aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore9
-rw-r--r--HOWTO/INSTALL-CROSS.md23
-rw-r--r--Makefile.in17
-rw-r--r--OTP_VERSION3
-rw-r--r--bootstrap/bin/start.bootbin5287 -> 5306 bytes
-rw-r--r--bootstrap/bin/start_clean.bootbin5287 -> 5306 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_a.beambin2700 -> 2684 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_asm.beambin11540 -> 11524 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_block.beambin14828 -> 9656 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_bool.beambin15732 -> 15652 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_bs.beambin0 -> 5928 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_bsm.beambin12756 -> 12636 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_clean.beambin9416 -> 8948 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_dead.beambin12156 -> 12972 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_dict.beambin5300 -> 5292 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_disasm.beambin26320 -> 26216 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_except.beambin3564 -> 3540 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_flatten.beambin3020 -> 2996 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_jump.beambin9448 -> 9372 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_listing.beambin2992 -> 2964 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_peep.beambin2780 -> 2424 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_receive.beambin6444 -> 6384 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_reorder.beambin0 -> 1992 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_split.beambin2416 -> 2396 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_trim.beambin7928 -> 7864 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_type.beambin14692 -> 17148 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_utils.beambin13620 -> 13756 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_validator.beambin30304 -> 29988 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_z.beambin2652 -> 2636 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl.beambin32376 -> 31940 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl_clauses.beambin2956 -> 2956 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl_inline.beambin38940 -> 38716 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl_sets.beambin2868 -> 2868 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl_trees.beambin20368 -> 20676 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/compile.beambin39368 -> 38704 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/compiler.app2
-rw-r--r--bootstrap/lib/compiler/ebin/core_lib.beambin5240 -> 4408 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_lint.beambin13656 -> 13580 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_parse.beambin50920 -> 50896 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_pp.beambin13252 -> 13148 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_scan.beambin6692 -> 6636 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/rec_env.beambin4772 -> 4920 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_dsetel.beambin7340 -> 7184 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_fold.beambin50072 -> 52236 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_fold_lists.beambin4596 -> 4596 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_inline.beambin4276 -> 4236 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_pre_attributes.beambin3348 -> 3308 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_pre_expand.beambin14940 -> 13472 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_codegen.beambin56616 -> 55864 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_core.beambin53748 -> 53740 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_kernel.beambin47352 -> 46880 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_kernel_pp.beambin12556 -> 12472 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_life.beambin19172 -> 19044 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application.beambin4620 -> 3852 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application_controller.beambin32152 -> 31932 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application_master.beambin6696 -> 6632 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application_starter.beambin1256 -> 1256 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/auth.beambin6552 -> 6516 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/code.beambin7196 -> 12140 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/code_server.beambin28824 -> 24740 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log.beambin36492 -> 35860 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log_1.beambin25252 -> 24876 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log_server.beambin6668 -> 6624 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/dist_ac.beambin26656 -> 26328 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/dist_util.beambin10568 -> 10352 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_boot_server.beambin6012 -> 5964 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_ddll.beambin2916 -> 2908 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_distribution.beambin1832 -> 1832 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_epmd.beambin7200 -> 7180 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_reply.beambin924 -> 920 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/error_handler.beambin1660 -> 1660 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/error_logger.beambin4480 -> 5932 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erts_debug.beambin5460 -> 5548 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file.beambin14556 -> 14460 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file_io_server.beambin15728 -> 15564 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file_server.beambin5436 -> 5408 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/gen_sctp.beambin3636 -> 3612 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/gen_tcp.beambin2416 -> 2404 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/gen_udp.beambin1632 -> 1616 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/global.beambin32764 -> 32252 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/global_group.beambin17740 -> 17568 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/group.beambin14160 -> 14040 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/heart.beambin5580 -> 5540 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/hipe_unified_loader.beambin13768 -> 13792 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet.beambin23420 -> 23320 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_sctp.beambin1556 -> 1536 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_tcp.beambin3044 -> 3032 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_udp.beambin1728 -> 1728 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_config.beambin7796 -> 7728 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_db.beambin27156 -> 27044 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_dns.beambin19764 -> 19596 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_gethost_native.beambin10500 -> 10436 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_hosts.beambin2144 -> 2140 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_parse.beambin12940 -> 12924 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_res.beambin14976 -> 14868 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_sctp.beambin2324 -> 2304 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_tcp.beambin2756 -> 2744 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_tcp_dist.beambin7224 -> 7184 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_udp.beambin1916 -> 1916 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/kernel.appup4
-rw-r--r--bootstrap/lib/kernel/ebin/kernel.beambin3796 -> 3632 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/kernel_config.beambin2768 -> 2764 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/net_adm.beambin3016 -> 3008 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/net_kernel.beambin22760 -> 22600 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/os.beambin5848 -> 3776 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/pg2.beambin7916 -> 7912 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/ram_file.beambin7044 -> 6996 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/rpc.beambin8616 -> 8580 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/seq_trace.beambin1444 -> 1440 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/standard_error.beambin3864 -> 3864 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user.beambin11588 -> 11572 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user_drv.beambin11488 -> 11412 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user_sup.beambin1764 -> 1752 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/wrap_log_reader.beambin3372 -> 3320 bytes
-rw-r--r--bootstrap/lib/kernel/include/file.hrl31
-rw-r--r--bootstrap/lib/stdlib/ebin/array.beambin12032 -> 12008 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/base64.beambin4544 -> 4540 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/beam_lib.beambin18644 -> 18612 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/binary.beambin3812 -> 2828 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/c.beambin14660 -> 14608 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/calendar.beambin5172 -> 5136 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets.beambin54048 -> 53688 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_server.beambin7028 -> 6988 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_utils.beambin28836 -> 28756 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_v8.beambin27632 -> 27488 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_v9.beambin50240 -> 49844 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dict.beambin9392 -> 9332 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/digraph.beambin8428 -> 8312 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/digraph_utils.beambin6844 -> 6824 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/edlin.beambin10248 -> 10184 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/edlin_expand.beambin3164 -> 3156 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/epp.beambin28220 -> 28212 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_anno.beambin4900 -> 4016 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_bits.beambin2552 -> 2528 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_compile.beambin7324 -> 7280 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_eval.beambin31000 -> 30640 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_expand_records.beambin22536 -> 21764 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_lint.beambin90024 -> 89756 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_parse.beambin84208 -> 82296 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_pp.beambin26912 -> 26796 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_scan.beambin31380 -> 28844 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_tar.beambin17256 -> 17156 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/error_logger_file_h.beambin4708 -> 4656 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/error_logger_tty_h.beambin4976 -> 4936 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/escript.beambin17676 -> 17592 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ets.beambin22720 -> 22604 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/eval_bits.beambin8136 -> 8096 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/file_sorter.beambin30708 -> 30408 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/filelib.beambin8088 -> 8056 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/filename.beambin12512 -> 14756 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gb_sets.beambin8432 -> 8396 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gb_trees.beambin5176 -> 5128 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen.beambin4296 -> 4276 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_event.beambin19624 -> 13524 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_fsm.beambin17412 -> 10476 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_server.beambin19596 -> 13744 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io.beambin6696 -> 6284 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib.beambin10008 -> 9984 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib_format.beambin13404 -> 13348 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib_fread.beambin7384 -> 7280 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib_pretty.beambin15224 -> 15156 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/lib.beambin9660 -> 9600 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/lists.beambin29768 -> 29768 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/log_mf_h.beambin2672 -> 2636 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/maps.beambin2408 -> 2404 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ms_transform.beambin20632 -> 20460 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/orddict.beambin2792 -> 2772 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/otp_internal.beambin11724 -> 11896 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/pool.beambin3848 -> 3836 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/proc_lib.beambin10692 -> 10656 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/proplists.beambin4948 -> 4944 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/qlc.beambin70684 -> 70148 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/qlc_pt.beambin76684 -> 76244 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/rand.beambin13568 -> 13560 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/random.beambin1712 -> 1736 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/re.beambin13672 -> 13600 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sets.beambin7096 -> 7060 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/shell.beambin30364 -> 30236 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/slave.beambin5200 -> 4852 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sofs.beambin40816 -> 40656 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/stdlib.appup4
-rw-r--r--bootstrap/lib/stdlib/ebin/supervisor.beambin24100 -> 23456 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/supervisor_bridge.beambin2908 -> 2072 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sys.beambin8620 -> 8564 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/timer.beambin5488 -> 5476 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/unicode.beambin11676 -> 11612 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/win32reg.beambin5632 -> 5600 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/zip.beambin26904 -> 26632 bytes
-rw-r--r--bootstrap/lib/stdlib/include/erl_bits.hrl10
-rw-r--r--configure.in8
-rw-r--r--erts/aclocal.m448
-rw-r--r--erts/configure.in164
-rw-r--r--erts/doc/src/absform.xml613
-rw-r--r--erts/doc/src/driver_entry.xml17
-rw-r--r--erts/doc/src/erl.xml15
-rw-r--r--erts/doc/src/erl_driver.xml53
-rw-r--r--erts/doc/src/erl_nif.xml2
-rw-r--r--erts/doc/src/erl_prim_loader.xml42
-rw-r--r--erts/doc/src/erlang.xml396
-rw-r--r--erts/doc/src/erts_alloc.xml15
-rw-r--r--erts/doc/src/init.xml5
-rw-r--r--erts/doc/src/run_erl.xml2
-rw-r--r--erts/emulator/Makefile.in65
-rw-r--r--erts/emulator/beam/atom.c5
-rw-r--r--erts/emulator/beam/atom.h1
-rw-r--r--erts/emulator/beam/atom.names29
-rw-r--r--erts/emulator/beam/beam_bif_load.c553
-rw-r--r--erts/emulator/beam/beam_bp.c32
-rw-r--r--erts/emulator/beam/beam_debug.c144
-rw-r--r--erts/emulator/beam/beam_emu.c1993
-rw-r--r--erts/emulator/beam/beam_load.c690
-rw-r--r--erts/emulator/beam/beam_load.h127
-rw-r--r--erts/emulator/beam/beam_ranges.c202
-rw-r--r--erts/emulator/beam/bif.c403
-rw-r--r--erts/emulator/beam/bif.h73
-rw-r--r--erts/emulator/beam/bif.tab19
-rw-r--r--erts/emulator/beam/big.c455
-rw-r--r--erts/emulator/beam/big.h23
-rw-r--r--erts/emulator/beam/binary.c81
-rw-r--r--erts/emulator/beam/break.c34
-rw-r--r--erts/emulator/beam/code_ix.c4
-rw-r--r--erts/emulator/beam/code_ix.h2
-rw-r--r--erts/emulator/beam/copy.c1399
-rw-r--r--erts/emulator/beam/dist.c72
-rw-r--r--erts/emulator/beam/erl_alloc.c302
-rw-r--r--erts/emulator/beam/erl_alloc.h52
-rw-r--r--erts/emulator/beam/erl_alloc.types58
-rw-r--r--erts/emulator/beam/erl_alloc_util.c360
-rw-r--r--erts/emulator/beam/erl_alloc_util.h69
-rw-r--r--erts/emulator/beam/erl_arith.c11
-rw-r--r--erts/emulator/beam/erl_async.c35
-rw-r--r--erts/emulator/beam/erl_bif_binary.c953
-rw-r--r--erts/emulator/beam/erl_bif_ddll.c17
-rw-r--r--erts/emulator/beam/erl_bif_info.c556
-rw-r--r--erts/emulator/beam/erl_bif_lists.c8
-rw-r--r--erts/emulator/beam/erl_bif_op.c14
-rw-r--r--erts/emulator/beam/erl_bif_port.c62
-rw-r--r--erts/emulator/beam/erl_bif_re.c4
-rw-r--r--erts/emulator/beam/erl_bif_trace.c26
-rw-r--r--erts/emulator/beam/erl_bif_unique.c6
-rw-r--r--erts/emulator/beam/erl_binary.h15
-rw-r--r--erts/emulator/beam/erl_bits.c4
-rw-r--r--erts/emulator/beam/erl_db.c17
-rw-r--r--erts/emulator/beam/erl_db_hash.c16
-rw-r--r--erts/emulator/beam/erl_db_tree.c238
-rw-r--r--erts/emulator/beam/erl_db_util.c377
-rw-r--r--erts/emulator/beam/erl_db_util.h15
-rw-r--r--erts/emulator/beam/erl_debug.c37
-rw-r--r--erts/emulator/beam/erl_debug.h7
-rw-r--r--erts/emulator/beam/erl_driver.h41
-rw-r--r--erts/emulator/beam/erl_fun.c3
-rw-r--r--erts/emulator/beam/erl_gc.c1467
-rw-r--r--erts/emulator/beam/erl_gc.h43
-rw-r--r--erts/emulator/beam/erl_hl_timer.c102
-rw-r--r--erts/emulator/beam/erl_init.c89
-rw-r--r--erts/emulator/beam/erl_lock_check.c8
-rw-r--r--erts/emulator/beam/erl_map.c124
-rw-r--r--erts/emulator/beam/erl_map.h19
-rw-r--r--erts/emulator/beam/erl_message.c1658
-rw-r--r--erts/emulator/beam/erl_message.h285
-rw-r--r--erts/emulator/beam/erl_msacc.c486
-rw-r--r--erts/emulator/beam/erl_msacc.h409
-rw-r--r--erts/emulator/beam/erl_nif.c57
-rw-r--r--erts/emulator/beam/erl_nif.h27
-rw-r--r--erts/emulator/beam/erl_node_container_utils.h4
-rw-r--r--erts/emulator/beam/erl_node_tables.c95
-rw-r--r--erts/emulator/beam/erl_node_tables.h3
-rw-r--r--erts/emulator/beam/erl_port.h12
-rw-r--r--erts/emulator/beam/erl_port_task.c5
-rw-r--r--erts/emulator/beam/erl_printf_term.c31
-rw-r--r--erts/emulator/beam/erl_printf_term.h3
-rw-r--r--erts/emulator/beam/erl_process.c3403
-rw-r--r--erts/emulator/beam/erl_process.h207
-rw-r--r--erts/emulator/beam/erl_process_dict.c255
-rw-r--r--erts/emulator/beam/erl_process_dict.h11
-rw-r--r--erts/emulator/beam/erl_process_dump.c31
-rw-r--r--erts/emulator/beam/erl_term.c37
-rw-r--r--erts/emulator/beam/erl_term.h237
-rw-r--r--erts/emulator/beam/erl_threads.h34
-rw-r--r--erts/emulator/beam/erl_time.h2
-rw-r--r--erts/emulator/beam/erl_time_sup.c21
-rw-r--r--erts/emulator/beam/erl_trace.c162
-rw-r--r--erts/emulator/beam/erl_utils.h69
-rw-r--r--erts/emulator/beam/erl_vm.h15
-rw-r--r--erts/emulator/beam/export.c3
-rw-r--r--erts/emulator/beam/external.c80
-rw-r--r--erts/emulator/beam/global.h401
-rw-r--r--erts/emulator/beam/hash.c142
-rw-r--r--erts/emulator/beam/hash.h31
-rw-r--r--erts/emulator/beam/index.h4
-rw-r--r--erts/emulator/beam/io.c366
-rw-r--r--erts/emulator/beam/module.c7
-rw-r--r--erts/emulator/beam/module.h3
-rw-r--r--erts/emulator/beam/ops.tab875
-rw-r--r--erts/emulator/beam/register.c3
-rw-r--r--erts/emulator/beam/sys.h127
-rw-r--r--erts/emulator/beam/time.c20
-rw-r--r--erts/emulator/beam/utils.c355
-rw-r--r--erts/emulator/drivers/common/efile_drv.c10
-rw-r--r--erts/emulator/drivers/common/inet_drv.c573
-rw-r--r--erts/emulator/drivers/ose/ose_efile.c1125
-rw-r--r--erts/emulator/drivers/ose/ose_signal_drv.c897
-rw-r--r--erts/emulator/drivers/ose/ttsl_drv.c69
-rw-r--r--erts/emulator/drivers/unix/ttsl_drv.c148
-rw-r--r--erts/emulator/drivers/unix/unix_efile.c2
-rw-r--r--erts/emulator/hipe/hipe_bif0.c24
-rw-r--r--erts/emulator/hipe/hipe_gc.c36
-rw-r--r--erts/emulator/hipe/hipe_mode_switch.c2
-rw-r--r--erts/emulator/hipe/hipe_mode_switch.h2
-rw-r--r--erts/emulator/hipe/hipe_native_bif.c36
-rw-r--r--erts/emulator/hipe/hipe_x86_signal.c201
-rw-r--r--erts/emulator/sys/common/erl_check_io.c24
-rw-r--r--erts/emulator/sys/common/erl_mmap.c582
-rw-r--r--erts/emulator/sys/common/erl_mmap.h32
-rw-r--r--erts/emulator/sys/common/erl_mseg.c390
-rw-r--r--erts/emulator/sys/common/erl_mseg.h19
-rw-r--r--erts/emulator/sys/common/erl_poll.c36
-rw-r--r--erts/emulator/sys/common/erl_poll.h22
-rw-r--r--erts/emulator/sys/ose/beam.lmconf26
-rw-r--r--erts/emulator/sys/ose/driver_int.h42
-rw-r--r--erts/emulator/sys/ose/erl_main.c54
-rw-r--r--erts/emulator/sys/ose/erl_ose_sys.h356
-rw-r--r--erts/emulator/sys/ose/erl_ose_sys_ddll.c127
-rw-r--r--erts/emulator/sys/ose/erl_poll.c818
-rw-r--r--erts/emulator/sys/ose/erts.sig17
-rw-r--r--erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf182
-rw-r--r--erts/emulator/sys/ose/gcc_4.6.3_lm_ppc.lcf242
-rw-r--r--erts/emulator/sys/ose/sys.c1847
-rw-r--r--erts/emulator/sys/ose/sys_float.c845
-rw-r--r--erts/emulator/sys/ose/sys_time.c57
-rw-r--r--erts/emulator/sys/unix/erl_child_setup.c560
-rw-r--r--erts/emulator/sys/unix/erl_child_setup.h77
-rw-r--r--erts/emulator/sys/unix/erl_unix_sys.h55
-rw-r--r--erts/emulator/sys/unix/sys.c1937
-rw-r--r--erts/emulator/sys/unix/sys_drivers.c1862
-rw-r--r--erts/emulator/sys/unix/sys_time.c114
-rw-r--r--erts/emulator/sys/unix/sys_uds.c155
-rw-r--r--erts/emulator/sys/unix/sys_uds.h57
-rw-r--r--erts/emulator/sys/win32/erl_poll.c4
-rw-r--r--erts/emulator/sys/win32/erl_win_sys.h14
-rw-r--r--erts/emulator/sys/win32/sys.c14
-rw-r--r--erts/emulator/sys/win32/sys_time.c1
-rw-r--r--erts/emulator/test/Makefile4
-rw-r--r--erts/emulator/test/a_SUITE.erl77
-rw-r--r--erts/emulator/test/after_SUITE.erl195
-rw-r--r--erts/emulator/test/alloc_SUITE.erl135
-rw-r--r--erts/emulator/test/alloc_SUITE_data/threads.c17
-rw-r--r--erts/emulator/test/async_ports_SUITE.erl39
-rw-r--r--erts/emulator/test/beam_SUITE.erl15
-rw-r--r--erts/emulator/test/beam_literals_SUITE.erl188
-rw-r--r--erts/emulator/test/bif_SUITE.erl379
-rw-r--r--erts/emulator/test/big_SUITE.erl150
-rw-r--r--erts/emulator/test/binary_SUITE.erl845
-rw-r--r--erts/emulator/test/bs_bincomp_SUITE.erl2
-rw-r--r--erts/emulator/test/bs_bit_binaries_SUITE.erl90
-rw-r--r--erts/emulator/test/bs_construct_SUITE.erl331
-rw-r--r--erts/emulator/test/bs_match_bin_SUITE.erl56
-rw-r--r--erts/emulator/test/bs_match_int_SUITE.erl96
-rw-r--r--erts/emulator/test/bs_match_misc_SUITE.erl232
-rw-r--r--erts/emulator/test/bs_match_tail_SUITE.erl77
-rw-r--r--erts/emulator/test/bs_utf_SUITE.erl110
-rw-r--r--erts/emulator/test/busy_port_SUITE.erl637
-rw-r--r--erts/emulator/test/call_trace_SUITE.erl1582
-rw-r--r--erts/emulator/test/code_SUITE.erl767
-rw-r--r--erts/emulator/test/code_SUITE_data/literals.erl7
-rw-r--r--erts/emulator/test/code_parallel_load_SUITE.erl49
-rw-r--r--erts/emulator/test/crypto_SUITE.erl399
-rw-r--r--erts/emulator/test/ddll_SUITE.erl1609
-rw-r--r--erts/emulator/test/decode_packet_SUITE.erl551
-rw-r--r--erts/emulator/test/distribution_SUITE.erl2683
-rw-r--r--erts/emulator/test/driver_SUITE.erl3136
-rw-r--r--erts/emulator/test/efile_SUITE.erl144
-rw-r--r--erts/emulator/test/emulator.spec.ose2
-rw-r--r--erts/emulator/test/erl_drv_thread_SUITE.erl120
-rw-r--r--erts/emulator/test/erl_link_SUITE.erl1523
-rw-r--r--erts/emulator/test/erts_debug_SUITE.erl81
-rw-r--r--erts/emulator/test/estone_SUITE.erl57
-rw-r--r--erts/emulator/test/evil_SUITE.erl466
-rw-r--r--erts/emulator/test/exception_SUITE.erl631
-rw-r--r--erts/emulator/test/float_SUITE.erl394
-rw-r--r--erts/emulator/test/float_SUITE_data/fp_drv.c1
-rw-r--r--erts/emulator/test/fun_SUITE.erl798
-rw-r--r--erts/emulator/test/fun_r13_SUITE.erl92
-rw-r--r--erts/emulator/test/gc_SUITE.erl49
-rw-r--r--erts/emulator/test/guard_SUITE.erl324
-rw-r--r--erts/emulator/test/hash_SUITE.erl88
-rw-r--r--erts/emulator/test/hibernate_SUITE.erl256
-rw-r--r--erts/emulator/test/ignore_cores.erl14
-rw-r--r--erts/emulator/test/list_bif_SUITE.erl169
-rw-r--r--erts/emulator/test/map_SUITE.erl297
-rw-r--r--erts/emulator/test/match_spec_SUITE.erl1171
-rw-r--r--erts/emulator/test/message_queue_data_SUITE.erl213
-rw-r--r--erts/emulator/test/module_info_SUITE.erl45
-rw-r--r--erts/emulator/test/monitor_SUITE.erl1092
-rw-r--r--erts/emulator/test/mtx_SUITE.erl404
-rw-r--r--erts/emulator/test/multi_load_SUITE.erl196
-rw-r--r--erts/emulator/test/nested_SUITE.erl96
-rw-r--r--erts/emulator/test/nif_SUITE.erl1265
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_SUITE.c6
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.erl4
-rw-r--r--erts/emulator/test/nif_SUITE_data/tester.erl5
-rw-r--r--erts/emulator/test/node_container_SUITE.erl1671
-rw-r--r--erts/emulator/test/nofrag_SUITE.erl106
-rw-r--r--erts/emulator/test/num_bif_SUITE.erl101
-rw-r--r--erts/emulator/test/old_mod.erl34
-rw-r--r--erts/emulator/test/old_scheduler_SUITE.erl349
-rw-r--r--erts/emulator/test/op_SUITE.erl294
-rw-r--r--erts/emulator/test/port_SUITE.erl2067
-rw-r--r--erts/emulator/test/port_SUITE_data/port_test.c35
-rw-r--r--erts/emulator/test/port_bif_SUITE.erl96
-rw-r--r--erts/emulator/test/process_SUITE.erl251
-rw-r--r--erts/emulator/test/random_iolist.erl16
-rw-r--r--erts/emulator/test/receive_SUITE.erl35
-rw-r--r--erts/emulator/test/ref_SUITE.erl51
-rw-r--r--erts/emulator/test/register_SUITE.erl62
-rw-r--r--erts/emulator/test/save_calls_SUITE.erl264
-rw-r--r--erts/emulator/test/scheduler_SUITE.erl1906
-rw-r--r--erts/emulator/test/scheduler_SUITE_data/Makefile.src8
-rw-r--r--erts/emulator/test/scheduler_SUITE_data/scheduler_SUITE.c31
-rw-r--r--erts/emulator/test/send_term_SUITE.erl180
-rw-r--r--erts/emulator/test/sensitive_SUITE.erl505
-rw-r--r--erts/emulator/test/signal_SUITE.erl438
-rw-r--r--erts/emulator/test/smoke_test_SUITE.erl48
-rw-r--r--erts/emulator/test/statistics_SUITE.erl537
-rw-r--r--erts/emulator/test/system_info_SUITE.erl239
-rw-r--r--erts/emulator/test/system_profile_SUITE.erl82
-rw-r--r--erts/emulator/test/time_SUITE.erl241
-rw-r--r--erts/emulator/test/timer_bif_SUITE.erl714
-rw-r--r--erts/emulator/test/trace_SUITE.erl2123
-rw-r--r--erts/emulator/test/trace_bif_SUITE.erl333
-rw-r--r--erts/emulator/test/trace_call_count_SUITE.erl314
-rw-r--r--erts/emulator/test/trace_call_time_SUITE.erl657
-rw-r--r--erts/emulator/test/trace_local_SUITE.erl1472
-rw-r--r--erts/emulator/test/trace_meta_SUITE.erl74
-rw-r--r--erts/emulator/test/trace_nif_SUITE.erl335
-rw-r--r--erts/emulator/test/trace_port_SUITE.erl819
-rw-r--r--erts/emulator/test/tuple_SUITE.erl10
-rw-r--r--erts/emulator/test/unique_SUITE.erl254
-rw-r--r--erts/emulator/test/z_SUITE.erl338
-rwxr-xr-xerts/emulator/utils/beam_makeops89
-rw-r--r--erts/emulator/valgrind/suppress.halfword56
-rw-r--r--erts/epmd/src/Makefile.in37
-rw-r--r--erts/epmd/src/epmd.c2
-rw-r--r--erts/epmd/src/epmd_int.h18
-rw-r--r--erts/epmd/src/epmd_srv.c7
-rw-r--r--erts/epmd/test/epmd_SUITE.erl2
-rw-r--r--erts/etc/common/Makefile.in83
-rw-r--r--erts/etc/common/erlexec.c24
-rw-r--r--erts/etc/common/run_erl_common.c696
-rw-r--r--erts/etc/common/run_erl_common.h97
-rw-r--r--erts/etc/common/to_erl_common.c717
-rw-r--r--erts/etc/common/to_erl_common.h29
-rw-r--r--erts/etc/ose/etc.lmconf20
-rw-r--r--erts/etc/ose/run_erl.c664
-rw-r--r--erts/etc/ose/run_erl.h30
-rw-r--r--erts/etc/ose/run_erl_main.c80
-rw-r--r--erts/etc/unix/etp-commands.in16
-rw-r--r--erts/etc/unix/run_erl.c610
-rw-r--r--erts/etc/unix/run_erl.h (renamed from erts/etc/common/run_erl_vsn.h)7
-rw-r--r--erts/etc/unix/safe_string.c (renamed from erts/etc/common/safe_string.c)11
-rw-r--r--erts/etc/unix/safe_string.h (renamed from erts/etc/common/safe_string.h)11
-rw-r--r--erts/etc/unix/to_erl.c591
-rw-r--r--erts/include/erl_int_sizes_config.h.in3
-rw-r--r--erts/include/internal/erl_printf_format.h11
-rw-r--r--erts/include/internal/ethr_internal.h1
-rw-r--r--erts/include/internal/ethr_mutex.h8
-rw-r--r--erts/include/internal/ethread.h143
-rw-r--r--erts/include/internal/ose/ethr_event.h114
-rw-r--r--erts/lib_src/common/erl_misc_utils.c6
-rw-r--r--erts/lib_src/common/erl_printf_format.c25
-rw-r--r--erts/lib_src/common/ethr_aux.c47
-rw-r--r--erts/lib_src/common/ethr_mutex.c2
-rw-r--r--erts/lib_src/ose/ethr_event.c220
-rw-r--r--erts/lib_src/ose/ethread.c833
-rw-r--r--erts/preloaded/ebin/erl_prim_loader.beambin56336 -> 55528 bytes
-rw-r--r--erts/preloaded/ebin/erlang.beambin102112 -> 102200 bytes
-rw-r--r--erts/preloaded/ebin/erts_code_purger.beambin0 -> 8704 bytes
-rw-r--r--erts/preloaded/ebin/erts_internal.beambin6500 -> 9976 bytes
-rw-r--r--erts/preloaded/ebin/init.beambin48764 -> 44588 bytes
-rw-r--r--erts/preloaded/ebin/otp_ring0.beambin1468 -> 1448 bytes
-rw-r--r--erts/preloaded/ebin/prim_eval.beambin1340 -> 1320 bytes
-rw-r--r--erts/preloaded/ebin/prim_file.beambin45004 -> 44800 bytes
-rw-r--r--erts/preloaded/ebin/prim_inet.beambin72716 -> 72608 bytes
-rw-r--r--erts/preloaded/ebin/prim_zip.beambin23424 -> 23156 bytes
-rw-r--r--erts/preloaded/ebin/zlib.beambin14176 -> 14156 bytes
-rw-r--r--erts/preloaded/src/Makefile1
-rw-r--r--erts/preloaded/src/erl_prim_loader.erl539
-rw-r--r--erts/preloaded/src/erlang.erl150
-rw-r--r--erts/preloaded/src/erts.app.src1
-rw-r--r--erts/preloaded/src/erts_code_purger.erl299
-rw-r--r--erts/preloaded/src/erts_internal.erl150
-rw-r--r--erts/preloaded/src/init.erl401
-rw-r--r--erts/test/Makefile2
-rw-r--r--erts/test/erl_print_SUITE.erl2
-rw-r--r--erts/test/erlc_SUITE.erl2
-rw-r--r--erts/test/erlexec_SUITE.erl2
-rw-r--r--erts/test/ethread_SUITE.erl34
-rw-r--r--erts/test/ignore_cores.erl2
-rw-r--r--erts/test/install_SUITE.erl2
-rw-r--r--erts/test/nt_SUITE.erl2
-rw-r--r--erts/test/otp_SUITE.erl59
-rw-r--r--erts/test/run_erl_SUITE.erl20
-rw-r--r--erts/vsn.mk4
-rw-r--r--lib/Makefile7
-rw-r--r--lib/asn1/c_src/Makefile7
-rw-r--r--lib/asn1/src/asn1ct_value.erl5
-rw-r--r--lib/asn1/test/asn1_SUITE.erl2
-rw-r--r--lib/asn1/test/asn1_SUITE_data/test_records.erl3
-rw-r--r--lib/asn1/test/asn1_test_lib.erl2
-rw-r--r--lib/asn1/test/error_SUITE.erl2
-rw-r--r--lib/asn1/test/h323test.erl2
-rw-r--r--lib/asn1/test/syntax_SUITE.erl2
-rw-r--r--lib/asn1/test/testChoExtension.erl2
-rw-r--r--lib/asn1/test/testChoExternal.erl2
-rw-r--r--lib/asn1/test/testChoPrim.erl2
-rw-r--r--lib/asn1/test/testChoRecursive.erl2
-rw-r--r--lib/asn1/test/testChoTypeRefCho.erl2
-rw-r--r--lib/asn1/test/testChoTypeRefPrim.erl2
-rw-r--r--lib/asn1/test/testChoTypeRefSeq.erl2
-rw-r--r--lib/asn1/test/testChoTypeRefSet.erl2
-rw-r--r--lib/asn1/test/testChoiceIndefinite.erl2
-rw-r--r--lib/asn1/test/testConstraints.erl2
-rw-r--r--lib/asn1/test/testContextSwitchingTypes.erl2
-rw-r--r--lib/asn1/test/testDER.erl2
-rw-r--r--lib/asn1/test/testDeepTConstr.erl2
-rw-r--r--lib/asn1/test/testDef.erl2
-rw-r--r--lib/asn1/test/testDoubleEllipses.erl2
-rw-r--r--lib/asn1/test/testEnumExt.erl2
-rw-r--r--lib/asn1/test/testINSTANCE_OF.erl2
-rw-r--r--lib/asn1/test/testInfObjectClass.erl2
-rw-r--r--lib/asn1/test/testMegaco.erl2
-rw-r--r--lib/asn1/test/testMergeCompile.erl2
-rw-r--r--lib/asn1/test/testNBAPsystem.erl2
-rw-r--r--lib/asn1/test/testOpenTypeImplicitTag.erl2
-rw-r--r--lib/asn1/test/testOpt.erl2
-rw-r--r--lib/asn1/test/testParamBasic.erl2
-rw-r--r--lib/asn1/test/testParameterizedInfObj.erl2
-rw-r--r--lib/asn1/test/testPrim.erl2
-rw-r--r--lib/asn1/test/testPrimExternal.erl2
-rw-r--r--lib/asn1/test/testPrimStrings.erl4
-rw-r--r--lib/asn1/test/testRfcs.erl2
-rw-r--r--lib/asn1/test/testSSLspecs.erl2
-rw-r--r--lib/asn1/test/testSelectionTypes.erl2
-rw-r--r--lib/asn1/test/testSeq2738.erl2
-rw-r--r--lib/asn1/test/testSeqDefault.erl2
-rw-r--r--lib/asn1/test/testSeqExtension.erl2
-rw-r--r--lib/asn1/test/testSeqExternal.erl2
-rw-r--r--lib/asn1/test/testSeqOf.erl2
-rw-r--r--lib/asn1/test/testSeqOfCho.erl2
-rw-r--r--lib/asn1/test/testSeqOfExternal.erl2
-rw-r--r--lib/asn1/test/testSeqOfIndefinite.erl2
-rw-r--r--lib/asn1/test/testSeqOfTag.erl2
-rw-r--r--lib/asn1/test/testSeqOptional.erl2
-rw-r--r--lib/asn1/test/testSeqPrim.erl2
-rw-r--r--lib/asn1/test/testSeqSetDefaultVal.erl2
-rw-r--r--lib/asn1/test/testSeqSetIndefinite.erl2
-rw-r--r--lib/asn1/test/testSeqTag.erl2
-rw-r--r--lib/asn1/test/testSeqTypeRefCho.erl2
-rw-r--r--lib/asn1/test/testSeqTypeRefPrim.erl2
-rw-r--r--lib/asn1/test/testSeqTypeRefSeq.erl2
-rw-r--r--lib/asn1/test/testSeqTypeRefSet.erl2
-rw-r--r--lib/asn1/test/testSetDefault.erl2
-rw-r--r--lib/asn1/test/testSetExtension.erl2
-rw-r--r--lib/asn1/test/testSetExternal.erl2
-rw-r--r--lib/asn1/test/testSetOf.erl2
-rw-r--r--lib/asn1/test/testSetOfCho.erl2
-rw-r--r--lib/asn1/test/testSetOfExternal.erl2
-rw-r--r--lib/asn1/test/testSetOfTag.erl2
-rw-r--r--lib/asn1/test/testSetPrim.erl2
-rw-r--r--lib/asn1/test/testSetTag.erl2
-rw-r--r--lib/asn1/test/testSetTypeRefCho.erl2
-rw-r--r--lib/asn1/test/testSetTypeRefPrim.erl2
-rw-r--r--lib/asn1/test/testSetTypeRefSeq.erl2
-rw-r--r--lib/asn1/test/testSetTypeRefSet.erl2
-rw-r--r--lib/asn1/test/testTCAP.erl2
-rw-r--r--lib/asn1/test/testTimer.erl2
-rw-r--r--lib/asn1/test/test_compile_options.erl2
-rw-r--r--lib/asn1/test/test_modified_x420.erl2
-rw-r--r--lib/asn1/test/test_partial_incomplete_decode.erl2
-rw-r--r--lib/asn1/test/test_selective_decode.erl2
-rw-r--r--lib/asn1/test/test_special_decode_performance.erl2
-rw-r--r--lib/asn1/test/test_undecoded_rest.erl2
-rw-r--r--lib/asn1/test/test_x691.erl2
-rw-r--r--lib/common_test/include/ct.hrl8
-rw-r--r--lib/common_test/src/Makefile13
-rw-r--r--lib/common_test/src/common_test.app.src36
-rw-r--r--lib/common_test/src/ct_config.erl3
-rw-r--r--lib/common_test/src/ct_make.erl7
-rw-r--r--lib/common_test/src/ct_release_test.erl2
-rw-r--r--lib/common_test/src/ct_run.erl4
-rw-r--r--lib/common_test/src/erl2html2.erl (renamed from lib/test_server/src/erl2html2.erl)31
-rw-r--r--lib/common_test/src/test_server.erl (renamed from lib/test_server/src/test_server.erl)0
-rw-r--r--lib/common_test/src/test_server_ctrl.erl (renamed from lib/test_server/src/test_server_ctrl.erl)14
-rw-r--r--lib/common_test/src/test_server_gl.erl (renamed from lib/test_server/src/test_server_gl.erl)4
-rw-r--r--lib/common_test/src/test_server_internal.hrl (renamed from lib/test_server/src/test_server_internal.hrl)0
-rw-r--r--lib/common_test/src/test_server_io.erl (renamed from lib/test_server/src/test_server_io.erl)0
-rw-r--r--lib/common_test/src/test_server_node.erl (renamed from lib/test_server/src/test_server_node.erl)3
-rw-r--r--lib/common_test/src/test_server_sup.erl (renamed from lib/test_server/src/test_server_sup.erl)0
-rw-r--r--lib/common_test/test/Makefile10
-rw-r--r--lib/common_test/test/common_test.cover7
-rw-r--r--lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl2
-rw-r--r--lib/common_test/test/ct_hooks_SUITE.erl2
-rw-r--r--lib/common_test/test/ct_master_SUITE.erl2
-rw-r--r--lib/common_test/test/ct_misc_1_SUITE.erl1
-rw-r--r--lib/common_test/test/ct_test_support.erl8
-rw-r--r--lib/common_test/test/ct_test_support_eh.erl2
-rw-r--r--lib/common_test/test/erl2html2_SUITE.erl (renamed from lib/test_server/test/erl2html2_SUITE.erl)0
-rw-r--r--lib/common_test/test/erl2html2_SUITE_data/Makefile.src (renamed from lib/test_server/test/erl2html2_SUITE_data/Makefile.src)0
-rw-r--r--lib/common_test/test/erl2html2_SUITE_data/header1.hrl (renamed from lib/test_server/test/erl2html2_SUITE_data/header1.hrl)0
-rw-r--r--lib/common_test/test/erl2html2_SUITE_data/include/header2.hrl (renamed from lib/test_server/test/erl2html2_SUITE_data/include/header2.hrl)0
-rw-r--r--lib/common_test/test/erl2html2_SUITE_data/include/header3.hrl (renamed from lib/test_server/test/erl2html2_SUITE_data/include/header3.hrl)0
-rw-r--r--lib/common_test/test/erl2html2_SUITE_data/m1.erl (renamed from lib/test_server/test/erl2html2_SUITE_data/m1.erl)0
-rw-r--r--lib/common_test/test/test_server_SUITE.erl (renamed from lib/test_server/test/test_server_SUITE.erl)4
-rw-r--r--lib/common_test/test/test_server_SUITE_data/Makefile.src (renamed from lib/test_server/test/test_server_SUITE_data/Makefile.src)0
-rw-r--r--lib/common_test/test/test_server_SUITE_data/test_server_SUITE.erl (renamed from lib/test_server/test/test_server_SUITE_data/test_server_SUITE.erl)3
-rw-r--r--lib/common_test/test/test_server_SUITE_data/test_server_SUITE_data/dummy_file (renamed from lib/test_server/test/test_server_SUITE_data/test_server_SUITE_data/dummy_file)0
-rw-r--r--lib/common_test/test/test_server_SUITE_data/test_server_break_SUITE.erl (renamed from lib/test_server/test/test_server_SUITE_data/test_server_break_SUITE.erl)2
-rw-r--r--lib/common_test/test/test_server_SUITE_data/test_server_conf01_SUITE.erl (renamed from lib/test_server/test/test_server_SUITE_data/test_server_conf01_SUITE.erl)2
-rw-r--r--lib/common_test/test/test_server_SUITE_data/test_server_conf02_SUITE.erl (renamed from lib/test_server/test/test_server_SUITE_data/test_server_conf02_SUITE.erl)2
-rw-r--r--lib/common_test/test/test_server_SUITE_data/test_server_cover_SUITE.erl (renamed from lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE.erl)2
-rw-r--r--lib/common_test/test/test_server_SUITE_data/test_server_cover_SUITE_data/cover_helper.erl (renamed from lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE_data/cover_helper.erl)0
-rw-r--r--lib/common_test/test/test_server_SUITE_data/test_server_parallel01_SUITE.erl (renamed from lib/test_server/test/test_server_SUITE_data/test_server_parallel01_SUITE.erl)2
-rw-r--r--lib/common_test/test/test_server_SUITE_data/test_server_shuffle01_SUITE.erl (renamed from lib/test_server/test/test_server_SUITE_data/test_server_shuffle01_SUITE.erl)21
-rw-r--r--lib/common_test/test/test_server_SUITE_data/test_server_skip_SUITE.erl (renamed from lib/test_server/test/test_server_SUITE_data/test_server_skip_SUITE.erl)3
-rw-r--r--lib/common_test/test/test_server_SUITE_data/test_server_unicode_SUITE.erl (renamed from lib/test_server/test/test_server_SUITE_data/test_server_unicode_SUITE.erl)2
-rw-r--r--lib/common_test/test/test_server_test_lib.erl (renamed from lib/test_server/test/test_server_test_lib.erl)0
-rw-r--r--lib/common_test/test/test_server_test_lib.hrl (renamed from lib/test_server/test/test_server_test_lib.hrl)0
-rw-r--r--lib/common_test/test_server/Makefile (renamed from lib/webtool/src/Makefile)82
-rw-r--r--lib/common_test/test_server/conf_vars.in (renamed from lib/test_server/src/conf_vars.in)0
-rw-r--r--lib/common_test/test_server/configure.in (renamed from lib/test_server/src/configure.in)0
-rw-r--r--lib/common_test/test_server/cross.cover (renamed from lib/test_server/src/cross.cover)0
-rw-r--r--lib/common_test/test_server/ts.config (renamed from lib/test_server/src/ts.config)0
-rw-r--r--lib/common_test/test_server/ts.erl (renamed from lib/test_server/src/ts.erl)0
-rw-r--r--lib/common_test/test_server/ts.hrl (renamed from lib/test_server/src/ts.hrl)0
-rw-r--r--lib/common_test/test_server/ts.unix.config (renamed from lib/test_server/src/ts.unix.config)0
-rw-r--r--lib/common_test/test_server/ts.win32.config (renamed from lib/test_server/src/ts.win32.config)0
-rw-r--r--lib/common_test/test_server/ts_autoconf_win32.erl (renamed from lib/test_server/src/ts_autoconf_win32.erl)0
-rw-r--r--lib/common_test/test_server/ts_benchmark.erl (renamed from lib/test_server/src/ts_benchmark.erl)0
-rw-r--r--lib/common_test/test_server/ts_erl_config.erl (renamed from lib/test_server/src/ts_erl_config.erl)0
-rw-r--r--lib/common_test/test_server/ts_install.erl (renamed from lib/test_server/src/ts_install.erl)0
-rw-r--r--lib/common_test/test_server/ts_install_cth.erl (renamed from lib/test_server/src/ts_install_cth.erl)0
-rw-r--r--lib/common_test/test_server/ts_lib.erl (renamed from lib/test_server/src/ts_lib.erl)0
-rw-r--r--lib/common_test/test_server/ts_make.erl (renamed from lib/test_server/src/ts_make.erl)2
-rw-r--r--lib/common_test/test_server/ts_run.erl (renamed from lib/test_server/src/ts_run.erl)0
-rw-r--r--lib/compiler/src/Makefile2
-rw-r--r--lib/compiler/src/beam_asm.erl5
-rw-r--r--lib/compiler/src/beam_block.erl494
-rw-r--r--lib/compiler/src/beam_bool.erl2
-rw-r--r--lib/compiler/src/beam_bs.erl278
-rw-r--r--lib/compiler/src/beam_clean.erl22
-rw-r--r--lib/compiler/src/beam_dead.erl57
-rw-r--r--lib/compiler/src/beam_dict.erl11
-rw-r--r--lib/compiler/src/beam_jump.erl2
-rw-r--r--lib/compiler/src/beam_peep.erl44
-rw-r--r--lib/compiler/src/beam_reorder.erl139
-rw-r--r--lib/compiler/src/beam_split.erl4
-rw-r--r--lib/compiler/src/beam_type.erl156
-rw-r--r--lib/compiler/src/beam_utils.erl9
-rw-r--r--lib/compiler/src/beam_validator.erl57
-rw-r--r--lib/compiler/src/cerl_trees.erl223
-rw-r--r--lib/compiler/src/compile.erl39
-rw-r--r--lib/compiler/src/compiler.app.src2
-rw-r--r--lib/compiler/src/core_lib.erl38
-rw-r--r--lib/compiler/src/core_lint.erl4
-rw-r--r--lib/compiler/src/rec_env.erl11
-rw-r--r--lib/compiler/src/sys_core_dsetel.erl36
-rw-r--r--lib/compiler/src/sys_core_fold.erl250
-rw-r--r--lib/compiler/src/sys_pre_expand.erl179
-rw-r--r--lib/compiler/src/v3_codegen.erl25
-rw-r--r--lib/compiler/src/v3_core.erl93
-rw-r--r--lib/compiler/src/v3_kernel.erl21
-rw-r--r--lib/compiler/test/Makefile9
-rw-r--r--lib/compiler/test/andor_SUITE.erl328
-rw-r--r--lib/compiler/test/apply_SUITE.erl102
-rw-r--r--lib/compiler/test/beam_block_SUITE.erl66
-rw-r--r--lib/compiler/test/beam_disasm_SUITE.erl25
-rw-r--r--lib/compiler/test/beam_reorder_SUITE.erl69
-rw-r--r--lib/compiler/test/beam_type_SUITE.erl98
-rw-r--r--lib/compiler/test/beam_validator_SUITE.erl226
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/xrange.S4
-rw-r--r--lib/compiler/test/bs_bincomp_SUITE.erl248
-rw-r--r--lib/compiler/test/bs_bit_binaries_SUITE.erl94
-rw-r--r--lib/compiler/test/bs_construct_SUITE.erl197
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl636
-rw-r--r--lib/compiler/test/bs_utf_SUITE.erl150
-rw-r--r--lib/compiler/test/compilation_SUITE.erl260
-rw-r--r--lib/compiler/test/compile_SUITE.erl550
-rw-r--r--lib/compiler/test/compile_SUITE_data/bad_record_use.erl29
-rw-r--r--lib/compiler/test/compile_SUITE_data/bad_record_use2.erl30
-rw-r--r--lib/compiler/test/core_SUITE.erl14
-rw-r--r--lib/compiler/test/core_fold_SUITE.erl124
-rw-r--r--lib/compiler/test/error_SUITE.erl121
-rw-r--r--lib/compiler/test/float_SUITE.erl98
-rw-r--r--lib/compiler/test/fun_SUITE.erl19
-rw-r--r--lib/compiler/test/guard_SUITE.erl1337
-rw-r--r--lib/compiler/test/inline_SUITE.erl183
-rw-r--r--lib/compiler/test/lc_SUITE.erl13
-rw-r--r--lib/compiler/test/map_SUITE.erl28
-rw-r--r--lib/compiler/test/match_SUITE.erl149
-rw-r--r--lib/compiler/test/misc_SUITE.erl143
-rw-r--r--lib/compiler/test/num_bif_SUITE.erl266
-rw-r--r--lib/compiler/test/receive_SUITE.erl39
-rw-r--r--lib/compiler/test/record_SUITE.erl391
-rw-r--r--lib/compiler/test/regressions_SUITE.erl27
-rw-r--r--lib/compiler/test/test_lib.erl13
-rw-r--r--lib/compiler/test/trycatch_SUITE.erl486
-rw-r--r--lib/compiler/test/warnings_SUITE.erl142
-rw-r--r--lib/cosEvent/test/Makefile4
-rw-r--r--lib/cosEvent/test/event_channel_SUITE.erl2
-rw-r--r--lib/cosEvent/test/generated_SUITE.erl2
-rw-r--r--lib/cosEventDomain/test/Makefile4
-rw-r--r--lib/cosEventDomain/test/event_domain_SUITE.erl2
-rw-r--r--lib/cosEventDomain/test/generated_SUITE.erl2
-rw-r--r--lib/cosFileTransfer/test/Makefile4
-rw-r--r--lib/cosFileTransfer/test/fileTransfer_SUITE.erl2
-rw-r--r--lib/cosNotification/test/Makefile4
-rw-r--r--lib/cosNotification/test/eventDB_SUITE.erl2
-rw-r--r--lib/cosNotification/test/generated_SUITE.erl2
-rw-r--r--lib/cosNotification/test/grammar_SUITE.erl2
-rw-r--r--lib/cosNotification/test/notification_SUITE.erl2
-rw-r--r--lib/cosProperty/test/Makefile4
-rw-r--r--lib/cosProperty/test/generated_SUITE.erl2
-rw-r--r--lib/cosProperty/test/property_SUITE.erl2
-rw-r--r--lib/cosTime/test/Makefile4
-rw-r--r--lib/cosTime/test/generated_SUITE.erl2
-rw-r--r--lib/cosTime/test/time_SUITE.erl2
-rw-r--r--lib/cosTransactions/test/Makefile4
-rw-r--r--lib/cosTransactions/test/generated_SUITE.erl2
-rw-r--r--lib/cosTransactions/test/transactions_SUITE.erl2
-rw-r--r--lib/crypto/Makefile4
-rw-r--r--lib/crypto/c_src/Makefile.in7
-rw-r--r--lib/crypto/c_src/crypto.c2779
-rw-r--r--lib/crypto/c_src/crypto_callback.c8
-rw-r--r--lib/crypto/doc/src/crypto.xml10
-rw-r--r--lib/crypto/src/crypto.erl855
-rw-r--r--lib/crypto/test/Makefile2
-rw-r--r--lib/crypto/test/blowfish_SUITE.erl3
-rw-r--r--lib/crypto/test/crypto_SUITE.erl90
-rw-r--r--lib/crypto/test/old_crypto_SUITE.erl2
-rw-r--r--lib/debugger/src/dbg_iload.erl4
-rw-r--r--lib/debugger/src/dbg_wx_win.erl7
-rw-r--r--lib/debugger/src/int.erl18
-rw-r--r--lib/debugger/test/Makefile2
-rw-r--r--lib/debugger/test/andor_SUITE.erl2
-rw-r--r--lib/debugger/test/bs_bincomp_SUITE.erl2
-rw-r--r--lib/debugger/test/bs_construct_SUITE.erl2
-rw-r--r--lib/debugger/test/bs_match_bin_SUITE.erl2
-rw-r--r--lib/debugger/test/bs_match_int_SUITE.erl2
-rw-r--r--lib/debugger/test/bs_match_misc_SUITE.erl2
-rw-r--r--lib/debugger/test/bs_match_tail_SUITE.erl2
-rw-r--r--lib/debugger/test/bs_utf_SUITE.erl2
-rw-r--r--lib/debugger/test/bug_SUITE.erl2
-rw-r--r--lib/debugger/test/cleanup.erl2
-rw-r--r--lib/debugger/test/dbg_ui_SUITE.erl2
-rw-r--r--lib/debugger/test/debugger_SUITE.erl2
-rw-r--r--lib/debugger/test/erl_eval_SUITE.erl2
-rw-r--r--lib/debugger/test/exception_SUITE.erl2
-rw-r--r--lib/debugger/test/fun_SUITE.erl2
-rw-r--r--lib/debugger/test/guard_SUITE.erl2
-rw-r--r--lib/debugger/test/int_SUITE.erl20
-rw-r--r--lib/debugger/test/int_break_SUITE.erl2
-rw-r--r--lib/debugger/test/int_eval_SUITE.erl2
-rw-r--r--lib/debugger/test/lc_SUITE.erl2
-rw-r--r--lib/debugger/test/line_number_SUITE.erl2
-rw-r--r--lib/debugger/test/map_SUITE.erl22
-rw-r--r--lib/debugger/test/record_SUITE.erl2
-rw-r--r--lib/debugger/test/trycatch_SUITE.erl2
-rw-r--r--lib/dialyzer/doc/src/dialyzer.xml2
-rw-r--r--lib/dialyzer/src/Makefile2
-rw-r--r--lib/dialyzer/src/dialyzer.app.src3
-rw-r--r--lib/dialyzer/src/dialyzer.hrl10
-rw-r--r--lib/dialyzer/src/dialyzer_analysis_callgraph.erl45
-rw-r--r--lib/dialyzer/src/dialyzer_callgraph.erl130
-rw-r--r--lib/dialyzer/src/dialyzer_cl.erl2
-rw-r--r--lib/dialyzer/src/dialyzer_codeserver.erl10
-rw-r--r--lib/dialyzer/src/dialyzer_contracts.erl23
-rw-r--r--lib/dialyzer/src/dialyzer_coordinator.erl40
-rw-r--r--lib/dialyzer/src/dialyzer_dataflow.erl28
-rw-r--r--lib/dialyzer/src/dialyzer_gui_wx.erl9
-rw-r--r--lib/dialyzer/src/dialyzer_race_data_server.erl134
-rw-r--r--lib/dialyzer/src/dialyzer_races.erl40
-rw-r--r--lib/dialyzer/src/dialyzer_succ_typings.erl3
-rw-r--r--lib/dialyzer/src/dialyzer_typesig.erl37
-rw-r--r--lib/dialyzer/src/dialyzer_utils.erl15
-rw-r--r--lib/dialyzer/src/dialyzer_worker.erl61
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs6
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/supervisor_incorrect_return2
-rw-r--r--lib/dialyzer/test/dialyzer_SUITE.erl2
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/crash10
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/simple6
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl3
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/results/mnesia4
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/app_call2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/bif13
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes36
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes22
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/literals12
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/maps12
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/record_creation_diffs2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/record_pat2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/relevant_record_warning2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/undefined2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/bif1/bif1.erl16
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/bif1/bif1_adt.erl12
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl6
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl6
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/trec.erl2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/undefined.erl29
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/wsp_pdu2
-rw-r--r--lib/diameter/src/base/diameter_peer_fsm.erl2
-rw-r--r--lib/diameter/src/base/diameter_service.erl2
-rw-r--r--lib/diameter/src/transport/diameter_sctp.erl12
-rw-r--r--lib/diameter/src/transport/diameter_tcp.erl2
-rw-r--r--lib/edoc/test/Makefile2
-rw-r--r--lib/edoc/test/edoc_SUITE.erl2
-rw-r--r--lib/eldap/src/eldap.erl9
-rw-r--r--lib/eldap/test/eldap_basic_SUITE.erl2
-rw-r--r--lib/erl_docgen/priv/css/otp_doc.css4
-rw-r--r--lib/erl_docgen/test/Makefile2
-rw-r--r--lib/erl_interface/src/Makefile.in63
-rw-r--r--lib/erl_interface/test/ei_accept_SUITE.erl2
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE.erl2
-rw-r--r--lib/erl_interface/test/ei_decode_SUITE.erl2
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE.erl2
-rw-r--r--lib/erl_interface/test/ei_encode_SUITE.erl2
-rw-r--r--lib/erl_interface/test/ei_format_SUITE.erl2
-rw-r--r--lib/erl_interface/test/ei_print_SUITE.erl2
-rw-r--r--lib/erl_interface/test/ei_tmo_SUITE.erl2
-rw-r--r--lib/erl_interface/test/erl_connect_SUITE.erl2
-rw-r--r--lib/erl_interface/test/erl_eterm_SUITE.erl2
-rw-r--r--lib/erl_interface/test/erl_ext_SUITE.erl2
-rw-r--r--lib/erl_interface/test/erl_format_SUITE.erl2
-rw-r--r--lib/erl_interface/test/erl_global_SUITE.erl2
-rw-r--r--lib/erl_interface/test/erl_match_SUITE.erl2
-rw-r--r--lib/erl_interface/test/port_call_SUITE.erl2
-rw-r--r--lib/eunit/src/eunit_surefire.erl6
-rw-r--r--lib/eunit/test/Makefile4
-rw-r--r--lib/gs/Makefile2
-rw-r--r--lib/gs/contribs/Makefile32
-rw-r--r--lib/gs/contribs/bonk/Makefile109
-rw-r--r--lib/gs/contribs/bonk/bitmaps/bonkbomb66
-rw-r--r--lib/gs/contribs/bonk/bitmaps/bonkface66
-rw-r--r--lib/gs/contribs/bonk/bitmaps/bonklogo320
-rw-r--r--lib/gs/contribs/bonk/bitmaps/bonkmiss66
-rw-r--r--lib/gs/contribs/bonk/bitmaps/bonktom66
-rw-r--r--lib/gs/contribs/bonk/bitmaps/bonkx66
-rw-r--r--lib/gs/contribs/bonk/bitmaps/erl-e106
-rw-r--r--lib/gs/contribs/bonk/bitmaps/erl-text106
-rw-r--r--lib/gs/contribs/bonk/bonk.erl584
-rw-r--r--lib/gs/contribs/bonk/bonk.gifbin196 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/bonk.tool6
-rw-r--r--lib/gs/contribs/bonk/bonk.txt30
-rw-r--r--lib/gs/contribs/bonk/bonk_sound.erl82
-rw-r--r--lib/gs/contribs/bonk/bonk_square.erl146
-rw-r--r--lib/gs/contribs/bonk/sounder.erl160
-rw-r--r--lib/gs/contribs/bonk/sounds/bonk.aubin2008 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/damn.aubin3744 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/explosion.aubin7708 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/gameover.aubin5986 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/hehee.aubin3772 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/level.aubin5360 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/missedme.aubin2735 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/music.aubin48072 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/ouch!!!.aubin2342 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/praisejesus.aubin16730 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/trumpet.aubin49332 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/yes.aubin4400 -> 0 bytes
-rw-r--r--lib/gs/contribs/cols/Makefile103
-rw-r--r--lib/gs/contribs/cols/cols.erl625
-rw-r--r--lib/gs/contribs/cols/cols.gifbin185 -> 0 bytes
-rw-r--r--lib/gs/contribs/cols/cols.tool5
-rw-r--r--lib/gs/contribs/cols/help.gifbin172 -> 0 bytes
-rw-r--r--lib/gs/contribs/cols/highscore.erl103
-rw-r--r--lib/gs/contribs/mandel/Makefile101
-rw-r--r--lib/gs/contribs/mandel/mandel.erl351
-rw-r--r--lib/gs/contribs/mandel/mandel.gifbin394 -> 0 bytes
-rw-r--r--lib/gs/contribs/mandel/mandel.html74
-rw-r--r--lib/gs/contribs/mandel/mandel.tool6
-rw-r--r--lib/gs/contribs/othello/Makefile101
-rw-r--r--lib/gs/contribs/othello/othello.erl237
-rw-r--r--lib/gs/contribs/othello/othello.gifbin148 -> 0 bytes
-rw-r--r--lib/gs/contribs/othello/othello.tool6
-rw-r--r--lib/gs/contribs/othello/othello_adt.erl540
-rw-r--r--lib/gs/contribs/othello/othello_board.erl649
-rw-r--r--lib/gs/contribs/othello/priv/marker.bm43
-rw-r--r--lib/gs/contribs/othello/priv/square.bm43
-rw-r--r--lib/gs/test/Makefile2
-rw-r--r--lib/hipe/cerl/cerl_cconv.erl13
-rw-r--r--lib/hipe/cerl/cerl_hipeify.erl12
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl94
-rw-r--r--lib/hipe/cerl/erl_types.erl139
-rw-r--r--lib/hipe/flow/cfg.hrl8
-rw-r--r--lib/hipe/icode/hipe_icode.erl42
-rw-r--r--lib/hipe/icode/hipe_icode.hrl3
-rw-r--r--lib/hipe/icode/hipe_icode_exceptions.erl20
-rw-r--r--lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl6
-rw-r--r--lib/hipe/main/hipe.erl5
-rw-r--r--lib/hipe/main/hipe.hrl.src5
-rw-r--r--lib/hipe/main/hipe_main.erl16
-rw-r--r--lib/hipe/test/Makefile2
-rw-r--r--lib/hipe/test/bs_SUITE_data/bs_utf.erl2
-rw-r--r--lib/ic/test/Makefile4
-rw-r--r--lib/ic/test/ic_SUITE.erl2
-rw-r--r--lib/ic/test/ic_be_SUITE.erl2
-rw-r--r--lib/ic/test/ic_pp_SUITE.erl2
-rw-r--r--lib/ic/test/ic_pragma_SUITE.erl2
-rw-r--r--lib/ic/test/ic_register_SUITE.erl2
-rw-r--r--lib/ic/test/java_client_erl_server_SUITE.erl2
-rw-r--r--lib/inets/src/tftp/tftp_engine.erl5
-rw-r--r--lib/inets/test/Makefile2
-rw-r--r--lib/inets/test/ftp_format_SUITE.erl1
-rw-r--r--lib/inets/test/ftp_suite_lib.erl3
-rw-r--r--lib/inets/test/httpc_cookie_SUITE.erl2
-rw-r--r--lib/inets/test/httpd_load.erl3
-rw-r--r--lib/inets/test/httpd_mod.erl3
-rw-r--r--lib/inets/test/old_httpd_SUITE.erl3
-rw-r--r--lib/jinterface/test/jinterface_SUITE.erl1
-rw-r--r--lib/jinterface/test/nc_SUITE.erl1
-rw-r--r--lib/kernel/doc/src/code.xml172
-rw-r--r--lib/kernel/doc/src/notes.xml3
-rw-r--r--lib/kernel/doc/src/os.xml25
-rw-r--r--lib/kernel/doc/src/ref_man.xml.src68
-rw-r--r--lib/kernel/doc/src/seq_trace.xml2
-rw-r--r--lib/kernel/include/file.hrl31
-rw-r--r--lib/kernel/src/code.erl438
-rw-r--r--lib/kernel/src/code_server.erl694
-rw-r--r--lib/kernel/src/disk_log.erl68
-rw-r--r--lib/kernel/src/disk_log.hrl6
-rw-r--r--lib/kernel/src/erl_distribution.erl90
-rw-r--r--lib/kernel/src/error_logger.erl81
-rw-r--r--lib/kernel/src/erts_debug.erl17
-rw-r--r--lib/kernel/src/global.erl40
-rw-r--r--lib/kernel/src/global_group.erl4
-rw-r--r--lib/kernel/src/hipe_unified_loader.erl28
-rw-r--r--lib/kernel/src/inet_config.erl3
-rw-r--r--lib/kernel/src/kernel.app.src2
-rw-r--r--lib/kernel/src/kernel.appup.src8
-rw-r--r--lib/kernel/src/kernel.erl8
-rw-r--r--lib/kernel/src/net_kernel.erl131
-rw-r--r--lib/kernel/src/os.erl209
-rw-r--r--lib/kernel/src/rpc.erl8
-rw-r--r--lib/kernel/test/Makefile5
-rw-r--r--lib/kernel/test/application_SUITE.erl544
-rw-r--r--lib/kernel/test/bif_SUITE.erl809
-rw-r--r--lib/kernel/test/cleanup.erl23
-rw-r--r--lib/kernel/test/code_SUITE.erl473
-rw-r--r--lib/kernel/test/disk_log_SUITE.erl5956
-rw-r--r--lib/kernel/test/erl_boot_server_SUITE.erl318
-rw-r--r--lib/kernel/test/erl_distribution_SUITE.erl1284
-rw-r--r--lib/kernel/test/erl_distribution_wb_SUITE.erl453
-rw-r--r--lib/kernel/test/erl_prim_loader_SUITE.erl530
-rw-r--r--lib/kernel/test/error_handler_SUITE.erl4
-rw-r--r--lib/kernel/test/error_logger_SUITE.erl160
-rw-r--r--lib/kernel/test/error_logger_warn_SUITE.erl64
-rw-r--r--lib/kernel/test/file_SUITE.erl3926
-rw-r--r--lib/kernel/test/file_name_SUITE.erl533
-rw-r--r--lib/kernel/test/gen_sctp_SUITE.erl1761
-rw-r--r--lib/kernel/test/gen_tcp_api_SUITE.erl335
-rw-r--r--lib/kernel/test/gen_tcp_echo_SUITE.erl487
-rw-r--r--lib/kernel/test/gen_tcp_misc_SUITE.erl449
-rw-r--r--lib/kernel/test/gen_udp_SUITE.erl439
-rw-r--r--lib/kernel/test/global_SUITE.erl3314
-rw-r--r--lib/kernel/test/global_group_SUITE.erl1453
-rw-r--r--lib/kernel/test/heart_SUITE.erl101
-rw-r--r--lib/kernel/test/ignore_cores.erl14
-rw-r--r--lib/kernel/test/inet_SUITE.erl622
-rw-r--r--lib/kernel/test/inet_res_SUITE.erl47
-rw-r--r--lib/kernel/test/inet_sockopt_SUITE.erl806
-rw-r--r--lib/kernel/test/init_SUITE.erl566
-rw-r--r--lib/kernel/test/interactive_shell_SUITE.erl460
-rw-r--r--lib/kernel/test/kernel_SUITE.erl26
-rw-r--r--lib/kernel/test/kernel_config_SUITE.erl46
-rw-r--r--lib/kernel/test/multi_load_SUITE.erl419
-rw-r--r--lib/kernel/test/os_SUITE.erl306
-rw-r--r--lib/kernel/test/pdict_SUITE.erl95
-rw-r--r--lib/kernel/test/pg2_SUITE.erl244
-rw-r--r--lib/kernel/test/prim_file_SUITE.erl1989
-rw-r--r--lib/kernel/test/ram_file_SUITE.erl758
-rw-r--r--lib/kernel/test/rpc_SUITE.erl575
-rw-r--r--lib/kernel/test/sendfile_SUITE.erl2
-rw-r--r--lib/kernel/test/seq_trace_SUITE.erl448
-rw-r--r--lib/kernel/test/wrap_log_reader_SUITE.erl415
-rw-r--r--lib/kernel/test/zlib_SUITE.erl524
-rw-r--r--lib/megaco/test/Makefile5
-rw-r--r--lib/mnesia/src/mnesia_lib.erl15
-rw-r--r--lib/mnesia/test/mnesia_consistency_test.erl2
-rw-r--r--lib/observer/src/observer_alloc_wx.erl140
-rw-r--r--lib/observer/src/observer_app_wx.erl47
-rw-r--r--lib/observer/src/observer_defs.hrl11
-rw-r--r--lib/observer/src/observer_perf_wx.erl730
-rw-r--r--lib/observer/test/Makefile6
-rw-r--r--lib/observer/test/crashdump_helper.erl2
-rw-r--r--lib/observer/test/crashdump_viewer_SUITE.erl1
-rw-r--r--lib/observer/test/etop_SUITE.erl2
-rw-r--r--lib/observer/test/observer_SUITE.erl2
-rw-r--r--lib/observer/test/ttb_SUITE.erl2
-rw-r--r--lib/odbc/test/Makefile2
-rw-r--r--lib/odbc/test/odbc_connect_SUITE.erl1
-rw-r--r--lib/odbc/test/odbc_data_type_SUITE.erl1
-rw-r--r--lib/odbc/test/odbc_query_SUITE.erl1
-rw-r--r--lib/odbc/test/odbc_start_SUITE.erl1
-rw-r--r--lib/odbc/test/odbc_test_lib.erl2
-rw-r--r--lib/orber/test/Makefile4
-rw-r--r--lib/orber/test/cdrcoding_10_SUITE.erl2
-rw-r--r--lib/orber/test/cdrcoding_11_SUITE.erl2
-rw-r--r--lib/orber/test/cdrcoding_12_SUITE.erl2
-rw-r--r--lib/orber/test/cdrlib_SUITE.erl2
-rw-r--r--lib/orber/test/corba_SUITE.erl2
-rw-r--r--lib/orber/test/csiv2_SUITE.erl2
-rw-r--r--lib/orber/test/data_types_SUITE.erl2
-rw-r--r--lib/orber/test/generated_SUITE.erl2
-rw-r--r--lib/orber/test/interceptors_SUITE.erl2
-rw-r--r--lib/orber/test/iop_ior_10_SUITE.erl2
-rw-r--r--lib/orber/test/iop_ior_11_SUITE.erl2
-rw-r--r--lib/orber/test/iop_ior_12_SUITE.erl2
-rw-r--r--lib/orber/test/ip_v4v6_interop_SUITE.erl2
-rw-r--r--lib/orber/test/lname_SUITE.erl2
-rw-r--r--lib/orber/test/multi_ORB_SUITE.erl2
-rw-r--r--lib/orber/test/naming_context_SUITE.erl2
-rw-r--r--lib/orber/test/orber_SUITE.erl2
-rw-r--r--lib/orber/test/orber_acl_SUITE.erl2
-rw-r--r--lib/orber/test/orber_firewall_ipv4_in_SUITE.erl2
-rw-r--r--lib/orber/test/orber_firewall_ipv4_out_SUITE.erl2
-rw-r--r--lib/orber/test/orber_firewall_ipv6_in_SUITE.erl2
-rw-r--r--lib/orber/test/orber_firewall_ipv6_out_SUITE.erl2
-rw-r--r--lib/orber/test/orber_nat_SUITE.erl2
-rw-r--r--lib/orber/test/orber_test_lib.erl2
-rw-r--r--lib/orber/test/orber_web_SUITE.erl2
-rw-r--r--lib/orber/test/tc_SUITE.erl2
-rw-r--r--lib/os_mon/test/Makefile3
-rw-r--r--lib/os_mon/test/cpu_sup_SUITE.erl2
-rw-r--r--lib/os_mon/test/disksup_SUITE.erl2
-rw-r--r--lib/os_mon/test/memsup_SUITE.erl2
-rw-r--r--lib/os_mon/test/os_mon_SUITE.erl2
-rw-r--r--lib/os_mon/test/os_mon_mib_SUITE.erl2
-rw-r--r--lib/os_mon/test/os_sup_SUITE.erl2
-rw-r--r--lib/ose/Makefile37
-rw-r--r--lib/ose/doc/html/.gitignore0
-rw-r--r--lib/ose/doc/man3/.gitignore0
-rw-r--r--lib/ose/doc/man6/.gitignore0
-rw-r--r--lib/ose/doc/pdf/.gitignore0
-rw-r--r--lib/ose/doc/src/.gitignore1
-rw-r--r--lib/ose/doc/src/Makefile133
-rw-r--r--lib/ose/doc/src/book.xml49
-rw-r--r--lib/ose/doc/src/notes.xml109
-rw-r--r--lib/ose/doc/src/ose_app.xml38
-rw-r--r--lib/ose/doc/src/ose_erl_driver.xml111
-rw-r--r--lib/ose/doc/src/ose_intro.xml154
-rw-r--r--lib/ose/doc/src/ose_signals_chapter.xml240
-rw-r--r--lib/ose/doc/src/part.xml39
-rw-r--r--lib/ose/doc/src/ref_man.xml40
-rw-r--r--lib/ose/ebin/.gitignore0
-rw-r--r--lib/ose/include/.gitignore0
-rw-r--r--lib/ose/info2
-rw-r--r--lib/ose/src/Makefile107
-rw-r--r--lib/ose/src/ose.app.src28
-rw-r--r--lib/ose/src/ose.appup.src23
-rw-r--r--lib/ose/src/ose.erl453
-rw-r--r--lib/ose/test/Makefile67
-rw-r--r--lib/ose/test/ose.cover2
-rw-r--r--lib/ose/test/ose.spec1
-rw-r--r--lib/ose/test/ose_SUITE.erl766
-rw-r--r--lib/ose/vsn.mk1
-rw-r--r--lib/otp_mibs/test/Makefile1
-rw-r--r--lib/otp_mibs/test/otp_mibs_SUITE.erl2
-rw-r--r--lib/parsetools/test/Makefile2
-rw-r--r--lib/parsetools/test/leex_SUITE.erl2
-rw-r--r--lib/parsetools/test/yecc_SUITE.erl2
-rw-r--r--lib/percept/test/Makefile3
-rw-r--r--lib/percept/test/egd_SUITE.erl6
-rw-r--r--lib/percept/test/percept_SUITE.erl2
-rw-r--r--lib/percept/test/percept_db_SUITE.erl2
-rw-r--r--lib/reltool/src/reltool.hrl46
-rw-r--r--lib/reltool/src/reltool_fgraph_win.erl4
-rw-r--r--lib/runtime_tools/c_src/Makefile.in7
-rw-r--r--lib/runtime_tools/doc/src/Makefile2
-rw-r--r--lib/runtime_tools/doc/src/msacc.xml305
-rw-r--r--lib/runtime_tools/doc/src/ref_man.xml1
-rw-r--r--lib/runtime_tools/doc/src/specs.xml1
-rw-r--r--lib/runtime_tools/src/Makefile4
-rw-r--r--lib/runtime_tools/src/msacc.erl355
-rw-r--r--lib/runtime_tools/src/runtime_tools.app.src3
-rw-r--r--lib/runtime_tools/test/Makefile5
-rw-r--r--lib/runtime_tools/test/dbg_SUITE.erl2
-rw-r--r--lib/runtime_tools/test/dyntrace_SUITE.erl2
-rw-r--r--lib/runtime_tools/test/erts_alloc_config_SUITE.erl2
-rw-r--r--lib/runtime_tools/test/msacc_SUITE.erl132
-rw-r--r--lib/runtime_tools/test/runtime_tools_SUITE.erl2
-rw-r--r--lib/sasl/doc/src/Makefile1
-rw-r--r--lib/sasl/doc/src/overload.xml152
-rw-r--r--lib/sasl/doc/src/ref_man.xml1
-rw-r--r--lib/sasl/doc/src/sasl_app.xml17
-rw-r--r--lib/sasl/doc/src/sasl_intro.xml1
-rw-r--r--lib/sasl/src/Makefile2
-rw-r--r--lib/sasl/src/misc_supp.erl2
-rw-r--r--lib/sasl/src/overload.erl233
-rw-r--r--lib/sasl/src/sasl.app.src3
-rw-r--r--lib/sasl/src/sasl.appup.src8
-rw-r--r--lib/sasl/src/sasl.erl5
-rw-r--r--lib/sasl/src/systools_make.erl4
-rw-r--r--lib/sasl/test/Makefile4
-rw-r--r--lib/sasl/test/overload_SUITE.erl168
-rw-r--r--lib/sasl/test/sasl_report_SUITE.erl2
-rw-r--r--lib/sasl/test/systools_SUITE.erl5
-rw-r--r--lib/sasl/test/systools_rc_SUITE.erl4
-rw-r--r--lib/snmp/test/Makefile1
-rw-r--r--lib/snmp/test/exp/snmp_agent_ms_test.erl2
-rw-r--r--lib/snmp/test/exp/snmp_agent_mt_test.erl2
-rw-r--r--lib/snmp/test/exp/snmp_agent_v1_test.erl2
-rw-r--r--lib/snmp/test/exp/snmp_agent_v2_test.erl2
-rw-r--r--lib/snmp/test/exp/snmp_agent_v3_test.erl2
-rw-r--r--lib/snmp/test/snmp_agent_mibs_test.erl2
-rw-r--r--lib/snmp/test/snmp_agent_nfilter_test.erl2
-rw-r--r--lib/snmp/test/snmp_agent_test.erl2
-rw-r--r--lib/snmp/test/snmp_agent_test_lib.erl2
-rw-r--r--lib/snmp/test/snmp_app_test.erl2
-rw-r--r--lib/snmp/test/snmp_compiler_test.erl2
-rw-r--r--lib/snmp/test/snmp_conf_test.erl2
-rw-r--r--lib/snmp/test/snmp_log_test.erl2
-rw-r--r--lib/snmp/test/snmp_manager_config_test.erl2
-rw-r--r--lib/snmp/test/snmp_manager_test.erl2
-rw-r--r--lib/snmp/test/snmp_manager_user.erl2
-rw-r--r--lib/snmp/test/snmp_manager_user_old.erl2
-rw-r--r--lib/snmp/test/snmp_manager_user_test.erl2
-rw-r--r--lib/snmp/test/snmp_manager_user_test_lib.erl2
-rw-r--r--lib/ssh/src/ssh_bits.erl141
-rw-r--r--lib/ssh/src/ssh_connect.hrl5
-rw-r--r--lib/ssh/src/ssh_message.erl169
-rw-r--r--lib/ssh/src/ssh_sftp.erl28
-rw-r--r--lib/ssh/src/ssh_transport.erl48
-rw-r--r--lib/ssh/src/ssh_xfer.erl26
-rw-r--r--lib/ssh/test/Makefile6
-rw-r--r--lib/ssh/test/ssh_protocol_SUITE.erl2
-rw-r--r--lib/ssl/doc/src/ssl_app.xml6
-rw-r--r--lib/ssl/src/ssl_cipher.erl18
-rw-r--r--lib/ssl/src/ssl_connection.hrl23
-rw-r--r--lib/ssl/src/ssl_internal.hrl14
-rw-r--r--lib/ssl/src/ssl_v3.erl4
-rw-r--r--lib/ssl/src/tls_v1.erl4
-rw-r--r--lib/ssl/test/Makefile5
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl40
-rw-r--r--lib/ssl/test/ssl_test_lib.erl4
-rw-r--r--lib/ssl/test/ssl_upgrade_SUITE.erl25
-rw-r--r--lib/stdlib/doc/src/erl_parse.xml120
-rw-r--r--lib/stdlib/doc/src/erl_scan.xml185
-rw-r--r--lib/stdlib/doc/src/filename.xml156
-rw-r--r--lib/stdlib/examples/erl_id_trans.erl151
-rw-r--r--lib/stdlib/include/erl_bits.hrl10
-rw-r--r--lib/stdlib/src/beam_lib.erl14
-rw-r--r--lib/stdlib/src/binary.erl77
-rw-r--r--lib/stdlib/src/dets.erl16
-rw-r--r--lib/stdlib/src/epp.erl486
-rw-r--r--lib/stdlib/src/erl_anno.erl96
-rw-r--r--lib/stdlib/src/erl_expand_records.erl36
-rw-r--r--lib/stdlib/src/erl_lint.erl84
-rw-r--r--lib/stdlib/src/erl_parse.yrl502
-rw-r--r--lib/stdlib/src/erl_scan.erl267
-rw-r--r--lib/stdlib/src/escript.erl8
-rw-r--r--lib/stdlib/src/file_sorter.erl22
-rw-r--r--lib/stdlib/src/filename.erl160
-rw-r--r--lib/stdlib/src/io.erl45
-rw-r--r--lib/stdlib/src/ms_transform.erl13
-rw-r--r--lib/stdlib/src/otp_internal.erl57
-rw-r--r--lib/stdlib/src/qlc.erl14
-rw-r--r--lib/stdlib/src/qlc_pt.erl40
-rw-r--r--lib/stdlib/src/random.erl1
-rw-r--r--lib/stdlib/src/shell.erl8
-rw-r--r--lib/stdlib/src/slave.erl23
-rw-r--r--lib/stdlib/src/stdlib.appup.src8
-rw-r--r--lib/stdlib/src/supervisor.erl74
-rw-r--r--lib/stdlib/test/Makefile3
-rw-r--r--lib/stdlib/test/array_SUITE.erl79
-rw-r--r--lib/stdlib/test/base64_SUITE.erl59
-rw-r--r--lib/stdlib/test/beam_lib_SUITE.erl741
-rw-r--r--lib/stdlib/test/binary_module_SUITE.erl1283
-rw-r--r--lib/stdlib/test/binref.erl8
-rw-r--r--lib/stdlib/test/c_SUITE.erl183
-rw-r--r--lib/stdlib/test/calendar_SUITE.erl237
-rw-r--r--lib/stdlib/test/dets_SUITE.erl430
-rw-r--r--lib/stdlib/test/dict_SUITE.erl29
-rw-r--r--lib/stdlib/test/digraph_SUITE.erl404
-rw-r--r--lib/stdlib/test/digraph_utils_SUITE.erl329
-rw-r--r--lib/stdlib/test/dummy1_h.erl2
-rw-r--r--lib/stdlib/test/dummy_via.erl2
-rw-r--r--lib/stdlib/test/edlin_expand_SUITE.erl36
-rw-r--r--lib/stdlib/test/epp_SUITE.erl631
-rw-r--r--lib/stdlib/test/erl_anno_SUITE.erl125
-rw-r--r--lib/stdlib/test/erl_eval_SUITE.erl1012
-rw-r--r--lib/stdlib/test/erl_expand_records_SUITE.erl143
-rw-r--r--lib/stdlib/test/erl_internal_SUITE.erl19
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl469
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl345
-rw-r--r--lib/stdlib/test/erl_scan_SUITE.erl793
-rw-r--r--lib/stdlib/test/error_logger_h_SUITE.erl12
-rw-r--r--lib/stdlib/test/escript_SUITE.erl685
-rw-r--r--lib/stdlib/test/ets_SUITE.erl4792
-rw-r--r--lib/stdlib/test/ets_tough_SUITE.erl69
-rw-r--r--lib/stdlib/test/file_sorter_SUITE.erl1365
-rw-r--r--lib/stdlib/test/filelib_SUITE.erl238
-rw-r--r--lib/stdlib/test/filename_SUITE.erl1125
-rw-r--r--lib/stdlib/test/fixtable_SUITE.erl493
-rw-r--r--lib/stdlib/test/format_SUITE.erl26
-rw-r--r--lib/stdlib/test/gen_event_SUITE.erl1232
-rw-r--r--lib/stdlib/test/gen_fsm_SUITE.erl425
-rw-r--r--lib/stdlib/test/gen_server_SUITE.erl895
-rw-r--r--lib/stdlib/test/id_transform_SUITE.erl23
-rw-r--r--lib/stdlib/test/io_SUITE.erl1697
-rw-r--r--lib/stdlib/test/io_proto_SUITE.erl1463
-rw-r--r--lib/stdlib/test/lists_SUITE.erl2327
-rw-r--r--lib/stdlib/test/log_mf_h_SUITE.erl49
-rw-r--r--lib/stdlib/test/maps_SUITE.erl22
-rw-r--r--lib/stdlib/test/ms_transform_SUITE.erl587
-rw-r--r--lib/stdlib/test/proc_lib_SUITE.erl102
-rw-r--r--lib/stdlib/test/qlc_SUITE.erl615
-rw-r--r--lib/stdlib/test/queue_SUITE.erl444
-rw-r--r--lib/stdlib/test/rand_SUITE.erl61
-rw-r--r--lib/stdlib/test/random_SUITE.erl102
-rw-r--r--lib/stdlib/test/random_iolist.erl16
-rw-r--r--lib/stdlib/test/random_unicode_list.erl18
-rw-r--r--lib/stdlib/test/re_SUITE.erl604
-rw-r--r--lib/stdlib/test/run_pcre_tests.erl47
-rw-r--r--lib/stdlib/test/select_SUITE.erl488
-rw-r--r--lib/stdlib/test/sets_SUITE.erl35
-rw-r--r--lib/stdlib/test/shell_SUITE.erl3302
-rw-r--r--lib/stdlib/test/slave_SUITE.erl178
-rw-r--r--lib/stdlib/test/sofs_SUITE.erl2987
-rw-r--r--lib/stdlib/test/stdlib_SUITE.erl21
-rw-r--r--lib/stdlib/test/string_SUITE.erl564
-rw-r--r--lib/stdlib/test/supervisor_SUITE.erl64
-rw-r--r--lib/stdlib/test/supervisor_bridge_SUITE.erl85
-rw-r--r--lib/stdlib/test/sys_SUITE.erl94
-rw-r--r--lib/stdlib/test/tar_SUITE.erl619
-rw-r--r--lib/stdlib/test/timer_SUITE.erl75
-rw-r--r--lib/stdlib/test/timer_simple_SUITE.erl333
-rw-r--r--lib/stdlib/test/unicode_SUITE.erl708
-rw-r--r--lib/stdlib/test/win32reg_SUITE.erl23
-rw-r--r--lib/stdlib/test/y2k_SUITE.erl157
-rw-r--r--lib/stdlib/test/zip_SUITE.erl175
-rw-r--r--lib/syntax_tools/src/erl_recomment.erl5
-rw-r--r--lib/syntax_tools/src/erl_syntax.erl2
-rw-r--r--lib/syntax_tools/src/erl_syntax_lib.erl12
-rw-r--r--lib/syntax_tools/src/erl_tidy.erl10
-rw-r--r--lib/syntax_tools/src/igor.erl5
-rw-r--r--lib/syntax_tools/src/merl.erl22
-rw-r--r--lib/syntax_tools/src/merl_transform.erl16
-rw-r--r--lib/syntax_tools/test/Makefile2
-rw-r--r--lib/syntax_tools/test/merl_SUITE.erl2
-rw-r--r--lib/syntax_tools/test/syntax_tools_SUITE.erl2
-rw-r--r--lib/test_server/AUTHORS12
-rw-r--r--lib/test_server/Makefile39
-rw-r--r--lib/test_server/README113
-rw-r--r--lib/test_server/doc/html/.gitignore0
-rw-r--r--lib/test_server/doc/man3/.gitignore0
-rw-r--r--lib/test_server/doc/man6/.gitignore0
-rw-r--r--lib/test_server/doc/pdf/.gitignore0
-rw-r--r--lib/test_server/doc/src/Makefile140
-rw-r--r--lib/test_server/doc/src/basics_chapter.xml215
-rw-r--r--lib/test_server/doc/src/book.xml50
-rw-r--r--lib/test_server/doc/src/example_chapter.xml151
-rw-r--r--lib/test_server/doc/src/fascicules.xml18
-rw-r--r--lib/test_server/doc/src/notes.xml1715
-rw-r--r--lib/test_server/doc/src/notes_history.xml113
-rw-r--r--lib/test_server/doc/src/part.xml46
-rw-r--r--lib/test_server/doc/src/part_notes.xml41
-rw-r--r--lib/test_server/doc/src/part_notes_history.xml39
-rw-r--r--lib/test_server/doc/src/ref_man.xml44
-rw-r--r--lib/test_server/doc/src/run_test_chapter.xml50
-rw-r--r--lib/test_server/doc/src/test_server.xml853
-rw-r--r--lib/test_server/doc/src/test_server_app.xml75
-rw-r--r--lib/test_server/doc/src/test_server_ctrl.xml844
-rw-r--r--lib/test_server/doc/src/test_spec_chapter.xml375
-rw-r--r--lib/test_server/doc/src/ts.xml568
-rw-r--r--lib/test_server/doc/src/why_test_chapter.xml141
-rw-r--r--lib/test_server/doc/src/write_framework_chapter.xml160
-rw-r--r--lib/test_server/doc/src/write_test_chapter.xml228
-rw-r--r--lib/test_server/ebin/.gitignore0
-rw-r--r--lib/test_server/include/test_server.hrl32
-rw-r--r--lib/test_server/include/test_server_line.hrl20
-rw-r--r--lib/test_server/info2
-rw-r--r--lib/test_server/prebuild.skip1
-rw-r--r--lib/test_server/src/Makefile144
-rw-r--r--lib/test_server/src/test_server.app.src39
-rw-r--r--lib/test_server/src/test_server.appup.src22
-rw-r--r--lib/test_server/src/things/distr_startup_SUITE.erl239
-rw-r--r--lib/test_server/src/things/mnesia_power_SUITE.erl126
-rw-r--r--lib/test_server/src/things/random_kill_SUITE.erl82
-rw-r--r--lib/test_server/src/things/soft.gs.txt16
-rw-r--r--lib/test_server/src/things/verify.erl200
-rw-r--r--lib/test_server/test/Makefile92
-rw-r--r--lib/test_server/test/test_server.cover1
-rw-r--r--lib/test_server/test/test_server.spec1
-rw-r--r--lib/test_server/vsn.mk1
-rw-r--r--lib/tools/Makefile2
-rw-r--r--lib/tools/c_src/Makefile.in8
-rw-r--r--lib/tools/doc/src/cover_chapter.xml43
-rw-r--r--lib/tools/emacs/erlang-skels-old.el2
-rw-r--r--lib/tools/emacs/erlang-skels.el2
-rw-r--r--lib/tools/emacs/erlang.el1
-rw-r--r--lib/tools/priv/.gitignore (renamed from lib/gs/contribs/ebin/.gitignore)0
-rw-r--r--lib/tools/priv/Makefile69
-rw-r--r--lib/tools/priv/cover.tool2
-rw-r--r--lib/tools/priv/index.html10
-rw-r--r--lib/tools/src/Makefile1
-rw-r--r--lib/tools/src/cover.erl8
-rw-r--r--lib/tools/src/cover_web.erl1185
-rw-r--r--lib/tools/src/lcnt.erl8
-rw-r--r--lib/tools/src/make.erl7
-rw-r--r--lib/tools/src/tools.app.src5
-rw-r--r--lib/tools/test/Makefile3
-rw-r--r--lib/tools/test/cover_SUITE.erl31
-rw-r--r--lib/tools/test/cover_SUITE_data/d.erl2
-rw-r--r--lib/tools/test/cprof_SUITE.erl2
-rw-r--r--lib/tools/test/emem_SUITE.erl2
-rw-r--r--lib/tools/test/eprof_SUITE.erl2
-rw-r--r--lib/tools/test/fprof_SUITE.erl2
-rw-r--r--lib/tools/test/ignore_cores.erl2
-rw-r--r--lib/tools/test/instrument_SUITE.erl2
-rw-r--r--lib/tools/test/lcnt_SUITE.erl2
-rw-r--r--lib/tools/test/make_SUITE.erl2
-rw-r--r--lib/tools/test/tools_SUITE.erl2
-rw-r--r--lib/tools/test/xref_SUITE.erl30
-rw-r--r--lib/typer/src/typer.erl12
-rw-r--r--lib/typer/test/Makefile2
-rw-r--r--lib/webtool/AUTHORS4
-rw-r--r--lib/webtool/Makefile39
-rw-r--r--lib/webtool/doc/html/.gitignore0
-rw-r--r--lib/webtool/doc/man1/.gitignore0
-rw-r--r--lib/webtool/doc/man3/.gitignore0
-rw-r--r--lib/webtool/doc/pdf/.gitignore0
-rw-r--r--lib/webtool/doc/src/Makefile132
-rw-r--r--lib/webtool/doc/src/book.xml48
-rw-r--r--lib/webtool/doc/src/fascicules.xml18
-rw-r--r--lib/webtool/doc/src/notes.xml269
-rw-r--r--lib/webtool/doc/src/notes_history.xml74
-rw-r--r--lib/webtool/doc/src/part.xml38
-rw-r--r--lib/webtool/doc/src/part_notes.xml40
-rw-r--r--lib/webtool/doc/src/part_notes_history.xml40
-rw-r--r--lib/webtool/doc/src/ref_man.xml39
-rw-r--r--lib/webtool/doc/src/start_webtool.xml104
-rw-r--r--lib/webtool/doc/src/webtool.xml157
-rw-r--r--lib/webtool/doc/src/webtool_chapter.xml246
-rw-r--r--lib/webtool/ebin/.gitignore0
-rw-r--r--lib/webtool/info2
-rw-r--r--lib/webtool/priv/Makefile82
-rwxr-xr-xlib/webtool/priv/bin/start_webtool3
-rw-r--r--lib/webtool/priv/bin/start_webtool.bat2
-rw-r--r--lib/webtool/priv/root/conf/mime.types99
-rw-r--r--lib/webtool/priv/root/doc/index.html11
-rw-r--r--lib/webtool/priv/root/doc/start_info.html28
-rw-r--r--lib/webtool/priv/root/doc/tool_management.html9
-rw-r--r--lib/webtool/src/webtool.app.src28
-rw-r--r--lib/webtool/src/webtool.appup.src22
-rw-r--r--lib/webtool/src/webtool.erl1207
-rw-r--r--lib/webtool/src/webtool_sup.erl75
-rw-r--r--lib/webtool/test/Makefile65
-rw-r--r--lib/webtool/test/webtool.spec1
-rw-r--r--lib/webtool/test/webtool_SUITE.erl51
-rw-r--r--lib/webtool/vsn.mk1
-rw-r--r--lib/wx/examples/demo/ex_canvas.erl2
-rw-r--r--lib/wx/examples/sudoku/sudoku_game.erl7
-rw-r--r--lib/xmerl/test/Makefile2
-rw-r--r--lib/xmerl/test/xmerl_SUITE.erl2
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl2
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_lib.erl2
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_text.erl2
-rw-r--r--lib/xmerl/test/xmerl_sax_SUITE.erl2
-rw-r--r--lib/xmerl/test/xmerl_sax_std_SUITE.erl2
-rw-r--r--lib/xmerl/test/xmerl_std_SUITE.erl2
-rw-r--r--lib/xmerl/test/xmerl_test_lib.erl2
-rw-r--r--lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE.erl2
-rw-r--r--lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE.erl2
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE.erl2
-rw-r--r--lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE.erl2
-rw-r--r--lib/xmerl/test/xmerl_xsd_lib.erl2
-rw-r--r--make/ose_lm.mk.in76
-rw-r--r--make/otp.mk.in10
-rwxr-xr-xotp_build4
-rw-r--r--system/doc/reference_manual/expressions.xml28
-rw-r--r--system/doc/reference_manual/macros.xml4
-rw-r--r--system/doc/reference_manual/typespec.xml23
-rw-r--r--xcomp/erl-xcomp-powerpc-ose5.conf358
-rw-r--r--xcomp/erl-xcomp-sfk-linux-ose5.conf305
-rw-r--r--xcomp/erl-xcomp-vars.sh2
1384 files changed, 83372 insertions, 112819 deletions
diff --git a/.gitignore b/.gitignore
index e27b5b12ff..3dcfa79f4d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -182,7 +182,6 @@ JAVADOC-GENERATED
# Files generated by configure.
#
-/lib/*/configure
/lib/*/config.log
/lib/*/config.status
@@ -190,6 +189,8 @@ JAVADOC-GENERATED
# Files generated by "./otp_build autoconf"
#
+/lib/*/configure
+/lib/common_test/test_server/configure
/lib/configure.in
/aclocal.m4
/lib/common_test/priv/auxdir/config.guess
@@ -201,9 +202,9 @@ JAVADOC-GENERATED
/lib/erl_interface/src/auxdir/install-sh
/lib/megaco/aclocal.m4
/lib/odbc/aclocal.m4
-/lib/test_server/src/config.guess
-/lib/test_server/src/config.sub
-/lib/test_server/src/install-sh
+/lib/common_test/test_server/config.guess
+/lib/common_test/test_server/config.sub
+/lib/common_test/test_server/install-sh
/lib/wx/aclocal.m4
/lib/wx/autoconf/config.guess
/lib/wx/autoconf/config.sub
diff --git a/HOWTO/INSTALL-CROSS.md b/HOWTO/INSTALL-CROSS.md
index 224f238fd0..0c984a825d 100644
--- a/HOWTO/INSTALL-CROSS.md
+++ b/HOWTO/INSTALL-CROSS.md
@@ -520,29 +520,6 @@ When a variable has been set, no warning will be issued.
`posix_memalign` implementation that accepts larger than page size
alignment.
-* `erl_xcomp_ose_ldflags_pass1` - Linker flags for the OSE module (pass 1)
-
-* `erl_xcomp_ose_ldflags_pass2` - Linker flags for the OSE module (pass 2)
-
-* `erl_xcomp_ose_OSEROOT` - OSE installation root directory
-
-* `erl_xcomp_ose_STRIP` - Strip utility shipped with the OSE distribution
-
-* `erl_xcomp_ose_LM_POST_LINK` - OSE postlink tool
-
-* `erl_xcomp_ose_LM_SET_CONF` - Sets the configuration for an OSE load module
-
-* `erl_xcomp_ose_LM_ELF_SIZE` - Prints the section size information for an
- OSE load module
-
-* `erl_xcomp_ose_LM_LCF` - OSE load module linker configuration file
-
-* `erl_xcomp_ose_BEAM_LM_CONF` - Beam OSE load module configuration file
-
-* `erl_xcomp_ose_EPMD_LM_CONF` - EPMD OSE load module configuration file
-
-* `erl_xcomp_ose_RUN_ERL_LM_CONF` - run_erl_lm OSE load module configuration file
-
Copyright and License
---------------------
diff --git a/Makefile.in b/Makefile.in
index 7ce420a8d7..377eebbbc2 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -670,8 +670,6 @@ tertiary_bootstrap_copy:
$(V_at)if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/wx ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/wx ; fi
$(V_at)if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/wx/ebin ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/wx/ebin ; fi
$(V_at)if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/wx/include ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/wx/include ; fi
- $(V_at)if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/test_server ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/test_server ; fi
- $(V_at)if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/test_server/include ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/test_server/include ; fi
$(V_at)if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/common_test ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/common_test ; fi
$(V_at)if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/common_test/include ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/common_test/include ; fi
$(V_at)for x in lib/ic/ebin/*.beam; do \
@@ -752,17 +750,6 @@ tertiary_bootstrap_copy:
done
# copy test includes to be able to compile tests with bootstrap compiler
- $(V_at)for x in lib/test_server/include/*.hrl; do \
- BN=`basename $$x`; \
- TF=$(BOOTSTRAP_ROOT)/bootstrap/lib/test_server/include/$$BN; \
- test -f $$TF && \
- test '!' -z "`find $$x -newer $$TF -print`" && \
- cp $$x $$TF; \
- test '!' -f $$TF && \
- cp $$x $$TF; \
- true; \
- done
-
$(V_at)for x in lib/common_test/include/*.hrl; do \
BN=`basename $$x`; \
TF=$(BOOTSTRAP_ROOT)/bootstrap/lib/common_test/include/$$BN; \
@@ -966,7 +953,7 @@ primary_bootstrap_copy:
# To remove modules left by the bootstrap building, but leave (restore)
# the modules in kernel which are needed for an emulator build
-KERNEL_PRELOAD = otp_ring0 init erl_prim_loader prim_inet prim_file zlib prim_zip erlang
+KERNEL_PRELOAD = otp_ring0 init erl_prim_loader prim_inet prim_file zlib prim_zip erlang erts_code_purger
KERNEL_PRELOAD_BEAMS=$(KERNEL_PRELOAD:%=$(BOOTSTRAP_TOP)/lib/kernel/ebin/%.beam)
start_scripts:
@@ -987,7 +974,7 @@ local_setup:
# ---------------------------------------------------------------------
TEST_DIRS := \
- lib/test_server \
+ lib/common_test/test_server \
$(wildcard lib/*/test) \
erts/test \
erts/epmd/test \
diff --git a/OTP_VERSION b/OTP_VERSION
index 32adf19808..cc12e7c6aa 100644
--- a/OTP_VERSION
+++ b/OTP_VERSION
@@ -1 +1,2 @@
-18.3
+19.0-rc0
+
diff --git a/bootstrap/bin/start.boot b/bootstrap/bin/start.boot
index ea3b3775aa..73381d4d8b 100644
--- a/bootstrap/bin/start.boot
+++ b/bootstrap/bin/start.boot
Binary files differ
diff --git a/bootstrap/bin/start_clean.boot b/bootstrap/bin/start_clean.boot
index ea3b3775aa..73381d4d8b 100644
--- a/bootstrap/bin/start_clean.boot
+++ b/bootstrap/bin/start_clean.boot
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_a.beam b/bootstrap/lib/compiler/ebin/beam_a.beam
index 3ff689bd81..2388ccad80 100644
--- a/bootstrap/lib/compiler/ebin/beam_a.beam
+++ b/bootstrap/lib/compiler/ebin/beam_a.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_asm.beam b/bootstrap/lib/compiler/ebin/beam_asm.beam
index 91c487f3d5..ae57c8dd6b 100644
--- a/bootstrap/lib/compiler/ebin/beam_asm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_asm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_block.beam b/bootstrap/lib/compiler/ebin/beam_block.beam
index 5d1e45fd72..7a96ad3196 100644
--- a/bootstrap/lib/compiler/ebin/beam_block.beam
+++ b/bootstrap/lib/compiler/ebin/beam_block.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_bool.beam b/bootstrap/lib/compiler/ebin/beam_bool.beam
index e503ad7484..e677c125a3 100644
--- a/bootstrap/lib/compiler/ebin/beam_bool.beam
+++ b/bootstrap/lib/compiler/ebin/beam_bool.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_bs.beam b/bootstrap/lib/compiler/ebin/beam_bs.beam
new file mode 100644
index 0000000000..18b9f8bc1b
--- /dev/null
+++ b/bootstrap/lib/compiler/ebin/beam_bs.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_bsm.beam b/bootstrap/lib/compiler/ebin/beam_bsm.beam
index 2f18ae4f30..b65f915978 100644
--- a/bootstrap/lib/compiler/ebin/beam_bsm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_bsm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_clean.beam b/bootstrap/lib/compiler/ebin/beam_clean.beam
index 2fd2d2a82f..0f24e040e3 100644
--- a/bootstrap/lib/compiler/ebin/beam_clean.beam
+++ b/bootstrap/lib/compiler/ebin/beam_clean.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_dead.beam b/bootstrap/lib/compiler/ebin/beam_dead.beam
index 6ae6de1d8b..10926614e6 100644
--- a/bootstrap/lib/compiler/ebin/beam_dead.beam
+++ b/bootstrap/lib/compiler/ebin/beam_dead.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_dict.beam b/bootstrap/lib/compiler/ebin/beam_dict.beam
index 17b3c40eda..4e12260e65 100644
--- a/bootstrap/lib/compiler/ebin/beam_dict.beam
+++ b/bootstrap/lib/compiler/ebin/beam_dict.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_disasm.beam b/bootstrap/lib/compiler/ebin/beam_disasm.beam
index 7c5dca424f..b2fd7faa0c 100644
--- a/bootstrap/lib/compiler/ebin/beam_disasm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_disasm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_except.beam b/bootstrap/lib/compiler/ebin/beam_except.beam
index f4fccfeef7..e5d2c51c4d 100644
--- a/bootstrap/lib/compiler/ebin/beam_except.beam
+++ b/bootstrap/lib/compiler/ebin/beam_except.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_flatten.beam b/bootstrap/lib/compiler/ebin/beam_flatten.beam
index c1d5604349..f6fc8dfc50 100644
--- a/bootstrap/lib/compiler/ebin/beam_flatten.beam
+++ b/bootstrap/lib/compiler/ebin/beam_flatten.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_jump.beam b/bootstrap/lib/compiler/ebin/beam_jump.beam
index 630a370a94..7382cafb48 100644
--- a/bootstrap/lib/compiler/ebin/beam_jump.beam
+++ b/bootstrap/lib/compiler/ebin/beam_jump.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_listing.beam b/bootstrap/lib/compiler/ebin/beam_listing.beam
index 4d8f94c4ea..41fac49d23 100644
--- a/bootstrap/lib/compiler/ebin/beam_listing.beam
+++ b/bootstrap/lib/compiler/ebin/beam_listing.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_peep.beam b/bootstrap/lib/compiler/ebin/beam_peep.beam
index 7a7856e247..334047bbf6 100644
--- a/bootstrap/lib/compiler/ebin/beam_peep.beam
+++ b/bootstrap/lib/compiler/ebin/beam_peep.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_receive.beam b/bootstrap/lib/compiler/ebin/beam_receive.beam
index 78c9eb1c39..0aa196f3de 100644
--- a/bootstrap/lib/compiler/ebin/beam_receive.beam
+++ b/bootstrap/lib/compiler/ebin/beam_receive.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_reorder.beam b/bootstrap/lib/compiler/ebin/beam_reorder.beam
new file mode 100644
index 0000000000..0dc44add6b
--- /dev/null
+++ b/bootstrap/lib/compiler/ebin/beam_reorder.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_split.beam b/bootstrap/lib/compiler/ebin/beam_split.beam
index 4821d92c96..a4e2b78938 100644
--- a/bootstrap/lib/compiler/ebin/beam_split.beam
+++ b/bootstrap/lib/compiler/ebin/beam_split.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_trim.beam b/bootstrap/lib/compiler/ebin/beam_trim.beam
index 6878a8a01c..194882f68a 100644
--- a/bootstrap/lib/compiler/ebin/beam_trim.beam
+++ b/bootstrap/lib/compiler/ebin/beam_trim.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_type.beam b/bootstrap/lib/compiler/ebin/beam_type.beam
index cb3bc1a8bd..35bc046ef8 100644
--- a/bootstrap/lib/compiler/ebin/beam_type.beam
+++ b/bootstrap/lib/compiler/ebin/beam_type.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_utils.beam b/bootstrap/lib/compiler/ebin/beam_utils.beam
index fc2e1b6c78..a97fc853a7 100644
--- a/bootstrap/lib/compiler/ebin/beam_utils.beam
+++ b/bootstrap/lib/compiler/ebin/beam_utils.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_validator.beam b/bootstrap/lib/compiler/ebin/beam_validator.beam
index 8b13cea141..73fa117755 100644
--- a/bootstrap/lib/compiler/ebin/beam_validator.beam
+++ b/bootstrap/lib/compiler/ebin/beam_validator.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_z.beam b/bootstrap/lib/compiler/ebin/beam_z.beam
index ac156a37e9..7bf77d7d33 100644
--- a/bootstrap/lib/compiler/ebin/beam_z.beam
+++ b/bootstrap/lib/compiler/ebin/beam_z.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl.beam b/bootstrap/lib/compiler/ebin/cerl.beam
index 7ff73413d7..88857b8905 100644
--- a/bootstrap/lib/compiler/ebin/cerl.beam
+++ b/bootstrap/lib/compiler/ebin/cerl.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl_clauses.beam b/bootstrap/lib/compiler/ebin/cerl_clauses.beam
index 2357df79f4..95dd3f3cbb 100644
--- a/bootstrap/lib/compiler/ebin/cerl_clauses.beam
+++ b/bootstrap/lib/compiler/ebin/cerl_clauses.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl_inline.beam b/bootstrap/lib/compiler/ebin/cerl_inline.beam
index 0e466ad38e..cc90a53ef9 100644
--- a/bootstrap/lib/compiler/ebin/cerl_inline.beam
+++ b/bootstrap/lib/compiler/ebin/cerl_inline.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl_sets.beam b/bootstrap/lib/compiler/ebin/cerl_sets.beam
index d16543cdbe..20cf324b41 100644
--- a/bootstrap/lib/compiler/ebin/cerl_sets.beam
+++ b/bootstrap/lib/compiler/ebin/cerl_sets.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl_trees.beam b/bootstrap/lib/compiler/ebin/cerl_trees.beam
index b23668fb2b..37120929ba 100644
--- a/bootstrap/lib/compiler/ebin/cerl_trees.beam
+++ b/bootstrap/lib/compiler/ebin/cerl_trees.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/compile.beam b/bootstrap/lib/compiler/ebin/compile.beam
index 111f85acd2..5234f98a75 100644
--- a/bootstrap/lib/compiler/ebin/compile.beam
+++ b/bootstrap/lib/compiler/ebin/compile.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/compiler.app b/bootstrap/lib/compiler/ebin/compiler.app
index 4dd52e31bf..37a6ce4acb 100644
--- a/bootstrap/lib/compiler/ebin/compiler.app
+++ b/bootstrap/lib/compiler/ebin/compiler.app
@@ -25,6 +25,7 @@
beam_asm,
beam_block,
beam_bool,
+ beam_bs,
beam_bsm,
beam_clean,
beam_dead,
@@ -37,6 +38,7 @@
beam_opcodes,
beam_peep,
beam_receive,
+ beam_reorder,
beam_split,
beam_trim,
beam_type,
diff --git a/bootstrap/lib/compiler/ebin/core_lib.beam b/bootstrap/lib/compiler/ebin/core_lib.beam
index ec87099635..32b770c186 100644
--- a/bootstrap/lib/compiler/ebin/core_lib.beam
+++ b/bootstrap/lib/compiler/ebin/core_lib.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_lint.beam b/bootstrap/lib/compiler/ebin/core_lint.beam
index b1cbbf030d..69143cdd23 100644
--- a/bootstrap/lib/compiler/ebin/core_lint.beam
+++ b/bootstrap/lib/compiler/ebin/core_lint.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_parse.beam b/bootstrap/lib/compiler/ebin/core_parse.beam
index 025ac1591b..3ef8588f65 100644
--- a/bootstrap/lib/compiler/ebin/core_parse.beam
+++ b/bootstrap/lib/compiler/ebin/core_parse.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_pp.beam b/bootstrap/lib/compiler/ebin/core_pp.beam
index 7ba89c698e..f320fd6908 100644
--- a/bootstrap/lib/compiler/ebin/core_pp.beam
+++ b/bootstrap/lib/compiler/ebin/core_pp.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_scan.beam b/bootstrap/lib/compiler/ebin/core_scan.beam
index c54edfc0e7..5f7b22ba8b 100644
--- a/bootstrap/lib/compiler/ebin/core_scan.beam
+++ b/bootstrap/lib/compiler/ebin/core_scan.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/rec_env.beam b/bootstrap/lib/compiler/ebin/rec_env.beam
index c49a2e23e9..9388b5d4e1 100644
--- a/bootstrap/lib/compiler/ebin/rec_env.beam
+++ b/bootstrap/lib/compiler/ebin/rec_env.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam b/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam
index 14c69eec6c..0c2d05286a 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_fold.beam b/bootstrap/lib/compiler/ebin/sys_core_fold.beam
index cbdef8e1d7..52c0d62f5f 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_fold.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_fold.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_fold_lists.beam b/bootstrap/lib/compiler/ebin/sys_core_fold_lists.beam
index 58ae7c0393..20cd2af6bc 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_fold_lists.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_fold_lists.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_inline.beam b/bootstrap/lib/compiler/ebin/sys_core_inline.beam
index 4f44297bee..963b7ef6e1 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_inline.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_inline.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_pre_attributes.beam b/bootstrap/lib/compiler/ebin/sys_pre_attributes.beam
index a1c6466ccd..934a539ad9 100644
--- a/bootstrap/lib/compiler/ebin/sys_pre_attributes.beam
+++ b/bootstrap/lib/compiler/ebin/sys_pre_attributes.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_pre_expand.beam b/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
index 6eba755081..71d381b5b3 100644
--- a/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
+++ b/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_codegen.beam b/bootstrap/lib/compiler/ebin/v3_codegen.beam
index 10647442a3..322469639f 100644
--- a/bootstrap/lib/compiler/ebin/v3_codegen.beam
+++ b/bootstrap/lib/compiler/ebin/v3_codegen.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_core.beam b/bootstrap/lib/compiler/ebin/v3_core.beam
index 5c5a124e4c..223eb2acef 100644
--- a/bootstrap/lib/compiler/ebin/v3_core.beam
+++ b/bootstrap/lib/compiler/ebin/v3_core.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_kernel.beam b/bootstrap/lib/compiler/ebin/v3_kernel.beam
index f5cdbb6e40..6555a39c86 100644
--- a/bootstrap/lib/compiler/ebin/v3_kernel.beam
+++ b/bootstrap/lib/compiler/ebin/v3_kernel.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam b/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam
index d54716bbee..306ecb1569 100644
--- a/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam
+++ b/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_life.beam b/bootstrap/lib/compiler/ebin/v3_life.beam
index 741a702e88..d8822f929f 100644
--- a/bootstrap/lib/compiler/ebin/v3_life.beam
+++ b/bootstrap/lib/compiler/ebin/v3_life.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/application.beam b/bootstrap/lib/kernel/ebin/application.beam
index 97c6d9d415..ac01acad27 100644
--- a/bootstrap/lib/kernel/ebin/application.beam
+++ b/bootstrap/lib/kernel/ebin/application.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/application_controller.beam b/bootstrap/lib/kernel/ebin/application_controller.beam
index c4fa46e33e..2b3c8cf454 100644
--- a/bootstrap/lib/kernel/ebin/application_controller.beam
+++ b/bootstrap/lib/kernel/ebin/application_controller.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/application_master.beam b/bootstrap/lib/kernel/ebin/application_master.beam
index b81dfa81d3..24492a6771 100644
--- a/bootstrap/lib/kernel/ebin/application_master.beam
+++ b/bootstrap/lib/kernel/ebin/application_master.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/application_starter.beam b/bootstrap/lib/kernel/ebin/application_starter.beam
index f5059a487a..043e15fb2a 100644
--- a/bootstrap/lib/kernel/ebin/application_starter.beam
+++ b/bootstrap/lib/kernel/ebin/application_starter.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/auth.beam b/bootstrap/lib/kernel/ebin/auth.beam
index 74dde4fd1c..cbe477830b 100644
--- a/bootstrap/lib/kernel/ebin/auth.beam
+++ b/bootstrap/lib/kernel/ebin/auth.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/code.beam b/bootstrap/lib/kernel/ebin/code.beam
index 71b2025094..28d8a5b579 100644
--- a/bootstrap/lib/kernel/ebin/code.beam
+++ b/bootstrap/lib/kernel/ebin/code.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/code_server.beam b/bootstrap/lib/kernel/ebin/code_server.beam
index f2400a9a6f..135fd066d9 100644
--- a/bootstrap/lib/kernel/ebin/code_server.beam
+++ b/bootstrap/lib/kernel/ebin/code_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/disk_log.beam b/bootstrap/lib/kernel/ebin/disk_log.beam
index 287a8c0de8..3384baedc0 100644
--- a/bootstrap/lib/kernel/ebin/disk_log.beam
+++ b/bootstrap/lib/kernel/ebin/disk_log.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/disk_log_1.beam b/bootstrap/lib/kernel/ebin/disk_log_1.beam
index 9c887c8ed9..fc1c4781f1 100644
--- a/bootstrap/lib/kernel/ebin/disk_log_1.beam
+++ b/bootstrap/lib/kernel/ebin/disk_log_1.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/disk_log_server.beam b/bootstrap/lib/kernel/ebin/disk_log_server.beam
index 8c1622c7d8..50154045be 100644
--- a/bootstrap/lib/kernel/ebin/disk_log_server.beam
+++ b/bootstrap/lib/kernel/ebin/disk_log_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/dist_ac.beam b/bootstrap/lib/kernel/ebin/dist_ac.beam
index ea948cfe88..d2c186f03a 100644
--- a/bootstrap/lib/kernel/ebin/dist_ac.beam
+++ b/bootstrap/lib/kernel/ebin/dist_ac.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/dist_util.beam b/bootstrap/lib/kernel/ebin/dist_util.beam
index f87dd4a45c..521bdb5d91 100644
--- a/bootstrap/lib/kernel/ebin/dist_util.beam
+++ b/bootstrap/lib/kernel/ebin/dist_util.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_boot_server.beam b/bootstrap/lib/kernel/ebin/erl_boot_server.beam
index 91899fe231..20c41fd06e 100644
--- a/bootstrap/lib/kernel/ebin/erl_boot_server.beam
+++ b/bootstrap/lib/kernel/ebin/erl_boot_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_ddll.beam b/bootstrap/lib/kernel/ebin/erl_ddll.beam
index e15e49d61c..0a644d2e38 100644
--- a/bootstrap/lib/kernel/ebin/erl_ddll.beam
+++ b/bootstrap/lib/kernel/ebin/erl_ddll.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_distribution.beam b/bootstrap/lib/kernel/ebin/erl_distribution.beam
index 9a6acc0585..eacacf799c 100644
--- a/bootstrap/lib/kernel/ebin/erl_distribution.beam
+++ b/bootstrap/lib/kernel/ebin/erl_distribution.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_epmd.beam b/bootstrap/lib/kernel/ebin/erl_epmd.beam
index 8910de12ef..8e8460514c 100644
--- a/bootstrap/lib/kernel/ebin/erl_epmd.beam
+++ b/bootstrap/lib/kernel/ebin/erl_epmd.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_reply.beam b/bootstrap/lib/kernel/ebin/erl_reply.beam
index 79fb539bd3..6cf7d9e196 100644
--- a/bootstrap/lib/kernel/ebin/erl_reply.beam
+++ b/bootstrap/lib/kernel/ebin/erl_reply.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/error_handler.beam b/bootstrap/lib/kernel/ebin/error_handler.beam
index 740ba28f72..64f44baeb7 100644
--- a/bootstrap/lib/kernel/ebin/error_handler.beam
+++ b/bootstrap/lib/kernel/ebin/error_handler.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/error_logger.beam b/bootstrap/lib/kernel/ebin/error_logger.beam
index 10f7a0b984..73ab813430 100644
--- a/bootstrap/lib/kernel/ebin/error_logger.beam
+++ b/bootstrap/lib/kernel/ebin/error_logger.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erts_debug.beam b/bootstrap/lib/kernel/ebin/erts_debug.beam
index bd73ff6c5c..908c63cb9a 100644
--- a/bootstrap/lib/kernel/ebin/erts_debug.beam
+++ b/bootstrap/lib/kernel/ebin/erts_debug.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/file.beam b/bootstrap/lib/kernel/ebin/file.beam
index 32a3a27993..a66a2621b9 100644
--- a/bootstrap/lib/kernel/ebin/file.beam
+++ b/bootstrap/lib/kernel/ebin/file.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/file_io_server.beam b/bootstrap/lib/kernel/ebin/file_io_server.beam
index b9c53bde49..dabb6b194e 100644
--- a/bootstrap/lib/kernel/ebin/file_io_server.beam
+++ b/bootstrap/lib/kernel/ebin/file_io_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/file_server.beam b/bootstrap/lib/kernel/ebin/file_server.beam
index 48352e9dfd..151293e05c 100644
--- a/bootstrap/lib/kernel/ebin/file_server.beam
+++ b/bootstrap/lib/kernel/ebin/file_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/gen_sctp.beam b/bootstrap/lib/kernel/ebin/gen_sctp.beam
index e2bb806f2b..91aaa41063 100644
--- a/bootstrap/lib/kernel/ebin/gen_sctp.beam
+++ b/bootstrap/lib/kernel/ebin/gen_sctp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/gen_tcp.beam b/bootstrap/lib/kernel/ebin/gen_tcp.beam
index 0182e11345..e40f1f2e45 100644
--- a/bootstrap/lib/kernel/ebin/gen_tcp.beam
+++ b/bootstrap/lib/kernel/ebin/gen_tcp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/gen_udp.beam b/bootstrap/lib/kernel/ebin/gen_udp.beam
index e49561399d..ec4eda12f7 100644
--- a/bootstrap/lib/kernel/ebin/gen_udp.beam
+++ b/bootstrap/lib/kernel/ebin/gen_udp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/global.beam b/bootstrap/lib/kernel/ebin/global.beam
index 158fbd1c93..419102e285 100644
--- a/bootstrap/lib/kernel/ebin/global.beam
+++ b/bootstrap/lib/kernel/ebin/global.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/global_group.beam b/bootstrap/lib/kernel/ebin/global_group.beam
index 85306ef123..1269f7e321 100644
--- a/bootstrap/lib/kernel/ebin/global_group.beam
+++ b/bootstrap/lib/kernel/ebin/global_group.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/group.beam b/bootstrap/lib/kernel/ebin/group.beam
index 0f72880f49..3df8f6030c 100644
--- a/bootstrap/lib/kernel/ebin/group.beam
+++ b/bootstrap/lib/kernel/ebin/group.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/heart.beam b/bootstrap/lib/kernel/ebin/heart.beam
index 8892785416..86044153af 100644
--- a/bootstrap/lib/kernel/ebin/heart.beam
+++ b/bootstrap/lib/kernel/ebin/heart.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
index 9da5cce487..a90757bd32 100644
--- a/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
+++ b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet.beam b/bootstrap/lib/kernel/ebin/inet.beam
index 75743c63cc..55598b0067 100644
--- a/bootstrap/lib/kernel/ebin/inet.beam
+++ b/bootstrap/lib/kernel/ebin/inet.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet6_sctp.beam b/bootstrap/lib/kernel/ebin/inet6_sctp.beam
index 10c2644259..5c827589bd 100644
--- a/bootstrap/lib/kernel/ebin/inet6_sctp.beam
+++ b/bootstrap/lib/kernel/ebin/inet6_sctp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet6_tcp.beam b/bootstrap/lib/kernel/ebin/inet6_tcp.beam
index 96dd4739ea..f1ab2912bb 100644
--- a/bootstrap/lib/kernel/ebin/inet6_tcp.beam
+++ b/bootstrap/lib/kernel/ebin/inet6_tcp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet6_udp.beam b/bootstrap/lib/kernel/ebin/inet6_udp.beam
index 73f0b52b90..2eb8c09701 100644
--- a/bootstrap/lib/kernel/ebin/inet6_udp.beam
+++ b/bootstrap/lib/kernel/ebin/inet6_udp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_config.beam b/bootstrap/lib/kernel/ebin/inet_config.beam
index f31fb16742..f49fa7a376 100644
--- a/bootstrap/lib/kernel/ebin/inet_config.beam
+++ b/bootstrap/lib/kernel/ebin/inet_config.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_db.beam b/bootstrap/lib/kernel/ebin/inet_db.beam
index 6401f0fcfa..1b7450f0d3 100644
--- a/bootstrap/lib/kernel/ebin/inet_db.beam
+++ b/bootstrap/lib/kernel/ebin/inet_db.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_dns.beam b/bootstrap/lib/kernel/ebin/inet_dns.beam
index b1c3bf3369..88ecaaf10b 100644
--- a/bootstrap/lib/kernel/ebin/inet_dns.beam
+++ b/bootstrap/lib/kernel/ebin/inet_dns.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_gethost_native.beam b/bootstrap/lib/kernel/ebin/inet_gethost_native.beam
index 098c397936..93f60428a1 100644
--- a/bootstrap/lib/kernel/ebin/inet_gethost_native.beam
+++ b/bootstrap/lib/kernel/ebin/inet_gethost_native.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_hosts.beam b/bootstrap/lib/kernel/ebin/inet_hosts.beam
index 3e70a8b8c1..7278913418 100644
--- a/bootstrap/lib/kernel/ebin/inet_hosts.beam
+++ b/bootstrap/lib/kernel/ebin/inet_hosts.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_parse.beam b/bootstrap/lib/kernel/ebin/inet_parse.beam
index 294afcea30..4323d12bf1 100644
--- a/bootstrap/lib/kernel/ebin/inet_parse.beam
+++ b/bootstrap/lib/kernel/ebin/inet_parse.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_res.beam b/bootstrap/lib/kernel/ebin/inet_res.beam
index f35242f49a..ada7300673 100644
--- a/bootstrap/lib/kernel/ebin/inet_res.beam
+++ b/bootstrap/lib/kernel/ebin/inet_res.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_sctp.beam b/bootstrap/lib/kernel/ebin/inet_sctp.beam
index 19506c14e9..835c7b2928 100644
--- a/bootstrap/lib/kernel/ebin/inet_sctp.beam
+++ b/bootstrap/lib/kernel/ebin/inet_sctp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_tcp.beam b/bootstrap/lib/kernel/ebin/inet_tcp.beam
index c2b42fef1c..698a94770b 100644
--- a/bootstrap/lib/kernel/ebin/inet_tcp.beam
+++ b/bootstrap/lib/kernel/ebin/inet_tcp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam b/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam
index 1b389cbb4d..59cb7ce40e 100644
--- a/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam
+++ b/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_udp.beam b/bootstrap/lib/kernel/ebin/inet_udp.beam
index 6fbdd29f6d..6876ba3892 100644
--- a/bootstrap/lib/kernel/ebin/inet_udp.beam
+++ b/bootstrap/lib/kernel/ebin/inet_udp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/kernel.appup b/bootstrap/lib/kernel/ebin/kernel.appup
index 7810fb611b..5cd6724383 100644
--- a/bootstrap/lib/kernel/ebin/kernel.appup
+++ b/bootstrap/lib/kernel/ebin/kernel.appup
@@ -18,9 +18,9 @@
%% %CopyrightEnd%
{"4.1.1",
%% Up from - max one major revision back
- [{<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.*
+ [{<<"4\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.*
{<<"3\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17
%% Down to - max one major revision back
- [{<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.*
+ [{<<"4\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.*
{<<"3\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17
}.
diff --git a/bootstrap/lib/kernel/ebin/kernel.beam b/bootstrap/lib/kernel/ebin/kernel.beam
index caeda89fa5..9fd407c287 100644
--- a/bootstrap/lib/kernel/ebin/kernel.beam
+++ b/bootstrap/lib/kernel/ebin/kernel.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/kernel_config.beam b/bootstrap/lib/kernel/ebin/kernel_config.beam
index 5a4649a054..8691aff64a 100644
--- a/bootstrap/lib/kernel/ebin/kernel_config.beam
+++ b/bootstrap/lib/kernel/ebin/kernel_config.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/net_adm.beam b/bootstrap/lib/kernel/ebin/net_adm.beam
index 4b09aae8a5..00772b61ff 100644
--- a/bootstrap/lib/kernel/ebin/net_adm.beam
+++ b/bootstrap/lib/kernel/ebin/net_adm.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/net_kernel.beam b/bootstrap/lib/kernel/ebin/net_kernel.beam
index e0bb445bf5..bd15759017 100644
--- a/bootstrap/lib/kernel/ebin/net_kernel.beam
+++ b/bootstrap/lib/kernel/ebin/net_kernel.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/os.beam b/bootstrap/lib/kernel/ebin/os.beam
index 9eaf7dfe5d..9ebe6c770f 100644
--- a/bootstrap/lib/kernel/ebin/os.beam
+++ b/bootstrap/lib/kernel/ebin/os.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/pg2.beam b/bootstrap/lib/kernel/ebin/pg2.beam
index 944f6a27a4..2115e46b60 100644
--- a/bootstrap/lib/kernel/ebin/pg2.beam
+++ b/bootstrap/lib/kernel/ebin/pg2.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/ram_file.beam b/bootstrap/lib/kernel/ebin/ram_file.beam
index a8b23f5490..b119b3656c 100644
--- a/bootstrap/lib/kernel/ebin/ram_file.beam
+++ b/bootstrap/lib/kernel/ebin/ram_file.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/rpc.beam b/bootstrap/lib/kernel/ebin/rpc.beam
index 4a8aa5da69..4d1cbdb625 100644
--- a/bootstrap/lib/kernel/ebin/rpc.beam
+++ b/bootstrap/lib/kernel/ebin/rpc.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/seq_trace.beam b/bootstrap/lib/kernel/ebin/seq_trace.beam
index efc5b7dc2a..68d1b50f84 100644
--- a/bootstrap/lib/kernel/ebin/seq_trace.beam
+++ b/bootstrap/lib/kernel/ebin/seq_trace.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/standard_error.beam b/bootstrap/lib/kernel/ebin/standard_error.beam
index be4f9292e7..9dfd66b2f4 100644
--- a/bootstrap/lib/kernel/ebin/standard_error.beam
+++ b/bootstrap/lib/kernel/ebin/standard_error.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/user.beam b/bootstrap/lib/kernel/ebin/user.beam
index d69339866a..c2b2808555 100644
--- a/bootstrap/lib/kernel/ebin/user.beam
+++ b/bootstrap/lib/kernel/ebin/user.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/user_drv.beam b/bootstrap/lib/kernel/ebin/user_drv.beam
index 6027806558..e306b172bf 100644
--- a/bootstrap/lib/kernel/ebin/user_drv.beam
+++ b/bootstrap/lib/kernel/ebin/user_drv.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/user_sup.beam b/bootstrap/lib/kernel/ebin/user_sup.beam
index 79dd095896..9e7b95544d 100644
--- a/bootstrap/lib/kernel/ebin/user_sup.beam
+++ b/bootstrap/lib/kernel/ebin/user_sup.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/wrap_log_reader.beam b/bootstrap/lib/kernel/ebin/wrap_log_reader.beam
index 68578800a0..91ef523b99 100644
--- a/bootstrap/lib/kernel/ebin/wrap_log_reader.beam
+++ b/bootstrap/lib/kernel/ebin/wrap_log_reader.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/include/file.hrl b/bootstrap/lib/kernel/include/file.hrl
index 7cf033f7f5..36112bb040 100644
--- a/bootstrap/lib/kernel/include/file.hrl
+++ b/bootstrap/lib/kernel/include/file.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1997-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.
@@ -23,37 +23,40 @@
%%--------------------------------------------------------------------------
-record(file_info,
- {size :: non_neg_integer(), % Size of file in bytes.
- type :: 'device' | 'directory' | 'other' | 'regular' | 'symlink',
- access :: 'read' | 'write' | 'read_write' | 'none',
- atime :: file:date_time() | non_neg_integer(),
+ {size :: non_neg_integer() | 'undefined', % Size of file in bytes.
+ type :: 'device' | 'directory' | 'other' | 'regular' | 'symlink'
+ | 'undefined',
+ access :: 'read' | 'write' | 'read_write' | 'none' | 'undefined',
+ atime :: file:date_time() | non_neg_integer() | 'undefined',
% The local time the file was last read:
% {{Year, Mon, Day}, {Hour, Min, Sec}}.
% atime, ctime, mtime may also be unix epochs()
- mtime :: file:date_time() | non_neg_integer(),
+ mtime :: file:date_time() | non_neg_integer() | 'undefined',
% The local time the file was last written.
- ctime :: file:date_time() | non_neg_integer(),
+ ctime :: file:date_time() | non_neg_integer() | 'undefined',
% The interpretation of this time field
% is dependent on operating system.
% On Unix it is the last time the file
% or the inode was changed. On Windows,
% it is the creation time.
- mode :: non_neg_integer(), % File permissions. On Windows,
+ mode :: non_neg_integer() | 'undefined',
+ % File permissions. On Windows,
% the owner permissions will be
% duplicated for group and user.
- links :: non_neg_integer(),
+ links :: non_neg_integer() | 'undefined',
% Number of links to the file (1 if the
% filesystem doesn't support links).
- major_device :: non_neg_integer(),
+ major_device :: non_neg_integer() | 'undefined',
% Identifies the file system (Unix),
% or the drive number (A: = 0, B: = 1)
% (Windows).
%% The following are Unix specific.
%% They are set to zero on other operating systems.
- minor_device :: non_neg_integer(), % Only valid for devices.
- inode :: non_neg_integer(), % Inode number for file.
- uid :: non_neg_integer(), % User id for owner.
- gid :: non_neg_integer()}). % Group id for owner.
+ minor_device :: non_neg_integer() | 'undefined',
+ % Only valid for devices.
+ inode :: non_neg_integer() | 'undefined', % Inode number for file.
+ uid :: non_neg_integer() | 'undefined', % User id for owner.
+ gid :: non_neg_integer() | 'undefined'}). % Group id for owner.
-record(file_descriptor,
diff --git a/bootstrap/lib/stdlib/ebin/array.beam b/bootstrap/lib/stdlib/ebin/array.beam
index 4ad9c7cd04..4ad8942b06 100644
--- a/bootstrap/lib/stdlib/ebin/array.beam
+++ b/bootstrap/lib/stdlib/ebin/array.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/base64.beam b/bootstrap/lib/stdlib/ebin/base64.beam
index e8d4b44102..ad725f61b9 100644
--- a/bootstrap/lib/stdlib/ebin/base64.beam
+++ b/bootstrap/lib/stdlib/ebin/base64.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/beam_lib.beam b/bootstrap/lib/stdlib/ebin/beam_lib.beam
index 4d2303a8a5..8b987fd7f7 100644
--- a/bootstrap/lib/stdlib/ebin/beam_lib.beam
+++ b/bootstrap/lib/stdlib/ebin/beam_lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/binary.beam b/bootstrap/lib/stdlib/ebin/binary.beam
index 666544c492..538d169565 100644
--- a/bootstrap/lib/stdlib/ebin/binary.beam
+++ b/bootstrap/lib/stdlib/ebin/binary.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/c.beam b/bootstrap/lib/stdlib/ebin/c.beam
index 0e07dc1531..133035102e 100644
--- a/bootstrap/lib/stdlib/ebin/c.beam
+++ b/bootstrap/lib/stdlib/ebin/c.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/calendar.beam b/bootstrap/lib/stdlib/ebin/calendar.beam
index 383d66e1a8..e71eebae3f 100644
--- a/bootstrap/lib/stdlib/ebin/calendar.beam
+++ b/bootstrap/lib/stdlib/ebin/calendar.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets.beam b/bootstrap/lib/stdlib/ebin/dets.beam
index 916557d6ad..b255a4e10f 100644
--- a/bootstrap/lib/stdlib/ebin/dets.beam
+++ b/bootstrap/lib/stdlib/ebin/dets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_server.beam b/bootstrap/lib/stdlib/ebin/dets_server.beam
index 46c6769dfe..da999f3025 100644
--- a/bootstrap/lib/stdlib/ebin/dets_server.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_server.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_utils.beam b/bootstrap/lib/stdlib/ebin/dets_utils.beam
index bcb506710b..ab627d50df 100644
--- a/bootstrap/lib/stdlib/ebin/dets_utils.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_utils.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_v8.beam b/bootstrap/lib/stdlib/ebin/dets_v8.beam
index 30784ed4a6..9a1416a316 100644
--- a/bootstrap/lib/stdlib/ebin/dets_v8.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_v8.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_v9.beam b/bootstrap/lib/stdlib/ebin/dets_v9.beam
index cda91beaaf..0b966769ba 100644
--- a/bootstrap/lib/stdlib/ebin/dets_v9.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_v9.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dict.beam b/bootstrap/lib/stdlib/ebin/dict.beam
index 9ba2a9b62a..3b2b5a4c04 100644
--- a/bootstrap/lib/stdlib/ebin/dict.beam
+++ b/bootstrap/lib/stdlib/ebin/dict.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/digraph.beam b/bootstrap/lib/stdlib/ebin/digraph.beam
index 01933d662b..76713562bc 100644
--- a/bootstrap/lib/stdlib/ebin/digraph.beam
+++ b/bootstrap/lib/stdlib/ebin/digraph.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/digraph_utils.beam b/bootstrap/lib/stdlib/ebin/digraph_utils.beam
index 458c6d2895..9065fda936 100644
--- a/bootstrap/lib/stdlib/ebin/digraph_utils.beam
+++ b/bootstrap/lib/stdlib/ebin/digraph_utils.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/edlin.beam b/bootstrap/lib/stdlib/ebin/edlin.beam
index 51d61d7a0b..8b1719eb0a 100644
--- a/bootstrap/lib/stdlib/ebin/edlin.beam
+++ b/bootstrap/lib/stdlib/ebin/edlin.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/edlin_expand.beam b/bootstrap/lib/stdlib/ebin/edlin_expand.beam
index 3d9846bdcf..adc0f4ba1c 100644
--- a/bootstrap/lib/stdlib/ebin/edlin_expand.beam
+++ b/bootstrap/lib/stdlib/ebin/edlin_expand.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/epp.beam b/bootstrap/lib/stdlib/ebin/epp.beam
index 00cf6f2a5c..e2a528f9fc 100644
--- a/bootstrap/lib/stdlib/ebin/epp.beam
+++ b/bootstrap/lib/stdlib/ebin/epp.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_anno.beam b/bootstrap/lib/stdlib/ebin/erl_anno.beam
index 4807dac5f9..72a255c88f 100644
--- a/bootstrap/lib/stdlib/ebin/erl_anno.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_anno.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_bits.beam b/bootstrap/lib/stdlib/ebin/erl_bits.beam
index 627b9ca711..af8619bac0 100644
--- a/bootstrap/lib/stdlib/ebin/erl_bits.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_bits.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_compile.beam b/bootstrap/lib/stdlib/ebin/erl_compile.beam
index e650afbf6d..82949da20a 100644
--- a/bootstrap/lib/stdlib/ebin/erl_compile.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_compile.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_eval.beam b/bootstrap/lib/stdlib/ebin/erl_eval.beam
index 6b8c0cd4c9..b58781d3f8 100644
--- a/bootstrap/lib/stdlib/ebin/erl_eval.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_eval.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_expand_records.beam b/bootstrap/lib/stdlib/ebin/erl_expand_records.beam
index db2d0e6b85..617913c674 100644
--- a/bootstrap/lib/stdlib/ebin/erl_expand_records.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_expand_records.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_lint.beam b/bootstrap/lib/stdlib/ebin/erl_lint.beam
index 744f2cdb36..3a0681d1bf 100644
--- a/bootstrap/lib/stdlib/ebin/erl_lint.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_lint.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_parse.beam b/bootstrap/lib/stdlib/ebin/erl_parse.beam
index 4b0e853390..79e96cabec 100644
--- a/bootstrap/lib/stdlib/ebin/erl_parse.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_parse.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_pp.beam b/bootstrap/lib/stdlib/ebin/erl_pp.beam
index d40913093a..4cc4884c92 100644
--- a/bootstrap/lib/stdlib/ebin/erl_pp.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_pp.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_scan.beam b/bootstrap/lib/stdlib/ebin/erl_scan.beam
index c29200f2e0..6c35d20c46 100644
--- a/bootstrap/lib/stdlib/ebin/erl_scan.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_scan.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_tar.beam b/bootstrap/lib/stdlib/ebin/erl_tar.beam
index e525b3738b..9bcbabc27c 100644
--- a/bootstrap/lib/stdlib/ebin/erl_tar.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_tar.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/error_logger_file_h.beam b/bootstrap/lib/stdlib/ebin/error_logger_file_h.beam
index 0b98a9ceed..0e61e87708 100644
--- a/bootstrap/lib/stdlib/ebin/error_logger_file_h.beam
+++ b/bootstrap/lib/stdlib/ebin/error_logger_file_h.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/error_logger_tty_h.beam b/bootstrap/lib/stdlib/ebin/error_logger_tty_h.beam
index 565904b903..46eafce18e 100644
--- a/bootstrap/lib/stdlib/ebin/error_logger_tty_h.beam
+++ b/bootstrap/lib/stdlib/ebin/error_logger_tty_h.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/escript.beam b/bootstrap/lib/stdlib/ebin/escript.beam
index e923cecea8..c006d9a1ad 100644
--- a/bootstrap/lib/stdlib/ebin/escript.beam
+++ b/bootstrap/lib/stdlib/ebin/escript.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ets.beam b/bootstrap/lib/stdlib/ebin/ets.beam
index 9ac333dbee..a15534b365 100644
--- a/bootstrap/lib/stdlib/ebin/ets.beam
+++ b/bootstrap/lib/stdlib/ebin/ets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/eval_bits.beam b/bootstrap/lib/stdlib/ebin/eval_bits.beam
index 6627e1132c..be20e8c720 100644
--- a/bootstrap/lib/stdlib/ebin/eval_bits.beam
+++ b/bootstrap/lib/stdlib/ebin/eval_bits.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/file_sorter.beam b/bootstrap/lib/stdlib/ebin/file_sorter.beam
index 24dbd901e5..9286aea119 100644
--- a/bootstrap/lib/stdlib/ebin/file_sorter.beam
+++ b/bootstrap/lib/stdlib/ebin/file_sorter.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/filelib.beam b/bootstrap/lib/stdlib/ebin/filelib.beam
index 5941f9189f..5ea27fdca6 100644
--- a/bootstrap/lib/stdlib/ebin/filelib.beam
+++ b/bootstrap/lib/stdlib/ebin/filelib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/filename.beam b/bootstrap/lib/stdlib/ebin/filename.beam
index e4b462f5ff..7f6818db30 100644
--- a/bootstrap/lib/stdlib/ebin/filename.beam
+++ b/bootstrap/lib/stdlib/ebin/filename.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gb_sets.beam b/bootstrap/lib/stdlib/ebin/gb_sets.beam
index 71da2376ba..3cb606350b 100644
--- a/bootstrap/lib/stdlib/ebin/gb_sets.beam
+++ b/bootstrap/lib/stdlib/ebin/gb_sets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gb_trees.beam b/bootstrap/lib/stdlib/ebin/gb_trees.beam
index db59d5af19..d8579c63cd 100644
--- a/bootstrap/lib/stdlib/ebin/gb_trees.beam
+++ b/bootstrap/lib/stdlib/ebin/gb_trees.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen.beam b/bootstrap/lib/stdlib/ebin/gen.beam
index ccaabd8087..586973a973 100644
--- a/bootstrap/lib/stdlib/ebin/gen.beam
+++ b/bootstrap/lib/stdlib/ebin/gen.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen_event.beam b/bootstrap/lib/stdlib/ebin/gen_event.beam
index d22f9ec402..4788735049 100644
--- a/bootstrap/lib/stdlib/ebin/gen_event.beam
+++ b/bootstrap/lib/stdlib/ebin/gen_event.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen_fsm.beam b/bootstrap/lib/stdlib/ebin/gen_fsm.beam
index 119c20e1d7..f78a7368d5 100644
--- a/bootstrap/lib/stdlib/ebin/gen_fsm.beam
+++ b/bootstrap/lib/stdlib/ebin/gen_fsm.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen_server.beam b/bootstrap/lib/stdlib/ebin/gen_server.beam
index d6e5d223fb..8ebe9d7a3a 100644
--- a/bootstrap/lib/stdlib/ebin/gen_server.beam
+++ b/bootstrap/lib/stdlib/ebin/gen_server.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io.beam b/bootstrap/lib/stdlib/ebin/io.beam
index fd64aedde1..283c912800 100644
--- a/bootstrap/lib/stdlib/ebin/io.beam
+++ b/bootstrap/lib/stdlib/ebin/io.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io_lib.beam b/bootstrap/lib/stdlib/ebin/io_lib.beam
index c95a88c0f0..c52bf42077 100644
--- a/bootstrap/lib/stdlib/ebin/io_lib.beam
+++ b/bootstrap/lib/stdlib/ebin/io_lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io_lib_format.beam b/bootstrap/lib/stdlib/ebin/io_lib_format.beam
index 032e15eeb1..3fdf08d9e4 100644
--- a/bootstrap/lib/stdlib/ebin/io_lib_format.beam
+++ b/bootstrap/lib/stdlib/ebin/io_lib_format.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io_lib_fread.beam b/bootstrap/lib/stdlib/ebin/io_lib_fread.beam
index b4af88d5b5..62a4beeb2d 100644
--- a/bootstrap/lib/stdlib/ebin/io_lib_fread.beam
+++ b/bootstrap/lib/stdlib/ebin/io_lib_fread.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam b/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
index eed02e5fa5..9d37b74ad3 100644
--- a/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
+++ b/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/lib.beam b/bootstrap/lib/stdlib/ebin/lib.beam
index 1cc92d1b8d..8e594d97ad 100644
--- a/bootstrap/lib/stdlib/ebin/lib.beam
+++ b/bootstrap/lib/stdlib/ebin/lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/lists.beam b/bootstrap/lib/stdlib/ebin/lists.beam
index b2dabc7d22..91297311b2 100644
--- a/bootstrap/lib/stdlib/ebin/lists.beam
+++ b/bootstrap/lib/stdlib/ebin/lists.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/log_mf_h.beam b/bootstrap/lib/stdlib/ebin/log_mf_h.beam
index 58a8d68ed5..0c4b22c3df 100644
--- a/bootstrap/lib/stdlib/ebin/log_mf_h.beam
+++ b/bootstrap/lib/stdlib/ebin/log_mf_h.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/maps.beam b/bootstrap/lib/stdlib/ebin/maps.beam
index 02e46c38be..7533b56554 100644
--- a/bootstrap/lib/stdlib/ebin/maps.beam
+++ b/bootstrap/lib/stdlib/ebin/maps.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ms_transform.beam b/bootstrap/lib/stdlib/ebin/ms_transform.beam
index cc8503fdb3..2c0eb8a742 100644
--- a/bootstrap/lib/stdlib/ebin/ms_transform.beam
+++ b/bootstrap/lib/stdlib/ebin/ms_transform.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/orddict.beam b/bootstrap/lib/stdlib/ebin/orddict.beam
index 665941a17c..f04348f982 100644
--- a/bootstrap/lib/stdlib/ebin/orddict.beam
+++ b/bootstrap/lib/stdlib/ebin/orddict.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/otp_internal.beam b/bootstrap/lib/stdlib/ebin/otp_internal.beam
index 7ceb6e46fb..e834be6dca 100644
--- a/bootstrap/lib/stdlib/ebin/otp_internal.beam
+++ b/bootstrap/lib/stdlib/ebin/otp_internal.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/pool.beam b/bootstrap/lib/stdlib/ebin/pool.beam
index 72934a42d7..a06ae1717a 100644
--- a/bootstrap/lib/stdlib/ebin/pool.beam
+++ b/bootstrap/lib/stdlib/ebin/pool.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/proc_lib.beam b/bootstrap/lib/stdlib/ebin/proc_lib.beam
index 0f732c8cae..568015b3e4 100644
--- a/bootstrap/lib/stdlib/ebin/proc_lib.beam
+++ b/bootstrap/lib/stdlib/ebin/proc_lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/proplists.beam b/bootstrap/lib/stdlib/ebin/proplists.beam
index 2640cfe4ae..835df8c3a0 100644
--- a/bootstrap/lib/stdlib/ebin/proplists.beam
+++ b/bootstrap/lib/stdlib/ebin/proplists.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/qlc.beam b/bootstrap/lib/stdlib/ebin/qlc.beam
index d9bdf2b93c..436b62e50e 100644
--- a/bootstrap/lib/stdlib/ebin/qlc.beam
+++ b/bootstrap/lib/stdlib/ebin/qlc.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/qlc_pt.beam b/bootstrap/lib/stdlib/ebin/qlc_pt.beam
index 90bc537b85..4032af0dd7 100644
--- a/bootstrap/lib/stdlib/ebin/qlc_pt.beam
+++ b/bootstrap/lib/stdlib/ebin/qlc_pt.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/rand.beam b/bootstrap/lib/stdlib/ebin/rand.beam
index 0f3ffb7542..8370469ff4 100644
--- a/bootstrap/lib/stdlib/ebin/rand.beam
+++ b/bootstrap/lib/stdlib/ebin/rand.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/random.beam b/bootstrap/lib/stdlib/ebin/random.beam
index f576b310df..fc351a800a 100644
--- a/bootstrap/lib/stdlib/ebin/random.beam
+++ b/bootstrap/lib/stdlib/ebin/random.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/re.beam b/bootstrap/lib/stdlib/ebin/re.beam
index 875c4a5513..7b2e736a21 100644
--- a/bootstrap/lib/stdlib/ebin/re.beam
+++ b/bootstrap/lib/stdlib/ebin/re.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sets.beam b/bootstrap/lib/stdlib/ebin/sets.beam
index d8546de28d..4d4a2205f9 100644
--- a/bootstrap/lib/stdlib/ebin/sets.beam
+++ b/bootstrap/lib/stdlib/ebin/sets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/shell.beam b/bootstrap/lib/stdlib/ebin/shell.beam
index 9ad6d68ebd..8e64036c90 100644
--- a/bootstrap/lib/stdlib/ebin/shell.beam
+++ b/bootstrap/lib/stdlib/ebin/shell.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/slave.beam b/bootstrap/lib/stdlib/ebin/slave.beam
index 532c46cd38..373d65f198 100644
--- a/bootstrap/lib/stdlib/ebin/slave.beam
+++ b/bootstrap/lib/stdlib/ebin/slave.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sofs.beam b/bootstrap/lib/stdlib/ebin/sofs.beam
index c7862afc2f..5514b0d4f9 100644
--- a/bootstrap/lib/stdlib/ebin/sofs.beam
+++ b/bootstrap/lib/stdlib/ebin/sofs.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/stdlib.appup b/bootstrap/lib/stdlib/ebin/stdlib.appup
index e545adc484..8b0206f6be 100644
--- a/bootstrap/lib/stdlib/ebin/stdlib.appup
+++ b/bootstrap/lib/stdlib/ebin/stdlib.appup
@@ -18,9 +18,9 @@
%% %CopyrightEnd%
{"2.7",
%% Up from - max one major revision back
- [{<<"2\\.[5-8](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.*
+ [{<<"2\\.[5-7](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.*
{<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}], % 17.0-17.5
%% Down to - max one major revision back
- [{<<"2\\.[5-8](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.*
+ [{<<"2\\.[5-7](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.*
{<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}] % 17.0-17.5
}.
diff --git a/bootstrap/lib/stdlib/ebin/supervisor.beam b/bootstrap/lib/stdlib/ebin/supervisor.beam
index 65790d73dc..e03a3264a6 100644
--- a/bootstrap/lib/stdlib/ebin/supervisor.beam
+++ b/bootstrap/lib/stdlib/ebin/supervisor.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/supervisor_bridge.beam b/bootstrap/lib/stdlib/ebin/supervisor_bridge.beam
index 4af6cc8f40..d2bfe6eea8 100644
--- a/bootstrap/lib/stdlib/ebin/supervisor_bridge.beam
+++ b/bootstrap/lib/stdlib/ebin/supervisor_bridge.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sys.beam b/bootstrap/lib/stdlib/ebin/sys.beam
index a569f8003f..d0162bdd07 100644
--- a/bootstrap/lib/stdlib/ebin/sys.beam
+++ b/bootstrap/lib/stdlib/ebin/sys.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/timer.beam b/bootstrap/lib/stdlib/ebin/timer.beam
index 9887f37c70..8d8fcf8937 100644
--- a/bootstrap/lib/stdlib/ebin/timer.beam
+++ b/bootstrap/lib/stdlib/ebin/timer.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/unicode.beam b/bootstrap/lib/stdlib/ebin/unicode.beam
index dc8fdcaf86..17a318c4d4 100644
--- a/bootstrap/lib/stdlib/ebin/unicode.beam
+++ b/bootstrap/lib/stdlib/ebin/unicode.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/win32reg.beam b/bootstrap/lib/stdlib/ebin/win32reg.beam
index b37ead63ba..2b4f9229ea 100644
--- a/bootstrap/lib/stdlib/ebin/win32reg.beam
+++ b/bootstrap/lib/stdlib/ebin/win32reg.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/zip.beam b/bootstrap/lib/stdlib/ebin/zip.beam
index 200b0f705c..1a19b1f28a 100644
--- a/bootstrap/lib/stdlib/ebin/zip.beam
+++ b/bootstrap/lib/stdlib/ebin/zip.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/include/erl_bits.hrl b/bootstrap/lib/stdlib/include/erl_bits.hrl
index 8405a55d55..2a54587a17 100644
--- a/bootstrap/lib/stdlib/include/erl_bits.hrl
+++ b/bootstrap/lib/stdlib/include/erl_bits.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-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.
@@ -26,10 +26,10 @@
-type bt_unit() :: 1..256.
-record(bittype, {
- type :: bt_type(),
- unit :: bt_unit(), %% element unit
- sign :: bt_sign(),
- endian :: bt_endian()
+ type :: bt_type() | 'undefined',
+ unit :: bt_unit() | 'undefined', %% element unit
+ sign :: bt_sign() | 'undefined',
+ endian :: bt_endian() | 'undefined'
}).
-record(bitdefault, {
diff --git a/configure.in b/configure.in
index 40498f2ff9..89486590b8 100644
--- a/configure.in
+++ b/configure.in
@@ -208,10 +208,6 @@ AS_HELP_STRING([--disable-threads], [disable async thread support]))
AC_ARG_ENABLE(dirty-schedulers,
AS_HELP_STRING([--enable-dirty-schedulers], [enable dirty scheduler support]))
-AC_ARG_ENABLE(halfword-emulator,
-AS_HELP_STRING([--enable-halfword-emulator],
- [enable halfword emulator (only for 64bit builds). Note: Halfword emulator is marked as deprecated and scheduled for removal in future major release.]))
-
AC_ARG_ENABLE(smp-support,
AS_HELP_STRING([--enable-smp-support], [enable smp support])
AS_HELP_STRING([--disable-smp-support], [disable smp support]))
@@ -282,6 +278,10 @@ AC_ARG_ENABLE(builtin-zlib,
AS_HELP_STRING([--enable-builtin-zlib],
[force use of our own built-in zlib]))
+AC_ARG_ENABLE(sharing-preserving,
+AS_HELP_STRING([--enable-sharing-preserving],
+ [enable copying of terms without destroying sharing]))
+
dnl This functionality has been lost along the way... :(
dnl It could perhaps be nice to reintroduce some day; therefore,
dnl it is not removed just commented out.
diff --git a/erts/aclocal.m4 b/erts/aclocal.m4
index ec9b66bf29..017fdbd589 100644
--- a/erts/aclocal.m4
+++ b/erts/aclocal.m4
@@ -74,21 +74,6 @@ AC_ARG_VAR(erl_xcomp_clock_gettime_cpu_time, [clock_gettime() can be used for re
AC_ARG_VAR(erl_xcomp_after_morecore_hook, [__after_morecore_hook can track malloc()s core memory usage: yes|no (only used when cross compiling)])
AC_ARG_VAR(erl_xcomp_dlsym_brk_wrappers, [dlsym(RTLD_NEXT, _) brk wrappers can track malloc()s core memory usage: yes|no (only used when cross compiling)])
-dnl Cross compilation variables for OSE
-AC_ARG_VAR(erl_xcomp_ose_ldflags_pass1, [Linker flags for the OSE module (pass 1) (only used when cross compiling for OSE)])
-AC_ARG_VAR(erl_xcomp_ose_ldflags_pass2, [Linker flags for the OSE module (pass 2) (only used when cross compiling for OSE)])
-AC_ARG_VAR(erl_xcomp_ose_OSEROOT, [OSE installation root directory (only used when cross compiling for OSE)])
-AC_ARG_VAR(erl_xcomp_ose_STRIP, [Strip utility shipped with the OSE distribution(only used when cross compiling for OSE)])
-AC_ARG_VAR(erl_xcomp_ose_LM_POST_LINK, [OSE postlink tool (only used when cross compiling for OSE)])
-AC_ARG_VAR(erl_xcomp_ose_LM_SET_CONF, [Sets the configuration for an OSE load module (only used when cross compiling for OSE)])
-AC_ARG_VAR(erl_xcomp_ose_LM_ELF_SIZE, [Prints the section size information for an OSE load module (only used when cross compiling for OSE)])
-AC_ARG_VAR(erl_xcomp_ose_LM_LCF, [OSE load module linker configuration file (only used when cross compiling for OSE)])
-AC_ARG_VAR(erl_xcomp_ose_BEAM_LM_CONF, [BEAM OSE load module default configuration file (only used when cross compiling for OSE)])
-AC_ARG_VAR(erl_xcomp_ose_EPMD_LM_CONF, [EPMD OSE load module default configuration file (only used when cross compiling for OSE)])
-AC_ARG_VAR(erl_xcomp_ose_RUN_ERL_LM_CONF, [run_erl_lm OSE load module default configuration file (only used when cross compiling for OSE)])
-AC_ARG_VAR(erl_xcomp_ose_CONFD, [OSE confd source file])
-AC_ARG_VAR(erl_xcomp_ose_CRT0_LM, [OSE crt0 lm source file])
-
])
AC_DEFUN(ERL_XCOMP_SYSROOT_INIT,
@@ -503,8 +488,6 @@ AC_CACHE_VAL(ac_cv_sys_ipv6_support,
#ifdef __WIN32__
#include <winsock2.h>
#include <ws2tcpip.h>
-#elif __OSE__
-#error "no ipv6"
#else
#include <netinet/in.h>
#endif],
@@ -517,8 +500,6 @@ else
#ifdef __WIN32__
#include <winsock2.h>
#include <ws2tcpip.h>
-#elif __OSE__
-#error "no ipv6"
#else
#include <netinet/in.h>
#endif],
@@ -991,12 +972,6 @@ if test "X$host_os" = "Xwin32"; then
THR_LIBS=
THR_LIB_NAME=win32_threads
THR_LIB_TYPE=win32_threads
-elif test "X$host_os" = "Xose"; then
- AC_MSG_RESULT(yes)
- THR_DEFS="-DOSE_THREADS"
- THR_LIBS=
- THR_LIB_NAME=ose_threads
- THR_LIB_TYPE=ose_threads
else
AC_MSG_RESULT(no)
THR_DEFS=
@@ -1583,22 +1558,9 @@ case "$THR_LIB_NAME" in
fi
;;
- pthread|ose_threads)
- case "$THR_LIB_NAME" in
- pthread)
- ETHR_THR_LIB_BASE_DIR=pthread
- AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads])
- ;;
- ose_threads)
- AC_DEFINE(ETHR_OSE_THREADS, 1,
- [Define if you have OSE style threads])
- ETHR_THR_LIB_BASE_DIR=ose
- AC_CHECK_HEADER(ose_spi/ose_spi.h,
- AC_DEFINE(HAVE_OSE_SPI_H, 1,
- [Define if you have the "ose_spi/ose_spi.h" header file.]))
- ;;
- esac
- if test "x$THR_LIB_NAME" = "xpthread"; then
+ pthread)
+ ETHR_THR_LIB_BASE_DIR=pthread
+ AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads])
case $host_os in
openbsd*)
# The default stack size is insufficient for our needs
@@ -1657,7 +1619,6 @@ case "$THR_LIB_NAME" in
*) ;;
esac
- fi
dnl We sometimes need ETHR_DEFS in order to find certain headers
dnl (at least for pthread.h on osf1).
saved_cppflags="$CPPFLAGS"
@@ -1702,7 +1663,6 @@ case "$THR_LIB_NAME" in
dnl
dnl Check for functions
dnl
- if test "x$THR_LIB_NAME" = "xpthread"; then
AC_CHECK_FUNC(pthread_spin_lock, \
[ethr_have_native_spinlock=yes \
AC_DEFINE(ETHR_HAVE_PTHREAD_SPIN_LOCK, 1, \
@@ -1922,8 +1882,6 @@ case "$THR_LIB_NAME" in
esac
CFLAGS=$old_CFLAGS
- fi ## test "x$THR_LIB_NAME" = "xpthread"
-
if test "X$disable_native_ethr_impls" = "Xyes"; then
ethr_have_native_atomics=no
else
diff --git a/erts/configure.in b/erts/configure.in
index 4ade3b3086..021780ecc2 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -106,7 +106,6 @@ AC_CONFIG_HEADER($host/config.h:config.h.in include/internal/$host/ethread_heade
dnl ----------------------------------------------------------------------
dnl Optional features.
dnl ----------------------------------------------------------------------
-enable_child_waiter_thread=no
ENABLE_ALLOC_TYPE_VARS=
AC_SUBST(ENABLE_ALLOC_TYPE_VARS)
@@ -143,14 +142,6 @@ AS_HELP_STRING([--enable-dirty-schedulers], [enable dirty scheduler support]),
*) enable_dirty_schedulers=yes ;;
esac ], enable_dirty_schedulers=no)
-AC_ARG_ENABLE(halfword-emulator,
-AS_HELP_STRING([--enable-halfword-emulator],
- [enable halfword emulator (only for 64bit builds). Note: Halfword emulator is marked as deprecated and scheduled for removal in future major release.]),
-[ case "$enableval" in
- no) enable_halfword_emualtor=no ;;
- *) enable_halfword_emulator=yes ;;
- esac ], enable_halfword_emulator=unknown)
-
AC_ARG_ENABLE(smp-support,
AS_HELP_STRING([--enable-smp-support], [enable smp support])
AS_HELP_STRING([--disable-smp-support], [disable smp support]),
@@ -351,6 +342,21 @@ AS_HELP_STRING([--disable-saved-compile-time], [disable saved compile time]),
AC_DEFINE_UNQUOTED(ERTS_SAVED_COMPILE_TIME, $save_compile_time, [Save compile time?])
+AC_ARG_WITH(microstate-accounting,
+AS_HELP_STRING([--with-microstate-accounting={yes|extra}],
+ [enable microstate account, possibly with extra detailed states])
+AS_HELP_STRING([--without-microstate-accounting],
+ [don't enable microstate accounting]),
+[],[with_microstate_accounting=yes])
+
+case "$with_microstate_accounting" in
+ yes) AC_DEFINE(ERTS_ENABLE_MSACC,[1],
+ [Define as 1 if you want to enable microstate accounting, 2 if you want extra states]) ;;
+ extra) AC_DEFINE(ERTS_ENABLE_MSACC,[2],
+ [Define as 1 if you want to enable microstate accounting, 2 if you want extra states]) ;;
+ *) ;;
+esac
+
dnl Magic test for clearcase.
OTP_RELEASE=
if test "${ERLANG_COMMERCIAL_BUILD}" != ""; then
@@ -578,6 +584,7 @@ fi
if test "x$GCC" = xyes; then
# Treat certain GCC warnings as errors
LM_TRY_ENABLE_CFLAG([-Werror=return-type], [WERRORFLAGS])
+ LM_TRY_ENABLE_CFLAG([-Werror=implicit], [WERRORFLAGS])
# until the emulator can handle this, I suggest we turn it off!
#WFLAGS="-Wall -Wshadow -Wcast-qual -Wmissing-declarations"
@@ -796,36 +803,18 @@ esac
AC_SUBST(LIBCARBON)
-dnl Check if we should/can build a halfword emulator
-
-AC_MSG_CHECKING(if we are building a halfword emulator (32bit heap on 64bit machine))
-if test "$enable_halfword_emulator" = "yes"; then
- if test "$ARCH" = "amd64"; then
- AC_DEFINE(HALFWORD_HEAP_EMULATOR, [1],
- [Define if building a halfword-heap 64bit emulator])
- ENABLE_ALLOC_TYPE_VARS="$ENABLE_ALLOC_TYPE_VARS halfword"
- AC_MSG_RESULT([yes])
-
- test -f "$ERL_TOP/erts/CONF_INFO" ||
- echo "" > "$ERL_TOP/erts/CONF_INFO"
- cat >> $ERL_TOP/erts/CONF_INFO <<EOF
-
- The HALFWORD emulator has been enabled.
- This is a DEPRECATED feature scheduled for removal
- in a future major release.
+dnl Check if we should/can build a sharing-preserving emulator
-EOF
- else
- AC_MSG_ERROR(no; halfword emulator not supported on this architecture)
- fi
+AC_MSG_CHECKING(if we are building a sharing-preserving emulator)
+if test "$enable_sharing_preserving" = "yes"; then
+ AC_DEFINE(SHCOPY, [1],
+ [Define if building a sharing-preserving emulator])
+ AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
-
-
-
dnl some tests below will call this if we haven't already - and autoconf
dnl can't handle those tests being done conditionally at runtime
AC_PROG_CPP
@@ -944,10 +933,7 @@ dnl what the user say. This might not be the right way to do it, but
dnl for now that is the way we do it.
USER_LD=$LD
USER_LDFLAGS="$LDFLAGS"
-case $host in
- *ose) ;;
- *) LD='$(CC)' ;;
-esac
+LD='$(CC)'
AC_SUBST(LD)
LDFLAG_RUNTIME_LIBRARY_PATH="$CFLAG_RUNTIME_LIBRARY_PATH"
@@ -962,8 +948,6 @@ dnl This is the os flavour, should be unix, ose, vxworks or win32
case $host in
win32)
ERLANG_OSTYPE=win32 ;;
- *ose)
- ERLANG_OSTYPE=ose ;;
*)
ERLANG_OSTYPE=unix ;;
esac
@@ -1272,7 +1256,7 @@ case "$enable_threads"-"$found_threads" in
AC_MSG_RESULT(yes; enabled by user) ;;
unknown-yes)
case $host_os in
- solaris*|linux*|darwin*|win32|ose)
+ solaris*|linux*|darwin*|win32)
emu_threads=yes
AC_MSG_RESULT(yes; default on this platform)
;;
@@ -1334,11 +1318,7 @@ else
AC_MSG_RESULT(no)
fi
- disable_child_waiter_thread=no
case $host_os in
- solaris*)
- enable_child_waiter_thread=yes
- ;;
linux*)
AC_MSG_CHECKING([whether dlopen() needs to be called before first call to dlerror()])
if test "x$ETHR_THR_LIB_BASE_TYPE" != "xposix_nptl"; then
@@ -1348,16 +1328,6 @@ else
else
AC_MSG_RESULT(no)
fi
- if test "x$ETHR_THR_LIB_BASE_TYPE" != "xposix_nptl"; then
- # Child waiter thread cannot be enabled
- disable_child_waiter_thread=yes
- enable_child_waiter_thread=no
- fi
- ;;
- win32|ose)
- # Child waiter thread cannot be enabled
- disable_child_waiter_thread=yes
- enable_child_waiter_thread=no
;;
*)
;;
@@ -1377,24 +1347,6 @@ else
esac
done
EMU_THR_DEFS=$new_emu_thr_defs
-
- AC_MSG_CHECKING(whether the child waiter thread should be enabled)
- if test $enable_child_waiter_thread = yes; then
- AC_DEFINE(ENABLE_CHILD_WAITER_THREAD,[1],
- [Define if you want to enable child waiter thread])
- AC_MSG_RESULT(yes)
- else
- case $ERTS_BUILD_SMP_EMU-$disable_child_waiter_thread in
- yes-no)
- AC_MSG_RESULT([yes on SMP build, but not on non-SMP build]);;
- *-yes)
- AC_DEFINE(DISABLE_CHILD_WAITER_THREAD,[1],
- [Define if you want to disable child waiter thread])
- AC_MSG_RESULT(no);;
- *)
- AC_MSG_RESULT(no);;
- esac
- fi
fi
AC_SUBST(EMU_THR_LIB_NAME)
@@ -1526,19 +1478,27 @@ dnl
# if -lsocket doesn't work by itself.
#--------------------------------------------------------------------
+tk_oldLibs=$LIBS
erl_checkBoth=0
+SOCKET_LIBS=""
AC_CHECK_FUNC(connect, erl_checkSocket=0, erl_checkSocket=1)
if test "$erl_checkSocket" = 1; then
- AC_CHECK_LIB(socket, main, LIBS="$LIBS -lsocket", erl_checkBoth=1)
+ AC_CHECK_LIB(socket, main, SOCKET_LIBS="-lsocket", erl_checkBoth=1)
fi
+
if test "$erl_checkBoth" = 1; then
- tk_oldLibs=$LIBS
LIBS="$LIBS -lsocket -lnsl"
- AC_CHECK_FUNC(accept, erl_checkNsl=0, [LIBS=$tk_oldLibs])
+ AC_CHECK_FUNC(accept, SOCKET_LIBS="-lsocket -lnsl")
fi
-AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, main, [LIBS="$LIBS -lnsl"]))
+
+LIBS="$tk_oldLibs $SOCKET_LIBS"
+AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, main, [SOCKET_LIBS="$SOCKET_LIBS -lnsl"]))
AC_CHECK_FUNC(gethostbyname_r,have_gethostbyname_r=yes)
+LIBS="$tk_oldLibs $SOCKET_LIBS"
+
+AC_SUBST(SOCKET_LIBS)
+
dnl
dnl These gethostbyname thingies use old style AC_DEFINE for BC with ancient
dnl autoconf...
@@ -2118,7 +2078,7 @@ AC_CHECK_FUNCS([getipnodebyname getipnodebyaddr gethostbyname2])
AC_CHECK_FUNCS([ieee_handler fpsetmask finite isnan isinf res_gethostbyname dlopen \
pread pwrite memmove strerror strerror_r strncasecmp \
gethrtime localtime_r gmtime_r inet_pton \
- memcpy mallopt sbrk _sbrk __sbrk brk _brk __brk \
+ mmap mremap memcpy mallopt sbrk _sbrk __sbrk brk _brk __brk \
flockfile fstat strlcpy strlcat setsid posix2time time2posix \
setlocale nl_langinfo poll mlockall ppoll])
@@ -2136,8 +2096,7 @@ fi
case X$erl_xcomp_posix_memalign in
Xno) ;;
- Xyes) AC_DEFINE(HAVE_POSIX_MEMALIGN,[1],
- [Define to 1 if you have the `posix_memalign' function.]) ;;
+ Xyes) have_posix_memalign=yes ;;
*)
AC_CHECK_FUNC(
[posix_memalign],
@@ -2152,15 +2111,19 @@ int main(void) {
return error;
return 0;
}
-],AC_DEFINE(HAVE_POSIX_MEMALIGN,[1],
- [Define to 1 if you have the `posix_memalign' function.])
+],have_posix_memalign=yes
)
else
- AC_DEFINE(HAVE_POSIX_MEMALIGN,[1],
- [Define to 1 if you have the `posix_memalign' function.])
+ have_posix_memalign=yes
fi]);;
esac
+if test $have_posix_memalign = yes; then
+ AC_DEFINE(HAVE_POSIX_MEMALIGN,[1],
+ [Define to 1 if you have the `posix_memalign' function.])
+fi
+
+
dnl writev on OS X snow leopard is broken for files > 4GB
case $host_os in
darwin10.8.0)
@@ -2170,17 +2133,6 @@ case $host_os in
AC_CHECK_FUNCS([writev]) ;;
esac
-case $host_os in
- *ose)
- AC_MSG_CHECKING([for mmap])
- AC_MSG_RESULT(not using for OSE)
- AC_MSG_CHECKING([for mremap])
- AC_MSG_RESULT(not using for OSE) ;;
- *)
- AC_CHECK_FUNCS([mmap mremap]) ;;
-esac
-
-
AC_CHECK_DECLS([posix2time, time2posix],,,[#include <time.h>])
disable_vfork=false
@@ -2829,17 +2781,26 @@ LM_SYS_IPV6
LM_SYS_MULTICAST
ERL_TIME_CORRECTION
AC_CHECK_PROG(M4, m4, m4)
+
+
+dnl HiPE cannot run on 64-bit without MAP_FIXED and MAP_NORESERVE
+if test X${enable_hipe} != Xno && test X$ac_cv_sizeof_void_p != X4; then
+ AC_CHECK_DECLS([MAP_FIXED, MAP_NORESERVE], [], [], [#include <sys/mman.h>])
+ if test X$ac_cv_have_decl_MAP_FIXED != Xyes || test X$ac_cv_have_decl_MAP_NORESERVE != Xyes; then
+ if test X${enable_hipe} = Xyes; then
+ AC_MSG_ERROR([HiPE on 64-bit needs MAP_FIXED and MAP_NORESERVE flags for mmap()])
+ else
+ enable_hipe=no
+ AC_MSG_WARN([Disable HiPE due to lack of MAP_FIXED and MAP_NORESERVE flags for mmap()])
+ fi
+ fi
+fi
+
dnl check to auto-enable hipe here...
if test "$cross_compiling" != "yes" && test X${enable_hipe} != Xno; then
if test -z "$M4"; then
enable_hipe=no
AC_MSG_NOTICE([HiPE disabled as no valid m4 is found in PATH])
- elif test "$enable_halfword_emulator" = "yes"; then
- if test X${enable_hipe} = Xyes; then
- AC_MSG_ERROR([HiPE can not be combined with halfword emulator (yet)])
- else
- AC_MSG_NOTICE([HiPE auto-disabled on halfword emulator])
- fi
else
case "$ARCH-$OPSYS" in
x86-linux|amd64-linux|x86-darwin*|amd64-darwin*|ppc-linux|ppc64-linux|ppc-darwin|arm-linux|amd64-freebsd|x86-freebsd|x86-sol2|amd64-sol2|ultrasparc-linux)
@@ -3768,7 +3729,7 @@ dnl crypto
#
#--------------------------------------------------------------------
-DED_SYS_INCLUDE="-I${ERL_TOP}/erts/emulator/beam -I${ERL_TOP}/erts/include -I${ERL_TOP}/erts/include/$host -I${ERL_TOP}/erts/include/internal -I${ERL_TOP}/erts/include/internal/$host -I${ERL_TOP}/erts/emulator/sys/$ERLANG_OSTYPE"
+DED_SYS_INCLUDE="-I${ERL_TOP}/erts/emulator/beam -I${ERL_TOP}/erts/include -I${ERL_TOP}/erts/include/$host -I${ERL_TOP}/erts/include/internal -I${ERL_TOP}/erts/include/internal/$host -I${ERL_TOP}/erts/emulator/sys/$ERLANG_OSTYPE -I${ERL_TOP}/erts/emulator/sys/common"
if test "X$ETHR_DEFS" = "X"; then
DED_THR_DEFS="-D_THREAD_SAFE -D_REENTRANT"
@@ -4940,7 +4901,6 @@ AC_OUTPUT(
Makefile:Makefile.in
../make/$host/otp.mk:../make/otp.mk.in
../make/$host/otp_ded.mk:../make/otp_ded.mk.in
- ../make/$host/ose_lm.mk:../make/ose_lm.mk.in
dnl
dnl The ones below should be moved to their respective lib
dnl
diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml
index 186c9a1143..13756ddfdc 100644
--- a/erts/doc/src/absform.xml
+++ b/erts/doc/src/absform.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2001</year><year>2015</year>
+ <year>2001</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -68,31 +68,29 @@
<item>If D is a module declaration consisting of the forms
<c>F_1</c>, ..., <c>F_k</c>, then
Rep(D) = <c>[Rep(F_1), ..., Rep(F_k)]</c>.</item>
- <item>If F is an attribute <c>-module(Mod)</c>, then
- Rep(F) = <c>{attribute,LINE,module,Mod}</c>.</item>
<item>If F is an attribute <c>-behavior(Behavior)</c>, then
Rep(F) = <c>{attribute,LINE,behavior,Behavior}</c>.</item>
<item>If F is an attribute <c>-behaviour(Behaviour)</c>, then
Rep(F) = <c>{attribute,LINE,behaviour,Behaviour}</c>.</item>
+ <item>If F is an attribute <c>-compile(Options)</c>, then
+ Rep(F) = <c>{attribute,LINE,compile,Options}</c>.</item>
<item>If F is an attribute <c>-export([Fun_1/A_1, ..., Fun_k/A_k])</c>, then
Rep(F) = <c>{attribute,LINE,export,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}</c>.</item>
- <item>If F is an attribute <c>-import(Mod,[Fun_1/A_1, ..., Fun_k/A_k])</c>, then
- Rep(F) = <c>{attribute,LINE,import,{Mod,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}}</c>.</item>
<item>If F is an attribute <c>-export_type([Type_1/A_1, ..., Type_k/A_k])</c>, then
Rep(F) = <c>{attribute,LINE,export_type,[{Type_1,A_1}, ..., {Type_k,A_k}]}</c>.</item>
- <item>If F is an attribute <c>-compile(Options)</c>, then
- Rep(F) = <c>{attribute,LINE,compile,Options}</c>.</item>
+ <item>If F is an attribute <c>-import(Mod,[Fun_1/A_1, ..., Fun_k/A_k])</c>, then
+ Rep(F) = <c>{attribute,LINE,import,{Mod,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}}</c>.</item>
+ <item>If F is an attribute <c>-module(Mod)</c>, then
+ Rep(F) = <c>{attribute,LINE,module,Mod}</c>.</item>
+ <item>If F is an attribute <c>-optional_callbacks([Fun_1/A_1, ..., Fun_k/A_k])</c>, then
+ Rep(F) = <c>{attribute,LINE,optional_callbacks,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}</c>.</item>
<item>If F is an attribute <c>-file(File,Line)</c>, then
Rep(F) = <c>{attribute,LINE,file,{File,Line}}</c>.</item>
- <item>If F is a record declaration
- <c>-record(Name,{V_1, ..., V_k})</c>, then Rep(F) =
- <c>{attribute,LINE,record,{Name,[Rep(V_1), ..., Rep(V_k)]}}</c>.
- For Rep(V), see below.</item>
- <item>If F is a type declaration
- <c>-Type Name(V_1, ..., V_k) :: T</c>, where
- <c>Type</c> is either the atom <c>type</c> or the atom <c>opaque</c>,
- each <c>V_i</c> is a variable, and <c>T</c> is a type, then Rep(F) =
- <c>{attribute,LINE,Type,{Name,Rep(T),[Rep(V_1), ..., Rep(V_k)]}}</c>.
+ <item>If F is a function declaration
+ <c>Name Fc_1 ; ... ; Name Fc_k</c>,
+ where each <c>Fc_i</c> is a function clause with a
+ pattern sequence of the same length <c>Arity</c>, then
+ Rep(F) = <c>{function,LINE,Name,Arity,[Rep(Fc_1), ...,Rep(Fc_k)]}</c>.
</item>
<item>If F is a function specification
<c>-Spec Name Ft_1; ...; Ft_k</c>,
@@ -109,15 +107,20 @@
<c>Arity</c>, then Rep(F) =
<c>{attribute,Line,spec,{{Mod,Name,Arity},[Rep(Ft_1), ..., Rep(Ft_k)]}}</c>.
</item>
+ <item>If F is a record declaration
+ <c>-record(Name,{V_1, ..., V_k})</c>,
+ where each <c>V_i</c> is a record field, then Rep(F) =
+ <c>{attribute,LINE,record,{Name,[Rep(V_1), ..., Rep(V_k)]}}</c>.
+ For Rep(V), see below.</item>
+ <item>If F is a type declaration
+ <c>-Type Name(V_1, ..., V_k) :: T</c>, where
+ <c>Type</c> is either the atom <c>type</c> or the atom <c>opaque</c>,
+ each <c>V_i</c> is a variable, and <c>T</c> is a type, then Rep(F) =
+ <c>{attribute,LINE,Type,{Name,Rep(T),[Rep(V_1), ..., Rep(V_k)]}}</c>.
+ </item>
<item>If F is a wild attribute <c>-A(T)</c>, then
Rep(F) = <c>{attribute,LINE,A,T}</c>.
<br></br></item>
- <item>If F is a function declaration
- <c>Name Fc_1 ; ... ; Name Fc_k</c>,
- where each <c>Fc_i</c> is a function clause with a
- pattern sequence of the same length <c>Arity</c>, then
- Rep(F) = <c>{function,LINE,Name,Arity,[Rep(Fc_1), ...,Rep(Fc_k)]}</c>.
- </item>
</list>
<section>
@@ -131,11 +134,6 @@
<item>If V is <c>A = E</c>,
where <c>E</c> is an expression, then
Rep(V) = <c>{record_field,LINE,Rep(A),Rep(E)}</c>.</item>
- <item>If V is <c>A :: T</c>, where <c>T</c> is a
- type and it does not contain
- <c>undefined</c> syntactically, then Rep(V) =
- <c>{typed_record_field,{record_field,LINE,Rep(A)},Rep(undefined | T)}</c>.
- </item>
<item>If V is <c>A :: T</c>, where <c>T</c> is a type, then Rep(V) =
<c>{typed_record_field,{record_field,LINE,Rep(A)},Rep(T)}</c>.
</item>
@@ -162,15 +160,15 @@
<p>There are five kinds of atomic literals, which are represented in the
same way in patterns, expressions and guards:</p>
<list type="bulleted">
- <item>If L is an integer or character literal, then
- Rep(L) = <c>{integer,LINE,L}</c>.</item>
+ <item>If L is an atom literal, then
+ Rep(L) = <c>{atom,LINE,L}</c>.</item>
<item>If L is a float literal, then
Rep(L) = <c>{float,LINE,L}</c>.</item>
+ <item>If L is an integer or character literal, then
+ Rep(L) = <c>{integer,LINE,L}</c>.</item>
<item>If L is a string literal consisting of the characters
<c>C_1</c>, ..., <c>C_k</c>, then
Rep(L) = <c>{string,LINE,[C_1, ..., C_k]}</c>.</item>
- <item>If L is an atom literal, then
- Rep(L) = <c>{atom,LINE,L}</c>.</item>
</list>
<p>Note that negative integer and float literals do not occur as such; they are
parsed as an application of the unary negation operator.</p>
@@ -178,47 +176,59 @@
<section>
<title>Patterns</title>
- <p>If <c>Ps</c> is a sequence of patterns <c>P_1, ..., P_k</c>, then
+ <p>If Ps is a sequence of patterns <c>P_1, ..., P_k</c>, then
Rep(Ps) = <c>[Rep(P_1), ..., Rep(P_k)]</c>. Such sequences occur as the
list of arguments to a function or fun.</p>
<p>Individual patterns are represented as follows:</p>
<list type="bulleted">
- <item>If P is an atomic literal L, then Rep(P) = Rep(L).</item>
+ <item>If P is an atomic literal <c>L</c>, then Rep(P) = Rep(L).</item>
+ <item>If P is a bit string pattern
+ <c>&lt;&lt;P_1:Size_1/TSL_1, ..., P_k:Size_k/TSL_k>></c>, where each
+ <c>Size_i</c> is an expression that can be evaluated to an integer
+ and each <c>TSL_i</c> is a type specificer list, then
+ Rep(P) = <c>{bin,LINE,[{bin_element,LINE,Rep(P_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(P_k),Rep(Size_k),Rep(TSL_k)}]}</c>.
+ For Rep(TSL), see below.
+ An omitted <c>Size_i</c> is represented by <c>default</c>.
+ An omitted <c>TSL_i</c> is represented by <c>default</c>.</item>
<item>If P is a compound pattern <c>P_1 = P_2</c>, then
Rep(P) = <c>{match,LINE,Rep(P_1),Rep(P_2)}</c>.</item>
- <item>If P is a variable pattern <c>V</c>, then
- Rep(P) = <c>{var,LINE,A}</c>,
- where A is an atom with a printname consisting of the same characters as
- <c>V</c>.</item>
- <item>If P is a universal pattern <c>_</c>, then
- Rep(P) = <c>{var,LINE,'_'}</c>.</item>
- <item>If P is a tuple pattern <c>{P_1, ..., P_k}</c>, then
- Rep(P) = <c>{tuple,LINE,[Rep(P_1), ..., Rep(P_k)]}</c>.</item>
- <item>If P is a nil pattern <c>[]</c>, then
- Rep(P) = <c>{nil,LINE}</c>.</item>
<item>If P is a cons pattern <c>[P_h | P_t]</c>, then
Rep(P) = <c>{cons,LINE,Rep(P_h),Rep(P_t)}</c>.</item>
- <item>If E is a binary pattern <c>&lt;&lt;P_1:Size_1/TSL_1, ..., P_k:Size_k/TSL_k>></c>, then
- Rep(E) = <c>{bin,LINE,[{bin_element,LINE,Rep(P_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(P_k),Rep(Size_k),Rep(TSL_k)}]}</c>.
- For Rep(TSL), see below.
- An omitted <c>Size</c> is represented by <c>default</c>. An omitted <c>TSL</c>
- (type specifier list) is represented by <c>default</c>.</item>
- <item>If P is <c>P_1 Op P_2</c>, where <c>Op</c> is a binary operator (this
- is either an occurrence of <c>++</c> applied to a literal string or character
+ <item>If P is a map pattern <c>#{A_1, ..., A_k}</c>, where each
+ <c>A_i</c> is an association <c>P_i_1 := P_i_2</c>, then Rep(P) =
+ <c>{map,LINE,[Rep(A_1), ..., Rep(A_k)]}</c>. For Rep(A), see
+ below.</item>
+ <item>If P is a nil pattern <c>[]</c>, then
+ Rep(P) = <c>{nil,LINE}</c>.</item>
+ <item>If P is an operator pattern <c>P_1 Op P_2</c>,
+ where <c>Op</c> is a binary operator (this is either an occurrence
+ of <c>++</c> applied to a literal string or character
list, or an occurrence of an expression that can be evaluated to a number
at compile time),
then Rep(P) = <c>{op,LINE,Op,Rep(P_1),Rep(P_2)}</c>.</item>
- <item>If P is <c>Op P_0</c>, where <c>Op</c> is a unary operator (this is an
- occurrence of an expression that can be evaluated to a number at compile
+ <item>If P is an operator pattern <c>Op P_0</c>,
+ where <c>Op</c> is a unary operator (this is an occurrence of
+ an expression that can be evaluated to a number at compile
time), then Rep(P) = <c>{op,LINE,Op,Rep(P_0)}</c>.</item>
- <item>If P is a record pattern <c>#Name{Field_1=P_1, ..., Field_k=P_k}</c>,
- then Rep(P) =
- <c>{record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(P_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(P_k)}]}</c>.</item>
- <item>If P is <c>#Name.Field</c>, then
- Rep(P) = <c>{record_index,LINE,Name,Rep(Field)}</c>.</item>
- <item>If P is <c>( P_0 )</c>, then
+ <item>If P is a parenthesized pattern <c>( P_0 )</c>, then
Rep(P) = <c>Rep(P_0)</c>,
- that is, patterns cannot be distinguished from their bodies.</item>
+ that is, parenthesized patterns cannot be distinguished from their
+ bodies.</item>
+ <item>If P is a record field index pattern <c>#Name.Field</c>,
+ where <c>Field</c> is an atom, then
+ Rep(P) = <c>{record_index,LINE,Name,Rep(Field)}</c>.</item>
+ <item>If P is a record pattern
+ <c>#Name{Field_1=P_1, ..., Field_k=P_k}</c>,
+ where each <c>Field_i</c> is an atom or <c>_</c>, then Rep(P) =
+ <c>{record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(P_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(P_k)}]}</c>.</item>
+ <item>If P is a tuple pattern <c>{P_1, ..., P_k}</c>, then
+ Rep(P) = <c>{tuple,LINE,[Rep(P_1), ..., Rep(P_k)]}</c>.</item>
+ <item>If P is a universal pattern <c>_</c>, then
+ Rep(P) = <c>{var,LINE,'_'}</c>.</item>
+ <item>If P is a variable pattern <c>V</c>, then
+ Rep(P) = <c>{var,LINE,A}</c>,
+ where A is an atom with a printname consisting of the same characters as
+ <c>V</c>.</item>
</list>
<p>Note that every pattern has the same source form as some expression, and is
represented the same way as the corresponding expression.</p>
@@ -226,167 +236,187 @@
<section>
<title>Expressions</title>
- <p>A body B is a sequence of expressions <c>E_1, ..., E_k</c>, and
- Rep(B) = <c>[Rep(E_1), ..., Rep(E_k)]</c>.</p>
+ <p>A body B is a nonempty sequence of expressions <c>E_1, ..., E_k</c>,
+ and Rep(B) = <c>[Rep(E_1), ..., Rep(E_k)]</c>.</p>
<p>An expression E is one of the following alternatives:</p>
<list type="bulleted">
- <item>If P is an atomic literal <c>L</c>, then Rep(P) = Rep(L).</item>
- <item>If E is <c>P = E_0</c>, then
- Rep(E) = <c>{match,LINE,Rep(P),Rep(E_0)}</c>.</item>
- <item>If E is a variable <c>V</c>, then Rep(E) = <c>{var,LINE,A}</c>,
- where <c>A</c> is an atom with a printname consisting of the same
- characters as <c>V</c>.</item>
- <item>If E is a tuple skeleton <c>{E_1, ..., E_k}</c>, then
- Rep(E) = <c>{tuple,LINE,[Rep(E_1), ..., Rep(E_k)]}</c>.</item>
- <item>If E is <c>[]</c>, then
- Rep(E) = <c>{nil,LINE}</c>.</item>
- <item>If E is a cons skeleton <c>[E_h | E_t]</c>, then
- Rep(E) = <c>{cons,LINE,Rep(E_h),Rep(E_t)}</c>.</item>
- <item>If E is a binary constructor <c>&lt;&lt;V_1:Size_1/TSL_1, ..., V_k:Size_k/TSL_k>></c>, then Rep(E) =
- <c>{bin,LINE,[{bin_element,LINE,Rep(V_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(V_k),Rep(Size_k),Rep(TSL_k)}]}</c>.
+ <item>If E is an atomic literal <c>L</c>, then Rep(E) = Rep(L).</item>
+ <item>If E is a bit string comprehension
+ <c>&lt;&lt;E_0 || Q_1, ..., Q_k>></c>,
+ where each <c>Q_i</c> is a qualifier, then
+ Rep(E) = <c>{bc,LINE,Rep(E_0),[Rep(Q_1), ..., Rep(Q_k)]}</c>.
+ For Rep(Q), see below.</item>
+ <item>If E is a bit string constructor
+ <c>&lt;&lt;E_1:Size_1/TSL_1, ..., E_k:Size_k/TSL_k>></c>,
+ where each <c>Size_i</c> is an expression and each
+ <c>TSL_i</c> is a type specificer list, then Rep(E) =
+ <c>{bin,LINE,[{bin_element,LINE,Rep(E_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(E_k),Rep(Size_k),Rep(TSL_k)}]}</c>.
For Rep(TSL), see below.
- An omitted <c>Size</c> is represented by <c>default</c>. An omitted <c>TSL</c>
- (type specifier list) is represented by <c>default</c>.</item>
- <item>If E is <c>E_1 Op E_2</c>, where <c>Op</c> is a binary operator,
- then Rep(E) = <c>{op,LINE,Op,Rep(E_1),Rep(E_2)}</c>.</item>
- <item>If E is <c>Op E_0</c>, where <c>Op</c> is a unary operator, then
- Rep(E) = <c>{op,LINE,Op,Rep(E_0)}</c>.</item>
- <item>If E is <c>#Name{Field_1=E_1, ..., Field_k=E_k}</c>,
- then Rep(E) =
- <c>{record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}</c>.</item>
- <item>If E is <c>E_0#Name{Field_1=E_1, ..., Field_k=E_k}</c>, then
- Rep(E) =
- <c>{record,LINE,Rep(E_0),Name,[{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}</c>.</item>
- <item>If E is <c>#Name.Field</c>, then
- Rep(E) = <c>{record_index,LINE,Name,Rep(Field)}</c>.</item>
- <item>If E is <c>E_0#Name.Field</c>, then
- Rep(E) = <c>{record_field,LINE,Rep(E_0),Name,Rep(Field)}</c>.</item>
- <item>If E is <c>#{W_1, ..., W_k}</c> where each
- <c>W_i</c> is a map assoc or exact field, then Rep(E) =
- <c>{map,LINE,[Rep(W_1), ..., Rep(W_k)]}</c>. For Rep(W), see
- below.</item>
- <item>If E is <c>E_0#{W_1, ..., W_k}</c> where
- <c>W_i</c> is a map assoc or exact field, then Rep(E) =
- <c>{map,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}</c>.
- For Rep(W), see below.</item>
- <item>If E is <c>catch E_0</c>, then
+ An omitted <c>Size_i</c> is represented by <c>default</c>.
+ An omitted <c>TSL_i</c> is represented by <c>default</c>.</item>
+ <item>If E is a block expression <c>begin B end</c>,
+ where <c>B</c> is a body, then
+ Rep(E) = <c>{block,LINE,Rep(B)}</c>.</item>
+ <item>If E is a case expression <c>case E_0 of Cc_1 ; ... ; Cc_k end</c>,
+ where <c>E_0</c> is an expression and each <c>Cc_i</c> is a
+ case clause then Rep(E) =
+ <c>{'case',LINE,Rep(E_0),[Rep(Cc_1), ..., Rep(Cc_k)]}</c>.</item>
+ <item>If E is a catch expression <c>catch E_0</c>, then
Rep(E) = <c>{'catch',LINE,Rep(E_0)}</c>.</item>
- <item>If E is <c>E_0(E_1, ..., E_k)</c>, then
+ <item>If E is a cons skeleton <c>[E_h | E_t]</c>, then
+ Rep(E) = <c>{cons,LINE,Rep(E_h),Rep(E_t)}</c>.</item>
+ <item>If E is a fun expression <c>fun Name/Arity</c>, then
+ Rep(E) = <c>{'fun',LINE,{function,Name,Arity}}</c>.</item>
+ <item>If E is a fun expression
+ <c>fun Module:Name/Arity</c>, then Rep(E) =
+ <c>{'fun',LINE,{function,Rep(Module),Rep(Name),Rep(Arity)}}</c>.
+ (Before the R15 release: Rep(E) =
+ <c>{'fun',LINE,{function,Module,Name,Arity}}</c>.)</item>
+ <item>If E is a fun expression <c>fun Fc_1 ; ... ; Fc_k end</c>,
+ where each <c>Fc_i</c> is a function clause then Rep(E) =
+ <c>{'fun',LINE,{clauses,[Rep(Fc_1), ..., Rep(Fc_k)]}}</c>.</item>
+ <item>If E is a fun expression
+ <c>fun Name Fc_1 ; ... ; Name Fc_k end</c>,
+ where <c>Name</c> is a variable and each
+ <c>Fc_i</c> is a function clause then Rep(E) =
+ <c>{named_fun,LINE,Name,[Rep(Fc_1), ..., Rep(Fc_k)]}</c>.
+ </item>
+ <item>If E is a function call <c>E_0(E_1, ..., E_k)</c>, then
Rep(E) = <c>{call,LINE,Rep(E_0),[Rep(E_1), ..., Rep(E_k)]}</c>.</item>
- <item>If E is <c>E_m:E_0(E_1, ..., E_k)</c>, then Rep(E) =
- <c>{call,LINE,{remote,LINE,Rep(E_m),Rep(E_0)},[Rep(E_1), ..., Rep(E_k)]}</c>.
+ <item>If E is a function call <c>E_m:E_0(E_1, ..., E_k)</c>,
+ then Rep(E) =
+ <c>{call,LINE,{remote,LINE,Rep(E_m),Rep(E_0)},[Rep(E_1), ..., Rep(E_k)]}</c>.
</item>
- <item>If E is a list comprehension <c>[E_0 || W_1, ..., W_k]</c>,
- where each <c>W_i</c> is a generator or a filter, then Rep(E) =
- <c>{lc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}</c>. For Rep(W), see
- below.</item>
- <item>If E is a binary comprehension
- <c>&lt;&lt;E_0 || W_1, ..., W_k>></c>,
- where each <c>W_i</c> is a generator or a filter, then
- Rep(E) = <c>{bc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}</c>.
- For Rep(W), see below.</item>
- <item>If E is <c>begin B end</c>, where <c>B</c> is a body, then
- Rep(E) = <c>{block,LINE,Rep(B)}</c>.</item>
- <item>If E is <c>if Ic_1 ; ... ; Ic_k end</c>,
+ <item>If E is an if expression <c>if Ic_1 ; ... ; Ic_k end</c>,
where each <c>Ic_i</c> is an if clause then Rep(E) =
<c>{'if',LINE,[Rep(Ic_1), ..., Rep(Ic_k)]}</c>.</item>
- <item>If E is <c>case E_0 of Cc_1 ; ... ; Cc_k end</c>,
- where <c>E_0</c> is an expression and each <c>Cc_i</c> is a
- case clause then Rep(E) =
- <c>{'case',LINE,Rep(E_0),[Rep(Cc_1), ..., Rep(Cc_k)]}</c>.</item>
- <item>If E is <c>try B catch Tc_1 ; ... ; Tc_k end</c>,
+ <item>If E is a list comprehension <c>[E_0 || Q_1, ..., Q_k]</c>,
+ where each <c>Q_i</c> is a qualifier, then Rep(E) =
+ <c>{lc,LINE,Rep(E_0),[Rep(Q_1), ..., Rep(Q_k)]}</c>. For Rep(Q), see
+ below.</item>
+ <item>If E is a map creation <c>#{A_1, ..., A_k}</c>,
+ where each <c>A_i</c> is an association <c>E_i_1 => E_i_2</c>
+ or <c>E_i_1 := E_i_2</c>, then Rep(E) =
+ <c>{map,LINE,[Rep(A_1), ..., Rep(A_k)]}</c>. For Rep(A), see
+ below.</item>
+ <item>If E is a map update <c>E_0#{A_1, ..., A_k}</c>,
+ where each <c>A_i</c> is an association <c>E_i_1 => E_i_2</c>
+ or <c>E_i_1 := E_i_2</c>, then Rep(E) =
+ <c>{map,LINE,Rep(E_0),[Rep(A_1), ..., Rep(A_k)]}</c>.
+ For Rep(A), see below.</item>
+ <item>If E is a match operator expression <c>P = E_0</c>,
+ where <c>P</c> is a pattern, then
+ Rep(E) = <c>{match,LINE,Rep(P),Rep(E_0)}</c>.</item>
+ <item>If E is nil, <c>[]</c>, then
+ Rep(E) = <c>{nil,LINE}</c>.</item>
+ <item>If E is an operator expression <c>E_1 Op E_2</c>,
+ where <c>Op</c> is a binary operator other than the match
+ operator <c>=</c>, then
+ Rep(E) = <c>{op,LINE,Op,Rep(E_1),Rep(E_2)}</c>.</item>
+ <item>If E is an operator expression <c>Op E_0</c>,
+ where <c>Op</c> is a unary operator, then
+ Rep(E) = <c>{op,LINE,Op,Rep(E_0)}</c>.</item>
+ <item>If E is a parenthesized expression <c>( E_0 )</c>, then
+ Rep(E) = <c>Rep(E_0)</c>, that is, parenthesized
+ expressions cannot be distinguished from their bodies.</item>
+ <item>If E is a receive expression <c>receive Cc_1 ; ... ; Cc_k end</c>,
+ where each <c>Cc_i</c> is a case clause then Rep(E) =
+ <c>{'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)]}</c>.</item>
+ <item>If E is a receive expression
+ <c>receive Cc_1 ; ... ; Cc_k after E_0 -> B_t end</c>,
+ where each <c>Cc_i</c> is a case clause,
+ <c>E_0</c> is an expression and <c>B_t</c> is a body, then Rep(E) =
+ <c>{'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)],Rep(E_0),Rep(B_t)}</c>.</item>
+ <item>If E is a record creation
+ <c>#Name{Field_1=E_1, ..., Field_k=E_k}</c>,
+ where each <c>Field_i</c> is an atom or <c>_</c>, then Rep(E) =
+ <c>{record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}</c>.</item>
+ <item>If E is a record field access <c>E_0#Name.Field</c>,
+ where <c>Field</c> is an atom, then
+ Rep(E) = <c>{record_field,LINE,Rep(E_0),Name,Rep(Field)}</c>.</item>
+ <item>If E is a record field index <c>#Name.Field</c>,
+ where <c>Field</c> is an atom, then
+ Rep(E) = <c>{record_index,LINE,Name,Rep(Field)}</c>.</item>
+ <item>If E is a record update
+ <c>E_0#Name{Field_1=E_1, ..., Field_k=E_k}</c>,
+ where each <c>Field_i</c> is an atom, then Rep(E) =
+ <c>{record,LINE,Rep(E_0),Name,[{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}</c>.</item>
+ <item>If E is a tuple skeleton <c>{E_1, ..., E_k}</c>, then
+ Rep(E) = <c>{tuple,LINE,[Rep(E_1), ..., Rep(E_k)]}</c>.</item>
+ <item>If E is a try expression <c>try B catch Tc_1 ; ... ; Tc_k end</c>,
where <c>B</c> is a body and each <c>Tc_i</c> is a catch clause then
Rep(E) =
<c>{'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],[]}</c>.</item>
- <item>If E is <c>try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n end</c>,
+ <item>If E is a try expression
+ <c>try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n end</c>,
where <c>B</c> is a body,
each <c>Cc_i</c> is a case clause and
each <c>Tc_j</c> is a catch clause then Rep(E) =
<c>{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., Rep(Tc_n)],[]}</c>.</item>
- <item>If E is <c>try B after A end</c>,
+ <item>If E is a try expression <c>try B after A end</c>,
where <c>B</c> and <c>A</c> are bodies then Rep(E) =
<c>{'try',LINE,Rep(B),[],[],Rep(A)}</c>.</item>
- <item>If E is <c>try B of Cc_1 ; ... ; Cc_k after A end</c>,
+ <item>If E is a try expression
+ <c>try B of Cc_1 ; ... ; Cc_k after A end</c>,
where <c>B</c> and <c>A</c> are a bodies and
each <c>Cc_i</c> is a case clause then Rep(E) =
<c>{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[],Rep(A)}</c>.</item>
- <item>If E is <c>try B catch Tc_1 ; ... ; Tc_k after A end</c>,
+ <item>If E is a try expression
+ <c>try B catch Tc_1 ; ... ; Tc_k after A end</c>,
where <c>B</c> and <c>A</c> are bodies and
each <c>Tc_i</c> is a catch clause then Rep(E) =
<c>{'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],Rep(A)}</c>.</item>
- <item>If E is <c>try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n after A end</c>,
+ <item>If E is a try expression
+ <c>try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n after A end</c>,
where <c>B</c> and <c>A</c> are a bodies,
- each <c>Cc_i</c> is a case clause and
+ each <c>Cc_i</c> is a case clause, and
each <c>Tc_j</c> is a catch clause then
Rep(E) =
<c>{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., Rep(Tc_n)],Rep(A)}</c>.</item>
- <item>If E is <c>receive Cc_1 ; ... ; Cc_k end</c>,
- where each <c>Cc_i</c> is a case clause then Rep(E) =
- <c>{'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)]}</c>.</item>
- <item>If E is <c>receive Cc_1 ; ... ; Cc_k after E_0 -> B_t end</c>,
- where each <c>Cc_i</c> is a case clause,
- <c>E_0</c> is an expression and <c>B_t</c> is a body, then Rep(E) =
- <c>{'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)],Rep(E_0),Rep(B_t)}</c>.</item>
- <item>If E is <c>fun Name / Arity</c>, then
- Rep(E) = <c>{'fun',LINE,{function,Name,Arity}}</c>.</item>
- <item>If E is <c>fun Module:Name/Arity</c>, then Rep(E) =
- <c>{'fun',LINE,{function,Rep(Module),Rep(Name),Rep(Arity)}}</c>.
- (Before the R15 release: Rep(E) =
- <c>{'fun',LINE,{function,Module,Name,Arity}}</c>.)</item>
- <item>If E is <c>fun Fc_1 ; ... ; Fc_k end</c>
- where each <c>Fc_i</c> is a function clause then Rep(E) =
- <c>{'fun',LINE,{clauses,[Rep(Fc_1), ..., Rep(Fc_k)]}}</c>.</item>
- <item>If E is <c>fun Name Fc_1 ; ... ; Name Fc_k end</c>
- where <c>Name</c> is a variable and each
- <c>Fc_i</c> is a function clause then Rep(E) =
- <c>{named_fun,LINE,Name,[Rep(Fc_1), ..., Rep(Fc_k)]}</c>.
- </item>
- <item>If E is <c>( E_0 )</c>, then
- Rep(E) = <c>Rep(E_0)</c>, that is, parenthesized
- expressions cannot be distinguished from their bodies.</item>
+ <item>If E is a variable <c>V</c>, then Rep(E) = <c>{var,LINE,A}</c>,
+ where <c>A</c> is an atom with a printname consisting of the same
+ characters as <c>V</c>.</item>
</list>
<section>
- <title>Generators and Filters</title>
- <p>When W is a generator or a filter (in the body of a list or
- binary comprehension), then:</p>
+ <title>Qualifiers</title>
+ <p>A qualifier Q is one of the following alternatives:</p>
<list type="bulleted">
- <item>If W is a generator <c>P &lt;- E</c>, where <c>P</c> is
+ <item>If Q is a filter <c>E</c>, where <c>E</c> is an expression, then
+ Rep(Q) = <c>Rep(E)</c>.</item>
+ <item>If Q is a generator <c>P &lt;- E</c>, where <c>P</c> is
a pattern and <c>E</c> is an expression, then
- Rep(W) = <c>{generate,LINE,Rep(P),Rep(E)}</c>.</item>
- <item>If W is a generator <c>P &lt;= E</c>, where <c>P</c> is
+ Rep(Q) = <c>{generate,LINE,Rep(P),Rep(E)}</c>.</item>
+ <item>If Q is a bit string generator
+ <c>P &lt;= E</c>, where <c>P</c> is
a pattern and <c>E</c> is an expression, then
- Rep(W) = <c>{b_generate,LINE,Rep(P),Rep(E)}</c>.</item>
- <item>If W is a filter <c>E</c>, which is an expression, then
- Rep(W) = <c>Rep(E)</c>.</item>
+ Rep(Q) = <c>{b_generate,LINE,Rep(P),Rep(E)}</c>.</item>
</list>
</section>
<section>
- <title>Binary Element Type Specifiers</title>
- <p>A type specifier list TSL for a binary element is a sequence of type
- specifiers <c>TS_1 - ... - TS_k</c>.
+ <title>Bit String Element Type Specifiers</title>
+ <p>A type specifier list TSL for a bit string element is a sequence
+ of type specifiers <c>TS_1 - ... - TS_k</c>, and
Rep(TSL) = <c>[Rep(TS_1), ..., Rep(TS_k)]</c>.</p>
- <p>When TS is a type specifier for a binary element, then:</p>
<list type="bulleted">
- <item>If TS is an atom <c>A</c>, then Rep(TS) = <c>A</c>.</item>
- <item>If TS is a couple <c>A:Value</c> where <c>A</c> is an atom
- and <c>Value</c> is an integer, then Rep(TS) =
- <c>{A,Value}</c>.</item>
+ <item>If TS is a type specifier <c>A</c>, where <c>A</c> is an atom,
+ then Rep(TS) = <c>A</c>.</item>
+ <item>If TS is a type specifier <c>A:Value</c>,
+ where <c>A</c> is an atom and <c>Value</c> is an integer,
+ then Rep(TS) = <c>{A,Value}</c>.</item>
</list>
</section>
<section>
- <title>Map Assoc and Exact Fields</title>
- <p>When W is an assoc or exact field (in the body of a map), then:</p>
+ <title>Associations</title>
+ <p>An association A is one of the following alternatives:</p>
<list type="bulleted">
- <item>If W is an assoc field <c>K => V</c>, where
- <c>K</c> and <c>V</c> are both expressions,
- then Rep(W) = <c>{map_field_assoc,LINE,Rep(K),Rep(V)}</c>.
+ <item>If A is an association <c>K => V</c>,
+ then Rep(A) = <c>{map_field_assoc,LINE,Rep(K),Rep(V)}</c>.
</item>
- <item>If W is an exact field <c>K := V</c>, where
- <c>K</c> and <c>V</c> are both expressions,
- then Rep(W) = <c>{map_field_exact,LINE,Rep(K),Rep(V)}</c>.
+ <item>If A is an association <c>K := V</c>,
+ then Rep(A) = <c>{map_field_exact,LINE,Rep(K),Rep(V)}</c>.
</item>
</list>
</section>
@@ -398,39 +428,39 @@
and catch clauses.</p>
<p>A clause <c>C</c> is one of the following alternatives:</p>
<list type="bulleted">
- <item>If C is a function clause <c>( Ps ) -> B</c>
- where <c>Ps</c> is a pattern sequence and <c>B</c> is a body, then
- Rep(C) = <c>{clause,LINE,Rep(Ps),[],Rep(B)}</c>.</item>
- <item>If C is a function clause <c>( Ps ) when Gs -> B</c>
- where <c>Ps</c> is a pattern sequence,
- <c>Gs</c> is a guard sequence and <c>B</c> is a body, then
- Rep(C) = <c>{clause,LINE,Rep(Ps),Rep(Gs),Rep(B)}</c>.</item>
- <item>If C is an if clause <c>Gs -> B</c>
- where <c>Gs</c> is a guard sequence and <c>B</c> is a body, then
- Rep(C) = <c>{clause,LINE,[],Rep(Gs),Rep(B)}</c>.</item>
- <item>If C is a case clause <c>P -> B</c>
+ <item>If C is a case clause <c>P -> B</c>,
where <c>P</c> is a pattern and <c>B</c> is a body, then
Rep(C) = <c>{clause,LINE,[Rep(P)],[],Rep(B)}</c>.</item>
- <item>If C is a case clause <c>P when Gs -> B</c>
+ <item>If C is a case clause <c>P when Gs -> B</c>,
where <c>P</c> is a pattern,
<c>Gs</c> is a guard sequence and <c>B</c> is a body, then
Rep(C) = <c>{clause,LINE,[Rep(P)],Rep(Gs),Rep(B)}</c>.</item>
- <item>If C is a catch clause <c>P -> B</c>
+ <item>If C is a catch clause <c>P -> B</c>,
where <c>P</c> is a pattern and <c>B</c> is a body, then
Rep(C) = <c>{clause,LINE,[Rep({throw,P,_})],[],Rep(B)}</c>.</item>
- <item>If C is a catch clause <c>X : P -> B</c>
+ <item>If C is a catch clause <c>X : P -> B</c>,
where <c>X</c> is an atomic literal or a variable pattern,
- <c>P</c> is a pattern and <c>B</c> is a body, then
+ <c>P</c> is a pattern, and <c>B</c> is a body, then
Rep(C) = <c>{clause,LINE,[Rep({X,P,_})],[],Rep(B)}</c>.</item>
- <item>If C is a catch clause <c>P when Gs -> B</c>
- where <c>P</c> is a pattern, <c>Gs</c> is a guard sequence
+ <item>If C is a catch clause <c>P when Gs -> B</c>,
+ where <c>P</c> is a pattern, <c>Gs</c> is a guard sequence,
and <c>B</c> is a body, then
Rep(C) = <c>{clause,LINE,[Rep({throw,P,_})],Rep(Gs),Rep(B)}</c>.</item>
- <item>If C is a catch clause <c>X : P when Gs -> B</c>
+ <item>If C is a catch clause <c>X : P when Gs -> B</c>,
where <c>X</c> is an atomic literal or a variable pattern,
- <c>P</c> is a pattern, <c>Gs</c> is a guard sequence
+ <c>P</c> is a pattern, <c>Gs</c> is a guard sequence,
and <c>B</c> is a body, then
Rep(C) = <c>{clause,LINE,[Rep({X,P,_})],Rep(Gs),Rep(B)}</c>.</item>
+ <item>If C is a function clause <c>( Ps ) -> B</c>,
+ where <c>Ps</c> is a pattern sequence and <c>B</c> is a body, then
+ Rep(C) = <c>{clause,LINE,Rep(Ps),[],Rep(B)}</c>.</item>
+ <item>If C is a function clause <c>( Ps ) when Gs -> B</c>,
+ where <c>Ps</c> is a pattern sequence,
+ <c>Gs</c> is a guard sequence and <c>B</c> is a body, then
+ Rep(C) = <c>{clause,LINE,Rep(Ps),Rep(Gs),Rep(B)}</c>.</item>
+ <item>If C is an if clause <c>Gs -> B</c>,
+ where <c>Gs</c> is a guard sequence and <c>B</c> is a body, then
+ Rep(C) = <c>{clause,LINE,[],Rep(Gs),Rep(B)}</c>.</item>
</list>
</section>
@@ -444,46 +474,61 @@
<c>[Rep(Gt_1), ..., Rep(Gt_k)]</c>.</p>
<p>A guard test <c>Gt</c> is one of the following alternatives:</p>
<list type="bulleted">
- <item>If Gt is an atomic literal L, then Rep(Gt) = Rep(L).</item>
- <item>If Gt is a variable pattern <c>V</c>, then
- Rep(Gt) = <c>{var,LINE,A}</c>, where A is an atom with
- a printname consisting of the same characters as <c>V</c>.</item>
- <item>If Gt is a tuple skeleton <c>{Gt_1, ..., Gt_k}</c>, then
- Rep(Gt) = <c>{tuple,LINE,[Rep(Gt_1), ..., Rep(Gt_k)]}</c>.</item>
- <item>If Gt is <c>[]</c>, then Rep(Gt) = <c>{nil,LINE}</c>.</item>
- <item>If Gt is a cons skeleton <c>[Gt_h | Gt_t]</c>, then
- Rep(Gt) = <c>{cons,LINE,Rep(Gt_h),Rep(Gt_t)}</c>.</item>
- <item>If Gt is a binary constructor
- <c>&lt;&lt;Gt_1:Size_1/TSL_1, ..., Gt_k:Size_k/TSL_k>></c>, then
+ <item>If Gt is an atomic literal <c>L</c>, then Rep(Gt) = Rep(L).</item>
+ <item>If Gt is a bit string constructor
+ <c>&lt;&lt;Gt_1:Size_1/TSL_1, ..., Gt_k:Size_k/TSL_k>></c>,
+ where each <c>Size_i</c> is a guard test and each
+ <c>TSL_i</c> is a type specificer list, then
Rep(Gt) = <c>{bin,LINE,[{bin_element,LINE,Rep(Gt_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(Gt_k),Rep(Size_k),Rep(TSL_k)}]}</c>.
For Rep(TSL), see above.
- An omitted <c>Size</c> is represented by <c>default</c>.
- An omitted <c>TSL</c> (type specifier list) is represented
- by <c>default</c>.</item>
- <item>If Gt is <c>Gt_1 Op Gt_2</c>, where <c>Op</c>
- is a binary operator, then Rep(Gt) =
- <c>{op,LINE,Op,Rep(Gt_1),Rep(Gt_2)}</c>.</item>
- <item>If Gt is <c>Op Gt_0</c>, where <c>Op</c> is a unary operator, then
+ An omitted <c>Size_i</c> is represented by <c>default</c>.
+ An omitted <c>TSL_i</c> is represented by <c>default</c>.</item>
+ <item>If Gt is a cons skeleton <c>[Gt_h | Gt_t]</c>, then
+ Rep(Gt) = <c>{cons,LINE,Rep(Gt_h),Rep(Gt_t)}</c>.</item>
+ <item>If Gt is a function call <c>A(Gt_1, ..., Gt_k)</c>,
+ where <c>A</c> is an atom, then Rep(Gt) =
+ <c>{call,LINE,Rep(A),[Rep(Gt_1), ..., Rep(Gt_k)]}</c>.</item>
+ <item>If Gt is a function call <c>A_m:A(Gt_1, ..., Gt_k)</c>,
+ where <c>A_m</c> is the atom <c>erlang</c> and <c>A</c> is
+ an atom or an operator, then Rep(Gt) =
+ <c>{call,LINE,{remote,LINE,Rep(A_m),Rep(A)},[Rep(Gt_1), ..., Rep(Gt_k)]}</c>.</item>
+ <item>If Gt is a map creation <c>#{A_1, ..., A_k}</c>,
+ where each <c>A_i</c> is an association <c>Gt_i_1 => Gt_i_2</c>
+ or <c>Gt_i_1 := Gt_i_2</c>, then Rep(Gt) =
+ <c>{map,LINE,[Rep(A_1), ..., Rep(A_k)]}</c>. For Rep(A), see
+ above.</item>
+ <item>If Gt is a map update <c>Gt_0#{A_1, ..., A_k}</c>, where each
+ <c>A_i</c> is an association <c>Gt_i_1 => Gt_i_2</c>
+ or <c>Gt_i_1 := Gt_i_2</c>, then Rep(Gt) =
+ <c>{map,LINE,Rep(Gt_0),[Rep(A_1), ..., Rep(A_k)]}</c>.
+ For Rep(A), see above.</item>
+ <item>If Gt is nil, <c>[]</c>,
+ then Rep(Gt) = <c>{nil,LINE}</c>.</item>
+ <item>If Gt is an operator guard test <c>Gt_1 Op Gt_2</c>,
+ where <c>Op</c> is a binary operator other than the match
+ operator <c>=</c>, then
+ Rep(Gt) = <c>{op,LINE,Op,Rep(Gt_1),Rep(Gt_2)}</c>.</item>
+ <item>If Gt is an operator guard test <c>Op Gt_0</c>,
+ where <c>Op</c> is a unary operator, then
Rep(Gt) = <c>{op,LINE,Op,Rep(Gt_0)}</c>.</item>
- <item>If Gt is <c>#Name{Field_1=Gt_1, ..., Field_k=Gt_k}</c>, then
- Rep(E) =
- <c>{record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(Gt_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(Gt_k)}]}</c>.</item>
- <item>If Gt is <c>#Name.Field</c>, then
- Rep(Gt) = <c>{record_index,LINE,Name,Rep(Field)}</c>.</item>
- <item>If Gt is <c>Gt_0#Name.Field</c>, then
- Rep(Gt) = <c>{record_field,LINE,Rep(Gt_0),Name,Rep(Field)}</c>.</item>
- <item>If Gt is <c>A(Gt_1, ..., Gt_k)</c>, where <c>A</c> is an atom, then
- Rep(Gt) = <c>{call,LINE,Rep(A),[Rep(Gt_1), ..., Rep(Gt_k)]}</c>.</item>
- <item>If Gt is <c>A_m:A(Gt_1, ..., Gt_k)</c>, where <c>A_m</c> is
- the atom <c>erlang</c> and <c>A</c> is an atom or an operator, then
- Rep(Gt) = <c>{call,LINE,{remote,LINE,Rep(A_m),Rep(A)},[Rep(Gt_1), ..., Rep(Gt_k)]}</c>.</item>
- <item>If Gt is <c>{A_m,A}(Gt_1, ..., Gt_k)</c>, where <c>A_m</c> is
- the atom <c>erlang</c> and <c>A</c> is an atom or an operator, then
- Rep(Gt) = <c>{call,LINE,Rep({A_m,A}),[Rep(Gt_1), ..., Rep(Gt_k)]}</c>.
- </item>
- <item>If Gt is <c>( Gt_0 )</c>, then
+ <item>If Gt is a parenthesized guard test <c>( Gt_0 )</c>, then
Rep(Gt) = <c>Rep(Gt_0)</c>, that is, parenthesized
guard tests cannot be distinguished from their bodies.</item>
+ <item>If Gt is a record creation
+ <c>#Name{Field_1=Gt_1, ..., Field_k=Gt_k}</c>,
+ where each <c>Field_i</c> is an atom or <c>_</c>, then Rep(Gt) =
+ <c>{record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(Gt_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(Gt_k)}]}</c>.</item>
+ <item>If Gt is a record field access <c>Gt_0#Name.Field</c>,
+ where <c>Field</c> is an atom, then
+ Rep(Gt) = <c>{record_field,LINE,Rep(Gt_0),Name,Rep(Field)}</c>.</item>
+ <item>If Gt is a record field index <c>#Name.Field</c>,
+ where <c>Field</c> is an atom, then
+ Rep(Gt) = <c>{record_index,LINE,Name,Rep(Field)}</c>.</item>
+ <item>If Gt is a tuple skeleton <c>{Gt_1, ..., Gt_k}</c>, then
+ Rep(Gt) = <c>{tuple,LINE,[Rep(Gt_1), ..., Rep(Gt_k)]}</c>.</item>
+ <item>If Gt is a variable pattern <c>V</c>, then
+ Rep(Gt) = <c>{var,LINE,A}</c>, where A is an atom with
+ a printname consisting of the same characters as <c>V</c>.</item>
</list>
<p>Note that every guard test has the same source form as some expression,
and is represented the same way as the corresponding expression.</p>
@@ -492,91 +537,83 @@
<section>
<title>Types</title>
<list type="bulleted">
- <item>If T is an annotated type <c>Anno :: Type</c>,
- where <c>Anno</c> is a variable and
- <c>Type</c> is a type, then Rep(T) =
- <c>{ann_type,LINE,[Rep(Anno),Rep(Type)]}</c>.</item>
+ <item>If T is an annotated type <c>A :: T_0</c>,
+ where <c>A</c> is a variable, then Rep(T) =
+ <c>{ann_type,LINE,[Rep(A),Rep(T_0)]}</c>.</item>
<item>If T is an atom or integer literal L, then Rep(T) = Rep(L).
</item>
- <item>If T is <c>L Op R</c>,
- where <c>Op</c> is a binary operator and <c>L</c> and <c>R</c>
- are types (this is an occurrence of an expression that can be
- evaluated to an integer at compile time), then
- Rep(T) = <c>{op,LINE,Op,Rep(L),Rep(R)}</c>.</item>
- <item>If T is <c>Op A</c>, where <c>Op</c> is a
- unary operator and <c>A</c> is a type (this is an occurrence of
- an expression that can be evaluated to an integer at compile time),
- then Rep(T) = <c>{op,LINE,Op,Rep(A)}</c>.</item>
- <item>If T is a bitstring type <c>&lt;&lt;_:M,_:_*N>></c>,
+ <item>If T is a bit string type <c>&lt;&lt;_:M,_:_*N>></c>,
where <c>M</c> and <c>N</c> are singleton integer types, then Rep(T) =
<c>{type,LINE,binary,[Rep(M),Rep(N)]}</c>.</item>
<item>If T is the empty list type <c>[]</c>, then Rep(T) =
<c>{type,Line,nil,[]}</c>.</item>
<item>If T is a fun type <c>fun()</c>, then Rep(T) =
<c>{type,LINE,'fun',[]}</c>.</item>
- <item>If T is a fun type <c>fun((...) -> B)</c>,
- where <c>B</c> is a type, then
- Rep(T) = <c>{type,LINE,'fun',[{type,LINE,any},Rep(B)]}</c>.
+ <item>If T is a fun type <c>fun((...) -> T_0)</c>, then
+ Rep(T) = <c>{type,LINE,'fun',[{type,LINE,any},Rep(T_0)]}</c>.
</item>
<item>If T is a fun type <c>fun(Ft)</c>, where
<c>Ft</c> is a function type,
- then Rep(T) = <c>Rep(Ft)</c>.</item>
+ then Rep(T) = <c>Rep(Ft)</c>. For Rep(Ft), see below.</item>
<item>If T is an integer range type <c>L .. H</c>,
where <c>L</c> and <c>H</c> are singleton integer types, then
Rep(T) = <c>{type,LINE,range,[Rep(L),Rep(H)]}</c>.</item>
<item>If T is a map type <c>map()</c>, then Rep(T) =
<c>{type,LINE,map,any}</c>.</item>
- <item>If T is a map type <c>#{P_1, ..., P_k}</c>, where each
- <c>P_i</c> is a map pair type, then Rep(T) =
- <c>{type,LINE,map,[Rep(P_1), ..., Rep(P_k)]}</c>.</item>
- <item>If T is a map pair type <c>K => V</c>, where
- <c>K</c> and <c>V</c> are types, then Rep(T) =
- <c>{type,LINE,map_field_assoc,[Rep(K),Rep(V)]}</c>.</item>
- <item>If T is a predefined (or built-in) type <c>N(A_1, ..., A_k)</c>,
- where each <c>A_i</c> is a type, then Rep(T) =
- <c>{type,LINE,N,[Rep(A_1), ..., Rep(A_k)]}</c>.</item>
+ <item>If T is a map type <c>#{A_1, ..., A_k}</c>, where each
+ <c>A_i</c> is an association type, then Rep(T) =
+ <c>{type,LINE,map,[Rep(A_1), ..., Rep(A_k)]}</c>.
+ For Rep(A), see below.</item>
+ <item>If T is an operator type <c>T_1 Op T_2</c>,
+ where <c>Op</c> is a binary operator (this is an occurrence of
+ an expression that can be evaluated to an integer at compile
+ time), then
+ Rep(T) = <c>{op,LINE,Op,Rep(T_1),Rep(T_2)}</c>.</item>
+ <item>If T is an operator type <c>Op T_0</c>, where <c>Op</c> is a
+ unary operator (this is an occurrence of
+ an expression that can be evaluated to an integer at compile time),
+ then Rep(T) = <c>{op,LINE,Op,Rep(T_0)}</c>.</item>
+ <item>If T is <c>( T_0 )</c>, then Rep(T) = <c>Rep(T_0)</c>,
+ that is, parenthesized types cannot be distinguished from their
+ bodies.</item>
+ <item>If T is a predefined (or built-in) type <c>N(T_1, ..., T_k)</c>,
+ then Rep(T) =
+ <c>{type,LINE,N,[Rep(T_1), ..., Rep(T_k)]}</c>.</item>
<item>If T is a record type <c>#Name{F_1, ..., F_k}</c>,
where each <c>F_i</c> is a record field type, then Rep(T) =
<c>{type,LINE,record,[Rep(Name),Rep(F_1), ..., Rep(F_k)]}</c>.
- </item>
- <item>If T is a record field type <c>Name :: Type</c>,
- where <c>Type</c> is a type, then Rep(T) =
- <c>{type,LINE,field_type,[Rep(Name),Rep(Type)]}</c>.</item>
- <item>If T is a remote type <c>M:N(A_1, ..., A_k)</c>, where
- each <c>A_i</c> is a type, then Rep(T) =
- <c>{remote_type,LINE,[Rep(M),Rep(N),[Rep(A_1), ..., Rep(A_k)]]}</c>.
+ For Rep(F), see below.</item>
+ <item>If T is a remote type <c>M:N(T_1, ..., T_k)</c>, then Rep(T) =
+ <c>{remote_type,LINE,[Rep(M),Rep(N),[Rep(T_1), ..., Rep(T_k)]]}</c>.
</item>
<item>If T is a tuple type <c>tuple()</c>, then Rep(T) =
<c>{type,LINE,tuple,any}</c>.</item>
- <item>If T is a tuple type <c>{A_1, ..., A_k}</c>, where
- each <c>A_i</c> is a type, then Rep(T) =
- <c>{type,LINE,tuple,[Rep(A_1), ..., Rep(A_k)]}</c>.</item>
- <item>If T is a type union <c>T_1 | ... | T_k</c>,
- where each <c>T_i</c> is a type, then Rep(T) =
+ <item>If T is a tuple type <c>{T_1, ..., T_k}</c>, then Rep(T) =
+ <c>{type,LINE,tuple,[Rep(T_1), ..., Rep(T_k)]}</c>.</item>
+ <item>If T is a type union <c>T_1 | ... | T_k</c>, then Rep(T) =
<c>{type,LINE,union,[Rep(T_1), ..., Rep(T_k)]}</c>.</item>
<item>If T is a type variable <c>V</c>, then Rep(T) =
<c>{var,LINE,A}</c>, where <c>A</c> is an atom with a printname
consisting of the same characters as <c>V</c>. A type variable
is any variable except underscore (<c>_</c>).</item>
- <item>If T is a user-defined type <c>N(A_1, ..., A_k)</c>,
- where each <c>A_i</c> is a type, then Rep(T) =
- <c>{user_type,LINE,N,[Rep(A_1), ..., Rep(A_k)]}</c>.</item>
- <item>If T is <c>( T_0 )</c>, then Rep(T) = <c>Rep(T_0)</c>,
- that is, parenthesized types cannot be distinguished from their
- bodies.</item>
+ <item>If T is a user-defined type <c>N(T_1, ..., T_k)</c>,
+ then Rep(T) =
+ <c>{user_type,LINE,N,[Rep(T_1), ..., Rep(T_k)]}</c>.</item>
</list>
<section>
<title>Function Types</title>
+ <p>A function type Ft is one of the following alternatives:</p>
<list type="bulleted">
<item>If Ft is a constrained function type <c>Ft_1 when Fc</c>,
where <c>Ft_1</c> is a function type and
<c>Fc</c> is a function constraint, then Rep(T) =
- <c>{type,LINE,bounded_fun,[Rep(Ft_1),Rep(Fc)]}</c>.</item>
- <item>If Ft is a function type <c>(A_1, ..., A_n) -> B</c>,
- where each <c>A_i</c> and <c>B</c> are types, then
- Rep(Ft) = <c>{type,LINE,'fun',[{type,LINE,product,[Rep(A_1),
- ..., Rep(A_n)]},Rep(B)]}</c>.</item>
+ <c>{type,LINE,bounded_fun,[Rep(Ft_1),Rep(Fc)]}</c>.
+ For Rep(Fc), see below.</item>
+ <item>If Ft is a function type <c>(T_1, ..., T_n) -> T_0</c>,
+ where each <c>T_i</c> is a type, then
+ Rep(Ft) = <c>{type,LINE,'fun',[{type,LINE,product,[Rep(T_1),
+ ..., Rep(T_n)]},Rep(T_0)]}</c>.</item>
</list>
</section>
@@ -592,6 +629,24 @@
</item>
</list>
</section>
+
+ <section>
+ <title>Association Types</title>
+ <list type="bulleted">
+ <item>If A is an association type <c>K => V</c>, where
+ <c>K</c> and <c>V</c> are types, then Rep(A) =
+ <c>{type,LINE,map_field_assoc,[Rep(K),Rep(V)]}</c>.</item>
+ </list>
+ </section>
+
+ <section>
+ <title>Record Field Types</title>
+ <list type="bulleted">
+ <item>If F is a record field type <c>Name :: Type</c>,
+ where <c>Type</c> is a type, then Rep(F) =
+ <c>{type,LINE,field_type,[Rep(Name),Rep(Type)]}</c>.</item>
+ </list>
+ </section>
</section>
<section>
diff --git a/erts/doc/src/driver_entry.xml b/erts/doc/src/driver_entry.xml
index bad20d6343..ae7f264d0c 100644
--- a/erts/doc/src/driver_entry.xml
+++ b/erts/doc/src/driver_entry.xml
@@ -247,14 +247,10 @@ typedef struct erl_drv_entry {
something that the <c>WaitForMultipleObjects</c> API
function understands). (Some trickery in the emulator allows
more than the built-in limit of 64 <c>Events</c> to be used.)</p>
- <p>On Enea OSE the <c>event</c> is one or more signals that can
- be retrieved using <seealso marker="ose:ose_erl_driver#erl_drv_ose_get_signal">erl_drv_ose_get_signal</seealso>.</p>
<p>To use this with threads and asynchronous routines, create a
- pipe on unix, an Event on Windows or a unique signal number on
- Enea OSE. When the routine
+ pipe on unix and an Event on Windows. When the routine
completes, write to the pipe (use <c>SetEvent</c> on
- Windows or send a message to the emulator process on Enea OSE),
- this will make the emulator call
+ Windows), this will make the emulator call
<c>ready_input</c> or <c>ready_output</c>.</p>
<p>Spurious events may happen. That is, calls to <c>ready_input</c>
or <c>ready_output</c> even though no real events are signaled. In
@@ -441,7 +437,14 @@ typedef struct erl_drv_entry {
<seealso marker="erl_driver#erl_drv_busy_msgq_limits">erl_drv_busy_msgq_limits()</seealso>
function.
</item>
- </taglist>
+ <tag><c>ERL_DRV_FLAG_USE_INIT_ACK</c></tag>
+ <item>When this flag is given the linked-in driver has to manually
+ acknowledge that the port has been successfully started using
+ <seealso marker="erl_driver#erl_drv_init_ack">erl_drv_init_ack()</seealso>.
+ This allows the implementor to make the erlang:open_port exit with
+ badarg after some initial asynchronous initialization has been done.
+ </item>
+ </taglist>
</item>
<tag>void *handle2</tag>
<item>
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index ed3e7e34c4..096af096dc 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -1361,6 +1361,21 @@
<seealso marker="kernel:error_logger#warning_map/0">error_logger(3)</seealso>
for further information.</p>
</item>
+ <tag><c><![CDATA[+xFlag Value]]></c></tag>
+ <item>
+ <p>Default process flag settings.</p>
+ <taglist>
+ <tag><marker id="+xmqd"><c>+xmqd off_heap|on_heap|mixed</c></marker></tag>
+ <item><p>
+ Sets the default value for the process flag
+ <c>message_queue_data</c>. If <c>+xmqd</c> is not
+ passed, <c>mixed</c> will be the default. For more information,
+ see the documentation of
+ <seealso marker="erlang#process_flag_message_queue_data"><c>process_flag(message_queue_data,
+ MQD)</c></seealso>.
+ </p></item>
+ </taglist>
+ </item>
<tag><c><![CDATA[+zFlag Value]]></c></tag>
<item>
<p>Miscellaneous flags.</p>
diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml
index 34dc8af238..241d4131d5 100644
--- a/erts/doc/src/erl_driver.xml
+++ b/erts/doc/src/erl_driver.xml
@@ -1077,9 +1077,7 @@ typedef struct ErlIOVec {
<c>select</c>/<c>poll</c> can use).
On windows, the Win32 API function <c>WaitForMultipleObjects</c>
is used. This places other restrictions on the event object.
- Refer to the Win32 SDK documentation.
- On Enea OSE, the receive function is used. See the <seealso
- marker="ose:ose_erl_driver"></seealso> for more details.</p>
+ Refer to the Win32 SDK documentation.</p>
<p>The <c>on</c> parameter should be <c>1</c> for setting events
and <c>0</c> for clearing them.</p>
<p>The <c>mode</c> argument is a bitwise-or combination of
@@ -1091,7 +1089,7 @@ typedef struct ErlIOVec {
<seealso marker="driver_entry#ready_output">ready_output</seealso>.
</p>
<note>
- <p>Some OS (Windows and Enea OSE) do not differentiate between read and write events.
+ <p>Some OS (Windows) do not differentiate between read and write events.
The call-back for a fired event then only depends on the value of <c>mode</c>.</p>
</note>
<p><c>ERL_DRV_USE</c> specifies if we are using the event object or if we want to close it.
@@ -2166,6 +2164,53 @@ ERL_DRV_MAP int sz
</func>
<func>
+ <name><ret>void</ret><nametext>erl_drv_init_ack(ErlDrvPort port, ErlDrvData res)</nametext></name>
+ <fsummary>Acknowledge the start of the port</fsummary>
+ <desc>
+ <marker id="erl_drv_init_ack"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>port</c></tag>
+ <item>The port handle of the port (driver instance) creating
+ doing the acknowledgment.
+ </item>
+ <tag><c>res</c></tag>
+ <item>The result of the port initialization. This can be the same values
+ as the return value of <seealso marker="driver_entry#start">start</seealso>,
+ i.e any of the error codes or the ErlDrvData that is to be used for this
+ port.
+ </item>
+ </taglist>
+ <p>
+ When this function is called the initiating erlang:open_port call is
+ returned as if the <seealso marker="driver_entry#start">start</seealso>
+ function had just been called. It can only be used when the
+ <seealso marker="driver_entry#driver_flags">ERL_DRV_FLAG_USE_INIT_ACK</seealso>
+ flag has been set on the linked-in driver.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>void</ret><nametext>erl_drv_set_os_pid(ErlDrvPort port, ErlDrvSInt pid)</nametext></name>
+ <fsummary>Set the os_pid for the port</fsummary>
+ <desc>
+ <marker id="erl_drv_set_os_pid"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>port</c></tag>
+ <item>The port handle of the port (driver instance) to set the pid on.
+ </item>
+ <tag><c>pid</c></tag>
+ <item>The pid to set.</item>
+ </taglist>
+ <p>
+ Set the os_pid seen when doing erlang:port_info/2 on this port.
+ </p>
+ </desc>
+ </func>
+
+ <func>
<name><ret>int</ret><nametext>erl_drv_thread_create(char *name,
ErlDrvTid *tid,
void * (*func)(void *),
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index 420c9fea38..be0e406b9c 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -753,7 +753,7 @@ typedef enum {
<func><name><ret>int</ret><nametext>enif_get_list_length(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len)</nametext></name>
<fsummary>Get the length of list <c>term</c></fsummary>
<desc><p>Set <c>*len</c> to the length of list <c>term</c> and return true,
- or return false if <c>term</c> is not a list.</p></desc>
+ or return false if <c>term</c> is not a proper list.</p></desc>
</func>
<func><name><ret>int</ret><nametext>enif_get_long(ErlNifEnv* env, ERL_NIF_TERM term, long int* ip)</nametext></name>
<fsummary>Read an long integer term</fsummary>
diff --git a/erts/doc/src/erl_prim_loader.xml b/erts/doc/src/erl_prim_loader.xml
index db4f132609..8f66e07ae1 100644
--- a/erts/doc/src/erl_prim_loader.xml
+++ b/erts/doc/src/erl_prim_loader.xml
@@ -50,36 +50,9 @@
<c>-loader_debug</c> are also experimental</p></warning>
</description>
- <datatypes>
- <datatype>
- <name name="host"/>
- </datatype>
- </datatypes>
<funcs>
<func>
- <name name="start" arity="3"/>
- <fsummary>Start the Erlang low level loader</fsummary>
- <desc>
- <p>Starts the Erlang low level loader. This function is called
- by the <c>init</c> process (and module). The <c>init</c>
- process reads the command line flags <c>-id <anno>Id</anno></c>,
- <c>-loader <anno>Loader</anno></c>, and <c>-hosts <anno>Hosts</anno></c>. These are
- the arguments supplied to the <c>start/3</c> function.</p>
- <p>If <c>-loader</c> is not given, the default loader is
- <c>efile</c> which tells the system to read from the file
- system.</p>
- <p>If <c>-loader</c> is <c>inet</c>, the <c>-id <anno>Id</anno></c>,
- <c>-hosts <anno>Hosts</anno></c>, and <c>-setcookie Cookie</c> flags must
- also be supplied. <c><anno>Hosts</anno></c> identifies hosts which this
- node can contact in order to load modules. One Erlang
- runtime system with a <c>erl_boot_server</c> process must be
- started on each of hosts given in <c><anno>Hosts</anno></c> in order to
- answer the requests. See <seealso
- marker="kernel:erl_boot_server">erl_boot_server(3)</seealso>.</p>
- </desc>
- </func>
- <func>
<name name="get_file" arity="1"/>
<fsummary>Get a file</fsummary>
<desc>
@@ -87,8 +60,6 @@
<c><anno>Filename</anno></c> is either an absolute file name or just the name
of the file, for example <c>"lists.beam"</c>. If an internal
path is set to the loader, this path is used to find the file.
- If a user supplied loader is used, the path can be stripped
- off if it is obsolete, and the loader does not use a path.
<c><anno>FullName</anno></c> is the complete name of the fetched file.
<c><anno>Bin</anno></c> is the contents of the file as a binary.</p>
@@ -189,17 +160,12 @@
<p>Specifies which other Erlang nodes the <c>inet</c> loader
can use. This flag is mandatory if the <c>-loader inet</c>
flag is present. On each host, there must be on Erlang node
- with the <c>erl_boot_server</c> which handles the load
- requests. <c>Hosts</c> is a list of IP addresses (hostnames
+ with the <seealso
+ marker="kernel:erl_boot_server">erl_boot_server(3)</seealso>
+ which handles the load requests.
+ <c>Hosts</c> is a list of IP addresses (hostnames
are not acceptable).</p>
</item>
- <tag><c>-id Id</c></tag>
- <item>
- <p>Specifies the identity of the Erlang runtime system. If
- the system runs as a distributed node, <c>Id</c> must be
- identical to the name supplied with the <c>-sname</c> or
- <c>-name</c> distribution flags.</p>
- </item>
<tag><c>-setcookie Cookie</c></tag>
<item>
<p>Specifies the cookie of the Erlang runtime system. This flag
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 30e6751f41..350a8506f5 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -59,6 +59,12 @@
</datatype>
<datatype>
+ <name name="message_queue_data"></name>
+ <desc><p>See <seealso marker="#process_flag_message_queue_data"><c>erlang:process_flag(message_queue_data, MQD)</c></seealso>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
<name name="timestamp"></name>
<desc><p>See <seealso marker="#timestamp/0">erlang:timestamp/0</seealso>.</p>
</desc>
@@ -125,6 +131,17 @@
</note>
</item>
+ <tag><c>perf_counter</c></tag>
+ <item><p>Symbolic representation of the performance counter
+ time unit used by the Erlang runtime system.</p>
+
+ <p>The <c>perf_counter</c> time unit behaves much in the same way
+ as the <c>native</c> time unit. That is it might differ inbetween
+ run-time restarts. You get values of this type by calling
+ <seealso marker="kernel:os#perf_counter/0"><c>os:perf_counter()</c></seealso>
+ </p>
+ </item>
+
</taglist>
<p>The <c>time_unit/0</c> type may be extended. Use
@@ -1105,7 +1122,7 @@
<fsummary>Prints a term on standard output.</fsummary>
<desc>
<p>Prints a text representation of <c><anno>Term</anno></c> on the
- standard output. On OSE, the term is printed to the ramlog.</p>
+ standard output.</p>
<warning>
<p>This BIF is intended for debugging only.</p>
</warning>
@@ -4281,9 +4298,59 @@ os_prompt% </pre>
<p>Returns the old value of the flag.</p>
</desc>
</func>
-
+ <marker id="process_flag_message_queue_data"/>
<func>
<name name="process_flag" arity="2" clause_i="5"/>
+ <fsummary>Set process flag <c>message_queue_data</c> for the calling process</fsummary>
+ <type name="message_queue_data"/>
+ <desc>
+ <p>This flag determines how messages in the message queue
+ are stored. When the flag is:</p>
+ <taglist>
+ <tag><c>off_heap</c></tag>
+ <item><p>
+ <em>All</em> messages in the message queue will be stored
+ outside of the process heap. This implies that <em>no</em>
+ messages in the message queue will be part of a garbage
+ collection of the process.
+ </p></item>
+ <tag><c>on_heap</c></tag>
+ <item><p>
+ All messages in the message queue will eventually be
+ placed on heap. They may however temporarily be stored
+ off heap. This is how messages always have been stored
+ up until ERTS version 8.0.
+ </p></item>
+ <tag><c>mixed</c></tag>
+ <item><p>
+ Messages may be placed either on the heap or outside
+ of the heap.
+ </p></item>
+ </taglist>
+ <p>
+ The default <c>message_queue_data</c> process flag is determined
+ by the <seealso marker="erl#+xmqd"><c>+xmqd</c></seealso>
+ <c>erl</c> command line argument.
+ </p>
+ <p>
+ If the process potentially may get a hugh amount of messages,
+ you are recommended to set the flag to <c>off_heap</c>. This
+ since a garbage collection with lots of messages placed on
+ the heap may become extremly expensive and the process may
+ consume large amounts of memory. Performance of the
+ actual message passing is however generally better when not
+ using the <c>off_heap</c> flag.
+ </p>
+ <p>
+ When changing this flag messages will be moved. This work
+ has been initiated but not completed when this function
+ call returns.
+ </p>
+ <p>Returns the old value of the flag.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="process_flag" arity="2" clause_i="6"/>
<fsummary>Sets process flag <c>priority</c> for the calling process.</fsummary>
<type name="priority_level"/>
<desc>
@@ -4357,7 +4424,7 @@ os_prompt% </pre>
</func>
<func>
- <name name="process_flag" arity="2" clause_i="6"/>
+ <name name="process_flag" arity="2" clause_i="7"/>
<fsummary>Sets process flag <c>save_calls</c> for the calling process.</fsummary>
<desc>
<p><c><anno>N</anno></c> must be an integer in the interval 0..10000.
@@ -4388,7 +4455,7 @@ os_prompt% </pre>
</func>
<func>
- <name name="process_flag" arity="2" clause_i="7"/>
+ <name name="process_flag" arity="2" clause_i="8"/>
<fsummary>Sets process flag <c>sensitive</c> for the calling process.</fsummary>
<desc>
<p>Sets or clears flag <c>sensitive</c> for the current process.
@@ -4442,6 +4509,7 @@ os_prompt% </pre>
<type name="process_info_result_item"/>
<type name="priority_level"/>
<type name="stack_item"/>
+ <type name="message_queue_data" />
<desc>
<p>Returns a list containing <c><anno>InfoTuple</anno></c>s with
miscellaneous information about the process identified by
@@ -4494,6 +4562,7 @@ os_prompt% </pre>
<type name="process_info_result_item"/>
<type name="stack_item"/>
<type name="priority_level"/>
+ <type name="message_queue_data" />
<desc>
<p>Returns information about the process identified by
<c><anno>Pid</anno></c>, as specified by
@@ -4585,6 +4654,17 @@ os_prompt% </pre>
The content of <c><anno>GCInfo</anno></c> can be changed without
prior notice.</p>
</item>
+ <tag><c>{garbage_collection_info, <anno>GCInfo</anno>}</c></tag>
+ <item>
+ <p><c><anno>GCInfo</anno></c> is a list containing miscellaneous
+ detailed information about garbage collection for this process.
+ The content of <c><anno>GCInfo</anno></c> can be changed without
+ prior notice.
+ See <seealso marker="#gc_start">gc_start</seealso> in
+ <seealso marker="#trace/3">erlang:trace/3</seealso> for details about
+ what each item means.
+ </p>
+ </item>
<tag><c>{group_leader, <anno>GroupLeader</anno>}</c></tag>
<item>
<p><c><anno>GroupLeader</anno></c> is group leader for the I/O of
@@ -4662,6 +4742,15 @@ os_prompt% </pre>
monitor by name, the list item is
<c>{process, {<anno>RegName</anno>, <anno>Node</anno>}}</c>.</p>
</item>
+ <tag><c>{message_queue_data, <anno>MQD</anno>}</c></tag>
+ <item>
+ <p>Returns the current state of the <c>message_queue_data</c>
+ process flag. <c><anno>MQD</anno></c> is either <c>off_heap</c>,
+ <c>on_heap</c>, or <c>mixed</c>. For more information, see the
+ documentation of
+ <seealso marker="#process_flag_message_queue_data"><c>process_flag(message_queue_data,
+ MQD)</c></seealso>.</p>
+ </item>
<tag><c>{priority, <anno>Level</anno>}</c></tag>
<item>
<p><c><anno>Level</anno></c> is the current priority level for
@@ -4804,6 +4893,12 @@ os_prompt% </pre>
<seealso marker="kernel:code">code(3)</seealso>)
and is not to be used elsewhere.</p>
</warning>
+ <note>
+ <p>As from <c>ERTS</c> 8.0 (OTP 19), any lingering processes
+ that still execute the old code will be killed by this function.
+ In earlier versions, such incorrect use could cause much
+ more fatal failures, like emulator crash.</p>
+ </note>
<p>Failure: <c>badarg</c> if there is no old code for
<c><anno>Module</anno></c>.</p>
</desc>
@@ -5430,6 +5525,8 @@ true</pre>
<name name="spawn_opt" arity="2"/>
<fsummary>Creates a new process with a fun as entry point.</fsummary>
<type name="priority_level"/>
+ <type name="message_queue_data" />
+ <type name="spawn_opt_option" />
<desc>
<p>Returns the process identifier (pid) of a new process
started by the application of <c><anno>Fun</anno></c>
@@ -5445,6 +5542,8 @@ true</pre>
<name name="spawn_opt" arity="3"/>
<fsummary>Creates a new process with a fun as entry point on a given node.</fsummary>
<type name="priority_level"/>
+ <type name="message_queue_data" />
+ <type name="spawn_opt_option" />
<desc>
<p>Returns the process identifier (pid) of a new process started
by the application of <c><anno>Fun</anno></c> to the
@@ -5459,6 +5558,8 @@ true</pre>
<name name="spawn_opt" arity="4"/>
<fsummary>Creates a new process with a function as entry point.</fsummary>
<type name="priority_level"/>
+ <type name="message_queue_data" />
+ <type name="spawn_opt_option" />
<desc>
<p>Works as
<seealso marker="#spawn/3">spawn/3</seealso>, except that an
@@ -5560,6 +5661,18 @@ true</pre>
fine-tuning an application and to measure the execution
time with various <c><anno>VSize</anno></c> values.</p>
</item>
+ <tag><c>{message_queue_data, <anno>MQD</anno>}</c></tag>
+ <item>
+ <p>Sets the state of the <c>message_queue_data</c> process
+ flag. <c><anno>MQD</anno></c> should be either <c>off_heap</c>,
+ <c>on_heap</c>, or <c>mixed</c>. The default
+ <c>message_queue_data</c> process flag is determined by the
+ <seealso marker="erl#+xmqd"><c>+xmqd</c></seealso> <c>erl</c>
+ command line argument. For more information, see the
+ documentation of
+ <seealso marker="#process_flag_message_queue_data"><c>process_flag(message_queue_data,
+ <anno>MQD</anno>)</c></seealso>.</p>
+ </item>
</taglist>
</desc>
</func>
@@ -5568,6 +5681,8 @@ true</pre>
<name name="spawn_opt" arity="5"/>
<fsummary>Creates a new process with a function as entry point on a given node.</fsummary>
<type name="priority_level"/>
+ <type name="message_queue_data" />
+ <type name="spawn_opt_option" />
<desc>
<p>Returns the process identifier (pid) of a new process started
by the application
@@ -5756,6 +5871,146 @@ true</pre>
<func>
<name name="statistics" arity="1" clause_i="6"/>
+ <fsummary>Information about microstate accounting.</fsummary>
+ <desc>
+ <marker id="statistics_microstate_accounting"></marker>
+ <p>
+ Microstate accounting can be used to measure how much time the Erlang
+ runtime system spends doing various tasks. It is designed to be as
+ lightweight as possible, but there will be some overhead when this
+ is enabled. Microstate accounting is meant to be a profiling tool
+ to help figure out performance bottlenecks.
+ To <c>start</c>/<c>stop</c>/<c>reset</c> microstate_accounting you use
+ the system_flag
+ <seealso marker="#system_flag_microstate_accounting">
+ <c>microstate_accounting</c></seealso>.
+ </p>
+ <p>
+ <c>erlang:statistics(microstate_accounting)</c> returns a list of maps
+ representing some of the OS threads within ERTS. Each map contains
+ <c>type</c> and <c>id</c> fields that can be used to identify what
+ thread it is, and also a counters field that contains data about how
+ much time has been spent in the various states.</p>
+ <pre>
+> <input>erlang:statistics(microstate_accounting).</input>
+[#{counters => #{aux => 1899182914,
+ check_io => 2605863602,
+ emulator => 45731880463,
+ gc => 1512206910,
+ other => 5421338456,
+ port => 221631,
+ sleep => 5150294100},
+ id => 1,
+ type => scheduler}|...]
+ </pre>
+ <p>The time unit is the same as returned by
+ <seealso marker="kernel:os#perf_counter/0">
+ <c>os:perf_counter/0</c></seealso>.
+ So to convert it to milliseconds you could do something like this:</p>
+ <pre>
+lists:map(
+ fun(#{ counters := Cnt } = M) ->
+ MsCnt = maps:map(fun(_K, PerfCount) ->
+ erlang:convert_time_unit(PerfCount, perf_counter, 1000)
+ end, Cnt),
+ M#{ counters := MsCnt }
+ end, erlang:statistics(microstate_accounting)).
+ </pre>
+ <p>
+ It is important to note that these values are not guaranteed to be
+ the exact time spent in each state. This is because of various
+ optimisation done in order to keep the overhead as small as possible.
+ </p>
+
+ <p>Currently the following <c><anno>MSAcc_Thread_Type</anno></c> are available:</p>
+ <taglist>
+ <tag><c>scheduler</c></tag>
+ <item>The main execution threads that do most of the work.</item>
+ <tag><c>async</c></tag><item>Async threads are used by various
+ linked-in drivers (mainly the file drivers) do offload non-cpu
+ intensive work.</item>
+ <tag><c>aux</c></tag><item>Takes care of any work that is not
+ specifically assigned to a scheduler.</item>
+ </taglist>
+ <p>Currently the following <c><anno>MSAcc_Thread_State</anno></c>s are available.
+ All states are exclusive, meaning that a thread cannot be in two states
+ at once. So if you add the numbers of all counters in a thread
+ you will get the total run-time for that thread.</p>
+ <taglist>
+ <tag><c>aux</c></tag>
+ <item>Time spent handling auxiliary jobs.</item>
+ <tag><c>check_io</c></tag>
+ <item>Time spent checking for new I/O events.</item>
+ <tag><c>emulator</c></tag>
+ <item>Time spent executing erlang processes.</item>
+ <tag><c>gc</c></tag>
+ <item>Time spent doing garbage collection. When extra states are
+ enabled this is the time spent doing non-fullsweep garbage
+ collections.</item>
+ <tag><c>other</c></tag>
+ <item>Time spent doing unaccounted things.</item>
+ <tag><c>port</c></tag>
+ <item>Time spent executing ports.</item>
+ <tag><c>sleep</c></tag>
+ <item>Time spent sleeping.</item>
+ </taglist>
+ <p>It is possible to add more fine grained <c><anno>MSAcc_Thread_State</anno></c>s
+ through configure.
+ (e.g. <c>./configure --with-microstate-accounting=extra</c>).
+ Enabling these states will cause a performance degradation when
+ microstate accounting is turned off and increase the overhead when
+ it is turned on.</p>
+ <taglist>
+ <tag><c>alloc</c></tag>
+ <item>Time spent managing memory. Without extra states this time is
+ spread out over all other states.</item>
+ <tag><c>bif</c></tag>
+ <item>Time spent in bifs. Without extra states this time is part of
+ the <c>emulator</c> state.</item>
+ <tag><c>busy_wait</c></tag>
+ <item>Time spent busy waiting. This is also the state where a
+ scheduler no longer reports that it is active when using
+ <seealso marker="#statistics_scheduler_wall_time">
+ <c>erlang:statistics(scheduler_wall_time)</c></seealso>.
+ So if you add all other states but this and sleep and then divide that
+ by all time in the thread you should get something very similar to the
+ scheduler_wall_time fraction. Without extra states this time is part
+ of the <c>other</c> state.</item>
+ <tag><c>ets</c></tag>
+ <item>Time spent executing ETS bifs. Without extra states this time is
+ part of the <c>emulator</c> state.</item>
+ <tag><c>gc_full</c></tag>
+ <item>Time spent doing fullsweep garbage collection. Without extra
+ states this time is part of the <c>gc</c> state.</item>
+ <tag><c>nif</c></tag>
+ <item>Time spent in nifs. Without extra states this time is part of
+ the <c>emulator</c> state.</item>
+ <tag><c>send</c></tag>
+ <item>Time spent sending messages (processes only). Without extra
+ states this time is part of the <c>emulator</c> state.</item>
+ <tag><c>timers</c></tag>
+ <item>Time spent managing timers. Without extra states this time is
+ part of the <c>other</c> state.</item>
+ </taglist>
+ <p>There is a utility module called
+ <seealso marker="runtime_tools:msacc"><c>msacc</c></seealso> in
+ runtime_tools that can be used to more easily analyse these
+ statistics.</p>
+
+ <p>
+ Returns <c>undefined</c> if the system flag
+ <seealso marker="#system_flag_microstate_accounting">
+ <c>microstate_accounting</c></seealso>
+ is turned off.
+ </p>
+ <p>The list of thread information is unsorted and may appear in
+ different order between calls.</p>
+ <note><p>The threads and states are subject to change without any
+ prior notice.</p></note>
+ </desc>
+ </func>
+ <func>
+ <name name="statistics" arity="1" clause_i="7"/>
<fsummary>Information about reductions.</fsummary>
<desc>
<marker id="statistics_reductions"></marker>
@@ -5773,7 +6028,7 @@ true</pre>
</func>
<func>
- <name name="statistics" arity="1" clause_i="7"/>
+ <name name="statistics" arity="1" clause_i="8"/>
<fsummary>Information about the run-queues.</fsummary>
<desc><marker id="statistics_run_queue"></marker>
<p>
@@ -5789,7 +6044,7 @@ true</pre>
</func>
<func>
- <name name="statistics" arity="1" clause_i="8"/>
+ <name name="statistics" arity="1" clause_i="9"/>
<fsummary>Information about the run-queue lengths.</fsummary>
<desc><marker id="statistics_run_queue_lengths"></marker>
<p>
@@ -5809,7 +6064,7 @@ true</pre>
</func>
<func>
- <name name="statistics" arity="1" clause_i="9"/>
+ <name name="statistics" arity="1" clause_i="10"/>
<fsummary>Information about runtime.</fsummary>
<desc>
<p>Returns information about runtime, in milliseconds.</p>
@@ -5824,7 +6079,7 @@ true</pre>
</func>
<func>
- <name name="statistics" arity="1" clause_i="10"/>
+ <name name="statistics" arity="1" clause_i="11"/>
<fsummary>Information about each schedulers work time.</fsummary>
<desc>
<marker id="statistics_scheduler_wall_time"></marker>
@@ -5895,7 +6150,7 @@ ok
</func>
<func>
- <name name="statistics" arity="1" clause_i="11"/>
+ <name name="statistics" arity="1" clause_i="12"/>
<fsummary>Information about active processes and ports.</fsummary>
<desc><marker id="statistics_total_active_tasks"></marker>
<p>
@@ -5913,7 +6168,7 @@ ok
</func>
<func>
- <name name="statistics" arity="1" clause_i="12"/>
+ <name name="statistics" arity="1" clause_i="13"/>
<fsummary>Information about the run-queue lengths.</fsummary>
<desc><marker id="statistics_total_run_queue_lengths"></marker>
<p>
@@ -5932,7 +6187,7 @@ ok
</func>
<func>
- <name name="statistics" arity="1" clause_i="13"/>
+ <name name="statistics" arity="1" clause_i="14"/>
<fsummary>Information about wall clock.</fsummary>
<desc>
<p>Returns information about wall clock. <c>wall_clock</c> can
@@ -6166,6 +6421,17 @@ ok
<func>
<name name="system_flag" arity="2" clause_i="5"/>
+ <fsummary>Set system flag microstate_accounting</fsummary>
+ <desc><p><marker id="system_flag_microstate_accounting"></marker>
+ Turns on/off microstate accounting measurements. By passing reset it is possible to reset
+ all counters to 0.</p>
+ <p>For more information see,
+ <seealso marker="#statistics_microstate_accounting">erlang:statistics(microstate_accounting)</seealso>.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="system_flag" arity="2" clause_i="6"/>
<fsummary>Sets system flag <c>min_heap_size</c>.</fsummary>
<desc>
<p>Sets the default minimum heap size for processes. The size
@@ -6180,7 +6446,7 @@ ok
</func>
<func>
- <name name="system_flag" arity="2" clause_i="6"/>
+ <name name="system_flag" arity="2" clause_i="7"/>
<fsummary>Sets system flag <c>min_bin_vheap_size</c>.</fsummary>
<desc>
<p>Sets the default minimum binary virtual heap size for
@@ -6197,45 +6463,57 @@ ok
</func>
<func>
- <name name="system_flag" arity="2" clause_i="7"/>
+ <name name="system_flag" arity="2" clause_i="8"/>
<fsummary>Sets system flag <c>multi_scheduling</c>.</fsummary>
<desc>
<p><marker id="system_flag_multi_scheduling"></marker>
If multi-scheduling is enabled, more than one scheduler
thread is used by the emulator. Multi-scheduling can be
- blocked. When multi-scheduling is blocked, only
- one scheduler thread schedules Erlang processes.</p>
+ blocked in two different ways. Either all schedulers but
+ one is blocked, or all <em>normal</em> schedulers but
+ one is blocked. When only normal schedulers are blocked
+ dirty schedulers are free to continue to schedule
+ processes.</p>
<p>If <c><anno>BlockState</anno> =:= block</c>, multi-scheduling is
- blocked. If <c><anno>BlockState</anno> =:= unblock</c> and no one
+ blocked. That is, one and only one scheduler thread will
+ execute. If <c><anno>BlockState</anno> =:= unblock</c> and no one
else blocks multi-scheduling, and this process has
blocked only once, multi-scheduling is unblocked.</p>
- <p>One process can block multi-scheduling multiple times.
- If a process has blocked multiple times, it must
- unblock exactly as many times as it has blocked before it
- has released its multi-scheduling block. If a process that
- has blocked multi-scheduling exits, it releases its
- blocking of multi-scheduling.</p>
+ <p>If <c><anno>BlockState</anno> =:= block_normal</c>, normal
+ multi-scheduling is blocked. That is, only one normal scheduler
+ thread will execute, but multiple dirty schedulers may execute.
+ If <c><anno>BlockState</anno> =:= unblock_normal</c> and no one
+ else blocks normal multi-scheduling, and this process has
+ blocked only once, normal multi-scheduling is unblocked.</p>
+ <p>One process can block multi-scheduling as well as normal
+ multi-scheduling multiple times. If a process has blocked
+ multiple times, it must unblock exactly as many times as it
+ has blocked before it has released its multi-scheduling
+ block. If a process that has blocked multi-scheduling or normal
+ multi scheduling exits, it automatically releases its blocking
+ of multi-scheduling and normal multi-scheduling.</p>
<p>The return values are <c>disabled</c>, <c>blocked</c>,
- or <c>enabled</c>. The returned value describes the
- state just after the call to
+ <c>blocked_normal</c>, or <c>enabled</c>. The returned value
+ describes the state just after the call to
<c>erlang:system_flag(multi_scheduling, <anno>BlockState</anno>)</c>
has been made. For information about the return values, see
<seealso marker="#system_info_multi_scheduling">erlang:system_info(multi_scheduling)</seealso>.</p>
- <note><p>Blocking of multi-scheduling is normally not needed.
- If you feel that you need to block multi-scheduling,
- consider it a few more times again. Blocking multi-scheduling
- is only to be used as a last resort, as it is most likely
- a <em>very inefficient</em> way to solve the problem.</p>
+ <note><p>Blocking of multi-scheduling and normal multi-scheduling
+ is normally not needed. If you feel that you need to use these
+ features, consider it a few more times again. Blocking
+ multi-scheduling is only to be used as a last resort, as it is
+ most likely a <em>very inefficient</em> way to solve the problem.</p>
</note>
<p>See also
<seealso marker="#system_info_multi_scheduling">erlang:system_info(multi_scheduling)</seealso>,
+ <seealso marker="#system_info_normal_multi_scheduling_blockers">erlang:system_info(normal_multi_scheduling_blockers)</seealso>,
<seealso marker="#system_info_multi_scheduling_blockers">erlang:system_info(multi_scheduling_blockers)</seealso>, and
<seealso marker="#system_info_schedulers">erlang:system_info(schedulers)</seealso>.</p>
</desc>
</func>
<func>
- <name name="system_flag" arity="2" clause_i="8"/>
+ <name name="system_flag" arity="2" clause_i="9"/>
<fsummary>Sets system flag <c>scheduler_bind_type</c>.</fsummary>
<type name="scheduler_bind_type"/>
<desc>
@@ -6353,7 +6631,7 @@ ok
</func>
<func>
- <name name="system_flag" arity="2" clause_i="9"/>
+ <name name="system_flag" arity="2" clause_i="10"/>
<fsummary>Sets system flag <c>scheduler_wall_time</c>.</fsummary>
<desc><p><marker id="system_flag_scheduler_wall_time"></marker>
Turns on or off scheduler wall time measurements.</p>
@@ -6363,7 +6641,7 @@ ok
</func>
<func>
- <name name="system_flag" arity="2" clause_i="10"/>
+ <name name="system_flag" arity="2" clause_i="11"/>
<fsummary>Sets system flag <c>schedulers_online</c>.</fsummary>
<desc>
<p><marker id="system_flag_schedulers_online"></marker>
@@ -6388,7 +6666,7 @@ ok
</func>
<func>
- <name name="system_flag" arity="2" clause_i="11"/>
+ <name name="system_flag" arity="2" clause_i="12"/>
<fsummary>Sets system flag <c>trace_control_word</c>.</fsummary>
<desc>
<p>Sets the value of the node trace control word to
@@ -6727,6 +7005,7 @@ ok
<name name="system_info" arity="1" clause_i="65"/>
<name name="system_info" arity="1" clause_i="66"/>
<name name="system_info" arity="1" clause_i="67"/>
+ <name name="system_info" arity="1" clause_i="68"/>
<fsummary>Information about the system.</fsummary>
<desc>
<p>Returns various information about the current system
@@ -7062,6 +7341,16 @@ ok
where <c><anno>MinHeapSize</anno></c> is the current
system-wide minimum heap size for spawned processes.</p>
</item>
+ <tag><marker id="system_info_message_queue_data"><c>message_queue_data</c></marker></tag>
+ <item>
+ <p>Returns the default value of the <c>message_queue_data</c>
+ process flag which is either <c>off_heap</c>, <c>on_heap</c>, or <c>mixed</c>.
+ This default is set by the <c>erl</c> command line argument
+ <seealso marker="erl#+xmqd"><c>+xmqd</c></seealso>. For more information on the
+ <c>message_queue_data</c> process flag, see documentation of
+ <seealso marker="#process_flag_message_queue_data"><c>process_flag(message_queue_data,
+ MQD)</c></seealso>.</p>
+ </item>
<tag><c>min_bin_vheap_size</c></tag>
<item>
<p>Returns <c>{min_bin_vheap_size,
@@ -7081,7 +7370,8 @@ ok
<tag><c>multi_scheduling</c></tag>
<item>
<marker id="system_info_multi_scheduling"></marker>
- <p>Returns <c>disabled</c>, <c>blocked</c>, or <c>enabled</c>:</p>
+ <p>Returns <c>disabled</c>, <c>blocked</c>, <c>blocked_normal</c>,
+ or <c>enabled</c>:</p>
<taglist>
<tag><c>disabled</c></tag>
<item>
@@ -7092,14 +7382,22 @@ ok
<tag><c>blocked</c></tag>
<item>
<p>The emulator has more than one scheduler thread,
- but all scheduler threads except one are blocked,
- that is, only one scheduler thread schedules
+ but all scheduler threads except one are blocked.
+ That is, only one scheduler thread schedules
Erlang processes and executes Erlang code.</p>
</item>
+ <tag><c>blocked_normal</c></tag>
+ <item>
+ <p>The emulator has more than one scheduler thread,
+ but all normal scheduler threads except one are
+ blocked. Note that dirty schedulers are not
+ blocked, and may schedule Erlang processes and
+ execute native code.</p>
+ </item>
<tag><c>enabled</c></tag>
<item>
<p>The emulator has more than one scheduler thread,
- and no scheduler threads are blocked, that is,
+ and no scheduler threads are blocked. That is,
all available scheduler threads schedule
Erlang processes and execute Erlang code.</p>
</item>
@@ -7107,6 +7405,7 @@ ok
<p>See also
<seealso marker="#system_flag_multi_scheduling">erlang:system_flag(multi_scheduling, BlockState)</seealso>,
<seealso marker="#system_info_multi_scheduling_blockers">erlang:system_info(multi_scheduling_blockers)</seealso>,
+ <seealso marker="#system_info_normal_multi_scheduling_blockers">erlang:system_info(normal_multi_scheduling_blockers)</seealso>,
and
<seealso marker="#system_info_schedulers">erlang:system_info(schedulers)</seealso>.</p>
</item>
@@ -7123,6 +7422,8 @@ ok
<p>See also
<seealso marker="#system_flag_multi_scheduling">erlang:system_flag(multi_scheduling, BlockState)</seealso>,
<seealso marker="#system_info_multi_scheduling">erlang:system_info(multi_scheduling)</seealso>,
+ <seealso marker="#system_info_normal_multi_scheduling_blockers">erlang:system_info(normal_multi_scheduling_blockers)</seealso>,
+
and
<seealso marker="#system_info_schedulers">erlang:system_info(schedulers)</seealso>.</p>
</item>
@@ -7132,7 +7433,25 @@ ok
used by the runtime system. It is on the form
"&lt;major ver&gt;.&lt;minor ver&gt;".</p>
</item>
- <tag><c>otp_release</c></tag>
+ <tag><c>normal_multi_scheduling_blockers</c></tag>
+ <item>
+ <marker id="system_info_normal_multi_scheduling_blockers"></marker>
+ <p>Returns a list of <c><anno>Pid</anno></c>s when
+ normal multi-scheduling is blocked (i.e. all normal schedulers
+ but one is blocked), otherwise the empty list is returned.
+ The <c><anno>Pid</anno></c>s in the list represent all the
+ processes currently blocking normal multi-scheduling.
+ A <c><anno>Pid</anno></c> occurs only once in the list, even if
+ the corresponding process has blocked multiple times.</p>
+ <p>See also
+ <seealso marker="#system_flag_multi_scheduling">erlang:system_flag(multi_scheduling, BlockState)</seealso>,
+ <seealso marker="#system_info_multi_scheduling">erlang:system_info(multi_scheduling)</seealso>,
+ <seealso marker="#system_info_multi_scheduling_blockers">erlang:system_info(multi_scheduling_blockers)</seealso>,
+
+ and
+ <seealso marker="#system_info_schedulers">erlang:system_info(schedulers)</seealso>.</p>
+ </item>
+ <tag><marker id="system_info_otp_release"><c>otp_release</c></marker></tag>
<item>
<marker id="system_info_otp_release"></marker>
<p>Returns a string containing the OTP release number of the
@@ -7373,6 +7692,7 @@ ok
<seealso marker="#system_info_scheduler_id">erlang:system_info(scheduler_id)</seealso>,
<seealso marker="#system_flag_multi_scheduling">erlang:system_flag(multi_scheduling, BlockState)</seealso>,
<seealso marker="#system_info_multi_scheduling">erlang:system_info(multi_scheduling)</seealso>,
+ <seealso marker="#system_info_normal_multi_scheduling_blockers">erlang:system_info(normal_multi_scheduling_blockers)</seealso>
and
<seealso marker="#system_info_multi_scheduling_blockers">erlang:system_info(multi_scheduling_blockers)</seealso>.</p>
</item>
diff --git a/erts/doc/src/erts_alloc.xml b/erts/doc/src/erts_alloc.xml
index 15b78ffa10..0965f9b49c 100644
--- a/erts/doc/src/erts_alloc.xml
+++ b/erts/doc/src/erts_alloc.xml
@@ -52,6 +52,8 @@
<item>Allocator used for ETS data.</item>
<tag><c>driver_alloc</c></tag>
<item>Allocator used for driver data.</item>
+ <tag><c>literal_alloc</c></tag>
+ <item>Allocator used for constant terms in Erlang code.</item>
<tag><c>sl_alloc</c></tag>
<item>Allocator used for memory blocks that are expected to be
short-lived.</item>
@@ -77,7 +79,7 @@
instead of creating new segments. This in order to reduce
the number of system calls made.</item>
</taglist>
- <p><c>sys_alloc</c> is always enabled and
+ <p><c>sys_alloc</c> and <c>literal_alloc</c> are always enabled and
cannot be disabled. <c>mseg_alloc</c> is always enabled if it is
available and an allocator that uses it is enabled. All other
allocators can be <seealso marker="#M_e">enabled or disabled</seealso>.
@@ -246,6 +248,7 @@
the currently present allocators:</p>
<list type="bulleted">
<item><c>B: binary_alloc</c></item>
+ <item><c>I: literal_alloc</c></item>
<item><c>D: std_alloc</c></item>
<item><c>E: ets_alloc</c></item>
<item><c>F: fix_alloc</c></item>
@@ -563,6 +566,16 @@
set to <c>false</c>, <c>sys_alloc</c> carriers will never be
created by allocators using the <c>alloc_util</c> framework.</item>
</taglist>
+ <p>The following flag is special for <c>literal_alloc</c>:</p>
+ <taglist>
+ <tag><marker id="MIscs"/><c><![CDATA[+MIscs <size in MB>]]></c></tag>
+ <item>
+ <c>literal_alloc</c> super carrier size (in MB). The amount of
+ <em>virtual</em> address space reserved for literal terms in
+ Erlang code on 64-bit architectures. The default is 1024 (1GB)
+ and is usually sufficient. The flag is ignored on 32-bit
+ architectures.</item>
+ </taglist>
<p>Instrumentation flags:</p>
<taglist>
<tag><marker id="Mim"/><c>+Mim true|false</c></tag>
diff --git a/erts/doc/src/init.xml b/erts/doc/src/init.xml
index fe26df61f7..2a33096d04 100644
--- a/erts/doc/src/init.xml
+++ b/erts/doc/src/init.xml
@@ -247,10 +247,7 @@
<c>Expr</c> during system initialization. If any of these
steps fail (syntax error, parse error or exception during
evaluation), Erlang stops with an error message. Here is an
- example that seeds the random number generator:</p>
- <pre>
-% <input>erl -eval '{X,Y,Z} = now(), random:seed(X,Y,Z).'</input></pre>
- <p>This example uses Erlang as a hexadecimal calculator:</p>
+ example that uses Erlang as a hexadecimal calculator:</p>
<pre>
% <input>erl -noshell -eval 'R = 16#1F+16#A0, io:format("~.16B~n", [R])' \\</input>
<input>-s erlang halt</input>
diff --git a/erts/doc/src/run_erl.xml b/erts/doc/src/run_erl.xml
index 0a5b2c6136..faec3c68c1 100644
--- a/erts/doc/src/run_erl.xml
+++ b/erts/doc/src/run_erl.xml
@@ -59,7 +59,7 @@
first argument to run_erl on the command line.</item>
<tag>pipe_dir</tag>
<item>This is where to put the named pipe, usually
- <c><![CDATA[/tmp/]]></c> on Unix or <c><![CDATA[/pipe/]]></c> on OSE. It shall be suffixed by a <c><![CDATA[/]]></c> (slash),
+ <c><![CDATA[/tmp/]]></c>. It shall be suffixed by a <c><![CDATA[/]]></c> (slash),
i.e. not <c><![CDATA[/tmp/epipies]]></c>, but <c><![CDATA[/tmp/epipes/]]></c>. </item>
<tag>log_dir</tag>
<item>This is where the log files are written. There will be one
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in
index a919f0e3ac..12148ad9c7 100644
--- a/erts/emulator/Makefile.in
+++ b/erts/emulator/Makefile.in
@@ -23,10 +23,6 @@ include ../vsn.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
-include $(TARGET)/gen_git_version.mk
-ifeq ($(findstring ose,$(TARGET)),ose)
-include $(ERL_TOP)/make/$(TARGET)/ose_lm.mk
-endif
-
ENABLE_ALLOC_TYPE_VARS = @ENABLE_ALLOC_TYPE_VARS@
HIPE_ENABLED=@HIPE_ENABLED@
DTRACE_ENABLED=@DTRACE_ENABLED@
@@ -245,9 +241,7 @@ HCC = @HCC@
LD = @LD@
DEXPORT = @DEXPORT@
RANLIB = @RANLIB@
-ifneq ($(findstring ose,$(TARGET)),ose)
STRIP = strip
-endif
PERL = @PERL@
RM = @RM@
MKDIR = @MKDIR@
@@ -323,7 +317,7 @@ else
CS_CFLAGS = $(CS_CFLAGS_)
endif
CS_LDFLAGS = $(LDFLAGS)
-CS_LIBS = -L../lib/internal/$(TARGET) -lerts_internal$(TYPEMARKER) @ERTS_INTERNAL_X_LIBS@
+CS_LIBS = -L../lib/internal/$(TARGET) -lerts_internal$(TYPEMARKER) @ERTS_INTERNAL_X_LIBS@ @SOCKET_LIBS@
LIBS += @TERMCAP_LIB@ -L../lib/internal/$(TARGET) @ERTS_INTERNAL_X_LIBS@
@@ -404,7 +398,7 @@ EMULATOR_EXECUTABLE = beam$(TF_MARKER).dll
else
EMULATOR_EXECUTABLE = beam$(TF_MARKER)
endif
-CS_EXECUTABLE = child_setup$(TYPEMARKER)
+CS_EXECUTABLE = erl_child_setup$(TYPEMARKER)
# ----------------------------------------------------------------------
@@ -597,6 +591,7 @@ ifeq ($(TARGET),win32)
PRELOAD_OBJ = $(OBJDIR)/beams.$(RES_EXT)
PRELOAD_SRC = $(TARGET)/beams.rc
$(PRELOAD_SRC): $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \
+ $(ERL_TOP)/erts/preloaded/ebin/erts_code_purger.beam \
$(ERL_TOP)/erts/preloaded/ebin/init.beam \
$(ERL_TOP)/erts/preloaded/ebin/prim_eval.beam \
$(ERL_TOP)/erts/preloaded/ebin/prim_inet.beam \
@@ -606,11 +601,13 @@ $(PRELOAD_SRC): $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \
$(ERL_TOP)/erts/preloaded/ebin/erl_prim_loader.beam \
$(ERL_TOP)/erts/preloaded/ebin/erlang.beam \
$(ERL_TOP)/erts/preloaded/ebin/erts_internal.beam
+
$(gen_verbose)LANG=C $(PERL) utils/make_preload $(MAKE_PRELOAD_EXTRA) -rc $^ > $@
else
PRELOAD_OBJ = $(OBJDIR)/preload.o
PRELOAD_SRC = $(TARGET)/preload.c
$(PRELOAD_SRC): $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \
+ $(ERL_TOP)/erts/preloaded/ebin/erts_code_purger.beam \
$(ERL_TOP)/erts/preloaded/ebin/init.beam \
$(ERL_TOP)/erts/preloaded/ebin/prim_eval.beam \
$(ERL_TOP)/erts/preloaded/ebin/prim_inet.beam \
@@ -684,14 +681,6 @@ $(OBJDIR)/%.o: $(TTF_DIR)/%.c
$(OBJDIR)/%.o: sys/$(ERLANG_OSTYPE)/%.c
$(V_CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
-ifeq ($(findstring ose,$(TARGET)),ose)
-$(OBJDIR)/ose_confd.o: $(OSE_CONFD)
- $(V_CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
-
-$(OBJDIR)/crt0_lm.o: $(CRT0_LM)
- $(V_CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
-endif
-
$(OBJDIR)/%.o: sys/common/%.c
$(V_CC) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@
@@ -704,11 +693,11 @@ $(OBJDIR)/%.o: drivers/$(ERLANG_OSTYPE)/%.c
# ----------------------------------------------------------------------
# Specials
#
-CS_SRC = sys/$(ERLANG_OSTYPE)/erl_child_setup.c
+CS_OBJ = $(OBJDIR)/erl_child_setup.o $(OBJDIR)/sys_uds.o $(OBJDIR)/hash.o
-$(BINDIR)/$(CS_EXECUTABLE): $(TTF_DIR)/GENERATED $(PRELOAD_SRC) $(CS_SRC) $(ERTS_LIB)
- $(ld_verbose)$(CS_PURIFY) $(CC) $(CS_LDFLAGS) -o $(BINDIR)/$(CS_EXECUTABLE) \
- $(CS_CFLAGS) $(COMMON_INCLUDES) $(CS_SRC) $(CS_LIBS)
+$(BINDIR)/$(CS_EXECUTABLE): $(TTF_DIR)/GENERATED $(PRELOAD_SRC) $(CS_OBJ) $(ERTS_LIB)
+ $(ld_verbose)$(CS_PURIFY) $(LD) $(CS_LDFLAGS) -o $(BINDIR)/$(CS_EXECUTABLE) \
+ $(CS_CFLAGS) $(COMMON_INCLUDES) $(CS_OBJ) $(CS_LIBS)
$(OBJDIR)/%.kp.o: sys/common/%.c
$(V_CC) -DERTS_KERNEL_POLL_VERSION $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@
@@ -787,7 +776,8 @@ RUN_OBJS = \
$(OBJDIR)/erl_zlib.o $(OBJDIR)/erl_nif.o \
$(OBJDIR)/erl_bif_binary.o $(OBJDIR)/erl_ao_firstfit_alloc.o \
$(OBJDIR)/erl_thr_queue.o $(OBJDIR)/erl_sched_spec_pre_alloc.o \
- $(OBJDIR)/erl_ptab.o $(OBJDIR)/erl_map.o
+ $(OBJDIR)/erl_ptab.o $(OBJDIR)/erl_map.o \
+ $(OBJDIR)/erl_msacc.o
ifeq ($(TARGET),win32)
DRV_OBJS = \
@@ -810,31 +800,10 @@ OS_OBJS = \
$(OBJDIR)/dosmap.o
else
-ifeq ($(findstring ose,$(TARGET)),ose)
-OS_OBJS = \
- $(OBJDIR)/sys.o \
- $(OBJDIR)/driver_tab.o \
- $(OBJDIR)/ose_efile.o \
- $(OBJDIR)/gzio.o \
- $(OBJDIR)/elib_memmove.o
-
-OS_OBJS += $(OBJDIR)/ose_confd.o \
- $(OBJDIR)/crt0_lm.o
-
-OS_OBJS += $(OBJDIR)/sys_float.o \
- $(OBJDIR)/sys_time.o
-
-DRV_OBJS = \
- $(OBJDIR)/efile_drv.o \
- $(OBJDIR)/ose_signal_drv.o \
- $(OBJDIR)/inet_drv.o \
- $(OBJDIR)/zlib_drv.o \
- $(OBJDIR)/ram_file_drv.o \
- $(OBJDIR)/ttsl_drv.o
-
-else
OS_OBJS = \
$(OBJDIR)/sys.o \
+ $(OBJDIR)/sys_drivers.o \
+ $(OBJDIR)/sys_uds.o \
$(OBJDIR)/driver_tab.o \
$(OBJDIR)/unix_efile.o \
$(OBJDIR)/gzio.o \
@@ -849,7 +818,6 @@ DRV_OBJS = \
$(OBJDIR)/ram_file_drv.o \
$(OBJDIR)/ttsl_drv.o
endif
-endif
ifneq ($(STATIC_NIFS),no)
STATIC_NIF_LIBS = $(STATIC_NIFS)
@@ -1022,19 +990,12 @@ $(BINDIR)/$(EMULATOR_EXECUTABLE): $(INIT_OBJS) $(OBJS) $(DEPLIBS)
$(STATIC_DRIVER_LIBS) $(LIBS)
else
-ifeq ($(findstring ose,$(TARGET)),ose)
-$(BINDIR)/$(EMULATOR_EXECUTABLE): $(INIT_OBJS) $(OBJS) $(DEPLIBS) $(LCF)
- $(call build-ose-load-module, $@, $(INIT_OBJS) $(OBJS), $(STATIC_NIF_LIBS) \
- $(STATIC_DRIVER_LIBS) $(LIBS), $(BEAM_LMCONF))
-
-else
$(BINDIR)/$(EMULATOR_EXECUTABLE): $(INIT_OBJS) $(OBJS) $(DEPLIBS)
$(ld_verbose)$(PURIFY) $(LD) -o $(BINDIR)/$(EMULATOR_EXECUTABLE) \
$(HIPEBEAMLDFLAGS) $(LDFLAGS) $(DEXPORT) $(INIT_OBJS) $(OBJS) \
$(STATIC_NIF_LIBS) $(STATIC_DRIVER_LIBS) $(LIBS)
endif
-endif
# ----------------------------------------------------------------------
# Dependencies
diff --git a/erts/emulator/beam/atom.c b/erts/emulator/beam/atom.c
index fe91134ef4..099c00bcf6 100644
--- a/erts/emulator/beam/atom.c
+++ b/erts/emulator/beam/atom.c
@@ -176,7 +176,7 @@ atom_alloc(Atom* tmpl)
/*
* Precompute ordinal value of first 3 bytes + 7 bits.
- * This is used by utils.c:cmp_atoms().
+ * This is used by utils.c:erts_cmp_atoms().
* We cannot use the full 32 bits of the first 4 bytes,
* since we use the sign of the difference between two
* ordinal values to represent their relative order.
@@ -435,6 +435,9 @@ init_atom_table(void)
f.cmp = (HCMP_FUN) atom_cmp;
f.alloc = (HALLOC_FUN) atom_alloc;
f.free = (HFREE_FUN) atom_free;
+ f.meta_alloc = (HMALLOC_FUN) erts_alloc;
+ f.meta_free = (HMFREE_FUN) erts_free;
+ f.meta_print = (HMPRINT_FUN) erts_print;
atom_text_pos = NULL;
atom_text_end = NULL;
diff --git a/erts/emulator/beam/atom.h b/erts/emulator/beam/atom.h
index ead56c83d8..2c002ca92f 100644
--- a/erts/emulator/beam/atom.h
+++ b/erts/emulator/beam/atom.h
@@ -129,6 +129,7 @@ typedef enum {
(erts_is_atom_utf8_bytes((byte *) LSTR, sizeof(LSTR) - 1, (TERM)))
#define ERTS_DECL_AM(S) Eterm AM_ ## S = am_atom_put(#S, sizeof(#S) - 1)
#define ERTS_INIT_AM(S) AM_ ## S = am_atom_put(#S, sizeof(#S) - 1)
+#define ERTS_MAKE_AM(Str) am_atom_put(Str, sizeof(Str) - 1)
int atom_table_size(void); /* number of elements */
int atom_table_sz(void); /* table size in bytes, excluding stored objects */
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index cb6d294a41..169b071cd7 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -102,6 +102,7 @@ atom asynchronous
atom atom
atom atom_used
atom attributes
+atom await_microstate_accounting_modifications
atom await_port_send_result
atom await_proc_exit
atom await_result
@@ -118,14 +119,15 @@ atom bif_timer_server
atom binary
atom binary_bin_to_list_trap
atom binary_copy_trap
+atom binary_find_trap
atom binary_longest_prefix_trap
atom binary_longest_suffix_trap
-atom binary_match_trap
-atom binary_matches_trap
atom binary_to_list_continue
atom binary_to_term_trap
atom block
+atom block_normal
atom blocked
+atom blocked_normal
atom bm
atom bnot
atom bor
@@ -173,6 +175,7 @@ atom const
atom context_switches
atom control
atom copy
+atom counters
atom cpu
atom cpu_timestamp
atom cr
@@ -189,7 +192,9 @@ atom dexit
atom depth
atom dgroup_leader
atom dictionary
+atom dirty_cpu
atom dirty_cpu_schedulers_online
+atom dirty_io
atom disable_trace
atom disabled
atom display_items
@@ -210,7 +215,9 @@ atom dsend
atom dsend_continue_trap
atom dunlink
atom duplicate_bag
+atom duplicated
atom dupnames
+atom einval
atom elib_malloc
atom emulator
atom enable_trace
@@ -258,6 +265,7 @@ atom functions
atom function_clause
atom garbage_collecting
atom garbage_collection
+atom garbage_collection_info
atom gc_end
atom gc_start
atom Ge='>='
@@ -268,6 +276,7 @@ atom get_tcw
atom getenv
atom gather_gc_info_result
atom gather_io_bytes
+atom gather_microstate_accounting_result
atom gather_sched_wall_time_result
atom gather_system_check_result
atom getting_linked
@@ -300,6 +309,7 @@ atom index
atom infinity
atom info
atom info_msg
+atom init
atom initial_call
atom input
atom internal
@@ -353,17 +363,20 @@ atom memory_internal
atom memory_types
atom message
atom message_binary
+atom message_queue_data
atom message_queue_len
atom messages
atom merge_trap
atom meta
atom meta_match_spec
atom micro_seconds
+atom microstate_accounting
atom milli_seconds
atom min_heap_size
atom min_bin_vheap_size
atom minor_version
atom Minus='-'
+atom mixed
atom module
atom module_info
atom monitored_by
@@ -427,10 +440,12 @@ atom notify
atom notsup
atom nouse_stdio
atom objects
+atom off_heap
atom offset
atom ok
atom old_heap_block_size
atom old_heap_size
+atom on_heap
atom on_load
atom open
atom open_error
@@ -441,13 +456,6 @@ atom orelse
atom os_pid
atom os_type
atom os_version
-atom ose_bg_proc
-atom ose_int_proc
-atom ose_phantom
-atom ose_pri_proc
-atom ose_process_prio
-atom ose_process_type
-atom ose_ti_proc
atom out
atom out_exited
atom out_exiting
@@ -592,6 +600,8 @@ atom trace trace_ts traced
atom trace_control_word
atom tracer
atom trap_exit
+atom trim
+atom trim_all
atom try_clause
atom true
atom tuple
@@ -607,6 +617,7 @@ atom use_stdio
atom used
atom utf8
atom unblock
+atom unblock_normal
atom uniq
atom unless_suspending
atom unloaded
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index 0e192b1ebd..0b47fc3586 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -38,9 +38,9 @@
#include "erl_thr_progress.h"
static void set_default_trace_pattern(Eterm module);
-static Eterm check_process_code(Process* rp, Module* modp, int allow_gc, int *redsp);
+static Eterm check_process_code(Process* rp, Module* modp, Uint flags, int *redsp);
static void delete_code(Module* modp);
-static void decrement_refc(BeamInstr* code);
+static void decrement_refc(BeamCodeHeader*);
static int any_heap_ref_ptrs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size);
static int any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size);
@@ -58,8 +58,8 @@ BIF_RETTYPE code_is_module_native_1(BIF_ALIST_1)
return am_undefined;
}
erts_rlock_old_code(code_ix);
- res = (erts_is_module_native(modp->curr.code) ||
- erts_is_module_native(modp->old.code)) ?
+ res = (erts_is_module_native(modp->curr.code_hdr) ||
+ erts_is_module_native(modp->old.code_hdr)) ?
am_true : am_false;
erts_runlock_old_code(code_ix);
return res;
@@ -81,12 +81,12 @@ BIF_RETTYPE code_make_stub_module_3(BIF_ALIST_3)
modp = erts_get_module(BIF_ARG_1, erts_active_code_ix());
if (modp && modp->curr.num_breakpoints > 0) {
- ASSERT(modp->curr.code != NULL);
+ ASSERT(modp->curr.code_hdr != NULL);
erts_clear_module_break(modp);
ASSERT(modp->curr.num_breakpoints == 0);
}
- erts_start_staging_code_ix();
+ erts_start_staging_code_ix(1);
res = erts_make_stub_module(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
@@ -139,6 +139,25 @@ prepare_loading_2(BIF_ALIST_2)
BIF_RET(res);
}
+BIF_RETTYPE
+has_prepared_code_on_load_1(BIF_ALIST_1)
+{
+ Eterm res;
+ ProcBin* pb;
+
+ if (!ERTS_TERM_IS_MAGIC_BINARY(BIF_ARG_1)) {
+ error:
+ BIF_ERROR(BIF_P, BADARG);
+ }
+
+ pb = (ProcBin*) binary_val(BIF_ARG_1);
+ res = erts_has_code_on_load(pb->val);
+ if (res == NIL) {
+ goto error;
+ }
+ BIF_RET(res);
+}
+
struct m {
Binary* code;
Eterm module;
@@ -154,7 +173,7 @@ static struct /* Protected by code_write_permission */
{
Process* stager;
ErtsThrPrgrLaterOp lop;
-}commiter_state;
+} committer_state;
#endif
static Eterm
@@ -163,14 +182,13 @@ exception_list(Process* p, Eterm tag, struct m* mp, Sint exceptions)
Eterm* hp = HAlloc(p, 3 + 2*exceptions);
Eterm res = NIL;
- mp += exceptions - 1;
while (exceptions > 0) {
if (mp->exception) {
res = CONS(hp, mp->module, res);
hp += 2;
exceptions--;
}
- mp--;
+ mp++;
}
return TUPLE2(hp, tag, res);
}
@@ -179,8 +197,8 @@ exception_list(Process* p, Eterm tag, struct m* mp, Sint exceptions)
BIF_RETTYPE
finish_loading_1(BIF_ALIST_1)
{
- int i;
- int n;
+ Sint i;
+ Sint n;
struct m* p = NULL;
Uint exceptions;
Eterm res;
@@ -201,9 +219,13 @@ finish_loading_1(BIF_ALIST_1)
*/
n = erts_list_length(BIF_ARG_1);
- if (n == -1) {
- ERTS_BIF_PREP_ERROR(res, BIF_P, BADARG);
- goto done;
+ if (n < 0) {
+ badarg:
+ if (p) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, p);
+ }
+ erts_release_code_write_permission();
+ BIF_ERROR(BIF_P, BADARG);
}
p = erts_alloc(ERTS_ALC_T_LOADER_TMP, n*sizeof(struct m));
@@ -218,29 +240,32 @@ finish_loading_1(BIF_ALIST_1)
ProcBin* pb;
if (!ERTS_TERM_IS_MAGIC_BINARY(term)) {
- ERTS_BIF_PREP_ERROR(res, BIF_P, BADARG);
- goto done;
+ goto badarg;
}
pb = (ProcBin*) binary_val(term);
p[i].code = pb->val;
p[i].module = erts_module_for_prepared_code(p[i].code);
if (p[i].module == NIL) {
- ERTS_BIF_PREP_ERROR(res, BIF_P, BADARG);
- goto done;
+ goto badarg;
}
BIF_ARG_1 = CDR(cons);
}
/*
* Since we cannot handle atomic loading of a group of modules
- * if one or more of them uses on_load, we will only allow one
- * element in the list. This limitation is intended to be
- * lifted in the future.
+ * if one or more of them uses on_load, we will only allow
+ * more than one element in the list if none of the modules
+ * have an on_load function.
*/
if (n > 1) {
- ERTS_BIF_PREP_ERROR(res, BIF_P, SYSTEM_LIMIT);
- goto done;
+ for (i = 0; i < n; i++) {
+ if (erts_has_code_on_load(p[i].code) == am_true) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, p);
+ erts_release_code_write_permission();
+ BIF_ERROR(BIF_P, SYSTEM_LIMIT);
+ }
+ }
}
/*
@@ -252,11 +277,27 @@ finish_loading_1(BIF_ALIST_1)
*/
res = am_ok;
- erts_start_staging_code_ix();
+ erts_start_staging_code_ix(n);
for (i = 0; i < n; i++) {
p[i].modp = erts_put_module(p[i].module);
+ p[i].modp->seen = 0;
}
+
+ exceptions = 0;
+ for (i = 0; i < n; i++) {
+ p[i].exception = 0;
+ if (p[i].modp->seen) {
+ p[i].exception = 1;
+ exceptions++;
+ }
+ p[i].modp->seen = 1;
+ }
+ if (exceptions) {
+ res = exception_list(BIF_P, am_duplicated, p, exceptions);
+ goto done;
+ }
+
for (i = 0; i < n; i++) {
if (p[i].modp->curr.num_breakpoints > 0 ||
p[i].modp->curr.num_traced_exports > 0 ||
@@ -281,7 +322,7 @@ finish_loading_1(BIF_ALIST_1)
exceptions = 0;
for (i = 0; i < n; i++) {
p[i].exception = 0;
- if (p[i].modp->curr.code && p[i].modp->old.code) {
+ if (p[i].modp->curr.code_hdr && p[i].modp->old.code_hdr) {
p[i].exception = 1;
exceptions++;
}
@@ -367,9 +408,9 @@ staging_epilogue(Process* c_p, int commit, Eterm res, int is_blocking,
* schedulers to read active code_ix in a safe way while executing
* without any memory barriers at all.
*/
- ASSERT(commiter_state.stager == NULL);
- commiter_state.stager = c_p;
- erts_schedule_thr_prgr_later_op(smp_code_ix_commiter, NULL, &commiter_state.lop);
+ ASSERT(committer_state.stager == NULL);
+ committer_state.stager = c_p;
+ erts_schedule_thr_prgr_later_op(smp_code_ix_commiter, NULL, &committer_state.lop);
erts_proc_inc_refc(c_p);
erts_suspend(c_p, ERTS_PROC_LOCK_MAIN, NULL);
/*
@@ -385,11 +426,11 @@ staging_epilogue(Process* c_p, int commit, Eterm res, int is_blocking,
#ifdef ERTS_SMP
static void smp_code_ix_commiter(void* null)
{
- Process* p = commiter_state.stager;
+ Process* p = committer_state.stager;
erts_commit_staging_code_ix();
#ifdef DEBUG
- commiter_state.stager = NULL;
+ committer_state.stager = NULL;
#endif
erts_release_code_write_permission();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
@@ -417,7 +458,7 @@ check_old_code_1(BIF_ALIST_1)
modp = erts_get_module(BIF_ARG_1, code_ix);
if (modp != NULL) {
erts_rlock_old_code(code_ix);
- if (modp->old.code != NULL) {
+ if (modp->old.code_hdr) {
res = am_true;
}
erts_runlock_old_code(code_ix);
@@ -426,7 +467,7 @@ check_old_code_1(BIF_ALIST_1)
}
Eterm
-erts_check_process_code(Process *c_p, Eterm module, int allow_gc, int *redsp)
+erts_check_process_code(Process *c_p, Eterm module, Uint flags, int *redsp)
{
Module* modp;
Eterm res;
@@ -441,7 +482,8 @@ erts_check_process_code(Process *c_p, Eterm module, int allow_gc, int *redsp)
if (!modp)
return am_false;
erts_rlock_old_code(code_ix);
- res = modp->old.code ? check_process_code(c_p, modp, allow_gc, redsp) : am_false;
+ res = (!modp->old.code_hdr ? am_false :
+ check_process_code(c_p, modp, flags, redsp));
erts_runlock_old_code(code_ix);
return res;
@@ -450,49 +492,21 @@ erts_check_process_code(Process *c_p, Eterm module, int allow_gc, int *redsp)
BIF_RETTYPE erts_internal_check_process_code_2(BIF_ALIST_2)
{
int reds = 0;
+ Uint flags;
Eterm res;
- Eterm olist = BIF_ARG_2;
- int allow_gc = 1;
if (is_not_atom(BIF_ARG_1))
goto badarg;
- while (is_list(olist)) {
- Eterm *lp = list_val(olist);
- Eterm opt = CAR(lp);
- if (is_tuple(opt)) {
- Eterm* tp = tuple_val(opt);
- switch (arityval(tp[0])) {
- case 2:
- switch (tp[1]) {
- case am_allow_gc:
- switch (tp[2]) {
- case am_false:
- allow_gc = 0;
- break;
- case am_true:
- allow_gc = 1;
- break;
- default:
- goto badarg;
- }
- break;
- default:
- goto badarg;
- }
- break;
- default:
- goto badarg;
- }
- }
- else
- goto badarg;
- olist = CDR(lp);
+ if (is_not_small(BIF_ARG_2))
+ goto badarg;
+
+ flags = unsigned_val(BIF_ARG_2);
+ if (flags & ~ERTS_CPC_ALL) {
+ goto badarg;
}
- if (is_not_nil(olist))
- goto badarg;
- res = erts_check_process_code(BIF_P, BIF_ARG_1, allow_gc, &reds);
+ res = erts_check_process_code(BIF_P, BIF_ARG_1, flags, &reds);
ASSERT(is_value(res));
@@ -519,13 +533,13 @@ BIF_RETTYPE delete_module_1(BIF_ALIST_1)
}
{
- erts_start_staging_code_ix();
+ erts_start_staging_code_ix(0);
code_ix = erts_staging_code_ix();
modp = erts_get_module(BIF_ARG_1, code_ix);
if (!modp) {
res = am_undefined;
}
- else if (modp->old.code != 0) {
+ else if (modp->old.code_hdr) {
erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
erts_dsprintf(dsbufp, "Module %T must be purged before loading\n",
BIF_ARG_1);
@@ -563,8 +577,8 @@ BIF_RETTYPE module_loaded_1(BIF_ALIST_1)
}
code_ix = erts_active_code_ix();
if ((modp = erts_get_module(BIF_ARG_1, code_ix)) != NULL) {
- if (modp->curr.code != NULL
- && modp->curr.code[MI_ON_LOAD_FUNCTION_PTR] == 0) {
+ if (modp->curr.code_hdr
+ && modp->curr.code_hdr->on_load_function_ptr == NULL) {
res = am_true;
}
}
@@ -611,8 +625,8 @@ BIF_RETTYPE call_on_load_function_1(BIF_ALIST_1)
{
Module* modp = erts_get_module(BIF_ARG_1, erts_active_code_ix());
- if (modp && modp->curr.code) {
- BIF_TRAP_CODE_PTR_0(BIF_P, modp->curr.code[MI_ON_LOAD_FUNCTION_PTR]);
+ if (modp && modp->curr.code_hdr) {
+ BIF_TRAP_CODE_PTR_0(BIF_P, modp->curr.code_hdr->on_load_function_ptr);
}
else {
BIF_ERROR(BIF_P, BADARG);
@@ -623,7 +637,6 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
{
ErtsCodeIndex code_ix;
Module* modp;
- Eterm on_load;
if (!erts_try_seize_code_write_permission(BIF_P)) {
ERTS_BIF_YIELD2(bif_export[BIF_finish_after_on_load_2],
@@ -638,14 +651,14 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
code_ix = erts_active_code_ix();
modp = erts_get_module(BIF_ARG_1, code_ix);
- if (!modp || modp->curr.code == 0) {
+ if (!modp || !modp->curr.code_hdr) {
error:
erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_release_code_write_permission();
BIF_ERROR(BIF_P, BADARG);
}
- if ((on_load = modp->curr.code[MI_ON_LOAD_FUNCTION_PTR]) == 0) {
+ if (modp->curr.code_hdr->on_load_function_ptr == NULL) {
goto error;
}
if (BIF_ARG_2 != am_false && BIF_ARG_2 != am_true) {
@@ -667,7 +680,7 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
ep->code[4] = 0;
}
}
- modp->curr.code[MI_ON_LOAD_FUNCTION_PTR] = 0;
+ modp->curr.code_hdr->on_load_function_ptr = NULL;
set_default_trace_pattern(BIF_ARG_1);
} else if (BIF_ARG_2 == am_false) {
BeamInstr* code;
@@ -679,13 +692,16 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
* the current code; the old code is not touched.
*/
erts_total_code_size -= modp->curr.code_length;
- code = modp->curr.code;
- end = (BeamInstr *)((char *)code + modp->curr.code_length);
+ code = (BeamInstr*) modp->curr.code_hdr;
+ end = (BeamInstr *) ((char *)code + modp->curr.code_length);
erts_cleanup_funs_on_purge(code, end);
beam_catches_delmod(modp->curr.catches, code, modp->curr.code_length,
erts_active_code_ix());
- erts_free(ERTS_ALC_T_CODE, (void *) code);
- modp->curr.code = NULL;
+ if (modp->curr.code_hdr->literals_start) {
+ erts_free(ERTS_ALC_T_LITERAL, modp->curr.code_hdr->literals_start);
+ }
+ erts_free(ERTS_ALC_T_CODE, modp->curr.code_hdr);
+ modp->curr.code_hdr = NULL;
modp->curr.code_length = 0;
modp->curr.catches = BEAM_CATCHES_NIL;
erts_remove_from_ranges(code);
@@ -721,31 +737,50 @@ set_default_trace_pattern(Eterm module)
}
}
+static ERTS_INLINE int
+check_mod_funs(Process *p, ErlOffHeap *off_heap, char *area, size_t area_size)
+{
+ struct erl_off_heap_header* oh;
+ for (oh = off_heap->first; oh; oh = oh->next) {
+ if (thing_subtag(oh->thing_word) == FUN_SUBTAG) {
+ ErlFunThing* funp = (ErlFunThing*) oh;
+ if (ErtsInArea(funp->fe->address, area, area_size))
+ return !0;
+ }
+ }
+ return 0;
+}
+
+
static Eterm
-check_process_code(Process* rp, Module* modp, int allow_gc, int *redsp)
+check_process_code(Process* rp, Module* modp, Uint flags, int *redsp)
{
BeamInstr* start;
+ char* literals;
+ Uint lit_bsize;
char* mod_start;
Uint mod_size;
- BeamInstr* end;
Eterm* sp;
- struct erl_off_heap_header* oh;
int done_gc = 0;
+ int need_gc = 0;
+ ErtsMessage *msgp;
+ ErlHeapFragment *hfrag;
-#define INSIDE(a) (start <= (a) && (a) < end)
+#define ERTS_ORDINARY_GC__ (1 << 0)
+#define ERTS_LITERAL_GC__ (1 << 1)
/*
* Pick up limits for the module.
*/
- start = modp->old.code;
- end = (BeamInstr *)((char *)start + modp->old.code_length);
+ start = (BeamInstr*) modp->old.code_hdr;
mod_start = (char *) start;
mod_size = modp->old.code_length;
/*
* Check if current instruction or continuation pointer points into module.
*/
- if (INSIDE(rp->i) || INSIDE(rp->cp)) {
+ if (ErtsInArea(rp->i, mod_start, mod_size)
+ || ErtsInArea(rp->cp, mod_start, mod_size)) {
return am_true;
}
@@ -753,7 +788,7 @@ check_process_code(Process* rp, Module* modp, int allow_gc, int *redsp)
* Check all continuation pointers stored on the stack.
*/
for (sp = rp->stop; sp < STACK_START(rp); sp++) {
- if (is_CP(*sp) && INSIDE(cp_val(*sp))) {
+ if (is_CP(*sp) && ErtsInArea(cp_val(*sp), mod_start, mod_size)) {
return am_true;
}
}
@@ -767,15 +802,15 @@ check_process_code(Process* rp, Module* modp, int allow_gc, int *redsp)
struct StackTrace *s;
ASSERT(is_list(rp->ftrace));
s = (struct StackTrace *) big_val(CDR(list_val(rp->ftrace)));
- if ((s->pc && INSIDE(s->pc)) ||
- (s->current && INSIDE(s->current))) {
+ if ((s->pc && ErtsInArea(s->pc, mod_start, mod_size)) ||
+ (s->current && ErtsInArea(s->current, mod_start, mod_size))) {
rp->freason = EXC_NULL;
rp->fvalue = NIL;
rp->ftrace = NIL;
} else {
int i;
for (i = 0; i < s->depth; i++) {
- if (INSIDE(s->trace[i])) {
+ if (ErtsInArea(s->trace[i], mod_start, mod_size)) {
rp->freason = EXC_NULL;
rp->fvalue = NIL;
rp->ftrace = NIL;
@@ -796,111 +831,147 @@ check_process_code(Process* rp, Module* modp, int allow_gc, int *redsp)
}
/*
- * See if there are funs that refer to the old version of the module.
+ * Message queue can contains funs, but (at least currently) no
+ * constants. If we got references to this module from the message
+ * queue, a GC cannot remove these...
*/
- rescan:
- for (oh = MSO(rp).first; oh; oh = oh->next) {
- if (thing_subtag(oh->thing_word) == FUN_SUBTAG) {
- ErlFunThing* funp = (ErlFunThing*) oh;
+ erts_smp_proc_lock(rp, ERTS_PROC_LOCK_MSGQ);
+ ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
+ erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_MSGQ);
- if (INSIDE((BeamInstr *) funp->fe->address)) {
- if (done_gc) {
- return am_true;
- } else {
- if (!allow_gc)
- return am_aborted;
- /*
- * Try to get rid of this fun by garbage collecting.
- * Clear both fvalue and ftrace to make sure they
- * don't hold any funs.
- */
- rp->freason = EXC_NULL;
- rp->fvalue = NIL;
- rp->ftrace = NIL;
- done_gc = 1;
- FLAGS(rp) |= F_NEED_FULLSWEEP;
- *redsp += erts_garbage_collect(rp, 0, rp->arg_reg, rp->arity);
- goto rescan;
- }
- }
+ literals = (char*) modp->old.code_hdr->literals_start;
+ lit_bsize = (char*) modp->old.code_hdr->literals_end - literals;
+
+ for (msgp = rp->msg.first; msgp; msgp = msgp->next) {
+ if (msgp->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ hfrag = &msgp->hfrag;
+ else if (is_value(ERL_MESSAGE_TERM(msgp)) && msgp->data.heap_frag)
+ hfrag = msgp->data.heap_frag;
+ else
+ continue;
+ for (; hfrag; hfrag = hfrag->next) {
+ if (check_mod_funs(rp, &hfrag->off_heap, mod_start, mod_size))
+ return am_true;
+ /* Should not contain any constants... */
+ ASSERT(!any_heap_refs(&hfrag->mem[0],
+ &hfrag->mem[hfrag->used_size],
+ literals,
+ lit_bsize));
}
}
- /*
- * See if there are constants inside the module referenced by the process.
- */
- done_gc = 0;
- for (;;) {
- ErlMessage* mp;
-
- if (any_heap_ref_ptrs(&rp->fvalue, &rp->fvalue+1, mod_start, mod_size)) {
+ while (1) {
+
+ /* Check heap, stack etc... */
+ if (check_mod_funs(rp, &rp->off_heap, mod_start, mod_size))
+ goto try_gc;
+ if (!(flags & ERTS_CPC_COPY_LITERALS)) {
+ /* Process ok. May contain old literals but we will be called
+ * again before module is purged.
+ */
+ return am_false;
+ }
+ if (any_heap_ref_ptrs(&rp->fvalue, &rp->fvalue+1, literals, lit_bsize)) {
rp->freason = EXC_NULL;
rp->fvalue = NIL;
rp->ftrace = NIL;
}
- if (any_heap_ref_ptrs(rp->stop, rp->hend, mod_start, mod_size)) {
- goto need_gc;
- }
- if (any_heap_refs(rp->heap, rp->htop, mod_start, mod_size)) {
- goto need_gc;
- }
-
- if (any_heap_refs(rp->old_heap, rp->old_htop, mod_start, mod_size)) {
- goto need_gc;
+ if (any_heap_ref_ptrs(rp->stop, rp->hend, literals, lit_bsize))
+ goto try_literal_gc;
+ if (any_heap_refs(rp->heap, rp->htop, literals, lit_bsize))
+ goto try_literal_gc;
+ if (any_heap_refs(rp->old_heap, rp->old_htop, literals, lit_bsize))
+ goto try_literal_gc;
+
+ /* Check dictionary */
+ if (rp->dictionary) {
+ Eterm* start = ERTS_PD_START(rp->dictionary);
+ Eterm* end = start + ERTS_PD_SIZE(rp->dictionary);
+
+ if (any_heap_ref_ptrs(start, end, literals, lit_bsize))
+ goto try_literal_gc;
}
- if (rp->dictionary != NULL) {
- Eterm* start = rp->dictionary->data;
- Eterm* end = start + rp->dictionary->used;
+ /* Check heap fragments */
+ for (hfrag = rp->mbuf; hfrag; hfrag = hfrag->next) {
+ Eterm *hp, *hp_end;
+ /* Off heap lists should already have been moved into process */
+ ASSERT(!check_mod_funs(rp, &hfrag->off_heap, mod_start, mod_size));
- if (any_heap_ref_ptrs(start, end, mod_start, mod_size)) {
- goto need_gc;
- }
+ hp = &hfrag->mem[0];
+ hp_end = &hfrag->mem[hfrag->used_size];
+ if (any_heap_refs(hp, hp_end, literals, lit_bsize))
+ goto try_literal_gc;
}
- for (mp = rp->msg.first; mp != NULL; mp = mp->next) {
- if (any_heap_ref_ptrs(mp->m, mp->m+2, mod_start, mod_size)) {
- goto need_gc;
+#ifdef DEBUG
+ /*
+ * Message buffer fragments should not have any references
+ * to constants, and off heap lists should already have
+ * been moved into process off heap structure.
+ */
+ for (msgp = rp->msg_frag; msgp; msgp = msgp->next) {
+ if (msgp->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ hfrag = &msgp->hfrag;
+ else
+ hfrag = msgp->data.heap_frag;
+ for (; hfrag; hfrag = hfrag->next) {
+ Eterm *hp, *hp_end;
+ ASSERT(!check_mod_funs(rp, &hfrag->off_heap, mod_start, mod_size));
+
+ hp = &hfrag->mem[0];
+ hp_end = &hfrag->mem[hfrag->used_size];
+ ASSERT(!any_heap_refs(hp, hp_end, literals, lit_bsize));
}
}
- break;
- need_gc:
- if (done_gc) {
+#endif
+
+ return am_false;
+
+ try_literal_gc:
+ need_gc |= ERTS_LITERAL_GC__;
+
+ try_gc:
+ need_gc |= ERTS_ORDINARY_GC__;
+
+ if ((done_gc & need_gc) == need_gc)
return am_true;
- } else {
- Eterm* literals;
- Uint lit_size;
- struct erl_off_heap_header* oh;
- if (!allow_gc)
- return am_aborted;
+ if (!(flags & ERTS_CPC_ALLOW_GC))
+ return am_aborted;
- /*
- * Try to get rid of constants by by garbage collecting.
- * Clear both fvalue and ftrace.
- */
- rp->freason = EXC_NULL;
- rp->fvalue = NIL;
- rp->ftrace = NIL;
- done_gc = 1;
+ need_gc &= ~done_gc;
+
+ /*
+ * Try to get rid of constants by by garbage collecting.
+ * Clear both fvalue and ftrace.
+ */
+
+ rp->freason = EXC_NULL;
+ rp->fvalue = NIL;
+ rp->ftrace = NIL;
+
+ if (need_gc & ERTS_ORDINARY_GC__) {
FLAGS(rp) |= F_NEED_FULLSWEEP;
- *redsp += erts_garbage_collect(rp, 0, rp->arg_reg, rp->arity);
- literals = (Eterm *) modp->old.code[MI_LITERALS_START];
- lit_size = (Eterm *) modp->old.code[MI_LITERALS_END] - literals;
- oh = (struct erl_off_heap_header *)
- modp->old.code[MI_LITERALS_OFF_HEAP];
- *redsp += lit_size / 10; /* Need, better value... */
- erts_garbage_collect_literals(rp, literals, lit_size, oh);
+ *redsp += erts_garbage_collect_nobump(rp, 0, rp->arg_reg, rp->arity);
+ done_gc |= ERTS_ORDINARY_GC__;
}
+ if (need_gc & ERTS_LITERAL_GC__) {
+ struct erl_off_heap_header* oh;
+ oh = modp->old.code_hdr->literals_off_heap;
+ *redsp += lit_bsize / 64; /* Need, better value... */
+ erts_garbage_collect_literals(rp, (Eterm*)literals, lit_bsize, oh);
+ done_gc |= ERTS_LITERAL_GC__;
+ }
+ need_gc = 0;
}
- return am_false;
-#undef INSIDE
-}
-#define in_area(ptr,start,nbytes) \
- ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes))
+#undef ERTS_ORDINARY_GC__
+#undef ERTS_LITERAL_GC__
+
+}
static int
any_heap_ref_ptrs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size)
@@ -913,7 +984,7 @@ any_heap_ref_ptrs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size)
switch (primary_tag(val)) {
case TAG_PRIMARY_BOXED:
case TAG_PRIMARY_LIST:
- if (in_area(EXPAND_POINTER(val), mod_start, mod_size)) {
+ if (ErtsInArea(val, mod_start, mod_size)) {
return 1;
}
break;
@@ -933,7 +1004,7 @@ any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size)
switch (primary_tag(val)) {
case TAG_PRIMARY_BOXED:
case TAG_PRIMARY_LIST:
- if (in_area(EXPAND_POINTER(val), mod_start, mod_size)) {
+ if (ErtsInArea(val, mod_start, mod_size)) {
return 1;
}
break;
@@ -943,7 +1014,7 @@ any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size)
if (header_is_bin_matchstate(val)) {
ErlBinMatchState *ms = (ErlBinMatchState*) p;
ErlBinMatchBuffer *mb = &(ms->mb);
- if (in_area(EXPAND_POINTER(mb->orig), mod_start, mod_size)) {
+ if (ErtsInArea(mb->orig, mod_start, mod_size)) {
return 1;
}
}
@@ -958,7 +1029,104 @@ any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size)
#undef in_area
-BIF_RETTYPE purge_module_1(BIF_ALIST_1)
+#ifdef ERTS_SMP
+static void copy_literals_commit(void*);
+#endif
+
+copy_literals_t erts_clrange = {NULL, 0, THE_NON_VALUE};
+
+/* copy literals
+ *
+ * copy_literals.ptr = LitPtr
+ * copy_literals.sz = LitSz
+ * ------ THR PROG COMMIT -----
+ *
+ * - check process code
+ * - check process code
+ * ...
+ * copy_literals.ptr = NULL
+ * copy_literals.sz = 0
+ * ------ THR PROG COMMIT -----
+ * ...
+ */
+
+
+BIF_RETTYPE erts_internal_copy_literals_2(BIF_ALIST_2)
+{
+ ErtsCodeIndex code_ix;
+ Eterm res = am_true;
+
+ if (is_not_atom(BIF_ARG_1) || (am_true != BIF_ARG_2 && am_false != BIF_ARG_2)) {
+ BIF_ERROR(BIF_P, BADARG);
+ }
+
+ if (!erts_try_seize_code_write_permission(BIF_P)) {
+ ERTS_BIF_YIELD2(bif_export[BIF_erts_internal_copy_literals_2],
+ BIF_P, BIF_ARG_1, BIF_ARG_2);
+ }
+
+ code_ix = erts_active_code_ix();
+
+ if (BIF_ARG_2 == am_true) {
+ Module* modp = erts_get_module(BIF_ARG_1, code_ix);
+ if (!modp || !modp->old.code_hdr) {
+ res = am_false;
+ goto done;
+ }
+ if (erts_clrange.ptr != NULL
+ && !(BIF_P->static_flags & ERTS_STC_FLG_SYSTEM_PROC)) {
+ res = am_aborted;
+ goto done;
+ }
+ erts_clrange.ptr = modp->old.code_hdr->literals_start;
+ erts_clrange.sz = modp->old.code_hdr->literals_end - erts_clrange.ptr;
+ erts_clrange.pid = BIF_P->common.id;
+ } else if (BIF_ARG_2 == am_false) {
+ if (erts_clrange.pid != BIF_P->common.id) {
+ res = am_false;
+ goto done;
+ }
+ erts_clrange.ptr = NULL;
+ erts_clrange.sz = 0;
+ erts_clrange.pid = THE_NON_VALUE;
+ }
+
+#ifdef ERTS_SMP
+ ASSERT(committer_state.stager == NULL);
+ committer_state.stager = BIF_P;
+ erts_schedule_thr_prgr_later_op(copy_literals_commit, NULL, &committer_state.lop);
+ erts_proc_inc_refc(BIF_P);
+ erts_suspend(BIF_P, ERTS_PROC_LOCK_MAIN, NULL);
+ ERTS_BIF_YIELD_RETURN(BIF_P, am_true);
+#endif
+done:
+ erts_release_code_write_permission();
+ BIF_RET(res);
+}
+
+#ifdef ERTS_SMP
+static void copy_literals_commit(void* null) {
+ Process* p = committer_state.stager;
+#ifdef DEBUG
+ committer_state.stager = NULL;
+#endif
+ erts_release_code_write_permission();
+ erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
+ if (!ERTS_PROC_IS_EXITING(p)) {
+ erts_resume(p, ERTS_PROC_LOCK_STATUS);
+ }
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+ erts_proc_dec_refc(p);
+}
+#endif /* ERTS_SMP */
+
+
+/* Do the actualy module purging and return:
+ * true for success
+ * false if no such old module
+ * BADARG if not an atom
+ */
+BIF_RETTYPE erts_internal_purge_module_1(BIF_ALIST_1)
{
ErtsCodeIndex code_ix;
BeamInstr* code;
@@ -972,7 +1140,8 @@ BIF_RETTYPE purge_module_1(BIF_ALIST_1)
}
if (!erts_try_seize_code_write_permission(BIF_P)) {
- ERTS_BIF_YIELD1(bif_export[BIF_purge_module_1], BIF_P, BIF_ARG_1);
+ ERTS_BIF_YIELD1(bif_export[BIF_erts_internal_purge_module_1],
+ BIF_P, BIF_ARG_1);
}
code_ix = erts_active_code_ix();
@@ -982,7 +1151,7 @@ BIF_RETTYPE purge_module_1(BIF_ALIST_1)
*/
if ((modp = erts_get_module(BIF_ARG_1, code_ix)) == NULL) {
- ERTS_BIF_PREP_ERROR(ret, BIF_P, BADARG);
+ ERTS_BIF_PREP_RET(ret, am_false);
}
else {
erts_rwlock_old_code(code_ix);
@@ -990,8 +1159,8 @@ BIF_RETTYPE purge_module_1(BIF_ALIST_1)
/*
* Any code to purge?
*/
- if (modp->old.code == 0) {
- ERTS_BIF_PREP_ERROR(ret, BIF_P, BADARG);
+ if (!modp->old.code_hdr) {
+ ERTS_BIF_PREP_RET(ret, am_false);
}
else {
/*
@@ -1013,14 +1182,17 @@ BIF_RETTYPE purge_module_1(BIF_ALIST_1)
*/
ASSERT(erts_total_code_size >= modp->old.code_length);
erts_total_code_size -= modp->old.code_length;
- code = modp->old.code;
+ code = (BeamInstr*) modp->old.code_hdr;
end = (BeamInstr *)((char *)code + modp->old.code_length);
erts_cleanup_funs_on_purge(code, end);
beam_catches_delmod(modp->old.catches, code, modp->old.code_length,
code_ix);
- decrement_refc(code);
+ decrement_refc(modp->old.code_hdr);
+ if (modp->old.code_hdr->literals_start) {
+ erts_free(ERTS_ALC_T_LITERAL, modp->old.code_hdr->literals_start);
+ }
erts_free(ERTS_ALC_T_CODE, (void *) code);
- modp->old.code = NULL;
+ modp->old.code_hdr = NULL;
modp->old.code_length = 0;
modp->old.catches = BEAM_CATCHES_NIL;
erts_remove_from_ranges(code);
@@ -1037,10 +1209,9 @@ BIF_RETTYPE purge_module_1(BIF_ALIST_1)
}
static void
-decrement_refc(BeamInstr* code)
+decrement_refc(BeamCodeHeader* code_hdr)
{
- struct erl_off_heap_header* oh =
- (struct erl_off_heap_header *) code[MI_LITERALS_OFF_HEAP];
+ struct erl_off_heap_header* oh = code_hdr->literals_off_heap;
while (oh) {
Binary* bptr;
@@ -1089,7 +1260,7 @@ delete_code(Module* modp)
ASSERT(modp->curr.num_breakpoints == 0);
ASSERT(modp->curr.num_traced_exports == 0);
modp->old = modp->curr;
- modp->curr.code = NULL;
+ modp->curr.code_hdr = NULL;
modp->curr.code_length = 0;
modp->curr.catches = BEAM_CATCHES_NIL;
modp->curr.nif = NULL;
@@ -1106,9 +1277,9 @@ beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, Eterm module)
* if not, delete old code; error if old code already exists.
*/
- if (modp->curr.code != NULL && modp->old.code != NULL) {
+ if (modp->curr.code_hdr && modp->old.code_hdr) {
return am_not_purged;
- } else if (modp->old.code == NULL) { /* Make the current version old. */
+ } else if (!modp->old.code_hdr) { /* Make the current version old. */
delete_code(modp);
}
return NIL;
diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c
index 9860968687..5d471d168b 100644
--- a/erts/emulator/beam/beam_bp.c
+++ b/erts/emulator/beam/beam_bp.c
@@ -154,8 +154,8 @@ erts_bp_match_functions(BpFunctions* f, Eterm mfa[3], int specified)
num_modules = 0;
for (current = 0; current < max_modules; current++) {
modp = module_code(current, code_ix);
- if (modp->curr.code) {
- max_funcs += modp->curr.code[MI_NUM_FUNCTIONS];
+ if (modp->curr.code_hdr) {
+ max_funcs += modp->curr.code_hdr->num_functions;
module[num_modules++] = modp;
}
}
@@ -163,9 +163,9 @@ erts_bp_match_functions(BpFunctions* f, Eterm mfa[3], int specified)
f->matching = (BpFunction *) Alloc(max_funcs*sizeof(BpFunction));
i = 0;
for (current = 0; current < num_modules; current++) {
- BeamInstr** code_base = (BeamInstr **) module[current]->curr.code;
+ BeamCodeHeader* code_hdr = module[current]->curr.code_hdr;
BeamInstr* code;
- Uint num_functions = (Uint)(UWord) code_base[MI_NUM_FUNCTIONS];
+ Uint num_functions = (Uint)(UWord) code_hdr->num_functions;
Uint fi;
if (specified > 0) {
@@ -179,7 +179,7 @@ erts_bp_match_functions(BpFunctions* f, Eterm mfa[3], int specified)
BeamInstr* pc;
int wi;
- code = code_base[MI_FUNCTIONS+fi];
+ code = code_hdr->functions[fi];
ASSERT(code[0] == (BeamInstr) BeamOp(op_i_func_info_IaaI));
pc = code+5;
if (erts_is_native_break(pc)) {
@@ -549,21 +549,21 @@ erts_clear_all_breaks(BpFunctions* f)
int
erts_clear_module_break(Module *modp) {
- BeamInstr** code_base;
+ BeamCodeHeader* code_hdr;
Uint n;
Uint i;
ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
ASSERT(modp);
- code_base = (BeamInstr **) modp->curr.code;
- if (code_base == NULL) {
+ code_hdr = modp->curr.code_hdr;
+ if (!code_hdr) {
return 0;
}
- n = (Uint)(UWord) code_base[MI_NUM_FUNCTIONS];
+ n = (Uint)(UWord) code_hdr->num_functions;
for (i = 0; i < n; ++i) {
BeamInstr* pc;
- pc = code_base[MI_FUNCTIONS+i] + 5;
+ pc = code_hdr->functions[i] + 5;
if (erts_is_native_break(pc)) {
continue;
}
@@ -575,7 +575,7 @@ erts_clear_module_break(Module *modp) {
for (i = 0; i < n; ++i) {
BeamInstr* pc;
- pc = code_base[MI_FUNCTIONS+i] + 5;
+ pc = code_hdr->functions[i] + 5;
if (erts_is_native_break(pc)) {
continue;
}
@@ -864,7 +864,7 @@ do_call_trace(Process* c_p, BeamInstr* I, Eterm* reg,
Eterm* cpp;
int return_to_trace = 0;
BeamInstr w;
- BeamInstr *cp_save;
+ BeamInstr *cp_save = c_p->cp;
Uint32 flags;
Uint need = 0;
Eterm* E = c_p->stop;
@@ -1205,17 +1205,17 @@ int erts_is_time_break(Process *p, BeamInstr *pc, Eterm *retval) {
BeamInstr *
erts_find_local_func(Eterm mfa[3]) {
Module *modp;
- BeamInstr** code_base;
+ BeamCodeHeader* code_hdr;
BeamInstr* code_ptr;
Uint i,n;
if ((modp = erts_get_module(mfa[0], erts_active_code_ix())) == NULL)
return NULL;
- if ((code_base = (BeamInstr **) modp->curr.code) == NULL)
+ if ((code_hdr = modp->curr.code_hdr) == NULL)
return NULL;
- n = (BeamInstr) code_base[MI_NUM_FUNCTIONS];
+ n = (BeamInstr) code_hdr->num_functions;
for (i = 0; i < n; ++i) {
- code_ptr = code_base[MI_FUNCTIONS+i];
+ code_ptr = code_hdr->functions[i];
ASSERT(((BeamInstr) BeamOp(op_i_func_info_IaaI)) == code_ptr[0]);
ASSERT(mfa[0] == ((Eterm) code_ptr[2]) ||
is_nil((Eterm) code_ptr[2]));
diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c
index 90985e4f53..e37bd4d78c 100644
--- a/erts/emulator/beam/beam_debug.c
+++ b/erts/emulator/beam/beam_debug.c
@@ -73,6 +73,40 @@ erts_debug_flat_size_1(BIF_ALIST_1)
}
}
+BIF_RETTYPE
+erts_debug_size_shared_1(BIF_ALIST_1)
+{
+ Process* p = BIF_P;
+ Eterm term = BIF_ARG_1;
+ Uint size = size_shared(term);
+
+ if (IS_USMALL(0, size)) {
+ BIF_RET(make_small(size));
+ } else {
+ Eterm* hp = HAlloc(p, BIG_UINT_HEAP_SIZE);
+ BIF_RET(uint_to_big(size, hp));
+ }
+}
+
+BIF_RETTYPE
+erts_debug_copy_shared_1(BIF_ALIST_1)
+{
+ Process* p = BIF_P;
+ Eterm term = BIF_ARG_1;
+ Uint size;
+ Eterm* hp;
+ Eterm copy;
+ erts_shcopy_t info;
+ INITIALIZE_SHCOPY(info);
+
+ size = copy_shared_calculate(term, &info);
+ if (size > 0) {
+ hp = HAlloc(p, size);
+ }
+ copy = copy_shared_perform(term, size, &info, &hp, &p->off_heap);
+ DESTROY_SHCOPY(info);
+ BIF_RET(copy);
+}
BIF_RETTYPE
erts_debug_breakpoint_2(BIF_ALIST_2)
@@ -208,7 +242,7 @@ erts_debug_disassemble_1(BIF_ALIST_1)
Eterm bin;
Eterm mfa;
BeamInstr* funcinfo = NULL; /* Initialized to eliminate warning. */
- BeamInstr* code_base;
+ BeamCodeHeader* code_hdr;
BeamInstr* code_ptr = NULL; /* Initialized to eliminate warning. */
BeamInstr instr;
BeamInstr uaddr;
@@ -258,12 +292,12 @@ erts_debug_disassemble_1(BIF_ALIST_1)
*/
code_ptr = ((BeamInstr *) ep->addressv[code_ix]) - 5;
funcinfo = code_ptr+2;
- } else if (modp == NULL || (code_base = modp->curr.code) == NULL) {
+ } else if (modp == NULL || (code_hdr = modp->curr.code_hdr) == NULL) {
BIF_RET(am_undef);
} else {
- n = code_base[MI_NUM_FUNCTIONS];
+ n = code_hdr->num_functions;
for (i = 0; i < n; i++) {
- code_ptr = (BeamInstr *) code_base[MI_FUNCTIONS+i];
+ code_ptr = code_hdr->functions[i];
if (code_ptr[3] == name && code_ptr[4] == arity) {
funcinfo = code_ptr+2;
break;
@@ -432,39 +466,33 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
while (*sign) {
switch (*sign) {
case 'r': /* x(0) */
- erts_print(to, to_arg, "x(0)");
+ erts_print(to, to_arg, "r(0)");
break;
case 'x': /* x(N) */
- if (reg_index(ap[0]) == 0) {
- erts_print(to, to_arg, "x[0]");
- } else {
- erts_print(to, to_arg, "x(%d)", reg_index(ap[0]));
+ {
+ Uint n = ap[0] / sizeof(Eterm);
+ erts_print(to, to_arg, "x(%d)", n);
+ ap++;
}
- ap++;
break;
case 'y': /* y(N) */
- erts_print(to, to_arg, "y(%d)", reg_index(ap[0]) - CP_SIZE);
- ap++;
+ {
+ Uint n = ap[0] / sizeof(Eterm) - CP_SIZE;
+ erts_print(to, to_arg, "y(%d)", n);
+ ap++;
+ }
break;
case 'n': /* Nil */
erts_print(to, to_arg, "[]");
break;
case 's': /* Any source (tagged constant or register) */
- tag = beam_reg_tag(*ap);
- if (tag == X_REG_DEF) {
- if (reg_index(*ap) == 0) {
- erts_print(to, to_arg, "x[0]");
- } else {
- erts_print(to, to_arg, "x(%d)", reg_index(*ap));
- }
- ap++;
- break;
- } else if (tag == Y_REG_DEF) {
- erts_print(to, to_arg, "y(%d)", reg_index(*ap) - CP_SIZE);
+ tag = loader_tag(*ap);
+ if (tag == LOADER_X_REG) {
+ erts_print(to, to_arg, "x(%d)", loader_x_reg_index(*ap));
ap++;
break;
- } else if (tag == R_REG_DEF) {
- erts_print(to, to_arg, "x(0)");
+ } else if (tag == LOADER_Y_REG) {
+ erts_print(to, to_arg, "y(%d)", loader_y_reg_index(*ap) - CP_SIZE);
ap++;
break;
}
@@ -481,20 +509,12 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
ap++;
break;
case 'd': /* Destination (x(0), x(N), y(N)) */
- switch (beam_reg_tag(*ap)) {
- case X_REG_DEF:
- if (reg_index(*ap) == 0) {
- erts_print(to, to_arg, "x[0]");
- } else {
- erts_print(to, to_arg, "x(%d)", reg_index(*ap));
- }
- break;
- case Y_REG_DEF:
- erts_print(to, to_arg, "y(%d)", reg_index(*ap) - CP_SIZE);
- break;
- case R_REG_DEF:
- erts_print(to, to_arg, "x(0)");
- break;
+ if (*ap & 1) {
+ erts_print(to, to_arg, "y(%d)",
+ *ap / sizeof(Eterm) - CP_SIZE);
+ } else {
+ erts_print(to, to_arg, "x(%d)",
+ *ap / sizeof(Eterm));
}
ap++;
break;
@@ -561,7 +581,7 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
ap++;
break;
case 'l': /* fr(N) */
- erts_print(to, to_arg, "fr(%d)", reg_index(ap[0]));
+ erts_print(to, to_arg, "fr(%d)", loader_reg_index(ap[0]));
ap++;
break;
default:
@@ -580,7 +600,6 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
unpacked = ap;
ap = addr + size;
switch (op) {
- case op_i_select_val_lins_rfI:
case op_i_select_val_lins_xfI:
case op_i_select_val_lins_yfI:
{
@@ -600,7 +619,6 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
}
}
break;
- case op_i_select_val_bins_rfI:
case op_i_select_val_bins_xfI:
case op_i_select_val_bins_yfI:
{
@@ -614,7 +632,6 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
}
}
break;
- case op_i_select_tuple_arity_rfI:
case op_i_select_tuple_arity_xfI:
case op_i_select_tuple_arity_yfI:
{
@@ -639,7 +656,6 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
}
}
break;
- case op_i_jump_on_val_rfII:
case op_i_jump_on_val_xfII:
case op_i_jump_on_val_yfII:
{
@@ -651,7 +667,6 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
}
}
break;
- case op_i_jump_on_val_zero_rfI:
case op_i_jump_on_val_zero_xfI:
case op_i_jump_on_val_zero_yfI:
{
@@ -663,7 +678,6 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
}
}
break;
- case op_i_put_tuple_rI:
case op_i_put_tuple_xI:
case op_i_put_tuple_yI:
case op_new_map_dII:
@@ -673,20 +687,16 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
int n = unpacked[-1];
while (n > 0) {
- if (!is_header(ap[0])) {
+ switch (loader_tag(ap[0])) {
+ case LOADER_X_REG:
+ erts_print(to, to_arg, " x(%d)", loader_x_reg_index(ap[0]));
+ break;
+ case LOADER_Y_REG:
+ erts_print(to, to_arg, " x(%d)", loader_y_reg_index(ap[0]));
+ break;
+ default:
erts_print(to, to_arg, " %T", (Eterm) ap[0]);
- } else {
- switch ((ap[0] >> 2) & 0x03) {
- case R_REG_DEF:
- erts_print(to, to_arg, " x(0)");
- break;
- case X_REG_DEF:
- erts_print(to, to_arg, " x(%d)", ap[0] >> 4);
- break;
- case Y_REG_DEF:
- erts_print(to, to_arg, " y(%d)", ap[0] >> 4);
- break;
- }
+ break;
}
ap++, size++, n--;
}
@@ -699,18 +709,16 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
while (n > 0) {
if (n % 3 == 1) {
erts_print(to, to_arg, " %X", ap[0]);
- } else if (!is_header(ap[0])) {
- erts_print(to, to_arg, " %T", (Eterm) ap[0]);
} else {
- switch ((ap[0] >> 2) & 0x03) {
- case R_REG_DEF:
- erts_print(to, to_arg, " x(0)");
+ switch (loader_tag(ap[0])) {
+ case LOADER_X_REG:
+ erts_print(to, to_arg, " x(%d)", loader_x_reg_index(ap[0]));
break;
- case X_REG_DEF:
- erts_print(to, to_arg, " x(%d)", ap[0] >> 4);
+ case LOADER_Y_REG:
+ erts_print(to, to_arg, " y(%d)", loader_y_reg_index(ap[0]));
break;
- case Y_REG_DEF:
- erts_print(to, to_arg, " y(%d)", ap[0] >> 4);
+ default:
+ erts_print(to, to_arg, " %T", (Eterm) ap[0]);
break;
}
}
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 1fe4cc9374..a390422040 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -99,10 +99,7 @@ do { \
do { \
int i_; \
int Arity_ = PC[-1]; \
- if (Arity_ > 0) { \
- CHECK_TERM(r(0)); \
- } \
- for (i_ = 1; i_ < Arity_; i_++) { \
+ for (i_ = 0; i_ < Arity_; i_++) { \
CHECK_TERM(x(i_)); \
} \
} while (0)
@@ -116,6 +113,9 @@ do { \
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#endif
+#define GET_BIF_MODULE(p) ((Eterm) (((Export *) p)->code[0]))
+#define GET_BIF_FUNCTION(p) ((Eterm) (((Export *) p)->code[1]))
+#define GET_BIF_ARITY(p) ((Eterm) (((Export *) p)->code[2]))
#define GET_BIF_ADDRESS(p) ((BifFunction) (((Export *) p)->code[4]))
#define TermWords(t) (((t) / (sizeof(BeamInstr)/sizeof(Eterm))) + !!((t) % (sizeof(BeamInstr)/sizeof(Eterm))))
@@ -151,25 +151,21 @@ do { \
ASSERT(VALID_INSTR(* (Eterm *)(ip))); \
I = (ip)
-#define FetchArgs(S1, S2) tmp_arg1 = (S1); tmp_arg2 = (S2)
+/*
+ * Register target (X or Y register).
+ */
+#define REG_TARGET(Target) (*(((Target) & 1) ? &yb(Target-1) : &xb(Target)))
/*
* Store a result into a register given a destination descriptor.
*/
-#define StoreResult(Result, DestDesc) \
- do { \
- Eterm stb_reg; \
- stb_reg = (DestDesc); \
- CHECK_TERM(Result); \
- switch (beam_reg_tag(stb_reg)) { \
- case R_REG_DEF: \
- r(0) = (Result); break; \
- case X_REG_DEF: \
- xb(x_reg_offset(stb_reg)) = (Result); break; \
- default: \
- yb(y_reg_offset(stb_reg)) = (Result); break; \
- } \
+#define StoreResult(Result, DestDesc) \
+ do { \
+ Eterm stb_reg; \
+ stb_reg = (DestDesc); \
+ CHECK_TERM(Result); \
+ REG_TARGET(stb_reg) = (Result); \
} while (0)
#define StoreSimpleDest(Src, Dest) Dest = (Src)
@@ -180,22 +176,16 @@ do { \
* be just before the next instruction.
*/
-#define StoreBifResult(Dst, Result) \
- do { \
- BeamInstr* stb_next; \
- Eterm stb_reg; \
- stb_reg = Arg(Dst); \
- I += (Dst) + 2; \
- stb_next = (BeamInstr *) *I; \
- CHECK_TERM(Result); \
- switch (beam_reg_tag(stb_reg)) { \
- case R_REG_DEF: \
- r(0) = (Result); Goto(stb_next); \
- case X_REG_DEF: \
- xb(x_reg_offset(stb_reg)) = (Result); Goto(stb_next); \
- default: \
- yb(y_reg_offset(stb_reg)) = (Result); Goto(stb_next); \
- } \
+#define StoreBifResult(Dst, Result) \
+ do { \
+ BeamInstr* stb_next; \
+ Eterm stb_reg; \
+ stb_reg = Arg(Dst); \
+ I += (Dst) + 2; \
+ stb_next = (BeamInstr *) *I; \
+ CHECK_TERM(Result); \
+ REG_TARGET(stb_reg) = (Result); \
+ Goto(stb_next); \
} while (0)
#define ClauseFail() goto jump_f
@@ -250,6 +240,14 @@ void** beam_ops;
HEAP_TOP(c_p) = HTOP; \
c_p->stop = E
+#define HEAVY_SWAPIN \
+ SWAPIN; \
+ FCALLS = c_p->fcalls
+
+#define HEAVY_SWAPOUT \
+ SWAPOUT; \
+ c_p->fcalls = FCALLS
+
/*
* Use LIGHT_SWAPOUT when the called function
* will call HeapOnlyAlloc() (and never HAlloc()).
@@ -293,7 +291,7 @@ void** beam_ops;
#define Ib(N) (N)
#define x(N) reg[N]
#define y(N) E[N]
-#define r(N) x##N
+#define r(N) x(N)
/*
* Makes sure that there are StackNeed + HeapNeed + 1 words available
@@ -309,12 +307,10 @@ void** beam_ops;
needed = (StackNeed) + 1; \
if (E - HTOP < (needed + (HeapNeed))) { \
SWAPOUT; \
- reg[0] = r(0); \
PROCESS_MAIN_CHK_LOCKS(c_p); \
- FCALLS -= erts_garbage_collect(c_p, needed + (HeapNeed), reg, (M)); \
+ FCALLS -= erts_garbage_collect_nobump(c_p, needed + (HeapNeed), reg, (M)); \
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); \
PROCESS_MAIN_CHK_LOCKS(c_p); \
- r(0) = reg[0]; \
SWAPIN; \
} \
E -= needed; \
@@ -363,12 +359,10 @@ void** beam_ops;
unsigned need = (Nh); \
if ((E - HTOP < need) || (MSO(c_p).overhead + (VNh) >= BIN_VHEAP_SZ(c_p))) {\
SWAPOUT; \
- reg[0] = r(0); \
PROCESS_MAIN_CHK_LOCKS(c_p); \
- FCALLS -= erts_garbage_collect(c_p, need, reg, (Live)); \
+ FCALLS -= erts_garbage_collect_nobump(c_p, need, reg, (Live)); \
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); \
PROCESS_MAIN_CHK_LOCKS(c_p); \
- r(0) = reg[0]; \
SWAPIN; \
} \
HEAP_SPACE_VERIFIED(need); \
@@ -386,12 +380,10 @@ void** beam_ops;
unsigned need = (Nh); \
if (E - HTOP < need) { \
SWAPOUT; \
- reg[0] = r(0); \
PROCESS_MAIN_CHK_LOCKS(c_p); \
- FCALLS -= erts_garbage_collect(c_p, need, reg, (Live)); \
+ FCALLS -= erts_garbage_collect_nobump(c_p, need, reg, (Live));\
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); \
PROCESS_MAIN_CHK_LOCKS(c_p); \
- r(0) = reg[0]; \
SWAPIN; \
} \
HEAP_SPACE_VERIFIED(need); \
@@ -408,15 +400,11 @@ void** beam_ops;
unsigned need = (Nh); \
if (E - HTOP < need) { \
SWAPOUT; \
- reg[0] = r(0); \
reg[Live] = Extra; \
PROCESS_MAIN_CHK_LOCKS(c_p); \
- FCALLS -= erts_garbage_collect(c_p, need, reg, (Live)+1); \
+ FCALLS -= erts_garbage_collect_nobump(c_p, need, reg, (Live)+1); \
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); \
PROCESS_MAIN_CHK_LOCKS(c_p); \
- if (Live > 0) { \
- r(0) = reg[0]; \
- } \
Extra = reg[Live]; \
SWAPIN; \
} \
@@ -438,10 +426,9 @@ void** beam_ops;
#define MakeFun(FunP, NumFree) \
do { \
- SWAPOUT; \
- reg[0] = r(0); \
+ HEAVY_SWAPOUT; \
r(0) = new_fun(c_p, reg, (ErlFunEntry *) FunP, NumFree); \
- SWAPIN; \
+ HEAVY_SWAPIN; \
} while (0)
#define PutTuple(Dst, Arity) \
@@ -531,15 +518,19 @@ void** beam_ops;
ASSERT(VALID_INSTR(Dst)); \
Goto(Dst)
-#define GetR(pos, tr) \
- do { \
- tr = Arg(pos); \
- switch (beam_reg_tag(tr)) { \
- case R_REG_DEF: tr = r(0); break; \
- case X_REG_DEF: tr = xb(x_reg_offset(tr)); break; \
- case Y_REG_DEF: ASSERT(y_reg_offset(tr) >= 1); tr = yb(y_reg_offset(tr)); break; \
- } \
- CHECK_TERM(tr); \
+#define GetR(pos, tr) \
+ do { \
+ tr = Arg(pos); \
+ switch (loader_tag(tr)) { \
+ case LOADER_X_REG: \
+ tr = x(loader_x_reg_index(tr)); \
+ break; \
+ case LOADER_Y_REG: \
+ ASSERT(loader_y_reg_index(tr) >= 1); \
+ tr = y(loader_y_reg_index(tr)); \
+ break; \
+ } \
+ CHECK_TERM(tr); \
} while (0)
#define GetArg1(N, Dst) GetR((N), Dst)
@@ -557,24 +548,93 @@ void** beam_ops;
HTOP += 2; \
} while (0)
+#define Swap(R1, R2) \
+ do { \
+ Eterm V = R1; \
+ R1 = R2; \
+ R2 = V; \
+ } while (0)
+
+#define SwapTemp(R1, R2, Tmp) \
+ do { \
+ Eterm V = R1; \
+ R1 = R2; \
+ R2 = Tmp = V; \
+ } while (0)
+
#define Move(Src, Dst, Store) \
do { \
Eterm term = (Src); \
Store(term, Dst); \
} while (0)
-#define Move2(S1, D1, S2, D2) D1 = (S1); D2 = (S2)
+#define Move2Par(S1, D1, S2, D2) \
+ do { \
+ Eterm V1, V2; \
+ V1 = (S1); V2 = (S2); D1 = V1; D2 = V2; \
+ } while (0)
+
+#define MoveShift(Src, SD, D) \
+ do { \
+ Eterm V; \
+ V = Src; D = SD; SD = V; \
+ } while (0)
+
+#define MoveDup(Src, D1, D2) \
+ do { \
+ D1 = D2 = (Src); \
+ } while (0)
+
#define Move3(S1, D1, S2, D2, S3, D3) D1 = (S1); D2 = (S2); D3 = (S3)
-#define MoveGenDest(src, dstp) \
- if ((dstp) == NULL) { r(0) = (src); } else { *(dstp) = src; }
+#define MoveWindow3(S1, S2, S3, D) \
+ do { \
+ Eterm xt0, xt1, xt2; \
+ Eterm *y = &D; \
+ xt0 = S1; \
+ xt1 = S2; \
+ xt2 = S3; \
+ y[0] = xt0; \
+ y[1] = xt1; \
+ y[2] = xt2; \
+ } while (0)
+
+#define MoveWindow4(S1, S2, S3, S4, D) \
+ do { \
+ Eterm xt0, xt1, xt2, xt3; \
+ Eterm *y = &D; \
+ xt0 = S1; \
+ xt1 = S2; \
+ xt2 = S3; \
+ xt3 = S4; \
+ y[0] = xt0; \
+ y[1] = xt1; \
+ y[2] = xt2; \
+ y[3] = xt3; \
+ } while (0)
+
+#define MoveWindow5(S1, S2, S3, S4, S5, D) \
+ do { \
+ Eterm xt0, xt1, xt2, xt3, xt4; \
+ Eterm *y = &D; \
+ xt0 = S1; \
+ xt1 = S2; \
+ xt2 = S3; \
+ xt3 = S4; \
+ xt4 = S5; \
+ y[0] = xt0; \
+ y[1] = xt1; \
+ y[2] = xt2; \
+ y[3] = xt3; \
+ y[4] = xt4; \
+ } while (0)
-#define MoveReturn(Src, Dest) \
- (Dest) = (Src); \
- I = c_p->cp; \
- ASSERT(VALID_INSTR(*c_p->cp)); \
- c_p->cp = 0; \
- CHECK_TERM(r(0)); \
+#define MoveReturn(Src) \
+ x(0) = (Src); \
+ I = c_p->cp; \
+ ASSERT(VALID_INSTR(*c_p->cp)); \
+ c_p->cp = 0; \
+ CHECK_TERM(r(0)); \
Goto(*I)
#define DeallocateReturn(Deallocate) \
@@ -586,26 +646,26 @@ void** beam_ops;
Goto(*I); \
} while (0)
-#define MoveDeallocateReturn(Src, Dest, Deallocate) \
- (Dest) = (Src); \
+#define MoveDeallocateReturn(Src, Deallocate) \
+ x(0) = (Src); \
DeallocateReturn(Deallocate)
-#define MoveCall(Src, Dest, CallDest, Size) \
- (Dest) = (Src); \
+#define MoveCall(Src, CallDest, Size) \
+ x(0) = (Src); \
SET_CP(c_p, I+Size+1); \
- SET_I((BeamInstr *) CallDest); \
+ SET_I((BeamInstr *) CallDest); \
Dispatch();
-#define MoveCallLast(Src, Dest, CallDest, Deallocate) \
- (Dest) = (Src); \
- RESTORE_CP(E); \
- E = ADD_BYTE_OFFSET(E, (Deallocate)); \
- SET_I((BeamInstr *) CallDest); \
+#define MoveCallLast(Src, CallDest, Deallocate) \
+ x(0) = (Src); \
+ RESTORE_CP(E); \
+ E = ADD_BYTE_OFFSET(E, (Deallocate)); \
+ SET_I((BeamInstr *) CallDest); \
Dispatch();
-#define MoveCallOnly(Src, Dest, CallDest) \
- (Dest) = (Src); \
- SET_I((BeamInstr *) CallDest); \
+#define MoveCallOnly(Src, CallDest) \
+ x(0) = (Src); \
+ SET_I((BeamInstr *) CallDest); \
Dispatch();
#define MoveJump(Src) \
@@ -613,60 +673,58 @@ void** beam_ops;
SET_I((BeamInstr *) Arg(0)); \
Goto(*I);
-#define GetList(Src, H, T) do { \
- Eterm* tmp_ptr = list_val(Src); \
- H = CAR(tmp_ptr); \
- T = CDR(tmp_ptr); } while (0)
-
-#define GetTupleElement(Src, Element, Dest) \
- do { \
- tmp_arg1 = (Eterm) COMPRESS_POINTER(((unsigned char *) tuple_val(Src)) + \
- (Element)); \
- (Dest) = (*(Eterm *) EXPAND_POINTER(tmp_arg1)); \
- } while (0)
-
-#define ExtractNextElement(Dest) \
- tmp_arg1 += sizeof(Eterm); \
- (Dest) = (* (Eterm *) (((unsigned char *) EXPAND_POINTER(tmp_arg1))))
-
-#define ExtractNextElement2(Dest) \
- do { \
- Eterm* ene_dstp = &(Dest); \
- ene_dstp[0] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[1]; \
- ene_dstp[1] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[2]; \
- tmp_arg1 += sizeof(Eterm) + sizeof(Eterm); \
+#define GetList(Src, H, T) \
+ do { \
+ Eterm* tmp_ptr = list_val(Src); \
+ Eterm hd, tl; \
+ hd = CAR(tmp_ptr); \
+ tl = CDR(tmp_ptr); \
+ H = hd; T = tl; \
} while (0)
-#define ExtractNextElement3(Dest) \
- do { \
- Eterm* ene_dstp = &(Dest); \
- ene_dstp[0] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[1]; \
- ene_dstp[1] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[2]; \
- ene_dstp[2] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[3]; \
- tmp_arg1 += 3*sizeof(Eterm); \
+#define GetTupleElement(Src, Element, Dest) \
+ do { \
+ Eterm* src; \
+ src = ADD_BYTE_OFFSET(tuple_val(Src), (Element)); \
+ (Dest) = *src; \
} while (0)
-#define ExtractNextElement4(Dest) \
- do { \
- Eterm* ene_dstp = &(Dest); \
- ene_dstp[0] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[1]; \
- ene_dstp[1] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[2]; \
- ene_dstp[2] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[3]; \
- ene_dstp[3] = ((Eterm *) EXPAND_POINTER(tmp_arg1))[4]; \
- tmp_arg1 += 4*sizeof(Eterm); \
+#define GetTupleElement2(Src, Element, Dest) \
+ do { \
+ Eterm* src; \
+ Eterm* dst; \
+ Eterm E1, E2; \
+ src = ADD_BYTE_OFFSET(tuple_val(Src), (Element)); \
+ dst = &(Dest); \
+ E1 = src[0]; \
+ E2 = src[1]; \
+ dst[0] = E1; \
+ dst[1] = E2; \
} while (0)
-#define ExtractElement(Element, Dest) \
- do { \
- tmp_arg1 += (Element); \
- (Dest) = (* (Eterm *) EXPAND_POINTER(tmp_arg1)); \
+#define GetTupleElement3(Src, Element, Dest) \
+ do { \
+ Eterm* src; \
+ Eterm* dst; \
+ Eterm E1, E2, E3; \
+ src = ADD_BYTE_OFFSET(tuple_val(Src), (Element)); \
+ dst = &(Dest); \
+ E1 = src[0]; \
+ E2 = src[1]; \
+ E3 = src[2]; \
+ dst[0] = E1; \
+ dst[1] = E2; \
+ dst[2] = E3; \
} while (0)
#define EqualImmed(X, Y, Action) if (X != Y) { Action; }
#define NotEqualImmed(X, Y, Action) if (X == Y) { Action; }
#define EqualExact(X, Y, Action) if (!EQ(X,Y)) { Action; }
-#define IsLessThan(X, Y, Action) if (CMP_GE(X, Y)) { Action; }
-#define IsGreaterEqual(X, Y, Action) if (CMP_LT(X, Y)) { Action; }
+#define NotEqualExact(X, Y, Action) if (EQ(X,Y)) { Action; }
+#define Equal(X, Y, Action) CMP_EQ_ACTION(X,Y,Action)
+#define NotEqual(X, Y, Action) CMP_NE_ACTION(X,Y,Action)
+#define IsLessThan(X, Y, Action) CMP_LT_ACTION(X,Y,Action)
+#define IsGreaterEqual(X, Y, Action) CMP_GE_ACTION(X,Y,Action)
#define IsFloat(Src, Fail) if (is_not_float(Src)) { Fail; }
@@ -690,18 +748,26 @@ void** beam_ops;
if (is_not_list(Src)) { Fail; } \
A(Need, Alive)
-#define IsNonemptyListTestHeap(Src, Need, Alive, Fail) \
- if (is_not_list(Src)) { Fail; } \
+#define IsNonemptyListTestHeap(Need, Alive, Fail) \
+ if (is_not_list(x(0))) { Fail; } \
TestHeap(Need, Alive)
+#define IsNonemptyListGetList(Src, H, T, Fail) \
+ if (is_not_list(Src)) { \
+ Fail; \
+ } else { \
+ Eterm* tmp_ptr = list_val(Src); \
+ Eterm hd, tl; \
+ hd = CAR(tmp_ptr); \
+ tl = CDR(tmp_ptr); \
+ H = hd; T = tl; \
+ }
+
#define IsTuple(X, Action) if (is_not_tuple(X)) Action
-#define IsArity(Pointer, Arity, Fail) \
- if (*(Eterm *) \
- EXPAND_POINTER(tmp_arg1 = (Eterm) \
- COMPRESS_POINTER(tuple_val(Pointer))) != (Arity)) \
- { \
- Fail; \
+#define IsArity(Pointer, Arity, Fail) \
+ if (*tuple_val(Pointer) != (Arity)) { \
+ Fail; \
}
#define IsMap(Src, Fail) if (!is_map(Src)) { Fail; }
@@ -738,15 +804,21 @@ void** beam_ops;
} \
} while (0)
-#define IsTupleOfArity(Src, Arity, Fail) \
- do { \
- if (is_not_tuple(Src) || \
- *(Eterm *) \
- EXPAND_POINTER(tmp_arg1 = \
- (Eterm) COMPRESS_POINTER(tuple_val(Src))) != Arity) { \
- Fail; \
- } \
+#ifdef DEBUG
+#define IsTupleOfArity(Src, Arityval, Fail) \
+ do { \
+ if (!(is_tuple(Src) && *tuple_val(Src) == Arityval)) { \
+ Fail; \
+ } \
} while (0)
+#else
+#define IsTupleOfArity(Src, Arityval, Fail) \
+ do { \
+ if (!(is_boxed(Src) && *tuple_val(Src) == Arityval)) { \
+ Fail; \
+ } \
+ } while (0)
+#endif
#define IsBoolean(X, Fail) if ((X) != am_true && (X) != am_false) { Fail; }
@@ -756,7 +828,7 @@ void** beam_ops;
#define IsBitstring(Src, Fail) \
if (is_not_binary(Src)) { Fail; }
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
#define BsSafeMul(A, B, Fail, Target) \
do { Uint64 _res = (A) * (B); \
if (_res / B != A) { Fail; } \
@@ -773,6 +845,7 @@ void** beam_ops;
#define BsGetFieldSize(Bits, Unit, Fail, Target) \
do { \
Sint _signed_size; Uint _uint_size; \
+ Uint temp_bits; \
if (is_small(Bits)) { \
_signed_size = signed_val(Bits); \
if (_signed_size < 0) { Fail; } \
@@ -787,6 +860,7 @@ void** beam_ops;
#define BsGetUncheckedFieldSize(Bits, Unit, Fail, Target) \
do { \
Sint _signed_size; Uint _uint_size; \
+ Uint temp_bits; \
if (is_small(Bits)) { \
_signed_size = signed_val(Bits); \
if (_signed_size < 0) { Fail; } \
@@ -998,23 +1072,17 @@ init_emulator(void)
*/
#if defined(__GNUC__) && defined(sparc) && !defined(DEBUG)
-# define REG_x0 asm("%l0")
# define REG_xregs asm("%l1")
# define REG_htop asm("%l2")
# define REG_stop asm("%l3")
# define REG_I asm("%l4")
# define REG_fcalls asm("%l5")
-# define REG_tmp_arg1 asm("%l6")
-# define REG_tmp_arg2 asm("%l7")
#else
-# define REG_x0
# define REG_xregs
# define REG_htop
# define REG_stop
# define REG_I
# define REG_fcalls
-# define REG_tmp_arg1
-# define REG_tmp_arg2
#endif
#ifdef USE_VM_PROBES
@@ -1132,11 +1200,6 @@ void process_main(void)
ERTS_DECLARE_DUMMY(Eterm pid);
#endif
- /*
- * X register zero; also called r(0)
- */
- register Eterm x0 REG_x0 = NIL;
-
/* Pointer to X registers: x(1)..x(N); reg[0] is used when doing GC,
* in all other cases x0 is used.
*/
@@ -1164,17 +1227,6 @@ void process_main(void)
register Sint FCALLS REG_fcalls = 0;
/*
- * Temporaries used for picking up arguments for instructions.
- */
- register Eterm tmp_arg1 REG_tmp_arg1 = NIL;
- register Eterm tmp_arg2 REG_tmp_arg2 = NIL;
-#if HEAP_ON_C_STACK
- Eterm tmp_big[2]; /* Temporary buffer for small bignums if HEAP_ON_C_STACK. */
-#else
- Eterm *tmp_big; /* Temporary buffer for small bignums if !HEAP_ON_C_STACK. */
-#endif
-
- /*
* X registers and floating point registers are located in
* scheduler specific data.
*/
@@ -1185,8 +1237,6 @@ void process_main(void)
*/
int neg_o_reds = 0;
- Eterm (*arith_func)(Process* p, Eterm* reg, Uint live);
-
#ifdef ERTS_OPCODE_COUNTER_SUPPORT
static void* counting_opcodes[] = { DEFINE_COUNTING_OPCODES };
#else
@@ -1197,13 +1247,13 @@ void process_main(void)
#endif
#endif
- Uint temp_bits; /* Temporary used by BsSkipBits2 & BsGetInteger2 */
-
Eterm pt_arity; /* Used by do_put_tuple */
Uint64 start_time = 0; /* Monitor long schedule */
BeamInstr* start_time_i = NULL;
+ ERTS_MSACC_DECLARE_CACHE_X() /* a cached value of the tsd pointer for msacc */
+
ERL_BITS_DECLARE_STATEP; /* Has to be last declaration */
@@ -1247,9 +1297,6 @@ void process_main(void)
PROCESS_MAIN_CHK_LOCKS(c_p);
ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p);
-#if HALFWORD_HEAP
- ASSERT(erts_get_scheduler_data()->num_tmp_heap_used == 0);
-#endif
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
c_p = schedule(c_p, reds_used);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
@@ -1260,6 +1307,8 @@ void process_main(void)
ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
+ ERTS_MSACC_UPDATE_CACHE_X();
+
if (erts_system_monitor_long_schedule != 0) {
start_time = erts_timestamp_millis();
start_time_i = c_p->i;
@@ -1267,9 +1316,6 @@ void process_main(void)
reg = ERTS_PROC_GET_SCHDATA(c_p)->x_reg_array;
freg = ERTS_PROC_GET_SCHDATA(c_p)->f_reg_array;
-#if !HEAP_ON_C_STACK
- tmp_big = ERTS_PROC_GET_SCHDATA(c_p)->beam_emu_tmp_heap;
-#endif
ERL_BITS_RELOAD_STATEP(c_p);
{
int reds;
@@ -1278,7 +1324,7 @@ void process_main(void)
int i;
argp = c_p->arg_reg;
- for (i = c_p->arity - 1; i > 0; i--) {
+ for (i = c_p->arity - 1; i >= 0; i--) {
reg[i] = argp[i];
CHECK_TERM(reg[i]);
}
@@ -1302,12 +1348,6 @@ void process_main(void)
}
next = (BeamInstr *) *I;
- r(0) = c_p->arg_reg[0];
-#ifdef HARDDEBUG
- if (c_p->arity > 0) {
- CHECK_TERM(r(0));
- }
-#endif
SWAPIN;
ASSERT(VALID_INSTR(next));
@@ -1346,26 +1386,24 @@ void process_main(void)
#endif
#include "beam_hot.h"
-#define STORE_ARITH_RESULT(res) StoreBifResult(2, (res));
-#define ARITH_FUNC(name) erts_gc_##name
-
{
Eterm increment_reg_val;
Eterm increment_val;
Uint live;
Eterm result;
- OpCase(i_increment_yIId):
- increment_reg_val = yb(Arg(0));
+ OpCase(i_increment_rIId):
+ increment_reg_val = x(0);
+ I--;
goto do_increment;
OpCase(i_increment_xIId):
increment_reg_val = xb(Arg(0));
goto do_increment;
- OpCase(i_increment_rIId):
- increment_reg_val = r(0);
- I--;
+ OpCase(i_increment_yIId):
+ increment_reg_val = yb(Arg(0));
+ goto do_increment;
do_increment:
increment_val = Arg(1);
@@ -1374,229 +1412,133 @@ void process_main(void)
ASSERT(MY_IS_SSMALL(i) == IS_SSMALL(i));
if (MY_IS_SSMALL(i)) {
result = make_small(i);
- store_result:
StoreBifResult(3, result);
}
}
live = Arg(2);
- SWAPOUT;
- reg[0] = r(0);
+ HEAVY_SWAPOUT;
reg[live] = increment_reg_val;
reg[live+1] = make_small(increment_val);
result = erts_gc_mixed_plus(c_p, reg, live);
- r(0) = reg[0];
- SWAPIN;
+ HEAVY_SWAPIN;
ERTS_HOLE_CHECK(c_p);
if (is_value(result)) {
- goto store_result;
+ StoreBifResult(3, result);
}
ASSERT(c_p->freason != BADMATCH || is_value(c_p->fvalue));
goto find_func_info;
}
-#define DO_BIG_ARITH(Func,Arg1,Arg2) \
- do { \
- Uint live = Arg(1); \
- SWAPOUT; \
- reg[0] = r(0); \
- reg[live] = (Arg1); \
- reg[live+1] = (Arg2); \
- result = (Func)(c_p, reg, live); \
- r(0) = reg[0]; \
- SWAPIN; \
- ERTS_HOLE_CHECK(c_p); \
- if (is_value(result)) { \
- StoreBifResult(4,result); \
- } \
- goto lb_Cl_error; \
- } while(0)
+#define DO_OUTLINED_ARITH_2(name, Op1, Op2) \
+ do { \
+ Eterm result; \
+ Uint live = Arg(1); \
+ \
+ HEAVY_SWAPOUT; \
+ reg[live] = Op1; \
+ reg[live+1] = Op2; \
+ result = erts_gc_##name(c_p, reg, live); \
+ HEAVY_SWAPIN; \
+ ERTS_HOLE_CHECK(c_p); \
+ if (is_value(result)) { \
+ StoreBifResult(4, result); \
+ } \
+ goto lb_Cl_error; \
+ } while (0)
- OpCase(i_plus_jIxxd):
{
+ Eterm PlusOp1, PlusOp2;
Eterm result;
- if (is_both_small(xb(Arg(2)), xb(Arg(3)))) {
- Sint i = signed_val(xb(Arg(2))) + signed_val(xb(Arg(3)));
+ OpCase(i_plus_jIxxd):
+ PlusOp1 = xb(Arg(2));
+ PlusOp2 = xb(Arg(3));
+ goto do_plus;
+
+ OpCase(i_plus_jIxyd):
+ PlusOp1 = xb(Arg(2));
+ PlusOp2 = yb(Arg(3));
+ goto do_plus;
+
+ OpCase(i_plus_jIssd):
+ GetArg2(2, PlusOp1, PlusOp2);
+ goto do_plus;
+
+ do_plus:
+ if (is_both_small(PlusOp1, PlusOp2)) {
+ Sint i = signed_val(PlusOp1) + signed_val(PlusOp2);
ASSERT(MY_IS_SSMALL(i) == IS_SSMALL(i));
if (MY_IS_SSMALL(i)) {
result = make_small(i);
StoreBifResult(4, result);
}
}
- DO_BIG_ARITH(ARITH_FUNC(mixed_plus), xb(Arg(2)), xb(Arg(3)));
+ DO_OUTLINED_ARITH_2(mixed_plus, PlusOp1, PlusOp2);
}
- OpCase(i_plus_jId):
{
+ Eterm MinusOp1, MinusOp2;
Eterm result;
- if (is_both_small(tmp_arg1, tmp_arg2)) {
- Sint i = signed_val(tmp_arg1) + signed_val(tmp_arg2);
- ASSERT(MY_IS_SSMALL(i) == IS_SSMALL(i));
- if (MY_IS_SSMALL(i)) {
- result = make_small(i);
- STORE_ARITH_RESULT(result);
- }
- }
- arith_func = ARITH_FUNC(mixed_plus);
- goto do_big_arith2;
- }
-
OpCase(i_minus_jIxxd):
- {
- Eterm result;
+ MinusOp1 = xb(Arg(2));
+ MinusOp2 = xb(Arg(3));
+ goto do_minus;
- if (is_both_small(xb(Arg(2)), xb(Arg(3)))) {
- Sint i = signed_val(xb(Arg(2))) - signed_val(xb(Arg(3)));
- ASSERT(MY_IS_SSMALL(i) == IS_SSMALL(i));
- if (MY_IS_SSMALL(i)) {
- result = make_small(i);
- StoreBifResult(4, result);
- }
- }
- DO_BIG_ARITH(ARITH_FUNC(mixed_minus), xb(Arg(2)), xb(Arg(3)));
- }
+ OpCase(i_minus_jIssd):
+ GetArg2(2, MinusOp1, MinusOp2);
+ goto do_minus;
- OpCase(i_minus_jId):
- {
- Eterm result;
-
- if (is_both_small(tmp_arg1, tmp_arg2)) {
- Sint i = signed_val(tmp_arg1) - signed_val(tmp_arg2);
+ do_minus:
+ if (is_both_small(MinusOp1, MinusOp2)) {
+ Sint i = signed_val(MinusOp1) - signed_val(MinusOp2);
ASSERT(MY_IS_SSMALL(i) == IS_SSMALL(i));
if (MY_IS_SSMALL(i)) {
result = make_small(i);
- STORE_ARITH_RESULT(result);
+ StoreBifResult(4, result);
}
}
- arith_func = ARITH_FUNC(mixed_minus);
- goto do_big_arith2;
+ DO_OUTLINED_ARITH_2(mixed_minus, MinusOp1, MinusOp2);
}
- OpCase(i_is_lt_f):
- if (CMP_GE(tmp_arg1, tmp_arg2)) {
- ClauseFail();
- }
- Next(1);
-
- OpCase(i_is_ge_f):
- if (CMP_LT(tmp_arg1, tmp_arg2)) {
- ClauseFail();
- }
- Next(1);
-
- OpCase(i_is_eq_f):
- if (CMP_NE(tmp_arg1, tmp_arg2)) {
- ClauseFail();
- }
- Next(1);
-
- OpCase(i_is_ne_f):
- if (CMP_EQ(tmp_arg1, tmp_arg2)) {
- ClauseFail();
- }
- Next(1);
-
- OpCase(i_is_eq_exact_f):
- if (!EQ(tmp_arg1, tmp_arg2)) {
- ClauseFail();
- }
- Next(1);
-
{
Eterm is_eq_exact_lit_val;
- OpCase(i_is_eq_exact_literal_xfc):
- is_eq_exact_lit_val = xb(Arg(0));
- I++;
+ OpCase(i_is_eq_exact_literal_fxc):
+ is_eq_exact_lit_val = xb(Arg(1));
goto do_is_eq_exact_literal;
- OpCase(i_is_eq_exact_literal_yfc):
- is_eq_exact_lit_val = yb(Arg(0));
- I++;
+ OpCase(i_is_eq_exact_literal_fyc):
+ is_eq_exact_lit_val = yb(Arg(1));
goto do_is_eq_exact_literal;
- OpCase(i_is_eq_exact_literal_rfc):
- is_eq_exact_lit_val = r(0);
-
do_is_eq_exact_literal:
- if (!eq(Arg(1), is_eq_exact_lit_val)) {
+ if (!eq(Arg(2), is_eq_exact_lit_val)) {
ClauseFail();
}
- Next(2);
+ Next(3);
}
{
Eterm is_ne_exact_lit_val;
- OpCase(i_is_ne_exact_literal_xfc):
- is_ne_exact_lit_val = xb(Arg(0));
- I++;
+ OpCase(i_is_ne_exact_literal_fxc):
+ is_ne_exact_lit_val = xb(Arg(1));
goto do_is_ne_exact_literal;
- OpCase(i_is_ne_exact_literal_yfc):
- is_ne_exact_lit_val = yb(Arg(0));
- I++;
+ OpCase(i_is_ne_exact_literal_fyc):
+ is_ne_exact_lit_val = yb(Arg(1));
goto do_is_ne_exact_literal;
- OpCase(i_is_ne_exact_literal_rfc):
- is_ne_exact_lit_val = r(0);
-
do_is_ne_exact_literal:
- if (eq(Arg(1), is_ne_exact_lit_val)) {
+ if (eq(Arg(2), is_ne_exact_lit_val)) {
ClauseFail();
}
- Next(2);
+ Next(3);
}
- OpCase(move_window3_xxxy): {
- BeamInstr *next;
- Eterm xt0, xt1, xt2;
- Eterm *y = (Eterm *)(((unsigned char *)E) + (Arg(3)));
- PreFetch(4, next);
- xt0 = xb(Arg(0));
- xt1 = xb(Arg(1));
- xt2 = xb(Arg(2));
- y[0] = xt0;
- y[1] = xt1;
- y[2] = xt2;
- NextPF(4, next);
- }
- OpCase(move_window4_xxxxy): {
- BeamInstr *next;
- Eterm xt0, xt1, xt2, xt3;
- Eterm *y = (Eterm *)(((unsigned char *)E) + (Arg(4)));
- PreFetch(5, next);
- xt0 = xb(Arg(0));
- xt1 = xb(Arg(1));
- xt2 = xb(Arg(2));
- xt3 = xb(Arg(3));
- y[0] = xt0;
- y[1] = xt1;
- y[2] = xt2;
- y[3] = xt3;
- NextPF(5, next);
- }
- OpCase(move_window5_xxxxxy): {
- BeamInstr *next;
- Eterm xt0, xt1, xt2, xt3, xt4;
- Eterm *y = (Eterm *)(((unsigned char *)E) + (Arg(5)));
- PreFetch(6, next);
- xt0 = xb(Arg(0));
- xt1 = xb(Arg(1));
- xt2 = xb(Arg(2));
- xt3 = xb(Arg(3));
- xt4 = xb(Arg(4));
- y[0] = xt0;
- y[1] = xt1;
- y[2] = xt2;
- y[3] = xt3;
- y[4] = xt4;
- NextPF(6, next);
- }
-
- OpCase(i_move_call_only_fcr): {
+ OpCase(i_move_call_only_fc): {
r(0) = Arg(1);
}
/* FALL THROUGH */
@@ -1606,7 +1548,7 @@ void process_main(void)
Dispatch();
}
- OpCase(i_move_call_last_fPcr): {
+ OpCase(i_move_call_last_fPc): {
r(0) = Arg(2);
}
/* FALL THROUGH */
@@ -1618,7 +1560,7 @@ void process_main(void)
Dispatch();
}
- OpCase(i_move_call_crf): {
+ OpCase(i_move_call_cf): {
r(0) = Arg(0);
I++;
}
@@ -1630,7 +1572,7 @@ void process_main(void)
Dispatch();
}
- OpCase(i_move_call_ext_last_ePcr): {
+ OpCase(i_move_call_ext_last_ePc): {
r(0) = Arg(2);
}
/* FALL THROUGH */
@@ -1646,7 +1588,7 @@ void process_main(void)
DTRACE_GLOBAL_CALL_FROM_EXPORT(c_p, Arg(0));
Dispatchx();
- OpCase(i_move_call_ext_cre): {
+ OpCase(i_move_call_ext_ce): {
r(0) = Arg(0);
I++;
}
@@ -1656,7 +1598,7 @@ void process_main(void)
DTRACE_GLOBAL_CALL_FROM_EXPORT(c_p, Arg(0));
Dispatchx();
- OpCase(i_move_call_ext_only_ecr): {
+ OpCase(i_move_call_ext_only_ec): {
r(0) = Arg(1);
}
/* FALL THROUGH */
@@ -1722,17 +1664,11 @@ void process_main(void)
PRE_BIF_SWAPOUT(c_p);
c_p->fcalls = FCALLS - 1;
- reg[0] = r(0);
result = erl_send(c_p, r(0), x(1));
PreFetch(0, next);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
- if (c_p->mbuf || MSO(c_p).overhead >= BIN_VHEAP_SZ(c_p)) {
- result = erts_gc_after_bif_call(c_p, result, reg, 2);
- r(0) = reg[0];
- E = c_p->stop;
- }
HTOP = HEAP_TOP(c_p);
FCALLS = c_p->fcalls;
if (is_value(result)) {
@@ -1743,7 +1679,6 @@ void process_main(void)
SET_CP(c_p, I+1);
SET_I(c_p->i);
SWAPIN;
- r(0) = reg[0];
Dispatch();
}
goto find_func_info;
@@ -1753,29 +1688,23 @@ void process_main(void)
Eterm element_index;
Eterm element_tuple;
- OpCase(i_element_xjsd):
- element_tuple = xb(Arg(0));
- I++;
+ OpCase(i_element_jxsd):
+ element_tuple = xb(Arg(1));
goto do_element;
- OpCase(i_element_yjsd):
- element_tuple = yb(Arg(0));
- I++;
+ OpCase(i_element_jysd):
+ element_tuple = yb(Arg(1));
goto do_element;
- OpCase(i_element_rjsd):
- element_tuple = r(0);
- /* Fall through */
-
do_element:
- GetArg1(1, element_index);
+ GetArg1(2, element_index);
if (is_small(element_index) && is_tuple(element_tuple)) {
Eterm* tp = tuple_val(element_tuple);
if ((signed_val(element_index) >= 1) &&
(signed_val(element_index) <= arityval(*tp))) {
Eterm result = tp[signed_val(element_index)];
- StoreBifResult(2, result);
+ StoreBifResult(3, result);
}
}
}
@@ -1789,29 +1718,24 @@ void process_main(void)
{
Eterm fast_element_tuple;
- OpCase(i_fast_element_rjId):
- fast_element_tuple = r(0);
+ OpCase(i_fast_element_jxId):
+ fast_element_tuple = xb(Arg(1));
+ goto do_fast_element;
+
+ OpCase(i_fast_element_jyId):
+ fast_element_tuple = yb(Arg(1));
+ goto do_fast_element;
do_fast_element:
if (is_tuple(fast_element_tuple)) {
Eterm* tp = tuple_val(fast_element_tuple);
- Eterm pos = Arg(1); /* Untagged integer >= 1 */
+ Eterm pos = Arg(2); /* Untagged integer >= 1 */
if (pos <= arityval(*tp)) {
Eterm result = tp[pos];
- StoreBifResult(2, result);
+ StoreBifResult(3, result);
}
}
goto badarg;
-
- OpCase(i_fast_element_xjId):
- fast_element_tuple = xb(Arg(0));
- I++;
- goto do_fast_element;
-
- OpCase(i_fast_element_yjId):
- fast_element_tuple = yb(Arg(0));
- I++;
- goto do_fast_element;
}
OpCase(catch_yf):
@@ -1832,11 +1756,10 @@ void process_main(void)
SWAPIN;
}
/* only x(2) is included in the rootset here */
- if (E - HTOP < 3 || c_p->mbuf) { /* Force GC in case add_stacktrace()
- * created heap fragments */
+ if (E - HTOP < 3) {
SWAPOUT;
PROCESS_MAIN_CHK_LOCKS(c_p);
- FCALLS -= erts_garbage_collect(c_p, 3, reg+2, 1);
+ FCALLS -= erts_garbage_collect_nobump(c_p, 3, reg+2, 1);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
SWAPIN;
@@ -1917,13 +1840,20 @@ void process_main(void)
* Pick up the next message and place it in x(0).
* If no message, jump to a wait or wait_timeout instruction.
*/
- OpCase(i_loop_rec_fr):
+ OpCase(i_loop_rec_f):
{
BeamInstr *next;
- ErlMessage* msgp;
+ ErtsMessage* msgp;
- loop_rec__:
+ /*
+ * We need to disable GC while matching messages
+ * in the queue. This since messages with data outside
+ * the heap will be corrupted by a GC.
+ */
+ ASSERT(!(c_p->flags & F_DELAY_GC));
+ c_p->flags |= F_DELAY_GC;
+ loop_rec__:
PROCESS_MAIN_CHK_LOCKS(c_p);
msgp = PEEK_MESSAGE(c_p);
@@ -1935,6 +1865,7 @@ void process_main(void)
if (ERTS_PROC_PENDING_EXIT(c_p)) {
erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE);
SWAPOUT;
+ c_p->flags &= ~F_DELAY_GC;
goto do_schedule; /* Will be rescheduled for exit */
}
ERTS_SMP_MSGQ_MV_INQ2PRIVQ(c_p);
@@ -1944,32 +1875,27 @@ void process_main(void)
else
#endif
{
+ c_p->flags &= ~F_DELAY_GC;
SET_I((BeamInstr *) Arg(0));
Goto(*I); /* Jump to a wait or wait_timeout instruction */
}
}
- ErtsMoveMsgAttachmentIntoProc(msgp, c_p, E, HTOP, FCALLS,
- {
- SWAPOUT;
- reg[0] = r(0);
- PROCESS_MAIN_CHK_LOCKS(c_p);
- },
- {
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- PROCESS_MAIN_CHK_LOCKS(c_p);
- r(0) = reg[0];
- SWAPIN;
- });
if (is_non_value(ERL_MESSAGE_TERM(msgp))) {
- /*
- * A corrupt distribution message that we weren't able to decode;
- * remove it...
- */
- ASSERT(!msgp->data.attached);
- /* TODO: Add DTrace probe for this bad message situation? */
- UNLINK_MESSAGE(c_p, msgp);
- free_message(msgp);
- goto loop_rec__;
+ SWAPOUT; /* erts_decode_dist_message() may write to heap... */
+ if (!erts_decode_dist_message(c_p, ERTS_PROC_LOCK_MAIN, msgp, 0)) {
+ /*
+ * A corrupt distribution message that we weren't able to decode;
+ * remove it...
+ */
+ /* No swapin should be needed */
+ ASSERT(HTOP == c_p->htop && E == c_p->stop);
+ /* TODO: Add DTrace probe for this bad message situation? */
+ UNLINK_MESSAGE(c_p, msgp);
+ msgp->next = NULL;
+ erts_cleanup_messages(msgp);
+ goto loop_rec__;
+ }
+ SWAPIN;
}
PreFetch(1, next);
r(0) = ERL_MESSAGE_TERM(msgp);
@@ -1981,8 +1907,7 @@ void process_main(void)
*/
OpCase(remove_message): {
BeamInstr *next;
- ErlMessage* msgp;
-
+ ErtsMessage* msgp;
PROCESS_MAIN_CHK_LOCKS(c_p);
PreFetch(0, next);
@@ -1996,20 +1921,7 @@ void process_main(void)
if (DT_UTAG(c_p) != NIL) {
if (DT_UTAG_FLAGS(c_p) & DT_UTAG_PERMANENT) {
SEQ_TRACE_TOKEN(c_p) = am_have_dt_utag;
-#ifdef DTRACE_TAG_HARDDEBUG
- if (DT_UTAG_FLAGS(c_p) & DT_UTAG_SPREADING)
- erts_fprintf(stderr,
- "Dtrace -> (%T) stop spreading "
- "tag %T with message %T\r\n",
- c_p->common.id,DT_UTAG(c_p),ERL_MESSAGE_TERM(msgp));
-#endif
} else {
-#ifdef DTRACE_TAG_HARDDEBUG
- erts_fprintf(stderr,
- "Dtrace -> (%T) kill tag %T with "
- "message %T\r\n",
- c_p->common.id,DT_UTAG(c_p),ERL_MESSAGE_TERM(msgp));
-#endif
DT_UTAG(c_p) = NIL;
SEQ_TRACE_TOKEN(c_p) = NIL;
}
@@ -2029,12 +1941,6 @@ void process_main(void)
DT_UTAG(c_p) = ERL_MESSAGE_DT_UTAG(msgp);
}
DT_UTAG_FLAGS(c_p) |= DT_UTAG_SPREADING;
-#ifdef DTRACE_TAG_HARDDEBUG
- erts_fprintf(stderr,
- "Dtrace -> (%T) receive tag (%T) "
- "with message %T\r\n",
- c_p->common.id, DT_UTAG(c_p), ERL_MESSAGE_TERM(msgp));
-#endif
} else {
#endif
ASSERT(is_tuple(SEQ_TRACE_TOKEN(c_p)));
@@ -2064,7 +1970,7 @@ void process_main(void)
dtrace_proc_str(c_p, receiver_name);
token2 = SEQ_TRACE_TOKEN(c_p);
- if (token2 != NIL && token2 != am_have_dt_utag) {
+ if (have_seqtrace(token2)) {
tok_label = signed_val(SEQ_TRACE_T_LABEL(token2));
tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token2));
tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token2));
@@ -2077,11 +1983,21 @@ void process_main(void)
UNLINK_MESSAGE(c_p, msgp);
JOIN_MESSAGE(c_p);
CANCEL_TIMER(c_p);
- free_message(msgp);
+
+ erts_save_message_in_proc(c_p, msgp);
+ c_p->flags &= ~F_DELAY_GC;
+
+ if (ERTS_IS_GC_DESIRED_INTERNAL(c_p, HTOP, E)) {
+ /*
+ * We want to GC soon but we leave a few
+ * reductions giving the message some time
+ * to turn into garbage.
+ */
+ ERTS_VBUMP_LEAVE_REDS_INTERNAL(c_p, 5, FCALLS);
+ }
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
-
NextPF(0, next);
}
@@ -2090,9 +2006,22 @@ void process_main(void)
* message didn't match), then jump to the loop_rec instruction.
*/
OpCase(loop_rec_end_f): {
+
+ ASSERT(c_p->flags & F_DELAY_GC);
+
SET_I((BeamInstr *) Arg(0));
SAVE_MESSAGE(c_p);
- goto loop_rec__;
+ if (FCALLS > 0 || FCALLS > neg_o_reds) {
+ FCALLS--;
+ goto loop_rec__;
+ }
+
+ c_p->flags &= ~F_DELAY_GC;
+ c_p->i = I;
+ SWAPOUT;
+ c_p->arity = 0;
+ c_p->current = NULL;
+ goto do_schedule;
}
/*
* Prepare to wait for a message or a timeout, whichever occurs first.
@@ -2131,8 +2060,6 @@ void process_main(void)
* c_p->def_arg_reg[0]. Note that it is safe to use this
* location because there are no living x registers in
* a receive statement.
- * Note that for the halfword emulator, the two first elements
- * of the array are used.
*/
BeamInstr** pi = (BeamInstr**) c_p->def_arg_reg;
*pi = I+3;
@@ -2249,10 +2176,6 @@ void process_main(void)
select_val2 = xb(Arg(0));
goto do_select_tuple_arity2;
- OpCase(i_select_tuple_arity2_rfAAff):
- select_val2 = r(0);
- I--;
-
do_select_tuple_arity2:
if (is_not_tuple(select_val2)) {
goto select_val2_fail;
@@ -2268,10 +2191,6 @@ void process_main(void)
select_val2 = xb(Arg(0));
goto do_select_val2;
- OpCase(i_select_val2_rfccff):
- select_val2 = r(0);
- I--;
-
do_select_val2:
if (select_val2 == Arg(2)) {
I += 3;
@@ -2295,10 +2214,6 @@ void process_main(void)
select_val = yb(Arg(0));
goto do_select_tuple_arity;
- OpCase(i_select_tuple_arity_rfI):
- select_val = r(0);
- I--;
-
do_select_tuple_arity:
if (is_tuple(select_val)) {
select_val = *tuple_val(select_val);
@@ -2315,10 +2230,6 @@ void process_main(void)
select_val = yb(Arg(0));
goto do_linear_search;
- OpCase(i_select_val_lins_rfI):
- select_val = r(0);
- I--;
-
do_linear_search: {
BeamInstr *vs = &Arg(3);
int ix = 0;
@@ -2345,10 +2256,6 @@ void process_main(void)
select_val = yb(Arg(0));
goto do_binary_search;
- OpCase(i_select_val_bins_rfI):
- select_val = r(0);
- I--;
-
do_binary_search:
{
struct Pairs {
@@ -2409,10 +2316,6 @@ void process_main(void)
jump_on_val_zero_index = xb(Arg(0));
goto do_jump_on_val_zero_index;
- OpCase(i_jump_on_val_zero_rfI):
- jump_on_val_zero_index = r(0);
- I--;
-
do_jump_on_val_zero_index:
if (is_small(jump_on_val_zero_index)) {
jump_on_val_zero_index = signed_val(jump_on_val_zero_index);
@@ -2437,10 +2340,6 @@ void process_main(void)
jump_on_val_index = xb(Arg(0));
goto do_jump_on_val_index;
- OpCase(i_jump_on_val_rfII):
- jump_on_val_index = r(0);
- I--;
-
do_jump_on_val_index:
if (is_small(jump_on_val_index)) {
jump_on_val_index = (Uint) (signed_val(jump_on_val_index) - Arg(3));
@@ -2460,15 +2359,12 @@ void process_main(void)
do {
Eterm term = *I++;
- switch (term & _TAG_IMMED1_MASK) {
- case (R_REG_DEF << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_HEADER:
- *hp++ = r(0);
- break;
- case (X_REG_DEF << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_HEADER:
- *hp++ = x(term >> _TAG_IMMED1_SIZE);
+ switch (loader_tag(term)) {
+ case LOADER_X_REG:
+ *hp++ = x(loader_x_reg_index(term));
break;
- case (Y_REG_DEF << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_HEADER:
- *hp++ = y(term >> _TAG_IMMED1_SIZE);
+ case LOADER_Y_REG:
+ *hp++ = y(loader_y_reg_index(term));
break;
default:
*hp++ = term;
@@ -2482,31 +2378,26 @@ void process_main(void)
OpCase(new_map_dII): {
Eterm res;
- x(0) = r(0);
- SWAPOUT;
+ HEAVY_SWAPOUT;
res = new_map(c_p, reg, I-1);
- SWAPIN;
- r(0) = x(0);
+ HEAVY_SWAPIN;
StoreResult(res, Arg(0));
Next(3+Arg(2));
}
-#define PUT_TERM_REG(term, desc) \
-do { \
- switch ((desc) & _TAG_IMMED1_MASK) { \
- case (R_REG_DEF << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_HEADER: \
- r(0) = (term); \
- break; \
- case (X_REG_DEF << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_HEADER: \
- x((desc) >> _TAG_IMMED1_SIZE) = (term); \
- break; \
- case (Y_REG_DEF << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_HEADER: \
- y((desc) >> _TAG_IMMED1_SIZE) = (term); \
- break; \
- default: \
- ASSERT(0); \
- break; \
- } \
+#define PUT_TERM_REG(term, desc) \
+do { \
+ switch (loader_tag(desc)) { \
+ case LOADER_X_REG: \
+ x(loader_x_reg_index(desc)) = (term); \
+ break; \
+ case LOADER_Y_REG: \
+ y(loader_y_reg_index(desc)) = (term); \
+ break; \
+ default: \
+ ASSERT(0); \
+ break; \
+ } \
} while(0)
OpCase(i_get_map_elements_fsI): {
@@ -2577,12 +2468,10 @@ do { \
Eterm map;
GetArg1(1, map);
- x(0) = r(0);
- SWAPOUT;
+ HEAVY_SWAPOUT;
res = update_map_assoc(c_p, reg, map, I);
- SWAPIN;
+ HEAVY_SWAPIN;
if (is_value(res)) {
- r(0) = x(0);
StoreResult(res, Arg(2));
Next(5+Arg(4));
} else {
@@ -2601,12 +2490,10 @@ do { \
Eterm map;
GetArg1(1, map);
- x(0) = r(0);
- SWAPOUT;
+ HEAVY_SWAPOUT;
res = update_map_exact(c_p, reg, map, I);
- SWAPIN;
+ HEAVY_SWAPIN;
if (is_value(res)) {
- r(0) = x(0);
StoreResult(res, Arg(2));
Next(5+Arg(4));
} else {
@@ -2688,13 +2575,10 @@ do { \
{
typedef Eterm (*GcBifFunction)(Process*, Eterm*, Uint);
GcBifFunction bf;
- Eterm arg;
Eterm result;
Uint live = (Uint) Arg(3);
- GetArg1(2, arg);
- reg[0] = r(0);
- reg[live] = arg;
+ GetArg1(2, x(live));
bf = (GcBifFunction) Arg(1);
c_p->fcalls = FCALLS;
SWAPOUT;
@@ -2705,7 +2589,6 @@ do { \
ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
SWAPIN;
- r(0) = reg[0];
ERTS_HOLE_CHECK(c_p);
FCALLS = c_p->fcalls;
if (is_value(result)) {
@@ -2715,12 +2598,12 @@ do { \
SET_I((BeamInstr *) Arg(0));
Goto(*I);
}
- reg[0] = arg;
+ x(0) = x(live);
I = handle_error(c_p, I, reg, translate_gc_bif((void *) bf));
goto post_error_handling;
}
- OpCase(i_gc_bif2_jIId): /* Note, one less parameter than the i_gc_bif1
+ OpCase(i_gc_bif2_jIIssd): /* Note, one less parameter than the i_gc_bif1
and i_gc_bif3 */
{
typedef Eterm (*GcBifFunction)(Process*, Eterm*, Uint);
@@ -2728,9 +2611,13 @@ do { \
Eterm result;
Uint live = (Uint) Arg(2);
- reg[0] = r(0);
- reg[live++] = tmp_arg1;
- reg[live] = tmp_arg2;
+ GetArg2(3, x(live), x(live+1));
+ /*
+ * XXX This calling convention does not make sense. 'live'
+ * should point out the first argument, not the second
+ * (i.e. 'live' should not be incremented below).
+ */
+ live++;
bf = (GcBifFunction) Arg(1);
c_p->fcalls = FCALLS;
SWAPOUT;
@@ -2741,35 +2628,37 @@ do { \
ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
SWAPIN;
- r(0) = reg[0];
ERTS_HOLE_CHECK(c_p);
FCALLS = c_p->fcalls;
if (is_value(result)) {
- StoreBifResult(3, result);
+ StoreBifResult(5, result);
}
if (Arg(0) != 0) {
SET_I((BeamInstr *) Arg(0));
Goto(*I);
}
- reg[0] = tmp_arg1;
- reg[1] = tmp_arg2;
+ live--;
+ x(0) = x(live);
+ x(1) = x(live+1);
I = handle_error(c_p, I, reg, translate_gc_bif((void *) bf));
goto post_error_handling;
}
- OpCase(i_gc_bif3_jIsId):
+ OpCase(i_gc_bif3_jIIssd):
{
typedef Eterm (*GcBifFunction)(Process*, Eterm*, Uint);
GcBifFunction bf;
- Eterm arg;
Eterm result;
- Uint live = (Uint) Arg(3);
+ Uint live = (Uint) Arg(2);
- GetArg1(2, arg);
- reg[0] = r(0);
- reg[live++] = arg;
- reg[live++] = tmp_arg1;
- reg[live] = tmp_arg2;
+ x(live) = x(SCRATCH_X_REG);
+ GetArg2(3, x(live+1), x(live+2));
+ /*
+ * XXX This calling convention does not make sense. 'live'
+ * should point out the first argument, not the third
+ * (i.e. 'live' should not be incremented below).
+ */
+ live += 2;
bf = (GcBifFunction) Arg(1);
c_p->fcalls = FCALLS;
SWAPOUT;
@@ -2780,19 +2669,19 @@ do { \
ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
SWAPIN;
- r(0) = reg[0];
ERTS_HOLE_CHECK(c_p);
FCALLS = c_p->fcalls;
if (is_value(result)) {
- StoreBifResult(4, result);
+ StoreBifResult(5, result);
}
if (Arg(0) != 0) {
SET_I((BeamInstr *) Arg(0));
Goto(*I);
}
- reg[0] = arg;
- reg[1] = tmp_arg1;
- reg[2] = tmp_arg2;
+ live -= 2;
+ x(0) = x(live);
+ x(1) = x(live+1);
+ x(2) = x(live+2);
I = handle_error(c_p, I, reg, translate_gc_bif((void *) bf));
goto post_error_handling;
}
@@ -2800,12 +2689,13 @@ do { \
/*
* Guards bifs and, or, xor in guards.
*/
- OpCase(i_bif2_fbd):
+ OpCase(i_bif2_fbssd):
{
- Eterm tmp_reg[2] = {tmp_arg1, tmp_arg2};
+ Eterm tmp_reg[2];
Eterm (*bf)(Process*, Eterm*);
Eterm result;
+ GetArg2(2, tmp_reg[0], tmp_reg[1]);
bf = (BifFunction) Arg(1);
c_p->fcalls = FCALLS;
PROCESS_MAIN_CHK_LOCKS(c_p);
@@ -2817,7 +2707,7 @@ do { \
ERTS_HOLE_CHECK(c_p);
FCALLS = c_p->fcalls;
if (is_value(result)) {
- StoreBifResult(2, result);
+ StoreBifResult(4, result);
}
SET_I((BeamInstr *) Arg(0));
Goto(*I);
@@ -2826,12 +2716,13 @@ do { \
/*
* Guards bifs and, or, xor, relational operators in body.
*/
- OpCase(i_bif2_body_bd):
+ OpCase(i_bif2_body_bssd):
{
- Eterm tmp_reg[2] = {tmp_arg1, tmp_arg2};
+ Eterm tmp_reg[2];
Eterm (*bf)(Process*, Eterm*);
Eterm result;
+ GetArg2(1, tmp_reg[0], tmp_reg[1]);
bf = (BifFunction) Arg(0);
PROCESS_MAIN_CHK_LOCKS(c_p);
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
@@ -2842,10 +2733,10 @@ do { \
ERTS_HOLE_CHECK(c_p);
if (is_value(result)) {
ASSERT(!is_CP(result));
- StoreBifResult(1, result);
+ StoreBifResult(3, result);
}
- reg[0] = tmp_arg1;
- reg[1] = tmp_arg2;
+ reg[0] = tmp_reg[0];
+ reg[1] = tmp_reg[1];
SWAPOUT;
I = handle_error(c_p, I, reg, bf);
goto post_error_handling;
@@ -2857,9 +2748,20 @@ do { \
*/
OpCase(call_bif_e):
{
- Eterm (*bf)(Process*, Eterm*, BeamInstr*) = GET_BIF_ADDRESS(Arg(0));
+ Eterm (*bf)(Process*, Eterm*, BeamInstr*);
Eterm result;
BeamInstr *next;
+ ErlHeapFragment *live_hf_end;
+
+ if (ERTS_MSACC_IS_ENABLED_CACHED_X()) {
+ if (GET_BIF_MODULE(Arg(0)) == am_ets) {
+ ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_ETS);
+ } else {
+ ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_BIF);
+ }
+ }
+
+ bf = GET_BIF_ADDRESS(Arg(0));
PRE_BIF_SWAPOUT(c_p);
c_p->fcalls = FCALLS - 1;
@@ -2869,20 +2771,26 @@ do { \
PreFetch(1, next);
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- reg[0] = r(0);
+ live_hf_end = c_p->mbuf;
result = (*bf)(c_p, reg, I);
ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
ERTS_HOLE_CHECK(c_p);
ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
- PROCESS_MAIN_CHK_LOCKS(c_p);
- if (c_p->mbuf || MSO(c_p).overhead >= BIN_VHEAP_SZ(c_p)) {
+ if (ERTS_IS_GC_DESIRED(c_p)) {
Uint arity = ((Export *)Arg(0))->code[2];
- result = erts_gc_after_bif_call(c_p, result, reg, arity);
+ result = erts_gc_after_bif_call_lhf(c_p, live_hf_end, result, reg, arity);
E = c_p->stop;
}
+ PROCESS_MAIN_CHK_LOCKS(c_p);
HTOP = HEAP_TOP(c_p);
FCALLS = c_p->fcalls;
+ /* We have to update the cache if we are enabled in order
+ to make sure no book keeping is done after we disabled
+ msacc. We don't always do this as it is quite expensive. */
+ if (ERTS_MSACC_IS_ENABLED_CACHED_X())
+ ERTS_MSACC_UPDATE_CACHE_X();
+ ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_EMULATOR);
if (is_value(result)) {
r(0) = result;
CHECK_TERM(r(0));
@@ -2891,7 +2799,6 @@ do { \
SET_CP(c_p, I+2);
SET_I(c_p->i);
SWAPIN;
- r(0) = reg[0];
Dispatch();
}
@@ -2907,111 +2814,81 @@ do { \
* Arithmetic operations.
*/
- OpCase(i_times_jId):
+ OpCase(i_times_jIssd):
{
- arith_func = ARITH_FUNC(mixed_times);
- goto do_big_arith2;
+ Eterm Op1, Op2;
+ GetArg2(2, Op1, Op2);
+ DO_OUTLINED_ARITH_2(mixed_times, Op1, Op2);
}
- OpCase(i_m_div_jId):
+ OpCase(i_m_div_jIssd):
{
- arith_func = ARITH_FUNC(mixed_div);
- goto do_big_arith2;
+ Eterm Op1, Op2;
+ GetArg2(2, Op1, Op2);
+ DO_OUTLINED_ARITH_2(mixed_div, Op1, Op2);
}
- OpCase(i_int_div_jId):
+ OpCase(i_int_div_jIssd):
{
- Eterm result;
+ Eterm Op1, Op2;
- if (tmp_arg2 == SMALL_ZERO) {
+ GetArg2(2, Op1, Op2);
+ if (Op2 == SMALL_ZERO) {
goto badarith;
- } else if (is_both_small(tmp_arg1, tmp_arg2)) {
- Sint ires = signed_val(tmp_arg1) / signed_val(tmp_arg2);
+ } else if (is_both_small(Op1, Op2)) {
+ Sint ires = signed_val(Op1) / signed_val(Op2);
if (MY_IS_SSMALL(ires)) {
- result = make_small(ires);
- STORE_ARITH_RESULT(result);
+ Eterm result = make_small(ires);
+ StoreBifResult(4, result);
}
}
- arith_func = ARITH_FUNC(int_div);
- goto do_big_arith2;
+ DO_OUTLINED_ARITH_2(int_div, Op1, Op2);
}
- OpCase(i_rem_jIxxd):
{
- Eterm result;
+ Eterm RemOp1, RemOp2;
- if (xb(Arg(3)) == SMALL_ZERO) {
- goto badarith;
- } else if (is_both_small(xb(Arg(2)), xb(Arg(3)))) {
- result = make_small(signed_val(xb(Arg(2))) % signed_val(xb(Arg(3))));
+ OpCase(i_rem_jIxxd):
+ RemOp1 = xb(Arg(2));
+ RemOp2 = xb(Arg(3));
+ goto do_rem;
+
+ OpCase(i_rem_jIssd):
+ GetArg2(2, RemOp1, RemOp2);
+ goto do_rem;
+
+ do_rem:
+ if (RemOp2 == SMALL_ZERO) {
+ goto badarith;
+ } else if (is_both_small(RemOp1, RemOp2)) {
+ Eterm result = make_small(signed_val(RemOp1) % signed_val(RemOp2));
StoreBifResult(4, result);
+ } else {
+ DO_OUTLINED_ARITH_2(int_rem, RemOp1, RemOp2);
}
- DO_BIG_ARITH(ARITH_FUNC(int_rem),xb(Arg(2)),xb(Arg(3)));
}
- OpCase(i_rem_jId):
{
- Eterm result;
-
- if (tmp_arg2 == SMALL_ZERO) {
- goto badarith;
- } else if (is_both_small(tmp_arg1, tmp_arg2)) {
- result = make_small(signed_val(tmp_arg1) % signed_val(tmp_arg2));
- STORE_ARITH_RESULT(result);
- } else {
- arith_func = ARITH_FUNC(int_rem);
- goto do_big_arith2;
- }
- }
+ Eterm BandOp1, BandOp2;
OpCase(i_band_jIxcd):
- {
- Eterm result;
+ BandOp1 = xb(Arg(2));
+ BandOp2 = Arg(3);
+ goto do_band;
- if (is_both_small(xb(Arg(2)), Arg(3))) {
+ OpCase(i_band_jIssd):
+ GetArg2(2, BandOp1, BandOp2);
+ goto do_band;
+
+ do_band:
+ if (is_both_small(BandOp1, BandOp2)) {
/*
* No need to untag -- TAG & TAG == TAG.
*/
- result = xb(Arg(2)) & Arg(3);
+ Eterm result = BandOp1 & BandOp2;
StoreBifResult(4, result);
}
- DO_BIG_ARITH(ARITH_FUNC(band),xb(Arg(2)),Arg(3));
- }
-
- OpCase(i_band_jId):
- {
- Eterm result;
-
- if (is_both_small(tmp_arg1, tmp_arg2)) {
- /*
- * No need to untag -- TAG & TAG == TAG.
- */
- result = tmp_arg1 & tmp_arg2;
- STORE_ARITH_RESULT(result);
- }
- arith_func = ARITH_FUNC(band);
- goto do_big_arith2;
- }
-
-#undef DO_BIG_ARITH
-
- do_big_arith2:
- {
- Eterm result;
- Uint live = Arg(1);
-
- SWAPOUT;
- reg[0] = r(0);
- reg[live] = tmp_arg1;
- reg[live+1] = tmp_arg2;
- result = arith_func(c_p, reg, live);
- r(0) = reg[0];
- SWAPIN;
- ERTS_HOLE_CHECK(c_p);
- if (is_value(result)) {
- STORE_ARITH_RESULT(result);
- }
- goto lb_Cl_error;
+ DO_OUTLINED_ARITH_2(band, BandOp1, BandOp2);
}
/*
@@ -3032,97 +2909,105 @@ do { \
goto find_func_info;
}
- OpCase(i_bor_jId):
+ OpCase(i_bor_jIssd):
{
- Eterm result;
+ Eterm Op1, Op2;
- if (is_both_small(tmp_arg1, tmp_arg2)) {
+ GetArg2(2, Op1, Op2);
+ if (is_both_small(Op1, Op2)) {
/*
* No need to untag -- TAG | TAG == TAG.
*/
- result = tmp_arg1 | tmp_arg2;
- STORE_ARITH_RESULT(result);
+ Eterm result = Op1 | Op2;
+ StoreBifResult(4, result);
}
- arith_func = ARITH_FUNC(bor);
- goto do_big_arith2;
+ DO_OUTLINED_ARITH_2(bor, Op1, Op2);
}
- OpCase(i_bxor_jId):
+ OpCase(i_bxor_jIssd):
{
- Eterm result;
+ Eterm Op1, Op2;
- if (is_both_small(tmp_arg1, tmp_arg2)) {
+ GetArg2(2, Op1, Op2);
+ if (is_both_small(Op1, Op2)) {
/*
* We could extract the tag from one argument, but a tag extraction
* could mean a shift. Therefore, play it safe here.
*/
- result = make_small(signed_val(tmp_arg1) ^ signed_val(tmp_arg2));
- STORE_ARITH_RESULT(result);
+ Eterm result = make_small(signed_val(Op1) ^ signed_val(Op2));
+ StoreBifResult(4, result);
}
- arith_func = ARITH_FUNC(bxor);
- goto do_big_arith2;
+ DO_OUTLINED_ARITH_2(bxor, Op1, Op2);
}
{
+ Eterm Op1, Op2;
Sint i;
Sint ires;
Eterm* bigp;
+ Eterm tmp_big[2];
- OpCase(i_bsr_jId):
- if (is_small(tmp_arg2)) {
- i = -signed_val(tmp_arg2);
- if (is_small(tmp_arg1)) {
+ OpCase(i_bsr_jIssd):
+ GetArg2(2, Op1, Op2);
+ if (is_small(Op2)) {
+ i = -signed_val(Op2);
+ if (is_small(Op1)) {
goto small_shift;
- } else if (is_big(tmp_arg1)) {
+ } else if (is_big(Op1)) {
if (i == 0) {
- StoreBifResult(2, tmp_arg1);
+ StoreBifResult(4, Op1);
}
goto big_shift;
}
- } else if (is_big(tmp_arg2)) {
+ } else if (is_big(Op2)) {
/*
* N bsr NegativeBigNum == N bsl MAX_SMALL
* N bsr PositiveBigNum == N bsl MIN_SMALL
*/
- tmp_arg2 = make_small(bignum_header_is_neg(*big_val(tmp_arg2)) ?
+ Op2 = make_small(bignum_header_is_neg(*big_val(Op2)) ?
MAX_SMALL : MIN_SMALL);
goto do_bsl;
}
goto badarith;
- OpCase(i_bsl_jId):
+ OpCase(i_bsl_jIssd):
+ GetArg2(2, Op1, Op2);
+
do_bsl:
- if (is_small(tmp_arg2)) {
- i = signed_val(tmp_arg2);
+ if (is_small(Op2)) {
+ i = signed_val(Op2);
- if (is_small(tmp_arg1)) {
+ if (is_small(Op1)) {
small_shift:
- ires = signed_val(tmp_arg1);
+ ires = signed_val(Op1);
if (i == 0 || ires == 0) {
- StoreBifResult(2, tmp_arg1);
+ StoreBifResult(4, Op1);
} else if (i < 0) { /* Right shift */
i = -i;
if (i >= SMALL_BITS-1) {
- tmp_arg1 = (ires < 0) ? SMALL_MINUS_ONE : SMALL_ZERO;
+ Op1 = (ires < 0) ? SMALL_MINUS_ONE : SMALL_ZERO;
} else {
- tmp_arg1 = make_small(ires >> i);
+ Op1 = make_small(ires >> i);
}
- StoreBifResult(2, tmp_arg1);
+ StoreBifResult(4, Op1);
} else if (i < SMALL_BITS-1) { /* Left shift */
if ((ires > 0 && ((~(Uint)0 << ((SMALL_BITS-1)-i)) & ires) == 0) ||
((~(Uint)0 << ((SMALL_BITS-1)-i)) & ~ires) == 0) {
- tmp_arg1 = make_small(ires << i);
- StoreBifResult(2, tmp_arg1);
+ Op1 = make_small(ires << i);
+ StoreBifResult(4, Op1);
}
}
- tmp_arg1 = small_to_big(ires, tmp_big);
+ Op1 = small_to_big(ires, tmp_big);
+#ifdef TAG_LITERAL_PTR
+ Op1 |= TAG_LITERAL_PTR;
+#endif
big_shift:
if (i > 0) { /* Left shift. */
- ires = big_size(tmp_arg1) + (i / D_EXP);
+ ires = big_size(Op1) + (i / D_EXP);
} else { /* Right shift. */
- ires = big_size(tmp_arg1);
+ ires = big_size(Op1);
if (ires <= (-i / D_EXP))
ires = 3; /* ??? */
else
@@ -3140,14 +3025,14 @@ do { \
c_p->freason = SYSTEM_LIMIT;
goto lb_Cl_error;
}
- TestHeapPreserve(ires+1, Arg(1), tmp_arg1);
+ TestHeapPreserve(ires+1, Arg(1), Op1);
bigp = HTOP;
- tmp_arg1 = big_lshift(tmp_arg1, i, bigp);
- if (is_big(tmp_arg1)) {
+ Op1 = big_lshift(Op1, i, bigp);
+ if (is_big(Op1)) {
HTOP += bignum_header_arity(*HTOP) + 1;
}
HEAP_SPACE_VERIFIED(0);
- if (is_nil(tmp_arg1)) {
+ if (is_nil(Op1)) {
/*
* This result must have been only slight larger
* than allowed since it wasn't caught by the
@@ -3157,25 +3042,25 @@ do { \
goto lb_Cl_error;
}
ERTS_HOLE_CHECK(c_p);
- StoreBifResult(2, tmp_arg1);
+ StoreBifResult(4, Op1);
}
- } else if (is_big(tmp_arg1)) {
+ } else if (is_big(Op1)) {
if (i == 0) {
- StoreBifResult(2, tmp_arg1);
+ StoreBifResult(4, Op1);
}
goto big_shift;
}
- } else if (is_big(tmp_arg2)) {
- if (bignum_header_is_neg(*big_val(tmp_arg2))) {
+ } else if (is_big(Op2)) {
+ if (bignum_header_is_neg(*big_val(Op2))) {
/*
* N bsl NegativeBigNum is either 0 or -1, depending on
* the sign of N. Since we don't believe this case
* is common, do the calculation with the minimum
* amount of code.
*/
- tmp_arg2 = make_small(MIN_SMALL);
+ Op2 = make_small(MIN_SMALL);
goto do_bsl;
- } else if (is_small(tmp_arg1) || is_big(tmp_arg1)) {
+ } else if (is_small(Op1) || is_big(Op1)) {
/*
* N bsl PositiveBigNum is too large to represent.
*/
@@ -3199,12 +3084,10 @@ do { \
bnot_val = make_small(~signed_val(bnot_val));
} else {
Uint live = Arg(2);
- SWAPOUT;
- reg[0] = r(0);
+ HEAVY_SWAPOUT;
reg[live] = bnot_val;
bnot_val = erts_gc_bnot(c_p, reg, live);
- r(0) = reg[0];
- SWAPIN;
+ HEAVY_SWAPIN;
ERTS_HOLE_CHECK(c_p);
if (is_nil(bnot_val)) {
goto lb_Cl_error;
@@ -3219,11 +3102,10 @@ do { \
OpCase(i_apply): {
BeamInstr *next;
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = apply(c_p, r(0), x(1), x(2), reg);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
- r(0) = reg[0];
SET_CP(c_p, I+1);
SET_I(next);
Dispatch();
@@ -3234,12 +3116,11 @@ do { \
OpCase(i_apply_last_P): {
BeamInstr *next;
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = apply(c_p, r(0), x(1), x(2), reg);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
- r(0) = reg[0];
- SET_CP(c_p, (BeamInstr *) EXPAND_POINTER(E[0]));
+ SET_CP(c_p, (BeamInstr *) E[0]);
E = ADD_BYTE_OFFSET(E, Arg(0));
SET_I(next);
Dispatch();
@@ -3250,11 +3131,10 @@ do { \
OpCase(i_apply_only): {
BeamInstr *next;
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = apply(c_p, r(0), x(1), x(2), reg);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
- r(0) = reg[0];
SET_I(next);
Dispatch();
}
@@ -3265,12 +3145,10 @@ do { \
OpCase(apply_I): {
BeamInstr *next;
- reg[0] = r(0);
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = fixed_apply(c_p, reg, Arg(0));
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
- r(0) = reg[0];
SET_CP(c_p, I+2);
SET_I(next);
Dispatch();
@@ -3282,13 +3160,11 @@ do { \
OpCase(apply_last_IP): {
BeamInstr *next;
- reg[0] = r(0);
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = fixed_apply(c_p, reg, Arg(0));
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
- r(0) = reg[0];
- SET_CP(c_p, (BeamInstr *) EXPAND_POINTER(E[0]));
+ SET_CP(c_p, (BeamInstr *) E[0]);
E = ADD_BYTE_OFFSET(E, Arg(1));
SET_I(next);
Dispatch();
@@ -3300,11 +3176,10 @@ do { \
OpCase(i_apply_fun): {
BeamInstr *next;
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = apply_fun(c_p, r(0), x(1), reg);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
- r(0) = reg[0];
SET_CP(c_p, I+1);
SET_I(next);
Dispatchfun();
@@ -3315,12 +3190,11 @@ do { \
OpCase(i_apply_fun_last_P): {
BeamInstr *next;
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = apply_fun(c_p, r(0), x(1), reg);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
- r(0) = reg[0];
- SET_CP(c_p, (BeamInstr *) EXPAND_POINTER(E[0]));
+ SET_CP(c_p, (BeamInstr *) E[0]);
E = ADD_BYTE_OFFSET(E, Arg(0));
SET_I(next);
Dispatchfun();
@@ -3331,11 +3205,10 @@ do { \
OpCase(i_apply_fun_only): {
BeamInstr *next;
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = apply_fun(c_p, r(0), x(1), reg);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
- r(0) = reg[0];
SET_I(next);
Dispatchfun();
}
@@ -3345,13 +3218,10 @@ do { \
OpCase(i_call_fun_I): {
BeamInstr *next;
- SWAPOUT;
- reg[0] = r(0);
-
+ HEAVY_SWAPOUT;
next = call_fun(c_p, Arg(0), reg, THE_NON_VALUE);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
- r(0) = reg[0];
SET_CP(c_p, I+2);
SET_I(next);
Dispatchfun();
@@ -3362,13 +3232,11 @@ do { \
OpCase(i_call_fun_last_IP): {
BeamInstr *next;
- SWAPOUT;
- reg[0] = r(0);
+ HEAVY_SWAPOUT;
next = call_fun(c_p, Arg(0), reg, THE_NON_VALUE);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
- r(0) = reg[0];
- SET_CP(c_p, (BeamInstr *) EXPAND_POINTER(E[0]));
+ SET_CP(c_p, (BeamInstr *) E[0]);
E = ADD_BYTE_OFFSET(E, Arg(1));
SET_I(next);
Dispatchfun();
@@ -3452,10 +3320,9 @@ do { \
*/
argp = c_p->arg_reg;
- for (i = c_p->arity - 1; i > 0; i--) {
+ for (i = c_p->arity - 1; i >= 0; i--) {
argp[i] = reg[i];
}
- c_p->arg_reg[0] = r(0);
SWAPOUT;
c_p->i = I;
goto do_schedule1;
@@ -3468,19 +3335,14 @@ do { \
Eterm* p;
PreFetch(3, next);
- GetArg2(0, element, tuple);
+ GetArg1(0, element);
+ tuple = REG_TARGET(Arg(1));
ASSERT(is_tuple(tuple));
p = (Eterm *) ((unsigned char *) tuple_val(tuple) + Arg(2));
*p = element;
NextPF(3, next);
}
- OpCase(i_is_ne_exact_f):
- if (EQ(tmp_arg1, tmp_arg2)) {
- ClauseFail();
- }
- Next(1);
-
OpCase(normal_exit): {
SWAPOUT;
c_p->freason = EXC_NORMAL;
@@ -3547,25 +3409,14 @@ do { \
{
Eterm badmatch_val;
- OpCase(badmatch_y):
- badmatch_val = yb(Arg(0));
- goto do_badmatch;
-
OpCase(badmatch_x):
badmatch_val = xb(Arg(0));
- goto do_badmatch;
-
- OpCase(badmatch_r):
- badmatch_val = r(0);
-
- do_badmatch:
c_p->fvalue = badmatch_val;
c_p->freason = BADMATCH;
}
/* Fall through here */
find_func_info: {
- reg[0] = r(0);
SWAPOUT;
I = handle_error(c_p, I, reg, NULL);
goto post_error_handling;
@@ -3582,11 +3433,9 @@ do { \
* code[3]: &&call_error_handler
* code[4]: Not used
*/
- SWAPOUT;
- reg[0] = r(0);
+ HEAVY_SWAPOUT;
I = call_error_handler(c_p, I-3, reg, am_undefined_function);
- r(0) = reg[0];
- SWAPIN;
+ HEAVY_SWAPIN;
if (I) {
Goto(*I);
}
@@ -3594,18 +3443,13 @@ do { \
/* Fall through */
OpCase(error_action_code): {
handle_error:
- reg[0] = r(0);
SWAPOUT;
I = handle_error(c_p, NULL, reg, NULL);
post_error_handling:
if (I == 0) {
goto do_schedule;
} else {
- r(0) = reg[0];
ASSERT(!is_value(r(0)));
- if (c_p->mbuf) {
- erts_garbage_collect(c_p, 0, reg+1, 3);
- }
SWAPIN;
Goto(*I);
}
@@ -3629,6 +3473,9 @@ do { \
* I[3]: Function pointer to dirty NIF
*/
BifFunction vbf;
+ ErlHeapFragment *live_hf_end;
+
+ ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_NIF);
DTRACE_NIF_ENTRY(c_p, (Eterm)I[-3], (Eterm)I[-2], (Uint)I[-1]);
c_p->current = I-3; /* current and vbf set to please handle_error */
@@ -3644,7 +3491,7 @@ do { \
NifF* fp = vbf = (NifF*) I[1];
struct enif_environment_t env;
erts_pre_nif(&env, c_p, (struct erl_module_nif*)I[2]);
- reg[0] = r(0);
+ live_hf_end = c_p->mbuf;
nif_bif_result = (*fp)(&env, bif_nif_arity, reg);
if (env.exception_thrown)
nif_bif_result = THE_NON_VALUE;
@@ -3654,6 +3501,8 @@ do { \
PROCESS_MAIN_CHK_LOCKS(c_p);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_EMULATOR);
+
DTRACE_NIF_RETURN(c_p, (Eterm)I[-3], (Eterm)I[-2], (Uint)I[-1]);
goto apply_bif_or_nif_epilogue;
@@ -3668,6 +3517,13 @@ do { \
* code[3]: &&apply_bif
* code[4]: Function pointer to BIF function
*/
+ if (ERTS_MSACC_IS_ENABLED_CACHED_X()) {
+ if ((Eterm)I[-3] == am_ets) {
+ ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_ETS);
+ } else {
+ ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_BIF);
+ }
+ }
c_p->current = I-3; /* In case we apply process_info/1,2 or load_nif/1 */
c_p->i = I; /* In case we apply check_process_code/2. */
@@ -3683,25 +3539,32 @@ do { \
bif_nif_arity = I[-1];
ASSERT(bif_nif_arity <= 4);
ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p);
- reg[0] = r(0);
+ ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
{
Eterm (*bf)(Process*, Eterm*, BeamInstr*) = vbf;
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
+ live_hf_end = c_p->mbuf;
nif_bif_result = (*bf)(c_p, reg, I);
ASSERT(!ERTS_PROC_IS_EXITING(c_p) ||
is_non_value(nif_bif_result));
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
}
-
+ /* We have to update the cache if we are enabled in order
+ to make sure no book keeping is done after we disabled
+ msacc. We don't always do this as it is quite expensive. */
+ if (ERTS_MSACC_IS_ENABLED_CACHED_X())
+ ERTS_MSACC_UPDATE_CACHE_X();
+ ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_EMULATOR);
DTRACE_BIF_RETURN(c_p, (Eterm)I[-3], (Eterm)I[-2], (Uint)I[-1]);
apply_bif_or_nif_epilogue:
ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
ERTS_HOLE_CHECK(c_p);
- if (c_p->mbuf) {
- nif_bif_result = erts_gc_after_bif_call(c_p, nif_bif_result,
- reg, bif_nif_arity);
+ if (ERTS_IS_GC_DESIRED(c_p)) {
+ nif_bif_result = erts_gc_after_bif_call_lhf(c_p, live_hf_end,
+ nif_bif_result,
+ reg, bif_nif_arity);
}
SWAPIN; /* There might have been a garbage collection. */
FCALLS = c_p->fcalls;
@@ -3713,7 +3576,6 @@ do { \
Goto(*I);
} else if (c_p->freason == TRAP) {
SET_I(c_p->i);
- r(0) = reg[0];
if (c_p->flags & F_HIBERNATE_SCHED) {
c_p->flags &= ~F_HIBERNATE_SCHED;
goto do_schedule;
@@ -3735,21 +3597,21 @@ do { \
StoreBifResult(1, result);
}
+ OpCase(i_get_hash_cId):
+ {
+ Eterm arg;
+ Eterm result;
+
+ GetArg1(0, arg);
+ result = erts_pd_hash_get_with_hx(c_p, Arg(1), arg);
+ StoreBifResult(2, result);
+ }
+
{
Eterm case_end_val;
OpCase(case_end_x):
case_end_val = xb(Arg(0));
- goto do_case_end;
-
- OpCase(case_end_y):
- case_end_val = yb(Arg(0));
- goto do_case_end;
-
- OpCase(case_end_r):
- case_end_val = r(0);
-
- do_case_end:
c_p->fvalue = case_end_val;
c_p->freason = EXC_CASE_CLAUSE;
goto find_func_info;
@@ -3797,19 +3659,13 @@ do { \
goto do_bs_init_bits_known;
}
- OpCase(i_bs_init_bits_fail_heap_IjId): {
- /* tmp_arg1 was fetched by an i_fetch instruction */
- num_bits_term = tmp_arg1;
- alloc = Arg(0);
- I++;
+ OpCase(i_bs_init_bits_fail_heap_sIjId): {
+ GetArg1(0, num_bits_term);
+ alloc = Arg(1);
+ I += 2;
goto do_bs_init_bits;
}
- OpCase(i_bs_init_bits_fail_rjId): {
- num_bits_term = r(0);
- alloc = 0;
- goto do_bs_init_bits;
- }
OpCase(i_bs_init_bits_fail_yjId): {
num_bits_term = yb(Arg(0));
I++;
@@ -3929,52 +3785,48 @@ do { \
}
{
- OpCase(i_bs_init_fail_heap_IjId): {
- /* tmp_arg1 was fetched by an i_fetch instruction */
- tmp_arg2 = Arg(0);
- I++;
- goto do_bs_init;
- }
+ Eterm BsOp1, BsOp2;
- OpCase(i_bs_init_fail_rjId): {
- tmp_arg1 = r(0);
- tmp_arg2 = 0;
+ OpCase(i_bs_init_fail_heap_sIjId): {
+ GetArg1(0, BsOp1);
+ BsOp2 = Arg(1);
+ I += 2;
goto do_bs_init;
}
OpCase(i_bs_init_fail_yjId): {
- tmp_arg1 = yb(Arg(0));
- tmp_arg2 = 0;
+ BsOp1 = yb(Arg(0));
+ BsOp2 = 0;
I++;
goto do_bs_init;
}
OpCase(i_bs_init_fail_xjId): {
- tmp_arg1 = xb(Arg(0));
- tmp_arg2 = 0;
+ BsOp1 = xb(Arg(0));
+ BsOp2 = 0;
I++;
}
/* FALL THROUGH */
do_bs_init:
- if (is_small(tmp_arg1)) {
- Sint size = signed_val(tmp_arg1);
+ if (is_small(BsOp1)) {
+ Sint size = signed_val(BsOp1);
if (size < 0) {
goto badarg;
}
- tmp_arg1 = (Eterm) size;
+ BsOp1 = (Eterm) size;
} else {
Uint bytes;
- if (!term_to_Uint(tmp_arg1, &bytes)) {
+ if (!term_to_Uint(BsOp1, &bytes)) {
c_p->freason = bytes;
goto lb_Cl_error;
}
if ((bytes >> (8*sizeof(Uint)-3)) != 0) {
goto system_limit;
}
- tmp_arg1 = (Eterm) bytes;
+ BsOp1 = (Eterm) bytes;
}
- if (tmp_arg1 <= ERL_ONHEAP_BIN_LIMIT) {
+ if (BsOp1 <= ERL_ONHEAP_BIN_LIMIT) {
goto do_heap_bin_alloc;
} else {
goto do_proc_bin_alloc;
@@ -3982,15 +3834,15 @@ do { \
OpCase(i_bs_init_heap_IIId): {
- tmp_arg1 = Arg(0);
- tmp_arg2 = Arg(1);
+ BsOp1 = Arg(0);
+ BsOp2 = Arg(1);
I++;
goto do_proc_bin_alloc;
}
OpCase(i_bs_init_IId): {
- tmp_arg1 = Arg(0);
- tmp_arg2 = 0;
+ BsOp1 = Arg(0);
+ BsOp2 = 0;
}
/* FALL THROUGH */
do_proc_bin_alloc: {
@@ -3999,13 +3851,13 @@ do { \
erts_bin_offset = 0;
erts_writable_bin = 0;
- TestBinVHeap(tmp_arg1 / sizeof(Eterm),
- tmp_arg2 + PROC_BIN_SIZE + ERL_SUB_BIN_SIZE, Arg(1));
+ TestBinVHeap(BsOp1 / sizeof(Eterm),
+ BsOp2 + PROC_BIN_SIZE + ERL_SUB_BIN_SIZE, Arg(1));
/*
* Allocate the binary struct itself.
*/
- bptr = erts_bin_nrml_alloc(tmp_arg1);
+ bptr = erts_bin_nrml_alloc(BsOp1);
erts_refc_init(&bptr->refc, 1);
erts_current_bin = (byte *) bptr->orig_bytes;
@@ -4015,28 +3867,28 @@ do { \
pb = (ProcBin *) HTOP;
HTOP += PROC_BIN_SIZE;
pb->thing_word = HEADER_PROC_BIN;
- pb->size = tmp_arg1;
+ pb->size = BsOp1;
pb->next = MSO(c_p).first;
MSO(c_p).first = (struct erl_off_heap_header*) pb;
pb->val = bptr;
pb->bytes = (byte*) bptr->orig_bytes;
pb->flags = 0;
- OH_OVERHEAD(&(MSO(c_p)), tmp_arg1 / sizeof(Eterm));
+ OH_OVERHEAD(&(MSO(c_p)), BsOp1 / sizeof(Eterm));
StoreBifResult(2, make_binary(pb));
}
OpCase(i_bs_init_heap_bin_heap_IIId): {
- tmp_arg1 = Arg(0);
- tmp_arg2 = Arg(1);
+ BsOp1 = Arg(0);
+ BsOp2 = Arg(1);
I++;
goto do_heap_bin_alloc;
}
OpCase(i_bs_init_heap_bin_IId): {
- tmp_arg1 = Arg(0);
- tmp_arg2 = 0;
+ BsOp1 = Arg(0);
+ BsOp2 = 0;
}
/* Fall through */
do_heap_bin_alloc:
@@ -4044,33 +3896,36 @@ do { \
ErlHeapBin* hb;
Uint bin_need;
- bin_need = heap_bin_size(tmp_arg1);
+ bin_need = heap_bin_size(BsOp1);
erts_bin_offset = 0;
erts_writable_bin = 0;
- TestHeap(bin_need+tmp_arg2+ERL_SUB_BIN_SIZE, Arg(1));
+ TestHeap(bin_need+BsOp2+ERL_SUB_BIN_SIZE, Arg(1));
hb = (ErlHeapBin *) HTOP;
HTOP += bin_need;
- hb->thing_word = header_heap_bin(tmp_arg1);
- hb->size = tmp_arg1;
+ hb->thing_word = header_heap_bin(BsOp1);
+ hb->size = BsOp1;
erts_current_bin = (byte *) hb->data;
- tmp_arg1 = make_binary(hb);
- StoreBifResult(2, tmp_arg1);
+ BsOp1 = make_binary(hb);
+ StoreBifResult(2, BsOp1);
}
}
- OpCase(i_bs_add_jId): {
- Uint Unit = Arg(1);
- if (is_both_small(tmp_arg1, tmp_arg2)) {
- Sint Arg1 = signed_val(tmp_arg1);
- Sint Arg2 = signed_val(tmp_arg2);
+ OpCase(bs_add_jssId): {
+ Eterm Op1, Op2;
+ Uint Unit = Arg(3);
+
+ GetArg2(1, Op1, Op2);
+ if (is_both_small(Op1, Op2)) {
+ Sint Arg1 = signed_val(Op1);
+ Sint Arg2 = signed_val(Op2);
if (Arg1 >= 0 && Arg2 >= 0) {
- BsSafeMul(Arg2, Unit, goto system_limit, tmp_arg1);
- tmp_arg1 += Arg1;
+ BsSafeMul(Arg2, Unit, goto system_limit, Op1);
+ Op1 += Arg1;
store_bs_add_result:
- if (tmp_arg1 <= MAX_SMALL) {
- tmp_arg1 = make_small(tmp_arg1);
+ if (Op1 <= MAX_SMALL) {
+ Op1 = make_small(Op1);
} else {
/*
* May generate a heap fragment, but in this
@@ -4082,10 +3937,10 @@ do { \
* references (such as the heap).
*/
SWAPOUT;
- tmp_arg1 = erts_make_integer(tmp_arg1, c_p);
+ Op1 = erts_make_integer(Op1, c_p);
HTOP = HEAP_TOP(c_p);
}
- StoreBifResult(2, tmp_arg1);
+ StoreBifResult(4, Op1);
}
goto badarg;
} else {
@@ -4108,16 +3963,16 @@ do { \
* an Uint, the reason is SYSTEM_LIMIT.
*/
- if (!term_to_Uint(tmp_arg1, &a)) {
+ if (!term_to_Uint(Op1, &a)) {
if (a == BADARG) {
goto badarg;
}
- if (!term_to_Uint(tmp_arg2, &b)) {
+ if (!term_to_Uint(Op2, &b)) {
c_p->freason = b;
goto lb_Cl_error;
}
goto system_limit;
- } else if (!term_to_Uint(tmp_arg2, &b)) {
+ } else if (!term_to_Uint(Op2, &b)) {
c_p->freason = b;
goto lb_Cl_error;
}
@@ -4127,8 +3982,8 @@ do { \
*/
BsSafeMul(b, Unit, goto system_limit, c);
- tmp_arg1 = a + c;
- if (tmp_arg1 < a) {
+ Op1 = a + c;
+ if (Op1 < a) {
/*
* If the result is less than one of the
* arguments, there must have been an overflow.
@@ -4150,52 +4005,47 @@ do { \
}
/*
- * tmp_arg1 = Number of bytes to build
- * tmp_arg2 = Source binary
- * Operands: Fail ExtraHeap Live Unit Dst
+ * x(SCRATCH_X_REG);
+ * Operands: Fail ExtraHeap Live Unit Size Dst
*/
- OpCase(i_bs_append_jIIId): {
+ OpCase(i_bs_append_jIIIsd): {
Uint live = Arg(2);
Uint res;
+ Eterm Size;
- SWAPOUT;
- reg[0] = r(0);
- reg[live] = tmp_arg2;
- res = erts_bs_append(c_p, reg, live, tmp_arg1, Arg(1), Arg(3));
- r(0) = reg[0];
- SWAPIN;
+ GetArg1(4, Size);
+ HEAVY_SWAPOUT;
+ reg[live] = x(SCRATCH_X_REG);
+ res = erts_bs_append(c_p, reg, live, Size, Arg(1), Arg(3));
+ HEAVY_SWAPIN;
if (is_non_value(res)) {
/* c_p->freason is already set (may be either BADARG or SYSTEM_LIMIT). */
goto lb_Cl_error;
}
- StoreBifResult(4, res);
+ StoreBifResult(5, res);
}
/*
- * tmp_arg1 = Number of bytes to build
- * tmp_arg2 = Source binary
- * Operands: Fail Unit Dst
+ * Operands: Fail Size Src Unit Dst
*/
- OpCase(i_bs_private_append_jId): {
+ OpCase(i_bs_private_append_jIssd): {
Eterm res;
+ Eterm Size, Src;
- res = erts_bs_private_append(c_p, tmp_arg2, tmp_arg1, Arg(1));
+ GetArg2(2, Size, Src);
+ res = erts_bs_private_append(c_p, Src, Size, Arg(1));
if (is_non_value(res)) {
/* c_p->freason is already set (may be either BADARG or SYSTEM_LIMIT). */
goto lb_Cl_error;
}
- StoreBifResult(2, res);
+ StoreBifResult(4, res);
}
- /*
- * tmp_arg1 = Initial size of writable binary
- * Operands: Live Dst
- */
OpCase(bs_init_writable): {
- SWAPOUT;
+ HEAVY_SWAPOUT;
r(0) = erts_bs_init_writable(c_p, r(0));
- SWAPIN;
+ HEAVY_SWAPIN;
Next(0);
}
@@ -4286,26 +4136,29 @@ do { \
/*
* Only used for validating a value matched out.
- *
- * tmp_arg1 = Integer to validate
- * tmp_arg2 = Match context
*/
- OpCase(i_bs_validate_unicode_retract_j): {
- /*
- * There is no need to untag the integer, but it IS necessary
- * to make sure it is small (a bignum pointer could fall in
- * the valid range).
- */
- if (is_not_small(tmp_arg1) || tmp_arg1 > make_small(0x10FFFFUL) ||
- (make_small(0xD800UL) <= tmp_arg1 &&
- tmp_arg1 <= make_small(0xDFFFUL))) {
- ErlBinMatchBuffer *mb = ms_matchbuffer(tmp_arg2);
+ OpCase(i_bs_validate_unicode_retract_jss): {
+ Eterm i; /* Integer to validate */
- mb->offset -= 32;
- goto badarg;
- }
- Next(1);
- }
+ /*
+ * There is no need to untag the integer, but it IS necessary
+ * to make sure it is small (a bignum pointer could fall in
+ * the valid range).
+ */
+
+ GetArg1(1, i);
+ if (is_not_small(i) || i > make_small(0x10FFFFUL) ||
+ (make_small(0xD800UL) <= i && i <= make_small(0xDFFFUL))) {
+ Eterm ms; /* Match context */
+ ErlBinMatchBuffer* mb;
+
+ GetArg1(2, ms);
+ mb = ms_matchbuffer(ms);
+ mb->offset -= 32;
+ goto badarg;
+ }
+ Next(3);
+ }
/*
* Matching of binaries.
@@ -4317,9 +4170,6 @@ do { \
Uint slots;
Eterm context;
- OpCase(i_bs_start_match2_rfIId): {
- context = r(0);
-
do_start_match:
slots = Arg(2);
if (!is_boxed(context)) {
@@ -4366,7 +4216,7 @@ do { \
ClauseFail();
}
NextPF(4, next);
- }
+
OpCase(i_bs_start_match2_xfIId): {
context = xb(Arg(0));
I++;
@@ -4379,18 +4229,6 @@ do { \
}
}
- OpCase(bs_test_zero_tail2_fr): {
- BeamInstr *next;
- ErlBinMatchBuffer *_mb;
-
- PreFetch(1, next);
- _mb = (ErlBinMatchBuffer*) ms_matchbuffer(r(0));
- if (_mb->size != _mb->offset) {
- ClauseFail();
- }
- NextPF(1, next);
- }
-
OpCase(bs_test_zero_tail2_fx): {
BeamInstr *next;
ErlBinMatchBuffer *_mb;
@@ -4403,16 +4241,6 @@ do { \
NextPF(2, next);
}
- OpCase(bs_test_tail_imm2_frI): {
- BeamInstr *next;
- ErlBinMatchBuffer *_mb;
- PreFetch(2, next);
- _mb = ms_matchbuffer(r(0));
- if (_mb->size - _mb->offset != Arg(1)) {
- ClauseFail();
- }
- NextPF(2, next);
- }
OpCase(bs_test_tail_imm2_fxI): {
BeamInstr *next;
ErlBinMatchBuffer *_mb;
@@ -4424,16 +4252,6 @@ do { \
NextPF(3, next);
}
- OpCase(bs_test_unit_frI): {
- BeamInstr *next;
- ErlBinMatchBuffer *_mb;
- PreFetch(2, next);
- _mb = ms_matchbuffer(r(0));
- if ((_mb->size - _mb->offset) % Arg(1)) {
- ClauseFail();
- }
- NextPF(2, next);
- }
OpCase(bs_test_unit_fxI): {
BeamInstr *next;
ErlBinMatchBuffer *_mb;
@@ -4445,16 +4263,6 @@ do { \
NextPF(3, next);
}
- OpCase(bs_test_unit8_fr): {
- BeamInstr *next;
- ErlBinMatchBuffer *_mb;
- PreFetch(1, next);
- _mb = ms_matchbuffer(r(0));
- if ((_mb->size - _mb->offset) & 7) {
- ClauseFail();
- }
- NextPF(1, next);
- }
OpCase(bs_test_unit8_fx): {
BeamInstr *next;
ErlBinMatchBuffer *_mb;
@@ -4469,19 +4277,11 @@ do { \
{
Eterm bs_get_integer8_context;
- OpCase(i_bs_get_integer_8_rfd): {
- bs_get_integer8_context = r(0);
- goto do_bs_get_integer_8;
- }
-
OpCase(i_bs_get_integer_8_xfd): {
- bs_get_integer8_context = xb(Arg(0));
- I++;
- }
-
- do_bs_get_integer_8: {
ErlBinMatchBuffer *_mb;
Eterm _result;
+ bs_get_integer8_context = xb(Arg(0));
+ I++;
_mb = ms_matchbuffer(bs_get_integer8_context);
if (_mb->size - _mb->offset < 8) {
ClauseFail();
@@ -4499,15 +4299,10 @@ do { \
{
Eterm bs_get_integer_16_context;
- OpCase(i_bs_get_integer_16_rfd):
- bs_get_integer_16_context = r(0);
- goto do_bs_get_integer_16;
-
OpCase(i_bs_get_integer_16_xfd):
bs_get_integer_16_context = xb(Arg(0));
I++;
- do_bs_get_integer_16:
{
ErlBinMatchBuffer *_mb;
Eterm _result;
@@ -4528,17 +4323,10 @@ do { \
{
Eterm bs_get_integer_32_context;
- OpCase(i_bs_get_integer_32_rfId):
- bs_get_integer_32_context = r(0);
- goto do_bs_get_integer_32;
-
-
OpCase(i_bs_get_integer_32_xfId):
bs_get_integer_32_context = xb(Arg(0));
I++;
-
- do_bs_get_integer_32:
{
ErlBinMatchBuffer *_mb;
Uint32 _integer;
@@ -4551,11 +4339,11 @@ do { \
_integer = get_int32(_mb->base + _mb->offset/8);
}
_mb->offset += 32;
-#if !defined(ARCH_64) || HALFWORD_HEAP
+#if !defined(ARCH_64)
if (IS_USMALL(0, _integer)) {
#endif
_result = make_small(_integer);
-#if !defined(ARCH_64) || HALFWORD_HEAP
+#if !defined(ARCH_64)
} else {
TestHeap(BIG_UINT_HEAP_SIZE, Arg(1));
_result = uint_to_big((Uint) _integer, HTOP);
@@ -4567,103 +4355,82 @@ do { \
}
}
- /* Operands: Size Live Fail Flags Dst */
- OpCase(i_bs_get_integer_imm_rIIfId): {
- tmp_arg1 = r(0);
- /* Operands: Size Live Fail Flags Dst */
- goto do_bs_get_integer_imm_test_heap;
- }
+ {
+ Eterm Ms, Sz;
- /* Operands: x(Reg) Size Live Fail Flags Dst */
+ /* Operands: x(Reg) Size Live Fail Flags Dst */
OpCase(i_bs_get_integer_imm_xIIfId): {
- tmp_arg1 = xb(Arg(0));
- I++;
- /* Operands: Size Live Fail Flags Dst */
- goto do_bs_get_integer_imm_test_heap;
- }
-
- /*
- * tmp_arg1 = match context
- * Operands: Size Live Fail Flags Dst
- */
- do_bs_get_integer_imm_test_heap: {
- Uint wordsneeded;
- tmp_arg2 = Arg(0);
- wordsneeded = 1+WSIZE(NBYTES(tmp_arg2));
- TestHeapPreserve(wordsneeded, Arg(1), tmp_arg1);
- I += 2;
- /* Operands: Fail Flags Dst */
- goto do_bs_get_integer_imm;
- }
-
- /* Operands: Size Fail Flags Dst */
- OpCase(i_bs_get_integer_small_imm_rIfId): {
- tmp_arg1 = r(0);
- tmp_arg2 = Arg(0);
- I++;
- /* Operands: Fail Flags Dst */
- goto do_bs_get_integer_imm;
- }
+ Uint wordsneeded;
+ Ms = xb(Arg(0));
+ Sz = Arg(1);
+ wordsneeded = 1+WSIZE(NBYTES(Sz));
+ TestHeapPreserve(wordsneeded, Arg(2), Ms);
+ I += 3;
+ /* Operands: Fail Flags Dst */
+ goto do_bs_get_integer_imm;
+ }
- /* Operands: x(Reg) Size Fail Flags Dst */
+ /* Operands: x(Reg) Size Fail Flags Dst */
OpCase(i_bs_get_integer_small_imm_xIfId): {
- tmp_arg1 = xb(Arg(0));
- tmp_arg2 = Arg(1);
- I += 2;
- /* Operands: Fail Flags Dst */
- goto do_bs_get_integer_imm;
- }
+ Ms = xb(Arg(0));
+ Sz = Arg(1);
+ I += 2;
+ /* Operands: Fail Flags Dst */
+ goto do_bs_get_integer_imm;
+ }
- /*
- * tmp_arg1 = match context
- * tmp_arg2 = size of field
- * Operands: Fail Flags Dst
- */
+ /*
+ * Ms = match context
+ * Sz = size of field
+ * Operands: Fail Flags Dst
+ */
do_bs_get_integer_imm: {
- ErlBinMatchBuffer* mb;
- Eterm result;
+ ErlBinMatchBuffer* mb;
+ Eterm result;
- mb = ms_matchbuffer(tmp_arg1);
- LIGHT_SWAPOUT;
- result = erts_bs_get_integer_2(c_p, tmp_arg2, Arg(1), mb);
- LIGHT_SWAPIN;
- HEAP_SPACE_VERIFIED(0);
- if (is_non_value(result)) {
- ClauseFail();
+ mb = ms_matchbuffer(Ms);
+ LIGHT_SWAPOUT;
+ result = erts_bs_get_integer_2(c_p, Sz, Arg(1), mb);
+ LIGHT_SWAPIN;
+ HEAP_SPACE_VERIFIED(0);
+ if (is_non_value(result)) {
+ ClauseFail();
+ }
+ StoreBifResult(2, result);
}
- StoreBifResult(2, result);
}
/*
- * tmp_arg1 = Match context
- * tmp_arg2 = Size field
- * Operands: Fail Live FlagsAndUnit Dst
+ * Operands: Fail Live FlagsAndUnit Ms Sz Dst
*/
- OpCase(i_bs_get_integer_fIId): {
+ OpCase(i_bs_get_integer_fIIssd): {
Uint flags;
Uint size;
+ Eterm Ms;
+ Eterm Sz;
ErlBinMatchBuffer* mb;
Eterm result;
flags = Arg(2);
- BsGetFieldSize(tmp_arg2, (flags >> 3), ClauseFail(), size);
+ GetArg2(3, Ms, Sz);
+ BsGetFieldSize(Sz, (flags >> 3), ClauseFail(), size);
if (size >= SMALL_BITS) {
Uint wordsneeded;
- /* check bits size before potential gc.
+ /* Check bits size before potential gc.
* We do not want a gc and then realize we don't need
- * the allocated space (i.e. if the op fails)
+ * the allocated space (i.e. if the op fails).
*
- * remember to reacquire the matchbuffer after gc.
+ * Remember to re-acquire the matchbuffer after gc.
*/
- mb = ms_matchbuffer(tmp_arg1);
+ mb = ms_matchbuffer(Ms);
if (mb->size - mb->offset < size) {
ClauseFail();
}
wordsneeded = 1+WSIZE(NBYTES((Uint) size));
- TestHeapPreserve(wordsneeded, Arg(1), tmp_arg1);
+ TestHeapPreserve(wordsneeded, Arg(1), Ms);
}
- mb = ms_matchbuffer(tmp_arg1);
+ mb = ms_matchbuffer(Ms);
LIGHT_SWAPOUT;
result = erts_bs_get_integer_2(c_p, size, flags, mb);
LIGHT_SWAPIN;
@@ -4671,18 +4438,13 @@ do { \
if (is_non_value(result)) {
ClauseFail();
}
- StoreBifResult(3, result);
+ StoreBifResult(5, result);
}
{
Eterm get_utf8_context;
/* Operands: MatchContext Fail Dst */
- OpCase(i_bs_get_utf8_rfd): {
- get_utf8_context = r(0);
- goto do_bs_get_utf8;
- }
-
OpCase(i_bs_get_utf8_xfd): {
get_utf8_context = xb(Arg(0));
I++;
@@ -4693,7 +4455,7 @@ do { \
* Operands: Fail Dst
*/
- do_bs_get_utf8: {
+ {
Eterm result = erts_bs_get_utf8(ms_matchbuffer(get_utf8_context));
if (is_non_value(result)) {
ClauseFail();
@@ -4706,12 +4468,7 @@ do { \
Eterm get_utf16_context;
/* Operands: MatchContext Fail Flags Dst */
- OpCase(i_bs_get_utf16_rfId): {
- get_utf16_context = r(0);
- goto do_bs_get_utf16;
- }
-
- OpCase(i_bs_get_utf16_xfId): {
+ OpCase(i_bs_get_utf16_xfId): {
get_utf16_context = xb(Arg(0));
I++;
}
@@ -4720,7 +4477,7 @@ do { \
* get_utf16_context = match_context
* Operands: Fail Flags Dst
*/
- do_bs_get_utf16: {
+ {
Eterm result = erts_bs_get_utf16(ms_matchbuffer(get_utf16_context),
Arg(1));
if (is_non_value(result)) {
@@ -4739,26 +4496,10 @@ do { \
Uint orig;
Uint hole_size;
- OpCase(bs_context_to_binary_r): {
- context_to_binary_context = x0;
- I -= 2;
- goto do_context_to_binary;
- }
-
- /* Unfortunately, inlining can generate this instruction. */
- OpCase(bs_context_to_binary_y): {
- context_to_binary_context = yb(Arg(0));
- goto do_context_to_binary0;
- }
-
- OpCase(bs_context_to_binary_x): {
+ OpCase(bs_context_to_binary_x):
context_to_binary_context = xb(Arg(0));
-
- do_context_to_binary0:
I--;
- }
- do_context_to_binary:
if (is_boxed(context_to_binary_context) &&
header_is_bin_matchstate(*boxed_val(context_to_binary_context))) {
ErlBinMatchState* ms;
@@ -4770,17 +4511,11 @@ do { \
}
Next(2);
- OpCase(i_bs_get_binary_all_reuse_rfI): {
- context_to_binary_context = x0;
- goto do_bs_get_binary_all_reuse;
- }
-
OpCase(i_bs_get_binary_all_reuse_xfI): {
context_to_binary_context = xb(Arg(0));
I++;
}
- do_bs_get_binary_all_reuse:
mb = ms_matchbuffer(context_to_binary_context);
size = mb->size - mb->offset;
if (size % Arg(1) != 0) {
@@ -4808,16 +4543,11 @@ do { \
{
Eterm match_string_context;
- OpCase(i_bs_match_string_rfII): {
- match_string_context = r(0);
- goto do_bs_match_string;
- }
OpCase(i_bs_match_string_xfII): {
match_string_context = xb(Arg(0));
I++;
}
- do_bs_match_string:
{
BeamInstr *next;
byte* bytes;
@@ -4845,14 +4575,6 @@ do { \
}
}
- OpCase(i_bs_save2_rI): {
- BeamInstr *next;
- ErlBinMatchState *_ms;
- PreFetch(1, next);
- _ms = (ErlBinMatchState*) boxed_val((Eterm) r(0));
- _ms->save_offset[Arg(0)] = _ms->mb.offset;
- NextPF(1, next);
- }
OpCase(i_bs_save2_xI): {
BeamInstr *next;
ErlBinMatchState *_ms;
@@ -4862,14 +4584,6 @@ do { \
NextPF(2, next);
}
- OpCase(i_bs_restore2_rI): {
- BeamInstr *next;
- ErlBinMatchState *_ms;
- PreFetch(1, next);
- _ms = (ErlBinMatchState*) boxed_val((Eterm) r(0));
- _ms->mb.offset = _ms->save_offset[Arg(0)];
- NextPF(1, next);
- }
OpCase(i_bs_restore2_xI): {
BeamInstr *next;
ErlBinMatchState *_ms;
@@ -4917,9 +4631,7 @@ do { \
BeamInstr real_I;
ASSERT(I[-5] == (BeamInstr) BeamOp(op_i_func_info_IaaI));
SWAPOUT;
- reg[0] = r(0);
real_I = erts_generic_breakpoint(c_p, I, reg);
- r(0) = reg[0];
SWAPIN;
ASSERT(VALID_INSTR(real_I));
Goto(real_I);
@@ -4979,7 +4691,7 @@ do { \
BeamInstr *next;
PreFetch(2, next);
- GetR(0, targ1);
+ targ1 = REG_TARGET(Arg(0));
/* Arg(0) == HEADER_FLONUM */
GET_DOUBLE(targ1, *(FloatDef*)ADD_BYTE_OFFSET(freg, fr));
NextPF(2, next);
@@ -4999,7 +4711,7 @@ do { \
Eterm fr = Arg(1);
BeamInstr *next;
- GetR(0, targ1);
+ targ1 = REG_TARGET(Arg(0));
PreFetch(2, next);
if (is_small(targ1)) {
fb(fr) = (double) signed_val(targ1);
@@ -5095,7 +4807,12 @@ do { \
#ifdef HIPE
{
- unsigned cmd;
+#define HIPE_MODE_SWITCH(Cmd) \
+ SWAPOUT; \
+ c_p->fcalls = FCALLS; \
+ c_p->def_arg_reg[4] = -neg_o_reds; \
+ c_p = hipe_mode_switch(c_p, Cmd, reg); \
+ goto L_post_hipe_mode_switch
OpCase(hipe_trap_call): {
/*
@@ -5109,52 +4826,45 @@ do { \
*/
ASSERT(I[-5] == (Uint) OpCode(i_func_info_IaaI));
c_p->hipe.u.ncallee = (void(*)(void)) I[-4];
- cmd = HIPE_MODE_SWITCH_CMD_CALL | (I[-1] << 8);
++hipe_trap_count;
- goto L_hipe_mode_switch;
+ HIPE_MODE_SWITCH(HIPE_MODE_SWITCH_CMD_CALL | (I[-1] << 8));
}
OpCase(hipe_trap_call_closure): {
ASSERT(I[-5] == (Uint) OpCode(i_func_info_IaaI));
c_p->hipe.u.ncallee = (void(*)(void)) I[-4];
- cmd = HIPE_MODE_SWITCH_CMD_CALL_CLOSURE | (I[-1] << 8);
++hipe_trap_count;
- goto L_hipe_mode_switch;
+ HIPE_MODE_SWITCH(HIPE_MODE_SWITCH_CMD_CALL_CLOSURE | (I[-1] << 8));
}
OpCase(hipe_trap_return): {
- cmd = HIPE_MODE_SWITCH_CMD_RETURN;
- goto L_hipe_mode_switch;
+ HIPE_MODE_SWITCH(HIPE_MODE_SWITCH_CMD_RETURN);
}
OpCase(hipe_trap_throw): {
- cmd = HIPE_MODE_SWITCH_CMD_THROW;
- goto L_hipe_mode_switch;
+ HIPE_MODE_SWITCH(HIPE_MODE_SWITCH_CMD_THROW);
}
OpCase(hipe_trap_resume): {
- cmd = HIPE_MODE_SWITCH_CMD_RESUME;
- goto L_hipe_mode_switch;
+ HIPE_MODE_SWITCH(HIPE_MODE_SWITCH_CMD_RESUME);
}
- L_hipe_mode_switch:
- /* XXX: this abuse of def_arg_reg[] is horrid! */
- SWAPOUT;
- c_p->fcalls = FCALLS;
- c_p->def_arg_reg[4] = -neg_o_reds;
- reg[0] = r(0);
- c_p = hipe_mode_switch(c_p, cmd, reg);
+#undef HIPE_MODE_SWITCH
+
+ L_post_hipe_mode_switch:
reg = ERTS_PROC_GET_SCHDATA(c_p)->x_reg_array;
freg = ERTS_PROC_GET_SCHDATA(c_p)->f_reg_array;
ERL_BITS_RELOAD_STATEP(c_p);
+ /* XXX: this abuse of def_arg_reg[] is horrid! */
neg_o_reds = -c_p->def_arg_reg[4];
FCALLS = c_p->fcalls;
SWAPIN;
- switch( c_p->def_arg_reg[3] ) { /* Halfword wont work with hipe yet! */
+ switch( c_p->def_arg_reg[3] ) {
case HIPE_MODE_SWITCH_RES_RETURN:
ASSERT(is_value(reg[0]));
- MoveReturn(reg[0], r(0));
+ SET_I(c_p->cp);
+ c_p->cp = 0;
+ Goto(*I);
case HIPE_MODE_SWITCH_RES_CALL_EXPORTED:
c_p->i = c_p->hipe.u.callee_exp->addressv[erts_active_code_ix()];
/*fall through*/
case HIPE_MODE_SWITCH_RES_CALL_BEAM:
SET_I(c_p->i);
- r(0) = reg[0];
Dispatch();
case HIPE_MODE_SWITCH_RES_CALL_CLOSURE:
/* This can be used to call any function value, but currently it's
@@ -5163,9 +4873,8 @@ do { \
BeamInstr *next;
next = call_fun(c_p, c_p->arity - 1, reg, THE_NON_VALUE);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
- r(0) = reg[0];
SET_I(next);
Dispatchfun();
}
@@ -5213,22 +4922,54 @@ do { \
}
OpCase(i_hibernate): {
- SWAPOUT;
+ HEAVY_SWAPOUT;
if (erts_hibernate(c_p, r(0), x(1), x(2), reg)) {
+ FCALLS = c_p->fcalls;
c_p->flags &= ~F_HIBERNATE_SCHED;
goto do_schedule;
} else {
+ HEAVY_SWAPIN;
I = handle_error(c_p, I, reg, hibernate_3);
goto post_error_handling;
}
}
+ /* This is optimised as an instruction because
+ it has to be very very fast */
+ OpCase(i_perf_counter): {
+ BeamInstr* next;
+ ErtsSysPerfCounter ts;
+ PreFetch(0, next);
+
+ ts = erts_sys_perf_counter();
+
+ if (IS_SSMALL(ts)) {
+ r(0) = make_small((Sint)ts);
+ } else {
+ TestHeap(ERTS_SINT64_HEAP_SIZE(ts),0);
+ r(0) = make_big(HTOP);
+#if defined(ARCH_32) || HALFWORD_HEAP
+ if (ts >= (((Uint64) 1) << 32)) {
+ *HTOP = make_pos_bignum_header(2);
+ BIG_DIGIT(HTOP, 0) = (Uint) (ts & ((Uint) 0xffffffff));
+ BIG_DIGIT(HTOP, 1) = (Uint) ((ts >> 32) & ((Uint) 0xffffffff));
+ HTOP += 3;
+ }
+ else
+#endif
+ {
+ *HTOP = make_pos_bignum_header(1);
+ BIG_DIGIT(HTOP, 0) = (Uint) ts;
+ HTOP += 2;
+ }
+ }
+ NextPF(0, next);
+ }
+
OpCase(i_debug_breakpoint): {
- SWAPOUT;
- reg[0] = r(0);
+ HEAVY_SWAPOUT;
I = call_error_handler(c_p, I-3, reg, am_breakpoint);
- r(0) = reg[0];
- SWAPIN;
+ HEAVY_SWAPIN;
if (I) {
Goto(*I);
}
@@ -6439,7 +6180,7 @@ call_fun(Process* p, /* Current process. */
*/
module = fe->module;
if ((modp = erts_get_module(module, code_ix)) != NULL
- && modp->curr.code != NULL) {
+ && modp->curr.code_hdr != NULL) {
/*
* There is a module loaded, but obviously the fun is not
* defined in it. We must not call the error_handler
@@ -6644,23 +6385,20 @@ static Eterm get_map_element_hash(Eterm map, Eterm key, Uint32 hx)
return vs ? *vs : THE_NON_VALUE;
}
-#define GET_TERM(term, dest) \
-do { \
- Eterm src = (Eterm)(term); \
- switch (src & _TAG_IMMED1_MASK) { \
- case (R_REG_DEF << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_HEADER: \
- dest = x(0); \
- break; \
- case (X_REG_DEF << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_HEADER: \
- dest = x(src >> _TAG_IMMED1_SIZE); \
- break; \
- case (Y_REG_DEF << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_HEADER: \
- dest = y(src >> _TAG_IMMED1_SIZE); \
- break; \
- default: \
- dest = src; \
- break; \
- } \
+#define GET_TERM(term, dest) \
+do { \
+ Eterm src = (Eterm)(term); \
+ switch (loader_tag(src)) { \
+ case LOADER_X_REG: \
+ dest = x(loader_x_reg_index(src)); \
+ break; \
+ case LOADER_Y_REG: \
+ dest = y(loader_y_reg_index(src)); \
+ break; \
+ default: \
+ dest = src; \
+ break; \
+ } \
} while(0)
@@ -6699,13 +6437,6 @@ new_map(Process* p, Eterm* reg, BeamInstr* I)
erts_factory_proc_init(&factory, p);
res = erts_hashmap_from_array(&factory, thp, n/2, 0);
erts_factory_close(&factory);
- if (p->mbuf) {
- Uint live = Arg(2);
- reg[live] = res;
- erts_garbage_collect(p, 0, reg, live+1);
- res = reg[live];
- E = p->stop;
- }
return res;
}
@@ -6771,13 +6502,6 @@ update_map_assoc(Process* p, Eterm* reg, Eterm map, BeamInstr* I)
hx = hashmap_make_hash(new_key);
res = erts_hashmap_insert(p, hx, new_key, val, res, 0);
- if (p->mbuf) {
- Uint live = Arg(3);
- reg[live] = res;
- erts_garbage_collect(p, 0, reg, live+1);
- res = reg[live];
- E = p->stop;
- }
new_p += 2;
}
@@ -6937,12 +6661,6 @@ update_map_assoc(Process* p, Eterm* reg, Eterm map, BeamInstr* I)
/* The expensive case, need to build a hashmap */
if (n > MAP_SMALL_MAP_LIMIT) {
res = erts_hashmap_from_ks_and_vs(p,flatmap_get_keys(mp),flatmap_get_values(mp),n);
- if (p->mbuf) {
- Uint live = Arg(3);
- reg[live] = res;
- erts_garbage_collect(p, 0, reg, live+1);
- res = reg[live];
- }
}
return res;
}
@@ -6998,14 +6716,6 @@ update_map_exact(Process* p, Eterm* reg, Eterm map, BeamInstr* I)
return res;
}
- if (p->mbuf) {
- Uint live = Arg(3);
- reg[live] = res;
- erts_garbage_collect(p, 0, reg, live+1);
- res = reg[live];
- E = p->stop;
- }
-
new_p += 2;
}
return res;
@@ -7114,6 +6824,15 @@ erts_is_builtin(Eterm Mod, Eterm Name, int arity)
Export e;
Export* ep;
+ if (Mod == am_erlang && Name == am_apply && arity == 3) {
+ /*
+ * Special case. apply/3 is built-in (implemented in C),
+ * but implemented in a different way than all other
+ * BIFs.
+ */
+ return 1;
+ }
+
e.code[0] = Mod;
e.code[1] = Name;
e.code[2] = arity;
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index a6dce2d1d2..f115df935f 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -80,7 +80,7 @@ ErlDrvBinary* erts_gzinflate_buffer(char*, int);
typedef struct {
Uint value; /* Value of label (NULL if not known yet). */
- Uint patches; /* Index (into code buffer) to first location
+ Sint patches; /* Index (into code buffer) to first location
* which must be patched with the value of this label.
*/
#ifdef ERTS_SMP
@@ -284,9 +284,10 @@ typedef struct LoaderState {
int specific_op; /* Specific opcode (-1 if not found). */
int num_functions; /* Number of functions in module. */
int num_labels; /* Number of labels. */
- int code_buffer_size; /* Size of code buffer in words. */
- BeamInstr* code; /* Loaded code. */
- int ci; /* Current index into loaded code. */
+ BeamCodeHeader* hdr; /* Loaded code header */
+ BeamInstr* codev; /* Loaded code buffer */
+ int codev_size; /* Size of code buffer in words. */
+ int ci; /* Current index into loaded code buffer. */
Label* labels;
StringPatch* string_patches; /* Linked list of position into string table to patch. */
BeamInstr catches; /* Linked list of catch_yf instructions. */
@@ -480,7 +481,7 @@ static void free_literal_fragment(ErlHeapFragment*);
static void loader_state_dtor(Binary* magic);
static Eterm insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
Eterm group_leader, Eterm module,
- BeamInstr* code, Uint size);
+ BeamCodeHeader* code, Uint size);
static int init_iff_file(LoaderState* stp, byte* code, Uint size);
static int scan_iff_file(LoaderState* stp, Uint* chunk_types,
Uint num_types, Uint num_mandatory);
@@ -526,15 +527,15 @@ static void new_string_patch(LoaderState* stp, int pos);
static Uint new_literal(LoaderState* stp, Eterm** hpp, Uint heap_size);
static int genopargcompare(GenOpArg* a, GenOpArg* b);
static Eterm get_module_info(Process* p, ErtsCodeIndex code_ix,
- BeamInstr* code, Eterm module, Eterm what);
+ BeamCodeHeader*, Eterm module, Eterm what);
static Eterm exported_from_module(Process* p, ErtsCodeIndex code_ix,
Eterm mod);
-static Eterm functions_in_module(Process* p, BeamInstr* code);
-static Eterm attributes_for_module(Process* p, BeamInstr* code);
-static Eterm compilation_info_for_module(Process* p, BeamInstr* code);
-static Eterm md5_of_module(Process* p, BeamInstr* code);
-static Eterm has_native(BeamInstr* code);
-static Eterm native_addresses(Process* p, BeamInstr* code);
+static Eterm functions_in_module(Process* p, BeamCodeHeader*);
+static Eterm attributes_for_module(Process* p, BeamCodeHeader*);
+static Eterm compilation_info_for_module(Process* p, BeamCodeHeader*);
+static Eterm md5_of_module(Process* p, BeamCodeHeader*);
+static Eterm has_native(BeamCodeHeader*);
+static Eterm native_addresses(Process* p, BeamCodeHeader*);
int patch_funentries(Eterm Patchlist);
int patch(Eterm Addresses, Uint fe);
static int safe_mul(UWord a, UWord b, UWord* resp);
@@ -601,6 +602,7 @@ extern void check_allocated_block(Uint type, void *blk);
#define CHKBLK(TYPE,BLK) /* nothing */
#endif
+
Eterm
erts_prepare_loading(Binary* magic, Process *c_p, Eterm group_leader,
Eterm* modp, byte* code, Uint unloaded_size)
@@ -641,20 +643,27 @@ erts_prepare_loading(Binary* magic, Process *c_p, Eterm group_leader,
/*
* Initialize code area.
*/
- stp->code_buffer_size = 2048 + stp->num_functions;
- stp->code = (BeamInstr *) erts_alloc(ERTS_ALC_T_CODE,
- sizeof(BeamInstr) * stp->code_buffer_size);
+ stp->codev_size = 2048 + stp->num_functions;
+ stp->hdr = (BeamCodeHeader*) erts_alloc(ERTS_ALC_T_CODE,
+ (offsetof(BeamCodeHeader,functions)
+ + sizeof(BeamInstr) * stp->codev_size));
- stp->code[MI_NUM_FUNCTIONS] = stp->num_functions;
- stp->ci = MI_FUNCTIONS + stp->num_functions + 1;
+ stp->hdr->num_functions = stp->num_functions;
- stp->code[MI_ATTR_PTR] = 0;
- stp->code[MI_ATTR_SIZE] = 0;
- stp->code[MI_ATTR_SIZE_ON_HEAP] = 0;
- stp->code[MI_COMPILE_PTR] = 0;
- stp->code[MI_COMPILE_SIZE] = 0;
- stp->code[MI_COMPILE_SIZE_ON_HEAP] = 0;
- stp->code[MI_MD5_PTR] = 0;
+ /* Let the codev array start at functions[0] in order to index
+ * both function pointers and the loaded code itself that follows.
+ */
+ stp->codev = (BeamInstr*) &stp->hdr->functions;
+ stp->ci = stp->num_functions + 1;
+
+ stp->hdr->attr_ptr = NULL;
+ stp->hdr->attr_size = 0;
+ stp->hdr->attr_size_on_heap = 0;
+ stp->hdr->compile_ptr = NULL;
+ stp->hdr->compile_size = 0;
+ stp->hdr->compile_size_on_heap = 0;
+ stp->hdr->literals_start = NULL;
+ stp->hdr->md5_ptr = NULL;
/*
* Read the atom table.
@@ -776,7 +785,7 @@ erts_finish_loading(Binary* magic, Process* c_p,
CHKBLK(ERTS_ALC_T_CODE,stp->code);
retval = insert_new_code(c_p, c_p_locks, stp->group_leader, stp->module,
- stp->code, stp->loaded_size);
+ stp->hdr, stp->loaded_size);
if (retval != NIL) {
goto load_error;
}
@@ -799,7 +808,8 @@ erts_finish_loading(Binary* magic, Process* c_p,
debug_dump_code(stp->code,stp->ci);
#endif
#endif
- stp->code = NULL; /* Prevent code from being freed. */
+ stp->hdr = NULL; /* Prevent code from being freed. */
+ stp->codev = NULL;
*modp = stp->module;
/*
@@ -831,7 +841,8 @@ erts_alloc_loader_state(void)
stp->specific_op = -1;
stp->genop = NULL;
stp->atom = NULL;
- stp->code = NULL;
+ stp->hdr = NULL;
+ stp->codev = NULL;
stp->labels = NULL;
stp->import = NULL;
stp->export = NULL;
@@ -870,13 +881,30 @@ erts_module_for_prepared_code(Binary* magic)
return NIL;
}
stp = ERTS_MAGIC_BIN_DATA(magic);
- if (stp->code != 0) {
+ if (stp->hdr != 0) {
return stp->module;
} else {
return NIL;
}
}
+/*
+ * Return a non-zero value if the module has an on_load function,
+ * or 0 if it does not.
+ */
+
+Eterm
+erts_has_code_on_load(Binary* magic)
+{
+ LoaderState* stp;
+
+ if (ERTS_MAGIC_BIN_DESTRUCTOR(magic) != loader_state_dtor) {
+ return NIL;
+ }
+ stp = ERTS_MAGIC_BIN_DATA(magic);
+ return stp->on_load ? am_true : am_false;
+}
+
static void
free_loader_state(Binary* magic)
{
@@ -891,7 +919,7 @@ static ErlHeapFragment* new_literal_fragment(Uint size)
ErlHeapFragment* bp;
bp = (ErlHeapFragment*) ERTS_HEAP_ALLOC(ERTS_ALC_T_PREPARED_CODE,
ERTS_HEAP_FRAG_SIZE(size));
- ERTS_INIT_HEAP_FRAG(bp, size);
+ ERTS_INIT_HEAP_FRAG(bp, size, size);
return bp;
}
@@ -920,9 +948,13 @@ loader_state_dtor(Binary* magic)
driver_free_binary(stp->bin);
stp->bin = 0;
}
- if (stp->code != 0) {
- erts_free(ERTS_ALC_T_CODE, stp->code);
- stp->code = 0;
+ if (stp->hdr != 0) {
+ if (stp->hdr->literals_start) {
+ erts_free(ERTS_ALC_T_LITERAL, stp->hdr->literals_start);
+ }
+ erts_free(ERTS_ALC_T_CODE, stp->hdr);
+ stp->hdr = 0;
+ stp->codev = 0;
}
if (stp->labels != 0) {
erts_free(ERTS_ALC_T_PREPARED_CODE, (void *) stp->labels);
@@ -995,7 +1027,7 @@ loader_state_dtor(Binary* magic)
static Eterm
insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
- Eterm group_leader, Eterm module, BeamInstr* code,
+ Eterm group_leader, Eterm module, BeamCodeHeader* code_hdr,
Uint size)
{
Module* modp;
@@ -1016,7 +1048,7 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
erts_total_code_size += size;
modp = erts_put_module(module);
- modp->curr.code = code;
+ modp->curr.code_hdr = code_hdr;
modp->curr.code_length = size;
modp->curr.catches = BEAM_CATCHES_NIL; /* Will be filled in later. */
@@ -1024,7 +1056,7 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
* Update ranges (used for finding a function from a PC value).
*/
- erts_update_ranges(code, size);
+ erts_update_ranges((BeamInstr*)modp->curr.code_hdr, size);
return NIL;
}
@@ -1373,7 +1405,7 @@ read_export_table(LoaderState* stp)
if (value == 0) {
LoadError2(stp, "export table entry %d: label %d not resolved", i, n);
}
- stp->export[i].address = address = stp->code + value;
+ stp->export[i].address = address = stp->codev + value;
/*
* Find out if there is a BIF with the same name.
@@ -1392,7 +1424,7 @@ read_export_table(LoaderState* stp)
* any other functions that walk through all local functions.
*/
- if (stp->labels[n].patches) {
+ if (stp->labels[n].patches >= 0) {
LoadError3(stp, "there are local calls to the stub for "
"the BIF %T:%T/%d",
stp->module, func, arity);
@@ -1513,8 +1545,8 @@ read_literal_table(LoaderState* stp)
}
if (heap_size > 0) {
- erts_factory_message_init(&factory, NULL, NULL,
- new_literal_fragment(heap_size));
+ erts_factory_heap_frag_init(&factory,
+ new_literal_fragment(heap_size));
factory.alloc_type = ERTS_ALC_T_PREPARED_CODE;
val = erts_decode_ext(&factory, &p);
@@ -1735,7 +1767,7 @@ read_code_header(LoaderState* stp)
stp->num_labels * sizeof(Label));
for (i = 0; i < stp->num_labels; i++) {
stp->labels[i].value = 0;
- stp->labels[i].patches = 0;
+ stp->labels[i].patches = -1;
#ifdef ERTS_SMP
stp->labels[i].looprec_targeted = 0;
#endif
@@ -1754,13 +1786,14 @@ read_code_header(LoaderState* stp)
} else {}
#define CodeNeed(w) do { \
- ASSERT(ci <= code_buffer_size); \
- if (code_buffer_size < ci+(w)) { \
- code_buffer_size = 2*ci+(w); \
- stp->code = code = \
- (BeamInstr *) erts_realloc(ERTS_ALC_T_CODE, \
- (void *) code, \
- code_buffer_size * sizeof(BeamInstr)); \
+ ASSERT(ci <= codev_size); \
+ if (codev_size < ci+(w)) { \
+ codev_size = 2*ci+(w); \
+ stp->hdr = (BeamCodeHeader*) erts_realloc(ERTS_ALC_T_CODE, \
+ (void *) stp->hdr, \
+ (offsetof(BeamCodeHeader,functions) \
+ + codev_size * sizeof(BeamInstr))); \
+ code = stp->codev = (BeamInstr*) &stp->hdr->functions; \
} \
} while (0)
@@ -1776,7 +1809,7 @@ load_code(LoaderState* stp)
int arg; /* Number of current argument. */
int num_specific; /* Number of specific ops for current. */
BeamInstr* code;
- int code_buffer_size;
+ int codev_size;
int specific;
Uint last_label = 0; /* Number of last label. */
Uint function_number = 0;
@@ -1793,15 +1826,15 @@ load_code(LoaderState* stp)
FUNC_INFO_SZ = 5
};
- code = stp->code;
- code_buffer_size = stp->code_buffer_size;
+ code = stp->codev;
+ codev_size = stp->codev_size;
ci = stp->ci;
for (;;) {
int new_op;
GenOp* tmp_op;
- ASSERT(ci <= code_buffer_size);
+ ASSERT(ci <= codev_size);
get_next_instr:
GetByte(stp, new_op);
@@ -1847,9 +1880,7 @@ load_code(LoaderState* stp)
case TAG_o:
break;
case TAG_x:
- if (last_op->a[arg].val == 0) {
- last_op->a[arg].type = TAG_r;
- } else if (last_op->a[arg].val >= MAX_REG) {
+ if (last_op->a[arg].val >= MAX_REG) {
LoadError1(stp, "invalid x register number: %u",
last_op->a[arg].val);
}
@@ -1894,15 +1925,14 @@ load_code(LoaderState* stp)
*/
{
Eterm* hp;
-/* XXX:PaN - Halfword should use ARCH_64 variant instead */
-#if !defined(ARCH_64) || HALFWORD_HEAP
+#if !defined(ARCH_64)
Uint high, low;
# endif
last_op->a[arg].val = new_literal(stp, &hp,
FLOAT_SIZE_OBJECT);
hp[0] = HEADER_FLONUM;
last_op->a[arg].type = TAG_q;
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
GetInt(stp, 8, hp[1]);
# else
GetInt(stp, 4, high);
@@ -2056,7 +2086,42 @@ load_code(LoaderState* stp)
if (((opc[specific].mask[0] & mask[0]) == mask[0]) &&
((opc[specific].mask[1] & mask[1]) == mask[1]) &&
((opc[specific].mask[2] & mask[2]) == mask[2])) {
- break;
+
+ if (!opc[specific].involves_r) {
+ break; /* No complications - match */
+ }
+
+ /*
+ * The specific operation uses the 'r' operand,
+ * which is shorthand for x(0). Now things
+ * get complicated. First we must check whether
+ * all operands that should be of type 'r' use
+ * x(0) (as opposed to some other X register).
+ */
+ for (arg = 0; arg < arity; arg++) {
+ if (opc[specific].involves_r & (1 << arg) &&
+ tmp_op->a[arg].type == TAG_x) {
+ if (tmp_op->a[arg].val != 0) {
+ break; /* Other X register than 0 */
+ }
+ }
+ }
+
+ if (arg == arity) {
+ /*
+ * All 'r' operands use x(0) in the generic
+ * operation. That means a match. Now we
+ * will need to rewrite the generic instruction
+ * to actually use 'r' instead of 'x(0)'.
+ */
+ for (arg = 0; arg < arity; arg++) {
+ if (opc[specific].involves_r & (1 << arg) &&
+ tmp_op->a[arg].type == TAG_x) {
+ tmp_op->a[arg].type = TAG_r;
+ }
+ }
+ break; /* Match */
+ }
}
specific++;
}
@@ -2167,14 +2232,11 @@ load_code(LoaderState* stp)
break;
case 's': /* Any source (tagged constant or register) */
switch (tag) {
- case TAG_r:
- code[ci++] = make_rreg();
- break;
case TAG_x:
- code[ci++] = make_xreg(tmp_op->a[arg].val);
+ code[ci++] = make_loader_x_reg(tmp_op->a[arg].val);
break;
case TAG_y:
- code[ci++] = make_yreg(tmp_op->a[arg].val);
+ code[ci++] = make_loader_y_reg(tmp_op->a[arg].val);
break;
case TAG_i:
code[ci++] = (BeamInstr) make_small((Uint)tmp_op->a[arg].val);
@@ -2185,6 +2247,10 @@ load_code(LoaderState* stp)
case TAG_n:
code[ci++] = NIL;
break;
+ case TAG_q:
+ new_literal_patch(stp, ci);
+ code[ci++] = tmp_op->a[arg].val;
+ break;
default:
LoadError1(stp, "bad tag %d for general source",
tmp_op->a[arg].type);
@@ -2193,14 +2259,11 @@ load_code(LoaderState* stp)
break;
case 'd': /* Destination (x(0), x(N), y(N) */
switch (tag) {
- case TAG_r:
- code[ci++] = make_rreg();
- break;
case TAG_x:
- code[ci++] = make_xreg(tmp_op->a[arg].val);
+ code[ci++] = tmp_op->a[arg].val * sizeof(Eterm);
break;
case TAG_y:
- code[ci++] = make_yreg(tmp_op->a[arg].val);
+ code[ci++] = tmp_op->a[arg].val * sizeof(Eterm) + 1;
break;
default:
LoadError1(stp, "bad tag %d for destination",
@@ -2357,20 +2420,13 @@ load_code(LoaderState* stp)
stp->labels[tmp_op->a[arg].val].patches = ci;
ci++;
break;
- case TAG_r:
- CodeNeed(1);
- code[ci++] = (R_REG_DEF << _TAG_PRIMARY_SIZE) |
- TAG_PRIMARY_HEADER;
- break;
case TAG_x:
CodeNeed(1);
- code[ci++] = (tmp_op->a[arg].val << _TAG_IMMED1_SIZE) |
- (X_REG_DEF << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_HEADER;
+ code[ci++] = make_loader_x_reg(tmp_op->a[arg].val);
break;
case TAG_y:
CodeNeed(1);
- code[ci++] = (tmp_op->a[arg].val << _TAG_IMMED1_SIZE) |
- (Y_REG_DEF << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_HEADER;
+ code[ci++] = make_loader_y_reg(tmp_op->a[arg].val);
break;
case TAG_n:
CodeNeed(1);
@@ -2393,8 +2449,7 @@ load_code(LoaderState* stp)
switch (stp->specific_op) {
case op_i_func_info_IaaI:
{
- Uint offset;
-
+ Sint offset;
if (function_number >= stp->num_functions) {
LoadError1(stp, "too many functions in module (header said %d)",
stp->num_functions);
@@ -2436,15 +2491,15 @@ load_code(LoaderState* stp)
stp->arity = code[ci-1];
ASSERT(stp->labels[last_label].value == ci - FUNC_INFO_SZ);
- offset = MI_FUNCTIONS + function_number;
- code[offset] = stp->labels[last_label].patches;
+ stp->hdr->functions[function_number] = (BeamInstr*) stp->labels[last_label].patches;
+ offset = function_number;
stp->labels[last_label].patches = offset;
function_number++;
if (stp->arity > MAX_ARG) {
LoadError1(stp, "too many arguments: %d", stp->arity);
}
#ifdef DEBUG
- ASSERT(stp->labels[0].patches == 0); /* Should not be referenced. */
+ ASSERT(stp->labels[0].patches < 0); /* Should not be referenced. */
for (i = 1; i < stp->num_labels; i++) {
ASSERT(stp->labels[i].patches < ci);
}
@@ -2458,7 +2513,6 @@ load_code(LoaderState* stp)
stp->on_load = ci;
break;
case op_bs_put_string_II:
- case op_i_bs_match_string_rfII:
case op_i_bs_match_string_xfII:
new_string_patch(stp, ci-1);
break;
@@ -2515,7 +2569,7 @@ load_code(LoaderState* stp)
* End of code found.
*/
case op_int_code_end:
- stp->code_buffer_size = code_buffer_size;
+ stp->codev_size = codev_size;
stp->ci = ci;
stp->function = THE_NON_VALUE;
stp->genop = NULL;
@@ -2680,6 +2734,12 @@ same_label(LoaderState* stp, GenOpArg Target, GenOpArg Label)
Target.val == Label.val;
}
+static int
+is_killed(LoaderState* stp, GenOpArg Reg, GenOpArg Live)
+{
+ return Reg.type == TAG_x && Live.type == TAG_u &&
+ Live.val <= Reg.val;
+}
/*
* Generate an instruction for element/2.
@@ -2696,17 +2756,17 @@ gen_element(LoaderState* stp, GenOpArg Fail, GenOpArg Index,
op->next = NULL;
if (Index.type == TAG_i && Index.val > 0 &&
- (Tuple.type == TAG_r || Tuple.type == TAG_x || Tuple.type == TAG_y)) {
+ (Tuple.type == TAG_x || Tuple.type == TAG_y)) {
op->op = genop_i_fast_element_4;
- op->a[0] = Tuple;
- op->a[1] = Fail;
+ op->a[0] = Fail;
+ op->a[1] = Tuple;
op->a[2].type = TAG_u;
op->a[2].val = Index.val;
op->a[3] = Dst;
} else {
op->op = genop_i_element_4;
- op->a[0] = Tuple;
- op->a[1] = Fail;
+ op->a[0] = Fail;
+ op->a[1] = Tuple;
op->a[2] = Index;
op->a[3] = Dst;
}
@@ -2832,23 +2892,16 @@ gen_get_integer2(LoaderState* stp, GenOpArg Fail, GenOpArg Ms, GenOpArg Live,
goto generic;
}
} else {
- GenOp* op2;
- NEW_GENOP(stp, op2);
-
- op->op = genop_i_fetch_2;
- op->arity = 2;
- op->a[0] = Ms;
- op->a[1] = Size;
- op->next = op2;
-
- op2->op = genop_i_bs_get_integer_4;
- op2->arity = 4;
- op2->a[0] = Fail;
- op2->a[1] = Live;
- op2->a[2].type = TAG_u;
- op2->a[2].val = (Unit.val << 3) | Flags.val;
- op2->a[3] = Dst;
- op2->next = NULL;
+ op->op = genop_i_bs_get_integer_6;
+ op->arity = 6;
+ op->a[0] = Fail;
+ op->a[1] = Live;
+ op->a[2].type = TAG_u;
+ op->a[2].val = (Unit.val << 3) | Flags.val;
+ op->a[3] = Ms;
+ op->a[4] = Size;
+ op->a[5] = Dst;
+ op->next = NULL;
return op;
}
op->next = NULL;
@@ -3272,14 +3325,14 @@ gen_literal_timeout(LoaderState* stp, GenOpArg Fail, GenOpArg Time)
op->a[1].type = TAG_u;
if (Time.type == TAG_i && (timeout = Time.val) >= 0 &&
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
(timeout >> 32) == 0
#else
1
#endif
) {
op->a[1].val = timeout;
-#if !defined(ARCH_64) || HALFWORD_HEAP
+#if !defined(ARCH_64)
} else if (Time.type == TAG_q) {
Eterm big;
@@ -3296,7 +3349,7 @@ gen_literal_timeout(LoaderState* stp, GenOpArg Fail, GenOpArg Time)
}
#endif
} else {
-#if !defined(ARCH_64) || HALFWORD_HEAP
+#if !defined(ARCH_64)
error:
#endif
op->op = genop_i_wait_error_0;
@@ -3319,14 +3372,14 @@ gen_literal_timeout_locked(LoaderState* stp, GenOpArg Fail, GenOpArg Time)
op->a[1].type = TAG_u;
if (Time.type == TAG_i && (timeout = Time.val) >= 0 &&
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
(timeout >> 32) == 0
#else
1
#endif
) {
op->a[1].val = timeout;
-#if !defined(ARCH_64) || HALFWORD_HEAP
+#if !defined(ARCH_64)
} else if (Time.type == TAG_q) {
Eterm big;
@@ -3343,7 +3396,7 @@ gen_literal_timeout_locked(LoaderState* stp, GenOpArg Fail, GenOpArg Time)
}
#endif
} else {
-#if !defined(ARCH_64) || HALFWORD_HEAP
+#if !defined(ARCH_64)
error:
#endif
op->op = genop_i_wait_error_locked_0;
@@ -3899,9 +3952,7 @@ gen_make_fun2(LoaderState* stp, GenOpArg idx)
/*
* Rewrite gc_bifs with one parameter (the common case). Utilized
* in ops.tab to rewrite instructions calling bif's in guards
- * to use a garbage collecting implementation. The instructions
- * are sometimes once again rewritten to handle literals (putting the
- * parameter in the mostly unused r[0] before the instruction is executed).
+ * to use a garbage collecting implementation.
*/
static GenOp*
gen_guard_bif1(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif,
@@ -3956,10 +4007,6 @@ gen_guard_bif1(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif,
/*
* This is used by the ops.tab rule that rewrites gc_bifs with two parameters.
- * The instruction returned is then again rewritten to an i_load instruction
- * followed by i_gc_bif2_jIId, to handle literals properly.
- * As opposed to the i_gc_bif1_jIsId, the instruction i_gc_bif2_jIId is
- * always rewritten, regardless of if there actually are any literals.
*/
static GenOp*
gen_guard_bif2(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif,
@@ -3986,23 +4033,19 @@ gen_guard_bif2(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif,
op->a[2].val = stp->import[Bif.val].arity;
return op;
}
- op->op = genop_ii_gc_bif2_6;
+ op->op = genop_i_gc_bif2_6;
op->arity = 6;
op->a[0] = Fail;
op->a[1].type = TAG_u;
- op->a[2] = S1;
- op->a[3] = S2;
- op->a[4] = Live;
+ op->a[2] = Live;
+ op->a[3] = S1;
+ op->a[4] = S2;
op->a[5] = Dst;
return op;
}
/*
* This is used by the ops.tab rule that rewrites gc_bifs with three parameters.
- * The instruction returned is then again rewritten to a move instruction that
- * uses r[0] for temp storage, followed by an i_load instruction,
- * followed by i_gc_bif3_jIsId, to handle literals properly. Rewriting
- * always occur, as with the gc_bif2 counterpart.
*/
static GenOp*
gen_guard_bif3(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif,
@@ -4033,10 +4076,10 @@ gen_guard_bif3(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif,
op->arity = 7;
op->a[0] = Fail;
op->a[1].type = TAG_u;
- op->a[2] = S1;
- op->a[3] = S2;
- op->a[4] = S3;
- op->a[5] = Live;
+ op->a[2] = Live;
+ op->a[3] = S1;
+ op->a[4] = S2;
+ op->a[5] = S3;
op->a[6] = Dst;
op->next = NULL;
return op;
@@ -4258,6 +4301,53 @@ gen_get_map_element(LoaderState* stp, GenOpArg Fail, GenOpArg Src,
return op;
}
+static int
+hash_internal_genop_arg(LoaderState* stp, GenOpArg Key, Uint32* hx)
+{
+ switch (Key.type) {
+ case TAG_a:
+ *hx = atom_tab(atom_val(Key.val))->slot.bucket.hvalue;
+ return 1;
+ case TAG_i:
+ *hx = Key.val;
+ return 1;
+ case TAG_n:
+ *hx = make_internal_hash(NIL);
+ return 1;
+ case TAG_q:
+ *hx = make_internal_hash(stp->literals[Key.val].term);
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+
+static GenOp*
+gen_get(LoaderState* stp, GenOpArg Src, GenOpArg Dst)
+{
+ GenOp* op;
+ Uint32 hx = 0;
+
+ NEW_GENOP(stp, op);
+ op->next = NULL;
+ if (hash_internal_genop_arg(stp, Src, &hx)) {
+ op->arity = 3;
+ op->op = genop_i_get_hash_3;
+ op->a[0] = Src;
+ op->a[1].type = TAG_u;
+ op->a[1].val = (BeamInstr) hx;
+ op->a[2] = Dst;
+ } else {
+ op->arity = 2;
+ op->op = genop_i_get_2;
+ op->a[0] = Src;
+ op->a[1] = Dst;
+ }
+ return op;
+}
+
+
static GenOp*
gen_get_map_elements(LoaderState* stp, GenOpArg Fail, GenOpArg Src,
GenOpArg Size, GenOpArg* Rest)
@@ -4323,7 +4413,7 @@ gen_has_map_fields(LoaderState* stp, GenOpArg Fail, GenOpArg Src,
for (i = 0; i < n; i++) {
op->a[3+2*i] = Rest[i];
op->a[3+2*i+1].type = TAG_x;
- op->a[3+2*i+1].val = 0; /* x(0); normally not used */
+ op->a[3+2*i+1].val = SCRATCH_X_REG; /* Ignore result */
}
return op;
}
@@ -4336,8 +4426,8 @@ gen_has_map_fields(LoaderState* stp, GenOpArg Fail, GenOpArg Src,
static int
freeze_code(LoaderState* stp)
{
- BeamInstr* code = stp->code;
- Uint *literal_end = NULL;
+ BeamCodeHeader* code_hdr = stp->hdr;
+ BeamInstr* codev = (BeamInstr*) &stp->hdr->functions;
int i;
byte* str_table;
unsigned strtab_size = stp->chunks[STR_CHUNK].size;
@@ -4362,77 +4452,76 @@ freeze_code(LoaderState* stp)
if (stp->line_instr == 0) {
line_size = 0;
} else {
- line_size = (MI_LINE_FUNC_TAB + (stp->num_functions + 1) +
- (stp->current_li+1) + stp->num_fnames) *
- sizeof(Eterm) + (stp->current_li+1) * stp->loc_size;
+ line_size = (offsetof(BeamCodeLineTab,func_tab)
+ + (stp->num_functions + 1) * sizeof(BeamInstr**) /* func_tab */
+ + (stp->current_li + 1) * sizeof(BeamInstr*) /* line items */
+ + stp->num_fnames * sizeof(Eterm) /* fname table */
+ + (stp->current_li + 1) * stp->loc_size); /* loc_tab */
}
- size = (stp->ci * sizeof(BeamInstr)) +
- (stp->total_literal_size * sizeof(Eterm)) +
+ size = offsetof(BeamCodeHeader,functions) + (stp->ci * sizeof(BeamInstr)) +
strtab_size + attr_size + compile_size + MD5_SIZE + line_size;
/*
* Move the code to its final location.
*/
- code = (BeamInstr *) erts_realloc(ERTS_ALC_T_CODE, (void *) code, size);
- CHKBLK(ERTS_ALC_T_CODE,code);
+ code_hdr = (BeamCodeHeader*) erts_realloc(ERTS_ALC_T_CODE, (void *) code_hdr, size);
+ codev = (BeamInstr*) &code_hdr->functions;
+ CHKBLK(ERTS_ALC_T_CODE,code_hdr);
/*
* Place a pointer to the op_int_code_end instruction in the
* function table in the beginning of the file.
*/
- code[MI_FUNCTIONS+stp->num_functions] = (BeamInstr) (code + stp->ci - 1);
- CHKBLK(ERTS_ALC_T_CODE,code);
+ code_hdr->functions[stp->num_functions] = (codev + stp->ci - 1);
+ CHKBLK(ERTS_ALC_T_CODE,code_hdr);
/*
* Store the pointer to the on_load function.
*/
if (stp->on_load) {
- code[MI_ON_LOAD_FUNCTION_PTR] = (BeamInstr) (code + stp->on_load);
+ code_hdr->on_load_function_ptr = codev + stp->on_load;
} else {
- code[MI_ON_LOAD_FUNCTION_PTR] = 0;
+ code_hdr->on_load_function_ptr = NULL;
}
- CHKBLK(ERTS_ALC_T_CODE,code);
+ CHKBLK(ERTS_ALC_T_CODE,code_hdr);
- literal_end = (Uint *) (code+stp->ci);
/*
- * Place the literal heap directly after the code and fix up all
- * instructions that refer to it.
+ * Place the literals in their own allocated heap (for fast range check)
+ * and fix up all instructions that refer to it.
*/
{
- Uint* ptr;
- Uint* low;
- Uint* high;
+ Eterm* ptr;
LiteralPatch* lp;
ErlOffHeap code_off_heap;
ERTS_INIT_OFF_HEAP(&code_off_heap);
- low = (Uint *) (code+stp->ci);
- high = low + stp->total_literal_size;
- code[MI_LITERALS_START] = (BeamInstr) low;
- code[MI_LITERALS_END] = (BeamInstr) high;
- ptr = low;
+ ptr = (Eterm*)erts_alloc(ERTS_ALC_T_LITERAL,
+ stp->total_literal_size*sizeof(Eterm));
+ code_hdr->literals_start = ptr;
+ code_hdr->literals_end = ptr + stp->total_literal_size;
for (i = 0; i < stp->num_literals; i++) {
- if (stp->literals[i].heap_frags) {
- move_multi_frags(&ptr, &code_off_heap, stp->literals[i].heap_frags,
- &stp->literals[i].term, 1);
+ if (is_not_immed(stp->literals[i].term)) {
+ erts_move_multi_frags(&ptr, &code_off_heap,
+ stp->literals[i].heap_frags,
+ &stp->literals[i].term, 1, 1);
+ ASSERT(erts_is_literal(stp->literals[i].term,
+ ptr_val(stp->literals[i].term)));
}
- else ASSERT(is_immed(stp->literals[i].term));
}
- code[MI_LITERALS_OFF_HEAP] = (BeamInstr) code_off_heap.first;
+ code_hdr->literals_off_heap = code_off_heap.first;
lp = stp->literal_patches;
while (lp != 0) {
BeamInstr* op_ptr;
Literal* lit;
- op_ptr = code + lp->pos;
+ op_ptr = codev + lp->pos;
lit = &stp->literals[op_ptr[0]];
op_ptr[0] = lit->term;
lp = lp->next;
}
- literal_end += stp->total_literal_size;
}
CHKBLK(ERTS_ALC_T_CODE,code);
@@ -4440,52 +4529,49 @@ freeze_code(LoaderState* stp)
* If there is line information, place it here.
*/
if (stp->line_instr == 0) {
- code[MI_LINE_TABLE] = (BeamInstr) 0;
- str_table = (byte *) literal_end;
+ code_hdr->line_table = NULL;
+ str_table = (byte *) (codev + stp->ci);
} else {
- Eterm* line_tab = (Eterm *) literal_end;
- Eterm* p;
- int ftab_size = stp->num_functions;
- int num_instrs = stp->current_li;
- Eterm* first_line_item;
+ BeamCodeLineTab* const line_tab = (BeamCodeLineTab *) (codev+stp->ci);
+ const int ftab_size = stp->num_functions;
+ const int num_instrs = stp->current_li;
+ const BeamInstr** const line_items =
+ (const BeamInstr**) &line_tab->func_tab[ftab_size + 1];
- code[MI_LINE_TABLE] = (BeamInstr) line_tab;
- p = line_tab + MI_LINE_FUNC_TAB;
+ code_hdr->line_table = line_tab;
- first_line_item = (p + ftab_size + 1);
for (i = 0; i < ftab_size; i++) {
- *p++ = (Eterm) (BeamInstr) (first_line_item + stp->func_line[i]);
+ line_tab->func_tab[i] = line_items + stp->func_line[i];
}
- *p++ = (Eterm) (BeamInstr) (first_line_item + num_instrs);
- ASSERT(p == first_line_item);
+ line_tab->func_tab[i] = line_items + num_instrs;
+
for (i = 0; i < num_instrs; i++) {
- *p++ = (Eterm) (BeamInstr) (code + stp->line_instr[i].pos);
+ line_items[i] = codev + stp->line_instr[i].pos;
}
- *p++ = (Eterm) (BeamInstr) (code + stp->ci - 1);
+ line_items[i] = codev + stp->ci - 1;
- line_tab[MI_LINE_FNAME_PTR] = (Eterm) (BeamInstr) p;
- memcpy(p, stp->fname, stp->num_fnames*sizeof(Eterm));
- p += stp->num_fnames;
+ line_tab->fname_ptr = (Eterm*) &line_items[i + 1];
+ memcpy(line_tab->fname_ptr, stp->fname, stp->num_fnames*sizeof(Eterm));
- line_tab[MI_LINE_LOC_TAB] = (Eterm) (BeamInstr) p;
- line_tab[MI_LINE_LOC_SIZE] = stp->loc_size;
+ line_tab->loc_size = stp->loc_size;
if (stp->loc_size == 2) {
- Uint16* locp = (Uint16 *) p;
- for (i = 0; i < num_instrs; i++) {
+ Uint16* locp = (Uint16 *) &line_tab->fname_ptr[stp->num_fnames];
+ line_tab->loc_tab.p2 = locp;
+ for (i = 0; i < num_instrs; i++) {
*locp++ = (Uint16) stp->line_instr[i].loc;
- }
- *locp++ = LINE_INVALID_LOCATION;
- str_table = (byte *) locp;
+ }
+ *locp++ = LINE_INVALID_LOCATION;
+ str_table = (byte *) locp;
} else {
- Uint32* locp = (Uint32 *) p;
- ASSERT(stp->loc_size == 4);
+ Uint32* locp = (Uint32 *) &line_tab->fname_ptr[stp->num_fnames];
+ ASSERT(stp->loc_size == 4);
+ line_tab->loc_tab.p4 = locp;
for (i = 0; i < num_instrs; i++) {
*locp++ = stp->line_instr[i].loc;
}
*locp++ = LINE_INVALID_LOCATION;
- str_table = (byte *) locp;
+ str_table = (byte *) locp;
}
-
CHKBLK(ERTS_ALC_T_CODE,code);
}
@@ -4497,13 +4583,13 @@ freeze_code(LoaderState* stp)
if (attr_size) {
byte* attr = str_table + strtab_size;
sys_memcpy(attr, stp->chunks[ATTR_CHUNK].start, stp->chunks[ATTR_CHUNK].size);
- code[MI_ATTR_PTR] = (BeamInstr) attr;
- code[MI_ATTR_SIZE] = (BeamInstr) stp->chunks[ATTR_CHUNK].size;
+ code_hdr->attr_ptr = attr;
+ code_hdr->attr_size = (BeamInstr) stp->chunks[ATTR_CHUNK].size;
decoded_size = erts_decode_ext_size(attr, attr_size);
if (decoded_size < 0) {
LoadError0(stp, "bad external term representation of module attributes");
}
- code[MI_ATTR_SIZE_ON_HEAP] = decoded_size;
+ code_hdr->attr_size_on_heap = decoded_size;
}
CHKBLK(ERTS_ALC_T_CODE,code);
if (compile_size) {
@@ -4513,9 +4599,9 @@ freeze_code(LoaderState* stp)
stp->chunks[COMPILE_CHUNK].size);
CHKBLK(ERTS_ALC_T_CODE,code);
- code[MI_COMPILE_PTR] = (BeamInstr) compile_info;
+ code_hdr->compile_ptr = compile_info;
CHKBLK(ERTS_ALC_T_CODE,code);
- code[MI_COMPILE_SIZE] = (BeamInstr) stp->chunks[COMPILE_CHUNK].size;
+ code_hdr->compile_size = (BeamInstr) stp->chunks[COMPILE_CHUNK].size;
CHKBLK(ERTS_ALC_T_CODE,code);
decoded_size = erts_decode_ext_size(compile_info, compile_size);
CHKBLK(ERTS_ALC_T_CODE,code);
@@ -4523,7 +4609,7 @@ freeze_code(LoaderState* stp)
LoadError0(stp, "bad external term representation of compilation information");
}
CHKBLK(ERTS_ALC_T_CODE,code);
- code[MI_COMPILE_SIZE_ON_HEAP] = decoded_size;
+ code_hdr->compile_size_on_heap = decoded_size;
}
CHKBLK(ERTS_ALC_T_CODE,code);
{
@@ -4531,7 +4617,7 @@ freeze_code(LoaderState* stp)
CHKBLK(ERTS_ALC_T_CODE,code);
sys_memcpy(md5_sum, stp->mod_md5, MD5_SIZE);
CHKBLK(ERTS_ALC_T_CODE,code);
- code[MI_MD5_PTR] = (BeamInstr) md5_sum;
+ code_hdr->md5_ptr = md5_sum;
CHKBLK(ERTS_ALC_T_CODE,code);
}
CHKBLK(ERTS_ALC_T_CODE,code);
@@ -4540,7 +4626,7 @@ freeze_code(LoaderState* stp)
* Make sure that we have not overflowed the allocated code space.
*/
ASSERT(str_table + strtab_size + attr_size + compile_size + MD5_SIZE ==
- ((byte *) code) + size);
+ ((byte *) code_hdr) + size);
/*
* Patch all instructions that refer to the string table.
@@ -4552,46 +4638,47 @@ freeze_code(LoaderState* stp)
BeamInstr* op_ptr;
byte* strp;
- op_ptr = code + sp->pos;
+ op_ptr = codev + sp->pos;
strp = str_table + op_ptr[0];
op_ptr[0] = (BeamInstr) strp;
sp = sp->next;
}
}
- CHKBLK(ERTS_ALC_T_CODE,code);
+ CHKBLK(ERTS_ALC_T_CODE,code_hdr);
/*
* Resolve all labels.
*/
for (i = 0; i < stp->num_labels; i++) {
- Uint this_patch;
- Uint next_patch;
+ Sint this_patch;
+ Sint next_patch;
Uint value = stp->labels[i].value;
- if (value == 0 && stp->labels[i].patches != 0) {
+ if (value == 0 && stp->labels[i].patches >= 0) {
LoadError1(stp, "label %d not resolved", i);
}
ASSERT(value < stp->ci);
this_patch = stp->labels[i].patches;
- while (this_patch != 0) {
+ while (this_patch >= 0) {
ASSERT(this_patch < stp->ci);
- next_patch = code[this_patch];
+ next_patch = codev[this_patch];
ASSERT(next_patch < stp->ci);
- code[this_patch] = (BeamInstr) (code + value);
+ codev[this_patch] = (BeamInstr) (codev + value);
this_patch = next_patch;
}
}
- CHKBLK(ERTS_ALC_T_CODE,code);
+ CHKBLK(ERTS_ALC_T_CODE,code_hdr);
/*
* Save the updated code pointer and code size.
*/
- stp->code = code;
+ stp->hdr = code_hdr;
+ stp->codev = codev;
stp->loaded_size = size;
- CHKBLK(ERTS_ALC_T_CODE,code);
+ CHKBLK(ERTS_ALC_T_CODE,code_hdr);
return 1;
load_error:
@@ -4599,7 +4686,8 @@ freeze_code(LoaderState* stp)
* Make sure that the caller frees the newly reallocated block, and
* not the old one (in case it has moved).
*/
- stp->code = code;
+ stp->hdr = code_hdr;
+ stp->codev = codev;
return 0;
}
@@ -4610,7 +4698,7 @@ final_touch(LoaderState* stp)
int on_load = stp->on_load;
unsigned catches;
Uint index;
- BeamInstr* code = stp->code;
+ BeamInstr* codev = stp->codev;
Module* modp;
/*
@@ -4620,10 +4708,10 @@ final_touch(LoaderState* stp)
index = stp->catches;
catches = BEAM_CATCHES_NIL;
while (index != 0) {
- BeamInstr next = code[index];
- code[index] = BeamOpCode(op_catch_yf);
- catches = beam_catches_cons((BeamInstr *)code[index+2], catches);
- code[index+2] = make_catch(catches);
+ BeamInstr next = codev[index];
+ codev[index] = BeamOpCode(op_catch_yf);
+ catches = beam_catches_cons((BeamInstr *)codev[index+2], catches);
+ codev[index+2] = make_catch(catches);
index = next;
}
modp = erts_put_module(stp->module);
@@ -4674,8 +4762,8 @@ final_touch(LoaderState* stp)
current = stp->import[i].patches;
while (current != 0) {
ASSERT(current < stp->ci);
- next = stp->code[current];
- stp->code[current] = import;
+ next = stp->codev[current];
+ stp->codev[current] = import;
current = next;
}
}
@@ -4688,7 +4776,7 @@ final_touch(LoaderState* stp)
for (i = 0; i < stp->num_lambdas; i++) {
unsigned entry_label = stp->lambdas[i].label;
ErlFunEntry* fe = stp->lambdas[i].fe;
- BeamInstr* code_ptr = (BeamInstr *) (stp->code + stp->labels[entry_label].value);
+ BeamInstr* code_ptr = stp->codev + stp->labels[entry_label].value;
if (fe->address[0] != 0) {
/*
@@ -4801,7 +4889,8 @@ transform_engine(LoaderState* st)
if (var[i].type != instr->a[ap].type)
goto restart;
switch (var[i].type) {
- case TAG_r: case TAG_n: break;
+ case TAG_n:
+ break;
default:
if (var[i].val != instr->a[ap].val)
goto restart;
@@ -5311,7 +5400,7 @@ new_label(LoaderState* stp)
(void *) stp->labels,
stp->num_labels * sizeof(Label));
stp->labels[num].value = 0;
- stp->labels[num].patches = 0;
+ stp->labels[num].patches = -1;
return num;
}
@@ -5371,7 +5460,7 @@ erts_module_info_0(Process* p, Eterm module)
{
Module* modp;
ErtsCodeIndex code_ix = erts_active_code_ix();
- BeamInstr* code;
+ BeamCodeHeader* code_hdr;
Eterm *hp;
Eterm list = NIL;
Eterm tup;
@@ -5385,13 +5474,13 @@ erts_module_info_0(Process* p, Eterm module)
return THE_NON_VALUE;
}
- code = modp->curr.code;
- if (code == NULL) {
+ code_hdr = modp->curr.code_hdr;
+ if (code_hdr == NULL) {
return THE_NON_VALUE;
}
#define BUILD_INFO(What) \
- tup = get_module_info(p, code_ix, code, module, What); \
+ tup = get_module_info(p, code_ix, code_hdr, module, What); \
hp = HAlloc(p, 5); \
tup = TUPLE2(hp, What, tup); \
hp += 3; \
@@ -5414,7 +5503,7 @@ erts_module_info_1(Process* p, Eterm module, Eterm what)
{
Module* modp;
ErtsCodeIndex code_ix = erts_active_code_ix();
- BeamInstr* code;
+ BeamCodeHeader* code_hdr;
if (is_not_atom(module)) {
return THE_NON_VALUE;
@@ -5425,34 +5514,34 @@ erts_module_info_1(Process* p, Eterm module, Eterm what)
return THE_NON_VALUE;
}
- code = modp->curr.code;
- if (code == NULL) {
+ code_hdr = modp->curr.code_hdr;
+ if (code_hdr == NULL) {
return THE_NON_VALUE;
}
- return get_module_info(p, code_ix, code, module, what);
+ return get_module_info(p, code_ix, code_hdr, module, what);
}
static Eterm
-get_module_info(Process* p, ErtsCodeIndex code_ix, BeamInstr* code,
+get_module_info(Process* p, ErtsCodeIndex code_ix, BeamCodeHeader* code_hdr,
Eterm module, Eterm what)
{
if (what == am_module) {
return module;
} else if (what == am_md5) {
- return md5_of_module(p, code);
+ return md5_of_module(p, code_hdr);
} else if (what == am_exports) {
return exported_from_module(p, code_ix, module);
} else if (what == am_functions) {
- return functions_in_module(p, code);
+ return functions_in_module(p, code_hdr);
} else if (what == am_attributes) {
- return attributes_for_module(p, code);
+ return attributes_for_module(p, code_hdr);
} else if (what == am_compile) {
- return compilation_info_for_module(p, code);
+ return compilation_info_for_module(p, code_hdr);
} else if (what == am_native_addresses) {
- return native_addresses(p, code);
+ return native_addresses(p, code_hdr);
} else if (what == am_native) {
- return has_native(code);
+ return has_native(code_hdr);
}
return THE_NON_VALUE;
}
@@ -5464,7 +5553,7 @@ get_module_info(Process* p, ErtsCodeIndex code_ix, BeamInstr* code,
Eterm
functions_in_module(Process* p, /* Process whose heap to use. */
- BeamInstr* code)
+ BeamCodeHeader* code_hdr)
{
int i;
Uint num_functions;
@@ -5473,12 +5562,12 @@ functions_in_module(Process* p, /* Process whose heap to use. */
Eterm* hp_end;
Eterm result = NIL;
- num_functions = code[MI_NUM_FUNCTIONS];
+ num_functions = code_hdr->num_functions;
need = 5*num_functions;
hp = HAlloc(p, need);
hp_end = hp + need;
for (i = num_functions-1; i >= 0 ; i--) {
- BeamInstr* func_info = (BeamInstr *) code[MI_FUNCTIONS+i];
+ BeamInstr* func_info = code_hdr->functions[i];
Eterm name = (Eterm) func_info[3];
int arity = (int) func_info[4];
Eterm tuple;
@@ -5504,11 +5593,11 @@ functions_in_module(Process* p, /* Process whose heap to use. */
*/
static Eterm
-has_native(BeamInstr *code)
+has_native(BeamCodeHeader *code_hdr)
{
Eterm result = am_false;
#ifdef HIPE
- if (erts_is_module_native(code)) {
+ if (erts_is_module_native(code_hdr)) {
result = am_true;
}
#endif
@@ -5516,15 +5605,15 @@ has_native(BeamInstr *code)
}
int
-erts_is_module_native(BeamInstr* code)
+erts_is_module_native(BeamCodeHeader* code_hdr)
{
Uint i, num_functions;
/* Check NativeAdress of first real function in module */
- if (code != NULL) {
- num_functions = code[MI_NUM_FUNCTIONS];
+ if (code_hdr != NULL) {
+ num_functions = code_hdr->num_functions;
for (i=0; i<num_functions; i++) {
- BeamInstr* func_info = (BeamInstr *) code[MI_FUNCTIONS+i];
+ BeamInstr* func_info = (BeamInstr *) code_hdr->functions[i];
Eterm name = (Eterm) func_info[3];
if (is_atom(name)) {
return func_info[1] != 0;
@@ -5541,7 +5630,7 @@ erts_is_module_native(BeamInstr* code)
*/
static Eterm
-native_addresses(Process* p, BeamInstr* code)
+native_addresses(Process* p, BeamCodeHeader* code_hdr)
{
int i;
Eterm* hp;
@@ -5550,12 +5639,12 @@ native_addresses(Process* p, BeamInstr* code)
Eterm* hp_end;
Eterm result = NIL;
- num_functions = code[MI_NUM_FUNCTIONS];
+ num_functions = code_hdr->num_functions;
need = (6+BIG_UINT_HEAP_SIZE)*num_functions;
hp = HAlloc(p, need);
hp_end = hp + need;
for (i = num_functions-1; i >= 0 ; i--) {
- BeamInstr* func_info = (BeamInstr *) code[MI_FUNCTIONS+i];
+ BeamInstr* func_info = code_hdr->functions[i];
Eterm name = (Eterm) func_info[3];
int arity = (int) func_info[4];
Eterm tuple;
@@ -5621,15 +5710,15 @@ exported_from_module(Process* p, /* Process whose heap to use. */
Eterm
attributes_for_module(Process* p, /* Process whose heap to use. */
- BeamInstr* code)
+ BeamCodeHeader* code_hdr)
{
byte* ext;
Eterm result = NIL;
- ext = (byte *) code[MI_ATTR_PTR];
+ ext = code_hdr->attr_ptr;
if (ext != NULL) {
ErtsHeapFactory factory;
- erts_factory_proc_prealloc_init(&factory, p, code[MI_ATTR_SIZE_ON_HEAP]);
+ erts_factory_proc_prealloc_init(&factory, p, code_hdr->attr_size_on_heap);
result = erts_decode_ext(&factory, &ext);
if (is_value(result)) {
erts_factory_close(&factory);
@@ -5644,15 +5733,15 @@ attributes_for_module(Process* p, /* Process whose heap to use. */
Eterm
compilation_info_for_module(Process* p, /* Process whose heap to use. */
- BeamInstr* code)
+ BeamCodeHeader* code_hdr)
{
byte* ext;
Eterm result = NIL;
- ext = (byte *) code[MI_COMPILE_PTR];
+ ext = code_hdr->compile_ptr;
if (ext != NULL) {
ErtsHeapFactory factory;
- erts_factory_proc_prealloc_init(&factory, p, code[MI_COMPILE_SIZE_ON_HEAP]);
+ erts_factory_proc_prealloc_init(&factory, p, code_hdr->compile_size_on_heap);
result = erts_decode_ext(&factory, &ext);
if (is_value(result)) {
erts_factory_close(&factory);
@@ -5667,9 +5756,9 @@ compilation_info_for_module(Process* p, /* Process whose heap to use. */
Eterm
md5_of_module(Process* p, /* Process whose heap to use. */
- BeamInstr* code)
+ BeamCodeHeader* code_hdr)
{
- return new_binary(p, (byte *) code[MI_MD5_PTR], MD5_SIZE);
+ return new_binary(p, code_hdr->md5_ptr, MD5_SIZE);
}
/*
@@ -5868,7 +5957,7 @@ make_stub(BeamInstr* fp, Eterm mod, Eterm func, Uint arity, Uint native, BeamIns
fp[4] = arity;
#ifdef HIPE
if (native) {
- fp[5] = BeamOpCode(op_move_return_nr);
+ fp[5] = BeamOpCode(op_move_return_n);
hipe_mfa_save_orig_beam_op(mod, func, arity, fp+5);
}
#endif
@@ -5880,7 +5969,7 @@ static byte*
stub_copy_info(LoaderState* stp,
int chunk, /* Chunk: ATTR_CHUNK or COMPILE_CHUNK */
byte* info, /* Where to store info. */
- BeamInstr* ptr_word, /* Where to store pointer into info. */
+ byte** ptr_word, /* Where to store pointer into info. */
BeamInstr* size_word, /* Where to store size into info. */
BeamInstr* size_on_heap_word) /* Where to store size on heap. */
{
@@ -5888,7 +5977,7 @@ stub_copy_info(LoaderState* stp,
Uint size = stp->chunks[chunk].size;
if (size != 0) {
memcpy(info, stp->chunks[chunk].start, size);
- *ptr_word = (BeamInstr) info;
+ *ptr_word = info;
decoded_size = erts_decode_ext_size(info, size);
if (decoded_size < 0) {
return 0;
@@ -6143,15 +6232,14 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
BeamInstr Patchlist;
Eterm MD5Bin;
Eterm* tp;
- BeamInstr* code = NULL;
- BeamInstr* ptrs;
+ BeamCodeHeader* code_hdr;
+ BeamInstr* code_base;
BeamInstr* fp;
byte* info;
- Uint ci;
- int n;
+ Sint n;
int code_size;
int rval;
- int i;
+ Sint i;
byte* temp_alloc = NULL;
byte* bytes;
Uint size;
@@ -6225,40 +6313,40 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
* Allocate memory for the stub module.
*/
- code_size = ((WORDS_PER_FUNCTION+1)*n + MI_FUNCTIONS + 2) * sizeof(BeamInstr);
- code_size += stp->chunks[ATTR_CHUNK].size;
- code_size += stp->chunks[COMPILE_CHUNK].size;
- code_size += MD5_SIZE;
- code = erts_alloc_fnf(ERTS_ALC_T_CODE, code_size);
- if (!code) {
+ code_size = (offsetof(BeamCodeHeader,functions)
+ + ((n+1) * sizeof(BeamInstr*))
+ + (WORDS_PER_FUNCTION*n + 1) * sizeof(BeamInstr)
+ + stp->chunks[ATTR_CHUNK].size
+ + stp->chunks[COMPILE_CHUNK].size
+ + MD5_SIZE);
+ code_hdr = erts_alloc_fnf(ERTS_ALC_T_CODE, code_size);
+ if (!code_hdr) {
goto error;
}
/*
- * Initialize code area.
+ * Initialize code header.
*/
- code[MI_NUM_FUNCTIONS] = n;
- code[MI_ATTR_PTR] = 0;
- code[MI_ATTR_SIZE] = 0;
- code[MI_ATTR_SIZE_ON_HEAP] = 0;
- code[MI_COMPILE_PTR] = 0;
- code[MI_COMPILE_SIZE] = 0;
- code[MI_COMPILE_SIZE_ON_HEAP] = 0;
- code[MI_LITERALS_START] = 0;
- code[MI_LITERALS_END] = 0;
- code[MI_LITERALS_OFF_HEAP] = 0;
- code[MI_ON_LOAD_FUNCTION_PTR] = 0;
- code[MI_LINE_TABLE] = 0;
- code[MI_MD5_PTR] = 0;
- ci = MI_FUNCTIONS + n + 1;
+ code_hdr->num_functions = n;
+ code_hdr->attr_ptr = NULL;
+ code_hdr->attr_size = 0;
+ code_hdr->attr_size_on_heap = 0;
+ code_hdr->compile_ptr = NULL;
+ code_hdr->compile_size = 0;
+ code_hdr->compile_size_on_heap = 0;
+ code_hdr->literals_start = NULL;
+ code_hdr->literals_end = NULL;
+ code_hdr->literals_off_heap = 0;
+ code_hdr->on_load_function_ptr = NULL;
+ code_hdr->line_table = NULL;
+ code_hdr->md5_ptr = NULL;
/*
* Make stubs for all functions.
*/
- ptrs = code + MI_FUNCTIONS;
- fp = code + ci;
+ fp = code_base = (BeamInstr*) &code_hdr->functions[n+1];
for (i = 0; i < n; i++) {
Eterm* listp;
Eterm tuple;
@@ -6301,11 +6389,11 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
* Set the pointer and make the stub. Put a return instruction
* as the body until we know what kind of trap we should put there.
*/
- ptrs[i] = (BeamInstr) fp;
+ code_hdr->functions[i] = fp;
#ifdef HIPE
op = (Eterm) BeamOpCode(op_hipe_trap_call); /* Might be changed later. */
#else
- op = (Eterm) BeamOpCode(op_move_return_nr);
+ op = (Eterm) BeamOpCode(op_move_return_n);
#endif
fp = make_stub(fp, Mod, func, arity, (Uint)native_address, op);
}
@@ -6314,7 +6402,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
* Insert the last pointer and the int_code_end instruction.
*/
- ptrs[i] = (BeamInstr) fp;
+ code_hdr->functions[i] = fp;
*fp++ = (BeamInstr) BeamOp(op_int_code_end);
/*
@@ -6323,16 +6411,16 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
info = (byte *) fp;
info = stub_copy_info(stp, ATTR_CHUNK, info,
- code+MI_ATTR_PTR,
- code+MI_ATTR_SIZE,
- code+MI_ATTR_SIZE_ON_HEAP);
+ &code_hdr->attr_ptr,
+ &code_hdr->attr_size,
+ &code_hdr->attr_size_on_heap);
if (info == NULL) {
goto error;
}
info = stub_copy_info(stp, COMPILE_CHUNK, info,
- code+MI_COMPILE_PTR,
- code+MI_COMPILE_SIZE,
- code+MI_COMPILE_SIZE_ON_HEAP);
+ &code_hdr->compile_ptr,
+ &code_hdr->compile_size,
+ &code_hdr->compile_size_on_heap);
if (info == NULL) {
goto error;
}
@@ -6341,7 +6429,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
byte *md5 = NULL;
if ((md5 = erts_get_aligned_binary_bytes(MD5Bin, &tmp)) != NULL) {
sys_memcpy(info, md5, MD5_SIZE);
- code[MI_MD5_PTR] = (BeamInstr) info;
+ code_hdr->md5_ptr = info;
}
erts_free_aligned_binary_bytes(tmp);
}
@@ -6350,7 +6438,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
* Insert the module in the module table.
*/
- rval = insert_new_code(p, 0, p->group_leader, Mod, code, code_size);
+ rval = insert_new_code(p, 0, p->group_leader, Mod, code_hdr, code_size);
if (rval != NIL) {
goto error;
}
@@ -6359,7 +6447,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
* Export all stub functions and insert the correct type of HiPE trap.
*/
- fp = code + ci;
+ fp = code_base;
for (i = 0; i < n; i++) {
stub_final_touch(stp, fp);
fp += WORDS_PER_FUNCTION;
diff --git a/erts/emulator/beam/beam_load.h b/erts/emulator/beam/beam_load.h
index d5af634fad..22ab71c868 100644
--- a/erts/emulator/beam/beam_load.h
+++ b/erts/emulator/beam/beam_load.h
@@ -24,7 +24,6 @@
#include "beam_opcodes.h"
#include "erl_process.h"
-int erts_is_module_native(BeamInstr* code);
Eterm beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks,
Eterm module);
@@ -52,6 +51,7 @@ extern BeamInstr* em_call_error_handler;
extern BeamInstr* em_apply_bif;
extern BeamInstr* em_call_nif;
+
/*
* The following variables keep a sorted list of address ranges for
* each module. It allows us to quickly find a function given an
@@ -60,72 +60,81 @@ extern BeamInstr* em_call_nif;
/* Total code size in bytes */
extern Uint erts_total_code_size;
-/*
- * Index into start of code chunks which contains additional information
- * about the loaded module.
- *
- * First number of functions.
- */
-#define MI_NUM_FUNCTIONS 0
+typedef struct BeamCodeLineTab_ BeamCodeLineTab;
/*
- * The attributes retrieved by Mod:module_info(attributes).
- */
-
-#define MI_ATTR_PTR 1
-#define MI_ATTR_SIZE 2
-#define MI_ATTR_SIZE_ON_HEAP 3
-
-/*
- * The compilation information retrieved by Mod:module_info(compile).
- */
-
-#define MI_COMPILE_PTR 4
-#define MI_COMPILE_SIZE 5
-#define MI_COMPILE_SIZE_ON_HEAP 6
-
-/*
- * Literal area (constant pool).
- */
-#define MI_LITERALS_START 7
-#define MI_LITERALS_END 8
-#define MI_LITERALS_OFF_HEAP 9
-
-/*
- * Pointer to the on_load function (or NULL if none).
- */
-#define MI_ON_LOAD_FUNCTION_PTR 10
-
-/*
- * Pointer to the line table (or NULL if none).
- */
-#define MI_LINE_TABLE 11
-
-/*
- * Pointer to the module MD5 sum (16 bytes)
- */
-#define MI_MD5_PTR 12
-
-/*
- * Start of function pointer table. This table contains pointers to
- * all functions in the module plus an additional pointer just beyond
- * the end of the last function.
- *
- * The actual loaded code (for the first function) start just beyond
- * this table.
+ * Header of code chunks which contains additional information
+ * about the loaded module.
*/
-
-#define MI_FUNCTIONS 13
+typedef struct beam_code_header {
+ /*
+ * Number of functions.
+ */
+ UWord num_functions;
+
+ /*
+ * The attributes retrieved by Mod:module_info(attributes).
+ */
+ byte* attr_ptr;
+ UWord attr_size;
+ UWord attr_size_on_heap;
+
+ /*
+ * The compilation information retrieved by Mod:module_info(compile).
+ */
+ byte* compile_ptr;
+ UWord compile_size;
+ UWord compile_size_on_heap;
+
+ /*
+ * Literal area (constant pool).
+ */
+ Eterm* literals_start;
+ Eterm* literals_end;
+ struct erl_off_heap_header* literals_off_heap;
+
+ /*
+ * Pointer to the on_load function (or NULL if none).
+ */
+ BeamInstr* on_load_function_ptr;
+
+ /*
+ * Pointer to the line table (or NULL if none).
+ */
+ BeamCodeLineTab* line_table;
+
+ /*
+ * Pointer to the module MD5 sum (16 bytes)
+ */
+ byte* md5_ptr;
+
+ /*
+ * Start of function pointer table. This table contains pointers to
+ * all functions in the module plus an additional pointer just beyond
+ * the end of the last function.
+ *
+ * The actual loaded code (for the first function) start just beyond
+ * this table.
+ */
+ BeamInstr* functions[1];
+
+}BeamCodeHeader;
+
+int erts_is_module_native(BeamCodeHeader* code);
/*
* Layout of the line table.
*/
-
-#define MI_LINE_FNAME_PTR 0
-#define MI_LINE_LOC_TAB 1
-#define MI_LINE_LOC_SIZE 2
-#define MI_LINE_FUNC_TAB 3
+struct BeamCodeLineTab_ {
+ Eterm* fname_ptr;
+ int loc_size;
+ union {
+ Uint16* p2;
+ Uint32* p4;
+ }loc_tab;
+ const BeamInstr** func_tab[1];
+};
#define LINE_INVALID_LOCATION (0)
diff --git a/erts/emulator/beam/beam_ranges.c b/erts/emulator/beam/beam_ranges.c
index 19079ba150..54c337ee72 100644
--- a/erts/emulator/beam/beam_ranges.c
+++ b/erts/emulator/beam/beam_ranges.c
@@ -37,8 +37,8 @@ typedef struct {
#define RANGE_END(R) ((BeamInstr*)erts_smp_atomic_read_nob(&(R)->end))
static Range* find_range(BeamInstr* pc);
-static void lookup_loc(FunctionInfo* fi, BeamInstr* pc,
- BeamInstr* modp, int idx);
+static void lookup_loc(FunctionInfo* fi, const BeamInstr* pc,
+ BeamCodeHeader*, int idx);
/*
* The following variables keep a sorted list of address ranges for
@@ -53,6 +53,7 @@ struct ranges {
};
static struct ranges r[ERTS_NUM_CODE_IX];
static erts_smp_atomic_t mem_used;
+static Range* write_ptr;
#ifdef HARD_DEBUG
static void check_consistency(struct ranges* p)
@@ -72,6 +73,17 @@ static void check_consistency(struct ranges* p)
# define CHECK(r)
#endif /* HARD_DEBUG */
+static int
+rangecompare(Range* a, Range* b)
+{
+ if (a->start < b->start) {
+ return -1;
+ } else if (a->start == b->start) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
void
erts_init_ranges(void)
@@ -88,45 +100,70 @@ erts_init_ranges(void)
}
void
-erts_start_staging_ranges(void)
+erts_start_staging_ranges(int num_new)
{
+ ErtsCodeIndex src = erts_active_code_ix();
ErtsCodeIndex dst = erts_staging_code_ix();
+ Sint need;
if (r[dst].modules) {
erts_smp_atomic_add_nob(&mem_used, -r[dst].allocated);
erts_free(ERTS_ALC_T_MODULE_REFS, r[dst].modules);
- r[dst].modules = NULL;
}
+
+ need = r[dst].allocated = r[src].n + num_new;
+ erts_smp_atomic_add_nob(&mem_used, need);
+ write_ptr = erts_alloc(ERTS_ALC_T_MODULE_REFS,
+ need * sizeof(Range));
+ r[dst].modules = write_ptr;
}
void
erts_end_staging_ranges(int commit)
{
- ErtsCodeIndex dst = erts_staging_code_ix();
-
- if (commit && r[dst].modules == NULL) {
+ if (commit) {
Sint i;
- Sint n;
-
- /* No modules added, just clone src and remove purged code. */
ErtsCodeIndex src = erts_active_code_ix();
+ ErtsCodeIndex dst = erts_staging_code_ix();
+ Range* mp;
+ Sint num_inserted;
- erts_smp_atomic_add_nob(&mem_used, r[src].n);
- r[dst].modules = erts_alloc(ERTS_ALC_T_MODULE_REFS,
- r[src].n * sizeof(Range));
- r[dst].allocated = r[src].n;
- n = 0;
+ mp = r[dst].modules;
+ num_inserted = write_ptr - mp;
for (i = 0; i < r[src].n; i++) {
Range* rp = r[src].modules+i;
if (rp->start < RANGE_END(rp)) {
/* Only insert a module that has not been purged. */
- r[dst].modules[n] = *rp;
- n++;
+ write_ptr->start = rp->start;
+ erts_smp_atomic_init_nob(&write_ptr->end,
+ (erts_aint_t)(RANGE_END(rp)));
+ write_ptr++;
+ }
+ }
+
+ /*
+ * There are num_inserted new range entries (unsorted) at the
+ * beginning of the modules array, followed by the old entries
+ * (sorted). We must now sort the entire array.
+ */
+
+ r[dst].n = write_ptr - mp;
+ if (num_inserted > 1) {
+ qsort(mp, r[dst].n, sizeof(Range),
+ (int (*)(const void *, const void *)) rangecompare);
+ } else if (num_inserted == 1) {
+ /* Sift the new range into place. This is faster than qsort(). */
+ Range t = mp[0];
+ for (i = 0; i < r[dst].n-1 && t.start > mp[i+1].start; i++) {
+ mp[i] = mp[i+1];
}
+ mp[i] = t;
}
- r[dst].n = n;
+ r[dst].modules = mp;
+ CHECK(&r[dst]);
erts_smp_atomic_set_nob(&r[dst].mid,
- (erts_aint_t) (r[dst].modules + n / 2));
+ (erts_aint_t) (r[dst].modules +
+ r[dst].n / 2));
}
}
@@ -135,82 +172,29 @@ erts_update_ranges(BeamInstr* code, Uint size)
{
ErtsCodeIndex dst = erts_staging_code_ix();
ErtsCodeIndex src = erts_active_code_ix();
- Sint i;
- Sint n;
- Sint need;
if (src == dst) {
ASSERT(!erts_initialized);
/*
- * During start-up of system, the indices are the same.
- * Handle this by faking a source area.
+ * During start-up of system, the indices are the same
+ * and erts_start_staging_ranges() has not been called.
*/
- src = (src+1) % ERTS_NUM_CODE_IX;
- if (r[src].modules) {
- erts_smp_atomic_add_nob(&mem_used, -r[src].allocated);
- erts_free(ERTS_ALC_T_MODULE_REFS, r[src].modules);
+ if (r[dst].modules == NULL) {
+ Sint need = 128;
+ erts_smp_atomic_add_nob(&mem_used, need);
+ r[dst].modules = erts_alloc(ERTS_ALC_T_MODULE_REFS,
+ need * sizeof(Range));
+ r[dst].allocated = need;
+ write_ptr = r[dst].modules;
}
- r[src] = r[dst];
- r[dst].modules = 0;
}
- CHECK(&r[src]);
-
- ASSERT(r[dst].modules == NULL);
- need = r[dst].allocated = r[src].n + 1;
- erts_smp_atomic_add_nob(&mem_used, need);
- r[dst].modules = (Range *) erts_alloc(ERTS_ALC_T_MODULE_REFS,
- need * sizeof(Range));
- n = 0;
- for (i = 0; i < r[src].n; i++) {
- Range* rp = r[src].modules+i;
- if (code < rp->start) {
- r[dst].modules[n].start = code;
- erts_smp_atomic_init_nob(&r[dst].modules[n].end,
- (erts_aint_t)(((byte *)code) + size));
- ASSERT(!n || RANGE_END(&r[dst].modules[n-1]) < code);
- n++;
- break;
- }
- if (rp->start < RANGE_END(rp)) {
- /* Only insert a module that has not been purged. */
- r[dst].modules[n].start = rp->start;
- erts_smp_atomic_init_nob(&r[dst].modules[n].end,
- (erts_aint_t)(RANGE_END(rp)));
- ASSERT(!n || RANGE_END(&r[dst].modules[n-1]) < rp->start);
- n++;
- }
- }
-
- while (i < r[src].n) {
- Range* rp = r[src].modules+i;
- if (rp->start < RANGE_END(rp)) {
- /* Only insert a module that has not been purged. */
- r[dst].modules[n].start = rp->start;
- erts_smp_atomic_init_nob(&r[dst].modules[n].end,
- (erts_aint_t)(RANGE_END(rp)));
- ASSERT(!n || RANGE_END(&r[dst].modules[n-1]) < rp->start);
- n++;
- }
- i++;
- }
-
- if (n == 0 || code > r[dst].modules[n-1].start) {
- r[dst].modules[n].start = code;
- erts_smp_atomic_init_nob(&r[dst].modules[n].end,
- (erts_aint_t)(((byte *)code) + size));
- ASSERT(!n || RANGE_END(&r[dst].modules[n-1]) < code);
- n++;
- }
-
- ASSERT(n <= r[src].n+1);
- r[dst].n = n;
- erts_smp_atomic_set_nob(&r[dst].mid,
- (erts_aint_t) (r[dst].modules + n / 2));
-
- CHECK(&r[dst]);
- CHECK(&r[src]);
+ ASSERT(r[dst].modules);
+ write_ptr->start = code;
+ erts_smp_atomic_init_nob(&(write_ptr->end),
+ (erts_aint_t)(((byte *)code) + size));
+ write_ptr++;
}
void
@@ -241,6 +225,7 @@ erts_lookup_function_info(FunctionInfo* fi, BeamInstr* pc, int full_info)
BeamInstr** high;
BeamInstr** mid;
Range* rp;
+ BeamCodeHeader* hdr;
fi->current = NULL;
fi->needed = 5;
@@ -249,9 +234,10 @@ erts_lookup_function_info(FunctionInfo* fi, BeamInstr* pc, int full_info)
if (rp == 0) {
return;
}
+ hdr = (BeamCodeHeader*) rp->start;
- low = (BeamInstr **) (rp->start + MI_FUNCTIONS);
- high = low + rp->start[MI_NUM_FUNCTIONS];
+ low = hdr->functions;
+ high = low + hdr->num_functions;
while (low < high) {
mid = low + (high-low) / 2;
if (pc < mid[0]) {
@@ -259,10 +245,9 @@ erts_lookup_function_info(FunctionInfo* fi, BeamInstr* pc, int full_info)
} else if (pc < mid[1]) {
fi->current = mid[0]+2;
if (full_info) {
- BeamInstr** fp = (BeamInstr **) (rp->start +
- MI_FUNCTIONS);
+ BeamInstr** fp = hdr->functions;
int idx = mid - fp;
- lookup_loc(fi, pc, rp->start, idx);
+ lookup_loc(fi, pc, hdr, idx);
}
return;
} else {
@@ -295,39 +280,34 @@ find_range(BeamInstr* pc)
}
static void
-lookup_loc(FunctionInfo* fi, BeamInstr* orig_pc, BeamInstr* modp, int idx)
+lookup_loc(FunctionInfo* fi, const BeamInstr* pc,
+ BeamCodeHeader* code_hdr, int idx)
{
- Eterm* line = (Eterm *) modp[MI_LINE_TABLE];
- Eterm* low;
- Eterm* high;
- Eterm* mid;
- Eterm pc;
+ BeamCodeLineTab* lt = code_hdr->line_table;
+ const BeamInstr** low;
+ const BeamInstr** high;
+ const BeamInstr** mid;
- if (line == 0) {
+ if (lt == NULL) {
return;
}
- pc = (Eterm) (BeamInstr) orig_pc;
- fi->fname_ptr = (Eterm *) (BeamInstr) line[MI_LINE_FNAME_PTR];
- low = (Eterm *) (BeamInstr) line[MI_LINE_FUNC_TAB+idx];
- high = (Eterm *) (BeamInstr) line[MI_LINE_FUNC_TAB+idx+1];
+ fi->fname_ptr = lt->fname_ptr;
+ low = lt->func_tab[idx];
+ high = lt->func_tab[idx+1];
while (high > low) {
mid = low + (high-low) / 2;
if (pc < mid[0]) {
high = mid;
} else if (pc < mid[1]) {
int file;
- int index = mid - (Eterm *) (BeamInstr) line[MI_LINE_FUNC_TAB];
+ int index = mid - lt->func_tab[0];
- if (line[MI_LINE_LOC_SIZE] == 2) {
- Uint16* loc_table =
- (Uint16 *) (BeamInstr) line[MI_LINE_LOC_TAB];
- fi->loc = loc_table[index];
+ if (lt->loc_size == 2) {
+ fi->loc = lt->loc_tab.p2[index];
} else {
- Uint32* loc_table =
- (Uint32 *) (BeamInstr) line[MI_LINE_LOC_TAB];
- ASSERT(line[MI_LINE_LOC_SIZE] == 4);
- fi->loc = loc_table[index];
+ ASSERT(lt->loc_size == 4);
+ fi->loc = lt->loc_tab.p4[index];
}
if (fi->loc == LINE_INVALID_LOCATION) {
return;
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 66c2853534..37bb28c6f8 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -44,6 +44,7 @@
#include "erl_ptab.h"
#include "erl_bits.h"
#include "erl_bif_unique.h"
+#include "erl_msacc.h"
Export *erts_await_result;
static Export* flush_monitor_messages_trap = NULL;
@@ -54,6 +55,9 @@ Export* erts_format_cpu_topology_trap = NULL;
static Export dsend_continue_trap_export;
Export *erts_convert_time_unit_trap = NULL;
+static Export *await_msacc_mod_trap = NULL;
+static erts_smp_atomic32_t msacc;
+
static Export *await_sched_wall_time_mod_trap;
static erts_smp_atomic32_t sched_wall_time;
@@ -72,7 +76,7 @@ BIF_RETTYPE spawn_3(BIF_ALIST_3)
ErlSpawnOpts so;
Eterm pid;
- so.flags = 0;
+ so.flags = erts_default_spo_flags;
pid = erl_create_process(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3, &so);
if (is_non_value(pid)) {
BIF_ERROR(BIF_P, so.error_code);
@@ -589,7 +593,7 @@ erts_queue_monitor_message(Process *p,
Eterm reason_copy, ref_copy, item_copy;
Uint reason_size, ref_size, item_size, heap_size;
ErlOffHeap *ohp;
- ErlHeapFragment *bp;
+ ErtsMessage *msgp;
reason_size = IS_CONST(reason) ? 0 : size_object(reason);
item_size = IS_CONST(item) ? 0 : size_object(item);
@@ -597,11 +601,8 @@ erts_queue_monitor_message(Process *p,
heap_size = 6+reason_size+ref_size+item_size;
- hp = erts_alloc_message_heap(heap_size,
- &bp,
- &ohp,
- p,
- p_locksp);
+ msgp = erts_alloc_message_heap(p, p_locksp, heap_size,
+ &hp, &ohp);
reason_copy = (IS_CONST(reason)
? reason
@@ -612,7 +613,7 @@ erts_queue_monitor_message(Process *p,
ref_copy = copy_struct(ref, ref_size, &hp, ohp);
tup = TUPLE5(hp, am_DOWN, ref_copy, type, item_copy, reason_copy);
- erts_queue_message(p, p_locksp, bp, tup, NIL);
+ erts_queue_message(p, p_locksp, msgp, tup, NIL);
}
static BIF_RETTYPE
@@ -841,7 +842,7 @@ BIF_RETTYPE spawn_link_3(BIF_ALIST_3)
ErlSpawnOpts so;
Eterm pid;
- so.flags = SPO_LINK;
+ so.flags = erts_default_spo_flags|SPO_LINK;
pid = erl_create_process(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3, &so);
if (is_non_value(pid)) {
BIF_ERROR(BIF_P, so.error_code);
@@ -878,7 +879,7 @@ BIF_RETTYPE spawn_opt_1(BIF_ALIST_1)
/*
* Store default values for options.
*/
- so.flags = SPO_USE_ARGS;
+ so.flags = erts_default_spo_flags|SPO_USE_ARGS;
so.min_heap_size = H_MIN_SIZE;
so.min_vheap_size = BIN_VH_MIN_SIZE;
so.priority = PRIORITY_NORMAL;
@@ -913,6 +914,22 @@ BIF_RETTYPE spawn_opt_1(BIF_ALIST_1)
so.priority = PRIORITY_LOW;
else
goto error;
+ } else if (arg == am_message_queue_data) {
+ switch (val) {
+ case am_mixed:
+ so.flags &= ~(SPO_OFF_HEAP_MSGQ|SPO_ON_HEAP_MSGQ);
+ break;
+ case am_on_heap:
+ so.flags &= ~SPO_OFF_HEAP_MSGQ;
+ so.flags |= SPO_ON_HEAP_MSGQ;
+ break;
+ case am_off_heap:
+ so.flags &= ~SPO_ON_HEAP_MSGQ;
+ so.flags |= SPO_OFF_HEAP_MSGQ;
+ break;
+ default:
+ goto error;
+ }
} else if (arg == am_min_heap_size && is_small(val)) {
Sint min_heap_size = signed_val(val);
if (min_heap_size < 0) {
@@ -1691,6 +1708,12 @@ BIF_RETTYPE process_flag_2(BIF_ALIST_2)
}
BIF_RET(old_value);
}
+ else if (BIF_ARG_1 == am_message_queue_data) {
+ old_value = erts_change_message_queue_management(BIF_P, BIF_ARG_2);
+ if (is_non_value(old_value))
+ goto error;
+ BIF_RET(old_value);
+ }
else if (BIF_ARG_1 == am_sensitive) {
Uint is_sensitive;
if (BIF_ARG_2 == am_true) {
@@ -1931,7 +1954,7 @@ do_send(Process *p, Eterm to, Eterm msg, Eterm *refp, ErtsSendContext* ctx)
} else if (is_atom(to)) {
Eterm id = erts_whereis_name_to_id(p, to);
- rp = erts_proc_lookup(id);
+ rp = erts_proc_lookup_raw(id);
if (rp) {
if (IS_TRACED(p))
trace_send(p, to, msg);
@@ -2023,11 +2046,7 @@ do_send(Process *p, Eterm to, Eterm msg, Eterm *refp, ErtsSendContext* ctx)
if (ERTS_PROC_GET_SAVED_CALLS_BUF(p))
save_calls(p, &exp_send);
- if (SEQ_TRACE_TOKEN(p) != NIL
-#ifdef USE_VM_PROBES
- && SEQ_TRACE_TOKEN(p) != am_have_dt_utag
-#endif
- ) {
+ if (have_seqtrace(SEQ_TRACE_TOKEN(p))) {
seq_trace_update_send(p);
seq_trace_output(SEQ_TRACE_TOKEN(p), msg,
SEQ_TRACE_SEND, portid, p);
@@ -2128,7 +2147,11 @@ BIF_RETTYPE send_3(BIF_ALIST_3)
int connect = !0;
Eterm l = opts;
Sint result;
+
DeclareTypedTmpHeap(ErtsSendContext, ctx, BIF_P);
+
+ ERTS_MSACC_PUSH_STATE_M_X();
+
UseTmpHeap(sizeof(ErtsSendContext)/sizeof(Eterm), BIF_P);
ctx->suspend = !0;
@@ -2157,7 +2180,10 @@ BIF_RETTYPE send_3(BIF_ALIST_3)
ref = NIL;
#endif
+ ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_SEND);
result = do_send(p, to, msg, &ref, ctx);
+ ERTS_MSACC_POP_STATE_M_X();
+
if (result > 0) {
ERTS_VBUMP_REDS(p, result);
if (ERTS_IS_PROC_OUT_OF_REDS(p))
@@ -2273,8 +2299,8 @@ Eterm erl_send(Process *p, Eterm to, Eterm msg)
Eterm ref;
Sint result;
DeclareTypedTmpHeap(ErtsSendContext, ctx, p);
+ ERTS_MSACC_PUSH_AND_SET_STATE_M_X(ERTS_MSACC_STATE_SEND);
UseTmpHeap(sizeof(ErtsSendContext)/sizeof(Eterm), p);
-
#ifdef DEBUG
ref = NIL;
#endif
@@ -2285,7 +2311,9 @@ Eterm erl_send(Process *p, Eterm to, Eterm msg)
ctx->dss.phase = ERTS_DSIG_SEND_PHASE_INIT;
result = do_send(p, to, msg, &ref, ctx);
-
+
+ ERTS_MSACC_POP_STATE_M_X();
+
if (result > 0) {
ERTS_VBUMP_REDS(p, result);
if (ERTS_IS_PROC_OUT_OF_REDS(p))
@@ -2809,7 +2837,7 @@ BIF_RETTYPE list_to_atom_1(BIF_ALIST_1)
{
Eterm res;
char *buf = (char *) erts_alloc(ERTS_ALC_T_TMP, MAX_ATOM_CHARACTERS);
- int i = intlist_to_buf(BIF_ARG_1, buf, MAX_ATOM_CHARACTERS);
+ Sint i = intlist_to_buf(BIF_ARG_1, buf, MAX_ATOM_CHARACTERS);
if (i < 0) {
erts_free(ERTS_ALC_T_TMP, (void *) buf);
@@ -2829,7 +2857,7 @@ BIF_RETTYPE list_to_atom_1(BIF_ALIST_1)
BIF_RETTYPE list_to_existing_atom_1(BIF_ALIST_1)
{
- int i;
+ Sint i;
char *buf = (char *) erts_alloc(ERTS_ALC_T_TMP, MAX_ATOM_CHARACTERS);
if ((i = intlist_to_buf(BIF_ARG_1, buf, MAX_ATOM_CHARACTERS)) < 0) {
@@ -2889,175 +2917,20 @@ BIF_RETTYPE integer_to_list_1(BIF_ALIST_1)
/**********************************************************************/
-/* convert a list of ascii ascii integer value to an integer */
-
-
-#define LTI_BAD_STRUCTURE 0
-#define LTI_NO_INTEGER 1
-#define LTI_SOME_INTEGER 2
-#define LTI_ALL_INTEGER 3
-
-static int do_list_to_integer(Process *p, Eterm orig_list,
- Eterm *integer, Eterm *rest)
-{
- Sint i = 0;
- Uint ui = 0;
- int skip = 0;
- int neg = 0;
- Sint n = 0;
- int m;
- int lg2;
- Eterm res;
- Eterm* hp;
- Eterm *hp_end;
- Eterm lst = orig_list;
- Eterm tail = lst;
- int error_res = LTI_BAD_STRUCTURE;
-
- if (is_nil(lst)) {
- error_res = LTI_NO_INTEGER;
- error:
- *rest = tail;
- *integer = make_small(0);
- return error_res;
- }
- if (is_not_list(lst))
- goto error;
-
- /* if first char is a '-' then it is a negative integer */
- if (CAR(list_val(lst)) == make_small('-')) {
- neg = 1;
- skip = 1;
- lst = CDR(list_val(lst));
- if (is_not_list(lst)) {
- tail = lst;
- error_res = LTI_NO_INTEGER;
- goto error;
- }
- } else if (CAR(list_val(lst)) == make_small('+')) {
- /* ignore plus */
- skip = 1;
- lst = CDR(list_val(lst));
- if (is_not_list(lst)) {
- tail = lst;
- error_res = LTI_NO_INTEGER;
- goto error;
- }
- }
-
- /* Calculate size and do type check */
-
- while(1) {
- if (is_not_small(CAR(list_val(lst)))) {
- break;
- }
- if (unsigned_val(CAR(list_val(lst))) < '0' ||
- unsigned_val(CAR(list_val(lst))) > '9') {
- break;
- }
- ui = ui * 10;
- ui = ui + unsigned_val(CAR(list_val(lst))) - '0';
- n++;
- lst = CDR(list_val(lst));
- if (is_nil(lst)) {
- break;
- }
- if (is_not_list(lst)) {
- break;
- }
- }
-
- tail = lst;
- if (!n) {
- error_res = LTI_NO_INTEGER;
- goto error;
- }
-
-
- /* If n <= 8 then we know it's a small int
- ** since 2^27 = 134217728. If n > 8 then we must
- ** construct a bignum and let that routine do the checking
- */
-
- if (n <= SMALL_DIGITS) { /* It must be small */
- if (neg) i = -(Sint)ui;
- else i = (Sint)ui;
- res = make_small(i);
- } else {
- /* Convert from log10 to log2 by multiplying with 1/log10(2)=3.3219
- which we round up to (3 + 1/3) */
- lg2 = (n+1)*3 + (n+1)/3 + 1;
- m = (lg2+D_EXP-1)/D_EXP; /* number of digits */
- m = BIG_NEED_SIZE(m); /* number of words + thing */
-
- hp = HAlloc(p, m);
- hp_end = hp + m;
-
- lst = orig_list;
- if (skip)
- lst = CDR(list_val(lst));
-
- /* load first digits (at least one digit) */
- if ((i = (n % D_DECIMAL_EXP)) == 0)
- i = D_DECIMAL_EXP;
- n -= i;
- m = 0;
- while(i--) {
- m = 10*m + (unsigned_val(CAR(list_val(lst))) - '0');
- lst = CDR(list_val(lst));
- }
- res = small_to_big(m, hp); /* load first digits */
-
- while(n) {
- i = D_DECIMAL_EXP;
- n -= D_DECIMAL_EXP;
- m = 0;
- while(i--) {
- m = 10*m + (unsigned_val(CAR(list_val(lst))) - '0');
- lst = CDR(list_val(lst));
- }
- if (is_small(res))
- res = small_to_big(signed_val(res), hp);
- res = big_times_small(res, D_DECIMAL_BASE, hp);
- if (is_small(res))
- res = small_to_big(signed_val(res), hp);
- res = big_plus_small(res, m, hp);
- }
-
- if (neg) {
- if (is_small(res))
- res = make_small(-signed_val(res));
- else {
- Uint *big = big_val(res); /* point to thing */
- *big = bignum_header_neg(*big);
- }
- }
-
- if (is_not_small(res)) {
- res = big_plus_small(res, 0, hp); /* includes conversion to small */
+/*
+ * Converts a list of ascii base10 digits to an integer fully or partially.
+ * Returns result and the remaining tail.
+ * On error returns: {error,not_a_list}, or {error, no_integer}
+ */
- if (is_not_small(res)) {
- hp += (big_arity(res)+1);
- }
- }
- HRelease(p,hp_end,hp);
- }
- *integer = res;
- *rest = tail;
- if (tail != NIL) {
- return LTI_SOME_INTEGER;
- }
- return LTI_ALL_INTEGER;
-}
BIF_RETTYPE string_to_integer_1(BIF_ALIST_1)
{
Eterm res;
Eterm tail;
Eterm *hp;
/* must be a list */
- switch (do_list_to_integer(BIF_P,BIF_ARG_1,&res,&tail)) {
- /* HAlloc after do_list_to_integer as it
- might HAlloc itself (bignum) */
+ switch (erts_list_to_integer(BIF_P, BIF_ARG_1, 10, &res, &tail)) {
+ /* HAlloc after erts_list_to_integer as it might HAlloc itself (bignum) */
case LTI_BAD_STRUCTURE:
hp = HAlloc(BIF_P,3);
BIF_RET(TUPLE2(hp, am_error, am_not_a_list));
@@ -3072,13 +2945,14 @@ BIF_RETTYPE string_to_integer_1(BIF_ALIST_1)
BIF_RETTYPE list_to_integer_1(BIF_ALIST_1)
{
- /* Using do_list_to_integer is about twice as fast as using
+ /* Using erts_list_to_integer is about twice as fast as using
erts_chars_to_integer because we do not have to copy the
entire list */
Eterm res;
Eterm dummy;
/* must be a list */
- if (do_list_to_integer(BIF_P,BIF_ARG_1,&res,&dummy) != LTI_ALL_INTEGER) {
+ if (erts_list_to_integer(BIF_P, BIF_ARG_1, 10,
+ &res, &dummy) != LTI_ALL_INTEGER) {
BIF_ERROR(BIF_P,BADARG);
}
BIF_RET(res);
@@ -3086,14 +2960,12 @@ BIF_RETTYPE list_to_integer_1(BIF_ALIST_1)
BIF_RETTYPE list_to_integer_2(BIF_ALIST_2)
{
-
/* Bif implementation is about 50% faster than pure erlang,
and since we have erts_chars_to_integer now it is simpler
as well. This could be optmized further if we did not have to
copy the list to buf. */
- int i;
- Eterm res;
- char *buf = NULL;
+ Sint i;
+ Eterm res, dummy;
int base;
i = erts_list_length(BIF_ARG_1);
@@ -3101,31 +2973,16 @@ BIF_RETTYPE list_to_integer_2(BIF_ALIST_2)
BIF_ERROR(BIF_P, BADARG);
base = signed_val(BIF_ARG_2);
-
+
if (base < 2 || base > 36)
BIF_ERROR(BIF_P, BADARG);
- /* Take fast path if base it 10 */
- if (base == 10)
- return list_to_integer_1(BIF_P,&BIF_ARG_1);
-
- buf = (char *) erts_alloc(ERTS_ALC_T_TMP, i + 1);
-
- if (intlist_to_buf(BIF_ARG_1, buf, i) < 0)
- goto list_to_integer_1_error;
- buf[i] = '\0'; /* null terminal */
-
- if ((res = erts_chars_to_integer(BIF_P,buf,i,base)) == THE_NON_VALUE)
- goto list_to_integer_1_error;
-
- erts_free(ERTS_ALC_T_TMP, (void *) buf);
+ if (erts_list_to_integer(BIF_P, BIF_ARG_1, base,
+ &res, &dummy) != LTI_ALL_INTEGER) {
+ BIF_ERROR(BIF_P,BADARG);
+ }
BIF_RET(res);
-
- list_to_integer_1_error:
- erts_free(ERTS_ALC_T_TMP, (void *) buf);
- BIF_ERROR(BIF_P, BADARG);
-
- }
+}
/**********************************************************************/
@@ -3431,7 +3288,7 @@ static BIF_RETTYPE do_charbuf_to_float(Process *BIF_P,char *buf) {
BIF_RETTYPE list_to_float_1(BIF_ALIST_1)
{
- int i;
+ Sint i;
Eterm res;
char *buf = NULL;
@@ -3548,7 +3405,7 @@ BIF_RETTYPE list_to_tuple_1(BIF_ALIST_1)
Eterm* cons;
Eterm res;
Eterm* hp;
- int len;
+ Sint len;
if ((len = erts_list_length(list)) < 0 || len > ERTS_MAX_TUPLE_SIZE) {
BIF_ERROR(BIF_P, BADARG);
@@ -3824,11 +3681,9 @@ BIF_RETTYPE now_0(BIF_ALIST_0)
BIF_RETTYPE garbage_collect_0(BIF_ALIST_0)
{
- int reds;
-
FLAGS(BIF_P) |= F_NEED_FULLSWEEP;
- reds = erts_garbage_collect(BIF_P, 0, NULL, 0);
- BIF_RET2(am_true, reds);
+ erts_garbage_collect(BIF_P, 0, NULL, 0);
+ BIF_RET(am_true);
}
/**********************************************************************/
@@ -3897,7 +3752,7 @@ BIF_RETTYPE display_string_1(BIF_ALIST_1)
{
Process* p = BIF_P;
Eterm string = BIF_ARG_1;
- int len = is_string(string);
+ Sint len = is_string(string);
char *str;
if (len <= 0) {
@@ -3952,7 +3807,7 @@ BIF_RETTYPE halt_1(BIF_ALIST_1)
erts_exit(ERTS_ABORT_EXIT, "");
}
else if (is_string(BIF_ARG_1) || BIF_ARG_1 == NIL) {
- int i;
+ Sint i;
if ((i = intlist_to_buf(BIF_ARG_1, halt_msg, HALT_MSG_SIZE-1)) < 0) {
goto error;
@@ -4022,7 +3877,7 @@ BIF_RETTYPE halt_2(BIF_ALIST_2)
erts_exit(ERTS_ABORT_EXIT, "");
}
else if (is_string(BIF_ARG_1) || BIF_ARG_1 == NIL) {
- int i;
+ Sint i;
if ((i = intlist_to_buf(BIF_ARG_1, halt_msg, HALT_MSG_SIZE-1)) < 0) {
goto error;
@@ -4119,16 +3974,9 @@ BIF_RETTYPE make_fun_3(BIF_ALIST_3)
if (arity < 0) {
goto error;
}
-#if HALFWORD_HEAP
- hp = HAlloc(BIF_P, 3);
- hp[0] = HEADER_EXPORT;
- /* Yes, May be misaligned, but X86_64 will fix it... */
- *((Export **) (hp+1)) = erts_export_get_or_make_stub(BIF_ARG_1, BIF_ARG_2, (Uint) arity);
-#else
hp = HAlloc(BIF_P, 2);
hp[0] = HEADER_EXPORT;
hp[1] = (Eterm) erts_export_get_or_make_stub(BIF_ARG_1, BIF_ARG_2, (Uint) arity);
-#endif
BIF_RET(make_export(hp));
}
@@ -4172,7 +4020,7 @@ BIF_RETTYPE list_to_pid_1(BIF_ALIST_1)
{
Uint a = 0, b = 0, c = 0;
char* cp;
- int i;
+ Sint i;
DistEntry *dep = NULL;
char *buf = (char *) erts_alloc(ERTS_ALC_T_TMP, 65);
/*
@@ -4349,22 +4197,33 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
Sint n;
if (BIF_ARG_1 == am_multi_scheduling) {
- if (BIF_ARG_2 == am_block || BIF_ARG_2 == am_unblock) {
+ if (BIF_ARG_2 == am_block || BIF_ARG_2 == am_unblock
+ || BIF_ARG_2 == am_block_normal || BIF_ARG_2 == am_unblock_normal) {
#ifndef ERTS_SMP
BIF_RET(am_disabled);
#else
+ int block = (BIF_ARG_2 == am_block
+ || BIF_ARG_2 == am_block_normal);
+ int normal = (BIF_ARG_2 == am_block_normal
+ || BIF_ARG_2 == am_unblock_normal);
if (erts_no_schedulers == 1)
BIF_RET(am_disabled);
else {
switch (erts_block_multi_scheduling(BIF_P,
ERTS_PROC_LOCK_MAIN,
- BIF_ARG_2 == am_block,
+ block,
+ normal,
0)) {
case ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED:
BIF_RET(am_blocked);
+ case ERTS_SCHDLR_SSPND_DONE_NMSCHED_BLOCKED:
+ BIF_RET(am_blocked_normal);
case ERTS_SCHDLR_SSPND_YIELD_DONE_MSCHED_BLOCKED:
ERTS_BIF_YIELD_RETURN_X(BIF_P, am_blocked,
am_multi_scheduling);
+ case ERTS_SCHDLR_SSPND_YIELD_DONE_NMSCHED_BLOCKED:
+ ERTS_BIF_YIELD_RETURN_X(BIF_P, am_blocked_normal,
+ am_multi_scheduling);
case ERTS_SCHDLR_SSPND_DONE:
BIF_RET(am_enabled);
case ERTS_SCHDLR_SSPND_YIELD_RESTART:
@@ -4397,11 +4256,7 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
switch (erts_set_schedulers_online(BIF_P,
ERTS_PROC_LOCK_MAIN,
signed_val(BIF_ARG_2),
- &old_no
-#ifdef ERTS_DIRTY_SCHEDULERS
- , 0
-#endif
- )) {
+ &old_no, 0)) {
case ERTS_SCHDLR_SSPND_DONE:
BIF_RET(make_small(old_no));
case ERTS_SCHDLR_SSPND_YIELD_RESTART:
@@ -4489,7 +4344,7 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
}
} else if (BIF_ARG_1 == make_small(1)) {
int i, max;
- ErlMessage* mp;
+ ErtsMessage* mp;
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_smp_thr_progress_block();
@@ -4582,6 +4437,31 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
default:
ERTS_INTERNAL_ERROR("Unknown state");
}
+#ifdef ERTS_ENABLE_MSACC
+ } else if (BIF_ARG_1 == am_microstate_accounting) {
+ Eterm threads;
+ if (BIF_ARG_2 == am_true || BIF_ARG_2 == am_false) {
+ erts_aint32_t new = BIF_ARG_2 == am_true ? ERTS_MSACC_ENABLE : ERTS_MSACC_DISABLE;
+ erts_aint32_t old = erts_smp_atomic32_xchg_nob(&msacc, new);
+ Eterm ref = erts_msacc_request(BIF_P, new, &threads);
+ if (is_non_value(ref))
+ BIF_RET(old ? am_true : am_false);
+ BIF_TRAP3(await_msacc_mod_trap,
+ BIF_P,
+ ref,
+ old ? am_true : am_false,
+ threads);
+ } else if (BIF_ARG_2 == am_reset) {
+ Eterm ref = erts_msacc_request(BIF_P, ERTS_MSACC_RESET, &threads);
+ erts_aint32_t old = erts_smp_atomic32_read_nob(&msacc);
+ ASSERT(is_value(ref));
+ BIF_TRAP3(await_msacc_mod_trap,
+ BIF_P,
+ ref,
+ old ? am_true : am_false,
+ threads);
+ }
+#endif
} else if (ERTS_IS_ATOM_STR("scheduling_statistics", BIF_ARG_1)) {
int what;
if (ERTS_IS_ATOM_STR("disable", BIF_ARG_2))
@@ -4634,7 +4514,7 @@ BIF_RETTYPE hash_2(BIF_ALIST_2)
if ((range = signed_val(BIF_ARG_2)) <= 0) { /* [1..MAX_SMALL] */
BIF_ERROR(BIF_P, BADARG);
}
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
if (range > ((1L << 27) - 1))
BIF_ERROR(BIF_P, BADARG);
#endif
@@ -4706,7 +4586,7 @@ BIF_RETTYPE phash2_2(BIF_ALIST_2)
/*
* Return either a small or a big. Use the heap for bigs if there is room.
*/
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
BIF_RET(make_small(final_hash));
#else
if (IS_USMALL(0, final_hash)) {
@@ -4746,29 +4626,27 @@ BIF_RETTYPE erts_internal_cmp_term_2(BIF_ALIST_2) {
/*
* Processes doing yield on return in a bif ends up in bif_return_trap().
*/
-static BIF_RETTYPE bif_return_trap(
-#ifdef DEBUG
- BIF_ALIST_2
-#else
- BIF_ALIST_1
-#endif
- )
+static BIF_RETTYPE bif_return_trap(BIF_ALIST_2)
{
-#ifdef DEBUG
+ Eterm res = BIF_ARG_1;
+
switch (BIF_ARG_2) {
- case am_multi_scheduling:
#ifdef ERTS_SMP
- erts_dbg_multi_scheduling_return_trap(BIF_P, BIF_ARG_1);
-#endif
- break;
- case am_schedulers_online:
+ case am_multi_scheduling: {
+ int msb = erts_is_multi_scheduling_blocked();
+ if (msb > 0)
+ res = am_blocked;
+ else if (msb < 0)
+ res = am_blocked_normal;
+ else
+ ERTS_INTERNAL_ERROR("Unexpected multi scheduling block state");
break;
+ }
+#endif
default:
break;
}
-#endif
-
- BIF_RET(BIF_ARG_1);
+ BIF_RET(res);
}
/*
@@ -4873,17 +4751,12 @@ void erts_init_bif(void)
erts_smp_atomic_init_nob(&erts_dead_ports_ptr, (erts_aint_t) NULL);
/*
- * bif_return_trap/1 is a hidden BIF that bifs that need to
- * yield the calling process traps to. The only thing it does:
- * return the value passed as argument.
+ * bif_return_trap/2 is a hidden BIF that bifs that need to
+ * yield the calling process traps to.
*/
- erts_init_trap_export(&bif_return_trap_export, am_erlang, am_bif_return_trap,
-#ifdef DEBUG
- 2
-#else
- 1
-#endif
- , &bif_return_trap);
+ erts_init_trap_export(&bif_return_trap_export,
+ am_erlang, am_bif_return_trap, 2,
+ &bif_return_trap);
erts_await_result = erts_export_put(am_erts_internal,
am_await_result,
@@ -4911,8 +4784,12 @@ void erts_init_bif(void)
await_port_send_result_trap
= erts_export_put(am_erts_internal, am_await_port_send_result, 3);
await_sched_wall_time_mod_trap
- = erts_export_put(am_erlang, am_await_sched_wall_time_modifications, 2);
+ = erts_export_put(am_erlang, am_await_sched_wall_time_modifications, 2);
+ await_msacc_mod_trap
+ = erts_export_put(am_erts_internal, am_await_microstate_accounting_modifications, 3);
+
erts_smp_atomic32_init_nob(&sched_wall_time, 0);
+ erts_smp_atomic32_init_nob(&msacc, ERTS_MSACC_IS_ENABLED());
}
#ifdef HARDDEBUG
diff --git a/erts/emulator/beam/bif.h b/erts/emulator/beam/bif.h
index c6ed60376a..46af552b39 100644
--- a/erts/emulator/beam/bif.h
+++ b/erts/emulator/beam/bif.h
@@ -54,22 +54,24 @@ extern Export *erts_convert_time_unit_trap;
(p)->fcalls = -CONTEXT_REDS; \
} while(0)
-
-#define ERTS_VBUMP_ALL_REDS(p) \
+#define ERTS_VBUMP_ALL_REDS_INTERNAL(p, fcalls) \
do { \
if (!ERTS_PROC_GET_SAVED_CALLS_BUF((p))) { \
- if ((p)->fcalls > 0) \
- ERTS_PROC_GET_SCHDATA((p))->virtual_reds += (p)->fcalls; \
- (p)->fcalls = 0; \
+ if ((fcalls) > 0) \
+ ERTS_PROC_GET_SCHDATA((p))->virtual_reds += (fcalls); \
+ (fcalls) = 0; \
} \
else { \
- if ((p)->fcalls > -CONTEXT_REDS) \
+ if ((fcalls) > -CONTEXT_REDS) \
ERTS_PROC_GET_SCHDATA((p))->virtual_reds \
- += ((p)->fcalls - (-CONTEXT_REDS)); \
- (p)->fcalls = -CONTEXT_REDS; \
+ += ((fcalls) - (-CONTEXT_REDS)); \
+ (fcalls) = -CONTEXT_REDS; \
} \
} while(0)
+#define ERTS_VBUMP_ALL_REDS(p) \
+ ERTS_VBUMP_ALL_REDS_INTERNAL((p), (p)->fcalls)
+
#define BUMP_REDS(p, gc) do { \
ASSERT(p); \
ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(p));\
@@ -110,10 +112,34 @@ do { \
} \
} while(0)
-#define ERTS_BIF_REDS_LEFT(p) \
+#define ERTS_VBUMP_LEAVE_REDS_INTERNAL(P, Reds, FCalls) \
+ do { \
+ if (ERTS_PROC_GET_SAVED_CALLS_BUF((P))) { \
+ int nreds__ = ((int)(Reds)) - CONTEXT_REDS; \
+ if ((FCalls) > nreds__) { \
+ ERTS_PROC_GET_SCHDATA((P))->virtual_reds \
+ += (FCalls) - nreds__; \
+ (FCalls) = nreds__; \
+ } \
+ } \
+ else { \
+ if ((FCalls) > (Reds)) { \
+ ERTS_PROC_GET_SCHDATA((P))->virtual_reds \
+ += (FCalls) - (Reds); \
+ (FCalls) = (Reds); \
+ } \
+ } \
+ } while (0)
+
+#define ERTS_VBUMP_LEAVE_REDS(P, Reds) \
+ ERTS_VBUMP_LEAVE_REDS_INTERNAL(P, Reds, (P)->fcalls)
+
+#define ERTS_REDS_LEFT(p, FCalls) \
(ERTS_PROC_GET_SAVED_CALLS_BUF((p)) \
- ? ((p)->fcalls > -CONTEXT_REDS ? ((p)->fcalls - (-CONTEXT_REDS)) : 0)\
- : ((p)->fcalls > 0 ? (p)->fcalls : 0))
+ ? ((FCalls) > -CONTEXT_REDS ? ((FCalls) - (-CONTEXT_REDS)) : 0) \
+ : ((FCalls) > 0 ? (FCalls) : 0))
+
+#define ERTS_BIF_REDS_LEFT(p) ERTS_REDS_LEFT(p, p->fcalls)
#define BIF_RET2(x, gc) do { \
BUMP_REDS(BIF_P, (gc)); \
@@ -312,37 +338,20 @@ do { \
} while(0)
extern Export bif_return_trap_export;
-#ifdef DEBUG
-#define ERTS_BIF_PREP_YIELD_RETURN_X(RET, P, VAL, DEBUG_VAL) \
-do { \
- ERTS_VBUMP_ALL_REDS(P); \
- ERTS_BIF_PREP_TRAP2(RET, &bif_return_trap_export, (P), (VAL), \
- (DEBUG_VAL)); \
-} while (0)
-#else
-#define ERTS_BIF_PREP_YIELD_RETURN_X(RET, P, VAL, DEBUG_VAL) \
+#define ERTS_BIF_PREP_YIELD_RETURN_X(RET, P, VAL, OP) \
do { \
ERTS_VBUMP_ALL_REDS(P); \
- ERTS_BIF_PREP_TRAP1(RET, &bif_return_trap_export, (P), (VAL)); \
+ ERTS_BIF_PREP_TRAP2(RET, &bif_return_trap_export, (P), (VAL), (OP));\
} while (0)
-#endif
#define ERTS_BIF_PREP_YIELD_RETURN(RET, P, VAL) \
ERTS_BIF_PREP_YIELD_RETURN_X(RET, (P), (VAL), am_undefined)
-#ifdef DEBUG
-#define ERTS_BIF_YIELD_RETURN_X(P, VAL, DEBUG_VAL) \
+#define ERTS_BIF_YIELD_RETURN_X(P, VAL, OP) \
do { \
ERTS_VBUMP_ALL_REDS(P); \
- BIF_TRAP2(&bif_return_trap_export, (P), (VAL), (DEBUG_VAL)); \
+ BIF_TRAP2(&bif_return_trap_export, (P), (VAL), (OP)); \
} while (0)
-#else
-#define ERTS_BIF_YIELD_RETURN_X(P, VAL, DEBUG_VAL) \
-do { \
- ERTS_VBUMP_ALL_REDS(P); \
- BIF_TRAP1(&bif_return_trap_export, (P), (VAL)); \
-} while (0)
-#endif
#define ERTS_BIF_RETURN_YIELD(P) ERTS_VBUMP_ALL_REDS((P))
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 3177d5dae7..a6670c10e8 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -115,7 +115,7 @@ bif erlang:time_offset/0
bif erlang:time_offset/1
bif erlang:timestamp/0
-bif erlang:open_port/2
+bif erts_internal:open_port/2
bif erlang:pid_to_list/1
bif erlang:ports/0
@@ -125,7 +125,6 @@ bif erlang:process_flag/3
bif erlang:process_info/1
bif erlang:process_info/2
bif erlang:processes/0
-bif erlang:purge_module/1
bif erlang:put/2
bif erlang:register/2
bif erlang:registered/0
@@ -167,10 +166,11 @@ bif erts_internal:request_system_task/3
bif erts_internal:check_process_code/2
bif erts_internal:map_to_tuple_keys/1
-bif erts_internal:map_type/1
+bif erts_internal:term_type/1
bif erts_internal:map_hashmap_children/1
bif erts_internal:time_unit/0
+bif erts_internal:perf_counter_unit/0
bif erts_internal:is_system_process/1
@@ -372,6 +372,7 @@ bif os:getpid/0
bif os:timestamp/0
bif os:system_time/0
bif os:system_time/1
+bif os:perf_counter/0
#
# Bifs in the erl_ddll module (the module actually does not exist)
@@ -641,6 +642,18 @@ bif ets:update_counter/4
bif erts_debug:map_info/1
#
+# New in 19.0
+#
+
+bif erts_internal:copy_literals/2
+bif erts_internal:purge_module/1
+bif binary:split/2
+bif binary:split/3
+bif erts_debug:size_shared/1
+bif erts_debug:copy_shared/1
+bif erlang:has_prepared_code_on_load/1
+
+#
# Obsolete
#
diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c
index 87d3be2b0f..c738a9ecf5 100644
--- a/erts/emulator/beam/big.c
+++ b/erts/emulator/beam/big.c
@@ -48,7 +48,7 @@
_t_dst = (dst)+((sz)-1); \
_t_src = (src)+((sz)-1); \
while(_t_sz--) *_t_dst-- = *_t_src--; \
- } \
+ } \
} while(0)
/* add a and b with carry in + out */
@@ -423,6 +423,25 @@
#endif
+/* Forward declaration of lookup tables (See below in this file) used in list to
+ * integer conversions for different bases. Also used in bignum printing.
+ */
+static const byte digits_per_sint_lookup[36-1];
+static const byte digits_per_small_lookup[36-1];
+static const Sint largest_power_of_base_lookup[36-1];
+
+static ERTS_INLINE byte get_digits_per_signed_int(Uint base) {
+ return digits_per_sint_lookup[base-2];
+}
+
+static ERTS_INLINE byte get_digits_per_small(Uint base) {
+ return digits_per_small_lookup[base-2];
+}
+
+static ERTS_INLINE Sint get_largest_power_of_base(Uint base) {
+ return largest_power_of_base_lookup[base-2];
+}
+
/*
** compare two number vectors
*/
@@ -1487,20 +1506,8 @@ Eterm uint_to_big(Uint x, Eterm *y)
Eterm uword_to_big(UWord x, Eterm *y)
{
-#if HALFWORD_HEAP
- Uint upper = x >> 32;
- Uint lower = x & 0xFFFFFFFFUL;
- if (upper == 0) {
- *y = make_pos_bignum_header(1);
- } else {
- *y = make_pos_bignum_header(2);
- BIG_DIGIT(y, 1) = upper;
- }
- BIG_DIGIT(y, 0) = lower;
-#else
*y = make_pos_bignum_header(1);
BIG_DIGIT(y, 0) = x;
-#endif
return make_big(y);
}
@@ -1525,7 +1532,7 @@ Eterm small_to_big(Sint x, Eterm *y)
Eterm erts_uint64_to_big(Uint64 x, Eterm **hpp)
{
Eterm *hp = *hpp;
-#if defined(ARCH_32) || HALFWORD_HEAP
+#if defined(ARCH_32)
if (x >= (((Uint64) 1) << 32)) {
*hp = make_pos_bignum_header(2);
BIG_DIGIT(hp, 0) = (Uint) (x & ((Uint) 0xffffffff));
@@ -1555,7 +1562,7 @@ Eterm erts_sint64_to_big(Sint64 x, Eterm **hpp)
neg = 1;
ux = -(Uint64)x;
}
-#if defined(ARCH_32) || HALFWORD_HEAP
+#if defined(ARCH_32)
if (ux >= (((Uint64) 1) << 32)) {
if (neg)
*hp = make_neg_bignum_header(2);
@@ -1588,7 +1595,7 @@ erts_uint64_array_to_big(Uint **hpp, int neg, int len, Uint64 *array)
pot_digits = digits = 0;
for (i = 0; i < len; i++) {
-#if defined(ARCH_32) || HALFWORD_HEAP
+#if defined(ARCH_32)
Uint low_val = array[i] & ((Uint) 0xffffffff);
Uint high_val = (array[i] >> 32) & ((Uint) 0xffffffff);
BIG_DIGIT(headerp, pot_digits) = low_val;
@@ -1651,8 +1658,6 @@ big_to_double(Wterm x, double* resp)
/*
* Logic has been copied from erl_bif_guard.c and slightly
* modified to use a static instead of dynamic heap
- *
- * HALFWORD: Return relative term with 'heap' as base.
*/
Eterm
double_to_big(double x, Eterm *heap, Uint hsz)
@@ -1683,7 +1688,7 @@ double_to_big(double x, Eterm *heap, Uint hsz)
sz = BIG_NEED_SIZE(ds); /* number of words including arity */
hp = heap;
- res = make_big_rel(hp, heap);
+ res = make_big(hp);
xp = (ErtsDigit*) (hp + 1);
ASSERT(ds < hsz);
@@ -1733,8 +1738,10 @@ static Uint write_big(Wterm x, void (*write_func)(void *, char), void *arg)
short sign = BIG_SIGN(xp);
ErtsDigit rem;
Uint n = 0;
+ const Uint digits_per_Sint = get_digits_per_signed_int(10);
+ const Sint largest_pow_of_base = get_largest_power_of_base(10);
- if (xl == 1 && *dx < D_DECIMAL_BASE) {
+ if (xl == 1 && *dx < largest_pow_of_base) {
rem = *dx;
if (rem == 0) {
(*write_func)(arg, '0'); n++;
@@ -1752,7 +1759,7 @@ static Uint write_big(Wterm x, void (*write_func)(void *, char), void *arg)
MOVE_DIGITS(tmp, dx, xl);
while(1) {
- tmpl = D_div(tmp, tmpl, D_DECIMAL_BASE, tmp, &rem);
+ tmpl = D_div(tmp, tmpl, largest_pow_of_base, tmp, &rem);
if (tmpl == 1 && *tmp == 0) {
while(rem) {
(*write_func)(arg, (rem % 10)+'0'); n++;
@@ -1760,7 +1767,7 @@ static Uint write_big(Wterm x, void (*write_func)(void *, char), void *arg)
}
break;
} else {
- int i = D_DECIMAL_EXP;
+ Uint i = digits_per_Sint;
while(i--) {
(*write_func)(arg, (rem % 10)+'0'); n++;
rem /= 10;
@@ -2562,63 +2569,100 @@ int term_equals_2pow32(Eterm x)
}
}
+static ERTS_INLINE int c2int_is_invalid_char(byte ch, int base) {
+ return (ch < '0'
+ || (ch > ('0' + base - 1)
+ && !(base > 10
+ && ((ch >= 'a' && ch < ('a' + base - 10))
+ || (ch >= 'A' && ch < ('A' + base - 10))))));
+}
-#define IS_VALID_CHARACTER(CHAR,BASE) \
- (CHAR < '0' \
- || (CHAR > ('0' + BASE - 1) \
- && !(BASE > 10 \
- && ((CHAR >= 'a' && CHAR < ('a' + BASE - 10)) \
- || (CHAR >= 'A' && CHAR < ('A' + BASE - 10))))))
-#define CHARACTER_FROM_BASE(CHAR) \
- ((CHAR <= '9') ? CHAR - '0' : 10 + ((CHAR <= 'Z') ? CHAR - 'A' : CHAR - 'a'))
-#define D_BASE_EXP(BASE) (d_base_exp_lookup[BASE-2])
-#define D_BASE_BASE(BASE) (d_base_base_lookup[BASE-2])
-#define LG2_LOOKUP(BASE) (lg2_lookup[base-2])
+static ERTS_INLINE byte c2int_digit_from_base(byte ch) {
+ return ch <= '9' ? ch - '0'
+ : (10 + (ch <= 'Z' ? ch - 'A' : ch - 'a'));
+}
/*
- * for i in 2..64 do
- * lg2_lookup[i-2] = log2(i)
- * end
- * How many bits are needed to store string of size n
+ * How many bits are needed to store 1 digit of given base in binary
+ * Wo.Alpha formula: Table [log2[n], {n,2,36}]
*/
-const double lg2_lookup[] = { 1.0, 1.58496, 2, 2.32193, 2.58496, 2.80735, 3.0,
- 3.16993, 3.32193, 3.45943, 3.58496, 3.70044, 3.80735, 3.90689, 4.0,
- 4.08746, 4.16993, 4.24793, 4.32193, 4.39232, 4.45943, 4.52356, 4.58496,
- 4.64386, 4.70044, 4.75489, 4.80735, 4.85798, 4.90689, 4.9542, 5.0,
- 5.04439, 5.08746, 5.12928, 5.16993, 5.20945, 5.24793, 5.2854, 5.32193,
- 5.35755, 5.39232, 5.42626, 5.45943, 5.49185, 5.52356, 5.55459, 5.58496,
- 5.61471, 5.64386, 5.67243, 5.70044, 5.72792, 5.75489, 5.78136, 5.80735,
- 5.83289, 5.85798, 5.88264, 5.90689, 5.93074, 5.9542, 5.97728, 6.0 };
+static const double lg2_lookup[36-1] = {
+ 1.0, 1.58496, 2.0, 2.32193, 2.58496, 2.80735, 3.0, 3.16993, 3.32193,
+ 3.45943, 3.58496, 3.70044, 3.80735, 3.90689, 4.0, 4.08746, 4.16993, 4.24793,
+ 4.32193, 4.39232, 4.45943, 4.52356, 4.58496, 4.64386, 4.70044, 4.75489,
+ 4.80735, 4.85798, 4.90689, 4.9542, 5.0, 5.04439, 5.08746, 5.12928, 5.16993
+};
+static ERTS_INLINE double lookup_log2(Uint base) {
+ return lg2_lookup[base - 2];
+}
/*
- * for i in 2..64 do
- * d_base_exp_lookup[i-2] = 31 / lg2_lookup[i-2];
- * end
- * How many characters can fit in 31 bits
+ * How many digits can fit into a signed int (Sint) for given base, we take
+ * one digit away just to be on the safer side (some corner cases).
*/
-const byte d_base_exp_lookup[] = { 31, 19, 15, 13, 11, 11, 10, 9, 9, 8, 8, 8, 8,
- 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5 };
+static const byte digits_per_sint_lookup[36-1] = {
+#if (SIZEOF_VOID_P == 4)
+ /* Wo.Alpha formula: Table [Trunc[31 / log[2,n]]-1, {n, 2, 36}] */
+ 30, 18, 14, 12, 10, 10, 9, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4
+#elif (SIZEOF_VOID_P == 8)
+ /* Wo.Alpha formula: Table [Trunc[63 / log[2,n]]-1, {n, 2, 36}] */
+ 62, 38, 30, 26, 23, 21, 20, 18, 17, 17, 16, 16, 15, 15, 14, 14, 14, 13, 13,
+ 13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11
+#else
+ #error "Please produce a lookup table for the new architecture"
+#endif
+};
+
+/*
+ * How many digits can fit into Erlang Small (SMALL_BITS-1) counting sign bit
+ */
+static const byte digits_per_small_lookup[36-1] = {
+#if (SIZEOF_VOID_P == 4)
+ /* Wo.Alpha formula: Table [Trunc[27 / log[2,n]]-1, {n, 2, 36}] */
+ 27, 17, 13, 11, 10, 9, 9, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+#elif (SIZEOF_VOID_P == 8)
+ /* Wo.Alpha formula: Table [Trunc[59 / log[2,n]]-1, {n, 2, 36}] */
+ 59, 37, 29, 25, 22, 21, 19, 18, 17, 17, 16, 15, 15, 15, 14, 14, 14, 13, 13,
+ 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11
+#else
+ #error "Please produce a lookup table for the new architecture"
+#endif
+};
/*
- * for i in 2..64 do
- * d_base_base_lookup[i-2] = pow(i,d_base_exp_lookup[i-2]);
- * end
- * How much can the characters which fit in 31 bit represent
+ * Largest power of base which can be represented in a signed int (Sint).
+ * Calculated by base 2..36 to the power of corresponding element from
+ * digits_per_sint_lookup.
*/
-const Uint d_base_base_lookup[] = { 2147483648u, 1162261467u, 1073741824u,
- 1220703125u, 362797056u, 1977326743u, 1073741824u, 387420489u,
- 1000000000u, 214358881u, 429981696u, 815730721u, 1475789056u,
- 170859375u, 268435456u, 410338673u, 612220032u, 893871739u, 1280000000u,
- 1801088541u, 113379904u, 148035889u, 191102976u, 244140625u, 308915776u,
- 387420489u, 481890304u, 594823321u, 729000000u, 887503681u, 1073741824u,
- 1291467969u, 1544804416u, 1838265625u, 60466176u, 69343957u, 79235168u,
- 90224199u, 102400000u, 115856201u, 130691232u, 147008443u, 164916224u,
- 184528125u, 205962976u, 229345007u, 254803968u, 282475249u, 312500000u,
- 345025251u, 380204032u, 418195493u, 459165024u, 503284375u, 550731776u,
- 601692057u, 656356768u, 714924299u, 777600000u, 844596301u, 916132832u,
- 992436543u, 1073741824u };
+static const Sint largest_power_of_base_lookup[36-1] = {
+#if (SIZEOF_VOID_P == 4)
+ /* Wo.Alpha formula: Table [Pow[n, Trunc[31 / log[2,n]]-1], {n, 2, 36}] */
+ 1073741824, 387420489, 268435456, 244140625, 60466176, 282475249, 134217728,
+ 43046721, 100000000, 19487171, 35831808, 62748517, 105413504, 11390625,
+ 16777216, 24137569, 34012224, 47045881, 64000000, 85766121, 5153632,
+ 6436343,7962624, 9765625, 11881376, 14348907, 17210368, 20511149, 24300000,
+ 28629151, 33554432, 39135393, 45435424, 52521875, 1679616
+#elif (SIZEOF_VOID_P == 8)
+ /* Wo.Alpha formula: Table [Pow[n, Trunc[63 / log[2,n]]-1], {n, 2, 36}]
+ * with LL added after each element manually */
+ 4611686018427387904LL, 1350851717672992089LL, 1152921504606846976LL,
+ 1490116119384765625LL, 789730223053602816LL, 558545864083284007LL,
+ 1152921504606846976LL, 150094635296999121LL, 100000000000000000LL,
+ 505447028499293771LL, 184884258895036416LL, 665416609183179841LL,
+ 155568095557812224LL, 437893890380859375LL, 72057594037927936LL,
+ 168377826559400929LL, 374813367582081024LL, 42052983462257059LL,
+ 81920000000000000LL, 154472377739119461LL, 282810057883082752LL,
+ 21914624432020321LL, 36520347436056576LL, 59604644775390625LL,
+ 95428956661682176LL, 150094635296999121LL, 232218265089212416LL,
+ 12200509765705829LL, 17714700000000000LL, 25408476896404831LL,
+ 36028797018963968LL, 50542106513726817LL, 70188843638032384LL,
+ 96549157373046875LL, 131621703842267136LL
+#else
+ #error "Please produce a lookup table for the new architecture"
+#endif
+};
Eterm erts_chars_to_integer(Process *BIF_P, char *bytes,
Uint size, const int base) {
@@ -2628,8 +2672,11 @@ Eterm erts_chars_to_integer(Process *BIF_P, char *bytes,
int neg = 0;
byte b;
Eterm *hp, *hp_end;
- int m;
+ Sint m;
int lg2;
+ const Uint digits_per_small = get_digits_per_small(base);
+ const Uint digits_per_Sint = get_digits_per_signed_int(base);
+ const Sint largest_pow_of_base = get_largest_power_of_base(base);
if (size == 0)
goto bytebuf_to_integer_1_error;
@@ -2644,57 +2691,68 @@ Eterm erts_chars_to_integer(Process *BIF_P, char *bytes,
size--;
}
+ /* Trim leading zeroes */
+ if (size) {
+ while (*bytes == '0') {
+ bytes++;
+ size--;
+ if (!size) {
+ /* All zero! */
+ res = make_small(0);
+ goto bytebuf_to_integer_1_done;
+ }
+ }
+ }
+
if (size == 0)
goto bytebuf_to_integer_1_error;
- if (size < SMALL_DIGITS && base <= 10) {
- /* *
- * Take shortcut if we know that all chars are '0' < b < '9' and
- * fit in a small. This improves speed by about 10% over the generic
- * small case.
- * */
- while (size--) {
- b = *bytes++;
+ if (size < digits_per_small) {
+ if (base <= 10) {
+ /* *
+ * Take shortcut if we know that all chars are '0' < b < '9' and
+ * fit in a small. This improves speed by about 10% over the generic
+ * small case.
+ * */
+ while (size--) {
+ b = *bytes++;
- if (b < '0' || b > ('0'+base-1))
- goto bytebuf_to_integer_1_error;
+ if (b < '0' || b > ('0'+base-1))
+ goto bytebuf_to_integer_1_error;
- i = i * base + b - '0';
- }
+ i = i * base + b - '0';
+ }
- if (neg)
- i = -i;
- res = make_small(i);
- goto bytebuf_to_integer_1_done;
+ if (neg)
+ i = -i;
+ res = make_small(i);
+ goto bytebuf_to_integer_1_done;
+ }
+
+ /* Take shortcut if we know it will fit in a small.
+ * This improves speed by about 30%.
+ */
+ while (size) {
+ b = *bytes++;
+ size--;
+
+ if (c2int_is_invalid_char(b, base))
+ goto bytebuf_to_integer_1_error;
+
+ i = i * base + c2int_digit_from_base(b);
+ }
+
+ if (neg)
+ i = -i;
+ res = make_small(i);
+ goto bytebuf_to_integer_1_done;
}
/*
* Calculate the maximum number of bits which will
* be needed to represent the binary
*/
- lg2 = ((size+2)*LG2_LOOKUP(base)+1);
-
- if (lg2 < SMALL_BITS) {
- /* Take shortcut if we know it will fit in a small.
- * This improves speed by about 30%.
- */
- while (size) {
- b = *bytes++;
- size--;
-
- if (IS_VALID_CHARACTER(b,base))
- goto bytebuf_to_integer_1_error;
-
- i = i * base + CHARACTER_FROM_BASE(b);
-
- }
-
- if (neg)
- i = -i;
- res = make_small(i);
- goto bytebuf_to_integer_1_done;
-
- }
+ lg2 = ((size+2)*lookup_log2(base)+1);
/* Start calculating bignum */
m = (lg2 + D_EXP-1)/D_EXP;
@@ -2703,8 +2761,8 @@ Eterm erts_chars_to_integer(Process *BIF_P, char *bytes,
hp = HAlloc(BIF_P, m);
hp_end = hp + m;
- if ((i = (size % D_BASE_EXP(base))) == 0)
- i = D_BASE_EXP(base);
+ if ((i = (size % digits_per_Sint)) == 0)
+ i = digits_per_Sint;
n = size - i;
m = 0;
@@ -2712,34 +2770,34 @@ Eterm erts_chars_to_integer(Process *BIF_P, char *bytes,
while (i--) {
b = *bytes++;
- if (IS_VALID_CHARACTER(b,base)) {
+ if (c2int_is_invalid_char(b,base)) {
HRelease(BIF_P, hp_end, hp);
goto bytebuf_to_integer_1_error;
}
- m = base * m + CHARACTER_FROM_BASE(b);
+ m = base * m + c2int_digit_from_base(b);
}
res = small_to_big(m, hp);
while (n) {
- i = D_BASE_EXP(base);
- n -= D_BASE_EXP(base);
+ i = digits_per_Sint;
+ n -= digits_per_Sint;
m = 0;
while (i--) {
b = *bytes++;
- if (IS_VALID_CHARACTER(b,base)) {
+ if (c2int_is_invalid_char(b,base)) {
HRelease(BIF_P, hp_end, hp);
goto bytebuf_to_integer_1_error;
}
- m = base * m + CHARACTER_FROM_BASE(b);
+ m = base * m + c2int_digit_from_base(b);
}
if (is_small(res)) {
res = small_to_big(signed_val(res), hp);
}
- res = big_times_small(res, D_BASE_BASE(base), hp);
+ res = big_times_small(res, largest_pow_of_base, hp);
if (is_small(res)) {
res = small_to_big(signed_val(res), hp);
}
@@ -2770,5 +2828,166 @@ bytebuf_to_integer_1_error:
bytebuf_to_integer_1_done:
return res;
+}
+/* Converts list of digits with given 'base' to integer sequentially. Returns
+ * result in 'integer_out', remaining tail goes to 'tail_out' and returns result
+ * code if the list was consumed fully or partially or there was an error
+ */
+LTI_result_t erts_list_to_integer(Process *BIF_P, Eterm orig_list,
+ const Uint base,
+ Eterm *integer_out, Eterm *tail_out)
+{
+ Sint i = 0;
+ Uint ui = 0;
+ int skip = 0;
+ int neg = 0;
+ Sint n = 0;
+ Sint m;
+ int lg2;
+ Eterm res;
+ Eterm lst = orig_list;
+ Eterm tail = lst;
+ int error_res = LTI_BAD_STRUCTURE;
+ const Uint digits_per_small = get_digits_per_small(base);
+ const Uint digits_per_Sint = get_digits_per_signed_int(base);
+
+ if (is_nil(lst)) {
+ error_res = LTI_NO_INTEGER;
+ error:
+ *tail_out = tail;
+ *integer_out = make_small(0);
+ return error_res;
+ }
+ if (is_not_list(lst))
+ goto error;
+
+ /* if first char is a '-' then it is a negative integer */
+ if (CAR(list_val(lst)) == make_small('-')) {
+ neg = 1;
+ skip = 1;
+ lst = CDR(list_val(lst));
+ if (is_not_list(lst)) {
+ tail = lst;
+ error_res = LTI_NO_INTEGER;
+ goto error;
+ }
+ } else if (CAR(list_val(lst)) == make_small('+')) {
+ /* ignore plus */
+ skip = 1;
+ lst = CDR(list_val(lst));
+ if (is_not_list(lst)) {
+ tail = lst;
+ error_res = LTI_NO_INTEGER;
+ goto error;
+ }
+ }
+
+ /* Calculate size and do type check */
+
+ while(1) {
+ byte ch;
+ if (is_not_small(CAR(list_val(lst)))) {
+ break;
+ }
+ ch = unsigned_val(CAR(list_val(lst)));
+ if (c2int_is_invalid_char(ch, base)) {
+ break;
+ }
+ ui = ui * base;
+ ui = ui + c2int_digit_from_base(ch);
+ n++;
+ lst = CDR(list_val(lst));
+ if (is_nil(lst)) {
+ break;
+ }
+ if (is_not_list(lst)) {
+ break;
+ }
+ }
+
+ tail = lst;
+ if (!n) {
+ error_res = LTI_NO_INTEGER;
+ goto error;
+ }
+
+
+ /* If length fits inside Sint then we know it's a small int. Else we
+ * must construct a bignum and let that routine do the checking
+ */
+
+ if (n <= digits_per_small) { /* It must be small */
+ i = neg ? -(Sint)ui : (Sint)ui;
+ res = make_small(i);
+ } else {
+ const Sint largest_pow_of_base = get_largest_power_of_base(base);
+ Eterm *hp;
+ Eterm *hp_end;
+
+ /* Convert from log_base to log2 using lookup table */
+ lg2 = ((n+2)*lookup_log2(base)+1);
+ m = (lg2+D_EXP-1)/D_EXP; /* number of digits */
+ m = BIG_NEED_SIZE(m); /* number of words + thing */
+
+ hp = HAlloc(BIF_P, m);
+ hp_end = hp + m;
+
+ lst = orig_list;
+ if (skip)
+ lst = CDR(list_val(lst));
+
+ /* load first digits (at least one digit) */
+ if ((i = (n % digits_per_Sint)) == 0)
+ i = digits_per_Sint;
+ n -= i;
+ m = 0;
+ while(i--) {
+ m *= base;
+ m += c2int_digit_from_base(unsigned_val(CAR(list_val(lst))));
+ lst = CDR(list_val(lst));
+ }
+ res = small_to_big(m, hp); /* load first digits */
+
+ while(n) {
+ i = digits_per_Sint;
+ n -= digits_per_Sint;
+ m = 0;
+ while(i--) {
+ m *= base;
+ m += c2int_digit_from_base(unsigned_val(CAR(list_val(lst))));
+ lst = CDR(list_val(lst));
+ }
+ if (is_small(res))
+ res = small_to_big(signed_val(res), hp);
+ res = big_times_small(res, largest_pow_of_base, hp);
+ if (is_small(res))
+ res = small_to_big(signed_val(res), hp);
+ res = big_plus_small(res, m, hp);
+ }
+
+ if (neg) {
+ if (is_small(res))
+ res = make_small(-signed_val(res));
+ else {
+ Uint *big = big_val(res); /* point to thing */
+ *big = bignum_header_neg(*big);
+ }
+ }
+
+ if (is_not_small(res)) {
+ res = big_plus_small(res, 0, hp); /* includes conversion to small */
+
+ if (is_not_small(res)) {
+ hp += (big_arity(res)+1);
+ }
+ }
+ HRelease(BIF_P, hp_end, hp);
+ }
+ *integer_out = res;
+ *tail_out = tail;
+ if (tail != NIL) {
+ return LTI_SOME_INTEGER;
+ }
+ return LTI_ALL_INTEGER;
}
diff --git a/erts/emulator/beam/big.h b/erts/emulator/beam/big.h
index 3c1f1e6b23..ee51e5d313 100644
--- a/erts/emulator/beam/big.h
+++ b/erts/emulator/beam/big.h
@@ -35,7 +35,7 @@
typedef Uint ErtsDigit;
-#if ((SIZEOF_VOID_P == 4) || HALFWORD_HEAP) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8)
+#if (SIZEOF_VOID_P == 4) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8)
/* Assume 32-bit machine with long long support */
typedef Uint64 ErtsDoubleDigit;
typedef Uint16 ErtsHalfDigit;
@@ -54,9 +54,6 @@ typedef Uint32 ErtsHalfDigit;
#error "can not determine machine size"
#endif
-#define D_DECIMAL_EXP 9
-#define D_DECIMAL_BASE 1000000000
-
typedef Uint dsize_t; /* Vector size type */
#define D_EXP (ERTS_SIZEOF_ETERM*8)
@@ -90,13 +87,9 @@ typedef Uint dsize_t; /* Vector size type */
#define BIG_UINT_HEAP_SIZE (1 + 1) /* always, since sizeof(Uint) <= sizeof(Eterm) */
-#if HALFWORD_HEAP
-#define BIG_UWORD_HEAP_SIZE(UW) (((UW) >> (sizeof(Uint) * 8)) ? 3 : 2)
-#else
#define BIG_UWORD_HEAP_SIZE(UW) BIG_UINT_HEAP_SIZE
-#endif
-#if defined(ARCH_32) || HALFWORD_HEAP
+#if defined(ARCH_32)
#define ERTS_UINT64_BIG_HEAP_SIZE__(X) \
((X) >= (((Uint64) 1) << 32) ? (1 + 2) : (1 + 1))
@@ -178,5 +171,15 @@ Eterm erts_sint64_to_big(Sint64, Eterm **);
Eterm erts_chars_to_integer(Process *, char*, Uint, const int);
+/* How list_to_integer classifies the input, was it even a string? */
+typedef enum {
+ LTI_BAD_STRUCTURE = 0,
+ LTI_NO_INTEGER = 1,
+ LTI_SOME_INTEGER = 2,
+ LTI_ALL_INTEGER = 3
+} LTI_result_t;
+
+LTI_result_t erts_list_to_integer(Process *BIF_P, Eterm orig_list,
+ const Uint base,
+ Eterm *integer_out, Eterm *tail_out);
#endif
-
diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c
index 247c8f1122..3fd284b589 100644
--- a/erts/emulator/beam/binary.c
+++ b/erts/emulator/beam/binary.c
@@ -34,6 +34,9 @@
#include "erl_binary.h"
#include "erl_bits.h"
+#define L2B_B2L_MIN_EXEC_REDS (CONTEXT_REDS/4)
+#define L2B_B2L_RESCHED_REDS (CONTEXT_REDS/40)
+
static Export binary_to_list_continue_export;
static Export list_to_binary_continue_export;
@@ -415,10 +418,10 @@ binary_to_list_chunk(Process *c_p,
}
static ERTS_INLINE BIF_RETTYPE
-binary_to_list(Process *c_p, Eterm *hp, Eterm tail, byte *bytes, Uint size, Uint bitoffs)
+binary_to_list(Process *c_p, Eterm *hp, Eterm tail, byte *bytes,
+ Uint size, Uint bitoffs, int reds_left, int one_chunk)
{
- int reds_left = ERTS_BIF_REDS_LEFT(c_p);
- if (size < reds_left*ERTS_B2L_BYTES_PER_REDUCTION) {
+ if (one_chunk) {
Eterm res;
BIF_RETTYPE ret;
int bump_reds = (size - 1)/ERTS_B2L_BYTES_PER_REDUCTION + 1;
@@ -472,11 +475,29 @@ BIF_RETTYPE binary_to_list_1(BIF_ALIST_1)
Uint size;
Uint bitsize;
Uint bitoffs;
+ int reds_left;
+ int one_chunk;
if (is_not_binary(BIF_ARG_1)) {
goto error;
}
+
size = binary_size(BIF_ARG_1);
+ reds_left = ERTS_BIF_REDS_LEFT(BIF_P);
+ one_chunk = size < reds_left*ERTS_B2L_BYTES_PER_REDUCTION;
+ if (!one_chunk) {
+ if (size < L2B_B2L_MIN_EXEC_REDS*ERTS_B2L_BYTES_PER_REDUCTION) {
+ if (reds_left <= L2B_B2L_RESCHED_REDS) {
+ /* Yield and do it with full context reds... */
+ ERTS_BIF_YIELD1(bif_export[BIF_binary_to_list_1],
+ BIF_P, BIF_ARG_1);
+ }
+ /* Allow a bit more reductions... */
+ one_chunk = 1;
+ reds_left = L2B_B2L_MIN_EXEC_REDS;
+ }
+ }
+
ERTS_GET_REAL_BIN(BIF_ARG_1, real_bin, offset, bitoffs, bitsize);
if (bitsize != 0) {
goto error;
@@ -486,7 +507,8 @@ BIF_RETTYPE binary_to_list_1(BIF_ALIST_1)
} else {
Eterm* hp = HAlloc(BIF_P, 2 * size);
byte* bytes = binary_bytes(real_bin)+offset;
- return binary_to_list(BIF_P, hp, NIL, bytes, size, bitoffs);
+ return binary_to_list(BIF_P, hp, NIL, bytes, size,
+ bitoffs, reds_left, one_chunk);
}
error:
@@ -505,6 +527,8 @@ BIF_RETTYPE binary_to_list_3(BIF_ALIST_3)
Uint start;
Uint stop;
Eterm* hp;
+ int reds_left;
+ int one_chunk;
if (is_not_binary(BIF_ARG_1)) {
goto error;
@@ -513,6 +537,21 @@ BIF_RETTYPE binary_to_list_3(BIF_ALIST_3)
goto error;
}
size = binary_size(BIF_ARG_1);
+ reds_left = ERTS_BIF_REDS_LEFT(BIF_P);
+ one_chunk = size < reds_left*ERTS_B2L_BYTES_PER_REDUCTION;
+ if (!one_chunk) {
+ if (size < L2B_B2L_MIN_EXEC_REDS*ERTS_B2L_BYTES_PER_REDUCTION) {
+ if (reds_left <= L2B_B2L_RESCHED_REDS) {
+ /* Yield and do it with full context reds... */
+ ERTS_BIF_YIELD3(bif_export[BIF_binary_to_list_3],
+ BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+ }
+ /* Allow a bit more reductions... */
+ one_chunk = 1;
+ reds_left = L2B_B2L_MIN_EXEC_REDS;
+ }
+ }
+
ERTS_GET_BINARY_BYTES(BIF_ARG_1, bytes, bitoffs, bitsize);
if (start < 1 || start > size || stop < 1 ||
stop > size || stop < start ) {
@@ -520,7 +559,8 @@ BIF_RETTYPE binary_to_list_3(BIF_ALIST_3)
}
i = stop-start+1;
hp = HAlloc(BIF_P, 2*i);
- return binary_to_list(BIF_P, hp, NIL, bytes+start-1, i, bitoffs);
+ return binary_to_list(BIF_P, hp, NIL, bytes+start-1, i,
+ bitoffs, reds_left, one_chunk);
error:
BIF_ERROR(BIF_P, BADARG);
}
@@ -537,11 +577,27 @@ BIF_RETTYPE bitstring_to_list_1(BIF_ALIST_1)
byte* bytes;
Eterm previous = NIL;
Eterm* hp;
+ int reds_left;
+ int one_chunk;
if (is_not_binary(BIF_ARG_1)) {
BIF_ERROR(BIF_P, BADARG);
}
size = binary_size(BIF_ARG_1);
+ reds_left = ERTS_BIF_REDS_LEFT(BIF_P);
+ one_chunk = size < reds_left*ERTS_B2L_BYTES_PER_REDUCTION;
+ if (!one_chunk) {
+ if (size < L2B_B2L_MIN_EXEC_REDS*ERTS_B2L_BYTES_PER_REDUCTION) {
+ if (reds_left <= L2B_B2L_RESCHED_REDS) {
+ /* Yield and do it with full context reds... */
+ ERTS_BIF_YIELD1(bif_export[BIF_bitstring_to_list_1],
+ BIF_P, BIF_ARG_1);
+ }
+ /* Allow a bit more reductions... */
+ one_chunk = 1;
+ reds_left = L2B_B2L_MIN_EXEC_REDS;
+ }
+ }
ERTS_GET_REAL_BIN(BIF_ARG_1, real_bin, offset, bitoffs, bitsize);
bytes = binary_bytes(real_bin)+offset;
if (bitsize == 0) {
@@ -566,7 +622,8 @@ BIF_RETTYPE bitstring_to_list_1(BIF_ALIST_1)
hp += 2;
}
- return binary_to_list(BIF_P, hp, previous, bytes, size, bitoffs);
+ return binary_to_list(BIF_P, hp, previous, bytes, size,
+ bitoffs, reds_left, one_chunk);
}
@@ -795,8 +852,19 @@ static BIF_RETTYPE list_to_binary_continue(BIF_ALIST_1)
BIF_RETTYPE erts_list_to_binary_bif(Process *c_p, Eterm arg, Export *bif)
{
+ int orig_reds_left = ERTS_BIF_REDS_LEFT(c_p);
BIF_RETTYPE ret;
+ if (orig_reds_left < L2B_B2L_MIN_EXEC_REDS) {
+ if (orig_reds_left <= L2B_B2L_RESCHED_REDS) {
+ /* Yield and do it with full context reds... */
+ ERTS_BIF_PREP_YIELD1(ret, bif, c_p, arg);
+ return ret;
+ }
+ /* Allow a bit more reductions... */
+ orig_reds_left = L2B_B2L_MIN_EXEC_REDS;
+ }
+
if (is_nil(arg))
ERTS_BIF_PREP_RET(ret, new_binary(c_p, (byte *) "", 0));
else if (is_not_list(arg))
@@ -818,7 +886,6 @@ BIF_RETTYPE erts_list_to_binary_bif(Process *c_p, Eterm arg, Export *bif)
bif,
erts_iolist_size_yielding,
erts_iolist_to_buf_yielding);
- int orig_reds_left = ERTS_BIF_REDS_LEFT(c_p);
/*
* First try to do it all at once without having to use
diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c
index 0ddf7f4e6d..8c039ef132 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -252,7 +252,7 @@ print_process_info(int to, void *to_arg, Process *p)
/* display the message queue only if there is anything in it */
if (!ERTS_IS_CRASH_DUMPING && p->msg.first != NULL && !garbing) {
- ErlMessage* mp;
+ ErtsMessage* mp;
erts_print(to, to_arg, "Message queue: [");
for (mp = p->msg.first; mp; mp = mp->next)
erts_print(to, to_arg, mp->next ? "%T," : "%T", ERL_MESSAGE_TERM(mp));
@@ -323,7 +323,7 @@ print_process_info(int to, void *to_arg, Process *p)
erts_print(to, to_arg, "Heap unused: %bpu\n", (p->hend - p->htop));
erts_print(to, to_arg, "OldHeap unused: %bpu\n",
(OLD_HEAP(p) == NULL) ? 0 : (OLD_HEND(p) - OLD_HTOP(p)) );
- erts_print(to, to_arg, "Memory: %beu\n", erts_process_memory(p));
+ erts_print(to, to_arg, "Memory: %beu\n", erts_process_memory(p, !0));
if (garbing) {
print_garb_info(to, to_arg, p);
@@ -381,7 +381,7 @@ loaded(int to, void *to_arg)
int i;
int old = 0;
int cur = 0;
- BeamInstr* code;
+ BeamCodeHeader* code;
Module* modp;
ErtsCodeIndex code_ix;
@@ -439,30 +439,30 @@ loaded(int to, void *to_arg)
erts_print(to, to_arg, "\n");
erts_print(to, to_arg, "Current size: %d\n",
modp->curr.code_length);
- code = modp->curr.code;
- if (code != NULL && code[MI_ATTR_PTR]) {
+ code = modp->curr.code_hdr;
+ if (code != NULL && code->attr_ptr) {
erts_print(to, to_arg, "Current attributes: ");
- dump_attributes(to, to_arg, (byte *) code[MI_ATTR_PTR],
- code[MI_ATTR_SIZE]);
+ dump_attributes(to, to_arg, code->attr_ptr,
+ code->attr_size);
}
- if (code != NULL && code[MI_COMPILE_PTR]) {
+ if (code != NULL && code->compile_ptr) {
erts_print(to, to_arg, "Current compilation info: ");
- dump_attributes(to, to_arg, (byte *) code[MI_COMPILE_PTR],
- code[MI_COMPILE_SIZE]);
+ dump_attributes(to, to_arg, code->compile_ptr,
+ code->compile_size);
}
if (modp->old.code_length != 0) {
erts_print(to, to_arg, "Old size: %d\n", modp->old.code_length);
- code = modp->old.code;
- if (code[MI_ATTR_PTR]) {
+ code = modp->old.code_hdr;
+ if (code->attr_ptr) {
erts_print(to, to_arg, "Old attributes: ");
- dump_attributes(to, to_arg, (byte *) code[MI_ATTR_PTR],
- code[MI_ATTR_SIZE]);
+ dump_attributes(to, to_arg, code->attr_ptr,
+ code->attr_size);
}
- if (code[MI_COMPILE_PTR]) {
+ if (code->compile_ptr) {
erts_print(to, to_arg, "Old compilation info: ");
- dump_attributes(to, to_arg, (byte *) code[MI_COMPILE_PTR],
- code[MI_COMPILE_SIZE]);
+ dump_attributes(to, to_arg, code->compile_ptr,
+ code->compile_size);
}
}
}
diff --git a/erts/emulator/beam/code_ix.c b/erts/emulator/beam/code_ix.c
index 209d008d18..1b0968c55c 100644
--- a/erts/emulator/beam/code_ix.c
+++ b/erts/emulator/beam/code_ix.c
@@ -65,12 +65,12 @@ void erts_code_ix_init(void)
CIX_TRACE("init");
}
-void erts_start_staging_code_ix(void)
+void erts_start_staging_code_ix(int num_new)
{
beam_catches_start_staging();
export_start_staging();
module_start_staging();
- erts_start_staging_ranges();
+ erts_start_staging_ranges(num_new);
CIX_TRACE("start");
}
diff --git a/erts/emulator/beam/code_ix.h b/erts/emulator/beam/code_ix.h
index 5f00b409ef..7a66211a5b 100644
--- a/erts/emulator/beam/code_ix.h
+++ b/erts/emulator/beam/code_ix.h
@@ -100,7 +100,7 @@ void erts_release_code_write_permission(void);
* Must be followed by calls to either "end" and "commit" or "abort" before
* code write permission can be released.
*/
-void erts_start_staging_code_ix(void);
+void erts_start_staging_code_ix(int num_new);
/* End the staging.
* Preceded by "start" and must be followed by "commit".
diff --git a/erts/emulator/beam/copy.c b/erts/emulator/beam/copy.c
index 64be43edb4..b38ebe066b 100644
--- a/erts/emulator/beam/copy.c
+++ b/erts/emulator/beam/copy.c
@@ -35,56 +35,59 @@
#include "erl_bits.h"
#include "dtrace-wrapper.h"
-static void move_one_frag(Eterm** hpp, ErlHeapFragment*, ErlOffHeap*);
+static void move_one_frag(Eterm** hpp, ErlHeapFragment*, ErlOffHeap*, int);
/*
* Copy object "obj" to process p.
*/
-Eterm
-copy_object(Eterm obj, Process* to)
-{
- Uint size = size_object(obj);
- Eterm* hp = HAlloc(to, size);
- Eterm res;
+Eterm copy_object_x(Eterm obj, Process* to, Uint extra) {
+ if (!is_immed(obj)) {
+ Uint size = size_object(obj);
+ Eterm* hp = HAllocX(to, size, extra);
+ Eterm res;
#ifdef USE_VM_PROBES
- if (DTRACE_ENABLED(copy_object)) {
- DTRACE_CHARBUF(proc_name, 64);
+ if (DTRACE_ENABLED(copy_object)) {
+ DTRACE_CHARBUF(proc_name, 64);
- erts_snprintf(proc_name, sizeof(DTRACE_CHARBUF_NAME(proc_name)),
- "%T", to->common.id);
- DTRACE2(copy_object, proc_name, size);
- }
+ erts_snprintf(proc_name, sizeof(DTRACE_CHARBUF_NAME(proc_name)),
+ "%T", to->common.id);
+ DTRACE2(copy_object, proc_name, size);
+ }
#endif
- res = copy_struct(obj, size, &hp, &to->off_heap);
+ res = copy_struct(obj, size, &hp, &to->off_heap);
#ifdef DEBUG
- if (eq(obj, res) == 0) {
- erts_exit(ERTS_ABORT_EXIT, "copy not equal to source\n");
- }
+ if (eq(obj, res) == 0) {
+ erts_exit(ERTS_ABORT_EXIT, "copy not equal to source\n");
+ }
#endif
- return res;
+ return res;
+ }
+ return obj;
}
/*
* Return the "flat" size of the object.
*/
-#if HALFWORD_HEAP
-Uint size_object_rel(Eterm obj, Eterm* base)
-#else
Uint size_object(Eterm obj)
-#endif
{
Uint sum = 0;
Eterm* ptr;
int arity;
+#ifdef DEBUG
+ Eterm mypid = erts_get_current_pid();
+#endif
DECLARE_ESTACK(s);
+
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] size_object %p\n", mypid, obj));
+
for (;;) {
switch (primary_tag(obj)) {
case TAG_PRIMARY_LIST:
sum += 2;
- ptr = list_val_rel(obj,base);
+ ptr = list_val(obj);
obj = *ptr++;
if (!IS_CONST(obj)) {
ESTACK_PUSH(s, obj);
@@ -93,11 +96,11 @@ Uint size_object(Eterm obj)
break;
case TAG_PRIMARY_BOXED:
{
- Eterm hdr = *boxed_val_rel(obj,base);
+ Eterm hdr = *boxed_val(obj);
ASSERT(is_header(hdr));
switch (hdr & _TAG_HEADER_MASK) {
case ARITYVAL_SUBTAG:
- ptr = tuple_val_rel(obj,base);
+ ptr = tuple_val(obj);
arity = header_arity(hdr);
sum += arity + 1;
if (arity == 0) { /* Empty tuple -- unusual. */
@@ -113,7 +116,7 @@ Uint size_object(Eterm obj)
break;
case FUN_SUBTAG:
{
- Eterm* bptr = fun_val_rel(obj,base);
+ Eterm* bptr = fun_val(obj);
ErlFunThing* funp = (ErlFunThing *) bptr;
unsigned eterms = 1 /* creator */ + funp->num_free;
unsigned sz = thing_arityval(hdr);
@@ -134,7 +137,7 @@ Uint size_object(Eterm obj)
{
Uint n;
flatmap_t *mp;
- mp = (flatmap_t*)flatmap_val_rel(obj,base);
+ mp = (flatmap_t*)flatmap_val(obj);
ptr = (Eterm *)mp;
n = flatmap_get_size(mp) + 1;
sum += n + 2;
@@ -153,7 +156,7 @@ Uint size_object(Eterm obj)
{
Eterm *head;
Uint sz;
- head = hashmap_val_rel(obj, base);
+ head = hashmap_val(obj);
sz = hashmap_bitcount(MAP_HEADER_VAL(hdr));
sum += 1 + sz + header_arity(hdr);
head += 1 + header_arity(hdr);
@@ -182,7 +185,7 @@ Uint size_object(Eterm obj)
Uint bitoffs;
Uint extra_bytes;
Eterm hdr;
- ERTS_GET_REAL_BIN_REL(obj, real_bin, offset, bitoffs, bitsize, base);
+ ERTS_GET_REAL_BIN(obj, real_bin, offset, bitoffs, bitsize);
if ((bitsize + bitoffs) > 8) {
sum += ERL_SUB_BIN_SIZE;
extra_bytes = 2;
@@ -192,11 +195,11 @@ Uint size_object(Eterm obj)
} else {
extra_bytes = 0;
}
- hdr = *binary_val_rel(real_bin,base);
+ hdr = *binary_val(real_bin);
if (thing_subtag(hdr) == REFC_BINARY_SUBTAG) {
sum += PROC_BIN_SIZE;
} else {
- sum += heap_bin_size(binary_size_rel(obj,base)+extra_bytes);
+ sum += heap_bin_size(binary_size(obj)+extra_bytes);
}
goto pop_next;
}
@@ -214,6 +217,7 @@ Uint size_object(Eterm obj)
pop_next:
if (ESTACK_ISEMPTY(s)) {
DESTROY_ESTACK(s);
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] size was: %u\n", mypid, sum));
return sum;
}
obj = ESTACK_POP(s);
@@ -225,14 +229,377 @@ Uint size_object(Eterm obj)
}
/*
+ * Machinery for sharing preserving information
+ * Using a WSTACK but not very transparently; consider refactoring
+ */
+
+#define DECLARE_BITSTORE(s) \
+ DECLARE_WSTACK(s); \
+ int WSTK_CONCAT(s,_bitoffs) = 0; \
+ int WSTK_CONCAT(s,_offset) = 0; \
+ UWord WSTK_CONCAT(s,_buffer) = 0
+
+#define DESTROY_BITSTORE(s) DESTROY_WSTACK(s)
+#define BITSTORE_PUT(s,i) \
+do { \
+ WSTK_CONCAT(s,_buffer) |= i << WSTK_CONCAT(s,_bitoffs); \
+ WSTK_CONCAT(s,_bitoffs) += 2; \
+ if (WSTK_CONCAT(s,_bitoffs) >= 8*sizeof(UWord)) { \
+ WSTACK_PUSH(s, WSTK_CONCAT(s,_buffer)); \
+ WSTK_CONCAT(s,_bitoffs) = 0; \
+ WSTK_CONCAT(s,_buffer) = 0; \
+ } \
+} while(0)
+#define BITSTORE_CLOSE(s) \
+do { \
+ if (WSTK_CONCAT(s,_bitoffs) > 0) { \
+ WSTACK_PUSH(s, WSTK_CONCAT(s,_buffer)); \
+ WSTK_CONCAT(s,_bitoffs) = 0; \
+ } \
+} while(0)
+
+#define BITSTORE_FETCH(s,dst) \
+do { \
+ UWord result; \
+ if (WSTK_CONCAT(s,_bitoffs) <= 0) { \
+ WSTK_CONCAT(s,_buffer) = s.wstart[WSTK_CONCAT(s,_offset)]; \
+ WSTK_CONCAT(s,_offset)++; \
+ WSTK_CONCAT(s,_bitoffs) = 8*sizeof(UWord); \
+ } \
+ WSTK_CONCAT(s,_bitoffs) -= 2; \
+ result = WSTK_CONCAT(s,_buffer) & 3; \
+ WSTK_CONCAT(s,_buffer) >>= 2; \
+ (dst) = result; \
+} while(0)
+
+#define BOXED_VISITED_MASK ((Eterm) 3)
+#define BOXED_VISITED ((Eterm) 1)
+#define BOXED_SHARED_UNPROCESSED ((Eterm) 2)
+#define BOXED_SHARED_PROCESSED ((Eterm) 3)
+
+#define COUNT_OFF_HEAP (0)
+
+#define IN_LITERAL_PURGE_AREA(info, ptr) \
+ ((info)->range_ptr && ( \
+ (info)->range_ptr <= (ptr) && \
+ (ptr) < ((info)->range_ptr + (info)->range_sz)))
+/*
+ * Return the real size of an object and find sharing information
+ * This currently returns the same as erts_debug:size/1.
+ * It is argued whether the size of subterms in constant pools
+ * should be counted or not.
+ */
+
+Uint size_shared(Eterm obj)
+{
+ Eterm saved_obj = obj;
+ Uint sum = 0;
+ Eterm* ptr;
+
+ DECLARE_EQUEUE(s);
+ DECLARE_BITSTORE(b);
+
+ for (;;) {
+ switch (primary_tag(obj)) {
+ case TAG_PRIMARY_LIST: {
+ Eterm head, tail;
+ ptr = list_val(obj);
+ /* we're not counting anything that's outside our heap */
+ if (!COUNT_OFF_HEAP && erts_is_literal(obj,ptr)) {
+ goto pop_next;
+ }
+ head = CAR(ptr);
+ tail = CDR(ptr);
+ /* if it's visited, don't count it */
+ if (primary_tag(tail) == TAG_PRIMARY_HEADER ||
+ primary_tag(head) == TAG_PRIMARY_HEADER) {
+ goto pop_next;
+ }
+ /* else make it visited now */
+ switch (primary_tag(tail)) {
+ case TAG_PRIMARY_LIST:
+ ptr[1] = (tail - TAG_PRIMARY_LIST) | TAG_PRIMARY_HEADER;
+ break;
+ case TAG_PRIMARY_IMMED1:
+ CAR(ptr) = (head - primary_tag(head)) | TAG_PRIMARY_HEADER;
+ CDR(ptr) = (tail - TAG_PRIMARY_IMMED1) | primary_tag(head);
+ break;
+ case TAG_PRIMARY_BOXED:
+ BITSTORE_PUT(b, primary_tag(head));
+ CAR(ptr) = (head - primary_tag(head)) | TAG_PRIMARY_HEADER;
+ CDR(ptr) = (tail - TAG_PRIMARY_BOXED) | TAG_PRIMARY_HEADER;
+ break;
+ }
+ /* and count it */
+ sum += 2;
+ if (!IS_CONST(head)) {
+ EQUEUE_PUT(s, head);
+ }
+ obj = tail;
+ break;
+ }
+ case TAG_PRIMARY_BOXED: {
+ Eterm hdr;
+ ptr = boxed_val(obj);
+ /* we're not counting anything that's outside our heap */
+ if (!COUNT_OFF_HEAP && erts_is_literal(obj,ptr)) {
+ goto pop_next;
+ }
+ hdr = *ptr;
+ /* if it's visited, don't count it */
+ if (primary_tag(hdr) != TAG_PRIMARY_HEADER) {
+ goto pop_next;
+ }
+ /* else make it visited now */
+ *ptr = (hdr - primary_tag(hdr)) + BOXED_VISITED;
+ /* and count it */
+ ASSERT(is_header(hdr));
+ switch (hdr & _TAG_HEADER_MASK) {
+ case ARITYVAL_SUBTAG: {
+ int arity = header_arity(hdr);
+ sum += arity + 1;
+ if (arity == 0) { /* Empty tuple -- unusual. */
+ goto pop_next;
+ }
+ while (arity-- > 0) {
+ obj = *++ptr;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT(s, obj);
+ }
+ }
+ goto pop_next;
+ }
+ case FUN_SUBTAG: {
+ ErlFunThing* funp = (ErlFunThing *) ptr;
+ unsigned eterms = 1 /* creator */ + funp->num_free;
+ unsigned sz = thing_arityval(hdr);
+ sum += 1 /* header */ + sz + eterms;
+ ptr += 1 /* header */ + sz;
+ while (eterms-- > 0) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT(s, obj);
+ }
+ }
+ goto pop_next;
+ }
+ case SUB_BINARY_SUBTAG: {
+ ErlSubBin* sb = (ErlSubBin *) ptr;
+ Uint extra_bytes;
+ Eterm hdr;
+ ASSERT((sb->thing_word & ~BOXED_VISITED_MASK) == HEADER_SUB_BIN);
+ if (sb->bitsize + sb->bitoffs > 8) {
+ sum += ERL_SUB_BIN_SIZE;
+ extra_bytes = 2;
+ } else if (sb->bitsize + sb->bitoffs > 0) {
+ sum += ERL_SUB_BIN_SIZE;
+ extra_bytes = 1;
+ } else {
+ extra_bytes = 0;
+ }
+ ptr = binary_val(sb->orig);
+ hdr = (*ptr) & ~BOXED_VISITED_MASK;
+ if (thing_subtag(hdr) == REFC_BINARY_SUBTAG) {
+ sum += PROC_BIN_SIZE;
+ } else {
+ ASSERT(thing_subtag(hdr) == HEAP_BINARY_SUBTAG);
+ sum += heap_bin_size(binary_size(obj) + extra_bytes);
+ }
+ goto pop_next;
+ }
+ case MAP_SUBTAG:
+ switch (MAP_HEADER_TYPE(hdr)) {
+ case MAP_HEADER_TAG_FLATMAP_HEAD : {
+ flatmap_t *mp = (flatmap_t*)flatmap_val(obj);
+ Uint n = flatmap_get_size(mp) + 1;
+ ptr = (Eterm *)mp;
+ sum += n + 2;
+ ptr += 2; /* hdr + size words */
+ while (n--) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT(s, obj);
+ }
+ }
+ goto pop_next;
+ }
+ case MAP_HEADER_TAG_HAMT_HEAD_BITMAP :
+ case MAP_HEADER_TAG_HAMT_HEAD_ARRAY :
+ case MAP_HEADER_TAG_HAMT_NODE_BITMAP : {
+ Uint n = hashmap_bitcount(MAP_HEADER_VAL(hdr));
+ sum += 1 + n + header_arity(hdr);
+ ptr += 1 + header_arity(hdr);
+ while (n--) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT(s, obj);
+ }
+ }
+ goto pop_next;
+ }
+ default:
+ erts_exit(ERTS_ABORT_EXIT, "size_shared: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr));
+ }
+ case BIN_MATCHSTATE_SUBTAG:
+ erts_exit(ERTS_ABORT_EXIT,
+ "size_shared: matchstate term not allowed");
+ default:
+ sum += thing_arityval(hdr) + 1;
+ goto pop_next;
+ }
+ break;
+ }
+ case TAG_PRIMARY_IMMED1:
+ pop_next:
+ if (EQUEUE_ISEMPTY(s)) {
+ goto cleanup;
+ }
+ obj = EQUEUE_GET(s);
+ break;
+ default:
+ erts_exit(ERTS_ABORT_EXIT, "size_shared: bad tag for %#x\n", obj);
+ }
+ }
+
+cleanup:
+ obj = saved_obj;
+ BITSTORE_CLOSE(b);
+ for (;;) {
+ switch (primary_tag(obj)) {
+ case TAG_PRIMARY_LIST: {
+ Eterm head, tail;
+ ptr = list_val(obj);
+ if (!COUNT_OFF_HEAP && erts_is_literal(obj,ptr)) {
+ goto cleanup_next;
+ }
+ head = CAR(ptr);
+ tail = CDR(ptr);
+ /* if not already clean, clean it up */
+ if (primary_tag(tail) == TAG_PRIMARY_HEADER) {
+ if (primary_tag(head) == TAG_PRIMARY_HEADER) {
+ Eterm saved;
+ BITSTORE_FETCH(b, saved);
+ CAR(ptr) = head = (head - TAG_PRIMARY_HEADER) | saved;
+ CDR(ptr) = tail = (tail - TAG_PRIMARY_HEADER) | TAG_PRIMARY_BOXED;
+ } else {
+ CDR(ptr) = tail = (tail - TAG_PRIMARY_HEADER) | TAG_PRIMARY_LIST;
+ }
+ } else if (primary_tag(head) == TAG_PRIMARY_HEADER) {
+ CAR(ptr) = head = (head - TAG_PRIMARY_HEADER) | primary_tag(tail);
+ CDR(ptr) = tail = (tail - primary_tag(tail)) | TAG_PRIMARY_IMMED1;
+ } else {
+ goto cleanup_next;
+ }
+ /* and its children too */
+ if (!IS_CONST(head)) {
+ EQUEUE_PUT_UNCHECKED(s, head);
+ }
+ obj = tail;
+ break;
+ }
+ case TAG_PRIMARY_BOXED: {
+ Eterm hdr;
+ ptr = boxed_val(obj);
+ if (!COUNT_OFF_HEAP && erts_is_literal(obj,ptr)) {
+ goto cleanup_next;
+ }
+ hdr = *ptr;
+ /* if not already clean, clean it up */
+ if (primary_tag(hdr) == TAG_PRIMARY_HEADER) {
+ goto cleanup_next;
+ }
+ else {
+ ASSERT(primary_tag(hdr) == BOXED_VISITED);
+ *ptr = hdr = (hdr - BOXED_VISITED) + TAG_PRIMARY_HEADER;
+ }
+ /* and its children too */
+ switch (hdr & _TAG_HEADER_MASK) {
+ case ARITYVAL_SUBTAG: {
+ int arity = header_arity(hdr);
+ if (arity == 0) { /* Empty tuple -- unusual. */
+ goto cleanup_next;
+ }
+ while (arity-- > 0) {
+ obj = *++ptr;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT_UNCHECKED(s, obj);
+ }
+ }
+ goto cleanup_next;
+ }
+ case FUN_SUBTAG: {
+ ErlFunThing* funp = (ErlFunThing *) ptr;
+ unsigned eterms = 1 /* creator */ + funp->num_free;
+ unsigned sz = thing_arityval(hdr);
+ ptr += 1 /* header */ + sz;
+ while (eterms-- > 0) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT_UNCHECKED(s, obj);
+ }
+ }
+ goto cleanup_next;
+ }
+ case MAP_SUBTAG:
+ switch (MAP_HEADER_TYPE(hdr)) {
+ case MAP_HEADER_TAG_FLATMAP_HEAD : {
+ flatmap_t *mp = (flatmap_t *) ptr;
+ Uint n = flatmap_get_size(mp) + 1;
+ ptr += 2; /* hdr + size words */
+ while (n--) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT_UNCHECKED(s, obj);
+ }
+ }
+ goto cleanup_next;
+ }
+ case MAP_HEADER_TAG_HAMT_HEAD_BITMAP :
+ case MAP_HEADER_TAG_HAMT_HEAD_ARRAY :
+ case MAP_HEADER_TAG_HAMT_NODE_BITMAP : {
+ Uint n = hashmap_bitcount(MAP_HEADER_VAL(hdr));
+ sum += 1 + n + header_arity(hdr);
+ ptr += 1 + header_arity(hdr);
+ while (n--) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT_UNCHECKED(s, obj);
+ }
+ }
+ goto cleanup_next;
+ }
+ default:
+ erts_exit(ERTS_ABORT_EXIT, "size_shared: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr));
+ }
+ default:
+ goto cleanup_next;
+ }
+ break;
+ }
+ case TAG_PRIMARY_IMMED1:
+ cleanup_next:
+ if (EQUEUE_ISEMPTY(s)) {
+ goto all_clean;
+ }
+ obj = EQUEUE_GET(s);
+ break;
+ default:
+ erts_exit(ERTS_ABORT_EXIT, "size_shared: bad tag for %#x\n", obj);
+ }
+ }
+
+ all_clean:
+ /* Return the result */
+ DESTROY_EQUEUE(s);
+ DESTROY_BITSTORE(b);
+ return sum;
+}
+
+
+/*
* Copy a structure to a heap.
*/
-#if HALFWORD_HEAP
-Eterm copy_struct_rel(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap,
- Eterm* src_base, Eterm* dst_base)
-#else
-Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
-#endif
+Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap, Uint *bsz)
{
char* hstart;
Uint hsize;
@@ -247,19 +614,23 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
Eterm* argp;
Eterm* const_tuple;
Eterm hdr;
+ Eterm *hend;
int i;
#ifdef DEBUG
Eterm org_obj = obj;
Uint org_sz = sz;
+ Eterm mypid = erts_get_current_pid();
#endif
if (IS_CONST(obj))
return obj;
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] copy_struct %p\n", mypid, obj));
+
DTRACE1(copy_struct, (int32_t)sz);
hp = htop = *hpp;
- hbot = htop + sz;
+ hbot = hend = htop + sz;
hstart = (char *)htop;
hsize = (char*) hbot - hstart;
const_tuple = 0;
@@ -268,7 +639,7 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
switch (primary_tag(obj)) {
case TAG_PRIMARY_LIST:
argp = &res;
- objp = list_val_rel(obj,src_base);
+ objp = list_val(obj);
goto L_copy_list;
case TAG_PRIMARY_BOXED: argp = &res; goto L_copy_boxed;
default:
@@ -286,14 +657,11 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
hp++;
break;
case TAG_PRIMARY_LIST:
- objp = list_val_rel(obj,src_base);
- #if !HALFWORD_HEAP || defined(DEBUG)
- if (in_area(objp,hstart,hsize)) {
- ASSERT(!HALFWORD_HEAP);
+ objp = list_val(obj);
+ if (ErtsInArea(objp,hstart,hsize)) {
hp++;
break;
}
- #endif
argp = hp++;
/* Fall through */
@@ -309,23 +677,15 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
}
else {
CAR(htop) = elem;
- #if HALFWORD_HEAP
- CDR(htop) = CDR(objp);
- *tailp = make_list_rel(htop,dst_base);
- htop += 2;
- goto L_copy;
- #else
tailp = &CDR(htop);
htop += 2;
- #endif
}
- ASSERT(!HALFWORD_HEAP || tp < hp || tp >= hbot);
- *tp = make_list_rel(tailp - 1, dst_base);
+ *tp = make_list(tailp - 1);
obj = CDR(objp);
if (!is_list(obj)) {
break;
}
- objp = list_val_rel(obj,src_base);
+ objp = list_val(obj);
}
switch (primary_tag(obj)) {
case TAG_PRIMARY_IMMED1: *tailp = obj; goto L_copy;
@@ -337,24 +697,21 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
}
case TAG_PRIMARY_BOXED:
- #if !HALFWORD_HEAP || defined(DEBUG)
- if (in_area(boxed_val_rel(obj,src_base),hstart,hsize)) {
- ASSERT(!HALFWORD_HEAP);
+ if (ErtsInArea(boxed_val(obj),hstart,hsize)) {
hp++;
break;
}
- #endif
argp = hp++;
L_copy_boxed:
- objp = boxed_val_rel(obj, src_base);
+ objp = boxed_val(obj);
hdr = *objp;
switch (hdr & _TAG_HEADER_MASK) {
case ARITYVAL_SUBTAG:
{
int const_flag = 1; /* assume constant tuple */
i = arityval(hdr);
- *argp = make_tuple_rel(htop, dst_base);
+ *argp = make_tuple(htop);
tp = htop; /* tp is pointer to new arity value */
*htop++ = *objp++; /* copy arity value */
while (i--) {
@@ -383,7 +740,7 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
while (i--) {
*tp++ = *objp++;
}
- *argp = make_binary_rel(hbot, dst_base);
+ *argp = make_binary(hbot);
pb = (ProcBin*) hbot;
erts_refc_inc(&pb->val->refc, 2);
pb->next = off_heap->first;
@@ -410,7 +767,7 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
extra_bytes = 0;
}
real_size = size+extra_bytes;
- objp = binary_val_rel(real_bin,src_base);
+ objp = binary_val(real_bin);
if (thing_subtag(*objp) == HEAP_BINARY_SUBTAG) {
ErlHeapBin* from = (ErlHeapBin *) objp;
ErlHeapBin* to;
@@ -440,7 +797,7 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
off_heap->first = (struct erl_off_heap_header*) to;
OH_OVERHEAD(off_heap, to->size / sizeof(Eterm));
}
- *argp = make_binary_rel(hbot, dst_base);
+ *argp = make_binary(hbot);
if (extra_bytes != 0) {
ErlSubBin* res;
hbot -= ERL_SUB_BIN_SIZE;
@@ -452,7 +809,7 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
res->offs = 0;
res->is_writable = 0;
res->orig = *argp;
- *argp = make_binary_rel(hbot, dst_base);
+ *argp = make_binary(hbot);
}
break;
}
@@ -470,7 +827,7 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
funp->next = off_heap->first;
off_heap->first = (struct erl_off_heap_header*) funp;
erts_refc_inc(&funp->fe->refc, 2);
- *argp = make_fun_rel(tp, dst_base);
+ *argp = make_fun(tp);
}
break;
case EXTERNAL_PID_SUBTAG:
@@ -490,7 +847,7 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
off_heap->first = (struct erl_off_heap_header*)etp;
erts_refc_inc(&etp->node->refc, 2);
- *argp = make_external_rel(tp, dst_base);
+ *argp = make_external(tp);
}
break;
case MAP_SUBTAG:
@@ -498,7 +855,7 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
switch (MAP_HEADER_TYPE(hdr)) {
case MAP_HEADER_TAG_FLATMAP_HEAD :
i = flatmap_get_size(objp) + 3;
- *argp = make_flatmap_rel(htop, dst_base);
+ *argp = make_flatmap(htop);
while (i--) {
*htop++ = *objp++;
}
@@ -509,7 +866,7 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
case MAP_HEADER_TAG_HAMT_NODE_BITMAP :
i = 1 + hashmap_bitcount(MAP_HEADER_VAL(hdr));
while (i--) { *htop++ = *objp++; }
- *argp = make_hashmap_rel(tp, dst_base);
+ *argp = make_hashmap(tp);
break;
default:
erts_exit(ERTS_ABORT_EXIT, "copy_struct: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr));
@@ -522,7 +879,7 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
i = thing_arityval(hdr)+1;
hbot -= i;
tp = hbot;
- *argp = make_boxed_rel(hbot, dst_base);
+ *argp = make_boxed(hbot);
while (i--) {
*tp++ = *objp++;
}
@@ -538,22 +895,870 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
}
}
+ if (bsz) {
+ *hpp = htop;
+ *bsz = hend - hbot;
+ } else {
#ifdef DEBUG
- if (htop != hbot)
- erts_exit(ERTS_ABORT_EXIT,
- "Internal error in copy_struct() when copying %T:"
- " htop=%p != hbot=%p (sz=%beu)\n",
- org_obj, htop, hbot, org_sz);
+ if (htop != hbot)
+ erts_exit(ERTS_ABORT_EXIT,
+ "Internal error in copy_struct() when copying %T:"
+ " htop=%p != hbot=%p (sz=%beu)\n",
+ org_obj, htop, hbot, org_sz);
#else
- if (htop > hbot) {
- erts_exit(ERTS_ABORT_EXIT,
- "Internal error in copy_struct(): htop, hbot overrun\n");
- }
+ if (htop > hbot) {
+ erts_exit(ERTS_ABORT_EXIT,
+ "Internal error in copy_struct(): htop, hbot overrun\n");
+ }
#endif
- *hpp = (Eterm *) (hstart+hsize);
+ *hpp = (Eterm *) (hstart+hsize);
+ }
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] result is at %p\n", mypid, res));
return res;
}
+
+/*
+ * Machinery for the table used by the sharing preserving copier
+ * Using an ESTACK but not very transparently; consider refactoring
+ */
+
+#define DECLARE_SHTABLE(s) \
+ DECLARE_ESTACK(s); \
+ Uint ESTK_CONCAT(s,_offset) = 0
+#define DESTROY_SHTABLE(s) DESTROY_ESTACK(s)
+#define SHTABLE_INCR 4
+#define SHTABLE_NEXT(s) ESTK_CONCAT(s,_offset)
+#define SHTABLE_PUSH(s,x,y,b) \
+do { \
+ if (s.sp > s.end - SHTABLE_INCR) { \
+ erl_grow_estack(&(s), SHTABLE_INCR); \
+ } \
+ *s.sp++ = (x); \
+ *s.sp++ = (y); \
+ *s.sp++ = (Eterm) NULL; \
+ *s.sp++ = (Eterm) (b); \
+ ESTK_CONCAT(s,_offset) += SHTABLE_INCR; \
+} while(0)
+#define SHTABLE_X(s,e) (s.start[e])
+#define SHTABLE_Y(s,e) (s.start[(e)+1])
+#define SHTABLE_FWD(s,e) ((Eterm *) (s.start[(e)+2]))
+#define SHTABLE_FWD_UPD(s,e,p) (s.start[(e)+2] = (Eterm) (p))
+#define SHTABLE_REV(s,e) ((Eterm *) (s.start[(e)+3]))
+
+#define LIST_SHARED_UNPROCESSED ((Eterm) 0)
+#define LIST_SHARED_PROCESSED ((Eterm) 1)
+
+#define HEAP_ELEM_TO_BE_FILLED _unchecked_make_list(NULL)
+
+
+/*
+ * Specialized macros for using/reusing the persistent state
+ */
+
+#define DECLARE_EQUEUE_INIT_INFO(q, info) \
+ UWord* EQUE_DEF_QUEUE(q) = info->queue_default; \
+ ErtsEQueue q = { \
+ EQUE_DEF_QUEUE(q), /* start */ \
+ EQUE_DEF_QUEUE(q), /* front */ \
+ EQUE_DEF_QUEUE(q), /* back */ \
+ 1, /* possibly_empty */ \
+ EQUE_DEF_QUEUE(q) + DEF_EQUEUE_SIZE, /* end */ \
+ ERTS_ALC_T_ESTACK /* alloc_type */ \
+ }
+
+#define DECLARE_EQUEUE_FROM_INFO(q, info) \
+ /* no EQUE_DEF_QUEUE(q), read-only */ \
+ ErtsEQueue q = { \
+ info->queue_start, /* start */ \
+ info->queue_start, /* front */ \
+ info->queue_start, /* back */ \
+ 1, /* possibly_empty */ \
+ info->queue_end, /* end */ \
+ info->queue_alloc_type /* alloc_type */ \
+ }
+
+#define DECLARE_BITSTORE_INIT_INFO(s, info) \
+ UWord* WSTK_DEF_STACK(s) = info->bitstore_default; \
+ ErtsWStack s = { \
+ WSTK_DEF_STACK(s), /* wstart */ \
+ WSTK_DEF_STACK(s), /* wsp */ \
+ WSTK_DEF_STACK(s) + DEF_WSTACK_SIZE, /* wend */ \
+ WSTK_DEF_STACK(s), /* wdflt */ \
+ ERTS_ALC_T_ESTACK /* alloc_type */ \
+ }; \
+ int WSTK_CONCAT(s,_bitoffs) = 0; \
+ /* no WSTK_CONCAT(s,_offset), write-only */ \
+ UWord WSTK_CONCAT(s,_buffer) = 0
+
+#define DECLARE_BITSTORE_FROM_INFO(s, info) \
+ /* no WSTK_DEF_STACK(s), read-only */ \
+ ErtsWStack s = { \
+ info->bitstore_start, /* wstart */ \
+ NULL, /* wsp, read-only */ \
+ NULL, /* wend, read-only */ \
+ NULL, /* wdef, read-only */ \
+ info->bitstore_alloc_type /* alloc_type */ \
+ }; \
+ int WSTK_CONCAT(s,_bitoffs) = 0; \
+ int WSTK_CONCAT(s,_offset) = 0; \
+ UWord WSTK_CONCAT(s,_buffer) = 0
+
+#define DECLARE_SHTABLE_INIT_INFO(s, info) \
+ Eterm* ESTK_DEF_STACK(s) = info->shtable_default; \
+ ErtsEStack s = { \
+ ESTK_DEF_STACK(s), /* start */ \
+ ESTK_DEF_STACK(s), /* sp */ \
+ ESTK_DEF_STACK(s) + DEF_ESTACK_SIZE, /* end */ \
+ ESTK_DEF_STACK(s), /* default */ \
+ ERTS_ALC_T_ESTACK /* alloc_type */ \
+ }; \
+ Uint ESTK_CONCAT(s,_offset) = 0
+
+#define DECLARE_SHTABLE_FROM_INFO(s, info) \
+ /* no ESTK_DEF_STACK(s), read-only */ \
+ ErtsEStack s = { \
+ info->shtable_start, /* start */ \
+ NULL, /* sp, read-only */ \
+ NULL, /* end, read-only */ \
+ NULL, /* def, read-only */ \
+ info->shtable_alloc_type /* alloc_type */ \
+ }; \
+ /* no ESTK_CONCAT(s,_offset), read-only */
+
+/*
+ * Copy object "obj" preserving sharing.
+ * First half: count size and calculate sharing.
+ */
+Uint copy_shared_calculate(Eterm obj, erts_shcopy_t *info)
+{
+ Uint sum;
+ Uint e;
+ unsigned sz;
+ Eterm* ptr;
+#ifdef DEBUG
+ Eterm mypid = erts_get_current_pid();
+#endif
+
+ DECLARE_EQUEUE_INIT_INFO(s, info);
+ DECLARE_BITSTORE_INIT_INFO(b, info);
+ DECLARE_SHTABLE_INIT_INFO(t, info);
+
+ /* step #0:
+ -------------------------------------------------------
+ get rid of the easy cases first:
+ - copying constants
+ - if not a proper process, do flat copy
+ */
+
+ if (IS_CONST(obj))
+ return 0;
+
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] copy_shared_calculate %p\n", mypid, obj));
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] message is %T\n", mypid, obj));
+
+ /* step #1:
+ -------------------------------------------------------
+ traverse the term and calculate the size;
+ when traversing, transform as you do in size_shared
+ but when you find shared objects:
+
+ a. add entry in the table, indexed by i
+ b. mark them:
+ b1. boxed terms, set header to (i | 11)
+ store (old header, NONV, NULL, backptr) in the entry
+ b2. cons cells, set CDR to NONV, set CAR to i
+ store (old CAR, old CDR, NULL, backptr) in the entry
+ */
+
+ sum = 0;
+
+ for (;;) {
+ switch (primary_tag(obj)) {
+ case TAG_PRIMARY_LIST: {
+ Eterm head, tail;
+ ptr = list_val(obj);
+ /* off heap list pointers are copied verbatim */
+ if (erts_is_literal(obj,ptr)) {
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] bypassed copying %p is %T\n", mypid, ptr, obj));
+ if (IN_LITERAL_PURGE_AREA(info,ptr))
+ info->literal_size += size_object(obj);
+ goto pop_next;
+ }
+ head = CAR(ptr);
+ tail = CDR(ptr);
+ /* if it's visited, don't count it;
+ if not already shared, make it shared and store it in the table */
+ if (primary_tag(tail) == TAG_PRIMARY_HEADER ||
+ primary_tag(head) == TAG_PRIMARY_HEADER) {
+ if (tail != THE_NON_VALUE) {
+ e = SHTABLE_NEXT(t);
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] tabling L %p\n", mypid, ptr));
+ SHTABLE_PUSH(t, head, tail, ptr);
+ CAR(ptr) = (e << _TAG_PRIMARY_SIZE) | LIST_SHARED_UNPROCESSED;
+ CDR(ptr) = THE_NON_VALUE;
+ }
+ goto pop_next;
+ }
+ /* else make it visited now */
+ switch (primary_tag(tail)) {
+ case TAG_PRIMARY_LIST:
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] mangling L/L %p\n", mypid, ptr));
+ CDR(ptr) = (tail - TAG_PRIMARY_LIST) | TAG_PRIMARY_HEADER;
+ break;
+ case TAG_PRIMARY_IMMED1:
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] mangling L/I %p\n", mypid, ptr));
+ CAR(ptr) = (head - primary_tag(head)) | TAG_PRIMARY_HEADER;
+ CDR(ptr) = (tail - TAG_PRIMARY_IMMED1) | primary_tag(head);
+ break;
+ case TAG_PRIMARY_BOXED:
+ BITSTORE_PUT(b, primary_tag(head));
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] mangling L/B %p\n", mypid, ptr));
+ CAR(ptr) = (head - primary_tag(head)) | TAG_PRIMARY_HEADER;
+ CDR(ptr) = (tail - TAG_PRIMARY_BOXED) | TAG_PRIMARY_HEADER;
+ break;
+ }
+ /* and count it */
+ sum += 2;
+ if (!IS_CONST(head)) {
+ EQUEUE_PUT(s, head);
+ }
+ obj = tail;
+ break;
+ }
+ case TAG_PRIMARY_BOXED: {
+ Eterm hdr;
+ ptr = boxed_val(obj);
+ /* off heap pointers to boxes are copied verbatim */
+ if (erts_is_literal(obj,ptr)) {
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] bypassed copying %p is %T\n", mypid, ptr, obj));
+ if (IN_LITERAL_PURGE_AREA(info,ptr))
+ info->literal_size += size_object(obj);
+ goto pop_next;
+ }
+ hdr = *ptr;
+ /* if it's visited, don't count it;
+ if not already shared, make it shared and store it in the table */
+ if (primary_tag(hdr) != TAG_PRIMARY_HEADER) {
+ if (primary_tag(hdr) == BOXED_VISITED) {
+ e = SHTABLE_NEXT(t);
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] tabling B %p\n", mypid, ptr));
+ SHTABLE_PUSH(t, hdr, THE_NON_VALUE, ptr);
+ *ptr = (e << _TAG_PRIMARY_SIZE) | BOXED_SHARED_UNPROCESSED;
+ }
+ goto pop_next;
+ }
+ /* else make it visited now */
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] mangling B %p\n", mypid, ptr));
+ *ptr = (hdr - primary_tag(hdr)) + BOXED_VISITED;
+ /* and count it */
+ ASSERT(is_header(hdr));
+ switch (hdr & _TAG_HEADER_MASK) {
+ case ARITYVAL_SUBTAG: {
+ int arity = header_arity(hdr);
+ sum += arity + 1;
+ if (arity == 0) { /* Empty tuple -- unusual. */
+ goto pop_next;
+ }
+ while (arity-- > 0) {
+ obj = *++ptr;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT(s, obj);
+ }
+ }
+ goto pop_next;
+ }
+ case FUN_SUBTAG: {
+ ErlFunThing* funp = (ErlFunThing *) ptr;
+ unsigned eterms = 1 /* creator */ + funp->num_free;
+ sz = thing_arityval(hdr);
+ sum += 1 /* header */ + sz + eterms;
+ ptr += 1 /* header */ + sz;
+ while (eterms-- > 0) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT(s, obj);
+ }
+ }
+ goto pop_next;
+ }
+ case SUB_BINARY_SUBTAG: {
+ ErlSubBin* sb = (ErlSubBin *) ptr;
+ Eterm real_bin = sb->orig;
+ Uint bit_offset = sb->bitoffs;
+ Uint bit_size = sb->bitsize;
+ size_t size = sb->size;
+ Uint extra_bytes;
+ Eterm hdr;
+ if (bit_size + bit_offset > 8) {
+ sum += ERL_SUB_BIN_SIZE;
+ extra_bytes = 2;
+ } else if (bit_size + bit_offset > 0) {
+ sum += ERL_SUB_BIN_SIZE;
+ extra_bytes = 1;
+ } else {
+ extra_bytes = 0;
+ }
+ ASSERT(is_boxed(real_bin) &&
+ (((*boxed_val(real_bin)) &
+ (_TAG_HEADER_MASK - _BINARY_XXX_MASK - BOXED_VISITED_MASK))
+ == _TAG_HEADER_REFC_BIN));
+ hdr = *_unchecked_binary_val(real_bin) & ~BOXED_VISITED_MASK;
+ if (thing_subtag(hdr) == HEAP_BINARY_SUBTAG) {
+ sum += heap_bin_size(size+extra_bytes);
+ } else {
+ ASSERT(thing_subtag(hdr) == REFC_BINARY_SUBTAG);
+ sum += PROC_BIN_SIZE;
+ }
+ goto pop_next;
+ }
+ case MAP_SUBTAG:
+ switch (MAP_HEADER_TYPE(hdr)) {
+ case MAP_HEADER_TAG_FLATMAP_HEAD : {
+ flatmap_t *mp = (flatmap_t *) ptr;
+ Uint n = flatmap_get_size(mp) + 1;
+ sum += n + 2;
+ ptr += 2; /* hdr + size words */
+ while (n--) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT(s, obj);
+ }
+ }
+ goto pop_next;
+ }
+ case MAP_HEADER_TAG_HAMT_HEAD_BITMAP :
+ case MAP_HEADER_TAG_HAMT_HEAD_ARRAY :
+ case MAP_HEADER_TAG_HAMT_NODE_BITMAP : {
+ Uint n = hashmap_bitcount(MAP_HEADER_VAL(hdr));
+ sum += 1 + n + header_arity(hdr);
+ ptr += 1 + header_arity(hdr);
+
+ if (n == 0) {
+ goto pop_next;
+ }
+ while(n--) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT(s, obj);
+ }
+ }
+ goto pop_next;
+ }
+ default:
+ erts_exit(ERTS_ABORT_EXIT, "copy_shared_calculate: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr));
+ }
+ case BIN_MATCHSTATE_SUBTAG:
+ erts_exit(ERTS_ABORT_EXIT,
+ "size_shared: matchstate term not allowed");
+ default:
+ sum += thing_arityval(hdr) + 1;
+ goto pop_next;
+ }
+ break;
+ }
+ case TAG_PRIMARY_IMMED1:
+ pop_next:
+ if (EQUEUE_ISEMPTY(s)) {
+ /* add sentinel to the table */
+ SHTABLE_PUSH(t, THE_NON_VALUE, THE_NON_VALUE, NULL);
+ /* store persistent info */
+ BITSTORE_CLOSE(b);
+ info->queue_start = s.start;
+ info->queue_end = s.end;
+ info->queue_alloc_type = s.alloc_type;
+ info->bitstore_start = b.wstart;
+ info->bitstore_alloc_type = b.alloc_type;
+ info->shtable_start = t.start;
+ info->shtable_alloc_type = t.alloc_type;
+ /* single point of return: the size of the object */
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] size was: %u\n", mypid, sum));
+ return sum + info->literal_size;
+ }
+ obj = EQUEUE_GET(s);
+ break;
+ default:
+ erts_exit(ERTS_ABORT_EXIT, "[pid=%T] size_shared: bad tag for %#x\n", obj);
+ }
+ }
+}
+
+/*
+ * Copy object "obj" preserving sharing.
+ * Second half: copy and restore the object.
+ */
+Uint copy_shared_perform(Eterm obj, Uint size, erts_shcopy_t *info,
+ Eterm** hpp, ErlOffHeap* off_heap) {
+ Uint e;
+ unsigned sz;
+ Eterm* ptr;
+ Eterm* hp;
+ Eterm* hscan;
+ Eterm result;
+ Eterm* resp;
+ Eterm *hbot, *hend;
+ unsigned remaining;
+#ifdef DEBUG
+ Eterm mypid = erts_get_current_pid();
+ Eterm saved_obj = obj;
+#endif
+
+ DECLARE_EQUEUE_FROM_INFO(s, info);
+ DECLARE_BITSTORE_FROM_INFO(b, info);
+ DECLARE_SHTABLE_FROM_INFO(t, info);
+
+ /* step #0:
+ -------------------------------------------------------
+ get rid of the easy cases first:
+ - copying constants
+ - if not a proper process, do flat copy
+ */
+
+ if (IS_CONST(obj))
+ return obj;
+
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] copy_shared_perform %p\n", mypid, obj));
+
+ /* step #2: was performed before this function was called
+ -------------------------------------------------------
+ allocate new space
+ */
+
+ hscan = hp = *hpp;
+ hbot = hend = hp + size;
+
+ /* step #3:
+ -------------------------------------------------------
+ traverse the term a second time and when traversing:
+ a. if the object is marked as shared
+ a1. if the entry contains a forwarding ptr, use that
+ a2. otherwise, copy it to the new space and store the
+ forwarding ptr to the entry
+ b. otherwise, reverse-transform as you do in size_shared
+ and copy to the new space
+ */
+
+ resp = &result;
+ remaining = 0;
+ for (;;) {
+ switch (primary_tag(obj)) {
+ case TAG_PRIMARY_LIST: {
+ Eterm head, tail;
+ ptr = list_val(obj);
+ /* off heap list pointers are copied verbatim */
+ if (erts_is_literal(obj,ptr)) {
+ if (!IN_LITERAL_PURGE_AREA(info,ptr)) {
+ *resp = obj;
+ } else {
+ Uint bsz = 0;
+ *resp = copy_struct_x(obj, hbot - hp, &hp, off_heap, &bsz);
+ hbot -= bsz;
+ }
+ goto cleanup_next;
+ }
+ head = CAR(ptr);
+ tail = CDR(ptr);
+ /* if it is shared */
+ if (tail == THE_NON_VALUE) {
+ e = head >> _TAG_PRIMARY_SIZE;
+ /* if it has been processed, just use the forwarding pointer */
+ if (primary_tag(head) == LIST_SHARED_PROCESSED) {
+ *resp = make_list(SHTABLE_FWD(t, e));
+ goto cleanup_next;
+ }
+ /* else, let's process it now,
+ copy it and keep the forwarding pointer */
+ else {
+ CAR(ptr) = (head - primary_tag(head)) + LIST_SHARED_PROCESSED;
+ head = SHTABLE_X(t, e);
+ tail = SHTABLE_Y(t, e);
+ ptr = &(SHTABLE_X(t, e));
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] tabled L %p is %p\n", mypid, ptr, SHTABLE_REV(t, e)));
+ SHTABLE_FWD_UPD(t, e, hp);
+ }
+ }
+ /* if not already clean, clean it up and copy it */
+ if (primary_tag(tail) == TAG_PRIMARY_HEADER) {
+ if (primary_tag(head) == TAG_PRIMARY_HEADER) {
+ Eterm saved;
+ BITSTORE_FETCH(b, saved);
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] unmangling L/B %p\n", mypid, ptr));
+ CAR(ptr) = head = (head - TAG_PRIMARY_HEADER) + saved;
+ CDR(ptr) = tail = (tail - TAG_PRIMARY_HEADER) + TAG_PRIMARY_BOXED;
+ } else {
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] unmangling L/L %p\n", mypid, ptr));
+ CDR(ptr) = tail = (tail - TAG_PRIMARY_HEADER) + TAG_PRIMARY_LIST;
+ }
+ } else if (primary_tag(head) == TAG_PRIMARY_HEADER) {
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] unmangling L/I %p\n", mypid, ptr));
+ CAR(ptr) = head = (head - TAG_PRIMARY_HEADER) | primary_tag(tail);
+ CDR(ptr) = tail = (tail - primary_tag(tail)) | TAG_PRIMARY_IMMED1;
+ } else {
+ ASSERT(0 && "cannot come here");
+ goto cleanup_next;
+ }
+ /* and its children too */
+ if (IS_CONST(head)) {
+ CAR(hp) = head;
+ } else {
+ EQUEUE_PUT_UNCHECKED(s, head);
+ CAR(hp) = HEAP_ELEM_TO_BE_FILLED;
+ }
+ *resp = make_list(hp);
+ resp = &(CDR(hp));
+ hp += 2;
+ obj = tail;
+ break;
+ }
+ case TAG_PRIMARY_BOXED: {
+ Eterm hdr;
+ ptr = boxed_val(obj);
+ /* off heap pointers to boxes are copied verbatim */
+ if (erts_is_literal(obj,ptr)) {
+ if (!IN_LITERAL_PURGE_AREA(info,ptr)) {
+ *resp = obj;
+ } else {
+ Uint bsz = 0;
+ *resp = copy_struct_x(obj, hbot - hp, &hp, off_heap, &bsz);
+ hbot -= bsz;
+ }
+ goto cleanup_next;
+ }
+ hdr = *ptr;
+ /* clean it up, unless it's already clean or shared and processed */
+ switch (primary_tag(hdr)) {
+ case TAG_PRIMARY_HEADER:
+ ASSERT(0 && "cannot come here");
+ /* if it is shared and has been processed,
+ just use the forwarding pointer */
+ case BOXED_SHARED_PROCESSED:
+ e = hdr >> _TAG_PRIMARY_SIZE;
+ *resp = make_boxed(SHTABLE_FWD(t, e));
+ goto cleanup_next;
+ /* if it is shared but has not been processed yet, let's process
+ it now: copy it and keep the forwarding pointer */
+ case BOXED_SHARED_UNPROCESSED:
+ e = hdr >> _TAG_PRIMARY_SIZE;
+ *ptr = (hdr - primary_tag(hdr)) + BOXED_SHARED_PROCESSED;
+ hdr = SHTABLE_X(t, e);
+ ASSERT(primary_tag(hdr) == BOXED_VISITED);
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] tabled B %p is %p\n", mypid, ptr, SHTABLE_REV(t, e)));
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] unmangling B %p\n", mypid, ptr));
+ SHTABLE_X(t, e) = hdr = (hdr - BOXED_VISITED) + TAG_PRIMARY_HEADER;
+ SHTABLE_FWD_UPD(t, e, hp);
+ break;
+ case BOXED_VISITED:
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] unmangling B %p\n", mypid, ptr));
+ *ptr = hdr = (hdr - BOXED_VISITED) + TAG_PRIMARY_HEADER;
+ break;
+ }
+ /* and its children too */
+ switch (hdr & _TAG_HEADER_MASK) {
+ case ARITYVAL_SUBTAG: {
+ int arity = header_arity(hdr);
+ *resp = make_boxed(hp);
+ *hp++ = hdr;
+ while (arity-- > 0) {
+ obj = *++ptr;
+ if (IS_CONST(obj)) {
+ *hp++ = obj;
+ } else {
+ EQUEUE_PUT_UNCHECKED(s, obj);
+ *hp++ = HEAP_ELEM_TO_BE_FILLED;
+ }
+ }
+ goto cleanup_next;
+ }
+ case FUN_SUBTAG: {
+ ErlFunThing* funp = (ErlFunThing *) ptr;
+ unsigned eterms = 1 /* creator */ + funp->num_free;
+ sz = thing_arityval(hdr);
+ funp = (ErlFunThing *) hp;
+ *resp = make_fun(hp);
+ *hp++ = hdr;
+ ptr++;
+ while (sz-- > 0) {
+ *hp++ = *ptr++;
+ }
+ while (eterms-- > 0) {
+ obj = *ptr++;
+ if (IS_CONST(obj)) {
+ *hp++ = obj;
+ } else {
+ EQUEUE_PUT_UNCHECKED(s, obj);
+ *hp++ = HEAP_ELEM_TO_BE_FILLED;
+ }
+ }
+ funp->next = off_heap->first;
+ off_heap->first = (struct erl_off_heap_header*) funp;
+ erts_refc_inc(&funp->fe->refc, 2);
+ goto cleanup_next;
+ }
+ case MAP_SUBTAG:
+ *resp = make_flatmap(hp);
+ *hp++ = hdr;
+ switch (MAP_HEADER_TYPE(hdr)) {
+ case MAP_HEADER_TAG_FLATMAP_HEAD : {
+ flatmap_t *mp = (flatmap_t *) ptr;
+ Uint n = flatmap_get_size(mp) + 1;
+ *hp++ = *++ptr; /* keys */
+ while (n--) {
+ obj = *++ptr;
+ if (IS_CONST(obj)) {
+ *hp++ = obj;
+ } else {
+ EQUEUE_PUT_UNCHECKED(s, obj);
+ *hp++ = HEAP_ELEM_TO_BE_FILLED;
+ }
+ }
+ goto cleanup_next;
+ }
+ case MAP_HEADER_TAG_HAMT_HEAD_BITMAP :
+ case MAP_HEADER_TAG_HAMT_HEAD_ARRAY :
+ *hp++ = *++ptr; /* total map size */
+ case MAP_HEADER_TAG_HAMT_NODE_BITMAP : {
+ Uint n = hashmap_bitcount(MAP_HEADER_VAL(hdr));
+ while (n--) {
+ obj = *++ptr;
+ if (IS_CONST(obj)) {
+ *hp++ = obj;
+ } else {
+ EQUEUE_PUT_UNCHECKED(s, obj);
+ *hp++ = HEAP_ELEM_TO_BE_FILLED;
+ }
+ }
+ goto cleanup_next;
+ }
+ default:
+ erts_exit(ERTS_ABORT_EXIT, "copy_shared_perform: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr));
+ }
+ case REFC_BINARY_SUBTAG: {
+ ProcBin* pb = (ProcBin *) ptr;
+ sz = thing_arityval(hdr);
+ if (pb->flags) {
+ erts_emasculate_writable_binary(pb);
+ }
+ pb = (ProcBin *) hp;
+ *resp = make_binary(hp);
+ *hp++ = hdr;
+ ptr++;
+ while (sz-- > 0) {
+ *hp++ = *ptr++;
+ }
+ erts_refc_inc(&pb->val->refc, 2);
+ pb->next = off_heap->first;
+ pb->flags = 0;
+ off_heap->first = (struct erl_off_heap_header*) pb;
+ OH_OVERHEAD(off_heap, pb->size / sizeof(Eterm));
+ goto cleanup_next;
+ }
+ case SUB_BINARY_SUBTAG: {
+ ErlSubBin* sb = (ErlSubBin *) ptr;
+ Eterm real_bin = sb->orig;
+ Uint bit_offset = sb->bitoffs;
+ Uint bit_size = sb->bitsize;
+ Uint offset = sb->offs;
+ size_t size = sb->size;
+ Uint extra_bytes;
+ Uint real_size;
+ if ((bit_size + bit_offset) > 8) {
+ extra_bytes = 2;
+ } else if ((bit_size + bit_offset) > 0) {
+ extra_bytes = 1;
+ } else {
+ extra_bytes = 0;
+ }
+ real_size = size+extra_bytes;
+ ASSERT(is_boxed(real_bin) &&
+ (((*boxed_val(real_bin)) &
+ (_TAG_HEADER_MASK - _BINARY_XXX_MASK - BOXED_VISITED_MASK))
+ == _TAG_HEADER_REFC_BIN));
+ ptr = _unchecked_binary_val(real_bin);
+ *resp = make_binary(hp);
+ if (extra_bytes != 0) {
+ ErlSubBin* res = (ErlSubBin *) hp;
+ hp += ERL_SUB_BIN_SIZE;
+ res->thing_word = HEADER_SUB_BIN;
+ res->size = size;
+ res->bitsize = bit_size;
+ res->bitoffs = bit_offset;
+ res->offs = 0;
+ res->is_writable = 0;
+ res->orig = make_binary(hp);
+ }
+ if (thing_subtag(*ptr & ~BOXED_VISITED_MASK) == HEAP_BINARY_SUBTAG) {
+ ErlHeapBin* from = (ErlHeapBin *) ptr;
+ ErlHeapBin* to = (ErlHeapBin *) hp;
+ hp += heap_bin_size(real_size);
+ to->thing_word = header_heap_bin(real_size);
+ to->size = real_size;
+ sys_memcpy(to->data, ((byte *)from->data)+offset, real_size);
+ } else {
+ ProcBin* from = (ProcBin *) ptr;
+ ProcBin* to = (ProcBin *) hp;
+ ASSERT(thing_subtag(*ptr & ~BOXED_VISITED_MASK) == REFC_BINARY_SUBTAG);
+ if (from->flags) {
+ erts_emasculate_writable_binary(from);
+ }
+ hp += PROC_BIN_SIZE;
+ to->thing_word = HEADER_PROC_BIN;
+ to->size = real_size;
+ to->val = from->val;
+ erts_refc_inc(&to->val->refc, 2);
+ to->bytes = from->bytes + offset;
+ to->next = off_heap->first;
+ to->flags = 0;
+ off_heap->first = (struct erl_off_heap_header*) to;
+ OH_OVERHEAD(off_heap, to->size / sizeof(Eterm));
+ }
+ goto cleanup_next;
+ }
+ case EXTERNAL_PID_SUBTAG:
+ case EXTERNAL_PORT_SUBTAG:
+ case EXTERNAL_REF_SUBTAG: {
+ ExternalThing *etp = (ExternalThing *) hp;
+ sz = thing_arityval(hdr);
+ *resp = make_external(hp);
+ *hp++ = hdr;
+ ptr++;
+ while (sz-- > 0) {
+ *hp++ = *ptr++;
+ }
+ etp->next = off_heap->first;
+ off_heap->first = (struct erl_off_heap_header*) etp;
+ erts_refc_inc(&etp->node->refc, 2);
+ goto cleanup_next;
+ }
+ default:
+ sz = thing_arityval(hdr);
+ *resp = make_boxed(hp);
+ *hp++ = hdr;
+ ptr++;
+ while (sz-- > 0) {
+ *hp++ = *ptr++;
+ }
+ goto cleanup_next;
+ }
+ break;
+ }
+ case TAG_PRIMARY_IMMED1:
+ *resp = obj;
+ cleanup_next:
+ if (EQUEUE_ISEMPTY(s)) {
+ goto all_clean;
+ }
+ obj = EQUEUE_GET(s);
+ for (;;) {
+ ASSERT(hscan < hp);
+ if (remaining == 0) {
+ if (*hscan == HEAP_ELEM_TO_BE_FILLED) {
+ resp = hscan;
+ hscan += 2;
+ break; /* scanning loop */
+ } else if (primary_tag(*hscan) == TAG_PRIMARY_HEADER) {
+ switch (*hscan & _TAG_HEADER_MASK) {
+ case ARITYVAL_SUBTAG:
+ remaining = header_arity(*hscan);
+ hscan++;
+ break;
+ case FUN_SUBTAG: {
+ ErlFunThing* funp = (ErlFunThing *) hscan;
+ hscan += 1 + thing_arityval(*hscan);
+ remaining = 1 + funp->num_free;
+ break;
+ }
+ case MAP_SUBTAG:
+ switch (MAP_HEADER_TYPE(*hscan)) {
+ case MAP_HEADER_TAG_FLATMAP_HEAD : {
+ flatmap_t *mp = (flatmap_t *) hscan;
+ remaining = flatmap_get_size(mp) + 1;
+ hscan += 2;
+ break;
+ }
+ case MAP_HEADER_TAG_HAMT_HEAD_BITMAP :
+ case MAP_HEADER_TAG_HAMT_HEAD_ARRAY :
+ case MAP_HEADER_TAG_HAMT_NODE_BITMAP :
+ remaining = hashmap_bitcount(MAP_HEADER_VAL(*hscan));
+ hscan += MAP_HEADER_ARITY(*hscan) + 1;
+ break;
+ default:
+ erts_exit(ERTS_ABORT_EXIT,
+ "copy_shared_perform: bad hashmap type %d\n",
+ MAP_HEADER_TYPE(*hscan));
+ }
+ break;
+ case SUB_BINARY_SUBTAG:
+ ASSERT(((ErlSubBin *) hscan)->bitoffs +
+ ((ErlSubBin *) hscan)->bitsize > 0);
+ hscan += ERL_SUB_BIN_SIZE;
+ break;
+ default:
+ hscan += 1 + thing_arityval(*hscan);
+ break;
+ }
+ } else {
+ hscan++;
+ }
+ } else if (*hscan == HEAP_ELEM_TO_BE_FILLED) {
+ resp = hscan++;
+ remaining--;
+ break; /* scanning loop */
+ } else {
+ hscan++;
+ remaining--;
+ }
+ }
+ ASSERT(resp < hp);
+ break;
+ default:
+ erts_exit(ERTS_ABORT_EXIT, "size_shared: bad tag for %#x\n", obj);
+ }
+ }
+
+ /* step #4:
+ -------------------------------------------------------
+ traverse the table and reverse-transform all stored entries
+ */
+
+all_clean:
+ for (e = 0; ; e += SHTABLE_INCR) {
+ ptr = SHTABLE_REV(t, e);
+ if (ptr == NULL)
+ break;
+ VERBOSE(DEBUG_SHCOPY, ("[copy] restoring shared: %x\n", ptr));
+ /* entry was a list */
+ if (SHTABLE_Y(t, e) != THE_NON_VALUE) {
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] untabling L %p\n", mypid, ptr));
+ CAR(ptr) = SHTABLE_X(t, e);
+ CDR(ptr) = SHTABLE_Y(t, e);
+ }
+ /* entry was boxed */
+ else {
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] untabling B %p\n", mypid, ptr));
+ *ptr = SHTABLE_X(t, e);
+ ASSERT(primary_tag(*ptr) == TAG_PRIMARY_HEADER);
+ }
+ }
+
+#ifdef DEBUG
+ if (eq(saved_obj, result) == 0) {
+ erts_fprintf(stderr, "original = %T\n", saved_obj);
+ erts_fprintf(stderr, "copy = %T\n", result);
+ erts_exit(ERTS_ABORT_EXIT, "copy (shared) not equal to source\n");
+ }
+#endif
+
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] original was %T\n", mypid, saved_obj));
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] copy is %T\n", mypid, result));
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] result is at %p\n", mypid, result));
+
+ ASSERT(hbot == hp);
+ ASSERT(size == ((hp - *hpp) + (hend - hbot)));
+ *hpp = hend;
+ return result;
+}
+
+
/*
* Copy a term that is guaranteed to be contained in a single
* heap block. The heap block is copied word by word, and any
@@ -563,21 +1768,12 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
*
* NOTE: Assumes that term is a tuple (ptr is an untagged tuple ptr).
*/
-#if HALFWORD_HEAP
-Eterm copy_shallow_rel(Eterm* ptr, Uint sz, Eterm** hpp, ErlOffHeap* off_heap,
- Eterm* src_base)
-#else
Eterm copy_shallow(Eterm* ptr, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
-#endif
{
Eterm* tp = ptr;
Eterm* hp = *hpp;
const Eterm res = make_tuple(hp);
-#if HALFWORD_HEAP
- const Sint offs = COMPRESS_POINTER(hp - (tp - src_base));
-#else
const Sint offs = (hp - tp) * sizeof(Eterm);
-#endif
while (sz--) {
Eterm val = *tp++;
@@ -652,17 +1848,24 @@ Eterm copy_shallow(Eterm* ptr, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
* move markers.
* Typically used to copy a multi-fragmented message (from NIF).
*/
-void move_multi_frags(Eterm** hpp, ErlOffHeap* off_heap, ErlHeapFragment* first,
- Eterm* refs, unsigned nrefs)
+void erts_move_multi_frags(Eterm** hpp, ErlOffHeap* off_heap, ErlHeapFragment* first,
+ Eterm* refs, unsigned nrefs, int literals)
{
ErlHeapFragment* bp;
Eterm* hp_start = *hpp;
Eterm* hp_end;
Eterm* hp;
unsigned i;
+ Eterm literal_tag;
+
+#ifdef TAG_LITERAL_PTR
+ literal_tag = (Eterm) literals ? TAG_LITERAL_PTR : 0;
+#else
+ literal_tag = (Eterm) 0;
+#endif
for (bp=first; bp!=NULL; bp=bp->next) {
- move_one_frag(hpp, bp, off_heap);
+ move_one_frag(hpp, bp, off_heap, literals);
}
hp_end = *hpp;
for (hp=hp_start; hp<hp_end; ++hp) {
@@ -675,6 +1878,9 @@ void move_multi_frags(Eterm** hpp, ErlOffHeap* off_heap, ErlHeapFragment* first,
val = *ptr;
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
+#ifdef TAG_LITERAL_PTR
+ val |= literal_tag;
+#endif
*hp = val;
}
break;
@@ -682,7 +1888,11 @@ void move_multi_frags(Eterm** hpp, ErlOffHeap* off_heap, ErlHeapFragment* first,
ptr = list_val(gval);
val = *ptr;
if (IS_MOVED_CONS(val)) {
- *hp = ptr[1];
+ val = ptr[1];
+#ifdef TAG_LITERAL_PTR
+ val |= literal_tag;
+#endif
+ *hp = val;
}
break;
case TAG_PRIMARY_HEADER:
@@ -693,12 +1903,12 @@ void move_multi_frags(Eterm** hpp, ErlOffHeap* off_heap, ErlHeapFragment* first,
}
}
for (i=0; i<nrefs; ++i) {
- refs[i] = follow_moved(refs[i]);
+ refs[i] = follow_moved(refs[i], literal_tag);
}
}
static void
-move_one_frag(Eterm** hpp, ErlHeapFragment* frag, ErlOffHeap* off_heap)
+move_one_frag(Eterm** hpp, ErlHeapFragment* frag, ErlOffHeap* off_heap, int literals)
{
Eterm* ptr = frag->mem;
Eterm* end = ptr + frag->used_size;
@@ -735,4 +1945,3 @@ move_one_frag(Eterm** hpp, ErlHeapFragment* frag, ErlOffHeap* off_heap)
OH_OVERHEAD(off_heap, frag->off_heap.overhead);
frag->off_heap.first = NULL;
}
-
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 787241b960..fa385f105d 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -378,10 +378,11 @@ static void doit_node_link_net_exits(ErtsLink *lnk, void *vnecp)
ASSERT(lnk->type == LINK_NODE);
if (is_internal_pid(lnk->pid)) {
ErtsProcLocks rp_locks = ERTS_PROC_LOCK_LINK;
- rp = erts_pid2proc(NULL, 0, lnk->pid, rp_locks);
- if (!rp) {
+ ErlOffHeap *ohp;
+ rp = erts_proc_lookup(lnk->pid);
+ if (!rp)
goto done;
- }
+ erts_smp_proc_lock(rp, rp_locks);
rlnk = erts_remove_link(&ERTS_P_LINKS(rp), name);
if (rlnk != NULL) {
ASSERT(is_atom(rlnk->pid) && (rlnk->type == LINK_NODE));
@@ -389,12 +390,14 @@ static void doit_node_link_net_exits(ErtsLink *lnk, void *vnecp)
}
n = ERTS_LINK_REFC(lnk);
for (i = 0; i < n; ++i) {
- ErlHeapFragment* bp;
- ErlOffHeap *ohp;
Eterm tup;
- Eterm *hp = erts_alloc_message_heap(3,&bp,&ohp,rp,&rp_locks);
+ Eterm *hp;
+ ErtsMessage *msgp;
+
+ msgp = erts_alloc_message_heap(rp, &rp_locks,
+ 3, &hp, &ohp);
tup = TUPLE2(hp, am_nodedown, name);
- erts_queue_message(rp, &rp_locks, bp, tup, NIL);
+ erts_queue_message(rp, &rp_locks, msgp, tup, NIL);
}
erts_smp_proc_unlock(rp, rp_locks);
}
@@ -737,19 +740,11 @@ Eterm erts_dsend_export_trap_context(Process* p, ErtsSendContext* ctx)
Binary* ctx_bin = erts_create_magic_binary(sizeof(struct exported_ctx),
erts_dsend_context_dtor);
struct exported_ctx* dst = ERTS_MAGIC_BIN_DATA(ctx_bin);
- Uint ctl_size = !HALFWORD_HEAP ? 0 : (arityval(ctx->ctl_heap[0]) + 1);
- Eterm* hp = HAlloc(p, ctl_size + PROC_BIN_SIZE);
+ Eterm* hp = HAlloc(p, PROC_BIN_SIZE);
sys_memcpy(&dst->ctx, ctx, sizeof(ErtsSendContext));
ASSERT(ctx->dss.ctl == make_tuple(ctx->ctl_heap));
-#if !HALFWORD_HEAP
dst->ctx.dss.ctl = make_tuple(dst->ctx.ctl_heap);
-#else
- /* Must put control tuple in low mem */
- sys_memcpy(hp, ctx->ctl_heap, ctl_size*sizeof(Eterm));
- dst->ctx.dss.ctl = make_tuple(hp);
- hp += ctl_size;
-#endif
if (ctx->dss.acmp) {
sys_memcpy(&dst->acm, ctx->dss.acmp, sizeof(ErtsAtomCacheMap));
dst->ctx.dss.acmp = &dst->acm;
@@ -886,11 +881,7 @@ erts_dsig_send_msg(Eterm remote, Eterm message, ErtsSendContext* ctx)
DTRACE_CHARBUF(receiver_name, 64);
#endif
- if (SEQ_TRACE_TOKEN(sender) != NIL
-#ifdef USE_VM_PROBES
- && SEQ_TRACE_TOKEN(sender) != am_have_dt_utag
-#endif
- ) {
+ if (have_seqtrace(SEQ_TRACE_TOKEN(sender))) {
seq_trace_update_send(sender);
token = SEQ_TRACE_TOKEN(sender);
seq_trace_output(token, message, SEQ_TRACE_SEND, remote, sender);
@@ -905,7 +896,7 @@ erts_dsig_send_msg(Eterm remote, Eterm message, ErtsSendContext* ctx)
erts_snprintf(receiver_name, sizeof(DTRACE_CHARBUF_NAME(receiver_name)),
"%T", remote);
msize = size_object(message);
- if (token != NIL && token != am_have_dt_utag) {
+ if (have_seqtrace(token)) {
tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
@@ -947,11 +938,7 @@ erts_dsig_send_reg_msg(Eterm remote_name, Eterm message,
DTRACE_CHARBUF(receiver_name, 128);
#endif
- if (SEQ_TRACE_TOKEN(sender) != NIL
-#ifdef USE_VM_PROBES
- && SEQ_TRACE_TOKEN(sender) != am_have_dt_utag
-#endif
- ) {
+ if (have_seqtrace(SEQ_TRACE_TOKEN(sender))) {
seq_trace_update_send(sender);
token = SEQ_TRACE_TOKEN(sender);
seq_trace_output(token, message, SEQ_TRACE_SEND, remote_name, sender);
@@ -966,7 +953,7 @@ erts_dsig_send_reg_msg(Eterm remote_name, Eterm message,
erts_snprintf(receiver_name, sizeof(DTRACE_CHARBUF_NAME(receiver_name)),
"{%T,%s}", remote_name, node_name);
msize = size_object(message);
- if (token != NIL && token != am_have_dt_utag) {
+ if (have_seqtrace(token)) {
tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
@@ -1011,11 +998,7 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote,
#endif
UseTmpHeapNoproc(6);
- if (token != NIL
-#ifdef USE_VM_PROBES
- && token != am_have_dt_utag
-#endif
- ) {
+ if (have_seqtrace(token)) {
seq_trace_update_send(dsdp->proc);
seq_trace_output_exit(token, reason, SEQ_TRACE_SEND, remote, local);
ctl = TUPLE5(&ctl_heap[0],
@@ -1034,7 +1017,7 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote,
"{%T,%s}", remote, node_name);
erts_snprintf(reason_str, sizeof(DTRACE_CHARBUF_NAME(reason_str)),
"%T", reason);
- if (token != NIL && token != am_have_dt_utag) {
+ if (have_seqtrace(token)) {
tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
@@ -1466,7 +1449,7 @@ int erts_net_message(Port *prt,
ErlOffHeap *ohp;
ASSERT(xsize);
heap_frag = erts_dist_ext_trailer(ede_copy);
- ERTS_INIT_HEAP_FRAG(heap_frag, token_size);
+ ERTS_INIT_HEAP_FRAG(heap_frag, token_size, token_size);
hp = heap_frag->mem;
ohp = &heap_frag->off_heap;
token = tuple[5];
@@ -1515,7 +1498,7 @@ int erts_net_message(Port *prt,
ErlOffHeap *ohp;
ASSERT(xsize);
heap_frag = erts_dist_ext_trailer(ede_copy);
- ERTS_INIT_HEAP_FRAG(heap_frag, token_size);
+ ERTS_INIT_HEAP_FRAG(heap_frag, token_size, token_size);
hp = heap_frag->mem;
ohp = &heap_frag->off_heap;
token = tuple[4];
@@ -2062,9 +2045,9 @@ dist_port_commandv(Port *prt, ErtsDistOutputBuf *obuf)
}
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
#define ERTS_PORT_REDS_MASK__ 0x003fffffffffffffL
-#elif defined(ARCH_32) || HALFWORD_HEAP
+#elif defined(ARCH_32)
#define ERTS_PORT_REDS_MASK__ 0x003fffff
#else
# error "Ohh come on ... !?!"
@@ -3275,11 +3258,16 @@ send_nodes_mon_msg(Process *rp,
Uint sz)
{
Eterm msg;
- ErlHeapFragment* bp;
+ Eterm *hp;
+ ErtsMessage *mp;
ErlOffHeap *ohp;
- Eterm *hp = erts_alloc_message_heap(sz, &bp, &ohp, rp, rp_locksp);
#ifdef DEBUG
- Eterm *hend = hp + sz;
+ Eterm *hend;
+#endif
+
+ mp = erts_alloc_message_heap(rp, rp_locksp, sz, &hp, &ohp);
+#ifdef DEBUG
+ hend = hp + sz;
#endif
if (!nmp->opts) {
@@ -3325,7 +3313,7 @@ send_nodes_mon_msg(Process *rp,
}
ASSERT(hend == hp);
- erts_queue_message(rp, rp_locksp, bp, msg, NIL);
+ erts_queue_message(rp, rp_locksp, mp, msg, NIL);
}
static void
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index 0877c24404..490e0c0915 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -103,9 +103,9 @@ static Uint install_debug_functions(void);
static int lock_all_physical_memory = 0;
-ErtsAllocatorFunctions_t erts_allctrs[ERTS_ALC_A_MAX+1];
+ErtsAllocatorFunctions_t ERTS_WRITE_UNLIKELY(erts_allctrs[ERTS_ALC_A_MAX+1]);
ErtsAllocatorInfo_t erts_allctrs_info[ERTS_ALC_A_MAX+1];
-ErtsAllocatorThrSpec_t erts_allctr_thr_spec[ERTS_ALC_A_MAX+1];
+ErtsAllocatorThrSpec_t ERTS_WRITE_UNLIKELY(erts_allctr_thr_spec[ERTS_ALC_A_MAX+1]);
#define ERTS_MIN(A, B) ((A) < (B) ? (A) : (B))
#define ERTS_MAX(A, B) ((A) > (B) ? (A) : (B))
@@ -123,10 +123,6 @@ typedef union {
static ErtsAllocatorState_t std_alloc_state;
static ErtsAllocatorState_t ll_alloc_state;
-#if HALFWORD_HEAP
-static ErtsAllocatorState_t std_low_alloc_state;
-static ErtsAllocatorState_t ll_low_alloc_state;
-#endif
static ErtsAllocatorState_t sl_alloc_state;
static ErtsAllocatorState_t temp_alloc_state;
static ErtsAllocatorState_t eheap_alloc_state;
@@ -134,6 +130,7 @@ static ErtsAllocatorState_t binary_alloc_state;
static ErtsAllocatorState_t ets_alloc_state;
static ErtsAllocatorState_t driver_alloc_state;
static ErtsAllocatorState_t fix_alloc_state;
+static ErtsAllocatorState_t literal_alloc_state;
static ErtsAllocatorState_t test_alloc_state;
typedef struct {
@@ -151,24 +148,10 @@ typedef struct {
#define ERTS_ALC_INFO_A_MSEG_ALLOC (ERTS_ALC_A_MAX + 2)
#define ERTS_ALC_INFO_A_MAX ERTS_ALC_INFO_A_MSEG_ALLOC
-#if !HALFWORD_HEAP
ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(aireq,
- ErtsAllocInfoReq,
- 5,
- ERTS_ALC_T_AINFO_REQ)
-#else
-static ERTS_INLINE ErtsAllocInfoReq *
-aireq_alloc(void)
-{
- return erts_alloc(ERTS_ALC_T_AINFO_REQ, sizeof(ErtsAllocInfoReq));
-}
-
-static ERTS_INLINE void
-aireq_free(ErtsAllocInfoReq *ptr)
-{
- erts_free(ERTS_ALC_T_AINFO_REQ, ptr);
-}
-#endif
+ ErtsAllocInfoReq,
+ 5,
+ ERTS_ALC_T_AINFO_REQ)
ErtsAlcType_t erts_fix_core_allocator_ix;
@@ -182,6 +165,8 @@ enum allctr_type {
struct au_init {
int enable;
int thr_spec;
+ int disable_allowed;
+ int thr_spec_allowed;
int carrier_migration_allowed;
enum allctr_type atype;
struct {
@@ -230,14 +215,11 @@ typedef struct {
struct au_init ets_alloc;
struct au_init driver_alloc;
struct au_init fix_alloc;
-#if HALFWORD_HEAP
- struct au_init std_low_alloc;
- struct au_init ll_low_alloc;
-#endif
+ struct au_init literal_alloc;
struct au_init test_alloc;
} erts_alc_hndl_args_init_t;
-#define ERTS_AU_INIT__ {0, 0, 1, GOODFIT, DEFAULT_ALLCTR_INIT, {1,1,1,1}}
+#define ERTS_AU_INIT__ {0, 0, 1, 1, 1, GOODFIT, DEFAULT_ALLCTR_INIT, {1,1,1,1}}
#define SET_DEFAULT_ALLOC_OPTS(IP) \
do { \
@@ -261,10 +243,6 @@ set_default_sl_alloc_opts(struct au_init *ip)
#endif
ip->init.util.ts = ERTS_ALC_MTA_SHORT_LIVED;
ip->init.util.rsbcst = 80;
-#if HALFWORD_HEAP
- ip->init.util.force = 1;
- ip->init.util.low_mem = 1;
-#endif
ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
}
@@ -300,9 +278,9 @@ set_default_ll_alloc_opts(struct au_init *ip)
ip->init.util.name_prefix = "ll_";
ip->init.util.alloc_no = ERTS_ALC_A_LONG_LIVED;
#ifndef SMALL_MEMORY
- ip->init.util.mmbcs = 2*1024*1024 - 40; /* Main carrier size */
+ ip->init.util.mmbcs = 2*1024*1024; /* Main carrier size */
#else
- ip->init.util.mmbcs = 1*1024*1024 - 40; /* Main carrier size */
+ ip->init.util.mmbcs = 1*1024*1024; /* Main carrier size */
#endif
ip->init.util.ts = ERTS_ALC_MTA_LONG_LIVED;
ip->init.util.asbcst = 0;
@@ -313,6 +291,54 @@ set_default_ll_alloc_opts(struct au_init *ip)
}
static void
+set_default_literal_alloc_opts(struct au_init *ip)
+{
+ SET_DEFAULT_ALLOC_OPTS(ip);
+ ip->enable = 1;
+ ip->thr_spec = 0;
+ ip->disable_allowed = 0;
+ ip->thr_spec_allowed = 0;
+ ip->carrier_migration_allowed = 0;
+ ip->atype = BESTFIT;
+ ip->init.bf.ao = 1;
+ ip->init.util.ramv = 0;
+ ip->init.util.mmsbc = 0;
+ ip->init.util.sbct = ~((UWord) 0);
+ ip->init.util.name_prefix = "literal_";
+ ip->init.util.alloc_no = ERTS_ALC_A_LITERAL;
+#ifndef SMALL_MEMORY
+ ip->init.util.mmbcs = 2*1024*1024; /* Main carrier size */
+#else
+ ip->init.util.mmbcs = 1*1024*1024; /* Main carrier size */
+#endif
+ ip->init.util.ts = ERTS_ALC_MTA_LITERAL;
+ ip->init.util.asbcst = 0;
+ ip->init.util.rsbcst = 0;
+ ip->init.util.rsbcmt = 0;
+ ip->init.util.rmbcmt = 0;
+ ip->init.util.acul = 0;
+
+#if defined(ARCH_32)
+# if HAVE_ERTS_MSEG
+ ip->init.util.mseg_alloc = &erts_alcu_literal_32_mseg_alloc;
+ ip->init.util.mseg_realloc = &erts_alcu_literal_32_mseg_realloc;
+ ip->init.util.mseg_dealloc = &erts_alcu_literal_32_mseg_dealloc;
+# endif
+ ip->init.util.sys_alloc = &erts_alcu_literal_32_sys_alloc;
+ ip->init.util.sys_realloc = &erts_alcu_literal_32_sys_realloc;
+ ip->init.util.sys_dealloc = &erts_alcu_literal_32_sys_dealloc;
+#elif defined(ARCH_64)
+# ifdef ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION
+ ip->init.util.mseg_alloc = &erts_alcu_literal_64_mseg_alloc;
+ ip->init.util.mseg_realloc = &erts_alcu_literal_64_mseg_realloc;
+ ip->init.util.mseg_dealloc = &erts_alcu_literal_64_mseg_dealloc;
+# endif
+#else
+# error Unknown architecture
+#endif
+}
+
+static void
set_default_temp_alloc_opts(struct au_init *ip)
{
SET_DEFAULT_ALLOC_OPTS(ip);
@@ -330,10 +356,6 @@ set_default_temp_alloc_opts(struct au_init *ip)
ip->init.util.ts = ERTS_ALC_MTA_TEMPORARY;
ip->init.util.rsbcst = 90;
ip->init.util.rmbcmt = 100;
-#if HALFWORD_HEAP
- ip->init.util.force = 1;
- ip->init.util.low_mem = 1;
-#endif
}
static void
@@ -352,10 +374,6 @@ set_default_eheap_alloc_opts(struct au_init *ip)
#endif
ip->init.util.ts = ERTS_ALC_MTA_EHEAP;
ip->init.util.rsbcst = 50;
-#if HALFWORD_HEAP
- ip->init.util.force = 1;
- ip->init.util.low_mem = 1;
-#endif
ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL_EHEAP_ALLOC;
}
@@ -589,18 +607,16 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_PROC)]
= sizeof(Process);
-#if !HALFWORD_HEAP
fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MONITOR_SH)]
= ERTS_MONITOR_SH_SIZE * sizeof(Uint);
fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_NLINK_SH)]
= ERTS_LINK_SH_SIZE * sizeof(Uint);
-#endif
fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_DRV_EV_D_STATE)]
= sizeof(ErtsDrvEventDataState);
fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_DRV_SEL_D_STATE)]
= sizeof(ErtsDrvSelectDataState);
fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MSG_REF)]
- = sizeof(ErlMessage);
+ = sizeof(ErtsMessageRef);
#ifdef ERTS_SMP
fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_THR_Q_EL_SL)]
= sizeof(ErtsThrQElement_t);
@@ -642,6 +658,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
set_default_driver_alloc_opts(&init.driver_alloc);
set_default_fix_alloc_opts(&init.fix_alloc,
fix_type_sizes);
+ set_default_literal_alloc_opts(&init.literal_alloc);
set_default_test_alloc_opts(&init.test_alloc);
if (argc && argv)
@@ -670,6 +687,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
init.ets_alloc.thr_spec = 0;
init.driver_alloc.thr_spec = 0;
init.fix_alloc.thr_spec = 0;
+ init.literal_alloc.thr_spec = 0;
#endif
/* Make adjustments for carrier migration support */
@@ -682,6 +700,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
adjust_carrier_migration_support(&init.ets_alloc);
adjust_carrier_migration_support(&init.driver_alloc);
adjust_carrier_migration_support(&init.fix_alloc);
+ adjust_carrier_migration_support(&init.literal_alloc);
if (init.erts_alloc_config) {
/* Adjust flags that erts_alloc_config won't like */
@@ -696,6 +715,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
init.ets_alloc.thr_spec = 0;
init.driver_alloc.thr_spec = 0;
init.fix_alloc.thr_spec = 0;
+ init.literal_alloc.thr_spec = 0;
/* No carrier migration */
init.temp_alloc.init.util.acul = 0;
@@ -707,6 +727,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
init.ets_alloc.init.util.acul = 0;
init.driver_alloc.init.util.acul = 0;
init.fix_alloc.init.util.acul = 0;
+ init.literal_alloc.init.util.acul = 0;
}
#ifdef ERTS_SMP
@@ -723,6 +744,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
adjust_tpref(&init.ets_alloc, erts_no_schedulers);
adjust_tpref(&init.driver_alloc, erts_no_schedulers);
adjust_tpref(&init.fix_alloc, erts_no_schedulers);
+ adjust_tpref(&init.literal_alloc, erts_no_schedulers);
#else
/* No thread specific if not smp */
@@ -741,6 +763,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
refuse_af_strategy(&init.ets_alloc);
refuse_af_strategy(&init.driver_alloc);
refuse_af_strategy(&init.fix_alloc);
+ refuse_af_strategy(&init.literal_alloc);
#ifdef ERTS_SMP
if (!init.temp_alloc.thr_spec)
@@ -775,24 +798,6 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
erts_allctrs[ERTS_ALC_A_SYSTEM].free = erts_sys_free;
erts_allctrs_info[ERTS_ALC_A_SYSTEM].enabled = 1;
-#if HALFWORD_HEAP
- /* Init low memory variants by cloning */
- init.std_low_alloc = init.std_alloc;
- init.std_low_alloc.init.util.name_prefix = "std_low_";
- init.std_low_alloc.init.util.alloc_no = ERTS_ALC_A_STANDARD_LOW;
- init.std_low_alloc.init.util.force = 1;
- init.std_low_alloc.init.util.low_mem = 1;
-
- init.ll_low_alloc = init.ll_alloc;
- init.ll_low_alloc.init.util.name_prefix = "ll_low_";
- init.ll_low_alloc.init.util.alloc_no = ERTS_ALC_A_LONG_LIVED_LOW;
- init.ll_low_alloc.init.util.force = 1;
- init.ll_low_alloc.init.util.low_mem = 1;
-
- set_au_allocator(ERTS_ALC_A_STANDARD_LOW, &init.std_low_alloc, ncpu);
- set_au_allocator(ERTS_ALC_A_LONG_LIVED_LOW, &init.ll_low_alloc, ncpu);
-#endif /* HALFWORD */
-
set_au_allocator(ERTS_ALC_A_TEMPORARY, &init.temp_alloc, ncpu);
set_au_allocator(ERTS_ALC_A_SHORT_LIVED, &init.sl_alloc, ncpu);
set_au_allocator(ERTS_ALC_A_STANDARD, &init.std_alloc, ncpu);
@@ -802,6 +807,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
set_au_allocator(ERTS_ALC_A_ETS, &init.ets_alloc, ncpu);
set_au_allocator(ERTS_ALC_A_DRIVER, &init.driver_alloc, ncpu);
set_au_allocator(ERTS_ALC_A_FIXED_SIZE, &init.fix_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_LITERAL, &init.literal_alloc, ncpu);
set_au_allocator(ERTS_ALC_A_TEST, &init.test_alloc, ncpu);
for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
@@ -836,14 +842,6 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
start_au_allocator(ERTS_ALC_A_LONG_LIVED,
&init.ll_alloc,
&ll_alloc_state);
-#if HALFWORD_HEAP
- start_au_allocator(ERTS_ALC_A_LONG_LIVED_LOW,
- &init.ll_low_alloc,
- &ll_low_alloc_state);
- start_au_allocator(ERTS_ALC_A_STANDARD_LOW,
- &init.std_low_alloc,
- &std_low_alloc_state);
-#endif
start_au_allocator(ERTS_ALC_A_EHEAP,
&init.eheap_alloc,
&eheap_alloc_state);
@@ -863,6 +861,9 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
start_au_allocator(ERTS_ALC_A_FIXED_SIZE,
&init.fix_alloc,
&fix_alloc_state);
+ start_au_allocator(ERTS_ALC_A_LITERAL,
+ &init.literal_alloc,
+ &literal_alloc_state);
start_au_allocator(ERTS_ALC_A_TEST,
&init.test_alloc,
@@ -871,9 +872,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
erts_mtrace_install_wrapper_functions();
extra_block_size += erts_instr_init(init.instr.stat, init.instr.map);
-#if !HALFWORD_HEAP
init_aireq_alloc();
-#endif
#ifdef DEBUG
extra_block_size += install_debug_functions();
@@ -971,6 +970,10 @@ set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init, int ncpu)
else
#endif
{
+#ifdef ERTS_SMP
+ erts_exit(ERTS_ABORT_EXIT, "%salloc is not thread safe\n",
+ init->init.util.name_prefix);
+#else
af->alloc = erts_alcu_alloc;
if (init->init.util.fix_type_size)
af->realloc = erts_realloc_fixed_size;
@@ -979,6 +982,7 @@ set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init, int ncpu)
else
af->realloc = erts_alcu_realloc;
af->free = erts_alcu_free;
+#endif
}
af->extra = NULL;
ai->alloc_util = 1;
@@ -1051,7 +1055,7 @@ start_au_allocator(ErtsAlcType_t alctr_n,
}
for (i = 0; i < size; i++) {
- void *as;
+ Allctr_t *as;
atype = init->atype;
if (!init->thr_spec)
@@ -1088,22 +1092,22 @@ start_au_allocator(ErtsAlcType_t alctr_n,
switch (atype) {
case GOODFIT:
- as = (void *) erts_gfalc_start((GFAllctr_t *) as0,
+ as = erts_gfalc_start((GFAllctr_t *) as0,
&init->init.gf,
&init->init.util);
break;
case BESTFIT:
- as = (void *) erts_bfalc_start((BFAllctr_t *) as0,
+ as = erts_bfalc_start((BFAllctr_t *) as0,
&init->init.bf,
&init->init.util);
break;
case AFIT:
- as = (void *) erts_afalc_start((AFAllctr_t *) as0,
+ as = erts_afalc_start((AFAllctr_t *) as0,
&init->init.af,
&init->init.util);
break;
case AOFIRSTFIT:
- as = (void *) erts_aoffalc_start((AOFFAllctr_t *) as0,
+ as = erts_aoffalc_start((AOFFAllctr_t *) as0,
&init->init.aoff,
&init->init.util);
break;
@@ -1273,9 +1277,6 @@ get_acul_value(struct au_init *auip, char *param_end, char** argv, int* ip)
if (sys_strcmp(value, "de") == 0) {
switch (auip->init.util.alloc_no) {
case ERTS_ALC_A_LONG_LIVED:
-#if HALFWORD_HEAP
- case ERTS_ALC_A_LONG_LIVED_LOW:
-#endif
return ERTS_ALC_DEFAULT_ENABLED_ACUL_LL_ALLOC;
case ERTS_ALC_A_EHEAP:
return ERTS_ALC_DEFAULT_ENABLED_ACUL_EHEAP_ALLOC;
@@ -1353,9 +1354,17 @@ handle_au_arg(struct au_init *auip,
else
goto bad_switch;
break;
- case 'e':
- auip->enable = get_bool_value(sub_param+1, argv, ip);
+ case 'e': {
+ int e = get_bool_value(sub_param + 1, argv, ip);
+ if (!auip->disable_allowed && !e) {
+ if (!u_switch)
+ bad_value(param, sub_param + 1, "false");
+ else
+ ASSERT(auip->enable); /* ignore */
+ }
+ else auip->enable = e;
break;
+ }
case 'l':
if (has_prefix("lmbcs", sub_param)) {
auip->default_.lmbcs = 0;
@@ -1424,7 +1433,14 @@ handle_au_arg(struct au_init *auip,
case 't': {
int res = get_bool_value(sub_param+1, argv, ip);
if (res > 0) {
- auip->thr_spec = 1;
+ if (!auip->thr_spec_allowed) {
+ if (!u_switch)
+ bad_value(param, sub_param + 1, "true");
+ else
+ ASSERT(!auip->thr_spec); /* ignore */
+ }
+ else
+ auip->thr_spec = 1;
break;
}
else if (res == 0) {
@@ -1473,6 +1489,16 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
case 'B':
handle_au_arg(&init->binary_alloc, &argv[i][3], argv, &i, 0);
break;
+ case 'I':
+ if (has_prefix("scs", argv[i]+3)) {
+#if HAVE_ERTS_MSEG
+ init->mseg.literal_mmap.scs =
+#endif
+ get_mb_value(argv[i]+6, argv, &i);
+ }
+ else
+ handle_au_arg(&init->literal_alloc, &argv[i][3], argv, &i, 0);
+ break;
case 'D':
handle_au_arg(&init->std_alloc, &argv[i][3], argv, &i, 0);
break;
@@ -1509,25 +1535,25 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
}
else if (has_prefix("scs", argv[i]+3)) {
#if HAVE_ERTS_MSEG
- init->mseg.mmap.scs =
+ init->mseg.dflt_mmap.scs =
#endif
get_mb_value(argv[i]+6, argv, &i);
}
else if (has_prefix("sco", argv[i]+3)) {
#if HAVE_ERTS_MSEG
- init->mseg.mmap.sco =
+ init->mseg.dflt_mmap.sco =
#endif
get_bool_value(argv[i]+6, argv, &i);
}
else if (has_prefix("scrpm", argv[i]+3)) {
#if HAVE_ERTS_MSEG
- init->mseg.mmap.scrpm =
+ init->mseg.dflt_mmap.scrpm =
#endif
get_bool_value(argv[i]+8, argv, &i);
}
else if (has_prefix("scrfsd", argv[i]+3)) {
#if HAVE_ERTS_MSEG
- init->mseg.mmap.scrfsd =
+ init->mseg.dflt_mmap.scrfsd =
#endif
get_amount_value(argv[i]+9, argv, &i);
}
@@ -1996,48 +2022,6 @@ alcu_size(ErtsAlcType_t ai, ErtsAlcUFixInfo_t *fi, int fisz)
return res;
}
-#if HALFWORD_HEAP
-static ERTS_INLINE int
-alcu_is_low(ErtsAlcType_t ai)
-{
- int is_low = 0;
- ASSERT(erts_allctrs_info[ai].enabled);
- ASSERT(erts_allctrs_info[ai].alloc_util);
-
- if (!erts_allctrs_info[ai].thr_spec) {
- Allctr_t *allctr = erts_allctrs_info[ai].extra;
- is_low = allctr->mseg_opt.low_mem;
- }
- else {
- ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[ai];
- int i;
-# ifdef DEBUG
- int found_one = 0;
-# endif
-
- ASSERT(tspec->enabled);
-
- for (i = tspec->size - 1; i >= 0; i--) {
- Allctr_t *allctr = tspec->allctr[i];
- if (allctr) {
-# ifdef DEBUG
- if (!found_one) {
- is_low = allctr->mseg_opt.low_mem;
- found_one = 1;
- }
- else ASSERT(is_low == allctr->mseg_opt.low_mem);
-# else
- is_low = allctr->mseg_opt.low_mem;
- break;
-# endif
- }
- }
- ASSERT(found_one);
- }
- return is_low;
-}
-#endif /* HALFWORD */
-
static ERTS_INLINE void
add_fix_values(UWord *ap, UWord *up, ErtsAlcUFixInfo_t *fi, ErtsAlcType_t type)
{
@@ -2067,9 +2051,6 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
int code;
int ets;
int maximum;
-#if HALFWORD_HEAP
- int low;
-#endif
} want = {0};
struct {
UWord total;
@@ -2082,9 +2063,6 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
UWord code;
UWord ets;
UWord maximum;
-#if HALFWORD_HEAP
- UWord low;
-#endif
} size = {0};
Eterm atoms[sizeof(size)/sizeof(UWord)];
UWord *uintps[sizeof(size)/sizeof(UWord)];
@@ -2143,11 +2121,6 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
atoms[length] = am_maximum;
uintps[length++] = &size.maximum;
}
-#if HALFWORD_HEAP
- want.low = 1;
- atoms[length] = am_low;
- uintps[length++] = &size.low;
-#endif
}
else {
DeclareTmpHeapNoproc(tmp_heap,2);
@@ -2241,15 +2214,6 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
return am_badarg;
}
break;
-#if HALFWORD_HEAP
- case am_low:
- if (!want.low) {
- want.low = 1;
- atoms[length] = am_low;
- uintps[length++] = &size.low;
- }
- break;
-#endif
default:
UnUseTmpHeapNoproc(2);
return am_badarg;
@@ -2330,11 +2294,6 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
if (save)
*save = asz;
size.total += asz;
-#if HALFWORD_HEAP
- if (alcu_is_low(ai)) {
- size.low += asz;
- }
-#endif
}
}
}
@@ -2361,7 +2320,6 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
&size.processes_used,
fi,
ERTS_ALC_T_PROC);
-#if !HALFWORD_HEAP
add_fix_values(&size.processes,
&size.processes_used,
fi,
@@ -2371,7 +2329,6 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
&size.processes_used,
fi,
ERTS_ALC_T_NLINK_SH);
-#endif
add_fix_values(&size.processes,
&size.processes_used,
fi,
@@ -2810,7 +2767,7 @@ erts_allocator_info(int to, void *arg)
erts_mseg_info(i, &to, arg, 0, NULL, NULL);
}
erts_print(to, arg, "=allocator:mseg_alloc.erts_mmap\n");
- erts_mmap_info(&to, arg, NULL, NULL, &emis);
+ erts_mmap_info(&erts_dflt_mmapper, &to, arg, NULL, NULL, &emis);
}
#endif
@@ -3036,12 +2993,12 @@ reply_alloc_info(void *vair)
int global_instances = air->req_sched == sched_id;
ErtsProcLocks rp_locks;
Process *rp = air->proc;
- Eterm ref_copy = NIL, ai_list, msg;
- Eterm *hp = NULL, *hp_end = NULL, *hp_start = NULL;
+ Eterm ref_copy = NIL, ai_list, msg = NIL;
+ Eterm *hp = NULL, *hp_start = NULL, *hp_end = NULL;
Eterm **hpp;
Uint sz, *szp;
ErlOffHeap *ohp = NULL;
- ErlHeapFragment *bp = NULL;
+ ErtsMessage *mp = NULL;
struct erts_mmap_info_struct emis;
int i;
Eterm (*info_func)(Allctr_t *,
@@ -3162,7 +3119,8 @@ reply_alloc_info(void *vair)
ai_list = erts_bld_cons(hpp, szp,
ainfo, ai_list);
- ainfo = (air->only_sz ? NIL : erts_mmap_info(NULL, NULL, hpp, szp, &emis));
+ ainfo = (air->only_sz ? NIL :
+ erts_mmap_info(&erts_dflt_mmapper, NULL, NULL, hpp, szp, &emis));
ainfo = erts_bld_tuple3(hpp, szp,
alloc_atom,
erts_bld_atom(hpp,szp,"erts_mmap"),
@@ -3242,20 +3200,17 @@ reply_alloc_info(void *vair)
if (hpp)
break;
- hp = erts_alloc_message_heap(sz, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, sz, &hp, &ohp);
hp_start = hp;
hp_end = hp + sz;
szp = NULL;
hpp = &hp;
}
- if (bp)
- bp = erts_resize_message_buffer(bp, hp - hp_start, &msg, 1);
- else {
- ASSERT(hp);
- HRelease(rp, hp_end, hp);
- }
- erts_queue_message(rp, &rp_locks, bp, msg, NIL);
+ if (hp != hp_end)
+ erts_shrink_message_heap(&mp, rp, hp_start, hp, hp_end, &msg, 1);
+
+ erts_queue_message(rp, &rp_locks, mp, msg, NIL);
if (air->req_sched == sched_id)
rp_locks &= ~ERTS_PROC_LOCK_MAIN;
@@ -3479,8 +3434,11 @@ UWord erts_alc_test(UWord op, UWord a1, UWord a2, UWord a3)
init.enable = 1;
init.atype = GOODFIT;
init.init.util.name_prefix = (char *) a1;
- init.init.util.ts = a2 ? 1 : 0;
-
+#ifdef ERTS_SMP
+ init.init.util.ts = 1;
+#else
+ init.init.util.ts = a2 ? 1 : 0;
+#endif
if ((char **) a3) {
char **argv = (char **) a3;
int i = 0;
diff --git a/erts/emulator/beam/erl_alloc.h b/erts/emulator/beam/erl_alloc.h
index f540bae20d..71e4713624 100644
--- a/erts/emulator/beam/erl_alloc.h
+++ b/erts/emulator/beam/erl_alloc.h
@@ -30,6 +30,7 @@
#ifdef USE_THREADS
#include "erl_threads.h"
#endif
+#include "erl_mmap.h"
#ifdef DEBUG
# undef ERTS_ALC_WANT_INLINE
@@ -43,9 +44,11 @@
#if ERTS_CAN_INLINE && ERTS_ALC_WANT_INLINE
# define ERTS_ALC_DO_INLINE 1
# define ERTS_ALC_INLINE static ERTS_INLINE
+# define ERTS_ALC_FORCE_INLINE static ERTS_FORCE_INLINE
#else
# define ERTS_ALC_DO_INLINE 0
# define ERTS_ALC_INLINE
+# define ERTS_ALC_FORCE_INLINE
#endif
#define ERTS_ALC_NO_FIXED_SIZES \
@@ -177,6 +180,12 @@ void sys_free(void *) __deprecated; /* erts_free() */
void *sys_alloc(Uint ) __deprecated; /* erts_alloc_fnf() */
void *sys_realloc(void *, Uint) __deprecated; /* erts_realloc_fnf() */
+#undef ERTS_HAVE_IS_IN_LITERAL_RANGE
+#if defined(ARCH_32) || defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+# define ERTS_HAVE_IS_IN_LITERAL_RANGE
+#endif
+
+
/*
* erts_alloc[_fnf](), erts_realloc[_fnf](), erts_free() works as
* malloc(), realloc(), and free() with the following exceptions:
@@ -204,6 +213,9 @@ void erts_free(ErtsAlcType_t type, void *ptr);
void *erts_alloc_fnf(ErtsAlcType_t type, Uint size);
void *erts_realloc_fnf(ErtsAlcType_t type, void *ptr, Uint size);
int erts_is_allctr_wrapper_prelocked(void);
+#ifdef ERTS_HAVE_IS_IN_LITERAL_RANGE
+int erts_is_in_literal_range(void* ptr);
+#endif
#endif /* #if !ERTS_ALC_DO_INLINE */
@@ -221,12 +233,14 @@ ERTS_ALC_INLINE
void *erts_alloc(ErtsAlcType_t type, Uint size)
{
void *res;
+ ERTS_MSACC_PUSH_AND_SET_STATE_X(ERTS_MSACC_STATE_ALLOC);
res = (*erts_allctrs[ERTS_ALC_T2A(type)].alloc)(
ERTS_ALC_T2N(type),
erts_allctrs[ERTS_ALC_T2A(type)].extra,
size);
if (!res)
erts_alloc_n_enomem(ERTS_ALC_T2N(type), size);
+ ERTS_MSACC_POP_STATE_X();
return res;
}
@@ -234,6 +248,7 @@ ERTS_ALC_INLINE
void *erts_realloc(ErtsAlcType_t type, void *ptr, Uint size)
{
void *res;
+ ERTS_MSACC_PUSH_AND_SET_STATE_X(ERTS_MSACC_STATE_ALLOC);
res = (*erts_allctrs[ERTS_ALC_T2A(type)].realloc)(
ERTS_ALC_T2N(type),
erts_allctrs[ERTS_ALC_T2A(type)].extra,
@@ -241,37 +256,48 @@ void *erts_realloc(ErtsAlcType_t type, void *ptr, Uint size)
size);
if (!res)
erts_realloc_n_enomem(ERTS_ALC_T2N(type), ptr, size);
+ ERTS_MSACC_POP_STATE_X();
return res;
}
ERTS_ALC_INLINE
void erts_free(ErtsAlcType_t type, void *ptr)
{
+ ERTS_MSACC_PUSH_AND_SET_STATE_X(ERTS_MSACC_STATE_ALLOC);
(*erts_allctrs[ERTS_ALC_T2A(type)].free)(
ERTS_ALC_T2N(type),
erts_allctrs[ERTS_ALC_T2A(type)].extra,
ptr);
+ ERTS_MSACC_POP_STATE_X();
}
ERTS_ALC_INLINE
void *erts_alloc_fnf(ErtsAlcType_t type, Uint size)
{
- return (*erts_allctrs[ERTS_ALC_T2A(type)].alloc)(
+ void *res;
+ ERTS_MSACC_PUSH_AND_SET_STATE_X(ERTS_MSACC_STATE_ALLOC);
+ res = (*erts_allctrs[ERTS_ALC_T2A(type)].alloc)(
ERTS_ALC_T2N(type),
erts_allctrs[ERTS_ALC_T2A(type)].extra,
size);
+ ERTS_MSACC_POP_STATE_X();
+ return res;
}
ERTS_ALC_INLINE
void *erts_realloc_fnf(ErtsAlcType_t type, void *ptr, Uint size)
{
- return (*erts_allctrs[ERTS_ALC_T2A(type)].realloc)(
+ void *res;
+ ERTS_MSACC_PUSH_AND_SET_STATE_X(ERTS_MSACC_STATE_ALLOC);
+ res = (*erts_allctrs[ERTS_ALC_T2A(type)].realloc)(
ERTS_ALC_T2N(type),
erts_allctrs[ERTS_ALC_T2A(type)].extra,
ptr,
size);
+ ERTS_MSACC_POP_STATE_X();
+ return res;
}
ERTS_ALC_INLINE
@@ -281,6 +307,28 @@ int erts_is_allctr_wrapper_prelocked(void)
&& !!erts_tsd_get(erts_allctr_prelock_tsd_key); /* by me */
}
+#ifdef ERTS_HAVE_IS_IN_LITERAL_RANGE
+
+ERTS_ALC_FORCE_INLINE
+int erts_is_in_literal_range(void* ptr)
+{
+#if defined(ARCH_32)
+ Uint ix = (UWord)ptr >> ERTS_MMAP_SUPERALIGNED_BITS;
+
+ return erts_literal_vspace_map[ix / ERTS_VSPACE_WORD_BITS]
+ & ((UWord)1 << (ix % ERTS_VSPACE_WORD_BITS));
+
+#elif defined(ARCH_64)
+ extern char* erts_literals_start;
+ extern UWord erts_literals_size;
+ return ErtsInArea(ptr, erts_literals_start, erts_literals_size);
+#else
+# error No ARCH_xx
+#endif
+}
+
+#endif /* ERTS_HAVE_IS_IN_LITERAL_RANGE */
+
#endif /* #if ERTS_ALC_DO_INLINE || defined(ERTS_ALC_INTERNAL__) */
#define ERTS_ALC_GET_THR_IX() ((int) erts_get_scheduler_id())
diff --git a/erts/emulator/beam/erl_alloc.types b/erts/emulator/beam/erl_alloc.types
index 7738531142..2932adca84 100644
--- a/erts/emulator/beam/erl_alloc.types
+++ b/erts/emulator/beam/erl_alloc.types
@@ -86,11 +86,7 @@ allocator LONG_LIVED true ll_alloc
allocator EHEAP true eheap_alloc
allocator ETS true ets_alloc
allocator FIXED_SIZE true fix_alloc
-
-+if halfword
-allocator LONG_LIVED_LOW true ll_low_alloc
-allocator STANDARD_LOW true std_low_alloc
-+endif
+allocator LITERAL true literal_alloc
+else # Non smp build
@@ -101,11 +97,7 @@ allocator LONG_LIVED false ll_alloc
allocator EHEAP false eheap_alloc
allocator ETS false ets_alloc
allocator FIXED_SIZE false fix_alloc
-
-+if halfword
-allocator LONG_LIVED_LOW false ll_low_alloc
-allocator STANDARD_LOW false std_low_alloc
-+endif
+allocator LITERAL false literal_alloc
+endif
@@ -160,6 +152,8 @@ type OLD_HEAP EHEAP PROCESSES old_heap
type HEAP_FRAG EHEAP PROCESSES heap_frag
type TMP_HEAP TEMPORARY PROCESSES tmp_heap
type MSG_REF FIXED_SIZE PROCESSES msg_ref
+type MSG EHEAP PROCESSES message
+type MSGQ_CHNG SHORT_LIVED PROCESSES messages_queue_change
type MSG_ROOTS TEMPORARY PROCESSES msg_roots
type ROOTSET TEMPORARY PROCESSES root_set
type LOADER_TMP TEMPORARY CODE loader_tmp
@@ -349,34 +343,11 @@ type SSB SHORT_LIVED PROCESSES ssb
+endif
-
-+if halfword
-
-type DDLL_PROCESS STANDARD_LOW SYSTEM ddll_processes
-type MONITOR_LH STANDARD_LOW PROCESSES monitor_lh
-type NLINK_LH STANDARD_LOW PROCESSES nlink_lh
-type CODE LONG_LIVED_LOW CODE code
-type DB_HEIR_DATA STANDARD_LOW ETS db_heir_data
-type DB_MS_PSDO_PROC LONG_LIVED_LOW ETS db_match_pseudo_proc
-type SCHDLR_DATA LONG_LIVED_LOW SYSTEM scheduler_data
-type LL_TEMP_TERM LONG_LIVED_LOW SYSTEM ll_temp_term
-
-type NIF_TRAP_EXPORT STANDARD_LOW CODE nif_trap_export_entry
-type EXPORT LONG_LIVED_LOW CODE export_entry
-type MONITOR_SH STANDARD_LOW PROCESSES monitor_sh
-type NLINK_SH STANDARD_LOW PROCESSES nlink_sh
-type AINFO_REQ STANDARD_LOW SYSTEM alloc_info_request
-type SCHED_WTIME_REQ STANDARD_LOW SYSTEM sched_wall_time_request
-type GC_INFO_REQ STANDARD_LOW SYSTEM gc_info_request
-type PORT_DATA_HEAP STANDARD_LOW SYSTEM port_data_heap
-type SYS_CHECK_REQ STANDARD_LOW SYSTEM system_check_request
-
-+else # "fullword"
-
type DDLL_PROCESS STANDARD SYSTEM ddll_processes
type MONITOR_LH STANDARD PROCESSES monitor_lh
type NLINK_LH STANDARD PROCESSES nlink_lh
type CODE LONG_LIVED CODE code
+type LITERAL LITERAL CODE literal
type DB_HEIR_DATA STANDARD ETS db_heir_data
type DB_MS_PSDO_PROC LONG_LIVED ETS db_match_pseudo_proc
type SCHDLR_DATA LONG_LIVED SYSTEM scheduler_data
@@ -390,11 +361,9 @@ type AINFO_REQ SHORT_LIVED SYSTEM alloc_info_request
type SCHED_WTIME_REQ SHORT_LIVED SYSTEM sched_wall_time_request
type GC_INFO_REQ SHORT_LIVED SYSTEM gc_info_request
type PORT_DATA_HEAP STANDARD SYSTEM port_data_heap
+type MSACC DRIVER SYSTEM microstate_accounting
type SYS_CHECK_REQ SHORT_LIVED SYSTEM system_check_request
-+endif
-
-
#
# Types used by system specific code
#
@@ -432,21 +401,6 @@ type SYS_WRITE_BUF BINARY SYSTEM sys_write_buf
+endif
-+if ose
-
-type SYS_READ_BUF TEMPORARY SYSTEM sys_read_buf
-type FD_TAB LONG_LIVED SYSTEM fd_tab
-type FD_ENTRY_BUF STANDARD SYSTEM fd_entry_buf
-type FD_SIG_LIST SHORT_LIVED SYSTEM fd_sig_list
-type DRV_EV STANDARD SYSTEM driver_event
-type CS_PROG_PATH LONG_LIVED SYSTEM cs_prog_path
-type ENVIRONMENT TEMPORARY SYSTEM environment
-type PUTENV_STR SYSTEM SYSTEM putenv_string
-type PRT_REP_EXIT STANDARD SYSTEM port_report_exit
-
-+endif
-
-
+if win32
type DRV_DATA_BUF SYSTEM SYSTEM drv_data_buf
diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c
index d9eaa7b32c..5e7dd7cce8 100644
--- a/erts/emulator/beam/erl_alloc_util.c
+++ b/erts/emulator/beam/erl_alloc_util.c
@@ -751,12 +751,77 @@ internal_free(void *ptr)
#endif
+#ifdef ARCH_32
+
+/*
+ * Bit vector for the entire 32-bit virtual address space
+ * with one bit for each super aligned memory segment.
+ */
+
+#define VSPACE_MAP_BITS (1 << (32 - ERTS_MMAP_SUPERALIGNED_BITS))
+#define VSPACE_MAP_SZ (VSPACE_MAP_BITS / ERTS_VSPACE_WORD_BITS)
+
+static ERTS_INLINE void set_bit(UWord* map, Uint ix)
+{
+ ASSERT(ix / ERTS_VSPACE_WORD_BITS < VSPACE_MAP_SZ);
+ map[ix / ERTS_VSPACE_WORD_BITS]
+ |= ((UWord)1 << (ix % ERTS_VSPACE_WORD_BITS));
+}
+
+static ERTS_INLINE void clr_bit(UWord* map, Uint ix)
+{
+ ASSERT(ix / ERTS_VSPACE_WORD_BITS < VSPACE_MAP_SZ);
+ map[ix / ERTS_VSPACE_WORD_BITS]
+ &= ~((UWord)1 << (ix % ERTS_VSPACE_WORD_BITS));
+}
+
+static ERTS_INLINE int is_bit_set(UWord* map, Uint ix)
+{
+ ASSERT(ix / ERTS_VSPACE_WORD_BITS < VSPACE_MAP_SZ);
+ return map[ix / ERTS_VSPACE_WORD_BITS]
+ & ((UWord)1 << (ix % ERTS_VSPACE_WORD_BITS));
+}
+
+UWord erts_literal_vspace_map[VSPACE_MAP_SZ];
+
+static void set_literal_range(void* start, Uint size)
+{
+ Uint ix = (UWord)start >> ERTS_MMAP_SUPERALIGNED_BITS;
+ Uint n = size >> ERTS_MMAP_SUPERALIGNED_BITS;
+
+ ASSERT(!((UWord)start & ERTS_INV_SUPERALIGNED_MASK));
+ ASSERT(!((UWord)size & ERTS_INV_SUPERALIGNED_MASK));
+ ASSERT(n);
+ while (n--) {
+ ASSERT(!is_bit_set(erts_literal_vspace_map, ix));
+ set_bit(erts_literal_vspace_map, ix);
+ ix++;
+ }
+}
+
+static void clear_literal_range(void* start, Uint size)
+{
+ Uint ix = (UWord)start >> ERTS_MMAP_SUPERALIGNED_BITS;
+ Uint n = size >> ERTS_MMAP_SUPERALIGNED_BITS;
+
+ ASSERT(!((UWord)start & ERTS_INV_SUPERALIGNED_MASK));
+ ASSERT(!((UWord)size & ERTS_INV_SUPERALIGNED_MASK));
+ ASSERT(n);
+ while (n--) {
+ ASSERT(is_bit_set(erts_literal_vspace_map, ix));
+ clr_bit(erts_literal_vspace_map, ix);
+ ix++;
+ }
+}
+
+#endif /* ARCH_32 */
+
/* mseg ... */
#if HAVE_ERTS_MSEG
-static ERTS_INLINE void *
-alcu_mseg_alloc(Allctr_t *allctr, Uint *size_p, Uint flags)
+void*
+erts_alcu_mseg_alloc(Allctr_t *allctr, Uint *size_p, Uint flags)
{
void *res;
UWord size = (UWord) *size_p;
@@ -766,8 +831,9 @@ alcu_mseg_alloc(Allctr_t *allctr, Uint *size_p, Uint flags)
return res;
}
-static ERTS_INLINE void *
-alcu_mseg_realloc(Allctr_t *allctr, void *seg, Uint old_size, Uint *new_size_p)
+void*
+erts_alcu_mseg_realloc(Allctr_t *allctr, void *seg,
+ Uint old_size, Uint *new_size_p)
{
void *res;
UWord new_size = (UWord) *new_size_p;
@@ -778,17 +844,103 @@ alcu_mseg_realloc(Allctr_t *allctr, void *seg, Uint old_size, Uint *new_size_p)
return res;
}
-static ERTS_INLINE void
-alcu_mseg_dealloc(Allctr_t *allctr, void *seg, Uint size, Uint flags)
+void
+erts_alcu_mseg_dealloc(Allctr_t *allctr, void *seg, Uint size, Uint flags)
{
erts_mseg_dealloc_opt(allctr->alloc_no, seg, (UWord) size, flags, &allctr->mseg_opt);
INC_CC(allctr->calls.mseg_dealloc);
}
-#endif
-static ERTS_INLINE void *
-alcu_sys_alloc(Allctr_t *allctr, Uint size, int superalign)
+#if defined(ARCH_32)
+
+void*
+erts_alcu_literal_32_mseg_alloc(Allctr_t *allctr, Uint *size_p, Uint flags)
+{
+ void* res;
+ ERTS_LC_ASSERT(allctr->alloc_no == ERTS_ALC_A_LITERAL
+ && !allctr->t && allctr->thread_safe);
+
+ res = erts_alcu_mseg_alloc(allctr, size_p, flags);
+ if (res)
+ set_literal_range(res, *size_p);
+ return res;
+}
+
+void*
+erts_alcu_literal_32_mseg_realloc(Allctr_t *allctr, void *seg,
+ Uint old_size, Uint *new_size_p)
+{
+ void* res;
+ ERTS_LC_ASSERT(allctr->alloc_no == ERTS_ALC_A_LITERAL
+ && !allctr->t && allctr->thread_safe);
+
+ if (seg && old_size)
+ clear_literal_range(seg, old_size);
+ res = erts_alcu_mseg_realloc(allctr, seg, old_size, new_size_p);
+ if (res)
+ set_literal_range(res, *new_size_p);
+ return res;
+}
+
+void
+erts_alcu_literal_32_mseg_dealloc(Allctr_t *allctr, void *seg, Uint size,
+ Uint flags)
+{
+ ERTS_LC_ASSERT(allctr->alloc_no == ERTS_ALC_A_LITERAL
+ && !allctr->t && allctr->thread_safe);
+
+ erts_alcu_mseg_dealloc(allctr, seg, size, flags);
+
+ clear_literal_range(seg, size);
+}
+
+#elif defined(ARCH_64) && defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+
+void*
+erts_alcu_literal_64_mseg_alloc(Allctr_t *allctr, Uint *size_p, Uint flags)
+{
+ void* res;
+ UWord size = (UWord) *size_p;
+ Uint32 mmap_flags = ERTS_MMAPFLG_SUPERCARRIER_ONLY;
+ if (flags & ERTS_MSEG_FLG_2POW)
+ mmap_flags |= ERTS_MMAPFLG_SUPERALIGNED;
+
+ res = erts_mmap(&erts_literal_mmapper, mmap_flags, &size);
+ *size_p = (Uint)size;
+ INC_CC(allctr->calls.mseg_alloc);
+ return res;
+}
+
+void*
+erts_alcu_literal_64_mseg_realloc(Allctr_t *allctr, void *seg,
+ Uint old_size, Uint *new_size_p)
+{
+ void *res;
+ UWord new_size = (UWord) *new_size_p;
+ res = erts_mremap(&erts_literal_mmapper, ERTS_MSEG_FLG_NONE, seg, old_size, &new_size);
+ *new_size_p = (Uint) new_size;
+ INC_CC(allctr->calls.mseg_realloc);
+ return res;
+}
+
+void
+erts_alcu_literal_64_mseg_dealloc(Allctr_t *allctr, void *seg, Uint size,
+ Uint flags)
+{
+ Uint32 mmap_flags = ERTS_MMAPFLG_SUPERCARRIER_ONLY;
+ if (flags & ERTS_MSEG_FLG_2POW)
+ mmap_flags |= ERTS_MMAPFLG_SUPERALIGNED;
+
+ erts_munmap(&erts_literal_mmapper, mmap_flags, seg, (UWord)size);
+ INC_CC(allctr->calls.mseg_dealloc);
+}
+#endif /* ARCH_64 && ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION */
+
+#endif /* HAVE_ERTS_MSEG */
+
+void*
+erts_alcu_sys_alloc(Allctr_t *allctr, Uint size, int superalign)
{
void *res;
#if ERTS_SA_MB_CARRIERS && ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC
@@ -803,8 +955,8 @@ alcu_sys_alloc(Allctr_t *allctr, Uint size, int superalign)
return res;
}
-static ERTS_INLINE void *
-alcu_sys_realloc(Allctr_t *allctr, void *ptr, Uint size, Uint old_size, int superalign)
+void*
+erts_alcu_sys_realloc(Allctr_t *allctr, void *ptr, Uint size, Uint old_size, int superalign)
{
void *res;
@@ -824,8 +976,8 @@ alcu_sys_realloc(Allctr_t *allctr, void *ptr, Uint size, Uint old_size, int supe
return res;
}
-static ERTS_INLINE void
-alcu_sys_free(Allctr_t *allctr, void *ptr, int superalign)
+void
+erts_alcu_sys_dealloc(Allctr_t *allctr, void *ptr, Uint size, int superalign)
{
#if ERTS_SA_MB_CARRIERS && ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC
if (superalign)
@@ -838,6 +990,49 @@ alcu_sys_free(Allctr_t *allctr, void *ptr, int superalign)
erts_mtrace_crr_free(allctr->alloc_no, ERTS_ALC_A_SYSTEM, ptr);
}
+#ifdef ARCH_32
+
+void*
+erts_alcu_literal_32_sys_alloc(Allctr_t *allctr, Uint size, int superalign)
+{
+ void* res;
+ ERTS_LC_ASSERT(allctr->alloc_no == ERTS_ALC_A_LITERAL
+ && !allctr->t && allctr->thread_safe);
+
+ res = erts_alcu_sys_alloc(allctr, size, 1);
+ if (res)
+ set_literal_range(res, size);
+ return res;
+}
+
+void*
+erts_alcu_literal_32_sys_realloc(Allctr_t *allctr, void *ptr, Uint size, Uint old_size, int superalign)
+{
+ void* res;
+ ERTS_LC_ASSERT(allctr->alloc_no == ERTS_ALC_A_LITERAL
+ && !allctr->t && allctr->thread_safe);
+
+ if (ptr && old_size)
+ clear_literal_range(ptr, old_size);
+ res = erts_alcu_sys_realloc(allctr, ptr, size, old_size, 1);
+ if (res)
+ set_literal_range(res, size);
+ return res;
+}
+
+void
+erts_alcu_literal_32_sys_dealloc(Allctr_t *allctr, void *ptr, Uint size, int superalign)
+{
+ ERTS_LC_ASSERT(allctr->alloc_no == ERTS_ALC_A_LITERAL
+ && !allctr->t && allctr->thread_safe);
+
+ erts_alcu_sys_dealloc(allctr, ptr, size, 1);
+
+ clear_literal_range(ptr, size);
+}
+
+#endif /* ARCH_32 */
+
static Uint
get_next_mbc_size(Allctr_t *allctr)
{
@@ -2084,7 +2279,7 @@ mbc_alloc_block(Allctr_t *allctr, Uint size, Uint *blk_szp)
if (!blk) {
blk = create_carrier(allctr, get_blk_sz, CFLG_MBC);
-#if !HALFWORD_HEAP && !ERTS_SUPER_ALIGNED_MSEG_ONLY
+#if !ERTS_SUPER_ALIGNED_MSEG_ONLY
if (!blk) {
/* Emergency! We couldn't create the carrier as we wanted.
Try to place it in a sys_alloced sbc. */
@@ -3531,8 +3726,7 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, UWord flags)
int is_mseg = 0;
#endif
- if (HALFWORD_HEAP
- || (ERTS_SUPER_ALIGNED_MSEG_ONLY && (flags & CFLG_MBC))
+ if ((ERTS_SUPER_ALIGNED_MSEG_ONLY && (flags & CFLG_MBC))
|| !allow_sys_alloc_carriers) {
flags |= CFLG_FORCE_MSEG;
flags &= ~CFLG_FORCE_SYS_ALLOC;
@@ -3540,6 +3734,8 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, UWord flags)
return NULL;
#endif
}
+ flags |= allctr->crr_set_flgs;
+ flags &= ~allctr->crr_clr_flgs;
ASSERT((flags & CFLG_SBC && !(flags & CFLG_MBC))
|| (flags & CFLG_MBC && !(flags & CFLG_SBC)));
@@ -3555,7 +3751,21 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, UWord flags)
return NULL;
}
- blk_sz = UMEMSZ2BLKSZ(allctr, umem_sz);
+ if (flags & CFLG_MAIN_CARRIER) {
+ ASSERT(flags & CFLG_MBC);
+ ASSERT(flags & CFLG_NO_CPOOL);
+ ASSERT(umem_sz == allctr->main_carrier_size);
+ ERTS_UNDEF(blk_sz, 0);
+
+ if (allctr->main_carrier_size < allctr->min_mbc_size)
+ allctr->main_carrier_size = allctr->min_mbc_size;
+ crr_sz = bcrr_sz = allctr->main_carrier_size;
+ }
+ else {
+ ERTS_UNDEF(bcrr_sz, 0);
+ ERTS_UNDEF(crr_sz, 0);
+ blk_sz = UMEMSZ2BLKSZ(allctr, umem_sz);
+ }
#ifdef ERTS_SMP
allctr->cpool.disable_abandon = ERTS_ALC_CPOOL_MAX_DISABLE_ABANDON;
@@ -3601,13 +3811,15 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, UWord flags)
mseg_flags = ERTS_MSEG_FLG_NONE;
}
else {
- crr_sz = (*allctr->get_next_mbc_size)(allctr);
- if (crr_sz < MBC_HEADER_SIZE(allctr) + blk_sz)
- crr_sz = MBC_HEADER_SIZE(allctr) + blk_sz;
- mseg_flags = ERTS_MSEG_FLG_2POW;
+ if (!(flags & CFLG_MAIN_CARRIER)) {
+ crr_sz = (*allctr->get_next_mbc_size)(allctr);
+ if (crr_sz < MBC_HEADER_SIZE(allctr) + blk_sz)
+ crr_sz = MBC_HEADER_SIZE(allctr) + blk_sz;
+ }
+ mseg_flags = ERTS_MSEG_FLG_2POW;
}
- crr = (Carrier_t *) alcu_mseg_alloc(allctr, &crr_sz, mseg_flags);
+ crr = (Carrier_t *) allctr->mseg_alloc(allctr, &crr_sz, mseg_flags);
if (!crr) {
have_tried_mseg = 1;
if (!(have_tried_sys_alloc || flags & CFLG_FORCE_MSEG))
@@ -3639,23 +3851,22 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, UWord flags)
if (flags & CFLG_SBC) {
bcrr_sz = blk_sz + SBC_HEADER_SIZE;
}
- else {
+ else if (!(flags & CFLG_MAIN_CARRIER)) {
bcrr_sz = MBC_HEADER_SIZE(allctr) + blk_sz;
- if (!(flags & CFLG_MAIN_CARRIER)
- && bcrr_sz < allctr->smallest_mbc_size)
- bcrr_sz = allctr->smallest_mbc_size;
+ if (bcrr_sz < allctr->smallest_mbc_size)
+ bcrr_sz = allctr->smallest_mbc_size;
}
crr_sz = (flags & CFLG_FORCE_SIZE
? UNIT_CEILING(bcrr_sz)
: SYS_ALLOC_CARRIER_CEILING(bcrr_sz));
- crr = (Carrier_t *) alcu_sys_alloc(allctr, crr_sz, flags & CFLG_MBC);
+ crr = (Carrier_t *) allctr->sys_alloc(allctr, crr_sz, flags & CFLG_MBC);
if (!crr) {
if (crr_sz > UNIT_CEILING(bcrr_sz)) {
crr_sz = UNIT_CEILING(bcrr_sz);
- crr = (Carrier_t *) alcu_sys_alloc(allctr, crr_sz, flags & CFLG_MBC);
+ crr = (Carrier_t *) allctr->sys_alloc(allctr, crr_sz, flags & CFLG_MBC);
}
if (!crr) {
#if HAVE_ERTS_MSEG
@@ -3754,7 +3965,7 @@ resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, UWord flags)
new_crr_sz = new_blk_sz + SBC_HEADER_SIZE;
new_crr_sz = ERTS_SACRR_UNIT_CEILING(new_crr_sz);
- new_crr = (Carrier_t *) alcu_mseg_realloc(allctr,
+ new_crr = (Carrier_t *) allctr->mseg_realloc(allctr,
old_crr,
old_crr_sz,
&new_crr_sz);
@@ -3769,11 +3980,6 @@ resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, UWord flags)
DEBUG_SAVE_ALIGNMENT(new_crr);
return new_blk;
}
-#if HALFWORD_HEAP
- /* Old carrier unchanged; restore stat */
- STAT_MSEG_SBC_ALLOC(allctr, old_crr_sz, old_blk_sz);
- return NULL;
-#endif
create_flags |= CFLG_FORCE_SYS_ALLOC; /* since mseg_realloc()
failed */
}
@@ -3784,7 +3990,7 @@ resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, UWord flags)
(void *) BLK2UMEM(old_blk),
MIN(new_blk_sz, old_blk_sz) - ABLK_HDR_SZ);
unlink_carrier(&allctr->sbc_list, old_crr);
- alcu_mseg_dealloc(allctr, old_crr, old_crr_sz, ERTS_MSEG_FLG_NONE);
+ allctr->mseg_dealloc(allctr, old_crr, old_crr_sz, ERTS_MSEG_FLG_NONE);
}
else {
/* Old carrier unchanged; restore stat */
@@ -3801,7 +4007,7 @@ resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, UWord flags)
? UNIT_CEILING(new_bcrr_sz)
: SYS_ALLOC_CARRIER_CEILING(new_bcrr_sz));
- new_crr = (Carrier_t *) alcu_sys_realloc(allctr,
+ new_crr = (Carrier_t *) allctr->sys_realloc(allctr,
(void *) old_crr,
new_crr_sz,
old_crr_sz,
@@ -3822,7 +4028,7 @@ resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, UWord flags)
else if (new_crr_sz > UNIT_CEILING(new_bcrr_sz)) {
new_crr_sz = new_blk_sz + SBC_HEADER_SIZE;
new_crr_sz = UNIT_CEILING(new_crr_sz);
- new_crr = (Carrier_t *) alcu_sys_realloc(allctr,
+ new_crr = (Carrier_t *) allctr->sys_realloc(allctr,
(void *) old_crr,
new_crr_sz,
old_crr_sz,
@@ -3845,7 +4051,7 @@ resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, UWord flags)
(void *) BLK2UMEM(old_blk),
MIN(new_blk_sz, old_blk_sz) - ABLK_HDR_SZ);
unlink_carrier(&allctr->sbc_list, old_crr);
- alcu_sys_free(allctr, old_crr, 0);
+ allctr->sys_dealloc(allctr, old_crr, CARRIER_SZ(old_crr), 0);
}
else {
/* Old carrier unchanged; restore... */
@@ -3861,13 +4067,13 @@ dealloc_carrier(Allctr_t *allctr, Carrier_t *crr, int superaligned)
{
#if HAVE_ERTS_MSEG
if (IS_MSEG_CARRIER(crr))
- alcu_mseg_dealloc(allctr, crr, CARRIER_SZ(crr),
+ allctr->mseg_dealloc(allctr, crr, CARRIER_SZ(crr),
(superaligned
? ERTS_MSEG_FLG_2POW
: ERTS_MSEG_FLG_NONE));
else
#endif
- alcu_sys_free(allctr, crr, superaligned);
+ allctr->sys_dealloc(allctr, crr, CARRIER_SZ(crr), superaligned);
}
static void
@@ -3962,9 +4168,6 @@ static struct {
Eterm e;
Eterm t;
Eterm ramv;
-#if HALFWORD_HEAP
- Eterm low;
-#endif
Eterm sbct;
#if HAVE_ERTS_MSEG
Eterm asbcst;
@@ -4055,9 +4258,6 @@ init_atoms(Allctr_t *allctr)
AM_INIT(e);
AM_INIT(t);
AM_INIT(ramv);
-#if HALFWORD_HEAP
- AM_INIT(low);
-#endif
AM_INIT(sbct);
#if HAVE_ERTS_MSEG
AM_INIT(asbcst);
@@ -4663,9 +4863,6 @@ info_options(Allctr_t *allctr,
"option e: true\n"
"option t: %s\n"
"option ramv: %s\n"
-#if HALFWORD_HEAP
- "option low: %s\n"
-#endif
"option sbct: %beu\n"
#if HAVE_ERTS_MSEG
"option asbcst: %bpu\n"
@@ -4684,9 +4881,6 @@ info_options(Allctr_t *allctr,
"option acul: %d\n",
topt,
allctr->ramv ? "true" : "false",
-#if HALFWORD_HEAP
- allctr->mseg_opt.low_mem ? "true" : "false",
-#endif
allctr->sbc_threshold,
#if HAVE_ERTS_MSEG
allctr->mseg_opt.abs_shrink_th,
@@ -4749,9 +4943,6 @@ info_options(Allctr_t *allctr,
add_2tup(hpp, szp, &res,
am.sbct,
bld_uint(hpp, szp, allctr->sbc_threshold));
-#if HALFWORD_HEAP
- add_2tup(hpp, szp, &res, am.low, allctr->mseg_opt.low_mem ? am_true : am_false);
-#endif
add_2tup(hpp, szp, &res, am.ramv, allctr->ramv ? am_true : am_false);
add_2tup(hpp, szp, &res, am.t, (allctr->t ? am_true : am_false));
add_2tup(hpp, szp, &res, am.e, am_true);
@@ -5146,6 +5337,11 @@ do_erts_alcu_alloc(ErtsAlcType_t type, void *extra, Uint size)
void *erts_alcu_alloc(ErtsAlcType_t type, void *extra, Uint size)
{
void *res;
+#ifdef ERTS_SMP
+ ASSERT(!"This is not thread safe");
+#elif defined(USE_THREADS)
+ ASSERT(erts_equal_tids(erts_main_thread, erts_thr_self()));
+#endif
res = do_erts_alcu_alloc(type, extra, size);
DEBUG_CHECK_ALIGNMENT(res);
return res;
@@ -5436,11 +5632,7 @@ do_erts_alcu_realloc(ErtsAlcType_t type,
Block_t *new_blk;
if(IS_SBC_BLK(blk)) {
do_carrier_resize:
-#if HALFWORD_HEAP
- new_blk = resize_carrier(allctr, blk, size, CFLG_SBC | CFLG_FORCE_MSEG);
-#else
new_blk = resize_carrier(allctr, blk, size, CFLG_SBC);
-#endif
res = new_blk ? BLK2UMEM(new_blk) : NULL;
}
else if (alcu_flgs & ERTS_ALCU_FLG_FAIL_REALLOC_MOVE)
@@ -5734,11 +5926,8 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
#ifdef ERTS_SMP
if (init->tspec || init->tpref)
allctr->mseg_opt.sched_spec = 1;
-#endif
-# if HALFWORD_HEAP
- allctr->mseg_opt.low_mem = init->low_mem;
-# endif
-#endif
+#endif /* ERTS_SMP */
+#endif /* HAVE_ERTS_MSEG */
allctr->name_prefix = init->name_prefix;
if (!allctr->name_prefix)
@@ -5887,17 +6076,52 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
+ ABLK_HDR_SZ)
- ABLK_HDR_SZ);
+ if (init->sys_alloc) {
+ ASSERT(init->sys_realloc && init->sys_dealloc);
+ allctr->sys_alloc = init->sys_alloc;
+ allctr->sys_realloc = init->sys_realloc;
+ allctr->sys_dealloc = init->sys_dealloc;
+ }
+ else {
+ ASSERT(!init->sys_realloc && !init->sys_dealloc);
+ allctr->sys_alloc = &erts_alcu_sys_alloc;
+ allctr->sys_realloc = &erts_alcu_sys_realloc;
+ allctr->sys_dealloc = &erts_alcu_sys_dealloc;
+ }
+#if HAVE_ERTS_MSEG
+ if (init->mseg_alloc) {
+ ASSERT(init->mseg_realloc && init->mseg_dealloc);
+ allctr->mseg_alloc = init->mseg_alloc;
+ allctr->mseg_realloc = init->mseg_realloc;
+ allctr->mseg_dealloc = init->mseg_dealloc;
+ }
+ else {
+ ASSERT(!init->mseg_realloc && !init->mseg_dealloc);
+ allctr->mseg_alloc = &erts_alcu_mseg_alloc;
+ allctr->mseg_realloc = &erts_alcu_mseg_realloc;
+ allctr->mseg_dealloc = &erts_alcu_mseg_dealloc;
+ }
+ /* If a custom carrier alloc function is specified, make sure it's used */
+ if (init->mseg_alloc && !init->sys_alloc) {
+ allctr->crr_set_flgs = CFLG_FORCE_MSEG;
+ allctr->crr_clr_flgs = CFLG_FORCE_SYS_ALLOC;
+ }
+ else if (!init->mseg_alloc && init->sys_alloc) {
+ allctr->crr_set_flgs = CFLG_FORCE_SYS_ALLOC;
+ allctr->crr_clr_flgs = CFLG_FORCE_MSEG;
+ }
+#endif
+
if (allctr->main_carrier_size) {
Block_t *blk;
blk = create_carrier(allctr,
allctr->main_carrier_size,
- CFLG_MBC
+ (ERTS_SUPER_ALIGNED_MSEG_ONLY
+ ? CFLG_FORCE_MSEG : CFLG_FORCE_SYS_ALLOC)
+ | CFLG_MBC
| CFLG_FORCE_SIZE
| CFLG_NO_CPOOL
-#if !HALFWORD_HEAP && !ERTS_SUPER_ALIGNED_MSEG_ONLY
- | CFLG_FORCE_SYS_ALLOC
-#endif
| CFLG_MAIN_CARRIER);
if (!blk) {
#ifdef USE_THREADS
diff --git a/erts/emulator/beam/erl_alloc_util.h b/erts/emulator/beam/erl_alloc_util.h
index f4a2ae7ff3..b7d717ed23 100644
--- a/erts/emulator/beam/erl_alloc_util.h
+++ b/erts/emulator/beam/erl_alloc_util.h
@@ -24,6 +24,12 @@
#define ERTS_ALCU_VSN_STR "3.0"
#include "erl_alloc_types.h"
+#ifdef USE_THREADS
+#define ERL_THREADS_EMU_INTERNAL__
+#include "erl_threads.h"
+#endif
+
+#include "erl_mseg.h"
#define ERTS_AU_PREF_ALLOC_BITS 11
#define ERTS_AU_MAX_PREF_ALLOC_INSTANCES (1 << ERTS_AU_PREF_ALLOC_BITS)
@@ -45,7 +51,6 @@ typedef struct {
int tspec;
int tpref;
int ramv;
- int low_mem; /* HALFWORD only */
UWord sbct;
UWord asbcst;
UWord rsbcst;
@@ -61,6 +66,15 @@ typedef struct {
void *fix;
size_t *fix_type_size;
+
+#if HAVE_ERTS_MSEG
+ void* (*mseg_alloc)(Allctr_t*, Uint *size_p, Uint flags);
+ void* (*mseg_realloc)(Allctr_t*, void *seg, Uint old_size, Uint *new_size_p);
+ void (*mseg_dealloc)(Allctr_t*, void *seg, Uint size, Uint flags);
+#endif
+ void* (*sys_alloc)(Allctr_t *allctr, Uint size, int superalign);
+ void* (*sys_realloc)(Allctr_t *allctr, void *ptr, Uint size, Uint old_size, int superalign);
+ void (*sys_dealloc)(Allctr_t *allctr, void *ptr, Uint size, int superalign);
} AllctrInit_t;
typedef struct {
@@ -90,7 +104,6 @@ typedef struct {
0, /* (bool) tspec: thread specific */\
0, /* (bool) tpref: thread preferred */\
0, /* (bool) ramv: realloc always moves */\
- 0, /* (bool) low_mem: HALFWORD only */\
512*1024, /* (bytes) sbct: sbc threshold */\
2*1024*2024, /* (amount) asbcst: abs sbc shrink threshold */\
20, /* (%) rsbcst: rel sbc shrink threshold */\
@@ -125,7 +138,6 @@ typedef struct {
0, /* (bool) tspec: thread specific */\
0, /* (bool) tpref: thread preferred */\
0, /* (bool) ramv: realloc always moves */\
- 0, /* (bool) low_mem: HALFWORD only */\
64*1024, /* (bytes) sbct: sbc threshold */\
2*1024*2024, /* (amount) asbcst: abs sbc shrink threshold */\
20, /* (%) rsbcst: rel sbc shrink threshold */\
@@ -176,20 +188,44 @@ void erts_alcu_check_delayed_dealloc(Allctr_t *, int, int *, ErtsThrPrgrVal *
#endif
erts_aint32_t erts_alcu_fix_alloc_shrink(Allctr_t *, erts_aint32_t);
+#ifdef ARCH_32
+extern UWord erts_literal_vspace_map[];
+# define ERTS_VSPACE_WORD_BITS (sizeof(UWord)*8)
+#endif
+
+void* erts_alcu_mseg_alloc(Allctr_t*, Uint *size_p, Uint flags);
+void* erts_alcu_mseg_realloc(Allctr_t*, void *seg, Uint old_size, Uint *new_size_p);
+void erts_alcu_mseg_dealloc(Allctr_t*, void *seg, Uint size, Uint flags);
+
+#if HAVE_ERTS_MSEG
+# if defined(ARCH_32)
+void* erts_alcu_literal_32_mseg_alloc(Allctr_t*, Uint *size_p, Uint flags);
+void* erts_alcu_literal_32_mseg_realloc(Allctr_t*, void *seg, Uint old_size, Uint *new_size_p);
+void erts_alcu_literal_32_mseg_dealloc(Allctr_t*, void *seg, Uint size, Uint flags);
+
+# elif defined(ARCH_64) && defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+void* erts_alcu_literal_64_mseg_alloc(Allctr_t*, Uint *size_p, Uint flags);
+void* erts_alcu_literal_64_mseg_realloc(Allctr_t*, void *seg, Uint old_size, Uint *new_size_p);
+void erts_alcu_literal_64_mseg_dealloc(Allctr_t*, void *seg, Uint size, Uint flags);
+# endif
+#endif /* HAVE_ERTS_MSEG */
+
+void* erts_alcu_sys_alloc(Allctr_t*, Uint size, int superalign);
+void* erts_alcu_sys_realloc(Allctr_t*, void *ptr, Uint size, Uint old_size, int superalign);
+void erts_alcu_sys_dealloc(Allctr_t*, void *ptr, Uint size, int superalign);
+#ifdef ARCH_32
+void* erts_alcu_literal_32_sys_alloc(Allctr_t*, Uint size, int superalign);
+void* erts_alcu_literal_32_sys_realloc(Allctr_t*, void *ptr, Uint size, Uint old_size, int superalign);
+void erts_alcu_literal_32_sys_dealloc(Allctr_t*, void *ptr, Uint size, int superalign);
#endif
+#endif /* !ERL_ALLOC_UTIL__ */
+
#if defined(GET_ERL_ALLOC_UTIL_IMPL) && !defined(ERL_ALLOC_UTIL_IMPL__)
#define ERL_ALLOC_UTIL_IMPL__
#define ERTS_ALCU_FLG_FAIL_REALLOC_MOVE (((Uint32) 1) << 0)
-#ifdef USE_THREADS
-#define ERL_THREADS_EMU_INTERNAL__
-#include "erl_threads.h"
-#endif
-
-#include "erl_mseg.h"
-
#undef ERTS_ALLOC_UTIL_HARD_DEBUG
#ifdef DEBUG
# if 0
@@ -223,7 +259,7 @@ erts_aint32_t erts_alcu_fix_alloc_shrink(Allctr_t *, erts_aint32_t);
#if ERTS_HAVE_MSEG_SUPER_ALIGNED \
|| (!HAVE_ERTS_MSEG && ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC)
-# ifndef MSEG_ALIGN_BITS
+# ifdef MSEG_ALIGN_BITS
# define ERTS_SUPER_ALIGN_BITS MSEG_ALIGN_BITS
# else
# define ERTS_SUPER_ALIGN_BITS 18
@@ -501,6 +537,8 @@ struct Allctr_t_ {
Uint min_mbc_size;
Uint min_mbc_first_free_size;
Uint min_block_size;
+ UWord crr_set_flgs;
+ UWord crr_clr_flgs;
/* Carriers */
CarrierList_t mbc_list;
@@ -546,6 +584,15 @@ struct Allctr_t_ {
void (*remove_mbc) (Allctr_t *, Carrier_t *);
UWord (*largest_fblk_in_mbc) (Allctr_t *, Carrier_t *);
+#if HAVE_ERTS_MSEG
+ void* (*mseg_alloc)(Allctr_t*, Uint *size_p, Uint flags);
+ void* (*mseg_realloc)(Allctr_t*, void *seg, Uint old_size, Uint *new_size_p);
+ void (*mseg_dealloc)(Allctr_t*, void *seg, Uint size, Uint flags);
+#endif
+ void* (*sys_alloc)(Allctr_t *allctr, Uint size, int superalign);
+ void* (*sys_realloc)(Allctr_t *allctr, void *ptr, Uint size, Uint old_size, int superalign);
+ void (*sys_dealloc)(Allctr_t *allctr, void *ptr, Uint size, int superalign);
+
void (*init_atoms) (void);
#ifdef ERTS_ALLOC_UTIL_HARD_DEBUG
diff --git a/erts/emulator/beam/erl_arith.c b/erts/emulator/beam/erl_arith.c
index b8c5ef9b09..3671025d22 100644
--- a/erts/emulator/beam/erl_arith.c
+++ b/erts/emulator/beam/erl_arith.c
@@ -42,15 +42,8 @@
# define MAX(x, y) (((x) > (y)) ? (x) : (y))
#endif
-#if !HEAP_ON_C_STACK
-# define DECLARE_TMP(VariableName,N,P) \
- Eterm *VariableName = ((ERTS_PROC_GET_SCHDATA(P)->erl_arith_tmp_heap) + (2 * N))
-#else
-# define DECLARE_TMP(VariableName,N,P) \
- Eterm VariableName[2]
-#endif
-# define ARG_IS_NOT_TMP(Arg,Tmp) ((Arg) != make_big((Tmp)))
-
+#define DECLARE_TMP(VariableName,N,P) Eterm VariableName[2]
+#define ARG_IS_NOT_TMP(Arg,Tmp) ((Arg) != make_big((Tmp)))
static Eterm shift(Process* p, Eterm arg1, Eterm arg2, int right);
diff --git a/erts/emulator/beam/erl_async.c b/erts/emulator/beam/erl_async.c
index f071898046..cdeeb5281b 100644
--- a/erts/emulator/beam/erl_async.c
+++ b/erts/emulator/beam/erl_async.c
@@ -167,7 +167,6 @@ async_ready_q(Uint sched_id)
#endif
-
void
erts_init_async(void)
{
@@ -401,13 +400,19 @@ static ERTS_INLINE void call_async_ready(ErtsAsync *a)
ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP);
#endif
if (!p) {
- if (a->async_free)
+ if (a->async_free) {
+ ERTS_MSACC_PUSH_AND_SET_STATE(ERTS_MSACC_STATE_PORT);
a->async_free(a->async_data);
+ ERTS_MSACC_POP_STATE();
+ }
}
else {
if (async_ready(p, a->async_data)) {
- if (a->async_free)
+ if (a->async_free) {
+ ERTS_MSACC_PUSH_AND_SET_STATE(ERTS_MSACC_STATE_PORT);
a->async_free(a->async_data);
+ ERTS_MSACC_POP_STATE();
+ }
}
#if ERTS_USE_ASYNC_READY_Q
erts_port_release(p);
@@ -461,6 +466,8 @@ static erts_tse_t *async_thread_init(ErtsAsyncQ *aq)
{
ErtsThrQInit_t qinit = ERTS_THR_Q_INIT_DEFAULT;
erts_tse_t *tse = erts_tse_fetch();
+ ERTS_DECLARE_DUMMY(Uint no);
+
#ifdef ERTS_SMP
ErtsThrPrgrCallbacks callbacks;
@@ -484,10 +491,12 @@ static erts_tse_t *async_thread_init(ErtsAsyncQ *aq)
/* Inform main thread that we are done initializing... */
erts_mtx_lock(&async->init.data.mtx);
- async->init.data.no_initialized++;
+ no = async->init.data.no_initialized++;
erts_cnd_signal(&async->init.data.cnd);
erts_mtx_unlock(&async->init.data.mtx);
+ erts_msacc_init_thread("async", no, 0);
+
return tse;
}
@@ -495,6 +504,7 @@ static void *async_main(void* arg)
{
ErtsAsyncQ *aq = (ErtsAsyncQ *) arg;
erts_tse_t *tse = async_thread_init(aq);
+ ERTS_MSACC_DECLARE_CACHE();
while (1) {
ErtsThrQPrepEnQ_t *prep_enq;
@@ -502,11 +512,14 @@ static void *async_main(void* arg)
if (is_nil(a->port))
break; /* Time to die */
+ ERTS_MSACC_UPDATE_CACHE();
+
#if ERTS_ASYNC_PRINT_JOB
erts_fprintf(stderr, "<- %ld\n", a->async_id);
#endif
-
+ ERTS_MSACC_SET_STATE_CACHED(ERTS_MSACC_STATE_PORT);
a->async_invoke(a->async_data);
+ ERTS_MSACC_SET_STATE_CACHED(ERTS_MSACC_STATE_OTHER);
async_reply(a, prep_enq);
}
@@ -629,10 +642,13 @@ long driver_async(ErlDrvPort ix, unsigned int* key,
unsigned int qix;
#if ERTS_USE_ASYNC_READY_Q
Uint sched_id;
+ ERTS_MSACC_PUSH_STATE();
sched_id = erts_get_scheduler_id();
if (!sched_id)
sched_id = 1;
+#else
+ ERTS_MSACC_PUSH_STATE();
#endif
prt = erts_drvport2port(ix);
@@ -685,12 +701,17 @@ long driver_async(ErlDrvPort ix, unsigned int* key,
return id;
}
#endif
-
+
+ ERTS_MSACC_SET_STATE_CACHED(ERTS_MSACC_STATE_PORT);
(*a->async_invoke)(a->async_data);
+ ERTS_MSACC_POP_STATE();
if (async_ready(prt, a->async_data)) {
- if (a->async_free != NULL)
+ if (a->async_free != NULL) {
+ ERTS_MSACC_SET_STATE_CACHED(ERTS_MSACC_STATE_PORT);
(*a->async_free)(a->async_data);
+ ERTS_MSACC_POP_STATE();
+ }
}
erts_free(ERTS_ALC_T_ASYNC, (void *) a);
diff --git a/erts/emulator/beam/erl_bif_binary.c b/erts/emulator/beam/erl_bif_binary.c
index 134aa2d396..aec72bd61a 100644
--- a/erts/emulator/beam/erl_bif_binary.c
+++ b/erts/emulator/beam/erl_bif_binary.c
@@ -55,10 +55,8 @@
/* Init and local variables */
-static Export binary_match_trap_export;
-static BIF_RETTYPE binary_match_trap(BIF_ALIST_3);
-static Export binary_matches_trap_export;
-static BIF_RETTYPE binary_matches_trap(BIF_ALIST_3);
+static Export binary_find_trap_export;
+static BIF_RETTYPE binary_find_trap(BIF_ALIST_3);
static Export binary_longest_prefix_trap_export;
static BIF_RETTYPE binary_longest_prefix_trap(BIF_ALIST_3);
static Export binary_longest_suffix_trap_export;
@@ -70,19 +68,15 @@ static BIF_RETTYPE binary_copy_trap(BIF_ALIST_2);
static Uint max_loop_limit;
static BIF_RETTYPE
-binary_match(Process *p, Eterm arg1, Eterm arg2, Eterm arg3);
+binary_match(Process *p, Eterm arg1, Eterm arg2, Eterm arg3, Uint flags);
static BIF_RETTYPE
-binary_matches(Process *p, Eterm arg1, Eterm arg2, Eterm arg3);
+binary_split(Process *p, Eterm arg1, Eterm arg2, Eterm arg3);
void erts_init_bif_binary(void)
{
- erts_init_trap_export(&binary_match_trap_export,
- am_erlang, am_binary_match_trap, 3,
- &binary_match_trap);
-
- erts_init_trap_export(&binary_matches_trap_export,
- am_erlang, am_binary_matches_trap, 3,
- &binary_matches_trap);
+ erts_init_trap_export(&binary_find_trap_export,
+ am_erlang, am_binary_find_trap, 3,
+ &binary_find_trap);
erts_init_trap_export(&binary_longest_prefix_trap_export,
am_erlang, am_binary_longest_prefix_trap, 3,
@@ -314,8 +308,8 @@ static BMData *create_bmdata(MyAllocator *my, byte *x, Uint len,
/*
* Aho Corasick - Build a Trie and fill in the failure functions
* when all strings are added.
- * The algorithm is nicely described by Dieter B�hler of University of
- * T�bingen:
+ * The algorithm is nicely described by Dieter Bühler of University of
+ * Tübingen:
* http://www-sr.informatik.uni-tuebingen.de/~buehler/AC/AC.html
*/
@@ -537,21 +531,23 @@ static void ac_init_find_all(ACFindAllState *state, ACTrie *act, Sint startpos,
state->out = NULL;
}
-static void ac_restore_find_all(ACFindAllState *state, char *buff)
+static void ac_restore_find_all(ACFindAllState *state,
+ const ACFindAllState *src)
{
- memcpy(state,buff,sizeof(ACFindAllState));
+ memcpy(state, src, sizeof(ACFindAllState));
if (state->allocated > 0) {
state->out = erts_alloc(ERTS_ALC_T_TMP, sizeof(FindallData) * (state->allocated));
- memcpy(state->out,buff+sizeof(ACFindAllState),sizeof(FindallData)*state->m);
+ memcpy(state->out, src+1, sizeof(FindallData)*state->m);
} else {
state->out = NULL;
}
}
-static void ac_serialize_find_all(ACFindAllState *state, char *buff)
+static void ac_serialize_find_all(const ACFindAllState *state,
+ ACFindAllState *dst)
{
- memcpy(buff,state,sizeof(ACFindAllState));
- memcpy(buff+sizeof(ACFindAllState),state->out,sizeof(FindallData)*state->m);
+ memcpy(dst, state, sizeof(ACFindAllState));
+ memcpy(dst+1, state->out, sizeof(FindallData)*state->m);
}
static void ac_clean_find_all(ACFindAllState *state)
@@ -565,9 +561,6 @@ static void ac_clean_find_all(ACFindAllState *state)
#endif
}
-#define SIZEOF_AC_SERIALIZED_FIND_ALL_STATE(S) \
- (sizeof(ACFindAllState)+(sizeof(FindallData)*(S).m))
-
/*
* Differs to the find_first function in that it stores all matches and the values
* arte returned only in the state.
@@ -814,24 +807,24 @@ static void bm_init_find_all(BMFindAllState *state, Sint startpos, Uint len)
state->out = NULL;
}
-static void bm_restore_find_all(BMFindAllState *state, char *buff)
+static void bm_restore_find_all(BMFindAllState *state,
+ const BMFindAllState *src)
{
- memcpy(state,buff,sizeof(BMFindAllState));
+ memcpy(state, src, sizeof(BMFindAllState));
if (state->allocated > 0) {
state->out = erts_alloc(ERTS_ALC_T_TMP, sizeof(FindallData) *
(state->allocated));
- memcpy(state->out,buff+sizeof(BMFindAllState),
- sizeof(FindallData)*state->m);
+ memcpy(state->out, src+1, sizeof(FindallData)*state->m);
} else {
state->out = NULL;
}
}
-static void bm_serialize_find_all(BMFindAllState *state, char *buff)
+static void bm_serialize_find_all(const BMFindAllState *state,
+ BMFindAllState *dst)
{
- memcpy(buff,state,sizeof(BMFindAllState));
- memcpy(buff+sizeof(BMFindAllState),state->out,
- sizeof(FindallData)*state->m);
+ memcpy(dst, state, sizeof(BMFindAllState));
+ memcpy(dst+1, state->out, sizeof(FindallData)*state->m);
}
static void bm_clean_find_all(BMFindAllState *state)
@@ -845,9 +838,6 @@ static void bm_clean_find_all(BMFindAllState *state)
#endif
}
-#define SIZEOF_BM_SERIALIZED_FIND_ALL_STATE(S) \
- (sizeof(BMFindAllState)+(sizeof(FindallData)*(S).m))
-
/*
* Differs to the find_first function in that it stores all matches and the
* values are returned only in the state.
@@ -1030,283 +1020,142 @@ BIF_RETTYPE binary_compile_pattern_1(BIF_ALIST_1)
#define DO_BIN_MATCH_BADARG -1
#define DO_BIN_MATCH_RESTART -2
-static int do_binary_match(Process *p, Eterm subject, Uint hsstart, Uint hsend,
- Eterm type, Binary *bin, Eterm state_term,
- Eterm *res_term)
-{
- byte *bytes;
- Uint bitoffs, bitsize;
- byte *temp_alloc = NULL;
-
- ERTS_GET_BINARY_BYTES(subject, bytes, bitoffs, bitsize);
- if (bitsize != 0) {
- goto badarg;
- }
- if (bitoffs != 0) {
- bytes = erts_get_aligned_binary_bytes(subject, &temp_alloc);
- }
- if (state_term != NIL) {
- Eterm *ptr = big_val(state_term);
- type = ptr[1];
- }
-
- if (type == am_bm) {
- BMData *bm;
- Sint pos;
- Eterm ret;
- Eterm *hp;
- BMFindFirstState state;
- Uint reds = get_reds(p, BM_LOOP_FACTOR);
- Uint save_reds = reds;
-
- bm = (BMData *) ERTS_MAGIC_BIN_DATA(bin);
-#ifdef HARDDEBUG
- dump_bm_data(bm);
-#endif
- if (state_term == NIL) {
- bm_init_find_first_match(&state, hsstart, hsend);
- } else {
- Eterm *ptr = big_val(state_term);
- memcpy(&state,ptr+2,sizeof(state));
- }
-#ifdef HARDDEBUG
- erts_printf("(bm) state->pos = %ld, state->len = %lu\n",state.pos,
- state.len);
-#endif
- pos = bm_find_first_match(&state, bm, bytes, &reds);
- if (pos == BM_NOT_FOUND) {
- ret = am_nomatch;
- } else if (pos == BM_RESTART) {
- int x = (sizeof(BMFindFirstState) / sizeof(Eterm)) +
- !!(sizeof(BMFindFirstState) % sizeof(Eterm));
-#ifdef HARDDEBUG
- erts_printf("Trap bm!\n");
-#endif
- hp = HAlloc(p,x+2);
- hp[0] = make_pos_bignum_header(x+1);
- hp[1] = type;
- memcpy(hp+2,&state,sizeof(state));
- *res_term = make_big(hp);
- erts_free_aligned_binary_bytes(temp_alloc);
- return DO_BIN_MATCH_RESTART;
- } else {
- Eterm erlen = erts_make_integer((Uint) bm->len, p);
- ret = erts_make_integer(pos,p);
- hp = HAlloc(p,3);
- ret = TUPLE2(hp, ret, erlen);
- }
- erts_free_aligned_binary_bytes(temp_alloc);
- BUMP_REDS(p, (save_reds - reds) / BM_LOOP_FACTOR);
- *res_term = ret;
- return DO_BIN_MATCH_OK;
- } else if (type == am_ac) {
- ACTrie *act;
- Uint pos, rlen;
- int acr;
- ACFindFirstState state;
- Eterm ret;
- Eterm *hp;
- Uint reds = get_reds(p, AC_LOOP_FACTOR);
- Uint save_reds = reds;
+#define BINARY_FIND_ALL 0x01
+#define BINARY_SPLIT_TRIM 0x02
+#define BINARY_SPLIT_TRIM_ALL 0x04
- act = (ACTrie *) ERTS_MAGIC_BIN_DATA(bin);
-#ifdef HARDDEBUG
- dump_ac_trie(act);
-#endif
- if (state_term == NIL) {
- ac_init_find_first_match(&state, act, hsstart, hsend);
- } else {
- Eterm *ptr = big_val(state_term);
- memcpy(&state,ptr+2,sizeof(state));
- }
- acr = ac_find_first_match(&state, bytes, &pos, &rlen, &reds);
- if (acr == AC_NOT_FOUND) {
- ret = am_nomatch;
- } else if (acr == AC_RESTART) {
- int x = (sizeof(state) / sizeof(Eterm)) +
- !!(sizeof(ACFindFirstState) % sizeof(Eterm));
-#ifdef HARDDEBUG
- erts_printf("Trap ac!\n");
-#endif
- hp = HAlloc(p,x+2);
- hp[0] = make_pos_bignum_header(x+1);
- hp[1] = type;
- memcpy(hp+2,&state,sizeof(state));
- *res_term = make_big(hp);
- erts_free_aligned_binary_bytes(temp_alloc);
- return DO_BIN_MATCH_RESTART;
- } else {
- Eterm epos = erts_make_integer(pos,p);
- Eterm erlen = erts_make_integer(rlen,p);
- hp = HAlloc(p,3);
- ret = TUPLE2(hp, epos, erlen);
- }
- erts_free_aligned_binary_bytes(temp_alloc);
- BUMP_REDS(p, (save_reds - reds) / AC_LOOP_FACTOR);
- *res_term = ret;
- return DO_BIN_MATCH_OK;
- }
- badarg:
- return DO_BIN_MATCH_BADARG;
-}
+typedef struct BinaryFindState {
+ Eterm type;
+ Uint flags;
+ Uint hsstart;
+ Uint hsend;
+ Eterm (*not_found_result) (Process *, Eterm, struct BinaryFindState *);
+ Eterm (*single_result) (Process *, Eterm, struct BinaryFindState *, Sint, Sint);
+ Eterm (*global_result) (Process *, Eterm, struct BinaryFindState *, FindallData *, Uint);
+} BinaryFindState;
+
+typedef struct BinaryFindState_bignum {
+ Eterm bignum_hdr;
+ BinaryFindState bfs;
+ union {
+ BMFindFirstState bmffs;
+ BMFindAllState bmfas;
+ ACFindFirstState acffs;
+ ACFindAllState acfas;
+ } data;
+} BinaryFindState_bignum;
+
+#define SIZEOF_BINARY_FIND_STATE(S) \
+ (sizeof(BinaryFindState)+sizeof(S))
+
+#define SIZEOF_BINARY_FIND_ALL_STATE(S) \
+ (sizeof(BinaryFindState)+sizeof(S)+(sizeof(FindallData)*(S).m))
+
+static Eterm do_match_not_found_result(Process *p, Eterm subject, BinaryFindState *bfs);
+static Eterm do_match_single_result(Process *p, Eterm subject, BinaryFindState *bfs,
+ Sint pos, Sint len);
+static Eterm do_match_global_result(Process *p, Eterm subject, BinaryFindState *bfs,
+ FindallData *fad, Uint fad_sz);
+static Eterm do_split_not_found_result(Process *p, Eterm subject, BinaryFindState *bfs);
+static Eterm do_split_single_result(Process *p, Eterm subject, BinaryFindState *bfs,
+ Sint pos, Sint len);
+static Eterm do_split_global_result(Process *p, Eterm subject, BinaryFindState *bfs,
+ FindallData *fad, Uint fad_sz);
-static int do_binary_matches(Process *p, Eterm subject, Uint hsstart,
- Uint hsend, Eterm type, Binary *bin,
- Eterm state_term, Eterm *res_term)
+static int parse_match_opts_list(Eterm l, Eterm bin, Uint *posp, Uint *endp)
{
- byte *bytes;
- Uint bitoffs, bitsize;
- byte *temp_alloc = NULL;
-
- ERTS_GET_BINARY_BYTES(subject, bytes, bitoffs, bitsize);
- if (bitsize != 0) {
- goto badarg;
- }
- if (bitoffs != 0) {
- bytes = erts_get_aligned_binary_bytes(subject, &temp_alloc);
- }
- if (state_term != NIL) {
- Eterm *ptr = big_val(state_term);
- type = ptr[1];
- }
-
- if (type == am_bm) {
- BMData *bm;
- Sint pos;
- Eterm ret,tpl;
- Eterm *hp;
- BMFindAllState state;
- Uint reds = get_reds(p, BM_LOOP_FACTOR);
- Uint save_reds = reds;
-
- bm = (BMData *) ERTS_MAGIC_BIN_DATA(bin);
-#ifdef HARDDEBUG
- dump_bm_data(bm);
-#endif
- if (state_term == NIL) {
- bm_init_find_all(&state, hsstart, hsend);
- } else {
- Eterm *ptr = big_val(state_term);
- bm_restore_find_all(&state,(char *) (ptr+2));
- }
-
- pos = bm_find_all_non_overlapping(&state, bm, bytes, &reds);
- if (pos == BM_NOT_FOUND) {
- ret = NIL;
- } else if (pos == BM_RESTART) {
- int x =
- (SIZEOF_BM_SERIALIZED_FIND_ALL_STATE(state) / sizeof(Eterm)) +
- !!(SIZEOF_BM_SERIALIZED_FIND_ALL_STATE(state) % sizeof(Eterm));
-#ifdef HARDDEBUG
- erts_printf("Trap bm!\n");
-#endif
- hp = HAlloc(p,x+2);
- hp[0] = make_pos_bignum_header(x+1);
- hp[1] = type;
- bm_serialize_find_all(&state, (char *) (hp+2));
- *res_term = make_big(hp);
- erts_free_aligned_binary_bytes(temp_alloc);
- bm_clean_find_all(&state);
- return DO_BIN_MATCH_RESTART;
- } else {
- FindallData *fad = state.out;
- int i;
- for (i = 0; i < state.m; ++i) {
- fad[i].epos = erts_make_integer(fad[i].pos,p);
- fad[i].elen = erts_make_integer(fad[i].len,p);
+ Eterm *tp;
+ Uint pos;
+ Sint len;
+ if (l == THE_NON_VALUE || l == NIL) {
+ /* Invalid term or NIL, we're called from binary_match(es)_2 or
+ have no options*/
+ *posp = 0;
+ *endp = binary_size(bin);
+ return 0;
+ } else if (is_list(l)) {
+ while(is_list(l)) {
+ Eterm t = CAR(list_val(l));
+ Uint orig_size;
+ if (!is_tuple(t)) {
+ goto badarg;
}
- hp = HAlloc(p,state.m * (3 + 2));
- ret = NIL;
- for (i = state.m - 1; i >= 0; --i) {
- tpl = TUPLE2(hp, fad[i].epos, fad[i].elen);
- hp +=3;
- ret = CONS(hp,tpl,ret);
- hp += 2;
+ tp = tuple_val(t);
+ if (arityval(*tp) != 2) {
+ goto badarg;
}
- }
- erts_free_aligned_binary_bytes(temp_alloc);
- bm_clean_find_all(&state);
- BUMP_REDS(p, (save_reds - reds) / BM_LOOP_FACTOR);
- *res_term = ret;
- return DO_BIN_MATCH_OK;
- } else if (type == am_ac) {
- ACTrie *act;
- int acr;
- ACFindAllState state;
- Eterm ret,tpl;
- Eterm *hp;
- Uint reds = get_reds(p, AC_LOOP_FACTOR);
- Uint save_reds = reds;
-
- act = (ACTrie *) ERTS_MAGIC_BIN_DATA(bin);
-#ifdef HARDDEBUG
- dump_ac_trie(act);
-#endif
- if (state_term == NIL) {
- ac_init_find_all(&state, act, hsstart, hsend);
- } else {
- Eterm *ptr = big_val(state_term);
- ac_restore_find_all(&state,(char *) (ptr+2));
- }
- acr = ac_find_all_non_overlapping(&state, bytes, &reds);
- if (acr == AC_NOT_FOUND) {
- ret = NIL;
- } else if (acr == AC_RESTART) {
- int x =
- (SIZEOF_AC_SERIALIZED_FIND_ALL_STATE(state) / sizeof(Eterm)) +
- !!(SIZEOF_AC_SERIALIZED_FIND_ALL_STATE(state) % sizeof(Eterm));
-#ifdef HARDDEBUG
- erts_printf("Trap ac!\n");
-#endif
- hp = HAlloc(p,x+2);
- hp[0] = make_pos_bignum_header(x+1);
- hp[1] = type;
- ac_serialize_find_all(&state, (char *) (hp+2));
- *res_term = make_big(hp);
- erts_free_aligned_binary_bytes(temp_alloc);
- ac_clean_find_all(&state);
- return DO_BIN_MATCH_RESTART;
- } else {
- FindallData *fad = state.out;
- int i;
- for (i = 0; i < state.m; ++i) {
- fad[i].epos = erts_make_integer(fad[i].pos,p);
- fad[i].elen = erts_make_integer(fad[i].len,p);
+ if (tp[1] != am_scope || is_not_tuple(tp[2])) {
+ goto badarg;
}
- hp = HAlloc(p,state.m * (3 + 2));
- ret = NIL;
- for (i = state.m - 1; i >= 0; --i) {
- tpl = TUPLE2(hp, fad[i].epos, fad[i].elen);
- hp +=3;
- ret = CONS(hp,tpl,ret);
- hp += 2;
+ tp = tuple_val(tp[2]);
+ if (arityval(*tp) != 2) {
+ goto badarg;
+ }
+ if (!term_to_Uint(tp[1], &pos)) {
+ goto badarg;
}
+ if (!term_to_Sint(tp[2], &len)) {
+ goto badarg;
+ }
+ if (len < 0) {
+ Uint lentmp = -(Uint)len;
+ /* overflow */
+ if ((Sint)lentmp < 0) {
+ goto badarg;
+ }
+ len = lentmp;
+ pos -= len;
+ }
+ /* overflow */
+ if ((pos + len) < pos || (len > 0 && (pos + len) == pos)) {
+ goto badarg;
+ }
+ *endp = len + pos;
+ *posp = pos;
+ if ((orig_size = binary_size(bin)) < pos ||
+ orig_size < (*endp)) {
+ goto badarg;
+ }
+ l = CDR(list_val(l));
}
- erts_free_aligned_binary_bytes(temp_alloc);
- ac_clean_find_all(&state);
- BUMP_REDS(p, (save_reds - reds) / AC_LOOP_FACTOR);
- *res_term = ret;
- return DO_BIN_MATCH_OK;
+ return 0;
+ } else {
+ badarg:
+ return 1;
}
- badarg:
- return DO_BIN_MATCH_BADARG;
}
-static int parse_match_opts_list(Eterm l, Eterm bin, Uint *posp, Uint *endp)
+static int parse_split_opts_list(Eterm l, Eterm bin, Uint *posp, Uint *endp, Uint *optp)
{
Eterm *tp;
Uint pos;
Sint len;
- if (l == ((Eterm) 0) || l == NIL) {
- /* Invalid term or NIL, we're called from binary_match(es)_2 or
- have no options*/
- *posp = 0;
- *endp = binary_size(bin);
+ *optp = 0;
+ *posp = 0;
+ *endp = binary_size(bin);
+ if (l == THE_NON_VALUE || l == NIL) {
return 0;
} else if (is_list(l)) {
while(is_list(l)) {
Eterm t = CAR(list_val(l));
Uint orig_size;
+ if (is_atom(t)) {
+ if (t == am_global) {
+ *optp |= BINARY_FIND_ALL;
+ l = CDR(list_val(l));
+ continue;
+ }
+ if (t == am_trim) {
+ *optp |= BINARY_SPLIT_TRIM;
+ l = CDR(list_val(l));
+ continue;
+ }
+ if (t == am_trim_all) {
+ *optp |= BINARY_SPLIT_TRIM_ALL;
+ l = CDR(list_val(l));
+ continue;
+ }
+ }
if (!is_tuple(t)) {
goto badarg;
}
@@ -1355,48 +1204,207 @@ static int parse_match_opts_list(Eterm l, Eterm bin, Uint *posp, Uint *endp)
}
}
-static BIF_RETTYPE binary_match_trap(BIF_ALIST_3)
+static int do_binary_find(Process *p, Eterm subject, BinaryFindState *bfs, Binary *bin,
+ Eterm state_term, Eterm *res_term)
{
- int runres;
- Eterm result;
- Binary *bin = ((ProcBin *) binary_val(BIF_ARG_3))->val;
- runres = do_binary_match(BIF_P,BIF_ARG_1,0,0,NIL,bin,BIF_ARG_2,&result);
- if (runres == DO_BIN_MATCH_OK) {
- BIF_RET(result);
- } else {
- BUMP_ALL_REDS(BIF_P);
- BIF_TRAP3(&binary_match_trap_export, BIF_P, BIF_ARG_1, result,
- BIF_ARG_3);
+ byte *bytes;
+ Uint bitoffs, bitsize;
+ byte *temp_alloc = NULL;
+ BinaryFindState_bignum *state_ptr = NULL;
+
+ ERTS_GET_BINARY_BYTES(subject, bytes, bitoffs, bitsize);
+ if (bitsize != 0) {
+ goto badarg;
+ }
+ if (bitoffs != 0) {
+ bytes = erts_get_aligned_binary_bytes(subject, &temp_alloc);
+ }
+ if (state_term != NIL) {
+ state_ptr = (BinaryFindState_bignum *)(big_val(state_term));
+ bfs = &(state_ptr->bfs);
}
-}
-static BIF_RETTYPE binary_matches_trap(BIF_ALIST_3)
-{
- int runres;
- Eterm result;
- Binary *bin = ((ProcBin *) binary_val(BIF_ARG_3))->val;
- runres = do_binary_matches(BIF_P,BIF_ARG_1,0,0,NIL,bin,BIF_ARG_2,&result);
- if (runres == DO_BIN_MATCH_OK) {
- BIF_RET(result);
+ if (bfs->flags & BINARY_FIND_ALL) {
+ if (bfs->type == am_bm) {
+ BMData *bm;
+ Sint pos;
+ BMFindAllState state;
+ Uint reds = get_reds(p, BM_LOOP_FACTOR);
+ Uint save_reds = reds;
+
+ bm = (BMData *) ERTS_MAGIC_BIN_DATA(bin);
+#ifdef HARDDEBUG
+ dump_bm_data(bm);
+#endif
+ if (state_term == NIL) {
+ bm_init_find_all(&state, bfs->hsstart, bfs->hsend);
+ } else {
+ bm_restore_find_all(&state, &(state_ptr->data.bmfas));
+ }
+
+ pos = bm_find_all_non_overlapping(&state, bm, bytes, &reds);
+ if (pos == BM_NOT_FOUND) {
+ *res_term = bfs->not_found_result(p, subject, bfs);
+ } else if (pos == BM_RESTART) {
+ int x =
+ (SIZEOF_BINARY_FIND_ALL_STATE(state) / sizeof(Eterm)) +
+ !!(SIZEOF_BINARY_FIND_ALL_STATE(state) % sizeof(Eterm));
+#ifdef HARDDEBUG
+ erts_printf("Trap bm!\n");
+#endif
+ state_ptr = (BinaryFindState_bignum*) HAlloc(p, x+1);
+ state_ptr->bignum_hdr = make_pos_bignum_header(x);
+ memcpy(&state_ptr->bfs, bfs, sizeof(BinaryFindState));
+ bm_serialize_find_all(&state, &state_ptr->data.bmfas);
+ *res_term = make_big(&state_ptr->bignum_hdr);
+ erts_free_aligned_binary_bytes(temp_alloc);
+ bm_clean_find_all(&state);
+ return DO_BIN_MATCH_RESTART;
+ } else {
+ *res_term = bfs->global_result(p, subject, bfs, state.out, state.m);
+ }
+ erts_free_aligned_binary_bytes(temp_alloc);
+ bm_clean_find_all(&state);
+ BUMP_REDS(p, (save_reds - reds) / BM_LOOP_FACTOR);
+ return DO_BIN_MATCH_OK;
+ } else if (bfs->type == am_ac) {
+ ACTrie *act;
+ int acr;
+ ACFindAllState state;
+ Uint reds = get_reds(p, AC_LOOP_FACTOR);
+ Uint save_reds = reds;
+
+ act = (ACTrie *) ERTS_MAGIC_BIN_DATA(bin);
+#ifdef HARDDEBUG
+ dump_ac_trie(act);
+#endif
+ if (state_term == NIL) {
+ ac_init_find_all(&state, act, bfs->hsstart, bfs->hsend);
+ } else {
+ ac_restore_find_all(&state, &(state_ptr->data.acfas));
+ }
+ acr = ac_find_all_non_overlapping(&state, bytes, &reds);
+ if (acr == AC_NOT_FOUND) {
+ *res_term = bfs->not_found_result(p, subject, bfs);
+ } else if (acr == AC_RESTART) {
+ int x =
+ (SIZEOF_BINARY_FIND_ALL_STATE(state) / sizeof(Eterm)) +
+ !!(SIZEOF_BINARY_FIND_ALL_STATE(state) % sizeof(Eterm));
+#ifdef HARDDEBUG
+ erts_printf("Trap ac!\n");
+#endif
+ state_ptr = (BinaryFindState_bignum*) HAlloc(p, x+1);
+ state_ptr->bignum_hdr = make_pos_bignum_header(x);
+ memcpy(&state_ptr->bfs, bfs, sizeof(BinaryFindState));
+ ac_serialize_find_all(&state, &state_ptr->data.acfas);
+ *res_term = make_big(&state_ptr->bignum_hdr);
+ erts_free_aligned_binary_bytes(temp_alloc);
+ ac_clean_find_all(&state);
+ return DO_BIN_MATCH_RESTART;
+ } else {
+ *res_term = bfs->global_result(p, subject, bfs, state.out, state.m);
+ }
+ erts_free_aligned_binary_bytes(temp_alloc);
+ ac_clean_find_all(&state);
+ BUMP_REDS(p, (save_reds - reds) / AC_LOOP_FACTOR);
+ return DO_BIN_MATCH_OK;
+ }
} else {
- BUMP_ALL_REDS(BIF_P);
- BIF_TRAP3(&binary_matches_trap_export, BIF_P, BIF_ARG_1, result,
- BIF_ARG_3);
- }
-}
+ if (bfs->type == am_bm) {
+ BMData *bm;
+ Sint pos;
+ BMFindFirstState state;
+ Uint reds = get_reds(p, BM_LOOP_FACTOR);
+ Uint save_reds = reds;
+
+ bm = (BMData *) ERTS_MAGIC_BIN_DATA(bin);
+#ifdef HARDDEBUG
+ dump_bm_data(bm);
+#endif
+ if (state_term == NIL) {
+ bm_init_find_first_match(&state, bfs->hsstart, bfs->hsend);
+ } else {
+ memcpy(&state, &state_ptr->data.bmffs, sizeof(BMFindFirstState));
+ }
-BIF_RETTYPE binary_match_3(BIF_ALIST_3)
-{
- return binary_match(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+#ifdef HARDDEBUG
+ erts_printf("(bm) state->pos = %ld, state->len = %lu\n",state.pos,
+ state.len);
+#endif
+ pos = bm_find_first_match(&state, bm, bytes, &reds);
+ if (pos == BM_NOT_FOUND) {
+ *res_term = bfs->not_found_result(p, subject, bfs);
+ } else if (pos == BM_RESTART) {
+ int x =
+ (SIZEOF_BINARY_FIND_STATE(state) / sizeof(Eterm)) +
+ !!(SIZEOF_BINARY_FIND_STATE(state) % sizeof(Eterm));
+#ifdef HARDDEBUG
+ erts_printf("Trap bm!\n");
+#endif
+ state_ptr = (BinaryFindState_bignum*) HAlloc(p, x+1);
+ state_ptr->bignum_hdr = make_pos_bignum_header(x);
+ memcpy(&state_ptr->bfs, bfs, sizeof(BinaryFindState));
+ memcpy(&state_ptr->data.acffs, &state, sizeof(BMFindFirstState));
+ *res_term = make_big(&state_ptr->bignum_hdr);
+ erts_free_aligned_binary_bytes(temp_alloc);
+ return DO_BIN_MATCH_RESTART;
+ } else {
+ *res_term = bfs->single_result(p, subject, bfs, pos, bm->len);
+ }
+ erts_free_aligned_binary_bytes(temp_alloc);
+ BUMP_REDS(p, (save_reds - reds) / BM_LOOP_FACTOR);
+ return DO_BIN_MATCH_OK;
+ } else if (bfs->type == am_ac) {
+ ACTrie *act;
+ Uint pos, rlen;
+ int acr;
+ ACFindFirstState state;
+ Uint reds = get_reds(p, AC_LOOP_FACTOR);
+ Uint save_reds = reds;
+
+ act = (ACTrie *) ERTS_MAGIC_BIN_DATA(bin);
+#ifdef HARDDEBUG
+ dump_ac_trie(act);
+#endif
+ if (state_term == NIL) {
+ ac_init_find_first_match(&state, act, bfs->hsstart, bfs->hsend);
+ } else {
+ memcpy(&state, &state_ptr->data.acffs, sizeof(ACFindFirstState));
+ }
+ acr = ac_find_first_match(&state, bytes, &pos, &rlen, &reds);
+ if (acr == AC_NOT_FOUND) {
+ *res_term = bfs->not_found_result(p, subject, bfs);
+ } else if (acr == AC_RESTART) {
+ int x =
+ (SIZEOF_BINARY_FIND_STATE(state) / sizeof(Eterm)) +
+ !!(SIZEOF_BINARY_FIND_STATE(state) % sizeof(Eterm));
+#ifdef HARDDEBUG
+ erts_printf("Trap ac!\n");
+#endif
+ state_ptr = (BinaryFindState_bignum*) HAlloc(p, x+1);
+ state_ptr->bignum_hdr = make_pos_bignum_header(x);
+ memcpy(&state_ptr->bfs, bfs, sizeof(BinaryFindState));
+ memcpy(&state_ptr->data.acffs, &state, sizeof(ACFindFirstState));
+ *res_term = make_big(&state_ptr->bignum_hdr);
+ erts_free_aligned_binary_bytes(temp_alloc);
+ return DO_BIN_MATCH_RESTART;
+ } else {
+ *res_term = bfs->single_result(p, subject, bfs, pos, rlen);
+ }
+ erts_free_aligned_binary_bytes(temp_alloc);
+ BUMP_REDS(p, (save_reds - reds) / AC_LOOP_FACTOR);
+ return DO_BIN_MATCH_OK;
+ }
+ }
+ badarg:
+ return DO_BIN_MATCH_BADARG;
}
static BIF_RETTYPE
-binary_match(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
+binary_match(Process *p, Eterm arg1, Eterm arg2, Eterm arg3, Uint flags)
{
- Uint hsstart;
- Uint hsend;
+ BinaryFindState bfs;
Eterm *tp;
- Eterm type;
Binary *bin;
Eterm bin_term = NIL;
int runres;
@@ -1405,11 +1413,12 @@ binary_match(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
if (is_not_binary(arg1)) {
goto badarg;
}
- if (parse_match_opts_list(arg3,arg1,&hsstart,&hsend)) {
+ bfs.flags = flags;
+ if (parse_match_opts_list(arg3, arg1, &(bfs.hsstart), &(bfs.hsend))) {
goto badarg;
}
- if (hsend == 0) {
- BIF_RET(am_nomatch);
+ if (bfs.hsend == 0) {
+ BIF_RET(do_match_not_found_result(p, arg1, &bfs));
}
if (is_tuple(arg2)) {
tp = tuple_val(arg2);
@@ -1420,21 +1429,24 @@ binary_match(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
!ERTS_TERM_IS_MAGIC_BINARY(tp[2])) {
goto badarg;
}
- type = tp[1];
+ bfs.type = tp[1];
bin = ((ProcBin *) binary_val(tp[2]))->val;
- if (type == am_bm &&
+ if (bfs.type == am_bm &&
ERTS_MAGIC_BIN_DESTRUCTOR(bin) != cleanup_my_data_bm) {
goto badarg;
}
- if (type == am_ac &&
+ if (bfs.type == am_ac &&
ERTS_MAGIC_BIN_DESTRUCTOR(bin) != cleanup_my_data_ac) {
goto badarg;
}
bin_term = tp[2];
- } else if (do_binary_match_compile(arg2,&type,&bin)) {
+ } else if (do_binary_match_compile(arg2, &(bfs.type), &bin)) {
goto badarg;
}
- runres = do_binary_match(p,arg1,hsstart,hsend,type,bin,NIL,&result);
+ bfs.not_found_result = &do_match_not_found_result;
+ bfs.single_result = &do_match_single_result;
+ bfs.global_result = &do_match_global_result;
+ runres = do_binary_find(p, arg1, &bfs, bin, NIL, &result);
if (runres == DO_BIN_MATCH_RESTART && bin_term == NIL) {
Eterm *hp = HAlloc(p, PROC_BIN_SIZE);
bin_term = erts_mk_magic_binary_term(&hp, &MSO(p), bin);
@@ -1446,7 +1458,7 @@ binary_match(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
BIF_RET(result);
case DO_BIN_MATCH_RESTART:
BUMP_ALL_REDS(p);
- BIF_TRAP3(&binary_match_trap_export, p, arg1, result, bin_term);
+ BIF_TRAP3(&binary_find_trap_export, p, arg1, result, bin_term);
default:
goto badarg;
}
@@ -1454,17 +1466,31 @@ binary_match(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
BIF_ERROR(p,BADARG);
}
+BIF_RETTYPE binary_match_2(BIF_ALIST_2)
+{
+ return binary_match(BIF_P, BIF_ARG_1, BIF_ARG_2, THE_NON_VALUE, 0);
+}
+
+BIF_RETTYPE binary_match_3(BIF_ALIST_3)
+{
+ return binary_match(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3, 0);
+}
+
+BIF_RETTYPE binary_matches_2(BIF_ALIST_2)
+{
+ return binary_match(BIF_P, BIF_ARG_1, BIF_ARG_2, THE_NON_VALUE, BINARY_FIND_ALL);
+}
+
BIF_RETTYPE binary_matches_3(BIF_ALIST_3)
{
- return binary_matches(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+ return binary_match(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3, BINARY_FIND_ALL);
}
static BIF_RETTYPE
-binary_matches(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
+binary_split(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
{
- Uint hsstart, hsend;
+ BinaryFindState bfs;
Eterm *tp;
- Eterm type;
Binary *bin;
Eterm bin_term = NIL;
int runres;
@@ -1473,11 +1499,12 @@ binary_matches(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
if (is_not_binary(arg1)) {
goto badarg;
}
- if (parse_match_opts_list(arg3,arg1,&hsstart,&hsend)) {
+ if (parse_split_opts_list(arg3, arg1, &(bfs.hsstart), &(bfs.hsend), &(bfs.flags))) {
goto badarg;
}
- if (hsend == 0) {
- BIF_RET(NIL);
+ if (bfs.hsend == 0) {
+ result = do_split_not_found_result(p, arg1, &bfs);
+ BIF_RET(result);
}
if (is_tuple(arg2)) {
tp = tuple_val(arg2);
@@ -1488,54 +1515,267 @@ binary_matches(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
!ERTS_TERM_IS_MAGIC_BINARY(tp[2])) {
goto badarg;
}
- type = tp[1];
+ bfs.type = tp[1];
bin = ((ProcBin *) binary_val(tp[2]))->val;
- if (type == am_bm &&
+ if (bfs.type == am_bm &&
ERTS_MAGIC_BIN_DESTRUCTOR(bin) != cleanup_my_data_bm) {
goto badarg;
}
- if (type == am_ac &&
+ if (bfs.type == am_ac &&
ERTS_MAGIC_BIN_DESTRUCTOR(bin) != cleanup_my_data_ac) {
goto badarg;
}
bin_term = tp[2];
- } else if (do_binary_match_compile(arg2,&type,&bin)) {
+ } else if (do_binary_match_compile(arg2, &(bfs.type), &bin)) {
goto badarg;
}
- runres = do_binary_matches(p,arg1,hsstart,hsend,type,bin,
- NIL,&result);
+ bfs.not_found_result = &do_split_not_found_result;
+ bfs.single_result = &do_split_single_result;
+ bfs.global_result = &do_split_global_result;
+ runres = do_binary_find(p, arg1, &bfs, bin, NIL, &result);
if (runres == DO_BIN_MATCH_RESTART && bin_term == NIL) {
Eterm *hp = HAlloc(p, PROC_BIN_SIZE);
bin_term = erts_mk_magic_binary_term(&hp, &MSO(p), bin);
} else if (bin_term == NIL) {
erts_bin_free(bin);
}
- switch (runres) {
+ switch(runres) {
case DO_BIN_MATCH_OK:
BIF_RET(result);
case DO_BIN_MATCH_RESTART:
- BUMP_ALL_REDS(p);
- BIF_TRAP3(&binary_matches_trap_export, p, arg1, result,
- bin_term);
+ BIF_TRAP3(&binary_find_trap_export, p, arg1, result, bin_term);
default:
goto badarg;
}
badarg:
- BIF_ERROR(p,BADARG);
+ BIF_ERROR(p, BADARG);
}
+BIF_RETTYPE binary_split_2(BIF_ALIST_2)
+{
+ return binary_split(BIF_P, BIF_ARG_1, BIF_ARG_2, THE_NON_VALUE);
+}
-BIF_RETTYPE binary_match_2(BIF_ALIST_2)
+BIF_RETTYPE binary_split_3(BIF_ALIST_3)
{
- return binary_match(BIF_P,BIF_ARG_1,BIF_ARG_2,((Eterm) 0));
+ return binary_split(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+}
+
+static Eterm do_match_not_found_result(Process *p, Eterm subject, BinaryFindState *bfs)
+{
+ if (bfs->flags & BINARY_FIND_ALL) {
+ return NIL;
+ } else {
+ return am_nomatch;
+ }
}
+static Eterm do_match_single_result(Process *p, Eterm subject, BinaryFindState *bfs,
+ Sint pos, Sint len)
+{
+ Eterm erlen;
+ Eterm *hp;
+ Eterm ret;
-BIF_RETTYPE binary_matches_2(BIF_ALIST_2)
+ erlen = erts_make_integer((Uint)(len), p);
+ ret = erts_make_integer(pos, p);
+ hp = HAlloc(p, 3);
+ ret = TUPLE2(hp, ret, erlen);
+
+ return ret;
+}
+
+static Eterm do_match_global_result(Process *p, Eterm subject, BinaryFindState *bfs,
+ FindallData *fad, Uint fad_sz)
+{
+ Sint i;
+ Eterm tpl;
+ Eterm *hp;
+ Eterm ret;
+
+ for (i = 0; i < fad_sz; ++i) {
+ fad[i].epos = erts_make_integer(fad[i].pos, p);
+ fad[i].elen = erts_make_integer(fad[i].len, p);
+ }
+ hp = HAlloc(p, fad_sz * (3 + 2));
+ ret = NIL;
+ for (i = fad_sz - 1; i >= 0; --i) {
+ tpl = TUPLE2(hp, fad[i].epos, fad[i].elen);
+ hp += 3;
+ ret = CONS(hp, tpl, ret);
+ hp += 2;
+ }
+
+ return ret;
+}
+
+static Eterm do_split_not_found_result(Process *p, Eterm subject, BinaryFindState *bfs)
{
- return binary_matches(BIF_P,BIF_ARG_1,BIF_ARG_2,((Eterm) 0));
+ Eterm *hp;
+ Eterm ret;
+
+ if (bfs->flags & (BINARY_SPLIT_TRIM | BINARY_SPLIT_TRIM_ALL)
+ && binary_size(subject) == 0) {
+ return NIL;
+ }
+ hp = HAlloc(p, 2);
+ ret = CONS(hp, subject, NIL);
+
+ return ret;
}
+static Eterm do_split_single_result(Process *p, Eterm subject, BinaryFindState *bfs,
+ Sint pos, Sint len)
+{
+ size_t orig_size;
+ Eterm orig;
+ Uint offset;
+ Uint bit_offset;
+ Uint bit_size;
+ ErlSubBin *sb1;
+ ErlSubBin *sb2;
+ Eterm *hp;
+ Eterm ret;
+
+ orig_size = binary_size(subject);
+
+ if ((bfs->flags & (BINARY_SPLIT_TRIM | BINARY_SPLIT_TRIM_ALL)) &&
+ (orig_size - pos - len) == 0) {
+ if (pos == 0) {
+ ret = NIL;
+ } else {
+ hp = HAlloc(p, (ERL_SUB_BIN_SIZE + 2));
+ ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size);
+ sb1 = (ErlSubBin *) hp;
+ sb1->thing_word = HEADER_SUB_BIN;
+ sb1->size = pos;
+ sb1->offs = offset;
+ sb1->orig = orig;
+ sb1->bitoffs = bit_offset;
+ sb1->bitsize = bit_size;
+ sb1->is_writable = 0;
+ hp += ERL_SUB_BIN_SIZE;
+
+ ret = CONS(hp, make_binary(sb1), NIL);
+ hp += 2;
+ }
+ } else {
+ if ((bfs->flags & BINARY_SPLIT_TRIM_ALL) && (pos == 0)) {
+ hp = HAlloc(p, 1 * (ERL_SUB_BIN_SIZE + 2));
+ ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size);
+ sb1 = NULL;
+ } else {
+ hp = HAlloc(p, 2 * (ERL_SUB_BIN_SIZE + 2));
+ ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size);
+ sb1 = (ErlSubBin *) hp;
+ sb1->thing_word = HEADER_SUB_BIN;
+ sb1->size = pos;
+ sb1->offs = offset;
+ sb1->orig = orig;
+ sb1->bitoffs = bit_offset;
+ sb1->bitsize = 0;
+ sb1->is_writable = 0;
+ hp += ERL_SUB_BIN_SIZE;
+ }
+
+ sb2 = (ErlSubBin *) hp;
+ sb2->thing_word = HEADER_SUB_BIN;
+ sb2->size = orig_size - pos - len;
+ sb2->offs = offset + pos + len;
+ sb2->orig = orig;
+ sb2->bitoffs = bit_offset;
+ sb2->bitsize = bit_size;
+ sb2->is_writable = 0;
+ hp += ERL_SUB_BIN_SIZE;
+
+ ret = CONS(hp, make_binary(sb2), NIL);
+ hp += 2;
+ if (sb1 != NULL) {
+ ret = CONS(hp, make_binary(sb1), ret);
+ hp += 2;
+ }
+ }
+ return ret;
+}
+
+static Eterm do_split_global_result(Process *p, Eterm subject, BinaryFindState *bfs,
+ FindallData *fad, Uint fad_sz)
+{
+ size_t orig_size;
+ Eterm orig;
+ Uint offset;
+ Uint bit_offset;
+ Uint bit_size;
+ ErlSubBin *sb;
+ Sint i;
+ Sint tail;
+ Uint list_size;
+ Uint end_pos;
+ Uint do_trim = bfs->flags & (BINARY_SPLIT_TRIM | BINARY_SPLIT_TRIM_ALL);
+ Eterm *hp;
+ Eterm *hendp;
+ Eterm ret;
+
+ tail = fad_sz - 1;
+ list_size = fad_sz + 1;
+ orig_size = binary_size(subject);
+ end_pos = (Uint)(orig_size);
+
+ hp = HAlloc(p, list_size * (ERL_SUB_BIN_SIZE + 2));
+ hendp = hp + list_size * (ERL_SUB_BIN_SIZE + 2);
+ ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size);
+ ASSERT(bit_size == 0);
+
+ ret = NIL;
+
+ for (i = tail; i >= 0; --i) {
+ sb = (ErlSubBin *)(hp);
+ sb->size = end_pos - (fad[i].pos + fad[i].len);
+ if (!(sb->size == 0 && do_trim)) {
+ sb->thing_word = HEADER_SUB_BIN;
+ sb->offs = offset + fad[i].pos + fad[i].len;
+ sb->orig = orig;
+ sb->bitoffs = bit_offset;
+ sb->bitsize = 0;
+ sb->is_writable = 0;
+ hp += ERL_SUB_BIN_SIZE;
+ ret = CONS(hp, make_binary(sb), ret);
+ hp += 2;
+ do_trim &= ~BINARY_SPLIT_TRIM;
+ }
+ end_pos = fad[i].pos;
+ }
+
+ sb = (ErlSubBin *)(hp);
+ sb->size = fad[0].pos;
+ if (!(sb->size == 0 && do_trim)) {
+ sb->thing_word = HEADER_SUB_BIN;
+ sb->offs = offset;
+ sb->orig = orig;
+ sb->bitoffs = bit_offset;
+ sb->bitsize = 0;
+ sb->is_writable = 0;
+ hp += ERL_SUB_BIN_SIZE;
+ ret = CONS(hp, make_binary(sb), ret);
+ hp += 2;
+ }
+ HRelease(p, hendp, hp);
+ return ret;
+}
+
+static BIF_RETTYPE binary_find_trap(BIF_ALIST_3)
+{
+ int runres;
+ Eterm result;
+ Binary *bin = ((ProcBin *) binary_val(BIF_ARG_3))->val;
+ runres = do_binary_find(BIF_P, BIF_ARG_1, NULL, bin, BIF_ARG_2, &result);
+ if (runres == DO_BIN_MATCH_OK) {
+ BIF_RET(result);
+ } else {
+ BUMP_ALL_REDS(BIF_P);
+ BIF_TRAP3(&binary_find_trap_export, BIF_P, BIF_ARG_1, result, BIF_ARG_3);
+ }
+}
BIF_RETTYPE erts_binary_part(Process *p, Eterm binary, Eterm epos, Eterm elen)
{
@@ -2550,7 +2790,6 @@ BIF_RETTYPE binary_referenced_byte_size_1(BIF_ALIST_1)
}
pb = (ProcBin *) binary_val(bin);
if (pb->thing_word == HEADER_PROC_BIN) {
- /* XXX:PaN - Halfword - orig_size is a long, we should handle that */
res = erts_make_integer((Uint) pb->val->orig_size, BIF_P);
} else { /* heap binary */
res = erts_make_integer((Uint) ((ErlHeapBin *) pb)->size, BIF_P);
@@ -2568,7 +2807,7 @@ BIF_RETTYPE binary_referenced_byte_size_1(BIF_ALIST_1)
#endif
static int get_need(Uint u) {
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
if (u > 0xFFFFFFFFUL) {
if (u > 0xFFFFFFFFFFFFUL) {
if (u > 0xFFFFFFFFFFFFFFUL) {
diff --git a/erts/emulator/beam/erl_bif_ddll.c b/erts/emulator/beam/erl_bif_ddll.c
index f4ef59993a..f006856b6a 100644
--- a/erts/emulator/beam/erl_bif_ddll.c
+++ b/erts/emulator/beam/erl_bif_ddll.c
@@ -1707,18 +1707,19 @@ static void notify_proc(Process *proc, Eterm ref, Eterm driver_name, Eterm type,
Eterm mess;
Eterm r;
Eterm *hp;
- ErlHeapFragment *bp;
- ErlOffHeap *ohp;
+ ErtsMessage *mp;
ErtsProcLocks rp_locks = 0;
+ ErlOffHeap *ohp;
ERTS_SMP_CHK_NO_PROC_LOCKS;
assert_drv_list_rwlocked();
if (errcode != 0) {
int need = load_error_need(errcode);
Eterm e;
- hp = erts_alloc_message_heap(6 /* tuple */ + 3 /* Error tuple */ +
- REF_THING_SIZE + need, &bp, &ohp,
- proc, &rp_locks);
+ mp = erts_alloc_message_heap(proc, &rp_locks,
+ (6 /* tuple */ + 3 /* Error tuple */ +
+ REF_THING_SIZE + need),
+ &hp, &ohp);
r = copy_ref(ref,hp);
hp += REF_THING_SIZE;
e = build_load_error_hp(hp, errcode);
@@ -1727,12 +1728,14 @@ static void notify_proc(Process *proc, Eterm ref, Eterm driver_name, Eterm type,
hp += 3;
mess = TUPLE5(hp,type,r,am_driver,driver_name,mess);
} else {
- hp = erts_alloc_message_heap(6 /* tuple */ + REF_THING_SIZE, &bp, &ohp, proc, &rp_locks);
+ mp = erts_alloc_message_heap(proc, &rp_locks,
+ 6 /* tuple */ + REF_THING_SIZE,
+ &hp, &ohp);
r = copy_ref(ref,hp);
hp += REF_THING_SIZE;
mess = TUPLE5(hp,type,r,am_driver,driver_name,tag);
}
- erts_queue_message(proc, &rp_locks, bp, mess, am_undefined);
+ erts_queue_message(proc, &rp_locks, mp, mess, am_undefined);
erts_smp_proc_unlock(proc, rp_locks);
ERTS_SMP_CHK_NO_PROC_LOCKS;
}
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 2c232c6c03..8c748c9bf7 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -64,6 +64,7 @@ static Export* alloc_sizes_trap = NULL;
static Export* gather_io_bytes_trap = NULL;
static Export *gather_sched_wall_time_res_trap;
+static Export *gather_msacc_res_trap;
static Export *gather_gc_info_res_trap;
static Export *gather_system_check_res_trap;
@@ -74,9 +75,6 @@ static char otp_version[] = ERLANG_OTP_VERSION;
static char erts_system_version[] = ("Erlang/OTP " ERLANG_OTP_RELEASE
"%s"
" [erts-" ERLANG_VERSION "]"
-#if !HEAP_ON_C_STACK && !HALFWORD_HEAP
- " [no-c-stack-objects]"
-#endif
#ifndef OTP_RELEASE
#ifdef ERLANG_GIT_VERSION
" [source-" ERLANG_GIT_VERSION "]"
@@ -85,12 +83,8 @@ static char erts_system_version[] = ("Erlang/OTP " ERLANG_OTP_RELEASE
#endif
#endif
#ifdef ARCH_64
-#if HALFWORD_HEAP
- " [64-bit halfword]"
-#else
" [64-bit]"
#endif
-#endif
#ifdef ERTS_SMP
" [smp:%beu:%beu]"
#endif
@@ -138,6 +132,9 @@ static char erts_system_version[] = ("Erlang/OTP " ERLANG_OTP_RELEASE
#ifdef USE_SYSTEMTAP
" [systemtap]"
#endif
+#ifdef SHCOPY
+ " [sharing-preserving]"
+#endif
"\n");
#define ASIZE(a) (sizeof(a)/sizeof(a[0]))
@@ -323,13 +320,11 @@ erts_print_system_version(int to, void *arg, Process *c_p)
char *ov = otp_version;
#ifdef ERTS_SMP
Uint total, online, active;
-#ifdef ERTS_DIRTY_SCHEDULERS
Uint dirty_cpu, dirty_cpu_onln, dirty_io;
- (void) erts_schedulers_state(&total, &online, &active, &dirty_cpu, &dirty_cpu_onln, &dirty_io, 0);
-#else
- (void) erts_schedulers_state(&total, &online, &active, NULL, NULL, NULL, 0);
-#endif
+ erts_schedulers_state(&total, &online, &active,
+ &dirty_cpu, &dirty_cpu_onln, NULL,
+ &dirty_io, NULL);
#endif
for (i = 0; i < sizeof(otp_version)-4; i++) {
if (ov[i] == '-' && ov[i+1] == 'r' && ov[i+2] == 'c')
@@ -597,6 +592,8 @@ static Eterm pi_args[] = {
am_min_bin_vheap_size,
am_current_location,
am_current_stacktrace,
+ am_message_queue_data,
+ am_garbage_collection_info
};
#define ERTS_PI_ARGS ((int) (sizeof(pi_args)/sizeof(Eterm)))
@@ -644,6 +641,8 @@ pi_arg2ix(Eterm arg)
case am_min_bin_vheap_size: return 28;
case am_current_location: return 29;
case am_current_stacktrace: return 30;
+ case am_message_queue_data: return 31;
+ case am_garbage_collection_info: return 32;
default: return -1;
}
}
@@ -672,18 +671,12 @@ static Eterm pi_1_keys[] = {
#define ERTS_PI_1_NO_OF_KEYS (sizeof(pi_1_keys)/sizeof(Eterm))
static Eterm pi_1_keys_list;
-#if HEAP_ON_C_STACK
static Eterm pi_1_keys_list_heap[2*ERTS_PI_1_NO_OF_KEYS];
-#endif
static void
process_info_init(void)
{
-#if HEAP_ON_C_STACK
Eterm *hp = &pi_1_keys_list_heap[0];
-#else
- Eterm *hp = erts_alloc(ERTS_ALC_T_LL_TEMP_TERM,sizeof(Eterm)*2*ERTS_PI_1_NO_OF_KEYS);
-#endif
int i;
pi_1_keys_list = NIL;
@@ -732,9 +725,10 @@ pi_pid2proc(Process *c_p, Eterm pid, ErtsProcLocks info_locks)
-BIF_RETTYPE
+static BIF_RETTYPE
process_info_aux(Process *BIF_P,
Process *rp,
+ ErtsProcLocks rp_locks,
Eterm rpid,
Eterm item,
int always_wrap);
@@ -825,10 +819,31 @@ process_info_list(Process *c_p, Eterm pid, Eterm list, int always_wrap,
*fail_type = ERTS_PI_FAIL_TYPE_AWAIT_EXIT;
goto done;
}
- else if (!(locks & ERTS_PROC_LOCK_STATUS)) {
- erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_STATUS);
+ else {
+ ErtsProcLocks unlock_locks = 0;
+
+ if (c_p == rp)
+ locks |= ERTS_PROC_LOCK_MAIN;
+
+ if (!(locks & ERTS_PROC_LOCK_STATUS))
+ unlock_locks |= ERTS_PROC_LOCK_STATUS;
+
+ if (locks & ERTS_PROC_LOCK_MSGQ) {
+ /*
+ * Move in queue into private queue and
+ * release msgq lock, enabling others to
+ * send messages to the process while it
+ * is being inspected...
+ */
+ ASSERT(locks & ERTS_PROC_LOCK_MAIN);
+ ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
+ locks &= ~ERTS_PROC_LOCK_MSGQ;
+ unlock_locks |= ERTS_PROC_LOCK_MSGQ;
+ }
+
+ if (unlock_locks)
+ erts_smp_proc_unlock(rp, unlock_locks);
}
-
/*
* We always handle 'messages' first if it should be part
@@ -840,7 +855,7 @@ process_info_list(Process *c_p, Eterm pid, Eterm list, int always_wrap,
if (want_messages) {
ix = pi_arg2ix(am_messages);
ASSERT(part_res[ix] == THE_NON_VALUE);
- part_res[ix] = process_info_aux(c_p, rp, pid, am_messages, always_wrap);
+ part_res[ix] = process_info_aux(c_p, rp, locks, pid, am_messages, always_wrap);
ASSERT(part_res[ix] != THE_NON_VALUE);
}
@@ -848,7 +863,7 @@ process_info_list(Process *c_p, Eterm pid, Eterm list, int always_wrap,
ix = res_elem_ix[res_elem_ix_ix];
if (part_res[ix] == THE_NON_VALUE) {
arg = pi_ix2arg(ix);
- part_res[ix] = process_info_aux(c_p, rp, pid, arg, always_wrap);
+ part_res[ix] = process_info_aux(c_p, rp, locks, pid, arg, always_wrap);
ASSERT(part_res[ix] != THE_NON_VALUE);
}
}
@@ -979,9 +994,31 @@ BIF_RETTYPE process_info_2(BIF_ALIST_2)
ERTS_BIF_AWAIT_X_DATA_TRAP(BIF_P, BIF_ARG_1, am_undefined);
}
else {
+ ErtsProcLocks unlock_locks = 0;
+
+ if (BIF_P == rp)
+ info_locks |= ERTS_PROC_LOCK_MAIN;
+
if (!(info_locks & ERTS_PROC_LOCK_STATUS))
- erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_STATUS);
- res = process_info_aux(BIF_P, rp, pid, BIF_ARG_2, 0);
+ unlock_locks |= ERTS_PROC_LOCK_STATUS;
+
+ if (info_locks & ERTS_PROC_LOCK_MSGQ) {
+ /*
+ * Move in queue into private queue and
+ * release msgq lock, enabling others to
+ * send messages to the process while it
+ * is being inspected...
+ */
+ ASSERT(info_locks & ERTS_PROC_LOCK_MAIN);
+ ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
+ info_locks &= ~ERTS_PROC_LOCK_MSGQ;
+ unlock_locks |= ERTS_PROC_LOCK_MSGQ;
+ }
+
+ if (unlock_locks)
+ erts_smp_proc_unlock(rp, unlock_locks);
+
+ res = process_info_aux(BIF_P, rp, info_locks, pid, BIF_ARG_2, 0);
}
ASSERT(is_value(res));
@@ -999,6 +1036,7 @@ BIF_RETTYPE process_info_2(BIF_ALIST_2)
Eterm
process_info_aux(Process *BIF_P,
Process *rp,
+ ErtsProcLocks rp_locks,
Eterm rpid,
Eterm item,
int always_wrap)
@@ -1070,171 +1108,55 @@ process_info_aux(Process *BIF_P,
break;
case am_messages: {
- ErlMessage* mp;
- int n;
-
- ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
- n = rp->msg.len;
- if (n == 0 || ERTS_TRACE_FLAGS(rp) & F_SENSITIVE) {
+ if (rp->msg.len == 0 || ERTS_TRACE_FLAGS(rp) & F_SENSITIVE) {
hp = HAlloc(BIF_P, 3);
} else {
- int remove_bad_messages = 0;
- struct {
- Uint copy_struct_size;
- ErlMessage* msgp;
- } *mq = erts_alloc(ERTS_ALC_T_TMP, n*sizeof(*mq));
- Sint i = 0;
- Uint heap_need = 3;
+ ErtsMessageInfo *mip;
+ Sint i;
+ Uint heap_need;
+#ifdef DEBUG
Eterm *hp_end;
+#endif
- for (mp = rp->msg.first; mp; mp = mp->next) {
- heap_need += 2;
- mq[i].msgp = mp;
- if (rp != BIF_P) {
- Eterm msg = ERL_MESSAGE_TERM(mq[i].msgp);
- if (is_value(msg)) {
- mq[i].copy_struct_size = (is_immed(msg)? 0 :
- size_object(msg));
- }
- else if (mq[i].msgp->data.attached) {
- mq[i].copy_struct_size
- = erts_msg_attached_data_size(mq[i].msgp);
- }
- else {
- /* Bad distribution message; ignore */
- remove_bad_messages = 1;
- mq[i].copy_struct_size = 0;
- }
- heap_need += mq[i].copy_struct_size;
- }
- else {
- mq[i].copy_struct_size = mp->data.attached ?
- erts_msg_attached_data_size(mp) : 0;
- }
- i++;
- }
+ mip = erts_alloc(ERTS_ALC_T_TMP,
+ rp->msg.len*sizeof(ErtsMessageInfo));
- if (rp != BIF_P) {
- hp = HAlloc(BIF_P, heap_need);
- hp_end = hp + heap_need;
- ASSERT(i == n);
- for (i--; i >= 0; i--) {
- Eterm msg = ERL_MESSAGE_TERM(mq[i].msgp);
- if (is_value(msg)) {
- if (mq[i].copy_struct_size)
- msg = copy_struct(msg,
- mq[i].copy_struct_size,
- &hp,
- &MSO(BIF_P));
- }
- else if (mq[i].msgp->data.attached) {
- ErlHeapFragment *hfp;
- /*
- * Decode it into a message buffer and attach it
- * to the message instead of the attached external
- * term.
- *
- * Note that we may not pass a process pointer
- * to erts_msg_distext2heap(), since it would then
- * try to alter locks on that process.
- */
- msg = erts_msg_distext2heap(
- NULL, NULL, &hfp, &ERL_MESSAGE_TOKEN(mq[i].msgp),
- mq[i].msgp->data.dist_ext);
-
- ERL_MESSAGE_TERM(mq[i].msgp) = msg;
- mq[i].msgp->data.heap_frag = hfp;
-
- if (is_non_value(msg)) {
- ASSERT(!mq[i].msgp->data.heap_frag);
- /* Bad distribution message; ignore */
- remove_bad_messages = 1;
- continue;
- }
- else {
- /* Make our copy of the message */
- ASSERT(size_object(msg) == erts_used_frag_sz(hfp));
- msg = copy_struct(msg,
- erts_used_frag_sz(hfp),
- &hp,
- &MSO(BIF_P));
- }
- }
- else {
- /* Bad distribution message; ignore */
- remove_bad_messages = 1;
- continue;
- }
- res = CONS(hp, msg, res);
- hp += 2;
- }
- HRelease(BIF_P, hp_end, hp+3);
- }
- else {
- for (i--; i >= 0; i--) {
- ErtsHeapFactory factory;
- Eterm msg = ERL_MESSAGE_TERM(mq[i].msgp);
-
- erts_factory_proc_prealloc_init(&factory, BIF_P,
- mq[i].copy_struct_size+2);
- if (mq[i].msgp->data.attached) {
- /* Decode it on the heap */
- erts_move_msg_attached_data_to_heap(&factory,
- mq[i].msgp);
- msg = ERL_MESSAGE_TERM(mq[i].msgp);
- ASSERT(!mq[i].msgp->data.attached);
- }
- if (is_value(msg)) {
- hp = erts_produce_heap(&factory, 2, 0);
- res = CONS(hp, msg, res);
- }
- else {
- /* Bad distribution message; ignore */
- remove_bad_messages = 1;
- continue;
- }
- erts_factory_close(&factory);
- }
- hp = HAlloc(BIF_P, 3);
- }
- erts_free(ERTS_ALC_T_TMP, mq);
- if (remove_bad_messages) {
- ErlMessage **mpp;
- /*
- * We need to remove bad distribution messages from
- * the queue, so that the value returned for
- * 'message_queue_len' is consistent with the value
- * returned for 'messages'.
- */
- mpp = &rp->msg.first;
- mp = rp->msg.first;
- while (mp) {
- if (is_value(ERL_MESSAGE_TERM(mp))) {
- mpp = &mp->next;
- mp = mp->next;
- }
- else {
- ErlMessage* bad_mp = mp;
- ASSERT(!mp->data.attached);
- if (rp->msg.save == &mp->next)
- rp->msg.save = mpp;
- if (rp->msg.last == &mp->next)
- rp->msg.last = mpp;
- *mpp = mp->next;
- mp = mp->next;
- rp->msg.len--;
- free_message(bad_mp);
- }
- }
+ /*
+ * Note that message queue may shrink when calling
+ * erts_prep_msgq_for_inspection() since it removes
+ * corrupt distribution messages.
+ */
+ heap_need = erts_prep_msgq_for_inspection(BIF_P, rp, rp_locks, mip);
+ heap_need += 3; /* top 2-tuple */
+ heap_need += rp->msg.len*2; /* Cons cells */
+
+ hp = HAlloc(BIF_P, heap_need); /* heap_need is exact */
+#ifdef DEBUG
+ hp_end = hp + heap_need;
+#endif
+
+ /* Build list of messages... */
+ for (i = rp->msg.len - 1, res = NIL; i >= 0; i--) {
+ Eterm msg = ERL_MESSAGE_TERM(mip[i].msgp);
+ Uint sz = mip[i].size;
+
+ if (sz != 0)
+ msg = copy_struct(msg, sz, &hp, &BIF_P->off_heap);
+
+ res = CONS(hp, msg, res);
+ hp += 2;
}
+
+ ASSERT(hp_end == hp + 3);
+
+ erts_free(ERTS_ALC_T_TMP, mip);
}
break;
}
case am_message_queue_len:
hp = HAlloc(BIF_P, 3);
- ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
res = make_small(rp->msg.len);
break;
@@ -1422,7 +1344,7 @@ process_info_aux(Process *BIF_P,
}
case am_total_heap_size: {
- ErlMessage *mp;
+ ErtsMessage *mp;
Uint total_heap_size;
Uint hsz = 3;
@@ -1432,8 +1354,6 @@ process_info_aux(Process *BIF_P,
total_heap_size += rp->mbuf_sz;
- ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
-
for (mp = rp->msg.first; mp; mp = mp->next)
if (mp->data.attached)
total_heap_size += erts_msg_attached_data_size(mp);
@@ -1455,7 +1375,7 @@ process_info_aux(Process *BIF_P,
case am_memory: { /* Memory consumed in bytes */
Uint hsz = 3;
- Uint size = erts_process_memory(rp);
+ Uint size = erts_process_memory(rp, 0);
(void) erts_bld_uint(NULL, &hsz, size);
hp = HAlloc(BIF_P, hsz);
res = erts_bld_uint(&hp, NULL, size);
@@ -1480,6 +1400,32 @@ process_info_aux(Process *BIF_P,
break;
}
+ case am_garbage_collection_info: {
+ Uint sz = 0, actual_sz = 0;
+
+ if (rp == BIF_P) {
+ sz += ERTS_PROCESS_GC_INFO_MAX_SIZE;
+ } else {
+ erts_process_gc_info(rp, &sz, NULL);
+ sz += 3;
+ }
+
+ hp = HAlloc(BIF_P, sz);
+ res = erts_process_gc_info(rp, &actual_sz, &hp);
+
+ /* We may have some extra space, fill with 0 tuples */
+ if (actual_sz <= sz - 3) {
+ for (; actual_sz < sz - 3; hp++, actual_sz++)
+ hp[0] = make_arityval(0);
+ } else {
+ for (; actual_sz < sz; hp++, actual_sz++)
+ hp[0] = make_arityval(0);
+ hp = HAlloc(BIF_P, 3);
+ }
+
+ break;
+ }
+
case am_group_leader: {
int sz = NC_HEAP_SIZE(rp->group_leader);
hp = HAlloc(BIF_P, 3 + sz);
@@ -1581,6 +1527,25 @@ process_info_aux(Process *BIF_P,
break;
}
+ case am_message_queue_data:
+ switch (rp->flags & (F_OFF_HEAP_MSGQ|F_ON_HEAP_MSGQ)) {
+ case F_OFF_HEAP_MSGQ:
+ res = am_off_heap;
+ break;
+ case F_ON_HEAP_MSGQ:
+ res = am_on_heap;
+ break;
+ case 0:
+ res = am_mixed;
+ break;
+ default:
+ res = am_error;
+ ERTS_INTERNAL_ERROR("Inconsistent message queue management state");
+ break;
+ }
+ hp = HAlloc(BIF_P, 3);
+ break;
+
default:
return THE_NON_VALUE; /* will produce badarg */
@@ -1755,7 +1720,7 @@ info_1_tuple(Process* BIF_P, /* Pointer to current process. */
if (arity == 2) {
Eterm res = THE_NON_VALUE;
char *buf;
- int len = is_string(*tp);
+ Sint len = is_string(*tp);
if (len <= 0)
return res;
buf = (char *) erts_alloc(ERTS_ALC_T_TMP, len+1);
@@ -1774,7 +1739,7 @@ info_1_tuple(Process* BIF_P, /* Pointer to current process. */
else {
Eterm res = THE_NON_VALUE;
char *buf;
- int len = is_string(tp[1]);
+ Sint len = is_string(tp[1]);
if (len <= 0)
return res;
buf = (char *) erts_alloc(ERTS_ALC_T_TMP, len+1);
@@ -2077,12 +2042,18 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
#ifndef ERTS_SMP
BIF_RET(am_disabled);
#else
+#ifndef ERTS_DIRTY_SCHEDULERS
if (erts_no_schedulers == 1)
BIF_RET(am_disabled);
- else {
- BIF_RET(erts_is_multi_scheduling_blocked()
- ? am_blocked
- : am_enabled);
+ else
+#endif
+ {
+ int msb = erts_is_multi_scheduling_blocked();
+ BIF_RET(!msb
+ ? am_enabled
+ : (msb > 0
+ ? am_blocked
+ : am_blocked_normal));
}
#endif
} else if (BIF_ARG_1 == am_build_type) {
@@ -2551,77 +2522,120 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
res = TUPLE3(hp, make_small(1), make_small(1), make_small(1));
BIF_RET(res);
#else
+ Eterm *hp;
Uint total, online, active;
- switch (erts_schedulers_state(&total,
- &online,
- &active,
- NULL,
- NULL,
- NULL,
- 1)) {
- case ERTS_SCHDLR_SSPND_DONE: {
- Eterm *hp = HAlloc(BIF_P, 4);
- res = TUPLE3(hp,
- make_small(total),
- make_small(online),
- make_small(active));
- BIF_RET(res);
+ erts_schedulers_state(&total, &online, &active,
+ NULL, NULL, NULL, NULL, NULL);
+ hp = HAlloc(BIF_P, 4);
+ res = TUPLE3(hp,
+ make_small(total),
+ make_small(online),
+ make_small(active));
+ BIF_RET(res);
+#endif
+ } else if (ERTS_IS_ATOM_STR("schedulers_state", BIF_ARG_1)) {
+#ifndef ERTS_SMP
+ Eterm *hp = HAlloc(BIF_P, 4);
+ res = TUPLE3(hp, make_small(1), make_small(1), make_small(1));
+ BIF_RET(res);
+#else
+ Eterm *hp;
+ Uint total, online, active;
+ erts_schedulers_state(&total, &online, &active,
+ NULL, NULL, NULL, NULL, NULL);
+ hp = HAlloc(BIF_P, 4);
+ res = TUPLE3(hp,
+ make_small(total),
+ make_small(online),
+ make_small(active));
+ BIF_RET(res);
+#endif
+ } else if (ERTS_IS_ATOM_STR("all_schedulers_state", BIF_ARG_1)) {
+#ifndef ERTS_SMP
+ Eterm *hp = HAlloc(BIF_P, 2+5);
+ res = CONS(hp+5,
+ TUPLE4(hp,
+ am_normal,
+ make_small(1),
+ make_small(1),
+ make_small(1)),
+ NIL);
+ BIF_RET(res);
+#else
+ Eterm *hp, tpl;
+ Uint sz, total, online, active,
+ dirty_cpu_total, dirty_cpu_online, dirty_cpu_active,
+ dirty_io_total, dirty_io_active;
+ erts_schedulers_state(&total, &online, &active,
+ &dirty_cpu_total, &dirty_cpu_online, &dirty_cpu_active,
+ &dirty_io_total, &dirty_io_active);
+
+ sz = 2+5;
+ if (dirty_cpu_total)
+ sz += 2+5;
+ if (dirty_io_total)
+ sz += 2+5;
+
+ hp = HAlloc(BIF_P, sz);
+
+ res = NIL;
+ if (dirty_io_total) {
+ tpl = TUPLE4(hp,
+ am_dirty_io,
+ make_small(dirty_io_total),
+ make_small(dirty_io_total),
+ make_small(dirty_io_active));
+ hp += 5;
+ res = CONS(hp, tpl, res);
+ hp += 2;
}
- case ERTS_SCHDLR_SSPND_YIELD_RESTART:
- ERTS_VBUMP_ALL_REDS(BIF_P);
- BIF_TRAP1(bif_export[BIF_system_info_1],
- BIF_P, BIF_ARG_1);
- default:
- ASSERT(0);
- BIF_ERROR(BIF_P, EXC_INTERNAL_ERROR);
+ if (dirty_cpu_total) {
+ tpl = TUPLE4(hp,
+ am_dirty_cpu,
+ make_small(dirty_cpu_total),
+ make_small(dirty_cpu_online),
+ make_small(dirty_cpu_active));
+ hp += 5;
+ res = CONS(hp, tpl, res);
+ hp += 2;
}
+ tpl = TUPLE4(hp,
+ am_normal,
+ make_small(total),
+ make_small(online),
+ make_small(active));
+ hp += 5;
+ res = CONS(hp, tpl, res);
+ BIF_RET(res);
#endif
} else if (ERTS_IS_ATOM_STR("schedulers_online", BIF_ARG_1)) {
#ifndef ERTS_SMP
BIF_RET(make_small(1));
#else
- Uint total, online, active;
- switch (erts_schedulers_state(&total, &online, &active, NULL, NULL, NULL, 1)) {
- case ERTS_SCHDLR_SSPND_DONE:
- BIF_RET(make_small(online));
- case ERTS_SCHDLR_SSPND_YIELD_RESTART:
- ERTS_VBUMP_ALL_REDS(BIF_P);
- BIF_TRAP1(bif_export[BIF_system_info_1],
- BIF_P, BIF_ARG_1);
- default:
- ASSERT(0);
- BIF_ERROR(BIF_P, EXC_INTERNAL_ERROR);
- }
+ Uint online;
+ erts_schedulers_state(NULL, &online, NULL, NULL, NULL, NULL, NULL, NULL);
+ BIF_RET(make_small(online));
#endif
} else if (ERTS_IS_ATOM_STR("schedulers_active", BIF_ARG_1)) {
#ifndef ERTS_SMP
BIF_RET(make_small(1));
#else
- Uint total, online, active;
- switch (erts_schedulers_state(&total, &online, &active, NULL, NULL, NULL, 1)) {
- case ERTS_SCHDLR_SSPND_DONE:
- BIF_RET(make_small(active));
- case ERTS_SCHDLR_SSPND_YIELD_RESTART:
- ERTS_VBUMP_ALL_REDS(BIF_P);
- BIF_TRAP1(bif_export[BIF_system_info_1],
- BIF_P, BIF_ARG_1);
- default:
- ASSERT(0);
- BIF_ERROR(BIF_P, EXC_INTERNAL_ERROR);
- }
+ Uint active;
+ erts_schedulers_state(NULL, NULL, &active, NULL, NULL, NULL, NULL, NULL);
+ BIF_RET(make_small(active));
#endif
#if defined(ERTS_SMP) && defined(ERTS_DIRTY_SCHEDULERS)
} else if (ERTS_IS_ATOM_STR("dirty_cpu_schedulers", BIF_ARG_1)) {
Uint dirty_cpu;
- erts_schedulers_state(NULL, NULL, NULL, &dirty_cpu, NULL, NULL, 1);
+ erts_schedulers_state(NULL, NULL, NULL, &dirty_cpu, NULL, NULL, NULL, NULL);
BIF_RET(make_small(dirty_cpu));
} else if (ERTS_IS_ATOM_STR("dirty_cpu_schedulers_online", BIF_ARG_1)) {
Uint dirty_cpu_onln;
- erts_schedulers_state(NULL, NULL, NULL, NULL, &dirty_cpu_onln, NULL, 1);
+ erts_schedulers_state(NULL, NULL, NULL, NULL, &dirty_cpu_onln, NULL, NULL, NULL);
BIF_RET(make_small(dirty_cpu_onln));
} else if (ERTS_IS_ATOM_STR("dirty_io_schedulers", BIF_ARG_1)) {
Uint dirty_io;
- erts_schedulers_state(NULL, NULL, NULL, NULL, NULL, &dirty_io, 1);
+ erts_schedulers_state(NULL, NULL, NULL, NULL, NULL, NULL, &dirty_io, NULL);
BIF_RET(make_small(dirty_io));
#endif
} else if (ERTS_IS_ATOM_STR("run_queues", BIF_ARG_1)) {
@@ -2675,7 +2689,16 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
if (erts_no_schedulers == 1)
BIF_RET(NIL);
else
- BIF_RET(erts_multi_scheduling_blockers(BIF_P));
+ BIF_RET(erts_multi_scheduling_blockers(BIF_P, 0));
+#endif
+ } else if (ERTS_IS_ATOM_STR("normal_multi_scheduling_blockers", BIF_ARG_1)) {
+#ifndef ERTS_SMP
+ BIF_RET(NIL);
+#else
+ if (erts_no_schedulers == 1)
+ BIF_RET(NIL);
+ else
+ BIF_RET(erts_multi_scheduling_blockers(BIF_P, 1));
#endif
} else if (ERTS_IS_ATOM_STR("modified_timing_level", BIF_ARG_1)) {
BIF_RET(ERTS_USE_MODIFIED_TIMING()
@@ -2742,6 +2765,19 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
BIF_RET(am_true);
}
#endif
+ else if (BIF_ARG_1 == am_message_queue_data) {
+ switch (erts_default_spo_flags & (SPO_ON_HEAP_MSGQ|SPO_OFF_HEAP_MSGQ)) {
+ case SPO_OFF_HEAP_MSGQ:
+ BIF_RET(am_off_heap);
+ case SPO_ON_HEAP_MSGQ:
+ BIF_RET(am_on_heap);
+ case 0:
+ BIF_RET(am_mixed);
+ default:
+ ERTS_INTERNAL_ERROR("Inconsistent message queue management state");
+ BIF_RET(am_error);
+ }
+ }
else if (ERTS_IS_ATOM_STR("compile_info",BIF_ARG_1)) {
Uint sz;
Eterm res = NIL, tup, text;
@@ -2780,6 +2816,20 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
else if (ERTS_IS_ATOM_STR("eager_check_io",BIF_ARG_1)) {
BIF_RET(erts_eager_check_io ? am_true : am_false);
}
+ else if (ERTS_IS_ATOM_STR("literal_test",BIF_ARG_1)) {
+#ifdef ERTS_HAVE_IS_IN_LITERAL_RANGE
+#ifdef ARCH_64
+ DECL_AM(range);
+ BIF_RET(AM_range);
+#else /* ARCH_32 */
+ DECL_AM(range_bitmask);
+ BIF_RET(AM_range_bitmask);
+#endif /* ARCH_32 */
+#else /* ! ERTS_HAVE_IS_IN_LITERAL_RANGE */
+ DECL_AM(tag);
+ BIF_RET(AM_tag);
+#endif
+ }
BIF_ERROR(BIF_P, BADARG);
}
@@ -3268,6 +3318,14 @@ BIF_RETTYPE statistics_1(BIF_ALIST_1)
szp = NULL;
hpp = &hp;
}
+#ifdef ERTS_ENABLE_MSACC
+ } else if (BIF_ARG_1 == am_microstate_accounting) {
+ Eterm threads;
+ res = erts_msacc_request(BIF_P, ERTS_MSACC_GATHER, &threads);
+ if (is_non_value(res))
+ BIF_RET(am_undefined);
+ BIF_TRAP2(gather_msacc_res_trap, BIF_P, res, threads);
+#endif
} else if (BIF_ARG_1 == am_context_switches) {
Eterm cs = erts_make_integer(erts_get_total_context_switches(), BIF_P);
hp = HAlloc(BIF_P, 3);
@@ -3488,7 +3546,7 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1)
BIF_RET(res);
}
else if (ERTS_IS_ATOM_STR("mmap", BIF_ARG_1)) {
- BIF_RET(erts_mmap_debug_info(BIF_P));
+ BIF_RET(erts_mmap_debug_info(&erts_dflt_mmapper, BIF_P));
}
else if (ERTS_IS_ATOM_STR("unique_monotonic_integer_state", BIF_ARG_1)) {
BIF_RET(erts_debug_get_unique_monotonic_integer_state(BIF_P));
@@ -3910,9 +3968,7 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
BIF_RET(am_false);
}
else {
- FLAGS(rp) |= F_FORCE_GC;
- if (BIF_P != rp)
- erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_MAIN);
+ ERTS_FORCE_GC(BIF_P);
BIF_RET(am_true);
}
}
@@ -4131,6 +4187,17 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
BIF_RET(am_ok);
}
}
+ else if (ERTS_IS_ATOM_STR("fill_heap", BIF_ARG_1)) {
+ UWord left = HeapWordsLeft(BIF_P);
+ if (left > 1) {
+ Eterm* hp = HAlloc(BIF_P, left);
+ *hp = make_pos_bignum_header(left - 1);
+ }
+ if (BIF_ARG_2 == am_true) {
+ FLAGS(BIF_P) |= F_NEED_FULLSWEEP;
+ }
+ BIF_RET(am_ok);
+ }
}
BIF_ERROR(BIF_P, BADARG);
@@ -4380,14 +4447,17 @@ static void os_info_init(void)
os_flavor(buf, 1024);
flav = erts_atom_put((byte *) buf, strlen(buf), ERTS_ATOM_ENC_LATIN1, 1);
erts_free(ERTS_ALC_T_TMP, (void *) buf);
- hp = erts_alloc(ERTS_ALC_T_LL_TEMP_TERM, (3+4)*sizeof(Eterm));
+ hp = erts_alloc(ERTS_ALC_T_LITERAL, (3+4)*sizeof(Eterm));
os_type_tuple = TUPLE2(hp, type, flav);
+ erts_set_literal_tag(&os_type_tuple, hp, 3);
+
hp += 3;
os_version(&major, &minor, &build);
os_version_tuple = TUPLE3(hp,
make_small(major),
make_small(minor),
make_small(build));
+ erts_set_literal_tag(&os_version_tuple, hp, 4);
}
void
@@ -4404,6 +4474,8 @@ erts_bif_info_init(void)
= erts_export_put(am_erlang, am_gather_gc_info_result, 1);
gather_io_bytes_trap
= erts_export_put(am_erts_internal, am_gather_io_bytes, 2);
+ gather_msacc_res_trap
+ = erts_export_put(am_erts_internal, am_gather_microstate_accounting_result, 2);
gather_system_check_res_trap
= erts_export_put(am_erts_internal, am_gather_system_check_result, 1);
process_info_init();
diff --git a/erts/emulator/beam/erl_bif_lists.c b/erts/emulator/beam/erl_bif_lists.c
index 5583dcb371..fe64e76575 100644
--- a/erts/emulator/beam/erl_bif_lists.c
+++ b/erts/emulator/beam/erl_bif_lists.c
@@ -42,7 +42,7 @@ static BIF_RETTYPE append(Process* p, Eterm A, Eterm B)
Eterm last;
size_t need;
Eterm* hp;
- int i;
+ Sint i;
if ((i = erts_list_length(A)) < 0) {
BIF_ERROR(p, BADARG);
@@ -99,9 +99,9 @@ static Eterm subtract(Process* p, Eterm A, Eterm B)
Eterm small_vec[SMALL_VEC_SIZE]; /* Preallocated memory for small lists */
Eterm* vec_p;
Eterm* vp;
- int i;
- int n;
- int m;
+ Sint i;
+ Sint n;
+ Sint m;
if ((n = erts_list_length(A)) < 0) {
BIF_ERROR(p, BADARG);
diff --git a/erts/emulator/beam/erl_bif_op.c b/erts/emulator/beam/erl_bif_op.c
index c9192fc420..0f20ded1d6 100644
--- a/erts/emulator/beam/erl_bif_op.c
+++ b/erts/emulator/beam/erl_bif_op.c
@@ -89,22 +89,22 @@ BIF_RETTYPE not_1(BIF_ALIST_1)
BIF_RETTYPE sgt_2(BIF_ALIST_2)
{
- BIF_RET(cmp_gt(BIF_ARG_1, BIF_ARG_2) ? am_true : am_false);
+ BIF_RET(CMP_GT(BIF_ARG_1, BIF_ARG_2) ? am_true : am_false);
}
BIF_RETTYPE sge_2(BIF_ALIST_2)
{
- BIF_RET(cmp_ge(BIF_ARG_1, BIF_ARG_2) ? am_true : am_false);
+ BIF_RET(CMP_GE(BIF_ARG_1, BIF_ARG_2) ? am_true : am_false);
}
BIF_RETTYPE slt_2(BIF_ALIST_2)
{
- BIF_RET(cmp_lt(BIF_ARG_1, BIF_ARG_2) ? am_true : am_false);
+ BIF_RET(CMP_LT(BIF_ARG_1, BIF_ARG_2) ? am_true : am_false);
}
BIF_RETTYPE sle_2(BIF_ALIST_2)
{
- BIF_RET(cmp_le(BIF_ARG_1, BIF_ARG_2) ? am_true : am_false);
+ BIF_RET(CMP_LE(BIF_ARG_1, BIF_ARG_2) ? am_true : am_false);
}
BIF_RETTYPE seq_2(BIF_ALIST_2)
@@ -114,7 +114,7 @@ BIF_RETTYPE seq_2(BIF_ALIST_2)
BIF_RETTYPE seqeq_2(BIF_ALIST_2)
{
- BIF_RET(cmp_eq(BIF_ARG_1, BIF_ARG_2) ? am_true : am_false);
+ BIF_RET(CMP_EQ(BIF_ARG_1, BIF_ARG_2) ? am_true : am_false);
}
BIF_RETTYPE sneq_2(BIF_ALIST_2)
@@ -124,7 +124,7 @@ BIF_RETTYPE sneq_2(BIF_ALIST_2)
BIF_RETTYPE sneqeq_2(BIF_ALIST_2)
{
- BIF_RET(cmp_ne(BIF_ARG_1, BIF_ARG_2) ? am_true : am_false);
+ BIF_RET(CMP_NE(BIF_ARG_1, BIF_ARG_2) ? am_true : am_false);
}
BIF_RETTYPE is_atom_1(BIF_ALIST_1)
@@ -258,7 +258,7 @@ Eterm erl_is_function(Process* p, Eterm arg1, Eterm arg2)
BIF_RET(am_true);
}
} else if (is_export(arg1)) {
- Export* exp = (Export *) EXPAND_POINTER((export_val(arg1))[1]);
+ Export* exp = (Export *) (export_val(arg1)[1]);
if (exp->code[2] == (Uint) arity) {
BIF_RET(am_true);
diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c
index 27c24197ea..86bcf43678 100644
--- a/erts/emulator/beam/erl_bif_port.c
+++ b/erts/emulator/beam/erl_bif_port.c
@@ -41,6 +41,7 @@
#include "external.h"
#include "packet_parser.h"
#include "erl_bits.h"
+#include "erl_bif_unique.h"
#include "dtrace-wrapper.h"
static Port *open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump);
@@ -50,10 +51,10 @@ static void free_args(char **);
char *erts_default_arg0 = "default";
-BIF_RETTYPE open_port_2(BIF_ALIST_2)
+BIF_RETTYPE erts_internal_open_port_2(BIF_ALIST_2)
{
Port *port;
- Eterm port_id;
+ Eterm res;
char *str;
int err_type, err_num;
@@ -61,27 +62,58 @@ BIF_RETTYPE open_port_2(BIF_ALIST_2)
if (!port) {
if (err_type == -3) {
ASSERT(err_num == BADARG || err_num == SYSTEM_LIMIT);
- BIF_ERROR(BIF_P, err_num);
+ if (err_num == BADARG)
+ res = am_badarg;
+ else if (err_num == SYSTEM_LIMIT)
+ res = am_system_limit;
+ else
+ /* this is only here to silence gcc, it should not happen */
+ BIF_ERROR(BIF_P, EXC_INTERNAL_ERROR);
} else if (err_type == -2) {
str = erl_errno_id(err_num);
+ res = erts_atom_put((byte *) str, strlen(str), ERTS_ATOM_ENC_LATIN1, 1);
} else {
- str = "einval";
+ res = am_einval;
}
- BIF_P->fvalue = erts_atom_put((byte *) str, strlen(str), ERTS_ATOM_ENC_LATIN1, 1);
- BIF_ERROR(BIF_P, EXC_ERROR);
- }
+ BIF_RET(res);
+ }
+
+ if (port->drv_ptr->flags & ERL_DRV_FLAG_USE_INIT_ACK) {
+ /* Copied from erl_port_task.c */
+ port->async_open_port = erts_alloc(ERTS_ALC_T_PRTSD,
+ sizeof(*port->async_open_port));
+ erts_make_ref_in_array(port->async_open_port->ref);
+ port->async_open_port->to = BIF_P->common.id;
+
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCKS_MSG_RECEIVE | ERTS_PROC_LOCK_LINK);
+ if (ERTS_PROC_PENDING_EXIT(BIF_P)) {
+ /* need to exit caller instead */
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCKS_MSG_RECEIVE | ERTS_PROC_LOCK_LINK);
+ KILL_CATCHES(BIF_P);
+ BIF_P->freason = EXC_EXIT;
+ erts_port_release(port);
+ BIF_RET(am_badarg);
+ }
+
+ ERTS_SMP_MSGQ_MV_INQ2PRIVQ(BIF_P);
+ BIF_P->msg.save = BIF_P->msg.last;
- erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_LINK);
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCKS_MSG_RECEIVE);
+
+ res = erts_proc_store_ref(BIF_P, port->async_open_port->ref);
+ } else {
+ res = port->common.id;
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_LINK);
+ }
- port_id = port->common.id;
erts_add_link(&ERTS_P_LINKS(port), LINK_PID, BIF_P->common.id);
- erts_add_link(&ERTS_P_LINKS(BIF_P), LINK_PID, port_id);
+ erts_add_link(&ERTS_P_LINKS(BIF_P), LINK_PID, port->common.id);
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_LINK);
erts_port_release(port);
- BIF_RET(port_id);
+ BIF_RET(res);
}
static ERTS_INLINE Port *
@@ -617,7 +649,7 @@ BIF_RETTYPE port_get_data_1(BIF_ALIST_1)
static Port *
open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)
{
- int i;
+ Sint i;
Eterm option;
Uint arity;
Eterm* tp;
@@ -945,8 +977,8 @@ static char **convert_args(Eterm l)
{
char **pp;
char *b;
- int n;
- int i = 0;
+ Sint n;
+ Sint i = 0;
Eterm str;
if (is_not_list(l) && is_not_nil(l)) {
return NULL;
@@ -992,7 +1024,7 @@ static byte* convert_environment(Process* p, Eterm env)
Eterm* temp_heap;
Eterm* hp;
Uint heap_size;
- int n;
+ Sint n;
Sint size;
byte* bytes;
int encoding = erts_get_native_filename_encoding();
diff --git a/erts/emulator/beam/erl_bif_re.c b/erts/emulator/beam/erl_bif_re.c
index 86951f32b0..7f7cd376ac 100644
--- a/erts/emulator/beam/erl_bif_re.c
+++ b/erts/emulator/beam/erl_bif_re.c
@@ -100,7 +100,7 @@ Sint erts_re_set_loop_limit(Sint limit)
static int term_to_int(Eterm term, int *sp)
{
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
if (is_small(term)) {
Uint x = signed_val(term);
@@ -151,7 +151,7 @@ static int term_to_int(Eterm term, int *sp)
static Eterm make_signed_integer(int x, Process *p)
{
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
return make_small(x);
#else
Eterm* hp;
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index 08807d72c9..71a7079b09 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -1887,11 +1887,7 @@ new_seq_trace_token(Process* p)
{
Eterm* hp;
- if (SEQ_TRACE_TOKEN(p) == NIL
-#ifdef USE_VM_PROBES
- || SEQ_TRACE_TOKEN(p) == am_have_dt_utag
-#endif
- ) {
+ if (have_no_seqtrace(SEQ_TRACE_TOKEN(p))) {
hp = HAlloc(p, 6);
SEQ_TRACE_TOKEN(p) = TUPLE5(hp, make_small(0), /* Flags */
make_small(0), /* Label */
@@ -1911,12 +1907,8 @@ BIF_RETTYPE erl_seq_trace_info(Process *p, Eterm item)
BIF_ERROR(p, BADARG);
}
- if (SEQ_TRACE_TOKEN(p) == NIL
-#ifdef USE_VM_PROBES
- || SEQ_TRACE_TOKEN(p) == am_have_dt_utag
-#endif
- ) {
- if ((item == am_send) || (item == am_receive) ||
+ if (have_no_seqtrace(SEQ_TRACE_TOKEN(p))) {
+ if ((item == am_send) || (item == am_receive) ||
(item == am_print) || (item == am_timestamp)
|| (item == am_monotonic_timestamp)
|| (item == am_strict_monotonic_timestamp)) {
@@ -1978,11 +1970,7 @@ BIF_RETTYPE seq_trace_info_1(BIF_ALIST_1)
*/
BIF_RETTYPE seq_trace_print_1(BIF_ALIST_1)
{
- if (SEQ_TRACE_TOKEN(BIF_P) == NIL
-#ifdef USE_VM_PROBES
- || SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag
-#endif
- ) {
+ if (have_no_seqtrace(SEQ_TRACE_TOKEN(BIF_P))) {
BIF_RET(am_false);
}
seq_trace_update_send(BIF_P);
@@ -2001,11 +1989,7 @@ BIF_RETTYPE seq_trace_print_1(BIF_ALIST_1)
*/
BIF_RETTYPE seq_trace_print_2(BIF_ALIST_2)
{
- if (SEQ_TRACE_TOKEN(BIF_P) == NIL
-#ifdef USE_VM_PROBES
- || SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag
-#endif
- ) {
+ if (have_no_seqtrace(SEQ_TRACE_TOKEN(BIF_P))) {
BIF_RET(am_false);
}
if (!(is_atom(BIF_ARG_1) || is_small(BIF_ARG_1))) {
diff --git a/erts/emulator/beam/erl_bif_unique.c b/erts/emulator/beam/erl_bif_unique.c
index 5eca09c5a6..c4a39b8897 100644
--- a/erts/emulator/beam/erl_bif_unique.c
+++ b/erts/emulator/beam/erl_bif_unique.c
@@ -338,7 +338,7 @@ static struct {
} w;
} raw_unique_monotonic_integer erts_align_attribute(ERTS_CACHE_LINE_SIZE);
-#if defined(ARCH_32) || HALFWORD_HEAP
+#if defined(ARCH_32)
# define ERTS_UNIQUE_MONOTONIC_OFFSET ERTS_SINT64_MIN
#else
# define ERTS_UNIQUE_MONOTONIC_OFFSET MIN_SMALL
@@ -368,7 +368,7 @@ get_unique_monotonic_integer_heap_size(Uint64 raw, int positive)
Sint64 value = ((Sint64) raw) + ERTS_UNIQUE_MONOTONIC_OFFSET;
if (IS_SSMALL(value))
return 0;
-#if defined(ARCH_32) || HALFWORD_HEAP
+#if defined(ARCH_32)
return ERTS_SINT64_HEAP_SIZE(value);
#else
return ERTS_UINT64_HEAP_SIZE((Uint64) value);
@@ -393,7 +393,7 @@ make_unique_monotonic_integer_value(Eterm *hp, Uint hsz, Uint64 raw, int positiv
if (hsz == 0)
res = make_small(value);
else {
-#if defined(ARCH_32) || HALFWORD_HEAP
+#if defined(ARCH_32)
res = erts_sint64_to_big(value, &hp);
#else
res = erts_uint64_to_big((Uint64) value, &hp);
diff --git a/erts/emulator/beam/erl_binary.h b/erts/emulator/beam/erl_binary.h
index ea01bf08f0..e181b5555d 100644
--- a/erts/emulator/beam/erl_binary.h
+++ b/erts/emulator/beam/erl_binary.h
@@ -72,7 +72,6 @@ typedef struct erl_heap_bin {
*/
#define binary_size(Bin) (binary_val(Bin)[1])
-#define binary_size_rel(Bin,BasePtr) (binary_val_rel(Bin,BasePtr)[1])
#define binary_bitsize(Bin) \
((*binary_val(Bin) == HEADER_SUB_BIN) ? \
@@ -95,12 +94,9 @@ typedef struct erl_heap_bin {
* Bitsize: output variable (Uint)
*/
-#define ERTS_GET_BINARY_BYTES(Bin,Bytep,Bitoffs,Bitsize) \
- ERTS_GET_BINARY_BYTES_REL(Bin,Bytep,Bitoffs,Bitsize,NULL)
-
-#define ERTS_GET_BINARY_BYTES_REL(Bin,Bytep,Bitoffs,Bitsize,BasePtr) \
+#define ERTS_GET_BINARY_BYTES(Bin,Bytep,Bitoffs,Bitsize) \
do { \
- Eterm* _real_bin = binary_val_rel(Bin,BasePtr); \
+ Eterm* _real_bin = binary_val(Bin); \
Uint _offs = 0; \
Bitoffs = Bitsize = 0; \
if (*_real_bin == HEADER_SUB_BIN) { \
@@ -108,7 +104,7 @@ do { \
_offs = _sb->offs; \
Bitoffs = _sb->bitoffs; \
Bitsize = _sb->bitsize; \
- _real_bin = binary_val_rel(_sb->orig,BasePtr); \
+ _real_bin = binary_val(_sb->orig); \
} \
if (*_real_bin == HEADER_PROC_BIN) { \
Bytep = ((ProcBin *) _real_bin)->bytes + _offs; \
@@ -131,11 +127,8 @@ do { \
*/
#define ERTS_GET_REAL_BIN(Bin, RealBin, ByteOffset, BitOffset, BitSize) \
- ERTS_GET_REAL_BIN_REL(Bin, RealBin, ByteOffset, BitOffset, BitSize, NULL)
-
-#define ERTS_GET_REAL_BIN_REL(Bin, RealBin, ByteOffset, BitOffset, BitSize, BasePtr) \
do { \
- ErlSubBin* _sb = (ErlSubBin *) binary_val_rel(Bin,BasePtr); \
+ ErlSubBin* _sb = (ErlSubBin *) binary_val(Bin); \
if (_sb->thing_word == HEADER_SUB_BIN) { \
RealBin = _sb->orig; \
ByteOffset = _sb->offs; \
diff --git a/erts/emulator/beam/erl_bits.c b/erts/emulator/beam/erl_bits.c
index 01734c55d7..11d83686a3 100644
--- a/erts/emulator/beam/erl_bits.c
+++ b/erts/emulator/beam/erl_bits.c
@@ -282,7 +282,7 @@ erts_bs_get_integer_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuff
* Simply shift whole bytes into the result.
*/
switch (BYTE_OFFSET(n)) {
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
case 7: w = (w << 8) | *bp++;
case 6: w = (w << 8) | *bp++;
case 5: w = (w << 8) | *bp++;
@@ -387,7 +387,7 @@ erts_bs_get_integer_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuff
case 3:
v32 = LSB[0] + (LSB[1]<<8) + (LSB[2]<<16);
goto big_small;
-#if !defined(ARCH_64) || HALFWORD_HEAP
+#if !defined(ARCH_64)
case 4:
v32 = (LSB[0] + (LSB[1]<<8) + (LSB[2]<<16) + (LSB[3]<<24));
if (!IS_USMALL(sgn, v32)) {
diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c
index 870b556851..441dbdde4f 100644
--- a/erts/emulator/beam/erl_db.c
+++ b/erts/emulator/beam/erl_db.c
@@ -1773,15 +1773,9 @@ BIF_RETTYPE ets_delete_1(BIF_ALIST_1)
* (it looks like an continuation pointer), but that is will crash the
* emulator if this BIF is call traced.
*/
-#if HALFWORD_HEAP
- Eterm *hp = HAlloc(BIF_P, 3);
- hp[0] = make_pos_bignum_header(2);
- *((UWord *) (UWord) (hp+1)) = (UWord) tb;
-#else
Eterm *hp = HAlloc(BIF_P, 2);
hp[0] = make_pos_bignum_header(1);
hp[1] = (Eterm) tb;
-#endif
BIF_TRAP1(&ets_delete_continue_exp, BIF_P, make_big(hp));
}
else {
@@ -1837,7 +1831,7 @@ BIF_RETTYPE ets_give_away_3(BIF_ALIST_3)
tb->common.id,
from_pid,
BIF_ARG_3),
- 0);
+ 0);
erts_smp_proc_unlock(to_proc, to_locks);
UnUseTmpHeap(5,BIF_P);
BIF_RET(am_true);
@@ -2839,7 +2833,7 @@ BIF_RETTYPE ets_match_spec_run_r_3(BIF_ALIST_3)
BIF_TRAP3(bif_export[BIF_ets_match_spec_run_r_3],
BIF_P,lst,BIF_ARG_2,ret);
}
- res = db_prog_match(BIF_P, mp, CAR(list_val(lst)), NULL, NULL, 0,
+ res = db_prog_match(BIF_P, mp, CAR(list_val(lst)), NULL, 0,
ERTS_PAM_COPY_RESULT, &dummy);
if (is_value(res)) {
hp = HAlloc(BIF_P, 2);
@@ -3216,7 +3210,7 @@ retry:
tb->common.id,
p->common.id,
heir_data),
- 0);
+ 0);
erts_smp_proc_unlock(to_proc, to_locks);
return !0;
}
@@ -3651,11 +3645,8 @@ static BIF_RETTYPE ets_delete_trap(BIF_ALIST_1)
Eterm* ptr = big_val(cont);
DbTable *tb = *((DbTable **) (UWord) (ptr + 1));
-#if HALFWORD_HEAP
- ASSERT(*ptr == make_pos_bignum_header(2));
-#else
ASSERT(*ptr == make_pos_bignum_header(1));
-#endif
+
db_lock(tb, LCK_WRITE);
trap = free_table_cont(p, tb, 0, 1);
db_unlock(tb, LCK_WRITE);
diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c
index fa925c94a5..240b79fc60 100644
--- a/erts/emulator/beam/erl_db_hash.c
+++ b/erts/emulator/beam/erl_db_hash.c
@@ -469,9 +469,6 @@ static ERTS_INLINE void try_shrink(DbTableHash* tb)
}
}
-#define EQ_REL(x,y,y_base) \
- (is_same(x,NULL,y,y_base) || (is_not_both_immed((x),(y)) && eq_rel((x),NULL,(y),y_base)))
-
/* Is this a live object (not pseodo-deleted) with the specified key?
*/
static ERTS_INLINE int has_live_key(DbTableHash* tb, HashDbTerm* b,
@@ -481,7 +478,7 @@ static ERTS_INLINE int has_live_key(DbTableHash* tb, HashDbTerm* b,
else {
Eterm itemKey = GETKEY(tb, b->dbterm.tpl);
ASSERT(!is_header(itemKey));
- return EQ_REL(key, itemKey, b->dbterm.tpl);
+ return EQ(key, itemKey);
}
}
@@ -494,7 +491,7 @@ static ERTS_INLINE int has_key(DbTableHash* tb, HashDbTerm* b,
else {
Eterm itemKey = GETKEY(tb, b->dbterm.tpl);
ASSERT(!is_header(itemKey));
- return EQ_REL(key, itemKey, b->dbterm.tpl);
+ return EQ(key, itemKey);
}
}
@@ -2204,11 +2201,11 @@ static void db_print_hash(int to, void *to_arg, int show, DbTable *tbl)
erts_print(to, to_arg, "*");
if (tb->common.compress) {
Eterm key = GETKEY(tb, list->dbterm.tpl);
- erts_print(to, to_arg, "key=%R", key, list->dbterm.tpl);
+ erts_print(to, to_arg, "key=%T", key);
}
else {
- Eterm obj = make_tuple_rel(list->dbterm.tpl,list->dbterm.tpl);
- erts_print(to, to_arg, "%R", obj, list->dbterm.tpl);
+ Eterm obj = make_tuple(list->dbterm.tpl);
+ erts_print(to, to_arg, "%T", obj);
}
if (list->next != 0)
erts_print(to, to_arg, ",");
@@ -2899,9 +2896,6 @@ Ldone:
handle->dbterm = &b->dbterm;
handle->flags = flags;
handle->new_size = b->dbterm.size;
-#if HALFWORD_HEAP
- handle->abs_vec = NULL;
-#endif
handle->lck = lck;
return 1;
}
diff --git a/erts/emulator/beam/erl_db_tree.c b/erts/emulator/beam/erl_db_tree.c
index 61293fbf9a..0f642f0867 100644
--- a/erts/emulator/beam/erl_db_tree.c
+++ b/erts/emulator/beam/erl_db_tree.c
@@ -280,7 +280,7 @@ struct select_delete_context {
/*
** Forward declarations
*/
-static TreeDbTerm *linkout_tree(DbTableTree *tb, Eterm key, Eterm* key_base);
+static TreeDbTerm *linkout_tree(DbTableTree *tb, Eterm key);
static TreeDbTerm *linkout_object_tree(DbTableTree *tb,
Eterm object);
static int do_free_tree_cont(DbTableTree *tb, int num_left);
@@ -291,15 +291,15 @@ static int delsub(TreeDbTerm **this);
static TreeDbTerm *slot_search(Process *p, DbTableTree *tb, Sint slot);
static TreeDbTerm *find_node(DbTableTree *tb, Eterm key);
static TreeDbTerm **find_node2(DbTableTree *tb, Eterm key);
-static TreeDbTerm *find_next(DbTableTree *tb, DbTreeStack*, Eterm key, Eterm* kbase);
-static TreeDbTerm *find_prev(DbTableTree *tb, DbTreeStack*, Eterm key, Eterm* kbase);
+static TreeDbTerm *find_next(DbTableTree *tb, DbTreeStack*, Eterm key);
+static TreeDbTerm *find_prev(DbTableTree *tb, DbTreeStack*, Eterm key);
static TreeDbTerm *find_next_from_pb_key(DbTableTree *tb, DbTreeStack*,
Eterm key);
static TreeDbTerm *find_prev_from_pb_key(DbTableTree *tb, DbTreeStack*,
Eterm key);
static void traverse_backwards(DbTableTree *tb,
DbTreeStack*,
- Eterm lastkey, Eterm* lk_base,
+ Eterm lastkey,
int (*doit)(DbTableTree *tb,
TreeDbTerm *,
void *,
@@ -307,7 +307,7 @@ static void traverse_backwards(DbTableTree *tb,
void *context);
static void traverse_forward(DbTableTree *tb,
DbTreeStack*,
- Eterm lastkey, Eterm* lk_base,
+ Eterm lastkey,
int (*doit)(DbTableTree *tb,
TreeDbTerm *,
void *,
@@ -315,8 +315,8 @@ static void traverse_forward(DbTableTree *tb,
void *context);
static int key_given(DbTableTree *tb, Eterm pattern, TreeDbTerm **ret,
Eterm *partly_bound_key);
-static Sint cmp_partly_bound(Eterm partly_bound_key, Eterm bound_key, Eterm* bk_base);
-static Sint do_cmp_partly_bound(Eterm a, Eterm b, Eterm* b_base, int *done);
+static Sint cmp_partly_bound(Eterm partly_bound_key, Eterm bound_key);
+static Sint do_cmp_partly_bound(Eterm a, Eterm b, int *done);
static int analyze_pattern(DbTableTree *tb, Eterm pattern,
struct mp_info *mpi);
@@ -517,7 +517,7 @@ static int db_next_tree(Process *p, DbTable *tbl, Eterm key, Eterm *ret)
if (is_atom(key) && key == am_EOT)
return DB_ERROR_BADKEY;
stack = get_any_stack(tb);
- this = find_next(tb, stack, key, NULL);
+ this = find_next(tb, stack, key);
release_stack(tb,stack);
if (this == NULL) {
*ret = am_EOT;
@@ -563,7 +563,7 @@ static int db_prev_tree(Process *p, DbTable *tbl, Eterm key, Eterm *ret)
if (is_atom(key) && key == am_EOT)
return DB_ERROR_BADKEY;
stack = get_any_stack(tb);
- this = find_prev(tb, stack, key, NULL);
+ this = find_prev(tb, stack, key);
release_stack(tb,stack);
if (this == NULL) {
*ret = am_EOT;
@@ -573,19 +573,13 @@ static int db_prev_tree(Process *p, DbTable *tbl, Eterm key, Eterm *ret)
return DB_ERROR_NONE;
}
-static ERTS_INLINE Sint cmp_key(DbTableTree* tb, Eterm key, Eterm* key_base,
- TreeDbTerm* obj)
-{
- return cmp_rel(key, key_base,
- GETKEY(tb,obj->dbterm.tpl), obj->dbterm.tpl);
+static ERTS_INLINE Sint cmp_key(DbTableTree* tb, Eterm key, TreeDbTerm* obj) {
+ return CMP(key, GETKEY(tb,obj->dbterm.tpl));
}
-static ERTS_INLINE int cmp_key_eq(DbTableTree* tb, Eterm key, Eterm* key_base,
- TreeDbTerm* obj)
-{
+static ERTS_INLINE int cmp_key_eq(DbTableTree* tb, Eterm key, TreeDbTerm* obj) {
Eterm obj_key = GETKEY(tb,obj->dbterm.tpl);
- return is_same(key, key_base, obj_key, obj->dbterm.tpl)
- || cmp_rel(key, key_base, obj_key, obj->dbterm.tpl) == 0;
+ return is_same(key, obj_key) || CMP(key, obj_key) == 0;
}
static int db_put_tree(DbTable *tbl, Eterm obj, int key_clash_fail)
@@ -619,7 +613,7 @@ static int db_put_tree(DbTable *tbl, Eterm obj, int key_clash_fail)
(*this)->balance = 0;
(*this)->left = (*this)->right = NULL;
break;
- } else if ((c = cmp_key(tb, key, NULL, *this)) < 0) {
+ } else if ((c = cmp_key(tb, key, *this)) < 0) {
/* go lefts */
dstack[dpos++] = DIR_LEFT;
tstack[tpos++] = this;
@@ -774,7 +768,7 @@ static int db_erase_tree(DbTable *tbl, Eterm key, Eterm *ret)
*ret = am_true;
- if ((res = linkout_tree(tb, key, NULL)) != NULL) {
+ if ((res = linkout_tree(tb, key)) != NULL) {
free_term(tb, res);
}
return DB_ERROR_NONE;
@@ -970,15 +964,15 @@ static int db_select_continue_tree(Process *p,
stack = get_any_stack(tb);
if (chunk_size) {
if (reverse) {
- traverse_backwards(tb, stack, lastkey, NULL, &doit_select_chunk, &sc);
+ traverse_backwards(tb, stack, lastkey, &doit_select_chunk, &sc);
} else {
- traverse_forward(tb, stack, lastkey, NULL, &doit_select_chunk, &sc);
+ traverse_forward(tb, stack, lastkey, &doit_select_chunk, &sc);
}
} else {
if (reverse) {
- traverse_forward(tb, stack, lastkey, NULL, &doit_select, &sc);
+ traverse_forward(tb, stack, lastkey, &doit_select, &sc);
} else {
- traverse_backwards(tb, stack, lastkey, NULL, &doit_select, &sc);
+ traverse_backwards(tb, stack, lastkey, &doit_select, &sc);
}
}
release_stack(tb,stack);
@@ -1003,9 +997,9 @@ static int db_select_continue_tree(Process *p,
}
key = GETKEY(tb, sc.lastobj);
- sz = size_object_rel(key,sc.lastobj);
+ sz = size_object(key);
hp = HAlloc(p, 9 + sz);
- key = copy_struct_rel(key, sz, &hp, &MSO(p), sc.lastobj, NULL);
+ key = copy_struct(key, sz, &hp, &MSO(p));
continuation = TUPLE8
(hp,
tptr[1],
@@ -1026,8 +1020,8 @@ static int db_select_continue_tree(Process *p,
key = GETKEY(tb, sc.lastobj);
if (chunk_size) {
if (end_condition != NIL &&
- ((!reverse && cmp_partly_bound(end_condition,key,sc.lastobj) < 0) ||
- (reverse && cmp_partly_bound(end_condition,key,sc.lastobj) > 0))) {
+ ((!reverse && cmp_partly_bound(end_condition,key) < 0) ||
+ (reverse && cmp_partly_bound(end_condition,key) > 0))) {
/* done anyway */
if (!sc.got) {
RET_TO_BIF(am_EOT, DB_ERROR_NONE);
@@ -1039,16 +1033,16 @@ static int db_select_continue_tree(Process *p,
}
} else {
if (end_condition != NIL &&
- ((!reverse && cmp_partly_bound(end_condition,key,sc.lastobj) > 0) ||
- (reverse && cmp_partly_bound(end_condition,key,sc.lastobj) < 0))) {
+ ((!reverse && cmp_partly_bound(end_condition,key) > 0) ||
+ (reverse && cmp_partly_bound(end_condition,key) < 0))) {
/* done anyway */
RET_TO_BIF(sc.accum,DB_ERROR_NONE);
}
}
/* Not done yet, let's trap. */
- sz = size_object_rel(key,sc.lastobj);
+ sz = size_object(key);
hp = HAlloc(p, 9 + sz);
- key = copy_struct_rel(key, sz, &hp, &MSO(p), sc.lastobj, NULL);
+ key = copy_struct(key, sz, &hp, &MSO(p));
continuation = TUPLE8
(hp,
tptr[1],
@@ -1075,7 +1069,6 @@ static int db_select_tree(Process *p, DbTable *tbl,
struct select_context sc;
struct mp_info mpi;
Eterm lastkey = THE_NON_VALUE;
- Eterm* lk_base = NULL;
Eterm key;
Eterm continuation;
unsigned sz;
@@ -1127,20 +1120,18 @@ static int db_select_tree(Process *p, DbTable *tbl,
if (mpi.some_limitation) {
if ((this = find_prev_from_pb_key(tb, stack, mpi.least)) != NULL) {
lastkey = GETKEY(tb, this->dbterm.tpl);
- lk_base = this->dbterm.tpl;
}
sc.end_condition = mpi.most;
}
- traverse_forward(tb, stack, lastkey, lk_base, &doit_select, &sc);
+ traverse_forward(tb, stack, lastkey, &doit_select, &sc);
} else {
if (mpi.some_limitation) {
if ((this = find_next_from_pb_key(tb, stack, mpi.most)) != NULL) {
lastkey = GETKEY(tb, this->dbterm.tpl);
- lk_base = this->dbterm.tpl;
}
sc.end_condition = mpi.least;
}
- traverse_backwards(tb, stack, lastkey, lk_base, &doit_select, &sc);
+ traverse_backwards(tb, stack, lastkey, &doit_select, &sc);
}
release_stack(tb,stack);
#ifdef HARDDEBUG
@@ -1153,9 +1144,9 @@ static int db_select_tree(Process *p, DbTable *tbl,
}
key = GETKEY(tb, sc.lastobj);
- sz = size_object_rel(key, sc.lastobj);
+ sz = size_object(key);
hp = HAlloc(p, 9 + sz + PROC_BIN_SIZE);
- key = copy_struct_rel(key, sz, &hp, &MSO(p), sc.lastobj, NULL);
+ key = copy_struct(key, sz, &hp, &MSO(p));
if (mpi.all_objects)
(mpi.mp)->flags |= BIN_FLAG_ALL_OBJECTS;
mpb=db_make_mp_binary(p,mpi.mp,&hp);
@@ -1236,7 +1227,7 @@ static int db_select_count_continue_tree(Process *p,
}
stack = get_any_stack(tb);
- traverse_backwards(tb, stack, lastkey, NULL, &doit_select_count, &sc);
+ traverse_backwards(tb, stack, lastkey, &doit_select_count, &sc);
release_stack(tb,stack);
BUMP_REDS(p, 1000 - sc.max);
@@ -1246,12 +1237,12 @@ static int db_select_count_continue_tree(Process *p,
}
key = GETKEY(tb, sc.lastobj);
if (end_condition != NIL &&
- (cmp_partly_bound(end_condition,key,sc.lastobj) > 0)) {
+ (cmp_partly_bound(end_condition,key) > 0)) {
/* done anyway */
RET_TO_BIF(make_small(sc.got),DB_ERROR_NONE);
}
/* Not done yet, let's trap. */
- sz = size_object_rel(key, sc.lastobj);
+ sz = size_object(key);
if (IS_USMALL(0, sc.got)) {
hp = HAlloc(p, sz + 6);
egot = make_small(sc.got);
@@ -1261,7 +1252,7 @@ static int db_select_count_continue_tree(Process *p,
egot = uint_to_big(sc.got, hp);
hp += BIG_UINT_HEAP_SIZE;
}
- key = copy_struct_rel(key, sz, &hp, &MSO(p), sc.lastobj, NULL);
+ key = copy_struct(key, sz, &hp, &MSO(p));
continuation = TUPLE5
(hp,
tptr[1],
@@ -1284,7 +1275,6 @@ static int db_select_count_tree(Process *p, DbTable *tbl,
struct select_count_context sc;
struct mp_info mpi;
Eterm lastkey = THE_NON_VALUE;
- Eterm* lk_base = NULL;
Eterm key;
Eterm continuation;
unsigned sz;
@@ -1334,12 +1324,11 @@ static int db_select_count_tree(Process *p, DbTable *tbl,
if (mpi.some_limitation) {
if ((this = find_next_from_pb_key(tb, stack, mpi.most)) != NULL) {
lastkey = GETKEY(tb, this->dbterm.tpl);
- lk_base = this->dbterm.tpl;
}
sc.end_condition = mpi.least;
}
- traverse_backwards(tb, stack, lastkey, lk_base, &doit_select_count, &sc);
+ traverse_backwards(tb, stack, lastkey, &doit_select_count, &sc);
release_stack(tb,stack);
BUMP_REDS(p, 1000 - sc.max);
if (sc.max > 0) {
@@ -1347,7 +1336,7 @@ static int db_select_count_tree(Process *p, DbTable *tbl,
}
key = GETKEY(tb, sc.lastobj);
- sz = size_object_rel(key, sc.lastobj);
+ sz = size_object(key);
if (IS_USMALL(0, sc.got)) {
hp = HAlloc(p, sz + PROC_BIN_SIZE + 6);
egot = make_small(sc.got);
@@ -1357,7 +1346,7 @@ static int db_select_count_tree(Process *p, DbTable *tbl,
egot = uint_to_big(sc.got, hp);
hp += BIG_UINT_HEAP_SIZE;
}
- key = copy_struct_rel(key, sz, &hp, &MSO(p), sc.lastobj, NULL);
+ key = copy_struct(key, sz, &hp, &MSO(p));
if (mpi.all_objects)
(mpi.mp)->flags |= BIN_FLAG_ALL_OBJECTS;
mpb = db_make_mp_binary(p,mpi.mp,&hp);
@@ -1388,7 +1377,6 @@ static int db_select_chunk_tree(Process *p, DbTable *tbl,
struct select_context sc;
struct mp_info mpi;
Eterm lastkey = THE_NON_VALUE;
- Eterm* lk_base = NULL;
Eterm key;
Eterm continuation;
unsigned sz;
@@ -1445,20 +1433,18 @@ static int db_select_chunk_tree(Process *p, DbTable *tbl,
if (mpi.some_limitation) {
if ((this = find_next_from_pb_key(tb, stack, mpi.most)) != NULL) {
lastkey = GETKEY(tb, this->dbterm.tpl);
- lk_base = this->dbterm.tpl;
}
sc.end_condition = mpi.least;
}
- traverse_backwards(tb, stack, lastkey, lk_base, &doit_select_chunk, &sc);
+ traverse_backwards(tb, stack, lastkey, &doit_select_chunk, &sc);
} else {
if (mpi.some_limitation) {
if ((this = find_prev_from_pb_key(tb, stack, mpi.least)) != NULL) {
lastkey = GETKEY(tb, this->dbterm.tpl);
- lk_base = this->dbterm.tpl;
}
sc.end_condition = mpi.most;
}
- traverse_forward(tb, stack, lastkey, lk_base, &doit_select_chunk, &sc);
+ traverse_forward(tb, stack, lastkey, &doit_select_chunk, &sc);
}
release_stack(tb,stack);
@@ -1483,9 +1469,9 @@ static int db_select_chunk_tree(Process *p, DbTable *tbl,
}
key = GETKEY(tb, sc.lastobj);
- sz = size_object_rel(key, sc.lastobj);
+ sz = size_object(key);
hp = HAlloc(p, 9 + sz + PROC_BIN_SIZE);
- key = copy_struct_rel(key, sz, &hp, &MSO(p), sc.lastobj, NULL);
+ key = copy_struct(key, sz, &hp, &MSO(p));
if (mpi.all_objects)
(mpi.mp)->flags |= BIN_FLAG_ALL_OBJECTS;
mpb = db_make_mp_binary(p,mpi.mp,&hp);
@@ -1508,9 +1494,9 @@ static int db_select_chunk_tree(Process *p, DbTable *tbl,
}
key = GETKEY(tb, sc.lastobj);
- sz = size_object_rel(key, sc.lastobj);
+ sz = size_object(key);
hp = HAlloc(p, 9 + sz + PROC_BIN_SIZE);
- key = copy_struct_rel(key, sz, &hp, &MSO(p), sc.lastobj, NULL);
+ key = copy_struct(key, sz, &hp, &MSO(p));
if (mpi.all_objects)
(mpi.mp)->flags |= BIN_FLAG_ALL_OBJECTS;
@@ -1586,7 +1572,7 @@ static int db_select_delete_continue_tree(Process *p,
sc.keypos = tb->common.keypos;
ASSERT(!erts_smp_atomic_read_nob(&tb->is_stack_busy));
- traverse_backwards(tb, &tb->static_stack, lastkey, NULL, &doit_select_delete, &sc);
+ traverse_backwards(tb, &tb->static_stack, lastkey, &doit_select_delete, &sc);
BUMP_REDS(p, 1000 - sc.max);
@@ -1595,11 +1581,11 @@ static int db_select_delete_continue_tree(Process *p,
}
key = GETKEY(tb, (sc.lastterm)->dbterm.tpl);
if (end_condition != NIL &&
- cmp_partly_bound(end_condition,key,sc.lastterm->dbterm.tpl) > 0) { /* done anyway */
+ cmp_partly_bound(end_condition,key) > 0) { /* done anyway */
RET_TO_BIF(erts_make_integer(sc.accum,p),DB_ERROR_NONE);
}
/* Not done yet, let's trap. */
- sz = size_object_rel(key, sc.lastterm->dbterm.tpl);
+ sz = size_object(key);
if (IS_USMALL(0, sc.accum)) {
hp = HAlloc(p, sz + 6);
eaccsum = make_small(sc.accum);
@@ -1609,7 +1595,7 @@ static int db_select_delete_continue_tree(Process *p,
eaccsum = uint_to_big(sc.accum, hp);
hp += BIG_UINT_HEAP_SIZE;
}
- key = copy_struct_rel(key, sz, &hp, &MSO(p), sc.lastterm->dbterm.tpl, NULL);
+ key = copy_struct(key, sz, &hp, &MSO(p));
continuation = TUPLE5
(hp,
tptr[1],
@@ -1630,7 +1616,6 @@ static int db_select_delete_tree(Process *p, DbTable *tbl,
struct select_delete_context sc;
struct mp_info mpi;
Eterm lastkey = THE_NON_VALUE;
- Eterm* lk_base = NULL;
Eterm key;
Eterm continuation;
unsigned sz;
@@ -1683,12 +1668,11 @@ static int db_select_delete_tree(Process *p, DbTable *tbl,
if (mpi.some_limitation) {
if ((this = find_next_from_pb_key(tb, &tb->static_stack, mpi.most)) != NULL) {
lastkey = GETKEY(tb, this->dbterm.tpl);
- lk_base = this->dbterm.tpl;
}
sc.end_condition = mpi.least;
}
- traverse_backwards(tb, &tb->static_stack, lastkey, lk_base, &doit_select_delete, &sc);
+ traverse_backwards(tb, &tb->static_stack, lastkey, &doit_select_delete, &sc);
BUMP_REDS(p, 1000 - sc.max);
if (sc.max > 0) {
@@ -1696,7 +1680,7 @@ static int db_select_delete_tree(Process *p, DbTable *tbl,
}
key = GETKEY(tb, (sc.lastterm)->dbterm.tpl);
- sz = size_object_rel(key, sc.lastterm->dbterm.tpl);
+ sz = size_object(key);
if (IS_USMALL(0, sc.accum)) {
hp = HAlloc(p, sz + PROC_BIN_SIZE + 6);
eaccsum = make_small(sc.accum);
@@ -1706,7 +1690,7 @@ static int db_select_delete_tree(Process *p, DbTable *tbl,
eaccsum = uint_to_big(sc.accum, hp);
hp += BIG_UINT_HEAP_SIZE;
}
- key = copy_struct_rel(key, sz, &hp, &MSO(p), sc.lastterm->dbterm.tpl, NULL);
+ key = copy_struct(key, sz, &hp, &MSO(p));
mpb = db_make_mp_binary(p,mpi.mp,&hp);
continuation = TUPLE5
@@ -1734,7 +1718,7 @@ static int db_take_tree(Process *p, DbTable *tbl, Eterm key, Eterm *ret)
TreeDbTerm *this;
*ret = NIL;
- this = linkout_tree(tb, key, NULL);
+ this = linkout_tree(tb, key);
if (this) {
Eterm copy, *hp, *hend;
@@ -1845,9 +1829,7 @@ do_db_tree_foreach_offheap(TreeDbTerm *tdbt,
do_db_tree_foreach_offheap(tdbt->right, func, arg);
}
-static TreeDbTerm *linkout_tree(DbTableTree *tb,
- Eterm key, Eterm* key_base)
-{
+static TreeDbTerm *linkout_tree(DbTableTree *tb, Eterm key) {
TreeDbTerm **tstack[STACK_NEED];
int tpos = 0;
int dstack[STACK_NEED+1];
@@ -1869,7 +1851,7 @@ static TreeDbTerm *linkout_tree(DbTableTree *tb,
for (;;) {
if (!*this) { /* Failure */
return NULL;
- } else if ((c = cmp_key(tb, key, key_base, *this)) < 0) {
+ } else if ((c = cmp_key(tb, key, *this)) < 0) {
dstack[dpos++] = DIR_LEFT;
tstack[tpos++] = this;
this = &((*this)->left);
@@ -1933,7 +1915,7 @@ static TreeDbTerm *linkout_object_tree(DbTableTree *tb,
for (;;) {
if (!*this) { /* Failure */
return NULL;
- } else if ((c = cmp_key(tb,key,NULL,*this)) < 0) {
+ } else if ((c = cmp_key(tb,key,*this)) < 0) {
dstack[dpos++] = DIR_LEFT;
tstack[tpos++] = this;
this = &((*this)->left);
@@ -2319,15 +2301,13 @@ done:
* Find next and previous in sort order
*/
-static TreeDbTerm *find_next(DbTableTree *tb, DbTreeStack* stack,
- Eterm key, Eterm* key_base)
-{
+static TreeDbTerm *find_next(DbTableTree *tb, DbTreeStack* stack, Eterm key) {
TreeDbTerm *this;
TreeDbTerm *tmp;
Sint c;
if(( this = TOP_NODE(stack)) != NULL) {
- if (!cmp_key_eq(tb,key,key_base,this)) {
+ if (!cmp_key_eq(tb,key,this)) {
/* Start from the beginning */
stack->pos = stack->slot = 0;
}
@@ -2337,7 +2317,7 @@ static TreeDbTerm *find_next(DbTableTree *tb, DbTreeStack* stack,
return NULL;
for (;;) {
PUSH_NODE(stack, this);
- if (( c = cmp_key(tb,key,key_base,this) ) > 0) {
+ if (( c = cmp_key(tb,key,this) ) > 0) {
if (this->right == NULL) /* We are at the previos
and the element does
not exist */
@@ -2377,15 +2357,13 @@ static TreeDbTerm *find_next(DbTableTree *tb, DbTreeStack* stack,
return this;
}
-static TreeDbTerm *find_prev(DbTableTree *tb, DbTreeStack* stack,
- Eterm key, Eterm* key_base)
-{
+static TreeDbTerm *find_prev(DbTableTree *tb, DbTreeStack* stack, Eterm key) {
TreeDbTerm *this;
TreeDbTerm *tmp;
Sint c;
if(( this = TOP_NODE(stack)) != NULL) {
- if (!cmp_key_eq(tb,key,key_base,this)) {
+ if (!cmp_key_eq(tb,key,this)) {
/* Start from the beginning */
stack->pos = stack->slot = 0;
}
@@ -2395,7 +2373,7 @@ static TreeDbTerm *find_prev(DbTableTree *tb, DbTreeStack* stack,
return NULL;
for (;;) {
PUSH_NODE(stack, this);
- if (( c = cmp_key(tb,key,key_base,this) ) < 0) {
+ if (( c = cmp_key(tb,key,this) ) < 0) {
if (this->left == NULL) /* We are at the next
and the element does
not exist */
@@ -2448,8 +2426,7 @@ static TreeDbTerm *find_next_from_pb_key(DbTableTree *tb, DbTreeStack* stack,
return NULL;
for (;;) {
PUSH_NODE(stack, this);
- if (( c = cmp_partly_bound(key,GETKEY(tb, this->dbterm.tpl),
- this->dbterm.tpl) ) >= 0) {
+ if (( c = cmp_partly_bound(key,GETKEY(tb, this->dbterm.tpl))) >= 0) {
if (this->right == NULL) {
do {
tmp = POP_NODE(stack);
@@ -2482,8 +2459,7 @@ static TreeDbTerm *find_prev_from_pb_key(DbTableTree *tb, DbTreeStack* stack,
return NULL;
for (;;) {
PUSH_NODE(stack, this);
- if (( c = cmp_partly_bound(key,GETKEY(tb, this->dbterm.tpl),
- this->dbterm.tpl) ) <= 0) {
+ if (( c = cmp_partly_bound(key,GETKEY(tb, this->dbterm.tpl))) <= 0) {
if (this->left == NULL) {
do {
tmp = POP_NODE(stack);
@@ -2514,10 +2490,10 @@ static TreeDbTerm *find_node(DbTableTree *tb, Eterm key)
DbTreeStack* stack = get_static_stack(tb);
if(!stack || EMPTY_NODE(stack)
- || !cmp_key_eq(tb, key, NULL, (this=TOP_NODE(stack)))) {
+ || !cmp_key_eq(tb, key, (this=TOP_NODE(stack)))) {
this = tb->root;
- while (this != NULL && (res = cmp_key(tb,key,NULL,this)) != 0) {
+ while (this != NULL && (res = cmp_key(tb,key,this)) != 0) {
if (res < 0)
this = this->left;
else
@@ -2539,7 +2515,7 @@ static TreeDbTerm **find_node2(DbTableTree *tb, Eterm key)
Sint res;
this = &tb->root;
- while ((*this) != NULL && (res = cmp_key(tb, key, NULL, *this)) != 0) {
+ while ((*this) != NULL && (res = cmp_key(tb, key, *this)) != 0) {
if (res < 0)
this = &((*this)->left);
else
@@ -2589,9 +2565,6 @@ db_lookup_dbterm_tree(Process *p, DbTable *tbl, Eterm key, Eterm obj,
handle->flags = flags;
handle->bp = (void**) pp;
handle->new_size = (*pp)->dbterm.size;
-#if HALFWORD_HEAP
- handle->abs_vec = NULL;
-#endif
return 1;
}
@@ -2622,7 +2595,7 @@ db_finalize_dbterm_tree(int cret, DbUpdateHandle *handle)
*/
static void traverse_backwards(DbTableTree *tb,
DbTreeStack* stack,
- Eterm lastkey, Eterm* lk_base,
+ Eterm lastkey,
int (*doit)(DbTableTree *,
TreeDbTerm *,
void *,
@@ -2641,16 +2614,15 @@ static void traverse_backwards(DbTableTree *tb,
this = this->right;
}
this = TOP_NODE(stack);
- next = find_prev(tb, stack, GETKEY(tb, this->dbterm.tpl),
- this->dbterm.tpl);
+ next = find_prev(tb, stack, GETKEY(tb, this->dbterm.tpl));
if (!((*doit)(tb, this, context, 0)))
return;
} else {
- next = find_prev(tb, stack, lastkey, lk_base);
+ next = find_prev(tb, stack, lastkey);
}
while ((this = next) != NULL) {
- next = find_prev(tb, stack, GETKEY(tb, this->dbterm.tpl), this->dbterm.tpl);
+ next = find_prev(tb, stack, GETKEY(tb, this->dbterm.tpl));
if (!((*doit)(tb, this, context, 0)))
return;
}
@@ -2661,7 +2633,7 @@ static void traverse_backwards(DbTableTree *tb,
*/
static void traverse_forward(DbTableTree *tb,
DbTreeStack* stack,
- Eterm lastkey, Eterm* lk_base,
+ Eterm lastkey,
int (*doit)(DbTableTree *,
TreeDbTerm *,
void *,
@@ -2680,15 +2652,15 @@ static void traverse_forward(DbTableTree *tb,
this = this->left;
}
this = TOP_NODE(stack);
- next = find_next(tb, stack, GETKEY(tb, this->dbterm.tpl), this->dbterm.tpl);
+ next = find_next(tb, stack, GETKEY(tb, this->dbterm.tpl));
if (!((*doit)(tb, this, context, 1)))
return;
} else {
- next = find_next(tb, stack, lastkey, lk_base);
+ next = find_next(tb, stack, lastkey);
}
while ((this = next) != NULL) {
- next = find_next(tb, stack, GETKEY(tb, this->dbterm.tpl), this->dbterm.tpl);
+ next = find_next(tb, stack, GETKEY(tb, this->dbterm.tpl));
if (!((*doit)(tb, this, context, 1)))
return;
}
@@ -2725,7 +2697,7 @@ static int key_given(DbTableTree *tb, Eterm pattern, TreeDbTerm **ret,
-static Sint do_cmp_partly_bound(Eterm a, Eterm b, Eterm* b_base, int *done)
+static Sint do_cmp_partly_bound(Eterm a, Eterm b, int *done)
{
Eterm* aa;
Eterm* bb;
@@ -2739,44 +2711,44 @@ static Sint do_cmp_partly_bound(Eterm a, Eterm b, Eterm* b_base, int *done)
*done = 1;
return 0;
}
- if (is_same(a,NULL,b,b_base))
+ if (is_same(a,b))
return 0;
switch (a & _TAG_PRIMARY_MASK) {
case TAG_PRIMARY_LIST:
if (!is_list(b)) {
- return cmp_rel(a,NULL,b,b_base);
+ return CMP(a,b);
}
aa = list_val(a);
- bb = list_val_rel(b,b_base);
+ bb = list_val(b);
while (1) {
- if ((j = do_cmp_partly_bound(*aa++, *bb++, b_base, done)) != 0 || *done)
+ if ((j = do_cmp_partly_bound(*aa++, *bb++, done)) != 0 || *done)
return j;
- if (is_same(*aa, NULL, *bb, b_base))
+ if (is_same(*aa, *bb))
return 0;
if (is_not_list(*aa) || is_not_list(*bb))
- return do_cmp_partly_bound(*aa, *bb, b_base, done);
+ return do_cmp_partly_bound(*aa, *bb, done);
aa = list_val(*aa);
- bb = list_val_rel(*bb,b_base);
+ bb = list_val(*bb);
}
case TAG_PRIMARY_BOXED:
if ((b & _TAG_PRIMARY_MASK) != TAG_PRIMARY_BOXED) {
- return cmp_rel(a,NULL,b,b_base);
+ return CMP(a,b);
}
a_hdr = ((*boxed_val(a)) & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE;
- b_hdr = ((*boxed_val_rel(b,b_base)) & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE;
+ b_hdr = ((*boxed_val(b)) & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE;
if (a_hdr != b_hdr) {
- return cmp_rel(a, NULL, b, b_base);
+ return CMP(a,b);
}
if (a_hdr == (_TAG_HEADER_ARITYVAL >> _TAG_PRIMARY_SIZE)) {
aa = tuple_val(a);
- bb = tuple_val_rel(b, b_base);
+ bb = tuple_val(b);
/* compare the arities */
i = arityval(*aa); /* get the arity*/
if (i < arityval(*bb)) return(-1);
if (i > arityval(*bb)) return(1);
while (i--) {
- if ((j = do_cmp_partly_bound(*++aa, *++bb, b_base, done)) != 0
+ if ((j = do_cmp_partly_bound(*++aa, *++bb, done)) != 0
|| *done)
return j;
}
@@ -2784,14 +2756,13 @@ static Sint do_cmp_partly_bound(Eterm a, Eterm b, Eterm* b_base, int *done)
}
/* Drop through */
default:
- return cmp_rel(a, NULL, b, b_base);
+ return CMP(a,b);
}
}
-static Sint cmp_partly_bound(Eterm partly_bound_key, Eterm bound_key, Eterm* bk_base)
-{
+static Sint cmp_partly_bound(Eterm partly_bound_key, Eterm bound_key) {
int done = 0;
- Sint ret = do_cmp_partly_bound(partly_bound_key, bound_key, bk_base, &done);
+ Sint ret = do_cmp_partly_bound(partly_bound_key, bound_key, &done);
#ifdef HARDDEBUG
erts_fprintf(stderr,"\ncmp_partly_bound: %T", partly_bound_key);
if (ret < 0)
@@ -2800,7 +2771,7 @@ static Sint cmp_partly_bound(Eterm partly_bound_key, Eterm bound_key, Eterm* bk_
erts_fprintf(stderr," > ");
else
erts_fprintf(stderr," == ");
- erts_fprintf(stderr,"%R\n", bound_key, bk_base);
+ erts_fprintf(stderr,"%T\n", bound_key);
#endif
return ret;
}
@@ -3017,12 +2988,10 @@ static int doit_select(DbTableTree *tb, TreeDbTerm *this, void *ptr,
if (sc->end_condition != NIL &&
((forward &&
cmp_partly_bound(sc->end_condition,
- GETKEY_WITH_POS(sc->keypos, this->dbterm.tpl),
- this->dbterm.tpl) < 0) ||
+ GETKEY_WITH_POS(sc->keypos, this->dbterm.tpl)) < 0) ||
(!forward &&
cmp_partly_bound(sc->end_condition,
- GETKEY_WITH_POS(sc->keypos, this->dbterm.tpl),
- this->dbterm.tpl) > 0))) {
+ GETKEY_WITH_POS(sc->keypos, this->dbterm.tpl)) > 0))) {
return 0;
}
ret = db_match_dbterm(&tb->common,sc->p,sc->mp,sc->all_objects,
@@ -3054,8 +3023,7 @@ static int doit_select_count(DbTableTree *tb, TreeDbTerm *this, void *ptr,
/* Always backwards traversing */
if (sc->end_condition != NIL &&
(cmp_partly_bound(sc->end_condition,
- GETKEY_WITH_POS(sc->keypos, this->dbterm.tpl),
- this->dbterm.tpl) > 0)) {
+ GETKEY_WITH_POS(sc->keypos, this->dbterm.tpl)) > 0)) {
return 0;
}
ret = db_match_dbterm(&tb->common, sc->p, sc->mp, 0,
@@ -3081,12 +3049,10 @@ static int doit_select_chunk(DbTableTree *tb, TreeDbTerm *this, void *ptr,
if (sc->end_condition != NIL &&
((forward &&
cmp_partly_bound(sc->end_condition,
- GETKEY_WITH_POS(sc->keypos, this->dbterm.tpl),
- this->dbterm.tpl) < 0) ||
+ GETKEY_WITH_POS(sc->keypos, this->dbterm.tpl)) < 0) ||
(!forward &&
cmp_partly_bound(sc->end_condition,
- GETKEY_WITH_POS(sc->keypos, this->dbterm.tpl),
- this->dbterm.tpl) > 0))) {
+ GETKEY_WITH_POS(sc->keypos, this->dbterm.tpl)) > 0))) {
return 0;
}
@@ -3124,14 +3090,13 @@ static int doit_select_delete(DbTableTree *tb, TreeDbTerm *this, void *ptr,
if (sc->end_condition != NIL &&
cmp_partly_bound(sc->end_condition,
- GETKEY_WITH_POS(sc->keypos, this->dbterm.tpl),
- this->dbterm.tpl) > 0)
+ GETKEY_WITH_POS(sc->keypos, this->dbterm.tpl)) > 0)
return 0;
ret = db_match_dbterm(&tb->common, sc->p, sc->mp, 0,
&this->dbterm, NULL, 0);
if (ret == am_true) {
key = GETKEY(sc->tb, this->dbterm.tpl);
- linkout_tree(sc->tb, key, this->dbterm.tpl);
+ linkout_tree(sc->tb, key);
sc->erase_lastterm = 1;
++sc->accum;
}
@@ -3157,11 +3122,10 @@ static void do_dump_tree2(DbTableTree* tb, int to, void *to_arg, int show,
}
else {
prefix = "";
- term = make_tuple_rel(t->dbterm.tpl,t->dbterm.tpl);
+ term = make_tuple(t->dbterm.tpl);
}
- erts_print(to, to_arg, "%*s%s%R (addr = %p, bal = %d)\n",
- offset, "", prefix, term, t->dbterm.tpl,
- t, t->balance);
+ erts_print(to, to_arg, "%*s%s%T (addr = %p, bal = %d)\n",
+ offset, "", prefix, term, t, t->balance);
}
do_dump_tree2(tb, to, to_arg, show, t->left, offset + 4);
}
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index af5b611afd..973be58420 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -239,11 +239,7 @@ typedef enum {
matchCall2,
matchCall3,
matchPushV,
-#if HALFWORD_HEAP
- matchPushVGuard, /* First guard-only variable reference */
-#endif
- matchPushVResult, /* First variable reference in result, or (if HALFWORD)
- in guard if also referenced in result */
+ matchPushVResult, /* First variable reference in result */
matchPushExpr, /* Push the whole expression we're matching ('$_') */
matchPushArrayAsList, /* Only when parameter is an Array and
not an erlang term (DCOMP_TRACE) */
@@ -310,9 +306,6 @@ DMC_DECLARE_STACK_TYPE(unsigned);
typedef struct DMCVariable {
int is_bound;
int is_in_body;
-#if HALFWORD_HEAP
- int first_guard_label; /* to maybe change from PushVGuard to PushVResult */
-#endif
} DMCVariable;
typedef struct DMCHeap {
@@ -374,7 +367,6 @@ typedef struct MatchVariable {
Eterm term;
#ifdef DEBUG
Process* proc;
- Eterm* base;
#endif
} MatchVariable;
@@ -415,7 +407,7 @@ cleanup_match_pseudo_process(ErtsMatchPseudoProcess *mpsp, int keep_heap)
else {
int i;
for (i = 0; i < ERTS_DEFAULT_MS_HEAP_SIZE; i++) {
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
mpsp->default_heap[i] = (Eterm) 0xdeadbeefdeadbeef;
#else
mpsp->default_heap[i] = (Eterm) 0xdeadbeef;
@@ -1240,7 +1232,7 @@ Eterm erts_match_set_run(Process *p, Binary *mpsp,
{
Eterm ret;
- ret = db_prog_match(p, mpsp, NIL, NULL, args, num_args,
+ ret = db_prog_match(p, mpsp, NIL, args, num_args,
in_flags, return_flags);
#if defined(HARDDEBUG)
if (is_non_value(ret)) {
@@ -1265,7 +1257,7 @@ static Eterm erts_match_set_run_ets(Process *p, Binary *mpsp,
{
Eterm ret;
- ret = db_prog_match(p, mpsp, args, NULL, NULL, num_args,
+ ret = db_prog_match(p, mpsp, args, NULL, num_args,
ERTS_PAM_COPY_RESULT,
return_flags);
#if defined(HARDDEBUG)
@@ -1755,71 +1747,6 @@ static Eterm dpm_array_to_list(Process *psp, Eterm *arr, int arity)
return ret;
}
-
-#if HALFWORD_HEAP
-struct heap_checkpoint_t
-{
- Process *p;
- Eterm* htop;
- ErlHeapFragment* mbuf;
- unsigned used_size;
- ErlOffHeap off_heap;
-};
-
-static void heap_checkpoint_init(Process* p, struct heap_checkpoint_t* hcp)
-{
- hcp->p = p;
- hcp->htop = HEAP_TOP(p);
- hcp->mbuf = MBUF(p);
- hcp->used_size = hcp->mbuf ? hcp->mbuf->used_size : 0;
- hcp->off_heap = MSO(p);
-}
-
-static void heap_checkpoint_revert(struct heap_checkpoint_t* hcp)
-{
- struct erl_off_heap_header* oh = MSO(hcp->p).first;
-
- if (oh != hcp->off_heap.first) {
- ASSERT(oh != NULL);
- if (hcp->off_heap.first) {
- while (oh->next != hcp->off_heap.first) {
- oh = oh->next;
- }
- oh->next = NULL;
- }
- erts_cleanup_offheap(&MSO(hcp->p));
- MSO(hcp->p) = hcp->off_heap;
- }
- if (MBUF(hcp->p) != hcp->mbuf) {
- ErlHeapFragment* hf = MBUF(hcp->p);
- ASSERT(hf != NULL);
- if (hcp->mbuf) {
- while (hf->next != hcp->mbuf) {
- hf = hf->next;
- }
- hf->next = NULL;
- }
- free_message_buffer(MBUF(hcp->p));
- MBUF(hcp->p) = hcp->mbuf;
- }
- if (hcp->mbuf != NULL && hcp->mbuf->used_size != hcp->used_size) {
- hcp->mbuf->used_size = hcp->used_size;
- }
- HEAP_TOP(hcp->p) = hcp->htop;
-}
-#endif /* HALFWORD_HEAP */
-
-static ERTS_INLINE Eterm copy_object_rel(Process* p, Eterm term, Eterm* base)
-{
- if (!is_immed(term)) {
- Uint sz = size_object_rel(term, base);
- Eterm* top = HAllocX(p, sz, HEAP_XTRA);
- return copy_struct_rel(term, sz, &top, &MSO(p), base, NULL);
- }
- return term;
-}
-
-
/*
** Execution of the match program, this is Pam.
** May return THE_NON_VALUE, which is a bailout.
@@ -1827,7 +1754,7 @@ static ERTS_INLINE Eterm copy_object_rel(Process* p, Eterm term, Eterm* base)
** i.e. 'DCOMP_TRACE' was specified
*/
Eterm db_prog_match(Process *c_p, Binary *bprog,
- Eterm term, Eterm* base,
+ Eterm term,
Eterm *termp,
int arity,
enum erts_pam_run_flags in_flags,
@@ -1855,17 +1782,12 @@ Eterm db_prog_match(Process *c_p, Binary *bprog,
Eterm bif_args[3];
int fail_label;
int atomic_trace;
-#if HALFWORD_HEAP
- struct heap_checkpoint_t c_p_checkpoint = {};
-#endif
#ifdef DMC_DEBUG
Uint *heap_fence;
Uint *stack_fence;
Uint save_op;
#endif /* DMC_DEBUG */
- ASSERT(base==NULL || HALFWORD_HEAP);
-
mpsp = get_match_pseudo_process(c_p, prog->heap_size);
psp = &mpsp->process;
@@ -1916,11 +1838,7 @@ Eterm db_prog_match(Process *c_p, Binary *bprog,
do_catch != 0 */
*return_flags = 0U;
-
variables = mpsp->u.variables;
-#if HALFWORD_HEAP
- c_p_checkpoint.p = NULL;
-#endif
restart:
ep = &term;
@@ -1931,14 +1849,12 @@ restart:
fail_label = -1;
build_proc = psp;
esdp->current_process = psp;
- ASSERT_HALFWORD(!c_p_checkpoint.p);
#ifdef DEBUG
ASSERT(variables == mpsp->u.variables);
for (i=0; i<prog->num_bindings; i++) {
variables[i].term = THE_NON_VALUE;
variables[i].proc = NULL;
- variables[i].base = base;
}
#endif
@@ -1974,9 +1890,9 @@ restart:
variables[n].term = dpm_array_to_list(psp, termp, arity);
break;
case matchTuple: /* *ep is a tuple of arity n */
- if (!is_tuple_rel(*ep,base))
+ if (!is_tuple(*ep))
FAIL();
- ep = tuple_val_rel(*ep,base);
+ ep = tuple_val(*ep);
n = *pc++;
if (arityval(*ep) != n)
FAIL();
@@ -1984,9 +1900,9 @@ restart:
break;
case matchPushT: /* *ep is a tuple of arity n,
push ptr to first element */
- if (!is_tuple_rel(*ep,base))
+ if (!is_tuple(*ep))
FAIL();
- tp = tuple_val_rel(*ep,base);
+ tp = tuple_val(*ep);
n = *pc++;
if (arityval(*tp) != n)
FAIL();
@@ -1996,51 +1912,51 @@ restart:
case matchList:
if (!is_list(*ep))
FAIL();
- ep = list_val_rel(*ep,base);
+ ep = list_val(*ep);
break;
case matchPushL:
if (!is_list(*ep))
FAIL();
- *sp++ = list_val_rel(*ep,base);
+ *sp++ = list_val(*ep);
++ep;
break;
case matchMap:
- if (!is_map_rel(*ep, base)) {
+ if (!is_map(*ep)) {
FAIL();
}
n = *pc++;
- if (is_flatmap_rel(*ep,base)) {
- if (flatmap_get_size(flatmap_val_rel(*ep, base)) < n) {
+ if (is_flatmap(*ep)) {
+ if (flatmap_get_size(flatmap_val(*ep)) < n) {
FAIL();
}
} else {
- ASSERT(is_hashmap_rel(*ep,base));
- if (hashmap_size_rel(*ep, base) < n) {
+ ASSERT(is_hashmap(*ep));
+ if (hashmap_size(*ep) < n) {
FAIL();
}
}
- ep = flatmap_val_rel(*ep, base);
+ ep = flatmap_val(*ep);
break;
case matchPushM:
- if (!is_map_rel(*ep, base)) {
+ if (!is_map(*ep)) {
FAIL();
}
n = *pc++;
- if (is_flatmap_rel(*ep,base)) {
- if (flatmap_get_size(flatmap_val_rel(*ep, base)) < n) {
+ if (is_flatmap(*ep)) {
+ if (flatmap_get_size(flatmap_val(*ep)) < n) {
FAIL();
}
} else {
- ASSERT(is_hashmap_rel(*ep,base));
- if (hashmap_size_rel(*ep, base) < n) {
+ ASSERT(is_hashmap(*ep));
+ if (hashmap_size(*ep) < n) {
FAIL();
}
}
- *sp++ = flatmap_val_rel(*ep++, base);
+ *sp++ = flatmap_val(*ep++);
break;
case matchKey:
t = (Eterm) *pc++;
- tp = erts_maps_get_rel(t, make_boxed_rel(ep, base), base);
+ tp = erts_maps_get(t, make_boxed(ep));
if (!tp) {
FAIL();
}
@@ -2061,29 +1977,29 @@ restart:
break;
case matchCmp:
n = *pc++;
- if (!eq_rel(variables[n].term, base, *ep, base))
+ if (!EQ(variables[n].term, *ep))
FAIL();
++ep;
break;
case matchEqBin:
t = (Eterm) *pc++;
- if (!eq_rel(t,NULL,*ep,base))
+ if (!EQ(t,*ep))
FAIL();
++ep;
break;
case matchEqFloat:
- if (!is_float_rel(*ep,base))
+ if (!is_float(*ep))
FAIL();
- if (memcmp(float_val_rel(*ep,base) + 1, pc, sizeof(double)))
+ if (memcmp(float_val(*ep) + 1, pc, sizeof(double)))
FAIL();
pc += TermWords(2);
++ep;
break;
case matchEqRef: {
Eterm* epc = (Eterm*)pc;
- if (!is_ref_rel(*ep,base))
+ if (!is_ref(*ep))
FAIL();
- if (!eq_rel(make_internal_ref_rel(epc, epc), epc, *ep, base)) {
+ if (!EQ(make_internal_ref(epc), *ep)) {
FAIL();
}
i = thing_arityval(*epc);
@@ -2092,9 +2008,9 @@ restart:
break;
}
case matchEqBig:
- if (!is_big_rel(*ep,base))
+ if (!is_big(*ep))
FAIL();
- tp = big_val_rel(*ep,base);
+ tp = big_val(*ep);
{
Eterm *epc = (Eterm *) pc;
if (*tp != *epc)
@@ -2236,62 +2152,36 @@ restart:
esp -= 2;
esp[-1] = t;
break;
-
- #if HALFWORD_HEAP
- case matchPushVGuard:
- if (!base) goto case_matchPushV;
- /* Build NULL-based copy on pseudo heap for easy disposal */
- n = *pc++;
- ASSERT(is_value(variables[n].term));
- ASSERT(!variables[n].proc);
- variables[n].term = copy_object_rel(psp, variables[n].term, base);
- *esp++ = variables[n].term;
- #ifdef DEBUG
- variables[n].proc = psp;
- variables[n].base = NULL;
- #endif
- break;
- #endif
case matchPushVResult:
if (!(in_flags & ERTS_PAM_COPY_RESULT)) goto case_matchPushV;
-
- /* Build (NULL-based) copy on callers heap */
- #if HALFWORD_HEAP
- if (!do_catch && !c_p_checkpoint.p) {
- heap_checkpoint_init(c_p, &c_p_checkpoint);
- }
- #endif
+ /* Build copy on callers heap */
n = *pc++;
ASSERT(is_value(variables[n].term));
ASSERT(!variables[n].proc);
- variables[n].term = copy_object_rel(c_p, variables[n].term, base);
+ variables[n].term = copy_object_x(variables[n].term, c_p, HEAP_XTRA);
*esp++ = variables[n].term;
#ifdef DEBUG
variables[n].proc = c_p;
- variables[n].base = NULL;
#endif
break;
case matchPushV:
case_matchPushV:
n = *pc++;
ASSERT(is_value(variables[n].term));
- ASSERT(!variables[n].base);
*esp++ = variables[n].term;
break;
case matchPushExpr:
if (in_flags & ERTS_PAM_COPY_RESULT) {
Uint sz;
Eterm* top;
- sz = size_object_rel(term, base);
+ sz = size_object(term);
top = HAllocX(build_proc, sz, HEAP_XTRA);
if (in_flags & ERTS_PAM_CONTIGUOUS_TUPLE) {
- ASSERT(is_tuple_rel(term,base));
- *esp++ = copy_shallow_rel(tuple_val_rel(term,base), sz,
- &top, &MSO(build_proc), base);
+ ASSERT(is_tuple(term));
+ *esp++ = copy_shallow(tuple_val(term), sz, &top, &MSO(build_proc));
}
else {
- *esp++ = copy_struct_rel(term, sz, &top, &MSO(build_proc),
- base, NULL);
+ *esp++ = copy_struct(term, sz, &top, &MSO(build_proc));
}
}
else {
@@ -2299,7 +2189,6 @@ restart:
}
break;
case matchPushArrayAsList:
- ASSERT_HALFWORD(base == NULL);
n = arity; /* Only happens when 'term' is an array */
tp = termp;
ehp = HAllocX(build_proc, n*2, HEAP_XTRA);
@@ -2315,7 +2204,6 @@ restart:
break;
case matchPushArrayAsListU:
/* This instruction is NOT efficient. */
- ASSERT_HALFWORD(base == NULL);
*esp++ = dpm_array_to_list(build_proc, termp, arity);
break;
case matchTrue:
@@ -2420,11 +2308,7 @@ restart:
*esp++ = am_true;
break;
case matchIsSeqTrace:
- if (SEQ_TRACE_TOKEN(c_p) != NIL
-#ifdef USE_VM_PROBES
- && SEQ_TRACE_TOKEN(c_p) != am_have_dt_utag
-#endif
- )
+ if (have_seqtrace(SEQ_TRACE_TOKEN(c_p)))
*esp++ = am_true;
else
*esp++ = am_false;
@@ -2448,11 +2332,7 @@ restart:
--esp;
break;
case matchGetSeqToken:
- if (SEQ_TRACE_TOKEN(c_p) == NIL
-#ifdef USE_VM_PROBES
- || SEQ_TRACE_TOKEN(c_p) == am_have_dt_utag
-#endif
- )
+ if (have_no_seqtrace(SEQ_TRACE_TOKEN(c_p)))
*esp++ = NIL;
else {
Eterm sender = SEQ_TRACE_TOKEN_SENDER(c_p);
@@ -2619,13 +2499,6 @@ restart:
}
}
fail:
-#if HALFWORD_HEAP
- if (c_p_checkpoint.p) {
- /* Dispose garbage built by guards on caller heap */
- heap_checkpoint_revert(&c_p_checkpoint);
- c_p_checkpoint.p = NULL;
- }
-#endif
*return_flags = 0U;
if (fail_label >= 0) { /* We failed during a "TryMeElse",
lets restart, with the next match
@@ -2788,13 +2661,6 @@ Wterm db_do_read_element(DbUpdateHandle* handle, Sint position)
{
Eterm elem = handle->dbterm->tpl[position];
if (!is_header(elem)) {
-#if HALFWORD_HEAP
- if (!is_immed(elem)
- && !handle->tb->common.compress
- && !(handle->abs_vec && handle->abs_vec[position])) {
- return rterm2wterm(elem, handle->dbterm->tpl);
- }
-#endif
return elem;
}
@@ -2822,9 +2688,6 @@ void db_do_update_element(DbUpdateHandle* handle,
Eterm* oldp;
Uint newval_sz;
Uint oldval_sz;
-#if HALFWORD_HEAP
- Eterm* old_base;
-#endif
if (is_both_immed(newval,oldval)) {
handle->dbterm->tpl[position] = newval;
@@ -2841,15 +2704,8 @@ void db_do_update_element(DbUpdateHandle* handle,
handle->dbterm);
handle->flags |= DB_MUST_RESIZE;
oldval = handle->dbterm->tpl[position];
- #if HALFWORD_HEAP
- old_base = NULL;
- #endif
}
else {
- #if HALFWORD_HEAP
- ASSERT(!handle->abs_vec);
- old_base = handle->dbterm->tpl;
- #endif
if (is_boxed(newval)) {
newp = boxed_val(newval);
switch (*newp & _TAG_HEADER_MASK) {
@@ -2859,7 +2715,7 @@ void db_do_update_element(DbUpdateHandle* handle,
case _TAG_HEADER_HEAP_BIN:
newval_sz = header_arity(*newp) + 1;
if (is_boxed(oldval)) {
- oldp = boxed_val_rel(oldval,old_base);
+ oldp = boxed_val(oldval);
switch (*oldp & _TAG_HEADER_MASK) {
case _TAG_HEADER_POS_BIG:
case _TAG_HEADER_NEG_BIG:
@@ -2879,20 +2735,13 @@ void db_do_update_element(DbUpdateHandle* handle,
}
}
}
-#if HALFWORD_HEAP
- else {
- old_base = (handle->tb->common.compress
- || (handle->abs_vec && handle->abs_vec[position])) ?
- NULL : handle->dbterm->tpl;
- }
-#endif
/* Not possible for simple memcpy or dbterm is already non-contiguous, */
/* need to realloc... */
newval_sz = is_immed(newval) ? 0 : size_object(newval);
new_size_set:
- oldval_sz = is_immed(oldval) ? 0 : size_object_rel(oldval,old_base);
+ oldval_sz = is_immed(oldval) ? 0 : size_object(oldval);
both_size_set:
handle->new_size = handle->new_size - oldval_sz + newval_sz;
@@ -2900,19 +2749,6 @@ both_size_set:
/* write new value in old dbterm, finalize will make a flat copy */
handle->dbterm->tpl[position] = newval;
handle->flags |= DB_MUST_RESIZE;
-
-#if HALFWORD_HEAP
- if (old_base && newval_sz > 0) {
- ASSERT(!handle->tb->common.compress);
- if (!handle->abs_vec) {
- int i = header_arity(handle->dbterm->tpl[0]);
- handle->abs_vec = erts_alloc(ERTS_ALC_T_TMP, (i+1)*sizeof(char));
- sys_memset(handle->abs_vec, 0, i+1);
- /* abs_vec[0] not used */
- }
- handle->abs_vec[position] = 1;
- }
-#endif
}
static ERTS_INLINE byte* db_realloc_term(DbTableCommon* tb, void* old,
@@ -3011,7 +2847,7 @@ static void* copy_to_comp(DbTableCommon* tb, Eterm obj, DbTerm* dest,
tpl[arity + 1] = alloc_size;
tmp_offheap.first = NULL;
- tpl[tb->keypos] = copy_struct_rel(key, size_object(key), &top.ep, &tmp_offheap, NULL, tpl);
+ tpl[tb->keypos] = copy_struct(key, size_object(key), &top.ep, &tmp_offheap);
dest->first_oh = tmp_offheap.first;
for (i=1; i<=arity; i++) {
if (i != tb->keypos) {
@@ -3030,7 +2866,7 @@ static void* copy_to_comp(DbTableCommon* tb, Eterm obj, DbTerm* dest,
Eterm* dbg_top = erts_alloc(ERTS_ALC_T_DB_TERM, dest->size * sizeof(Eterm));
dest->debug_clone = dbg_top;
tmp_offheap.first = dest->first_oh;
- copy_struct_rel(obj, dest->size, &dbg_top, &tmp_offheap, NULL, dbg_top);
+ copy_struct(obj, dest->size, &dbg_top, &tmp_offheap);
dest->first_oh = tmp_offheap.first;
ASSERT(dbg_top == dest->debug_clone + dest->size);
}
@@ -3077,7 +2913,7 @@ void* db_store_term(DbTableCommon *tb, DbTerm* old, Uint offset, Eterm obj)
newp->size = size;
top = newp->tpl;
tmp_offheap.first = NULL;
- copy_struct_rel(obj, size, &top, &tmp_offheap, NULL, top);
+ copy_struct(obj, size, &top, &tmp_offheap);
newp->first_oh = tmp_offheap.first;
#ifdef DEBUG_CLONE
newp->debug_clone = NULL;
@@ -3160,29 +2996,8 @@ void db_finalize_resize(DbUpdateHandle* handle, Uint offset)
tmp_offheap.first = NULL;
- #if HALFWORD_HEAP
- if (handle->abs_vec) {
- int i, arity = header_arity(handle->dbterm->tpl[0]);
-
- top[0] = tpl[0];
- top += arity + 1;
- for (i=1; i<=arity; i++) {
- Eterm* src_base = handle->abs_vec[i] ? NULL : tpl;
-
- newDbTerm->tpl[i] = copy_struct_rel(tpl[i],
- size_object_rel(tpl[i],src_base),
- &top, &tmp_offheap, src_base,
- newDbTerm->tpl);
- }
- newDbTerm->first_oh = tmp_offheap.first;
- ASSERT((byte*)top <= (newp + alloc_sz));
- erts_free(ERTS_ALC_T_TMP, handle->abs_vec);
- }
- else
- #endif /* HALFWORD_HEAP */
{
- copy_struct_rel(make_tuple_rel(tpl,tpl), handle->new_size, &top,
- &tmp_offheap, tpl, top);
+ copy_struct(make_tuple(tpl), handle->new_size, &top, &tmp_offheap);
newDbTerm->first_oh = tmp_offheap.first;
ASSERT((byte*)top == (newp + alloc_sz));
}
@@ -3199,9 +3014,9 @@ Eterm db_copy_from_comp(DbTableCommon* tb, DbTerm* bp, Eterm** hpp,
hp[0] = bp->tpl[0];
*hpp += arity + 1;
- hp[tb->keypos] = copy_struct_rel(bp->tpl[tb->keypos],
- size_object_rel(bp->tpl[tb->keypos], bp->tpl),
- hpp, off_heap, bp->tpl, NULL);
+ hp[tb->keypos] = copy_struct(bp->tpl[tb->keypos],
+ size_object(bp->tpl[tb->keypos]),
+ hpp, off_heap);
erts_factory_static_init(&factory, *hpp, bp->size - (arity+1), off_heap);
@@ -3221,7 +3036,7 @@ Eterm db_copy_from_comp(DbTableCommon* tb, DbTerm* bp, Eterm** hpp,
ASSERT((*hpp - hp) <= bp->size);
#ifdef DEBUG_CLONE
- ASSERT(eq_rel(make_tuple(hp),NULL,make_tuple(bp->debug_clone),bp->debug_clone));
+ ASSERT(EQ(make_tuple(hp),make_tuple(bp->debug_clone)));
#endif
return make_tuple(hp);
}
@@ -3245,14 +3060,14 @@ Eterm db_copy_element_from_ets(DbTableCommon* tb, Process* p,
*hpp = erts_produce_heap(&factory, extra, 0);
erts_factory_close(&factory);
#ifdef DEBUG_CLONE
- ASSERT(eq_rel(copy, NULL, obj->debug_clone[pos], obj->debug_clone));
+ ASSERT(EQ(copy, obj->debug_clone[pos]));
#endif
return copy;
}
else {
- Uint sz = size_object_rel(obj->tpl[pos], obj->tpl);
+ Uint sz = size_object(obj->tpl[pos]);
*hpp = HAlloc(p, sz + extra);
- return copy_struct_rel(obj->tpl[pos], sz, hpp, &MSO(p), obj->tpl, NULL);
+ return copy_struct(obj->tpl[pos], sz, hpp, &MSO(p));
}
}
@@ -3599,26 +3414,10 @@ static DMCRet dmc_one_term(DMCContext *context,
{
Eterm* ref_val = internal_ref_val(c);
DMC_PUSH(*text, matchEqRef);
-#if HALFWORD_HEAP
- {
- union {
- UWord u;
- Uint t[2];
- } fiddle;
- ASSERT(thing_arityval(ref_val[0]) == 3);
- fiddle.t[0] = ref_val[0];
- fiddle.t[1] = ref_val[1];
- DMC_PUSH(*text, fiddle.u);
- fiddle.t[0] = ref_val[2];
- fiddle.t[1] = ref_val[3];
- DMC_PUSH(*text, fiddle.u);
- }
-#else
n = thing_arityval(ref_val[0]);
for (i = 0; i <= n; ++i) {
DMC_PUSH(*text, ref_val[i]);
}
-#endif
break;
}
case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):
@@ -3627,53 +3426,19 @@ static DMCRet dmc_one_term(DMCContext *context,
Eterm* bval = big_val(c);
n = thing_arityval(bval[0]);
DMC_PUSH(*text, matchEqBig);
-#if HALFWORD_HEAP
- {
- union {
- UWord u;
- Uint t[2];
- } fiddle;
- ASSERT(n >= 1);
- fiddle.t[0] = bval[0];
- fiddle.t[1] = bval[1];
- DMC_PUSH(*text, fiddle.u);
- for (i = 2; i <= n; ++i) {
- fiddle.t[0] = bval[i];
- if (++i <= n) {
- fiddle.t[1] = bval[i];
- } else {
- fiddle.t[1] = (Uint) 0;
- }
- DMC_PUSH(*text, fiddle.u);
- }
- }
-#else
for (i = 0; i <= n; ++i) {
DMC_PUSH(*text, (Uint) bval[i]);
}
-#endif
break;
}
case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):
DMC_PUSH(*text,matchEqFloat);
-#if HALFWORD_HEAP
- {
- union {
- UWord u;
- Uint t[2];
- } fiddle;
- fiddle.t[0] = float_val(c)[1];
- fiddle.t[1] = float_val(c)[2];
- DMC_PUSH(*text, fiddle.u);
- }
-#else
DMC_PUSH(*text, (Uint) float_val(c)[1]);
#ifdef ARCH_64
DMC_PUSH(*text, (Uint) 0);
#else
DMC_PUSH(*text, (Uint) float_val(c)[2]);
#endif
-#endif
break;
default: /* BINARY, FUN, VECTOR, or EXTERNAL */
DMC_PUSH(*text, matchEqBin);
@@ -3997,24 +3762,8 @@ static void dmc_add_pushv_variant(DMCContext *context, DMCHeap *heap,
MatchOps instr = matchPushV;
ASSERT(n < heap->vars_used && v->is_bound);
- if (context->is_guard) {
- #if HALFWORD_HEAP
- if (!v->first_guard_label) {
- v->first_guard_label = DMC_STACK_NUM(*text);
- ASSERT(v->first_guard_label);
- instr = matchPushVGuard; /* may be changed to PushVResult below */
- }
- #endif
- }
- else { /* body */
- #if HALFWORD_HEAP
- if (v->first_guard_label) {
- /* Avoid double-copy, copy to result heap at first encounter in guard */
- DMC_POKE(*text, v->first_guard_label, matchPushVResult);
- v->is_in_body = 1;
- }
- #endif
- if (!v->is_in_body) {
+ if (!context->is_guard) {
+ if(!v->is_in_body) {
instr = matchPushVResult;
v->is_in_body = 1;
}
@@ -5443,16 +5192,13 @@ Eterm db_match_dbterm(DbTableCommon* tb, Process* c_p, Binary* bprog,
int all, DbTerm* obj, Eterm** hpp, Uint extra)
{
Uint32 dummy;
- Eterm* base;
Eterm res;
if (tb->compress) {
obj = db_alloc_tmp_uncompressed(tb, obj);
- base = NULL;
}
- else base = HALFWORD_HEAP ? obj->tpl : NULL;
- res = db_prog_match(c_p, bprog, make_tuple_rel(obj->tpl,base), base, NULL, 0,
+ res = db_prog_match(c_p, bprog, make_tuple(obj->tpl), NULL, 0,
ERTS_PAM_COPY_RESULT|ERTS_PAM_CONTIGUOUS_TUPLE, &dummy);
if (is_value(res) && hpp!=NULL) {
@@ -5573,7 +5319,7 @@ void db_match_dis(Binary *bp)
first = 0;
else
erts_printf(", ");
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
erts_printf("0x%016bex", rt->data.ui[ri]);
#else
erts_printf("0x%08bex", rt->data.ui[ri]);
@@ -5597,7 +5343,7 @@ void db_match_dis(Binary *bp)
first = 0;
else
erts_printf(", ");
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
erts_printf("0x%016bex", *et);
#else
erts_printf("0x%08bex", *et);
@@ -5720,13 +5466,6 @@ void db_match_dis(Binary *bp)
++t;
erts_printf("PushV\t%beu\n", n);
break;
- #if HALFWORD_HEAP
- case matchPushVGuard:
- n = (Uint) *++t;
- ++t;
- erts_printf("PushVGuard\t%beu\n", n);
- break;
- #endif
case matchPushVResult:
n = (Uint) *++t;
++t;
diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h
index 0903a40460..911ed37aef 100644
--- a/erts/emulator/beam/erl_db_util.h
+++ b/erts/emulator/beam/erl_db_util.h
@@ -90,9 +90,6 @@ typedef struct {
Uint new_size;
int flags;
void* lck;
-#if HALFWORD_HEAP
- unsigned char* abs_vec; /* [i] true if dbterm->tpl[i] is absolute Eterm */
-#endif
} DbUpdateHandle;
@@ -290,10 +287,10 @@ ERTS_GLB_INLINE Eterm db_copy_key(Process* p, DbTable* tb, DbTerm* obj)
Eterm key = GETKEY(tb, obj->tpl);
if IS_CONST(key) return key;
else {
- Uint size = size_object_rel(key, obj->tpl);
+ Uint size = size_object(key);
Eterm* hp = HAlloc(p, size);
- Eterm res = copy_struct_rel(key, size, &hp, &MSO(p), obj->tpl, NULL);
- ASSERT(eq_rel(res,NULL,key,obj->tpl));
+ Eterm res = copy_struct(key, size, &hp, &MSO(p));
+ ASSERT(EQ(res,key));
return res;
}
}
@@ -305,14 +302,14 @@ ERTS_GLB_INLINE Eterm db_copy_object_from_ets(DbTableCommon* tb, DbTerm* bp,
return db_copy_from_comp(tb, bp, hpp, off_heap);
}
else {
- return copy_shallow_rel(bp->tpl, bp->size, hpp, off_heap, bp->tpl);
+ return copy_shallow(bp->tpl, bp->size, hpp, off_heap);
}
}
ERTS_GLB_INLINE int db_eq(DbTableCommon* tb, Eterm a, DbTerm* b)
{
if (!tb->compress) {
- return eq_rel(a, NULL, make_tuple_rel(b->tpl,b->tpl), b->tpl);
+ return EQ(a, make_tuple(b->tpl));
}
else {
return db_eq_comp(tb, a, b);
@@ -438,7 +435,7 @@ Binary *db_match_compile(Eterm *matchexpr, Eterm *guards,
Eterm db_match_dbterm(DbTableCommon* tb, Process* c_p, Binary* bprog,
int all, DbTerm* obj, Eterm** hpp, Uint extra);
-Eterm db_prog_match(Process *p, Binary *prog, Eterm term, Eterm* base,
+Eterm db_prog_match(Process *p, Binary *prog, Eterm term,
Eterm *termp, int arity,
enum erts_pam_run_flags in_flags,
Uint32 *return_flags /* Zeroed on enter */);
diff --git a/erts/emulator/beam/erl_debug.c b/erts/emulator/beam/erl_debug.c
index 4928aae9c2..2902c98864 100644
--- a/erts/emulator/beam/erl_debug.c
+++ b/erts/emulator/beam/erl_debug.c
@@ -312,6 +312,8 @@ void erts_check_for_holes(Process* p)
p->last_htop = HEAP_TOP(p);
for (hf = MBUF(p); hf != 0; hf = hf->next) {
+ if (hf == p->heap_hfrag)
+ continue;
if (hf == p->last_mbuf) {
break;
}
@@ -402,7 +404,7 @@ void verify_process(Process *p)
erts_exit(ERTS_ERROR_EXIT,"Wild pointer found in " name " of %T!\n",p->common.id); }
- ErlMessage* mp = p->msg.first;
+ ErtsMessage* mp = p->msg.first;
VERBOSE(DEBUG_MEMORY,("Verify process: %T...\n",p->common.id));
@@ -416,7 +418,7 @@ void verify_process(Process *p)
erts_check_heap(p);
if (p->dictionary)
- VERIFY_AREA("dictionary",p->dictionary->data, p->dictionary->used);
+ VERIFY_AREA("dictionary", ERTS_PD_START(p->dictionary), ERTS_PD_SIZE(p->dictionary));
VERIFY_ETERM("seq trace token",p->seq_trace_token);
VERIFY_ETERM("group leader",p->group_leader);
VERIFY_ETERM("fvalue",p->fvalue);
@@ -531,7 +533,7 @@ static void print_process_memory(Process *p)
PTR_SIZE, "PCB", dashes, dashes, dashes, dashes);
if (p->msg.first != NULL) {
- ErlMessage* mp;
+ ErtsMessage* mp;
erts_printf(" Message Queue:\n");
mp = p->msg.first;
while (mp != NULL) {
@@ -542,8 +544,8 @@ static void print_process_memory(Process *p)
}
if (p->dictionary != NULL) {
- int n = p->dictionary->used;
- Eterm *ptr = p->dictionary->data;
+ int n = ERTS_PD_SIZE(p->dictionary);
+ Eterm *ptr = ERTS_PD_START(p->dictionary);
erts_printf(" Dictionary: ");
while (n--) erts_printf("0x%0*lx ",PTR_SIZE,(unsigned long)ptr++);
erts_printf("\n");
@@ -631,29 +633,4 @@ void print_memory_info(Process *p)
}
erts_printf("+-----------------%s-%s-%s-%s-+\n",dashes,dashes,dashes,dashes);
}
-#if !HEAP_ON_C_STACK && defined(DEBUG)
-Eterm *erts_debug_allocate_tmp_heap(int size, Process *p)
-{
- ErtsSchedulerData *sd = ((p == NULL) ? erts_get_scheduler_data() : ERTS_PROC_GET_SCHDATA(p));
- int offset = sd->num_tmp_heap_used;
-
- ASSERT(offset+size <= TMP_HEAP_SIZE);
- return (sd->tmp_heap)+offset;
-}
-void erts_debug_use_tmp_heap(int size, Process *p)
-{
- ErtsSchedulerData *sd = ((p == NULL) ? erts_get_scheduler_data() : ERTS_PROC_GET_SCHDATA(p));
-
- sd->num_tmp_heap_used += size;
- ASSERT(sd->num_tmp_heap_used <= TMP_HEAP_SIZE);
-}
-void erts_debug_unuse_tmp_heap(int size, Process *p)
-{
- ErtsSchedulerData *sd = ((p == NULL) ? erts_get_scheduler_data() : ERTS_PROC_GET_SCHDATA(p));
-
- sd->num_tmp_heap_used -= size;
- ASSERT(sd->num_tmp_heap_used >= 0);
-}
-#endif
#endif
-
diff --git a/erts/emulator/beam/erl_debug.h b/erts/emulator/beam/erl_debug.h
index 4905e64f07..029320691d 100644
--- a/erts/emulator/beam/erl_debug.h
+++ b/erts/emulator/beam/erl_debug.h
@@ -48,6 +48,7 @@
#define DEBUG_THREADS 0x0010 /* Thread-related stuff */
#define DEBUG_PROCESSES 0x0020 /* Process creation and removal */
#define DEBUG_MEMORY 0x0040 /* Display results of memory checks */
+#define DEBUG_SHCOPY 0x0080 /* Sharing-preserving copying of terms */
extern Uint32 verbose;
@@ -92,10 +93,4 @@ extern void print_tagged_memory(Eterm *start, Eterm *end);
extern void print_untagged_memory(Eterm *start, Eterm *end);
extern void print_memory(Process *p);
extern void print_memory_info(Process *p);
-#if defined(DEBUG) && !HEAP_ON_C_STACK
-extern Eterm *erts_debug_allocate_tmp_heap(int, Process *);
-extern void erts_debug_use_tmp_heap(int, Process *);
-extern void erts_debug_unuse_tmp_heap(int, Process *);
-#endif
-
#endif /* _ERL_DEBUG_H_ */
diff --git a/erts/emulator/beam/erl_driver.h b/erts/emulator/beam/erl_driver.h
index 7ab58e336b..0234b9b0e4 100644
--- a/erts/emulator/beam/erl_driver.h
+++ b/erts/emulator/beam/erl_driver.h
@@ -37,11 +37,6 @@
# endif
#endif
-/* This is OK to override by the NIF/driver implementor */
-#if defined(HALFWORD_HEAP_EMULATOR_SAVED__) && !defined(HALFWORD_HEAP_EMULATOR)
-#define HALFWORD_HEAP_EMULATOR HALFWORD_HEAP_EMULATOR_SAVED__
-#endif
-
#include "erl_drv_nif.h"
#include <stdlib.h>
@@ -131,6 +126,7 @@ typedef struct {
#define ERL_DRV_FLAG_USE_PORT_LOCKING (1 << 0)
#define ERL_DRV_FLAG_SOFT_BUSY (1 << 1)
#define ERL_DRV_FLAG_NO_BUSY_MSGQ (1 << 2)
+#define ERL_DRV_FLAG_USE_INIT_ACK (1 << 3)
/*
* Integer types
@@ -340,22 +336,23 @@ typedef struct erl_drv_entry {
#ifdef STATIC_ERLANG_DRIVER
# define ERLANG_DRIVER_NAME(NAME) NAME ## _driver_init
+# define ERL_DRIVER_EXPORT
#else
# define ERLANG_DRIVER_NAME(NAME) driver_init
+# if defined(__GNUC__) && __GNUC__ >= 4
+# define ERL_DRIVER_EXPORT __attribute__ ((visibility("default")))
+# elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+# define ERL_DRIVER_EXPORT __global
+# else
+# define ERL_DRIVER_EXPORT
+# endif
#endif
-/* For windows dynamic drivers */
#ifndef ERL_DRIVER_TYPES_ONLY
-#if defined(__WIN32__)
-# define DRIVER_INIT(DRIVER_NAME) \
- __declspec(dllexport) ErlDrvEntry* ERLANG_DRIVER_NAME(DRIVER_NAME)(void); \
- __declspec(dllexport) ErlDrvEntry* ERLANG_DRIVER_NAME(DRIVER_NAME)(void)
-#else
-# define DRIVER_INIT(DRIVER_NAME) \
- ErlDrvEntry* ERLANG_DRIVER_NAME(DRIVER_NAME)(void); \
- ErlDrvEntry* ERLANG_DRIVER_NAME(DRIVER_NAME)(void)
-#endif
+#define DRIVER_INIT(DRIVER_NAME) \
+ ERL_DRIVER_EXPORT ErlDrvEntry* ERLANG_DRIVER_NAME(DRIVER_NAME)(void); \
+ ERL_DRIVER_EXPORT ErlDrvEntry* ERLANG_DRIVER_NAME(DRIVER_NAME)(void)
#define ERL_DRV_BUSY_MSGQ_DISABLED (~((ErlDrvSizeT) 0))
#define ERL_DRV_BUSY_MSGQ_READ_ONLY ((ErlDrvSizeT) 0)
@@ -661,15 +658,11 @@ EXTERN char *driver_dl_error(void);
EXTERN int erl_drv_putenv(const char *key, char *value);
EXTERN int erl_drv_getenv(const char *key, char *value, size_t *value_size);
-#ifdef __OSE__
-typedef ErlDrvUInt ErlDrvOseEventId;
-EXTERN union SIGNAL *erl_drv_ose_get_signal(ErlDrvEvent ev);
-EXTERN ErlDrvEvent erl_drv_ose_event_alloc(SIGSELECT sig, ErlDrvOseEventId handle,
- ErlDrvOseEventId (*resolve_signal)(union SIGNAL *sig), void *extra);
-EXTERN void erl_drv_ose_event_free(ErlDrvEvent ev);
-EXTERN void erl_drv_ose_event_fetch(ErlDrvEvent ev, SIGSELECT *sig,
- ErlDrvOseEventId *handle, void **extra);
-#endif
+/* spawn start init ack */
+EXTERN void erl_drv_init_ack(ErlDrvPort ix, ErlDrvData res);
+
+/* set the pid seen in port_info */
+EXTERN void erl_drv_set_os_pid(ErlDrvPort ix, ErlDrvSInt pid);
#endif /* !ERL_DRIVER_TYPES_ONLY */
diff --git a/erts/emulator/beam/erl_fun.c b/erts/emulator/beam/erl_fun.c
index 2f13aa364f..ed555aa92f 100644
--- a/erts/emulator/beam/erl_fun.c
+++ b/erts/emulator/beam/erl_fun.c
@@ -66,6 +66,9 @@ erts_init_fun_table(void)
f.cmp = (HCMP_FUN) fun_cmp;
f.alloc = (HALLOC_FUN) fun_alloc;
f.free = (HFREE_FUN) fun_free;
+ f.meta_alloc = (HMALLOC_FUN) erts_alloc;
+ f.meta_free = (HMFREE_FUN) erts_free;
+ f.meta_print = (HMPRINT_FUN) erts_print;
hash_init(ERTS_ALC_T_FUN_TABLE, &erts_fun_table, "fun_table", 16, f);
}
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index f48c46ca33..0d125c5598 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -47,6 +47,17 @@
#define ERTS_INACT_WR_PB_LEAVE_LIMIT 10
#define ERTS_INACT_WR_PB_LEAVE_PERCENTAGE 10
+#if defined(DEBUG) || 0
+#define ERTS_GC_DEBUG
+#else
+#undef ERTS_GC_DEBUG
+#endif
+#ifdef ERTS_GC_DEBUG
+# define ERTS_GC_ASSERT ASSERT
+#else
+# define ERTS_GC_ASSERT(B) ((void) 1)
+#endif
+
/*
* Returns number of elements in an array.
*/
@@ -67,10 +78,10 @@
#define ErtsGcQuickSanityCheck(P) \
do { \
ASSERT((P)->heap < (P)->hend); \
- ASSERT((P)->heap_sz == (P)->hend - (P)->heap); \
+ ASSERT((p)->abandoned_heap || (P)->heap_sz == (P)->hend - (P)->heap); \
ASSERT((P)->heap <= (P)->htop && (P)->htop <= (P)->hend); \
ASSERT((P)->heap <= (P)->stop && (P)->stop <= (P)->hend); \
- ASSERT((P)->heap <= (P)->high_water && (P)->high_water <= (P)->hend);\
+ ASSERT((p)->abandoned_heap || ((P)->heap <= (P)->high_water && (P)->high_water <= (P)->hend)); \
OverRunCheck((P)); \
} while (0)
#else
@@ -98,18 +109,33 @@ typedef struct {
static Uint setup_rootset(Process*, Eterm*, int, Rootset*);
static void cleanup_rootset(Rootset *rootset);
-static Uint combined_message_size(Process* p);
static void remove_message_buffers(Process* p);
-static int major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl);
-static int minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl);
-static void do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj);
-static Eterm* sweep_rootset(Rootset *rootset, Eterm* htop, char* src, Uint src_size);
-static Eterm* sweep_one_area(Eterm* n_hp, Eterm* n_htop, char* src, Uint src_size);
-static Eterm* sweep_one_heap(Eterm* heap_ptr, Eterm* heap_end, Eterm* htop,
- char* src, Uint src_size);
-static Eterm* collect_heap_frags(Process* p, Eterm* heap,
- Eterm* htop, Eterm* objv, int nobj);
-static void adjust_after_fullsweep(Process *p, int need, Eterm *objv, int nobj);
+static Eterm *full_sweep_heaps(Process *p,
+ int hibernate,
+ Eterm *n_heap, Eterm* n_htop,
+ char *oh, Uint oh_size,
+ Eterm *objv, int nobj);
+static int garbage_collect(Process* p, ErlHeapFragment *live_hf_end,
+ int need, Eterm* objv, int nobj);
+static int major_collection(Process* p, ErlHeapFragment *live_hf_end,
+ int need, Eterm* objv, int nobj, Uint *recl);
+static int minor_collection(Process* p, ErlHeapFragment *live_hf_end,
+ int need, Eterm* objv, int nobj, Uint *recl);
+static void do_minor(Process *p, ErlHeapFragment *live_hf_end,
+ char *mature, Uint mature_size,
+ Uint new_sz, Eterm* objv, int nobj);
+static Eterm *sweep_new_heap(Eterm *n_hp, Eterm *n_htop,
+ char* old_heap, Uint old_heap_size);
+static Eterm *sweep_heaps(Eterm *n_hp, Eterm *n_htop,
+ char* old_heap, Uint old_heap_size);
+static Eterm* sweep_literal_area(Eterm* n_hp, Eterm* n_htop,
+ char* old_heap, Uint old_heap_size,
+ char* src, Uint src_size);
+static Eterm* sweep_literals_to_old_heap(Eterm* heap_ptr, Eterm* heap_end, Eterm* htop,
+ char* src, Uint src_size);
+static Eterm* collect_live_heap_frags(Process* p, ErlHeapFragment *live_hf_end,
+ Eterm* heap, Eterm* htop, Eterm* objv, int nobj);
+static int adjust_after_fullsweep(Process *p, int need, Eterm *objv, int nobj);
static void shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj);
static void grow_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj);
static void sweep_off_heap(Process *p, int fullsweep);
@@ -119,16 +145,16 @@ static void offset_rootset(Process *p, Sint offs, char* area, Uint area_size,
Eterm* objv, int nobj);
static void offset_off_heap(Process* p, Sint offs, char* area, Uint area_size);
static void offset_mqueue(Process *p, Sint offs, char* area, Uint area_size);
+static void move_msgq_to_heap(Process *p);
static void init_gc_info(ErtsGCInfo *gcip);
#ifdef HARDDEBUG
static void disallow_heap_frag_ref_in_heap(Process* p);
static void disallow_heap_frag_ref_in_old_heap(Process* p);
-static void disallow_heap_frag_ref(Process* p, Eterm* n_htop, Eterm* objv, int nobj);
#endif
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
# define MAX_HEAP_SIZES 154
#else
# define MAX_HEAP_SIZES 59
@@ -147,26 +173,24 @@ typedef struct {
erts_smp_atomic32_t refc;
} ErtsGCInfoReq;
-#if !HALFWORD_HEAP
-ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(gcireq,
- ErtsGCInfoReq,
- 5,
- ERTS_ALC_T_GC_INFO_REQ)
-#else
-static ERTS_INLINE ErtsGCInfoReq *
-gcireq_alloc(void)
+static ERTS_INLINE int
+gc_cost(Uint gc_moved_live_words, Uint resize_moved_words)
{
- return erts_alloc(ERTS_ALC_T_GC_INFO_REQ,
- sizeof(ErtsGCInfoReq));
-}
+ Sint reds;
-static ERTS_INLINE void
-gcireq_free(ErtsGCInfoReq *ptr)
-{
- erts_free(ERTS_ALC_T_GC_INFO_REQ, ptr);
+ reds = gc_moved_live_words/10;
+ reds += resize_moved_words/100;
+ if (reds < 1)
+ return 1;
+ if (reds > INT_MAX)
+ return INT_MAX;
+ return (int) reds;
}
-#endif
+ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(gcireq,
+ ErtsGCInfoReq,
+ 5,
+ ERTS_ALC_T_GC_INFO_REQ)
/*
* Initialize GC global data.
*/
@@ -208,7 +232,7 @@ erts_init_gc(void)
}
- /* for 32 bit we want max_heap_size to be MAX(32bit) / 4 [words] (and halfword)
+ /* for 32 bit we want max_heap_size to be MAX(32bit) / 4 [words]
* for 64 bit we want max_heap_size to be MAX(52bit) / 8 [words]
*/
@@ -232,10 +256,7 @@ erts_init_gc(void)
init_gc_info(&esdp->gc_info);
}
-#if !HALFWORD_HEAP
init_gcireq_alloc();
-#endif
-
}
/*
@@ -351,10 +372,19 @@ erts_offset_off_heap(ErlOffHeap *ohp, Sint offs, Eterm* low, Eterm* high)
#undef ptr_within
Eterm
-erts_gc_after_bif_call(Process* p, Eterm result, Eterm* regs, Uint arity)
+erts_gc_after_bif_call_lhf(Process* p, ErlHeapFragment *live_hf_end,
+ Eterm result, Eterm* regs, Uint arity)
{
int cost;
+ if (p->flags & F_HIBERNATE_SCHED) {
+ /*
+ * We just hibernated. We do *not* want to mess
+ * up the hibernation by an ordinary GC...
+ */
+ return result;
+ }
+
if (is_non_value(result)) {
if (p->freason == TRAP) {
#if HIPE
@@ -362,21 +392,28 @@ erts_gc_after_bif_call(Process* p, Eterm result, Eterm* regs, Uint arity)
regs = ERTS_PROC_GET_SCHDATA(p)->x_reg_array;
}
#endif
- cost = erts_garbage_collect(p, 0, regs, p->arity);
+ cost = garbage_collect(p, live_hf_end, 0, regs, p->arity);
} else {
- cost = erts_garbage_collect(p, 0, regs, arity);
+ cost = garbage_collect(p, live_hf_end, 0, regs, arity);
}
} else {
Eterm val[1];
val[0] = result;
- cost = erts_garbage_collect(p, 0, val, 1);
+ cost = garbage_collect(p, live_hf_end, 0, val, 1);
result = val[0];
}
BUMP_REDS(p, cost);
return result;
}
+Eterm
+erts_gc_after_bif_call(Process* p, Eterm result, Eterm* regs, Uint arity)
+{
+ return erts_gc_after_bif_call_lhf(p, ERTS_INVALID_HFRAG_PTR,
+ result, regs, arity);
+}
+
static ERTS_INLINE void reset_active_writer(Process *p)
{
struct erl_off_heap_header* ptr;
@@ -390,6 +427,139 @@ static ERTS_INLINE void reset_active_writer(Process *p)
}
}
+#define ERTS_DELAY_GC_EXTRA_FREE 40
+#define ERTS_ABANDON_HEAP_COST 10
+
+static int
+delay_garbage_collection(Process *p, ErlHeapFragment *live_hf_end, int need)
+{
+ ErlHeapFragment *hfrag;
+ Eterm *orig_heap, *orig_hend, *orig_htop, *orig_stop;
+ Eterm *stop, *hend;
+ Uint hsz, ssz;
+ int reds_left;
+
+ ERTS_HOLE_CHECK(p);
+
+ if ((p->flags & F_DISABLE_GC)
+ && p->live_hf_end == ERTS_INVALID_HFRAG_PTR) {
+ /*
+ * A BIF yielded with disabled GC. Remember
+ * heap fragments created by the BIF until we
+ * do next GC.
+ */
+ p->live_hf_end = live_hf_end;
+ }
+
+ if (need == 0)
+ return 1;
+
+ /*
+ * Satisfy need in a heap fragment...
+ */
+ ASSERT(need > 0);
+
+ orig_heap = p->heap;
+ orig_hend = p->hend;
+ orig_htop = p->htop;
+ orig_stop = p->stop;
+
+ ssz = orig_hend - orig_stop;
+ hsz = ssz + need + ERTS_DELAY_GC_EXTRA_FREE;
+
+ hfrag = new_message_buffer(hsz);
+ hfrag->next = p->mbuf;
+ p->mbuf = hfrag;
+ p->mbuf_sz += hsz;
+ p->heap = p->htop = &hfrag->mem[0];
+ p->hend = hend = &hfrag->mem[hsz];
+ p->stop = stop = hend - ssz;
+ sys_memcpy((void *) stop, (void *) orig_stop, ssz * sizeof(Eterm));
+
+ if (p->abandoned_heap) {
+ /* Active heap already in a fragment; adjust it... */
+ ErlHeapFragment *hfrag = ((ErlHeapFragment *)
+ (((char *) orig_heap)
+ - offsetof(ErlHeapFragment, mem)));
+ Uint unused = orig_hend - orig_htop;
+ ASSERT(hfrag->used_size == hfrag->alloc_size);
+ ASSERT(hfrag->used_size >= unused);
+ hfrag->used_size -= unused;
+ p->mbuf_sz -= unused;
+ }
+ else {
+ /* Do not leave a hole in the abandoned heap... */
+ if (orig_htop < orig_hend) {
+ *orig_htop = make_pos_bignum_header(orig_hend-orig_htop-1);
+ if (orig_htop + 1 < orig_hend) {
+ orig_hend[-1] = (Uint) (orig_htop - orig_heap);
+ p->flags |= F_ABANDONED_HEAP_USE;
+ }
+ }
+ p->abandoned_heap = orig_heap;
+ }
+
+#ifdef CHECK_FOR_HOLES
+ p->last_htop = p->htop;
+ p->heap_hfrag = hfrag;
+#endif
+
+ /* Make sure that we do a proper GC as soon as possible... */
+ p->flags |= F_FORCE_GC;
+ reds_left = ERTS_BIF_REDS_LEFT(p);
+ if (reds_left > ERTS_ABANDON_HEAP_COST) {
+ int vreds = reds_left - ERTS_ABANDON_HEAP_COST;
+ ERTS_VBUMP_REDS(p, vreds);
+ }
+ return ERTS_ABANDON_HEAP_COST;
+}
+
+static ERTS_FORCE_INLINE Uint
+young_gen_usage(Process *p)
+{
+ Uint hsz;
+ Eterm *aheap;
+
+ hsz = p->mbuf_sz;
+
+ if (p->flags & F_ON_HEAP_MSGQ) {
+ ErtsMessage *mp;
+ for (mp = p->msg.first; mp; mp = mp->next)
+ if (mp->data.attached)
+ hsz += erts_msg_attached_data_size(mp);
+ }
+
+ aheap = p->abandoned_heap;
+ if (!aheap)
+ hsz += p->htop - p->heap;
+ else {
+ /* used in orig heap */
+ if (p->flags & F_ABANDONED_HEAP_USE)
+ hsz += aheap[p->heap_sz-1];
+ else
+ hsz += p->heap_sz;
+ /* Remove unused part in latest fragment */
+ hsz -= p->hend - p->htop;
+ }
+ return hsz;
+}
+
+#define ERTS_GET_ORIG_HEAP(Proc, Heap, HTop) \
+ do { \
+ Eterm *aheap__ = (Proc)->abandoned_heap; \
+ if (!aheap__) { \
+ (Heap) = (Proc)->heap; \
+ (HTop) = (Proc)->htop; \
+ } \
+ else { \
+ (Heap) = aheap__; \
+ if ((Proc)->flags & F_ABANDONED_HEAP_USE) \
+ (HTop) = aheap__ + aheap__[(Proc)->heap_sz-1]; \
+ else \
+ (HTop) = aheap__ + (Proc)->heap_sz; \
+ } \
+ } while (0)
+
/*
* Garbage collect a process.
*
@@ -398,21 +568,28 @@ static ERTS_INLINE void reset_active_writer(Process *p)
* objv: Array of terms to add to rootset; that is to preserve.
* nobj: Number of objects in objv.
*/
-int
-erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
+static int
+garbage_collect(Process* p, ErlHeapFragment *live_hf_end,
+ int need, Eterm* objv, int nobj)
{
Uint reclaimed_now = 0;
- int done = 0;
+ int reds;
ErtsMonotonicTime start_time = 0; /* Shut up faulty warning... */
ErtsSchedulerData *esdp;
+ ERTS_MSACC_PUSH_STATE_M();
#ifdef USE_VM_PROBES
DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE);
#endif
- if (p->flags & F_DISABLE_GC) {
- ASSERT(need == 0);
- return 1;
- }
+ if (p->flags & (F_DISABLE_GC|F_DELAY_GC))
+ return delay_garbage_collection(p, live_hf_end, need);
+
+ if (p->abandoned_heap)
+ live_hf_end = ERTS_INVALID_HFRAG_PTR;
+ else if (p->live_hf_end != ERTS_INVALID_HFRAG_PTR)
+ live_hf_end = p->live_hf_end;
+
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_GC);
esdp = erts_get_scheduler_data();
@@ -420,16 +597,14 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
trace_gc(p, am_gc_start);
}
- (void) erts_smp_atomic32_read_bor_nob(&p->state, ERTS_PSFLG_GC);
+ erts_smp_atomic32_read_bor_nob(&p->state, ERTS_PSFLG_GC);
if (erts_system_monitor_long_gc != 0)
start_time = erts_get_monotonic_time(esdp);
ERTS_CHK_OFFHEAP(p);
ErtsGcQuickSanityCheck(p);
- if (GEN_GCS(p) >= MAX_GEN_GCS(p)) {
- FLAGS(p) |= F_NEED_FULLSWEEP;
- }
+
#ifdef USE_VM_PROBES
*pidbuf = '\0';
if (DTRACE_ENABLED(gc_major_start)
@@ -442,17 +617,23 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
/*
* Test which type of GC to do.
*/
- while (!done) {
- if ((FLAGS(p) & F_NEED_FULLSWEEP) != 0) {
- DTRACE2(gc_major_start, pidbuf, need);
- done = major_collection(p, need, objv, nobj, &reclaimed_now);
- DTRACE2(gc_major_end, pidbuf, reclaimed_now);
- } else {
- DTRACE2(gc_minor_start, pidbuf, need);
- done = minor_collection(p, need, objv, nobj, &reclaimed_now);
- DTRACE2(gc_minor_end, pidbuf, reclaimed_now);
- }
+
+ if (GEN_GCS(p) < MAX_GEN_GCS(p) && !(FLAGS(p) & F_NEED_FULLSWEEP)) {
+ DTRACE2(gc_minor_start, pidbuf, need);
+ reds = minor_collection(p, live_hf_end, need, objv, nobj, &reclaimed_now);
+ DTRACE2(gc_minor_end, pidbuf, reclaimed_now);
+ if (reds < 0)
+ goto do_major_collection;
+ }
+ else {
+ do_major_collection:
+ ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_GC_FULL);
+ DTRACE2(gc_major_start, pidbuf, need);
+ reds = major_collection(p, live_hf_end, need, objv, nobj, &reclaimed_now);
+ DTRACE2(gc_major_end, pidbuf, reclaimed_now);
+ ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_GC);
}
+
reset_active_writer(p);
/*
@@ -491,6 +672,9 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
esdp->gc_info.reclaimed += reclaimed_now;
FLAGS(p) &= ~F_FORCE_GC;
+ p->live_hf_end = ERTS_INVALID_HFRAG_PTR;
+
+ ERTS_MSACC_POP_STATE_M();
#ifdef CHECK_FOR_HOLES
/*
@@ -512,15 +696,20 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
p->last_old_htop = p->old_htop;
#endif
- /* FIXME: This function should really return an Sint, i.e., a possibly
- 64 bit wide signed integer, but that requires updating all the code
- that calls it. For now, we just return INT_MAX if the result is too
- large for an int. */
- {
- Sint result = (HEAP_TOP(p) - HEAP_START(p)) / 10;
- if (result >= INT_MAX) return INT_MAX;
- else return (int) result;
- }
+ return reds;
+}
+
+int
+erts_garbage_collect_nobump(Process* p, int need, Eterm* objv, int nobj)
+{
+ return garbage_collect(p, ERTS_INVALID_HFRAG_PTR, need, objv, nobj);
+}
+
+void
+erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
+{
+ int reds = garbage_collect(p, ERTS_INVALID_HFRAG_PTR, need, objv, nobj);
+ BUMP_REDS(p, reds);
}
/*
@@ -533,13 +722,11 @@ erts_garbage_collect_hibernate(Process* p)
Uint heap_size;
Eterm* heap;
Eterm* htop;
- Rootset rootset;
- char* src;
- Uint src_size;
Uint actual_size;
char* area;
Uint area_size;
Sint offs;
+ int reds;
if (p->flags & F_DISABLE_GC)
ERTS_INTERNAL_ERROR("GC disabled");
@@ -549,8 +736,6 @@ erts_garbage_collect_hibernate(Process* p)
*/
erts_smp_atomic32_read_bor_nob(&p->state, ERTS_PSFLG_GC);
ErtsGcQuickSanityCheck(p);
- ASSERT(p->mbuf_sz == 0);
- ASSERT(p->mbuf == 0);
ASSERT(p->stop == p->hend); /* Stack must be empty. */
/*
@@ -558,46 +743,25 @@ erts_garbage_collect_hibernate(Process* p)
*/
- heap_size = p->heap_sz + (p->old_htop - p->old_heap);
+ heap_size = p->heap_sz + (p->old_htop - p->old_heap) + p->mbuf_sz;
heap = (Eterm*) ERTS_HEAP_ALLOC(ERTS_ALC_T_TMP_HEAP,
sizeof(Eterm)*heap_size);
htop = heap;
- (void) setup_rootset(p, p->arg_reg, p->arity, &rootset);
-#if HIPE
- hipe_empty_nstack(p);
-#endif
-
- src = (char *) p->heap;
- src_size = (char *) p->htop - src;
- htop = sweep_rootset(&rootset, htop, src, src_size);
- htop = sweep_one_area(heap, htop, src, src_size);
+ htop = full_sweep_heaps(p,
+ 1,
+ heap,
+ htop,
+ (char *) p->old_heap,
+ (char *) p->old_htop - (char *) p->old_heap,
+ p->arg_reg,
+ p->arity);
- if (p->old_heap) {
- src = (char *) p->old_heap;
- src_size = (char *) p->old_htop - src;
- htop = sweep_rootset(&rootset, htop, src, src_size);
- htop = sweep_one_area(heap, htop, src, src_size);
- }
-
- cleanup_rootset(&rootset);
-
- if (MSO(p).first) {
- sweep_off_heap(p, 1);
- }
-
- /*
- * Update all pointers.
- */
ERTS_HEAP_FREE(ERTS_ALC_T_HEAP,
- (void*)HEAP_START(p),
- HEAP_SIZE(p) * sizeof(Eterm));
- if (p->old_heap) {
- ERTS_HEAP_FREE(ERTS_ALC_T_OLD_HEAP,
- (void*)p->old_heap,
- (p->old_hend - p->old_heap) * sizeof(Eterm));
- p->old_heap = p->old_htop = p->old_hend = 0;
- }
+ (p->abandoned_heap
+ ? p->abandoned_heap
+ : p->heap),
+ p->heap_sz * sizeof(Eterm));
p->heap = heap;
p->high_water = htop;
@@ -612,6 +776,7 @@ erts_garbage_collect_hibernate(Process* p)
}
FLAGS(p) &= ~F_FORCE_GC;
+ p->live_hf_end = ERTS_INVALID_HFRAG_PTR;
/*
* Move the heap to its final destination.
@@ -631,6 +796,8 @@ erts_garbage_collect_hibernate(Process* p)
sys_memcpy((void *) heap, (void *) p->heap, actual_size*sizeof(Eterm));
ERTS_HEAP_FREE(ERTS_ALC_T_TMP_HEAP, p->heap, p->heap_sz*sizeof(Eterm));
+ remove_message_buffers(p);
+
p->stop = p->hend = heap + heap_size;
offs = heap - p->heap;
@@ -659,15 +826,18 @@ erts_garbage_collect_hibernate(Process* p)
ErtsGcQuickSanityCheck(p);
erts_smp_atomic32_read_band_nob(&p->state, ~ERTS_PSFLG_GC);
+
+ reds = gc_cost(actual_size, actual_size);
+ BUMP_REDS(p, reds);
}
void
erts_garbage_collect_literals(Process* p, Eterm* literals,
- Uint lit_size,
+ Uint byte_lit_size,
struct erl_off_heap_header* oh)
{
- Uint byte_lit_size = sizeof(Eterm)*lit_size;
+ Uint lit_size = byte_lit_size / sizeof(Eterm);
Uint old_heap_size;
Eterm* temp_lit;
Sint offs;
@@ -743,7 +913,7 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*g_ptr++ = val;
- } else if (in_area(ptr, area, area_size)) {
+ } else if (ErtsInArea(ptr, area, area_size)) {
MOVE_BOXED(ptr,val,old_htop,g_ptr++);
} else {
g_ptr++;
@@ -754,7 +924,7 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
val = *ptr;
if (IS_MOVED_CONS(val)) { /* Moved */
*g_ptr++ = ptr[1];
- } else if (in_area(ptr, area, area_size)) {
+ } else if (ErtsInArea(ptr, area, area_size)) {
MOVE_CONS(ptr,val,old_htop,g_ptr++);
} else {
g_ptr++;
@@ -774,8 +944,10 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
* Now we'll have to go through all heaps updating all other references.
*/
- old_htop = sweep_one_heap(p->heap, p->htop, old_htop, area, area_size);
- old_htop = sweep_one_area(p->old_heap, old_htop, area, area_size);
+ old_htop = sweep_literals_to_old_heap(p->heap, p->htop, old_htop, area, area_size);
+ old_htop = sweep_literal_area(p->old_heap, old_htop,
+ (char *) p->old_heap, sizeof(Eterm)*old_heap_size,
+ area, area_size);
ASSERT(p->old_htop <= old_htop && old_htop <= p->old_hend);
p->old_htop = old_htop;
@@ -834,15 +1006,18 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
}
static int
-minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
+minor_collection(Process* p, ErlHeapFragment *live_hf_end,
+ int need, Eterm* objv, int nobj, Uint *recl)
{
- Uint mature = HIGH_WATER(p) - HEAP_START(p);
+ Eterm *mature = p->abandoned_heap ? p->abandoned_heap : p->heap;
+ Uint mature_size = p->high_water - mature;
+ Uint size_before = young_gen_usage(p);
/*
* Allocate an old heap if we don't have one and if we'll need one.
*/
- if (OLD_HEAP(p) == NULL && mature != 0) {
+ if (OLD_HEAP(p) == NULL && mature_size != 0) {
Eterm* n_old;
/* Note: We choose a larger heap size than strictly needed,
@@ -850,7 +1025,7 @@ minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
* This improved Estone by more than 1200 estones on my computer
* (Ultra Sparc 10).
*/
- Uint new_sz = erts_next_heap_size(HEAP_TOP(p) - HEAP_START(p), 1);
+ Uint new_sz = erts_next_heap_size(size_before, 1);
/* Create new, empty old_heap */
n_old = (Eterm *) ERTS_HEAP_ALLOC(ERTS_ALC_T_OLD_HEAP,
@@ -866,41 +1041,32 @@ minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
*/
if (OLD_HEAP(p) &&
- ((mature <= OLD_HEND(p) - OLD_HTOP(p)) &&
- ((BIN_VHEAP_MATURE(p) < ( BIN_OLD_VHEAP_SZ(p) - BIN_OLD_VHEAP(p)))) &&
- ((BIN_OLD_VHEAP_SZ(p) > BIN_OLD_VHEAP(p))) ) ) {
- ErlMessage *msgp;
- Uint size_after;
- Uint need_after;
- const Uint stack_size = STACK_SZ_ON_HEAP(p);
- const Uint size_before = MBUF_SIZE(p) + (HEAP_TOP(p) - HEAP_START(p));
- Uint new_sz = HEAP_SIZE(p) + MBUF_SIZE(p) + combined_message_size(p);
+ ((mature_size <= OLD_HEND(p) - OLD_HTOP(p)) &&
+ ((BIN_OLD_VHEAP_SZ(p) > BIN_OLD_VHEAP(p))) ) ) {
+ Eterm *prev_old_htop;
+ Uint stack_size, size_after, adjust_size, need_after, new_sz, new_mature;
+
+ stack_size = p->hend - p->stop;
+ new_sz = stack_size + size_before;
new_sz = next_heap_size(p, new_sz, 0);
- do_minor(p, new_sz, objv, nobj);
+ prev_old_htop = p->old_htop;
+ do_minor(p, live_hf_end, (char *) mature, mature_size*sizeof(Eterm),
+ new_sz, objv, nobj);
+
+ if (p->flags & F_ON_HEAP_MSGQ)
+ move_msgq_to_heap(p);
- size_after = HEAP_TOP(p) - HEAP_START(p);
+ new_mature = p->old_htop - prev_old_htop;
+
+ size_after = new_mature;
+ size_after += HEAP_TOP(p) - HEAP_START(p) + p->mbuf_sz;
*recl += (size_before - size_after);
- /*
- * Copy newly received message onto the end of the new heap.
- */
- ErtsGcQuickSanityCheck(p);
- for (msgp = p->msg.first; msgp; msgp = msgp->next) {
- if (msgp->data.attached) {
- ErtsHeapFactory factory;
- erts_factory_proc_prealloc_init(&factory, p,
- erts_msg_attached_data_size(msgp));
- erts_move_msg_attached_data_to_heap(&factory, msgp);
- erts_factory_close(&factory);
- ErtsGcQuickSanityCheck(p);
- }
- }
ErtsGcQuickSanityCheck(p);
GEN_GCS(p)++;
need_after = ((HEAP_TOP(p) - HEAP_START(p))
- + erts_used_frag_sz(MBUF(p))
+ need
+ stack_size);
@@ -913,6 +1079,8 @@ minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
* the heap size is substantial, we don't want to shrink.
*/
+ adjust_size = 0;
+
if ((HEAP_SIZE(p) > 3000) && (4 * need_after < HEAP_SIZE(p)) &&
((HEAP_SIZE(p) > 8000) ||
(HEAP_SIZE(p) > (OLD_HEND(p) - OLD_HEAP(p))))) {
@@ -934,28 +1102,33 @@ minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
: next_heap_size(p, wanted, 0);
if (wanted < HEAP_SIZE(p)) {
shrink_new_heap(p, wanted, objv, nobj);
+ adjust_size = p->htop - p->heap;
}
- ASSERT(HEAP_SIZE(p) == next_heap_size(p, HEAP_SIZE(p), 0));
- ASSERT(MBUF(p) == NULL);
- return 1; /* We are done. */
+ goto done;
}
if (HEAP_SIZE(p) >= need_after) {
/*
* The heap size turned out to be just right. We are done.
*/
- ASSERT(HEAP_SIZE(p) == next_heap_size(p, HEAP_SIZE(p), 0));
- ASSERT(MBUF(p) == NULL);
- return 1;
+ goto done;
}
+
+ grow_new_heap(p, next_heap_size(p, need_after, 0), objv, nobj);
+ adjust_size = p->htop - p->heap;
+
+ done:
+ ASSERT(HEAP_SIZE(p) == next_heap_size(p, HEAP_SIZE(p), 0));
+ ASSERT(MBUF(p) == NULL);
+
+ return gc_cost(size_after, adjust_size);
}
/*
- * Still not enough room after minor collection. Must force a major collection.
+ * Not enough room for a minor collection. Must force a major collection.
*/
- FLAGS(p) |= F_NEED_FULLSWEEP;
- return 0;
+ return -1;
}
/*
@@ -1009,7 +1182,9 @@ static ERTS_INLINE void offset_nstack(Process* p, Sint offs,
#endif /* HIPE */
static void
-do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
+do_minor(Process *p, ErlHeapFragment *live_hf_end,
+ char *mature, Uint mature_size,
+ Uint new_sz, Eterm* objv, int nobj)
{
Rootset rootset; /* Rootset for GC (stack, dictionary, etc). */
Roots* roots;
@@ -1018,17 +1193,24 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
Eterm* ptr;
Eterm val;
Eterm gval;
- char* heap = (char *) HEAP_START(p);
- Uint heap_size = (char *) HEAP_TOP(p) - heap;
- Uint mature_size = (char *) HIGH_WATER(p) - heap;
Eterm* old_htop = OLD_HTOP(p);
Eterm* n_heap;
+ char* oh = (char *) OLD_HEAP(p);
+ Uint oh_size = (char *) OLD_HTOP(p) - oh;
+
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] MINOR GC: %p %p %p %p\n", p->common.id,
+ HEAP_START(p), HEAP_END(p), OLD_HEAP(p), OLD_HEND(p)));
n_htop = n_heap = (Eterm*) ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP,
sizeof(Eterm)*new_sz);
- if (MBUF(p) != NULL) {
- n_htop = collect_heap_frags(p, n_heap, n_htop, objv, nobj);
+ if (live_hf_end != ERTS_INVALID_HFRAG_PTR) {
+ /*
+ * Move heap frags that we know are completely live
+ * directly into the new young heap generation.
+ */
+ n_htop = collect_live_heap_frags(p, live_hf_end, n_heap, n_htop,
+ objv, nobj);
}
n = setup_rootset(p, objv, nobj, &rootset);
@@ -1051,9 +1233,9 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*g_ptr++ = val;
- } else if (in_area(ptr, heap, mature_size)) {
+ } else if (ErtsInArea(ptr, mature, mature_size)) {
MOVE_BOXED(ptr,val,old_htop,g_ptr++);
- } else if (in_area(ptr, heap, heap_size)) {
+ } else if (ErtsInYoungGen(gval, ptr, oh, oh_size)) {
MOVE_BOXED(ptr,val,n_htop,g_ptr++);
} else {
g_ptr++;
@@ -1066,9 +1248,9 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
val = *ptr;
if (IS_MOVED_CONS(val)) { /* Moved */
*g_ptr++ = ptr[1];
- } else if (in_area(ptr, heap, mature_size)) {
+ } else if (ErtsInArea(ptr, mature, mature_size)) {
MOVE_CONS(ptr,val,old_htop,g_ptr++);
- } else if (in_area(ptr, heap, heap_size)) {
+ } else if (ErtsInYoungGen(gval, ptr, oh, oh_size)) {
MOVE_CONS(ptr,val,n_htop,g_ptr++);
} else {
g_ptr++;
@@ -1093,7 +1275,7 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
*/
if (mature_size == 0) {
- n_htop = sweep_one_area(n_heap, n_htop, heap, heap_size);
+ n_htop = sweep_new_heap(n_heap, n_htop, oh, oh_size);
} else {
Eterm* n_hp = n_heap;
Eterm* ptr;
@@ -1110,9 +1292,9 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*n_hp++ = val;
- } else if (in_area(ptr, heap, mature_size)) {
+ } else if (ErtsInArea(ptr, mature, mature_size)) {
MOVE_BOXED(ptr,val,old_htop,n_hp++);
- } else if (in_area(ptr, heap, heap_size)) {
+ } else if (ErtsInYoungGen(gval, ptr, oh, oh_size)) {
MOVE_BOXED(ptr,val,n_htop,n_hp++);
} else {
n_hp++;
@@ -1124,9 +1306,9 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
val = *ptr;
if (IS_MOVED_CONS(val)) {
*n_hp++ = ptr[1];
- } else if (in_area(ptr, heap, mature_size)) {
+ } else if (ErtsInArea(ptr, mature, mature_size)) {
MOVE_CONS(ptr,val,old_htop,n_hp++);
- } else if (in_area(ptr, heap, heap_size)) {
+ } else if (ErtsInYoungGen(gval, ptr, oh, oh_size)) {
MOVE_CONS(ptr,val,n_htop,n_hp++);
} else {
n_hp++;
@@ -1146,10 +1328,10 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
if (IS_MOVED_BOXED(val)) {
*origptr = val;
mb->base = binary_bytes(val);
- } else if (in_area(ptr, heap, mature_size)) {
+ } else if (ErtsInArea(ptr, mature, mature_size)) {
MOVE_BOXED(ptr,val,old_htop,origptr);
mb->base = binary_bytes(mb->orig);
- } else if (in_area(ptr, heap, heap_size)) {
+ } else if (ErtsInYoungGen(*origptr, ptr, oh, oh_size)) {
MOVE_BOXED(ptr,val,n_htop,origptr);
mb->base = binary_bytes(mb->orig);
}
@@ -1170,9 +1352,8 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
* may point to the old (soon to be deleted) new_heap.
*/
- if (OLD_HTOP(p) < old_htop) {
- old_htop = sweep_one_area(OLD_HTOP(p), old_htop, heap, heap_size);
- }
+ if (OLD_HTOP(p) < old_htop)
+ old_htop = sweep_new_heap(OLD_HTOP(p), old_htop, oh, oh_size);
OLD_HTOP(p) = old_htop;
HIGH_WATER(p) = n_htop;
@@ -1204,8 +1385,12 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
#endif
ERTS_HEAP_FREE(ERTS_ALC_T_HEAP,
- (void*)HEAP_START(p),
+ (p->abandoned_heap
+ ? p->abandoned_heap
+ : HEAP_START(p)),
HEAP_SIZE(p) * sizeof(Eterm));
+ p->abandoned_heap = NULL;
+ p->flags &= ~F_ABANDONED_HEAP_USE;
HEAP_START(p) = n_heap;
HEAP_TOP(p) = n_htop;
HEAP_SIZE(p) = new_sz;
@@ -1222,31 +1407,30 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
*/
static int
-major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
+major_collection(Process* p, ErlHeapFragment *live_hf_end,
+ int need, Eterm* objv, int nobj, Uint *recl)
{
- Rootset rootset;
- Roots* roots;
- const Uint size_before = ((HEAP_TOP(p) - HEAP_START(p))
- + (OLD_HTOP(p) - OLD_HEAP(p))
- + MBUF_SIZE(p));
+ Uint size_before, size_after, stack_size;
Eterm* n_heap;
Eterm* n_htop;
- char* src = (char *) HEAP_START(p);
- Uint src_size = (char *) HEAP_TOP(p) - src;
char* oh = (char *) OLD_HEAP(p);
Uint oh_size = (char *) OLD_HTOP(p) - oh;
- Uint n;
- Uint new_sz;
- int done;
+ Uint new_sz, stk_sz;
+ int adjusted;
+
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] MAJOR GC: %p %p %p %p\n", p->common.id,
+ HEAP_START(p), HEAP_END(p), OLD_HEAP(p), OLD_HEND(p)));
/*
* Do a fullsweep GC. First figure out the size of the heap
* to receive all live data.
*/
- new_sz = (HEAP_SIZE(p) + MBUF_SIZE(p)
- + combined_message_size(p)
- + (OLD_HTOP(p) - OLD_HEAP(p)));
+ size_before = young_gen_usage(p);
+ size_before += p->old_htop - p->old_heap;
+ stack_size = p->hend - p->stop;
+
+ new_sz = stack_size + size_before;
new_sz = next_heap_size(p, new_sz, 0);
/*
@@ -1260,13 +1444,76 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
n_htop = n_heap = (Eterm *) ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP,
sizeof(Eterm)*new_sz);
- /*
- * Get rid of heap fragments.
- */
+ if (live_hf_end != ERTS_INVALID_HFRAG_PTR) {
+ /*
+ * Move heap frags that we know are completely live
+ * directly into the heap.
+ */
+ n_htop = collect_live_heap_frags(p, live_hf_end, n_heap, n_htop,
+ objv, nobj);
+ }
- if (MBUF(p) != NULL) {
- n_htop = collect_heap_frags(p, n_heap, n_htop, objv, nobj);
+ n_htop = full_sweep_heaps(p, 0, n_heap, n_htop, oh, oh_size, objv, nobj);
+
+ /* Move the stack to the end of the heap */
+ stk_sz = HEAP_END(p) - p->stop;
+ sys_memcpy(n_heap + new_sz - stk_sz, p->stop, stk_sz * sizeof(Eterm));
+ p->stop = n_heap + new_sz - stk_sz;
+
+#ifdef USE_VM_PROBES
+ if (HEAP_SIZE(p) != new_sz && DTRACE_ENABLED(process_heap_grow)) {
+ DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_proc_str(p, pidbuf);
+ DTRACE3(process_heap_grow, pidbuf, HEAP_SIZE(p), new_sz);
}
+#endif
+
+ ERTS_HEAP_FREE(ERTS_ALC_T_HEAP,
+ (p->abandoned_heap
+ ? p->abandoned_heap
+ : HEAP_START(p)),
+ p->heap_sz * sizeof(Eterm));
+ p->abandoned_heap = NULL;
+ p->flags &= ~F_ABANDONED_HEAP_USE;
+ HEAP_START(p) = n_heap;
+ HEAP_TOP(p) = n_htop;
+ HEAP_SIZE(p) = new_sz;
+ HEAP_END(p) = n_heap + new_sz;
+ GEN_GCS(p) = 0;
+
+ HIGH_WATER(p) = HEAP_TOP(p);
+
+ remove_message_buffers(p);
+
+ if (p->flags & F_ON_HEAP_MSGQ)
+ move_msgq_to_heap(p);
+
+ ErtsGcQuickSanityCheck(p);
+
+ size_after = HEAP_TOP(p) - HEAP_START(p) + p->mbuf_sz;
+ *recl += size_before - size_after;
+
+ adjusted = adjust_after_fullsweep(p, need, objv, nobj);
+
+#ifdef HARDDEBUG
+ disallow_heap_frag_ref_in_heap(p);
+#endif
+ ErtsGcQuickSanityCheck(p);
+
+ return gc_cost(size_after, adjusted ? size_after : 0);
+}
+
+static Eterm *
+full_sweep_heaps(Process *p,
+ int hibernate,
+ Eterm *n_heap, Eterm* n_htop,
+ char *oh, Uint oh_size,
+ Eterm *objv, int nobj)
+{
+ Rootset rootset;
+ Roots *roots;
+ Uint n;
/*
* Copy all top-level terms directly referenced by the rootset to
@@ -1274,7 +1521,14 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
*/
n = setup_rootset(p, objv, nobj, &rootset);
- n_htop = fullsweep_nstack(p, n_htop);
+
+#ifdef HIPE
+ if (hibernate)
+ hipe_empty_nstack(p);
+ else
+ n_htop = fullsweep_nstack(p, n_htop);
+#endif
+
roots = rootset.roots;
while (n--) {
Eterm* g_ptr = roots->v;
@@ -1294,7 +1548,7 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*g_ptr++ = val;
- } else if (in_area(ptr, src, src_size) || in_area(ptr, oh, oh_size)) {
+ } else if (!erts_is_literal(gval, ptr)) {
MOVE_BOXED(ptr,val,n_htop,g_ptr++);
} else {
g_ptr++;
@@ -1307,7 +1561,7 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
val = *ptr;
if (IS_MOVED_CONS(val)) {
*g_ptr++ = ptr[1];
- } else if (in_area(ptr, src, src_size) || in_area(ptr, oh, oh_size)) {
+ } else if (!erts_is_literal(gval, ptr)) {
MOVE_CONS(ptr,val,n_htop,g_ptr++);
} else {
g_ptr++;
@@ -1332,74 +1586,7 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
* until all is copied.
*/
- if (oh_size == 0) {
- n_htop = sweep_one_area(n_heap, n_htop, src, src_size);
- } else {
- Eterm* n_hp = n_heap;
-
- while (n_hp != n_htop) {
- Eterm* ptr;
- Eterm val;
- Eterm gval = *n_hp;
-
- switch (primary_tag(gval)) {
- case TAG_PRIMARY_BOXED: {
- ptr = boxed_val(gval);
- val = *ptr;
- if (IS_MOVED_BOXED(val)) {
- ASSERT(is_boxed(val));
- *n_hp++ = val;
- } else if (in_area(ptr, src, src_size) || in_area(ptr, oh, oh_size)) {
- MOVE_BOXED(ptr,val,n_htop,n_hp++);
- } else {
- n_hp++;
- }
- break;
- }
- case TAG_PRIMARY_LIST: {
- ptr = list_val(gval);
- val = *ptr;
- if (IS_MOVED_CONS(val)) {
- *n_hp++ = ptr[1];
- } else if (in_area(ptr, src, src_size) || in_area(ptr, oh, oh_size)) {
- MOVE_CONS(ptr,val,n_htop,n_hp++);
- } else {
- n_hp++;
- }
- break;
- }
- case TAG_PRIMARY_HEADER: {
- if (!header_is_thing(gval))
- n_hp++;
- else {
- if (header_is_bin_matchstate(gval)) {
- ErlBinMatchState *ms = (ErlBinMatchState*) n_hp;
- ErlBinMatchBuffer *mb = &(ms->mb);
- Eterm* origptr;
- origptr = &(mb->orig);
- ptr = boxed_val(*origptr);
- val = *ptr;
- if (IS_MOVED_BOXED(val)) {
- *origptr = val;
- mb->base = binary_bytes(*origptr);
- } else if (in_area(ptr, src, src_size) ||
- in_area(ptr, oh, oh_size)) {
- MOVE_BOXED(ptr,val,n_htop,origptr);
- mb->base = binary_bytes(*origptr);
- ptr = boxed_val(*origptr);
- val = *ptr;
- }
- }
- n_hp += (thing_arityval(gval)+1);
- }
- break;
- }
- default:
- n_hp++;
- break;
- }
- }
- }
+ n_htop = sweep_heaps(n_heap, n_htop, oh, oh_size);
if (MSO(p).first) {
sweep_off_heap(p, 1);
@@ -1412,75 +1599,13 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
OLD_HEAP(p) = OLD_HTOP(p) = OLD_HEND(p) = NULL;
}
- /* Move the stack to the end of the heap */
- n = HEAP_END(p) - p->stop;
- sys_memcpy(n_heap + new_sz - n, p->stop, n * sizeof(Eterm));
- p->stop = n_heap + new_sz - n;
-
-#ifdef USE_VM_PROBES
- if (HEAP_SIZE(p) != new_sz && DTRACE_ENABLED(process_heap_grow)) {
- DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE);
-
- dtrace_proc_str(p, pidbuf);
- DTRACE3(process_heap_grow, pidbuf, HEAP_SIZE(p), new_sz);
- }
-#endif
-
- ERTS_HEAP_FREE(ERTS_ALC_T_HEAP,
- (void *) HEAP_START(p),
- (HEAP_END(p) - HEAP_START(p)) * sizeof(Eterm));
- HEAP_START(p) = n_heap;
- HEAP_TOP(p) = n_htop;
- HEAP_SIZE(p) = new_sz;
- HEAP_END(p) = n_heap + new_sz;
- GEN_GCS(p) = 0;
-
- HIGH_WATER(p) = HEAP_TOP(p);
-
- ErtsGcQuickSanityCheck(p);
-
- *recl += size_before - (HEAP_TOP(p) - HEAP_START(p));
-
- remove_message_buffers(p);
-
- {
- ErlMessage *msgp;
-
- /*
- * Copy newly received message onto the end of the new heap.
- */
- for (msgp = p->msg.first; msgp; msgp = msgp->next) {
- if (msgp->data.attached) {
- ErtsHeapFactory factory;
- erts_factory_proc_prealloc_init(&factory, p,
- erts_msg_attached_data_size(msgp));
- erts_move_msg_attached_data_to_heap(&factory, msgp);
- erts_factory_close(&factory);
- ErtsGcQuickSanityCheck(p);
- }
- }
- }
-
- if (MBUF(p)) {
- /* This is a very rare case when distributed messages copied above
- * contained maps so big they did not fit on the heap causing the
- * factory to create heap frags.
- * Solution: Trigger a minor gc (without tenuring)
- */
- HIGH_WATER(p) = HEAP_START(p);
- done = 0;
- } else {
- adjust_after_fullsweep(p, need, objv, nobj);
- done = 1;
- }
-
- ErtsGcQuickSanityCheck(p);
- return done;
+ return n_htop;
}
-static void
+static int
adjust_after_fullsweep(Process *p, int need, Eterm *objv, int nobj)
{
+ int adjusted = 0;
Uint wanted, sz, need_after;
Uint stack_size = STACK_SZ_ON_HEAP(p);
@@ -1493,6 +1618,7 @@ adjust_after_fullsweep(Process *p, int need, Eterm *objv, int nobj)
/* Too small - grow to match requested need */
sz = next_heap_size(p, need_after, 0);
grow_new_heap(p, sz, objv, nobj);
+ adjusted = 1;
} else if (3 * HEAP_SIZE(p) < 4 * need_after){
/* Need more than 75% of current, postpone to next GC.*/
FLAGS(p) |= F_HEAP_GROW;
@@ -1509,25 +1635,10 @@ adjust_after_fullsweep(Process *p, int need, Eterm *objv, int nobj)
if (sz < HEAP_SIZE(p)) {
shrink_new_heap(p, sz, objv, nobj);
+ adjusted = 1;
}
}
-}
-
-/*
- * Return the size of all message buffers that are NOT linked in the
- * mbuf list.
- */
-static Uint
-combined_message_size(Process* p)
-{
- Uint sz;
- ErlMessage *msgp;
-
- for (sz = 0, msgp = p->msg.first; msgp; msgp = msgp->next) {
- if (msgp->data.attached)
- sz += erts_msg_attached_data_size(msgp);
- }
- return sz;
+ return adjusted;
}
/*
@@ -1540,6 +1651,10 @@ remove_message_buffers(Process* p)
free_message_buffer(MBUF(p));
MBUF(p) = NULL;
}
+ if (p->msg_frag) {
+ erts_cleanup_messages(p->msg_frag);
+ p->msg_frag = NULL;
+ }
MBUF_SIZE(p) = 0;
}
#ifdef HARDDEBUG
@@ -1551,64 +1666,6 @@ remove_message_buffers(Process* p)
* For performance reasons, we use _unchecked_list_val(), _unchecked_boxed_val(),
* and so on to avoid a function call.
*/
-
-static void
-disallow_heap_frag_ref(Process* p, Eterm* n_htop, Eterm* objv, int nobj)
-{
- ErlHeapFragment* mbuf;
- ErlHeapFragment* qb;
- Eterm gval;
- Eterm* ptr;
- Eterm val;
-
- ASSERT(p->htop != NULL);
- mbuf = MBUF(p);
-
- while (nobj--) {
- gval = *objv;
-
- switch (primary_tag(gval)) {
-
- case TAG_PRIMARY_BOXED: {
- ptr = _unchecked_boxed_val(gval);
- val = *ptr;
- if (IS_MOVED_BOXED(val)) {
- ASSERT(is_boxed(val));
- objv++;
- } else {
- for (qb = mbuf; qb != NULL; qb = qb->next) {
- if (in_area(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
- abort();
- }
- }
- objv++;
- }
- break;
- }
-
- case TAG_PRIMARY_LIST: {
- ptr = _unchecked_list_val(gval);
- val = *ptr;
- if (IS_MOVED_CONS(val)) {
- objv++;
- } else {
- for (qb = mbuf; qb != NULL; qb = qb->next) {
- if (in_area(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
- abort();
- }
- }
- objv++;
- }
- break;
- }
-
- default: {
- objv++;
- break;
- }
- }
- }
-}
static void
disallow_heap_frag_ref_in_heap(Process* p)
@@ -1636,9 +1693,9 @@ disallow_heap_frag_ref_in_heap(Process* p)
switch (primary_tag(val)) {
case TAG_PRIMARY_BOXED:
ptr = _unchecked_boxed_val(val);
- if (!in_area(ptr, heap, heap_size)) {
+ if (!ErtsInArea(ptr, heap, heap_size)) {
for (qb = MBUF(p); qb != NULL; qb = qb->next) {
- if (in_area(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
+ if (ErtsInArea(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
abort();
}
}
@@ -1646,9 +1703,9 @@ disallow_heap_frag_ref_in_heap(Process* p)
break;
case TAG_PRIMARY_LIST:
ptr = _unchecked_list_val(val);
- if (!in_area(ptr, heap, heap_size)) {
+ if (!ErtsInArea(ptr, heap, heap_size)) {
for (qb = MBUF(p); qb != NULL; qb = qb->next) {
- if (in_area(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
+ if (ErtsInArea(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
abort();
}
}
@@ -1690,26 +1747,26 @@ disallow_heap_frag_ref_in_old_heap(Process* p)
val = *hp++;
switch (primary_tag(val)) {
case TAG_PRIMARY_BOXED:
- ptr = (Eterm *) EXPAND_POINTER(val);
- if (!in_area(ptr, old_heap, old_heap_size)) {
- if (in_area(ptr, new_heap, new_heap_size)) {
+ ptr = (Eterm *) val;
+ if (!ErtsInArea(ptr, old_heap, old_heap_size)) {
+ if (ErtsInArea(ptr, new_heap, new_heap_size)) {
abort();
}
for (qb = MBUF(p); qb != NULL; qb = qb->next) {
- if (in_area(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
+ if (ErtsInArea(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
abort();
}
}
}
break;
case TAG_PRIMARY_LIST:
- ptr = (Eterm *) EXPAND_POINTER(val);
- if (!in_area(ptr, old_heap, old_heap_size)) {
- if (in_area(ptr, new_heap, new_heap_size)) {
+ ptr = (Eterm *) val;
+ if (!ErtsInArea(ptr, old_heap, old_heap_size)) {
+ if (ErtsInArea(ptr, new_heap, new_heap_size)) {
abort();
}
for (qb = MBUF(p); qb != NULL; qb = qb->next) {
- if (in_area(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
+ if (ErtsInArea(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
abort();
}
}
@@ -1718,7 +1775,7 @@ disallow_heap_frag_ref_in_old_heap(Process* p)
case TAG_PRIMARY_HEADER:
if (header_is_thing(val)) {
hp += _unchecked_thing_arityval(val);
- if (!in_area(hp, old_heap, old_heap_size+1)) {
+ if (!ErtsInArea(hp, old_heap, old_heap_size+1)) {
abort();
}
}
@@ -1728,66 +1785,30 @@ disallow_heap_frag_ref_in_old_heap(Process* p)
}
#endif
-static Eterm*
-sweep_rootset(Rootset* rootset, Eterm* htop, char* src, Uint src_size)
+typedef enum {
+ ErtsSweepNewHeap,
+ ErtsSweepHeaps,
+ ErtsSweepLiteralArea
+} ErtsSweepType;
+
+static ERTS_FORCE_INLINE Eterm *
+sweep(Eterm *n_hp, Eterm *n_htop,
+ ErtsSweepType type,
+ char *oh, Uint ohsz,
+ char *src, Uint src_size)
{
- Roots* roots = rootset->roots;
- Uint n = rootset->num_roots;
Eterm* ptr;
- Eterm gval;
Eterm val;
+ Eterm gval;
- while (n--) {
- Eterm* g_ptr = roots->v;
- Uint g_sz = roots->sz;
-
- roots++;
- while (g_sz--) {
- gval = *g_ptr;
-
- switch (primary_tag(gval)) {
- case TAG_PRIMARY_BOXED: {
- ptr = boxed_val(gval);
- val = *ptr;
- if (IS_MOVED_BOXED(val)) {
- ASSERT(is_boxed(val));
- *g_ptr++ = val;
- } else if (in_area(ptr, src, src_size)) {
- MOVE_BOXED(ptr,val,htop,g_ptr++);
- } else {
- g_ptr++;
- }
- break;
- }
- case TAG_PRIMARY_LIST: {
- ptr = list_val(gval);
- val = *ptr;
- if (IS_MOVED_CONS(val)) {
- *g_ptr++ = ptr[1];
- } else if (in_area(ptr, src, src_size)) {
- MOVE_CONS(ptr,val,htop,g_ptr++);
- } else {
- g_ptr++;
- }
- break;
- }
-
- default:
- g_ptr++;
- break;
- }
- }
- }
- return htop;
-}
+#undef ERTS_IS_IN_SWEEP_AREA
-
-static Eterm*
-sweep_one_area(Eterm* n_hp, Eterm* n_htop, char* src, Uint src_size)
-{
- Eterm* ptr;
- Eterm val;
- Eterm gval;
+#define ERTS_IS_IN_SWEEP_AREA(TPtr, Ptr) \
+ (type == ErtsSweepHeaps \
+ ? !erts_is_literal((TPtr), (Ptr)) \
+ : (type == ErtsSweepNewHeap \
+ ? ErtsInYoungGen((TPtr), (Ptr), oh, ohsz) \
+ : ErtsInArea((Ptr), src, src_size)))
while (n_hp != n_htop) {
ASSERT(n_hp < n_htop);
@@ -1799,7 +1820,7 @@ sweep_one_area(Eterm* n_hp, Eterm* n_htop, char* src, Uint src_size)
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*n_hp++ = val;
- } else if (in_area(ptr, src, src_size)) {
+ } else if (ERTS_IS_IN_SWEEP_AREA(gval, ptr)) {
MOVE_BOXED(ptr,val,n_htop,n_hp++);
} else {
n_hp++;
@@ -1811,7 +1832,7 @@ sweep_one_area(Eterm* n_hp, Eterm* n_htop, char* src, Uint src_size)
val = *ptr;
if (IS_MOVED_CONS(val)) {
*n_hp++ = ptr[1];
- } else if (in_area(ptr, src, src_size)) {
+ } else if (ERTS_IS_IN_SWEEP_AREA(gval, ptr)) {
MOVE_CONS(ptr,val,n_htop,n_hp++);
} else {
n_hp++;
@@ -1832,7 +1853,7 @@ sweep_one_area(Eterm* n_hp, Eterm* n_htop, char* src, Uint src_size)
if (IS_MOVED_BOXED(val)) {
*origptr = val;
mb->base = binary_bytes(*origptr);
- } else if (in_area(ptr, src, src_size)) {
+ } else if (ERTS_IS_IN_SWEEP_AREA(*origptr, ptr)) {
MOVE_BOXED(ptr,val,n_htop,origptr);
mb->base = binary_bytes(*origptr);
}
@@ -1847,10 +1868,41 @@ sweep_one_area(Eterm* n_hp, Eterm* n_htop, char* src, Uint src_size)
}
}
return n_htop;
+#undef ERTS_IS_IN_SWEEP_AREA
+}
+
+static Eterm *
+sweep_new_heap(Eterm *n_hp, Eterm *n_htop, char* old_heap, Uint old_heap_size)
+{
+ return sweep(n_hp, n_htop,
+ ErtsSweepNewHeap,
+ old_heap, old_heap_size,
+ NULL, 0);
+}
+
+static Eterm *
+sweep_heaps(Eterm *n_hp, Eterm *n_htop, char* old_heap, Uint old_heap_size)
+{
+ return sweep(n_hp, n_htop,
+ ErtsSweepHeaps,
+ old_heap, old_heap_size,
+ NULL, 0);
+}
+
+static Eterm *
+sweep_literal_area(Eterm *n_hp, Eterm *n_htop,
+ char* old_heap, Uint old_heap_size,
+ char* src, Uint src_size)
+{
+ return sweep(n_hp, n_htop,
+ ErtsSweepLiteralArea,
+ old_heap, old_heap_size,
+ src, src_size);
}
static Eterm*
-sweep_one_heap(Eterm* heap_ptr, Eterm* heap_end, Eterm* htop, char* src, Uint src_size)
+sweep_literals_to_old_heap(Eterm* heap_ptr, Eterm* heap_end, Eterm* htop,
+ char* src, Uint src_size)
{
while (heap_ptr < heap_end) {
Eterm* ptr;
@@ -1864,7 +1916,7 @@ sweep_one_heap(Eterm* heap_ptr, Eterm* heap_end, Eterm* htop, char* src, Uint sr
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*heap_ptr++ = val;
- } else if (in_area(ptr, src, src_size)) {
+ } else if (ErtsInArea(ptr, src, src_size)) {
MOVE_BOXED(ptr,val,htop,heap_ptr++);
} else {
heap_ptr++;
@@ -1876,7 +1928,7 @@ sweep_one_heap(Eterm* heap_ptr, Eterm* heap_end, Eterm* htop, char* src, Uint sr
val = *ptr;
if (IS_MOVED_CONS(val)) {
*heap_ptr++ = ptr[1];
- } else if (in_area(ptr, src, src_size)) {
+ } else if (ErtsInArea(ptr, src, src_size)) {
MOVE_CONS(ptr,val,htop,heap_ptr++);
} else {
heap_ptr++;
@@ -1897,7 +1949,7 @@ sweep_one_heap(Eterm* heap_ptr, Eterm* heap_end, Eterm* htop, char* src, Uint sr
if (IS_MOVED_BOXED(val)) {
*origptr = val;
mb->base = binary_bytes(*origptr);
- } else if (in_area(ptr, src, src_size)) {
+ } else if (ErtsInArea(ptr, src, src_size)) {
MOVE_BOXED(ptr,val,htop,origptr);
mb->base = binary_bytes(*origptr);
}
@@ -1948,43 +2000,21 @@ move_one_area(Eterm* n_htop, char* src, Uint src_size)
*/
static Eterm*
-collect_heap_frags(Process* p, Eterm* n_hstart, Eterm* n_htop,
- Eterm* objv, int nobj)
+collect_live_heap_frags(Process* p, ErlHeapFragment *live_hf_end,
+ Eterm* n_hstart, Eterm* n_htop,
+ Eterm* objv, int nobj)
{
ErlHeapFragment* qb;
char* frag_begin;
Uint frag_size;
/*
- * We don't allow references to a heap fragments from the stack, heap,
- * or process dictionary.
- */
-#ifdef HARDDEBUG
- disallow_heap_frag_ref(p, n_htop, p->stop, STACK_START(p) - p->stop);
- if (p->dictionary != NULL) {
- disallow_heap_frag_ref(p, n_htop, p->dictionary->data, p->dictionary->used);
- }
- /* OTP-18: Actually we do allow references from heap to heap fragments now.
- This can happen when doing "binary_to_term" with a "fat" map contained
- in another term. A "fat" map is a hashmap with higher heap demand than
- first estimated by "binary_to_term" causing the factory to allocate
- additional heap (fragments) for the hashmap tree nodes.
- Run map_SUITE:t_gc_rare_map_overflow to provoke this.
-
- Inverted references like this does not matter however. The copy done
- below by move_one_area() with move markers in the fragments and the
- sweeping done later by the GC should make everything ok in the end.
- */
- /***disallow_heap_frag_ref_in_heap(p);***/
-#endif
-
- /*
* Move the heap fragments to the new heap. Note that no GC is done on
* the heap fragments. Any garbage will thus be moved as well and survive
* until next GC.
*/
qb = MBUF(p);
- while (qb != NULL) {
+ while (qb != live_hf_end) {
ASSERT(!qb->off_heap.first); /* process fragments use the MSO(p) list */
frag_size = qb->used_size * sizeof(Eterm);
if (frag_size != 0) {
@@ -1996,12 +2026,177 @@ collect_heap_frags(Process* p, Eterm* n_hstart, Eterm* n_htop,
return n_htop;
}
+static ERTS_INLINE void
+copy_one_frag(Eterm** hpp, ErlOffHeap* off_heap,
+ ErlHeapFragment *bp, Eterm *refs, int nrefs)
+{
+ Uint sz;
+ int i;
+ Sint offs;
+ struct erl_off_heap_header* oh;
+ Eterm *fhp, *hp;
+
+ OH_OVERHEAD(off_heap, bp->off_heap.overhead);
+ sz = bp->used_size;
+
+ fhp = bp->mem;
+ hp = *hpp;
+ offs = hp - fhp;
+
+ oh = NULL;
+ while (sz--) {
+ Uint cpy_sz;
+ Eterm val = *fhp++;
+
+ switch (primary_tag(val)) {
+ case TAG_PRIMARY_IMMED1:
+ *hp++ = val;
+ break;
+ case TAG_PRIMARY_LIST:
+ case TAG_PRIMARY_BOXED:
+ *hp++ = offset_ptr(val, offs);
+ break;
+ case TAG_PRIMARY_HEADER:
+ *hp++ = val;
+ switch (val & _HEADER_SUBTAG_MASK) {
+ case ARITYVAL_SUBTAG:
+ break;
+ case REFC_BINARY_SUBTAG:
+ case FUN_SUBTAG:
+ case EXTERNAL_PID_SUBTAG:
+ case EXTERNAL_PORT_SUBTAG:
+ case EXTERNAL_REF_SUBTAG:
+ oh = (struct erl_off_heap_header*) (hp-1);
+ cpy_sz = thing_arityval(val);
+ goto cpy_words;
+ default:
+ cpy_sz = header_arity(val);
+
+ cpy_words:
+ ASSERT(sz >= cpy_sz);
+ sz -= cpy_sz;
+ while (cpy_sz >= 8) {
+ cpy_sz -= 8;
+ *hp++ = *fhp++;
+ *hp++ = *fhp++;
+ *hp++ = *fhp++;
+ *hp++ = *fhp++;
+ *hp++ = *fhp++;
+ *hp++ = *fhp++;
+ *hp++ = *fhp++;
+ *hp++ = *fhp++;
+ }
+ switch (cpy_sz) {
+ case 7: *hp++ = *fhp++;
+ case 6: *hp++ = *fhp++;
+ case 5: *hp++ = *fhp++;
+ case 4: *hp++ = *fhp++;
+ case 3: *hp++ = *fhp++;
+ case 2: *hp++ = *fhp++;
+ case 1: *hp++ = *fhp++;
+ default: break;
+ }
+ if (oh) {
+ /* Add to offheap list */
+ oh->next = off_heap->first;
+ off_heap->first = oh;
+ ASSERT(*hpp <= (Eterm*)oh);
+ ASSERT(hp > (Eterm*)oh);
+ oh = NULL;
+ }
+ break;
+ }
+ break;
+ }
+ }
+
+ ASSERT(bp->used_size == hp - *hpp);
+ *hpp = hp;
+
+ for (i = 0; i < nrefs; i++) {
+ if (is_not_immed(refs[i]))
+ refs[i] = offset_ptr(refs[i], offs);
+ }
+ bp->off_heap.first = NULL;
+}
+
+static void
+move_msgq_to_heap(Process *p)
+{
+ ErtsMessage **mpp = &p->msg.first;
+
+ while (*mpp) {
+ ErtsMessage *mp = *mpp;
+
+ if (mp->data.attached) {
+ ErlHeapFragment *bp;
+ ErtsHeapFactory factory;
+
+ erts_factory_proc_prealloc_init(&factory, p,
+ erts_msg_attached_data_size(mp));
+
+ if (is_non_value(ERL_MESSAGE_TERM(mp))) {
+ if (mp->data.dist_ext) {
+ ASSERT(mp->data.dist_ext->heap_size >= 0);
+ if (is_not_nil(ERL_MESSAGE_TOKEN(mp))) {
+ bp = erts_dist_ext_trailer(mp->data.dist_ext);
+ ERL_MESSAGE_TOKEN(mp) = copy_struct(ERL_MESSAGE_TOKEN(mp),
+ bp->used_size,
+ &factory.hp,
+ factory.off_heap);
+ erts_cleanup_offheap(&bp->off_heap);
+ }
+ ERL_MESSAGE_TERM(mp) = erts_decode_dist_ext(&factory,
+ mp->data.dist_ext);
+ erts_free_dist_ext_copy(mp->data.dist_ext);
+ mp->data.dist_ext = NULL;
+ }
+ }
+ else {
+
+ if (mp->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ bp = &mp->hfrag;
+ else
+ bp = mp->data.heap_frag;
+
+ if (bp->next)
+ erts_move_multi_frags(&factory.hp, factory.off_heap, bp,
+ mp->m, ERL_MESSAGE_REF_ARRAY_SZ, 0);
+ else
+ copy_one_frag(&factory.hp, factory.off_heap, bp,
+ mp->m, ERL_MESSAGE_REF_ARRAY_SZ);
+
+ if (mp->data.attached != ERTS_MSG_COMBINED_HFRAG) {
+ mp->data.heap_frag = NULL;
+ free_message_buffer(bp);
+ }
+ else {
+ ErtsMessage *tmp = erts_alloc_message(0, NULL);
+ sys_memcpy((void *) tmp->m, (void *) mp->m,
+ sizeof(Eterm)*ERL_MESSAGE_REF_ARRAY_SZ);
+ tmp->next = mp->next;
+ if (p->msg.save == &mp->next)
+ p->msg.save = &tmp->next;
+ if (p->msg.last == &mp->next)
+ p->msg.last = &tmp->next;
+ *mpp = tmp;
+ mp->next = NULL;
+ erts_cleanup_messages(mp);
+ mp = tmp;
+ }
+ }
+
+ erts_factory_close(&factory);
+ }
+
+ mpp = &(*mpp)->next;
+ }
+}
+
static Uint
setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
{
- Uint avail;
Roots* roots;
- ErlMessage* mp;
Uint n;
n = 0;
@@ -2013,8 +2208,8 @@ setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
++n;
if (p->dictionary != NULL) {
- roots[n].v = p->dictionary->data;
- roots[n].sz = p->dictionary->used;
+ roots[n].v = ERTS_PD_START(p->dictionary);
+ roots[n].sz = ERTS_PD_SIZE(p->dictionary);
++n;
}
if (nobj > 0) {
@@ -2024,7 +2219,7 @@ setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
}
ASSERT((is_nil(p->seq_trace_token) ||
- is_tuple(follow_moved(p->seq_trace_token)) ||
+ is_tuple(follow_moved(p->seq_trace_token, (Eterm) 0)) ||
is_atom(p->seq_trace_token)));
if (is_not_immed(p->seq_trace_token)) {
roots[n].v = &p->seq_trace_token;
@@ -2042,7 +2237,7 @@ setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
is_internal_pid(ERTS_TRACER_PROC(p)) ||
is_internal_port(ERTS_TRACER_PROC(p)));
- ASSERT(is_pid(follow_moved(p->group_leader)));
+ ASSERT(is_pid(follow_moved(p->group_leader, (Eterm) 0)));
if (is_not_immed(p->group_leader)) {
roots[n].v = &p->group_leader;
roots[n].sz = 1;
@@ -2079,31 +2274,47 @@ setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
ASSERT(n <= rootset->size);
- mp = p->msg.first;
- avail = rootset->size - n;
- while (mp != NULL) {
- if (avail == 0) {
- Uint new_size = 2*rootset->size;
- if (roots == rootset->def) {
- roots = erts_alloc(ERTS_ALC_T_ROOTSET,
- new_size*sizeof(Roots));
- sys_memcpy(roots, rootset->def, sizeof(rootset->def));
- } else {
- roots = erts_realloc(ERTS_ALC_T_ROOTSET,
- (void *) roots,
- new_size*sizeof(Roots));
- }
+ switch (p->flags & (F_OFF_HEAP_MSGQ|F_OFF_HEAP_MSGQ_CHNG)) {
+ case F_OFF_HEAP_MSGQ|F_OFF_HEAP_MSGQ_CHNG:
+ (void) erts_move_messages_off_heap(p);
+ case F_OFF_HEAP_MSGQ:
+ break;
+ case F_OFF_HEAP_MSGQ_CHNG:
+ case 0: {
+ /*
+ * We do not have off heap message queue enabled, i.e. we
+ * need to add message queue to rootset...
+ */
+ ErtsMessage *mp;
+
+ /* Ensure large enough rootset... */
+ if (n + p->msg.len > rootset->size) {
+ Uint new_size = n + p->msg.len;
+ ERTS_GC_ASSERT(roots == rootset->def);
+ roots = erts_alloc(ERTS_ALC_T_ROOTSET,
+ new_size*sizeof(Roots));
+ sys_memcpy(roots, rootset->def, n*sizeof(Roots));
rootset->size = new_size;
- avail = new_size - n;
}
- if (mp->data.attached == NULL) {
- roots[n].v = mp->m;
- roots[n].sz = 2;
- n++;
- avail--;
+
+ for (mp = p->msg.first; mp; mp = mp->next) {
+
+ if (!mp->data.attached) {
+ /*
+ * Message may refer data on heap;
+ * add it to rootset...
+ */
+ roots[n].v = mp->m;
+ roots[n].sz = ERL_MESSAGE_REF_ARRAY_SZ;
+ n++;
+ }
}
- mp = mp->next;
+ break;
}
+ }
+
+ ASSERT(rootset->size >= n);
+
rootset->roots = roots;
rootset->num_roots = n;
return n;
@@ -2343,11 +2554,11 @@ sweep_off_heap(Process *p, int fullsweep)
*/
while (ptr) {
if (IS_MOVED_BOXED(ptr->thing_word)) {
- ASSERT(!in_area(ptr, oheap, oheap_sz));
+ ASSERT(!ErtsInArea(ptr, oheap, oheap_sz));
*prev = ptr = (struct erl_off_heap_header*) boxed_val(ptr->thing_word);
ASSERT(!IS_MOVED_BOXED(ptr->thing_word));
if (ptr->thing_word == HEADER_PROC_BIN) {
- int to_new_heap = !in_area(ptr, oheap, oheap_sz);
+ int to_new_heap = !ErtsInArea(ptr, oheap, oheap_sz);
ASSERT(to_new_heap == !seen_mature || (!to_new_heap && (seen_mature=1)));
if (to_new_heap) {
bin_vheap += ptr->size / sizeof(Eterm);
@@ -2361,7 +2572,7 @@ sweep_off_heap(Process *p, int fullsweep)
ptr = ptr->next;
}
}
- else if (!in_area(ptr, oheap, oheap_sz)) {
+ else if (!ErtsInArea(ptr, oheap, oheap_sz)) {
/* garbage */
switch (thing_subtag(ptr->thing_word)) {
case REFC_BINARY_SUBTAG:
@@ -2393,7 +2604,7 @@ sweep_off_heap(Process *p, int fullsweep)
* generational collection - keep objects in list.
*/
while (ptr) {
- ASSERT(in_area(ptr, oheap, oheap_sz));
+ ASSERT(ErtsInArea(ptr, oheap, oheap_sz));
ASSERT(!IS_MOVED_BOXED(ptr->thing_word));
if (ptr->thing_word == HEADER_PROC_BIN) {
BIN_OLD_VHEAP(p) += ptr->size / sizeof(Eterm); /* for binary gc (words)*/
@@ -2412,7 +2623,6 @@ sweep_off_heap(Process *p, int fullsweep)
}
BIN_VHEAP_SZ(p) = next_vheap_size(p, bin_vheap, BIN_VHEAP_SZ(p));
MSO(p).overhead = bin_vheap;
- BIN_VHEAP_MATURE(p) = bin_vheap;
/*
* If we got any shrink candidates, check them out.
@@ -2483,7 +2693,7 @@ offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
switch (primary_tag(val)) {
case TAG_PRIMARY_LIST:
case TAG_PRIMARY_BOXED:
- if (in_area(ptr_val(val), area, area_size)) {
+ if (ErtsInArea(ptr_val(val), area, area_size)) {
*hp = offset_ptr(val, offs);
}
hp++;
@@ -2505,7 +2715,7 @@ offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
{
struct erl_off_heap_header* oh = (struct erl_off_heap_header*) hp;
- if (in_area(oh->next, area, area_size)) {
+ if (ErtsInArea(oh->next, area, area_size)) {
Eterm** uptr = (Eterm **) (void *) &oh->next;
*uptr += offs; /* Patch the mso chain */
}
@@ -2515,7 +2725,7 @@ offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
{
ErlBinMatchState *ms = (ErlBinMatchState*) hp;
ErlBinMatchBuffer *mb = &(ms->mb);
- if (in_area(ptr_val(mb->orig), area, area_size)) {
+ if (ErtsInArea(ptr_val(mb->orig), area, area_size)) {
mb->orig = offset_ptr(mb->orig, offs);
mb->base = binary_bytes(mb->orig);
}
@@ -2545,7 +2755,7 @@ offset_heap_ptr(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
switch (primary_tag(val)) {
case TAG_PRIMARY_LIST:
case TAG_PRIMARY_BOXED:
- if (in_area(ptr_val(val), area, area_size)) {
+ if (ErtsInArea(ptr_val(val), area, area_size)) {
*hp = offset_ptr(val, offs);
}
hp++;
@@ -2560,7 +2770,7 @@ offset_heap_ptr(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
static void
offset_off_heap(Process* p, Sint offs, char* area, Uint area_size)
{
- if (MSO(p).first && in_area((Eterm *)MSO(p).first, area, area_size)) {
+ if (MSO(p).first && ErtsInArea((Eterm *)MSO(p).first, area, area_size)) {
Eterm** uptr = (Eterm**) (void *) &MSO(p).first;
*uptr += offs;
}
@@ -2572,35 +2782,39 @@ offset_off_heap(Process* p, Sint offs, char* area, Uint area_size)
static void
offset_mqueue(Process *p, Sint offs, char* area, Uint area_size)
{
- ErlMessage* mp = p->msg.first;
-
- while (mp != NULL) {
- Eterm mesg = ERL_MESSAGE_TERM(mp);
- if (is_value(mesg)) {
- switch (primary_tag(mesg)) {
- case TAG_PRIMARY_LIST:
- case TAG_PRIMARY_BOXED:
- if (in_area(ptr_val(mesg), area, area_size)) {
- ERL_MESSAGE_TERM(mp) = offset_ptr(mesg, offs);
+ ErtsMessage* mp = p->msg.first;
+
+ if ((p->flags & (F_OFF_HEAP_MSGQ|F_OFF_HEAP_MSGQ_CHNG)) != F_OFF_HEAP_MSGQ) {
+
+ while (mp != NULL) {
+ Eterm mesg = ERL_MESSAGE_TERM(mp);
+ if (is_value(mesg)) {
+ switch (primary_tag(mesg)) {
+ case TAG_PRIMARY_LIST:
+ case TAG_PRIMARY_BOXED:
+ if (ErtsInArea(ptr_val(mesg), area, area_size)) {
+ ERL_MESSAGE_TERM(mp) = offset_ptr(mesg, offs);
+ }
+ break;
}
- break;
}
- }
- mesg = ERL_MESSAGE_TOKEN(mp);
- if (is_boxed(mesg) && in_area(ptr_val(mesg), area, area_size)) {
- ERL_MESSAGE_TOKEN(mp) = offset_ptr(mesg, offs);
- }
+ mesg = ERL_MESSAGE_TOKEN(mp);
+ if (is_boxed(mesg) && ErtsInArea(ptr_val(mesg), area, area_size)) {
+ ERL_MESSAGE_TOKEN(mp) = offset_ptr(mesg, offs);
+ }
#ifdef USE_VM_PROBES
- mesg = ERL_MESSAGE_DT_UTAG(mp);
- if (is_boxed(mesg) && in_area(ptr_val(mesg), area, area_size)) {
- ERL_MESSAGE_DT_UTAG(mp) = offset_ptr(mesg, offs);
- }
+ mesg = ERL_MESSAGE_DT_UTAG(mp);
+ if (is_boxed(mesg) && ErtsInArea(ptr_val(mesg), area, area_size)) {
+ ERL_MESSAGE_DT_UTAG(mp) = offset_ptr(mesg, offs);
+ }
#endif
- ASSERT((is_nil(ERL_MESSAGE_TOKEN(mp)) ||
- is_tuple(ERL_MESSAGE_TOKEN(mp)) ||
- is_atom(ERL_MESSAGE_TOKEN(mp))));
- mp = mp->next;
+ ASSERT((is_nil(ERL_MESSAGE_TOKEN(mp)) ||
+ is_tuple(ERL_MESSAGE_TOKEN(mp)) ||
+ is_atom(ERL_MESSAGE_TOKEN(mp))));
+ mp = mp->next;
+ }
+
}
}
@@ -2609,8 +2823,8 @@ offset_one_rootset(Process *p, Sint offs, char* area, Uint area_size,
Eterm* objv, int nobj)
{
if (p->dictionary) {
- offset_heap(p->dictionary->data,
- p->dictionary->used,
+ offset_heap(ERTS_PD_START(p->dictionary),
+ ERTS_PD_SIZE(p->dictionary),
offs, area, area_size);
}
@@ -2659,7 +2873,7 @@ reply_gc_info(void *vgcirp)
Eterm **hpp;
Uint sz, *szp;
ErlOffHeap *ohp = NULL;
- ErlHeapFragment *bp = NULL;
+ ErtsMessage *mp = NULL;
ASSERT(esdp);
@@ -2685,12 +2899,13 @@ reply_gc_info(void *vgcirp)
if (hpp)
break;
- hp = erts_alloc_message_heap(sz, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, sz, &hp, &ohp);
+
szp = NULL;
hpp = &hp;
}
- erts_queue_message(rp, &rp_locks, bp, msg, NIL);
+ erts_queue_message(rp, &rp_locks, mp, msg, NIL);
if (gcirp->req_sched == esdp->no)
rp_locks &= ~ERTS_PROC_LOCK_MAIN;
@@ -2737,41 +2952,105 @@ erts_gc_info_request(Process *c_p)
return ref;
}
+Eterm
+erts_process_gc_info(Process *p, Uint *sizep, Eterm **hpp)
+{
+ ERTS_DECL_AM(bin_vheap_size);
+ ERTS_DECL_AM(bin_vheap_block_size);
+ ERTS_DECL_AM(bin_old_vheap_size);
+ ERTS_DECL_AM(bin_old_vheap_block_size);
+ Eterm tags[] = {
+ /* If you increase the number of elements here, make sure to update
+ any call sites as they may have stack allocations that depend
+ on the number of elements here. */
+ am_old_heap_block_size,
+ am_heap_block_size,
+ am_mbuf_size,
+ am_recent_size,
+ am_stack_size,
+ am_old_heap_size,
+ am_heap_size,
+ AM_bin_vheap_size,
+ AM_bin_vheap_block_size,
+ AM_bin_old_vheap_size,
+ AM_bin_old_vheap_block_size
+ };
+ UWord values[] = {
+ OLD_HEAP(p) ? OLD_HEND(p) - OLD_HEAP(p) : 0,
+ HEAP_SIZE(p),
+ MBUF_SIZE(p),
+ HIGH_WATER(p) - HEAP_START(p),
+ STACK_START(p) - p->stop,
+ OLD_HEAP(p) ? OLD_HTOP(p) - OLD_HEAP(p) : 0,
+ HEAP_TOP(p) - HEAP_START(p),
+ MSO(p).overhead,
+ BIN_VHEAP_SZ(p),
+ BIN_OLD_VHEAP(p),
+ BIN_OLD_VHEAP_SZ(p)
+ };
+
+ Eterm res = THE_NON_VALUE;
+
+ ERTS_CT_ASSERT(sizeof(values)/sizeof(*values) == sizeof(tags)/sizeof(*tags));
+ ERTS_CT_ASSERT(sizeof(values)/sizeof(*values) == ERTS_PROCESS_GC_INFO_MAX_TERMS);
+
+ res = erts_bld_atom_uword_2tup_list(hpp,
+ sizep,
+ sizeof(values)/sizeof(*values),
+ tags,
+ values);
+
+ return res;
+}
+
#if defined(DEBUG) || defined(ERTS_OFFHEAP_DEBUG)
static int
within2(Eterm *ptr, Process *p, Eterm *real_htop)
{
- ErlHeapFragment* bp = MBUF(p);
- ErlMessage* mp = p->msg.first;
- Eterm *htop = real_htop ? real_htop : HEAP_TOP(p);
+ ErlHeapFragment* bp;
+ ErtsMessage* mp;
+ Eterm *htop, *heap;
+
+ if (p->abandoned_heap)
+ ERTS_GET_ORIG_HEAP(p, heap, htop);
+ else {
+ heap = p->heap;
+ htop = real_htop ? real_htop : HEAP_TOP(p);
+ }
if (OLD_HEAP(p) && (OLD_HEAP(p) <= ptr && ptr < OLD_HEND(p))) {
return 1;
}
- if (HEAP_START(p) <= ptr && ptr < htop) {
+ if (heap <= ptr && ptr < htop) {
return 1;
}
- while (bp != NULL) {
- if (bp->mem <= ptr && ptr < bp->mem + bp->used_size) {
- return 1;
- }
- bp = bp->next;
- }
+
+ mp = p->msg_frag;
+ bp = p->mbuf;
+
+ if (bp)
+ goto search_heap_frags;
+
while (mp) {
- if (mp->data.attached) {
- ErlHeapFragment *hfp;
- if (is_value(ERL_MESSAGE_TERM(mp)))
- hfp = mp->data.heap_frag;
- else if (is_not_nil(ERL_MESSAGE_TOKEN(mp)))
- hfp = erts_dist_ext_trailer(mp->data.dist_ext);
- else
- hfp = NULL;
- if (hfp && hfp->mem <= ptr && ptr < hfp->mem + hfp->used_size)
+
+ if (mp->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ bp = &mp->hfrag;
+ else
+ bp = mp->data.heap_frag;
+
+ mp = mp->next;
+
+ search_heap_frags:
+
+ while (bp) {
+ if (bp->mem <= ptr && ptr < bp->mem + bp->used_size) {
return 1;
+ }
+ bp = bp->next;
}
- mp = mp->next;
}
+
return 0;
}
@@ -2793,11 +3072,11 @@ do { \
__FILE__, __LINE__, #EXP); \
} while (0)
+
#ifdef ERTS_OFFHEAP_DEBUG_CHK_CIRCULAR_LIST
# define ERTS_OFFHEAP_VISITED_BIT ((Eterm) 1 << 31)
#endif
-
void
erts_check_off_heap2(Process *p, Eterm *htop)
{
@@ -2826,7 +3105,7 @@ erts_check_off_heap2(Process *p, Eterm *htop)
}
ERTS_CHK_OFFHEAP_ASSERT(refc >= 1);
#ifdef ERTS_OFFHEAP_DEBUG_CHK_CIRCULAR_LIST
- ERTS_CHK_OFFHEAP_ASSERT(!(u.hdr->thing_word & ERTS_EXTERNAL_VISITED_BIT));
+ ERTS_CHK_OFFHEAP_ASSERT(!(u.hdr->thing_word & ERTS_OFFHEAP_VISITED_BIT));
u.hdr->thing_word |= ERTS_OFFHEAP_VISITED_BIT;
#endif
if (old) {
@@ -2839,7 +3118,7 @@ erts_check_off_heap2(Process *p, Eterm *htop)
}
}
-#ifdef ERTS_OFFHEAP_DEBUG_CHK_CIRCULAR_EXTERNAL_LIST
+#ifdef ERTS_OFFHEAP_DEBUG_CHK_CIRCULAR_LIST
for (u.hdr = MSO(p).first; u.hdr; u.hdr = u.hdr->next)
u.hdr->thing_word &= ~ERTS_OFFHEAP_VISITED_BIT;
#endif
diff --git a/erts/emulator/beam/erl_gc.h b/erts/emulator/beam/erl_gc.h
index ecd1bf4d22..2cedd9361f 100644
--- a/erts/emulator/beam/erl_gc.h
+++ b/erts/emulator/beam/erl_gc.h
@@ -69,17 +69,18 @@ do { \
while (nelts--) *HTOP++ = *PTR++; \
} while(0)
-#define in_area(ptr,start,nbytes) \
- ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes))
-
#if defined(DEBUG) || defined(ERTS_OFFHEAP_DEBUG)
int within(Eterm *ptr, Process *p);
#endif
-ERTS_GLB_INLINE Eterm follow_moved(Eterm term);
+#define ErtsInYoungGen(TPtr, Ptr, OldHeap, OldHeapSz) \
+ (!erts_is_literal((TPtr), (Ptr)) \
+ & !ErtsInArea((Ptr), (OldHeap), (OldHeapSz)))
+
+ERTS_GLB_INLINE Eterm follow_moved(Eterm term, Eterm xptr_tag);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
-ERTS_GLB_INLINE Eterm follow_moved(Eterm term)
+ERTS_GLB_INLINE Eterm follow_moved(Eterm term, Eterm xptr_tag)
{
Eterm* ptr;
switch (primary_tag(term)) {
@@ -87,17 +88,18 @@ ERTS_GLB_INLINE Eterm follow_moved(Eterm term)
break;
case TAG_PRIMARY_BOXED:
ptr = boxed_val(term);
- if (IS_MOVED_BOXED(*ptr)) term = *ptr;
+ if (IS_MOVED_BOXED(*ptr)) term = (*ptr) | xptr_tag;
break;
case TAG_PRIMARY_LIST:
ptr = list_val(term);
- if (IS_MOVED_CONS(ptr[0])) term = ptr[1];
+ if (IS_MOVED_CONS(ptr[0])) term = (ptr[1]) | xptr_tag;
break;
default:
ASSERT(!"strange tag in follow_moved");
}
return term;
}
+
#endif
#endif /* ERL_GC_C__ || HIPE_GC_C__ */
@@ -106,6 +108,23 @@ ERTS_GLB_INLINE Eterm follow_moved(Eterm term)
* Global exported
*/
+#define ERTS_IS_GC_DESIRED_INTERNAL(Proc, HTop, STop) \
+ ((((STop) - (HTop) < (Proc)->mbuf_sz)) \
+ | ((Proc)->off_heap.overhead > (Proc)->bin_vheap_sz) \
+ | !!((Proc)->flags & F_FORCE_GC))
+
+#define ERTS_IS_GC_DESIRED(Proc) \
+ ERTS_IS_GC_DESIRED_INTERNAL((Proc), (Proc)->htop, (Proc)->stop)
+
+#define ERTS_FORCE_GC_INTERNAL(Proc, FCalls) \
+ do { \
+ (Proc)->flags |= F_FORCE_GC; \
+ ERTS_VBUMP_ALL_REDS_INTERNAL((Proc), (FCalls)); \
+ } while (0)
+
+#define ERTS_FORCE_GC(Proc) \
+ ERTS_FORCE_GC_INTERNAL((Proc), (Proc)->fcalls)
+
extern Uint erts_test_long_gc_sleep;
typedef struct {
@@ -113,10 +132,18 @@ typedef struct {
Uint64 garbage_cols;
} ErtsGCInfo;
+#define ERTS_PROCESS_GC_INFO_MAX_TERMS (11) /* number of elements in process_gc_info*/
+#define ERTS_PROCESS_GC_INFO_MAX_SIZE \
+ (ERTS_PROCESS_GC_INFO_MAX_TERMS * (2/*cons*/ + 3/*2-tuple*/ + BIG_UINT_HEAP_SIZE))
+Eterm erts_process_gc_info(struct process*, Uint *, Eterm **);
+
void erts_gc_info(ErtsGCInfo *gcip);
void erts_init_gc(void);
-int erts_garbage_collect(struct process*, int, Eterm*, int);
+int erts_garbage_collect_nobump(struct process*, int, Eterm*, int);
+void erts_garbage_collect(struct process*, int, Eterm*, int);
void erts_garbage_collect_hibernate(struct process* p);
+Eterm erts_gc_after_bif_call_lhf(struct process* p, ErlHeapFragment *live_hf_end,
+ Eterm result, Eterm* regs, Uint arity);
Eterm erts_gc_after_bif_call(struct process* p, Eterm result, Eterm* regs, Uint arity);
void erts_garbage_collect_literals(struct process* p, Eterm* literals,
Uint lit_size,
diff --git a/erts/emulator/beam/erl_hl_timer.c b/erts/emulator/beam/erl_hl_timer.c
index fb6d249145..491d2f8c84 100644
--- a/erts/emulator/beam/erl_hl_timer.c
+++ b/erts/emulator/beam/erl_hl_timer.c
@@ -1245,7 +1245,9 @@ hlt_bif_timer_timeout(ErtsHLTimer *tmr, Uint32 roflgs)
* the middle of tree destruction).
*/
if (!ERTS_PROC_IS_EXITING(proc)) {
- erts_queue_message(proc, &proc_locks, tmr->btm.bp,
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = tmr->btm.bp;
+ erts_queue_message(proc, &proc_locks, mp,
tmr->btm.message, NIL);
erts_smp_proc_unlock(proc, ERTS_PROC_LOCKS_MSG_SEND);
queued_message = 1;
@@ -1926,36 +1928,31 @@ access_sched_local_btm(Process *c_p, Eterm pid,
if (proc) {
Uint hsz;
- ErlOffHeap *ohp;
- ErlHeapFragment* bp;
+ ErtsMessage *mp;
Eterm *hp, msg, ref, result;
+ ErlOffHeap *ohp;
+ Uint32 *refn;
#ifdef ERTS_HLT_DEBUG
Eterm *hp_end;
#endif
- hsz = 3; /* 2-tuple */
- if (!async)
- hsz += REF_THING_SIZE;
+ hsz = REF_THING_SIZE;
+ if (async) {
+ refn = trefn; /* timer ref */
+ hsz += 4; /* 3-tuple */
+ }
else {
- if (is_non_value(tref) || proc != c_p)
- hsz += REF_THING_SIZE;
- hsz += 1; /* upgrade to 3-tuple */
+ refn = rrefn; /* request ref */
+ hsz += 3; /* 2-tuple */
}
+
+ ERTS_HLT_ASSERT(refn);
+
if (time_left > (Sint64) MAX_SMALL)
hsz += ERTS_SINT64_HEAP_SIZE(time_left);
- if (proc == c_p) {
- bp = NULL;
- ohp = NULL;
- hp = HAlloc(c_p, hsz);
- }
- else {
- hp = erts_alloc_message_heap(hsz,
- &bp,
- &ohp,
- proc,
- &proc_locks);
- }
+ mp = erts_alloc_message_heap(proc, &proc_locks,
+ hsz, &hp, &ohp);
#ifdef ERTS_HLT_DEBUG
hp_end = hp + hsz;
@@ -1968,35 +1965,22 @@ access_sched_local_btm(Process *c_p, Eterm pid,
else
result = erts_sint64_to_big(time_left, &hp);
- if (!async) {
- write_ref_thing(hp,
- rrefn[0],
- rrefn[1],
- rrefn[2]);
- ref = make_internal_ref(hp);
- hp += REF_THING_SIZE;
- msg = TUPLE2(hp, ref, result);
+ write_ref_thing(hp,
+ refn[0],
+ refn[1],
+ refn[2]);
+ ref = make_internal_ref(hp);
+ hp += REF_THING_SIZE;
- ERTS_HLT_ASSERT(hp + 3 == hp_end);
- }
- else {
- Eterm tag = cancel ? am_cancel_timer : am_read_timer;
- if (is_value(tref) && proc == c_p)
- ref = tref;
- else {
- write_ref_thing(hp,
- trefn[0],
- trefn[1],
- trefn[2]);
- ref = make_internal_ref(hp);
- hp += REF_THING_SIZE;
- }
- msg = TUPLE3(hp, tag, ref, result);
+ msg = (async
+ ? TUPLE3(hp, (cancel
+ ? am_cancel_timer
+ : am_read_timer), ref, result)
+ : TUPLE2(hp, ref, result));
- ERTS_HLT_ASSERT(hp + 4 == hp_end);
+ ERTS_HLT_ASSERT(hp + (async ? 4 : 3) == hp_end);
- }
- erts_queue_message(proc, &proc_locks, bp, msg, NIL);
+ erts_queue_message(proc, &proc_locks, mp, msg, NIL);
if (c_p)
proc_locks &= ~ERTS_PROC_LOCK_MAIN;
@@ -2034,7 +2018,7 @@ bif_timer_access_request(void *vreq)
static int
try_access_sched_remote_btm(ErtsSchedulerData *esdp,
Process *c_p, Uint32 sid,
- Eterm tref, Uint32 *trefn,
+ Uint32 *trefn,
int async, int cancel,
int info, Eterm *resp)
{
@@ -2093,21 +2077,31 @@ try_access_sched_remote_btm(ErtsSchedulerData *esdp,
}
}
else {
- Eterm tag, res, msg;
+ ErtsMessage *mp;
+ Eterm tag, res, msg, tref;
Uint hsz;
Eterm *hp;
ErtsProcLocks proc_locks = ERTS_PROC_LOCK_MAIN;
+ ErlOffHeap *ohp;
- hsz = 4;
+ hsz = 4 + REF_THING_SIZE;
if (time_left > (Sint64) MAX_SMALL)
hsz += ERTS_SINT64_HEAP_SIZE(time_left);
- hp = HAlloc(c_p, hsz);
+ mp = erts_alloc_message_heap(c_p, &proc_locks,
+ hsz, &hp, &ohp);
if (cancel)
tag = am_cancel_timer;
else
tag = am_read_timer;
+ write_ref_thing(hp,
+ trefn[0],
+ trefn[1],
+ trefn[2]);
+ tref = make_internal_ref(hp);
+ hp += REF_THING_SIZE;
+
if (time_left < 0)
res = am_false;
else if (time_left <= (Sint64) MAX_SMALL)
@@ -2117,7 +2111,7 @@ try_access_sched_remote_btm(ErtsSchedulerData *esdp,
msg = TUPLE3(hp, tag, tref, res);
- erts_queue_message(c_p, &proc_locks, NULL, msg, NIL);
+ erts_queue_message(c_p, &proc_locks, mp, msg, NIL);
proc_locks &= ~ERTS_PROC_LOCK_MAIN;
if (proc_locks)
@@ -2158,8 +2152,8 @@ access_bif_timer(Process *c_p, Eterm tref, int cancel, int async, int info)
info);
ERTS_BIF_PREP_RET(ret, res);
}
- else if (try_access_sched_remote_btm(esdp, c_p, sid,
- tref, trefn,
+ else if (try_access_sched_remote_btm(esdp, c_p,
+ sid, trefn,
async, cancel,
info, &res)) {
ERTS_BIF_PREP_RET(ret, res);
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index e729574ec7..86c4eeb484 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -91,11 +91,6 @@ const int etp_arch_bits = 32;
#else
# error "Not 64-bit, nor 32-bit arch"
#endif
-#if HALFWORD_HEAP
-const int etp_halfword = 1;
-#else
-const int etp_halfword = 0;
-#endif
#ifdef HIPE
const int etp_hipe = 1;
#else
@@ -157,7 +152,7 @@ volatile int erts_writing_erl_crash_dump = 0;
int erts_initialized = 0;
#if defined(USE_THREADS) && !defined(ERTS_SMP)
-static erts_tid_t main_thread;
+erts_tid_t erts_main_thread;
#endif
int erts_use_sender_punish;
@@ -197,7 +192,7 @@ Uint32 verbose; /* See erl_debug.h for information about verbose */
int erts_atom_table_size = ATOM_LIMIT; /* Maximum number of atoms */
-int erts_pd_initial_size = 10;
+int erts_pd_initial_size = 8; /* must be power of 2 */
int erts_modified_timing_level;
@@ -393,11 +388,13 @@ erl_init(int ncpu,
erts_mseg_late_init(); /* Must be after timer (erts_init_time()) and thread
initializations */
#endif
+ erl_sys_late_init();
#ifdef HIPE
hipe_mode_switch_init(); /* Must be after init_load/beam_catches/init */
#endif
packet_parser_init();
erl_nif_init();
+ erts_msacc_init();
}
static Eterm
@@ -436,13 +433,36 @@ erl_first_process_otp(char* modname, void* code, unsigned size, int argc, char**
hp += 2;
args = CONS(hp, env, args);
- so.flags = SPO_SYSTEM_PROC;
+ so.flags = erts_default_spo_flags|SPO_SYSTEM_PROC;
res = erl_create_process(&parent, start_mod, am_start, args, &so);
erts_smp_proc_unlock(&parent, ERTS_PROC_LOCK_MAIN);
erts_cleanup_empty_process(&parent);
return res;
}
+static Eterm
+erl_system_process_otp(Eterm parent_pid, char* modname)
+{
+ Eterm start_mod;
+ Process* parent;
+ ErlSpawnOpts so;
+ Eterm res;
+
+ start_mod = erts_atom_put((byte *) modname, sys_strlen(modname), ERTS_ATOM_ENC_LATIN1, 1);
+ if (erts_find_function(start_mod, am_start, 0,
+ erts_active_code_ix()) == NULL) {
+ erts_exit(ERTS_ERROR_EXIT, "No function %s:start/0\n", modname);
+ }
+
+ parent = erts_pid2proc(NULL, 0, parent_pid, ERTS_PROC_LOCK_MAIN);
+
+ so.flags = erts_default_spo_flags|SPO_SYSTEM_PROC;
+ res = erl_create_process(parent, start_mod, am_start, NIL, &so);
+ erts_smp_proc_unlock(parent, ERTS_PROC_LOCK_MAIN);
+ return res;
+}
+
+
Eterm
erts_preloaded(Process* p)
{
@@ -635,6 +655,8 @@ void erts_usage(void)
erts_fprintf(stderr, "-W<i|w|e> set error logger warnings mapping,\n");
erts_fprintf(stderr, " see error_logger documentation for details\n");
+ erts_fprintf(stderr, "-xmqd val set default message queue data flag for processes,\n");
+ erts_fprintf(stderr, " valid values are: off_heap | on_heap | mixed\n");
erts_fprintf(stderr, "-zdbbl size set the distribution buffer busy limit in kilobytes\n");
erts_fprintf(stderr, " valid range is [1-%d]\n", INT_MAX/1024);
erts_fprintf(stderr, "-zdntgc time set delayed node table gc in seconds\n");
@@ -723,6 +745,10 @@ early_init(int *argc, char **argv) /*
char envbuf[21]; /* enough for any 64-bit integer */
size_t envbufsz;
+#if defined(USE_THREADS) && !defined(ERTS_SMP)
+ erts_main_thread = erts_thr_self();
+#endif
+
erts_save_emu_args(*argc, argv);
erts_sched_compact_load = 1;
@@ -776,9 +802,6 @@ early_init(int *argc, char **argv) /*
(erts_aint32_t) ((Uint16) -1));
erts_pre_init_process();
-#if defined(USE_THREADS) && !defined(ERTS_SMP)
- main_thread = erts_thr_self();
-#endif
/*
* We need to know the number of schedulers to use before we
@@ -1172,6 +1195,7 @@ early_init(int *argc, char **argv) /*
erts_thr_late_init(&elid);
}
#endif
+ erts_msacc_early_init();
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_lc_late_init();
@@ -1236,6 +1260,7 @@ erl_start(int argc, char **argv)
ErtsTimeWarpMode time_warp_mode;
int node_tab_delete_delay = ERTS_NODE_TAB_DELAY_GC_DEFAULT;
ErtsDbSpinCount db_spin_count = ERTS_DB_SPNCNT_NORMAL;
+ Eterm otp_ring0_pid;
set_default_time_adj(&time_correction,
&time_warp_mode);
@@ -1405,6 +1430,7 @@ erl_start(int argc, char **argv)
case 't': verbose |= DEBUG_THREADS; break;
case 'p': verbose |= DEBUG_PROCESSES; break;
case 'm': verbose |= DEBUG_MESSAGES; break;
+ case 'c': verbose |= DEBUG_SHCOPY; break;
default : erts_fprintf(stderr,"Unknown verbose option: %c\n",*ch);
}
}
@@ -1417,6 +1443,7 @@ erl_start(int argc, char **argv)
if (verbose & DEBUG_THREADS) erts_printf("THREADS ");
if (verbose & DEBUG_PROCESSES) erts_printf("PROCESSES ");
if (verbose & DEBUG_MESSAGES) erts_printf("MESSAGES ");
+ if (verbose & DEBUG_SHCOPY) erts_printf("SHCOPY ");
erts_printf("\n");
#else
erts_fprintf(stderr, "warning: -v (only in debug compiled code)\n");
@@ -1479,7 +1506,7 @@ erl_start(int argc, char **argv)
VERBOSE(DEBUG_SYSTEM, ("using minimum heap size %d\n", H_MIN_SIZE));
} else if (has_prefix("pds", sub_param)) {
arg = get_arg(sub_param+3, argv[i+1], &i);
- if ((erts_pd_initial_size = atoi(arg)) <= 0) {
+ if (!erts_pd_set_initial_size(atoi(arg))) {
erts_fprintf(stderr, "bad initial process dictionary size %s\n", arg);
erts_usage();
}
@@ -2020,6 +2047,32 @@ erl_start(int argc, char **argv)
}
break;
+ case 'x': {
+ char *sub_param = argv[i]+2;
+ if (has_prefix("mqd", sub_param)) {
+ arg = get_arg(sub_param+3, argv[i+1], &i);
+ if (sys_strcmp(arg, "mixed") == 0)
+ erts_default_spo_flags &= ~(SPO_ON_HEAP_MSGQ|SPO_OFF_HEAP_MSGQ);
+ else if (sys_strcmp(arg, "on_heap") == 0) {
+ erts_default_spo_flags &= ~SPO_OFF_HEAP_MSGQ;
+ erts_default_spo_flags |= SPO_ON_HEAP_MSGQ;
+ }
+ else if (sys_strcmp(arg, "off_heap") == 0) {
+ erts_default_spo_flags &= ~SPO_ON_HEAP_MSGQ;
+ erts_default_spo_flags |= SPO_OFF_HEAP_MSGQ;
+ }
+ else {
+ erts_fprintf(stderr,
+ "Invalid message_queue_data flag: %s\n", arg);
+ erts_usage();
+ }
+ } else {
+ erts_fprintf(stderr, "bad -x option %s\n", argv[i]);
+ erts_usage();
+ }
+ break;
+ }
+
case 'z': {
char *sub_param = argv[i]+2;
@@ -2073,7 +2126,8 @@ erl_start(int argc, char **argv)
"Invalid ets busy wait threshold: %s\n", arg);
erts_usage();
}
- } else {
+ }
+ else {
erts_fprintf(stderr, "bad -z option %s\n", argv[i]);
erts_usage();
}
@@ -2156,8 +2210,10 @@ erl_start(int argc, char **argv)
erts_initialized = 1;
- (void) erl_first_process_otp("otp_ring0", NULL, 0,
- boot_argc, boot_argv);
+ otp_ring0_pid = erl_first_process_otp("otp_ring0", NULL, 0,
+ boot_argc, boot_argv);
+
+ (void) erl_system_process_otp(otp_ring0_pid, "erts_code_purger");
#ifdef ERTS_SMP
erts_start_schedulers();
@@ -2167,6 +2223,7 @@ erl_start(int argc, char **argv)
#else
{
ErtsSchedulerData *esdp = erts_get_scheduler_data();
+ erts_msacc_init_thread("scheduler", 1, 1);
erts_thr_set_main_status(1, 1);
#if ERTS_USE_ASYNC_READY_Q
esdp->aux_work_data.async_ready.queue
@@ -2232,7 +2289,7 @@ system_cleanup(int flush_async)
if (!flush_async
|| !erts_initialized
#if defined(USE_THREADS) && !defined(ERTS_SMP)
- || !erts_equal_tids(main_thread, erts_thr_self())
+ || !erts_equal_tids(erts_main_thread, erts_thr_self())
#endif
)
return;
diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c
index 3b3b247020..598bf84c0b 100644
--- a/erts/emulator/beam/erl_lock_check.c
+++ b/erts/emulator/beam/erl_lock_check.c
@@ -113,9 +113,6 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "environ", NULL },
#endif
{ "efile_drv", "address" },
-#if defined(ENABLE_CHILD_WAITER_THREAD) || defined(ERTS_SMP)
- { "child_status", NULL },
-#endif
{ "drv_ev_state_grow", NULL, },
{ "drv_ev_state", "address" },
{ "safe_hash", "address" },
@@ -140,6 +137,8 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "mmap_init_atoms", NULL },
{ "drv_tsd", NULL },
{ "async_enq_mtx", NULL },
+ { "msacc_list_mutex", NULL },
+ { "msacc_unmanaged_mutex", NULL },
#ifdef ERTS_SMP
{ "atom_tab", NULL },
{ "misc_op_list_pre_alloc_lock", "address" },
@@ -156,9 +155,6 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "instr", NULL },
{ "alcu_allocator", "index" },
{ "mseg", NULL },
-#if HALFWORD_HEAP
- { "pmmap", NULL },
-#endif
#ifdef ERTS_SMP
{ "port_task_pre_alloc_lock", "address" },
{ "proclist_pre_alloc_lock", "address" },
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index 3c066cea7b..4b6931f848 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -172,26 +172,22 @@ BIF_RETTYPE maps_to_list_1(BIF_ALIST_1) {
*/
const Eterm *
-#if HALFWORD_HEAP
-erts_maps_get_rel(Eterm key, Eterm map, Eterm *map_base)
-#else
erts_maps_get(Eterm key, Eterm map)
-#endif
{
Uint32 hx;
- if (is_flatmap_rel(map, map_base)) {
+ if (is_flatmap(map)) {
Eterm *ks, *vs;
flatmap_t *mp;
Uint n, i;
- mp = (flatmap_t *)flatmap_val_rel(map, map_base);
+ mp = (flatmap_t *)flatmap_val(map);
n = flatmap_get_size(mp);
if (n == 0) {
return NULL;
}
- ks = (Eterm *)tuple_val_rel(mp->keys, map_base) + 1;
+ ks = (Eterm *)tuple_val(mp->keys) + 1;
vs = flatmap_get_values(mp);
if (is_immed(key)) {
@@ -203,16 +199,16 @@ erts_maps_get(Eterm key, Eterm map)
}
for (i = 0; i < n; i++) {
- if (eq_rel(ks[i], map_base, key, NULL)) {
+ if (EQ(ks[i], key)) {
return &vs[i];
}
}
return NULL;
}
- ASSERT(is_hashmap_rel(map, map_base));
+ ASSERT(is_hashmap(map));
hx = hashmap_make_hash(key);
- return erts_hashmap_get_rel(hx, key, map, map_base);
+ return erts_hashmap_get(hx, key, map);
}
BIF_RETTYPE maps_find_2(BIF_ALIST_2) {
@@ -1998,11 +1994,7 @@ Eterm* hashmap_iterator_prev(ErtsWStack* s) {
}
const Eterm *
-#if HALFWORD_HEAP
-erts_hashmap_get_rel(Uint32 hx, Eterm key, Eterm node, Eterm *map_base)
-#else
erts_hashmap_get(Uint32 hx, Eterm key, Eterm node)
-#endif
{
Eterm *ptr, hdr, *res;
Uint ix, lvl = 0;
@@ -2011,7 +2003,7 @@ erts_hashmap_get(Uint32 hx, Eterm key, Eterm node)
UseTmpHeapNoproc(2);
ASSERT(is_boxed(node));
- ptr = boxed_val_rel(node, map_base);
+ ptr = boxed_val(node);
hdr = *ptr;
ASSERT(is_header(hdr));
ASSERT(is_hashmap_header_head(hdr));
@@ -2032,15 +2024,15 @@ erts_hashmap_get(Uint32 hx, Eterm key, Eterm node)
node = ptr[ix+1];
if (is_list(node)) { /* LEAF NODE [K|V] */
- ptr = list_val_rel(node,map_base);
- res = eq_rel(CAR(ptr), map_base, key, NULL) ? &(CDR(ptr)) : NULL;
+ ptr = list_val(node);
+ res = EQ(CAR(ptr), key) ? &(CDR(ptr)) : NULL;
break;
}
hx = hashmap_shift_hash(th,hx,lvl,key);
ASSERT(is_boxed(node));
- ptr = boxed_val_rel(node, map_base);
+ ptr = boxed_val(node);
hdr = *ptr;
ASSERT(is_header(hdr));
ASSERT(!is_hashmap_header_head(hdr));
@@ -2706,32 +2698,88 @@ BIF_RETTYPE erts_internal_map_to_tuple_keys_1(BIF_ALIST_1) {
}
/*
- * erts_internal:map_type/1
+ * erts_internal:term_type/1
*
* Used in erts_debug:size/1
*/
-BIF_RETTYPE erts_internal_map_type_1(BIF_ALIST_1) {
- DECL_AM(hashmap);
- DECL_AM(hashmap_node);
- DECL_AM(flatmap);
- if (is_map(BIF_ARG_1)) {
- Eterm hdr = *(boxed_val(BIF_ARG_1));
- ASSERT(is_header(hdr));
- switch (hdr & _HEADER_MAP_SUBTAG_MASK) {
- case HAMT_SUBTAG_HEAD_FLATMAP:
- BIF_RET(AM_flatmap);
- case HAMT_SUBTAG_HEAD_ARRAY:
- case HAMT_SUBTAG_HEAD_BITMAP:
- BIF_RET(AM_hashmap);
- case HAMT_SUBTAG_NODE_BITMAP:
- BIF_RET(AM_hashmap_node);
- default:
- erts_exit(ERTS_ERROR_EXIT, "bad header");
+BIF_RETTYPE erts_internal_term_type_1(BIF_ALIST_1) {
+ Eterm obj = BIF_ARG_1;
+ switch (primary_tag(obj)) {
+ case TAG_PRIMARY_LIST:
+ BIF_RET(ERTS_MAKE_AM("list"));
+ case TAG_PRIMARY_BOXED: {
+ Eterm hdr = *boxed_val(obj);
+ ASSERT(is_header(hdr));
+ switch (hdr & _TAG_HEADER_MASK) {
+ case ARITYVAL_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("tuple"));
+ case EXPORT_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("export"));
+ case FUN_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("fun"));
+ case MAP_SUBTAG:
+ switch (MAP_HEADER_TYPE(hdr)) {
+ case MAP_HEADER_TAG_FLATMAP_HEAD :
+ BIF_RET(ERTS_MAKE_AM("flatmap"));
+ case MAP_HEADER_TAG_HAMT_HEAD_BITMAP :
+ case MAP_HEADER_TAG_HAMT_HEAD_ARRAY :
+ BIF_RET(ERTS_MAKE_AM("hashmap"));
+ case MAP_HEADER_TAG_HAMT_NODE_BITMAP :
+ BIF_RET(ERTS_MAKE_AM("hashmap_node"));
+ default:
+ erts_exit(ERTS_ABORT_EXIT, "term_type: bad map header type %d\n", MAP_HEADER_TYPE(hdr));
+ }
+ case REFC_BINARY_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("refc_binary"));
+ case HEAP_BINARY_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("heap_binary"));
+ case SUB_BINARY_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("sub_binary"));
+ case BIN_MATCHSTATE_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("matchstate"));
+ case POS_BIG_SUBTAG:
+ case NEG_BIG_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("bignum"));
+ case REF_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("reference"));
+ case EXTERNAL_REF_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("external_reference"));
+ case EXTERNAL_PID_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("external_pid"));
+ case EXTERNAL_PORT_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("external_port"));
+ case FLOAT_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("hfloat"));
+ default:
+ erts_exit(ERTS_ABORT_EXIT, "term_type: Invalid tag (0x%X)\n", hdr);
+ }
}
+ case TAG_PRIMARY_IMMED1:
+ switch (obj & _TAG_IMMED1_MASK) {
+ case _TAG_IMMED1_SMALL:
+ BIF_RET(ERTS_MAKE_AM("fixnum"));
+ case _TAG_IMMED1_PID:
+ BIF_RET(ERTS_MAKE_AM("pid"));
+ case _TAG_IMMED1_PORT:
+ BIF_RET(ERTS_MAKE_AM("port"));
+ case _TAG_IMMED1_IMMED2:
+ switch (obj & _TAG_IMMED2_MASK) {
+ case _TAG_IMMED2_ATOM:
+ BIF_RET(ERTS_MAKE_AM("atom"));
+ case _TAG_IMMED2_CATCH:
+ BIF_RET(ERTS_MAKE_AM("catch"));
+ case _TAG_IMMED2_NIL:
+ BIF_RET(ERTS_MAKE_AM("nil"));
+ default:
+ erts_exit(ERTS_ABORT_EXIT, "term_type: Invalid tag (0x%X)\n", obj);
+ }
+ default:
+ erts_exit(ERTS_ABORT_EXIT, "term_type: Invalid tag (0x%X)\n", obj);
+ }
+ default:
+ erts_exit(ERTS_ABORT_EXIT, "term_type: Invalid tag (0x%X)\n", obj);
}
- BIF_P->fvalue = BIF_ARG_1;
- BIF_ERROR(BIF_P, BADMAP);
}
/*
diff --git a/erts/emulator/beam/erl_map.h b/erts/emulator/beam/erl_map.h
index 4d9d74bc37..052fa99f03 100644
--- a/erts/emulator/beam/erl_map.h
+++ b/erts/emulator/beam/erl_map.h
@@ -57,7 +57,6 @@ typedef struct flatmap_s {
#define hashmap_size(x) (((hashmap_head_t*) hashmap_val(x))->size)
-#define hashmap_size_rel(RTERM, BASE) hashmap_size(rterm2wterm(RTERM, BASE))
#define hashmap_make_hash(Key) make_internal_hash(Key)
#define hashmap_restore_hash(Heap,Lvl,Key) \
@@ -104,23 +103,9 @@ Eterm erts_hashmap_from_array(ErtsHeapFactory*, Eterm *leafs, Uint n, int rejec
Eterm erts_hashmap_from_ks_and_vs_extra(Process *p, Eterm *ks, Eterm *vs, Uint n,
Eterm k, Eterm v);
-const Eterm *
-#if HALFWORD_HEAP
-erts_maps_get_rel(Eterm key, Eterm map, Eterm *map_base);
-# define erts_maps_get(A, B) erts_maps_get_rel(A, B, NULL)
-#else
-erts_maps_get(Eterm key, Eterm map);
-# define erts_maps_get_rel(A, B, B_BASE) erts_maps_get(A, B)
-#endif
+const Eterm *erts_maps_get(Eterm key, Eterm map);
-const Eterm *
-#if HALFWORD_HEAP
-erts_hashmap_get_rel(Uint32 hx, Eterm key, Eterm node, Eterm *map_base);
-# define erts_hashmap_get(Hx, K, M) erts_hashmap_get_rel(Hx, K, M, NULL)
-#else
-erts_hashmap_get(Uint32 hx, Eterm key, Eterm map);
-# define erts_hashmap_get_rel(Hx, K, M, M_BASE) erts_hashmap_get(Hx, K, M)
-#endif
+const Eterm *erts_hashmap_get(Uint32 hx, Eterm key, Eterm map);
/* hamt nodes v2.0
*
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index fa6b2fc613..88efb2c59f 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -33,8 +33,8 @@
#include "erl_binary.h"
#include "dtrace-wrapper.h"
-ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(message,
- ErlMessage,
+ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(message_ref,
+ ErtsMessageRef,
ERL_MESSAGE_BUF_SZ,
ERTS_ALC_T_MSG_REF)
@@ -44,27 +44,20 @@ ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(message,
#undef HARD_DEBUG
#endif
-
-
-
-#ifdef DEBUG
-static ERTS_INLINE int in_heapfrag(const Eterm* ptr, const ErlHeapFragment *bp)
+void
+init_message(void)
{
- return ((unsigned)(ptr - bp->mem) < bp->used_size);
+ init_message_ref_alloc();
}
-#endif
-
-void
-init_message(void)
+void *erts_alloc_message_ref(void)
{
- init_message_alloc();
+ return (void *) message_ref_alloc();
}
-void
-free_message(ErlMessage* mp)
+void erts_free_message_ref(void *mp)
{
- message_free(mp);
+ message_ref_free((ErtsMessageRef *) mp);
}
/* Allocate message buffer (size in words) */
@@ -74,7 +67,8 @@ new_message_buffer(Uint size)
ErlHeapFragment* bp;
bp = (ErlHeapFragment*) ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP_FRAG,
ERTS_HEAP_FRAG_SIZE(size));
- ERTS_INIT_HEAP_FRAG(bp, size);
+ ERTS_INIT_HEAP_FRAG(bp, size, size);
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] new message buffer %p\n", erts_get_current_pid(), bp->mem));
return bp;
}
@@ -203,83 +197,57 @@ free_message_buffer(ErlHeapFragment* bp)
}while (bp != NULL);
}
-static ERTS_INLINE void
-link_mbuf_to_proc(Process *proc, ErlHeapFragment *bp)
+void
+erts_cleanup_messages(ErtsMessage *msgp)
{
- if (bp) {
- /* Link the message buffer */
- bp->next = MBUF(proc);
- MBUF(proc) = bp;
- MBUF_SIZE(proc) += bp->used_size;
- FLAGS(proc) |= F_FORCE_GC;
-
- /* Move any off_heap's into the process */
- if (bp->off_heap.first != NULL) {
- struct erl_off_heap_header** next_p = &bp->off_heap.first;
- while (*next_p != NULL) {
- next_p = &((*next_p)->next);
+ ErtsMessage *mp = msgp;
+ while (mp) {
+ ErtsMessage *fmp;
+ ErlHeapFragment *bp;
+ if (is_non_value(ERL_MESSAGE_TERM(mp))) {
+ if (is_not_immed(ERL_MESSAGE_TOKEN(mp))) {
+ bp = (ErlHeapFragment *) mp->data.dist_ext->ext_endp;
+ erts_cleanup_offheap(&bp->off_heap);
}
- *next_p = MSO(proc).first;
- MSO(proc).first = bp->off_heap.first;
- bp->off_heap.first = NULL;
- OH_OVERHEAD(&(MSO(proc)), bp->off_heap.overhead);
+ if (mp->data.dist_ext)
+ erts_free_dist_ext_copy(mp->data.dist_ext);
}
+ else {
+ if (mp->data.attached != ERTS_MSG_COMBINED_HFRAG)
+ bp = mp->data.heap_frag;
+ else {
+ bp = mp->hfrag.next;
+ erts_cleanup_offheap(&mp->hfrag.off_heap);
+ }
+ if (bp)
+ free_message_buffer(bp);
+ }
+ fmp = mp;
+ mp = mp->next;
+ erts_free_message(fmp);
}
}
-Eterm
-erts_msg_distext2heap(Process *pp,
- ErtsProcLocks *plcksp,
- ErlHeapFragment **bpp,
- Eterm *tokenp,
- ErtsDistExternal *dist_extp)
+ErtsMessage *
+erts_realloc_shrink_message(ErtsMessage *mp, Uint sz, Eterm *brefs, Uint brefs_size)
{
- Eterm msg;
- Uint tok_sz = 0;
- Eterm *hp = NULL;
- ErtsHeapFactory factory;
- Sint sz;
-
- *bpp = NULL;
- sz = erts_decode_dist_ext_size(dist_extp);
- if (sz < 0)
- goto decode_error;
- if (is_not_nil(*tokenp)) {
- ErlHeapFragment *heap_frag = erts_dist_ext_trailer(dist_extp);
- tok_sz = heap_frag->used_size;
- sz += tok_sz;
- }
- if (pp) {
- ErlOffHeap *ohp;
- hp = erts_alloc_message_heap(sz, bpp, &ohp, pp, plcksp);
- }
- else {
- *bpp = new_message_buffer(sz);
- hp = (*bpp)->mem;
- }
- erts_factory_message_init(&factory, pp, hp, *bpp);
- msg = erts_decode_dist_ext(&factory, dist_extp);
- if (is_non_value(msg))
- goto decode_error;
- if (is_not_nil(*tokenp)) {
- ErlHeapFragment *heap_frag = erts_dist_ext_trailer(dist_extp);
- hp = erts_produce_heap(&factory, tok_sz, 0);
- *tokenp = copy_struct(*tokenp, tok_sz, &hp, factory.off_heap);
- erts_cleanup_offheap(&heap_frag->off_heap);
+ ErtsMessage *nmp = erts_realloc(ERTS_ALC_T_MSG, mp,
+ sizeof(ErtsMessage) + (sz - 1)*sizeof(Eterm));
+ if (nmp != mp) {
+ Eterm *sp = &mp->hfrag.mem[0];
+ Eterm *ep = sp + sz;
+ Sint offs = &nmp->hfrag.mem[0] - sp;
+ erts_offset_off_heap(&nmp->hfrag.off_heap, offs, sp, ep);
+ erts_offset_heap(&nmp->hfrag.mem[0], sz, offs, sp, ep);
+ if (brefs && brefs_size)
+ erts_offset_heap_ptr(brefs, brefs_size, offs, sp, ep);
}
- erts_free_dist_ext_copy(dist_extp);
- erts_factory_close(&factory);
- return msg;
- decode_error:
- if (is_not_nil(*tokenp)) {
- ErlHeapFragment *heap_frag = erts_dist_ext_trailer(dist_extp);
- erts_cleanup_offheap(&heap_frag->off_heap);
- }
- erts_free_dist_ext_copy(dist_extp);
- *bpp = NULL;
- return THE_NON_VALUE;
- }
+ nmp->hfrag.used_size = sz;
+ nmp->hfrag.alloc_size = sz;
+
+ return nmp;
+}
void
erts_queue_dist_message(Process *rcvr,
@@ -287,7 +255,7 @@ erts_queue_dist_message(Process *rcvr,
ErtsDistExternal *dist_ext,
Eterm token)
{
- ErlMessage* mp;
+ ErtsMessage* mp;
#ifdef USE_VM_PROBES
Sint tok_label = 0;
Sint tok_lastcnt = 0;
@@ -299,7 +267,17 @@ erts_queue_dist_message(Process *rcvr,
ERTS_SMP_LC_ASSERT(*rcvr_locks == erts_proc_lc_my_proc_locks(rcvr));
- mp = message_alloc();
+ mp = erts_alloc_message(0, NULL);
+ mp->data.dist_ext = dist_ext;
+
+ ERL_MESSAGE_TERM(mp) = THE_NON_VALUE;
+#ifdef USE_VM_PROBES
+ ERL_MESSAGE_DT_UTAG(mp) = NIL;
+ if (token == am_have_dt_utag)
+ ERL_MESSAGE_TOKEN(mp) = NIL;
+ else
+#endif
+ ERL_MESSAGE_TOKEN(mp) = token;
#ifdef ERTS_SMP
if (!(*rcvr_locks & ERTS_PROC_LOCK_MSGQ)) {
@@ -318,64 +296,46 @@ erts_queue_dist_message(Process *rcvr,
if (!(*rcvr_locks & ERTS_PROC_LOCK_MSGQ))
erts_smp_proc_unlock(rcvr, ERTS_PROC_LOCK_MSGQ);
/* Drop message if receiver is exiting or has a pending exit ... */
- if (is_not_nil(token)) {
- ErlHeapFragment *heap_frag;
- heap_frag = erts_dist_ext_trailer(mp->data.dist_ext);
- erts_cleanup_offheap(&heap_frag->off_heap);
- }
- erts_free_dist_ext_copy(dist_ext);
- message_free(mp);
+ erts_cleanup_messages(mp);
}
else
#endif
if (IS_TRACED_FL(rcvr, F_TRACE_RECEIVE)) {
/* Ahh... need to decode it in order to trace it... */
- ErlHeapFragment *mbuf;
- Eterm msg;
if (!(*rcvr_locks & ERTS_PROC_LOCK_MSGQ))
erts_smp_proc_unlock(rcvr, ERTS_PROC_LOCK_MSGQ);
- message_free(mp);
- msg = erts_msg_distext2heap(rcvr, rcvr_locks, &mbuf, &token, dist_ext);
- if (is_value(msg))
+ if (!erts_decode_dist_message(rcvr, *rcvr_locks, mp, 0))
+ erts_free_message(mp);
+ else {
+ Eterm msg = ERL_MESSAGE_TERM(mp);
+ token = ERL_MESSAGE_TOKEN(mp);
#ifdef USE_VM_PROBES
- if (DTRACE_ENABLED(message_queued)) {
- DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE);
-
- dtrace_proc_str(rcvr, receiver_name);
- if (token != NIL && token != am_have_dt_utag) {
- tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
- tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
- tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
- }
- DTRACE6(message_queued,
- receiver_name, size_object(msg), rcvr->msg.len,
- tok_label, tok_lastcnt, tok_serial);
- }
+ if (DTRACE_ENABLED(message_queued)) {
+ DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_proc_str(rcvr, receiver_name);
+ if (have_seqtrace(token)) {
+ tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
+ tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
+ tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
+ }
+ DTRACE6(message_queued,
+ receiver_name, size_object(msg), rcvr->msg.len,
+ tok_label, tok_lastcnt, tok_serial);
+ }
#endif
- erts_queue_message(rcvr, rcvr_locks, mbuf, msg, token);
+ erts_queue_message(rcvr, rcvr_locks, mp, msg, token);
+ }
}
else {
/* Enqueue message on external format */
- ERL_MESSAGE_TERM(mp) = THE_NON_VALUE;
-#ifdef USE_VM_PROBES
- ERL_MESSAGE_DT_UTAG(mp) = NIL;
- if (token == am_have_dt_utag) {
- ERL_MESSAGE_TOKEN(mp) = NIL;
- } else {
-#endif
- ERL_MESSAGE_TOKEN(mp) = token;
-#ifdef USE_VM_PROBES
- }
-#endif
- mp->next = NULL;
-
#ifdef USE_VM_PROBES
if (DTRACE_ENABLED(message_queued)) {
DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE);
dtrace_proc_str(rcvr, receiver_name);
- if (token != NIL && token != am_have_dt_utag) {
+ if (have_seqtrace(token)) {
tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
@@ -388,7 +348,7 @@ erts_queue_dist_message(Process *rcvr,
tok_label, tok_lastcnt, tok_serial);
}
#endif
- mp->data.dist_ext = dist_ext;
+
LINK_MESSAGE(rcvr, mp);
if (!(*rcvr_locks & ERTS_PROC_LOCK_MSGQ))
@@ -408,9 +368,9 @@ erts_queue_dist_message(Process *rcvr,
static Sint
queue_message(Process *c_p,
Process* receiver,
- ErtsProcLocks *receiver_locks,
erts_aint32_t *receiver_state,
- ErlHeapFragment* bp,
+ ErtsProcLocks *receiver_locks,
+ ErtsMessage* mp,
Eterm message,
Eterm seq_trace_token
#ifdef USE_VM_PROBES
@@ -419,31 +379,24 @@ queue_message(Process *c_p,
)
{
Sint res;
- ErlMessage* mp;
int locked_msgq = 0;
- erts_aint_t state;
-
-#ifndef ERTS_SMP
- ASSERT(bp != NULL || receiver->mbuf == NULL);
-#endif
+ erts_aint32_t state;
ERTS_SMP_LC_ASSERT(*receiver_locks == erts_proc_lc_my_proc_locks(receiver));
- mp = message_alloc();
-
- if (receiver_state)
- state = *receiver_state;
- else
- state = erts_smp_atomic32_read_acqb(&receiver->state);
-
#ifdef ERTS_SMP
- if (state & (ERTS_PSFLG_EXITING|ERTS_PSFLG_PENDING_EXIT))
- goto exiting;
-
if (!(*receiver_locks & ERTS_PROC_LOCK_MSGQ)) {
if (erts_smp_proc_trylock(receiver, ERTS_PROC_LOCK_MSGQ) == EBUSY) {
ErtsProcLocks need_locks = ERTS_PROC_LOCK_MSGQ;
+
+ if (receiver_state)
+ state = *receiver_state;
+ else
+ state = erts_smp_atomic32_read_nob(&receiver->state);
+ if (state & (ERTS_PSFLG_EXITING|ERTS_PSFLG_PENDING_EXIT))
+ goto exiting;
+
if (*receiver_locks & ERTS_PROC_LOCK_STATUS) {
erts_smp_proc_unlock(receiver, ERTS_PROC_LOCK_STATUS);
need_locks |= ERTS_PROC_LOCK_STATUS;
@@ -451,13 +404,12 @@ queue_message(Process *c_p,
erts_smp_proc_lock(receiver, need_locks);
}
locked_msgq = 1;
- state = erts_smp_atomic32_read_nob(&receiver->state);
- if (receiver_state)
- *receiver_state = state;
}
#endif
+ state = erts_smp_atomic32_read_nob(&receiver->state);
+
if (state & (ERTS_PSFLG_PENDING_EXIT|ERTS_PSFLG_EXITING)) {
#ifdef ERTS_SMP
exiting:
@@ -465,9 +417,7 @@ queue_message(Process *c_p,
/* Drop message if receiver is exiting or has a pending exit... */
if (locked_msgq)
erts_smp_proc_unlock(receiver, ERTS_PROC_LOCK_MSGQ);
- if (bp)
- free_message_buffer(bp);
- message_free(mp);
+ erts_cleanup_messages(mp);
return 0;
}
@@ -476,13 +426,9 @@ queue_message(Process *c_p,
#ifdef USE_VM_PROBES
ERL_MESSAGE_DT_UTAG(mp) = dt_utag;
#endif
- mp->next = NULL;
- mp->data.heap_frag = bp;
-#ifndef ERTS_SMP
res = receiver->msg.len;
-#else
- res = receiver->msg_inq.len;
+#ifdef ERTS_SMP
if (*receiver_locks & ERTS_PROC_LOCK_MAIN) {
/*
* We move 'in queue' to 'private queue' and place
@@ -492,7 +438,7 @@ queue_message(Process *c_p,
* we don't need to include the 'in queue' in
* the root set when garbage collecting.
*/
- res += receiver->msg.len;
+ res += receiver->msg_inq.len;
ERTS_SMP_MSGQ_MV_INQ2PRIVQ(receiver);
LINK_MESSAGE_PRIVQ(receiver, mp);
}
@@ -544,19 +490,19 @@ queue_message(Process *c_p,
void
#ifdef USE_VM_PROBES
erts_queue_message_probe(Process* receiver, ErtsProcLocks *receiver_locks,
- ErlHeapFragment* bp,
+ ErtsMessage* mp,
Eterm message, Eterm seq_trace_token, Eterm dt_utag)
#else
erts_queue_message(Process* receiver, ErtsProcLocks *receiver_locks,
- ErlHeapFragment* bp,
+ ErtsMessage* mp,
Eterm message, Eterm seq_trace_token)
#endif
{
queue_message(NULL,
receiver,
- receiver_locks,
NULL,
- bp,
+ receiver_locks,
+ mp,
message,
seq_trace_token
#ifdef USE_VM_PROBES
@@ -566,245 +512,37 @@ erts_queue_message(Process* receiver, ErtsProcLocks *receiver_locks,
}
void
-erts_link_mbuf_to_proc(struct process *proc, ErlHeapFragment *bp)
+erts_link_mbuf_to_proc(Process *proc, ErlHeapFragment *first_bp)
{
- Eterm* htop = HEAP_TOP(proc);
-
- link_mbuf_to_proc(proc, bp);
- if (htop < HEAP_LIMIT(proc)) {
- *htop = make_pos_bignum_header(HEAP_LIMIT(proc)-htop-1);
- HEAP_TOP(proc) = HEAP_LIMIT(proc);
- }
-}
-
-/*
- * Moves content of message buffer attached to a message into a heap.
- * The message buffer is deallocated.
- */
-void
-erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg)
-{
- struct erl_off_heap_header* oh;
- Eterm term, token, *fhp, *hp;
- Sint offs;
- Uint sz;
- ErlHeapFragment *bp;
-#ifdef USE_VM_PROBES
- Eterm utag;
-#endif
-
-#ifdef HARD_DEBUG
- struct erl_off_heap_header* dbg_oh_start = off_heap->first;
- Eterm dbg_term, dbg_token;
- ErlHeapFragment *dbg_bp;
- Uint *dbg_hp, *dbg_thp_start;
- Uint dbg_term_sz, dbg_token_sz;
-#ifdef USE_VM_PROBES
- Eterm dbg_utag;
- Uint dbg_utag_sz;
-#endif
-#endif
-
- bp = msg->data.heap_frag;
- term = ERL_MESSAGE_TERM(msg);
- token = ERL_MESSAGE_TOKEN(msg);
-#ifdef USE_VM_PROBES
- utag = ERL_MESSAGE_DT_UTAG(msg);
-#endif
- if (!bp) {
-#ifdef USE_VM_PROBES
- ASSERT(is_immed(term) && is_immed(token) && is_immed(utag));
-#else
- ASSERT(is_immed(term) && is_immed(token));
-#endif
- return;
- }
-
-#ifdef HARD_DEBUG
- dbg_term_sz = size_object(term);
- dbg_token_sz = size_object(token);
- dbg_bp = new_message_buffer(dbg_term_sz + dbg_token_sz);
-#ifdef USE_VM_PROBES
- dbg_utag_sz = size_object(utag);
- dbg_bp = new_message_buffer(dbg_term_sz + dbg_token_sz + dbg_utag_sz );
-#endif
- /*ASSERT(dbg_term_sz + dbg_token_sz == erts_msg_used_frag_sz(msg));
- Copied size may be smaller due to removed SubBins's or garbage.
- Copied size may be larger due to duplicated shared terms.
- */
- dbg_hp = dbg_bp->mem;
- dbg_term = copy_struct(term, dbg_term_sz, &dbg_hp, &dbg_bp->off_heap);
- dbg_token = copy_struct(token, dbg_token_sz, &dbg_hp, &dbg_bp->off_heap);
-#ifdef USE_VM_PROBES
- dbg_utag = copy_struct(utag, dbg_utag_sz, &dbg_hp, &dbg_bp->off_heap);
-#endif
- dbg_thp_start = *hpp;
-#endif
-
- if (bp->next != NULL) {
- move_multi_frags(hpp, off_heap, bp, msg->m,
-#ifdef USE_VM_PROBES
- 3
-#else
- 2
-#endif
- );
- goto copy_done;
- }
-
- OH_OVERHEAD(off_heap, bp->off_heap.overhead);
- sz = bp->used_size;
-
- ASSERT(is_immed(term) || in_heapfrag(ptr_val(term),bp));
- ASSERT(is_immed(token) || in_heapfrag(ptr_val(token),bp));
-
- fhp = bp->mem;
- hp = *hpp;
- offs = hp - fhp;
-
- oh = NULL;
- while (sz--) {
- Uint cpy_sz;
- Eterm val = *fhp++;
-
- switch (primary_tag(val)) {
- case TAG_PRIMARY_IMMED1:
- *hp++ = val;
- break;
- case TAG_PRIMARY_LIST:
- case TAG_PRIMARY_BOXED:
- ASSERT(in_heapfrag(ptr_val(val), bp));
- *hp++ = offset_ptr(val, offs);
- break;
- case TAG_PRIMARY_HEADER:
- *hp++ = val;
- switch (val & _HEADER_SUBTAG_MASK) {
- case ARITYVAL_SUBTAG:
- break;
- case REFC_BINARY_SUBTAG:
- case FUN_SUBTAG:
- case EXTERNAL_PID_SUBTAG:
- case EXTERNAL_PORT_SUBTAG:
- case EXTERNAL_REF_SUBTAG:
- oh = (struct erl_off_heap_header*) (hp-1);
- cpy_sz = thing_arityval(val);
- goto cpy_words;
- default:
- cpy_sz = header_arity(val);
-
- cpy_words:
- ASSERT(sz >= cpy_sz);
- sz -= cpy_sz;
- while (cpy_sz >= 8) {
- cpy_sz -= 8;
- *hp++ = *fhp++;
- *hp++ = *fhp++;
- *hp++ = *fhp++;
- *hp++ = *fhp++;
- *hp++ = *fhp++;
- *hp++ = *fhp++;
- *hp++ = *fhp++;
- *hp++ = *fhp++;
- }
- switch (cpy_sz) {
- case 7: *hp++ = *fhp++;
- case 6: *hp++ = *fhp++;
- case 5: *hp++ = *fhp++;
- case 4: *hp++ = *fhp++;
- case 3: *hp++ = *fhp++;
- case 2: *hp++ = *fhp++;
- case 1: *hp++ = *fhp++;
- default: break;
+ if (first_bp) {
+ ErlHeapFragment *bp = first_bp;
+
+ while (1) {
+ /* Move any off_heap's into the process */
+ if (bp->off_heap.first != NULL) {
+ struct erl_off_heap_header** next_p = &bp->off_heap.first;
+ while (*next_p != NULL) {
+ next_p = &((*next_p)->next);
}
- if (oh) {
- /* Add to offheap list */
- oh->next = off_heap->first;
- off_heap->first = oh;
- ASSERT(*hpp <= (Eterm*)oh);
- ASSERT(hp > (Eterm*)oh);
- oh = NULL;
- }
- break;
+ *next_p = MSO(proc).first;
+ MSO(proc).first = bp->off_heap.first;
+ bp->off_heap.first = NULL;
+ OH_OVERHEAD(&(MSO(proc)), bp->off_heap.overhead);
}
- break;
+ MBUF_SIZE(proc) += bp->used_size;
+ if (!bp->next)
+ break;
+ bp = bp->next;
}
- }
-
- ASSERT(bp->used_size == hp - *hpp);
- *hpp = hp;
- if (is_not_immed(token)) {
- ASSERT(in_heapfrag(ptr_val(token), bp));
- ERL_MESSAGE_TOKEN(msg) = offset_ptr(token, offs);
-#ifdef HARD_DEBUG
- ASSERT(dbg_thp_start <= ptr_val(ERL_MESSAGE_TOKEN(msg)));
- ASSERT(hp > ptr_val(ERL_MESSAGE_TOKEN(msg)));
-#endif
- }
-
- if (is_not_immed(term)) {
- ASSERT(in_heapfrag(ptr_val(term),bp));
- ERL_MESSAGE_TERM(msg) = offset_ptr(term, offs);
-#ifdef HARD_DEBUG
- ASSERT(dbg_thp_start <= ptr_val(ERL_MESSAGE_TERM(msg)));
- ASSERT(hp > ptr_val(ERL_MESSAGE_TERM(msg)));
-#endif
- }
-#ifdef USE_VM_PROBES
- if (is_not_immed(utag)) {
- ASSERT(in_heapfrag(ptr_val(utag), bp));
- ERL_MESSAGE_DT_UTAG(msg) = offset_ptr(utag, offs);
-#ifdef HARD_DEBUG
- ASSERT(dbg_thp_start <= ptr_val(ERL_MESSAGE_DT_UTAG(msg)));
- ASSERT(hp > ptr_val(ERL_MESSAGE_DT_UTAG(msg)));
-#endif
- }
-#endif
-
-copy_done:
-
-#ifdef HARD_DEBUG
- {
- int i, j;
- ErlHeapFragment* frag;
- {
- struct erl_off_heap_header* dbg_oh = off_heap->first;
- i = j = 0;
- while (dbg_oh != dbg_oh_start) {
- dbg_oh = dbg_oh->next;
- i++;
- }
- for (frag=bp; frag; frag=frag->next) {
- dbg_oh = frag->off_heap.first;
- while (dbg_oh) {
- dbg_oh = dbg_oh->next;
- j++;
- }
- }
- ASSERT(i == j);
- }
+ /* Link the message buffer */
+ bp->next = MBUF(proc);
+ MBUF(proc) = first_bp;
}
-#endif
-
-
- bp->off_heap.first = NULL;
- free_message_buffer(bp);
- msg->data.heap_frag = NULL;
-
-#ifdef HARD_DEBUG
- ASSERT(eq(ERL_MESSAGE_TERM(msg), dbg_term));
- ASSERT(eq(ERL_MESSAGE_TOKEN(msg), dbg_token));
-#ifdef USE_VM_PROBES
- ASSERT(eq(ERL_MESSAGE_DT_UTAG(msg), dbg_utag));
-#endif
- free_message_buffer(dbg_bp);
-#endif
-
}
-
Uint
-erts_msg_attached_data_size_aux(ErlMessage *msg)
+erts_msg_attached_data_size_aux(ErtsMessage *msg)
{
Sint sz;
ASSERT(is_non_value(ERL_MESSAGE_TERM(msg)));
@@ -833,29 +571,87 @@ erts_msg_attached_data_size_aux(ErlMessage *msg)
return sz;
}
-void
-erts_move_msg_attached_data_to_heap(ErtsHeapFactory* factory,
- ErlMessage *msg)
+ErtsMessage *
+erts_try_alloc_message_on_heap(Process *pp,
+ erts_aint32_t *psp,
+ ErtsProcLocks *plp,
+ Uint sz,
+ Eterm **hpp,
+ ErlOffHeap **ohpp,
+ int *on_heap_p)
{
- if (is_value(ERL_MESSAGE_TERM(msg)))
- erts_move_msg_mbuf_to_heap(&factory->hp, factory->off_heap, msg);
- else if (msg->data.dist_ext) {
- ASSERT(msg->data.dist_ext->heap_size >= 0);
- if (is_not_nil(ERL_MESSAGE_TOKEN(msg))) {
- ErlHeapFragment *heap_frag;
- heap_frag = erts_dist_ext_trailer(msg->data.dist_ext);
- ERL_MESSAGE_TOKEN(msg) = copy_struct(ERL_MESSAGE_TOKEN(msg),
- heap_frag->used_size,
- &factory->hp,
- factory->off_heap);
- erts_cleanup_offheap(&heap_frag->off_heap);
+#ifdef ERTS_SMP
+ int locked_main = 0;
+#endif
+ ErtsMessage *mp;
+
+ ASSERT(!(*psp & ERTS_PSFLG_OFF_HEAP_MSGQ));
+
+ if (
+#if defined(ERTS_SMP)
+ *plp & ERTS_PROC_LOCK_MAIN
+#else
+ 1
+#endif
+ ) {
+#ifdef ERTS_SMP
+ try_on_heap:
+#endif
+ if ((*psp & (ERTS_PSFLG_EXITING|ERTS_PSFLG_PENDING_EXIT))
+ || (pp->flags & F_DISABLE_GC)
+ || HEAP_LIMIT(pp) - HEAP_TOP(pp) <= sz) {
+ /*
+ * The heap is either potentially in an inconsistent
+ * state, or not large enough.
+ */
+#ifdef ERTS_SMP
+ if (locked_main) {
+ *plp &= ~ERTS_PROC_LOCK_MAIN;
+ erts_smp_proc_unlock(pp, ERTS_PROC_LOCK_MAIN);
+ }
+#endif
+ goto in_message_fragment;
}
- ERL_MESSAGE_TERM(msg) = erts_decode_dist_ext(factory,
- msg->data.dist_ext);
- erts_free_dist_ext_copy(msg->data.dist_ext);
- msg->data.dist_ext = NULL;
+
+ *hpp = HEAP_TOP(pp);
+ HEAP_TOP(pp) = *hpp + sz;
+ *ohpp = &MSO(pp);
+ mp = erts_alloc_message(0, NULL);
+ mp->data.attached = NULL;
+ *on_heap_p = !0;
+ }
+#ifdef ERTS_SMP
+ else if (erts_smp_proc_trylock(pp, ERTS_PROC_LOCK_MAIN) == 0) {
+ locked_main = 1;
+ *psp = erts_smp_atomic32_read_nob(&pp->state);
+ *plp |= ERTS_PROC_LOCK_MAIN;
+ goto try_on_heap;
}
- /* else: bad external detected when calculating size */
+#endif
+ else {
+ in_message_fragment:
+ if (!((*psp) & ERTS_PSFLG_ON_HEAP_MSGQ)) {
+ mp = erts_alloc_message(sz, hpp);
+ *ohpp = sz == 0 ? NULL : &mp->hfrag.off_heap;
+ }
+ else {
+ mp = erts_alloc_message(0, NULL);
+ if (!sz) {
+ *hpp = NULL;
+ *ohpp = NULL;
+ }
+ else {
+ ErlHeapFragment *bp;
+ bp = new_message_buffer(sz);
+ *hpp = &bp->mem[0];
+ mp->data.heap_frag = bp;
+ *ohpp = &bp->off_heap;
+ }
+ }
+ *on_heap_p = 0;
+ }
+
+ return mp;
}
/*
@@ -870,7 +666,8 @@ erts_send_message(Process* sender,
unsigned flags)
{
Uint msize;
- ErlHeapFragment* bp = NULL;
+ ErtsMessage* mp;
+ ErlOffHeap *ohp;
Eterm token = NIL;
Sint res = 0;
#ifdef USE_VM_PROBES
@@ -879,67 +676,96 @@ erts_send_message(Process* sender,
Sint tok_label = 0;
Sint tok_lastcnt = 0;
Sint tok_serial = 0;
+ Eterm utag = NIL;
+#endif
+ erts_aint32_t receiver_state;
+#ifdef SHCOPY_SEND
+ erts_shcopy_t info;
#endif
BM_STOP_TIMER(system);
BM_MESSAGE(message,sender,receiver);
BM_START_TIMER(send);
- #ifdef USE_VM_PROBES
+#ifdef USE_VM_PROBES
*sender_name = *receiver_name = '\0';
- if (DTRACE_ENABLED(message_send)) {
+ if (DTRACE_ENABLED(message_send)) {
erts_snprintf(sender_name, sizeof(DTRACE_CHARBUF_NAME(sender_name)),
"%T", sender->common.id);
erts_snprintf(receiver_name, sizeof(DTRACE_CHARBUF_NAME(receiver_name)),
"%T", receiver->common.id);
}
#endif
+
+ receiver_state = erts_smp_atomic32_read_nob(&receiver->state);
+
if (SEQ_TRACE_TOKEN(sender) != NIL && !(flags & ERTS_SND_FLG_NO_SEQ_TRACE)) {
Eterm* hp;
Eterm stoken = SEQ_TRACE_TOKEN(sender);
Uint seq_trace_size = 0;
#ifdef USE_VM_PROBES
Uint dt_utag_size = 0;
- Eterm utag = NIL;
#endif
-
- BM_SWAP_TIMER(send,size);
- msize = size_object(message);
- BM_SWAP_TIMER(size,send);
-
-#ifdef USE_VM_PROBES
- if (stoken != am_have_dt_utag) {
-#endif
-
+ BM_SWAP_TIMER(send,size);
+
+ /* SHCOPY corrupts the heap between
+ * copy_shared_calculate, and
+ * copy_shared_perform. (it inserts move_markers like the gc).
+ * Make sure we don't use the heap between those instances.
+ */
+ if (have_seqtrace(stoken)) {
seq_trace_update_send(sender);
seq_trace_output(stoken, message, SEQ_TRACE_SEND,
receiver->common.id, sender);
seq_trace_size = 6; /* TUPLE5 */
-#ifdef USE_VM_PROBES
- }
- if (DT_UTAG_FLAGS(sender) & DT_UTAG_SPREADING) {
- dt_utag_size = size_object(DT_UTAG(sender));
- } else if (stoken == am_have_dt_utag ) {
- stoken = NIL;
}
+#ifdef USE_VM_PROBES
+ if (DT_UTAG_FLAGS(sender) & DT_UTAG_SPREADING) {
+ dt_utag_size = size_object(DT_UTAG(sender));
+ } else if (stoken == am_have_dt_utag ) {
+ stoken = NIL;
+ }
+#endif
+
+#ifdef SHCOPY_SEND
+ INITIALIZE_SHCOPY(info);
+ msize = copy_shared_calculate(message, &info);
+#else
+ msize = size_object(message);
#endif
+ BM_SWAP_TIMER(size,send);
- bp = new_message_buffer(msize + seq_trace_size
+ mp = erts_alloc_message_heap_state(receiver,
+ &receiver_state,
+ receiver_locks,
+ (msize
#ifdef USE_VM_PROBES
- + dt_utag_size
+ + dt_utag_size
#endif
- );
- hp = bp->mem;
+ + seq_trace_size),
+ &hp,
+ &ohp);
BM_SWAP_TIMER(send,copy);
- token = copy_struct(stoken,
- seq_trace_size,
- &hp,
- &bp->off_heap);
- message = copy_struct(message, msize, &hp, &bp->off_heap);
+#ifdef SHCOPY_SEND
+ if (is_not_immed(message))
+ message = copy_shared_perform(message, msize, &info, &hp, ohp);
+ DESTROY_SHCOPY(info);
+#else
+ if (is_not_immed(message))
+ message = copy_struct(message, msize, &hp, ohp);
+#endif
+ if (is_immed(stoken))
+ token = stoken;
+ else
+ token = copy_struct(stoken, seq_trace_size, &hp, ohp);
+
#ifdef USE_VM_PROBES
if (DT_UTAG_FLAGS(sender) & DT_UTAG_SPREADING) {
- utag = copy_struct(DT_UTAG(sender), dt_utag_size, &hp, &bp->off_heap);
+ if (is_immed(DT_UTAG(sender)))
+ utag = DT_UTAG(sender);
+ else
+ utag = copy_struct(DT_UTAG(sender), dt_utag_size, &hp, ohp);
#ifdef DTRACE_TAG_HARDDEBUG
erts_fprintf(stderr,
"Dtrace -> (%T) Spreading tag (%T) with "
@@ -952,7 +778,7 @@ erts_send_message(Process* sender,
#ifdef USE_VM_PROBES
if (DTRACE_ENABLED(message_send)) {
- if (stoken != NIL && stoken != am_have_dt_utag) {
+ if (have_seqtrace(stoken)) {
tok_label = signed_val(SEQ_TRACE_T_LABEL(stoken));
tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(stoken));
tok_serial = signed_val(SEQ_TRACE_T_SERIAL(stoken));
@@ -961,103 +787,63 @@ erts_send_message(Process* sender,
msize, tok_label, tok_lastcnt, tok_serial);
}
#endif
- res = queue_message(NULL,
- receiver,
- receiver_locks,
- NULL,
- bp,
- message,
- token
-#ifdef USE_VM_PROBES
- , utag
-#endif
- );
- BM_SWAP_TIMER(send,system);
- } else if (sender == receiver) {
- /* Drop message if receiver has a pending exit ... */
-#ifdef ERTS_SMP
- ErtsProcLocks need_locks = (~(*receiver_locks)
- & (ERTS_PROC_LOCK_MSGQ
- | ERTS_PROC_LOCK_STATUS));
- if (need_locks) {
- *receiver_locks |= need_locks;
- if (erts_smp_proc_trylock(receiver, need_locks) == EBUSY) {
- if (need_locks == ERTS_PROC_LOCK_MSGQ) {
- erts_smp_proc_unlock(receiver, ERTS_PROC_LOCK_STATUS);
- need_locks = ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS;
- }
- erts_smp_proc_lock(receiver, need_locks);
- }
+ } else {
+ Eterm *hp;
+
+ if (receiver == sender && !(receiver_state & ERTS_PSFLG_OFF_HEAP_MSGQ)) {
+ mp = erts_alloc_message(0, NULL);
+ msize = 0;
}
- if (!ERTS_PROC_PENDING_EXIT(receiver))
+ else {
+ BM_SWAP_TIMER(send,size);
+#ifdef SHCOPY_SEND
+ INITIALIZE_SHCOPY(info);
+ msize = copy_shared_calculate(message, &info);
+#else
+ msize = size_object(message);
#endif
- {
- ErlMessage* mp = message_alloc();
-
- DTRACE6(message_send, sender_name, receiver_name,
- size_object(message), tok_label, tok_lastcnt, tok_serial);
- mp->data.attached = NULL;
- ERL_MESSAGE_TERM(mp) = message;
- ERL_MESSAGE_TOKEN(mp) = NIL;
-#ifdef USE_VM_PROBES
- ERL_MESSAGE_DT_UTAG(mp) = NIL;
+ BM_SWAP_TIMER(size,send);
+
+ mp = erts_alloc_message_heap_state(receiver,
+ &receiver_state,
+ receiver_locks,
+ msize,
+ &hp,
+ &ohp);
+ BM_SWAP_TIMER(send,copy);
+#ifdef SHCOPY_SEND
+ if (is_not_immed(message))
+ message = copy_shared_perform(message, msize, &info, &hp, ohp);
+ DESTROY_SHCOPY(info);
+#else
+ if (is_not_immed(message))
+ message = copy_struct(message, msize, &hp, ohp);
#endif
- mp->next = NULL;
- /*
- * We move 'in queue' to 'private queue' and place
- * message at the end of 'private queue' in order
- * to ensure that the 'in queue' doesn't contain
- * references into the heap. By ensuring this,
- * we don't need to include the 'in queue' in
- * the root set when garbage collecting.
- */
-
- ERTS_SMP_MSGQ_MV_INQ2PRIVQ(receiver);
- LINK_MESSAGE_PRIVQ(receiver, mp);
-
- res = receiver->msg.len;
-
- if (IS_TRACED_FL(receiver, F_TRACE_RECEIVE)) {
- trace_receive(receiver, message);
- }
+ BM_MESSAGE_COPIED(msz);
+ BM_SWAP_TIMER(copy,send);
}
- BM_SWAP_TIMER(send,system);
- } else {
- ErlOffHeap *ohp;
- Eterm *hp;
- erts_aint32_t state;
-
- BM_SWAP_TIMER(send,size);
- msize = size_object(message);
- BM_SWAP_TIMER(size,send);
- hp = erts_alloc_message_heap_state(msize,
- &bp,
- &ohp,
- receiver,
- receiver_locks,
- &state);
- BM_SWAP_TIMER(send,copy);
- message = copy_struct(message, msize, &hp, ohp);
- BM_MESSAGE_COPIED(msz);
- BM_SWAP_TIMER(copy,send);
DTRACE6(message_send, sender_name, receiver_name,
msize, tok_label, tok_lastcnt, tok_serial);
- res = queue_message(sender,
- receiver,
- receiver_locks,
- &state,
- bp,
- message,
- token
+ }
+
+ res = queue_message(sender,
+ receiver,
+ &receiver_state,
+ receiver_locks,
+ mp,
+ message,
+ token
#ifdef USE_VM_PROBES
- , NIL
+ , utag
#endif
- );
- BM_SWAP_TIMER(send,system);
- }
- return res;
+ );
+
+ BM_SWAP_TIMER(send,system);
+
+ return res;
}
+
/*
* This function delivers an EXIT message to a process
* which is trapping EXITs.
@@ -1075,46 +861,572 @@ erts_deliver_exit_message(Eterm from, Process *to, ErtsProcLocks *to_locksp,
Uint sz_from;
Eterm* hp;
Eterm temptoken;
- ErlHeapFragment* bp = NULL;
-
- if (token != NIL
-#ifdef USE_VM_PROBES
- && token != am_have_dt_utag
+ ErtsMessage* mp;
+ ErlOffHeap *ohp;
+#ifdef SHCOPY_SEND
+ erts_shcopy_t info;
#endif
- ) {
+ if (have_seqtrace(token)) {
ASSERT(is_tuple(token));
- sz_reason = size_object(reason);
sz_token = size_object(token);
sz_from = size_object(from);
- bp = new_message_buffer(sz_reason + sz_from + sz_token + 4);
- hp = bp->mem;
- mess = copy_struct(reason, sz_reason, &hp, &bp->off_heap);
- from_copy = copy_struct(from, sz_from, &hp, &bp->off_heap);
+#ifdef SHCOPY_SEND
+ INITIALIZE_SHCOPY(info);
+ sz_reason = copy_shared_calculate(reason, &info);
+#else
+ sz_reason = size_object(reason);
+#endif
+ mp = erts_alloc_message_heap(to, to_locksp,
+ sz_reason + sz_from + sz_token + 4,
+ &hp, &ohp);
+#ifdef SHCOPY_SEND
+ mess = copy_shared_perform(reason, sz_reason, &info, &hp, ohp);
+ DESTROY_SHCOPY(info);
+#else
+ mess = copy_struct(reason, sz_reason, &hp, ohp);
+#endif
+ from_copy = copy_struct(from, sz_from, &hp, ohp);
save = TUPLE3(hp, am_EXIT, from_copy, mess);
hp += 4;
/* the trace token must in this case be updated by the caller */
seq_trace_output(token, save, SEQ_TRACE_SEND, to->common.id, NULL);
- temptoken = copy_struct(token, sz_token, &hp, &bp->off_heap);
- erts_queue_message(to, to_locksp, bp, save, temptoken);
+ temptoken = copy_struct(token, sz_token, &hp, ohp);
+ erts_queue_message(to, to_locksp, mp, save, temptoken);
} else {
- ErlOffHeap *ohp;
- sz_reason = size_object(reason);
sz_from = IS_CONST(from) ? 0 : size_object(from);
+#ifdef SHCOPY_SEND
+ INITIALIZE_SHCOPY(info);
+ sz_reason = copy_shared_calculate(reason, &info);
+#else
+ sz_reason = size_object(reason);
+#endif
+ mp = erts_alloc_message_heap(to, to_locksp,
+ sz_reason+sz_from+4, &hp, &ohp);
- hp = erts_alloc_message_heap(sz_reason+sz_from+4,
- &bp,
- &ohp,
- to,
- to_locksp);
-
+#ifdef SHCOPY_SEND
+ mess = copy_shared_perform(reason, sz_reason, &info, &hp, ohp);
+ DESTROY_SHCOPY(info);
+#else
mess = copy_struct(reason, sz_reason, &hp, ohp);
+#endif
from_copy = (IS_CONST(from)
? from
: copy_struct(from, sz_from, &hp, ohp));
save = TUPLE3(hp, am_EXIT, from_copy, mess);
- erts_queue_message(to, to_locksp, bp, save, NIL);
+ erts_queue_message(to, to_locksp, mp, save, NIL);
+ }
+}
+
+void erts_save_message_in_proc(Process *p, ErtsMessage *msgp)
+{
+ ErlHeapFragment *hfp;
+
+ if (msgp->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ hfp = &msgp->hfrag;
+ else if (msgp->data.attached) {
+ hfp = msgp->data.heap_frag;
+ }
+ else {
+ erts_free_message(msgp);
+ return; /* Nothing to save */
+ }
+
+ while (1) {
+ struct erl_off_heap_header *ohhp = hfp->off_heap.first;
+ if (ohhp) {
+ for ( ; ohhp->next; ohhp = ohhp->next)
+ ;
+ ohhp->next = p->off_heap.first;
+ p->off_heap.first = hfp->off_heap.first;
+ hfp->off_heap.first = NULL;
+ }
+ p->off_heap.overhead += hfp->off_heap.overhead;
+ hfp->off_heap.overhead = 0;
+ p->mbuf_sz += hfp->used_size;
+
+ if (!hfp->next)
+ break;
+ hfp = hfp->next;
+ }
+
+ msgp->next = p->msg_frag;
+ p->msg_frag = msgp;
+}
+
+Sint
+erts_move_messages_off_heap(Process *c_p)
+{
+ int reds = 1;
+ /*
+ * Move all messages off heap. This *only* occurs when the
+ * process had off heap message disabled and just enabled
+ * it...
+ */
+ ErtsMessage *mp;
+
+ reds += c_p->msg.len / 10;
+
+ ASSERT(erts_smp_atomic32_read_nob(&c_p->state)
+ & ERTS_PSFLG_OFF_HEAP_MSGQ);
+ ASSERT(c_p->flags & F_OFF_HEAP_MSGQ_CHNG);
+
+ for (mp = c_p->msg.first; mp; mp = mp->next) {
+ Uint msg_sz, token_sz;
+#ifdef USE_VM_PROBES
+ Uint utag_sz;
+#endif
+ Eterm *hp;
+ ErlHeapFragment *hfrag;
+
+ if (mp->data.attached)
+ continue;
+
+ if (is_immed(ERL_MESSAGE_TERM(mp))
+#ifdef USE_VM_PROBES
+ && is_immed(ERL_MESSAGE_DT_UTAG(mp))
+#endif
+ && is_not_immed(ERL_MESSAGE_TOKEN(mp)))
+ continue;
+
+ /*
+ * The message refers into the heap. Copy the message
+ * from the heap into a heap fragment and attach
+ * it to the message...
+ */
+ msg_sz = size_object(ERL_MESSAGE_TERM(mp));
+#ifdef USE_VM_PROBES
+ utag_sz = size_object(ERL_MESSAGE_DT_UTAG(mp));
+#endif
+ token_sz = size_object(ERL_MESSAGE_TOKEN(mp));
+
+ hfrag = new_message_buffer(msg_sz
+#ifdef USE_VM_PROBES
+ + utag_sz
+#endif
+ + token_sz);
+ hp = hfrag->mem;
+ if (is_not_immed(ERL_MESSAGE_TERM(mp)))
+ ERL_MESSAGE_TERM(mp) = copy_struct(ERL_MESSAGE_TERM(mp),
+ msg_sz, &hp,
+ &hfrag->off_heap);
+ if (is_not_immed(ERL_MESSAGE_TOKEN(mp)))
+ ERL_MESSAGE_TOKEN(mp) = copy_struct(ERL_MESSAGE_TOKEN(mp),
+ token_sz, &hp,
+ &hfrag->off_heap);
+#ifdef USE_VM_PROBES
+ if (is_not_immed(ERL_MESSAGE_DT_UTAG(mp)))
+ ERL_MESSAGE_DT_UTAG(mp) = copy_struct(ERL_MESSAGE_DT_UTAG(mp),
+ utag_sz, &hp,
+ &hfrag->off_heap);
+#endif
+ mp->data.heap_frag = hfrag;
+ reds += 1;
+ }
+
+ return reds;
+}
+
+Sint
+erts_complete_off_heap_message_queue_change(Process *c_p)
+{
+ int reds = 1;
+
+ ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN == erts_proc_lc_my_proc_locks(c_p));
+ ASSERT(c_p->flags & F_OFF_HEAP_MSGQ_CHNG);
+ ASSERT(erts_smp_atomic32_read_nob(&c_p->state) & ERTS_PSFLG_OFF_HEAP_MSGQ);
+
+ /*
+ * This job was first initiated when the process changed to off heap
+ * message queue management. Since then ERTS_PSFLG_OFF_HEAP_MSGQ
+ * has been set. However, the management state might have been changed
+ * again (multiple times) since then. Check users last requested state
+ * (the flags F_OFF_HEAP_MSGQ, and F_ON_HEAP_MSGQ), and make the state
+ * consistent with that.
+ */
+
+ if (!(c_p->flags & F_OFF_HEAP_MSGQ))
+ erts_smp_atomic32_read_band_nob(&c_p->state,
+ ~ERTS_PSFLG_OFF_HEAP_MSGQ);
+ else {
+ reds += 2;
+ erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ);
+ ERTS_SMP_MSGQ_MV_INQ2PRIVQ(c_p);
+ erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ);
+ reds += erts_move_messages_off_heap(c_p);
}
+ c_p->flags &= ~F_OFF_HEAP_MSGQ_CHNG;
+ return reds;
+}
+
+typedef struct {
+ Eterm pid;
+ ErtsThrPrgrLaterOp lop;
+} ErtsChangeOffHeapMessageQueue;
+
+static void
+change_off_heap_msgq(void *vcohmq)
+{
+ ErtsChangeOffHeapMessageQueue *cohmq;
+ /*
+ * Now we've waited thread progress which ensures that all
+ * messages to the process are enqueued off heap. Schedule
+ * completion of this change as a system task on the process
+ * itself. This in order to avoid lock contention on its
+ * main lock. We will be called in
+ * erts_complete_off_heap_message_queue_change() (above) when
+ * the system task has been selected for execution.
+ */
+ cohmq = (ErtsChangeOffHeapMessageQueue *) vcohmq;
+ erts_schedule_complete_off_heap_message_queue_change(cohmq->pid);
+ erts_free(ERTS_ALC_T_MSGQ_CHNG, vcohmq);
+}
+
+Eterm
+erts_change_message_queue_management(Process *c_p, Eterm new_state)
+{
+ Eterm res;
+
+#ifdef DEBUG
+ if (c_p->flags & F_OFF_HEAP_MSGQ) {
+ ASSERT(erts_smp_atomic32_read_nob(&c_p->state)
+ & ERTS_PSFLG_OFF_HEAP_MSGQ);
+ }
+ else {
+ if (c_p->flags & F_OFF_HEAP_MSGQ_CHNG) {
+ ASSERT(erts_smp_atomic32_read_nob(&c_p->state)
+ & ERTS_PSFLG_OFF_HEAP_MSGQ);
+ }
+ else {
+ ASSERT(!(erts_smp_atomic32_read_nob(&c_p->state)
+ & ERTS_PSFLG_OFF_HEAP_MSGQ));
+ }
+ }
+#endif
+
+ switch (c_p->flags & (F_OFF_HEAP_MSGQ|F_ON_HEAP_MSGQ)) {
+
+ case F_OFF_HEAP_MSGQ:
+ res = am_off_heap;
+
+ switch (new_state) {
+ case am_off_heap:
+ break;
+ case am_on_heap:
+ c_p->flags |= F_ON_HEAP_MSGQ;
+ erts_smp_atomic32_read_bor_nob(&c_p->state,
+ ERTS_PSFLG_ON_HEAP_MSGQ);
+ /* fall through */
+ case am_mixed:
+ c_p->flags &= ~F_OFF_HEAP_MSGQ;
+ /*
+ * We are not allowed to clear ERTS_PSFLG_OFF_HEAP_MSGQ
+ * if a off heap change is ongoing. It will be adjusted
+ * when the change completes...
+ */
+ if (!(c_p->flags & F_OFF_HEAP_MSGQ_CHNG)) {
+ /* Safe to clear ERTS_PSFLG_OFF_HEAP_MSGQ... */
+ erts_smp_atomic32_read_band_nob(&c_p->state,
+ ~ERTS_PSFLG_OFF_HEAP_MSGQ);
+ }
+ break;
+ default:
+ res = THE_NON_VALUE; /* badarg */
+ break;
+ }
+ break;
+
+ case F_ON_HEAP_MSGQ:
+ res = am_on_heap;
+
+ switch (new_state) {
+ case am_on_heap:
+ break;
+ case am_mixed:
+ c_p->flags &= ~F_ON_HEAP_MSGQ;
+ erts_smp_atomic32_read_band_nob(&c_p->state,
+ ~ERTS_PSFLG_ON_HEAP_MSGQ);
+ break;
+ case am_off_heap:
+ c_p->flags &= ~F_ON_HEAP_MSGQ;
+ erts_smp_atomic32_read_band_nob(&c_p->state,
+ ~ERTS_PSFLG_ON_HEAP_MSGQ);
+ goto change_to_off_heap;
+ default:
+ res = THE_NON_VALUE; /* badarg */
+ break;
+ }
+ break;
+
+ case 0:
+ res = am_mixed;
+
+ switch (new_state) {
+ case am_mixed:
+ break;
+ case am_on_heap:
+ c_p->flags |= F_ON_HEAP_MSGQ;
+ erts_smp_atomic32_read_bor_nob(&c_p->state,
+ ERTS_PSFLG_ON_HEAP_MSGQ);
+ break;
+ case am_off_heap:
+ goto change_to_off_heap;
+ default:
+ res = THE_NON_VALUE; /* badarg */
+ break;
+ }
+ break;
+
+ default:
+ res = am_error;
+ ERTS_INTERNAL_ERROR("Inconsistent message queue management state");
+ break;
+ }
+
+ return res;
+
+change_to_off_heap:
+
+ c_p->flags |= F_OFF_HEAP_MSGQ;
+
+ /*
+ * We do not have to schedule a change if
+ * we have an ongoing off heap change...
+ */
+ if (!(c_p->flags & F_OFF_HEAP_MSGQ_CHNG)) {
+ ErtsChangeOffHeapMessageQueue *cohmq;
+ /*
+ * Need to set ERTS_PSFLG_OFF_HEAP_MSGQ and wait
+ * thread progress before completing the change in
+ * order to ensure that all senders observe that
+ * messages should be passed off heap. When the
+ * change has completed, GC does not need to inspect
+ * the message queue at all.
+ */
+ erts_smp_atomic32_read_bor_nob(&c_p->state,
+ ERTS_PSFLG_OFF_HEAP_MSGQ);
+ c_p->flags |= F_OFF_HEAP_MSGQ_CHNG;
+ cohmq = erts_alloc(ERTS_ALC_T_MSGQ_CHNG,
+ sizeof(ErtsChangeOffHeapMessageQueue));
+ cohmq->pid = c_p->common.id;
+ erts_schedule_thr_prgr_later_op(change_off_heap_msgq,
+ (void *) cohmq,
+ &cohmq->lop);
+ }
+
+ return res;
+}
+
+int
+erts_decode_dist_message(Process *proc, ErtsProcLocks proc_locks,
+ ErtsMessage *msgp, int force_off_heap)
+{
+ ErtsHeapFactory factory;
+ Eterm msg;
+ ErlHeapFragment *bp;
+ Sint need;
+ int decode_in_heap_frag;
+
+ decode_in_heap_frag = (force_off_heap
+ || !(proc_locks & ERTS_PROC_LOCK_MAIN)
+ || (proc->flags & F_OFF_HEAP_MSGQ));
+
+ if (msgp->data.dist_ext->heap_size >= 0)
+ need = msgp->data.dist_ext->heap_size;
+ else {
+ need = erts_decode_dist_ext_size(msgp->data.dist_ext);
+ if (need < 0) {
+ /* bad msg; remove it... */
+ if (is_not_immed(ERL_MESSAGE_TOKEN(msgp))) {
+ bp = erts_dist_ext_trailer(msgp->data.dist_ext);
+ erts_cleanup_offheap(&bp->off_heap);
+ }
+ erts_free_dist_ext_copy(msgp->data.dist_ext);
+ msgp->data.dist_ext = NULL;
+ return 0;
+ }
+
+ msgp->data.dist_ext->heap_size = need;
+ }
+
+ if (is_not_immed(ERL_MESSAGE_TOKEN(msgp))) {
+ bp = erts_dist_ext_trailer(msgp->data.dist_ext);
+ need += bp->used_size;
+ }
+
+ if (decode_in_heap_frag)
+ erts_factory_heap_frag_init(&factory, new_message_buffer(need));
+ else
+ erts_factory_proc_prealloc_init(&factory, proc, need);
+
+ ASSERT(msgp->data.dist_ext->heap_size >= 0);
+ if (is_not_immed(ERL_MESSAGE_TOKEN(msgp))) {
+ ErlHeapFragment *heap_frag;
+ heap_frag = erts_dist_ext_trailer(msgp->data.dist_ext);
+ ERL_MESSAGE_TOKEN(msgp) = copy_struct(ERL_MESSAGE_TOKEN(msgp),
+ heap_frag->used_size,
+ &factory.hp,
+ factory.off_heap);
+ erts_cleanup_offheap(&heap_frag->off_heap);
+ }
+
+ msg = erts_decode_dist_ext(&factory, msgp->data.dist_ext);
+ ERL_MESSAGE_TERM(msgp) = msg;
+ erts_free_dist_ext_copy(msgp->data.dist_ext);
+ msgp->data.attached = NULL;
+
+ if (is_non_value(msg)) {
+ erts_factory_undo(&factory);
+ return 0;
+ }
+
+ erts_factory_trim_and_close(&factory, msgp->m,
+ ERL_MESSAGE_REF_ARRAY_SZ);
+
+ ASSERT(!msgp->data.heap_frag);
+
+ if (decode_in_heap_frag)
+ msgp->data.heap_frag = factory.heap_frags;
+
+ return 1;
+}
+
+/*
+ * ERTS_INSPECT_MSGQ_KEEP_OH_MSGS == 0 will move off heap messages
+ * into the heap of the inspected process if off_heap_message_queue
+ * is false when process_info(_, messages) is called. That is, the
+ * following GC will have more data in the rootset compared to the
+ * scenario when process_info(_, messages) had not been called.
+ *
+ * ERTS_INSPECT_MSGQ_KEEP_OH_MSGS != 0 will keep off heap messages
+ * off heap when process_info(_, messages) is called regardless of
+ * the off_heap_message_queue setting of the process. That is, it
+ * will change the following execution of the process as little as
+ * possible.
+ */
+#define ERTS_INSPECT_MSGQ_KEEP_OH_MSGS 1
+
+Uint
+erts_prep_msgq_for_inspection(Process *c_p, Process *rp,
+ ErtsProcLocks rp_locks, ErtsMessageInfo *mip)
+{
+ Uint tot_heap_size;
+ ErtsMessage* mp;
+ Sint i;
+ int self_on_heap;
+
+ /*
+ * Prepare the message queue for inspection
+ * by process_info().
+ *
+ *
+ * - Decode all messages on external format
+ * - Remove all corrupt dist messages from queue
+ * - Save pointer to, and heap size need of each
+ * message in the mip array.
+ * - Return total heap size need for all messages
+ * that needs to be copied.
+ *
+ * If ERTS_INSPECT_MSGQ_KEEP_OH_MSGS == 0:
+ * - In case off heap messages is disabled and
+ * we are inspecting our own queue, move all
+ * off heap data into the heap.
+ */
+
+ self_on_heap = c_p == rp && !(c_p->flags & F_OFF_HEAP_MSGQ);
+
+ tot_heap_size = 0;
+ i = 0;
+ mp = rp->msg.first;
+ while (mp) {
+ Eterm msg = ERL_MESSAGE_TERM(mp);
+
+ mip[i].size = 0;
+
+ if (is_non_value(msg)) {
+ /* Dist message on external format; decode it... */
+ if (mp->data.attached)
+ erts_decode_dist_message(rp, rp_locks, mp,
+ ERTS_INSPECT_MSGQ_KEEP_OH_MSGS);
+
+ msg = ERL_MESSAGE_TERM(mp);
+
+ if (is_non_value(msg)) {
+ ErtsMessage **mpp;
+ ErtsMessage *bad_mp = mp;
+ /*
+ * Bad distribution message; remove
+ * it from the queue...
+ */
+ ASSERT(!mp->data.attached);
+
+ mpp = i == 0 ? &rp->msg.first : &mip[i-1].msgp->next;
+
+ if (rp->msg.save == &bad_mp->next)
+ rp->msg.save = mpp;
+ if (rp->msg.last == &bad_mp->next)
+ rp->msg.last = mpp;
+ mp = mp->next;
+ *mpp = mp;
+ rp->msg.len--;
+ bad_mp->next = NULL;
+ erts_cleanup_messages(bad_mp);
+ continue;
+ }
+ }
+
+ ASSERT(is_value(msg));
+
+#if ERTS_INSPECT_MSGQ_KEEP_OH_MSGS
+ if (is_not_immed(msg) && (!self_on_heap || mp->data.attached)) {
+ Uint sz = size_object(msg);
+ mip[i].size = sz;
+ tot_heap_size += sz;
+ }
+#else
+ if (self_on_heap) {
+ if (mp->data.attached) {
+ ErtsMessage *tmp = NULL;
+ if (mp->data.attached != ERTS_MSG_COMBINED_HFRAG) {
+ erts_link_mbuf_to_proc(rp, mp->data.heap_frag);
+ mp->data.attached = NULL;
+ }
+ else {
+ /*
+ * Need to replace the message reference since
+ * we will get references to the message data
+ * from the heap...
+ */
+ ErtsMessage **mpp;
+ tmp = erts_alloc_message(0, NULL);
+ sys_memcpy((void *) tmp->m, (void *) mp->m,
+ sizeof(Eterm)*ERL_MESSAGE_REF_ARRAY_SZ);
+ mpp = i == 0 ? &rp->msg.first : &mip[i-1].msgp->next;
+ tmp->next = mp->next;
+ if (rp->msg.save == &mp->next)
+ rp->msg.save = &tmp->next;
+ if (rp->msg.last == &mp->next)
+ rp->msg.last = &tmp->next;
+ *mpp = tmp;
+ erts_save_message_in_proc(rp, mp);
+ mp = tmp;
+ }
+ }
+ }
+ else if (is_not_immed(msg)) {
+ Uint sz = size_object(msg);
+ mip[i].size = sz;
+ tot_heap_size += sz;
+ }
+
+#endif
+
+ mip[i].msgp = mp;
+ i++;
+ mp = mp->next;
+ }
+
+ return tot_heap_size;
}
void erts_factory_proc_init(ErtsHeapFactory* factory,
@@ -1127,47 +1439,138 @@ void erts_factory_proc_prealloc_init(ErtsHeapFactory* factory,
Process* p,
Sint size)
{
+ ErlHeapFragment *bp = p->mbuf;
factory->mode = FACTORY_HALLOC;
factory->p = p;
factory->hp_start = HAlloc(p, size);
factory->hp = factory->hp_start;
factory->hp_end = factory->hp_start + size;
factory->off_heap = &p->off_heap;
+ factory->message = NULL;
factory->off_heap_saved.first = p->off_heap.first;
factory->off_heap_saved.overhead = p->off_heap.overhead;
- factory->heap_frags_saved = p->mbuf;
+ factory->heap_frags_saved = bp;
+ factory->heap_frags_saved_used = bp ? bp->used_size : 0;
factory->heap_frags = NULL; /* not used */
factory->alloc_type = 0; /* not used */
}
-void erts_factory_message_init(ErtsHeapFactory* factory,
- Process* rp,
- Eterm* hp,
- ErlHeapFragment* bp)
+void erts_factory_heap_frag_init(ErtsHeapFactory* factory,
+ ErlHeapFragment* bp)
{
- if (bp) {
- factory->mode = FACTORY_HEAP_FRAGS;
- factory->p = NULL;
- factory->hp_start = bp->mem;
- factory->hp = hp ? hp : bp->mem;
- factory->hp_end = bp->mem + bp->alloc_size;
- factory->off_heap = &bp->off_heap;
- factory->heap_frags = bp;
- factory->heap_frags_saved = bp;
- factory->alloc_type = ERTS_ALC_T_HEAP_FRAG;
- ASSERT(!bp->next);
+ factory->mode = FACTORY_HEAP_FRAGS;
+ factory->p = NULL;
+ factory->hp_start = bp->mem;
+ factory->hp = bp->mem;
+ factory->hp_end = bp->mem + bp->alloc_size;
+ factory->off_heap = &bp->off_heap;
+ factory->message = NULL;
+ factory->heap_frags = bp;
+ factory->heap_frags_saved = NULL;
+ factory->heap_frags_saved_used = 0;
+ factory->alloc_type = ERTS_ALC_T_HEAP_FRAG;
+ ASSERT(!bp->next);
+ factory->off_heap_saved.first = factory->off_heap->first;
+ factory->off_heap_saved.overhead = factory->off_heap->overhead;
+
+ ASSERT(factory->hp >= factory->hp_start && factory->hp <= factory->hp_end);
+}
+
+
+ErtsMessage *
+erts_factory_message_create(ErtsHeapFactory* factory,
+ Process *proc,
+ ErtsProcLocks *proc_locksp,
+ Uint sz)
+{
+ Eterm *hp;
+ ErlOffHeap *ohp;
+ ErtsMessage *msgp;
+ int on_heap;
+ erts_aint32_t state;
+
+ state = erts_smp_atomic32_read_nob(&proc->state);
+
+ if (state & ERTS_PSFLG_OFF_HEAP_MSGQ) {
+ msgp = erts_alloc_message(sz, &hp);
+ ohp = sz == 0 ? NULL : &msgp->hfrag.off_heap;
+ on_heap = 0;
}
else {
- factory->mode = FACTORY_HALLOC;
- factory->p = rp;
- factory->hp_start = hp;
- factory->hp = hp;
- factory->hp_end = HEAP_TOP(rp);
- factory->off_heap = &rp->off_heap;
- factory->heap_frags_saved = rp->mbuf;
- factory->heap_frags = NULL; /* not used */
- factory->alloc_type = 0; /* not used */
+ msgp = erts_try_alloc_message_on_heap(proc, &state,
+ proc_locksp,
+ sz, &hp, &ohp,
+ &on_heap);
+ }
+
+ if (on_heap) {
+ ERTS_SMP_ASSERT(*proc_locksp & ERTS_PROC_LOCK_MAIN);
+ ASSERT(ohp == &proc->off_heap);
+ factory->mode = FACTORY_HALLOC;
+ factory->p = proc;
+ factory->heap_frags_saved = proc->mbuf;
+ factory->heap_frags_saved_used = proc->mbuf ? proc->mbuf->used_size : 0;
+ }
+ else {
+ factory->mode = FACTORY_MESSAGE;
+ factory->p = NULL;
+ factory->heap_frags_saved = NULL;
+ factory->heap_frags_saved_used = 0;
+
+ if (msgp->data.attached == ERTS_MSG_COMBINED_HFRAG) {
+ ASSERT(!msgp->hfrag.next);
+ factory->heap_frags = NULL;
+ }
+ else {
+ ASSERT(!msgp->data.heap_frag
+ || !msgp->data.heap_frag->next);
+ factory->heap_frags = msgp->data.heap_frag;
+ }
+ }
+ factory->hp_start = hp;
+ factory->hp = hp;
+ factory->hp_end = hp + sz;
+ factory->message = msgp;
+ factory->off_heap = ohp;
+ factory->alloc_type = ERTS_ALC_T_HEAP_FRAG;
+ if (ohp) {
+ factory->off_heap_saved.first = ohp->first;
+ factory->off_heap_saved.overhead = ohp->overhead;
}
+ else {
+ factory->off_heap_saved.first = NULL;
+ factory->off_heap_saved.overhead = 0;
+ }
+
+ ASSERT(factory->hp >= factory->hp_start && factory->hp <= factory->hp_end);
+
+ return msgp;
+}
+
+void erts_factory_selfcontained_message_init(ErtsHeapFactory* factory,
+ ErtsMessage *msgp,
+ Eterm *hp)
+{
+ ErlHeapFragment* bp;
+ if (msgp->data.attached == ERTS_MSG_COMBINED_HFRAG) {
+ bp = &msgp->hfrag;
+ factory->heap_frags = NULL;
+ }
+ else {
+ bp = msgp->data.heap_frag;
+ factory->heap_frags = bp;
+ }
+ factory->mode = FACTORY_MESSAGE;
+ factory->p = NULL;
+ factory->hp_start = bp->mem;
+ factory->hp = hp;
+ factory->hp_end = bp->mem + bp->alloc_size;
+ factory->message = msgp;
+ factory->off_heap = &bp->off_heap;
+ factory->heap_frags_saved = NULL;
+ factory->heap_frags_saved_used = 0;
+ factory->alloc_type = ERTS_ALC_T_HEAP_FRAG;
+ ASSERT(!bp->next);
factory->off_heap_saved.first = factory->off_heap->first;
factory->off_heap_saved.overhead = factory->off_heap->overhead;
@@ -1250,9 +1653,17 @@ static void reserve_heap(ErtsHeapFactory* factory, Uint need, Uint xtra)
factory->hp_end = factory->hp + need;
return;
- case FACTORY_HEAP_FRAGS:
- case FACTORY_TMP:
- bp = factory->heap_frags;
+ case FACTORY_MESSAGE:
+ if (!factory->heap_frags) {
+ ASSERT(factory->message->data.attached == ERTS_MSG_COMBINED_HFRAG);
+ bp = &factory->message->hfrag;
+ }
+ else {
+ /* Fall through */
+ case FACTORY_HEAP_FRAGS:
+ case FACTORY_TMP:
+ bp = factory->heap_frags;
+ }
if (bp) {
ASSERT(factory->hp > bp->mem);
@@ -1290,8 +1701,23 @@ void erts_factory_close(ErtsHeapFactory* factory)
HRelease(factory->p, factory->hp_end, factory->hp);
break;
- case FACTORY_HEAP_FRAGS:
- bp = factory->heap_frags;
+ case FACTORY_MESSAGE:
+ if (!factory->heap_frags) {
+ if (factory->message->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ bp = &factory->message->hfrag;
+ else
+ bp = NULL;
+ }
+ else {
+ if (factory->message->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ factory->message->hfrag.next = factory->heap_frags;
+ else
+ factory->message->data.heap_frag = factory->heap_frags;
+
+ /* Fall through */
+ case FACTORY_HEAP_FRAGS:
+ bp = factory->heap_frags;
+ }
if (bp) {
ASSERT(factory->hp >= bp->mem);
@@ -1315,17 +1741,47 @@ void erts_factory_close(ErtsHeapFactory* factory)
void erts_factory_trim_and_close(ErtsHeapFactory* factory,
Eterm *brefs, Uint brefs_size)
{
- if (factory->mode == FACTORY_HEAP_FRAGS) {
- ErlHeapFragment* bp = factory->heap_frags;
+ ErlHeapFragment *bp;
+
+ switch (factory->mode) {
+ case FACTORY_MESSAGE: {
+ ErtsMessage *mp = factory->message;
+ if (mp->data.attached == ERTS_MSG_COMBINED_HFRAG) {
+ if (!mp->hfrag.next) {
+ Uint sz = factory->hp - factory->hp_start;
+ mp = erts_shrink_message(mp, sz, brefs, brefs_size);
+ factory->message = mp;
+ factory->mode = FACTORY_CLOSED;
+ return;
+ }
+ /*else we don't trim multi fragmented messages for now (off_heap...) */
+ break;
+ }
+ /* Fall through... */
+ }
+ case FACTORY_HEAP_FRAGS:
+ bp = factory->heap_frags;
+ if (!bp)
+ break;
if (bp->next == NULL) {
Uint used_sz = factory->hp - bp->mem;
ASSERT(used_sz <= bp->alloc_size);
- factory->heap_frags = erts_resize_message_buffer(bp, used_sz,
- brefs, brefs_size);
+ if (used_sz > 0)
+ bp = erts_resize_message_buffer(bp, used_sz,
+ brefs, brefs_size);
+ else {
+ free_message_buffer(bp);
+ bp = NULL;
+ }
+ factory->heap_frags = bp;
+ if (factory->mode == FACTORY_MESSAGE)
+ factory->message->data.heap_frag = bp;
factory->mode = FACTORY_CLOSED;
return;
}
- /*else we don't trim multi fragmented messages for now */
+ /*else we don't trim multi fragmented messages for now (off_heap...) */
+ default:
+ break;
}
erts_factory_close(factory);
}
@@ -1373,28 +1829,33 @@ void erts_factory_undo(ErtsHeapFactory* factory)
/* Rollback heap top
*/
- if (factory->heap_frags_saved == NULL) { /* No heap frags when we started */
- ASSERT(factory->hp_start >= HEAP_START(factory->p));
- ASSERT(factory->hp_start <= HEAP_LIMIT(factory->p));
- HEAP_TOP(factory->p) = factory->hp_start;
- }
- else {
+ if (HEAP_START(factory->p) <= factory->hp_start
+ && factory->hp_start <= HEAP_LIMIT(factory->p)) {
+ HEAP_TOP(factory->p) = factory->hp_start;
+ }
+
+ /* Fix last heap frag */
+ if (factory->heap_frags_saved) {
ASSERT(factory->heap_frags_saved == factory->p->mbuf);
- if (factory->hp_start == factory->heap_frags_saved->mem) {
+ if (factory->hp_start != factory->heap_frags_saved->mem)
+ factory->heap_frags_saved->used_size = factory->heap_frags_saved_used;
+ else {
factory->p->mbuf = factory->p->mbuf->next;
ERTS_HEAP_FREE(ERTS_ALC_T_HEAP_FRAG, factory->heap_frags_saved,
ERTS_HEAP_FRAG_SIZE(factory->heap_frags_saved->alloc_size));
}
- else if (factory->hp_start != factory->hp_end) {
- unsigned remains = factory->hp_start - factory->heap_frags_saved->mem;
- ASSERT(remains > 0 && remains < factory->heap_frags_saved->used_size);
- factory->heap_frags_saved->used_size = remains;
- }
}
}
break;
+ case FACTORY_MESSAGE:
+ if (factory->message->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ factory->message->hfrag.next = factory->heap_frags;
+ else
+ factory->message->data.heap_frag = factory->heap_frags;
+ erts_cleanup_messages(factory->message);
+ break;
case FACTORY_TMP:
case FACTORY_HEAP_FRAGS:
erts_cleanup_offheap(factory->off_heap);
@@ -1422,4 +1883,3 @@ void erts_factory_undo(ErtsHeapFactory* factory)
factory->heap_frags = NULL;
#endif
}
-
diff --git a/erts/emulator/beam/erl_message.h b/erts/emulator/beam/erl_message.h
index 92ba3e571c..60035d15ae 100644
--- a/erts/emulator/beam/erl_message.h
+++ b/erts/emulator/beam/erl_message.h
@@ -24,6 +24,8 @@
struct proc_bin;
struct external_thing_;
+typedef struct erl_mesg ErtsMessage;
+
/*
* This struct represents data that must be updated by structure copy,
* but is stored outside of any heap.
@@ -32,9 +34,6 @@ struct external_thing_;
struct erl_off_heap_header {
Eterm thing_word;
Uint size;
-#if HALFWORD_HEAP
- void* dummy_ptr_padding__;
-#endif
struct erl_off_heap_header* next;
};
@@ -57,6 +56,7 @@ typedef struct {
enum {
FACTORY_CLOSED = 0,
FACTORY_HALLOC,
+ FACTORY_MESSAGE,
FACTORY_HEAP_FRAGS,
FACTORY_STATIC,
FACTORY_TMP
@@ -65,8 +65,10 @@ typedef struct {
Eterm* hp_start;
Eterm* hp;
Eterm* hp_end;
+ ErtsMessage *message;
struct erl_heap_fragment* heap_frags;
struct erl_heap_fragment* heap_frags_saved;
+ Uint heap_frags_saved_used;
ErlOffHeap* off_heap;
ErlOffHeap off_heap_saved;
Uint32 alloc_type;
@@ -74,7 +76,10 @@ typedef struct {
void erts_factory_proc_init(ErtsHeapFactory*, Process*);
void erts_factory_proc_prealloc_init(ErtsHeapFactory*, Process*, Sint size);
-void erts_factory_message_init(ErtsHeapFactory*, Process*, Eterm* hp, struct erl_heap_fragment*);
+void erts_factory_heap_frag_init(ErtsHeapFactory*, struct erl_heap_fragment*);
+ErtsMessage *erts_factory_message_create(ErtsHeapFactory *, Process *,
+ ErtsProcLocks *, Uint sz);
+void erts_factory_selfcontained_message_init(ErtsHeapFactory*, ErtsMessage *, Eterm *);
void erts_factory_static_init(ErtsHeapFactory*, Eterm* hp, Uint size, ErlOffHeap*);
void erts_factory_tmp_init(ErtsHeapFactory*, Eterm* hp, Uint size, Uint32 atype);
void erts_factory_dummy_init(ErtsHeapFactory*);
@@ -96,6 +101,8 @@ void erts_factory_undo(ErtsHeapFactory*);
#include "external.h"
#include "erl_process.h"
+#define ERTS_INVALID_HFRAG_PTR ((ErlHeapFragment *) ~((UWord) 7))
+
/*
* This struct represents a heap fragment, which is used when there
* isn't sufficient room in the process heap and we can't do a GC.
@@ -110,33 +117,53 @@ struct erl_heap_fragment {
Eterm mem[1]; /* Data */
};
-typedef struct erl_mesg {
- struct erl_mesg* next; /* Next message */
- union {
- ErtsDistExternal *dist_ext;
- ErlHeapFragment *heap_frag;
- void *attached;
- } data;
+/* m[0] = message, m[1] = seq trace token */
+#define ERL_MESSAGE_REF_ARRAY_SZ 2
+#define ERL_MESSAGE_TERM(mp) ((mp)->m[0])
+#define ERL_MESSAGE_TOKEN(mp) ((mp)->m[1])
+
#ifdef USE_VM_PROBES
- Eterm m[3]; /* m[0] = message, m[1] = seq trace token, m[3] = dynamic trace user tag */
+/* m[2] = dynamic trace user tag */
+#undef ERL_MESSAGE_REF_ARRAY_SZ
+#define ERL_MESSAGE_REF_ARRAY_SZ 3
+#define ERL_MESSAGE_DT_UTAG(mp) ((mp)->m[2])
#else
- Eterm m[2]; /* m[0] = message, m[1] = seq trace token */
#endif
-} ErlMessage;
-#define ERL_MESSAGE_TERM(mp) ((mp)->m[0])
-#define ERL_MESSAGE_TOKEN(mp) ((mp)->m[1])
#ifdef USE_VM_PROBES
-#define ERL_MESSAGE_DT_UTAG(mp) ((mp)->m[2])
+#define have_no_seqtrace(T) ((T) == NIL || (T) == am_have_dt_utag)
+#else
+#define have_no_seqtrace(T) ((T) == NIL)
#endif
+#define have_seqtrace(T) (!have_no_seqtrace(T))
+
+#define ERL_MESSAGE_REF_FIELDS__ \
+ ErtsMessage *next; /* Next message */ \
+ union { \
+ ErtsDistExternal *dist_ext; \
+ ErlHeapFragment *heap_frag; \
+ void *attached; \
+ } data; \
+ Eterm m[ERL_MESSAGE_REF_ARRAY_SZ]
+
+
+typedef struct erl_msg_ref__ {
+ ERL_MESSAGE_REF_FIELDS__;
+} ErtsMessageRef;
+
+struct erl_mesg {
+ ERL_MESSAGE_REF_FIELDS__;
+
+ ErlHeapFragment hfrag;
+};
/* Size of default message buffer (erl_message.c) */
#define ERL_MESSAGE_BUF_SZ 500
typedef struct {
- ErlMessage* first;
- ErlMessage** last; /* point to the last next pointer */
- ErlMessage** save;
+ ErtsMessage* first;
+ ErtsMessage** last; /* point to the last next pointer */
+ ErtsMessage** save;
Sint len; /* queue length */
/*
@@ -144,14 +171,14 @@ typedef struct {
* recv_set/1 instructions.
*/
BeamInstr* mark; /* address to rec_loop/2 instruction */
- ErlMessage** saved_last; /* saved last pointer */
+ ErtsMessage** saved_last; /* saved last pointer */
} ErlMessageQueue;
#ifdef ERTS_SMP
typedef struct {
- ErlMessage* first;
- ErlMessage** last; /* point to the last next pointer */
+ ErtsMessage* first;
+ ErtsMessage** last; /* point to the last next pointer */
Sint len; /* queue length */
} ErlMessageInQueue;
@@ -202,7 +229,7 @@ do { \
/* Unlink current message */
#define UNLINK_MESSAGE(p,msgp) do { \
- ErlMessage* __mp = (msgp)->next; \
+ ErtsMessage* __mp = (msgp)->next; \
*(p)->msg.save = __mp; \
(p)->msg.len--; \
if (__mp == NULL) \
@@ -218,76 +245,33 @@ do { \
#define SAVE_MESSAGE(p) \
(p)->msg.save = &(*(p)->msg.save)->next
-/*
- * ErtsMoveMsgAttachmentIntoProc() moves data attached to a message
- * onto the heap of a process. The attached data is the content of
- * the the message either on the internal format or on the external
- * format, and also possibly a seq trace token on the internal format.
- * If the message content is on the external format, the decode might
- * fail. If the decoding fails, ERL_MESSAGE_TERM(M) will contain
- * THE_NON_VALUE. That is, ERL_MESSAGE_TERM(M) *has* to be checked
- * afterwards and taken care of appropriately.
- *
- * ErtsMoveMsgAttachmentIntoProc() will shallow copy to heap if
- * possible; otherwise, move to heap via garbage collection.
- *
- * ErtsMoveMsgAttachmentIntoProc() is used when receiveing messages
- * in process_main() and in hipe_check_get_msg().
- */
-
-#define ErtsMoveMsgAttachmentIntoProc(M, P, ST, HT, FC, SWPO, SWPI) \
-do { \
- if ((M)->data.attached) { \
- Uint need__ = erts_msg_attached_data_size((M)); \
- { SWPO ; } \
- if ((ST) - (HT) >= need__) { \
- ErtsHeapFactory factory__; \
- erts_factory_proc_prealloc_init(&factory__, (P), need__); \
- erts_move_msg_attached_data_to_heap(&factory__, (M)); \
- erts_factory_close(&factory__); \
- if ((P)->mbuf != NULL) { \
- /* Heap was exhausted by messages. This is a rare case */ \
- /* that can currently (OTP 18) only happen if hamts are */ \
- /* far exceeding the estimated heap size. Do GC. */ \
- (FC) -= erts_garbage_collect((P), 0, NULL, 0); \
- } \
- } \
- else { \
- (FC) -= erts_garbage_collect((P), 0, NULL, 0); \
- } \
- { SWPI ; } \
- ASSERT(!(M)->data.attached); \
- } \
-} while (0)
-
#define ERTS_SND_FLG_NO_SEQ_TRACE (((unsigned) 1) << 0)
#define ERTS_HEAP_FRAG_SIZE(DATA_WORDS) \
(sizeof(ErlHeapFragment) - sizeof(Eterm) + (DATA_WORDS)*sizeof(Eterm))
-#define ERTS_INIT_HEAP_FRAG(HEAP_FRAG_P, DATA_WORDS) \
-do { \
- (HEAP_FRAG_P)->next = NULL; \
- (HEAP_FRAG_P)->alloc_size = (DATA_WORDS); \
- (HEAP_FRAG_P)->used_size = (DATA_WORDS); \
- (HEAP_FRAG_P)->off_heap.first = NULL; \
- (HEAP_FRAG_P)->off_heap.overhead = 0; \
-} while (0)
+#define ERTS_INIT_HEAP_FRAG(HEAP_FRAG_P, USED_WORDS, DATA_WORDS) \
+ do { \
+ (HEAP_FRAG_P)->next = NULL; \
+ (HEAP_FRAG_P)->alloc_size = (DATA_WORDS); \
+ (HEAP_FRAG_P)->used_size = (USED_WORDS); \
+ (HEAP_FRAG_P)->off_heap.first = NULL; \
+ (HEAP_FRAG_P)->off_heap.overhead = 0; \
+ } while (0)
void init_message(void);
-void free_message(ErlMessage *);
ErlHeapFragment* new_message_buffer(Uint);
ErlHeapFragment* erts_resize_message_buffer(ErlHeapFragment *, Uint,
Eterm *, Uint);
void free_message_buffer(ErlHeapFragment *);
void erts_queue_dist_message(Process*, ErtsProcLocks*, ErtsDistExternal *, Eterm);
#ifdef USE_VM_PROBES
-void erts_queue_message_probe(Process*, ErtsProcLocks*, ErlHeapFragment*,
+void erts_queue_message_probe(Process*, ErtsProcLocks*, ErtsMessage*,
Eterm message, Eterm seq_trace_token, Eterm dt_utag);
#define erts_queue_message(RP,RL,BP,Msg,SEQ) \
erts_queue_message_probe((RP),(RL),(BP),(Msg),(SEQ),NIL)
#else
-void erts_queue_message(Process*, ErtsProcLocks*, ErlHeapFragment*,
+void erts_queue_message(Process*, ErtsProcLocks*, ErtsMessage*,
Eterm message, Eterm seq_trace_token);
#define erts_queue_message_probe(RP,RL,BP,Msg,SEQ,TAG) \
erts_queue_message((RP),(RL),(BP),(Msg),(SEQ))
@@ -296,20 +280,141 @@ void erts_deliver_exit_message(Eterm, Process*, ErtsProcLocks *, Eterm, Eterm);
Sint erts_send_message(Process*, Process*, ErtsProcLocks*, Eterm, unsigned);
void erts_link_mbuf_to_proc(Process *proc, ErlHeapFragment *bp);
-void erts_move_msg_mbuf_to_heap(Eterm**, ErlOffHeap*, ErlMessage *);
-
-Uint erts_msg_attached_data_size_aux(ErlMessage *msg);
-void erts_move_msg_attached_data_to_heap(ErtsHeapFactory*, ErlMessage *);
-Eterm erts_msg_distext2heap(Process *, ErtsProcLocks *, ErlHeapFragment **,
- Eterm *, ErtsDistExternal *);
+Uint erts_msg_attached_data_size_aux(ErtsMessage *msg);
void erts_cleanup_offheap(ErlOffHeap *offheap);
+void erts_save_message_in_proc(Process *p, ErtsMessage *msg);
+Sint erts_move_messages_off_heap(Process *c_p);
+Sint erts_complete_off_heap_message_queue_change(Process *c_p);
+Eterm erts_change_message_queue_management(Process *c_p, Eterm new_state);
+
+int erts_decode_dist_message(Process *, ErtsProcLocks, ErtsMessage *, int);
+
+void erts_cleanup_messages(ErtsMessage *mp);
+
+typedef struct {
+ Uint size;
+ ErtsMessage *msgp;
+} ErtsMessageInfo;
+
+Uint erts_prep_msgq_for_inspection(Process *c_p,
+ Process *rp,
+ ErtsProcLocks rp_locks,
+ ErtsMessageInfo *mip);
+
+void *erts_alloc_message_ref(void);
+void erts_free_message_ref(void *);
+#define ERTS_SMALL_FIX_MSG_SZ 10
+#define ERTS_MEDIUM_FIX_MSG_SZ 20
+#define ERTS_LARGE_FIX_MSG_SZ 30
+void *erts_alloc_small_message(void);
+void erts_free_small_message(void *mp);
+
+typedef struct {
+ ErtsMessage m;
+ Eterm data[ERTS_SMALL_FIX_MSG_SZ-1];
+} ErtsSmallFixSzMessage;
+
+typedef struct {
+ ErtsMessage m;
+ Eterm data[ERTS_MEDIUM_FIX_MSG_SZ-1];
+} ErtsMediumFixSzMessage;
+
+typedef struct {
+ ErtsMessage m;
+ Eterm data[ERTS_LARGE_FIX_MSG_SZ-1];
+} ErtsLargeFixSzMessage;
+
+ErtsMessage *erts_try_alloc_message_on_heap(Process *pp,
+ erts_aint32_t *psp,
+ ErtsProcLocks *plp,
+ Uint sz,
+ Eterm **hpp,
+ ErlOffHeap **ohpp,
+ int *on_heap_p);
+ErtsMessage *erts_realloc_shrink_message(ErtsMessage *mp, Uint sz,
+ Eterm *brefs, Uint brefs_size);
+
+ERTS_GLB_FORCE_INLINE ErtsMessage *erts_alloc_message(Uint sz, Eterm **hpp);
+ERTS_GLB_FORCE_INLINE ErtsMessage *erts_shrink_message(ErtsMessage *mp, Uint sz,
+ Eterm *brefs, Uint brefs_size);
+ERTS_GLB_FORCE_INLINE void erts_free_message(ErtsMessage *mp);
ERTS_GLB_INLINE Uint erts_used_frag_sz(const ErlHeapFragment*);
-ERTS_GLB_INLINE Uint erts_msg_attached_data_size(ErlMessage *msg);
+ERTS_GLB_INLINE Uint erts_msg_attached_data_size(ErtsMessage *msg);
+
+#define ERTS_MSG_COMBINED_HFRAG ((void *) 0x1)
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+ERTS_GLB_FORCE_INLINE ErtsMessage *erts_alloc_message(Uint sz, Eterm **hpp)
+{
+ ErtsMessage *mp;
+
+ if (sz == 0) {
+ mp = erts_alloc_message_ref();
+ mp->next = NULL;
+ ERL_MESSAGE_TERM(mp) = NIL;
+ mp->data.attached = NULL;
+ if (hpp)
+ *hpp = NULL;
+ return mp;
+ }
+
+ mp = erts_alloc(ERTS_ALC_T_MSG,
+ sizeof(ErtsMessage) + (sz - 1)*sizeof(Eterm));
+
+ mp->next = NULL;
+ ERL_MESSAGE_TERM(mp) = NIL;
+ mp->data.attached = ERTS_MSG_COMBINED_HFRAG;
+ ERTS_INIT_HEAP_FRAG(&mp->hfrag, sz, sz);
+
+ if (hpp)
+ *hpp = &mp->hfrag.mem[0];
+
+ return mp;
+}
+
+ERTS_GLB_FORCE_INLINE ErtsMessage *
+erts_shrink_message(ErtsMessage *mp, Uint sz, Eterm *brefs, Uint brefs_size)
+{
+ if (sz == 0) {
+ ErtsMessage *nmp;
+ if (!mp->data.attached)
+ return mp;
+ ASSERT(mp->data.attached == ERTS_MSG_COMBINED_HFRAG);
+ nmp = erts_alloc_message_ref();
+#ifdef DEBUG
+ if (brefs && brefs_size) {
+ int i;
+ for (i = 0; i < brefs_size; i++)
+ ASSERT(is_non_value(brefs[i]) || is_immed(brefs[i]));
+ }
+#endif
+ erts_free(ERTS_ALC_T_MSG, mp);
+ return nmp;
+ }
+
+ ASSERT(mp->data.attached == ERTS_MSG_COMBINED_HFRAG);
+ ASSERT(mp->hfrag.used_size >= sz);
+
+ if (sz >= (mp->hfrag.alloc_size - mp->hfrag.alloc_size / 16)) {
+ mp->hfrag.used_size = sz;
+ return mp;
+ }
+
+ return erts_realloc_shrink_message(mp, sz, brefs, brefs_size);
+}
+
+ERTS_GLB_FORCE_INLINE void erts_free_message(ErtsMessage *mp)
+{
+ if (mp->data.attached != ERTS_MSG_COMBINED_HFRAG)
+ erts_free_message_ref(mp);
+ else
+ erts_free(ERTS_ALC_T_MSG, mp);
+}
+
ERTS_GLB_INLINE Uint erts_used_frag_sz(const ErlHeapFragment* bp)
{
Uint sz = 0;
@@ -319,11 +424,17 @@ ERTS_GLB_INLINE Uint erts_used_frag_sz(const ErlHeapFragment* bp)
return sz;
}
-ERTS_GLB_INLINE Uint erts_msg_attached_data_size(ErlMessage *msg)
+ERTS_GLB_INLINE Uint erts_msg_attached_data_size(ErtsMessage *msg)
{
ASSERT(msg->data.attached);
- if (is_value(ERL_MESSAGE_TERM(msg)))
- return erts_used_frag_sz(msg->data.heap_frag);
+ if (is_value(ERL_MESSAGE_TERM(msg))) {
+ ErlHeapFragment *bp;
+ if (msg->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ bp = &msg->hfrag;
+ else
+ bp = msg->data.heap_frag;
+ return erts_used_frag_sz(bp);
+ }
else if (msg->data.dist_ext->heap_size < 0)
return erts_msg_attached_data_size_aux(msg);
else {
diff --git a/erts/emulator/beam/erl_msacc.c b/erts/emulator/beam/erl_msacc.c
new file mode 100644
index 0000000000..71e3fd8b6e
--- /dev/null
+++ b/erts/emulator/beam/erl_msacc.c
@@ -0,0 +1,486 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2014-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%
+ */
+
+/*
+ * Description: Microstate accounting.
+ *
+ * We keep track of the different states that the
+ * Erlang VM threads are in, in order to provide
+ * performance/debugging statistics. There is a
+ * small overhead in enabling this, but in the big
+ * scheme of things it should be negligible.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#define ERTS_MSACC_STATE_STRINGS 1
+
+#include "sys.h"
+#include "global.h"
+#include "erl_threads.h"
+#include "erl_bif_unique.h"
+#include "erl_map.h"
+#include "erl_msacc.h"
+
+#if ERTS_ENABLE_MSACC
+
+static Eterm erts_msacc_gather_stats(ErtsMsAcc *msacc, Eterm **hpp, Uint *szp);
+static void erts_msacc_reset(ErtsMsAcc *msacc);
+static ErtsMsAcc* get_msacc(void);
+
+#ifdef USE_THREADS
+erts_tsd_key_t ERTS_WRITE_UNLIKELY(erts_msacc_key);
+#else
+ErtsMsAcc *ERTS_WRITE_UNLIKELY(erts_msacc) = NULL;
+#endif
+int ERTS_WRITE_UNLIKELY(erts_msacc_enabled);
+
+static Eterm *erts_msacc_state_atoms = NULL;
+static erts_rwmtx_t msacc_mutex;
+static ErtsMsAcc *msacc_managed = NULL;
+#ifdef USE_THREADS
+static ErtsMsAcc *msacc_unmanaged = NULL;
+static Uint msacc_unmanaged_count = 0;
+#endif
+
+/* we have to split initiation as atoms are not inited in early init */
+void erts_msacc_early_init(void) {
+#ifndef ERTS_MSACC_ALWAYS_ON
+ erts_msacc_enabled = 0;
+#endif
+ erts_rwmtx_init(&msacc_mutex,"msacc_list_mutex");
+#ifdef USE_THREADS
+ erts_tsd_key_create(&erts_msacc_key,"erts_msacc_key");
+#else
+ erts_msacc = NULL;
+#endif
+}
+
+void erts_msacc_init(void) {
+ int i;
+ erts_msacc_state_atoms = erts_alloc(ERTS_ALC_T_MSACC,
+ sizeof(Eterm)*ERTS_MSACC_STATE_COUNT);
+ for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++) {
+ erts_msacc_state_atoms[i] = am_atom_put(erts_msacc_states[i],
+ strlen(erts_msacc_states[i]));
+ }
+}
+
+void erts_msacc_init_thread(char *type, int id, int managed) {
+ ErtsMsAcc *msacc;
+
+ msacc = erts_alloc(ERTS_ALC_T_MSACC, sizeof(ErtsMsAcc));
+
+ msacc->type = strdup(type);
+ msacc->id = make_small(id);
+ msacc->unmanaged = !managed;
+ msacc->tid = erts_thr_self();
+ msacc->perf_counter = 0;
+
+#ifdef USE_THREADS
+ erts_rwmtx_rwlock(&msacc_mutex);
+ if (!managed) {
+ erts_mtx_init(&msacc->mtx,"msacc_unmanaged_mutex");
+ msacc->next = msacc_unmanaged;
+ msacc_unmanaged = msacc;
+ msacc_unmanaged_count++;
+ ERTS_MSACC_TSD_SET(msacc);
+ } else {
+ msacc->next = msacc_managed;
+ msacc_managed = msacc;
+ }
+ erts_rwmtx_rwunlock(&msacc_mutex);
+#else
+ msacc_managed = msacc;
+#endif
+
+ erts_msacc_reset(msacc);
+
+#ifdef ERTS_MSACC_ALWAYS_ON
+ ERTS_MSACC_TSD_SET(msacc);
+ msacc->perf_counter = erts_sys_perf_counter();
+ msacc->state = ERTS_MSACC_STATE_OTHER;
+#endif
+}
+
+/*
+ * Creates a structure looking like this
+ * #{ type => scheduler, id => 1, counters => #{ State1 => Counter1 ... StateN => CounterN}}
+ */
+static
+Eterm erts_msacc_gather_stats(ErtsMsAcc *msacc, Eterm **hpp, Uint *szp) {
+ int i;
+ Eterm *hp;
+ Eterm key, state_key, state_map;
+ Eterm res = THE_NON_VALUE;
+ flatmap_t *map;
+
+ if (szp) {
+ *szp += MAP_HEADER_FLATMAP_SZ + 1 + 2*(3);
+ *szp += MAP_HEADER_FLATMAP_SZ + 1 + 2*(ERTS_MSACC_STATE_COUNT);
+ for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++) {
+ (void)erts_bld_sint64(NULL,szp,(Sint64)msacc->perf_counters[i]);
+#ifdef ERTS_MSACC_STATE_COUNTERS
+ (void)erts_bld_uint64(NULL,szp,msacc->state_counters[i]);
+ *szp += 3; /* tuple to put state+perf counter in */
+#endif
+ }
+ }
+
+ if (hpp) {
+ Eterm counters[ERTS_MSACC_STATE_COUNT];
+ hp = *hpp;
+ for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++) {
+ Eterm counter = erts_bld_sint64(&hp,NULL,(Sint64)msacc->perf_counters[i]);
+#ifdef ERTS_MSACC_STATE_COUNTERS
+ Eterm counter__ = erts_bld_uint64(&hp,NULL,msacc->state_counters[i]);
+ counters[i] = TUPLE2(hp,counter,counter__);
+ hp += 3;
+#else
+ counters[i] = counter;
+#endif
+ }
+
+ key = TUPLE3(hp,am_counters,am_id,am_type);
+ hp += 4;
+
+ state_key = make_tuple(hp);
+ hp[0] = make_arityval(ERTS_MSACC_STATE_COUNT);
+
+ for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++)
+ hp[1+i] = erts_msacc_state_atoms[i];
+ hp += 1 + ERTS_MSACC_STATE_COUNT;
+
+ map = (flatmap_t*)hp;
+ hp += MAP_HEADER_FLATMAP_SZ;
+ map->thing_word = MAP_HEADER_FLATMAP;
+ map->size = ERTS_MSACC_STATE_COUNT;
+ map->keys = state_key;
+ for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++)
+ hp[i] = counters[i];
+ hp += ERTS_MSACC_STATE_COUNT;
+ state_map = make_flatmap(map);
+
+ map = (flatmap_t*)hp;
+ hp += MAP_HEADER_FLATMAP_SZ;
+ map->thing_word = MAP_HEADER_FLATMAP;
+ map->size = 3;
+ map->keys = key;
+ hp[0] = state_map;
+ hp[1] = msacc->id;
+ hp[2] = am_atom_put(msacc->type,strlen(msacc->type));
+ hp += 3;
+
+ *hpp = hp;
+ res = make_flatmap(map);
+ }
+
+ return res;
+}
+
+typedef struct {
+ int action;
+ Process *proc;
+ Eterm ref;
+ Eterm ref_heap[REF_THING_SIZE];
+ Uint req_sched;
+ erts_smp_atomic32_t refc;
+} ErtsMSAccReq;
+
+static ErtsMsAcc* get_msacc(void) {
+ ErtsMsAcc *msacc;
+ erts_rwmtx_rlock(&msacc_mutex);
+ msacc = msacc_managed;
+ while (!erts_equal_tids(msacc->tid,erts_thr_self())) {
+ msacc = msacc->next;
+ ASSERT(msacc != NULL);
+ }
+ erts_rwmtx_runlock(&msacc_mutex);
+ return msacc;
+}
+
+static void send_reply(ErtsMsAcc *msacc, ErtsMSAccReq *msaccrp) {
+ ErtsSchedulerData *esdp = erts_get_scheduler_data();
+ Process *rp = msaccrp->proc;
+ ErtsMessage *msgp = NULL;
+ Eterm **hpp, *hp;
+ Eterm ref_copy = NIL, msg;
+ Uint sz, *szp;
+ ErlOffHeap *ohp = NULL;
+ ErtsProcLocks rp_locks = (esdp && msaccrp->req_sched == esdp->no
+ ? ERTS_PROC_LOCK_MAIN : 0);
+
+ sz = 0;
+ hpp = NULL;
+ szp = &sz;
+
+ if (msacc->unmanaged) erts_mtx_lock(&msacc->mtx);
+
+ while (1) {
+ if (hpp)
+ ref_copy = STORE_NC(hpp, ohp, msaccrp->ref);
+ else
+ *szp += REF_THING_SIZE;
+
+ if (msaccrp->action != ERTS_MSACC_GATHER)
+ msg = ref_copy;
+ else {
+ msg = erts_msacc_gather_stats(msacc, hpp, szp);
+ msg = erts_bld_tuple(hpp, szp, 2, ref_copy, msg);
+ }
+ if (hpp)
+ break;
+
+ msgp = erts_alloc_message_heap(rp, &rp_locks, sz, &hp, &ohp);
+ hpp = &hp;
+ szp = NULL;
+ }
+
+ if (msacc->unmanaged) erts_mtx_unlock(&msacc->mtx);
+
+ erts_queue_message(rp, &rp_locks, msgp, msg, NIL);
+
+ if (esdp && msaccrp->req_sched == esdp->no)
+ rp_locks &= ~ERTS_PROC_LOCK_MAIN;
+
+ if (rp_locks)
+ erts_smp_proc_unlock(rp, rp_locks);
+
+}
+
+static void
+reply_msacc(void *vmsaccrp)
+{
+ ErtsMsAcc *msacc = ERTS_MSACC_TSD_GET();
+ ErtsMSAccReq *msaccrp = (ErtsMSAccReq *) vmsaccrp;
+
+ ASSERT(!msacc || !msacc->unmanaged);
+
+ if (msaccrp->action == ERTS_MSACC_ENABLE && !msacc) {
+ msacc = get_msacc();
+
+ msacc->perf_counter = erts_sys_perf_counter();
+
+ msacc->state = ERTS_MSACC_STATE_OTHER;
+
+ ERTS_MSACC_TSD_SET(msacc);
+
+ } else if (msaccrp->action == ERTS_MSACC_DISABLE && msacc) {
+ ERTS_MSACC_TSD_SET(NULL);
+ } else if (msaccrp->action == ERTS_MSACC_RESET) {
+ msacc = msacc ? msacc : get_msacc();
+ erts_msacc_reset(msacc);
+ } else if (msaccrp->action == ERTS_MSACC_GATHER && !msacc) {
+ msacc = get_msacc();
+ }
+
+ ASSERT(!msacc || !msacc->unmanaged);
+
+ send_reply(msacc, msaccrp);
+
+ erts_proc_dec_refc(msaccrp->proc);
+
+ if (erts_smp_atomic32_dec_read_nob(&msaccrp->refc) == 0)
+ erts_free(ERTS_ALC_T_MSACC, vmsaccrp);
+}
+
+static void erts_msacc_reset(ErtsMsAcc *msacc) {
+ int i;
+ if (msacc->unmanaged) erts_mtx_lock(&msacc->mtx);
+
+ for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++) {
+ msacc->perf_counters[i] = 0;
+#ifdef ERTS_MSACC_STATE_COUNTERS
+ msacc->state_counters[i] = 0;
+#endif
+ }
+
+ if (msacc->unmanaged) erts_mtx_unlock(&msacc->mtx);
+}
+
+#endif /* ERTS_ENABLE_MSACC */
+
+
+/*
+ * This function is responsible for enabling, disabling, resetting and
+ * gathering data related to microstate accounting.
+ *
+ * Managed threads and unmanaged threads are handled differently.
+ * - managed threads get a misc_aux job telling them to switch on msacc
+ * - unmanaged have some fields protected by a mutex that has to be taken
+ * before any values can be updated
+ *
+ * For performance reasons there is also a global value erts_msacc_enabled
+ * that controls the state of all threads. Statistics gathering is only on
+ * if erts_msacc_enabled && msacc is true.
+ */
+Eterm
+erts_msacc_request(Process *c_p, int action, Eterm *threads)
+{
+#ifdef ERTS_ENABLE_MSACC
+ ErtsMsAcc *msacc = ERTS_MSACC_TSD_GET();
+ ErtsSchedulerData *esdp = ERTS_PROC_GET_SCHDATA(c_p);
+ Eterm ref;
+ ErtsMSAccReq *msaccrp;
+ Eterm *hp;
+
+
+#ifdef ERTS_MSACC_ALWAYS_ON
+ if (action == ERTS_MSACC_ENABLE || action == ERTS_MSACC_DISABLE)
+ return THE_NON_VALUE;
+#else
+ /* take care of double enable, and double disable here */
+ if (msacc && action == ERTS_MSACC_ENABLE) {
+ return THE_NON_VALUE;
+ } else if (!msacc && action == ERTS_MSACC_DISABLE) {
+ return THE_NON_VALUE;
+ }
+#endif
+
+ ref = erts_make_ref(c_p);
+
+ msaccrp = erts_alloc(ERTS_ALC_T_MSACC, sizeof(ErtsMSAccReq));
+ hp = &msaccrp->ref_heap[0];
+
+ msaccrp->action = action;
+ msaccrp->proc = c_p;
+ msaccrp->ref = STORE_NC(&hp, NULL, ref);
+ msaccrp->req_sched = esdp->no;
+
+#ifdef ERTS_SMP
+ *threads = erts_no_schedulers;
+ *threads += 1; /* aux thread */
+#else
+ *threads = 1;
+#endif
+
+ erts_smp_atomic32_init_nob(&msaccrp->refc,(erts_aint32_t)*threads);
+
+ erts_proc_add_refc(c_p, *threads);
+
+ if (erts_no_schedulers > 1)
+ erts_schedule_multi_misc_aux_work(1,
+ erts_no_schedulers,
+ reply_msacc,
+ (void *) msaccrp);
+#ifdef ERTS_SMP
+ /* aux thread */
+ erts_schedule_misc_aux_work(0, reply_msacc, (void *) msaccrp);
+#endif
+
+#ifdef USE_THREADS
+ /* Manage unmanaged threads */
+ switch (action) {
+ case ERTS_MSACC_GATHER: {
+ Uint unmanaged_count;
+ ErtsMsAcc *msacc, **unmanaged;
+ int i = 0;
+
+ /* we copy a list of pointers here so that we do not have to have
+ the msacc_mutex when sending messages */
+ erts_rwmtx_rlock(&msacc_mutex);
+ unmanaged_count = msacc_unmanaged_count;
+ unmanaged = erts_alloc(ERTS_ALC_T_MSACC,
+ sizeof(ErtsMsAcc*)*unmanaged_count);
+
+ for (i = 0, msacc = msacc_unmanaged;
+ i < unmanaged_count;
+ i++, msacc = msacc->next) {
+ unmanaged[i] = msacc;
+ }
+ erts_rwmtx_runlock(&msacc_mutex);
+
+ for (i = 0; i < unmanaged_count; i++) {
+ erts_mtx_lock(&unmanaged[i]->mtx);
+ if (unmanaged[i]->perf_counter) {
+ ErtsSysPerfCounter perf_counter;
+ /* if enabled update stats */
+ perf_counter = erts_sys_perf_counter();
+ unmanaged[i]->perf_counters[unmanaged[i]->state] +=
+ perf_counter - unmanaged[i]->perf_counter;
+ unmanaged[i]->perf_counter = perf_counter;
+ }
+ erts_mtx_unlock(&unmanaged[i]->mtx);
+ send_reply(unmanaged[i],msaccrp);
+ }
+ erts_free(ERTS_ALC_T_MSACC,unmanaged);
+ /* We have just sent unmanaged_count messages, so bump no of threads */
+ *threads += unmanaged_count;
+ break;
+ }
+ case ERTS_MSACC_RESET: {
+ ErtsMsAcc *msacc;
+ erts_rwmtx_rlock(&msacc_mutex);
+ for (msacc = msacc_unmanaged; msacc != NULL; msacc = msacc->next)
+ erts_msacc_reset(msacc);
+ erts_rwmtx_runlock(&msacc_mutex);
+ break;
+ }
+ case ERTS_MSACC_ENABLE: {
+ erts_rwmtx_rlock(&msacc_mutex);
+ for (msacc = msacc_unmanaged; msacc != NULL; msacc = msacc->next) {
+ erts_mtx_lock(&msacc->mtx);
+ msacc->perf_counter = erts_sys_perf_counter();
+ /* we assume the unmanaged thread is sleeping */
+ msacc->state = ERTS_MSACC_STATE_SLEEP;
+ erts_mtx_unlock(&msacc->mtx);
+ }
+ erts_rwmtx_runlock(&msacc_mutex);
+ break;
+ }
+ case ERTS_MSACC_DISABLE: {
+ ErtsSysPerfCounter perf_counter;
+ erts_rwmtx_rlock(&msacc_mutex);
+ /* make sure to update stats with latest results */
+ for (msacc = msacc_unmanaged; msacc != NULL; msacc = msacc->next) {
+ erts_mtx_lock(&msacc->mtx);
+ perf_counter = erts_sys_perf_counter();
+ msacc->perf_counters[msacc->state] += perf_counter - msacc->perf_counter;
+ msacc->perf_counter = 0;
+ erts_mtx_unlock(&msacc->mtx);
+ }
+ erts_rwmtx_runlock(&msacc_mutex);
+ break;
+ }
+ default: { ASSERT(0); }
+ }
+
+#endif
+
+ *threads = make_small(*threads);
+
+ reply_msacc((void *) msaccrp);
+
+#ifndef ERTS_MSACC_ALWAYS_ON
+ /* enable/disable the global value */
+ if (action == ERTS_MSACC_ENABLE) {
+ erts_msacc_enabled = 1;
+ } else if (action == ERTS_MSACC_DISABLE) {
+ erts_msacc_enabled = 0;
+ }
+#endif
+
+ return ref;
+#else
+ return THE_NON_VALUE;
+#endif
+}
diff --git a/erts/emulator/beam/erl_msacc.h b/erts/emulator/beam/erl_msacc.h
new file mode 100644
index 0000000000..284388f7aa
--- /dev/null
+++ b/erts/emulator/beam/erl_msacc.h
@@ -0,0 +1,409 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2014-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%
+ */
+
+#ifndef ERL_MSACC_H__
+#define ERL_MSACC_H__
+
+/* Can be enabled/disabled via configure */
+#if ERTS_ENABLE_MSACC == 2
+#define ERTS_MSACC_EXTENDED_STATES 1
+#endif
+
+/* Uncomment this to also count the number of
+ transitions to a state. This will add a count
+ to the counter map. */
+/* #define ERTS_MSACC_STATE_COUNTERS 1 */
+
+/* Uncomment this to make msacc to always be on,
+ this reduces overhead a little bit when profiling */
+/* #define ERTS_MSACC_ALWAYS_ON 1 */
+
+#define ERTS_MSACC_DISABLE 0
+#define ERTS_MSACC_ENABLE 1
+#define ERTS_MSACC_RESET 2
+#define ERTS_MSACC_GATHER 3
+
+/*
+ * When adding a new state, you have to:
+ * * Add it here
+ * * Increment ERTS_MSACC_STATE_COUNT
+ * * Add string value to erts_msacc_states
+ * * Have to be in alphabetical order!
+ * * Only add states to the non-extended section after
+ * careful benchmarking to make sure the overhead
+ * when disabled is minimal.
+ */
+
+#ifndef ERTS_MSACC_EXTENDED_STATES
+#define ERTS_MSACC_STATE_AUX 0
+#define ERTS_MSACC_STATE_CHECK_IO 1
+#define ERTS_MSACC_STATE_EMULATOR 2
+#define ERTS_MSACC_STATE_GC 3
+#define ERTS_MSACC_STATE_OTHER 4
+#define ERTS_MSACC_STATE_PORT 5
+#define ERTS_MSACC_STATE_SLEEP 6
+
+#define ERTS_MSACC_STATE_COUNT 7
+
+#if ERTS_MSACC_STATE_STRINGS && ERTS_ENABLE_MSACC
+static char *erts_msacc_states[] = {
+ "aux",
+ "check_io",
+ "emulator",
+ "gc",
+ "other",
+ "port",
+ "sleep"
+};
+#endif
+
+#else
+
+#define ERTS_MSACC_STATE_ALLOC 0
+#define ERTS_MSACC_STATE_AUX 1
+#define ERTS_MSACC_STATE_BIF 2
+#define ERTS_MSACC_STATE_BUSY_WAIT 3
+#define ERTS_MSACC_STATE_CHECK_IO 4
+#define ERTS_MSACC_STATE_EMULATOR 5
+#define ERTS_MSACC_STATE_ETS 6
+#define ERTS_MSACC_STATE_GC 7
+#define ERTS_MSACC_STATE_GC_FULL 8
+#define ERTS_MSACC_STATE_NIF 9
+#define ERTS_MSACC_STATE_OTHER 10
+#define ERTS_MSACC_STATE_PORT 11
+#define ERTS_MSACC_STATE_SEND 12
+#define ERTS_MSACC_STATE_SLEEP 13
+#define ERTS_MSACC_STATE_TIMERS 14
+
+#define ERTS_MSACC_STATE_COUNT 15
+
+#if ERTS_MSACC_STATE_STRINGS
+static char *erts_msacc_states[] = {
+ "alloc",
+ "aux",
+ "bif",
+ "busy_wait",
+ "check_io",
+ "emulator",
+ "ets",
+ "gc",
+ "gc_full",
+ "nif",
+ "other",
+ "port",
+ "send",
+ "sleep",
+ "timers"
+};
+#endif
+
+#endif
+
+typedef struct erl_msacc_t_ ErtsMsAcc;
+
+struct erl_msacc_t_ {
+
+ /* the the values below are protected by mtx iff unmanaged = 1 */
+ ErtsSysPerfCounter perf_counter;
+ ErtsSysPerfCounter perf_counters[ERTS_MSACC_STATE_COUNT];
+#ifdef ERTS_MSACC_STATE_COUNTERS
+ Uint64 state_counters[ERTS_MSACC_STATE_COUNT];
+#endif
+ Uint state;
+
+ /* protected by msacc_mutex in erl_msacc.c, and should be constant */
+ int unmanaged;
+ erts_mtx_t mtx;
+ ErtsMsAcc *next;
+ erts_tid_t tid;
+ Eterm id;
+ char *type;
+};
+
+#if ERTS_ENABLE_MSACC
+
+#define ERTS_MSACC_INLINE ERTS_GLB_INLINE
+
+#ifdef USE_THREADS
+extern erts_tsd_key_t erts_msacc_key;
+#else
+extern ErtsMsAcc *erts_msacc;
+#endif
+
+#ifdef ERTS_MSACC_ALWAYS_ON
+#define erts_msacc_enabled 1
+#else
+extern int erts_msacc_enabled;
+#endif
+
+#ifdef USE_THREADS
+#define ERTS_MSACC_TSD_GET() erts_tsd_get(erts_msacc_key)
+#define ERTS_MSACC_TSD_SET(tsd) erts_tsd_set(erts_msacc_key,tsd)
+#else
+#define ERTS_MSACC_TSD_GET() erts_msacc
+#define ERTS_MSACC_TSD_SET(tsd) erts_msacc = tsd
+#endif
+
+void erts_msacc_early_init(void);
+void erts_msacc_init(void);
+void erts_msacc_init_thread(char *type, int id, int liberty);
+
+/* The defines below are used to instrument the vm code
+ * with different state changes. There are two variants
+ * of each define. One that has a cached ErtsMsAcc *
+ * that it can use, and one that does not.
+ * The cached values are necessary to have in order to get
+ * low enough overhead when running without msacc enabled.
+ *
+ * The two most common patterns to use the function with are:
+ *
+ * ERTS_MSACC_PUSH_AND_SET_STATE(ERTS_MSACC_STATE_NEWSTATE);
+ * ... call other function in new state ...
+ * ERTS_MSACC_POP_STATE();
+ *
+ * Note that the erts_msacc_push* function declare new variables, so
+ * to conform with C89 we have to call it in the beginning of a function.
+ * We might not want to change state it the beginning though, so we use this:
+ *
+ * ERTS_MSACC_PUSH_STATE();
+ * ... some other code ...
+ * ERTS_MSACC_SET_STATE_CACHED(ERTS_MSACC_STATE_NEWSTATE);
+ * ... call other function in new state ...
+ * ERTS_MSACC_POP_STATE();
+ *
+ * Notice that we used the cached version of set_state as push_state already
+ * read the erts_msacc_enabled to the cache.
+ *
+ * Most macros also have other variants with the suffix _m which means that
+ * they are known to only be called in managed threads, or with the _x suffix
+ * which means that it should only be used in an emulator compiled with
+ * extended states.
+ *
+ * Here is a listing of the entire api:
+ *
+ * void ERTS_MSACC_DECLARE_CACHE()
+ * void ERTS_MSACC_UPDATE_CACHE()
+ * void ERTS_MSACC_IS_ENABLED()
+ * void ERTS_MSACC_IS_ENABLED_CACHED()
+ *
+ * void ERTS_MSACC_PUSH_STATE()
+ * void ERTS_MSACC_SET_STATE(int state)
+ * void ERTS_MSACC_PUSH_AND_SET_STATE(int state)
+ *
+ * void ERTS_MSACC_PUSH_STATE_CACHED()
+ * void ERTS_MSACC_SET_STATE_CACHED(int state)
+ * void ERTS_MSACC_PUSH_AND_SET_STATE_CACHED(int state)
+ * void ERTS_MSACC_POP_STATE()
+ *
+ * void ERTS_MSACC_PUSH_STATE_M()
+ * void ERTS_MSACC_PUSH_STATE_CACHED_M()
+ * void ERTS_MSACC_SET_STATE_CACHED_M(int state)
+ * void ERTS_MSACC_SET_STATE_M(int state)
+ * void ERTS_MSACC_POP_STATE_M()
+ * void ERTS_MSACC_PUSH_AND_SET_STATE_M(int state)
+ *
+ * Most functions are also available with an _x suffix that are only enabled
+ * when using the extra states. If they are not, just add them to the end
+ * of this file.
+ */
+
+/* cache handling functions */
+#define ERTS_MSACC_IS_ENABLED() ERTS_UNLIKELY(erts_msacc_enabled)
+#define ERTS_MSACC_DECLARE_CACHE() \
+ ErtsMsAcc *ERTS_MSACC_UPDATE_CACHE(); \
+ ERTS_DECLARE_DUMMY(Uint __erts_msacc_state) = ERTS_MSACC_STATE_OTHER;
+#define ERTS_MSACC_IS_ENABLED_CACHED() ERTS_UNLIKELY(__erts_msacc_cache != NULL)
+#define ERTS_MSACC_UPDATE_CACHE() \
+ __erts_msacc_cache = erts_msacc_enabled ? ERTS_MSACC_TSD_GET() : NULL
+
+
+/* The defines below implicitly declare and load a new cache */
+#define ERTS_MSACC_PUSH_STATE() \
+ ERTS_MSACC_DECLARE_CACHE(); \
+ ERTS_MSACC_PUSH_STATE_CACHED()
+#define ERTS_MSACC_SET_STATE(state) \
+ ERTS_MSACC_DECLARE_CACHE(); \
+ ERTS_MSACC_SET_STATE_CACHED(state)
+#define ERTS_MSACC_PUSH_AND_SET_STATE(state) \
+ ERTS_MSACC_PUSH_STATE(); ERTS_MSACC_SET_STATE_CACHED(state)
+
+/* The defines below need an already declared cache to work */
+#define ERTS_MSACC_PUSH_STATE_CACHED() \
+ __erts_msacc_state = ERTS_MSACC_IS_ENABLED_CACHED() ? \
+ erts_msacc_get_state_um__(__erts_msacc_cache) : ERTS_MSACC_STATE_OTHER
+#define ERTS_MSACC_SET_STATE_CACHED(state) \
+ if (ERTS_MSACC_IS_ENABLED_CACHED()) \
+ erts_msacc_set_state_um__(__erts_msacc_cache, state, 1)
+#define ERTS_MSACC_PUSH_AND_SET_STATE_CACHED(state) \
+ ERTS_MSACC_PUSH_STATE_CACHED(); ERTS_MSACC_SET_STATE_CACHED(state)
+#define ERTS_MSACC_POP_STATE() \
+ if (ERTS_MSACC_IS_ENABLED_CACHED()) \
+ erts_msacc_set_state_um__(__erts_msacc_cache, __erts_msacc_state, 0)
+
+/* Only use these defines when we know that we have in a managed thread */
+#define ERTS_MSACC_PUSH_STATE_M() \
+ ERTS_MSACC_DECLARE_CACHE(); \
+ ERTS_MSACC_PUSH_STATE_CACHED_M()
+#define ERTS_MSACC_PUSH_STATE_CACHED_M() \
+ __erts_msacc_state = ERTS_MSACC_IS_ENABLED_CACHED() ? \
+ erts_msacc_get_state_m__(__erts_msacc_cache) : ERTS_MSACC_STATE_OTHER
+#define ERTS_MSACC_SET_STATE_M(state) \
+ ERTS_MSACC_DECLARE_CACHE(); \
+ ERTS_MSACC_SET_STATE_CACHED_M(state)
+#define ERTS_MSACC_SET_STATE_CACHED_M(state) \
+ if (ERTS_MSACC_IS_ENABLED_CACHED()) \
+ erts_msacc_set_state_m__(__erts_msacc_cache, state, 1)
+#define ERTS_MSACC_POP_STATE_M() \
+ if (ERTS_MSACC_IS_ENABLED_CACHED()) \
+ erts_msacc_set_state_m__(__erts_msacc_cache, __erts_msacc_state, 0)
+#define ERTS_MSACC_PUSH_AND_SET_STATE_M(state) \
+ ERTS_MSACC_PUSH_STATE_M(); ERTS_MSACC_SET_STATE_CACHED_M(state)
+
+ERTS_MSACC_INLINE
+void erts_msacc_set_state_um__(ErtsMsAcc *msacc,Uint state,int increment);
+ERTS_MSACC_INLINE
+void erts_msacc_set_state_m__(ErtsMsAcc *msacc,Uint state,int increment);
+
+ERTS_MSACC_INLINE
+Uint erts_msacc_get_state_um__(ErtsMsAcc *msacc);
+ERTS_MSACC_INLINE
+Uint erts_msacc_get_state_m__(ErtsMsAcc *msacc);
+
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+ERTS_MSACC_INLINE
+Uint erts_msacc_get_state_um__(ErtsMsAcc *msacc) {
+ Uint state;
+ if (msacc->unmanaged)
+ erts_mtx_lock(&msacc->mtx);
+ state = msacc->state;
+ if (msacc->unmanaged)
+ erts_mtx_unlock(&msacc->mtx);
+ return state;
+}
+
+ERTS_MSACC_INLINE
+Uint erts_msacc_get_state_m__(ErtsMsAcc *msacc) {
+ return msacc->state;
+}
+
+ERTS_MSACC_INLINE
+void erts_msacc_set_state_um__(ErtsMsAcc *msacc, Uint new_state, int increment) {
+ if (ERTS_UNLIKELY(msacc->unmanaged)) {
+ erts_mtx_lock(&msacc->mtx);
+ msacc->state = new_state;
+ if (ERTS_LIKELY(!msacc->perf_counter)) {
+ erts_mtx_unlock(&msacc->mtx);
+ return;
+ }
+ }
+
+ erts_msacc_set_state_m__(msacc,new_state,increment);
+
+ if (ERTS_UNLIKELY(msacc->unmanaged))
+ erts_mtx_unlock(&msacc->mtx);
+}
+
+ERTS_MSACC_INLINE
+void erts_msacc_set_state_m__(ErtsMsAcc *msacc, Uint new_state, int increment) {
+ ErtsSysPerfCounter prev_perf_counter;
+ Sint64 diff;
+
+ if (new_state == msacc->state)
+ return;
+
+ prev_perf_counter = msacc->perf_counter;
+ msacc->perf_counter = erts_sys_perf_counter();
+ diff = msacc->perf_counter - prev_perf_counter;
+ ASSERT(diff >= 0);
+ msacc->perf_counters[msacc->state] += diff;
+#ifdef ERTS_MSACC_STATE_COUNTERS
+ msacc->state_counters[new_state] += increment;
+#endif
+ msacc->state = new_state;
+}
+
+#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
+
+#else
+
+#define ERTS_MSACC_IS_ENABLED() 0
+#define erts_msacc_early_init()
+#define erts_msacc_init()
+#define erts_msacc_init_thread(type, id, liberty)
+#define ERTS_MSACC_PUSH_STATE()
+#define ERTS_MSACC_PUSH_STATE_CACHED()
+#define ERTS_MSACC_POP_STATE()
+#define ERTS_MSACC_SET_STATE(state)
+#define ERTS_MSACC_SET_STATE_CACHED(state)
+#define ERTS_MSACC_PUSH_AND_SET_STATE(state)
+#define ERTS_MSACC_PUSH_AND_SET_STATE_CACHED(state)
+#define ERTS_MSACC_UPDATE_CACHE()
+#define ERTS_MSACC_IS_ENABLED_CACHED()
+#define ERTS_MSACC_DECLARE_CACHE()
+#define ERTS_MSACC_PUSH_STATE_M()
+#define ERTS_MSACC_PUSH_STATE_CACHED_M()
+#define ERTS_MSACC_SET_STATE_CACHED_M(state)
+#define ERTS_MSACC_POP_STATE_M()
+#define ERTS_MSACC_PUSH_AND_SET_STATE_M(state)
+
+
+#endif /* ERTS_ENABLE_MSACC */
+
+#ifndef ERTS_MSACC_EXTENDED_STATES
+
+#define ERTS_MSACC_PUSH_STATE_X()
+#define ERTS_MSACC_POP_STATE_X()
+#define ERTS_MSACC_SET_STATE_X(state)
+#define ERTS_MSACC_SET_STATE_M_X(state)
+#define ERTS_MSACC_SET_STATE_CACHED_X(state)
+#define ERTS_MSACC_PUSH_AND_SET_STATE_X(state)
+#define ERTS_MSACC_PUSH_AND_SET_STATE_CACHED_X(state)
+#define ERTS_MSACC_UPDATE_CACHE_X()
+#define ERTS_MSACC_IS_ENABLED_CACHED_X() 0
+#define ERTS_MSACC_DECLARE_CACHE_X()
+#define ERTS_MSACC_PUSH_STATE_M_X()
+#define ERTS_MSACC_PUSH_STATE_CACHED_M_X()
+#define ERTS_MSACC_SET_STATE_CACHED_M_X(state)
+#define ERTS_MSACC_POP_STATE_M_X()
+#define ERTS_MSACC_PUSH_AND_SET_STATE_M_X(state)
+
+#else
+
+#define ERTS_MSACC_PUSH_STATE_X() ERTS_MSACC_PUSH_STATE()
+#define ERTS_MSACC_POP_STATE_X() ERTS_MSACC_POP_STATE()
+#define ERTS_MSACC_SET_STATE_X(state) ERTS_MSACC_SET_STATE(state)
+#define ERTS_MSACC_SET_STATE_M_X(state) ERTS_MSACC_SET_STATE_M(state)
+#define ERTS_MSACC_SET_STATE_CACHED_X(state) ERTS_MSACC_SET_STATE_CACHED(state)
+#define ERTS_MSACC_PUSH_AND_SET_STATE_X(state) ERTS_MSACC_PUSH_AND_SET_STATE(state)
+#define ERTS_MSACC_PUSH_AND_SET_STATE_CACHED_X(state) ERTS_MSACC_PUSH_AND_SET_STATE_CACHED(state)
+#define ERTS_MSACC_UPDATE_CACHE_X() ERTS_MSACC_UPDATE_CACHE()
+#define ERTS_MSACC_IS_ENABLED_CACHED_X() ERTS_MSACC_IS_ENABLED_CACHED()
+#define ERTS_MSACC_DECLARE_CACHE_X() ERTS_MSACC_DECLARE_CACHE()
+#define ERTS_MSACC_PUSH_STATE_M_X() ERTS_MSACC_PUSH_STATE_M()
+#define ERTS_MSACC_PUSH_STATE_CACHED_M_X() ERTS_MSACC_PUSH_STATE_CACHED_M()
+#define ERTS_MSACC_SET_STATE_CACHED_M_X(state) ERTS_MSACC_SET_STATE_CACHED_M(state)
+#define ERTS_MSACC_POP_STATE_M_X() ERTS_MSACC_POP_STATE_M()
+#define ERTS_MSACC_PUSH_AND_SET_STATE_M_X(state) ERTS_MSACC_PUSH_AND_SET_STATE_M(state)
+
+#endif /* !ERTS_MSACC_EXTENDED_STATES */
+
+#endif /* ERL_MSACC_H__ */
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index 1097916c97..8580bc2689 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -314,6 +314,7 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid,
ErtsProcLocks rp_locks = 0;
Process* rp;
Process* c_p;
+ ErtsMessage *mp;
ErlHeapFragment* frags;
Eterm receiver = to_pid->pid;
int flush_me = 0;
@@ -347,7 +348,7 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid,
ASSERT(frags == MBUF(&menv->phony_proc));
if (frags != NULL) {
/* Move all offheap's from phony proc to the first fragment.
- Quick and dirty, but erts_move_msg_mbuf_to_heap doesn't care. */
+ Quick and dirty... */
ASSERT(!is_offheap(&frags->off_heap));
frags->off_heap = MSO(&menv->phony_proc);
clear_offheap(&MSO(&menv->phony_proc));
@@ -359,7 +360,9 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid,
if (flush_me) {
flush_env(env); /* Needed for ERTS_HOLE_CHECK */
}
- erts_queue_message(rp, &rp_locks, frags, msg, am_undefined);
+ mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = frags;
+ erts_queue_message(rp, &rp_locks, mp, msg, am_undefined);
if (c_p == rp)
rp_locks &= ~ERTS_PROC_LOCK_MAIN;
if (rp_locks)
@@ -376,9 +379,19 @@ ERL_NIF_TERM enif_make_copy(ErlNifEnv* dst_env, ERL_NIF_TERM src_term)
{
Uint sz;
Eterm* hp;
+#ifdef SHCOPY
+ erts_shcopy_t info;
+ INITIALIZE_SHCOPY(info);
+ sz = copy_shared_calculate(src_term, &info);
+ hp = alloc_heap(dst_env, sz);
+ src_term = copy_shared_perform(src_term, sz, &info, &hp, &MSO(dst_env->proc));
+ DESTROY_SHCOPY(info);
+ return src_term;
+#else
sz = size_object(src_term);
hp = alloc_heap(dst_env, sz);
return copy_struct(src_term, sz, &hp, &MSO(dst_env->proc));
+#endif
}
@@ -898,8 +911,13 @@ int enif_get_list_cell(ErlNifEnv* env, Eterm term, Eterm* head, Eterm* tail)
int enif_get_list_length(ErlNifEnv* env, Eterm term, unsigned* len)
{
- if (is_not_list(term) && is_not_nil(term)) return 0;
- *len = erts_list_length(term);
+ Sint i;
+ Uint u;
+
+ if ((i = erts_list_length(term)) < 0) return 0;
+ u = (Uint)i;
+ if ((unsigned)u != u) return 0;
+ *len = u;
return 1;
}
@@ -1792,12 +1810,10 @@ execute_dirty_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
ep = (NifExport*) ERTS_PROC_GET_NIF_TRAP_EXPORT(proc);
ASSERT(ep);
ep->fp = NULL;
+ erts_smp_atomic32_read_band_mb(&proc->state, ~(ERTS_PSFLG_DIRTY_CPU_PROC
+ | ERTS_PSFLG_DIRTY_IO_PROC));
result = (*fp)(env, argc, argv);
- erts_smp_atomic32_read_band_mb(&proc->state,
- ~(ERTS_PSFLG_DIRTY_CPU_PROC
- |ERTS_PSFLG_DIRTY_IO_PROC
- |ERTS_PSFLG_DIRTY_CPU_PROC_IN_Q
- |ERTS_PSFLG_DIRTY_IO_PROC_IN_Q));
+
if (erts_refc_dectest(&env->mod_nif->rt_dtor_cnt, 0) == 0 && env->mod_nif->mod == NULL)
close_lib(env->mod_nif);
/*
@@ -1845,13 +1861,6 @@ schedule_dirty_nif(ErlNifEnv* env, int flags, int argc, const ERL_NIF_TERM argv[
a = erts_smp_atomic32_read_acqb(&proc->state);
while (1) {
n = state = a;
- /*
- * clear any current dirty flags and dirty queue indicators,
- * in case the application is shifting a job from one type
- * of dirty scheduler to the other
- */
- n &= ~(ERTS_PSFLG_DIRTY_CPU_PROC|ERTS_PSFLG_DIRTY_IO_PROC
- |ERTS_PSFLG_DIRTY_CPU_PROC_IN_Q|ERTS_PSFLG_DIRTY_IO_PROC_IN_Q);
if (flags == ERL_NIF_DIRTY_JOB_CPU_BOUND)
n |= ERTS_PSFLG_DIRTY_CPU_PROC;
else
@@ -2251,17 +2260,17 @@ int enif_map_iterator_get_pair(ErlNifEnv *env,
***************************************************************************/
-static BeamInstr** get_func_pp(BeamInstr* mod_code, Eterm f_atom, unsigned arity)
+static BeamInstr** get_func_pp(BeamCodeHeader* mod_code, Eterm f_atom, unsigned arity)
{
- int n = (int) mod_code[MI_NUM_FUNCTIONS];
+ int n = (int) mod_code->num_functions;
int j;
for (j = 0; j < n; ++j) {
- BeamInstr* code_ptr = (BeamInstr*) mod_code[MI_FUNCTIONS+j];
+ BeamInstr* code_ptr = (BeamInstr*) mod_code->functions[j];
ASSERT(code_ptr[0] == (BeamInstr) BeamOp(op_i_func_info_IaaI));
if (f_atom == ((Eterm) code_ptr[3])
&& arity == ((unsigned) code_ptr[4])) {
- return (BeamInstr**) &mod_code[MI_FUNCTIONS+j];
+ return (BeamInstr**) &mod_code->functions[j];
}
}
return NULL;
@@ -2444,8 +2453,8 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
if (init_func != NULL)
handle = init_func;
- if (!in_area(caller, mod->curr.code, mod->curr.code_length)) {
- ASSERT(in_area(caller, mod->old.code, mod->old.code_length));
+ if (!in_area(caller, mod->curr.code_hdr, mod->curr.code_length)) {
+ ASSERT(in_area(caller, mod->old.code_hdr, mod->old.code_length));
ret = load_nif_error(BIF_P, "old_code", "Calling load_nif from old "
"module '%T' not allowed", mod_atom);
@@ -2499,7 +2508,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
for (i=0; i < entry->num_of_funcs && ret==am_ok; i++) {
BeamInstr** code_pp;
if (!erts_atom_get(f->name, sys_strlen(f->name), &f_atom, ERTS_ATOM_ENC_LATIN1)
- || (code_pp = get_func_pp(mod->curr.code, f_atom, f->arity))==NULL) {
+ || (code_pp = get_func_pp(mod->curr.code_hdr, f_atom, f->arity))==NULL) {
ret = load_nif_error(BIF_P,bad_lib,"Function not found %T:%s/%u",
mod_atom, f->name, f->arity);
}
@@ -2642,7 +2651,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
{
BeamInstr* code_ptr;
erts_atom_get(f->name, sys_strlen(f->name), &f_atom, ERTS_ATOM_ENC_LATIN1);
- code_ptr = *get_func_pp(mod->curr.code, f_atom, f->arity);
+ code_ptr = *get_func_pp(mod->curr.code_hdr, f_atom, f->arity);
if (code_ptr[1] == 0) {
code_ptr[5+0] = (BeamInstr) BeamOp(op_call_nif);
diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h
index 75070ad901..c9c8b1d0af 100644
--- a/erts/emulator/beam/erl_nif.h
+++ b/erts/emulator/beam/erl_nif.h
@@ -77,13 +77,8 @@ typedef ErlNapiSInt64 ErlNifSInt64;
typedef ErlNapiUInt ErlNifUInt;
typedef ErlNapiSInt ErlNifSInt;
-#ifdef HALFWORD_HEAP_EMULATOR
-# define ERL_NIF_VM_VARIANT "beam.halfword"
-typedef unsigned int ERL_NIF_TERM;
-#else
# define ERL_NIF_VM_VARIANT "beam.vanilla"
typedef ErlNifUInt ERL_NIF_TERM;
-#endif
typedef ERL_NIF_TERM ERL_NIF_UINT;
@@ -226,22 +221,28 @@ extern TWinDynNifCallbacks WinDynNifCallbacks;
#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_))
# define ERL_NIF_INIT_GLOB TWinDynNifCallbacks WinDynNifCallbacks;
-# ifdef STATIC_ERLANG_NIF
-# define ERL_NIF_INIT_DECL(MODNAME) __declspec(dllexport) ErlNifEntry* MODNAME ## _nif_init(TWinDynNifCallbacks* callbacks)
-# else
-# define ERL_NIF_INIT_DECL(MODNAME) __declspec(dllexport) ErlNifEntry* nif_init(TWinDynNifCallbacks* callbacks)
-# endif
+# define ERL_NIF_INIT_ARGS TWinDynNifCallbacks* callbacks
# define ERL_NIF_INIT_BODY memcpy(&WinDynNifCallbacks,callbacks,sizeof(TWinDynNifCallbacks))
+# define ERL_NIF_INIT_EXPORT __declspec(dllexport)
#else
# define ERL_NIF_INIT_GLOB
+# define ERL_NIF_INIT_ARGS void
# define ERL_NIF_INIT_BODY
-# ifdef STATIC_ERLANG_NIF
-# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* MODNAME ## _nif_init(void)
+# if defined(__GNUC__) && __GNUC__ >= 4
+# define ERL_NIF_INIT_EXPORT __attribute__ ((visibility("default")))
+# elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+# define ERL_NIF_INIT_EXPORT __global
# else
-# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* nif_init(void)
+# define ERL_NIF_INIT_EXPORT
# endif
#endif
+#ifdef STATIC_ERLANG_NIF
+# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* MODNAME ## _nif_init(ERL_NIF_INIT_ARGS)
+#else
+# define ERL_NIF_INIT_DECL(MODNAME) ERL_NIF_INIT_EXPORT ErlNifEntry* nif_init(ERL_NIF_INIT_ARGS)
+#endif
+
#ifdef ERL_NIF_DIRTY_SCHEDULER_SUPPORT
# define ERL_NIF_ENTRY_OPTIONS ERL_NIF_DIRTY_NIF_OPTION
#else
diff --git a/erts/emulator/beam/erl_node_container_utils.h b/erts/emulator/beam/erl_node_container_utils.h
index 211b1a0090..b6a3531e28 100644
--- a/erts/emulator/beam/erl_node_container_utils.h
+++ b/erts/emulator/beam/erl_node_container_utils.h
@@ -255,7 +255,7 @@ extern ErtsPTab erts_port;
* Refs *
\* */
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
#define internal_ref_no_of_numbers(x) \
(internal_ref_data((x))[0])
@@ -328,8 +328,6 @@ extern ErtsPTab erts_port;
: external_ref_channel_no((x)))
#define is_ref(x) (is_internal_ref((x)) \
|| is_external_ref((x)))
-#define is_ref_rel(x,Base) (is_internal_ref_rel((x),Base) \
- || is_external_ref_rel((x),Base))
#define is_not_ref(x) (!is_ref(x))
#endif
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index e69bd49c42..8617f42d7b 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -787,10 +787,13 @@ void erts_init_node_tables(int dd_sec)
erts_smp_rwmtx_init_opt(&erts_node_table_rwmtx, &rwmtx_opt, "node_table");
erts_smp_rwmtx_init_opt(&erts_dist_table_rwmtx, &rwmtx_opt, "dist_table");
- f.hash = (H_FUN) dist_table_hash;
- f.cmp = (HCMP_FUN) dist_table_cmp;
- f.alloc = (HALLOC_FUN) dist_table_alloc;
- f.free = (HFREE_FUN) dist_table_free;
+ f.hash = (H_FUN) dist_table_hash;
+ f.cmp = (HCMP_FUN) dist_table_cmp;
+ f.alloc = (HALLOC_FUN) dist_table_alloc;
+ f.free = (HFREE_FUN) dist_table_free;
+ f.meta_alloc = (HMALLOC_FUN) erts_alloc;
+ f.meta_free = (HMFREE_FUN) erts_free;
+ f.meta_print = (HMPRINT_FUN) erts_print;
hash_init(ERTS_ALC_T_DIST_TABLE, &erts_dist_table, "dist_table", 11, f);
f.hash = (H_FUN) node_table_hash;
@@ -1157,23 +1160,11 @@ insert_offheap(ErlOffHeap *oh, int type, Eterm id)
break;
}
if (insert_bin) {
-#if HALFWORD_HEAP
- UWord val = (UWord) u.pb->val;
- DeclareTmpHeapNoproc(id_heap,BIG_UINT_HEAP_SIZE*2); /* extra place allocated */
-#else
DeclareTmpHeapNoproc(id_heap,BIG_UINT_HEAP_SIZE);
-#endif
Uint *hp = &id_heap[0];
InsertedBin *nib;
-#if HALFWORD_HEAP
- int actual_need = BIG_UWORD_HEAP_SIZE(val);
- ASSERT(actual_need <= (BIG_UINT_HEAP_SIZE*2));
- UseTmpHeapNoproc(actual_need);
- a.id = erts_bld_uword(&hp, NULL, (UWord) val);
-#else
UseTmpHeapNoproc(BIG_UINT_HEAP_SIZE);
a.id = erts_bld_uint(&hp, NULL, (Uint) u.pb->val);
-#endif
erts_match_prog_foreach_offheap(u.pb->val,
insert_offheap2,
(void *) &a);
@@ -1181,11 +1172,7 @@ insert_offheap(ErlOffHeap *oh, int type, Eterm id)
nib->bin_val = u.pb->val;
nib->next = inserted_bins;
inserted_bins = nib;
-#if HALFWORD_HEAP
- UnUseTmpHeapNoproc(actual_need);
-#else
UnUseTmpHeapNoproc(BIG_UINT_HEAP_SIZE);
-#endif
}
}
break;
@@ -1371,56 +1358,50 @@ setup_reference_table(void)
for (i = 0; i < max; i++) {
Process *proc = erts_pix2proc(i);
if (proc) {
- ErlMessage *msg;
+ int mli;
+ ErtsMessage *msg_list[] = {
+ proc->msg.first,
+#ifdef ERTS_SMP
+ proc->msg_inq.first,
+#endif
+ proc->msg_frag};
/* Insert Heap */
insert_offheap(&(proc->off_heap),
HEAP_REF,
proc->common.id);
- /* Insert message buffers */
+ /* Insert heap fragments buffers */
for(hfp = proc->mbuf; hfp; hfp = hfp->next)
insert_offheap(&(hfp->off_heap),
HEAP_REF,
proc->common.id);
- /* Insert msg msg buffers */
- for (msg = proc->msg.first; msg; msg = msg->next) {
- ErlHeapFragment *heap_frag = NULL;
- if (msg->data.attached) {
- if (is_value(ERL_MESSAGE_TERM(msg)))
- heap_frag = msg->data.heap_frag;
- else {
- if (msg->data.dist_ext->dep)
- insert_dist_entry(msg->data.dist_ext->dep,
- HEAP_REF, proc->common.id, 0);
- if (is_not_nil(ERL_MESSAGE_TOKEN(msg)))
- heap_frag = erts_dist_ext_trailer(msg->data.dist_ext);
+
+ /* Insert msg buffers */
+ for (mli = 0; mli < sizeof(msg_list)/sizeof(msg_list[0]); mli++) {
+ ErtsMessage *msg;
+ for (msg = msg_list[mli]; msg; msg = msg->next) {
+ ErlHeapFragment *heap_frag = NULL;
+ if (msg->data.attached) {
+ if (msg->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ heap_frag = &msg->hfrag;
+ else if (is_value(ERL_MESSAGE_TERM(msg)))
+ heap_frag = msg->data.heap_frag;
+ else {
+ if (msg->data.dist_ext->dep)
+ insert_dist_entry(msg->data.dist_ext->dep,
+ HEAP_REF, proc->common.id, 0);
+ if (is_not_nil(ERL_MESSAGE_TOKEN(msg)))
+ heap_frag = erts_dist_ext_trailer(msg->data.dist_ext);
+ }
}
- }
- if (heap_frag)
- insert_offheap(&(heap_frag->off_heap),
- HEAP_REF,
- proc->common.id);
- }
-#ifdef ERTS_SMP
- for (msg = proc->msg_inq.first; msg; msg = msg->next) {
- ErlHeapFragment *heap_frag = NULL;
- if (msg->data.attached) {
- if (is_value(ERL_MESSAGE_TERM(msg)))
- heap_frag = msg->data.heap_frag;
- else {
- if (msg->data.dist_ext->dep)
- insert_dist_entry(msg->data.dist_ext->dep,
- HEAP_REF, proc->common.id, 0);
- if (is_not_nil(ERL_MESSAGE_TOKEN(msg)))
- heap_frag = erts_dist_ext_trailer(msg->data.dist_ext);
+ while (heap_frag) {
+ insert_offheap(&(heap_frag->off_heap),
+ HEAP_REF,
+ proc->common.id);
+ heap_frag = heap_frag->next;
}
}
- if (heap_frag)
- insert_offheap(&(heap_frag->off_heap),
- HEAP_REF,
- proc->common.id);
}
-#endif
/* Insert links */
if (ERTS_P_LINKS(proc))
insert_links(ERTS_P_LINKS(proc), proc->common.id);
diff --git a/erts/emulator/beam/erl_node_tables.h b/erts/emulator/beam/erl_node_tables.h
index 694ac84232..fb2f2a5407 100644
--- a/erts/emulator/beam/erl_node_tables.h
+++ b/erts/emulator/beam/erl_node_tables.h
@@ -41,6 +41,7 @@
#include "sys.h"
#include "hash.h"
+#include "erl_alloc.h"
#include "erl_process.h"
#include "erl_monitors.h"
#include "erl_smp.h"
@@ -66,7 +67,7 @@
#define ERTS_DE_QFLGS_ALL (ERTS_DE_QFLG_BUSY \
| ERTS_DE_QFLG_EXIT)
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
#define ERTS_DIST_OUTPUT_BUF_DBG_PATTERN ((Uint) 0xf713f713f713f713UL)
#else
#define ERTS_DIST_OUTPUT_BUF_DBG_PATTERN ((Uint) 0xf713f713)
diff --git a/erts/emulator/beam/erl_port.h b/erts/emulator/beam/erl_port.h
index acd68ef0ad..fa97707a87 100644
--- a/erts/emulator/beam/erl_port.h
+++ b/erts/emulator/beam/erl_port.h
@@ -187,6 +187,11 @@ struct _erl_drv_port {
ErtsPrtSD *psd; /* Port specific data */
int reds; /* Only used while executing driver callbacks */
+
+ struct {
+ Eterm to;
+ Uint32 ref[ERTS_MAX_REF_NUMBERS];
+ } *async_open_port; /* Reference used with async open port */
};
@@ -687,7 +692,7 @@ erts_drvport2port_state(ErlDrvPort drvport, erts_aint32_t *statep)
Port *prt = ERTS_ErlDrvPort2Port(drvport);
erts_aint32_t state;
ASSERT(prt);
- ERTS_LC_ASSERT(erts_lc_is_emu_thr());
+// ERTS_LC_ASSERT(erts_lc_is_emu_thr());
if (prt == ERTS_INVALID_ERL_DRV_PORT)
return ERTS_INVALID_ERL_DRV_PORT;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt)
@@ -944,4 +949,9 @@ ErtsPortOpResult erts_port_control(Process *, Port *, unsigned int, Eterm, Eterm
ErtsPortOpResult erts_port_call(Process *, Port *, unsigned int, Eterm, Eterm *);
ErtsPortOpResult erts_port_info(Process *, Port *, Eterm, Eterm *);
+/*
+ * Signals from ports to ports. Used by sys drivers.
+ */
+int erl_drv_port_control(Eterm, char, char*, ErlDrvSizeT);
+
#endif
diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c
index ddcca06b0a..e85395e062 100644
--- a/erts/emulator/beam/erl_port_task.c
+++ b/erts/emulator/beam/erl_port_task.c
@@ -1648,6 +1648,7 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
int active;
Uint64 start_time = 0;
ErtsSchedulerData *esdp = runq->scheduler;
+ ERTS_MSACC_PUSH_STATE_M();
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(runq));
@@ -1690,6 +1691,7 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
state = erts_atomic32_read_nob(&pp->state);
pp->reds = ERTS_PORT_REDS_EXECUTE;
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_PORT);
goto begin_handle_tasks;
while (1) {
@@ -1734,7 +1736,7 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
reds = ERTS_PORT_REDS_INPUT;
ASSERT((state & ERTS_PORT_SFLGS_DEAD) == 0);
DTRACE_DRIVER(driver_ready_input, pp);
- /* NOTE some windows/ose drivers use ->ready_input
+ /* NOTE some windows drivers use ->ready_input
for input and output */
(*pp->drv_ptr->ready_input)((ErlDrvData) pp->drv_data,
ptp->u.alive.td.io.event);
@@ -1822,6 +1824,7 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
}
erts_unblock_fpe(fpe_was_unmasked);
+ ERTS_MSACC_POP_STATE_M();
if (io_tasks_executed) {
diff --git a/erts/emulator/beam/erl_printf_term.c b/erts/emulator/beam/erl_printf_term.c
index 2917d58932..45ba4371dc 100644
--- a/erts/emulator/beam/erl_printf_term.c
+++ b/erts/emulator/beam/erl_printf_term.c
@@ -117,13 +117,12 @@ do { \
/* return 0 if list is not a non-empty flat list of printable characters */
static int
-is_printable_string(Eterm list, Eterm* base)
-{
+is_printable_string(Eterm list) {
int len = 0;
int c;
while(is_list(list)) {
- Eterm* consp = list_val_rel(list, base);
+ Eterm* consp = list_val(list);
Eterm hd = CAR(consp);
if (!is_byte(hd))
@@ -260,9 +259,7 @@ static char *format_binary(Uint16 x, char *b) {
#endif
static int
-print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount,
- Eterm* obj_base) /* ignored if !HALFWORD_HEAP */
-{
+print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount) {
DECLARE_WSTACK(s);
int res;
int i;
@@ -308,7 +305,7 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount,
obj = (Eterm) popped.word;
L_print_one_cons:
{
- Eterm* cons = list_val_rel(obj, obj_base);
+ Eterm* cons = list_val(obj);
Eterm tl;
obj = CAR(cons);
@@ -344,11 +341,7 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount,
PRINT_CHAR(res, fn, arg, '>');
goto L_done;
}
-#if HALFWORD_HEAP
- wobj = is_immed(obj) ? (Wterm)obj : rterm2wterm(obj, obj_base);
-#else
wobj = (Wterm)obj;
-#endif
switch (tag_val_def(wobj)) {
case NIL_DEF:
PRINT_STRING(res, fn, arg, "[]");
@@ -424,10 +417,10 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount,
PRINT_CHAR(res, fn, arg, '>');
break;
case LIST_DEF:
- if (is_printable_string(obj, obj_base)) {
+ if (is_printable_string(obj)) {
int c;
PRINT_CHAR(res, fn, arg, '"');
- nobj = list_val_rel(obj, obj_base);
+ nobj = list_val(obj);
while (1) {
if ((*dcount)-- <= 0)
goto L_done;
@@ -441,7 +434,7 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount,
}
if (is_not_list(*nobj))
break;
- nobj = list_val_rel(*nobj, obj_base);
+ nobj = list_val(*nobj);
}
PRINT_CHAR(res, fn, arg, '"');
} else {
@@ -469,11 +462,11 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount,
case BINARY_DEF:
{
byte* bytep;
- Uint bytesize = binary_size_rel(obj,obj_base);
+ Uint bytesize = binary_size(obj);
Uint bitoffs;
Uint bitsize;
byte octet;
- ERTS_GET_BINARY_BYTES_REL(obj, bytep, bitoffs, bitsize, obj_base);
+ ERTS_GET_BINARY_BYTES(obj, bytep, bitoffs, bitsize);
if (bitsize || !bytesize
|| !is_printable_ascii(bytep, bytesize, bitoffs)) {
@@ -648,13 +641,11 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount,
int
-erts_printf_term(fmtfn_t fn, void* arg, ErlPfEterm term, long precision,
- ErlPfEterm* term_base)
-{
+erts_printf_term(fmtfn_t fn, void* arg, ErlPfEterm term, long precision) {
int res;
ERTS_CT_ASSERT(sizeof(ErlPfEterm) == sizeof(Eterm));
- res = print_term(fn, arg, (Eterm)term, &precision, (Eterm*)term_base);
+ res = print_term(fn, arg, (Eterm)term, &precision);
if (res < 0)
return res;
if (precision <= 0)
diff --git a/erts/emulator/beam/erl_printf_term.h b/erts/emulator/beam/erl_printf_term.h
index 87618a36d7..4618457f27 100644
--- a/erts/emulator/beam/erl_printf_term.h
+++ b/erts/emulator/beam/erl_printf_term.h
@@ -22,6 +22,5 @@
#define ERL_PRINTF_TERM_H__
#include "erl_printf_format.h"
-int erts_printf_term(fmtfn_t fn, void* arg, ErlPfEterm term, long precision,
- ErlPfEterm* term_base);
+int erts_printf_term(fmtfn_t fn, void* arg, ErlPfEterm term, long precision);
#endif
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index c2afcc9c4f..a706ebf595 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -58,11 +58,7 @@
#define ERTS_PROC_MIN_CONTEXT_SWITCH_REDS_COST (CONTEXT_REDS/10)
-#ifndef ERTS_SCHED_MIN_SPIN
#define ERTS_SCHED_SPIN_UNTIL_YIELD 100
-#else
-#define ERTS_SCHED_SPIN_UNTIL_YIELD 1
-#endif
#define ERTS_SCHED_SYS_SLEEP_SPINCOUNT_VERY_LONG 40
#define ERTS_SCHED_AUX_WORK_SLEEP_SPINCOUNT_FACT_VERY_LONG 1000
@@ -119,7 +115,7 @@
#define RUNQ_SET_RQ(X, RQ) erts_smp_atomic_set_nob((X), (erts_aint_t) (RQ))
#ifdef DEBUG
-# if defined(ARCH_64) && !HALFWORD_HEAP
+# if defined(ARCH_64)
# define ERTS_DBG_SET_INVALID_RUNQP(RQP, N) \
(RUNQ_SET_RQ((RQP), (0xdeadbeefdead0003LL | ((N) << 4)))
# define ERTS_DBG_VERIFY_VALID_RUNQP(RQP) \
@@ -152,19 +148,13 @@ extern BeamInstr beam_apply[];
extern BeamInstr beam_exit[];
extern BeamInstr beam_continue_exit[];
-#ifdef __OSE__
-/* Eager check I/O not supported on OSE yet. */
-int erts_eager_check_io = 0;
-#else
-int erts_eager_check_io = 1;
-#endif
-int erts_sched_compact_load;
-int erts_sched_balance_util = 0;
-Uint erts_no_schedulers;
-#ifdef ERTS_DIRTY_SCHEDULERS
-Uint erts_no_dirty_cpu_schedulers;
-Uint erts_no_dirty_io_schedulers;
-#endif
+int ERTS_WRITE_UNLIKELY(erts_default_spo_flags) = 0;
+int ERTS_WRITE_UNLIKELY(erts_eager_check_io) = 1;
+int ERTS_WRITE_UNLIKELY(erts_sched_compact_load);
+int ERTS_WRITE_UNLIKELY(erts_sched_balance_util) = 0;
+Uint ERTS_WRITE_UNLIKELY(erts_no_schedulers);
+Uint ERTS_WRITE_UNLIKELY(erts_no_dirty_cpu_schedulers) = 0;
+Uint ERTS_WRITE_UNLIKELY(erts_no_dirty_io_schedulers) = 0;
static char *erts_aux_work_flag_descr[ERTS_SSI_AUX_WORK_NO_FLAGS] = {0};
int erts_aux_work_no_flags = ERTS_SSI_AUX_WORK_NO_FLAGS;
@@ -196,84 +186,176 @@ int erts_disable_proc_not_running_opt;
static ErtsAuxWorkData *aux_thread_aux_work_data;
-#define ERTS_SCHDLR_SSPND_CHNG_WAITER (((erts_aint32_t) 1) << 0)
+#define ERTS_SCHDLR_SSPND_CHNG_NMSB (((erts_aint32_t) 1) << 0)
#define ERTS_SCHDLR_SSPND_CHNG_MSB (((erts_aint32_t) 1) << 1)
#define ERTS_SCHDLR_SSPND_CHNG_ONLN (((erts_aint32_t) 1) << 2)
+#define ERTS_SCHDLR_SSPND_CHNG_DCPU_ONLN (((erts_aint32_t) 1) << 3)
-#ifndef DEBUG
+typedef enum {
+ ERTS_SCHED_NORMAL,
+ ERTS_SCHED_DIRTY_CPU,
+ ERTS_SCHED_DIRTY_IO
+} ErtsSchedType;
-#define ERTS_SCHDLR_SSPND_CHNG_SET(VAL, OLD_VAL) \
- erts_smp_atomic32_set_nob(&schdlr_sspnd.changing, (VAL))
+typedef struct {
+ int ongoing;
+ ErtsProcList *blckrs;
+ ErtsProcList *chngq;
+} ErtsMultiSchedulingBlock;
-#ifdef ERTS_DIRTY_SCHEDULERS
-#define ERTS_SCHDLR_SSPND_DIRTY_CPU_CHNG_SET(VAL, OLD_VAL) \
- erts_smp_atomic32_set_nob(&schdlr_sspnd.dirty_cpu_changing, (VAL))
-#define ERTS_SCHDLR_SSPND_DIRTY_IO_CHNG_SET(VAL, OLD_VAL) \
- erts_smp_atomic32_set_nob(&schdlr_sspnd.dirty_io_changing, (VAL))
-#endif
+static struct {
+ erts_smp_mtx_t mtx;
+ Uint32 online;
+ Uint32 curr_online;
+ Uint32 active;
+ erts_smp_atomic32_t changing;
+ ErtsProcList *chngq;
+ Eterm changer;
+ ErtsMultiSchedulingBlock nmsb; /* Normal multi Scheduling Block */
+ ErtsMultiSchedulingBlock msb; /* Multi Scheduling Block */
+} schdlr_sspnd;
-#else
+#define ERTS_SCHDLR_SSPND_S_BITS 10
+#define ERTS_SCHDLR_SSPND_DCS_BITS 11
+#define ERTS_SCHDLR_SSPND_DIS_BITS 11
-#define ERTS_SCHDLR_SSPND_CHNG_SET(VAL, OLD_VAL) \
-do { \
- erts_aint32_t old_val__; \
- old_val__ = erts_smp_atomic32_xchg_nob(&schdlr_sspnd.changing, \
- (VAL)); \
- ASSERT(old_val__ == (OLD_VAL)); \
-} while (0)
+#define ERTS_SCHDLR_SSPND_S_MASK ((1 << ERTS_SCHDLR_SSPND_S_BITS)-1)
+#define ERTS_SCHDLR_SSPND_DCS_MASK ((1 << ERTS_SCHDLR_SSPND_DCS_BITS)-1)
+#define ERTS_SCHDLR_SSPND_DIS_MASK ((1 << ERTS_SCHDLR_SSPND_DIS_BITS)-1)
-#ifdef ERTS_DIRTY_SCHEDULERS
-#define ERTS_SCHDLR_SSPND_DIRTY_CPU_CHNG_SET(VAL, OLD_VAL) \
-do { \
- erts_aint32_t old_val__; \
- old_val__ = erts_smp_atomic32_xchg_nob(&schdlr_sspnd.dirty_cpu_changing, \
- (VAL)); \
- ASSERT(old_val__ == (OLD_VAL)); \
-} while (0)
-#define ERTS_SCHDLR_SSPND_DIRTY_IO_CHNG_SET(VAL, OLD_VAL) \
-do { \
- erts_aint32_t old_val__; \
- old_val__ = erts_smp_atomic32_xchg_nob(&schdlr_sspnd.dirty_io_changing, \
- (VAL)); \
- ASSERT(old_val__ == (OLD_VAL)); \
-} while (0)
-#endif
+#define ERTS_SCHDLR_SSPND_S_SHIFT 0
+#define ERTS_SCHDLR_SSPND_DCS_SHIFT (ERTS_SCHDLR_SSPND_S_SHIFT \
+ + ERTS_SCHDLR_SSPND_S_BITS)
+#define ERTS_SCHDLR_SSPND_DIS_SHIFT (ERTS_SCHDLR_SSPND_DCS_SHIFT \
+ + ERTS_SCHDLR_SSPND_DCS_BITS)
+#if (ERTS_SCHDLR_SSPND_S_BITS \
+ + ERTS_SCHDLR_SSPND_DCS_BITS \
+ + ERTS_SCHDLR_SSPND_DIS_BITS) > 32
+# error Wont fit in Uint32
#endif
-
-static struct {
- erts_smp_mtx_t mtx;
- erts_smp_cnd_t cnd;
- int online;
- int curr_online;
- int wait_curr_online;
-#ifdef ERTS_DIRTY_SCHEDULERS
- int dirty_cpu_online;
- int dirty_cpu_curr_online;
- int dirty_cpu_wait_curr_online;
- int dirty_io_online;
- int dirty_io_curr_online;
- int dirty_io_wait_curr_online;
+#if (ERTS_MAX_NO_OF_SCHEDULERS-1) > ERTS_SCHDLR_SSPND_S_MASK
+# error Max no schedulers wont fit in its bit-field
#endif
- erts_smp_atomic32_t changing;
- erts_smp_atomic32_t active;
-#ifdef ERTS_DIRTY_SCHEDULERS
- erts_smp_atomic32_t dirty_cpu_changing;
- erts_smp_atomic32_t dirty_cpu_active;
- erts_smp_atomic32_t dirty_io_changing;
- erts_smp_atomic32_t dirty_io_active;
+#if ERTS_MAX_NO_OF_DIRTY_CPU_SCHEDULERS > ERTS_SCHDLR_SSPND_DCS_MASK
+# error Max no dirty cpu schedulers wont fit in its bit-field
#endif
- struct {
- int ongoing;
- long wait_active;
-#ifdef ERTS_DIRTY_SCHEDULERS
- long dirty_cpu_wait_active;
- long dirty_io_wait_active;
+#if ERTS_MAX_NO_OF_DIRTY_IO_SCHEDULERS > ERTS_SCHDLR_SSPND_DIS_MASK
+# error Max no dirty io schedulers wont fit in its bit-field
#endif
- ErtsProcList *procs;
- } msb; /* Multi Scheduling Block */
-} schdlr_sspnd;
+
+#define ERTS_SCHDLR_SSPND_MAKE_NSCHEDS_VAL(S, DCS, DIS) \
+ ((((Uint32) (((S) & ERTS_SCHDLR_SSPND_S_MASK))-1) \
+ << ERTS_SCHDLR_SSPND_S_SHIFT) \
+ | ((((Uint32) ((DCS) & ERTS_SCHDLR_SSPND_DCS_MASK)) \
+ << ERTS_SCHDLR_SSPND_DCS_SHIFT)) \
+ | ((((Uint32) ((DIS) & ERTS_SCHDLR_SSPND_DIS_MASK)) \
+ << ERTS_SCHDLR_SSPND_DIS_SHIFT)))
+
+static void init_scheduler_suspend(void);
+
+static ERTS_INLINE Uint32
+schdlr_sspnd_get_nscheds(Uint32 *valp, ErtsSchedType type)
+{
+ Uint32 res = (Uint32) (*valp);
+ switch (type) {
+ case ERTS_SCHED_NORMAL:
+ res >>= ERTS_SCHDLR_SSPND_S_SHIFT;
+ res &= (Uint32) ERTS_SCHDLR_SSPND_S_MASK;
+ res++;
+ break;
+ case ERTS_SCHED_DIRTY_CPU:
+ res >>= ERTS_SCHDLR_SSPND_DCS_SHIFT;
+ res &= (Uint32) ERTS_SCHDLR_SSPND_DCS_MASK;
+ break;
+ case ERTS_SCHED_DIRTY_IO:
+ res >>= ERTS_SCHDLR_SSPND_DIS_SHIFT;
+ res &= (Uint32) ERTS_SCHDLR_SSPND_DIS_MASK;
+ break;
+ default:
+ ERTS_INTERNAL_ERROR("Invalid scheduler type");
+ return 0;
+ }
+
+ return res;
+}
+
+static ERTS_INLINE void
+schdlr_sspnd_dec_nscheds(Uint32 *valp, ErtsSchedType type)
+{
+ ASSERT(schdlr_sspnd_get_nscheds(valp, type) > 0);
+
+ switch (type) {
+ case ERTS_SCHED_NORMAL:
+ *valp -= ((Uint32) 1) << ERTS_SCHDLR_SSPND_S_SHIFT;
+ break;
+ case ERTS_SCHED_DIRTY_CPU:
+ *valp -= ((Uint32) 1) << ERTS_SCHDLR_SSPND_DCS_SHIFT;
+ break;
+ case ERTS_SCHED_DIRTY_IO:
+ *valp -= ((Uint32) 1) << ERTS_SCHDLR_SSPND_DIS_SHIFT;
+ break;
+ default:
+ ERTS_INTERNAL_ERROR("Invalid scheduler type");
+ }
+}
+
+static ERTS_INLINE void
+schdlr_sspnd_inc_nscheds(Uint32 *valp, ErtsSchedType type)
+{
+ switch (type) {
+ case ERTS_SCHED_NORMAL:
+ ASSERT(schdlr_sspnd_get_nscheds(valp, type)
+ < ERTS_MAX_NO_OF_SCHEDULERS-1);
+ *valp += ((Uint32) 1) << ERTS_SCHDLR_SSPND_S_SHIFT;
+ break;
+ case ERTS_SCHED_DIRTY_CPU:
+ ASSERT(schdlr_sspnd_get_nscheds(valp, type)
+ < ERTS_MAX_NO_OF_DIRTY_CPU_SCHEDULERS);
+ *valp += ((Uint32) 1) << ERTS_SCHDLR_SSPND_DCS_SHIFT;
+ break;
+ case ERTS_SCHED_DIRTY_IO:
+ ASSERT(schdlr_sspnd_get_nscheds(valp, type)
+ < ERTS_MAX_NO_OF_DIRTY_IO_SCHEDULERS);
+ *valp += ((Uint32) 1) << ERTS_SCHDLR_SSPND_DIS_SHIFT;
+ break;
+ default:
+ ERTS_INTERNAL_ERROR("Invalid scheduler type");
+ }
+}
+
+static ERTS_INLINE void
+schdlr_sspnd_set_nscheds(Uint32 *valp, ErtsSchedType type, Uint32 no)
+{
+ Uint32 val = *valp;
+
+ switch (type) {
+ case ERTS_SCHED_NORMAL:
+ ASSERT(no > 0);
+ val &= ~(((Uint32) ERTS_SCHDLR_SSPND_S_MASK)
+ << ERTS_SCHDLR_SSPND_S_SHIFT);
+ val |= (((no-1) & ((Uint32) ERTS_SCHDLR_SSPND_S_MASK))
+ << ERTS_SCHDLR_SSPND_S_SHIFT);
+ break;
+ case ERTS_SCHED_DIRTY_CPU:
+ val &= ~(((Uint32) ERTS_SCHDLR_SSPND_DCS_MASK)
+ << ERTS_SCHDLR_SSPND_DCS_SHIFT);
+ val |= ((no & ((Uint32) ERTS_SCHDLR_SSPND_DCS_MASK))
+ << ERTS_SCHDLR_SSPND_DCS_SHIFT);
+ break;
+ case ERTS_SCHED_DIRTY_IO:
+ val &= ~(((Uint32) ERTS_SCHDLR_SSPND_DIS_MASK)
+ << ERTS_SCHDLR_SSPND_DIS_SHIFT);
+ val |= ((no & ((Uint32) ERTS_SCHDLR_SSPND_DIS_MASK))
+ << ERTS_SCHDLR_SSPND_DIS_SHIFT);
+ break;
+ default:
+ ERTS_INTERNAL_ERROR("Invalid scheduler type");
+ }
+
+ *valp = val;
+}
static struct {
erts_smp_mtx_t update_mtx;
@@ -303,7 +385,7 @@ do { \
erts_sched_stat_t erts_sched_stat;
#ifdef USE_THREADS
-static erts_tsd_key_t sched_data_key;
+static erts_tsd_key_t ERTS_WRITE_UNLIKELY(sched_data_key);
#endif
static erts_smp_atomic32_t function_calls;
@@ -343,11 +425,10 @@ static ErtsAlignedSchedulerSleepInfo *aligned_dirty_io_sched_sleep_info;
static Uint last_reductions;
static Uint last_exact_reductions;
-Uint erts_default_process_flags;
-Eterm erts_system_monitor;
-Eterm erts_system_monitor_long_gc;
-Uint erts_system_monitor_long_schedule;
-Eterm erts_system_monitor_large_heap;
+Eterm ERTS_WRITE_UNLIKELY(erts_system_monitor);
+Eterm ERTS_WRITE_UNLIKELY(erts_system_monitor_long_gc);
+Uint ERTS_WRITE_UNLIKELY(erts_system_monitor_long_schedule);
+Eterm ERTS_WRITE_UNLIKELY(erts_system_monitor_large_heap);
struct erts_system_monitor_flags_t erts_system_monitor_flags;
/* system performance monitor */
@@ -361,7 +442,8 @@ int erts_system_profile_ts_type = ERTS_TRACE_FLG_NOW_TIMESTAMP;
typedef enum {
ERTS_PSTT_GC, /* Garbage Collect */
- ERTS_PSTT_CPC /* Check Process Code */
+ ERTS_PSTT_CPC, /* Check Process Code */
+ ERTS_PSTT_COHMQ /* Change off heap message queue */
} ErtsProcSysTaskType;
#define ERTS_MAX_PROC_SYS_TASK_ARGS 2
@@ -434,8 +516,10 @@ do { \
do { \
ErtsRunQueue *RQVAR; \
int ix__; \
+ int online__ = (int) schdlr_sspnd_get_nscheds(&schdlr_sspnd.online, \
+ ERTS_SCHED_NORMAL); \
ERTS_SMP_LC_ASSERT(erts_smp_lc_mtx_is_locked(&schdlr_sspnd.mtx)); \
- for (ix__ = 0; ix__ < schdlr_sspnd.online; ix__++) { \
+ for (ix__ = 0; ix__ < online__; ix__++) { \
RQVAR = ERTS_RUNQ_IX(ix__); \
erts_smp_runq_lock(RQVAR); \
{ DO; } \
@@ -507,9 +591,6 @@ dbg_chk_aux_work_val(erts_aint32_t value)
#if HAVE_ERTS_MSEG
valid |= ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK;
#endif
-#ifdef ERTS_SMP_SCHEDULERS_NEED_TO_CHECK_CHILDREN
- valid |= ERTS_SSI_AUX_WORK_CHECK_CHILDREN;
-#endif
#ifdef ERTS_SSI_AUX_WORK_REAP_PORTS
valid |= ERTS_SSI_AUX_WORK_REAP_PORTS;
#endif
@@ -596,8 +677,6 @@ erts_pre_init_process(void)
= "MISC_THR_PRGR";
erts_aux_work_flag_descr[ERTS_SSI_AUX_WORK_MISC_IX]
= "MISC";
- erts_aux_work_flag_descr[ERTS_SSI_AUX_WORK_CHECK_CHILDREN_IX]
- = "CHECK_CHILDREN";
erts_aux_work_flag_descr[ERTS_SSI_AUX_WORK_SET_TMO_IX]
= "SET_TMO";
erts_aux_work_flag_descr[ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK_IX]
@@ -685,7 +764,6 @@ erts_init_process(int ncpu, int proc_tab_size, int legacy_proc_tab)
last_reductions = 0;
last_exact_reductions = 0;
- erts_default_process_flags = 0;
}
void
@@ -955,6 +1033,12 @@ sched_wall_time_change(ErtsSchedulerData *esdp, int working)
}
}
}
+ if (!working) {
+ ERTS_MSACC_SET_STATE_M_X(ERTS_MSACC_STATE_BUSY_WAIT);
+ } else {
+ ERTS_MSACC_SET_STATE_M_X(ERTS_MSACC_STATE_OTHER);
+ }
+
}
typedef struct {
@@ -976,7 +1060,6 @@ typedef struct {
} ErtsSystemCheckReq;
-#if !HALFWORD_HEAP
ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(swtreq,
ErtsSchedWallTimeReq,
5,
@@ -986,33 +1069,6 @@ ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(screq,
ErtsSystemCheckReq,
5,
ERTS_ALC_T_SYS_CHECK_REQ)
-#else
-static ERTS_INLINE ErtsSchedWallTimeReq *
-swtreq_alloc(void)
-{
- return erts_alloc(ERTS_ALC_T_SCHED_WTIME_REQ,
- sizeof(ErtsSchedWallTimeReq));
-}
-
-static ERTS_INLINE void
-swtreq_free(ErtsSchedWallTimeReq *ptr)
-{
- erts_free(ERTS_ALC_T_SCHED_WTIME_REQ, ptr);
-}
-
-static ERTS_INLINE ErtsSystemCheckReq *
-screq_alloc(void)
-{
- return erts_alloc(ERTS_ALC_T_SYS_CHECK_REQ,
- sizeof(ErtsSystemCheckReq));
-}
-
-static ERTS_INLINE void
-screq_free(ErtsSystemCheckReq *ptr)
-{
- erts_free(ERTS_ALC_T_SYS_CHECK_REQ, ptr);
-}
-#endif
static void
reply_sched_wall_time(void *vswtrp)
@@ -1029,7 +1085,7 @@ reply_sched_wall_time(void *vswtrp)
Eterm **hpp;
Uint sz, *szp;
ErlOffHeap *ohp = NULL;
- ErlHeapFragment *bp = NULL;
+ ErtsMessage *mp = NULL;
ASSERT(esdp);
#ifdef ERTS_DIRTY_SCHEDULERS
@@ -1085,12 +1141,12 @@ reply_sched_wall_time(void *vswtrp)
if (hpp)
break;
- hp = erts_alloc_message_heap(sz, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, sz, &hp, &ohp);
szp = NULL;
hpp = &hp;
}
- erts_queue_message(rp, &rp_locks, bp, msg, NIL);
+ erts_queue_message(rp, &rp_locks, mp, msg, NIL);
if (swtrp->req_sched == esdp->no)
rp_locks &= ~ERTS_PROC_LOCK_MAIN;
@@ -1157,7 +1213,7 @@ reply_system_check(void *vscrp)
Eterm **hpp;
Uint sz;
ErlOffHeap *ohp = NULL;
- ErlHeapFragment *bp = NULL;
+ ErtsMessage *mp = NULL;
ASSERT(esdp);
#ifdef ERTS_DIRTY_SCHEDULERS
@@ -1165,11 +1221,11 @@ reply_system_check(void *vscrp)
#endif
sz = REF_THING_SIZE;
- hp = erts_alloc_message_heap(sz, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, sz, &hp, &ohp);
hpp = &hp;
msg = STORE_NC(hpp, ohp, scrp->ref);
- erts_queue_message(rp, &rp_locks, bp, msg, NIL);
+ erts_queue_message(rp, &rp_locks, mp, msg, NIL);
if (scrp->req_sched == esdp->no)
rp_locks &= ~ERTS_PROC_LOCK_MAIN;
@@ -1224,6 +1280,15 @@ proclist_create(Process *p)
return plp;
}
+static ERTS_INLINE ErtsProcList *
+proclist_copy(ErtsProcList *plp0)
+{
+ ErtsProcList *plp1 = proclist_alloc();
+ plp1->pid = plp0->pid;
+ plp1->started_interval = plp0->started_interval;
+ return plp1;
+}
+
static ERTS_INLINE void
proclist_destroy(ErtsProcList *plp)
{
@@ -1231,6 +1296,12 @@ proclist_destroy(ErtsProcList *plp)
}
ErtsProcList *
+erts_proclist_copy(ErtsProcList *plp)
+{
+ return proclist_copy(plp);
+}
+
+ErtsProcList *
erts_proclist_create(Process *p)
{
return proclist_create(p);
@@ -1821,15 +1892,17 @@ handle_delayed_dealloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waitin
int need_thr_progress = 0;
ErtsThrPrgrVal wakeup = ERTS_THR_PRGR_INVALID;
int more_work = 0;
-
+ ERTS_MSACC_PUSH_STATE_M_X();
#ifdef ERTS_DIRTY_SCHEDULERS
ASSERT(!awdp->esdp || !ERTS_SCHEDULER_IS_DIRTY(awdp->esdp));
#endif
unset_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD);
+ ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_ALLOC);
erts_alloc_scheduler_handle_delayed_dealloc((void *) awdp->esdp,
&need_thr_progress,
&wakeup,
&more_work);
+ ERTS_MSACC_POP_STATE_M_X();
if (more_work) {
if (set_aux_work_flags(ssi, ERTS_SSI_AUX_WORK_DD)
& ERTS_SSI_AUX_WORK_DD_THR_PRGR) {
@@ -2216,34 +2289,6 @@ erts_debug_wait_completed(Process *c_p, int flags)
}
-#ifdef ERTS_SMP_SCHEDULERS_NEED_TO_CHECK_CHILDREN
-void
-erts_smp_notify_check_children_needed(void)
-{
- int i;
- for (i = 0; i < erts_no_schedulers; i++)
- set_aux_work_flags_wakeup_nob(ERTS_SCHED_SLEEP_INFO_IX(i),
- ERTS_SSI_AUX_WORK_CHECK_CHILDREN);
-#ifdef ERTS_DIRTY_SCHEDULERS
- for (i = 0; i < erts_no_dirty_cpu_schedulers; i++)
- set_aux_work_flags_wakeup_nob(ERTS_DIRTY_CPU_SCHED_SLEEP_INFO_IX(i),
- ERTS_SSI_AUX_WORK_CHECK_CHILDREN);
- for (i = 0; i < erts_no_dirty_io_schedulers; i++)
- set_aux_work_flags_wakeup_nob(ERTS_DIRTY_IO_SCHED_SLEEP_INFO_IX(i),
- ERTS_SSI_AUX_WORK_CHECK_CHILDREN);
-#endif
-}
-
-static ERTS_INLINE erts_aint32_t
-handle_check_children(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting)
-{
- unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_CHECK_CHILDREN);
- erts_check_children();
- return aux_work & ~ERTS_SSI_AUX_WORK_CHECK_CHILDREN;
-}
-
-#endif
-
static void
notify_reap_ports_relb(void)
{
@@ -2329,12 +2374,15 @@ handle_aux_work(ErtsAuxWorkData *awdp, erts_aint32_t orig_aux_work, int waiting)
ERTS_DBG_CHK_AUX_WORK_VAL(aux_work); \
if (!(aux_work & ~ignore)) { \
ERTS_DBG_CHK_AUX_WORK_VAL(aux_work); \
+ ERTS_MSACC_UPDATE_CACHE(); \
+ ERTS_MSACC_POP_STATE_M(); \
return aux_work; \
} \
}
erts_aint32_t aux_work = orig_aux_work;
erts_aint32_t ignore = 0;
+ ERTS_MSACC_PUSH_AND_SET_STATE_M(ERTS_MSACC_STATE_AUX);
ASSERT(!awdp->esdp || !ERTS_SCHEDULER_IS_DIRTY(awdp->esdp));
#ifdef ERTS_SMP
@@ -2398,10 +2446,6 @@ handle_aux_work(ErtsAuxWorkData *awdp, erts_aint32_t orig_aux_work, int waiting)
HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_MISC,
handle_misc_aux_work);
-#ifdef ERTS_SMP_SCHEDULERS_NEED_TO_CHECK_CHILDREN
- HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_CHECK_CHILDREN,
- handle_check_children);
-#endif
HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_SET_TMO,
handle_setup_aux_work_timer);
@@ -2429,6 +2473,8 @@ handle_aux_work(ErtsAuxWorkData *awdp, erts_aint32_t orig_aux_work, int waiting)
haw_thr_prgr_current_check_progress(awdp);
#endif
+ ERTS_MSACC_UPDATE_CACHE();
+ ERTS_MSACC_POP_STATE_M();
return aux_work;
#undef HANDLE_AUX_WORK
@@ -2629,19 +2675,10 @@ try_set_sys_scheduling(void)
#endif
static ERTS_INLINE int
-prepare_for_sys_schedule(ErtsSchedulerData *esdp, int non_blocking)
+prepare_for_sys_schedule(int non_blocking)
{
if (non_blocking && erts_eager_check_io) {
#ifdef ERTS_SMP
-#ifdef ERTS_SCHED_ONLY_POLL_SCHED_1
- if (esdp->no != 1) {
- /* If we are not scheduler 1 and ERTS_SCHED_ONLY_POLL_SCHED_1 is used
- then we make sure to wake scheduler 1 */
- ErtsRunQueue *rq = ERTS_RUNQ_IX(0);
- wake_scheduler(rq);
- return 0;
- }
-#endif
return try_set_sys_scheduling();
#else
return 1;
@@ -2651,16 +2688,6 @@ prepare_for_sys_schedule(ErtsSchedulerData *esdp, int non_blocking)
#ifdef ERTS_SMP
while (!erts_port_task_have_outstanding_io_tasks()
&& try_set_sys_scheduling()) {
-#ifdef ERTS_SCHED_ONLY_POLL_SCHED_1
- if (esdp->no != 1) {
- /* If we are not scheduler 1 and ERTS_SCHED_ONLY_POLL_SCHED_1 is used
- then we make sure to wake scheduler 1 */
- ErtsRunQueue *rq = ERTS_RUNQ_IX(0);
- clear_sys_scheduling();
- wake_scheduler(rq);
- return 0;
- }
-#endif
if (!erts_port_task_have_outstanding_io_tasks())
return 1;
clear_sys_scheduling();
@@ -2712,13 +2739,6 @@ sched_active(Uint no, ErtsRunQueue *rq)
profile_scheduler(make_small(no), am_active);
}
-static int ERTS_INLINE
-ongoing_multi_scheduling_block(void)
-{
- ERTS_SMP_LC_ASSERT(erts_lc_mtx_is_locked(&schdlr_sspnd.mtx));
- return schdlr_sspnd.msb.ongoing;
-}
-
static ERTS_INLINE void
empty_runq_aux(ErtsRunQueue *rq, Uint32 old_flags)
{
@@ -2955,6 +2975,8 @@ aux_thread(void *unused)
ssi->event = erts_tse_fetch();
+ erts_msacc_init_thread("aux", 1, 1);
+
callbacks.arg = (void *) ssi;
callbacks.wakeup = thr_prgr_wakeup;
callbacks.prepare_wait = thr_prgr_prep_wait;
@@ -2965,6 +2987,7 @@ aux_thread(void *unused)
init_aux_work_data(awdp, NULL, NULL);
awdp->ssi = ssi;
+
sched_prep_spin_wait(ssi);
while (1) {
@@ -2984,8 +3007,6 @@ aux_thread(void *unused)
erts_thr_progress_active(NULL, thr_prgr_active = 0);
erts_thr_progress_prepare_wait(NULL);
- ERTS_SCHED_FAIR_YIELD();
-
flgs = sched_spin_wait(ssi, 0);
if (flgs & ERTS_SSI_FLG_SLEEPING) {
@@ -3020,6 +3041,9 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
#ifdef ERTS_SMP
int thr_prgr_active = 1;
erts_aint32_t flgs;
+#endif
+ ERTS_MSACC_PUSH_STATE_M();
+#ifdef ERTS_SMP
ERTS_SMP_LC_ASSERT(erts_smp_lc_runq_is_locked(rq));
@@ -3053,7 +3077,7 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
* be waiting in erl_sys_schedule()
*/
- if (ERTS_SCHEDULER_IS_DIRTY(esdp) || !prepare_for_sys_schedule(esdp, 0)) {
+ if (ERTS_SCHEDULER_IS_DIRTY(esdp) || !prepare_for_sys_schedule(0)) {
sched_waiting(esdp->no, rq);
@@ -3067,7 +3091,7 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
sched_wall_time_change(esdp, thr_prgr_active);
while (1) {
- ErtsMonotonicTime current_time;
+ ErtsMonotonicTime current_time = 0;
aux_work = erts_atomic32_read_acqb(&ssi->aux_work);
if (aux_work && !ERTS_SCHEDULER_IS_DIRTY(esdp)) {
@@ -3076,6 +3100,7 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
sched_wall_time_change(esdp, 1);
}
aux_work = handle_aux_work(&esdp->aux_work_data, aux_work, 1);
+ ERTS_MSACC_UPDATE_CACHE();
if (aux_work && erts_thr_progress_update(esdp))
erts_thr_progress_leader_update(esdp);
}
@@ -3100,8 +3125,10 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
timeout_time = erts_check_next_timeout_time(esdp);
current_time = erts_get_monotonic_time(esdp);
do_timeout = (current_time >= timeout_time);
- } else
+ } else {
+ current_time = 0;
timeout_time = ERTS_MONOTONIC_TIME_MAX;
+ }
if (do_timeout) {
if (!thr_prgr_active) {
erts_thr_progress_active(esdp, thr_prgr_active = 1);
@@ -3117,8 +3144,6 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
erts_thr_progress_prepare_wait(esdp);
}
- ERTS_SCHED_FAIR_YIELD();
-
flgs = sched_spin_wait(ssi, spincount);
if (flgs & ERTS_SSI_FLG_SLEEPING) {
ASSERT(flgs & ERTS_SSI_FLG_WAITING);
@@ -3139,7 +3164,9 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
- 1) + 1;
} else
timeout = -1;
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_SLEEP);
res = erts_tse_twait(ssi->event, timeout);
+ ERTS_MSACC_POP_STATE_M();
current_time = ERTS_SCHEDULER_IS_DIRTY(esdp) ? 0 :
erts_get_monotonic_time(esdp);
} while (res == EINTR);
@@ -3189,13 +3216,8 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
#ifdef ERTS_DIRTY_SCHEDULERS
ASSERT(!ERTS_SCHEDULER_IS_DIRTY(esdp));
#endif
-
-#ifdef ERTS_SCHED_ONLY_POLL_SCHED_1
- ASSERT(esdp->no == 1);
-#endif
sched_waiting_sys(esdp->no, rq);
-
erts_smp_runq_unlock(rq);
ASSERT(working);
@@ -3213,9 +3235,13 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
if (working)
sched_wall_time_change(esdp, working = 0);
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_CHECK_IO);
+
ASSERT(!erts_port_task_have_outstanding_io_tasks());
erl_sys_schedule(1); /* Might give us something to do */
+ ERTS_MSACC_POP_STATE_M();
+
if (!ERTS_SCHEDULER_IS_DIRTY(esdp)) {
current_time = erts_get_monotonic_time(esdp);
if (current_time >= erts_next_timeout_time(esdp->next_tmo_ref))
@@ -3236,6 +3262,7 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
erts_thr_progress_active(esdp, thr_prgr_active = 1);
#endif
aux_work = handle_aux_work(&esdp->aux_work_data, aux_work, 1);
+ ERTS_MSACC_UPDATE_CACHE();
#ifdef ERTS_SMP
if (aux_work && erts_thr_progress_update(esdp))
erts_thr_progress_leader_update(esdp);
@@ -3262,7 +3289,7 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
* Got to check that we still got I/O tasks; otherwise
* we have to continue checking for I/O...
*/
- if (!prepare_for_sys_schedule(esdp, 0)) {
+ if (!prepare_for_sys_schedule(0)) {
spincount *= ERTS_SCHED_TSE_SLEEP_SPINCOUNT_FACT;
goto tse_wait;
}
@@ -3284,7 +3311,7 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
* Got to check that we still got I/O tasks; otherwise
* we have to wait in erl_sys_schedule() after all...
*/
- if (!prepare_for_sys_schedule(esdp, 0)) {
+ if (!prepare_for_sys_schedule(0)) {
/*
* Not allowed to wait in erl_sys_schedule;
* do tse wait instead...
@@ -3333,8 +3360,12 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
ASSERT(!erts_port_task_have_outstanding_io_tasks());
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_CHECK_IO);
+
erl_sys_schedule(0);
+ ERTS_MSACC_POP_STATE_M();
+
if (!ERTS_SCHEDULER_IS_DIRTY(esdp)) {
ErtsMonotonicTime current_time = erts_get_monotonic_time(esdp);
if (current_time >= erts_next_timeout_time(esdp->next_tmo_ref))
@@ -3404,7 +3435,8 @@ wake_scheduler(ErtsRunQueue *rq)
* so all code *should* handle this without having
* the lock on the run queue.
*/
- ERTS_SMP_LC_ASSERT(!erts_smp_lc_runq_is_locked(rq));
+ ERTS_SMP_LC_ASSERT(!erts_smp_lc_runq_is_locked(rq)
+ || ERTS_RUNQ_IX_IS_DIRTY(rq->ix));
ssi = rq->scheduler->ssi;
@@ -3729,6 +3761,13 @@ check_requeue_process(ErtsRunQueue *rq, int prio_q)
return 0;
}
+static ERTS_INLINE void
+free_proxy_proc(Process *proxy)
+{
+ ASSERT(erts_smp_atomic32_read_nob(&proxy->state) & ERTS_PSFLG_PROXY);
+ erts_free(ERTS_ALC_T_PROC, proxy);
+}
+
#ifdef ERTS_SMP
static ErtsRunQueue *
@@ -3900,24 +3939,33 @@ static ERTS_INLINE void
resume_run_queue(ErtsRunQueue *rq)
{
int pix;
+ Uint32 oflgs;
erts_smp_runq_lock(rq);
- (void) ERTS_RUNQ_FLGS_READ_BSET(rq,
- (ERTS_RUNQ_FLG_OUT_OF_WORK
- | ERTS_RUNQ_FLG_HALFTIME_OUT_OF_WORK
- | ERTS_RUNQ_FLG_SUSPENDED),
- (ERTS_RUNQ_FLG_OUT_OF_WORK
- | ERTS_RUNQ_FLG_HALFTIME_OUT_OF_WORK));
+ oflgs = ERTS_RUNQ_FLGS_READ_BSET(rq,
+ (ERTS_RUNQ_FLG_OUT_OF_WORK
+ | ERTS_RUNQ_FLG_HALFTIME_OUT_OF_WORK
+ | ERTS_RUNQ_FLG_SUSPENDED),
+ (ERTS_RUNQ_FLG_OUT_OF_WORK
+ | ERTS_RUNQ_FLG_HALFTIME_OUT_OF_WORK));
+
+ if (oflgs & ERTS_RUNQ_FLG_SUSPENDED) {
+ erts_aint32_t len;
+
+ rq->check_balance_reds = ERTS_RUNQ_CALL_CHECK_BALANCE_REDS;
+ for (pix = 0; pix < ERTS_NO_PROC_PRIO_LEVELS; pix++) {
+ len = erts_smp_atomic32_read_dirty(&rq->procs.prio_info[pix].len);
+ rq->procs.prio_info[pix].max_len = len;
+ rq->procs.prio_info[pix].reds = 0;
+ }
+ len = erts_smp_atomic32_read_dirty(&rq->ports.info.len);
+ rq->ports.info.max_len = len;
+ rq->ports.info.reds = 0;
+ len = erts_smp_atomic32_read_dirty(&rq->len);
+ rq->max_len = len;
- rq->check_balance_reds = ERTS_RUNQ_CALL_CHECK_BALANCE_REDS;
- for (pix = 0; pix < ERTS_NO_PROC_PRIO_LEVELS; pix++) {
- rq->procs.prio_info[pix].max_len = 0;
- rq->procs.prio_info[pix].reds = 0;
}
- rq->ports.info.max_len = 0;
- rq->ports.info.reds = 0;
- rq->max_len = 0;
erts_smp_runq_unlock(rq);
@@ -4043,9 +4091,6 @@ evacuate_run_queue(ErtsRunQueue *rq,
erts_aint32_t state;
Process *proc;
int notify = 0;
-#ifdef ERTS_DIRTY_SCHEDULERS
- int requeue;
-#endif
to_rq = NULL;
#ifdef ERTS_DIRTY_SCHEDULERS
@@ -4060,49 +4105,94 @@ evacuate_run_queue(ErtsRunQueue *rq,
proc = dequeue_process(rq, prio_q, &state);
while (proc) {
-#ifdef ERTS_DIRTY_SCHEDULERS
- requeue = 1;
+ Process *real_proc;
+ int prio;
+ erts_aint32_t max_qbit, qbit, real_state;
+
+ prio = ERTS_PSFLGS_GET_PRQ_PRIO(state);
+ qbit = ((erts_aint32_t) 1) << prio;
+
+ if (!(state & ERTS_PSFLG_PROXY)) {
+ real_proc = proc;
+ real_state = state;
+ }
+ else {
+ real_proc = erts_proc_lookup_raw(proc->common.id);
+ if (!real_proc) {
+ free_proxy_proc(proc);
+ goto handle_next_proc;
+ }
+ real_state = erts_smp_atomic32_read_acqb(&real_proc->state);
+ }
+
+ max_qbit = (state >> ERTS_PSFLGS_IN_PRQ_MASK_OFFSET);
+ max_qbit &= ERTS_PSFLGS_QMASK;
+ max_qbit |= 1 << ERTS_PSFLGS_QMASK_BITS;
+ max_qbit &= -max_qbit;
+
+ if (qbit > max_qbit) {
+ /* Process already queued with higher prio; drop it... */
+ if (real_proc != proc)
+ free_proxy_proc(proc);
+ else {
+ erts_aint32_t clr_bits;
+#ifdef DEBUG
+ erts_aint32_t old;
#endif
- if (ERTS_PSFLG_BOUND & state) {
- /* Bound processes get stuck here... */
- proc->next = NULL;
- if (sbpp->last)
- sbpp->last->next = proc;
- else
- sbpp->first = proc;
- sbpp->last = proc;
-#ifdef ERTS_DIRTY_SCHEDULERS
- requeue = 0;
+
+ clr_bits = ERTS_PSFLG_IN_RUNQ;
+ clr_bits |= qbit << ERTS_PSFLGS_IN_PRQ_MASK_OFFSET;
+
+#ifdef DEBUG
+ old =
+#else
+ (void)
#endif
+ erts_smp_atomic32_read_band_mb(&proc->state,
+ ~clr_bits);
+ ASSERT((old & clr_bits) == clr_bits);
+
+ }
+
+ goto handle_next_proc;
}
+
#ifdef ERTS_DIRTY_SCHEDULERS
- else if (state & ERTS_PSFLG_DIRTY_CPU_PROC_IN_Q) {
+
+ if (ERTS_RUNQ_IX_IS_DIRTY(rq->ix)) {
+ erts_aint32_t dqbit = qbit;
#ifdef DEBUG
- erts_aint32_t old =
-#else
- (void)
+ erts_aint32_t old_dqbit;
#endif
- erts_smp_atomic32_read_band_nob(&proc->state,
- ~(ERTS_PSFLG_DIRTY_CPU_PROC
- | ERTS_PSFLG_DIRTY_CPU_PROC_IN_Q));
- /* assert that no other dirty flags are set */
- ASSERT(!(old & (ERTS_PSFLG_DIRTY_IO_PROC|ERTS_PSFLG_DIRTY_IO_PROC_IN_Q)));
- } else if (state & ERTS_PSFLG_DIRTY_IO_PROC_IN_Q) {
+
+ if (rq == ERTS_DIRTY_CPU_RUNQ)
+ dqbit <<= ERTS_PDSFLGS_IN_CPU_PRQ_MASK_OFFSET;
+ else {
+ ASSERT(rq == ERTS_DIRTY_IO_RUNQ);
+ dqbit <<= ERTS_PDSFLGS_IN_IO_PRQ_MASK_OFFSET;
+ }
+
#ifdef DEBUG
- erts_aint32_t old =
+ old_dqbit = (int)
#else
- (void)
+ (void)
#endif
- erts_smp_atomic32_read_band_nob(&proc->state,
- ~(ERTS_PSFLG_DIRTY_IO_PROC
- | ERTS_PSFLG_DIRTY_IO_PROC_IN_Q));
- /* assert that no other dirty flags are set */
- ASSERT(!(old & (ERTS_PSFLG_DIRTY_CPU_PROC|ERTS_PSFLG_DIRTY_CPU_PROC_IN_Q)));
+ erts_smp_atomic32_read_band_mb(&real_proc->dirty_state,
+ ~dqbit);
+ ASSERT(old_dqbit & dqbit);
}
- if (requeue) {
-#else
- else {
#endif
+
+ if (ERTS_PSFLG_BOUND & real_state) {
+ /* Bound processes get stuck here... */
+ proc->next = NULL;
+ if (sbpp->last)
+ sbpp->last->next = proc;
+ else
+ sbpp->first = proc;
+ sbpp->last = proc;
+ }
+ else {
int prio = (int) ERTS_PSFLGS_GET_PRQ_PRIO(state);
erts_smp_runq_unlock(rq);
@@ -4125,6 +4215,8 @@ evacuate_run_queue(ErtsRunQueue *rq,
erts_smp_runq_lock(rq);
}
+
+ handle_next_proc:
proc = dequeue_process(rq, prio_q, &state);
}
if (notify)
@@ -5405,17 +5497,11 @@ erts_early_init_scheduling(int no_schedulers)
wakeup_other.threshold = ERTS_SCHED_WAKEUP_OTHER_THRESHOLD_MEDIUM;
wakeup_other.type = ERTS_SCHED_WAKEUP_OTHER_TYPE_DEFAULT;
#endif
-#ifndef ERTS_SCHED_MIN_SPIN
sched_busy_wait.sys_schedule = ERTS_SCHED_SYS_SLEEP_SPINCOUNT_MEDIUM;
sched_busy_wait.tse = (ERTS_SCHED_SYS_SLEEP_SPINCOUNT_MEDIUM
* ERTS_SCHED_TSE_SLEEP_SPINCOUNT_FACT);
sched_busy_wait.aux_work = (ERTS_SCHED_SYS_SLEEP_SPINCOUNT_MEDIUM
* ERTS_SCHED_AUX_WORK_SLEEP_SPINCOUNT_FACT_MEDIUM);
-#else
- sched_busy_wait.sys_schedule = ERTS_SCHED_SYS_SLEEP_SPINCOUNT_NONE;
- sched_busy_wait.tse = ERTS_SCHED_SYS_SLEEP_SPINCOUNT_NONE;
- sched_busy_wait.aux_work = ERTS_SCHED_SYS_SLEEP_SPINCOUNT_NONE;
-#endif
}
int
@@ -5599,9 +5685,6 @@ init_scheduler_data(ErtsSchedulerData* esdp, int num,
esdp->f_reg_array =
erts_alloc_permanent_cache_aligned(ERTS_ALC_T_BEAM_REGISTER,
MAX_REG * sizeof(FloatDef));
-#if !HEAP_ON_C_STACK
- esdp->num_tmp_heap_used = 0;
-#endif
#ifdef ERTS_DIRTY_SCHEDULERS
if (ERTS_RUNQ_IX_IS_DIRTY(runq->ix)) {
esdp->no = 0;
@@ -5661,6 +5744,9 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online
char *daww_ptr;
size_t daww_sz;
size_t size_runqs;
+#ifdef ERTS_SMP
+ erts_aint32_t set_schdlr_sspnd_change_flags;
+#endif
init_misc_op_list_alloc();
init_proc_sys_task_queues_alloc();
@@ -5886,10 +5972,8 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online
#endif
init_misc_aux_work();
-#if !HALFWORD_HEAP
init_swtreq_alloc();
init_screq_alloc();
-#endif
erts_atomic32_init_nob(&debug_wait_completed_count, 0); /* debug only */
debug_wait_completed_flags = 0;
@@ -5900,25 +5984,6 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online
erts_alloc_permanent_cache_aligned(ERTS_ALC_T_SCHDLR_DATA,
sizeof(ErtsAuxWorkData));
- erts_smp_mtx_init(&schdlr_sspnd.mtx, "schdlr_sspnd");
- erts_smp_cnd_init(&schdlr_sspnd.cnd);
-
- erts_smp_atomic32_init_nob(&schdlr_sspnd.changing, 0);
- schdlr_sspnd.online = no_schedulers_online;
- schdlr_sspnd.curr_online = no_schedulers;
- schdlr_sspnd.msb.ongoing = 0;
- erts_smp_atomic32_init_nob(&schdlr_sspnd.active, no_schedulers);
-#ifdef ERTS_DIRTY_SCHEDULERS
- erts_smp_atomic32_init_nob(&schdlr_sspnd.dirty_cpu_changing, 0);
- schdlr_sspnd.dirty_cpu_online = no_dirty_cpu_schedulers_online;
- schdlr_sspnd.dirty_cpu_curr_online = no_dirty_cpu_schedulers;
- erts_smp_atomic32_init_nob(&schdlr_sspnd.dirty_cpu_active, no_dirty_cpu_schedulers);
- erts_smp_atomic32_init_nob(&schdlr_sspnd.dirty_io_changing, 0);
- schdlr_sspnd.dirty_io_online = no_dirty_io_schedulers;
- schdlr_sspnd.dirty_io_curr_online = no_dirty_io_schedulers;
- erts_smp_atomic32_init_nob(&schdlr_sspnd.dirty_io_active, no_dirty_io_schedulers);
-#endif
- schdlr_sspnd.msb.procs = NULL;
init_no_runqs(no_schedulers_online, no_schedulers_online);
balance_info.last_active_runqs = no_schedulers;
erts_smp_mtx_init(&balance_info.update_mtx, "migration_info_update");
@@ -5933,32 +5998,66 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online
init_migration_paths();
- if (no_schedulers_online < no_schedulers) {
+ init_scheduler_suspend();
+
+ set_schdlr_sspnd_change_flags = 0;
+
+ schdlr_sspnd_set_nscheds(&schdlr_sspnd.online,
+ ERTS_SCHED_NORMAL,
+ no_schedulers_online);
+ schdlr_sspnd_set_nscheds(&schdlr_sspnd.curr_online,
+ ERTS_SCHED_NORMAL,
+ no_schedulers);
+ schdlr_sspnd_set_nscheds(&schdlr_sspnd.active,
+ ERTS_SCHED_NORMAL,
+ no_schedulers);
+
+ if (no_schedulers_online != no_schedulers) {
+ ASSERT(no_schedulers_online < no_schedulers);
+ set_schdlr_sspnd_change_flags |= ERTS_SCHDLR_SSPND_CHNG_ONLN;
+ schdlr_sspnd.changer = am_init;
change_no_used_runqs(no_schedulers_online);
for (ix = no_schedulers_online; ix < erts_no_run_queues; ix++)
suspend_run_queue(ERTS_RUNQ_IX(ix));
}
- schdlr_sspnd.wait_curr_online = no_schedulers_online;
- schdlr_sspnd.curr_online *= 2; /* Boot strapping... */
- ERTS_SCHDLR_SSPND_CHNG_SET((ERTS_SCHDLR_SSPND_CHNG_ONLN
- | ERTS_SCHDLR_SSPND_CHNG_WAITER), 0);
#ifdef ERTS_DIRTY_SCHEDULERS
- schdlr_sspnd.dirty_cpu_wait_curr_online = no_dirty_cpu_schedulers_online;
- schdlr_sspnd.dirty_cpu_curr_online *= 2;
- ERTS_SCHDLR_SSPND_DIRTY_CPU_CHNG_SET((ERTS_SCHDLR_SSPND_CHNG_ONLN
- | ERTS_SCHDLR_SSPND_CHNG_WAITER), 0);
- for (ix = no_dirty_cpu_schedulers_online; ix < no_dirty_cpu_schedulers; ix++) {
- ErtsSchedulerData* esdp = ERTS_DIRTY_CPU_SCHEDULER_IX(ix);
- erts_smp_atomic32_read_bor_nob(&esdp->ssi->flags, ERTS_SSI_FLG_SUSPENDED);
+
+ schdlr_sspnd_set_nscheds(&schdlr_sspnd.online,
+ ERTS_SCHED_DIRTY_CPU,
+ no_dirty_cpu_schedulers_online);
+ schdlr_sspnd_set_nscheds(&schdlr_sspnd.curr_online,
+ ERTS_SCHED_DIRTY_CPU,
+ no_dirty_cpu_schedulers);
+ schdlr_sspnd_set_nscheds(&schdlr_sspnd.active,
+ ERTS_SCHED_DIRTY_CPU,
+ no_dirty_cpu_schedulers);
+
+ if (no_dirty_cpu_schedulers_online != no_dirty_cpu_schedulers) {
+ ASSERT(no_dirty_cpu_schedulers_online < no_dirty_cpu_schedulers);
+ set_schdlr_sspnd_change_flags |= ERTS_SCHDLR_SSPND_CHNG_DCPU_ONLN;
+ for (ix = no_dirty_cpu_schedulers_online; ix < no_dirty_cpu_schedulers; ix++) {
+ ErtsSchedulerData* esdp = ERTS_DIRTY_CPU_SCHEDULER_IX(ix);
+ erts_smp_atomic32_read_bor_nob(&esdp->ssi->flags, ERTS_SSI_FLG_SUSPENDED);
+ }
}
- schdlr_sspnd.dirty_io_wait_curr_online = no_dirty_io_schedulers;
- schdlr_sspnd.dirty_io_curr_online *= 2;
- ERTS_SCHDLR_SSPND_DIRTY_IO_CHNG_SET((ERTS_SCHDLR_SSPND_CHNG_ONLN
- | ERTS_SCHDLR_SSPND_CHNG_WAITER), 0);
+ schdlr_sspnd_set_nscheds(&schdlr_sspnd.online,
+ ERTS_SCHED_DIRTY_IO,
+ no_dirty_io_schedulers);
+ schdlr_sspnd_set_nscheds(&schdlr_sspnd.curr_online,
+ ERTS_SCHED_DIRTY_IO,
+ no_dirty_io_schedulers);
+ schdlr_sspnd_set_nscheds(&schdlr_sspnd.active,
+ ERTS_SCHED_DIRTY_IO,
+ no_dirty_io_schedulers);
+
#endif
+ if (set_schdlr_sspnd_change_flags)
+ erts_smp_atomic32_set_nob(&schdlr_sspnd.changing,
+ set_schdlr_sspnd_change_flags);
+
erts_smp_atomic32_init_nob(&doing_sys_schedule, 0);
init_misc_aux_work();
@@ -5973,11 +6072,9 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online
#endif
}
erts_no_schedulers = 1;
-#ifdef ERTS_DIRTY_SCHEDULERS
erts_no_dirty_cpu_schedulers = 0;
erts_no_dirty_io_schedulers = 0;
#endif
-#endif
erts_smp_atomic32_init_nob(&function_calls, 0);
@@ -6069,19 +6166,96 @@ make_proxy_proc(Process *prev_proxy, Process *proc, erts_aint32_t prio)
return proxy;
}
-static ERTS_INLINE void
-free_proxy_proc(Process *proxy)
-{
- ASSERT(erts_smp_atomic32_read_nob(&proxy->state) & ERTS_PSFLG_PROXY);
- erts_free(ERTS_ALC_T_PROC, proxy);
-}
-
#define ERTS_ENQUEUE_NOT 0
#define ERTS_ENQUEUE_NORMAL_QUEUE 1
-#ifdef ERTS_DIRTY_SCHEDULERS
#define ERTS_ENQUEUE_DIRTY_CPU_QUEUE 2
#define ERTS_ENQUEUE_DIRTY_IO_QUEUE 3
+
+#ifdef ERTS_DIRTY_SCHEDULERS
+
+static int
+check_dirty_enqueue_in_prio_queue(Process *c_p,
+ erts_aint32_t *newp,
+ erts_aint32_t actual,
+ erts_aint32_t aprio,
+ erts_aint32_t qbit)
+{
+ int queue;
+ erts_aint32_t dact, max_qbit;
+
+ /* Termination should be done on an ordinary scheduler */
+ if (actual & ERTS_PSFLG_EXITING) {
+ *newp &= ~ERTS_PSFLGS_DIRTY_WORK;
+ return ERTS_ENQUEUE_NORMAL_QUEUE;
+ }
+
+ /*
+ * If we have system tasks, we enqueue on ordinary run-queue
+ * and take care of those system tasks first.
+ */
+ if (actual & ERTS_PSFLG_ACTIVE_SYS)
+ return ERTS_ENQUEUE_NORMAL_QUEUE;
+
+ dact = erts_smp_atomic32_read_mb(&c_p->dirty_state);
+ if (actual & (ERTS_PSFLG_DIRTY_ACTIVE_SYS
+ | ERTS_PSFLG_DIRTY_CPU_PROC)) {
+ max_qbit = ((dact >> ERTS_PDSFLGS_IN_CPU_PRQ_MASK_OFFSET)
+ & ERTS_PDSFLGS_QMASK);
+ queue = ERTS_ENQUEUE_DIRTY_CPU_QUEUE;
+ }
+ else {
+ ASSERT(actual & ERTS_PSFLG_DIRTY_IO_PROC);
+ max_qbit = ((dact >> ERTS_PDSFLGS_IN_IO_PRQ_MASK_OFFSET)
+ & ERTS_PDSFLGS_QMASK);
+ queue = ERTS_ENQUEUE_DIRTY_IO_QUEUE;
+ }
+
+ max_qbit |= 1 << ERTS_PSFLGS_QMASK_BITS;
+ max_qbit &= -max_qbit;
+
+ if (qbit >= max_qbit)
+ return ERTS_ENQUEUE_NOT; /* Already queued in higher or equal prio */
+ if ((actual & (ERTS_PSFLG_IN_RUNQ|ERTS_PSFLGS_USR_PRIO_MASK))
+ != (aprio << ERTS_PSFLGS_USR_PRIO_OFFSET)) {
+ /*
+ * Process struct already enqueued, or actual prio not
+ * equal to user prio, i.e., enqueue using proxy.
+ */
+ return -1*queue;
+ }
+
+ *newp |= ERTS_PSFLG_IN_RUNQ;
+ return queue;
+}
+
+static ERTS_INLINE int
+fin_dirty_enq_s_change(Process *p,
+ int pstruct_reserved,
+ erts_aint32_t enq_prio,
+ int qmask_offset)
+{
+ erts_aint32_t qbit = 1 << enq_prio;
+ qbit <<= qmask_offset;
+
+ if (qbit & erts_smp_atomic32_read_bor_mb(&p->dirty_state, qbit)) {
+ /* Already enqueue by someone else... */
+ if (pstruct_reserved) {
+ /* We reserved process struct for enqueue; clear it... */
+#ifdef DEBUG
+ erts_aint32_t old =
+#else
+ (void)
#endif
+ erts_smp_atomic32_read_band_nob(&p->state, ~ERTS_PSFLG_IN_RUNQ);
+ ASSERT(old & ERTS_PSFLG_IN_RUNQ);
+ }
+ return 0;
+ }
+
+ return !0;
+}
+
+#endif /* ERTS_DIRTY_SCHEDULERS */
static ERTS_INLINE int
check_enqueue_in_prio_queue(Process *c_p,
@@ -6097,61 +6271,14 @@ check_enqueue_in_prio_queue(Process *c_p,
*prq_prio_p = aprio;
#ifdef ERTS_DIRTY_SCHEDULERS
- if (actual & (ERTS_PSFLG_DIRTY_CPU_PROC|ERTS_PSFLG_DIRTY_IO_PROC)) {
- /*
- * If we have system tasks of a priority higher
- * or equal to the user priority, we enqueue
- * on ordinary run-queue and take care of
- * those system tasks first.
- */
- if (actual & ERTS_PSFLG_ACTIVE_SYS) {
- erts_aint32_t uprio, stprio, qmask;
- uprio = (actual >> ERTS_PSFLGS_USR_PRIO_OFFSET) & ERTS_PSFLGS_PRIO_MASK;
- if (aprio < uprio)
- goto enqueue_normal_runq; /* system tasks with higher prio */
- erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_STATUS);
- qmask = c_p->sys_task_qs->qmask;
- erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_STATUS);
- switch (qmask & -qmask) {
- case MAX_BIT:
- stprio = PRIORITY_MAX;
- break;
- case HIGH_BIT:
- stprio = PRIORITY_HIGH;
- break;
- case NORMAL_BIT:
- stprio = PRIORITY_NORMAL;
- break;
- case LOW_BIT:
- stprio = PRIORITY_LOW;
- break;
- default:
- stprio = PRIORITY_LOW+1;
- break;
- }
- if (stprio <= uprio)
- goto enqueue_normal_runq; /* system tasks with higher prio */
- }
-
- /* Enqueue in dirty run queue if not already enqueued */
- if (actual & (ERTS_PSFLG_DIRTY_CPU_PROC_IN_Q|ERTS_PSFLG_DIRTY_IO_PROC_IN_Q))
- return ERTS_ENQUEUE_NOT; /* already in queue */
- if (actual & ERTS_PSFLG_DIRTY_CPU_PROC) {
- *newp |= ERTS_PSFLG_DIRTY_CPU_PROC_IN_Q;
- if (actual & ERTS_PSFLG_IN_RUNQ)
- return -ERTS_ENQUEUE_DIRTY_CPU_QUEUE; /* use proxy */
- *newp |= ERTS_PSFLG_IN_RUNQ;
- return ERTS_ENQUEUE_DIRTY_CPU_QUEUE;
- }
- *newp |= ERTS_PSFLG_DIRTY_IO_PROC_IN_Q;
- if (actual & ERTS_PSFLG_IN_RUNQ)
- return -ERTS_ENQUEUE_DIRTY_IO_QUEUE; /* use proxy */
- *newp |= ERTS_PSFLG_IN_RUNQ;
- return ERTS_ENQUEUE_DIRTY_IO_QUEUE;
+ if (actual & ERTS_PSFLGS_DIRTY_WORK) {
+ int res = check_dirty_enqueue_in_prio_queue(c_p, newp, actual,
+ aprio, qbit);
+ if (res != ERTS_ENQUEUE_NORMAL_QUEUE)
+ return res;
}
-
- enqueue_normal_runq:
#endif
+
max_qbit = (actual >> ERTS_PSFLGS_IN_PRQ_MASK_OFFSET) & ERTS_PSFLGS_QMASK;
max_qbit |= 1 << ERTS_PSFLGS_QMASK_BITS;
max_qbit &= -max_qbit;
@@ -6183,6 +6310,65 @@ check_enqueue_in_prio_queue(Process *c_p,
return ERTS_ENQUEUE_NORMAL_QUEUE;
}
+static ERTS_INLINE ErtsRunQueue *
+select_enqueue_run_queue(int enqueue, int enq_prio, Process *p, erts_aint32_t state)
+{
+
+ switch (enqueue) {
+
+ case ERTS_ENQUEUE_NOT:
+
+ return NULL;
+
+#ifdef ERTS_DIRTY_SCHEDULERS
+
+ case ERTS_ENQUEUE_DIRTY_CPU_QUEUE:
+ case -ERTS_ENQUEUE_DIRTY_CPU_QUEUE:
+
+ if (fin_dirty_enq_s_change(p, enqueue > 0, enq_prio,
+ ERTS_PDSFLGS_IN_CPU_PRQ_MASK_OFFSET))
+ return ERTS_DIRTY_CPU_RUNQ;
+
+ return NULL;
+
+
+ case ERTS_ENQUEUE_DIRTY_IO_QUEUE:
+ case -ERTS_ENQUEUE_DIRTY_IO_QUEUE:
+
+ if (fin_dirty_enq_s_change(p, enqueue > 0, enq_prio,
+ ERTS_PDSFLGS_IN_IO_PRQ_MASK_OFFSET))
+ return ERTS_DIRTY_IO_RUNQ;
+
+ return NULL;
+
+#endif
+
+ default: {
+ ErtsRunQueue* runq;
+
+ ASSERT(enqueue == ERTS_ENQUEUE_NORMAL_QUEUE
+ || enqueue == -ERTS_ENQUEUE_NORMAL_QUEUE);
+
+ runq = erts_get_runq_proc(p);
+
+#ifdef ERTS_SMP
+ if (!(ERTS_PSFLG_BOUND & state)) {
+ ErtsRunQueue *new_runq = erts_check_emigration_need(runq, enq_prio);
+ if (new_runq) {
+ RUNQ_SET_RQ(&p->run_queue, new_runq);
+ runq = new_runq;
+ }
+ }
+#endif
+
+ ASSERT(runq);
+
+ return runq;
+ }
+ }
+}
+
+
/*
* schedule_out_process() return with c_rq locked.
*/
@@ -6191,11 +6377,7 @@ schedule_out_process(ErtsRunQueue *c_rq, erts_aint32_t state, Process *p, Proces
{
erts_aint32_t a, e, n, enq_prio = -1;
int enqueue; /* < 0 -> use proxy */
- Process* sched_p;
ErtsRunQueue* runq;
-#ifdef ERTS_SMP
- int check_emigration_need;
-#endif
a = state;
@@ -6207,7 +6389,7 @@ schedule_out_process(ErtsRunQueue *c_rq, erts_aint32_t state, Process *p, Proces
enqueue = ERTS_ENQUEUE_NOT;
n &= ~(ERTS_PSFLG_RUNNING|ERTS_PSFLG_RUNNING_SYS);
- if (a & ERTS_PSFLG_ACTIVE_SYS
+ if (a & (ERTS_PSFLG_ACTIVE_SYS|ERTS_PSFLG_DIRTY_ACTIVE_SYS)
|| (a & (ERTS_PSFLG_ACTIVE|ERTS_PSFLG_SUSPENDED)) == ERTS_PSFLG_ACTIVE) {
enqueue = check_enqueue_in_prio_queue(p, &enq_prio, &n, a);
}
@@ -6216,16 +6398,17 @@ schedule_out_process(ErtsRunQueue *c_rq, erts_aint32_t state, Process *p, Proces
break;
}
- switch (enqueue) {
- case ERTS_ENQUEUE_NOT:
+ runq = select_enqueue_run_queue(enqueue, enq_prio, p, n);
+
+ if (!runq) {
+
if (erts_system_profile_flags.runnable_procs) {
/* Status lock prevents out of order "runnable proc" trace msgs */
ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_STATUS & erts_proc_lc_my_proc_locks(p));
- if (!(a & ERTS_PSFLG_ACTIVE_SYS)
- && (!(a & ERTS_PSFLG_ACTIVE)
- || (a & ERTS_PSFLG_SUSPENDED))) {
+ if (!(a & (ERTS_PSFLG_ACTIVE_SYS|ERTS_PSFLG_DIRTY_ACTIVE_SYS))
+ && (!(a & ERTS_PSFLG_ACTIVE) || (a & ERTS_PSFLG_SUSPENDED))) {
/* Process inactive */
profile_runnable_proc(p, am_inactive);
}
@@ -6238,98 +6421,76 @@ schedule_out_process(ErtsRunQueue *c_rq, erts_aint32_t state, Process *p, Proces
return 0;
-#ifdef ERTS_DIRTY_SCHEDULERS
-#ifdef ERTS_SMP
- case ERTS_ENQUEUE_DIRTY_CPU_QUEUE:
- case -ERTS_ENQUEUE_DIRTY_CPU_QUEUE:
- runq = ERTS_DIRTY_CPU_RUNQ;
- ASSERT(ERTS_SCHEDULER_IS_DIRTY_CPU(runq->scheduler));
-#ifdef ERTS_SMP
- check_emigration_need = 0;
-#endif
- break;
+ }
+ else {
+ Process* sched_p;
- case ERTS_ENQUEUE_DIRTY_IO_QUEUE:
- case -ERTS_ENQUEUE_DIRTY_IO_QUEUE:
- runq = ERTS_DIRTY_IO_RUNQ;
- ASSERT(ERTS_SCHEDULER_IS_DIRTY_IO(runq->scheduler));
-#ifdef ERTS_SMP
- check_emigration_need = 0;
-#endif
- break;
-#endif
-#endif
+ ASSERT(!(n & ERTS_PSFLG_SUSPENDED) || (n & (ERTS_PSFLG_ACTIVE_SYS
+ | ERTS_PSFLG_DIRTY_ACTIVE_SYS)));
- default:
- ASSERT(enqueue == ERTS_ENQUEUE_NORMAL_QUEUE
- || enqueue == -ERTS_ENQUEUE_NORMAL_QUEUE);
+ if (enqueue < 0)
+ sched_p = make_proxy_proc(proxy, p, enq_prio);
+ else {
+ sched_p = p;
+ if (proxy)
+ free_proxy_proc(proxy);
+ }
- runq = erts_get_runq_proc(p);
-#ifdef ERTS_SMP
- check_emigration_need = !(ERTS_PSFLG_BOUND & n);
-#endif
- break;
- }
+ ASSERT(runq);
- ASSERT(!(n & ERTS_PSFLG_SUSPENDED) || (n & ERTS_PSFLG_ACTIVE_SYS));
+ erts_smp_runq_lock(runq);
- if (enqueue < 0)
- sched_p = make_proxy_proc(proxy, p, enq_prio);
- else {
- sched_p = p;
- if (proxy)
- free_proxy_proc(proxy);
- }
+ /* Enqueue the process */
+ enqueue_process(runq, (int) enq_prio, sched_p);
-#ifdef ERTS_SMP
- if (check_emigration_need) {
- ErtsRunQueue *new_runq = erts_check_emigration_need(runq, enq_prio);
- if (new_runq) {
- RUNQ_SET_RQ(&sched_p->run_queue, new_runq);
- runq = new_runq;
- }
- }
-#endif
+ if (runq == c_rq)
+ return 1;
- ASSERT(runq);
+ erts_smp_runq_unlock(runq);
- erts_smp_runq_lock(runq);
+ smp_notify_inc_runq(runq);
- /* Enqueue the process */
- enqueue_process(runq, (int) enq_prio, sched_p);
+ erts_smp_runq_lock(c_rq);
- if (runq == c_rq)
return 1;
- erts_smp_runq_unlock(runq);
- smp_notify_inc_runq(runq);
- erts_smp_runq_lock(c_rq);
- return 1;
+ }
+
}
static ERTS_INLINE void
-add2runq(Process *p, erts_aint32_t state, erts_aint32_t prio)
+add2runq(int enqueue, erts_aint32_t prio,
+ Process *proc, erts_aint32_t state,
+ Process **proxy)
{
- ErtsRunQueue *runq = erts_get_runq_proc(p);
+ ErtsRunQueue *runq;
-#ifdef ERTS_SMP
- if (!(ERTS_PSFLG_BOUND & state)) {
- ErtsRunQueue *new_runq = erts_check_emigration_need(runq, (int) prio);
- if (new_runq) {
- RUNQ_SET_RQ(&p->run_queue, new_runq);
- runq = new_runq;
- }
- }
-#endif
- ASSERT(runq);
+ runq = select_enqueue_run_queue(enqueue, prio, proc, state);
+
+ if (runq) {
+ Process *sched_p;
- erts_smp_runq_lock(runq);
+ if (enqueue > 0)
+ sched_p = proc;
+ else {
+ Process *pxy;
- /* Enqueue the process */
- enqueue_process(runq, (int) prio, p);
+ if (!proxy)
+ pxy = NULL;
+ else {
+ pxy = *proxy;
+ *proxy = NULL;
+ }
+ sched_p = make_proxy_proc(pxy, proc, prio);
+ }
- erts_smp_runq_unlock(runq);
- smp_notify_inc_runq(runq);
+ erts_smp_runq_lock(runq);
+ /* Enqueue the process */
+ enqueue_process(runq, (int) prio, sched_p);
+
+ erts_smp_runq_unlock(runq);
+ smp_notify_inc_runq(runq);
+ }
}
static ERTS_INLINE int
@@ -6435,10 +6596,7 @@ schedule_process(Process *p, erts_aint32_t in_state, ErtsProcLocks locks)
&state,
&enq_prio,
locks);
- if (enqueue != ERTS_ENQUEUE_NOT)
- add2runq(enqueue > 0 ? p : make_proxy_proc(NULL, p, enq_prio),
- state,
- enq_prio);
+ add2runq(enqueue, enq_prio, p, state, NULL);
}
void
@@ -6447,22 +6605,99 @@ erts_schedule_process(Process *p, erts_aint32_t state, ErtsProcLocks locks)
schedule_process(p, state, locks);
}
-static void
-schedule_process_sys_task(Process *p, erts_aint32_t state, Process *proxy)
+static int
+schedule_process_sys_task(Process *p, erts_aint32_t prio, ErtsProcSysTask *st)
{
- /*
- * Expects status lock to be locked when called, and
- * returns with status lock unlocked...
- */
- erts_aint32_t a = state, n, enq_prio = -1;
+ int res;
+ int locked;
+ ErtsProcSysTaskQs *stqs, *free_stqs;
+ erts_aint32_t state, a, n, enq_prio;
int enqueue; /* < 0 -> use proxy */
- unsigned int prof_runnable_procs = erts_system_profile_flags.runnable_procs;
+ unsigned int prof_runnable_procs;
+
+ res = 1; /* prepare for success */
+ st->next = st->prev = st; /* Prep for empty prio queue */
+ state = erts_smp_atomic32_read_nob(&p->state);
+ prof_runnable_procs = erts_system_profile_flags.runnable_procs;
+ locked = 0;
+ free_stqs = NULL;
+ if (state & ERTS_PSFLG_ACTIVE_SYS)
+ stqs = NULL;
+ else {
+ alloc_qs:
+ stqs = proc_sys_task_queues_alloc();
+ stqs->qmask = 1 << prio;
+ stqs->ncount = 0;
+ stqs->q[PRIORITY_MAX] = NULL;
+ stqs->q[PRIORITY_HIGH] = NULL;
+ stqs->q[PRIORITY_NORMAL] = NULL;
+ stqs->q[PRIORITY_LOW] = NULL;
+ stqs->q[prio] = st;
+ }
+
+ if (!locked) {
+ locked = 1;
+ erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
+
+ state = erts_smp_atomic32_read_nob(&p->state);
+ if (state & ERTS_PSFLG_EXITING) {
+ free_stqs = stqs;
+ res = 0;
+ goto cleanup;
+ }
+ }
+
+ if (!p->sys_task_qs) {
+ if (stqs)
+ p->sys_task_qs = stqs;
+ else
+ goto alloc_qs;
+ }
+ else {
+ free_stqs = stqs;
+ stqs = p->sys_task_qs;
+ if (!stqs->q[prio]) {
+ stqs->q[prio] = st;
+ stqs->qmask |= 1 << prio;
+ }
+ else {
+ st->next = stqs->q[prio];
+ st->prev = stqs->q[prio]->prev;
+ st->next->prev = st;
+ st->prev->next = st;
+ ASSERT(stqs->qmask & (1 << prio));
+ }
+ }
+
+ if (ERTS_PSFLGS_GET_ACT_PRIO(state) > prio) {
+ erts_aint32_t n, a, e;
+ /* Need to elevate actual prio */
+
+ a = state;
+ do {
+ if (ERTS_PSFLGS_GET_ACT_PRIO(a) <= prio) {
+ n = a;
+ break;
+ }
+ n = e = a;
+ n &= ~ERTS_PSFLGS_ACT_PRIO_MASK;
+ n |= (prio << ERTS_PSFLGS_ACT_PRIO_OFFSET);
+ a = erts_smp_atomic32_cmpxchg_nob(&p->state, n, e);
+ } while (a != e);
+ state = n;
+ }
+
+
+ a = state;
+ enq_prio = -1;
/* Status lock prevents out of order "runnable proc" trace msgs */
ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_STATUS & erts_proc_lc_my_proc_locks(p));
- if (!prof_runnable_procs)
+ if (!prof_runnable_procs) {
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+ locked = 0;
+ }
ASSERT(!(state & ERTS_PSFLG_PROXY));
@@ -6470,8 +6705,10 @@ schedule_process_sys_task(Process *p, erts_aint32_t state, Process *proxy)
erts_aint32_t e;
n = e = a;
- if (a & ERTS_PSFLG_FREE)
+ if (a & ERTS_PSFLG_FREE) {
+ res = 0;
goto cleanup; /* We don't want to schedule free processes... */
+ }
enqueue = ERTS_ENQUEUE_NOT;
n |= ERTS_PSFLG_ACTIVE_SYS;
@@ -6495,29 +6732,22 @@ schedule_process_sys_task(Process *p, erts_aint32_t state, Process *proxy)
}
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
- prof_runnable_procs = 0;
+ locked = 0;
}
- if (enqueue != ERTS_ENQUEUE_NOT) {
- Process *sched_p;
- if (enqueue > 0)
- sched_p = p;
- else {
- sched_p = make_proxy_proc(proxy, p, enq_prio);
- proxy = NULL;
- }
- add2runq(sched_p, n, enq_prio);
- }
+ add2runq(enqueue, enq_prio, p, n, NULL);
cleanup:
- if (prof_runnable_procs)
+ if (locked)
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
- if (proxy)
- free_proxy_proc(proxy);
+ if (free_stqs)
+ proc_sys_task_queues_free(free_stqs);
ERTS_SMP_LC_ASSERT(!(ERTS_PROC_LOCK_STATUS & erts_proc_lc_my_proc_locks(p)));
+
+ return res;
}
static ERTS_INLINE int
@@ -6600,23 +6830,7 @@ resume_process(Process *p, ErtsProcLocks locks)
&state,
&enq_prio,
locks);
- if (enqueue)
- add2runq(enqueue > 0 ? p : make_proxy_proc(NULL, p, enq_prio),
- state,
- enq_prio);
-}
-
-int
-erts_get_max_no_executing_schedulers(void)
-{
-#ifdef ERTS_SMP
- if (erts_smp_atomic32_read_nob(&schdlr_sspnd.changing))
- return (int) erts_no_schedulers;
- ERTS_THR_MEMORY_BARRIER;
- return (int) erts_smp_atomic32_read_nob(&schdlr_sspnd.active);
-#else
- return 1;
-#endif
+ add2runq(enqueue, enq_prio, p, state, NULL);
}
#ifdef ERTS_SMP
@@ -6721,42 +6935,82 @@ sched_set_suspended_sleeptype(ErtsSchedulerSleepInfo *ssi)
}
}
-#ifdef ERTS_DIRTY_SCHEDULERS
+static void
+init_scheduler_suspend(void)
+{
+ erts_smp_mtx_init(&schdlr_sspnd.mtx, "schdlr_sspnd");
+ schdlr_sspnd.online = ERTS_SCHDLR_SSPND_MAKE_NSCHEDS_VAL(1, 0, 0);
+ schdlr_sspnd.curr_online = ERTS_SCHDLR_SSPND_MAKE_NSCHEDS_VAL(1, 0, 0);
+ schdlr_sspnd.active = ERTS_SCHDLR_SSPND_MAKE_NSCHEDS_VAL(1, 0, 0);
+ erts_smp_atomic32_init_nob(&schdlr_sspnd.changing, 0);
+ schdlr_sspnd.chngq = NULL;
+ schdlr_sspnd.changer = am_false;
+ schdlr_sspnd.nmsb.ongoing = 0;
+ schdlr_sspnd.nmsb.blckrs = NULL;
+ schdlr_sspnd.nmsb.chngq = NULL;
+ schdlr_sspnd.msb.ongoing = 0;
+ schdlr_sspnd.msb.blckrs = NULL;
+ schdlr_sspnd.msb.chngq = NULL;
+}
+
+typedef struct {
+ struct {
+ Eterm chngr;
+ Eterm nxt;
+ } onln;
+ struct {
+ ErtsProcList *chngrs;
+ } msb;
+} ErtsSchdlrSspndResume;
+
+static void
+schdlr_sspnd_resume_proc(Eterm pid)
+{
+ Process *p = erts_pid2proc(NULL, 0, pid, ERTS_PROC_LOCK_STATUS);
+ if (p) {
+ resume_process(p, ERTS_PROC_LOCK_STATUS);
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+ }
+}
+
+static ERTS_INLINE void
+schdlr_sspnd_resume_procs(ErtsSchedType sched_type,
+ ErtsSchdlrSspndResume *resume)
+{
+ if (is_internal_pid(resume->onln.chngr)) {
+ schdlr_sspnd_resume_proc(resume->onln.chngr);
+ resume->onln.chngr = NIL;
+ }
+ if (is_internal_pid(resume->onln.nxt)) {
+ schdlr_sspnd_resume_proc(resume->onln.nxt);
+ resume->onln.nxt = NIL;
+ }
+ while (resume->msb.chngrs) {
+ ErtsProcList *plp = resume->msb.chngrs;
+ resume->msb.chngrs = plp->next;
+ schdlr_sspnd_resume_proc(plp->pid);
+ proclist_destroy(plp);
+ }
+}
static void
suspend_scheduler(ErtsSchedulerData *esdp)
{
erts_aint32_t flgs;
erts_aint32_t changing;
-#ifdef ERTS_DIRTY_SCHEDULERS
- long no = (long) (ERTS_SCHEDULER_IS_DIRTY(esdp)
- ? ERTS_DIRTY_SCHEDULER_NO(esdp)
- : esdp->no);
-#else
- long no = (long) esdp->no;
-#endif
+ long no;
ErtsSchedulerSleepInfo *ssi = esdp->ssi;
- long active_schedulers;
int curr_online = 1;
- int wake = 0;
+ ErtsSchdlrSspndResume resume = {{NIL, NIL}, {NULL}};
erts_aint32_t aux_work;
int thr_prgr_active = 1;
ErtsStuckBoundProcesses sbp = {NULL, NULL};
- int* ss_onlinep;
- int* ss_curr_onlinep;
- int* ss_wait_curr_onlinep;
- long* ss_wait_activep;
- long ss_wait_active_target;
- erts_smp_atomic32_t* ss_changingp;
- erts_smp_atomic32_t* ss_activep;
+ ErtsSchedType sched_type;
+ erts_aint32_t online_flag;
/*
* Schedulers may be suspended in two different ways:
* - A scheduler may be suspended since it is not online.
- * All schedulers with scheduler ids greater than
- * schdlr_sspnd.online are suspended; same for dirty
- * schedulers and schdlr_sspnd.dirty_cpu_online and
- * schdlr_sspnd.dirty_io_online.
* - Multi scheduling is blocked. All schedulers except the
* scheduler with scheduler id 1 are suspended, and all
* dirty CPU and dirty I/O schedulers are suspended.
@@ -6764,27 +7018,43 @@ suspend_scheduler(ErtsSchedulerData *esdp)
* Regardless of why a scheduler is suspended, it ends up here.
*/
- ASSERT(ERTS_SCHEDULER_IS_DIRTY(esdp) || no != 1);
-
#ifdef ERTS_DIRTY_SCHEDULERS
if (ERTS_SCHEDULER_IS_DIRTY(esdp)) {
+ no = ERTS_DIRTY_SCHEDULER_NO(esdp);
+ if (ERTS_RUNQ_IS_DIRTY_CPU_RUNQ(esdp->run_queue)) {
+ online_flag = ERTS_SCHDLR_SSPND_CHNG_DCPU_ONLN;
+ sched_type = ERTS_SCHED_DIRTY_CPU;
+ }
+ else {
+ online_flag = 0;
+ sched_type = ERTS_SCHED_DIRTY_IO;
+ }
+ }
+ else
+#endif
+ {
+ online_flag = ERTS_SCHDLR_SSPND_CHNG_ONLN;
+ no = esdp->no;
+ sched_type = ERTS_SCHED_NORMAL;
+ }
+
+ ASSERT(sched_type != ERTS_SCHED_NORMAL || no != 1);
+
+ if (sched_type != ERTS_SCHED_NORMAL) {
if (erts_smp_mtx_trylock(&schdlr_sspnd.mtx) == EBUSY) {
erts_smp_runq_unlock(esdp->run_queue);
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
erts_smp_runq_lock(esdp->run_queue);
}
- if (ongoing_multi_scheduling_block())
+ if (schdlr_sspnd.msb.ongoing)
evacuate_run_queue(esdp->run_queue, &sbp);
- } else
-#endif
+ erts_smp_runq_unlock(esdp->run_queue);
+ }
+ else {
evacuate_run_queue(esdp->run_queue, &sbp);
- erts_smp_runq_unlock(esdp->run_queue);
+ erts_smp_runq_unlock(esdp->run_queue);
-#ifdef ERTS_DIRTY_SCHEDULERS
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp))
-#endif
- {
erts_sched_check_cpu_bind_prep_suspend(esdp);
if (erts_system_profile_flags.scheduler)
@@ -6798,318 +7068,115 @@ suspend_scheduler(ErtsSchedulerData *esdp)
flgs = sched_prep_spin_suspended(ssi, ERTS_SSI_FLG_SUSPENDED);
if (flgs & ERTS_SSI_FLG_SUSPENDED) {
-#ifdef ERTS_DIRTY_SCHEDULERS
- if (ERTS_SCHEDULER_IS_DIRTY(esdp)) {
- if (ERTS_RUNQ_IS_DIRTY_CPU_RUNQ(esdp->run_queue)) {
- active_schedulers = erts_smp_atomic32_dec_read_nob(&schdlr_sspnd.dirty_cpu_active);
- ASSERT(active_schedulers >= 0);
- changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.dirty_cpu_changing);
- ss_onlinep = &schdlr_sspnd.dirty_cpu_online;
- ss_curr_onlinep = &schdlr_sspnd.dirty_cpu_curr_online;
- ss_wait_curr_onlinep = &schdlr_sspnd.dirty_cpu_wait_curr_online;
- ss_changingp = &schdlr_sspnd.dirty_cpu_changing;
- ss_wait_activep = &schdlr_sspnd.msb.dirty_cpu_wait_active;
- ss_activep = &schdlr_sspnd.dirty_cpu_active;
- } else {
- active_schedulers = erts_smp_atomic32_dec_read_nob(&schdlr_sspnd.dirty_io_active);
- ASSERT(active_schedulers >= 0);
- changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.dirty_io_changing);
- ss_onlinep = &schdlr_sspnd.dirty_io_online;
- ss_curr_onlinep = &schdlr_sspnd.dirty_io_curr_online;
- ss_wait_curr_onlinep = &schdlr_sspnd.dirty_io_wait_curr_online;
- ss_changingp = &schdlr_sspnd.dirty_io_changing;
- ss_wait_activep = &schdlr_sspnd.msb.dirty_io_wait_active;
- ss_activep = &schdlr_sspnd.dirty_io_active;
- }
- ss_wait_active_target = 0;
- }
- else
-#endif
- {
- active_schedulers = erts_smp_atomic32_dec_read_nob(&schdlr_sspnd.active);
- ASSERT(active_schedulers >= 1);
- changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
- ss_onlinep = &schdlr_sspnd.online;
- ss_curr_onlinep = &schdlr_sspnd.curr_online;
- ss_wait_curr_onlinep = &schdlr_sspnd.wait_curr_online;
- ss_changingp = &schdlr_sspnd.changing;
- ss_wait_activep = &schdlr_sspnd.msb.wait_active;
- ss_activep = &schdlr_sspnd.active;
- ss_wait_active_target = 1;
- }
- if (changing & ERTS_SCHDLR_SSPND_CHNG_MSB) {
- if (active_schedulers == *ss_wait_activep)
- wake = 1;
- if (active_schedulers == ss_wait_active_target) {
- changing = erts_smp_atomic32_read_band_nob(ss_changingp,
- ~ERTS_SCHDLR_SSPND_CHNG_MSB);
- changing &= ~ERTS_SCHDLR_SSPND_CHNG_MSB;
- }
- }
+ schdlr_sspnd_dec_nscheds(&schdlr_sspnd.active, sched_type);
- while (1) {
- if (changing & ERTS_SCHDLR_SSPND_CHNG_ONLN) {
- int changed = 0;
- if (no > *ss_onlinep && curr_online) {
- (*ss_curr_onlinep)--;
- curr_online = 0;
- changed = 1;
- }
- else if (no <= *ss_onlinep && !curr_online) {
- (*ss_curr_onlinep)++;
- curr_online = 1;
- changed = 1;
- }
- if (changed
- && *ss_curr_onlinep == *ss_wait_curr_onlinep)
- wake = 1;
- if (*ss_onlinep == *ss_curr_onlinep) {
- changing = erts_smp_atomic32_read_band_nob(ss_changingp,
- ~ERTS_SCHDLR_SSPND_CHNG_ONLN);
- changing &= ~ERTS_SCHDLR_SSPND_CHNG_ONLN;
- }
- }
-
- if (wake) {
- erts_smp_cnd_signal(&schdlr_sspnd.cnd);
- wake = 0;
- }
-
- if (curr_online && !ongoing_multi_scheduling_block()) {
- flgs = erts_smp_atomic32_read_acqb(&ssi->flags);
- if (!(flgs & ERTS_SSI_FLG_SUSPENDED))
- break;
- }
- erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+ ASSERT(schdlr_sspnd_get_nscheds(&schdlr_sspnd.active,
+ ERTS_SCHED_NORMAL) >= 1);
- while (1) {
- erts_aint32_t qmask;
- erts_aint32_t flgs;
+ changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
- qmask = (ERTS_RUNQ_FLGS_GET(esdp->run_queue)
- & ERTS_RUNQ_FLGS_QMASK);
- aux_work = erts_atomic32_read_acqb(&ssi->aux_work);
- if (aux_work|qmask) {
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp)) {
- if (!thr_prgr_active) {
- erts_thr_progress_active(esdp, thr_prgr_active = 1);
- sched_wall_time_change(esdp, 1);
- }
- if (aux_work)
- aux_work = handle_aux_work(&esdp->aux_work_data,
- aux_work,
- 1);
+ while (1) {
- if (aux_work && erts_thr_progress_update(esdp))
- erts_thr_progress_leader_update(esdp);
- }
- if (qmask) {
-#ifdef ERTS_DIRTY_SCHEDULERS
- if (ERTS_SCHEDULER_IS_DIRTY(esdp)) {
- erts_smp_mtx_lock(&schdlr_sspnd.mtx);
- erts_smp_runq_lock(esdp->run_queue);
- if (ongoing_multi_scheduling_block())
- evacuate_run_queue(esdp->run_queue, &sbp);
- erts_smp_runq_unlock(esdp->run_queue);
- erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
- } else
-#endif
- {
- erts_smp_runq_lock(esdp->run_queue);
- evacuate_run_queue(esdp->run_queue, &sbp);
- erts_smp_runq_unlock(esdp->run_queue);
- }
+ if (changing & (ERTS_SCHDLR_SSPND_CHNG_NMSB
+ | ERTS_SCHDLR_SSPND_CHNG_MSB)) {
+ int i = 0;
+ ErtsMultiSchedulingBlock *msb[3] = {0};
+ if (changing & ERTS_SCHDLR_SSPND_CHNG_NMSB)
+ msb[i++] = &schdlr_sspnd.nmsb;
+ if (changing & ERTS_SCHDLR_SSPND_CHNG_MSB)
+ msb[i++] = &schdlr_sspnd.msb;
+
+ for (i = 0; msb[i]; i++) {
+ erts_aint32_t clr_flg = 0;
+
+ if (msb[i] == &schdlr_sspnd.nmsb
+ && schdlr_sspnd_get_nscheds(&schdlr_sspnd.active,
+ ERTS_SCHED_NORMAL) == 1) {
+ clr_flg = ERTS_SCHDLR_SSPND_CHNG_NMSB;
}
- }
-
- if (!aux_work) {
-#ifdef ERTS_DIRTY_SCHEDULERS
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp))
-#endif
- {
- if (thr_prgr_active) {
- erts_thr_progress_active(esdp, thr_prgr_active = 0);
- sched_wall_time_change(esdp, 0);
- }
- erts_thr_progress_prepare_wait(esdp);
+ else if (schdlr_sspnd.active
+ == ERTS_SCHDLR_SSPND_MAKE_NSCHEDS_VAL(1, 0, 0)) {
+ clr_flg = ERTS_SCHDLR_SSPND_CHNG_MSB;
}
- flgs = sched_spin_suspended(ssi,
- ERTS_SCHED_SUSPEND_SLEEP_SPINCOUNT);
- if (flgs == (ERTS_SSI_FLG_SLEEPING
- | ERTS_SSI_FLG_WAITING
- | ERTS_SSI_FLG_SUSPENDED)) {
- flgs = sched_set_suspended_sleeptype(ssi);
- if (flgs == (ERTS_SSI_FLG_SLEEPING
- | ERTS_SSI_FLG_TSE_SLEEPING
- | ERTS_SSI_FLG_WAITING
- | ERTS_SSI_FLG_SUSPENDED)) {
- int res;
- do {
- res = erts_tse_twait(ssi->event, -1);
- } while (res == EINTR);
+ if (clr_flg) {
+ ErtsProcList *plp, *end_plp;
+ changing = erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
+ ~clr_flg);
+ changing &= ~clr_flg;
+ (void) erts_proclist_fetch(&msb[i]->chngq, &end_plp);
+ /* resume processes that initiated the multi scheduling block... */
+ plp = msb[i]->chngq;
+ while (plp) {
+ erts_proclist_store_last(&msb[i]->blckrs,
+ proclist_copy(plp));
+ plp = plp->next;
}
+ if (end_plp)
+ end_plp->next = resume.msb.chngrs;
+ resume.msb.chngrs = msb[i]->chngq;
+ msb[i]->chngq = NULL;
}
-#ifdef ERTS_DIRTY_SCHEDULERS
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp))
-#endif
- erts_thr_progress_finalize_wait(esdp);
}
-
- flgs = sched_prep_spin_suspended(ssi, (ERTS_SSI_FLG_WAITING
- | ERTS_SSI_FLG_SUSPENDED));
- if (!(flgs & ERTS_SSI_FLG_SUSPENDED))
- break;
- changing = erts_smp_atomic32_read_nob(ss_changingp);
- if (changing & ~ERTS_SCHDLR_SSPND_CHNG_WAITER)
- break;
}
- erts_smp_mtx_lock(&schdlr_sspnd.mtx);
- changing = erts_smp_atomic32_read_nob(ss_changingp);
- }
-
- active_schedulers = erts_smp_atomic32_inc_read_nob(ss_activep);
- changing = erts_smp_atomic32_read_nob(ss_changingp);
- if ((changing & ERTS_SCHDLR_SSPND_CHNG_MSB)
- && *ss_onlinep == active_schedulers) {
- erts_smp_atomic32_read_band_nob(ss_changingp,
- ~ERTS_SCHDLR_SSPND_CHNG_MSB);
- }
-
-#ifdef ERTS_DIRTY_SCHEDULERS
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp))
-#endif
- ASSERT(no <= *ss_onlinep);
- ASSERT(!ongoing_multi_scheduling_block());
-
- }
-
- erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
-
- ASSERT(curr_online);
-
-#ifdef ERTS_DIRTY_SCHEDULERS
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp))
-#endif
- {
- if (erts_system_profile_flags.scheduler)
- profile_scheduler(make_small(esdp->no), am_active);
-
- if (!thr_prgr_active) {
- erts_thr_progress_active(esdp, thr_prgr_active = 1);
- sched_wall_time_change(esdp, 1);
- }
- }
-
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp))
- (void) erts_get_monotonic_time(esdp);
- erts_smp_runq_lock(esdp->run_queue);
- non_empty_runq(esdp->run_queue);
-
-#ifdef ERTS_DIRTY_SCHEDULERS
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp))
-#endif
- {
- schedule_bound_processes(esdp->run_queue, &sbp);
-
- erts_sched_check_cpu_bind_post_suspend(esdp);
- }
-}
-
-#else /* !ERTS_DIRTY_SCHEDULERS */
-
-static void
-suspend_scheduler(ErtsSchedulerData *esdp)
-{
- erts_aint32_t flgs;
- erts_aint32_t changing;
- long no = (long) esdp->no;
- ErtsSchedulerSleepInfo *ssi = esdp->ssi;
- long active_schedulers;
- int curr_online = 1;
- int wake = 0;
- erts_aint32_t aux_work;
- int thr_prgr_active = 1;
- ErtsStuckBoundProcesses sbp = {NULL, NULL};
-
- /*
- * Schedulers may be suspended in two different ways:
- * - A scheduler may be suspended since it is not online.
- * All schedulers with scheduler ids greater than
- * schdlr_sspnd.online are suspended.
- * - Multi scheduling is blocked. All schedulers except the
- * scheduler with scheduler id 1 are suspended.
- *
- * Regardless of why a scheduler is suspended, it ends up here.
- */
-
- ASSERT(no != 1);
-
- evacuate_run_queue(esdp->run_queue, &sbp);
-
- erts_smp_runq_unlock(esdp->run_queue);
-
- erts_sched_check_cpu_bind_prep_suspend(esdp);
-
- if (erts_system_profile_flags.scheduler)
- profile_scheduler(make_small(esdp->no), am_inactive);
-
- sched_wall_time_change(esdp, 0);
-
- erts_smp_mtx_lock(&schdlr_sspnd.mtx);
-
- flgs = sched_prep_spin_suspended(ssi, ERTS_SSI_FLG_SUSPENDED);
- if (flgs & ERTS_SSI_FLG_SUSPENDED) {
-
- active_schedulers = erts_smp_atomic32_dec_read_nob(&schdlr_sspnd.active);
- ASSERT(active_schedulers >= 1);
- changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
- if (changing & ERTS_SCHDLR_SSPND_CHNG_MSB) {
- if (active_schedulers == schdlr_sspnd.msb.wait_active)
- wake = 1;
- if (active_schedulers == 1) {
- changing = erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
- ~ERTS_SCHDLR_SSPND_CHNG_MSB);
- changing &= ~ERTS_SCHDLR_SSPND_CHNG_MSB;
- }
- }
-
- while (1) {
- if (changing & ERTS_SCHDLR_SSPND_CHNG_ONLN) {
+ if (changing & online_flag) {
int changed = 0;
- if (no > schdlr_sspnd.online && curr_online) {
- schdlr_sspnd.curr_online--;
+ Uint32 st_online;
+
+ st_online = schdlr_sspnd_get_nscheds(&schdlr_sspnd.online,
+ sched_type);
+ if (no > st_online && curr_online) {
+ schdlr_sspnd_dec_nscheds(&schdlr_sspnd.curr_online,
+ sched_type);
curr_online = 0;
changed = 1;
}
- else if (no <= schdlr_sspnd.online && !curr_online) {
- schdlr_sspnd.curr_online++;
+ else if (no <= st_online && !curr_online) {
+ schdlr_sspnd_inc_nscheds(&schdlr_sspnd.curr_online,
+ sched_type);
curr_online = 1;
changed = 1;
}
if (changed
- && schdlr_sspnd.curr_online == schdlr_sspnd.wait_curr_online)
- wake = 1;
- if (schdlr_sspnd.online == schdlr_sspnd.curr_online) {
+ && (schdlr_sspnd_get_nscheds(&schdlr_sspnd.online,
+ sched_type)
+ == schdlr_sspnd_get_nscheds(&schdlr_sspnd.curr_online,
+ sched_type))) {
+ ErtsProcList *plp;
changing = erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
- ~ERTS_SCHDLR_SSPND_CHNG_ONLN);
- changing &= ~ERTS_SCHDLR_SSPND_CHNG_ONLN;
+ ~online_flag);
+ changing &= ~online_flag;
+ if (sched_type == ERTS_SCHED_NORMAL) {
+ ASSERT(is_internal_pid(schdlr_sspnd.changer)
+ || schdlr_sspnd.changer == am_init);
+ /* resume process that initiated this change... */
+ resume.onln.chngr = schdlr_sspnd.changer;
+ plp = erts_proclist_peek_first(schdlr_sspnd.chngq);
+ if (!plp)
+ schdlr_sspnd.changer = am_false;
+ else {
+ schdlr_sspnd.changer = am_true; /* change right in transit */
+ /* resume process that is queued for next change... */
+ resume.onln.nxt = plp->pid;
+ ASSERT(is_internal_pid(resume.onln.nxt));
+ }
+ }
}
}
- if (wake) {
- erts_smp_cnd_signal(&schdlr_sspnd.cnd);
- wake = 0;
- }
-
- if (curr_online && !ongoing_multi_scheduling_block()) {
+ if (curr_online
+ && (sched_type == ERTS_SCHED_NORMAL
+ ? !(schdlr_sspnd.msb.ongoing|schdlr_sspnd.nmsb.ongoing)
+ : !schdlr_sspnd.msb.ongoing)) {
flgs = erts_smp_atomic32_read_acqb(&ssi->flags);
if (!(flgs & ERTS_SSI_FLG_SUSPENDED))
break;
}
erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+ schdlr_sspnd_resume_procs(sched_type, &resume);
+
while (1) {
ErtsMonotonicTime current_time;
erts_aint32_t qmask;
@@ -7117,9 +7184,23 @@ suspend_scheduler(ErtsSchedulerData *esdp)
qmask = (ERTS_RUNQ_FLGS_GET(esdp->run_queue)
& ERTS_RUNQ_FLGS_QMASK);
- aux_work = erts_atomic32_read_acqb(&ssi->aux_work);
- if (aux_work|qmask) {
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp)) {
+
+ if (sched_type != ERTS_SCHED_NORMAL) {
+ if (qmask) {
+ erts_smp_mtx_lock(&schdlr_sspnd.mtx);
+ erts_smp_runq_lock(esdp->run_queue);
+ if (schdlr_sspnd.msb.ongoing)
+ evacuate_run_queue(esdp->run_queue, &sbp);
+ erts_smp_runq_unlock(esdp->run_queue);
+ erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+ }
+ aux_work = 0;
+ }
+ else {
+
+ aux_work = erts_atomic32_read_acqb(&ssi->aux_work);
+
+ if (aux_work|qmask) {
if (!thr_prgr_active) {
erts_thr_progress_active(esdp, thr_prgr_active = 1);
sched_wall_time_change(esdp, 1);
@@ -7128,45 +7209,53 @@ suspend_scheduler(ErtsSchedulerData *esdp)
aux_work = handle_aux_work(&esdp->aux_work_data,
aux_work,
1);
+
if (aux_work && erts_thr_progress_update(esdp))
erts_thr_progress_leader_update(esdp);
+ if (qmask) {
+ erts_smp_runq_lock(esdp->run_queue);
+ evacuate_run_queue(esdp->run_queue, &sbp);
+ erts_smp_runq_unlock(esdp->run_queue);
+ }
}
- if (qmask) {
- erts_smp_runq_lock(esdp->run_queue);
- evacuate_run_queue(esdp->run_queue, &sbp);
- erts_smp_runq_unlock(esdp->run_queue);
- }
+
}
if (aux_work) {
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp)) {
- current_time = erts_get_monotonic_time(esdp);
- if (current_time >= erts_next_timeout_time(esdp->next_tmo_ref)) {
- if (!thr_prgr_active) {
- erts_thr_progress_active(esdp, thr_prgr_active = 1);
- sched_wall_time_change(esdp, 1);
- }
- erts_bump_timers(esdp->timer_wheel, current_time);
+ ASSERT(sched_type == ERTS_SCHED_NORMAL);
+ current_time = erts_get_monotonic_time(esdp);
+ if (current_time >= erts_next_timeout_time(esdp->next_tmo_ref)) {
+ if (!thr_prgr_active) {
+ erts_thr_progress_active(esdp, thr_prgr_active = 1);
+ sched_wall_time_change(esdp, 1);
}
+ erts_bump_timers(esdp->timer_wheel, current_time);
}
}
else {
ErtsMonotonicTime timeout_time;
- int do_timeout = 0;
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp)) {
+ int do_timeout;
+
+ if (sched_type == ERTS_SCHED_NORMAL) {
timeout_time = erts_check_next_timeout_time(esdp);
current_time = erts_get_monotonic_time(esdp);
do_timeout = (current_time >= timeout_time);
- } else
+ }
+ else {
timeout_time = ERTS_MONOTONIC_TIME_MAX;
+ current_time = 0;
+ do_timeout = 0;
+ }
+
if (do_timeout) {
+ ASSERT(sched_type == ERTS_SCHED_NORMAL);
if (!thr_prgr_active) {
erts_thr_progress_active(esdp, thr_prgr_active = 1);
sched_wall_time_change(esdp, 1);
}
}
else {
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp)) {
+ if (sched_type == ERTS_SCHED_NORMAL) {
if (thr_prgr_active) {
erts_thr_progress_active(esdp, thr_prgr_active = 0);
sched_wall_time_change(esdp, 0);
@@ -7185,30 +7274,39 @@ suspend_scheduler(ErtsSchedulerData *esdp)
| ERTS_SSI_FLG_SUSPENDED)) {
int res;
- current_time = ERTS_SCHEDULER_IS_DIRTY(esdp) ? 0 :
- erts_get_monotonic_time(esdp);
+ if (sched_type == ERTS_SCHED_NORMAL)
+ current_time = erts_get_monotonic_time(esdp);
+ else
+ current_time = 0;
+
do {
Sint64 timeout;
if (current_time >= timeout_time)
break;
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp)) {
+ if (sched_type != ERTS_SCHED_NORMAL)
+ timeout = -1;
+ else
timeout = ERTS_MONOTONIC_TO_NSEC(timeout_time
- current_time
- 1) + 1;
- } else
- timeout = -1;
res = erts_tse_twait(ssi->event, timeout);
- current_time = ERTS_SCHEDULER_IS_DIRTY(esdp) ? 0 :
- erts_get_monotonic_time(esdp);
+
+ if (sched_type == ERTS_SCHED_NORMAL)
+ current_time = erts_get_monotonic_time(esdp);
+ else
+ current_time = 0;
+
} while (res == EINTR);
}
}
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp))
+ if (sched_type == ERTS_SCHED_NORMAL)
erts_thr_progress_finalize_wait(esdp);
}
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp) && current_time >= timeout_time)
+ if (current_time >= timeout_time) {
+ ASSERT(sched_type == ERTS_SCHED_NORMAL);
erts_bump_timers(esdp->timer_wheel, current_time);
+ }
}
flgs = sched_prep_spin_suspended(ssi, (ERTS_SSI_FLG_WAITING
@@ -7216,7 +7314,7 @@ suspend_scheduler(ErtsSchedulerData *esdp)
if (!(flgs & ERTS_SSI_FLG_SUSPENDED))
break;
changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
- if (changing & ~ERTS_SCHDLR_SSPND_CHNG_WAITER)
+ if (changing)
break;
}
@@ -7224,612 +7322,494 @@ suspend_scheduler(ErtsSchedulerData *esdp)
changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
}
- active_schedulers = erts_smp_atomic32_inc_read_nob(&schdlr_sspnd.active);
+ schdlr_sspnd_inc_nscheds(&schdlr_sspnd.active, sched_type);
changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
if ((changing & ERTS_SCHDLR_SSPND_CHNG_MSB)
- && schdlr_sspnd.online == active_schedulers) {
+ && schdlr_sspnd.online == schdlr_sspnd.active) {
erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
~ERTS_SCHDLR_SSPND_CHNG_MSB);
}
- ASSERT(no <= schdlr_sspnd.online);
- ASSERT(!ongoing_multi_scheduling_block());
-
+ ASSERT(no <= schdlr_sspnd_get_nscheds(&schdlr_sspnd.online, sched_type));
+ ASSERT((sched_type == ERTS_SCHED_NORMAL
+ ? !(schdlr_sspnd.msb.ongoing|schdlr_sspnd.nmsb.ongoing)
+ : !schdlr_sspnd.msb.ongoing));
}
erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+ ASSERT(!resume.msb.chngrs);
+ schdlr_sspnd_resume_procs(sched_type, &resume);
+
ASSERT(curr_online);
- if (erts_system_profile_flags.scheduler)
- profile_scheduler(make_small(esdp->no), am_active);
+ if (!ERTS_SCHEDULER_IS_DIRTY(esdp)) {
+ if (erts_system_profile_flags.scheduler)
+ profile_scheduler(make_small(esdp->no), am_active);
- if (!thr_prgr_active) {
- erts_thr_progress_active(esdp, thr_prgr_active = 1);
- sched_wall_time_change(esdp, 1);
+ if (!thr_prgr_active) {
+ erts_thr_progress_active(esdp, thr_prgr_active = 1);
+ sched_wall_time_change(esdp, 1);
+ }
}
+ if (sched_type == ERTS_SCHED_NORMAL)
+ (void) erts_get_monotonic_time(esdp);
erts_smp_runq_lock(esdp->run_queue);
non_empty_runq(esdp->run_queue);
- schedule_bound_processes(esdp->run_queue, &sbp);
+ if (sched_type == ERTS_SCHED_NORMAL) {
+ schedule_bound_processes(esdp->run_queue, &sbp);
- erts_sched_check_cpu_bind_post_suspend(esdp);
+ erts_sched_check_cpu_bind_post_suspend(esdp);
+ }
}
-#endif
-
-ErtsSchedSuspendResult
+void
erts_schedulers_state(Uint *total,
Uint *online,
Uint *active,
Uint *dirty_cpu,
Uint *dirty_cpu_online,
+ Uint *dirty_cpu_active,
Uint *dirty_io,
- int yield_allowed)
+ Uint *dirty_io_active)
{
- int res = ERTS_SCHDLR_SSPND_EINVAL;
- erts_aint32_t changing;
- erts_smp_mtx_lock(&schdlr_sspnd.mtx);
- changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
-#ifdef ERTS_DIRTY_SCHEDULERS
- changing |= (erts_smp_atomic32_read_nob(&schdlr_sspnd.dirty_cpu_changing)
- | erts_smp_atomic32_read_nob(&schdlr_sspnd.dirty_io_changing));
-#endif
- if (yield_allowed && (changing & ~ERTS_SCHDLR_SSPND_CHNG_WAITER))
- res = ERTS_SCHDLR_SSPND_YIELD_RESTART;
- else {
+ if (active || online || dirty_cpu_online
+ || dirty_cpu_active || dirty_io_active) {
+ erts_smp_mtx_lock(&schdlr_sspnd.mtx);
if (active)
- *active = schdlr_sspnd.online;
+ *active = schdlr_sspnd_get_nscheds(&schdlr_sspnd.active,
+ ERTS_SCHED_NORMAL);
if (online)
- *online = schdlr_sspnd.online;
- if (ongoing_multi_scheduling_block() && active)
- *active = 1;
-#ifdef ERTS_DIRTY_SCHEDULERS
+ *online = schdlr_sspnd_get_nscheds(&schdlr_sspnd.curr_online,
+ ERTS_SCHED_NORMAL);
+ if (dirty_cpu_active)
+ *dirty_cpu_active = schdlr_sspnd_get_nscheds(&schdlr_sspnd.active,
+ ERTS_SCHED_DIRTY_CPU);
if (dirty_cpu_online)
- *dirty_cpu_online = schdlr_sspnd.dirty_cpu_online;
-#endif
- res = ERTS_SCHDLR_SSPND_DONE;
+ *dirty_cpu_online = schdlr_sspnd_get_nscheds(&schdlr_sspnd.curr_online,
+ ERTS_SCHED_DIRTY_CPU);
+ if (dirty_io_active)
+ *dirty_io_active = schdlr_sspnd_get_nscheds(&schdlr_sspnd.active,
+ ERTS_SCHED_DIRTY_IO);
+ erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
}
- erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+
if (total)
*total = erts_no_schedulers;
-#ifdef ERTS_DIRTY_SCHEDULERS
if (dirty_cpu)
*dirty_cpu = erts_no_dirty_cpu_schedulers;
if (dirty_io)
*dirty_io = erts_no_dirty_io_schedulers;
-#endif
- return res;
}
-#ifdef ERTS_DIRTY_SCHEDULERS
+static void
+abort_sched_onln_chng_waitq(Process *p)
+{
+ Eterm resume = NIL;
+
+ erts_smp_mtx_lock(&schdlr_sspnd.mtx);
+
+#ifdef DEBUG
+ {
+ int found_it = 0;
+ ErtsProcList *plp = erts_proclist_peek_first(schdlr_sspnd.chngq);
+ while (plp) {
+ if (erts_proclist_same(plp, p))
+ found_it++;
+ plp = erts_proclist_peek_next(schdlr_sspnd.chngq, plp);
+ }
+ ASSERT(found_it == !!(p->flags & F_SCHDLR_ONLN_WAITQ));
+ }
+#endif
+
+ if (p->flags & F_SCHDLR_ONLN_WAITQ) {
+ ErtsProcList *plp = NULL;
+
+ plp = erts_proclist_peek_first(schdlr_sspnd.chngq);
+ if (plp) {
+ if (erts_proclist_same(plp, p)
+ && schdlr_sspnd.changer == am_true) {
+ p->flags &= ~F_SCHDLR_ONLN_WAITQ;
+ /*
+ * Change right was in transit to us;
+ * transfer it to the next process by
+ * resuming it...
+ */
+ erts_proclist_remove(&schdlr_sspnd.chngq, plp);
+ proclist_destroy(plp);
+ plp = erts_proclist_peek_first(schdlr_sspnd.chngq);
+ if (plp)
+ resume = plp->pid;
+ else
+ schdlr_sspnd.changer = am_false;
+ }
+ else {
+ do {
+ if (erts_proclist_same(plp, p)) {
+ p->flags &= ~F_SCHDLR_ONLN_WAITQ;
+ erts_proclist_remove(&schdlr_sspnd.chngq, plp);
+ proclist_destroy(plp);
+ break;
+ }
+ plp = erts_proclist_peek_next(schdlr_sspnd.chngq, plp);
+ } while (plp);
+ }
+ }
+ }
+
+ erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+
+ if (is_internal_pid(resume))
+ schdlr_sspnd_resume_proc(resume);
+}
ErtsSchedSuspendResult
erts_set_schedulers_online(Process *p,
ErtsProcLocks plocks,
Sint new_no,
- Sint *old_no
-#ifdef ERTS_DIRTY_SCHEDULERS
- , int dirty_only
-#endif
- )
+ Sint *old_no,
+ int dirty_only)
{
- ErtsSchedulerData *esdp;
- int ix, res = -1, no, have_unlocked_plocks, end_wait;
- erts_aint32_t changing = 0;
+ int resume_proc, ix, res = -1, no, have_unlocked_plocks;
+ erts_aint32_t changing = 0, change_flags;
+ int online, increase;
+ ErtsProcList *plp;
#ifdef ERTS_DIRTY_SCHEDULERS
- ErtsSchedulerSleepInfo* ssi;
- int dirty_no, change_dirty;
+ int dirty_no, change_dirty, dirty_online;
+#else
+ ASSERT(!dirty_only);
#endif
if (new_no < 1)
return ERTS_SCHDLR_SSPND_EINVAL;
-#ifdef ERTS_DIRTY_SCHEDULERS
else if (dirty_only && erts_no_dirty_cpu_schedulers < new_no)
return ERTS_SCHDLR_SSPND_EINVAL;
-#endif
else if (erts_no_schedulers < new_no)
return ERTS_SCHDLR_SSPND_EINVAL;
- esdp = ERTS_PROC_GET_SCHDATA(p);
- end_wait = 0;
+#ifdef ERTS_DIRTY_SCHEDULERS
+ if (dirty_only)
+ resume_proc = 0;
+ else
+#endif
+ {
+ resume_proc = 1;
+ /*
+ * If we suspend current process we need to suspend before
+ * requesting the change; otherwise, we got a resume/suspend
+ * race...
+ */
+ if (!(plocks & ERTS_PROC_LOCK_STATUS))
+ erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
+ suspend_process(p, p);
+ if (!(plocks & ERTS_PROC_LOCK_STATUS))
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+ }
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
+ change_flags = 0;
have_unlocked_plocks = 0;
no = (int) new_no;
#ifdef ERTS_DIRTY_SCHEDULERS
- ASSERT(schdlr_sspnd.dirty_cpu_online <= erts_no_dirty_cpu_schedulers);
+ if (!dirty_only)
+#endif
+ {
+ changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
+ if (changing & ERTS_SCHDLR_SSPND_CHNG_ONLN) {
+ enqueue_wait:
+ p->flags |= F_SCHDLR_ONLN_WAITQ;
+ plp = proclist_create(p);
+ erts_proclist_store_last(&schdlr_sspnd.chngq, plp);
+ resume_proc = 0;
+ res = ERTS_SCHDLR_SSPND_YIELD_RESTART;
+ goto done;
+ }
+ plp = erts_proclist_peek_first(schdlr_sspnd.chngq);
+ if (!plp) {
+ ASSERT(schdlr_sspnd.changer == am_false);
+ }
+ else {
+ ASSERT(schdlr_sspnd.changer == am_true);
+ if (!erts_proclist_same(plp, p))
+ goto enqueue_wait;
+ p->flags &= ~F_SCHDLR_ONLN_WAITQ;
+ erts_proclist_remove(&schdlr_sspnd.chngq, plp);
+ proclist_destroy(plp);
+ }
+ }
+
+ *old_no = online = schdlr_sspnd_get_nscheds(&schdlr_sspnd.online,
+ ERTS_SCHED_NORMAL);
+#ifndef ERTS_DIRTY_SCHEDULERS
+ if (no == online) {
+ res = ERTS_SCHDLR_SSPND_DONE;
+ goto done;
+ }
+#else /* ERTS_DIRTY_SCHEDULERS */
+ dirty_online = schdlr_sspnd_get_nscheds(&schdlr_sspnd.online,
+ ERTS_SCHED_DIRTY_CPU);
+ if (dirty_only)
+ *old_no = dirty_online;
+
+ ASSERT(dirty_online <= erts_no_dirty_cpu_schedulers);
+
if (dirty_only) {
- if (no > schdlr_sspnd.online) {
- erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
- return ERTS_SCHDLR_SSPND_EINVAL;
+ if (no > online) {
+ res = ERTS_SCHDLR_SSPND_EINVAL;
+ goto done;
}
dirty_no = no;
+ if (dirty_no == dirty_online) {
+ res = ERTS_SCHDLR_SSPND_DONE;
+ goto done;
+ }
+ change_dirty = 1;
} else {
/*
* Adjust the number of dirty CPU schedulers online relative to the
* adjustment made to the number of normal schedulers online.
*/
int total_pct = erts_no_dirty_cpu_schedulers*100/erts_no_schedulers;
- int onln_pct = no*total_pct/schdlr_sspnd.online;
- dirty_no = schdlr_sspnd.dirty_cpu_online*onln_pct/100;
+ int onln_pct = no*total_pct/online;
+ dirty_no = dirty_online*onln_pct/100;
if (dirty_no == 0)
dirty_no = 1;
ASSERT(dirty_no <= erts_no_dirty_cpu_schedulers);
- }
-#endif
- changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
-#ifdef ERTS_DIRTY_SCHEDULERS
- changing |= erts_smp_atomic32_read_nob(&schdlr_sspnd.dirty_cpu_changing);
-#endif
- if (changing) {
- res = ERTS_SCHDLR_SSPND_YIELD_RESTART;
- }
- else {
- int online = *old_no = schdlr_sspnd.online;
-#ifdef ERTS_DIRTY_SCHEDULERS
- int dirty_online = schdlr_sspnd.dirty_cpu_online;
- if (dirty_only) {
- *old_no = schdlr_sspnd.dirty_cpu_online;
- if (dirty_no == schdlr_sspnd.dirty_cpu_online) {
+ if (no != online)
+ change_dirty = (dirty_no != dirty_online);
+ else {
+ dirty_only = 1;
+ if (dirty_no == dirty_online) {
res = ERTS_SCHDLR_SSPND_DONE;
+ goto done;
}
change_dirty = 1;
- } else {
-#endif
- if (no == schdlr_sspnd.online) {
-#ifdef ERTS_DIRTY_SCHEDULERS
- dirty_only = 1;
- if (dirty_no == schdlr_sspnd.dirty_cpu_online)
-#endif
- res = ERTS_SCHDLR_SSPND_DONE;
-#ifdef ERTS_DIRTY_SCHEDULERS
- else
- change_dirty = 1;
-#endif
- }
-#ifdef ERTS_DIRTY_SCHEDULERS
- else
- change_dirty = (dirty_no != schdlr_sspnd.dirty_cpu_online);
}
-#endif
- if (res == -1)
- {
- int increase = (no > online);
-#ifdef ERTS_DIRTY_SCHEDULERS
- if (!dirty_only) {
-#endif
- ERTS_SCHDLR_SSPND_CHNG_SET((ERTS_SCHDLR_SSPND_CHNG_ONLN
- | ERTS_SCHDLR_SSPND_CHNG_WAITER), 0);
- schdlr_sspnd.online = no;
-#ifdef ERTS_DIRTY_SCHEDULERS
- } else
- increase = (dirty_no > dirty_online);
- if (change_dirty) {
- ERTS_SCHDLR_SSPND_DIRTY_CPU_CHNG_SET((ERTS_SCHDLR_SSPND_CHNG_ONLN
- | ERTS_SCHDLR_SSPND_CHNG_WAITER), 0);
- schdlr_sspnd.dirty_cpu_online = dirty_no;
- }
-#endif
- if (increase) {
- int ix;
-#ifdef ERTS_DIRTY_SCHEDULERS
- if (!dirty_only) {
-#endif
- schdlr_sspnd.wait_curr_online = no;
- if (ongoing_multi_scheduling_block()) {
- for (ix = online; ix < no; ix++)
- erts_sched_poke(ERTS_SCHED_SLEEP_INFO_IX(ix));
- }
- else {
- if (plocks) {
- have_unlocked_plocks = 1;
- erts_smp_proc_unlock(p, plocks);
- }
- change_no_used_runqs(no);
+ }
+ if (change_dirty) {
+ change_flags |= ERTS_SCHDLR_SSPND_CHNG_DCPU_ONLN;
+ schdlr_sspnd_set_nscheds(&schdlr_sspnd.online,
+ ERTS_SCHED_DIRTY_CPU,
+ dirty_no);
+ }
- for (ix = online; ix < no; ix++)
- resume_run_queue(ERTS_RUNQ_IX(ix));
+ if (dirty_only)
+ increase = (dirty_no > dirty_online);
+ else
+#endif /* ERTS_DIRTY_SCHEDULERS */
+ {
+ change_flags |= ERTS_SCHDLR_SSPND_CHNG_ONLN;
+ schdlr_sspnd_set_nscheds(&schdlr_sspnd.online,
+ ERTS_SCHED_NORMAL,
+ no);
+ increase = (no > online);
+ }
- for (ix = no; ix < erts_no_run_queues; ix++)
- suspend_run_queue(ERTS_RUNQ_IX(ix));
- }
+ erts_smp_atomic32_read_bor_nob(&schdlr_sspnd.changing, change_flags);
+
+ res = ERTS_SCHDLR_SSPND_DONE;
+ if (increase) {
+ int ix;
#ifdef ERTS_DIRTY_SCHEDULERS
+ if (change_dirty) {
+ ErtsSchedulerSleepInfo* ssi;
+ if (schdlr_sspnd.msb.ongoing) {
+ for (ix = dirty_online; ix < dirty_no; ix++) {
+ ssi = ERTS_DIRTY_CPU_SCHED_SLEEP_INFO_IX(ix);
+ erts_sched_poke(ssi);
}
- if (change_dirty) {
- schdlr_sspnd.dirty_cpu_wait_curr_online = dirty_no;
- ASSERT(schdlr_sspnd.dirty_cpu_curr_online !=
- schdlr_sspnd.dirty_cpu_wait_curr_online);
- if (ongoing_multi_scheduling_block()) {
- for (ix = dirty_online; ix < dirty_no; ix++) {
- ssi = ERTS_DIRTY_CPU_SCHED_SLEEP_INFO_IX(ix);
- erts_sched_poke(ssi);
- }
- } else {
- for (ix = dirty_online; ix < dirty_no; ix++) {
- ssi = ERTS_DIRTY_CPU_SCHED_SLEEP_INFO_IX(ix);
- scheduler_ssi_resume_wake(ssi);
- erts_smp_atomic32_read_band_nob(&ssi->flags,
- ~ERTS_SSI_FLG_SUSPENDED);
- }
- wake_dirty_schedulers(ERTS_DIRTY_CPU_RUNQ, 0);
- }
+ } else {
+ for (ix = dirty_online; ix < dirty_no; ix++) {
+ ssi = ERTS_DIRTY_CPU_SCHED_SLEEP_INFO_IX(ix);
+ scheduler_ssi_resume_wake(ssi);
}
-#endif
- res = ERTS_SCHDLR_SSPND_DONE;
}
- else /* if (no < online) */ {
-#ifdef ERTS_DIRTY_SCHEDULERS
- if (change_dirty) {
- schdlr_sspnd.dirty_cpu_wait_curr_online = dirty_no;
- ASSERT(schdlr_sspnd.dirty_cpu_curr_online !=
- schdlr_sspnd.dirty_cpu_wait_curr_online);
- if (ongoing_multi_scheduling_block()) {
- for (ix = dirty_no; ix < dirty_online; ix++) {
- ssi = ERTS_DIRTY_CPU_SCHED_SLEEP_INFO_IX(ix);
- erts_sched_poke(ssi);
- }
- } else {
- for (ix = dirty_no; ix < dirty_online; ix++) {
- ssi = ERTS_DIRTY_CPU_SCHED_SLEEP_INFO_IX(ix);
- erts_smp_atomic32_read_bor_nob(&ssi->flags,
- ERTS_SSI_FLG_SUSPENDED);
- }
- wake_dirty_schedulers(ERTS_DIRTY_CPU_RUNQ, 0);
- }
- }
- if (dirty_only) {
- res = ERTS_SCHDLR_SSPND_DONE;
- }
- else
+ }
+ if (!dirty_only)
#endif
- {
- if (p->scheduler_data->no <= no) {
- res = ERTS_SCHDLR_SSPND_DONE;
- schdlr_sspnd.wait_curr_online = no;
- }
- else {
- /*
- * Yield! Current process needs to migrate
- * before bif returns.
- */
- res = ERTS_SCHDLR_SSPND_YIELD_DONE;
- schdlr_sspnd.wait_curr_online = no+1;
- }
-
- if (ongoing_multi_scheduling_block()) {
- for (ix = no; ix < online; ix++)
- erts_sched_poke(ERTS_SCHED_SLEEP_INFO_IX(ix));
- }
- else {
- if (plocks) {
- have_unlocked_plocks = 1;
- erts_smp_proc_unlock(p, plocks);
- }
-
- change_no_used_runqs(no);
- for (ix = no; ix < erts_no_run_queues; ix++)
- suspend_run_queue(ERTS_RUNQ_IX(ix));
-
- for (ix = no; ix < online; ix++) {
- ErtsRunQueue *rq = ERTS_RUNQ_IX(ix);
- wake_scheduler(rq);
- }
- }
- }
+ {
+ if (schdlr_sspnd.msb.ongoing|schdlr_sspnd.nmsb.ongoing) {
+ for (ix = online; ix < no; ix++)
+ erts_sched_poke(ERTS_SCHED_SLEEP_INFO_IX(ix));
}
-
-#ifdef ERTS_DIRTY_SCHEDULERS
- if (change_dirty) {
- while (schdlr_sspnd.dirty_cpu_curr_online != schdlr_sspnd.dirty_cpu_wait_curr_online)
- erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
- ERTS_SCHDLR_SSPND_DIRTY_CPU_CHNG_SET(0, ERTS_SCHDLR_SSPND_CHNG_WAITER);
- erts_smp_atomic32_read_band_nob(&schdlr_sspnd.dirty_cpu_changing,
- ~ERTS_SCHDLR_SSPND_CHNG_WAITER);
- }
- if (!dirty_only)
-#endif
- {
- if (schdlr_sspnd.curr_online != schdlr_sspnd.wait_curr_online) {
- erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
- if (plocks && !have_unlocked_plocks) {
- have_unlocked_plocks = 1;
- erts_smp_proc_unlock(p, plocks);
- }
- erts_thr_progress_active(esdp, 0);
- erts_thr_progress_prepare_wait(esdp);
- end_wait = 1;
- erts_smp_mtx_lock(&schdlr_sspnd.mtx);
+ else {
+ if (plocks) {
+ have_unlocked_plocks = 1;
+ erts_smp_proc_unlock(p, plocks);
}
+ change_no_used_runqs(no);
- while (schdlr_sspnd.curr_online != schdlr_sspnd.wait_curr_online)
- erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
+ for (ix = online; ix < no; ix++)
+ resume_run_queue(ERTS_RUNQ_IX(ix));
- ASSERT(res != ERTS_SCHDLR_SSPND_DONE
- ? (ERTS_SCHDLR_SSPND_CHNG_WAITER
- & erts_smp_atomic32_read_nob(&schdlr_sspnd.changing))
- : (ERTS_SCHDLR_SSPND_CHNG_WAITER
- == erts_smp_atomic32_read_nob(&schdlr_sspnd.changing)));
- erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
- ~ERTS_SCHDLR_SSPND_CHNG_WAITER);
+ for (ix = no; ix < erts_no_run_queues; ix++)
+ suspend_run_queue(ERTS_RUNQ_IX(ix));
}
}
}
-
- erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+ else /* if decrease */ {
#ifdef ERTS_DIRTY_SCHEDULERS
- ASSERT(schdlr_sspnd.dirty_cpu_online <= schdlr_sspnd.online);
- if (!dirty_only)
-#endif
- {
- if (end_wait) {
- erts_thr_progress_finalize_wait(esdp);
- erts_thr_progress_active(esdp, 1);
- }
- if (have_unlocked_plocks)
- erts_smp_proc_lock(p, plocks);
- }
-
- return res;
-}
-
-#else /* !ERTS_DIRTY_SCHEDULERS */
-
-ErtsSchedSuspendResult
-erts_set_schedulers_online(Process *p,
- ErtsProcLocks plocks,
- Sint new_no,
- Sint *old_no)
-{
- ErtsSchedulerData *esdp;
- int ix, res, no, have_unlocked_plocks, end_wait;
- erts_aint32_t changing;
-
- if (new_no < 1 || erts_no_schedulers < new_no)
- return ERTS_SCHDLR_SSPND_EINVAL;
-
- esdp = ERTS_PROC_GET_SCHDATA(p);
- end_wait = 0;
-
- erts_smp_mtx_lock(&schdlr_sspnd.mtx);
-
- have_unlocked_plocks = 0;
- no = (int) new_no;
-
- changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
- if (changing) {
- res = ERTS_SCHDLR_SSPND_YIELD_RESTART;
- }
- else {
- int online = *old_no = schdlr_sspnd.online;
- if (no == schdlr_sspnd.online) {
- res = ERTS_SCHDLR_SSPND_DONE;
- }
- else {
- ERTS_SCHDLR_SSPND_CHNG_SET((ERTS_SCHDLR_SSPND_CHNG_ONLN
- | ERTS_SCHDLR_SSPND_CHNG_WAITER), 0);
- schdlr_sspnd.online = no;
- if (no > online) {
- int ix;
- schdlr_sspnd.wait_curr_online = no;
- if (ongoing_multi_scheduling_block()) {
- for (ix = online; ix < no; ix++)
- erts_sched_poke(ERTS_SCHED_SLEEP_INFO_IX(ix));
+ if (change_dirty) {
+ ErtsSchedulerSleepInfo* ssi;
+ if (schdlr_sspnd.msb.ongoing) {
+ for (ix = dirty_no; ix < dirty_online; ix++) {
+ ssi = ERTS_DIRTY_CPU_SCHED_SLEEP_INFO_IX(ix);
+ erts_sched_poke(ssi);
}
- else {
- if (plocks) {
- have_unlocked_plocks = 1;
- erts_smp_proc_unlock(p, plocks);
- }
- change_no_used_runqs(no);
-
- for (ix = online; ix < no; ix++)
- resume_run_queue(ERTS_RUNQ_IX(ix));
-
- for (ix = no; ix < erts_no_run_queues; ix++)
- suspend_run_queue(ERTS_RUNQ_IX(ix));
+ } else {
+ for (ix = dirty_no; ix < dirty_online; ix++) {
+ ssi = ERTS_DIRTY_CPU_SCHED_SLEEP_INFO_IX(ix);
+ erts_smp_atomic32_read_bor_nob(&ssi->flags,
+ ERTS_SSI_FLG_SUSPENDED);
}
- res = ERTS_SCHDLR_SSPND_DONE;
+ wake_dirty_schedulers(ERTS_DIRTY_CPU_RUNQ, 0);
}
- else /* if (no < online) */ {
- if (p->scheduler_data->no <= no) {
- res = ERTS_SCHDLR_SSPND_DONE;
- schdlr_sspnd.wait_curr_online = no;
- }
- else {
- /*
- * Yield! Current process needs to migrate
- * before bif returns.
- */
- res = ERTS_SCHDLR_SSPND_YIELD_DONE;
- schdlr_sspnd.wait_curr_online = no+1;
- }
-
- if (ongoing_multi_scheduling_block()) {
- for (ix = no; ix < online; ix++)
- erts_sched_poke(ERTS_SCHED_SLEEP_INFO_IX(ix));
- }
- else {
- if (plocks) {
- have_unlocked_plocks = 1;
- erts_smp_proc_unlock(p, plocks);
- }
-
- change_no_used_runqs(no);
- for (ix = no; ix < erts_no_run_queues; ix++)
- suspend_run_queue(ERTS_RUNQ_IX(ix));
-
- for (ix = no; ix < online; ix++) {
- ErtsRunQueue *rq = ERTS_RUNQ_IX(ix);
- wake_scheduler(rq);
- }
- }
+ }
+ if (!dirty_only)
+#endif
+ {
+ if (schdlr_sspnd.msb.ongoing|schdlr_sspnd.nmsb.ongoing) {
+ for (ix = no; ix < online; ix++)
+ erts_sched_poke(ERTS_SCHED_SLEEP_INFO_IX(ix));
}
-
- if (schdlr_sspnd.curr_online != schdlr_sspnd.wait_curr_online) {
- erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
- if (plocks && !have_unlocked_plocks) {
+ else {
+ if (plocks) {
have_unlocked_plocks = 1;
erts_smp_proc_unlock(p, plocks);
}
- erts_thr_progress_active(esdp, 0);
- erts_thr_progress_prepare_wait(esdp);
- end_wait = 1;
- erts_smp_mtx_lock(&schdlr_sspnd.mtx);
- }
- while (schdlr_sspnd.curr_online != schdlr_sspnd.wait_curr_online)
- erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
-
- ASSERT(res != ERTS_SCHDLR_SSPND_DONE
- ? (ERTS_SCHDLR_SSPND_CHNG_WAITER
- & erts_smp_atomic32_read_nob(&schdlr_sspnd.changing))
- : (ERTS_SCHDLR_SSPND_CHNG_WAITER
- == erts_smp_atomic32_read_nob(&schdlr_sspnd.changing)));
- erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
- ~ERTS_SCHDLR_SSPND_CHNG_WAITER);
+ change_no_used_runqs(no);
+ for (ix = no; ix < erts_no_run_queues; ix++)
+ suspend_run_queue(ERTS_RUNQ_IX(ix));
+ for (ix = no; ix < online; ix++) {
+ ErtsRunQueue *rq = ERTS_RUNQ_IX(ix);
+ wake_scheduler(rq);
+ }
+ }
}
}
- erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
- if (end_wait) {
- erts_thr_progress_finalize_wait(esdp);
- erts_thr_progress_active(esdp, 1);
+ if (change_flags & ERTS_SCHDLR_SSPND_CHNG_ONLN) {
+ /* Suspend and wait for requested change to complete... */
+ schdlr_sspnd.changer = p->common.id;
+ resume_proc = 0;
+ res = ERTS_SCHDLR_SSPND_YIELD_DONE;
}
+
+done:
+
+ ASSERT(schdlr_sspnd_get_nscheds(&schdlr_sspnd.online,
+ ERTS_SCHED_DIRTY_CPU)
+ <= schdlr_sspnd_get_nscheds(&schdlr_sspnd.online,
+ ERTS_SCHED_NORMAL));
+
+ erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+
if (have_unlocked_plocks)
erts_smp_proc_lock(p, plocks);
+ if (resume_proc) {
+ if (!(plocks & ERTS_PROC_LOCK_STATUS))
+ erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
+ resume_process(p, plocks|ERTS_PROC_LOCK_STATUS);
+ if (!(plocks & ERTS_PROC_LOCK_STATUS))
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+ }
+
return res;
}
-#endif
-
ErtsSchedSuspendResult
-erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all)
+erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int normal, int all)
{
- int ix, res, have_unlocked_plocks = 0, online;
- erts_aint32_t changing;
+ int resume_proc, ix, res, have_unlocked_plocks = 0;
ErtsProcList *plp;
#ifdef ERTS_DIRTY_SCHEDULERS
ErtsSchedulerSleepInfo* ssi;
#endif
+ ErtsMultiSchedulingBlock *msbp;
+ erts_aint32_t chng_flg;
+ int have_blckd_flg;
- erts_smp_mtx_lock(&schdlr_sspnd.mtx);
- changing = erts_smp_atomic32_read_nob(&schdlr_sspnd.changing);
-#ifdef ERTS_DIRTY_SCHEDULERS
- changing |= (erts_smp_atomic32_read_nob(&schdlr_sspnd.dirty_cpu_changing)
- | erts_smp_atomic32_read_nob(&schdlr_sspnd.dirty_io_changing));
-#endif
- if (changing) {
- res = ERTS_SCHDLR_SSPND_YIELD_RESTART; /* Yield */
+ if (normal) {
+ chng_flg = ERTS_SCHDLR_SSPND_CHNG_NMSB;
+ have_blckd_flg = F_HAVE_BLCKD_NMSCHED;
+ msbp = &schdlr_sspnd.nmsb;
+ }
+ else {
+ chng_flg = ERTS_SCHDLR_SSPND_CHNG_MSB;
+ have_blckd_flg = F_HAVE_BLCKD_MSCHED;
+ msbp = &schdlr_sspnd.msb;
}
- else if (on) { /* ------ BLOCK ------ */
- if (schdlr_sspnd.msb.procs) {
+
+ /*
+ * If we suspend current process we need to suspend before
+ * requesting the change; otherwise, we got a resume/suspend
+ * race...
+ */
+ if (!on) {
+ /* We never suspend current process when unblocking... */
+ resume_proc = 0;
+ }
+ else {
+ resume_proc = 1;
+ if (!(plocks & ERTS_PROC_LOCK_STATUS))
+ erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
+ suspend_process(p, p);
+ if (!(plocks & ERTS_PROC_LOCK_STATUS))
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+ }
+
+ erts_smp_mtx_lock(&schdlr_sspnd.mtx);
+ if (on) { /* ------ BLOCK ------ */
+ if (msbp->chngq) {
+ ASSERT(msbp->ongoing);
+ p->flags |= have_blckd_flg;
+ goto wait_until_msb;
+ }
+ else if (msbp->blckrs) {
+ ASSERT(msbp->ongoing);
plp = proclist_create(p);
- erts_proclist_store_last(&schdlr_sspnd.msb.procs, plp);
- p->flags |= F_HAVE_BLCKD_MSCHED;
- ASSERT(erts_smp_atomic32_read_nob(&schdlr_sspnd.active) == 1);
-#ifdef ERTS_DIRTY_SCHEDULERS
- ASSERT(erts_smp_atomic32_read_nob(&schdlr_sspnd.dirty_cpu_active) == 0);
- ASSERT(erts_smp_atomic32_read_nob(&schdlr_sspnd.dirty_io_active) == 0);
-#endif
+ erts_proclist_store_last(&msbp->blckrs, plp);
+ p->flags |= have_blckd_flg;
+ ASSERT(schdlr_sspnd.active == ERTS_SCHDLR_SSPND_MAKE_NSCHEDS_VAL(1, 0, 0));
ASSERT(p->scheduler_data->no == 1);
- res = ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED;
- } else {
- int online = schdlr_sspnd.online;
- p->flags |= F_HAVE_BLCKD_MSCHED;
+ if (schdlr_sspnd.msb.ongoing)
+ res = ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED;
+ else
+ res = ERTS_SCHDLR_SSPND_DONE_NMSCHED_BLOCKED;
+ }
+ else {
+ int online = (int) schdlr_sspnd_get_nscheds(&schdlr_sspnd.online,
+ ERTS_SCHED_NORMAL);
+ ASSERT(!msbp->ongoing);
+ p->flags |= have_blckd_flg;
if (plocks) {
have_unlocked_plocks = 1;
erts_smp_proc_unlock(p, plocks);
}
- ASSERT(!ongoing_multi_scheduling_block());
- schdlr_sspnd.msb.ongoing = 1;
- if (online == 1) {
- res = ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED;
- ASSERT(erts_smp_atomic32_read_nob(&schdlr_sspnd.active) == 1);
-#ifdef ERTS_DIRTY_SCHEDULERS
- ASSERT(erts_smp_atomic32_read_nob(&schdlr_sspnd.dirty_cpu_active) == 1);
- ASSERT(!(erts_smp_atomic32_read_nob(&ERTS_DIRTY_CPU_SCHED_SLEEP_INFO_IX(0)->flags)
- & ERTS_SSI_FLG_SUSPENDED));
- schdlr_sspnd.msb.dirty_cpu_wait_active = 0;
- ERTS_SCHDLR_SSPND_DIRTY_CPU_CHNG_SET((ERTS_SCHDLR_SSPND_CHNG_MSB
- | ERTS_SCHDLR_SSPND_CHNG_WAITER), 0);
- ssi = ERTS_DIRTY_CPU_SCHED_SLEEP_INFO_IX(0);
- erts_smp_atomic32_read_bor_nob(&ssi->flags, ERTS_SSI_FLG_SUSPENDED);
- wake_dirty_schedulers(ERTS_DIRTY_CPU_RUNQ, 0);
- while (erts_smp_atomic32_read_nob(&schdlr_sspnd.dirty_cpu_active)
- != schdlr_sspnd.msb.dirty_cpu_wait_active)
- erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
- ERTS_SCHDLR_SSPND_DIRTY_CPU_CHNG_SET(0, ERTS_SCHDLR_SSPND_CHNG_WAITER);
-
- schdlr_sspnd.msb.dirty_io_wait_active = 0;
- ERTS_SCHDLR_SSPND_DIRTY_IO_CHNG_SET((ERTS_SCHDLR_SSPND_CHNG_MSB
- | ERTS_SCHDLR_SSPND_CHNG_WAITER), 0);
- for (ix = 0; ix < erts_no_dirty_io_schedulers; ix++) {
- ssi = ERTS_DIRTY_IO_SCHED_SLEEP_INFO_IX(ix);
- erts_smp_atomic32_read_bor_nob(&ssi->flags,
- ERTS_SSI_FLG_SUSPENDED);
- }
- wake_dirty_schedulers(ERTS_DIRTY_IO_RUNQ, 0);
- while (erts_smp_atomic32_read_nob(&schdlr_sspnd.dirty_io_active)
- != schdlr_sspnd.msb.dirty_io_wait_active)
- erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
- ERTS_SCHDLR_SSPND_DIRTY_IO_CHNG_SET(0, ERTS_SCHDLR_SSPND_CHNG_WAITER);
-#endif
+ ASSERT(!msbp->ongoing);
+ msbp->ongoing = 1;
+ if (schdlr_sspnd.active == ERTS_SCHDLR_SSPND_MAKE_NSCHEDS_VAL(1, 0, 0)
+ || (normal && schdlr_sspnd_get_nscheds(&schdlr_sspnd.active,
+ ERTS_SCHED_NORMAL) == 1)) {
ASSERT(p->scheduler_data->no == 1);
+ plp = proclist_create(p);
+ erts_proclist_store_last(&msbp->blckrs, plp);
+ if (schdlr_sspnd.msb.ongoing)
+ res = ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED;
+ else
+ res = ERTS_SCHDLR_SSPND_DONE_NMSCHED_BLOCKED;
}
else {
- ERTS_SCHDLR_SSPND_CHNG_SET((ERTS_SCHDLR_SSPND_CHNG_MSB
- | ERTS_SCHDLR_SSPND_CHNG_WAITER), 0);
- if (p->scheduler_data->no == 1) {
- res = ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED;
- schdlr_sspnd.msb.wait_active = 1;
- }
- else {
- /*
- * Yield! Current process needs to migrate
- * before bif returns.
- */
- res = ERTS_SCHDLR_SSPND_YIELD_DONE_MSCHED_BLOCKED;
- schdlr_sspnd.msb.wait_active = 2;
- }
-
-#ifdef ERTS_DIRTY_SCHEDULERS
- schdlr_sspnd.msb.dirty_cpu_wait_active = 0;
- ERTS_SCHDLR_SSPND_DIRTY_CPU_CHNG_SET((ERTS_SCHDLR_SSPND_CHNG_MSB
- | ERTS_SCHDLR_SSPND_CHNG_WAITER), 0);
- for (ix = 0; ix < erts_no_dirty_cpu_schedulers; ix++) {
- ssi = ERTS_DIRTY_CPU_SCHED_SLEEP_INFO_IX(ix);
- erts_smp_atomic32_read_bor_nob(&ssi->flags,
- ERTS_SSI_FLG_SUSPENDED);
- }
- wake_dirty_schedulers(ERTS_DIRTY_CPU_RUNQ, 0);
- while (erts_smp_atomic32_read_nob(&schdlr_sspnd.dirty_cpu_active)
- != schdlr_sspnd.msb.dirty_cpu_wait_active)
- erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
- ERTS_SCHDLR_SSPND_DIRTY_CPU_CHNG_SET(0, ERTS_SCHDLR_SSPND_CHNG_WAITER);
- ASSERT(schdlr_sspnd.dirty_cpu_curr_online == schdlr_sspnd.dirty_cpu_online);
-
- schdlr_sspnd.msb.dirty_io_wait_active = 0;
- ERTS_SCHDLR_SSPND_DIRTY_IO_CHNG_SET((ERTS_SCHDLR_SSPND_CHNG_MSB
- | ERTS_SCHDLR_SSPND_CHNG_WAITER), 0);
- for (ix = 0; ix < erts_no_dirty_io_schedulers; ix++) {
- ssi = ERTS_DIRTY_IO_SCHED_SLEEP_INFO_IX(ix);
- erts_smp_atomic32_read_bor_nob(&ssi->flags,
- ERTS_SSI_FLG_SUSPENDED);
- }
- wake_dirty_schedulers(ERTS_DIRTY_IO_RUNQ, 0);
- while (erts_smp_atomic32_read_nob(&schdlr_sspnd.dirty_io_active)
- != schdlr_sspnd.msb.dirty_io_wait_active)
- erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
- ERTS_SCHDLR_SSPND_DIRTY_IO_CHNG_SET(0, ERTS_SCHDLR_SSPND_CHNG_WAITER);
- ASSERT(schdlr_sspnd.dirty_io_curr_online == schdlr_sspnd.dirty_io_online);
-#endif
+ erts_smp_atomic32_read_bor_nob(&schdlr_sspnd.changing,
+ chng_flg);
change_no_used_runqs(1);
for (ix = 1; ix < erts_no_run_queues; ix++)
suspend_run_queue(ERTS_RUNQ_IX(ix));
@@ -7839,84 +7819,84 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all)
wake_scheduler(rq);
}
- if (erts_smp_atomic32_read_nob(&schdlr_sspnd.active)
- != schdlr_sspnd.msb.wait_active) {
- ErtsSchedulerData *esdp;
-
- erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
-
- if (plocks && !have_unlocked_plocks) {
- have_unlocked_plocks = 1;
- erts_smp_proc_unlock(p, plocks);
+#ifdef ERTS_DIRTY_SCHEDULERS
+ if (!normal) {
+ for (ix = 0; ix < erts_no_dirty_cpu_schedulers; ix++) {
+ ssi = ERTS_DIRTY_CPU_SCHED_SLEEP_INFO_IX(ix);
+ erts_smp_atomic32_read_bor_nob(&ssi->flags,
+ ERTS_SSI_FLG_SUSPENDED);
}
+ wake_dirty_schedulers(ERTS_DIRTY_CPU_RUNQ, 0);
- esdp = ERTS_PROC_GET_SCHDATA(p);
-
- erts_thr_progress_active(esdp, 0);
- erts_thr_progress_prepare_wait(esdp);
-
- erts_smp_mtx_lock(&schdlr_sspnd.mtx);
-
- while (erts_smp_atomic32_read_nob(&schdlr_sspnd.active)
- != schdlr_sspnd.msb.wait_active)
- erts_smp_cnd_wait(&schdlr_sspnd.cnd,
- &schdlr_sspnd.mtx);
-
- erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
-
- erts_thr_progress_active(esdp, 1);
- erts_thr_progress_finalize_wait(esdp);
+ for (ix = 0; ix < erts_no_dirty_io_schedulers; ix++) {
+ ssi = ERTS_DIRTY_IO_SCHED_SLEEP_INFO_IX(ix);
+ erts_smp_atomic32_read_bor_nob(&ssi->flags,
+ ERTS_SSI_FLG_SUSPENDED);
+ }
+ wake_dirty_schedulers(ERTS_DIRTY_IO_RUNQ, 0);
+ }
+#endif
- erts_smp_mtx_lock(&schdlr_sspnd.mtx);
+ wait_until_msb:
- }
+ ASSERT(chng_flg & erts_smp_atomic32_read_nob(&schdlr_sspnd.changing));
- ASSERT(res != ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED
- ? (ERTS_SCHDLR_SSPND_CHNG_WAITER
- & erts_smp_atomic32_read_nob(&schdlr_sspnd.changing))
- : (ERTS_SCHDLR_SSPND_CHNG_WAITER
- == erts_smp_atomic32_read_nob(&schdlr_sspnd.changing)));
- erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
- ~ERTS_SCHDLR_SSPND_CHNG_WAITER);
+ plp = proclist_create(p);
+ erts_proclist_store_last(&msbp->chngq, plp);
+ resume_proc = 0;
+ if (schdlr_sspnd.msb.ongoing)
+ res = ERTS_SCHDLR_SSPND_YIELD_DONE_MSCHED_BLOCKED;
+ else
+ res = ERTS_SCHDLR_SSPND_YIELD_DONE_NMSCHED_BLOCKED;
}
- plp = proclist_create(p);
- erts_proclist_store_last(&schdlr_sspnd.msb.procs, plp);
ASSERT(p->scheduler_data);
}
}
- else if (!ongoing_multi_scheduling_block()) {
- /* unblock not ongoing */
- ASSERT(!schdlr_sspnd.msb.procs);
- res = ERTS_SCHDLR_SSPND_DONE;
+ else if (!msbp->ongoing) {
+ ASSERT(!msbp->blckrs);
+ goto unblock_res;
}
else { /* ------ UNBLOCK ------ */
- if (p->flags & F_HAVE_BLCKD_MSCHED) {
- ErtsProcList *plp = erts_proclist_peek_first(schdlr_sspnd.msb.procs);
-
- while (plp) {
- ErtsProcList *tmp_plp = plp;
- plp = erts_proclist_peek_next(schdlr_sspnd.msb.procs, plp);
- if (erts_proclist_same(tmp_plp, p)) {
- erts_proclist_remove(&schdlr_sspnd.msb.procs, tmp_plp);
- proclist_destroy(tmp_plp);
- if (!all)
- break;
+ if (p->flags & have_blckd_flg) {
+ ErtsProcList *plps[2];
+ ErtsProcList *plp;
+ int limit = 0;
+
+ plps[limit++] = erts_proclist_peek_first(msbp->blckrs);
+ if (all)
+ plps[limit++] = erts_proclist_peek_first(msbp->chngq);
+
+ for (ix = 0; ix < limit; ix++) {
+ plp = plps[ix];
+ while (plp) {
+ ErtsProcList *tmp_plp = plp;
+ plp = erts_proclist_peek_next(msbp->blckrs, plp);
+ if (erts_proclist_same(tmp_plp, p)) {
+ erts_proclist_remove(&msbp->blckrs, tmp_plp);
+ proclist_destroy(tmp_plp);
+ if (!all)
+ break;
+ }
}
}
}
- if (schdlr_sspnd.msb.procs)
- res = ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED;
- else {
- ERTS_SCHDLR_SSPND_CHNG_SET(ERTS_SCHDLR_SSPND_CHNG_MSB, 0);
- p->flags &= ~F_HAVE_BLCKD_MSCHED;
- schdlr_sspnd.msb.ongoing = 0;
- if (schdlr_sspnd.online == 1) {
+ if (!msbp->blckrs && !msbp->chngq) {
+ int online = (int) schdlr_sspnd_get_nscheds(&schdlr_sspnd.online,
+ ERTS_SCHED_NORMAL);
+ erts_smp_atomic32_read_bor_nob(&schdlr_sspnd.changing,
+ chng_flg);
+ p->flags &= ~have_blckd_flg;
+ msbp->ongoing = 0;
+ if (online == 1) {
/* No normal schedulers to resume */
- ASSERT(erts_smp_atomic32_read_nob(&schdlr_sspnd.active) == 1);
- ERTS_SCHDLR_SSPND_CHNG_SET(0, ERTS_SCHDLR_SSPND_CHNG_MSB);
+ ASSERT(schdlr_sspnd_get_nscheds(&schdlr_sspnd.active,
+ ERTS_SCHED_NORMAL) == 1);
+#ifndef ERTS_DIRTY_SCHEDULERS
+ erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
+ ~chng_flg);
+#endif
}
- else {
- online = schdlr_sspnd.online;
+ else if (!(schdlr_sspnd.msb.ongoing|schdlr_sspnd.nmsb.ongoing)) {
if (plocks) {
have_unlocked_plocks = 1;
erts_smp_proc_unlock(p, plocks);
@@ -7932,83 +7912,91 @@ erts_block_multi_scheduling(Process *p, ErtsProcLocks plocks, int on, int all)
suspend_run_queue(ERTS_RUNQ_IX(ix));
}
#ifdef ERTS_DIRTY_SCHEDULERS
- ERTS_SCHDLR_SSPND_DIRTY_CPU_CHNG_SET(ERTS_SCHDLR_SSPND_CHNG_MSB, 0);
- schdlr_sspnd.msb.dirty_cpu_wait_active = schdlr_sspnd.dirty_cpu_online;
- for (ix = 0; ix < schdlr_sspnd.dirty_cpu_online; ix++) {
- ssi = ERTS_DIRTY_CPU_SCHED_SLEEP_INFO_IX(ix);
- scheduler_ssi_resume_wake(ssi);
- erts_smp_atomic32_read_band_nob(&ssi->flags,
- ~ERTS_SSI_FLG_SUSPENDED);
- }
- wake_dirty_schedulers(ERTS_DIRTY_CPU_RUNQ, 0);
-
- ERTS_SCHDLR_SSPND_DIRTY_IO_CHNG_SET(ERTS_SCHDLR_SSPND_CHNG_MSB, 0);
- schdlr_sspnd.msb.dirty_io_wait_active = erts_no_dirty_io_schedulers;
- for (ix = 0; ix < erts_no_dirty_io_schedulers; ix++) {
- ssi = ERTS_DIRTY_IO_SCHED_SLEEP_INFO_IX(ix);
- scheduler_ssi_resume_wake(ssi);
- erts_smp_atomic32_read_band_nob(&ssi->flags,
- ~ERTS_SSI_FLG_SUSPENDED);
- }
- wake_dirty_schedulers(ERTS_DIRTY_IO_RUNQ, 0);
+ if (!normal) {
+ ASSERT(!schdlr_sspnd.msb.ongoing);
+ online = (int) schdlr_sspnd_get_nscheds(&schdlr_sspnd.online,
+ ERTS_SCHED_DIRTY_CPU);
+ for (ix = 0; ix < online; ix++) {
+ ssi = ERTS_DIRTY_CPU_SCHED_SLEEP_INFO_IX(ix);
+ scheduler_ssi_resume_wake(ssi);
+ }
+
+ for (ix = 0; ix < erts_no_dirty_io_schedulers; ix++) {
+ ssi = ERTS_DIRTY_IO_SCHED_SLEEP_INFO_IX(ix);
+ scheduler_ssi_resume_wake(ssi);
+ }
+ }
#endif
- res = ERTS_SCHDLR_SSPND_DONE;
}
+
+ unblock_res:
+ if (schdlr_sspnd.msb.ongoing)
+ res = ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED;
+ else if (schdlr_sspnd.nmsb.ongoing)
+ res = ERTS_SCHDLR_SSPND_DONE_NMSCHED_BLOCKED;
+ else
+ res = ERTS_SCHDLR_SSPND_DONE;
}
erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
+
if (have_unlocked_plocks)
erts_smp_proc_lock(p, plocks);
- return res;
-}
-#ifdef DEBUG
-void
-erts_dbg_multi_scheduling_return_trap(Process *p, Eterm return_value)
-{
- if (return_value == am_blocked) {
- erts_aint32_t active = erts_smp_atomic32_read_nob(&schdlr_sspnd.active);
- ASSERT(1 <= active && active <= 2);
- ASSERT(ERTS_PROC_GET_SCHDATA(p)->no == 1);
+ if (resume_proc) {
+ if (!(plocks & ERTS_PROC_LOCK_STATUS))
+ erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
+ resume_process(p, plocks|ERTS_PROC_LOCK_STATUS);
+ if (!(plocks & ERTS_PROC_LOCK_STATUS))
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
}
+
+ return res;
}
-#endif
int
erts_is_multi_scheduling_blocked(void)
{
int res;
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
- res = schdlr_sspnd.msb.procs != NULL;
+ if (schdlr_sspnd.msb.blckrs)
+ res = 1;
+ else if (schdlr_sspnd.nmsb.blckrs)
+ res = -1;
+ else
+ res = 0;
erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
return res;
}
Eterm
-erts_multi_scheduling_blockers(Process *p)
+erts_multi_scheduling_blockers(Process *p, int normal)
{
Eterm res = NIL;
+ ErtsMultiSchedulingBlock *msbp;
+
+ msbp = normal ? &schdlr_sspnd.nmsb : &schdlr_sspnd.msb;
erts_smp_mtx_lock(&schdlr_sspnd.mtx);
- if (!erts_proclist_is_empty(schdlr_sspnd.msb.procs)) {
+ if (!erts_proclist_is_empty(msbp->blckrs)) {
Eterm *hp, *hp_end;
ErtsProcList *plp1, *plp2;
Uint max_size = 0;
- for (plp1 = erts_proclist_peek_first(schdlr_sspnd.msb.procs);
+ for (plp1 = erts_proclist_peek_first(msbp->blckrs);
plp1;
- plp1 = erts_proclist_peek_next(schdlr_sspnd.msb.procs, plp1)) {
+ plp1 = erts_proclist_peek_next(msbp->blckrs, plp1)) {
max_size += 2;
}
ASSERT(max_size);
hp = HAlloc(p, max_size);
hp_end = hp + max_size;
- for (plp1 = erts_proclist_peek_first(schdlr_sspnd.msb.procs);
+ for (plp1 = erts_proclist_peek_first(msbp->blckrs);
plp1;
- plp1 = erts_proclist_peek_next(schdlr_sspnd.msb.procs, plp1)) {
- for (plp2 = erts_proclist_peek_first(schdlr_sspnd.msb.procs);
+ plp1 = erts_proclist_peek_next(msbp->blckrs, plp1)) {
+ for (plp2 = erts_proclist_peek_first(msbp->blckrs);
plp2->pid != plp1->pid;
- plp2 = erts_proclist_peek_next(schdlr_sspnd.msb.procs, plp2));
+ plp2 = erts_proclist_peek_next(msbp->blckrs, plp2));
if (plp2 == plp1) {
res = CONS(hp, plp1->pid, res);
hp += 2;
@@ -8046,6 +8034,8 @@ sched_thread_func(void *vesdp)
callbacks.wait = thr_prgr_wait;
callbacks.finalize_wait = thr_prgr_fin_wait;
+ erts_msacc_init_thread("scheduler", no, 1);
+
erts_thr_progress_register_managed_thread(esdp, &callbacks, 0);
erts_alloc_register_scheduler(vesdp);
#endif
@@ -8075,39 +8065,6 @@ sched_thread_func(void *vesdp)
#endif
erts_thread_init_float();
- if (no == 1) {
- erts_thr_progress_active(esdp, 0);
- erts_thr_progress_prepare_wait(esdp);
- }
-
- erts_smp_mtx_lock(&schdlr_sspnd.mtx);
-
- ASSERT(erts_smp_atomic32_read_nob(&schdlr_sspnd.changing)
- & ERTS_SCHDLR_SSPND_CHNG_ONLN);
-
- if (--schdlr_sspnd.curr_online == schdlr_sspnd.wait_curr_online) {
- erts_smp_atomic32_read_band_nob(&schdlr_sspnd.changing,
- ~ERTS_SCHDLR_SSPND_CHNG_ONLN);
- if (no != 1)
-#ifdef ERTS_DIRTY_SCHEDULERS
- erts_smp_cnd_broadcast(&schdlr_sspnd.cnd);
-#else
- erts_smp_cnd_signal(&schdlr_sspnd.cnd);
-#endif
- }
-
- if (no == 1) {
- while (schdlr_sspnd.curr_online != schdlr_sspnd.wait_curr_online)
- erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
- ERTS_SCHDLR_SSPND_CHNG_SET(0, ERTS_SCHDLR_SSPND_CHNG_WAITER);
- }
- erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
-
- if (no == 1) {
- erts_thr_progress_finalize_wait(esdp);
- erts_thr_progress_active(esdp, 1);
- }
-
#ifdef ERTS_DO_VERIFY_UNUSED_TEMP_ALLOC
esdp->verify_unused_temp_alloc
= erts_alloc_get_verify_unused_temp_alloc(
@@ -8162,24 +8119,6 @@ sched_dirty_cpu_thread_func(void *vesdp)
#endif
erts_thread_init_float();
- erts_smp_mtx_lock(&schdlr_sspnd.mtx);
- ASSERT(erts_smp_atomic32_read_nob(&schdlr_sspnd.dirty_cpu_changing)
- & ERTS_SCHDLR_SSPND_CHNG_ONLN);
-
- if (--schdlr_sspnd.dirty_cpu_curr_online == schdlr_sspnd.dirty_cpu_wait_curr_online) {
- erts_smp_atomic32_read_band_nob(&schdlr_sspnd.dirty_cpu_changing,
- ~ERTS_SCHDLR_SSPND_CHNG_ONLN);
- if (no != 1)
- erts_smp_cnd_broadcast(&schdlr_sspnd.cnd);
- }
-
- if (no == 1) {
- while (schdlr_sspnd.dirty_cpu_curr_online != schdlr_sspnd.dirty_cpu_wait_curr_online)
- erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
- ERTS_SCHDLR_SSPND_DIRTY_CPU_CHNG_SET(0, ERTS_SCHDLR_SSPND_CHNG_WAITER);
- }
- erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
-
process_main();
/* No schedulers should *ever* terminate */
erts_exit(ERTS_ABORT_EXIT,
@@ -8225,24 +8164,6 @@ sched_dirty_io_thread_func(void *vesdp)
#endif
erts_thread_init_float();
- erts_smp_mtx_lock(&schdlr_sspnd.mtx);
- ASSERT(erts_smp_atomic32_read_nob(&schdlr_sspnd.dirty_io_changing)
- & ERTS_SCHDLR_SSPND_CHNG_ONLN);
-
- if (--schdlr_sspnd.dirty_io_curr_online == schdlr_sspnd.dirty_io_wait_curr_online) {
- erts_smp_atomic32_read_band_nob(&schdlr_sspnd.dirty_io_changing,
- ~ERTS_SCHDLR_SSPND_CHNG_ONLN);
- if (no != 1)
- erts_smp_cnd_broadcast(&schdlr_sspnd.cnd);
- }
-
- if (no == 1) {
- while (schdlr_sspnd.dirty_io_curr_online != schdlr_sspnd.dirty_io_wait_curr_online)
- erts_smp_cnd_wait(&schdlr_sspnd.cnd, &schdlr_sspnd.mtx);
- ERTS_SCHDLR_SSPND_DIRTY_IO_CHNG_SET(0, ERTS_SCHDLR_SSPND_CHNG_WAITER);
- }
- erts_smp_mtx_unlock(&schdlr_sspnd.mtx);
-
process_main();
/* No schedulers should *ever* terminate */
erts_exit(ERTS_ABORT_EXIT,
@@ -8301,18 +8222,12 @@ erts_start_schedulers(void)
erts_snprintf(opts.name, 16, "%lu_scheduler", actual + 1);
-#ifdef __OSE__
- /* This should be done in the bind strategy */
- opts.coreNo = (actual+1) % ose_num_cpus();
-#endif
-
res = ethr_thr_create(&esdp->tid, sched_thread_func, (void*)esdp, &opts);
if (res != 0) {
break;
}
}
-
erts_no_schedulers = actual;
#ifdef ERTS_DIRTY_SCHEDULERS
@@ -8341,10 +8256,6 @@ erts_start_schedulers(void)
erts_snprintf(opts.name, 16, "aux");
-#ifdef __OSE__
- opts.coreNo = 0;
-#endif /* __OSE__ */
-
res = ethr_thr_create(&aux_tid, aux_thread, NULL, &opts);
if (res != 0)
erts_exit(ERTS_ERROR_EXIT, "Failed to create aux thread\n");
@@ -8364,7 +8275,6 @@ erts_start_schedulers(void)
actual, actual == 1 ? " was" : "s were");
erts_send_error_to_logger_nogl(dsbufp);
}
-
}
#endif /* ERTS_SMP */
@@ -8383,7 +8293,7 @@ add_pend_suspend(Process *suspendee,
sizeof(ErtsPendingSuspend));
psp->next = NULL;
#ifdef DEBUG
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
psp->end = (ErtsPendingSuspend *) 0xdeaddeaddeaddead;
#else
psp->end = (ErtsPendingSuspend *) 0xdeaddead;
@@ -9378,6 +9288,8 @@ Process *schedule(Process *p, int calls)
Uint32 flags;
erts_aint32_t state = 0; /* Supress warning... */
+ ERTS_MSACC_DECLARE_CACHE();
+
#ifdef USE_VM_PROBES
if (p != NULL && DTRACE_ENABLED(process_unscheduled)) {
DTRACE_CHARBUF(process_buf, DTRACE_TERM_BUF_SIZE);
@@ -9412,6 +9324,8 @@ Process *schedule(Process *p, int calls)
} else {
sched_out_proc:
+ ASSERT(!(p->flags & F_DELAY_GC));
+
#ifdef ERTS_SMP
ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(p);
esdp = p->scheduler_data;
@@ -9480,6 +9394,8 @@ Process *schedule(Process *p, int calls)
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN|ERTS_PROC_LOCK_STATUS);
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_OTHER);
+
if (state & ERTS_PSFLG_FREE) {
#ifdef ERTS_SMP
ASSERT(esdp->free_process == p);
@@ -9516,15 +9432,16 @@ Process *schedule(Process *p, int calls)
#ifdef ERTS_SMP
ErtsMigrationPaths *mps;
ErtsMigrationPath *mp;
- ErtsProcList *pnd_xtrs = rq->procs.pending_exiters;
- if (erts_proclist_fetch(&pnd_xtrs, NULL)) {
- rq->procs.pending_exiters = NULL;
- erts_smp_runq_unlock(rq);
- handle_pending_exiters(pnd_xtrs);
- erts_smp_runq_lock(rq);
- }
if (!ERTS_SCHEDULER_IS_DIRTY(esdp)) {
+ ErtsProcList *pnd_xtrs = rq->procs.pending_exiters;
+ if (erts_proclist_fetch(&pnd_xtrs, NULL)) {
+ rq->procs.pending_exiters = NULL;
+ erts_smp_runq_unlock(rq);
+ handle_pending_exiters(pnd_xtrs);
+ erts_smp_runq_lock(rq);
+ }
+
if (rq->check_balance_reds <= 0)
check_balance(rq);
@@ -9568,12 +9485,10 @@ Process *schedule(Process *p, int calls)
erts_aint32_t aux_work;
int leader_update = erts_thr_progress_update(esdp);
aux_work = erts_atomic32_read_acqb(&esdp->ssi->aux_work);
- if (aux_work | leader_update | ERTS_SCHED_FAIR) {
+ if (aux_work | leader_update) {
erts_smp_runq_unlock(rq);
if (leader_update)
erts_thr_progress_leader_update(esdp);
- else if (ERTS_SCHED_FAIR)
- ERTS_SCHED_FAIR_YIELD();
if (aux_work)
handle_aux_work(&esdp->aux_work_data, aux_work, 0);
erts_smp_runq_lock(rq);
@@ -9642,7 +9557,7 @@ Process *schedule(Process *p, int calls)
scheduler_wait(&fcalls, esdp, rq);
flags = ERTS_RUNQ_FLGS_SET_NOB(rq, ERTS_RUNQ_FLG_EXEC);
flags |= ERTS_RUNQ_FLG_EXEC;
-
+ ERTS_MSACC_UPDATE_CACHE();
#ifdef ERTS_SMP
non_empty_runq(rq);
#endif
@@ -9651,12 +9566,14 @@ Process *schedule(Process *p, int calls)
}
else if (!ERTS_SCHEDULER_IS_DIRTY(esdp) &&
(fcalls > input_reductions &&
- prepare_for_sys_schedule(esdp, !0))) {
+ prepare_for_sys_schedule(!0))) {
ErtsMonotonicTime current_time;
/*
* Schedule system-level activities.
*/
+ ERTS_MSACC_PUSH_STATE_CACHED_M();
+
erts_smp_atomic32_set_relb(&function_calls, 0);
fcalls = 0;
@@ -9664,7 +9581,9 @@ Process *schedule(Process *p, int calls)
erts_sys_schedule_interrupt(0);
#endif
erts_smp_runq_unlock(rq);
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_CHECK_IO);
erl_sys_schedule(1);
+ ERTS_MSACC_POP_STATE_M();
current_time = erts_get_monotonic_time(esdp);
if (current_time >= erts_next_timeout_time(esdp->next_tmo_ref))
@@ -9722,11 +9641,12 @@ Process *schedule(Process *p, int calls)
pick_next_process: {
erts_aint32_t psflg_band_mask;
int prio_q;
- int qmask;
+ int qmask, qbit;
flags = ERTS_RUNQ_FLGS_GET_NOB(rq);
qmask = (int) (flags & ERTS_RUNQ_FLGS_PROCS_QMASK);
- switch (qmask & -qmask) {
+ qbit = qmask & -qmask;
+ switch (qbit) {
case MAX_BIT:
prio_q = PRIORITY_MAX;
break;
@@ -9742,9 +9662,12 @@ Process *schedule(Process *p, int calls)
case 0: /* No process at all */
default:
ASSERT(qmask == 0);
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_OTHER);
goto check_activities_to_run;
}
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_EMULATOR);
+
BM_START_TIMER(system);
/*
@@ -9754,20 +9677,11 @@ Process *schedule(Process *p, int calls)
ASSERT(p); /* Wrong qmask in rq->flags? */
- psflg_band_mask = ~(((erts_aint32_t) 1) << (ERTS_PSFLGS_GET_PRQ_PRIO(state)
- + ERTS_PSFLGS_IN_PRQ_MASK_OFFSET));
-
-#ifdef ERTS_DIRTY_SCHEDULERS
- ASSERT((state & (ERTS_PSFLG_DIRTY_CPU_PROC|ERTS_PSFLG_DIRTY_IO_PROC)) !=
- (ERTS_PSFLG_DIRTY_CPU_PROC|ERTS_PSFLG_DIRTY_IO_PROC));
- if (state & (ERTS_PSFLG_DIRTY_CPU_PROC|ERTS_PSFLG_DIRTY_IO_PROC)) {
- ASSERT((ERTS_SCHEDULER_IS_DIRTY_CPU(esdp) && (state & ERTS_PSFLG_DIRTY_CPU_PROC)) ||
- (ERTS_SCHEDULER_IS_DIRTY_IO(esdp) && (state & ERTS_PSFLG_DIRTY_IO_PROC)));
- if (!ERTS_SCHEDULER_IS_DIRTY(esdp) && !(state & ERTS_PSFLG_ACTIVE_SYS))
- goto pick_next_process;
- state &= ~(ERTS_PSFLG_DIRTY_CPU_PROC_IN_Q|ERTS_PSFLG_DIRTY_IO_PROC_IN_Q);
- }
-#endif
+ if (ERTS_SCHEDULER_IS_DIRTY(esdp))
+ psflg_band_mask = ~((erts_aint32_t) 0);
+ else
+ psflg_band_mask = ~(((erts_aint32_t) 1) << (ERTS_PSFLGS_GET_PRQ_PRIO(state)
+ + ERTS_PSFLGS_IN_PRQ_MASK_OFFSET));
if (!(state & ERTS_PSFLG_PROXY))
psflg_band_mask &= ~ERTS_PSFLG_IN_RUNQ;
@@ -9790,9 +9704,11 @@ Process *schedule(Process *p, int calls)
| ERTS_PSFLG_RUNNING_SYS))) {
tmp = state & (ERTS_PSFLG_SUSPENDED
| ERTS_PSFLG_PENDING_EXIT
- | ERTS_PSFLG_ACTIVE_SYS);
+ | ERTS_PSFLG_ACTIVE_SYS
+ | ERTS_PSFLG_DIRTY_ACTIVE_SYS);
if (tmp != ERTS_PSFLG_SUSPENDED) {
- if (state & ERTS_PSFLG_ACTIVE_SYS)
+ if (state & (ERTS_PSFLG_ACTIVE_SYS
+ | ERTS_PSFLG_DIRTY_ACTIVE_SYS))
new |= ERTS_PSFLG_RUNNING_SYS;
else
new |= ERTS_PSFLG_RUNNING;
@@ -9805,7 +9721,8 @@ Process *schedule(Process *p, int calls)
| ERTS_PSFLG_FREE))
|| ((state & (ERTS_PSFLG_SUSPENDED
| ERTS_PSFLG_PENDING_EXIT
- | ERTS_PSFLG_ACTIVE_SYS))
+ | ERTS_PSFLG_ACTIVE_SYS
+ | ERTS_PSFLG_DIRTY_ACTIVE_SYS))
== ERTS_PSFLG_SUSPENDED)) {
if (state & ERTS_PSFLG_FREE)
erts_proc_dec_refc(p);
@@ -9824,10 +9741,42 @@ Process *schedule(Process *p, int calls)
esdp->current_process = p;
+
+ reds = context_reds;
+
+#ifdef ERTS_SMP
+
+ erts_smp_runq_unlock(rq);
+
+#ifdef ERTS_DIRTY_SCHEDULERS
+ if (ERTS_SCHEDULER_IS_DIRTY(esdp)) {
+#ifdef DEBUG
+ int old_dqbit;
+#endif
+ int dqbit = qbit;
+
+ if (rq == ERTS_DIRTY_CPU_RUNQ)
+ dqbit <<= ERTS_PDSFLGS_IN_CPU_PRQ_MASK_OFFSET;
+ else {
+ ASSERT(rq == ERTS_DIRTY_IO_RUNQ);
+ dqbit <<= ERTS_PDSFLGS_IN_IO_PRQ_MASK_OFFSET;
+ }
+
+#ifdef DEBUG
+ old_dqbit = (int)
+#else
+ (void)
+#endif
+ erts_smp_atomic32_read_band_mb(&p->dirty_state, ~dqbit);
+ ASSERT(old_dqbit & dqbit);
+ }
+#endif /* ERTS_DIRTY_SCHEDULERS */
+
+#endif /* ERTS_SMP */
+
}
#ifdef ERTS_SMP
- erts_smp_runq_unlock(rq);
if (flags & ERTS_RUNQ_FLG_PROTECTED)
(void) ERTS_RUNQ_FLGS_UNSET(rq, ERTS_RUNQ_FLG_PROTECTED);
@@ -9862,15 +9811,56 @@ Process *schedule(Process *p, int calls)
erts_smp_spin_unlock(&erts_sched_stat.lock);
}
- if (ERTS_PROC_PENDING_EXIT(p)) {
+ ASSERT(!p->scheduler_data);
+ p->scheduler_data = esdp;
+
+ state = erts_smp_atomic32_read_nob(&p->state);
+
+#ifdef ERTS_DIRTY_SCHEDULERS
+ if (!ERTS_SCHEDULER_IS_DIRTY(esdp)) {
+ if (!!(state & ERTS_PSFLGS_DIRTY_WORK)
+ & !(state & ERTS_PSFLG_ACTIVE_SYS)) {
+ /* Migrate to dirty scheduler... */
+ sunlock_sched_out_proc:
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+ p->fcalls = reds;
+ goto sched_out_proc;
+
+ }
+ }
+ else {
+ if (state & (ERTS_PSFLG_ACTIVE_SYS
+ | ERTS_PSFLG_PENDING_EXIT
+ | ERTS_PSFLG_EXITING)) {
+ /* Migrate to normal scheduler... */
+ goto sunlock_sched_out_proc;
+ }
+ if ((state & ERTS_PSFLG_DIRTY_ACTIVE_SYS)
+ && rq == ERTS_DIRTY_IO_RUNQ) {
+ /* Migrate to dirty cpu scheduler... */
+ goto sunlock_sched_out_proc;
+ }
+
+ ASSERT((state & ERTS_PSFLG_DIRTY_ACTIVE_SYS)
+ || *p->i == (BeamInstr) em_call_nif);
+
+ ASSERT(rq == ERTS_DIRTY_CPU_RUNQ
+ ? (state & (ERTS_PSFLG_DIRTY_CPU_PROC
+ | ERTS_PSFLG_DIRTY_ACTIVE_SYS))
+ : (rq == ERTS_DIRTY_IO_RUNQ
+ && (state & ERTS_PSFLG_DIRTY_IO_PROC)));
+ }
+#endif
+
+ if (state & ERTS_PSFLG_PENDING_EXIT) {
erts_handle_pending_exit(p,
ERTS_PROC_LOCK_MAIN|ERTS_PROC_LOCK_STATUS);
state = erts_smp_atomic32_read_nob(&p->state);
}
- ASSERT(!p->scheduler_data);
- p->scheduler_data = esdp;
-#endif
- reds = context_reds;
+
+#endif /* ERTS_SMP */
+
+ p->fcalls = reds;
if (IS_TRACED(p)) {
if (state & ERTS_PSFLG_EXITING) {
@@ -9899,7 +9889,8 @@ Process *schedule(Process *p, int calls)
reds -= execute_sys_tasks(p, &state, reds);
if (reds <= 0
#ifdef ERTS_DIRTY_SCHEDULERS
- || (state & (ERTS_PSFLG_DIRTY_CPU_PROC|ERTS_PSFLG_DIRTY_IO_PROC))
+ || ERTS_SCHEDULER_IS_DIRTY(esdp)
+ || (state & ERTS_PSFLGS_DIRTY_WORK)
#endif
) {
p->fcalls = reds;
@@ -9932,13 +9923,13 @@ Process *schedule(Process *p, int calls)
}
}
- if (!(state & ERTS_PSFLG_EXITING)
- && ((FLAGS(p) & F_FORCE_GC)
- || (MSO(p).overhead > BIN_VHEAP_SZ(p)))) {
- reds -= erts_garbage_collect(p, 0, p->arg_reg, p->arity);
- if (reds <= 0) {
- p->fcalls = reds;
- goto sched_out_proc;
+ if (ERTS_IS_GC_DESIRED(p)) {
+ if (!(state & ERTS_PSFLG_EXITING) && !(p->flags & F_DISABLE_GC)) {
+ reds -= erts_garbage_collect_nobump(p, 0, p->arg_reg, p->arity);
+ if (reds <= 0) {
+ p->fcalls = reds;
+ goto sched_out_proc;
+ }
}
}
@@ -9947,7 +9938,6 @@ Process *schedule(Process *p, int calls)
proxy_p = NULL;
}
- p->fcalls = reds;
ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(p);
/* Never run a suspended process */
@@ -9978,7 +9968,7 @@ notify_sys_task_executed(Process *c_p, ErtsProcSysTask *st, Eterm st_result)
if (rp) {
ErtsProcLocks rp_locks;
ErlOffHeap *ohp;
- ErlHeapFragment* bp;
+ ErtsMessage *mp;
Eterm *hp, msg, req_id, result;
Uint st_result_sz, hsz;
#ifdef DEBUG
@@ -9990,11 +9980,7 @@ notify_sys_task_executed(Process *c_p, ErtsProcSysTask *st, Eterm st_result)
st_result_sz = is_immed(st_result) ? 0 : size_object(st_result);
hsz = st->req_id_sz + st_result_sz + 4 /* 3-tuple */;
- hp = erts_alloc_message_heap(hsz,
- &bp,
- &ohp,
- rp,
- &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, hsz, &hp, &ohp);
#ifdef DEBUG
hp_start = hp;
@@ -10019,7 +10005,7 @@ notify_sys_task_executed(Process *c_p, ErtsProcSysTask *st, Eterm st_result)
ASSERT(hp_start + hsz == hp);
#endif
- erts_queue_message(rp, &rp_locks, bp, msg, NIL);
+ erts_queue_message(rp, &rp_locks, mp, msg, NIL);
if (c_p == rp)
rp_locks &= ~ERTS_PROC_LOCK_MAIN;
@@ -10221,10 +10207,10 @@ execute_sys_tasks(Process *c_p, erts_aint32_t *statep, int in_reds)
else {
if (!garbage_collected) {
FLAGS(c_p) |= F_NEED_FULLSWEEP;
- reds += erts_garbage_collect(c_p,
- 0,
- c_p->arg_reg,
- c_p->arity);
+ reds += erts_garbage_collect_nobump(c_p,
+ 0,
+ c_p->arg_reg,
+ c_p->arity);
garbage_collected = 1;
}
st_res = am_true;
@@ -10233,7 +10219,7 @@ execute_sys_tasks(Process *c_p, erts_aint32_t *statep, int in_reds)
case ERTS_PSTT_CPC:
st_res = erts_check_process_code(c_p,
st->arg[0],
- st->arg[1] == am_true,
+ unsigned_val(st->arg[1]),
&reds);
if (is_non_value(st_res)) {
/* Needed gc, but gc was disabled */
@@ -10241,6 +10227,10 @@ execute_sys_tasks(Process *c_p, erts_aint32_t *statep, int in_reds)
st = NULL;
}
break;
+ case ERTS_PSTT_COHMQ:
+ reds += erts_complete_off_heap_message_queue_change(c_p);
+ st_res = am_true;
+ break;
default:
ERTS_INTERNAL_ERROR("Invalid process sys task type");
st_res = am_false;
@@ -10283,6 +10273,9 @@ cleanup_sys_tasks(Process *c_p, erts_aint32_t in_state, int in_reds)
case ERTS_PSTT_CPC:
st_res = am_false;
break;
+ case ERTS_PSTT_COHMQ:
+ st_res = am_false;
+ break;
default:
ERTS_INTERNAL_ERROR("Invalid process sys task type");
st_res = am_false;
@@ -10301,10 +10294,8 @@ BIF_RETTYPE
erts_internal_request_system_task_3(BIF_ALIST_3)
{
Process *rp = erts_proc_lookup(BIF_ARG_1);
- ErtsProcSysTaskQs *stqs, *free_stqs = NULL;
ErtsProcSysTask *st = NULL;
- erts_aint32_t prio, rp_state;
- int rp_locked;
+ erts_aint32_t prio;
Eterm noproc_res, req_type;
if (!rp && !is_internal_pid(BIF_ARG_1)) {
@@ -10361,7 +10352,6 @@ erts_internal_request_system_task_3(BIF_ALIST_3)
}
st = erts_alloc(ERTS_ALC_T_PROC_SYS_TSK,
ERTS_PROC_SYS_TASK_SIZE(tot_sz));
- st->next = st->prev = st; /* Prep for empty prio queue */
ERTS_INIT_OFF_HEAP(&st->off_heap);
hp = &st->heap[0];
@@ -10393,7 +10383,7 @@ erts_internal_request_system_task_3(BIF_ALIST_3)
case am_check_process_code:
if (is_not_atom(st->arg[0]))
goto badarg;
- if (st->arg[1] != am_true && st->arg[1] != am_false)
+ if (is_not_small(st->arg[1]) || (unsigned_val(st->arg[1]) & ~ERTS_CPC_ALL))
goto badarg;
noproc_res = am_false;
st->type = ERTS_PSTT_CPC;
@@ -10405,95 +10395,11 @@ erts_internal_request_system_task_3(BIF_ALIST_3)
goto badarg;
}
- rp_state = erts_smp_atomic32_read_nob(&rp->state);
-
- rp_locked = 0;
-
- free_stqs = NULL;
- if (rp_state & ERTS_PSFLG_ACTIVE_SYS)
- stqs = NULL;
- else {
- alloc_qs:
- stqs = proc_sys_task_queues_alloc();
- stqs->qmask = 1 << prio;
- stqs->ncount = 0;
- stqs->q[PRIORITY_MAX] = NULL;
- stqs->q[PRIORITY_HIGH] = NULL;
- stqs->q[PRIORITY_NORMAL] = NULL;
- stqs->q[PRIORITY_LOW] = NULL;
- stqs->q[prio] = st;
- }
-
- if (!rp_locked) {
- rp_locked = 1;
- erts_smp_proc_lock(rp, ERTS_PROC_LOCK_STATUS);
-
- rp_state = erts_smp_atomic32_read_nob(&rp->state);
- if (rp_state & ERTS_PSFLG_EXITING) {
- erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_STATUS);
- rp = NULL;
- free_stqs = stqs;
- goto noproc;
- }
+ if (!schedule_process_sys_task(rp, prio, st)) {
+ noproc:
+ notify_sys_task_executed(BIF_P, st, noproc_res);
}
- if (!rp->sys_task_qs) {
- if (stqs)
- rp->sys_task_qs = stqs;
- else
- goto alloc_qs;
- }
- else {
- if (stqs)
- free_stqs = stqs;
- stqs = rp->sys_task_qs;
- if (!stqs->q[prio]) {
- stqs->q[prio] = st;
- stqs->qmask |= 1 << prio;
- }
- else {
- st->next = stqs->q[prio];
- st->prev = stqs->q[prio]->prev;
- st->next->prev = st;
- st->prev->next = st;
- ASSERT(stqs->qmask & (1 << prio));
- }
- }
-
- if (ERTS_PSFLGS_GET_ACT_PRIO(rp_state) > prio) {
- erts_aint32_t n, a, e;
- /* Need to elevate actual prio */
-
- a = rp_state;
- do {
- if (ERTS_PSFLGS_GET_ACT_PRIO(a) <= prio) {
- n = a;
- break;
- }
- n = e = a;
- n &= ~ERTS_PSFLGS_ACT_PRIO_MASK;
- n |= (prio << ERTS_PSFLGS_ACT_PRIO_OFFSET);
- a = erts_smp_atomic32_cmpxchg_nob(&rp->state, n, e);
- } while (a != e);
- rp_state = n;
- }
-
- /*
- * schedule_process_sys_task() unlocks status
- * lock on process.
- */
- schedule_process_sys_task(rp, rp_state, NULL);
-
- if (free_stqs)
- proc_sys_task_queues_free(free_stqs);
-
- BIF_RET(am_ok);
-
-noproc:
-
- notify_sys_task_executed(BIF_P, st, noproc_res);
- if (free_stqs)
- proc_sys_task_queues_free(free_stqs);
BIF_RET(am_ok);
badarg:
@@ -10502,11 +10408,35 @@ badarg:
erts_cleanup_offheap(&st->off_heap);
erts_free(ERTS_ALC_T_PROC_SYS_TSK, st);
}
- if (free_stqs)
- proc_sys_task_queues_free(free_stqs);
BIF_ERROR(BIF_P, BADARG);
}
+void
+erts_schedule_complete_off_heap_message_queue_change(Eterm pid)
+{
+ Process *rp = erts_proc_lookup(pid);
+ if (rp) {
+ ErtsProcSysTask *st;
+ erts_aint32_t state;
+ int i;
+
+ st = erts_alloc(ERTS_ALC_T_PROC_SYS_TSK,
+ ERTS_PROC_SYS_TASK_SIZE(0));
+ st->type = ERTS_PSTT_COHMQ;
+ st->requester = NIL;
+ st->reply_tag = NIL;
+ st->req_id = NIL;
+ st->req_id_sz = 0;
+ for (i = 0; i < ERTS_MAX_PROC_SYS_TASK_ARGS; i++)
+ st->arg[i] = NIL;
+ ERTS_INIT_OFF_HEAP(&st->off_heap);
+ state = erts_smp_atomic32_read_nob(&rp->state);
+
+ if (!schedule_process_sys_task(rp, ERTS_PSFLGS_GET_USR_PRIO(state), st))
+ erts_free(ERTS_ALC_T_PROC_SYS_TSK, st);
+ }
+}
+
static void
save_gc_task(Process *c_p, ErtsProcSysTask *st, int prio)
{
@@ -10892,6 +10822,9 @@ static void early_init_process_struct(void *varg, Eterm data)
Process *proc = arg->proc;
proc->common.id = make_internal_pid(data);
+#ifdef ERTS_DIRTY_SCHEDULERS
+ erts_smp_atomic32_init_nob(&proc->dirty_state, 0);
+#endif
erts_smp_atomic32_init_relb(&proc->state, arg->state);
#ifdef ERTS_SMP
@@ -10952,6 +10885,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
Eterm args, /* Arguments for function (must be well-formed list). */
ErlSpawnOpts* so) /* Options for spawn. */
{
+ Uint flags = 0;
ErtsRunQueue *rq = NULL;
Process *p;
Sint arity; /* Number of arguments. */
@@ -10961,6 +10895,10 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
Eterm res = THE_NON_VALUE;
erts_aint32_t state = 0;
erts_aint32_t prio = (erts_aint32_t) PRIORITY_NORMAL;
+#ifdef SHCOPY_SPAWN
+ erts_shcopy_t info;
+ INITIALIZE_SHCOPY(info);
+#endif
#ifdef ERTS_SMP
erts_smp_proc_lock(parent, ERTS_PROC_LOCKS_ALL_MINOR);
@@ -10989,6 +10927,15 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
state |= (((prio & ERTS_PSFLGS_PRIO_MASK) << ERTS_PSFLGS_ACT_PRIO_OFFSET)
| ((prio & ERTS_PSFLGS_PRIO_MASK) << ERTS_PSFLGS_USR_PRIO_OFFSET));
+ if (so->flags & SPO_OFF_HEAP_MSGQ) {
+ state |= ERTS_PSFLG_OFF_HEAP_MSGQ;
+ flags |= F_OFF_HEAP_MSGQ;
+ }
+ else if (so->flags & SPO_ON_HEAP_MSGQ) {
+ state |= ERTS_PSFLG_ON_HEAP_MSGQ;
+ flags |= F_ON_HEAP_MSGQ;
+ }
+
if (!rq)
rq = erts_get_runq_proc(parent);
@@ -11007,11 +10954,15 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
BM_COUNT(processes_spawned);
BM_SWAP_TIMER(system,size);
+#ifdef SHCOPY_SPAWN
+ arg_size = copy_shared_calculate(args, &info);
+#else
arg_size = size_object(args);
+#endif
BM_SWAP_TIMER(size,system);
heap_need = arg_size;
- p->flags = erts_default_process_flags;
+ p->flags = flags;
p->static_flags = 0;
if (so->flags & SPO_SYSTEM_PROC)
@@ -11060,12 +11011,13 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->stop = p->hend = p->heap + sz;
p->htop = p->heap;
p->heap_sz = sz;
+ p->abandoned_heap = NULL;
+ p->live_hf_end = ERTS_INVALID_HFRAG_PTR;
p->catches = 0;
p->bin_vheap_sz = p->min_vheap_size;
p->bin_old_vheap_sz = p->min_vheap_size;
p->bin_old_vheap = 0;
- p->bin_vheap_mature = 0;
p->sys_task_qs = NULL;
@@ -11084,7 +11036,12 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
BM_MESSAGE(args,p,parent);
BM_START_TIMER(system);
BM_SWAP_TIMER(system,copy);
+#ifdef SHCOPY_SPAWN
+ p->arg_reg[2] = copy_shared_perform(args, arg_size, &info, &p->htop, &p->off_heap);
+ DESTROY_SHCOPY(info);
+#else
p->arg_reg[2] = copy_struct(args, arg_size, &p->htop, &p->off_heap);
+#endif
BM_MESSAGE_COPIED(arg_size);
BM_SWAP_TIMER(copy,system);
p->arity = 3;
@@ -11130,6 +11087,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->accessor_bif_timers = NULL;
#endif
p->mbuf = NULL;
+ p->msg_frag = NULL;
p->mbuf_sz = 0;
p->psd = NULL;
p->dictionary = NULL;
@@ -11265,6 +11223,8 @@ void erts_init_empty_process(Process *p)
p->stop = NULL;
p->hend = NULL;
p->heap = NULL;
+ p->abandoned_heap = NULL;
+ p->live_hf_end = ERTS_INVALID_HFRAG_PTR;
p->gen_gcs = 0;
p->max_gen_gcs = 0;
p->min_heap_size = 0;
@@ -11285,7 +11245,6 @@ void erts_init_empty_process(Process *p)
p->bin_old_vheap_sz = BIN_VH_MIN_SIZE;
p->bin_old_vheap = 0;
p->sys_task_qs = NULL;
- p->bin_vheap_mature = 0;
ERTS_PTMR_INIT(p);
p->next = NULL;
p->off_heap.first = NULL;
@@ -11297,6 +11256,7 @@ void erts_init_empty_process(Process *p)
p->old_htop = NULL;
p->old_heap = NULL;
p->mbuf = NULL;
+ p->msg_frag = NULL;
p->mbuf_sz = 0;
p->psd = NULL;
ERTS_P_MONITORS(p) = NULL;
@@ -11354,6 +11314,9 @@ void erts_init_empty_process(Process *p)
p->last_old_htop = NULL;
#endif
+#ifdef ERTS_DIRTY_SCHEDULERS
+ erts_smp_atomic32_init_nob(&p->dirty_state, 0);
+#endif
erts_smp_atomic32_init_nob(&p->state, (erts_aint32_t) PRIORITY_NORMAL);
#ifdef ERTS_SMP
@@ -11385,6 +11348,8 @@ erts_debug_verify_clean_empty_process(Process* p)
ASSERT(p->htop == NULL);
ASSERT(p->stop == NULL);
ASSERT(p->hend == NULL);
+ ASSERT(p->abandoned_heap == NULL);
+ ASSERT(p->live_hf_end == ERTS_INVALID_HFRAG_PTR);
ASSERT(p->heap == NULL);
ASSERT(p->common.id == ERTS_INVALID_PID);
ASSERT(ERTS_TRACER_PROC(p) == NIL);
@@ -11462,9 +11427,10 @@ erts_cleanup_empty_process(Process* p)
static void
delete_process(Process* p)
{
- ErlMessage* mp;
-
+ Eterm *heap;
VERBOSE(DEBUG_PROCESSES, ("Removing process: %T\n",p->common.id));
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] delete process: %p %p %p %p\n", p->common.id,
+ HEAP_START(p), HEAP_END(p), OLD_HEAP(p), OLD_HEND(p)));
/* Cleanup psd */
@@ -11488,16 +11454,17 @@ delete_process(Process* p)
* Release heaps. Clobber contents in DEBUG build.
*/
-
-#ifdef DEBUG
- sys_memset(p->heap, DEBUG_BAD_BYTE, p->heap_sz*sizeof(Eterm));
-#endif
-
#ifdef HIPE
hipe_delete_process(&p->hipe);
#endif
- ERTS_HEAP_FREE(ERTS_ALC_T_HEAP, (void*) p->heap, p->heap_sz*sizeof(Eterm));
+ heap = p->abandoned_heap ? p->abandoned_heap : p->heap;
+
+#ifdef DEBUG
+ sys_memset(heap, DEBUG_BAD_BYTE, p->heap_sz*sizeof(Eterm));
+#endif
+
+ ERTS_HEAP_FREE(ERTS_ALC_T_HEAP, (void*) heap, p->heap_sz*sizeof(Eterm));
if (p->old_heap != NULL) {
#ifdef DEBUG
@@ -11516,27 +11483,14 @@ delete_process(Process* p)
free_message_buffer(p->mbuf);
}
+ if (p->msg_frag)
+ erts_cleanup_messages(p->msg_frag);
+
erts_erase_dicts(p);
/* free all pending messages */
- mp = p->msg.first;
- while(mp != NULL) {
- ErlMessage* next_mp = mp->next;
- if (mp->data.attached) {
- if (is_value(mp->m[0]))
- free_message_buffer(mp->data.heap_frag);
- else {
- if (is_not_nil(mp->m[1])) {
- ErlHeapFragment *heap_frag;
- heap_frag = (ErlHeapFragment *) mp->data.dist_ext->ext_endp;
- erts_cleanup_offheap(&heap_frag->off_heap);
- }
- erts_free_dist_ext_copy(mp->data.dist_ext);
- }
- }
- free_message(mp);
- mp = next_mp;
- }
+ erts_cleanup_messages(p->msg.first);
+ p->msg.first = NULL;
ASSERT(!p->nodes_monitors);
ASSERT(!p->suspend_monitors);
@@ -11555,7 +11509,9 @@ set_proc_exiting(Process *p,
ERTS_SMP_LC_ASSERT(erts_proc_lc_my_proc_locks(p) == ERTS_PROC_LOCKS_ALL);
enqueue = change_proc_schedule_state(p,
- ERTS_PSFLG_SUSPENDED|ERTS_PSFLG_PENDING_EXIT,
+ (ERTS_PSFLG_SUSPENDED
+ | ERTS_PSFLG_PENDING_EXIT
+ | ERTS_PSFLGS_DIRTY_WORK),
ERTS_PSFLG_EXITING|ERTS_PSFLG_ACTIVE,
&state,
&enq_prio,
@@ -11589,10 +11545,7 @@ set_proc_exiting(Process *p,
}
#endif
- if (enqueue)
- add2runq(enqueue > 0 ? p : make_proxy_proc(NULL, p, enq_prio),
- state,
- enq_prio);
+ add2runq(enqueue, enq_prio, p, state, NULL);
}
static ERTS_INLINE erts_aint32_t
@@ -11695,6 +11648,11 @@ save_pending_exiter(Process *p)
else
rq = esdp->run_queue;
+#ifdef ERTS_DIRTY_SCHEDULERS
+ if (ERTS_RUNQ_IX_IS_DIRTY(rq->ix))
+ rq = ERTS_RUNQ_IX(0); /* Handle on ordinary scheduler */
+#endif
+
plp = proclist_create(p);
erts_smp_runq_lock(rq);
@@ -11704,13 +11662,8 @@ save_pending_exiter(Process *p)
non_empty_runq(rq);
erts_smp_runq_unlock(rq);
-#ifdef ERTS_DIRTY_SCHEDULERS
- if (ERTS_RUNQ_IX_IS_DIRTY(rq->ix))
- wake_dirty_schedulers(rq, 0);
- else
-#endif
- wake_scheduler(rq);
+ wake_scheduler(rq);
}
#endif
@@ -11724,35 +11677,46 @@ static ERTS_INLINE void
send_exit_message(Process *to, ErtsProcLocks *to_locksp,
Eterm exit_term, Uint term_size, Eterm token)
{
- if (token == NIL
-#ifdef USE_VM_PROBES
- || token == am_have_dt_utag
-#endif
- ) {
- Eterm* hp;
- Eterm mess;
- ErlHeapFragment* bp;
- ErlOffHeap *ohp;
-
- hp = erts_alloc_message_heap(term_size, &bp, &ohp, to, to_locksp);
+ ErtsMessage *mp;
+ ErlOffHeap *ohp;
+ Eterm* hp;
+ Eterm mess;
+#ifdef SHCOPY_SEND
+ erts_shcopy_t info;
+#endif
+
+ if (!have_seqtrace(token)) {
+#ifdef SHCOPY_SEND
+ INITIALIZE_SHCOPY(info);
+ term_size = copy_shared_calculate(exit_term, &info);
+ mp = erts_alloc_message_heap(to, to_locksp, term_size, &hp, &ohp);
+ mess = copy_shared_perform(exit_term, term_size, &info, &hp, ohp);
+ DESTROY_SHCOPY(info);
+#else
+ mp = erts_alloc_message_heap(to, to_locksp, term_size, &hp, &ohp);
mess = copy_struct(exit_term, term_size, &hp, ohp);
- erts_queue_message(to, to_locksp, bp, mess, NIL);
+#endif
+ erts_queue_message(to, to_locksp, mp, mess, NIL);
} else {
- ErlHeapFragment* bp;
- Eterm* hp;
- Eterm mess;
Eterm temp_token;
Uint sz_token;
ASSERT(is_tuple(token));
sz_token = size_object(token);
- bp = new_message_buffer(term_size+sz_token);
- hp = bp->mem;
- mess = copy_struct(exit_term, term_size, &hp, &bp->off_heap);
+#ifdef SHCOPY_SEND
+ INITIALIZE_SHCOPY(info);
+ term_size = copy_shared_calculate(exit_term, &info);
+ mp = erts_alloc_message_heap(to, to_locksp, term_size+sz_token, &hp, &ohp);
+ mess = copy_shared_perform(exit_term, term_size, &info, &hp, ohp);
+ DESTROY_SHCOPY(info);
+#else
+ mp = erts_alloc_message_heap(to, to_locksp, term_size+sz_token, &hp, &ohp);
+ mess = copy_struct(exit_term, term_size, &hp, ohp);
+#endif
/* the trace token must in this case be updated by the caller */
seq_trace_output(token, mess, SEQ_TRACE_SEND, to->common.id, NULL);
- temp_token = copy_struct(token, sz_token, &hp, &bp->off_heap);
- erts_queue_message(to, to_locksp, bp, mess, temp_token);
+ temp_token = copy_struct(token, sz_token, &hp, ohp);
+ erts_queue_message(to, to_locksp, mp, mess, temp_token);
}
}
@@ -11861,11 +11825,7 @@ send_exit_signal(Process *c_p, /* current process if and only
if ((state & ERTS_PSFLG_TRAP_EXIT)
&& (reason != am_kill || (flags & ERTS_XSIG_FLG_IGN_KILL))) {
- if (is_not_nil(token)
-#ifdef USE_VM_PROBES
- && token != am_have_dt_utag
-#endif
- && token_update)
+ if (have_seqtrace(token) && token_update)
seq_trace_update_send(token_update);
if (is_value(exit_tuple))
send_exit_message(rp, rp_locks, exit_tuple, exit_tuple_sz, token);
@@ -12397,14 +12357,39 @@ erts_continue_exit_process(Process *p)
#endif
#ifdef ERTS_SMP
+ if (p->flags & F_SCHDLR_ONLN_WAITQ)
+ abort_sched_onln_chng_waitq(p);
+
if (p->flags & F_HAVE_BLCKD_MSCHED) {
ErtsSchedSuspendResult ssr;
- ssr = erts_block_multi_scheduling(p, ERTS_PROC_LOCK_MAIN, 0, 1);
+ ssr = erts_block_multi_scheduling(p, ERTS_PROC_LOCK_MAIN, 0, 0, 1);
+ switch (ssr) {
+ case ERTS_SCHDLR_SSPND_YIELD_RESTART:
+ goto yield;
+ case ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED:
+ case ERTS_SCHDLR_SSPND_DONE_NMSCHED_BLOCKED:
+ case ERTS_SCHDLR_SSPND_YIELD_DONE_MSCHED_BLOCKED:
+ case ERTS_SCHDLR_SSPND_YIELD_DONE_NMSCHED_BLOCKED:
+ case ERTS_SCHDLR_SSPND_DONE:
+ case ERTS_SCHDLR_SSPND_YIELD_DONE:
+ p->flags &= ~F_HAVE_BLCKD_MSCHED;
+ break;
+ case ERTS_SCHDLR_SSPND_EINVAL:
+ default:
+ erts_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error: %d\n",
+ __FILE__, __LINE__, (int) ssr);
+ }
+ }
+ if (p->flags & F_HAVE_BLCKD_NMSCHED) {
+ ErtsSchedSuspendResult ssr;
+ ssr = erts_block_multi_scheduling(p, ERTS_PROC_LOCK_MAIN, 0, 1, 1);
switch (ssr) {
case ERTS_SCHDLR_SSPND_YIELD_RESTART:
goto yield;
case ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED:
+ case ERTS_SCHDLR_SSPND_DONE_NMSCHED_BLOCKED:
case ERTS_SCHDLR_SSPND_YIELD_DONE_MSCHED_BLOCKED:
+ case ERTS_SCHDLR_SSPND_YIELD_DONE_NMSCHED_BLOCKED:
case ERTS_SCHDLR_SSPND_DONE:
case ERTS_SCHDLR_SSPND_YIELD_DONE:
p->flags &= ~F_HAVE_BLCKD_MSCHED;
@@ -12698,7 +12683,7 @@ stack_element_dump(int to, void *to_arg, Eterm* sp, int yreg)
}
if (is_CP(x)) {
- erts_print(to, to_arg, "Return addr %p (", (Eterm *) EXPAND_POINTER(x));
+ erts_print(to, to_arg, "Return addr %p (", (Eterm *) x);
print_function_from_pc(to, to_arg, cp_val(x));
erts_print(to, to_arg, ")\n");
yreg = 0;
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index b536426b0f..c88bd7056c 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -79,10 +79,8 @@ struct ErtsNodesMonitor_;
#define ERTS_HAVE_SCHED_UTIL_BALANCING_SUPPORT 0
#define ERTS_MAX_NO_OF_SCHEDULERS 1024
-#ifdef ERTS_DIRTY_SCHEDULERS
#define ERTS_MAX_NO_OF_DIRTY_CPU_SCHEDULERS ERTS_MAX_NO_OF_SCHEDULERS
#define ERTS_MAX_NO_OF_DIRTY_IO_SCHEDULERS ERTS_MAX_NO_OF_SCHEDULERS
-#endif
#define ERTS_DEFAULT_MAX_PROCESSES (1 << 18)
@@ -246,7 +244,9 @@ extern int erts_sched_thread_suggested_stack_size;
typedef enum {
ERTS_SCHDLR_SSPND_DONE_MSCHED_BLOCKED,
+ ERTS_SCHDLR_SSPND_DONE_NMSCHED_BLOCKED,
ERTS_SCHDLR_SSPND_YIELD_DONE_MSCHED_BLOCKED,
+ ERTS_SCHDLR_SSPND_YIELD_DONE_NMSCHED_BLOCKED,
ERTS_SCHDLR_SSPND_DONE,
ERTS_SCHDLR_SSPND_YIELD_RESTART,
ERTS_SCHDLR_SSPND_YIELD_DONE,
@@ -304,7 +304,6 @@ typedef enum {
ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN_IX,
ERTS_SSI_AUX_WORK_MISC_THR_PRGR_IX,
ERTS_SSI_AUX_WORK_MISC_IX,
- ERTS_SSI_AUX_WORK_CHECK_CHILDREN_IX,
ERTS_SSI_AUX_WORK_SET_TMO_IX,
ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK_IX,
ERTS_SSI_AUX_WORK_REAP_PORTS_IX,
@@ -337,8 +336,6 @@ typedef enum {
(((erts_aint32_t) 1) << ERTS_SSI_AUX_WORK_MISC_THR_PRGR_IX)
#define ERTS_SSI_AUX_WORK_MISC \
(((erts_aint32_t) 1) << ERTS_SSI_AUX_WORK_MISC_IX)
-#define ERTS_SSI_AUX_WORK_CHECK_CHILDREN \
- (((erts_aint32_t) 1) << ERTS_SSI_AUX_WORK_CHECK_CHILDREN_IX)
#define ERTS_SSI_AUX_WORK_SET_TMO \
(((erts_aint32_t) 1) << ERTS_SSI_AUX_WORK_SET_TMO_IX)
#define ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK \
@@ -643,12 +640,6 @@ struct ErtsSchedulerData_ {
Process *free_process;
ErtsThrPrgrData thr_progress_data;
#endif
-#if !HEAP_ON_C_STACK
- Eterm tmp_heap[TMP_HEAP_SIZE];
- int num_tmp_heap_used;
- Eterm beam_emu_tmp_heap[BEAM_EMU_TMP_HEAP_SIZE];
- Eterm erl_arith_tmp_heap[ERL_ARITH_TMP_HEAP_SIZE];
-#endif
ErtsSchedulerSleepInfo *ssi;
Process *current_process;
Uint no; /* Scheduler number for normal schedulers */
@@ -702,13 +693,6 @@ extern ErtsAlignedSchedulerData *erts_aligned_dirty_io_scheduler_data;
extern ErtsSchedulerData *erts_scheduler_data;
#endif
-#ifdef ERTS_SCHED_FAIR
-#define ERTS_SCHED_FAIR_YIELD() ETHR_YIELD()
-#else
-#define ERTS_SCHED_FAIR 0
-#define ERTS_SCHED_FAIR_YIELD()
-#endif
-
#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
int erts_smp_lc_runq_is_locked(ErtsRunQueue *);
#endif
@@ -924,7 +908,6 @@ struct ErtsPendingSuspend_ {
# define MIN_VHEAP_SIZE(p) (p)->min_vheap_size
# define BIN_VHEAP_SZ(p) (p)->bin_vheap_sz
-# define BIN_VHEAP_MATURE(p) (p)->bin_vheap_mature
# define BIN_OLD_VHEAP_SZ(p) (p)->bin_old_vheap_sz
# define BIN_OLD_VHEAP(p) (p)->bin_old_vheap
@@ -942,6 +925,7 @@ struct process {
Eterm* stop; /* Stack top */
Eterm* heap; /* Heap start */
Eterm* hend; /* Heap end */
+ Eterm* abandoned_heap;
Uint heap_sz; /* Size of heap in words */
Uint min_heap_size; /* Minimum size of heap (in words). */
Uint min_vheap_size; /* Minimum size of virtual heap (in words). */
@@ -1038,18 +1022,22 @@ struct process {
Uint16 gen_gcs; /* Number of (minor) generational GCs. */
Uint16 max_gen_gcs; /* Max minor gen GCs before fullsweep. */
ErlOffHeap off_heap; /* Off-heap data updated by copy_struct(). */
- ErlHeapFragment* mbuf; /* Pointer to message buffer list */
- Uint mbuf_sz; /* Size of all message buffers */
+ ErlHeapFragment* mbuf; /* Pointer to heap fragment list */
+ ErlHeapFragment* live_hf_end;
+ ErtsMessage *msg_frag; /* Pointer to message fragment list */
+ Uint mbuf_sz; /* Total size of heap fragments and message fragments */
ErtsPSD *psd; /* Rarely used process specific data */
Uint64 bin_vheap_sz; /* Virtual heap block size for binaries */
- Uint64 bin_vheap_mature; /* Virtual heap block size for binaries */
Uint64 bin_old_vheap_sz; /* Virtual old heap block size for binaries */
Uint64 bin_old_vheap; /* Virtual old heap size for binaries */
ErtsProcSysTaskQs *sys_task_qs;
erts_smp_atomic32_t state; /* Process state flags (see ERTS_PSFLG_*) */
+#ifdef ERTS_DIRTY_SCHEDULERS
+ erts_smp_atomic32_t dirty_state; /* Process dirty state flags (see ERTS_PDSFLG_*) */
+#endif
#ifdef ERTS_SMP
ErlMessageInQueue msg_inq;
@@ -1067,6 +1055,7 @@ struct process {
#ifdef CHECK_FOR_HOLES
Eterm* last_htop; /* No need to scan the heap below this point. */
ErlHeapFragment* last_mbuf; /* No need to scan beyond this mbuf. */
+ ErlHeapFragment* heap_hfrag; /* Heap abandoned, htop now lives in this frag */
#endif
#ifdef DEBUG
@@ -1090,6 +1079,7 @@ extern const Process erts_invalid_process;
do { \
(p)->last_htop = 0; \
(p)->last_mbuf = 0; \
+ (p)->heap_hfrag = NULL; \
} while (0)
# define ERTS_HOLE_CHECK(p) erts_check_for_holes((p))
@@ -1167,15 +1157,16 @@ void erts_check_for_holes(Process* p);
#define ERTS_PSFLG_RUNNING_SYS ERTS_PSFLG_BIT(15)
#define ERTS_PSFLG_PROXY ERTS_PSFLG_BIT(16)
#define ERTS_PSFLG_DELAYED_SYS ERTS_PSFLG_BIT(17)
-#ifdef ERTS_DIRTY_SCHEDULERS
-#define ERTS_PSFLG_DIRTY_CPU_PROC ERTS_PSFLG_BIT(18)
-#define ERTS_PSFLG_DIRTY_IO_PROC ERTS_PSFLG_BIT(19)
-#define ERTS_PSFLG_DIRTY_CPU_PROC_IN_Q ERTS_PSFLG_BIT(20)
-#define ERTS_PSFLG_DIRTY_IO_PROC_IN_Q ERTS_PSFLG_BIT(21)
+#define ERTS_PSFLG_OFF_HEAP_MSGQ ERTS_PSFLG_BIT(18)
+#define ERTS_PSFLG_ON_HEAP_MSGQ ERTS_PSFLG_BIT(19)
+#define ERTS_PSFLG_DIRTY_CPU_PROC ERTS_PSFLG_BIT(20)
+#define ERTS_PSFLG_DIRTY_IO_PROC ERTS_PSFLG_BIT(21)
+#define ERTS_PSFLG_DIRTY_ACTIVE_SYS ERTS_PSFLG_BIT(22)
#define ERTS_PSFLG_MAX (ERTS_PSFLGS_ZERO_BIT_OFFSET + 22)
-#else
-#define ERTS_PSFLG_MAX (ERTS_PSFLGS_ZERO_BIT_OFFSET + 18)
-#endif
+
+#define ERTS_PSFLGS_DIRTY_WORK (ERTS_PSFLG_DIRTY_CPU_PROC \
+ | ERTS_PSFLG_DIRTY_IO_PROC \
+ | ERTS_PSFLG_DIRTY_ACTIVE_SYS)
#define ERTS_PSFLGS_IN_PRQ_MASK (ERTS_PSFLG_IN_PRQ_MAX \
| ERTS_PSFLG_IN_PRQ_HIGH \
@@ -1189,6 +1180,36 @@ void erts_check_for_holes(Process* p);
#define ERTS_PSFLGS_GET_PRQ_PRIO(PSFLGS) \
(((PSFLGS) >> ERTS_PSFLGS_PRQ_PRIO_OFFSET) & ERTS_PSFLGS_PRIO_MASK)
+#ifdef ERTS_DIRTY_SCHEDULERS
+
+/*
+ * Flags in the dirty_state field.
+ */
+
+#define ERTS_PDSFLG_IN_CPU_PRQ_MAX (((erts_aint32_t) 1) << 0)
+#define ERTS_PDSFLG_IN_CPU_PRQ_HIGH (((erts_aint32_t) 1) << 1)
+#define ERTS_PDSFLG_IN_CPU_PRQ_NORMAL (((erts_aint32_t) 1) << 2)
+#define ERTS_PDSFLG_IN_CPU_PRQ_LOW (((erts_aint32_t) 1) << 3)
+#define ERTS_PDSFLG_IN_IO_PRQ_MAX (((erts_aint32_t) 1) << 4)
+#define ERTS_PDSFLG_IN_IO_PRQ_HIGH (((erts_aint32_t) 1) << 5)
+#define ERTS_PDSFLG_IN_IO_PRQ_NORMAL (((erts_aint32_t) 1) << 6)
+#define ERTS_PDSFLG_IN_IO_PRQ_LOW (((erts_aint32_t) 1) << 7)
+
+#define ERTS_PDSFLGS_QMASK ERTS_PSFLGS_QMASK
+#define ERTS_PDSFLGS_IN_CPU_PRQ_MASK_OFFSET 0
+#define ERTS_PDSFLGS_IN_IO_PRQ_MASK_OFFSET ERTS_PSFLGS_QMASK_BITS
+
+#define ERTS_PDSFLG_IN_CPU_PRQ_MASK (ERTS_PDSFLG_IN_CPU_PRQ_MAX \
+ | ERTS_PDSFLG_IN_CPU_PRQ_HIGH \
+ | ERTS_PDSFLG_IN_CPU_PRQ_NORMAL\
+ | ERTS_PDSFLG_IN_CPU_PRQ_LOW)
+#define ERTS_PDSFLG_IN_IO_PRQ_MASK (ERTS_PDSFLG_IN_CPU_PRQ_MAX \
+ | ERTS_PDSFLG_IN_CPU_PRQ_HIGH \
+ | ERTS_PDSFLG_IN_CPU_PRQ_NORMAL\
+ | ERTS_PDSFLG_IN_CPU_PRQ_LOW)
+#endif
+
+
/*
* Static flags that do not change after process creation.
*/
@@ -1222,12 +1243,16 @@ void erts_check_for_holes(Process* p);
#define SPO_USE_ARGS 2
#define SPO_MONITOR 4
#define SPO_SYSTEM_PROC 8
+#define SPO_OFF_HEAP_MSGQ 16
+#define SPO_ON_HEAP_MSGQ 32
+
+extern int erts_default_spo_flags;
/*
* The following struct contains options for a process to be spawned.
*/
typedef struct {
- Uint flags;
+ int flags;
int error_code; /* Error code returned from create_process(). */
Eterm mref; /* Monitor ref returned (if SPO_MONITOR was given). */
@@ -1267,7 +1292,6 @@ Eterm* erts_heap_alloc(Process* p, Uint need, Uint xtra);
Eterm* erts_set_hole_marker(Eterm* ptr, Uint sz);
#endif
-extern Uint erts_default_process_flags;
extern erts_smp_rwmtx_t erts_cpu_bind_rwmtx;
/* If any of the erts_system_monitor_* variables are set (enabled),
** erts_system_monitor must be != NIL, to allow testing on just
@@ -1309,7 +1333,25 @@ extern int erts_system_profile_ts_type;
#define F_HAVE_BLCKD_MSCHED (1 << 8) /* Process has blocked multi-scheduling */
#define F_P2PNR_RESCHED (1 << 9) /* Process has been rescheduled via erts_pid2proc_not_running() */
#define F_FORCE_GC (1 << 10) /* Force gc at process in-scheduling */
-#define F_DISABLE_GC (1 << 11) /* Disable GC */
+#define F_DISABLE_GC (1 << 11) /* Disable GC (see below) */
+#define F_OFF_HEAP_MSGQ (1 << 12) /* Off heap msg queue */
+#define F_ON_HEAP_MSGQ (1 << 13) /* Off heap msg queue */
+#define F_OFF_HEAP_MSGQ_CHNG (1 << 14) /* Off heap msg queue changing */
+#define F_ABANDONED_HEAP_USE (1 << 15) /* Have usage of abandoned heap */
+#define F_DELAY_GC (1 << 16) /* Similar to disable GC (see below) */
+#define F_SCHDLR_ONLN_WAITQ (1 << 17) /* Process enqueued waiting to change schedulers online */
+#define F_HAVE_BLCKD_NMSCHED (1 << 18) /* Process has blocked normal multi-scheduling */
+
+/*
+ * F_DISABLE_GC and F_DELAY_GC are similar. Both will prevent
+ * GC of the process, but it is important to use the right
+ * one:
+ * - F_DISABLE_GC should *only* be used by BIFs. This when
+ * the BIF needs to yield while preventig a GC.
+ * - F_DELAY_GC should only be used when GC is temporarily
+ * disabled while the process is scheduled. A process must
+ * not be scheduled out while F_DELAY_GC is set.
+ */
#define ERTS_TRACE_FLAGS_TS_TYPE_SHIFT 0
@@ -1493,6 +1535,7 @@ int erts_setup_nif_gc(Process* proc, Eterm** objv, int* nobj); /* see erl_nif.c
void erts_destroy_nif_export(void *); /* see erl_nif.c */
ErtsProcList *erts_proclist_create(Process *);
+ErtsProcList *erts_proclist_copy(ErtsProcList *);
void erts_proclist_destroy(ErtsProcList *);
ERTS_GLB_INLINE int erts_proclist_same(ErtsProcList *, Process *);
@@ -1673,40 +1716,31 @@ void erts_schedule_thr_prgr_later_cleanup_op(void (*)(void *),
void *,
ErtsThrPrgrLaterOp *,
UWord);
+void erts_schedule_complete_off_heap_message_queue_change(Eterm pid);
#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
int erts_dbg_check_halloc_lock(Process *p);
#endif
-#ifdef DEBUG
-void erts_dbg_multi_scheduling_return_trap(Process *, Eterm);
-#endif
-int erts_get_max_no_executing_schedulers(void);
#if defined(ERTS_SMP) || defined(ERTS_DIRTY_SCHEDULERS)
-ErtsSchedSuspendResult
-erts_schedulers_state(Uint *, Uint *, Uint *, Uint *, Uint *, Uint *, int);
+void
+erts_schedulers_state(Uint *, Uint *, Uint *, Uint *, Uint *, Uint *, Uint *, Uint *);
#endif
#ifdef ERTS_SMP
ErtsSchedSuspendResult
erts_set_schedulers_online(Process *p,
ErtsProcLocks plocks,
Sint new_no,
- Sint *old_no
-#ifdef ERTS_DIRTY_SCHEDULERS
- , int dirty_only
-#endif
- );
+ Sint *old_no,
+ int dirty_only);
ErtsSchedSuspendResult
-erts_block_multi_scheduling(Process *, ErtsProcLocks, int, int);
+erts_block_multi_scheduling(Process *, ErtsProcLocks, int, int, int);
int erts_is_multi_scheduling_blocked(void);
-Eterm erts_multi_scheduling_blockers(Process *);
+Eterm erts_multi_scheduling_blockers(Process *, int);
void erts_start_schedulers(void);
void erts_alloc_notify_delayed_dealloc(int);
void erts_alloc_ensure_handle_delayed_dealloc_call(int);
-#ifdef ERTS_SMP
void erts_notify_canceled_timer(ErtsSchedulerData *, int);
#endif
-void erts_smp_notify_check_children_needed(void);
-#endif
#if ERTS_USE_ASYNC_READY_Q
void erts_notify_check_async_ready_queue(void *);
#endif
@@ -1800,7 +1834,7 @@ Uint erts_debug_nbalance(void);
int erts_debug_wait_completed(Process *c_p, int flags);
-Uint erts_process_memory(Process *c_p);
+Uint erts_process_memory(Process *c_p, int incl_msg_inq);
#ifdef ERTS_SMP
# define ERTS_GET_SCHEDULER_DATA_FROM_PROC(PROC) ((PROC)->scheduler_data)
@@ -2110,6 +2144,22 @@ ERTS_GLB_INLINE void erts_smp_xrunq_unlock(ErtsRunQueue *rq, ErtsRunQueue *xrq);
ERTS_GLB_INLINE void erts_smp_runqs_lock(ErtsRunQueue *rq1, ErtsRunQueue *rq2);
ERTS_GLB_INLINE void erts_smp_runqs_unlock(ErtsRunQueue *rq1, ErtsRunQueue *rq2);
+ERTS_GLB_INLINE ErtsMessage *erts_alloc_message_heap_state(Process *pp,
+ erts_aint32_t *psp,
+ ErtsProcLocks *plp,
+ Uint sz,
+ Eterm **hpp,
+ ErlOffHeap **ohpp);
+ERTS_GLB_INLINE ErtsMessage *erts_alloc_message_heap(Process *pp,
+ ErtsProcLocks *plp,
+ Uint sz,
+ Eterm **hpp,
+ ErlOffHeap **ohpp);
+
+ERTS_GLB_INLINE void erts_shrink_message_heap(ErtsMessage **msgpp, Process *pp,
+ Eterm *start_hp, Eterm *used_hp, Eterm *end_hp,
+ Eterm *brefs, Uint brefs_size);
+
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
ERTS_GLB_INLINE
@@ -2258,6 +2308,63 @@ erts_smp_runqs_unlock(ErtsRunQueue *rq1, ErtsRunQueue *rq2)
#endif
}
+ERTS_GLB_INLINE ErtsMessage *
+erts_alloc_message_heap_state(Process *pp,
+ erts_aint32_t *psp,
+ ErtsProcLocks *plp,
+ Uint sz,
+ Eterm **hpp,
+ ErlOffHeap **ohpp)
+{
+ int on_heap;
+
+ if ((*psp) & ERTS_PSFLG_OFF_HEAP_MSGQ) {
+ ErtsMessage *mp = erts_alloc_message(sz, hpp);
+ *ohpp = sz == 0 ? NULL : &mp->hfrag.off_heap;
+ return mp;
+ }
+
+ return erts_try_alloc_message_on_heap(pp, psp, plp, sz, hpp, ohpp, &on_heap);
+}
+
+ERTS_GLB_INLINE ErtsMessage *
+erts_alloc_message_heap(Process *pp,
+ ErtsProcLocks *plp,
+ Uint sz,
+ Eterm **hpp,
+ ErlOffHeap **ohpp)
+{
+ erts_aint32_t state = erts_smp_atomic32_read_nob(&pp->state);
+ return erts_alloc_message_heap_state(pp, &state, plp, sz, hpp, ohpp);
+}
+
+ERTS_GLB_INLINE void
+erts_shrink_message_heap(ErtsMessage **msgpp, Process *pp,
+ Eterm *start_hp, Eterm *used_hp, Eterm *end_hp,
+ Eterm *brefs, Uint brefs_size)
+{
+ ASSERT(start_hp <= used_hp && used_hp <= end_hp);
+ if ((*msgpp)->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ *msgpp = erts_shrink_message(*msgpp, used_hp - start_hp,
+ brefs, brefs_size);
+ else if (!(*msgpp)->data.attached) {
+ ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN
+ & erts_proc_lc_my_proc_locks(pp));
+ HRelease(pp, end_hp, used_hp);
+ }
+ else {
+ ErlHeapFragment *hfrag = (*msgpp)->data.heap_frag;
+ if (start_hp != used_hp)
+ hfrag = erts_resize_message_buffer(hfrag, used_hp - start_hp,
+ brefs, brefs_size);
+ else {
+ free_message_buffer(hfrag);
+ hfrag = NULL;
+ }
+ (*msgpp)->data.heap_frag = hfrag;
+ }
+}
+
#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
ERTS_GLB_INLINE ErtsAtomCacheMap *erts_get_atom_cache_map(Process *c_p);
diff --git a/erts/emulator/beam/erl_process_dict.c b/erts/emulator/beam/erl_process_dict.c
index 3253ee6b70..487b944fc0 100644
--- a/erts/emulator/beam/erl_process_dict.c
+++ b/erts/emulator/beam/erl_process_dict.c
@@ -51,16 +51,19 @@
#define INITIAL_SIZE (erts_pd_initial_size)
/* Hash utility macros */
-#define HASH_RANGE(PDict) ((PDict)->homeSize + (PDict)->splitPosition)
+#define HASH_RANGE(PDict) ((PDict)->usedSlots)
-#define MAKE_HASH(Term) \
-((is_small(Term)) ? unsigned_val(Term) : \
- ((is_atom(Term)) ? \
- (atom_tab(atom_val(term))->slot.bucket.hvalue) : \
- make_hash2(Term)))
+#define MAKE_HASH(Term) \
+ ((is_small(Term)) ? unsigned_val(Term) : \
+ ((is_atom(Term)) ? \
+ (atom_tab(atom_val(Term))->slot.bucket.hvalue) : \
+ make_internal_hash(Term)))
#define PD_SZ2BYTES(Sz) (sizeof(ProcDict) + ((Sz) - 1)*sizeof(Eterm))
+#define pd_hash_value(Pdict, Key) \
+ pd_hash_value_to_ix(Pdict, MAKE_HASH((Key)))
+
/* Memory allocation macros */
#define PD_ALLOC(Sz) \
erts_alloc(ERTS_ALC_T_PROC_DICT, (Sz))
@@ -74,14 +77,19 @@
#define TCDR(Term) CDR(list_val(Term))
/* Array access macro */
-#define ARRAY_GET(PDict, Index) (((PDict)->size > (Index)) ? \
- (PDict)->data[Index] : NIL)
+#define ARRAY_GET(PDict, Index) (ASSERT((Index) < (PDict)->arraySize), \
+ (PDict)->data[Index])
+#define ARRAY_PUT(PDict, Index, Val) (ASSERT((Index) < (PDict)->arraySize), \
+ (PDict)->data[Index] = (Val))
+
+#define IS_POW2(X) ((X) && !((X) & ((X)-1)))
/*
* Forward decalarations
*/
static void pd_hash_erase(Process *p, Eterm id, Eterm *ret);
static void pd_hash_erase_all(Process *p);
+static Eterm pd_hash_get_with_hval(Process *p, Eterm bucket, Eterm id);
static Eterm pd_hash_get_keys(Process *p, Eterm value);
static Eterm pd_hash_get_all_keys(Process *p, ProcDict *pd);
static Eterm pd_hash_get_all(Process *p, ProcDict *pd);
@@ -91,9 +99,9 @@ static void shrink(Process *p, Eterm* ret);
static void grow(Process *p);
static void array_shrink(ProcDict **ppd, unsigned int need);
-static Eterm array_put(ProcDict **ppdict, unsigned int ndx, Eterm term);
+static void ensure_array_size(ProcDict**, unsigned int size);
-static unsigned int pd_hash_value(ProcDict *pdict, Eterm term);
+static unsigned int pd_hash_value_to_ix(ProcDict *pdict, Uint32 hx);
static unsigned int next_array_size(unsigned int need);
/*
@@ -134,6 +142,16 @@ static void pd_check(ProcDict *pd);
** External interface
*/
+int
+erts_pd_set_initial_size(int size)
+{
+ if (size <= 0)
+ return 0;
+
+ erts_pd_initial_size = 1 << erts_fit_in_bits_uint(size-1);
+ return 1;
+}
+
/*
* Called from break handler
*/
@@ -146,9 +164,9 @@ erts_dictionary_dump(int to, void *to_arg, ProcDict *pd)
/*PD_CHECK(pd);*/
if (pd == NULL)
return;
- erts_print(to, to_arg, "(size = %d, used = %d, homeSize = %d, "
+ erts_print(to, to_arg, "(size = %d, usedSlots = %d, "
"splitPosition = %d, numElements = %d)\n",
- pd->size, pd->used, pd->homeSize,
+ pd->arraySize, pd->usedSlots,
pd->splitPosition, (unsigned int) pd->numElements);
for (i = 0; i < HASH_RANGE(pd); ++i) {
erts_print(to, to_arg, "%d: %T\n", i, ARRAY_GET(pd, i));
@@ -203,7 +221,7 @@ erts_dicts_mem_size(Process *p)
{
Uint size = 0;
if (p->dictionary)
- size += PD_SZ2BYTES(p->dictionary->size);
+ size += PD_SZ2BYTES(p->dictionary->arraySize);
return size;
}
@@ -345,7 +363,7 @@ static void pd_hash_erase(Process *p, Eterm id, Eterm *ret)
if (is_boxed(old)) { /* Tuple */
ASSERT(is_tuple(old));
if (EQ(tuple_val(old)[1], id)) {
- array_put(&(p->dictionary), hval, NIL);
+ ARRAY_PUT(p->dictionary, hval, NIL);
--(p->dictionary->numElements);
*ret = tuple_val(old)[2];
}
@@ -365,7 +383,7 @@ static void pd_hash_erase(Process *p, Eterm id, Eterm *ret)
old = ARRAY_GET(p->dictionary, hval);
ASSERT(is_list(old));
if (is_nil(TCDR(old))) {
- array_put(&p->dictionary, hval, TCAR(old));
+ ARRAY_PUT(p->dictionary, hval, TCAR(old));
}
} else if (is_not_nil(old)) {
#ifdef DEBUG
@@ -390,40 +408,56 @@ static void pd_hash_erase_all(Process *p)
}
}
+Eterm erts_pd_hash_get_with_hx(Process *p, Uint32 hx, Eterm id)
+{
+ unsigned int hval;
+ ProcDict *pd = p->dictionary;
+
+ ASSERT(hx == MAKE_HASH(id));
+ if (pd == NULL)
+ return am_undefined;
+ hval = pd_hash_value_to_ix(pd, hx);
+ return pd_hash_get_with_hval(p, ARRAY_GET(pd, hval), id);
+}
+
Eterm erts_pd_hash_get(Process *p, Eterm id)
{
unsigned int hval;
- Eterm tmp;
ProcDict *pd = p->dictionary;
if (pd == NULL)
return am_undefined;
hval = pd_hash_value(pd, id);
- tmp = ARRAY_GET(pd, hval);
- if (is_boxed(tmp)) { /* Tuple */
- ASSERT(is_tuple(tmp));
- if (EQ(tuple_val(tmp)[1], id)) {
- return tuple_val(tmp)[2];
+ return pd_hash_get_with_hval(p, ARRAY_GET(pd, hval), id);
+}
+
+Eterm pd_hash_get_with_hval(Process *p, Eterm bucket, Eterm id)
+{
+ if (is_boxed(bucket)) { /* Tuple */
+ ASSERT(is_tuple(bucket));
+ if (EQ(tuple_val(bucket)[1], id)) {
+ return tuple_val(bucket)[2];
}
- } else if (is_list(tmp)) {
- for (; tmp != NIL && !EQ(tuple_val(TCAR(tmp))[1], id); tmp = TCDR(tmp)) {
+ } else if (is_list(bucket)) {
+ for (; bucket != NIL && !EQ(tuple_val(TCAR(bucket))[1], id); bucket = TCDR(bucket)) {
;
}
- if (tmp != NIL) {
- return tuple_val(TCAR(tmp))[2];
+ if (bucket != NIL) {
+ return tuple_val(TCAR(bucket))[2];
}
- } else if (is_not_nil(tmp)) {
+ } else if (is_not_nil(bucket)) {
#ifdef DEBUG
erts_fprintf(stderr,
"Process dictionary for process %T is broken, trying to "
"display term found in line %d:\n"
- "%T\n", p->common.id, __LINE__, tmp);
+ "%T\n", p->common.id, __LINE__, bucket);
#endif
erts_exit(ERTS_ERROR_EXIT, "Damaged process dictionary found during get/1.");
}
return am_undefined;
}
+
#define PD_GET_TKEY(Dst,Src) \
do { \
ASSERT(is_tuple((Src))); \
@@ -549,8 +583,11 @@ static Eterm pd_hash_put(Process *p, Eterm id, Eterm value)
if (p->dictionary == NULL) {
/* Create it */
- array_put(&(p->dictionary), INITIAL_SIZE - 1, NIL);
- p->dictionary->homeSize = INITIAL_SIZE;
+ ensure_array_size(&p->dictionary, INITIAL_SIZE);
+ p->dictionary->usedSlots = INITIAL_SIZE;
+ p->dictionary->sizeMask = INITIAL_SIZE*2 - 1;
+ p->dictionary->splitPosition = 0;
+ p->dictionary->numElements = 0;
}
hval = pd_hash_value(p->dictionary, id);
old = ARRAY_GET(p->dictionary, hval);
@@ -583,7 +620,7 @@ static Eterm pd_hash_put(Process *p, Eterm id, Eterm value)
root[0] = id;
root[1] = value;
root[2] = old;
- BUMP_REDS(p, erts_garbage_collect(p, needed, root, 3));
+ erts_garbage_collect(p, needed, root, 3);
id = root[0];
value = root[1];
old = root[2];
@@ -602,19 +639,19 @@ static Eterm pd_hash_put(Process *p, Eterm id, Eterm value)
* Update the dictionary.
*/
if (is_nil(old)) {
- array_put(&(p->dictionary), hval, tpl);
+ ARRAY_PUT(p->dictionary, hval, tpl);
++(p->dictionary->numElements);
} else if (is_boxed(old)) {
ASSERT(is_tuple(old));
if (EQ(tuple_val(old)[1],id)) {
- array_put(&(p->dictionary), hval, tpl);
+ ARRAY_PUT(p->dictionary, hval, tpl);
return tuple_val(old)[2];
} else {
hp = HeapOnlyAlloc(p, 4);
tmp = CONS(hp, old, NIL);
hp += 2;
++(p->dictionary->numElements);
- array_put(&(p->dictionary), hval, CONS(hp, tpl, tmp));
+ ARRAY_PUT(p->dictionary, hval, CONS(hp, tpl, tmp));
hp += 2;
ASSERT(hp <= hp_limit);
}
@@ -624,7 +661,7 @@ static Eterm pd_hash_put(Process *p, Eterm id, Eterm value)
* New key. Simply prepend the tuple to the beginning of the list.
*/
hp = HeapOnlyAlloc(p, 2);
- array_put(&(p->dictionary), hval, CONS(hp, tpl, old));
+ ARRAY_PUT(p->dictionary, hval, CONS(hp, tpl, old));
hp += 2;
ASSERT(hp <= hp_limit);
++(p->dictionary->numElements);
@@ -659,7 +696,7 @@ static Eterm pd_hash_put(Process *p, Eterm id, Eterm value)
nlist = CONS(hp, tpl, nlist);
hp += 2;
ASSERT(hp <= hp_limit);
- array_put(&(p->dictionary), hval, nlist);
+ ARRAY_PUT(p->dictionary, hval, nlist);
return tuple_val(TCAR(tmp))[2];
}
} else {
@@ -684,6 +721,7 @@ static Eterm pd_hash_put(Process *p, Eterm id, Eterm value)
static void shrink(Process *p, Eterm* ret)
{
+ ProcDict *pd = p->dictionary;
unsigned int range = HASH_RANGE(p->dictionary);
unsigned int steps = (range*3) / 10;
Eterm hi, lo, tmp;
@@ -698,25 +736,26 @@ static void shrink(Process *p, Eterm* ret)
}
for (i = 0; i < steps; ++i) {
- ProcDict *pd = p->dictionary;
if (pd->splitPosition == 0) {
- pd->homeSize /= 2;
- pd->splitPosition = pd->homeSize;
+ ASSERT(IS_POW2(pd->usedSlots));
+ pd->sizeMask = pd->usedSlots - 1;
+ pd->splitPosition = pd->usedSlots / 2;
}
--(pd->splitPosition);
- hi = ARRAY_GET(pd, (pd->splitPosition + pd->homeSize));
+ /* Must wait to decrement 'usedSlots' for GC rootset below */
+ hi = ARRAY_GET(pd, pd->usedSlots - 1);
lo = ARRAY_GET(pd, pd->splitPosition);
if (hi != NIL) {
if (lo == NIL) {
- array_put(&(p->dictionary), pd->splitPosition, hi);
+ ARRAY_PUT(pd, pd->splitPosition, hi);
} else {
- int needed = 4;
+ Sint needed = 4;
if (is_list(hi) && is_list(lo)) {
needed = 2*erts_list_length(hi);
}
if (HeapWordsLeft(p) < needed) {
- BUMP_REDS(p, erts_garbage_collect(p, needed, ret, 1));
- hi = pd->data[(pd->splitPosition + pd->homeSize)];
+ erts_garbage_collect(p, needed, ret, 1);
+ hi = pd->data[pd->usedSlots - 1];
lo = pd->data[pd->splitPosition];
}
#ifdef DEBUG
@@ -727,13 +766,13 @@ static void shrink(Process *p, Eterm* ret)
hp = HeapOnlyAlloc(p, 4);
tmp = CONS(hp, hi, NIL);
hp += 2;
- array_put(&(p->dictionary), pd->splitPosition,
+ ARRAY_PUT(pd, pd->splitPosition,
CONS(hp,lo,tmp));
hp += 2;
ASSERT(hp <= hp_limit);
} else { /* hi is a list */
hp = HeapOnlyAlloc(p, 2);
- array_put(&(p->dictionary), pd->splitPosition,
+ ARRAY_PUT(pd, pd->splitPosition,
CONS(hp, lo, hi));
hp += 2;
ASSERT(hp <= hp_limit);
@@ -741,7 +780,7 @@ static void shrink(Process *p, Eterm* ret)
} else { /* lo is a list */
if (is_tuple(hi)) {
hp = HeapOnlyAlloc(p, 2);
- array_put(&(p->dictionary), pd->splitPosition,
+ ARRAY_PUT(pd, pd->splitPosition,
CONS(hp, hi, lo));
hp += 2;
ASSERT(hp <= hp_limit);
@@ -753,14 +792,15 @@ static void shrink(Process *p, Eterm* ret)
hp += 2;
}
ASSERT(hp <= hp_limit);
- array_put(&(p->dictionary), pd->splitPosition, lo);
+ ARRAY_PUT(pd, pd->splitPosition, lo);
}
}
}
}
- array_put(&(p->dictionary), (pd->splitPosition + pd->homeSize), NIL);
+ --pd->usedSlots;
+ ARRAY_PUT(pd, pd->usedSlots, NIL);
}
- if (HASH_RANGE(p->dictionary) <= (p->dictionary->size / 4)) {
+ if (HASH_RANGE(p->dictionary) <= (p->dictionary->arraySize / 4)) {
array_shrink(&(p->dictionary), (HASH_RANGE(p->dictionary) * 3) / 2);
}
}
@@ -768,14 +808,14 @@ static void shrink(Process *p, Eterm* ret)
static void grow(Process *p)
{
unsigned int i,j;
- unsigned int steps = p->dictionary->homeSize / 5;
+ unsigned int steps = (p->dictionary->usedSlots / 4) & 0xf;
Eterm l1,l2;
Eterm l;
Eterm *hp;
unsigned int pos;
unsigned int homeSize;
- int needed = 0;
- ProcDict *pd;
+ Sint needed = 0;
+ ProcDict *pd = p->dictionary;
#ifdef DEBUG
Eterm *hp_limit;
#endif
@@ -784,18 +824,20 @@ static void grow(Process *p)
if (steps == 0)
steps = 1;
/* Dont grow over MAX_HASH */
- if ((MAX_HASH - steps) <= HASH_RANGE(p->dictionary)) {
+ if ((MAX_HASH - steps) <= HASH_RANGE(pd)) {
return;
}
+ ensure_array_size(&p->dictionary, HASH_RANGE(pd) + steps);
+ pd = p->dictionary;
+
/*
* Calculate total number of heap words needed, and garbage collect
* if necessary.
*/
- pd = p->dictionary;
pos = pd->splitPosition;
- homeSize = pd->homeSize;
+ homeSize = pd->usedSlots - pd->splitPosition;
for (i = 0; i < steps; ++i) {
if (pos == homeSize) {
homeSize *= 2;
@@ -811,7 +853,7 @@ static void grow(Process *p)
}
}
if (HeapWordsLeft(p) < needed) {
- BUMP_REDS(p, erts_garbage_collect(p, needed, 0, 0));
+ erts_garbage_collect(p, needed, 0, 0);
}
#ifdef DEBUG
hp_limit = p->htop + needed;
@@ -820,21 +862,22 @@ static void grow(Process *p)
/*
* Now grow.
*/
-
+ homeSize = pd->usedSlots - pd->splitPosition;
for (i = 0; i < steps; ++i) {
- ProcDict *pd = p->dictionary;
- if (pd->splitPosition == pd->homeSize) {
- pd->homeSize *= 2;
- pd->splitPosition = 0;
+ if (pd->splitPosition == homeSize) {
+ homeSize *= 2;
+ pd->sizeMask = homeSize*2 - 1;
+ pd->splitPosition = 0;
}
pos = pd->splitPosition;
++pd->splitPosition; /* For the hashes */
+ ++pd->usedSlots;
+ ASSERT(pos + homeSize == pd->usedSlots - 1);
l = ARRAY_GET(pd, pos);
if (is_tuple(l)) {
if (pd_hash_value(pd, tuple_val(l)[1]) != pos) {
- array_put(&(p->dictionary), pos +
- p->dictionary->homeSize, l);
- array_put(&(p->dictionary), pos, NIL);
+ ARRAY_PUT(pd, pos + homeSize, l);
+ ARRAY_PUT(pd, pos, NIL);
}
} else {
l2 = NIL;
@@ -856,10 +899,8 @@ static void grow(Process *p)
if (l2 != NIL && TCDR(l2) == NIL)
l2 = TCAR(l2);
ASSERT(hp <= hp_limit);
- /* After array_put pd is no longer valid */
- array_put(&(p->dictionary), pos, l1);
- array_put(&(p->dictionary), pos +
- p->dictionary->homeSize, l2);
+ ARRAY_PUT(pd, pos, l1);
+ ARRAY_PUT(pd, pos + homeSize, l2);
}
}
@@ -876,73 +917,65 @@ static void array_shrink(ProcDict **ppd, unsigned int need)
{
unsigned int siz = next_array_size(need);
- HDEBUGF(("array_shrink: size = %d, used = %d, need = %d",
- (*ppd)->size, (*ppd)->used, need));
+ HDEBUGF(("array_shrink: size = %d, need = %d",
+ (*ppd)->arraySize, need));
- if (siz > (*ppd)->size)
+ if (siz >= (*ppd)->arraySize)
return; /* Only shrink */
*ppd = PD_REALLOC(((void *) *ppd),
- PD_SZ2BYTES((*ppd)->size),
+ PD_SZ2BYTES((*ppd)->arraySize),
PD_SZ2BYTES(siz));
- (*ppd)->size = siz;
- if ((*ppd)->size < (*ppd)->used)
- (*ppd)->used = (*ppd)->size;
+ (*ppd)->arraySize = siz;
}
-static Eterm array_put(ProcDict **ppdict, unsigned int ndx, Eterm term)
+static void ensure_array_size(ProcDict **ppdict, unsigned int size)
{
+ ProcDict *pd = *ppdict;
unsigned int i;
- Eterm ret;
- if (*ppdict == NULL) {
- Uint siz = next_array_size(ndx+1);
- ProcDict *p;
- p = PD_ALLOC(PD_SZ2BYTES(siz));
+ if (pd == NULL) {
+ Uint siz = next_array_size(size);
+
+ pd = PD_ALLOC(PD_SZ2BYTES(siz));
for (i = 0; i < siz; ++i)
- p->data[i] = NIL;
- p->size = siz;
- p->homeSize = p->splitPosition = p->numElements = p->used = 0;
- *ppdict = p;
- } else if (ndx >= (*ppdict)->size) {
- Uint osize = (*ppdict)->size;
- Uint nsize = next_array_size(ndx+1);
- *ppdict = PD_REALLOC(((void *) *ppdict),
+ pd->data[i] = NIL;
+ pd->arraySize = siz;
+ *ppdict = pd;
+ } else if (size > pd->arraySize) {
+ Uint osize = pd->arraySize;
+ Uint nsize = next_array_size(size);
+ pd = PD_REALLOC(((void *) pd),
PD_SZ2BYTES(osize),
PD_SZ2BYTES(nsize));
for (i = osize; i < nsize; ++i)
- (*ppdict)->data[i] = NIL;
- (*ppdict)->size = nsize;
+ pd->data[i] = NIL;
+ pd->arraySize = nsize;
+ *ppdict = pd;
}
- ret = (*ppdict)->data[ndx];
- (*ppdict)->data[ndx] = term;
- if ((ndx + 1) > (*ppdict)->used)
- (*ppdict)->used = ndx + 1;
-#ifdef HARDDEBUG
- HDEBUGF(("array_put: (*ppdict)->size = %d, (*ppdict)->used = %d, ndx = %d",
- (*ppdict)->size, (*ppdict)->used, ndx));
- erts_fprintf(stderr, "%T", term);
-#endif /* HARDDEBUG */
- return ret;
}
/*
** Basic utilities
*/
-static unsigned int pd_hash_value(ProcDict *pdict, Eterm term)
+static unsigned int pd_hash_value_to_ix(ProcDict *pdict, Uint32 hx)
{
- Uint hash, high;
+ Uint high;
- hash = MAKE_HASH(term);
- high = hash % (pdict->homeSize*2);
+ ASSERT(IS_POW2(pdict->sizeMask+1));
+ ASSERT(HASH_RANGE(pdict) >= (pdict->sizeMask >> 1));
+ ASSERT(HASH_RANGE(pdict) <= (pdict->sizeMask + 1));
+
+ high = hx & pdict->sizeMask;
if (high >= HASH_RANGE(pdict))
- return hash % pdict->homeSize;
+ return hx & (pdict->sizeMask >> 1);
return high;
}
+
static unsigned int next_array_size(unsigned int need)
{
static unsigned int tab[] =
@@ -1002,24 +1035,28 @@ static unsigned int next_array_size(unsigned int need)
static void pd_check(ProcDict *pd)
{
unsigned int i;
+ unsigned int used;
Uint num;
if (pd == NULL)
return;
- ASSERT(pd->size >= pd->used);
+ used = HASH_RANGE(pd);
+ ASSERT(pd->arraySize >= used);
ASSERT(HASH_RANGE(pd) <= MAX_HASH);
- for (i = 0, num = 0; i < pd->used; ++i) {
+ for (i = 0, num = 0; i < used; ++i) {
Eterm t = pd->data[i];
if (is_nil(t)) {
continue;
} else if (is_tuple(t)) {
++num;
ASSERT(arityval(*tuple_val(t)) == 2);
+ ASSERT(pd_hash_value(pd, tuple_val(t)[1]) == i);
continue;
} else if (is_list(t)) {
while (t != NIL) {
++num;
ASSERT(is_tuple(TCAR(t)));
ASSERT(arityval(*(tuple_val(TCAR(t)))) == 2);
+ ASSERT(pd_hash_value(pd, tuple_val(TCAR(t))[1]) == i);
t = TCDR(t);
}
continue;
@@ -1030,7 +1067,7 @@ static void pd_check(ProcDict *pd)
}
}
ASSERT(num == pd->numElements);
- ASSERT(pd->splitPosition <= pd->homeSize);
+ ASSERT(pd->usedSlots >= pd->splitPosition*2);
}
#endif /* DEBUG */
diff --git a/erts/emulator/beam/erl_process_dict.h b/erts/emulator/beam/erl_process_dict.h
index cc53800eb5..dac214c8a1 100644
--- a/erts/emulator/beam/erl_process_dict.h
+++ b/erts/emulator/beam/erl_process_dict.h
@@ -23,14 +23,18 @@
#include "sys.h"
typedef struct proc_dict {
- unsigned int size;
- unsigned int used;
- unsigned int homeSize;
+ unsigned int sizeMask;
+ unsigned int usedSlots;
+ unsigned int arraySize;
unsigned int splitPosition;
Uint numElements;
Eterm data[1]; /* The beginning of an array of erlang terms */
} ProcDict;
+#define ERTS_PD_START(PD) ((PD)->data)
+#define ERTS_PD_SIZE(PD) ((PD)->usedSlots)
+
+int erts_pd_set_initial_size(int size);
Uint erts_dicts_mem_size(struct process *p);
void erts_erase_dicts(struct process *p);
void erts_dictionary_dump(int to, void *to_arg, ProcDict *pd);
@@ -39,5 +43,6 @@ void erts_deep_dictionary_dump(int to, void *to_arg,
Eterm erts_dictionary_copy(struct process *p, ProcDict *pd);
Eterm erts_pd_hash_get(struct process *p, Eterm id);
+Eterm erts_pd_hash_get_with_hx(Process *p, Uint32 hx, Eterm id);
#endif
diff --git a/erts/emulator/beam/erl_process_dump.c b/erts/emulator/beam/erl_process_dump.c
index 25f0b1ed38..39c36ee7a9 100644
--- a/erts/emulator/beam/erl_process_dump.c
+++ b/erts/emulator/beam/erl_process_dump.c
@@ -78,13 +78,14 @@ erts_deep_process_dump(int to, void *to_arg)
dump_binaries(to, to_arg, all_binaries);
}
-Uint erts_process_memory(Process *p) {
- ErlMessage *mp;
+Uint erts_process_memory(Process *p, int incl_msg_inq) {
+ ErtsMessage *mp;
Uint size = 0;
struct saved_calls *scb;
size += sizeof(Process);
- ERTS_SMP_MSGQ_MV_INQ2PRIVQ(p);
+ if (incl_msg_inq)
+ ERTS_SMP_MSGQ_MV_INQ2PRIVQ(p);
erts_doforall_links(ERTS_P_LINKS(p), &erts_one_link_size, &size);
erts_doforall_monitors(ERTS_P_MONITORS(p), &erts_one_mon_size, &size);
@@ -92,7 +93,7 @@ Uint erts_process_memory(Process *p) {
if (p->old_hend && p->old_heap)
size += (p->old_hend - p->old_heap) * sizeof(Eterm);
- size += p->msg.len * sizeof(ErlMessage);
+ size += p->msg.len * sizeof(ErtsMessage);
for (mp = p->msg.first; mp; mp = mp->next)
if (mp->data.attached)
@@ -119,7 +120,7 @@ static void
dump_process_info(int to, void *to_arg, Process *p)
{
Eterm* sp;
- ErlMessage* mp;
+ ErtsMessage* mp;
int yreg = -1;
ERTS_SMP_MSGQ_MV_INQ2PRIVQ(p);
@@ -365,7 +366,7 @@ heap_dump(int to, void *to_arg, Eterm x)
while (x != OUR_NIL) {
if (is_CP(x)) {
- next = (Eterm *) EXPAND_POINTER(x);
+ next = (Eterm *) x;
} else if (is_list(x)) {
ptr = list_val(x);
if (ptr[0] != OUR_NIL) {
@@ -378,7 +379,7 @@ heap_dump(int to, void *to_arg, Eterm x)
ptr[1] = make_small(0);
}
x = ptr[0];
- ptr[0] = (Eterm) COMPRESS_POINTER(next);
+ ptr[0] = (Eterm) next;
next = ptr + 1;
continue;
}
@@ -408,7 +409,7 @@ heap_dump(int to, void *to_arg, Eterm x)
ptr[0] = OUR_NIL;
} else {
x = ptr[arity];
- ptr[0] = (Eterm) COMPRESS_POINTER(next);
+ ptr[0] = (Eterm) next;
next = ptr + arity - 1;
continue;
}
@@ -617,7 +618,7 @@ erts_dump_extended_process_state(int to, void *to_arg, erts_aint32_t psflg) {
if (psflg)
erts_print(to, to_arg, " | ");
- for (i = 0; i < ERTS_PSFLG_MAX && psflg; i++) {
+ for (i = 0; i <= ERTS_PSFLG_MAX && psflg; i++) {
erts_aint32_t chk = (1 << i);
if (psflg & chk) {
switch (chk) {
@@ -657,16 +658,16 @@ erts_dump_extended_process_state(int to, void *to_arg, erts_aint32_t psflg) {
erts_print(to, to_arg, "PROXY"); break;
case ERTS_PSFLG_DELAYED_SYS:
erts_print(to, to_arg, "DELAYED_SYS"); break;
-#ifdef ERTS_DIRTY_SCHEDULERS
+ case ERTS_PSFLG_OFF_HEAP_MSGQ:
+ erts_print(to, to_arg, "OFF_HEAP_MSGQ"); break;
+ case ERTS_PSFLG_ON_HEAP_MSGQ:
+ erts_print(to, to_arg, "ON_HEAP_MSGQ"); break;
case ERTS_PSFLG_DIRTY_CPU_PROC:
erts_print(to, to_arg, "DIRTY_CPU_PROC"); break;
case ERTS_PSFLG_DIRTY_IO_PROC:
erts_print(to, to_arg, "DIRTY_IO_PROC"); break;
- case ERTS_PSFLG_DIRTY_CPU_PROC_IN_Q:
- erts_print(to, to_arg, "DIRTY_CPU_PROC_IN_Q"); break;
- case ERTS_PSFLG_DIRTY_IO_PROC_IN_Q:
- erts_print(to, to_arg, "DIRTY_IO_PROC_IN_Q"); break;
-#endif
+ case ERTS_PSFLG_DIRTY_ACTIVE_SYS:
+ erts_print(to, to_arg, "DIRTY_ACTIVE_SYS"); break;
default:
erts_print(to, to_arg, "UNKNOWN(%d)", chk); break;
}
diff --git a/erts/emulator/beam/erl_term.c b/erts/emulator/beam/erl_term.c
index bae3385d3f..d2343912b4 100644
--- a/erts/emulator/beam/erl_term.c
+++ b/erts/emulator/beam/erl_term.c
@@ -28,6 +28,37 @@
#include <stdlib.h>
#include <stdio.h>
+void
+erts_set_literal_tag(Eterm *term, Eterm *hp_start, Eterm hsz)
+{
+#ifdef TAG_LITERAL_PTR
+ Eterm *hp_end, *hp;
+
+ hp_end = hp_start + hsz;
+ hp = hp_start;
+
+ while (hp < hp_end) {
+ switch (primary_tag(*hp)) {
+ case TAG_PRIMARY_BOXED:
+ case TAG_PRIMARY_LIST:
+ *hp |= TAG_LITERAL_PTR;
+ break;
+ case TAG_PRIMARY_HEADER:
+ if (header_is_thing(*hp)) {
+ hp += thing_arityval(*hp);
+ }
+ break;
+ default:
+ break;
+ }
+
+ hp++;
+ }
+ if (is_boxed(*term) || is_list(*term))
+ *term |= TAG_LITERAL_PTR;
+#endif
+}
+
__decl_noreturn static void __noreturn
et_abort(const char *expr, const char *file, unsigned line)
{
@@ -174,9 +205,7 @@ ET_DEFINE_CHECKED(Uint,external_thing_data_words,ExternalThing*,is_thing_ptr);
ET_DEFINE_CHECKED(Eterm,make_cp,UWord *,_is_taggable_pointer);
ET_DEFINE_CHECKED(UWord *,cp_val,Eterm,is_CP);
ET_DEFINE_CHECKED(Uint,catch_val,Eterm,is_catch);
-ET_DEFINE_CHECKED(Uint,x_reg_offset,Uint,_is_xreg);
-ET_DEFINE_CHECKED(Uint,y_reg_offset,Uint,_is_yreg);
-ET_DEFINE_CHECKED(Uint,x_reg_index,Uint,_is_xreg);
-ET_DEFINE_CHECKED(Uint,y_reg_index,Uint,_is_yreg);
+ET_DEFINE_CHECKED(Uint,loader_x_reg_index,Uint,_is_loader_x_reg);
+ET_DEFINE_CHECKED(Uint,loader_y_reg_index,Uint,_is_loader_y_reg);
#endif /* ET_DEBUG */
diff --git a/erts/emulator/beam/erl_term.h b/erts/emulator/beam/erl_term.h
index d5e91d80d9..2b28762db5 100644
--- a/erts/emulator/beam/erl_term.h
+++ b/erts/emulator/beam/erl_term.h
@@ -21,34 +21,10 @@
#ifndef __ERL_TERM_H
#define __ERL_TERM_H
-#include "sys.h" /* defines HALFWORD_HEAP */
+#include "erl_mmap.h"
typedef UWord Wterm; /* Full word terms */
-#if HALFWORD_HEAP
-# define HEAP_ON_C_STACK 0
-# if HALFWORD_ASSERT
-# ifdef ET_DEBUG
-# undef ET_DEBUG
-# endif
-# define ET_DEBUG 1
-# endif
-# if 1
-# define CHECK_POINTER_MASK 0xFFFFFFFF00000000UL
-# define COMPRESS_POINTER(APointer) ((Eterm) (UWord) (APointer))
-# define EXPAND_POINTER(AnEterm) ((UWord) (AnEterm))
-# else
-# define CHECK_POINTER_MASK 0x0UL
-# define COMPRESS_POINTER(AnUint) (AnUint)
-# define EXPAND_POINTER(APointer) (APointer)
-# endif
-#else
-# define HEAP_ON_C_STACK 1
-# define CHECK_POINTER_MASK 0x0UL
-# define COMPRESS_POINTER(AnUint) (AnUint)
-# define EXPAND_POINTER(APointer) (APointer)
-#endif
-
struct erl_node_; /* Declared in erl_node_tables.h */
/*
@@ -74,6 +50,24 @@ struct erl_node_; /* Declared in erl_node_tables.h */
#define _ET_APPLY(F,X) _unchecked_##F(X)
#endif
+#if defined(ARCH_64)
+# define TAG_PTR_MASK__ 0x7
+# if !defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+# ifdef HIPE
+# error Hipe on 64-bit needs a real mmap as it does not support the literal tag
+# endif
+# define TAG_LITERAL_PTR 0x4
+# else
+# undef TAG_LITERAL_PTR
+# endif
+#elif defined(ARCH_32)
+# define TAG_PTR_MASK__ 0x3
+# undef TAG_LITERAL_PTR
+#else
+# error Not supported arch
+#endif
+
+
#define _TAG_PRIMARY_SIZE 2
#define _TAG_PRIMARY_MASK 0x3
#define TAG_PRIMARY_HEADER 0x0
@@ -190,15 +184,13 @@ struct erl_node_; /* Declared in erl_node_tables.h */
/* boxed object access methods */
-#if HALFWORD_HEAP
-#define _is_taggable_pointer(x) (((UWord)(x) & (CHECK_POINTER_MASK | 0x3)) == 0)
-#define _boxed_precond(x) (is_boxed(x))
-#else
-#define _is_taggable_pointer(x) (((Uint)(x) & 0x3) == 0)
+
+#define _is_taggable_pointer(x) (((Uint)(x) & TAG_PTR_MASK__) == 0)
+
#define _boxed_precond(x) (is_boxed(x))
-#endif
-#define _is_aligned(x) (((Uint)(x) & 0x3) == 0)
-#define _unchecked_make_boxed(x) ((Uint) COMPRESS_POINTER(x) + TAG_PRIMARY_BOXED)
+
+#define _is_aligned(x) (((Uint)(x) & TAG_PTR_MASK__) == 0)
+#define _unchecked_make_boxed(x) ((Uint)(x) + TAG_PRIMARY_BOXED)
_ET_DECLARE_CHECKED(Eterm,make_boxed,const Eterm*)
#define make_boxed(x) _ET_APPLY(make_boxed,(x))
#if 1
@@ -209,12 +201,16 @@ _ET_DECLARE_CHECKED(int,is_boxed,Eterm)
#else
#define is_boxed(x) (((x) & _TAG_PRIMARY_MASK) == TAG_PRIMARY_BOXED)
#endif
-#define _unchecked_boxed_val(x) ((Eterm*) EXPAND_POINTER(((x) - TAG_PRIMARY_BOXED)))
+#ifdef TAG_LITERAL_PTR
+#define _unchecked_boxed_val(x) _unchecked_ptr_val(x)
+#else
+#define _unchecked_boxed_val(x) ((Eterm*) ((x) - TAG_PRIMARY_BOXED))
+#endif
_ET_DECLARE_CHECKED(Eterm*,boxed_val,Wterm)
#define boxed_val(x) _ET_APPLY(boxed_val,(x))
/* cons cell ("list") access methods */
-#define _unchecked_make_list(x) ((Uint) COMPRESS_POINTER(x) + TAG_PRIMARY_LIST)
+#define _unchecked_make_list(x) ((Uint)(x) + TAG_PRIMARY_LIST)
_ET_DECLARE_CHECKED(Eterm,make_list,const Eterm*)
#define make_list(x) _ET_APPLY(make_list,(x))
#if 1
@@ -226,12 +222,12 @@ _ET_DECLARE_CHECKED(int,is_not_list,Eterm)
#define is_list(x) (((x) & _TAG_PRIMARY_MASK) == TAG_PRIMARY_LIST)
#define is_not_list(x) (!is_list((x)))
#endif
-#if HALFWORD_HEAP
#define _list_precond(x) (is_list(x))
+#ifdef TAG_LITERAL_PTR
+#define _unchecked_list_val(x) _unchecked_ptr_val(x)
#else
-#define _list_precond(x) (is_list(x))
+#define _unchecked_list_val(x) ((Eterm*) ((x) - TAG_PRIMARY_LIST))
#endif
-#define _unchecked_list_val(x) ((Eterm*) EXPAND_POINTER((x) - TAG_PRIMARY_LIST))
_ET_DECLARE_CHECKED(Eterm*,list_val,Wterm)
#define list_val(x) _ET_APPLY(list_val,(x))
@@ -242,15 +238,22 @@ _ET_DECLARE_CHECKED(Eterm*,list_val,Wterm)
#define CDR(x) ((x)[1])
/* generic tagged pointer (boxed or list) access methods */
-#define _unchecked_ptr_val(x) ((Eterm*) EXPAND_POINTER((x) & ~((Uint) 0x3)))
+#define _unchecked_ptr_val(x) ((Eterm*) ((x) & ~((Uint) TAG_PTR_MASK__)))
#define ptr_val(x) _unchecked_ptr_val((x)) /*XXX*/
#define _unchecked_offset_ptr(x,offs) ((x)+((offs)*sizeof(Eterm)))
#define offset_ptr(x,offs) _unchecked_offset_ptr(x,offs) /*XXX*/
#define _unchecked_byte_offset_ptr(x,byte_offs) ((x)+(offs))
#define byte_offset_ptr(x,offs) _unchecked_byte_offset_ptr(x,offs) /*XXX*/
+#ifdef TAG_LITERAL_PTR
+#define _unchecked_is_not_literal_ptr(x) (!((x) & TAG_LITERAL_PTR))
+#define is_not_literal_ptr(x) _unchecked_is_not_literal_ptr((x)) /*XXX*/
+#define is_literal_ptr(x) (!is_not_literal_ptr((x))) /*XXX*/
+#endif
+
+
/* fixnum ("small") access methods */
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
#define SMALL_BITS (64-4)
#define SMALL_DIGITS (17)
#else
@@ -396,11 +399,7 @@ _ET_DECLARE_CHECKED(Eterm*,fun_val,Wterm)
_ET_DECLARE_CHECKED(Eterm*,export_val,Wterm)
#define export_val(x) _ET_APPLY(export_val,(x))
#define is_export_header(x) ((x) == HEADER_EXPORT)
-#if HALFWORD_HEAP
-#define HEADER_EXPORT _make_header(2,_TAG_HEADER_EXPORT)
-#else
#define HEADER_EXPORT _make_header(1,_TAG_HEADER_EXPORT)
-#endif
/* bignum access methods */
#define make_pos_bignum_header(sz) _make_header((sz),_TAG_HEADER_POS_BIG)
@@ -424,7 +423,7 @@ _ET_DECLARE_CHECKED(Eterm*,big_val,Wterm)
#define big_val(x) _ET_APPLY(big_val,(x))
/* flonum ("float") access methods */
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
#define HEADER_FLONUM _make_header(1,_TAG_HEADER_FLOAT)
#else
#define HEADER_FLONUM _make_header(2,_TAG_HEADER_FLOAT)
@@ -445,12 +444,12 @@ typedef union float_def
byte fb[sizeof(ieee754_8)];
Uint16 fs[sizeof(ieee754_8) / sizeof(Uint16)];
Uint32 fw[sizeof(ieee754_8) / sizeof(Uint32)];
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
Uint fdw;
#endif
} FloatDef;
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
#define FLOAT_VAL_GET_DOUBLE(fval, f) (f).fdw = *((fval)+1)
@@ -727,7 +726,7 @@ _ET_DECLARE_CHECKED(struct erl_node_*,internal_port_node,Eterm)
#define ERTS_MAX_REF_NUMBERS 3
#define ERTS_REF_NUMBERS ERTS_MAX_REF_NUMBERS
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
# define ERTS_REF_WORDS (ERTS_REF_NUMBERS/2 + 1)
# define ERTS_REF_32BIT_WORDS (ERTS_REF_NUMBERS+1)
#else
@@ -749,7 +748,7 @@ typedef struct {
#define make_ref_thing_header(DW) \
_make_header((DW)+REF_THING_HEAD_SIZE-1,_TAG_HEADER_REF)
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
/*
* Ref layout on a 64-bit little endian machine:
@@ -1009,27 +1008,20 @@ _ET_DECLARE_CHECKED(struct erl_node_*,external_ref_node,Eterm)
#define MAP_HEADER_VAL(Hdr) (((Hdr) >> (_HEADER_ARITY_OFFS + MAP_HEADER_TAG_SZ + MAP_HEADER_ARITY_SZ)) & (0xffff))
#define make_hashmap(x) make_boxed((Eterm*)(x))
-#define make_hashmap_rel make_boxed_rel
#define is_hashmap(x) (is_boxed((x)) && is_hashmap_header(*boxed_val((x))))
#define is_not_hashmap(x) (!is_hashmap(x))
-#define is_hashmap_rel(RTERM,BASE) is_hashmap(rterm2wterm(RTERM,BASE))
#define is_hashmap_header(x) (((x) & (_HEADER_MAP_HASHMAP_HEAD_MASK)) == HAMT_SUBTAG_HEAD_ARRAY)
#define hashmap_val(x) _unchecked_boxed_val((x))
-#define hashmap_val_rel(RTERM, BASE) hashmap_val(rterm2wterm(RTERM, BASE))
#define make_flatmap(x) make_boxed((Eterm*)(x))
-#define make_flatmap_rel(x, BASE) make_boxed_rel((Eterm*)(x),(BASE))
#define is_flatmap(x) (is_boxed((x)) && is_flatmap_header(*boxed_val((x))))
-#define is_flatmap_rel(RTERM,BASE) is_flatmap(rterm2wterm(RTERM,BASE))
#define is_not_flatmap(x) (!is_flatmap((x)))
#define is_flatmap_header(x) (((x) & (_HEADER_MAP_SUBTAG_MASK)) == HAMT_SUBTAG_HEAD_FLATMAP)
#define flatmap_val(x) (_unchecked_boxed_val((x)))
-#define flatmap_val_rel(RTERM, BASE) flatmap_val(rterm2wterm(RTERM, BASE))
#define is_map_header(x) (((x) & (_TAG_HEADER_MASK)) == _TAG_HEADER_MAP)
#define is_map(x) (is_boxed((x)) && is_map_header(*boxed_val(x)))
#define is_not_map(x) (!is_map(x))
-#define is_map_rel(RTERM,BASE) is_map(rterm2wterm(RTERM,BASE))
/* number tests */
@@ -1048,14 +1040,14 @@ _ET_DECLARE_CHECKED(struct erl_node_*,external_ref_node,Eterm)
#error "fix yer arch, like"
#endif
-#define _unchecked_make_cp(x) ((Eterm) COMPRESS_POINTER(x))
+#define _unchecked_make_cp(x) ((Eterm)(x))
_ET_DECLARE_CHECKED(Eterm,make_cp,BeamInstr*)
#define make_cp(x) _ET_APPLY(make_cp,(x))
#define is_not_CP(x) ((x) & _CPMASK)
#define is_CP(x) (!is_not_CP(x))
-#define _unchecked_cp_val(x) ((BeamInstr*) EXPAND_POINTER(x))
+#define _unchecked_cp_val(x) ((BeamInstr*) (x))
_ET_DECLARE_CHECKED(BeamInstr*,cp_val,Eterm)
#define cp_val(x) _ET_APPLY(cp_val,(x))
@@ -1071,44 +1063,40 @@ _ET_DECLARE_CHECKED(Uint,catch_val,Eterm)
/*
* Overloaded tags.
*
- * SMALL = 15
- * ATOM/NIL=7
+ * In the loader, we want to tag a term in a way so that it can
+ * be any literal (atom/integer/float/tuple/list/binary) or a
+ * register.
*
- * Note that the two least significant bits in SMALL/ATOM/NIL always are 3;
- * thus, we can distinguish register from literals by looking at only these
- * two bits.
+ * We can achive that by overloading the PID and PORT tags to
+ * mean X and Y registers. That works because there are no
+ * pid or port literals.
*/
-#define X_REG_DEF 0
-#define Y_REG_DEF 1
-#define R_REG_DEF 2
+#define _LOADER_TAG_XREG _TAG_IMMED1_PID
+#define _LOADER_TAG_YREG _TAG_IMMED1_PORT
+#define _LOADER_TAG_SIZE _TAG_IMMED1_SIZE
+#define _LOADER_MASK _TAG_IMMED1_MASK
-#define beam_reg_tag(x) ((x) & 3)
+#define LOADER_X_REG _LOADER_TAG_XREG
+#define LOADER_Y_REG _LOADER_TAG_YREG
-#define make_rreg() R_REG_DEF
-#define make_xreg(ix) (((ix) * sizeof(Eterm)) | X_REG_DEF)
-#define make_yreg(ix) (((ix) * sizeof(Eterm)) | Y_REG_DEF)
+#define make_loader_x_reg(R) (((R) << _LOADER_TAG_SIZE) | _LOADER_TAG_XREG)
+#define make_loader_y_reg(R) (((R) << _LOADER_TAG_SIZE) | _LOADER_TAG_YREG)
-#define _is_xreg(x) (beam_reg_tag(x) == X_REG_DEF)
-#define _is_yreg(x) (beam_reg_tag(x) == Y_REG_DEF)
+#define loader_reg_index(R) ((R) >> _LOADER_TAG_SIZE)
-#define _unchecked_x_reg_offset(R) ((R) - X_REG_DEF)
-_ET_DECLARE_CHECKED(Uint,x_reg_offset,Uint)
-#define x_reg_offset(R) _ET_APPLY(x_reg_offset,(R))
+#define loader_tag(T) ((T) & _LOADER_MASK)
-#define _unchecked_y_reg_offset(R) ((R) - Y_REG_DEF)
-_ET_DECLARE_CHECKED(Uint,y_reg_offset,Uint)
-#define y_reg_offset(R) _ET_APPLY(y_reg_offset,(R))
+#define _is_loader_x_reg(x) (loader_tag(x) == _LOADER_TAG_XREG)
+#define _is_loader_y_reg(x) (loader_tag(x) == _LOADER_TAG_YREG)
-#define reg_index(R) ((R) / sizeof(Eterm))
+#define _unchecked_loader_x_reg_index(R) ((R) >> _LOADER_TAG_SIZE)
+_ET_DECLARE_CHECKED(Uint,loader_x_reg_index,Uint)
+#define loader_x_reg_index(R) _ET_APPLY(loader_x_reg_index,(R))
-#define _unchecked_x_reg_index(R) ((R) >> 2)
-_ET_DECLARE_CHECKED(Uint,x_reg_index,Uint)
-#define x_reg_index(R) _ET_APPLY(x_reg_index,(R))
-
-#define _unchecked_y_reg_index(R) ((R) >> 2)
-_ET_DECLARE_CHECKED(Uint,y_reg_index,Uint)
-#define y_reg_index(R) _ET_APPLY(y_reg_index,(R))
+#define _unchecked_loader_y_reg_index(R) ((R) >> _LOADER_TAG_SIZE)
+_ET_DECLARE_CHECKED(Uint,loader_y_reg_index,Uint)
+#define loader_y_reg_index(R) _ET_APPLY(loader_y_reg_index,(R))
/*
* Backwards compatibility definitions:
@@ -1160,82 +1148,9 @@ extern unsigned tag_val_def(Wterm);
#define FLOAT_BIG _NUMBER_CODE(FLOAT_DEF,BIG_DEF)
#define FLOAT_FLOAT _NUMBER_CODE(FLOAT_DEF,FLOAT_DEF)
-#if HALFWORD_HEAP
-#define ptr2rel(PTR,BASE) ((Eterm*)((char*)(PTR) - (char*)(BASE)))
-#define rterm2wterm(REL,BASE) ((Wterm)(REL) + (Wterm)(BASE))
-
-#else /* HALFWORD_HEAP */
-
-#define ptr2rel(PTR,BASE) (PTR)
-#define rterm2wterm(REL,BASE) (REL)
-
-#endif /* !HALFWORD_HEAP */
-
-#define make_list_rel(PTR, BASE) make_list(ptr2rel(PTR,BASE))
-#define make_boxed_rel(PTR, BASE) make_boxed(ptr2rel(PTR,BASE))
-#define make_fun_rel make_boxed_rel
-#define make_binary_rel make_boxed_rel
-#define make_tuple_rel make_boxed_rel
-#define make_external_rel make_boxed_rel
-#define make_internal_ref_rel make_boxed_rel
-#define make_big_rel make_boxed_rel
-
-#define binary_val_rel(RTERM, BASE) binary_val(rterm2wterm(RTERM, BASE))
-#define list_val_rel(RTERM, BASE) list_val(rterm2wterm(RTERM, BASE))
-#define boxed_val_rel(RTERM, BASE) boxed_val(rterm2wterm(RTERM, BASE))
-#define tuple_val_rel(RTERM, BASE) tuple_val(rterm2wterm(RTERM, BASE))
-#define export_val_rel(RTERM, BASE) export_val(rterm2wterm(RTERM, BASE))
-#define fun_val_rel(RTERM, BASE) fun_val(rterm2wterm(RTERM, BASE))
-#define big_val_rel(RTERM,BASE) big_val(rterm2wterm(RTERM,BASE))
-#define float_val_rel(RTERM,BASE) float_val(rterm2wterm(RTERM,BASE))
-#define internal_ref_val_rel(RTERM,BASE) internal_ref_val(rterm2wterm(RTERM,BASE))
-
-#define external_thing_ptr_rel(RTERM, BASE) external_thing_ptr(rterm2wterm(RTERM, BASE))
-#define external_data_words_rel(RTERM,BASE) external_data_words(rterm2wterm(RTERM,BASE))
-
-#define external_port_node_rel(RTERM,BASE) external_port_node(rterm2wterm(RTERM,BASE))
-#define external_port_data_rel(RTERM,BASE) external_port_data(rterm2wterm(RTERM,BASE))
-
-#define is_external_pid_rel(RTERM,BASE) is_external_pid(rterm2wterm(RTERM,BASE))
-#define external_pid_node_rel(RTERM,BASE) external_pid_node(rterm2wterm(RTERM,BASE))
-#define external_pid_data_rel(RTERM,BASE) external_pid_data(rterm2wterm(RTERM,BASE))
+#define is_same(A,B) ((A)==(B))
-#define is_binary_rel(RTERM,BASE) is_binary(rterm2wterm(RTERM,BASE))
-#define is_float_rel(RTERM,BASE) is_float(rterm2wterm(RTERM,BASE))
-#define is_fun_rel(RTERM,BASE) is_fun(rterm2wterm(RTERM,BASE))
-#define is_big_rel(RTERM,BASE) is_big(rterm2wterm(RTERM,BASE))
-#define is_export_rel(RTERM,BASE) is_export(rterm2wterm(RTERM,BASE))
-#define is_tuple_rel(RTERM,BASE) is_tuple(rterm2wterm(RTERM,BASE))
-
-#define GET_DOUBLE_REL(RTERM, f, BASE) GET_DOUBLE(rterm2wterm(RTERM,BASE), f)
-
-#define ref_thing_ptr_rel(RTERM,BASE) ref_thing_ptr(rterm2wterm(RTERM,BASE))
-#define is_internal_ref_rel(RTERM,BASE) is_internal_ref(rterm2wterm(RTERM,BASE))
-#define is_external_rel(RTERM,BASE) is_external(rterm2wterm(RTERM,BASE))
-#define is_external_port_rel(RTERM,BASE) is_external_port(rterm2wterm(RTERM,BASE))
-#define is_external_ref_rel(RTERM,BASE) is_external_ref(rterm2wterm(RTERM,BASE))
-
-#define external_node_rel(RTERM,BASE) external_node(rterm2wterm(RTERM,BASE))
-
-
-#if HALFWORD_HEAP
-ERTS_GLB_INLINE int is_same(Eterm a, Eterm* a_base, Eterm b, Eterm* b_base);
-
-#if ERTS_GLB_INLINE_INCL_FUNC_DEF
-ERTS_GLB_INLINE int is_same(Eterm a, Eterm* a_base, Eterm b, Eterm* b_base)
-{
- /* If bases differ, assume a and b are on different "heaps",
- ie can only be same if immed */
- ASSERT(a_base == b_base || is_immed(a) || is_immed(b)
- || rterm2wterm(a,a_base) != rterm2wterm(b,b_base));
-
- return a == b && (a_base == b_base || is_immed(a));
-}
-#endif
-
-#else /* !HALFWORD_HEAP */
-#define is_same(A,A_BASE,B,B_BASE) ((A)==(B))
-#endif
+void erts_set_literal_tag(Eterm *term, Eterm *hp_start, Eterm hsz);
#endif /* __ERL_TERM_H */
diff --git a/erts/emulator/beam/erl_threads.h b/erts/emulator/beam/erl_threads.h
index 34f91e2ec8..e689547d1d 100644
--- a/erts/emulator/beam/erl_threads.h
+++ b/erts/emulator/beam/erl_threads.h
@@ -2056,6 +2056,8 @@ erts_atomic64_read_dirty(erts_atomic64_t *var)
#endif /* !USE_THREADS */
+#include "erl_msacc.h"
+
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
ERTS_GLB_INLINE void
@@ -2414,6 +2416,7 @@ erts_cnd_wait(erts_cnd_t *cnd, erts_mtx_t *mtx)
{
#ifdef USE_THREADS
int res;
+ ERTS_MSACC_PUSH_AND_SET_STATE(ERTS_MSACC_STATE_SLEEP);
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_lc_unlock(&mtx->lc);
#endif
@@ -2432,6 +2435,7 @@ erts_cnd_wait(erts_cnd_t *cnd, erts_mtx_t *mtx)
#endif
if (res != 0 && res != EINTR)
erts_thr_fatal_error(res, "wait on condition variable");
+ ERTS_MSACC_POP_STATE();
#endif
}
@@ -3488,7 +3492,11 @@ ERTS_GLB_INLINE void erts_tse_reset(erts_tse_t *ep)
ERTS_GLB_INLINE int erts_tse_wait(erts_tse_t *ep)
{
#ifdef USE_THREADS
- return ethr_event_wait(&((ethr_ts_event *) ep)->event);
+ int res;
+ ERTS_MSACC_PUSH_AND_SET_STATE(ERTS_MSACC_STATE_SLEEP);
+ res = ethr_event_wait(&((ethr_ts_event *) ep)->event);
+ ERTS_MSACC_POP_STATE();
+ return res;
#else
return ENOTSUP;
#endif
@@ -3497,7 +3505,11 @@ ERTS_GLB_INLINE int erts_tse_wait(erts_tse_t *ep)
ERTS_GLB_INLINE int erts_tse_swait(erts_tse_t *ep, int spincount)
{
#ifdef USE_THREADS
- return ethr_event_swait(&((ethr_ts_event *) ep)->event, spincount);
+ int res;
+ ERTS_MSACC_PUSH_AND_SET_STATE(ERTS_MSACC_STATE_SLEEP);
+ res = ethr_event_swait(&((ethr_ts_event *) ep)->event, spincount);
+ ERTS_MSACC_POP_STATE();
+ return res;
#else
return ENOTSUP;
#endif
@@ -3506,8 +3518,12 @@ ERTS_GLB_INLINE int erts_tse_swait(erts_tse_t *ep, int spincount)
ERTS_GLB_INLINE int erts_tse_twait(erts_tse_t *ep, Sint64 tmo)
{
#ifdef USE_THREADS
- return ethr_event_twait(&((ethr_ts_event *) ep)->event,
- (ethr_sint64_t) tmo);
+ int res;
+ ERTS_MSACC_PUSH_AND_SET_STATE(ERTS_MSACC_STATE_SLEEP);
+ res = ethr_event_twait(&((ethr_ts_event *) ep)->event,
+ (ethr_sint64_t) tmo);
+ ERTS_MSACC_POP_STATE();
+ return res;
#else
return ENOTSUP;
#endif
@@ -3516,9 +3532,13 @@ ERTS_GLB_INLINE int erts_tse_twait(erts_tse_t *ep, Sint64 tmo)
ERTS_GLB_INLINE int erts_tse_stwait(erts_tse_t *ep, int spincount, Sint64 tmo)
{
#ifdef USE_THREADS
- return ethr_event_stwait(&((ethr_ts_event *) ep)->event,
- spincount,
- (ethr_sint64_t) tmo);
+ int res;
+ ERTS_MSACC_PUSH_AND_SET_STATE(ERTS_MSACC_STATE_SLEEP);
+ res = ethr_event_stwait(&((ethr_ts_event *) ep)->event,
+ spincount,
+ (ethr_sint64_t) tmo);
+ ERTS_MSACC_POP_STATE();
+ return res;
#else
return ENOTSUP;
#endif
diff --git a/erts/emulator/beam/erl_time.h b/erts/emulator/beam/erl_time.h
index 93a0d556bf..5242063550 100644
--- a/erts/emulator/beam/erl_time.h
+++ b/erts/emulator/beam/erl_time.h
@@ -142,6 +142,8 @@ erts_time_unit_conversion(Uint64 value,
Uint32 from_time_unit,
Uint32 to_time_unit);
+ErtsSysPerfCounter erts_perf_counter_unit(void);
+
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
ERTS_GLB_INLINE Uint64
diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c
index 99005356ed..f3f528eaf6 100644
--- a/erts/emulator/beam/erl_time_sup.c
+++ b/erts/emulator/beam/erl_time_sup.c
@@ -1749,7 +1749,7 @@ erts_get_monotonic_time(ErtsSchedulerData *esdp)
{
ErtsMonotonicTime mtime = time_sup.r.o.get_time();
update_last_mtime(esdp, mtime);
- return mtime;
+ return mtime;
}
ErtsMonotonicTime
@@ -1957,15 +1957,16 @@ send_time_offset_changed_notifications(void *new_offsetp)
ErtsProcLocks rp_locks = ERTS_PROC_LOCK_LINK;
erts_smp_proc_lock(rp, ERTS_PROC_LOCK_LINK);
if (erts_lookup_monitor(ERTS_P_MONITORS(rp), ref)) {
- ErlHeapFragment *bp;
+ ErtsMessage *mp;
ErlOffHeap *ohp;
Eterm message;
- hp = erts_alloc_message_heap(hsz, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks,
+ hsz, &hp, &ohp);
*patch_refp = ref;
ASSERT(hsz == size_object(message_template));
message = copy_struct(message_template, hsz, &hp, ohp);
- erts_queue_message(rp, &rp_locks, bp, message, NIL);
+ erts_queue_message(rp, &rp_locks, mp, message, NIL);
}
erts_smp_proc_unlock(rp, rp_locks);
}
@@ -2434,9 +2435,19 @@ BIF_RETTYPE os_system_time_0(BIF_ALIST_0)
BIF_RET(make_time_val(BIF_P, stime));
}
-BIF_RETTYPE os_system_time_1(BIF_ALIST_0)
+BIF_RETTYPE os_system_time_1(BIF_ALIST_1)
{
ErtsSystemTime stime = erts_os_system_time();
BIF_RET(time_unit_conversion(BIF_P, BIF_ARG_1, stime, 0));
}
+BIF_RETTYPE
+os_perf_counter_0(BIF_ALIST_0)
+{
+ BIF_RET(make_time_val(BIF_P, erts_sys_perf_counter()));
+}
+
+BIF_RETTYPE erts_internal_perf_counter_unit_0(BIF_ALIST_0)
+{
+ BIF_RET(make_time_val(BIF_P, erts_sys_perf_counter_unit()));
+}
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index 114853cac4..41876b8c62 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -373,15 +373,10 @@ void erts_init_trace(void) {
static Eterm system_seq_tracer;
-#ifdef ERTS_SMP
#define ERTS_ALLOC_SYSMSG_HEAP(SZ, BPP, OHPP, UNUSED) \
(*(BPP) = new_message_buffer((SZ)), \
*(OHPP) = &(*(BPP))->off_heap, \
(*(BPP))->mem)
-#else
-#define ERTS_ALLOC_SYSMSG_HEAP(SZ, BPP, OHPP, RPP) \
- erts_alloc_message_heap((SZ), (BPP), (OHPP), (RPP), 0)
-#endif
#ifdef ERTS_SMP
#define ERTS_ENQ_TRACE_MSG(FPID, TPID, MSG, BP) \
@@ -390,8 +385,12 @@ do { \
enqueue_sys_msg_unlocked(SYS_MSG_TYPE_TRACE, (FPID), (TPID), (MSG), (BP)); \
} while(0)
#else
-#define ERTS_ENQ_TRACE_MSG(FPID, TPROC, MSG, BP) \
- erts_queue_message((TPROC), NULL, (BP), (MSG), NIL)
+#define ERTS_ENQ_TRACE_MSG(FPID, TPROC, MSG, BP) \
+ do { \
+ ErtsMessage *mp__ = erts_alloc_message(0, NULL); \
+ mp__->data.heap_frag = (BP); \
+ erts_queue_message((TPROC), NULL, mp__, (MSG), NIL); \
+ } while (0)
#endif
/*
@@ -826,11 +825,9 @@ send_to_port(Process *c_p, Eterm message,
static void
profile_send(Eterm from, Eterm message) {
Uint sz = 0;
- ErlHeapFragment *bp = NULL;
Uint *hp = NULL;
Eterm msg = NIL;
Process *profile_p = NULL;
- ErlOffHeap *off_heap = NULL;
Eterm profiler = erts_get_system_profile();
@@ -856,6 +853,7 @@ profile_send(Eterm from, Eterm message) {
}
} else {
+ ErtsMessage *mp;
ASSERT(is_internal_pid(profiler));
profile_p = erts_proc_lookup(profiler);
@@ -864,10 +862,13 @@ profile_send(Eterm from, Eterm message) {
return;
sz = size_object(message);
- hp = erts_alloc_message_heap(sz, &bp, &off_heap, profile_p, 0);
- msg = copy_struct(message, sz, &hp, &bp->off_heap);
-
- erts_queue_message(profile_p, NULL, bp, msg, NIL);
+ mp = erts_alloc_message(sz, &hp);
+ if (sz == 0)
+ msg = message;
+ else
+ msg = copy_struct(message, sz, &hp, &mp->hfrag.off_heap);
+
+ erts_queue_message(profile_p, NULL, mp, msg, NIL);
}
}
@@ -1235,11 +1236,7 @@ seq_trace_update_send(Process *p)
{
Eterm seq_tracer = erts_get_system_seq_tracer();
ASSERT((is_tuple(SEQ_TRACE_TOKEN(p)) || is_nil(SEQ_TRACE_TOKEN(p))));
- if ( (p->common.id == seq_tracer) || (SEQ_TRACE_TOKEN(p) == NIL)
-#ifdef USE_VM_PROBES
- || (SEQ_TRACE_TOKEN(p) == am_have_dt_utag)
-#endif
- ) {
+ if ((p->common.id == seq_tracer) || have_no_seqtrace(SEQ_TRACE_TOKEN(p))) {
return 0;
}
SEQ_TRACE_TOKEN_SENDER(p) = p->common.id;
@@ -1431,7 +1428,11 @@ seq_trace_output_generic(Eterm token, Eterm msg, Uint type,
erts_smp_mtx_unlock(&smq_mtx);
#else
/* trace_token must be NIL here */
- erts_queue_message(tracer, NULL, bp, mess, NIL);
+ {
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = bp;
+ erts_queue_message(tracer, NULL, mp, mess, NIL);
+ }
#endif
}
}
@@ -1851,12 +1852,7 @@ erts_call_trace(Process* p, BeamInstr mfa[3], Binary *match_spec,
ts_type = ERTS_TFLGS2TSTYPE(*tracee_flags);
if (is_internal_port(*tracer_pid)) {
-#if HEAP_ON_C_STACK
- Eterm local_heap[60+ERTS_TRACE_PATCH_TS_MAX_SIZE+MAX_ARG];
-#else
- Eterm *local_heap = erts_alloc(ERTS_ALC_T_TEMP_TERM,
- sizeof(Eterm)*(60+ERTS_TRACE_PATCH_TS_MAX_SIZE+MAX_ARG));
-#endif
+ Eterm local_heap[64+ERTS_TRACE_PATCH_TS_MAX_SIZE+MAX_ARG];
hp = local_heap;
if (!erts_is_valid_tracer_port(*tracer_pid)) {
@@ -1871,9 +1867,6 @@ erts_call_trace(Process* p, BeamInstr mfa[3], Binary *match_spec,
if (is_not_nil(tracee))
erts_smp_proc_unlock(p, ERTS_PROC_LOCKS_ALL_MINOR);
#endif
-#if !HEAP_ON_C_STACK
- erts_free(ERTS_ALC_T_TEMP_TERM,local_heap);
-#endif
UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
return 0;
}
@@ -1901,9 +1894,6 @@ erts_call_trace(Process* p, BeamInstr mfa[3], Binary *match_spec,
ERTS_PAM_TMP_RESULT, &return_flags);
if (is_non_value(pam_result)) {
erts_match_set_release_result(p);
-#if !HEAP_ON_C_STACK
- erts_free(ERTS_ALC_T_TEMP_TERM,local_heap);
-#endif
UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
return 0;
}
@@ -1912,9 +1902,6 @@ erts_call_trace(Process* p, BeamInstr mfa[3], Binary *match_spec,
/* Meta trace */
if (pam_result == am_false) {
erts_match_set_release_result(p);
-#if !HEAP_ON_C_STACK
- erts_free(ERTS_ALC_T_TEMP_TERM,local_heap);
-#endif
UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
return return_flags;
}
@@ -1922,17 +1909,11 @@ erts_call_trace(Process* p, BeamInstr mfa[3], Binary *match_spec,
/* Non-meta trace */
if (*tracee_flags & F_TRACE_SILENT) {
erts_match_set_release_result(p);
-#if !HEAP_ON_C_STACK
- erts_free(ERTS_ALC_T_TEMP_TERM,local_heap);
-#endif
UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
return 0;
}
if (pam_result == am_false) {
erts_match_set_release_result(p);
-#if !HEAP_ON_C_STACK
- erts_free(ERTS_ALC_T_TEMP_TERM,local_heap);
-#endif
UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
return return_flags;
}
@@ -1974,9 +1955,6 @@ erts_call_trace(Process* p, BeamInstr mfa[3], Binary *match_spec,
send_to_port(p, mess, tracer_pid, tracee_flags);
erts_smp_mtx_unlock(&smq_mtx);
erts_match_set_release_result(p);
-#if !HEAP_ON_C_STACK
- erts_free(ERTS_ALC_T_TEMP_TERM,local_heap);
-#endif
UnUseTmpHeap(ERL_SUB_BIN_SIZE,p);
return *tracer_pid == NIL ? 0 : return_flags;
@@ -2314,11 +2292,6 @@ void save_calls(Process *p, Export *e)
void
trace_gc(Process *p, Eterm what)
{
- ERTS_DECL_AM(bin_vheap_size);
- ERTS_DECL_AM(bin_vheap_block_size);
- ERTS_DECL_AM(bin_old_vheap_size);
- ERTS_DECL_AM(bin_old_vheap_block_size);
-
ErlHeapFragment *bp = NULL;
ErlOffHeap *off_heap;
ERTS_TRACER_REF_TYPE tracer_ref = ERTS_NULL_TRACER_REF; /* Initialized
@@ -2329,52 +2302,19 @@ trace_gc(Process *p, Eterm what)
Eterm msg = NIL;
Uint size;
- Eterm tags[] = {
- am_old_heap_block_size,
- am_heap_block_size,
- am_mbuf_size,
- am_recent_size,
- am_stack_size,
- am_old_heap_size,
- am_heap_size,
- AM_bin_vheap_size,
- AM_bin_vheap_block_size,
- AM_bin_old_vheap_size,
- AM_bin_old_vheap_block_size
- };
-
- UWord values[] = {
- OLD_HEAP(p) ? OLD_HEND(p) - OLD_HEAP(p) : 0,
- HEAP_SIZE(p),
- MBUF_SIZE(p),
- HIGH_WATER(p) - HEAP_START(p),
- STACK_START(p) - p->stop,
- OLD_HEAP(p) ? OLD_HTOP(p) - OLD_HEAP(p) : 0,
- HEAP_TOP(p) - HEAP_START(p),
- MSO(p).overhead,
- BIN_VHEAP_SZ(p),
- BIN_OLD_VHEAP(p),
- BIN_OLD_VHEAP_SZ(p)
- };
#define LOCAL_HEAP_SIZE \
- (sizeof(values)/sizeof(*values)) * \
- (2/*cons*/ + 3/*2-tuple*/ + BIG_UINT_HEAP_SIZE) + \
+ (ERTS_PROCESS_GC_INFO_MAX_SIZE) + \
5/*4-tuple */ + ERTS_TRACE_PATCH_TS_MAX_SIZE
DeclareTmpHeap(local_heap,LOCAL_HEAP_SIZE,p);
- ERTS_CT_ASSERT(sizeof(values)/sizeof(*values) == sizeof(tags)/sizeof(Eterm));
-
UseTmpHeap(LOCAL_HEAP_SIZE,p);
if (is_internal_port(ERTS_TRACER_PROC(p))) {
hp = local_heap;
#ifdef DEBUG
size = 0;
- (void) erts_bld_atom_uword_2tup_list(NULL,
- &size,
- sizeof(values)/sizeof(*values),
- tags,
- values);
+ (void) erts_process_gc_info(p, &size, NULL);
+
size += 5/*4-tuple*/ + PATCH_TS_SIZE(p);
#endif
} else {
@@ -2385,11 +2325,8 @@ trace_gc(Process *p, Eterm what)
ERTS_TRACE_FLAGS(p));
size = 0;
- (void) erts_bld_atom_uword_2tup_list(NULL,
- &size,
- sizeof(values)/sizeof(*values),
- tags,
- values);
+ (void) erts_process_gc_info(p, &size, NULL);
+
size += 5/*4-tuple*/ + PATCH_TS_SIZE(p);
hp = ERTS_ALLOC_SYSMSG_HEAP(size, &bp, &off_heap, tracer_ref);
@@ -2397,11 +2334,7 @@ trace_gc(Process *p, Eterm what)
ASSERT(size <= LOCAL_HEAP_SIZE);
- msg = erts_bld_atom_uword_2tup_list(&hp,
- NULL,
- sizeof(values)/sizeof(*values),
- tags,
- values);
+ msg = erts_process_gc_info(p, NULL, &hp);
msg = TUPLE4(hp, am_trace, p->common.id, what, msg);
hp += 5;
@@ -2477,7 +2410,11 @@ monitor_long_schedule_proc(Process *p, BeamInstr *in_fp, BeamInstr *out_fp, Uint
#ifdef ERTS_SMP
enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->common.id, NIL, msg, bp);
#else
- erts_queue_message(monitor_p, NULL, bp, msg, NIL);
+ {
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = bp;
+ erts_queue_message(monitor_p, NULL, mp, msg, NIL);
+ }
#endif
}
void
@@ -2538,7 +2475,11 @@ monitor_long_schedule_port(Port *pp, ErtsPortTaskType type, Uint time)
#ifdef ERTS_SMP
enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, pp->common.id, NIL, msg, bp);
#else
- erts_queue_message(monitor_p, NULL, bp, msg, NIL);
+ {
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = bp;
+ erts_queue_message(monitor_p, NULL, mp, msg, NIL);
+ }
#endif
}
@@ -2609,7 +2550,11 @@ monitor_long_gc(Process *p, Uint time) {
#ifdef ERTS_SMP
enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->common.id, NIL, msg, bp);
#else
- erts_queue_message(monitor_p, NULL, bp, msg, NIL);
+ {
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = bp;
+ erts_queue_message(monitor_p, NULL, mp, msg, NIL);
+ }
#endif
}
@@ -2680,7 +2625,11 @@ monitor_large_heap(Process *p) {
#ifdef ERTS_SMP
enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->common.id, NIL, msg, bp);
#else
- erts_queue_message(monitor_p, NULL, bp, msg, NIL);
+ {
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = bp;
+ erts_queue_message(monitor_p, NULL, mp, msg, NIL);
+ }
#endif
}
@@ -2708,7 +2657,11 @@ monitor_generic(Process *p, Eterm type, Eterm spec) {
#ifdef ERTS_SMP
enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->common.id, NIL, msg, bp);
#else
- erts_queue_message(monitor_p, NULL, bp, msg, NIL);
+ {
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = bp;
+ erts_queue_message(monitor_p, NULL, mp, msg, NIL);
+ }
#endif
}
@@ -3436,8 +3389,6 @@ sys_msg_dispatcher_func(void *unused)
if (erts_thr_progress_update(NULL))
erts_thr_progress_leader_update(NULL);
- ERTS_SCHED_FAIR_YIELD();
-
#ifdef DEBUG_PRINTOUTS
print_msg_type(smqp);
#endif
@@ -3496,8 +3447,11 @@ sys_msg_dispatcher_func(void *unused)
goto failure;
}
else {
+ ErtsMessage *mp;
queue_proc_msg:
- erts_queue_message(proc,&proc_locks,smqp->bp,smqp->msg,NIL);
+ mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = smqp->bp;
+ erts_queue_message(proc,&proc_locks,mp,smqp->msg,NIL);
#ifdef DEBUG_PRINTOUTS
erts_fprintf(stderr, "delivered\n");
#endif
@@ -3592,9 +3546,6 @@ static void
init_sys_msg_dispatcher(void)
{
erts_smp_thr_opts_t thr_opts = ERTS_SMP_THR_OPTS_DEFAULT_INITER;
-#ifdef __OSE__
- thr_opts.coreNo = 0;
-#endif
thr_opts.detached = 1;
thr_opts.name = "sys_msg_dispatcher";
init_smq_element_alloc();
@@ -3602,7 +3553,6 @@ init_sys_msg_dispatcher(void)
sys_message_queue_end = NULL;
erts_smp_cnd_init(&smq_cnd);
erts_smp_mtx_init(&smq_mtx, "sys_msg_q");
-
erts_smp_thr_create(&sys_msg_dispatcher_tid,
sys_msg_dispatcher_func,
NULL,
diff --git a/erts/emulator/beam/erl_utils.h b/erts/emulator/beam/erl_utils.h
index 6dab3bf297..640969daf0 100644
--- a/erts/emulator/beam/erl_utils.h
+++ b/erts/emulator/beam/erl_utils.h
@@ -115,7 +115,7 @@ void erts_silence_warn_unused_result(long unused);
int erts_fit_in_bits_int64(Sint64);
int erts_fit_in_bits_int32(Sint32);
int erts_fit_in_bits_uint(Uint);
-int erts_list_length(Eterm);
+Sint erts_list_length(Eterm);
int erts_is_builtin(Eterm, Eterm, int);
Uint32 make_broken_hash(Eterm);
Uint32 block_hash(byte *, unsigned, Uint32);
@@ -157,51 +157,46 @@ void erts_init_utils_mem(void);
erts_dsprintf_buf_t *erts_create_tmp_dsbuf(Uint);
void erts_destroy_tmp_dsbuf(erts_dsprintf_buf_t *);
-#if HALFWORD_HEAP
-int eq_rel(Eterm a, Eterm* a_base, Eterm b, Eterm* b_base);
-# define eq(A,B) eq_rel(A,NULL,B,NULL)
-#else
int eq(Eterm, Eterm);
-# define eq_rel(A,A_BASE,B,B_BASE) eq(A,B)
-#endif
#define EQ(x,y) (((x) == (y)) || (is_not_both_immed((x),(y)) && eq((x),(y))))
-#if HALFWORD_HEAP
-Sint erts_cmp_rel_opt(Eterm, Eterm*, Eterm, Eterm*, int, int);
-#define cmp_rel(A,A_BASE,B,B_BASE) erts_cmp_rel_opt(A,A_BASE,B,B_BASE,0,0)
-#define cmp_rel_term(A,A_BASE,B,B_BASE) erts_cmp_rel_opt(A,A_BASE,B,B_BASE,1,0)
-#define CMP(A,B) erts_cmp_rel_opt(A,NULL,B,NULL,0,0)
-#define CMP_TERM(A,B) erts_cmp_rel_opt(A,NULL,B,NULL,1,0)
-#define CMP_EQ_ONLY(A,B) erts_cmp_rel_opt(A,NULL,B,NULL,0,1)
-#else
+int erts_cmp_atoms(Eterm a, Eterm b);
Sint erts_cmp(Eterm, Eterm, int, int);
+Sint erts_cmp_compound(Eterm, Eterm, int, int);
Sint cmp(Eterm a, Eterm b);
-#define cmp_rel(A,A_BASE,B,B_BASE) erts_cmp(A,B,0,0)
-#define cmp_rel_term(A,A_BASE,B,B_BASE) erts_cmp(A,B,1,0)
#define CMP(A,B) erts_cmp(A,B,0,0)
#define CMP_TERM(A,B) erts_cmp(A,B,1,0)
#define CMP_EQ_ONLY(A,B) erts_cmp(A,B,0,1)
-#endif
-#define cmp_lt(a,b) (CMP((a),(b)) < 0)
-#define cmp_le(a,b) (CMP((a),(b)) <= 0)
-#define cmp_eq(a,b) (CMP_EQ_ONLY((a),(b)) == 0)
-#define cmp_ne(a,b) (CMP_EQ_ONLY((a),(b)) != 0)
-#define cmp_ge(a,b) (CMP((a),(b)) >= 0)
-#define cmp_gt(a,b) (CMP((a),(b)) > 0)
-
-#define cmp_lt_term(a,b) (CMP_TERM((a),(b)) < 0)
-#define cmp_le_term(a,b) (CMP_TERM((a),(b)) <= 0)
-#define cmp_ge_term(a,b) (CMP_TERM((a),(b)) >= 0)
-#define cmp_gt_term(a,b) (CMP_TERM((a),(b)) > 0)
-
-#define CMP_LT(a,b) ((a) != (b) && cmp_lt((a),(b)))
-#define CMP_GE(a,b) ((a) == (b) || cmp_ge((a),(b)))
-#define CMP_EQ(a,b) ((a) == (b) || cmp_eq((a),(b)))
-#define CMP_NE(a,b) ((a) != (b) && cmp_ne((a),(b)))
-
-#define CMP_LT_TERM(a,b) ((a) != (b) && cmp_lt_term((a),(b)))
-#define CMP_GE_TERM(a,b) ((a) == (b) || cmp_ge_term((a),(b)))
+#define CMP_LT(a,b) ((a) != (b) && CMP((a),(b)) < 0)
+#define CMP_LE(a,b) ((a) == (b) || CMP((a),(b)) <= 0)
+#define CMP_EQ(a,b) ((a) == (b) || CMP_EQ_ONLY((a),(b)) == 0)
+#define CMP_NE(a,b) ((a) != (b) && CMP_EQ_ONLY((a),(b)) != 0)
+#define CMP_GE(a,b) ((a) == (b) || CMP((a),(b)) >= 0)
+#define CMP_GT(a,b) ((a) != (b) && CMP((a),(b)) > 0)
+
+#define CMP_EQ_ACTION(X,Y,Action) \
+ if ((X) != (Y)) { CMP_SPEC((X),(Y),!=,Action,1); }
+#define CMP_NE_ACTION(X,Y,Action) \
+ if ((X) == (Y)) { Action; } else { CMP_SPEC((X),(Y),==,Action,1); }
+#define CMP_GE_ACTION(X,Y,Action) \
+ if ((X) != (Y)) { CMP_SPEC((X),(Y),<,Action,0); }
+#define CMP_LT_ACTION(X,Y,Action) \
+ if ((X) == (Y)) { Action; } else { CMP_SPEC((X),(Y),>=,Action,0); }
+
+#define CMP_SPEC(X,Y,Op,Action,EqOnly) \
+ if (is_atom(X) && is_atom(Y)) { \
+ if (erts_cmp_atoms(X, Y) Op 0) { Action; }; \
+ } else if (is_both_small(X, Y)) { \
+ if (signed_val(X) Op signed_val(Y)) { Action; }; \
+ } else if (is_float(X) && is_float(Y)) { \
+ FloatDef af, bf; \
+ GET_DOUBLE(X, af); \
+ GET_DOUBLE(Y, bf); \
+ if (af.fd Op bf.fd) { Action; }; \
+ } else { \
+ if (erts_cmp_compound(X,Y,0,EqOnly) Op 0) { Action; }; \
+ }
#endif
diff --git a/erts/emulator/beam/erl_vm.h b/erts/emulator/beam/erl_vm.h
index 8948ca2ea9..98f27a1725 100644
--- a/erts/emulator/beam/erl_vm.h
+++ b/erts/emulator/beam/erl_vm.h
@@ -40,14 +40,6 @@
#define MAX_ARG 255 /* Max number of arguments allowed */
#define MAX_REG 1024 /* Max number of x(N) registers used */
-/* Scheduler stores data for temporary heaps if
- !HEAP_ON_C_STACK. Macros (*TmpHeap*) in global.h selects if we put temporary
- heap data on the C stack or if we use the buffers in the scheduler data. */
-#define TMP_HEAP_SIZE 128 /* Number of Eterm in the schedulers
- small heap for transient heap data */
-#define ERL_ARITH_TMP_HEAP_SIZE 4 /* as does erl_arith... */
-#define BEAM_EMU_TMP_HEAP_SIZE 2 /* and beam_emu... */
-
/*
* The new arithmetic operations need some extra X registers in the register array.
* so does the gc_bif's (i_gc_bif3 need 3 extra).
@@ -117,12 +109,8 @@
#define HeapWordsLeft(p) (HEAP_LIMIT(p) - HEAP_TOP(p))
#if defined(DEBUG) || defined(CHECK_FOR_HOLES)
-#if HALFWORD_HEAP
-# define ERTS_HOLE_MARKER (0xdeadbeef)
-#else
# define ERTS_HOLE_MARKER (((0xdeadbeef << 24) << 8) | 0xdeadbeef)
-#endif
-#endif
+#endif /* egil: 32-bit ? */
/*
* Allocate heap memory on the ordinary heap, NEVER in a heap
@@ -153,6 +141,7 @@
typedef struct op_entry {
char* name; /* Name of instruction. */
Uint32 mask[3]; /* Signature mask. */
+ unsigned involves_r; /* Needs special attention when matching. */
int sz; /* Number of loaded words. */
char* pack; /* Instructions for packing engine. */
char* sign; /* Signature string. */
diff --git a/erts/emulator/beam/export.c b/erts/emulator/beam/export.c
index 2420df36b5..581efe6eec 100644
--- a/erts/emulator/beam/export.c
+++ b/erts/emulator/beam/export.c
@@ -184,6 +184,9 @@ init_export_table(void)
f.cmp = (HCMP_FUN) export_cmp;
f.alloc = (HALLOC_FUN) export_alloc;
f.free = (HFREE_FUN) export_free;
+ f.meta_alloc = (HMALLOC_FUN) erts_alloc;
+ f.meta_free = (HMFREE_FUN) erts_free;
+ f.meta_print = (HMPRINT_FUN) erts_print;
for (i=0; i<ERTS_NUM_CODE_IX; i++) {
erts_index_init(ERTS_ALC_T_EXPORT_TABLE, &export_tables[i], "export_list",
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index ffe3303796..aac1490f0c 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -2339,10 +2339,6 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
Eterm val;
FloatDef f;
Sint r = 0;
-#if HALFWORD_HEAP
- UWord wobj;
-#endif
-
if (ctx) {
WSTACK_CHANGE_ALLOCATOR(s, ERTS_ALC_T_SAVED_ESTACK);
@@ -2362,11 +2358,8 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
outer_loop:
while (!WSTACK_ISEMPTY(s)) {
-#if HALFWORD_HEAP
- obj = (Eterm) (wobj = WSTACK_POP(s));
-#else
obj = WSTACK_POP(s);
-#endif
+
switch (val = WSTACK_POP(s)) {
case ENC_TERM:
break;
@@ -2384,11 +2377,7 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
break;
case ENC_PATCH_FUN_SIZE:
{
-#if HALFWORD_HEAP
- byte* size_p = (byte *) wobj;
-#else
byte* size_p = (byte *) obj;
-#endif
put_int32(ep - size_p, size_p);
}
goto outer_loop;
@@ -2435,21 +2424,13 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
case ENC_LAST_ARRAY_ELEMENT:
/* obj is the tuple */
{
-#if HALFWORD_HEAP
- Eterm* ptr = (Eterm *) wobj;
-#else
Eterm* ptr = (Eterm *) obj;
-#endif
obj = *ptr;
}
break;
default: /* ENC_LAST_ARRAY_ELEMENT+1 and upwards */
{
-#if HALFWORD_HEAP
- Eterm* ptr = (Eterm *) wobj;
-#else
Eterm* ptr = (Eterm *) obj;
-#endif
obj = *ptr++;
WSTACK_PUSH2(s, val-1, (UWord)ptr);
}
@@ -2976,7 +2957,7 @@ dec_term(ErtsDistExternal *edep,
case B2TDecodeList:
objp = next - 2;
while (n > 0) {
- objp[0] = (Eterm) COMPRESS_POINTER(next);
+ objp[0] = (Eterm) next;
objp[1] = make_list(next);
next = objp;
objp -= 2;
@@ -2987,7 +2968,7 @@ dec_term(ErtsDistExternal *edep,
case B2TDecodeTuple:
objp = next - 1;
while (n-- > 0) {
- objp[0] = (Eterm) COMPRESS_POINTER(next);
+ objp[0] = (Eterm) next;
next = objp;
objp--;
}
@@ -3043,7 +3024,7 @@ dec_term(ErtsDistExternal *edep,
while (next != NULL) {
objp = next;
- next = (Eterm *) EXPAND_POINTER(*objp);
+ next = (Eterm *) *objp;
switch (*ep++) {
case INTEGER_EXT:
@@ -3051,7 +3032,7 @@ dec_term(ErtsDistExternal *edep,
Sint sn = get_int32(ep);
ep += 4;
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
*objp = make_small(sn);
#else
if (MY_IS_SSMALL(sn)) {
@@ -3174,7 +3155,7 @@ dec_term_atom_common:
reds -= n;
}
while (n-- > 0) {
- objp[0] = (Eterm) COMPRESS_POINTER(next);
+ objp[0] = (Eterm) next;
next = objp;
objp--;
}
@@ -3192,8 +3173,8 @@ dec_term_atom_common:
*objp = make_list(hp);
hp += 2 * n;
objp = hp - 2;
- objp[0] = (Eterm) COMPRESS_POINTER((objp+1));
- objp[1] = (Eterm) COMPRESS_POINTER(next);
+ objp[0] = (Eterm) (objp+1);
+ objp[1] = (Eterm) next;
next = objp;
objp -= 2;
n--;
@@ -3206,7 +3187,7 @@ dec_term_atom_common:
reds -= n;
}
while (n > 0) {
- objp[0] = (Eterm) COMPRESS_POINTER(next);
+ objp[0] = (Eterm) next;
objp[1] = make_list(next);
next = objp;
objp -= 2;
@@ -3373,7 +3354,7 @@ dec_term_atom_common:
RefThing *rtp = (RefThing *) hp;
ref_num = (Uint32 *) (hp + REF_THING_HEAD_SIZE);
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
hp += REF_THING_HEAD_SIZE + ref_words/2 + 1;
rtp->header = make_ref_thing_header(ref_words/2 + 1);
#else
@@ -3384,13 +3365,13 @@ dec_term_atom_common:
}
else {
ExternalThing *etp = (ExternalThing *) hp;
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
hp += EXTERNAL_THING_HEAD_SIZE + ref_words/2 + 1;
#else
hp += EXTERNAL_THING_HEAD_SIZE + ref_words;
#endif
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
etp->header = make_external_ref_header(ref_words/2 + 1);
#else
etp->header = make_external_ref_header(ref_words);
@@ -3403,7 +3384,7 @@ dec_term_atom_common:
ref_num = &(etp->data.ui32[0]);
}
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
*(ref_num++) = ref_words /* 32-bit arity */;
#endif
ref_num[0] = r0;
@@ -3411,7 +3392,7 @@ dec_term_atom_common:
ref_num[i] = get_int32(ep);
ep += 4;
}
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
if ((1 + ref_words) % 2)
ref_num[ref_words] = 0;
#endif
@@ -3563,12 +3544,7 @@ dec_term_atom_common:
}
*objp = make_export(hp);
*hp++ = HEADER_EXPORT;
-#if HALFWORD_HEAP
- *((UWord *) (UWord) hp) = (UWord) erts_export_get_or_make_stub(mod, name, arity);
- hp += 2;
-#else
*hp++ = (Eterm) erts_export_get_or_make_stub(mod, name, arity);
-#endif
break;
}
break;
@@ -3604,8 +3580,8 @@ dec_term_atom_common:
*objp = make_flatmap(mp);
for (n = size; n; n--) {
- *vptr = (Eterm) COMPRESS_POINTER(next);
- *kptr = (Eterm) COMPRESS_POINTER(vptr);
+ *vptr = (Eterm) next;
+ *kptr = (Eterm) vptr;
next = kptr;
vptr--;
kptr--;
@@ -3619,8 +3595,8 @@ dec_term_atom_common:
hamt->leaf_array = hp;
for (n = size; n; n--) {
- CDR(hp) = (Eterm) COMPRESS_POINTER(next);
- CAR(hp) = (Eterm) COMPRESS_POINTER(&CDR(hp));
+ CDR(hp) = (Eterm) next;
+ CAR(hp) = (Eterm) &CDR(hp);
next = &CAR(hp);
hp += 2;
}
@@ -3697,11 +3673,11 @@ dec_term_atom_common:
/* Environment */
for (i = num_free-1; i >= 0; i--) {
- funp->env[i] = (Eterm) COMPRESS_POINTER(next);
+ funp->env[i] = (Eterm) next;
next = funp->env + i;
}
/* Creator */
- funp->creator = (Eterm) COMPRESS_POINTER(next);
+ funp->creator = (Eterm) next;
next = &(funp->creator);
break;
}
@@ -3770,7 +3746,7 @@ dec_term_atom_common:
/* Environment */
for (i = num_free-1; i >= 0; i--) {
- funp->env[i] = (Eterm) COMPRESS_POINTER(next);
+ funp->env[i] = (Eterm) next;
next = funp->env + i;
}
break;
@@ -3897,7 +3873,7 @@ dec_term_atom_common:
}
WSTACK_DESTROY(flat_maps);
- ASSERT((Eterm*)EXPAND_POINTER(*dbg_resultp) != NULL);
+ ASSERT((Eterm*)*dbg_resultp != NULL);
if (ctx) {
ctx->state = B2TDone;
@@ -4190,11 +4166,7 @@ encode_size_struct_int(TTBSizeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj,
case EXPORT_DEF:
{
Export* ep = *((Export **) (export_val(obj) + 1));
-#if HALFWORD_HEAP
- result += 2;
-#else
result += 1;
-#endif
result += encode_size_struct2(acmp, ep->code[0], dflags);
result += encode_size_struct2(acmp, ep->code[1], dflags);
result += encode_size_struct2(acmp, make_small(ep->code[2]), dflags);
@@ -4309,7 +4281,7 @@ init_done:
switch (tag) {
case INTEGER_EXT:
SKIP(4);
-#if !defined(ARCH_64) || HALFWORD_HEAP
+#if !defined(ARCH_64)
heap_size += BIG_UINT_HEAP_SIZE;
#endif
break;
@@ -4398,7 +4370,7 @@ init_done:
ep += 2;
atom_extra_skip = 1 + 4*id_words;
/* In case it is an external ref */
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
heap_size += EXTERNAL_THING_HEAD_SIZE + id_words/2 + 1;
#else
heap_size += EXTERNAL_THING_HEAD_SIZE + id_words;
@@ -4484,11 +4456,7 @@ init_done:
break;
case EXPORT_EXT:
terms += 3;
-#if HALFWORD_HEAP
- heap_size += 3;
-#else
heap_size += 2;
-#endif
break;
case NEW_FUN_EXT:
{
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 1b8595fe57..d7edf451be 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -310,9 +310,6 @@ typedef union {
typedef struct proc_bin {
Eterm thing_word; /* Subtag REFC_BINARY_SUBTAG. */
Uint size; /* Binary size in bytes. */
-#if HALFWORD_HEAP
- void* dummy_ptr_padding__;
-#endif
struct erl_off_heap_header *next;
Binary *val; /* Pointer to Binary structure. */
byte *bytes; /* Pointer to the actual data bytes. */
@@ -383,7 +380,7 @@ extern int bif_reductions; /* reductions + fcalls (when doing call_bif) */
extern int stackdump_on_exit;
/*
- * Here is an implementation of a lightweiht stack.
+ * Here is an implementation of a lightweight stack.
*
* Use it like this:
*
@@ -848,6 +845,94 @@ do {\
} while(0)
+/*
+ * An implementation of lightweight unbounded queues,
+ * using a circular dynamic array.
+ * It does not include support for change_allocator.
+ *
+ * Use it like this:
+ *
+ * DECLARE_EQUEUE(Queue) (At the start of a block)
+ * ...
+ * EQUEUE_PUT(Queue, Term)
+ * ...
+ * if (EQUEUE_ISEMPTY(Queue)) {
+ * Queue is empty
+ * } else {
+ * Term = EQUEUE_GET(Stack);
+ * Process popped Term here
+ * }
+ * ...
+ * DESTROY_EQUEUE(Queue)
+ */
+
+typedef struct {
+ Eterm* start;
+ Eterm* front;
+ Eterm* back;
+ int possibly_empty;
+ Eterm* end;
+ ErtsAlcType_t alloc_type;
+} ErtsEQueue;
+
+#define DEF_EQUEUE_SIZE (16)
+
+void erl_grow_equeue(ErtsEQueue*, Eterm* def_queue);
+#define EQUE_CONCAT(a,b) a##b
+#define EQUE_DEF_QUEUE(q) EQUE_CONCAT(q,_default_equeue)
+
+#define DECLARE_EQUEUE(q) \
+ UWord EQUE_DEF_QUEUE(q)[DEF_EQUEUE_SIZE]; \
+ ErtsEQueue q = { \
+ EQUE_DEF_QUEUE(q), /* start */ \
+ EQUE_DEF_QUEUE(q), /* front */ \
+ EQUE_DEF_QUEUE(q), /* back */ \
+ 1, /* possibly_empty */ \
+ EQUE_DEF_QUEUE(q) + DEF_EQUEUE_SIZE, /* end */ \
+ ERTS_ALC_T_ESTACK /* alloc_type */ \
+ }
+
+#define DESTROY_EQUEUE(q) \
+do { \
+ if (q.start != EQUE_DEF_QUEUE(q)) { \
+ erts_free(q.alloc_type, q.start); \
+ } \
+} while(0)
+
+#define EQUEUE_PUT_UNCHECKED(q, x) \
+do { \
+ q.possibly_empty = 0; \
+ *(q.back) = (x); \
+ if (++(q.back) == q.end) { \
+ q.back = q.start; \
+ } \
+} while(0)
+
+#define EQUEUE_PUT(q, x) \
+do { \
+ if (q.back == q.front && !q.possibly_empty) { \
+ erl_grow_equeue(&q, EQUE_DEF_QUEUE(q)); \
+ } \
+ EQUEUE_PUT_UNCHECKED(q, x); \
+} while(0)
+
+#define EQUEUE_ISEMPTY(q) (q.back == q.front && q.possibly_empty)
+
+ERTS_GLB_INLINE Eterm erts_equeue_get(ErtsEQueue *q);
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+ERTS_GLB_INLINE Eterm erts_equeue_get(ErtsEQueue *q) {
+ Eterm x;
+ q->possibly_empty = 1;
+ x = *(q->front);
+ if (++(q->front) == q->end) {
+ q->front = q->start;
+ }
+ return x;
+}
+#endif
+#define EQUEUE_GET(q) erts_equeue_get(&(q));
+
/* binary.c */
void erts_emasculate_writable_binary(ProcBin* pb);
@@ -900,8 +985,18 @@ Eterm erl_send(Process *p, Eterm to, Eterm msg);
Eterm erl_is_function(Process* p, Eterm arg1, Eterm arg2);
/* beam_bif_load.c */
-Eterm erts_check_process_code(Process *c_p, Eterm module, int allow_gc, int *redsp);
+#define ERTS_CPC_ALLOW_GC (1 << 0)
+#define ERTS_CPC_COPY_LITERALS (1 << 1)
+#define ERTS_CPC_ALL (ERTS_CPC_ALLOW_GC | ERTS_CPC_COPY_LITERALS)
+Eterm erts_check_process_code(Process *c_p, Eterm module, Uint flags, int *redsp);
+typedef struct {
+ Eterm *ptr;
+ Uint sz;
+ Eterm pid;
+} copy_literals_t;
+
+extern copy_literals_t erts_clrange;
/* beam_load.c */
typedef struct {
@@ -913,6 +1008,7 @@ typedef struct {
Binary* erts_alloc_loader_state(void);
Eterm erts_module_for_prepared_code(Binary* magic);
+Eterm erts_has_code_on_load(Binary* magic);
Eterm erts_prepare_loading(Binary* loader_state, Process *c_p,
Eterm group_leader, Eterm* modp,
byte* code, Uint size);
@@ -931,7 +1027,7 @@ Eterm erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info);
/* beam_ranges.c */
void erts_init_ranges(void);
-void erts_start_staging_ranges(void);
+void erts_start_staging_ranges(int num_new);
void erts_end_staging_ranges(int commit);
void erts_update_ranges(BeamInstr* code, Uint size);
void erts_remove_from_ranges(BeamInstr* code);
@@ -956,35 +1052,71 @@ __decl_noreturn void __noreturn erts_exit(int n, char*, ...);
__decl_noreturn void __noreturn erts_flush_async_exit(int n, char*, ...);
void erl_error(char*, va_list);
-/* copy.c */
-Eterm copy_object(Eterm, Process*);
+/* This controls whether sharing-preserving copy is used by Erlang */
-#if HALFWORD_HEAP
-Uint size_object_rel(Eterm, Eterm*);
-# define size_object(A) size_object_rel(A,NULL)
+#ifdef SHCOPY
+#define SHCOPY_SEND
+#define SHCOPY_SPAWN
+#endif
+
+/* The persistent state while the sharing-preserving copier works */
-Eterm copy_struct_rel(Eterm, Uint, Eterm**, ErlOffHeap*, Eterm* src_base, Eterm* dst_base);
-# define copy_struct(OBJ,SZ,HPP,OH) copy_struct_rel(OBJ,SZ,HPP,OH, NULL,NULL)
+typedef struct {
+ Eterm queue_default[DEF_EQUEUE_SIZE];
+ Eterm* queue_start;
+ Eterm* queue_end;
+ ErtsAlcType_t queue_alloc_type;
+ UWord bitstore_default[DEF_WSTACK_SIZE];
+ UWord* bitstore_start;
+ ErtsAlcType_t bitstore_alloc_type;
+ Eterm shtable_default[DEF_ESTACK_SIZE];
+ Eterm* shtable_start;
+ ErtsAlcType_t shtable_alloc_type;
+ Uint literal_size;
+ Eterm *range_ptr;
+ Uint range_sz;
+} erts_shcopy_t;
+
+#define INITIALIZE_SHCOPY(info) \
+do { \
+ info.queue_start = info.queue_default; \
+ info.bitstore_start = info.bitstore_default; \
+ info.shtable_start = info.shtable_default; \
+ info.literal_size = 0; \
+ info.range_ptr = erts_clrange.ptr; \
+ info.range_sz = erts_clrange.sz; \
+} while(0)
-Eterm copy_shallow_rel(Eterm*, Uint, Eterm**, ErlOffHeap*, Eterm* src_base);
-# define copy_shallow(A,B,C,D) copy_shallow_rel(A,B,C,D,NULL)
+#define DESTROY_SHCOPY(info) \
+do { \
+ if (info.queue_start != info.queue_default) { \
+ erts_free(info.queue_alloc_type, info.queue_start); \
+ } \
+ if (info.bitstore_start != info.bitstore_default) { \
+ erts_free(info.bitstore_alloc_type, info.bitstore_start); \
+ } \
+ if (info.shtable_start != info.shtable_default) { \
+ erts_free(info.shtable_alloc_type, info.shtable_start); \
+ } \
+} while(0)
-#else /* !HALFWORD_HEAP */
+/* copy.c */
+Eterm copy_object_x(Eterm, Process*, Uint);
+#define copy_object(Term, Proc) copy_object_x(Term,Proc,0)
Uint size_object(Eterm);
-# define size_object_rel(A,B) size_object(A)
+Uint copy_shared_calculate(Eterm, erts_shcopy_t*);
+Eterm copy_shared_perform(Eterm, Uint, erts_shcopy_t*, Eterm**, ErlOffHeap*);
-Eterm copy_struct(Eterm, Uint, Eterm**, ErlOffHeap*);
-# define copy_struct_rel(OBJ,SZ,HPP,OH, SB,DB) copy_struct(OBJ,SZ,HPP,OH)
+Uint size_shared(Eterm);
+Eterm copy_struct_x(Eterm, Uint, Eterm**, ErlOffHeap*, Uint* bsz);
+#define copy_struct(Obj,Sz,HPP,OH) \
+ copy_struct_x(Obj,Sz,HPP,OH,NULL)
Eterm copy_shallow(Eterm*, Uint, Eterm**, ErlOffHeap*);
-# define copy_shallow_rel(A,B,C,D, BASE) copy_shallow(A,B,C,D)
-#endif
-
-
-void move_multi_frags(Eterm** hpp, ErlOffHeap*, ErlHeapFragment* first,
- Eterm* refs, unsigned nrefs);
+void erts_move_multi_frags(Eterm** hpp, ErlOffHeap*, ErlHeapFragment* first,
+ Eterm* refs, unsigned nrefs, int literals);
/* Utilities */
extern void erts_delete_nodes_monitors(Process *, ErtsProcLocks);
@@ -1037,6 +1169,9 @@ extern ErtsModifiedTimings erts_modified_timings[];
extern int erts_no_line_info;
extern Eterm erts_error_logger_warnings;
extern int erts_initialized;
+#if defined(USE_THREADS) && !defined(ERTS_SMP)
+extern erts_tid_t erts_main_thread;
+#endif
extern int erts_compat_rel;
extern int erts_use_sender_punish;
void erts_short_init(void);
@@ -1177,10 +1312,10 @@ int erts_utf8_to_latin1(byte* dest, const byte* source, int slen);
#define ERTS_UTF8_OK_MAX_CHARS 4
void bin_write(int, void*, byte*, size_t);
-int intlist_to_buf(Eterm, char*, int); /* most callers pass plain char*'s */
+Sint intlist_to_buf(Eterm, char*, Sint); /* most callers pass plain char*'s */
struct Sint_buf {
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
char s[22];
#else
char s[12];
@@ -1250,7 +1385,7 @@ ErlDrvSizeT erts_iolist_to_buf(Eterm, char*, ErlDrvSizeT);
ErlDrvSizeT erts_iolist_to_buf_yielding(ErtsIOList2BufState *);
int erts_iolist_size_yielding(ErtsIOListState *state);
int erts_iolist_size(Eterm, ErlDrvSizeT *);
-int is_string(Eterm);
+Sint is_string(Eterm);
void erl_at_exit(void (*) (void*), void*);
Eterm collect_memory(Process *);
void dump_memory_to_fd(int);
@@ -1296,6 +1431,29 @@ int erts_print_system_version(int to, void *arg, Process *c_p);
int erts_hibernate(Process* c_p, Eterm module, Eterm function, Eterm args, Eterm* reg);
+ERTS_GLB_FORCE_INLINE int erts_is_literal(Eterm tptr, Eterm *ptr);
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+ERTS_GLB_FORCE_INLINE int erts_is_literal(Eterm tptr, Eterm *ptr)
+{
+ ASSERT(is_boxed(tptr) || is_list(tptr));
+ ASSERT(ptr == ptr_val(tptr));
+
+#if defined(ERTS_HAVE_IS_IN_LITERAL_RANGE)
+ return erts_is_in_literal_range(ptr);
+#elif defined(TAG_LITERAL_PTR)
+ return is_literal_ptr(tptr);
+#else
+# error Not able to detect literals...
+#endif
+
+}
+
+#endif
+
+Eterm erts_msacc_request(Process *c_p, int action, Eterm *threads);
+
/*
** Call_trace uses this API for the parameter matching functions
*/
@@ -1344,191 +1502,21 @@ extern void erts_match_prog_foreach_offheap(Binary *b,
extern erts_driver_t vanilla_driver;
extern erts_driver_t spawn_driver;
+extern erts_driver_t forker_driver;
extern erts_driver_t fd_driver;
int erts_beam_jump_table(void);
-/* Should maybe be placed in erl_message.h, but then we get an include mess. */
-ERTS_GLB_INLINE Eterm *
-erts_alloc_message_heap_state(Uint size,
- ErlHeapFragment **bpp,
- ErlOffHeap **ohpp,
- Process *receiver,
- ErtsProcLocks *receiver_locks,
- erts_aint32_t *statep);
-
-ERTS_GLB_INLINE Eterm *
-erts_alloc_message_heap(Uint size,
- ErlHeapFragment **bpp,
- ErlOffHeap **ohpp,
- Process *receiver,
- ErtsProcLocks *receiver_locks);
-
-#if ERTS_GLB_INLINE_INCL_FUNC_DEF
-
-/*
- * NOTE: erts_alloc_message_heap() releases msg q and status
- * lock on receiver without ensuring that other locks are
- * held. User is responsible to ensure that the receiver
- * pointer cannot become invalid until after message has
- * been passed. This is normal done either by increasing
- * reference count on process (preferred) or by holding
- * main or link lock over the whole message passing
- * operation.
- */
-
-ERTS_GLB_INLINE Eterm *
-erts_alloc_message_heap_state(Uint size,
- ErlHeapFragment **bpp,
- ErlOffHeap **ohpp,
- Process *receiver,
- ErtsProcLocks *receiver_locks,
- erts_aint32_t *statep)
-{
- Eterm *hp;
- erts_aint32_t state;
-#ifdef ERTS_SMP
- int locked_main = 0;
- state = erts_smp_atomic32_read_acqb(&receiver->state);
- if (statep)
- *statep = state;
- if (state & (ERTS_PSFLG_EXITING
- | ERTS_PSFLG_PENDING_EXIT))
- goto allocate_in_mbuf;
-#endif
-
- if (size > (Uint) INT_MAX)
- erts_exit(ERTS_ABORT_EXIT, "HUGE size (%beu)\n", size);
-
- if (
-#if defined(ERTS_SMP)
- *receiver_locks & ERTS_PROC_LOCK_MAIN
-#else
- 1
-#endif
- ) {
-#ifdef ERTS_SMP
- try_allocate_on_heap:
-#endif
- state = erts_smp_atomic32_read_nob(&receiver->state);
- if (statep)
- *statep = state;
- if ((state & (ERTS_PSFLG_EXITING
- | ERTS_PSFLG_PENDING_EXIT))
- || (receiver->flags & F_DISABLE_GC)
- || HEAP_LIMIT(receiver) - HEAP_TOP(receiver) <= size) {
- /*
- * The heap is either potentially in an inconsistent
- * state, or not large enough.
- */
-#ifdef ERTS_SMP
- if (locked_main) {
- *receiver_locks &= ~ERTS_PROC_LOCK_MAIN;
- erts_smp_proc_unlock(receiver, ERTS_PROC_LOCK_MAIN);
- }
-#endif
- goto allocate_in_mbuf;
- }
- hp = HEAP_TOP(receiver);
- HEAP_TOP(receiver) = hp + size;
- *bpp = NULL;
- *ohpp = &MSO(receiver);
- }
-#ifdef ERTS_SMP
- else if (erts_smp_proc_trylock(receiver, ERTS_PROC_LOCK_MAIN) == 0) {
- locked_main = 1;
- *receiver_locks |= ERTS_PROC_LOCK_MAIN;
- goto try_allocate_on_heap;
- }
-#endif
- else {
- ErlHeapFragment *bp;
- allocate_in_mbuf:
- bp = new_message_buffer(size);
- hp = bp->mem;
- *bpp = bp;
- *ohpp = &bp->off_heap;
- }
-
- return hp;
-}
-
-ERTS_GLB_INLINE Eterm *
-erts_alloc_message_heap(Uint size,
- ErlHeapFragment **bpp,
- ErlOffHeap **ohpp,
- Process *receiver,
- ErtsProcLocks *receiver_locks)
-{
- return erts_alloc_message_heap_state(size, bpp, ohpp, receiver,
- receiver_locks, NULL);
-}
-
-#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
-
-#if !HEAP_ON_C_STACK
-# if defined(DEBUG)
-# define DeclareTmpHeap(VariableName,Size,Process) \
- Eterm *VariableName = erts_debug_allocate_tmp_heap(Size,Process)
-# define DeclareTypedTmpHeap(Type,VariableName,Process) \
- Type *VariableName = (Type *) erts_debug_allocate_tmp_heap(sizeof(Type)/sizeof(Eterm),Process)
-# define DeclareTmpHeapNoproc(VariableName,Size) \
- Eterm *VariableName = erts_debug_allocate_tmp_heap(Size,NULL)
-# define UseTmpHeap(Size,Proc) \
- do { \
- erts_debug_use_tmp_heap((Size),(Proc)); \
- } while (0)
-# define UnUseTmpHeap(Size,Proc) \
- do { \
- erts_debug_unuse_tmp_heap((Size),(Proc)); \
- } while (0)
-# define UseTmpHeapNoproc(Size) \
- do { \
- erts_debug_use_tmp_heap(Size,NULL); \
- } while (0)
-# define UnUseTmpHeapNoproc(Size) \
- do { \
- erts_debug_unuse_tmp_heap(Size,NULL); \
- } while (0)
-# else
-# define DeclareTmpHeap(VariableName,Size,Process) \
- Eterm *VariableName = (ERTS_PROC_GET_SCHDATA(Process)->tmp_heap)+(ERTS_PROC_GET_SCHDATA(Process)->num_tmp_heap_used)
-# define DeclareTypedTmpHeap(Type,VariableName,Process) \
- Type *VariableName = (Type *) (ERTS_PROC_GET_SCHDATA(Process)->tmp_heap)+(ERTS_PROC_GET_SCHDATA(Process)->num_tmp_heap_used)
-# define DeclareTmpHeapNoproc(VariableName,Size) \
- Eterm *VariableName = (erts_get_scheduler_data()->tmp_heap)+(erts_get_scheduler_data()->num_tmp_heap_used)
-# define UseTmpHeap(Size,Proc) \
- do { \
- ERTS_PROC_GET_SCHDATA(Proc)->num_tmp_heap_used += (Size); \
- } while (0)
-# define UnUseTmpHeap(Size,Proc) \
- do { \
- ERTS_PROC_GET_SCHDATA(Proc)->num_tmp_heap_used -= (Size); \
- } while (0)
-# define UseTmpHeapNoproc(Size) \
- do { \
- erts_get_scheduler_data()->num_tmp_heap_used += (Size); \
- } while (0)
-# define UnUseTmpHeapNoproc(Size) \
- do { \
- erts_get_scheduler_data()->num_tmp_heap_used -= (Size); \
- } while (0)
-
-
-# endif
-
-#else
-# define DeclareTmpHeap(VariableName,Size,Process) \
+#define DeclareTmpHeap(VariableName,Size,Process) \
Eterm VariableName[Size]
-# define DeclareTypedTmpHeap(Type,VariableName,Process) \
+#define DeclareTypedTmpHeap(Type,VariableName,Process) \
Type VariableName[1]
-# define DeclareTmpHeapNoproc(VariableName,Size) \
+#define DeclareTmpHeapNoproc(VariableName,Size) \
Eterm VariableName[Size]
-# define UseTmpHeap(Size,Proc) /* Nothing */
-# define UnUseTmpHeap(Size,Proc) /* Nothing */
-# define UseTmpHeapNoproc(Size) /* Nothing */
-# define UnUseTmpHeapNoproc(Size) /* Nothing */
-#endif /* HEAP_ON_C_STACK */
+#define UseTmpHeap(Size,Proc) /* Nothing */
+#define UnUseTmpHeap(Size,Proc) /* Nothing */
+#define UseTmpHeapNoproc(Size) /* Nothing */
+#define UnUseTmpHeapNoproc(Size) /* Nothing */
ERTS_GLB_INLINE void dtrace_pid_str(Eterm pid, char *process_buf);
ERTS_GLB_INLINE void dtrace_proc_str(Process *process, char *process_buf);
@@ -1576,6 +1564,7 @@ dtrace_fun_decode(Process *process,
erts_snprintf(mfa_buf, DTRACE_TERM_BUF_SIZE, "%T:%T/%d",
module, function, arity);
}
+
#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
#endif /* !__GLOBAL_H__ */
diff --git a/erts/emulator/beam/hash.c b/erts/emulator/beam/hash.c
index 895fe657d1..5a0b93f693 100644
--- a/erts/emulator/beam/hash.c
+++ b/erts/emulator/beam/hash.c
@@ -27,8 +27,6 @@
#endif
#include "sys.h"
-#include "erl_vm.h"
-#include "global.h"
#include "hash.h"
/*
@@ -66,6 +64,7 @@ void hash_get_info(HashInfo *hi, Hash *h)
int i;
int max_depth = 0;
int objects = 0;
+ int used = 0;
for (i = 0; i < size; i++) {
int depth = 0;
@@ -76,14 +75,18 @@ void hash_get_info(HashInfo *hi, Hash *h)
depth++;
b = b->next;
}
- if (depth > max_depth)
- max_depth = depth;
+ if (depth) {
+ used++;
+ if (depth > max_depth)
+ max_depth = depth;
+ }
}
+ ASSERT(objects == h->nobjs);
hi->name = h->name;
hi->size = h->size;
- hi->used = h->used;
- hi->objs = objects;
+ hi->used = used;
+ hi->objs = h->nobjs;
hi->depth = max_depth;
}
@@ -98,11 +101,11 @@ void hash_info(int to, void *arg, Hash* h)
hash_get_info(&hi, h);
- erts_print(to, arg, "=hash_table:%s\n", hi.name);
- erts_print(to, arg, "size: %d\n", hi.size);
- erts_print(to, arg, "used: %d\n", hi.used);
- erts_print(to, arg, "objs: %d\n", hi.objs);
- erts_print(to, arg, "depth: %d\n", hi.depth);
+ h->fun.meta_print(to, arg, "=hash_table:%s\n", hi.name);
+ h->fun.meta_print(to, arg, "size: %d\n", hi.size);
+ h->fun.meta_print(to, arg, "used: %d\n", hi.used);
+ h->fun.meta_print(to, arg, "objs: %d\n", hi.objs);
+ h->fun.meta_print(to, arg, "depth: %d\n", hi.depth);
}
@@ -119,47 +122,56 @@ hash_table_sz(Hash *h)
}
+static ERTS_INLINE void set_thresholds(Hash* h)
+{
+ h->grow_threshold = (8*h->size)/5; /* grow at 160% load */
+ if (h->size_ix > h->min_size_ix)
+ h->shrink_threshold = h->size / 5; /* shrink at 20% load */
+ else
+ h->shrink_threshold = -1; /* never shrink below inital size */
+}
+
/*
** init a pre allocated or static hash structure
** and allocate buckets.
*/
-Hash* hash_init(ErtsAlcType_t type, Hash* h, char* name, int size, HashFunctions fun)
+Hash* hash_init(int type, Hash* h, char* name, int size, HashFunctions fun)
{
int sz;
int ix = 0;
- h->type = type;
+ h->meta_alloc_type = type;
while (h_size_table[ix] != -1 && h_size_table[ix] < size)
ix++;
if (h_size_table[ix] == -1)
- erts_exit(ERTS_ERROR_EXIT, "panic: too large hash table size (%d)\n", size);
+ return NULL;
size = h_size_table[ix];
sz = size*sizeof(HashBucket*);
- h->bucket = (HashBucket**) erts_alloc(h->type, sz);
+ h->bucket = (HashBucket**) fun.meta_alloc(h->meta_alloc_type, sz);
sys_memzero(h->bucket, sz);
h->is_allocated = 0;
h->name = name;
h->fun = fun;
h->size = size;
- h->size20percent = h->size/5;
- h->size80percent = (4*h->size)/5;
- h->ix = ix;
- h->used = 0;
+ h->size_ix = ix;
+ h->min_size_ix = ix;
+ h->nobjs = 0;
+ set_thresholds(h);
return h;
}
/*
** Create a new hash table
*/
-Hash* hash_new(ErtsAlcType_t type, char* name, int size, HashFunctions fun)
+Hash* hash_new(int type, char* name, int size, HashFunctions fun)
{
Hash* h;
- h = erts_alloc(type, sizeof(Hash));
+ h = fun.meta_alloc(type, sizeof(Hash));
h = hash_init(type, h, name, size, fun);
h->is_allocated = 1;
@@ -183,9 +195,9 @@ void hash_delete(Hash* h)
b = b_next;
}
}
- erts_free(h->type, h->bucket);
+ h->fun.meta_free(h->meta_alloc_type, h->bucket);
if (h->is_allocated)
- erts_free(h->type, (void*) h);
+ h->fun.meta_free(h->meta_alloc_type, (void*) h);
}
/*
@@ -199,39 +211,34 @@ static void rehash(Hash* h, int grow)
int i;
if (grow) {
- if ((h_size_table[h->ix+1]) == -1)
+ if ((h_size_table[h->size_ix+1]) == -1)
return;
- h->ix++;
+ h->size_ix++;
}
else {
- if (h->ix == 0)
+ if (h->size_ix == 0)
return;
- h->ix--;
+ h->size_ix--;
}
- h->size = h_size_table[h->ix];
- h->size20percent = h->size/5;
- h->size80percent = (4*h->size)/5;
+ h->size = h_size_table[h->size_ix];
sz = h->size*sizeof(HashBucket*);
- new_bucket = (HashBucket **) erts_alloc(h->type, sz);
+ new_bucket = (HashBucket **) h->fun.meta_alloc(h->meta_alloc_type, sz);
sys_memzero(new_bucket, sz);
- h->used = 0;
-
for (i = 0; i < old_size; i++) {
HashBucket* b = h->bucket[i];
while (b != (HashBucket*) 0) {
HashBucket* b_next = b->next;
int ix = b->hvalue % h->size;
- if (new_bucket[ix] == NULL)
- h->used++;
b->next = new_bucket[ix];
new_bucket[ix] = b;
b = b_next;
}
}
- erts_free(h->type, (void *) h->bucket);
+ h->fun.meta_free(h->meta_alloc_type, (void *) h->bucket);
h->bucket = new_bucket;
+ set_thresholds(h);
}
/*
@@ -268,68 +275,15 @@ void* hash_put(Hash* h, void* tmpl)
}
b = (HashBucket*) h->fun.alloc(tmpl);
- if (h->bucket[ix] == NULL)
- h->used++;
-
b->hvalue = hval;
b->next = h->bucket[ix];
h->bucket[ix] = b;
- if (h->used > h->size80percent) /* rehash at 80% */
+ if (++h->nobjs > h->grow_threshold)
rehash(h, 1);
return (void*) b;
}
-static void
-hash_insert_entry(Hash* h, HashBucket* entry)
-{
- HashValue hval = entry->hvalue;
- int ix = hval % h->size;
- HashBucket* b = h->bucket[ix];
-
- while (b != (HashBucket*) 0) {
- if ((b->hvalue == hval) && (h->fun.cmp((void*)entry, (void*)b) == 0)) {
- abort(); /* Should not happen */
- }
- b = b->next;
- }
-
- if (h->bucket[ix] == NULL)
- h->used++;
-
- entry->next = h->bucket[ix];
- h->bucket[ix] = entry;
-
- if (h->used > h->size80percent) /* rehash at 80% */
- rehash(h, 1);
-}
-
-
-/*
- * Move all entries in src into dst; empty src.
- * Entries in src must not exist in dst.
- */
-void
-erts_hash_merge(Hash* src, Hash* dst)
-{
- int limit = src->size;
- HashBucket** bucket = src->bucket;
- int i;
-
- src->used = 0;
- for (i = 0; i < limit; i++) {
- HashBucket* b = bucket[i];
- HashBucket* next;
-
- bucket[i] = NULL;
- while (b) {
- next = b->next;
- hash_insert_entry(dst, b);
- b = next;
- }
- }
-}
-
/*
** Erase hash entry return template if erased
** return 0 if not erased
@@ -348,9 +302,7 @@ void* hash_erase(Hash* h, void* tmpl)
else
h->bucket[ix] = b->next;
h->fun.free((void*)b);
- if (h->bucket[ix] == NULL)
- h->used--;
- if (h->used < h->size20percent) /* rehash at 20% */
+ if (--h->nobjs < h->shrink_threshold)
rehash(h, 0);
return tmpl;
}
@@ -381,9 +333,7 @@ hash_remove(Hash *h, void *tmpl)
prev->next = b->next;
else
h->bucket[ix] = b->next;
- if (h->bucket[ix] == NULL)
- h->used--;
- if (h->used < h->size20percent) /* rehash at 20% */
+ if (--h->nobjs < h->shrink_threshold)
rehash(h, 0);
return (void *) b;
}
diff --git a/erts/emulator/beam/hash.h b/erts/emulator/beam/hash.h
index 87fdb360e3..e94aaa0a84 100644
--- a/erts/emulator/beam/hash.h
+++ b/erts/emulator/beam/hash.h
@@ -29,14 +29,17 @@
#include "sys.h"
#endif
-#include "erl_alloc.h"
-
typedef unsigned long HashValue;
+typedef struct hash Hash;
typedef int (*HCMP_FUN)(void*, void*);
typedef HashValue (*H_FUN)(void*);
typedef void* (*HALLOC_FUN)(void*);
typedef void (*HFREE_FUN)(void*);
+/* Meta functions */
+typedef void* (*HMALLOC_FUN)(int,size_t);
+typedef void (*HMFREE_FUN)(int,void*);
+typedef int (*HMPRINT_FUN)(int,void*,char*, ...);
/*
** This bucket must be placed in top of
@@ -55,6 +58,9 @@ typedef struct hash_functions
HCMP_FUN cmp;
HALLOC_FUN alloc;
HFREE_FUN free;
+ HMALLOC_FUN meta_alloc;
+ HMFREE_FUN meta_free;
+ HMPRINT_FUN meta_print;
} HashFunctions;
typedef struct {
@@ -65,22 +71,23 @@ typedef struct {
int depth;
} HashInfo;
-typedef struct hash
+struct hash
{
HashFunctions fun; /* Function block */
int is_allocated; /* 0 iff hash structure is on stack or is static */
- ErtsAlcType_t type;
+ int meta_alloc_type; /* argument to pass to meta_alloc and meta_free */
char* name; /* Table name (static string, for debugging) */
int size; /* Number of slots */
- int size20percent; /* 20 percent of number of slots */
- int size80percent; /* 80 percent of number of slots */
- int ix; /* Size index in size table */
- int used; /* Number of slots used */
+ int shrink_threshold;
+ int grow_threshold;
+ int size_ix; /* Size index in size table */
+ int min_size_ix; /* Never shrink table smaller than this */
+ int nobjs; /* Number of objects in table */
HashBucket** bucket; /* Vector of bucket pointers (objects) */
-} Hash;
+};
-Hash* hash_new(ErtsAlcType_t, char*, int, HashFunctions);
-Hash* hash_init(ErtsAlcType_t, Hash*, char*, int, HashFunctions);
+Hash* hash_new(int, char*, int, HashFunctions);
+Hash* hash_init(int, Hash*, char*, int, HashFunctions);
void hash_delete(Hash*);
void hash_get_info(HashInfo*, Hash*);
@@ -93,6 +100,4 @@ void* hash_erase(Hash*, void*);
void* hash_remove(Hash*, void*);
void hash_foreach(Hash*, void (*func)(void *, void *), void *);
-void erts_hash_merge(Hash* src, Hash* dst);
-
#endif
diff --git a/erts/emulator/beam/index.h b/erts/emulator/beam/index.h
index 14fab41026..99b2bdfab0 100644
--- a/erts/emulator/beam/index.h
+++ b/erts/emulator/beam/index.h
@@ -30,6 +30,10 @@
#include "hash.h"
#endif
+#ifndef ERL_ALLOC_H__
+#include "erl_alloc.h"
+#endif
+
typedef struct index_slot
{
HashBucket bucket;
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index 81a05a6b87..797e4cdadc 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -53,10 +53,11 @@
#include "erl_time.h"
extern ErlDrvEntry fd_driver_entry;
-#ifndef __OSE__
extern ErlDrvEntry vanilla_driver_entry;
-#endif
extern ErlDrvEntry spawn_driver_entry;
+#ifndef __WIN32__
+extern ErlDrvEntry forker_driver_entry;
+#endif
extern ErlDrvEntry *driver_tab[]; /* table of static drivers, only used during initialization */
erts_driver_t *driver_list; /* List of all drivers, static and dynamic. */
@@ -74,6 +75,9 @@ const Port erts_invalid_port = {{ERTS_INVALID_PORT}};
erts_driver_t vanilla_driver;
erts_driver_t spawn_driver;
+#ifndef __WIN32__
+erts_driver_t forker_driver;
+#endif
erts_driver_t fd_driver;
int erts_port_synchronous_ops = 0;
@@ -87,6 +91,7 @@ static void deliver_result(Eterm sender, Eterm pid, Eterm res);
static int init_driver(erts_driver_t *, ErlDrvEntry *, DE_Handle *);
static void terminate_port(Port *p);
static void pdl_init(void);
+static int driver_failure_term(ErlDrvPort ix, Eterm term, int eof);
#ifdef ERTS_SMP
static void driver_monitor_lock_pdl(Port *p);
static void driver_monitor_unlock_pdl(Port *p);
@@ -308,12 +313,9 @@ static Port *create_port(char *name,
size_t port_size, busy_port_queue_size, size;
erts_aint32_t state = ERTS_PORT_SFLG_CONNECTED;
erts_aint32_t x_pts_flgs = 0;
-#ifdef DEBUG
- /* Make sure the debug flags survives until port is freed */
- state |= ERTS_PORT_SFLG_PORT_DEBUG;
-#endif
#ifdef ERTS_SMP
+ ErtsRunQueue *runq;
if (!driver_lock) {
/* Align size for mutex following port struct */
port_size = size = ERTS_ALC_DATA_ALIGN_SIZE(sizeof(Port));
@@ -323,6 +325,12 @@ static Port *create_port(char *name,
#endif
port_size = size = ERTS_ALC_DATA_ALIGN_SIZE(sizeof(Port));
+#ifdef DEBUG
+ /* Make sure the debug flags survives until port is freed */
+ state |= ERTS_PORT_SFLG_PORT_DEBUG;
+#endif
+
+
busy_port_queue_size
= ((driver->flags & ERL_DRV_FLAG_NO_BUSY_MSGQ)
? 0
@@ -358,8 +366,12 @@ static Port *create_port(char *name,
p += sizeof(erts_mtx_t);
state |= ERTS_PORT_SFLG_PORT_SPECIFIC_LOCK;
}
- erts_smp_atomic_set_nob(&prt->run_queue,
- (erts_aint_t) erts_get_runq_current(NULL));
+ if (erts_get_scheduler_data())
+ runq = erts_get_runq_current(NULL);
+ else
+ runq = ERTS_RUNQ_IX(0);
+ erts_smp_atomic_set_nob(&prt->run_queue, (erts_aint_t) runq);
+
prt->xports = NULL;
#else
erts_atomic32_init_nob(&prt->refc, 1);
@@ -386,6 +398,7 @@ static Port *create_port(char *name,
ERTS_PTMR_INIT(prt);
erts_port_task_handle_init(&prt->timeout_task);
prt->psd = NULL;
+ prt->async_open_port = NULL;
prt->drv_data = (SWord) 0;
prt->os_pid = -1;
@@ -467,6 +480,11 @@ erts_port_free(Port *prt)
erts_port_task_fini_sched(&prt->sched);
+ if (prt->async_open_port) {
+ erts_free(ERTS_ALC_T_PRTSD, prt->async_open_port);
+ prt->async_open_port = NULL;
+ }
+
#ifdef ERTS_SMP
ASSERT(prt->lock);
if (state & ERTS_PORT_SFLG_PORT_SPECIFIC_LOCK)
@@ -688,6 +706,7 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */
error_number = error_type = 0;
if (driver->start) {
+ ERTS_MSACC_PUSH_STATE_M();
if (IS_TRACED_FL(port, F_TRACE_SCHED_PORTS)) {
trace_sched_ports_where(port, am_in, am_start);
}
@@ -698,6 +717,7 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */
DTRACE3(driver_start, process_str, driver->name, port_str);
}
#endif
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_PORT);
fpe_was_unmasked = erts_block_fpe();
drv_data = (*driver->start)(ERTS_Port2ErlDrvPort(port), name, opts);
if (((SWord) drv_data) == -1)
@@ -717,6 +737,7 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */
}
erts_unblock_fpe(fpe_was_unmasked);
+ ERTS_MSACC_POP_STATE_M();
port->caller = NIL;
if (IS_TRACED_FL(port, F_TRACE_SCHED_PORTS)) {
trace_sched_ports_where(port, am_out, am_start);
@@ -1106,7 +1127,7 @@ io_list_vec_len(Eterm obj, int* vsize, Uint* csize,
Uint p_v_size = 0;
Uint p_c_size = 0;
Uint p_in_clist = 0;
- Uint total; /* Uint due to halfword emulator */
+ Uint total;
goto L_jump_start; /* avoid a push */
@@ -1413,7 +1434,7 @@ queue_port_sched_op_reply(Process *rp,
erts_factory_trim_and_close(factory, &msg, 1);
- erts_queue_message(rp, rp_locksp, factory->heap_frags, msg, NIL);
+ erts_queue_message(rp, rp_locksp, factory->message, msg, NIL);
}
static void
@@ -1421,12 +1442,9 @@ port_sched_op_reply(Eterm to, Uint32 *ref_num, Eterm msg)
{
Process *rp = erts_proc_lookup_raw(to);
if (rp) {
- ErlOffHeap *ohp;
- ErlHeapFragment* bp;
ErtsHeapFactory factory;
Eterm msg_copy;
Uint hsz, msg_sz;
- Eterm *hp;
ErtsProcLocks rp_locks = 0;
hsz = ERTS_QUEUE_PORT_SCHED_OP_REPLY_SIZE;
@@ -1437,18 +1455,13 @@ port_sched_op_reply(Eterm to, Uint32 *ref_num, Eterm msg)
hsz += msg_sz;
}
- hp = erts_alloc_message_heap(hsz,
- &bp,
- &ohp,
- rp,
- &rp_locks);
- erts_factory_message_init(&factory, rp, hp, bp);
- if (is_immed(msg))
- msg_copy = msg;
- else {
- msg_copy = copy_struct(msg, msg_sz, &hp, ohp);
- factory.hp = hp;
- }
+ (void) erts_factory_message_create(&factory, rp,
+ &rp_locks, hsz);
+ msg_copy = (is_immed(msg)
+ ? msg
+ : copy_struct(msg, msg_sz,
+ &factory.hp,
+ factory.off_heap));
queue_port_sched_op_reply(rp,
&rp_locks,
@@ -1536,6 +1549,26 @@ erts_schedule_proc2port_signal(Process *c_p,
return ERTS_PORT_OP_SCHEDULED;
}
+static int
+erts_schedule_port2port_signal(Eterm port_num, ErtsProc2PortSigData *sigdp,
+ int task_flags,
+ ErtsProc2PortSigCallback callback)
+{
+ Port *prt = erts_port_lookup_raw(port_num);
+
+ if (!prt)
+ return -1;
+
+ sigdp->caller = ERTS_INVALID_PID;
+
+ return erts_port_task_schedule(prt->common.id,
+ NULL,
+ ERTS_PORT_TASK_PROC_SIG,
+ sigdp,
+ callback,
+ task_flags);
+}
+
static ERTS_INLINE void
send_badsig(Port *prt) {
ErtsProcLocks rp_locks = ERTS_PROC_LOCKS_XSIG_SEND;
@@ -1680,6 +1713,7 @@ call_driver_outputv(int bang_op,
else {
ErtsSchedulerData *esdp = erts_get_scheduler_data();
ErlDrvSizeT size = evp->size;
+ ERTS_MSACC_PUSH_AND_SET_STATE_M(ERTS_MSACC_STATE_PORT);
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt)
|| ERTS_IS_CRASH_DUMPING);
@@ -1700,6 +1734,8 @@ call_driver_outputv(int bang_op,
esdp->io.out += (Uint64) size;
else
erts_atomic64_add_nob(&bytes_out, (erts_aint64_t) size);
+
+ ERTS_MSACC_POP_STATE_M();
}
}
@@ -1780,6 +1816,7 @@ call_driver_output(int bang_op,
send_badsig(prt);
else {
ErtsSchedulerData *esdp = erts_get_scheduler_data();
+ ERTS_MSACC_PUSH_AND_SET_STATE_M(ERTS_MSACC_STATE_PORT);
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt)
|| ERTS_IS_CRASH_DUMPING);
@@ -1799,6 +1836,8 @@ call_driver_output(int bang_op,
esdp->io.out += (Uint64) size;
else
erts_atomic64_add_nob(&bytes_out, (erts_aint64_t) size);
+
+ ERTS_MSACC_POP_STATE_M();
}
}
@@ -2371,6 +2410,11 @@ erts_port_exit(Process *c_p,
| ERTS_PORT_SIG_FLG_BROKEN_LINK
| ERTS_PORT_SIG_FLG_FORCE_SCHED)) == 0);
+#ifndef __WIN32__
+ if (prt->drv_ptr == &forker_driver)
+ return ERTS_PORT_OP_DROPPED;
+#endif
+
if (!(flags & ERTS_PORT_SIG_FLG_FORCE_SCHED)) {
ErtsTryImmDrvCallState try_call_state
= ERTS_INIT_TRY_IMM_DRV_CALL_STATE(c_p,
@@ -2735,6 +2779,72 @@ erts_port_link(Process *c_p, Port *prt, Eterm to, Eterm *refp)
port_sig_link);
}
+static void
+init_ack_send_reply(Port *port, Eterm resp)
+{
+
+ if (!is_internal_port(resp)) {
+ Process *rp = erts_proc_lookup_raw(port->async_open_port->to);
+ erts_smp_proc_lock(rp, ERTS_PROC_LOCK_LINK);
+ erts_remove_link(&ERTS_P_LINKS(port), port->async_open_port->to);
+ erts_remove_link(&ERTS_P_LINKS(rp), port->common.id);
+ erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_LINK);
+ }
+ port_sched_op_reply(port->async_open_port->to,
+ port->async_open_port->ref,
+ resp);
+
+ erts_free(ERTS_ALC_T_PRTSD, port->async_open_port);
+ port->async_open_port = NULL;
+}
+
+void
+erl_drv_init_ack(ErlDrvPort ix, ErlDrvData res) {
+ Port *port = erts_drvport2port(ix);
+ SWord err_type = (SWord)res;
+ Eterm resp;
+
+ if (port == ERTS_INVALID_ERL_DRV_PORT && port->async_open_port)
+ return;
+
+ if (port->async_open_port) {
+ switch(err_type) {
+ case -3:
+ resp = am_badarg;
+ break;
+ case -2: {
+ char *str = erl_errno_id(errno);
+ resp = erts_atom_put((byte *) str, strlen(str),
+ ERTS_ATOM_ENC_LATIN1, 1);
+ break;
+ }
+ case -1:
+ resp = am_einval;
+ break;
+ default:
+ resp = port->common.id;
+ break;
+ }
+
+ init_ack_send_reply(port, resp);
+
+ if (err_type == -1 || err_type == -2 || err_type == -3)
+ driver_failure_term(ix, am_normal, 0);
+ port->drv_data = err_type;
+ }
+}
+
+void
+erl_drv_set_os_pid(ErlDrvPort ix, ErlDrvSInt pid) {
+ Port *port = erts_drvport2port(ix);
+
+ if (port == ERTS_INVALID_ERL_DRV_PORT)
+ return;
+
+ port->os_pid = (SWord)pid;
+
+}
+
void erts_init_io(int port_tab_size,
int port_tab_size_ignore_files,
int legacy_port_tab)
@@ -2795,10 +2905,11 @@ void erts_init_io(int port_tab_size,
erts_smp_rwmtx_rwlock(&erts_driver_list_lock);
init_driver(&fd_driver, &fd_driver_entry, NULL);
-#ifndef __OSE__
init_driver(&vanilla_driver, &vanilla_driver_entry, NULL);
-#endif
init_driver(&spawn_driver, &spawn_driver_entry, NULL);
+#ifndef __WIN32__
+ init_driver(&forker_driver, &forker_driver_entry, NULL);
+#endif
erts_init_static_drivers();
for (dp = driver_tab; *dp != NULL; dp++)
erts_add_driver_entry(*dp, NULL, 1);
@@ -2860,6 +2971,9 @@ void erts_lcnt_enable_io_lock_count(int enable) {
lcnt_enable_drv_lock_count(&vanilla_driver, enable);
lcnt_enable_drv_lock_count(&spawn_driver, enable);
+#ifndef __WIN32__
+ lcnt_enable_drv_lock_count(&forker_driver, enable);
+#endif
lcnt_enable_drv_lock_count(&fd_driver, enable);
/* enable lock counting in all drivers */
for (dp = driver_list; dp; dp = dp->next) {
@@ -3055,16 +3169,17 @@ deliver_result(Eterm sender, Eterm pid, Eterm res)
if (rp) {
Eterm tuple;
- ErlHeapFragment *bp;
+ ErtsMessage *mp;
ErlOffHeap *ohp;
Eterm* hp;
Uint sz_res;
sz_res = size_object(res);
- hp = erts_alloc_message_heap(sz_res + 3, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks,
+ sz_res + 3, &hp, &ohp);
res = copy_struct(res, sz_res, &hp, ohp);
tuple = TUPLE2(hp, sender, res);
- erts_queue_message(rp, &rp_locks, bp, tuple, NIL);
+ erts_queue_message(rp, &rp_locks, mp, tuple, NIL);
if (rp_locks)
erts_smp_proc_unlock(rp, rp_locks);
@@ -3092,7 +3207,7 @@ static void deliver_read_message(Port* prt, erts_aint32_t state, Eterm to,
Eterm tuple;
Process* rp;
Eterm* hp;
- ErlHeapFragment *bp;
+ ErtsMessage *mp;
ErlOffHeap *ohp;
ErtsProcLocks rp_locks = 0;
int scheduler = erts_get_scheduler_id() != 0;
@@ -3118,7 +3233,7 @@ static void deliver_read_message(Port* prt, erts_aint32_t state, Eterm to,
if (!rp)
return;
- hp = erts_alloc_message_heap(need, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, need, &hp, &ohp);
listp = NIL;
if ((state & ERTS_PORT_SFLG_BINARY_IO) == 0) {
@@ -3160,7 +3275,7 @@ static void deliver_read_message(Port* prt, erts_aint32_t state, Eterm to,
tuple = TUPLE2(hp, prt->common.id, tuple);
hp += 3;
- erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined);
+ erts_queue_message(rp, &rp_locks, mp, tuple, am_undefined);
if (rp_locks)
erts_smp_proc_unlock(rp, rp_locks);
if (!scheduler)
@@ -3234,7 +3349,7 @@ deliver_vec_message(Port* prt, /* Port */
Eterm tuple;
Process* rp;
Eterm* hp;
- ErlHeapFragment *bp;
+ ErtsMessage *mp;
ErlOffHeap *ohp;
ErtsProcLocks rp_locks = 0;
int scheduler = erts_get_scheduler_id() != 0;
@@ -3266,7 +3381,7 @@ deliver_vec_message(Port* prt, /* Port */
need += (hlen+csize)*2;
}
- hp = erts_alloc_message_heap(need, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, need, &hp, &ohp);
listp = NIL;
iov += vsize;
@@ -3327,7 +3442,7 @@ deliver_vec_message(Port* prt, /* Port */
tuple = TUPLE2(hp, prt->common.id, tuple);
hp += 3;
- erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined);
+ erts_queue_message(rp, &rp_locks, mp, tuple, am_undefined);
erts_smp_proc_unlock(rp, rp_locks);
if (!scheduler)
erts_proc_dec_refc(rp);
@@ -3367,6 +3482,7 @@ static void flush_port(Port *p)
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(p));
if (p->drv_ptr->flush != NULL) {
+ ERTS_MSACC_PUSH_STATE_M();
#ifdef USE_VM_PROBES
if (DTRACE_ENABLED(driver_flush)) {
DTRACE_FORMAT_COMMON_PID_AND_PORT(ERTS_PORT_GET_CONNECTED(p), p)
@@ -3376,9 +3492,11 @@ static void flush_port(Port *p)
if (IS_TRACED_FL(p, F_TRACE_SCHED_PORTS)) {
trace_sched_ports_where(p, am_in, am_flush);
}
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_PORT);
fpe_was_unmasked = erts_block_fpe();
(*p->drv_ptr->flush)((ErlDrvData)p->drv_data);
erts_unblock_fpe(fpe_was_unmasked);
+ ERTS_MSACC_POP_STATE_M();
if (IS_TRACED_FL(p, F_TRACE_SCHED_PORTS)) {
trace_sched_ports_where(p, am_out, am_flush);
}
@@ -3426,6 +3544,7 @@ terminate_port(Port *prt)
drv = prt->drv_ptr;
if ((drv != NULL) && (drv->stop != NULL)) {
int fpe_was_unmasked = erts_block_fpe();
+ ERTS_MSACC_PUSH_AND_SET_STATE_M(ERTS_MSACC_STATE_PORT);
#ifdef USE_VM_PROBES
if (DTRACE_ENABLED(driver_stop)) {
DTRACE_FORMAT_COMMON_PID_AND_PORT(connected_id, prt)
@@ -3434,6 +3553,7 @@ terminate_port(Port *prt)
#endif
(*drv->stop)((ErlDrvData)prt->drv_data);
erts_unblock_fpe(fpe_was_unmasked);
+ ERTS_MSACC_POP_STATE_M();
#ifdef ERTS_SMP
if (prt->xports)
erts_port_handle_xports(prt);
@@ -3744,6 +3864,7 @@ call_driver_control(Eterm caller,
ErlDrvSizeT *from_size)
{
ErlDrvSSizeT cres;
+ ERTS_MSACC_PUSH_STATE_M();
if (!prt->drv_ptr->control)
return ERTS_PORT_OP_BADARG;
@@ -3757,6 +3878,8 @@ call_driver_control(Eterm caller,
command, size);
}
#endif
+
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_PORT);
prt->caller = caller;
cres = prt->drv_ptr->control((ErlDrvData) prt->drv_data,
@@ -3767,6 +3890,8 @@ call_driver_control(Eterm caller,
*from_size);
prt->caller = NIL;
+ ERTS_MSACC_POP_STATE_M();
+
if (cres < 0)
return ERTS_PORT_OP_BADARG;
@@ -3818,7 +3943,6 @@ write_port_control_result(int control_flags,
ErlDrvSizeT resp_size,
char *pre_alloc_buf,
Eterm **hpp,
- ErlHeapFragment *bp,
ErlOffHeap *ohp)
{
Eterm res;
@@ -3892,16 +4016,13 @@ port_sig_control(Port *prt,
if (res == ERTS_PORT_OP_DONE) {
Eterm msg;
- Eterm *hp;
- ErlHeapFragment *bp;
- ErlOffHeap *ohp;
ErtsHeapFactory factory;
Process *rp;
ErtsProcLocks rp_locks = 0;
Uint hsz, rsz;
int control_flags;
- rp = erts_proc_lookup_raw(sigdp->caller);
+ rp = sigdp->caller == ERTS_INVALID_PID ? NULL : erts_proc_lookup_raw(sigdp->caller);
if (!rp)
goto done;
@@ -3914,22 +4035,15 @@ port_sig_control(Port *prt,
hsz = rsz + ERTS_QUEUE_PORT_SCHED_OP_REPLY_SIZE;
- hp = erts_alloc_message_heap(hsz,
- &bp,
- &ohp,
- rp,
- &rp_locks);
- erts_factory_message_init(&factory, rp, hp, bp);
+ (void) erts_factory_message_create(&factory, rp,
+ &rp_locks, hsz);
msg = write_port_control_result(control_flags,
resp_bufp,
resp_size,
&resp_buf[0],
- &hp,
- bp,
- ohp);
- factory.hp = hp;
-
+ &factory.hp,
+ factory.off_heap);
queue_port_sched_op_reply(rp,
&rp_locks,
&factory,
@@ -3944,7 +4058,8 @@ port_sig_control(Port *prt,
/* failure */
- port_sched_op_reply(sigdp->caller, sigdp->ref, am_badarg);
+ if (sigdp->caller != ERTS_INVALID_PID)
+ port_sched_op_reply(sigdp->caller, sigdp->ref, am_badarg);
done:
@@ -3954,6 +4069,23 @@ done:
return ERTS_PORT_REDS_CONTROL;
}
+/*
+ * This is an asynchronous control call. I.e. it will not return anything
+ * to the caller.
+ */
+int
+erl_drv_port_control(Eterm port_num, char cmd, char* buff, ErlDrvSizeT size)
+{
+ ErtsProc2PortSigData *sigdp = erts_port_task_alloc_p2p_sig_data();
+
+ sigdp->flags = ERTS_P2P_SIG_TYPE_CONTROL | ERTS_P2P_SIG_DATA_FLG_REPLY;
+ sigdp->u.control.binp = NULL;
+ sigdp->u.control.command = cmd;
+ sigdp->u.control.bufp = buff;
+ sigdp->u.control.size = size;
+
+ return erts_schedule_port2port_signal(port_num, sigdp, 0, port_sig_control);
+}
ErtsPortOpResult
erts_port_control(Process* c_p,
@@ -4070,7 +4202,6 @@ erts_port_control(Process* c_p,
resp_size,
&resp_buf[0],
&hp,
- NULL,
&c_p->off_heap);
BUMP_REDS(c_p, ERTS_PORT_REDS_CONTROL);
return ERTS_PORT_OP_DONE;
@@ -4092,10 +4223,10 @@ erts_port_control(Process* c_p,
binp = NULL;
if (is_binary(data) && binary_bitoffset(data) == 0) {
- Eterm *ebinp = binary_val_rel(data, NULL);
+ Eterm *ebinp = binary_val(data);
ASSERT(!tmp_alloced);
if (*ebinp == HEADER_SUB_BIN)
- ebinp = binary_val_rel(((ErlSubBin *) ebinp)->orig, NULL);
+ ebinp = binary_val(((ErlSubBin *) ebinp)->orig);
if (*ebinp != HEADER_PROC_BIN)
copy = 1;
else {
@@ -4148,6 +4279,7 @@ call_driver_call(Eterm caller,
unsigned *ret_flagsp)
{
ErlDrvSSizeT cres;
+ ERTS_MSACC_PUSH_STATE_M();
if (!prt->drv_ptr->call)
return ERTS_PORT_OP_BADARG;
@@ -4163,6 +4295,8 @@ call_driver_call(Eterm caller,
}
#endif
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_PORT);
+
prt->caller = caller;
cres = prt->drv_ptr->call((ErlDrvData) prt->drv_data,
command,
@@ -4173,6 +4307,8 @@ call_driver_call(Eterm caller,
ret_flagsp);
prt->caller = NIL;
+ ERTS_MSACC_POP_STATE_M();
+
if (cres <= 0
|| ((byte) (*resp_bufp)[0]) != VERSION_MAGIC)
return ERTS_PORT_OP_BADARG;
@@ -4229,21 +4365,14 @@ port_sig_call(Port *prt,
hsz = erts_decode_ext_size((byte *) resp_bufp, resp_size);
if (hsz >= 0) {
- ErlHeapFragment* bp;
- ErlOffHeap* ohp;
ErtsHeapFactory factory;
byte *endp;
hsz += 3; /* ok tuple */
hsz += ERTS_QUEUE_PORT_SCHED_OP_REPLY_SIZE;
- hp = erts_alloc_message_heap(hsz,
- &bp,
- &ohp,
- rp,
- &rp_locks);
+ (void) erts_factory_message_create(&factory, rp, &rp_locks, hsz);
endp = (byte *) resp_bufp;
- erts_factory_message_init(&factory, rp, hp, bp);
msg = erts_decode_ext(&factory, &endp);
if (is_value(msg)) {
hp = erts_produce_heap(&factory,
@@ -4504,7 +4633,9 @@ port_sig_info(Port *prt,
sigdp->u.info.item);
if (is_value(value)) {
ErtsHeapFactory factory;
- erts_factory_message_init(&factory, NULL, hp, bp);
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = bp;
+ erts_factory_selfcontained_message_init(&factory, mp, hp);
queue_port_sched_op_reply(rp,
&rp_locks,
&factory,
@@ -4592,8 +4723,8 @@ reply_io_bytes(void *vreq)
rp = erts_proc_lookup(req->pid);
if (rp) {
- ErlOffHeap *ohp = NULL;
- ErlHeapFragment *bp = NULL;
+ ErlOffHeap *ohp;
+ ErtsMessage *mp;
ErtsProcLocks rp_locks;
Eterm ref, msg, ein, eout, *hp;
Uint64 in, out;
@@ -4615,7 +4746,7 @@ reply_io_bytes(void *vreq)
erts_bld_uint64(NULL, &hsz, in);
erts_bld_uint64(NULL, &hsz, out);
- hp = erts_alloc_message_heap(hsz, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, hsz, &hp, &ohp);
ref = make_internal_ref(hp);
write_ref_thing(hp, req->refn[0], req->refn[1], req->refn[2]);
@@ -4625,7 +4756,7 @@ reply_io_bytes(void *vreq)
eout = erts_bld_uint64(&hp, NULL, out);
msg = TUPLE4(hp, ref, make_small(sched_id), ein, eout);
- erts_queue_message(rp, &rp_locks, bp, msg, NIL);
+ erts_queue_message(rp, &rp_locks, mp, msg, NIL);
if (req->sched_id == sched_id)
rp_locks &= ~ERTS_PROC_LOCK_MAIN;
@@ -4731,6 +4862,10 @@ print_port_info(Port *p, int to, void *arg)
erts_print(to, arg, "Port is a file: %s\n",p->name);
} else if (p->drv_ptr == &spawn_driver) {
erts_print(to, arg, "Port controls external process: %s\n",p->name);
+#ifndef __WIN32__
+ } else if (p->drv_ptr == &forker_driver) {
+ erts_print(to, arg, "Port controls forker process: %s\n",p->name);
+#endif
} else {
erts_print(to, arg, "Port controls linked-in driver: %s\n",p->name);
}
@@ -4877,6 +5012,7 @@ int get_port_flags(ErlDrvPort ix)
void erts_raw_port_command(Port* p, byte* buf, Uint len)
{
int fpe_was_unmasked;
+ ERTS_MSACC_PUSH_STATE_M();
ERTS_SMP_CHK_NO_PROC_LOCKS;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(p));
@@ -4897,9 +5033,11 @@ void erts_raw_port_command(Port* p, byte* buf, Uint len)
DTRACE4(driver_output, "-raw-", port_str, p->name, len);
}
#endif
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_PORT);
fpe_was_unmasked = erts_block_fpe();
(*p->drv_ptr->output)((ErlDrvData)p->drv_data, (char*) buf, (int) len);
erts_unblock_fpe(fpe_was_unmasked);
+ ERTS_MSACC_POP_STATE_M();
}
int async_ready(Port *p, void* data)
@@ -4911,6 +5049,7 @@ int async_ready(Port *p, void* data)
if (p) {
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(p));
if (p->drv_ptr->ready_async != NULL) {
+ ERTS_MSACC_PUSH_AND_SET_STATE_M(ERTS_MSACC_STATE_PORT);
#ifdef USE_VM_PROBES
if (DTRACE_ENABLED(driver_ready_async)) {
DTRACE_FORMAT_COMMON_PID_AND_PORT(ERTS_PORT_GET_CONNECTED(p), p)
@@ -4919,6 +5058,7 @@ int async_ready(Port *p, void* data)
#endif
(*p->drv_ptr->ready_async)((ErlDrvData)p->drv_data, data);
need_free = 0;
+ ERTS_MSACC_POP_STATE_M();
}
erts_port_driver_callback_epilogue(p, NULL);
@@ -5070,11 +5210,11 @@ ErlDrvTermData driver_mk_term_nil(void)
void driver_report_exit(ErlDrvPort ix, int status)
{
Eterm* hp;
+ ErlOffHeap *ohp;
Eterm tuple;
Process *rp;
Eterm pid;
- ErlHeapFragment *bp = NULL;
- ErlOffHeap *ohp;
+ ErtsMessage *mp;
ErtsProcLocks rp_locks = 0;
int scheduler = erts_get_scheduler_id() != 0;
Port* prt = erts_drvport2port(ix);
@@ -5094,13 +5234,13 @@ void driver_report_exit(ErlDrvPort ix, int status)
if (!rp)
return;
- hp = erts_alloc_message_heap(3+3, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, 3+3, &hp, &ohp);
tuple = TUPLE2(hp, am_exit_status, make_small(status));
hp += 3;
tuple = TUPLE2(hp, prt->common.id, tuple);
- erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined);
+ erts_queue_message(rp, &rp_locks, mp, tuple, am_undefined);
erts_smp_proc_unlock(rp, rp_locks);
if (!scheduler)
@@ -5210,7 +5350,6 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len)
ErtsProcLocks rp_locks = 0;
struct b2t_states__ b2t;
int scheduler;
- int is_heap_need_limited = 1;
ErtsSchedulerData *esdp = erts_get_scheduler_data();
ERTS_UNDEF(mess,NIL);
@@ -5249,25 +5388,17 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len)
break;
case ERL_DRV_INT: /* signed int argument */
ERTS_DDT_CHK_ENOUGH_ARGS(1);
-#if HALFWORD_HEAP
- erts_bld_sint64(NULL, &need, (Sint64)ptr[0]);
-#else
/* check for bignum */
if (!IS_SSMALL((Sint)ptr[0]))
need += BIG_UINT_HEAP_SIZE; /* use small_to_big */
-#endif
ptr++;
depth++;
break;
case ERL_DRV_UINT: /* unsigned int argument */
ERTS_DDT_CHK_ENOUGH_ARGS(1);
-#if HALFWORD_HEAP
- erts_bld_uint64(NULL, &need, (Uint64)ptr[0]);
-#else
/* check for bignum */
if (!IS_USMALL(0, (Uint)ptr[0]))
need += BIG_UINT_HEAP_SIZE; /* use small_to_big */
-#endif
ptr++;
depth++;
break;
@@ -5387,9 +5518,6 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len)
need += hsz;
ptr += 2;
depth++;
- if (size > MAP_SMALL_MAP_LIMIT*3) { /* may contain big map */
- is_heap_need_limited = 0;
- }
break;
}
case ERL_DRV_MAP: { /* int */
@@ -5397,7 +5525,6 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len)
if ((int) ptr[0] < 0) ERTS_DDT_FAIL;
if (ptr[0] > MAP_SMALL_MAP_LIMIT) {
need += HASHMAP_ESTIMATED_HEAP_SIZE(ptr[0]);
- is_heap_need_limited = 0;
} else {
need += MAP_HEADER_FLATMAP_SZ + 1 + 2*ptr[0];
}
@@ -5436,17 +5563,7 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len)
goto done;
}
- /* Try copy directly to destination heap if we know there are no big maps */
- if (is_heap_need_limited) {
- ErlOffHeap *ohp;
- ErlHeapFragment* bp;
- Eterm* hp = erts_alloc_message_heap(need, &bp, &ohp, rp, &rp_locks);
- erts_factory_message_init(&factory, rp, hp, bp);
- }
- else {
- erts_factory_message_init(&factory, NULL, NULL,
- new_message_buffer(need));
- }
+ (void) erts_factory_message_create(&factory, rp, &rp_locks, need);
/*
* Interpret the instructions and build the term.
@@ -5466,10 +5583,6 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len)
break;
case ERL_DRV_INT: /* signed int argument */
-#if HALFWORD_HEAP
- erts_reserve_heap(&factory, BIG_NEED_SIZE(2));
- mess = erts_bld_sint64(&factory.hp, NULL, (Sint64)ptr[0]);
-#else
erts_reserve_heap(&factory, BIG_UINT_HEAP_SIZE);
if (IS_SSMALL((Sint)ptr[0]))
mess = make_small((Sint)ptr[0]);
@@ -5477,15 +5590,10 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len)
mess = small_to_big((Sint)ptr[0], factory.hp);
factory.hp += BIG_UINT_HEAP_SIZE;
}
-#endif
ptr++;
break;
case ERL_DRV_UINT: /* unsigned int argument */
-#if HALFWORD_HEAP
- erts_reserve_heap(&factory, BIG_NEED_FOR_BITS(64));
- mess = erts_bld_uint64(&factory.hp, NULL, (Uint64)ptr[0]);
-#else
erts_reserve_heap(&factory, BIG_UINT_HEAP_SIZE);
if (IS_USMALL(0, (Uint)ptr[0]))
mess = make_small((Uint)ptr[0]);
@@ -5493,7 +5601,6 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len)
mess = uint_to_big((Uint)ptr[0], factory.hp);
factory.hp += BIG_UINT_HEAP_SIZE;
}
-#endif
ptr++;
break;
@@ -5725,9 +5832,9 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len)
if (res > 0) {
mess = ESTACK_POP(stack); /* get resulting value */
- erts_factory_close(&factory);
+ erts_factory_trim_and_close(&factory, &mess, 1);
/* send message */
- erts_queue_message(rp, &rp_locks, factory.heap_frags, mess, am_undefined);
+ erts_queue_message(rp, &rp_locks, factory.message, mess, am_undefined);
}
else {
if (b2t.ix > b2t.used)
@@ -6832,7 +6939,7 @@ int driver_monitor_process(ErlDrvPort drvport,
{
Port *prt;
int ret;
-#if !HEAP_ON_C_STACK || (defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK))
+#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
ErtsSchedulerData *sched = erts_get_scheduler_data();
#endif
@@ -6843,16 +6950,6 @@ int driver_monitor_process(ErlDrvPort drvport,
/* Now (in SMP) we should have either the port lock (if we have a scheduler) or the port data lock
(if we're a driver thread) */
ERTS_SMP_LC_ASSERT((sched != NULL || prt->port_data_lock));
-
-#if !HEAP_ON_C_STACK
- if (!sched) {
- /* Need a separate allocation for the ref :( */
- Eterm *buf = erts_alloc(ERTS_ALC_T_TEMP_TERM,
- sizeof(Eterm)*REF_THING_SIZE);
- ret = do_driver_monitor_process(prt,buf,process,monitor);
- erts_free(ERTS_ALC_T_TEMP_TERM,buf);
- } else
-#endif
{
DeclareTmpHeapNoproc(buf,REF_THING_SIZE);
UseTmpHeapNoproc(REF_THING_SIZE);
@@ -6905,7 +7002,7 @@ int driver_demonitor_process(ErlDrvPort drvport,
{
Port *prt;
int ret;
-#if !HEAP_ON_C_STACK || (defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK))
+#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
ErtsSchedulerData *sched = erts_get_scheduler_data();
#endif
@@ -6916,15 +7013,6 @@ int driver_demonitor_process(ErlDrvPort drvport,
/* Now we should have either the port lock (if we have a scheduler) or the port data lock
(if we're a driver thread) */
ERTS_SMP_LC_ASSERT((sched != NULL || prt->port_data_lock));
-#if !HEAP_ON_C_STACK
- if (!sched) {
- /* Need a separate allocation for the ref :( */
- Eterm *buf = erts_alloc(ERTS_ALC_T_TEMP_TERM,
- sizeof(Eterm)*REF_THING_SIZE);
- ret = do_driver_demonitor_process(prt,buf,monitor);
- erts_free(ERTS_ALC_T_TEMP_TERM,buf);
- } else
-#endif
{
DeclareTmpHeapNoproc(buf,REF_THING_SIZE);
UseTmpHeapNoproc(REF_THING_SIZE);
@@ -6960,7 +7048,7 @@ ErlDrvTermData driver_get_monitored_process(ErlDrvPort drvport,
{
Port *prt;
ErlDrvTermData ret;
-#if !HEAP_ON_C_STACK || (defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK))
+#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
ErtsSchedulerData *sched = erts_get_scheduler_data();
#endif
@@ -6971,16 +7059,6 @@ ErlDrvTermData driver_get_monitored_process(ErlDrvPort drvport,
/* Now we should have either the port lock (if we have a scheduler) or the port data lock
(if we're a driver thread) */
ERTS_SMP_LC_ASSERT((sched != NULL || prt->port_data_lock));
-
-#if !HEAP_ON_C_STACK
- if (!sched) {
- /* Need a separate allocation for the ref :( */
- Eterm *buf = erts_alloc(ERTS_ALC_T_TEMP_TERM,
- sizeof(Eterm)*REF_THING_SIZE);
- ret = do_driver_get_monitored_process(prt,buf,monitor);
- erts_free(ERTS_ALC_T_TEMP_TERM,buf);
- } else
-#endif
{
DeclareTmpHeapNoproc(buf,REF_THING_SIZE);
UseTmpHeapNoproc(REF_THING_SIZE);
@@ -7004,6 +7082,7 @@ void erts_fire_port_monitor(Port *prt, Eterm ref)
void (*callback)(ErlDrvData drv_data, ErlDrvMonitor *monitor);
ErlDrvMonitor drv_monitor;
int fpe_was_unmasked;
+ ERTS_MSACC_PUSH_STATE_M();
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
ASSERT(prt->drv_ptr != NULL);
@@ -7015,6 +7094,7 @@ void erts_fire_port_monitor(Port *prt, Eterm ref)
callback = prt->drv_ptr->process_exit;
ASSERT(callback != NULL);
ref_to_driver_monitor(ref,&drv_monitor);
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_PORT);
DRV_MONITOR_UNLOCK_PDL(prt);
#ifdef USE_VM_PROBES
if (DTRACE_ENABLED(driver_process_exit)) {
@@ -7026,6 +7106,7 @@ void erts_fire_port_monitor(Port *prt, Eterm ref)
(*callback)((ErlDrvData) (prt->drv_data), &drv_monitor);
erts_unblock_fpe(fpe_was_unmasked);
DRV_MONITOR_LOCK_PDL(prt);
+ ERTS_MSACC_POP_STATE_M();
/* remove monitor *after* callback */
rmon = erts_remove_monitor(&ERTS_P_MONITORS(prt), ref);
DRV_MONITOR_UNLOCK_PDL(prt);
@@ -7046,6 +7127,9 @@ driver_failure_term(ErlDrvPort ix, Eterm term, int eof)
if (prt == ERTS_INVALID_ERL_DRV_PORT)
return -1;
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
+
+ if (prt->async_open_port)
+ init_ack_send_reply(prt, prt->common.id);
if (eof)
flush_linebuf_messages(prt, state);
if (state & ERTS_PORT_SFLG_CLOSING) {
diff --git a/erts/emulator/beam/module.c b/erts/emulator/beam/module.c
index 86dd3b5aac..f5c7b177d3 100644
--- a/erts/emulator/beam/module.c
+++ b/erts/emulator/beam/module.c
@@ -74,8 +74,8 @@ static Module* module_alloc(Module* tmpl)
erts_smp_atomic_add_nob(&tot_module_bytes, sizeof(Module));
obj->module = tmpl->module;
- obj->curr.code = 0;
- obj->old.code = 0;
+ obj->curr.code_hdr = 0;
+ obj->old.code_hdr = 0;
obj->curr.code_length = 0;
obj->old.code_length = 0;
obj->slot.index = -1;
@@ -103,6 +103,9 @@ void init_module_table(void)
f.cmp = (HCMP_FUN) module_cmp;
f.alloc = (HALLOC_FUN) module_alloc;
f.free = (HFREE_FUN) module_free;
+ f.meta_alloc = (HMALLOC_FUN) erts_alloc;
+ f.meta_free = (HMFREE_FUN) erts_free;
+ f.meta_print = (HMPRINT_FUN) erts_print;
for (i = 0; i < ERTS_NUM_CODE_IX; i++) {
erts_index_init(ERTS_ALC_T_MODULE_TABLE, &module_tables[i], "module_code",
diff --git a/erts/emulator/beam/module.h b/erts/emulator/beam/module.h
index c8a6351b04..b7468b0926 100644
--- a/erts/emulator/beam/module.h
+++ b/erts/emulator/beam/module.h
@@ -26,7 +26,7 @@
#endif
struct erl_module_instance {
- BeamInstr* code;
+ BeamCodeHeader* code_hdr;
int code_length; /* Length of loaded code in bytes. */
unsigned catches;
struct erl_module_nif* nif;
@@ -37,6 +37,7 @@ struct erl_module_instance {
typedef struct erl_module {
IndexSlot slot; /* Must be located at top of struct! */
int module; /* Atom index for module (not tagged). */
+ int seen; /* Used by finish_loading() */
struct erl_module_instance curr;
struct erl_module_instance old; /* protected by "old_code" rwlock */
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index 1d32e72247..9e53b4bfcc 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -39,8 +39,8 @@ too_old_compiler | never() =>
# necessary.) Since the instructions don't work correctly in R12B, simply
# refuse to load the module.
-func_info M=a a==am_module_info A=u==0 | label L | move n r => too_old_compiler
-func_info M=a a==am_module_info A=u==1 | label L | move n r => too_old_compiler
+func_info M=a a==am_module_info A=u==0 | label L | move n x==0 => too_old_compiler
+func_info M=a a==am_module_info A=u==1 | label L | move n x==0 => too_old_compiler
# The undocumented and unsupported guard BIF is_constant/1 was removed
# in R13. The is_constant/2 operation is marked as obsolete in genop.tab,
@@ -76,17 +76,6 @@ return
# with the following call instruction, we need to make sure that
# there is no line/1 instruction between the move and the call.
#
-
-move S r | line Loc | call_ext Ar Func => \
- line Loc | move S r | call_ext Ar Func
-move S r | line Loc | call_ext_last Ar Func=u$is_bif D => \
- line Loc | move S r | call_ext_last Ar Func D
-move S r | line Loc | call_ext_only Ar Func=u$is_bif => \
- line Loc | move S r | call_ext_only Ar Func
-move S r | line Loc | call Ar Func => \
- line Loc | move S r | call Ar Func
-
-#
# A tail-recursive call to an external function (non-BIF) will
# never be saved on the stack, so there is no reason to keep
# the line instruction. (The compiler did not remove the line
@@ -94,10 +83,14 @@ move S r | line Loc | call Ar Func => \
# BIFs and ordinary Erlang functions.)
#
-line Loc | call_ext_last Ar Func=u$is_not_bif D => \
- call_ext_last Ar Func D
-line Loc | call_ext_only Ar Func=u$is_not_bif => \
- call_ext_only Ar Func
+move S X0=x==0 | line Loc | call_ext Ar Func => \
+ line Loc | move S X0 | call_ext Ar Func
+move S X0=x==0 | line Loc | call_ext_last Ar Func=u$is_not_bif D => \
+ move S X0 | call_ext_last Ar Func D
+move S X0=x==0 | line Loc | call_ext_only Ar Func=u$is_not_bif => \
+ move S X0 | call_ext_only Ar Func
+move S X0=x==0 | line Loc | call Ar Func => \
+ line Loc | move S X0 | call Ar Func
line Loc | func_info M F A => func_info M F A | line Loc
@@ -167,31 +160,24 @@ is_tuple Fail=f S | select_tuple_arity S=d Fail=f Size=u Rest=* => \
select_tuple_arity S=d Fail=f Size=u Rest=* => \
gen_select_tuple_arity(S, Fail, Size, Rest)
-i_select_val_bins r f I
i_select_val_bins x f I
i_select_val_bins y f I
-i_select_val_lins r f I
i_select_val_lins x f I
i_select_val_lins y f I
-i_select_val2 r f c c f f
i_select_val2 x f c c f f
i_select_val2 y f c c f f
-i_select_tuple_arity r f I
i_select_tuple_arity x f I
i_select_tuple_arity y f I
-i_select_tuple_arity2 r f A A f f
i_select_tuple_arity2 x f A A f f
i_select_tuple_arity2 y f A A f f
-i_jump_on_val_zero r f I
i_jump_on_val_zero x f I
i_jump_on_val_zero y f I
-i_jump_on_val r f I I
i_jump_on_val x f I I
i_jump_on_val y f I I
@@ -203,30 +189,21 @@ is_ne_exact L1 S1 S2 | jump Fail | label L2 | same_label(L1, L2) => \
%macro: get_list GetList -pack
get_list x x x
get_list x x y
-get_list x x r
get_list x y x
get_list x y y
-get_list x y r
-get_list x r x
-get_list x r y
get_list y x x
get_list y x y
-get_list y x r
get_list y y x
get_list y y y
-get_list y y r
-get_list y r x
-get_list y r y
+# The following get_list instructions using x(0) are frequently used.
get_list r x x
+get_list r r y
+get_list x r x
get_list r x y
-get_list r x r
-get_list r y x
-get_list r y y
get_list r y r
-get_list r r x
-get_list r r y
+get_list r x r
# Old-style catch.
catch y f
@@ -237,33 +214,31 @@ try Y F => catch Y F
try_case Y => try_end Y
try_end y
-try_case_end Literal=q => move Literal x | try_case_end x
try_case_end s
# Destructive set tuple element
-set_tuple_element Lit=q Tuple Pos => move Lit x | set_tuple_element x Tuple Pos
set_tuple_element s d P
# Get tuple element
%macro: i_get_tuple_element GetTupleElement -pack
i_get_tuple_element x P x
-i_get_tuple_element r P x
i_get_tuple_element y P x
-i_get_tuple_element x P r
-i_get_tuple_element y P r
%cold
-i_get_tuple_element r P r
i_get_tuple_element x P y
-i_get_tuple_element r P y
i_get_tuple_element y P y
%hot
+%macro: i_get_tuple_element2 GetTupleElement2 -pack
+i_get_tuple_element2 x P x
+
+%macro: i_get_tuple_element3 GetTupleElement3 -pack
+i_get_tuple_element3 x P x
+
%macro: is_number IsNumber -fail_action
%cold
-is_number f r
is_number f x
is_number f y
%hot
@@ -273,16 +248,12 @@ is_number Fail Literal=q => move Literal x | is_number Fail x
jump f
-case_end Literal=cq => move Literal x | case_end x
-badmatch Literal=cq => move Literal x | badmatch x
+case_end NotInX=cy => move NotInX x | case_end x
+badmatch NotInX=cy => move NotInX x | badmatch x
-case_end r
case_end x
-case_end y
-badmatch r
badmatch x
-badmatch y
if_end
raise s s
@@ -291,7 +262,7 @@ raise s s
badarg j
system_limit j
-move C=cxy r | jump Lbl => move_jump Lbl C
+move C=cxy x==0 | jump Lbl => move_jump Lbl C
%macro: move_jump MoveJump -nonext
move_jump f n
@@ -309,8 +280,6 @@ move_window/6
# x -> y
-move S1=r S2=y | move X1=x Y1=y => move2 S1 S2 X1 Y1
-
move X1=x Y1=y | move X2=x Y2=y | move X3=x Y3=y | succ(Y1,Y2) | succ(Y2,Y3) => \
move_window X1 X2 X3 Y1 Y3
@@ -323,24 +292,76 @@ move_window X1=x X2=x X3=x X4=x Y1=y Y4=y | move X5=x Y5=y | succ(Y4,Y5) => \
move_window X1=x X2=x X3=x Y1=y Y3=y => move_window3 X1 X2 X3 Y1
move_window X1=x X2=x X3=x X4=x Y1=y Y4=y => move_window4 X1 X2 X3 X4 Y1
+%macro: move_window3 MoveWindow3 -pack
+%macro: move_window4 MoveWindow4 -pack
+%macro: move_window5 MoveWindow5 -pack
+
move_window3 x x x y
move_window4 x x x x y
move_window5 x x x x x y
-move X1=x Y1=y | move X2=x Y2=y => move2 X1 Y1 X2 Y2
-move Y1=y X1=x | move Y2=y X2=x => move2 Y1 X1 Y2 X2
-move X1=x X2=x | move X3=x X4=x => move2 X1 X2 X3 X4
+# Swap registers.
+move R1=x Tmp=x | move R2=xy R1 | move Tmp R2 => swap_temp R1 R2 Tmp
+
+swap_temp R1 R2 Tmp | line Loc | apply Live | is_killed(Tmp, Live) => \
+ swap R1 R2 | line Loc | apply Live
+
+swap_temp R1 R2 Tmp | line Loc | call Live Addr | is_killed(Tmp, Live) => \
+ swap R1 R2 | line Loc | call Live Addr
+swap_temp R1 R2 Tmp | call_only Live Addr | \
+ is_killed(Tmp, Live) => swap R1 R2 | call_only Live Addr
+swap_temp R1 R2 Tmp | call_last Live Addr D | \
+ is_killed(Tmp, Live) => swap R1 R2 | call_last Live Addr D
-move S1=x S2=r | move S3=x S4=x => move2 S1 S2 S3 S4
-move S1=x S2=r | move X1=x Y1=y => move2 S1 S2 X1 Y1
-move S1=y S2=r | move X1=x Y1=y => move2 S1 S2 X1 Y1
+swap_temp R1 R2 Tmp | line Loc | call_ext Live Addr | is_killed(Tmp, Live) => \
+ swap R1 R2 | line Loc | call_ext Live Addr
+swap_temp R1 R2 Tmp | line Loc | call_ext_only Live Addr | \
+ is_killed(Tmp, Live) => swap R1 R2 | line Loc | call_ext_only Live Addr
+swap_temp R1 R2 Tmp | line Loc | call_ext_last Live Addr D | \
+ is_killed(Tmp, Live) => swap R1 R2 | line Loc | call_ext_last Live Addr D
-move Y1=y X1=x | move S1=r D1=x => move2 Y1 X1 S1 D1
-move S1=r D1=x | move Y1=y X1=x => move2 S1 D1 Y1 X1
+%macro: swap_temp SwapTemp -pack
+swap_temp x x x
+swap_temp x y x
-move2 X1=x Y1=y X2=x Y2=y | move X3=x Y3=y => move3 X1 Y1 X2 Y2 X3 Y3
-move2 Y1=y X1=x Y2=y X2=x | move Y3=y X3=x => move3 Y1 X1 Y2 X2 Y3 X3
-move2 X1=x X2=x X3=x X4=x | move X5=x X6=x => move3 X1 X2 X3 X4 X5 X6
+%macro: swap Swap -pack
+swap x x
+swap x y
+
+move Src=x D1=x | move Src=x D2=x => move_dup Src D1 D2
+move Src=x SD=x | move SD=x D=x => move_dup Src SD D
+move Src=x D1=x | move Src=x D2=y => move_dup Src D1 D2
+move Src=y SD=x | move SD=x D=y => move_dup Src SD D
+move Src=x SD=x | move SD=x D=y => move_dup Src SD D
+move Src=y SD=x | move SD=x D=x => move_dup Src SD D
+
+move SD=x D=x | move Src=xy SD=x => move_shift Src SD D
+move SD=y D=x | move Src=x SD=y => move_shift Src SD D
+move SD=x D=y | move Src=x SD=x => move_shift Src SD D
+
+# The transformations above guarantee that the source for
+# the second move is not the same as the destination for
+# the first move. That means that we can do the moves in
+# parallel (fetch both values, then store them) which could
+# be faster.
+
+move X1=x Y1=y | move X2=x Y2=y => move2_par X1 Y1 X2 Y2
+move Y1=y X1=x | move Y2=y X2=x => move2_par Y1 X1 Y2 X2
+
+move X1=x X2=x | move X3=x X4=x => move2_par X1 X2 X3 X4
+
+move X1=x X2=x | move X3=x Y1=y => move2_par X1 X2 X3 Y1
+
+move S1=x S2=x | move X1=x Y1=y => move2_par S1 S2 X1 Y1
+
+move S1=y S2=x | move X1=x Y1=y => move2_par S1 S2 X1 Y1
+
+move Y1=y X1=x | move S1=x D1=x => move2_par Y1 X1 S1 D1
+move S1=x D1=x | move Y1=y X1=x => move2_par S1 D1 Y1 X1
+
+move2_par X1=x Y1=y X2=x Y2=y | move X3=x Y3=y => move3 X1 Y1 X2 Y2 X3 Y3
+move2_par Y1=y X1=x Y2=y X2=x | move Y3=y X3=x => move3 Y1 X1 Y2 X2 Y3 X3
+move2_par X1=x X2=x X3=x X4=x | move X5=x X6=x => move3 X1 X2 X3 X4 X5 X6
move C=aiq X=x==1 => move_x1 C
move C=aiq X=x==2 => move_x2 C
@@ -348,21 +369,32 @@ move C=aiq X=x==2 => move_x2 C
move_x1 c
move_x2 c
-%macro: move2 Move2 -pack
-move2 x y x y
-move2 y x y x
-move2 x x x x
+%macro: move_shift MoveShift -pack
+move_shift x x x
+move_shift y x x
+move_shift x y x
+move_shift x x y
+
+%macro: move_dup MoveDup -pack
+move_dup x x x
+move_dup x x y
+move_dup y x x
+move_dup y x y
-move2 x r x x
+%macro: move2_par Move2Par -pack
-move2 x r x y
-move2 r y x y
-move2 y r x y
+move2_par x y x y
+move2_par y x y x
+move2_par x x x x
-move2 r x y x
-move2 y x r x
+move2_par x x x y
-%macro: move3 Move3
+move2_par y x x y
+
+move2_par x x y x
+move2_par y x x x
+
+%macro: move3 Move3 -pack
move3 x y x y x y
move3 y x y x y x
move3 x x x x x x
@@ -375,20 +407,22 @@ move S=c D=y => move S x | move x D
%macro:move Move -pack -gen_dest
move x x
move x y
-move x r
move y x
-move y r
-move r x
-move r y
-move c r
move c x
move n x
-move n r
move y y
+# The following move instructions using x(0) are frequently used.
+
+move x r
+move r x
+move y r
+move c r
+move r y
+
# Receive operations.
-loop_rec Fail Src | smp_mark_target_label(Fail) => i_loop_rec Fail Src
+loop_rec Fail x==0 | smp_mark_target_label(Fail) => i_loop_rec Fail
label L | wait_timeout Fail Src | smp_already_locked(L) => label L | i_wait_timeout_locked Fail Src
wait_timeout Fail Src => i_wait_timeout Fail Src
@@ -403,7 +437,7 @@ label L | timeout | smp_already_locked(L) => label L | timeout_locked
remove_message
timeout
timeout_locked
-i_loop_rec f r
+i_loop_rec f
loop_rec_end f
wait f
wait_locked f
@@ -421,93 +455,57 @@ send
# Optimized comparisons with one immediate/literal operand.
#
-is_eq_exact Lbl R=rxy C=ian => i_is_eq_exact_immed Lbl R C
-is_eq_exact Lbl R=rxy C=q => i_is_eq_exact_literal R Lbl C
+is_eq_exact Lbl R=xy C=ian => i_is_eq_exact_immed Lbl R C
+is_eq_exact Lbl R=xy C=q => i_is_eq_exact_literal Lbl R C
-is_ne_exact Lbl R=rxy C=ian => i_is_ne_exact_immed Lbl R C
-is_ne_exact Lbl R=rxy C=q => i_is_ne_exact_literal R Lbl C
+is_ne_exact Lbl R=xy C=ian => i_is_ne_exact_immed Lbl R C
+is_ne_exact Lbl R=xy C=q => i_is_ne_exact_literal Lbl R C
%macro: i_is_eq_exact_immed EqualImmed -fail_action
i_is_eq_exact_immed f r c
i_is_eq_exact_immed f x c
i_is_eq_exact_immed f y c
-i_is_eq_exact_literal r f c
-i_is_eq_exact_literal x f c
-i_is_eq_exact_literal y f c
+i_is_eq_exact_literal f x c
+i_is_eq_exact_literal f y c
%macro: i_is_ne_exact_immed NotEqualImmed -fail_action
-i_is_ne_exact_immed f r c
i_is_ne_exact_immed f x c
i_is_ne_exact_immed f y c
-i_is_ne_exact_literal r f c
-i_is_ne_exact_literal x f c
-i_is_ne_exact_literal y f c
+i_is_ne_exact_literal f x c
+i_is_ne_exact_literal f y c
-#
-# Common Compare Specializations
-# We don't do all of them since we want
-# to keep the instruction set small-ish
-#
-
-is_eq_exact Lbl S1=xy S2=r => is_eq_exact Lbl S2 S1
-is_eq_exact Lbl S1=rx S2=xy => i_is_eq_exact_spec Lbl S1 S2
-%macro: i_is_eq_exact_spec EqualExact -fail_action
+is_eq_exact Lbl Y=y X=x => is_eq_exact Lbl X Y
+%macro: is_eq_exact EqualExact -fail_action -pack
+is_eq_exact f x x
+is_eq_exact f x y
+is_eq_exact f s s
-i_is_eq_exact_spec f x x
-i_is_eq_exact_spec f x y
-i_is_eq_exact_spec f r x
-i_is_eq_exact_spec f r y
+%macro: is_lt IsLessThan -fail_action
+is_lt f x x
+is_lt f x c
+is_lt f c x
%cold
-i_is_eq_exact_spec f r r
+is_lt f s s
%hot
-is_lt Lbl S1=rxc S2=rxc => i_is_lt_spec Lbl S1 S2
-
-%macro: i_is_lt_spec IsLessThan -fail_action
-
-i_is_lt_spec f x x
-i_is_lt_spec f x r
-i_is_lt_spec f x c
-i_is_lt_spec f r x
-i_is_lt_spec f r c
-i_is_lt_spec f c x
-i_is_lt_spec f c r
+%macro: is_ge IsGreaterEqual -fail_action
+is_ge f x x
+is_ge f x c
+is_ge f c x
%cold
-i_is_lt_spec f r r
-i_is_lt_spec f c c
+is_ge f s s
%hot
-is_ge Lbl S1=xc S2=xc => i_is_ge_spec Lbl S1 S2
-
-%macro: i_is_ge_spec IsGreaterEqual -fail_action
-
-i_is_ge_spec f x x
-i_is_ge_spec f x c
-i_is_ge_spec f c x
-%cold
-i_is_ge_spec f c c
-%hot
-
-#
-# All other comparisons.
-#
-
-is_eq_exact Lbl S1 S2 => i_fetch S1 S2 | i_is_eq_exact Lbl
-is_ne_exact Lbl S1 S2 => i_fetch S1 S2 | i_is_ne_exact Lbl
+%macro: is_ne_exact NotEqualExact -fail_action
+is_ne_exact f s s
-is_lt Lbl S1 S2 => i_fetch S1 S2 | i_is_lt Lbl
-is_ge Lbl S1 S2 => i_fetch S1 S2 | i_is_ge Lbl
-is_eq Lbl S1 S2 => i_fetch S1 S2 | i_is_eq Lbl
-is_ne Lbl S1 S2 => i_fetch S1 S2 | i_is_ne Lbl
+%macro: is_eq Equal -fail_action
+is_eq f s s
-i_is_eq_exact f
-i_is_ne_exact f
-i_is_lt f
-i_is_ge f
-i_is_eq f
-i_is_ne f
+%macro: is_ne NotEqual -fail_action
+is_ne f s s
#
# Putting things.
@@ -525,7 +523,6 @@ i_put_tuple Dst Arity Puts=* | put S => \
i_put_tuple/2
%macro:i_put_tuple PutTuple -pack -goto:do_put_tuple
-i_put_tuple r I
i_put_tuple x I
i_put_tuple y I
@@ -542,74 +539,36 @@ put_list x n x
put_list y n x
put_list x x x
put_list y x x
-put_list x x r
-put_list y r r
put_list y y x
put_list x y x
-put_list r x x
-put_list r y x
-put_list r x r
-put_list y y r
-put_list y r x
-put_list r n x
-put_list x r x
-put_list x y r
-put_list y x r
put_list y x x
-put_list x r r
-
# put_list SrcReg Constant Dst
-put_list r c r
-put_list r c x
-put_list r c y
-put_list x c r
put_list x c x
put_list x c y
-put_list y c r
put_list y c x
-put_list y c y
# put_list Constant SrcReg Dst
-put_list c r r
-put_list c r x
-put_list c r y
-put_list c x r
put_list c x x
-put_list c x y
-
-put_list c y r
put_list c y x
-put_list c y y
-%cold
-put_list s s d
-%hot
+# The following put_list instructions using x(0) are frequently used.
-%macro: i_fetch FetchArgs -pack
-i_fetch c r
-i_fetch c x
-i_fetch c y
-i_fetch r c
-i_fetch r x
-i_fetch r y
-i_fetch x c
-i_fetch x r
-i_fetch x x
-i_fetch x y
-i_fetch y c
-i_fetch y r
-i_fetch y x
-i_fetch y y
+put_list y r r
+put_list x r r
+put_list r n r
+put_list r n x
+put_list r x x
+put_list r x r
+put_list x x r
%cold
-i_fetch c c
-i_fetch s s
+put_list s s d
%hot
#
@@ -631,27 +590,27 @@ return_trace
# Note: There is no 'move_return y r', since there never are any y registers
# when we do move_return (if we have y registers, we must do move_deallocate_return).
-move S r | return => move_return S r
+move S x==0 | return => move_return S
%macro: move_return MoveReturn -nonext
-move_return x r
-move_return c r
-move_return n r
+move_return x
+move_return c
+move_return n
-move S r | deallocate D | return => move_deallocate_return S r D
+move S x==0 | deallocate D | return => move_deallocate_return S D
%macro: move_deallocate_return MoveDeallocateReturn -pack -nonext
-move_deallocate_return x r Q
-move_deallocate_return y r Q
-move_deallocate_return c r Q
-move_deallocate_return n r Q
+move_deallocate_return x Q
+move_deallocate_return y Q
+move_deallocate_return c Q
+move_deallocate_return n Q
deallocate D | return => deallocate_return D
%macro: deallocate_return DeallocateReturn -nonext
deallocate_return Q
-test_heap Need u==1 | put_list Y=y r r => test_heap_1_put_list Need Y
+test_heap Need u==1 | put_list Y=y x==0 x==0 => test_heap_1_put_list Need Y
%macro: test_heap_1_put_list TestHeapPutList -pack
test_heap_1_put_list I y
@@ -660,18 +619,18 @@ test_heap_1_put_list I y
is_tuple Fail Literal=q => move Literal x | is_tuple Fail x
is_tuple Fail=f c => jump Fail
-is_tuple Fail=f S=rxy | test_arity Fail=f S=rxy Arity => is_tuple_of_arity Fail S Arity
+is_tuple Fail=f S=xy | test_arity Fail=f S=xy Arity => is_tuple_of_arity Fail S Arity
%macro:is_tuple_of_arity IsTupleOfArity -fail_action
+is_tuple_of_arity f r A
is_tuple_of_arity f x A
is_tuple_of_arity f y A
-is_tuple_of_arity f r A
%macro: is_tuple IsTuple -fail_action
+is_tuple f r
is_tuple f x
is_tuple f y
-is_tuple f r
test_arity Fail Literal=q Arity => move Literal x | test_arity Fail x Arity
test_arity Fail=f c Arity => jump Fail
@@ -679,95 +638,63 @@ test_arity Fail=f c Arity => jump Fail
%macro: test_arity IsArity -fail_action
test_arity f x A
test_arity f y A
-test_arity f r A
-
-is_tuple_of_arity Fail=f Reg Arity | get_tuple_element Reg P=u==0 Dst=xy => \
- is_tuple_of_arity Fail Reg Arity | extract_next_element Dst | original_reg Reg P
-
-test_arity Fail Reg Arity | get_tuple_element Reg P=u==0 Dst=xy => \
- test_arity Fail Reg Arity | extract_next_element Dst | original_reg Reg P
-
-original_reg Reg P1 | get_tuple_element Reg P2 Dst=xy | succ(P1, P2) => \
- extract_next_element Dst | original_reg Reg P2
-
-get_tuple_element Reg P Dst => i_get_tuple_element Reg P Dst | original_reg Reg P
-
-original_reg Reg Pos =>
-original_reg/2
+get_tuple_element Reg=x P1 D1=x | get_tuple_element Reg=x P2 D2=x | \
+ get_tuple_element Reg=x P3 D3=x | \
+ succ(P1, P2) | succ(P2, P3) | \
+ succ(D1, D2) | succ(D2, D3) => i_get_tuple_element3 Reg P1 D1
-extract_next_element D1=xy | original_reg Reg P1 | get_tuple_element Reg P2 D2=xy | \
-succ(P1, P2) | succ(D1, D2) => \
- extract_next_element2 D1 | original_reg Reg P2
+get_tuple_element Reg=x P1 D1=x | get_tuple_element Reg=x P2 D2=x | \
+ succ(P1, P2) | succ(D1, D2) => i_get_tuple_element2 Reg P1 D1
-extract_next_element2 D1=xy | original_reg Reg P1 | get_tuple_element Reg P2 D2=xy | \
-succ(P1, P2) | succ2(D1, D2) => \
- extract_next_element3 D1 | original_reg Reg P2
-
-#extract_next_element3 D1=xy | original_reg Reg P1 | get_tuple_element Reg P2 D2=xy | \
-#succ(P1, P2) | succ3(D1, D2) => \
-# extract_next_element4 D1 | original_reg Reg P2
-
-%macro: extract_next_element ExtractNextElement -pack
-extract_next_element x
-extract_next_element y
-
-%macro: extract_next_element2 ExtractNextElement2 -pack
-extract_next_element2 x
-extract_next_element2 y
-
-%macro: extract_next_element3 ExtractNextElement3 -pack
-extract_next_element3 x
-extract_next_element3 y
-
-#%macro: extract_next_element4 ExtractNextElement4 -pack
-#extract_next_element4 x
-#extract_next_element4 y
+get_tuple_element Reg P Dst => i_get_tuple_element Reg P Dst
is_integer Fail=f i =>
is_integer Fail=f an => jump Fail
is_integer Fail Literal=q => move Literal x | is_integer Fail x
-is_integer Fail=f S=rx | allocate Need Regs => is_integer_allocate Fail S Need Regs
+is_integer Fail=f S=x | allocate Need Regs => is_integer_allocate Fail S Need Regs
%macro: is_integer_allocate IsIntegerAllocate -fail_action
is_integer_allocate f x I I
-is_integer_allocate f r I I
%macro: is_integer IsInteger -fail_action
is_integer f x
is_integer f y
-is_integer f r
is_list Fail=f n =>
is_list Fail Literal=q => move Literal x | is_list Fail x
is_list Fail=f c => jump Fail
%macro: is_list IsList -fail_action
-is_list f r
is_list f x
%cold
is_list f y
%hot
-is_nonempty_list Fail=f S=rx | allocate Need Rs => is_nonempty_list_allocate Fail S Need Rs
+is_nonempty_list Fail=f S=x | allocate Need Rs => is_nonempty_list_allocate Fail S Need Rs
%macro:is_nonempty_list_allocate IsNonemptyListAllocate -fail_action -pack
-is_nonempty_list_allocate f x I t
is_nonempty_list_allocate f r I t
+is_nonempty_list_allocate f x I t
-is_nonempty_list F=f r | test_heap I1 I2 => is_non_empty_list_test_heap F r I1 I2
+is_nonempty_list F=f x==0 | test_heap I1 I2 => is_non_empty_list_test_heap F I1 I2
%macro: is_non_empty_list_test_heap IsNonemptyListTestHeap -fail_action -pack
-is_non_empty_list_test_heap f r I t
+is_non_empty_list_test_heap f I t
+
+is_nonempty_list Fail=f S=x | get_list S D1=x D2=x => \
+ is_nonempty_list_get_list Fail S D1 D2
+
+%macro: is_nonempty_list_get_list IsNonemptyListGetList -fail_action -pack
+is_nonempty_list_get_list f r x x
+is_nonempty_list_get_list f x x x
%macro: is_nonempty_list IsNonemptyList -fail_action
is_nonempty_list f x
is_nonempty_list f y
-is_nonempty_list f r
%macro: is_atom IsAtom -fail_action
is_atom f x
-is_atom f r
%cold
is_atom f y
%hot
@@ -775,7 +702,6 @@ is_atom Fail=f a =>
is_atom Fail=f niq => jump Fail
%macro: is_float IsFloat -fail_action
-is_float f r
is_float f x
%cold
is_float f y
@@ -789,12 +715,10 @@ is_nil Fail=f qia => jump Fail
%macro: is_nil IsNil -fail_action
is_nil f x
is_nil f y
-is_nil f r
is_binary Fail Literal=q => move Literal x | is_binary Fail x
is_binary Fail=f c => jump Fail
%macro: is_binary IsBinary -fail_action
-is_binary f r
is_binary f x
%cold
is_binary f y
@@ -806,7 +730,6 @@ is_bitstr Fail Term => is_bitstring Fail Term
is_bitstring Fail Literal=q => move Literal x | is_bitstring Fail x
is_bitstring Fail=f c => jump Fail
%macro: is_bitstring IsBitstring -fail_action
-is_bitstring f r
is_bitstring f x
%cold
is_bitstring f y
@@ -814,7 +737,6 @@ is_bitstring f y
is_reference Fail=f cq => jump Fail
%macro: is_reference IsRef -fail_action
-is_reference f r
is_reference f x
%cold
is_reference f y
@@ -822,7 +744,6 @@ is_reference f y
is_pid Fail=f cq => jump Fail
%macro: is_pid IsPid -fail_action
-is_pid f r
is_pid f x
%cold
is_pid f y
@@ -830,7 +751,6 @@ is_pid f y
is_port Fail=f cq => jump Fail
%macro: is_port IsPort -fail_action
-is_port f r
is_port f x
%cold
is_port f y
@@ -842,14 +762,12 @@ is_boolean Fail=f ac => jump Fail
%cold
%macro: is_boolean IsBoolean -fail_action
-is_boolean f r
is_boolean f x
is_boolean f y
%hot
is_function2 Fail=f acq Arity => jump Fail
is_function2 Fail=f Fun a => jump Fail
-is_function2 Fail Fun Literal=q => move Literal x | is_function2 Fail Fun x
is_function2 f s s
%macro: is_function2 IsFunction2 -fail_action
@@ -989,76 +907,76 @@ call_ext_only u==3 u$func:erlang:hibernate/3 => i_hibernate
%unless USE_VM_PROBES
call_ext Arity u$func:erlang:dt_get_tag/0 => \
- move a=am_undefined r
+ move a=am_undefined x=0
call_ext_last Arity u$func:erlang:dt_get_tag/0 D => \
- move a=am_undefined r | deallocate D | return
+ move a=am_undefined x=0 | deallocate D | return
call_ext_only Arity u$func:erlang:dt_get_tag/0 => \
- move a=am_undefined r | return
-
-move Any r | call_ext Arity u$func:erlang:dt_put_tag/1 => \
- move a=am_undefined r
-move Any r | call_ext_last Arity u$func:erlang:dt_put_tag/1 D => \
- move a=am_undefined r | deallocate D | return
-move Any r | call_ext_only Arity u$func:erlang:dt_put_tag/1 => \
- move a=am_undefined r | return
+ move a=am_undefined x=0 | return
+
+move Any x==0 | call_ext Arity u$func:erlang:dt_put_tag/1 => \
+ move a=am_undefined x=0
+move Any x==0 | call_ext_last Arity u$func:erlang:dt_put_tag/1 D => \
+ move a=am_undefined x=0 | deallocate D | return
+move Any x==0 | call_ext_only Arity u$func:erlang:dt_put_tag/1 => \
+ move a=am_undefined x=0 | return
call_ext Arity u$func:erlang:dt_put_tag/1 => \
- move a=am_undefined r
+ move a=am_undefined x=0
call_ext_last Arity u$func:erlang:dt_put_tag/1 D => \
- move a=am_undefined r | deallocate D | return
+ move a=am_undefined x=0 | deallocate D | return
call_ext_only Arity u$func:erlang:dt_put_tag/1 => \
- move a=am_undefined r | return
+ move a=am_undefined x=0 | return
call_ext Arity u$func:erlang:dt_get_tag_data/0 => \
- move a=am_undefined r
+ move a=am_undefined x=0
call_ext_last Arity u$func:erlang:dt_get_tag_data/0 D => \
- move a=am_undefined r | deallocate D | return
+ move a=am_undefined x=0 | deallocate D | return
call_ext_only Arity u$func:erlang:dt_get_tag_data/0 => \
- move a=am_undefined r | return
-
-move Any r | call_ext Arity u$func:erlang:dt_spread_tag/1 => \
- move a=am_true r
-move Any r | call_ext_last Arity u$func:erlang:dt_spread_tag/1 D => \
- move a=am_true r | deallocate D | return
-move Any r | call_ext_only Arity u$func:erlang:dt_spread_tag/1 => \
- move a=am_true r | return
+ move a=am_undefined x=0 | return
+
+move Any x==0 | call_ext Arity u$func:erlang:dt_spread_tag/1 => \
+ move a=am_true x=0
+move Any x==0 | call_ext_last Arity u$func:erlang:dt_spread_tag/1 D => \
+ move a=am_true x=0 | deallocate D | return
+move Any x==0 | call_ext_only Arity u$func:erlang:dt_spread_tag/1 => \
+ move a=am_true x=0 | return
call_ext Arity u$func:erlang:dt_spread_tag/1 => \
- move a=am_true r
+ move a=am_true x=0
call_ext_last Arity u$func:erlang:dt_spread_tag/1 D => \
- move a=am_true r | deallocate D | return
+ move a=am_true x=0 | deallocate D | return
call_ext_only Arity u$func:erlang:dt_spread_tag/1 => \
- move a=am_true r | return
-
-move Any r | call_ext Arity u$func:erlang:dt_restore_tag/1 => \
- move a=am_true r
-move Any r | call_ext_last Arity u$func:erlang:dt_restore_tag/1 D => \
- move a=am_true r | deallocate D | return
-move Any r | call_ext_only Arity u$func:erlang:dt_restore_tag/1 => \
- move a=am_true r | return
+ move a=am_true x=0 | return
+
+move Any x==0 | call_ext Arity u$func:erlang:dt_restore_tag/1 => \
+ move a=am_true x=0
+move Any x==0 | call_ext_last Arity u$func:erlang:dt_restore_tag/1 D => \
+ move a=am_true x=0 | deallocate D | return
+move Any x==0 | call_ext_only Arity u$func:erlang:dt_restore_tag/1 => \
+ move a=am_true x=0 | return
call_ext Arity u$func:erlang:dt_restore_tag/1 => \
- move a=am_true r
+ move a=am_true x=0
call_ext_last Arity u$func:erlang:dt_restore_tag/1 D => \
- move a=am_true r | deallocate D | return
+ move a=am_true x=0 | deallocate D | return
call_ext_only Arity u$func:erlang:dt_restore_tag/1 => \
- move a=am_true r | return
-
-move Any r | call_ext Arity u$func:erlang:dt_prepend_vm_tag_data/1 => \
- move Any r
-move Any r | call_ext_last Arity u$func:erlang:dt_prepend_vm_tag_data/1 D => \
- move Any r | deallocate D | return
-move Any r | call_ext_only Arity u$func:erlang:dt_prepend_vm_tag_data/1 => \
- move Any r | return
+ move a=am_true x=0 | return
+
+move Any x==0 | call_ext Arity u$func:erlang:dt_prepend_vm_tag_data/1 => \
+ move Any x=0
+move Any x==0 | call_ext_last Arity u$func:erlang:dt_prepend_vm_tag_data/1 D => \
+ move Any x=0 | deallocate D | return
+move Any x==0 | call_ext_only Arity u$func:erlang:dt_prepend_vm_tag_data/1 => \
+ move Any x=0 | return
call_ext Arity u$func:erlang:dt_prepend_vm_tag_data/1 =>
call_ext_last Arity u$func:erlang:dt_prepend_vm_tag_data/1 D => \
deallocate D | return
call_ext_only Arity u$func:erlang:dt_prepend_vm_tag_data/1 => \
return
-move Any r | call_ext Arity u$func:erlang:dt_append_vm_tag_data/1 => \
- move Any r
-move Any r | call_ext_last Arity u$func:erlang:dt_append_vm_tag_data/1 D => \
- move Any r | deallocate D | return
-move Any r | call_ext_only Arity u$func:erlang:dt_append_vm_tag_data/1 => \
- move Any r | return
+move Any x==0 | call_ext Arity u$func:erlang:dt_append_vm_tag_data/1 => \
+ move Any x=0
+move Any x==0 | call_ext_last Arity u$func:erlang:dt_append_vm_tag_data/1 D => \
+ move Any x=0 | deallocate D | return
+move Any x==0 | call_ext_only Arity u$func:erlang:dt_append_vm_tag_data/1 => \
+ move Any x=0 | return
call_ext Arity u$func:erlang:dt_append_vm_tag_data/1 =>
call_ext_last Arity u$func:erlang:dt_append_vm_tag_data/1 D => \
deallocate D | return
@@ -1066,10 +984,17 @@ call_ext_only Arity u$func:erlang:dt_append_vm_tag_data/1 => \
return
# Can happen after one of the transformations above.
-move Discarded r | move Something r => move Something r
+move Discarded x==0 | move Something x==0 => move Something x=0
%endif
+call_ext u==0 u$func:os:perf_counter/0 => \
+ i_perf_counter
+call_ext_last u==0 u$func:os:perf_counter/0 D => \
+ i_perf_counter | deallocate_return D
+call_ext_only u==0 u$func:os:perf_counter/0 => \
+ i_perf_counter | return
+
#
# The general case for BIFs that have no special instructions.
# A BIF used in the tail must be followed by a return instruction.
@@ -1091,9 +1016,9 @@ call_ext_only Ar=u Bif=u$is_bif => \
# with call instructions.
#
-move S=c r | call_ext Ar=u Func=u$is_not_bif => i_move_call_ext S r Func
-move S=c r | call_ext_last Ar=u Func=u$is_not_bif D => i_move_call_ext_last Func D S r
-move S=c r | call_ext_only Ar=u Func=u$is_not_bif => i_move_call_ext_only Func S r
+move S=c x==0 | call_ext Ar=u Func=u$is_not_bif => i_move_call_ext S Func
+move S=c x==0 | call_ext_last Ar=u Func=u$is_not_bif D => i_move_call_ext_last Func D S
+move S=c x==0 | call_ext_only Ar=u Func=u$is_not_bif => i_move_call_ext_only Func S
call_ext Ar Func => i_call_ext Func
call_ext_last Ar Func D => i_call_ext_last Func D
@@ -1109,6 +1034,8 @@ i_apply_fun_only
i_hibernate
+i_perf_counter
+
call_bif e
#
@@ -1118,80 +1045,74 @@ call_bif e
bif0 u$bif:erlang:self/0 Dst=d => self Dst
bif0 u$bif:erlang:node/0 Dst=d => node Dst
-bif1 Fail Bif=u$bif:erlang:get/1 Src=s Dst=d => i_get Src Dst
+bif1 Fail Bif=u$bif:erlang:get/1 Src=s Dst=d => gen_get(Src, Dst)
-bif2 Jump=j u$bif:erlang:element/2 S1=s S2=rxy Dst=d => gen_element(Jump, S1, S2, Dst)
+bif2 Jump=j u$bif:erlang:element/2 S1=s S2=xy Dst=d => gen_element(Jump, S1, S2, Dst)
-bif1 Fail Bif Literal=q Dst => move Literal x | bif1 Fail Bif x Dst
bif1 p Bif S1 Dst => bif1_body Bif S1 Dst
-bif1_body Bif Literal=q Dst => move Literal x | bif1_body Bif x Dst
-
-bif2 p Bif S1 S2 Dst => i_fetch S1 S2 | i_bif2_body Bif Dst
-bif2 Fail Bif S1 S2 Dst => i_fetch S1 S2 | i_bif2 Fail Bif Dst
+bif2 p Bif S1 S2 Dst => i_bif2_body Bif S1 S2 Dst
+bif2 Fail Bif S1 S2 Dst => i_bif2 Fail Bif S1 S2 Dst
+i_get_hash c I d
i_get s d
%macro: self Self
-self r
self x
self y
%macro: node Node
-node r
node x
%cold
node y
%hot
-i_fast_element r j I d
-i_fast_element x j I d
-i_fast_element y j I d
+i_fast_element j x I d
+i_fast_element j y I d
-i_element r j s d
-i_element x j s d
-i_element y j s d
+i_element j x s d
+i_element j y s d
bif1 f b s d
bif1_body b s d
-i_bif2 f b d
-i_bif2_body b d
+i_bif2 f b s s d
+i_bif2_body b s s d
#
# Internal calls.
#
-move S=c r | call Ar P=f => i_move_call S r P
-move S=s r | call Ar P=f => move_call S r P
+move S=c x==0 | call Ar P=f => i_move_call S P
+move S=s x==0 | call Ar P=f => move_call S P
-i_move_call c r f
+i_move_call c f
%macro:move_call MoveCall -arg_f -size -nonext
-move_call/3
+move_call/2
-move_call x r f
-move_call y r f
+move_call x f
+move_call y f
-move S=c r | call_last Ar P=f D => i_move_call_last P D S r
-move S r | call_last Ar P=f D => move_call_last S r P D
+move S=c x==0 | call_last Ar P=f D => i_move_call_last P D S
+move S x==0 | call_last Ar P=f D => move_call_last S P D
-i_move_call_last f P c r
+i_move_call_last f P c
%macro:move_call_last MoveCallLast -arg_f -nonext -pack
-move_call_last/4
-move_call_last x r f Q
-move_call_last y r f Q
+move_call_last/3
+move_call_last x f Q
+move_call_last y f Q
-move S=c r | call_only Ar P=f => i_move_call_only P S r
-move S=x r | call_only Ar P=f => move_call_only S r P
+move S=c x==0 | call_only Ar P=f => i_move_call_only P S
+move S=x x==0 | call_only Ar P=f => move_call_only S P
-i_move_call_only f c r
+i_move_call_only f c
%macro:move_call_only MoveCallOnly -arg_f -nonext
-move_call_only/3
+move_call_only/2
-move_call_only x r f
+move_call_only x f
call Ar Func => i_call Func
call_last Ar Func D => i_call_last Func D
@@ -1205,9 +1126,9 @@ i_call_ext e
i_call_ext_last e P
i_call_ext_only e
-i_move_call_ext c r e
-i_move_call_ext_last e P c r
-i_move_call_ext_only e c r
+i_move_call_ext c e
+i_move_call_ext_last e P c
+i_move_call_ext_only e c
# Fun calls.
@@ -1227,7 +1148,6 @@ i_make_fun I t
%macro: is_function IsFunction -fail_action
is_function f x
is_function f y
-is_function f r
is_function Fail=f c => jump Fail
func_info M F A => i_func_info u M F A
@@ -1239,131 +1159,105 @@ func_info M F A => i_func_info u M F A
%cold
bs_start_match2 Fail=f ica X Y D => jump Fail
bs_start_match2 Fail Bin X Y D => i_bs_start_match2 Bin Fail X Y D
-i_bs_start_match2 r f I I d
i_bs_start_match2 x f I I d
i_bs_start_match2 y f I I d
bs_save2 Reg Index => gen_bs_save(Reg, Index)
-i_bs_save2 r I
i_bs_save2 x I
bs_restore2 Reg Index => gen_bs_restore(Reg, Index)
-i_bs_restore2 r I
i_bs_restore2 x I
# Matching integers
bs_match_string Fail Ms Bits Val => i_bs_match_string Ms Fail Bits Val
-i_bs_match_string r f I I
i_bs_match_string x f I I
# Fetching integers from binaries.
-bs_get_integer2 Fail=f Ms=rx Live=u Sz=sq Unit=u Flags=u Dst=d => \
+bs_get_integer2 Fail=f Ms=x Live=u Sz=sq Unit=u Flags=u Dst=d => \
gen_get_integer2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
-i_bs_get_integer_small_imm r I f I d
i_bs_get_integer_small_imm x I f I d
-i_bs_get_integer_imm r I I f I d
i_bs_get_integer_imm x I I f I d
-i_bs_get_integer f I I d
-i_bs_get_integer_8 r f d
+i_bs_get_integer f I I s s d
i_bs_get_integer_8 x f d
-i_bs_get_integer_16 r f d
i_bs_get_integer_16 x f d
-i_bs_get_integer_32 r f I d
i_bs_get_integer_32 x f I d
# Fetching binaries from binaries.
-bs_get_binary2 Fail=f Ms=rx Live=u Sz=sq Unit=u Flags=u Dst=d => \
+bs_get_binary2 Fail=f Ms=x Live=u Sz=sq Unit=u Flags=u Dst=d => \
gen_get_binary2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
%macro: i_bs_get_binary_imm2 BsGetBinaryImm_2 -fail_action -gen_dest
%macro: i_bs_get_binary2 BsGetBinary_2 -fail_action -gen_dest
%macro: i_bs_get_binary_all2 BsGetBinaryAll_2 -fail_action -gen_dest
-i_bs_get_binary_imm2 f r I I I d
i_bs_get_binary_imm2 f x I I I d
-i_bs_get_binary2 f r I s I d
i_bs_get_binary2 f x I s I d
-i_bs_get_binary_all2 f r I I d
i_bs_get_binary_all2 f x I I d
-i_bs_get_binary_all_reuse r f I
i_bs_get_binary_all_reuse x f I
# Fetching float from binaries.
-bs_get_float2 Fail=f Ms=rx Live=u Sz=s Unit=u Flags=u Dst=d => \
+bs_get_float2 Fail=f Ms=x Live=u Sz=s Unit=u Flags=u Dst=d => \
gen_get_float2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
-bs_get_float2 Fail=f Ms=rx Live=u Sz=q Unit=u Flags=u Dst=d => jump Fail
+bs_get_float2 Fail=f Ms=x Live=u Sz=q Unit=u Flags=u Dst=d => jump Fail
%macro: i_bs_get_float2 BsGetFloat2 -fail_action -gen_dest
-i_bs_get_float2 f r I s I d
i_bs_get_float2 f x I s I d
# Miscellanous
-bs_skip_bits2 Fail=f Ms=rx Sz=s Unit=u Flags=u => \
- gen_skip_bits2(Fail, Ms, Sz, Unit, Flags)
-bs_skip_bits2 Fail=f Ms=rx Sz=q Unit=u Flags=u => \
+bs_skip_bits2 Fail=f Ms=x Sz=sq Unit=u Flags=u => \
gen_skip_bits2(Fail, Ms, Sz, Unit, Flags)
%macro: i_bs_skip_bits_imm2 BsSkipBitsImm2 -fail_action
-i_bs_skip_bits_imm2 f r I
i_bs_skip_bits_imm2 f x I
%macro: i_bs_skip_bits2 BsSkipBits2 -fail_action
-i_bs_skip_bits2 f r x I
-i_bs_skip_bits2 f r y I
i_bs_skip_bits2 f x x I
-i_bs_skip_bits2 f x r I
i_bs_skip_bits2 f x y I
%macro: i_bs_skip_bits_all2 BsSkipBitsAll2 -fail_action
-i_bs_skip_bits_all2 f r I
i_bs_skip_bits_all2 f x I
-bs_test_tail2 Fail=f Ms=rx Bits=u==0 => bs_test_zero_tail2 Fail Ms
-bs_test_tail2 Fail=f Ms=rx Bits=u => bs_test_tail_imm2 Fail Ms Bits
-bs_test_zero_tail2 f r
+bs_test_tail2 Fail=f Ms=x Bits=u==0 => bs_test_zero_tail2 Fail Ms
+bs_test_tail2 Fail=f Ms=x Bits=u => bs_test_tail_imm2 Fail Ms Bits
bs_test_zero_tail2 f x
-bs_test_tail_imm2 f r I
bs_test_tail_imm2 f x I
bs_test_unit F Ms Unit=u==8 => bs_test_unit8 F Ms
-bs_test_unit f r I
bs_test_unit f x I
-bs_test_unit8 f r
bs_test_unit8 f x
-bs_context_to_binary r
+# An y register operand for bs_context_to_binary is rare,
+# but can happen because of inlining.
+
+bs_context_to_binary Y=y => move Y x | bs_context_to_binary x
+
bs_context_to_binary x
-bs_context_to_binary y
#
# Utf8/utf16/utf32 support. (R12B-5)
#
-bs_get_utf8 Fail=f Ms=rx u u Dst=d => i_bs_get_utf8 Ms Fail Dst
-i_bs_get_utf8 r f d
+bs_get_utf8 Fail=f Ms=x u u Dst=d => i_bs_get_utf8 Ms Fail Dst
i_bs_get_utf8 x f d
-bs_skip_utf8 Fail=f Ms=rx u u => i_bs_get_utf8 Ms Fail x
+bs_skip_utf8 Fail=f Ms=x u u => i_bs_get_utf8 Ms Fail x
-bs_get_utf16 Fail=f Ms=rx u Flags=u Dst=d => i_bs_get_utf16 Ms Fail Flags Dst
-bs_skip_utf16 Fail=f Ms=rx u Flags=u => i_bs_get_utf16 Ms Fail Flags x
+bs_get_utf16 Fail=f Ms=x u Flags=u Dst=d => i_bs_get_utf16 Ms Fail Flags Dst
+bs_skip_utf16 Fail=f Ms=x u Flags=u => i_bs_get_utf16 Ms Fail Flags x
-i_bs_get_utf16 r f I d
i_bs_get_utf16 x f I d
-bs_get_utf32 Fail=f Ms=rx Live=u Flags=u Dst=d => \
+bs_get_utf32 Fail=f Ms=x Live=u Flags=u Dst=d => \
bs_get_integer2 Fail Ms Live i=32 u=1 Flags Dst | \
- i_fetch Dst Ms | \
- i_bs_validate_unicode_retract Fail
-bs_skip_utf32 Fail=f Ms=rx Live=u Flags=u => \
+ i_bs_validate_unicode_retract Fail Dst Ms
+bs_skip_utf32 Fail=f Ms=x Live=u Flags=u => \
bs_get_integer2 Fail Ms Live i=32 u=1 Flags x | \
- i_fetch x Ms | \
- i_bs_validate_unicode_retract Fail
+ i_bs_validate_unicode_retract Fail x Ms
-i_bs_validate_unicode_retract j
+i_bs_validate_unicode_retract j s s
%hot
#
@@ -1385,13 +1279,12 @@ bs_init2 Fail Sz=u Words Regs Flags Dst => \
bs_init2 Fail Sz Words=u==0 Regs Flags Dst => \
i_bs_init_fail Sz Fail Regs Dst
bs_init2 Fail Sz Words Regs Flags Dst => \
- i_fetch Sz r | i_bs_init_fail_heap Words Fail Regs Dst
+ i_bs_init_fail_heap Sz Words Fail Regs Dst
-i_bs_init_fail r j I d
i_bs_init_fail x j I d
i_bs_init_fail y j I d
-i_bs_init_fail_heap I j I d
+i_bs_init_fail_heap s I j I d
i_bs_init I I d
i_bs_init_heap_bin I I d
@@ -1408,39 +1301,35 @@ bs_init_bits Fail Sz=u Words Regs Flags Dst => i_bs_init_bits_heap Sz Words Reg
bs_init_bits Fail Sz Words=u==0 Regs Flags Dst => \
i_bs_init_bits_fail Sz Fail Regs Dst
bs_init_bits Fail Sz Words Regs Flags Dst => \
- i_fetch Sz r | i_bs_init_bits_fail_heap Words Fail Regs Dst
+ i_bs_init_bits_fail_heap Sz Words Fail Regs Dst
-i_bs_init_bits_fail r j I d
i_bs_init_bits_fail x j I d
i_bs_init_bits_fail y j I d
-i_bs_init_bits_fail_heap I j I d
+i_bs_init_bits_fail_heap s I j I d
i_bs_init_bits I I d
i_bs_init_bits_heap I I I d
bs_add Fail S1=i==0 S2 Unit=u==1 D => move S2 D
-bs_add Fail S1 S2 Unit D => i_fetch S1 S2 | i_bs_add Fail Unit D
-i_bs_add j I d
+bs_add j s s I d
bs_append Fail Size Extra Live Unit Bin Flags Dst => \
- i_fetch Size Bin | i_bs_append Fail Extra Live Unit Dst
+ move Bin x | i_bs_append Fail Extra Live Unit Size Dst
bs_private_append Fail Size Unit Bin Flags Dst => \
- i_fetch Size Bin | i_bs_private_append Fail Unit Dst
+ i_bs_private_append Fail Unit Size Bin Dst
bs_init_writable
-i_bs_append j I I I d
-i_bs_private_append j I d
+i_bs_append j I I I s d
+i_bs_private_append j I s s d
#
# Storing integers into binaries.
#
-bs_put_integer Fail=j Sz=s Unit=u Flags=u Literal=q => \
- move Literal x | bs_put_integer Fail Sz Unit Flags x
bs_put_integer Fail=j Sz=sq Unit=u Flags=u Src=s => \
gen_put_integer(Fail, Sz, Unit, Flags, Src)
@@ -1454,32 +1343,22 @@ i_new_bs_put_integer_imm j I I s
# Utf8/utf16/utf32 support. (R12B-5)
#
-bs_utf8_size Fail Literal=q Dst=d => \
- move Literal x | bs_utf8_size Fail x Dst
bs_utf8_size j Src=s Dst=d => i_bs_utf8_size Src Dst
i_bs_utf8_size s d
-bs_utf16_size Fail Literal=q Dst=d => \
- move Literal x | bs_utf16_size Fail x Dst
bs_utf16_size j Src=s Dst=d => i_bs_utf16_size Src Dst
i_bs_utf16_size s d
-bs_put_utf8 Fail=j Flags=u Literal=q => \
- move Literal x | bs_put_utf8 Fail Flags x
bs_put_utf8 Fail u Src=s => i_bs_put_utf8 Fail Src
i_bs_put_utf8 j s
-bs_put_utf16 Fail=j Flags=u Literal=q => \
- move Literal x | bs_put_utf16 Fail Flags x
bs_put_utf16 Fail Flags=u Src=s => i_bs_put_utf16 Fail Flags Src
i_bs_put_utf16 j I s
-bs_put_utf32 Fail=j Flags=u Literal=q => \
- move Literal x | bs_put_utf32 Fail Flags x
bs_put_utf32 Fail=j Flags=u Src=s => \
i_bs_validate_unicode Fail Src | bs_put_integer Fail i=32 u=1 Flags Src
@@ -1490,9 +1369,6 @@ i_bs_validate_unicode j s
#
bs_put_float Fail Sz=q Unit Flags Val => badarg Fail
-bs_put_float Fail=j Sz Unit=u Flags=u Literal=q => \
- move Literal x | bs_put_float Fail Sz Unit Flags x
-
bs_put_float Fail=j Sz=s Unit=u Flags=u Src=s => \
gen_put_float(Fail, Sz, Unit, Flags, Src)
@@ -1506,8 +1382,6 @@ i_new_bs_put_float_imm j I I s
# Storing binaries into binaries.
#
-bs_put_binary Fail Sz Unit Flags Literal=q => \
- move Literal x | bs_put_binary Fail Sz Unit Flags x
bs_put_binary Fail=j Sz=s Unit=u Flags=u Src=s => \
gen_put_binary(Fail, Sz, Unit, Flags, Src)
@@ -1600,7 +1474,6 @@ is_map Fail Lit=q | literal_is_map(Lit) =>
is_map Fail cq => jump Fail
%macro: is_map IsMap -fail_action
-is_map f r
is_map f x
is_map f y
@@ -1611,101 +1484,120 @@ has_map_fields Fail Src Size Rest=* => \
## Transform get_map_elements(s) #{ K1 := V1, K2 := V2 }
-get_map_elements Fail Src=rxy Size=u==2 Rest=* => \
+get_map_elements Fail Src=xy Size=u==2 Rest=* => \
gen_get_map_element(Fail, Src, Size, Rest)
get_map_elements Fail Src Size Rest=* | map_key_sort(Size, Rest) => \
gen_get_map_elements(Fail, Src, Size, Rest)
i_get_map_elements f s I
-i_get_map_element Fail Src=rxy Key=ry Dst => \
+i_get_map_element Fail Src=xy Key=y Dst => \
move Key x | i_get_map_element Fail Src x Dst
%macro: i_get_map_element_hash GetMapElementHash -fail_action
-i_get_map_element_hash f r c I r
-i_get_map_element_hash f x c I r
-i_get_map_element_hash f y c I r
-i_get_map_element_hash f r c I x
i_get_map_element_hash f x c I x
i_get_map_element_hash f y c I x
-i_get_map_element_hash f r c I y
i_get_map_element_hash f x c I y
i_get_map_element_hash f y c I y
%macro: i_get_map_element GetMapElement -fail_action
-i_get_map_element f r x r
-i_get_map_element f x x r
-i_get_map_element f y x r
-i_get_map_element f r x x
i_get_map_element f x x x
i_get_map_element f y x x
-i_get_map_element f r x y
i_get_map_element f x x y
i_get_map_element f y x y
#
+# Convert the plus operations to a generic plus instruction.
+#
+gen_plus/5
+gen_minus/5
+
+gc_bif1 Fail Live u$bif:erlang:splus/1 Src Dst => \
+ gen_plus Fail Live Src i Dst
+gc_bif2 Fail Live u$bif:erlang:splus/2 S1 S2 Dst => \
+ gen_plus Fail Live S1 S2 Dst
+
+gc_bif1 Fail Live u$bif:erlang:sminus/1 Src Dst => \
+ gen_minus Fail Live i Src Dst
+gc_bif2 Fail Live u$bif:erlang:sminus/2 S1 S2 Dst => \
+ gen_minus Fail Live S1 S2 Dst
+
+#
# Optimize addition and subtraction of small literals using
# the i_increment/4 instruction (in bodies, not in guards).
#
-gc_bif2 p Live u$bif:erlang:splus/2 Int=i Reg=d Dst => \
+gen_plus p Live Int=i Reg=d Dst => \
gen_increment(Reg, Int, Live, Dst)
-gc_bif2 p Live u$bif:erlang:splus/2 Reg=d Int=i Dst => \
+gen_plus p Live Reg=d Int=i Dst => \
gen_increment(Reg, Int, Live, Dst)
-gc_bif2 p Live u$bif:erlang:sminus/2 Reg=d Int=i Dst | \
- negation_is_small(Int) => \
+gen_minus p Live Reg=d Int=i Dst | negation_is_small(Int) => \
gen_increment_from_minus(Reg, Int, Live, Dst)
#
# GCing arithmetic instructions.
#
-gc_bif2 Fail I u$bif:erlang:splus/2 S1=x S2=x Dst=d => i_plus Fail I S1 S2 Dst
-gc_bif2 Fail I u$bif:erlang:splus/2 S1 S2 Dst=d => i_fetch S1 S2 | i_plus Fail I Dst
-gc_bif2 Fail I u$bif:erlang:sminus/2 S1=x S2=x Dst=d => i_minus Fail I S1 S2 Dst
-gc_bif2 Fail I u$bif:erlang:sminus/2 S1 S2 Dst=d => i_fetch S1 S2 | i_minus Fail I Dst
-gc_bif2 Fail I u$bif:erlang:stimes/2 S1 S2 Dst=d => i_fetch S1 S2 | i_times Fail I Dst
-gc_bif2 Fail I u$bif:erlang:div/2 S1 S2 Dst=d => i_fetch S1 S2 | i_m_div Fail I Dst
+gen_plus Fail Live Y=y X=x Dst => i_plus Fail Live X Y Dst
+gen_plus Fail Live S1 S2 Dst => i_plus Fail Live S1 S2 Dst
-gc_bif2 Fail I u$bif:erlang:intdiv/2 S1 S2 Dst=d => i_fetch S1 S2 | i_int_div Fail I Dst
-gc_bif2 Fail I u$bif:erlang:rem/2 S1=x S2=x Dst=d => i_rem Fail I S1 S2 Dst
-gc_bif2 Fail I u$bif:erlang:rem/2 S1 S2 Dst=d => i_fetch S1 S2 | i_rem Fail I Dst
+gen_minus Fail Live S1 S2 Dst => i_minus Fail Live S1 S2 Dst
-gc_bif2 Fail I u$bif:erlang:bsl/2 S1 S2 Dst=d => i_fetch S1 S2 | i_bsl Fail I Dst
-gc_bif2 Fail I u$bif:erlang:bsr/2 S1 S2 Dst=d => i_fetch S1 S2 | i_bsr Fail I Dst
+gc_bif2 Fail Live u$bif:erlang:stimes/2 S1 S2 Dst => \
+ i_times Fail Live S1 S2 Dst
-gc_bif2 Fail I u$bif:erlang:band/2 S1=x S2=c Dst=d => i_band Fail I S1 S2 Dst
-gc_bif2 Fail I u$bif:erlang:band/2 S1 S2 Dst=d => i_fetch S1 S2 | i_band Fail I Dst
-gc_bif2 Fail I u$bif:erlang:bor/2 S1 S2 Dst=d => i_fetch S1 S2 | i_bor Fail I Dst
-gc_bif2 Fail I u$bif:erlang:bxor/2 S1 S2 Dst=d => i_fetch S1 S2 | i_bxor Fail I Dst
+gc_bif2 Fail Live u$bif:erlang:div/2 S1 S2 Dst => \
+ i_m_div Fail Live S1 S2 Dst
+gc_bif2 Fail Live u$bif:erlang:intdiv/2 S1 S2 Dst => \
+ i_int_div Fail Live S1 S2 Dst
-gc_bif1 Fail I u$bif:erlang:bnot/1 Src Dst=d => i_int_bnot Fail Src I Dst
+gc_bif2 Fail Live u$bif:erlang:rem/2 S1 S2 Dst => \
+ i_rem Fail Live S1 S2 Dst
+
+gc_bif2 Fail Live u$bif:erlang:bsl/2 S1 S2 Dst => \
+ i_bsl Fail Live S1 S2 Dst
+gc_bif2 Fail Live u$bif:erlang:bsr/2 S1 S2 Dst => \
+ i_bsr Fail Live S1 S2 Dst
+
+gc_bif2 Fail Live u$bif:erlang:band/2 S1 S2 Dst => \
+ i_band Fail Live S1 S2 Dst
+
+gc_bif2 Fail Live u$bif:erlang:bor/2 S1 S2 Dst => \
+ i_bor Fail Live S1 S2 Dst
-gc_bif1 Fail I u$bif:erlang:sminus/1 Src Dst=d => i_fetch i Src | i_minus Fail I Dst
-gc_bif1 Fail I u$bif:erlang:splus/1 Src Dst=d => i_fetch i Src | i_plus Fail I Dst
+gc_bif2 Fail Live u$bif:erlang:bxor/2 S1 S2 Dst => \
+ i_bxor Fail Live S1 S2 Dst
+
+gc_bif1 Fail I u$bif:erlang:bnot/1 Src Dst=d => i_int_bnot Fail Src I Dst
i_increment r I I d
i_increment x I I d
i_increment y I I d
i_plus j I x x d
-i_plus j I d
+i_plus j I x y d
+i_plus j I s s d
+
i_minus j I x x d
-i_minus j I d
-i_times j I d
-i_m_div j I d
-i_int_div j I d
+i_minus j I s s d
+
+i_times j I s s d
+
+i_m_div j I s s d
+i_int_div j I s s d
+
i_rem j I x x d
-i_rem j I d
+i_rem j I s s d
-i_bsl j I d
-i_bsr j I d
+i_bsl j I s s d
+i_bsr j I s s d
i_band j I x c d
-i_band j I d
-i_bor j I d
-i_bxor j I d
+i_band j I s s d
+
+i_bor j I s s d
+i_bxor j I s s d
i_int_bnot j s I d
@@ -1731,21 +1623,18 @@ gc_bif2 Fail I Bif S1 S2 Dst => \
gc_bif3 Fail I Bif S1 S2 S3 Dst => \
gen_guard_bif3(Fail, I, Bif, S1, S2, S3, Dst)
-i_gc_bif1 Fail Bif V=q Live D => move V x | i_gc_bif1 Fail Bif x Live D
-
i_gc_bif1 j I s I d
-ii_gc_bif2/6
-
-ii_gc_bif2 Fail Bif S1 S2 Live D => i_fetch S1 S2 | i_gc_bif2 Fail Bif Live D
-
-i_gc_bif2 j I I d
+i_gc_bif2 j I I s s d
ii_gc_bif3/7
-ii_gc_bif3 Fail Bif S1 S2 S3 Live D => move S1 x | i_fetch S2 S3 | i_gc_bif3 Fail Bif x Live D
+# A specific instruction can only have 6 operands, so we must
+# pass one of the arguments in an x register.
+ii_gc_bif3 Fail Bif Live S1 S2 S3 Dst => \
+ move S1 x | i_gc_bif3 Fail Bif Live S2 S3 Dst
-i_gc_bif3 j I s I d
+i_gc_bif3 j I I s s d
#
# The following instruction is specially handled in beam_load.c
diff --git a/erts/emulator/beam/register.c b/erts/emulator/beam/register.c
index 020e61d136..ebc35b0c4d 100644
--- a/erts/emulator/beam/register.c
+++ b/erts/emulator/beam/register.c
@@ -151,6 +151,9 @@ void init_register_table(void)
f.cmp = (HCMP_FUN) reg_cmp;
f.alloc = (HALLOC_FUN) reg_alloc;
f.free = (HFREE_FUN) reg_free;
+ f.meta_alloc = (HMALLOC_FUN) erts_alloc;
+ f.meta_free = (HMFREE_FUN) erts_free;
+ f.meta_print = (HMPRINT_FUN) erts_print;
hash_init(ERTS_ALC_T_REG_TABLE, &process_reg, "process_reg",
PREG_HASH_SIZE, f);
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index 6497a1e648..03b9088adc 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -21,6 +21,19 @@
#ifndef __SYS_H__
#define __SYS_H__
+#if !defined(__GNUC__)
+# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) 0
+#elif !defined(__GNUC_MINOR__)
+# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
+ ((__GNUC__ << 24) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
+#elif !defined(__GNUC_PATCHLEVEL__)
+# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
+ (((__GNUC__ << 24) | (__GNUC_MINOR__ << 12)) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
+#else
+# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
+ (((__GNUC__ << 24) | (__GNUC_MINOR__ << 12) | __GNUC_PATCHLEVEL__) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
+#endif
+
#ifdef ERTS_INLINE
# ifndef ERTS_CAN_INLINE
# define ERTS_CAN_INLINE 1
@@ -38,6 +51,17 @@
# endif
#endif
+#ifndef ERTS_FORCE_INLINE
+# if ERTS_AT_LEAST_GCC_VSN__(3,1,1)
+# define ERTS_FORCE_INLINE __inline__ __attribute__((__always_inline__))
+# elif defined(__WIN32__)
+# define ERTS_FORCE_INLINE __forceinline
+# endif
+# ifndef ERTS_FORCE_INLINE
+# define ERTS_FORCE_INLINE ERTS_INLINE
+# endif
+#endif
+
#if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
# undef ERTS_CAN_INLINE
# define ERTS_CAN_INLINE 0
@@ -46,8 +70,10 @@
#endif
#if ERTS_CAN_INLINE
+#define ERTS_GLB_FORCE_INLINE static ERTS_FORCE_INLINE
#define ERTS_GLB_INLINE static ERTS_INLINE
#else
+#define ERTS_GLB_FORCE_INLINE
#define ERTS_GLB_INLINE
#endif
@@ -61,22 +87,14 @@
# define NO_FPE_SIGNALS
#endif
-#ifdef DISABLE_CHILD_WAITER_THREAD
-#undef ENABLE_CHILD_WAITER_THREAD
-#endif
-
-#if defined(ERTS_SMP) && !defined(DISABLE_CHILD_WAITER_THREAD)
-#undef ENABLE_CHILD_WAITER_THREAD
-#define ENABLE_CHILD_WAITER_THREAD 1
-#endif
-
#define ERTS_I64_LITERAL(X) X##LL
+#define ErtsInArea(ptr,start,nbytes) \
+ ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes))
+
#if defined (__WIN32__)
# include "erl_win_sys.h"
-#elif defined (__OSE__)
-# include "erl_ose_sys.h"
-#else
+#else
# include "erl_unix_sys.h"
#ifndef UNIX
# define UNIX 1
@@ -111,19 +129,6 @@ typedef int ErtsSysFdType;
typedef ERTS_SYS_FD_TYPE ErtsSysFdType;
#endif
-#if !defined(__GNUC__)
-# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) 0
-#elif !defined(__GNUC_MINOR__)
-# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
- ((__GNUC__ << 24) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
-#elif !defined(__GNUC_PATCHLEVEL__)
-# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
- (((__GNUC__ << 24) | (__GNUC_MINOR__ << 12)) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
-#else
-# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
- (((__GNUC__ << 24) | (__GNUC_MINOR__ << 12) | __GNUC_PATCHLEVEL__) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
-#endif
-
#if ERTS_AT_LEAST_GCC_VSN__(2, 96, 0)
# define ERTS_LIKELY(BOOL) __builtin_expect((BOOL), !0)
# define ERTS_UNLIKELY(BOOL) __builtin_expect((BOOL), 0)
@@ -131,6 +136,17 @@ typedef ERTS_SYS_FD_TYPE ErtsSysFdType;
# define ERTS_LIKELY(BOOL) (BOOL)
# define ERTS_UNLIKELY(BOOL) (BOOL)
#endif
+
+#if ERTS_AT_LEAST_GCC_VSN__(2, 96, 0)
+#ifndef __llvm__
+# define ERTS_WRITE_UNLIKELY(X) X __attribute__ ((section ("ERTS_LOW_WRITE") ))
+#else
+# define ERTS_WRITE_UNLIKELY(X) X __attribute__ ((section ("__DATA,ERTS_LOW_WRITE") ))
+#endif
+#else
+# define ERTS_WRITE_UNLIKELY(X) X
+#endif
+
#ifdef __GNUC__
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
# define ERTS_DECLARE_DUMMY(X) X __attribute__ ((unused))
@@ -191,6 +207,12 @@ __decl_noreturn void __noreturn erl_assert_error(const char* expr, const char *f
# define ASSERT(e) ((void) 1)
#endif
+#ifdef ERTS_SMP
+# define ERTS_SMP_ASSERT(e) ASSERT(e)
+#else
+# define ERTS_SMP_ASSERT(e) ((void)1)
+#endif
+
/* ERTS_UNDEF can be used to silence false warnings about
* "variable may be used uninitialized" while keeping the variable
* marked as undefined by valgrind.
@@ -285,62 +307,11 @@ __decl_noreturn void __noreturn erl_assert_error(const char* expr, const char *f
#else
#error Neither 32 nor 64 bit architecture
#endif
-#if defined(ARCH_64) && defined(HALFWORD_HEAP_EMULATOR)
-# define HALFWORD_HEAP 1
-# define HALFWORD_ASSERT 0
-# define ASSERT_HALFWORD(COND) ASSERT(COND)
-# undef ERTS_SIZEOF_TERM
-# define ERTS_SIZEOF_TERM 4
-#else
-# define HALFWORD_HEAP 0
-# define HALFWORD_ASSERT 0
-# define ASSERT_HALFWORD(COND)
-#endif
#if SIZEOF_VOID_P != SIZEOF_SIZE_T
#error sizeof(void*) != sizeof(size_t)
#endif
-#if HALFWORD_HEAP
-
-#if SIZEOF_INT == 4
-typedef unsigned int Eterm;
-typedef unsigned int Uint;
-typedef int Sint;
-#define ERTS_UINT_MAX UINT_MAX
-#define ERTS_SIZEOF_ETERM SIZEOF_INT
-#define ErtsStrToSint strtol
-#else
-#error Found no appropriate type to use for 'Eterm', 'Uint' and 'Sint'
-#endif
-
-#if SIZEOF_VOID_P == SIZEOF_LONG
-typedef unsigned long UWord;
-typedef long SWord;
-#define SWORD_CONSTANT(Const) Const##L
-#define UWORD_CONSTANT(Const) Const##UL
-#define ERTS_UWORD_MAX ULONG_MAX
-#define ERTS_SWORD_MAX LONG_MAX
-#elif SIZEOF_VOID_P == SIZEOF_INT
-typedef unsigned int UWord;
-typedef int SWord;
-#define SWORD_CONSTANT(Const) Const
-#define UWORD_CONSTANT(Const) Const##U
-#define ERTS_UWORD_MAX UINT_MAX
-#define ERTS_SWORD_MAX INT_MAX
-#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG
-typedef unsigned long long UWord;
-typedef long long SWord;
-#define SWORD_CONSTANT(Const) Const##LL
-#define UWORD_CONSTANT(Const) Const##ULL
-#define ERTS_UWORD_MAX ULLONG_MAX
-#define ERTS_SWORD_MAX LLONG_MAX
-#else
-#error Found no appropriate type to use for 'Eterm', 'Uint' and 'Sint'
-#endif
-
-#else /* !HALFWORD_HEAP */
-
#if SIZEOF_VOID_P == SIZEOF_LONG
typedef unsigned long Eterm;
typedef unsigned long Uint;
@@ -383,8 +354,6 @@ typedef Uint UWord;
typedef Sint SWord;
#define ERTS_UINT_MAX ERTS_UWORD_MAX
-#endif /* HALFWORD_HEAP */
-
typedef UWord BeamInstr;
#ifndef HAVE_INT64
@@ -786,6 +755,7 @@ void erts_sys_main_thread(void);
extern int erts_sys_prepare_crash_dump(int secs);
extern void erts_sys_pre_init(void);
extern void erl_sys_init(void);
+extern void erl_sys_late_init(void);
extern void erl_sys_args(int *argc, char **argv);
extern void erl_sys_schedule(int);
void sys_tty_reset(int);
@@ -1103,7 +1073,6 @@ extern int erts_use_kernel_poll;
#define put_int8(i, s) do {((unsigned char*)(s))[0] = (i) & 0xff;} while (0)
-
/*
* Use DEBUGF as you would use printf, but use double parentheses:
*
diff --git a/erts/emulator/beam/time.c b/erts/emulator/beam/time.c
index 988338ed81..0ce4f443f3 100644
--- a/erts/emulator/beam/time.c
+++ b/erts/emulator/beam/time.c
@@ -278,9 +278,14 @@ ErtsMonotonicTime
erts_check_next_timeout_time(ErtsSchedulerData *esdp)
{
ErtsTimerWheel *tiw = esdp->timer_wheel;
+ ErtsMonotonicTime time;
+ ERTS_MSACC_DECLARE_CACHE_X();
if (tiw->true_next_timeout_time)
return tiw->next_timeout_time;
- return find_next_timeout(esdp, tiw, 1, 0, 0);
+ ERTS_MSACC_PUSH_AND_SET_STATE_CACHED_X(ERTS_MSACC_STATE_TIMERS);
+ time = find_next_timeout(esdp, tiw, 1, 0, 0);
+ ERTS_MSACC_POP_STATE_M_X();
+ return time;
}
#ifndef ERTS_TW_DEBUG
@@ -336,6 +341,7 @@ erts_bump_timers(ErtsTimerWheel *tiw, ErtsMonotonicTime curr_time)
{
int tiw_pos_ix, slots, yielded_slot_restarted, yield_count;
ErtsMonotonicTime bump_to, tmp_slots, old_pos;
+ ERTS_MSACC_PUSH_AND_SET_STATE_M_X(ERTS_MSACC_STATE_TIMERS);
yield_count = ERTS_TWHEEL_BUMP_YIELD_LIMIT;
@@ -371,6 +377,7 @@ erts_bump_timers(ErtsTimerWheel *tiw, ErtsMonotonicTime curr_time)
tiw->next_timeout_time = curr_time + ERTS_MONOTONIC_DAY;
tiw->pos = bump_to;
tiw->yield_slot = ERTS_TWHEEL_SLOT_INACTIVE;
+ ERTS_MSACC_POP_STATE_M_X();
return;
}
@@ -382,6 +389,7 @@ erts_bump_timers(ErtsTimerWheel *tiw, ErtsMonotonicTime curr_time)
tiw->yield_slot = ERTS_TWHEEL_SLOT_AT_ONCE;
tiw->true_next_timeout_time = 1;
tiw->next_timeout_time = ERTS_CLKTCKS_TO_MONOTONIC(old_pos);
+ ERTS_MSACC_POP_STATE_M_X();
return;
}
@@ -400,8 +408,10 @@ erts_bump_timers(ErtsTimerWheel *tiw, ErtsMonotonicTime curr_time)
p = tiw->at_once.head;
}
- if (tiw->pos >= bump_to)
+ if (tiw->pos >= bump_to) {
+ ERTS_MSACC_POP_STATE_M_X();
break;
+ }
if (tiw->nto == 0)
goto empty_wheel;
@@ -478,6 +488,7 @@ erts_bump_timers(ErtsTimerWheel *tiw, ErtsMonotonicTime curr_time)
tiw->yield_slot = tiw_pos_ix;
tiw->yield_slots_left = slots;
tiw->yield_start_pos = old_pos;
+ ERTS_MSACC_POP_STATE_M_X();
return; /* Yield! */
}
@@ -500,6 +511,7 @@ erts_bump_timers(ErtsTimerWheel *tiw, ErtsMonotonicTime curr_time)
/* Search at most two seconds ahead... */
(void) find_next_timeout(NULL, tiw, 0, curr_time, ERTS_SEC_TO_MONOTONIC(2));
+ ERTS_MSACC_POP_STATE_M_X();
}
Uint
@@ -569,6 +581,7 @@ erts_twheel_set_timer(ErtsTimerWheel *tiw,
ErtsMonotonicTime timeout_pos)
{
ErtsMonotonicTime timeout_time;
+ ERTS_MSACC_PUSH_AND_SET_STATE_M_X(ERTS_MSACC_STATE_TIMERS);
p->u.func.timeout = timeout;
p->u.func.cancel = cancel;
@@ -612,6 +625,7 @@ erts_twheel_set_timer(ErtsTimerWheel *tiw,
tiw->true_next_timeout_time = 1;
tiw->next_timeout_time = timeout_time;
}
+ ERTS_MSACC_POP_STATE_M_X();
}
void
@@ -620,11 +634,13 @@ erts_twheel_cancel_timer(ErtsTimerWheel *tiw, ErtsTWheelTimer *p)
if (p->slot != ERTS_TWHEEL_SLOT_INACTIVE) {
ErlCancelProc cancel;
void *arg;
+ ERTS_MSACC_PUSH_AND_SET_STATE_M_X(ERTS_MSACC_STATE_TIMERS);
remove_timer(tiw, p);
cancel = p->u.func.cancel;
arg = p->u.func.arg;
if (cancel)
(*cancel)(arg);
+ ERTS_MSACC_POP_STATE_M_X();
}
}
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index b9ce70e364..66fcfcf6ce 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -110,7 +110,6 @@ Eterm*
erts_heap_alloc(Process* p, Uint need, Uint xtra)
{
ErlHeapFragment* bp;
- Eterm* htop;
Uint n;
#if defined(DEBUG) || defined(CHECK_FOR_HOLES)
Uint i;
@@ -156,16 +155,6 @@ erts_heap_alloc(Process* p, Uint need, Uint xtra)
n--;
#endif
- /*
- * When we have created a heap fragment, we are no longer allowed
- * to store anything more on the heap.
- */
- htop = HEAP_TOP(p);
- if (htop < HEAP_LIMIT(p)) {
- *htop = make_pos_bignum_header(HEAP_LIMIT(p)-htop-1);
- HEAP_TOP(p) = HEAP_LIMIT(p);
- }
-
bp->next = MBUF(p);
MBUF(p) = bp;
bp->alloc_size = n;
@@ -269,6 +258,31 @@ erl_grow_pstack(ErtsPStack* s, void* default_pstack, unsigned need_bytes)
s->psp = s->pstart + sp_offs;
}
+/*
+ * Helper function for the EQUEUE macros defined in global.h.
+ */
+
+void
+erl_grow_equeue(ErtsEQueue* q, Eterm* default_equeue)
+{
+ Uint old_size = (q->end - q->start);
+ Uint new_size = old_size * 2;
+ Uint first_part = (q->end - q->front);
+ Uint second_part = (q->back - q->start);
+ Eterm* new_ptr = erts_alloc(q->alloc_type, new_size*sizeof(Eterm));
+ ASSERT(q->back == q->front); // of course the queue is full now!
+ if (first_part > 0)
+ sys_memcpy(new_ptr, q->front, first_part*sizeof(Eterm));
+ if (second_part > 0)
+ sys_memcpy(new_ptr+first_part, q->start, second_part*sizeof(Eterm));
+ if (q->start != default_equeue)
+ erts_free(q->alloc_type, q->start);
+ q->start = new_ptr;
+ q->end = q->start + new_size;
+ q->front = q->start;
+ q->back = q->start + old_size;
+}
+
/* CTYPE macros */
#define LATIN1
@@ -303,10 +317,10 @@ erl_grow_pstack(ErtsPStack* s, void* default_pstack, unsigned need_bytes)
* Calculate length of a list.
* Returns -1 if not a proper list (i.e. not terminated with NIL)
*/
-int
+Sint
erts_list_length(Eterm list)
{
- int i = 0;
+ Sint i = 0;
while(is_list(list)) {
i++;
@@ -894,7 +908,7 @@ tail_recur:
Uint y2 = y1 < 0 ? -(Uint)y1 : y1;
UINT32_HASH_STEP(y2, FUNNY_NUMBER2);
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
if (y2 >> 32)
UINT32_HASH_STEP(y2 >> 32, FUNNY_NUMBER2);
#endif
@@ -1015,7 +1029,7 @@ tail_recur:
}
d = BIG_DIGIT(ptr, k);
k = sizeof(ErtsDigit);
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
if (!(d >> 32))
k /= 2;
#endif
@@ -1985,7 +1999,7 @@ tail_recur:
(atom_tab(atom_val(term))->slot.bucket.hvalue);
break;
case SMALL_DEF:
-#if defined(ARCH_64) && !HALFWORD_HEAP
+#if defined(ARCH_64)
{
Sint y1 = signed_val(term);
Uint y2 = y1 < 0 ? -(Uint)y1 : y1;
@@ -2281,7 +2295,11 @@ static void do_send_logger_message(Eterm *hp, ErlOffHeap *ohp, ErlHeapFragment *
erts_queue_error_logger_message(from, message, bp);
}
#else
- erts_queue_message(p, NULL /* only used for smp build */, bp, message, NIL);
+ {
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = bp;
+ erts_queue_message(p, NULL /* only used for smp build */, mp, message, NIL);
+ }
#endif
}
@@ -2594,11 +2612,7 @@ erts_destroy_tmp_dsbuf(erts_dsprintf_buf_t *dsbufp)
* Test for equality of two terms.
* Returns 0 if not equal, or a non-zero value otherwise.
*/
-#if HALFWORD_HEAP
-int eq_rel(Eterm a, Eterm* a_base, Eterm b, Eterm* b_base)
-#else
int eq(Eterm a, Eterm b)
-#endif
{
DECLARE_WSTACK(stack);
Sint sz;
@@ -2606,18 +2620,18 @@ int eq(Eterm a, Eterm b)
Eterm* bb;
tailrecur:
- if (is_same(a, a_base, b, b_base)) goto pop_next;
+ if (is_same(a, b)) goto pop_next;
tailrecur_ne:
switch (primary_tag(a)) {
case TAG_PRIMARY_LIST:
if (is_list(b)) {
- Eterm* aval = list_val_rel(a, a_base);
- Eterm* bval = list_val_rel(b, b_base);
+ Eterm* aval = list_val(a);
+ Eterm* bval = list_val(b);
while (1) {
Eterm atmp = CAR(aval);
Eterm btmp = CAR(bval);
- if (!is_same(atmp,a_base,btmp,b_base)) {
+ if (!is_same(atmp,btmp)) {
WSTACK_PUSH2(stack,(UWord) CDR(bval),(UWord) CDR(aval));
a = atmp;
b = btmp;
@@ -2625,7 +2639,7 @@ tailrecur_ne:
}
atmp = CDR(aval);
btmp = CDR(bval);
- if (is_same(atmp,a_base,btmp,b_base)) {
+ if (is_same(atmp,btmp)) {
goto pop_next;
}
if (is_not_list(atmp) || is_not_list(btmp)) {
@@ -2633,22 +2647,22 @@ tailrecur_ne:
b = btmp;
goto tailrecur_ne;
}
- aval = list_val_rel(atmp, a_base);
- bval = list_val_rel(btmp, b_base);
+ aval = list_val(atmp);
+ bval = list_val(btmp);
}
}
break; /* not equal */
case TAG_PRIMARY_BOXED:
{
- Eterm hdr = *boxed_val_rel(a,a_base);
+ Eterm hdr = *boxed_val(a);
switch (hdr & _TAG_HEADER_MASK) {
case ARITYVAL_SUBTAG:
{
- aa = tuple_val_rel(a, a_base);
- if (!is_boxed(b) || *boxed_val_rel(b,b_base) != *aa)
+ aa = tuple_val(a);
+ if (!is_boxed(b) || *boxed_val(b) != *aa)
goto not_equal;
- bb = tuple_val_rel(b,b_base);
+ bb = tuple_val(b);
if ((sz = arityval(*aa)) == 0) goto pop_next;
++aa;
++bb;
@@ -2667,16 +2681,16 @@ tailrecur_ne:
Uint a_bitoffs;
Uint b_bitoffs;
- if (!is_binary_rel(b,b_base)) {
+ if (!is_binary(b)) {
goto not_equal;
}
- a_size = binary_size_rel(a,a_base);
- b_size = binary_size_rel(b,b_base);
+ a_size = binary_size(a);
+ b_size = binary_size(b);
if (a_size != b_size) {
goto not_equal;
}
- ERTS_GET_BINARY_BYTES_REL(a, a_ptr, a_bitoffs, a_bitsize, a_base);
- ERTS_GET_BINARY_BYTES_REL(b, b_ptr, b_bitoffs, b_bitsize, b_base);
+ ERTS_GET_BINARY_BYTES(a, a_ptr, a_bitoffs, a_bitsize);
+ ERTS_GET_BINARY_BYTES(b, b_ptr, b_bitoffs, b_bitsize);
if ((a_bitsize | b_bitsize | a_bitoffs | b_bitoffs) == 0) {
if (sys_memcmp(a_ptr, b_ptr, a_size) == 0) goto pop_next;
} else if (a_bitsize == b_bitsize) {
@@ -2687,9 +2701,9 @@ tailrecur_ne:
}
case EXPORT_SUBTAG:
{
- if (is_export_rel(b,b_base)) {
- Export* a_exp = *((Export **) (export_val_rel(a,a_base) + 1));
- Export* b_exp = *((Export **) (export_val_rel(b,b_base) + 1));
+ if (is_export(b)) {
+ Export* a_exp = *((Export **) (export_val(a) + 1));
+ Export* b_exp = *((Export **) (export_val(b) + 1));
if (a_exp == b_exp) goto pop_next;
}
break; /* not equal */
@@ -2699,10 +2713,10 @@ tailrecur_ne:
ErlFunThing* f1;
ErlFunThing* f2;
- if (!is_fun_rel(b,b_base))
+ if (!is_fun(b))
goto not_equal;
- f1 = (ErlFunThing *) fun_val_rel(a,a_base);
- f2 = (ErlFunThing *) fun_val_rel(b,b_base);
+ f1 = (ErlFunThing *) fun_val(a);
+ f2 = (ErlFunThing *) fun_val(b);
if (f1->fe->module != f2->fe->module ||
f1->fe->old_index != f2->fe->old_index ||
f1->fe->old_uniq != f2->fe->old_uniq ||
@@ -2720,15 +2734,15 @@ tailrecur_ne:
ExternalThing *ap;
ExternalThing *bp;
- if(!is_external_rel(b,b_base))
+ if(!is_external(b))
goto not_equal;
- ap = external_thing_ptr_rel(a,a_base);
- bp = external_thing_ptr_rel(b,b_base);
+ ap = external_thing_ptr(a);
+ bp = external_thing_ptr(b);
if(ap->header == bp->header && ap->node == bp->node) {
- ASSERT(1 == external_data_words_rel(a,a_base));
- ASSERT(1 == external_data_words_rel(b,b_base));
+ ASSERT(1 == external_data_words(a));
+ ASSERT(1 == external_data_words(b));
if (ap->data.ui[0] == bp->data.ui[0]) goto pop_next;
}
@@ -2749,11 +2763,11 @@ tailrecur_ne:
ExternalThing* athing;
ExternalThing* bthing;
- if(!is_external_ref_rel(b,b_base))
+ if(!is_external_ref(b))
goto not_equal;
- athing = external_thing_ptr_rel(a,a_base);
- bthing = external_thing_ptr_rel(b,b_base);
+ athing = external_thing_ptr(a);
+ bthing = external_thing_ptr(b);
if(athing->node != bthing->node)
goto not_equal;
@@ -2765,12 +2779,12 @@ tailrecur_ne:
goto ref_common;
case REF_SUBTAG:
- if (!is_internal_ref_rel(b,b_base))
+ if (!is_internal_ref(b))
goto not_equal;
{
- RefThing* athing = ref_thing_ptr_rel(a,a_base);
- RefThing* bthing = ref_thing_ptr_rel(b,b_base);
+ RefThing* athing = ref_thing_ptr(a);
+ RefThing* bthing = ref_thing_ptr(b);
alen = internal_thing_ref_no_of_numbers(athing);
blen = internal_thing_ref_no_of_numbers(bthing);
anum = internal_thing_ref_numbers(athing);
@@ -2820,10 +2834,10 @@ tailrecur_ne:
{
int i;
- if (!is_big_rel(b,b_base))
+ if (!is_big(b))
goto not_equal;
- aa = big_val_rel(a,a_base);
- bb = big_val_rel(b,b_base);
+ aa = big_val(a);
+ bb = big_val(b);
if (*aa != *bb)
goto not_equal;
i = BIG_ARITY(aa);
@@ -2838,19 +2852,19 @@ tailrecur_ne:
FloatDef af;
FloatDef bf;
- if (is_float_rel(b,b_base)) {
- GET_DOUBLE_REL(a, af, a_base);
- GET_DOUBLE_REL(b, bf, b_base);
+ if (is_float(b)) {
+ GET_DOUBLE(a, af);
+ GET_DOUBLE(b, bf);
if (af.fd == bf.fd) goto pop_next;
}
break; /* not equal */
}
case MAP_SUBTAG:
- if (is_flatmap_rel(a, a_base)) {
- aa = flatmap_val_rel(a, a_base);
- if (!is_boxed(b) || *boxed_val_rel(b,b_base) != *aa)
+ if (is_flatmap(a)) {
+ aa = flatmap_val(a);
+ if (!is_boxed(b) || *boxed_val(b) != *aa)
goto not_equal;
- bb = flatmap_val_rel(b,b_base);
+ bb = flatmap_val(b);
sz = flatmap_get_size((flatmap_t*)aa);
if (sz != flatmap_get_size((flatmap_t*)bb)) goto not_equal;
@@ -2862,11 +2876,11 @@ tailrecur_ne:
goto term_array;
} else {
- if (!is_boxed(b) || *boxed_val_rel(b,b_base) != hdr)
+ if (!is_boxed(b) || *boxed_val(b) != hdr)
goto not_equal;
- aa = hashmap_val_rel(a, a_base) + 1;
- bb = hashmap_val_rel(b, b_base) + 1;
+ aa = hashmap_val(a) + 1;
+ bb = hashmap_val(b) + 1;
switch (hdr & _HEADER_MAP_SUBTAG_MASK) {
case HAMT_SUBTAG_HEAD_ARRAY:
aa++; bb++;
@@ -2899,7 +2913,7 @@ term_array: /* arrays in 'aa' and 'bb', length in 'sz' */
Eterm* bp = bb;
Sint i = sz;
for (;;) {
- if (!is_same(*ap,a_base,*bp,b_base)) break;
+ if (!is_same(*ap,*bp)) break;
if (--i == 0) goto pop_next;
++ap;
++bp;
@@ -2977,7 +2991,7 @@ static int cmpbytes(byte *s1, int l1, byte *s2, int l2)
#define float_comp(x,y) (((x)<(y)) ? -1 : (((x)==(y)) ? 0 : 1))
-static int cmp_atoms(Eterm a, Eterm b)
+int erts_cmp_atoms(Eterm a, Eterm b)
{
Atom *aa = atom_tab(atom_val(a));
Atom *bb = atom_tab(atom_val(b));
@@ -2988,7 +3002,6 @@ static int cmp_atoms(Eterm a, Eterm b)
bb->name+3, bb->len-3);
}
-#if !HALFWORD_HEAP
/* cmp(Eterm a, Eterm b)
* For compatibility with HiPE - arith-based compare.
*/
@@ -2996,39 +3009,22 @@ Sint cmp(Eterm a, Eterm b)
{
return erts_cmp(a, b, 0, 0);
}
-#endif
-#if HALFWORD_HEAP
-static Sint erts_cmp_compound_rel_opt(Eterm a, Eterm* a_base,
- Eterm b, Eterm* b_base,
- int exact, int eq_only);
-#else
-static Sint erts_cmp_compound(Eterm a, Eterm b, int exact, int eq_only);
-#endif
+Sint erts_cmp_compound(Eterm a, Eterm b, int exact, int eq_only);
-#if HALFWORD_HEAP
-Sint erts_cmp_rel_opt(Eterm a, Eterm* a_base,
- Eterm b, Eterm* b_base,
- int exact, int eq_only)
-#else
Sint erts_cmp(Eterm a, Eterm b, int exact, int eq_only)
-#endif
{
if (is_atom(a) && is_atom(b)) {
- return cmp_atoms(a, b);
+ return erts_cmp_atoms(a, b);
} else if (is_both_small(a, b)) {
return (signed_val(a) - signed_val(b));
- } else if (is_float_rel(a, a_base) && is_float_rel(b, b_base)) {
+ } else if (is_float(a) && is_float(b)) {
FloatDef af, bf;
- GET_DOUBLE_REL(a, af, a_base);
- GET_DOUBLE_REL(b, bf, b_base);
+ GET_DOUBLE(a, af);
+ GET_DOUBLE(b, bf);
return float_comp(af.fd, bf.fd);
}
-#if HALFWORD_HEAP
- return erts_cmp_compound_rel_opt(a,a_base,b,b_base,exact,eq_only);
-#else
return erts_cmp_compound(a,b,exact,eq_only);
-#endif
}
@@ -3036,13 +3032,7 @@ Sint erts_cmp(Eterm a, Eterm b, int exact, int eq_only)
* exact = 1 -> term-based compare
* exact = 0 -> arith-based compare
*/
-#if HALFWORD_HEAP
-static Sint erts_cmp_compound_rel_opt(Eterm a, Eterm* a_base,
- Eterm b, Eterm* b_base,
- int exact, int eq_only)
-#else
-static Sint erts_cmp_compound(Eterm a, Eterm b, int exact, int eq_only)
-#endif
+Sint erts_cmp_compound(Eterm a, Eterm b, int exact, int eq_only)
{
#define PSTACK_TYPE struct erts_cmp_hashmap_state
struct erts_cmp_hashmap_state {
@@ -3099,7 +3089,7 @@ static Sint erts_cmp_compound(Eterm a, Eterm b, int exact, int eq_only)
do { \
if((AN) != (BN)) { \
if((AN)->sysname != (BN)->sysname) \
- RETURN_NEQ(cmp_atoms((AN)->sysname, (BN)->sysname)); \
+ RETURN_NEQ(erts_cmp_atoms((AN)->sysname, (BN)->sysname)); \
ASSERT((AN)->creation != (BN)->creation); \
RETURN_NEQ(((AN)->creation < (BN)->creation) ? -1 : 1); \
} \
@@ -3109,7 +3099,7 @@ static Sint erts_cmp_compound(Eterm a, Eterm b, int exact, int eq_only)
bodyrecur:
j = 0;
tailrecur:
- if (is_same(a,a_base,b,b_base)) { /* Equal values or pointers. */
+ if (is_same(a,b)) { /* Equal values or pointers. */
goto pop_next;
}
tailrecur_ne:
@@ -3117,7 +3107,7 @@ tailrecur_ne:
/* deal with majority (?) cases by brute-force */
if (is_atom(a)) {
if (is_atom(b)) {
- ON_CMP_GOTO(cmp_atoms(a, b));
+ ON_CMP_GOTO(erts_cmp_atoms(a, b));
}
} else if (is_both_small(a, b)) {
ON_CMP_GOTO(signed_val(a) - signed_val(b));
@@ -3135,9 +3125,9 @@ tailrecur_ne:
if (is_internal_port(b)) {
bnode = erts_this_node;
bdata = internal_port_data(b);
- } else if (is_external_port_rel(b,b_base)) {
- bnode = external_port_node_rel(b,b_base);
- bdata = external_port_data_rel(b,b_base);
+ } else if (is_external_port(b)) {
+ bnode = external_port_node(b);
+ bdata = external_port_data(b);
} else {
a_tag = PORT_DEF;
goto mixed_types;
@@ -3153,9 +3143,9 @@ tailrecur_ne:
if (is_internal_pid(b)) {
bnode = erts_this_node;
bdata = internal_pid_data(b);
- } else if (is_external_pid_rel(b,b_base)) {
- bnode = external_pid_node_rel(b,b_base);
- bdata = external_pid_data_rel(b,b_base);
+ } else if (is_external_pid(b)) {
+ bnode = external_pid_node(b);
+ bdata = external_pid_data(b);
} else {
a_tag = PID_DEF;
goto mixed_types;
@@ -3188,12 +3178,12 @@ tailrecur_ne:
a_tag = LIST_DEF;
goto mixed_types;
}
- aa = list_val_rel(a,a_base);
- bb = list_val_rel(b,b_base);
+ aa = list_val(a);
+ bb = list_val(b);
while (1) {
Eterm atmp = CAR(aa);
Eterm btmp = CAR(bb);
- if (!is_same(atmp,a_base,btmp,b_base)) {
+ if (!is_same(atmp,btmp)) {
WSTACK_PUSH2(stack,(UWord) CDR(bb),(UWord) CDR(aa));
a = atmp;
b = btmp;
@@ -3201,7 +3191,7 @@ tailrecur_ne:
}
atmp = CDR(aa);
btmp = CDR(bb);
- if (is_same(atmp,a_base,btmp,b_base)) {
+ if (is_same(atmp,btmp)) {
goto pop_next;
}
if (is_not_list(atmp) || is_not_list(btmp)) {
@@ -3209,20 +3199,20 @@ tailrecur_ne:
b = btmp;
goto tailrecur_ne;
}
- aa = list_val_rel(atmp,a_base);
- bb = list_val_rel(btmp,b_base);
+ aa = list_val(atmp);
+ bb = list_val(btmp);
}
case TAG_PRIMARY_BOXED:
{
- Eterm ahdr = *boxed_val_rel(a,a_base);
+ Eterm ahdr = *boxed_val(a);
switch ((ahdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) {
case (_TAG_HEADER_ARITYVAL >> _TAG_PRIMARY_SIZE):
- if (!is_tuple_rel(b,b_base)) {
+ if (!is_tuple(b)) {
a_tag = TUPLE_DEF;
goto mixed_types;
}
- aa = tuple_val_rel(a,a_base);
- bb = tuple_val_rel(b,b_base);
+ aa = tuple_val(a);
+ bb = tuple_val(b);
/* compare the arities */
i = arityval(ahdr); /* get the arity*/
if (i != arityval(*bb)) {
@@ -3238,18 +3228,18 @@ tailrecur_ne:
{
struct erts_cmp_hashmap_state* sp;
if (is_flatmap_header(ahdr)) {
- if (!is_flatmap_rel(b,b_base)) {
- if (is_hashmap_rel(b,b_base)) {
- aa = (Eterm *)flatmap_val_rel(a,a_base);
- i = flatmap_get_size((flatmap_t*)aa) - hashmap_size_rel(b,b_base);
+ if (!is_flatmap(b)) {
+ if (is_hashmap(b)) {
+ aa = (Eterm *)flatmap_val(a);
+ i = flatmap_get_size((flatmap_t*)aa) - hashmap_size(b);
ASSERT(i != 0);
RETURN_NEQ(i);
}
a_tag = MAP_DEF;
goto mixed_types;
}
- aa = (Eterm *)flatmap_val_rel(a,a_base);
- bb = (Eterm *)flatmap_val_rel(b,b_base);
+ aa = (Eterm *)flatmap_val(a);
+ bb = (Eterm *)flatmap_val(b);
i = flatmap_get_size((flatmap_t*)aa);
if (i != flatmap_get_size((flatmap_t*)bb)) {
@@ -3276,21 +3266,21 @@ tailrecur_ne:
goto bodyrecur;
}
}
- if (!is_hashmap_rel(b,b_base)) {
- if (is_flatmap_rel(b,b_base)) {
- bb = (Eterm *)flatmap_val_rel(b,b_base);
- i = hashmap_size_rel(a,a_base) - flatmap_get_size((flatmap_t*)bb);
+ if (!is_hashmap(b)) {
+ if (is_flatmap(b)) {
+ bb = (Eterm *)flatmap_val(b);
+ i = hashmap_size(a) - flatmap_get_size((flatmap_t*)bb);
ASSERT(i != 0);
RETURN_NEQ(i);
}
a_tag = MAP_DEF;
goto mixed_types;
}
- i = hashmap_size_rel(a,a_base) - hashmap_size_rel(b,b_base);
+ i = hashmap_size(a) - hashmap_size(b);
if (i) {
RETURN_NEQ(i);
}
- if (hashmap_size_rel(a,a_base) == 0) {
+ if (hashmap_size(a) == 0) {
goto pop_next;
}
@@ -3325,48 +3315,48 @@ tailrecur_ne:
goto bodyrecur;
}
case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):
- if (!is_float_rel(b,b_base)) {
+ if (!is_float(b)) {
a_tag = FLOAT_DEF;
goto mixed_types;
} else {
FloatDef af;
FloatDef bf;
- GET_DOUBLE_REL(a, af, a_base);
- GET_DOUBLE_REL(b, bf, b_base);
+ GET_DOUBLE(a, af);
+ GET_DOUBLE(b, bf);
ON_CMP_GOTO(float_comp(af.fd, bf.fd));
}
case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):
case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE):
- if (!is_big_rel(b,b_base)) {
+ if (!is_big(b)) {
a_tag = BIG_DEF;
goto mixed_types;
}
- ON_CMP_GOTO(big_comp(rterm2wterm(a,a_base), rterm2wterm(b,b_base)));
+ ON_CMP_GOTO(big_comp(a, b));
case (_TAG_HEADER_EXPORT >> _TAG_PRIMARY_SIZE):
- if (!is_export_rel(b,b_base)) {
+ if (!is_export(b)) {
a_tag = EXPORT_DEF;
goto mixed_types;
} else {
- Export* a_exp = *((Export **) (export_val_rel(a,a_base) + 1));
- Export* b_exp = *((Export **) (export_val_rel(b,b_base) + 1));
+ Export* a_exp = *((Export **) (export_val(a) + 1));
+ Export* b_exp = *((Export **) (export_val(b) + 1));
- if ((j = cmp_atoms(a_exp->code[0], b_exp->code[0])) != 0) {
+ if ((j = erts_cmp_atoms(a_exp->code[0], b_exp->code[0])) != 0) {
RETURN_NEQ(j);
}
- if ((j = cmp_atoms(a_exp->code[1], b_exp->code[1])) != 0) {
+ if ((j = erts_cmp_atoms(a_exp->code[1], b_exp->code[1])) != 0) {
RETURN_NEQ(j);
}
ON_CMP_GOTO((Sint) a_exp->code[2] - (Sint) b_exp->code[2]);
}
break;
case (_TAG_HEADER_FUN >> _TAG_PRIMARY_SIZE):
- if (!is_fun_rel(b,b_base)) {
+ if (!is_fun(b)) {
a_tag = FUN_DEF;
goto mixed_types;
} else {
- ErlFunThing* f1 = (ErlFunThing *) fun_val_rel(a,a_base);
- ErlFunThing* f2 = (ErlFunThing *) fun_val_rel(b,b_base);
+ ErlFunThing* f1 = (ErlFunThing *) fun_val(a);
+ ErlFunThing* f2 = (ErlFunThing *) fun_val(b);
Sint diff;
diff = cmpbytes(atom_tab(atom_val(f1->fe->module))->name,
@@ -3398,29 +3388,29 @@ tailrecur_ne:
if (is_internal_pid(b)) {
bnode = erts_this_node;
bdata = internal_pid_data(b);
- } else if (is_external_pid_rel(b,b_base)) {
- bnode = external_pid_node_rel(b,b_base);
- bdata = external_pid_data_rel(b,b_base);
+ } else if (is_external_pid(b)) {
+ bnode = external_pid_node(b);
+ bdata = external_pid_data(b);
} else {
a_tag = EXTERNAL_PID_DEF;
goto mixed_types;
}
- anode = external_pid_node_rel(a,a_base);
- adata = external_pid_data_rel(a,a_base);
+ anode = external_pid_node(a);
+ adata = external_pid_data(a);
goto pid_common;
case (_TAG_HEADER_EXTERNAL_PORT >> _TAG_PRIMARY_SIZE):
if (is_internal_port(b)) {
bnode = erts_this_node;
bdata = internal_port_data(b);
- } else if (is_external_port_rel(b,b_base)) {
- bnode = external_port_node_rel(b,b_base);
- bdata = external_port_data_rel(b,b_base);
+ } else if (is_external_port(b)) {
+ bnode = external_port_node(b);
+ bdata = external_port_data(b);
} else {
a_tag = EXTERNAL_PORT_DEF;
goto mixed_types;
}
- anode = external_port_node_rel(a,a_base);
- adata = external_port_data_rel(a,a_base);
+ anode = external_port_node(a);
+ adata = external_port_data(a);
goto port_common;
case (_TAG_HEADER_REF >> _TAG_PRIMARY_SIZE):
/*
@@ -3428,14 +3418,13 @@ tailrecur_ne:
* (32-bit words), *not* ref data words.
*/
-
- if (is_internal_ref_rel(b,b_base)) {
- RefThing* bthing = ref_thing_ptr_rel(b,b_base);
+ if (is_internal_ref(b)) {
+ RefThing* bthing = ref_thing_ptr(b);
bnode = erts_this_node;
bnum = internal_thing_ref_numbers(bthing);
blen = internal_thing_ref_no_of_numbers(bthing);
- } else if(is_external_ref_rel(b,b_base)) {
- ExternalThing* bthing = external_thing_ptr_rel(b,b_base);
+ } else if(is_external_ref(b)) {
+ ExternalThing* bthing = external_thing_ptr(b);
bnode = bthing->node;
bnum = external_thing_ref_numbers(bthing);
blen = external_thing_ref_no_of_numbers(bthing);
@@ -3444,7 +3433,7 @@ tailrecur_ne:
goto mixed_types;
}
{
- RefThing* athing = ref_thing_ptr_rel(a,a_base);
+ RefThing* athing = ref_thing_ptr(a);
anode = erts_this_node;
anum = internal_thing_ref_numbers(athing);
alen = internal_thing_ref_no_of_numbers(athing);
@@ -3477,13 +3466,13 @@ tailrecur_ne:
RETURN_NEQ((Sint32) (anum[i] - bnum[i]));
goto pop_next;
case (_TAG_HEADER_EXTERNAL_REF >> _TAG_PRIMARY_SIZE):
- if (is_internal_ref_rel(b,b_base)) {
- RefThing* bthing = ref_thing_ptr_rel(b,b_base);
+ if (is_internal_ref(b)) {
+ RefThing* bthing = ref_thing_ptr(b);
bnode = erts_this_node;
bnum = internal_thing_ref_numbers(bthing);
blen = internal_thing_ref_no_of_numbers(bthing);
- } else if (is_external_ref_rel(b,b_base)) {
- ExternalThing* bthing = external_thing_ptr_rel(b,b_base);
+ } else if (is_external_ref(b)) {
+ ExternalThing* bthing = external_thing_ptr(b);
bnode = bthing->node;
bnum = external_thing_ref_numbers(bthing);
blen = external_thing_ref_no_of_numbers(bthing);
@@ -3492,7 +3481,7 @@ tailrecur_ne:
goto mixed_types;
}
{
- ExternalThing* athing = external_thing_ptr_rel(a,a_base);
+ ExternalThing* athing = external_thing_ptr(a);
anode = athing->node;
anum = external_thing_ref_numbers(athing);
alen = external_thing_ref_no_of_numbers(athing);
@@ -3500,13 +3489,13 @@ tailrecur_ne:
goto ref_common;
default:
/* Must be a binary */
- ASSERT(is_binary_rel(a,a_base));
- if (!is_binary_rel(b,b_base)) {
+ ASSERT(is_binary(a));
+ if (!is_binary(b)) {
a_tag = BINARY_DEF;
goto mixed_types;
} else {
- Uint a_size = binary_size_rel(a,a_base);
- Uint b_size = binary_size_rel(b,b_base);
+ Uint a_size = binary_size(a);
+ Uint b_size = binary_size(b);
Uint a_bitsize;
Uint b_bitsize;
Uint a_bitoffs;
@@ -3515,8 +3504,8 @@ tailrecur_ne:
int cmp;
byte* a_ptr;
byte* b_ptr;
- ERTS_GET_BINARY_BYTES_REL(a, a_ptr, a_bitoffs, a_bitsize, a_base);
- ERTS_GET_BINARY_BYTES_REL(b, b_ptr, b_bitoffs, b_bitsize, b_base);
+ ERTS_GET_BINARY_BYTES(a, a_ptr, a_bitoffs, a_bitsize);
+ ERTS_GET_BINARY_BYTES(b, b_ptr, b_bitoffs, b_bitsize);
if ((a_bitsize | b_bitsize | a_bitoffs | b_bitoffs) == 0) {
min_size = (a_size < b_size) ? a_size : b_size;
if ((cmp = sys_memcmp(a_ptr, b_ptr, min_size)) != 0) {
@@ -3547,13 +3536,8 @@ tailrecur_ne:
{
FloatDef f1, f2;
Eterm big;
-#if HALFWORD_HEAP
- Wterm aw = is_immed(a) ? a : rterm2wterm(a,a_base);
- Wterm bw = is_immed(b) ? b : rterm2wterm(b,b_base);
-#else
Eterm aw = a;
Eterm bw = b;
-#endif
#define MAX_LOSSLESS_FLOAT ((double)((1LL << 53) - 2))
#define MIN_LOSSLESS_FLOAT ((double)(((1LL << 53) - 2)*-1))
#define BIG_ARITY_FLOAT_MAX (1024 / D_EXP) /* arity of max float as a bignum */
@@ -3625,7 +3609,7 @@ tailrecur_ne:
}
} else {
big = double_to_big(f2.fd, big_buf, sizeof(big_buf)/sizeof(Eterm));
- j = big_comp(aw, rterm2wterm(big,big_buf));
+ j = big_comp(aw, big);
}
if (_NUMBER_CODE(a_tag, b_tag) == FLOAT_BIG) {
j = -j;
@@ -3673,9 +3657,9 @@ term_array: /* arrays in 'aa' and 'bb', length in 'i' */
while (--i) {
a = *aa++;
b = *bb++;
- if (!is_same(a,a_base, b,b_base)) {
+ if (!is_same(a, b)) {
if (is_atom(a) && is_atom(b)) {
- if ((j = cmp_atoms(a, b)) != 0) {
+ if ((j = erts_cmp_atoms(a, b)) != 0) {
goto not_equal;
}
} else if (is_both_small(a, b)) {
@@ -3946,11 +3930,11 @@ void bin_write(int to, void *to_arg, byte* buf, size_t sz)
/* Fill buf with the contents of bytelist list
return number of chars in list or -1 for error */
-int
-intlist_to_buf(Eterm list, char *buf, int len)
+Sint
+intlist_to_buf(Eterm list, char *buf, Sint len)
{
Eterm* listptr;
- int sz = 0;
+ Sint sz = 0;
if (is_nil(list))
return 0;
@@ -4365,7 +4349,7 @@ iolist_size(const int yield_support, ErtsIOListState *state, Eterm obj, ErlDrvSi
{
int res, init_yield_count, yield_count;
Eterm* objp;
- Uint size = (Uint) *sizep; /* Intentionally Uint due to halfword heap */
+ Uint size = (Uint) *sizep;
DECLARE_ESTACK(s);
if (!yield_support)
@@ -4497,11 +4481,12 @@ int erts_iolist_size(Eterm obj, ErlDrvSizeT* sizep)
return iolist_size(0, NULL, obj, sizep);
}
-/* return 0 if item is not a non-empty flat list of bytes */
-int
+/* return 0 if item is not a non-empty flat list of bytes
+ otherwise return the nonzero length of the list */
+Sint
is_string(Eterm list)
{
- int len = 0;
+ Sint len = 0;
while(is_list(list)) {
Eterm* consp = list_val(list);
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c
index 5e25747ddf..3088dfd572 100644
--- a/erts/emulator/drivers/common/efile_drv.c
+++ b/erts/emulator/drivers/common/efile_drv.c
@@ -101,15 +101,9 @@
# include "config.h"
#endif
-#ifndef __OSE__
#include <ctype.h>
#include <sys/types.h>
#include <stdlib.h>
-#else
-#include "ctype.h"
-#include "sys/types.h"
-#include "stdlib.h"
-#endif
/* Need (NON)BLOCKING macros for sendfile */
#ifndef WANT_NONBLOCKING
@@ -882,7 +876,7 @@ static void reply_Uint_posix_error(file_descriptor *desc, Uint num,
TRACE_C('N');
response[0] = FILE_RESP_NUMERR;
-#if SIZEOF_VOID_P == 4 || HALFWORD_HEAP
+#if SIZEOF_VOID_P == 4
put_int32(0, response+1);
#else
put_int32(num>>32, response+1);
@@ -951,7 +945,7 @@ static int reply_Uint(file_descriptor *desc, Uint result) {
TRACE_C('R');
tmp[0] = FILE_RESP_NUMBER;
-#if SIZEOF_VOID_P == 4 || HALFWORD_HEAP
+#if SIZEOF_VOID_P == 4
put_int32(0, tmp+1);
#else
put_int32(result>>32, tmp+1);
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 2d2bd80783..b219669ce5 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -94,10 +94,6 @@ typedef unsigned long long llu_t;
#define INT16_MAX (32767)
#endif
-#ifdef __OSE__
-#include "inet.h"
-#endif
-
#ifdef __WIN32__
#define STRNCASECMP strncasecmp
@@ -298,139 +294,7 @@ static unsigned long one_value = 1;
#define TCP_SHUT_RD SD_RECEIVE
#define TCP_SHUT_RDWR SD_BOTH
-#elif defined (__OSE__)
-
-/*
- * Some notes about how inet (currently only tcp) works on OSE.
- * The driver uses OSE signals to communicate with the one_inet
- * process. Because of the difference in how signals and file descriptors
- * work the whole select/deselect mechanic is very different.
- * In ose when a sock_select is done a function is called. That function
- * notes the changes that the driver want to do, but does not act on it.
- * later when the function returns the new desired state is compared
- * to the previous state and the apprioriate actions are taken. The action
- * is usually to either request more data from the stack or stop requesting
- * data.
- *
- * One thing to note is that the driver never does select/deselect. It always
- * listens for the signals. Flow of data is regulated by sending or not sending
- * signals to the ose inet process.
- *
- * The interesting functions to look at are:
- * * inet_driver_select : called when sock_select is called
- * * tcp_inet_ose_dispatch_signal : checks state changes and sends new signals
- * * tcp_inet_drv_output_ose : ready output callback, reads signals and calls
- * dispatch_signal
- * * tcp_inet_drv_input_ose : ready input callback.
- */
-
-#include "efs.h"
-#include "sys/socket.h"
-#include "sys/uio.h"
-#include "sfk/sys/sfk_uio.h"
-#include "netinet/in.h"
-#include "netinet/tcp.h"
-#include "netdb.h"
-#include "ose_spi/socket.sig"
-
-
-static ssize_t writev_fallback(int fd, const struct iovec *iov, int iovcnt, int max_sz);
-
-#define INVALID_SOCKET -1
-#define INVALID_EVENT -1
-#define SOCKET_ERROR -1
-
-#define SOCKET int
-#define HANDLE int
-#define FD_READ ERL_DRV_READ
-#define FD_WRITE ERL_DRV_WRITE
-#define FD_CLOSE 0
-#define FD_CONNECT (1<<4)
-#define FD_ACCEPT (1<<5)
-#define SOCK_FD_ERROR (1<<6)
-
-#define sock_connect(s, addr, len) connect((s), (addr), (len))
-#define sock_listen(s, b) listen((s), (b))
-#define sock_bind(s, addr, len) bind((s), (addr), (len))
-#define sock_getopt(s,t,n,v,l) getsockopt((s),(t),(n),(v),(l))
-#define sock_setopt(s,t,n,v,l) setsockopt((s),(t),(n),(v),(l))
-#define sock_name(s, addr, len) getsockname((s), (addr), (len))
-#define sock_peer(s, addr, len) getpeername((s), (addr), (len))
-#define sock_ntohs(x) ntohs((x))
-#define sock_ntohl(x) ntohl((x))
-#define sock_htons(x) htons((x))
-#define sock_htonl(x) htonl((x))
-
-#define sock_accept(s, addr, len) accept((s), (addr), (len))
-#define sock_send(s,buf,len,flag) inet_send((s),(buf),(len),(flag))
-#define sock_sendto(s,buf,blen,flag,addr,alen) \
- sendto((s),(buf),(blen),(flag),(addr),(alen))
-#define sock_sendv(s, vec, size, np, flag) \
- (*(np) = writev_fallback((s), (struct iovec*)(vec), (size), (*(np))))
-#define sock_sendmsg(s,msghdr,flag) sendmsg((s),(msghdr),(flag))
-
-#define sock_open(af, type, proto) socket((af), (type), (proto))
-#define sock_close(s) close((s))
-#define sock_dup(s) dup((s))
-#define sock_shutdown(s, how) shutdown((s), (how))
-
-#define sock_hostname(buf, len) gethostname((buf), (len))
-#define sock_getservbyname(name,proto) getservbyname((name), (proto))
-#define sock_getservbyport(port,proto) getservbyport((port), (proto))
-
-#define sock_recv(s,buf,len,flag) recv((s),(buf),(len),(flag))
-#define sock_recvfrom(s,buf,blen,flag,addr,alen) \
- recvfrom((s),(buf),(blen),(flag),(addr),(alen))
-#define sock_recvmsg(s,msghdr,flag) recvmsg((s),(msghdr),(flag))
-
-#define sock_errno() errno
-#define sock_create_event(d) ((d)->s) /* return file descriptor */
-#define sock_close_event(e) /* do nothing */
-
-#ifndef WANT_NONBLOCKING
-#define WANT_NONBLOCKING
-#endif
-#include "sys.h"
-
-typedef unsigned long u_long;
-#define IN_CLASSA(a) ((((in_addr_t)(a)) & 0x80000000) == 0)
-#define IN_CLASSA_NET 0xff000000
-#define IN_CLASSA_NSHIFT 24
-#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET)
-#define IN_CLASSA_MAX 128
-
-#define IN_CLASSB(a) ((((in_addr_t)(a)) & 0xc0000000) == 0x80000000)
-#define IN_CLASSB_NET 0xffff0000
-#define IN_CLASSB_NSHIFT 16
-#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET)
-#define IN_CLASSB_MAX 65536
-
-#define IN_CLASSC(a) ((((in_addr_t)(a)) & 0xe0000000) == 0xc0000000)
-#define IN_CLASSC_NET 0xffffff00
-#define IN_CLASSC_NSHIFT 8
-#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET)
-
-#define IN_CLASSD(a) ((((in_addr_t)(a)) & 0xf0000000) == 0xe0000000)
-#define IN_MULTICAST(a) IN_CLASSD(a)
-
-#define IN_EXPERIMENTAL(a) ((((in_addr_t)(a)) & 0xe0000000) == 0xe0000000)
-#define IN_BADCLASS(a) ((((in_addr_t)(a)) & 0xf0000000) == 0xf0000000)
-
-#define sock_select(d, flags, onoff) do { \
- ASSERT(!(d)->is_ignored); \
- (d)->event_mask = (onoff) ? \
- ((d)->event_mask | (flags)) : \
- ((d)->event_mask & ~(flags)); \
- DEBUGF(("(%s / %d) sock_select(%ld): flags=%02X, onoff=%d, event_mask=%02lX, s=%d\r\n", \
- __FILE__, __LINE__, (long) (d)->port, (flags), (onoff), (unsigned long) (d)->event_mask, (d)->s)); \
- inet_driver_select((d), (flags), (onoff)); \
- } while(0)
-
-#define TCP_SHUT_WR SHUT_WR
-#define TCP_SHUT_RD SHUT_RD
-#define TCP_SHUT_RDWR SHUT_RDWR
-
-#else /* !__OSE__ && !__WIN32__ */
+#else /* !__WIN32__ */
#include <sys/time.h>
#ifdef NETDB_H_NEEDS_IN_H
@@ -704,7 +568,7 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
#define TCP_SHUT_RD SHUT_RD
#define TCP_SHUT_RDWR SHUT_RDWR
-#endif /* !__WIN32__ && !__OSE__ */
+#endif /* !__WIN32__ */
#ifdef HAVE_SOCKLEN_T
# define SOCKLEN_T socklen_t
@@ -1168,13 +1032,6 @@ typedef struct {
char *netns; /* Socket network namespace name
as full file path */
#endif
-#ifdef __OSE__
- int select_state; /* state to keep track of whether we
- should trigger another read/write
- request at end of ready_input/output */
- ErlDrvEvent events[6];
-#endif
-
} inet_descriptor;
@@ -1190,10 +1047,8 @@ static void tcp_inet_stop(ErlDrvData);
static void tcp_inet_command(ErlDrvData, char*, ErlDrvSizeT);
static void tcp_inet_commandv(ErlDrvData, ErlIOVec*);
static void tcp_inet_flush(ErlDrvData drv_data);
-#ifndef __OSE__
static void tcp_inet_drv_input(ErlDrvData, ErlDrvEvent);
static void tcp_inet_drv_output(ErlDrvData data, ErlDrvEvent event);
-#endif
static ErlDrvData tcp_inet_start(ErlDrvPort, char* command);
static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData, unsigned int,
char*, ErlDrvSizeT, char**, ErlDrvSizeT);
@@ -1206,71 +1061,6 @@ static void tcp_inet_event(ErlDrvData, ErlDrvEvent);
static void find_dynamic_functions(void);
#endif
-#ifdef __OSE__
-/* The structure of the signal used for requesting asynchronous
- * notification from the stack. Under normal circumstances the network stack
- * shouldn't overwrite the value set in the fd field by the sender
- * of the request */
-struct OseAsyncSig {
- struct FmEvent event;
- int fd;
-};
-
-union SIGNAL {
- SIGSELECT signo;
- struct OseAsyncSig async;
-};
-
-static ErlDrvSSizeT tcp_inet_ctl_ose(ErlDrvData e, unsigned int cmd,
- char* buf, ErlDrvSizeT len,
- char** rbuf, ErlDrvSizeT rsize);
-static void tcp_inet_commandv_ose(ErlDrvData e, ErlIOVec* ev);
-static void tcp_inet_drv_output_ose(ErlDrvData data, ErlDrvEvent event);
-static void tcp_inet_drv_input_ose(ErlDrvData data, ErlDrvEvent event);
-static ErlDrvOseEventId inet_resolve_signal(union SIGNAL *sig);
-
-#ifdef INET_DRV_DEBUG
-
-static char *read_req = "SO_EVENT_READ_REQUEST";
-static char *read_rep = "SO_EVENT_READ_REPLY";
-static char *write_req = "SO_EVENT_WRITE_REQUEST";
-static char *write_rep = "SO_EVENT_WRITE_REPLY";
-static char *eof_req = "SO_EVENT_EOF_REQUEST";
-static char *eof_rep = "SO_EVENT_EOF_REPLY";
-static char *accept_req = "SO_EVENT_ACCEPT_REQUEST";
-static char *accept_rep = "SO_EVENT_ACCEPT_REPLY";
-static char *connect_req = "SO_EVENT_CONNECT_REQUEST";
-static char *connect_rep = "SO_EVENT_CONNECT_REPLY";
-static char *error_req = "SO_EVENT_ERROR_REQUEST";
-static char *error_rep = "SO_EVENT_ERROR_REPLY";
-static char signo_tmp[32];
-
-static char *signo_to_string(SIGSELECT signo) {
- switch (signo) {
- case SO_EVENT_READ_REQUEST: { return read_req; }
- case SO_EVENT_READ_REPLY: { return read_rep; }
- case SO_EVENT_WRITE_REQUEST: { return write_req; }
- case SO_EVENT_WRITE_REPLY: { return write_rep; }
- case SO_EVENT_EOF_REQUEST: { return eof_req; }
- case SO_EVENT_EOF_REPLY: { return eof_rep; }
- case SO_EVENT_ACCEPT_REQUEST: { return accept_req; }
- case SO_EVENT_ACCEPT_REPLY: { return accept_rep; }
- case SO_EVENT_CONNECT_REQUEST: { return connect_req; }
- case SO_EVENT_CONNECT_REPLY: { return connect_rep; }
- case SO_EVENT_ERROR_REQUEST: { return error_req; }
- case SO_EVENT_ERROR_REPLY: { return error_rep; }
- }
-
- snprintf(signo_tmp,32,"0x%x",signo);
-
- return signo_tmp;
-}
-
-#endif
-
-#endif /* __OSE__ */
-
-
static struct erl_drv_entry tcp_inet_driver_entry =
{
tcp_inet_init, /* inet_init will add this driver !! */
@@ -1280,9 +1070,6 @@ static struct erl_drv_entry tcp_inet_driver_entry =
#ifdef __WIN32__
tcp_inet_event,
NULL,
-#elif defined(__OSE__)
- tcp_inet_drv_input_ose, /*ready_input*/
- tcp_inet_drv_output_ose, /*ready_output*/
#else
tcp_inet_drv_input,
tcp_inet_drv_output,
@@ -1290,17 +1077,9 @@ static struct erl_drv_entry tcp_inet_driver_entry =
"tcp_inet",
NULL,
NULL,
-#ifdef __OSE__
- tcp_inet_ctl_ose,
-#else
tcp_inet_ctl,
-#endif
tcp_inet_timeout,
-#ifdef __OSE__
- tcp_inet_commandv_ose,
-#else
tcp_inet_commandv,
-#endif
NULL,
tcp_inet_flush,
NULL,
@@ -1452,14 +1231,6 @@ static int packet_inet_output(udp_descriptor* udesc, HANDLE event);
/* convert descriptor pointer to inet_descriptor pointer */
#define INETP(d) (&(d)->inet)
-#ifdef __OSE__
-static void inet_driver_select(inet_descriptor* desc,
- int flags, int onoff);
-static void tcp_inet_ose_dispatch_signals(tcp_descriptor *desc,
- int prev_select_state,
- union SIGNAL *sig);
-#endif
-
static int async_ref = 0; /* async reference id generator */
#define NEW_ASYNC_ID() ((async_ref++) & 0xffff)
@@ -4355,16 +4126,6 @@ static void desc_close(inet_descriptor* desc)
desc->forced_events = 0;
desc->send_would_block = 0;
#endif
-#ifdef __OSE__
- if (desc->events[0]) {
- driver_select(desc->port,desc->events[0],FD_READ|FD_WRITE|ERL_DRV_USE,0);
- driver_select(desc->port,desc->events[1],FD_READ|FD_WRITE|ERL_DRV_USE,0);
- driver_select(desc->port,desc->events[2],FD_READ|FD_WRITE|ERL_DRV_USE,0);
- driver_select(desc->port,desc->events[3],FD_READ|FD_WRITE|ERL_DRV_USE,0);
- driver_select(desc->port,desc->events[4],FD_READ|FD_WRITE|ERL_DRV_USE,0);
- driver_select(desc->port,desc->events[5],FD_READ|FD_WRITE|ERL_DRV_USE,0);
- }
-#else
/*
* We should close the fd here, but the other driver might still
* be selecting on it.
@@ -4374,7 +4135,6 @@ static void desc_close(inet_descriptor* desc)
ERL_DRV_USE, 0);
else
inet_stop_select((ErlDrvEvent)(long)desc->event,NULL);
-#endif
desc->event = INVALID_EVENT; /* closed by stop_select callback */
desc->s = INVALID_SOCKET;
desc->event_mask = 0;
@@ -4416,65 +4176,6 @@ static int erl_inet_close(inet_descriptor* desc)
return 0;
}
-#ifdef __OSE__
-static void inet_select_init(inet_descriptor* desc)
-{
- desc->events[0] =
- erl_drv_ose_event_alloc(SO_EVENT_READ_REPLY,
- desc->s,
- inet_resolve_signal,
- NULL);
- driver_select(desc->port, desc->events[0],
- ERL_DRV_READ|ERL_DRV_USE, 1);
-
- desc->events[1] =
- erl_drv_ose_event_alloc(SO_EVENT_EOF_REPLY,
- desc->s,
- inet_resolve_signal,
- NULL);
- driver_select(desc->port, desc->events[1],
- ERL_DRV_READ|ERL_DRV_USE, 1);
-
- desc->events[2] =
- erl_drv_ose_event_alloc(SO_EVENT_ACCEPT_REPLY,
- desc->s,
- inet_resolve_signal,
- NULL);
- driver_select(desc->port, desc->events[2],
- ERL_DRV_READ|ERL_DRV_USE, 1);
-
- /* trigger tcp_inet_input */
- desc->events[3] =
- erl_drv_ose_event_alloc(SO_EVENT_WRITE_REPLY,
- desc->s,
- inet_resolve_signal,
- NULL);
- driver_select(desc->port, desc->events[3],
- ERL_DRV_WRITE|ERL_DRV_USE, 1);
-
- desc->events[4] =
- erl_drv_ose_event_alloc(SO_EVENT_CONNECT_REPLY,
- desc->s,
- inet_resolve_signal,
- NULL);
- driver_select(desc->port, desc->events[4],
- ERL_DRV_WRITE|ERL_DRV_USE, 1);
-
- desc->events[5] =
- erl_drv_ose_event_alloc(SO_EVENT_ERROR_REPLY,
- desc->s,
- inet_resolve_signal,
- NULL);
- driver_select(desc->port, desc->events[5],
- ERL_DRV_WRITE|ERL_DRV_USE, 1);
-
- /* Issue a select on error event before any other select to be sure we are
- prepared to receive error notifications from the stack, even in the
- situations when select isn't issued */
- sock_select(desc, SOCK_FD_ERROR, 1);
-}
-#endif
-
static ErlDrvSSizeT inet_ctl_open(inet_descriptor* desc, int domain, int type,
char** rbuf, ErlDrvSizeT rsize)
{
@@ -4557,9 +4258,6 @@ static ErlDrvSSizeT inet_ctl_open(inet_descriptor* desc, int domain, int type,
#ifdef __WIN32__
driver_select(desc->port, desc->event, ERL_DRV_READ, 1);
#endif
-#ifdef __OSE__
- inet_select_init(desc);
-#endif
desc->state = INET_STATE_OPEN;
desc->stype = type;
@@ -4583,13 +4281,7 @@ static ErlDrvSSizeT inet_ctl_fdopen(inet_descriptor* desc, int domain, int type,
if (name.sa.sa_family != domain)
return ctl_error(EINVAL, rbuf, rsize);
}
-#ifdef __OSE__
- /* for fdopen duplicating the sd will allow to uniquely identify
- the signal from OSE with erlang port */
- desc->s = sock_dup(s);
-#else
desc->s = s;
-#endif
if ((desc->event = sock_create_event(desc)) == INVALID_EVENT)
return ctl_error(sock_errno(), rbuf, rsize);
@@ -4607,12 +4299,6 @@ static ErlDrvSSizeT inet_ctl_fdopen(inet_descriptor* desc, int domain, int type,
sz = sizeof(name);
if (!IS_SOCKET_ERROR(sock_peer(s, (struct sockaddr*) &name, &sz))) {
desc->state = INET_STATE_CONNECTED;
-#ifdef __OSE__
- /* since we are dealing with different descriptors (i.e. inet and
- socket) the select part should be initialized with the right
- values */
- inet_select_init(desc);
-#endif
}
}
@@ -8414,15 +8100,6 @@ static ErlDrvData inet_start(ErlDrvPort port, int size, int protocol)
#ifdef HAVE_SETNS
desc->netns = NULL;
#endif
-#ifdef __OSE__
- desc->select_state = 0;
- desc->events[0] = NULL;
- desc->events[1] = NULL;
- desc->events[2] = NULL;
- desc->events[3] = NULL;
- desc->events[4] = NULL;
- desc->events[5] = NULL;
-#endif
return (ErlDrvData)desc;
}
@@ -9149,10 +8826,6 @@ static tcp_descriptor* tcp_inet_copy(tcp_descriptor* desc,SOCKET s,
copy_desc->inet.port = port;
copy_desc->inet.dport = driver_mk_port(port);
-#ifdef __OSE__
- inet_select_init(&copy_desc->inet);
-#endif
-
*err = 0;
return copy_desc;
}
@@ -9214,23 +8887,6 @@ static void tcp_inet_stop(ErlDrvData e)
inet_stop(INETP(desc));
}
-#ifdef __OSE__
-
-static ErlDrvSSizeT tcp_inet_ctl_ose(ErlDrvData e, unsigned int cmd,
- char* buf, ErlDrvSizeT len,
- char** rbuf, ErlDrvSizeT rsize) {
-
- tcp_descriptor* desc = (tcp_descriptor*)e;
- int prev_select_state = INETP(desc)->select_state;
-
- ErlDrvSSizeT res = tcp_inet_ctl(e,cmd,buf,len,rbuf,rsize);
-
- tcp_inet_ose_dispatch_signals((tcp_descriptor*)e,prev_select_state,NULL);
-
- return res;
-}
-#endif
-
/* TCP requests from Erlang */
static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
char* buf, ErlDrvSizeT len,
@@ -9672,17 +9328,6 @@ static void tcp_inet_command(ErlDrvData e, char *buf, ErlDrvSizeT len)
DEBUGF(("tcp_inet_command(%ld) }\r\n", (long)desc->inet.port));
}
-#ifdef __OSE__
-
-static void tcp_inet_commandv_ose(ErlDrvData e, ErlIOVec* ev) {
- int prev_select_state = INETP((tcp_descriptor*)e)->select_state;
- tcp_inet_commandv(e, ev);
- tcp_inet_ose_dispatch_signals((tcp_descriptor*)e,prev_select_state,NULL);
-}
-
-#endif
-
-
static void tcp_inet_commandv(ErlDrvData e, ErlIOVec* ev)
{
tcp_descriptor* desc = (tcp_descriptor*)e;
@@ -9755,22 +9400,6 @@ static void inet_stop_select(ErlDrvEvent event, void* _)
{
#ifdef __WIN32__
WSACloseEvent((HANDLE)event);
-#elif defined(__OSE__)
- ErlDrvOseEventId id;
- union SIGNAL *sig;
- erl_drv_ose_event_fetch(event, NULL, &id,NULL);
- DEBUGF(("inet_stop_select(?#?) {s=%d\n",id));
- sock_close((int)id);
- /* On socket close all the signals waiting to be processed as part of the
- select should be deallocated */
- while((sig = erl_drv_ose_get_signal(event))) {
- DEBUGF(("inet_stop_select(?#?): Freeing signal %s\n",
- signo_to_string(sig->signo)));
- free_buf(&sig);
- }
- erl_drv_ose_event_free(event);
- DEBUGF(("inet_stop_select(?#?) }\n"));
-
#else
sock_close((SOCKET)(long)event);
#endif
@@ -10319,146 +9948,7 @@ static void tcp_inet_event(ErlDrvData e, ErlDrvEvent event)
return;
}
-#elif defined(__OSE__) /* !__WIN32__ */
-/* The specific resolve signal function. It will return the socket descriptor
- for which the select was issued */
-static ErlDrvOseEventId inet_resolve_signal(union SIGNAL *sig) {
- DEBUGF(("%s(?#?): s=%d got signal %s, status = %d, extra = %d, sender = 0x%x\n",
- __FUNCTION__,sig->async.fd,signo_to_string(sig->signo),
- sig->async.event.status,
- sig->async.event.extra,sender(&sig)));
- if (sig->signo == SO_EVENT_READ_REPLY ||
- sig->signo == SO_EVENT_ACCEPT_REPLY ||
- sig->signo == SO_EVENT_EOF_REPLY ||
- sig->signo == SO_EVENT_WRITE_REPLY ||
- sig->signo == SO_EVENT_ERROR_REPLY ||
- sig->signo == SO_EVENT_CONNECT_REPLY ) {
- return sig->async.fd;
- }
-
- return -1;
-}
-
-static void inet_driver_select(inet_descriptor* desc,
- int flags, int onoff) {
- ASSERT(!desc->is_ignored);
-
- if(onoff) {
- desc->select_state |= flags;
- } else {
- desc->select_state &= ~flags;
- }
-}
-
-static ssize_t writev_fallback(int fd, const struct iovec *iov, int iovcnt, int max_sz)
-{
- size_t data_len = 0;
- size_t sent = 0;
- ssize_t n;
- int i;
-
- for(i = 0; i < iovcnt; i++)
- {
- data_len = iov[i].iov_len;
-tryagain:
- n = sock_send(fd, iov[i].iov_base, data_len, 0);
- if (IS_SOCKET_ERROR(n)) {
- /* If buffer length is greater than the amount stack is able to
- * send out then try to send at least max_sz (this comes with
- * SO_EVENT_WRITE_REPLY signal*/
- if ((errno == EMSGSIZE) && (max_sz > 0) && (data_len > max_sz)) {
- data_len = max_sz;
- goto tryagain;
- }
- break;
- }
- sent += n;
- }
- return sent;
-}
-
-#define OSE_EVENT_REQ(TCP_DESC,EVENT) do { \
- union SIGNAL *sig = alloc(sizeof(struct OseAsyncSig), EVENT); \
- sig->async.fd = INETP(TCP_DESC)->s; \
- ose_request_event(INETP(TCP_DESC)->s, &sig, 1); \
- DEBUGF(("%s(%ld): s=%d sent %s\r\n",__FUNCTION__, \
- INETP(TCP_DESC)->port,INETP(TCP_DESC)->s,signo_to_string(EVENT))); \
- } while(0)
-
-static void tcp_inet_ose_dispatch_signals(tcp_descriptor *desc,
- int prev_select_state,
- union SIGNAL *sig) {
- if (sig) {
- DEBUGF(("tcp_inet_ose_dispatch_signals(%ld) {s=%d resend\r\n",
- (long)INETP(desc)->port,INETP(desc)->s));
- /* We are reacting to a signal, which means that if
- the select_state for that signal is still activated
- we should send a new signal */
- switch (sig->signo) {
- case SO_EVENT_READ_REPLY: {
- if (INETP(desc)->select_state & FD_READ)
- OSE_EVENT_REQ(desc,SO_EVENT_READ_REQUEST);
- break;
- }
- case SO_EVENT_WRITE_REPLY: {
- if (INETP(desc)->select_state & FD_WRITE)
- OSE_EVENT_REQ(desc,SO_EVENT_WRITE_REQUEST);
- break;
- }
- case SO_EVENT_CONNECT_REPLY: {
- if (INETP(desc)->select_state & FD_CONNECT)
- OSE_EVENT_REQ(desc,SO_EVENT_CONNECT_REQUEST);
- break;
- }
- case SO_EVENT_ACCEPT_REPLY: {
- if (INETP(desc)->select_state & FD_ACCEPT)
- OSE_EVENT_REQ(desc,SO_EVENT_ACCEPT_REQUEST);
- break;
- }
- case SO_EVENT_ERROR_REPLY: {
- if (INETP(desc)->select_state & SOCK_FD_ERROR)
- OSE_EVENT_REQ(desc,SO_EVENT_ERROR_REQUEST);
- break;
- }
-
- }
- DEBUGF(("tcp_inet_ose_dispatch_signals(%ld) }\r\n",
- (long)INETP(desc)->port));
- }
-
- if (INETP(desc)->select_state != prev_select_state) {
- /* If the select state has changed we have to issue signals for
- the state parts that have changed. */
- int xor_select_state = INETP(desc)->select_state ^ prev_select_state;
- DEBUGF(("tcp_inet_ose_dispatch_signals(%ld) {s=%d select change\r\n",
- (long)INETP(desc)->port,INETP(desc)->s));
- if ((xor_select_state & FD_READ) &&
- (INETP(desc)->select_state & FD_READ)) {
- OSE_EVENT_REQ(desc,SO_EVENT_READ_REQUEST);
- }
- if ((xor_select_state & FD_WRITE) &&
- (INETP(desc)->select_state & FD_WRITE)) {
- OSE_EVENT_REQ(desc,SO_EVENT_WRITE_REQUEST);
- }
- if ((xor_select_state & FD_CONNECT) &&
- (INETP(desc)->select_state & FD_CONNECT)) {
- OSE_EVENT_REQ(desc,SO_EVENT_CONNECT_REQUEST);
- }
- if ((xor_select_state & FD_ACCEPT) &&
- (INETP(desc)->select_state & FD_ACCEPT)) {
- OSE_EVENT_REQ(desc,SO_EVENT_ACCEPT_REQUEST);
- }
- if ((xor_select_state & SOCK_FD_ERROR) &&
- (INETP(desc)->select_state & SOCK_FD_ERROR)) {
- OSE_EVENT_REQ(desc,SO_EVENT_ERROR_REQUEST);
- }
-
- DEBUGF(("tcp_inet_ose_dispatch_signals(%ld) }\r\n",
- (long)INETP(desc)->port));
- }
-}
-
-#endif /* __OSE__ */
+#endif /* __WIN32__ */
/* socket has input:
@@ -10945,49 +10435,6 @@ static void tcp_shutdown_async(tcp_descriptor* desc)
desc->tcp_add_flags |= TCP_ADDF_SHUTDOWN_WR_DONE;
}
-#ifdef __OSE__
-
-static void tcp_inet_drv_output_ose(ErlDrvData data, ErlDrvEvent event)
-{
- union SIGNAL *event_sig = erl_drv_ose_get_signal(event);
-
- while (event_sig) {
- int prev_select_state = INETP((tcp_descriptor*)data)->select_state;
- int res = tcp_inet_output((tcp_descriptor*)data, (HANDLE)event_sig);
- if (res != -1) {
- tcp_inet_ose_dispatch_signals((tcp_descriptor*)data,
- prev_select_state,event_sig);
- free_buf(&event_sig);
- event_sig = erl_drv_ose_get_signal(event);
- } else {
- /* NOTE: here the event object could have been deallocated!!!!
- inet_stop_select is called when doing driver_select(ERL_DRV_USE,0)
- */
- free_buf(&event_sig);
- return;
- }
- }
-}
-
-static void tcp_inet_drv_input_ose(ErlDrvData data, ErlDrvEvent event)
-{
- union SIGNAL *event_sig = erl_drv_ose_get_signal(event);
-
- while (event_sig) {
- int prev_select_state = INETP((tcp_descriptor*)data)->select_state;
- int res = tcp_inet_input((tcp_descriptor*)data, (HANDLE)event);
- if (res != -1) {
- tcp_inet_ose_dispatch_signals((tcp_descriptor*)data, prev_select_state,
- event_sig);
- free_buf(&event_sig);
- event_sig = erl_drv_ose_get_signal(event);
- } else {
- free_buf(&event_sig);
- return;
- }
- }
-}
-#else
static void tcp_inet_drv_output(ErlDrvData data, ErlDrvEvent event)
{
(void)tcp_inet_output((tcp_descriptor*)data, (HANDLE)event);
@@ -10997,7 +10444,6 @@ static void tcp_inet_drv_input(ErlDrvData data, ErlDrvEvent event)
{
(void)tcp_inet_input((tcp_descriptor*)data, (HANDLE)event);
}
-#endif
/* socket ready for ouput:
** 1. INET_STATE_CONNECTING => non block connect ?
@@ -11063,13 +10509,6 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event)
ssize_t n;
SysIOVec* iov;
-#ifdef __OSE__
- /* For large size buffers case the amount of data that the stack is
- able to send out (received in the .extra field) should be passed
- down to writev_fallback */
- n = event ? ((union SIGNAL*)event)->async.event.extra : 0;
-#endif
-
if ((iov = driver_peekq(ix, &vsize)) == NULL) {
sock_select(INETP(desc), FD_WRITE, 0);
send_empty_out_q_msgs(INETP(desc));
@@ -11097,12 +10536,6 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event)
sizes > (max 32 bit signed int) */
size_t howmuch = 0x7FFFFFFF; /* max signed 32 bit */
int x;
-#ifdef __OSE__
- /* For EWOULDBLOCK sock_sendv returns 0 so we have to be sure it
- wasn't the case */
- if(sock_errno() == ERRNO_BLOCK)
- goto done;
-#endif
for(x = 0; x < vsize && iov[x].iov_len == 0; ++x)
;
if (x < vsize) {
diff --git a/erts/emulator/drivers/ose/ose_efile.c b/erts/emulator/drivers/ose/ose_efile.c
deleted file mode 100644
index c8337a95d5..0000000000
--- a/erts/emulator/drivers/ose/ose_efile.c
+++ /dev/null
@@ -1,1125 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1997-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%
- */
-/*
- * Purpose: Provides file and directory operations for OSE.
- */
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-#if defined(HAVE_POSIX_FALLOCATE) && !defined(__sun) && !defined(__sun__)
-#define _XOPEN_SOURCE 600
-#endif
-#if !defined(_GNU_SOURCE) && defined(HAVE_LINUX_FALLOC_H)
-#define _GNU_SOURCE
-#endif
-#include "sys.h"
-#include "erl_driver.h"
-#include "erl_efile.h"
-#if defined(DARWIN) || defined(HAVE_LINUX_FALLOC_H) || defined(HAVE_POSIX_FALLOCATE)
-#include "fcntl.h"
-#endif
-#include "ose.h"
-#include "unistd.h"
-#include "sys/stat.h"
-#include "dirent.h"
-#include "sys/time.h"
-#include "time.h"
-#include "assert.h"
-
-/* Find a definition of MAXIOV, that is used in the code later. */
-#if defined IOV_MAX
-#define MAXIOV IOV_MAX
-#elif defined UIO_MAXIOV
-#define MAXIOV UIO_MAXIOV
-#else
-#define MAXIOV 16
-#endif
-
-/*
- * Macros for testing file types.
- */
-
-#define ISDIR(st) (((st).st_mode & S_IFMT) == S_IFDIR)
-#define ISREG(st) (((st).st_mode & S_IFMT) == S_IFREG)
-#define ISDEV(st) \
- (((st).st_mode&S_IFMT) == S_IFCHR || ((st).st_mode&S_IFMT) == S_IFBLK)
-#define ISLNK(st) (((st).st_mode & S_IFLNK) == S_IFLNK)
-#ifdef NO_UMASK
-#define FILE_MODE 0644
-#define DIR_MODE 0755
-#else
-#define FILE_MODE 0666
-#define DIR_MODE 0777
-#endif
-
-#define IS_DOT_OR_DOTDOT(s) \
- (s[0] == '.' && (s[1] == '\0' || (s[1] == '.' && s[2] == '\0')))
-
-/*
- * Macros for handling local file descriptors
- * and mutexes.
- *
- * Handling of files like this is necessary because OSE
- * does not allow seeking after the end of a file. So
- * what we do it emulate this by keeping track of the size
- * of the file and where the file's positions is. If a
- * write happens after eof then we pad it.
- *
- * Given time this should be rewritten to get rid of the
- * mutex and use the port lock to protect the data. This
- * could be done be done by adapting the efile api for some
- * calls to allow some meta-data to be associated with the
- * open file.
- */
-
-#define L_FD_IS_VALID(fd_data) ((fd_data)->beyond_eof > 0)
-#define L_FD_INVALIDATE(fd_data) (fd_data)->beyond_eof = 0
-#define L_FD_CUR(fd_data) (fd_data)->pos
-#define L_FD_OFFS_BEYOND_EOF(fd_data, offs) \
- (((fd_data)->size > offs) ? 0 : 1)
-
-#define L_FD_FAIL -1
-#define L_FD_SUCCESS 1
-#define L_FD_PAD_SIZE 255
-
-struct fd_meta {
- ErlDrvMutex *meta_mtx;
- struct fd_data *fd_data_list;
-};
-
-struct fd_data {
- int fd;
- struct fd_data *next;
- struct fd_data *prev;
- int pos;
- int beyond_eof;
- size_t size;
-#ifdef DEBUG
- PROCESS owner;
-#endif
-};
-
-static int l_invalidate_local_fd(int fd);
-static int l_pad_file(struct fd_data *fd_data, off_t offset);
-static int check_error(int result, Efile_error* errInfo);
-static struct fd_data* l_new_fd(void);
-static int l_remove_local_fd(int fd);
-static struct fd_data* l_find_local_fd(int fd);
-static int l_update_local_fd(int fd, int pos, int size);
-
-static struct fd_meta* fdm = NULL;
-
-
-/***************************************************************************/
-
-static int
-l_remove_local_fd(int fd)
-{
- struct fd_data *fd_data;
- fd_data = l_find_local_fd(fd);
-
- if (fd_data == NULL) {
- return L_FD_FAIL;
- }
-#ifdef DEBUG
- assert(fd_data->owner == current_process());
-#endif
- erl_drv_mutex_lock(fdm->meta_mtx);
- /* head ? */
- if (fd_data == fdm->fd_data_list) {
- if (fd_data->next != NULL) {
- /* remove link to head */
- fd_data->next->prev = NULL;
- /* set new head */
- fdm->fd_data_list = fd_data->next;
- }
- else {
- /* head is lonely */
- fdm->fd_data_list = NULL;
- }
- }
- else { /* not head */
- if (fd_data->prev == NULL) {
- erl_drv_mutex_unlock(fdm->meta_mtx);
- return L_FD_FAIL;
- }
- else {
- if (fd_data->next != NULL) {
- fd_data->next->prev = fd_data->prev;
- fd_data->prev->next = fd_data->next;
- }
- else {
- fd_data->prev->next = NULL;
- }
- }
- }
-
- /* scramble values */
- fd_data->beyond_eof = -1;
- fd_data->next = NULL;
- fd_data->prev = NULL;
- fd_data->fd = -1;
-
- /* unlock and clean */
- driver_free(fd_data);
- erl_drv_mutex_unlock(fdm->meta_mtx);
-
- return L_FD_SUCCESS;
-}
-
-/***************************************************************************/
-
-static int
-l_invalidate_local_fd(int fd) {
- struct fd_data *fd_data;
-
- if ((fd_data = l_find_local_fd(fd)) == NULL) {
- return L_FD_FAIL;
- }
-
- fd_data->beyond_eof = 0;
- return L_FD_SUCCESS;
-}
-
-/****************************************************************************/
-
-static struct fd_data*
-l_find_local_fd(int fd) {
- struct fd_data *fd_data;
-
- fd_data = NULL;
- erl_drv_mutex_lock(fdm->meta_mtx);
- for (fd_data = fdm->fd_data_list; fd_data != NULL; ) {
- if (fd_data->fd == fd) {
-#ifdef DEBUG
- assert(fd_data->owner == current_process());
-#endif
- break;
- }
- fd_data = fd_data->next;
- }
- erl_drv_mutex_unlock(fdm->meta_mtx);
- return fd_data;
-}
-
-/***************************************************************************/
-
-static struct fd_data*
-l_new_fd(void) {
- struct fd_data *fd_data;
-
- fd_data = driver_alloc(sizeof(struct fd_data));
- if (fd_data == NULL) {
- return NULL;
- }
- erl_drv_mutex_lock(fdm->meta_mtx);
- if (fdm->fd_data_list == NULL) {
- fdm->fd_data_list = fd_data;
- fdm->fd_data_list->prev = NULL;
- fdm->fd_data_list->next = NULL;
- }
- else {
- fd_data->next = fdm->fd_data_list;
- fdm->fd_data_list = fd_data;
- fdm->fd_data_list->prev = NULL;
- }
-#ifdef DEBUG
- fd_data->owner = current_process();
-#endif
- erl_drv_mutex_unlock(fdm->meta_mtx);
- return fd_data;
-}
-
-/***************************************************************************/
-
-static int
-l_update_local_fd(int fd, int pos, int size) {
- struct fd_data *fd_data = NULL;
-
- fd_data = l_find_local_fd(fd);
- /* new fd to handle? */
- if (fd_data == NULL) {
- fd_data = l_new_fd();
- if (fd_data == NULL) {
- /* out of memory */
- return L_FD_FAIL;
- }
- }
- fd_data->size = size;
- fd_data->pos = pos;
- fd_data->fd = fd;
- fd_data->beyond_eof = 1;
-
- return L_FD_SUCCESS;
-}
-
-/***************************************************************************/
-
-static int
-l_pad_file(struct fd_data *fd_data, off_t offset) {
- int size_dif;
- int written = 0;
- int ret_val = L_FD_SUCCESS;
- char padding[L_FD_PAD_SIZE];
-
- size_dif = (offset - fd_data->size);
- memset(&padding, '\0', L_FD_PAD_SIZE);
-
- while (size_dif > 0) {
- written = write(fd_data->fd, padding,
- (size_dif < L_FD_PAD_SIZE) ?
- size_dif : L_FD_PAD_SIZE);
- if (written < 0 && errno != EINTR && errno != EAGAIN) {
- ret_val = -1;
- break;
- }
- size_dif -= written;
- }
- L_FD_INVALIDATE(fd_data);
- return ret_val;
-}
-
-/***************************************************************************/
-
-static int
-check_error(int result, Efile_error *errInfo) {
- if (result < 0) {
- errInfo->posix_errno = errInfo->os_errno = errno;
- return 0;
- }
- return 1;
-}
-
-/***************************************************************************/
-
-int
-efile_init() {
- fdm = driver_alloc(sizeof(struct fd_meta));
- if (fdm == NULL) {
- return L_FD_FAIL;
- }
- fdm->meta_mtx = erl_drv_mutex_create("ose_efile local fd mutex\n");
- erl_drv_mutex_lock(fdm->meta_mtx);
- fdm->fd_data_list = NULL;
- erl_drv_mutex_unlock(fdm->meta_mtx);
- return L_FD_SUCCESS;
-}
-
-/***************************************************************************/
-
-int
-efile_mkdir(Efile_error* errInfo, /* Where to return error codes. */
- char* name) /* Name of directory to create. */
-{
-#ifdef NO_MKDIR_MODE
- return check_error(mkdir(name), errInfo);
-#else
- int res = mkdir(name, DIR_MODE);
- if (res < 0 && errno == EINVAL) {
- errno = ENOENT;
- }
- return check_error(res, errInfo);
-#endif
-}
-
-/***************************************************************************/
-
-int
-efile_rmdir(Efile_error* errInfo, /* Where to return error codes. */
- char* name) /* Name of directory to delete. */
-{
- if (rmdir(name) == 0) {
- return 1;
- }
- if (errno == ENOTEMPTY) {
- errno = EEXIST;
- }
- if (errno == EEXIST || errno == EINVAL) {
- int saved_errno = errno;
- struct stat file_stat;
- struct stat cwd_stat;
-
- if(stat(name, &file_stat) != 0) {
- errno = ENOENT;
- return check_error(-1, errInfo);
- }
- /*
- * The error code might be wrong if this is the current directory.
- */
- if (stat(name, &file_stat) == 0 && stat(".", &cwd_stat) == 0 &&
- file_stat.st_ino == cwd_stat.st_ino &&
- file_stat.st_dev == cwd_stat.st_dev) {
- saved_errno = EACCES;
- }
- errno = saved_errno;
- }
- return check_error(-1, errInfo);
-}
-
-/***************************************************************************/
-
-int
-efile_delete_file(Efile_error* errInfo, /* Where to return error codes. */
- char* name) /* Name of file to delete. */
-{
- struct stat statbuf;
-
- if (stat(name, &statbuf) >= 0) {
- /* Do not let unlink() remove directories */
- if (ISDIR(statbuf)) {
- errno = EPERM;
- return check_error(-1, errInfo);
- }
-
- if (unlink(name) == 0) {
- return 1;
- }
-
- if (errno == EISDIR) {
- errno = EPERM;
- return check_error(-1, errInfo);
- }
- }
- else {
- if (errno == EINVAL) {
- errno = ENOENT;
- return check_error(-1, errInfo);
- }
- }
- return check_error(-1, errInfo);
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * Changes the name of an existing file or directory, from src to dst.
- * If src and dst refer to the same file or directory, does nothing
- * and returns success. Otherwise if dst already exists, it will be
- * deleted and replaced by src subject to the following conditions:
- * If src is a directory, dst may be an empty directory.
- * If src is a file, dst may be a file.
- * In any other situation where dst already exists, the rename will
- * fail.
- *
- * Results:
- * If the directory was successfully created, returns 1.
- * Otherwise the return value is 0 and errno is set to
- * indicate the error. Some possible values for errno are:
- *
- * EACCES: src or dst parent directory can't be read and/or written.
- * EEXIST: dst is a non-empty directory.
- * EINVAL: src is a root directory or dst is a subdirectory of src.
- * EISDIR: dst is a directory, but src is not.
- * ENOENT: src doesn't exist, or src or dst is "".
- * ENOTDIR: src is a directory, but dst is not.
- * EXDEV: src and dst are on different filesystems.
- *
- * Side effects:
- * The implementation of rename may allow cross-filesystem renames,
- * but the caller should be prepared to emulate it with copy and
- * delete if errno is EXDEV.
- *
- *---------------------------------------------------------------------------
- */
-
-int
-efile_rename(Efile_error* errInfo, /* Where to return error codes. */
- char* src, /* Original name. */
- char* dst) /* New name. */
-{
-
- /* temporary fix AFM does not recognize ./<file name>
- * in destination remove pending on adaption of AFM fix
- */
-
- char *dot_str;
- if (dst != NULL) {
- dot_str = strchr(dst, '.');
- if (dot_str && dot_str == dst && dot_str[1] == '/') {
- dst = dst+2;
- }
- }
-
- if (rename(src, dst) == 0) {
- return 1;
- }
- if (errno == ENOTEMPTY) {
- errno = EEXIST;
- }
- if (errno == EINVAL) {
- struct stat file_stat;
-
- if (stat(dst, &file_stat)== 0) {
- if (ISDIR(file_stat)) {
- errno = EISDIR;
- }
- else if (ISREG(file_stat)) {
- errno = ENOTDIR;
- }
- else {
- errno = EINVAL;
- }
- }
- else {
- errno = EINVAL;
- }
- }
-
- if (strcmp(src, "/") == 0) {
- errno = EINVAL;
- }
- return check_error(-1, errInfo);
-}
-
-/***************************************************************************/
-
-int
-efile_chdir(Efile_error* errInfo, /* Where to return error codes. */
- char* name) /* Name of directory to make current. */
-{
- return check_error(chdir(name), errInfo);
-}
-
-/***************************************************************************/
-
-int
-efile_getdcwd(Efile_error* errInfo, /* Where to return error codes. */
- int drive, /* 0 - current, 1 - A, 2 - B etc. */
- char* buffer, /* Where to return the current
- directory. */
- size_t size) /* Size of buffer. */
-{
- if (drive == 0) {
- if (getcwd(buffer, size) == NULL)
- return check_error(-1, errInfo);
-
- return 1;
- }
-
- /*
- * Drives other than 0 is not supported on Unix.
- */
-
- errno = ENOTSUP;
- return check_error(-1, errInfo);
-}
-
-/***************************************************************************/
-
-int
-efile_readdir(Efile_error* errInfo, /* Where to return error codes. */
- char* name, /* Name of directory to open. */
- EFILE_DIR_HANDLE* p_dir_handle, /* Pointer to directory
- handle of
- open directory.*/
- char* buffer, /* Pointer to buffer for
- one filename. */
- size_t *size) /* in-out Size of buffer, length
- of name. */
-{
- DIR *dp; /* Pointer to directory structure. */
- struct dirent* dirp; /* Pointer to directory entry. */
-
- /*
- * If this is the first call, we must open the directory.
- */
-
- if (*p_dir_handle == NULL) {
- dp = opendir(name);
- if (dp == NULL)
- return check_error(-1, errInfo);
- *p_dir_handle = (EFILE_DIR_HANDLE) dp;
- }
-
- /*
- * Retrieve the name of the next file using the directory handle.
- */
-
- dp = *((DIR **)((void *)p_dir_handle));
- for (;;) {
- dirp = readdir(dp);
- if (dirp == NULL) {
- closedir(dp);
- return 0;
- }
- if (IS_DOT_OR_DOTDOT(dirp->d_name))
- continue;
- buffer[0] = '\0';
- strncat(buffer, dirp->d_name, (*size)-1);
- *size = strlen(dirp->d_name);
- return 1;
- }
-}
-
-/***************************************************************************/
-
-int
-efile_openfile(Efile_error* errInfo, /* Where to return error codes. */
- char* name, /* Name of directory to open. */
- int flags, /* Flags to user for opening. */
- int* pfd, /* Where to store the file
- descriptor. */
- Sint64 *pSize) /* Where to store the size of the
- file. */
-{
- struct stat statbuf;
- int fd;
- int mode; /* Open mode. */
-
- if (stat(name, &statbuf) >= 0 && !ISREG(statbuf)) {
- errno = EISDIR;
- return check_error(-1, errInfo);
- }
-
- switch (flags & (EFILE_MODE_READ|EFILE_MODE_WRITE)) {
- case EFILE_MODE_READ:
- mode = O_RDONLY;
- break;
- case EFILE_MODE_WRITE:
- if (flags & EFILE_NO_TRUNCATE)
- mode = O_WRONLY | O_CREAT;
- else
- mode = O_WRONLY | O_CREAT | O_TRUNC;
- break;
- case EFILE_MODE_READ_WRITE:
- mode = O_RDWR | O_CREAT;
- break;
- default:
- errno = EINVAL;
- return check_error(-1, errInfo);
- }
-
-
- if (flags & EFILE_MODE_APPEND) {
- mode &= ~O_TRUNC;
- mode |= O_APPEND;
- }
-
- if (flags & EFILE_MODE_EXCL) {
- mode |= O_EXCL;
- }
-
- fd = open(name, mode, FILE_MODE);
-
- if (!check_error(fd, errInfo))
- return 0;
-
- *pfd = fd;
- if (pSize) {
- *pSize = statbuf.st_size;
- }
- return 1;
-}
-
-/***************************************************************************/
-
-int
-efile_may_openfile(Efile_error* errInfo, char *name) {
- struct stat statbuf; /* Information about the file */
- int result;
-
- result = stat(name, &statbuf);
- if (!check_error(result, errInfo))
- return 0;
- if (!ISREG(statbuf)) {
- errno = EISDIR;
- return check_error(-1, errInfo);
- }
- return 1;
-}
-
-/***************************************************************************/
-
-void
-efile_closefile(int fd)
-{
- if (l_find_local_fd(fd) != NULL) {
- l_remove_local_fd(fd);
- }
- close(fd);
-}
-
-/***************************************************************************/
-
-int
-efile_fdatasync(Efile_error *errInfo, /* Where to return error codes. */
- int fd) /* File descriptor for file to sync data. */
-{
- return efile_fsync(errInfo, fd);
-}
-
-/***************************************************************************/
-
-int
-efile_fsync(Efile_error *errInfo, /* Where to return error codes. */
- int fd) /* File descriptor for file to sync. */
-{
- return check_error(fsync(fd), errInfo);
-}
-
-/***************************************************************************/
-
-int
-efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo,
- char* name, int info_for_link)
-{
- struct stat statbuf; /* Information about the file */
- int result;
-
- result = stat(name, &statbuf);
- if (!check_error(result, errInfo)) {
- return 0;
- }
-
-#if SIZEOF_OFF_T == 4
- pInfo->size_high = 0;
-#else
- pInfo->size_high = (Uint32)(statbuf.st_size >> 32);
-#endif
- pInfo->size_low = (Uint32)statbuf.st_size;
-
-#ifdef NO_ACCESS
- /* Just look at read/write access for owner. */
-
- pInfo->access = ((statbuf.st_mode >> 6) & 07) >> 1;
-
-#else
- pInfo->access = FA_NONE;
- if (access(name, R_OK) == 0)
- pInfo->access |= FA_READ;
- if (access(name, W_OK) == 0)
- pInfo->access |= FA_WRITE;
-
-#endif
-
- if (ISDEV(statbuf))
- pInfo->type = FT_DEVICE;
- else if (ISDIR(statbuf))
- pInfo->type = FT_DIRECTORY;
- else if (ISREG(statbuf))
- pInfo->type = FT_REGULAR;
- else if (ISLNK(statbuf))
- pInfo->type = FT_SYMLINK;
- else
- pInfo->type = FT_OTHER;
-
- pInfo->accessTime = statbuf.st_atime;
- pInfo->modifyTime = statbuf.st_mtime;
- pInfo->cTime = statbuf.st_ctime;
-
- pInfo->mode = statbuf.st_mode;
- pInfo->links = statbuf.st_nlink;
- pInfo->major_device = statbuf.st_dev;
- pInfo->inode = statbuf.st_ino;
- pInfo->uid = statbuf.st_uid;
- pInfo->gid = statbuf.st_gid;
-
- return 1;
-}
-
-/***************************************************************************/
-
-int
-efile_write_info(Efile_error *errInfo, Efile_info *pInfo, char *name)
-{
- /*
- * On some systems chown will always fail for a non-root user unless
- * POSIX_CHOWN_RESTRICTED is not set. Others will succeed as long as
- * you don't try to chown a file to someone besides youself.
- */
- if (pInfo->mode != -1) {
- mode_t newMode = pInfo->mode & (S_ISUID | S_ISGID |
- S_IRWXU | S_IRWXG | S_IRWXO);
- if (chmod(name, newMode)) {
- newMode &= ~(S_ISUID | S_ISGID);
- if (chmod(name, newMode)) {
- return check_error(-1, errInfo);
- }
- }
- }
-
- return 1;
-}
-
-/***************************************************************************/
-
-int
-efile_write(Efile_error* errInfo, /* Where to return error codes. */
- int flags, /* Flags given when file was
- opened. */
- int fd, /* File descriptor to write to. */
- char* buf, /* Buffer to write. */
- size_t count) /* Number of bytes to write. */
-{
- ssize_t written; /* Bytes written in last operation. */
- struct fd_data *fd_data;
-
- if ((fd_data = l_find_local_fd(fd)) != NULL) {
- if (L_FD_IS_VALID(fd_data)) {
- /* we are beyond eof and need to pad*/
- if (l_pad_file(fd_data, L_FD_CUR(fd_data)) < 0) {
- return check_error(-1, errInfo);
- }
- }
- }
-
- while (count > 0) {
- if ((written = write(fd, buf, count)) < 0) {
- if (errno != EINTR) {
- return check_error(-1, errInfo);
- }
- else {
- written = 0;
- }
- }
- ASSERT(written <= count);
- buf += written;
- count -= written;
- }
- return 1;
-}
-
-/***************************************************************************/
-
-int
-efile_writev(Efile_error* errInfo, /* Where to return error codes */
- int flags, /* Flags given when file was
- * opened */
- int fd, /* File descriptor to write to */
- SysIOVec* iov, /* Vector of buffer structs.
- * The structs may be changed i.e.
- * due to incomplete writes */
- int iovcnt) /* Number of structs in vector */
-{
- struct fd_data *fd_data;
- int cnt = 0; /* Buffers so far written */
-
- ASSERT(iovcnt >= 0);
- if ((fd_data = l_find_local_fd(fd)) != NULL) {
- if (L_FD_IS_VALID(fd_data)) {
- /* we are beyond eof and need to pad*/
- if (l_pad_file(fd_data, L_FD_CUR(fd_data)) < 0) {
- return check_error(-1, errInfo);
- }
- }
- }
- while (cnt < iovcnt) {
- if ((! iov[cnt].iov_base) || (iov[cnt].iov_len <= 0)) {
- /* Empty buffer - skip */
- cnt++;
- }
- else { /* Non-empty buffer */
- ssize_t w; /* Bytes written in this call */
- do {
- w = write(fd, iov[cnt].iov_base, iov[cnt].iov_len);
- } while (w < 0 && errno == EINTR);
-
- ASSERT(w <= iov[cnt].iov_len || w == -1);
-
- if (w < 0) {
- return check_error(-1, errInfo);
- }
- /* Move forward to next buffer to write */
- for (; cnt < iovcnt && w > 0; cnt++) {
- if (iov[cnt].iov_base && iov[cnt].iov_len > 0) {
- if (w < iov[cnt].iov_len) {
- /* Adjust the buffer for next write */
- iov[cnt].iov_len -= w;
- iov[cnt].iov_base += w;
- w = 0;
- break;
- }
- else {
- w -= iov[cnt].iov_len;
- }
- }
- }
- ASSERT(w == 0);
- } /* else Non-empty buffer */
- } /* while (cnt< iovcnt) */
- return 1;
-}
-
-/***************************************************************************/
-
-int
-efile_read(Efile_error* errInfo, /* Where to return error codes. */
- int flags, /* Flags given when file was opened. */
- int fd, /* File descriptor to read from. */
- char* buf, /* Buffer to read into. */
- size_t count, /* Number of bytes to read. */
- size_t *pBytesRead) /* Where to return number of
- bytes read. */
-{
- ssize_t n;
- struct fd_data *fd_data;
-
- if ((fd_data = l_find_local_fd(fd)) != NULL) {
- if (L_FD_IS_VALID(fd_data)) {
- *pBytesRead = 0;
- return 1;
- }
- }
- for (;;) {
- if ((n = read(fd, buf, count)) >= 0) {
- break;
- }
- else if (errno != EINTR) {
- return check_error(-1, errInfo);
- }
- }
- if (fd_data != NULL && L_FD_IS_VALID(fd_data)) {
- L_FD_INVALIDATE(fd_data);
- }
- *pBytesRead = (size_t) n;
- return 1;
-}
-
-/* pread() and pwrite() */
-/* Some unix systems, notably Solaris has these syscalls */
-/* It is especially nice for i.e. the dets module to have support */
-/* for this, even if the underlying OS dosn't support it, it is */
-/* reasonably easy to work around by first calling seek, and then */
-/* calling read(). */
-/* This later strategy however changes the file pointer, which pread() */
-/* does not do. We choose to ignore this and say that the location */
-/* of the file pointer is undefined after a call to any of the p functions*/
-
-
-int
-efile_pread(Efile_error* errInfo, /* Where to return error codes. */
- int fd, /* File descriptor to read from. */
- Sint64 offset, /* Offset in bytes from BOF. */
- char* buf, /* Buffer to read into. */
- size_t count, /* Number of bytes to read. */
- size_t *pBytesRead) /* Where to return
- number of bytes read. */
-{
- int res = efile_seek(errInfo, fd, offset, EFILE_SEEK_SET, NULL);
- if (res) {
- return efile_read(errInfo, 0, fd, buf, count, pBytesRead);
- } else {
- return res;
- }
-}
-
-
-/***************************************************************************/
-
-int
-efile_pwrite(Efile_error* errInfo, /* Where to return error codes. */
- int fd, /* File descriptor to write to. */
- char* buf, /* Buffer to write. */
- size_t count, /* Number of bytes to write. */
- Sint64 offset) /* where to write it */
-{
- int res = efile_seek(errInfo, fd, offset, EFILE_SEEK_SET, NULL);
-
- if (res) {
- return efile_write(errInfo, 0, fd, buf, count);
- } else {
- return res;
- }
-}
-
-/***************************************************************************/
-
-int
-efile_seek(Efile_error* errInfo, /* Where to return error codes. */
- int fd, /* File descriptor to do the seek on. */
- Sint64 offset, /* Offset in bytes from the given
- origin. */
- int origin, /* Origin of seek (SEEK_SET, SEEK_CUR,
- SEEK_END). */
- Sint64 *new_location) /* Resulting new location in file. */
-{
- off_t off, result;
- off = (off_t) offset;
-
- switch (origin) {
- case EFILE_SEEK_SET:
- origin = SEEK_SET;
- break;
- case EFILE_SEEK_CUR:
- origin = SEEK_CUR;
- break;
- case EFILE_SEEK_END:
- origin = SEEK_END;
- break;
- default:
- errno = EINVAL;
- return check_error(-1, errInfo);
- }
-
- if (off != offset) {
- errno = EINVAL;
- return check_error(-1, errInfo);
- }
-
- errno = 0;
- result = lseek(fd, off, origin);
-
- if (result >= 0) {
- l_invalidate_local_fd(fd);
- }
-
- if (result < 0)
- {
- if (errno == ENOSYS) {
- int size, cur_pos;
-
- if (off < 0) {
- errno = EINVAL;
- return check_error(-1, errInfo);
- }
-
- cur_pos = lseek(fd, 0, SEEK_CUR);
- size = lseek(fd, 0, SEEK_END);
-
- if (origin == SEEK_SET) {
- result = offset;
- }
- else if (origin == SEEK_CUR) {
- result = offset + cur_pos;
- }
- else if (origin == SEEK_END) {
- result = size + offset;
- }
-
- /* sanity check our result */
- if (size > result) {
- return check_error(-1, errInfo);
- }
-
- /* store the data localy */
- l_update_local_fd(fd, result, size);
-
- /* reset the original file position */
- if (origin != SEEK_END) {
- lseek(fd, cur_pos, SEEK_SET);
- }
- }
- else if (errno == 0) {
- errno = EINVAL;
- }
- }
-
- if (new_location) {
- *new_location = result;
- }
-
- return 1;
-}
-
-/***************************************************************************/
-
-int
-efile_truncate_file(Efile_error* errInfo, int *fd, int flags)
-{
- off_t offset;
- struct fd_data *fd_data;
-
- if ((fd_data = l_find_local_fd(*fd)) != NULL && L_FD_IS_VALID(fd_data)) {
- offset = L_FD_CUR(fd_data);
- }
- else {
- offset = lseek(*fd, 0, SEEK_CUR);
- }
-
- return check_error(((offset >= 0) &&
- (ftruncate(*fd, offset) == 0)) ? 1 : -1, errInfo);
-}
-
-/***************************************************************************/
-
-int
-efile_readlink(Efile_error* errInfo, char* name, char* buffer, size_t size)
-{
- errno = ENOTSUP;
- return check_error(-1, errInfo);
-}
-
-/***************************************************************************/
-
-int
-efile_altname(Efile_error* errInfo, char* name, char* buffer, size_t size)
-{
- errno = ENOTSUP;
- return check_error(-1, errInfo);
-}
-
-/***************************************************************************/
-
-int
-efile_link(Efile_error* errInfo, char* old, char* new)
-{
- errno = ENOTSUP;
- return check_error(-1, errInfo);
-}
-
-/***************************************************************************/
-
-int
-efile_symlink(Efile_error* errInfo, char* old, char* new)
-{
- errno = ENOTSUP;
- return check_error(-1, errInfo);
-}
-
-/***************************************************************************/
-
-int
-efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset,
- Sint64 length, int advise)
-{
- return check_error(posix_fadvise(fd, offset, length, advise), errInfo);
-}
-
-/***************************************************************************/
-
-static int
-call_posix_fallocate(int fd, Sint64 offset, Sint64 length)
-{
- int ret;
-
- /*
- * On Linux and Solaris for example, posix_fallocate() returns
- * a positive error number on error and it does not set errno.
- * On FreeBSD however (9.0 at least), it returns -1 on error
- * and it sets errno.
- */
- do {
- ret = posix_fallocate(fd, (off_t) offset, (off_t) length);
- if (ret > 0) {
- errno = ret;
- ret = -1;
- }
- } while (ret != 0 && errno == EINTR);
-
- return ret;
-}
-
-/***************************************************************************/
-
-int
-efile_fallocate(Efile_error* errInfo, int fd, Sint64 offset, Sint64 length)
-{
- return check_error(call_posix_fallocate(fd, offset, length), errInfo);
-}
diff --git a/erts/emulator/drivers/ose/ose_signal_drv.c b/erts/emulator/drivers/ose/ose_signal_drv.c
deleted file mode 100644
index 2be9462a47..0000000000
--- a/erts/emulator/drivers/ose/ose_signal_drv.c
+++ /dev/null
@@ -1,897 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2013-2013. 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%
- */
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "errno.h"
-#include "stdio.h"
-#include "string.h"
-#include "stddef.h"
-
-#include "sys.h"
-#include "erl_driver.h"
-#include "ose.h"
-
-
-#ifdef HAVE_OSE_SPI_H
-#include "ose_spi/ose_spi.h"
-#endif
-
-#define DEBUG_ATTACH 0
-#define DEBUG_HUNT 0
-#define DEBUG_SEND 0
-#define DEBUG_LISTEN 0
-
-#if 0
-#define DEBUGP(FMT,...) printf(FMT, __VA_ARGS__)
-#else
-#define DEBUGP(FMT,...)
-#endif
-
-#if DEBUG_ATTACH
-#define DEBUGP_ATTACH(...) DEBUGP( __VA_ARGS__)
-#else
-#define DEBUGP_ATTACH(...)
-#endif
-
-#if DEBUG_HUNT
-#define DEBUGP_HUNT(...) DEBUGP( __VA_ARGS__)
-#else
-#define DEBUGP_HUNT(...)
-#endif
-
-#if DEBUG_LISTEN
-#define DEBUGP_LISTEN(...) DEBUGP( __VA_ARGS__)
-#else
-#define DEBUGP_LISTEN(...)
-#endif
-
-#if DEBUG_SEND
-#define DEBUGP_SEND(...) DEBUGP( __VA_ARGS__)
-#else
-#define DEBUGP_SEND(...)
-#endif
-
-
-#define DRIVER_NAME "ose_signal_drv"
-#define GET_SPID 1
-#define GET_NAME 2
-#define HUNT 100
-#define DEHUNT 101
-#define ATTACH 102
-#define DETACH 103
-#define SEND 104
-#define SEND_W_S 105
-#define LISTEN 106
-#define OPEN 200
-
-#define REF_SEGMENT_SIZE 8
-
-struct async {
- SIGSELECT signo;
- ErlDrvTermData port;
- ErlDrvTermData proc;
- PROCESS spid;
- PROCESS target;
- Uint32 ref;
-};
-
-/**
- * OSE signals
- **/
-union SIGNAL {
- SIGSELECT signo;
- struct async async;
-};
-
-/**
- * The driver's context
- **/
-typedef struct _driver_context {
- ErlDrvPort port;
- PROCESS spid;
- ErlDrvEvent perm_events[2];
- ErlDrvEvent *events;
- Uint32 event_cnt;
- Uint32 ref;
- Uint32 *outstanding_refs;
- Uint32 outstanding_refs_max;
- Uint32 outstanding_refs_cnt;
-} driver_context_t;
-
-/**
- * Global variables
- **/
-static ErlDrvTermData a_ok;
-static ErlDrvTermData a_error;
-static ErlDrvTermData a_enomem;
-static ErlDrvTermData a_enoent;
-static ErlDrvTermData a_badarg;
-static ErlDrvTermData a_mailbox_up;
-static ErlDrvTermData a_mailbox_down;
-static ErlDrvTermData a_ose_drv_reply;
-static ErlDrvTermData a_message;
-static PROCESS proxy_proc;
-
-
-/**
- * Serialize/unserialize unsigned 32-bit values
- **/
-static char *put_u32(unsigned int value, char *ptr) {
- *ptr++ = (value & 0xff000000) >> 24;
- *ptr++ = (value & 0x00ff0000) >> 16;
- *ptr++ = (value & 0x0000ff00) >> 8;
- *ptr++ = (value & 0xff);
-
- return ptr;
-}
-
-static unsigned int get_u32(char *ptr) {
- unsigned int result = 0;
- result += (ptr[0] & 0xff) << 24;
- result += (ptr[1] & 0xff) << 16;
- result += (ptr[2] & 0xff) << 8;
- result += (ptr[3] & 0xff);
-
- return result;
-}
-
-
-/* Stolen from efile_drv.c */
-
-/* char EV_CHAR_P(ErlIOVec *ev, int p, int q) */
-#define EV_CHAR_P(ev, p, q) \
- (((char *)(ev)->iov[(q)].iov_base) + (p))
-
-/* int EV_GET_CHAR(ErlIOVec *ev, char *p, int *pp, int *qp) */
-#define EV_GET_CHAR(ev, p, pp, qp) ev_get_char(ev, p ,pp, qp)
-static int
-ev_get_char(ErlIOVec *ev, char *p, int *pp, int *qp) {
- if (*(pp)+1 <= (ev)->iov[*(qp)].iov_len) {
- *(p) = *EV_CHAR_P(ev, *(pp), *(qp));
- if (*(pp)+1 < (ev)->iov[*(qp)].iov_len)
- *(pp) = *(pp)+1;
- else {
- (*(qp))++;
- *pp = 0;
- }
- return !0;
- }
- return 0;
-}
-
-/* Uint32 EV_UINT32(ErlIOVec *ev, int p, int q)*/
-#define EV_UINT32(ev, p, q) \
- ((Uint32) *(((unsigned char *)(ev)->iov[(q)].iov_base) + (p)))
-
-/* int EV_GET_UINT32(ErlIOVec *ev, Uint32 *p, int *pp, int *qp) */
-#define EV_GET_UINT32(ev, p, pp, qp) ev_get_uint32(ev,(Uint32*)(p),pp,qp)
-static int
-ev_get_uint32(ErlIOVec *ev, Uint32 *p, int *pp, int *qp) {
- if (*(pp)+4 <= (ev)->iov[*(qp)].iov_len) {
- *(p) = (EV_UINT32(ev, *(pp), *(qp)) << 24)
- | (EV_UINT32(ev, *(pp)+1, *(qp)) << 16)
- | (EV_UINT32(ev, *(pp)+2, *(qp)) << 8)
- | (EV_UINT32(ev, *(pp)+3, *(qp)));
- if (*(pp)+4 < (ev)->iov[*(qp)].iov_len)
- *(pp) = *(pp)+4;
- else {
- (*(qp))++;
- *pp = 0;
- }
- return !0;
- }
- return 0;
-}
-
-/**
- * Convinience macros
- **/
-#define send_response(port,output) erl_drv_send_term(driver_mk_port(port),\
- driver_caller(port), output, sizeof(output) / sizeof(output[0]));
-
-void iov_memcpy(void *dest,ErlIOVec *ev,int ind,int off);
-void iov_memcpy(void *dest,ErlIOVec *ev,int ind,int off) {
- int i;
- memcpy(dest,ev->iov[ind].iov_base+off,ev->iov[ind].iov_len-off);
- for (i = ind+1; i < ev->vsize; i++)
- memcpy(dest,ev->iov[i].iov_base,ev->iov[i].iov_len);
-}
-
-/**
- * Reference handling
- **/
-
-static int add_reference(driver_context_t *ctxt, Uint32 ref) {
-
- /*
- * Premature optimizations may be evil, but they sure are fun.
- */
-
- if (ctxt->outstanding_refs == NULL) {
- /* First ref to be ignored */
- ctxt->outstanding_refs = driver_alloc(REF_SEGMENT_SIZE*sizeof(Uint32));
- if (!ctxt->outstanding_refs)
- return 1;
-
- memset(ctxt->outstanding_refs,0,REF_SEGMENT_SIZE*sizeof(Uint32));
- ctxt->outstanding_refs_max += REF_SEGMENT_SIZE;
- ctxt->outstanding_refs[ctxt->outstanding_refs_cnt++] = ref;
- } else if (ctxt->outstanding_refs_cnt == ctxt->outstanding_refs_max) {
- /* Expand ref array */
- Uint32 *new_array;
- ctxt->outstanding_refs_max += REF_SEGMENT_SIZE;
- new_array = driver_realloc(ctxt->outstanding_refs,
- ctxt->outstanding_refs_max*sizeof(Uint32));
-
- if (!new_array) {
- ctxt->outstanding_refs_max -= REF_SEGMENT_SIZE;
- return 1;
- }
-
- ctxt->outstanding_refs = new_array;
-
- memset(ctxt->outstanding_refs+ctxt->outstanding_refs_cnt,0,
- REF_SEGMENT_SIZE*sizeof(Uint32));
- ctxt->outstanding_refs[ctxt->outstanding_refs_cnt++] = ref;
-
- } else {
- /* Find an empty slot:
- * First we try current index,
- * then we scan for a slot.
- */
- if (!ctxt->outstanding_refs[ctxt->outstanding_refs_cnt]) {
- ctxt->outstanding_refs[ctxt->outstanding_refs_cnt++] = ref;
- } else {
- int i;
- ASSERT(ctxt->outstanding_refs_cnt < ctxt->outstanding_refs_max);
- for (i = 0; i < ctxt->outstanding_refs_max; i++)
- if (!ctxt->outstanding_refs[i])
- break;
- ASSERT(ctxt->outstanding_refs[i] == 0);
- ctxt->outstanding_refs[i] = ref;
- ctxt->outstanding_refs_cnt++;
- }
- }
- return 0;
-}
-
-/* Return 0 if removed, 1 if does not exist, */
-static int remove_reference(driver_context_t *ctxt, Uint32 ref) {
- int i,j;
-
- if (ctxt->outstanding_refs_max == 0 && ctxt->outstanding_refs_cnt == 0) {
- ASSERT(ctxt->outstanding_refs == NULL);
- return 1;
- }
-
- for (i = 0; i < ctxt->outstanding_refs_max; i++) {
- if (ctxt->outstanding_refs[i] == ref) {
- ctxt->outstanding_refs[i] = 0;
- ctxt->outstanding_refs_cnt--;
- i = -1;
- break;
- }
- }
-
- if (i != -1)
- return 1;
-
- if (ctxt->outstanding_refs_cnt == 0) {
- driver_free(ctxt->outstanding_refs);
- ctxt->outstanding_refs = NULL;
- ctxt->outstanding_refs_max = 0;
- } else if (ctxt->outstanding_refs_cnt == (ctxt->outstanding_refs_max - REF_SEGMENT_SIZE)) {
- Uint32 *new_array;
- for (i = 0, j = 0; i < ctxt->outstanding_refs_cnt; i++) {
- if (ctxt->outstanding_refs[i] == 0) {
- for (j = i+1; j < ctxt->outstanding_refs_max; j++)
- if (ctxt->outstanding_refs[j]) {
- ctxt->outstanding_refs[i] = ctxt->outstanding_refs[j];
- ctxt->outstanding_refs[j] = 0;
- break;
- }
- }
- }
- ctxt->outstanding_refs_max -= REF_SEGMENT_SIZE;
- new_array = driver_realloc(ctxt->outstanding_refs,
- ctxt->outstanding_refs_max*sizeof(Uint32));
- if (!new_array) {
- ctxt->outstanding_refs_max += REF_SEGMENT_SIZE;
- return 2;
- }
-
- ctxt->outstanding_refs = new_array;
-
- }
-
- return 0;
-}
-
-/**
- * The OSE proxy process. This only handles ERTS_SIGNAL_OSE_DRV_ATTACH.
- * The process is needed because signals triggered by attach ignore
- * redir tables.
- *
- * We have one global proxy process to save memory. An attempt to make each
- * port phantom into a proxy was made, but that used way to much memory.
- */
-static OS_PROCESS(driver_proxy_process) {
- SIGSELECT sigs[] = {1,ERTS_SIGNAL_OSE_DRV_ATTACH};
- PROCESS master = 0;
-
- while (1) {
- union SIGNAL *sig = receive(sigs);
-
- if (sig->signo == ERTS_SIGNAL_OSE_DRV_ATTACH) {
-
- /* The first message is used to determine who to send messages to. */
- if (master == 0)
- master = sender(&sig);
-
- if (sig->async.target == 0) {
- PROCESS from = sender(&sig);
- restore(sig);
- DEBUGP_ATTACH("0x%x: got attach 0x%x, sending to 0x%x\n",
- current_process(),from,master);
- sig->async.target = from;
- send(&sig,master);
- } else {
- PROCESS target = sig->async.target;
- restore(sig);
- sig->async.target = 0;
- DEBUGP_ATTACH("0x%x: doing attach on 0x%x\n",current_process(),target);
- attach(&sig,target);
- }
- }
- }
-}
-
-
-/**
- * Init routine for the driver
- **/
-static int drv_init(void) {
-
- a_ok = driver_mk_atom("ok");
- a_error = driver_mk_atom("error");
- a_enomem = driver_mk_atom("enomem");
- a_enoent = driver_mk_atom("enoent");
- a_badarg = driver_mk_atom("badarg");
- a_mailbox_up = driver_mk_atom("mailbox_up");
- a_mailbox_down = driver_mk_atom("mailbox_down");
- a_ose_drv_reply = driver_mk_atom("ose_drv_reply");
- a_message = driver_mk_atom("message");
-
- proxy_proc = create_process(get_ptype(current_process()),
- "ose_signal_driver_proxy",
- driver_proxy_process, 10000,
- get_pri(current_process()),
- 0, 0, NULL, 0, 0);
-
-#ifdef DEBUG
- efs_clone(proxy_proc);
-#endif
- start(proxy_proc);
-
- return 0;
-}
-
-/* Signal resolution callback */
-static ErlDrvOseEventId resolve_signal(union SIGNAL* osig) {
- union SIGNAL *sig = osig;
- if (sig->signo == ERTS_SIGNAL_OSE_DRV_HUNT ||
- sig->signo == ERTS_SIGNAL_OSE_DRV_ATTACH) {
- return sig->async.spid;
- }
- DEBUGP("%p: Got signal %d sent to %p from 0x%p\n",
- current_process(),sig->signo,addressee(&sig),sender(&sig));
- return addressee(&sig);
-}
-
-
-/**
- * Start routine for the driver
- **/
-static ErlDrvData drv_start(ErlDrvPort port, char *command)
-{
- driver_context_t *ctxt = driver_alloc(sizeof(driver_context_t));
-
- ctxt->perm_events[0] = NULL;
- ctxt->perm_events[1] = NULL;
-
- ctxt->spid = 0;
- ctxt->port = port;
- ctxt->event_cnt = 0;
- ctxt->events = NULL;
- ctxt->ref = 0;
- ctxt->outstanding_refs = NULL;
- ctxt->outstanding_refs_max = 0;
- ctxt->outstanding_refs_cnt = 0;
-
-
- /* Set the communication protocol to Erlang to be binary */
- set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
-
- /* Everything ok */
- return (ErlDrvData)ctxt;
-}
-
-/**
- * Stop routine for the driver
- **/
-static void drv_stop(ErlDrvData driver_data)
-{
- driver_context_t *ctxt = (driver_context_t *)driver_data;
- int i;
-
- /* HUNT + ATTACH */
- if (ctxt->perm_events[0])
- driver_select(ctxt->port, ctxt->perm_events[0],
- ERL_DRV_USE|ERL_DRV_READ, 0);
- if (ctxt->perm_events[1])
- driver_select(ctxt->port, ctxt->perm_events[1],
- ERL_DRV_USE|ERL_DRV_READ, 0);
-
- for (i = 0; i < ctxt->event_cnt; i++) {
- driver_select(ctxt->port, ctxt->events[i], ERL_DRV_USE|ERL_DRV_READ, 0);
- }
-
- if (ctxt->spid != 0)
- kill_proc(ctxt->spid);
- DEBUGP("0x%x: stopped\n",ctxt->spid);
- if (ctxt->events)
- driver_free(ctxt->events);
- if (ctxt->outstanding_refs)
- driver_free(ctxt->outstanding_refs);
-
- driver_free(ctxt);
-}
-
-/**
- * Output from Erlang
- **/
-static void outputv(ErlDrvData driver_data, ErlIOVec *ev)
-{
- driver_context_t *ctxt = (driver_context_t *)driver_data;
- int p = 0, q = 1;
- char cmd;
-
- if (! EV_GET_CHAR(ev,&cmd,&p,&q)) {
- ErlDrvTermData output[] = {
- ERL_DRV_ATOM, a_ose_drv_reply,
- ERL_DRV_PORT, driver_mk_port(ctxt->port),
- ERL_DRV_ATOM, a_badarg,
- ERL_DRV_TUPLE, 3};
- send_response(ctxt->port, output);
- return;
- }
-
- /* Command is in the buffer's first byte */
- switch(cmd) {
-
- case OPEN: {
- char *name = driver_alloc(ev->size - 1+1);
- struct OS_redir_entry redir[2];
-
- redir[0].sig = 1;
- redir[0].pid = current_process();
-
- iov_memcpy(name,ev,q,p);
- name[ev->size-1] = '\0';
-
- ctxt->spid = create_process(OS_PHANTOM, name, NULL, 0,
- 0, 0, 0, redir, 0, 0);
-
- DEBUGP("0x%x: open\n",ctxt->spid);
-
- ctxt->perm_events[1] =
- erl_drv_ose_event_alloc(ERTS_SIGNAL_OSE_DRV_ATTACH,(int)ctxt->spid,
- resolve_signal, NULL);
- driver_select(ctxt->port,ctxt->perm_events[1],ERL_DRV_READ|ERL_DRV_USE,1);
-
- ctxt->perm_events[0] =
- erl_drv_ose_event_alloc(ERTS_SIGNAL_OSE_DRV_HUNT,(int)ctxt->spid,
- resolve_signal, NULL);
- driver_select(ctxt->port,ctxt->perm_events[0],ERL_DRV_READ|ERL_DRV_USE,1);
-
- start(ctxt->spid);
-
- {
- ErlDrvTermData output[] = {
- ERL_DRV_ATOM, a_ose_drv_reply,
- ERL_DRV_PORT, driver_mk_port(ctxt->port),
- ERL_DRV_ATOM, a_ok,
- ERL_DRV_TUPLE, 3};
-
- send_response(ctxt->port, output);
- }
-
- break;
-
- }
-
- case ATTACH:
- case HUNT:
- {
- union SIGNAL *sig = alloc(sizeof(union SIGNAL),
- cmd == HUNT ? ERTS_SIGNAL_OSE_DRV_HUNT:ERTS_SIGNAL_OSE_DRV_ATTACH);
-
- sig->async.port = driver_mk_port(ctxt->port);
- sig->async.proc = driver_caller(ctxt->port);
- sig->async.spid = ctxt->spid;
- sig->async.ref = ++ctxt->ref;
-
- if (add_reference(ctxt,ctxt->ref)) {
- ErlDrvTermData output[] = {
- ERL_DRV_ATOM, a_ose_drv_reply,
- ERL_DRV_PORT, driver_mk_port(ctxt->port),
- ERL_DRV_ATOM, a_enomem,
- ERL_DRV_TUPLE, 3};
- send_response(ctxt->port, output);
- free_buf(&sig);
- } else {
- ErlDrvTermData output[] = {
- ERL_DRV_ATOM, a_ose_drv_reply,
- ERL_DRV_PORT, driver_mk_port(ctxt->port),
- ERL_DRV_PORT, driver_mk_port(ctxt->port),
- ERL_DRV_INT, (ErlDrvUInt)ctxt->ref,
- ERL_DRV_TUPLE, 2,
- ERL_DRV_TUPLE, 3};
- send_response(ctxt->port, output);
-
- if (cmd == HUNT) {
- char *huntname = driver_alloc(sizeof(char)*((ev->size-1)+1));
-
- iov_memcpy(huntname,ev,q,p);
- huntname[ev->size-1] = '\0';
-
- DEBUGP_HUNT("0x%x: hunt %s -> %u (%u,%u)\n",
- ctxt->spid,huntname,ctxt->ref,
- ctxt->outstanding_refs_cnt,
- ctxt->outstanding_refs_max);
-
- hunt(huntname, 0, NULL, &sig);
-
- driver_free(huntname);
- } else {
- EV_GET_UINT32(ev,&sig->async.target,&p,&q);
- DEBUGP_ATTACH("0x%x: attach %u -> %u (%u,%u)\n",
- ctxt->spid,sig->async.target,
- ctxt->ref,
- ctxt->outstanding_refs_cnt,
- ctxt->outstanding_refs_max);
-
- send(&sig,proxy_proc);
- }
-
- }
-
- break;
- }
-
- case DETACH:
- case DEHUNT:
- {
-
- Uint32 ref;
-
- EV_GET_UINT32(ev,&ref,&p,&q);
- if (cmd == DETACH) {
- DEBUGP_ATTACH("0x%x: detach %u (%u,%u)\n",ctxt->spid,ref,
- ctxt->outstanding_refs_cnt,
- ctxt->outstanding_refs_max);
- } else {
- DEBUGP_HUNT("0x%x: dehunt %u (%u,%u)\n",ctxt->spid,ref,
- ctxt->outstanding_refs_cnt,
- ctxt->outstanding_refs_max);
- }
-
- if (remove_reference(ctxt,ref)) {
- ErlDrvTermData output[] = {
- ERL_DRV_ATOM, a_ose_drv_reply,
- ERL_DRV_PORT, driver_mk_port(ctxt->port),
- ERL_DRV_ATOM, a_error,
- ERL_DRV_ATOM, a_enoent,
- ERL_DRV_TUPLE, 2,
- ERL_DRV_TUPLE, 3};
-
- send_response(ctxt->port, output);
- } else {
- ErlDrvTermData output[] = {
- ERL_DRV_ATOM, a_ose_drv_reply,
- ERL_DRV_PORT, driver_mk_port(ctxt->port),
- ERL_DRV_ATOM, a_ok,
- ERL_DRV_TUPLE, 3};
-
- send_response(ctxt->port, output);
- }
-
- break;
- }
-
- case SEND:
- case SEND_W_S:
- {
- PROCESS spid;
- PROCESS sender;
- SIGSELECT signo;
- OSBUFSIZE size = ev->size-9;
- union SIGNAL *sig;
-
- EV_GET_UINT32(ev,&spid,&p,&q);
-
- if (cmd == SEND_W_S) {
- EV_GET_UINT32(ev,&sender,&p,&q);
- size -= 4;
- } else {
- sender = ctxt->spid;
- }
-
- EV_GET_UINT32(ev,&signo,&p,&q);
-
- sig = alloc(size + sizeof(SIGSELECT),signo);
-
- if (cmd == SEND_W_S) {
- DEBUGP_SEND("0x%x: send_w_s(%u,%u,%u)\n",ctxt->spid,spid,signo,sender);
- } else {
- DEBUGP_SEND("0x%x: send(%u,%u)\n",ctxt->spid,spid,signo);
- }
-
- iov_memcpy(((char *)&sig->signo) + sizeof(SIGSELECT),ev,q,p);
-
- send_w_s(&sig, sender, spid);
-
- break;
- }
-
- case LISTEN:
- {
- int i,j,event_cnt = (ev->size - 1)/4;
- ErlDrvEvent *events = NULL;
- SIGSELECT signo,tmp_signo;
-
- if (event_cnt == 0) {
- for (i = 0; i < ctxt->event_cnt; i++)
- driver_select(ctxt->port,ctxt->events[i],ERL_DRV_READ|ERL_DRV_USE,0);
- if (ctxt->events)
- driver_free(ctxt->events);
- } else {
- events = driver_alloc(sizeof(ErlDrvEvent)*event_cnt);
- EV_GET_UINT32(ev,&signo,&p,&q);
- for (i = 0, j = 0; i < event_cnt || j < ctxt->event_cnt; ) {
-
- if (ctxt->events)
- erl_drv_ose_event_fetch(ctxt->events[j],&tmp_signo,NULL,NULL);
-
- if (signo == tmp_signo) {
- events[i++] = ctxt->events[j++];
- EV_GET_UINT32(ev,&signo,&p,&q);
- } else if (signo < tmp_signo || !ctxt->events) {
- /* New signal to select on */
- events[i] = erl_drv_ose_event_alloc(signo,(int)ctxt->spid,
- resolve_signal, NULL);
- driver_select(ctxt->port,events[i++],ERL_DRV_READ|ERL_DRV_USE,1);
- EV_GET_UINT32(ev,&signo,&p,&q);
- } else {
- /* Remove old signal to select on */
- driver_select(ctxt->port,ctxt->events[j++],ERL_DRV_READ|ERL_DRV_USE,0);
- }
- }
- if (ctxt->events)
- driver_free(ctxt->events);
- }
- ctxt->events = events;
- ctxt->event_cnt = event_cnt;
-
- {
- ErlDrvTermData output[] = {
- ERL_DRV_ATOM, a_ose_drv_reply,
- ERL_DRV_PORT, driver_mk_port(ctxt->port),
- ERL_DRV_ATOM, a_ok,
- ERL_DRV_TUPLE, 3};
- send_response(ctxt->port, output);
- }
- break;
- }
-
- default:
- {
- DEBUGP("Warning: 'ose_signal_drv' unknown command '%d'\n", cmd);
- break;
- }
- }
-}
-
-/**
- * Handler for when OSE signal arrives
- **/
-static void ready_input(ErlDrvData driver_data, ErlDrvEvent event)
-{
- driver_context_t *ctxt = (driver_context_t *)driver_data;
- union SIGNAL *sig = erl_drv_ose_get_signal(event);
-
- while (sig != NULL) {
-
- switch(sig->signo)
- {
- /* Remote process is available */
- case ERTS_SIGNAL_OSE_DRV_HUNT:
- {
- const PROCESS spid = sender(&sig);
-
- if (remove_reference(ctxt,sig->async.ref)) {
- DEBUGP_HUNT("0x%x: Got hunt from 0x%x -> %u (CANCELLED) (%u,%u)\n",
- ctxt->spid,spid,sig->async.ref,
- ctxt->outstanding_refs_cnt,
- ctxt->outstanding_refs_max);
- /* Already removed by dehunt */
- } else {
- ErlDrvTermData reply[] = {
- ERL_DRV_ATOM, a_mailbox_up,
- ERL_DRV_PORT, sig->async.port,
- ERL_DRV_PORT, sig->async.port,
- ERL_DRV_UINT, (ErlDrvUInt)sig->async.ref,
- ERL_DRV_TUPLE, 2,
- ERL_DRV_UINT, (ErlDrvUInt)spid,
- ERL_DRV_TUPLE, 4};
- DEBUGP_HUNT("0x%x: Got hunt from 0x%x -> %u (%u,%u)\n",
- ctxt->spid,spid,sig->async.ref,
- ctxt->outstanding_refs_cnt,
- ctxt->outstanding_refs_max);
- erl_drv_send_term(sig->async.port, sig->async.proc, reply,
- sizeof(reply) / sizeof(reply[0]));
- }
- break;
- }
-
- /* Remote process is down */
- case ERTS_SIGNAL_OSE_DRV_ATTACH:
- {
- PROCESS spid = sig->async.target;
-
- if (remove_reference(ctxt,sig->async.ref)) {
- DEBUGP_ATTACH("0x%x: Got attach from 0x%x -> %u (CANCELLED) (%u,%u)\n",
- ctxt->spid,spid,sig->async.ref,
- ctxt->outstanding_refs_cnt,
- ctxt->outstanding_refs_max);
- /* Already removed by detach */
- } else {
- ErlDrvTermData reply[] = {
- ERL_DRV_ATOM, a_mailbox_down,
- ERL_DRV_PORT, sig->async.port,
- ERL_DRV_PORT, sig->async.port,
- ERL_DRV_UINT, sig->async.ref,
- ERL_DRV_TUPLE, 2,
- ERL_DRV_UINT, (ErlDrvUInt)spid,
- ERL_DRV_TUPLE, 4};
- DEBUGP_ATTACH("0x%x: Got attach from 0x%x -> %u (%u,%u)\n",
- ctxt->spid,spid,sig->async.ref,
- ctxt->outstanding_refs_cnt,
- ctxt->outstanding_refs_max);
- erl_drv_send_term(sig->async.port, sig->async.proc, reply,
- sizeof(reply) / sizeof(reply[0]));
- }
- break;
- }
-
- /* Received user defined signal */
- default:
- {
- const PROCESS spid = sender(&sig);
- const OSBUFSIZE size = sigsize(&sig) - sizeof(SIGSELECT);
- const char *sig_data = ((char *)&sig->signo) + sizeof(SIGSELECT);
-
- ErlDrvTermData reply[] = {
- ERL_DRV_ATOM, a_message,
- ERL_DRV_PORT, driver_mk_port(ctxt->port),
- ERL_DRV_UINT, (ErlDrvUInt)spid,
- ERL_DRV_UINT, (ErlDrvUInt)ctxt->spid,
- ERL_DRV_UINT, (ErlDrvUInt)sig->signo,
- ERL_DRV_BUF2BINARY, (ErlDrvTermData)sig_data, (ErlDrvUInt)size,
- ERL_DRV_TUPLE, 4,
- ERL_DRV_TUPLE, 3};
-
- DEBUGP_SEND("0x%x: Got 0x%u\r\n", spid, sig->signo);
-
- erl_drv_output_term(driver_mk_port(ctxt->port), reply,
- sizeof(reply) / sizeof(reply[0]));
- break;
- }
- }
-
- free_buf(&sig);
- sig = erl_drv_ose_get_signal(event);
- }
-}
-
-/**
- * Handler for 'port_control'
- **/
-static ErlDrvSSizeT control(ErlDrvData driver_data, unsigned int cmd,
- char *buf, ErlDrvSizeT len,
- char **rbuf, ErlDrvSizeT rlen)
-{
- driver_context_t *ctxt = (driver_context_t *)driver_data;
-
- switch(cmd)
- {
- case GET_SPID:
- {
- const PROCESS spid = ctxt->spid;
- put_u32(spid, *rbuf);
- return sizeof(PROCESS);
- }
-
-#ifdef HAVE_OSE_SPI_H
- case GET_NAME:
- {
- const PROCESS spid = get_u32(buf);
- char *name = (char*)get_pid_info(spid,OSE_PI_NAME);
- int n;
- if (!name) {
- *rbuf = NULL;
- return 0;
- }
-
- if (rlen < (n = strlen(name))) {
- ErlDrvBinary *bin = driver_alloc_binary(n);
- strncpy(bin->orig_bytes,name,n);
- *rbuf = (char*)bin;
- } else
- strncpy(*rbuf,name,n);
- free_buf((union SIGNAL**)&name);
-
- return n;
- }
-#endif
- default:
- {
- /* Unknown command */
- return (ErlDrvSSizeT)ERL_DRV_ERROR_GENERAL;
- break;
- }
- }
-}
-
-static void stop_select(ErlDrvEvent event, void *reserved)
-{
- erl_drv_ose_event_free(event);
-}
-
-/**
- * Setup the driver entry for the Erlang runtime
- **/
-ErlDrvEntry ose_signal_driver_entry = {
- .init = drv_init,
- .start = drv_start,
- .stop = drv_stop,
- .outputv = outputv,
- .ready_input = ready_input,
- .driver_name = DRIVER_NAME,
- .control = control,
- .extended_marker = ERL_DRV_EXTENDED_MARKER,
- .major_version = ERL_DRV_EXTENDED_MAJOR_VERSION,
- .minor_version = ERL_DRV_EXTENDED_MINOR_VERSION,
- .driver_flags = ERL_DRV_FLAG_USE_PORT_LOCKING,
- .stop_select = stop_select
-};
-
diff --git a/erts/emulator/drivers/ose/ttsl_drv.c b/erts/emulator/drivers/ose/ttsl_drv.c
deleted file mode 100644
index f759b47984..0000000000
--- a/erts/emulator/drivers/ose/ttsl_drv.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-2013. 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%
- */
-/*
- * Stub tty driver because group/user depend on this.
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "erl_driver.h"
-
-static int ttysl_init(void);
-static ErlDrvData ttysl_start(ErlDrvPort, char*);
-
-/* Define the driver table entry. */
-struct erl_drv_entry ttsl_driver_entry = {
- ttysl_init,
- ttysl_start,
- NULL,
- NULL,
- NULL,
- NULL,
- "tty_sl",
- NULL,
- NULL,
- NULL,
- NULL, /* timeout */
- NULL, /* outputv */
- NULL, /* ready_async */
- NULL, /* flush */
- NULL, /* call */
- NULL, /* event */
- ERL_DRV_EXTENDED_MARKER,
- ERL_DRV_EXTENDED_MAJOR_VERSION,
- ERL_DRV_EXTENDED_MINOR_VERSION,
- 0, /* ERL_DRV_FLAGs */
- NULL,
- NULL, /* process_exit */
- NULL
-};
-
-
-static int ttysl_init(void)
-{
- return 0;
-}
-
-static ErlDrvData ttysl_start(ErlDrvPort port, char* buf)
-{
- return ERL_DRV_ERROR_GENERAL;
-}
diff --git a/erts/emulator/drivers/unix/ttsl_drv.c b/erts/emulator/drivers/unix/ttsl_drv.c
index 25cad37e25..abfc52d3bc 100644
--- a/erts/emulator/drivers/unix/ttsl_drv.c
+++ b/erts/emulator/drivers/unix/ttsl_drv.c
@@ -199,7 +199,7 @@ static void my_debug_printf(char *fmt, ...)
erts_vsnprintf(buffer,1024,fmt,args);
va_end(args);
erts_fprintf(debuglog,"%s\n",buffer);
- //erts_printf("Debuglog = %s\n",buffer);
+ /*erts_printf("Debuglog = %s\n",buffer);*/
}
#else
@@ -261,15 +261,17 @@ static int ttysl_init(void)
if (debuglog != NULL)
setbuf(debuglog,NULL);
}
- DEBUGLOG(("Debuglog = %s(0x%ld)\n",dl,(long) debuglog));
+ DEBUGLOG(("ttysl_init: Debuglog = %s(0x%ld)\n",dl,(long) debuglog));
}
#endif
+ DEBUGLOG(("ttysl_init: ttysl_port = %d\n", ttysl_port));
return 0;
}
static ErlDrvData ttysl_start(ErlDrvPort port, char* buf)
{
#ifndef HAVE_TERMCAP
+ DEBUGLOG(("ttysl_start: failure - no TERMCAP configured!\n"));
return ERL_DRV_ERROR_GENERAL;
#else
char *s, *t, *l;
@@ -277,36 +279,46 @@ static ErlDrvData ttysl_start(ErlDrvPort port, char* buf)
int flag;
extern int using_oldshell; /* set this to let the rest of erts know */
+ DEBUGLOG(("ttysl_start: driver input \"%s\", ttysl_port = %d (-1 expected)", buf, ttysl_port));
utf8buf_size = 0;
- if (ttysl_port != (ErlDrvPort)-1)
- return ERL_DRV_ERROR_GENERAL;
+ if (ttysl_port != (ErlDrvPort)-1) {
+ DEBUGLOG(("ttysl_start: failure with ttysl_port = %d, not initialized properly?\n", ttysl_port));
+ return ERL_DRV_ERROR_GENERAL;
+ }
- if (!isatty(0) || !isatty(1))
+ DEBUGLOG(("ttysl_start: isatty(0) = %d (1 expected), isatty(1) = %d (1 expected)", isatty(0), isatty(1)));
+ if (!isatty(0) || !isatty(1)) {
+ DEBUGLOG(("ttysl_start: failure in isatty, isatty(0) = %d, isatty(1) = %d", isatty(0), isatty(1)));
return ERL_DRV_ERROR_GENERAL;
+ }
/* Set the terminal modes to default leave as is. */
canon = echo = sig = 0;
/* Parse the input parameters. */
for (s = strchr(buf, ' '); s; s = t) {
- s++;
- /* Find end of this argument (start of next) and insert NUL. */
- if ((t = strchr(s, ' '))) {
- *t = '\0';
- }
- if ((flag = ((*s == '+') ? 1 : ((*s == '-') ? -1 : 0)))) {
- if (s[1] == 'c') canon = flag;
- if (s[1] == 'e') echo = flag;
- if (s[1] == 's') sig = flag;
- }
- else if ((ttysl_fd = open(s, O_RDWR, 0)) < 0)
- return ERL_DRV_ERROR_GENERAL;
+ s++;
+ /* Find end of this argument (start of next) and insert NUL. */
+ if ((t = strchr(s, ' '))) {
+ *t = '\0';
+ }
+ if ((flag = ((*s == '+') ? 1 : ((*s == '-') ? -1 : 0)))) {
+ if (s[1] == 'c') canon = flag;
+ if (s[1] == 'e') echo = flag;
+ if (s[1] == 's') sig = flag;
+ }
+ else if ((ttysl_fd = open(s, O_RDWR, 0)) < 0) {
+ DEBUGLOG(("ttysl_start: failed to open ttysl_fd, open(%s, O_RDWR, 0)) = %d\n", s, ttysl_fd));
+ return ERL_DRV_ERROR_GENERAL;
+ }
}
+
if (ttysl_fd < 0)
ttysl_fd = 0;
if (tty_init(ttysl_fd, canon, echo, sig) < 0 ||
- tty_set(ttysl_fd) < 0) {
+ tty_set(ttysl_fd) < 0) {
+ DEBUGLOG(("ttysl_start: failed init tty or set tty\n"));
ttysl_port = (ErlDrvPort)-1;
tty_reset(ttysl_fd);
return ERL_DRV_ERROR_GENERAL;
@@ -314,6 +326,7 @@ static ErlDrvData ttysl_start(ErlDrvPort port, char* buf)
/* Set up smart line and termcap stuff. */
if (!start_lbuf() || !start_termcap()) {
+ DEBUGLOG(("ttysl_start: failed to start_lbuf or start_termcap\n"));
stop_lbuf(); /* Must free this */
tty_reset(ttysl_fd);
return ERL_DRV_ERROR_GENERAL;
@@ -335,10 +348,10 @@ static ErlDrvData ttysl_start(ErlDrvPort port, char* buf)
l = setlocale(LC_CTYPE, ""); /* Set international environment */
if (l != NULL) {
utf8_mode = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0);
- DEBUGLOG(("setlocale: %s\n",l));
+ DEBUGLOG(("ttysl_start: setlocale: %s",l));
}
#endif
- DEBUGLOG(("utf8_mode is %s\n",(utf8_mode) ? "on" : "off"));
+ DEBUGLOG(("ttysl_start: utf8_mode is %s",(utf8_mode) ? "on" : "off"));
sys_signal(SIGCONT, cont);
sys_signal(SIGWINCH, winch);
@@ -348,6 +361,7 @@ static ErlDrvData ttysl_start(ErlDrvPort port, char* buf)
/* we need to know this when we enter the break handler */
using_oldshell = 0;
+ DEBUGLOG(("ttysl_start: successful start\n"));
return (ErlDrvData)ttysl_port; /* Nothing important to return */
#endif /* HAVE_TERMCAP */
}
@@ -418,6 +432,7 @@ static ErlDrvSSizeT ttysl_control(ErlDrvData drv_data,
static void ttysl_stop(ErlDrvData ttysl_data)
{
+ DEBUGLOG(("ttysl_stop: ttysl_port = %d\n",ttysl_port));
if (ttysl_port != (ErlDrvPort)-1) {
stop_lbuf();
stop_termcap();
@@ -617,12 +632,13 @@ static int check_buf_size(byte *s, int n)
int ch;
int size = 10;
+ DEBUGLOG(("check_buf_size: n = %d",n));
while(pos < n) {
/* Indata is always UTF-8 */
if ((ch = pick_utf8(s,n,&pos)) < 0) {
/* XXX temporary allow invalid chars */
ch = (int) s[pos];
- DEBUGLOG(("Invalid UTF8:%d",ch));
+ DEBUGLOG(("check_buf_size: Invalid UTF8:%d",ch));
++pos;
}
if (utf8_mode) { /* That is, terminal is UTF8 compliant */
@@ -630,7 +646,7 @@ static int check_buf_size(byte *s, int n)
#ifdef HAVE_WCWIDTH
int width;
#endif
- DEBUGLOG(("Printable(UTF-8:%d):%d",pos,ch));
+ DEBUGLOG(("check_buf_size: Printable(UTF-8:%d):%d",pos,ch));
size++;
#ifdef HAVE_WCWIDTH
if ((width = wcwidth(ch)) > 1) {
@@ -640,21 +656,21 @@ static int check_buf_size(byte *s, int n)
} else if (ch == '\t') {
size += 8;
} else {
- DEBUGLOG(("Magic(UTF-8:%d):%d",pos,ch));
+ DEBUGLOG(("check_buf_size: Magic(UTF-8:%d):%d",pos,ch));
size += 2;
}
} else {
if (ch <= 255 && isprint(ch)) {
- DEBUGLOG(("Printable:%d",ch));
+ DEBUGLOG(("check_buf_size: Printable:%d",ch));
size++;
} else if (ch == '\t')
size += 8;
else if (ch >= 128) {
- DEBUGLOG(("Non printable:%d",ch));
+ DEBUGLOG(("check_buf_size: Non printable:%d",ch));
size += (octal_or_hex_positions(ch) + 1);
}
else {
- DEBUGLOG(("Magic:%d",ch));
+ DEBUGLOG(("check_buf_size: Magic:%d",ch));
size += 2;
}
}
@@ -664,10 +680,12 @@ static int check_buf_size(byte *s, int n)
lbuf_size = size + lpos + BUFSIZ;
if ((lbuf = driver_realloc(lbuf, lbuf_size * sizeof(Uint32))) == NULL) {
+ DEBUGLOG(("check_buf_size: alloc failure of %d bytes", lbuf_size * sizeof(Uint32)));
driver_failure(ttysl_port, -1);
return(0);
}
}
+ DEBUGLOG(("check_buf_size: success\n"));
return(1);
}
@@ -685,6 +703,8 @@ static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, ErlDrvSizeT coun
if (lpos > MAXSIZE)
put_chars((byte*)"\n", 1);
+ DEBUGLOG(("ttysl_from_erlang: OP = %d", buf[0]));
+
switch (buf[0]) {
case OP_PUTC_SYNC:
/* Using sync means that we have to send an ok to the
@@ -695,7 +715,7 @@ static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, ErlDrvSizeT coun
the port_command. */
/* fall through */
case OP_PUTC:
- DEBUGLOG(("OP: Putc(%lu)",(unsigned long) count-1));
+ DEBUGLOG(("ttysl_from_erlang: OP: Putc(%lu)",(unsigned long) count-1));
if (check_buf_size((byte*)buf+1, count-1) == 0)
return;
put_chars((byte*)buf+1, count-1);
@@ -738,6 +758,7 @@ static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, ErlDrvSizeT coun
ERL_DRV_USE|ERL_DRV_WRITE,1);
break;
} else {
+ DEBUGLOG(("ttysl_from_erlang: driver failure in writev(%d,..) = %d (errno = %d)\n", ttysl_fd, written, errno));
driver_failure_posix(ttysl_port, errno);
return;
}
@@ -774,6 +795,9 @@ static void ttysl_to_tty(ErlDrvData ttysl_data, ErlDrvEvent fd) {
ErlDrvSizeT sz;
iov = driver_peekq(ttysl_port,&qlen);
+
+ DEBUGLOG(("ttysl_to_tty: qlen = %d", qlen));
+
if (iov)
written = writev(ttysl_fd, iov, qlen > MAXIOV ? MAXIOV : qlen);
else
@@ -782,6 +806,7 @@ static void ttysl_to_tty(ErlDrvData ttysl_data, ErlDrvEvent fd) {
if (errno == EINTR) {
continue;
} else if (errno != ERRNO_BLOCK){
+ DEBUGLOG(("ttysl_to_tty: driver failure in writev(%d,..) = %d (errno = %d)\n", ttysl_fd, written, errno));
driver_failure_posix(ttysl_port, errno);
}
break;
@@ -804,6 +829,7 @@ static void ttysl_to_tty(ErlDrvData ttysl_data, ErlDrvEvent fd) {
/* flush has been called, which means we should terminate
when queue is empty. This will not send any exit
message */
+ DEBUGLOG(("ttysl_to_tty: ttysl_terminate normal\n"));
driver_failure_atom(ttysl_port, "normal");
break;
}
@@ -814,6 +840,7 @@ static void ttysl_to_tty(ErlDrvData ttysl_data, ErlDrvEvent fd) {
}
static void ttysl_flush_tty(ErlDrvData ttysl_data) {
+ DEBUGLOG(("ttysl_flush_tty: .."));
ttysl_terminate = 1;
return;
}
@@ -834,6 +861,8 @@ static void ttysl_from_tty(ErlDrvData ttysl_data, ErlDrvEvent fd)
p += utf8buf_size;
utf8buf_size = 0;
}
+
+ DEBUGLOG(("ttysl_from_tty: remainder = %d", left));
if ((i = read((int)(SWord)fd, (char *) p, left)) >= 0) {
if (p != b) {
@@ -847,7 +876,7 @@ static void ttysl_from_tty(ErlDrvData ttysl_data, ErlDrvEvent fd)
utf8buf_size = i -pos;
memcpy(utf8buf,b+pos,utf8buf_size);
} else if (ch == -1) {
- DEBUGLOG(("Giving up on UTF8 mode, invalid character"));
+ DEBUGLOG(("ttysl_from_tty: Giving up on UTF8 mode, invalid character"));
utf8_mode = 0;
goto latin_terminal;
}
@@ -864,6 +893,7 @@ static void ttysl_from_tty(ErlDrvData ttysl_data, ErlDrvEvent fd)
}
}
} else {
+ DEBUGLOG(("ttysl_from_tty: driver failure in read(%d,..) = %d\n", (int)(SWord)fd, i));
driver_failure(ttysl_port, -1);
}
}
@@ -1155,7 +1185,7 @@ static int write_buf(Uint32 *s, int n)
byte *octbuff;
byte octtmp[256];
int octbytes;
- DEBUGLOG(("Escaped: %d", ch));
+ DEBUGLOG(("write_buf: Escaped: %d", ch));
octbytes = octal_or_hex_positions(ch);
if (octbytes > 256) {
octbuff = driver_alloc(octbytes);
@@ -1164,11 +1194,11 @@ static int write_buf(Uint32 *s, int n)
}
octbytes = 0;
octal_or_hex_format(ch, octbuff, &octbytes);
- DEBUGLOG(("octbytes: %d", octbytes));
+ DEBUGLOG(("write_buf: octbytes: %d", octbytes));
outc('\\');
for (i = 0; i < octbytes; ++i) {
outc(lastput = octbuff[i]);
- DEBUGLOG(("outc: %d", (int) lastput));
+ DEBUGLOG(("write_buf: outc: %d", (int) lastput));
}
n -= octbytes+1;
s += octbytes+1;
@@ -1180,7 +1210,7 @@ static int write_buf(Uint32 *s, int n)
--n; s++;
#endif
} else {
- DEBUGLOG(("Very unexpected character %d",(int) *s));
+ DEBUGLOG(("write_buf: Very unexpected character %d",(int) *s));
++n;
--s;
}
@@ -1242,6 +1272,9 @@ static int start_termcap(void)
size_t envsz = 1024;
char *env = NULL;
char *c;
+ int tres;
+
+ DEBUGLOG(("start_termcap: .."));
capbuf = driver_alloc(1024);
if (!capbuf)
@@ -1249,9 +1282,10 @@ static int start_termcap(void)
eres = erl_drv_getenv("TERM", capbuf, &envsz);
if (eres == 0)
env = capbuf;
- else if (eres < 0)
+ else if (eres < 0) {
+ DEBUGLOG(("start_termcap: failure in erl_drv_getenv(\"TERM\", ..) = %d\n", eres));
goto false;
- else /* if (eres > 1) */ {
+ } else /* if (eres > 1) */ {
char *envbuf = driver_alloc(envsz);
if (!envbuf)
goto false;
@@ -1261,7 +1295,8 @@ static int start_termcap(void)
if (eres == 0)
break;
newenvbuf = driver_realloc(envbuf, envsz);
- if (eres < 0 || !newenvbuf) {
+ if (eres < 0 || !newenvbuf) {
+ DEBUGLOG(("start_termcap: failure in erl_drv_getenv(\"TERM\", ..) = %d or realloc buf == %p\n", eres, newenvbuf));
env = newenvbuf ? newenvbuf : envbuf;
goto false;
}
@@ -1269,8 +1304,10 @@ static int start_termcap(void)
}
env = envbuf;
}
- if (tgetent((char*)lbuf, env) <= 0)
- goto false;
+ if ((tres = tgetent((char*)lbuf, env)) <= 0) {
+ DEBUGLOG(("start_termcap: failure in tgetent(..) = %d\n", tres));
+ goto false;
+ }
if (env != capbuf) {
env = NULL;
driver_free(env);
@@ -1286,8 +1323,11 @@ static int start_termcap(void)
if (!(left = tgetflag("bs") ? "\b" : tgetstr("bc", &c)))
left = "\b"; /* Can't happen - but does on Solaris 2 */
right = tgetstr("nd", &c);
- if (up && down && left && right)
- return TRUE;
+ if (up && down && left && right) {
+ DEBUGLOG(("start_termcap: successful start\n"));
+ return TRUE;
+ }
+ DEBUGLOG(("start_termcap: failed start\n"));
false:
if (env && env != capbuf)
driver_free(env);
@@ -1364,10 +1404,13 @@ static void update_cols(void)
static struct termios tty_smode, tty_rmode;
-static int tty_init(int fd, int canon, int echo, int sig)
-{
- if (tcgetattr(fd, &tty_rmode) < 0)
- return -1;
+static int tty_init(int fd, int canon, int echo, int sig) {
+ int tres;
+ DEBUGLOG(("tty_init: fd = %d, canon = %d, echo = %d, sig = %d", fd, canon, echo, sig));
+ if ((tres = tcgetattr(fd, &tty_rmode)) < 0) {
+ DEBUGLOG(("tty_init: failure in tcgetattr(%d,..) = %d\n", fd, tres));
+ return -1;
+ }
tty_smode = tty_rmode;
/* Default characteristics for all usage including termcap output. */
@@ -1420,6 +1463,7 @@ static int tty_init(int fd, int canon, int echo, int sig)
#endif
tty_smode.c_lflag &= ~(ISIG|IEXTEN);
}
+ DEBUGLOG(("tty_init: successful init\n"));
return 0;
}
@@ -1430,20 +1474,25 @@ static int tty_init(int fd, int canon, int echo, int sig)
static int tty_set(int fd)
{
- DEBUGF(("Setting tty...\n"));
+ int tres;
+ DEBUGF(("tty_set: Setting tty...\n"));
- if (tcsetattr(fd, TCSANOW, &tty_smode) < 0)
+ if ((tres = tcsetattr(fd, TCSANOW, &tty_smode)) < 0) {
+ DEBUGLOG(("tty_set: failure in tcgetattr(%d,..) = %d\n", fd, tres));
return(-1);
+ }
return(0);
}
static int tty_reset(int fd) /* of terminal device */
{
- DEBUGF(("Resetting tty...\n"));
+ int tres;
+ DEBUGF(("tty_reset: Resetting tty...\n"));
- if (tcsetattr(fd, TCSANOW, &tty_rmode) < 0)
+ if ((tres = tcsetattr(fd, TCSANOW, &tty_rmode)) < 0) {
+ DEBUGLOG(("tty_reset: failure in tcsetattr(%d,..) = %d\n", fd, tres));
return(-1);
-
+ }
return(0);
}
@@ -1458,6 +1507,7 @@ static int tty_reset(int fd) /* of terminal device */
static RETSIGTYPE suspend(int sig)
{
if (tty_reset(ttysl_fd) < 0) {
+ DEBUGLOG(("signal: failure in suspend(%d), can't reset tty %d\n", sig, ttysl_fd));
fprintf(stderr,"Can't reset tty \n");
exit(1);
}
@@ -1469,6 +1519,7 @@ static RETSIGTYPE suspend(int sig)
sys_signal(sig, suspend); /* Reset signal handler */
if (tty_set(ttysl_fd) < 0) {
+ DEBUGLOG(("signal: failure in suspend(%d), can't set tty %d\n", sig, ttysl_fd));
fprintf(stderr,"Can't set tty raw \n");
exit(1);
}
@@ -1479,6 +1530,7 @@ static RETSIGTYPE suspend(int sig)
static RETSIGTYPE cont(int sig)
{
if (tty_set(ttysl_fd) < 0) {
+ DEBUGLOG(("signal: failure in cont(%d), can't set tty raw %d\n", sig, ttysl_fd));
fprintf(stderr,"Can't set tty raw\n");
exit(1);
}
diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c
index 00da48b107..ac9b681d03 100644
--- a/erts/emulator/drivers/unix/unix_efile.c
+++ b/erts/emulator/drivers/unix/unix_efile.c
@@ -467,7 +467,7 @@ int
efile_fdatasync(Efile_error *errInfo, /* Where to return error codes. */
int fd) /* File descriptor for file to sync data. */
{
-#ifdef HAVE_FDATASYNC
+#if defined(HAVE_FDATASYNC) && !defined(__DARWIN__)
return check_error(fdatasync(fd), errInfo);
#else
return efile_fsync(errInfo, fd);
diff --git a/erts/emulator/hipe/hipe_bif0.c b/erts/emulator/hipe/hipe_bif0.c
index c838150db8..70354aa9af 100644
--- a/erts/emulator/hipe/hipe_bif0.c
+++ b/erts/emulator/hipe/hipe_bif0.c
@@ -488,7 +488,7 @@ static void *const_term_alloc(void *tmpl)
alloc_size = size + (offsetof(struct const_term, mem)/sizeof(Eterm));
hipe_constants_size += alloc_size;
- p = (struct const_term*)erts_alloc(ERTS_ALC_T_HIPE, alloc_size * sizeof(Eterm));
+ p = (struct const_term*)erts_alloc(ERTS_ALC_T_LITERAL, alloc_size * sizeof(Eterm));
/* I have absolutely no idea if having a private 'off_heap'
works or not. _Some_ off_heap object is required for
@@ -497,6 +497,8 @@ static void *const_term_alloc(void *tmpl)
hp = &p->mem[0];
p->val = copy_struct(obj, size, &hp, &const_term_table_off_heap);
+ erts_set_literal_tag(&p->val, &p->mem[0], size);
+
return &p->bucket;
}
@@ -507,6 +509,9 @@ static void init_const_term_table(void)
f.cmp = (HCMP_FUN) const_term_cmp;
f.alloc = (HALLOC_FUN) const_term_alloc;
f.free = (HFREE_FUN) NULL;
+ f.meta_alloc = (HMALLOC_FUN) erts_alloc;
+ f.meta_free = (HMFREE_FUN) erts_free;
+ f.meta_print = (HMPRINT_FUN) erts_print;
hash_init(ERTS_ALC_T_HIPE, &const_term_table, "const_term_table", 97, f);
}
@@ -574,15 +579,15 @@ static void print_mfa(Eterm mod, Eterm fun, unsigned int ari)
static Uint *hipe_find_emu_address(Eterm mod, Eterm name, unsigned int arity)
{
Module *modp;
- Uint *code_base;
+ BeamCodeHeader* code_hdr;
int i, n;
modp = erts_get_module(mod, erts_active_code_ix());
- if (modp == NULL || (code_base = modp->curr.code) == NULL)
+ if (modp == NULL || (code_hdr = modp->curr.code_hdr) == NULL)
return NULL;
- n = code_base[MI_NUM_FUNCTIONS];
+ n = code_hdr->num_functions;
for (i = 0; i < n; ++i) {
- Uint *code_ptr = (Uint*)code_base[MI_FUNCTIONS+i];
+ Uint *code_ptr = (Uint*)code_hdr->functions[i];
ASSERT(code_ptr[0] == BeamOpCode(op_i_func_info_IaaI));
if (code_ptr[3] == name && code_ptr[4] == arity)
return code_ptr+5;
@@ -715,6 +720,9 @@ static void init_nbif_table(void)
f.cmp = (HCMP_FUN) nbif_cmp;
f.alloc = (HALLOC_FUN) nbif_alloc;
f.free = NULL;
+ f.meta_alloc = (HMALLOC_FUN) erts_alloc;
+ f.meta_free = (HMFREE_FUN) erts_free;
+ f.meta_print = (HMPRINT_FUN) erts_print;
hash_init(ERTS_ALC_T_NBIF_TABLE, &nbif_table, "nbif_table", 500, f);
@@ -808,6 +816,9 @@ static void init_primop_table(void)
f.cmp = (HCMP_FUN) primop_cmp;
f.alloc = (HALLOC_FUN) primop_alloc;
f.free = NULL;
+ f.meta_alloc = (HMALLOC_FUN) erts_alloc;
+ f.meta_free = (HMFREE_FUN) erts_free;
+ f.meta_print = (HMPRINT_FUN) erts_print;
hash_init(ERTS_ALC_T_HIPE, &primop_table, "primop_table", 50, f);
@@ -1826,6 +1837,9 @@ static void init_modinfo_table(void)
f.cmp = (HCMP_FUN) modinfo_cmp;
f.alloc = (HALLOC_FUN) modinfo_alloc;
f.free = (HFREE_FUN) NULL;
+ f.meta_alloc = (HMALLOC_FUN) erts_alloc;
+ f.meta_free = (HMFREE_FUN) erts_free;
+ f.meta_print = (HMPRINT_FUN) erts_print;
hash_init(ERTS_ALC_T_HIPE, &modinfo_table, "modinfo_table", 11, f);
}
diff --git a/erts/emulator/hipe/hipe_gc.c b/erts/emulator/hipe/hipe_gc.c
index 2c747771ac..2e19bf88bf 100644
--- a/erts/emulator/hipe/hipe_gc.c
+++ b/erts/emulator/hipe/hipe_gc.c
@@ -46,10 +46,6 @@ Eterm *fullsweep_nstack(Process *p, Eterm *n_htop)
/* arch-specific nstack walk state */
struct nstack_walk_state walk_state;
- /* fullsweep-specific state */
- char *src, *oh;
- Uint src_size, oh_size;
-
if (!p->hipe.nstack) {
ASSERT(!p->hipe.nsp && !p->hipe.nstend);
return n_htop;
@@ -66,11 +62,6 @@ Eterm *fullsweep_nstack(Process *p, Eterm *n_htop)
sdesc = nstack_walk_init_sdesc(p, &walk_state);
- src = (char*)HEAP_START(p);
- src_size = (char*)HEAP_TOP(p) - src;
- oh = (char*)OLD_HEAP(p);
- oh_size = (char*)OLD_HTOP(p) - oh;
-
for (;;) {
if (nstack_walk_nsp_reached_end(nsp, nsp_end)) {
if (nsp == nsp_end) {
@@ -97,8 +88,7 @@ Eterm *fullsweep_nstack(Process *p, Eterm *n_htop)
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*nsp_i = val;
- } else if (in_area(ptr, src, src_size) ||
- in_area(ptr, oh, oh_size)) {
+ } else if (!erts_is_literal(gval, ptr)) {
MOVE_BOXED(ptr, val, n_htop, nsp_i);
}
} else if (is_list(gval)) {
@@ -106,8 +96,7 @@ Eterm *fullsweep_nstack(Process *p, Eterm *n_htop)
Eterm val = *ptr;
if (IS_MOVED_CONS(val)) {
*nsp_i = ptr[1];
- } else if (in_area(ptr, src, src_size) ||
- in_area(ptr, oh, oh_size)) {
+ } else if (!erts_is_literal(gval, ptr)) {
ASSERT(within(ptr, p));
MOVE_CONS(ptr, val, n_htop, nsp_i);
}
@@ -139,11 +128,13 @@ void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
unsigned int mask;
/* arch-specific nstack walk state */
struct nstack_walk_state walk_state;
+ char *oh;
+ Uint oh_size;
/* gensweep-specific state */
Eterm *old_htop, *n_htop;
- char *heap;
- Uint heap_size, mature_size;
+ char *mature;
+ Uint mature_size;
if (!p->hipe.nstack) {
ASSERT(!p->hipe.nsp && !p->hipe.nstend);
@@ -168,9 +159,10 @@ void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
old_htop = *ptr_old_htop;
n_htop = *ptr_n_htop;
- heap = (char*)HEAP_START(p);
- heap_size = (char*)HEAP_TOP(p) - heap;
- mature_size = (char*)HIGH_WATER(p) - heap;
+ mature = (char *) (p->abandoned_heap ? p->abandoned_heap : p->heap);
+ mature_size = (char*)HIGH_WATER(p) - mature;
+ oh = (char*)OLD_HEAP(p);
+ oh_size = (char*)OLD_HTOP(p) - oh;
for (;;) {
if (nstack_walk_nsp_reached_end(nsp, nsp_end)) {
@@ -209,9 +201,9 @@ void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*nsp_i = val;
- } else if (in_area(ptr, heap, mature_size)) {
+ } else if (ErtsInArea(ptr, mature, mature_size)) {
MOVE_BOXED(ptr, val, old_htop, nsp_i);
- } else if (in_area(ptr, heap, heap_size)) {
+ } else if (ErtsInYoungGen(gval, ptr, oh, oh_size)) {
ASSERT(within(ptr, p));
MOVE_BOXED(ptr, val, n_htop, nsp_i);
}
@@ -220,9 +212,9 @@ void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
Eterm val = *ptr;
if (IS_MOVED_CONS(val)) {
*nsp_i = ptr[1];
- } else if (in_area(ptr, heap, mature_size)) {
+ } else if (ErtsInArea(ptr, mature, mature_size)) {
MOVE_CONS(ptr, val, old_htop, nsp_i);
- } else if (in_area(ptr, heap, heap_size)) {
+ } else if (ErtsInYoungGen(gval, ptr, oh, oh_size)) {
ASSERT(within(ptr, p));
MOVE_CONS(ptr, val, n_htop, nsp_i);
}
diff --git a/erts/emulator/hipe/hipe_mode_switch.c b/erts/emulator/hipe/hipe_mode_switch.c
index 9243e029f6..804c458b6c 100644
--- a/erts/emulator/hipe/hipe_mode_switch.c
+++ b/erts/emulator/hipe/hipe_mode_switch.c
@@ -196,7 +196,7 @@ hipe_push_beam_trap_frame(Process *p, Eterm reg[], unsigned arity)
ASSERT(!(p->flags & F_DISABLE_GC));
if ((p->stop - 2) < p->htop) {
DPRINTF("calling gc to increase BEAM stack size");
- p->fcalls -= erts_garbage_collect(p, 2, reg, arity);
+ erts_garbage_collect(p, 2, reg, arity);
ASSERT(!((p->stop - 2) < p->htop));
}
p->stop -= 2;
diff --git a/erts/emulator/hipe/hipe_mode_switch.h b/erts/emulator/hipe/hipe_mode_switch.h
index bc863a4f36..620cc6356b 100644
--- a/erts/emulator/hipe/hipe_mode_switch.h
+++ b/erts/emulator/hipe/hipe_mode_switch.h
@@ -95,7 +95,7 @@ ERTS_GLB_INLINE void hipe_reserve_beam_trap_frame(Process *p, Eterm reg[], unsig
/* ensure that at least 2 words are available on the BEAM stack */
if ((p->stop - 2) < p->htop) {
- p->fcalls -= erts_garbage_collect(p, 2, reg, arity);
+ erts_garbage_collect(p, 2, reg, arity);
ASSERT(!((p->stop - 2) < p->htop));
}
p->stop -= 2;
diff --git a/erts/emulator/hipe/hipe_native_bif.c b/erts/emulator/hipe/hipe_native_bif.c
index 994f963ece..0ec417999b 100644
--- a/erts/emulator/hipe/hipe_native_bif.c
+++ b/erts/emulator/hipe/hipe_native_bif.c
@@ -80,7 +80,7 @@ Eterm hipe_show_nstack_1(BIF_ALIST_1)
void hipe_gc(Process *p, Eterm need)
{
hipe_set_narity(p, 1);
- p->fcalls -= erts_garbage_collect(p, unsigned_val(need), NULL, 0);
+ erts_garbage_collect(p, unsigned_val(need), NULL, 0);
hipe_set_narity(p, 0);
}
@@ -157,13 +157,22 @@ BIF_RETTYPE hipe_set_timeout(BIF_ALIST_1)
*/
void hipe_select_msg(Process *p)
{
- ErlMessage *msgp;
+ ErtsMessage *msgp;
msgp = PEEK_MESSAGE(p);
UNLINK_MESSAGE(p, msgp); /* decrements global 'erts_proc_tot_mem' variable */
JOIN_MESSAGE(p);
CANCEL_TIMER(p); /* calls erts_cancel_proc_timer() */
- free_message(msgp);
+ erts_save_message_in_proc(p, msgp);
+ p->flags &= ~F_DELAY_GC;
+ if (ERTS_IS_GC_DESIRED(p)) {
+ /*
+ * We want to GC soon but we leave a few
+ * reductions giving the message some time
+ * to turn into garbage.
+ */
+ ERTS_VBUMP_LEAVE_REDS(p, 5);
+ }
}
void hipe_fclearerror_error(Process *p)
@@ -520,8 +529,9 @@ BIF_RETTYPE hipe_is_divisible(BIF_ALIST_2)
*/
Eterm hipe_check_get_msg(Process *c_p)
{
- Eterm ret;
- ErlMessage *msgp;
+ ErtsMessage *msgp;
+
+ c_p->flags |= F_DELAY_GC;
next_message:
@@ -543,25 +553,29 @@ Eterm hipe_check_get_msg(Process *c_p)
/* XXX: BEAM doesn't need this */
c_p->hipe_smp.have_receive_locks = 1;
#endif
+ c_p->flags &= ~F_DELAY_GC;
return THE_NON_VALUE;
#ifdef ERTS_SMP
}
#endif
}
- ErtsMoveMsgAttachmentIntoProc(msgp, c_p, c_p->stop, HEAP_TOP(c_p),
- c_p->fcalls, (void) 0, (void) 0);
- ret = ERL_MESSAGE_TERM(msgp);
- if (is_non_value(ret)) {
+
+ if (is_non_value(ERL_MESSAGE_TERM(msgp))
+ && !erts_decode_dist_message(c_p, ERTS_PROC_LOCK_MAIN, msgp, 0)) {
/*
* A corrupt distribution message that we weren't able to decode;
* remove it...
*/
ASSERT(!msgp->data.attached);
UNLINK_MESSAGE(c_p, msgp);
- free_message(msgp);
+ msgp->next = NULL;
+ erts_cleanup_messages(msgp);
goto next_message;
}
- return ret;
+
+ ASSERT(is_value(ERL_MESSAGE_TERM(msgp)));
+
+ return ERL_MESSAGE_TERM(msgp);
}
/*
diff --git a/erts/emulator/hipe/hipe_x86_signal.c b/erts/emulator/hipe/hipe_x86_signal.c
index b7dae88417..0ecd13c4bc 100644
--- a/erts/emulator/hipe/hipe_x86_signal.c
+++ b/erts/emulator/hipe/hipe_x86_signal.c
@@ -38,9 +38,6 @@
*
* Our solution is to override the C library's signal handler setup
* procedure with our own which enforces the SA_ONSTACK flag.
- *
- * XXX: This code only supports Linux with glibc-2.1 or above,
- * and Solaris 8.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -55,27 +52,6 @@
#include "hipe_signal.h"
#if __GLIBC__ == 2 && (__GLIBC_MINOR__ >= 3)
-/* See comment below for glibc 2.2. */
-#ifndef __USE_GNU
-#define __USE_GNU /* to un-hide RTLD_NEXT */
-#endif
-#include <dlfcn.h>
-static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*);
-#define init_done() (__next_sigaction != 0)
-extern int __sigaction(int, const struct sigaction*, struct sigaction*);
-#define __SIGACTION __sigaction
-static void do_init(void)
-{
- __next_sigaction = dlsym(RTLD_NEXT, "__sigaction");
- if (__next_sigaction != 0)
- return;
- perror("dlsym");
- abort();
-}
-#define INIT() do { if (!init_done()) do_init(); } while (0)
-#endif /* glibc 2.3 */
-
-#if __GLIBC__ == 2 && (__GLIBC_MINOR__ == 2 /*|| __GLIBC_MINOR__ == 3*/)
/*
* __libc_sigaction() is the core routine.
* Without libpthread, sigaction() and __sigaction() are both aliases
@@ -100,65 +76,14 @@ static void do_init(void)
* old BSD or SysV interfaces.
* glibc's internal calls to __sigaction() appear to be mostly safe.
* hipe_signal_init() fixes some unsafe ones, e.g. the SIGPROF handler.
- *
- * Tested with glibc-2.1.92 on RedHat 7.0, glibc-2.2.2 on RedHat 7.1,
- * glibc-2.2.4 on RedHat 7.2, and glibc-2.2.5 on RedHat 7.3.
*/
-#if 0
-/* works with 2.2.5 and 2.2.4, but not 2.2.2 or 2.1.92 */
+#ifndef __USE_GNU
#define __USE_GNU /* to un-hide RTLD_NEXT */
-#include <dlfcn.h>
-static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*);
-#define init_done() (__next_sigaction != 0)
-#define __SIGACTION __sigaction
-static void do_init(void)
-{
- __next_sigaction = dlsym(RTLD_NEXT, "__sigaction");
- if (__next_sigaction != 0)
- return;
- perror("dlsym");
- abort();
-}
-#define INIT() do { if (!init_done()) do_init(); } while (0)
-#else
-/* semi-works with all 2.2 versions so far */
-extern int __sigaction(int, const struct sigaction*, struct sigaction*);
-#define __next_sigaction __sigaction /* pthreads-aware version */
-#undef __SIGACTION /* we can't override __sigaction() */
-#define INIT() do{}while(0)
#endif
-#endif /* glibc 2.2 */
-
-#if __GLIBC__ == 2 && __GLIBC_MINOR__ == 1
-/*
- * __sigaction() is the core routine.
- * Without libpthread, sigaction() is an alias for __sigaction().
- * libpthread redefines sigaction() as a non-trivial wrapper around
- * __sigaction().
- * glibc has internal calls to both sigaction() and __sigaction().
- *
- * Overriding __sigaction() would be ideal, but doing so breaks
- * libpthread (threads hang). Instead we override sigaction() and
- * use dlsym RTLD_NEXT to find glibc's version of sigaction().
- * glibc's internal calls to __sigaction() appear to be mostly safe.
- * hipe_signal_init() fixes some unsafe ones, e.g. the SIGPROF handler.
- *
- * Tested with glibc-2.1.3 on RedHat 6.2.
- */
-#include <dlfcn.h>
-static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*);
-#define init_done() (__next_sigaction != 0)
-#undef __SIGACTION
-static void do_init(void)
-{
- __next_sigaction = dlsym(RTLD_NEXT, "sigaction");
- if (__next_sigaction != 0)
- return;
- perror("dlsym");
- abort();
-}
-#define INIT() do { if (!init_done()) do_init(); } while (0)
-#endif /* glibc 2.1 */
+#define NEXT_SIGACTION "__sigaction"
+#define LIBC_SIGACTION __sigaction
+#define OVERRIDE_SIGACTION
+#endif /* glibc >= 2.3 */
/* Is there no standard identifier for Darwin/MacOSX ? */
#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__)
@@ -181,21 +106,10 @@ static void do_init(void)
* The other _sigaction, _sigaction_no_bind I don't understand the purpose
* of and don't modify.
*/
-#include <dlfcn.h>
-static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*);
-#define init_done() (__next_sigaction != 0)
-extern int _sigaction(int, const struct sigaction*, struct sigaction*);
-#define __SIGACTION _sigaction
-static void do_init(void)
-{
- __next_sigaction = dlsym(RTLD_NEXT, "sigaction");
- if (__next_sigaction != 0)
- return;
- perror("dlsym_darwin");
- abort();
-}
+#define NEXT_SIGACTION "sigaction"
+#define LIBC_SIGACTION _sigaction
+#undef OVERRIDE_SIGACTION
#define _NSIG NSIG
-#define INIT() do { if (!init_done()) do_init(); } while (0)
#endif /* __DARWIN__ */
#if defined(__sun__)
@@ -218,20 +132,10 @@ static void do_init(void)
* our init routine has had a chance to find _sigaction()'s address.
* This forces us to initialise at the first call.
*/
-#include <dlfcn.h>
-static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*);
-#define init_done() (__next_sigaction != 0)
-#define __SIGACTION _sigaction
-static void do_init(void)
-{
- __next_sigaction = dlsym(RTLD_NEXT, "_sigaction");
- if (__next_sigaction != 0)
- return;
- perror("dlsym");
- abort();
-}
+#define NEXT_SIGACTION "_sigaction"
+#define LIBC_SIGACTION _sigaction
+#define OVERRIDE_SIGACTION
#define _NSIG NSIG
-#define INIT() do { if (!init_done()) do_init(); } while (0)
#endif /* __sun__ */
#if defined(__FreeBSD__)
@@ -239,23 +143,22 @@ static void do_init(void)
* This is a copy of Darwin code for FreeBSD.
* CAVEAT: detailed semantics are not verified yet.
*/
-#include <dlfcn.h>
-static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*);
-#define init_done() (__next_sigaction != 0)
-extern int _sigaction(int, const struct sigaction*, struct sigaction*);
-#define __SIGACTION _sigaction
-static void do_init(void)
-{
- __next_sigaction = dlsym(RTLD_NEXT, "sigaction");
- if (__next_sigaction != 0)
- return;
- perror("dlsym_freebsd");
- abort();
-}
+#define NEXT_SIGACTION "sigaction"
+#define LIBC_SIGACTION _sigaction
+#undef OVERRIDE_SIGACTION
#define _NSIG NSIG
-#define INIT() do { if (!init_done()) do_init(); } while (0)
#endif /* __FreeBSD__ */
+#if defined(__NetBSD__)
+/*
+ * Note: This is only stub code to allow the build to succeed.
+ * Whether this actually provides the needed overrides for safe
+ * signal delivery or not is unknown.
+ */
+#undef NEXT_SIGACTION
+#undef OVERRIDE_SIGACTION
+#endif /* __NetBSD__ */
+
#if !(defined(__GLIBC__) || defined(__DARWIN__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__sun__))
/*
* Unknown libc -- assume musl. Note: musl deliberately does not provide a musl-specific
@@ -265,30 +168,40 @@ static void do_init(void)
* There are libc-internal calls to __libc_sigaction which install handlers, so we must
* override __libc_sigaction rather than __sigaction.
*/
+#define NEXT_SIGACTION "__libc_sigaction"
+#define LIBC_SIGACTION __libc_sigaction
+#define OVERRIDE_SIGACTION
+#ifndef _NSIG
+#define _NSIG NSIG
+#endif
+#endif /* !(__GLIBC__ || __DARWIN__ || __NetBSD__ || __FreeBSD__ || __sun__) */
+
+#if defined(NEXT_SIGACTION)
+/*
+ * Initialize a function pointer to the libc core sigaction routine,
+ * to be used by our wrappers.
+ */
#include <dlfcn.h>
-static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*);
-#define init_done() (__next_sigaction != 0)
-#define __SIGACTION __libc_sigaction
+static int (*next_sigaction)(int, const struct sigaction*, struct sigaction*);
static void do_init(void)
{
- __next_sigaction = dlsym(RTLD_NEXT, "__libc_sigaction");
- if (__next_sigaction != 0)
+ next_sigaction = dlsym(RTLD_NEXT, NEXT_SIGACTION);
+ if (next_sigaction != 0)
return;
perror("dlsym");
abort();
}
-#ifndef _NSIG
-#define _NSIG NSIG
-#endif
-#define INIT() do { if (!init_done()) do_init(); } while (0)
-#endif /* !(__GLIBC__ || __DARWIN__ || __NetBSD__ || __FreeBSD__ || __sun__) */
+#define INIT() do { if (!next_sigaction) do_init(); } while (0)
+#else /* !defined(NEXT_SIGACTION) */
+#define INIT() do { } while (0)
+#endif /* !defined(NEXT_SIGACTION) */
-#if !defined(__NetBSD__)
+#if defined(NEXT_SIGACTION)
/*
* This is our wrapper for sigaction(). sigaction() can be called before
* hipe_signal_init() has been executed, especially when threads support
* has been linked with the executable. Therefore, we must initialise
- * __next_sigaction() dynamically, the first time it's needed.
+ * next_sigaction() dynamically, the first time it's needed.
*/
static int my_sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
{
@@ -304,24 +217,26 @@ static int my_sigaction(int signum, const struct sigaction *act, struct sigactio
newact.sa_flags |= SA_ONSTACK;
act = &newact;
}
- return __next_sigaction(signum, act, oldact);
+ return next_sigaction(signum, act, oldact);
}
#endif
+
+#if defined(LIBC_SIGACTION)
/*
* This overrides the C library's core sigaction() procedure, catching
* all its internal calls.
*/
-#ifdef __SIGACTION
-int __SIGACTION(int signum, const struct sigaction *act, struct sigaction *oldact)
+extern int LIBC_SIGACTION(int, const struct sigaction*, struct sigaction*);
+int LIBC_SIGACTION(int signum, const struct sigaction *act, struct sigaction *oldact)
{
return my_sigaction(signum, act, oldact);
}
#endif
+#if defined(OVERRIDE_SIGACTION)
/*
* This catches the application's own sigaction() calls.
*/
-#if !defined(__DARWIN__) && !defined(__NetBSD__) && !defined(__FreeBSD__)
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
{
return my_sigaction(signum, act, oldact);
@@ -336,15 +251,11 @@ static void hipe_sigaltstack(void *ss_sp)
stack_t ss;
ss.ss_sp = ss_sp;
- ss.ss_flags = SS_ONSTACK;
+ ss.ss_flags = 0;
ss.ss_size = SIGSTKSZ;
if (sigaltstack(&ss, NULL) < 0) {
- /* might be a broken pre-2.4 Linux kernel, try harder */
- ss.ss_flags = 0;
- if (sigaltstack(&ss, NULL) < 0) {
- perror("sigaltstack");
- abort();
- }
+ perror("sigaltstack");
+ abort();
}
}
@@ -381,9 +292,7 @@ void hipe_signal_init(void)
struct sigaction sa;
int i;
-#ifndef __NetBSD__
INIT();
-#endif
hipe_sigaltstack_init();
diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c
index 105b129065..f87196d724 100644
--- a/erts/emulator/sys/common/erl_check_io.c
+++ b/erts/emulator/sys/common/erl_check_io.c
@@ -1337,11 +1337,7 @@ print_select_op(erts_dsprintf_buf_t *dsbufp,
{
Port *pp = erts_drvport2port(ix);
erts_dsprintf(dsbufp,
-#ifdef __OSE__
- "driver_select(%p, %d,%s%s%s%s | %d, %d) "
-#else
"driver_select(%p, %d,%s%s%s%s, %d) "
-#endif
"by ",
ix,
(int) GET_FD(fd),
@@ -1861,25 +1857,6 @@ stale_drv_select(Eterm id, ErtsDrvEventState *state, int mode)
#ifndef ERTS_SYS_CONTINOUS_FD_NUMBERS
-#ifdef __OSE__
-static SafeHashValue drv_ev_state_hash(void *des)
-{
- ErtsSysFdType fd = ((ErtsDrvEventState *) des)->fd;
- /* We use hash on signo ^ id in order for steal to happen when the
- same signo + fd is selected on by two different ports */
- SafeHashValue val = (SafeHashValue)(fd->signo ^ fd->id);
- return val ^ (val >> 8);
-}
-
-static int drv_ev_state_cmp(void *des1, void *des2)
-{
- ErtsSysFdType fd1 = ((ErtsDrvEventState *) des1)->fd;
- ErtsSysFdType fd2 = ((ErtsDrvEventState *) des2)->fd;
- if (fd1->signo == fd2->signo && fd1->id == fd2->id)
- return 0;
- return 1;
-}
-#else /* !__OSE__ && !ERTS_SYS_CONTINOUS_FD_NUMBERS i.e. probably windows */
static SafeHashValue drv_ev_state_hash(void *des)
{
SafeHashValue val = (SafeHashValue) ((ErtsDrvEventState *) des)->fd;
@@ -1891,7 +1868,6 @@ static int drv_ev_state_cmp(void *des1, void *des2)
return ( ((ErtsDrvEventState *) des1)->fd == ((ErtsDrvEventState *) des2)->fd
? 0 : 1);
}
-#endif
static void *drv_ev_state_alloc(void *des_tmpl)
{
diff --git a/erts/emulator/sys/common/erl_mmap.c b/erts/emulator/sys/common/erl_mmap.c
index 4180e65fdc..889d6f3868 100644
--- a/erts/emulator/sys/common/erl_mmap.c
+++ b/erts/emulator/sys/common/erl_mmap.c
@@ -51,23 +51,22 @@
#endif
/*
- * `mmap_state.sa.bot` and `mmap_state.sua.top` are read only after
+ * `mm->sa.bot` and `mm->sua.top` are read only after
* initialization, but the other pointers are not; i.e., only
* ERTS_MMAP_IN_SUPERCARRIER() is allowed without the mutex held.
*/
#define ERTS_MMAP_IN_SUPERCARRIER(PTR) \
- (((UWord) (PTR)) - ((UWord) mmap_state.sa.bot) \
- < ((UWord) mmap_state.sua.top) - ((UWord) mmap_state.sa.bot))
+ (((UWord) (PTR)) - ((UWord) mm->sa.bot) \
+ < ((UWord) mm->sua.top) - ((UWord) mm->sa.bot))
#define ERTS_MMAP_IN_SUPERALIGNED_AREA(PTR) \
- (ERTS_SMP_LC_ASSERT(erts_lc_mtx_is_locked(&mmap_state.mtx)), \
- (((UWord) (PTR)) - ((UWord) mmap_state.sa.bot) \
- < ((UWord) mmap_state.sa.top) - ((UWord) mmap_state.sa.bot)))
+ (ERTS_SMP_LC_ASSERT(erts_lc_mtx_is_locked(&mm->mtx)), \
+ (((UWord) (PTR)) - ((UWord) mm->sa.bot) \
+ < ((UWord) mm->sa.top) - ((UWord) mm->sa.bot)))
#define ERTS_MMAP_IN_SUPERUNALIGNED_AREA(PTR) \
- (ERTS_SMP_LC_ASSERT(erts_lc_mtx_is_locked(&mmap_state.mtx)), \
- (((UWord) (PTR)) - ((UWord) mmap_state.sua.bot) \
- < ((UWord) mmap_state.sua.top) - ((UWord) mmap_state.sua.bot)))
+ (ERTS_SMP_LC_ASSERT(erts_lc_mtx_is_locked(&mm->mtx)), \
+ (((UWord) (PTR)) - ((UWord) mm->sua.bot) \
+ < ((UWord) mm->sua.top) - ((UWord) mm->sua.bot)))
-int erts_have_erts_mmap;
UWord erts_page_inv_mask;
#if defined(DEBUG) || defined(ERTS_MMAP_DEBUG)
@@ -197,10 +196,10 @@ static ErtsMMapOp mmap_ops[ERTS_MMAP_OP_RINGBUF_SZ];
#define ERTS_MMAP_OP_LCK(RES, IN_SZ, OUT_SZ) \
do { \
- erts_smp_mtx_lock(&mmap_state.mtx); \
+ erts_smp_mtx_lock(&mm->mtx); \
ERTS_MMAP_OP_START((IN_SZ)); \
ERTS_MMAP_OP_END((RES), (OUT_SZ)); \
- erts_smp_mtx_unlock(&mmap_state.mtx); \
+ erts_smp_mtx_unlock(&mm->mtx); \
} while (0)
#define ERTS_MUNMAP_OP(PTR, SZ) \
@@ -219,9 +218,9 @@ static ErtsMMapOp mmap_ops[ERTS_MMAP_OP_RINGBUF_SZ];
#define ERTS_MUNMAP_OP_LCK(PTR, SZ) \
do { \
- erts_smp_mtx_lock(&mmap_state.mtx); \
+ erts_smp_mtx_lock(&mm->mtx); \
ERTS_MUNMAP_OP((PTR), (SZ)); \
- erts_smp_mtx_unlock(&mmap_state.mtx); \
+ erts_smp_mtx_unlock(&mm->mtx); \
} while (0)
#define ERTS_MREMAP_OP_START(OLD_PTR, OLD_SZ, IN_SZ) \
@@ -247,10 +246,10 @@ static ErtsMMapOp mmap_ops[ERTS_MMAP_OP_RINGBUF_SZ];
#define ERTS_MREMAP_OP_LCK(RES, OLD_PTR, OLD_SZ, IN_SZ, OUT_SZ) \
do { \
- erts_smp_mtx_lock(&mmap_state.mtx); \
+ erts_smp_mtx_lock(&mm->mtx); \
ERTS_MREMAP_OP_START((OLD_PTR), (OLD_SZ), (IN_SZ)); \
ERTS_MREMAP_OP_END((RES), (OUT_SZ)); \
- erts_smp_mtx_unlock(&mmap_state.mtx); \
+ erts_smp_mtx_unlock(&mm->mtx); \
} while (0)
#define ERTS_MMAP_OP_ABORT() \
@@ -294,7 +293,7 @@ typedef struct {
Uint nseg;
}ErtsFreeSegMap;
-static struct {
+struct ErtsMemMapper_ {
int (*reserve_physical)(char *, UWord);
void (*unreserve_physical)(char *, UWord);
int supercarrier;
@@ -346,54 +345,62 @@ static struct {
UWord used;
} os;
} size;
-} mmap_state;
+};
+
+ErtsMemMapper erts_dflt_mmapper;
+
+#if defined(ARCH_64) && defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+ErtsMemMapper erts_literal_mmapper;
+char* erts_literals_start;
+UWord erts_literals_size;
+#endif
#define ERTS_MMAP_SIZE_SC_SA_INC(SZ) \
do { \
- mmap_state.size.supercarrier.used.total += (SZ); \
- mmap_state.size.supercarrier.used.sa += (SZ); \
- ERTS_MMAP_ASSERT(mmap_state.size.supercarrier.used.total \
- <= mmap_state.size.supercarrier.total); \
- ERTS_MMAP_ASSERT(mmap_state.size.supercarrier.used.sa \
- <= mmap_state.size.supercarrier.used.total); \
+ mm->size.supercarrier.used.total += (SZ); \
+ mm->size.supercarrier.used.sa += (SZ); \
+ ERTS_MMAP_ASSERT(mm->size.supercarrier.used.total \
+ <= mm->size.supercarrier.total); \
+ ERTS_MMAP_ASSERT(mm->size.supercarrier.used.sa \
+ <= mm->size.supercarrier.used.total); \
} while (0)
#define ERTS_MMAP_SIZE_SC_SA_DEC(SZ) \
do { \
- ERTS_MMAP_ASSERT(mmap_state.size.supercarrier.used.total >= (SZ)); \
- mmap_state.size.supercarrier.used.total -= (SZ); \
- ERTS_MMAP_ASSERT(mmap_state.size.supercarrier.used.sa >= (SZ)); \
- mmap_state.size.supercarrier.used.sa -= (SZ); \
+ ERTS_MMAP_ASSERT(mm->size.supercarrier.used.total >= (SZ)); \
+ mm->size.supercarrier.used.total -= (SZ); \
+ ERTS_MMAP_ASSERT(mm->size.supercarrier.used.sa >= (SZ)); \
+ mm->size.supercarrier.used.sa -= (SZ); \
} while (0)
#define ERTS_MMAP_SIZE_SC_SUA_INC(SZ) \
do { \
- mmap_state.size.supercarrier.used.total += (SZ); \
- mmap_state.size.supercarrier.used.sua += (SZ); \
- ERTS_MMAP_ASSERT(mmap_state.size.supercarrier.used.total \
- <= mmap_state.size.supercarrier.total); \
- ERTS_MMAP_ASSERT(mmap_state.size.supercarrier.used.sua \
- <= mmap_state.size.supercarrier.used.total); \
+ mm->size.supercarrier.used.total += (SZ); \
+ mm->size.supercarrier.used.sua += (SZ); \
+ ERTS_MMAP_ASSERT(mm->size.supercarrier.used.total \
+ <= mm->size.supercarrier.total); \
+ ERTS_MMAP_ASSERT(mm->size.supercarrier.used.sua \
+ <= mm->size.supercarrier.used.total); \
} while (0)
#define ERTS_MMAP_SIZE_SC_SUA_DEC(SZ) \
do { \
- ERTS_MMAP_ASSERT(mmap_state.size.supercarrier.used.total >= (SZ)); \
- mmap_state.size.supercarrier.used.total -= (SZ); \
- ERTS_MMAP_ASSERT(mmap_state.size.supercarrier.used.sua >= (SZ)); \
- mmap_state.size.supercarrier.used.sua -= (SZ); \
+ ERTS_MMAP_ASSERT(mm->size.supercarrier.used.total >= (SZ)); \
+ mm->size.supercarrier.used.total -= (SZ); \
+ ERTS_MMAP_ASSERT(mm->size.supercarrier.used.sua >= (SZ)); \
+ mm->size.supercarrier.used.sua -= (SZ); \
} while (0)
#define ERTS_MMAP_SIZE_OS_INC(SZ) \
do { \
- ERTS_MMAP_ASSERT(mmap_state.size.os.used + (SZ) >= (SZ)); \
- mmap_state.size.os.used += (SZ); \
+ ERTS_MMAP_ASSERT(mm->size.os.used + (SZ) >= (SZ)); \
+ mm->size.os.used += (SZ); \
} while (0)
#define ERTS_MMAP_SIZE_OS_DEC(SZ) \
do { \
- ERTS_MMAP_ASSERT(mmap_state.size.os.used >= (SZ)); \
- mmap_state.size.os.used -= (SZ); \
+ ERTS_MMAP_ASSERT(mm->size.os.used >= (SZ)); \
+ mm->size.os.used -= (SZ); \
} while (0)
static void
-add_free_desc_area(char *start, char *end)
+add_free_desc_area(ErtsMemMapper* mm, char *start, char *end)
{
ERTS_MMAP_ASSERT(end == (void *) 0 || end > start);
if (sizeof(ErtsFreeSegDesc) <= ((UWord) end) - ((UWord) start)) {
@@ -403,7 +410,7 @@ add_free_desc_area(char *start, char *end)
no = 1;
prev_desc = (ErtsFreeSegDesc *) start;
- prev_desc->start = mmap_state.desc.free_list;
+ prev_desc->start = mm->desc.free_list;
desc = (ErtsFreeSegDesc *) (start + sizeof(ErtsFreeSegDesc));
desc_end = start + 2*sizeof(ErtsFreeSegDesc);
@@ -414,59 +421,59 @@ add_free_desc_area(char *start, char *end)
desc_end += sizeof(ErtsFreeSegDesc);
no++;
}
- mmap_state.desc.free_list = (char *) prev_desc;
- mmap_state.no.free_seg_descs += no;
+ mm->desc.free_list = (char *) prev_desc;
+ mm->no.free_seg_descs += no;
}
}
static ErtsFreeSegDesc *
-add_unused_free_desc_area(void)
+add_unused_free_desc_area(ErtsMemMapper* mm)
{
char *ptr;
- if (!mmap_state.desc.unused_start)
+ if (!mm->desc.unused_start)
return NULL;
- ERTS_MMAP_ASSERT(mmap_state.desc.unused_end);
+ ERTS_MMAP_ASSERT(mm->desc.unused_end);
ERTS_MMAP_ASSERT(ERTS_PAGEALIGNED_SIZE
- <= mmap_state.desc.unused_end - mmap_state.desc.unused_start);
+ <= mm->desc.unused_end - mm->desc.unused_start);
- ptr = mmap_state.desc.unused_start + ERTS_PAGEALIGNED_SIZE;
- add_free_desc_area(mmap_state.desc.unused_start, ptr);
+ ptr = mm->desc.unused_start + ERTS_PAGEALIGNED_SIZE;
+ add_free_desc_area(mm, mm->desc.unused_start, ptr);
- if ((mmap_state.desc.unused_end - ptr) >= ERTS_PAGEALIGNED_SIZE)
- mmap_state.desc.unused_start = ptr;
+ if ((mm->desc.unused_end - ptr) >= ERTS_PAGEALIGNED_SIZE)
+ mm->desc.unused_start = ptr;
else
- mmap_state.desc.unused_end = mmap_state.desc.unused_start = NULL;
+ mm->desc.unused_end = mm->desc.unused_start = NULL;
- ERTS_MMAP_ASSERT(mmap_state.desc.free_list);
- return (ErtsFreeSegDesc *) mmap_state.desc.free_list;
+ ERTS_MMAP_ASSERT(mm->desc.free_list);
+ return (ErtsFreeSegDesc *) mm->desc.free_list;
}
static ERTS_INLINE ErtsFreeSegDesc *
-alloc_desc(void)
+alloc_desc(ErtsMemMapper* mm)
{
ErtsFreeSegDesc *res;
- res = (ErtsFreeSegDesc *) mmap_state.desc.free_list;
+ res = (ErtsFreeSegDesc *) mm->desc.free_list;
if (!res) {
- res = add_unused_free_desc_area();
+ res = add_unused_free_desc_area(mm);
if (!res)
return NULL;
}
- mmap_state.desc.free_list = res->start;
- ASSERT(mmap_state.no.free_segs.curr < mmap_state.no.free_seg_descs);
- mmap_state.no.free_segs.curr++;
- if (mmap_state.no.free_segs.max < mmap_state.no.free_segs.curr)
- mmap_state.no.free_segs.max = mmap_state.no.free_segs.curr;
+ mm->desc.free_list = res->start;
+ ASSERT(mm->no.free_segs.curr < mm->no.free_seg_descs);
+ mm->no.free_segs.curr++;
+ if (mm->no.free_segs.max < mm->no.free_segs.curr)
+ mm->no.free_segs.max = mm->no.free_segs.curr;
return res;
}
static ERTS_INLINE void
-free_desc(ErtsFreeSegDesc *desc)
+free_desc(ErtsMemMapper* mm, ErtsFreeSegDesc *desc)
{
- desc->start = mmap_state.desc.free_list;
- mmap_state.desc.free_list = (char *) desc;
- ERTS_MMAP_ASSERT(mmap_state.no.free_segs.curr > 0);
- mmap_state.no.free_segs.curr--;
+ desc->start = mm->desc.free_list;
+ mm->desc.free_list = (char *) desc;
+ ERTS_MMAP_ASSERT(mm->no.free_segs.curr > 0);
+ mm->no.free_segs.curr--;
}
static ERTS_INLINE ErtsFreeSegDesc* anode_to_desc(RBTNode* anode)
@@ -1233,7 +1240,7 @@ Eterm build_free_seg_list(Process* p, ErtsFreeSegMap* map)
# define ERTS_MMAP_FD (-1)
# else
# define ERTS_MMAP_FLAGS (MAP_PRIVATE)
-# define ERTS_MMAP_FD mmap_state.mmap_fd
+# define ERTS_MMAP_FD mm->mmap_fd
# endif
#endif
@@ -1378,11 +1385,12 @@ static void unreserve_noop(char *ptr, UWord size)
}
static UWord
-alloc_desc_insert_free_seg(ErtsFreeSegMap *map, char* start, char* end)
+alloc_desc_insert_free_seg(ErtsMemMapper* mm,
+ ErtsFreeSegMap *map, char* start, char* end)
{
char *ptr;
ErtsFreeSegMap *da_map;
- ErtsFreeSegDesc *desc = alloc_desc();
+ ErtsFreeSegDesc *desc = alloc_desc(mm);
if (desc) {
insert_free_seg(map, desc, start, end);
return 0;
@@ -1395,13 +1403,13 @@ alloc_desc_insert_free_seg(ErtsFreeSegMap *map, char* start, char* end)
*/
#if ERTS_HAVE_OS_MMAP
- if (!mmap_state.no_os_mmap) {
- ptr = os_mmap(mmap_state.desc.new_area_hint, ERTS_PAGEALIGNED_SIZE, 0);
+ if (!mm->no_os_mmap) {
+ ptr = os_mmap(mm->desc.new_area_hint, ERTS_PAGEALIGNED_SIZE, 0);
if (ptr) {
- mmap_state.desc.new_area_hint = ptr+ERTS_PAGEALIGNED_SIZE;
+ mm->desc.new_area_hint = ptr+ERTS_PAGEALIGNED_SIZE;
ERTS_MMAP_SIZE_OS_INC(ERTS_PAGEALIGNED_SIZE);
- add_free_desc_area(ptr, ptr+ERTS_PAGEALIGNED_SIZE);
- desc = alloc_desc();
+ add_free_desc_area(mm, ptr, ptr+ERTS_PAGEALIGNED_SIZE);
+ desc = alloc_desc(mm);
ERTS_MMAP_ASSERT(desc);
insert_free_seg(map, desc, start, end);
return 0;
@@ -1412,20 +1420,20 @@ alloc_desc_insert_free_seg(ErtsFreeSegMap *map, char* start, char* end)
/*
* ...then try to find a good place in the supercarrier...
*/
- da_map = &mmap_state.sua.map;
+ da_map = &mm->sua.map;
desc = lookup_free_seg(da_map, ERTS_PAGEALIGNED_SIZE);
if (desc) {
- if (mmap_state.reserve_physical(desc->start, ERTS_PAGEALIGNED_SIZE))
+ if (mm->reserve_physical(desc->start, ERTS_PAGEALIGNED_SIZE))
ERTS_MMAP_SIZE_SC_SUA_INC(ERTS_PAGEALIGNED_SIZE);
else
desc = NULL;
}
else {
- da_map = &mmap_state.sa.map;
+ da_map = &mm->sa.map;
desc = lookup_free_seg(da_map, ERTS_PAGEALIGNED_SIZE);
if (desc) {
- if (mmap_state.reserve_physical(desc->start, ERTS_PAGEALIGNED_SIZE))
+ if (mm->reserve_physical(desc->start, ERTS_PAGEALIGNED_SIZE))
ERTS_MMAP_SIZE_SC_SA_INC(ERTS_PAGEALIGNED_SIZE);
else
desc = NULL;
@@ -1433,15 +1441,15 @@ alloc_desc_insert_free_seg(ErtsFreeSegMap *map, char* start, char* end)
}
if (desc) {
char *da_end = desc->start + ERTS_PAGEALIGNED_SIZE;
- add_free_desc_area(desc->start, da_end);
+ add_free_desc_area(mm, desc->start, da_end);
if (da_end != desc->end)
resize_free_seg(da_map, desc, da_end, desc->end);
else {
delete_free_seg(da_map, desc);
- free_desc(desc);
+ free_desc(mm, desc);
}
- desc = alloc_desc();
+ desc = alloc_desc(mm);
ERTS_MMAP_ASSERT(desc);
insert_free_seg(map, desc, start, end);
return 0;
@@ -1454,10 +1462,10 @@ alloc_desc_insert_free_seg(ErtsFreeSegMap *map, char* start, char* end)
ptr = start + ERTS_PAGEALIGNED_SIZE;
ERTS_MMAP_ASSERT(ptr <= end);
- add_free_desc_area(start, ptr);
+ add_free_desc_area(mm, start, ptr);
if (ptr != end) {
- desc = alloc_desc();
+ desc = alloc_desc(mm);
ERTS_MMAP_ASSERT(desc);
insert_free_seg(map, desc, ptr, end);
}
@@ -1466,46 +1474,46 @@ alloc_desc_insert_free_seg(ErtsFreeSegMap *map, char* start, char* end)
}
void *
-erts_mmap(Uint32 flags, UWord *sizep)
+erts_mmap(ErtsMemMapper* mm, Uint32 flags, UWord *sizep)
{
char *seg;
UWord asize = ERTS_PAGEALIGNED_CEILING(*sizep);
/* Map in premapped supercarrier */
- if (mmap_state.supercarrier && !(ERTS_MMAPFLG_OS_ONLY & flags)) {
+ if (mm->supercarrier && !(ERTS_MMAPFLG_OS_ONLY & flags)) {
char *end;
ErtsFreeSegDesc *desc;
Uint32 superaligned = (ERTS_MMAPFLG_SUPERALIGNED & flags);
- erts_smp_mtx_lock(&mmap_state.mtx);
+ erts_smp_mtx_lock(&mm->mtx);
ERTS_MMAP_OP_START(*sizep);
if (!superaligned) {
- desc = lookup_free_seg(&mmap_state.sua.map, asize);
+ desc = lookup_free_seg(&mm->sua.map, asize);
if (desc) {
seg = desc->start;
end = seg+asize;
- if (!mmap_state.reserve_physical(seg, asize))
+ if (!mm->reserve_physical(seg, asize))
goto supercarrier_reserve_failure;
if (desc->end == end) {
- delete_free_seg(&mmap_state.sua.map, desc);
- free_desc(desc);
+ delete_free_seg(&mm->sua.map, desc);
+ free_desc(mm, desc);
}
else {
ERTS_MMAP_ASSERT(end < desc->end);
- resize_free_seg(&mmap_state.sua.map, desc, end, desc->end);
+ resize_free_seg(&mm->sua.map, desc, end, desc->end);
}
ERTS_MMAP_SIZE_SC_SUA_INC(asize);
goto supercarrier_success;
}
- if (asize <= mmap_state.sua.bot - mmap_state.sa.top) {
- if (!mmap_state.reserve_physical(mmap_state.sua.bot - asize,
+ if (asize <= mm->sua.bot - mm->sa.top) {
+ if (!mm->reserve_physical(mm->sua.bot - asize,
asize))
goto supercarrier_reserve_failure;
- mmap_state.sua.bot -= asize;
- seg = mmap_state.sua.bot;
+ mm->sua.bot -= asize;
+ seg = mm->sua.bot;
ERTS_MMAP_SIZE_SC_SUA_INC(asize);
goto supercarrier_success;
}
@@ -1513,84 +1521,84 @@ erts_mmap(Uint32 flags, UWord *sizep)
asize = ERTS_SUPERALIGNED_CEILING(asize);
- desc = lookup_free_seg(&mmap_state.sa.map, asize);
+ desc = lookup_free_seg(&mm->sa.map, asize);
if (desc) {
char *start = seg = desc->start;
seg = (char *) ERTS_SUPERALIGNED_CEILING(seg);
end = seg+asize;
- if (!mmap_state.reserve_physical(start, (UWord) (end - start)))
+ if (!mm->reserve_physical(start, (UWord) (end - start)))
goto supercarrier_reserve_failure;
ERTS_MMAP_SIZE_SC_SA_INC(asize);
if (desc->end == end) {
if (start != seg)
- resize_free_seg(&mmap_state.sa.map, desc, start, seg);
+ resize_free_seg(&mm->sa.map, desc, start, seg);
else {
- delete_free_seg(&mmap_state.sa.map, desc);
- free_desc(desc);
+ delete_free_seg(&mm->sa.map, desc);
+ free_desc(mm, desc);
}
}
else {
ERTS_MMAP_ASSERT(end < desc->end);
- resize_free_seg(&mmap_state.sa.map, desc, end, desc->end);
+ resize_free_seg(&mm->sa.map, desc, end, desc->end);
if (start != seg) {
UWord ad_sz;
- ad_sz = alloc_desc_insert_free_seg(&mmap_state.sua.map,
+ ad_sz = alloc_desc_insert_free_seg(mm, &mm->sua.map,
start, seg);
start += ad_sz;
if (start != seg)
- mmap_state.unreserve_physical(start, (UWord) (seg - start));
+ mm->unreserve_physical(start, (UWord) (seg - start));
}
}
goto supercarrier_success;
}
if (superaligned) {
- char *start = mmap_state.sa.top;
+ char *start = mm->sa.top;
seg = (char *) ERTS_SUPERALIGNED_CEILING(start);
- if (asize + (seg - start) <= mmap_state.sua.bot - start) {
+ if (asize + (seg - start) <= mm->sua.bot - start) {
end = seg + asize;
- if (!mmap_state.reserve_physical(start, (UWord) (end - start)))
+ if (!mm->reserve_physical(start, (UWord) (end - start)))
goto supercarrier_reserve_failure;
- mmap_state.sa.top = end;
+ mm->sa.top = end;
ERTS_MMAP_SIZE_SC_SA_INC(asize);
if (start != seg) {
UWord ad_sz;
- ad_sz = alloc_desc_insert_free_seg(&mmap_state.sua.map,
+ ad_sz = alloc_desc_insert_free_seg(mm, &mm->sua.map,
start, seg);
start += ad_sz;
if (start != seg)
- mmap_state.unreserve_physical(start, (UWord) (seg - start));
+ mm->unreserve_physical(start, (UWord) (seg - start));
}
goto supercarrier_success;
}
- desc = lookup_free_seg(&mmap_state.sua.map, asize + ERTS_SUPERALIGNED_SIZE);
+ desc = lookup_free_seg(&mm->sua.map, asize + ERTS_SUPERALIGNED_SIZE);
if (desc) {
char *org_start = desc->start;
char *org_end = desc->end;
seg = (char *) ERTS_SUPERALIGNED_CEILING(org_start);
end = seg + asize;
- if (!mmap_state.reserve_physical(seg, (UWord) (org_end - seg)))
+ if (!mm->reserve_physical(seg, (UWord) (org_end - seg)))
goto supercarrier_reserve_failure;
ERTS_MMAP_SIZE_SC_SUA_INC(asize);
if (org_start != seg) {
ERTS_MMAP_ASSERT(org_start < seg);
- resize_free_seg(&mmap_state.sua.map, desc, org_start, seg);
+ resize_free_seg(&mm->sua.map, desc, org_start, seg);
desc = NULL;
}
if (end != org_end) {
UWord ad_sz = 0;
ERTS_MMAP_ASSERT(end < org_end);
if (desc)
- resize_free_seg(&mmap_state.sua.map, desc, end, org_end);
+ resize_free_seg(&mm->sua.map, desc, end, org_end);
else
- ad_sz = alloc_desc_insert_free_seg(&mmap_state.sua.map,
+ ad_sz = alloc_desc_insert_free_seg(mm, &mm->sua.map,
end, org_end);
end += ad_sz;
if (end != org_end)
- mmap_state.unreserve_physical(end,
+ mm->unreserve_physical(end,
(UWord) (org_end - end));
}
goto supercarrier_success;
@@ -1598,12 +1606,12 @@ erts_mmap(Uint32 flags, UWord *sizep)
}
ERTS_MMAP_OP_ABORT();
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ erts_smp_mtx_unlock(&mm->mtx);
}
#if ERTS_HAVE_OS_MMAP
/* Map using OS primitives */
- if (!(ERTS_MMAPFLG_SUPERCARRIER_ONLY & flags) && !mmap_state.no_os_mmap) {
+ if (!(ERTS_MMAPFLG_SUPERCARRIER_ONLY & flags) && !mm->no_os_mmap) {
if (!(ERTS_MMAPFLG_SUPERALIGNED & flags)) {
seg = os_mmap(NULL, asize, 0);
if (!seg)
@@ -1661,25 +1669,25 @@ supercarrier_success:
#endif
ERTS_MMAP_OP_END(seg, asize);
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ erts_smp_mtx_unlock(&mm->mtx);
*sizep = asize;
return (void *) seg;
supercarrier_reserve_failure:
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ erts_smp_mtx_unlock(&mm->mtx);
*sizep = 0;
return NULL;
}
void
-erts_munmap(Uint32 flags, void *ptr, UWord size)
+erts_munmap(ErtsMemMapper* mm, Uint32 flags, void *ptr, UWord size)
{
ERTS_MMAP_ASSERT(ERTS_IS_PAGEALIGNED(ptr));
ERTS_MMAP_ASSERT(ERTS_IS_PAGEALIGNED(size));
if (!ERTS_MMAP_IN_SUPERCARRIER(ptr)) {
- ERTS_MMAP_ASSERT(!mmap_state.no_os_mmap);
+ ERTS_MMAP_ASSERT(!mm->no_os_mmap);
#if ERTS_HAVE_OS_MMAP
ERTS_MUNMAP_OP_LCK(ptr, size);
ERTS_MMAP_SIZE_OS_DEC(size);
@@ -1692,45 +1700,45 @@ erts_munmap(Uint32 flags, void *ptr, UWord size)
ErtsFreeSegDesc *prev, *next, *desc;
UWord ad_sz = 0;
- ERTS_MMAP_ASSERT(mmap_state.supercarrier);
+ ERTS_MMAP_ASSERT(mm->supercarrier);
start = (char *) ptr;
end = start + size;
- erts_smp_mtx_lock(&mmap_state.mtx);
+ erts_smp_mtx_lock(&mm->mtx);
ERTS_MUNMAP_OP(ptr, size);
if (ERTS_MMAP_IN_SUPERALIGNED_AREA(ptr)) {
- map = &mmap_state.sa.map;
+ map = &mm->sa.map;
adjacent_free_seg(map, start, end, &prev, &next);
ERTS_MMAP_SIZE_SC_SA_DEC(size);
- if (end == mmap_state.sa.top) {
+ if (end == mm->sa.top) {
ERTS_MMAP_ASSERT(!next);
if (prev) {
start = prev->start;
delete_free_seg(map, prev);
- free_desc(prev);
+ free_desc(mm, prev);
}
- mmap_state.sa.top = start;
+ mm->sa.top = start;
goto supercarrier_success;
}
}
else {
- map = &mmap_state.sua.map;
+ map = &mm->sua.map;
adjacent_free_seg(map, start, end, &prev, &next);
ERTS_MMAP_SIZE_SC_SUA_DEC(size);
- if (start == mmap_state.sua.bot) {
+ if (start == mm->sua.bot) {
ERTS_MMAP_ASSERT(!prev);
if (next) {
end = next->end;
delete_free_seg(map, next);
- free_desc(next);
+ free_desc(mm, next);
}
- mmap_state.sua.bot = end;
+ mm->sua.bot = end;
goto supercarrier_success;
}
}
@@ -1742,7 +1750,7 @@ erts_munmap(Uint32 flags, void *ptr, UWord size)
end = next->end;
if (prev) {
delete_free_seg(map, next);
- free_desc(next);
+ free_desc(mm, next);
goto save_prev;
}
desc = next;
@@ -1756,7 +1764,7 @@ erts_munmap(Uint32 flags, void *ptr, UWord size)
if (desc)
resize_free_seg(map, desc, start, end);
else
- ad_sz = alloc_desc_insert_free_seg(map, start, end);
+ ad_sz = alloc_desc_insert_free_seg(mm, map, start, end);
supercarrier_success: {
UWord unres_sz;
@@ -1764,30 +1772,32 @@ erts_munmap(Uint32 flags, void *ptr, UWord size)
ERTS_MMAP_ASSERT(size >= ad_sz);
unres_sz = size - ad_sz;
if (unres_sz)
- mmap_state.unreserve_physical(((char *) ptr) + ad_sz, unres_sz);
+ mm->unreserve_physical(((char *) ptr) + ad_sz, unres_sz);
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ erts_smp_mtx_unlock(&mm->mtx);
}
}
}
static void *
-remap_move(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
+remap_move(ErtsMemMapper* mm,
+ Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
{
UWord size = *sizep;
- void *new_ptr = erts_mmap(flags, &size);
+ void *new_ptr = erts_mmap(mm, flags, &size);
if (!new_ptr)
return NULL;
*sizep = size;
if (old_size < size)
size = old_size;
sys_memcpy(new_ptr, ptr, (size_t) size);
- erts_munmap(flags, ptr, old_size);
+ erts_munmap(mm, flags, ptr, old_size);
return new_ptr;
}
void *
-erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
+erts_mremap(ErtsMemMapper* mm,
+ Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
{
void *new_ptr;
Uint32 superaligned;
@@ -1799,11 +1809,11 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
if (!ERTS_MMAP_IN_SUPERCARRIER(ptr)) {
- ERTS_MMAP_ASSERT(!mmap_state.no_os_mmap);
+ ERTS_MMAP_ASSERT(!mm->no_os_mmap);
- if (!(ERTS_MMAPFLG_OS_ONLY & flags) && mmap_state.supercarrier) {
- new_ptr = remap_move(ERTS_MMAPFLG_SUPERCARRIER_ONLY|flags, ptr,
- old_size, sizep);
+ if (!(ERTS_MMAPFLG_OS_ONLY & flags) && mm->supercarrier) {
+ new_ptr = remap_move(mm, ERTS_MMAPFLG_SUPERCARRIER_ONLY|flags,
+ ptr, old_size, sizep);
if (new_ptr)
return new_ptr;
}
@@ -1850,7 +1860,7 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
#endif
#if ERTS_HAVE_OS_MREMAP
if (superaligned)
- return remap_move(flags, new_ptr, old_size, sizep);
+ return remap_move(mm, flags, new_ptr, old_size, sizep);
else {
new_ptr = os_mremap(ptr, old_size, asize, 0);
if (!new_ptr)
@@ -1872,10 +1882,10 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
ErtsFreeSegDesc *prev, *next;
UWord ad_sz = 0;
- ERTS_MMAP_ASSERT(mmap_state.supercarrier);
+ ERTS_MMAP_ASSERT(mm->supercarrier);
if (ERTS_MMAPFLG_OS_ONLY & flags)
- return remap_move(flags, ptr, old_size, sizep);
+ return remap_move(mm, flags, ptr, old_size, sizep);
superaligned = (ERTS_MMAPFLG_SUPERALIGNED & flags);
@@ -1883,19 +1893,19 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
? ERTS_SUPERALIGNED_CEILING(*sizep)
: ERTS_PAGEALIGNED_CEILING(*sizep));
- erts_smp_mtx_lock(&mmap_state.mtx);
+ erts_smp_mtx_lock(&mm->mtx);
if (ERTS_MMAP_IN_SUPERALIGNED_AREA(ptr)
- ? (!superaligned && lookup_free_seg(&mmap_state.sua.map, asize))
- : (superaligned && lookup_free_seg(&mmap_state.sa.map, asize))) {
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ ? (!superaligned && lookup_free_seg(&mm->sua.map, asize))
+ : (superaligned && lookup_free_seg(&mm->sa.map, asize))) {
+ erts_smp_mtx_unlock(&mm->mtx);
/*
* Segment currently in wrong area (due to a previous memory
* shortage), move it to the right area.
* (remap_move() will succeed)
*/
- return remap_move(ERTS_MMAPFLG_SUPERCARRIER_ONLY|flags, ptr,
- old_size, sizep);
+ return remap_move(mm, ERTS_MMAPFLG_SUPERCARRIER_ONLY|flags,
+ ptr, old_size, sizep);
}
ERTS_MREMAP_OP_START(ptr, old_size, *sizep);
@@ -1917,18 +1927,18 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
UWord unres_sz;
new_ptr = ptr;
if (!ERTS_MMAP_IN_SUPERALIGNED_AREA(ptr)) {
- map = &mmap_state.sua.map;
+ map = &mm->sua.map;
ERTS_MMAP_SIZE_SC_SUA_DEC(old_size - asize);
}
else {
- if (end == mmap_state.sa.top) {
- mmap_state.sa.top = new_end;
- mmap_state.unreserve_physical(((char *) ptr) + asize,
+ if (end == mm->sa.top) {
+ mm->sa.top = new_end;
+ mm->unreserve_physical(((char *) ptr) + asize,
old_size - asize);
goto supercarrier_resize_success;
}
ERTS_MMAP_SIZE_SC_SA_DEC(old_size - asize);
- map = &mmap_state.sa.map;
+ map = &mm->sa.map;
}
adjacent_free_seg(map, start, end, &prev, &next);
@@ -1936,11 +1946,11 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
if (next)
resize_free_seg(map, next, new_end, next->end);
else
- ad_sz = alloc_desc_insert_free_seg(map, new_end, end);
+ ad_sz = alloc_desc_insert_free_seg(mm, map, new_end, end);
ERTS_MMAP_ASSERT(old_size - asize >= ad_sz);
unres_sz = old_size - asize - ad_sz;
if (unres_sz)
- mmap_state.unreserve_physical(((char *) ptr) + asize + ad_sz,
+ mm->unreserve_physical(((char *) ptr) + asize + ad_sz,
unres_sz);
goto supercarrier_resize_success;
}
@@ -1950,17 +1960,17 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
ERTS_MMAP_ASSERT(ERTS_IS_PAGEALIGNED(old_size));
ERTS_MMAP_ASSERT(ERTS_IS_PAGEALIGNED(asize));
- adjacent_free_seg(&mmap_state.sua.map, start, end, &prev, &next);
+ adjacent_free_seg(&mm->sua.map, start, end, &prev, &next);
if (next && new_end <= next->end) {
- if (!mmap_state.reserve_physical(((char *) ptr) + old_size,
+ if (!mm->reserve_physical(((char *) ptr) + old_size,
asize - old_size))
goto supercarrier_reserve_failure;
if (new_end < next->end)
- resize_free_seg(&mmap_state.sua.map, next, new_end, next->end);
+ resize_free_seg(&mm->sua.map, next, new_end, next->end);
else {
- delete_free_seg(&mmap_state.sua.map, next);
- free_desc(next);
+ delete_free_seg(&mm->sua.map, next);
+ free_desc(mm, next);
}
new_ptr = ptr;
ERTS_MMAP_SIZE_SC_SUA_INC(asize - old_size);
@@ -1969,28 +1979,28 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
}
else { /* Superaligned area */
- if (end == mmap_state.sa.top) {
- if (new_end <= mmap_state.sua.bot) {
- if (!mmap_state.reserve_physical(((char *) ptr) + old_size,
+ if (end == mm->sa.top) {
+ if (new_end <= mm->sua.bot) {
+ if (!mm->reserve_physical(((char *) ptr) + old_size,
asize - old_size))
goto supercarrier_reserve_failure;
- mmap_state.sa.top = new_end;
+ mm->sa.top = new_end;
new_ptr = ptr;
ERTS_MMAP_SIZE_SC_SA_INC(asize - old_size);
goto supercarrier_resize_success;
}
}
else {
- adjacent_free_seg(&mmap_state.sa.map, start, end, &prev, &next);
+ adjacent_free_seg(&mm->sa.map, start, end, &prev, &next);
if (next && new_end <= next->end) {
- if (!mmap_state.reserve_physical(((char *) ptr) + old_size,
+ if (!mm->reserve_physical(((char *) ptr) + old_size,
asize - old_size))
goto supercarrier_reserve_failure;
if (new_end < next->end)
- resize_free_seg(&mmap_state.sa.map, next, new_end, next->end);
+ resize_free_seg(&mm->sa.map, next, new_end, next->end);
else {
- delete_free_seg(&mmap_state.sa.map, next);
- free_desc(next);
+ delete_free_seg(&mm->sa.map, next);
+ free_desc(mm, next);
}
new_ptr = ptr;
ERTS_MMAP_SIZE_SC_SA_INC(asize - old_size);
@@ -2000,12 +2010,12 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
}
ERTS_MMAP_OP_ABORT();
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ erts_smp_mtx_unlock(&mm->mtx);
/* Failed to resize... */
}
- return remap_move(flags, ptr, old_size, sizep);
+ return remap_move(mm, flags, ptr, old_size, sizep);
supercarrier_resize_success:
@@ -2022,25 +2032,24 @@ supercarrier_resize_success:
#endif
ERTS_MREMAP_OP_END(new_ptr, asize);
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ erts_smp_mtx_unlock(&mm->mtx);
*sizep = asize;
return new_ptr;
supercarrier_reserve_failure:
ERTS_MREMAP_OP_END(NULL, old_size);
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ erts_smp_mtx_unlock(&mm->mtx);
*sizep = old_size;
return NULL;
}
-int erts_mmap_in_supercarrier(void *ptr)
+int erts_mmap_in_supercarrier(ErtsMemMapper* mm, void *ptr)
{
return ERTS_MMAP_IN_SUPERCARRIER(ptr);
}
-
static struct {
Eterm total;
Eterm total_sa;
@@ -2103,8 +2112,9 @@ static void hard_dbg_mseg_init(void);
#endif
void
-erts_mmap_init(ErtsMMapInit *init)
+erts_mmap_init(ErtsMemMapper* mm, ErtsMMapInit *init)
{
+ static int is_first_call = 1;
int virtual_map = 0;
char *start = NULL, *end = NULL;
UWord pagesize;
@@ -2131,20 +2141,20 @@ erts_mmap_init(ErtsMMapInit *init)
ERTS_MMAP_OP_RINGBUF_INIT();
- erts_have_erts_mmap = 0;
-
- mmap_state.supercarrier = 0;
- mmap_state.reserve_physical = reserve_noop;
- mmap_state.unreserve_physical = unreserve_noop;
+ mm->supercarrier = 0;
+ mm->reserve_physical = reserve_noop;
+ mm->unreserve_physical = unreserve_noop;
#if HAVE_MMAP && !defined(MAP_ANON)
- mmap_state.mmap_fd = open("/dev/zero", O_RDWR);
- if (mmap_state.mmap_fd < 0)
+ mm->mmap_fd = open("/dev/zero", O_RDWR);
+ if (mm->mmap_fd < 0)
erts_exit(1, "erts_mmap: Failed to open /dev/zero\n");
#endif
- erts_smp_mtx_init(&mmap_state.mtx, "erts_mmap");
- erts_mtx_init(&am.init_mutex, "mmap_init_atoms");
+ erts_smp_mtx_init(&mm->mtx, "erts_mmap");
+ if (is_first_call) {
+ erts_mtx_init(&am.init_mutex, "mmap_init_atoms");
+ }
#ifdef ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION
if (init->virtual_range.start) {
@@ -2160,8 +2170,8 @@ erts_mmap_init(ErtsMMapInit *init)
sz = start - ptr;
if (sz)
os_munmap(end, sz);
- mmap_state.reserve_physical = os_reserve_physical;
- mmap_state.unreserve_physical = os_unreserve_physical;
+ mm->reserve_physical = os_reserve_physical;
+ mm->unreserve_physical = os_unreserve_physical;
virtual_map = 1;
}
else
@@ -2179,8 +2189,8 @@ erts_mmap_init(ErtsMMapInit *init)
#ifdef ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION
if (!init->scrpm) {
start = os_mmap_virtual(NULL, sz);
- mmap_state.reserve_physical = os_reserve_physical;
- mmap_state.unreserve_physical = os_unreserve_physical;
+ mm->reserve_physical = os_reserve_physical;
+ mm->unreserve_physical = os_unreserve_physical;
virtual_map = 1;
}
else
@@ -2206,34 +2216,32 @@ erts_mmap_init(ErtsMMapInit *init)
}
#endif
}
- if (!mmap_state.no_os_mmap)
- erts_have_erts_mmap |= ERTS_HAVE_ERTS_OS_MMAP;
#endif
- mmap_state.no.free_seg_descs = 0;
- mmap_state.no.free_segs.curr = 0;
- mmap_state.no.free_segs.max = 0;
+ mm->no.free_seg_descs = 0;
+ mm->no.free_segs.curr = 0;
+ mm->no.free_segs.max = 0;
- mmap_state.size.supercarrier.total = 0;
- mmap_state.size.supercarrier.used.total = 0;
- mmap_state.size.supercarrier.used.sa = 0;
- mmap_state.size.supercarrier.used.sua = 0;
- mmap_state.size.os.used = 0;
+ mm->size.supercarrier.total = 0;
+ mm->size.supercarrier.used.total = 0;
+ mm->size.supercarrier.used.sa = 0;
+ mm->size.supercarrier.used.sua = 0;
+ mm->size.os.used = 0;
- mmap_state.desc.new_area_hint = NULL;
+ mm->desc.new_area_hint = NULL;
if (!start) {
- mmap_state.sa.bot = NULL;
- mmap_state.sua.top = NULL;
- mmap_state.sa.bot = NULL;
- mmap_state.sua.top = NULL;
- mmap_state.no_os_mmap = 0;
- mmap_state.supercarrier = 0;
+ mm->sa.bot = NULL;
+ mm->sua.top = NULL;
+ mm->sa.bot = NULL;
+ mm->sua.top = NULL;
+ mm->no_os_mmap = 0;
+ mm->supercarrier = 0;
}
else {
size_t desc_size;
- mmap_state.no_os_mmap = init->sco;
+ mm->no_os_mmap = init->sco;
desc_size = init->scrfsd;
if (desc_size < 100)
@@ -2244,66 +2252,73 @@ erts_mmap_init(ErtsMMapInit *init)
+ ERTS_PAGEALIGNED_SIZE) > end - start)
erts_exit(1, "erts_mmap: No space for segments in super carrier\n");
- mmap_state.sa.bot = start;
- mmap_state.sa.bot += desc_size;
- mmap_state.sa.bot = (char *) ERTS_SUPERALIGNED_CEILING(mmap_state.sa.bot);
- mmap_state.sa.top = mmap_state.sa.bot;
- mmap_state.sua.top = end;
- mmap_state.sua.bot = mmap_state.sua.top;
+ mm->sa.bot = start;
+ mm->sa.bot += desc_size;
+ mm->sa.bot = (char *) ERTS_SUPERALIGNED_CEILING(mm->sa.bot);
+ mm->sa.top = mm->sa.bot;
+ mm->sua.top = end;
+ mm->sua.bot = mm->sua.top;
- mmap_state.size.supercarrier.used.total += (UWord) (mmap_state.sa.bot - start);
+ mm->size.supercarrier.used.total += (UWord) (mm->sa.bot - start);
- mmap_state.desc.free_list = NULL;
- mmap_state.desc.reserved = 0;
+ mm->desc.free_list = NULL;
+ mm->desc.reserved = 0;
if (end == (void *) 0) {
/*
* Very unlikely, but we need a guarantee
- * that `mmap_state.sua.top` always will
+ * that `mm->sua.top` always will
* compare as larger than all segment pointers
* into the super carrier...
*/
- mmap_state.sua.top -= ERTS_PAGEALIGNED_SIZE;
- mmap_state.size.supercarrier.used.total += ERTS_PAGEALIGNED_SIZE;
+ mm->sua.top -= ERTS_PAGEALIGNED_SIZE;
+ mm->size.supercarrier.used.total += ERTS_PAGEALIGNED_SIZE;
#ifdef ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION
- if (!virtual_map || os_reserve_physical(mmap_state.sua.top, ERTS_PAGEALIGNED_SIZE))
+ if (!virtual_map || os_reserve_physical(mm->sua.top, ERTS_PAGEALIGNED_SIZE))
#endif
- add_free_desc_area(mmap_state.sua.top, end);
- mmap_state.desc.reserved += (end - mmap_state.sua.top) / sizeof(ErtsFreeSegDesc);
+ add_free_desc_area(mm, mm->sua.top, end);
+ mm->desc.reserved += (end - mm->sua.top) / sizeof(ErtsFreeSegDesc);
}
- mmap_state.size.supercarrier.total = (UWord) (mmap_state.sua.top - start);
+ mm->size.supercarrier.total = (UWord) (mm->sua.top - start);
/*
* Area before (and after) super carrier
* will be used for free segment descritors.
*/
#ifdef ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION
- if (virtual_map && !os_reserve_physical(start, mmap_state.sa.bot - start))
+ if (virtual_map && !os_reserve_physical(start, mm->sa.bot - start))
erts_exit(1, "erts_mmap: Failed to reserve physical memory for descriptors\n");
#endif
- mmap_state.desc.unused_start = start;
- mmap_state.desc.unused_end = mmap_state.sa.bot;
- mmap_state.desc.reserved += ((mmap_state.desc.unused_end - start)
+ mm->desc.unused_start = start;
+ mm->desc.unused_end = mm->sa.bot;
+ mm->desc.reserved += ((mm->desc.unused_end - start)
/ sizeof(ErtsFreeSegDesc));
- init_free_seg_map(&mmap_state.sa.map, SA_SZ_ADDR_ORDER);
- init_free_seg_map(&mmap_state.sua.map, SZ_REVERSE_ADDR_ORDER);
+ init_free_seg_map(&mm->sa.map, SA_SZ_ADDR_ORDER);
+ init_free_seg_map(&mm->sua.map, SZ_REVERSE_ADDR_ORDER);
- mmap_state.supercarrier = 1;
- erts_have_erts_mmap |= ERTS_HAVE_ERTS_SUPERCARRIER_MMAP;
+ mm->supercarrier = 1;
- mmap_state.desc.new_area_hint = end;
+ mm->desc.new_area_hint = end;
}
#if !ERTS_HAVE_OS_MMAP
- mmap_state.no_os_mmap = 1;
+ mm->no_os_mmap = 1;
#endif
#ifdef HARD_DEBUG_MSEG
hard_dbg_mseg_init();
#endif
+
+#if defined(ARCH_64) && defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+ if (mm == &erts_literal_mmapper) {
+ erts_literals_start = erts_literal_mmapper.sa.bot;
+ erts_literals_size = erts_literal_mmapper.sua.top - erts_literals_start;
+ }
+#endif
+ is_first_call = 0;
}
@@ -2313,7 +2328,8 @@ add_2tup(Uint **hpp, Uint *szp, Eterm *lp, Eterm el1, Eterm el2)
*lp = erts_bld_cons(hpp, szp, erts_bld_tuple(hpp, szp, 2, el1, el2), *lp);
}
-Eterm erts_mmap_info(int *print_to_p,
+Eterm erts_mmap_info(ErtsMemMapper* mm,
+ int *print_to_p,
void *print_to_arg,
Eterm** hpp, Uint* szp,
struct erts_mmap_info_struct* emis)
@@ -2328,29 +2344,29 @@ Eterm erts_mmap_info(int *print_to_p,
Eterm res = THE_NON_VALUE;
if (!hpp) {
- erts_smp_mtx_lock(&mmap_state.mtx);
- emis->sizes[0] = mmap_state.size.supercarrier.total;
- emis->sizes[1] = mmap_state.sa.top - mmap_state.sa.bot;
- emis->sizes[2] = mmap_state.sua.top - mmap_state.sua.bot;
- emis->sizes[3] = mmap_state.size.supercarrier.used.total;
- emis->sizes[4] = mmap_state.size.supercarrier.used.sa;
- emis->sizes[5] = mmap_state.size.supercarrier.used.sua;
+ erts_smp_mtx_lock(&mm->mtx);
+ emis->sizes[0] = mm->size.supercarrier.total;
+ emis->sizes[1] = mm->sa.top - mm->sa.bot;
+ emis->sizes[2] = mm->sua.top - mm->sua.bot;
+ emis->sizes[3] = mm->size.supercarrier.used.total;
+ emis->sizes[4] = mm->size.supercarrier.used.sa;
+ emis->sizes[5] = mm->size.supercarrier.used.sua;
- emis->segs[0] = mmap_state.no.free_segs.curr;
- emis->segs[1] = mmap_state.no.free_segs.max;
- emis->segs[2] = mmap_state.no.free_seg_descs;
- emis->segs[3] = mmap_state.desc.reserved;
- emis->segs[4] = mmap_state.sa.map.nseg;
- emis->segs[5] = mmap_state.sua.map.nseg;
+ emis->segs[0] = mm->no.free_segs.curr;
+ emis->segs[1] = mm->no.free_segs.max;
+ emis->segs[2] = mm->no.free_seg_descs;
+ emis->segs[3] = mm->desc.reserved;
+ emis->segs[4] = mm->sa.map.nseg;
+ emis->segs[5] = mm->sua.map.nseg;
- emis->os_used = mmap_state.size.os.used;
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ emis->os_used = mm->size.os.used;
+ erts_smp_mtx_unlock(&mm->mtx);
}
if (print_to_p) {
int to = *print_to_p;
void *arg = print_to_arg;
- if (mmap_state.supercarrier) {
+ if (mm->supercarrier) {
const char* prefix = "supercarrier ";
erts_print(to, arg, "%stotal size: %bpu\n", prefix, emis->sizes[0]);
erts_print(to, arg, "%stotal sa size: %bpu\n", prefix, emis->sizes[1]);
@@ -2365,7 +2381,7 @@ Eterm erts_mmap_info(int *print_to_p,
erts_print(to, arg, "%ssa free segs: %bpu\n", prefix, emis->segs[4]);
erts_print(to, arg, "%ssua free segs: %bpu\n", prefix, emis->segs[5]);
}
- if (!mmap_state.no_os_mmap) {
+ if (!mm->no_os_mmap) {
erts_print(to, arg, "os mmap size used: %bpu\n", emis->os_used);
}
}
@@ -2377,7 +2393,7 @@ Eterm erts_mmap_info(int *print_to_p,
}
lix = 0;
- if (mmap_state.supercarrier) {
+ if (mm->supercarrier) {
group[0] = erts_bld_atom_uword_2tup_list(hpp, szp,
sizeof(size_tags)/sizeof(Eterm),
size_tags, emis->sizes);
@@ -2389,7 +2405,7 @@ Eterm erts_mmap_info(int *print_to_p,
lix++;
}
- if (!mmap_state.no_os_mmap) {
+ if (!mm->no_os_mmap) {
group[0] = erts_bld_atom_uword_2tup_list(hpp, szp,
1, &am.used, &emis->os_used);
list[lix] = erts_bld_2tup_list(hpp, szp, 1, group_tags, group);
@@ -2401,25 +2417,26 @@ Eterm erts_mmap_info(int *print_to_p,
return res;
}
-Eterm erts_mmap_info_options(char *prefix,
+Eterm erts_mmap_info_options(ErtsMemMapper* mm,
+ char *prefix,
int *print_to_p,
void *print_to_arg,
Uint **hpp,
Uint *szp)
{
- const UWord scs = mmap_state.sua.top - mmap_state.sa.bot;
- const Eterm sco = mmap_state.no_os_mmap ? am_true : am_false;
- const Eterm scrpm = (mmap_state.reserve_physical == reserve_noop) ? am_true : am_false;
+ const UWord scs = mm->sua.top - mm->sa.bot;
+ const Eterm sco = mm->no_os_mmap ? am_true : am_false;
+ const Eterm scrpm = (mm->reserve_physical == reserve_noop) ? am_true : am_false;
Eterm res = THE_NON_VALUE;
if (print_to_p) {
int to = *print_to_p;
void *arg = print_to_arg;
erts_print(to, arg, "%sscs: %bpu\n", prefix, scs);
- if (mmap_state.supercarrier) {
+ if (mm->supercarrier) {
erts_print(to, arg, "%ssco: %T\n", prefix, sco);
erts_print(to, arg, "%sscrpm: %T\n", prefix, scrpm);
- erts_print(to, arg, "%sscrfsd: %beu\n", prefix, mmap_state.desc.reserved);
+ erts_print(to, arg, "%sscrfsd: %beu\n", prefix, mm->desc.reserved);
}
}
@@ -2429,9 +2446,9 @@ Eterm erts_mmap_info_options(char *prefix,
}
res = NIL;
- if (mmap_state.supercarrier) {
+ if (mm->supercarrier) {
add_2tup(hpp, szp, &res, am.scrfsd,
- erts_bld_uint(hpp,szp, mmap_state.desc.reserved));
+ erts_bld_uint(hpp,szp, mm->desc.reserved));
add_2tup(hpp, szp, &res, am.scrpm, scrpm);
add_2tup(hpp, szp, &res, am.sco, sco);
}
@@ -2441,9 +2458,9 @@ Eterm erts_mmap_info_options(char *prefix,
}
-Eterm erts_mmap_debug_info(Process* p)
+Eterm erts_mmap_debug_info(ErtsMemMapper* mm, Process* p)
{
- if (mmap_state.supercarrier) {
+ if (mm->supercarrier) {
ERTS_DECL_AM(sabot);
ERTS_DECL_AM(satop);
ERTS_DECL_AM(suabot);
@@ -2453,18 +2470,17 @@ Eterm erts_mmap_debug_info(Process* p)
UWord values[4];
Eterm *hp, *hp_end;
Uint may_need;
- const Uint PTR_BIG_SZ = HALFWORD_HEAP ? 3 : 2;
-
- erts_smp_mtx_lock(&mmap_state.mtx);
- values[0] = (UWord)mmap_state.sa.bot;
- values[1] = (UWord)mmap_state.sa.top;
- values[2] = (UWord)mmap_state.sua.bot;
- values[3] = (UWord)mmap_state.sua.top;
- sa_list = build_free_seg_list(p, &mmap_state.sa.map);
- sua_list = build_free_seg_list(p, &mmap_state.sua.map);
- erts_smp_mtx_unlock(&mmap_state.mtx);
-
- may_need = 4*(2+3+PTR_BIG_SZ) + 2*(2+3);
+
+ erts_smp_mtx_lock(&mm->mtx);
+ values[0] = (UWord)mm->sa.bot;
+ values[1] = (UWord)mm->sa.top;
+ values[2] = (UWord)mm->sua.bot;
+ values[3] = (UWord)mm->sua.top;
+ sa_list = build_free_seg_list(p, &mm->sa.map);
+ sua_list = build_free_seg_list(p, &mm->sua.map);
+ erts_smp_mtx_unlock(&mm->mtx);
+
+ may_need = 4*(2+3+2) + 2*(2+3);
hp = HAlloc(p, may_need);
hp_end = hp + may_need;
diff --git a/erts/emulator/sys/common/erl_mmap.h b/erts/emulator/sys/common/erl_mmap.h
index 66619c5161..67e131b53e 100644
--- a/erts/emulator/sys/common/erl_mmap.h
+++ b/erts/emulator/sys/common/erl_mmap.h
@@ -30,9 +30,6 @@
#define ERTS_MMAPFLG_SUPERCARRIER_ONLY (((Uint32) 1) << 1)
#define ERTS_MMAPFLG_SUPERALIGNED (((Uint32) 1) << 2)
-#define ERTS_HAVE_ERTS_OS_MMAP (1 << 0)
-#define ERTS_HAVE_ERTS_SUPERCARRIER_MMAP (1 << 1)
-extern int erts_have_erts_mmap;
extern UWord erts_page_inv_mask;
typedef struct {
@@ -53,23 +50,31 @@ typedef struct {
#define ERTS_MMAP_INIT_DEFAULT_INITER \
{{NULL, NULL}, {NULL, NULL}, 0, 1, (1 << 16), 1}
-void *erts_mmap(Uint32 flags, UWord *sizep);
-void erts_munmap(Uint32 flags, void *ptr, UWord size);
-void *erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep);
-int erts_mmap_in_supercarrier(void *ptr);
-void erts_mmap_init(ErtsMMapInit*);
+#define ERTS_LITERAL_VIRTUAL_AREA_SIZE (UWORD_CONSTANT(1)*1024*1024*1024)
+
+#define ERTS_MMAP_INIT_LITERAL_INITER \
+ {{NULL, NULL}, {NULL, NULL}, ERTS_LITERAL_VIRTUAL_AREA_SIZE, 1, (1 << 16), 0}
+
+typedef struct ErtsMemMapper_ ErtsMemMapper;
+
+void *erts_mmap(ErtsMemMapper*, Uint32 flags, UWord *sizep);
+void erts_munmap(ErtsMemMapper*, Uint32 flags, void *ptr, UWord size);
+void *erts_mremap(ErtsMemMapper*, Uint32 flags, void *ptr, UWord old_size, UWord *sizep);
+int erts_mmap_in_supercarrier(ErtsMemMapper*, void *ptr);
+void erts_mmap_init(ErtsMemMapper*, ErtsMMapInit*);
struct erts_mmap_info_struct
{
UWord sizes[6];
UWord segs[6];
UWord os_used;
};
-Eterm erts_mmap_info(int *print_to_p, void *print_to_arg,
+Eterm erts_mmap_info(ErtsMemMapper*, int *print_to_p, void *print_to_arg,
Eterm** hpp, Uint* szp, struct erts_mmap_info_struct*);
-Eterm erts_mmap_info_options(char *prefix, int *print_to_p, void *print_to_arg,
+Eterm erts_mmap_info_options(ErtsMemMapper*,
+ char *prefix, int *print_to_p, void *print_to_arg,
Uint **hpp, Uint *szp);
struct process;
-Eterm erts_mmap_debug_info(struct process*);
+Eterm erts_mmap_debug_info(ErtsMemMapper*, struct process*);
#define ERTS_SUPERALIGNED_SIZE \
(1 << ERTS_MMAP_SUPERALIGNED_BITS)
@@ -121,6 +126,11 @@ Eterm erts_mmap_debug_info(struct process*);
# define ERTS_HAVE_OS_MMAP 1
#endif
+extern ErtsMemMapper erts_dflt_mmapper;
+#if defined(ARCH_64) && defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+extern ErtsMemMapper erts_literal_mmapper;
+#endif
+
/*#define HARD_DEBUG_MSEG*/
#ifdef HARD_DEBUG_MSEG
# define HARD_DBG_INSERT_MSEG hard_dbg_insert_mseg
diff --git a/erts/emulator/sys/common/erl_mseg.c b/erts/emulator/sys/common/erl_mseg.c
index 3398be2b07..286130bece 100644
--- a/erts/emulator/sys/common/erl_mseg.c
+++ b/erts/emulator/sys/common/erl_mseg.c
@@ -99,17 +99,12 @@ static const int debruijn[32] = {
static int atoms_initialized;
-typedef struct mem_kind_t MemKind;
-
const ErtsMsegOpt_t erts_mseg_default_opt = {
1, /* Use cache */
1, /* Preserv data */
0, /* Absolute shrink threshold */
0, /* Relative shrink threshold */
0 /* Scheduler specific */
-#if HALFWORD_HEAP
- ,0 /* need low memory */
-#endif
};
@@ -142,7 +137,14 @@ struct cache_t_ {
typedef struct ErtsMsegAllctr_t_ ErtsMsegAllctr_t;
-struct mem_kind_t {
+struct ErtsMsegAllctr_t_ {
+ int ix;
+
+ int is_init_done;
+ int is_thread_safe;
+ erts_mtx_t mtx;
+
+ int is_cache_check_scheduled;
cache_t cache[MAX_CACHE_SIZE];
cache_t cache_unpowered_node;
@@ -168,29 +170,6 @@ struct mem_kind_t {
} max_ever;
} segments;
- ErtsMsegAllctr_t *ma;
- const char* name;
- MemKind* next;
-};/*MemKind*/
-
-struct ErtsMsegAllctr_t_ {
- int ix;
-
- int is_init_done;
- int is_thread_safe;
- erts_mtx_t mtx;
-
- int is_cache_check_scheduled;
-
- MemKind* mk_list;
-
-#if HALFWORD_HEAP
- MemKind low_mem;
- MemKind hi_mem;
-#else
- MemKind the_mem;
-#endif
-
Uint max_cache_size;
Uint abs_max_cache_bad_fit;
Uint rel_max_cache_bad_fit;
@@ -302,22 +281,17 @@ schedule_cache_check(ErtsMsegAllctr_t *ma) {
/* #define ERTS_PRINT_ERTS_MMAP */
static ERTS_INLINE void *
-mseg_create(ErtsMsegAllctr_t *ma, Uint flags, MemKind* mk, UWord *sizep)
+mseg_create(ErtsMsegAllctr_t *ma, Uint flags, UWord *sizep)
{
#ifdef ERTS_PRINT_ERTS_MMAP
UWord req_size = *sizep;
#endif
void *seg;
Uint32 mmap_flags = 0;
-#if HALFWORD_HEAP
- mmap_flags |= ((mk == &ma->low_mem)
- ? ERTS_MMAPFLG_SUPERCARRIER_ONLY
- : ERTS_MMAPFLG_OS_ONLY);
-#endif
if (MSEG_FLG_IS_2POW(flags))
mmap_flags |= ERTS_MMAPFLG_SUPERALIGNED;
- seg = erts_mmap(mmap_flags, sizep);
+ seg = erts_mmap(&erts_dflt_mmapper, mmap_flags, sizep);
#ifdef ERTS_PRINT_ERTS_MMAP
erts_fprintf(stderr, "%p = erts_mmap(%s, {%bpu, %bpu});\n", seg,
@@ -331,18 +305,13 @@ mseg_create(ErtsMsegAllctr_t *ma, Uint flags, MemKind* mk, UWord *sizep)
}
static ERTS_INLINE void
-mseg_destroy(ErtsMsegAllctr_t *ma, Uint flags, MemKind* mk, void *seg_p, UWord size) {
+mseg_destroy(ErtsMsegAllctr_t *ma, Uint flags, void *seg_p, UWord size) {
Uint32 mmap_flags = 0;
-#if HALFWORD_HEAP
- mmap_flags |= ((mk == &ma->low_mem)
- ? ERTS_MMAPFLG_SUPERCARRIER_ONLY
- : ERTS_MMAPFLG_OS_ONLY);
-#endif
if (MSEG_FLG_IS_2POW(flags))
mmap_flags |= ERTS_MMAPFLG_SUPERALIGNED;
- erts_munmap(mmap_flags, seg_p, size);
+ erts_munmap(&erts_dflt_mmapper, mmap_flags, seg_p, size);
#ifdef ERTS_PRINT_ERTS_MMAP
erts_fprintf(stderr, "erts_munmap(%s, %p, %bpu);\n",
(mmap_flags & ERTS_MMAPFLG_SUPERALIGNED) ? "sa" : "sua",
@@ -353,22 +322,17 @@ mseg_destroy(ErtsMsegAllctr_t *ma, Uint flags, MemKind* mk, void *seg_p, UWord s
}
static ERTS_INLINE void *
-mseg_recreate(ErtsMsegAllctr_t *ma, Uint flags, MemKind* mk, void *old_seg, UWord old_size, UWord *sizep)
+mseg_recreate(ErtsMsegAllctr_t *ma, Uint flags, void *old_seg, UWord old_size, UWord *sizep)
{
#ifdef ERTS_PRINT_ERTS_MMAP
UWord req_size = *sizep;
#endif
void *new_seg;
Uint32 mmap_flags = 0;
-#if HALFWORD_HEAP
- mmap_flags |= ((mk == &ma->low_mem)
- ? ERTS_MMAPFLG_SUPERCARRIER_ONLY
- : ERTS_MMAPFLG_OS_ONLY);
-#endif
if (MSEG_FLG_IS_2POW(flags))
mmap_flags |= ERTS_MMAPFLG_SUPERALIGNED;
- new_seg = erts_mremap(mmap_flags, old_seg, old_size, sizep);
+ new_seg = erts_mremap(&erts_dflt_mmapper, mmap_flags, old_seg, old_size, sizep);
#ifdef ERTS_PRINT_ERTS_MMAP
erts_fprintf(stderr, "%p = erts_mremap(%s, %p, %bpu, {%bpu, %bpu});\n",
@@ -392,11 +356,8 @@ do { \
|| erts_smp_thr_progress_is_blocking() \
|| ERTS_IS_CRASH_DUMPING); \
} while (0)
-#define ERTS_DBG_MK_CHK_THR_ACCESS(MK) \
- ERTS_DBG_MA_CHK_THR_ACCESS((MK)->ma)
#else
#define ERTS_DBG_MA_CHK_THR_ACCESS(MA)
-#define ERTS_DBG_MK_CHK_THR_ACCESS(MK)
#endif
/* Cache interface */
@@ -409,10 +370,10 @@ static ERTS_INLINE void mseg_cache_clear_node(cache_t *c) {
c->prev = c;
}
-static ERTS_INLINE int cache_bless_segment(MemKind *mk, void *seg, UWord size, Uint flags) {
+static ERTS_INLINE int cache_bless_segment(ErtsMsegAllctr_t *ma, void *seg, UWord size, Uint flags) {
cache_t *c;
- ERTS_DBG_MK_CHK_THR_ACCESS(mk);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
ASSERT(!MSEG_FLG_IS_2POW(flags) || (MSEG_FLG_IS_2POW(flags) && MAP_IS_ALIGNED(seg) && IS_2POW(size)));
@@ -421,11 +382,11 @@ static ERTS_INLINE int cache_bless_segment(MemKind *mk, void *seg, UWord size, U
* Large blocks has no such cache and it is up to mseg to cache them to speed things up.
*/
- if (!erts_circleq_is_empty(&(mk->cache_free))) {
+ if (!erts_circleq_is_empty(&(ma->cache_free))) {
/* We have free slots, use one to cache the segment */
- c = erts_circleq_head(&(mk->cache_free));
+ c = erts_circleq_head(&(ma->cache_free));
erts_circleq_remove(c);
c->seg = seg;
@@ -437,29 +398,28 @@ static ERTS_INLINE int cache_bless_segment(MemKind *mk, void *seg, UWord size, U
ASSERT(ix < CACHE_AREAS);
ASSERT((1 << (ix + MSEG_ALIGN_BITS)) == size);
- erts_circleq_push_head(&(mk->cache_powered_node[ix]), c);
+ erts_circleq_push_head(&(ma->cache_powered_node[ix]), c);
} else
- erts_circleq_push_head(&(mk->cache_unpowered_node), c);
+ erts_circleq_push_head(&(ma->cache_unpowered_node), c);
- mk->cache_size++;
- ASSERT(mk->cache_size <= mk->ma->max_cache_size);
+ ma->cache_size++;
return 1;
- } else if (!MSEG_FLG_IS_2POW(flags) && !erts_circleq_is_empty(&(mk->cache_unpowered_node))) {
+ } else if (!MSEG_FLG_IS_2POW(flags) && !erts_circleq_is_empty(&(ma->cache_unpowered_node))) {
/* No free slots.
* Evict oldest slot from unpowered cache so we can cache an unpowered (sbc) segment */
- c = erts_circleq_tail(&(mk->cache_unpowered_node));
+ c = erts_circleq_tail(&(ma->cache_unpowered_node));
erts_circleq_remove(c);
- mseg_destroy(mk->ma, ERTS_MSEG_FLG_NONE, mk, c->seg, c->size);
+ mseg_destroy(ma, ERTS_MSEG_FLG_NONE, c->seg, c->size);
mseg_cache_clear_node(c);
c->seg = seg;
c->size = size;
- erts_circleq_push_head(&(mk->cache_unpowered_node), c);
+ erts_circleq_push_head(&(ma->cache_unpowered_node), c);
return 1;
} else if (!MSEG_FLG_IS_2POW(flags)) {
@@ -473,20 +433,20 @@ static ERTS_INLINE int cache_bless_segment(MemKind *mk, void *seg, UWord size, U
int i;
for( i = 0; i < CACHE_AREAS; i++) {
- if (erts_circleq_is_empty(&(mk->cache_powered_node[i])))
+ if (erts_circleq_is_empty(&(ma->cache_powered_node[i])))
continue;
- c = erts_circleq_tail(&(mk->cache_powered_node[i]));
+ c = erts_circleq_tail(&(ma->cache_powered_node[i]));
erts_circleq_remove(c);
- mseg_destroy(mk->ma, ERTS_MSEG_FLG_2POW, mk, c->seg, c->size);
+ mseg_destroy(ma, ERTS_MSEG_FLG_2POW, c->seg, c->size);
mseg_cache_clear_node(c);
c->seg = seg;
c->size = size;
- erts_circleq_push_head(&(mk->cache_unpowered_node), c);
+ erts_circleq_push_head(&(ma->cache_unpowered_node), c);
return 1;
}
@@ -495,11 +455,11 @@ static ERTS_INLINE int cache_bless_segment(MemKind *mk, void *seg, UWord size, U
return 0;
}
-static ERTS_INLINE void *cache_get_segment(MemKind *mk, UWord *size_p, Uint flags) {
+static ERTS_INLINE void *cache_get_segment(ErtsMsegAllctr_t *ma, UWord *size_p, Uint flags) {
UWord size = *size_p;
- ERTS_DBG_MK_CHK_THR_ACCESS(mk);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
if (MSEG_FLG_IS_2POW(flags)) {
@@ -512,10 +472,10 @@ static ERTS_INLINE void *cache_get_segment(MemKind *mk, UWord *size_p, Uint flag
for( i = ix; i < CACHE_AREAS; i++) {
- if (erts_circleq_is_empty(&(mk->cache_powered_node[i])))
+ if (erts_circleq_is_empty(&(ma->cache_powered_node[i])))
continue;
- c = erts_circleq_head(&(mk->cache_powered_node[i]));
+ c = erts_circleq_head(&(ma->cache_powered_node[i]));
erts_circleq_remove(c);
ASSERT(IS_2POW(c->size));
@@ -524,31 +484,31 @@ static ERTS_INLINE void *cache_get_segment(MemKind *mk, UWord *size_p, Uint flag
csize = c->size;
seg = (char*) c->seg;
- mk->cache_size--;
- mk->cache_hits++;
+ ma->cache_size--;
+ ma->cache_hits++;
/* link to free cache list */
mseg_cache_clear_node(c);
- erts_circleq_push_head(&(mk->cache_free), c);
+ erts_circleq_push_head(&(ma->cache_free), c);
- ASSERT(!(mk->cache_size < 0));
+ ASSERT(!(ma->cache_size < 0));
if (csize != size)
- mseg_destroy(mk->ma, ERTS_MSEG_FLG_2POW, mk, seg + size, csize - size);
+ mseg_destroy(ma, ERTS_MSEG_FLG_2POW, seg + size, csize - size);
return seg;
}
}
- else if (!erts_circleq_is_empty(&(mk->cache_unpowered_node))) {
+ else if (!erts_circleq_is_empty(&(ma->cache_unpowered_node))) {
void *seg;
cache_t *c;
cache_t *best = NULL;
UWord bdiff = 0;
UWord csize;
- UWord bad_max_abs = mk->ma->abs_max_cache_bad_fit;
- UWord bad_max_rel = mk->ma->rel_max_cache_bad_fit;
+ UWord bad_max_abs = ma->abs_max_cache_bad_fit;
+ UWord bad_max_rel = ma->rel_max_cache_bad_fit;
- erts_circleq_foreach(c, &(mk->cache_unpowered_node)) {
+ erts_circleq_foreach(c, &(ma->cache_unpowered_node)) {
csize = c->size;
if (csize >= size) {
if (((csize - size)*100 < bad_max_rel*size) && (csize - size) < bad_max_abs ) {
@@ -557,11 +517,11 @@ static ERTS_INLINE void *cache_get_segment(MemKind *mk, UWord *size_p, Uint flag
erts_circleq_remove(c);
- mk->cache_size--;
- mk->cache_hits++;
+ ma->cache_size--;
+ ma->cache_hits++;
mseg_cache_clear_node(c);
- erts_circleq_push_head(&(mk->cache_free), c);
+ erts_circleq_push_head(&(ma->cache_free), c);
*size_p = csize;
@@ -584,7 +544,7 @@ static ERTS_INLINE void *cache_get_segment(MemKind *mk, UWord *size_p, Uint flag
ASSERT(best->seg);
ASSERT(best->size > 0);
- mk->cache_hits++;
+ ma->cache_hits++;
/* Use current cache placement for remaining segment space */
@@ -608,7 +568,7 @@ static ERTS_INLINE void *cache_get_segment(MemKind *mk, UWord *size_p, Uint flag
* using callbacks from aux-work in the scheduler.
*/
-static ERTS_INLINE Uint mseg_drop_one_memkind_cache_size(MemKind *mk, Uint flags, cache_t *head) {
+static ERTS_INLINE Uint mseg_drop_one_cache_size(ErtsMsegAllctr_t *ma, Uint flags, cache_t *head) {
cache_t *c = NULL;
c = erts_circleq_tail(head);
@@ -617,19 +577,19 @@ static ERTS_INLINE Uint mseg_drop_one_memkind_cache_size(MemKind *mk, Uint flags
if (erts_mtrace_enabled)
erts_mtrace_crr_free(SEGTYPE, SEGTYPE, c->seg);
- mseg_destroy(mk->ma, flags, mk, c->seg, c->size);
+ mseg_destroy(ma, flags, c->seg, c->size);
mseg_cache_clear_node(c);
- erts_circleq_push_head(&(mk->cache_free), c);
+ erts_circleq_push_head(&(ma->cache_free), c);
- mk->segments.current.watermark--;
- mk->cache_size--;
+ ma->segments.current.watermark--;
+ ma->cache_size--;
- ASSERT( mk->cache_size >= 0 );
+ ASSERT(ma->cache_size >= 0);
- return mk->cache_size;
+ return ma->cache_size;
}
-static ERTS_INLINE Uint mseg_drop_memkind_cache_size(MemKind *mk, Uint flags, cache_t *head) {
+static ERTS_INLINE Uint mseg_drop_cache_size(ErtsMsegAllctr_t *ma, Uint flags, cache_t *head) {
cache_t *c = NULL;
while (!erts_circleq_is_empty(head)) {
@@ -640,58 +600,52 @@ static ERTS_INLINE Uint mseg_drop_memkind_cache_size(MemKind *mk, Uint flags, ca
if (erts_mtrace_enabled)
erts_mtrace_crr_free(SEGTYPE, SEGTYPE, c->seg);
- mseg_destroy(mk->ma, flags, mk, c->seg, c->size);
+ mseg_destroy(ma, flags, c->seg, c->size);
mseg_cache_clear_node(c);
- erts_circleq_push_head(&(mk->cache_free), c);
-
- mk->segments.current.watermark--;
- mk->cache_size--;
+ erts_circleq_push_head(&(ma->cache_free), c);
+ ma->segments.current.watermark--;
+ ma->cache_size--;
}
- ASSERT( mk->cache_size >= 0 );
+ ASSERT(ma->cache_size >= 0);
- return mk->cache_size;
+ return ma->cache_size;
}
-/* mseg_check_memkind_cache
- * - Check if we can empty some cached segments in this
- * MemKind.
+/* mseg_check_cache
+ * - Check if we can empty some cached segments in this allocator
*/
-static Uint mseg_check_memkind_cache(MemKind *mk) {
+static Uint mseg_check_cache(ErtsMsegAllctr_t *ma) {
int i;
- ERTS_DBG_MK_CHK_THR_ACCESS(mk);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
for (i = 0; i < CACHE_AREAS; i++) {
- if (!erts_circleq_is_empty(&(mk->cache_powered_node[i])))
- return mseg_drop_one_memkind_cache_size(mk, ERTS_MSEG_FLG_2POW, &(mk->cache_powered_node[i]));
+ if (!erts_circleq_is_empty(&(ma->cache_powered_node[i])))
+ return mseg_drop_one_cache_size(ma, ERTS_MSEG_FLG_2POW, &(ma->cache_powered_node[i]));
}
- if (!erts_circleq_is_empty(&(mk->cache_unpowered_node)))
- return mseg_drop_one_memkind_cache_size(mk, ERTS_MSEG_FLG_NONE, &(mk->cache_unpowered_node));
+ if (!erts_circleq_is_empty(&(ma->cache_unpowered_node)))
+ return mseg_drop_one_cache_size(ma, ERTS_MSEG_FLG_NONE, &(ma->cache_unpowered_node));
return 0;
}
/* mseg_cache_check
* - Check if we have some cache we can purge
- * in any of the memkinds.
*/
static void mseg_cache_check(ErtsMsegAllctr_t *ma) {
- MemKind* mk;
Uint empty_cache = 1;
ERTS_MSEG_LOCK(ma);
- for (mk = ma->mk_list; mk; mk = mk->next) {
- if (mseg_check_memkind_cache(mk))
- empty_cache = 0;
- }
+ if (mseg_check_cache(ma))
+ empty_cache = 0;
/* If all MemKinds caches are empty,
* remove aux-work callback
@@ -709,7 +663,7 @@ static void mseg_cache_check(ErtsMsegAllctr_t *ma) {
/* erts_mseg_cache_check
* - This is a callback that is scheduled as aux-work from
* schedulers and is called at some interval if we have a cache
- * on this mseg-allocator and memkind.
+ * on this mseg-allocator.
* - Purpose: Empty cache slowly so we don't collect mapped areas
* and bloat memory.
*/
@@ -719,42 +673,32 @@ void erts_mseg_cache_check(void) {
}
-/* *_mseg_clear_*_cache
+/* mseg_clear_cache
* Remove cached segments from the allocator completely
*/
-static void mseg_clear_memkind_cache(MemKind *mk) {
+
+static void mseg_clear_cache(ErtsMsegAllctr_t *ma) {
int i;
+ ERTS_MSEG_LOCK(ma);
+ ERTS_DBG_MA_CHK_THR_ACCESS(ma);
/* drop pow2 caches */
for (i = 0; i < CACHE_AREAS; i++) {
- if (erts_circleq_is_empty(&(mk->cache_powered_node[i])))
+ if (erts_circleq_is_empty(&(ma->cache_powered_node[i])))
continue;
- mseg_drop_memkind_cache_size(mk, ERTS_MSEG_FLG_2POW, &(mk->cache_powered_node[i]));
- ASSERT(erts_circleq_is_empty(&(mk->cache_powered_node[i])));
+ mseg_drop_cache_size(ma, ERTS_MSEG_FLG_2POW, &(ma->cache_powered_node[i]));
+ ASSERT(erts_circleq_is_empty(&(ma->cache_powered_node[i])));
}
/* drop varied caches */
- if (!erts_circleq_is_empty(&(mk->cache_unpowered_node)))
- mseg_drop_memkind_cache_size(mk, ERTS_MSEG_FLG_NONE, &(mk->cache_unpowered_node));
-
- ASSERT(erts_circleq_is_empty(&(mk->cache_unpowered_node)));
- ASSERT(mk->cache_size == 0);
-}
+ if (!erts_circleq_is_empty(&(ma->cache_unpowered_node)))
+ mseg_drop_cache_size(ma, ERTS_MSEG_FLG_NONE, &(ma->cache_unpowered_node));
-static void mseg_clear_cache(ErtsMsegAllctr_t *ma) {
- MemKind* mk;
-
- ERTS_MSEG_LOCK(ma);
- ERTS_DBG_MA_CHK_THR_ACCESS(ma);
-
-
- for (mk = ma->mk_list; mk; mk = mk->next) {
- mseg_clear_memkind_cache(mk);
- }
+ ASSERT(erts_circleq_is_empty(&(ma->cache_unpowered_node)));
+ ASSERT(ma->cache_size == 0);
INC_CC(ma, clear_cache);
-
ERTS_MSEG_UNLOCK(ma);
}
@@ -763,25 +707,12 @@ void erts_mseg_clear_cache(void) {
mseg_clear_cache(ERTS_MSEG_ALLCTR_IX(0));
}
-
-
-static ERTS_INLINE MemKind* memkind(ErtsMsegAllctr_t *ma,
- const ErtsMsegOpt_t *opt)
-{
-#if HALFWORD_HEAP
- return opt->low_mem ? &ma->low_mem : &ma->hi_mem;
-#else
- return &ma->the_mem;
-#endif
-}
-
static void *
mseg_alloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, UWord *size_p,
Uint flags, const ErtsMsegOpt_t *opt)
{
UWord size;
void *seg;
- MemKind* mk = memkind(ma, opt);
INC_CC(ma, alloc);
@@ -795,10 +726,10 @@ mseg_alloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, UWord *size_p,
}
}
- if (opt->cache && mk->cache_size > 0 && (seg = cache_get_segment(mk, &size, flags)) != NULL)
+ if (opt->cache && ma->cache_size > 0 && (seg = cache_get_segment(ma, &size, flags)) != NULL)
goto done;
- seg = mseg_create(ma, flags, mk, &size);
+ seg = mseg_create(ma, flags, &size);
if (!seg)
*size_p = 0;
@@ -808,7 +739,7 @@ done:
if (erts_mtrace_enabled)
erts_mtrace_crr_alloc(seg, atype, ERTS_MTRACE_SEGMENT_ID, size);
- ERTS_MSEG_ALLOC_STAT(mk,size);
+ ERTS_MSEG_ALLOC_STAT(ma,size);
}
return seg;
@@ -819,11 +750,9 @@ static void
mseg_dealloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg, UWord size,
Uint flags, const ErtsMsegOpt_t *opt)
{
- MemKind* mk = memkind(ma, opt);
-
- ERTS_MSEG_DEALLOC_STAT(mk,size);
+ ERTS_MSEG_DEALLOC_STAT(ma,size);
- if (opt->cache && cache_bless_segment(mk, seg, size, flags)) {
+ if (opt->cache && cache_bless_segment(ma, seg, size, flags)) {
schedule_cache_check(ma);
goto done;
}
@@ -831,7 +760,7 @@ mseg_dealloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg, UWord size,
if (erts_mtrace_enabled)
erts_mtrace_crr_free(atype, SEGTYPE, seg);
- mseg_destroy(ma, flags, mk, seg, size);
+ mseg_destroy(ma, flags, seg, size);
done:
@@ -842,7 +771,6 @@ static void *
mseg_realloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg,
UWord old_size, UWord *new_size_p, Uint flags, const ErtsMsegOpt_t *opt)
{
- MemKind* mk;
void *new_seg;
UWord new_size;
@@ -861,7 +789,6 @@ mseg_realloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg,
return NULL;
}
- mk = memkind(ma, opt);
new_seg = seg;
if (!MSEG_FLG_IS_2POW(flags))
@@ -876,7 +803,7 @@ mseg_realloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg,
if (new_size > old_size) {
if (opt->preserv) {
- new_seg = mseg_recreate(ma, flags, mk, (void *) seg, old_size, &new_size);
+ new_seg = mseg_recreate(ma, flags, (void *) seg, old_size, &new_size);
if (!new_seg)
new_size = old_size;
}
@@ -896,7 +823,7 @@ mseg_realloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg,
new_size = old_size;
}
else {
- new_seg = mseg_recreate(ma, flags, mk, (void *) seg, old_size, &new_size);
+ new_seg = mseg_recreate(ma, flags, (void *) seg, old_size, &new_size);
if (!new_seg)
new_size = old_size;
}
@@ -910,7 +837,7 @@ mseg_realloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg,
ASSERT(!MSEG_FLG_IS_2POW(flags) || IS_2POW(new_size));
*new_size_p = new_size;
- ERTS_MSEG_REALLOC_STAT(mk, old_size, new_size);
+ ERTS_MSEG_REALLOC_STAT(ma, old_size, new_size);
return new_seg;
}
@@ -1070,7 +997,8 @@ info_options(ErtsMsegAllctr_t *ma,
{
Eterm res;
- res = erts_mmap_info_options(prefix, print_to_p, print_to_arg, hpp, szp);
+ res = erts_mmap_info_options(&erts_dflt_mmapper,
+ prefix, print_to_p, print_to_arg, hpp, szp);
if (print_to_p) {
int to = *print_to_p;
@@ -1180,63 +1108,63 @@ info_calls(ErtsMsegAllctr_t *ma, int *print_to_p, void *print_to_arg, Uint **hpp
}
static Eterm
-info_status(ErtsMsegAllctr_t *ma, MemKind* mk, int *print_to_p, void *print_to_arg,
+info_status(ErtsMsegAllctr_t *ma, int *print_to_p, void *print_to_arg,
int begin_new_max_period, Uint **hpp, Uint *szp)
{
Eterm res = THE_NON_VALUE;
- if (mk->segments.max_ever.no < mk->segments.max.no)
- mk->segments.max_ever.no = mk->segments.max.no;
- if (mk->segments.max_ever.sz < mk->segments.max.sz)
- mk->segments.max_ever.sz = mk->segments.max.sz;
+ if (ma->segments.max_ever.no < ma->segments.max.no)
+ ma->segments.max_ever.no = ma->segments.max.no;
+ if (ma->segments.max_ever.sz < ma->segments.max.sz)
+ ma->segments.max_ever.sz = ma->segments.max.sz;
if (print_to_p) {
int to = *print_to_p;
void *arg = print_to_arg;
- erts_print(to, arg, "cached_segments: %beu\n", mk->cache_size);
- erts_print(to, arg, "cache_hits: %beu\n", mk->cache_hits);
+ erts_print(to, arg, "cached_segments: %beu\n", ma->cache_size);
+ erts_print(to, arg, "cache_hits: %beu\n", ma->cache_hits);
erts_print(to, arg, "segments: %beu %beu %beu\n",
- mk->segments.current.no, mk->segments.max.no, mk->segments.max_ever.no);
+ ma->segments.current.no, ma->segments.max.no, ma->segments.max_ever.no);
erts_print(to, arg, "segments_size: %beu %beu %beu\n",
- mk->segments.current.sz, mk->segments.max.sz, mk->segments.max_ever.sz);
+ ma->segments.current.sz, ma->segments.max.sz, ma->segments.max_ever.sz);
erts_print(to, arg, "segments_watermark: %beu\n",
- mk->segments.current.watermark);
+ ma->segments.current.watermark);
}
if (hpp || szp) {
res = NIL;
add_2tup(hpp, szp, &res,
am.segments_watermark,
- bld_unstable_uint(hpp, szp, mk->segments.current.watermark));
+ bld_unstable_uint(hpp, szp, ma->segments.current.watermark));
add_4tup(hpp, szp, &res,
am.segments_size,
- bld_unstable_uint(hpp, szp, mk->segments.current.sz),
- bld_unstable_uint(hpp, szp, mk->segments.max.sz),
- bld_unstable_uint(hpp, szp, mk->segments.max_ever.sz));
+ bld_unstable_uint(hpp, szp, ma->segments.current.sz),
+ bld_unstable_uint(hpp, szp, ma->segments.max.sz),
+ bld_unstable_uint(hpp, szp, ma->segments.max_ever.sz));
add_4tup(hpp, szp, &res,
am.segments,
- bld_unstable_uint(hpp, szp, mk->segments.current.no),
- bld_unstable_uint(hpp, szp, mk->segments.max.no),
- bld_unstable_uint(hpp, szp, mk->segments.max_ever.no));
+ bld_unstable_uint(hpp, szp, ma->segments.current.no),
+ bld_unstable_uint(hpp, szp, ma->segments.max.no),
+ bld_unstable_uint(hpp, szp, ma->segments.max_ever.no));
add_2tup(hpp, szp, &res,
am.cache_hits,
- bld_unstable_uint(hpp, szp, mk->cache_hits));
+ bld_unstable_uint(hpp, szp, ma->cache_hits));
add_2tup(hpp, szp, &res,
am.cached_segments,
- bld_unstable_uint(hpp, szp, mk->cache_size));
+ bld_unstable_uint(hpp, szp, ma->cache_size));
}
if (begin_new_max_period) {
- mk->segments.max.no = mk->segments.current.no;
- mk->segments.max.sz = mk->segments.current.sz;
+ ma->segments.max.no = ma->segments.current.no;
+ ma->segments.max.sz = ma->segments.current.sz;
}
return res;
}
-static Eterm info_memkind(ErtsMsegAllctr_t *ma, MemKind* mk, int *print_to_p, void *print_to_arg,
+static Eterm info_memkind(ErtsMsegAllctr_t *ma, int *print_to_p, void *print_to_arg,
int begin_max_per, Uint **hpp, Uint *szp)
{
Eterm res = THE_NON_VALUE;
@@ -1244,15 +1172,15 @@ static Eterm info_memkind(ErtsMsegAllctr_t *ma, MemKind* mk, int *print_to_p, vo
Eterm values[3];
if (print_to_p) {
- erts_print(*print_to_p, print_to_arg, "memory kind: %s\n", mk->name);
+ erts_print(*print_to_p, print_to_arg, "memory kind: %s\n", "all memory");
}
if (hpp || szp) {
atoms[0] = am.name;
atoms[1] = am.status;
atoms[2] = am.calls;
- values[0] = erts_bld_string(hpp, szp, mk->name);
+ values[0] = erts_bld_string(hpp, szp, "all memory");
}
- values[1] = info_status(ma, mk, print_to_p, print_to_arg, begin_max_per, hpp, szp);
+ values[1] = info_status(ma, print_to_p, print_to_arg, begin_max_per, hpp, szp);
values[2] = info_calls(ma, print_to_p, print_to_arg, hpp, szp);
if (hpp || szp)
@@ -1261,7 +1189,6 @@ static Eterm info_memkind(ErtsMsegAllctr_t *ma, MemKind* mk, int *print_to_p, vo
return res;
}
-
static Eterm
info_version(ErtsMsegAllctr_t *ma, int *print_to_p, void *print_to_arg, Uint **hpp, Uint *szp)
{
@@ -1326,12 +1253,7 @@ erts_mseg_info(int ix,
ERTS_MSEG_LOCK(ma);
ERTS_DBG_MA_CHK_THR_ACCESS(ma);
-#if HALFWORD_HEAP
- values[n++] = info_memkind(ma, &ma->low_mem, print_to_p, print_to_arg, begin_max_per, hpp, szp);
- values[n++] = info_memkind(ma, &ma->hi_mem, print_to_p, print_to_arg, begin_max_per, hpp, szp);
-#else
- values[n++] = info_memkind(ma, &ma->the_mem, print_to_p, print_to_arg, begin_max_per, hpp, szp);
-#endif
+ values[n++] = info_memkind(ma, print_to_p, print_to_arg, begin_max_per, hpp, szp);
if (hpp || szp)
res = bld_2tup_list(hpp, szp, n, atoms, values);
@@ -1408,13 +1330,10 @@ Uint
erts_mseg_no(const ErtsMsegOpt_t *opt)
{
ErtsMsegAllctr_t *ma = ERTS_MSEG_ALLCTR_OPT(opt);
- MemKind* mk;
- Uint n = 0;
+ Uint n;
ERTS_MSEG_LOCK(ma);
ERTS_DBG_MA_CHK_THR_ACCESS(ma);
- for (mk=ma->mk_list; mk; mk=mk->next) {
- n += mk->segments.current.no;
- }
+ n = ma->segments.current.no;
ERTS_MSEG_UNLOCK(ma);
return n;
}
@@ -1426,16 +1345,16 @@ erts_mseg_unit_size(void)
}
-static void mem_kind_init(ErtsMsegAllctr_t *ma, MemKind* mk, const char* name)
+static void mem_cache_init(ErtsMsegAllctr_t *ma)
{
int i;
/* Clear all cache headers */
- mseg_cache_clear_node(&(mk->cache_free));
- mseg_cache_clear_node(&(mk->cache_unpowered_node));
+ mseg_cache_clear_node(&(ma->cache_free));
+ mseg_cache_clear_node(&(ma->cache_unpowered_node));
for (i = 0; i < CACHE_AREAS; i++) {
- mseg_cache_clear_node(&(mk->cache_powered_node[i]));
+ mseg_cache_clear_node(&(ma->cache_powered_node[i]));
}
/* Populate cache free list */
@@ -1443,25 +1362,20 @@ static void mem_kind_init(ErtsMsegAllctr_t *ma, MemKind* mk, const char* name)
ASSERT(ma->max_cache_size <= MAX_CACHE_SIZE);
for (i = 0; i < ma->max_cache_size; i++) {
- mseg_cache_clear_node(&(mk->cache[i]));
- erts_circleq_push_head(&(mk->cache_free), &(mk->cache[i]));
+ mseg_cache_clear_node(&(ma->cache[i]));
+ erts_circleq_push_head(&(ma->cache_free), &(ma->cache[i]));
}
- mk->cache_size = 0;
- mk->cache_hits = 0;
-
- mk->segments.current.watermark = 0;
- mk->segments.current.no = 0;
- mk->segments.current.sz = 0;
- mk->segments.max.no = 0;
- mk->segments.max.sz = 0;
- mk->segments.max_ever.no = 0;
- mk->segments.max_ever.sz = 0;
-
- mk->ma = ma;
- mk->name = name;
- mk->next = ma->mk_list;
- ma->mk_list = mk;
+ ma->cache_size = 0;
+ ma->cache_hits = 0;
+
+ ma->segments.current.watermark = 0;
+ ma->segments.current.no = 0;
+ ma->segments.current.sz = 0;
+ ma->segments.max.no = 0;
+ ma->segments.max.sz = 0;
+ ma->segments.max_ever.no = 0;
+ ma->segments.max_ever.sz = 0;
}
void
@@ -1488,17 +1402,11 @@ erts_mseg_init(ErtsMsegInit_t *init)
erts_mtx_init(&init_atoms_mutex, "mseg_init_atoms");
-#if HALFWORD_HEAP
- if (sizeof(void *) != 8)
- erts_exit(1,"Halfword emulator cannot be run in 32bit mode");
-
- init->mmap.virtual_range.start = (char *) sbrk(0);
- init->mmap.virtual_range.end = (char *) 0x100000000UL;
- init->mmap.sco = 0;
+ erts_mmap_init(&erts_dflt_mmapper, &init->dflt_mmap);
+#if defined(ARCH_64) && defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+ erts_mmap_init(&erts_literal_mmapper, &init->literal_mmap);
#endif
- erts_mmap_init(&init->mmap);
-
if (!IS_2POW(GET_PAGE_SIZE))
erts_exit(ERTS_ABORT_EXIT, "erts_mseg: Unexpected page_size %beu\n", GET_PAGE_SIZE);
@@ -1529,14 +1437,7 @@ erts_mseg_init(ErtsMsegInit_t *init)
if (ma->max_cache_size > MAX_CACHE_SIZE)
ma->max_cache_size = MAX_CACHE_SIZE;
- ma->mk_list = NULL;
-
-#if HALFWORD_HEAP
- mem_kind_init(ma, &ma->low_mem, "low memory");
- mem_kind_init(ma, &ma->hi_mem, "high memory");
-#else
- mem_kind_init(ma, &ma->the_mem, "all memory");
-#endif
+ mem_cache_init(ma);
sys_memzero((void *) &ma->calls, sizeof(ErtsMsegCalls));
}
@@ -1545,13 +1446,8 @@ erts_mseg_init(ErtsMsegInit_t *init)
static ERTS_INLINE Uint tot_cache_size(ErtsMsegAllctr_t *ma)
{
- MemKind* mk;
- Uint sz = 0;
ERTS_DBG_MA_CHK_THR_ACCESS(ma);
- for (mk=ma->mk_list; mk; mk=mk->next) {
- sz += mk->cache_size;
- }
- return sz;
+ return ma->cache_size;
}
/*
diff --git a/erts/emulator/sys/common/erl_mseg.h b/erts/emulator/sys/common/erl_mseg.h
index ba04e919fc..2acd8f8505 100644
--- a/erts/emulator/sys/common/erl_mseg.h
+++ b/erts/emulator/sys/common/erl_mseg.h
@@ -42,16 +42,6 @@
#if ERTS_HAVE_MSEG_SUPER_ALIGNED
# define MSEG_ALIGN_BITS ERTS_MMAP_SUPERALIGNED_BITS
-#else
-/* If we don't use super aligned multiblock carriers
- * we will mmap with page size alignment (and thus use corresponding
- * align bits).
- *
- * Current implementation needs this to be a constant and
- * only uses this for user dev testing so setting page size
- * to 4096 (12 bits) is fine.
- */
-# define MSEG_ALIGN_BITS (12)
#endif
#if HAVE_ERTS_MSEG
@@ -69,7 +59,8 @@ typedef struct {
Uint rmcbf;
Uint mcs;
Uint nos;
- ErtsMMapInit mmap;
+ ErtsMMapInit dflt_mmap;
+ ErtsMMapInit literal_mmap;
} ErtsMsegInit_t;
#define ERTS_MSEG_INIT_DEFAULT_INITIALIZER \
@@ -78,7 +69,8 @@ typedef struct {
20, /* rmcbf: Relative max cache bad fit */ \
10, /* mcs: Max cache size */ \
1000, /* cci: Cache check interval */ \
- ERTS_MMAP_INIT_DEFAULT_INITER \
+ ERTS_MMAP_INIT_DEFAULT_INITER, \
+ ERTS_MMAP_INIT_LITERAL_INITER \
}
typedef struct {
@@ -87,9 +79,6 @@ typedef struct {
UWord abs_shrink_th;
UWord rel_shrink_th;
int sched_spec;
-#if HALFWORD_HEAP
- int low_mem;
-#endif
} ErtsMsegOpt_t;
extern const ErtsMsegOpt_t erts_mseg_default_opt;
diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c
index 21fa214364..36ee94111c 100644
--- a/erts/emulator/sys/common/erl_poll.c
+++ b/erts/emulator/sys/common/erl_poll.c
@@ -74,6 +74,7 @@
#include "erl_thr_progress.h"
#include "erl_driver.h"
#include "erl_alloc.h"
+#include "erl_msacc.h"
#if !defined(ERTS_POLL_USE_EPOLL) \
&& !defined(ERTS_POLL_USE_DEVPOLL) \
@@ -2238,6 +2239,7 @@ static ERTS_INLINE int
check_fd_events(ErtsPollSet ps, ErtsMonotonicTime timeout_time, int max_res)
{
int res;
+ ERTS_MSACC_PUSH_STATE_M();
if (erts_smp_atomic_read_nob(&ps->no_of_user_fds) == 0
&& timeout_time == ERTS_POLL_NO_TIMEOUT) {
/* Nothing to poll and zero timeout; done... */
@@ -2259,6 +2261,7 @@ check_fd_events(ErtsPollSet ps, ErtsMonotonicTime timeout_time, int max_res)
#ifdef ERTS_SMP
erts_thr_progress_prepare_wait(NULL);
#endif
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_SLEEP);
timerfd_set(ps, &its);
res = epoll_wait(ps->kp_fd, ps->res_events, max_res, -1);
res = timerfd_clear(ps, res, max_res);
@@ -2268,10 +2271,12 @@ check_fd_events(ErtsPollSet ps, ErtsMonotonicTime timeout_time, int max_res)
}
#else /* !ERTS_POLL_USE_TIMERFD */
timeout = (int) get_timeout(ps, 1000, timeout_time);
+ if (timeout) {
#ifdef ERTS_SMP
- if (timeout)
erts_thr_progress_prepare_wait(NULL);
#endif
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_SLEEP);
+ }
res = epoll_wait(ps->kp_fd, ps->res_events, max_res, timeout);
#endif /* !ERTS_POLL_USE_TIMERFD */
#elif ERTS_POLL_USE_KQUEUE /* --- kqueue ------------------------------ */
@@ -2279,10 +2284,12 @@ check_fd_events(ErtsPollSet ps, ErtsMonotonicTime timeout_time, int max_res)
if (max_res > ps->res_events_len)
grow_res_events(ps, max_res);
timeout = get_timeout_timespec(ps, &ts, timeout_time);
+ if (timeout) {
#ifdef ERTS_SMP
- if (timeout)
erts_thr_progress_prepare_wait(NULL);
#endif
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_SLEEP);
+ }
res = kevent(ps->kp_fd, NULL, 0, ps->res_events, max_res, &ts);
#endif /* ----------------------------------------- */
}
@@ -2306,26 +2313,33 @@ check_fd_events(ErtsPollSet ps, ErtsMonotonicTime timeout_time, int max_res)
if (poll_res.dp_nfds > ps->res_events_len)
grow_res_events(ps, poll_res.dp_nfds);
poll_res.dp_fds = ps->res_events;
+ if (timeout) {
#ifdef ERTS_SMP
- if (timeout)
erts_thr_progress_prepare_wait(NULL);
#endif
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_SLEEP);
+ }
poll_res.dp_timeout = timeout;
res = ioctl(ps->kp_fd, DP_POLL, &poll_res);
#elif ERTS_POLL_USE_POLL && defined(HAVE_PPOLL) /* --- ppoll ---------------- */
struct timespec ts;
timeout = get_timeout_timespec(ps, &ts, timeout_time);
+ if (timeout) {
#ifdef ERTS_SMP
- if (timeout)
erts_thr_progress_prepare_wait(NULL);
#endif
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_SLEEP);
+ }
res = ppoll(ps->poll_fds, ps->no_poll_fds, &ts, NULL);
#elif ERTS_POLL_USE_POLL /* --- poll --------------------------------- */
timeout = (int) get_timeout(ps, 1000, timeout_time);
+
+ if (timeout) {
#ifdef ERTS_SMP
- if (timeout)
erts_thr_progress_prepare_wait(NULL);
#endif
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_SLEEP);
+ }
res = poll(ps->poll_fds, ps->no_poll_fds, timeout);
#elif ERTS_POLL_USE_SELECT /* --- select ------------------------------ */
SysTimeval to;
@@ -2334,18 +2348,22 @@ check_fd_events(ErtsPollSet ps, ErtsMonotonicTime timeout_time, int max_res)
ERTS_FD_COPY(&ps->input_fds, &ps->res_input_fds);
ERTS_FD_COPY(&ps->output_fds, &ps->res_output_fds);
+ if (timeout) {
#ifdef ERTS_SMP
- if (timeout)
erts_thr_progress_prepare_wait(NULL);
#endif
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_SLEEP);
+ }
res = ERTS_SELECT(ps->max_fd + 1,
&ps->res_input_fds,
&ps->res_output_fds,
NULL,
&to);
#ifdef ERTS_SMP
- if (timeout)
+ if (timeout) {
erts_thr_progress_finalize_wait(NULL);
+ ERTS_MSACC_POP_STATE_M();
+ }
if (res < 0
&& errno == EBADF
&& ERTS_POLLSET_HAVE_UPDATE_REQUESTS(ps)) {
@@ -2380,10 +2398,12 @@ check_fd_events(ErtsPollSet ps, ErtsMonotonicTime timeout_time, int max_res)
return res;
#endif /* ----------------------------------------- */
}
+ if (timeout) {
#ifdef ERTS_SMP
- if (timeout)
erts_thr_progress_finalize_wait(NULL);
#endif
+ ERTS_MSACC_POP_STATE_M();
+ }
return res;
}
}
diff --git a/erts/emulator/sys/common/erl_poll.h b/erts/emulator/sys/common/erl_poll.h
index bd3a46ef0f..bc2c681876 100644
--- a/erts/emulator/sys/common/erl_poll.h
+++ b/erts/emulator/sys/common/erl_poll.h
@@ -93,7 +93,7 @@
# if defined(ERTS_USE_POLL)
# undef ERTS_POLL_USE_POLL
# define ERTS_POLL_USE_POLL 1
-# elif !defined(__WIN32__) && !defined(__OSE__)
+# elif !defined(__WIN32__)
# undef ERTS_POLL_USE_SELECT
# define ERTS_POLL_USE_SELECT 1
# endif
@@ -104,31 +104,13 @@
typedef Uint32 ErtsPollEvents;
#undef ERTS_POLL_EV_E2N
-#if defined(__WIN32__) || defined(__OSE__) /* --- win32 or ose -------- */
+#if defined(__WIN32__) /* --- win32 --------------------------------------- */
#define ERTS_POLL_EV_IN 1
#define ERTS_POLL_EV_OUT 2
#define ERTS_POLL_EV_ERR 4
#define ERTS_POLL_EV_NVAL 8
-#ifdef __OSE__
-
-typedef struct ErtsPollOseMsgList_ {
- struct ErtsPollOseMsgList_ *next;
- union SIGNAL *data;
-} ErtsPollOseMsgList;
-
-struct erts_sys_fd_type {
- SIGSELECT signo;
- ErlDrvOseEventId id;
- ErtsPollOseMsgList *msgs;
- ErlDrvOseEventId (*resolve_signal)(union SIGNAL *sig);
- ethr_mutex mtx;
- void *extra;
-};
-
-#endif
-
#elif ERTS_POLL_USE_EPOLL /* --- epoll ------------------------------- */
#include <sys/epoll.h>
diff --git a/erts/emulator/sys/ose/beam.lmconf b/erts/emulator/sys/ose/beam.lmconf
deleted file mode 100644
index 4ad46b01d9..0000000000
--- a/erts/emulator/sys/ose/beam.lmconf
+++ /dev/null
@@ -1,26 +0,0 @@
-OSE_LM_STACK_SIZES=256,512,1024,2048,4096,8192,16384,65536
-OSE_LM_SIGNAL_SIZES=31,63,127,255,1023,4095,16383,65535
-OSE_LM_POOL_SIZE=0x200000
-OSE_LM_MAIN_NAME=main
-OSE_LM_MAIN_STACK_SIZE=0xF000
-OSE_LM_MAIN_PRIORITY=20
-## Has to be of a type that allows MAM
-OSE_LM_PROGRAM_TYPE=APP_RAM
-OSE_LM_DATA_INIT=YES
-OSE_LM_BSS_INIT=YES
-OSE_LM_EXEC_MODEL=SHARED
-HEAP_MAX_SIZE=1000000000
-HEAP_SMALL_BUF_INIT_SIZE=20971520
-HEAP_LARGE_BUF_THRESHOLD=16000000
-HEAP_LOCK_TYPE=2
-
-ERTS_DEFAULT_PRIO=24
-ERTS_SCHEDULER_PRIO=24
-ERTS_ASYNC_PRIO=22
-ERTS_AUX_PRIO=24
-ERTS_SYS_MSG_DISPATCHER_PRIO=21
-
-# Setting the environment variable EFS_RESOLVE_TMO on the block to 0.
-# This will eliminiate delays when trying to open files on not mounted
-# volumes.
-EFS_RESOLVE_TMO=0
diff --git a/erts/emulator/sys/ose/driver_int.h b/erts/emulator/sys/ose/driver_int.h
deleted file mode 100644
index 4a5b7171d1..0000000000
--- a/erts/emulator/sys/ose/driver_int.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1997-2009. 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%
- */
-/*
- * System dependant driver declarations
- */
-
-#ifndef __DRIVER_INT_H__
-#define __DRIVER_INT_H__
-
-#ifdef HAVE_SYS_UIO_H
-#include <sys/types.h>
-#include <sys/uio.h>
-
-typedef struct iovec SysIOVec;
-
-#else
-
-typedef struct {
- char* iov_base;
- int iov_len;
-} SysIOVec;
-
-#endif
-
-#endif
diff --git a/erts/emulator/sys/ose/erl_main.c b/erts/emulator/sys/ose/erl_main.c
deleted file mode 100644
index 877e85f43a..0000000000
--- a/erts/emulator/sys/ose/erl_main.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2000-2009. 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%
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-#include <stdlib.h>
-
-#include "sys.h"
-#include "erl_vm.h"
-#include "global.h"
-#include "ose.h"
-
-int
-main(int argc, char **argv) {
-
- (void)stdin;(void)stdout;(void)stderr;
-
- /* When starting using pm_create -c ARGV="-- -root ..", argv[0] is the first
- part of ARGV and not the name of the executable. So we shuffle some
- pointers here to make erl_start happy. */
- if (argv[0][0] == '-') {
- int i;
- char **tmp_argv = malloc(sizeof(char*)*(argc+1));
- for (i = 0; i < argc; i++)
- tmp_argv[i+1] = argv[i];
- tmp_argv[0] = "beam";
- erl_start(argc+1,tmp_argv);
- free(tmp_argv);
- } else {
- erl_start(argc,argv);
- }
-
- stop(current_process());
-
- return 0;
-}
diff --git a/erts/emulator/sys/ose/erl_ose_sys.h b/erts/emulator/sys/ose/erl_ose_sys.h
deleted file mode 100644
index d0cd3180bf..0000000000
--- a/erts/emulator/sys/ose/erl_ose_sys.h
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1997-2011. 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%
- *
- * This file handles differences between different Unix systems.
- * This should be the only place with conditional compilation
- * depending on the type of OS.
- */
-
-#ifndef _ERL_OSE_SYS_H
-#define _ERL_OSE_SYS_H
-
-#include "ose.h"
-#undef NIL
-#include "ramlog.h"
-#include "erts.sig"
-
-#include "fcntl.h"
-#include "math.h"
-#include "stdio.h"
-#include "stdlib.h"
-#include "string.h"
-#include "sys/param.h"
-#include "sys/time.h"
-#include "time.h"
-#include "dirent.h"
-#include "ethread.h"
-
-/* FIXME: configuration options */
-#define ERTS_SCHED_MIN_SPIN 1
-#define ERTS_SCHED_ONLY_POLL_SCHED_1 1
-#define ERTS_SCHED_FAIR 1
-#define NO_SYSCONF 1
-#define OPEN_MAX FOPEN_MAX
-
-#define MAP_ANON MAP_ANONYMOUS
-
-#ifndef HAVE_MMAP
-# define HAVE_MMAP 0
-#endif
-
-#if HAVE_MMAP
-# include "sys/mman.h"
-#endif
-
-/*
- * Min number of async threads
- */
-#define ERTS_MIN_NO_OF_ASYNC_THREADS 1
-
-/*
- * Our own type of "FD's"
- */
-#define ERTS_SYS_FD_TYPE struct erts_sys_fd_type*
-#define NO_FSTAT_ON_SYS_FD_TYPE 1 /* They are signals, not files */
-
-#include "sys/stat.h"
-
-/* FIXME mremap is not defined in OSE - POSIX issue */
-extern void *mremap (void *__addr, size_t __old_len, size_t __new_len,
- int __flags, ...);
-
-/* FIXME: mremap constants */
-#define MREMAP_MAYMOVE 1
-#define MREMAP_FIXED 2
-
-typedef void *GETENV_STATE;
-
-/*
-** For the erl_timer_sup module.
-*/
-#define HAVE_GETHRTIME
-
-typedef long long SysHrTime;
-extern SysHrTime sys_gethrtime(void);
-
-void sys_init_hrtime(void);
-
-typedef time_t erts_time_t;
-
-typedef struct timeval SysTimeval;
-
-#define sys_gettimeofday(Arg) ((void) gettimeofday((Arg), NULL))
-
-typedef struct {
- clock_t tms_utime;
- clock_t tms_stime;
- clock_t tms_cutime;
- clock_t tms_cstime;
-} SysTimes;
-
-extern int erts_ticks_per_sec;
-
-#define SYS_CLK_TCK (erts_ticks_per_sec)
-
-extern clock_t sys_times(SysTimes *buffer);
-
-/* No use in having other resolutions than 1 Ms. */
-#define SYS_CLOCK_RESOLUTION 1
-
-#define erts_isfinite finite
-
-#ifdef NO_FPE_SIGNALS
-
-#define erts_get_current_fp_exception() NULL
-#ifdef ERTS_SMP
-#define erts_thread_init_fp_exception() do{}while(0)
-#endif
-# define __ERTS_FP_CHECK_INIT(fpexnp) do {} while (0)
-# define __ERTS_FP_ERROR(fpexnp, f, Action) if (!finite(f)) { Action; } else {}
-# define __ERTS_FP_ERROR_THOROUGH(fpexnp, f, Action) __ERTS_FP_ERROR(fpexnp, f, Action)
-# define __ERTS_SAVE_FP_EXCEPTION(fpexnp)
-# define __ERTS_RESTORE_FP_EXCEPTION(fpexnp)
-
-#define erts_sys_block_fpe() 0
-#define erts_sys_unblock_fpe(x) do{}while(0)
-
-#else /* !NO_FPE_SIGNALS */
-
-extern volatile unsigned long *erts_get_current_fp_exception(void);
-#ifdef ERTS_SMP
-extern void erts_thread_init_fp_exception(void);
-#endif
-# if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
-# define erts_fwait(fpexnp,f) \
- __asm__ __volatile__("fwait" : "=m"(*(fpexnp)) : "m"(f))
-# elif (defined(__powerpc__) || defined(__ppc__)) && defined(__GNUC__)
-# define erts_fwait(fpexnp,f) \
- __asm__ __volatile__("" : "=m"(*(fpexnp)) : "fm"(f))
-# elif defined(__sparc__) && defined(__linux__) && defined(__GNUC__)
-# define erts_fwait(fpexnp,f) \
- __asm__ __volatile__("" : "=m"(*(fpexnp)) : "em"(f))
-# else
-# define erts_fwait(fpexnp,f) \
- __asm__ __volatile__("" : "=m"(*(fpexnp)) : "g"(f))
-# endif
-# if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
- extern void erts_restore_fpu(void);
-# else
-# define erts_restore_fpu() /*empty*/
-# endif
-# if (!defined(__GNUC__) || \
- (__GNUC__ < 2) || \
- (__GNUC__ == 2 && __GNUC_MINOR < 96)) && \
- !defined(__builtin_expect)
-# define __builtin_expect(x, expected_value) (x)
-# endif
-static __inline__ int erts_check_fpe(volatile unsigned long *fp_exception, double f)
-{
- erts_fwait(fp_exception, f);
- if (__builtin_expect(*fp_exception == 0, 1))
- return 0;
- *fp_exception = 0;
- erts_restore_fpu();
- return 1;
-}
-# undef erts_fwait
-# undef erts_restore_fpu
-extern void erts_fp_check_init_error(volatile unsigned long *fp_exception);
-static __inline__ void __ERTS_FP_CHECK_INIT(volatile unsigned long *fp_exception)
-{
- if (__builtin_expect(*fp_exception == 0, 1))
- return;
- erts_fp_check_init_error(fp_exception);
-}
-# define __ERTS_FP_ERROR(fpexnp, f, Action) do { if (erts_check_fpe((fpexnp),(f))) { Action; } } while (0)
-# define __ERTS_SAVE_FP_EXCEPTION(fpexnp) unsigned long old_erl_fp_exception = *(fpexnp)
-# define __ERTS_RESTORE_FP_EXCEPTION(fpexnp) \
- do { *(fpexnp) = old_erl_fp_exception; } while (0)
- /* This is for library calls where we don't trust the external
- code to always throw floating-point exceptions on errors. */
-static __inline__ int erts_check_fpe_thorough(volatile unsigned long *fp_exception, double f)
-{
- return erts_check_fpe(fp_exception, f) || !finite(f);
-}
-# define __ERTS_FP_ERROR_THOROUGH(fpexnp, f, Action) \
- do { if (erts_check_fpe_thorough((fpexnp),(f))) { Action; } } while (0)
-
-int erts_sys_block_fpe(void);
-void erts_sys_unblock_fpe(int);
-
-#endif /* !NO_FPE_SIGNALS */
-
-#define ERTS_FP_CHECK_INIT(p) __ERTS_FP_CHECK_INIT(&(p)->fp_exception)
-#define ERTS_FP_ERROR(p, f, A) __ERTS_FP_ERROR(&(p)->fp_exception, f, A)
-#define ERTS_FP_ERROR_THOROUGH(p, f, A) __ERTS_FP_ERROR_THOROUGH(&(p)->fp_exception, f, A)
-
-/* FIXME: force HAVE_GETPAGESIZE and stub getpagesize */
-#ifndef HAVE_GETPAGESIZE
-#define HAVE_GETPAGESIZE 1
-#endif
-
-extern int getpagesize(void);
-
-#ifndef HZ
-#define HZ 60
-#endif
-
-/* OSE5 doesn't provide limits.h so a number of macros should be
- * added manually */
-
-#ifndef CHAR_BIT
-#define CHAR_BIT 8
-#endif
-
-/* Minimum and maximum values a `signed int' can hold. */
-#ifndef INT_MAX
-#define INT_MAX 2147483647
-#endif
-
-#ifndef INT_MIN
-#define INT_MIN (-INT_MAX - 1)
-#endif
-
-#ifndef UINT_MAX
-# define UINT_MAX 4294967295U
-#endif
-
-/*
-static void erts_ose_sys_send(union SIGNAL **signal,PROCESS dst,
- char* file,int line) {
- SIGSELECT **ziggy = (SIGSELECT**)signal;
- printf("%s:%d 0x%x Send signal 0x%x(0x%x) to 0x%x\r\n",
- file,line,current_process(),ziggy[0][0],*ziggy,dst);
- send(signal,dst);
-}
-#define send(signal,dst) erts_ose_sys_send(signal,dst,__FILE__,__LINE__)
-
-static void erts_ose_sys_send_w_sender(union SIGNAL **signal,
- PROCESS sender,PROCESS dst,
- char* file,int line) {
- SIGSELECT **ziggy = (SIGSELECT**)signal;
- printf("%s:%d 0x%x Send signal 0x%x(0x%x) to 0x%x as 0x%x\r\n",
- file,line,current_process(),ziggy[0][0],*ziggy,dst,sender);
- send_w_sender(signal,sender,dst);
-}
-#define send_w_sender(signal,sender,dst) \
- erts_ose_sys_send_w_sender(signal,sender,dst,__FILE__,__LINE__)
-
-
-static union SIGNAL *erts_ose_sys_receive(SIGSELECT *sigsel,
- char *file,
- int line) {
- SIGSELECT *sig;
- int i;
-
- printf("%s:%d 0x%x receive({%d,",file,line,current_process(),sigsel[0]);
- for (i = 1; i < sigsel[0]; i++)
- printf("0x%x, ",sigsel[i]);
- if (sigsel[0] != 0)
- printf("0x%x",sigsel[i]);
- printf("})\n");
- sig = (SIGSELECT*)receive(sigsel);
- printf("%s:%d 0x%x got 0x%x from 0x%x\n",file,line,current_process(),
- *sig,sender((union SIGNAL**)(&sig)));
- return (union SIGNAL*)sig;
-}
-#define receive(SIGSEL) erts_ose_sys_receive(SIGSEL,__FILE__,__LINE__)
-
-static union SIGNAL *erts_ose_sys_receive_w_tmo(OSTIME tmo,SIGSELECT *sigsel,
- char *file,int line) {
- SIGSELECT *sig;
- int i;
- if (tmo == 0) {
- sig = (SIGSELECT*)receive_w_tmo(tmo,sigsel);
- if (sig != NULL) {
- printf("%s:%d 0x%x receive_w_tmo(0,{%d,",file,line,current_process(),
- sigsel[0]);
- for (i = 1; i < sigsel[0]; i++)
- printf("0x%x, ",sigsel[i]);
- if (sigsel[0] != 0)
- printf("0x%x",sigsel[i]);
- printf("})\n");
- printf("%s:%d 0x%x got 0x%x from 0x%x\n",file,line,current_process(),
- *sig,sender((union SIGNAL**)(&sig)));
- }
- } else {
- printf("%s:%d 0x%x receive_w_tmo(%u,{%d,",file,line,current_process(),tmo,
- sigsel[0]);
- for (i = 1; i < sigsel[0]; i++)
- printf("0x%x, ",sigsel[i]);
- if (sigsel[0] != 0)
- printf("0x%x",sigsel[i]);
- printf("})\n");
- sig = (SIGSELECT*)receive_w_tmo(tmo,sigsel);
- printf("%s:%d 0x%x got ",file,line,current_process());
- if (sig == NULL)
- printf("TIMEOUT\n");
- else
- printf("0x%x from 0x%x\n",*sig,sender((union SIGNAL**)(&sig)));
- }
-
- return (union SIGNAL*)sig;
-}
-
-#define receive_w_tmo(tmo,sigsel) erts_ose_sys_receive_w_tmo(tmo,sigsel, \
- __FILE__,__LINE__)
-
-static union SIGNAL *erts_ose_sys_receive_fsem(OSTIME tmo,SIGSELECT *sigsel,
- OSFSEMVAL fsem,
- char *file,int line) {
- SIGSELECT *sig;
- int i;
- if (tmo == 0) {
- sig = (SIGSELECT*)receive_fsem(tmo,sigsel,fsem);
- if (sig != NULL && sig != OS_RCV_FSEM) {
- printf("%s:%d 0x%x receive_fsem(0,{%d,",file,line,current_process(),
- sigsel[0]);
- for (i = 1; i < sigsel[0]; i++)
- printf("0x%x, ",sigsel[i]);
- if (sigsel[0] != 0)
- printf("0x%x",sigsel[i]);
- printf("},%d)\n",fsem);
- printf("%s:%d 0x%x got 0x%x from 0x%x\n",file,line,current_process(),
- *sig,sender((union SIGNAL**)(&sig)));
- }
- } else {
- printf("%s:%d 0x%x receive_fsem(%u,{%d,",file,line,current_process(),tmo,
- sigsel[0]);
- for (i = 1; i < sigsel[0]; i++)
- printf("0x%x, ",sigsel[i]);
- if (sigsel[0] != 0)
- printf("0x%x",sigsel[i]);
- printf("},%d)\n",fsem);
- sig = (SIGSELECT*)receive_fsem(tmo,sigsel,fsem);
- printf("%s:%d 0x%x got ",file,line,current_process());
- if (sig == NULL)
- printf("TIMEOUT\n");
- else if (sig == OS_RCV_FSEM)
- printf("FSEM\n");
- else
- printf("0x%x from 0x%x\n",*sig,sender((union SIGNAL**)(&sig)));
- }
-
- return (union SIGNAL*)sig;
-}
-
-#define receive_fsem(tmo,sigsel,fsem) \
- erts_ose_sys_receive_fsem(tmo,sigsel,fsem,__FILE__,__LINE__)
-*/
-#endif /* _ERL_OSE_SYS_H */
diff --git a/erts/emulator/sys/ose/erl_ose_sys_ddll.c b/erts/emulator/sys/ose/erl_ose_sys_ddll.c
deleted file mode 100644
index 5051f7fcc1..0000000000
--- a/erts/emulator/sys/ose/erl_ose_sys_ddll.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2006-2013. 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%
- */
-
-/*
- * Interface functions to the dynamic linker using dl* functions.
- * (No support in OSE, we use static linkage instead)
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "sys.h"
-#include "erl_vm.h"
-#include "global.h"
-
-
-void erl_sys_ddll_init(void) {
-}
-
-/*
- * Open a shared object
- */
-int erts_sys_ddll_open(const char *full_name, void **handle, ErtsSysDdllError* err)
-{
- return ERL_DE_ERROR_NO_DDLL_FUNCTIONALITY;
-}
-
-int erts_sys_ddll_open_noext(char *dlname, void **handle, ErtsSysDdllError* err)
-{
- return ERL_DE_ERROR_NO_DDLL_FUNCTIONALITY;
-}
-
-/*
- * Find a symbol in the shared object
- */
-int erts_sys_ddll_sym2(void *handle, const char *func_name, void **function,
- ErtsSysDdllError* err)
-{
- return ERL_DE_ERROR_NO_DDLL_FUNCTIONALITY;
-}
-
-/* XXX:PaN These two will be changed with new driver interface! */
-
-/*
- * Load the driver init function, might appear under different names depending on object arch...
- */
-
-int erts_sys_ddll_load_driver_init(void *handle, void **function)
-{
- void *fn;
- int res;
- if ((res = erts_sys_ddll_sym2(handle, "driver_init", &fn, NULL)) != ERL_DE_NO_ERROR) {
- res = erts_sys_ddll_sym2(handle, "_driver_init", &fn, NULL);
- }
- if (res == ERL_DE_NO_ERROR) {
- *function = fn;
- }
- return res;
-}
-
-int erts_sys_ddll_load_nif_init(void *handle, void **function, ErtsSysDdllError* err)
-{
- void *fn;
- int res;
- if ((res = erts_sys_ddll_sym2(handle, "nif_init", &fn, err)) != ERL_DE_NO_ERROR) {
- res = erts_sys_ddll_sym2(handle, "_nif_init", &fn, err);
- }
- if (res == ERL_DE_NO_ERROR) {
- *function = fn;
- }
- return res;
-}
-
-/*
- * Call the driver_init function, whatever it's really called, simple on unix...
-*/
-void *erts_sys_ddll_call_init(void *function) {
- void *(*initfn)(void) = function;
- return (*initfn)();
-}
-void *erts_sys_ddll_call_nif_init(void *function) {
- return erts_sys_ddll_call_init(function);
-}
-
-
-
-/*
- * Close a chared object
- */
-int erts_sys_ddll_close2(void *handle, ErtsSysDdllError* err)
-{
- return ERL_DE_ERROR_NO_DDLL_FUNCTIONALITY;
-}
-
-
-/*
- * Return string that describes the (current) error
- */
-char *erts_sys_ddll_error(int code)
-{
- return "Unspecified error";
-}
-
-void erts_sys_ddll_free_error(ErtsSysDdllError* err)
-{
- if (err->str != NULL) {
- erts_free(ERTS_ALC_T_DDLL_TMP_BUF, err->str);
- }
-}
diff --git a/erts/emulator/sys/ose/erl_poll.c b/erts/emulator/sys/ose/erl_poll.c
deleted file mode 100644
index c690f08dea..0000000000
--- a/erts/emulator/sys/ose/erl_poll.c
+++ /dev/null
@@ -1,818 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2006-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%
- */
-
-/*
- * Description: Poll interface suitable for ERTS on OSE with or without
- * SMP support.
- *
- * The interface is currently implemented using:
- * - receive + receive_fsem
- *
- * Author: Lukas Larsson
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "erl_thr_progress.h"
-#include "erl_driver.h"
-#include "erl_alloc.h"
-#include "erl_poll.h"
-
-#define NOFILE 4096
-
-/*
- * Some debug macros
- */
-
-/* #define HARDDEBUG
-#define HARDTRACE*/
-#ifdef HARDDEBUG
-#ifdef HARDTRACE
-#define HARDTRACEF(X, ...) { fprintf(stderr, X, __VA_ARGS__); fprintf(stderr,"\r\n"); }
-#else
-#define HARDTRACEF(...)
-#endif
-
-#else
-#define HARDTRACEF(X,...)
-#define HARDDEBUGF(...)
-#endif
-
-#if 0
-#define ERTS_POLL_DEBUG_PRINT
-#endif
-
-#if defined(DEBUG) && 0
-#define HARD_DEBUG
-#endif
-
-# define SEL_ALLOC erts_alloc
-# define SEL_REALLOC realloc_wrap
-# define SEL_FREE erts_free
-
-#ifdef ERTS_SMP
-
-#define ERTS_POLLSET_LOCK(PS) \
- erts_smp_mtx_lock(&(PS)->mtx)
-#define ERTS_POLLSET_UNLOCK(PS) \
- erts_smp_mtx_unlock(&(PS)->mtx)
-
-#else
-
-#define ERTS_POLLSET_LOCK(PS)
-#define ERTS_POLLSET_UNLOCK(PS)
-
-#endif
-
-/*
- * --- Data types ------------------------------------------------------------
- */
-
-union SIGNAL {
- SIGSELECT sig_no;
-};
-
-typedef struct erts_sigsel_item_ ErtsSigSelItem;
-
-struct erts_sigsel_item_ {
- ErtsSigSelItem *next;
- ErtsSysFdType fd;
- ErtsPollEvents events;
-};
-
-typedef struct erts_sigsel_info_ ErtsSigSelInfo;
-
-struct erts_sigsel_info_ {
- ErtsSigSelInfo *next;
- SIGSELECT signo;
- ErlDrvOseEventId (*decode)(union SIGNAL* sig);
- ErtsSigSelItem *fds;
-};
-
-struct ErtsPollSet_ {
- SIGSELECT *sigs;
- ErtsSigSelInfo *info;
- Uint sig_count;
- Uint item_count;
- PROCESS interrupt;
- erts_atomic32_t wakeup_state;
- erts_atomic64_t timeout_time;
-#ifdef ERTS_SMP
- erts_smp_mtx_t mtx;
-#endif
-};
-
-static int max_fds = -1;
-
-static ERTS_INLINE void
-init_timeout_time(ErtsPollSet ps)
-{
- erts_atomic64_init_nob(&ps->timeout_time,
- (erts_aint64_t) ERTS_MONOTONIC_TIME_MAX);
-}
-
-static ERTS_INLINE void
-set_timeout_time(ErtsPollSet ps, ErtsMonotonicTime time)
-{
- erts_atomic64_set_relb(&ps->timeout_time,
- (erts_aint64_t) time);
-}
-
-static ERTS_INLINE ErtsMonotonicTime
-get_timeout_time(ErtsPollSet ps)
-{
- return (ErtsMonotonicTime) erts_atomic64_read_acqb(&ps->timeout_time);
-}
-
-#define ERTS_POLL_NOT_WOKEN ((erts_aint32_t) (1 << 0))
-#define ERTS_POLL_WOKEN_INTR ((erts_aint32_t) (1 << 1))
-#define ERTS_POLL_WOKEN_TIMEDOUT ((erts_aint32_t) (1 << 2))
-#define ERTS_POLL_WOKEN_IO_READY ((erts_aint32_t) (1 << 3))
-#define ERTS_POLL_SLEEPING ((erts_aint32_t) (1 << 4))
-
-/* signal list prototypes */
-static ErtsSigSelInfo *get_sigsel_info(ErtsPollSet ps, SIGSELECT signo);
-static ErtsSigSelItem *get_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd);
-static ErtsSigSelInfo *add_sigsel_info(ErtsPollSet ps, ErtsSysFdType fd,
- ErlDrvOseEventId (*decode)(union SIGNAL* sig));
-static ErtsSigSelItem *add_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd,
- ErlDrvOseEventId (*decode)(union SIGNAL* sig));
-static int del_sigsel_info(ErtsPollSet ps, ErtsSigSelInfo *info);
-static int del_sigsel_item(ErtsPollSet ps, ErtsSigSelItem *item);
-static int update_sigsel(ErtsPollSet ps);
-
-static ErtsSigSelInfo *
-get_sigsel_info(ErtsPollSet ps, SIGSELECT signo) {
- ErtsSigSelInfo *curr = ps->info;
- while (curr != NULL) {
- if (curr->signo == signo)
- return curr;
- curr = curr->next;
- }
- return NULL;
-}
-
-static ErtsSigSelItem *
-get_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd) {
- ErtsSigSelInfo *info = get_sigsel_info(ps,fd->signo);
- ErtsSigSelItem *curr;
-
- if (info == NULL)
- return NULL;
-
- curr = info->fds;
-
- while (curr != NULL) {
- if (curr->fd->id == fd->id) {
- ASSERT(curr->fd->signo == fd->signo);
- return curr;
- }
- curr = curr->next;
- }
- return NULL;
-}
-
-static ErtsSigSelInfo *
-add_sigsel_info(ErtsPollSet ps, ErtsSysFdType fd,
- ErlDrvOseEventId (*decode)(union SIGNAL* sig)) {
- ErtsSigSelInfo *info = SEL_ALLOC(ERTS_ALC_T_POLLSET,
- sizeof(ErtsSigSelInfo));
- info->next = ps->info;
- info->fds = NULL;
- info->signo = fd->signo;
- info->decode = decode;
- ps->info = info;
- ps->sig_count++;
- return info;
-}
-
-static ErtsSigSelItem *
-add_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd,
- ErlDrvOseEventId (*decode)(union SIGNAL* sig)) {
- ErtsSigSelInfo *info = get_sigsel_info(ps,fd->signo);
- ErtsSigSelItem *item = SEL_ALLOC(ERTS_ALC_T_POLLSET,
- sizeof(ErtsSigSelItem));
- if (info == NULL)
- info = add_sigsel_info(ps, fd, decode);
- if (info->decode != decode) {
- erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
- erts_dsprintf(dsbufp, "erts_poll_control() inconsistency: multiple resolve_signal functions for same signal (%d)\n",
- fd->signo);
- erts_send_error_to_logger_nogl(dsbufp);
- }
- ASSERT(info->decode == decode);
- item->next = info->fds;
- item->fd = fd;
- item->events = 0;
- info->fds = item;
- ps->item_count++;
- return item;
-}
-
-static int del_sigsel_info(ErtsPollSet ps, ErtsSigSelInfo *info) {
- ErtsSigSelInfo *curr, *prev;
-
- if (ps->info == info) {
- ps->info = ps->info->next;
- } else {
- curr = ps->info->next;
- prev = ps->info;
-
- while (curr != info) {
- if (curr == NULL)
- return 1;
- prev = curr;
- curr = curr->next;
- }
- prev->next = curr->next;
- }
-
- ps->sig_count--;
- SEL_FREE(ERTS_ALC_T_POLLSET, info);
- return 0;
-}
-
-static int del_sigsel_item(ErtsPollSet ps, ErtsSigSelItem *item) {
- ErtsSigSelInfo *info = get_sigsel_info(ps,item->fd->signo);
- ErtsSigSelItem *curr, *prev;
-
- ps->item_count--;
- ASSERT(ps->item_count >= 0);
-
- if (info->fds == item) {
- info->fds = info->fds->next;
- SEL_FREE(ERTS_ALC_T_POLLSET,item);
- if (info->fds == NULL)
- return del_sigsel_info(ps,info);
- return 0;
- }
-
- curr = info->fds->next;
- prev = info->fds;
-
- while (curr != item) {
- if (curr == NULL) {
- /* We did not find an item to delete so we have to
- * increment item count again.
- */
- ps->item_count++;
- return 1;
- }
- prev = curr;
- curr = curr->next;
- }
- prev->next = curr->next;
- SEL_FREE(ERTS_ALC_T_POLLSET,item);
- return 0;
-}
-
-#ifdef ERTS_SMP
-
-static void update_redir_tables(ErtsPollSet ps) {
- struct OS_redir_entry *redir_table;
- PROCESS sched_1 = ERTS_SCHEDULER_IX(0)->tid.id;
- int i;
- redir_table = SEL_ALLOC(ERTS_ALC_T_POLLSET,
- sizeof(struct OS_redir_entry)*(ps->sig_count+1));
-
- redir_table[0].sig = ps->sig_count+1;
- redir_table[0].pid = 0;
-
- for (i = 1; i < ps->sig_count+1; i++) {
- redir_table[i].sig = ps->sigs[i];
- redir_table[i].pid = sched_1;
- }
-
- for (i = 1; i < erts_no_schedulers; i++) {
- ErtsSchedulerData *esdp = ERTS_SCHEDULER_IX(i);
- set_redirection(esdp->tid.id,redir_table);
- }
-
- SEL_FREE(ERTS_ALC_T_POLLSET,redir_table);
-}
-
-#endif
-
-static int update_sigsel(ErtsPollSet ps) {
- ErtsSigSelInfo *info = ps->info;
-
- int i;
-
- if (ps->sigs != NULL)
- SEL_FREE(ERTS_ALC_T_POLLSET,ps->sigs);
-
- if (ps->sig_count == 0) {
- /* If there are no signals we place a non-valid signal to make sure that
- * we do not trigger on a any unrelated signals which are sent to the
- * process.
- */
- ps->sigs = SEL_ALLOC(ERTS_ALC_T_POLLSET,sizeof(SIGSELECT)*(2));
- ps->sigs[0] = 1;
- ps->sigs[1] = ERTS_SIGNAL_INVALID;
- return 0;
- }
-
- ps->sigs = SEL_ALLOC(ERTS_ALC_T_POLLSET,sizeof(SIGSELECT)*(ps->sig_count+1));
- ps->sigs[0] = ps->sig_count;
-
- for (i = 1; info != NULL; i++, info = info->next)
- ps->sigs[i] = info->signo;
-
-#ifdef ERTS_SMP
- update_redir_tables(ps);
-#endif
-
- return 0;
-}
-
-static ERTS_INLINE void
-wake_poller(ErtsPollSet ps)
-{
- erts_aint32_t wakeup_state;
-
- ERTS_THR_MEMORY_BARRIER;
- wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
- while (wakeup_state != ERTS_POLL_WOKEN_IO_READY
- && wakeup_state != ERTS_POLL_WOKEN_INTR) {
- erts_aint32_t act = erts_atomic32_cmpxchg_nob(&ps->wakeup_state,
- ERTS_POLL_WOKEN_INTR,
- wakeup_state);
- if (act == wakeup_state) {
- wakeup_state = act;
- break;
- }
- wakeup_state = act;
- }
- if (wakeup_state == ERTS_POLL_SLEEPING) {
- /*
- * Since we don't know the internals of signal_fsem() we issue
- * a memory barrier as a safety precaution ensuring that
- * the store we just made to wakeup_state wont be reordered
- * with loads in signal_fsem().
- */
- ERTS_THR_MEMORY_BARRIER;
- signal_fsem(ps->interrupt);
- }
-}
-
-static ERTS_INLINE void
-reset_interrupt(ErtsPollSet ps)
-{
- /* We need to keep io-ready if set */
- erts_aint32_t wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
- while (wakeup_state != ERTS_POLL_NOT_WOKEN &&
- wakeup_state != ERTS_POLL_SLEEPING) {
- erts_aint32_t act = erts_atomic32_cmpxchg_nob(&ps->wakeup_state,
- ERTS_POLL_NOT_WOKEN,
- wakeup_state);
- if (wakeup_state == act)
- break;
- wakeup_state = act;
- }
- ERTS_THR_MEMORY_BARRIER;
-}
-
-static ERTS_INLINE void
-set_interrupt(ErtsPollSet ps)
-{
- wake_poller(ps);
-}
-
-void erts_poll_interrupt(ErtsPollSet ps,int set) {
- HARDTRACEF("erts_poll_interrupt called!\n");
-
- if (!set)
- reset_interrupt(ps);
- else
- set_interrupt(ps);
-
-}
-
-void erts_poll_interrupt_timed(ErtsPollSet ps,
- int set,
- ErtsTimeoutTime timeout_time) {
- HARDTRACEF("erts_poll_interrupt_timed called!\n");
-
- if (!set)
- reset_interrupt(ps);
- else if (get_timeout_time(ps) > timeout_time)
- set_interrupt(ps);
-}
-
-ErtsPollEvents erts_poll_control(ErtsPollSet ps, ErtsSysFdType fd,
- ErtsPollEvents pe, int on, int* do_wake) {
- ErtsSigSelItem *curr;
- ErtsPollEvents new_events;
- int old_sig_count;
-
- HARDTRACEF(
- "%ux: In erts_poll_control, fd = %d, pe = %d, on = %d, *do_wake = %d, curr = 0x%xu",
- ps, fd, pe, on, do_wake, curr);
-
- ERTS_POLLSET_LOCK(ps);
-
- if (on && (pe & ERTS_POLL_EV_IN) && (pe & ERTS_POLL_EV_OUT)) {
- /* Check to make sure both in and out are not used at the same time */
- new_events = ERTS_POLL_EV_NVAL;
- goto done;
- }
-
- curr = get_sigsel_item(ps, fd);
- old_sig_count = ps->sig_count;
-
- if (curr == NULL && on) {
- curr = add_sigsel_item(ps, fd, fd->resolve_signal);
- } else if (curr == NULL && !on) {
- new_events = ERTS_POLL_EV_NVAL;
- goto done;
- }
-
- new_events = curr->events;
-
- if (pe == 0) {
- *do_wake = 0;
- goto done;
- }
-
- if (on) {
- new_events |= pe;
- curr->events = new_events;
- } else {
- new_events &= ~pe;
- curr->events = new_events;
- if (new_events == 0 && del_sigsel_item(ps, curr)) {
- new_events = ERTS_POLL_EV_NVAL;
- goto done;
- }
- }
-
- if (ps->sig_count != old_sig_count) {
- if (update_sigsel(ps))
- new_events = ERTS_POLL_EV_NVAL;
- }
-done:
- ERTS_POLLSET_UNLOCK(ps);
- HARDTRACEF("%ux: Out erts_poll_control", ps);
- return new_events;
-}
-
-int erts_poll_wait(ErtsPollSet ps,
- ErtsPollResFd pr[],
- int *len,
- ErtsMonotonicTime timeout_time)
-{
- int res = ETIMEDOUT, no_fds, currid = 0;
- OSTIME timeout;
- union SIGNAL *sig;
- ErtsMonotonicTime current_time, diff_time, timeout;
- // HARDTRACEF("%ux: In erts_poll_wait",ps);
- if (ps->interrupt == (PROCESS)0)
- ps->interrupt = current_process();
-
- ASSERT(current_process() == ps->interrupt);
- ASSERT(get_fsem(current_process()) == 0);
- ASSERT(erts_atomic32_read_nob(&ps->wakeup_state) &
- (ERTS_POLL_NOT_WOKEN | ERTS_POLL_WOKEN_INTR));
- /* Max no of spots avable in pr */
- no_fds = *len;
-
- *len = 0;
-
- /* erts_printf("Entering erts_poll_wait(), timeout_time=%bps\n",
- timeout_time); */
-
- if (timeout_time == ERTS_POLL_NO_TIMEOUT) {
- no_timeout:
- timeout = (OSTIME) 0;
- save_timeout_time = ERTS_MONOTONIC_TIME_MIN;
- }
- else {
- ErtsMonotonicTime current_time, diff_time;
- current_time = erts_get_monotonic_time(NULL);
- diff_time = timeout_time - current_time;
- if (diff_time <= 0)
- goto no_timeout;
- diff_time = (ERTS_MONOTONIC_TO_MSEC(diff_time - 1) + 1);
- if (diff_time > INT_MAX)
- diff_time = INT_MAX;
- timeout = (OSTIME) diff_time;
- save_timeout_time = current_time;
- save_timeout_time += ERTS_MSEC_TO_MONOTONIC(diff_time);
- }
-
- set_timeout_time(ps, save_timeout_time);
-
- while (currid < no_fds) {
- if (timeout > 0) {
- erts_aint32_t act = erts_atomic32_cmpxchg_nob(&ps->wakeup_state,
- ERTS_POLL_SLEEPING,
- ERTS_POLL_NOT_WOKEN);
- if (act == ERTS_POLL_NOT_WOKEN) {
-#ifdef ERTS_SMP
- erts_thr_progress_prepare_wait(NULL);
-#endif
- sig = receive_fsem(timeout, ps->sigs, 1);
-#ifdef ERTS_SMP
- erts_thr_progress_finalize_wait(NULL);
-#endif
- } else {
- ASSERT(act == ERTS_POLL_WOKEN_INTR);
- sig = OS_RCV_FSEM;
- }
- } else
- sig = receive_w_tmo(0, ps->sigs);
-
- if (sig == NULL) {
- if (timeout > 0) {
- erts_aint32_t act = erts_atomic32_cmpxchg_nob(&ps->wakeup_state,
- ERTS_POLL_WOKEN_TIMEDOUT,
- ERTS_POLL_SLEEPING);
- if (act == ERTS_POLL_WOKEN_INTR)
- /* Restore fsem as it was signaled but we got a timeout */
- wait_fsem(1);
- } else
- erts_atomic32_cmpxchg_nob(&ps->wakeup_state,
- ERTS_POLL_WOKEN_TIMEDOUT,
- ERTS_POLL_NOT_WOKEN);
- break;
- } else if (sig == OS_RCV_FSEM) {
- ASSERT(erts_atomic32_read_nob(&ps->wakeup_state) == ERTS_POLL_WOKEN_INTR);
- break;
- }
- {
- ErtsSigSelInfo *info = get_sigsel_info(ps, sig->sig_no);
- struct erts_sys_fd_type fd = { sig->sig_no, info->decode(sig) };
- ErtsSigSelItem *item = get_sigsel_item(ps, &fd);
-
- ASSERT(sig);
- if (currid == 0 && timeout > 0) {
- erts_aint32_t act = erts_atomic32_cmpxchg_nob(&ps->wakeup_state,
- ERTS_POLL_WOKEN_IO_READY,
- ERTS_POLL_SLEEPING);
- if (act == ERTS_POLL_WOKEN_INTR) {
- /* Restore fsem as it was signaled but we got a msg */
- wait_fsem(1);
- act = erts_atomic32_cmpxchg_nob(&ps->wakeup_state,
- ERTS_POLL_WOKEN_IO_READY,
- ERTS_POLL_WOKEN_INTR);
- }
- } else if (currid == 0) {
- erts_atomic32_set_nob(&ps->wakeup_state,
- ERTS_POLL_WOKEN_IO_READY);
- }
-
- if (item == NULL) {
- erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
- erts_dsprintf(
- dsbufp,
- "erts_poll_wait() failed: found unkown signal id %d (signo %u) "
- "(curr_proc 0x%x)\n",
- fd.id, fd.signo, current_process());
- erts_send_error_to_logger_nogl(dsbufp);
- timeout = 0;
- /* Under normal circumstances the signal is deallocated by the
- * driver that issued the select operation. But in this case
- * there's no driver waiting for such signal so we have to
- * deallocate it here */
- if (sig)
- free_buf(&sig);
- } else {
- int i;
- struct erts_sys_fd_type *fd = NULL;
- ErtsPollOseMsgList *tl,*new;
-
- /* Check if this fd has already been triggered by a previous signal */
- for (i = 0; i < currid;i++) {
- if (pr[i].fd == item->fd) {
- fd = pr[i].fd;
- pr[i].events |= item->events;
- break;
- }
- }
-
- /* First time this fd is triggered */
- if (fd == NULL) {
- pr[currid].fd = item->fd;
- pr[currid].events = item->events;
- fd = item->fd;
- timeout = 0;
- currid++;
- }
-
- /* Insert new signal in approriate list */
- new = erts_alloc(ERTS_ALC_T_FD_SIG_LIST,sizeof(ErtsPollOseMsgList));
- new->next = NULL;
- new->data = sig;
-
- ethr_mutex_lock(&fd->mtx);
- tl = fd->msgs;
-
- if (tl == NULL) {
- fd->msgs = new;
- } else {
- while (tl->next != NULL)
- tl = tl->next;
- tl->next = new;
- }
- ethr_mutex_unlock(&fd->mtx);
- }
-
- }
- }
-
- {
- erts_aint32_t wakeup_state = erts_atomic32_read_nob(&ps->wakeup_state);
-
- switch (wakeup_state) {
- case ERTS_POLL_WOKEN_IO_READY:
- res = 0;
- break;
- case ERTS_POLL_WOKEN_INTR:
- res = EINTR;
- break;
- case ERTS_POLL_WOKEN_TIMEDOUT:
- res = ETIMEDOUT;
- break;
- case ERTS_POLL_NOT_WOKEN:
- /* This happens when we get an invalid signal only */
- res = EINVAL;
- break;
- default:
- res = 0;
- erts_exit(ERTS_ABORT_EXIT,
- "%s:%d: Internal error: Invalid wakeup_state=%d\n",
- __FILE__, __LINE__, (int) wakeup_state);
- }
- }
-
- erts_atomic32_set_nob(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN);
- set_timeout_time(ps, ERTS_MONOTONIC_TIME_MAX);
-
- *len = currid;
-
- // HARDTRACEF("%ux: Out erts_poll_wait",ps);
- return res;
-}
-
-int erts_poll_max_fds(void)
-{
-
- HARDTRACEF("In/Out erts_poll_max_fds -> %d",max_fds);
- return max_fds;
-}
-
-void erts_poll_info(ErtsPollSet ps,
- ErtsPollInfo *pip)
-{
- Uint size = 0;
- Uint num_events = 0;
-
- size += sizeof(struct ErtsPollSet_);
- size += sizeof(ErtsSigSelInfo)*ps->sig_count;
- size += sizeof(ErtsSigSelItem)*ps->item_count;
- size += sizeof(SIGSELECT)*(ps->sig_count+1);
-
- pip->primary = "receive_fsem";
-
- pip->fallback = NULL;
-
- pip->kernel_poll = NULL;
-
- pip->memory_size = size;
-
- pip->poll_set_size = num_events;
-
- pip->fallback_poll_set_size = 0;
-
- pip->lazy_updates = 0;
-
- pip->pending_updates = 0;
-
- pip->batch_updates = 0;
-
- pip->concurrent_updates = 0;
-
-
- pip->max_fds = erts_poll_max_fds();
- HARDTRACEF("%ux: Out erts_poll_info",ps);
-
-}
-
-ErtsPollSet erts_poll_create_pollset(void)
-{
- ErtsPollSet ps = SEL_ALLOC(ERTS_ALC_T_POLLSET,
- sizeof(struct ErtsPollSet_));
-
- ps->sigs = NULL;
- ps->sig_count = 0;
- ps->item_count = 0;
- ps->info = NULL;
- ps->interrupt = (PROCESS)0;
- erts_atomic32_init_nob(&ps->wakeup_state, ERTS_POLL_NOT_WOKEN);
- init_timeout_time(ps);
-#ifdef ERTS_SMP
- erts_smp_mtx_init(&ps->mtx, "pollset");
-#endif
- update_sigsel(ps);
- HARDTRACEF("%ux: Out erts_poll_create_pollset",ps);
- return ps;
-}
-
-void erts_poll_destroy_pollset(ErtsPollSet ps)
-{
- ErtsSigSelInfo *info;
- for (info = ps->info; ps->info != NULL; info = ps->info, ps->info = ps->info->next) {
- ErtsSigSelItem *item;
- for (item = info->fds; info->fds != NULL; item = info->fds, info->fds = info->fds->next)
- SEL_FREE(ERTS_ALC_T_POLLSET, item);
- SEL_FREE(ERTS_ALC_T_POLLSET, info);
- }
-
- SEL_FREE(ERTS_ALC_T_POLLSET,ps->sigs);
-
-#ifdef ERTS_SMP
- erts_smp_mtx_destroy(&ps->mtx);
-#endif
-
- SEL_FREE(ERTS_ALC_T_POLLSET,ps);
-}
-
-void erts_poll_init(void)
-{
- HARDTRACEF("In %s", __FUNCTION__);
- max_fds = 256;
-
- HARDTRACEF("Out %s", __FUNCTION__);
-}
-
-
-/* OSE driver functions */
-
-union SIGNAL *erl_drv_ose_get_signal(ErlDrvEvent drv_ev) {
- struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev;
- ethr_mutex_lock(&ev->mtx);
- if (ev->msgs == NULL) {
- ethr_mutex_unlock(&ev->mtx);
- return NULL;
- } else {
- ErtsPollOseMsgList *msg = ev->msgs;
- union SIGNAL *sig = (union SIGNAL*)msg->data;
- ASSERT(msg->data);
- ev->msgs = msg->next;
- ethr_mutex_unlock(&ev->mtx);
- erts_free(ERTS_ALC_T_FD_SIG_LIST,msg);
- restore(sig);
- return sig;
- }
-}
-
-ErlDrvEvent
-erl_drv_ose_event_alloc(SIGSELECT signo, ErlDrvOseEventId id,
- ErlDrvOseEventId (*resolve_signal)(union SIGNAL *sig), void *extra) {
- struct erts_sys_fd_type *ev = erts_alloc(ERTS_ALC_T_DRV_EV,
- sizeof(struct erts_sys_fd_type));
- ev->signo = signo;
- ev->extra = extra;
- ev->id = id;
- ev->msgs = NULL;
- ev->resolve_signal = resolve_signal;
- ethr_mutex_init(&ev->mtx);
- return (ErlDrvEvent)ev;
-}
-
-void erl_drv_ose_event_free(ErlDrvEvent drv_ev) {
- struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev;
- ASSERT(ev->msgs == NULL);
- ethr_mutex_destroy(&ev->mtx);
- erts_free(ERTS_ALC_T_DRV_EV,ev);
-}
-
-void erl_drv_ose_event_fetch(ErlDrvEvent drv_ev, SIGSELECT *signo,
- ErlDrvOseEventId *id, void **extra) {
- struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev;
- if (signo)
- *signo = ev->signo;
- if (extra)
- *extra = ev->extra;
- if (id)
- *id = ev->id;
-}
diff --git a/erts/emulator/sys/ose/erts.sig b/erts/emulator/sys/ose/erts.sig
deleted file mode 100644
index 78b883ee6c..0000000000
--- a/erts/emulator/sys/ose/erts.sig
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef ERTS_OSE_SIGNALS
-#define ERTS_OSE_SIGNALS
-
-#ifndef ERTS_OSE_SIGNAL_BASE
-#define ERTS_OSE_SIGNAL_BASE 0x01900280
-#endif
-
-#define ERTS_SIGNAL_INVALID ERTS_OSE_SIGNAL_BASE
-#define ERTS_SIGNAL_FD_DRV_CONFIG ERTS_OSE_SIGNAL_BASE+1
-#define ERTS_SIGNAL_FD_DRV_ASYNC ERTS_OSE_SIGNAL_BASE+2
-#define ERTS_SIGNAL_OSE_DRV_ATTACH ERTS_OSE_SIGNAL_BASE+3
-#define ERTS_SIGNAL_OSE_DRV_HUNT ERTS_OSE_SIGNAL_BASE+4
-
-#define ERTS_SIGNAL_RUN_ERL_SETUP ERTS_OSE_SIGNAL_BASE+100
-#define ERTS_SIGNAL_RUN_ERL_DAEMON ERTS_OSE_SIGNAL_BASE+101
-
-#endif
diff --git a/erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf b/erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf
deleted file mode 100644
index a19d23facf..0000000000
--- a/erts/emulator/sys/ose/gcc_4.4.3_lm_ppc.lcf
+++ /dev/null
@@ -1,182 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2013-2014 by Enea Software AB,
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the copyright holder nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- ******************************************************************************/
-
-OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc")
-OUTPUT_ARCH("powerpc")
-ENTRY("crt0_lm")
-MEMORY
-{
- rom : ORIGIN = 0x01000000, LENGTH = 0x01000000
- ram : ORIGIN = 0x02000000, LENGTH = 0x01000000
-}
-PHDRS
-{
- ph_conf PT_LOAD ;
- ph_rom PT_LOAD ;
- ph_ram PT_LOAD ;
-}
-SECTIONS
-{
- .text :
- {
- *(.text_first)
- *(.text)
- *(.text.*)
- *(.stub)
- *(oscode)
- *(.init*)
- *(.fini*)
- *(.gnu.warning)
- *(.gnu.linkonce.t.*)
- *(.glue_7t)
- *(.glue_7)
- } > rom :ph_rom = 0
- .ose_sfk_biosentry :
- {
- *(.ose_sfk_biosentry)
- } > rom :ph_rom
- .ctors :
- {
- __CTOR_LIST__ = .;
- *(.ctors)
- *(SORT(.ctors.*))
- __CTOR_END__ = .;
- } > rom :ph_rom
- .dtors :
- {
- __DTOR_LIST__ = .;
- *(.dtors)
- *(SORT(.dtors.*))
- __DTOR_END__ = .;
- } > rom :ph_rom
- OSESYMS :
- {
- *(.osesyms)
- } > rom :ph_rom
- .rodata :
- {
- *(.rodata)
- *(.rodata.*)
- *(.gnu.linkonce.r.*)
- } > rom :ph_rom
- .eh_frame_hdr :
- {
- *(.eh_frame_hdr)
- } > rom :ph_rom
- .eh_frame :
- {
- __EH_FRAME_BEGIN__ = .;
- *(.eh_frame)
- LONG(0)
- __EH_FRAME_END__ = .;
- } > rom :ph_rom
- .gcc_except_table :
- {
- *(.gcc_except_table .gcc_except_table.*)
- } > rom :ph_rom
- .sdata2 :
- {
- PROVIDE (_SDA2_BASE_ = .);
- *(.sdata2)
- *(.sdata2.*)
- *(.gnu.linkonce.s2.*)
- } > rom :ph_rom
- .sbss2 :
- {
- *(.sbss2)
- *(.sbss2.*)
- *(.gnu.linkonce.sb2.*)
- } > rom :ph_rom
- LMCONF :
- {
- obj/?*?/ose_confd.o(.rodata)
- *(LMCONF)
- } > rom :ph_conf
- .data :
- {
- LONG(0xDEADBABE)
- *(.data)
- *(.data.*)
- *(.gnu.linkonce.d.*)
- SORT(CONSTRUCTORS)
- . = ALIGN(0x10);
- } > ram :ph_ram = 0
- .sdata2 :
- {
- _SDA2_BASE_ = .;
- *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
- }> ram :ph_ram
- .sdata :
- {
- PROVIDE (_SDA_BASE_ = .);
- *(.sdata)
- *(.sdata.*)
- *(.gnu.linkonce.s.*)
- } > ram :ph_ram
- .sbss :
- {
- *(.sbss)
- *(.sbss.*)
- *(.scommon)
- *(.gnu.linkonce.sb.*)
- } > ram :ph_ram
- .bss (NOLOAD) :
- {
- *(.bss)
- *(.bss.*)
- *(COMMON)
- *(.gnu.linkonce.b.*)
- *(.osvars)
- } > ram :ph_ram
- .ignore (NOLOAD) :
- {
- *(.rel.dyn)
- } > ram :ph_ram
- .debug 0 : { *(.debug) }
- .line 0 : { *(.line) }
- .debug_srcinfo 0 : { *(.debug_srcinfo) }
- .debug_sfnames 0 : { *(.debug_sfnames) }
- .debug_aranges 0 : { *(.debug_aranges) }
- .debug_pubnames 0 : { *(.debug_pubnames) }
- .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
- .debug_abbrev 0 : { *(.debug_abbrev) }
- .debug_line 0 : { *(.debug_line) }
- .debug_frame 0 : { *(.debug_frame) }
- .debug_str 0 : { *(.debug_str) }
- .debug_loc 0 : { *(.debug_loc) }
- .debug_macinfo 0 : { *(.debug_macinfo) }
- .debug_weaknames 0 : { *(.debug_weaknames) }
- .debug_funcnames 0 : { *(.debug_funcnames) }
- .debug_typenames 0 : { *(.debug_typenames) }
- .debug_varnames 0 : { *(.debug_varnames) }
-}
-__OSESYMS_START = ADDR(OSESYMS);
-__OSESYMS_END = ADDR(OSESYMS) + SIZEOF(OSESYMS);
diff --git a/erts/emulator/sys/ose/gcc_4.6.3_lm_ppc.lcf b/erts/emulator/sys/ose/gcc_4.6.3_lm_ppc.lcf
deleted file mode 100644
index 3440c2961b..0000000000
--- a/erts/emulator/sys/ose/gcc_4.6.3_lm_ppc.lcf
+++ /dev/null
@@ -1,242 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2013-2014 by Enea Software AB,
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the copyright holder nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- ******************************************************************************/
-
-OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc")
-OUTPUT_ARCH("powerpc")
-
-ENTRY("crt0_lm")
-
-/* Note:
- * You may have to increase the length of the "rom" memory region and the
- * origin and length of the "ram" memory region below depending on the size
- * of the code and data in your load module.
- */
-
-MEMORY
-{
- conf : ORIGIN = 0x00100000, LENGTH = 0x00030000
- rom : ORIGIN = 0x01000000, LENGTH = 0x01000000
- ram : ORIGIN = 0x03000000, LENGTH = 0x01000000
-}
-
-PHDRS
-{
- ph_conf PT_LOAD ;
- ph_rom PT_LOAD ;
- ph_ram PT_LOAD ;
-}
-
-SECTIONS
-{
-/*---------------------------------------------------------------------------
- * Load module configuration area
- *-------------------------------------------------------------------------*/
-
- /* Load module configuration section. */
- LMCONF :
- {
- obj/?*?/ose_confd.o(.rodata)
- *(LMCONF)
- } > conf :ph_conf
-
-/*---------------------------------------------------------------------------
- * Read-only area
- *-------------------------------------------------------------------------*/
-
- /* Code section. */
- .text :
- {
- *(.text)
- *(.text.*)
- *(.stub)
- *(oscode)
- *(.init*)
- *(.fini*)
- *(.gnu.warning)
- *(.gnu.linkonce.t.*)
- } > rom :ph_rom = 0
-
- /* OSE symbols section. */
- OSESYMS :
- {
- *(.osesyms)
- } > rom :ph_rom
-
- /* Read-only data section. */
- .rodata :
- {
- *(.rodata)
- *(.rodata.*)
- *(.gnu.linkonce.r.*)
- } > rom :ph_rom
-
- /* C++ exception handling section. */
- .eh_frame :
- {
- __EH_FRAME_BEGIN__ = .;
- *(.eh_frame)
- LONG(0)
- __EH_FRAME_END__ = .;
- } > rom :ph_rom
-
- /* C++ exception handling section. */
- .gcc_except_table :
- {
- *(.gcc_except_table .gcc_except_table.*)
- } > rom :ph_rom
-
- /* PowerPC EABI initialized read-only data section. */
- .sdata2 :
- {
- PROVIDE (_SDA2_BASE_ = .);
- *(.sdata2)
- *(.sdata2.*)
- *(.gnu.linkonce.s2.*)
- } > rom :ph_rom
-
- /* PowerPC EABI uninitialized read-only data section. */
- .sbss2 :
- {
- *(.sbss2)
- *(.sbss2.*)
- *(.gnu.linkonce.sb2.*)
- } > rom :ph_rom
-
-/*---------------------------------------------------------------------------
- * Read-write area
- *-------------------------------------------------------------------------*/
-
- /*-------------------------------------------------------------------
- * Initialized data (copied by PM)
- *-----------------------------------------------------------------*/
-
- /* Data section. */
- .data :
- {
- *(.data)
- *(.data.*)
- *(.gnu.linkonce.d.*)
- SORT(CONSTRUCTORS)
- } > ram :ph_ram
-
- /* C++ constructor section. */
- .ctors :
- {
- __CTOR_LIST__ = .;
- *(.ctors)
- *(SORT(.ctors.*))
- __CTOR_END__ = .;
- } > ram :ph_ram
-
- /* C++ destructor section. */
- .dtors :
- {
- __DTOR_LIST__ = .;
- *(.dtors)
- *(SORT(.dtors.*))
- __DTOR_END__ = .;
- } > ram :ph_ram
-
-
- /* Small data section. */
- .sdata ALIGN(0x10) :
- {
- PROVIDE (_SDA_BASE_ = .);
- *(.sdata)
- *(.sdata.*)
- *(.gnu.linkonce.s.*)
- } > ram :ph_ram
-
- /*-------------------------------------------------------------------
- * Uninitialized data (cleared by PM)
- *-----------------------------------------------------------------*/
-
- /* Small bss section. */
- .sbss :
- {
- *(.sbss)
- *(.sbss.*)
- *(.scommon)
- *(.gnu.linkonce.sb.*)
- } > ram :ph_ram
-
- /* Bss section. */
- .bss :
- {
- *(.bss)
- *(.bss.*)
- *(COMMON)
- *(.gnu.linkonce.b.*)
- } > ram :ph_ram
-
-/*---------------------------------------------------------------------------
- * Debug information
- *-------------------------------------------------------------------------*/
-
- /*
- * Stabs debug sections.
- */
-
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
-
- /*
- * DWARF debug sections.
- */
-
- /* DWARF 1 */
- .debug 0 : { *(.debug) }
- .line 0 : { *(.line) }
- /* GNU DWARF 1 extensions */
- .debug_srcinfo 0 : { *(.debug_srcinfo) }
- .debug_sfnames 0 : { *(.debug_sfnames) }
- /* DWARF 1.1 and DWARF 2 */
- .debug_aranges 0 : { *(.debug_aranges) }
- .debug_pubnames 0 : { *(.debug_pubnames) }
- /* DWARF 2 */
- .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
- .debug_abbrev 0 : { *(.debug_abbrev) }
- .debug_line 0 : { *(.debug_line) }
- .debug_frame 0 : { *(.debug_frame) }
- .debug_str 0 : { *(.debug_str) }
- .debug_loc 0 : { *(.debug_loc) }
- .debug_macinfo 0 : { *(.debug_macinfo) }
- /* SGI/MIPS DWARF 2 extensions */
- .debug_weaknames 0 : { *(.debug_weaknames) }
- .debug_funcnames 0 : { *(.debug_funcnames) }
- .debug_typenames 0 : { *(.debug_typenames) }
- .debug_varnames 0 : { *(.debug_varnames) }
-}
diff --git a/erts/emulator/sys/ose/sys.c b/erts/emulator/sys/ose/sys.c
deleted file mode 100644
index e354faf02c..0000000000
--- a/erts/emulator/sys/ose/sys.c
+++ /dev/null
@@ -1,1847 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-2013. 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%
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-#include "sys/time.h"
-#include "time.h"
-#include "sys/uio.h"
-#include "termios.h"
-#include "ctype.h"
-#include "termios.h"
-
-#ifdef HAVE_FCNTL_H
-#include "fcntl.h"
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-#include "sys/ioctl.h"
-#endif
-
-#define ERTS_WANT_BREAK_HANDLING
-#define WANT_NONBLOCKING
-#include "sys.h"
-#include "erl_thr_progress.h"
-
-#ifdef USE_THREADS
-#include "erl_threads.h"
-#endif
-
-#include "erl_mseg.h"
-
-#include "unistd.h"
-#include "efs.h"
-#include "erl_printf.h"
-#include "aio.h"
-#include "pm.h"
-#include "fcntl.h"
-
-/* Set the define to 1 to get some logging */
-#if 0
-#include "ramlog.h"
-#define LOG(output) ramlog_printf output
-#else
-#define LOG(output)
-#endif
-
-extern char **environ;
-static erts_smp_rwmtx_t environ_rwmtx;
-static PROCESS sig_proxy_pid = 0;
-
-#define MAX_VSIZE 16 /* Max number of entries allowed in an I/O
- * vector sock_sendv().
- */
-/*
- * Don't need global.h, but bif_table.h (included by bif.h),
- * won't compile otherwise
- */
-#include "global.h"
-#include "bif.h"
-
-#include "erl_sys_driver.h"
-#include "erl_check_io.h"
-#include "erl_cpu_topology.h"
-
-/* The priority for reader/writer processes */
-#define FD_PROC_PRI get_pri(current_process())
-
-typedef struct ErtsSysReportExit_ ErtsSysReportExit;
-struct ErtsSysReportExit_ {
- ErtsSysReportExit *next;
- Eterm port;
- int pid;
- int ifd;
- int ofd;
- ErlDrvEvent attach_event;
- ErlDrvEvent input_event;
- ErlDrvEvent output_event;
-};
-
-/* This data is shared by these drivers - initialized by spawn_init() */
-static struct driver_data {
- ErlDrvPort port_num;
- int ofd;
- int ifd;
- int packet_bytes;
- ErtsSysReportExit *report_exit;
- int pid;
- int alive;
- int status;
- ErlDrvEvent input_event;
- ErlDrvEvent output_event;
- struct aiocb aiocb;
- FmHandle handle;
- char *install_handle;
-} *driver_data; /* indexed by fd */
-
-struct async {
- SIGSELECT signo;
- ErlDrvTermData port;
- ErlDrvTermData proc;
- PROCESS spid;
- PROCESS target;
- Uint32 ref;
-};
-
-static ErtsSysReportExit *report_exit_list;
-static ERTS_INLINE void report_exit_status(ErtsSysReportExit *rep, int status);
-
-extern int driver_interrupt(int, int);
-extern void do_break(void);
-
-extern void erl_sys_args(int*, char**);
-
-/* The following two defs should probably be moved somewhere else */
-
-extern void erts_sys_init_float(void);
-
-extern void erl_crash_dump(char* file, int line, char* fmt, ...);
-
-#define DIR_SEPARATOR_CHAR '/'
-
-#if defined(DEBUG)
-#define ERL_BUILD_TYPE_MARKER ".debug"
-#else /* opt */
-#define ERL_BUILD_TYPE_MARKER
-#endif
-
-#define CHILD_SETUP_PROG_NAME "child_setup" ERL_BUILD_TYPE_MARKER
-
-#ifdef DEBUG
-static int debug_log = 0;
-#endif
-
-#ifdef ERTS_SMP
-static erts_smp_atomic32_t have_prepared_crash_dump;
-#define ERTS_PREPARED_CRASH_DUMP \
- ((int) erts_smp_atomic32_xchg_nob(&have_prepared_crash_dump, 1))
-#else
-static volatile int have_prepared_crash_dump;
-#define ERTS_PREPARED_CRASH_DUMP \
- (have_prepared_crash_dump++)
-#endif
-
-static erts_smp_atomic_t sys_misc_mem_sz;
-
-#if defined(ERTS_SMP)
-erts_mtx_t chld_stat_mtx;
-#endif
-
-#if defined(ERTS_SMP) /* ------------------------------------------------- */
-#define CHLD_STAT_LOCK erts_mtx_lock(&chld_stat_mtx)
-#define CHLD_STAT_UNLOCK erts_mtx_unlock(&chld_stat_mtx)
-
-#else /* ------------------------------------------------------------------- */
-#define CHLD_STAT_LOCK
-#define CHLD_STAT_UNLOCK
-static volatile int children_died;
-#endif
-
-#define SET_AIO(REQ,FD,SIZE,BUFF) \
- memset(&(REQ),0,sizeof(REQ)); \
- (REQ).aio_fildes = FD; \
- (REQ).aio_offset = FM_POSITION_CURRENT; \
- (REQ).aio_nbytes = SIZE; \
- (REQ).aio_buf = BUFF; \
- (REQ).aio_sigevent.sigev_notify = SIGEV_NONE
-
-/* the first sizeof(struct aiocb *) bytes of the write buffer
- * will contain the pointer to the aiocb struct, this needs
- * to be freed between asynchronous writes.
- * A write of 0 bytes is ignored. */
-#define WRITE_AIO(FD,SIZE,BUFF) do { \
- if (SIZE > 0) { \
- struct aiocb *write_req = driver_alloc(sizeof(struct aiocb)); \
- char *write_buff = driver_alloc((sizeof(char)*SIZE)+1+ \
- (sizeof(struct aiocb *))); \
- *(struct aiocb **)write_buff = (struct aiocb *)write_req; \
- write_buff += sizeof(struct aiocb *); \
- memcpy(write_buff,BUFF,SIZE+1); \
- SET_AIO(*write_req,FD,SIZE,write_buff); \
- if (aio_write(write_req)) \
- ramlog_printf("%s:%d: write failed with %d\n", \
- __FILE__,__LINE__,errno); \
- } \
-} while(0)
-
-/* free the write_buffer and write_req
- * created in the WRITE_AIO() request macro */
-#define FREE_AIO(ptr) do { \
- struct aiocb *aiocb_ptr; \
- char *buffer_ptr; \
- aiocb_ptr = *(struct aiocb **)((ptr)-sizeof(struct aiocb *)); \
- buffer_ptr = (((char*)ptr)-sizeof(struct aiocb *)); \
- driver_free(aiocb_ptr); \
- driver_free(buffer_ptr); \
-} while(0)
-
-#define DISPATCH_AIO(sig) do { \
- if (aio_dispatch(sig)) \
- ramlog_printf("%s:%d: dispatch failed with %d\n", \
- __FILE__,__LINE__,errno); \
- } while(0)
-
-#define AIO_PIPE_SIZE 1024
-
-/* debug print macros */
-#define DEBUG_RES 0
-
-#ifdef DEBUG_RES
-#define DEBUG_CHECK_RES(actual, expected) \
- do { \
- if (actual != expected ) { \
- ramlog_printf("Result check failed" \
- " got: 0x%08x expected:0x%08x\nat: %s:%d\n", \
- actual, expected, __FILE__, __LINE__); \
- abort(); /* This might perhaps be too harsh? */ \
- } \
- } while(0)
-#else
-#define DEBUG_CHECK_RES
-#endif
-
-static struct fd_data {
- char pbuf[4]; /* hold partial packet bytes */
- int psz; /* size of pbuf */
- char *buf;
- char *cpos;
- int sz;
- int remain; /* for input on fd */
-} *fd_data; /* indexed by fd */
-
-/********************* General functions ****************************/
-
-/* This is used by both the drivers and general I/O, must be set early */
-static int max_files = -1;
-
-/*
- * a few variables used by the break handler
- */
-#ifdef ERTS_SMP
-erts_smp_atomic32_t erts_break_requested;
-#define ERTS_SET_BREAK_REQUESTED \
- erts_smp_atomic32_set_nob(&erts_break_requested, (erts_aint32_t) 1)
-#define ERTS_UNSET_BREAK_REQUESTED \
- erts_smp_atomic32_set_nob(&erts_break_requested, (erts_aint32_t) 0)
-#else
-volatile int erts_break_requested = 0;
-#define ERTS_SET_BREAK_REQUESTED (erts_break_requested = 1)
-#define ERTS_UNSET_BREAK_REQUESTED (erts_break_requested = 0)
-#endif
-/* set early so the break handler has access to initial mode */
-static struct termios initial_tty_mode;
-static int replace_intr = 0;
-/* assume yes initially, ttsl_init will clear it */
-int using_oldshell = 1;
-static PROCESS get_signal_proxy_pid(void);
-
-static void
-init_check_io(void)
-{
- erts_init_check_io();
- max_files = erts_check_io_max_files();
-}
-
-#ifdef ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
-#define ERTS_CHK_IO_AS_INTR() erts_check_io_async_sig_interrupt()
-#else
-#define ERTS_CHK_IO_AS_INTR() erts_check_io_interrupt(1)
-#endif
-#define ERTS_CHK_IO_INTR erts_check_io_interrupt
-#define ERTS_CHK_IO_INTR_TMD erts_check_io_interrupt_timed
-#define ERTS_CHK_IO erts_check_io
-#define ERTS_CHK_IO_SZ erts_check_io_size
-
-
-void
-erts_sys_schedule_interrupt(int set)
-{
- ERTS_CHK_IO_INTR(set);
-}
-
-#ifdef ERTS_SMP
-void
-erts_sys_schedule_interrupt_timed(int set, ErtsMonotonicTime timeout_time)
-{
- ERTS_CHK_IO_INTR_TMD(set, timeout_time);
-}
-#endif
-
-Uint
-erts_sys_misc_mem_sz(void)
-{
- Uint res = ERTS_CHK_IO_SZ();
- res += erts_smp_atomic_read_mb(&sys_misc_mem_sz);
- return res;
-}
-
-/*
- * reset the terminal to the original settings on exit
- */
-void sys_tty_reset(int exit_code)
-{
- if (using_oldshell && !replace_intr) {
- SET_BLOCKING(0);
- }
- else if (isatty(0)) {
- tcsetattr(0,TCSANOW,&initial_tty_mode);
- }
-}
-
-#ifdef USE_THREADS
-
-typedef struct {
- int sched_bind_data;
-} erts_thr_create_data_t;
-
-/*
- * thr_create_prepare() is called in parent thread before thread creation.
- * Returned value is passed as argument to thr_create_cleanup().
- */
-static void *
-thr_create_prepare(void)
-{
- erts_thr_create_data_t *tcdp;
-
- tcdp = erts_alloc(ERTS_ALC_T_TMP, sizeof(erts_thr_create_data_t));
-
- tcdp->sched_bind_data = erts_sched_bind_atthrcreate_prepare();
-
- return (void *) tcdp;
-}
-
-
-/* thr_create_cleanup() is called in parent thread after thread creation. */
-static void
-thr_create_cleanup(void *vtcdp)
-{
- erts_thr_create_data_t *tcdp = (erts_thr_create_data_t *) vtcdp;
-
- erts_sched_bind_atthrcreate_parent(tcdp->sched_bind_data);
-
- erts_free(ERTS_ALC_T_TMP, tcdp);
-}
-
-static void
-thr_create_prepare_child(void *vtcdp)
-{
- erts_thr_create_data_t *tcdp = (erts_thr_create_data_t *) vtcdp;
-
-#ifdef ERTS_ENABLE_LOCK_COUNT
- erts_lcnt_thread_setup();
-#endif
-
- erts_sched_bind_atthrcreate_child(tcdp->sched_bind_data);
-}
-
-#endif /* #ifdef USE_THREADS */
-
-/* The two functions below are stolen from win_con.c
- They have to use malloc/free/realloc directly becasue
- we want to do able to do erts_printf very early on.
- */
-#define VPRINTF_BUF_INC_SIZE 128
-static erts_dsprintf_buf_t *
-grow_vprintf_buf(erts_dsprintf_buf_t *dsbufp, size_t need)
-{
- char *buf;
- size_t size;
-
- ASSERT(dsbufp);
-
- if (!dsbufp->str) {
- size = (((need + VPRINTF_BUF_INC_SIZE - 1)
- / VPRINTF_BUF_INC_SIZE)
- * VPRINTF_BUF_INC_SIZE);
- buf = (char *) malloc(size * sizeof(char));
- }
- else {
- size_t free_size = dsbufp->size - dsbufp->str_len;
-
- if (need <= free_size)
- return dsbufp;
-
- size = need - free_size + VPRINTF_BUF_INC_SIZE;
- size = (((size + VPRINTF_BUF_INC_SIZE - 1)
- / VPRINTF_BUF_INC_SIZE)
- * VPRINTF_BUF_INC_SIZE);
- size += dsbufp->size;
- buf = (char *) realloc((void *) dsbufp->str,
- size * sizeof(char));
- }
- if (!buf)
- return NULL;
- if (buf != dsbufp->str)
- dsbufp->str = buf;
- dsbufp->size = size;
- return dsbufp;
-}
-
-static int erts_sys_ramlog_printf(char *format, va_list arg_list)
-{
- int res,i;
- erts_dsprintf_buf_t dsbuf = ERTS_DSPRINTF_BUF_INITER(grow_vprintf_buf);
- res = erts_vdsprintf(&dsbuf, format, arg_list);
- if (res >= 0) {
- for (i = 0; i < dsbuf.str_len; i+= 50)
- /* We print 50 characters at a time because otherwise
- the ramlog looks broken */
- ramlog_printf("%.*s",dsbuf.str_len-50 < 0?dsbuf.str_len:50,dsbuf.str+i);
- }
- if (dsbuf.str)
- free((void *) dsbuf.str);
- return res;
-}
-
-void
-erts_sys_pre_init(void)
-{
- erts_printf_add_cr_to_stdout = 1;
- erts_printf_add_cr_to_stderr = 1;
-#ifdef USE_THREADS
- {
- erts_thr_init_data_t eid = ERTS_THR_INIT_DATA_DEF_INITER;
-
- eid.thread_create_child_func = thr_create_prepare_child;
- /* Before creation in parent */
- eid.thread_create_prepare_func = thr_create_prepare;
- /* After creation in parent */
- eid.thread_create_parent_func = thr_create_cleanup,
-
- erts_thr_init(&eid);
-
- report_exit_list = NULL;
-
-#ifdef ERTS_ENABLE_LOCK_COUNT
- erts_lcnt_init();
-#endif
-
-#if defined(ERTS_SMP)
- erts_mtx_init(&chld_stat_mtx, "child_status");
-#endif
- }
-#ifdef ERTS_SMP
- erts_smp_atomic32_init_nob(&erts_break_requested, 0);
- erts_smp_atomic32_init_nob(&have_prepared_crash_dump, 0);
-#else
- erts_break_requested = 0;
- have_prepared_crash_dump = 0;
-#endif
-#if !defined(ERTS_SMP)
- children_died = 0;
-#endif
-#endif /* USE_THREADS */
-
- erts_printf_stdout_func = erts_sys_ramlog_printf;
-
- erts_smp_atomic_init_nob(&sys_misc_mem_sz, 0);
-}
-
-void
-erl_sys_init(void)
-{
-
-#ifdef USE_SETLINEBUF
- setlinebuf(stdout);
-#else
- setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
-#endif
-
- erts_sys_init_float();
-
- /* we save this so the break handler can set and reset it properly */
- /* also so that we can reset on exit (break handler or not) */
- if (isatty(0)) {
- tcgetattr(0,&initial_tty_mode);
- }
- tzset(); /* Required at least for NetBSD with localtime_r() */
-}
-
-static ERTS_INLINE int
-prepare_crash_dump(int secs)
-{
-#define NUFBUF (3)
- int i, max;
- char env[21]; /* enough to hold any 64-bit integer */
- size_t envsz;
- /*DeclareTmpHeapNoproc(heap,NUFBUF);*/
- /*Eterm *hp = heap;*/
- /*Eterm list = NIL;*/
- int has_heart = 0;
-
- UseTmpHeapNoproc(NUFBUF);
-
- if (ERTS_PREPARED_CRASH_DUMP)
- return 0; /* We have already been called */
-
-
- /* Positive secs means an alarm must be set
- * 0 or negative means no alarm
- *
- * Set alarm before we try to write to a port
- * we don't want to hang on a port write with
- * no alarm.
- *
- */
-
-#if 0 /*ose TBD!!!*/
- if (secs >= 0) {
- alarm((unsigned int)secs);
- }
-#endif
-
- /* Make sure we unregister at epmd (unknown fd) and get at least
- one free filedescriptor (for erl_crash.dump) */
-
- max = max_files;
- if (max < 1024)
- max = 1024;
- for (i = 3; i < max; i++) {
- close(i);
- }
-
- envsz = sizeof(env);
- i = erts_sys_getenv__("ERL_CRASH_DUMP_NICE", env, &envsz);
- if (i >= 0) {
- int nice_val;
- nice_val = i != 0 ? 0 : atoi(env);
- if (nice_val > 39) {
- nice_val = 39;
- }
- set_pri(nice_val);
- }
-
- UnUseTmpHeapNoproc(NUFBUF);
-#undef NUFBUF
- return has_heart;
-}
-
-int erts_sys_prepare_crash_dump(int secs)
-{
- return prepare_crash_dump(secs);
-}
-
-static ERTS_INLINE void
-break_requested(void)
-{
- /*
- * just set a flag - checked for and handled by
- * scheduler threads erts_check_io() (not signal handler).
- */
-#ifdef DEBUG
- fprintf(stderr,"break!\n");
-#endif
- if (ERTS_BREAK_REQUESTED)
- erts_exit(ERTS_INTR_EXIT, "");
-
- ERTS_SET_BREAK_REQUESTED;
- ERTS_CHK_IO_AS_INTR(); /* Make sure we don't sleep in poll */
-}
-
-/* Disable break */
-void erts_set_ignore_break(void) {
-
-}
-
-/* Don't use ctrl-c for break handler but let it be
- used by the shell instead (see user_drv.erl) */
-void erts_replace_intr(void) {
- struct termios mode;
-
- if (isatty(0)) {
- tcgetattr(0, &mode);
-
- /* here's an example of how to replace ctrl-c with ctrl-u */
- /* mode.c_cc[VKILL] = 0;
- mode.c_cc[VINTR] = CKILL; */
-
- mode.c_cc[VINTR] = 0; /* disable ctrl-c */
- tcsetattr(0, TCSANOW, &mode);
- replace_intr = 1;
- }
-}
-
-void init_break_handler(void)
-{
-
-}
-
-int sys_max_files(void)
-{
- return(max_files);
-}
-
-
-/************************** OS info *******************************/
-
-/* Used by erlang:info/1. */
-/* (This code was formerly in drv.XXX/XXX_os_drv.c) */
-
-char os_type[] = "ose";
-
-void
-os_flavor(char* namebuf, /* Where to return the name. */
- unsigned size) /* Size of name buffer. */
-{
-#if 0
- struct utsname uts; /* Information about the system. */
- char* s;
-
- (void) uname(&uts);
- for (s = uts.sysname; *s; s++) {
- if (isupper((int) *s)) {
- *s = tolower((int) *s);
- }
- }
- strcpy(namebuf, uts.sysname);
-#else
- strncpy(namebuf, "release", size);
-#endif
-}
-
-void
-os_version(pMajor, pMinor, pBuild)
-int* pMajor; /* Pointer to major version. */
-int* pMinor; /* Pointer to minor version. */
-int* pBuild; /* Pointer to build number. */
-{
- *pMajor = 5;
- *pMinor = 7;
- *pBuild = 0;
-}
-
-void init_getenv_state(GETENV_STATE *state)
-{
- erts_smp_rwmtx_rlock(&environ_rwmtx);
- *state = NULL;
-}
-
-char **environ; /*ose - needs replacement*/
-
-char *getenv_string(GETENV_STATE *state0)
-{
- char **state = (char **) *state0;
- char *cp;
-
- ERTS_SMP_LC_ASSERT(erts_smp_lc_rwmtx_is_rlocked(&environ_rwmtx));
-
- if (state == NULL)
- state = environ;
-
- cp = *state++;
- *state0 = (GETENV_STATE) state;
-
- return cp;
-}
-
-void fini_getenv_state(GETENV_STATE *state)
-{
- *state = NULL;
- erts_smp_rwmtx_runlock(&environ_rwmtx);
-}
-
-
-/************************** Port I/O *******************************/
-
-/* I. Common stuff */
-
-union SIGNAL {
- SIGSELECT sig_no;
- struct FmReadPtr fm_read_reply;
- struct FmWritePtr fm_write_reply;
- struct async async;
-};
-
-/* II. The spawn/fd drivers */
-
-/*
- * Decreasing the size of it below 16384 is not allowed.
- */
-#define ERTS_SYS_READ_BUF_SZ (64*1024)
-
-/* Driver interfaces */
-static ErlDrvData spawn_start(ErlDrvPort, char*, SysDriverOpts*);
-static ErlDrvData fd_start(ErlDrvPort, char*, SysDriverOpts*);
-static ErlDrvSSizeT fd_control(ErlDrvData, unsigned int, char *, ErlDrvSizeT,
- char **, ErlDrvSizeT);
-static int spawn_init(void);
-static void fd_stop(ErlDrvData);
-static void erl_stop(ErlDrvData);
-static void ready_input(ErlDrvData, ErlDrvEvent);
-static void ready_output(ErlDrvData, ErlDrvEvent);
-static void output(ErlDrvData, char*, ErlDrvSizeT);
-static void stop_select(ErlDrvEvent, void*);
-
-static PROCESS
-get_signal_proxy_pid(void) {
- union SIGNAL *sig;
- SIGSELECT any_sig[] = {1,ERTS_SIGNAL_OSE_DRV_ATTACH};
-
- if (!sig_proxy_pid) {
- sig = alloc(sizeof(union SIGNAL), ERTS_SIGNAL_OSE_DRV_ATTACH);
- hunt("ose_signal_driver_proxy", 0, NULL, &sig);
- sig = receive(any_sig);
- sig_proxy_pid = sender(&sig);
- free_buf(&sig);
- }
- ASSERT(sig_proxy_pid);
- return sig_proxy_pid;
-}
-
-static ErlDrvOseEventId
-resolve_signal(union SIGNAL* sig) {
- switch(sig->sig_no) {
-
- case FM_READ_PTR_REPLY:
- return (ErlDrvOseEventId)sig->fm_read_reply.handle;
-
- case FM_WRITE_PTR_REPLY:
- return (ErlDrvOseEventId)sig->fm_write_reply.handle;
-
- case ERTS_SIGNAL_OSE_DRV_ATTACH:
- return (ErlDrvOseEventId)sig->async.target;
-
- default:
- break;
- }
- return (ErlDrvOseEventId)-1;
-}
-
-struct erl_drv_entry spawn_driver_entry = {
- spawn_init,
- spawn_start,
- NULL, /* erl_stop, */
- output,
- ready_input,
- ready_output,
- "spawn",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- ERL_DRV_EXTENDED_MARKER,
- ERL_DRV_EXTENDED_MAJOR_VERSION,
- ERL_DRV_EXTENDED_MINOR_VERSION,
- ERL_DRV_FLAG_USE_PORT_LOCKING,
- NULL, NULL,
- stop_select
-};
-struct erl_drv_entry fd_driver_entry = {
- NULL,
- fd_start,
- fd_stop,
- output,
- ready_input,
- ready_output,
- "fd",
- NULL,
- NULL,
- fd_control,
- NULL,
- NULL,
- NULL, /* ready_async */
- NULL, /* flush */
- NULL, /* call */
- NULL, /* event */
- ERL_DRV_EXTENDED_MARKER,
- ERL_DRV_EXTENDED_MAJOR_VERSION,
- ERL_DRV_EXTENDED_MINOR_VERSION,
- 0, /* ERL_DRV_FLAGs */
- NULL, /* handle2 */
- NULL, /* process_exit */
- stop_select
-};
-
-static void
-set_spawn_fd(int local_fd, int remote_fd, PROCESS remote_pid) {
- PROCESS vm_pid;
- FmHandle handle;
- char env_val[55];
- char env_name[10];
- EfsStatus efs_res;
-
- /* get pid of pipevm and handle of chosen fd */
- efs_res = efs_examine_fd(local_fd, FLIB_FD_VMPID, &vm_pid, 0);
- DEBUG_CHECK_RES(efs_res, EFS_SUCCESS);
-
- /* setup the file descriptor to buffer per line */
- efs_res = efs_config_fd(local_fd, FLIB_FD_BUFMODE, FM_BUFF_LINE,
- FLIB_FD_BUFSIZE, 80, 0);
- DEBUG_CHECK_RES(efs_res, EFS_SUCCESS);
-
- /* duplicate handle and set spawn pid owner */
- efs_res = efs_dup_to(local_fd, remote_pid, &handle);
- DEBUG_CHECK_RES(efs_res, EFS_SUCCESS);
-
- sprintf(env_name, "FD%d", remote_fd);
-
- /* Syntax of the environment variable:
- * "FD#" "<pid of pipevm>,<handle>,<buffer mode>,<buff size>,<omode>" */
- sprintf(env_val, "0x%lx,0x%lx,%lu,%lu,0x%x",
- vm_pid, handle,
- FM_BUFF_LINE, 80,
- O_APPEND);
-
- set_env(remote_pid, env_name, env_val);
-}
-
-static ErlDrvData
-set_driver_data(ErlDrvPort port_num,
- int ifd,
- int ofd,
- int packet_bytes,
- int read_write,
- int exit_status,
- PROCESS pid)
-{
- Port *prt;
- ErtsSysReportExit *report_exit;
-
- prt = erts_drvport2port(port_num);
- if (prt != ERTS_INVALID_ERL_DRV_PORT) {
- prt->os_pid = pid;
- }
-
- /* READ */
- if (read_write & DO_READ) {
- EfsStatus res = efs_examine_fd(ifd, FLIB_FD_HANDLE,
- &driver_data[ifd].handle, 0);
- if (res != EFS_SUCCESS)
- ramlog_printf("%s:%d: efs_examine_fd(%d) failed with %d\n",
- __FILE__,__LINE__,ifd,errno);
- driver_data[ifd].ifd = ifd;
- driver_data[ifd].packet_bytes = packet_bytes;
- driver_data[ifd].port_num = port_num;
- driver_data[ifd].pid = pid;
-
- /* async read struct */
- memset(&driver_data[ifd].aiocb, 0, sizeof(struct aiocb));
- driver_data[ifd].aiocb.aio_buf = driver_alloc(AIO_PIPE_SIZE);
- driver_data[ifd].aiocb.aio_fildes = ifd;
- driver_data[ifd].aiocb.aio_nbytes = (packet_bytes?packet_bytes:AIO_PIPE_SIZE);
- driver_data[ifd].alive = 1;
- driver_data[ifd].status = 0;
- driver_data[ifd].input_event =
- erl_drv_ose_event_alloc(FM_READ_PTR_REPLY,
- driver_data[ifd].handle, resolve_signal,
- &driver_data[ifd].ifd);
-
- /* READ & WRITE */
- if (read_write & DO_WRITE) {
- driver_data[ifd].ofd = ofd;
- efs_examine_fd(ofd, FLIB_FD_HANDLE, &driver_data[ofd].handle, 0);
-
- driver_data[ifd].output_event =
- erl_drv_ose_event_alloc(FM_WRITE_PTR_REPLY,
- driver_data[ofd].handle, resolve_signal,
- &driver_data[ofd].ofd);
- driver_data[ofd].pid = pid;
- if (ifd != ofd) {
- driver_data[ofd] = driver_data[ifd];
- driver_data[ofd].aiocb.aio_buf = NULL;
- }
- }
- else { /* READ ONLY */
- driver_data[ifd].ofd = -1;
- }
-
- /* enable input event */
- (void) driver_select(port_num, driver_data[ifd].input_event,
- (ERL_DRV_READ | ERL_DRV_USE), 1);
-
- if (aio_read(&driver_data[ifd].aiocb))
- ramlog_printf("%s:%d: aio_read(%d) failed with %d\n",
- __FILE__,__LINE__,ifd,errno);
- }
- else { /* WRITE ONLY */
- efs_examine_fd(ofd, FLIB_FD_HANDLE, &driver_data[ofd].handle, 0);
- driver_data[ofd].packet_bytes = packet_bytes;
- driver_data[ofd].port_num = port_num;
- driver_data[ofd].ofd = ofd;
- driver_data[ofd].pid = pid;
- driver_data[ofd].alive = 1;
- driver_data[ofd].status = 0;
- driver_data[ofd].output_event =
- erl_drv_ose_event_alloc(FM_WRITE_PTR_REPLY, driver_data[ofd].handle,
- resolve_signal, &driver_data[ofd].ofd);
- driver_data[ofd].input_event = driver_data[ofd].output_event;
- }
-
- /* this is used for spawned load modules, and is needed
- * to properly uninstall them */
- if (exit_status) {
- struct PmProgramInfo *info;
- int install_handle_size;
- union SIGNAL *sig;
- PmStatus pm_status;
- report_exit = erts_alloc(ERTS_ALC_T_PRT_REP_EXIT,
- sizeof(ErtsSysReportExit));
- report_exit->next = report_exit_list;
- report_exit->port = erts_drvport2id(port_num);
- report_exit->pid = pid;
- report_exit->ifd = (read_write & DO_READ) ? ifd : -1;
- report_exit->ofd = (read_write & DO_WRITE) ? ofd : -1;
- report_exit_list = report_exit;
- report_exit->attach_event =
- erl_drv_ose_event_alloc(ERTS_SIGNAL_OSE_DRV_ATTACH, pid,
- resolve_signal, &driver_data[ifd].ifd);
-
- /* setup ifd and ofd report exit */
- driver_data[ifd].report_exit = report_exit;
- driver_data[ofd].report_exit = report_exit;
-
- pm_status = ose_pm_program_info(pid, &info);
- DEBUG_CHECK_RES(pm_status, PM_SUCCESS);
-
- install_handle_size = strlen(info->install_handle)+1;
- driver_data[ifd].install_handle = driver_alloc(install_handle_size);
- strcpy(driver_data[ifd].install_handle,
- info->install_handle);
-
- free_buf((union SIGNAL **)&info);
-
- sig = alloc(sizeof(struct async), ERTS_SIGNAL_OSE_DRV_ATTACH);
- sig->async.target = pid;
- send(&sig, get_signal_proxy_pid());
-
- /* this event will trigger when we receive an attach signal
- * from the recently dead load module */
- (void)driver_select(port_num,report_exit->attach_event, DO_READ, 1);
- }
- else {
- report_exit = NULL;
- }
-
- /* the return value is the pointer to the driver_data struct we created
- * in this function, it will be used in the drivers input
- * and output functions */
- return (ErlDrvData)((!(read_write & DO_READ) && read_write & DO_WRITE)
- ? &driver_data[ofd]
- : &driver_data[ifd]);
-}
-
-static int spawn_init()
-{
- int i;
-
- driver_data = (struct driver_data *)
- erts_alloc(ERTS_ALC_T_DRV_TAB, max_files * sizeof(struct driver_data));
- erts_smp_atomic_add_nob(&sys_misc_mem_sz,
- max_files * sizeof(struct driver_data));
-
- for (i = 0; i < max_files; i++)
- driver_data[i].pid = -1;
-
- return 1;
-}
-
-static void
-init_fd_data(int fd, ErlDrvPort port_num)
-{
- fd_data[fd].buf = NULL;
- fd_data[fd].cpos = NULL;
- fd_data[fd].remain = 0;
- fd_data[fd].sz = 0;
- fd_data[fd].psz = 0;
-}
-
-/* FIXME write a decent text on pipes on ose */
-static ErlDrvData
-spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
-{
- int ifd[2];
- int ofd[2];
- static uint32_t ticker = 1;
- PmStatus pm_status;
- OSDOMAIN domain = PM_NEW_DOMAIN;
- PROCESS progpid, mainbid, mainpid;
- char *handle = NULL;
- struct PmProgramInfo *info;
- char *args = NULL;
- char *tmp_handle;
- ErlDrvData res = (ErlDrvData)-1;
- int handle_size;
- char *ptr;
-
-
- args = driver_alloc(strlen(name)+1);
- strcpy(args, name);
- /* We need to handle name in three parts
- * - install handle (must be unique)
- * - install binary (needed for ose_pm_install_load_module())
- * - full path (as argument to the spawned applications env.var
- */
-
- /* full path including arguments */
- args = driver_alloc(strlen(name)+1);
- strcpy(args, name);
-
- /* handle path */
- tmp_handle = strrchr(name, '/');
- if (tmp_handle == NULL) {
- tmp_handle = name;
- }
- else {
- tmp_handle++;
- }
-
- /* handle args */
- ptr = strchr(tmp_handle, ' ');
- if (ptr != NULL) {
- *ptr = '\0';
- handle_size = ptr - tmp_handle;
- }
- else {
- handle_size = strlen(name)+1;
- }
-
- /* make room for ticker */
- handle_size += (ticker<10)?3:((ticker<100)?4:5);
- handle = driver_alloc(handle_size);
-
- do {
- snprintf(handle, handle_size, "%s_%d", tmp_handle, ticker);
- pm_status = ose_pm_install_load_module(0, "ELF", name, handle,
- 0, 0, NULL);
- ticker++;
- } while (pm_status == PM_EINSTALL_HANDLE_ALREADY_INSTALLED);
-
- if (pm_status != PM_SUCCESS) {
- errno = ENOSYS; /* FIXME add comment */
- return ERL_DRV_ERROR_ERRNO;
- }
-
- /* Create Program */
- pm_status = ose_pm_create_program(&domain, handle, 0, 0,
- NULL, &progpid, &mainbid);
- DEBUG_CHECK_RES(pm_status, PM_SUCCESS);
-
- /* Get the mainpid from the newly created program */
- pm_status = ose_pm_program_info(progpid, &info);
- DEBUG_CHECK_RES(pm_status, PM_SUCCESS);
-
- mainpid = info->main_process;
- free_buf ((union SIGNAL **)&info);
-
- /* pipevm needs to be started
- * pipe will return 0 if success, -1 if not,
- * errno will be set */
- if (pipe(ifd) != 0 || pipe(ofd) != 0) {
- DEBUG_CHECK_RES(0, -1);
- ASSERT(0);
- }
-
- /* setup driver data */
- res = set_driver_data(port_num, ofd[0], ifd[1], opts->packet_bytes,
- opts->read_write, 1 /* opts->exit_status */, progpid);
-
- /* init the fd_data array for read/write */
- init_fd_data(ofd[0], port_num);
- init_fd_data(ifd[1], port_num);
-
- /* setup additional configurations
- * for the spawned applications environment */
- if (args != NULL) {
- set_env(progpid, "ARGV", args);
- }
- set_env(mainbid, "EFS_RESOLVE_TMO", 0);
- set_spawn_fd(ifd[0], 0, mainpid);
- set_spawn_fd(ofd[1], 1, mainpid);
- set_spawn_fd(ofd[1], 2, mainpid);
-
- /* start the spawned program */
- pm_status = ose_pm_start_program(mainbid);
- DEBUG_CHECK_RES(pm_status, PM_SUCCESS);
-
- /* close unused fd's */
- close(ifd[0]);
- close(ofd[1]);
-
- if (handle) {
- driver_free(handle);
- }
-
- return (ErlDrvData)res;
-}
-
-#define FD_DEF_HEIGHT 24
-#define FD_DEF_WIDTH 80
-/* Control op */
-#define FD_CTRL_OP_GET_WINSIZE 100
-
-static int fd_get_window_size(int fd, Uint32 *width, Uint32 *height)
-{
-#ifdef TIOCGWINSZ
- struct winsize ws;
- if (ioctl(fd,TIOCGWINSZ,&ws) == 0) {
- *width = (Uint32) ws.ws_col;
- *height = (Uint32) ws.ws_row;
- return 0;
- }
-#endif
- return -1;
-}
-
-static ErlDrvSSizeT fd_control(ErlDrvData drv_data,
- unsigned int command,
- char *buf, ErlDrvSizeT len,
- char **rbuf, ErlDrvSizeT rlen)
-{
- struct driver_data *data = (struct driver_data *)drv_data;
- char resbuff[2*sizeof(Uint32)];
- switch (command) {
- case FD_CTRL_OP_GET_WINSIZE:
- {
- Uint32 w,h;
- if (fd_get_window_size(data->ifd,&w,&h))
- return 0;
- memcpy(resbuff,&w,sizeof(Uint32));
- memcpy(resbuff+sizeof(Uint32),&h,sizeof(Uint32));
- }
- break;
- default:
- return 0;
- }
- if (rlen < 2*sizeof(Uint32)) {
- *rbuf = driver_alloc(2*sizeof(Uint32));
- }
- memcpy(*rbuf,resbuff,2*sizeof(Uint32));
- return 2*sizeof(Uint32);
-}
-
-static ErlDrvData fd_start(ErlDrvPort port_num, char* name,
- SysDriverOpts* opts)
-{
- ErlDrvData res;
-
- CHLD_STAT_LOCK;
- if (opts->read_write & DO_READ) {
- init_fd_data(opts->ifd, port_num);
- }
- if (opts->read_write & DO_WRITE) {
- init_fd_data(opts->ofd, port_num);
- }
- res = set_driver_data(port_num, opts->ifd, opts->ofd,
- opts->packet_bytes,
- opts->read_write, 0, -1);
- CHLD_STAT_UNLOCK;
- return res;
-}
-
-static void clear_fd_data(int fd)
-{
- if (fd_data[fd].sz > 0) {
- erts_free(ERTS_ALC_T_FD_ENTRY_BUF, (void *) fd_data[fd].buf);
- ASSERT(erts_smp_atomic_read_nob(&sys_misc_mem_sz) >= fd_data[fd].sz);
- erts_smp_atomic_add_nob(&sys_misc_mem_sz, -1*fd_data[fd].sz);
- }
- fd_data[fd].buf = NULL;
- fd_data[fd].sz = 0;
- fd_data[fd].remain = 0;
- fd_data[fd].cpos = NULL;
- fd_data[fd].psz = 0;
-}
-
-static void nbio_stop_fd(ErlDrvPort prt, ErlDrvEvent ev)
-{
- int *fd;
- driver_select(prt,ev,DO_READ|DO_WRITE,0);
- erl_drv_ose_event_fetch(ev, NULL, NULL, (void **)&fd);
- clear_fd_data(*fd);
- SET_BLOCKING(*fd);
-}
-
-static void fd_stop(ErlDrvData drv_data) /* Does not close the fds */
-{
- struct driver_data *data = (struct driver_data *)drv_data;
-
- if (data->ofd != -1) {
- if (data->ifd != data->ofd) { /* read and write */
- nbio_stop_fd(data->port_num, data->input_event);
- nbio_stop_fd(data->port_num, data->output_event);
- }
- else { /* write only */
- nbio_stop_fd(data->port_num, data->output_event);
- }
- }
- else { /* read only */
- nbio_stop_fd(data->port_num, data->input_event);
- }
-}
-
-
-static void erl_stop(ErlDrvData drv_data)
-{
- struct driver_data *data = (struct driver_data *)drv_data;
-
- CHLD_STAT_LOCK;
- data->pid = -1;
- CHLD_STAT_UNLOCK;
-
- if (data->ofd != -1) {
- if (data->ifd != data->ofd) { /* read and write */
- nbio_stop_fd(data->port_num, data->input_event);
- nbio_stop_fd(data->port_num, data->output_event);
- }
- else { /* write only */
- nbio_stop_fd(data->port_num, data->output_event);
- }
- }
- else { /* read only */
- nbio_stop_fd(data->port_num, data->input_event);
- }
- close(data->ifd);
- close(data->ofd);
-}
-
-/* The parameter e is a pointer to the driver_data structure
- * related to the fd to be used as output */
-static void output(ErlDrvData drv_data, char* buf, ErlDrvSizeT len)
-{
- ErlDrvSizeT sz;
- char lb[4];
- char* lbp;
- struct driver_data *data = (struct driver_data *)drv_data;
-
- if (((data->packet_bytes == 2) &&
- (len > 0xffff)) || (data->packet_bytes == 1 && len > 0xff)) {
- driver_failure_posix(data->port_num, EINVAL);
- return; /* -1; */
- }
- put_int32(len, lb);
- lbp = lb + (4-(data->packet_bytes));
-
- if ((sz = driver_sizeq(data->port_num)) > 0) {
- if (data->packet_bytes != 0) {
- driver_enq(data->port_num, lbp, data->packet_bytes);
- }
- driver_enq(data->port_num, buf, len);
-
- if (sz + len + data->packet_bytes >= (1 << 13))
- set_busy_port(data->port_num, 1);
- }
- else {
- char *pbbuf;
- if (data->packet_bytes != 0) {
- pbbuf = malloc(len + data->packet_bytes);
- int i;
- for (i = 0; i < data->packet_bytes; i++) {
- *pbbuf++ = *lbp++;
- }
- strncpy(pbbuf, buf, len);
- pbbuf -= data->packet_bytes;
- }
- driver_select(data->port_num, data->output_event,
- ERL_DRV_WRITE|ERL_DRV_USE, 1);
- WRITE_AIO(data->ofd,
- (data->packet_bytes ? len+data->packet_bytes : len),
- (data->packet_bytes ? pbbuf : buf));
- if (data->packet_bytes != 0) free(pbbuf);
- }
- return; /* 0; */
-}
-
-/* This function is being run when we in recieve
- * either a read of 0 bytes, or the attach signal from a dying
- * spawned load module */
-static int port_inp_failure(ErlDrvPort port_num, ErlDrvEvent ready_fd, int res)
- /* Result: 0 (eof) or -1 (error) */
-{
- int *fd;
- SIGSELECT sig_no;
- ASSERT(res <= 0);
-
- erl_drv_ose_event_fetch(ready_fd,&sig_no, NULL, (void **)&fd);
- /* As we need to handle two signals, we do this in two steps */
- if (driver_data[*fd].alive) {
- report_exit_status(driver_data[*fd].report_exit, 0); /* status? */
- }
- else {
- driver_select(port_num,ready_fd,DO_READ|DO_WRITE,0);
- clear_fd_data(*fd);
- driver_report_exit(driver_data[*fd].port_num, driver_data[*fd].status);
- /* As we do not really know if the spawn has crashed or exited nicely
- * we do not check the result status of the following call.. FIXME
- * can we handle this in a better way? */
- ose_pm_uninstall_load_module(driver_data[*fd].install_handle);
- driver_free(driver_data[*fd].install_handle);
- driver_free((void *)driver_data[*fd].aiocb.aio_buf);
-
- close(*fd);
- }
-
- return 0;
-}
-
-/* The parameter e is a pointer to the driver_data structure
- * related to the fd to be used as output.
- * ready_fd is the event that triggered this call to ready_input */
-static void ready_input(ErlDrvData drv_data, ErlDrvEvent ready_fd)
-{
- int res;
- Uint h;
- char *buf;
- union SIGNAL *sig;
- struct driver_data *data = (struct driver_data *)drv_data;
-
- sig = erl_drv_ose_get_signal(ready_fd);
- ASSERT(sig);
-
-
- while (sig) {
- /* If we've recieved an attach signal, we need to handle
- * it in port_inp_failure */
- if (sig->sig_no == ERTS_SIGNAL_OSE_DRV_ATTACH) {
- port_inp_failure(data->port_num, ready_fd, 0);
- }
- else {
- res = sig->fm_read_reply.actual;
- if (res == 0) {
- port_inp_failure(data->port_num, ready_fd, res);
- break;
- }
-
- if (data->packet_bytes == 0) {
- if (res < 0) {
- if ((errno != EINTR) && (errno != ERRNO_BLOCK)) {
- port_inp_failure(data->port_num, ready_fd, res);
- }
- }
- else if (res == 0) {
- /* read of 0 bytes, eof, otherside of pipe is assumed dead */
- port_inp_failure(data->port_num, ready_fd, res);
- break;
- }
- else {
- buf = driver_alloc(res);
- memcpy(buf, (void *)data->aiocb.aio_buf, res);
- driver_select(data->port_num, data->output_event,
- ERL_DRV_WRITE|ERL_DRV_USE, 1);
- driver_output(data->port_num, (char*) buf, res);
- driver_free(buf);
- }
- /* clear the previous read */
- memset(data->aiocb.aio_buf, 0, res);
-
- /* issue a new read */
- DISPATCH_AIO(sig);
- aio_read(&data->aiocb);
- }
- else if (data->packet_bytes && fd_data[data->ifd].remain > 0) {
- /* we've read a partial package, or a header */
-
- if (res == fd_data[data->ifd].remain) { /* we are done! */
- char *buf = data->aiocb.aio_buf;
- int i;
-
- /* do we have anything buffered? */
- if (fd_data[data->ifd].buf != NULL) {
- memcpy(fd_data[data->ifd].buf + fd_data[data->ifd].sz,
- buf, res);
- buf = fd_data[data->ifd].buf;
- }
-
- fd_data[data->ifd].sz += res;
- driver_output(data->port_num, buf, (fd_data[data->ifd].sz>0?fd_data[data->ifd].sz:res));
- clear_fd_data(data->ifd);
-
- /* clear the previous read */
- memset(data->aiocb.aio_buf, 0, res);
-
- /* issue a new read */
- DISPATCH_AIO(sig);
- data->aiocb.aio_nbytes = data->packet_bytes;
-
- if (data->aiocb.aio_buf == NULL) {
- port_inp_failure(data->port_num, ready_fd, -1);
- }
- aio_read(&data->aiocb);
- }
- else if(res < fd_data[data->ifd].remain) { /* received part of a package */
- if (fd_data[data->ifd].sz == 0) {
-
- fd_data[data->ifd].sz += res;
- memcpy(fd_data[data->ifd].buf, data->aiocb.aio_buf, res);
- fd_data[data->ifd].remain -= res;
- }
- else {
- memcpy(fd_data[data->ifd].buf + fd_data[data->ifd].sz,
- data->aiocb.aio_buf, res);
- fd_data[data->ifd].sz += res;
- fd_data[data->ifd].remain -= res;
- }
- /* clear the previous read */
- memset(data->aiocb.aio_buf, 0, res);
-
- /* issue a new read */
- DISPATCH_AIO(sig);
- data->aiocb.aio_nbytes = fd_data[data->ifd].remain;
-
- if (data->aiocb.aio_buf == NULL) {
- port_inp_failure(data->port_num, ready_fd, -1);
- }
- aio_read(&data->aiocb);
- }
- }
- else if (data->packet_bytes && fd_data[data->ifd].remain == 0) { /* we've recieved a header */
-
- /* analyze the header FIXME */
- switch (data->packet_bytes) {
- case 1: h = get_int8(data->aiocb.aio_buf); break;
- case 2: h = get_int16(data->aiocb.aio_buf); break;
- case 4: h = get_int32(data->aiocb.aio_buf); break;
- }
-
- fd_data[data->ifd].buf = erts_alloc_fnf(ERTS_ALC_T_FD_ENTRY_BUF, h + data->packet_bytes);
- fd_data[data->ifd].remain = ((h + data->packet_bytes) - res);
-
- /* clear the previous read */
- memset(data->aiocb.aio_buf, 0, data->packet_bytes);
-
- /* issue a new read */
- DISPATCH_AIO(sig);
- data->aiocb.aio_nbytes = h;
-
- if (data->aiocb.aio_buf == NULL) {
- port_inp_failure(data->port_num, ready_fd, -1);
- }
- aio_read(&data->aiocb);
- }
- }
- sig = erl_drv_ose_get_signal(ready_fd);
- }
-}
-
-
-/* The parameter e is a pointer to the driver_data structure
- * related to the fd to be used as output.
- * ready_fd is the event that triggered this call to ready_input */
-static void ready_output(ErlDrvData drv_data, ErlDrvEvent ready_fd)
-{
- SysIOVec *iov;
- int vlen;
- int res;
- union SIGNAL *sig;
- struct driver_data *data = (struct driver_data *)drv_data;
-
- sig = erl_drv_ose_get_signal(ready_fd);
- ASSERT(sig);
-
- while (sig != NULL) {
- if (sig->fm_write_reply.actual <= 0) {
- int status;
-
- status = efs_status_to_errno(sig->fm_write_reply.status);
- driver_select(data->port_num, ready_fd, ERL_DRV_WRITE, 0);
- DISPATCH_AIO(sig);
- FREE_AIO(sig->fm_write_reply.buffer);
-
- driver_failure_posix(data->port_num, status);
- }
- else { /* written bytes > 0 */
- iov = driver_peekq(data->port_num, &vlen);
- if (vlen > 0) {
- DISPATCH_AIO(sig);
- FREE_AIO(sig->fm_write_reply.buffer);
- res = driver_deq(data->port_num, iov[0].iov_len);
- if (res > 0) {
- iov = driver_peekq(data->port_num, &vlen);
- WRITE_AIO(data->ofd, iov[0].iov_len, iov[0].iov_base);
- }
- }
- else if (vlen == 0) {
- DISPATCH_AIO(sig);
- FREE_AIO(sig->fm_write_reply.buffer);
- }
-
- }
- sig = erl_drv_ose_get_signal(ready_fd);
- }
-}
-
-static void stop_select(ErlDrvEvent ready_fd, void* _)
-{
- int *fd;
- erl_drv_ose_event_fetch(ready_fd, NULL, NULL, (void **)&fd);
- erl_drv_ose_event_free(ready_fd);
- close(*fd);
-}
-
-
-void erts_do_break_handling(void)
-{
- struct termios temp_mode;
- int saved = 0;
-
- /*
- * Most functions that do_break() calls are intentionally not thread safe;
- * therefore, make sure that all threads but this one are blocked before
- * proceeding!
- */
- erts_smp_thr_progress_block();
-
- /* during break we revert to initial settings */
- /* this is done differently for oldshell */
- if (using_oldshell && !replace_intr) {
- SET_BLOCKING(1);
- }
- else if (isatty(0)) {
- tcgetattr(0,&temp_mode);
- tcsetattr(0,TCSANOW,&initial_tty_mode);
- saved = 1;
- }
-
- /* call the break handling function, reset the flag */
- do_break();
-
- fflush(stdout);
-
- /* after break we go back to saved settings */
- if (using_oldshell && !replace_intr) {
- SET_NONBLOCKING(1);
- }
- else if (saved) {
- tcsetattr(0,TCSANOW,&temp_mode);
- }
-
- erts_smp_thr_progress_unblock();
-}
-
-static pid_t
-getpid(void)
-{
- return get_bid(current_process());
-}
-
-int getpagesize(void)
-{
- return 1024;
-}
-
-
-/* Fills in the systems representation of the jam/beam process identifier.
-** The Pid is put in STRING representation in the supplied buffer,
-** no interpretatione of this should be done by the rest of the
-** emulator. The buffer should be at least 21 bytes long.
-*/
-void sys_get_pid(char *buffer, size_t buffer_size){
- pid_t p = getpid();
- /* Assume the pid is scalar and can rest in an unsigned long... */
- erts_snprintf(buffer, buffer_size, "%lu",(unsigned long) p);
-}
-
-int
-erts_sys_putenv_raw(char *key, char *value) {
- return erts_sys_putenv(key, value);
-}
-int
-erts_sys_putenv(char *key, char *value)
-{
- int res;
-
- erts_smp_rwmtx_rwlock(&environ_rwmtx);
- res = set_env(get_bid(current_process()), key,
- value);
- erts_smp_rwmtx_rwunlock(&environ_rwmtx);
- return res;
-}
-
-
-int
-erts_sys_unsetenv(char *key)
-{
- int res;
-
- erts_smp_rwmtx_rwlock(&environ_rwmtx);
- res = set_env(get_bid(current_process()),key,NULL);
- erts_smp_rwmtx_rwunlock(&environ_rwmtx);
-
- return res;
-}
-
-int
-erts_sys_getenv__(char *key, char *value, size_t *size)
-{
- int res;
- char *orig_value = get_env(get_bid(current_process()), key);
- if (!orig_value)
- res = -1;
- else {
- size_t len = sys_strlen(orig_value);
- if (len >= *size) {
- *size = len + 1;
- res = 1;
- }
- else {
- *size = len;
- sys_memcpy((void *) value, (void *) orig_value, len+1);
- res = 0;
- }
- free_buf((union SIGNAL **)&orig_value);
- }
- return res;
-}
-
-int
-erts_sys_getenv_raw(char *key, char *value, size_t *size) {
- return erts_sys_getenv(key, value, size);
-}
-
-/*
- * erts_sys_getenv
- * returns:
- * -1, if environment key is not set with a value
- * 0, if environment key is set and value fits into buffer res
- * 1, if environment key is set but does not fit into buffer res
- * res is set with the needed buffer res value
- */
-
-int
-erts_sys_getenv(char *key, char *value, size_t *size)
-{
- int res;
- erts_smp_rwmtx_rlock(&environ_rwmtx);
- res = erts_sys_getenv__(key, value, size);
- erts_smp_rwmtx_runlock(&environ_rwmtx);
- return res;
-}
-
-void
-sys_init_io(void)
-{
- fd_data = (struct fd_data *)
- erts_alloc(ERTS_ALC_T_FD_TAB, max_files * sizeof(struct fd_data));
- erts_smp_atomic_add_nob(&sys_misc_mem_sz,
- max_files * sizeof(struct fd_data));
-}
-
-extern const char pre_loaded_code[];
-extern Preload pre_loaded[];
-
-void erts_sys_alloc_init(void)
-{
-}
-
-void *erts_sys_alloc(ErtsAlcType_t t, void *x, Uint sz)
-{
- void *res = malloc((size_t) sz);
-#if HAVE_ERTS_MSEG
- if (!res) {
- erts_mseg_clear_cache();
- return malloc((size_t) sz);
- }
-#endif
- return res;
-}
-
-void *erts_sys_realloc(ErtsAlcType_t t, void *x, void *p, Uint sz)
-{
- void *res = realloc(p, (size_t) sz);
-#if HAVE_ERTS_MSEG
- if (!res) {
- erts_mseg_clear_cache();
- return realloc(p, (size_t) sz);
- }
-#endif
- return res;
-}
-
-void erts_sys_free(ErtsAlcType_t t, void *x, void *p)
-{
- free(p);
-}
-
-/* Return a pointer to a vector of names of preloaded modules */
-
-Preload*
-sys_preloaded(void)
-{
- return pre_loaded;
-}
-
-/* Return a pointer to preloaded code for module "module" */
-unsigned char*
-sys_preload_begin(Preload* p)
-{
- return p->code;
-}
-
-/* Clean up if allocated */
-void sys_preload_end(Preload* p)
-{
- /* Nothing */
-}
-
-/* Read a key from console (?) */
-
-int sys_get_key(fd)
-int fd;
-{
- int c;
- unsigned char rbuf[64];
-
- fflush(stdout); /* Flush query ??? */
-
- if ((c = read(fd,rbuf,64)) <= 0) {
- return c;
- }
-
- return rbuf[0];
-}
-
-
-#ifdef DEBUG
-
-extern int erts_initialized;
-void
-erl_assert_error(const char* expr, const char* func,
- const char* file, int line)
-{
- fflush(stdout);
- fprintf(stderr, "%s:%d:%s() Assertion failed: %s\n",
- file, line, func, expr);
- fflush(stderr);
- ramlog_printf("%s:%d:%s() Assertion failed: %s\n",
- file, line, func, expr);
-
- abort();
-}
-
-void
-erl_debug(char* fmt, ...)
-{
- char sbuf[1024]; /* Temporary buffer. */
- va_list va;
-
- if (debug_log) {
- va_start(va, fmt);
- vsprintf(sbuf, fmt, va);
- va_end(va);
- fprintf(stderr, "%s", sbuf);
- }
-}
-
-#endif /* DEBUG */
-
-static ERTS_INLINE void
-report_exit_status(ErtsSysReportExit *rep, int status)
-{
- if (rep->ifd >= 0) {
- driver_data[rep->ifd].alive = 0;
- driver_data[rep->ifd].status = status;
- }
- if (rep->ofd >= 0) {
- driver_data[rep->ofd].alive = 0;
- driver_data[rep->ofd].status = status;
- }
-
- erts_free(ERTS_ALC_T_PRT_REP_EXIT, rep);
-}
-
-#define ERTS_REPORT_EXIT_STATUS report_exit_status
-
-/*
- * Called from schedule() when it runs out of runnable processes,
- * or when Erlang code has performed INPUT_REDUCTIONS reduction
- * steps. runnable == 0 iff there are no runnable Erlang processes.
- */
-void
-erl_sys_schedule(int runnable)
-{
- ASSERT(get_fsem(current_process()) == 0);
-#ifdef ERTS_SMP
- ASSERT(erts_get_scheduler_data()->no == 1);
- ERTS_CHK_IO(!runnable);
-#else
- ERTS_CHK_IO( 1 );
-#endif
- ASSERT(get_fsem(current_process()) == 0);
- ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
-}
-
-
-#ifdef ERTS_SMP
-
-void
-erts_sys_main_thread(void)
-{
- erts_thread_disable_fpe();
-
- /* Become signal receiver thread... */
-#ifdef ERTS_ENABLE_LOCK_CHECK
- erts_lc_set_thread_name("signal_receiver");
-#endif
-
- while (1) {
- static const SIGSELECT sigsel[] = {0};
- union SIGNAL *msg = receive(sigsel);
-
- fprintf(stderr,"Main thread got message %d from 0x%x!!\r\n",
- msg->sig_no, sender(&msg));
- free_buf(&msg);
- }
-}
-
-#endif /* ERTS_SMP */
-
-void
-erl_sys_args(int* argc, char** argv)
-{
- int i, j;
-
- erts_smp_rwmtx_init(&environ_rwmtx, "environ");
-
- init_check_io();
-
- /* Handled arguments have been marked with NULL. Slide arguments
- not handled towards the beginning of argv. */
- for (i = 0, j = 0; i < *argc; i++) {
- if (argv[i])
- argv[j++] = argv[i];
- }
- *argc = j;
-
-}
diff --git a/erts/emulator/sys/ose/sys_float.c b/erts/emulator/sys/ose/sys_float.c
deleted file mode 100644
index 51875792ae..0000000000
--- a/erts/emulator/sys/ose/sys_float.c
+++ /dev/null
@@ -1,845 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2001-2013. 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%
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "sys.h"
-#include "global.h"
-#include "erl_process.h"
-
-
-#ifdef NO_FPE_SIGNALS
-
-void
-erts_sys_init_float(void)
-{
-# ifdef SIGFPE
- sys_sigset(SIGFPE, SIG_IGN); /* Ignore so we can test for NaN and Inf */
-# endif
-}
-
-#else /* !NO_FPE_SIGNALS */
-
-#ifdef ERTS_SMP
-static erts_tsd_key_t fpe_key;
-
-/* once-only initialisation early in the main thread (via erts_sys_init_float()) */
-static void erts_init_fp_exception(void)
-{
- /* XXX: the wrappers prevent using a pthread destructor to
- deallocate the key's value; so when/where do we do that? */
- erts_tsd_key_create(&fpe_key);
-}
-
-void erts_thread_init_fp_exception(void)
-{
- unsigned long *fpe = erts_alloc(ERTS_ALC_T_FP_EXCEPTION, sizeof(*fpe));
- *fpe = 0L;
- erts_tsd_set(fpe_key, fpe);
-}
-
-static ERTS_INLINE volatile unsigned long *erts_thread_get_fp_exception(void)
-{
- return (volatile unsigned long*)erts_tsd_get(fpe_key);
-}
-#else /* !SMP */
-#define erts_init_fp_exception() /*empty*/
-static volatile unsigned long fp_exception;
-#define erts_thread_get_fp_exception() (&fp_exception)
-#endif /* SMP */
-
-volatile unsigned long *erts_get_current_fp_exception(void)
-{
- Process *c_p;
-
- c_p = erts_get_current_process();
- if (c_p)
- return &c_p->fp_exception;
- return erts_thread_get_fp_exception();
-}
-
-static void set_current_fp_exception(unsigned long pc)
-{
- volatile unsigned long *fpexnp = erts_get_current_fp_exception();
- ASSERT(fpexnp != NULL);
- *fpexnp = pc;
-}
-
-void erts_fp_check_init_error(volatile unsigned long *fpexnp)
-{
- char buf[64];
- snprintf(buf, sizeof buf, "ERTS_FP_CHECK_INIT at %p: detected unhandled FPE at %p\r\n",
- __builtin_return_address(0), (void*)*fpexnp);
- if (write(2, buf, strlen(buf)) <= 0)
- erts_exit(ERTS_ABORT_EXIT, "%s", buf);
- *fpexnp = 0;
-#if defined(__i386__) || defined(__x86_64__)
- erts_restore_fpu();
-#endif
-}
-
-/* Is there no standard identifier for Darwin/MacOSX ? */
-#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__)
-#define __DARWIN__ 1
-#endif
-
-#if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
-
-static void unmask_x87(void)
-{
- unsigned short cw;
-
- __asm__ __volatile__("fstcw %0" : "=m"(cw));
- cw &= ~(0x01|0x04|0x08); /* unmask IM, ZM, OM */
- __asm__ __volatile__("fldcw %0" : : "m"(cw));
-}
-
-/* mask x87 FPE, return true if the previous state was unmasked */
-static int mask_x87(void)
-{
- unsigned short cw;
- int unmasked;
-
- __asm__ __volatile__("fstcw %0" : "=m"(cw));
- unmasked = (cw & (0x01|0x04|0x08)) == 0;
- /* or just set cw = 0x37f */
- cw |= (0x01|0x04|0x08); /* mask IM, ZM, OM */
- __asm__ __volatile__("fldcw %0" : : "m"(cw));
- return unmasked;
-}
-
-static void unmask_sse2(void)
-{
- unsigned int mxcsr;
-
- __asm__ __volatile__("stmxcsr %0" : "=m"(mxcsr));
- mxcsr &= ~(0x003F|0x0680); /* clear exn flags, unmask OM, ZM, IM (not PM, UM, DM) */
- __asm__ __volatile__("ldmxcsr %0" : : "m"(mxcsr));
-}
-
-/* mask SSE2 FPE, return true if the previous state was unmasked */
-static int mask_sse2(void)
-{
- unsigned int mxcsr;
- int unmasked;
-
- __asm__ __volatile__("stmxcsr %0" : "=m"(mxcsr));
- unmasked = (mxcsr & 0x0680) == 0;
- /* or just set mxcsr = 0x1f80 */
- mxcsr &= ~0x003F; /* clear exn flags */
- mxcsr |= 0x0680; /* mask OM, ZM, IM (not PM, UM, DM) */
- __asm__ __volatile__("ldmxcsr %0" : : "m"(mxcsr));
- return unmasked;
-}
-
-#if defined(__x86_64__)
-
-static inline int cpu_has_sse2(void) { return 1; }
-
-#else /* !__x86_64__ */
-
-/*
- * Check if an x86-32 processor has SSE2.
- */
-static unsigned int xor_eflags(unsigned int mask)
-{
- unsigned int eax, edx;
-
- eax = mask; /* eax = mask */
- __asm__("pushfl\n\t"
- "popl %0\n\t" /* edx = original EFLAGS */
- "xorl %0, %1\n\t" /* eax = mask ^ EFLAGS */
- "pushl %1\n\t"
- "popfl\n\t" /* new EFLAGS = mask ^ original EFLAGS */
- "pushfl\n\t"
- "popl %1\n\t" /* eax = new EFLAGS */
- "xorl %0, %1\n\t" /* eax = new EFLAGS ^ old EFLAGS */
- "pushl %0\n\t"
- "popfl" /* restore original EFLAGS */
- : "=d"(edx), "=a"(eax)
- : "1"(eax));
- return eax;
-}
-
-static __inline__ unsigned int cpuid_eax(unsigned int op)
-{
- unsigned int eax, save_ebx;
-
- /* In PIC mode i386 reserves EBX. So we must save
- and restore it ourselves to not upset gcc. */
- __asm__(
- "movl %%ebx, %1\n\t"
- "cpuid\n\t"
- "movl %1, %%ebx"
- : "=a"(eax), "=m"(save_ebx)
- : "0"(op)
- : "cx", "dx");
- return eax;
-}
-
-static __inline__ unsigned int cpuid_edx(unsigned int op)
-{
- unsigned int eax, edx, save_ebx;
-
- /* In PIC mode i386 reserves EBX. So we must save
- and restore it ourselves to not upset gcc. */
- __asm__(
- "movl %%ebx, %2\n\t"
- "cpuid\n\t"
- "movl %2, %%ebx"
- : "=a"(eax), "=d"(edx), "=m"(save_ebx)
- : "0"(op)
- : "cx");
- return edx;
-}
-
-/* The AC bit, bit #18, is a new bit introduced in the EFLAGS
- * register on the Intel486 processor to generate alignment
- * faults. This bit cannot be set on the Intel386 processor.
- */
-static __inline__ int is_386(void)
-{
- return ((xor_eflags(1<<18) >> 18) & 1) == 0;
-}
-
-/* Newer x86 processors have a CPUID instruction, as indicated by
- * the ID bit (#21) in EFLAGS being modifiable.
- */
-static __inline__ int has_CPUID(void)
-{
- return (xor_eflags(1<<21) >> 21) & 1;
-}
-
-static int cpu_has_sse2(void)
-{
- unsigned int maxlev, features;
- static int has_sse2 = -1;
-
- if (has_sse2 >= 0)
- return has_sse2;
- has_sse2 = 0;
-
- if (is_386())
- return 0;
- if (!has_CPUID())
- return 0;
- maxlev = cpuid_eax(0);
- /* Intel A-step Pentium had a preliminary version of CPUID.
- It also didn't have SSE2. */
- if ((maxlev & 0xFFFFFF00) == 0x0500)
- return 0;
- /* If max level is zero then CPUID cannot report any features. */
- if (maxlev == 0)
- return 0;
- features = cpuid_edx(1);
- has_sse2 = (features & (1 << 26)) != 0;
-
- return has_sse2;
-}
-#endif /* !__x86_64__ */
-
-static void unmask_fpe(void)
-{
- __asm__ __volatile__("fnclex");
- unmask_x87();
- if (cpu_has_sse2())
- unmask_sse2();
-}
-
-static void unmask_fpe_conditional(int unmasked)
-{
- if (unmasked)
- unmask_fpe();
-}
-
-/* mask x86 FPE, return true if the previous state was unmasked */
-static int mask_fpe(void)
-{
- int unmasked;
-
- unmasked = mask_x87();
- if (cpu_has_sse2())
- unmasked |= mask_sse2();
- return unmasked;
-}
-
-void erts_restore_fpu(void)
-{
- __asm__ __volatile__("fninit");
- unmask_x87();
- if (cpu_has_sse2())
- unmask_sse2();
-}
-
-#elif defined(__sparc__) && defined(__linux__)
-
-#if defined(__arch64__)
-#define LDX "ldx"
-#define STX "stx"
-#else
-#define LDX "ld"
-#define STX "st"
-#endif
-
-static void unmask_fpe(void)
-{
- unsigned long fsr;
-
- __asm__(STX " %%fsr, %0" : "=m"(fsr));
- fsr &= ~(0x1FUL << 23); /* clear FSR[TEM] field */
- fsr |= (0x1AUL << 23); /* enable NV, OF, DZ exceptions */
- __asm__ __volatile__(LDX " %0, %%fsr" : : "m"(fsr));
-}
-
-static void unmask_fpe_conditional(int unmasked)
-{
- if (unmasked)
- unmask_fpe();
-}
-
-/* mask SPARC FPE, return true if the previous state was unmasked */
-static int mask_fpe(void)
-{
- unsigned long fsr;
- int unmasked;
-
- __asm__(STX " %%fsr, %0" : "=m"(fsr));
- unmasked = ((fsr >> 23) & 0x1A) == 0x1A;
- fsr &= ~(0x1FUL << 23); /* clear FSR[TEM] field */
- __asm__ __volatile__(LDX " %0, %%fsr" : : "m"(fsr));
- return unmasked;
-}
-
-#elif (defined(__powerpc__) && defined(__linux__)) || (defined(__ppc__) && defined(__DARWIN__))
-
-#if defined(__linux__)
-#include <sys/prctl.h>
-
-static void set_fpexc_precise(void)
-{
- if (prctl(PR_SET_FPEXC, PR_FP_EXC_PRECISE) < 0) {
- perror("PR_SET_FPEXC");
- exit(1);
- }
-}
-
-#elif defined(__DARWIN__)
-
-#include <mach/mach.h>
-#include <pthread.h>
-
-/*
- * FE0 FE1 MSR bits
- * 0 0 floating-point exceptions disabled
- * 0 1 floating-point imprecise nonrecoverable
- * 1 0 floating-point imprecise recoverable
- * 1 1 floating-point precise mode
- *
- * Apparently:
- * - Darwin 5.5 (MacOS X <= 10.1) starts with FE0 == FE1 == 0,
- * and resets FE0 and FE1 to 0 after each SIGFPE.
- * - Darwin 6.0 (MacOS X 10.2) starts with FE0 == FE1 == 1,
- * and does not reset FE0 or FE1 after a SIGFPE.
- */
-#define FE0_MASK (1<<11)
-#define FE1_MASK (1<<8)
-
-/* a thread cannot get or set its own MSR bits */
-static void *fpu_fpe_enable(void *arg)
-{
- thread_t t = *(thread_t*)arg;
- struct ppc_thread_state state;
- unsigned int state_size = PPC_THREAD_STATE_COUNT;
-
- if (thread_get_state(t, PPC_THREAD_STATE, (natural_t*)&state, &state_size) != KERN_SUCCESS) {
- perror("thread_get_state");
- exit(1);
- }
- if ((state.srr1 & (FE1_MASK|FE0_MASK)) != (FE1_MASK|FE0_MASK)) {
-#if 1
- /* This would also have to be performed in the SIGFPE handler
- to work around the MSR reset older Darwin releases do. */
- state.srr1 |= (FE1_MASK|FE0_MASK);
- thread_set_state(t, PPC_THREAD_STATE, (natural_t*)&state, state_size);
-#else
- fprintf(stderr, "srr1 == 0x%08x, your Darwin is too old\n", state.srr1);
- exit(1);
-#endif
- }
- return NULL; /* Ok, we appear to be on Darwin 6.0 or later */
-}
-
-static void set_fpexc_precise(void)
-{
- thread_t self = mach_thread_self();
- pthread_t enabler;
-
- if (pthread_create(&enabler, NULL, fpu_fpe_enable, &self)) {
- perror("pthread_create");
- } else if (pthread_join(enabler, NULL)) {
- perror("pthread_join");
- }
-}
-
-#endif
-
-static void set_fpscr(unsigned int fpscr)
-{
- union {
- double d;
- unsigned int fpscr[2];
- } u;
-
- u.fpscr[0] = 0xFFF80000;
- u.fpscr[1] = fpscr;
- __asm__ __volatile__("mtfsf 255,%0" : : "f"(u.d));
-}
-
-static unsigned int get_fpscr(void)
-{
- union {
- double d;
- unsigned int fpscr[2];
- } u;
-
- __asm__("mffs %0" : "=f"(u.d));
- return u.fpscr[1];
-}
-
-static void unmask_fpe(void)
-{
- set_fpexc_precise();
- set_fpscr(0x80|0x40|0x10); /* VE, OE, ZE; not UE or XE */
-}
-
-static void unmask_fpe_conditional(int unmasked)
-{
- if (unmasked)
- unmask_fpe();
-}
-
-/* mask PowerPC FPE, return true if the previous state was unmasked */
-static int mask_fpe(void)
-{
- int unmasked;
-
- unmasked = (get_fpscr() & (0x80|0x40|0x10)) == (0x80|0x40|0x10);
- set_fpscr(0x00);
- return unmasked;
-}
-
-#else
-
-static void unmask_fpe(void)
-{
- fpsetmask(FP_X_INV | FP_X_OFL | FP_X_DZ);
-}
-
-static void unmask_fpe_conditional(int unmasked)
-{
- if (unmasked)
- unmask_fpe();
-}
-
-/* mask IEEE FPE, return true if previous state was unmasked */
-static int mask_fpe(void)
-{
- const fp_except unmasked_mask = FP_X_INV | FP_X_OFL | FP_X_DZ;
- fp_except old_mask;
-
- old_mask = fpsetmask(0);
- return (old_mask & unmasked_mask) == unmasked_mask;
-}
-
-#endif
-
-#if (defined(__linux__) && (defined(__i386__) || defined(__x86_64__) || defined(__sparc__) || defined(__powerpc__))) || (defined(__DARWIN__) && (defined(__i386__) || defined(__x86_64__) || defined(__ppc__))) || (defined(__FreeBSD__) && (defined(__x86_64__) || defined(__i386__))) || ((defined(__NetBSD__) || defined(__OpenBSD__)) && defined(__x86_64__)) || (defined(__sun__) && defined(__x86_64__))
-
-#if defined(__linux__) && defined(__i386__)
-#if !defined(X86_FXSR_MAGIC)
-#define X86_FXSR_MAGIC 0x0000
-#endif
-#elif defined(__FreeBSD__) && defined(__x86_64__)
-#include <sys/types.h>
-#include <machine/fpu.h>
-#elif defined(__FreeBSD__) && defined(__i386__)
-#include <sys/types.h>
-#include <machine/npx.h>
-#elif defined(__DARWIN__)
-#include <machine/signal.h>
-#elif defined(__OpenBSD__) && defined(__x86_64__)
-#include <sys/types.h>
-#include <machine/fpu.h>
-#endif
-#if !(defined(__OpenBSD__) && defined(__x86_64__))
-#include <ucontext.h>
-#endif
-#include <string.h>
-
-#if defined(__linux__) && defined(__x86_64__)
-#define mc_pc(mc) ((mc)->gregs[REG_RIP])
-#elif defined(__linux__) && defined(__i386__)
-#define mc_pc(mc) ((mc)->gregs[REG_EIP])
-#elif defined(__DARWIN__) && defined(__i386__)
-#ifdef DARWIN_MODERN_MCONTEXT
-#define mc_pc(mc) ((mc)->__ss.__eip)
-#else
-#define mc_pc(mc) ((mc)->ss.eip)
-#endif
-#elif defined(__DARWIN__) && defined(__x86_64__)
-#ifdef DARWIN_MODERN_MCONTEXT
-#define mc_pc(mc) ((mc)->__ss.__rip)
-#else
-#define mc_pc(mc) ((mc)->ss.rip)
-#endif
-#elif defined(__FreeBSD__) && defined(__x86_64__)
-#define mc_pc(mc) ((mc)->mc_rip)
-#elif defined(__FreeBSD__) && defined(__i386__)
-#define mc_pc(mc) ((mc)->mc_eip)
-#elif defined(__NetBSD__) && defined(__x86_64__)
-#define mc_pc(mc) ((mc)->__gregs[_REG_RIP])
-#elif defined(__NetBSD__) && defined(__i386__)
-#define mc_pc(mc) ((mc)->__gregs[_REG_EIP])
-#elif defined(__OpenBSD__) && defined(__x86_64__)
-#define mc_pc(mc) ((mc)->sc_rip)
-#elif defined(__sun__) && defined(__x86_64__)
-#define mc_pc(mc) ((mc)->gregs[REG_RIP])
-#endif
-
-static void fpe_sig_action(int sig, siginfo_t *si, void *puc)
-{
- ucontext_t *uc = puc;
- unsigned long pc;
-
-#if defined(__linux__)
-#if defined(__x86_64__)
- mcontext_t *mc = &uc->uc_mcontext;
- fpregset_t fpstate = mc->fpregs;
- pc = mc_pc(mc);
- /* A failed SSE2 instruction will restart. To avoid
- looping we mask SSE2 exceptions now and unmask them
- again later in erts_check_fpe()/erts_restore_fpu().
- On RISCs we update PC to skip the failed instruction,
- but the ever increasing complexity of the x86 instruction
- set encoding makes that a poor solution here. */
- fpstate->mxcsr = 0x1F80;
- fpstate->swd &= ~0xFF;
-#elif defined(__i386__)
- mcontext_t *mc = &uc->uc_mcontext;
- fpregset_t fpstate = mc->fpregs;
- pc = mc_pc(mc);
- if ((fpstate->status >> 16) == X86_FXSR_MAGIC)
- ((struct _fpstate*)fpstate)->mxcsr = 0x1F80;
- fpstate->sw &= ~0xFF;
-#elif defined(__sparc__) && defined(__arch64__)
- /* on SPARC the 3rd parameter points to a sigcontext not a ucontext */
- struct sigcontext *sc = (struct sigcontext*)puc;
- pc = sc->sigc_regs.tpc;
- sc->sigc_regs.tpc = sc->sigc_regs.tnpc;
- sc->sigc_regs.tnpc += 4;
-#elif defined(__sparc__)
- /* on SPARC the 3rd parameter points to a sigcontext not a ucontext */
- struct sigcontext *sc = (struct sigcontext*)puc;
- pc = sc->si_regs.pc;
- sc->si_regs.pc = sc->si_regs.npc;
- sc->si_regs.npc = (unsigned long)sc->si_regs.npc + 4;
-#elif defined(__powerpc__)
-#if defined(__powerpc64__)
- mcontext_t *mc = &uc->uc_mcontext;
- unsigned long *regs = &mc->gp_regs[0];
-#else
- mcontext_t *mc = uc->uc_mcontext.uc_regs;
- unsigned long *regs = &mc->gregs[0];
-#endif
- pc = regs[PT_NIP];
- regs[PT_NIP] += 4;
- regs[PT_FPSCR] = 0x80|0x40|0x10; /* VE, OE, ZE; not UE or XE */
-#endif
-#elif defined(__DARWIN__) && (defined(__i386__) || defined(__x86_64__))
-#ifdef DARWIN_MODERN_MCONTEXT
- mcontext_t mc = uc->uc_mcontext;
- pc = mc_pc(mc);
- mc->__fs.__fpu_mxcsr = 0x1F80;
- *(unsigned short *)&mc->__fs.__fpu_fsw &= ~0xFF;
-#else
- mcontext_t mc = uc->uc_mcontext;
- pc = mc_pc(mc);
- mc->fs.fpu_mxcsr = 0x1F80;
- *(unsigned short *)&mc->fs.fpu_fsw &= ~0xFF;
-#endif /* DARWIN_MODERN_MCONTEXT */
-#elif defined(__DARWIN__) && defined(__ppc__)
- mcontext_t mc = uc->uc_mcontext;
- pc = mc->ss.srr0;
- mc->ss.srr0 += 4;
- mc->fs.fpscr = 0x80|0x40|0x10;
-#elif defined(__FreeBSD__) && defined(__x86_64__)
- mcontext_t *mc = &uc->uc_mcontext;
- struct savefpu *savefpu = (struct savefpu*)&mc->mc_fpstate;
- struct envxmm *envxmm = &savefpu->sv_env;
- pc = mc_pc(mc);
- envxmm->en_mxcsr = 0x1F80;
- envxmm->en_sw &= ~0xFF;
-#elif defined(__FreeBSD__) && defined(__i386__)
- mcontext_t *mc = &uc->uc_mcontext;
- union savefpu *savefpu = (union savefpu*)&mc->mc_fpstate;
- pc = mc_pc(mc);
- if (mc->mc_fpformat == _MC_FPFMT_XMM) {
- struct envxmm *envxmm = &savefpu->sv_xmm.sv_env;
- envxmm->en_mxcsr = 0x1F80;
- envxmm->en_sw &= ~0xFF;
- } else {
- struct env87 *env87 = &savefpu->sv_87.sv_env;
- env87->en_sw &= ~0xFF;
- }
-#elif defined(__NetBSD__) && defined(__x86_64__)
- mcontext_t *mc = &uc->uc_mcontext;
- struct fxsave64 *fxsave = (struct fxsave64 *)&mc->__fpregs;
- pc = mc_pc(mc);
- fxsave->fx_mxcsr = 0x1F80;
- fxsave->fx_fsw &= ~0xFF;
-#elif defined(__NetBSD__) && defined(__i386__)
- mcontext_t *mc = &uc->uc_mcontext;
- pc = mc_pc(mc);
- if (uc->uc_flags & _UC_FXSAVE) {
- struct envxmm *envxmm = (struct envxmm *)&mc->__fpregs;
- envxmm->en_mxcsr = 0x1F80;
- envxmm->en_sw &= ~0xFF;
- } else {
- struct env87 *env87 = (struct env87 *)&mc->__fpregs;
- env87->en_sw &= ~0xFF;
- }
-#elif defined(__OpenBSD__) && defined(__x86_64__)
- struct fxsave64 *fxsave = uc->sc_fpstate;
- pc = mc_pc(uc);
- fxsave->fx_mxcsr = 0x1F80;
- fxsave->fx_fsw &= ~0xFF;
-#elif defined(__sun__) && defined(__x86_64__)
- mcontext_t *mc = &uc->uc_mcontext;
- struct fpchip_state *fpstate = &mc->fpregs.fp_reg_set.fpchip_state;
- pc = mc_pc(mc);
- fpstate->mxcsr = 0x1F80;
- fpstate->sw &= ~0xFF;
-#endif
-#if 0
- {
- char buf[64];
- snprintf(buf, sizeof buf, "%s: FPE at %p\r\n", __FUNCTION__, (void*)pc);
- write(2, buf, strlen(buf));
- }
-#endif
- set_current_fp_exception(pc);
-}
-
-static void erts_thread_catch_fp_exceptions(void)
-{
- struct sigaction act;
- memset(&act, 0, sizeof act);
- act.sa_sigaction = fpe_sig_action;
- act.sa_flags = SA_SIGINFO;
- sigaction(SIGFPE, &act, NULL);
- unmask_fpe();
-}
-
-#else /* !((__linux__ && (__i386__ || __x86_64__ || __powerpc__)) || (__DARWIN__ && (__i386__ || __x86_64__ || __ppc__))) */
-
-static void fpe_sig_handler(int sig)
-{
- set_current_fp_exception(1); /* XXX: convert to sigaction so we can get the trap PC */
-}
-
-static void erts_thread_catch_fp_exceptions(void)
-{
- sys_sigset(SIGFPE, fpe_sig_handler);
- unmask_fpe();
-}
-
-#endif /* (__linux__ && (__i386__ || __x86_64__ || __powerpc__)) || (__DARWIN__ && (__i386__ || __x86_64__ || __ppc__))) */
-
-/* once-only initialisation early in the main thread */
-void erts_sys_init_float(void)
-{
- erts_init_fp_exception();
- erts_thread_catch_fp_exceptions();
- erts_printf_block_fpe = erts_sys_block_fpe;
- erts_printf_unblock_fpe = erts_sys_unblock_fpe;
-}
-
-#endif /* NO_FPE_SIGNALS */
-
-void erts_thread_init_float(void)
-{
-#ifdef ERTS_SMP
- /* This allows Erlang schedulers to leave Erlang-process context
- and still have working FP exceptions. XXX: is this needed? */
- erts_thread_init_fp_exception();
-#endif
-
-#ifndef NO_FPE_SIGNALS
- /* NOTE:
- * erts_thread_disable_fpe() is called in all threads at
- * creation. We at least need to call unmask_fpe()
- */
-#if defined(__DARWIN__) || defined(__FreeBSD__)
- /* Darwin (7.9.0) does not appear to propagate FP exception settings
- to a new thread from its parent. So if we want FP exceptions, we
- must manually re-enable them in each new thread.
- FreeBSD 6.1 appears to suffer from a similar issue. */
- erts_thread_catch_fp_exceptions();
-#else
- unmask_fpe();
-#endif
-
-#endif
-}
-
-void erts_thread_disable_fpe(void)
-{
-#if !defined(NO_FPE_SIGNALS)
- (void)mask_fpe();
-#endif
-}
-
-#if !defined(NO_FPE_SIGNALS)
-int erts_sys_block_fpe(void)
-{
- return mask_fpe();
-}
-
-void erts_sys_unblock_fpe(int unmasked)
-{
- unmask_fpe_conditional(unmasked);
-}
-#endif
-
-/* The following check is incorporated from the Vee machine */
-
-#define ISDIGIT(d) ((d) >= '0' && (d) <= '9')
-
-/*
- ** Convert a double to ascii format 0.dddde[+|-]ddd
- ** return number of characters converted or -1 if error.
- **
- ** These two functions should maybe use localeconv() to pick up
- ** the current radix character, but since it is uncertain how
- ** expensive such a system call is, and since no-one has heard
- ** of other radix characters than '.' and ',' an ad-hoc
- ** low execution time solution is used instead.
- */
-
-int
-sys_double_to_chars_ext(double fp, char *buffer, size_t buffer_size, size_t decimals)
-{
- char *s = buffer;
-
- if (erts_snprintf(buffer, buffer_size, "%.*e", decimals, fp) >= buffer_size)
- return -1;
- /* Search upto decimal point */
- if (*s == '+' || *s == '-') s++;
- while (ISDIGIT(*s)) s++;
- if (*s == ',') *s++ = '.'; /* Replace ',' with '.' */
- /* Scan to end of string */
- while (*s) s++;
- return s-buffer; /* i.e strlen(buffer) */
-}
-
-/* Float conversion */
-
-int
-sys_chars_to_double(char* buf, double* fp)
-{
-#ifndef NO_FPE_SIGNALS
- volatile unsigned long *fpexnp = erts_get_current_fp_exception();
-#endif
- char *s = buf, *t, *dp;
-
- /* Robert says that something like this is what he really wanted:
- * (The [.,] radix test is NOT what Robert wanted - it was added later)
- *
- * 7 == sscanf(Tbuf, "%[+-]%[0-9][.,]%[0-9]%[eE]%[+-]%[0-9]%s", ....);
- * if (*s2 == 0 || *s3 == 0 || *s4 == 0 || *s6 == 0 || *s7)
- * break;
- */
-
- /* Scan string to check syntax. */
- if (*s == '+' || *s == '-') s++;
- if (!ISDIGIT(*s)) /* Leading digits. */
- return -1;
- while (ISDIGIT(*s)) s++;
- if (*s != '.' && *s != ',') /* Decimal part. */
- return -1;
- dp = s++; /* Remember decimal point pos just in case */
- if (!ISDIGIT(*s))
- return -1;
- while (ISDIGIT(*s)) s++;
- if (*s == 'e' || *s == 'E') {
- /* There is an exponent. */
- s++;
- if (*s == '+' || *s == '-') s++;
- if (!ISDIGIT(*s))
- return -1;
- while (ISDIGIT(*s)) s++;
- }
- if (*s) /* That should be it */
- return -1;
-
-#ifdef NO_FPE_SIGNALS
- errno = 0;
-#endif
- __ERTS_FP_CHECK_INIT(fpexnp);
- *fp = strtod(buf, &t);
- __ERTS_FP_ERROR_THOROUGH(fpexnp, *fp, return -1);
- if (t != s) { /* Whole string not scanned */
- /* Try again with other radix char */
- *dp = (*dp == '.') ? ',' : '.';
- errno = 0;
- __ERTS_FP_CHECK_INIT(fpexnp);
- *fp = strtod(buf, &t);
- __ERTS_FP_ERROR_THOROUGH(fpexnp, *fp, return -1);
- }
-
-#ifdef NO_FPE_SIGNALS
- if (errno == ERANGE) {
- if (*fp == HUGE_VAL || *fp == -HUGE_VAL) {
- /* overflow, should give error */
- return -1;
- } else if (t == s && *fp == 0.0) {
- /* This should give 0.0 - OTP-7178 */
- errno = 0;
-
- } else if (*fp == 0.0) {
- return -1;
- }
- }
-#endif
- return 0;
-}
-
-int
-matherr(struct exception *exc)
-{
-#if !defined(NO_FPE_SIGNALS)
- volatile unsigned long *fpexnp = erts_get_current_fp_exception();
- if (fpexnp != NULL)
- *fpexnp = (unsigned long)__builtin_return_address(0);
-#endif
- return 1;
-}
diff --git a/erts/emulator/sys/ose/sys_time.c b/erts/emulator/sys/ose/sys_time.c
deleted file mode 100644
index 5dac75956a..0000000000
--- a/erts/emulator/sys/ose/sys_time.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2005-2009. 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%
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "sys.h"
-#include "global.h"
-
-/******************* Routines for time measurement *********************/
-
-int erts_ticks_per_sec = 0; /* Will be SYS_CLK_TCK in erl_unix_sys.h */
-
-int sys_init_time(void)
-{
- return SYS_CLOCK_RESOLUTION;
-}
-
-clock_t sys_times(SysTimes *now) {
- now->tms_utime = now->tms_stime = now->tms_cutime = now->tms_cstime = 0;
- return 0;
-}
-
-static OSTICK last_tick_count = 0;
-static SysHrTime wrap = 0;
-static OSTICK us_per_tick;
-
-void sys_init_hrtime() {
- us_per_tick = system_tick();
-}
-
-SysHrTime sys_gethrtime() {
- OSTICK ticks = get_ticks();
- if (ticks < (SysHrTime) last_tick_count) {
- wrap += 1ULL << 32;
- }
- last_tick_count = ticks;
- return ((((SysHrTime) ticks) + wrap) * 1000*us_per_tick);
-}
diff --git a/erts/emulator/sys/unix/erl_child_setup.c b/erts/emulator/sys/unix/erl_child_setup.c
index a3c5c20641..8dd14bbac6 100644
--- a/erts/emulator/sys/unix/erl_child_setup.c
+++ b/erts/emulator/sys/unix/erl_child_setup.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2002-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.
@@ -19,109 +19,234 @@
*/
/*
- * After a vfork() (or fork()) the child exec()s to this program which
- * sets up the child and exec()s to the user program (see spawn_start()
- * in sys.c and ticket OTP-4389).
+ * This program is started at erts startup and all fork's that
+ * have to be done are done in here. This is done for a couple
+ * of reasons:
+ * - Allow usage of fork without a memory explosion.
+ * -- we do not want to use vfork, as it blocks the VM
+ * until the execv is done, and if the program that
+ * is to be executed is on an NFS that is unavailable,
+ * the execv can block for a very long time.
+ * -- we cannot do fork inside the VM as that would temporarily
+ * duplicate the memory usage of the VM per parallel exec.
+ *
+ * Some implementation notes:
+ * - A single Unix Domain Socket is setup in between the VM and
+ * this program. Over that UDS the file descriptors that should
+ * be used to talk to the child program are sent.
+ * The actual command to execute, together with options and the
+ * environment, is sent over the pipe represented by the
+ * file descriptors mentioned above. We don't send the
+ * command over the UDS as that would increase the likely hood
+ * that it's buffer would be full.
+ *
+ * - Since it is this program that execv's, it has to take care of
+ * all the SIGCHLD signals that the child programs generate. The
+ * signals are received and the pid+exit reason is sent as data
+ * on the UDS to the VM. The VM is then able to map the pid to the
+ * port of the child program that just exited and deliver the status
+ * code if requested.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-#define NEED_CHILD_SETUP_DEFINES
-#include "sys.h"
-#include "erl_misc_utils.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/wait.h>
-#ifdef SIG_SIGSET /* Old SysV */
-void sys_sigrelease(int sig)
+#define WANT_NONBLOCKING
+
+#include "erl_driver.h"
+#include "sys_uds.h"
+#include "hash.h"
+#include "erl_term.h"
+#include "erl_child_setup.h"
+
+#define SET_CLOEXEC(fd) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC)
+
+#if defined(__ANDROID__)
+#define SHELL "/system/bin/sh"
+#else
+#define SHELL "/bin/sh"
+#endif /* __ANDROID__ */
+
+//#define HARD_DEBUG
+#ifdef HARD_DEBUG
+#define DEBUG_PRINT(fmt, ...) fprintf(stderr, fmt "\r\n", ##__VA_ARGS__)
+#else
+#define DEBUG_PRINT(fmt, ...)
+#endif
+
+#define ABORT(fmt, ...) do { \
+ fprintf(stderr, "erl_child_setup: " fmt "\r\n", ##__VA_ARGS__); \
+ abort(); \
+ } while(0)
+
+#ifdef DEBUG
+void
+erl_assert_error(const char* expr, const char* func, const char* file, int line)
{
- sigrelse(sig);
+ fflush(stdout);
+ fprintf(stderr, "%s:%d:%s() Assertion failed: %s\n",
+ file, line, func, expr);
+ fflush(stderr);
+ abort();
}
-#else /* !SIG_SIGSET */
-#ifdef SIG_SIGNAL /* Old BSD */
-sys_sigrelease(int sig)
+#endif
+
+void sys_sigblock(int sig)
{
- sigsetmask(sigblock(0) & ~sigmask(sig));
+ sigset_t mask;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, sig);
+ sigprocmask(SIG_BLOCK, &mask, (sigset_t *)NULL);
}
-#else /* !SIG_SIGNAL */ /* The True Way - POSIX!:-) */
+
void sys_sigrelease(int sig)
{
sigset_t mask;
-
sigemptyset(&mask);
sigaddset(&mask, sig);
sigprocmask(SIG_UNBLOCK, &mask, (sigset_t *)NULL);
}
-#endif /* !SIG_SIGNAL */
-#endif /* !SIG_SIGSET */
-
-#if defined(__ANDROID__)
-static int system_properties_fd(void);
-#endif /* __ANDROID__ */
-#if defined(__ANDROID__)
-#define SHELL "/system/bin/sh"
-#else
-#define SHELL "/bin/sh"
-#endif /* __ANDROID__ */
+static void add_os_pid_to_port_id_mapping(Eterm, pid_t);
+static Eterm get_port_id(pid_t);
+static int forker_hash_init(void);
+static int max_files = -1;
+static int sigchld_pipe[2];
-int
-main(int argc, char *argv[])
+static int
+start_new_child(int pipes[])
{
- int i, from, to;
- int erts_spawn_executable = 0;
+ int size, res, i, pos = 0;
+ char *buff, *o_buff;
+
+ char *cmd, *wd, **new_environ, **args = NULL;
+
+ Sint cnt, flags;
- /* OBSERVE!
- * Keep child setup after fork() (implemented in sys.c) up to date
- * if changes are made here.
- */
+ /* only child executes here */
- if (argc != CS_ARGV_NO_OF_ARGS) {
- if (argc < CS_ARGV_NO_OF_ARGS) {
- return 1;
- } else {
- erts_spawn_executable = 1;
- }
+ do {
+ res = read(pipes[0], (char*)&size, sizeof(size));
+ } while(res < 0 && (errno == EINTR || errno == ERRNO_BLOCK));
+
+ if (res <= 0) {
+ goto child_error;
}
- if (strcmp("false", argv[CS_ARGV_UNBIND_IX]) != 0)
- if (erts_unbind_from_cpu_str(argv[CS_ARGV_UNBIND_IX]) != 0)
- return 1;
+ buff = malloc(size);
+
+ DEBUG_PRINT("size = %d", size);
+
+ do {
+ if ((res = read(pipes[0], buff + pos, size - pos)) < 0) {
+ if (errno == ERRNO_BLOCK || errno == EINTR)
+ continue;
+ goto child_error;
+ }
+ if (res == 0) {
+ errno = EPIPE;
+ goto child_error;
+ }
+ pos += res;
+ } while(size - pos != 0);
+
+ o_buff = buff;
+
+ flags = get_int32(buff);
+ buff += sizeof(Sint32);
- for (i = 0; i < CS_ARGV_NO_OF_DUP2_OPS; i++) {
- if (argv[CS_ARGV_DUP2_OP_IX(i)][0] == '-'
- && argv[CS_ARGV_DUP2_OP_IX(i)][1] == '\0')
- break;
- if (sscanf(argv[CS_ARGV_DUP2_OP_IX(i)], "%d:%d", &from, &to) != 2)
- return 1;
- if (dup2(from, to) < 0)
- return 1;
+ DEBUG_PRINT("flags = %d", flags);
+
+ cmd = buff;
+ buff += strlen(buff) + 1;
+ if (*buff == '\0') {
+ wd = NULL;
+ } else {
+ wd = buff;
+ buff += strlen(buff) + 1;
}
+ buff++;
- if (sscanf(argv[CS_ARGV_FD_CR_IX], "%d:%d", &from, &to) != 2)
- return 1;
+ DEBUG_PRINT("wd = %s", wd);
-#if defined(HAVE_CLOSEFROM)
- closefrom(from);
-#elif defined(__ANDROID__)
- if (from <= to) {
- int spfd = system_properties_fd();
- for (i = from; i <= to; i++) {
- if (i != spfd) {
- (void) close(i);
- }
- }
+ cnt = get_int32(buff);
+ buff += sizeof(Sint32);
+ new_environ = malloc(sizeof(char*)*(cnt + 1));
+
+ DEBUG_PRINT("env_len = %ld", cnt);
+ for (i = 0; i < cnt; i++, buff++) {
+ new_environ[i] = buff;
+ while(*buff != '\0') buff++;
}
-#else /* !__ANDROID__ */
- for (i = from; i <= to; i++) {
- (void) close(i);
+ new_environ[cnt] = NULL;
+
+ if (o_buff + size != buff) {
+ /* This is a spawn executable call */
+ cnt = get_int32(buff);
+ buff += sizeof(Sint32);
+ args = malloc(sizeof(char*)*(cnt + 1));
+ for (i = 0; i < cnt; i++, buff++) {
+ args[i] = buff;
+ while(*buff != '\0') buff++;
+ }
+ args[cnt] = NULL;
}
-#endif /* HAVE_CLOSEFROM */
- if (!(argv[CS_ARGV_WD_IX][0] == '.' && argv[CS_ARGV_WD_IX][1] == '\0')
- && chdir(argv[CS_ARGV_WD_IX]) < 0)
- return 1;
+ if (o_buff + size != buff) {
+ errno = EINVAL;
+ goto child_error;
+ }
+
+ DEBUG_PRINT("read ack");
+ do {
+ ErtsSysForkerProto proto;
+ res = read(pipes[0], &proto, sizeof(proto));
+ if (res > 0) {
+ ASSERT(proto.action == ErtsSysForkerProtoAction_Ack);
+ ASSERT(res == sizeof(proto));
+ }
+ } while(res < 0 && (errno == EINTR || errno == ERRNO_BLOCK));
+ if (res < 1) {
+ errno = EPIPE;
+ goto child_error;
+ }
+
+ DEBUG_PRINT("Do that forking business: '%s'\n",cmd);
+
+ /* When the dup2'ing below is done, only
+ fd's 0, 1, 2 and maybe 3, 4 should survive the
+ exec. All other fds (i.e. the unix domain sockets
+ and stray pipe ends) should have CLOEXEC set on them
+ so they will be closed when the exec happens */
+ if (flags & FORKER_FLAG_USE_STDIO) {
+ /* stdin for process */
+ if (flags & FORKER_FLAG_DO_WRITE &&
+ dup2(pipes[0], 0) < 0)
+ goto child_error;
+ /* stdout for process */
+ if (flags & FORKER_FLAG_DO_READ &&
+ dup2(pipes[1], 1) < 0)
+ goto child_error;
+ }
+ else { /* XXX will fail if pipes[0] == 4 (unlikely..) */
+ if (flags & FORKER_FLAG_DO_READ && dup2(pipes[1], 4) < 0)
+ goto child_error;
+ if (flags & FORKER_FLAG_DO_WRITE && dup2(pipes[0], 3) < 0)
+ goto child_error;
+ }
+
+ if (dup2(pipes[2], 2) < 0)
+ goto child_error;
+
+ if (wd && chdir(wd) < 0)
+ goto child_error;
#if defined(USE_SETPGRP_NOARGS) /* SysV */
(void) setpgrp();
@@ -131,34 +256,301 @@ main(int argc, char *argv[])
(void) setsid();
#endif
+ close(pipes[0]);
+ close(pipes[1]);
+ close(pipes[2]);
+
sys_sigrelease(SIGCHLD);
- sys_sigrelease(SIGINT);
- sys_sigrelease(SIGUSR1);
-
- if (erts_spawn_executable) {
- if (argv[CS_ARGV_NO_OF_ARGS + 1] == NULL) {
- execl(argv[CS_ARGV_NO_OF_ARGS],argv[CS_ARGV_NO_OF_ARGS],
- (char *) NULL);
- } else {
- execv(argv[CS_ARGV_NO_OF_ARGS],&(argv[CS_ARGV_NO_OF_ARGS + 1]));
- }
+
+ if (args) {
+ /* spawn_executable */
+ execve(cmd, args, new_environ);
} else {
- execl(SHELL, "sh", "-c", argv[CS_ARGV_CMD_IX], (char *) NULL);
+ execle(SHELL, "sh", "-c", cmd, (char *) NULL, new_environ);
}
- return 1;
+child_error:
+ DEBUG_PRINT("exec error: %d\r\n",errno);
+ _exit(128 + errno);
+}
+
+
+/*
+ * [OTP-3906]
+ * Solaris signal management gets confused when threads are used and a
+ * lot of child processes dies. The confusion results in that SIGCHLD
+ * signals aren't delivered to the emulator which in turn results in
+ * a lot of defunct processes in the system.
+ *
+ * The problem seems to appear when a signal is frequently
+ * blocked/unblocked at the same time as the signal is frequently
+ * propagated. The child waiter thread is a workaround for this problem.
+ * The SIGCHLD signal is always blocked (in all threads), and the child
+ * waiter thread fetches the signal by a call to sigwait(). See
+ * child_waiter().
+ *
+ * This should be a non-issue since the fork:ing was moved outside of
+ * the emulator into erl_child_setup. I'm leaving the comment here
+ * for posterity. */
+
+static void handle_sigchld(int sig) {
+ int buff[2], res;
+
+ sys_sigblock(SIGCHLD);
+
+ while ((buff[0] = waitpid((pid_t)(-1), buff+1, WNOHANG)) > 0) {
+ do {
+ res = write(sigchld_pipe[1], buff, sizeof(buff));
+ } while (res < 0 && errno == EINTR);
+ if (res <= 0)
+ ABORT("Failed to write to sigchld_pipe (%d): %d (%d)", sigchld_pipe[1], res, errno);
+ DEBUG_PRINT("Reap child %d (%d)", buff[0], buff[1]);
+ }
+
+ sys_sigrelease(SIGCHLD);
}
#if defined(__ANDROID__)
static int system_properties_fd(void)
{
- int fd;
+ static int fd = -2;
char *env;
+ if (fd != -2) return fd;
env = getenv("ANDROID_PROPERTY_WORKSPACE");
if (!env) {
+ fd = -1;
return -1;
}
fd = atoi(env);
return fd;
}
#endif /* __ANDROID__ */
+
+int
+main(int argc, char *argv[])
+{
+ /* This fd should be open from beam */
+ int uds_fd = 3, max_fd = 3;
+#ifndef HAVE_CLOSEFROM
+ int i;
+#endif
+ struct sigaction sa;
+
+ if (argc < 1 || sscanf(argv[1],"%d",&max_files) != 1) {
+ ABORT("Invalid arguments to child_setup");
+ }
+
+/* We close all fds except the uds from beam.
+ All other fds from now on will have the
+ CLOEXEC flags set on them. This means that we
+ only have to close a very limited number of fds
+ after we fork before the exec. */
+#if defined(HAVE_CLOSEFROM)
+ closefrom(4);
+#else
+ for (i = 4; i < max_files; i++)
+#if defined(__ANDROID__)
+ if (i != system_properties_fd())
+#endif
+ (void) close(i);
+#endif
+
+ if (pipe(sigchld_pipe) < 0) {
+ ABORT("Failed to setup sigchld pipe (%d)", errno);
+ }
+
+ SET_CLOEXEC(sigchld_pipe[0]);
+ SET_CLOEXEC(sigchld_pipe[1]);
+
+ max_fd = max_fd < sigchld_pipe[0] ? sigchld_pipe[0] : max_fd;
+
+ sa.sa_handler = &handle_sigchld;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
+ if (sigaction(SIGCHLD, &sa, 0) == -1) {
+ perror(0);
+ exit(1);
+ }
+
+ forker_hash_init();
+
+ SET_CLOEXEC(uds_fd);
+
+ DEBUG_PRINT("Starting forker %d", max_files);
+
+ while (1) {
+ fd_set read_fds;
+ int res;
+ FD_ZERO(&read_fds);
+ FD_SET(uds_fd, &read_fds);
+ FD_SET(sigchld_pipe[0], &read_fds);
+ DEBUG_PRINT("child_setup selecting on %d, %d (%d)",
+ uds_fd, sigchld_pipe[0], max_fd);
+ res = select(max_fd+1, &read_fds, NULL, NULL, NULL);
+
+ if (res < 0) {
+ if (errno == EINTR) continue;
+ ABORT("Select failed: %d (%d)",res, errno);
+ }
+
+ if (FD_ISSET(uds_fd, &read_fds)) {
+ int pipes[3], res, os_pid;
+ ErtsSysForkerProto proto;
+ errno = 0;
+ if ((res = sys_uds_read(uds_fd, (char*)&proto, sizeof(proto),
+ pipes, 3, MSG_DONTWAIT)) < 0) {
+ if (errno == EINTR)
+ continue;
+ DEBUG_PRINT("erl_child_setup failed to read from uds: %d, %d", res, errno);
+ _exit(0);
+ }
+
+ if (res == 0) {
+ DEBUG_PRINT("uds was closed!");
+ _exit(0);
+ }
+ /* Since we use unix domain sockets and send the entire data in
+ one go we *should* get the entire payload at once. */
+ ASSERT(res == sizeof(proto));
+ ASSERT(proto.action == ErtsSysForkerProtoAction_Start);
+
+ sys_sigblock(SIGCHLD);
+
+ errno = 0;
+
+ os_pid = fork();
+ if (os_pid == 0)
+ start_new_child(pipes);
+
+ add_os_pid_to_port_id_mapping(proto.u.start.port_id, os_pid);
+
+ /* We write an ack here, but expect the reply on
+ the pipes[0] inside the fork */
+ proto.action = ErtsSysForkerProtoAction_Go;
+ proto.u.go.os_pid = os_pid;
+ proto.u.go.error_number = errno;
+ while (write(pipes[1], &proto, sizeof(proto)) < 0 && errno == EINTR)
+ ; /* remove gcc warning */
+
+#ifdef FORKER_PROTO_START_ACK
+ proto.action = ErtsSysForkerProtoAction_StartAck;
+ while (write(uds_fd, &proto, sizeof(proto)) < 0 && errno == EINTR)
+ ; /* remove gcc warning */
+#endif
+
+ sys_sigrelease(SIGCHLD);
+ close(pipes[0]);
+ close(pipes[1]);
+ close(pipes[2]);
+ }
+
+ if (FD_ISSET(sigchld_pipe[0], &read_fds)) {
+ int ibuff[2];
+ ErtsSysForkerProto proto;
+ res = read(sigchld_pipe[0], ibuff, sizeof(ibuff));
+ if (res <= 0) {
+ if (errno == EINTR)
+ continue;
+ ABORT("Failed to read from sigchld pipe: %d (%d)", res, errno);
+ }
+
+ proto.u.sigchld.port_id = get_port_id((pid_t)(ibuff[0]));
+
+ if (proto.u.sigchld.port_id == THE_NON_VALUE)
+ continue; /* exit status report not requested */
+
+ proto.action = ErtsSysForkerProtoAction_SigChld;
+ proto.u.sigchld.error_number = ibuff[1];
+ DEBUG_PRINT("send %s to %d", buff, uds_fd);
+ if (write(uds_fd, &proto, sizeof(proto)) < 0) {
+ if (errno == EINTR)
+ continue;
+ /* The uds was close, which most likely means that the VM
+ has exited. This will be detected when we try to read
+ from the uds_fd. */
+ DEBUG_PRINT("Failed to write to uds: %d (%d)", uds_fd, errno);
+ }
+ }
+ }
+ return 1;
+}
+
+typedef struct exit_status {
+ HashBucket hb;
+ pid_t os_pid;
+ Eterm port_id;
+} ErtsSysExitStatus;
+
+static Hash *forker_hash;
+
+static void add_os_pid_to_port_id_mapping(Eterm port_id, pid_t os_pid)
+{
+ if (port_id != THE_NON_VALUE) {
+ /* exit status report requested */
+ ErtsSysExitStatus es;
+ es.os_pid = os_pid;
+ es.port_id = port_id;
+ hash_put(forker_hash, &es);
+ }
+}
+
+static Eterm get_port_id(pid_t os_pid)
+{
+ ErtsSysExitStatus est, *es;
+ Eterm port_id;
+ est.os_pid = os_pid;
+ es = hash_remove(forker_hash, &est);
+ if (!es) return THE_NON_VALUE;
+ port_id = es->port_id;
+ free(es);
+ return port_id;
+}
+
+static int fcmp(void *a, void *b)
+{
+ ErtsSysExitStatus *sa = a;
+ ErtsSysExitStatus *sb = b;
+ return !(sa->os_pid == sb->os_pid);
+}
+
+static HashValue fhash(void *e)
+{
+ ErtsSysExitStatus *se = e;
+ Uint32 val = se->os_pid;
+ val = (val+0x7ed55d16) + (val<<12);
+ val = (val^0xc761c23c) ^ (val>>19);
+ val = (val+0x165667b1) + (val<<5);
+ val = (val+0xd3a2646c) ^ (val<<9);
+ val = (val+0xfd7046c5) + (val<<3);
+ val = (val^0xb55a4f09) ^ (val>>16);
+ return val;
+}
+
+static void *falloc(void *e)
+{
+ ErtsSysExitStatus *se = e;
+ ErtsSysExitStatus *ne = malloc(sizeof(ErtsSysExitStatus));
+ ne->os_pid = se->os_pid;
+ ne->port_id = se->port_id;
+ return ne;
+}
+
+static void *meta_alloc(int type, size_t size) { return malloc(size); }
+static void meta_free(int type, void *p) { free(p); }
+
+static int forker_hash_init(void)
+{
+ HashFunctions forker_hash_functions;
+ forker_hash_functions.hash = fhash;
+ forker_hash_functions.cmp = fcmp;
+ forker_hash_functions.alloc = falloc;
+ forker_hash_functions.free = free;
+ forker_hash_functions.meta_alloc = meta_alloc;
+ forker_hash_functions.meta_free = meta_free;
+ forker_hash_functions.meta_print = NULL;
+
+ forker_hash = hash_new(0, "forker_hash",
+ 16, forker_hash_functions);
+
+ return 1;
+}
diff --git a/erts/emulator/sys/unix/erl_child_setup.h b/erts/emulator/sys/unix/erl_child_setup.h
new file mode 100644
index 0000000000..a28b136bfc
--- /dev/null
+++ b/erts/emulator/sys/unix/erl_child_setup.h
@@ -0,0 +1,77 @@
+/*
+ * %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%
+ *
+ * This file defines the interface inbetween erts and child_setup.
+ */
+
+#ifndef _ERL_UNIX_FORKER_H
+#define _ERL_UNIX_FORKER_H
+
+#include "sys.h"
+
+#ifdef __FreeBSD__
+/* The freebsd sendmsg man page explicitly states that
+ you should not close fds before they are known
+ to have reached the other side, so this Ack protects
+ against that. */
+#define FORKER_PROTO_START_ACK 1
+#endif
+
+#define FORKER_ARGV_NO_OF_ARGS 3
+#define FORKER_ARGV_PROGNAME_IX 0 /* Program name */
+#define FORKER_ARGV_MAX_FILES 1 /* max_files */
+
+#define FORKER_FLAG_USE_STDIO (1 << 0) /* dup the pipe to stdin/stderr */
+#define FORKER_FLAG_EXIT_STATUS (1 << 1) /* send the exit status to parent */
+#define FORKER_FLAG_DO_READ (1 << 2) /* dup write fd */
+#define FORKER_FLAG_DO_WRITE (1 << 3) /* dup read fd */
+
+#if SIZEOF_VOID_P == SIZEOF_LONG
+typedef unsigned long ErtsSysPortId;
+#elif SIZEOF_VOID_P == SIZEOF_INT
+typedef unsigned int ErtsSysPortId;
+#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG
+typedef unsigned long long ErtsSysPortId;
+#endif
+
+typedef struct ErtsSysForkerProto_ {
+ enum {
+ ErtsSysForkerProtoAction_Start,
+ ErtsSysForkerProtoAction_StartAck,
+ ErtsSysForkerProtoAction_Go,
+ ErtsSysForkerProtoAction_SigChld,
+ ErtsSysForkerProtoAction_Ack
+ } action;
+ union {
+ struct {
+ ErtsSysPortId port_id;
+ int fds[3];
+ } start;
+ struct {
+ pid_t os_pid;
+ int error_number;
+ } go;
+ struct {
+ ErtsSysPortId port_id;
+ int error_number;
+ } sigchld;
+ } u;
+} ErtsSysForkerProto;
+
+#endif /* #ifndef _ERL_UNIX_FORKER_H */
diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h
index 8d4e98bf3a..8b1822ca9f 100644
--- a/erts/emulator/sys/unix/erl_unix_sys.h
+++ b/erts/emulator/sys/unix/erl_unix_sys.h
@@ -30,9 +30,7 @@
#include <limits.h>
#include <stdlib.h>
#include <string.h>
-#ifndef QNX
#include <memory.h>
-#endif
#if defined(__sun__) && defined(__SVR4) && !defined(__EXTENSIONS__)
# define __EXTENSIONS__
@@ -92,11 +90,6 @@
#include <ieeefp.h>
#endif
-#ifdef QNX
-#include <process.h>
-#include <sys/qnx_glob.h>
-#endif
-
#include <pwd.h>
#ifndef HZ
@@ -108,6 +101,10 @@
#endif
#include <netdb.h>
+#ifdef HAVE_MACH_ABSOLUTE_TIME
+#include <mach/mach_time.h>
+#endif
+
#ifdef HAVE_POSIX_MEMALIGN
# define ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC 1
#endif
@@ -136,13 +133,6 @@
# define ERTS_POLL_NEED_ASYNC_INTERRUPT_SUPPORT
#endif
-#ifndef ENABLE_CHILD_WAITER_THREAD
-# ifdef ERTS_SMP
-# define ERTS_SMP_SCHEDULERS_NEED_TO_CHECK_CHILDREN
-void erts_check_children(void);
-# endif
-#endif
-
typedef void *GETENV_STATE;
/*
@@ -171,6 +161,7 @@ typedef long long ErtsSysHrTime;
#endif
typedef ErtsMonotonicTime ErtsSystemTime;
+typedef ErtsSysHrTime ErtsSysPerfCounter;
#define ERTS_MONOTONIC_TIME_MIN (((ErtsMonotonicTime) 1) << 63)
#define ERTS_MONOTONIC_TIME_MAX (~ERTS_MONOTONIC_TIME_MIN)
@@ -219,6 +210,7 @@ ErtsSystemTime erts_os_system_time(void);
* It may or may not be monotonic.
*/
ErtsSysHrTime erts_sys_hrtime(void);
+#define ERTS_HRTIME_UNIT (1000*1000*1000)
struct erts_sys_time_read_only_data__ {
#ifdef ERTS_OS_MONOTONIC_INLINE_FUNC_PTR_CALL__
@@ -227,6 +219,8 @@ struct erts_sys_time_read_only_data__ {
#ifdef ERTS_OS_TIMES_INLINE_FUNC_PTR_CALL__
void (*os_times)(ErtsMonotonicTime *, ErtsSystemTime *);
#endif
+ ErtsSysPerfCounter (*perf_counter)(void);
+ ErtsSysPerfCounter perf_counter_unit;
int ticks_per_sec;
};
@@ -280,7 +274,24 @@ erts_os_times(ErtsMonotonicTime *mtimep, ErtsSystemTime *stimep)
#endif /* ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT */
/*
- *
+ * Functions for getting the performance counter
+ */
+
+ERTS_GLB_INLINE ErtsSysPerfCounter erts_sys_perf_counter(void);
+#define erts_sys_perf_counter_unit() erts_sys_time_data__.r.o.perf_counter_unit
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+ERTS_GLB_INLINE ErtsSysPerfCounter
+erts_sys_perf_counter()
+{
+ return (*erts_sys_time_data__.r.o.perf_counter)();
+}
+
+#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
+
+/*
+ * Functions for measuring CPU time
*/
#if (defined(HAVE_GETHRVTIME) || defined(HAVE_CLOCK_GETTIME_CPU_TIME))
@@ -310,7 +321,6 @@ typedef void (*SIGFUNC)(int);
extern SIGFUNC sys_signal(int, SIGFUNC);
extern void sys_sigrelease(int);
extern void sys_sigblock(int);
-extern void sys_stop_cat(void);
/*
* Handling of floating point exceptions.
@@ -425,19 +435,6 @@ void erts_sys_unblock_fpe(int);
#define ERTS_FP_ERROR_THOROUGH(p, f, A) __ERTS_FP_ERROR_THOROUGH(&(p)->fp_exception, f, A)
-#ifdef NEED_CHILD_SETUP_DEFINES
-/* The child setup argv[] */
-#define CS_ARGV_PROGNAME_IX 0 /* Program name */
-#define CS_ARGV_UNBIND_IX 1 /* Unbind from cpu */
-#define CS_ARGV_WD_IX 2 /* Working directory */
-#define CS_ARGV_CMD_IX 3 /* Command */
-#define CS_ARGV_FD_CR_IX 4 /* Fd close range */
-#define CS_ARGV_DUP2_OP_IX(N) ((N) + 5) /* dup2 operations */
-
-#define CS_ARGV_NO_OF_DUP2_OPS 3 /* Number of dup2 ops */
-#define CS_ARGV_NO_OF_ARGS 8 /* Number of arguments */
-#endif /* #ifdef NEED_CHILD_SETUP_DEFINES */
-
/* Threads */
#ifdef USE_THREADS
extern int init_async(int);
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index d94b37430e..0a18e54389 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -49,7 +49,6 @@
#include <sys/ioctl.h>
#endif
-#define NEED_CHILD_SETUP_DEFINES
#define ERTS_WANT_BREAK_HANDLING
#define ERTS_WANT_GOT_SIGUSR1
#define WANT_NONBLOCKING /* must define this to pull in defs from sys.h */
@@ -67,7 +66,7 @@
#include "erl_mseg.h"
extern char **environ;
-static erts_smp_rwmtx_t environ_rwmtx;
+erts_smp_rwmtx_t environ_rwmtx;
#define MAX_VSIZE 16 /* Max number of entries allowed in an I/O
* vector sock_sendv().
@@ -76,89 +75,12 @@ static erts_smp_rwmtx_t environ_rwmtx;
* Don't need global.h, but bif_table.h (included by bif.h),
* won't compile otherwise
*/
-#include "global.h"
+#include "global.h"
#include "bif.h"
-#include "erl_sys_driver.h"
#include "erl_check_io.h"
#include "erl_cpu_topology.h"
-#ifndef DISABLE_VFORK
-#define DISABLE_VFORK 0
-#endif
-
-#if defined IOV_MAX
-#define MAXIOV IOV_MAX
-#elif defined UIO_MAXIOV
-#define MAXIOV UIO_MAXIOV
-#else
-#define MAXIOV 16
-#endif
-
-#ifdef USE_THREADS
-# ifdef ENABLE_CHILD_WAITER_THREAD
-# define CHLDWTHR ENABLE_CHILD_WAITER_THREAD
-# else
-# define CHLDWTHR 0
-# endif
-# define FDBLOCK 1
-#else
-# define CHLDWTHR 0
-# define FDBLOCK 0
-#endif
-/*
- * [OTP-3906]
- * Solaris signal management gets confused when threads are used and a
- * lot of child processes dies. The confusion results in that SIGCHLD
- * signals aren't delivered to the emulator which in turn results in
- * a lot of defunct processes in the system.
- *
- * The problem seems to appear when a signal is frequently
- * blocked/unblocked at the same time as the signal is frequently
- * propagated. The child waiter thread is a workaround for this problem.
- * The SIGCHLD signal is always blocked (in all threads), and the child
- * waiter thread fetches the signal by a call to sigwait(). See
- * child_waiter().
- */
-
-typedef struct ErtsSysReportExit_ ErtsSysReportExit;
-struct ErtsSysReportExit_ {
- ErtsSysReportExit *next;
- Eterm port;
- int pid;
- int ifd;
- int ofd;
-#if CHLDWTHR && !defined(ERTS_SMP)
- int status;
-#endif
-};
-
-/* Used by the fd driver iff the fd could not be set to non-blocking */
-typedef struct ErtsSysBlocking_ {
- ErlDrvPDL pdl;
- int res;
- int err;
- unsigned int pkey;
-} ErtsSysBlocking;
-
-
-/* This data is shared by these drivers - initialized by spawn_init() */
-static struct driver_data {
- ErlDrvPort port_num;
- int ofd, packet_bytes;
- ErtsSysReportExit *report_exit;
- int pid;
- int alive;
- int status;
- int terminating;
- ErtsSysBlocking *blocking;
-} *driver_data; /* indexed by fd */
-
-static ErtsSysReportExit *report_exit_list;
-#if CHLDWTHR && !defined(ERTS_SMP)
-static ErtsSysReportExit *report_exit_transit_list;
-#endif
-
extern int driver_interrupt(int, int);
extern void do_break(void);
@@ -170,33 +92,6 @@ extern void erts_sys_init_float(void);
extern void erl_crash_dump(char* file, int line, char* fmt, ...);
-#define DIR_SEPARATOR_CHAR '/'
-
-#if defined(__ANDROID__)
-#define SHELL "/system/bin/sh"
-#else
-#define SHELL "/bin/sh"
-#endif /* __ANDROID__ */
-
-
-#if defined(DEBUG)
-#define ERL_BUILD_TYPE_MARKER ".debug"
-#elif defined(PURIFY)
-#define ERL_BUILD_TYPE_MARKER ".purify"
-#elif defined(QUANTIFY)
-#define ERL_BUILD_TYPE_MARKER ".quantify"
-#elif defined(PURECOV)
-#define ERL_BUILD_TYPE_MARKER ".purecov"
-#elif defined(VALGRIND)
-#define ERL_BUILD_TYPE_MARKER ".valgrind"
-#else /* opt */
-#define ERL_BUILD_TYPE_MARKER
-#endif
-
-#define CHILD_SETUP_PROG_NAME "child_setup" ERL_BUILD_TYPE_MARKER
-#if !DISABLE_VFORK
-static char *child_setup_prog;
-#endif
#ifdef DEBUG
static int debug_log = 0;
@@ -220,7 +115,7 @@ static volatile int have_prepared_crash_dump;
(have_prepared_crash_dump++)
#endif
-static erts_smp_atomic_t sys_misc_mem_sz;
+erts_smp_atomic_t sys_misc_mem_sz;
#if defined(ERTS_SMP)
static void smp_sig_notify(char c);
@@ -233,46 +128,6 @@ static int sig_suspend_fds[2] = {-1, -1};
jmp_buf erts_sys_sigsegv_jmp;
-#if CHLDWTHR || defined(ERTS_SMP)
-erts_mtx_t chld_stat_mtx;
-#endif
-#if CHLDWTHR
-static erts_tid_t child_waiter_tid;
-/* chld_stat_mtx is used to protect against concurrent accesses
- of the driver_data fields pid, alive, and status. */
-erts_cnd_t chld_stat_cnd;
-static long children_alive;
-#define CHLD_STAT_LOCK erts_mtx_lock(&chld_stat_mtx)
-#define CHLD_STAT_UNLOCK erts_mtx_unlock(&chld_stat_mtx)
-#define CHLD_STAT_WAIT erts_cnd_wait(&chld_stat_cnd, &chld_stat_mtx)
-#define CHLD_STAT_SIGNAL erts_cnd_signal(&chld_stat_cnd)
-#elif defined(ERTS_SMP) /* ------------------------------------------------- */
-#define CHLD_STAT_LOCK erts_mtx_lock(&chld_stat_mtx)
-#define CHLD_STAT_UNLOCK erts_mtx_unlock(&chld_stat_mtx)
-
-#else /* ------------------------------------------------------------------- */
-#define CHLD_STAT_LOCK
-#define CHLD_STAT_UNLOCK
-static volatile int children_died;
-#endif
-
-
-static struct fd_data {
- char pbuf[4]; /* hold partial packet bytes */
- int psz; /* size of pbuf */
- char *buf;
- char *cpos;
- int sz;
- int remain; /* for input on fd */
-} *fd_data; /* indexed by fd */
-
-/* static FUNCTION(int, write_fill, (int, char*, int)); unused? */
-static void note_child_death(int, int);
-
-#if CHLDWTHR
-static void* child_waiter(void *);
-#endif
-
static int crashdump_companion_cube_fd = -1;
/********************* General functions ****************************/
@@ -453,9 +308,10 @@ MALLOC_USE_HASH(1);
#ifdef USE_THREADS
#ifdef ERTS_THR_HAVE_SIG_FUNCS
+
/*
* Child thread inherits parents signal mask at creation. In order to
- * guarantee that the main thread will receive all SIGINT, SIGCHLD, and
+ * guarantee that the main thread will receive all SIGINT, and
* SIGUSR1 signals sent to the process, we block these signals in the
* parent thread when creating a new thread.
*/
@@ -551,14 +407,11 @@ erts_sys_pre_init(void)
#ifdef ERTS_THR_HAVE_SIG_FUNCS
sigemptyset(&thr_create_sigmask);
sigaddset(&thr_create_sigmask, SIGINT); /* block interrupt */
- sigaddset(&thr_create_sigmask, SIGCHLD); /* block child signals */
sigaddset(&thr_create_sigmask, SIGUSR1); /* block user defined signal */
#endif
erts_thr_init(&eid);
- report_exit_list = NULL;
-
#ifdef ERTS_ENABLE_LOCK_COUNT
erts_lcnt_init();
#endif
@@ -569,17 +422,6 @@ erts_sys_pre_init(void)
#ifdef USE_THREADS
-#if CHLDWTHR || defined(ERTS_SMP)
- erts_mtx_init(&chld_stat_mtx, "child_status");
-#endif
-#if CHLDWTHR
-#ifndef ERTS_SMP
- report_exit_transit_list = NULL;
-#endif
- erts_cnd_init(&chld_stat_cnd);
- children_alive = 0;
-#endif
-
#ifdef ERTS_SMP
erts_smp_atomic32_init_nob(&erts_break_requested, 0);
erts_smp_atomic32_init_nob(&erts_got_sigusr1, 0);
@@ -589,9 +431,6 @@ erts_sys_pre_init(void)
erts_got_sigusr1 = 0;
have_prepared_crash_dump = 0;
#endif
-#if !CHLDWTHR && !defined(ERTS_SMP)
- children_died = 0;
-#endif
#endif /* USE_THREADS */
@@ -628,39 +467,6 @@ erts_sys_pre_init(void)
void
erl_sys_init(void)
{
-#if !DISABLE_VFORK
- {
- int res;
- char bindir[MAXPATHLEN];
- size_t bindirsz = sizeof(bindir);
- Uint csp_path_sz;
-
- res = erts_sys_getenv_raw("BINDIR", bindir, &bindirsz);
- if (res != 0) {
- if (res < 0)
- erts_exit(1,
- "Environment variable BINDIR is not set\n");
- if (res > 0)
- erts_exit(1,
- "Value of environment variable BINDIR is too large\n");
- }
- if (bindir[0] != DIR_SEPARATOR_CHAR)
- erts_exit(1,
- "Environment variable BINDIR does not contain an"
- " absolute path\n");
- csp_path_sz = (strlen(bindir)
- + 1 /* DIR_SEPARATOR_CHAR */
- + sizeof(CHILD_SETUP_PROG_NAME)
- + 1);
- child_setup_prog = erts_alloc(ERTS_ALC_T_CS_PROG_PATH, csp_path_sz);
- erts_smp_atomic_add_nob(&sys_misc_mem_sz, csp_path_sz);
- erts_snprintf(child_setup_prog, csp_path_sz,
- "%s%c%s",
- bindir,
- DIR_SEPARATOR_CHAR,
- CHILD_SETUP_PROG_NAME);
- }
-#endif
#ifdef USE_SETLINEBUF
setlinebuf(stdout);
@@ -978,43 +784,6 @@ int sys_max_files(void)
return(max_files);
}
-static void block_signals(void)
-{
-#if !CHLDWTHR
- sys_sigblock(SIGCHLD);
-#endif
-#ifndef ERTS_SMP
- sys_sigblock(SIGINT);
-#ifndef ETHR_UNUSABLE_SIGUSRX
- sys_sigblock(SIGUSR1);
-#endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */
-#endif /* #ifndef ERTS_SMP */
-
-#if defined(ERTS_SMP) && !defined(ETHR_UNUSABLE_SIGUSRX)
- sys_sigblock(ERTS_SYS_SUSPEND_SIGNAL);
-#endif
-
-}
-
-static void unblock_signals(void)
-{
- /* Update erl_child_setup.c if changed */
-#if !CHLDWTHR
- sys_sigrelease(SIGCHLD);
-#endif
-#ifndef ERTS_SMP
- sys_sigrelease(SIGINT);
-#ifndef ETHR_UNUSABLE_SIGUSRX
- sys_sigrelease(SIGUSR1);
-#endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */
-#endif /* #ifndef ERTS_SMP */
-
-#if defined(ERTS_SMP) && !defined(ETHR_UNUSABLE_SIGUSRX)
- sys_sigrelease(ERTS_SYS_SUSPEND_SIGNAL);
-#endif
-
-}
-
/************************** OS info *******************************/
/* Used by erlang:info/1. */
@@ -1102,1502 +871,6 @@ void fini_getenv_state(GETENV_STATE *state)
erts_smp_rwmtx_runlock(&environ_rwmtx);
}
-
-/************************** Port I/O *******************************/
-
-
-
-/* I. Common stuff */
-
-/*
- * Decreasing the size of it below 16384 is not allowed.
- */
-
-/* II. The spawn/fd/vanilla drivers */
-
-#define ERTS_SYS_READ_BUF_SZ (64*1024)
-
-/* Driver interfaces */
-static ErlDrvData spawn_start(ErlDrvPort, char*, SysDriverOpts*);
-static ErlDrvData fd_start(ErlDrvPort, char*, SysDriverOpts*);
-#if FDBLOCK
-static void fd_async(void *);
-static void fd_ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data);
-#endif
-static ErlDrvSSizeT fd_control(ErlDrvData, unsigned int, char *, ErlDrvSizeT,
- char **, ErlDrvSizeT);
-static ErlDrvData vanilla_start(ErlDrvPort, char*, SysDriverOpts*);
-static int spawn_init(void);
-static void fd_stop(ErlDrvData);
-static void fd_flush(ErlDrvData);
-static void stop(ErlDrvData);
-static void ready_input(ErlDrvData, ErlDrvEvent);
-static void ready_output(ErlDrvData, ErlDrvEvent);
-static void output(ErlDrvData, char*, ErlDrvSizeT);
-static void outputv(ErlDrvData, ErlIOVec*);
-static void stop_select(ErlDrvEvent, void*);
-
-struct erl_drv_entry spawn_driver_entry = {
- spawn_init,
- spawn_start,
- stop,
- output,
- ready_input,
- ready_output,
- "spawn",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- ERL_DRV_EXTENDED_MARKER,
- ERL_DRV_EXTENDED_MAJOR_VERSION,
- ERL_DRV_EXTENDED_MINOR_VERSION,
- ERL_DRV_FLAG_USE_PORT_LOCKING,
- NULL, NULL,
- stop_select
-};
-struct erl_drv_entry fd_driver_entry = {
- NULL,
- fd_start,
- fd_stop,
- output,
- ready_input,
- ready_output,
- "fd",
- NULL,
- NULL,
- fd_control,
- NULL,
- outputv,
-#if FDBLOCK
- fd_ready_async, /* ready_async */
-#else
- NULL,
-#endif
- fd_flush, /* flush */
- NULL, /* call */
- NULL, /* event */
- ERL_DRV_EXTENDED_MARKER,
- ERL_DRV_EXTENDED_MAJOR_VERSION,
- ERL_DRV_EXTENDED_MINOR_VERSION,
- 0, /* ERL_DRV_FLAGs */
- NULL, /* handle2 */
- NULL, /* process_exit */
- stop_select
-};
-struct erl_drv_entry vanilla_driver_entry = {
- NULL,
- vanilla_start,
- stop,
- output,
- ready_input,
- ready_output,
- "vanilla",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL, /* flush */
- NULL, /* call */
- NULL, /* event */
- ERL_DRV_EXTENDED_MARKER,
- ERL_DRV_EXTENDED_MAJOR_VERSION,
- ERL_DRV_EXTENDED_MINOR_VERSION,
- 0, /* ERL_DRV_FLAGs */
- NULL, /* handle2 */
- NULL, /* process_exit */
- stop_select
-};
-
-/* Handle SIGCHLD signals. */
-#if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
-static RETSIGTYPE onchld(void)
-#else
-static RETSIGTYPE onchld(int signum)
-#endif
-{
-#if CHLDWTHR
- ASSERT(0); /* We should *never* catch a SIGCHLD signal */
-#elif defined(ERTS_SMP)
- smp_sig_notify('C');
-#else
- children_died = 1;
- ERTS_CHK_IO_AS_INTR(); /* Make sure we don't sleep in poll */
-#endif
-}
-
-static int set_blocking_data(struct driver_data *dd) {
-
- dd->blocking = erts_alloc(ERTS_ALC_T_SYS_BLOCKING, sizeof(ErtsSysBlocking));
-
- erts_smp_atomic_add_nob(&sys_misc_mem_sz, sizeof(ErtsSysBlocking));
-
- dd->blocking->pdl = driver_pdl_create(dd->port_num);
- dd->blocking->res = 0;
- dd->blocking->err = 0;
- dd->blocking->pkey = driver_async_port_key(dd->port_num);
-
- return 1;
-}
-
-static int set_driver_data(ErlDrvPort port_num,
- int ifd,
- int ofd,
- int packet_bytes,
- int read_write,
- int exit_status,
- int pid,
- int is_blocking)
-{
- Port *prt;
- ErtsSysReportExit *report_exit;
-
- if (!exit_status)
- report_exit = NULL;
- else {
- report_exit = erts_alloc(ERTS_ALC_T_PRT_REP_EXIT,
- sizeof(ErtsSysReportExit));
- report_exit->next = report_exit_list;
- report_exit->port = erts_drvport2id(port_num);
- report_exit->pid = pid;
- report_exit->ifd = read_write & DO_READ ? ifd : -1;
- report_exit->ofd = read_write & DO_WRITE ? ofd : -1;
-#if CHLDWTHR && !defined(ERTS_SMP)
- report_exit->status = 0;
-#endif
- report_exit_list = report_exit;
- }
-
- prt = erts_drvport2port(port_num);
- if (prt != ERTS_INVALID_ERL_DRV_PORT)
- prt->os_pid = pid;
-
- if (read_write & DO_READ) {
- driver_data[ifd].packet_bytes = packet_bytes;
- driver_data[ifd].port_num = port_num;
- driver_data[ifd].report_exit = report_exit;
- driver_data[ifd].pid = pid;
- driver_data[ifd].alive = 1;
- driver_data[ifd].status = 0;
- driver_data[ifd].terminating = 0;
- driver_data[ifd].blocking = NULL;
- if (read_write & DO_WRITE) {
- driver_data[ifd].ofd = ofd;
- if (is_blocking && FDBLOCK)
- if (!set_blocking_data(driver_data+ifd))
- return -1;
- if (ifd != ofd)
- driver_data[ofd] = driver_data[ifd]; /* structure copy */
- } else { /* DO_READ only */
- driver_data[ifd].ofd = -1;
- }
- (void) driver_select(port_num, ifd, (ERL_DRV_READ|ERL_DRV_USE), 1);
- return(ifd);
- } else { /* DO_WRITE only */
- driver_data[ofd].packet_bytes = packet_bytes;
- driver_data[ofd].port_num = port_num;
- driver_data[ofd].report_exit = report_exit;
- driver_data[ofd].ofd = ofd;
- driver_data[ofd].pid = pid;
- driver_data[ofd].alive = 1;
- driver_data[ofd].status = 0;
- driver_data[ofd].terminating = 0;
- driver_data[ofd].blocking = NULL;
- if (is_blocking && FDBLOCK)
- if (!set_blocking_data(driver_data+ofd))
- return -1;
- return(ofd);
- }
-}
-
-static int spawn_init()
-{
- int i;
-#if CHLDWTHR
- erts_thr_opts_t thr_opts = ERTS_THR_OPTS_DEFAULT_INITER;
-
- thr_opts.detached = 0;
- thr_opts.suggested_stack_size = 0; /* Smallest possible */
- thr_opts.name = "child_waiter";
-#endif
-
- sys_signal(SIGPIPE, SIG_IGN); /* Ignore - we'll handle the write failure */
- driver_data = (struct driver_data *)
- erts_alloc(ERTS_ALC_T_DRV_TAB, max_files * sizeof(struct driver_data));
- erts_smp_atomic_add_nob(&sys_misc_mem_sz,
- max_files * sizeof(struct driver_data));
-
- for (i = 0; i < max_files; i++)
- driver_data[i].pid = -1;
-
-#if CHLDWTHR
- sys_sigblock(SIGCHLD);
-#endif
-
- sys_signal(SIGCHLD, onchld); /* Reap children */
-
-#if CHLDWTHR
- erts_thr_create(&child_waiter_tid, child_waiter, NULL, &thr_opts);
-#endif
-
- return 1;
-}
-
-static void close_pipes(int ifd[2], int ofd[2], int read_write)
-{
- if (read_write & DO_READ) {
- (void) close(ifd[0]);
- (void) close(ifd[1]);
- }
- if (read_write & DO_WRITE) {
- (void) close(ofd[0]);
- (void) close(ofd[1]);
- }
-}
-
-static void init_fd_data(int fd, ErlDrvPort port_num)
-{
- fd_data[fd].buf = NULL;
- fd_data[fd].cpos = NULL;
- fd_data[fd].remain = 0;
- fd_data[fd].sz = 0;
- fd_data[fd].psz = 0;
-}
-
-static char **build_unix_environment(char *block)
-{
- int i;
- int j;
- int len;
- char *cp;
- char **cpp;
- char** old_env;
-
- ERTS_SMP_LC_ASSERT(erts_smp_lc_rwmtx_is_rlocked(&environ_rwmtx));
-
- cp = block;
- len = 0;
- while (*cp != '\0') {
- cp += strlen(cp) + 1;
- len++;
- }
- old_env = environ;
- while (*old_env++ != NULL) {
- len++;
- }
-
- cpp = (char **) erts_alloc_fnf(ERTS_ALC_T_ENVIRONMENT,
- sizeof(char *) * (len+1));
- if (cpp == NULL) {
- return NULL;
- }
-
- cp = block;
- len = 0;
- while (*cp != '\0') {
- cpp[len] = cp;
- cp += strlen(cp) + 1;
- len++;
- }
-
- i = len;
- for (old_env = environ; *old_env; old_env++) {
- char* old = *old_env;
-
- for (j = 0; j < len; j++) {
- char *s, *t;
-
- s = cpp[j];
- t = old;
- while (*s == *t && *s != '=') {
- s++, t++;
- }
- if (*s == '=' && *t == '=') {
- break;
- }
- }
-
- if (j == len) { /* New version not found */
- cpp[len++] = old;
- }
- }
-
- for (j = 0; j < i; ) {
- size_t last = strlen(cpp[j])-1;
- if (cpp[j][last] == '=' && strchr(cpp[j], '=') == cpp[j]+last) {
- cpp[j] = cpp[--len];
- if (len < i) {
- i--;
- } else {
- j++;
- }
- }
- else {
- j++;
- }
- }
-
- cpp[len] = NULL;
- return cpp;
-}
-
-/*
- [arndt] In most Unix systems, including Solaris 2.5, 'fork' allocates memory
- in swap space for the child of a 'fork', whereas 'vfork' does not do this.
- The natural call to use here is therefore 'vfork'. Due to a bug in
- 'vfork' in Solaris 2.5 (apparently fixed in 2.6), using 'vfork'
- can be dangerous in what seems to be these circumstances:
- If the child code under a vfork sets the signal action to SIG_DFL
- (or SIG_IGN)
- for any signal which was previously set to a signal handler, the
- state of the parent is clobbered, so that the later arrival of
- such a signal yields a sigsegv in the parent. If the signal was
- not set to a signal handler, but ignored, all seems to work.
- If you change the forking code below, beware of this.
- */
-
-static ErlDrvData spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
-{
-#define CMD_LINE_PREFIX_STR "exec "
-#define CMD_LINE_PREFIX_STR_SZ (sizeof(CMD_LINE_PREFIX_STR) - 1)
-
- int ifd[2], ofd[2], len, pid, i;
- char **volatile new_environ; /* volatile since a vfork() then cannot
- cause 'new_environ' to be clobbered
- in the parent process. */
- int saved_errno;
- long res;
- char *cmd_line;
-#ifndef QNX
- int unbind;
-#endif
-#if !DISABLE_VFORK
- int no_vfork;
- size_t no_vfork_sz = sizeof(no_vfork);
-
- no_vfork = (erts_sys_getenv_raw("ERL_NO_VFORK",
- (char *) &no_vfork,
- &no_vfork_sz) >= 0);
-#endif
-
- switch (opts->read_write) {
- case DO_READ:
- if (pipe(ifd) < 0)
- return ERL_DRV_ERROR_ERRNO;
- if (ifd[0] >= max_files) {
- close_pipes(ifd, ofd, opts->read_write);
- errno = EMFILE;
- return ERL_DRV_ERROR_ERRNO;
- }
- ofd[1] = -1; /* keep purify happy */
- break;
- case DO_WRITE:
- if (pipe(ofd) < 0) return ERL_DRV_ERROR_ERRNO;
- if (ofd[1] >= max_files) {
- close_pipes(ifd, ofd, opts->read_write);
- errno = EMFILE;
- return ERL_DRV_ERROR_ERRNO;
- }
- ifd[0] = -1; /* keep purify happy */
- break;
- case DO_READ|DO_WRITE:
- if (pipe(ifd) < 0) return ERL_DRV_ERROR_ERRNO;
- errno = EMFILE; /* default for next two conditions */
- if (ifd[0] >= max_files || pipe(ofd) < 0) {
- close_pipes(ifd, ofd, DO_READ);
- return ERL_DRV_ERROR_ERRNO;
- }
- if (ofd[1] >= max_files) {
- close_pipes(ifd, ofd, opts->read_write);
- errno = EMFILE;
- return ERL_DRV_ERROR_ERRNO;
- }
- break;
- default:
- ASSERT(0);
- return ERL_DRV_ERROR_GENERAL;
- }
-
- if (opts->spawn_type == ERTS_SPAWN_EXECUTABLE) {
- /* started with spawn_executable, not with spawn */
- len = strlen(name);
- cmd_line = (char *) erts_alloc_fnf(ERTS_ALC_T_TMP, len + 1);
- if (!cmd_line) {
- close_pipes(ifd, ofd, opts->read_write);
- errno = ENOMEM;
- return ERL_DRV_ERROR_ERRNO;
- }
- memcpy((void *) cmd_line,(void *) name, len);
- cmd_line[len] = '\0';
- if (access(cmd_line,X_OK) != 0) {
- int save_errno = errno;
- erts_free(ERTS_ALC_T_TMP, cmd_line);
- errno = save_errno;
- return ERL_DRV_ERROR_ERRNO;
- }
- } else {
- /* make the string suitable for giving to "sh" */
- len = strlen(name);
- cmd_line = (char *) erts_alloc_fnf(ERTS_ALC_T_TMP,
- CMD_LINE_PREFIX_STR_SZ + len + 1);
- if (!cmd_line) {
- close_pipes(ifd, ofd, opts->read_write);
- errno = ENOMEM;
- return ERL_DRV_ERROR_ERRNO;
- }
- memcpy((void *) cmd_line,
- (void *) CMD_LINE_PREFIX_STR,
- CMD_LINE_PREFIX_STR_SZ);
- memcpy((void *) (cmd_line + CMD_LINE_PREFIX_STR_SZ), (void *) name, len);
- cmd_line[CMD_LINE_PREFIX_STR_SZ + len] = '\0';
- }
-
- erts_smp_rwmtx_rlock(&environ_rwmtx);
-
- if (opts->envir == NULL) {
- new_environ = environ;
- } else if ((new_environ = build_unix_environment(opts->envir)) == NULL) {
- erts_smp_rwmtx_runlock(&environ_rwmtx);
- erts_free(ERTS_ALC_T_TMP, (void *) cmd_line);
- errno = ENOMEM;
- return ERL_DRV_ERROR_ERRNO;
- }
-
-#ifndef QNX
- /* Block child from SIGINT and SIGUSR1. Must be before fork()
- to be safe. */
- block_signals();
-
- CHLD_STAT_LOCK;
-
- unbind = erts_sched_bind_atfork_prepare();
-
-#if !DISABLE_VFORK
- /* See fork/vfork discussion before this function. */
- if (no_vfork) {
-#endif
-
- DEBUGF(("Using fork\n"));
- pid = fork();
-
- if (pid == 0) {
- /* The child! Setup child... */
-
- if (erts_sched_bind_atfork_child(unbind) != 0)
- goto child_error;
-
- /* OBSERVE!
- * Keep child setup after vfork() (implemented below and in
- * erl_child_setup.c) up to date if changes are made here.
- */
-
- if (opts->use_stdio) {
- if (opts->read_write & DO_READ) {
- /* stdout for process */
- if (dup2(ifd[1], 1) < 0)
- goto child_error;
- if(opts->redir_stderr)
- /* stderr for process */
- if (dup2(ifd[1], 2) < 0)
- goto child_error;
- }
- if (opts->read_write & DO_WRITE)
- /* stdin for process */
- if (dup2(ofd[0], 0) < 0)
- goto child_error;
- }
- else { /* XXX will fail if ofd[0] == 4 (unlikely..) */
- if (opts->read_write & DO_READ)
- if (dup2(ifd[1], 4) < 0)
- goto child_error;
- if (opts->read_write & DO_WRITE)
- if (dup2(ofd[0], 3) < 0)
- goto child_error;
- }
-
-#if defined(HAVE_CLOSEFROM)
- closefrom(opts->use_stdio ? 3 : 5);
-#else
- for (i = opts->use_stdio ? 3 : 5; i < max_files; i++)
- (void) close(i);
-#endif
-
- if (opts->wd && chdir(opts->wd) < 0)
- goto child_error;
-
-#if defined(USE_SETPGRP_NOARGS) /* SysV */
- (void) setpgrp();
-#elif defined(USE_SETPGRP) /* BSD */
- (void) setpgrp(0, getpid());
-#else /* POSIX */
- (void) setsid();
-#endif
-
- unblock_signals();
-
- if (opts->spawn_type == ERTS_SPAWN_EXECUTABLE) {
- if (opts->argv == NULL) {
- execle(cmd_line,cmd_line,(char *) NULL, new_environ);
- } else {
- if (opts->argv[0] == erts_default_arg0) {
- opts->argv[0] = cmd_line;
- }
- execve(cmd_line, opts->argv, new_environ);
- if (opts->argv[0] == cmd_line) {
- opts->argv[0] = erts_default_arg0;
- }
- }
- } else {
- execle(SHELL, "sh", "-c", cmd_line, (char *) NULL, new_environ);
- }
- child_error:
- _exit(1);
- }
-#if !DISABLE_VFORK
- }
-#define ENOUGH_BYTES (44)
- else { /* Use vfork() */
- char **cs_argv= erts_alloc(ERTS_ALC_T_TMP,(CS_ARGV_NO_OF_ARGS + 1)*
- sizeof(char *));
- char fd_close_range[ENOUGH_BYTES]; /* 44 bytes are enough to */
- char dup2_op[CS_ARGV_NO_OF_DUP2_OPS][ENOUGH_BYTES]; /* hold any "%d:%d" string */
- /* on a 64-bit machine. */
-
- /* Setup argv[] for the child setup program (implemented in
- erl_child_setup.c) */
- i = 0;
- if (opts->use_stdio) {
- if (opts->read_write & DO_READ){
- /* stdout for process */
- erts_snprintf(&dup2_op[i++][0], ENOUGH_BYTES, "%d:%d", ifd[1], 1);
- if(opts->redir_stderr)
- /* stderr for process */
- erts_snprintf(&dup2_op[i++][0], ENOUGH_BYTES, "%d:%d", ifd[1], 2);
- }
- if (opts->read_write & DO_WRITE)
- /* stdin for process */
- erts_snprintf(&dup2_op[i++][0], ENOUGH_BYTES, "%d:%d", ofd[0], 0);
- } else { /* XXX will fail if ofd[0] == 4 (unlikely..) */
- if (opts->read_write & DO_READ)
- erts_snprintf(&dup2_op[i++][0], ENOUGH_BYTES, "%d:%d", ifd[1], 4);
- if (opts->read_write & DO_WRITE)
- erts_snprintf(&dup2_op[i++][0], ENOUGH_BYTES, "%d:%d", ofd[0], 3);
- }
- for (; i < CS_ARGV_NO_OF_DUP2_OPS; i++)
- strcpy(&dup2_op[i][0], "-");
- erts_snprintf(fd_close_range, ENOUGH_BYTES, "%d:%d", opts->use_stdio ? 3 : 5, max_files-1);
-
- cs_argv[CS_ARGV_PROGNAME_IX] = child_setup_prog;
- cs_argv[CS_ARGV_WD_IX] = opts->wd ? opts->wd : ".";
- cs_argv[CS_ARGV_UNBIND_IX] = erts_sched_bind_atvfork_child(unbind);
- cs_argv[CS_ARGV_FD_CR_IX] = fd_close_range;
- for (i = 0; i < CS_ARGV_NO_OF_DUP2_OPS; i++)
- cs_argv[CS_ARGV_DUP2_OP_IX(i)] = &dup2_op[i][0];
-
- if (opts->spawn_type == ERTS_SPAWN_EXECUTABLE) {
- int num = 0;
- int j = 0;
- if (opts->argv != NULL) {
- for(; opts->argv[num] != NULL; ++num)
- ;
- }
- cs_argv = erts_realloc(ERTS_ALC_T_TMP,cs_argv, (CS_ARGV_NO_OF_ARGS + 1 + num + 1) * sizeof(char *));
- cs_argv[CS_ARGV_CMD_IX] = "-";
- cs_argv[CS_ARGV_NO_OF_ARGS] = cmd_line;
- if (opts->argv != NULL) {
- for (;opts->argv[j] != NULL; ++j) {
- if (opts->argv[j] == erts_default_arg0) {
- cs_argv[CS_ARGV_NO_OF_ARGS + 1 + j] = cmd_line;
- } else {
- cs_argv[CS_ARGV_NO_OF_ARGS + 1 + j] = opts->argv[j];
- }
- }
- }
- cs_argv[CS_ARGV_NO_OF_ARGS + 1 + j] = NULL;
- } else {
- cs_argv[CS_ARGV_CMD_IX] = cmd_line; /* Command */
- cs_argv[CS_ARGV_NO_OF_ARGS] = NULL;
- }
- DEBUGF(("Using vfork\n"));
- pid = vfork();
-
- if (pid == 0) {
- /* The child! */
-
- /* Observe!
- * OTP-4389: The child setup program (implemented in
- * erl_child_setup.c) will perform the necessary setup of the
- * child before it execs to the user program. This because
- * vfork() only allow an *immediate* execve() or _exit() in the
- * child.
- */
- execve(child_setup_prog, cs_argv, new_environ);
- _exit(1);
- }
- erts_free(ERTS_ALC_T_TMP,cs_argv);
- }
-#undef ENOUGH_BYTES
-#endif
-
- erts_sched_bind_atfork_parent(unbind);
-
- if (pid == -1) {
- saved_errno = errno;
- CHLD_STAT_UNLOCK;
- erts_smp_rwmtx_runlock(&environ_rwmtx);
- erts_free(ERTS_ALC_T_TMP, (void *) cmd_line);
- unblock_signals();
- close_pipes(ifd, ofd, opts->read_write);
- errno = saved_errno;
- return ERL_DRV_ERROR_ERRNO;
- }
-#else /* QNX */
- if (opts->use_stdio) {
- if (opts->read_write & DO_READ)
- qnx_spawn_options.iov[1] = ifd[1]; /* stdout for process */
- if (opts->read_write & DO_WRITE)
- qnx_spawn_options.iov[0] = ofd[0]; /* stdin for process */
- }
- else {
- if (opts->read_write & DO_READ)
- qnx_spawn_options.iov[4] = ifd[1];
- if (opts->read_write & DO_WRITE)
- qnx_spawn_options.iov[3] = ofd[0];
- }
- /* Close fds on exec */
- for (i = 3; i < max_files; i++)
- fcntl(i, F_SETFD, 1);
-
- qnx_spawn_options.flags = _SPAWN_SETSID;
- if ((pid = spawnl(P_NOWAIT, SHELL, SHELL, "-c", cmd_line,
- (char *) 0)) < 0) {
- erts_free(ERTS_ALC_T_TMP, (void *) cmd_line);
- reset_qnx_spawn();
- erts_smp_rwmtx_runlock(&environ_rwmtx);
- close_pipes(ifd, ofd, opts->read_write);
- return ERL_DRV_ERROR_GENERAL;
- }
- reset_qnx_spawn();
-#endif /* QNX */
-
- erts_free(ERTS_ALC_T_TMP, (void *) cmd_line);
-
- if (new_environ != environ)
- erts_free(ERTS_ALC_T_ENVIRONMENT, (void *) new_environ);
-
- if (opts->read_write & DO_READ)
- (void) close(ifd[1]);
- if (opts->read_write & DO_WRITE)
- (void) close(ofd[0]);
-
- if (opts->read_write & DO_READ) {
- SET_NONBLOCKING(ifd[0]);
- init_fd_data(ifd[0], port_num);
- }
- if (opts->read_write & DO_WRITE) {
- SET_NONBLOCKING(ofd[1]);
- init_fd_data(ofd[1], port_num);
- }
-
- res = set_driver_data(port_num, ifd[0], ofd[1], opts->packet_bytes,
- opts->read_write, opts->exit_status, pid, 0);
- /* Don't unblock SIGCHLD until now, since the call above must
- first complete putting away the info about our new subprocess. */
- unblock_signals();
-
-#if CHLDWTHR
- ASSERT(children_alive >= 0);
-
- if (!(children_alive++))
- CHLD_STAT_SIGNAL; /* Wake up child waiter thread if no children
- was alive before we fork()ed ... */
-#endif
- /* Don't unlock chld_stat_mtx until now of the same reason as above */
- CHLD_STAT_UNLOCK;
-
- erts_smp_rwmtx_runlock(&environ_rwmtx);
-
- return (ErlDrvData)res;
-#undef CMD_LINE_PREFIX_STR
-#undef CMD_LINE_PREFIX_STR_SZ
-}
-
-#ifdef QNX
-static reset_qnx_spawn()
-{
- int i;
-
- /* Reset qnx_spawn_options */
- qnx_spawn_options.flags = 0;
- qnx_spawn_options.iov[0] = 0xff;
- qnx_spawn_options.iov[1] = 0xff;
- qnx_spawn_options.iov[2] = 0xff;
- qnx_spawn_options.iov[3] = 0xff;
-}
-#endif
-
-#define FD_DEF_HEIGHT 24
-#define FD_DEF_WIDTH 80
-/* Control op */
-#define FD_CTRL_OP_GET_WINSIZE 100
-
-static int fd_get_window_size(int fd, Uint32 *width, Uint32 *height)
-{
-#ifdef TIOCGWINSZ
- struct winsize ws;
- if (ioctl(fd,TIOCGWINSZ,&ws) == 0) {
- *width = (Uint32) ws.ws_col;
- *height = (Uint32) ws.ws_row;
- return 0;
- }
-#endif
- return -1;
-}
-
-static ErlDrvSSizeT fd_control(ErlDrvData drv_data,
- unsigned int command,
- char *buf, ErlDrvSizeT len,
- char **rbuf, ErlDrvSizeT rlen)
-{
- int fd = (int)(long)drv_data;
- char resbuff[2*sizeof(Uint32)];
- switch (command) {
- case FD_CTRL_OP_GET_WINSIZE:
- {
- Uint32 w,h;
- if (fd_get_window_size(fd,&w,&h))
- return 0;
- memcpy(resbuff,&w,sizeof(Uint32));
- memcpy(resbuff+sizeof(Uint32),&h,sizeof(Uint32));
- }
- break;
- default:
- return 0;
- }
- if (rlen < 2*sizeof(Uint32)) {
- *rbuf = driver_alloc(2*sizeof(Uint32));
- }
- memcpy(*rbuf,resbuff,2*sizeof(Uint32));
- return 2*sizeof(Uint32);
-}
-
-static ErlDrvData fd_start(ErlDrvPort port_num, char* name,
- SysDriverOpts* opts)
-{
- ErlDrvData res;
- int non_blocking = 0;
-
- if (((opts->read_write & DO_READ) && opts->ifd >= max_files) ||
- ((opts->read_write & DO_WRITE) && opts->ofd >= max_files))
- return ERL_DRV_ERROR_GENERAL;
-
- /*
- * Historical:
- *
- * "Note about nonblocking I/O.
- *
- * At least on Solaris, setting the write end of a TTY to nonblocking,
- * will set the input end to nonblocking as well (and vice-versa).
- * If erl is run in a pipeline like this: cat | erl
- * the input end of the TTY will be the standard input of cat.
- * And cat is not prepared to handle nonblocking I/O."
- *
- * Actually, the reason for this is not that the tty itself gets set
- * in non-blocking mode, but that the "input end" (cat's stdin) and
- * the "output end" (erlang's stdout) are typically the "same" file
- * descriptor, dup()'ed from a single fd by one of this process'
- * ancestors.
- *
- * The workaround for this problem used to be a rather bad kludge,
- * interposing an extra process ("internal cat") between erlang's
- * stdout and the original stdout, allowing erlang to set its stdout
- * in non-blocking mode without affecting the stdin of the preceding
- * process in the pipeline - and being a kludge, it caused all kinds
- * of weird problems.
- *
- * So, this is the current logic:
- *
- * The only reason to set non-blocking mode on the output fd at all is
- * if it's something that can cause a write() to block, of course,
- * i.e. primarily if it points to a tty, socket, pipe, or fifo.
- *
- * If we don't set non-blocking mode when we "should" have, and output
- * becomes blocked, the entire runtime system will be suspended - this
- * is normally bad of course, and can happen fairly "easily" - e.g. user
- * hits ^S on tty - but doesn't necessarily happen.
- *
- * If we do set non-blocking mode when we "shouldn't" have, the runtime
- * system will end up seeing EOF on the input fd (due to the preceding
- * process dying), which typically will cause the entire runtime system
- * to terminate immediately (due to whatever erlang process is seeing
- * the EOF taking it as a signal to halt the system). This is *very* bad.
- *
- * I.e. we should take a conservative approach, and only set non-
- * blocking mode when we a) need to, and b) are reasonably certain
- * that it won't be a problem. And as in the example above, the problem
- * occurs when input fd and output fd point to different "things".
- *
- * However, determining that they are not just the same "type" of
- * "thing", but actually the same instance of that type of thing, is
- * unreasonably complex in many/most cases.
- *
- * Also, with pipes, sockets, and fifos it's far from obvious that the
- * user *wants* non-blocking output: If you're running erlang inside
- * some complex pipeline, you're probably not running a real-time system
- * that must never stop, but rather *want* it to suspend if the output
- * channel is "full".
- *
- * So, the bottom line: We will only set the output fd non-blocking if
- * it points to a tty, and either a) the input fd also points to a tty,
- * or b) we can make sure that setting the output fd non-blocking
- * doesn't interfere with someone else's input, via a somewhat milder
- * kludge than the above.
- *
- * Also keep in mind that while this code is almost exclusively run as
- * a result of an erlang open_port({fd,0,1}, ...), that isn't the only
- * case - it can be called with any old pre-existing file descriptors,
- * the relations between which (if they're even two) we can only guess
- * at - still, we try our best...
- *
- * Added note OTP 18: Some systems seem to use stdout/stderr to log data
- * using unix pipes, so we cannot allow the system to block on a write.
- * Therefore we use an async thread to write the data to fd's that could
- * not be set to non-blocking. When no async threads are available we
- * fall back on the old behaviour.
- *
- * Also the guarantee about what is delivered to the OS has changed.
- * Pre 18 the fd driver did no flushing of data before terminating.
- * Now it does. This is because we want to be able to guarantee that things
- * such as escripts and friends really have outputted all data before
- * terminating. This could potentially block the termination of the system
- * for a very long time, but if the user wants to terminate fast she should
- * use erlang:halt with flush=false.
- */
-
- if (opts->read_write & DO_READ) {
- init_fd_data(opts->ifd, port_num);
- }
- if (opts->read_write & DO_WRITE) {
- init_fd_data(opts->ofd, port_num);
-
- /* If we don't have a read end, all bets are off - no non-blocking. */
- if (opts->read_write & DO_READ) {
-
- if (isatty(opts->ofd)) { /* output fd is a tty:-) */
-
- if (isatty(opts->ifd)) { /* input fd is also a tty */
-
- /* To really do this "right", we should also check that
- input and output fd point to the *same* tty - but
- this seems like overkill; ttyname() isn't for free,
- and this is a very common case - and it's hard to
- imagine a scenario where setting non-blocking mode
- here would cause problems - go ahead and do it. */
-
- non_blocking = 1;
- SET_NONBLOCKING(opts->ofd);
-
- } else { /* output fd is a tty, input fd isn't */
-
- /* This is a "problem case", but also common (see the
- example above) - i.e. it makes sense to try a bit
- harder before giving up on non-blocking mode: Try to
- re-open the tty that the output fd points to, and if
- successful replace the original one with the "new" fd
- obtained this way, and set *that* one in non-blocking
- mode. (Yes, this is a kludge.)
-
- However, re-opening the tty may fail in a couple of
- (unusual) cases:
-
- 1) The name of the tty (or an equivalent one, i.e.
- same major/minor number) can't be found, because
- it actually lives somewhere other than /dev (or
- wherever ttyname() looks for it), and isn't
- equivalent to any of those that do live in the
- "standard" place - this should be *very* unusual.
-
- 2) Permissions on the tty don't allow us to open it -
- it's perfectly possible to have an fd open to an
- object whose permissions wouldn't allow us to open
- it. This is not as unusual as it sounds, one case
- is if the user has su'ed to someone else (not
- root) - we have a read/write fd open to the tty
- (because it has been inherited all the way down
- here), but we have neither read nor write
- permission for the tty.
-
- In these cases, we finally give up, and don't set the
- output fd in non-blocking mode. */
-
- char *tty;
- int nfd;
-
- if ((tty = ttyname(opts->ofd)) != NULL &&
- (nfd = open(tty, O_WRONLY)) != -1) {
- dup2(nfd, opts->ofd);
- close(nfd);
- non_blocking = 1;
- SET_NONBLOCKING(opts->ofd);
- }
- }
- }
- }
- }
- CHLD_STAT_LOCK;
- res = (ErlDrvData)(long)set_driver_data(port_num, opts->ifd, opts->ofd,
- opts->packet_bytes,
- opts->read_write, 0, -1,
- !non_blocking);
- CHLD_STAT_UNLOCK;
- return res;
-}
-
-static void clear_fd_data(int fd)
-{
- if (fd_data[fd].sz > 0) {
- erts_free(ERTS_ALC_T_FD_ENTRY_BUF, (void *) fd_data[fd].buf);
- ASSERT(erts_smp_atomic_read_nob(&sys_misc_mem_sz) >= fd_data[fd].sz);
- erts_smp_atomic_add_nob(&sys_misc_mem_sz, -1*fd_data[fd].sz);
- }
- fd_data[fd].buf = NULL;
- fd_data[fd].sz = 0;
- fd_data[fd].remain = 0;
- fd_data[fd].cpos = NULL;
- fd_data[fd].psz = 0;
-}
-
-static void nbio_stop_fd(ErlDrvPort prt, int fd)
-{
- driver_select(prt,fd,DO_READ|DO_WRITE,0);
- clear_fd_data(fd);
- SET_BLOCKING(fd);
-}
-
-static void fd_stop(ErlDrvData ev) /* Does not close the fds */
-{
- int ofd;
- int fd = (int)(long)ev;
- ErlDrvPort prt = driver_data[fd].port_num;
-
-#if FDBLOCK
- if (driver_data[fd].blocking) {
- erts_free(ERTS_ALC_T_SYS_BLOCKING,driver_data[fd].blocking);
- driver_data[fd].blocking = NULL;
- erts_smp_atomic_add_nob(&sys_misc_mem_sz, -1*sizeof(ErtsSysBlocking));
- }
-#endif
-
- nbio_stop_fd(prt, fd);
- ofd = driver_data[fd].ofd;
- if (ofd != fd && ofd != -1)
- nbio_stop_fd(prt, ofd);
-}
-
-static void fd_flush(ErlDrvData fd)
-{
- if (!driver_data[(int)(long)fd].terminating)
- driver_data[(int)(long)fd].terminating = 1;
-}
-
-static ErlDrvData vanilla_start(ErlDrvPort port_num, char* name,
- SysDriverOpts* opts)
-{
- int flags, fd;
- ErlDrvData res;
-
- flags = (opts->read_write == DO_READ ? O_RDONLY :
- opts->read_write == DO_WRITE ? O_WRONLY|O_CREAT|O_TRUNC :
- O_RDWR|O_CREAT);
- if ((fd = open(name, flags, 0666)) < 0)
- return ERL_DRV_ERROR_GENERAL;
- if (fd >= max_files) {
- close(fd);
- return ERL_DRV_ERROR_GENERAL;
- }
- SET_NONBLOCKING(fd);
- init_fd_data(fd, port_num);
-
- CHLD_STAT_LOCK;
- res = (ErlDrvData)(long)set_driver_data(port_num, fd, fd,
- opts->packet_bytes,
- opts->read_write, 0, -1, 0);
- CHLD_STAT_UNLOCK;
- return res;
-}
-
-/* Note that driver_data[fd].ifd == fd if the port was opened for reading, */
-/* otherwise (i.e. write only) driver_data[fd].ofd = fd. */
-
-static void stop(ErlDrvData fd)
-{
- ErlDrvPort prt;
- int ofd;
-
- prt = driver_data[(int)(long)fd].port_num;
- nbio_stop_fd(prt, (int)(long)fd);
-
- ofd = driver_data[(int)(long)fd].ofd;
- if (ofd != (int)(long)fd && (int)(long)ofd != -1)
- nbio_stop_fd(prt, ofd);
- else
- ofd = -1;
-
- CHLD_STAT_LOCK;
-
- /* Mark as unused. */
- driver_data[(int)(long)fd].pid = -1;
-
- CHLD_STAT_UNLOCK;
-
- /* SMP note: Close has to be last thing done (open file descriptors work
- as locks on driver_data[] entries) */
- driver_select(prt, (int)(long)fd, ERL_DRV_USE, 0); /* close(fd); */
- if (ofd >= 0) {
- driver_select(prt, (int)(long)ofd, ERL_DRV_USE, 0); /* close(ofd); */
- }
-}
-
-/* used by fd_driver */
-static void outputv(ErlDrvData e, ErlIOVec* ev)
-{
- int fd = (int)(long)e;
- ErlDrvPort ix = driver_data[fd].port_num;
- int pb = driver_data[fd].packet_bytes;
- int ofd = driver_data[fd].ofd;
- ssize_t n;
- ErlDrvSizeT sz;
- char lb[4];
- char* lbp;
- ErlDrvSizeT len = ev->size;
-
- /* (len > ((unsigned long)-1 >> (4-pb)*8)) */
- /* if (pb >= 0 && (len & (((ErlDrvSizeT)1 << (pb*8))) - 1) != len) {*/
- if (((pb == 2) && (len > 0xffff)) || (pb == 1 && len > 0xff)) {
- driver_failure_posix(ix, EINVAL);
- return; /* -1; */
- }
- /* Handles 0 <= pb <= 4 only */
- put_int32((Uint32) len, lb);
- lbp = lb + (4-pb);
-
- ev->iov[0].iov_base = lbp;
- ev->iov[0].iov_len = pb;
- ev->size += pb;
-
- if (driver_data[fd].blocking && FDBLOCK)
- driver_pdl_lock(driver_data[fd].blocking->pdl);
-
- if ((sz = driver_sizeq(ix)) > 0) {
- driver_enqv(ix, ev, 0);
-
- if (driver_data[fd].blocking && FDBLOCK)
- driver_pdl_unlock(driver_data[fd].blocking->pdl);
-
- if (sz + ev->size >= (1 << 13))
- set_busy_port(ix, 1);
- }
- else if (!driver_data[fd].blocking || !FDBLOCK) {
- /* We try to write directly if the fd in non-blocking */
- int vsize = ev->vsize > MAX_VSIZE ? MAX_VSIZE : ev->vsize;
-
- n = writev(ofd, (const void *) (ev->iov), vsize);
- if (n == ev->size)
- return; /* 0;*/
- if (n < 0) {
- if ((errno != EINTR) && (errno != ERRNO_BLOCK)) {
- driver_failure_posix(ix, errno);
- return; /* -1;*/
- }
- n = 0;
- }
- driver_enqv(ix, ev, n); /* n is the skip value */
- driver_select(ix, ofd, ERL_DRV_WRITE|ERL_DRV_USE, 1);
- }
-#if FDBLOCK
- else {
- if (ev->size != 0) {
- driver_enqv(ix, ev, 0);
- driver_pdl_unlock(driver_data[fd].blocking->pdl);
- driver_async(ix, &driver_data[fd].blocking->pkey,
- fd_async, driver_data+fd, NULL);
- } else {
- driver_pdl_unlock(driver_data[fd].blocking->pdl);
- }
- }
-#endif
- /* return 0;*/
-}
-
-/* Used by spawn_driver and vanilla driver */
-static void output(ErlDrvData e, char* buf, ErlDrvSizeT len)
-{
- int fd = (int)(long)e;
- ErlDrvPort ix = driver_data[fd].port_num;
- int pb = driver_data[fd].packet_bytes;
- int ofd = driver_data[fd].ofd;
- ssize_t n;
- ErlDrvSizeT sz;
- char lb[4];
- char* lbp;
- struct iovec iv[2];
-
- /* (len > ((unsigned long)-1 >> (4-pb)*8)) */
- if (((pb == 2) && (len > 0xffff)) || (pb == 1 && len > 0xff)) {
- driver_failure_posix(ix, EINVAL);
- return; /* -1; */
- }
- put_int32(len, lb);
- lbp = lb + (4-pb);
-
- if ((sz = driver_sizeq(ix)) > 0) {
- driver_enq(ix, lbp, pb);
- driver_enq(ix, buf, len);
- if (sz + len + pb >= (1 << 13))
- set_busy_port(ix, 1);
- }
- else {
- iv[0].iov_base = lbp;
- iv[0].iov_len = pb; /* should work for pb=0 */
- iv[1].iov_base = buf;
- iv[1].iov_len = len;
- n = writev(ofd, iv, 2);
- if (n == pb+len)
- return; /* 0; */
- if (n < 0) {
- if ((errno != EINTR) && (errno != ERRNO_BLOCK)) {
- driver_failure_posix(ix, errno);
- return; /* -1; */
- }
- n = 0;
- }
- if (n < pb) {
- driver_enq(ix, lbp+n, pb-n);
- driver_enq(ix, buf, len);
- }
- else {
- n -= pb;
- driver_enq(ix, buf+n, len-n);
- }
- driver_select(ix, ofd, ERL_DRV_WRITE|ERL_DRV_USE, 1);
- }
- return; /* 0; */
-}
-
-static int port_inp_failure(ErlDrvPort port_num, int ready_fd, int res)
- /* Result: 0 (eof) or -1 (error) */
-{
- int err = errno;
-
- ASSERT(res <= 0);
- (void) driver_select(port_num, ready_fd, ERL_DRV_READ|ERL_DRV_WRITE, 0);
- clear_fd_data(ready_fd);
-
- if (driver_data[ready_fd].blocking && FDBLOCK) {
- driver_pdl_lock(driver_data[ready_fd].blocking->pdl);
- if (driver_sizeq(driver_data[ready_fd].port_num) > 0) {
- driver_pdl_unlock(driver_data[ready_fd].blocking->pdl);
- /* We have stuff in the output queue, so we just
- set the state to terminating and wait for fd_async_ready
- to terminate the port */
- if (res == 0)
- driver_data[ready_fd].terminating = 2;
- else
- driver_data[ready_fd].terminating = -err;
- return 0;
- }
- driver_pdl_unlock(driver_data[ready_fd].blocking->pdl);
- }
-
- if (res == 0) {
- if (driver_data[ready_fd].report_exit) {
- CHLD_STAT_LOCK;
-
- if (driver_data[ready_fd].alive) {
- /*
- * We have eof and want to report exit status, but the process
- * hasn't exited yet. When it does report_exit_status() will
- * driver_select() this fd which will make sure that we get
- * back here with driver_data[ready_fd].alive == 0 and
- * driver_data[ready_fd].status set.
- */
- CHLD_STAT_UNLOCK;
- return 0;
- }
- else {
- int status = driver_data[ready_fd].status;
- CHLD_STAT_UNLOCK;
-
- /* We need not be prepared for stopped/continued processes. */
- if (WIFSIGNALED(status))
- status = 128 + WTERMSIG(status);
- else
- status = WEXITSTATUS(status);
-
- driver_report_exit(driver_data[ready_fd].port_num, status);
- }
- }
- driver_failure_eof(port_num);
- } else {
- driver_failure_posix(port_num, err);
- }
- return 0;
-}
-
-/* fd is the drv_data that is returned from the */
-/* initial start routine */
-/* ready_fd is the descriptor that is ready to read */
-
-static void ready_input(ErlDrvData e, ErlDrvEvent ready_fd)
-{
- int fd = (int)(long)e;
- ErlDrvPort port_num;
- int packet_bytes;
- int res;
- Uint h;
-
- port_num = driver_data[fd].port_num;
- packet_bytes = driver_data[fd].packet_bytes;
-
-
- if (packet_bytes == 0) {
- byte *read_buf = (byte *) erts_alloc(ERTS_ALC_T_SYS_READ_BUF,
- ERTS_SYS_READ_BUF_SZ);
- res = read(ready_fd, read_buf, ERTS_SYS_READ_BUF_SZ);
- if (res < 0) {
- if ((errno != EINTR) && (errno != ERRNO_BLOCK))
- port_inp_failure(port_num, ready_fd, res);
- }
- else if (res == 0)
- port_inp_failure(port_num, ready_fd, res);
- else
- driver_output(port_num, (char*) read_buf, res);
- erts_free(ERTS_ALC_T_SYS_READ_BUF, (void *) read_buf);
- }
- else if (fd_data[ready_fd].remain > 0) { /* We try to read the remainder */
- /* space is allocated in buf */
- res = read(ready_fd, fd_data[ready_fd].cpos,
- fd_data[ready_fd].remain);
- if (res < 0) {
- if ((errno != EINTR) && (errno != ERRNO_BLOCK))
- port_inp_failure(port_num, ready_fd, res);
- }
- else if (res == 0) {
- port_inp_failure(port_num, ready_fd, res);
- }
- else if (res == fd_data[ready_fd].remain) { /* we're done */
- driver_output(port_num, fd_data[ready_fd].buf,
- fd_data[ready_fd].sz);
- clear_fd_data(ready_fd);
- }
- else { /* if (res < fd_data[ready_fd].remain) */
- fd_data[ready_fd].cpos += res;
- fd_data[ready_fd].remain -= res;
- }
- }
- else if (fd_data[ready_fd].remain == 0) { /* clean fd */
- byte *read_buf = (byte *) erts_alloc(ERTS_ALC_T_SYS_READ_BUF,
- ERTS_SYS_READ_BUF_SZ);
- /* We make one read attempt and see what happens */
- res = read(ready_fd, read_buf, ERTS_SYS_READ_BUF_SZ);
- if (res < 0) {
- if ((errno != EINTR) && (errno != ERRNO_BLOCK))
- port_inp_failure(port_num, ready_fd, res);
- }
- else if (res == 0) { /* eof */
- port_inp_failure(port_num, ready_fd, res);
- }
- else if (res < packet_bytes - fd_data[ready_fd].psz) {
- memcpy(fd_data[ready_fd].pbuf+fd_data[ready_fd].psz,
- read_buf, res);
- fd_data[ready_fd].psz += res;
- }
- else { /* if (res >= packet_bytes) */
- unsigned char* cpos = read_buf;
- int bytes_left = res;
-
- while (1) {
- int psz = fd_data[ready_fd].psz;
- char* pbp = fd_data[ready_fd].pbuf + psz;
-
- while(bytes_left && (psz < packet_bytes)) {
- *pbp++ = *cpos++;
- bytes_left--;
- psz++;
- }
-
- if (psz < packet_bytes) {
- fd_data[ready_fd].psz = psz;
- break;
- }
- fd_data[ready_fd].psz = 0;
-
- switch (packet_bytes) {
- case 1: h = get_int8(fd_data[ready_fd].pbuf); break;
- case 2: h = get_int16(fd_data[ready_fd].pbuf); break;
- case 4: h = get_int32(fd_data[ready_fd].pbuf); break;
- default: ASSERT(0); return; /* -1; */
- }
-
- if (h <= (bytes_left)) {
- driver_output(port_num, (char*) cpos, h);
- cpos += h;
- bytes_left -= h;
- continue;
- }
- else { /* The last message we got was split */
- char *buf = erts_alloc_fnf(ERTS_ALC_T_FD_ENTRY_BUF, h);
- if (!buf) {
- errno = ENOMEM;
- port_inp_failure(port_num, ready_fd, -1);
- }
- else {
- erts_smp_atomic_add_nob(&sys_misc_mem_sz, h);
- sys_memcpy(buf, cpos, bytes_left);
- fd_data[ready_fd].buf = buf;
- fd_data[ready_fd].sz = h;
- fd_data[ready_fd].remain = h - bytes_left;
- fd_data[ready_fd].cpos = buf + bytes_left;
- }
- break;
- }
- }
- }
- erts_free(ERTS_ALC_T_SYS_READ_BUF, (void *) read_buf);
- }
-}
-
-
-/* fd is the drv_data that is returned from the */
-/* initial start routine */
-/* ready_fd is the descriptor that is ready to read */
-
-static void ready_output(ErlDrvData e, ErlDrvEvent ready_fd)
-{
- int fd = (int)(long)e;
- ErlDrvPort ix = driver_data[fd].port_num;
- int n;
- struct iovec* iv;
- int vsize;
-
-
- if ((iv = (struct iovec*) driver_peekq(ix, &vsize)) == NULL) {
- driver_select(ix, ready_fd, ERL_DRV_WRITE, 0);
- if (driver_data[fd].terminating)
- driver_failure_atom(driver_data[fd].port_num,"normal");
- return; /* 0; */
- }
- vsize = vsize > MAX_VSIZE ? MAX_VSIZE : vsize;
- if ((n = writev(ready_fd, iv, vsize)) > 0) {
- if (driver_deq(ix, n) == 0)
- set_busy_port(ix, 0);
- }
- else if (n < 0) {
- if (errno == ERRNO_BLOCK || errno == EINTR)
- return; /* 0; */
- else {
- int res = errno;
- driver_select(ix, ready_fd, ERL_DRV_WRITE, 0);
- driver_failure_posix(ix, res);
- return; /* -1; */
- }
- }
- return; /* 0; */
-}
-
-static void stop_select(ErlDrvEvent fd, void* _)
-{
- close((int)fd);
-}
-
-#if FDBLOCK
-
-static void
-fd_async(void *async_data)
-{
- int res;
- struct driver_data *dd = (struct driver_data*)async_data;
- SysIOVec *iov0;
- SysIOVec *iov;
- int iovlen;
- int err = 0;
- /* much of this code is stolen from efile_drv:invoke_writev */
- driver_pdl_lock(dd->blocking->pdl);
- iov0 = driver_peekq(dd->port_num, &iovlen);
- iovlen = iovlen < MAXIOV ? iovlen : MAXIOV;
- iov = erts_alloc_fnf(ERTS_ALC_T_SYS_WRITE_BUF,
- sizeof(SysIOVec)*iovlen);
- if (!iov) {
- res = -1;
- err = ENOMEM;
- driver_pdl_unlock(dd->blocking->pdl);
- } else {
- memcpy(iov,iov0,iovlen*sizeof(SysIOVec));
- driver_pdl_unlock(dd->blocking->pdl);
-
- do {
- res = writev(dd->ofd, iov, iovlen);
- } while (res < 0 && errno == EINTR);
- if (res < 0)
- err = errno;
-
- erts_free(ERTS_ALC_T_SYS_WRITE_BUF, iov);
- }
- dd->blocking->res = res;
- dd->blocking->err = err;
-}
-
-void fd_ready_async(ErlDrvData drv_data,
- ErlDrvThreadData thread_data) {
- struct driver_data *dd = (struct driver_data *)thread_data;
- ErlDrvPort port_num = dd->port_num;
-
- ASSERT(dd->blocking);
- ASSERT(dd == (driver_data + (int)(long)drv_data));
-
- if (dd->blocking->res > 0) {
- driver_pdl_lock(dd->blocking->pdl);
- if (driver_deq(port_num, dd->blocking->res) == 0) {
- driver_pdl_unlock(dd->blocking->pdl);
- set_busy_port(port_num, 0);
- if (dd->terminating) {
- /* The port is has been ordered to terminate
- from either fd_flush or port_inp_failure */
- if (dd->terminating == 1)
- driver_failure_atom(port_num, "normal");
- else if (dd->terminating == 2)
- driver_failure_eof(port_num);
- else if (dd->terminating < 0)
- driver_failure_posix(port_num, -dd->terminating);
- return; /* -1; */
- }
- } else {
- driver_pdl_unlock(dd->blocking->pdl);
- /* still data left to write in queue */
- driver_async(port_num, &dd->blocking->pkey, fd_async, dd, NULL);
- return /* 0; */;
- }
- } else if (dd->blocking->res < 0) {
- if (dd->blocking->err == ERRNO_BLOCK) {
- set_busy_port(port_num, 1);
- /* still data left to write in queue */
- driver_async(port_num, &dd->blocking->pkey, fd_async, dd, NULL);
- } else
- driver_failure_posix(port_num, dd->blocking->err);
- return; /* -1; */
- }
- return; /* 0; */
-}
-
-#endif
-
void erts_do_break_handling(void)
{
struct termios temp_mode;
@@ -2738,10 +1011,6 @@ erts_sys_unsetenv(char *key)
void
sys_init_io(void)
{
- fd_data = (struct fd_data *)
- erts_alloc(ERTS_ALC_T_FD_TAB, max_files * sizeof(struct fd_data));
- erts_smp_atomic_add_nob(&sys_misc_mem_sz,
- max_files * sizeof(struct fd_data));
}
#if (0) /* unused? */
@@ -2935,179 +1204,6 @@ erl_debug(char* fmt, ...)
#endif /* DEBUG */
-static ERTS_INLINE void
-report_exit_status(ErtsSysReportExit *rep, int status)
-{
- Port *pp;
-#ifdef ERTS_SMP
- CHLD_STAT_UNLOCK;
- pp = erts_thr_id2port_sflgs(rep->port,
- ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP);
- CHLD_STAT_LOCK;
-#else
- pp = erts_id2port_sflgs(rep->port,
- NULL,
- 0,
- ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP);
-#endif
- if (pp) {
- if (rep->ifd >= 0) {
- driver_data[rep->ifd].alive = 0;
- driver_data[rep->ifd].status = status;
- (void) driver_select(ERTS_Port2ErlDrvPort(pp),
- rep->ifd,
- (ERL_DRV_READ|ERL_DRV_USE),
- 1);
- }
- if (rep->ofd >= 0) {
- driver_data[rep->ofd].alive = 0;
- driver_data[rep->ofd].status = status;
- (void) driver_select(ERTS_Port2ErlDrvPort(pp),
- rep->ofd,
- (ERL_DRV_WRITE|ERL_DRV_USE),
- 1);
- }
-#ifdef ERTS_SMP
- erts_thr_port_release(pp);
-#else
- erts_port_release(pp);
-#endif
- }
- erts_free(ERTS_ALC_T_PRT_REP_EXIT, rep);
-}
-
-#if !CHLDWTHR /* ---------------------------------------------------------- */
-
-#define ERTS_REPORT_EXIT_STATUS report_exit_status
-
-static int check_children(void)
-{
- int res = 0;
- int pid;
- int status;
-
-#ifndef ERTS_SMP
- if (children_died)
-#endif
- {
- sys_sigblock(SIGCHLD);
- CHLD_STAT_LOCK;
- while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
- note_child_death(pid, status);
-#ifndef ERTS_SMP
- children_died = 0;
-#endif
- CHLD_STAT_UNLOCK;
- sys_sigrelease(SIGCHLD);
- res = 1;
- }
- return res;
-}
-
-#ifdef ERTS_SMP
-
-void
-erts_check_children(void)
-{
- (void) check_children();
-}
-
-#endif
-
-#elif CHLDWTHR && defined(ERTS_SMP) /* ------------------------------------- */
-
-#define ERTS_REPORT_EXIT_STATUS report_exit_status
-
-#define check_children() (0)
-
-
-#else /* CHLDWTHR && !defined(ERTS_SMP) ------------------------------------ */
-
-#define ERTS_REPORT_EXIT_STATUS initiate_report_exit_status
-
-static ERTS_INLINE void
-initiate_report_exit_status(ErtsSysReportExit *rep, int status)
-{
- rep->next = report_exit_transit_list;
- rep->status = status;
- report_exit_transit_list = rep;
- erts_sys_schedule_interrupt(1);
-}
-
-static int check_children(void)
-{
- int res;
- ErtsSysReportExit *rep;
- CHLD_STAT_LOCK;
- rep = report_exit_transit_list;
- res = rep != NULL;
- while (rep) {
- ErtsSysReportExit *curr_rep = rep;
- rep = rep->next;
- report_exit_status(curr_rep, curr_rep->status);
- }
- report_exit_transit_list = NULL;
- CHLD_STAT_UNLOCK;
- return res;
-}
-
-#endif /* ------------------------------------------------------------------ */
-
-static void note_child_death(int pid, int status)
-{
- ErtsSysReportExit **repp = &report_exit_list;
- ErtsSysReportExit *rep = report_exit_list;
-
- while (rep) {
- if (pid == rep->pid) {
- *repp = rep->next;
- ERTS_REPORT_EXIT_STATUS(rep, status);
- break;
- }
- repp = &rep->next;
- rep = rep->next;
- }
-}
-
-#if CHLDWTHR
-
-static void *
-child_waiter(void *unused)
-{
- int pid;
- int status;
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
- erts_lc_set_thread_name("child waiter");
-#endif
-
- while(1) {
-#ifdef DEBUG
- int waitpid_errno;
-#endif
- pid = waitpid(-1, &status, 0);
-#ifdef DEBUG
- waitpid_errno = errno;
-#endif
- CHLD_STAT_LOCK;
- if (pid < 0) {
- ASSERT(waitpid_errno == ECHILD);
- }
- else {
- children_alive--;
- ASSERT(children_alive >= 0);
- note_child_death(pid, status);
- }
- while (!children_alive)
- CHLD_STAT_WAIT; /* Wait for children to wait on... :) */
- CHLD_STAT_UNLOCK;
- }
-
- return NULL;
-}
-
-#endif
-
/*
* Called from schedule() when it runs out of runnable processes,
* or when Erlang code has performed INPUT_REDUCTIONS reduction
@@ -3116,13 +1212,8 @@ child_waiter(void *unused)
void
erl_sys_schedule(int runnable)
{
-#ifdef ERTS_SMP
ERTS_CHK_IO(!runnable);
-#else
- ERTS_CHK_IO(runnable ? 0 : !check_children());
-#endif
ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
- (void) check_children();
}
@@ -3150,10 +1241,6 @@ smp_sig_notify(char c)
static void *
signal_dispatcher_thread_func(void *unused)
{
-#if !CHLDWTHR
- int initialized = 0;
- int notify_check_children = 0;
-#endif
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_lc_set_thread_name("signal_dispatcher");
#endif
@@ -3191,19 +1278,7 @@ signal_dispatcher_thread_func(void *unused)
*/
switch (buf[i]) {
case 0: /* Emulator initialized */
-#if !CHLDWTHR
- initialized = 1;
- if (!notify_check_children)
-#endif
- break;
-#if !CHLDWTHR
- case 'C': /* SIGCHLD */
- if (initialized)
- erts_smp_notify_check_children_needed();
- else
- notify_check_children = 1;
- break;
-#endif
+ break;
case 'I': /* SIGINT */
break_requested();
break;
diff --git a/erts/emulator/sys/unix/sys_drivers.c b/erts/emulator/sys/unix/sys_drivers.c
new file mode 100644
index 0000000000..82fea1b330
--- /dev/null
+++ b/erts/emulator/sys/unix/sys_drivers.c
@@ -0,0 +1,1862 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1996-2014. 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%
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef ISC32
+#define _POSIX_SOURCE
+#define _XOPEN_SOURCE
+#endif
+
+#include <sys/times.h> /* ! */
+#include <time.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/uio.h>
+#include <termios.h>
+#include <ctype.h>
+#include <sys/utsname.h>
+#include <sys/select.h>
+#include <arpa/inet.h>
+
+#ifdef ISC32
+#include <sys/bsdtypes.h>
+#endif
+
+#include <termios.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#define WANT_NONBLOCKING /* must define this to pull in defs from sys.h */
+#include "sys.h"
+
+#ifdef USE_THREADS
+#include "erl_threads.h"
+#endif
+
+extern char **environ;
+extern erts_smp_rwmtx_t environ_rwmtx;
+
+extern erts_smp_atomic_t sys_misc_mem_sz;
+
+static Eterm forker_port;
+
+#define MAX_VSIZE 16 /* Max number of entries allowed in an I/O
+ * vector sock_sendv().
+ */
+/*
+ * Don't need global.h, but erl_cpu_topology.h won't compile otherwise
+ */
+#include "global.h"
+#include "erl_cpu_topology.h"
+
+#include "erl_sys_driver.h"
+#include "sys_uds.h"
+
+#include "erl_child_setup.h"
+
+#if defined IOV_MAX
+#define MAXIOV IOV_MAX
+#elif defined UIO_MAXIOV
+#define MAXIOV UIO_MAXIOV
+#else
+#define MAXIOV 16
+#endif
+
+#ifdef USE_THREADS
+# define FDBLOCK 1
+#else
+# define FDBLOCK 0
+#endif
+
+/* Used by the fd driver iff the fd could not be set to non-blocking */
+typedef struct ErtsSysBlocking_ {
+ ErlDrvPDL pdl;
+ int res;
+ int err;
+ unsigned int pkey;
+} ErtsSysBlocking;
+
+typedef struct fd_data {
+ int fd;
+ char pbuf[4]; /* hold partial packet bytes */
+ int psz; /* size of pbuf */
+ char *buf;
+ char *cpos;
+ int sz;
+ int remain; /* for input on fd */
+} ErtsSysFdData;
+
+typedef struct driver_data {
+ ErlDrvPort port_num;
+ ErtsSysFdData *ofd;
+ ErtsSysFdData *ifd;
+ int packet_bytes;
+ int pid;
+ int alive;
+ int status;
+ int terminating;
+ ErtsSysBlocking *blocking;
+} ErtsSysDriverData;
+
+#define DIR_SEPARATOR_CHAR '/'
+
+#if defined(__ANDROID__)
+#define SHELL "/system/bin/sh"
+#else
+#define SHELL "/bin/sh"
+#endif /* __ANDROID__ */
+
+#if defined(DEBUG)
+#define ERL_BUILD_TYPE_MARKER ".debug"
+#elif defined(PURIFY)
+#define ERL_BUILD_TYPE_MARKER ".purify"
+#elif defined(QUANTIFY)
+#define ERL_BUILD_TYPE_MARKER ".quantify"
+#elif defined(PURECOV)
+#define ERL_BUILD_TYPE_MARKER ".purecov"
+#elif defined(VALGRIND)
+#define ERL_BUILD_TYPE_MARKER ".valgrind"
+#else /* opt */
+#define ERL_BUILD_TYPE_MARKER
+#endif
+
+#ifdef DEBUG
+#define close(fd) do { int res = close(fd); ASSERT(res > -1); } while(0)
+#endif
+
+#define CHILD_SETUP_PROG_NAME "erl_child_setup" ERL_BUILD_TYPE_MARKER
+
+// #define HARD_DEBUG
+#ifdef HARD_DEBUG
+#define driver_select(port_num, fd, flags, onoff) \
+ do { \
+ if (((flags) & ERL_DRV_READ) && onoff) \
+ fprintf(stderr,"%010d %p: read select %d\r\n", __LINE__, port_num, (int)fd); \
+ if (((flags) & ERL_DRV_WRITE) && onoff) \
+ fprintf(stderr,"%010d %p: writ select %d\r\n", __LINE__, port_num, (int)fd); \
+ if (((flags) & ERL_DRV_READ) && !onoff) \
+ fprintf(stderr,"%010d %p: read unsele %d\r\n", __LINE__, port_num, (int)fd); \
+ if (((flags) & ERL_DRV_WRITE) && !onoff) \
+ fprintf(stderr,"%010d %p: writ unsele %d\r\n", __LINE__, port_num, (int)fd); \
+ driver_select_nkp(port_num, fd, flags, onoff); \
+ } while(0)
+#endif
+
+/*
+ * Decreasing the size of it below 16384 is not allowed.
+ */
+
+#define ERTS_SYS_READ_BUF_SZ (64*1024)
+
+/* I. Initialization */
+
+void
+erl_sys_late_init(void)
+{
+ SysDriverOpts opts;
+#ifdef ERTS_SMP
+ Port *port;
+#endif
+
+ sys_signal(SIGPIPE, SIG_IGN); /* Ignore - we'll handle the write failure */
+
+ opts.packet_bytes = 0;
+ opts.use_stdio = 1;
+ opts.redir_stderr = 0;
+ opts.read_write = 0;
+ opts.hide_window = 0;
+ opts.wd = NULL;
+ opts.envir = NULL;
+ opts.exit_status = 0;
+ opts.overlapped_io = 0;
+ opts.spawn_type = ERTS_SPAWN_ANY;
+ opts.argv = NULL;
+ opts.parallelism = erts_port_parallelism;
+
+#ifdef ERTS_SMP
+ port =
+#endif
+ erts_open_driver(&forker_driver, make_internal_pid(0), "forker", &opts, NULL, NULL);
+#ifdef ERTS_SMP
+ erts_mtx_unlock(port->lock);
+#endif
+}
+
+/* II. Prototypes */
+
+/* II.I Spawn prototypes */
+static ErlDrvData spawn_start(ErlDrvPort, char*, SysDriverOpts*);
+static ErlDrvSSizeT spawn_control(ErlDrvData, unsigned int, char *,
+ ErlDrvSizeT, char **, ErlDrvSizeT);
+
+/* II.II Vanilla prototypes */
+static ErlDrvData vanilla_start(ErlDrvPort, char*, SysDriverOpts*);
+
+
+/* II.III FD prototypes */
+static ErlDrvData fd_start(ErlDrvPort, char*, SysDriverOpts*);
+#if FDBLOCK
+static void fd_async(void *);
+static void fd_ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data);
+#endif
+static ErlDrvSSizeT fd_control(ErlDrvData, unsigned int, char *, ErlDrvSizeT,
+ char **, ErlDrvSizeT);
+static void fd_stop(ErlDrvData);
+static void fd_flush(ErlDrvData);
+
+/* II.IV Common prototypes */
+static void stop(ErlDrvData);
+static void ready_input(ErlDrvData, ErlDrvEvent);
+static void ready_output(ErlDrvData, ErlDrvEvent);
+static void output(ErlDrvData, char*, ErlDrvSizeT);
+static void outputv(ErlDrvData, ErlIOVec*);
+static void stop_select(ErlDrvEvent, void*);
+
+/* II.V Forker prototypes */
+static ErlDrvData forker_start(ErlDrvPort, char*, SysDriverOpts*);
+static void forker_stop(ErlDrvData);
+static void forker_ready_input(ErlDrvData, ErlDrvEvent);
+static void forker_ready_output(ErlDrvData, ErlDrvEvent);
+static ErlDrvSSizeT forker_control(ErlDrvData, unsigned int, char *,
+ ErlDrvSizeT, char **, ErlDrvSizeT);
+
+/* III Driver entries */
+
+/* III.I The spawn driver */
+struct erl_drv_entry spawn_driver_entry = {
+ NULL,
+ spawn_start,
+ stop,
+ output,
+ ready_input,
+ ready_output,
+ "spawn",
+ NULL,
+ NULL,
+ spawn_control,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ ERL_DRV_FLAG_USE_PORT_LOCKING | ERL_DRV_FLAG_USE_INIT_ACK,
+ NULL, NULL,
+ stop_select
+};
+
+/* III.II The fd driver */
+struct erl_drv_entry fd_driver_entry = {
+ NULL,
+ fd_start,
+ fd_stop,
+ output,
+ ready_input,
+ ready_output,
+ "fd",
+ NULL,
+ NULL,
+ fd_control,
+ NULL,
+ outputv,
+#if FDBLOCK
+ fd_ready_async, /* ready_async */
+#else
+ NULL,
+#endif
+ fd_flush, /* flush */
+ NULL, /* call */
+ NULL, /* event */
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0, /* ERL_DRV_FLAGs */
+ NULL, /* handle2 */
+ NULL, /* process_exit */
+ stop_select
+};
+
+/* III.III The vanilla driver */
+struct erl_drv_entry vanilla_driver_entry = {
+ NULL,
+ vanilla_start,
+ stop,
+ output,
+ ready_input,
+ ready_output,
+ "vanilla",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* flush */
+ NULL, /* call */
+ NULL, /* event */
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0, /* ERL_DRV_FLAGs */
+ NULL, /* handle2 */
+ NULL, /* process_exit */
+ stop_select
+};
+
+/* III.III The forker driver */
+struct erl_drv_entry forker_driver_entry = {
+ NULL,
+ forker_start,
+ forker_stop,
+ NULL,
+ forker_ready_input,
+ forker_ready_output,
+ "spawn_forker",
+ NULL,
+ NULL,
+ forker_control,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL, NULL,
+ stop_select
+};
+
+/* Untility functions */
+
+static int set_blocking_data(ErtsSysDriverData *dd) {
+
+ dd->blocking = erts_alloc(ERTS_ALC_T_SYS_BLOCKING, sizeof(ErtsSysBlocking));
+
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, sizeof(ErtsSysBlocking));
+
+ dd->blocking->pdl = driver_pdl_create(dd->port_num);
+ dd->blocking->res = 0;
+ dd->blocking->err = 0;
+ dd->blocking->pkey = driver_async_port_key(dd->port_num);
+
+ return 1;
+}
+
+static void init_fd_data(ErtsSysFdData *fd_data, int fd)
+{
+ fd_data->fd = fd;
+ fd_data->buf = NULL;
+ fd_data->cpos = NULL;
+ fd_data->remain = 0;
+ fd_data->sz = 0;
+ fd_data->psz = 0;
+}
+
+static ErtsSysDriverData *
+create_driver_data(ErlDrvPort port_num,
+ int ifd,
+ int ofd,
+ int packet_bytes,
+ int read_write,
+ int exit_status,
+ int pid,
+ int is_blocking)
+{
+ Port *prt;
+ ErtsSysDriverData *driver_data;
+ char *data;
+ int size = sizeof(ErtsSysDriverData);
+
+ if (read_write & DO_READ)
+ size += sizeof(ErtsSysFdData);
+
+ if ((read_write & DO_WRITE) &&
+ ((ifd != ofd || ofd == -1) || !(read_write & DO_READ)))
+ size += sizeof(ErtsSysFdData);
+
+ data = erts_alloc(ERTS_ALC_T_DRV_TAB,size);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, size);
+
+ driver_data = (ErtsSysDriverData*)data;
+ data += sizeof(*driver_data);
+
+ prt = erts_drvport2port(port_num);
+ if (prt != ERTS_INVALID_ERL_DRV_PORT)
+ prt->os_pid = pid;
+
+ driver_data->packet_bytes = packet_bytes;
+ driver_data->port_num = port_num;
+ driver_data->pid = pid;
+ driver_data->alive = exit_status ? 1 : 0;
+ driver_data->status = 0;
+ driver_data->terminating = 0;
+ driver_data->blocking = NULL;
+
+ if (read_write & DO_READ) {
+ driver_data->ifd = (ErtsSysFdData*)data;
+ data += sizeof(*driver_data->ifd);
+ init_fd_data(driver_data->ifd, ifd);
+ driver_select(port_num, ifd, (ERL_DRV_READ|ERL_DRV_USE), 1);
+ } else {
+ driver_data->ifd = NULL;
+ }
+
+ if (read_write & DO_WRITE) {
+ if (ofd != -1 && ifd == ofd && read_write & DO_READ) {
+ /* This is for when ifd and ofd are the same fd */
+ driver_data->ofd = driver_data->ifd;
+ } else {
+ driver_data->ofd = (ErtsSysFdData*)data;
+ data += sizeof(*driver_data->ofd);
+ init_fd_data(driver_data->ofd, ofd);
+ }
+ if (is_blocking && FDBLOCK)
+ if (!set_blocking_data(driver_data)) {
+ erts_free(ERTS_ALC_T_DRV_TAB, driver_data);
+ return NULL;
+ }
+ } else {
+ driver_data->ofd = NULL;
+ }
+
+ return driver_data;
+}
+
+/* Spawn driver */
+
+static void close_pipes(int ifd[2], int ofd[2])
+{
+ close(ifd[0]);
+ close(ifd[1]);
+ close(ofd[0]);
+ close(ofd[1]);
+}
+
+static char **build_unix_environment(char *block)
+{
+ int i;
+ int j;
+ int len;
+ char *cp;
+ char **cpp;
+ char** old_env;
+
+ ERTS_SMP_LC_ASSERT(erts_smp_lc_rwmtx_is_rlocked(&environ_rwmtx));
+
+ cp = block;
+ len = 0;
+ while (*cp != '\0') {
+ cp += strlen(cp) + 1;
+ len++;
+ }
+ old_env = environ;
+ while (*old_env++ != NULL) {
+ len++;
+ }
+
+ cpp = (char **) erts_alloc_fnf(ERTS_ALC_T_ENVIRONMENT,
+ sizeof(char *) * (len+1));
+ if (cpp == NULL) {
+ return NULL;
+ }
+
+ cp = block;
+ len = 0;
+ while (*cp != '\0') {
+ cpp[len] = cp;
+ cp += strlen(cp) + 1;
+ len++;
+ }
+
+ i = len;
+ for (old_env = environ; *old_env; old_env++) {
+ char* old = *old_env;
+
+ for (j = 0; j < len; j++) {
+ char *s, *t;
+
+ /* check if cpp[j] equals old
+ before the = sign,
+ i.e.
+ "TMPDIR=/tmp/" */
+ s = cpp[j];
+ t = old;
+ while (*s == *t && *s != '=') {
+ s++, t++;
+ }
+ if (*s == '=' && *t == '=') {
+ break;
+ }
+ }
+
+ if (j == len) { /* New version not found */
+ cpp[len++] = old;
+ }
+ }
+
+ for (j = 0; j < i; ) {
+ size_t last = strlen(cpp[j])-1;
+ if (cpp[j][last] == '=' && strchr(cpp[j], '=') == cpp[j]+last) {
+ cpp[j] = cpp[--len];
+ if (len < i) {
+ i--;
+ } else {
+ j++;
+ }
+ }
+ else {
+ j++;
+ }
+ }
+
+ cpp[len] = NULL;
+ return cpp;
+}
+
+static ErlDrvData spawn_start(ErlDrvPort port_num, char* name,
+ SysDriverOpts* opts)
+{
+#define CMD_LINE_PREFIX_STR "exec "
+#define CMD_LINE_PREFIX_STR_SZ (sizeof(CMD_LINE_PREFIX_STR) - 1)
+
+ int len;
+ char **new_environ;
+ ErtsSysDriverData *dd;
+ char *cmd_line;
+ char wd_buff[MAXPATHLEN+1];
+ char *wd;
+ int ifd[2], ofd[2], stderrfd;
+
+ if (pipe(ifd) < 0) return ERL_DRV_ERROR_ERRNO;
+ errno = EMFILE; /* default for next three conditions */
+ if (ifd[0] >= sys_max_files() || pipe(ofd) < 0) {
+ close(ifd[0]);
+ close(ifd[1]);
+ return ERL_DRV_ERROR_ERRNO;
+ }
+ if (ofd[1] >= sys_max_files()) {
+ close_pipes(ifd, ofd);
+ errno = EMFILE;
+ return ERL_DRV_ERROR_ERRNO;
+ }
+
+ SET_NONBLOCKING(ifd[0]);
+ SET_NONBLOCKING(ofd[1]);
+
+ stderrfd = opts->redir_stderr ? ifd[1] : dup(2);
+
+ if (stderrfd >= sys_max_files() || stderrfd < 0) {
+ close_pipes(ifd, ofd);
+ if (stderrfd > -1)
+ close(stderrfd);
+ return ERL_DRV_ERROR_ERRNO;
+ }
+
+ if (opts->spawn_type == ERTS_SPAWN_EXECUTABLE) {
+ /* started with spawn_executable, not with spawn */
+ len = strlen(name);
+ cmd_line = (char *) erts_alloc_fnf(ERTS_ALC_T_TMP, len + 1);
+ if (!cmd_line) {
+ close_pipes(ifd, ofd);
+ errno = ENOMEM;
+ return ERL_DRV_ERROR_ERRNO;
+ }
+ memcpy((void *) cmd_line,(void *) name, len);
+ cmd_line[len] = '\0';
+ len = len + 1;
+ if (access(cmd_line,X_OK) != 0) {
+ int save_errno = errno;
+ erts_free(ERTS_ALC_T_TMP, cmd_line);
+ close_pipes(ifd, ofd);
+ errno = save_errno;
+ return ERL_DRV_ERROR_ERRNO;
+ }
+ } else {
+ /* make the string suitable for giving to "sh" */
+ len = strlen(name);
+ cmd_line = (char *) erts_alloc_fnf(ERTS_ALC_T_TMP,
+ CMD_LINE_PREFIX_STR_SZ + len + 1);
+ if (!cmd_line) {
+ close_pipes(ifd, ofd);
+ errno = ENOMEM;
+ return ERL_DRV_ERROR_ERRNO;
+ }
+ memcpy((void *) cmd_line,
+ (void *) CMD_LINE_PREFIX_STR,
+ CMD_LINE_PREFIX_STR_SZ);
+ memcpy((void *) (cmd_line + CMD_LINE_PREFIX_STR_SZ), (void *) name, len);
+ cmd_line[CMD_LINE_PREFIX_STR_SZ + len] = '\0';
+ len = CMD_LINE_PREFIX_STR_SZ + len + 1;
+ }
+
+ erts_smp_rwmtx_rlock(&environ_rwmtx);
+
+ if (opts->envir == NULL) {
+ new_environ = environ;
+ } else if ((new_environ = build_unix_environment(opts->envir)) == NULL) {
+ erts_smp_rwmtx_runlock(&environ_rwmtx);
+ close_pipes(ifd, ofd);
+ erts_free(ERTS_ALC_T_TMP, (void *) cmd_line);
+ errno = ENOMEM;
+ return ERL_DRV_ERROR_ERRNO;
+ }
+
+ if (opts->wd == NULL) {
+ if ((wd = getcwd(wd_buff, MAXPATHLEN+1)) == NULL) {
+ /* on some OSs this call opens a fd in the
+ background which means that this can
+ return EMFILE */
+ int err = errno;
+ close_pipes(ifd, ofd);
+ erts_free(ERTS_ALC_T_TMP, (void *) cmd_line);
+ if (new_environ != environ)
+ erts_free(ERTS_ALC_T_ENVIRONMENT, (void *) new_environ);
+ erts_smp_rwmtx_runlock(&environ_rwmtx);
+ errno = err;
+ return ERL_DRV_ERROR_ERRNO;
+ }
+ } else {
+ wd = opts->wd;
+ }
+
+ {
+ struct iovec *io_vector;
+ int iov_len = 5;
+ char nullbuff[] = "\0";
+ int j, i = 0, res;
+ Sint32 buffsz = 0, env_len = 0, argv_len = 0,
+ flags = (opts->use_stdio ? FORKER_FLAG_USE_STDIO : 0)
+ | (opts->exit_status ? FORKER_FLAG_EXIT_STATUS : 0)
+ | (opts->read_write & DO_READ ? FORKER_FLAG_DO_READ : 0)
+ | (opts->read_write & DO_WRITE ? FORKER_FLAG_DO_WRITE : 0);
+
+ /* count number of elements in environment */
+ while(new_environ[env_len] != NULL)
+ env_len++;
+ iov_len += 1 + env_len; /* num envs including size int */
+
+ /* count number of element in argument list */
+ if (opts->spawn_type == ERTS_SPAWN_EXECUTABLE) {
+ if (opts->argv != NULL) {
+ while(opts->argv[argv_len] != NULL)
+ argv_len++;
+ } else {
+ argv_len++;
+ }
+ iov_len += 1 + argv_len; /* num argvs including size int */
+ }
+
+ io_vector = erts_alloc_fnf(ERTS_ALC_T_TMP, sizeof(struct iovec) * iov_len);
+
+ if (!io_vector) {
+ close_pipes(ifd, ofd);
+ erts_smp_rwmtx_runlock(&environ_rwmtx);
+ erts_free(ERTS_ALC_T_TMP, (void *) cmd_line);
+ if (new_environ != environ)
+ erts_free(ERTS_ALC_T_ENVIRONMENT, (void *) new_environ);
+ errno = ENOMEM;
+ return ERL_DRV_ERROR_ERRNO;
+ }
+
+ io_vector[i].iov_base = (void*)&buffsz;
+ io_vector[i++].iov_len = sizeof(buffsz);
+
+ io_vector[i].iov_base = (void*)&flags;
+ flags = htonl(flags);
+ io_vector[i++].iov_len = sizeof(flags);
+ buffsz += sizeof(flags);
+
+ io_vector[i].iov_base = cmd_line;
+ io_vector[i++].iov_len = len;
+ buffsz += len;
+
+ io_vector[i].iov_base = wd;
+ io_vector[i].iov_len = strlen(io_vector[i].iov_base) + 1;
+ buffsz += io_vector[i++].iov_len;
+
+ io_vector[i].iov_base = nullbuff;
+ io_vector[i++].iov_len = 1;
+ buffsz += io_vector[i-1].iov_len;
+
+ io_vector[i].iov_base = (void*)&env_len;
+ env_len = htonl(env_len);
+ io_vector[i++].iov_len = sizeof(env_len);
+ buffsz += io_vector[i-1].iov_len;
+
+ for (j = 0; new_environ[j] != NULL; j++) {
+ io_vector[i].iov_base = new_environ[j];
+ io_vector[i++].iov_len = strlen(new_environ[j]) + 1;
+ buffsz += io_vector[i-1].iov_len;
+ }
+
+ /* only append arguments if this was a spawn_executable */
+ if (opts->spawn_type == ERTS_SPAWN_EXECUTABLE) {
+
+ io_vector[i].iov_base = (void*)&argv_len;
+ argv_len = htonl(argv_len);
+ io_vector[i++].iov_len = sizeof(argv_len);
+ buffsz += io_vector[i-1].iov_len;
+
+ if (opts->argv) {
+ /* If there are arguments we copy in the references to
+ them into the iov */
+ for (j = 0; opts->argv[j]; j++) {
+ if (opts->argv[j] == erts_default_arg0)
+ io_vector[i].iov_base = cmd_line;
+ else
+ io_vector[i].iov_base = opts->argv[j];
+ io_vector[i].iov_len = strlen(io_vector[i].iov_base) + 1;
+ buffsz += io_vector[i++].iov_len;
+ }
+ } else {
+ io_vector[i].iov_base = cmd_line;
+ io_vector[i].iov_len = strlen(io_vector[i].iov_base) + 1;
+ buffsz += io_vector[i++].iov_len;
+ }
+ }
+
+ /* we send the request to do the fork */
+ if ((res = writev(ofd[1], io_vector, iov_len > MAXIOV ? MAXIOV : iov_len)) < 0) {
+ if (errno == ERRNO_BLOCK) {
+ res = 0;
+ } else {
+ int err = errno;
+ close_pipes(ifd, ofd);
+ erts_free(ERTS_ALC_T_TMP, io_vector);
+ if (new_environ != environ)
+ erts_free(ERTS_ALC_T_ENVIRONMENT, (void *) new_environ);
+ erts_smp_rwmtx_runlock(&environ_rwmtx);
+ erts_free(ERTS_ALC_T_TMP, (void *) cmd_line);
+ errno = err;
+ return ERL_DRV_ERROR_ERRNO;
+ }
+ }
+
+ if (res < buffsz) {
+ /* we only wrote part of the command payload. Enqueue the rest. */
+ for (i = 0; i < iov_len; i++) {
+ driver_enq(port_num, io_vector[i].iov_base, io_vector[i].iov_len);
+ }
+ driver_deq(port_num, res);
+ driver_select(port_num, ofd[1], ERL_DRV_WRITE|ERL_DRV_USE, 1);
+ }
+
+ erts_free(ERTS_ALC_T_TMP, io_vector);
+ }
+
+ erts_free(ERTS_ALC_T_TMP, (void *) cmd_line);
+
+ if (new_environ != environ)
+ erts_free(ERTS_ALC_T_ENVIRONMENT, (void *) new_environ);
+
+ erts_smp_rwmtx_runlock(&environ_rwmtx);
+
+ dd = create_driver_data(port_num, ifd[0], ofd[1], opts->packet_bytes,
+ DO_WRITE | DO_READ, opts->exit_status,
+ 0, 0);
+
+ {
+ /* send ofd[0] + ifd[1] + stderrfd to forker port */
+ ErtsSysForkerProto *proto =
+ erts_alloc(ERTS_ALC_T_DRV_CTRL_DATA,
+ sizeof(ErtsSysForkerProto));
+ memset(proto, 0, sizeof(ErtsSysForkerProto));
+ proto->action = ErtsSysForkerProtoAction_Start;
+ proto->u.start.fds[0] = ofd[0];
+ proto->u.start.fds[1] = ifd[1];
+ proto->u.start.fds[2] = stderrfd;
+ proto->u.start.port_id = opts->exit_status ? erts_drvport2id(port_num) : THE_NON_VALUE;
+ if (erl_drv_port_control(forker_port, 'S', (char*)proto, sizeof(*proto))) {
+ /* The forker port has been killed, we close both fd's which will
+ make open_port throw an epipe error */
+ close(ofd[0]);
+ close(ifd[1]);
+ }
+ }
+
+ /* we set these fds to negative to mark if
+ they should be closed after the handshake */
+ if (!(opts->read_write & DO_READ))
+ dd->ifd->fd *= -1;
+
+ if (!(opts->read_write & DO_WRITE))
+ dd->ofd->fd *= -1;
+
+ return (ErlDrvData)dd;
+#undef CMD_LINE_PREFIX_STR
+#undef CMD_LINE_PREFIX_STR_SZ
+}
+
+static ErlDrvSSizeT spawn_control(ErlDrvData e, unsigned int cmd, char *buf,
+ ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen)
+{
+ ErtsSysDriverData *dd = (ErtsSysDriverData*)e;
+ ErtsSysForkerProto *proto = (ErtsSysForkerProto *)buf;
+
+ ASSERT(len == sizeof(*proto));
+ ASSERT(proto->action == ErtsSysForkerProtoAction_SigChld);
+
+ dd->status = proto->u.sigchld.error_number;
+ dd->alive = -1;
+
+ if (dd->ifd)
+ driver_select(dd->port_num, abs(dd->ifd->fd), ERL_DRV_READ | ERL_DRV_USE, 1);
+
+ if (dd->ofd)
+ driver_select(dd->port_num, abs(dd->ofd->fd), ERL_DRV_WRITE | ERL_DRV_USE, 1);
+
+ return 0;
+}
+
+#define FD_DEF_HEIGHT 24
+#define FD_DEF_WIDTH 80
+/* Control op */
+#define FD_CTRL_OP_GET_WINSIZE 100
+
+static int fd_get_window_size(int fd, Uint32 *width, Uint32 *height)
+{
+#ifdef TIOCGWINSZ
+ struct winsize ws;
+ if (ioctl(fd,TIOCGWINSZ,&ws) == 0) {
+ *width = (Uint32) ws.ws_col;
+ *height = (Uint32) ws.ws_row;
+ return 0;
+ }
+#endif
+ return -1;
+}
+
+static ErlDrvSSizeT fd_control(ErlDrvData drv_data,
+ unsigned int command,
+ char *buf, ErlDrvSizeT len,
+ char **rbuf, ErlDrvSizeT rlen)
+{
+ int fd = (int)(long)drv_data;
+ char resbuff[2*sizeof(Uint32)];
+ switch (command) {
+ case FD_CTRL_OP_GET_WINSIZE:
+ {
+ Uint32 w,h;
+ if (fd_get_window_size(fd,&w,&h))
+ return 0;
+ memcpy(resbuff,&w,sizeof(Uint32));
+ memcpy(resbuff+sizeof(Uint32),&h,sizeof(Uint32));
+ }
+ break;
+ default:
+ return 0;
+ }
+ if (rlen < 2*sizeof(Uint32)) {
+ *rbuf = driver_alloc(2*sizeof(Uint32));
+ }
+ memcpy(*rbuf,resbuff,2*sizeof(Uint32));
+ return 2*sizeof(Uint32);
+}
+
+static ErlDrvData fd_start(ErlDrvPort port_num, char* name,
+ SysDriverOpts* opts)
+{
+ int non_blocking = 0;
+
+ if (((opts->read_write & DO_READ) && opts->ifd >= sys_max_files()) ||
+ ((opts->read_write & DO_WRITE) && opts->ofd >= sys_max_files()))
+ return ERL_DRV_ERROR_GENERAL;
+
+ /*
+ * Historical:
+ *
+ * "Note about nonblocking I/O.
+ *
+ * At least on Solaris, setting the write end of a TTY to nonblocking,
+ * will set the input end to nonblocking as well (and vice-versa).
+ * If erl is run in a pipeline like this: cat | erl
+ * the input end of the TTY will be the standard input of cat.
+ * And cat is not prepared to handle nonblocking I/O."
+ *
+ * Actually, the reason for this is not that the tty itself gets set
+ * in non-blocking mode, but that the "input end" (cat's stdin) and
+ * the "output end" (erlang's stdout) are typically the "same" file
+ * descriptor, dup()'ed from a single fd by one of this process'
+ * ancestors.
+ *
+ * The workaround for this problem used to be a rather bad kludge,
+ * interposing an extra process ("internal cat") between erlang's
+ * stdout and the original stdout, allowing erlang to set its stdout
+ * in non-blocking mode without affecting the stdin of the preceding
+ * process in the pipeline - and being a kludge, it caused all kinds
+ * of weird problems.
+ *
+ * So, this is the current logic:
+ *
+ * The only reason to set non-blocking mode on the output fd at all is
+ * if it's something that can cause a write() to block, of course,
+ * i.e. primarily if it points to a tty, socket, pipe, or fifo.
+ *
+ * If we don't set non-blocking mode when we "should" have, and output
+ * becomes blocked, the entire runtime system will be suspended - this
+ * is normally bad of course, and can happen fairly "easily" - e.g. user
+ * hits ^S on tty - but doesn't necessarily happen.
+ *
+ * If we do set non-blocking mode when we "shouldn't" have, the runtime
+ * system will end up seeing EOF on the input fd (due to the preceding
+ * process dying), which typically will cause the entire runtime system
+ * to terminate immediately (due to whatever erlang process is seeing
+ * the EOF taking it as a signal to halt the system). This is *very* bad.
+ *
+ * I.e. we should take a conservative approach, and only set non-
+ * blocking mode when we a) need to, and b) are reasonably certain
+ * that it won't be a problem. And as in the example above, the problem
+ * occurs when input fd and output fd point to different "things".
+ *
+ * However, determining that they are not just the same "type" of
+ * "thing", but actually the same instance of that type of thing, is
+ * unreasonably complex in many/most cases.
+ *
+ * Also, with pipes, sockets, and fifos it's far from obvious that the
+ * user *wants* non-blocking output: If you're running erlang inside
+ * some complex pipeline, you're probably not running a real-time system
+ * that must never stop, but rather *want* it to suspend if the output
+ * channel is "full".
+ *
+ * So, the bottom line: We will only set the output fd non-blocking if
+ * it points to a tty, and either a) the input fd also points to a tty,
+ * or b) we can make sure that setting the output fd non-blocking
+ * doesn't interfere with someone else's input, via a somewhat milder
+ * kludge than the above.
+ *
+ * Also keep in mind that while this code is almost exclusively run as
+ * a result of an erlang open_port({fd,0,1}, ...), that isn't the only
+ * case - it can be called with any old pre-existing file descriptors,
+ * the relations between which (if they're even two) we can only guess
+ * at - still, we try our best...
+ *
+ * Added note OTP 18: Some systems seem to use stdout/stderr to log data
+ * using unix pipes, so we cannot allow the system to block on a write.
+ * Therefore we use an async thread to write the data to fd's that could
+ * not be set to non-blocking. When no async threads are available we
+ * fall back on the old behaviour.
+ *
+ * Also the guarantee about what is delivered to the OS has changed.
+ * Pre 18 the fd driver did no flushing of data before terminating.
+ * Now it does. This is because we want to be able to guarantee that things
+ * such as escripts and friends really have outputted all data before
+ * terminating. This could potentially block the termination of the system
+ * for a very long time, but if the user wants to terminate fast she should
+ * use erlang:halt with flush=false.
+ */
+
+ /* Try to figure out if we can use non-blocking writes */
+ if (opts->read_write & DO_WRITE) {
+
+ /* If we don't have a read end, all bets are off - no non-blocking. */
+ if (opts->read_write & DO_READ) {
+
+ if (isatty(opts->ofd)) { /* output fd is a tty:-) */
+
+ if (isatty(opts->ifd)) { /* input fd is also a tty */
+
+ /* To really do this "right", we should also check that
+ input and output fd point to the *same* tty - but
+ this seems like overkill; ttyname() isn't for free,
+ and this is a very common case - and it's hard to
+ imagine a scenario where setting non-blocking mode
+ here would cause problems - go ahead and do it. */
+
+ non_blocking = 1;
+ SET_NONBLOCKING(opts->ofd);
+
+ } else { /* output fd is a tty, input fd isn't */
+
+ /* This is a "problem case", but also common (see the
+ example above) - i.e. it makes sense to try a bit
+ harder before giving up on non-blocking mode: Try to
+ re-open the tty that the output fd points to, and if
+ successful replace the original one with the "new" fd
+ obtained this way, and set *that* one in non-blocking
+ mode. (Yes, this is a kludge.)
+
+ However, re-opening the tty may fail in a couple of
+ (unusual) cases:
+
+ 1) The name of the tty (or an equivalent one, i.e.
+ same major/minor number) can't be found, because
+ it actually lives somewhere other than /dev (or
+ wherever ttyname() looks for it), and isn't
+ equivalent to any of those that do live in the
+ "standard" place - this should be *very* unusual.
+
+ 2) Permissions on the tty don't allow us to open it -
+ it's perfectly possible to have an fd open to an
+ object whose permissions wouldn't allow us to open
+ it. This is not as unusual as it sounds, one case
+ is if the user has su'ed to someone else (not
+ root) - we have a read/write fd open to the tty
+ (because it has been inherited all the way down
+ here), but we have neither read nor write
+ permission for the tty.
+
+ In these cases, we finally give up, and don't set the
+ output fd in non-blocking mode. */
+
+ char *tty;
+ int nfd;
+
+ if ((tty = ttyname(opts->ofd)) != NULL &&
+ (nfd = open(tty, O_WRONLY)) != -1) {
+ dup2(nfd, opts->ofd);
+ close(nfd);
+ non_blocking = 1;
+ SET_NONBLOCKING(opts->ofd);
+ }
+ }
+ }
+ }
+ }
+ return (ErlDrvData)create_driver_data(port_num, opts->ifd, opts->ofd,
+ opts->packet_bytes,
+ opts->read_write, 0, -1,
+ !non_blocking);
+}
+
+static void clear_fd_data(ErtsSysFdData *fdd)
+{
+ if (fdd->sz > 0) {
+ erts_free(ERTS_ALC_T_FD_ENTRY_BUF, (void *) fdd->buf);
+ ASSERT(erts_smp_atomic_read_nob(&sys_misc_mem_sz) >= fdd->sz);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, -1*fdd->sz);
+ }
+ fdd->buf = NULL;
+ fdd->sz = 0;
+ fdd->remain = 0;
+ fdd->cpos = NULL;
+ fdd->psz = 0;
+}
+
+static void nbio_stop_fd(ErlDrvPort prt, ErtsSysFdData *fdd)
+{
+ driver_select(prt, abs(fdd->fd), DO_READ|DO_WRITE, 0);
+ clear_fd_data(fdd);
+ SET_BLOCKING(abs(fdd->fd));
+
+}
+
+static void fd_stop(ErlDrvData ev) /* Does not close the fds */
+{
+ ErtsSysDriverData* dd = (ErtsSysDriverData*)ev;
+ ErlDrvPort prt = dd->port_num;
+ int sz = sizeof(ErtsSysDriverData);
+
+#if FDBLOCK
+ if (dd->blocking) {
+ erts_free(ERTS_ALC_T_SYS_BLOCKING, dd->blocking);
+ dd->blocking = NULL;
+ sz += sizeof(ErtsSysBlocking);
+ }
+#endif
+
+ if (dd->ifd) {
+ sz += sizeof(ErtsSysFdData);
+ nbio_stop_fd(prt, dd->ifd);
+ }
+ if (dd->ofd && dd->ofd != dd->ifd) {
+ sz += sizeof(ErtsSysFdData);
+ nbio_stop_fd(prt, dd->ofd);
+ }
+
+ erts_free(ERTS_ALC_T_DRV_TAB, dd);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, -sz);
+}
+
+static void fd_flush(ErlDrvData ev)
+{
+ ErtsSysDriverData* dd = (ErtsSysDriverData*)ev;
+ if (!dd->terminating)
+ dd->terminating = 1;
+}
+
+static ErlDrvData vanilla_start(ErlDrvPort port_num, char* name,
+ SysDriverOpts* opts)
+{
+ int flags, fd;
+ ErlDrvData res;
+
+ flags = (opts->read_write == DO_READ ? O_RDONLY :
+ opts->read_write == DO_WRITE ? O_WRONLY|O_CREAT|O_TRUNC :
+ O_RDWR|O_CREAT);
+ if ((fd = open(name, flags, 0666)) < 0)
+ return ERL_DRV_ERROR_GENERAL;
+ if (fd >= sys_max_files()) {
+ close(fd);
+ return ERL_DRV_ERROR_GENERAL;
+ }
+ SET_NONBLOCKING(fd);
+
+ res = (ErlDrvData)(long)create_driver_data(port_num, fd, fd,
+ opts->packet_bytes,
+ opts->read_write, 0, -1, 0);
+ return res;
+}
+
+/* Note that driver_data[fd].ifd == fd if the port was opened for reading, */
+/* otherwise (i.e. write only) driver_data[fd].ofd = fd. */
+
+static void stop(ErlDrvData ev)
+{
+ ErtsSysDriverData* dd = (ErtsSysDriverData*)ev;
+ ErlDrvPort prt = dd->port_num;
+
+ if (dd->ifd) {
+ nbio_stop_fd(prt, dd->ifd);
+ driver_select(prt, abs(dd->ifd->fd), ERL_DRV_USE, 0); /* close(ifd); */
+ }
+
+ if (dd->ofd && dd->ofd != dd->ifd) {
+ nbio_stop_fd(prt, dd->ofd);
+ driver_select(prt, abs(dd->ofd->fd), ERL_DRV_USE, 0); /* close(ofd); */
+ }
+
+ erts_free(ERTS_ALC_T_DRV_TAB, dd);
+}
+
+/* used by fd_driver */
+static void outputv(ErlDrvData e, ErlIOVec* ev)
+{
+ ErtsSysDriverData *dd = (ErtsSysDriverData*)e;
+ ErlDrvPort ix = dd->port_num;
+ int pb = dd->packet_bytes;
+ int ofd = dd->ofd ? dd->ofd->fd : -1;
+ ssize_t n;
+ ErlDrvSizeT sz;
+ char lb[4];
+ char* lbp;
+ ErlDrvSizeT len = ev->size;
+
+ /* (len > ((unsigned long)-1 >> (4-pb)*8)) */
+ /* if (pb >= 0 && (len & (((ErlDrvSizeT)1 << (pb*8))) - 1) != len) {*/
+ if (((pb == 2) && (len > 0xffff)) || (pb == 1 && len > 0xff)) {
+ driver_failure_posix(ix, EINVAL);
+ return; /* -1; */
+ }
+ /* Handles 0 <= pb <= 4 only */
+ put_int32((Uint32) len, lb);
+ lbp = lb + (4-pb);
+
+ ev->iov[0].iov_base = lbp;
+ ev->iov[0].iov_len = pb;
+ ev->size += pb;
+
+ if (dd->blocking && FDBLOCK)
+ driver_pdl_lock(dd->blocking->pdl);
+
+ if ((sz = driver_sizeq(ix)) > 0) {
+ driver_enqv(ix, ev, 0);
+
+ if (dd->blocking && FDBLOCK)
+ driver_pdl_unlock(dd->blocking->pdl);
+
+ if (sz + ev->size >= (1 << 13))
+ set_busy_port(ix, 1);
+ }
+ else if (!dd->blocking || !FDBLOCK) {
+ /* We try to write directly if the fd in non-blocking */
+ int vsize = ev->vsize > MAX_VSIZE ? MAX_VSIZE : ev->vsize;
+
+ n = writev(ofd, (const void *) (ev->iov), vsize);
+ if (n == ev->size)
+ return; /* 0;*/
+ if (n < 0) {
+ if ((errno != EINTR) && (errno != ERRNO_BLOCK)) {
+ driver_failure_posix(ix, errno);
+ return; /* -1;*/
+ }
+ n = 0;
+ }
+ driver_enqv(ix, ev, n); /* n is the skip value */
+ driver_select(ix, ofd, ERL_DRV_WRITE|ERL_DRV_USE, 1);
+ }
+#if FDBLOCK
+ else {
+ if (ev->size != 0) {
+ driver_enqv(ix, ev, 0);
+ driver_pdl_unlock(dd->blocking->pdl);
+ driver_async(ix, &dd->blocking->pkey,
+ fd_async, dd, NULL);
+ } else {
+ driver_pdl_unlock(dd->blocking->pdl);
+ }
+ }
+#endif
+ /* return 0;*/
+}
+
+/* Used by spawn_driver and vanilla driver */
+static void output(ErlDrvData e, char* buf, ErlDrvSizeT len)
+{
+ ErtsSysDriverData *dd = (ErtsSysDriverData*)e;
+ ErlDrvPort ix = dd->port_num;
+ int pb = dd->packet_bytes;
+ int ofd = dd->ofd ? dd->ofd->fd : -1;
+ ssize_t n;
+ ErlDrvSizeT sz;
+ char lb[4];
+ char* lbp;
+ struct iovec iv[2];
+
+ /* (len > ((unsigned long)-1 >> (4-pb)*8)) */
+ if (((pb == 2) && (len > 0xffff))
+ || (pb == 1 && len > 0xff)
+ || dd->pid == 0 /* Attempt at output before port is ready */) {
+ driver_failure_posix(ix, EINVAL);
+ return; /* -1; */
+ }
+ put_int32(len, lb);
+ lbp = lb + (4-pb);
+
+ if ((sz = driver_sizeq(ix)) > 0) {
+ driver_enq(ix, lbp, pb);
+ driver_enq(ix, buf, len);
+ if (sz + len + pb >= (1 << 13))
+ set_busy_port(ix, 1);
+ }
+ else {
+ iv[0].iov_base = lbp;
+ iv[0].iov_len = pb; /* should work for pb=0 */
+ iv[1].iov_base = buf;
+ iv[1].iov_len = len;
+ n = writev(ofd, iv, 2);
+ if (n == pb+len)
+ return; /* 0; */
+ if (n < 0) {
+ if ((errno != EINTR) && (errno != ERRNO_BLOCK)) {
+ driver_failure_posix(ix, errno);
+ return; /* -1; */
+ }
+ n = 0;
+ }
+ if (n < pb) {
+ driver_enq(ix, lbp+n, pb-n);
+ driver_enq(ix, buf, len);
+ }
+ else {
+ n -= pb;
+ driver_enq(ix, buf+n, len-n);
+ }
+ driver_select(ix, ofd, ERL_DRV_WRITE|ERL_DRV_USE, 1);
+ }
+ return; /* 0; */
+}
+
+static int port_inp_failure(ErtsSysDriverData *dd, int res)
+ /* Result: 0 (eof) or -1 (error) */
+{
+ int err = errno;
+
+ ASSERT(res <= 0);
+ if (dd->ifd) {
+ driver_select(dd->port_num, dd->ifd->fd, ERL_DRV_READ|ERL_DRV_WRITE, 0);
+ clear_fd_data(dd->ifd);
+ }
+
+ if (dd->blocking && FDBLOCK) {
+ driver_pdl_lock(dd->blocking->pdl);
+ if (driver_sizeq(dd->port_num) > 0) {
+ driver_pdl_unlock(dd->blocking->pdl);
+ /* We have stuff in the output queue, so we just
+ set the state to terminating and wait for fd_async_ready
+ to terminate the port */
+ if (res == 0)
+ dd->terminating = 2;
+ else
+ dd->terminating = -err;
+ return 0;
+ }
+ driver_pdl_unlock(dd->blocking->pdl);
+ }
+
+ if (res == 0) {
+ if (dd->alive == 1) {
+ /*
+ * We have eof and want to report exit status, but the process
+ * hasn't exited yet. When it does ready_input will
+ * driver_select() this fd which will make sure that we get
+ * back here with dd->alive == -1 and dd->status set.
+ */
+ return 0;
+ }
+ else if (dd->alive == -1) {
+ int status = dd->status;
+
+ /* We need not be prepared for stopped/continued processes. */
+ if (WIFSIGNALED(status))
+ status = 128 + WTERMSIG(status);
+ else
+ status = WEXITSTATUS(status);
+ driver_report_exit(dd->port_num, status);
+ }
+ driver_failure_eof(dd->port_num);
+ } else if (dd->ifd) {
+ erl_drv_init_ack(dd->port_num, ERL_DRV_ERROR_ERRNO);
+ } else {
+ driver_failure_posix(dd->port_num, err);
+ }
+ return 0;
+}
+
+/* fd is the drv_data that is returned from the */
+/* initial start routine */
+/* ready_fd is the descriptor that is ready to read */
+
+static void ready_input(ErlDrvData e, ErlDrvEvent ready_fd)
+{
+ ErtsSysDriverData *dd = (ErtsSysDriverData*)e;
+ ErlDrvPort port_num;
+ int packet_bytes;
+ int res;
+ Uint h;
+
+ port_num = dd->port_num;
+ packet_bytes = dd->packet_bytes;
+
+ ASSERT(abs(dd->ifd->fd) == ready_fd);
+
+ if (dd->pid == 0) {
+ /* the pid is sent from erl_child_setup. spawn driver only. */
+ ErtsSysForkerProto proto;
+ int res;
+
+ if((res = read(ready_fd, &proto, sizeof(proto))) <= 0) {
+ /* hmm, child setup seems to have closed the pipe too early...
+ we close the port as there is not much else we can do */
+ if (res < 0 && errno == ERRNO_BLOCK)
+ return;
+ driver_select(port_num, ready_fd, ERL_DRV_READ, 0);
+ if (res == 0)
+ errno = EPIPE;
+ port_inp_failure(dd, -1);
+ return;
+ }
+
+ ASSERT(proto.action == ErtsSysForkerProtoAction_Go);
+ dd->pid = proto.u.go.os_pid;
+
+ if (dd->pid == -1) {
+ /* Setup failed! The only reason why this should happen is if
+ the fork fails. */
+ errno = proto.u.go.error_number;
+ port_inp_failure(dd, -1);
+ return;
+ }
+
+ proto.action = ErtsSysForkerProtoAction_Ack;
+
+ if (driver_sizeq(port_num) > 0) {
+ driver_enq(port_num, (char*)&proto, sizeof(proto));
+ } else {
+ if (write(abs(dd->ofd->fd), &proto, sizeof(proto)) < 0)
+ if (errno == ERRNO_BLOCK || errno == EINTR)
+ driver_enq(port_num, (char*)&proto, sizeof(proto));
+ /* do nothing on failure here. If the ofd is broken, then
+ the ifd will probably also be broken and trigger
+ a port_inp_failure */
+ }
+
+ if (dd->ifd->fd < 0) {
+ driver_select(port_num, abs(dd->ifd->fd), ERL_DRV_READ|ERL_DRV_USE, 0);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, -sizeof(ErtsSysFdData));
+ dd->ifd = NULL;
+ }
+
+ if (dd->ofd->fd < 0 || driver_sizeq(port_num) > 0)
+ /* we select in order to close fd or write to queue,
+ child setup will close this fd if fd < 0 */
+ driver_select(port_num, abs(dd->ofd->fd), ERL_DRV_WRITE|ERL_DRV_USE, 1);
+
+ erl_drv_set_os_pid(port_num, dd->pid);
+ erl_drv_init_ack(port_num, e);
+ return;
+ }
+
+ if (packet_bytes == 0) {
+ byte *read_buf = (byte *) erts_alloc(ERTS_ALC_T_SYS_READ_BUF,
+ ERTS_SYS_READ_BUF_SZ);
+ res = read(ready_fd, read_buf, ERTS_SYS_READ_BUF_SZ);
+ if (res < 0) {
+ if ((errno != EINTR) && (errno != ERRNO_BLOCK))
+ port_inp_failure(dd, res);
+ }
+ else if (res == 0)
+ port_inp_failure(dd, res);
+ else
+ driver_output(port_num, (char*) read_buf, res);
+ erts_free(ERTS_ALC_T_SYS_READ_BUF, (void *) read_buf);
+ }
+ else if (dd->ifd->remain > 0) { /* We try to read the remainder */
+ /* space is allocated in buf */
+ res = read(ready_fd, dd->ifd->cpos,
+ dd->ifd->remain);
+ if (res < 0) {
+ if ((errno != EINTR) && (errno != ERRNO_BLOCK))
+ port_inp_failure(dd, res);
+ }
+ else if (res == 0) {
+ port_inp_failure(dd, res);
+ }
+ else if (res == dd->ifd->remain) { /* we're done */
+ driver_output(port_num, dd->ifd->buf,
+ dd->ifd->sz);
+ clear_fd_data(dd->ifd);
+ }
+ else { /* if (res < dd->ifd->remain) */
+ dd->ifd->cpos += res;
+ dd->ifd->remain -= res;
+ }
+ }
+ else if (dd->ifd->remain == 0) { /* clean fd */
+ byte *read_buf = (byte *) erts_alloc(ERTS_ALC_T_SYS_READ_BUF,
+ ERTS_SYS_READ_BUF_SZ);
+ /* We make one read attempt and see what happens */
+ res = read(ready_fd, read_buf, ERTS_SYS_READ_BUF_SZ);
+ if (res < 0) {
+ if ((errno != EINTR) && (errno != ERRNO_BLOCK))
+ port_inp_failure(dd, res);
+ }
+ else if (res == 0) { /* eof */
+ port_inp_failure(dd, res);
+ }
+ else if (res < packet_bytes - dd->ifd->psz) {
+ memcpy(dd->ifd->pbuf+dd->ifd->psz,
+ read_buf, res);
+ dd->ifd->psz += res;
+ }
+ else { /* if (res >= packet_bytes) */
+ unsigned char* cpos = read_buf;
+ int bytes_left = res;
+
+ while (1) {
+ int psz = dd->ifd->psz;
+ char* pbp = dd->ifd->pbuf + psz;
+
+ while(bytes_left && (psz < packet_bytes)) {
+ *pbp++ = *cpos++;
+ bytes_left--;
+ psz++;
+ }
+
+ if (psz < packet_bytes) {
+ dd->ifd->psz = psz;
+ break;
+ }
+ dd->ifd->psz = 0;
+
+ switch (packet_bytes) {
+ case 1: h = get_int8(dd->ifd->pbuf); break;
+ case 2: h = get_int16(dd->ifd->pbuf); break;
+ case 4: h = get_int32(dd->ifd->pbuf); break;
+ default: ASSERT(0); return; /* -1; */
+ }
+
+ if (h <= (bytes_left)) {
+ driver_output(port_num, (char*) cpos, h);
+ cpos += h;
+ bytes_left -= h;
+ continue;
+ }
+ else { /* The last message we got was split */
+ char *buf = erts_alloc_fnf(ERTS_ALC_T_FD_ENTRY_BUF, h);
+ if (!buf) {
+ errno = ENOMEM;
+ port_inp_failure(dd, -1);
+ }
+ else {
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, h);
+ sys_memcpy(buf, cpos, bytes_left);
+ dd->ifd->buf = buf;
+ dd->ifd->sz = h;
+ dd->ifd->remain = h - bytes_left;
+ dd->ifd->cpos = buf + bytes_left;
+ }
+ break;
+ }
+ }
+ }
+ erts_free(ERTS_ALC_T_SYS_READ_BUF, (void *) read_buf);
+ }
+}
+
+
+/* fd is the drv_data that is returned from the */
+/* initial start routine */
+/* ready_fd is the descriptor that is ready to read */
+
+static void ready_output(ErlDrvData e, ErlDrvEvent ready_fd)
+{
+ ErtsSysDriverData *dd = (ErtsSysDriverData*)e;
+ ErlDrvPort ix = dd->port_num;
+ int n;
+ struct iovec* iv;
+ int vsize;
+
+ if ((iv = (struct iovec*) driver_peekq(ix, &vsize)) == NULL) {
+ driver_select(ix, ready_fd, ERL_DRV_WRITE, 0);
+ if (dd->pid > 0 && dd->ofd->fd < 0) {
+ /* The port was opened with 'in' option, which means we
+ should close the output fd as soon as the command has
+ been sent. */
+ driver_select(ix, ready_fd, ERL_DRV_WRITE|ERL_DRV_USE, 0);
+ erts_smp_atomic_add_nob(&sys_misc_mem_sz, -sizeof(ErtsSysFdData));
+ dd->ofd = NULL;
+ }
+ if (dd->terminating)
+ driver_failure_atom(dd->port_num,"normal");
+ return; /* 0; */
+ }
+ vsize = vsize > MAX_VSIZE ? MAX_VSIZE : vsize;
+ if ((n = writev(ready_fd, iv, vsize)) > 0) {
+ if (driver_deq(ix, n) == 0)
+ set_busy_port(ix, 0);
+ }
+ else if (n < 0) {
+ if (errno == ERRNO_BLOCK || errno == EINTR)
+ return; /* 0; */
+ else {
+ int res = errno;
+ driver_select(ix, ready_fd, ERL_DRV_WRITE, 0);
+ driver_failure_posix(ix, res);
+ return; /* -1; */
+ }
+ }
+ return; /* 0; */
+}
+
+static void stop_select(ErlDrvEvent fd, void* _)
+{
+ close((int)fd);
+}
+
+#if FDBLOCK
+
+static void
+fd_async(void *async_data)
+{
+ int res;
+ ErtsSysDriverData *dd = (ErtsSysDriverData *)async_data;
+ SysIOVec *iov0;
+ SysIOVec *iov;
+ int iovlen;
+ int err = 0;
+ /* much of this code is stolen from efile_drv:invoke_writev */
+ driver_pdl_lock(dd->blocking->pdl);
+ iov0 = driver_peekq(dd->port_num, &iovlen);
+ iovlen = iovlen < MAXIOV ? iovlen : MAXIOV;
+ iov = erts_alloc_fnf(ERTS_ALC_T_SYS_WRITE_BUF,
+ sizeof(SysIOVec)*iovlen);
+ if (!iov) {
+ res = -1;
+ err = ENOMEM;
+ driver_pdl_unlock(dd->blocking->pdl);
+ } else {
+ memcpy(iov,iov0,iovlen*sizeof(SysIOVec));
+ driver_pdl_unlock(dd->blocking->pdl);
+
+ do {
+ res = writev(dd->ofd->fd, iov, iovlen);
+ } while (res < 0 && errno == EINTR);
+ if (res < 0)
+ err = errno;
+ err = errno;
+
+ erts_free(ERTS_ALC_T_SYS_WRITE_BUF, iov);
+ }
+ dd->blocking->res = res;
+ dd->blocking->err = err;
+}
+
+void fd_ready_async(ErlDrvData drv_data,
+ ErlDrvThreadData thread_data) {
+ ErtsSysDriverData *dd = (ErtsSysDriverData *)thread_data;
+ ErlDrvPort port_num = dd->port_num;
+
+ ASSERT(dd->blocking);
+
+ if (dd->blocking->res > 0) {
+ driver_pdl_lock(dd->blocking->pdl);
+ if (driver_deq(port_num, dd->blocking->res) == 0) {
+ driver_pdl_unlock(dd->blocking->pdl);
+ set_busy_port(port_num, 0);
+ if (dd->terminating) {
+ /* The port is has been ordered to terminate
+ from either fd_flush or port_inp_failure */
+ if (dd->terminating == 1)
+ driver_failure_atom(port_num, "normal");
+ else if (dd->terminating == 2)
+ driver_failure_eof(port_num);
+ else if (dd->terminating < 0)
+ driver_failure_posix(port_num, -dd->terminating);
+ return; /* -1; */
+ }
+ } else {
+ driver_pdl_unlock(dd->blocking->pdl);
+ /* still data left to write in queue */
+ driver_async(port_num, &dd->blocking->pkey, fd_async, dd, NULL);
+ return /* 0; */;
+ }
+ } else if (dd->blocking->res < 0) {
+ if (dd->blocking->err == ERRNO_BLOCK) {
+ set_busy_port(port_num, 1);
+ /* still data left to write in queue */
+ driver_async(port_num, &dd->blocking->pkey, fd_async, dd, NULL);
+ } else
+ driver_failure_posix(port_num, dd->blocking->err);
+ return; /* -1; */
+ }
+ return; /* 0; */
+}
+
+#endif
+
+/* Forker driver */
+
+static int forker_fd;
+
+static ErlDrvData forker_start(ErlDrvPort port_num, char* name,
+ SysDriverOpts* opts)
+{
+
+ int i;
+ int fds[2];
+ int res, unbind;
+ char bindir[MAXPATHLEN];
+ size_t bindirsz = sizeof(bindir);
+ Uint csp_path_sz;
+ char *child_setup_prog;
+
+ forker_port = erts_drvport2id(port_num);
+
+ res = erts_sys_getenv_raw("BINDIR", bindir, &bindirsz);
+ if (res != 0) {
+ if (res < 0)
+ erts_exit(1,
+ "Environment variable BINDIR is not set\n");
+ if (res > 0)
+ erts_exit(1,
+ "Value of environment variable BINDIR is too large\n");
+ }
+ if (bindir[0] != DIR_SEPARATOR_CHAR)
+ erts_exit(1,
+ "Environment variable BINDIR does not contain an"
+ " absolute path\n");
+ csp_path_sz = (strlen(bindir)
+ + 1 /* DIR_SEPARATOR_CHAR */
+ + sizeof(CHILD_SETUP_PROG_NAME)
+ + 1);
+ child_setup_prog = erts_alloc(ERTS_ALC_T_CS_PROG_PATH, csp_path_sz);
+ erts_snprintf(child_setup_prog, csp_path_sz,
+ "%s%c%s",
+ bindir,
+ DIR_SEPARATOR_CHAR,
+ CHILD_SETUP_PROG_NAME);
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
+ erts_exit(ERTS_ABORT_EXIT,
+ "Could not open unix domain socket in spawn_init: %d\n",
+ errno);
+ }
+
+ forker_fd = fds[0];
+
+ unbind = erts_sched_bind_atfork_prepare();
+
+ i = fork();
+
+ if (i == 0) {
+ /* The child */
+ char *cs_argv[FORKER_ARGV_NO_OF_ARGS] =
+ {CHILD_SETUP_PROG_NAME, NULL, NULL};
+ char buff[128];
+
+ erts_sched_bind_atfork_child(unbind);
+
+ snprintf(buff, 128, "%d", sys_max_files());
+ cs_argv[FORKER_ARGV_MAX_FILES] = buff;
+
+ /* We preallocate fd 3 for the uds fd */
+ if (fds[1] != 3) {
+ dup2(fds[1], 3);
+ }
+
+#if defined(USE_SETPGRP_NOARGS) /* SysV */
+ (void) setpgrp();
+#elif defined(USE_SETPGRP) /* BSD */
+ (void) setpgrp(0, getpid());
+#else /* POSIX */
+ (void) setsid();
+#endif
+
+ execv(child_setup_prog, cs_argv);
+ _exit(1);
+ }
+
+ erts_sched_bind_atfork_parent(unbind);
+
+ erts_free(ERTS_ALC_T_CS_PROG_PATH, child_setup_prog);
+
+ close(fds[1]);
+
+ SET_NONBLOCKING(forker_fd);
+
+ driver_select(port_num, forker_fd, ERL_DRV_READ|ERL_DRV_USE, 1);
+
+ return (ErlDrvData)port_num;
+}
+
+static void forker_stop(ErlDrvData e)
+{
+ /* we probably should do something here,
+ the port has been closed by the user. */
+}
+
+static void forker_ready_input(ErlDrvData e, ErlDrvEvent fd)
+{
+ int res;
+ ErtsSysForkerProto *proto;
+
+ proto = erts_alloc(ERTS_ALC_T_DRV_CTRL_DATA, sizeof(*proto));
+
+ if ((res = read(fd, proto, sizeof(*proto))) < 0) {
+ if (errno == ERRNO_BLOCK)
+ return;
+ erts_exit(ERTS_DUMP_EXIT, "Failed to read from erl_child_setup: %d\n", errno);
+ }
+
+ if (res == 0)
+ erts_exit(ERTS_DUMP_EXIT, "erl_child_setup closed\n");
+
+ ASSERT(res == sizeof(*proto));
+
+#ifdef FORKER_PROTO_START_ACK
+ if (proto->action == ErtsSysForkerProtoAction_StartAck) {
+ /* Ideally we would like to not have to ack each Start
+ command being sent over the uds, but it would seem
+ that some operating systems (only observed on FreeBSD)
+ throw away data on the uds when the socket becomes full,
+ so we have to.
+ */
+ ErlDrvPort port_num = (ErlDrvPort)e;
+ int vlen;
+ SysIOVec *iov = driver_peekq(port_num, &vlen);
+ ErtsSysForkerProto *proto = (ErtsSysForkerProto *)iov[0].iov_base;
+
+ close(proto->u.start.fds[0]);
+ close(proto->u.start.fds[1]);
+ if (proto->u.start.fds[1] != proto->u.start.fds[2])
+ close(proto->u.start.fds[2]);
+
+ driver_deq(port_num, sizeof(*proto));
+
+ if (driver_sizeq(port_num) > 0)
+ driver_select(port_num, forker_fd, ERL_DRV_WRITE|ERL_DRV_USE, 1);
+ } else
+#endif
+ {
+ ASSERT(proto->action == ErtsSysForkerProtoAction_SigChld);
+
+ /* ideally this would be a port_command call, but as command is
+ already used by the spawn_driver, we use control instead.
+ Note that when using erl_drv_port_control it is an asynchronous
+ control. */
+ erl_drv_port_control(proto->u.sigchld.port_id, 'S',
+ (char*)proto, sizeof(*proto));
+ }
+
+}
+
+static void forker_ready_output(ErlDrvData e, ErlDrvEvent fd)
+{
+ ErlDrvPort port_num = (ErlDrvPort)e;
+
+#ifndef FORKER_PROTO_START_ACK
+ while (driver_sizeq(port_num) > 0) {
+#endif
+ int vlen;
+ SysIOVec *iov = driver_peekq(port_num, &vlen);
+ ErtsSysForkerProto *proto = (ErtsSysForkerProto *)iov[0].iov_base;
+ ASSERT(iov[0].iov_len >= (sizeof(*proto)));
+ if (sys_uds_write(forker_fd, (char*)proto, sizeof(*proto),
+ proto->u.start.fds, 3, 0) < 0) {
+ if (errno == ERRNO_BLOCK)
+ return;
+ erts_exit(ERTS_DUMP_EXIT, "Failed to write to erl_child_setup: %d\n", errno);
+ }
+#ifndef FORKER_PROTO_START_ACK
+ close(proto->u.start.fds[0]);
+ close(proto->u.start.fds[1]);
+ if (proto->u.start.fds[1] != proto->u.start.fds[2])
+ close(proto->u.start.fds[2]);
+ driver_deq(port_num, sizeof(*proto));
+ }
+#endif
+
+ driver_select(port_num, forker_fd, ERL_DRV_WRITE, 0);
+}
+
+static ErlDrvSSizeT forker_control(ErlDrvData e, unsigned int cmd, char *buf,
+ ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen)
+{
+ ErtsSysForkerProto *proto = (ErtsSysForkerProto *)buf;
+ ErlDrvPort port_num = (ErlDrvPort)e;
+ int res;
+
+ driver_enq(port_num, buf, len);
+ if (driver_sizeq(port_num) > sizeof(*proto)) {
+ return 0;
+ }
+
+ if ((res = sys_uds_write(forker_fd, (char*)proto, sizeof(*proto),
+ proto->u.start.fds, 3, 0)) < 0) {
+ if (errno == ERRNO_BLOCK) {
+ driver_select(port_num, forker_fd, ERL_DRV_WRITE|ERL_DRV_USE, 1);
+ return 0;
+ }
+ erts_exit(ERTS_DUMP_EXIT, "Failed to write to erl_child_setup: %d\n", errno);
+ }
+
+#ifndef FORKER_PROTO_START_ACK
+ ASSERT(res == sizeof(*proto));
+ close(proto->u.start.fds[0]);
+ close(proto->u.start.fds[1]);
+ if (proto->u.start.fds[1] != proto->u.start.fds[2])
+ close(proto->u.start.fds[2]);
+ driver_deq(port_num, sizeof(*proto));
+#endif
+
+ return 0;
+}
diff --git a/erts/emulator/sys/unix/sys_time.c b/erts/emulator/sys/unix/sys_time.c
index 95b3daa4ed..8ce02506ab 100644
--- a/erts/emulator/sys/unix/sys_time.c
+++ b/erts/emulator/sys/unix/sys_time.c
@@ -65,6 +65,8 @@
# include <fcntl.h>
#endif
+static void init_perf_counter(void);
+
/******************* Routines for time measurement *********************/
#undef ERTS_SYS_TIME_INTERNAL_STATE_WRITE_FREQ__
@@ -404,6 +406,8 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
# error Missing erts_os_system_time() implementation
#endif
+ init_perf_counter();
+
}
void
@@ -908,10 +912,120 @@ erts_os_times(ErtsMonotonicTime *mtimep, ErtsSystemTime *stimep)
#endif
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
+ * Performance counter functions *
+\* */
+
+
+/* What resolution to spin to in micro seconds */
+#define RESOLUTION 100
+/* How many iterations to spin */
+#define ITERATIONS 1
+/* How many significant figures to round to */
+#define SIGFIGS 3
+
+static ErtsSysPerfCounter calculate_perf_counter_unit(void) {
+ int i;
+ ErtsSysPerfCounter pre, post;
+ double value = 0;
+ double round_factor;
+#if defined(HAVE_GETHRTIME) && defined(GETHRTIME_WITH_CLOCK_GETTIME)
+ struct timespec basetime,comparetime;
+#define __GETTIME(arg) clock_gettime(CLOCK_MONOTONIC,arg)
+#define __GETUSEC(arg) (arg.tv_nsec / 1000)
+#else
+ SysTimeval basetime,comparetime;
+#define __GETTIME(arg) sys_gettimeofday(arg)
+#define __GETUSEC(arg) arg.tv_usec
+#endif
+
+ for (i = 0; i < ITERATIONS; i++) {
+ /* Make sure usec just flipped over at current resolution */
+ __GETTIME(&basetime);
+ do {
+ __GETTIME(&comparetime);
+ } while ((__GETUSEC(basetime) / RESOLUTION) == (__GETUSEC(comparetime) / RESOLUTION));
+
+ pre = erts_sys_perf_counter();
+
+ __GETTIME(&basetime);
+ do {
+ __GETTIME(&comparetime);
+ } while ((__GETUSEC(basetime) / RESOLUTION) == (__GETUSEC(comparetime) / RESOLUTION));
+
+ post = erts_sys_perf_counter();
+
+ value += post - pre;
+ }
+ /* After this value is ticks per us */
+ value /= (RESOLUTION*ITERATIONS);
+
+ /* We round to 3 significant figures */
+ round_factor = pow(10.0, SIGFIGS - ceil(log10(value)));
+ value = ((ErtsSysPerfCounter)(value * round_factor + 0.5)) / round_factor;
+
+ /* convert to ticks per second */
+ return 1000000 * value;
+}
+
+static int have_rdtscp(void)
+{
+#if defined(ETHR_X86_RUNTIME_CONF__)
+ /* On early x86 cpu's the tsc varies with the current speed of the cpu,
+ which means that the time per tick vary depending on the current
+ load of the cpu. We do not want this as it would give very scewed
+ numbers when the cpu is mostly idle.
+ The linux kernel seems to think that checking for constant and
+ reliable is enough to trust the counter so we do the same.
+
+ If this test is not good enough, I don't know what we'll do.
+ Maybe fallback on erts_sys_hrtime always, but that would be a shame as
+ rdtsc is about 3 times faster than hrtime... */
+ return ETHR_X86_RUNTIME_CONF_HAVE_CONSTANT_TSC__ &&
+ ETHR_X86_RUNTIME_CONF_HAVE_TSC_RELIABLE__;
+#else
+ return 0;
+#endif
+}
+
+static ErtsSysPerfCounter rdtsc(void)
+{
+ /* It may have been a good idea to put the cpuid instruction before
+ the rdtsc, but I decided against it because it is not really
+ needed for msacc, and it slows it down by quite a bit (5-7 times slower).
+ As a result though, this timestamp becomes much less
+ accurate as it might be re-ordered to be executed way before or after this
+ function is called.
+ */
+ ErtsSysPerfCounter ts;
+#if defined(__x86_64__)
+ __asm__ __volatile__ ("rdtsc\n\t"
+ "shl $32, %%rdx\n\t"
+ "or %%rdx, %0" : "=a" (ts) : : "rdx");
+#elif defined(__i386__)
+ __asm__ __volatile__ ("rdtsc\n\t"
+ : "=A" (ts) );
+#endif
+ return ts;
+}
+
+static void init_perf_counter(void)
+{
+ if (have_rdtscp()) {
+ erts_sys_time_data__.r.o.perf_counter = rdtsc;
+ erts_sys_time_data__.r.o.perf_counter_unit = calculate_perf_counter_unit();
+ } else {
+ erts_sys_time_data__.r.o.perf_counter = erts_sys_hrtime;
+ erts_sys_time_data__.r.o.perf_counter_unit = ERTS_HRTIME_UNIT;
+ }
+}
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifdef HAVE_GETHRVTIME_PROCFS_IOCTL
+/* The code below only has effect on solaris < 10,
+ needed in order for gehhrvtime to work properly */
int sys_start_hrvtime(void)
{
long msacct = PR_MSACCT;
diff --git a/erts/emulator/sys/unix/sys_uds.c b/erts/emulator/sys/unix/sys_uds.c
new file mode 100644
index 0000000000..015d0346a1
--- /dev/null
+++ b/erts/emulator/sys/unix/sys_uds.c
@@ -0,0 +1,155 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2002-2009. 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 "sys_uds.h"
+
+int
+sys_uds_readv(int fd, struct iovec *iov, size_t iov_len,
+ int *fds, int fd_count, int flags) {
+ struct msghdr msg;
+ struct cmsghdr *cmsg = NULL;
+ char ancillary_buff[256] = {0};
+ int res, i = 0;
+
+ /* setup a place to fill in message contents */
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_iov = iov;
+ msg.msg_iovlen = iov_len;
+
+ /* provide space for the ancillary data */
+ msg.msg_control = ancillary_buff;
+ msg.msg_controllen = sizeof(ancillary_buff);
+
+ if((res = recvmsg(fd, &msg, flags)) < 0) {
+#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__)
+ /* When some OS X versions run out of fd's
+ they give EMSGSIZE instead of EMFILE.
+ We remap this as we want the correct
+ error to appear for the user */
+ if (errno == EMSGSIZE)
+ errno = EMFILE;
+#endif
+ return res;
+ }
+
+ if((msg.msg_flags & MSG_CTRUNC) == MSG_CTRUNC)
+ {
+ /* We assume that we have given enough space for any header
+ that are sent to us. So the only remaining reason to get
+ this flag set is if the caller has run out of file descriptors.
+ */
+ errno = EMFILE;
+ return -1;
+ }
+
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg) ) {
+ if ((cmsg->cmsg_level == SOL_SOCKET) &&
+ (cmsg->cmsg_type == SCM_RIGHTS)) {
+ int *cmsg_data = (int *)CMSG_DATA(cmsg);
+ while ((char*)cmsg_data < (char*)cmsg + cmsg->cmsg_len) {
+ if (i < fd_count) {
+ fds[i++] = *cmsg_data++;
+ } else {
+ /* for some strange reason, we have received more FD's
+ than we wanted... close them if we are not running
+ debug. */
+ if(i >= fd_count) abort();
+ close(*cmsg_data++);
+ }
+ }
+ }
+ }
+
+ return res;
+}
+
+int
+sys_uds_read(int fd, char *buff, size_t len,
+ int *fds, int fd_count, int flags) {
+ struct iovec iov;
+ iov.iov_base = buff;
+ iov.iov_len = len;
+ return sys_uds_readv(fd, &iov, 1, fds, fd_count, flags);
+}
+
+
+int
+sys_uds_writev(int fd, struct iovec *iov, size_t iov_len,
+ int *fds, int fd_count, int flags) {
+
+ struct msghdr msg;
+ struct cmsghdr *cmsg = NULL;
+ int res, i;
+
+ /* initialize socket message */
+ memset(&msg, 0, sizeof(struct msghdr));
+
+ /* We flatten the iov if it is too long */
+ if (iov_len > MAXIOV) {
+ int size = 0;
+ char *buff;
+ for (i = 0; i < iov_len; i++)
+ size += iov[i].iov_len;
+ buff = malloc(size);
+
+ for (i = 0; i < iov_len; i++) {
+ memcpy(buff, iov[i].iov_base, iov[i].iov_len);
+ buff += iov[i].iov_len;
+ }
+
+ iov[0].iov_base = buff - size;
+ iov[0].iov_len = size;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ } else {
+ msg.msg_iov = iov;
+ msg.msg_iovlen = iov_len;
+ }
+
+ /* initialize the ancillary data */
+ msg.msg_control = calloc(1, CMSG_SPACE(sizeof(int) * fd_count));
+ msg.msg_controllen = CMSG_SPACE(sizeof(int) * fd_count);
+
+ /* copy the fd array into the ancillary data */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ if(!cmsg) abort();
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fd_count);
+ memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * fd_count);
+
+ res = sendmsg(fd, &msg, flags);
+
+ if (iov_len > MAXIOV)
+ free(iov[0].iov_base);
+
+ free(msg.msg_control);
+
+ return res;
+}
+
+int
+sys_uds_write(int fd, char *buff, size_t len,
+ int *fds, int fd_count, int flags) {
+ struct iovec iov;
+ iov.iov_base = buff;
+ iov.iov_len = len;
+ return sys_uds_writev(fd, &iov, 1, fds, fd_count, flags);
+}
diff --git a/erts/emulator/sys/unix/sys_uds.h b/erts/emulator/sys/unix/sys_uds.h
new file mode 100644
index 0000000000..844a2804d8
--- /dev/null
+++ b/erts/emulator/sys/unix/sys_uds.h
@@ -0,0 +1,57 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2002-2009. 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%
+ */
+
+#ifndef _ERL_UNIX_UDS_H
+#define _ERL_UNIX_UDS_H
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#if defined(__sun__) && !defined(_XOPEN_SOURCE)
+#define _XOPEN_SOURCE 500
+#endif
+
+#include <limits.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#if defined IOV_MAX
+#define MAXIOV IOV_MAX
+#elif defined UIO_MAXIOV
+#define MAXIOV UIO_MAXIOV
+#else
+#define MAXIOV 16
+#endif
+
+#include "sys.h"
+
+int sys_uds_readv(int fd, struct iovec *iov, size_t iov_len,
+ int *fds, int fd_count, int flags);
+int sys_uds_read(int fd, char *buff, size_t len,
+ int *fds, int fd_count, int flags);
+int sys_uds_writev(int fd, struct iovec *iov, size_t iov_len,
+ int *fds, int fd_count, int flags);
+int sys_uds_write(int fd, char *buff, size_t len,
+ int *fds, int fd_count, int flags);
+
+#endif /* #ifndef _ERL_UNIX_UDS_H */
diff --git a/erts/emulator/sys/win32/erl_poll.c b/erts/emulator/sys/win32/erl_poll.c
index 547d4b1d21..9c1bef5f4f 100644
--- a/erts/emulator/sys/win32/erl_poll.c
+++ b/erts/emulator/sys/win32/erl_poll.c
@@ -27,6 +27,7 @@
#include "erl_alloc.h"
#include "erl_poll.h"
#include "erl_time.h"
+#include "erl_msacc.h"
/*
* Some debug macros
@@ -1188,16 +1189,19 @@ int erts_poll_wait(ErtsPollSet ps,
if (timeout > 0 && !erts_atomic32_read_nob(&break_waiter_state)) {
HANDLE harr[2] = {ps->event_io_ready, break_happened_event};
int num_h = 2;
+ ERTS_MSACC_PUSH_STATE_M();
HARDDEBUGF(("Start waiting %d [%d]",num_h, (int) timeout));
ERTS_POLLSET_UNLOCK(ps);
#ifdef ERTS_SMP
erts_thr_progress_prepare_wait(NULL);
#endif
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_SLEEP);
WaitForMultipleObjects(num_h, harr, FALSE, timeout);
#ifdef ERTS_SMP
erts_thr_progress_finalize_wait(NULL);
#endif
+ ERTS_MSACC_POP_STATE_M();
ERTS_POLLSET_LOCK(ps);
HARDDEBUGF(("Stop waiting %d [%d]",num_h, (int) timeout));
woke_up(ps);
diff --git a/erts/emulator/sys/win32/erl_win_sys.h b/erts/emulator/sys/win32/erl_win_sys.h
index 7e8dd8a4ca..99c1066ab3 100644
--- a/erts/emulator/sys/win32/erl_win_sys.h
+++ b/erts/emulator/sys/win32/erl_win_sys.h
@@ -183,6 +183,7 @@ typedef LONGLONG ErtsSysHrTime;
#endif
typedef ErtsMonotonicTime ErtsSystemTime;
+typedef ErtsMonotonicTime ErtsSysPerfCounter;
ErtsSystemTime erts_os_system_time(void);
@@ -213,6 +214,7 @@ ERTS_GLB_INLINE ErtsMonotonicTime erts_os_monotonic_time(void);
ERTS_GLB_INLINE void erts_os_times(ErtsMonotonicTime *,
ErtsSystemTime *);
ERTS_GLB_INLINE ErtsSysHrTime erts_sys_hrtime(void);
+ERTS_GLB_INLINE ErtsSysPerfCounter erts_sys_perf_counter(void);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
@@ -234,6 +236,18 @@ erts_sys_hrtime(void)
return (*erts_sys_time_data__.r.o.sys_hrtime)();
}
+ERTS_GLB_INLINE ErtsSysPerfCounter
+erts_sys_perf_counter(void)
+{
+ return (*erts_sys_time_data__.r.o.sys_hrtime)();
+}
+
+ERTS_GLB_INLINE ErtsSysPerfCounter
+erts_sys_perf_counter_unit(void)
+{
+ return 1000 * 1000 * 1000;
+}
+
#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
extern void sys_gettimeofday(SysTimeval *tv);
diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c
index 37d3e16256..ea7523ddc2 100644
--- a/erts/emulator/sys/win32/sys.c
+++ b/erts/emulator/sys/win32/sys.c
@@ -1334,10 +1334,8 @@ spawn_start(ErlDrvPort port_num, char* utf8_name, SysDriverOpts* opts)
retval = set_driver_data(dp, hFromChild, hToChild, opts->read_write,
opts->exit_status);
if (retval != ERL_DRV_ERROR_GENERAL && retval != ERL_DRV_ERROR_ERRNO) {
- Port *prt = erts_drvport2port(port_num);
- /* We assume that this cannot generate a negative number */
- ASSERT(prt != ERTS_INVALID_ERL_DRV_PORT);
- prt->os_pid = (SWord) pid;
+ /* We assume that this cannot generate a negative number */
+ erl_drv_set_os_pid(port_num, pid);
}
}
@@ -1528,8 +1526,8 @@ create_child_process
* Parse out the program name from the command line (it can be quoted and
* contain spaces).
*/
- newcmdline = (wchar_t *) erts_alloc(ERTS_ALC_T_TMP, 2048*sizeof(wchar_t));
cmdlength = parse_command(origcmd);
+ newcmdline = (wchar_t *) erts_alloc(ERTS_ALC_T_TMP, (MAX_PATH+wcslen(origcmd)-cmdlength)*sizeof(wchar_t));
thecommand = (wchar_t *) erts_alloc(ERTS_ALC_T_TMP, (cmdlength+1)*sizeof(wchar_t));
wcsncpy(thecommand, origcmd, cmdlength);
thecommand[cmdlength] = L'\0';
@@ -3273,6 +3271,12 @@ void erl_sys_init(void)
}
void
+erl_sys_late_init(void)
+{
+ /* do nothing */
+}
+
+void
erts_sys_schedule_interrupt(int set)
{
erts_check_io_interrupt(set);
diff --git a/erts/emulator/sys/win32/sys_time.c b/erts/emulator/sys/win32/sys_time.c
index 3cf7f7cf07..9a9d90610d 100644
--- a/erts/emulator/sys/win32/sys_time.c
+++ b/erts/emulator/sys/win32/sys_time.c
@@ -397,6 +397,7 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
erts_sys_time_data__.r.o.os_monotonic_time = os_mtime_func;
erts_sys_time_data__.r.o.os_times = os_times_func;
+ erts_sys_time_data__.r.o.sys_hrtime = sys_hrtime_func;
init_resp->os_monotonic_time_unit = time_unit;
init_resp->have_os_monotonic_time = 1;
init_resp->have_corrected_os_monotonic_time = 0;
diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile
index 77614d455c..318db4b45e 100644
--- a/erts/emulator/test/Makefile
+++ b/erts/emulator/test/Makefile
@@ -74,11 +74,13 @@ MODULES= \
match_spec_SUITE \
module_info_SUITE \
monitor_SUITE \
+ multi_load_SUITE \
nested_SUITE \
nif_SUITE \
node_container_SUITE \
nofrag_SUITE \
num_bif_SUITE \
+ message_queue_data_SUITE \
op_SUITE \
port_SUITE \
port_bif_SUITE \
@@ -157,7 +159,7 @@ RELSYSDIR = $(RELEASE_PATH)/emulator_test
# FLAGS
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_COMPILE_FLAGS +=
# ----------------------------------------------------
# Targets
diff --git a/erts/emulator/test/a_SUITE.erl b/erts/emulator/test/a_SUITE.erl
index 16f060fe34..5b3a213154 100644
--- a/erts/emulator/test/a_SUITE.erl
+++ b/erts/emulator/test/a_SUITE.erl
@@ -27,68 +27,43 @@
%%%-------------------------------------------------------------------
-module(a_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2, long_timers/1, pollset_size/1]).
+-export([all/0, suite/0,
+ long_timers/1, pollset_size/1]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]}].
all() ->
[long_timers, pollset_size].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-long_timers(doc) ->
- [];
-long_timers(suite) ->
- [];
long_timers(Config) when is_list(Config) ->
- Dir = ?config(data_dir, Config),
- ?line long_timers_test:start(Dir),
- ?line {comment,
- "Testcase started! This test will run in parallel with the "
- "erts testsuite and ends in the z_SUITE:long_timers testcase."}.
+ Dir = proplists:get_value(data_dir, Config),
+ long_timers_test:start(Dir),
+ {comment, "Testcase started! This test will run in parallel with the "
+ "erts testsuite and ends in the z_SUITE:long_timers testcase."}.
-pollset_size(doc) ->
- [];
-pollset_size(suite) ->
- [];
pollset_size(Config) when is_list(Config) ->
%% Ensure inet_gethost_native port program started, in order to
%% allow other suites to use it...
inet_gethost_native:gethostbyname("localhost"),
- ?line Parent = self(),
- ?line Go = make_ref(),
- ?line spawn(fun () ->
- Name = pollset_size_testcase_initial_state_holder,
- true = register(Name, self()),
- ChkIo = get_check_io_info(),
- io:format("Initial: ~p~n", [ChkIo]),
- Parent ! Go,
- receive
- {get_initial_check_io_result, Pid} ->
- Pid ! {initial_check_io_result, ChkIo}
- end
- end),
- ?line receive Go -> ok end,
- ?line {comment,
- "Testcase started! This test will run in parallel with the "
- "erts testsuite and ends in the z_SUITE:pollset_size testcase."}.
+ Parent = self(),
+ Go = make_ref(),
+ spawn(fun () ->
+ Name = pollset_size_testcase_initial_state_holder,
+ true = register(Name, self()),
+ ChkIo = get_check_io_info(),
+ io:format("Initial: ~p~n", [ChkIo]),
+ Parent ! Go,
+ receive
+ {get_initial_check_io_result, Pid} ->
+ Pid ! {initial_check_io_result, ChkIo}
+ end
+ end),
+ receive Go -> ok end,
+ {comment, "Testcase started! This test will run in parallel with the "
+ "erts testsuite and ends in the z_SUITE:pollset_size testcase."}.
%%
%% Internal functions...
@@ -106,5 +81,3 @@ display_check_io(ChkIo) ->
get_check_io_info() ->
z_SUITE:get_check_io_info().
-
-
diff --git a/erts/emulator/test/after_SUITE.erl b/erts/emulator/test/after_SUITE.erl
index 5017a83185..a72cd8deea 100644
--- a/erts/emulator/test/after_SUITE.erl
+++ b/erts/emulator/test/after_SUITE.erl
@@ -22,92 +22,66 @@
%% Tests receive after.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
+-export([all/0, suite/0,
t_after/1, receive_after/1, receive_after_big/1,
receive_after_errors/1, receive_var_zero/1, receive_zero/1,
multi_timeout/1, receive_after_32bit/1,
receive_after_blast/1]).
--export([init_per_testcase/2, end_per_testcase/2]).
-
%% Internal exports.
-export([timeout_g/0]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 4}}].
all() ->
[t_after, receive_after, receive_after_big,
receive_after_errors, receive_var_zero, receive_zero,
multi_timeout, receive_after_32bit, receive_after_blast].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?t:timetrap(?t:minutes(3)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
%% Tests for an old round-off error in 'receive after'."
t_after(Config) when is_list(Config) ->
- ?line spawn(fun frequent_process/0),
- ?line Period = test_server:minutes(1),
- ?line Before = erlang:monotonic_time(),
+ spawn(fun frequent_process/0),
+ Period = test_server:minutes(1),
+ Before = erlang:monotonic_time(),
receive
- after Period ->
- ?line After = erlang:monotonic_time(),
- ?line report(Period, Before, After)
- end.
+ after Period ->
+ After = erlang:monotonic_time(),
+ report(Period, Before, After)
+ end.
report(Period, Before, After) ->
case erlang:convert_time_unit(After - Before, native, 100*1000) / Period of
- Percent when Percent > 100.10 ->
- test_server:fail({too_inaccurate, Percent});
- Percent when Percent < 100.0 ->
- test_server:fail({too_early, Percent});
- Percent ->
- Comment = io_lib:format("Elapsed/expected: ~.2f %", [Percent]),
- {comment, lists:flatten(Comment)}
+ Percent when Percent > 100.10 ->
+ ct:fail({too_inaccurate, Percent});
+ Percent when Percent < 100.0 ->
+ ct:fail({too_early, Percent});
+ Percent ->
+ Comment = io_lib:format("Elapsed/expected: ~.2f %", [Percent]),
+ {comment, lists:flatten(Comment)}
end.
frequent_process() ->
receive
- after 100 ->
- ?line frequent_process()
- end.
+ after 100 ->
+ frequent_process()
+ end.
-receive_after(doc) ->
- "Test that 'receive after' works (doesn't hang). "
- "The test takes 10 seconds to complete.";
+%% Test that 'receive after' works (doesn't hang).
+%% The test takes 10 seconds to complete.
receive_after(Config) when is_list(Config) ->
- ?line receive_after1(5000).
+ receive_after1(5000).
receive_after1(1) ->
- ?line io:format("Testing: receive after ~p~n", [1]),
- ?line receive after 1 -> ok end;
+ io:format("Testing: receive after ~p~n", [1]),
+ receive after 1 -> ok end;
receive_after1(N) ->
- ?line io:format("Testing: receive after ~p~n", [N]),
- ?line receive after N -> receive_after1(N div 2) end.
+ io:format("Testing: receive after ~p~n", [N]),
+ receive after N -> receive_after1(N div 2) end.
receive_after_big(Config) when is_list(Config) ->
%% Test that 'receive after' with a 32 bit number works.
@@ -119,14 +93,14 @@ receive_after_big1(Timeout) ->
erlang:yield(),
spawn(fun() -> Self ! here_is_a_message end),
ok = receive
- here_is_a_message ->
- ok
- after Timeout ->
- %% We test that the timeout can be set,
- %% not that an timeout occurs after the appropriate delay
- %% (48 days, 56 minutes, 48 seconds)!
- timeout
- end.
+ here_is_a_message ->
+ ok
+ after Timeout ->
+ %% We test that the timeout can be set,
+ %% not that an timeout occurs after the appropriate delay
+ %% (48 days, 56 minutes, 48 seconds)!
+ timeout
+ end.
receive_after_big2() ->
Self = self(),
@@ -147,38 +121,38 @@ receive_after_big2() ->
%% Test error cases for 'receive after'.
receive_after_errors(Config) when is_list(Config) ->
- ?line ?TryAfter(-1),
- ?line ?TryAfter(0.0),
- ?line ?TryAfter(3.14),
- ?line ?TryAfter(16#100000000),
- ?line ?TryAfter(392347129847294724972398472984729847129874),
- ?line ?TryAfter(16#3fffffffffffffff),
- ?line ?TryAfter(16#ffffffffffffffff),
- ?line ?TryAfter(-16#100000000),
- ?line ?TryAfter(-3891278094774921784123987129848),
- ?line ?TryAfter(xxx),
+ ?TryAfter(-1),
+ ?TryAfter(0.0),
+ ?TryAfter(3.14),
+ ?TryAfter(16#100000000),
+ ?TryAfter(392347129847294724972398472984729847129874),
+ ?TryAfter(16#3fffffffffffffff),
+ ?TryAfter(16#ffffffffffffffff),
+ ?TryAfter(-16#100000000),
+ ?TryAfter(-3891278094774921784123987129848),
+ ?TryAfter(xxx),
ok.
try_after(Timeout) ->
{'EXIT',{timeout_value,_}} = (catch receive after Timeout -> ok end).
-receive_var_zero(doc) -> "Test 'after Z', when Z == 0.";
+%% Test 'after Z', when Z == 0.
receive_var_zero(Config) when is_list(Config) ->
self() ! x,
self() ! y,
Z = zero(),
timeout = receive
- z -> ok
- after Z -> timeout
- end,
+ z -> ok
+ after Z -> timeout
+ end,
timeout = receive
- after Z -> timeout
- end,
+ after Z -> timeout
+ end,
self() ! w,
receive
x -> ok;
Other ->
- ?line ?t:fail({bad_message,Other})
+ ct:fail({bad_message,Other})
end.
zero() -> 0.
@@ -188,44 +162,43 @@ receive_zero(Config) when is_list(Config) ->
self() ! x,
self() ! y,
timeout = receive
- z -> ok
- after 0 ->
- timeout
- end,
+ z -> ok
+ after 0 ->
+ timeout
+ end,
self() ! w,
timeout = receive
after 0 -> timeout
end,
receive
- x -> ok;
- Other ->
- ?line ?t:fail({bad_message,Other})
+ x -> ok;
+ Other ->
+ ct:fail({bad_message,Other})
end.
-multi_timeout(doc) ->
- "Test for catching invalid assertion in erl_message.c (in queue_message)."
- "This failed (dumped core) with debug-compiled emulator.";
+%% Test for catching invalid assertion in erl_message.c (in queue_message)
+%% This failed (dumped core) with debug-compiled emulator.
multi_timeout(Config) when is_list(Config) ->
- ?line P = spawn(?MODULE, timeout_g, []),
- ?line P ! a,
- ?line P ! b,
- ?line receive
- after 1000 -> ok
- end,
- ?line P ! c,
- ?line receive
- after 1000 -> ok
- end,
- ?line P ! d,
+ P = spawn(?MODULE, timeout_g, []),
+ P ! a,
+ P ! b,
+ receive
+ after 1000 -> ok
+ end,
+ P ! c,
+ receive
+ after 1000 -> ok
+ end,
+ P ! d,
ok.
timeout_g() ->
- ?line receive
- a -> ok
+ receive
+ a -> ok
+ end,
+ receive
+ after 100000 -> ok
end,
- ?line receive
- after 100000 -> ok
- end,
ok.
%% OTP-7493: Timeout for 32 bit numbers (such as 16#ffffFFFF) could
@@ -264,8 +237,8 @@ receive_after_blast(Config) when is_list(Config) ->
TimeoutTime = erlang:monotonic_time(milli_seconds) + 5000,
lists:foreach(fun ({P, _}) -> P ! {go, TimeoutTime} end, PMs),
lists:foreach(fun ({P, M}) ->
- receive
- {'DOWN', M, process, P, normal} ->
- ok
- end
- end, PMs).
+ receive
+ {'DOWN', M, process, P, normal} ->
+ ok
+ end
+ end, PMs).
diff --git a/erts/emulator/test/alloc_SUITE.erl b/erts/emulator/test/alloc_SUITE.erl
index aa6a1fbcdc..1f690c5015 100644
--- a/erts/emulator/test/alloc_SUITE.erl
+++ b/erts/emulator/test/alloc_SUITE.erl
@@ -19,8 +19,7 @@
-module(alloc_SUITE).
-author('[email protected]').
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
+-export([all/0, suite/0, init_per_testcase/2, end_per_testcase/2]).
-export([basic/1,
coalesce/1,
@@ -34,42 +33,20 @@
cpool/1,
migration/1]).
--export([init_per_testcase/2, end_per_testcase/2]).
+-include_lib("common_test/include/ct.hrl").
--include_lib("test_server/include/test_server.hrl").
-
--define(DEFAULT_TIMETRAP_SECS, 240).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 4}}].
all() ->
[basic, coalesce, threads, realloc_copy, bucket_index,
bucket_mask, rbtree, mseg_clear_cache, erts_mmap, cpool, migration].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-
init_per_testcase(Case, Config) when is_list(Config) ->
- Dog = ?t:timetrap(?t:seconds(?DEFAULT_TIMETRAP_SECS)),
- [{watchdog, Dog}, {testcase, Case}, {debug,false} | Config].
+ [{testcase, Case},{debug,false}|Config].
end_per_testcase(_Case, Config) when is_list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -77,41 +54,23 @@ end_per_testcase(_Case, Config) when is_list(Config) ->
%% Testcases %%
%% %%
-basic(suite) -> [];
-basic(doc) -> [];
-basic(Cfg) -> ?line drv_case(Cfg).
+basic(Cfg) -> drv_case(Cfg).
-coalesce(suite) -> [];
-coalesce(doc) -> [];
-coalesce(Cfg) -> ?line drv_case(Cfg).
+coalesce(Cfg) -> drv_case(Cfg).
-threads(suite) -> [];
-threads(doc) -> [];
-threads(Cfg) -> ?line drv_case(Cfg).
+threads(Cfg) -> drv_case(Cfg).
-realloc_copy(suite) -> [];
-realloc_copy(doc) -> [];
-realloc_copy(Cfg) -> ?line drv_case(Cfg).
+realloc_copy(Cfg) -> drv_case(Cfg).
-bucket_index(suite) -> [];
-bucket_index(doc) -> [];
-bucket_index(Cfg) -> ?line drv_case(Cfg).
+bucket_index(Cfg) -> drv_case(Cfg).
-bucket_mask(suite) -> [];
-bucket_mask(doc) -> [];
-bucket_mask(Cfg) -> ?line drv_case(Cfg).
+bucket_mask(Cfg) -> drv_case(Cfg).
-rbtree(suite) -> [];
-rbtree(doc) -> [];
-rbtree(Cfg) -> ?line drv_case(Cfg).
+rbtree(Cfg) -> drv_case(Cfg).
-mseg_clear_cache(suite) -> [];
-mseg_clear_cache(doc) -> [];
-mseg_clear_cache(Cfg) -> ?line drv_case(Cfg).
+mseg_clear_cache(Cfg) -> drv_case(Cfg).
-cpool(suite) -> [];
-cpool(doc) -> [];
-cpool(Cfg) -> ?line drv_case(Cfg).
+cpool(Cfg) -> drv_case(Cfg).
migration(Cfg) ->
case erlang:system_info(smp_support) of
@@ -122,15 +81,12 @@ migration(Cfg) ->
end.
erts_mmap(Config) when is_list(Config) ->
- case {?t:os_type(), is_halfword_vm()} of
- {{unix, _}, false} ->
+ case test_server:os_type() of
+ {unix, _} ->
[erts_mmap_do(Config, SCO, SCRPM, SCRFSD)
|| SCO <-[true,false], SCRFSD <-[1234,0], SCRPM <- [true,false]];
-
- {_,true} ->
- {skipped, "No supercarrier support on halfword vm"};
{SkipOs,_} ->
- ?line {skipped,
+ {skipped,
lists:flatten(["Not run on "
| io_lib:format("~p",[SkipOs])])}
end.
@@ -188,28 +144,28 @@ drv_case(Config) ->
drv_case(Config, one_shot, "").
drv_case(Config, Mode, NodeOpts) when is_list(Config) ->
- case ?t:os_type() of
+ case test_server:os_type() of
{Family, _} when Family == unix; Family == win32 ->
- ?line {ok, Node} = start_node(Config, NodeOpts),
- ?line Self = self(),
- ?line Ref = make_ref(),
- ?line spawn_link(Node,
+ {ok, Node} = start_node(Config, NodeOpts),
+ Self = self(),
+ Ref = make_ref(),
+ spawn_link(Node,
fun () ->
Res = run_drv_case(Config, Mode),
Self ! {Ref, Res}
end),
- ?line Result = receive {Ref, Rslt} -> Rslt end,
- ?line stop_node(Node),
- ?line Result;
+ Result = receive {Ref, Rslt} -> Rslt end,
+ stop_node(Node),
+ Result;
SkipOs ->
- ?line {skipped,
+ {skipped,
lists:flatten(["Not run on "
| io_lib:format("~p",[SkipOs])])}
end.
run_drv_case(Config, Mode) ->
- DataDir = ?config(data_dir,Config),
- CaseName = ?config(testcase,Config),
+ DataDir = proplists:get_value(data_dir,Config),
+ CaseName = proplists:get_value(testcase,Config),
File = filename:join(DataDir, CaseName),
{ok,CaseName,Bin} = compile:file(File, [binary,return_errors]),
{module,CaseName} = erlang:load_module(CaseName,Bin),
@@ -269,7 +225,6 @@ print_stats(migration) ->
io:format("Number of blocks : ~p\n", [Btot]),
io:format("Number of carriers: ~p\n", [Ctot]);
-
print_stats(_) -> ok.
tuple_add(T1, T2) ->
@@ -341,7 +296,7 @@ repeat_while_loop(Fun, TRef, I) ->
flush_log() ->
receive
{print, Str} ->
- ?t:format("~s", [Str]),
+ io:format("~s", [Str]),
flush_log()
after 0 ->
ok
@@ -351,23 +306,23 @@ handle_result(_State, Result0) ->
flush_log(),
case Result0 of
{'EXIT', Error} ->
- ?line ?t:fail(Error);
+ ct:fail(Error);
{'EXIT', error, Error} ->
- ?line ?t:fail(Error);
+ ct:fail(Error);
{failed, Comment} ->
- ?line ?t:fail(Comment);
+ ct:fail(Comment);
{skipped, Comment} ->
- ?line {skipped, Comment};
+ {skipped, Comment};
{succeeded, ""} ->
- ?line succeeded;
+ succeeded;
{succeeded, Comment} ->
- ?line {comment, Comment};
+ {comment, Comment};
continue ->
continue
end.
start_node(Config, Opts) when is_list(Config), is_list(Opts) ->
- case ?config(debug,Config) of
+ case proplists:get_value(debug,Config) of
true -> {ok, node()};
_ -> start_node_1(Config, Opts)
end.
@@ -376,23 +331,16 @@ start_node_1(Config, Opts) ->
Pa = filename:dirname(code:which(?MODULE)),
Name = list_to_atom(atom_to_list(?MODULE)
++ "-"
- ++ atom_to_list(?config(testcase, Config))
+ ++ atom_to_list(proplists:get_value(testcase, Config))
++ "-"
++ integer_to_list(erlang:system_time(seconds))
++ "-"
++ integer_to_list(erlang:unique_integer([positive]))),
- ?t:start_node(Name, slave, [{args, Opts++" -pa "++Pa}]).
+ test_server:start_node(Name, slave, [{args, Opts++" -pa "++Pa}]).
stop_node(Node) when Node =:= node() -> ok;
stop_node(Node) ->
- ?t:stop_node(Node).
-
-is_halfword_vm() ->
- case {erlang:system_info({wordsize, internal}),
- erlang:system_info({wordsize, external})} of
- {4, 8} -> true;
- {WS, WS} -> false
- end.
+ test_server:stop_node(Node).
free_memory() ->
%% Free memory in MB.
@@ -411,5 +359,6 @@ free_memory() ->
TotFree div (1024*1024)
catch
error : undef ->
- ?t:fail({"os_mon not built"})
+ ct:fail({"os_mon not built"})
end.
+
diff --git a/erts/emulator/test/alloc_SUITE_data/threads.c b/erts/emulator/test/alloc_SUITE_data/threads.c
index 2f5f841e3d..44d982b6c7 100644
--- a/erts/emulator/test/alloc_SUITE_data/threads.c
+++ b/erts/emulator/test/alloc_SUITE_data/threads.c
@@ -96,16 +96,11 @@ static void fail(int t_no, char *frmt, ...)
exit_thread(t_no, 0);
}
-static Allctr_t *alloc_not_ts = NULL;
static Allctr_t *alloc_ts_1 = NULL;
static Allctr_t *alloc_ts_2 = NULL;
static void stop_allocators(void)
{
- if (alloc_not_ts) {
- STOP_ALC(alloc_not_ts);
- alloc_not_ts = NULL;
- }
if (alloc_ts_1) {
STOP_ALC(alloc_ts_1);
alloc_ts_1 = NULL;
@@ -155,7 +150,6 @@ testcase_run(TestCaseState_t *tcs)
if (!IS_THREADS_ENABLED)
testcase_skipped(tcs, "Threads not enabled");
- alloc_not_ts = NULL;
alloc_ts_1 = NULL;
alloc_ts_2 = NULL;
@@ -164,16 +158,12 @@ testcase_run(TestCaseState_t *tcs)
sprintf(sbct_buf, "%d", SBC_THRESHOLD/1024);
memcpy((void *) argv, argv_org, sizeof(argv_org));
- alloc_not_ts = START_ALC("threads_not_ts", 0, argv);
- ASSERT(tcs, alloc_not_ts);
- memcpy((void *) argv, argv_org, sizeof(argv_org));
alloc_ts_1 = START_ALC("threads_ts_1", 1, argv);
ASSERT(tcs, alloc_ts_1);
memcpy((void *) argv, argv_org, sizeof(argv_org));
alloc_ts_2 = START_ALC("threads_ts_2", 1, argv);
ASSERT(tcs, alloc_ts_2);
- ASSERT(tcs, !IS_ALLOC_THREAD_SAFE(alloc_not_ts));
ASSERT(tcs, IS_ALLOC_THREAD_SAFE(alloc_ts_1));
ASSERT(tcs, IS_ALLOC_THREAD_SAFE(alloc_ts_2));
@@ -190,12 +180,7 @@ testcase_run(TestCaseState_t *tcs)
threads[i].arg.no_ops_per_bl = NO_OF_OPS_PER_BL;
- if (i == 1) {
- alc = "threads_not_ts";
- threads[i].arg.no_ops_per_bl *= 2;
- threads[i].arg.a = alloc_not_ts;
- }
- else if (i % 2 == 0) {
+ if (i % 2 == 0) {
alc = "threads_ts_1";
threads[i].arg.a = alloc_ts_1;
}
diff --git a/erts/emulator/test/async_ports_SUITE.erl b/erts/emulator/test/async_ports_SUITE.erl
index c89b3655ff..f0f5fb5687 100644
--- a/erts/emulator/test/async_ports_SUITE.erl
+++ b/erts/emulator/test/async_ports_SUITE.erl
@@ -1,8 +1,10 @@
-module(async_ports_SUITE).
--include_lib("common_test/include/ct.hrl").
+-export([all/0, suite/0]).
+-export([permanent_busy_test/1]).
+-export([run_loop/5]).
--compile(export_all).
+-include_lib("common_test/include/ct.hrl").
-define(PACKET_SIZE, (10 * 1024 * 8)).
-define(CPORT_DELAY, 100).
@@ -11,17 +13,15 @@
-define(TEST_PROCS_COUNT, 2).
-define(TC_TIMETRAP_SECONDS, 10).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {seconds, ?TC_TIMETRAP_SECONDS}}].
all() ->
- [
- permanent_busy_test
- ].
+ [permanent_busy_test].
permanent_busy_test(Config) ->
- ct:timetrap({seconds, ?TC_TIMETRAP_SECONDS}),
- ExePath = filename:join(?config(data_dir, Config), "cport"),
-
+ ExePath = filename:join(proplists:get_value(data_dir, Config), "cport"),
Self = self(),
spawn_link(
fun() ->
@@ -29,17 +29,16 @@ permanent_busy_test(Config) ->
Port = open_port(ExePath),
- Testers =
- lists:map(
- fun(_) ->
- erlang:spawn_link(?MODULE, run_loop,
- [Self,
- Port,
- Block,
- ?TEST_LOOPS_COUNT,
- 0])
- end,
- lists:seq(1, ?TEST_PROCS_COUNT)),
+ Testers = lists:map(
+ fun(_) ->
+ spawn_link(?MODULE, run_loop,
+ [Self,
+ Port,
+ Block,
+ ?TEST_LOOPS_COUNT,
+ 0])
+ end,
+ lists:seq(1, ?TEST_PROCS_COUNT)),
Self ! {test_info, Port, Testers},
endless_flush(Port)
end),
diff --git a/erts/emulator/test/beam_SUITE.erl b/erts/emulator/test/beam_SUITE.erl
index 706a4a1c16..07dfeb6633 100644
--- a/erts/emulator/test/beam_SUITE.erl
+++ b/erts/emulator/test/beam_SUITE.erl
@@ -28,7 +28,7 @@
-export([applied/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -61,15 +61,15 @@ apply_last(Config) when is_list(Config) ->
{Pid, finished} ->
stack_size(Pid)
after 30000 ->
- ?t:fail("applied/2 timed out.")
+ ct:fail("applied/2 timed out.")
end,
Pid ! die,
- ?t:format("Size: ~p~n", [Size]),
+ io:format("Size: ~p~n", [Size]),
if
Size < 700 ->
ok;
true ->
- ?t:fail("10000 apply() grew stack too much.")
+ ct:fail("10000 apply() grew stack too much.")
end,
ok.
@@ -95,7 +95,7 @@ apply_last_bif(Config) when is_list(Config) ->
%% Test three high register numbers in a put_list instruction
%% (to test whether packing works properly).
packed_registers(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Mod = packed_regs,
Name = filename:join(PrivDir, atom_to_list(Mod) ++ ".erl"),
@@ -132,8 +132,7 @@ verify_packed_regs([], _, -1) -> ok;
verify_packed_regs([{Term, N}| T], Term, N) ->
verify_packed_regs(T, Term, N-1);
verify_packed_regs(L, Term, N) ->
- ok = io:format("Expected [{~p, ~p}|T]; got\n~p\n", [Term, N, L]),
- test_server:fail().
+ ct:fail("Expected [{~p, ~p}|T]; got\n~p\n", [Term, N, L]).
buildo_mucho(Config) when is_list(Config) ->
buildo_mucho_1(),
@@ -319,7 +318,7 @@ fconv(Config) when is_list(Config) ->
do_fconv(Type) ->
try
do_fconv(Type, 1.0),
- test_server:fail()
+ ct:fail(no_badarith)
catch
error:badarith ->
ok
diff --git a/erts/emulator/test/beam_literals_SUITE.erl b/erts/emulator/test/beam_literals_SUITE.erl
index 9f14ca26e5..b013ff5fbb 100644
--- a/erts/emulator/test/beam_literals_SUITE.erl
+++ b/erts/emulator/test/beam_literals_SUITE.erl
@@ -28,7 +28,7 @@
put_list/1, fconv/1, literal_case_expression/1,
increment/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -55,7 +55,7 @@ end_per_group(_GroupName, Config) ->
Config.
-putting(doc) -> "Test creating lists and tuples containing big number literals.";
+%% Test creating lists and tuples containing big number literals.
putting(Config) when is_list(Config) ->
-773973888575883407313908 = chksum(putting1(8987697898797)).
@@ -64,23 +64,22 @@ putting1(X) ->
[X|349873987387373],
[329878349873|-387394729872], -773973937933873929749873}.
-matching_bigs(doc) -> "Test matching of a few big number literals (in Beam,"
- "select_val/3 will NOT be used).";
+%% Test matching of a few big number literals (in Beam select_val/3 will NOT be used).
matching_bigs(Config) when is_list(Config) ->
a = matching1(3972907842873739),
b = matching1(-389789298378939783333333333333333333784),
other = matching1(3141699999999999999999999999999999999),
other = matching1(42).
-matching_smalls(doc) -> "Test matching small numbers (both positive and negative).";
+%% Test matching small numbers (both positive and negative).
matching_smalls(Config) when is_list(Config) ->
- ?line a = m_small(-42),
- ?line b = m_small(0),
- ?line c = m_small(105),
- ?line d = m_small(-13),
- ?line e = m_small(337848),
- ?line other = m_small(324),
- ?line other = m_small(-7),
+ a = m_small(-42),
+ b = m_small(0),
+ c = m_small(105),
+ d = m_small(-13),
+ e = m_small(337848),
+ other = m_small(324),
+ other = m_small(-7),
ok.
m_small(-42) -> a;
@@ -90,17 +89,16 @@ m_small(-13) -> d;
m_small(337848) -> e;
m_small(_) -> other.
-matching_smalls_jt(doc) ->
- "Test matching small numbers (both positive and negative). "
- "Make sure that a jump table is used.";
+%% Test matching small numbers (both positive and negative).
+%% Make sure that a jump table is used.
matching_smalls_jt(Config) when is_list(Config) ->
- ?line a = m_small_jt(-2),
- ?line b = m_small_jt(-1),
- ?line c = m_small_jt(0),
- ?line d = m_small_jt(2),
- ?line e = m_small_jt(3),
- ?line other = m_small(324),
- ?line other = m_small(-7),
+ a = m_small_jt(-2),
+ b = m_small_jt(-1),
+ c = m_small_jt(0),
+ d = m_small_jt(2),
+ e = m_small_jt(3),
+ other = m_small(324),
+ other = m_small(-7),
ok.
m_small_jt(-2) -> a;
@@ -117,8 +115,7 @@ matching1(-389789298378939783333333333333333333784) -> b;
matching1(_) -> other.
-matching_more_bigs(doc) -> "Test matching of a big number literals (in Beam,"
- "a select_val/3 instruction will be used).";
+%% Test matching of a big number literals (in Beam, a select_val/3 instruction will be used)
matching_more_bigs(Config) when is_list(Config) ->
a = matching2(-999766349740978337),
b = matching2(9734097866575478),
@@ -137,8 +134,7 @@ matching2(13987294872948990) -> d;
matching2(777723896192459245) -> e;
matching2(_) -> other.
-matching_bigs_and_smalls(doc) -> "Test matching of a mix of big numbers and literals.";
-matching_bigs_and_smalls(suite) -> [];
+%% Test matching of a mix of big numbers and literals.
matching_bigs_and_smalls(Config) when is_list(Config) ->
a = matching3(38472928723987239873873),
b = matching3(0),
@@ -159,30 +155,30 @@ matching3(42) -> e;
matching3(-4533) -> f;
matching3(_) -> other.
-badmatch(doc) -> "Test literal badmatches with big number and floats.";
+%% Test literal badmatches with big number and floats.
badmatch(Config) when is_list(Config) ->
%% We are satisfied if we can load this module and run it.
Big = id(32984798729847892498297824872982972978239874),
Float = id(3.1415927),
- ?line catch a = Big,
- ?line catch b = Float,
- ?line {'EXIT',{{badmatch,3879373498378993387},_}} =
+ catch a = Big,
+ catch b = Float,
+ {'EXIT',{{badmatch,3879373498378993387},_}} =
(catch c = 3879373498378993387),
- ?line {'EXIT',{{badmatch,7.0},_}} = (catch d = 7.0),
- ?line case Big of
- Big -> ok
- end,
- ?line case Float of
- Float -> ok
- end,
+ {'EXIT',{{badmatch,7.0},_}} = (catch d = 7.0),
+ case Big of
+ Big -> ok
+ end,
+ case Float of
+ Float -> ok
+ end,
ok.
case_clause(Config) when is_list(Config) ->
- ?line {'EXIT',{{case_clause,337.0},_}} = (catch case_clause_float()),
- ?line {'EXIT',{{try_clause,42.0},_}} = (catch try_case_clause_float()),
- ?line {'EXIT',{{case_clause,37932749837839747383847398743789348734987},_}} =
+ {'EXIT',{{case_clause,337.0},_}} = (catch case_clause_float()),
+ {'EXIT',{{try_clause,42.0},_}} = (catch try_case_clause_float()),
+ {'EXIT',{{case_clause,37932749837839747383847398743789348734987},_}} =
(catch case_clause_big()),
- ?line {'EXIT',{{try_clause,977387349872349870423364354398566348},_}} =
+ {'EXIT',{{try_clause,977387349872349870423364354398566348},_}} =
(catch try_case_clause_big()),
ok.
@@ -210,8 +206,7 @@ try_case_clause_big() ->
error
end.
-receiving(doc) -> "Test receive with a big number literal (more than 27 bits, "
- "less than 32 bits).";
+%% Test receive with a big number literal (more than 27 bits, less than 32 bits).
receiving(Config) when is_list(Config) ->
Self = self(),
spawn(fun() -> Self ! here_is_a_message end),
@@ -222,11 +217,11 @@ receiving(Config) when is_list(Config) ->
timeout
end.
-literal_type_tests(doc) -> "Test type tests on literal values.";
+%% Test type tests on literal values.
literal_type_tests(Config) when is_list(Config) ->
%% Generate an Erlang module with all different type of type tests.
- ?line Tests = make_test([{T, L} || T <- type_tests(), L <- literals()]),
- ?line Mod = literal_test,
+ Tests = make_test([{T, L} || T <- type_tests(), L <- literals()]),
+ Mod = literal_test,
Anno = erl_anno:new(0),
Func = {function, Anno, test, 0, [{clause,Anno,[],[],Tests}]},
Form = [{attribute,Anno,module,Mod},
@@ -234,22 +229,22 @@ literal_type_tests(Config) when is_list(Config) ->
Func, {eof,Anno}],
%% Print generated code for inspection.
- ?line lists:foreach(fun (F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Form),
+ lists:foreach(fun (F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Form),
%% Test compile:form/1. This implies full optimization (default).
- ?line {ok,Mod,Code1} = compile:forms(Form),
- ?line {module,Mod} = code:load_binary(Mod, Mod, Code1),
- ?line Mod:test(),
- ?line true = code:delete(Mod),
- ?line code:purge(Mod),
+ {ok,Mod,Code1} = compile:forms(Form),
+ {module,Mod} = code:load_binary(Mod, Mod, Code1),
+ Mod:test(),
+ true = code:delete(Mod),
+ code:purge(Mod),
%% Test compile:form/2. Turn off all optimizations.
- ?line {ok,Mod,Code2} = compile:forms(Form, [binary,report,time,
+ {ok,Mod,Code2} = compile:forms(Form, [binary,report,time,
no_copt,no_postopt]),
- ?line {module,Mod} = code:load_binary(Mod, Mod, Code2),
- ?line Mod:test(),
- ?line true = code:delete(Mod),
- ?line code:purge(Mod),
+ {module,Mod} = code:load_binary(Mod, Mod, Code2),
+ Mod:test(),
+ true = code:delete(Mod),
+ code:purge(Mod),
ok.
make_test([{is_function=T,L}|Ts]) ->
@@ -299,34 +294,34 @@ type_tests() ->
put_list(Config) when is_list(Config) ->
%% put_list x0 Literal Reg
- ?line [Config|8739757395764] = put_list_rqr(Config),
- ?line {[Config|7779757395764],Config} = put_list_rqx(Config),
- ?line [Config|98765432100000] = put_list_rqy(Config),
+ [Config|8739757395764] = put_list_rqr(Config),
+ {[Config|7779757395764],Config} = put_list_rqx(Config),
+ [Config|98765432100000] = put_list_rqy(Config),
%% put_list x Literal Reg
- ?line [Config|16#FFFFF77777137483769] = put_list_xqr(ignore, Config),
- ?line {[Config|16#AAAAAFFFFF77777],{a,b},Config} = put_list_xqx({a,b}, Config),
- ?line [Config|12777765432979879] = put_list_xqy(ignore, Config),
+ [Config|16#FFFFF77777137483769] = put_list_xqr(ignore, Config),
+ {[Config|16#AAAAAFFFFF77777],{a,b},Config} = put_list_xqx({a,b}, Config),
+ [Config|12777765432979879] = put_list_xqy(ignore, Config),
%% put_list y Literal Reg
- ?line [Config|17424134793676869867] = put_list_yqr(Config),
- ?line {[Config|77424134793676869867],Config} = put_list_yqx(Config),
- ?line {Config,[Config|16#BCDEFF4241676869867]} = put_list_yqy(Config),
+ [Config|17424134793676869867] = put_list_yqr(Config),
+ {[Config|77424134793676869867],Config} = put_list_yqx(Config),
+ {Config,[Config|16#BCDEFF4241676869867]} = put_list_yqy(Config),
%% put_list Literal x0 Reg
- ?line [42.0|Config] = put_list_qrr(Config),
- ?line [Config,42.0|Config] = put_list_qrx(Config),
- ?line [100.0|Config] = put_list_qry(Config),
+ [42.0|Config] = put_list_qrr(Config),
+ [Config,42.0|Config] = put_list_qrx(Config),
+ [100.0|Config] = put_list_qry(Config),
%% put_list Literal x1 Reg
- ?line [127.0|Config] = put_list_qxr({ignore,me}, Config),
- ?line [Config,130.0|Config] = put_list_qxx(ignore, Config),
- ?line [99.0|Config] = put_list_qxy(Config),
+ [127.0|Config] = put_list_qxr({ignore,me}, Config),
+ [Config,130.0|Config] = put_list_qxx(ignore, Config),
+ [99.0|Config] = put_list_qxy(Config),
%% put_list Literal y0 Reg
- ?line [200.0|Config] = put_list_qyr(Config),
- ?line [Config,210.0|Config] = put_list_qyx(Config),
- ?line [[300.0|Config]|Config] = put_list_qyy(Config),
+ [200.0|Config] = put_list_qyr(Config),
+ [Config,210.0|Config] = put_list_qyx(Config),
+ [[300.0|Config]|Config] = put_list_qyy(Config),
ok.
@@ -417,8 +412,8 @@ put_list_qyy(Config) ->
[Res|Config].
fconv(Config) when is_list(Config) ->
- ?line 5.0 = fconv_1(-34444444450.0),
- ?line 13.0 = fconv_2(7.0),
+ 5.0 = fconv_1(-34444444450.0),
+ 13.0 = fconv_2(7.0),
ok.
fconv_1(F) when is_float(F) ->
@@ -428,19 +423,18 @@ fconv_2(F) when is_float(F) ->
6.0 + F.
literal_case_expression(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line Src = filename:join(DataDir, "literal_case_expression"),
- ?line {ok,literal_case_expression=Mod,Code} =
- compile:file(Src, [from_asm,binary]),
- ?line {module,Mod} = code:load_binary(Mod, Src, Code),
- ?line ok = Mod:x(),
- ?line ok = Mod:y(),
- ?line ok = Mod:zi1(),
- ?line ok = Mod:zi2(),
- ?line ok = Mod:za1(),
- ?line ok = Mod:za2(),
- ?line true = code:delete(Mod),
- ?line code:purge(Mod),
+ DataDir = proplists:get_value(data_dir, Config),
+ Src = filename:join(DataDir, "literal_case_expression"),
+ {ok,literal_case_expression=Mod,Code} = compile:file(Src, [from_asm,binary]),
+ {module,Mod} = code:load_binary(Mod, Src, Code),
+ ok = Mod:x(),
+ ok = Mod:y(),
+ ok = Mod:zi1(),
+ ok = Mod:zi2(),
+ ok = Mod:za1(),
+ ok = Mod:za2(),
+ true = code:delete(Mod),
+ code:purge(Mod),
ok.
%% Test the i_increment instruction.
@@ -452,27 +446,27 @@ increment(Config) when is_list(Config) ->
Neg32 = -(1 bsl 27),
Big32 = id(1 bsl 32),
Result32 = (1 bsl 32) + (1 bsl 27),
- ?line Result32 = Big32 + (1 bsl 27),
- ?line Result32 = Big32 - Neg32,
+ Result32 = Big32 + (1 bsl 27),
+ Result32 = Big32 - Neg32,
%% Same thing, but for the 64-bit emulator.
Neg64 = -(1 bsl 59),
Big64 = id(1 bsl 64),
Result64 = (1 bsl 64) + (1 bsl 59),
- ?line Result64 = Big64 + (1 bsl 59),
- ?line Result64 = Big64 - Neg64,
+ Result64 = Big64 + (1 bsl 59),
+ Result64 = Big64 - Neg64,
%% Test error handling for the i_increment instruction.
Bad = id(bad),
- ?line {'EXIT',{badarith,_}} = (catch Bad + 42),
+ {'EXIT',{badarith,_}} = (catch Bad + 42),
%% Small operands, but a big result.
Res32 = 1 bsl 27,
Small32 = id(Res32-1),
- ?line Res32 = Small32 + 1,
+ Res32 = Small32 + 1,
Res64 = 1 bsl 59,
Small64 = id(Res64-1),
- ?line Res64 = Small64 + 1,
+ Res64 = Small64 + 1,
ok.
%% Help functions.
diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl
index d6a771e7b9..43d00e699a 100644
--- a/erts/emulator/test/bif_SUITE.erl
+++ b/erts/emulator/test/bif_SUITE.erl
@@ -20,21 +20,22 @@
-module(bif_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2,
+-export([all/0, suite/0,
display/1, display_huge/0,
erl_bif_types/1,guard_bifs_in_erl_bif_types/1,
shadow_comments/1,
specs/1,improper_bif_stubs/1,auto_imports/1,
t_list_to_existing_atom/1,os_env/1,otp_7526/1,
binary_to_atom/1,binary_to_existing_atom/1,
- atom_to_binary/1,min_max/1, erlang_halt/1]).
+ atom_to_binary/1,min_max/1, erlang_halt/1,
+ is_builtin/1]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 1}}].
all() ->
[erl_bif_types, guard_bifs_in_erl_bif_types, shadow_comments,
@@ -42,37 +43,9 @@ all() ->
t_list_to_existing_atom, os_env, otp_7526,
display,
atom_to_binary, binary_to_atom, binary_to_existing_atom,
- min_max, erlang_halt].
+ min_max, erlang_halt, is_builtin].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?t:timetrap(?t:minutes(1)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
-
-display(suite) ->
- [];
-display(doc) ->
- ["Uses erlang:display to test that erts_printf does not do deep recursion"];
+%% Uses erlang:display to test that erts_printf does not do deep recursion
display(Config) when is_list(Config) ->
Pa = filename:dirname(code:which(?MODULE)),
{ok, Node} = test_server:start_node(display_huge_term,peer,
@@ -117,7 +90,7 @@ erl_bif_types_2(List) ->
[_|_] ->
io:put_chars("Bifs with bad arity\n"),
io:format("~p\n", [BadArity]),
- ?line ?t:fail({length(BadArity),bad_arity})
+ ct:fail({length(BadArity),bad_arity})
end.
erl_bif_types_3(List) ->
@@ -141,7 +114,7 @@ erl_bif_types_3(List) ->
io:put_chars("Bifs with failing calls to erlang_bif_types:type/3 "
"(or with bogus return values):\n"),
io:format("~p\n", [BadSmokeTest]),
- ?line ?t:fail({length(BadSmokeTest),bad_smoke_test})
+ ct:fail({length(BadSmokeTest),bad_smoke_test})
end.
guard_bifs_in_erl_bif_types(_Config) ->
@@ -162,7 +135,7 @@ guard_bifs_in_erl_bif_types(_Config) ->
"The following guard BIFs have no type information "
"in erl_bif_types:\n\n",
[io_lib:format(" ~p/~p\n", [F,A]) || {F,A} <- Not]]),
- ?t:fail()
+ ct:fail(erl_bif_types)
end.
shadow_comments(_Config) ->
@@ -202,7 +175,7 @@ shadow_comments(_Config) ->
"obvious.\n\nThe following comments are missing:\n\n",
[io_lib:format("%% Shadowed by erl_bif_types: ~p:~p/~p\n",
[M,F,A]) || {M,F,A} <- NoComments]]),
- ?t:fail()
+ ct:fail(bif_stub)
end,
case NoBifSpecs of
@@ -216,7 +189,7 @@ shadow_comments(_Config) ->
"Therefore, the following comments should be removed:\n\n",
[io_lib:format("%% Shadowed by erl_bif_types: ~p:~p/~p\n",
[M,F,A]) || {M,F,A} <- NoBifSpecs]]),
- ?t:fail()
+ ct:fail(erl_bif_types)
end.
extract_comments(Mod, Path) ->
@@ -238,7 +211,7 @@ ensure_erl_bif_types_compiled() ->
case erlang:function_exported(erl_bif_types, module_info, 0) of
false ->
%% Fail cleanly.
- ?t:fail("erl_bif_types not compiled");
+ ct:fail("erl_bif_types not compiled");
true ->
ok
end.
@@ -276,7 +249,7 @@ specs(_) ->
[_|_] ->
io:put_chars("The following BIFs don't have specs:\n"),
[print_mfa(MFA) || MFA <- NoSpecs],
- ?t:fail()
+ ct:fail(no_spec)
end.
is_operator({erlang,F,A}) ->
@@ -336,7 +309,7 @@ auto_imports([{erlang,F,A}|T], Errors) ->
auto_imports([], 0) ->
ok;
auto_imports([], Errors) ->
- ?t:fail({Errors,inconsistencies}).
+ ct:fail({Errors,inconsistencies}).
extract_functions(M, Abstr) ->
[{{M,F,A},Body} || {function,_,F,A,Body} <- Abstr].
@@ -355,40 +328,36 @@ check_stub({_,F,A}, B) ->
io:put_chars(erl_pp:function(Func)),
io:nl(),
io:put_chars("The body should be: erlang:nif_error(undef)"),
- ?t:fail()
+ ct:fail(invalid_body)
end.
t_list_to_existing_atom(Config) when is_list(Config) ->
- ?line all = list_to_existing_atom("all"),
- ?line ?MODULE = list_to_existing_atom(?MODULE_STRING),
- ?line UnlikelyStr = "dsfj923874390867er869fds9864y97jhg3973qerueoru",
+ all = list_to_existing_atom("all"),
+ ?MODULE = list_to_existing_atom(?MODULE_STRING),
+ UnlikelyStr = "dsfj923874390867er869fds9864y97jhg3973qerueoru",
try
- ?line list_to_existing_atom(UnlikelyStr),
- ?line ?t:fail()
+ list_to_existing_atom(UnlikelyStr),
+ ct:fail(atom_exists)
catch
error:badarg -> ok
end,
%% The compiler has become smarter! We need the call to id/1 in
%% the next line.
- ?line UnlikelyAtom = list_to_atom(id(UnlikelyStr)),
- ?line UnlikelyAtom = list_to_existing_atom(UnlikelyStr),
+ UnlikelyAtom = list_to_atom(id(UnlikelyStr)),
+ UnlikelyAtom = list_to_existing_atom(UnlikelyStr),
ok.
-os_env(doc) ->
- [];
-os_env(suite) ->
- [];
os_env(Config) when is_list(Config) ->
- ?line EnvVar1 = "MjhgvFDrresdCghN mnjkUYg vfrD",
- ?line false = os:getenv(EnvVar1),
- ?line true = os:putenv(EnvVar1, "mors"),
- ?line "mors" = os:getenv(EnvVar1),
- ?line true = os:putenv(EnvVar1, ""),
- ?line case os:getenv(EnvVar1) of
- "" -> ?line ok;
- false -> ?line ok;
- BadVal -> ?line ?t:fail(BadVal)
+ EnvVar1 = "MjhgvFDrresdCghN mnjkUYg vfrD",
+ false = os:getenv(EnvVar1),
+ true = os:putenv(EnvVar1, "mors"),
+ "mors" = os:getenv(EnvVar1),
+ true = os:putenv(EnvVar1, ""),
+ case os:getenv(EnvVar1) of
+ "" -> ok;
+ false -> ok;
+ BadVal -> ct:fail(BadVal)
end,
true = os:putenv(EnvVar1, "mors"),
true = os:unsetenv(EnvVar1),
@@ -396,19 +365,18 @@ os_env(Config) when is_list(Config) ->
true = os:unsetenv(EnvVar1), % unset unset variable
%% os:putenv, os:getenv and os:unsetenv currently use a temp
%% buffer of size 1024 for storing key+value
- ?line os_env_long(1010, 1030, "hej hopp").
+ os_env_long(1010, 1030, "hej hopp").
os_env_long(Min, Max, _Value) when Min > Max ->
- ?line ok;
+ ok;
os_env_long(Min, Max, Value) ->
- ?line EnvVar = lists:duplicate(Min, $X),
- ?line true = os:putenv(EnvVar, Value),
- ?line Value = os:getenv(EnvVar),
+ EnvVar = lists:duplicate(Min, $X),
+ true = os:putenv(EnvVar, Value),
+ Value = os:getenv(EnvVar),
true = os:unsetenv(EnvVar),
- ?line os_env_long(Min+1, Max, Value).
+ os_env_long(Min+1, Max, Value).
-otp_7526(doc) ->
- ["Test that string:to_integer does not Halloc in wrong order."];
+%% Test that string:to_integer does not Halloc in wrong order.
otp_7526(Config) when is_list(Config) ->
ok = test_7526(256).
@@ -423,15 +391,15 @@ do_test_7526(N,M) ->
{Self, Ref} = {self(), make_ref()},
T = erlang:make_tuple(M,0),
spawn_opt(fun()->
- L = iterate_7526(N, []),
- BadList = [X || X <- L, X =/= 9223372036854775808],
- BadLen = length(BadList),
- M = length(tuple_to_list(T)),
- %%io:format("~b bad conversions: ~p~n", [BadLen, BadList]),
- Self ! {done, Ref, BadLen}
- end,
- [link,{fullsweep_after,0}]),
- receive {done, Ref, Len} -> Len end.
+ L = iterate_7526(N, []),
+ BadList = [X || X <- L, X =/= 9223372036854775808],
+ BadLen = length(BadList),
+ M = length(tuple_to_list(T)),
+ %%io:format("~b bad conversions: ~p~n", [BadLen, BadList]),
+ Self ! {done, Ref, BadLen}
+ end,
+ [link,{fullsweep_after,0}]),
+ receive {done, Ref, Len} -> Len end.
test_7526(0) ->
@@ -455,57 +423,53 @@ binary_to_atom(Config) when is_list(Config) ->
LongBin = list_to_binary(Long),
%% latin1
- ?line '' = test_binary_to_atom(<<>>, latin1),
- ?line '\377' = test_binary_to_atom(<<255>>, latin1),
- ?line HalfLongAtom = test_binary_to_atom(HalfLongBin, latin1),
- ?line LongAtom = test_binary_to_atom(LongBin, latin1),
+ '' = test_binary_to_atom(<<>>, latin1),
+ '\377' = test_binary_to_atom(<<255>>, latin1),
+ HalfLongAtom = test_binary_to_atom(HalfLongBin, latin1),
+ LongAtom = test_binary_to_atom(LongBin, latin1),
%% utf8
- ?line '' = test_binary_to_atom(<<>>, utf8),
- ?line HalfLongAtom = test_binary_to_atom(HalfLongBin, utf8),
- ?line HalfLongAtom = test_binary_to_atom(HalfLongBin, unicode),
- ?line [] = [C || C <- lists:seq(128, 255),
+ '' = test_binary_to_atom(<<>>, utf8),
+ HalfLongAtom = test_binary_to_atom(HalfLongBin, utf8),
+ HalfLongAtom = test_binary_to_atom(HalfLongBin, unicode),
+ [] = [C || C <- lists:seq(128, 255),
begin
list_to_atom([C]) =/=
test_binary_to_atom(<<C/utf8>>, utf8)
end],
%% badarg failures.
- ?line fail_binary_to_atom(atom),
- ?line fail_binary_to_atom(42),
- ?line fail_binary_to_atom({a,b,c}),
- ?line fail_binary_to_atom([1,2,3]),
- ?line fail_binary_to_atom([]),
- ?line fail_binary_to_atom(42.0),
- ?line fail_binary_to_atom(self()),
- ?line fail_binary_to_atom(make_ref()),
- ?line fail_binary_to_atom(<<0:7>>),
- ?line fail_binary_to_atom(<<42:13>>),
- ?line ?BADARG(binary_to_atom(id(<<>>), blurf)),
- ?line ?BADARG(binary_to_atom(id(<<>>), [])),
+ fail_binary_to_atom(atom),
+ fail_binary_to_atom(42),
+ fail_binary_to_atom({a,b,c}),
+ fail_binary_to_atom([1,2,3]),
+ fail_binary_to_atom([]),
+ fail_binary_to_atom(42.0),
+ fail_binary_to_atom(self()),
+ fail_binary_to_atom(make_ref()),
+ fail_binary_to_atom(<<0:7>>),
+ fail_binary_to_atom(<<42:13>>),
+ ?BADARG(binary_to_atom(id(<<>>), blurf)),
+ ?BADARG(binary_to_atom(id(<<>>), [])),
%% Bad UTF8 sequences.
- ?line ?BADARG(binary_to_atom(id(<<255>>), utf8)),
- ?line ?BADARG(binary_to_atom(id(<<255,0>>), utf8)),
- ?line ?BADARG(binary_to_atom(id(<<16#C0,16#80>>), utf8)), %Overlong 0.
- ?line [?BADARG(binary_to_atom(<<C/utf8>>, utf8)) ||
- C <- lists:seq(256, 16#D7FF)],
- ?line [?BADARG(binary_to_atom(<<C/utf8>>, utf8)) ||
- C <- lists:seq(16#E000, 16#FFFD)],
- ?line [?BADARG(binary_to_atom(<<C/utf8>>, utf8)) ||
- C <- lists:seq(16#10000, 16#8FFFF)],
- ?line [?BADARG(binary_to_atom(<<C/utf8>>, utf8)) ||
- C <- lists:seq(16#90000, 16#10FFFF)],
+ ?BADARG(binary_to_atom(id(<<255>>), utf8)),
+ ?BADARG(binary_to_atom(id(<<255,0>>), utf8)),
+ ?BADARG(binary_to_atom(id(<<16#C0,16#80>>), utf8)), %Overlong 0.
+ [?BADARG(binary_to_atom(<<C/utf8>>, utf8)) || C <- lists:seq(256, 16#D7FF)],
+ [?BADARG(binary_to_atom(<<C/utf8>>, utf8)) || C <- lists:seq(16#E000, 16#FFFD)],
+ [?BADARG(binary_to_atom(<<C/utf8>>, utf8)) || C <- lists:seq(16#10000, 16#8FFFF)],
+ [?BADARG(binary_to_atom(<<C/utf8>>, utf8)) || C <- lists:seq(16#90000, 16#10FFFF)],
%% system_limit failures.
- ?line ?SYS_LIMIT(binary_to_atom(id(<<0:512/unit:8,255>>), utf8)),
- ?line ?SYS_LIMIT(binary_to_atom(id(<<0:512/unit:8,255,0>>), utf8)),
- ?line ?SYS_LIMIT(binary_to_atom(<<0:256/unit:8>>, latin1)),
- ?line ?SYS_LIMIT(binary_to_atom(<<0:257/unit:8>>, latin1)),
- ?line ?SYS_LIMIT(binary_to_atom(<<0:512/unit:8>>, latin1)),
- ?line ?SYS_LIMIT(binary_to_atom(<<0:256/unit:8>>, utf8)),
- ?line ?SYS_LIMIT(binary_to_atom(<<0:257/unit:8>>, utf8)),
- ?line ?SYS_LIMIT(binary_to_atom(<<0:512/unit:8>>, utf8)),
+ ?SYS_LIMIT(binary_to_atom(id(<<0:512/unit:8,255>>), utf8)),
+ ?SYS_LIMIT(binary_to_atom(id(<<0:512/unit:8,255,0>>), utf8)),
+ ?SYS_LIMIT(binary_to_atom(<<0:256/unit:8>>, latin1)),
+ ?SYS_LIMIT(binary_to_atom(<<0:257/unit:8>>, latin1)),
+ ?SYS_LIMIT(binary_to_atom(<<0:512/unit:8>>, latin1)),
+ ?SYS_LIMIT(binary_to_atom(<<0:256/unit:8>>, utf8)),
+ ?SYS_LIMIT(binary_to_atom(<<0:257/unit:8>>, utf8)),
+ ?SYS_LIMIT(binary_to_atom(<<0:512/unit:8>>, utf8)),
ok.
test_binary_to_atom(Bin0, Encoding) ->
@@ -518,49 +482,49 @@ test_binary_to_atom(Bin0, Encoding) ->
fail_binary_to_atom(Bin) ->
try
- binary_to_atom(Bin, latin1)
+ binary_to_atom(Bin, latin1)
catch
- error:badarg ->
- ok
+ error:badarg ->
+ ok
end,
try
- binary_to_atom(Bin, utf8)
+ binary_to_atom(Bin, utf8)
catch
- error:badarg ->
- ok
+ error:badarg ->
+ ok
end,
try
- binary_to_existing_atom(Bin, latin1)
+ binary_to_existing_atom(Bin, latin1)
catch
- error:badarg ->
- ok
+ error:badarg ->
+ ok
end,
try
- binary_to_existing_atom(Bin, utf8)
+ binary_to_existing_atom(Bin, utf8)
catch
- error:badarg ->
- ok
+ error:badarg ->
+ ok
end.
binary_to_existing_atom(Config) when is_list(Config) ->
- ?line UnlikelyBin = <<"ou0897979655678dsfj923874390867er869fds973qerueoru">>,
+ UnlikelyBin = <<"ou0897979655678dsfj923874390867er869fds973qerueoru">>,
try
- ?line binary_to_existing_atom(UnlikelyBin, latin1),
- ?line ?t:fail()
+ binary_to_existing_atom(UnlikelyBin, latin1),
+ ct:fail(atom_exists)
catch
error:badarg -> ok
end,
try
- ?line binary_to_existing_atom(UnlikelyBin, utf8),
- ?line ?t:fail()
+ binary_to_existing_atom(UnlikelyBin, utf8),
+ ct:fail(atom_exists)
catch
error:badarg -> ok
end,
- ?line UnlikelyAtom = binary_to_atom(id(UnlikelyBin), latin1),
- ?line UnlikelyAtom = binary_to_existing_atom(UnlikelyBin, latin1),
+ UnlikelyAtom = binary_to_atom(id(UnlikelyBin), latin1),
+ UnlikelyAtom = binary_to_existing_atom(UnlikelyBin, latin1),
ok.
@@ -573,32 +537,32 @@ atom_to_binary(Config) when is_list(Config) ->
LongBin = list_to_binary(Long),
%% latin1
- ?line <<>> = atom_to_binary('', latin1),
- ?line <<"abc">> = atom_to_binary(abc, latin1),
- ?line <<127>> = atom_to_binary('\177', latin1),
- ?line HalfLongBin = atom_to_binary(HalfLongAtom, latin1),
- ?line LongBin = atom_to_binary(LongAtom, latin1),
+ <<>> = atom_to_binary('', latin1),
+ <<"abc">> = atom_to_binary(abc, latin1),
+ <<127>> = atom_to_binary('\177', latin1),
+ HalfLongBin = atom_to_binary(HalfLongAtom, latin1),
+ LongBin = atom_to_binary(LongAtom, latin1),
%% utf8.
- ?line <<>> = atom_to_binary('', utf8),
- ?line <<>> = atom_to_binary('', unicode),
- ?line <<127>> = atom_to_binary('\177', utf8),
- ?line <<"abcdef">> = atom_to_binary(abcdef, utf8),
- ?line HalfLongBin = atom_to_binary(HalfLongAtom, utf8),
- ?line LongAtomBin = atom_to_binary(LongAtom, utf8),
- ?line verify_long_atom_bin(LongAtomBin, 0),
+ <<>> = atom_to_binary('', utf8),
+ <<>> = atom_to_binary('', unicode),
+ <<127>> = atom_to_binary('\177', utf8),
+ <<"abcdef">> = atom_to_binary(abcdef, utf8),
+ HalfLongBin = atom_to_binary(HalfLongAtom, utf8),
+ LongAtomBin = atom_to_binary(LongAtom, utf8),
+ verify_long_atom_bin(LongAtomBin, 0),
%% Failing cases.
- ?line fail_atom_to_binary(<<1>>),
- ?line fail_atom_to_binary(42),
- ?line fail_atom_to_binary({a,b,c}),
- ?line fail_atom_to_binary([1,2,3]),
- ?line fail_atom_to_binary([]),
- ?line fail_atom_to_binary(42.0),
- ?line fail_atom_to_binary(self()),
- ?line fail_atom_to_binary(make_ref()),
- ?line ?BADARG(atom_to_binary(id(a), blurf)),
- ?line ?BADARG(atom_to_binary(id(b), [])),
+ fail_atom_to_binary(<<1>>),
+ fail_atom_to_binary(42),
+ fail_atom_to_binary({a,b,c}),
+ fail_atom_to_binary([1,2,3]),
+ fail_atom_to_binary([]),
+ fail_atom_to_binary(42.0),
+ fail_atom_to_binary(self()),
+ fail_atom_to_binary(make_ref()),
+ ?BADARG(atom_to_binary(id(a), blurf)),
+ ?BADARG(atom_to_binary(id(b), [])),
ok.
verify_long_atom_bin(<<I/utf8,T/binary>>, I) ->
@@ -607,74 +571,73 @@ verify_long_atom_bin(<<>>, 255) -> ok.
fail_atom_to_binary(Term) ->
try
- atom_to_binary(Term, latin1)
+ atom_to_binary(Term, latin1)
catch
- error:badarg ->
- ok
+ error:badarg ->
+ ok
end,
try
- atom_to_binary(Term, utf8)
+ atom_to_binary(Term, utf8)
catch
- error:badarg ->
- ok
+ error:badarg ->
+ ok
end.
min_max(Config) when is_list(Config) ->
- ?line a = erlang:min(id(a), a),
- ?line a = erlang:min(id(a), b),
- ?line a = erlang:min(id(b), a),
- ?line b = erlang:min(id(b), b),
- ?line a = erlang:max(id(a), a),
- ?line b = erlang:max(id(a), b),
- ?line b = erlang:max(id(b), a),
- ?line b = erlang:max(id(b), b),
-
- ?line 42.0 = erlang:min(42.0, 42),
- ?line 42.0 = erlang:max(42.0, 42),
+ a = erlang:min(id(a), a),
+ a = erlang:min(id(a), b),
+ a = erlang:min(id(b), a),
+ b = erlang:min(id(b), b),
+ a = erlang:max(id(a), a),
+ b = erlang:max(id(a), b),
+ b = erlang:max(id(b), a),
+ b = erlang:max(id(b), b),
+
+ 42.0 = erlang:min(42.0, 42),
+ 42.0 = erlang:max(42.0, 42),
%% And now (R14) they are also autoimported!
- ?line a = min(id(a), a),
- ?line a = min(id(a), b),
- ?line a = min(id(b), a),
- ?line b = min(id(b), b),
- ?line a = max(id(a), a),
- ?line b = max(id(a), b),
- ?line b = max(id(b), a),
- ?line b = max(id(b), b),
-
- ?line 42.0 = min(42.0, 42),
- ?line 42.0 = max(42.0, 42),
-
+ a = min(id(a), a),
+ a = min(id(a), b),
+ a = min(id(b), a),
+ b = min(id(b), b),
+ a = max(id(a), a),
+ b = max(id(a), b),
+ b = max(id(b), a),
+ b = max(id(b), b),
+
+ 42.0 = min(42.0, 42),
+ 42.0 = max(42.0, 42),
ok.
erlang_halt(Config) when is_list(Config) ->
try erlang:halt(undefined) of
- _-> ?t:fail({erlang,halt,{undefined}})
+ _-> ct:fail({erlang,halt,{undefined}})
catch error:badarg -> ok end,
try halt(undefined) of
- _-> ?t:fail({halt,{undefined}})
+ _-> ct:fail({halt,{undefined}})
catch error:badarg -> ok end,
try erlang:halt(undefined, []) of
- _-> ?t:fail({erlang,halt,{undefined,[]}})
+ _-> ct:fail({erlang,halt,{undefined,[]}})
catch error:badarg -> ok end,
try halt(undefined, []) of
- _-> ?t:fail({halt,{undefined,[]}})
+ _-> ct:fail({halt,{undefined,[]}})
catch error:badarg -> ok end,
try halt(0, undefined) of
- _-> ?t:fail({halt,{0,undefined}})
+ _-> ct:fail({halt,{0,undefined}})
catch error:badarg -> ok end,
try halt(0, [undefined]) of
- _-> ?t:fail({halt,{0,[undefined]}})
+ _-> ct:fail({halt,{0,[undefined]}})
catch error:badarg -> ok end,
try halt(0, [{undefined,true}]) of
- _-> ?t:fail({halt,{0,[{undefined,true}]}})
+ _-> ct:fail({halt,{0,[{undefined,true}]}})
catch error:badarg -> ok end,
try halt(0, [{flush,undefined}]) of
- _-> ?t:fail({halt,{0,[{flush,undefined}]}})
+ _-> ct:fail({halt,{0,[{flush,undefined}]}})
catch error:badarg -> ok end,
try halt(0, [{flush,true,undefined}]) of
- _-> ?t:fail({halt,{0,[{flush,true,undefined}]}})
+ _-> ct:fail({halt,{0,[{flush,true,undefined}]}})
catch error:badarg -> ok end,
H = hostname(),
{ok,N1} = slave:start(H, halt_node1),
@@ -716,6 +679,22 @@ wait_until_stable_size(File,PrevSz) ->
wait_until_stable_size(File,NewSz)
end.
+is_builtin(_Config) ->
+ Exp0 = [{M,F,A} || {M,_} <- code:all_loaded(),
+ {F,A} <- M:module_info(exports)],
+ Exp = ordsets:from_list(Exp0),
+
+ %% erlang:apply/3 is considered to be built-in, but is not
+ %% implemented as other BIFs.
+
+ Builtins0 = [{erlang,apply,3}|erlang:system_info(snifs)],
+ Builtins = ordsets:from_list(Builtins0),
+ NotBuiltin = ordsets:subtract(Exp, Builtins),
+ _ = [true = erlang:is_builtin(M, F, A) || {M,F,A} <- Builtins],
+ _ = [false = erlang:is_builtin(M, F, A) || {M,F,A} <- NotBuiltin],
+
+ ok.
+
%% Helpers
diff --git a/erts/emulator/test/big_SUITE.erl b/erts/emulator/test/big_SUITE.erl
index e8f881f2a4..d331083661 100644
--- a/erts/emulator/test/big_SUITE.erl
+++ b/erts/emulator/test/big_SUITE.erl
@@ -20,8 +20,8 @@
-module(big_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
+-export([all/0, suite/0, groups/0]).
+
-export([t_div/1, eq_28/1, eq_32/1, eq_big/1, eq_math/1, big_literals/1,
borders/1, negative/1, big_float_1/1, big_float_2/1,
shift_limit_1/1, powmod/1, system_limit/1, toobig/1, otp_6692/1]).
@@ -32,11 +32,12 @@
-export([fac/1, fib/1, pow/2, gcd/2, lcm/2]).
--export([init_per_testcase/2, end_per_testcase/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 3}}].
all() ->
[t_div, eq_28, eq_32, eq_big, eq_math, big_literals,
@@ -46,27 +47,6 @@ all() ->
groups() ->
[{big_float, [], [big_float_1, big_float_2]}].
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?t:timetrap(?t:minutes(3)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
%%
%% Syntax of data files:
%% Expr1 = Expr2.
@@ -95,7 +75,7 @@ eq_math(Config) when is_list(Config) ->
test(TestFile).
-borders(doc) -> "Tests border cases between small/big.";
+%% Tests border cases between small/big.
borders(Config) when is_list(Config) ->
TestFile = test_file(Config, "borders.dat"),
test(TestFile).
@@ -107,7 +87,7 @@ negative(Config) when is_list(Config) ->
%% Find test file
test_file(Config, Name) ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
filename:join(DataDir, Name).
%%
@@ -119,12 +99,12 @@ test(File) ->
test(File, [node()]).
test(File, Nodes) ->
- ?line {ok,Fd} = file:open(File, [read]),
+ {ok,Fd} = file:open(File, [read]),
Res = test(File, Fd, Nodes),
file:close(Fd),
case Res of
{0,Cases} -> {comment, integer_to_list(Cases) ++ " cases"};
- {_,_} -> test_server:fail()
+ {_,_} -> ct:fail("failed")
end.
test(File, Fd, Ns) ->
@@ -156,7 +136,7 @@ multi_match(Ns, Expr) ->
multi_match(Ns, Expr, []).
multi_match([Node|Ns], Expr, Rs) ->
- ?line X = rpc:call(Node, big_SUITE, eval, [Expr]),
+ X = rpc:call(Node, big_SUITE, eval, [Expr]),
if X == 0 -> multi_match(Ns, Expr, Rs);
true -> multi_match(Ns, Expr, [{Node,X}|Rs])
end;
@@ -248,10 +228,10 @@ lcm(Q, R) ->
%% Test case t_div cut in from R2D test suite.
t_div(Config) when is_list(Config) ->
- ?line 'try'(fun() -> 98765432101234 div 98765432101235 end, 0),
+ 'try'(fun() -> 98765432101234 div 98765432101235 end, 0),
% Big remainder, small quotient.
- ?line 'try'(fun() -> 339254531512 div 68719476736 end, 4),
+ 'try'(fun() -> 339254531512 div 68719476736 end, 4),
ok.
'try'(Fun, Result) ->
@@ -265,65 +245,60 @@ t_div(Config) when is_list(Config) ->
{result, Result} ->
'try'(Iter-1, Fun, Result, [0|Filler]);
{result, Other} ->
- io:format("Expected ~p; got ~p~n", [Result, Other]),
- test_server:fail()
+ ct:fail("Expected ~p; got ~p~n", [Result, Other])
end.
init(ReplyTo, Fun, _Filler) ->
ReplyTo ! {result, Fun()}.
-big_literals(doc) ->
- "Tests that big-number literals work correctly.";
+%% Tests that big-number literals work correctly.
big_literals(Config) when is_list(Config) ->
%% Note: The literal test cannot be compiler on a pre-R4 Beam emulator,
%% so we compile it now.
- ?line DataDir = ?config(data_dir, Config),
- ?line Test = filename:join(DataDir, "literal_test"),
- ?line {ok, Mod, Bin} = compile:file(Test, [binary]),
- ?line {module, Mod} = code:load_binary(Mod, Mod, Bin),
- ?line ok = Mod:t(),
+ DataDir = proplists:get_value(data_dir, Config),
+ Test = filename:join(DataDir, "literal_test"),
+ {ok, Mod, Bin} = compile:file(Test, [binary]),
+ {module, Mod} = code:load_binary(Mod, Mod, Bin),
+ ok = Mod:t(),
ok.
-big_float_1(doc) ->
- ["OTP-2436, part 1"];
+%% OTP-2436, part 1
big_float_1(Config) when is_list(Config) ->
%% F is a number very close to a maximum float.
- ?line F = id(1.7e308),
- ?line I = trunc(F),
- ?line true = (I == F),
- ?line false = (I /= F),
- ?line true = (I > F/2),
- ?line false = (I =< F/2),
- ?line true = (I*2 >= F),
- ?line false = (I*2 < F),
- ?line true = (I*I > F),
- ?line false = (I*I =< F),
-
- ?line true = (F == I),
- ?line false = (F /= I),
- ?line false = (F/2 > I),
- ?line true = (F/2 =< I),
- ?line false = (F >= I*2),
- ?line true = (F < I*2),
- ?line false = (F > I*I),
- ?line true = (F =< I*I),
+ F = id(1.7e308),
+ I = trunc(F),
+ true = (I == F),
+ false = (I /= F),
+ true = (I > F/2),
+ false = (I =< F/2),
+ true = (I*2 >= F),
+ false = (I*2 < F),
+ true = (I*I > F),
+ false = (I*I =< F),
+
+ true = (F == I),
+ false = (F /= I),
+ false = (F/2 > I),
+ true = (F/2 =< I),
+ false = (F >= I*2),
+ true = (F < I*2),
+ false = (F > I*I),
+ true = (F =< I*I),
ok.
-big_float_2(doc) ->
- ["OTP-2436, part 2"];
+%% "OTP-2436, part 2
big_float_2(Config) when is_list(Config) ->
- ?line F = id(1.7e308),
- ?line I = trunc(F),
- ?line {'EXIT', _} = (catch 1/(2*I)),
- ?line _Ignore = 2/I,
- ?line {'EXIT', _} = (catch 4/(2*I)),
+ F = id(1.7e308),
+ I = trunc(F),
+ {'EXIT', _} = (catch 1/(2*I)),
+ _Ignore = 2/I,
+ {'EXIT', _} = (catch 4/(2*I)),
ok.
-shift_limit_1(doc) ->
- ["OTP-3256"];
+%% OTP-3256
shift_limit_1(Config) when is_list(Config) ->
- ?line case catch (id(1) bsl 100000000) of
+ case catch (id(1) bsl 100000000) of
{'EXIT', {system_limit, _}} ->
ok
end,
@@ -352,16 +327,16 @@ powmod(A, B, C) ->
end.
system_limit(Config) when is_list(Config) ->
- ?line Maxbig = maxbig(),
- ?line {'EXIT',{system_limit,_}} = (catch Maxbig+1),
- ?line {'EXIT',{system_limit,_}} = (catch -Maxbig-1),
- ?line {'EXIT',{system_limit,_}} = (catch 2*Maxbig),
- ?line {'EXIT',{system_limit,_}} = (catch bnot Maxbig),
- ?line {'EXIT',{system_limit,_}} = (catch apply(erlang, id('bnot'), [Maxbig])),
- ?line {'EXIT',{system_limit,_}} = (catch Maxbig bsl 2),
- ?line {'EXIT',{system_limit,_}} = (catch apply(erlang, id('bsl'), [Maxbig,2])),
- ?line {'EXIT',{system_limit,_}} = (catch id(1) bsl (1 bsl 45)),
- ?line {'EXIT',{system_limit,_}} = (catch id(1) bsl (1 bsl 69)),
+ Maxbig = maxbig(),
+ {'EXIT',{system_limit,_}} = (catch Maxbig+1),
+ {'EXIT',{system_limit,_}} = (catch -Maxbig-1),
+ {'EXIT',{system_limit,_}} = (catch 2*Maxbig),
+ {'EXIT',{system_limit,_}} = (catch bnot Maxbig),
+ {'EXIT',{system_limit,_}} = (catch apply(erlang, id('bnot'), [Maxbig])),
+ {'EXIT',{system_limit,_}} = (catch Maxbig bsl 2),
+ {'EXIT',{system_limit,_}} = (catch apply(erlang, id('bsl'), [Maxbig,2])),
+ {'EXIT',{system_limit,_}} = (catch id(1) bsl (1 bsl 45)),
+ {'EXIT',{system_limit,_}} = (catch id(1) bsl (1 bsl 69)),
ok.
maxbig() ->
@@ -372,7 +347,7 @@ maxbig() ->
id(I) -> I.
toobig(Config) when is_list(Config) ->
- ?line {'EXIT',{{badmatch,_},_}} = (catch toobig()),
+ {'EXIT',{{badmatch,_},_}} = (catch toobig()),
ok.
toobig() ->
@@ -381,12 +356,9 @@ toobig() ->
<<ANr:ASize>> = A, % should fail
ANr band ANr.
-otp_6692(suite) ->
- [];
-otp_6692(doc) ->
- ["Tests for DIV/REM bug reported in OTP-6692"];
+%% Tests for DIV/REM bug reported in OTP-6692
otp_6692(Config) when is_list(Config)->
- ?line loop1(1,1000).
+ loop1(1,1000).
fact(N) ->
fact(N,1).
diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl
index 96ba2f64d4..fcd49e43d3 100644
--- a/erts/emulator/test/binary_SUITE.erl
+++ b/erts/emulator/test/binary_SUITE.erl
@@ -40,7 +40,7 @@
%% phash2(Binary, N)
%%
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
@@ -106,17 +106,17 @@ end_per_testcase(_Func, _Config) ->
copy_terms(Config) when is_list(Config) ->
Self = self(),
- ?line Pid = spawn_link(fun() -> copy_server(Self) end),
+ Pid = spawn_link(fun() -> copy_server(Self) end),
F = fun(Term) ->
Pid ! Term,
receive
Term -> ok;
Other ->
io:format("Sent: ~P\nGot back:~P", [Term,12,Other,12]),
- ?t:fail(bad_term)
+ ct:fail(bad_term)
end
end,
- ?line test_terms(F),
+ test_terms(F),
ok.
copy_server(Parent) ->
@@ -129,154 +129,152 @@ copy_server(Parent) ->
%% Tests list_to_binary/1, binary_to_list/1 and size/1,
%% using flat lists.
-conversions(suite) -> [];
conversions(Config) when is_list(Config) ->
- ?line test_bin([]),
- ?line test_bin([1]),
- ?line test_bin([1, 2]),
- ?line test_bin([1, 2, 3]),
- ?line test_bin(lists:seq(0, ?heap_binary_size)),
- ?line test_bin(lists:seq(0, ?heap_binary_size+1)),
- ?line test_bin(lists:seq(0, 255)),
- ?line test_bin(lists:duplicate(50000, $@)),
+ test_bin([]),
+ test_bin([1]),
+ test_bin([1, 2]),
+ test_bin([1, 2, 3]),
+ test_bin(lists:seq(0, ?heap_binary_size)),
+ test_bin(lists:seq(0, ?heap_binary_size+1)),
+ test_bin(lists:seq(0, 255)),
+ test_bin(lists:duplicate(50000, $@)),
%% Binary in list.
List = [1,2,3,4,5],
- ?line B1 = make_sub_binary(list_to_binary(List)),
- ?line 5 = size(B1),
- ?line 5 = size(make_unaligned_sub_binary(B1)),
- ?line 40 = bit_size(B1),
- ?line 40 = bit_size(make_unaligned_sub_binary(B1)),
- ?line B2 = list_to_binary([42,B1,19]),
- ?line B2 = list_to_binary([42,make_unaligned_sub_binary(B1),19]),
- ?line B2 = iolist_to_binary(B2),
- ?line B2 = iolist_to_binary(make_unaligned_sub_binary(B2)),
- ?line 7 = size(B2),
- ?line 7 = size(make_sub_binary(B2)),
- ?line 56 = bit_size(B2),
- ?line 56 = bit_size(make_sub_binary(B2)),
- ?line [42,1,2,3,4,5,19] = binary_to_list(B2),
- ?line [42,1,2,3,4,5,19] = binary_to_list(make_sub_binary(B2)),
- ?line [42,1,2,3,4,5,19] = binary_to_list(make_unaligned_sub_binary(B2)),
- ?line [42,1,2,3,4,5,19] = bitstring_to_list(B2),
- ?line [42,1,2,3,4,5,19] = bitstring_to_list(make_sub_binary(B2)),
- ?line [42,1,2,3,4,5,19] = bitstring_to_list(make_unaligned_sub_binary(B2)),
+ B1 = make_sub_binary(list_to_binary(List)),
+ 5 = size(B1),
+ 5 = size(make_unaligned_sub_binary(B1)),
+ 40 = bit_size(B1),
+ 40 = bit_size(make_unaligned_sub_binary(B1)),
+ B2 = list_to_binary([42,B1,19]),
+ B2 = list_to_binary([42,make_unaligned_sub_binary(B1),19]),
+ B2 = iolist_to_binary(B2),
+ B2 = iolist_to_binary(make_unaligned_sub_binary(B2)),
+ 7 = size(B2),
+ 7 = size(make_sub_binary(B2)),
+ 56 = bit_size(B2),
+ 56 = bit_size(make_sub_binary(B2)),
+ [42,1,2,3,4,5,19] = binary_to_list(B2),
+ [42,1,2,3,4,5,19] = binary_to_list(make_sub_binary(B2)),
+ [42,1,2,3,4,5,19] = binary_to_list(make_unaligned_sub_binary(B2)),
+ [42,1,2,3,4,5,19] = bitstring_to_list(B2),
+ [42,1,2,3,4,5,19] = bitstring_to_list(make_sub_binary(B2)),
+ [42,1,2,3,4,5,19] = bitstring_to_list(make_unaligned_sub_binary(B2)),
ok.
test_bin(List) ->
- ?line Size = length(List),
- ?line Bin = list_to_binary(List),
- ?line Bin = iolist_to_binary(List),
- ?line Bin = list_to_bitstring(List),
- ?line Size = iolist_size(List),
- ?line Size = iolist_size(Bin),
- ?line Size = iolist_size(make_unaligned_sub_binary(Bin)),
- ?line Size = size(Bin),
- ?line Size = size(make_sub_binary(Bin)),
- ?line Size = size(make_unaligned_sub_binary(Bin)),
- ?line List = binary_to_list(Bin),
- ?line List = binary_to_list(make_sub_binary(Bin)),
- ?line List = binary_to_list(make_unaligned_sub_binary(Bin)),
- ?line List = bitstring_to_list(Bin),
- ?line List = bitstring_to_list(make_unaligned_sub_binary(Bin)).
+ Size = length(List),
+ Bin = list_to_binary(List),
+ Bin = iolist_to_binary(List),
+ Bin = list_to_bitstring(List),
+ Size = iolist_size(List),
+ Size = iolist_size(Bin),
+ Size = iolist_size(make_unaligned_sub_binary(Bin)),
+ Size = size(Bin),
+ Size = size(make_sub_binary(Bin)),
+ Size = size(make_unaligned_sub_binary(Bin)),
+ List = binary_to_list(Bin),
+ List = binary_to_list(make_sub_binary(Bin)),
+ List = binary_to_list(make_unaligned_sub_binary(Bin)),
+ List = bitstring_to_list(Bin),
+ List = bitstring_to_list(make_unaligned_sub_binary(Bin)).
%% Tests list_to_binary/1, iolist_to_binary/1, list_to_bitstr/1, binary_to_list/1,3,
%% bitstr_to_list/1, and size/1, using deep lists.
deep_lists(Config) when is_list(Config) ->
- ?line test_deep_list(["abc"]),
- ?line test_deep_list([[12,13,[123,15]]]),
- ?line test_deep_list([[12,13,[lists:seq(0, 255), []]]]),
+ test_deep_list(["abc"]),
+ test_deep_list([[12,13,[123,15]]]),
+ test_deep_list([[12,13,[lists:seq(0, 255), []]]]),
ok.
test_deep_list(List) ->
- ?line FlatList = lists:flatten(List),
- ?line Size = length(FlatList),
- ?line Bin = list_to_binary(List),
- ?line Bin = iolist_to_binary(List),
- ?line Bin = iolist_to_binary(Bin),
- ?line Bin = list_to_bitstring(List),
- ?line Size = size(Bin),
- ?line Size = iolist_size(List),
- ?line Size = iolist_size(FlatList),
- ?line Size = iolist_size(Bin),
- ?line Bitsize = bit_size(Bin),
- ?line Bitsize = 8*Size,
- ?line FlatList = binary_to_list(Bin),
- ?line FlatList = bitstring_to_list(Bin),
+ FlatList = lists:flatten(List),
+ Size = length(FlatList),
+ Bin = list_to_binary(List),
+ Bin = iolist_to_binary(List),
+ Bin = iolist_to_binary(Bin),
+ Bin = list_to_bitstring(List),
+ Size = size(Bin),
+ Size = iolist_size(List),
+ Size = iolist_size(FlatList),
+ Size = iolist_size(Bin),
+ Bitsize = bit_size(Bin),
+ Bitsize = 8*Size,
+ FlatList = binary_to_list(Bin),
+ FlatList = bitstring_to_list(Bin),
io:format("testing plain binary..."),
- ?line t_binary_to_list_3(FlatList, Bin, 1, Size),
+ t_binary_to_list_3(FlatList, Bin, 1, Size),
io:format("testing unaligned sub binary..."),
- ?line t_binary_to_list_3(FlatList, make_unaligned_sub_binary(Bin), 1, Size).
+ t_binary_to_list_3(FlatList, make_unaligned_sub_binary(Bin), 1, Size).
t_binary_to_list_3(List, Bin, From, To) ->
- ?line going_up(List, Bin, From, To),
- ?line going_down(List, Bin, From, To),
- ?line going_center(List, Bin, From, To).
+ going_up(List, Bin, From, To),
+ going_down(List, Bin, From, To),
+ going_center(List, Bin, From, To).
going_up(List, Bin, From, To) when From =< To ->
- ?line List = binary_to_list(Bin, From, To),
- ?line going_up(tl(List), Bin, From+1, To);
+ List = binary_to_list(Bin, From, To),
+ going_up(tl(List), Bin, From+1, To);
going_up(_List, _Bin, From, To) when From > To ->
ok.
going_down(List, Bin, From, To) when To > 0->
- ?line compare(List, binary_to_list(Bin, From, To), To-From+1),
- ?line going_down(List, Bin, From, To-1);
+ compare(List, binary_to_list(Bin, From, To), To-From+1),
+ going_down(List, Bin, From, To-1);
going_down(_List, _Bin, _From, _To) ->
ok.
going_center(List, Bin, From, To) when From >= To ->
- ?line compare(List, binary_to_list(Bin, From, To), To-From+1),
- ?line going_center(tl(List), Bin, From+1, To-1);
+ compare(List, binary_to_list(Bin, From, To), To-From+1),
+ going_center(tl(List), Bin, From+1, To-1);
going_center(_List, _Bin, _From, _To) ->
ok.
compare([X|Rest1], [X|Rest2], Left) when Left > 0 ->
- ?line compare(Rest1, Rest2, Left-1);
+ compare(Rest1, Rest2, Left-1);
compare([_X|_], [_Y|_], _Left) ->
- ?line test_server:fail();
+ ct:fail("compare fail");
compare(_List, [], 0) ->
ok.
deep_bitstr_lists(Config) when is_list(Config) ->
- ?line {<<7:3>>,[<<7:3>>]} = test_deep_bitstr([<<7:3>>]),
- ?line {<<42,5:3>>=Bin,[42,<<5:3>>]=List} = test_deep_bitstr([42,<<5:3>>]),
- ?line {Bin,List} = test_deep_bitstr([42|<<5:3>>]),
- ?line {Bin,List} = test_deep_bitstr([<<42,5:3>>]),
- ?line {Bin,List} = test_deep_bitstr([<<1:3>>,<<10:5>>|<<5:3>>]),
- ?line {Bin,List} = test_deep_bitstr([<<1:3>>,<<10:5>>,<<5:3>>]),
- ?line {Bin,List} = test_deep_bitstr([[<<1:3>>,<<10:5>>],[],<<5:3>>]),
- ?line {Bin,List} = test_deep_bitstr([[[<<1:3>>]|<<10:5>>],[],<<5:3>>]),
- ?line {Bin,List} = test_deep_bitstr([[<<0:1>>,<<0:1>>,[],<<1:1>>,<<10:5>>],
+ {<<7:3>>,[<<7:3>>]} = test_deep_bitstr([<<7:3>>]),
+ {<<42,5:3>>=Bin,[42,<<5:3>>]=List} = test_deep_bitstr([42,<<5:3>>]),
+ {Bin,List} = test_deep_bitstr([42|<<5:3>>]),
+ {Bin,List} = test_deep_bitstr([<<42,5:3>>]),
+ {Bin,List} = test_deep_bitstr([<<1:3>>,<<10:5>>|<<5:3>>]),
+ {Bin,List} = test_deep_bitstr([<<1:3>>,<<10:5>>,<<5:3>>]),
+ {Bin,List} = test_deep_bitstr([[<<1:3>>,<<10:5>>],[],<<5:3>>]),
+ {Bin,List} = test_deep_bitstr([[[<<1:3>>]|<<10:5>>],[],<<5:3>>]),
+ {Bin,List} = test_deep_bitstr([[<<0:1>>,<<0:1>>,[],<<1:1>>,<<10:5>>],
<<1:1>>,<<0:1>>,<<1:1>>]),
ok.
test_deep_bitstr(List) ->
- %%?line {'EXIT',{badarg,_}} = list_to_binary(List),
+ %%{'EXIT',{badarg,_}} = list_to_binary(List),
Bin = list_to_bitstring(List),
{Bin,bitstring_to_list(Bin)}.
-bad_list_to_binary(suite) -> [];
bad_list_to_binary(Config) when is_list(Config) ->
- ?line test_bad_bin(atom),
- ?line test_bad_bin(42),
- ?line test_bad_bin([1|2]),
- ?line test_bad_bin([256]),
- ?line test_bad_bin([255, [256]]),
- ?line test_bad_bin([-1]),
- ?line test_bad_bin([atom_in_list]),
- ?line test_bad_bin([[<<8>>]|bad_tail]),
+ test_bad_bin(atom),
+ test_bad_bin(42),
+ test_bad_bin([1|2]),
+ test_bad_bin([256]),
+ test_bad_bin([255, [256]]),
+ test_bad_bin([-1]),
+ test_bad_bin([atom_in_list]),
+ test_bad_bin([[<<8>>]|bad_tail]),
{'EXIT',{badarg,_}} = (catch list_to_binary(id(<<1,2,3>>))),
{'EXIT',{badarg,_}} = (catch list_to_binary(id([<<42:7>>]))),
{'EXIT',{badarg,_}} = (catch list_to_bitstring(id(<<1,2,3>>))),
%% Funs used to be implemented as a type of binary internally.
- ?line test_bad_bin(fun(X, Y) -> X*Y end),
- ?line test_bad_bin([1,fun(X) -> X + 1 end,2|fun() -> 0 end]),
- ?line test_bad_bin([fun(X) -> X + 1 end]),
+ test_bad_bin(fun(X, Y) -> X*Y end),
+ test_bad_bin([1,fun(X) -> X + 1 end,2|fun() -> 0 end]),
+ test_bad_bin([fun(X) -> X + 1 end]),
%% Test iolists that do not fit in the address space.
%% Unfortunately, it would be too slow to test in a 64-bit emulator.
@@ -287,15 +285,15 @@ bad_list_to_binary(Config) when is_list(Config) ->
huge_iolists() ->
FourGigs = 1 bsl 32,
- ?line Sizes = [FourGigs+N || N <- lists:seq(0, 64)] ++
+ Sizes = [FourGigs+N || N <- lists:seq(0, 64)] ++
[1 bsl N || N <- lists:seq(33, 37)],
- ?line Base = <<0:(1 bsl 20)/unit:8>>,
+ Base = <<0:(1 bsl 20)/unit:8>>,
[begin
L = build_iolist(Sz, Base),
- ?line {'EXIT',{system_limit,_}} = (catch list_to_binary([L])),
- ?line {'EXIT',{system_limit,_}} = (catch list_to_bitstring([L])),
- ?line {'EXIT',{system_limit,_}} = (catch binary:list_to_bin([L])),
- ?line {'EXIT',{system_limit,_}} = (catch iolist_to_binary(L))
+ {'EXIT',{system_limit,_}} = (catch list_to_binary([L])),
+ {'EXIT',{system_limit,_}} = (catch list_to_bitstring([L])),
+ {'EXIT',{system_limit,_}} = (catch binary:list_to_bin([L])),
+ {'EXIT',{system_limit,_}} = (catch iolist_to_binary(L))
end || Sz <- Sizes],
ok.
@@ -305,15 +303,15 @@ test_bad_bin(List) ->
{'EXIT',{badarg,_}} = (catch list_to_bitstring(List)),
{'EXIT',{badarg,_}} = (catch iolist_size(List)).
-bad_binary_to_list(doc) -> "Tries binary_to_list/1,3 with bad arguments.";
+%% Tries binary_to_list/1,3 with bad arguments.
bad_binary_to_list(Config) when is_list(Config) ->
- ?line bad_bin_to_list(fun(X) -> X * 42 end),
+ bad_bin_to_list(fun(X) -> X * 42 end),
GoodBin = list_to_binary(lists:seq(1, 10)),
- ?line bad_bin_to_list(fun(X) -> X * 44 end, 1, 2),
- ?line bad_bin_to_list(GoodBin, 0, 1),
- ?line bad_bin_to_list(GoodBin, 2, 1),
- ?line bad_bin_to_list(GoodBin, 11, 11),
+ bad_bin_to_list(fun(X) -> X * 44 end, 1, 2),
+ bad_bin_to_list(GoodBin, 0, 1),
+ bad_bin_to_list(GoodBin, 2, 1),
+ bad_bin_to_list(GoodBin, 11, 11),
{'EXIT',{badarg,_}} = (catch binary_to_list(id(<<42:7>>))),
ok.
@@ -327,63 +325,61 @@ bad_bin_to_list(Bin, First, Last) ->
%% Tries to split a binary at all possible positions.
-t_split_binary(suite) -> [];
t_split_binary(Config) when is_list(Config) ->
- ?line L = lists:seq(0, ?heap_binary_size-5), %Heap binary.
- ?line B = list_to_binary(L),
- ?line split(L, B, size(B)),
+ L = lists:seq(0, ?heap_binary_size-5), %Heap binary.
+ B = list_to_binary(L),
+ split(L, B, size(B)),
%% Sub binary of heap binary.
- ?line split(L, make_sub_binary(B), size(B)),
+ split(L, make_sub_binary(B), size(B)),
{X,_Y} = split_binary(B, size(B) div 2),
- ?line split(binary_to_list(X), X, size(X)),
+ split(binary_to_list(X), X, size(X)),
%% Unaligned sub binary of heap binary.
- ?line split(L, make_unaligned_sub_binary(B), size(B)),
+ split(L, make_unaligned_sub_binary(B), size(B)),
{X,_Y} = split_binary(B, size(B) div 2),
- ?line split(binary_to_list(X), X, size(X)),
+ split(binary_to_list(X), X, size(X)),
%% Reference-counted binary.
- ?line L2 = lists:seq(0, ?heap_binary_size+1),
- ?line B2 = list_to_binary(L2),
- ?line split(L2, B2, size(B2)),
+ L2 = lists:seq(0, ?heap_binary_size+1),
+ B2 = list_to_binary(L2),
+ split(L2, B2, size(B2)),
%% Sub binary of reference-counted binary.
- ?line split(L2, make_sub_binary(B2), size(B2)),
+ split(L2, make_sub_binary(B2), size(B2)),
{X2,_Y2} = split_binary(B2, size(B2) div 2),
- ?line split(binary_to_list(X2), X2, size(X2)),
+ split(binary_to_list(X2), X2, size(X2)),
%% Unaligned sub binary of reference-counted binary.
- ?line split(L2, make_unaligned_sub_binary(B2), size(B2)),
+ split(L2, make_unaligned_sub_binary(B2), size(B2)),
{X2,_Y2} = split_binary(B2, size(B2) div 2),
- ?line split(binary_to_list(X2), X2, size(X2)),
+ split(binary_to_list(X2), X2, size(X2)),
ok.
split(L, B, Pos) when Pos > 0 ->
- ?line {B1, B2} = split_binary(B, Pos),
- ?line B1 = list_to_binary(lists:sublist(L, 1, Pos)),
- ?line B2 = list_to_binary(lists:nthtail(Pos, L)),
- ?line split(L, B, Pos-1);
+ {B1, B2} = split_binary(B, Pos),
+ B1 = list_to_binary(lists:sublist(L, 1, Pos)),
+ B2 = list_to_binary(lists:nthtail(Pos, L)),
+ split(L, B, Pos-1);
split(_L, _B, 0) ->
ok.
-bad_split(doc) -> "Tries split_binary/2 with bad arguments.";
-bad_split(suite) -> [];
+%% Tries split_binary/2 with bad arguments.
bad_split(Config) when is_list(Config) ->
GoodBin = list_to_binary([1,2,3]),
- ?line bad_split(GoodBin, -1),
- ?line bad_split(GoodBin, 4),
- ?line bad_split(GoodBin, a),
+ bad_split(GoodBin, -1),
+ bad_split(GoodBin, 4),
+ bad_split(GoodBin, a),
%% Funs are a kind of binaries.
- ?line bad_split(fun(_X) -> 1 end, 1),
+ bad_split(fun(_X) -> 1 end, 1),
ok.
bad_split(Bin, Pos) ->
{'EXIT',{badarg,_}} = (catch split_binary(Bin, Pos)).
-t_hash(doc) -> "Test hash/2 with different type of binaries.";
+%% Test hash/2 with different type of binaries.
t_hash(Config) when is_list(Config) ->
test_hash([]),
test_hash([253]),
@@ -396,36 +392,34 @@ test_hash(List) ->
Bin = list_to_binary(List),
Sbin = make_sub_binary(List),
Unaligned = make_unaligned_sub_binary(Sbin),
- ?line test_hash_1(Bin, Sbin, Unaligned, fun erlang:hash/2),
- ?line test_hash_1(Bin, Sbin, Unaligned, fun erlang:phash/2),
- ?line test_hash_1(Bin, Sbin, Unaligned, fun erlang:phash2/2).
+ test_hash_1(Bin, Sbin, Unaligned, fun erlang:hash/2),
+ test_hash_1(Bin, Sbin, Unaligned, fun erlang:phash/2),
+ test_hash_1(Bin, Sbin, Unaligned, fun erlang:phash2/2).
test_hash_1(Bin, Sbin, Unaligned, Hash) when is_function(Hash, 2) ->
N = 65535,
case {Hash(Bin, N),Hash(Sbin, N),Hash(Unaligned, N)} of
{H,H,H} -> ok;
{H1,H2,H3} ->
- io:format("Different hash values: ~p, ~p, ~p\n", [H1,H2,H3]),
- ?t:fail()
+ ct:fail("Different hash values: ~p, ~p, ~p\n", [H1,H2,H3])
end.
-bad_size(doc) -> "Try bad arguments to size/1.";
-bad_size(suite) -> [];
+%% Try bad arguments to size/1.
bad_size(Config) when is_list(Config) ->
- ?line {'EXIT',{badarg,_}} = (catch size(fun(X) -> X + 33 end)),
+ {'EXIT',{badarg,_}} = (catch size(fun(X) -> X + 33 end)),
ok.
bad_term_to_binary(Config) when is_list(Config) ->
T = id({a,b,c}),
- ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, not_a_list)),
- ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [blurf])),
- ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,-1}])),
- ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,10}])),
- ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,cucumber}])),
- ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed}])),
- ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{version,1}|bad_tail])),
- ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{minor_version,-1}])),
- ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{minor_version,x}])),
+ {'EXIT',{badarg,_}} = (catch term_to_binary(T, not_a_list)),
+ {'EXIT',{badarg,_}} = (catch term_to_binary(T, [blurf])),
+ {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,-1}])),
+ {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,10}])),
+ {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,cucumber}])),
+ {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed}])),
+ {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{version,1}|bad_tail])),
+ {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{minor_version,-1}])),
+ {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{minor_version,x}])),
ok.
@@ -464,7 +458,7 @@ terms(Config) when is_list(Config) ->
UnalignedC = make_unaligned_sub_binary(BinC),
Term = binary_to_term_stress(UnalignedC)
end,
- ?line test_terms(TestFun),
+ test_terms(TestFun),
ok.
terms_compression_levels(Term, UncompressedSz, Level) when Level < 10 ->
@@ -476,7 +470,7 @@ terms_compression_levels(Term, UncompressedSz, Level) when Level < 10 ->
terms_compression_levels(_, _, _) -> ok.
terms_float(Config) when is_list(Config) ->
- ?line test_floats(fun(Term) ->
+ test_floats(fun(Term) ->
Bin0 = term_to_binary(Term, [{minor_version,0}]),
Term = binary_to_term_stress(Bin0),
Bin1 = term_to_binary(Term),
@@ -492,22 +486,21 @@ terms_float(Config) when is_list(Config) ->
float_middle_endian(Config) when is_list(Config) ->
%% Testing for roundtrip is not enough.
- ?line <<131,70,63,240,0,0,0,0,0,0>> = term_to_binary(1.0, [{minor_version,1}]),
- ?line 1.0 = binary_to_term_stress(<<131,70,63,240,0,0,0,0,0,0>>).
+ <<131,70,63,240,0,0,0,0,0,0>> = term_to_binary(1.0, [{minor_version,1}]),
+ 1.0 = binary_to_term_stress(<<131,70,63,240,0,0,0,0,0,0>>).
external_size(Config) when is_list(Config) ->
%% Build a term whose external size only fits in a big num (on 32-bit CPU).
- ?line external_size_1(16#11111111111111117777777777777777888889999, 0, 16#FFFFFFF),
+ external_size_1(16#11111111111111117777777777777777888889999, 0, 16#FFFFFFF),
%% Test that the same binary aligned and unaligned has the same external size.
- ?line Bin = iolist_to_binary([1,2,3,96]),
- ?line Unaligned = make_unaligned_sub_binary(Bin),
+ Bin = iolist_to_binary([1,2,3,96]),
+ Unaligned = make_unaligned_sub_binary(Bin),
case {erlang:external_size(Bin),erlang:external_size(Unaligned)} of
{X,X} -> ok;
{Sz1,Sz2} ->
- io:format(" Aligned size: ~p\n", [Sz1]),
- io:format("Unaligned size: ~p\n", [Sz2]),
- ?line ?t:fail()
+ ct:fail(" Aligned size: ~p\n"
+ "Unaligned size: ~p\n", [Sz1,Sz2])
end,
true = (erlang:external_size(Bin) =:= erlang:external_size(Bin, [{minor_version, 1}])),
true = (erlang:external_size(Unaligned) =:= erlang:external_size(Unaligned, [{minor_version, 1}])).
@@ -521,30 +514,29 @@ external_size_1(Term, Size0, Limit) when Size0 < Limit ->
external_size_1(_, _, _) -> ok.
t_iolist_size(Config) when is_list(Config) ->
- ?line Seed = {erlang:monotonic_time(),
- erlang:time_offset(),
- erlang:unique_integer([positive])},
- ?line io:format("Seed: ~p", [Seed]),
- ?line random:seed(Seed),
- ?line Base = <<0:(1 bsl 20)/unit:8>>,
- ?line Powers = [1 bsl N || N <- lists:seq(2, 37)],
- ?line Sizes0 = [[N - random:uniform(N div 2),
- lists:seq(N-2, N+2),
- N+N div 2,
- N + random:uniform(N div 2)] ||
- N <- Powers],
+ _ = rand:uniform(), %Seed generator
+ io:format("Seed: ~p", [rand:export_seed()]),
+
+ Base = <<0:(1 bsl 20)/unit:8>>,
+ Powers = [1 bsl N || N <- lists:seq(2, 37)],
+ Sizes0 = [[N - rand:uniform(N div 2),
+ lists:seq(N-2, N+2),
+ N+N div 2,
+ N + rand:uniform(N div 2)] ||
+ N <- Powers],
+
%% Test sizes around 1^32 more thoroughly.
FourGigs = 1 bsl 32,
- ?line Sizes1 = [FourGigs+N || N <- lists:seq(-8, 40)] ++ Sizes0,
- ?line Sizes2 = lists:flatten(Sizes1),
- ?line Sizes = lists:usort(Sizes2),
+ Sizes1 = [FourGigs+N || N <- lists:seq(-8, 40)] ++ Sizes0,
+ Sizes2 = lists:flatten(Sizes1),
+ Sizes = lists:usort(Sizes2),
io:format("~p sizes:", [length(Sizes)]),
io:format("~p\n", [Sizes]),
- ?line [Sz = iolist_size(build_iolist(Sz, Base)) || Sz <- Sizes],
+ _ = [Sz = iolist_size(build_iolist(Sz, Base)) || Sz <- Sizes],
ok.
build_iolist(N, Base) when N < 16 ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 ->
<<Bin:N/binary,_/binary>> = Base,
Bin;
@@ -552,7 +544,7 @@ build_iolist(N, Base) when N < 16 ->
lists:seq(1, N)
end;
build_iolist(N, Base) when N =< byte_size(Base) ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 ->
<<Bin:N/binary,_/binary>> = Base,
Bin;
@@ -570,7 +562,7 @@ build_iolist(N, Base) when N =< byte_size(Base) ->
end
end;
build_iolist(N0, Base) ->
- Small = random:uniform(15),
+ Small = rand:uniform(15),
Seq = lists:seq(1, Small),
N = N0 - Small,
case N rem 2 of
@@ -583,33 +575,32 @@ build_iolist(N0, Base) ->
end.
-bad_binary_to_term_2(doc) -> "OTP-4053.";
-bad_binary_to_term_2(suite) -> [];
+%% OTP-4053
bad_binary_to_term_2(Config) when is_list(Config) ->
- ?line {ok, N} = test_server:start_node(plopp, slave, []),
- ?line R = rpc:call(N, erlang, binary_to_term, [<<131,111,255,255,255,0>>]),
- ?line case R of
+ {ok, N} = test_server:start_node(plopp, slave, []),
+ R = rpc:call(N, erlang, binary_to_term, [<<131,111,255,255,255,0>>]),
+ case R of
{badrpc, {'EXIT', _}} ->
ok;
_Other ->
- test_server:fail({rpcresult, R})
+ ct:fail({rpcresult, R})
end,
- ?line test_server:stop_node(N),
+ test_server:stop_node(N),
ok.
-bad_binary_to_term(doc) -> "Try bad input to binary_to_term/1.";
+%% Try bad input to binary_to_term/1.
bad_binary_to_term(Config) when is_list(Config) ->
- ?line bad_bin_to_term(an_atom),
- ?line bad_bin_to_term({an,tuple}),
- ?line bad_bin_to_term({a,list}),
- ?line bad_bin_to_term(fun() -> self() end),
- ?line bad_bin_to_term(fun(X) -> 42*X end),
- ?line bad_bin_to_term(fun(X, Y) -> {X,Y} end),
- ?line bad_bin_to_term(fun(X, Y, Z) -> {X,Y,Z} end),
- ?line bad_bin_to_term(bit_sized_binary(term_to_binary({you,should,'not',see,this,term}))),
+ bad_bin_to_term(an_atom),
+ bad_bin_to_term({an,tuple}),
+ bad_bin_to_term({a,list}),
+ bad_bin_to_term(fun() -> self() end),
+ bad_bin_to_term(fun(X) -> 42*X end),
+ bad_bin_to_term(fun(X, Y) -> {X,Y} end),
+ bad_bin_to_term(fun(X, Y, Z) -> {X,Y,Z} end),
+ bad_bin_to_term(bit_sized_binary(term_to_binary({you,should,'not',see,this,term}))),
%% Bad float.
- ?line bad_bin_to_term(<<131,70,-1:64>>),
+ bad_bin_to_term(<<131,70,-1:64>>),
ok.
bad_bin_to_term(BadBin) ->
@@ -618,25 +609,24 @@ bad_bin_to_term(BadBin) ->
bad_bin_to_term(BadBin,Opts) ->
{'EXIT',{badarg,_}} = (catch binary_to_term_stress(BadBin,Opts)).
-safe_binary_to_term2(doc) -> "Test safety options for binary_to_term/2";
+%% Test safety options for binary_to_term/2
safe_binary_to_term2(Config) when is_list(Config) ->
- ?line bad_bin_to_term(<<131,100,0,14,"undefined_atom">>, [safe]),
- ?line bad_bin_to_term(<<131,100,0,14,"other_bad_atom">>, [safe]),
+ bad_bin_to_term(<<131,100,0,14,"undefined_atom">>, [safe]),
+ bad_bin_to_term(<<131,100,0,14,"other_bad_atom">>, [safe]),
BadHostAtom = <<100,0,14,"badguy@badhost">>,
Empty = <<0,0,0,0>>,
BadRef = <<131,114,0,3,BadHostAtom/binary,0,<<0,0,0,255>>/binary,
Empty/binary,Empty/binary>>,
- ?line bad_bin_to_term(BadRef, [safe]), % good ref, with a bad atom
- ?line fullsweep_after = binary_to_term_stress(<<131,100,0,15,"fullsweep_after">>, [safe]), % should be a good atom
+ bad_bin_to_term(BadRef, [safe]), % good ref, with a bad atom
+ fullsweep_after = binary_to_term_stress(<<131,100,0,15,"fullsweep_after">>, [safe]), % should be a good atom
BadExtFun = <<131,113,100,0,4,98,108,117,101,100,0,4,109,111,111,110,97,3>>,
- ?line bad_bin_to_term(BadExtFun, [safe]),
+ bad_bin_to_term(BadExtFun, [safe]),
ok.
%% Tests bad input to binary_to_term/1.
-bad_terms(suite) -> [];
bad_terms(Config) when is_list(Config) ->
- ?line test_terms(fun corrupter/1),
+ test_terms(fun corrupter/1),
{'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,3:32,0,11,22,33>>)),
{'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,3:32,9,11,22,33>>)),
{'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,0:32,1,11,22,33>>)),
@@ -669,7 +659,7 @@ corrupter(Term) ->
corrupter0(Term).
corrupter0(Term) ->
- ?line try
+ try
S = io_lib:format("About to corrupt: ~P", [Term,12]),
io:put_chars(S)
catch
@@ -677,42 +667,41 @@ corrupter0(Term) ->
io:format("About to corrupt: <<bit-level-binary:~p",
[bit_size(Term)])
end,
- ?line Bin = term_to_binary(Term),
- ?line corrupter(Bin, size(Bin)-1),
- ?line CompressedBin = term_to_binary(Term, [compressed]),
- ?line corrupter(CompressedBin, size(CompressedBin)-1).
+ Bin = term_to_binary(Term),
+ corrupter(Bin, size(Bin)-1),
+ CompressedBin = term_to_binary(Term, [compressed]),
+ corrupter(CompressedBin, size(CompressedBin)-1).
corrupter(Bin, Pos) when Pos >= 0 ->
- ?line {ShorterBin, Rest} = split_binary(Bin, Pos),
- ?line catch binary_to_term_stress(ShorterBin), %% emulator shouldn't crash
- ?line MovedBin = list_to_binary([ShorterBin]),
- ?line catch binary_to_term_stress(MovedBin), %% emulator shouldn't crash
+ {ShorterBin, Rest} = split_binary(Bin, Pos),
+ catch binary_to_term_stress(ShorterBin), %% emulator shouldn't crash
+ MovedBin = list_to_binary([ShorterBin]),
+ catch binary_to_term_stress(MovedBin), %% emulator shouldn't crash
%% Bit faults, shouldn't crash
<<Byte,Tail/binary>> = Rest,
Fun = fun(M) -> FaultyByte = Byte bxor M,
catch binary_to_term_stress(<<ShorterBin/binary,
FaultyByte, Tail/binary>>) end,
- ?line lists:foreach(Fun,[1,2,4,8,16,32,64,128,255]),
- ?line corrupter(Bin, Pos-1);
+ lists:foreach(Fun,[1,2,4,8,16,32,64,128,255]),
+ corrupter(Bin, Pos-1);
corrupter(_Bin, _) ->
ok.
-more_bad_terms(suite) -> [];
more_bad_terms(Config) when is_list(Config) ->
- ?line Data = ?config(data_dir, Config),
- ?line BadFile = filename:join(Data, "bad_binary"),
- ?line ok = io:format("File: ~s\n", [BadFile]),
- ?line case file:read_file(BadFile) of
+ Data = proplists:get_value(data_dir, Config),
+ BadFile = filename:join(Data, "bad_binary"),
+ ok = io:format("File: ~s\n", [BadFile]),
+ case file:read_file(BadFile) of
{ok,Bin} ->
- ?line {'EXIT',{badarg,_}} = (catch binary_to_term_stress(Bin)),
+ {'EXIT',{badarg,_}} = (catch binary_to_term_stress(Bin)),
ok;
Other ->
- ?line ?t:fail(Other)
+ ct:fail(Other)
end.
otp_5484(Config) when is_list(Config) ->
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch
binary_to_term_stress(
<<131,
@@ -725,7 +714,7 @@ otp_5484(Config) when is_list(Config) ->
255,
106>>)),
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch
binary_to_term_stress(
<<131,
@@ -737,13 +726,13 @@ otp_5484(Config) when is_list(Config) ->
2,
106>>)),
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch
binary_to_term_stress(
%% A old-type fun in a list containing a bad creator pid.
<<131,108,0,0,0,1,117,0,0,0,0,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,255,255,0,25,255,0,0,0,0,100,0,1,116,97,0,98,6,142,121,72,106>>)),
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch
binary_to_term_stress(
%% A new-type fun in a list containing a bad creator pid.
@@ -755,7 +744,7 @@ otp_5484(Config) when is_list(Config) ->
106, %[] instead of an atom.
0,0,0,27,0,0,0,0,0,106>>)),
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch
binary_to_term_stress(
%% A new-type fun in a list containing a bad module.
@@ -766,7 +755,7 @@ otp_5484(Config) when is_list(Config) ->
107,0,1,64, %String instead of atom (same length).
97,0,98,6,64,82,230,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,0,0,0,48,0,0,0,0,0,97,42,97,7,106>>)),
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch
binary_to_term_stress(
%% A new-type fun in a list containing a bad index.
@@ -778,7 +767,7 @@ otp_5484(Config) when is_list(Config) ->
104,0, %Tuple {} instead of integer.
98,6,64,82,230,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,0,0,0,48,0,0,0,0,0,97,42,97,7,106>>)),
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch
binary_to_term_stress(
%% A new-type fun in a list containing a bad unique value.
@@ -792,46 +781,46 @@ otp_5484(Config) when is_list(Config) ->
103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,0,0,0,48,0,0,0,0,0,97,42,97,7,106>>)),
%% An absurdly large atom.
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch binary_to_term_stress(iolist_to_binary([<<131,100,65000:16>>|
lists:duplicate(65000, 42)]))),
%% Longer than 255 characters.
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch binary_to_term_stress(iolist_to_binary([<<131,100,256:16>>|
lists:duplicate(256, 42)]))),
%% OTP-7218. Thanks to Matthew Dempsky. Also make sure that we
%% cover the other error cases for external funs (EXPORT_EXT).
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch binary_to_term_stress(
<<131,
113, %EXPORT_EXP
97,13, %Integer: 13
97,13, %Integer: 13
97,13>>)), %Integer: 13
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch binary_to_term_stress(
<<131,
113, %EXPORT_EXP
100,0,1,64, %Atom: '@'
97,13, %Integer: 13
97,13>>)), %Integer: 13
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch binary_to_term_stress(
<<131,
113, %EXPORT_EXP
100,0,1,64, %Atom: '@'
100,0,1,64, %Atom: '@'
106>>)), %NIL
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch binary_to_term_stress(
<<131,
113, %EXPORT_EXP
100,0,1,64, %Atom: '@'
100,0,1,64, %Atom: '@'
98,255,255,255,255>>)), %Integer: -1
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch binary_to_term_stress(
<<131,
113, %EXPORT_EXP
@@ -840,7 +829,7 @@ otp_5484(Config) when is_list(Config) ->
113,97,13,97,13,97,13>>)), %fun 13:13/13
%% Bad funs.
- ?line {'EXIT',_} = (catch binary_to_term_stress(fake_fun(0, lists:seq(0, 256)))),
+ {'EXIT',_} = (catch binary_to_term_stress(fake_fun(0, lists:seq(0, 256)))),
ok.
fake_fun(Arity, Env0) ->
@@ -863,9 +852,9 @@ fake_fun(Arity, Env0) ->
%% More bad terms submitted by Matthias Lang.
otp_5933(Config) when is_list(Config) ->
- ?line try_bad_lengths(<<131,$m>>), %binary
- ?line try_bad_lengths(<<131,$n>>), %bignum
- ?line try_bad_lengths(<<131,$o>>), %huge bignum
+ try_bad_lengths(<<131,$m>>), %binary
+ try_bad_lengths(<<131,$n>>), %bignum
+ try_bad_lengths(<<131,$o>>), %huge bignum
ok.
try_bad_lengths(B) ->
@@ -884,7 +873,7 @@ otp_6817(Config) when is_list(Config) ->
%% Floats are only validated when the heap fragment has been allocated.
BadFloat = <<131,99,53,46,48,$X,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,101,45,48,49,0,0,0,0,0>>,
- ?line otp_6817_try_bin(BadFloat),
+ otp_6817_try_bin(BadFloat),
%% {Binary,BadFloat}: When the error in float is discovered, a refc-binary
%% has been allocated and the list of refc-binaries goes through the
@@ -904,7 +893,7 @@ otp_6817(Config) when is_list(Config) ->
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,
249,250,251,252,253,254,255,99,51,46,49,52,$B,$l,$u,$r,$f,48,48,48,48,48,48,
48,48,49,50,52,51,52,101,43,48,48,0,0,0,0,0>>,
- ?line otp_6817_try_bin(BinAndFloat),
+ otp_6817_try_bin(BinAndFloat),
%% {Fun,BadFloat}
FunAndFloat =
@@ -912,14 +901,14 @@ otp_6817(Config) when is_list(Config) ->
71,8,0,0,0,0,0,0,0,0,100,0,1,116,97,0,98,5,175,169,123,103,100,0,13,110,111,
110,111,100,101,64,110,111,104,111,115,116,0,0,0,41,0,0,0,0,0,99,50,46,55,48,
$Y,57,57,57,57,57,57,57,57,57,57,57,57,57,54,52,52,55,101,43,48,48,0,0,0,0,0>>,
- ?line otp_6817_try_bin(FunAndFloat),
+ otp_6817_try_bin(FunAndFloat),
%% [ExternalPid|BadFloat]
ExtPidAndFloat =
<<131,108,0,0,0,1,103,100,0,13,107,97,108,108,101,64,115,116,114,105,100,101,
114,0,0,0,36,0,0,0,0,2,99,48,46,$@,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
48,48,48,48,48,101,43,48,48,0,0,0,0,0>>,
- ?line otp_6817_try_bin(ExtPidAndFloat),
+ otp_6817_try_bin(ExtPidAndFloat),
ok.
otp_6817_try_bin(Bin) ->
@@ -937,8 +926,7 @@ otp_6817_try_bin(Bin) ->
%% Will crash if the bug is present.
erlang:garbage_collect().
-otp_8117(doc) -> "Some bugs in binary_to_term when 32-bit integers are negative.";
-otp_8117(suite) -> [];
+%% Some bugs in binary_to_term when 32-bit integers are negative.
otp_8117(Config) when is_list(Config) ->
[otp_8117_do(Op,-(1 bsl N)) || Op <- ['fun',named_fun,list,tuple],
N <- lists:seq(0,31)],
@@ -947,23 +935,22 @@ otp_8117(Config) when is_list(Config) ->
otp_8117_do('fun',Neg) ->
% Fun with negative num_free
FunBin = term_to_binary(fun() -> ok end),
- ?line <<B1:27/binary,_NumFree:32,Rest/binary>> = FunBin,
- ?line bad_bin_to_term(<<B1/binary,Neg:32,Rest/binary>>);
+ <<B1:27/binary,_NumFree:32,Rest/binary>> = FunBin,
+ bad_bin_to_term(<<B1/binary,Neg:32,Rest/binary>>);
otp_8117_do(named_fun,Neg) ->
% Named fun with negative num_free
FunBin = term_to_binary(fun F() -> F end),
- ?line <<B1:27/binary,_NumFree:32,Rest/binary>> = FunBin,
- ?line bad_bin_to_term(<<B1/binary,Neg:32,Rest/binary>>);
+ <<B1:27/binary,_NumFree:32,Rest/binary>> = FunBin,
+ bad_bin_to_term(<<B1/binary,Neg:32,Rest/binary>>);
otp_8117_do(list,Neg) ->
%% List with negative length
- ?line bad_bin_to_term(<<131,104,2,108,Neg:32,97,11,104,1,97,12,97,13,106,97,14>>);
+ bad_bin_to_term(<<131,104,2,108,Neg:32,97,11,104,1,97,12,97,13,106,97,14>>);
otp_8117_do(tuple,Neg) ->
%% Tuple with negative arity
- ?line bad_bin_to_term(<<131,104,2,105,Neg:32,97,11,97,12,97,13,97,14>>).
+ bad_bin_to_term(<<131,104,2,105,Neg:32,97,11,97,12,97,13,97,14>>).
-ordering(doc) -> "Tests ordering of binaries.";
-ordering(suite) -> [];
+%% Tests ordering of binaries.
ordering(Config) when is_list(Config) ->
B1 = list_to_binary([7,8,9]),
B2 = make_sub_binary([1,2,3,4]),
@@ -972,54 +959,54 @@ ordering(Config) when is_list(Config) ->
%% From R8 binaries are compared as strings.
- ?line false = B1 == B2,
- ?line false = B1 =:= B2,
- ?line true = B1 /= B2,
- ?line true = B1 =/= B2,
+ false = B1 == B2,
+ false = B1 =:= B2,
+ true = B1 /= B2,
+ true = B1 =/= B2,
- ?line true = B1 > B2,
- ?line true = B2 < B3,
- ?line true = B2 =< B1,
- ?line true = B2 =< B3,
+ true = B1 > B2,
+ true = B2 < B3,
+ true = B2 =< B1,
+ true = B2 =< B3,
- ?line true = B2 =:= Unaligned,
- ?line true = B2 == Unaligned,
- ?line true = Unaligned < B3,
- ?line true = Unaligned =< B3,
+ true = B2 =:= Unaligned,
+ true = B2 == Unaligned,
+ true = Unaligned < B3,
+ true = Unaligned =< B3,
%% Binaries are greater than all other terms.
- ?line true = B1 > 0,
- ?line true = B1 > 39827491247298471289473333333333333333333333333333,
- ?line true = B1 > -3489274937438742190467869234328742398347,
- ?line true = B1 > 3.14,
- ?line true = B1 > [],
- ?line true = B1 > [a],
- ?line true = B1 > {a},
- ?line true = B1 > self(),
- ?line true = B1 > make_ref(),
- ?line true = B1 > xxx,
- ?line true = B1 > fun() -> 1 end,
- ?line true = B1 > fun erlang:send/2,
-
- ?line Path = ?config(priv_dir, Config),
- ?line AFile = filename:join(Path, "vanilla_file"),
- ?line Port = open_port(AFile, [out]),
- ?line true = B1 > Port,
-
- ?line true = B1 >= 0,
- ?line true = B1 >= 39827491247298471289473333333333333333333333333333,
- ?line true = B1 >= -3489274937438742190467869234328742398347,
- ?line true = B1 >= 3.14,
- ?line true = B1 >= [],
- ?line true = B1 >= [a],
- ?line true = B1 >= {a},
- ?line true = B1 >= self(),
- ?line true = B1 >= make_ref(),
- ?line true = B1 >= xxx,
- ?line true = B1 >= fun() -> 1 end,
- ?line true = B1 >= fun erlang:send/2,
- ?line true = B1 >= Port,
+ true = B1 > 0,
+ true = B1 > 39827491247298471289473333333333333333333333333333,
+ true = B1 > -3489274937438742190467869234328742398347,
+ true = B1 > 3.14,
+ true = B1 > [],
+ true = B1 > [a],
+ true = B1 > {a},
+ true = B1 > self(),
+ true = B1 > make_ref(),
+ true = B1 > xxx,
+ true = B1 > fun() -> 1 end,
+ true = B1 > fun erlang:send/2,
+
+ Path = proplists:get_value(priv_dir, Config),
+ AFile = filename:join(Path, "vanilla_file"),
+ Port = open_port(AFile, [out]),
+ true = B1 > Port,
+
+ true = B1 >= 0,
+ true = B1 >= 39827491247298471289473333333333333333333333333333,
+ true = B1 >= -3489274937438742190467869234328742398347,
+ true = B1 >= 3.14,
+ true = B1 >= [],
+ true = B1 >= [a],
+ true = B1 >= {a},
+ true = B1 >= self(),
+ true = B1 >= make_ref(),
+ true = B1 >= xxx,
+ true = B1 >= fun() -> 1 end,
+ true = B1 >= fun erlang:send/2,
+ true = B1 >= Port,
ok.
@@ -1032,153 +1019,153 @@ unaligned_order(Config) when is_list(Config) ->
test_unaligned_order(I, J) ->
Align = {I,J},
io:format("~p ~p", [I,J]),
- ?line true = test_unaligned_order_1('=:=', <<1,2,3,16#AA,16#7C,4,16#5F,5,16#5A>>,
+ true = test_unaligned_order_1('=:=', <<1,2,3,16#AA,16#7C,4,16#5F,5,16#5A>>,
<<1,2,3,16#AA,16#7C,4,16#5F,5,16#5A>>,
Align),
- ?line false = test_unaligned_order_1('=/=', <<1,2,3>>, <<1,2,3>>, Align),
- ?line true = test_unaligned_order_1('==', <<4,5,6>>, <<4,5,6>>, Align),
- ?line false = test_unaligned_order_1('/=', <<1,2,3>>, <<1,2,3>>, Align),
+ false = test_unaligned_order_1('=/=', <<1,2,3>>, <<1,2,3>>, Align),
+ true = test_unaligned_order_1('==', <<4,5,6>>, <<4,5,6>>, Align),
+ false = test_unaligned_order_1('/=', <<1,2,3>>, <<1,2,3>>, Align),
- ?line true = test_unaligned_order_1('<', <<1,2>>, <<1,2,3>>, Align),
- ?line true = test_unaligned_order_1('=<', <<1,2>>, <<1,2,3>>, Align),
- ?line true = test_unaligned_order_1('=<', <<1,2,7,8>>, <<1,2,7,8>>, Align),
+ true = test_unaligned_order_1('<', <<1,2>>, <<1,2,3>>, Align),
+ true = test_unaligned_order_1('=<', <<1,2>>, <<1,2,3>>, Align),
+ true = test_unaligned_order_1('=<', <<1,2,7,8>>, <<1,2,7,8>>, Align),
ok.
test_unaligned_order_1(Op, A, B, {Aa,Ba}) ->
erlang:Op(unaligned_sub_bin(A, Aa), unaligned_sub_bin(B, Ba)).
test_terms(Test_Func) ->
- ?line Test_Func(atom),
- ?line Test_Func(''),
- ?line Test_Func('a'),
- ?line Test_Func('ab'),
- ?line Test_Func('abc'),
- ?line Test_Func('abcd'),
- ?line Test_Func('abcde'),
- ?line Test_Func('abcdef'),
- ?line Test_Func('abcdefg'),
- ?line Test_Func('abcdefgh'),
-
- ?line Test_Func(fun() -> ok end),
+ Test_Func(atom),
+ Test_Func(''),
+ Test_Func('a'),
+ Test_Func('ab'),
+ Test_Func('abc'),
+ Test_Func('abcd'),
+ Test_Func('abcde'),
+ Test_Func('abcdef'),
+ Test_Func('abcdefg'),
+ Test_Func('abcdefgh'),
+
+ Test_Func(fun() -> ok end),
X = id([a,{b,c},c]),
Y = id({x,y,z}),
Z = id(1 bsl 8*257),
- ?line Test_Func(fun() -> X end),
- ?line Test_Func(fun() -> {X,Y} end),
- ?line Test_Func([fun() -> {X,Y,Z} end,
+ Test_Func(fun() -> X end),
+ Test_Func(fun() -> {X,Y} end),
+ Test_Func([fun() -> {X,Y,Z} end,
fun() -> {Z,X,Y} end,
fun() -> {Y,Z,X} end]),
- ?line Test_Func({trace_ts,{even_bigger,{some_data,fun() -> ok end}},{1,2,3}}),
- ?line Test_Func({trace_ts,{even_bigger,{some_data,<<1,2,3,4,5,6,7,8,9,10>>}},
+ Test_Func({trace_ts,{even_bigger,{some_data,fun() -> ok end}},{1,2,3}}),
+ Test_Func({trace_ts,{even_bigger,{some_data,<<1,2,3,4,5,6,7,8,9,10>>}},
{1,2,3}}),
- ?line Test_Func(1),
- ?line Test_Func(42),
- ?line Test_Func(-23),
- ?line Test_Func(256),
- ?line Test_Func(25555),
- ?line Test_Func(-3333),
+ Test_Func(1),
+ Test_Func(42),
+ Test_Func(-23),
+ Test_Func(256),
+ Test_Func(25555),
+ Test_Func(-3333),
- ?line Test_Func(1.0),
+ Test_Func(1.0),
- ?line Test_Func(183749783987483978498378478393874),
- ?line Test_Func(-37894183749783987483978498378478393874),
+ Test_Func(183749783987483978498378478393874),
+ Test_Func(-37894183749783987483978498378478393874),
Very_Big = very_big_num(),
- ?line Test_Func(Very_Big),
- ?line Test_Func(-Very_Big+1),
-
- ?line Test_Func([]),
- ?line Test_Func("abcdef"),
- ?line Test_Func([a, b, 1, 2]),
- ?line Test_Func([a|b]),
-
- ?line Test_Func({}),
- ?line Test_Func({1}),
- ?line Test_Func({a, b}),
- ?line Test_Func({a, b, c}),
- ?line Test_Func(list_to_tuple(lists:seq(0, 255))),
- ?line Test_Func(list_to_tuple(lists:seq(0, 256))),
-
- ?line Test_Func(make_ref()),
- ?line Test_Func([make_ref(), make_ref()]),
-
- ?line Test_Func(make_port()),
-
- ?line Test_Func(make_pid()),
-
- ?line Test_Func(Bin0 = list_to_binary(lists:seq(0, 14))),
- ?line Test_Func(Bin1 = list_to_binary(lists:seq(0, ?heap_binary_size))),
- ?line Test_Func(Bin2 = list_to_binary(lists:seq(0, ?heap_binary_size+1))),
- ?line Test_Func(Bin3 = list_to_binary(lists:seq(0, 255))),
-
- ?line Test_Func(make_unaligned_sub_binary(Bin0)),
- ?line Test_Func(make_unaligned_sub_binary(Bin1)),
- ?line Test_Func(make_unaligned_sub_binary(Bin2)),
- ?line Test_Func(make_unaligned_sub_binary(Bin3)),
-
- ?line Test_Func(make_sub_binary(lists:seq(42, 43))),
- ?line Test_Func(make_sub_binary([42,43,44])),
- ?line Test_Func(make_sub_binary([42,43,44,45])),
- ?line Test_Func(make_sub_binary([42,43,44,45,46])),
- ?line Test_Func(make_sub_binary([42,43,44,45,46,47])),
- ?line Test_Func(make_sub_binary([42,43,44,45,46,47,48])),
- ?line Test_Func(make_sub_binary(lists:seq(42, 49))),
- ?line Test_Func(make_sub_binary(lists:seq(0, 14))),
- ?line Test_Func(make_sub_binary(lists:seq(0, ?heap_binary_size))),
- ?line Test_Func(make_sub_binary(lists:seq(0, ?heap_binary_size+1))),
- ?line Test_Func(make_sub_binary(lists:seq(0, 255))),
-
- ?line Test_Func(make_unaligned_sub_binary(lists:seq(42, 43))),
- ?line Test_Func(make_unaligned_sub_binary([42,43,44])),
- ?line Test_Func(make_unaligned_sub_binary([42,43,44,45])),
- ?line Test_Func(make_unaligned_sub_binary([42,43,44,45,46])),
- ?line Test_Func(make_unaligned_sub_binary([42,43,44,45,46,47])),
- ?line Test_Func(make_unaligned_sub_binary([42,43,44,45,46,47,48])),
- ?line Test_Func(make_unaligned_sub_binary(lists:seq(42, 49))),
- ?line Test_Func(make_unaligned_sub_binary(lists:seq(0, 14))),
- ?line Test_Func(make_unaligned_sub_binary(lists:seq(0, ?heap_binary_size))),
- ?line Test_Func(make_unaligned_sub_binary(lists:seq(0, ?heap_binary_size+1))),
- ?line Test_Func(make_unaligned_sub_binary(lists:seq(0, 255))),
+ Test_Func(Very_Big),
+ Test_Func(-Very_Big+1),
+
+ Test_Func([]),
+ Test_Func("abcdef"),
+ Test_Func([a, b, 1, 2]),
+ Test_Func([a|b]),
+
+ Test_Func({}),
+ Test_Func({1}),
+ Test_Func({a, b}),
+ Test_Func({a, b, c}),
+ Test_Func(list_to_tuple(lists:seq(0, 255))),
+ Test_Func(list_to_tuple(lists:seq(0, 256))),
+
+ Test_Func(make_ref()),
+ Test_Func([make_ref(), make_ref()]),
+
+ Test_Func(make_port()),
+
+ Test_Func(make_pid()),
+
+ Test_Func(Bin0 = list_to_binary(lists:seq(0, 14))),
+ Test_Func(Bin1 = list_to_binary(lists:seq(0, ?heap_binary_size))),
+ Test_Func(Bin2 = list_to_binary(lists:seq(0, ?heap_binary_size+1))),
+ Test_Func(Bin3 = list_to_binary(lists:seq(0, 255))),
+
+ Test_Func(make_unaligned_sub_binary(Bin0)),
+ Test_Func(make_unaligned_sub_binary(Bin1)),
+ Test_Func(make_unaligned_sub_binary(Bin2)),
+ Test_Func(make_unaligned_sub_binary(Bin3)),
+
+ Test_Func(make_sub_binary(lists:seq(42, 43))),
+ Test_Func(make_sub_binary([42,43,44])),
+ Test_Func(make_sub_binary([42,43,44,45])),
+ Test_Func(make_sub_binary([42,43,44,45,46])),
+ Test_Func(make_sub_binary([42,43,44,45,46,47])),
+ Test_Func(make_sub_binary([42,43,44,45,46,47,48])),
+ Test_Func(make_sub_binary(lists:seq(42, 49))),
+ Test_Func(make_sub_binary(lists:seq(0, 14))),
+ Test_Func(make_sub_binary(lists:seq(0, ?heap_binary_size))),
+ Test_Func(make_sub_binary(lists:seq(0, ?heap_binary_size+1))),
+ Test_Func(make_sub_binary(lists:seq(0, 255))),
+
+ Test_Func(make_unaligned_sub_binary(lists:seq(42, 43))),
+ Test_Func(make_unaligned_sub_binary([42,43,44])),
+ Test_Func(make_unaligned_sub_binary([42,43,44,45])),
+ Test_Func(make_unaligned_sub_binary([42,43,44,45,46])),
+ Test_Func(make_unaligned_sub_binary([42,43,44,45,46,47])),
+ Test_Func(make_unaligned_sub_binary([42,43,44,45,46,47,48])),
+ Test_Func(make_unaligned_sub_binary(lists:seq(42, 49))),
+ Test_Func(make_unaligned_sub_binary(lists:seq(0, 14))),
+ Test_Func(make_unaligned_sub_binary(lists:seq(0, ?heap_binary_size))),
+ Test_Func(make_unaligned_sub_binary(lists:seq(0, ?heap_binary_size+1))),
+ Test_Func(make_unaligned_sub_binary(lists:seq(0, 255))),
%% Bit level binaries.
- ?line Test_Func(<<1:1>>),
- ?line Test_Func(<<2:2>>),
- ?line Test_Func(<<42:10>>),
- ?line Test_Func(list_to_bitstring([<<5:6>>|lists:seq(0, 255)])),
+ Test_Func(<<1:1>>),
+ Test_Func(<<2:2>>),
+ Test_Func(<<42:10>>),
+ Test_Func(list_to_bitstring([<<5:6>>|lists:seq(0, 255)])),
- ?line Test_Func(F = fun(A) -> 42*A end),
- ?line Test_Func(lists:duplicate(32, F)),
+ Test_Func(F = fun(A) -> 42*A end),
+ Test_Func(lists:duplicate(32, F)),
- ?line Test_Func(FF = fun binary_SUITE:all/0),
- ?line Test_Func(lists:duplicate(32, FF)),
+ Test_Func(FF = fun binary_SUITE:all/0),
+ Test_Func(lists:duplicate(32, FF)),
ok.
test_floats(Test_Func) ->
- ?line Test_Func(5.5),
- ?line Test_Func(-15.32),
- ?line Test_Func(1.2435e25),
- ?line Test_Func(1.2333e-20),
- ?line Test_Func(199.0e+15),
+ Test_Func(5.5),
+ Test_Func(-15.32),
+ Test_Func(1.2435e25),
+ Test_Func(1.2333e-20),
+ Test_Func(199.0e+15),
ok.
very_big_num() ->
very_big_num(33, 1).
very_big_num(Left, Result) when Left > 0 ->
- ?line very_big_num(Left-1, Result*256);
+ very_big_num(Left-1, Result*256);
very_big_num(0, Result) ->
- ?line Result.
+ Result.
make_port() ->
- ?line open_port({spawn, efile}, [eof]).
+ open_port({spawn, efile}, [eof]).
make_pid() ->
- ?line spawn_link(?MODULE, sleeper, []).
+ spawn_link(?MODULE, sleeper, []).
sleeper() ->
- ?line receive after infinity -> ok end.
+ receive after infinity -> ok end.
%% Test that binaries are garbage collected properly.
@@ -1218,7 +1205,7 @@ gc_test1(Pid) ->
receive
{Pid,done} -> ok
after 10000 ->
- ?line ?t:fail()
+ ct:fail("timeout")
end.
%% Like split binary, but returns REFC binaries. Only useful for gc_test/1.
@@ -1237,7 +1224,7 @@ gc() ->
gc1() -> ok.
bit_sized_binary_sizes(Config) when is_list(Config) ->
- ?line [bsbs_1(A) || A <- lists:seq(1, 8)],
+ [bsbs_1(A) || A <- lists:seq(1, 8)],
ok.
bsbs_1(A) ->
@@ -1279,13 +1266,13 @@ obsolete_funs(Config) when is_list(Config) ->
X = id({1,2,3}),
Y = id([a,b,c,d]),
Z = id({x,y,z}),
- ?line obsolete_fun(fun() -> ok end),
- ?line obsolete_fun(fun() -> X end),
- ?line obsolete_fun(fun(A) -> {A,X} end),
- ?line obsolete_fun(fun() -> {X,Y} end),
- ?line obsolete_fun(fun() -> {X,Y,Z} end),
+ obsolete_fun(fun() -> ok end),
+ obsolete_fun(fun() -> X end),
+ obsolete_fun(fun(A) -> {A,X} end),
+ obsolete_fun(fun() -> {X,Y} end),
+ obsolete_fun(fun() -> {X,Y,Z} end),
- ?line obsolete_fun(fun ?MODULE:all/1),
+ obsolete_fun(fun ?MODULE:all/1),
erts_debug:set_internal_state(available_internal_state, false),
ok.
@@ -1312,41 +1299,41 @@ no_fun_roundtrip(Term) ->
%% but recognized by binary_to_term/1.
robustness(Config) when is_list(Config) ->
- ?line [] = binary_to_term_stress(<<131,107,0,0>>), %Empty string.
- ?line [] = binary_to_term_stress(<<131,108,0,0,0,0,106>>), %Zero-length list.
+ [] = binary_to_term_stress(<<131,107,0,0>>), %Empty string.
+ [] = binary_to_term_stress(<<131,108,0,0,0,0,106>>), %Zero-length list.
%% {[],a} where [] is a zero-length list.
- ?line {[],a} = binary_to_term_stress(<<131,104,2,108,0,0,0,0,106,100,0,1,97>>),
+ {[],a} = binary_to_term_stress(<<131,104,2,108,0,0,0,0,106,100,0,1,97>>),
%% {42,a} where 42 is a zero-length list with 42 in the tail.
- ?line {42,a} = binary_to_term_stress(<<131,104,2,108,0,0,0,0,97,42,100,0,1,97>>),
+ {42,a} = binary_to_term_stress(<<131,104,2,108,0,0,0,0,97,42,100,0,1,97>>),
%% {{x,y},a} where {x,y} is a zero-length list with {x,y} in the tail.
- ?line {{x,y},a} = binary_to_term_stress(<<131,104,2,108,0,0,0,0,
+ {{x,y},a} = binary_to_term_stress(<<131,104,2,108,0,0,0,0,
104,2,100,0,1,120,100,0,1,
121,100,0,1,97>>),
%% Bignums fitting in 32 bits.
- ?line 16#7FFFFFFF = binary_to_term_stress(<<131,98,127,255,255,255>>),
- ?line -1 = binary_to_term_stress(<<131,98,255,255,255,255>>),
+ 16#7FFFFFFF = binary_to_term_stress(<<131,98,127,255,255,255>>),
+ -1 = binary_to_term_stress(<<131,98,255,255,255,255>>),
ok.
%% OTP-8180: Test several terms that have been known to crash the emulator.
%% (Thanks to Scott Lystig Fritchie.)
otp_8180(Config) when is_list(Config) ->
- ?line Data = ?config(data_dir, Config),
- ?line Wc = filename:join(Data, "zzz.*"),
+ Data = proplists:get_value(data_dir, Config),
+ Wc = filename:join(Data, "zzz.*"),
Files = filelib:wildcard(Wc),
[run_otp_8180(F) || F <- Files],
ok.
run_otp_8180(Name) ->
io:format("~s", [Name]),
- ?line {ok,Bins} = file:consult(Name),
+ {ok,Bins} = file:consult(Name),
[begin
io:format("~p\n", [Bin]),
- ?line {'EXIT',{badarg,_}} = (catch binary_to_term_stress(Bin))
+ {'EXIT',{badarg,_}} = (catch binary_to_term_stress(Bin))
end || Bin <- Bins],
ok.
@@ -1518,7 +1505,7 @@ cmp_old_impl(Config) when is_list(Config) ->
false ->
{skipped, "No "++Rel++" available"};
true ->
- {ok, Node} = ?t:start_node(list_to_atom(atom_to_list(?MODULE)++"_"++Rel),
+ {ok, Node} = test_server:start_node(list_to_atom(atom_to_list(?MODULE)++"_"++Rel),
peer,
[{args, " -setcookie "++Cookie},
{erl, [{release, Rel}]}]),
@@ -1560,7 +1547,7 @@ cmp_old_impl(Config) when is_list(Config) ->
cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(1000000)))]}),
cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(10000000)))]}),
- ?t:stop_node(Node),
+ test_server:stop_node(Node),
ok
end.
@@ -1604,7 +1591,7 @@ bit_sized_binary(Bin0) ->
unaligned_sub_bin(Bin, 0) -> Bin;
unaligned_sub_bin(Bin0, Offs) ->
- F = random:uniform(256),
+ F = rand:uniform(256),
Roffs = 8-Offs,
Bin1 = <<F:Offs,Bin0/binary,F:Roffs>>,
Sz = size(Bin0),
diff --git a/erts/emulator/test/bs_bincomp_SUITE.erl b/erts/emulator/test/bs_bincomp_SUITE.erl
index dcd13c19df..8836fe40ae 100644
--- a/erts/emulator/test/bs_bincomp_SUITE.erl
+++ b/erts/emulator/test/bs_bincomp_SUITE.erl
@@ -131,7 +131,7 @@ tracing(Config) when is_list(Config) ->
random_binary() ->
Seq = [1,2,3,4,5,6,7,8,9,10],
- << <<($a + random:uniform($z - $a)):8>> || _ <- Seq >>.
+ << <<($a + rand:uniform($z - $a)):8>> || _ <- Seq >>.
random_binaries(N) when N > 0 ->
random_binary(),
diff --git a/erts/emulator/test/bs_bit_binaries_SUITE.erl b/erts/emulator/test/bs_bit_binaries_SUITE.erl
index a07fd7609c..dd056d10af 100644
--- a/erts/emulator/test/bs_bit_binaries_SUITE.erl
+++ b/erts/emulator/test/bs_bit_binaries_SUITE.erl
@@ -30,7 +30,7 @@
big_binary_to_and_from_list/1,send_and_receive/1,
send_and_receive_alot/1,append/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -57,9 +57,9 @@ end_per_group(_GroupName, Config) ->
misc(Config) when is_list(Config) ->
- ?line <<1:100>> = id(<<1:100>>),
- ?line {ok,ok} = {match(7),match(9)},
- ?line {ok,ok} = {match1(15),match1(31)},
+ <<1:100>> = id(<<1:100>>),
+ {ok,ok} = {match(7),match(9)},
+ {ok,ok} = {match1(15),match1(31)},
ok.
@@ -76,70 +76,70 @@ match1(N) ->
ok.
test_bit_size(Config) when is_list(Config) ->
- ?line 101 = bit_size(<<1:101>>),
- ?line 1001 = bit_size(<<1:1001>>),
- ?line 80 = bit_size(<<1:80>>),
- ?line 800 = bit_size(<<1:800>>),
- ?line Bin = <<0:16#1000000>>,
- ?line BigBin = list_to_bitstring([Bin||_ <- lists:seq(1,16#10)]++[<<1:1>>]),
- ?line 16#10000001 = erlang:bit_size(BigBin),
+ 101 = bit_size(<<1:101>>),
+ 1001 = bit_size(<<1:1001>>),
+ 80 = bit_size(<<1:80>>),
+ 800 = bit_size(<<1:800>>),
+ Bin = <<0:16#1000000>>,
+ BigBin = list_to_bitstring([Bin||_ <- lists:seq(1,16#10)]++[<<1:1>>]),
+ 16#10000001 = erlang:bit_size(BigBin),
%% Only run these on computers with lots of memory
%% HugeBin = list_to_bitstring([BigBin||_ <- lists:seq(1,16#10)]++[<<1:1>>]),
%% 16#100000011 = bit_size(HugeBin),
- ?line 0 = bit_size(<<>>),
+ 0 = bit_size(<<>>),
ok.
horrid_match(Config) when is_list(Config) ->
- ?line <<1:4,B:24/bitstring>> = <<1:4,42:24/little>>,
- ?line <<42:24/little>> = B,
+ <<1:4,B:24/bitstring>> = <<1:4,42:24/little>>,
+ <<42:24/little>> = B,
ok.
test_bitstr(Config) when is_list(Config) ->
- ?line <<1:7,B/bitstring>> = <<1:7,<<1:1,6>>/bitstring>>,
- ?line <<1:1,6>> = B,
- ?line B = <<1:1,6>>,
+ <<1:7,B/bitstring>> = <<1:7,<<1:1,6>>/bitstring>>,
+ <<1:1,6>> = B,
+ B = <<1:1,6>>,
ok.
asymmetric_tests(Config) when is_list(Config) ->
- ?line <<1:12>> = <<0,1:4>>,
- ?line <<0,1:4>> = <<1:12>>,
- ?line <<1:1,X/bitstring>> = <<128,255,0,0:2>>,
- ?line <<1,254,0,0:1>> = X,
- ?line X = <<1,254,0,0:1>>,
- ?line <<1:1,X1:25/bitstring>> = <<128,255,0,0:2>>,
- ?line <<1,254,0,0:1>> = X1,
- ?line X1 = <<1,254,0,0:1>>,
+ <<1:12>> = <<0,1:4>>,
+ <<0,1:4>> = <<1:12>>,
+ <<1:1,X/bitstring>> = <<128,255,0,0:2>>,
+ <<1,254,0,0:1>> = X,
+ X = <<1,254,0,0:1>>,
+ <<1:1,X1:25/bitstring>> = <<128,255,0,0:2>>,
+ <<1,254,0,0:1>> = X1,
+ X1 = <<1,254,0,0:1>>,
ok.
big_asymmetric_tests(Config) when is_list(Config) ->
- ?line <<1:875,1:12>> = <<1:875,0,1:4>>,
- ?line <<1:875,0,1:4>> = <<1:875,1:12>>,
- ?line <<1:1,X/bitstring>> = <<128,255,0,0:2,1:875>>,
- ?line <<1,254,0,0:1,1:875>> = X,
- ?line X = <<1,254,0,0:1,1:875>>,
- ?line <<1:1,X1:900/bitstring>> = <<128,255,0,0:2,1:875>>,
- ?line <<1,254,0,0:1,1:875>> = X1,
- ?line X1 = <<1,254,0,0:1,1:875>>,
+ <<1:875,1:12>> = <<1:875,0,1:4>>,
+ <<1:875,0,1:4>> = <<1:875,1:12>>,
+ <<1:1,X/bitstring>> = <<128,255,0,0:2,1:875>>,
+ <<1,254,0,0:1,1:875>> = X,
+ X = <<1,254,0,0:1,1:875>>,
+ <<1:1,X1:900/bitstring>> = <<128,255,0,0:2,1:875>>,
+ <<1,254,0,0:1,1:875>> = X1,
+ X1 = <<1,254,0,0:1,1:875>>,
ok.
binary_to_and_from_list(Config) when is_list(Config) ->
- ?line <<1,2,3,4,1:1>> = list_to_bitstring(bitstring_to_list(<<1,2,3,4,1:1>>)),
- ?line [1,2,3,4,<<1:1>>] = bitstring_to_list(<<1,2,3,4,1:1>>),
- ?line <<1:1,1,2,3,4>> = list_to_bitstring([<<1:1>>,1,2,3,4]),
- ?line [128,129,1,130,<<0:1>>] = bitstring_to_list(<<1:1,1,2,3,4>>),
+ <<1,2,3,4,1:1>> = list_to_bitstring(bitstring_to_list(<<1,2,3,4,1:1>>)),
+ [1,2,3,4,<<1:1>>] = bitstring_to_list(<<1,2,3,4,1:1>>),
+ <<1:1,1,2,3,4>> = list_to_bitstring([<<1:1>>,1,2,3,4]),
+ [128,129,1,130,<<0:1>>] = bitstring_to_list(<<1:1,1,2,3,4>>),
ok.
big_binary_to_and_from_list(Config) when is_list(Config) ->
- ?line <<1:800,2,3,4,1:1>> = list_to_bitstring(bitstring_to_list(<<1:800,2,3,4,1:1>>)),
- ?line [1,2,3,4|_Rest1] = bitstring_to_list(<<1,2,3,4,1:800,1:1>>),
- ?line <<1:801,1,2,3,4>> = list_to_bitstring([<<1:801>>,1,2,3,4]),
+ <<1:800,2,3,4,1:1>> = list_to_bitstring(bitstring_to_list(<<1:800,2,3,4,1:1>>)),
+ [1,2,3,4|_Rest1] = bitstring_to_list(<<1,2,3,4,1:800,1:1>>),
+ <<1:801,1,2,3,4>> = list_to_bitstring([<<1:801>>,1,2,3,4]),
ok.
send_and_receive(Config) when is_list(Config) ->
- ?line Bin = <<1,2:7>>,
+ Bin = <<1,2:7>>,
Pid = spawn_link(fun() -> receiver(Bin) end),
- ?line Pid ! {self(),<<1:7,8:5,Bin/bitstring>>},
- ?line receive
+ Pid ! {self(),<<1:7,8:5,Bin/bitstring>>},
+ receive
ok ->
ok
end.
@@ -176,8 +176,8 @@ receiver_alot(Bin) ->
append(Config) when is_list(Config) ->
cs_init(),
- ?line <<(-1):256/signed-unit:8>> = cs(do_append(id(<<>>), 256*8)),
- ?line <<(-1):256/signed-unit:8>> = cs(do_append2(id(<<>>), 256*4)),
+ <<(-1):256/signed-unit:8>> = cs(do_append(id(<<>>), 256*8)),
+ <<(-1):256/signed-unit:8>> = cs(do_append2(id(<<>>), 256*4)),
<<(-1):256/signed-unit:8>> = cs(do_append3(id(<<>>), 256*8)),
cs_end().
diff --git a/erts/emulator/test/bs_construct_SUITE.erl b/erts/emulator/test/bs_construct_SUITE.erl
index 7ed99f5b4e..8deb0c7422 100644
--- a/erts/emulator/test/bs_construct_SUITE.erl
+++ b/erts/emulator/test/bs_construct_SUITE.erl
@@ -22,8 +22,7 @@
-module(bs_construct_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
+-export([all/0, suite/0,
test1/1, test2/1, test3/1, test4/1, test5/1, testf/1,
not_used/1, in_guard/1,
mem_leak/1, coerce_to_float/1, bjorn/1,
@@ -31,9 +30,11 @@
copy_writable_binary/1, kostis/1, dynamic/1, bs_add/1,
otp_7422/1, zero_width/1, bad_append/1, bs_add_overflow/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {seconds, 10}}].
all() ->
[test1, test2, test3, test4, test5, testf, not_used,
@@ -42,21 +43,6 @@ all() ->
copy_writable_binary, kostis, dynamic, bs_add, otp_7422, zero_width,
bad_append, bs_add_overflow].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
big(1) ->
57285702734876389752897683.
@@ -68,9 +54,9 @@ r(L) ->
-define(T(B, L), {B, ??B, L}).
-define(N(B), {B, ??B, unknown}).
--define(FAIL(Expr), ?line fail_check(catch Expr, ??Expr, [])).
+-define(FAIL(Expr), fail_check(catch Expr, ??Expr, [])).
--define(FAIL_VARS(Expr, Vars), ?line fail_check(catch Expr, ??Expr, Vars)).
+-define(FAIL_VARS(Expr, Vars), fail_check(catch Expr, ??Expr, Vars)).
l(I_13, I_big1) ->
[
@@ -189,7 +175,7 @@ one_test({C_bin, E_bin, Str, Bytes}) when is_list(Bytes) ->
true ->
io:format("ERROR: Compiled: ~p. Expected ~p. Got ~p.~n",
[Str, Bytes, binary_to_list(C_bin)]),
- test_server:fail(comp)
+ ct:fail(comp)
end,
if
E_bin == Bin ->
@@ -197,7 +183,7 @@ one_test({C_bin, E_bin, Str, Bytes}) when is_list(Bytes) ->
true ->
io:format("ERROR: Interpreted: ~p. Expected ~p. Got ~p.~n",
[Str, Bytes, binary_to_list(E_bin)]),
- test_server:fail(comp)
+ ct:fail(comp)
end;
one_test({C_bin, E_bin, Str, Result}) ->
io:format(" ~s ~p~n", [Str, C_bin]),
@@ -218,7 +204,7 @@ one_test({C_bin, E_bin, Str, Result}) ->
io:format("ERROR: Compiled not equal to interpreted:"
"~n ~p, ~p.~n",
[binary_to_list(C_bin), binary_to_list(E_bin)]),
- test_server:fail(comp);
+ ct:fail(comp);
0 ->
ok;
%% For situations where the final bits may not matter, like
@@ -253,23 +239,22 @@ fail_check({'EXIT',{badarg,_}}, Str, Vars) ->
try evaluate(Str, Vars) of
Res ->
io:format("Interpreted result: ~p", [Res]),
- ?t:fail(did_not_fail_in_intepreted_code)
+ ct:fail(did_not_fail_in_intepreted_code)
catch
error:badarg ->
ok
end;
fail_check(Res, _, _) ->
io:format("Compiled result: ~p", [Res]),
- ?t:fail(did_not_fail_in_compiled_code).
+ ct:fail(did_not_fail_in_compiled_code).
%%% Simple working cases
-test1(suite) -> [];
test1(Config) when is_list(Config) ->
- ?line I_13 = i(13),
- ?line I_big1 = big(1),
- ?line Vars = [{'I_13', I_13},
+ I_13 = i(13),
+ I_big1 = big(1),
+ Vars = [{'I_13', I_13},
{'I_big1', I_big1}],
- ?line lists:foreach(fun one_test/1, eval_list(l(I_13, I_big1), Vars)).
+ lists:foreach(fun one_test/1, eval_list(l(I_13, I_big1), Vars)).
%%% Misc
@@ -285,10 +270,9 @@ gen(N, S, A) ->
gen_l(N, S, A) ->
[?T(<<A:S/little, A:(N-S)/little>>, comp(N, A, S))].
-test2(suite) -> [];
test2(Config) when is_list(Config) ->
- ?line test2(0, 8, 2#10101010101010101),
- ?line test2(0, 8, 2#1111111111).
+ test2(0, 8, 2#10101010101010101),
+ test2(0, 8, 2#1111111111).
test2(End, End, _) ->
ok;
@@ -313,10 +297,9 @@ t3() ->
?N(<<>>)
].
-test3(suite) -> [];
test3(Config) when is_list(Config) ->
- ?line Vars = [],
- ?line lists:foreach(fun one_test/1, eval_list(t3(), Vars)).
+ Vars = [],
+ lists:foreach(fun one_test/1, eval_list(t3(), Vars)).
gen_u(N, S, A) ->
[?N(<<A:S, A:(N-S)>>)].
@@ -324,10 +307,9 @@ gen_u(N, S, A) ->
gen_u_l(N, S, A) ->
[?N(<<A:S/little, A:(N-S)/little>>)].
-test4(suite) -> [];
test4(Config) when is_list(Config) ->
- ?line test4(0, 16, 2#10101010101010101),
- ?line test4(0, 16, 2#1111111111).
+ test4(0, 16, 2#10101010101010101),
+ test4(0, 16, 2#1111111111).
test4(End, End, _) ->
ok;
@@ -345,11 +327,10 @@ gen_b(N, S, A) ->
[?T(<<A:S/binary-unit:1, A:(N-S)/binary-unit:1>>,
binary_to_list(<<A:S/binary-unit:1, A:(N-S)/binary-unit:1>>))].
-test5(suite) -> [];
-test5(doc) -> ["OTP-3995"];
+%% OTP-3995
test5(Config) when is_list(Config) ->
- ?line test5(0, 8, <<73>>),
- ?line test5(0, 8, <<68>>).
+ test5(0, 8, <<73>>),
+ test5(0, 8, <<68>>).
test5(End, End, _) ->
ok;
@@ -363,47 +344,46 @@ test5(S, A) ->
lists:foreach(fun one_test/1, eval_list(gen_b(N, S, A), Vars)).
%%% Failure cases
-testf(suite) -> [];
testf(Config) when is_list(Config) ->
- ?line ?FAIL(<<3.14>>),
- ?line ?FAIL(<<<<1,2>>>>),
+ ?FAIL(<<3.14>>),
+ ?FAIL(<<<<1,2>>>>),
- ?line ?FAIL(<<2.71/binary>>),
- ?line ?FAIL(<<24334/binary>>),
- ?line ?FAIL(<<24334344294788947129487129487219847/binary>>),
+ ?FAIL(<<2.71/binary>>),
+ ?FAIL(<<24334/binary>>),
+ ?FAIL(<<24334344294788947129487129487219847/binary>>),
BigInt = id(24334344294788947129487129487219847),
- ?line ?FAIL_VARS(<<BigInt/binary>>, [{'BigInt',BigInt}]),
- ?line ?FAIL_VARS(<<42,BigInt/binary>>, [{'BigInt',BigInt}]),
- ?line ?FAIL_VARS(<<BigInt:2/binary>>, [{'BigInt',BigInt}]),
+ ?FAIL_VARS(<<BigInt/binary>>, [{'BigInt',BigInt}]),
+ ?FAIL_VARS(<<42,BigInt/binary>>, [{'BigInt',BigInt}]),
+ ?FAIL_VARS(<<BigInt:2/binary>>, [{'BigInt',BigInt}]),
%% One negative field size, but the sum of field sizes will be 1 byte.
%% Make sure that we reject that properly.
I_minus_777 = id(-777),
I_minus_2047 = id(-2047),
- ?line ?FAIL_VARS(<<I_minus_777:2048/unit:8,57:I_minus_2047/unit:8>>,
+ ?FAIL_VARS(<<I_minus_777:2048/unit:8,57:I_minus_2047/unit:8>>,
ordsets:from_list([{'I_minus_777',I_minus_777},
{'I_minus_2047',I_minus_2047}])),
- ?line ?FAIL(<<<<1,2,3>>/float>>),
+ ?FAIL(<<<<1,2,3>>/float>>),
%% Negative field widths.
- ?line testf_1(-8, <<1,2,3,4,5>>),
- ?line ?FAIL(<<0:(-(1 bsl 100))>>),
+ testf_1(-8, <<1,2,3,4,5>>),
+ ?FAIL(<<0:(-(1 bsl 100))>>),
- ?line ?FAIL(<<42:(-16)>>),
- ?line ?FAIL(<<3.14:(-8)/float>>),
- ?line ?FAIL(<<<<23,56,0,2>>:(-16)/binary>>),
- ?line ?FAIL(<<<<23,56,0,2>>:(2.5)/binary>>),
- ?line ?FAIL(<<<<23,56,0,2>>:(anka)>>),
- ?line ?FAIL(<<<<23,56,0,2>>:(anka)>>),
+ ?FAIL(<<42:(-16)>>),
+ ?FAIL(<<3.14:(-8)/float>>),
+ ?FAIL(<<<<23,56,0,2>>:(-16)/binary>>),
+ ?FAIL(<<<<23,56,0,2>>:(2.5)/binary>>),
+ ?FAIL(<<<<23,56,0,2>>:(anka)>>),
+ ?FAIL(<<<<23,56,0,2>>:(anka)>>),
%% Unit failures.
- ?line ?FAIL(<<<<1:1>>/binary>>),
+ ?FAIL(<<<<1:1>>/binary>>),
Sz = id(1),
- ?line ?FAIL_VARS(<<<<1:Sz>>/binary>>, [{'Sz',Sz}]),
- ?line {'EXIT',{badarg,_}} = (catch <<<<1:(id(1))>>/binary>>),
- ?line ?FAIL(<<<<7,8,9>>/binary-unit:16>>),
- ?line ?FAIL(<<<<7,8,9,3:7>>/binary-unit:16>>),
- ?line ?FAIL(<<<<7,8,9,3:7>>/binary-unit:17>>),
+ ?FAIL_VARS(<<<<1:Sz>>/binary>>, [{'Sz',Sz}]),
+ {'EXIT',{badarg,_}} = (catch <<<<1:(id(1))>>/binary>>),
+ ?FAIL(<<<<7,8,9>>/binary-unit:16>>),
+ ?FAIL(<<<<7,8,9,3:7>>/binary-unit:16>>),
+ ?FAIL(<<<<7,8,9,3:7>>/binary-unit:17>>),
ok.
@@ -413,14 +393,13 @@ testf_1(W, B) ->
?FAIL_VARS(<<3.14:W/float>>, Vars),
?FAIL_VARS(<<B:W/binary>>, [{'B',B}|Vars]).
-not_used(doc) ->
- "Test that constructed binaries that are not used will still give an exception.";
+%% Test that constructed binaries that are not used will still give an exception.
not_used(Config) when is_list(Config) ->
- ?line ok = not_used1(3, <<"dum">>),
- ?line {'EXIT',{badarg,_}} = (catch not_used1(3, "dum")),
- ?line {'EXIT',{badarg,_}} = (catch not_used2(444, -2)),
- ?line {'EXIT',{badarg,_}} = (catch not_used2(444, anka)),
- ?line {'EXIT',{badarg,_}} = (catch not_used3(444)),
+ ok = not_used1(3, <<"dum">>),
+ {'EXIT',{badarg,_}} = (catch not_used1(3, "dum")),
+ {'EXIT',{badarg,_}} = (catch not_used2(444, -2)),
+ {'EXIT',{badarg,_}} = (catch not_used2(444, anka)),
+ {'EXIT',{badarg,_}} = (catch not_used3(444)),
ok.
not_used1(I, BinString) ->
@@ -436,11 +415,11 @@ not_used3(I) ->
ok.
in_guard(Config) when is_list(Config) ->
- ?line 1 = in_guard(<<16#74ad:16>>, 16#e95, 5),
- ?line 2 = in_guard(<<16#3A,16#F7,"hello">>, 16#3AF7, <<"hello">>),
- ?line 3 = in_guard(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415),
- ?line 3 = in_guard(<<16#FBCD:14,3/float,3:2>>, 16#FBCD, 3),
- ?line 3 = in_guard(<<16#FBCD:14,(2 bsl 226)/float,3:2>>, 16#FBCD, 2 bsl 226),
+ 1 = in_guard(<<16#74ad:16>>, 16#e95, 5),
+ 2 = in_guard(<<16#3A,16#F7,"hello">>, 16#3AF7, <<"hello">>),
+ 3 = in_guard(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415),
+ 3 = in_guard(<<16#FBCD:14,3/float,3:2>>, 16#FBCD, 3),
+ 3 = in_guard(<<16#FBCD:14,(2 bsl 226)/float,3:2>>, 16#FBCD, 2 bsl 226),
nope = in_guard(<<1>>, 42, b),
nope = in_guard(<<1>>, a, b),
nope = in_guard(<<1,2>>, 1, 1),
@@ -454,16 +433,16 @@ in_guard(Bin, A, B) when <<A:14,B/float,3:2>> == Bin -> 3;
in_guard(Bin, A, B) when {a,b,<<A:14,B/float,3:2>>} == Bin -> cant_happen;
in_guard(_, _, _) -> nope.
-mem_leak(doc) -> "Make sure that construction has no memory leak";
+%% Make sure that construction has no memory leak
mem_leak(Config) when is_list(Config) ->
- ?line B = make_bin(16, <<0>>),
- ?line mem_leak(1024, B),
+ B = make_bin(16, <<0>>),
+ mem_leak(1024, B),
ok.
mem_leak(0, _) -> ok;
mem_leak(N, B) ->
- ?line big_bin(B, <<23>>),
- ?line {'EXIT',{badarg,_}} = (catch big_bin(B, bad)),
+ big_bin(B, <<23>>),
+ {'EXIT',{badarg,_}} = (catch big_bin(B, bad)),
mem_leak(N-1, B).
big_bin(B1, B2) ->
@@ -477,18 +456,18 @@ make_bin(0, Acc) -> Acc;
make_bin(N, Acc) -> make_bin(N-1, <<Acc/binary,Acc/binary>>).
-define(COF(Int0),
- ?line (fun(Int) ->
+ (fun(Int) ->
true = <<Int:32/float>> =:= <<(float(Int)):32/float>>,
true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
end)(nonliteral(Int0)),
- ?line true = <<Int0:32/float>> =:= <<(float(Int0)):32/float>>,
- ?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>).
+ true = <<Int0:32/float>> =:= <<(float(Int0)):32/float>>,
+ true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>).
-define(COF64(Int0),
- ?line (fun(Int) ->
+ (fun(Int) ->
true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
end)(nonliteral(Int0)),
- ?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>).
+ true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>).
nonliteral(X) -> X.
@@ -507,7 +486,7 @@ coerce_to_float(Config) when is_list(Config) ->
ok.
bjorn(Config) when is_list(Config) ->
- ?line error = bjorn_1(),
+ error = bjorn_1(),
ok.
bjorn_1() ->
@@ -535,46 +514,47 @@ do_something() ->
throw(blurf).
huge_float_field(Config) when is_list(Config) ->
- ?line {'EXIT',{badarg,_}} = (catch <<0.0:9/float-unit:8>>),
- ?line huge_float_check(catch <<0.0:67108865/float-unit:64>>),
- ?line huge_float_check(catch <<0.0:((1 bsl 26)+1)/float-unit:64>>),
- ?line huge_float_check(catch <<0.0:(id(67108865))/float-unit:64>>),
-%% ?line huge_float_check(catch <<0.0:((1 bsl 60)+1)/float-unit:64>>),
- ?line huge_float_check(catch <<3839739387439387383739387987347983:((1 bsl 26)+1)/float-unit:64>>),
-%% ?line huge_float_check(catch <<3839739387439387383739387987347983:((1 bsl 60)+1)/float-unit:64>>),
+ {'EXIT',{badarg,_}} = (catch <<0.0:9/float-unit:8>>),
+ huge_float_check(catch <<0.0:67108865/float-unit:64>>),
+ huge_float_check(catch <<0.0:((1 bsl 26)+1)/float-unit:64>>),
+ huge_float_check(catch <<0.0:(id(67108865))/float-unit:64>>),
+%% huge_float_check(catch <<0.0:((1 bsl 60)+1)/float-unit:64>>),
+ huge_float_check(catch <<3839739387439387383739387987347983:((1 bsl 26)+1)/float-unit:64>>),
+%% huge_float_check(catch <<3839739387439387383739387987347983:((1 bsl 60)+1)/float-unit:64>>),
ok.
huge_float_check({'EXIT',{system_limit,_}}) -> ok;
huge_float_check({'EXIT',{badarg,_}}) -> ok.
huge_binary(Config) when is_list(Config) ->
- ?line 16777216 = size(<<0:(id(1 bsl 26)),(-1):(id(1 bsl 26))>>),
- ?line garbage_collect(),
+ ct:timetrap({seconds, 30}),
+ 16777216 = size(<<0:(id(1 bsl 26)),(-1):(id(1 bsl 26))>>),
+ garbage_collect(),
{Shift,Return} = case free_mem() of
undefined ->
%% This test has to be inlined inside the case to
%% use a literal Shift
- ?line garbage_collect(),
- ?line id(<<0:((1 bsl 32)-1)>>),
+ garbage_collect(),
+ id(<<0:((1 bsl 32)-1)>>),
{32,ok};
Mb when Mb > 600 ->
- ?line garbage_collect(),
- ?line id(<<0:((1 bsl 32)-1)>>),
+ garbage_collect(),
+ id(<<0:((1 bsl 32)-1)>>),
{32,ok};
Mb when Mb > 300 ->
- ?line garbage_collect(),
- ?line id(<<0:((1 bsl 31)-1)>>),
+ garbage_collect(),
+ id(<<0:((1 bsl 31)-1)>>),
{31,"Limit huge binaries to 256 Mb"};
_ ->
- ?line garbage_collect(),
- ?line id(<<0:((1 bsl 30)-1)>>),
+ garbage_collect(),
+ id(<<0:((1 bsl 30)-1)>>),
{30,"Limit huge binary to 128 Mb"}
end,
- ?line garbage_collect(),
- ?line id(<<0:((1 bsl Shift)-1)>>),
- ?line garbage_collect(),
- ?line id(<<0:(id((1 bsl Shift)-1))>>),
- ?line garbage_collect(),
+ garbage_collect(),
+ id(<<0:((1 bsl Shift)-1)>>),
+ garbage_collect(),
+ id(<<0:(id((1 bsl Shift)-1))>>),
+ garbage_collect(),
case Return of
ok -> ok;
Comment -> {comment, Comment}
@@ -609,16 +589,16 @@ free_mem() ->
system_limit(Config) when is_list(Config) ->
WordSize = erlang:system_info(wordsize),
BitsPerWord = WordSize * 8,
- ?line {'EXIT',{system_limit,_}} =
+ {'EXIT',{system_limit,_}} =
(catch <<0:(id(0)),42:(id(1 bsl BitsPerWord))>>),
- ?line {'EXIT',{system_limit,_}} =
+ {'EXIT',{system_limit,_}} =
(catch <<42:(id(1 bsl BitsPerWord)),0:(id(0))>>),
- ?line {'EXIT',{system_limit,_}} =
+ {'EXIT',{system_limit,_}} =
(catch <<(id(<<>>))/binary,0:(id(1 bsl 100))>>),
%% Would fail to load.
- ?line {'EXIT',{system_limit,_}} = (catch <<0:(1 bsl 67)>>),
- ?line {'EXIT',{system_limit,_}} = (catch <<0:((1 bsl 64)+1)>>),
+ {'EXIT',{system_limit,_}} = (catch <<0:(1 bsl 67)>>),
+ {'EXIT',{system_limit,_}} = (catch <<0:((1 bsl 64)+1)>>),
case WordSize of
4 ->
@@ -628,60 +608,59 @@ system_limit(Config) when is_list(Config) ->
end.
system_limit_32() ->
- ?line {'EXIT',{badarg,_}} = (catch <<42:(-1)>>),
- ?line {'EXIT',{badarg,_}} = (catch <<42:(id(-1))>>),
- ?line {'EXIT',{badarg,_}} = (catch <<42:(id(-389739873536870912))/unit:8>>),
- ?line {'EXIT',{system_limit,_}} = (catch <<42:536870912/unit:8>>),
- ?line {'EXIT',{system_limit,_}} = (catch <<42:(id(536870912))/unit:8>>),
- ?line {'EXIT',{system_limit,_}} = (catch <<0:(id(8)),42:536870912/unit:8>>),
- ?line {'EXIT',{system_limit,_}} =
+ {'EXIT',{badarg,_}} = (catch <<42:(-1)>>),
+ {'EXIT',{badarg,_}} = (catch <<42:(id(-1))>>),
+ {'EXIT',{badarg,_}} = (catch <<42:(id(-389739873536870912))/unit:8>>),
+ {'EXIT',{system_limit,_}} = (catch <<42:536870912/unit:8>>),
+ {'EXIT',{system_limit,_}} = (catch <<42:(id(536870912))/unit:8>>),
+ {'EXIT',{system_limit,_}} = (catch <<0:(id(8)),42:536870912/unit:8>>),
+ {'EXIT',{system_limit,_}} =
(catch <<0:(id(8)),42:(id(536870912))/unit:8>>),
%% The size would be silently truncated, resulting in a crash.
- ?line {'EXIT',{system_limit,_}} = (catch <<0:(1 bsl 35)>>),
- ?line {'EXIT',{system_limit,_}} = (catch <<0:((1 bsl 32)+1)>>),
+ {'EXIT',{system_limit,_}} = (catch <<0:(1 bsl 35)>>),
+ {'EXIT',{system_limit,_}} = (catch <<0:((1 bsl 32)+1)>>),
%% Would fail to load.
- ?line {'EXIT',{system_limit,_}} = (catch <<0:(1 bsl 43)>>),
- ?line {'EXIT',{system_limit,_}} = (catch <<0:((1 bsl 40)+1)>>),
+ {'EXIT',{system_limit,_}} = (catch <<0:(1 bsl 43)>>),
+ {'EXIT',{system_limit,_}} = (catch <<0:((1 bsl 40)+1)>>),
ok.
badarg(Config) when is_list(Config) ->
- ?line {'EXIT',{badarg,_}} =
+ {'EXIT',{badarg,_}} =
(catch <<0:(id(1 bsl 100)),0:(id(-1))>>),
- ?line {'EXIT',{badarg,_}} =
+ {'EXIT',{badarg,_}} =
(catch <<0:(id(1 bsl 100)),0:(id(-(1 bsl 70)))>>),
- ?line {'EXIT',{badarg,_}} =
+ {'EXIT',{badarg,_}} =
(catch <<0:(id(-(1 bsl 70))),0:(id(1 bsl 100))>>),
- ?line {'EXIT',{badarg,_}} =
+ {'EXIT',{badarg,_}} =
(catch <<(id(<<>>))/binary,0:(id(-(1 bsl 100)))>>),
ok.
copy_writable_binary(Config) when is_list(Config) ->
- ?line [copy_writable_binary_1(I) || I <- lists:seq(0, 256)],
+ [copy_writable_binary_1(I) || I <- lists:seq(0, 256)],
ok.
copy_writable_binary_1(_) ->
- ?line Bin0 = <<(id(<<>>))/binary,0,1,2,3,4,5,6,7>>,
- ?line SubBin = make_sub_bin(Bin0),
- ?line id(<<42,34,55,Bin0/binary>>), %Make reallocation likelier.
- ?line Pid = spawn(fun() ->
+ Bin0 = <<(id(<<>>))/binary,0,1,2,3,4,5,6,7>>,
+ SubBin = make_sub_bin(Bin0),
+ id(<<42,34,55,Bin0/binary>>), %Make reallocation likelier.
+ Pid = spawn(fun() ->
copy_writable_binary_holder(Bin0, SubBin)
end),
- ?line Tab = ets:new(holder, []),
- ?line ets:insert(Tab, {17,Bin0}),
- ?line ets:insert(Tab, {42,SubBin}),
- ?line id(<<Bin0/binary,0:(64*1024*8)>>),
- ?line Pid ! self(),
- ?line [{17,Bin0}] = ets:lookup(Tab, 17),
- ?line [{42,Bin0}] = ets:lookup(Tab, 42),
+ Tab = ets:new(holder, []),
+ ets:insert(Tab, {17,Bin0}),
+ ets:insert(Tab, {42,SubBin}),
+ id(<<Bin0/binary,0:(64*1024*8)>>),
+ Pid ! self(),
+ [{17,Bin0}] = ets:lookup(Tab, 17),
+ [{42,Bin0}] = ets:lookup(Tab, 42),
receive
{Pid,Bin0,Bin0} -> ok;
Other ->
- io:format("Unexpected message: ~p", [Other]),
- ?line ?t:fail()
+ ct:fail("Unexpected message: ~p", [Other])
end,
ok.
@@ -722,8 +701,8 @@ have_250_terabytes_of_ram() -> false.
%% give the same result.
dynamic(Config) when is_list(Config) ->
- ?line dynamic_1(fun dynamic_big/5),
- ?line dynamic_1(fun dynamic_little/5),
+ dynamic_1(fun dynamic_big/5),
+ dynamic_1(fun dynamic_little/5),
ok.
dynamic_1(Dynamic) ->
@@ -802,32 +781,32 @@ bs_add(Config) when is_list(Config) ->
return],
%% Write assembly file and assemble it.
- ?line PrivDir = ?config(priv_dir, Config),
- ?line RootName = filename:join(PrivDir, atom_to_list(Mod)),
- ?line AsmFile = RootName ++ ".S",
- ?line {ok,Fd} = file:open(AsmFile, [write]),
- ?line [io:format(Fd, "~p. \n", [T]) || T <- Code],
- ?line ok = file:close(Fd),
- ?line {ok,Mod} = compile:file(AsmFile, [from_asm,report,{outdir,PrivDir}]),
- ?line LoadRc = code:load_abs(RootName),
- ?line {module,_Module} = LoadRc,
+ PrivDir = proplists:get_value(priv_dir, Config),
+ RootName = filename:join(PrivDir, atom_to_list(Mod)),
+ AsmFile = RootName ++ ".S",
+ {ok,Fd} = file:open(AsmFile, [write]),
+ [io:format(Fd, "~p. \n", [T]) || T <- Code],
+ ok = file:close(Fd),
+ {ok,Mod} = compile:file(AsmFile, [from_asm,report,{outdir,PrivDir}]),
+ LoadRc = code:load_abs(RootName),
+ {module,_Module} = LoadRc,
%% Find smallest positive bignum.
- ?line SmallestBig = smallest_big(),
- ?line io:format("~p\n", [SmallestBig]),
- ?line Expected = SmallestBig + N,
+ SmallestBig = smallest_big(),
+ io:format("~p\n", [SmallestBig]),
+ Expected = SmallestBig + N,
DoTest = fun() ->
exit(Mod:bs_add(SmallestBig, -SmallestBig))
end,
- ?line {Pid,Mref} = spawn_monitor(DoTest),
+ {Pid,Mref} = spawn_monitor(DoTest),
receive
{'DOWN',Mref,process,Pid,Res} -> ok
end,
- ?line Expected = Res,
+ Expected = Res,
%% Clean up.
- ?line ok = file:delete(AsmFile),
- ?line ok = file:delete(code:which(Mod)),
+ ok = file:delete(AsmFile),
+ ok = file:delete(code:which(Mod)),
ok.
@@ -868,17 +847,17 @@ otp_7422_bin(N) when N < 512 ->
otp_7422_bin(_) -> ok.
zero_width(Config) when is_list(Config) ->
- ?line Z = id(0),
+ Z = id(0),
Small = id(42),
Big = id(1 bsl 128),
- ?line <<>> = <<Small:Z>>,
- ?line <<>> = <<Small:0>>,
- ?line <<>> = <<Big:Z>>,
- ?line <<>> = <<Big:0>>,
+ <<>> = <<Small:Z>>,
+ <<>> = <<Small:0>>,
+ <<>> = <<Big:Z>>,
+ <<>> = <<Big:0>>,
- ?line {'EXIT',{badarg,_}} = (catch <<not_a_number:0>>),
- ?line {'EXIT',{badarg,_}} = (catch <<(id(not_a_number)):Z>>),
- ?line {'EXIT',{badarg,_}} = (catch <<(id(not_a_number)):0>>),
+ {'EXIT',{badarg,_}} = (catch <<not_a_number:0>>),
+ {'EXIT',{badarg,_}} = (catch <<(id(not_a_number)):Z>>),
+ {'EXIT',{badarg,_}} = (catch <<(id(not_a_number)):0>>),
ok.
@@ -935,8 +914,8 @@ bs_add_overflow(Config) ->
Large = <<0:((1 bsl 30)-1)>>,
{'EXIT',{system_limit,_}} =
(catch <<Large/bits, Large/bits, Large/bits, Large/bits,
- Large/bits, Large/bits, Large/bits, Large/bits,
- Large/bits>>),
+ Large/bits, Large/bits, Large/bits, Large/bits,
+ Large/bits>>),
ok
end.
diff --git a/erts/emulator/test/bs_match_bin_SUITE.erl b/erts/emulator/test/bs_match_bin_SUITE.erl
index ba79643e69..6f7abf8c4e 100644
--- a/erts/emulator/test/bs_match_bin_SUITE.erl
+++ b/erts/emulator/test/bs_match_bin_SUITE.erl
@@ -24,7 +24,7 @@
init_per_group/2,end_per_group/2,
byte_split_binary/1,bit_split_binary/1,match_huge_bin/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -47,33 +47,33 @@ end_per_group(_GroupName, Config) ->
Config.
-byte_split_binary(doc) -> "Tries to split a binary at all byte-aligned positions.";
+%% Tries to split a binary at all byte-aligned positions.
byte_split_binary(Config) when is_list(Config) ->
- ?line L = lists:seq(0, 57),
- ?line B = mkbin(L),
- ?line byte_split(L, B, size(B)),
- ?line Unaligned = make_unaligned_sub_binary(B),
- ?line byte_split(L, Unaligned, size(Unaligned)).
+ L = lists:seq(0, 57),
+ B = mkbin(L),
+ byte_split(L, B, size(B)),
+ Unaligned = make_unaligned_sub_binary(B),
+ byte_split(L, Unaligned, size(Unaligned)).
byte_split(L, B, Pos) when Pos >= 0 ->
- ?line Sz1 = Pos,
- ?line Sz2 = size(B) - Pos,
- ?line <<B1:Sz1/binary,B2:Sz2/binary>> = B,
- ?line B1 = list_to_binary(lists:sublist(L, 1, Pos)),
- ?line B2 = list_to_binary(lists:nthtail(Pos, L)),
- ?line byte_split(L, B, Pos-1);
+ Sz1 = Pos,
+ Sz2 = size(B) - Pos,
+ <<B1:Sz1/binary,B2:Sz2/binary>> = B,
+ B1 = list_to_binary(lists:sublist(L, 1, Pos)),
+ B2 = list_to_binary(lists:nthtail(Pos, L)),
+ byte_split(L, B, Pos-1);
byte_split(_, _, _) -> ok.
-bit_split_binary(doc) -> "Tries to split a binary at all positions.";
+%% Tries to split a binary at all positions.
bit_split_binary(Config) when is_list(Config) ->
Fun = fun(Bin, List, SkipBef, N) ->
- ?line SkipAft = 8*size(Bin) - N - SkipBef,
+ SkipAft = 8*size(Bin) - N - SkipBef,
%%io:format("~p, ~p, ~p", [SkipBef,N,SkipAft]),
- ?line <<_:SkipBef,OutBin:N/binary-unit:1,_:SkipAft>> = Bin,
- ?line OutBin = make_bin_from_list(List, N)
+ <<_:SkipBef,OutBin:N/binary-unit:1,_:SkipAft>> = Bin,
+ OutBin = make_bin_from_list(List, N)
end,
- ?line bit_split_binary1(Fun, erlang:md5(<<1,2,3>>)),
- ?line bit_split_binary1(Fun,
+ bit_split_binary1(Fun, erlang:md5(<<1,2,3>>)),
+ bit_split_binary1(Fun,
make_unaligned_sub_binary(erlang:md5(<<1,2,3>>))),
ok.
@@ -119,19 +119,19 @@ make_unaligned_sub_binary(Bin0) ->
id(I) -> I.
match_huge_bin(Config) when is_list(Config) ->
- ?line Bin = <<0:(1 bsl 27),13:8>>,
- ?line skip_huge_bin_1(1 bsl 27, Bin),
- ?line 16777216 = match_huge_bin_1(1 bsl 27, Bin),
+ Bin = <<0:(1 bsl 27),13:8>>,
+ skip_huge_bin_1(1 bsl 27, Bin),
+ 16777216 = match_huge_bin_1(1 bsl 27, Bin),
%% Test overflowing the size of a binary field.
- ?line nomatch = overflow_huge_bin_skip_32(Bin),
- ?line nomatch = overflow_huge_bin_32(Bin),
- ?line nomatch = overflow_huge_bin_skip_64(Bin),
- ?line nomatch = overflow_huge_bin_64(Bin),
+ nomatch = overflow_huge_bin_skip_32(Bin),
+ nomatch = overflow_huge_bin_32(Bin),
+ nomatch = overflow_huge_bin_skip_64(Bin),
+ nomatch = overflow_huge_bin_64(Bin),
%% Size in variable
- ?line ok = overflow_huge_bin(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
- ?line ok = overflow_huge_bin_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+ ok = overflow_huge_bin(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+ ok = overflow_huge_bin_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
ok.
diff --git a/erts/emulator/test/bs_match_int_SUITE.erl b/erts/emulator/test/bs_match_int_SUITE.erl
index 368f71978d..42d692c1ba 100644
--- a/erts/emulator/test/bs_match_int_SUITE.erl
+++ b/erts/emulator/test/bs_match_int_SUITE.erl
@@ -24,7 +24,7 @@
integer/1,signed_integer/1,dynamic/1,more_dynamic/1,mml/1,
match_huge_int/1,bignum/1,unaligned_32_bit/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-import(lists, [seq/2]).
@@ -51,22 +51,22 @@ end_per_group(_GroupName, Config) ->
integer(Config) when is_list(Config) ->
- ?line 0 = get_int(mkbin([])),
- ?line 0 = get_int(mkbin([0])),
- ?line 42 = get_int(mkbin([42])),
- ?line 255 = get_int(mkbin([255])),
- ?line 256 = get_int(mkbin([1,0])),
- ?line 257 = get_int(mkbin([1,1])),
- ?line 258 = get_int(mkbin([1,2])),
- ?line 258 = get_int(mkbin([1,2])),
- ?line 65534 = get_int(mkbin([255,254])),
- ?line 16776455 = get_int(mkbin([255,253,7])),
- ?line 4245492555 = get_int(mkbin([253,13,19,75])),
- ?line 4294967294 = get_int(mkbin([255,255,255,254])),
- ?line 4294967295 = get_int(mkbin([255,255,255,255])),
- ?line Eight = [200,1,19,128,222,42,97,111],
- ?line cmp128(Eight, uint(Eight)),
- ?line fun_clause(catch get_int(mkbin(seq(1,5)))),
+ 0 = get_int(mkbin([])),
+ 0 = get_int(mkbin([0])),
+ 42 = get_int(mkbin([42])),
+ 255 = get_int(mkbin([255])),
+ 256 = get_int(mkbin([1,0])),
+ 257 = get_int(mkbin([1,1])),
+ 258 = get_int(mkbin([1,2])),
+ 258 = get_int(mkbin([1,2])),
+ 65534 = get_int(mkbin([255,254])),
+ 16776455 = get_int(mkbin([255,253,7])),
+ 4245492555 = get_int(mkbin([253,13,19,75])),
+ 4294967294 = get_int(mkbin([255,255,255,254])),
+ 4294967295 = get_int(mkbin([255,255,255,255])),
+ Eight = [200,1,19,128,222,42,97,111],
+ cmp128(Eight, uint(Eight)),
+ fun_clause(catch get_int(mkbin(seq(1,5)))),
ok.
get_int(Bin) ->
@@ -89,13 +89,13 @@ cmp128(<<I:128>>, I) -> equal;
cmp128(_, _) -> not_equal.
signed_integer(Config) when is_list(Config) ->
- ?line {no_match,_} = sint(mkbin([])),
- ?line {no_match,_} = sint(mkbin([1,2,3])),
- ?line 127 = sint(mkbin([127])),
- ?line -1 = sint(mkbin([255])),
- ?line -128 = sint(mkbin([128])),
- ?line 42 = sint(mkbin([42,255])),
- ?line 127 = sint(mkbin([127,255])).
+ {no_match,_} = sint(mkbin([])),
+ {no_match,_} = sint(mkbin([1,2,3])),
+ 127 = sint(mkbin([127])),
+ -1 = sint(mkbin([255])),
+ -128 = sint(mkbin([128])),
+ 42 = sint(mkbin([42,255])),
+ 127 = sint(mkbin([127,255])).
sint(Bin) ->
case Bin of
@@ -130,7 +130,7 @@ dynamic(Bin, S1, S2, A, B) ->
_Other -> erlang:error(badmatch, [Bin,S1,S2,A,B])
end.
-more_dynamic(doc) -> "Extract integers at different alignments and of different sizes.";
+%% Extract integers at different alignments and of different sizes.
more_dynamic(Config) when is_list(Config) ->
% Unsigned big-endian numbers.
@@ -139,7 +139,7 @@ more_dynamic(Config) when is_list(Config) ->
<<_:SkipBef,Int:N,_:SkipAft>> = Bin,
Int = make_int(List, N, 0)
end,
- ?line more_dynamic1(Unsigned, erlang:md5(mkbin([42]))),
+ more_dynamic1(Unsigned, erlang:md5(mkbin([42]))),
%% Signed big-endian numbers.
Signed = fun(Bin, List, SkipBef, N) ->
@@ -151,10 +151,10 @@ more_dynamic(Config) when is_list(Config) ->
io:format("Bin = ~p,", [Bin]),
io:format("SkipBef = ~p, N = ~p", [SkipBef,N]),
io:format("Expected ~p, got ~p", [Int,Other]),
- ?t:fail()
+ ct:fail(signed_big_endian_fail)
end
end,
- ?line more_dynamic1(Signed, erlang:md5(mkbin([43]))),
+ more_dynamic1(Signed, erlang:md5(mkbin([43]))),
%% Unsigned little-endian numbers.
UnsLittle = fun(Bin, List, SkipBef, N) ->
@@ -162,7 +162,7 @@ more_dynamic(Config) when is_list(Config) ->
<<_:SkipBef,Int:N/little,_:SkipAft>> = Bin,
Int = make_int(big_to_little(List, N), N, 0)
end,
- ?line more_dynamic1(UnsLittle, erlang:md5(mkbin([44]))),
+ more_dynamic1(UnsLittle, erlang:md5(mkbin([44]))),
%% Signed little-endian numbers.
SignLittle = fun(Bin, List, SkipBef, N) ->
@@ -171,7 +171,7 @@ more_dynamic(Config) when is_list(Config) ->
Little = big_to_little(List, N),
Int = make_signed_int(Little, N)
end,
- ?line more_dynamic1(SignLittle, erlang:md5(mkbin([45]))),
+ more_dynamic1(SignLittle, erlang:md5(mkbin([45]))),
ok.
@@ -227,23 +227,23 @@ mkbin(L) when is_list(L) -> list_to_binary(L).
mml(Config) when is_list(Config) ->
- ?line single_byte_binary = mml_choose(<<42>>),
- ?line multi_byte_binary = mml_choose(<<42,43>>).
+ single_byte_binary = mml_choose(<<42>>),
+ multi_byte_binary = mml_choose(<<42,43>>).
mml_choose(<<_A:8>>) -> single_byte_binary;
mml_choose(<<_A:8,_T/binary>>) -> multi_byte_binary.
match_huge_int(Config) when is_list(Config) ->
Sz = 1 bsl 27,
- ?line Bin = <<0:Sz,13:8>>,
- ?line skip_huge_int_1(Sz, Bin),
- ?line 0 = match_huge_int_1(Sz, Bin),
+ Bin = <<0:Sz,13:8>>,
+ skip_huge_int_1(Sz, Bin),
+ 0 = match_huge_int_1(Sz, Bin),
%% Test overflowing the size of an integer field.
- ?line nomatch = overflow_huge_int_skip_32(Bin),
+ nomatch = overflow_huge_int_skip_32(Bin),
case erlang:system_info(wordsize) of
4 ->
- ?line nomatch = overflow_huge_int_32(Bin);
+ nomatch = overflow_huge_int_32(Bin);
8 ->
%% An attempt will be made to allocate heap space for
%% the bignum (which will probably fail); only if the
@@ -251,15 +251,15 @@ match_huge_int(Config) when is_list(Config) ->
%% the binary is too small.
ok
end,
- ?line nomatch = overflow_huge_int_skip_64(Bin),
- ?line nomatch = overflow_huge_int_64(Bin),
+ nomatch = overflow_huge_int_skip_64(Bin),
+ nomatch = overflow_huge_int_64(Bin),
%% Test overflowing the size of an integer field using variables as sizes.
- ?line Sizes = case erlang:system_info(wordsize) of
+ Sizes = case erlang:system_info(wordsize) of
4 -> lists:seq(25, 32);
8 -> []
end ++ lists:seq(50, 64),
- ?line ok = overflow_huge_int_unit128(Bin, Sizes),
+ ok = overflow_huge_int_unit128(Bin, Sizes),
ok.
@@ -326,19 +326,19 @@ overflow_huge_int_64(<<Int:9223372036854775808/unit:128,0,_/binary>>) -> {8,Int}
overflow_huge_int_64(_) -> nomatch.
bignum(Config) when is_list(Config) ->
- ?line Bin = id(<<42,0:1024/unit:8,43>>),
- ?line <<42:1025/little-integer-unit:8,_:8>> = Bin,
- ?line <<_:8,43:1025/integer-unit:8>> = Bin,
+ Bin = id(<<42,0:1024/unit:8,43>>),
+ <<42:1025/little-integer-unit:8,_:8>> = Bin,
+ <<_:8,43:1025/integer-unit:8>> = Bin,
- ?line BignumBin = id(<<0:512/unit:8,258254417031933722623:9/unit:8>>),
- ?line <<258254417031933722623:(512+9)/unit:8>> = BignumBin,
+ BignumBin = id(<<0:512/unit:8,258254417031933722623:9/unit:8>>),
+ <<258254417031933722623:(512+9)/unit:8>> = BignumBin,
erlang:garbage_collect(), %Search for holes in debug-build.
ok.
unaligned_32_bit(Config) when is_list(Config) ->
%% There used to be a risk for heap overflow (fixed in R11B-5).
- ?line L = unaligned_32_bit_1(<<-1:(64*1024)>>),
- ?line unaligned_32_bit_verify(L, 1638).
+ L = unaligned_32_bit_1(<<-1:(64*1024)>>),
+ unaligned_32_bit_verify(L, 1638).
unaligned_32_bit_1(<<1:1,U:32,_:7,T/binary>>) ->
[U|unaligned_32_bit_1(T)];
diff --git a/erts/emulator/test/bs_match_misc_SUITE.erl b/erts/emulator/test/bs_match_misc_SUITE.erl
index e875dc859c..114d7ecb36 100644
--- a/erts/emulator/test/bs_match_misc_SUITE.erl
+++ b/erts/emulator/test/bs_match_misc_SUITE.erl
@@ -19,17 +19,18 @@
%%
-module(bs_match_misc_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
+-export([all/0, suite/0,
bound_var/1,bound_tail/1,t_float/1,little_float/1,sean/1,
kenneth/1,encode_binary/1,native/1,happi/1,
size_var/1,wiger/1,x0_context/1,huge_float_field/1,
writable_binary_matched/1,otp_7198/1,unordered_bindings/1,
float_middle_endian/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {seconds, 10}}].
all() ->
[bound_var, bound_tail, t_float, little_float, sean,
@@ -37,39 +38,24 @@ all() ->
x0_context, huge_float_field, writable_binary_matched,
otp_7198, unordered_bindings, float_middle_endian].
-groups() ->
- [].
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-bound_var(doc) -> "Test matching of bound variables.";
+%% Test matching of bound variables.
bound_var(Config) when is_list(Config) ->
- ?line ok = bound_var(42, 13, <<42,13>>),
- ?line nope = bound_var(42, 13, <<42,255>>),
- ?line nope = bound_var(42, 13, <<154,255>>),
+ ok = bound_var(42, 13, <<42,13>>),
+ nope = bound_var(42, 13, <<42,255>>),
+ nope = bound_var(42, 13, <<154,255>>),
ok.
bound_var(A, B, <<A:8,B:8>>) -> ok;
bound_var(_, _, _) -> nope.
-bound_tail(doc) -> "Test matching of a bound tail.";
+%% Test matching of a bound tail.
bound_tail(Config) when is_list(Config) ->
- ?line ok = bound_tail(<<>>, <<13,14>>),
- ?line ok = bound_tail(<<2,3>>, <<1,1,2,3>>),
- ?line nope = bound_tail(<<2,3>>, <<1,1,2,7>>),
- ?line nope = bound_tail(<<2,3>>, <<1,1,2,3,4>>),
- ?line nope = bound_tail(<<2,3>>, <<>>),
+ ok = bound_tail(<<>>, <<13,14>>),
+ ok = bound_tail(<<2,3>>, <<1,1,2,3>>),
+ nope = bound_tail(<<2,3>>, <<1,1,2,7>>),
+ nope = bound_tail(<<2,3>>, <<1,1,2,3,4>>),
+ nope = bound_tail(<<2,3>>, <<>>),
ok.
bound_tail(T, <<_:16,T/binary>>) -> ok;
@@ -79,26 +65,26 @@ t_float(Config) when is_list(Config) ->
F = f1(),
G = f_one(),
- ?line G = match_float(<<63,128,0,0>>, 32, 0),
- ?line G = match_float(<<63,240,0,0,0,0,0,0>>, 64, 0),
+ G = match_float(<<63,128,0,0>>, 32, 0),
+ G = match_float(<<63,240,0,0,0,0,0,0>>, 64, 0),
- ?line fcmp(F, match_float(<<F:32/float>>, 32, 0)),
- ?line fcmp(F, match_float(<<F:64/float>>, 64, 0)),
- ?line fcmp(F, match_float(<<1:1,F:32/float,127:7>>, 32, 1)),
- ?line fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)),
- ?line fcmp(F, match_float(<<1:13,F:32/float,127:3>>, 32, 13)),
- ?line fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)),
+ fcmp(F, match_float(<<F:32/float>>, 32, 0)),
+ fcmp(F, match_float(<<F:64/float>>, 64, 0)),
+ fcmp(F, match_float(<<1:1,F:32/float,127:7>>, 32, 1)),
+ fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)),
+ fcmp(F, match_float(<<1:13,F:32/float,127:3>>, 32, 13)),
+ fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)),
- ?line {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16, 0)),
- ?line {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16#7fffffff, 0)),
+ {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16, 0)),
+ {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16#7fffffff, 0)),
ok.
float_middle_endian(Config) when is_list(Config) ->
F = 9007199254740990.0, % turns to -NaN when word-swapped
- ?line fcmp(F, match_float(<<F:64/float>>, 64, 0)),
- ?line fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)),
- ?line fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)),
+ fcmp(F, match_float(<<F:64/float>>, 64, 0)),
+ fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)),
+ fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)),
ok.
@@ -115,15 +101,15 @@ little_float(Config) when is_list(Config) ->
F = f2(),
G = f_one(),
- ?line G = match_float_little(<<0,0,0,0,0,0,240,63>>, 64, 0),
- ?line G = match_float_little(<<0,0,128,63>>, 32, 0),
+ G = match_float_little(<<0,0,0,0,0,0,240,63>>, 64, 0),
+ G = match_float_little(<<0,0,128,63>>, 32, 0),
- ?line fcmp(F, match_float_little(<<F:32/float-little>>, 32, 0)),
- ?line fcmp(F, match_float_little(<<F:64/float-little>>, 64, 0)),
- ?line fcmp(F, match_float_little(<<1:1,F:32/float-little,127:7>>, 32, 1)),
- ?line fcmp(F, match_float_little(<<1:1,F:64/float-little,127:7>>, 64, 1)),
- ?line fcmp(F, match_float_little(<<1:13,F:32/float-little,127:3>>, 32, 13)),
- ?line fcmp(F, match_float_little(<<1:13,F:64/float-little,127:3>>, 64, 13)),
+ fcmp(F, match_float_little(<<F:32/float-little>>, 32, 0)),
+ fcmp(F, match_float_little(<<F:64/float-little>>, 64, 0)),
+ fcmp(F, match_float_little(<<1:1,F:32/float-little,127:7>>, 32, 1)),
+ fcmp(F, match_float_little(<<1:1,F:64/float-little,127:7>>, 64, 1)),
+ fcmp(F, match_float_little(<<1:13,F:32/float-little,127:3>>, 32, 13)),
+ fcmp(F, match_float_little(<<1:13,F:64/float-little,127:3>>, 64, 13)),
ok.
@@ -151,16 +137,16 @@ f_one() ->
1.0.
sean(Config) when is_list(Config) ->
- ?line small = sean1(<<>>),
- ?line small = sean1(<<1>>),
- ?line small = sean1(<<1,2>>),
- ?line small = sean1(<<1,2,3>>),
- ?line large = sean1(<<1,2,3,4>>),
-
- ?line small = sean1(<<4>>),
- ?line small = sean1(<<4,5>>),
- ?line small = sean1(<<4,5,6>>),
- ?line {'EXIT',{function_clause,_}} = (catch sean1(<<4,5,6,7>>)),
+ small = sean1(<<>>),
+ small = sean1(<<1>>),
+ small = sean1(<<1,2>>),
+ small = sean1(<<1,2,3>>),
+ large = sean1(<<1,2,3,4>>),
+
+ small = sean1(<<4>>),
+ small = sean1(<<4,5>>),
+ small = sean1(<<4,5,6>>),
+ {'EXIT',{function_clause,_}} = (catch sean1(<<4,5,6,7>>)),
ok.
sean1(<<B/binary>>) when byte_size(B) < 4 -> small;
@@ -292,28 +278,28 @@ getBase64Char(_Else) ->
-define(M(F), <<F>> = <<F>>).
native(Config) when is_list(Config) ->
- ?line ?M(3.14:64/native-float),
- ?line ?M(333:16/native),
- ?line ?M(38658345:32/native),
+ ?M(3.14:64/native-float),
+ ?M(333:16/native),
+ ?M(38658345:32/native),
case <<1:16/native>> of
<<0,1>> -> native_big();
<<1,0>> -> native_little()
end.
native_big() ->
- ?line <<37.33:64/native-float>> = <<37.33:64/big-float>>,
- ?line <<3974:16/native-integer>> = <<3974:16/big-integer>>,
+ <<37.33:64/native-float>> = <<37.33:64/big-float>>,
+ <<3974:16/native-integer>> = <<3974:16/big-integer>>,
{comment,"Big endian"}.
native_little() ->
- ?line <<37869.32343:64/native-float>> = <<37869.32343:64/little-float>>,
- ?line <<7974:16/native-integer>> = <<7974:16/little-integer>>,
+ <<37869.32343:64/native-float>> = <<37869.32343:64/little-float>>,
+ <<7974:16/native-integer>> = <<7974:16/little-integer>>,
{comment,"Little endian"}.
happi(Config) when is_list(Config) ->
Bin = <<".123">>,
- ?line <<"123">> = lex_digits1(Bin, 1, []),
- ?line <<"123">> = lex_digits2(Bin, 1, []),
+ <<"123">> = lex_digits1(Bin, 1, []),
+ <<"123">> = lex_digits2(Bin, 1, []),
ok.
lex_digits1(<<$., Rest/binary>>,_Val,_Acc) ->
@@ -334,16 +320,16 @@ dec(A) ->
A-$0.
size_var(Config) when is_list(Config) ->
- ?line {<<45>>,<<>>} = split(<<1:16,45>>),
- ?line {<<45>>,<<46,47>>} = split(<<1:16,45,46,47>>),
- ?line {<<45,46>>,<<47>>} = split(<<2:16,45,46,47>>),
+ {<<45>>,<<>>} = split(<<1:16,45>>),
+ {<<45>>,<<46,47>>} = split(<<1:16,45,46,47>>),
+ {<<45,46>>,<<47>>} = split(<<2:16,45,46,47>>),
- ?line {<<45,46,47>>,<<48>>} = split_2(<<16:8,3:16,45,46,47,48>>),
+ {<<45,46,47>>,<<48>>} = split_2(<<16:8,3:16,45,46,47,48>>),
- ?line {<<45,46>>,<<47>>} = split(2, <<2:16,45,46,47>>),
- ?line {'EXIT',{function_clause,_}} = (catch split(42, <<2:16,45,46,47>>)),
+ {<<45,46>>,<<47>>} = split(2, <<2:16,45,46,47>>),
+ {'EXIT',{function_clause,_}} = (catch split(42, <<2:16,45,46,47>>)),
- ?line <<"cdef">> = skip(<<2:8,"abcdef">>),
+ <<"cdef">> = skip(<<2:8,"abcdef">>),
ok.
@@ -359,11 +345,11 @@ split_2(<<N0:8,N:N0,B:N/binary,T/binary>>) ->
skip(<<N:8,_:N/binary,T/binary>>) -> T.
wiger(Config) when is_list(Config) ->
- ?line ok1 = wcheck(<<3>>),
- ?line ok2 = wcheck(<<1,2,3>>),
- ?line ok3 = wcheck(<<4>>),
- ?line {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>),
- ?line {error,<<>>} = wcheck(<<>>),
+ ok1 = wcheck(<<3>>),
+ ok2 = wcheck(<<1,2,3>>),
+ ok3 = wcheck(<<4>>),
+ {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>),
+ {error,<<>>} = wcheck(<<>>),
ok.
wcheck(<<A>>) when A==3->
@@ -396,24 +382,24 @@ x0_2(_, Bin) ->
x0_3(_, Bin) ->
case Bin of
- <<_:72,7:8,_/binary>> ->
- ?line ?t:fail();
- <<_:64,0:16,_/binary>> ->
- ?line ?t:fail();
- <<_:64,42:16,123456:32,_/binary>> ->
- ok
+ <<_:72,7:8,_/binary>> ->
+ ct:fail(bs_matched_1);
+ <<_:64,0:16,_/binary>> ->
+ ct:fail(bs_matched_2);
+ <<_:64,42:16,123456:32,_/binary>> ->
+ ok
end.
huge_float_field(Config) when is_list(Config) ->
Sz = 1 bsl 27,
- ?line Bin = <<0:Sz>>,
+ Bin = <<0:Sz>>,
- ?line nomatch = overflow_huge_float_skip_32(Bin),
- ?line nomatch = overflow_huge_float_32(Bin),
+ nomatch = overflow_huge_float_skip_32(Bin),
+ nomatch = overflow_huge_float_32(Bin),
- ?line ok = overflow_huge_float(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
- ?line ok = overflow_huge_float_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+ ok = overflow_huge_float(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+ ok = overflow_huge_float_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
ok.
overflow_huge_float_skip_32(<<_:4294967296/float,0,_/binary>>) -> 1; % 1 bsl 32
@@ -455,15 +441,15 @@ overflow_huge_float(_, []) -> ok.
overflow_huge_float_unit128(Bin, [Sz0|Sizes]) ->
Sz = id(1 bsl Sz0),
case Bin of
- <<_:Sz/float-unit:128,0,_/binary>> ->
- {error,Sz};
- _ ->
- case Bin of
- <<Var:Sz/float-unit:128,0,_/binary>> ->
- {error,Sz,Var};
- _ ->
- overflow_huge_float_unit128(Bin, Sizes)
- end
+ <<_:Sz/float-unit:128,0,_/binary>> ->
+ {error,Sz};
+ _ ->
+ case Bin of
+ <<Var:Sz/float-unit:128,0,_/binary>> ->
+ {error,Sz,Var};
+ _ ->
+ overflow_huge_float_unit128(Bin, Sizes)
+ end
end;
overflow_huge_float_unit128(_, []) -> ok.
@@ -473,25 +459,24 @@ overflow_huge_float_unit128(_, []) -> ok.
%%
writable_binary_matched(Config) when is_list(Config) ->
- ?line WritableBin = create_writeable_binary(),
- ?line writable_binary_matched(WritableBin, WritableBin, 500).
+ WritableBin = create_writeable_binary(),
+ writable_binary_matched(WritableBin, WritableBin, 500).
writable_binary_matched(<<0>>, _, N) ->
- if
- N =:= 0 -> ok;
- true ->
- put(grow_heap, [N|get(grow_heap)]),
- ?line WritableBin = create_writeable_binary(),
- ?line writable_binary_matched(WritableBin, WritableBin, N-1)
+ if N =:= 0 -> ok;
+ true ->
+ put(grow_heap, [N|get(grow_heap)]),
+ WritableBin = create_writeable_binary(),
+ writable_binary_matched(WritableBin, WritableBin, N-1)
end;
writable_binary_matched(<<B:8,T/binary>>, WritableBin0, N) ->
- ?line WritableBin = writable_binary(WritableBin0, B),
+ WritableBin = writable_binary(WritableBin0, B),
writable_binary_matched(T, WritableBin, N).
writable_binary(WritableBin0, B) when is_binary(WritableBin0) ->
%% Heavy append to force the binary to move.
- ?line WritableBin = <<WritableBin0/binary,0:(size(WritableBin0))/unit:8,B>>,
- ?line id(<<(id(0)):128/unit:8>>),
+ WritableBin = <<WritableBin0/binary,0:(size(WritableBin0))/unit:8,B>>,
+ id(<<(id(0)):128/unit:8>>),
WritableBin.
create_writeable_binary() ->
@@ -502,7 +487,7 @@ otp_7198(Config) when is_list(Config) ->
%% increase the number of saved positions, the thing word was not updated
%% to account for the new size. Therefore, if there was a garbage collection,
%% the new slots would be included in the garbage collection.
- ?line [do_otp_7198(FillerSize) || FillerSize <- lists:seq(0, 256)],
+ [do_otp_7198(FillerSize) || FillerSize <- lists:seq(0, 256)],
ok.
do_otp_7198(FillerSize) ->
@@ -512,8 +497,7 @@ do_otp_7198(FillerSize) ->
{'DOWN',Ref,process,Pid,normal} ->
ok;
{'DOWN',Ref,process,Pid,Reason} ->
- io:format("unexpected: ~p", [Reason]),
- ?line ?t:fail()
+ ct:fail("unexpected: ~p", [Reason])
end.
do_otp_7198_test(_) ->
@@ -540,27 +524,27 @@ otp_7198_scan(<<>>, TokAcc) ->
otp_7198_scan(<<D, Z, Rest/binary>>, TokAcc) when
(D =:= $D orelse D =:= $d) and
((Z =:= $\s) or (Z =:= $() or (Z =:= $))) ->
- otp_7198_scan(<<Z, Rest/binary>>, ['AND' | TokAcc]);
+ otp_7198_scan(<<Z, Rest/binary>>, ['AND' | TokAcc]);
otp_7198_scan(<<D>>, TokAcc) when
(D =:= $D) or (D =:= $d) ->
- otp_7198_scan(<<>>, ['AND' | TokAcc]);
+ otp_7198_scan(<<>>, ['AND' | TokAcc]);
otp_7198_scan(<<N, Z, Rest/binary>>, TokAcc) when
(N =:= $N orelse N =:= $n) and
((Z =:= $\s) or (Z =:= $() or (Z =:= $))) ->
- otp_7198_scan(<<Z, Rest/binary>>, ['NOT' | TokAcc]);
+ otp_7198_scan(<<Z, Rest/binary>>, ['NOT' | TokAcc]);
otp_7198_scan(<<C, Rest/binary>>, TokAcc) when
(C >= $A) and (C =< $Z);
(C >= $a) and (C =< $z);
(C >= $0) and (C =< $9) ->
- case Rest of
- <<$:, R/binary>> ->
- otp_7198_scan(R, [{'FIELD', C} | TokAcc]);
- _ ->
- otp_7198_scan(Rest, [{'KEYWORD', C} | TokAcc])
- end.
+ case Rest of
+ <<$:, R/binary>> ->
+ otp_7198_scan(R, [{'FIELD', C} | TokAcc]);
+ _ ->
+ otp_7198_scan(Rest, [{'KEYWORD', C} | TokAcc])
+ end.
unordered_bindings(Config) when is_list(Config) ->
{<<1,2,3,4>>,<<42,42>>,<<3,3,3>>} =
diff --git a/erts/emulator/test/bs_match_tail_SUITE.erl b/erts/emulator/test/bs_match_tail_SUITE.erl
index 58b0d3fef6..8392a0df47 100644
--- a/erts/emulator/test/bs_match_tail_SUITE.erl
+++ b/erts/emulator/test/bs_match_tail_SUITE.erl
@@ -21,61 +21,46 @@
-module(bs_match_tail_SUITE).
-author('[email protected]').
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,aligned/1,unaligned/1,zero_tail/1]).
+-export([all/0, suite/0,
+ aligned/1,unaligned/1,zero_tail/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[aligned, unaligned, zero_tail].
-groups() ->
- [].
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-aligned(doc) -> "Test aligned tails.";
+%% Test aligned tails.
aligned(Config) when is_list(Config) ->
- ?line Tail1 = mkbin([]),
- ?line {258,Tail1} = al_get_tail_used(mkbin([1,2])),
- ?line Tail2 = mkbin(lists:seq(1, 127)),
- ?line {35091,Tail2} = al_get_tail_used(mkbin([137,19|Tail2])),
-
- ?line 64896 = al_get_tail_unused(mkbin([253,128])),
- ?line 64895 = al_get_tail_unused(mkbin([253,127|lists:seq(42, 255)])),
-
- ?line Tail3 = mkbin(lists:seq(0, 19)),
- ?line {0,Tail1} = get_dyn_tail_used(Tail1, 0),
- ?line {0,Tail3} = get_dyn_tail_used(mkbin([Tail3]), 0),
- ?line {73,Tail3} = get_dyn_tail_used(mkbin([73|Tail3]), 8),
-
- ?line 0 = get_dyn_tail_unused(mkbin([]), 0),
- ?line 233 = get_dyn_tail_unused(mkbin([233]), 8),
- ?line 23 = get_dyn_tail_unused(mkbin([23,22,2]), 8),
+ Tail1 = mkbin([]),
+ {258,Tail1} = al_get_tail_used(mkbin([1,2])),
+ Tail2 = mkbin(lists:seq(1, 127)),
+ {35091,Tail2} = al_get_tail_used(mkbin([137,19|Tail2])),
+
+ 64896 = al_get_tail_unused(mkbin([253,128])),
+ 64895 = al_get_tail_unused(mkbin([253,127|lists:seq(42, 255)])),
+
+ Tail3 = mkbin(lists:seq(0, 19)),
+ {0,Tail1} = get_dyn_tail_used(Tail1, 0),
+ {0,Tail3} = get_dyn_tail_used(mkbin([Tail3]), 0),
+ {73,Tail3} = get_dyn_tail_used(mkbin([73|Tail3]), 8),
+
+ 0 = get_dyn_tail_unused(mkbin([]), 0),
+ 233 = get_dyn_tail_unused(mkbin([233]), 8),
+ 23 = get_dyn_tail_unused(mkbin([23,22,2]), 8),
ok.
al_get_tail_used(<<A:16,T/binary>>) -> {A,T}.
al_get_tail_unused(<<A:16,_/binary>>) -> A.
-unaligned(doc) -> "Test that an non-aligned tail cannot be matched out.";
+%% Test that an non-aligned tail cannot be matched out.
unaligned(Config) when is_list(Config) ->
- ?line {'EXIT',{function_clause,_}} = (catch get_tail_used(mkbin([42]))),
- ?line {'EXIT',{{badmatch,_},_}} = (catch get_dyn_tail_used(mkbin([137]), 3)),
- ?line {'EXIT',{function_clause,_}} = (catch get_tail_unused(mkbin([42,33]))),
- ?line {'EXIT',{{badmatch,_},_}} = (catch get_dyn_tail_unused(mkbin([44]), 7)),
+ {'EXIT',{function_clause,_}} = (catch get_tail_used(mkbin([42]))),
+ {'EXIT',{{badmatch,_},_}} = (catch get_dyn_tail_used(mkbin([137]), 3)),
+ {'EXIT',{function_clause,_}} = (catch get_tail_unused(mkbin([42,33]))),
+ {'EXIT',{{badmatch,_},_}} = (catch get_dyn_tail_unused(mkbin([44]), 7)),
ok.
get_tail_used(<<A:1,T/binary>>) -> {A,T}.
@@ -90,11 +75,11 @@ get_dyn_tail_unused(Bin, Sz) ->
<<A:Sz,_/binary>> = Bin,
A.
-zero_tail(doc) -> "Test that zero tails are tested correctly.";
+%% Test that zero tails are tested correctly.
zero_tail(Config) when is_list(Config) ->
- ?line 7 = (catch test_zero_tail(mkbin([7]))),
- ?line {'EXIT',{function_clause,_}} = (catch test_zero_tail(mkbin([1,2]))),
- ?line {'EXIT',{function_clause,_}} = (catch test_zero_tail2(mkbin([1,2,3]))),
+ 7 = (catch test_zero_tail(mkbin([7]))),
+ {'EXIT',{function_clause,_}} = (catch test_zero_tail(mkbin([1,2]))),
+ {'EXIT',{function_clause,_}} = (catch test_zero_tail2(mkbin([1,2,3]))),
ok.
test_zero_tail(<<A:8>>) -> A.
@@ -102,7 +87,3 @@ test_zero_tail(<<A:8>>) -> A.
test_zero_tail2(<<_A:4,_B:4>>) -> ok.
mkbin(L) when is_list(L) -> list_to_binary(L).
-
-
-
-
diff --git a/erts/emulator/test/bs_utf_SUITE.erl b/erts/emulator/test/bs_utf_SUITE.erl
index 0625c22163..f1c09bfbb0 100644
--- a/erts/emulator/test/bs_utf_SUITE.erl
+++ b/erts/emulator/test/bs_utf_SUITE.erl
@@ -20,52 +20,28 @@
-module(bs_utf_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2,
+-export([all/0, suite/0,
utf8_roundtrip/1,utf16_roundtrip/1,utf32_roundtrip/1,
utf8_illegal_sequences/1,utf16_illegal_sequences/1,
utf32_illegal_sequences/1,
bad_construction/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--define(FAIL(Expr), ?line fail_check(catch Expr, ??Expr, [])).
+-define(FAIL(Expr), fail_check(catch Expr, ??Expr, [])).
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog = ?t:timetrap(?t:minutes(6)),
- [{watchdog,Dog}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 6}}].
all() ->
[utf8_roundtrip, utf16_roundtrip, utf32_roundtrip,
utf8_illegal_sequences, utf16_illegal_sequences,
utf32_illegal_sequences, bad_construction].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
utf8_roundtrip(Config) when is_list(Config) ->
- ?line utf8_roundtrip(0, 16#D7FF),
- ?line utf8_roundtrip(16#E000, 16#10FFFF),
+ utf8_roundtrip(0, 16#D7FF),
+ utf8_roundtrip(16#E000, 16#10FFFF),
ok.
utf8_roundtrip(First, Last) when First =< Last ->
@@ -83,10 +59,9 @@ utf16_roundtrip(Config) when is_list(Config) ->
Big = fun utf16_big_roundtrip/1,
Little = fun utf16_little_roundtrip/1,
PidRefs = [spawn_monitor(fun() ->
- do_utf16_roundtrip(Fun)
- end) || Fun <- [Big,Little]],
- [receive {'DOWN',Ref,process,Pid,Reason} -> normal=Reason end ||
- {Pid,Ref} <- PidRefs],
+ do_utf16_roundtrip(Fun)
+ end) || Fun <- [Big,Little]],
+ [receive {'DOWN',Ref,process,Pid,Reason} -> normal=Reason end || {Pid,Ref} <- PidRefs],
ok.
do_utf16_roundtrip(Fun) ->
@@ -154,20 +129,20 @@ utf32_little_roundtrip(Char) ->
ok.
utf8_illegal_sequences(Config) when is_list(Config) ->
- ?line fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large.
- ?line fail_range(16#D800, 16#DFFF), %Reserved for UTF-16.
+ fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large.
+ fail_range(16#D800, 16#DFFF), %Reserved for UTF-16.
%% Illegal first character.
- ?line [fail(<<I,16#8F,16#8F,16#8F>>) || I <- lists:seq(16#80, 16#BF)],
+ [fail(<<I,16#8F,16#8F,16#8F>>) || I <- lists:seq(16#80, 16#BF)],
%% Short sequences.
- ?line short_sequences(16#80, 16#10FFFF),
+ short_sequences(16#80, 16#10FFFF),
%% Overlong sequences. (Using more bytes than necessary
%% is not allowed.)
- ?line overlong(0, 127, 2),
- ?line overlong(128, 16#7FF, 3),
- ?line overlong(16#800, 16#FFFF, 4),
+ overlong(0, 127, 2),
+ overlong(128, 16#7FF, 3),
+ overlong(16#800, 16#FFFF, 4),
ok.
fail_range(Char, End) when Char =< End ->
@@ -187,9 +162,9 @@ short_sequences(Char, End) ->
short_sequences_1(Char, Step, End) when Char =< End ->
CharEnd = lists:min([Char+Step-1,End]),
[spawn_monitor(fun() ->
- io:format("~p - ~p\n", [Char,CharEnd]),
- do_short_sequences(Char, CharEnd)
- end)|short_sequences_1(Char+Step, Step, End)];
+ io:format("~p - ~p\n", [Char,CharEnd]),
+ do_short_sequences(Char, CharEnd)
+ end)|short_sequences_1(Char+Step, Step, End)];
short_sequences_1(_, _, _) -> [].
do_short_sequences(Char, End) when Char =< End ->
@@ -228,9 +203,9 @@ overlong(_, _, _) -> ok.
overlong(Char, NumBytes) when NumBytes < 5 ->
case int_to_utf8(Char, NumBytes) of
<<Char/utf8>>=Bin ->
- ?t:fail({illegal_encoding_accepted,Bin,Char});
+ ct:fail({illegal_encoding_accepted,Bin,Char});
<<OtherChar/utf8>>=Bin ->
- ?t:fail({illegal_encoding_accepted,Bin,Char,OtherChar});
+ ct:fail({illegal_encoding_accepted,Bin,Char,OtherChar});
_ -> ok
end,
overlong(Char, NumBytes+1);
@@ -241,16 +216,16 @@ fail(Bin) ->
fail_1(make_unaligned(Bin)).
fail_1(<<Char/utf8>>=Bin) ->
- ?t:fail({illegal_encoding_accepted,Bin,Char});
+ ct:fail({illegal_encoding_accepted,Bin,Char});
fail_1(_) -> ok.
utf16_illegal_sequences(Config) when is_list(Config) ->
- ?line utf16_fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large.
- ?line utf16_fail_range(16#D800, 16#DFFF), %Reserved for UTF-16.
+ utf16_fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large.
+ utf16_fail_range(16#D800, 16#DFFF), %Reserved for UTF-16.
- ?line lonely_hi_surrogate(16#D800, 16#DFFF),
- ?line leading_lo_surrogate(16#DC00, 16#DFFF),
+ lonely_hi_surrogate(16#D800, 16#DFFF),
+ leading_lo_surrogate(16#DC00, 16#DFFF),
ok.
@@ -265,9 +240,9 @@ lonely_hi_surrogate(Char, End) when Char =< End ->
BinLittle = <<Char:16/little>>,
case {BinBig,BinLittle} of
{<<Bad/big-utf16>>,_} ->
- ?t:fail({lonely_hi_surrogate_accepted,Bad});
+ ct:fail({lonely_hi_surrogate_accepted,Bad});
{_,<<Bad/little-utf16>>} ->
- ?t:fail({lonely_hi_surrogate_accepted,Bad});
+ ct:fail({lonely_hi_surrogate_accepted,Bad});
{_,_} ->
ok
end,
@@ -284,9 +259,9 @@ leading_lo_surrogate(HiSurr, LoSurr, End) when LoSurr =< End ->
BinLittle = <<HiSurr:16/little,LoSurr:16/little>>,
case {BinBig,BinLittle} of
{<<Bad/big-utf16,_/bits>>,_} ->
- ?t:fail({leading_lo_surrogate_accepted,Bad});
+ ct:fail({leading_lo_surrogate_accepted,Bad});
{_,<<Bad/little-utf16,_/bits>>} ->
- ?t:fail({leading_lo_surrogate_accepted,Bad});
+ ct:fail({leading_lo_surrogate_accepted,Bad});
{_,_} ->
ok
end,
@@ -294,20 +269,20 @@ leading_lo_surrogate(HiSurr, LoSurr, End) when LoSurr =< End ->
leading_lo_surrogate(_, _, _) -> ok.
utf32_illegal_sequences(Config) when is_list(Config) ->
- ?line utf32_fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large.
- ?line utf32_fail_range(16#D800, 16#DFFF), %Reserved for UTF-16.
- ?line utf32_fail_range(-100, -1),
+ utf32_fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large.
+ utf32_fail_range(16#D800, 16#DFFF), %Reserved for UTF-16.
+ utf32_fail_range(-100, -1),
ok.
utf32_fail_range(Char, End) when Char =< End ->
{'EXIT',_} = (catch <<Char/big-utf32>>),
{'EXIT',_} = (catch <<Char/little-utf32>>),
case {<<Char:32>>,<<Char:32/little>>} of
- {<<Unexpected/utf32>>,_} ->
- ?line ?t:fail(Unexpected);
- {_,<<Unexpected/little-utf32>>} ->
- ?line ?t:fail(Unexpected);
- {_,_} -> ok
+ {<<Unexpected/utf32>>,_} ->
+ ct:fail(Unexpected);
+ {_,<<Unexpected/little-utf32>>} ->
+ ct:fail(Unexpected);
+ {_,_} -> ok
end,
utf32_fail_range(Char+1, End);
utf32_fail_range(_, _) -> ok.
@@ -387,14 +362,14 @@ fail_check({'EXIT',{badarg,_}}, Str, Vars) ->
try evaluate(Str, Vars) of
Res ->
io:format("Interpreted result: ~p", [Res]),
- ?t:fail(did_not_fail_in_intepreted_code)
+ ct:fail(did_not_fail_in_intepreted_code)
catch
error:badarg ->
ok
end;
fail_check(Res, _, _) ->
io:format("Compiled result: ~p", [Res]),
- ?t:fail(did_not_fail_in_compiled_code).
+ ct:fail(did_not_fail_in_compiled_code).
evaluate(Str, Vars) ->
{ok,Tokens,_} =
@@ -406,4 +381,3 @@ evaluate(Str, Vars) ->
end.
id(I) -> I.
-
diff --git a/erts/emulator/test/busy_port_SUITE.erl b/erts/emulator/test/busy_port_SUITE.erl
index 6a2588aadd..c582f8d77b 100644
--- a/erts/emulator/test/busy_port_SUITE.erl
+++ b/erts/emulator/test/busy_port_SUITE.erl
@@ -20,8 +20,7 @@
-module(busy_port_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,end_per_testcase/2,
+-export([all/0, suite/0, end_per_testcase/2,
io_to_busy/1, message_order/1, send_3/1,
system_monitor/1, no_trap_exit/1,
no_trap_exit_unlinked/1, trap_exit/1, multiple_writers/1,
@@ -29,12 +28,14 @@
-compile(export_all).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Internal exports.
-export([init/2]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 4}}].
all() ->
[io_to_busy, message_order, send_3, system_monitor,
@@ -43,21 +44,6 @@ all() ->
scheduling_delay_busy,scheduling_delay_busy_nosuspend,
scheduling_busy_link].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
end_per_testcase(_Case, Config) when is_list(Config) ->
case whereis(busy_drv_server) of
undefined ->
@@ -76,17 +62,14 @@ end_per_testcase(_Case, Config) when is_list(Config) ->
%% Tests I/O operations to a busy port, to make sure a suspended send
%% operation is correctly restarted. This used to crash Beam.
-io_to_busy(suite) -> [];
io_to_busy(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(30)),
+ ct:timetrap({seconds, 30}),
- ?line start_busy_driver(Config),
- ?line process_flag(trap_exit, true),
- ?line Writer = fun_spawn(fun writer/0),
- ?line Generator = fun_spawn(fun() -> generator(100, Writer) end),
- ?line wait_for([Writer, Generator]),
-
- ?line test_server:timetrap_cancel(Dog),
+ start_busy_driver(Config),
+ process_flag(trap_exit, true),
+ Writer = fun_spawn(fun writer/0),
+ Generator = fun_spawn(fun() -> generator(100, Writer) end),
+ wait_for([Writer, Generator]),
ok.
generator(N, Writer) ->
@@ -130,27 +113,24 @@ forget(_) ->
%% Test the interaction of busy ports and message sending.
%% This used to cause the wrong message to be received.
-message_order(suite) -> {req, dynamic_loading};
message_order(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
-
- ?line start_busy_driver(Config),
- ?line Self = self(),
- ?line Busy = fun_spawn(fun () -> send_to_busy_1(Self) end),
- ?line receive after 1000 -> ok end,
- ?line Busy ! first,
- ?line Busy ! second,
- ?line receive after 1 -> ok end,
- ?line unlock_slave(),
- ?line Busy ! third,
- ?line receive
- {Busy, first} ->
- ok;
- Other ->
- test_server:fail({unexpected_message, Other})
- end,
-
- ?line test_server:timetrap_cancel(Dog),
+ ct:timetrap({seconds, 10}),
+
+ start_busy_driver(Config),
+ Self = self(),
+ Busy = fun_spawn(fun () -> send_to_busy_1(Self) end),
+ receive after 1000 -> ok end,
+ Busy ! first,
+ Busy ! second,
+ receive after 1 -> ok end,
+ unlock_slave(),
+ Busy ! third,
+ receive
+ {Busy, first} ->
+ ok;
+ Other ->
+ ct:fail({unexpected_message, Other})
+ end,
ok.
send_to_busy_1(Parent) ->
@@ -164,80 +144,64 @@ send_to_busy_1(Parent) ->
end.
%% Test the bif send/3
-send_3(suite) -> {req,dynamic_loading};
-send_3(doc) -> ["Test the BIF send/3"];
send_3(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
+ ct:timetrap({seconds, 10}),
%%
- ?line start_busy_driver(Config),
- ?line {Owner,Slave} = get_slave(),
- ?line ok = erlang:send(Slave, {Owner,{command,"set busy"}},
- [nosuspend]),
+ start_busy_driver(Config),
+ {Owner,Slave} = get_slave(),
+ ok = erlang:send(Slave, {Owner,{command,"set busy"}}, [nosuspend]),
receive after 100 -> ok end, % ensure command reached port
- ?line nosuspend = erlang:send(Slave, {Owner,{command,"busy"}},
- [nosuspend]),
- ?line unlock_slave(),
- ?line ok = erlang:send(Slave, {Owner,{command,"not busy"}},
- [nosuspend]),
- ?line ok = command(stop),
- %%
- ?line test_server:timetrap_cancel(Dog),
+ nosuspend = erlang:send(Slave, {Owner,{command,"busy"}}, [nosuspend]),
+ unlock_slave(),
+ ok = erlang:send(Slave, {Owner,{command,"not busy"}}, [nosuspend]),
+ ok = command(stop),
ok.
%% Test the erlang:system_monitor(Pid, [busy_port])
-system_monitor(suite) -> {req,dynamic_loading};
-system_monitor(doc) -> ["Test erlang:system_monitor({Pid,[busy_port]})."];
system_monitor(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Self = self(),
+ ct:timetrap({seconds, 10}),
+ Self = self(),
%%
- ?line OldMonitor = erlang:system_monitor(Self, [busy_port]),
- ?line {Self,[busy_port]} = erlang:system_monitor(),
- ?line Void = make_ref(),
- ?line start_busy_driver(Config),
- ?line {Owner,Slave} = get_slave(),
- ?line Master = command(get_master),
- ?line Parent = self(),
- ?line Busy =
- spawn_link(
- fun() ->
- (catch port_command(Slave, "set busy")),
- receive {Parent,alpha} -> ok end,
- (catch port_command(Slave, "busy")),
- (catch port_command(Slave, "free")),
- Parent ! {self(),alpha},
- command(lock),
- receive {Parent,beta} -> ok end,
- command({port_command,"busy"}),
- command({port_command,"free"}),
- Parent ! {self(),beta}
- end),
- ?line Void = rec(Void),
- ?line Busy ! {self(),alpha},
- ?line {monitor,Busy,busy_port,Slave} = rec(Void),
- ?line unlock_slave(),
- ?line {Busy,alpha} = rec(Void),
- ?line Void = rec(Void),
- ?line Busy ! {self(), beta},
- ?line {monitor,Owner,busy_port,Slave} = rec(Void),
- ?line port_command(Master, "u"),
- ?line {Busy,beta} = rec(Void),
- ?line Void = rec(Void),
- ?line _NewMonitor = erlang:system_monitor(OldMonitor),
- ?line OldMonitor = erlang:system_monitor(),
- ?line OldMonitor = erlang:system_monitor(OldMonitor),
- %%
- ?line test_server:timetrap_cancel(Dog),
+ OldMonitor = erlang:system_monitor(Self, [busy_port]),
+ {Self,[busy_port]} = erlang:system_monitor(),
+ Void = make_ref(),
+ start_busy_driver(Config),
+ {Owner,Slave} = get_slave(),
+ Master = command(get_master),
+ Parent = self(),
+ Busy = spawn_link(
+ fun() ->
+ (catch port_command(Slave, "set busy")),
+ receive {Parent,alpha} -> ok end,
+ (catch port_command(Slave, "busy")),
+ (catch port_command(Slave, "free")),
+ Parent ! {self(),alpha},
+ command(lock),
+ receive {Parent,beta} -> ok end,
+ command({port_command,"busy"}),
+ command({port_command,"free"}),
+ Parent ! {self(),beta}
+ end),
+ Void = rec(Void),
+ Busy ! {self(),alpha},
+ {monitor,Busy,busy_port,Slave} = rec(Void),
+ unlock_slave(),
+ {Busy,alpha} = rec(Void),
+ Void = rec(Void),
+ Busy ! {self(), beta},
+ {monitor,Owner,busy_port,Slave} = rec(Void),
+ port_command(Master, "u"),
+ {Busy,beta} = rec(Void),
+ Void = rec(Void),
+ _NewMonitor = erlang:system_monitor(OldMonitor),
+ OldMonitor = erlang:system_monitor(),
+ OldMonitor = erlang:system_monitor(OldMonitor),
ok.
-
-
rec(Tag) ->
receive X -> X after 1000 -> Tag end.
-
-
%% Assuming the following scenario,
%%
%% +---------------+ +-----------+
@@ -248,65 +212,59 @@ rec(Tag) ->
%%
%% tests that the suspended process is killed if the port is killed.
-no_trap_exit(suite) -> [];
no_trap_exit(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line process_flag(trap_exit, true),
- ?line Pid = fun_spawn(fun no_trap_exit_process/3,
- [self(), linked, Config]),
- ?line receive
- {Pid, port_created, Port} ->
- io:format("Process ~w created port ~w", [Pid, Port]),
- ?line exit(Port, die);
- Other1 ->
- test_server:fail({unexpected_message, Other1})
- end,
- ?line receive
- {'EXIT', Pid, die} ->
- ok;
- Other2 ->
- test_server:fail({unexpected_message, Other2})
- end,
-
- ?line test_server:timetrap_cancel(Dog),
+ ct:timetrap({seconds, 10}),
+ process_flag(trap_exit, true),
+ Pid = fun_spawn(fun no_trap_exit_process/3, [self(), linked, Config]),
+ receive
+ {Pid, port_created, Port} ->
+ io:format("Process ~w created port ~w", [Pid, Port]),
+ exit(Port, die);
+ Other1 ->
+ ct:fail({unexpected_message, Other1})
+ end,
+ receive
+ {'EXIT', Pid, die} ->
+ ok;
+ Other2 ->
+ ct:fail({unexpected_message, Other2})
+ end,
ok.
%% The same scenario as above, but the port has been explicitly
%% unlinked from the process.
-no_trap_exit_unlinked(suite) -> [];
no_trap_exit_unlinked(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line process_flag(trap_exit, true),
- ?line Pid = fun_spawn(fun no_trap_exit_process/3,
- [self(), unlink, Config]),
- ?line receive
- {Pid, port_created, Port} ->
- io:format("Process ~w created port ~w", [Pid, Port]),
- ?line exit(Port, die);
- Other1 ->
- test_server:fail({unexpected_message, Other1})
- end,
- ?line receive
- {'EXIT', Pid, normal} ->
- ok;
- Other2 ->
- test_server:fail({unexpected_message, Other2})
- end,
- ?line test_server:timetrap_cancel(Dog),
+ ct:timetrap({seconds, 10}),
+ process_flag(trap_exit, true),
+ Pid = fun_spawn(fun no_trap_exit_process/3,
+ [self(), unlink, Config]),
+ receive
+ {Pid, port_created, Port} ->
+ io:format("Process ~w created port ~w", [Pid, Port]),
+ exit(Port, die);
+ Other1 ->
+ ct:fail({unexpected_message, Other1})
+ end,
+ receive
+ {'EXIT', Pid, normal} ->
+ ok;
+ Other2 ->
+ ct:fail({unexpected_message, Other2})
+ end,
ok.
no_trap_exit_process(ResultTo, Link, Config) ->
- ?line load_busy_driver(Config),
- ?line _Master = open_port({spawn, "busy_drv master"}, [eof]),
- ?line Slave = open_port({spawn, "busy_drv slave"}, [eof]),
- ?line case Link of
- linked -> ok;
- unlink -> unlink(Slave)
- end,
- ?line (catch port_command(Slave, "lock port")),
- ?line ResultTo ! {self(), port_created, Slave},
- ?line (catch port_command(Slave, "suspend me")),
+ load_busy_driver(Config),
+ _Master = open_port({spawn, "busy_drv master"}, [eof]),
+ Slave = open_port({spawn, "busy_drv slave"}, [eof]),
+ case Link of
+ linked -> ok;
+ unlink -> unlink(Slave)
+ end,
+ (catch port_command(Slave, "lock port")),
+ ResultTo ! {self(), port_created, Slave},
+ (catch port_command(Slave, "suspend me")),
ok.
%% Assuming the following scenario,
@@ -320,36 +278,34 @@ no_trap_exit_process(ResultTo, Link, Config) ->
%% tests that the suspended process is scheduled runnable and
%% receives an 'EXIT' message if the port is killed.
-trap_exit(suite) -> [];
trap_exit(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Pid = fun_spawn(fun busy_port_exit_process/2, [self(), Config]),
- ?line receive
+ ct:timetrap({seconds, 10}),
+ Pid = fun_spawn(fun busy_port_exit_process/2, [self(), Config]),
+ receive
{Pid, port_created, Port} ->
io:format("Process ~w created port ~w", [Pid, Port]),
- ?line unlink(Pid),
- ?line {status, suspended} = process_info(Pid, status),
- ?line exit(Port, die);
+ unlink(Pid),
+ {status, suspended} = process_info(Pid, status),
+ exit(Port, die);
Other1 ->
- test_server:fail({unexpected_message, Other1})
+ ct:fail({unexpected_message, Other1})
end,
- ?line receive
+ receive
{Pid, ok} ->
ok;
Other2 ->
- test_server:fail({unexpected_message, Other2})
+ ct:fail({unexpected_message, Other2})
end,
- ?line test_server:timetrap_cancel(Dog),
ok.
busy_port_exit_process(ResultTo, Config) ->
- ?line process_flag(trap_exit, true),
- ?line load_busy_driver(Config),
- ?line _Master = open_port({spawn, "busy_drv master"}, [eof]),
- ?line Slave = open_port({spawn, "busy_drv slave"}, [eof]),
- ?line (catch port_command(Slave, "lock port")),
- ?line ResultTo ! {self(), port_created, Slave},
- ?line (catch port_command(Slave, "suspend me")),
+ process_flag(trap_exit, true),
+ load_busy_driver(Config),
+ _Master = open_port({spawn, "busy_drv master"}, [eof]),
+ Slave = open_port({spawn, "busy_drv slave"}, [eof]),
+ (catch port_command(Slave, "lock port")),
+ ResultTo ! {self(), port_created, Slave},
+ (catch port_command(Slave, "suspend me")),
receive
{'EXIT', Slave, die} ->
ResultTo ! {self(), ok};
@@ -362,19 +318,18 @@ busy_port_exit_process(ResultTo, Config) ->
%% This should work even if some of the processes have terminated
%% in the meantime.
-multiple_writers(suite) -> [];
multiple_writers(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line start_busy_driver(Config),
- ?line process_flag(trap_exit, true),
+ ct:timetrap({seconds, 10}),
+ start_busy_driver(Config),
+ process_flag(trap_exit, true),
%% Start the waiters and make sure they have blocked.
- ?line W1 = fun_spawn(fun quick_writer/0),
- ?line W2 = fun_spawn(fun quick_writer/0),
- ?line W3 = fun_spawn(fun quick_writer/0),
- ?line W4 = fun_spawn(fun quick_writer/0),
- ?line W5 = fun_spawn(fun quick_writer/0),
- ?line test_server:sleep(500), % Make sure writers have blocked.
+ W1 = fun_spawn(fun quick_writer/0),
+ W2 = fun_spawn(fun quick_writer/0),
+ W3 = fun_spawn(fun quick_writer/0),
+ W4 = fun_spawn(fun quick_writer/0),
+ W5 = fun_spawn(fun quick_writer/0),
+ test_server:sleep(500), % Make sure writers have blocked.
%% Kill two of the processes.
exit(W1, kill),
@@ -383,10 +338,8 @@ multiple_writers(Config) when is_list(Config) ->
receive {'EXIT', W3, killed} -> ok end,
%% Unlock the port. The surviving processes should be become runnable.
- ?line unlock_slave(),
- ?line wait_for([W2, W4, W5]),
-
- ?line test_server:timetrap_cancel(Dog),
+ unlock_slave(),
+ wait_for([W2, W4, W5]),
ok.
quick_writer() ->
@@ -402,205 +355,193 @@ soft_busy_driver(Config) when is_list(Config) ->
hs_test(Config, false).
hs_test(Config, HardBusy) when is_list(Config) ->
- ?line DrvName = case HardBusy of
- true -> 'hard_busy_drv';
- false -> 'soft_busy_drv'
- end,
- ?line erl_ddll:start(),
- ?line Path = ?config(data_dir, Config),
+ DrvName = case HardBusy of
+ true -> 'hard_busy_drv';
+ false -> 'soft_busy_drv'
+ end,
+ erl_ddll:start(),
+ Path = proplists:get_value(data_dir, Config),
case erl_ddll:load_driver(Path, DrvName) of
- ok -> ok;
- {error, Error} ->
- io:format("~s\n", [erl_ddll:format_error(Error)]),
- ?line ?t:fail()
+ ok -> ok;
+ {error, Error} ->
+ ct:fail(erl_ddll:format_error(Error))
end,
- ?line Port = open_port({spawn, DrvName}, []),
-
+ Port = open_port({spawn, DrvName}, []),
+
NotSuspended = fun (Proc) ->
- chk_not_value({status,suspended},
- process_info(Proc, status))
- end,
+ chk_not_value({status,suspended},
+ process_info(Proc, status))
+ end,
NotBusyEnd = fun (Proc, Res, Time) ->
- receive
- {Port, caller, Proc} -> ok
- after
- 500 -> exit(missing_caller_message)
- end,
- chk_value({return, true}, Res),
- chk_range(0, Time, 100)
- end,
+ receive
+ {Port, caller, Proc} -> ok
+ after
+ 500 -> exit(missing_caller_message)
+ end,
+ chk_value({return, true}, Res),
+ chk_range(0, Time, 100)
+ end,
ForceEnd = fun (Proc, Res, Time) ->
- case HardBusy of
- false ->
- NotBusyEnd(Proc, Res, Time);
- true ->
- chk_value({error, notsup}, Res),
- chk_range(0, Time, 100),
- receive
- Msg -> exit({unexpected_msg, Msg})
- after
- 500 -> ok
- end
- end
- end,
+ case HardBusy of
+ false ->
+ NotBusyEnd(Proc, Res, Time);
+ true ->
+ chk_value({error, notsup}, Res),
+ chk_range(0, Time, 100),
+ receive
+ Msg -> exit({unexpected_msg, Msg})
+ after
+ 500 -> ok
+ end
+ end
+ end,
BadArg = fun (_Proc, Res, Time) ->
- chk_value({error, badarg}, Res),
- chk_range(0, Time, 100)
- end,
+ chk_value({error, badarg}, Res),
+ chk_range(0, Time, 100)
+ end,
%% Not busy
%% Not busy; nosuspend option
- ?line hs_busy_pcmd(Port, [nosuspend], NotSuspended, NotBusyEnd),
+ hs_busy_pcmd(Port, [nosuspend], NotSuspended, NotBusyEnd),
%% Not busy; force option
- ?line hs_busy_pcmd(Port, [force], NotSuspended, ForceEnd),
+ hs_busy_pcmd(Port, [force], NotSuspended, ForceEnd),
%% Not busy; force and nosuspend option
- ?line hs_busy_pcmd(Port, [force, nosuspend], NotSuspended, ForceEnd),
+ hs_busy_pcmd(Port, [force, nosuspend], NotSuspended, ForceEnd),
%% Not busy; no option
- ?line hs_busy_pcmd(Port, [], NotSuspended, NotBusyEnd),
+ hs_busy_pcmd(Port, [], NotSuspended, NotBusyEnd),
%% Not busy; bad option
- ?line hs_busy_pcmd(Port, [bad_option], NotSuspended, BadArg),
+ hs_busy_pcmd(Port, [bad_option], NotSuspended, BadArg),
%% Make busy
- ?line erlang:port_control(Port, $B, []),
+ erlang:port_control(Port, $B, []),
%% Busy; nosuspend option
- ?line hs_busy_pcmd(Port, [nosuspend], NotSuspended,
- fun (_Proc, Res, Time) ->
- chk_value({return, false}, Res),
- chk_range(0, Time, 100),
- receive
- Msg -> exit({unexpected_msg, Msg})
- after
- 500 -> ok
- end
- end),
+ hs_busy_pcmd(Port, [nosuspend], NotSuspended,
+ fun (_Proc, Res, Time) ->
+ chk_value({return, false}, Res),
+ chk_range(0, Time, 100),
+ receive
+ Msg -> exit({unexpected_msg, Msg})
+ after
+ 500 -> ok
+ end
+ end),
%% Busy; force option
- ?line hs_busy_pcmd(Port, [force], NotSuspended, ForceEnd),
+ hs_busy_pcmd(Port, [force], NotSuspended, ForceEnd),
%% Busy; force and nosuspend option
- ?line hs_busy_pcmd(Port, [force, nosuspend], NotSuspended, ForceEnd),
+ hs_busy_pcmd(Port, [force, nosuspend], NotSuspended, ForceEnd),
%% Busy; bad option
- ?line hs_busy_pcmd(Port, [bad_option], NotSuspended, BadArg),
+ hs_busy_pcmd(Port, [bad_option], NotSuspended, BadArg),
%% no option on busy port
- ?line hs_busy_pcmd(Port, [],
- fun (Proc) ->
- receive after 1000 -> ok end,
- chk_value({status,suspended},
- process_info(Proc, status)),
-
- %% Make not busy
- erlang:port_control(Port, $N, [])
- end,
- fun (_Proc, Res, Time) ->
- chk_value({return, true}, Res),
- chk_range(1000, Time, 2000)
- end),
-
- ?line true = erlang:port_close(Port),
- ?line ok = erl_ddll:unload_driver(DrvName),
- ?line ok = erl_ddll:stop(),
- ?line ok.
+ hs_busy_pcmd(Port, [],
+ fun (Proc) ->
+ receive after 1000 -> ok end,
+ chk_value({status,suspended},
+ process_info(Proc, status)),
+
+ %% Make not busy
+ erlang:port_control(Port, $N, [])
+ end,
+ fun (_Proc, Res, Time) ->
+ chk_value({return, true}, Res),
+ chk_range(1000, Time, 2000)
+ end),
+
+ true = erlang:port_close(Port),
+ ok = erl_ddll:unload_driver(DrvName),
+ ok = erl_ddll:stop(),
+ ok.
hs_busy_pcmd(Prt, Opts, StartFun, EndFun) ->
Tester = self(),
P = spawn_link(fun () ->
- erlang:yield(),
- Tester ! {self(), doing_port_command},
- Start = erlang:monotonic_time(micro_seconds),
- Res = try {return,
- port_command(Prt, [], Opts)}
- catch Exception:Error -> {Exception, Error}
- end,
- End = erlang:monotonic_time(micro_seconds),
- Time = round((End - Start)/1000),
- Tester ! {self(), port_command_result, Res, Time}
- end),
+ erlang:yield(),
+ Tester ! {self(), doing_port_command},
+ Start = erlang:monotonic_time(micro_seconds),
+ Res = try {return,
+ port_command(Prt, [], Opts)}
+ catch Exception:Error -> {Exception, Error}
+ end,
+ End = erlang:monotonic_time(micro_seconds),
+ Time = round((End - Start)/1000),
+ Tester ! {self(), port_command_result, Res, Time}
+ end),
receive
- {P, doing_port_command} ->
- ok
+ {P, doing_port_command} ->
+ ok
end,
StartFun(P),
receive
- {P, port_command_result, Res, Time} ->
- EndFun(P, Res, Time)
+ {P, port_command_result, Res, Time} ->
+ EndFun(P, Res, Time)
end.
scheduling_delay_busy(Config) ->
-
- Scenario =
- [{1,{spawn,[{var,drvname},undefined]}},
- {2,{call,[{var,1},open_port]}},
- {3,{spawn,[{var,2},{var,1}]}},
- {0,{ack,[{var,1},{busy,1,250}]}},
- {0,{cast,[{var,3},{command,2}]}},
- [{0,{cast,[{var,3},{command,I}]}}
- || I <- lists:seq(3,50)],
- {0,{cast,[{var,3},take_control]}},
- {0,{cast,[{var,1},{new_owner,{var,3}}]}},
- {0,{cast,[{var,3},close]}},
- {0,{timer,sleep,[300]}},
- {0,{erlang,port_command,[{var,2},<<$N>>,[force]]}},
- [{0,{cast,[{var,1},{command,I}]}}
- || I <- lists:seq(101,127)]
- ,{10,{call,[{var,3},get_data]}}
- ],
+ Scenario = [{1,{spawn,[{var,drvname},undefined]}},
+ {2,{call,[{var,1},open_port]}},
+ {3,{spawn,[{var,2},{var,1}]}},
+ {0,{ack,[{var,1},{busy,1,250}]}},
+ {0,{cast,[{var,3},{command,2}]}},
+ [{0,{cast,[{var,3},{command,I}]}} || I <- lists:seq(3,50)],
+ {0,{cast,[{var,3},take_control]}},
+ {0,{cast,[{var,1},{new_owner,{var,3}}]}},
+ {0,{cast,[{var,3},close]}},
+ {0,{timer,sleep,[300]}},
+ {0,{erlang,port_command,[{var,2},<<$N>>,[force]]}},
+ [{0,{cast,[{var,1},{command,I}]}} || I <- lists:seq(101,127)],
+ {10,{call,[{var,3},get_data]}}],
Validation = [{seq,10,lists:seq(1,50)}],
- port_scheduling(Scenario,Validation,?config(data_dir,Config)).
+ port_scheduling(Scenario,Validation,proplists:get_value(data_dir,Config)).
scheduling_delay_busy_nosuspend(Config) ->
-
- Scenario =
- [{1,{spawn,[{var,drvname},undefined]}},
- {2,{call,[{var,1},open_port]}},
- {0,{cast,[{var,1},{command,1,100}]}},
- {0,{cast,[{var,1},{busy,2}]}},
- {0,{timer,sleep,[200]}}, % ensure reached port
- {10,{call,[{var,1},{command,3,[nosuspend]}]}},
- {0,{timer,sleep,[200]}},
- {0,{erlang,port_command,[{var,2},<<$N>>,[force]]}},
- {0,{cast,[{var,1},close]}},
- {20,{call,[{var,1},get_data]}}
- ],
+ Scenario = [{1,{spawn,[{var,drvname},undefined]}},
+ {2,{call,[{var,1},open_port]}},
+ {0,{cast,[{var,1},{command,1,100}]}},
+ {0,{cast,[{var,1},{busy,2}]}},
+ {0,{timer,sleep,[200]}}, % ensure reached port
+ {10,{call,[{var,1},{command,3,[nosuspend]}]}},
+ {0,{timer,sleep,[200]}},
+ {0,{erlang,port_command,[{var,2},<<$N>>,[force]]}},
+ {0,{cast,[{var,1},close]}},
+ {20,{call,[{var,1},get_data]}}],
Validation = [{eq,10,nosuspend},{seq,20,[1,2]}],
- port_scheduling(Scenario,Validation,?config(data_dir,Config)).
+ port_scheduling(Scenario,Validation,proplists:get_value(data_dir,Config)).
scheduling_busy_link(Config) ->
-
- Scenario =
- [{1,{spawn,[{var,drvname},undefined]}},
- {2,{call,[{var,1},open_port]}},
- {3,{spawn,[{var,2},{var,1}]}},
- {0,{cast,[{var,1},unlink]}},
- {0,{cast,[{var,1},{busy,1}]}},
- {0,{cast,[{var,1},{command,2}]}},
- {0,{cast,[{var,1},link]}},
- {0,{timer,sleep,[1000]}},
- {0,{ack,[{var,3},take_control]}},
- {0,{cast,[{var,1},{new_owner,{var,3}}]}},
- {0,{cast,[{var,3},close]}},
- {10,{call,[{var,3},get_data]}},
- {20,{call,[{var,1},get_exit]}}
- ],
+ Scenario = [{1,{spawn,[{var,drvname},undefined]}},
+ {2,{call,[{var,1},open_port]}},
+ {3,{spawn,[{var,2},{var,1}]}},
+ {0,{cast,[{var,1},unlink]}},
+ {0,{cast,[{var,1},{busy,1}]}},
+ {0,{cast,[{var,1},{command,2}]}},
+ {0,{cast,[{var,1},link]}},
+ {0,{timer,sleep,[1000]}},
+ {0,{ack,[{var,3},take_control]}},
+ {0,{cast,[{var,1},{new_owner,{var,3}}]}},
+ {0,{cast,[{var,3},close]}},
+ {10,{call,[{var,3},get_data]}},
+ {20,{call,[{var,1},get_exit]}}],
Validation = [{seq,10,[1]},
{seq,20,[{'EXIT',noproc}]}],
- port_scheduling(Scenario,Validation,?config(data_dir,Config)).
+ port_scheduling(Scenario,Validation,proplists:get_value(data_dir,Config)).
process_init(DrvName,Owner) ->
process_flag(trap_exit,true),
@@ -699,11 +640,11 @@ handle_msg(close,Port,Owner,_Data) ->
handle_msg(get_data,Port,_Owner,{[],_Exit}) ->
%% Wait for data if it has not arrived yet
receive
- {Port,{data,Data}} ->
- Data
+ {Port,{data,Data}} ->
+ Data
after 2000 ->
- pal("~p",[erlang:process_info(self())]),
- exit(did_not_get_port_data)
+ pal("~p",[erlang:process_info(self())]),
+ exit(did_not_get_port_data)
end;
handle_msg(get_data,_Port,Owner,{Data,Exit}) ->
pal("GetData",[]),
@@ -753,8 +694,7 @@ port_scheduling(Scenario,Validation,Path) ->
case erl_ddll:load_driver(Path, DrvName) of
ok -> ok;
{error, Error} ->
- io:format("~s\n", [erl_ddll:format_error(Error)]),
- ?line ?t:fail()
+ ct:fail(erl_ddll:format_error(Error))
end,
Data = run_scenario(lists:flatten(Scenario),[{drvname,DrvName}]),
@@ -860,7 +800,7 @@ wait_for(Pids) ->
{'EXIT', Pid, normal} ->
wait_for(lists:delete(Pid, Pids));
Other ->
- test_server:fail({bad_exit, Other})
+ ct:fail({bad_exit, Other})
end.
fun_spawn(Fun) ->
@@ -896,39 +836,38 @@ fun_spawn(Fun, Args) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
load_busy_driver(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line erl_ddll:start(),
+ DataDir = proplists:get_value(data_dir, Config),
+ erl_ddll:start(),
case erl_ddll:load_driver(DataDir, "busy_drv") of
ok -> ok;
{error, Error} ->
- io:format("~s\n", [erl_ddll:format_error(Error)]),
- ?line ?t:fail()
+ ct:fail(erl_ddll:format_error(Error))
end.
%%% Interface functions.
start_busy_driver(Config) when is_list(Config) ->
- ?line Pid = spawn_link(?MODULE, init, [Config, self()]),
- ?line receive
+ Pid = spawn_link(?MODULE, init, [Config, self()]),
+ receive
{Pid, started} ->
ok;
Other ->
- test_server:fail({unexpected_message, Other})
+ ct:fail({unexpected_message, Other})
end.
unlock_slave() ->
command(unlock).
get_slave() ->
- ?line command(get_slave).
+ command(get_slave).
%% Internal functions.
command(Msg) ->
- ?line whereis(busy_drv_server) ! {self(), Msg},
- ?line receive
- {busy_drv_reply, Reply} ->
- Reply
+ whereis(busy_drv_server) ! {self(), Msg},
+ receive
+ {busy_drv_reply, Reply} ->
+ Reply
end.
%%% Server.
diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl
index 064404a038..4ec18aa49e 100644
--- a/erts/emulator/test/call_trace_SUITE.erl
+++ b/erts/emulator/test/call_trace_SUITE.erl
@@ -21,66 +21,46 @@
-module(call_trace_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2,
- hipe/1,process_specs/1,basic/1,flags/1,errors/1,pam/1,change_pam/1,
- return_trace/1,exception_trace/1,on_load/1,deep_exception/1,
- upgrade/1,
- exception_nocatch/1,bit_syntax/1]).
+-export([all/0, suite/0,
+ init_per_testcase/2,end_per_testcase/2,
+ hipe/1,process_specs/1,basic/1,flags/1,errors/1,pam/1,change_pam/1,
+ return_trace/1,exception_trace/1,on_load/1,deep_exception/1,
+ upgrade/1,
+ exception_nocatch/1,bit_syntax/1]).
%% Helper functions.
-export([bar/0,foo/0,foo/1,foo/2,expect/1,worker_foo/1,pam_foo/2,nasty/0,
- id/1,deep/3,deep_1/3,deep_2/2,deep_3/2,deep_4/1,deep_5/1,
- bs_sum_a/2,bs_sum_b/2]).
+ id/1,deep/3,deep_1/3,deep_2/2,deep_3/2,deep_4/1,deep_5/1,
+ bs_sum_a/2,bs_sum_b/2]).
%% Debug
-export([abbr/1,abbr/2]).
-
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(P, 20).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {seconds, 30}}].
all() ->
Common = [errors, on_load],
NotHipe = [process_specs, basic, flags, pam, change_pam,
- upgrade,
- return_trace, exception_trace, deep_exception,
- exception_nocatch, bit_syntax],
+ upgrade,
+ return_trace, exception_trace, deep_exception,
+ exception_nocatch, bit_syntax],
Hipe = [hipe],
case test_server:is_native(call_trace_SUITE) of
- true -> Hipe ++ Common;
- false -> NotHipe ++ Common
+ true -> Hipe ++ Common;
+ false -> NotHipe ++ Common
end.
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog = ?t:timetrap(?t:seconds(30)),
- [{watchdog, Dog}|Config].
+ Config.
end_per_testcase(_Func, Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
-
%% Reloading the module will clear all trace patterns, and
%% in a debug-compiled emulator run assertions of the counters
%% for the number of traced exported functions in this module.
@@ -88,51 +68,49 @@ end_per_testcase(_Func, Config) ->
c:l(?MODULE).
hipe(Config) when is_list(Config) ->
- ?line 0 = erlang:trace_pattern({?MODULE,worker_foo,1}, true),
- ?line 0 = erlang:trace_pattern({?MODULE,worker_foo,1}, true, [local]),
- ?line AllFuncs = erlang:trace_pattern({'_','_','_'}, true),
+ 0 = erlang:trace_pattern({?MODULE,worker_foo,1}, true),
+ 0 = erlang:trace_pattern({?MODULE,worker_foo,1}, true, [local]),
+ AllFuncs = erlang:trace_pattern({'_','_','_'}, true),
%% Make sure that a traced, exported function can still be found.
- ?line true = erlang:function_exported(error_handler, undefined_function, 3),
- ?line AllFuncs = erlang:trace_pattern({'_','_','_'}, false),
+ true = erlang:function_exported(error_handler, undefined_function, 3),
+ AllFuncs = erlang:trace_pattern({'_','_','_'}, false),
ok.
-process_specs(doc) ->
- "Tests 'all', 'new', and 'existing' for specifying processes.";
-process_specs(suite) -> [];
+%% Tests 'all', 'new', and 'existing' for specifying processes.
process_specs(Config) when is_list(Config) ->
- ?line Tracer = start_tracer(),
- ?line {flags,[call]} = trace_info(self(), flags),
- ?line {tracer,Tracer} = trace_info(self(), tracer),
- ?line trace_func({?MODULE,worker_foo,1}, []),
+ Tracer = start_tracer(),
+ {flags,[call]} = trace_info(self(), flags),
+ {tracer,Tracer} = trace_info(self(), tracer),
+ trace_func({?MODULE,worker_foo,1}, []),
%% Test the 'new' flag.
- ?line {Work1A,Work1B} = start_and_trace(new, [1,2,3], A1B={3,2,1}),
+ {Work1A,Work1B} = start_and_trace(new, [1,2,3], A1B={3,2,1}),
{flags,[]} = trace_info(Work1A, flags),
{tracer,[]} = trace_info(Work1A, tracer),
{tracer,Tracer} = trace_info(Work1B, tracer),
{flags,[call]} = trace_info(Work1B, flags),
- ?line expect({trace,Work1B,call,{?MODULE,worker_foo,[A1B]}}),
- ?line unlink(Work1B),
- ?line Mref = erlang:monitor(process, Work1B),
- ?line exit(Work1B, kill),
+ expect({trace,Work1B,call,{?MODULE,worker_foo,[A1B]}}),
+ unlink(Work1B),
+ Mref = erlang:monitor(process, Work1B),
+ exit(Work1B, kill),
receive
- {'DOWN',Mref,_,_,_} -> ok
+ {'DOWN',Mref,_,_,_} -> ok
end,
- ?line undefined = trace_info(Work1B, flags),
- ?line {flags,[]} = trace_info(new, flags),
- ?line {tracer,[]} = trace_info(new, tracer),
+ undefined = trace_info(Work1B, flags),
+ {flags,[]} = trace_info(new, flags),
+ {tracer,[]} = trace_info(new, tracer),
%% Test the 'existing' flag.
- ?line {Work2A,_Work2B} = start_and_trace(existing, A2A=[5,6,7], [7,6,5]),
- ?line expect({trace,Work2A,call,{?MODULE,worker_foo,[A2A]}}),
+ {Work2A,_Work2B} = start_and_trace(existing, A2A=[5,6,7], [7,6,5]),
+ expect({trace,Work2A,call,{?MODULE,worker_foo,[A2A]}}),
%% Test the 'all' flag.
- ?line {Work3A,Work3B} = start_and_trace(all, A3A=[12,13], A3B=[13,12]),
- ?line expect({trace,Work3A,call,{?MODULE,worker_foo,[A3A]}}),
- ?line expect({trace,Work3B,call,{?MODULE,worker_foo,[A3B]}}),
-
+ {Work3A,Work3B} = start_and_trace(all, A3A=[12,13], A3B=[13,12]),
+ expect({trace,Work3A,call,{?MODULE,worker_foo,[A3A]}}),
+ expect({trace,Work3B,call,{?MODULE,worker_foo,[A3B]}}),
+
ok.
start_and_trace(Flag, A1, A2) ->
@@ -142,33 +120,33 @@ start_and_trace(Flag, A1, A2) ->
call_worker(W1, A1),
call_worker(W2, A2),
case Flag of
- new ->
- {flags,[call]} = trace_info(new, flags),
- {tracer,_} = trace_info(new, tracer);
- _Other ->
- ok
+ new ->
+ {flags,[call]} = trace_info(new, flags),
+ {tracer,_} = trace_info(new, tracer);
+ _Other ->
+ ok
end,
trace_pid(Flag, false, [call]),
{W1,W2}.
start_worker() ->
- ?line spawn(fun worker_loop/0).
+ spawn(fun worker_loop/0).
call_worker(Pid, Arg) ->
Pid ! {self(),{call,Arg}},
receive
- {result,Res} -> Res
+ {result,Res} -> Res
after 5000 ->
- ?line ?t:fail(no_answer_from_worker)
+ ct:fail(no_answer_from_worker)
end.
worker_loop() ->
receive
- {From,{call,Arg}} ->
- From ! {result,?MODULE:worker_foo(Arg)},
- worker_loop();
- Other ->
- exit({unexpected_message,Other})
+ {From,{call,Arg}} ->
+ From ! {result,?MODULE:worker_foo(Arg)},
+ worker_loop();
+ Other ->
+ exit({unexpected_message,Other})
end.
worker_foo(_Arg) ->
@@ -177,98 +155,98 @@ worker_foo(_Arg) ->
%% Basic test of the call tracing (we trace one process).
basic(_Config) ->
case test_server:is_native(lists) of
- true -> {skip,"lists is native"};
- false -> basic()
+ true -> {skip,"lists is native"};
+ false -> basic()
end.
basic() ->
- ?line start_tracer(),
- ?line trace_info(self(), flags),
- ?line trace_info(self(), tracer),
- ?line 0 = trace_func({?MODULE,no_such_function,0}, []),
- ?line {traced,undefined} =
- trace_info({?MODULE,no_such_function,0}, traced),
- ?line {match_spec, undefined} =
- trace_info({?MODULE,no_such_function,0}, match_spec),
+ start_tracer(),
+ trace_info(self(), flags),
+ trace_info(self(), tracer),
+ 0 = trace_func({?MODULE,no_such_function,0}, []),
+ {traced,undefined} =
+ trace_info({?MODULE,no_such_function,0}, traced),
+ {match_spec, undefined} =
+ trace_info({?MODULE,no_such_function,0}, match_spec),
%% Trace some functions...
- ?line trace_func({lists,'_','_'}, []),
+ trace_func({lists,'_','_'}, []),
%% Make sure that tracing the same functions more than once
%% does not cause any problems.
- ?line 3 = trace_func({?MODULE,foo,'_'}, true),
- ?line 3 = trace_func({?MODULE,foo,'_'}, true),
- ?line 1 = trace_func({?MODULE,bar,0}, true),
- ?line 1 = trace_func({?MODULE,bar,0}, true),
- ?line {traced,global} = trace_info({?MODULE,bar,0}, traced),
- ?line 1 = trace_func({erlang,list_to_integer,1}, true),
- ?line {traced,global} = trace_info({erlang,list_to_integer,1}, traced),
+ 3 = trace_func({?MODULE,foo,'_'}, true),
+ 3 = trace_func({?MODULE,foo,'_'}, true),
+ 1 = trace_func({?MODULE,bar,0}, true),
+ 1 = trace_func({?MODULE,bar,0}, true),
+ {traced,global} = trace_info({?MODULE,bar,0}, traced),
+ 1 = trace_func({erlang,list_to_integer,1}, true),
+ {traced,global} = trace_info({erlang,list_to_integer,1}, traced),
%% ... and call them...
- ?line AList = [x,y,z],
- ?line true = lists:member(y, AList),
- ?line foo0 = ?MODULE:foo(),
- ?line 4 = ?MODULE:foo(3),
- ?line 11 = ?MODULE:foo(7, 4),
- ?line ok = ?MODULE:bar(),
- ?line 42 = list_to_integer(non_literal("42")),
+ AList = [x,y,z],
+ true = lists:member(y, AList),
+ foo0 = ?MODULE:foo(),
+ 4 = ?MODULE:foo(3),
+ 11 = ?MODULE:foo(7, 4),
+ ok = ?MODULE:bar(),
+ 42 = list_to_integer(non_literal("42")),
%% ... make sure the we got trace messages (but not for ?MODULE:expect/1).
- ?line Self = self(),
- ?line ?MODULE:expect({trace,Self,call,{lists,member,[y,AList]}}),
- ?line ?MODULE:expect({trace,Self,call,{?MODULE,foo,[]}}),
- ?line ?MODULE:expect({trace,Self,call,{?MODULE,foo,[3]}}),
- ?line ?MODULE:expect({trace,Self,call,{?MODULE,foo,[7,4]}}),
- ?line ?MODULE:expect({trace,Self,call,{?MODULE,bar,[]}}),
- ?line ?MODULE:expect({trace,Self,call,{erlang,list_to_integer,["42"]}}),
+ Self = self(),
+ ?MODULE:expect({trace,Self,call,{lists,member,[y,AList]}}),
+ ?MODULE:expect({trace,Self,call,{?MODULE,foo,[]}}),
+ ?MODULE:expect({trace,Self,call,{?MODULE,foo,[3]}}),
+ ?MODULE:expect({trace,Self,call,{?MODULE,foo,[7,4]}}),
+ ?MODULE:expect({trace,Self,call,{?MODULE,bar,[]}}),
+ ?MODULE:expect({trace,Self,call,{erlang,list_to_integer,["42"]}}),
%% Turn off trace for this module and call functions...
- ?line trace_func({?MODULE,'_','_'}, false),
- ?line {traced,false} = trace_info({?MODULE,bar,0}, traced),
- ?line foo0 = ?MODULE:foo(),
- ?line 4 = ?MODULE:foo(3),
- ?line 11 = ?MODULE:foo(7, 4),
- ?line ok = ?MODULE:bar(),
- ?line [1,2,3,4,5,6,7,8,9,10] = lists:seq(1, 10),
- ?line 777 = list_to_integer(non_literal("777")),
+ trace_func({?MODULE,'_','_'}, false),
+ {traced,false} = trace_info({?MODULE,bar,0}, traced),
+ foo0 = ?MODULE:foo(),
+ 4 = ?MODULE:foo(3),
+ 11 = ?MODULE:foo(7, 4),
+ ok = ?MODULE:bar(),
+ [1,2,3,4,5,6,7,8,9,10] = lists:seq(1, 10),
+ 777 = list_to_integer(non_literal("777")),
%% ... turn on all trace messages...
- ?line trace_func({'_','_','_'}, false),
- ?line [b,a] = lists:reverse([a,b]),
+ trace_func({'_','_','_'}, false),
+ [b,a] = lists:reverse([a,b]),
%% Read out the remaing trace messages.
- ?line ?MODULE:expect({trace,Self,call,{lists,seq,[1,10]}}),
- ?line ?MODULE:expect({trace,Self,call,{erlang,list_to_integer,["777"]}}),
+ ?MODULE:expect({trace,Self,call,{lists,seq,[1,10]}}),
+ ?MODULE:expect({trace,Self,call,{erlang,list_to_integer,["777"]}}),
receive
- Any ->
- ?line ?t:fail({unexpected_message,Any})
+ Any ->
+ ct:fail({unexpected_message,Any})
after 1 ->
- ok
+ ok
end,
%% Turn on and then off tracing on all external functions.
%% This might cause the emulator to crasch later if it doesn't
%% restore all export entries properly.
- ?line AllFuncs = trace_func({'_','_','_'}, true),
+ AllFuncs = trace_func({'_','_','_'}, true),
io:format("AllFuncs = ~p", [AllFuncs]),
%% Make sure that a traced, exported function can still be found.
- ?line true = erlang:function_exported(error_handler, undefined_function, 3),
- ?line AllFuncs = trace_func({'_','_','_'}, false),
- ?line erlang:trace_delivered(all),
+ true = erlang:function_exported(error_handler, undefined_function, 3),
+ AllFuncs = trace_func({'_','_','_'}, false),
+ erlang:trace_delivered(all),
receive
- {trace_delivered,_,_} -> ok
+ {trace_delivered,_,_} -> ok
end,
c:flush(), % Print the traces messages.
c:flush(), % Print the traces messages.
- ?line {traced,false} = trace_info({erlang,list_to_integer,1}, traced),
+ {traced,false} = trace_info({erlang,list_to_integer,1}, traced),
ok.
@@ -287,8 +265,8 @@ foo(X, Y) -> X+Y.
%% This test case was written to verify that we do not change
%% any behaviour with the introduction of "block-free" upgrade in R16.
%% In short: Do not refer to this test case as an authority of how it must work.
-upgrade(doc) ->
- "Test tracing on module being upgraded";
+
+%% Test tracing on module being upgraded
upgrade(Config) when is_list(Config) ->
V1 = compile_version(my_upgrade_test, 1, Config),
V2 = compile_version(my_upgrade_test, 2, Config),
@@ -304,8 +282,8 @@ upgrade_do(V1, V2, TraceLocalVersion) ->
trace_func({my_upgrade_test,'_','_'}, [], [global]),
case TraceLocalVersion of
- true -> trace_func({my_upgrade_test,local_version,0}, [], [local]);
- _ -> ok
+ true -> trace_func({my_upgrade_test,local_version,0}, [], [local]);
+ _ -> ok
end,
1 = my_upgrade_test:version(),
1 = my_upgrade_test:do_local(),
@@ -320,15 +298,15 @@ upgrade_do(V1, V2, TraceLocalVersion) ->
expect({trace,Self,call,{my_upgrade_test,do_local,[]}}),
expect({trace,Self,call,{my_upgrade_test,do_real_local,[]}}),
case TraceLocalVersion of
- true -> expect({trace,Self,call,{my_upgrade_test,local_version,[]}});
- _ -> ok
+ true -> expect({trace,Self,call,{my_upgrade_test,local_version,[]}});
+ _ -> ok
end,
expect({trace,Self,call,{my_upgrade_test,make_fun_exp,[]}}),
expect({trace,Self,call,{my_upgrade_test,make_fun_local,[]}}),
expect({trace,Self,call,{my_upgrade_test,version,[]}}), % F1_exp
case TraceLocalVersion of
- true -> expect({trace,Self,call,{my_upgrade_test,local_version,[]}}); % F1_loc
- _ -> ok
+ true -> expect({trace,Self,call,{my_upgrade_test,local_version,[]}}); % F1_loc
+ _ -> ok
end,
{module,my_upgrade_test} = erlang:load_module(my_upgrade_test, V2),
@@ -350,8 +328,8 @@ upgrade_do(V1, V2, TraceLocalVersion) ->
trace_func({my_upgrade_test,'_','_'}, [], [global]),
case TraceLocalVersion of
- true -> trace_func({my_upgrade_test,local_version,0}, [], [local]);
- _ -> ok
+ true -> trace_func({my_upgrade_test,local_version,0}, [], [local]);
+ _ -> ok
end,
2 = my_upgrade_test:version(),
2 = my_upgrade_test:do_local(),
@@ -363,13 +341,13 @@ upgrade_do(V1, V2, TraceLocalVersion) ->
expect({trace,Self,call,{my_upgrade_test,do_local,[]}}),
expect({trace,Self,call,{my_upgrade_test,do_real_local,[]}}),
case TraceLocalVersion of
- true -> expect({trace,Self,call,{my_upgrade_test,local_version,[]}});
- _ -> ok
+ true -> expect({trace,Self,call,{my_upgrade_test,local_version,[]}});
+ _ -> ok
end,
expect({trace,Self,call,{my_upgrade_test,version,[]}}), % F2_exp
case TraceLocalVersion of
- true -> expect({trace,Self,call,{my_upgrade_test,local_version,[]}}); % F2_loc
- _ -> ok
+ true -> expect({trace,Self,call,{my_upgrade_test,local_version,[]}}); % F2_loc
+ _ -> ok
end,
true = erlang:delete_module(my_upgrade_test),
@@ -385,10 +363,10 @@ upgrade_do(V1, V2, TraceLocalVersion) ->
ok.
compile_version(Module, Version, Config) ->
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
File = filename:join(Data, atom_to_list(Module)),
{ok,Module,Bin} = compile:file(File, [{d,'VERSION',Version},
- binary,report]),
+ binary,report]),
Bin.
@@ -397,162 +375,157 @@ compile_version(Module, Version, Config) ->
%% Also, test the '{tracer,Pid}' option.
flags(_Config) ->
case test_server:is_native(filename) of
- true -> {skip,"filename is native"};
- false -> flags()
+ true -> {skip,"filename is native"};
+ false -> flags()
end.
flags() ->
- ?line Tracer = start_tracer_loop(),
- ?line trace_pid(self(), true, [call,{tracer,Tracer}]),
+ Tracer = start_tracer_loop(),
+ trace_pid(self(), true, [call,{tracer,Tracer}]),
%% Trace some functions...
- ?line trace_func({filename,'_','_'}, true),
+ trace_func({filename,'_','_'}, true),
%% ... and call them...
- ?line Self = self(),
- ?line filename:absname("nisse"),
- ?line ?MODULE:expect({trace,Self,call,{filename,absname,["nisse"]}}),
- ?line trace_pid(Self, true, [call,arity]),
- ?line filename:absname("kalle"),
- ?line filename:absname("kalle", "/root"),
- ?line ?MODULE:expect({trace,Self,call,{filename,absname,1}}),
- ?line ?MODULE:expect({trace,Self,call,{filename,absname,2}}),
- ?line trace_info(Self, flags),
+ Self = self(),
+ filename:absname("nisse"),
+ ?MODULE:expect({trace,Self,call,{filename,absname,["nisse"]}}),
+ trace_pid(Self, true, [call,arity]),
+ filename:absname("kalle"),
+ filename:absname("kalle", "/root"),
+ ?MODULE:expect({trace,Self,call,{filename,absname,1}}),
+ ?MODULE:expect({trace,Self,call,{filename,absname,2}}),
+ trace_info(Self, flags),
%% Timestamp + arity.
flag_test(fun() ->
- ?line trace_pid(Self, true, [timestamp]),
- ?line "dum" = filename:basename("/abcd/dum"),
- ?line Ts = expect({trace_ts,Self,call,{filename,basename,1},ts}),
- ?line trace_info(Self, flags),
- Ts
- end),
+ trace_pid(Self, true, [timestamp]),
+ "dum" = filename:basename("/abcd/dum"),
+ Ts = expect({trace_ts,Self,call,{filename,basename,1},ts}),
+ trace_info(Self, flags),
+ Ts
+ end),
%% Timestamp.
- ?line AnArg = "/abcd/hejsan",
+ AnArg = "/abcd/hejsan",
flag_test(fun() ->
- ?line trace_pid(Self, false, [arity]),
- ?line "hejsan" = filename:basename(AnArg),
- ?line Ts = expect({trace_ts,Self,call,
- {filename,basename,[AnArg]},ts}),
- ?line trace_info(Self, flags),
- Ts
- end),
+ trace_pid(Self, false, [arity]),
+ "hejsan" = filename:basename(AnArg),
+ Ts = expect({trace_ts,Self,call,
+ {filename,basename,[AnArg]},ts}),
+ trace_info(Self, flags),
+ Ts
+ end),
%% All flags turned off.
- ?line trace_pid(Self, false, [timestamp]),
- ?line AnotherArg = filename:join(AnArg, "hoppsan"),
- ?line "hoppsan" = filename:basename(AnotherArg),
- ?line expect({trace,Self,call,{filename,join,[AnArg,"hoppsan"]}}),
- ?line expect({trace,Self,call,{filename,basename,[AnotherArg]}}),
- ?line trace_info(Self, flags),
-
+ trace_pid(Self, false, [timestamp]),
+ AnotherArg = filename:join(AnArg, "hoppsan"),
+ "hoppsan" = filename:basename(AnotherArg),
+ expect({trace,Self,call,{filename,join,[AnArg,"hoppsan"]}}),
+ expect({trace,Self,call,{filename,basename,[AnotherArg]}}),
+ trace_info(Self, flags),
+
ok.
flag_test(Test) ->
Now = now(),
Ts = Test(),
case timer:now_diff(Ts, Now) of
- Time when Time < 5*1000000 ->
- %% Reasonable short time.
- ok;
- _Diff ->
- %% Too large difference.
- io:format("Now = ~p\n", [Now]),
- io:format("Ts = ~p\n", [Ts]),
- ?line ?t:fail()
+ Time when Time < 5*1000000 ->
+ %% Reasonable short time.
+ ok;
+ _Diff ->
+ %% Too large difference.
+ ct:fail("Now = ~p, Ts = ~p", [Now, Ts])
end,
flag_test_cpu_timestamp(Test).
flag_test_cpu_timestamp(Test) ->
try erlang:trace(all, true, [cpu_timestamp]) of
- _ ->
- io:format("CPU timestamps"),
- Ts = Test(),
- erlang:trace(all, false, [cpu_timestamp]),
- Origin = {0,0,0},
- Hour = 3600*1000000,
- case timer:now_diff(Ts, Origin) of
- Diff when Diff < 4*Hour ->
- %% In the worst case, CPU timestamps count from when this
- %% Erlang emulator was started. The above test is a conservative
- %% test that all CPU timestamps should pass.
- ok;
- _Time ->
- io:format("Strange CPU timestamp: ~p", [Ts]),
- ?line ?t:fail()
- end,
- io:format("Turned off CPU timestamps")
+ _ ->
+ io:format("CPU timestamps"),
+ Ts = Test(),
+ erlang:trace(all, false, [cpu_timestamp]),
+ Origin = {0,0,0},
+ Hour = 3600*1000000,
+ case timer:now_diff(Ts, Origin) of
+ Diff when Diff < 4*Hour ->
+ %% In the worst case, CPU timestamps count from when this
+ %% Erlang emulator was started. The above test is a conservative
+ %% test that all CPU timestamps should pass.
+ ok;
+ _Time ->
+ ct:fail("Strange CPU timestamp: ~p", [Ts])
+ end,
+ io:format("Turned off CPU timestamps")
catch
- error:badarg -> ok
+ error:badarg -> ok
end.
-errors(doc) -> "Test bad arguments for trace/3 and trace_pattern/3.";
-errors(suite) -> [];
+%% Test bad arguments for trace/3 and trace_pattern/3.
errors(Config) when is_list(Config) ->
- ?line expect_badarg_pid(aaa, true, []),
- ?line expect_badarg_pid({pid,dum}, false, []),
- ?line expect_badarg_func({'_','_',1}, []),
- ?line expect_badarg_func({'_',gosh,1}, []),
- ?line expect_badarg_func({xxx,'_',2}, []),
- ?line expect_badarg_func({xxx,yyy,b}, glurp),
+ expect_badarg_pid(aaa, true, []),
+ expect_badarg_pid({pid,dum}, false, []),
+ expect_badarg_func({'_','_',1}, []),
+ expect_badarg_func({'_',gosh,1}, []),
+ expect_badarg_func({xxx,'_',2}, []),
+ expect_badarg_func({xxx,yyy,b}, glurp),
ok.
expect_badarg_pid(What, How, Flags) ->
case catch erlang:trace(What, How, Flags) of
- {'EXIT',{badarg,Where}} ->
- io:format("trace(~p, ~p, ~p) ->\n {'EXIT',{badarg,~p}}",
- [What,How,Flags,Where]),
- ok;
- Other ->
- io:format("trace(~p, ~p, ~p) -> ~p",
- [What,How,Flags,Other]),
- ?t:fail({unexpected,Other})
+ {'EXIT',{badarg,Where}} ->
+ io:format("trace(~p, ~p, ~p) ->\n {'EXIT',{badarg,~p}}",
+ [What,How,Flags,Where]),
+ ok;
+ Other ->
+ io:format("trace(~p, ~p, ~p) -> ~p",
+ [What,How,Flags,Other]),
+ ct:fail({unexpected,Other})
end.
expect_badarg_func(MFA, Pattern) ->
case catch erlang:trace_pattern(MFA, Pattern) of
- {'EXIT',{badarg,Where}} ->
- io:format("trace_pattern(~p, ~p) ->\n {'EXIT',{badarg,~p}}",
- [MFA,Pattern,Where]),
- ok;
- Other ->
- io:format("trace_pattern(~p, ~p) -> ~p",
- [MFA, Pattern, Other]),
- ?t:fail({unexpected,Other})
+ {'EXIT',{badarg,Where}} ->
+ io:format("trace_pattern(~p, ~p) ->\n {'EXIT',{badarg,~p}}",
+ [MFA,Pattern,Where]),
+ ok;
+ Other ->
+ io:format("trace_pattern(~p, ~p) -> ~p",
+ [MFA, Pattern, Other]),
+ ct:fail({unexpected,Other})
end.
-pam(doc) -> "Basic test of PAM.";
-pam(suite) -> [];
+%% Basic test of PAM.
pam(Config) when is_list(Config) ->
- ?line start_tracer(),
- ?line Self = self(),
+ start_tracer(),
+ Self = self(),
%% Build the match program.
- ?line Prog1 = {[{a,tuple},'$1'],[],[]},
- ?line Prog2 = {[{a,bigger,tuple},'$1'],[],[{message,'$1'}]},
- ?line MatchProg = [Prog1,Prog2],
- ?line pam_trace(MatchProg),
+ Prog1 = {[{a,tuple},'$1'],[],[]},
+ Prog2 = {[{a,bigger,tuple},'$1'],[],[{message,'$1'}]},
+ MatchProg = [Prog1,Prog2],
+ pam_trace(MatchProg),
%% Do some calls.
- ?line ?MODULE:pam_foo(not_a_tuple, [a,b]),
- ?line ?MODULE:pam_foo({a,tuple}, [a,list]),
- ?line ?MODULE:pam_foo([this,one,will,'not',match], dummy_arg),
- ?line LongList = lists:seq(1,10),
- ?line ?MODULE:pam_foo({a,bigger,tuple}, LongList),
+ ?MODULE:pam_foo(not_a_tuple, [a,b]),
+ ?MODULE:pam_foo({a,tuple}, [a,list]),
+ ?MODULE:pam_foo([this,one,will,'not',match], dummy_arg),
+ LongList = lists:seq(1,10),
+ ?MODULE:pam_foo({a,bigger,tuple}, LongList),
%% Check that we get the correct trace messages.
- ?line expect({trace,Self,call,{?MODULE,pam_foo,[{a,tuple},[a,list]]}}),
- ?line expect({trace,Self,call,
- {?MODULE,pam_foo,[{a,bigger,tuple},LongList]},
- LongList}),
+ expect({trace,Self,call,{?MODULE,pam_foo,[{a,tuple},[a,list]]}}),
+ expect({trace,Self,call,
+ {?MODULE,pam_foo,[{a,bigger,tuple},LongList]},
+ LongList}),
- ?line trace_func({?MODULE,pam_foo,'_'}, false),
+ trace_func({?MODULE,pam_foo,'_'}, false),
ok.
pam_trace(Prog) ->
@@ -567,38 +540,38 @@ pam_foo(A, B) ->
%% Test changing PAM programs for a function.
change_pam(_Config) ->
case test_server:is_native(lists) of
- true -> {skip,"lists is native"};
- false -> change_pam()
+ true -> {skip,"lists is native"};
+ false -> change_pam()
end.
change_pam() ->
- ?line start_tracer(),
- ?line Self = self(),
+ start_tracer(),
+ Self = self(),
%% Install the first match program.
%% Test using timestamp at the same time.
- ?line trace_pid(Self, true, [call,arity,timestamp]),
- ?line Prog1 = [{['$1','$2'],[],[{message,'$1'}]}],
- ?line change_pam_trace(Prog1),
- ?line [x,y] = lists:append(id([x]), id([y])),
- ?line {heap_size,_} = erlang:process_info(Self, heap_size),
- ?line expect({trace_ts,Self,call,{lists,append,2},[x],ts}),
- ?line expect({trace_ts,Self,call,{erlang,process_info,2},Self,ts}),
+ trace_pid(Self, true, [call,arity,timestamp]),
+ Prog1 = [{['$1','$2'],[],[{message,'$1'}]}],
+ change_pam_trace(Prog1),
+ [x,y] = lists:append(id([x]), id([y])),
+ {heap_size,_} = erlang:process_info(Self, heap_size),
+ expect({trace_ts,Self,call,{lists,append,2},[x],ts}),
+ expect({trace_ts,Self,call,{erlang,process_info,2},Self,ts}),
%% Install a new PAM program.
- ?line Prog2 = [{['$1','$2'],[],[{message,'$2'}]}],
- ?line change_pam_trace(Prog2),
- ?line [xx,yy] = lists:append(id([xx]), id([yy])),
- ?line {current_function,_} = erlang:process_info(Self, current_function),
- ?line expect({trace_ts,Self,call,{lists,append,2},[yy],ts}),
- ?line expect({trace_ts,Self,call,{erlang,process_info,2},current_function,ts}),
+ Prog2 = [{['$1','$2'],[],[{message,'$2'}]}],
+ change_pam_trace(Prog2),
+ [xx,yy] = lists:append(id([xx]), id([yy])),
+ {current_function,_} = erlang:process_info(Self, current_function),
+ expect({trace_ts,Self,call,{lists,append,2},[yy],ts}),
+ expect({trace_ts,Self,call,{erlang,process_info,2},current_function,ts}),
- ?line 1 = trace_func({lists,append,2}, false),
- ?line 1 = trace_func({erlang,process_info,2}, false),
- ?line {match_spec,false} = trace_info({lists,append,2}, match_spec),
- ?line {match_spec,false} = trace_info({erlang,process_info,2}, match_spec),
+ 1 = trace_func({lists,append,2}, false),
+ 1 = trace_func({erlang,process_info,2}, false),
+ {match_spec,false} = trace_info({lists,append,2}, match_spec),
+ {match_spec,false} = trace_info({erlang,process_info,2}, match_spec),
ok.
@@ -611,71 +584,71 @@ change_pam_trace(Prog) ->
return_trace(_Config) ->
case test_server:is_native(lists) of
- true -> {skip,"lists is native"};
- false -> return_trace()
+ true -> {skip,"lists is native"};
+ false -> return_trace()
end.
return_trace() ->
X = {save,me},
- ?line start_tracer(),
- ?line Self = self(),
+ start_tracer(),
+ Self = self(),
%% Test call and return trace and timestamp.
- ?line trace_pid(Self, true, [call,timestamp]),
+ trace_pid(Self, true, [call,timestamp]),
Stupid = {pointless,tuple},
- ?line Prog1 = [{['$1','$2'],[],[{return_trace},{message,{Stupid}}]}],
- ?line 1 = trace_func({lists,append,2}, Prog1),
- ?line 1 = trace_func({erlang,process_info,2}, Prog1),
- ?line {match_spec,Prog1} = trace_info({lists,append,2}, match_spec),
- ?line {match_spec,Prog1} = trace_info({erlang,process_info,2}, match_spec),
+ Prog1 = [{['$1','$2'],[],[{return_trace},{message,{Stupid}}]}],
+ 1 = trace_func({lists,append,2}, Prog1),
+ 1 = trace_func({erlang,process_info,2}, Prog1),
+ {match_spec,Prog1} = trace_info({lists,append,2}, match_spec),
+ {match_spec,Prog1} = trace_info({erlang,process_info,2}, match_spec),
- ?line [x,y] = lists:append(id([x]), id([y])),
+ [x,y] = lists:append(id([x]), id([y])),
Current = {current_function,{?MODULE,return_trace,0}},
- ?line Current = erlang:process_info(Self, current_function),
- ?line expect({trace_ts,Self,call,{lists,append,[[x],[y]]},Stupid,ts}),
- ?line expect({trace_ts,Self,return_from,{lists,append,2},[x,y],ts}),
- ?line expect({trace_ts,Self,call,{erlang,process_info,[Self,current_function]},
- Stupid,ts}),
- ?line expect({trace_ts,Self,return_from,{erlang,process_info,2},Current,ts}),
+ Current = erlang:process_info(Self, current_function),
+ expect({trace_ts,Self,call,{lists,append,[[x],[y]]},Stupid,ts}),
+ expect({trace_ts,Self,return_from,{lists,append,2},[x,y],ts}),
+ expect({trace_ts,Self,call,{erlang,process_info,[Self,current_function]},
+ Stupid,ts}),
+ expect({trace_ts,Self,return_from,{erlang,process_info,2},Current,ts}),
%% Try catch/exit.
- ?line 1 = trace_func({?MODULE,nasty,0}, [{[],[],[{return_trace},{message,false}]}]),
- ?line {'EXIT',good_bye} = (catch ?MODULE:nasty()),
- ?line 1 = trace_func({?MODULE,nasty,0}, false),
+ 1 = trace_func({?MODULE,nasty,0}, [{[],[],[{return_trace},{message,false}]}]),
+ {'EXIT',good_bye} = (catch ?MODULE:nasty()),
+ 1 = trace_func({?MODULE,nasty,0}, false),
%% Turn off trace.
- ?line 1 = trace_func({lists,append,2}, false),
- ?line 1 = trace_func({erlang,process_info,2}, false),
- ?line {match_spec,false} = trace_info({lists,append,2}, match_spec),
- ?line {match_spec,false} = trace_info({erlang,process_info,2}, match_spec),
+ 1 = trace_func({lists,append,2}, false),
+ 1 = trace_func({erlang,process_info,2}, false),
+ {match_spec,false} = trace_info({lists,append,2}, match_spec),
+ {match_spec,false} = trace_info({erlang,process_info,2}, match_spec),
%% No timestamp, no trace message for call.
- ?line trace_pid(Self, false, [timestamp]),
- ?line Prog2 = [{['$1','$2'],[],[{return_trace},{message,false}]},
- {['$1'],[],[{return_trace},{message,false}]}],
- ?line 1 = trace_func({lists,seq,2}, Prog2),
- ?line 1 = trace_func({erlang,atom_to_list,1}, Prog2),
- ?line {match_spec,Prog2} = trace_info({lists,seq,2}, match_spec),
- ?line {match_spec,Prog2} = trace_info({erlang,atom_to_list,1}, match_spec),
+ trace_pid(Self, false, [timestamp]),
+ Prog2 = [{['$1','$2'],[],[{return_trace},{message,false}]},
+ {['$1'],[],[{return_trace},{message,false}]}],
+ 1 = trace_func({lists,seq,2}, Prog2),
+ 1 = trace_func({erlang,atom_to_list,1}, Prog2),
+ {match_spec,Prog2} = trace_info({lists,seq,2}, match_spec),
+ {match_spec,Prog2} = trace_info({erlang,atom_to_list,1}, match_spec),
- ?line lists:seq(2, 7),
- ?line _ = atom_to_list(non_literal(nisse)),
- ?line expect({trace,Self,return_from,{lists,seq,2},[2,3,4,5,6,7]}),
- ?line expect({trace,Self,return_from,{erlang,atom_to_list,1},"nisse"}),
+ lists:seq(2, 7),
+ _ = atom_to_list(non_literal(nisse)),
+ expect({trace,Self,return_from,{lists,seq,2},[2,3,4,5,6,7]}),
+ expect({trace,Self,return_from,{erlang,atom_to_list,1},"nisse"}),
%% Turn off trace.
- ?line 1 = trace_func({lists,seq,2}, false),
- ?line 1 = trace_func({erlang,atom_to_list,1}, false),
- ?line {match_spec,false} = trace_info({lists,seq,2}, match_spec),
- ?line {match_spec,false} = trace_info({erlang,atom_to_list,1}, match_spec),
+ 1 = trace_func({lists,seq,2}, false),
+ 1 = trace_func({erlang,atom_to_list,1}, false),
+ {match_spec,false} = trace_info({lists,seq,2}, match_spec),
+ {match_spec,false} = trace_info({erlang,atom_to_list,1}, match_spec),
+
+ {save,me} = X,
- ?line {save,me} = X,
-
ok.
nasty() ->
@@ -683,396 +656,393 @@ nasty() ->
exception_trace(_Config) ->
case test_server:is_native(lists) of
- true -> {skip,"lists is native"};
- false -> exception_trace()
+ true -> {skip,"lists is native"};
+ false -> exception_trace()
end.
exception_trace() ->
X = {save,me},
- ?line start_tracer(),
- ?line Self = self(),
+ start_tracer(),
+ Self = self(),
%% Test call and return trace and timestamp.
- ?line trace_pid(Self, true, [call,timestamp]),
+ trace_pid(Self, true, [call,timestamp]),
Stupid = {pointless,tuple},
- ?line Prog1 = [{['$1','$2'],[],[{exception_trace},{message,{Stupid}}]}],
- ?line 1 = trace_func({lists,append,2}, Prog1),
- ?line 1 = trace_func({erlang,process_info,2}, Prog1),
- ?line {match_spec,Prog1} = trace_info({lists,append,2}, match_spec),
- ?line {match_spec,Prog1} =
- trace_info({erlang,process_info,2}, match_spec),
-
- ?line [x,y] = lists:append(id([x]), id([y])),
+ Prog1 = [{['$1','$2'],[],[{exception_trace},{message,{Stupid}}]}],
+ 1 = trace_func({lists,append,2}, Prog1),
+ 1 = trace_func({erlang,process_info,2}, Prog1),
+ {match_spec,Prog1} = trace_info({lists,append,2}, match_spec),
+ {match_spec,Prog1} =
+ trace_info({erlang,process_info,2}, match_spec),
+
+ [x,y] = lists:append(id([x]), id([y])),
Current = {current_function,{?MODULE,exception_trace,0}},
- ?line Current = erlang:process_info(Self, current_function),
- ?line expect({trace_ts,Self,call,{lists,append,[[x],[y]]},Stupid,ts}),
- ?line expect({trace_ts,Self,return_from,{lists,append,2},[x,y],ts}),
- ?line expect({trace_ts,Self,call,{erlang,process_info,
- [Self,current_function]},
- Stupid,ts}),
- ?line expect({trace_ts,Self,return_from,
- {erlang,process_info,2},Current,ts}),
+ Current = erlang:process_info(Self, current_function),
+ expect({trace_ts,Self,call,{lists,append,[[x],[y]]},Stupid,ts}),
+ expect({trace_ts,Self,return_from,{lists,append,2},[x,y],ts}),
+ expect({trace_ts,Self,call,{erlang,process_info,
+ [Self,current_function]},
+ Stupid,ts}),
+ expect({trace_ts,Self,return_from,
+ {erlang,process_info,2},Current,ts}),
%% Try catch/exit.
- ?line 1 = trace_func({?MODULE,nasty,0},
- [{[],[],[{exception_trace},{message,false}]}]),
- ?line {'EXIT',good_bye} = (catch ?MODULE:nasty()),
- ?line expect({trace_ts,Self,exception_from,
- {?MODULE,nasty,0},{exit,good_bye},ts}),
- ?line 1 = trace_func({?MODULE,nasty,0}, false),
+ 1 = trace_func({?MODULE,nasty,0},
+ [{[],[],[{exception_trace},{message,false}]}]),
+ {'EXIT',good_bye} = (catch ?MODULE:nasty()),
+ expect({trace_ts,Self,exception_from,
+ {?MODULE,nasty,0},{exit,good_bye},ts}),
+ 1 = trace_func({?MODULE,nasty,0}, false),
%% Turn off trace.
- ?line 1 = trace_func({lists,append,2}, false),
- ?line 1 = trace_func({erlang,process_info,2}, false),
- ?line {match_spec,false} = trace_info({lists,append,2}, match_spec),
- ?line {match_spec,false} =
- trace_info({erlang,process_info,2}, match_spec),
+ 1 = trace_func({lists,append,2}, false),
+ 1 = trace_func({erlang,process_info,2}, false),
+ {match_spec,false} = trace_info({lists,append,2}, match_spec),
+ {match_spec,false} =
+ trace_info({erlang,process_info,2}, match_spec),
%% No timestamp, no trace message for call.
- ?line trace_pid(Self, false, [timestamp]),
- ?line Prog2 = [{['$1','$2'],[],[{exception_trace},{message,false}]},
- {['$1'],[],[{exception_trace},{message,false}]}],
- ?line 1 = trace_func({lists,seq,2}, Prog2),
- ?line 1 = trace_func({erlang,atom_to_list,1}, Prog2),
- ?line {match_spec,Prog2} = trace_info({lists,seq,2}, match_spec),
- ?line {match_spec,Prog2} =
- trace_info({erlang,atom_to_list,1}, match_spec),
+ trace_pid(Self, false, [timestamp]),
+ Prog2 = [{['$1','$2'],[],[{exception_trace},{message,false}]},
+ {['$1'],[],[{exception_trace},{message,false}]}],
+ 1 = trace_func({lists,seq,2}, Prog2),
+ 1 = trace_func({erlang,atom_to_list,1}, Prog2),
+ {match_spec,Prog2} = trace_info({lists,seq,2}, match_spec),
+ {match_spec,Prog2} =
+ trace_info({erlang,atom_to_list,1}, match_spec),
- ?line lists:seq(2, 7),
- ?line _ = atom_to_list(non_literal(nisse)),
- ?line expect({trace,Self,return_from,{lists,seq,2},[2,3,4,5,6,7]}),
- ?line expect({trace,Self,return_from,{erlang,atom_to_list,1},"nisse"}),
+ lists:seq(2, 7),
+ _ = atom_to_list(non_literal(nisse)),
+ expect({trace,Self,return_from,{lists,seq,2},[2,3,4,5,6,7]}),
+ expect({trace,Self,return_from,{erlang,atom_to_list,1},"nisse"}),
%% Turn off trace.
- ?line 1 = trace_func({lists,seq,2}, false),
- ?line 1 = trace_func({erlang,atom_to_list,1}, false),
- ?line {match_spec,false} = trace_info({lists,seq,2}, match_spec),
- ?line {match_spec,false} =
- trace_info({erlang,atom_to_list,1}, match_spec),
+ 1 = trace_func({lists,seq,2}, false),
+ 1 = trace_func({erlang,atom_to_list,1}, false),
+ {match_spec,false} = trace_info({lists,seq,2}, match_spec),
+ {match_spec,false} =
+ trace_info({erlang,atom_to_list,1}, match_spec),
- ?line expect(),
- ?line {save,me} = X,
+ expect(),
+ {save,me} = X,
ok.
-on_load(doc) -> "Test the on_load argument for trace_pattern/3.";
-on_load(suite) -> [];
+%% Test the on_load argument for trace_pattern/3.
on_load(Config) when is_list(Config) ->
- ?line 0 = erlang:trace_pattern(on_load, []),
- ?line {traced,global} = erlang:trace_info(on_load, traced),
- ?line {match_spec,[]} = erlang:trace_info(on_load, match_spec),
+ 0 = erlang:trace_pattern(on_load, []),
+ {traced,global} = erlang:trace_info(on_load, traced),
+ {match_spec,[]} = erlang:trace_info(on_load, match_spec),
- ?line 0 = erlang:trace_pattern(on_load, true, [local]),
- ?line {traced,local} = erlang:trace_info(on_load, traced),
- ?line {match_spec,[]} = erlang:trace_info(on_load, match_spec),
+ 0 = erlang:trace_pattern(on_load, true, [local]),
+ {traced,local} = erlang:trace_info(on_load, traced),
+ {match_spec,[]} = erlang:trace_info(on_load, match_spec),
- ?line 0 = erlang:trace_pattern(on_load, false, [local]),
- ?line {traced,false} = erlang:trace_info(on_load, traced),
- ?line {match_spec,false} = erlang:trace_info(on_load, match_spec),
+ 0 = erlang:trace_pattern(on_load, false, [local]),
+ {traced,false} = erlang:trace_info(on_load, traced),
+ {match_spec,false} = erlang:trace_info(on_load, match_spec),
- ?line Pam1 = [{[],[],[{message,false}]}],
- ?line 0 = erlang:trace_pattern(on_load, Pam1),
- ?line {traced,global} = erlang:trace_info(on_load, traced),
- ?line {match_spec,Pam1} = erlang:trace_info(on_load, match_spec),
+ Pam1 = [{[],[],[{message,false}]}],
+ 0 = erlang:trace_pattern(on_load, Pam1),
+ {traced,global} = erlang:trace_info(on_load, traced),
+ {match_spec,Pam1} = erlang:trace_info(on_load, match_spec),
- ?line 0 = erlang:trace_pattern(on_load, true, [local]),
- ?line 0 = erlang:trace_pattern(on_load, false, [local]),
+ 0 = erlang:trace_pattern(on_load, true, [local]),
+ 0 = erlang:trace_pattern(on_load, false, [local]),
ok.
-deep_exception(doc) -> "Test the new exception trace.";
-deep_exception(suite) -> [];
+%% Test the new exception trace.
deep_exception(Config) when is_list(Config) ->
deep_exception().
deep_exception() ->
- ?line start_tracer(),
- ?line Self = self(),
- ?line N = 200000,
- ?line LongImproperList = seq(1, N-1, N),
-
+ start_tracer(),
+ Self = self(),
+ N = 200000,
+ LongImproperList = seq(1, N-1, N),
+
Prog = [{'_',[],[{exception_trace}]}],
-%% ?line 1 = trace_pid(Self, true, [call]),
- ?line 1 = trace_func({?MODULE,deep,'_'}, Prog),
- ?line 1 = trace_func({?MODULE,deep_1,'_'}, Prog),
- ?line 1 = trace_func({?MODULE,deep_2,'_'}, Prog),
- ?line 1 = trace_func({?MODULE,deep_3,'_'}, Prog),
- ?line 1 = trace_func({?MODULE,deep_4,'_'}, Prog),
- ?line 1 = trace_func({?MODULE,deep_5,'_'}, Prog),
- ?line 1 = trace_func({?MODULE,id,'_'}, Prog),
- ?line 1 = trace_func({erlang,'++','_'}, Prog),
- ?line 1 = trace_func({erlang,exit,1}, Prog),
- ?line 1 = trace_func({erlang,throw,1}, Prog),
- ?line 2 = trace_func({erlang,error,'_'}, Prog),
- ?line 1 = trace_func({lists,reverse,2}, Prog),
-
- ?line deep_exception(?LINE, exit, [paprika], 1,
- [{trace,Self,call,{erlang,exit,[paprika]}},
- {trace,Self,exception_from,{erlang,exit,1},
- {exit,paprika}}],
- exception_from, {exit,paprika}),
- ?line deep_exception(?LINE, throw, [3.14], 2,
- [{trace,Self,call,{erlang,throw,[3.14]}},
- {trace,Self,exception_from,{erlang,throw,1},
- {throw,3.14}}],
- exception_from, {throw,3.14}),
- ?line deep_exception(?LINE, error, [{paprika}], 3,
- [{trace,Self,call,{erlang,error,[{paprika}]}},
- {trace,Self,exception_from,{erlang,error,1},
- {error,{paprika}}}],
- exception_from, {error,{paprika}}),
- ?line deep_exception(?LINE, error, ["{paprika}",[]], 3,
- [{trace,Self,call,{erlang,error,["{paprika}",[]]}},
- {trace,Self,exception_from,{erlang,error,2},
- {error,"{paprika}"}}],
- exception_from, {error,"{paprika}"}),
- ?line deep_exception(?LINE, id, [broccoli], 4, [],
- return_from, broccoli),
- ?line deep_exception(
- ?LINE, append, [1,2], 5,
- [{trace,Self,call,{erlang,'++',[1,2]}},
- {trace,Self,exception_from,{erlang,'++',2},{error,badarg}}],
- exception_from, {error,badarg}),
- ?line deep_exception(?LINE, '=', [1,2], 6, [],
- exception_from, {error,{badmatch,2}}),
+ %% 1 = trace_pid(Self, true, [call]),
+ 1 = trace_func({?MODULE,deep,'_'}, Prog),
+ 1 = trace_func({?MODULE,deep_1,'_'}, Prog),
+ 1 = trace_func({?MODULE,deep_2,'_'}, Prog),
+ 1 = trace_func({?MODULE,deep_3,'_'}, Prog),
+ 1 = trace_func({?MODULE,deep_4,'_'}, Prog),
+ 1 = trace_func({?MODULE,deep_5,'_'}, Prog),
+ 1 = trace_func({?MODULE,id,'_'}, Prog),
+ 1 = trace_func({erlang,'++','_'}, Prog),
+ 1 = trace_func({erlang,exit,1}, Prog),
+ 1 = trace_func({erlang,throw,1}, Prog),
+ 2 = trace_func({erlang,error,'_'}, Prog),
+ 1 = trace_func({lists,reverse,2}, Prog),
+
+ deep_exception(?LINE, exit, [paprika], 1,
+ [{trace,Self,call,{erlang,exit,[paprika]}},
+ {trace,Self,exception_from,{erlang,exit,1},
+ {exit,paprika}}],
+ exception_from, {exit,paprika}),
+ deep_exception(?LINE, throw, [3.14], 2,
+ [{trace,Self,call,{erlang,throw,[3.14]}},
+ {trace,Self,exception_from,{erlang,throw,1},
+ {throw,3.14}}],
+ exception_from, {throw,3.14}),
+ deep_exception(?LINE, error, [{paprika}], 3,
+ [{trace,Self,call,{erlang,error,[{paprika}]}},
+ {trace,Self,exception_from,{erlang,error,1},
+ {error,{paprika}}}],
+ exception_from, {error,{paprika}}),
+ deep_exception(?LINE, error, ["{paprika}",[]], 3,
+ [{trace,Self,call,{erlang,error,["{paprika}",[]]}},
+ {trace,Self,exception_from,{erlang,error,2},
+ {error,"{paprika}"}}],
+ exception_from, {error,"{paprika}"}),
+ deep_exception(?LINE, id, [broccoli], 4, [],
+ return_from, broccoli),
+ deep_exception(
+ ?LINE, append, [1,2], 5,
+ [{trace,Self,call,{erlang,'++',[1,2]}},
+ {trace,Self,exception_from,{erlang,'++',2},{error,badarg}}],
+ exception_from, {error,badarg}),
+ deep_exception(?LINE, '=', [1,2], 6, [],
+ exception_from, {error,{badmatch,2}}),
%%
- ?line io:format("== Subtest: ~w", [?LINE]),
- ?line try lists:reverse(LongImproperList, []) of
- R1 -> test_server:fail({returned,abbr(R1)})
- catch error:badarg -> ok
- end,
- ?line expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}})
- when is_list(L1), is_list(L2), S == Self ->
- next;
- ({trace,S,exception_from,
- {lists,reverse,2},{error,badarg}})
- when S == Self ->
- expected;
- ('_') ->
- {trace,Self,exception_from,
- {lists,reverse,2},{error,badarg}};
- (_) ->
- {unexpected,
- {trace,Self,exception_from,
- {lists,reverse,2},{error,badarg}}}
- end),
- ?line deep_exception(?LINE, deep_5, [1,2], 7,
- [{trace,Self,call,{erlang,error,[undef]}},
- {trace,Self,exception_from,{erlang,error,1},
- {error,undef}}],
- exception_from, {error,undef}),
- ?line deep_exception(?LINE, deep_5, [undef], 8,
- [{trace,Self,call,{?MODULE,deep_5,[undef]}},
- {trace,Self,exception_from,{?MODULE,deep_5,1},
- {error,function_clause}}],
- exception_from, {error,function_clause}),
-
+ io:format("== Subtest: ~w", [?LINE]),
+ try lists:reverse(LongImproperList, []) of
+ R1 -> ct:fail({returned,abbr(R1)})
+ catch error:badarg -> ok
+ end,
+ expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}})
+ when is_list(L1), is_list(L2), S == Self ->
+ next;
+ ({trace,S,exception_from,
+ {lists,reverse,2},{error,badarg}})
+ when S == Self ->
+ expected;
+ ('_') ->
+ {trace,Self,exception_from,
+ {lists,reverse,2},{error,badarg}};
+ (_) ->
+ {unexpected,
+ {trace,Self,exception_from,
+ {lists,reverse,2},{error,badarg}}}
+ end),
+ deep_exception(?LINE, deep_5, [1,2], 7,
+ [{trace,Self,call,{erlang,error,[undef]}},
+ {trace,Self,exception_from,{erlang,error,1},
+ {error,undef}}],
+ exception_from, {error,undef}),
+ deep_exception(?LINE, deep_5, [undef], 8,
+ [{trace,Self,call,{?MODULE,deep_5,[undef]}},
+ {trace,Self,exception_from,{?MODULE,deep_5,1},
+ {error,function_clause}}],
+ exception_from, {error,function_clause}),
+
%% Apply
%%
- ?line deep_exception(?LINE, apply, [erlang,error,[[mo|rot]]], 1,
- [{trace,Self,call,{erlang,error,[[mo|rot]]}},
- {trace,Self,exception_from,{erlang,error,1},
- {error,[mo|rot]}}],
- exception_from, {error,[mo|rot]}),
- ?line deep_exception(?LINE, apply, [erlang,error,[[mo|"rot"],[]]], 1,
- [{trace,Self,call,{erlang,error,[[mo|"rot"],[]]}},
- {trace,Self,exception_from,{erlang,error,2},
- {error,[mo|"rot"]}}],
- exception_from, {error,[mo|"rot"]}),
- ?line Morot = make_ref(),
- ?line deep_exception(?LINE, apply, [erlang,throw,[Morot]], 3,
- [{trace,Self,call,{erlang,throw,[Morot]}},
- {trace,Self,exception_from,{erlang,throw,1},
- {throw,Morot}}],
- exception_from, {throw,Morot}),
- ?line deep_exception(?LINE, apply, [erlang,exit,[["morot"|Morot]]], 2,
- [{trace,Self,call,{erlang,exit,[["morot"|Morot]]}},
- {trace,Self,exception_from,{erlang,exit,1},
- {exit,["morot"|Morot]}}],
- exception_from, {exit,["morot"|Morot]}),
- ?line deep_exception(
- ?LINE, apply, [?MODULE,id,[spenat]], 4,
- [{trace,Self,call,{?MODULE,id,[spenat]}},
- {trace,Self,return_from,{?MODULE,id,1},spenat}],
- return_from, spenat),
- ?line deep_exception(
- ?LINE, apply, [erlang,'++',[1,2]], 5,
- [{trace,Self,call,{erlang,'++',[1,2]}},
- {trace,Self,exception_from,{erlang,'++',2},{error,badarg}}],
- exception_from, {error,badarg}),
- ?line io:format("== Subtest: ~w", [?LINE]),
- ?line try apply(lists, reverse, [LongImproperList, []]) of
- R2 -> test_server:fail({returned,abbr(R2)})
- catch error:badarg -> ok
- end,
- ?line expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}})
- when is_list(L1), is_list(L2), S == Self ->
- next;
- ({trace,S,exception_from,
- {lists,reverse,2},{error,badarg}})
- when S == Self ->
- expected;
- ('_') ->
- {trace,Self,exception_from,
- {lists,reverse,2},{error,badarg}};
- (_) ->
- {unexpected,
- {trace,Self,exception_from,
- {lists,reverse,2},{error,badarg}}}
- end),
- ?line deep_exception(?LINE, apply, [?MODULE,deep_5,[1,2]], 7,
- [{trace,Self,call,{erlang,error,[undef]}},
- {trace,Self,exception_from,{erlang,error,1},
- {error,undef}}],
- exception_from, {error,undef}),
- ?line deep_exception(?LINE, apply, [?MODULE,deep_5,[undef]], 8,
- [{trace,Self,call,{?MODULE,deep_5,[undef]}},
- {trace,Self,exception_from,{?MODULE,deep_5,1},
- {error,function_clause}}],
- exception_from, {error,function_clause}),
+ deep_exception(?LINE, apply, [erlang,error,[[mo|rot]]], 1,
+ [{trace,Self,call,{erlang,error,[[mo|rot]]}},
+ {trace,Self,exception_from,{erlang,error,1},
+ {error,[mo|rot]}}],
+ exception_from, {error,[mo|rot]}),
+ deep_exception(?LINE, apply, [erlang,error,[[mo|"rot"],[]]], 1,
+ [{trace,Self,call,{erlang,error,[[mo|"rot"],[]]}},
+ {trace,Self,exception_from,{erlang,error,2},
+ {error,[mo|"rot"]}}],
+ exception_from, {error,[mo|"rot"]}),
+ Morot = make_ref(),
+ deep_exception(?LINE, apply, [erlang,throw,[Morot]], 3,
+ [{trace,Self,call,{erlang,throw,[Morot]}},
+ {trace,Self,exception_from,{erlang,throw,1},
+ {throw,Morot}}],
+ exception_from, {throw,Morot}),
+ deep_exception(?LINE, apply, [erlang,exit,[["morot"|Morot]]], 2,
+ [{trace,Self,call,{erlang,exit,[["morot"|Morot]]}},
+ {trace,Self,exception_from,{erlang,exit,1},
+ {exit,["morot"|Morot]}}],
+ exception_from, {exit,["morot"|Morot]}),
+ deep_exception(
+ ?LINE, apply, [?MODULE,id,[spenat]], 4,
+ [{trace,Self,call,{?MODULE,id,[spenat]}},
+ {trace,Self,return_from,{?MODULE,id,1},spenat}],
+ return_from, spenat),
+ deep_exception(
+ ?LINE, apply, [erlang,'++',[1,2]], 5,
+ [{trace,Self,call,{erlang,'++',[1,2]}},
+ {trace,Self,exception_from,{erlang,'++',2},{error,badarg}}],
+ exception_from, {error,badarg}),
+ io:format("== Subtest: ~w", [?LINE]),
+ try apply(lists, reverse, [LongImproperList, []]) of
+ R2 -> ct:fail({returned,abbr(R2)})
+ catch error:badarg -> ok
+ end,
+ expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}})
+ when is_list(L1), is_list(L2), S == Self ->
+ next;
+ ({trace,S,exception_from,
+ {lists,reverse,2},{error,badarg}})
+ when S == Self ->
+ expected;
+ ('_') ->
+ {trace,Self,exception_from,
+ {lists,reverse,2},{error,badarg}};
+ (_) ->
+ {unexpected,
+ {trace,Self,exception_from,
+ {lists,reverse,2},{error,badarg}}}
+ end),
+ deep_exception(?LINE, apply, [?MODULE,deep_5,[1,2]], 7,
+ [{trace,Self,call,{erlang,error,[undef]}},
+ {trace,Self,exception_from,{erlang,error,1},
+ {error,undef}}],
+ exception_from, {error,undef}),
+ deep_exception(?LINE, apply, [?MODULE,deep_5,[undef]], 8,
+ [{trace,Self,call,{?MODULE,deep_5,[undef]}},
+ {trace,Self,exception_from,{?MODULE,deep_5,1},
+ {error,function_clause}}],
+ exception_from, {error,function_clause}),
%% Apply of fun
%%
- ?line deep_exception(?LINE, apply,
- [fun () ->
- erlang:error([{"palsternacka",3.14},17])
- end, []], 1,
- [{trace,Self,call,
- {erlang,error,[[{"palsternacka",3.14},17]]}},
- {trace,Self,exception_from,{erlang,error,1},
- {error,[{"palsternacka",3.14},17]}}],
- exception_from, {error,[{"palsternacka",3.14},17]}),
- ?line deep_exception(?LINE, apply,
- [fun () ->
- erlang:error(["palsternacka",17], [])
- end, []], 1,
- [{trace,Self,call,
- {erlang,error,[["palsternacka",17],[]]}},
- {trace,Self,exception_from,{erlang,error,2},
- {error,["palsternacka",17]}}],
- exception_from, {error,["palsternacka",17]}),
- ?line deep_exception(?LINE, apply,
- [fun () -> erlang:throw(Self) end, []], 2,
- [{trace,Self,call,{erlang,throw,[Self]}},
- {trace,Self,exception_from,{erlang,throw,1},
- {throw,Self}}],
- exception_from, {throw,Self}),
- ?line deep_exception(?LINE, apply,
- [fun () ->
- erlang:exit({1,2,3,4,[5,palsternacka]})
- end, []], 3,
- [{trace,Self,call,
- {erlang,exit,[{1,2,3,4,[5,palsternacka]}]}},
- {trace,Self,exception_from,{erlang,exit,1},
- {exit,{1,2,3,4,[5,palsternacka]}}}],
- exception_from, {exit,{1,2,3,4,[5,palsternacka]}}),
- ?line deep_exception(?LINE, apply,
- [fun () -> ?MODULE:id(bladsallad) end, []], 4,
- [{trace,Self,call,{?MODULE,id,[bladsallad]}},
- {trace,Self,return_from,{?MODULE,id,1},bladsallad}],
- return_from, bladsallad),
- ?line deep_exception(?LINE, apply,
- [fun (A, B) -> A ++ B end, [1,2]], 5,
- [{trace,Self,call,{erlang,'++',[1,2]}},
- {trace,Self,exception_from,
- {erlang,'++',2},{error,badarg}}],
- exception_from, {error,badarg}),
- ?line deep_exception(?LINE, apply, [fun (A, B) -> A = B end, [1,2]], 6,
- [],
- exception_from, {error,{badmatch,2}}),
- ?line io:format("== Subtest: ~w", [?LINE]),
- ?line try apply(fun() -> lists:reverse(LongImproperList, []) end, []) of
- R3 -> test_server:fail({returned,abbr(R3)})
- catch error:badarg -> ok
- end,
- ?line expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}})
- when is_list(L1), is_list(L2), S == Self ->
- next;
- ({trace,S,exception_from,
- {lists,reverse,2},{error,badarg}})
- when S == Self ->
- expected;
- ('_') ->
- {trace,Self,exception_from,
- {lists,reverse,2},{error,badarg}};
- (_) ->
- {unexpected,
- {trace,Self,exception_from,
- {lists,reverse,2},{error,badarg}}}
- end),
- ?line deep_exception(?LINE, apply,
- [fun () -> ?MODULE:deep_5(1,2) end, []], 7,
- [{trace,Self,call,{erlang,error,[undef]}},
- {trace,Self,exception_from,{erlang,error,1},
- {error,undef}}],
- exception_from, {error,undef}),
- ?line deep_exception(?LINE, apply,
- [fun () -> ?MODULE:deep_5(undef) end, []], 8,
- [{trace,Self,call,{?MODULE,deep_5,[undef]}},
- {trace,Self,exception_from,{?MODULE,deep_5,1},
- {error,function_clause}}],
- exception_from, {error,function_clause}),
-
- ?line trace_func({?MODULE,'_','_'}, false),
- ?line trace_func({erlang,'_','_'}, false),
- ?line trace_func({lists,'_','_'}, false),
- ?line expect(),
- ?line ok.
+ deep_exception(?LINE, apply,
+ [fun () ->
+ erlang:error([{"palsternacka",3.14},17])
+ end, []], 1,
+ [{trace,Self,call,
+ {erlang,error,[[{"palsternacka",3.14},17]]}},
+ {trace,Self,exception_from,{erlang,error,1},
+ {error,[{"palsternacka",3.14},17]}}],
+ exception_from, {error,[{"palsternacka",3.14},17]}),
+ deep_exception(?LINE, apply,
+ [fun () ->
+ erlang:error(["palsternacka",17], [])
+ end, []], 1,
+ [{trace,Self,call,
+ {erlang,error,[["palsternacka",17],[]]}},
+ {trace,Self,exception_from,{erlang,error,2},
+ {error,["palsternacka",17]}}],
+ exception_from, {error,["palsternacka",17]}),
+ deep_exception(?LINE, apply,
+ [fun () -> erlang:throw(Self) end, []], 2,
+ [{trace,Self,call,{erlang,throw,[Self]}},
+ {trace,Self,exception_from,{erlang,throw,1},
+ {throw,Self}}],
+ exception_from, {throw,Self}),
+ deep_exception(?LINE, apply,
+ [fun () ->
+ erlang:exit({1,2,3,4,[5,palsternacka]})
+ end, []], 3,
+ [{trace,Self,call,
+ {erlang,exit,[{1,2,3,4,[5,palsternacka]}]}},
+ {trace,Self,exception_from,{erlang,exit,1},
+ {exit,{1,2,3,4,[5,palsternacka]}}}],
+ exception_from, {exit,{1,2,3,4,[5,palsternacka]}}),
+ deep_exception(?LINE, apply,
+ [fun () -> ?MODULE:id(bladsallad) end, []], 4,
+ [{trace,Self,call,{?MODULE,id,[bladsallad]}},
+ {trace,Self,return_from,{?MODULE,id,1},bladsallad}],
+ return_from, bladsallad),
+ deep_exception(?LINE, apply,
+ [fun (A, B) -> A ++ B end, [1,2]], 5,
+ [{trace,Self,call,{erlang,'++',[1,2]}},
+ {trace,Self,exception_from,
+ {erlang,'++',2},{error,badarg}}],
+ exception_from, {error,badarg}),
+ deep_exception(?LINE, apply, [fun (A, B) -> A = B end, [1,2]], 6,
+ [],
+ exception_from, {error,{badmatch,2}}),
+ io:format("== Subtest: ~w", [?LINE]),
+ try apply(fun() -> lists:reverse(LongImproperList, []) end, []) of
+ R3 -> ct:fail({returned,abbr(R3)})
+ catch error:badarg -> ok
+ end,
+ expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}})
+ when is_list(L1), is_list(L2), S == Self ->
+ next;
+ ({trace,S,exception_from,
+ {lists,reverse,2},{error,badarg}})
+ when S == Self ->
+ expected;
+ ('_') ->
+ {trace,Self,exception_from,
+ {lists,reverse,2},{error,badarg}};
+ (_) ->
+ {unexpected,
+ {trace,Self,exception_from,
+ {lists,reverse,2},{error,badarg}}}
+ end),
+ deep_exception(?LINE, apply,
+ [fun () -> ?MODULE:deep_5(1,2) end, []], 7,
+ [{trace,Self,call,{erlang,error,[undef]}},
+ {trace,Self,exception_from,{erlang,error,1},
+ {error,undef}}],
+ exception_from, {error,undef}),
+ deep_exception(?LINE, apply,
+ [fun () -> ?MODULE:deep_5(undef) end, []], 8,
+ [{trace,Self,call,{?MODULE,deep_5,[undef]}},
+ {trace,Self,exception_from,{?MODULE,deep_5,1},
+ {error,function_clause}}],
+ exception_from, {error,function_clause}),
+
+ trace_func({?MODULE,'_','_'}, false),
+ trace_func({erlang,'_','_'}, false),
+ trace_func({lists,'_','_'}, false),
+ expect(),
+ ok.
deep_exception(Line, B, Q, N, Extra, Tag, R) ->
- ?line Self = self(),
- ?line io:format("== Subtest: ~w", [Line]),
- ?line Result = ?MODULE:deep(N, B, Q),
- ?line Result = deep_expect(Self, B, Q, N, Extra, Tag, R).
+ Self = self(),
+ io:format("== Subtest: ~w", [Line]),
+ Result = ?MODULE:deep(N, B, Q),
+ Result = deep_expect(Self, B, Q, N, Extra, Tag, R).
deep_expect(Self, B, Q, N, Extra, Tag, R) ->
- ?line expect({trace,Self,call,{?MODULE,deep,[N,B,Q]}}),
- ?line Result = deep_expect_N(Self, B, Q, N, Extra, Tag, R),
- ?line expect({trace,Self,return_from,{?MODULE,deep,3},Result}),
- ?line Result.
+ expect({trace,Self,call,{?MODULE,deep,[N,B,Q]}}),
+ Result = deep_expect_N(Self, B, Q, N, Extra, Tag, R),
+ expect({trace,Self,return_from,{?MODULE,deep,3},Result}),
+ Result.
deep_expect_N(Self, B, Q, N, Extra, Tag, R) ->
deep_expect_N(Self, B, Q, N, Extra, Tag, R, N).
deep_expect_N(Self, B, Q, N, Extra, Tag, R, J) when J > 0 ->
- ?line expect({trace,Self,call,{?MODULE,deep_1,[J,B,Q]}}),
- ?line deep_expect_N(Self, B, Q, N, Extra, Tag, R, J-1);
+ expect({trace,Self,call,{?MODULE,deep_1,[J,B,Q]}}),
+ deep_expect_N(Self, B, Q, N, Extra, Tag, R, J-1);
deep_expect_N(Self, B, Q, N, Extra, Tag, R, 0) ->
- ?line expect({trace,Self,call,{?MODULE,deep_2,[B,Q]}}),
- ?line expect({trace,Self,call,{?MODULE,deep_3,[B,Q]}}),
- ?line expect({trace,Self,return_from,{?MODULE,deep_3,2},{B,Q}}),
- ?line expect({trace,Self,call,{?MODULE,deep_4,[{B,Q}]}}),
- ?line expect({trace,Self,call,{?MODULE,id,[{B,Q}]}}),
- ?line expect({trace,Self,return_from,{?MODULE,id,1},{B,Q}}),
- ?line deep_expect_Extra(Self, N, Extra, Tag, R),
- ?line expect({trace,Self,Tag,{?MODULE,deep_4,1},R}),
- ?line expect({trace,Self,Tag,{?MODULE,deep_2,2},R}),
- ?line deep_expect_N(Self, N, Tag, R).
+ expect({trace,Self,call,{?MODULE,deep_2,[B,Q]}}),
+ expect({trace,Self,call,{?MODULE,deep_3,[B,Q]}}),
+ expect({trace,Self,return_from,{?MODULE,deep_3,2},{B,Q}}),
+ expect({trace,Self,call,{?MODULE,deep_4,[{B,Q}]}}),
+ expect({trace,Self,call,{?MODULE,id,[{B,Q}]}}),
+ expect({trace,Self,return_from,{?MODULE,id,1},{B,Q}}),
+ deep_expect_Extra(Self, N, Extra, Tag, R),
+ expect({trace,Self,Tag,{?MODULE,deep_4,1},R}),
+ expect({trace,Self,Tag,{?MODULE,deep_2,2},R}),
+ deep_expect_N(Self, N, Tag, R).
deep_expect_Extra(Self, N, [E|Es], Tag, R) ->
- ?line expect(E),
- ?line deep_expect_Extra(Self, N, Es, Tag, R);
+ expect(E),
+ deep_expect_Extra(Self, N, Es, Tag, R);
deep_expect_Extra(_Self, _N, [], _Tag, _R) ->
- ?line ok.
+ ok.
deep_expect_N(Self, N, Tag, R) when N > 0 ->
- ?line expect({trace,Self,Tag,{?MODULE,deep_1,3},R}),
- ?line deep_expect_N(Self, N-1, Tag, R);
+ expect({trace,Self,Tag,{?MODULE,deep_1,3},R}),
+ deep_expect_N(Self, N-1, Tag, R);
deep_expect_N(_Self, 0, return_from, R) ->
- ?line {value,R};
+ {value,R};
deep_expect_N(_Self, 0, exception_from, R) ->
- ?line R.
+ R.
-exception_nocatch(doc) -> "Test the new exception trace.";
-exception_nocatch(suite) -> [];
+%% Test the new exception trace.
exception_nocatch(Config) when is_list(Config) ->
exception_nocatch().
@@ -1082,78 +1052,78 @@ exception_nocatch() ->
Deep4LocBadmatch = get_deep_4_loc({'=',[a,b]}),
Prog = [{'_',[],[{exception_trace}]}],
- ?line 1 = erlang:trace_pattern({?MODULE,deep_1,'_'}, Prog),
- ?line 1 = erlang:trace_pattern({?MODULE,deep_2,'_'}, Prog),
- ?line 1 = erlang:trace_pattern({?MODULE,deep_3,'_'}, Prog),
- ?line 1 = erlang:trace_pattern({?MODULE,deep_4,'_'}, Prog),
- ?line 1 = erlang:trace_pattern({?MODULE,deep_5,'_'}, Prog),
- ?line 1 = erlang:trace_pattern({?MODULE,id,'_'}, Prog),
- ?line 1 = erlang:trace_pattern({erlang,exit,1}, Prog),
- ?line 1 = erlang:trace_pattern({erlang,throw,1}, Prog),
- ?line 2 = erlang:trace_pattern({erlang,error,'_'}, Prog),
- ?line Q1 = {make_ref(),Prog},
- ?line T1 =
- exception_nocatch(?LINE, exit, [Q1], 3,
- [{trace,t1,call,{erlang,exit,[Q1]}},
- {trace,t1,exception_from,{erlang,exit,1},
- {exit,Q1}}],
- exception_from, {exit,Q1}),
- ?line expect({trace,T1,exit,Q1}),
- ?line Q2 = {cake,14.125},
- ?line T2 =
- exception_nocatch(?LINE, throw, [Q2], 2,
- [{trace,t2,call,{erlang,throw,[Q2]}},
- {trace,t2,exception_from,{erlang,throw,1},
- {error,{nocatch,Q2}}}],
- exception_from, {error,{nocatch,Q2}}),
- ?line expect({trace,T2,exit,{{nocatch,Q2},[{erlang,throw,[Q2],[]},
- {?MODULE,deep_4,1,
- Deep4LocThrow}]}}),
- ?line Q3 = {dump,[dump,{dump}]},
- ?line T3 =
- exception_nocatch(?LINE, error, [Q3], 4,
- [{trace,t3,call,{erlang,error,[Q3]}},
- {trace,t3,exception_from,{erlang,error,1},
- {error,Q3}}],
- exception_from, {error,Q3}),
- ?line expect({trace,T3,exit,{Q3,[{erlang,error,[Q3],[]},
- {?MODULE,deep_4,1,Deep4LocError}]}}),
- ?line T4 =
- exception_nocatch(?LINE, '=', [17,4711], 5, [],
- exception_from, {error,{badmatch,4711}}),
- ?line expect({trace,T4,exit,{{badmatch,4711},
- [{?MODULE,deep_4,1,Deep4LocBadmatch}]}}),
+ 1 = erlang:trace_pattern({?MODULE,deep_1,'_'}, Prog),
+ 1 = erlang:trace_pattern({?MODULE,deep_2,'_'}, Prog),
+ 1 = erlang:trace_pattern({?MODULE,deep_3,'_'}, Prog),
+ 1 = erlang:trace_pattern({?MODULE,deep_4,'_'}, Prog),
+ 1 = erlang:trace_pattern({?MODULE,deep_5,'_'}, Prog),
+ 1 = erlang:trace_pattern({?MODULE,id,'_'}, Prog),
+ 1 = erlang:trace_pattern({erlang,exit,1}, Prog),
+ 1 = erlang:trace_pattern({erlang,throw,1}, Prog),
+ 2 = erlang:trace_pattern({erlang,error,'_'}, Prog),
+ Q1 = {make_ref(),Prog},
+ T1 =
+ exception_nocatch(?LINE, exit, [Q1], 3,
+ [{trace,t1,call,{erlang,exit,[Q1]}},
+ {trace,t1,exception_from,{erlang,exit,1},
+ {exit,Q1}}],
+ exception_from, {exit,Q1}),
+ expect({trace,T1,exit,Q1}),
+ Q2 = {cake,14.125},
+ T2 =
+ exception_nocatch(?LINE, throw, [Q2], 2,
+ [{trace,t2,call,{erlang,throw,[Q2]}},
+ {trace,t2,exception_from,{erlang,throw,1},
+ {error,{nocatch,Q2}}}],
+ exception_from, {error,{nocatch,Q2}}),
+ expect({trace,T2,exit,{{nocatch,Q2},[{erlang,throw,[Q2],[]},
+ {?MODULE,deep_4,1,
+ Deep4LocThrow}]}}),
+ Q3 = {dump,[dump,{dump}]},
+ T3 =
+ exception_nocatch(?LINE, error, [Q3], 4,
+ [{trace,t3,call,{erlang,error,[Q3]}},
+ {trace,t3,exception_from,{erlang,error,1},
+ {error,Q3}}],
+ exception_from, {error,Q3}),
+ expect({trace,T3,exit,{Q3,[{erlang,error,[Q3],[]},
+ {?MODULE,deep_4,1,Deep4LocError}]}}),
+ T4 =
+ exception_nocatch(?LINE, '=', [17,4711], 5, [],
+ exception_from, {error,{badmatch,4711}}),
+ expect({trace,T4,exit,{{badmatch,4711},
+ [{?MODULE,deep_4,1,Deep4LocBadmatch}]}}),
%%
- ?line erlang:trace_pattern({?MODULE,'_','_'}, false),
- ?line erlang:trace_pattern({erlang,'_','_'}, false),
- ?line expect(),
- ?line ok.
+ erlang:trace_pattern({?MODULE,'_','_'}, false),
+ erlang:trace_pattern({erlang,'_','_'}, false),
+ expect(),
+ ok.
get_deep_4_loc(Arg) ->
try
- deep_4(Arg),
- ?t:fail(should_not_return_to_here)
+ deep_4(Arg),
+ ct:fail(should_not_return_to_here)
catch
- _:_ ->
- [{?MODULE,deep_4,1,Loc0}|_] = erlang:get_stacktrace(),
- Loc0
+ _:_ ->
+ [{?MODULE,deep_4,1,Loc0}|_] = erlang:get_stacktrace(),
+ Loc0
end.
exception_nocatch(Line, B, Q, N, Extra, Tag, R) ->
- ?line io:format("== Subtest: ~w", [Line]),
- ?line Go = make_ref(),
- ?line Tracee =
- spawn(fun () ->
- receive
- Go ->
- deep_1(N, B, Q)
- end
- end),
- ?line 1 = erlang:trace(Tracee, true, [call,return_to,procs]),
- ?line Tracee ! Go,
- ?line deep_expect_N(Tracee, B, Q, N-1,
- [setelement(2, T, Tracee) || T <- Extra], Tag, R),
- ?line Tracee.
+ io:format("== Subtest: ~w", [Line]),
+ Go = make_ref(),
+ Tracee =
+ spawn(fun () ->
+ receive
+ Go ->
+ deep_1(N, B, Q)
+ end
+ end),
+ 1 = erlang:trace(Tracee, true, [call,return_to,procs]),
+ Tracee ! Go,
+ deep_expect_N(Tracee, B, Q, N-1,
+ [setelement(2, T, Tracee) || T <- Extra], Tag, R),
+ Tracee.
%% Make sure that code that uses the optimized bit syntax matching
%% can be traced without crashing the emulator. (Actually, it seems
@@ -1161,22 +1131,22 @@ exception_nocatch(Line, B, Q, N, Extra, Tag, R) ->
%% will keep the test case anyway.)
bit_syntax(Config) when is_list(Config) ->
- ?line start_tracer(),
- ?line 1 = trace_func({?MODULE,bs_sum_a,'_'}, []),
- ?line 1 = trace_func({?MODULE,bs_sum_b,'_'}, []),
+ start_tracer(),
+ 1 = trace_func({?MODULE,bs_sum_a,'_'}, []),
+ 1 = trace_func({?MODULE,bs_sum_b,'_'}, []),
- ?line 6 = call_bs_sum_a(<<1,2,3>>),
- ?line 10 = call_bs_sum_b(<<1,2,3,4>>),
+ 6 = call_bs_sum_a(<<1,2,3>>),
+ 10 = call_bs_sum_b(<<1,2,3,4>>),
- ?line trace_func({?MODULE,'_','_'}, false),
- ?line erlang:trace_delivered(all),
+ trace_func({?MODULE,'_','_'}, false),
+ erlang:trace_delivered(all),
receive
- {trace_delivered,_,_} -> ok
+ {trace_delivered,_,_} -> ok
end,
-
+
Self = self(),
- ?line expect({trace,Self,call,{?MODULE,bs_sum_a,[<<2,3>>,1]}}),
- ?line expect({trace,Self,call,{?MODULE,bs_sum_b,[1,<<2,3,4>>]}}),
+ expect({trace,Self,call,{?MODULE,bs_sum_a,[<<2,3>>,1]}}),
+ expect({trace,Self,call,{?MODULE,bs_sum_b,[1,<<2,3,4>>]}}),
ok.
@@ -1191,7 +1161,7 @@ bs_sum_a(<<>>, Acc) -> Acc.
bs_sum_b(Acc, <<H,T/binary>>) -> bs_sum_b(H+Acc, T);
bs_sum_b(Acc, <<>>) -> Acc.
-
+
@@ -1199,98 +1169,98 @@ bs_sum_b(Acc, <<>>) -> Acc.
expect() ->
case flush() of
- [] -> ok;
- Msgs ->
- test_server:fail({unexpected,abbr(Msgs)})
+ [] -> ok;
+ Msgs ->
+ ct:fail({unexpected,abbr(Msgs)})
end.
expect({trace_ts,Pid,Type,MFA,Term,ts}=Message) ->
receive
- M ->
- case M of
- {trace_ts,Pid,Type,MFA,Term,Ts}=MessageTs ->
- ok = io:format("Expected and got ~p", [abbr(MessageTs)]),
- Ts;
- _ ->
- io:format("Expected ~p; got ~p", [abbr(Message),abbr(M)]),
- test_server:fail({unexpected,abbr([M|flush()])})
- end
+ M ->
+ case M of
+ {trace_ts,Pid,Type,MFA,Term,Ts}=MessageTs ->
+ ok = io:format("Expected and got ~p", [abbr(MessageTs)]),
+ Ts;
+ _ ->
+ io:format("Expected ~p; got ~p", [abbr(Message),abbr(M)]),
+ ct:fail({unexpected,abbr([M|flush()])})
+ end
after 5000 ->
- io:format("Expected ~p; got nothing", [abbr(Message)]),
- test_server:fail(no_trace_message)
+ io:format("Expected ~p; got nothing", [abbr(Message)]),
+ ct:fail(no_trace_message)
end;
expect({trace_ts,Pid,Type,MFA,ts}=Message) ->
receive
- M ->
- case M of
- {trace_ts,Pid,Type,MFA,Ts} ->
- ok = io:format("Expected and got ~p", [abbr(M)]),
- Ts;
- _ ->
- io:format("Expected ~p; got ~p", [abbr(Message),abbr(M)]),
- test_server:fail({unexpected,abbr([M|flush()])})
- end
+ M ->
+ case M of
+ {trace_ts,Pid,Type,MFA,Ts} ->
+ ok = io:format("Expected and got ~p", [abbr(M)]),
+ Ts;
+ _ ->
+ io:format("Expected ~p; got ~p", [abbr(Message),abbr(M)]),
+ ct:fail({unexpected,abbr([M|flush()])})
+ end
after 5000 ->
- io:format("Expected ~p; got nothing", [abbr(Message)]),
- test_server:fail(no_trace_message)
+ io:format("Expected ~p; got nothing", [abbr(Message)]),
+ ct:fail(no_trace_message)
end;
expect(Validator) when is_function(Validator) ->
receive
- M ->
- case Validator(M) of
- expected ->
- ok = io:format("Expected and got ~p", [abbr(M)]);
- next ->
- ok = io:format("Expected and got ~p", [abbr(M)]),
- expect(Validator);
- {unexpected,Message} ->
- io:format("Expected ~p; got ~p", [abbr(Message),abbr(M)]),
- test_server:fail({unexpected,abbr([M|flush()])})
- end
+ M ->
+ case Validator(M) of
+ expected ->
+ ok = io:format("Expected and got ~p", [abbr(M)]);
+ next ->
+ ok = io:format("Expected and got ~p", [abbr(M)]),
+ expect(Validator);
+ {unexpected,Message} ->
+ io:format("Expected ~p; got ~p", [abbr(Message),abbr(M)]),
+ ct:fail({unexpected,abbr([M|flush()])})
+ end
after 5000 ->
- io:format("Expected ~p; got nothing", [abbr(Validator('_'))]),
- test_server:fail(no_trace_message)
+ io:format("Expected ~p; got nothing", [abbr(Validator('_'))]),
+ ct:fail(no_trace_message)
end;
expect(Message) ->
receive
- M ->
- case M of
- Message ->
- ok = io:format("Expected and got ~p", [abbr(Message)]);
- Other ->
- io:format("Expected ~p; got ~p",
- [abbr(Message),abbr(Other)]),
- test_server:fail({unexpected,abbr([Other|flush()])})
- end
+ M ->
+ case M of
+ Message ->
+ ok = io:format("Expected and got ~p", [abbr(Message)]);
+ Other ->
+ io:format("Expected ~p; got ~p",
+ [abbr(Message),abbr(Other)]),
+ ct:fail({unexpected,abbr([Other|flush()])})
+ end
after 5000 ->
- io:format("Expected ~p; got nothing", [abbr(Message)]),
- test_server:fail(no_trace_message)
+ io:format("Expected ~p; got nothing", [abbr(Message)]),
+ ct:fail(no_trace_message)
end.
trace_info(What, Key) ->
get(tracer) ! {apply,self(),{erlang,trace_info,[What,Key]}},
Res = receive
- {apply_result,Result} -> Result
- end,
+ {apply_result,Result} -> Result
+ end,
ok = io:format("erlang:trace_info(~p, ~p) -> ~p",
- [What,Key,Res]),
+ [What,Key,Res]),
Res.
-
+
trace_func(MFA, MatchSpec) ->
trace_func(MFA, MatchSpec, []).
trace_func(MFA, MatchSpec, Flags) ->
get(tracer) ! {apply,self(),{erlang,trace_pattern,[MFA, MatchSpec, Flags]}},
Res = receive
- {apply_result,Result} -> Result
- end,
+ {apply_result,Result} -> Result
+ end,
ok = io:format("trace_pattern(~p, ~p, ~p) -> ~p", [MFA,MatchSpec,Flags,Res]),
Res.
trace_pid(Pid, On, Flags) ->
get(tracer) ! {apply,self(),{erlang,trace,[Pid,On,Flags]}},
Res = receive
- {apply_result,Result} -> Result
- end,
+ {apply_result,Result} -> Result
+ end,
ok = io:format("trace(~p, ~p, ~p) -> ~p", [Pid,On,Flags,Res]),
Res.
@@ -1310,19 +1280,19 @@ tracer(RelayTo) ->
tracer_loop(RelayTo) ->
receive
- {apply,From,{M,F,A}} ->
- From ! {apply_result,apply(M, F, A)},
- tracer_loop(RelayTo);
- Msg ->
- RelayTo ! Msg,
- tracer_loop(RelayTo)
+ {apply,From,{M,F,A}} ->
+ From ! {apply_result,apply(M, F, A)},
+ tracer_loop(RelayTo);
+ Msg ->
+ RelayTo ! Msg,
+ tracer_loop(RelayTo)
end.
id(I) -> I.
deep(N, Class, Reason) ->
try ?MODULE:deep_1(N, Class, Reason) of
- Value -> {value,Value}
+ Value -> {value,Value}
catch C:R -> {C,R}
end.
@@ -1339,30 +1309,30 @@ deep_3(Class, Reason) ->
deep_4(CR) ->
case ?MODULE:id(CR) of
- {exit,[Reason]} ->
- erlang:exit(Reason);
- {throw,[Reason]} ->
- erlang:throw(Reason);
- {error,[Reason,Arglist]} ->
- erlang:error(Reason, Arglist);
- {error,[Reason]} ->
- erlang:error(Reason);
- {id,[Reason]} ->
- Reason;
- {reverse,[A,B]} ->
- lists:reverse(A, B);
- {append,[A,B]} ->
- A ++ B;
- {apply,[Fun,Args]} ->
- erlang:apply(Fun, Args);
- {apply,[M,F,Args]} ->
- erlang:apply(M, F, Args);
- {deep_5,[A,B]} ->
- ?MODULE:deep_5(A, B);
- {deep_5,[A]} ->
- ?MODULE:deep_5(A);
- {'=',[A,B]} ->
- A = B
+ {exit,[Reason]} ->
+ erlang:exit(Reason);
+ {throw,[Reason]} ->
+ erlang:throw(Reason);
+ {error,[Reason,Arglist]} ->
+ erlang:error(Reason, Arglist);
+ {error,[Reason]} ->
+ erlang:error(Reason);
+ {id,[Reason]} ->
+ Reason;
+ {reverse,[A,B]} ->
+ lists:reverse(A, B);
+ {append,[A,B]} ->
+ A ++ B;
+ {apply,[Fun,Args]} ->
+ erlang:apply(Fun, Args);
+ {apply,[M,F,Args]} ->
+ erlang:apply(M, F, Args);
+ {deep_5,[A,B]} ->
+ ?MODULE:deep_5(A, B);
+ {deep_5,[A]} ->
+ ?MODULE:deep_5(A);
+ {'=',[A,B]} ->
+ A = B
end.
deep_5(A) when is_integer(A) ->
@@ -1370,9 +1340,9 @@ deep_5(A) when is_integer(A) ->
flush() ->
receive X ->
- [X|flush()]
+ [X|flush()]
after 1000 ->
- []
+ []
end.
%% Abbreviate large complex terms
@@ -1395,10 +1365,10 @@ abbr_tuple(_, _, _, R) ->
%%
abbr_list(_, 0, R) ->
case io_lib:printable_list(R) of
- true ->
- reverse(R, "...");
- false ->
- reverse(R, '...')
+ true ->
+ reverse(R, "...");
+ false ->
+ reverse(R, '...')
end;
abbr_list([H|T], N, R) ->
M = N-1,
diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl
index 9f318a38be..db285a3977 100644
--- a/erts/emulator/test/code_SUITE.erl
+++ b/erts/emulator/test/code_SUITE.erl
@@ -19,17 +19,17 @@
%%
-module(code_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- versions/1,new_binary_types/1,
- t_check_process_code/1,t_check_old_code/1,
- t_check_process_code_ets/1,
- external_fun/1,get_chunk/1,module_md5/1,make_stub/1,
- make_stub_many_funs/1,constant_pools/1,constant_refc_binaries/1,
- false_dependency/1,coverage/1,fun_confusion/1]).
+-export([all/0, suite/0, init_per_suite/1, end_per_suite/1,
+ versions/1,new_binary_types/1,
+ t_check_process_code/1,t_check_old_code/1,
+ t_check_process_code_ets/1,
+ external_fun/1,get_chunk/1,module_md5/1,make_stub/1,
+ make_stub_many_funs/1,constant_pools/1,constant_refc_binaries/1,
+ false_dependency/1,coverage/1,fun_confusion/1,
+ t_copy_literals/1]).
-define(line_trace, 1).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -38,10 +38,7 @@ all() ->
t_check_process_code_ets, t_check_old_code, external_fun, get_chunk,
module_md5, make_stub, make_stub_many_funs,
constant_pools, constant_refc_binaries, false_dependency,
- coverage, fun_confusion].
-
-groups() ->
- [].
+ coverage, fun_confusion, t_copy_literals].
init_per_suite(Config) ->
erts_debug:set_internal_state(available_internal_state, true),
@@ -51,12 +48,6 @@ end_per_suite(_Config) ->
catch erts_debug:set_internal_state(available_internal_state, false),
ok.
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
%% Make sure that only two versions of a module can be loaded.
versions(Config) when is_list(Config) ->
V1 = compile_version(1, Config),
@@ -77,10 +68,10 @@ versions(Config) when is_list(Config) ->
_ = monitor(process, P1),
_ = monitor(process, P2),
receive
- {'DOWN',_,process,P1,normal} -> ok
+ {'DOWN',_,process,P1,normal} -> ok
end,
receive
- {'DOWN',_,process,P2,normal} -> ok
+ {'DOWN',_,process,P2,normal} -> ok
end,
true = erlang:purge_module(versions),
true = erlang:delete_module(versions),
@@ -88,84 +79,84 @@ versions(Config) when is_list(Config) ->
ok.
compile_version(Version, Config) ->
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
File = filename:join(Data, "versions"),
{ok,versions,Bin} = compile:file(File, [{d,'VERSION',Version},
- binary,report]),
+ binary,report]),
Bin.
load_version(Code, Ver) ->
case erlang:load_module(versions, Code) of
- {module,versions} ->
- Pid = spawn_link(versions, loop, []),
- Ver = versions:version(),
- Ver = check_version(Pid),
- {ok,Pid,Ver};
- Error ->
- Error
+ {module,versions} ->
+ Pid = spawn_link(versions, loop, []),
+ Ver = versions:version(),
+ Ver = check_version(Pid),
+ {ok,Pid,Ver};
+ Error ->
+ Error
end.
check_version(Pid) ->
Pid ! {self(),version},
receive
- {Pid,version,Version} ->
- Version
+ {Pid,version,Version} ->
+ Version
end.
new_binary_types(Config) when is_list(Config) ->
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "my_code_test"),
- ?line {ok,my_code_test,Bin} = compile:file(File, [binary]),
- ?line {module,my_code_test} = erlang:load_module(my_code_test,
- make_sub_binary(Bin)),
- ?line true = erlang:delete_module(my_code_test),
- ?line true = erlang:purge_module(my_code_test),
-
- ?line {module,my_code_test} = erlang:load_module(my_code_test,
- make_unaligned_sub_binary(Bin)),
- ?line true = erlang:delete_module(my_code_test),
- ?line true = erlang:purge_module(my_code_test),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "my_code_test"),
+ {ok,my_code_test,Bin} = compile:file(File, [binary]),
+ {module,my_code_test} = erlang:load_module(my_code_test,
+ make_sub_binary(Bin)),
+ true = erlang:delete_module(my_code_test),
+ true = erlang:purge_module(my_code_test),
+
+ {module,my_code_test} = erlang:load_module(my_code_test,
+ make_unaligned_sub_binary(Bin)),
+ true = erlang:delete_module(my_code_test),
+ true = erlang:purge_module(my_code_test),
%% Try heap binaries and bad binaries.
- ?line {error,badfile} = erlang:load_module(my_code_test, <<1,2>>),
- ?line {error,badfile} = erlang:load_module(my_code_test,
- make_sub_binary(<<1,2>>)),
- ?line {error,badfile} = erlang:load_module(my_code_test,
- make_unaligned_sub_binary(<<1,2>>)),
- ?line {'EXIT',{badarg,_}} = (catch erlang:load_module(my_code_test,
- bit_sized_binary(Bin))),
+ {error,badfile} = erlang:load_module(my_code_test, <<1,2>>),
+ {error,badfile} = erlang:load_module(my_code_test,
+ make_sub_binary(<<1,2>>)),
+ {error,badfile} = erlang:load_module(my_code_test,
+ make_unaligned_sub_binary(<<1,2>>)),
+ {'EXIT',{badarg,_}} = (catch erlang:load_module(my_code_test,
+ bit_sized_binary(Bin))),
ok.
t_check_process_code(Config) when is_list(Config) ->
- ?line Priv = ?config(priv_dir, Config),
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "my_code_test"),
- ?line Code = filename:join(Priv, "my_code_test"),
+ Priv = proplists:get_value(priv_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "my_code_test"),
+ Code = filename:join(Priv, "my_code_test"),
- ?line {ok,my_code_test} = c:c(File, [{outdir,Priv}]),
+ {ok,my_code_test} = c:c(File, [{outdir,Priv}]),
- ?line MyFun = fun(X, Y) -> X + Y end, %Confuse things.
- ?line F = my_code_test:make_fun(42),
- ?line 2 = fun_refc(F),
- ?line MyFun2 = fun(X, Y) -> X * Y end, %Confuse things.
- ?line 44 = F(2),
+ MyFun = fun(X, Y) -> X + Y end, %Confuse things.
+ F = my_code_test:make_fun(42),
+ 2 = fun_refc(F),
+ MyFun2 = fun(X, Y) -> X * Y end, %Confuse things.
+ 44 = F(2),
%% Delete the module and call the fun again.
- ?line true = erlang:delete_module(my_code_test),
- ?line 2 = fun_refc(F),
- ?line 45 = F(3),
- ?line {'EXIT',{undef,_}} = (catch my_code_test:make_fun(33)),
+ true = erlang:delete_module(my_code_test),
+ 2 = fun_refc(F),
+ 45 = F(3),
+ {'EXIT',{undef,_}} = (catch my_code_test:make_fun(33)),
%% The fun should still be there, preventing purge.
- ?line true = erlang:check_process_code(self(), my_code_test),
+ true = erlang:check_process_code(self(), my_code_test),
gc(),
gc(), %Place funs on the old heap.
- ?line true = erlang:check_process_code(self(), my_code_test),
+ true = erlang:check_process_code(self(), my_code_test),
%% Using the funs here guarantees that they will not be prematurely garbed.
- ?line 48 = F(6),
- ?line 3 = MyFun(1, 2),
- ?line 12 = MyFun2(3, 4),
+ 48 = F(6),
+ 3 = MyFun(1, 2),
+ 12 = MyFun2(3, 4),
%% Kill all funs.
t_check_process_code1(Code, []).
@@ -173,64 +164,64 @@ t_check_process_code(Config) when is_list(Config) ->
%% The real fun was killed, but we have some fakes which look similar.
t_check_process_code1(Code, Fakes) ->
- ?line MyFun = fun(X, Y) -> X + Y + 1 end, %Confuse things.
- ?line false = erlang:check_process_code(self(), my_code_test),
- ?line 4 = MyFun(1, 2),
+ MyFun = fun(X, Y) -> X + Y + 1 end, %Confuse things.
+ false = erlang:check_process_code(self(), my_code_test),
+ 4 = MyFun(1, 2),
t_check_process_code2(Code, Fakes).
t_check_process_code2(Code, _) ->
- ?line false = erlang:check_process_code(self(), my_code_test),
- ?line true = erlang:purge_module(my_code_test),
+ false = erlang:check_process_code(self(), my_code_test),
+ true = erlang:purge_module(my_code_test),
%% In the next test we will load the same module twice.
- ?line {module,my_code_test} = code:load_abs(Code),
- ?line F = my_code_test:make_fun(37),
- ?line 2 = fun_refc(F),
- ?line false = erlang:check_process_code(self(), my_code_test),
- ?line {module,my_code_test} = code:load_abs(Code),
- ?line 2 = fun_refc(F),
+ {module,my_code_test} = code:load_abs(Code),
+ F = my_code_test:make_fun(37),
+ 2 = fun_refc(F),
+ false = erlang:check_process_code(self(), my_code_test),
+ {module,my_code_test} = code:load_abs(Code),
+ 2 = fun_refc(F),
%% Still false because the fun with the same identify is found
%% in the current code.
- ?line false = erlang:check_process_code(self(), my_code_test),
-
+ false = erlang:check_process_code(self(), my_code_test),
+
%% Some fake funs in the same module should not do any difference.
- ?line false = erlang:check_process_code(self(), my_code_test),
+ false = erlang:check_process_code(self(), my_code_test),
38 = F(1),
t_check_process_code3(Code, F, []).
t_check_process_code3(Code, F, Fakes) ->
Pid = spawn_link(fun() -> body(F, Fakes) end),
- ?line true = erlang:purge_module(my_code_test),
- ?line false = erlang:check_process_code(self(), my_code_test),
- ?line false = erlang:check_process_code(Pid, my_code_test),
+ true = erlang:purge_module(my_code_test),
+ false = erlang:check_process_code(self(), my_code_test),
+ false = erlang:check_process_code(Pid, my_code_test),
- ?line true = erlang:delete_module(my_code_test),
- ?line true = erlang:check_process_code(self(), my_code_test),
- ?line true = erlang:check_process_code(Pid, my_code_test),
+ true = erlang:delete_module(my_code_test),
+ true = erlang:check_process_code(self(), my_code_test),
+ true = erlang:check_process_code(Pid, my_code_test),
39 = F(2),
t_check_process_code4(Code, Pid).
t_check_process_code4(_Code, Pid) ->
Pid ! drop_funs,
receive after 1 -> ok end,
- ?line false = erlang:check_process_code(Pid, my_code_test),
+ false = erlang:check_process_code(Pid, my_code_test),
ok.
body(F, Fakes) ->
receive
- jog ->
- 40 = F(3),
- erlang:garbage_collect(),
- body(F, Fakes);
- drop_funs ->
- dropped_body()
+ jog ->
+ 40 = F(3),
+ erlang:garbage_collect(),
+ body(F, Fakes);
+ drop_funs ->
+ dropped_body()
end.
dropped_body() ->
receive
- X -> exit(X)
+ X -> exit(X)
end.
gc() ->
@@ -238,61 +229,60 @@ gc() ->
gc1().
gc1() -> ok.
-t_check_process_code_ets(doc) ->
- "Test check_process_code/2 in combination with a fun obtained from an ets table.";
+%% Test check_process_code/2 in combination with a fun obtained from an ets table.
t_check_process_code_ets(Config) when is_list(Config) ->
case test_server:is_native(?MODULE) of
- true ->
- {skip,"Native code"};
- false ->
- do_check_process_code_ets(Config)
+ true ->
+ {skip,"Native code"};
+ false ->
+ do_check_process_code_ets(Config)
end.
do_check_process_code_ets(Config) ->
- ?line Priv = ?config(priv_dir, Config),
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "my_code_test"),
-
- ?line erlang:purge_module(my_code_test),
- ?line erlang:delete_module(my_code_test),
- ?line {ok,my_code_test} = c:c(File, [{outdir,Priv}]),
-
- ?line T = ets:new(my_code_test, []),
- ?line ets:insert(T, {7,my_code_test:make_fun(107)}),
- ?line ets:insert(T, {8,my_code_test:make_fun(108)}),
- ?line erlang:delete_module(my_code_test),
- ?line false = erlang:check_process_code(self(), my_code_test),
+ Priv = proplists:get_value(priv_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "my_code_test"),
+
+ erlang:purge_module(my_code_test),
+ erlang:delete_module(my_code_test),
+ {ok,my_code_test} = c:c(File, [{outdir,Priv}]),
+
+ T = ets:new(my_code_test, []),
+ ets:insert(T, {7,my_code_test:make_fun(107)}),
+ ets:insert(T, {8,my_code_test:make_fun(108)}),
+ erlang:delete_module(my_code_test),
+ false = erlang:check_process_code(self(), my_code_test),
Body = fun() ->
- [{7,F1}] = ets:lookup(T, 7),
- [{8,F2}] = ets:lookup(T, 8),
- IdleLoop = fun() -> receive _X -> ok end end,
- RecLoop = fun(Again) ->
- receive
- call -> 110 = F1(3),
- 100 = F2(-8),
- Again(Again);
- {drop_funs,To} ->
- To ! funs_dropped,
- IdleLoop()
- end
- end,
- true = erlang:check_process_code(self(), my_code_test),
- RecLoop(RecLoop)
- end,
- ?line Pid = spawn_link(Body),
+ [{7,F1}] = ets:lookup(T, 7),
+ [{8,F2}] = ets:lookup(T, 8),
+ IdleLoop = fun() -> receive _X -> ok end end,
+ RecLoop = fun(Again) ->
+ receive
+ call -> 110 = F1(3),
+ 100 = F2(-8),
+ Again(Again);
+ {drop_funs,To} ->
+ To ! funs_dropped,
+ IdleLoop()
+ end
+ end,
+ true = erlang:check_process_code(self(), my_code_test),
+ RecLoop(RecLoop)
+ end,
+ Pid = spawn_link(Body),
receive after 1 -> ok end,
- ?line true = erlang:check_process_code(Pid, my_code_test),
+ true = erlang:check_process_code(Pid, my_code_test),
Pid ! call,
Pid ! {drop_funs,self()},
receive
- funs_dropped -> ok;
- Other -> ?t:fail({unexpected,Other})
+ funs_dropped -> ok;
+ Other -> ct:fail({unexpected,Other})
after 10000 ->
- ?line ?t:fail(no_funs_dropped_answer)
+ ct:fail(no_funs_dropped_answer)
end,
- ?line false = erlang:check_process_code(Pid, my_code_test),
+ false = erlang:check_process_code(Pid, my_code_test),
ok.
fun_refc(F) ->
@@ -302,89 +292,89 @@ fun_refc(F) ->
%% Test the erlang:check_old_code/1 BIF.
t_check_old_code(Config) when is_list(Config) ->
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "my_code_test"),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "my_code_test"),
- ?line erlang:purge_module(my_code_test),
- ?line erlang:delete_module(my_code_test),
- ?line catch erlang:purge_module(my_code_test),
+ erlang:purge_module(my_code_test),
+ erlang:delete_module(my_code_test),
+ catch erlang:purge_module(my_code_test),
+
+ false = erlang:check_old_code(my_code_test),
+
+ {ok,my_code_test,Code} = compile:file(File, [binary]),
+ {module,my_code_test} = code:load_binary(my_code_test, File, Code),
- ?line false = erlang:check_old_code(my_code_test),
+ false = erlang:check_old_code(my_code_test),
+ {module,my_code_test} = code:load_binary(my_code_test, File, Code),
+ true = erlang:check_old_code(my_code_test),
- ?line {ok,my_code_test,Code} = compile:file(File, [binary]),
- ?line {module,my_code_test} = code:load_binary(my_code_test, File, Code),
-
- ?line false = erlang:check_old_code(my_code_test),
- ?line {module,my_code_test} = code:load_binary(my_code_test, File, Code),
- ?line true = erlang:check_old_code(my_code_test),
+ true = erlang:purge_module(my_code_test),
+ true = erlang:delete_module(my_code_test),
+ true = erlang:purge_module(my_code_test),
- ?line true = erlang:purge_module(my_code_test),
- ?line true = erlang:delete_module(my_code_test),
- ?line true = erlang:purge_module(my_code_test),
+ {'EXIT',_} = (catch erlang:check_old_code([])),
- ?line {'EXIT',_} = (catch erlang:check_old_code([])),
-
ok.
external_fun(Config) when is_list(Config) ->
- ?line false = erlang:function_exported(another_code_test, x, 1),
+ false = erlang:function_exported(another_code_test, x, 1),
AnotherCodeTest = id(another_code_test),
ExtFun = fun AnotherCodeTest:x/1,
- ?line {'EXIT',{undef,_}} = (catch ExtFun(answer)),
- ?line false = erlang:function_exported(another_code_test, x, 1),
- ?line false = lists:member(another_code_test, erlang:loaded()),
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "another_code_test"),
- ?line {ok,another_code_test,Code} = compile:file(File, [binary,report]),
- ?line {module,another_code_test} = erlang:load_module(another_code_test, Code),
- ?line 42 = ExtFun(answer),
+ {'EXIT',{undef,_}} = (catch ExtFun(answer)),
+ false = erlang:function_exported(another_code_test, x, 1),
+ false = lists:member(another_code_test, erlang:loaded()),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "another_code_test"),
+ {ok,another_code_test,Code} = compile:file(File, [binary,report]),
+ {module,another_code_test} = erlang:load_module(another_code_test, Code),
+ 42 = ExtFun(answer),
ok.
get_chunk(Config) when is_list(Config) ->
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "my_code_test"),
- ?line {ok,my_code_test,Code} = compile:file(File, [binary]),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "my_code_test"),
+ {ok,my_code_test,Code} = compile:file(File, [binary]),
%% Should work.
- ?line Chunk = get_chunk_ok("Atom", Code),
- ?line Chunk = get_chunk_ok("Atom", make_sub_binary(Code)),
- ?line Chunk = get_chunk_ok("Atom", make_unaligned_sub_binary(Code)),
+ Chunk = get_chunk_ok("Atom", Code),
+ Chunk = get_chunk_ok("Atom", make_sub_binary(Code)),
+ Chunk = get_chunk_ok("Atom", make_unaligned_sub_binary(Code)),
%% Should fail.
- ?line {'EXIT',{badarg,_}} = (catch code:get_chunk(bit_sized_binary(Code), "Atom")),
- ?line {'EXIT',{badarg,_}} = (catch code:get_chunk(Code, "bad chunk id")),
+ {'EXIT',{badarg,_}} = (catch code:get_chunk(bit_sized_binary(Code), "Atom")),
+ {'EXIT',{badarg,_}} = (catch code:get_chunk(Code, "bad chunk id")),
%% Invalid beam code or missing chunk should return 'undefined'.
- ?line undefined = code:get_chunk(<<"not a beam module">>, "Atom"),
- ?line undefined = code:get_chunk(Code, "XXXX"),
+ undefined = code:get_chunk(<<"not a beam module">>, "Atom"),
+ undefined = code:get_chunk(Code, "XXXX"),
ok.
get_chunk_ok(Chunk, Code) ->
case code:get_chunk(Code, Chunk) of
- Bin when is_binary(Bin) -> Bin
+ Bin when is_binary(Bin) -> Bin
end.
module_md5(Config) when is_list(Config) ->
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "my_code_test"),
- ?line {ok,my_code_test,Code} = compile:file(File, [binary]),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "my_code_test"),
+ {ok,my_code_test,Code} = compile:file(File, [binary]),
%% Should work.
- ?line Chunk = module_md5_ok(Code),
- ?line Chunk = module_md5_ok(make_sub_binary(Code)),
- ?line Chunk = module_md5_ok(make_unaligned_sub_binary(Code)),
+ Chunk = module_md5_ok(Code),
+ Chunk = module_md5_ok(make_sub_binary(Code)),
+ Chunk = module_md5_ok(make_unaligned_sub_binary(Code)),
%% Should fail.
- ?line {'EXIT',{badarg,_}} = (catch code:module_md5(bit_sized_binary(Code))),
+ {'EXIT',{badarg,_}} = (catch code:module_md5(bit_sized_binary(Code))),
%% Invalid beam code should return 'undefined'.
- ?line undefined = code:module_md5(<<"not a beam module">>),
+ undefined = code:module_md5(<<"not a beam module">>),
ok.
-
+
module_md5_ok(Code) ->
case code:module_md5(Code) of
- Bin when is_binary(Bin), size(Bin) =:= 16 -> Bin
+ Bin when is_binary(Bin), size(Bin) =:= 16 -> Bin
end.
@@ -392,106 +382,106 @@ make_stub(Config) when is_list(Config) ->
catch erlang:purge_module(my_code_test),
MD5 = erlang:md5(<<>>),
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "my_code_test"),
- ?line {ok,my_code_test,Code} = compile:file(File, [binary]),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "my_code_test"),
+ {ok,my_code_test,Code} = compile:file(File, [binary]),
- ?line my_code_test = code:make_stub_module(my_code_test, Code, {[],[],MD5}),
- ?line true = erlang:delete_module(my_code_test),
- ?line true = erlang:purge_module(my_code_test),
+ my_code_test = code:make_stub_module(my_code_test, Code, {[],[],MD5}),
+ true = erlang:delete_module(my_code_test),
+ true = erlang:purge_module(my_code_test),
- ?line my_code_test = code:make_stub_module(my_code_test,
- make_unaligned_sub_binary(Code),
- {[],[],MD5}),
- ?line true = erlang:delete_module(my_code_test),
- ?line true = erlang:purge_module(my_code_test),
+ my_code_test = code:make_stub_module(my_code_test,
+ make_unaligned_sub_binary(Code),
+ {[],[],MD5}),
+ true = erlang:delete_module(my_code_test),
+ true = erlang:purge_module(my_code_test),
- ?line my_code_test = code:make_stub_module(my_code_test, zlib:gzip(Code),
- {[],[],MD5}),
- ?line true = erlang:delete_module(my_code_test),
- ?line true = erlang:purge_module(my_code_test),
+ my_code_test = code:make_stub_module(my_code_test, zlib:gzip(Code),
+ {[],[],MD5}),
+ true = erlang:delete_module(my_code_test),
+ true = erlang:purge_module(my_code_test),
%% Should fail.
- ?line {'EXIT',{badarg,_}} =
- (catch code:make_stub_module(my_code_test, <<"bad">>, {[],[],MD5})),
- ?line {'EXIT',{badarg,_}} =
- (catch code:make_stub_module(my_code_test,
- bit_sized_binary(Code),
- {[],[],MD5})),
- ?line {'EXIT',{badarg,_}} =
- (catch code:make_stub_module(my_code_test_with_wrong_name,
- Code, {[],[],MD5})),
+ {'EXIT',{badarg,_}} =
+ (catch code:make_stub_module(my_code_test, <<"bad">>, {[],[],MD5})),
+ {'EXIT',{badarg,_}} =
+ (catch code:make_stub_module(my_code_test,
+ bit_sized_binary(Code),
+ {[],[],MD5})),
+ {'EXIT',{badarg,_}} =
+ (catch code:make_stub_module(my_code_test_with_wrong_name,
+ Code, {[],[],MD5})),
ok.
make_stub_many_funs(Config) when is_list(Config) ->
catch erlang:purge_module(many_funs),
MD5 = erlang:md5(<<>>),
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "many_funs"),
- ?line {ok,many_funs,Code} = compile:file(File, [binary]),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "many_funs"),
+ {ok,many_funs,Code} = compile:file(File, [binary]),
- ?line many_funs = code:make_stub_module(many_funs, Code, {[],[],MD5}),
- ?line true = erlang:delete_module(many_funs),
- ?line true = erlang:purge_module(many_funs),
- ?line many_funs = code:make_stub_module(many_funs,
- make_unaligned_sub_binary(Code),
- {[],[],MD5}),
- ?line true = erlang:delete_module(many_funs),
- ?line true = erlang:purge_module(many_funs),
+ many_funs = code:make_stub_module(many_funs, Code, {[],[],MD5}),
+ true = erlang:delete_module(many_funs),
+ true = erlang:purge_module(many_funs),
+ many_funs = code:make_stub_module(many_funs,
+ make_unaligned_sub_binary(Code),
+ {[],[],MD5}),
+ true = erlang:delete_module(many_funs),
+ true = erlang:purge_module(many_funs),
%% Should fail.
- ?line {'EXIT',{badarg,_}} =
- (catch code:make_stub_module(many_funs, <<"bad">>, {[],[],MD5})),
- ?line {'EXIT',{badarg,_}} =
- (catch code:make_stub_module(many_funs,
- bit_sized_binary(Code),
- {[],[],MD5})),
+ {'EXIT',{badarg,_}} =
+ (catch code:make_stub_module(many_funs, <<"bad">>, {[],[],MD5})),
+ {'EXIT',{badarg,_}} =
+ (catch code:make_stub_module(many_funs,
+ bit_sized_binary(Code),
+ {[],[],MD5})),
ok.
constant_pools(Config) when is_list(Config) ->
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "literals"),
- ?line {ok,literals,Code} = compile:file(File, [report,binary]),
- ?line {module,literals} = erlang:load_module(literals,
- make_sub_binary(Code)),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "literals"),
+ {ok,literals,Code} = compile:file(File, [report,binary]),
+ {module,literals} = erlang:load_module(literals,
+ make_sub_binary(Code)),
%% Initialize.
- ?line A = literals:a(),
- ?line B = literals:b(),
- ?line C = literals:huge_bignum(),
- ?line process_flag(trap_exit, true),
+ A = literals:a(),
+ B = literals:b(),
+ C = literals:huge_bignum(),
+ process_flag(trap_exit, true),
Self = self(),
%% Have a process WITHOUT old heap that references the literals
%% in the 'literals' module.
- ?line NoOldHeap = spawn_link(fun() -> no_old_heap(Self) end),
+ NoOldHeap = spawn_link(fun() -> no_old_heap(Self) end),
receive go -> ok end,
- ?line true = erlang:delete_module(literals),
- ?line false = erlang:check_process_code(NoOldHeap, literals),
- ?line erlang:check_process_code(self(), literals),
- ?line true = erlang:purge_module(literals),
- ?line NoOldHeap ! done,
- ?line receive
- {'EXIT',NoOldHeap,{A,B,C}} ->
- ok;
- Other ->
- ?line ?t:fail({unexpected,Other})
- end,
- ?line {module,literals} = erlang:load_module(literals, Code),
+ true = erlang:delete_module(literals),
+ false = erlang:check_process_code(NoOldHeap, literals),
+ erlang:check_process_code(self(), literals),
+ true = erlang:purge_module(literals),
+ NoOldHeap ! done,
+ receive
+ {'EXIT',NoOldHeap,{A,B,C}} ->
+ ok;
+ Other ->
+ ct:fail({unexpected,Other})
+ end,
+ {module,literals} = erlang:load_module(literals, Code),
%% Have a process WITH an old heap that references the literals
%% in the 'literals' module.
- ?line OldHeap = spawn_link(fun() -> old_heap(Self) end),
+ OldHeap = spawn_link(fun() -> old_heap(Self) end),
receive go -> ok end,
- ?line true = erlang:delete_module(literals),
- ?line false = erlang:check_process_code(OldHeap, literals),
- ?line erlang:check_process_code(self(), literals),
- ?line erlang:purge_module(literals),
- ?line OldHeap ! done,
+ true = erlang:delete_module(literals),
+ false = erlang:check_process_code(OldHeap, literals),
+ erlang:check_process_code(self(), literals),
+ erlang:purge_module(literals),
+ OldHeap ! done,
receive
- {'EXIT',OldHeap,{A,B,C,[1,2,3|_]=Seq}} when length(Seq) =:= 16 ->
- ok
+ {'EXIT',OldHeap,{A,B,C,[1,2,3|_]=Seq}} when length(Seq) =:= 16 ->
+ ok
end.
no_old_heap(Parent) ->
@@ -500,8 +490,8 @@ no_old_heap(Parent) ->
Res = {A,B,literals:huge_bignum()},
Parent ! go,
receive
- done ->
- exit(Res)
+ done ->
+ exit(Res)
end.
old_heap(Parent) ->
@@ -511,16 +501,16 @@ old_heap(Parent) ->
create_old_heap(),
Parent ! go,
receive
- done ->
- exit(Res)
+ done ->
+ exit(Res)
end.
create_old_heap() ->
case process_info(self(), [heap_size,total_heap_size]) of
- [{heap_size,Sz},{total_heap_size,Total}] when Sz < Total ->
- ok;
- _ ->
- create_old_heap()
+ [{heap_size,Sz},{total_heap_size,Total}] when Sz < Total ->
+ ok;
+ _ ->
+ create_old_heap()
end.
constant_refc_binaries(Config) when is_list(Config) ->
@@ -529,7 +519,7 @@ constant_refc_binaries(Config) when is_list(Config) ->
io:format("Binary data (bytes) before test: ~p\n", [Bef]),
%% Compile the the literals module.
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
File = filename:join(Data, "literals"),
{ok,literals,Code} = compile:file(File, [report,binary]),
@@ -554,29 +544,29 @@ constant_refc_binaries(Config) when is_list(Config) ->
io:format("Binary data (bytes) after test: ~p", [Aft]),
Diff = Aft - Bef,
if
- Diff < 0 ->
- io:format("~p less bytes", [abs(Diff)]);
- Diff > 0 ->
- io:format("~p more bytes", [Diff]);
- true ->
- ok
+ Diff < 0 ->
+ io:format("~p less bytes", [abs(Diff)]);
+ Diff > 0 ->
+ io:format("~p more bytes", [Diff]);
+ true ->
+ ok
end,
%% Test for leaks. We must accept some natural variations in
%% the size of allocated binaries.
if
- Diff > 64*1024 ->
- ?t:fail(binary_leak);
- true ->
- ok
+ Diff > 64*1024 ->
+ ct:fail(binary_leak);
+ true ->
+ ok
end.
memory_binary() ->
try
- erlang:memory(binary)
+ erlang:memory(binary)
catch
- error:notsup ->
- 0
+ error:notsup ->
+ 0
end.
provoke_mem_leak(0, _, _) -> ok;
@@ -586,19 +576,19 @@ provoke_mem_leak(N, Code, Check) ->
%% Create several processes with references to the literal binary.
Self = self(),
Pids = [spawn_link(fun() ->
- create_binaries(Self, NumRefs, Check)
- end) || NumRefs <- lists:seq(1, 10)],
+ create_binaries(Self, NumRefs, Check)
+ end) || NumRefs <- lists:seq(1, 10)],
[receive {started,Pid} -> ok end || Pid <- Pids],
%% Make the code old and remove references to the constant pool
%% in all processes.
true = erlang:delete_module(literals),
Ms = [spawn_monitor(fun() ->
- false = erlang:check_process_code(Pid, literals)
- end) || Pid <- Pids],
+ false = erlang:check_process_code(Pid, literals)
+ end) || Pid <- Pids],
[receive
- {'DOWN',R,process,P,normal} ->
- ok
+ {'DOWN',R,process,P,normal} ->
+ ok
end || {P,R} <- Ms],
%% Purge the code.
@@ -606,14 +596,14 @@ provoke_mem_leak(N, Code, Check) ->
%% Tell the processes that the code has been purged.
[begin
- monitor(process, Pid),
- Pid ! purged
+ monitor(process, Pid),
+ Pid ! purged
end || Pid <- Pids],
%% Wait for all processes to terminate.
[receive
- {'DOWN',_,process,Pid,normal} ->
- ok
+ {'DOWN',_,process,Pid,normal} ->
+ ok
end || Pid <- Pids],
%% We now expect that the binary has been deallocated.
@@ -625,112 +615,112 @@ create_binaries(Parent, NumRefs, Check) ->
{bits,Bits} = literals:bits(),
Parent ! {started,self()},
receive
- purged ->
- %% The code has been purged. Now make sure that
- %% the binaries haven't been corrupted.
- Check = erlang:md5(Bin),
- [Bin = B || B <- Bins],
- <<42:13,Bin/binary>> = Bits,
-
- %% Remove all references to the binaries
- %% Doing it explicitly like this ensures that
- %% the binaries are gone when the parent process
- %% receives the 'DOWN' message.
- erlang:garbage_collect()
+ purged ->
+ %% The code has been purged. Now make sure that
+ %% the binaries haven't been corrupted.
+ Check = erlang:md5(Bin),
+ [Bin = B || B <- Bins],
+ <<42:13,Bin/binary>> = Bits,
+
+ %% Remove all references to the binaries
+ %% Doing it explicitly like this ensures that
+ %% the binaries are gone when the parent process
+ %% receives the 'DOWN' message.
+ erlang:garbage_collect()
end.
wait_for_memory_deallocations() ->
try
- erts_debug:set_internal_state(wait, deallocations)
+ erts_debug:set_internal_state(wait, deallocations)
catch
- error:undef ->
- erts_debug:set_internal_state(available_internal_state, true),
- wait_for_memory_deallocations()
+ error:undef ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ wait_for_memory_deallocations()
end.
%% OTP-7559: c_p->cp could contain garbage and create a false dependency
%% to a module in a process. (Thanks to Richard Carlsson.)
false_dependency(Config) when is_list(Config) ->
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "cpbugx"),
- ?line {ok,cpbugx,Code} = compile:file(File, [binary,report]),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "cpbugx"),
+ {ok,cpbugx,Code} = compile:file(File, [binary,report]),
do_false_dependency(fun cpbugx:before/0, Code),
do_false_dependency(fun cpbugx:before2/0, Code),
do_false_dependency(fun cpbugx:before3/0, Code),
-%% %% Spawn process. Make sure it has called cpbugx:before/0 and returned.
-%% Parent = self(),
-%% ?line Pid = spawn_link(fun() -> false_dependency_loop(Parent) end),
-%% ?line receive initialized -> ok end,
+ %% %% Spawn process. Make sure it has called cpbugx:before/0 and returned.
+ %% Parent = self(),
+ %% Pid = spawn_link(fun() -> false_dependency_loop(Parent) end),
+ %% receive initialized -> ok end,
+
+ %% %% Reload the module. Make sure the process is still alive.
+ %% {module,cpbugx} = erlang:load_module(cpbugx, Bin),
+ %% io:put_chars(binary_to_list(element(2, process_info(Pid, backtrace)))),
+ %% true = is_process_alive(Pid),
-%% %% Reload the module. Make sure the process is still alive.
-%% ?line {module,cpbugx} = erlang:load_module(cpbugx, Bin),
-%% ?line io:put_chars(binary_to_list(element(2, process_info(Pid, backtrace)))),
-%% ?line true = is_process_alive(Pid),
+ %% %% There should not be any dependency to cpbugx.
+ %% false = erlang:check_process_code(Pid, cpbugx),
-%% %% There should not be any dependency to cpbugx.
-%% ?line false = erlang:check_process_code(Pid, cpbugx),
-
-%% %% Kill the process.
-%% ?line unlink(Pid), exit(Pid, kill),
+ %% %% Kill the process.
+ %% unlink(Pid), exit(Pid, kill),
ok.
do_false_dependency(Init, Code) ->
- ?line {module,cpbugx} = erlang:load_module(cpbugx, Code),
+ {module,cpbugx} = erlang:load_module(cpbugx, Code),
%% Spawn process. Make sure it has the appropriate init function
%% and returned. CP should not contain garbage after the return.
Parent = self(),
- ?line Pid = spawn_link(fun() -> false_dependency_loop(Parent, Init, true) end),
- ?line receive initialized -> ok end,
+ Pid = spawn_link(fun() -> false_dependency_loop(Parent, Init, true) end),
+ receive initialized -> ok end,
%% Reload the module. Make sure the process is still alive.
- ?line {module,cpbugx} = erlang:load_module(cpbugx, Code),
- ?line io:put_chars(binary_to_list(element(2, process_info(Pid, backtrace)))),
- ?line true = is_process_alive(Pid),
+ {module,cpbugx} = erlang:load_module(cpbugx, Code),
+ io:put_chars(binary_to_list(element(2, process_info(Pid, backtrace)))),
+ true = is_process_alive(Pid),
%% There should not be any dependency to cpbugx.
- ?line false = erlang:check_process_code(Pid, cpbugx),
+ false = erlang:check_process_code(Pid, cpbugx),
%% Kill the process and completely unload the code.
- ?line unlink(Pid), exit(Pid, kill),
- ?line true = erlang:purge_module(cpbugx),
- ?line true = erlang:delete_module(cpbugx),
- ?line code:is_module_native(cpbugx), % test is_module_native on deleted code
- ?line true = erlang:purge_module(cpbugx),
- ?line code:is_module_native(cpbugx), % test is_module_native on purged code
+ unlink(Pid), exit(Pid, kill),
+ true = erlang:purge_module(cpbugx),
+ true = erlang:delete_module(cpbugx),
+ code:is_module_native(cpbugx), % test is_module_native on deleted code
+ true = erlang:purge_module(cpbugx),
+ code:is_module_native(cpbugx), % test is_module_native on purged code
ok.
-
+
false_dependency_loop(Parent, Init, SendInitAck) ->
Init(),
case SendInitAck of
- true -> Parent ! initialized;
- false -> void
- %% Just send one init-ack. I guess the point of this test
- %% wasn't to fill parents msg-queue (?). Seen to cause
- %% out-of-mem (on halfword-vm for some reason) by
- %% 91 million msg in queue. /sverker
+ true -> Parent ! initialized;
+ false -> void
+ %% Just send one init-ack. I guess the point of this test
+ %% wasn't to fill parents msg-queue (?). Seen to cause
+ %% out-of-mem (on halfword-vm for some reason) by
+ %% 91 million msg in queue. /sverker
end,
receive
- _ -> false_dependency_loop(Parent, Init, false)
+ _ -> false_dependency_loop(Parent, Init, false)
end.
coverage(Config) when is_list(Config) ->
- ?line code:is_module_native(?MODULE),
- ?line {'EXIT',{badarg,_}} = (catch erlang:purge_module({a,b,c})),
- ?line {'EXIT',{badarg,_}} = (catch code:is_module_native({a,b,c})),
- ?line {'EXIT',{badarg,_}} = (catch erlang:check_process_code(not_a_pid, ?MODULE)),
- ?line {'EXIT',{badarg,_}} = (catch erlang:check_process_code(self(), [not_a_module])),
- ?line {'EXIT',{badarg,_}} = (catch erlang:delete_module([a,b,c])),
- ?line {'EXIT',{badarg,_}} = (catch erlang:module_loaded(42)),
+ code:is_module_native(?MODULE),
+ {'EXIT',{badarg,_}} = (catch erlang:purge_module({a,b,c})),
+ {'EXIT',{badarg,_}} = (catch code:is_module_native({a,b,c})),
+ {'EXIT',{badarg,_}} = (catch erlang:check_process_code(not_a_pid, ?MODULE)),
+ {'EXIT',{badarg,_}} = (catch erlang:check_process_code(self(), [not_a_module])),
+ {'EXIT',{badarg,_}} = (catch erlang:delete_module([a,b,c])),
+ {'EXIT',{badarg,_}} = (catch erlang:module_loaded(42)),
ok.
fun_confusion(Config) when is_list(Config) ->
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
Src = filename:join(Data, "fun_confusion"),
Mod = fun_confusion,
@@ -753,6 +743,80 @@ compile_load(Mod, Src, Ver) ->
{module,Mod} = code:load_binary(Mod, "fun_confusion.beam", Code1),
ok.
+
+t_copy_literals(Config) when is_list(Config) ->
+ %% Compile the the literals module.
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "literals"),
+ {ok,literals,Code} = compile:file(File, [report,binary]),
+ {module,literals} = erlang:load_module(literals, Code),
+
+ N = 30,
+ Me = self(),
+ %% reload literals code every 567 ms
+ Rel = spawn_link(fun() -> reloader(literals,Code,567) end),
+ %% add new literal msgs to the loop every 789 ms
+ Sat = spawn_link(fun() -> saturate(Me,789) end),
+ %% run for 10s
+ _ = spawn_link(fun() -> receive after 10000 -> Me ! done end end),
+ ok = chase_msg(N, Me),
+ %% cleanup
+ Rel ! done,
+ Sat ! done,
+ ok = flush(),
+ ok.
+
+
+chase_msg(0, Pid) ->
+ chase_loop(Pid);
+chase_msg(N, Master) ->
+ Pid = spawn_link(fun() -> chase_msg(N - 1,Master) end),
+ chase_loop(Pid).
+
+chase_loop(Pid) ->
+ receive
+ done ->
+ Pid ! done,
+ ok;
+ {_From,Msg} ->
+ Pid ! {self(), Msg},
+ ok = traverse(Msg),
+ chase_loop(Pid)
+ end.
+
+saturate(Pid,Time) ->
+ Es = [msg1,msg2,msg3,msg4,msg5],
+ Msg = [literals:E()||E <- Es],
+ Pid ! {self(), Msg},
+ receive
+ done -> ok
+ after Time ->
+ saturate(Pid,Time)
+ end.
+
+traverse([]) -> ok;
+traverse([H|T]) ->
+ ok = traverse(H),
+ traverse(T);
+traverse(T) when is_tuple(T) -> ok;
+traverse(B) when is_binary(B) -> ok;
+traverse(I) when is_integer(I) -> ok;
+traverse(#{ 1 := V1, b := V2 }) ->
+ ok = traverse(V1),
+ ok = traverse(V2),
+ ok.
+
+
+reloader(Mod,Code,Time) ->
+ receive
+ done -> ok
+ after Time ->
+ code:purge(Mod),
+ {module,Mod} = erlang:load_module(Mod, Code),
+ reloader(Mod,Code,Time)
+ end.
+
+
%% Utilities.
make_sub_binary(Bin) when is_binary(Bin) ->
@@ -775,4 +839,7 @@ bit_sized_binary(Bin0) ->
BitSize = 8*size(Bin) + 1,
Bin.
+flush() ->
+ receive _ -> flush() after 0 -> ok end.
+
id(I) -> I.
diff --git a/erts/emulator/test/code_SUITE_data/literals.erl b/erts/emulator/test/code_SUITE_data/literals.erl
index 9802d9d3f9..a36bfe09dd 100644
--- a/erts/emulator/test/code_SUITE_data/literals.erl
+++ b/erts/emulator/test/code_SUITE_data/literals.erl
@@ -20,6 +20,7 @@
-module(literals).
-export([a/0,b/0,huge_bignum/0,binary/0,unused_binaries/0,bits/0]).
+-export([msg1/0,msg2/0,msg3/0,msg4/0,msg5/0]).
a() ->
{a,42.0,[7,38877938333399637266518333334747]}.
@@ -101,3 +102,9 @@ unused_binaries() ->
bits() ->
{bits,<<42:13,?MB_1>>}.
+
+msg1() -> "halloj".
+msg2() -> {"hello","world"}.
+msg3() -> <<"halloj">>.
+msg4() -> #{ 1=> "hello", b => "world"}.
+msg5() -> {1,2,3,4,5,6}.
diff --git a/erts/emulator/test/code_parallel_load_SUITE.erl b/erts/emulator/test/code_parallel_load_SUITE.erl
index b7ac0420cd..e9e7000434 100644
--- a/erts/emulator/test/code_parallel_load_SUITE.erl
+++ b/erts/emulator/test/code_parallel_load_SUITE.erl
@@ -19,49 +19,34 @@
%%
-module(code_parallel_load_SUITE).
--export([
- all/0,
- suite/0,
- init_per_suite/1,
- end_per_suite/1,
- init_per_testcase/2,
- end_per_testcase/2
- ]).
-
--export([
- multiple_load_check_purge_repeat/1,
- many_load_distributed_only_once/1
- ]).
+-export([all/0,
+ suite/0,
+ init_per_testcase/2,
+ end_per_testcase/2]).
+
+-export([multiple_load_check_purge_repeat/1,
+ many_load_distributed_only_once/1]).
-define(model, code_parallel_load_SUITE_model).
-define(interval, 50).
-define(number_of_processes, 160).
-define(passes, 4).
+-include_lib("common_test/include/ct.hrl").
--include_lib("test_server/include/test_server.hrl").
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 4}}].
all() ->
- [
- multiple_load_check_purge_repeat,
- many_load_distributed_only_once
- ].
-
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
+ [ multiple_load_check_purge_repeat,
+ many_load_distributed_only_once ].
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?t:timetrap(?t:minutes(3)),
- [{watchdog, Dog}|Config].
+ Config.
end_per_testcase(_Func, Config) ->
- SConf = ?config(save_config, Config),
+ SConf = proplists:get_value(save_config, Config),
Pids = proplists:get_value(purge_pids, SConf),
case check_old_code(?model) of
@@ -72,9 +57,7 @@ end_per_testcase(_Func, Config) ->
true -> check_and_purge_processes_code(Pids, ?model);
_ -> ok
end,
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
+ ok.
multiple_load_check_purge_repeat(_Conf) ->
Ts = [v1,v2,v3,v4,v5,v6],
diff --git a/erts/emulator/test/crypto_SUITE.erl b/erts/emulator/test/crypto_SUITE.erl
index 3622592586..6212997272 100644
--- a/erts/emulator/test/crypto_SUITE.erl
+++ b/erts/emulator/test/crypto_SUITE.erl
@@ -20,65 +20,44 @@
-module(crypto_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- t_md5/1,t_md5_update/1,error/1,unaligned_context/1,random_lists/1,
- misc_errors/1]).
+-export([all/0, suite/0,
+ t_md5/1,t_md5_update/1,error/1,unaligned_context/1,random_lists/1,
+ misc_errors/1]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]}].
all() ->
[t_md5, t_md5_update, error, unaligned_context,
random_lists, misc_errors].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-
-misc_errors(doc) ->
- ["Test crc32, adler32 and md5 error cases not covered by other tests"];
-misc_errors(suite) ->
- [];
+%% Test crc32, adler32 and md5 error cases not covered by other tests"
misc_errors(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(2)),
- ?line 1 = erlang:adler32([]),
- ?line L = lists:duplicate(600,3),
- ?line 1135871753 = erlang:adler32(L),
- ?line L2 = lists:duplicate(22000,3),
- ?line 1100939744 = erlang:adler32(L2),
- ?line {'EXIT', {badarg,_}} = (catch erlang:adler32(L++[a])),
- ?line {'EXIT', {badarg,_}} = (catch erlang:crc32(L++[a])),
- ?line {'EXIT', {badarg,_}} = (catch erlang:crc32([1,2,3|<<25:7>>])),
- ?line {'EXIT', {badarg,_}} = (catch erlang:crc32([1,2,3|4])),
- ?line Big = 111111111111111111111111111111,
- ?line {'EXIT', {badarg,_}} = (catch erlang:crc32(Big,<<"hej">>)),
- ?line {'EXIT', {badarg,_}} = (catch erlang:crc32(25,[1,2,3|4])),
- ?line {'EXIT', {badarg,_}} = (catch erlang:crc32_combine(Big,3,3)),
- ?line {'EXIT', {badarg,_}} = (catch erlang:crc32_combine(3,Big,3)),
- ?line {'EXIT', {badarg,_}} = (catch erlang:crc32_combine(3,3,Big)),
- ?line {'EXIT', {badarg,_}} = (catch erlang:adler32(Big,<<"hej">>)),
- ?line {'EXIT', {badarg,_}} = (catch erlang:adler32(25,[1,2,3|4])),
- ?line {'EXIT', {badarg,_}} = (catch erlang:adler32_combine(Big,3,3)),
- ?line {'EXIT', {badarg,_}} = (catch erlang:adler32_combine(3,Big,3)),
- ?line {'EXIT', {badarg,_}} = (catch erlang:adler32_combine(3,3,Big)),
- ?line {'EXIT', {badarg,_}} = (catch erlang:md5_update(<<"hej">>,<<"hej">>)),
- ?line {'EXIT', {badarg,_}} = (catch erlang:md5_final(<<"hej">>)),
- ?line test_server:timetrap_cancel(Dog),
+ ct:timetrap({minutes, 2}),
+ 1 = erlang:adler32([]),
+ L = lists:duplicate(600,3),
+ 1135871753 = erlang:adler32(L),
+ L2 = lists:duplicate(22000,3),
+ 1100939744 = erlang:adler32(L2),
+ {'EXIT', {badarg,_}} = (catch erlang:adler32(L++[a])),
+ {'EXIT', {badarg,_}} = (catch erlang:crc32(L++[a])),
+ {'EXIT', {badarg,_}} = (catch erlang:crc32([1,2,3|<<25:7>>])),
+ {'EXIT', {badarg,_}} = (catch erlang:crc32([1,2,3|4])),
+ Big = 111111111111111111111111111111,
+ {'EXIT', {badarg,_}} = (catch erlang:crc32(Big,<<"hej">>)),
+ {'EXIT', {badarg,_}} = (catch erlang:crc32(25,[1,2,3|4])),
+ {'EXIT', {badarg,_}} = (catch erlang:crc32_combine(Big,3,3)),
+ {'EXIT', {badarg,_}} = (catch erlang:crc32_combine(3,Big,3)),
+ {'EXIT', {badarg,_}} = (catch erlang:crc32_combine(3,3,Big)),
+ {'EXIT', {badarg,_}} = (catch erlang:adler32(Big,<<"hej">>)),
+ {'EXIT', {badarg,_}} = (catch erlang:adler32(25,[1,2,3|4])),
+ {'EXIT', {badarg,_}} = (catch erlang:adler32_combine(Big,3,3)),
+ {'EXIT', {badarg,_}} = (catch erlang:adler32_combine(3,Big,3)),
+ {'EXIT', {badarg,_}} = (catch erlang:adler32_combine(3,3,Big)),
+ {'EXIT', {badarg,_}} = (catch erlang:md5_update(<<"hej">>,<<"hej">>)),
+ {'EXIT', {badarg,_}} = (catch erlang:md5_final(<<"hej">>)),
ok.
@@ -93,7 +72,7 @@ nicesplit(N,L) ->
nicesplit(0,Tail,Acc) ->
{lists:reverse(Acc),Tail};
nicesplit(_,[],Acc) ->
- {lists:reverse(Acc),[]};
+ {lists:reverse(Acc),[]};
nicesplit(N,[H|Tail],Acc) ->
nicesplit(N-1,Tail,[H|Acc]).
@@ -102,17 +81,17 @@ run_in_para([],_) ->
run_in_para(FunList,Schedulers) ->
{ThisTime,NextTime} = nicesplit(Schedulers,FunList),
case length(ThisTime) of
- 1 ->
- [{L,Fun}] = ThisTime,
- try
- Fun()
+ 1 ->
+ [{L,Fun}] = ThisTime,
+ try
+ Fun()
catch
- _:Reason ->
- exit({error_at_line,L,Reason})
- end;
+ _:Reason ->
+ exit({error_at_line,L,Reason})
+ end;
_ ->
- These = [ {L,erlang:spawn_monitor(F)} || {L,F} <- ThisTime ],
- collect_workers(These)
+ These = [ {L,erlang:spawn_monitor(F)} || {L,F} <- ThisTime ],
+ collect_workers(These)
end,
run_in_para(NextTime,Schedulers).
@@ -120,159 +99,147 @@ collect_workers([]) ->
ok;
collect_workers([{L,{Pid,Ref}}|T]) ->
receive
- {'DOWN',Ref,process,Pid,normal} ->
- collect_workers(T);
- {'DOWN',Ref,process,Pid,Other} ->
- exit({error_at_line,L,Other})
+ {'DOWN',Ref,process,Pid,normal} ->
+ collect_workers(T);
+ {'DOWN',Ref,process,Pid,Other} ->
+ exit({error_at_line,L,Other})
end.
-random_lists(doc) ->
- ["Test crc32, adler32 and md5 on a number of pseudo-randomly generated "
- "lists."];
-random_lists(suite) ->
- [];
+%% Test crc32, adler32 and md5 on a number of pseudo-randomly generated lists.
random_lists(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(5)),
- ?line Num = erlang:system_info(schedulers_online),
- ?line B = list_to_binary(
- lists:duplicate(
- (erlang:system_info(context_reductions)*10) - 50,$!)),
- ?line CRC32_1 = fun(L) -> erlang:crc32(L) end,
- ?line CRC32_2 = fun(L) -> ?REF:crc32(L) end,
- ?line ADLER32_1 = fun(L) -> erlang:adler32(L) end,
- ?line ADLER32_2 = fun(L) -> ?REF:adler32(L) end,
- ?line MD5_1 = fun(L) -> erlang:md5(L) end,
- ?line MD5_2 = fun(L) -> ?REF:md5_final(
- ?REF:md5_update(?REF:md5_init(),L)) end,
- ?line MD5_3 = fun(L) -> erlang:md5_final(
- erlang:md5_update(erlang:md5_init(),L)) end,
- ?line CRC32_1_L = fun(L) -> erlang:crc32([B|L]) end,
- ?line CRC32_2_L = fun(L) -> ?REF:crc32([B|L]) end,
- ?line ADLER32_1_L = fun(L) -> erlang:adler32([B|L]) end,
- ?line ADLER32_2_L = fun(L) -> ?REF:adler32([B|L]) end,
- ?line MD5_1_L = fun(L) -> erlang:md5([B|L]) end,
- ?line MD5_2_L = fun(L) -> ?REF:md5_final(
- ?REF:md5_update(?REF:md5_init(),[B|L])) end,
- ?line MD5_3_L = fun(L) -> erlang:md5_final(
- erlang:md5_update(
- erlang:md5_init(),[B|L])) end,
- ?line Wlist0 =
- [{?LINE, fun() -> random_iolist:run(150, CRC32_1, CRC32_2) end},
- {?LINE, fun() -> random_iolist:run(150, ADLER32_1, ADLER32_2) end},
- {?LINE, fun() -> random_iolist:run(150,MD5_1,MD5_2) end},
- {?LINE, fun() -> random_iolist:run(150,MD5_1,MD5_3) end},
- {?LINE, fun() -> random_iolist:run(150, CRC32_1_L, CRC32_2_L) end},
- {?LINE,
- fun() -> random_iolist:run(150, ADLER32_1_L, ADLER32_2_L) end},
- {?LINE, fun() -> random_iolist:run(150,MD5_1_L,MD5_2_L) end},
- {?LINE, fun() -> random_iolist:run(150,MD5_1_L,MD5_3_L) end}],
- ?line run_in_para(Wlist0,Num),
- ?line CRC32_1_2 = fun(L1,L2) -> erlang:crc32([L1,L2]) end,
- ?line CRC32_2_2 = fun(L1,L2) -> erlang:crc32(erlang:crc32(L1),L2) end,
- ?line CRC32_3_2 = fun(L1,L2) -> erlang:crc32_combine(
- erlang:crc32(L1),
- erlang:crc32(L2),
- erlang:iolist_size(L2))
- end,
- ?line ADLER32_1_2 = fun(L1,L2) -> erlang:adler32([L1,L2]) end,
- ?line ADLER32_2_2 = fun(L1,L2) -> erlang:adler32(
- erlang:adler32(L1),L2) end,
- ?line ADLER32_3_2 = fun(L1,L2) -> erlang:adler32_combine(
- erlang:adler32(L1),
- erlang:adler32(L2),
- erlang:iolist_size(L2))
- end,
- ?line MD5_1_2 = fun(L1,L2) -> erlang:md5([L1,L2]) end,
- ?line MD5_2_2 = fun(L1,L2) ->
- erlang:md5_final(
- erlang:md5_update(
- erlang:md5_update(
- erlang:md5_init(),
- L1),
- L2))
- end,
- ?line CRC32_1_L_2 = fun(L1,L2) -> erlang:crc32([[B|L1],[B|L2]]) end,
- ?line CRC32_2_L_2 = fun(L1,L2) -> erlang:crc32(
- erlang:crc32([B|L1]),[B|L2]) end,
- ?line CRC32_3_L_2 = fun(L1,L2) -> erlang:crc32_combine(
- erlang:crc32([B|L1]),
- erlang:crc32([B|L2]),
- erlang:iolist_size([B|L2]))
- end,
- ?line ADLER32_1_L_2 = fun(L1,L2) -> erlang:adler32([[B|L1],[B|L2]]) end,
- ?line ADLER32_2_L_2 = fun(L1,L2) -> erlang:adler32(
- erlang:adler32([B|L1]),
- [B|L2])
- end,
- ?line ADLER32_3_L_2 = fun(L1,L2) -> erlang:adler32_combine(
- erlang:adler32([B|L1]),
- erlang:adler32([B|L2]),
- erlang:iolist_size([B|L2]))
- end,
- ?line MD5_1_L_2 = fun(L1,L2) -> erlang:md5([[B|L1],[B|L2]]) end,
- ?line MD5_2_L_2 = fun(L1,L2) ->
- erlang:md5_final(
- erlang:md5_update(
- erlang:md5_update(
- erlang:md5_init(),
- [B|L1]),
- [B|L2]))
- end,
- ?line Wlist1 =
- [{?LINE, fun() -> random_iolist:run2(150,CRC32_1_2,CRC32_2_2) end},
- {?LINE, fun() -> random_iolist:run2(150,CRC32_1_2,CRC32_3_2) end},
- {?LINE, fun() -> random_iolist:run2(150,ADLER32_1_2,ADLER32_2_2) end},
- {?LINE, fun() -> random_iolist:run2(150,ADLER32_1_2,ADLER32_3_2) end},
- {?LINE, fun() -> random_iolist:run2(150,MD5_1_2,MD5_2_2) end},
- {?LINE, fun() -> random_iolist:run2(150,CRC32_1_L_2,CRC32_2_L_2) end},
- {?LINE, fun() -> random_iolist:run2(150,CRC32_1_L_2,CRC32_3_L_2) end},
- {?LINE,
- fun() -> random_iolist:run2(150,ADLER32_1_L_2,ADLER32_2_L_2) end},
- {?LINE,
- fun() -> random_iolist:run2(150,ADLER32_1_L_2,ADLER32_3_L_2) end},
- {?LINE, fun() -> random_iolist:run2(150,MD5_1_L_2,MD5_2_L_2) end}],
- ?line run_in_para(Wlist1,Num),
- ?line test_server:timetrap_cancel(Dog),
+ ct:timetrap({minutes, 5}),
+ Num = erlang:system_info(schedulers_online),
+ B = list_to_binary(
+ lists:duplicate(
+ (erlang:system_info(context_reductions)*10) - 50,$!)),
+ CRC32_1 = fun(L) -> erlang:crc32(L) end,
+ CRC32_2 = fun(L) -> ?REF:crc32(L) end,
+ ADLER32_1 = fun(L) -> erlang:adler32(L) end,
+ ADLER32_2 = fun(L) -> ?REF:adler32(L) end,
+ MD5_1 = fun(L) -> erlang:md5(L) end,
+ MD5_2 = fun(L) -> ?REF:md5_final(
+ ?REF:md5_update(?REF:md5_init(),L)) end,
+ MD5_3 = fun(L) -> erlang:md5_final(
+ erlang:md5_update(erlang:md5_init(),L)) end,
+ CRC32_1_L = fun(L) -> erlang:crc32([B|L]) end,
+ CRC32_2_L = fun(L) -> ?REF:crc32([B|L]) end,
+ ADLER32_1_L = fun(L) -> erlang:adler32([B|L]) end,
+ ADLER32_2_L = fun(L) -> ?REF:adler32([B|L]) end,
+ MD5_1_L = fun(L) -> erlang:md5([B|L]) end,
+ MD5_2_L = fun(L) -> ?REF:md5_final(
+ ?REF:md5_update(?REF:md5_init(),[B|L])) end,
+ MD5_3_L = fun(L) -> erlang:md5_final(
+ erlang:md5_update(
+ erlang:md5_init(),[B|L])) end,
+ Wlist0 =
+ [{?LINE, fun() -> random_iolist:run(150, CRC32_1, CRC32_2) end},
+ {?LINE, fun() -> random_iolist:run(150, ADLER32_1, ADLER32_2) end},
+ {?LINE, fun() -> random_iolist:run(150,MD5_1,MD5_2) end},
+ {?LINE, fun() -> random_iolist:run(150,MD5_1,MD5_3) end},
+ {?LINE, fun() -> random_iolist:run(150, CRC32_1_L, CRC32_2_L) end},
+ {?LINE,
+ fun() -> random_iolist:run(150, ADLER32_1_L, ADLER32_2_L) end},
+ {?LINE, fun() -> random_iolist:run(150,MD5_1_L,MD5_2_L) end},
+ {?LINE, fun() -> random_iolist:run(150,MD5_1_L,MD5_3_L) end}],
+ run_in_para(Wlist0,Num),
+ CRC32_1_2 = fun(L1,L2) -> erlang:crc32([L1,L2]) end,
+ CRC32_2_2 = fun(L1,L2) -> erlang:crc32(erlang:crc32(L1),L2) end,
+ CRC32_3_2 = fun(L1,L2) -> erlang:crc32_combine(
+ erlang:crc32(L1),
+ erlang:crc32(L2),
+ erlang:iolist_size(L2))
+ end,
+ ADLER32_1_2 = fun(L1,L2) -> erlang:adler32([L1,L2]) end,
+ ADLER32_2_2 = fun(L1,L2) -> erlang:adler32(
+ erlang:adler32(L1),L2) end,
+ ADLER32_3_2 = fun(L1,L2) -> erlang:adler32_combine(
+ erlang:adler32(L1),
+ erlang:adler32(L2),
+ erlang:iolist_size(L2))
+ end,
+ MD5_1_2 = fun(L1,L2) -> erlang:md5([L1,L2]) end,
+ MD5_2_2 = fun(L1,L2) ->
+ erlang:md5_final(
+ erlang:md5_update(
+ erlang:md5_update(
+ erlang:md5_init(),
+ L1),
+ L2))
+ end,
+ CRC32_1_L_2 = fun(L1,L2) -> erlang:crc32([[B|L1],[B|L2]]) end,
+ CRC32_2_L_2 = fun(L1,L2) -> erlang:crc32(
+ erlang:crc32([B|L1]),[B|L2]) end,
+ CRC32_3_L_2 = fun(L1,L2) -> erlang:crc32_combine(
+ erlang:crc32([B|L1]),
+ erlang:crc32([B|L2]),
+ erlang:iolist_size([B|L2]))
+ end,
+ ADLER32_1_L_2 = fun(L1,L2) -> erlang:adler32([[B|L1],[B|L2]]) end,
+ ADLER32_2_L_2 = fun(L1,L2) -> erlang:adler32(
+ erlang:adler32([B|L1]),
+ [B|L2])
+ end,
+ ADLER32_3_L_2 = fun(L1,L2) -> erlang:adler32_combine(
+ erlang:adler32([B|L1]),
+ erlang:adler32([B|L2]),
+ erlang:iolist_size([B|L2]))
+ end,
+ MD5_1_L_2 = fun(L1,L2) -> erlang:md5([[B|L1],[B|L2]]) end,
+ MD5_2_L_2 = fun(L1,L2) ->
+ erlang:md5_final(
+ erlang:md5_update(
+ erlang:md5_update(
+ erlang:md5_init(),
+ [B|L1]),
+ [B|L2]))
+ end,
+ Wlist1 =
+ [{?LINE, fun() -> random_iolist:run2(150,CRC32_1_2,CRC32_2_2) end},
+ {?LINE, fun() -> random_iolist:run2(150,CRC32_1_2,CRC32_3_2) end},
+ {?LINE, fun() -> random_iolist:run2(150,ADLER32_1_2,ADLER32_2_2) end},
+ {?LINE, fun() -> random_iolist:run2(150,ADLER32_1_2,ADLER32_3_2) end},
+ {?LINE, fun() -> random_iolist:run2(150,MD5_1_2,MD5_2_2) end},
+ {?LINE, fun() -> random_iolist:run2(150,CRC32_1_L_2,CRC32_2_L_2) end},
+ {?LINE, fun() -> random_iolist:run2(150,CRC32_1_L_2,CRC32_3_L_2) end},
+ {?LINE,
+ fun() -> random_iolist:run2(150,ADLER32_1_L_2,ADLER32_2_L_2) end},
+ {?LINE,
+ fun() -> random_iolist:run2(150,ADLER32_1_L_2,ADLER32_3_L_2) end},
+ {?LINE, fun() -> random_iolist:run2(150,MD5_1_L_2,MD5_2_L_2) end}],
+ run_in_para(Wlist1,Num),
ok.
-%%
-%%
-t_md5(doc) ->
- ["Generate MD5 message digests and check the result. Examples are "
- "from RFC-1321."];
+%% Generate MD5 message digests and check the result. Examples are from RFC-1321.
t_md5(Config) when is_list(Config) ->
- ?line t_md5_test("", "d41d8cd98f00b204e9800998ecf8427e"),
- ?line t_md5_test("a", "0cc175b9c0f1b6a831c399e269772661"),
- ?line t_md5_test("abc", "900150983cd24fb0d6963f7d28e17f72"),
- ?line t_md5_test(["message ","digest"], "f96b697d7cb7938d525a2f31aaf161d0"),
- ?line t_md5_test(["message ",unaligned_sub_bin(<<"digest">>)],
- "f96b697d7cb7938d525a2f31aaf161d0"),
- ?line t_md5_test("abcdefghijklmnopqrstuvwxyz",
- "c3fcd3d76192e4007dfb496cca67e13b"),
- ?line t_md5_test("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
- "0123456789",
- "d174ab98d277d9f5a5611c2c9f419d9f"),
- ?line t_md5_test("12345678901234567890123456789012345678901234567890"
- "123456789012345678901234567890",
- "57edf4a22be3c955ac49da2e2107b67a"),
+ t_md5_test("", "d41d8cd98f00b204e9800998ecf8427e"),
+ t_md5_test("a", "0cc175b9c0f1b6a831c399e269772661"),
+ t_md5_test("abc", "900150983cd24fb0d6963f7d28e17f72"),
+ t_md5_test(["message ","digest"], "f96b697d7cb7938d525a2f31aaf161d0"),
+ t_md5_test(["message ",unaligned_sub_bin(<<"digest">>)],
+ "f96b697d7cb7938d525a2f31aaf161d0"),
+ t_md5_test("abcdefghijklmnopqrstuvwxyz",
+ "c3fcd3d76192e4007dfb496cca67e13b"),
+ t_md5_test("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+ "0123456789",
+ "d174ab98d277d9f5a5611c2c9f419d9f"),
+ t_md5_test("12345678901234567890123456789012345678901234567890"
+ "123456789012345678901234567890",
+ "57edf4a22be3c955ac49da2e2107b67a"),
ok.
-%%
-%%
-t_md5_update(doc) ->
- ["Generate MD5 message using md5_init, md5_update, and md5_final, and"
- "check the result. Examples are from RFC-1321."];
+%% Generate MD5 message using md5_init, md5_update, and md5_final, and
+%% check the result. Examples are from RFC-1321.
t_md5_update(Config) when is_list(Config) ->
- ?line t_md5_update_1(fun(Str) -> Str end),
- ?line t_md5_update_1(fun(Str) -> list_to_binary(Str) end),
- ?line t_md5_update_1(fun(Str) -> unaligned_sub_bin(list_to_binary(Str)) end),
+ t_md5_update_1(fun(Str) -> Str end),
+ t_md5_update_1(fun(Str) -> list_to_binary(Str) end),
+ t_md5_update_1(fun(Str) -> unaligned_sub_bin(list_to_binary(Str)) end),
ok.
t_md5_update_1(Tr) when is_function(Tr, 1) ->
Ctx = erlang:md5_init(),
Ctx1 = erlang:md5_update(Ctx, Tr("ABCDEFGHIJKLMNOPQRSTUVWXYZ")),
Ctx2 = erlang:md5_update(Ctx1, Tr("abcdefghijklmnopqrstuvwxyz"
- "0123456789")),
+ "0123456789")),
m(erlang:md5_final(Ctx2),
hexstr2bin("d174ab98d277d9f5a5611c2c9f419d9f")),
ok.
@@ -280,28 +247,28 @@ t_md5_update_1(Tr) when is_function(Tr, 1) ->
%%
%%
error(Config) when is_list(Config) ->
- ?line {'EXIT',{badarg,_}} = (catch erlang:md5(bit_sized_binary(<<"abc">>))),
- ?line Ctx0 = erlang:md5_init(),
- ?line {'EXIT',{badarg,_}} =
- (catch erlang:md5_update(Ctx0, bit_sized_binary(<<"abcfjldjd">>))),
- ?line {'EXIT',{badarg,_}} =
- (catch erlang:md5_update(Ctx0, ["something",bit_sized_binary(<<"abcfjldjd">>)])),
- ?line {'EXIT',{badarg,_}} =
- (catch erlang:md5_update(bit_sized_binary(Ctx0), "something")),
- ?line {'EXIT',{badarg,_}} = (catch erlang:md5_final(bit_sized_binary(Ctx0))),
- ?line m(erlang:md5_final(Ctx0), hexstr2bin("d41d8cd98f00b204e9800998ecf8427e")),
+ {'EXIT',{badarg,_}} = (catch erlang:md5(bit_sized_binary(<<"abc">>))),
+ Ctx0 = erlang:md5_init(),
+ {'EXIT',{badarg,_}} =
+ (catch erlang:md5_update(Ctx0, bit_sized_binary(<<"abcfjldjd">>))),
+ {'EXIT',{badarg,_}} =
+ (catch erlang:md5_update(Ctx0, ["something",bit_sized_binary(<<"abcfjldjd">>)])),
+ {'EXIT',{badarg,_}} =
+ (catch erlang:md5_update(bit_sized_binary(Ctx0), "something")),
+ {'EXIT',{badarg,_}} = (catch erlang:md5_final(bit_sized_binary(Ctx0))),
+ m(erlang:md5_final(Ctx0), hexstr2bin("d41d8cd98f00b204e9800998ecf8427e")),
ok.
%%
%%
unaligned_context(Config) when is_list(Config) ->
- ?line Ctx0 = erlang:md5_init(),
- ?line Ctx1 = erlang:md5_update(unaligned_sub_bin(Ctx0), "ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
- ?line Ctx = erlang:md5_update(unaligned_sub_bin(Ctx1),
- "abcdefghijklmnopqrstuvwxyz0123456789"),
- ?line m(erlang:md5_final(unaligned_sub_bin(Ctx)),
- hexstr2bin("d174ab98d277d9f5a5611c2c9f419d9f")),
+ Ctx0 = erlang:md5_init(),
+ Ctx1 = erlang:md5_update(unaligned_sub_bin(Ctx0), "ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
+ Ctx = erlang:md5_update(unaligned_sub_bin(Ctx1),
+ "abcdefghijklmnopqrstuvwxyz0123456789"),
+ m(erlang:md5_final(unaligned_sub_bin(Ctx)),
+ hexstr2bin("d174ab98d277d9f5a5611c2c9f419d9f")),
ok.
%%
@@ -347,5 +314,3 @@ bit_sized_binary(Bin0) ->
Bin.
id(I) -> I.
-
-
diff --git a/erts/emulator/test/ddll_SUITE.erl b/erts/emulator/test/ddll_SUITE.erl
index cabd6472d4..6982178827 100644
--- a/erts/emulator/test/ddll_SUITE.erl
+++ b/erts/emulator/test/ddll_SUITE.erl
@@ -31,30 +31,31 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2, ddll_test/1, errors/1,
- reference_count/1,
- kill_port/1, dont_kill_port/1]).
+-export([all/0, suite/0,
+ ddll_test/1, errors/1, reference_count/1,
+ kill_port/1, dont_kill_port/1]).
-export([unload_on_process_exit/1, delayed_unload_with_ports/1,
- unload_due_to_process_exit/1,
- no_unload_due_to_process_exit/1, no_unload_due_to_process_exit_2/1,
- unload_reload_thingie/1, unload_reload_thingie_2/1,
- unload_reload_thingie_3/1, reload_pending/1, reload_pending_kill/1,
- load_fail_init/1,
- reload_pending_fail_init/1,
- more_error_codes/1, forced_port_killing/1,
- no_trap_exit_and_kill_ports/1,
- monitor_demonitor/1, monitor_demonitor_load/1, new_interface/1,
- lock_driver/1]).
+ unload_due_to_process_exit/1,
+ no_unload_due_to_process_exit/1, no_unload_due_to_process_exit_2/1,
+ unload_reload_thingie/1, unload_reload_thingie_2/1,
+ unload_reload_thingie_3/1, reload_pending/1, reload_pending_kill/1,
+ load_fail_init/1,
+ reload_pending_fail_init/1,
+ more_error_codes/1, forced_port_killing/1,
+ no_trap_exit_and_kill_ports/1,
+ monitor_demonitor/1, monitor_demonitor_load/1, new_interface/1,
+ lock_driver/1]).
% Private exports
-export([echo_loader/2, nice_echo_loader/2 ,properties/1, load_and_unload/1]).
-import(ordsets, [subtract/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {seconds, 10}}].
all() ->
[ddll_test, errors, reference_count, kill_port,
@@ -70,1057 +71,931 @@ all() ->
no_trap_exit_and_kill_ports, monitor_demonitor,
monitor_demonitor_load, new_interface, lock_driver].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-unload_on_process_exit(suite) ->
- [];
-unload_on_process_exit(doc) ->
- ["Check that the driver is unloaded on process exit"];
+%% Check that the driver is unloaded on process exit
unload_on_process_exit(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line false = lists:member("echo_drv",element(2,erl_ddll:loaded_drivers())),
+ Path = proplists:get_value(data_dir, Config),
+ false = lists:member("echo_drv",element(2,erl_ddll:loaded_drivers())),
Parent = self(),
- ?line Pid = spawn(fun() ->
- receive go -> ok end,
- erl_ddll:try_load(Path, echo_drv, []),
- Parent ! gone,
- receive go -> ok end,
- erl_ddll:loaded_drivers(),
- exit(banan)
- end),
- ?line Ref = erlang:monitor(process,Pid),
- ?line false = lists:member("echo_drv",element(2,erl_ddll:loaded_drivers())),
+ Pid = spawn(fun() ->
+ receive go -> ok end,
+ erl_ddll:try_load(Path, echo_drv, []),
+ Parent ! gone,
+ receive go -> ok end,
+ erl_ddll:loaded_drivers(),
+ exit(banan)
+ end),
+ Ref = erlang:monitor(process,Pid),
+ false = lists:member("echo_drv",element(2,erl_ddll:loaded_drivers())),
Pid ! go,
- ?line receive
- gone -> ok
+ receive
+ gone -> ok
end,
- ?line true = lists:member("echo_drv",element(2,erl_ddll:loaded_drivers())),
+ true = lists:member("echo_drv",element(2,erl_ddll:loaded_drivers())),
Pid ! go,
- ?line receive
- {'DOWN', Ref, process, Pid, banan} ->
- ok
+ receive
+ {'DOWN', Ref, process, Pid, banan} ->
+ ok
end,
receive after 500 -> ok end,
- ?line false = lists:member("echo_drv",element(2,erl_ddll:loaded_drivers())),
- ?line test_server:timetrap_cancel(Dog),
+ false = lists:member("echo_drv",element(2,erl_ddll:loaded_drivers())),
ok.
-delayed_unload_with_ports(suite) ->
- [];
-delayed_unload_with_ports(doc) ->
- ["Check that the driver is unloaded when the last port is closed"];
+%% Check that the driver is unloaded when the last port is closed
delayed_unload_with_ports(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line erl_ddll:try_load(Path, echo_drv, []),
- ?line erl_ddll:try_load(Path, echo_drv, []),
- ?line Port = open_port({spawn, echo_drv}, [eof]),
- ?line 1 = erl_ddll:info(echo_drv, port_count),
- ?line Port2 = open_port({spawn, echo_drv}, [eof]),
- ?line 2 = erl_ddll:info(echo_drv, port_count),
- ?line {ok,pending_process} = erl_ddll:try_unload(echo_drv,[{monitor, pending_driver}]),
- ?line {ok,pending_driver,Ref} = erl_ddll:try_unload(echo_drv,[{monitor, pending_driver}]),
- ?line ok = receive _ -> false after 0 -> ok end,
- ?line Port ! {self(), close},
- ?line ok = receive {Port,closed} -> ok after 1000 -> false end,
- ?line 1 = erl_ddll:info(echo_drv, port_count),
- ?line Port2 ! {self(), close},
- ?line ok = receive {Port2,closed} -> ok after 1000 -> false end,
- ?line ok = receive {'DOWN', Ref, driver, echo_drv, unloaded} -> ok after 1000 -> false end,
- ?line test_server:timetrap_cancel(Dog),
+ Path = proplists:get_value(data_dir, Config),
+ erl_ddll:try_load(Path, echo_drv, []),
+ erl_ddll:try_load(Path, echo_drv, []),
+ Port = open_port({spawn, echo_drv}, [eof]),
+ 1 = erl_ddll:info(echo_drv, port_count),
+ Port2 = open_port({spawn, echo_drv}, [eof]),
+ 2 = erl_ddll:info(echo_drv, port_count),
+ {ok,pending_process} = erl_ddll:try_unload(echo_drv,[{monitor, pending_driver}]),
+ {ok,pending_driver,Ref} = erl_ddll:try_unload(echo_drv,[{monitor, pending_driver}]),
+ ok = receive _ -> false after 0 -> ok end,
+ Port ! {self(), close},
+ ok = receive {Port,closed} -> ok after 1000 -> false end,
+ 1 = erl_ddll:info(echo_drv, port_count),
+ Port2 ! {self(), close},
+ ok = receive {Port2,closed} -> ok after 1000 -> false end,
+ ok = receive {'DOWN', Ref, driver, echo_drv, unloaded} -> ok after 1000 -> false end,
ok.
-unload_due_to_process_exit(suite) ->
- [];
-unload_due_to_process_exit(doc) ->
- ["Check that the driver with ports is unloaded on process exit"];
+%% Check that the driver with ports is unloaded on process exit
unload_due_to_process_exit(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line Parent = self(),
- ?line F3 = fun() ->
- Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
- receive X -> Parent ! {got,X} end
- end,
- ?line Pid = spawn(fun() ->
- receive go -> ok end,
- {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
- spawn(F3),
- receive go -> ok end,
- _Port = open_port({spawn, echo_drv}, [eof]),
- _Port2 = open_port({spawn, echo_drv}, [eof]),
- exit(banan)
- end),
- ?line Ref = erlang:monitor(process,Pid),
+ Path = proplists:get_value(data_dir, Config),
+ Parent = self(),
+ F3 = fun() ->
+ Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
+ receive X -> Parent ! {got,X} end
+ end,
+ Pid = spawn(fun() ->
+ receive go -> ok end,
+ {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
+ spawn(F3),
+ receive go -> ok end,
+ _Port = open_port({spawn, echo_drv}, [eof]),
+ _Port2 = open_port({spawn, echo_drv}, [eof]),
+ exit(banan)
+ end),
+ Ref = erlang:monitor(process,Pid),
Pid ! go,
- ?line {ok,Ref2} = receive
- R when is_reference(R) -> {ok,R};
- Other -> {error, Other}
- after 500 -> {error, timeout}
- end,
+ {ok,Ref2} = receive
+ R when is_reference(R) -> {ok,R};
+ Other -> {error, Other}
+ after 500 -> {error, timeout}
+ end,
Pid ! go,
- ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
- ?line ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end,
- ?line test_server:timetrap_cancel(Dog),
+ ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
+ ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end,
ok.
-no_unload_due_to_process_exit(suite) ->
- [];
-no_unload_due_to_process_exit(doc) ->
- ["Check that a driver with driver loaded in another process is not unloaded on process exit"];
+%% Check that a driver with driver loaded in another process is not unloaded on process exit
no_unload_due_to_process_exit(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line Parent = self(),
- ?line F3 = fun() ->
- Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
- receive X -> Parent ! {got,X} end
- end,
- ?line Pid = spawn(fun() ->
- receive go -> ok end,
- {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
- spawn(F3),
- receive go -> ok end,
- _Port = open_port({spawn, echo_drv}, [eof]),
- _Port2 = open_port({spawn, echo_drv}, [eof]),
- exit(banan)
- end),
- ?line Ref = erlang:monitor(process,Pid),
+ Path = proplists:get_value(data_dir, Config),
+ Parent = self(),
+ F3 = fun() ->
+ Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
+ receive X -> Parent ! {got,X} end
+ end,
+ Pid = spawn(fun() ->
+ receive go -> ok end,
+ {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
+ spawn(F3),
+ receive go -> ok end,
+ _Port = open_port({spawn, echo_drv}, [eof]),
+ _Port2 = open_port({spawn, echo_drv}, [eof]),
+ exit(banan)
+ end),
+ Ref = erlang:monitor(process,Pid),
Pid ! go,
- ?line {ok,Ref2} = receive
- R when is_reference(R) -> {ok,R};
- Other -> {error, Other}
- after 500 -> {error, timeout}
- end,
- ?line {ok, already_loaded} = erl_ddll:try_load(Path, echo_drv, []),
+ {ok,Ref2} = receive
+ R when is_reference(R) -> {ok,R};
+ Other -> {error, Other}
+ after 500 -> {error, timeout}
+ end,
+ {ok, already_loaded} = erl_ddll:try_load(Path, echo_drv, []),
Pid ! go,
- ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
- ?line ok = receive X -> {error, X} after 300 -> ok end,
- ?line ok = unload_expect_fast(echo_drv,[]),
- ?line ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end,
- ?line test_server:timetrap_cancel(Dog),
+ ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
+ ok = receive X -> {error, X} after 300 -> ok end,
+ ok = unload_expect_fast(echo_drv,[]),
+ ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end,
ok.
-no_unload_due_to_process_exit_2(suite) ->
- [];
-no_unload_due_to_process_exit_2(doc) ->
- ["Check that a driver with open ports in another process is not unloaded on process exit"];
+%% Check that a driver with open ports in another process is not unloaded on process exit
no_unload_due_to_process_exit_2(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line Parent = self(),
- ?line F3 = fun() ->
- Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
- receive X -> Parent ! {got,X} end
- end,
- ?line Pid = spawn(fun() ->
- receive go -> ok end,
- {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
- spawn(F3),
- receive go -> ok end,
- _Port = open_port({spawn, echo_drv}, [eof]),
- _Port2 = open_port({spawn, echo_drv}, [eof]),
- exit(banan)
- end),
- ?line Ref = erlang:monitor(process,Pid),
+ Path = proplists:get_value(data_dir, Config),
+ Parent = self(),
+ F3 = fun() ->
+ Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
+ receive X -> Parent ! {got,X} end
+ end,
+ Pid = spawn(fun() ->
+ receive go -> ok end,
+ {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
+ spawn(F3),
+ receive go -> ok end,
+ _Port = open_port({spawn, echo_drv}, [eof]),
+ _Port2 = open_port({spawn, echo_drv}, [eof]),
+ exit(banan)
+ end),
+ Ref = erlang:monitor(process,Pid),
Pid ! go,
- ?line {ok,Ref2} = receive
- R when is_reference(R) -> {ok,R};
- Other -> {error, Other}
- after 500 -> {error, timeout}
- end,
- ?line Port = open_port({spawn, echo_drv}, [eof]),
+ {ok,Ref2} = receive
+ R when is_reference(R) -> {ok,R};
+ Other -> {error, Other}
+ after 500 -> {error, timeout}
+ end,
+ Port = open_port({spawn, echo_drv}, [eof]),
Pid ! go,
- ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
- ?line ok = receive X -> {error, X} after 300 -> ok end,
- ?line erlang:port_close(Port),
- ?line ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end,
- ?line test_server:timetrap_cancel(Dog),
+ ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
+ ok = receive X -> {error, X} after 300 -> ok end,
+ erlang:port_close(Port),
+ ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end,
ok.
-unload_reload_thingie(suite) ->
- [];
-unload_reload_thingie(doc) ->
- ["Check delayed unload and reload"];
+%% Check delayed unload and reload
unload_reload_thingie(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line Parent = self(),
- ?line {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
- ?line F3 = fun() ->
- Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded_only}),
- receive X -> Parent ! {got,X} end
- end,
- ?line Pid = spawn(fun() ->
- receive go -> ok end,
- _Port = open_port({spawn, echo_drv}, [eof]),
- spawn(F3),
- receive go -> ok end,
- exit(banan)
- end),
- ?line Ref = erlang:monitor(process,Pid),
+ Path = proplists:get_value(data_dir, Config),
+ Parent = self(),
+ {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
+ F3 = fun() ->
+ Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded_only}),
+ receive X -> Parent ! {got,X} end
+ end,
+ Pid = spawn(fun() ->
+ receive go -> ok end,
+ _Port = open_port({spawn, echo_drv}, [eof]),
+ spawn(F3),
+ receive go -> ok end,
+ exit(banan)
+ end),
+ Ref = erlang:monitor(process,Pid),
+ Pid ! go,
+ {ok,Ref2} = receive
+ R when is_reference(R) -> {ok,R};
+ Other -> {error, Other}
+ after 500 -> {error, timeout}
+ end,
+ {ok,pending_driver,Ref3} = erl_ddll:try_unload(echo_drv,[{monitor,pending}]),
+ Ref4 = erl_ddll:monitor(driver,{echo_drv,loaded}),
+ ok = receive {'DOWN',Ref4, driver,echo_drv,load_cancelled} -> ok after 1000 -> false end,
+ {ok,already_loaded} = erl_ddll:try_load(Path, echo_drv, []),
+ ok = receive {'UP',Ref3, driver,echo_drv,unload_cancelled} -> ok after 1000 -> false end,
Pid ! go,
- ?line {ok,Ref2} = receive
- R when is_reference(R) -> {ok,R};
- Other -> {error, Other}
- after 500 -> {error, timeout}
- end,
- ?line {ok,pending_driver,Ref3} = erl_ddll:try_unload(echo_drv,[{monitor,pending}]),
- ?line Ref4 = erl_ddll:monitor(driver,{echo_drv,loaded}),
- ?line ok = receive {'DOWN',Ref4, driver,echo_drv,load_cancelled} -> ok after 1000 -> false end,
- ?line {ok,already_loaded} = erl_ddll:try_load(Path, echo_drv, []),
- ?line ok = receive {'UP',Ref3, driver,echo_drv,unload_cancelled} -> ok after 1000 -> false end,
- ?line Pid ! go,
- ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
- ?line [{Parent,1}] = erl_ddll:info(echo_drv, processes),
- ?line 0 = erl_ddll:info(echo_drv, port_count),
- ?line ok = unload_expect_fast(echo_drv,[{monitor,pending}]),
- ?line ok = receive
- {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok
- after 300 -> error
- end,
- ?line ok = receive X -> {error, X} after 300 -> ok end,
- ?line test_server:timetrap_cancel(Dog),
+ ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
+ [{Parent,1}] = erl_ddll:info(echo_drv, processes),
+ 0 = erl_ddll:info(echo_drv, port_count),
+ ok = unload_expect_fast(echo_drv,[{monitor,pending}]),
+ ok = receive
+ {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok
+ after 300 -> error
+ end,
+ ok = receive X -> {error, X} after 300 -> ok end,
ok.
-unload_reload_thingie_2(suite) ->
- [];
-unload_reload_thingie_2(doc) ->
- ["Check delayed unload and reload"];
+%% Check delayed unload and reload
unload_reload_thingie_2(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line Parent = self(),
- ?line {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
- ?line F3 = fun() ->
- Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded_only}),
- receive X -> Parent ! {got,X} end
- end,
- ?line Pid = spawn(fun() ->
- receive go -> ok end,
- _Port = open_port({spawn, echo_drv}, [eof]),
- spawn(F3),
- receive go -> ok end,
- exit(banan)
- end),
- ?line Ref = erlang:monitor(process,Pid),
+ Path = proplists:get_value(data_dir, Config),
+ Parent = self(),
+ {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
+ F3 = fun() ->
+ Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded_only}),
+ receive X -> Parent ! {got,X} end
+ end,
+ Pid = spawn(fun() ->
+ receive go -> ok end,
+ _Port = open_port({spawn, echo_drv}, [eof]),
+ spawn(F3),
+ receive go -> ok end,
+ exit(banan)
+ end),
+ Ref = erlang:monitor(process,Pid),
+ Pid ! go,
+ {ok,Ref2} = receive
+ R when is_reference(R) -> {ok,R};
+ Other -> {error, Other}
+ after 500 -> {error, timeout}
+ end,
+ {ok,pending_driver,Ref3} = erl_ddll:try_load(Path, echo_drv,
+ [{monitor,pending_driver},{reload,pending_driver}]),
+ Ref4 = erl_ddll:monitor(driver,{echo_drv,unloaded}),
Pid ! go,
- ?line {ok,Ref2} = receive
- R when is_reference(R) -> {ok,R};
- Other -> {error, Other}
- after 500 -> {error, timeout}
- end,
- ?line {ok,pending_driver,Ref3} = erl_ddll:try_load(Path,echo_drv,[{monitor,pending_driver},{reload,pending_driver}]),
- ?line Ref4 = erl_ddll:monitor(driver,{echo_drv,unloaded}),
- ?line Pid ! go,
- ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
- ?line ok = receive {'DOWN',Ref4, driver,echo_drv,unloaded} -> ok after 1000 -> false end,
- ?line ok = receive {'UP',Ref3, driver,echo_drv,loaded} -> ok after 1000 -> false end,
- ?line [{Parent,1}] = erl_ddll:info(echo_drv, processes),
- ?line 0 = erl_ddll:info(echo_drv, port_count),
- ?line ok = receive
- {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok
- after 300 -> error
- end,
- ?line ok = unload_expect_fast(echo_drv,[{monitor,pending}]),
- ?line ok = receive X -> {error, X} after 300 -> ok end,
- ?line test_server:timetrap_cancel(Dog),
+ ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
+ ok = receive {'DOWN',Ref4, driver,echo_drv,unloaded} -> ok after 1000 -> false end,
+ ok = receive {'UP',Ref3, driver,echo_drv,loaded} -> ok after 1000 -> false end,
+ [{Parent,1}] = erl_ddll:info(echo_drv, processes),
+ 0 = erl_ddll:info(echo_drv, port_count),
+ ok = receive
+ {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok
+ after 300 -> error
+ end,
+ ok = unload_expect_fast(echo_drv,[{monitor,pending}]),
+ ok = receive X -> {error, X} after 300 -> ok end,
ok.
-unload_reload_thingie_3(suite) ->
- [];
-unload_reload_thingie_3(doc) ->
- ["Check delayed unload and reload failure"];
+%% Check delayed unload and reload failure
unload_reload_thingie_3(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line Parent = self(),
- ?line {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
- ?line F3 = fun() ->
- Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
- receive X -> Parent ! {got,X} end
- end,
- ?line Pid = spawn(fun() ->
- receive go -> ok end,
- _Port = open_port({spawn, echo_drv}, [eof]),
- spawn(F3),
- receive go -> ok end,
- exit(banan)
- end),
- ?line Ref = erlang:monitor(process,Pid),
+ Path = proplists:get_value(data_dir, Config),
+ Parent = self(),
+ {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
+ F3 = fun() ->
+ Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
+ receive X -> Parent ! {got,X} end
+ end,
+ Pid = spawn(fun() ->
+ receive go -> ok end,
+ _Port = open_port({spawn, echo_drv}, [eof]),
+ spawn(F3),
+ receive go -> ok end,
+ exit(banan)
+ end),
+ Ref = erlang:monitor(process,Pid),
+ Pid ! go,
+ {ok,Ref2} = receive
+ R when is_reference(R) -> {ok,R};
+ Other -> {error, Other}
+ after 500 -> {error, timeout}
+ end,
+ {ok,pending_driver,Ref3} = erl_ddll:try_load(filename:join([Path,"skrumpf"]), echo_drv,
+ [{monitor,pending_driver},{reload,pending_driver}]),
+ Ref4 = erl_ddll:monitor(driver,{echo_drv,unloaded}),
Pid ! go,
- ?line {ok,Ref2} = receive
- R when is_reference(R) -> {ok,R};
- Other -> {error, Other}
- after 500 -> {error, timeout}
- end,
- ?line {ok,pending_driver,Ref3} = erl_ddll:try_load(filename:join([Path,"skrumpf"]),echo_drv,[{monitor,pending_driver},{reload,pending_driver}]),
- ?line Ref4 = erl_ddll:monitor(driver,{echo_drv,unloaded}),
- ?line Pid ! go,
- ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
- ?line ok = receive
- {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok
- after 300 -> error
- end,
- ?line ok = receive {'DOWN',Ref4,driver,echo_drv,unloaded} -> ok after 300 -> false end,
- ?line ok = receive
- {'DOWN',Ref3, driver,echo_drv,{load_failure,_}} -> ok
- after 1000 -> false
- end,
- ?line {'EXIT',_} = (catch erl_ddll:info(echo_drv, port_count)),
- ?line {error, not_loaded} = erl_ddll:try_unload(echo_drv,[{monitor,pending}]),
- ?line ok = receive X -> {error, X} after 300 -> ok end,
- ?line test_server:timetrap_cancel(Dog),
+ ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
+ ok = receive
+ {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok
+ after 300 -> error
+ end,
+ ok = receive {'DOWN',Ref4,driver,echo_drv,unloaded} -> ok after 300 -> false end,
+ ok = receive
+ {'DOWN',Ref3, driver,echo_drv,{load_failure,_}} -> ok
+ after 1000 -> false
+ end,
+ {'EXIT',_} = (catch erl_ddll:info(echo_drv, port_count)),
+ {error, not_loaded} = erl_ddll:try_unload(echo_drv,[{monitor,pending}]),
+ ok = receive X -> {error, X} after 300 -> ok end,
ok.
-reload_pending(suite) -> [];
-reload_pending(doc) -> ["Reload a driver that is pending on a user"];
+%% Reload a driver that is pending on a user
reload_pending(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line Parent = self(),
- ?line F3 = fun() ->
- Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
- receive X -> Parent ! {got,X} end
- end,
- ?line Pid = spawn(fun() ->
- receive go -> ok end,
- {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
- spawn(F3),
- receive go -> ok end,
- _Port = open_port({spawn, echo_drv}, [eof]),
- _Port2 = open_port({spawn, echo_drv}, [eof]),
- Parent ! opened,
- receive go -> ok end,
- exit(banan)
- end),
- ?line Ref = erlang:monitor(process,Pid),
+ Path = proplists:get_value(data_dir, Config),
+ Parent = self(),
+ F3 = fun() ->
+ Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
+ receive X -> Parent ! {got,X} end
+ end,
+ Pid = spawn(fun() ->
+ receive go -> ok end,
+ {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
+ spawn(F3),
+ receive go -> ok end,
+ _Port = open_port({spawn, echo_drv}, [eof]),
+ _Port2 = open_port({spawn, echo_drv}, [eof]),
+ Parent ! opened,
+ receive go -> ok end,
+ exit(banan)
+ end),
+ Ref = erlang:monitor(process,Pid),
Pid ! go,
- ?line {ok,Ref2} = receive
- R when is_reference(R) -> {ok,R};
- Other -> {error, Other}
- after 500 -> {error, timeout}
- end,
- ?line {ok, already_loaded} = erl_ddll:try_load(Path, echo_drv, []),
- ?line Port = open_port({spawn, echo_drv}, [eof]),
+ {ok,Ref2} = receive
+ R when is_reference(R) -> {ok,R};
+ Other -> {error, Other}
+ after 500 -> {error, timeout}
+ end,
+ {ok, already_loaded} = erl_ddll:try_load(Path, echo_drv, []),
+ Port = open_port({spawn, echo_drv}, [eof]),
Pid ! go,
- ?line receive opened -> ok end,
- ?line {error, pending_process} =
- erl_ddll:try_load(Path, echo_drv,
- [{reload,pending_driver},
- {monitor,pending_driver}]),
- ?line {ok, pending_process, Ref3} =
- erl_ddll:try_load(Path, echo_drv,
- [{reload,pending},
- {monitor,pending}]),
- ?line ok = receive X -> {error, X} after 300 -> ok end,
+ receive opened -> ok end,
+ {error, pending_process} =
+ erl_ddll:try_load(Path, echo_drv,
+ [{reload,pending_driver},
+ {monitor,pending_driver}]),
+ {ok, pending_process, Ref3} =
+ erl_ddll:try_load(Path, echo_drv,
+ [{reload,pending},
+ {monitor,pending}]),
+ ok = receive X -> {error, X} after 300 -> ok end,
Pid ! go,
- ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
- ?line ok = receive Y -> {error, Y} after 300 -> ok end,
- ?line erlang:port_close(Port),
- ?line ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end,
- ?line ok = receive {'UP', Ref3, driver, echo_drv, loaded} -> ok after 300 -> error end,
+ ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
+ ok = receive Y -> {error, Y} after 300 -> ok end,
+ erlang:port_close(Port),
+ ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end,
+ ok = receive {'UP', Ref3, driver, echo_drv, loaded} -> ok after 300 -> error end,
[{Parent,1}] = erl_ddll:info(echo_drv,processes),
- ?line ok = receive Z -> {error, Z} after 300 -> ok end,
- ?line test_server:timetrap_cancel(Dog),
+ ok = receive Z -> {error, Z} after 300 -> ok end,
ok.
-load_fail_init(suite) -> [];
-load_fail_init(doc) -> ["Tests failure in the init in driver struct."];
+%% Tests failure in the init in driver struct.
load_fail_init(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line PathFailing = ?config(priv_dir, Config),
- ?line [_|_] = AllFailInits = filelib:wildcard("echo_drv_fail_init.*",Path),
- ?line lists:foreach(fun(Name) ->
- Src = filename:join([Path,Name]),
- Ext = filename:extension(Name),
- Dst =filename:join([PathFailing,"echo_drv"++Ext]),
- file:delete(Dst),
- {ok,_} = file:copy(Src,Dst)
- end,
- AllFailInits),
- ?line [_|_] = filelib:wildcard("echo_drv.*",PathFailing),
- ?line {error, driver_init_failed} = erl_ddll:try_load(PathFailing,
- echo_drv,
- [{monitor,pending}]),
- ?line ok = receive XX ->
- {unexpected,XX}
- after 300 ->
- ok
- end,
- ?line test_server:timetrap_cancel(Dog),
+ Path = proplists:get_value(data_dir, Config),
+ PathFailing = proplists:get_value(priv_dir, Config),
+ [_|_] = AllFailInits = filelib:wildcard("echo_drv_fail_init.*",Path),
+ lists:foreach(fun(Name) ->
+ Src = filename:join([Path,Name]),
+ Ext = filename:extension(Name),
+ Dst =filename:join([PathFailing,"echo_drv"++Ext]),
+ file:delete(Dst),
+ {ok,_} = file:copy(Src,Dst)
+ end,
+ AllFailInits),
+ [_|_] = filelib:wildcard("echo_drv.*",PathFailing),
+ {error, driver_init_failed} = erl_ddll:try_load(PathFailing,
+ echo_drv,
+ [{monitor,pending}]),
+ ok = receive XX ->
+ {unexpected,XX}
+ after 300 ->
+ ok
+ end,
ok.
-reload_pending_fail_init(suite) -> [];
-reload_pending_fail_init(doc) -> ["Reload a driver that is pending but init fails"];
+%% Reload a driver that is pending but init fails
reload_pending_fail_init(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line PathFailing = ?config(priv_dir, Config),
- ?line [_|_] = AllFailInits = filelib:wildcard("echo_drv_fail_init.*",Path),
- ?line lists:foreach(fun(Name) ->
- Src = filename:join([Path,Name]),
- Ext = filename:extension(Name),
- Dst =filename:join([PathFailing,"echo_drv"++Ext]),
- file:delete(Dst),
- {ok,_} = file:copy(Src,Dst)
- end,
- AllFailInits),
- ?line [_|_] = filelib:wildcard("echo_drv.*",PathFailing),
- ?line Parent = self(),
- ?line F3 = fun() ->
- Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
- receive X -> Parent ! {got,X} end
- end,
- ?line Pid = spawn(fun() ->
- receive go -> ok end,
- {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
- spawn(F3),
- receive go -> ok end,
- _Port = open_port({spawn, echo_drv}, [eof]),
- _Port2 = open_port({spawn, echo_drv}, [eof]),
- Parent ! opened,
- receive go -> ok end,
- exit(banan)
- end),
- ?line Ref = erlang:monitor(process,Pid),
+ Path = proplists:get_value(data_dir, Config),
+ PathFailing = proplists:get_value(priv_dir, Config),
+ [_|_] = AllFailInits = filelib:wildcard("echo_drv_fail_init.*",Path),
+ lists:foreach(fun(Name) ->
+ Src = filename:join([Path,Name]),
+ Ext = filename:extension(Name),
+ Dst =filename:join([PathFailing,"echo_drv"++Ext]),
+ file:delete(Dst),
+ {ok,_} = file:copy(Src,Dst)
+ end,
+ AllFailInits),
+ [_|_] = filelib:wildcard("echo_drv.*",PathFailing),
+ Parent = self(),
+ F3 = fun() ->
+ Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
+ receive X -> Parent ! {got,X} end
+ end,
+ Pid = spawn(fun() ->
+ receive go -> ok end,
+ {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
+ spawn(F3),
+ receive go -> ok end,
+ _Port = open_port({spawn, echo_drv}, [eof]),
+ _Port2 = open_port({spawn, echo_drv}, [eof]),
+ Parent ! opened,
+ receive go -> ok end,
+ exit(banan)
+ end),
+ Ref = erlang:monitor(process,Pid),
Pid ! go,
- ?line {ok,Ref2} = receive
- R when is_reference(R) -> {ok,R};
- Other -> {error, Other}
- after 500 -> {error, timeout}
- end,
- ?line {ok, already_loaded} = erl_ddll:try_load(Path, echo_drv, []),
- ?line Port = open_port({spawn, echo_drv}, [eof]),
+ {ok,Ref2} = receive
+ R when is_reference(R) -> {ok,R};
+ Other -> {error, Other}
+ after 500 -> {error, timeout}
+ end,
+ {ok, already_loaded} = erl_ddll:try_load(Path, echo_drv, []),
+ Port = open_port({spawn, echo_drv}, [eof]),
Pid ! go,
- ?line receive opened -> ok end,
- ?line {ok, pending_process, Ref3} =
- erl_ddll:try_load(PathFailing, echo_drv,
- [{reload,pending},
- {monitor,pending}]),
- ?line ok = receive X -> {error, X} after 300 -> ok end,
+ receive opened -> ok end,
+ {ok, pending_process, Ref3} =
+ erl_ddll:try_load(PathFailing, echo_drv,
+ [{reload,pending},
+ {monitor,pending}]),
+ ok = receive X -> {error, X} after 300 -> ok end,
Pid ! go,
- ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
- ?line ok = receive Y -> {error, Y} after 300 -> ok end,
- ?line erlang:port_close(Port),
- ?line ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end,
- ?line ok = receive {'DOWN', Ref3, driver, echo_drv, {load_failure,driver_init_failed}} -> ok after 300 -> error end,
- ?line {'EXIT',{badarg,_}} = (catch erl_ddll:info(echo_drv,processes)),
-
- ?line ok = receive Z -> {error, Z} after 300 -> ok end,
- ?line test_server:timetrap_cancel(Dog),
+ ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
+ ok = receive Y -> {error, Y} after 300 -> ok end,
+ erlang:port_close(Port),
+ ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end,
+ ok = receive {'DOWN', Ref3, driver, echo_drv, {load_failure,driver_init_failed}} -> ok after 300 -> error end,
+ {'EXIT',{badarg,_}} = (catch erl_ddll:info(echo_drv,processes)),
+
+ ok = receive Z -> {error, Z} after 300 -> ok end,
ok.
-reload_pending_kill(suite) -> [];
-reload_pending_kill(doc) -> ["Reload a driver with kill_ports option "
- "that is pending on a user"];
+%% Reload a driver with kill_ports option that is pending on a user
reload_pending_kill(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line OldFlag = process_flag(trap_exit,true),
- ?line Path = ?config(data_dir, Config),
- ?line Parent = self(),
- ?line F3 = fun() ->
- Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
- receive X -> Parent ! {got,X} end
- end,
- ?line Pid = spawn(fun() ->
- process_flag(trap_exit,true),
- receive go -> ok end,
- {ok, loaded} = erl_ddll:try_load(Path, echo_drv, [{driver_options,[kill_ports]}]),
- spawn(F3),
- receive go -> ok end,
- Port = open_port({spawn, echo_drv}, [eof]),
- Port2 = open_port({spawn, echo_drv}, [eof]),
- Parent ! opened,
- receive go -> ok end,
- receive
- {'EXIT', Port2, driver_unloaded} ->
- Parent ! first_exit
- end,
- receive
- {'EXIT', Port, driver_unloaded} ->
- Parent ! second_exit
- end,
- receive go -> ok end,
- exit(banan)
- end),
- ?line Ref = erlang:monitor(process,Pid),
+ OldFlag = process_flag(trap_exit,true),
+ Path = proplists:get_value(data_dir, Config),
+ Parent = self(),
+ F3 = fun() ->
+ Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
+ receive X -> Parent ! {got,X} end
+ end,
+ Pid = spawn(fun() ->
+ process_flag(trap_exit,true),
+ receive go -> ok end,
+ {ok, loaded} = erl_ddll:try_load(Path, echo_drv, [{driver_options,[kill_ports]}]),
+ spawn(F3),
+ receive go -> ok end,
+ Port = open_port({spawn, echo_drv}, [eof]),
+ Port2 = open_port({spawn, echo_drv}, [eof]),
+ Parent ! opened,
+ receive go -> ok end,
+ receive
+ {'EXIT', Port2, driver_unloaded} ->
+ Parent ! first_exit
+ end,
+ receive
+ {'EXIT', Port, driver_unloaded} ->
+ Parent ! second_exit
+ end,
+ receive go -> ok end,
+ exit(banan)
+ end),
+ Ref = erlang:monitor(process,Pid),
Pid ! go,
- ?line {ok,Ref2} = receive
- R when is_reference(R) -> {ok,R};
- Other -> {error, Other}
- after 500 -> {error, timeout}
- end,
- ?line {ok, already_loaded} = erl_ddll:try_load(Path, echo_drv, [{driver_options,[kill_ports]}]),
- ?line {error,inconsistent} = erl_ddll:try_load(Path, echo_drv, []),
- ?line Port = open_port({spawn, echo_drv}, [eof]),
+ {ok,Ref2} = receive
+ R when is_reference(R) -> {ok,R};
+ Other -> {error, Other}
+ after 500 -> {error, timeout}
+ end,
+ {ok, already_loaded} = erl_ddll:try_load(Path, echo_drv, [{driver_options,[kill_ports]}]),
+ {error,inconsistent} = erl_ddll:try_load(Path, echo_drv, []),
+ Port = open_port({spawn, echo_drv}, [eof]),
Pid ! go,
- ?line receive opened -> ok end,
- ?line {error, pending_process} =
- erl_ddll:try_load(Path, echo_drv,
- [{driver_options,[kill_ports]},
- {reload,pending_driver},
- {monitor,pending_driver}]),
- ?line {ok, pending_process, Ref3} =
- erl_ddll:try_load(Path, echo_drv,
- [{driver_options,[kill_ports]},
- {reload,pending},
- {monitor,pending}]),
- ?line ok = receive
- {'EXIT', Port, driver_unloaded} ->
- ok
- after 300 -> error
- end,
+ receive opened -> ok end,
+ {error, pending_process} =
+ erl_ddll:try_load(Path, echo_drv,
+ [{driver_options,[kill_ports]},
+ {reload,pending_driver},
+ {monitor,pending_driver}]),
+ {ok, pending_process, Ref3} =
+ erl_ddll:try_load(Path, echo_drv,
+ [{driver_options,[kill_ports]},
+ {reload,pending},
+ {monitor,pending}]),
+ ok = receive
+ {'EXIT', Port, driver_unloaded} ->
+ ok
+ after 300 -> error
+ end,
Pid ! go,
- ?line ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end,
- ?line ok = receive {'UP', Ref3, driver, echo_drv, loaded} -> ok after 300 -> error end,
- ?line [_,_] = erl_ddll:info(echo_drv,processes),
- ?line ok = receive first_exit -> ok after 300 -> error end,
- ?line ok = receive second_exit -> ok after 300 -> error end,
- ?line 0 = erl_ddll:info(echo_drv,port_count),
- ?line ok = receive X -> {error, X} after 300 -> ok end,
+ ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end,
+ ok = receive {'UP', Ref3, driver, echo_drv, loaded} -> ok after 300 -> error end,
+ [_,_] = erl_ddll:info(echo_drv,processes),
+ ok = receive first_exit -> ok after 300 -> error end,
+ ok = receive second_exit -> ok after 300 -> error end,
+ 0 = erl_ddll:info(echo_drv,port_count),
+ ok = receive X -> {error, X} after 300 -> ok end,
Pid ! go,
- ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
- ?line ok = receive Y -> {error, Y} after 300 -> ok end,
- ?line Port2 = open_port({spawn, echo_drv}, [eof]),
- ?line true = is_port(Port2),
+ ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
+ ok = receive Y -> {error, Y} after 300 -> ok end,
+ Port2 = open_port({spawn, echo_drv}, [eof]),
+ true = is_port(Port2),
[{Parent,1}] = erl_ddll:info(echo_drv,processes),
- ?line 1 = erl_ddll:info(echo_drv,port_count),
- ?line erlang:port_close(Port2),
- ?line ok = receive {'EXIT', Port2, normal} -> ok after 300 -> error end,
- ?line 0 = erl_ddll:info(echo_drv,port_count),
- ?line [{Parent,1}] = erl_ddll:info(echo_drv,processes),
- ?line Port3 = open_port({spawn, echo_drv}, [eof]),
- ?line {ok, pending_driver, Ref4} =
- erl_ddll:try_unload(echo_drv,[{monitor,pending_driver}]),
- ?line ok = receive
- {'EXIT', Port3, driver_unloaded} ->
- ok
- after 300 -> error
- end,
- ?line ok = receive {'DOWN', Ref4, driver, echo_drv, unloaded} -> ok after 300 -> error end,
+ 1 = erl_ddll:info(echo_drv,port_count),
+ erlang:port_close(Port2),
+ ok = receive {'EXIT', Port2, normal} -> ok after 300 -> error end,
+ 0 = erl_ddll:info(echo_drv,port_count),
+ [{Parent,1}] = erl_ddll:info(echo_drv,processes),
+ Port3 = open_port({spawn, echo_drv}, [eof]),
+ {ok, pending_driver, Ref4} =
+ erl_ddll:try_unload(echo_drv,[{monitor,pending_driver}]),
+ ok = receive
+ {'EXIT', Port3, driver_unloaded} ->
+ ok
+ after 300 -> error
+ end,
+ ok = receive {'DOWN', Ref4, driver, echo_drv, unloaded} -> ok after 300 -> error end,
io:format("Port = ~w, Port2 = ~w, Port3 = ~w~n",[Port,Port2,Port3]),
- ?line ok = receive Z -> {error, Z} after 300 -> ok end,
- ?line process_flag(trap_exit,OldFlag),
- ?line test_server:timetrap_cancel(Dog),
+ ok = receive Z -> {error, Z} after 300 -> ok end,
+ process_flag(trap_exit,OldFlag),
ok.
-more_error_codes(suite) ->
- [];
-more_error_codes(doc) ->
- ["Some more error code checking"];
+%% Some more error code checking
more_error_codes(Config) when is_list(Config) ->
- ?line {error,Err} = erl_ddll:try_load("./echo_dr",echo_dr,[]),
- ?line true = is_list(erl_ddll:format_error(Err)),
- ?line true = is_list(erl_ddll:format_error(not_loaded)),
+ {error,Err} = erl_ddll:try_load("./echo_dr",echo_dr,[]),
+ true = is_list(erl_ddll:format_error(Err)),
+ true = is_list(erl_ddll:format_error(not_loaded)),
ok.
-forced_port_killing(suite) ->
- [];
-forced_port_killing(doc) ->
- ["Check kill_ports option to try_unload "];
+%% Check kill_ports option to try_unload
forced_port_killing(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line OldFlag=process_flag(trap_exit,true),
- ?line Parent = self(),
- ?line F3 = fun() ->
- Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
- receive X -> Parent ! {got,X} end
- end,
- ?line {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
- ?line spawn(F3),
- ?line {ok,Ref2} = receive
- R when is_reference(R) -> {ok,R};
- Other -> {error, Other}
- after 500 -> {error, timeout}
- end,
- ?line Port = open_port({spawn, echo_drv}, [eof]),
- ?line Port2 = open_port({spawn, echo_drv}, [eof]),
- ?line {ok, pending_driver, Ref1} =
- erl_ddll:try_unload(echo_drv,[{monitor,pending_driver},kill_ports]),
- ?line ok = receive
- {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok
- after 300 -> error
- end,
- ?line ok = receive {'EXIT',Port,driver_unloaded} -> ok after 300 -> false end,
- ?line ok = receive {'EXIT',Port2,driver_unloaded} -> ok after 300 -> false end,
- ?line ok = receive {'DOWN',Ref1, driver, echo_drv, unloaded} -> ok after 300 -> false end,
- ?line process_flag(trap_exit,OldFlag),
- ?line ok = receive X -> {error, X} after 300 -> ok end,
- ?line test_server:timetrap_cancel(Dog),
+ Path = proplists:get_value(data_dir, Config),
+ OldFlag=process_flag(trap_exit,true),
+ Parent = self(),
+ F3 = fun() ->
+ Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
+ receive X -> Parent ! {got,X} end
+ end,
+ {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []),
+ spawn(F3),
+ {ok,Ref2} = receive
+ R when is_reference(R) -> {ok,R};
+ Other -> {error, Other}
+ after 500 -> {error, timeout}
+ end,
+ Port = open_port({spawn, echo_drv}, [eof]),
+ Port2 = open_port({spawn, echo_drv}, [eof]),
+ {ok, pending_driver, Ref1} =
+ erl_ddll:try_unload(echo_drv,[{monitor,pending_driver},kill_ports]),
+ ok = receive
+ {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok
+ after 300 -> error
+ end,
+ ok = receive {'EXIT',Port,driver_unloaded} -> ok after 300 -> false end,
+ ok = receive {'EXIT',Port2,driver_unloaded} -> ok after 300 -> false end,
+ ok = receive {'DOWN',Ref1, driver, echo_drv, unloaded} -> ok after 300 -> false end,
+ process_flag(trap_exit,OldFlag),
+ ok = receive X -> {error, X} after 300 -> ok end,
ok.
-no_trap_exit_and_kill_ports(suite) ->
- [];
-no_trap_exit_and_kill_ports(doc) ->
- ["Check delayed unload and reload with no trap_exit"];
+%% Check delayed unload and reload with no trap_exit
no_trap_exit_and_kill_ports(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line Parent = self(),
- ?line OldFlag=process_flag(trap_exit,true),
- ?line F3 = fun() ->
- Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
- receive X -> Parent ! {got,X} end
- end,
- ?line Pid = spawn(fun() ->
- process_flag(trap_exit,false),
- receive go -> ok end,
- {ok, loaded} = erl_ddll:try_load(Path, echo_drv,
- [{driver_options,[kill_ports]}]),
- spawn(F3),
- receive go -> ok end,
- _Port = open_port({spawn, echo_drv}, [eof]),
- _Port2 = open_port({spawn, echo_drv}, [eof]),
- exit(banan)
- end),
- ?line Ref = erlang:monitor(process,Pid),
+ Path = proplists:get_value(data_dir, Config),
+ Parent = self(),
+ OldFlag=process_flag(trap_exit,true),
+ F3 = fun() ->
+ Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}),
+ receive X -> Parent ! {got,X} end
+ end,
+ Pid = spawn(fun() ->
+ process_flag(trap_exit,false),
+ receive go -> ok end,
+ {ok, loaded} = erl_ddll:try_load(Path, echo_drv,
+ [{driver_options,[kill_ports]}]),
+ spawn(F3),
+ receive go -> ok end,
+ _Port = open_port({spawn, echo_drv}, [eof]),
+ _Port2 = open_port({spawn, echo_drv}, [eof]),
+ exit(banan)
+ end),
+ Ref = erlang:monitor(process,Pid),
Pid ! go,
- ?line {ok,Ref2} = receive
- R when is_reference(R) -> {ok,R};
- Other -> {error, Other}
- after 500 -> {error, timeout}
- end,
- ?line {error, inconsistent} = erl_ddll:try_load(Path, echo_drv, []),
- ?line MyPort = open_port({spawn, echo_drv}, [eof]),
+ {ok,Ref2} = receive
+ R when is_reference(R) -> {ok,R};
+ Other -> {error, Other}
+ after 500 -> {error, timeout}
+ end,
+ {error, inconsistent} = erl_ddll:try_load(Path, echo_drv, []),
+ MyPort = open_port({spawn, echo_drv}, [eof]),
Pid ! go,
- ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
- ?line ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end,
- ?line ok = receive {'EXIT',MyPort,driver_unloaded} -> ok after 300 -> error end,
- ?line process_flag(trap_exit,OldFlag),
- ?line test_server:timetrap_cancel(Dog),
+ ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end,
+ ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end,
+ ok = receive {'EXIT',MyPort,driver_unloaded} -> ok after 300 -> error end,
+ process_flag(trap_exit,OldFlag),
ok.
-monitor_demonitor(suite) ->
- [];
-monitor_demonitor(doc) ->
- ["Check monitor and demonitor of drivers"];
+%% Check monitor and demonitor of drivers
monitor_demonitor(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line erl_ddll:try_load(Path, echo_drv, []),
- ?line Ref = erl_ddll:monitor(driver,{echo_drv,unloaded}),
- ?line Self = self(),
- ?line [{Self,1}] = erl_ddll:info(echo_drv,awaiting_unload),
- ?line true = erl_ddll:demonitor(Ref),
- ?line [] = erl_ddll:info(echo_drv,awaiting_unload),
- ?line erl_ddll:try_unload(echo_drv,[]),
- ?line ok = receive _ -> error after 300 -> ok end,
- ?line test_server:timetrap_cancel(Dog),
+ Path = proplists:get_value(data_dir, Config),
+ erl_ddll:try_load(Path, echo_drv, []),
+ Ref = erl_ddll:monitor(driver,{echo_drv,unloaded}),
+ Self = self(),
+ [{Self,1}] = erl_ddll:info(echo_drv,awaiting_unload),
+ true = erl_ddll:demonitor(Ref),
+ [] = erl_ddll:info(echo_drv,awaiting_unload),
+ erl_ddll:try_unload(echo_drv,[]),
+ ok = receive _ -> error after 300 -> ok end,
ok.
-monitor_demonitor_load(suite) ->
- [];
-monitor_demonitor_load(doc) ->
- ["Check monitor/demonitor of driver loading"];
+%% Check monitor/demonitor of driver loading
monitor_demonitor_load(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line {ok,loaded} = erl_ddll:try_load(Path, echo_drv, []),
- ?line Port = open_port({spawn, echo_drv}, [eof]),
- ?line Ref = erl_ddll:monitor(driver,{echo_drv,loaded}),
- ?line ok = receive {'UP',Ref,driver,echo_drv,loaded} -> ok after 500 -> error end,
- ?line {ok, pending_driver} = erl_ddll:try_unload(echo_drv,[]),
- ?line Ref2 = erl_ddll:monitor(driver,{echo_drv,loaded}),
- ?line ok = receive {'DOWN',Ref2,driver,echo_drv,load_cancelled} -> ok after 0 -> error end,
- ?line {ok,already_loaded} = erl_ddll:try_load(Path, echo_drv, []),
- ?line {ok, pending_driver} =
- erl_ddll:try_load(Path, echo_drv, [{reload,pending_driver}]),
- ?line Ref3 = erl_ddll:monitor(driver,{echo_drv,loaded}),
- ?line Ref4 = erl_ddll:monitor(driver,{echo_drv,unloaded}),
- ?line ok = receive _ -> error after 300 -> ok end,
- ?line Self = self(),
- ?line [{Self,1}] = erl_ddll:info(echo_drv,awaiting_load),
- ?line true = erl_ddll:demonitor(Ref3),
- ?line [] = erl_ddll:info(echo_drv,awaiting_load),
- ?line erlang:port_close(Port),
- ?line ok = receive {'DOWN',Ref4,driver,echo_drv,unloaded} -> ok after 300 -> error end,
- ?line ok = receive _ -> error after 300 -> ok end,
- ?line ok = unload_expect_fast(echo_drv,[]),
- ?line test_server:timetrap_cancel(Dog),
+ Path = proplists:get_value(data_dir, Config),
+ {ok,loaded} = erl_ddll:try_load(Path, echo_drv, []),
+ Port = open_port({spawn, echo_drv}, [eof]),
+ Ref = erl_ddll:monitor(driver,{echo_drv,loaded}),
+ ok = receive {'UP',Ref,driver,echo_drv,loaded} -> ok after 500 -> error end,
+ {ok, pending_driver} = erl_ddll:try_unload(echo_drv,[]),
+ Ref2 = erl_ddll:monitor(driver,{echo_drv,loaded}),
+ ok = receive {'DOWN',Ref2,driver,echo_drv,load_cancelled} -> ok after 0 -> error end,
+ {ok,already_loaded} = erl_ddll:try_load(Path, echo_drv, []),
+ {ok, pending_driver} =
+ erl_ddll:try_load(Path, echo_drv, [{reload,pending_driver}]),
+ Ref3 = erl_ddll:monitor(driver,{echo_drv,loaded}),
+ Ref4 = erl_ddll:monitor(driver,{echo_drv,unloaded}),
+ ok = receive _ -> error after 300 -> ok end,
+ Self = self(),
+ [{Self,1}] = erl_ddll:info(echo_drv,awaiting_load),
+ true = erl_ddll:demonitor(Ref3),
+ [] = erl_ddll:info(echo_drv,awaiting_load),
+ erlang:port_close(Port),
+ ok = receive {'DOWN',Ref4,driver,echo_drv,unloaded} -> ok after 300 -> error end,
+ ok = receive _ -> error after 300 -> ok end,
+ ok = unload_expect_fast(echo_drv,[]),
ok.
-new_interface(suite) ->
- [];
-new_interface(doc) ->
- ["Test the new load/unload/reload interface"];
+%% Test the new load/unload/reload interface
new_interface(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
% Typical scenario
- ?line ok = erl_ddll:load(Path, echo_drv),
- ?line Port = open_port({spawn, echo_drv}, [eof]),
- ?line ok = erl_ddll:unload(echo_drv),
- ?line Port ! {self(), {command, "text"}},
- ?line ok = receive
- {Port, {data, "text"}} -> ok;
- _ -> error
- after
- 1000 -> error
- end,
- ?line Ref = erl_ddll:monitor(driver,{echo_drv,unloaded}),
- ?line ok = receive X -> {error, X} after 300 -> ok end,
- ?line erlang:port_close(Port),
- ?line ok = receive {'DOWN', Ref, driver, echo_drv, unloaded} -> ok after 300 -> error end,
+ ok = erl_ddll:load(Path, echo_drv),
+ Port = open_port({spawn, echo_drv}, [eof]),
+ ok = erl_ddll:unload(echo_drv),
+ Port ! {self(), {command, "text"}},
+ ok = receive
+ {Port, {data, "text"}} -> ok;
+ _ -> error
+ after
+ 1000 -> error
+ end,
+ Ref = erl_ddll:monitor(driver,{echo_drv,unloaded}),
+ ok = receive X -> {error, X} after 300 -> ok end,
+ erlang:port_close(Port),
+ ok = receive {'DOWN', Ref, driver, echo_drv, unloaded} -> ok after 300 -> error end,
% More than one user
- ?line ok = erl_ddll:load(Path, echo_drv),
- ?line Ref2 = erl_ddll:monitor(driver,{echo_drv,unloaded}),
- ?line ok = erl_ddll:load(Path, echo_drv),
- ?line ok = erl_ddll:load(Path, echo_drv),
- ?line Port2 = open_port({spawn, echo_drv}, [eof]),
- ?line ok = erl_ddll:unload(echo_drv),
- ?line Port2 ! {self(), {command, "text"}},
- ?line ok = receive
- {Port2, {data, "text"}} -> ok;
- _ -> error
- after
- 1000 -> error
- end,
- ?line ok = erl_ddll:unload(echo_drv),
- ?line Port2 ! {self(), {command, "text"}},
- ?line ok = receive
- {Port2, {data, "text"}} -> ok;
- _ -> error
- after
- 1000 -> error
- end,
- ?line ok = erl_ddll:unload(echo_drv),
- ?line Port2 ! {self(), {command, "text"}},
- ?line ok = receive
- {Port2, {data, "text"}} -> ok;
- _ -> error
- after
- 1000 -> error
- end,
- ?line ok = receive X2 -> {error, X2} after 300 -> ok end,
- ?line ok = erl_ddll:load(Path, echo_drv),
- ?line ok = receive {'UP', Ref2, driver, echo_drv, unload_cancelled} -> ok after 300 -> error end,
- ?line Ref3 = erl_ddll:monitor(driver,{echo_drv,unloaded_only}),
- ?line erlang:port_close(Port2),
- ?line ok = receive X3 -> {error, X3} after 300 -> ok end,
- ?line ok = erl_ddll:unload(echo_drv),
- ?line ok = receive {'DOWN', Ref3, driver, echo_drv, unloaded} -> ok after 300 -> error end,
- ?line test_server:timetrap_cancel(Dog),
+ ok = erl_ddll:load(Path, echo_drv),
+ Ref2 = erl_ddll:monitor(driver,{echo_drv,unloaded}),
+ ok = erl_ddll:load(Path, echo_drv),
+ ok = erl_ddll:load(Path, echo_drv),
+ Port2 = open_port({spawn, echo_drv}, [eof]),
+ ok = erl_ddll:unload(echo_drv),
+ Port2 ! {self(), {command, "text"}},
+ ok = receive
+ {Port2, {data, "text"}} -> ok;
+ _ -> error
+ after
+ 1000 -> error
+ end,
+ ok = erl_ddll:unload(echo_drv),
+ Port2 ! {self(), {command, "text"}},
+ ok = receive
+ {Port2, {data, "text"}} -> ok;
+ _ -> error
+ after
+ 1000 -> error
+ end,
+ ok = erl_ddll:unload(echo_drv),
+ Port2 ! {self(), {command, "text"}},
+ ok = receive
+ {Port2, {data, "text"}} -> ok;
+ _ -> error
+ after
+ 1000 -> error
+ end,
+ ok = receive X2 -> {error, X2} after 300 -> ok end,
+ ok = erl_ddll:load(Path, echo_drv),
+ ok = receive {'UP', Ref2, driver, echo_drv, unload_cancelled} -> ok after 300 -> error end,
+ Ref3 = erl_ddll:monitor(driver,{echo_drv,unloaded_only}),
+ erlang:port_close(Port2),
+ ok = receive X3 -> {error, X3} after 300 -> ok end,
+ ok = erl_ddll:unload(echo_drv),
+ ok = receive {'DOWN', Ref3, driver, echo_drv, unloaded} -> ok after 300 -> error end,
ok.
-
-
+
+
ddll_test(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
- %?line {error,{already_started,ErlDdllPid}} = erl_ddll:start(),
- %?line ErlDdllPid = whereis(ddll_server),
+ %{error,{already_started,ErlDdllPid}} = erl_ddll:start(),
+ %ErlDdllPid = whereis(ddll_server),
%% Load the echo driver and verify that it was loaded.
{ok,L1,L2}=load_echo_driver(Path),
%% Verify that the driver works.
- ?line Port = open_port({spawn, echo_drv}, [eof]),
- ?line {hej, "hopp",4711,123445567436543653} =
- erlang:port_call(Port,{hej, "hopp",4711,123445567436543653}),
- ?line {hej, "hopp",4711,123445567436543653} =
- erlang:port_call(Port,47,{hej, "hopp",4711,123445567436543653}),
- ?line Port ! {self(), {command, "text"}},
- ?line 1 = receive
- {Port, {data, "text"}} -> 1;
- _Other -> 2
- after
- 1000 -> 2
- end,
- ?line Port ! {self(), close},
- ?line receive {Port, closed} -> ok end,
-
-%% %% Unload the driver and verify that it was unloaded.
- ok = unload_echo_driver(L1,L2),
-
-%% %?line {error, {already_started, _}} = erl_ddll:start(),
-
- ?line test_server:timetrap_cancel(Dog),
+ Port = open_port({spawn, echo_drv}, [eof]),
+ {hej, "hopp",4711,123445567436543653} =
+ erlang:port_call(Port,{hej, "hopp",4711,123445567436543653}),
+ {hej, "hopp",4711,123445567436543653} =
+ erlang:port_call(Port,47,{hej, "hopp",4711,123445567436543653}),
+ Port ! {self(), {command, "text"}},
+ 1 = receive
+ {Port, {data, "text"}} -> 1;
+ _Other -> 2
+ after
+ 1000 -> 2
+ end,
+ Port ! {self(), close},
+ receive {Port, closed} -> ok end,
+
+ %% %% Unload the driver and verify that it was unloaded.
+ ok = unload_echo_driver(L1,L2),
+
+ %% %{error, {already_started, _}} = erl_ddll:start(),
ok.
%% Tests errors having to do with bad drivers.
errors(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
- ?line {ok, L1} = erl_ddll:loaded_drivers(),
+ {ok, L1} = erl_ddll:loaded_drivers(),
- ?line {error, {open_error, _}} = erl_ddll:load_driver(Path, bad_name),
- ?line {error, driver_init_failed} = erl_ddll:load_driver(Path, initfail_drv),
- ?line {error, bad_driver_name} = erl_ddll:load_driver(Path, wrongname_drv),
+ {error, {open_error, _}} = erl_ddll:load_driver(Path, bad_name),
+ {error, driver_init_failed} = erl_ddll:load_driver(Path, initfail_drv),
+ {error, bad_driver_name} = erl_ddll:load_driver(Path, wrongname_drv),
%% We assume that there is a statically linked driver named "ddll":
- ?line {error, linked_in_driver} = erl_ddll:unload_driver(efile),
- ?line {error, not_loaded} = erl_ddll:unload_driver("__pucko_driver__"),
-
+ {error, linked_in_driver} = erl_ddll:unload_driver(efile),
+ {error, not_loaded} = erl_ddll:unload_driver("__pucko_driver__"),
+
case os:type() of
- {unix, _} ->
- ?line {error, no_driver_init} =
- erl_ddll:load_driver(Path, noinit_drv);
- _ ->
- ok
+ {unix, _} ->
+ {error, no_driver_init} =
+ erl_ddll:load_driver(Path, noinit_drv);
+ _ ->
+ ok
end,
- ?line {ok, L1} = erl_ddll:loaded_drivers(),
-
- ?line test_server:timetrap_cancel(Dog),
+ {ok, L1} = erl_ddll:loaded_drivers(),
ok.
-reference_count(doc) ->
- ["Check that drivers are unloaded when their reference count ",
- "reaches zero, and that they cannot be unloaded while ",
- "they are still referenced."];
+%% Check that drivers are unloaded when their reference count
+%% reaches zero, and that they cannot be unloaded while
+%% they are still referenced.
reference_count(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
%% Spawn a process that loads the driver (and holds a reference
%% to it).
Pid1=spawn_link(?MODULE, echo_loader, [Path, self()]),
receive
- {Pid1, echo_loaded} -> ok
- after 2000 -> test_server:fail("echo_loader failed to start.")
+ {Pid1, echo_loaded} -> ok
+ after 2000 -> ct:fail("echo_loader failed to start.")
end,
Pid1 ! {self(), die},
- ?line test_server:sleep(200), % Give time to unload.
+ test_server:sleep(200), % Give time to unload.
% Verify that the driver was automaticly unloaded when the
% process died.
- ?line {error, not_loaded}=erl_ddll:unload_driver(echo_drv),
-
- ?line test_server:timetrap_cancel(Dog),
+ {error, not_loaded}=erl_ddll:unload_driver(echo_drv),
ok.
% Loads the echo driver, send msg to started, sits and waits to
% get a signal to die, then unloads the driver and terminates.
echo_loader(Path, Starter) ->
- ?line {ok, L1, L2}=load_echo_driver(Path),
- ?line Starter ! {self(), echo_loaded},
+ {ok, L1, L2}=load_echo_driver(Path),
+ Starter ! {self(), echo_loaded},
receive
- {Starter, die} ->
- ?line unload_echo_driver(L1,L2)
+ {Starter, die} ->
+ unload_echo_driver(L1,L2)
end.
% Loads the echo driver, send msg to started, sits and waits to
% get a signal to die, then unloads the driver and terminates.
nice_echo_loader(Path, Starter) ->
- ?line {ok, L1, L2}=load_nice_echo_driver(Path),
- ?line Starter ! {self(), echo_loaded},
+ {ok, L1, L2}=load_nice_echo_driver(Path),
+ Starter ! {self(), echo_loaded},
receive
- {Starter, die} ->
- ?line unload_echo_driver(L1,L2)
+ {Starter, die} ->
+ unload_echo_driver(L1,L2)
end.
-kill_port(doc) ->
- ["Test that a port that uses a driver is killed when the ",
- "process that loaded the driver dies."];
+%% Test that a port that uses a driver is killed when the
+%% process that loaded the driver dies.
kill_port(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
%% Spawn a process that loads the driver (and holds a reference
%% to it).
- ?line Pid1=spawn(?MODULE, echo_loader, [Path, self()]),
- ?line receive
- {Pid1, echo_loaded} ->
- ok
- after 3000 ->
- ?line exit(Pid1, kill),
- ?line test_server:fail("echo_loader failed to start.")
- end,
+ Pid1=spawn(?MODULE, echo_loader, [Path, self()]),
+ receive
+ {Pid1, echo_loaded} ->
+ ok
+ after 3000 ->
+ exit(Pid1, kill),
+ ct:fail("echo_loader failed to start.")
+ end,
% Spawn off a port that uses the driver.
- ?line Port = open_port({spawn, echo_drv}, [eof]),
+ Port = open_port({spawn, echo_drv}, [eof]),
% Kill the process / unload the driver.
- ?line process_flag(trap_exit, true),
- ?line exit(Pid1, kill),
- ?line test_server:sleep(200), % Give some time to unload.
- ?line {error, not_loaded} = erl_ddll:unload_driver(echo_drv),
+ process_flag(trap_exit, true),
+ exit(Pid1, kill),
+ test_server:sleep(200), % Give some time to unload.
+ {error, not_loaded} = erl_ddll:unload_driver(echo_drv),
% See if the port is killed.
receive
- {'EXIT', Port, Reason} ->
- io:format("Port exited with reason ~w", [Reason])
+ {'EXIT', Port, Reason} ->
+ io:format("Port exited with reason ~w", [Reason])
after 5000 ->
- ?line test_server:fail("Echo port did not terminate.")
+ ct:fail("Echo port did not terminate.")
end,
-
- %% Cleanup and exit.
- ?line test_server:timetrap_cancel(Dog),
ok.
-dont_kill_port(doc) ->
- ["Test that a port that uses a driver is not killed when the ",
- "process that loaded the driver dies and it's nicely opened."];
+%% Test that a port that uses a driver is not killed when the
+%% process that loaded the driver dies and it's nicely opened.
dont_kill_port(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
%% Spawn a process that loads the driver (and holds a reference
%% to it).
- ?line Pid1=spawn(?MODULE, nice_echo_loader, [Path, self()]),
- ?line receive
- {Pid1, echo_loaded} ->
- ok
- after 3000 ->
- ?line exit(Pid1, kill),
- ?line test_server:fail("echo_loader failed to start.")
- end,
+ Pid1=spawn(?MODULE, nice_echo_loader, [Path, self()]),
+ receive
+ {Pid1, echo_loaded} ->
+ ok
+ after 3000 ->
+ exit(Pid1, kill),
+ ct:fail("echo_loader failed to start.")
+ end,
% Spawn off a port that uses the driver.
- ?line Port = open_port({spawn, echo_drv}, [eof]),
+ Port = open_port({spawn, echo_drv}, [eof]),
% Kill the process / unload the driver.
- ?line process_flag(trap_exit, true),
- ?line exit(Pid1, kill),
- ?line test_server:sleep(200), % Give some time to unload.
- ?line {hej, "hopp",4711,123445567436543653} =
- erlang:port_call(Port,{hej, "hopp",4711,123445567436543653}),
- ?line [] = erl_ddll:info(echo_drv,processes),
+ process_flag(trap_exit, true),
+ exit(Pid1, kill),
+ test_server:sleep(200), % Give some time to unload.
+ {hej, "hopp",4711,123445567436543653} =
+ erlang:port_call(Port,{hej, "hopp",4711,123445567436543653}),
+ [] = erl_ddll:info(echo_drv,processes),
%% unload should work with no owner
- ?line ok = erl_ddll:unload_driver(echo_drv), %Kill ports while at it
+ ok = erl_ddll:unload_driver(echo_drv), %Kill ports while at it
% See if the port is killed.
receive
- {'EXIT', Port, Reason} ->
- io:format("Port exited with reason ~w", [Reason])
+ {'EXIT', Port, Reason} ->
+ io:format("Port exited with reason ~w", [Reason])
after 5000 ->
- ?line test_server:fail("Echo port did not terminate.")
+ ct:fail("Echo port did not terminate.")
end,
-
- %% Cleanup and exit.
- ?line test_server:timetrap_cancel(Dog),
ok.
-properties(doc) -> ["Test that a process that loaded a driver ",
- "is the only process that can unload it."];
+%% Test that a process that loaded a driver
+%% is the only process that can unload it.
properties(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
% Let another process load the echo driver.
Pid=spawn_link(?MODULE, echo_loader, [Path, self()]),
receive
- {Pid, echo_loaded} -> ok
- after 2000 -> test_server:fail("echo_loader failed to start.")
+ {Pid, echo_loaded} -> ok
+ after 2000 -> ct:fail("echo_loader failed to start.")
end,
% Try to unload the driver from this process (the wrong one).
- ?line {error, _} = erl_ddll:unload_driver(echo_drv),
- ?line {ok, Drivers} = erl_ddll:loaded_drivers(),
- ?line case lists:member("echo_drv", Drivers) of
- true ->
- ok;
- false ->
- test_server:fail("Unload from wrong process "
- "succeeded.")
- end,
+ {error, _} = erl_ddll:unload_driver(echo_drv),
+ {ok, Drivers} = erl_ddll:loaded_drivers(),
+ case lists:member("echo_drv", Drivers) of
+ true ->
+ ok;
+ false ->
+ ct:fail("Unload from wrong process succeeded.")
+ end,
% Unload the driver and terminate dummy process.
- ?line Pid ! {self(), die},
- ?line test_server:sleep(200), % Give time to unload.
- ?line test_server:timetrap_cancel(Dog),
+ Pid ! {self(), die},
+ test_server:sleep(200), % Give time to unload.
ok.
-load_and_unload(doc) -> ["Load two drivers and unload them in load order."];
+%% Load two drivers and unload them in load order.
load_and_unload(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(60)),
- ?line Path = ?config(data_dir, Config),
- ?line {ok, Loaded_drivers1} = erl_ddll:loaded_drivers(),
- ?line ok = erl_ddll:load_driver(Path, echo_drv),
- ?line ok = erl_ddll:load_driver(Path, dummy_drv),
- ?line ok = erl_ddll:unload_driver(echo_drv),
- ?line ok = erl_ddll:unload_driver(dummy_drv),
- ?line {ok, Loaded_drivers2} = erl_ddll:loaded_drivers(),
- ?line Set1 = ordsets:from_list(Loaded_drivers1),
- ?line Set2 = ordsets:from_list(Loaded_drivers2),
- ?line io:format("~p == ~p\n", [Loaded_drivers1, Loaded_drivers2]),
- ?line [] = ordsets:to_list(ordsets:subtract(Set2, Set1)),
-
- ?line test_server:timetrap_cancel(Dog),
+ Path = proplists:get_value(data_dir, Config),
+ {ok, Loaded_drivers1} = erl_ddll:loaded_drivers(),
+ ok = erl_ddll:load_driver(Path, echo_drv),
+ ok = erl_ddll:load_driver(Path, dummy_drv),
+ ok = erl_ddll:unload_driver(echo_drv),
+ ok = erl_ddll:unload_driver(dummy_drv),
+ {ok, Loaded_drivers2} = erl_ddll:loaded_drivers(),
+ Set1 = ordsets:from_list(Loaded_drivers1),
+ Set2 = ordsets:from_list(Loaded_drivers2),
+ io:format("~p == ~p\n", [Loaded_drivers1, Loaded_drivers2]),
+ [] = ordsets:to_list(ordsets:subtract(Set2, Set1)),
ok.
-lock_driver(suite) ->
- [];
-lock_driver(doc) ->
- ["Check multiple calls to driver_lock_driver"];
+%% Check multiple calls to driver_lock_driver
lock_driver(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line {ok, _} = erl_ddll:try_load(Path, lock_drv, []),
- ?line Port1 = open_port({spawn, lock_drv}, [eof]),
- ?line Port2 = open_port({spawn, lock_drv}, [eof]),
- ?line true = erl_ddll:info(lock_drv,permanent),
- ?line erlang:port_close(Port1),
- ?line erlang:port_close(Port2),
- ?line test_server:timetrap_cancel(Dog),
+ Path = proplists:get_value(data_dir, Config),
+ {ok, _} = erl_ddll:try_load(Path, lock_drv, []),
+ Port1 = open_port({spawn, lock_drv}, [eof]),
+ Port2 = open_port({spawn, lock_drv}, [eof]),
+ true = erl_ddll:info(lock_drv,permanent),
+ erlang:port_close(Port1),
+ erlang:port_close(Port2),
ok.
-
+
% Load and unload the echo_drv driver.
% Make sure that the driver doesn't exist before we load it,
% and that it exists before we unload it.
load_echo_driver(Path) ->
- ?line {ok, L1} = erl_ddll:loaded_drivers(),
- ?line ok = erl_ddll:load_driver(Path, echo_drv),
- ?line {ok, L2} = erl_ddll:loaded_drivers(),
- ?line ["echo_drv"] = ordsets:to_list(subtract(ordsets:from_list(L2),
- ordsets:from_list(L1))),
+ {ok, L1} = erl_ddll:loaded_drivers(),
+ ok = erl_ddll:load_driver(Path, echo_drv),
+ {ok, L2} = erl_ddll:loaded_drivers(),
+ ["echo_drv"] = ordsets:to_list(subtract(ordsets:from_list(L2),
+ ordsets:from_list(L1))),
{ok,L1,L2}.
load_nice_echo_driver(Path) ->
- ?line {ok, L1} = erl_ddll:loaded_drivers(),
- ?line ok = erl_ddll:load(Path, echo_drv),
- ?line {ok, L2} = erl_ddll:loaded_drivers(),
- ?line ["echo_drv"] = ordsets:to_list(subtract(ordsets:from_list(L2),
- ordsets:from_list(L1))),
+ {ok, L1} = erl_ddll:loaded_drivers(),
+ ok = erl_ddll:load(Path, echo_drv),
+ {ok, L2} = erl_ddll:loaded_drivers(),
+ ["echo_drv"] = ordsets:to_list(subtract(ordsets:from_list(L2),
+ ordsets:from_list(L1))),
{ok,L1,L2}.
unload_echo_driver(L1,L2) ->
- ?line {ok, L2} = erl_ddll:loaded_drivers(),
- ?line ok = erl_ddll:unload_driver(echo_drv),
- ?line {ok, L3} = erl_ddll:loaded_drivers(),
- ?line [] = ordsets:to_list(subtract(ordsets:from_list(L3),
- ordsets:from_list(L1))),
+ {ok, L2} = erl_ddll:loaded_drivers(),
+ ok = erl_ddll:unload_driver(echo_drv),
+ {ok, L3} = erl_ddll:loaded_drivers(),
+ [] = ordsets:to_list(subtract(ordsets:from_list(L3),
+ ordsets:from_list(L1))),
ok.
unload_expect_fast(Driver,XFlags) ->
{ok, pending_driver, Ref} =
- erl_ddll:try_unload(Driver,
- [{monitor,pending_driver}]++XFlags),
+ erl_ddll:try_unload(Driver,
+ [{monitor,pending_driver}]++XFlags),
receive
- {'DOWN', Ref, driver, Driver, unloaded} ->
- case lists:member(atom_to_list(Driver),element(2,erl_ddll:loaded_drivers())) of
- true ->
- {error, {still_there, Driver}};
- false ->
- ok
- end
+ {'DOWN', Ref, driver, Driver, unloaded} ->
+ case lists:member(atom_to_list(Driver),element(2,erl_ddll:loaded_drivers())) of
+ true ->
+ {error, {still_there, Driver}};
+ false ->
+ ok
+ end
after 1000 ->
- {error,{unable_to_unload, Driver}}
+ {error,{unable_to_unload, Driver}}
end.
diff --git a/erts/emulator/test/decode_packet_SUITE.erl b/erts/emulator/test/decode_packet_SUITE.erl
index 6a5ca20ac3..ad592f7147 100644
--- a/erts/emulator/test/decode_packet_SUITE.erl
+++ b/erts/emulator/test/decode_packet_SUITE.erl
@@ -22,15 +22,16 @@
-module(decode_packet_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2,
- basic/1, packet_size/1, neg/1, http/1, line/1, ssl/1, otp_8536/1,
+-export([all/0, suite/0,groups/0,
+ init_per_testcase/2,end_per_testcase/2,
+ basic/1, packet_size/1, neg/1, http/1, line/1, ssl/1, otp_8536/1,
otp_9389/1, otp_9389_line/1]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 1}}].
all() ->
[basic, packet_size, neg, http, line, ssl, otp_8536,
@@ -39,69 +40,49 @@ all() ->
groups() ->
[].
-init_per_suite(Config) ->
+init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
+ rand:seed(exsplus),
+ io:format("*** SEED: ~p ***\n", [rand:export_seed()]),
Config.
-end_per_suite(_Config) ->
+end_per_testcase(_Func, _Config) ->
ok.
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Seed = {S1,S2,S3} = {erlang:monotonic_time(),
- erlang:time_offset(),
- erlang:unique_integer()},
- random:seed(S1,S2,S3),
- io:format("*** SEED: ~p ***\n", [Seed]),
- Dog=?t:timetrap(?t:minutes(1)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
-basic(doc) -> [];
-basic(suite) -> [];
basic(Config) when is_list(Config) ->
- ?line Packet = <<101,22,203,54,175>>,
- ?line Rest = <<123,34,0,250>>,
- ?line Bin = <<Packet/binary,Rest/binary>>,
- ?line {ok, Bin, <<>>} = decode_pkt(raw,Bin),
+ Packet = <<101,22,203,54,175>>,
+ Rest = <<123,34,0,250>>,
+ Bin = <<Packet/binary,Rest/binary>>,
+ {ok, Bin, <<>>} = decode_pkt(raw,Bin),
- ?line {more, 5+1} = decode_pkt(1,<<5,1,2,3,4>>),
- ?line {more, 5+2} = decode_pkt(2,<<0,5,1,2,3,4>>),
- ?line {more, 5+4} = decode_pkt(4,<<0,0,0,5,1,2,3,4>>),
+ {more, 5+1} = decode_pkt(1,<<5,1,2,3,4>>),
+ {more, 5+2} = decode_pkt(2,<<0,5,1,2,3,4>>),
+ {more, 5+4} = decode_pkt(4,<<0,0,0,5,1,2,3,4>>),
- ?line {more, undefined} = decode_pkt(1,<<>>),
- ?line {more, undefined} = decode_pkt(2,<<0>>),
- ?line {more, undefined} = decode_pkt(4,<<0,0,0>>),
+ {more, undefined} = decode_pkt(1,<<>>),
+ {more, undefined} = decode_pkt(2,<<0>>),
+ {more, undefined} = decode_pkt(4,<<0,0,0>>),
Types = [1,2,4,asn1,sunrm,cdr,fcgi,tpkt,ssl_tls],
%% Run tests for different header types and bit offsets.
lists:foreach(fun({Type,Bits})->basic_pack(Type,Packet,Rest,Bits),
- more_length(Type,Packet,Bits) end,
- [{T,B} || T<-Types, B<-lists:seq(0,32)]),
+ more_length(Type,Packet,Bits) end,
+ [{T,B} || T<-Types, B<-lists:seq(0,32)]),
ok.
basic_pack(Type,Body,Rest,BitOffs) ->
- ?line {Bin,Unpacked,_} = pack(Type,Body,Rest,BitOffs),
- ?line {ok, Unpacked, Rest} = decode_pkt(Type,Bin),
+ {Bin,Unpacked,_} = pack(Type,Body,Rest,BitOffs),
+ {ok, Unpacked, Rest} = decode_pkt(Type,Bin),
case Rest of
- <<>> -> ok;
- _ ->
- ?line <<_:1,NRest/bits>> = Rest,
- basic_pack(Type,Body,NRest,BitOffs)
+ <<>> -> ok;
+ _ ->
+ <<_:1,NRest/bits>> = Rest,
+ basic_pack(Type,Body,NRest,BitOffs)
end.
more_length(Type,Body,BitOffs) ->
- ?line {Bin,_,_} = pack(Type,Body,<<>>,BitOffs),
+ {Bin,_,_} = pack(Type,Body,<<>>,BitOffs),
HdrSize = byte_size(Bin) - byte_size(Body),
more_length_do(Type,HdrSize,Bin,byte_size(Bin)).
@@ -110,17 +91,17 @@ more_length_do(_,_,_,0) ->
more_length_do(Type,HdrSize,Bin,Size) ->
TrySize = (Size*3) div 4,
NSize = if TrySize < HdrSize -> Size - 1;
- true -> TrySize
- end,
+ true -> TrySize
+ end,
{B1,_} = split_binary(Bin,NSize),
- ?line {more, Length} = decode_pkt(Type,B1),
+ {more, Length} = decode_pkt(Type,B1),
case Length of
- L when L=:=byte_size(Bin) -> ok;
- undefined when NSize<HdrSize -> ok
+ L when L=:=byte_size(Bin) -> ok;
+ undefined when NSize<HdrSize -> ok
end,
more_length_do(Type,HdrSize,Bin,NSize).
-
+
pack(Type,Packet,Rest) ->
{Bin,Unpacked} = pack(Type,Packet),
@@ -136,7 +117,7 @@ pack(Type,Body,Rest,BitOffs) ->
{Packet,Unpacked} = pack(Type,Body),
%% Make Bin a sub-bin with an arbitrary bitoffset within Orig
- Prefix = random:uniform(1 bsl BitOffs) - 1,
+ Prefix = rand:uniform(1 bsl BitOffs) - 1,
Orig = <<Prefix:BitOffs,Packet/binary,Rest/bits>>,
<<_:BitOffs,Bin/bits>> = Orig,
{Bin,Unpacked,Orig}.
@@ -151,212 +132,206 @@ pack(4,Bin) ->
Psz = byte_size(Bin),
{<<Psz:32,Bin/binary>>, Bin};
pack(asn1,Bin) ->
- Ident = case random:uniform(3) of
- 1 -> <<17>>;
- 2 -> <<16#1f,16#81,17>>;
- 3 -> <<16#1f,16#81,16#80,16#80,17>>
- end,
+ Ident = case rand:uniform(3) of
+ 1 -> <<17>>;
+ 2 -> <<16#1f,16#81,17>>;
+ 3 -> <<16#1f,16#81,16#80,16#80,17>>
+ end,
Psz = byte_size(Bin),
- Length = case random:uniform(4) of
- 1 when Psz < 128 ->
- <<Psz:8>>;
- R when R=<2 andalso Psz < 16#10000 ->
- <<16#82,Psz:16>>;
- R when R=<3 andalso Psz < 16#1000000 ->
- <<16#83,Psz:24>>;
- _ when Psz < 16#100000000 ->
- <<16#84,Psz:32>>
- end,
+ Length = case rand:uniform(4) of
+ 1 when Psz < 128 ->
+ <<Psz:8>>;
+ R when R=<2 andalso Psz < 16#10000 ->
+ <<16#82,Psz:16>>;
+ R when R=<3 andalso Psz < 16#1000000 ->
+ <<16#83,Psz:24>>;
+ _ when Psz < 16#100000000 ->
+ <<16#84,Psz:32>>
+ end,
Res = <<Ident/binary,Length/binary,Bin/binary>>,
{Res,Res};
pack(sunrm,Bin) ->
Psz = byte_size(Bin),
Res = if Psz < 16#80000000 ->
- <<Psz:32,Bin/binary>>
- end,
+ <<Psz:32,Bin/binary>>
+ end,
{Res,Res};
pack(cdr,Bin) ->
GIOP = <<"GIOP">>,
- Major = random:uniform(256) - 1,
- Minor = random:uniform(256) - 1,
- MType = random:uniform(256) - 1,
+ Major = rand:uniform(256) - 1,
+ Minor = rand:uniform(256) - 1,
+ MType = rand:uniform(256) - 1,
Psz = byte_size(Bin),
- Res = case random:uniform(2) of
- 1 -> <<GIOP/binary,Major:8,Minor:8,0:8,MType:8,Psz:32/big,Bin/binary>>;
- 2 -> <<GIOP/binary,Major:8,Minor:8,1:8,MType:8,Psz:32/little,Bin/binary>>
- end,
+ Res = case rand:uniform(2) of
+ 1 -> <<GIOP/binary,Major:8,Minor:8,0:8,MType:8,Psz:32/big,Bin/binary>>;
+ 2 -> <<GIOP/binary,Major:8,Minor:8,1:8,MType:8,Psz:32/little,Bin/binary>>
+ end,
{Res,Res};
pack(fcgi,Bin) ->
Ver = 1,
- Type = random:uniform(256) - 1,
- Id = random:uniform(65536) - 1,
- PaddSz = random:uniform(16) - 1,
+ Type = rand:uniform(256) - 1,
+ Id = rand:uniform(65536) - 1,
+ PaddSz = rand:uniform(16) - 1,
Psz = byte_size(Bin),
- Reserv = random:uniform(256) - 1,
+ Reserv = rand:uniform(256) - 1,
Padd = case PaddSz of
- 0 -> <<>>;
- _ -> list_to_binary([random:uniform(256)-1
- || _<- lists:seq(1,PaddSz)])
- end,
+ 0 -> <<>>;
+ _ -> list_to_binary([rand:uniform(256)-1
+ || _<- lists:seq(1,PaddSz)])
+ end,
Res = <<Ver:8,Type:8,Id:16,Psz:16/big,PaddSz:8,Reserv:8,Bin/binary>>,
{<<Res/binary,Padd/binary>>, Res};
pack(tpkt,Bin) ->
Ver = 3,
- Reserv = random:uniform(256) - 1,
+ Reserv = rand:uniform(256) - 1,
Size = byte_size(Bin) + 4,
Res = <<Ver:8,Reserv:8,Size:16,Bin/binary>>,
{Res, Res};
pack(ssl_tls,Bin) ->
- Content = case (random:uniform(256) - 1) of
- C when C<128 -> C;
- _ -> v2hello
- end,
- Major = random:uniform(256) - 1,
- Minor = random:uniform(256) - 1,
+ Content = case (rand:uniform(256) - 1) of
+ C when C<128 -> C;
+ _ -> v2hello
+ end,
+ Major = rand:uniform(256) - 1,
+ Minor = rand:uniform(256) - 1,
pack_ssl(Content,Major,Minor,Bin).
pack_ssl(Content, Major, Minor, Body) ->
case Content of
- v2hello ->
- Size = byte_size(Body),
- Res = <<1:1,(Size+3):15, 1:8, Major:8, Minor:8, Body/binary>>,
- C = 22,
- Data = <<1:8, (Size+2):24, Major:8, Minor:8, Body/binary>>;
- C when is_integer(C) ->
- Size = byte_size(Body),
- Res = <<Content:8, Major:8, Minor:8, Size:16, Body/binary>>,
- Data = Body
+ v2hello ->
+ Size = byte_size(Body),
+ Res = <<1:1,(Size+3):15, 1:8, Major:8, Minor:8, Body/binary>>,
+ C = 22,
+ Data = <<1:8, (Size+2):24, Major:8, Minor:8, Body/binary>>;
+ C when is_integer(C) ->
+ Size = byte_size(Body),
+ Res = <<Content:8, Major:8, Minor:8, Size:16, Body/binary>>,
+ Data = Body
end,
{Res, {ssl_tls,[],C,{Major,Minor}, Data}}.
-packet_size(doc) -> [];
-packet_size(suite) -> [];
packet_size(Config) when is_list(Config) ->
- ?line Packet = <<101,22,203,54,175>>,
- ?line Rest = <<123,34,0,250>>,
+ Packet = <<101,22,203,54,175>>,
+ Rest = <<123,34,0,250>>,
F = fun({Type,Max})->
- ?line {Bin,Unpacked} = pack(Type,Packet,Rest),
- ?line case decode_pkt(Type,Bin,[{packet_size,Max}]) of
- {ok,Unpacked,Rest} when Max=:=0; Max>=byte_size(Packet) ->
- ok;
- {error,_} when Max<byte_size(Packet), Max=/=0 ->
- ok;
- {error,_} when Type=:=fcgi, Max=/=0 ->
- %% packet includes random amount of padding
- ok
- end
- end,
- ?line lists:foreach(F, [{T,D} || T<-[1,2,4,asn1,sunrm,cdr,fcgi,tpkt,ssl_tls],
- D<-lists:seq(0, byte_size(Packet)*2)]),
+ {Bin,Unpacked} = pack(Type,Packet,Rest),
+ case decode_pkt(Type,Bin,[{packet_size,Max}]) of
+ {ok,Unpacked,Rest} when Max=:=0; Max>=byte_size(Packet) ->
+ ok;
+ {error,_} when Max<byte_size(Packet), Max=/=0 ->
+ ok;
+ {error,_} when Type=:=fcgi, Max=/=0 ->
+ %% packet includes random amount of padding
+ ok
+ end
+ end,
+ lists:foreach(F, [{T,D} || T<-[1,2,4,asn1,sunrm,cdr,fcgi,tpkt,ssl_tls],
+ D<-lists:seq(0, byte_size(Packet)*2)]),
%% Test OTP-8102, "negative" 4-byte sizes.
lists:foreach(fun(Size) ->
- ?line {error,_} = decode_pkt(4,<<Size:32,Packet/binary>>)
- end,
- lists:seq(-10,-1)),
+ {error,_} = decode_pkt(4,<<Size:32,Packet/binary>>)
+ end,
+ lists:seq(-10,-1)),
%% Test OTP-9389, long HTTP header lines.
Opts = [{packet_size, 128}],
Pkt = list_to_binary(["GET / HTTP/1.1\r\nHost: localhost\r\nLink: /",
string:chars($Y, 64), "\r\n\r\n"]),
<<Pkt1:50/binary, Pkt2/binary>> = Pkt,
- ?line {ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest1} =
- erlang:decode_packet(http, Pkt1, Opts),
- ?line {ok, {http_header,_,'Host',_,"localhost"}, Rest2} =
- erlang:decode_packet(httph, Rest1, Opts),
- ?line {more, undefined} = erlang:decode_packet(httph, Rest2, Opts),
- ?line {ok, {http_header,_,"Link",_,_}, _} =
- erlang:decode_packet(httph, list_to_binary([Rest2, Pkt2]), Opts),
+ {ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest1} =
+ erlang:decode_packet(http, Pkt1, Opts),
+ {ok, {http_header,_,'Host',_,"localhost"}, Rest2} =
+ erlang:decode_packet(httph, Rest1, Opts),
+ {more, undefined} = erlang:decode_packet(httph, Rest2, Opts),
+ {ok, {http_header,_,"Link",_,_}, _} =
+ erlang:decode_packet(httph, list_to_binary([Rest2, Pkt2]), Opts),
Pkt3 = list_to_binary(["GET / HTTP/1.1\r\nHost: localhost\r\nLink: /",
string:chars($Y, 129), "\r\n\r\n"]),
- ?line {ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest3} =
- erlang:decode_packet(http, Pkt3, Opts),
- ?line {ok, {http_header,_,'Host',_,"localhost"}, Rest4} =
- erlang:decode_packet(httph, Rest3, Opts),
- ?line {error, invalid} = erlang:decode_packet(httph, Rest4, Opts),
+ {ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest3} =
+ erlang:decode_packet(http, Pkt3, Opts),
+ {ok, {http_header,_,'Host',_,"localhost"}, Rest4} =
+ erlang:decode_packet(httph, Rest3, Opts),
+ {error, invalid} = erlang:decode_packet(httph, Rest4, Opts),
ok.
-neg(doc) -> [];
-neg(suite) -> [];
neg(Config) when is_list(Config) ->
- ?line Bin = <<"dummy">>,
+ Bin = <<"dummy">>,
Fun = fun()->dummy end,
-
+
BadargF = fun(T,B,Opts)-> {'EXIT',{badarg,_}} = (catch decode_pkt(T,B,Opts)) end,
%% Invalid Type args
lists:foreach(fun(T)-> BadargF(T,Bin,[]) end,
- [3,-1,5,2.0,{2},unknown,[],"line",Bin,Fun,self()]),
+ [3,-1,5,2.0,{2},unknown,[],"line",Bin,Fun,self()]),
%% Invalid Bin args
lists:foreach(fun(B)-> BadargF(0,B,[]) end,
- [3,2.0,unknown,[],"Bin",[Bin],{Bin},Fun,self()]),
+ [3,2.0,unknown,[],"Bin",[Bin],{Bin},Fun,self()]),
%% Invalid options
InvOpts = [2,false,self(),Bin,"Options",Fun,
- packet_size,{packet_size},{packet_size,0,false},
- {packet_size,-1},{packet_size,100.0},{packet_size,false},
- {line_length,-1},{line_length,100.0},{line_length,false}],
+ packet_size,{packet_size},{packet_size,0,false},
+ {packet_size,-1},{packet_size,100.0},{packet_size,false},
+ {line_length,-1},{line_length,100.0},{line_length,false}],
lists:foreach(fun(Opt)-> BadargF(0,Bin,Opt),
- BadargF(0,Bin,[Opt]),
- BadargF(0,Bin,[Opt,{packet_size,1000}]),
- BadargF(0,Bin,[{packet_size,1000},Opt]) end,
- InvOpts),
+ BadargF(0,Bin,[Opt]),
+ BadargF(0,Bin,[Opt,{packet_size,1000}]),
+ BadargF(0,Bin,[{packet_size,1000},Opt]) end,
+ InvOpts),
ok.
-http(doc) -> [];
-http(suite) -> [];
http(Config) when is_list(Config) ->
- ?line <<"foo">> = http_do(http_request("foo")),
- ?line <<" bar">> = http_do(http_request(" bar")),
- ?line <<"Hello!">> = http_do(http_response("Hello!")),
+ <<"foo">> = http_do(http_request("foo")),
+ <<" bar">> = http_do(http_request(" bar")),
+ <<"Hello!">> = http_do(http_response("Hello!")),
%% Test all known header atoms
Val = "dummy value",
ValB = list_to_binary(Val),
Rest = <<"Rest">>,
HdrF = fun(Str,N) ->
- ?line StrA = list_to_atom(Str),
- ?line StrB = list_to_binary(Str),
- ?line Bin = <<StrB/binary,": ",ValB/binary,"\r\n",Rest/binary>>,
- ?line {ok, {http_header,N,StrA,undefined,Val}, Rest} = decode_pkt(httph,Bin),
- ?line {ok, {http_header,N,StrA,undefined,ValB}, Rest} = decode_pkt(httph_bin,Bin),
- ?line N + 1
- end,
- ?line lists:foldl(HdrF, 1, http_hdr_strings()),
+ StrA = list_to_atom(Str),
+ StrB = list_to_binary(Str),
+ Bin = <<StrB/binary,": ",ValB/binary,"\r\n",Rest/binary>>,
+ {ok, {http_header,N,StrA,undefined,Val}, Rest} = decode_pkt(httph,Bin),
+ {ok, {http_header,N,StrA,undefined,ValB}, Rest} = decode_pkt(httph_bin,Bin),
+ N + 1
+ end,
+ lists:foldl(HdrF, 1, http_hdr_strings()),
%% Test all known method atoms
MethF = fun(Meth) ->
- ?line MethA = list_to_atom(Meth),
- ?line MethB = list_to_binary(Meth),
- ?line Bin = <<MethB/binary," /invalid/url HTTP/1.0\r\n",Rest/binary>>,
- ?line {ok, {http_request,MethA,{abs_path,"/invalid/url"},{1,0}},
- Rest} = decode_pkt(http,Bin),
- ?line {ok, {http_request,MethA,{abs_path,<<"/invalid/url">>},{1,0}},
- Rest} = decode_pkt(http_bin,Bin)
- end,
- ?line lists:foreach(MethF, http_meth_strings()),
+ MethA = list_to_atom(Meth),
+ MethB = list_to_binary(Meth),
+ Bin = <<MethB/binary," /invalid/url HTTP/1.0\r\n",Rest/binary>>,
+ {ok, {http_request,MethA,{abs_path,"/invalid/url"},{1,0}},
+ Rest} = decode_pkt(http,Bin),
+ {ok, {http_request,MethA,{abs_path,<<"/invalid/url">>},{1,0}},
+ Rest} = decode_pkt(http_bin,Bin)
+ end,
+ lists:foreach(MethF, http_meth_strings()),
%% Test all uri variants
UriF = fun({Str,ResL,ResB}) ->
- Bin = <<"GET ",(list_to_binary(Str))/binary," HTTP/1.1\r\n",Rest/binary>>,
- {ok, {http_request, 'GET', ResL, {1,1}}, Rest} = decode_pkt(http,Bin),
- {ok, {http_request, 'GET', ResB, {1,1}}, Rest} = decode_pkt(http_bin,Bin)
- end,
+ Bin = <<"GET ",(list_to_binary(Str))/binary," HTTP/1.1\r\n",Rest/binary>>,
+ {ok, {http_request, 'GET', ResL, {1,1}}, Rest} = decode_pkt(http,Bin),
+ {ok, {http_request, 'GET', ResB, {1,1}}, Rest} = decode_pkt(http_bin,Bin)
+ end,
lists:foreach(UriF, http_uri_variants()),
%% Response with empty phrase
- ?line {ok,{http_response,{1,1},200,[]},<<>>} = decode_pkt(http, <<"HTTP/1.1 200\r\n">>, []),
- ?line {ok,{http_response,{1,1},200,<<>>},<<>>} = decode_pkt(http_bin, <<"HTTP/1.1 200\r\n">>, []),
+ {ok,{http_response,{1,1},200,[]},<<>>} = decode_pkt(http, <<"HTTP/1.1 200\r\n">>, []),
+ {ok,{http_response,{1,1},200,<<>>},<<>>} = decode_pkt(http_bin, <<"HTTP/1.1 200\r\n">>, []),
ok.
-
+
http_with_bin(http) ->
http_bin;
http_with_bin(httph) ->
@@ -367,88 +342,88 @@ http_do(Tup) ->
http_do({Bin, []}, _) ->
Bin;
http_do({Bin,[{_Line,PL,PB}|Tail]}, Type) ->
- ?line {ok, PL, Rest} = decode_pkt(Type,Bin),
- ?line {ok, PB, Rest} = decode_pkt(http_with_bin(Type),Bin),
+ {ok, PL, Rest} = decode_pkt(Type,Bin),
+ {ok, PB, Rest} = decode_pkt(http_with_bin(Type),Bin),
%% Same tests again but as SubBin
- PreLen = random:uniform(64),
- Prefix = random:uniform(1 bsl PreLen) - 1,
- SufLen = random:uniform(64),
- Suffix = random:uniform(1 bsl SufLen) - 1,
+ PreLen = rand:uniform(64),
+ Prefix = rand:uniform(1 bsl PreLen) - 1,
+ SufLen = rand:uniform(64),
+ Suffix = rand:uniform(1 bsl SufLen) - 1,
Orig = <<Prefix:PreLen, Bin/bits, Suffix:SufLen>>,
BinLen = bit_size(Bin),
<<_:PreLen, SubBin:BinLen/bits, _/bits>> = Orig, % Make SubBin
- ?line SubBin = Bin, % just to make sure
+ SubBin = Bin, % just to make sure
- ?line {ok, PL, Rest} = decode_pkt(Type,SubBin),
- ?line {ok, PB, Rest} = decode_pkt(http_with_bin(Type),SubBin),
+ {ok, PL, Rest} = decode_pkt(Type,SubBin),
+ {ok, PB, Rest} = decode_pkt(http_with_bin(Type),SubBin),
http_do({Rest, Tail}, httph).
http_request(Msg) ->
QnA = [{"POST /invalid/url HTTP/1.1\r\n",
- {http_request, 'POST', {abs_path, "/invalid/url" }, {1,1}},
- {http_request, 'POST', {abs_path,<<"/invalid/url">>}, {1,1}}},
- {"Connection: close\r\n",
- {http_header,2,'Connection',undefined, "close"},
- {http_header,2,'Connection',undefined,<<"close">>}},
- {"Host\t : localhost:8000\r\n", % white space before :
- {http_header,14,'Host',undefined, "localhost:8000"},
- {http_header,14,'Host',undefined,<<"localhost:8000">>}},
- {"User-Agent: perl post\r\n",
- {http_header,24,'User-Agent',undefined, "perl post"},
- {http_header,24,'User-Agent',undefined,<<"perl post">>}},
- {"Content-Length: 4\r\n",
- {http_header,38,'Content-Length',undefined, "4"},
- {http_header,38,'Content-Length',undefined,<<"4">>}},
- {"Content-Type: text/xml; charset=utf-8\r\n",
- {http_header,42,'Content-Type',undefined, "text/xml; charset=utf-8"},
- {http_header,42,'Content-Type',undefined,<<"text/xml; charset=utf-8">>}},
- {"Other-Field: with some text\r\n",
- {http_header,0, "Other-Field" ,undefined, "with some text"},
- {http_header,0,<<"Other-Field">>,undefined,<<"with some text">>}},
- {"Make-sure-a-LONG-HEaDer-fIeLd-is-fORMATTED-NicelY: with some text\r\n",
- {http_header,0, "Make-Sure-A-Long-Header-Field-Is-Formatted-Nicely" ,undefined, "with some text"},
- {http_header,0,<<"Make-Sure-A-Long-Header-Field-Is-Formatted-Nicely">>,undefined,<<"with some text">>}},
- {"Multi-Line: Once upon a time in a land far far away,\r\n"
- " there lived a princess imprisoned in the highest tower\r\n"
- " of the most haunted castle.\r\n",
- {http_header,0, "Multi-Line" ,undefined, "Once upon a time in a land far far away,\r\n there lived a princess imprisoned in the highest tower\r\n of the most haunted castle."},
- {http_header,0,<<"Multi-Line">>,undefined,<<"Once upon a time in a land far far away,\r\n there lived a princess imprisoned in the highest tower\r\n of the most haunted castle.">>}},
- {"\r\n",
- http_eoh,
- http_eoh}],
+ {http_request, 'POST', {abs_path, "/invalid/url" }, {1,1}},
+ {http_request, 'POST', {abs_path,<<"/invalid/url">>}, {1,1}}},
+ {"Connection: close\r\n",
+ {http_header,2,'Connection',undefined, "close"},
+ {http_header,2,'Connection',undefined,<<"close">>}},
+ {"Host\t : localhost:8000\r\n", % white space before :
+ {http_header,14,'Host',undefined, "localhost:8000"},
+ {http_header,14,'Host',undefined,<<"localhost:8000">>}},
+ {"User-Agent: perl post\r\n",
+ {http_header,24,'User-Agent',undefined, "perl post"},
+ {http_header,24,'User-Agent',undefined,<<"perl post">>}},
+ {"Content-Length: 4\r\n",
+ {http_header,38,'Content-Length',undefined, "4"},
+ {http_header,38,'Content-Length',undefined,<<"4">>}},
+ {"Content-Type: text/xml; charset=utf-8\r\n",
+ {http_header,42,'Content-Type',undefined, "text/xml; charset=utf-8"},
+ {http_header,42,'Content-Type',undefined,<<"text/xml; charset=utf-8">>}},
+ {"Other-Field: with some text\r\n",
+ {http_header,0, "Other-Field" ,undefined, "with some text"},
+ {http_header,0,<<"Other-Field">>,undefined,<<"with some text">>}},
+ {"Make-sure-a-LONG-HEaDer-fIeLd-is-fORMATTED-NicelY: with some text\r\n",
+ {http_header,0, "Make-Sure-A-Long-Header-Field-Is-Formatted-Nicely" ,undefined, "with some text"},
+ {http_header,0,<<"Make-Sure-A-Long-Header-Field-Is-Formatted-Nicely">>,undefined,<<"with some text">>}},
+ {"Multi-Line: Once upon a time in a land far far away,\r\n"
+ " there lived a princess imprisoned in the highest tower\r\n"
+ " of the most haunted castle.\r\n",
+ {http_header,0, "Multi-Line" ,undefined, "Once upon a time in a land far far away,\r\n there lived a princess imprisoned in the highest tower\r\n of the most haunted castle."},
+ {http_header,0,<<"Multi-Line">>,undefined,<<"Once upon a time in a land far far away,\r\n there lived a princess imprisoned in the highest tower\r\n of the most haunted castle.">>}},
+ {"\r\n",
+ http_eoh,
+ http_eoh}],
Bin = lists:foldl(fun({Line,_,_},Acc) -> LineBin = list_to_binary(Line),
- <<Acc/binary,LineBin/binary>> end,
- <<"">>, QnA),
+ <<Acc/binary,LineBin/binary>> end,
+ <<"">>, QnA),
MsgBin = list_to_binary(Msg),
{<<Bin/binary,MsgBin/binary>>, QnA}.
http_response(Msg) ->
QnA = [{"HTTP/1.0 404 Object Not Found\r\n",
- {http_response, {1,0}, 404, "Object Not Found"},
- {http_response, {1,0}, 404, <<"Object Not Found">>}},
- {"Server: inets/4.7.16\r\n",
- {http_header, 30, 'Server', undefined, "inets/4.7.16"},
- {http_header, 30, 'Server', undefined, <<"inets/4.7.16">>}},
- {"Date: Fri, 04 Jul 2008 17:16:22 GMT\r\n",
- {http_header, 3, 'Date', undefined, "Fri, 04 Jul 2008 17:16:22 GMT"},
- {http_header, 3, 'Date', undefined, <<"Fri, 04 Jul 2008 17:16:22 GMT">>}},
- {"Content-Type: text/html\r\n",
- {http_header, 42, 'Content-Type', undefined, "text/html"},
- {http_header, 42, 'Content-Type', undefined, <<"text/html">>}},
- {"Content-Length: 207\r\n",
- {http_header, 38, 'Content-Length', undefined, "207"},
- {http_header, 38, 'Content-Length', undefined, <<"207">>}},
- {"\r\n",
- http_eoh,
- http_eoh}],
+ {http_response, {1,0}, 404, "Object Not Found"},
+ {http_response, {1,0}, 404, <<"Object Not Found">>}},
+ {"Server: inets/4.7.16\r\n",
+ {http_header, 30, 'Server', undefined, "inets/4.7.16"},
+ {http_header, 30, 'Server', undefined, <<"inets/4.7.16">>}},
+ {"Date: Fri, 04 Jul 2008 17:16:22 GMT\r\n",
+ {http_header, 3, 'Date', undefined, "Fri, 04 Jul 2008 17:16:22 GMT"},
+ {http_header, 3, 'Date', undefined, <<"Fri, 04 Jul 2008 17:16:22 GMT">>}},
+ {"Content-Type: text/html\r\n",
+ {http_header, 42, 'Content-Type', undefined, "text/html"},
+ {http_header, 42, 'Content-Type', undefined, <<"text/html">>}},
+ {"Content-Length: 207\r\n",
+ {http_header, 38, 'Content-Length', undefined, "207"},
+ {http_header, 38, 'Content-Length', undefined, <<"207">>}},
+ {"\r\n",
+ http_eoh,
+ http_eoh}],
Bin = lists:foldl(fun({Line,_,_},Acc) -> LineBin = list_to_binary(Line),
- <<Acc/binary,LineBin/binary>> end,
- <<"">>, QnA),
+ <<Acc/binary,LineBin/binary>> end,
+ <<"">>, QnA),
MsgBin = list_to_binary(Msg),
{<<Bin/binary,MsgBin/binary>>, QnA}.
@@ -489,60 +464,56 @@ http_uri_variants() ->
{"something_else", "something_else", <<"something_else">>}].
-line(doc) -> [];
-line(suite) -> [];
line(Config) when is_list(Config) ->
Text = <<"POST /invalid/url HTTP/1.1\r\n"
- "Connection: close\r\n"
- "Host\t : localhost:8000\r\n"
- "User-Agent: perl post\r\n"
- "Content-Length: 4\r\n"
- "Content-Type: text/xml; charset=utf-8\r\n"
- "Other-Field: with some text\r\n"
- "Multi-Line: Once upon a time in a land far far away,\r\n"
- " there lived a princess imprisoned in the highest tower\r\n"
- " of the most haunted castle.\r\n"
- "\r\nThe residue">>,
+ "Connection: close\r\n"
+ "Host\t : localhost:8000\r\n"
+ "User-Agent: perl post\r\n"
+ "Content-Length: 4\r\n"
+ "Content-Type: text/xml; charset=utf-8\r\n"
+ "Other-Field: with some text\r\n"
+ "Multi-Line: Once upon a time in a land far far away,\r\n"
+ " there lived a princess imprisoned in the highest tower\r\n"
+ " of the most haunted castle.\r\n"
+ "\r\nThe residue">>,
lists:foreach(fun(MaxLen) -> line_do(Text,MaxLen) end,
- [0,7,19,29,37]),
+ [0,7,19,29,37]),
ok.
line_do(Bin,MaxLen) ->
Res = decode_pkt(line,Bin,[{line_length,MaxLen}]),
MyRes = decode_line(Bin,MaxLen),
- ?line MyRes = Res,
+ MyRes = Res,
case Res of
- {ok,_,Rest} ->
- line_do(Rest,MaxLen);
- {more,undefined} ->
- ok
+ {ok,_,Rest} ->
+ line_do(Rest,MaxLen);
+ {more,undefined} ->
+ ok
end.
-
+
% Emulates decode_packet(line,Bin,[{line_length,MaxLen}])
decode_line(Bin,MaxLen) ->
- ?line case find_in_binary($\n,Bin) of
- notfound when MaxLen>0 andalso byte_size(Bin) >= MaxLen ->
- {LineB,Rest} = split_binary(Bin,MaxLen),
- {ok,LineB,Rest};
- notfound ->
- {more,undefined};
- Pos when MaxLen>0 andalso Pos > MaxLen ->
- {LineB,Rest} = split_binary(Bin,MaxLen),
- {ok,LineB,Rest};
- Pos ->
- {LineB,Rest} = split_binary(Bin,Pos),
- {ok,LineB,Rest}
+ case find_in_binary($\n,Bin) of
+ notfound when MaxLen>0 andalso byte_size(Bin) >= MaxLen ->
+ {LineB,Rest} = split_binary(Bin,MaxLen),
+ {ok,LineB,Rest};
+ notfound ->
+ {more,undefined};
+ Pos when MaxLen>0 andalso Pos > MaxLen ->
+ {LineB,Rest} = split_binary(Bin,MaxLen),
+ {ok,LineB,Rest};
+ Pos ->
+ {LineB,Rest} = split_binary(Bin,Pos),
+ {ok,LineB,Rest}
end.
find_in_binary(Byte, Bin) ->
case string:chr(binary_to_list(Bin),Byte) of
- 0 -> notfound;
- P -> P
+ 0 -> notfound;
+ P -> P
end.
-ssl(doc) -> [];
-ssl(suite) -> [];
ssl(Config) when is_list(Config) ->
Major = 34,
Minor = 17,
@@ -550,15 +521,15 @@ ssl(Config) when is_list(Config) ->
Rest = <<23,123,203,12,234>>,
F = fun(Content) ->
- {Packet,Unpacked} = pack_ssl(Content, Major, Minor, Body),
- Bin = <<Packet/binary,Rest/binary>>,
- ?line {ok, Unpacked, Rest} = decode_pkt(ssl_tls, Bin)
- end,
+ {Packet,Unpacked} = pack_ssl(Content, Major, Minor, Body),
+ Bin = <<Packet/binary,Rest/binary>>,
+ {ok, Unpacked, Rest} = decode_pkt(ssl_tls, Bin)
+ end,
F(25),
F(v2hello),
ok.
-otp_8536(doc) -> ["Corrupt sub-binary-strings from httph_bin"];
+%% Corrupt sub-binary-strings from httph_bin
otp_8536(Config) when is_list(Config) ->
lists:foreach(fun otp_8536_do/1, lists:seq(1,50)),
ok.
@@ -571,7 +542,7 @@ otp_8536_do(N) ->
Bin = <<Hdr/binary, ": ", Data/binary, "\r\n\r\n">>,
io:format("Bin='~p'\n",[Bin]),
- ?line {ok,{http_header,0,Hdr2,undefined,Data2},<<"\r\n">>} = decode_pkt(httph_bin, Bin, []),
+ {ok,{http_header,0,Hdr2,undefined,Data2},<<"\r\n">>} = decode_pkt(httph_bin, Bin, []),
%% Do something to trash the C-stack, how about another decode_packet:
decode_pkt(httph_bin,<<Letters/binary, ": ", Data/binary, "\r\n\r\n">>, []),
@@ -587,8 +558,7 @@ decode_pkt(Type,Bin,Opts) ->
%%io:format(" -> ~p\n",[Res]),
Res.
-otp_9389(doc) -> ["Verify line_length works correctly for HTTP headers"];
-otp_9389(suite) -> [];
+%% Verify line_length works correctly for HTTP headers
otp_9389(Config) when is_list(Config) ->
Opts = [{packet_size, 16384}, {line_length, 3000}],
Pkt = list_to_binary(["GET / HTTP/1.1\r\nHost: localhost\r\nLink: /",
@@ -596,26 +566,25 @@ otp_9389(Config) when is_list(Config) ->
"\r\nContent-Length: 0\r\n\r\n"]),
<<Pkt1:5000/binary, Pkt2/binary>> = Pkt,
{ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest1} =
- erlang:decode_packet(http, Pkt1, Opts),
+ erlang:decode_packet(http, Pkt1, Opts),
{ok, {http_header,_,'Host',_,"localhost"}, Rest2} =
- erlang:decode_packet(httph, Rest1, Opts),
+ erlang:decode_packet(httph, Rest1, Opts),
{more, undefined} = erlang:decode_packet(httph, Rest2, Opts),
{ok, {http_header,_,"Link",_,Link}, Rest3} =
- erlang:decode_packet(httph, list_to_binary([Rest2, Pkt2]), Opts),
+ erlang:decode_packet(httph, list_to_binary([Rest2, Pkt2]), Opts),
true = (length(Link) > 8000),
{ok, {http_header,_,'Content-Length',_,"0"}, <<"\r\n">>} =
- erlang:decode_packet(httph, Rest3, Opts),
+ erlang:decode_packet(httph, Rest3, Opts),
ok.
-otp_9389_line(doc) -> ["Verify packet_size works correctly for line mode"];
-otp_9389_line(suite) -> [];
+%% Verify packet_size works correctly for line mode
otp_9389_line(Config) when is_list(Config) ->
Opts = [{packet_size, 20}],
Line1 = <<"0123456789012345678\n">>,
Line2 = <<"0123456789\n">>,
Line3 = <<"01234567890123456789\n">>,
Pkt = list_to_binary([Line1, Line2, Line3]),
- ?line {ok, Line1, Rest1} = erlang:decode_packet(line, Pkt, Opts),
- ?line {ok, Line2, Rest2} = erlang:decode_packet(line, Rest1, Opts),
- ?line {error, invalid} = erlang:decode_packet(line, Rest2, Opts),
+ {ok, Line1, Rest1} = erlang:decode_packet(line, Pkt, Opts),
+ {ok, Line2, Rest2} = erlang:decode_packet(line, Rest1, Opts),
+ {error, invalid} = erlang:decode_packet(line, Rest2, Opts),
ok.
diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl
index 151fab0a0e..f116ec979b 100644
--- a/erts/emulator/test/distribution_SUITE.erl
+++ b/erts/emulator/test/distribution_SUITE.erl
@@ -33,41 +33,40 @@
%% Tests distribution and the tcp driver.
--include_lib("test_server/include/test_server.hrl").
-
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- ping/1, bulk_send_small/1,
- bulk_send_big/1, bulk_send_bigbig/1,
- local_send_small/1, local_send_big/1,
- local_send_legal/1, link_to_busy/1, exit_to_busy/1,
- lost_exit/1, link_to_dead/1, link_to_dead_new_node/1,
- applied_monitor_node/1, ref_port_roundtrip/1, nil_roundtrip/1,
- trap_bif_1/1, trap_bif_2/1, trap_bif_3/1,
- stop_dist/1,
- dist_auto_connect_never/1, dist_auto_connect_once/1,
- dist_parallel_send/1,
- atom_roundtrip/1,
- unicode_atom_roundtrip/1,
- atom_roundtrip_r15b/1,
- contended_atom_cache_entry/1,
- contended_unicode_atom_cache_entry/1,
- bad_dist_structure/1,
- bad_dist_ext_receive/1,
- bad_dist_ext_process_info/1,
- bad_dist_ext_control/1,
- bad_dist_ext_connection_id/1]).
-
--export([init_per_testcase/2, end_per_testcase/2]).
+-include_lib("common_test/include/ct.hrl").
+
+-export([all/0, suite/0, groups/0,
+ ping/1, bulk_send_small/1,
+ bulk_send_big/1, bulk_send_bigbig/1,
+ local_send_small/1, local_send_big/1,
+ local_send_legal/1, link_to_busy/1, exit_to_busy/1,
+ lost_exit/1, link_to_dead/1, link_to_dead_new_node/1,
+ applied_monitor_node/1, ref_port_roundtrip/1, nil_roundtrip/1,
+ trap_bif_1/1, trap_bif_2/1, trap_bif_3/1,
+ stop_dist/1,
+ dist_auto_connect_never/1, dist_auto_connect_once/1,
+ dist_parallel_send/1,
+ atom_roundtrip/1,
+ unicode_atom_roundtrip/1,
+ atom_roundtrip_r15b/1,
+ contended_atom_cache_entry/1,
+ contended_unicode_atom_cache_entry/1,
+ bad_dist_structure/1,
+ bad_dist_ext_receive/1,
+ bad_dist_ext_process_info/1,
+ bad_dist_ext_control/1,
+ bad_dist_ext_connection_id/1]).
%% Internal exports.
-export([sender/3, receiver2/2, dummy_waiter/0, dead_process/0,
- roundtrip/1, bounce/1, do_dist_auto_connect/1, inet_rpc_server/1,
- dist_parallel_sender/3, dist_parallel_receiver/0,
- dist_evil_parallel_receiver/0,
+ roundtrip/1, bounce/1, do_dist_auto_connect/1, inet_rpc_server/1,
+ dist_parallel_sender/3, dist_parallel_receiver/0,
+ dist_evil_parallel_receiver/0,
sendersender/4, sendersender2/4]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 4}}].
all() ->
[ping, {group, bulk_send}, {group, local_send},
@@ -90,80 +89,54 @@ groups() ->
[bad_dist_ext_receive, bad_dist_ext_process_info,
bad_dist_ext_control, bad_dist_ext_connection_id]}].
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
--define(DEFAULT_TIMETRAP, 4*60*1000).
-
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?t:timetrap(?DEFAULT_TIMETRAP),
- [{watchdog, Dog},{testcase, Func}|Config].
-
-end_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
-ping(doc) ->
- ["Tests pinging a node in different ways."];
+%% Tests pinging a node in different ways.
ping(Config) when is_list(Config) ->
Times = 1024,
%% Ping a non-existing node many times. This used to crash the emulator
%% on Windows.
- ?line Host = hostname(),
- ?line BadName = list_to_atom("__pucko__@" ++ Host),
- ?line io:format("Pinging ~s (assumed to not exist)", [BadName]),
- ?line test_server:do_times(Times, fun() -> pang = net_adm:ping(BadName)
- end),
+ Host = hostname(),
+ BadName = list_to_atom("__pucko__@" ++ Host),
+ io:format("Pinging ~s (assumed to not exist)", [BadName]),
+ test_server:do_times(Times, fun() -> pang = net_adm:ping(BadName)
+ end),
%% Pings another node.
- ?line {ok, OtherNode} = start_node(distribution_SUITE_other),
- ?line io:format("Pinging ~s (assumed to exist)", [OtherNode]),
- ?line test_server:do_times(Times, fun() -> pong = net_adm:ping(OtherNode) end),
- ?line stop_node(OtherNode),
+ {ok, OtherNode} = start_node(distribution_SUITE_other),
+ io:format("Pinging ~s (assumed to exist)", [OtherNode]),
+ test_server:do_times(Times, fun() -> pong = net_adm:ping(OtherNode) end),
+ stop_node(OtherNode),
%% Pings our own node many times.
- ?line Node = node(),
- ?line io:format("Pinging ~s (the same node)", [Node]),
- ?line test_server:do_times(Times, fun() -> pong = net_adm:ping(Node) end),
+ Node = node(),
+ io:format("Pinging ~s (the same node)", [Node]),
+ test_server:do_times(Times, fun() -> pong = net_adm:ping(Node) end),
ok.
bulk_send_small(Config) when is_list(Config) ->
- ?line bulk_send(64, 32).
+ bulk_send(64, 32).
bulk_send_big(Config) when is_list(Config) ->
- ?line bulk_send(32, 64).
+ bulk_send(32, 64).
bulk_send_bigbig(Config) when is_list(Config) ->
- ?line bulk_sendsend(32*5, 4).
+ bulk_sendsend(32*5, 4).
bulk_send(Terms, BinSize) ->
- ?line Dog = test_server:timetrap(test_server:seconds(30)),
-
- ?line io:format("Sending ~w binaries, each of size ~w K",
- [Terms, BinSize]),
- ?line {ok, Node} = start_node(bulk_receiver),
- ?line Recv = spawn(Node, erlang, apply, [fun receiver/2, [0, 0]]),
- ?line Bin = list_to_binary(lists:duplicate(BinSize*1024, 253)),
- ?line Size = Terms*size(Bin),
- ?line {Elapsed, {Terms, Size}} = test_server:timecall(?MODULE, sender,
- [Recv, Bin, Terms]),
- ?line stop_node(Node),
-
- ?line test_server:timetrap_cancel(Dog),
+ ct:timetrap({seconds, 30}),
+
+ io:format("Sending ~w binaries, each of size ~w K", [Terms, BinSize]),
+ {ok, Node} = start_node(bulk_receiver),
+ Recv = spawn(Node, erlang, apply, [fun receiver/2, [0, 0]]),
+ Bin = list_to_binary(lists:duplicate(BinSize*1024, 253)),
+ Size = Terms*size(Bin),
+ {Elapsed, {Terms, Size}} = test_server:timecall(?MODULE, sender,
+ [Recv, Bin, Terms]),
+ stop_node(Node),
{comment, integer_to_list(trunc(Size/1024/max(1,Elapsed)+0.5)) ++ " K/s"}.
bulk_sendsend(Terms, BinSize) ->
@@ -173,29 +146,29 @@ bulk_sendsend(Terms, BinSize) ->
true -> MonitorCount1 / MonitorCount2
end,
Comment = integer_to_list(Rate1) ++ " K/s, " ++
- integer_to_list(Rate2) ++ " K/s, " ++
- integer_to_list(MonitorCount1) ++ " monitor msgs, " ++
- integer_to_list(MonitorCount2) ++ " monitor msgs, " ++
- float_to_list(Ratio) ++ " monitor ratio",
+ integer_to_list(Rate2) ++ " K/s, " ++
+ integer_to_list(MonitorCount1) ++ " monitor msgs, " ++
+ integer_to_list(MonitorCount2) ++ " monitor msgs, " ++
+ float_to_list(Ratio) ++ " monitor ratio",
if
- %% A somewhat arbitrary ratio, but hopefully one that will
- %% accommodate a wide range of CPU speeds.
- Ratio > 8.0 ->
- {comment,Comment};
- true ->
- io:put_chars(Comment),
- ?line ?t:fail(ratio_too_low)
+ %% A somewhat arbitrary ratio, but hopefully one that will
+ %% accommodate a wide range of CPU speeds.
+ Ratio > 8.0 ->
+ {comment,Comment};
+ true ->
+ io:put_chars(Comment),
+ ct:fail(ratio_too_low)
end.
bulk_sendsend2(Terms, BinSize, BusyBufSize) ->
- ?line Dog = test_server:timetrap(test_server:seconds(30)),
+ ct:timetrap({seconds, 30}),
- ?line io:format("Sending ~w binaries, each of size ~w K",
- [Terms, BinSize]),
- ?line {ok, NodeRecv} = start_node(bulk_receiver),
- ?line Recv = spawn(NodeRecv, erlang, apply, [fun receiver/2, [0, 0]]),
- ?line Bin = list_to_binary(lists:duplicate(BinSize*1024, 253)),
- %%?line Size = Terms*size(Bin),
+ io:format("Sending ~w binaries, each of size ~w K",
+ [Terms, BinSize]),
+ {ok, NodeRecv} = start_node(bulk_receiver),
+ Recv = spawn(NodeRecv, erlang, apply, [fun receiver/2, [0, 0]]),
+ Bin = list_to_binary(lists:duplicate(BinSize*1024, 253)),
+ %%Size = Terms*size(Bin),
%% SLF LEFT OFF HERE.
%% When the caller uses small hunks, like 4k via
@@ -206,23 +179,21 @@ bulk_sendsend2(Terms, BinSize, BusyBufSize) ->
%% default busy size and "+zdbbl 5", and if the 5 case gets
%% "many many more" monitor messages, then we know we're working.
- ?line {ok, NodeSend} = start_node(bulk_sender, "+zdbbl " ++ integer_to_list(BusyBufSize)),
- ?line _Send = spawn(NodeSend, erlang, apply, [fun sendersender/4, [self(), Recv, Bin, Terms]]),
- ?line {Elapsed, {_TermsN, SizeN}, MonitorCount} =
- receive {sendersender, BigRes} ->
+ {ok, NodeSend} = start_node(bulk_sender, "+zdbbl " ++ integer_to_list(BusyBufSize)),
+ _Send = spawn(NodeSend, erlang, apply, [fun sendersender/4, [self(), Recv, Bin, Terms]]),
+ {Elapsed, {_TermsN, SizeN}, MonitorCount} =
+ receive {sendersender, BigRes} ->
BigRes
- end,
- ?line stop_node(NodeRecv),
- ?line stop_node(NodeSend),
-
- ?line test_server:timetrap_cancel(Dog),
+ end,
+ stop_node(NodeRecv),
+ stop_node(NodeSend),
{trunc(SizeN/1024/Elapsed+0.5), MonitorCount}.
sender(To, _Bin, 0) ->
To ! {done, self()},
receive
- Any ->
- Any
+ Any ->
+ Any
end;
sender(To, Bin, Left) ->
To ! {term, Bin},
@@ -233,9 +204,9 @@ sender(To, Bin, Left) ->
sendersender(Parent, To, Bin, Left) ->
erlang:system_monitor(self(), [busy_dist_port]),
[spawn(fun() -> sendersender2(To, Bin, Left, false) end) ||
- _ <- lists:seq(1,1)],
+ _ <- lists:seq(1,1)],
{USec, {Res, MonitorCount}} =
- timer:tc(?MODULE, sendersender2, [To, Bin, Left, true]),
+ timer:tc(?MODULE, sendersender2, [To, Bin, Left, true]),
Parent ! {sendersender, {USec/1000000, Res, MonitorCount}}.
sendersender2(To, Bin, Left, SendDone) ->
@@ -243,22 +214,22 @@ sendersender2(To, Bin, Left, SendDone) ->
sendersender3(To, _Bin, 0, SendDone, MonitorCount) ->
if SendDone ->
- To ! {done, self()};
+ To ! {done, self()};
true ->
- ok
+ ok
end,
receive
{monitor, _Pid, _Type, _Info} ->
sendersender3(To, _Bin, 0, SendDone, MonitorCount + 1)
after 0 ->
- if SendDone ->
- receive
- Any when is_tuple(Any), size(Any) == 2 ->
- {Any, MonitorCount}
- end;
- true ->
- exit(normal)
- end
+ if SendDone ->
+ receive
+ Any when is_tuple(Any), size(Any) == 2 ->
+ {Any, MonitorCount}
+ end;
+ true ->
+ exit(normal)
+ end
end;
sendersender3(To, Bin, Left, SendDone, MonitorCount) ->
To ! {term, Bin},
@@ -269,80 +240,74 @@ sendersender3(To, Bin, Left, SendDone, MonitorCount) ->
receiver(Terms, Size) ->
receive
- {term, Bin} ->
- receiver(Terms+1, Size+size(Bin));
- {done, ReplyTo} ->
- ReplyTo ! {Terms, Size}
+ {term, Bin} ->
+ receiver(Terms+1, Size+size(Bin));
+ {done, ReplyTo} ->
+ ReplyTo ! {Terms, Size}
end.
-local_send_big(doc) ->
- ["Sends several big message to an non-registered process on ",
- "the local node."];
+%% Sends several big message to an non-registered process on the local node.
local_send_big(Config) when is_list(Config) ->
- Data0=local_send_big(doc)++
- ["Tests sending small and big messages to a non-existing ",
- "local registered process."],
+ Data0= ["Tests sending small and big messages to a non-existing ",
+ "local registered process."],
Data1=[Data0,[Data0, Data0, [Data0], Data0],Data0],
Data2=Data0++lists:flatten(Data1)++
- list_to_binary(lists:flatten(Data1)),
+ list_to_binary(lists:flatten(Data1)),
Func=fun() -> Data2= {arbitrary_name, node()} ! Data2 end,
- ?line test_server:do_times(4096, Func),
+ test_server:do_times(4096, Func),
ok.
-local_send_small(doc) ->
- ["Sends a small message to an non-registered process on the ",
- "local node."];
+%% Sends a small message to an non-registered process on the local node.
local_send_small(Config) when is_list(Config) ->
Data={some_stupid, "arbitrary", 'Data'},
Func=fun() -> Data= {unregistered_name, node()} ! Data end,
- ?line test_server:do_times(4096, Func),
+ test_server:do_times(4096, Func),
ok.
-local_send_legal(doc) ->
- ["Sends data to a registered process on the local node, ",
- "as if it was on another node."];
+%% Sends data to a registered process on the local node, as if it was on another node.
local_send_legal(Config) when is_list(Config) ->
Times=16384,
- Data={local_send_legal(doc), local_send_legal(doc)},
+ Txt = "Some Not so random Data",
+ Data={[Txt,Txt,Txt], [Txt,Txt,Txt]},
Pid=spawn(?MODULE,receiver2, [0, 0]) ,
- ?line true=register(registered_process, Pid),
+ true=register(registered_process, Pid),
Func=fun() -> Data={registered_process, node()} ! Data end,
TotalSize=size(Data)*Times,
- ?line test_server:do_times(Times, Func),
+ test_server:do_times(Times, Func),
% Check that all msgs really came through.
Me=self(),
- ?line {done, Me}=
- {registered_process, node()} ! {done, Me},
+ {done, Me}=
+ {registered_process, node()} ! {done, Me},
receive
- {Times, TotalSize} ->
- ok;
- _ ->
- test_server:fail("Wrong number of msgs received.")
+ {Times, TotalSize} ->
+ ok;
+ _ ->
+ ct:fail("Wrong number of msgs received.")
end,
ok.
receiver2(Num, TotSize) ->
receive
- {done, ReplyTo} ->
- ReplyTo ! {Num, TotSize};
- Stuff ->
- receiver2(Num+1, TotSize+size(Stuff))
+ {done, ReplyTo} ->
+ ReplyTo ! {Num, TotSize};
+ Stuff ->
+ receiver2(Num+1, TotSize+size(Stuff))
end.
-link_to_busy(doc) -> "Test that link/1 to a busy distribution port works.";
+%% Test that link/1 to a busy distribution port works.
link_to_busy(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(60)),
- ?line {ok, Node} = start_node(link_to_busy),
- ?line Recv = spawn(Node, erlang, apply, [fun sink/1, [link_to_busy_sink]]),
+ ct:timetrap({seconds, 60}),
+ {ok, Node} = start_node(link_to_busy),
+ Recv = spawn(Node, erlang, apply, [fun sink/1, [link_to_busy_sink]]),
Tracer = case os:getenv("TRACE_BUSY_DIST_PORT") of
- "true" -> start_busy_dist_port_tracer();
- _ -> false
- end,
+ "true" -> start_busy_dist_port_tracer();
+ _ -> false
+ end,
%% We will spawn off a process which will try to link to the other
%% node. The linker process will not actually run until this
@@ -351,20 +316,19 @@ link_to_busy(Config) when is_list(Config) ->
%% process will block, too, because of the because busy port,
%% and will later be restarted.
- ?line do_busy_test(Node, fun () -> linker(Recv) end),
+ do_busy_test(Node, fun () -> linker(Recv) end),
%% Same thing, but we apply link/1 instead of calling it directly.
- ?line do_busy_test(Node, fun () -> applied_linker(Recv) end),
+ do_busy_test(Node, fun () -> applied_linker(Recv) end),
%% Same thing again, but we apply link/1 in the tail of a function.
- ?line do_busy_test(Node, fun () -> tail_applied_linker(Recv) end),
+ do_busy_test(Node, fun () -> tail_applied_linker(Recv) end),
%% Done.
- ?line stop_node(Node),
- ?line stop_busy_dist_port_tracer(Tracer),
- ?line test_server:timetrap_cancel(Dog),
+ stop_node(Node),
+ stop_busy_dist_port_tracer(Tracer),
ok.
linker(Pid) ->
@@ -379,16 +343,16 @@ applied_linker(Pid) ->
tail_applied_linker(Pid) ->
apply(erlang, link, [Pid]).
-
-exit_to_busy(doc) -> "Test that exit/2 to a busy distribution port works.";
+
+%% Test that exit/2 to a busy distribution port works.
exit_to_busy(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(60)),
- ?line {ok, Node} = start_node(exit_to_busy),
+ ct:timetrap({seconds, 60}),
+ {ok, Node} = start_node(exit_to_busy),
Tracer = case os:getenv("TRACE_BUSY_DIST_PORT") of
- "true" -> start_busy_dist_port_tracer();
- _ -> false
- end,
+ "true" -> start_busy_dist_port_tracer();
+ _ -> false
+ end,
%% We will spawn off a process which will try to exit a process on
%% the other node. That process will not actually run until this
@@ -397,59 +361,58 @@ exit_to_busy(Config) when is_list(Config) ->
%% too, because of the busy distribution port, and will be allowed
%% to continue when the port becomes non-busy.
- ?line Recv1 = spawn(Node, fun () -> sink(exit_to_busy_sink) end),
- ?line M1 = erlang:monitor(process, Recv1),
- ?line do_busy_test(Node, fun () -> joey_killer(Recv1) end),
- ?line receive
- {'DOWN', M1, process, Recv1, R1} ->
- ?line joey_said_die = R1
- end,
+ Recv1 = spawn(Node, fun () -> sink(exit_to_busy_sink) end),
+ M1 = erlang:monitor(process, Recv1),
+ do_busy_test(Node, fun () -> joey_killer(Recv1) end),
+ receive
+ {'DOWN', M1, process, Recv1, R1} ->
+ joey_said_die = R1
+ end,
%% Same thing, but tail call to exit/2.
- ?line Recv2 = spawn(Node, fun () -> sink(exit_to_busy_sink) end),
- ?line M2 = erlang:monitor(process, Recv2),
- ?line do_busy_test(Node, fun () -> tail_joey_killer(Recv2) end),
- ?line receive
- {'DOWN', M2, process, Recv2, R2} ->
- ?line joey_said_die = R2
- end,
+ Recv2 = spawn(Node, fun () -> sink(exit_to_busy_sink) end),
+ M2 = erlang:monitor(process, Recv2),
+ do_busy_test(Node, fun () -> tail_joey_killer(Recv2) end),
+ receive
+ {'DOWN', M2, process, Recv2, R2} ->
+ joey_said_die = R2
+ end,
%% Same thing, but we apply exit/2 instead of calling it directly.
- ?line Recv3 = spawn(Node, fun () -> sink(exit_to_busy_sink) end),
- ?line M3 = erlang:monitor(process, Recv3),
- ?line do_busy_test(Node, fun () -> applied_joey_killer(Recv3) end),
- ?line receive
- {'DOWN', M3, process, Recv3, R3} ->
- ?line joey_said_die = R3
- end,
+ Recv3 = spawn(Node, fun () -> sink(exit_to_busy_sink) end),
+ M3 = erlang:monitor(process, Recv3),
+ do_busy_test(Node, fun () -> applied_joey_killer(Recv3) end),
+ receive
+ {'DOWN', M3, process, Recv3, R3} ->
+ joey_said_die = R3
+ end,
%% Same thing again, but we apply exit/2 in the tail of a function.
- ?line Recv4 = spawn(Node, fun () -> sink(exit_to_busy_sink) end),
- ?line M4 = erlang:monitor(process, Recv4),
- ?line do_busy_test(Node, fun () -> tail_applied_joey_killer(Recv4) end),
- ?line receive
- {'DOWN', M4, process, Recv4, R4} ->
- ?line joey_said_die = R4
- end,
-
+ Recv4 = spawn(Node, fun () -> sink(exit_to_busy_sink) end),
+ M4 = erlang:monitor(process, Recv4),
+ do_busy_test(Node, fun () -> tail_applied_joey_killer(Recv4) end),
+ receive
+ {'DOWN', M4, process, Recv4, R4} ->
+ joey_said_die = R4
+ end,
+
%% Done.
- ?line stop_node(Node),
- ?line stop_busy_dist_port_tracer(Tracer),
- ?line test_server:timetrap_cancel(Dog),
+ stop_node(Node),
+ stop_busy_dist_port_tracer(Tracer),
ok.
make_busy_data() ->
Size = 1024*1024,
Key = '__busy__port__data__',
case get(Key) of
- undefined ->
- Data = list_to_binary(lists:duplicate(Size, 253)),
- put(Key, Data),
- Data;
- Data ->
- true = is_binary(Data),
- true = size(Data) == Size,
- Data
+ undefined ->
+ Data = list_to_binary(lists:duplicate(Size, 253)),
+ put(Key, Data),
+ Data;
+ Data ->
+ true = is_binary(Data),
+ true = size(Data) == Size,
+ Data
end.
make_busy(Node, Time) when is_integer(Time) ->
@@ -458,27 +421,27 @@ make_busy(Node, Time) when is_integer(Time) ->
Data = make_busy_data(),
%% first make port busy
Pid = spawn_link(fun () ->
- forever(fun () ->
- dport_reg_send(Node,
- '__noone__',
- Data)
- end)
- end),
+ forever(fun () ->
+ dport_reg_send(Node,
+ '__noone__',
+ Data)
+ end)
+ end),
receive after Own -> ok end,
until(fun () ->
- case process_info(Pid, status) of
- {status, suspended} -> true;
- _ -> false
- end
- end),
+ case process_info(Pid, status) of
+ {status, suspended} -> true;
+ _ -> false
+ end
+ end),
%% then dist entry
make_busy(Node, [nosuspend], Data),
Pid.
make_busy(Node, Opts, Data) ->
case erlang:send({'__noone__', Node}, Data, Opts) of
- nosuspend -> nosuspend;
- _ -> make_busy(Node, Opts, Data)
+ nosuspend -> nosuspend;
+ _ -> make_busy(Node, Opts, Data)
end.
unmake_busy(Pid) ->
@@ -491,29 +454,29 @@ do_busy_test(Node, Fun) ->
receive after 100 -> ok end,
Pinfo = process_info(P, [status, current_function]),
unmake_busy(Busy),
- ?t:format("~p : ~p~n", [P, Pinfo]),
+ io:format("~p : ~p~n", [P, Pinfo]),
case Pinfo of
- undefined ->
- receive
- {'DOWN', M, process, P, Reason} ->
- ?t:format("~p died with exit reason ~p~n", [P, Reason])
- end,
- ?t:fail(premature_death);
- _ ->
- %% Don't match arity; it is different in debug and
- %% optimized emulator
- [{status, suspended},
- {current_function, {erlang, bif_return_trap, _}}] = Pinfo,
- receive
- {'DOWN', M, process, P, Reason} ->
- ?t:format("~p died with exit reason ~p~n", [P, Reason]),
- normal = Reason
- end
+ undefined ->
+ receive
+ {'DOWN', M, process, P, Reason} ->
+ io:format("~p died with exit reason ~p~n", [P, Reason])
+ end,
+ ct:fail(premature_death);
+ _ ->
+ %% Don't match arity; it is different in debug and
+ %% optimized emulator
+ [{status, suspended},
+ {current_function, {erlang, bif_return_trap, _}}] = Pinfo,
+ receive
+ {'DOWN', M, process, P, Reason} ->
+ io:format("~p died with exit reason ~p~n", [P, Reason]),
+ normal = Reason
+ end
end.
remote_is_process_alive(Pid) ->
rpc:call(node(Pid), erlang, is_process_alive,
- [Pid]).
+ [Pid]).
joey_killer(Pid) ->
exit(Pid, joey_said_die),
@@ -535,234 +498,227 @@ sink(Name) ->
sink1() ->
receive
- _Any -> sink1()
+ _Any -> sink1()
end.
-lost_exit(doc) ->
- "Test that EXIT and DOWN messages send to another node are not lost if "
- "the distribution port is busy.";
+%% Test that EXIT and DOWN messages send to another node are not lost if
+%% the distribution port is busy.
lost_exit(Config) when is_list(Config) ->
- ?line {ok, Node} = start_node(lost_exit),
+ {ok, Node} = start_node(lost_exit),
Tracer = case os:getenv("TRACE_BUSY_DIST_PORT") of
- "true" -> start_busy_dist_port_tracer();
- _ -> false
- end,
+ "true" -> start_busy_dist_port_tracer();
+ _ -> false
+ end,
Self = self(),
Die = make_ref(),
- ?line R1 = spawn(fun () -> receive after infinity -> ok end end),
- ?line MR1 = erlang:monitor(process, R1),
-
- ?line {L1, ML1} = spawn_monitor(fun() ->
- link(R1),
- Self ! {self(), linked},
- receive
- Die ->
- exit(controlled_suicide)
- end
- end),
-
- ?line R2 = spawn(fun () ->
- M = erlang:monitor(process, L1),
- receive
- {'DOWN', M, process, L1, R} ->
- Self ! {self(), got_down_message, L1, R}
- end
- end),
-
- ?line receive {L1, linked} -> ok end,
-
+ R1 = spawn(fun () -> receive after infinity -> ok end end),
+ MR1 = erlang:monitor(process, R1),
+
+ {L1, ML1} = spawn_monitor(fun() ->
+ link(R1),
+ Self ! {self(), linked},
+ receive
+ Die ->
+ exit(controlled_suicide)
+ end
+ end),
+
+ R2 = spawn(fun () ->
+ M = erlang:monitor(process, L1),
+ receive
+ {'DOWN', M, process, L1, R} ->
+ Self ! {self(), got_down_message, L1, R}
+ end
+ end),
+
+ receive {L1, linked} -> ok end,
+
Busy = make_busy(Node, 2000),
receive after 100 -> ok end,
L1 ! Die,
- ?line receive
- {'DOWN', ML1, process, L1, RL1} ->
- ?line controlled_suicide = RL1
- end,
+ receive
+ {'DOWN', ML1, process, L1, RL1} ->
+ controlled_suicide = RL1
+ end,
receive after 500 -> ok end,
unmake_busy(Busy),
- ?line receive
- {'DOWN', MR1, process, R1, RR1} ->
- ?line controlled_suicide = RR1
- end,
-
- ?line receive
- {R2, got_down_message, L1, RR2} ->
- ?line controlled_suicide = RR2
- end,
+ receive
+ {'DOWN', MR1, process, R1, RR1} ->
+ controlled_suicide = RR1
+ end,
+
+ receive
+ {R2, got_down_message, L1, RR2} ->
+ controlled_suicide = RR2
+ end,
%% Done.
- ?line stop_busy_dist_port_tracer(Tracer),
- ?line stop_node(Node),
+ stop_busy_dist_port_tracer(Tracer),
+ stop_node(Node),
ok.
dummy_waiter() ->
receive
after infinity ->
- ok
+ ok
end.
-link_to_dead(doc) ->
- ["Test that linking to a dead remote process gives an EXIT message ",
- "AND that the link is teared down."];
+%% Test that linking to a dead remote process gives an EXIT message
+%% AND that the link is teared down.
link_to_dead(Config) when is_list(Config) ->
- ?line process_flag(trap_exit, true),
- ?line {ok, Node} = start_node(link_to_dead),
-% ?line monitor_node(Node, true),
- ?line net_adm:ping(Node), %% Ts_cross_server workaround.
- ?line Pid = spawn(Node, ?MODULE, dead_process, []),
+ process_flag(trap_exit, true),
+ {ok, Node} = start_node(link_to_dead),
+ % monitor_node(Node, true),
+ net_adm:ping(Node), %% Ts_cross_server workaround.
+ Pid = spawn(Node, ?MODULE, dead_process, []),
receive
after 5000 -> ok
end,
- ?line link(Pid),
- ?line receive
- {'EXIT', Pid, noproc} ->
- ok;
- Other ->
- ?line test_server:fail({unexpected_message, Other})
- after 5000 ->
- ?line test_server:fail(nothing_received)
- end,
- ?line {links, Links} = process_info(self(), links),
- ?line io:format("Pid=~p, links=~p", [Pid, Links]),
- ?line false = lists:member(Pid, Links),
- ?line stop_node(Node),
- ?line receive
- Message ->
- ?line test_server:fail({unexpected_message, Message})
- after 3000 ->
- ok
- end,
+ link(Pid),
+ receive
+ {'EXIT', Pid, noproc} ->
+ ok;
+ Other ->
+ ct:fail({unexpected_message, Other})
+ after 5000 ->
+ ct:fail(nothing_received)
+ end,
+ {links, Links} = process_info(self(), links),
+ io:format("Pid=~p, links=~p", [Pid, Links]),
+ false = lists:member(Pid, Links),
+ stop_node(Node),
+ receive
+ Message ->
+ ct:fail({unexpected_message, Message})
+ after 3000 ->
+ ok
+ end,
ok.
-
+
dead_process() ->
erlang:error(die).
-link_to_dead_new_node(doc) ->
- ["Test that linking to a pid on node that has gone and restarted gives ",
- "the correct EXIT message (OTP-2304)."];
+%% Test that linking to a pid on node that has gone and restarted gives
+%% the correct EXIT message (OTP-2304).
link_to_dead_new_node(Config) when is_list(Config) ->
- ?line process_flag(trap_exit, true),
+ process_flag(trap_exit, true),
%% Start the node, get a Pid and stop the node again.
- ?line {ok, Node} = start_node(link_to_dead_new_node),
- ?line Pid = spawn(Node, ?MODULE, dead_process, []),
- ?line stop_node(Node),
+ {ok, Node} = start_node(link_to_dead_new_node),
+ Pid = spawn(Node, ?MODULE, dead_process, []),
+ stop_node(Node),
%% Start a new node with the same name.
- ?line {ok, Node} = start_node(link_to_dead_new_node),
- ?line link(Pid),
- ?line receive
- {'EXIT', Pid, noproc} ->
- ok;
- Other ->
- ?line test_server:fail({unexpected_message, Other})
- after 5000 ->
- ?line test_server:fail(nothing_received)
- end,
+ {ok, Node} = start_node(link_to_dead_new_node),
+ link(Pid),
+ receive
+ {'EXIT', Pid, noproc} ->
+ ok;
+ Other ->
+ ct:fail({unexpected_message, Other})
+ after 5000 ->
+ ct:fail(nothing_received)
+ end,
%% Make sure that the link wasn't created.
- ?line {links, Links} = process_info(self(), links),
- ?line io:format("Pid=~p, links=~p", [Pid, Links]),
- ?line false = lists:member(Pid, Links),
- ?line stop_node(Node),
- ?line receive
- Message ->
- ?line test_server:fail({unexpected_message, Message})
- after 3000 ->
- ok
- end,
+ {links, Links} = process_info(self(), links),
+ io:format("Pid=~p, links=~p", [Pid, Links]),
+ false = lists:member(Pid, Links),
+ stop_node(Node),
+ receive
+ Message ->
+ ct:fail({unexpected_message, Message})
+ after 3000 ->
+ ok
+ end,
ok.
-applied_monitor_node(doc) ->
- "Test that monitor_node/2 works when applied.";
+%% Test that monitor_node/2 works when applied.
applied_monitor_node(Config) when is_list(Config) ->
- ?line NonExisting = list_to_atom("__non_existing__@" ++ hostname()),
+ NonExisting = list_to_atom("__non_existing__@" ++ hostname()),
%% Tail-recursive call to apply (since the node is non-existing,
%% there will be a trap).
- ?line true = tail_apply(erlang, monitor_node, [NonExisting, true]),
- ?line [{nodedown, NonExisting}] = test_server:messages_get(),
+ true = tail_apply(erlang, monitor_node, [NonExisting, true]),
+ [{nodedown, NonExisting}] = test_server:messages_get(),
%% Ordinary call (with trap).
- ?line true = apply(erlang, monitor_node, [NonExisting, true]),
- ?line [{nodedown, NonExisting}] = test_server:messages_get(),
-
+ true = apply(erlang, monitor_node, [NonExisting, true]),
+ [{nodedown, NonExisting}] = test_server:messages_get(),
+
ok.
tail_apply(M, F, A) ->
apply(M, F, A).
-ref_port_roundtrip(doc) ->
- "Test that sending a port or reference to another node and back again "
- "doesn't correct them in any way.";
+%% Test that sending a port or reference to another node and back again
+%% doesn't correct them in any way.
ref_port_roundtrip(Config) when is_list(Config) ->
- ?line process_flag(trap_exit, true),
- ?line Port = open_port({spawn, efile}, []),
- ?line Ref = make_ref(),
- ?line {ok, Node} = start_node(ref_port_roundtrip),
- ?line net_adm:ping(Node),
- ?line Term = {Port, Ref},
- ?line io:format("Term before: ~p", [show_term(Term)]),
- ?line Pid = spawn_link(Node, ?MODULE, roundtrip, [Term]),
- ?line receive after 5000 -> ok end,
- ?line stop_node(Node),
- ?line receive
- {'EXIT', Pid, {Port, Ref}} ->
- ?line io:format("Term after: ~p", [show_term(Term)]),
- ok;
- Other ->
- ?line io:format("Term after: ~p", [show_term(Term)]),
- ?line test_server:fail({unexpected, Other})
- after 10000 ->
- ?line test_server:fail(timeout)
- end,
+ process_flag(trap_exit, true),
+ Port = open_port({spawn, efile}, []),
+ Ref = make_ref(),
+ {ok, Node} = start_node(ref_port_roundtrip),
+ net_adm:ping(Node),
+ Term = {Port, Ref},
+ io:format("Term before: ~p", [show_term(Term)]),
+ Pid = spawn_link(Node, ?MODULE, roundtrip, [Term]),
+ receive after 5000 -> ok end,
+ stop_node(Node),
+ receive
+ {'EXIT', Pid, {Port, Ref}} ->
+ io:format("Term after: ~p", [show_term(Term)]),
+ ok;
+ Other ->
+ io:format("Term after: ~p", [show_term(Term)]),
+ ct:fail({unexpected, Other})
+ after 10000 ->
+ ct:fail(timeout)
+ end,
ok.
roundtrip(Term) ->
exit(Term).
-nil_roundtrip(doc) ->
- "Test that the smallest external term [] aka NIL can be sent to "
- "another node node and back again.";
+%% Test that the smallest external term [] aka NIL can be sent to
+%% another node node and back again.
nil_roundtrip(Config) when is_list(Config) ->
- ?line process_flag(trap_exit, true),
- ?line {ok, Node} = start_node(nil_roundtrip),
- ?line net_adm:ping(Node),
- ?line Pid = spawn_link(Node, ?MODULE, bounce, [self()]),
- ?line Pid ! [],
- ?line receive
- [] ->
- ?line receive
- {'EXIT', Pid, []} ->
- ?line stop_node(Node),
- ok
- end
- end.
+ process_flag(trap_exit, true),
+ {ok, Node} = start_node(nil_roundtrip),
+ net_adm:ping(Node),
+ Pid = spawn_link(Node, ?MODULE, bounce, [self()]),
+ Pid ! [],
+ receive
+ [] ->
+ receive
+ {'EXIT', Pid, []} ->
+ stop_node(Node),
+ ok
+ end
+ end.
bounce(Dest) ->
receive Msg ->
- Dest ! Msg,
- exit(Msg)
+ Dest ! Msg,
+ exit(Msg)
end.
show_term(Term) ->
binary_to_list(term_to_binary(Term)).
-stop_dist(doc) ->
- ["Tests behaviour after net_kernel:stop (OTP-2586)."];
+%% Tests behaviour after net_kernel:stop (OTP-2586).
stop_dist(Config) when is_list(Config) ->
- ?line Str = os:cmd(atom_to_list(lib:progname())
- ++ " -noshell -pa "
- ++ ?config(data_dir, Config)
- ++ " -s run"),
+ Str = os:cmd(atom_to_list(lib:progname())
+ ++ " -noshell -pa "
+ ++ proplists:get_value(data_dir, Config)
+ ++ " -s run"),
%% The "true" may be followed by an error report, so ignore anything that
%% follows it.
- ?line "true\n"++_ = Str,
+ "true\n"++_ = Str,
%% "May fail on FreeBSD due to differently configured name lookup - ask Arndt",
%% if you can find him.
@@ -770,37 +726,31 @@ stop_dist(Config) when is_list(Config) ->
ok.
-trap_bif_1(doc) ->
- [""];
trap_bif_1(Config) when is_list(Config) ->
- ?line {true} = tr1(),
+ {true} = tr1(),
ok.
-trap_bif_2(doc) ->
- [""];
trap_bif_2(Config) when is_list(Config) ->
- ?line {true} = tr2(),
+ {true} = tr2(),
ok.
-trap_bif_3(doc) ->
- [""];
trap_bif_3(Config) when is_list(Config) ->
- ?line {hoo} = tr3(),
+ {hoo} = tr3(),
ok.
tr1() ->
- ?line NonExisting = 'abc@boromir',
- ?line X = erlang:monitor_node(NonExisting, true),
+ NonExisting = 'abc@boromir',
+ X = erlang:monitor_node(NonExisting, true),
{X}.
tr2() ->
- ?line NonExisting = 'abc@boromir',
- ?line X = apply(erlang, monitor_node, [NonExisting, true]),
+ NonExisting = 'abc@boromir',
+ X = apply(erlang, monitor_node, [NonExisting, true]),
{X}.
tr3() ->
- ?line NonExisting = 'abc@boromir',
- ?line X = {NonExisting, glirp} ! hoo,
+ NonExisting = 'abc@boromir',
+ X = {NonExisting, glirp} ! hoo,
{X}.
@@ -821,60 +771,61 @@ tr3() ->
% * n2 gets pang when pinging n1
% * n2 forces connection by using net_kernel:connect_node (ovverrides)
% * n2 gets pong when pinging n1.
-dist_auto_connect_once(doc) -> "Test the dist_auto_connect once kernel parameter";
+
+%% Test the dist_auto_connect once kernel parameter
dist_auto_connect_once(Config) when is_list(Config) ->
- ?line Sock = start_relay_node(dist_auto_connect_relay_node,[]),
- ?line NN = inet_rpc_nodename(Sock),
- ?line Sock2 = start_relay_node(dist_auto_connect_once_node,
- "-kernel dist_auto_connect once"),
- ?line NN2 = inet_rpc_nodename(Sock2),
- ?line {ok,[]} = do_inet_rpc(Sock,erlang,nodes,[]),
- ?line {ok, pong} = do_inet_rpc(Sock2,net_adm,ping,[NN]),
- ?line {ok,[NN2]} = do_inet_rpc(Sock,erlang,nodes,[]),
- ?line {ok,[NN]} = do_inet_rpc(Sock2,erlang,nodes,[]),
- ?line [_,HostPartPeer] = string:tokens(atom_to_list(NN),"@"),
- ?line [_,MyHostPart] = string:tokens(atom_to_list(node()),"@"),
+ Sock = start_relay_node(dist_auto_connect_relay_node,[]),
+ NN = inet_rpc_nodename(Sock),
+ Sock2 = start_relay_node(dist_auto_connect_once_node,
+ "-kernel dist_auto_connect once"),
+ NN2 = inet_rpc_nodename(Sock2),
+ {ok,[]} = do_inet_rpc(Sock,erlang,nodes,[]),
+ {ok, pong} = do_inet_rpc(Sock2,net_adm,ping,[NN]),
+ {ok,[NN2]} = do_inet_rpc(Sock,erlang,nodes,[]),
+ {ok,[NN]} = do_inet_rpc(Sock2,erlang,nodes,[]),
+ [_,HostPartPeer] = string:tokens(atom_to_list(NN),"@"),
+ [_,MyHostPart] = string:tokens(atom_to_list(node()),"@"),
% Give net_kernel a chance to change the state of the node to up to.
- ?line receive after 1000 -> ok end,
+ receive after 1000 -> ok end,
case HostPartPeer of
- MyHostPart ->
- ?line ok = stop_relay_node(Sock),
- ?line {ok,pang} = do_inet_rpc(Sock2,net_adm,ping,[NN]);
- _ ->
- ?line {ok, true} = do_inet_rpc(Sock,net_kernel,disconnect,[NN2]),
- receive
- after 500 -> ok
- end
+ MyHostPart ->
+ ok = stop_relay_node(Sock),
+ {ok,pang} = do_inet_rpc(Sock2,net_adm,ping,[NN]);
+ _ ->
+ {ok, true} = do_inet_rpc(Sock,net_kernel,disconnect,[NN2]),
+ receive
+ after 500 -> ok
+ end
end,
- ?line {ok, []} = do_inet_rpc(Sock2,erlang,nodes,[]),
+ {ok, []} = do_inet_rpc(Sock2,erlang,nodes,[]),
Sock3 = case HostPartPeer of
- MyHostPart ->
- ?line start_relay_node(dist_auto_connect_relay_node,[]);
- _ ->
- Sock
- end,
- ?line TS1 = timestamp(),
- ?line {ok, pang} = do_inet_rpc(Sock2,net_adm,ping,[NN]),
- ?line TS2 = timestamp(),
+ MyHostPart ->
+ start_relay_node(dist_auto_connect_relay_node,[]);
+ _ ->
+ Sock
+ end,
+ TS1 = timestamp(),
+ {ok, pang} = do_inet_rpc(Sock2,net_adm,ping,[NN]),
+ TS2 = timestamp(),
RefT = net_kernel:connecttime() - 1000,
- ?line true = ((TS2 - TS1) < RefT),
- ?line TS3 = timestamp(),
- ?line {ok, true} = do_inet_rpc(Sock2,erlang,monitor_node,
- [NN,true,[allow_passive_connect]]),
- ?line TS4 = timestamp(),
- ?line true = ((TS4 - TS3) > RefT),
- ?line {ok, pong} = do_inet_rpc(Sock3,net_adm,ping,[NN2]),
- ?line {ok, pong} = do_inet_rpc(Sock2,net_adm,ping,[NN]),
- ?line {ok, true} = do_inet_rpc(Sock3,net_kernel,disconnect,[NN2]),
+ true = ((TS2 - TS1) < RefT),
+ TS3 = timestamp(),
+ {ok, true} = do_inet_rpc(Sock2,erlang,monitor_node,
+ [NN,true,[allow_passive_connect]]),
+ TS4 = timestamp(),
+ true = ((TS4 - TS3) > RefT),
+ {ok, pong} = do_inet_rpc(Sock3,net_adm,ping,[NN2]),
+ {ok, pong} = do_inet_rpc(Sock2,net_adm,ping,[NN]),
+ {ok, true} = do_inet_rpc(Sock3,net_kernel,disconnect,[NN2]),
receive
after 500 -> ok
end,
- ?line {ok, pang} = do_inet_rpc(Sock2,net_adm,ping,[NN]),
- ?line {ok, true} = do_inet_rpc(Sock2,net_kernel,connect_node,[NN]),
- ?line {ok, pong} = do_inet_rpc(Sock2,net_adm,ping,[NN]),
- ?line stop_relay_node(Sock3),
- ?line stop_relay_node(Sock2).
-
+ {ok, pang} = do_inet_rpc(Sock2,net_adm,ping,[NN]),
+ {ok, true} = do_inet_rpc(Sock2,net_kernel,connect_node,[NN]),
+ {ok, pong} = do_inet_rpc(Sock2,net_adm,ping,[NN]),
+ stop_relay_node(Sock3),
+ stop_relay_node(Sock2).
+
%% Start a relay node and a lonely (dist_auto_connect never) node.
@@ -883,51 +834,51 @@ dist_auto_connect_once(Config) when is_list(Config) ->
%% Result is sent here through relay node.
dist_auto_connect_never(Config) when is_list(Config) ->
Self = self(),
- ?line {ok, RelayNode} =
- start_node(dist_auto_connect_relay),
- ?line spawn(RelayNode,
- fun() ->
- register(dist_auto_connect_relay, self()),
- dist_auto_connect_relay(Self)
- end),
- ?line {ok, Handle} = dist_auto_connect_start(dist_auto_connect, never),
- ?line Result =
- receive
- {do_dist_auto_connect, ok} ->
- ok;
- {do_dist_auto_connect, Error} ->
- {error, Error};
- Other ->
- {error, Other}
- after 32000 ->
- timeout
- end,
- ?line stop_node(RelayNode),
- ?line Stopped = dist_auto_connect_stop(Handle),
- ?line Junk =
- receive
- {do_dist_auto_connect, _} = J ->
- J
- after 0 ->
- ok
- end,
- ?line {ok, ok, ok} = {Result, Stopped, Junk},
+ {ok, RelayNode} =
+ start_node(dist_auto_connect_relay),
+ spawn(RelayNode,
+ fun() ->
+ register(dist_auto_connect_relay, self()),
+ dist_auto_connect_relay(Self)
+ end),
+ {ok, Handle} = dist_auto_connect_start(dist_auto_connect, never),
+ Result =
+ receive
+ {do_dist_auto_connect, ok} ->
+ ok;
+ {do_dist_auto_connect, Error} ->
+ {error, Error};
+ Other ->
+ {error, Other}
+ after 32000 ->
+ timeout
+ end,
+ stop_node(RelayNode),
+ Stopped = dist_auto_connect_stop(Handle),
+ Junk =
+ receive
+ {do_dist_auto_connect, _} = J ->
+ J
+ after 0 ->
+ ok
+ end,
+ {ok, ok, ok} = {Result, Stopped, Junk},
ok.
do_dist_auto_connect([never]) ->
Node = list_to_atom("dist_auto_connect_relay@" ++ hostname()),
io:format("~p:do_dist_auto_connect([false]) Node=~p~n",
- [?MODULE, Node]),
+ [?MODULE, Node]),
Ping = net_adm:ping(Node),
io:format("~p:do_dist_auto_connect([false]) Ping=~p~n",
- [?MODULE, Ping]),
+ [?MODULE, Ping]),
Result = case Ping of
- pang -> ok;
- _ -> {error, Ping}
- end,
+ pang -> ok;
+ _ -> {error, Ping}
+ end,
io:format("~p:do_dist_auto_connect([false]) Result=~p~n",
- [?MODULE, Result]),
+ [?MODULE, Result]),
net_kernel:connect_node(Node),
catch {dist_auto_connect_relay, Node} ! {do_dist_auto_connect, Result};
% receive after 1000 -> ok end,
@@ -935,10 +886,10 @@ do_dist_auto_connect([never]) ->
do_dist_auto_connect(Arg) ->
io:format("~p:do_dist_auto_connect(~p)~n",
- [?MODULE, Arg]),
+ [?MODULE, Arg]),
receive after 10000 -> ok end,
halt().
-
+
dist_auto_connect_start(Name, Value) when is_atom(Name) ->
dist_auto_connect_start(atom_to_list(Name), Value);
@@ -948,16 +899,16 @@ dist_auto_connect_start(Name, Value) when is_list(Name), is_atom(Value) ->
ValueStr = atom_to_list(Value),
Cookie = atom_to_list(erlang:get_cookie()),
Cmd = lists:concat(
- [%"xterm -e ",
- atom_to_list(lib:progname()),
-% " -noinput ",
- " -detached ",
- long_or_short(), " ", Name,
- " -setcookie ", Cookie,
- " -pa ", ModuleDir,
- " -s ", atom_to_list(?MODULE),
- " do_dist_auto_connect ", ValueStr,
- " -kernel dist_auto_connect ", ValueStr]),
+ [%"xterm -e ",
+ atom_to_list(lib:progname()),
+ % " -noinput ",
+ " -detached ",
+ long_or_short(), " ", Name,
+ " -setcookie ", Cookie,
+ " -pa ", ModuleDir,
+ " -s ", atom_to_list(?MODULE),
+ " do_dist_auto_connect ", ValueStr,
+ " -kernel dist_auto_connect ", ValueStr]),
io:format("~p:dist_auto_connect_start() cmd: ~p~n", [?MODULE, Cmd]),
Port = open_port({spawn, Cmd}, [stream]),
{ok, {Port, Node}}.
@@ -975,102 +926,83 @@ dist_auto_connect_stop(Port, _Node, Pid, N) when is_integer(N), N =< 0 ->
Result;
dist_auto_connect_stop(Port, Node, Pid, N) when is_integer(N) ->
case net_adm:ping(Node) of
- pong ->
- receive after 100 -> ok end,
- dist_auto_connect_stop(Port, Node, Pid, N-100);
- pang ->
- exit(Pid, normal),
- catch erlang:port_close(Port),
- io:format("~p:dist_auto_connect_stop() ok~n", [?MODULE]),
- ok
+ pong ->
+ receive after 100 -> ok end,
+ dist_auto_connect_stop(Port, Node, Pid, N-100);
+ pang ->
+ exit(Pid, normal),
+ catch erlang:port_close(Port),
+ io:format("~p:dist_auto_connect_stop() ok~n", [?MODULE]),
+ ok
end.
dist_auto_connect_relay(Parent) ->
receive X ->
- catch Parent ! X
+ catch Parent ! X
end,
dist_auto_connect_relay(Parent).
-dist_parallel_send(doc) ->
- [];
-dist_parallel_send(suite) ->
- [];
dist_parallel_send(Config) when is_list(Config) ->
- ?line {ok, RNode} = start_node(dist_parallel_receiver),
- ?line {ok, SNode} = start_node(dist_parallel_sender),
- ?line WatchDog = spawn_link(
- fun () ->
- TRef = erlang:start_timer((?DEFAULT_TIMETRAP
- div 2),
- self(),
- oops),
- receive
- {timeout, TRef, _ } ->
- spawn(SNode,
- fun () ->
- abort(timeout)
- end),
- spawn(RNode,
- fun () ->
- abort(timeout)
- end)
-%% rpc:cast(SNode, erlang, halt,
-%% ["Timetrap (sender)"]),
-%% rpc:cast(RNode, erlang, halt,
-%% ["Timetrap (receiver)"])
- end
- end),
- ?line MkSndrs = fun (Receiver) ->
- lists:map(fun (_) ->
- spawn_link(SNode,
- ?MODULE,
- dist_parallel_sender,
- [self(),
- Receiver,
- 1000])
- end,
- lists:seq(1, 64))
- end,
- ?line SndrsStart = fun (Sndrs) ->
- Parent = self(),
- spawn_link(
- SNode,
- fun () ->
- lists:foreach(fun (P) ->
- P ! {go, Parent}
- end,
- Sndrs)
- end)
- end,
- ?line SndrsWait = fun (Sndrs) ->
- lists:foreach(fun (P) ->
- receive {P, done} -> ok end
- end,
- Sndrs)
- end,
- ?line DPR = spawn_link(RNode, ?MODULE, dist_parallel_receiver, []),
- ?line Sndrs1 = MkSndrs(DPR),
- ?line SndrsStart(Sndrs1),
- ?line SndrsWait(Sndrs1),
- ?line unlink(DPR),
- ?line exit(DPR, bang),
-
- ?line DEPR = spawn_link(RNode, ?MODULE, dist_evil_parallel_receiver, []),
- ?line Sndrs2 = MkSndrs(DEPR),
- ?line SndrsStart(Sndrs2),
- ?line SndrsWait(Sndrs2),
- ?line unlink(DEPR),
- ?line exit(DEPR, bang),
-
- ?line unlink(WatchDog),
- ?line exit(WatchDog, bang),
-
- ?line stop_node(RNode),
- ?line stop_node(SNode),
-
- ?line ok.
+ {ok, RNode} = start_node(dist_parallel_receiver),
+ {ok, SNode} = start_node(dist_parallel_sender),
+ WatchDog = spawn_link(
+ fun () ->
+ TRef = erlang:start_timer((2*60*1000), self(), oops),
+ receive
+ {timeout, TRef, _ } ->
+ spawn(SNode, fun () -> abort(timeout) end),
+ spawn(RNode, fun () -> abort(timeout) end)
+ %% rpc:cast(SNode, erlang, halt,
+ %% ["Timetrap (sender)"]),
+ %% rpc:cast(RNode, erlang, halt,
+ %% ["Timetrap (receiver)"])
+ end
+ end),
+ MkSndrs = fun (Receiver) ->
+ lists:map(fun (_) ->
+ spawn_link(SNode,
+ ?MODULE,
+ dist_parallel_sender,
+ [self(), Receiver, 1000])
+ end, lists:seq(1, 64))
+ end,
+ SndrsStart = fun (Sndrs) ->
+ Parent = self(),
+ spawn_link(SNode,
+ fun () ->
+ lists:foreach(fun (P) ->
+ P ! {go, Parent}
+ end, Sndrs)
+ end)
+ end,
+ SndrsWait = fun (Sndrs) ->
+ lists:foreach(fun (P) ->
+ receive {P, done} -> ok end
+ end, Sndrs)
+ end,
+ DPR = spawn_link(RNode, ?MODULE, dist_parallel_receiver, []),
+ Sndrs1 = MkSndrs(DPR),
+ SndrsStart(Sndrs1),
+ SndrsWait(Sndrs1),
+ unlink(DPR),
+ exit(DPR, bang),
+
+ DEPR = spawn_link(RNode, ?MODULE, dist_evil_parallel_receiver, []),
+ Sndrs2 = MkSndrs(DEPR),
+ SndrsStart(Sndrs2),
+ SndrsWait(Sndrs2),
+ unlink(DEPR),
+ exit(DEPR, bang),
+
+ unlink(WatchDog),
+ exit(WatchDog, bang),
+
+ stop_node(RNode),
+ stop_node(SNode),
+
+ ok.
do_dist_parallel_sender(Parent, _Receiver, 0) ->
Parent ! {self(), done};
@@ -1092,71 +1024,71 @@ dist_evil_parallel_receiver() ->
dist_evil_parallel_receiver().
atom_roundtrip(Config) when is_list(Config) ->
- ?line AtomData = atom_data(),
- ?line verify_atom_data(AtomData),
- ?line {ok, Node} = start_node(Config),
- ?line do_atom_roundtrip(Node, AtomData),
- ?line stop_node(Node),
- ?line ok.
+ AtomData = atom_data(),
+ verify_atom_data(AtomData),
+ {ok, Node} = start_node(Config),
+ do_atom_roundtrip(Node, AtomData),
+ stop_node(Node),
+ ok.
atom_roundtrip_r15b(Config) when is_list(Config) ->
- case ?t:is_release_available("r15b") of
- true ->
- ?line AtomData = atom_data(),
- ?line verify_atom_data(AtomData),
- ?line {ok, Node} = start_node(Config, [], "r15b"),
- ?line do_atom_roundtrip(Node, AtomData),
- ?line stop_node(Node),
- ?line ok;
- false ->
- ?line {skip,"No OTP R15B available"}
+ case test_server:is_release_available("r15b") of
+ true ->
+ AtomData = atom_data(),
+ verify_atom_data(AtomData),
+ {ok, Node} = start_node(Config, [], "r15b"),
+ do_atom_roundtrip(Node, AtomData),
+ stop_node(Node),
+ ok;
+ false ->
+ {skip,"No OTP R15B available"}
end.
unicode_atom_roundtrip(Config) when is_list(Config) ->
- ?line AtomData = unicode_atom_data(),
- ?line verify_atom_data(AtomData),
- ?line {ok, Node} = start_node(Config),
- ?line do_atom_roundtrip(Node, AtomData),
- ?line stop_node(Node),
- ?line ok.
+ AtomData = unicode_atom_data(),
+ verify_atom_data(AtomData),
+ {ok, Node} = start_node(Config),
+ do_atom_roundtrip(Node, AtomData),
+ stop_node(Node),
+ ok.
do_atom_roundtrip(Node, AtomData) ->
- ?line Parent = self(),
- ?line Proc = spawn_link(Node, fun () -> verify_atom_data_loop(Parent) end),
- ?line Proc ! {self(), AtomData},
- ?line receive {Proc, AD1} -> AtomData = AD1 end,
- ?line Proc ! {self(), AtomData},
- ?line receive {Proc, AD2} -> AtomData = AD2 end,
- ?line RevAtomData = lists:reverse(AtomData),
- ?line Proc ! {self(), RevAtomData},
- ?line receive {Proc, RAD1} -> RevAtomData = RAD1 end,
- ?line unlink(Proc),
- ?line exit(Proc, bang),
- ?line ok.
+ Parent = self(),
+ Proc = spawn_link(Node, fun () -> verify_atom_data_loop(Parent) end),
+ Proc ! {self(), AtomData},
+ receive {Proc, AD1} -> AtomData = AD1 end,
+ Proc ! {self(), AtomData},
+ receive {Proc, AD2} -> AtomData = AD2 end,
+ RevAtomData = lists:reverse(AtomData),
+ Proc ! {self(), RevAtomData},
+ receive {Proc, RAD1} -> RevAtomData = RAD1 end,
+ unlink(Proc),
+ exit(Proc, bang),
+ ok.
verify_atom_data_loop(From) ->
receive
- {From, AtomData} ->
- verify_atom_data(AtomData),
- From ! {self(), AtomData},
- verify_atom_data_loop(From)
+ {From, AtomData} ->
+ verify_atom_data(AtomData),
+ From ! {self(), AtomData},
+ verify_atom_data_loop(From)
end.
atom_data() ->
lists:map(fun (N) ->
- ATxt = "a"++integer_to_list(N),
- {list_to_atom(ATxt), ATxt}
- end,
- lists:seq(1, 2000)).
+ ATxt = "a"++integer_to_list(N),
+ {list_to_atom(ATxt), ATxt}
+ end,
+ lists:seq(1, 2000)).
verify_atom_data(AtomData) ->
lists:foreach(fun ({Atom, AtomTxt}) when is_atom(Atom) ->
- AtomTxt = atom_to_list(Atom);
- ({PPR, AtomTxt}) ->
- % Pid, Port, or Ref
- AtomTxt = atom_to_list(node(PPR))
- end,
- AtomData).
+ AtomTxt = atom_to_list(Atom);
+ ({PPR, AtomTxt}) ->
+ % Pid, Port, or Ref
+ AtomTxt = atom_to_list(node(PPR))
+ end,
+ AtomData).
uc_atom_tup(ATxt) ->
Atom = string_to_atom(ATxt),
@@ -1209,9 +1141,8 @@ unicode_atom_data() ->
uc_atom_tup(lists:seq(65500, 65754)),
uc_atom_tup(lists:seq(65500, 65563))
| lists:map(fun (N) ->
- uc_atom_tup(lists:seq(64000+N, 64254+N))
- end,
- lists:seq(1, 2000))].
+ uc_atom_tup(lists:seq(64000+N, 64254+N))
+ end, lists:seq(1, 2000))].
contended_atom_cache_entry(Config) when is_list(Config) ->
contended_atom_cache_entry_test(Config, latin1).
@@ -1220,79 +1151,77 @@ contended_unicode_atom_cache_entry(Config) when is_list(Config) ->
contended_atom_cache_entry_test(Config, unicode).
contended_atom_cache_entry_test(Config, Type) ->
- ?line TestServer = self(),
- ?line ProcessPairs = 10,
- ?line Msgs = 100000,
- ?line {ok, SNode} = start_node(Config),
- ?line {ok, RNode} = start_node(Config),
- ?line Success = make_ref(),
- ?line spawn_link(
- SNode,
- fun () ->
- erts_debug:set_internal_state(available_internal_state,
- true),
- Master = self(),
- CIX = get_cix(),
- TestAtoms = case Type of
- latin1 ->
- get_conflicting_atoms(CIX,
- ProcessPairs);
- unicode ->
- get_conflicting_unicode_atoms(CIX,
- ProcessPairs)
- end,
- io:format("Testing with the following atoms all using "
- "cache index ~p:~n ~w~n",
- [CIX, TestAtoms]),
- Ps = lists:map(
- fun (A) ->
- Ref = make_ref(),
- R = spawn_link(
- RNode,
- fun () ->
- Atom = receive
- {Ref, txt, ATxt} ->
- case Type of
- latin1 ->
- list_to_atom(ATxt);
- unicode ->
- string_to_atom(ATxt)
- end
- end,
- receive_ref_atom(Ref,
- Atom,
- Msgs),
- Master ! {self(), success}
- end),
- S = spawn_link(
- SNode,
- fun () ->
- receive go -> ok end,
- R ! {Ref,
- txt,
- atom_to_list(A)},
- send_ref_atom(R, Ref, A, Msgs)
- end),
- {S, R}
- end,
- TestAtoms),
- lists:foreach(fun ({S, _}) ->
- S ! go
- end,
- Ps),
- lists:foreach(fun ({_, R}) ->
- receive {R, success} -> ok end
- end,
- Ps),
- TestServer ! Success
- end),
- ?line receive
- Success ->
- ok
- end,
- ?line stop_node(SNode),
- ?line stop_node(RNode),
- ?line ok.
+ TestServer = self(),
+ ProcessPairs = 10,
+ Msgs = 100000,
+ {ok, SNode} = start_node(Config),
+ {ok, RNode} = start_node(Config),
+ Success = make_ref(),
+ spawn_link(
+ SNode,
+ fun () ->
+ erts_debug:set_internal_state(available_internal_state,
+ true),
+ Master = self(),
+ CIX = get_cix(),
+ TestAtoms = case Type of
+ latin1 ->
+ get_conflicting_atoms(CIX,
+ ProcessPairs);
+ unicode ->
+ get_conflicting_unicode_atoms(CIX,
+ ProcessPairs)
+ end,
+ io:format("Testing with the following atoms all using "
+ "cache index ~p:~n ~w~n",
+ [CIX, TestAtoms]),
+ Ps = lists:map(
+ fun (A) ->
+ Ref = make_ref(),
+ R = spawn_link(RNode,
+ fun () ->
+ Atom = receive
+ {Ref, txt, ATxt} ->
+ case Type of
+ latin1 ->
+ list_to_atom(ATxt);
+ unicode ->
+ string_to_atom(ATxt)
+ end
+ end,
+ receive_ref_atom(Ref,
+ Atom,
+ Msgs),
+ Master ! {self(), success}
+ end),
+ S = spawn_link(SNode,
+ fun () ->
+ receive go -> ok end,
+ R ! {Ref,
+ txt,
+ atom_to_list(A)},
+ send_ref_atom(R, Ref, A, Msgs)
+ end),
+ {S, R}
+ end,
+ TestAtoms),
+ lists:foreach(fun ({S, _}) ->
+ S ! go
+ end,
+ Ps),
+ lists:foreach(fun ({_, R}) ->
+ receive {R, success} -> ok end
+ end,
+ Ps),
+ TestServer ! Success
+ end),
+ receive
+ Success ->
+ ok
+ end,
+ stop_node(SNode),
+ stop_node(RNode),
+ ok.
send_ref_atom(_To, _Ref, _Atom, 0) ->
ok;
@@ -1304,11 +1233,11 @@ receive_ref_atom(_Ref, _Atom, 0) ->
ok;
receive_ref_atom(Ref, Atom, N) ->
receive
- {Ref, Value} ->
- Atom = Value
+ {Ref, Value} ->
+ Atom = Value
end,
receive_ref_atom(Ref, Atom, N-1).
-
+
get_cix() ->
get_cix(1000).
@@ -1316,34 +1245,34 @@ get_cix(CIX) when is_integer(CIX), CIX < 0 ->
get_cix(0);
get_cix(CIX) when is_integer(CIX) ->
get_cix(CIX,
- unwanted_cixs(),
- erts_debug:get_internal_state(max_atom_out_cache_index)).
+ unwanted_cixs(),
+ erts_debug:get_internal_state(max_atom_out_cache_index)).
get_cix(CIX, Unwanted, MaxCIX) when CIX > MaxCIX ->
get_cix(0, Unwanted, MaxCIX);
get_cix(CIX, Unwanted, MaxCIX) ->
case lists:member(CIX, Unwanted) of
- true -> get_cix(CIX+1, Unwanted, MaxCIX);
- false -> CIX
+ true -> get_cix(CIX+1, Unwanted, MaxCIX);
+ false -> CIX
end.
unwanted_cixs() ->
lists:map(fun (Node) ->
- erts_debug:get_internal_state({atom_out_cache_index,
- Node})
- end,
- nodes()).
-
-
+ erts_debug:get_internal_state({atom_out_cache_index,
+ Node})
+ end,
+ nodes()).
+
+
get_conflicting_atoms(_CIX, 0) ->
[];
get_conflicting_atoms(CIX, N) ->
Atom = list_to_atom("atom" ++ integer_to_list(erlang:unique_integer([positive]))),
case erts_debug:get_internal_state({atom_out_cache_index, Atom}) of
- CIX ->
- [Atom|get_conflicting_atoms(CIX, N-1)];
- _ ->
- get_conflicting_atoms(CIX, N)
+ CIX ->
+ [Atom|get_conflicting_atoms(CIX, N-1)];
+ _ ->
+ get_conflicting_atoms(CIX, N)
end.
get_conflicting_unicode_atoms(_CIX, 0) ->
@@ -1351,10 +1280,10 @@ get_conflicting_unicode_atoms(_CIX, 0) ->
get_conflicting_unicode_atoms(CIX, N) ->
Atom = string_to_atom([16#1f608] ++ "atom" ++ integer_to_list(erlang:unique_integer([positive]))),
case erts_debug:get_internal_state({atom_out_cache_index, Atom}) of
- CIX ->
- [Atom|get_conflicting_unicode_atoms(CIX, N-1)];
- _ ->
- get_conflicting_unicode_atoms(CIX, N)
+ CIX ->
+ [Atom|get_conflicting_unicode_atoms(CIX, N-1)];
+ _ ->
+ get_conflicting_unicode_atoms(CIX, N)
end.
-define(COOKIE, '').
@@ -1376,482 +1305,474 @@ get_conflicting_unicode_atoms(CIX, N) ->
-define(DOP_MONITOR_P_EXIT, 21).
start_monitor(Offender,P) ->
- ?line Parent = self(),
- ?line Q = spawn(Offender,
- fun () ->
- Ref = erlang:monitor(process,P),
- Parent ! {self(),ref,Ref},
- receive
- just_stay_alive -> ok
- end
- end),
- ?line Ref = receive
- {Q,ref,R} ->
- R
- after 5000 ->
- error
- end,
+ Parent = self(),
+ Q = spawn(Offender,
+ fun () ->
+ Ref = erlang:monitor(process,P),
+ Parent ! {self(),ref,Ref},
+ receive
+ just_stay_alive -> ok
+ end
+ end),
+ Ref = receive
+ {Q,ref,R} ->
+ R
+ after 5000 ->
+ error
+ end,
io:format("Ref is ~p~n",[Ref]),
ok.
start_link(Offender,P) ->
- ?line Parent = self(),
- ?line Q = spawn(Offender,
- fun () ->
- process_flag(trap_exit,true),
- link(P),
- Parent ! {self(),ref,P},
- receive
- just_stay_alive -> ok
- end
- end),
- ?line Ref = receive
- {Q,ref,R} ->
- R
- after 5000 ->
- error
- end,
+ Parent = self(),
+ Q = spawn(Offender,
+ fun () ->
+ process_flag(trap_exit,true),
+ link(P),
+ Parent ! {self(),ref,P},
+ receive
+ just_stay_alive -> ok
+ end
+ end),
+ Ref = receive
+ {Q,ref,R} ->
+ R
+ after 5000 ->
+ error
+ end,
io:format("Ref is ~p~n",[Ref]),
ok.
-bad_dist_structure(suite) ->
- [];
-bad_dist_structure(doc) ->
- ["Test dist messages with valid structure (binary to term ok) but malformed"
- "control content"];
+%% Test dist messages with valid structure (binary to term ok) but malformed control content
bad_dist_structure(Config) when is_list(Config) ->
- %process_flag(trap_exit,true),
- ODog = ?config(watchdog, Config),
- ?t:timetrap_cancel(ODog),
- Dog = ?t:timetrap(?t:seconds(15)),
-
- ?line {ok, Offender} = start_node(bad_dist_structure_offender),
- ?line {ok, Victim} = start_node(bad_dist_structure_victim),
- ?line start_node_monitors([Offender,Victim]),
- ?line Parent = self(),
- ?line P = spawn(Victim,
- fun () ->
- process_flag(trap_exit,true),
- Parent ! {self(), started},
- receive check_msgs -> ok end,
- bad_dist_struct_check_msgs([one,
- two]),
- Parent ! {self(), messages_checked},
- receive done -> ok end
- end),
- ?line receive {P, started} -> ok end,
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line verify_up(Offender, Victim),
- ?line true = lists:member(Offender, rpc:call(Victim, erlang, nodes, [])),
- ?line start_monitor(Offender,P),
- ?line P ! one,
- ?line send_bad_structure(Offender, P,{?DOP_MONITOR_P_EXIT,'replace',P,normal},2),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line start_monitor(Offender,P),
- ?line send_bad_structure(Offender, P,{?DOP_MONITOR_P_EXIT,'replace',P,normal,normal},2),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line start_link(Offender,P),
- ?line send_bad_structure(Offender, P,{?DOP_LINK},0),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line start_link(Offender,P),
- ?line send_bad_structure(Offender, P,{?DOP_UNLINK,'replace'},2),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line start_link(Offender,P),
- ?line send_bad_structure(Offender, P,{?DOP_UNLINK,'replace',make_ref()},2),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line start_link(Offender,P),
- ?line send_bad_structure(Offender, P,{?DOP_UNLINK,make_ref(),P},0),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line start_link(Offender,P),
- ?line send_bad_structure(Offender, P,{?DOP_UNLINK,normal,normal},0),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line start_monitor(Offender,P),
- ?line send_bad_structure(Offender, P,{?DOP_MONITOR_P,'replace',P},2),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line start_monitor(Offender,P),
- ?line send_bad_structure(Offender, P,{?DOP_MONITOR_P,'replace',P,normal},2),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line start_monitor(Offender,P),
- ?line send_bad_structure(Offender, P,{?DOP_DEMONITOR_P,'replace',P},2),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line start_monitor(Offender,P),
- ?line send_bad_structure(Offender, P,{?DOP_DEMONITOR_P,'replace',P,normal},2),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_EXIT,'replace',P},2),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_EXIT,make_ref(),normal,normal},0),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_EXIT_TT,'replace',token,P},2),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_EXIT_TT,make_ref(),token,normal,normal},0),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_EXIT2,'replace',P},2),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_EXIT2,make_ref(),normal,normal},0),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_EXIT2_TT,'replace',token,P},2),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_EXIT2_TT,make_ref(),token,normal,normal},0),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_GROUP_LEADER,'replace'},2),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_GROUP_LEADER,'replace','atomic'},2),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_GROUP_LEADER,'replace',P},0),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_REG_SEND_TT,'replace','',name},2,{message}),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_REG_SEND_TT,'replace','',name,token},0,{message}),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_REG_SEND,'replace',''},2,{message}),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_REG_SEND,'replace','',P},0,{message}),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_REG_SEND,'replace','',name},0,{message}),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_REG_SEND,'replace','',name,{token}},2,{message}),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_SEND_TT,'',P},0,{message}),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_SEND_TT,'',name,token},0,{message}),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_SEND,''},0,{message}),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_SEND,'',name},0,{message}),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line send_bad_structure(Offender, P,{?DOP_SEND,'',P,{token}},0,{message}),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line P ! two,
- ?line P ! check_msgs,
- ?line receive
- {P, messages_checked} -> ok
- after 5000 ->
- exit(victim_is_dead)
- end,
-
- ?line {message_queue_len, 0}
- = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
-
- ?line unlink(P),
- ?line P ! done,
- ?line stop_node(Offender),
- ?line stop_node(Victim),
- ?t:timetrap_cancel(Dog),
+ ct:timetrap({seconds, 15}),
+
+ {ok, Offender} = start_node(bad_dist_structure_offender),
+ {ok, Victim} = start_node(bad_dist_structure_victim),
+ start_node_monitors([Offender,Victim]),
+ Parent = self(),
+ P = spawn(Victim,
+ fun () ->
+ process_flag(trap_exit,true),
+ Parent ! {self(), started},
+ receive check_msgs -> ok end,
+ bad_dist_struct_check_msgs([one,
+ two]),
+ Parent ! {self(), messages_checked},
+ receive done -> ok end
+ end),
+ receive {P, started} -> ok end,
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ verify_up(Offender, Victim),
+ true = lists:member(Offender, rpc:call(Victim, erlang, nodes, [])),
+ start_monitor(Offender,P),
+ P ! one,
+ send_bad_structure(Offender, P,{?DOP_MONITOR_P_EXIT,'replace',P,normal},2),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ start_monitor(Offender,P),
+ send_bad_structure(Offender, P,{?DOP_MONITOR_P_EXIT,'replace',P,normal,normal},2),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ start_link(Offender,P),
+ send_bad_structure(Offender, P,{?DOP_LINK},0),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ start_link(Offender,P),
+ send_bad_structure(Offender, P,{?DOP_UNLINK,'replace'},2),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ start_link(Offender,P),
+ send_bad_structure(Offender, P,{?DOP_UNLINK,'replace',make_ref()},2),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ start_link(Offender,P),
+ send_bad_structure(Offender, P,{?DOP_UNLINK,make_ref(),P},0),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ start_link(Offender,P),
+ send_bad_structure(Offender, P,{?DOP_UNLINK,normal,normal},0),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ start_monitor(Offender,P),
+ send_bad_structure(Offender, P,{?DOP_MONITOR_P,'replace',P},2),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ start_monitor(Offender,P),
+ send_bad_structure(Offender, P,{?DOP_MONITOR_P,'replace',P,normal},2),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ start_monitor(Offender,P),
+ send_bad_structure(Offender, P,{?DOP_DEMONITOR_P,'replace',P},2),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ start_monitor(Offender,P),
+ send_bad_structure(Offender, P,{?DOP_DEMONITOR_P,'replace',P,normal},2),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_EXIT,'replace',P},2),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_EXIT,make_ref(),normal,normal},0),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_EXIT_TT,'replace',token,P},2),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_EXIT_TT,make_ref(),token,normal,normal},0),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_EXIT2,'replace',P},2),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_EXIT2,make_ref(),normal,normal},0),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_EXIT2_TT,'replace',token,P},2),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_EXIT2_TT,make_ref(),token,normal,normal},0),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_GROUP_LEADER,'replace'},2),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_GROUP_LEADER,'replace','atomic'},2),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_GROUP_LEADER,'replace',P},0),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_REG_SEND_TT,'replace','',name},2,{message}),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_REG_SEND_TT,'replace','',name,token},0,{message}),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_REG_SEND,'replace',''},2,{message}),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_REG_SEND,'replace','',P},0,{message}),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_REG_SEND,'replace','',name},0,{message}),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_REG_SEND,'replace','',name,{token}},2,{message}),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_SEND_TT,'',P},0,{message}),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_SEND_TT,'',name,token},0,{message}),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_SEND,''},0,{message}),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_SEND,'',name},0,{message}),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ send_bad_structure(Offender, P,{?DOP_SEND,'',P,{token}},0,{message}),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ P ! two,
+ P ! check_msgs,
+ receive
+ {P, messages_checked} -> ok
+ after 5000 ->
+ exit(victim_is_dead)
+ end,
+
+ {message_queue_len, 0}
+ = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
+
+ unlink(P),
+ P ! done,
+ stop_node(Offender),
+ stop_node(Victim),
ok.
bad_dist_ext_receive(Config) when is_list(Config) ->
- ?line {ok, Offender} = start_node(bad_dist_ext_receive_offender),
- ?line {ok, Victim} = start_node(bad_dist_ext_receive_victim),
- ?line start_node_monitors([Offender,Victim]),
-
- ?line Parent = self(),
-
- ?line P = spawn_link(Victim,
- fun () ->
- Parent ! {self(), started},
- receive check_msgs -> ok end,
- bad_dist_ext_check_msgs([one,
- two,
- three]),
- Parent ! {self(), messages_checked},
- receive done -> ok end
- end),
-
- ?line receive {P, started} -> ok end,
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line verify_up(Offender, Victim),
- ?line true = lists:member(Offender, rpc:call(Victim, erlang, nodes, [])),
- ?line P ! one,
- ?line send_bad_msg(Offender, P),
- ?line P ! two,
- ?line verify_down(Offender, connection_closed, Victim, killed),
- ?line {message_queue_len, 2}
- = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
-
- ?line Suspended = make_ref(),
- ?line S = spawn(Victim,
- fun () ->
- erlang:suspend_process(P),
- Parent ! Suspended,
- receive after infinity -> ok end
- end),
- ?line MS = erlang:monitor(process, S),
- ?line receive Suspended -> ok end,
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line verify_up(Offender, Victim),
- ?line true = lists:member(Offender, rpc:call(Victim, erlang, nodes, [])),
- ?line send_bad_msgs(Offender, P, 5),
- ?line true = lists:member(Offender, rpc:call(Victim, erlang, nodes, [])),
- ?line P ! three,
- ?line send_bad_msgs(Offender, P, 5),
+ {ok, Offender} = start_node(bad_dist_ext_receive_offender),
+ {ok, Victim} = start_node(bad_dist_ext_receive_victim),
+ start_node_monitors([Offender,Victim]),
+
+ Parent = self(),
+
+ P = spawn_link(Victim,
+ fun () ->
+ Parent ! {self(), started},
+ receive check_msgs -> ok end,
+ bad_dist_ext_check_msgs([one,
+ two,
+ three]),
+ Parent ! {self(), messages_checked},
+ receive done -> ok end
+ end),
+
+ receive {P, started} -> ok end,
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ verify_up(Offender, Victim),
+ true = lists:member(Offender, rpc:call(Victim, erlang, nodes, [])),
+ P ! one,
+ send_bad_msg(Offender, P),
+ P ! two,
+ verify_down(Offender, connection_closed, Victim, killed),
+ {message_queue_len, 2}
+ = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
+
+ Suspended = make_ref(),
+ S = spawn(Victim,
+ fun () ->
+ erlang:suspend_process(P),
+ Parent ! Suspended,
+ receive after infinity -> ok end
+ end),
+ MS = erlang:monitor(process, S),
+ receive Suspended -> ok end,
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ verify_up(Offender, Victim),
+ true = lists:member(Offender, rpc:call(Victim, erlang, nodes, [])),
+ send_bad_msgs(Offender, P, 5),
+ true = lists:member(Offender, rpc:call(Victim, erlang, nodes, [])),
+ P ! three,
+ send_bad_msgs(Offender, P, 5),
%% Make sure bad msgs has reached Victim
- ?line rpc:call(Offender, rpc, call, [Victim, erlang, node, []]),
-
- ?line verify_still_up(Offender, Victim),
- ?line {message_queue_len, 13}
- = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
-
- ?line exit(S, bang),
- ?line receive {'DOWN', MS, process, S, bang} -> ok end,
- ?line verify_down(Offender, connection_closed, Victim, killed),
- ?line {message_queue_len, 3}
- = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
-
- ?line P ! check_msgs,
- ?line receive {P, messages_checked} -> ok end,
-
- ?line {message_queue_len, 0}
- = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
-
- ?line P ! done,
- ?line unlink(P),
- ?line verify_no_down(Offender, Victim),
- ?line stop_node(Offender),
- ?line stop_node(Victim).
+ rpc:call(Offender, rpc, call, [Victim, erlang, node, []]),
+
+ verify_still_up(Offender, Victim),
+ {message_queue_len, 13}
+ = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
+
+ exit(S, bang),
+ receive {'DOWN', MS, process, S, bang} -> ok end,
+ verify_down(Offender, connection_closed, Victim, killed),
+ {message_queue_len, 3}
+ = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
+
+ P ! check_msgs,
+ receive {P, messages_checked} -> ok end,
+
+ {message_queue_len, 0}
+ = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
+
+ P ! done,
+ unlink(P),
+ verify_no_down(Offender, Victim),
+ stop_node(Offender),
+ stop_node(Victim).
bad_dist_ext_process_info(Config) when is_list(Config) ->
- ?line {ok, Offender} = start_node(bad_dist_ext_process_info_offender),
- ?line {ok, Victim} = start_node(bad_dist_ext_process_info_victim),
- ?line start_node_monitors([Offender,Victim]),
-
- ?line Parent = self(),
- ?line P = spawn_link(Victim,
- fun () ->
- Parent ! {self(), started},
- receive check_msgs -> ok end,
- bad_dist_ext_check_msgs([one, two]),
- Parent ! {self(), messages_checked},
- receive done -> ok end
- end),
-
- ?line receive {P, started} -> ok end,
- ?line P ! one,
-
- ?line Suspended = make_ref(),
- ?line S = spawn(Victim,
- fun () ->
- erlang:suspend_process(P),
- Parent ! Suspended,
- receive after infinity -> ok end
- end),
-
- ?line receive Suspended -> ok end,
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line verify_up(Offender, Victim),
- ?line send_bad_msgs(Offender, P, 5),
-
- ?line P ! two,
- ?line send_bad_msgs(Offender, P, 5),
+ {ok, Offender} = start_node(bad_dist_ext_process_info_offender),
+ {ok, Victim} = start_node(bad_dist_ext_process_info_victim),
+ start_node_monitors([Offender,Victim]),
+
+ Parent = self(),
+ P = spawn_link(Victim,
+ fun () ->
+ Parent ! {self(), started},
+ receive check_msgs -> ok end,
+ bad_dist_ext_check_msgs([one, two]),
+ Parent ! {self(), messages_checked},
+ receive done -> ok end
+ end),
+
+ receive {P, started} -> ok end,
+ P ! one,
+
+ Suspended = make_ref(),
+ S = spawn(Victim,
+ fun () ->
+ erlang:suspend_process(P),
+ Parent ! Suspended,
+ receive after infinity -> ok end
+ end),
+
+ receive Suspended -> ok end,
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ verify_up(Offender, Victim),
+ send_bad_msgs(Offender, P, 5),
+
+ P ! two,
+ send_bad_msgs(Offender, P, 5),
%% Make sure bad msgs has reached Victim
- ?line rpc:call(Offender, rpc, call, [Victim, erlang, node, []]),
-
- ?line verify_still_up(Offender, Victim),
- ?line {message_queue_len, 12}
- = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
- ?line verify_still_up(Offender, Victim),
- ?line [{message_queue_len, 2},
- {messages, [one, two]}]
- = rpc:call(Victim, erlang, process_info, [P, [message_queue_len,
- messages]]),
- ?line verify_down(Offender, connection_closed, Victim, killed),
-
- ?line P ! check_msgs,
- ?line exit(S, bang),
- ?line receive {P, messages_checked} -> ok end,
-
- ?line {message_queue_len, 0}
- = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
-
- ?line P ! done,
- ?line unlink(P),
- ?line verify_no_down(Offender, Victim),
- ?line stop_node(Offender),
- ?line stop_node(Victim).
+ rpc:call(Offender, rpc, call, [Victim, erlang, node, []]),
+
+ verify_still_up(Offender, Victim),
+ {message_queue_len, 12}
+ = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
+ verify_still_up(Offender, Victim),
+ [{message_queue_len, 2},
+ {messages, [one, two]}]
+ = rpc:call(Victim, erlang, process_info, [P, [message_queue_len,
+ messages]]),
+ verify_down(Offender, connection_closed, Victim, killed),
+
+ P ! check_msgs,
+ exit(S, bang),
+ receive {P, messages_checked} -> ok end,
+
+ {message_queue_len, 0}
+ = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
+
+ P ! done,
+ unlink(P),
+ verify_no_down(Offender, Victim),
+ stop_node(Offender),
+ stop_node(Victim).
bad_dist_ext_control(Config) when is_list(Config) ->
- ?line {ok, Offender} = start_node(bad_dist_ext_control_offender),
- ?line {ok, Victim} = start_node(bad_dist_ext_control_victim),
- ?line start_node_monitors([Offender,Victim]),
+ {ok, Offender} = start_node(bad_dist_ext_control_offender),
+ {ok, Victim} = start_node(bad_dist_ext_control_victim),
+ start_node_monitors([Offender,Victim]),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line verify_up(Offender, Victim),
- ?line send_bad_dhdr(Offender, Victim),
- ?line verify_down(Offender, connection_closed, Victim, killed),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ verify_up(Offender, Victim),
+ send_bad_dhdr(Offender, Victim),
+ verify_down(Offender, connection_closed, Victim, killed),
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line verify_up(Offender, Victim),
- ?line send_bad_ctl(Offender, Victim),
- ?line verify_down(Offender, connection_closed, Victim, killed),
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ verify_up(Offender, Victim),
+ send_bad_ctl(Offender, Victim),
+ verify_down(Offender, connection_closed, Victim, killed),
- ?line verify_no_down(Offender, Victim),
- ?line stop_node(Offender),
- ?line stop_node(Victim).
+ verify_no_down(Offender, Victim),
+ stop_node(Offender),
+ stop_node(Victim).
bad_dist_ext_connection_id(Config) when is_list(Config) ->
- ?line {ok, Offender} = start_node(bad_dist_ext_connection_id_offender),
- ?line {ok, Victim} = start_node(bad_dist_ext_connection_id_victim),
- ?line start_node_monitors([Offender,Victim]),
-
- ?line Parent = self(),
- ?line P = spawn_link(Victim,
- fun () ->
- Parent ! {self(), started},
- receive check_msgs -> ok end,
- bad_dist_ext_check_msgs([]),
- Parent ! {self(), messages_checked},
- receive done -> ok end
- end),
-
- ?line receive {P, started} -> ok end,
- ?line Suspended = make_ref(),
- ?line S = spawn(Victim,
- fun () ->
- erlang:suspend_process(P),
- Parent ! Suspended,
- receive after infinity -> ok end
- end),
- ?line MS = erlang:monitor(process, S),
- ?line receive Suspended -> ok end,
- ?line pong = rpc:call(Victim, net_adm, ping, [Offender]),
- ?line verify_up(Offender, Victim),
- ?line send_bad_msg(Offender, P),
+ {ok, Offender} = start_node(bad_dist_ext_connection_id_offender),
+ {ok, Victim} = start_node(bad_dist_ext_connection_id_victim),
+ start_node_monitors([Offender,Victim]),
+
+ Parent = self(),
+ P = spawn_link(Victim,
+ fun () ->
+ Parent ! {self(), started},
+ receive check_msgs -> ok end,
+ bad_dist_ext_check_msgs([]),
+ Parent ! {self(), messages_checked},
+ receive done -> ok end
+ end),
+
+ receive {P, started} -> ok end,
+ Suspended = make_ref(),
+ S = spawn(Victim,
+ fun () ->
+ erlang:suspend_process(P),
+ Parent ! Suspended,
+ receive after infinity -> ok end
+ end),
+ MS = erlang:monitor(process, S),
+ receive Suspended -> ok end,
+ pong = rpc:call(Victim, net_adm, ping, [Offender]),
+ verify_up(Offender, Victim),
+ send_bad_msg(Offender, P),
%% Make sure bad msg has reached Victim
- ?line rpc:call(Offender, rpc, call, [Victim, erlang, node, []]),
+ rpc:call(Offender, rpc, call, [Victim, erlang, node, []]),
- ?line {message_queue_len, 1}
- = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
+ {message_queue_len, 1}
+ = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
- ?line true = rpc:call(Offender, net_kernel, disconnect, [Victim]),
- ?line verify_down(Offender, disconnect, Victim, connection_closed),
- ?line pong = rpc:call(Offender, net_adm, ping, [Victim]),
+ true = rpc:call(Offender, net_kernel, disconnect, [Victim]),
+ verify_down(Offender, disconnect, Victim, connection_closed),
+ pong = rpc:call(Offender, net_adm, ping, [Victim]),
- ?line verify_up(Offender, Victim),
+ verify_up(Offender, Victim),
%% We have a new connection between Offender and Victim, bad message
%% should not bring it down.
- ?line {message_queue_len, 1}
- = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
+ {message_queue_len, 1}
+ = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
- ?line exit(S, bang),
- ?line receive {'DOWN', MS, process, S, bang} -> ok end,
+ exit(S, bang),
+ receive {'DOWN', MS, process, S, bang} -> ok end,
%% Wait for a while (if the connection is taken down it might take a
%% while).
- ?line receive after 2000 -> ok end,
- ?line verify_still_up(Offender, Victim),
+ receive after 2000 -> ok end,
+ verify_still_up(Offender, Victim),
+
+ P ! check_msgs,
+ receive {P, messages_checked} -> ok end,
- ?line P ! check_msgs,
- ?line receive {P, messages_checked} -> ok end,
+ {message_queue_len, 0}
+ = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
- ?line {message_queue_len, 0}
- = rpc:call(Victim, erlang, process_info, [P, message_queue_len]),
-
- ?line verify_still_up(Offender, Victim),
- ?line P ! done,
- ?line unlink(P),
- ?line verify_no_down(Offender, Victim),
- ?line stop_node(Offender),
- ?line stop_node(Victim).
+ verify_still_up(Offender, Victim),
+ P ! done,
+ unlink(P),
+ verify_no_down(Offender, Victim),
+ stop_node(Offender),
+ stop_node(Victim).
bad_dist_struct_check_msgs([]) ->
receive
- Msg ->
- exit({unexpected_message, Msg})
+ Msg ->
+ exit({unexpected_message, Msg})
after 0 ->
- ok
+ ok
end;
bad_dist_struct_check_msgs([M|Ms]) ->
receive
- {'EXIT',_,_} = EM ->
- io:format("Ignoring exit message: ~p~n",[EM]),
- bad_dist_struct_check_msgs([M|Ms]);
- Msg ->
- M = Msg,
- bad_dist_struct_check_msgs(Ms)
+ {'EXIT',_,_} = EM ->
+ io:format("Ignoring exit message: ~p~n",[EM]),
+ bad_dist_struct_check_msgs([M|Ms]);
+ Msg ->
+ M = Msg,
+ bad_dist_struct_check_msgs(Ms)
end.
bad_dist_ext_check_msgs([]) ->
receive
- Msg ->
- exit({unexpected_message, Msg})
+ Msg ->
+ exit({unexpected_message, Msg})
after 0 ->
- ok
+ ok
end;
bad_dist_ext_check_msgs([M|Ms]) ->
receive
- Msg ->
- M = Msg,
- bad_dist_ext_check_msgs(Ms)
+ Msg ->
+ M = Msg,
+ bad_dist_ext_check_msgs(Ms)
end.
-
+
dport_reg_send(Node, Name, Msg) ->
DPrt = case dport(Node) of
- undefined ->
- pong = net_adm:ping(Node),
- dport(Node);
- Prt ->
- Prt
- end,
+ undefined ->
+ pong = net_adm:ping(Node),
+ dport(Node);
+ Prt ->
+ Prt
+ end,
port_command(DPrt, [dmsg_hdr(),
- dmsg_ext({?DOP_REG_SEND,
- self(),
- ?COOKIE,
- Name}),
- dmsg_ext(Msg)]).
+ dmsg_ext({?DOP_REG_SEND,
+ self(),
+ ?COOKIE,
+ Name}),
+ dmsg_ext(Msg)]).
dport_send(To, Msg) ->
Node = node(To),
DPrt = case dport(Node) of
- undefined ->
- pong = net_adm:ping(Node),
- dport(Node);
- Prt ->
- Prt
- end,
+ undefined ->
+ pong = net_adm:ping(Node),
+ dport(Node);
+ Prt ->
+ Prt
+ end,
port_command(DPrt, [dmsg_hdr(),
- dmsg_ext({?DOP_SEND,
- ?COOKIE,
- To}),
- dmsg_ext(Msg)]).
+ dmsg_ext({?DOP_SEND,
+ ?COOKIE,
+ To}),
+ dmsg_ext(Msg)]).
send_bad_structure(Offender,Victim,Bad,WhereToPutSelf) ->
send_bad_structure(Offender,Victim,Bad,WhereToPutSelf,[]).
send_bad_structure(Offender,Victim,Bad,WhereToPutSelf,PayLoad) ->
Parent = self(),
Done = make_ref(),
spawn(Offender,
- fun () ->
- Node = node(Victim),
- pong = net_adm:ping(Node),
- DPrt = dport(Node),
- Bad1 = case WhereToPutSelf of
- 0 ->
- Bad;
- N when N > 0 ->
- setelement(N,Bad,self())
- end,
- DData = [dmsg_hdr(),
- dmsg_ext(Bad1)] ++
- case PayLoad of
- [] -> [];
- _Other -> [dmsg_ext(PayLoad)]
- end,
- port_command(DPrt, DData),
- Parent ! {DData,Done}
- end),
+ fun () ->
+ Node = node(Victim),
+ pong = net_adm:ping(Node),
+ DPrt = dport(Node),
+ Bad1 = case WhereToPutSelf of
+ 0 ->
+ Bad;
+ N when N > 0 ->
+ setelement(N,Bad,self())
+ end,
+ DData = [dmsg_hdr(),
+ dmsg_ext(Bad1)] ++
+ case PayLoad of
+ [] -> [];
+ _Other -> [dmsg_ext(PayLoad)]
+ end,
+ port_command(DPrt, DData),
+ Parent ! {DData,Done}
+ end),
receive
- {WhatSent,Done} ->
- io:format("Offender sent ~p~n",[WhatSent]),
- ok
+ {WhatSent,Done} ->
+ io:format("Offender sent ~p~n",[WhatSent]),
+ ok
after 5000 ->
- exit(unable_to_send)
+ exit(unable_to_send)
end.
-
+
%% send_bad_msgs():
%% Send a valid distribution header and control message
@@ -1861,21 +1782,21 @@ send_bad_msg(BadNode, To) ->
send_bad_msgs(BadNode, To, 1).
send_bad_msgs(BadNode, To, Repeat) when is_atom(BadNode),
- is_pid(To),
- is_integer(Repeat) ->
+ is_pid(To),
+ is_integer(Repeat) ->
Parent = self(),
Done = make_ref(),
spawn_link(BadNode,
- fun () ->
- Node = node(To),
- pong = net_adm:ping(Node),
- DPrt = dport(Node),
- DData = [dmsg_hdr(),
- dmsg_ext({?DOP_SEND, ?COOKIE, To}),
- dmsg_bad_atom_cache_ref()],
- repeat(fun () -> port_command(DPrt, DData) end, Repeat),
- Parent ! Done
- end),
+ fun () ->
+ Node = node(To),
+ pong = net_adm:ping(Node),
+ DPrt = dport(Node),
+ DData = [dmsg_hdr(),
+ dmsg_ext({?DOP_SEND, ?COOKIE, To}),
+ dmsg_bad_atom_cache_ref()],
+ repeat(fun () -> port_command(DPrt, DData) end, Repeat),
+ Parent ! Done
+ end),
receive Done -> ok end.
%% send_bad_ctl():
@@ -1884,24 +1805,24 @@ send_bad_ctl(BadNode, ToNode) when is_atom(BadNode), is_atom(ToNode) ->
Parent = self(),
Done = make_ref(),
spawn_link(BadNode,
- fun () ->
- pong = net_adm:ping(ToNode),
- %% We creat a valid ctl msg and replace an
- %% atom with an invalid atom cache reference
- <<131,Replace/binary>> = term_to_binary(replace),
- Ctl = dmsg_ext({?DOP_REG_SEND,
- self(),
- ?COOKIE,
- replace}),
- CtlBeginSize = size(Ctl) - size(Replace),
- <<CtlBegin:CtlBeginSize/binary, Replace/binary>> = Ctl,
- port_command(dport(ToNode),
- [dmsg_fake_hdr2(),
- CtlBegin,
- dmsg_bad_atom_cache_ref(),
- dmsg_ext({a, message})]),
- Parent ! Done
- end),
+ fun () ->
+ pong = net_adm:ping(ToNode),
+ %% We creat a valid ctl msg and replace an
+ %% atom with an invalid atom cache reference
+ <<131,Replace/binary>> = term_to_binary(replace),
+ Ctl = dmsg_ext({?DOP_REG_SEND,
+ self(),
+ ?COOKIE,
+ replace}),
+ CtlBeginSize = size(Ctl) - size(Replace),
+ <<CtlBegin:CtlBeginSize/binary, Replace/binary>> = Ctl,
+ port_command(dport(ToNode),
+ [dmsg_fake_hdr2(),
+ CtlBegin,
+ dmsg_bad_atom_cache_ref(),
+ dmsg_ext({a, message})]),
+ Parent ! Done
+ end),
receive Done -> ok end.
%% send_bad_dhr():
@@ -1910,17 +1831,17 @@ send_bad_dhdr(BadNode, ToNode) when is_atom(BadNode), is_atom(ToNode) ->
Parent = self(),
Done = make_ref(),
spawn_link(BadNode,
- fun () ->
- pong = net_adm:ping(ToNode),
- port_command(dport(ToNode), dmsg_bad_hdr()),
- Parent ! Done
- end),
+ fun () ->
+ pong = net_adm:ping(ToNode),
+ port_command(dport(ToNode), dmsg_bad_hdr()),
+ Parent ! Done
+ end),
receive Done -> ok end.
dport(Node) when is_atom(Node) ->
case catch erts_debug:get_internal_state(available_internal_state) of
- true -> true;
- _ -> erts_debug:set_internal_state(available_internal_state, true)
+ true -> true;
+ _ -> erts_debug:set_internal_state(available_internal_state, true)
end,
erts_debug:get_internal_state({dist_port, Node}).
@@ -1933,7 +1854,7 @@ dmsg_bad_hdr() ->
[131, % Version Magic
$D, % Dist header
255]. % 255 atom references
-
+
%% dmsg_fake_hdr1() ->
%% A = <<"fake header atom 1">>,
@@ -1974,21 +1895,21 @@ start_node(Name, Args, Rel) when is_atom(Name), is_list(Rel) ->
Pa = filename:dirname(code:which(?MODULE)),
Cookie = atom_to_list(erlang:get_cookie()),
RelArg = case Rel of
- [] -> [];
- _ -> [{erl,[{release,Rel}]}]
- end,
+ [] -> [];
+ _ -> [{erl,[{release,Rel}]}]
+ end,
test_server:start_node(Name, slave,
- [{args,
- Args++" -setcookie "++Cookie++" -pa \""++Pa++"\""}
- | RelArg]);
+ [{args,
+ Args++" -setcookie "++Cookie++" -pa \""++Pa++"\""}
+ | RelArg]);
start_node(Config, Args, Rel) when is_list(Config), is_list(Rel) ->
Name = list_to_atom((atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(?config(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(seconds))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive])))),
+ ++ "-"
+ ++ atom_to_list(proplists:get_value(testcase, Config))
+ ++ "-"
+ ++ integer_to_list(erlang:system_time(seconds))
+ ++ "-"
+ ++ integer_to_list(erlang:unique_integer([positive])))),
start_node(Name, Args, Rel).
stop_node(Node) ->
@@ -1999,13 +1920,13 @@ freeze_node(Node, MS) ->
DoingIt = make_ref(),
Freezer = self(),
spawn_link(Node,
- fun () ->
- erts_debug:set_internal_state(available_internal_state,
- true),
- dport_send(Freezer, DoingIt),
- receive after Own -> ok end,
- erts_debug:set_internal_state(block, MS+Own)
- end),
+ fun () ->
+ erts_debug:set_internal_state(available_internal_state,
+ true),
+ dport_send(Freezer, DoingIt),
+ receive after Own -> ok end,
+ erts_debug:set_internal_state(block, MS+Own)
+ end),
receive DoingIt -> ok end,
receive after Own -> ok end.
@@ -2016,46 +1937,46 @@ do_inet_rpc({_,_,Sock},M,F,A) ->
Bin = term_to_binary({M,F,A}),
gen_tcp:send(Sock,Bin),
case gen_tcp:recv(Sock,0) of
- {ok, Bin2} ->
- T = binary_to_term(Bin2),
- {ok,T};
- Else ->
- {error, Else}
+ {ok, Bin2} ->
+ T = binary_to_term(Bin2),
+ {ok,T};
+ Else ->
+ {error, Else}
end.
inet_rpc_server([Host, PortList]) ->
Port = list_to_integer(PortList),
{ok, Sock} = gen_tcp:connect(Host, Port,[binary, {packet, 4},
- {active, false}]),
+ {active, false}]),
inet_rpc_server_loop(Sock).
inet_rpc_server_loop(Sock) ->
case gen_tcp:recv(Sock,0) of
- {ok, Bin} ->
- {M,F,A} = binary_to_term(Bin),
- Res = (catch apply(M,F,A)),
- RB = term_to_binary(Res),
- gen_tcp:send(Sock,RB),
- inet_rpc_server_loop(Sock);
- _ ->
- erlang:halt()
+ {ok, Bin} ->
+ {M,F,A} = binary_to_term(Bin),
+ Res = (catch apply(M,F,A)),
+ RB = term_to_binary(Res),
+ gen_tcp:send(Sock,RB),
+ inet_rpc_server_loop(Sock);
+ _ ->
+ erlang:halt()
end.
-
+
start_relay_node(Node, Args) ->
Pa = filename:dirname(code:which(?MODULE)),
Cookie = "NOT"++atom_to_list(erlang:get_cookie()),
{ok, LSock} = gen_tcp:listen(0, [binary, {packet, 4},
- {active, false}]),
+ {active, false}]),
{ok, Port} = inet:port(LSock),
{ok, Host} = inet:gethostname(),
RunArg = "-run " ++ atom_to_list(?MODULE) ++ " inet_rpc_server " ++
- Host ++ " " ++ integer_to_list(Port),
+ Host ++ " " ++ integer_to_list(Port),
{ok, NN} =
- test_server:start_node(Node, peer,
- [{args, Args ++
- " -setcookie "++Cookie++" -pa "++Pa++" "++
- RunArg}]),
+ test_server:start_node(Node, peer,
+ [{args, Args ++
+ " -setcookie "++Cookie++" -pa "++Pa++" "++
+ RunArg}]),
[N,H] = string:tokens(atom_to_list(NN),"@"),
{ok, Sock} = gen_tcp:accept(LSock),
pang = net_adm:ping(NN),
@@ -2070,28 +1991,28 @@ wait_dead(N,H,0) ->
{error,{not_dead,N,H}};
wait_dead(N,H,X) ->
case erl_epmd:port_please(N,H) of
- {port,_,_} ->
- receive
- after 1000 ->
- ok
- end,
- wait_dead(N,H,X-1);
- noport ->
- ok;
- Else ->
- {error, {unexpected, Else}}
+ {port,_,_} ->
+ receive
+ after 1000 ->
+ ok
+ end,
+ wait_dead(N,H,X-1);
+ noport ->
+ ok;
+ Else ->
+ {error, {unexpected, Else}}
end.
-
+
start_node_monitors(Nodes) ->
Master = self(),
lists:foreach(fun (Node) ->
- spawn(Node,
- fun () ->
- node_monitor(Master)
- end)
- end,
- Nodes),
+ spawn(Node,
+ fun () ->
+ node_monitor(Master)
+ end)
+ end,
+ Nodes),
ok.
node_monitor(Master) ->
@@ -2100,42 +2021,42 @@ node_monitor(Master) ->
net_kernel:monitor_nodes(true, Opts),
Nodes1 = nodes(connected),
case lists:sort(Nodes0) == lists:sort(Nodes1) of
- true ->
- lists:foreach(fun (Node) ->
- Master ! {nodeup, node(), Node}
- end,
- Nodes0),
- ?t:format("~p ~p: ~p~n", [node(), erlang:system_time(micro_seconds), Nodes0]),
- node_monitor_loop(Master);
- false ->
- net_kernel:monitor_nodes(false, Opts),
- flush_node_changes(),
- node_monitor(Master)
+ true ->
+ lists:foreach(fun (Node) ->
+ Master ! {nodeup, node(), Node}
+ end,
+ Nodes0),
+ io:format("~p ~p: ~p~n", [node(), erlang:system_time(micro_seconds), Nodes0]),
+ node_monitor_loop(Master);
+ false ->
+ net_kernel:monitor_nodes(false, Opts),
+ flush_node_changes(),
+ node_monitor(Master)
end.
flush_node_changes() ->
receive
- {NodeChange, _Node, _InfoList} when NodeChange == nodeup;
- NodeChange == nodedown ->
- flush_node_changes()
+ {NodeChange, _Node, _InfoList} when NodeChange == nodeup;
+ NodeChange == nodedown ->
+ flush_node_changes()
after 0 ->
- ok
+ ok
end.
node_monitor_loop(Master) ->
receive
- {nodeup, Node, _InfoList} = Msg ->
- Master ! {nodeup, node(), Node},
- ?t:format("~p ~p: ~p~n", [node(), erlang:system_time(micro_seconds), Msg]),
- node_monitor_loop(Master);
- {nodedown, Node, InfoList} = Msg ->
- Reason = case lists:keysearch(nodedown_reason, 1, InfoList) of
- {value, {nodedown_reason, R}} -> R;
- _ -> undefined
- end,
- Master ! {nodedown, node(), Node, Reason},
- ?t:format("~p ~p: ~p~n", [node(), erlang:system_time(micro_seconds), Msg]),
- node_monitor_loop(Master)
+ {nodeup, Node, _InfoList} = Msg ->
+ Master ! {nodeup, node(), Node},
+ io:format("~p ~p: ~p~n", [node(), erlang:system_time(micro_seconds), Msg]),
+ node_monitor_loop(Master);
+ {nodedown, Node, InfoList} = Msg ->
+ Reason = case lists:keysearch(nodedown_reason, 1, InfoList) of
+ {value, {nodedown_reason, R}} -> R;
+ _ -> undefined
+ end,
+ Master ! {nodedown, node(), Node, Reason},
+ io:format("~p ~p: ~p~n", [node(), erlang:system_time(micro_seconds), Msg]),
+ node_monitor_loop(Master)
end.
verify_up(A, B) ->
@@ -2149,16 +2070,16 @@ verify_still_up(A, B) ->
verify_no_down(A, B) ->
receive
- {nodedown, A, B, _} = Msg0 ->
- ?t:fail(Msg0)
+ {nodedown, A, B, _} = Msg0 ->
+ ct:fail(Msg0)
after 0 ->
- ok
+ ok
end,
receive
- {nodedown, B, A, _} = Msg1 ->
- ?t:fail(Msg1)
+ {nodedown, B, A, _} = Msg1 ->
+ ct:fail(Msg1)
after 0 ->
- ok
+ ok
end.
%% verify_down(A, B) ->
@@ -2167,12 +2088,12 @@ verify_no_down(A, B) ->
verify_down(A, ReasonA, B, ReasonB) ->
receive
- {nodedown, A, B, _} = Msg0 ->
- {nodedown, A, B, ReasonA} = Msg0
+ {nodedown, A, B, _} = Msg0 ->
+ {nodedown, A, B, ReasonA} = Msg0
end,
receive
- {nodedown, B, A, _} = Msg1 ->
- {nodedown, B, A, ReasonB} = Msg1
+ {nodedown, B, A, _} = Msg1 ->
+ {nodedown, B, A, ReasonB} = Msg1
end,
ok.
@@ -2192,17 +2113,17 @@ from(_, []) -> [].
long_or_short() ->
case net_kernel:longnames() of
- true -> " -name ";
- false -> " -sname "
+ true -> " -name ";
+ false -> " -sname "
end.
until(Fun) ->
case Fun() of
- true ->
- ok;
- false ->
- receive after 10 -> ok end,
- until(Fun)
+ true ->
+ ok;
+ false ->
+ receive after 10 -> ok end,
+ until(Fun)
end.
forever(Fun) ->
@@ -2227,9 +2148,9 @@ stop_busy_dist_port_tracer(_) ->
busy_dist_port_tracer() ->
receive
- {monitor, _SuspendedProcess, busy_dist_port, _Port} = M ->
- erlang:display(M),
- busy_dist_port_tracer()
+ {monitor, _SuspendedProcess, busy_dist_port, _Port} = M ->
+ erlang:display(M),
+ busy_dist_port_tracer()
end.
repeat(_Fun, 0) ->
@@ -2242,38 +2163,38 @@ string_to_atom_ext(String) ->
Utf8List = string_to_utf8_list(String),
Len = length(Utf8List),
case Len < 256 of
- true ->
- [?SMALL_ATOM_UTF8_EXT, Len | Utf8List];
- false ->
- [?ATOM_UTF8_EXT, Len bsr 8, Len band 16#ff | Utf8List]
+ true ->
+ [?SMALL_ATOM_UTF8_EXT, Len | Utf8List];
+ false ->
+ [?ATOM_UTF8_EXT, Len bsr 8, Len band 16#ff | Utf8List]
end.
string_to_atom(String) ->
binary_to_term(list_to_binary([?VERSION_MAGIC
- | string_to_atom_ext(String)])).
+ | string_to_atom_ext(String)])).
string_to_utf8_list([]) ->
[];
string_to_utf8_list([CP|CPs]) when is_integer(CP),
- 0 =< CP,
- CP =< 16#7F ->
+ 0 =< CP,
+ CP =< 16#7F ->
[CP | string_to_utf8_list(CPs)];
string_to_utf8_list([CP|CPs]) when is_integer(CP),
- 16#80 =< CP,
- CP =< 16#7FF ->
+ 16#80 =< CP,
+ CP =< 16#7FF ->
[16#C0 bor (CP bsr 6),
16#80 bor (16#3F band CP)
| string_to_utf8_list(CPs)];
string_to_utf8_list([CP|CPs]) when is_integer(CP),
- 16#800 =< CP,
- CP =< 16#FFFF ->
+ 16#800 =< CP,
+ CP =< 16#FFFF ->
[16#E0 bor (CP bsr 12),
16#80 bor (16#3F band (CP bsr 6)),
16#80 bor (16#3F band CP)
| string_to_utf8_list(CPs)];
string_to_utf8_list([CP|CPs]) when is_integer(CP),
- 16#10000 =< CP,
- CP =< 16#10FFFF ->
+ 16#10000 =< CP,
+ CP =< 16#10FFFF ->
[16#F0 bor (CP bsr 18),
16#80 bor (16#3F band (CP bsr 12)),
16#80 bor (16#3F band (CP bsr 6)),
@@ -2283,47 +2204,47 @@ string_to_utf8_list([CP|CPs]) when is_integer(CP),
utf8_list_to_string([]) ->
[];
utf8_list_to_string([B|Bs]) when is_integer(B),
- 0 =< B,
- B =< 16#7F ->
+ 0 =< B,
+ B =< 16#7F ->
[B | utf8_list_to_string(Bs)];
utf8_list_to_string([B0, B1 | Bs]) when is_integer(B0),
- 16#C0 =< B0,
- B0 =< 16#DF,
- is_integer(B1),
- 16#80 =< B1,
- B1 =< 16#BF ->
+ 16#C0 =< B0,
+ B0 =< 16#DF,
+ is_integer(B1),
+ 16#80 =< B1,
+ B1 =< 16#BF ->
[(((B0 band 16#1F) bsl 6)
- bor (B1 band 16#3F))
+ bor (B1 band 16#3F))
| utf8_list_to_string(Bs)];
utf8_list_to_string([B0, B1, B2 | Bs]) when is_integer(B0),
- 16#E0 =< B0,
- B0 =< 16#EF,
- is_integer(B1),
- 16#80 =< B1,
- B1 =< 16#BF,
- is_integer(B2),
- 16#80 =< B2,
- B2 =< 16#BF ->
+ 16#E0 =< B0,
+ B0 =< 16#EF,
+ is_integer(B1),
+ 16#80 =< B1,
+ B1 =< 16#BF,
+ is_integer(B2),
+ 16#80 =< B2,
+ B2 =< 16#BF ->
[(((B0 band 16#F) bsl 12)
- bor ((B1 band 16#3F) bsl 6)
- bor (B2 band 16#3F))
+ bor ((B1 band 16#3F) bsl 6)
+ bor (B2 band 16#3F))
| utf8_list_to_string(Bs)];
utf8_list_to_string([B0, B1, B2, B3 | Bs]) when is_integer(B0),
- 16#F0 =< B0,
- B0 =< 16#F7,
- is_integer(B1),
- 16#80 =< B1,
- B1 =< 16#BF,
- is_integer(B2),
- 16#80 =< B2,
- B2 =< 16#BF,
- is_integer(B3),
- 16#80 =< B3,
- B3 =< 16#BF ->
+ 16#F0 =< B0,
+ B0 =< 16#F7,
+ is_integer(B1),
+ 16#80 =< B1,
+ B1 =< 16#BF,
+ is_integer(B2),
+ 16#80 =< B2,
+ B2 =< 16#BF,
+ is_integer(B3),
+ 16#80 =< B3,
+ B3 =< 16#BF ->
[(((B0 band 16#7) bsl 18)
- bor ((B1 band 16#3F) bsl 12)
- bor ((B2 band 16#3F) bsl 6)
- bor (B3 band 16#3F))
+ bor ((B1 band 16#3F) bsl 12)
+ bor ((B2 band 16#3F) bsl 6)
+ bor (B3 band 16#3F))
| utf8_list_to_string(Bs)].
mk_pid({NodeName, Creation}, Number, Serial) when is_atom(NodeName) ->
@@ -2331,17 +2252,17 @@ mk_pid({NodeName, Creation}, Number, Serial) when is_atom(NodeName) ->
mk_pid({NodeNameExt, Creation}, Number, Serial);
mk_pid({NodeNameExt, Creation}, Number, Serial) ->
case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
- ?PID_EXT,
- NodeNameExt,
- uint32_be(Number),
- uint32_be(Serial),
- uint8(Creation)])) of
- Pid when is_pid(Pid) ->
- Pid;
- {'EXIT', {badarg, _}} ->
- exit({badarg, mk_pid, [{NodeNameExt, Creation}, Number, Serial]});
- Other ->
- exit({unexpected_binary_to_term_result, Other})
+ ?PID_EXT,
+ NodeNameExt,
+ uint32_be(Number),
+ uint32_be(Serial),
+ uint8(Creation)])) of
+ Pid when is_pid(Pid) ->
+ Pid;
+ {'EXIT', {badarg, _}} ->
+ exit({badarg, mk_pid, [{NodeNameExt, Creation}, Number, Serial]});
+ Other ->
+ exit({unexpected_binary_to_term_result, Other})
end.
mk_port({NodeName, Creation}, Number) when is_atom(NodeName) ->
@@ -2349,59 +2270,59 @@ mk_port({NodeName, Creation}, Number) when is_atom(NodeName) ->
mk_port({NodeNameExt, Creation}, Number);
mk_port({NodeNameExt, Creation}, Number) ->
case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
- ?PORT_EXT,
- NodeNameExt,
- uint32_be(Number),
- uint8(Creation)])) of
- Port when is_port(Port) ->
- Port;
- {'EXIT', {badarg, _}} ->
- exit({badarg, mk_port, [{NodeNameExt, Creation}, Number]});
- Other ->
- exit({unexpected_binary_to_term_result, Other})
+ ?PORT_EXT,
+ NodeNameExt,
+ uint32_be(Number),
+ uint8(Creation)])) of
+ Port when is_port(Port) ->
+ Port;
+ {'EXIT', {badarg, _}} ->
+ exit({badarg, mk_port, [{NodeNameExt, Creation}, Number]});
+ Other ->
+ exit({unexpected_binary_to_term_result, Other})
end.
mk_ref({NodeName, Creation}, [Number] = NL) when is_atom(NodeName),
- is_integer(Creation),
- is_integer(Number) ->
+ is_integer(Creation),
+ is_integer(Number) ->
<<?VERSION_MAGIC, NodeNameExt/binary>> = term_to_binary(NodeName),
mk_ref({NodeNameExt, Creation}, NL);
mk_ref({NodeNameExt, Creation}, [Number]) when is_integer(Creation),
- is_integer(Number) ->
+ is_integer(Number) ->
case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
- ?REFERENCE_EXT,
- NodeNameExt,
- uint32_be(Number),
- uint8(Creation)])) of
- Ref when is_reference(Ref) ->
- Ref;
- {'EXIT', {badarg, _}} ->
- exit({badarg, mk_ref, [{NodeNameExt, Creation}, [Number]]});
- Other ->
- exit({unexpected_binary_to_term_result, Other})
+ ?REFERENCE_EXT,
+ NodeNameExt,
+ uint32_be(Number),
+ uint8(Creation)])) of
+ Ref when is_reference(Ref) ->
+ Ref;
+ {'EXIT', {badarg, _}} ->
+ exit({badarg, mk_ref, [{NodeNameExt, Creation}, [Number]]});
+ Other ->
+ exit({unexpected_binary_to_term_result, Other})
end;
mk_ref({NodeName, Creation}, Numbers) when is_atom(NodeName),
- is_integer(Creation),
- is_list(Numbers) ->
+ is_integer(Creation),
+ is_list(Numbers) ->
<<?VERSION_MAGIC, NodeNameExt/binary>> = term_to_binary(NodeName),
mk_ref({NodeNameExt, Creation}, Numbers);
mk_ref({NodeNameExt, Creation}, Numbers) when is_integer(Creation),
- is_list(Numbers) ->
+ is_list(Numbers) ->
case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
- ?NEW_REFERENCE_EXT,
- uint16_be(length(Numbers)),
- NodeNameExt,
- uint8(Creation),
- lists:map(fun (N) ->
- uint32_be(N)
- end,
- Numbers)])) of
- Ref when is_reference(Ref) ->
- Ref;
- {'EXIT', {badarg, _}} ->
- exit({badarg, mk_ref, [{NodeNameExt, Creation}, Numbers]});
- Other ->
- exit({unexpected_binary_to_term_result, Other})
+ ?NEW_REFERENCE_EXT,
+ uint16_be(length(Numbers)),
+ NodeNameExt,
+ uint8(Creation),
+ lists:map(fun (N) ->
+ uint32_be(N)
+ end,
+ Numbers)])) of
+ Ref when is_reference(Ref) ->
+ Ref;
+ {'EXIT', {badarg, _}} ->
+ exit({badarg, mk_ref, [{NodeNameExt, Creation}, Numbers]});
+ Other ->
+ exit({unexpected_binary_to_term_result, Other})
end.
diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl
index 4211c49848..c589470f5b 100644
--- a/erts/emulator/test/driver_SUITE.erl
+++ b/erts/emulator/test/driver_SUITE.erl
@@ -29,64 +29,64 @@
-module(driver_SUITE).
-export([all/0, suite/0,groups/0,init_per_suite/1,
- end_per_suite/1, init_per_group/2,end_per_group/2,
- init_per_testcase/2,
- end_per_testcase/2,
-
- a_test/1,
- outputv_echo/1,
- timer_measure/1,
- timer_cancel/1,
- timer_change/1,
- timer_delay/1,
- queue_echo/1,
- outputv_errors/1,
- driver_unloaded/1,
- io_ready_exit/1,
- use_fallback_pollset/1,
- bad_fd_in_pollset/1,
- driver_event/1,
- fd_change/1,
- steal_control/1,
- otp_6602/1,
- driver_system_info_base_ver/1,
- driver_system_info_prev_ver/1,
- driver_system_info_current_ver/1,
- driver_monitor/1,
-
- ioq_exit_ready_input/1,
- ioq_exit_ready_output/1,
- ioq_exit_timeout/1,
- ioq_exit_ready_async/1,
- ioq_exit_event/1,
- ioq_exit_ready_input_async/1,
- ioq_exit_ready_output_async/1,
- ioq_exit_timeout_async/1,
- ioq_exit_event_async/1,
- zero_extended_marker_garb_drv/1,
- invalid_extended_marker_drv/1,
- larger_major_vsn_drv/1,
- larger_minor_vsn_drv/1,
- smaller_major_vsn_drv/1,
- smaller_minor_vsn_drv/1,
- peek_non_existing_queue/1,
- otp_6879/1,
- caller/1,
- many_events/1,
- missing_callbacks/1,
- smp_select/1,
- driver_select_use/1,
- thread_mseg_alloc_cache_clean/1,
- otp_9302/1,
- thr_free_drv/1,
- async_blast/1,
- thr_msg_blast/1,
- consume_timeslice/1,
- z_test/1]).
+ end_per_suite/1, init_per_group/2,end_per_group/2,
+ init_per_testcase/2,
+ end_per_testcase/2,
+
+ a_test/1,
+ outputv_echo/1,
+ timer_measure/1,
+ timer_cancel/1,
+ timer_change/1,
+ timer_delay/1,
+ queue_echo/1,
+ outputv_errors/1,
+ driver_unloaded/1,
+ io_ready_exit/1,
+ use_fallback_pollset/1,
+ bad_fd_in_pollset/1,
+ driver_event/1,
+ fd_change/1,
+ steal_control/1,
+ otp_6602/1,
+ driver_system_info_base_ver/1,
+ driver_system_info_prev_ver/1,
+ driver_system_info_current_ver/1,
+ driver_monitor/1,
+
+ ioq_exit_ready_input/1,
+ ioq_exit_ready_output/1,
+ ioq_exit_timeout/1,
+ ioq_exit_ready_async/1,
+ ioq_exit_event/1,
+ ioq_exit_ready_input_async/1,
+ ioq_exit_ready_output_async/1,
+ ioq_exit_timeout_async/1,
+ ioq_exit_event_async/1,
+ zero_extended_marker_garb_drv/1,
+ invalid_extended_marker_drv/1,
+ larger_major_vsn_drv/1,
+ larger_minor_vsn_drv/1,
+ smaller_major_vsn_drv/1,
+ smaller_minor_vsn_drv/1,
+ peek_non_existing_queue/1,
+ otp_6879/1,
+ caller/1,
+ many_events/1,
+ missing_callbacks/1,
+ smp_select/1,
+ driver_select_use/1,
+ thread_mseg_alloc_cache_clean/1,
+ otp_9302/1,
+ thr_free_drv/1,
+ async_blast/1,
+ thr_msg_blast/1,
+ consume_timeslice/1,
+ z_test/1]).
-export([bin_prefix/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
% First byte in communication with the timer driver
@@ -119,22 +119,22 @@
-define(heap_binary_size, 64).
init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog=?t:timetrap(?t:minutes(2)),
case catch erts_debug:get_internal_state(available_internal_state) of
- true -> ok;
- _ -> erts_debug:set_internal_state(available_internal_state, true)
+ true -> ok;
+ _ -> erts_debug:set_internal_state(available_internal_state, true)
end,
erlang:display({init_per_testcase, Case}),
- ?line 0 = element(1, erts_debug:get_internal_state(check_io_debug)),
- [{watchdog, Dog},{testcase, Case}|Config].
+ 0 = element(1, erts_debug:get_internal_state(check_io_debug)),
+ [{testcase, Case}|Config].
end_per_testcase(Case, Config) ->
- Dog = ?config(watchdog, Config),
erlang:display({end_per_testcase, Case}),
- ?line 0 = element(1, erts_debug:get_internal_state(check_io_debug)),
- ?t:timetrap_cancel(Dog).
+ 0 = element(1, erts_debug:get_internal_state(check_io_debug)),
+ ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 1}}].
all() -> %% Keep a_test first and z_test last...
[a_test, outputv_errors, outputv_echo, queue_echo, {group, timer},
@@ -179,42 +179,42 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-outputv_errors(doc) -> "Test sending bad types to port with an outputv-capable driver.";
+%% Test sending bad types to port with an outputv-capable driver.
outputv_errors(Config) when is_list(Config) ->
- ?line Path = ?config(data_dir, Config),
- ?line erl_ddll:start(),
- ?line ok = load_driver(Path, outputv_drv),
+ Path = proplists:get_value(data_dir, Config),
+ erl_ddll:start(),
+ ok = load_driver(Path, outputv_drv),
outputv_bad_types(fun(T) ->
- ?line outputv_errors_1(T),
- ?line outputv_errors_1([1|T]),
- ?line L = [1,2,3],
- ?line outputv_errors_1([L,T]),
- ?line outputv_errors_1([L|T])
- end),
+ outputv_errors_1(T),
+ outputv_errors_1([1|T]),
+ L = [1,2,3],
+ outputv_errors_1([L,T]),
+ outputv_errors_1([L|T])
+ end),
outputv_errors_1(42),
%% Test iolists that do not fit in the address space.
%% Unfortunately, it would be too slow to test in a 64-bit emulator.
case erlang:system_info(wordsize) of
- 4 -> outputv_huge_iolists();
- _ -> ok
+ 4 -> outputv_huge_iolists();
+ _ -> ok
end.
outputv_bad_types(Test) ->
Types = [-1,256,atom,42.0,{a,b,c},make_ref(),fun() -> 42 end,
- [1|2],<<1:1>>,<<1:9>>,<<1:15>>],
+ [1|2],<<1:1>>,<<1:9>>,<<1:15>>],
_ = [Test(Type) || Type <- Types],
ok.
outputv_huge_iolists() ->
FourGigs = 1 bsl 32,
- ?line Sizes = [FourGigs+N || N <- lists:seq(0, 64)] ++
- [1 bsl N || N <- lists:seq(33, 37)],
- ?line Base = <<0:(1 bsl 20)/unit:8>>,
+ Sizes = [FourGigs+N || N <- lists:seq(0, 64)] ++
+ [1 bsl N || N <- lists:seq(33, 37)],
+ Base = <<0:(1 bsl 20)/unit:8>>,
[begin
- ?line L = build_iolist(Sz, Base),
- ?line outputv_errors_1(L)
+ L = build_iolist(Sz, Base),
+ outputv_errors_1(L)
end || Sz <- Sizes],
ok.
@@ -224,95 +224,94 @@ outputv_errors_1(Term) ->
port_close(Port).
build_iolist(N, Base) when N < 16 ->
- case random:uniform(3) of
- 1 ->
- <<Bin:N/binary,_/binary>> = Base,
- Bin;
- _ ->
- lists:seq(1, N)
+ case rand:uniform(3) of
+ 1 ->
+ <<Bin:N/binary,_/binary>> = Base,
+ Bin;
+ _ ->
+ lists:seq(1, N)
end;
build_iolist(N, Base) when N =< byte_size(Base) ->
- case random:uniform(3) of
- 1 ->
- <<Bin:N/binary,_/binary>> = Base,
- Bin;
- 2 ->
- <<Bin:N/binary,_/binary>> = Base,
- [Bin];
- 3 ->
- case N rem 2 of
- 0 ->
- L = build_iolist(N div 2, Base),
- [L,L];
- 1 ->
- L = build_iolist(N div 2, Base),
- [L,L,45]
- end
+ case rand:uniform(3) of
+ 1 ->
+ <<Bin:N/binary,_/binary>> = Base,
+ Bin;
+ 2 ->
+ <<Bin:N/binary,_/binary>> = Base,
+ [Bin];
+ 3 ->
+ case N rem 2 of
+ 0 ->
+ L = build_iolist(N div 2, Base),
+ [L,L];
+ 1 ->
+ L = build_iolist(N div 2, Base),
+ [L,L,45]
+ end
end;
build_iolist(N0, Base) ->
- Small = random:uniform(15),
+ Small = rand:uniform(15),
Seq = lists:seq(1, Small),
N = N0 - Small,
case N rem 2 of
- 0 ->
- L = build_iolist(N div 2, Base),
- [L,L|Seq];
- 1 ->
- L = build_iolist(N div 2, Base),
- [47,L,L|Seq]
+ 0 ->
+ L = build_iolist(N div 2, Base),
+ [L,L|Seq];
+ 1 ->
+ L = build_iolist(N div 2, Base),
+ [47,L,L|Seq]
end.
-outputv_echo(doc) -> ["Test echoing data with a driver that supports outputv."];
+%% Test echoing data with a driver that supports outputv.
outputv_echo(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(10)),
+ ct:timetrap({minutes, 10}),
Name = 'outputv_drv',
P = start_driver(Config, Name, true),
- ?line ov_test(P, {bin,0}),
- ?line ov_test(P, {bin,1}),
- ?line ov_test(P, {bin,2}),
- ?line ov_test(P, {bin,3}),
- ?line ov_test(P, {bin,4}),
- ?line ov_test(P, {bin,5}),
- ?line ov_test(P, {bin,6}),
- ?line ov_test(P, {bin,7}),
- ?line ov_test(P, {bin,8}),
- ?line ov_test(P, {bin,15}),
- ?line ov_test(P, {bin,16}),
- ?line ov_test(P, {bin,17}),
-
- ?line ov_test(P, {list,0}),
- ?line ov_test(P, {list,1}),
- ?line ov_test(P, {list,2}),
- ?line ov_test(P, [int,int,{list,0},int]),
- ?line ov_test(P, [int,int,{list,1},int]),
- ?line ov_test(P, [int,int,{list,2}]),
- ?line ov_test(P, [{list,3},int,int,{list,2}]),
- ?line ov_test(P, {list,33}),
-
- ?line ov_test(P, [{bin,0}]),
- ?line ov_test(P, [{bin,1}]),
- ?line ov_test(P, [{bin,2}]),
- ?line ov_test(P, [{bin,3}]),
- ?line ov_test(P, [{bin,4}]),
- ?line ov_test(P, [{bin,5}]),
- ?line ov_test(P, [{bin,6},int]),
- ?line ov_test(P, [int,{bin,3}]),
- ?line ov_test(P, [int|{bin,4}]),
- ?line ov_test(P, [{bin,17},int,{bin,13}|{bin,3}]),
-
- ?line ov_test(P, [int,{bin,17},int,{bin,?heap_binary_size+1}|{bin,3}]),
+ ov_test(P, {bin,0}),
+ ov_test(P, {bin,1}),
+ ov_test(P, {bin,2}),
+ ov_test(P, {bin,3}),
+ ov_test(P, {bin,4}),
+ ov_test(P, {bin,5}),
+ ov_test(P, {bin,6}),
+ ov_test(P, {bin,7}),
+ ov_test(P, {bin,8}),
+ ov_test(P, {bin,15}),
+ ov_test(P, {bin,16}),
+ ov_test(P, {bin,17}),
+
+ ov_test(P, {list,0}),
+ ov_test(P, {list,1}),
+ ov_test(P, {list,2}),
+ ov_test(P, [int,int,{list,0},int]),
+ ov_test(P, [int,int,{list,1},int]),
+ ov_test(P, [int,int,{list,2}]),
+ ov_test(P, [{list,3},int,int,{list,2}]),
+ ov_test(P, {list,33}),
+
+ ov_test(P, [{bin,0}]),
+ ov_test(P, [{bin,1}]),
+ ov_test(P, [{bin,2}]),
+ ov_test(P, [{bin,3}]),
+ ov_test(P, [{bin,4}]),
+ ov_test(P, [{bin,5}]),
+ ov_test(P, [{bin,6},int]),
+ ov_test(P, [int,{bin,3}]),
+ ov_test(P, [int|{bin,4}]),
+ ov_test(P, [{bin,17},int,{bin,13}|{bin,3}]),
+
+ ov_test(P, [int,{bin,17},int,{bin,?heap_binary_size+1}|{bin,3}]),
stop_driver(P, Name),
- ?line test_server:timetrap_cancel(Dog),
ok.
ov_test(Port, Template) ->
Self = self(),
spawn_opt(erlang, apply, [fun () -> ov_test(Self, Port, Template) end,[]],
- [link,{fullsweep_after,0}]),
+ [link,{fullsweep_after,0}]),
receive
- done -> ok
+ done -> ok
end.
ov_test(Parent, Port, Template) ->
@@ -354,21 +353,20 @@ ov_send_and_test(Port, Data, ExpectedResult) ->
io:format("~p ! ~P", [Port,Data,12]),
Port ! {self(),{command,Data}},
receive
- {Port,{data,ReturnData}} ->
- io:format("~p returned ~P", [Port,ReturnData,12]),
- compare(ReturnData, ExpectedResult);
- {Port,{data,OtherData}} ->
- io:format("~p returned WRONG data ~p", [Port,OtherData]),
- ?line test_server:fail();
- Wrong ->
- ?line test_server:fail({unexpected_port_or_data,Wrong})
+ {Port,{data,ReturnData}} ->
+ io:format("~p returned ~P", [Port,ReturnData,12]),
+ compare(ReturnData, ExpectedResult);
+ {Port,{data,OtherData}} ->
+ ct:fail("~p returned WRONG data ~p", [Port,OtherData]);
+ Wrong ->
+ ct:fail({unexpected_port_or_data,Wrong})
end.
compare(Got, Expected) ->
case {list_to_binary([Got]),list_to_binary([Expected])} of
- {B,B} -> ok;
- {_Gb,_Eb} ->
- ?t:fail(got_bad_data)
+ {B,B} -> ok;
+ {_Gb,_Eb} ->
+ ct:fail(got_bad_data)
end.
@@ -377,146 +375,138 @@ compare(Got, Expected) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-timer_measure(doc) -> ["Check that timers time out in good time."];
+%% Check that timers time out in good time.
timer_measure(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(1)),
Name = 'timer_drv',
- ?line Port = start_driver(Config, Name, false),
+ Port = start_driver(Config, Name, false),
- ?line try_timeouts(Port, 8997),
+ try_timeouts(Port, 8997),
- ?line stop_driver(Port, Name),
- ?line test_server:timetrap_cancel(Dog),
+ stop_driver(Port, Name),
ok.
try_timeouts(_, 0) -> ok;
try_timeouts(Port, Timeout) ->
- ?line TimeBefore = erlang:monotonic_time(),
- ?line erlang:port_command(Port, <<?START_TIMER,Timeout:32>>),
+ TimeBefore = erlang:monotonic_time(),
+ erlang:port_command(Port, <<?START_TIMER,Timeout:32>>),
receive
- {Port,{data,[?TIMER]}} ->
- ?line Elapsed = erl_millisecs() - erl_millisecs(TimeBefore),
- io:format("Elapsed: ~p Timeout: ~p\n", [Elapsed, Timeout]),
- if
- Elapsed < Timeout ->
- ?line ?t:fail(too_short);
- Elapsed > Timeout + ?delay ->
- ?line ?t:fail(too_long);
- true ->
- try_timeouts(Port, Timeout div 2)
- end
+ {Port,{data,[?TIMER]}} ->
+ Elapsed = erl_millisecs() - erl_millisecs(TimeBefore),
+ io:format("Elapsed: ~p Timeout: ~p\n", [Elapsed, Timeout]),
+ if
+ Elapsed < Timeout ->
+ ct:fail(too_short);
+ Elapsed > Timeout + ?delay ->
+ ct:fail(too_long);
+ true ->
+ try_timeouts(Port, Timeout div 2)
+ end
after Timeout + ?delay ->
- ?line test_server:fail("driver failed to timeout")
+ ct:fail("driver failed to timeout")
end.
-timer_cancel(doc) -> ["Try cancelling timers set in a driver."];
+%% Try cancelling timers set in a driver.
timer_cancel(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(1)),
Name = 'timer_drv',
- ?line Port = start_driver(Config, Name, false),
+ Port = start_driver(Config, Name, false),
- ?line try_cancel(Port, 10000),
+ try_cancel(Port, 10000),
- ?line stop_driver(Port, Name),
- ?line test_server:timetrap_cancel(Dog),
+ stop_driver(Port, Name),
ok.
-
+
try_cancel(Port, Timeout) ->
- ?line T_before = erl_millisecs(),
+ T_before = erl_millisecs(),
Port ! {self(),{command,<<?START_TIMER,(Timeout + ?delay):32>>}},
receive
- {Port, {data, [?TIMER]}} ->
- ?line test_server:fail("driver timed out before cancelling it")
+ {Port, {data, [?TIMER]}} ->
+ ct:fail("driver timed out before cancelling it")
after Timeout ->
- Port ! {self(), {command, [?CANCEL_TIMER]}},
- receive
- {Port, {data, [?TIMER]}} ->
- ?line test_server:fail("driver timed out after cancelling it");
- {Port, {data, [?CANCELLED]}} ->
- ?line Time_milli_secs = erl_millisecs() - T_before,
-
- io:format("Time_milli_secs: ~p Timeout: ~p\n",
- [Time_milli_secs, Timeout]),
- if
- Time_milli_secs > (Timeout + ?delay) ->
- ?line test_server:fail("too long real time");
- Timeout == 0 -> ok;
- true -> try_cancel(Port, Timeout div 2)
- end
- after ?delay ->
- test_server:fail("No message from driver")
- end
+ Port ! {self(), {command, [?CANCEL_TIMER]}},
+ receive
+ {Port, {data, [?TIMER]}} ->
+ ct:fail("driver timed out after cancelling it");
+ {Port, {data, [?CANCELLED]}} ->
+ Time_milli_secs = erl_millisecs() - T_before,
+
+ io:format("Time_milli_secs: ~p Timeout: ~p\n",
+ [Time_milli_secs, Timeout]),
+ if
+ Time_milli_secs > (Timeout + ?delay) ->
+ ct:fail("too long real time");
+ Timeout == 0 -> ok;
+ true -> try_cancel(Port, Timeout div 2)
+ end
+ after ?delay ->
+ ct:fail("No message from driver")
+ end
end.
%% Test that timers don't time out too early if we do a sleep
%% before setting a timer.
timer_delay(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(1)),
Name = 'timer_drv',
- ?line Port = start_driver(Config, Name, false),
+ Port = start_driver(Config, Name, false),
- ?line TimeBefore = erlang:monotonic_time(),
+ TimeBefore = erlang:monotonic_time(),
Timeout0 = 350,
- ?line erlang:port_command(Port, <<?DELAY_START_TIMER,Timeout0:32>>),
+ erlang:port_command(Port, <<?DELAY_START_TIMER,Timeout0:32>>),
Timeout = Timeout0 +
- case os:type() of
- {win32,_} -> 0; %Driver doesn't sleep on Windows.
- _ -> 1000
- end,
+ case os:type() of
+ {win32,_} -> 0; %Driver doesn't sleep on Windows.
+ _ -> 1000
+ end,
receive
- {Port,{data,[?TIMER]}} ->
- ?line Elapsed = erl_millisecs() - erl_millisecs(TimeBefore),
- io:format("Elapsed time: ~p Timeout: ~p\n",
- [Elapsed,Timeout]),
- if
- Elapsed < Timeout ->
- ?line ?t:fail(too_short);
- Elapsed > Timeout + ?delay ->
- ?line ?t:fail(too_long);
- true ->
- ok
- end
+ {Port,{data,[?TIMER]}} ->
+ Elapsed = erl_millisecs() - erl_millisecs(TimeBefore),
+ io:format("Elapsed time: ~p Timeout: ~p\n",
+ [Elapsed,Timeout]),
+ if
+ Elapsed < Timeout ->
+ ct:fail(too_short);
+ Elapsed > Timeout + ?delay ->
+ ct:fail(too_long);
+ true ->
+ ok
+ end
end,
- ?line stop_driver(Port, Name),
- ?line test_server:timetrap_cancel(Dog),
+ stop_driver(Port, Name),
ok.
%% Test that driver_set_timer with new timout really changes
%% the timer (ticket OTP-5942), it didn't work before
timer_change(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(1)),
Name = 'timer_drv',
- ?line Port = start_driver(Config, Name, false),
+ Port = start_driver(Config, Name, false),
- ?line try_change_timer(Port, 10000),
+ try_change_timer(Port, 10000),
- ?line stop_driver(Port, Name),
- ?line test_server:timetrap_cancel(Dog),
+ stop_driver(Port, Name),
ok.
-
+
try_change_timer(_Port, 0) -> ok;
try_change_timer(Port, Timeout) ->
- ?line Timeout_3 = Timeout*3,
- ?line TimeBefore = erlang:monotonic_time(),
- ?line erlang:port_command(Port, <<?START_TIMER,Timeout_3:32>>),
- ?line erlang:port_command(Port, <<?START_TIMER,Timeout:32>>),
+ Timeout_3 = Timeout*3,
+ TimeBefore = erlang:monotonic_time(),
+ erlang:port_command(Port, <<?START_TIMER,Timeout_3:32>>),
+ erlang:port_command(Port, <<?START_TIMER,Timeout:32>>),
receive
- {Port,{data,[?TIMER]}} ->
- ?line Elapsed = erl_millisecs() - erl_millisecs(TimeBefore),
- io:format("Elapsed: ~p Timeout: ~p\n", [Elapsed,Timeout]),
- if
- Elapsed < Timeout ->
- ?line ?t:fail(too_short);
- Elapsed > Timeout + ?delay ->
- ?line ?t:fail(too_long);
- true ->
- try_timeouts(Port, Timeout div 2)
- end
+ {Port,{data,[?TIMER]}} ->
+ Elapsed = erl_millisecs() - erl_millisecs(TimeBefore),
+ io:format("Elapsed: ~p Timeout: ~p\n", [Elapsed,Timeout]),
+ if
+ Elapsed < Timeout ->
+ ct:fail(too_short);
+ Elapsed > Timeout + ?delay ->
+ ct:fail(too_long);
+ true ->
+ try_timeouts(Port, Timeout div 2)
+ end
after Timeout + ?delay ->
- ?line test_server:fail("driver failed to timeout")
+ ct:fail("driver failed to timeout")
end.
@@ -524,49 +514,47 @@ try_change_timer(Port, Timeout) ->
%% Queue test suites
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-queue_echo(doc) ->
- ["1) Queue up data in a driver that uses the full driver_queue API to do this."
- "2) Get the data back, a random amount at a time."];
+%% 1) Queue up data in a driver that uses the full driver_queue API to do this.
+%% 2) Get the data back, a random amount at a time.
queue_echo(Config) when is_list(Config) ->
- case ?t:is_native(?MODULE) of
- true -> exit(crashes_native_code);
- false -> queue_echo_1(Config)
+ case test_server:is_native(?MODULE) of
+ true -> exit(crashes_native_code);
+ false -> queue_echo_1(Config)
end.
queue_echo_1(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(10)),
+ ct:timetrap({minutes, 10}),
Name = 'queue_drv',
- ?line P = start_driver(Config, Name, true),
-
- ?line q_echo(P, [{?ENQ, {list,1}},
- {?ENQ, {list,0}},
- {?ENQ, {bin,0}},
- {?ENQ, {bin,1}},
- {?ENQ, {bin,2}},
- {?ENQ, {bin,3}},
- {?ENQ, {bin,4}},
- {?ENQ, {bin,5}},
- {?ENQ, {bin,600}},
- {?PUSHQ, {list,0}},
- {?PUSHQ, {list,1}},
- {?PUSHQ, {bin,0}},
- {?PUSHQ, {bin,1}},
- {?PUSHQ, {bin,888}},
- {?ENQ_BIN, {bin,0}},
- {?ENQ_BIN, {bin,1}},
- {?ENQ_BIN, {bin,2}},
- {?ENQ_BIN, {bin,3}},
- {?ENQ_BIN, {bin,4}},
- {?ENQ_BIN, {bin,777}},
- {?PUSHQ_BIN, {bin,0}},
- {?PUSHQ_BIN, {bin,1}},
- {?PUSHQ_BIN, {bin,334}},
- {?ENQV, [{bin,0},{list,1},{bin,1},{bin,555}]},
- {?ENQV, [{bin,0},{list,1},{bin,1}]},
- {?PUSHQV, [{bin,0},{list,1},{bin,1},{bin,319}]}]),
-
- ?line stop_driver(P, Name),
- ?line test_server:timetrap_cancel(Dog),
+ P = start_driver(Config, Name, true),
+
+ q_echo(P, [{?ENQ, {list,1}},
+ {?ENQ, {list,0}},
+ {?ENQ, {bin,0}},
+ {?ENQ, {bin,1}},
+ {?ENQ, {bin,2}},
+ {?ENQ, {bin,3}},
+ {?ENQ, {bin,4}},
+ {?ENQ, {bin,5}},
+ {?ENQ, {bin,600}},
+ {?PUSHQ, {list,0}},
+ {?PUSHQ, {list,1}},
+ {?PUSHQ, {bin,0}},
+ {?PUSHQ, {bin,1}},
+ {?PUSHQ, {bin,888}},
+ {?ENQ_BIN, {bin,0}},
+ {?ENQ_BIN, {bin,1}},
+ {?ENQ_BIN, {bin,2}},
+ {?ENQ_BIN, {bin,3}},
+ {?ENQ_BIN, {bin,4}},
+ {?ENQ_BIN, {bin,777}},
+ {?PUSHQ_BIN, {bin,0}},
+ {?PUSHQ_BIN, {bin,1}},
+ {?PUSHQ_BIN, {bin,334}},
+ {?ENQV, [{bin,0},{list,1},{bin,1},{bin,555}]},
+ {?ENQV, [{bin,0},{list,1},{bin,1}]},
+ {?PUSHQV, [{bin,0},{list,1},{bin,1},{bin,319}]}]),
+
+ stop_driver(P, Name),
ok.
q_echo(Port, SpecList) ->
@@ -606,7 +594,7 @@ q_echo(Port, SpecList) ->
feed_and_dequeue(Port, HeapData, 2),
feed_and_dequeue(Port, HeapData, 3),
feed_and_dequeue(Port, HeapData, 4),
-
+
io:format("\n").
feed_and_dequeue(Port, Data, DeqSize) ->
@@ -626,9 +614,9 @@ feed_driver(Port, [], ExpectedInPort, Qb) ->
{ExpectedInPort,Qb};
feed_driver(Port, [{Method0,Data}|T], Expected_return, Qb_before) ->
Method = case Method0 of
- ?RANDOM -> uniform(6)-1;
- Other -> Other
- end,
+ ?RANDOM -> uniform(6)-1;
+ Other -> Other
+ end,
Size = size(list_to_binary([Data])),
%% ***********************************************************************
@@ -643,22 +631,21 @@ feed_driver(Port, [{Method0,Data}|T], Expected_return, Qb_before) ->
Qb_in_driver = bytes_queued(Port),
case Qb_before + Size of
- Qb_in_driver -> ok;
- Sum ->
- io:format("Qb_before: ~p\n"
- "Qb_before+Size: ~p\n"
- "Qb_in_driver: ~p",
- [Qb_before,Sum,Qb_in_driver]),
- ?t:fail()
+ Qb_in_driver -> ok;
+ Sum ->
+ ct:fail("Qb_before: ~p\n"
+ "Qb_before+Size: ~p\n"
+ "Qb_in_driver: ~p",
+ [Qb_before,Sum,Qb_in_driver])
end,
X_return = case Method of
- ?ENQ -> list_to_binary([Expected_return,Data]);
- ?PUSHQ -> list_to_binary([Data,Expected_return]);
- ?PUSHQ_BIN -> list_to_binary([Data,Expected_return]);
- ?ENQ_BIN -> list_to_binary([Expected_return,Data]);
- ?PUSHQV -> list_to_binary([Data,Expected_return]);
- ?ENQV -> list_to_binary([Expected_return,Data])
- end,
+ ?ENQ -> list_to_binary([Expected_return,Data]);
+ ?PUSHQ -> list_to_binary([Data,Expected_return]);
+ ?PUSHQ_BIN -> list_to_binary([Data,Expected_return]);
+ ?ENQ_BIN -> list_to_binary([Expected_return,Data]);
+ ?PUSHQV -> list_to_binary([Data,Expected_return]);
+ ?ENQV -> list_to_binary([Expected_return,Data])
+ end,
feed_driver(Port, T, X_return, Qb_before + Size).
%% method_name(0) -> pushq;
@@ -676,26 +663,22 @@ compare_return(Port, _Data_list, 0, _Back_len) ->
0 = bytes_queued(Port);
compare_return(Port, QueuedInPort0, Len_to_get, DeqSize) ->
case bytes_queued(Port) of
- Len_to_get -> ok;
- BytesInQueue ->
- io:format("Len_to_get: ~p", [Len_to_get]),
- io:format("Bytes in queue: ~p", [BytesInQueue]),
- ?line test_server:fail()
+ Len_to_get -> ok;
+ BytesInQueue ->
+ ct:fail("Len_to_get: ~p\nBytes in queue: ~p", [Len_to_get,BytesInQueue])
end,
BytesToDequeue = if (DeqSize > Len_to_get) -> Len_to_get;
- true -> DeqSize
- end,
+ true -> DeqSize
+ end,
Dequeued = read_head(Port, BytesToDequeue),
case bin_prefix(Dequeued, QueuedInPort0) of
- true ->
- deq(Port, BytesToDequeue),
- <<_:BytesToDequeue/binary,QueuedInPort/binary>> = QueuedInPort0,
- compare_return(Port, QueuedInPort, Len_to_get - BytesToDequeue, DeqSize);
- false ->
- io:format("Bytes to dequeue: ~p", [BytesToDequeue]),
- io:format("Dequeued: ~p", [Dequeued]),
- io:format("Queued in port: ~P", [QueuedInPort0,12]),
- ?t:fail()
+ true ->
+ deq(Port, BytesToDequeue),
+ <<_:BytesToDequeue/binary,QueuedInPort/binary>> = QueuedInPort0,
+ compare_return(Port, QueuedInPort, Len_to_get - BytesToDequeue, DeqSize);
+ false ->
+ ct:fail("Bytes to dequeue: ~p\nDequeued: ~p\nQueued in port: ~P",
+ [BytesToDequeue, Dequeued, QueuedInPort0,12])
end.
%% bin_prefix(PrefixBinary, Binary)
@@ -713,8 +696,8 @@ queue_op(Port, Method, Data) ->
bytes_queued(Port) ->
case erlang:port_control(Port, ?BYTES_QUEUED, []) of
- <<I:32>> -> I;
- Bad -> ?t:fail({bad_result,Bad})
+ <<I:32>> -> I;
+ Bad -> ct:fail({bad_result,Bad})
end.
deq(Port, Size) ->
@@ -724,83 +707,77 @@ read_head(Port, Size) ->
erlang:port_control(Port, ?READ_HEAD, <<Size:32>>).
-driver_unloaded(doc) ->
- [];
-driver_unloaded(suite) ->
- [];
driver_unloaded(Config) when is_list(Config) ->
- ?line process_flag(trap_exit, true),
- ?line Drv = timer_drv,
- ?line User = self(),
- ?line Loaded = make_ref(),
- ?line Die = make_ref(),
- ?line Loader = spawn(fun () ->
- erl_ddll:start(),
- ok = load_driver(?config(data_dir,
- Config),
- Drv),
- User ! Loaded,
- receive Die -> exit(bye) end
- end),
- ?line receive Loaded -> ok end,
- ?line Port = open_port({spawn, Drv}, []),
- ?line Loader ! Die,
- ?line receive
- {'EXIT', Port, Reason} ->
- ?line driver_unloaded = Reason
- %% Reason used to be -1
- end.
-
-
-io_ready_exit(doc) -> [];
-io_ready_exit(suite) -> [];
+ process_flag(trap_exit, true),
+ Drv = timer_drv,
+ User = self(),
+ Loaded = make_ref(),
+ Die = make_ref(),
+ Loader = spawn(fun () ->
+ erl_ddll:start(),
+ ok = load_driver(proplists:get_value(data_dir,
+ Config),
+ Drv),
+ User ! Loaded,
+ receive Die -> exit(bye) end
+ end),
+ receive Loaded -> ok end,
+ Port = open_port({spawn, Drv}, []),
+ Loader ! Die,
+ receive
+ {'EXIT', Port, Reason} ->
+ driver_unloaded = Reason
+ %% Reason used to be -1
+ end.
+
+
io_ready_exit(Config) when is_list(Config) ->
- ?line OTE = process_flag(trap_exit, true),
- ?line Test = self(),
- ?line Dgawd = spawn(fun () ->
- ok = dgawd_handler:install(),
- Mon = erlang:monitor(process, Test),
- Test ! dgawd_handler_started,
- receive
- {'DOWN', Mon, _, _, _} -> ok;
- stop_dgawd_handler -> ok
- end,
- dgawd_handler:restore(),
- Test ! dgawd_handler_stopped
- end),
- ?line receive dgawd_handler_started -> ok end,
- ?line Drv = io_ready_exit_drv,
- ?line erl_ddll:start(),
- ?line ok = load_driver(?config(data_dir, Config), Drv),
- ?line Port = open_port({spawn, Drv}, []),
- ?line case erlang:port_control(Port, 0, "") of
- "ok" ->
- receive
- {'EXIT', Port, Reason} ->
- ?line case Reason of
- ready_output_driver_failure ->
- ?t:format("Exited in output_ready()~n"),
- ?line ok;
- ready_input_driver_failure ->
- ?t:format("Exited in input_ready()~n"),
- ?line ok;
- Error -> ?line ?t:fail(Error)
- end
- end,
- receive after 2000 -> ok end,
- ?line false = dgawd_handler:got_dgawd_report(),
- ?line Dgawd ! stop_dgawd_handler,
- ?line receive dgawd_handler_stopped -> ok end,
- ?line process_flag(trap_exit, OTE),
- ?line ok;
- "nyiftos" ->
- ?line process_flag(trap_exit, OTE),
- ?line {skipped, "Not yet implemented for this OS"};
- Error ->
- ?line process_flag(trap_exit, OTE),
- ?line ?t:fail({unexpected_control_result, Error})
- end.
-
+ OTE = process_flag(trap_exit, true),
+ Test = self(),
+ Dgawd = spawn(fun () ->
+ ok = dgawd_handler:install(),
+ Mon = erlang:monitor(process, Test),
+ Test ! dgawd_handler_started,
+ receive
+ {'DOWN', Mon, _, _, _} -> ok;
+ stop_dgawd_handler -> ok
+ end,
+ dgawd_handler:restore(),
+ Test ! dgawd_handler_stopped
+ end),
+ receive dgawd_handler_started -> ok end,
+ Drv = io_ready_exit_drv,
+ erl_ddll:start(),
+ ok = load_driver(proplists:get_value(data_dir, Config), Drv),
+ Port = open_port({spawn, Drv}, []),
+ case erlang:port_control(Port, 0, "") of
+ "ok" ->
+ receive
+ {'EXIT', Port, Reason} ->
+ case Reason of
+ ready_output_driver_failure ->
+ io:format("Exited in output_ready()~n"),
+ ok;
+ ready_input_driver_failure ->
+ io:format("Exited in input_ready()~n"),
+ ok;
+ Error -> ct:fail(Error)
+ end
+ end,
+ receive after 2000 -> ok end,
+ false = dgawd_handler:got_dgawd_report(),
+ Dgawd ! stop_dgawd_handler,
+ receive dgawd_handler_stopped -> ok end,
+ process_flag(trap_exit, OTE),
+ ok;
+ "nyiftos" ->
+ process_flag(trap_exit, OTE),
+ {skipped, "Not yet implemented for this OS"};
+ Error ->
+ process_flag(trap_exit, OTE),
+ ct:fail({unexpected_control_result, Error})
+ end.
+
-define(CHKIO_STOP, 0).
-define(CHKIO_USE_FALLBACK_POLLSET, 1).
@@ -812,138 +789,128 @@ io_ready_exit(Config) when is_list(Config) ->
-define(CHKIO_SMP_SELECT, 7).
-define(CHKIO_DRV_USE, 8).
-use_fallback_pollset(doc) -> [];
-use_fallback_pollset(suite) -> [];
use_fallback_pollset(Config) when is_list(Config) ->
FlbkFun = fun () ->
- ChkIoDuring = erlang:system_info(check_io),
- case lists:keysearch(fallback_poll_set_size,
- 1,
- ChkIoDuring) of
- {value,
- {fallback_poll_set_size, N}} when N > 0 ->
- ?line ok;
- Error ->
- ?line ?t:fail({failed_to_use_fallback, Error})
- end
- end,
- ?line {BckupTest, Handel, OkRes}
- = case chkio_test_init(Config) of
- {erts_poll_info, ChkIo} = Hndl ->
- case lists:keysearch(fallback, 1, ChkIo) of
- {value, {fallback, B}} when B =/= false ->
- ?line {FlbkFun, Hndl, ok};
- _ ->
- ?line {fun () -> ok end,
- Hndl,
- {comment,
- "This implementation does not use "
- "a fallback pollset"}}
- end;
- Skip ->
- {fun () -> ok end, Skip, ok}
- end,
- ?line case chkio_test_fini(chkio_test(Handel,
- ?CHKIO_USE_FALLBACK_POLLSET,
- fun () ->
- ?line sleep(1000),
- ?line BckupTest()
- end)) of
- {skipped, _} = Res -> ?line Res;
- _ -> ?line OkRes
- end.
-
-bad_fd_in_pollset(doc) -> [];
-bad_fd_in_pollset(suite) -> [];
+ ChkIoDuring = erlang:system_info(check_io),
+ case lists:keysearch(fallback_poll_set_size,
+ 1,
+ ChkIoDuring) of
+ {value,
+ {fallback_poll_set_size, N}} when N > 0 ->
+ ok;
+ Error ->
+ ct:fail({failed_to_use_fallback, Error})
+ end
+ end,
+ {BckupTest, Handel, OkRes}
+ = case chkio_test_init(Config) of
+ {erts_poll_info, ChkIo} = Hndl ->
+ case lists:keysearch(fallback, 1, ChkIo) of
+ {value, {fallback, B}} when B =/= false ->
+ {FlbkFun, Hndl, ok};
+ _ ->
+ {fun () -> ok end,
+ Hndl,
+ {comment,
+ "This implementation does not use "
+ "a fallback pollset"}}
+ end;
+ Skip ->
+ {fun () -> ok end, Skip, ok}
+ end,
+ case chkio_test_fini(chkio_test(Handel,
+ ?CHKIO_USE_FALLBACK_POLLSET,
+ fun () ->
+ sleep(1000),
+ BckupTest()
+ end)) of
+ {skipped, _} = Res -> Res;
+ _ -> OkRes
+ end.
+
bad_fd_in_pollset(Config) when is_list(Config) ->
- ?line chkio_test_fini(chkio_test(chkio_test_init(Config),
- ?CHKIO_BAD_FD_IN_POLLSET,
- fun () -> ?line sleep(1000) end)).
+ chkio_test_fini(chkio_test(chkio_test_init(Config),
+ ?CHKIO_BAD_FD_IN_POLLSET,
+ fun () -> sleep(1000) end)).
-driver_event(doc) -> [];
-driver_event(suite) -> [];
driver_event(Config) when is_list(Config) ->
- ?line chkio_test_fini(chkio_test(chkio_test_init(Config),
- ?CHKIO_DRIVER_EVENT,
- fun () -> ?line sleep(1000) end)).
+ chkio_test_fini(chkio_test(chkio_test_init(Config),
+ ?CHKIO_DRIVER_EVENT,
+ fun () -> sleep(1000) end)).
-fd_change(doc) -> [];
-fd_change(suite) -> [];
fd_change(Config) when is_list(Config) ->
- ?line chkio_test_fini(chkio_test(chkio_test_init(Config),
- ?CHKIO_FD_CHANGE,
- fun () -> ?line sleep(1000) end)).
+ chkio_test_fini(chkio_test(chkio_test_init(Config),
+ ?CHKIO_FD_CHANGE,
+ fun () -> sleep(1000) end)).
-steal_control(doc) -> [];
-steal_control(suite) -> [];
steal_control(Config) when is_list(Config) ->
- ?line chkio_test_fini(case chkio_test_init(Config) of
- {erts_poll_info, _} = Hndl ->
- ?line steal_control_test(Hndl);
- Skip ->
- ?line Skip
- end).
+ chkio_test_fini(case chkio_test_init(Config) of
+ {erts_poll_info, _} = Hndl ->
+ steal_control_test(Hndl);
+ Skip ->
+ Skip
+ end).
steal_control_test(Hndl = {erts_poll_info, Before}) ->
- ?line Port = open_chkio_port(),
- ?line case erlang:port_control(Port, ?CHKIO_STEAL_AUX, "") of
- [$f,$d,$s,$:| _] = FdList ->
- ?line chk_chkio_port(Port),
- sleep(500),
- ?line chk_chkio_port(Port),
- ?line Res = chkio_test(Hndl,
- ?CHKIO_STEAL,
- FdList,
- fun () ->
- ?line chk_chkio_port(Port),
- ?line sleep(500),
- ?line chk_chkio_port(Port)
- end),
- ?line case erlang:port_control(Port, ?CHKIO_STOP, "") of
- "ok" ->
- ?line chk_chkio_port(Port),
- ?line ok;
- StopErr ->
- ?line chk_chkio_port(Port),
- ?line ?t:fail({stop_error, StopErr})
- end,
- ?line close_chkio_port(Port),
- ?line Res;
- [$s,$k,$i,$p,$:,$\ |Skip] ->
- ?line chk_chkio_port(Port),
- ?line close_chkio_port(Port),
- {chkio_test_result,
- {skipped, Skip},
- Before};
- StartErr ->
- ?line chk_chkio_port(Port),
- ?line ?t:fail({start_error, StartErr})
- end.
+ Port = open_chkio_port(),
+ case erlang:port_control(Port, ?CHKIO_STEAL_AUX, "") of
+ [$f,$d,$s,$:| _] = FdList ->
+ chk_chkio_port(Port),
+ sleep(500),
+ chk_chkio_port(Port),
+ Res = chkio_test(Hndl,
+ ?CHKIO_STEAL,
+ FdList,
+ fun () ->
+ chk_chkio_port(Port),
+ sleep(500),
+ chk_chkio_port(Port)
+ end),
+ case erlang:port_control(Port, ?CHKIO_STOP, "") of
+ "ok" ->
+ chk_chkio_port(Port),
+ ok;
+ StopErr ->
+ chk_chkio_port(Port),
+ ct:fail({stop_error, StopErr})
+ end,
+ close_chkio_port(Port),
+ Res;
+ [$s,$k,$i,$p,$:,$\ |Skip] ->
+ chk_chkio_port(Port),
+ close_chkio_port(Port),
+ {chkio_test_result,
+ {skipped, Skip},
+ Before};
+ StartErr ->
+ chk_chkio_port(Port),
+ ct:fail({start_error, StartErr})
+ end.
chkio_test_init(Config) when is_list(Config) ->
- ?line ChkIo = get_stable_check_io_info(),
- ?line case catch lists:keysearch(name, 1, ChkIo) of
- {value, {name, erts_poll}} ->
- ?line ?t:format("Before test: ~p~n", [ChkIo]),
- ?line Path = ?config(data_dir, Config),
- ?line erl_ddll:start(),
- ?line ok = load_driver(Path, 'chkio_drv'),
- ?line process_flag(trap_exit, true),
- ?line {erts_poll_info, ChkIo};
- _ ->
- ?line {skipped, "Test written to test erts_poll() which isn't used"}
- end.
-
+ ChkIo = get_stable_check_io_info(),
+ case catch lists:keysearch(name, 1, ChkIo) of
+ {value, {name, erts_poll}} ->
+ io:format("Before test: ~p~n", [ChkIo]),
+ Path = proplists:get_value(data_dir, Config),
+ erl_ddll:start(),
+ ok = load_driver(Path, 'chkio_drv'),
+ process_flag(trap_exit, true),
+ {erts_poll_info, ChkIo};
+ _ ->
+ {skipped, "Test written to test erts_poll() which isn't used"}
+ end.
+
chkio_test_fini({skipped, _} = Res) ->
Res;
chkio_test_fini({chkio_test_result, Res, Before}) ->
- ?line ok = erl_ddll:unload_driver('chkio_drv'),
- ?line ok = erl_ddll:stop(),
- ?line After = get_stable_check_io_info(),
- ?line ?t:format("After test: ~p~n", [After]),
- ?line verify_chkio_state(Before, After),
- ?line Res.
+ ok = erl_ddll:unload_driver('chkio_drv'),
+ ok = erl_ddll:stop(),
+ After = get_stable_check_io_info(),
+ io:format("After test: ~p~n", [After]),
+ verify_chkio_state(Before, After),
+ Res.
open_chkio_port() ->
open_port({spawn, 'chkio_drv'}, []).
@@ -951,269 +918,255 @@ open_chkio_port() ->
close_chkio_port(Port) when is_port(Port) ->
true = erlang:port_close(Port),
receive
- {'EXIT', Port, normal} ->
- ok;
- {'EXIT', Port, Reason} ->
- ?t:fail({abnormal_port_exit, Port, Reason});
- {Port, Message} ->
- ?t:fail({strange_message_from_port, Message})
+ {'EXIT', Port, normal} ->
+ ok;
+ {'EXIT', Port, Reason} ->
+ ct:fail({abnormal_port_exit, Port, Reason});
+ {Port, Message} ->
+ ct:fail({strange_message_from_port, Message})
end.
chk_chkio_port(Port) ->
receive
- {'EXIT', Port, Reason} when Reason /= normal ->
- ?t:fail({port_exited, Port, Reason})
+ {'EXIT', Port, Reason} when Reason /= normal ->
+ ct:fail({port_exited, Port, Reason})
after 0 ->
- ok
+ ok
end.
-
+
chkio_test({skipped, _} = Res, _Test, _Fun) ->
- ?line Res;
+ Res;
chkio_test({erts_poll_info, _Before} = EPI, Test, Fun) when is_integer(Test) ->
chkio_test(EPI, Test, "", Fun).
chkio_test({skipped, _} = Res, _Test, _TestArgs, _Fun) ->
- ?line Res;
+ Res;
chkio_test({erts_poll_info, Before},
- Test,
- TestArgs,
- Fun) when is_integer(Test),
- is_list(TestArgs) ->
- ?line Port = open_chkio_port(),
- ?line case erlang:port_control(Port, Test, TestArgs) of
- "ok" ->
- ?line chk_chkio_port(Port),
- ?line Fun(),
- ?line During = erlang:system_info(check_io),
- ?line erlang:display(During),
- ?line 0 = element(1, erts_debug:get_internal_state(check_io_debug)),
- ?line ?t:format("During test: ~p~n", [During]),
- ?line chk_chkio_port(Port),
- ?line case erlang:port_control(Port, ?CHKIO_STOP, "") of
- Res when is_list(Res) ->
- ?line chk_chkio_port(Port),
- ?line ?t:format("~s", [Res]),
- ?line close_chkio_port(Port),
- ?line Res,
- ?line case Res of
- [$c,$o,$m,$m,$e,$n,$t,$:,$\ |Cmnt] ->
- ?line {chkio_test_result,
- {comment, Cmnt},
- Before};
- _ ->
- ?line {chkio_test_result,
- Res,
- Before}
- end;
- StopErr ->
- ?line chk_chkio_port(Port),
- ?line ?t:fail({stop_error, StopErr})
- end;
- [$s,$k,$i,$p,$:,$\ |Skip] ->
- ?line chk_chkio_port(Port),
- ?line close_chkio_port(Port),
- {chkio_test_result,
- {skipped, Skip},
- Before};
- StartErr ->
- ?line chk_chkio_port(Port),
- ?line ?t:fail({start_error, StartErr})
- end.
+ Test,
+ TestArgs,
+ Fun) when is_integer(Test),
+ is_list(TestArgs) ->
+ Port = open_chkio_port(),
+ case erlang:port_control(Port, Test, TestArgs) of
+ "ok" ->
+ chk_chkio_port(Port),
+ Fun(),
+ During = erlang:system_info(check_io),
+ erlang:display(During),
+ 0 = element(1, erts_debug:get_internal_state(check_io_debug)),
+ io:format("During test: ~p~n", [During]),
+ chk_chkio_port(Port),
+ case erlang:port_control(Port, ?CHKIO_STOP, "") of
+ Res when is_list(Res) ->
+ chk_chkio_port(Port),
+ io:format("~s", [Res]),
+ close_chkio_port(Port),
+ Res,
+ case Res of
+ [$c,$o,$m,$m,$e,$n,$t,$:,$\ |Cmnt] ->
+ {chkio_test_result,
+ {comment, Cmnt},
+ Before};
+ _ ->
+ {chkio_test_result,
+ Res,
+ Before}
+ end;
+ StopErr ->
+ chk_chkio_port(Port),
+ ct:fail({stop_error, StopErr})
+ end;
+ [$s,$k,$i,$p,$:,$\ |Skip] ->
+ chk_chkio_port(Port),
+ close_chkio_port(Port),
+ {chkio_test_result,
+ {skipped, Skip},
+ Before};
+ StartErr ->
+ chk_chkio_port(Port),
+ ct:fail({start_error, StartErr})
+ end.
verify_chkio_state(Before, After) ->
- ?line TotSetSize = lists:keysearch(total_poll_set_size, 1, Before),
- ?line TotSetSize = lists:keysearch(total_poll_set_size, 1, After),
- ?line case lists:keysearch(fallback, 1, Before) of
- {value,{fallback,false}} ->
- ?line ok;
- _ ->
- ?line BckupSetSize = lists:keysearch(fallback_poll_set_size,
- 1,
- Before),
- ?line BckupSetSize = lists:keysearch(fallback_poll_set_size,
- 1,
- After)
- end,
- ?line ok.
+ TotSetSize = lists:keysearch(total_poll_set_size, 1, Before),
+ TotSetSize = lists:keysearch(total_poll_set_size, 1, After),
+ case lists:keysearch(fallback, 1, Before) of
+ {value,{fallback,false}} ->
+ ok;
+ _ ->
+ BckupSetSize = lists:keysearch(fallback_poll_set_size,
+ 1,
+ Before),
+ BckupSetSize = lists:keysearch(fallback_poll_set_size,
+ 1,
+ After)
+ end,
+ ok.
get_stable_check_io_info() ->
ChkIo = erlang:system_info(check_io),
PendUpdNo = case lists:keysearch(pending_updates, 1, ChkIo) of
- {value, {pending_updates, PendNo}} ->
- PendNo;
- false ->
- 0
- end,
+ {value, {pending_updates, PendNo}} ->
+ PendNo;
+ false ->
+ 0
+ end,
{value, {active_fds, ActFds}} = lists:keysearch(active_fds, 1, ChkIo),
case {PendUpdNo, ActFds} of
- {0, 0} ->
- ChkIo;
- _ ->
- receive after 10 -> ok end,
- get_stable_check_io_info()
+ {0, 0} ->
+ ChkIo;
+ _ ->
+ receive after 10 -> ok end,
+ get_stable_check_io_info()
end.
-otp_6602(doc) -> ["Missed port lock when stealing control of fd from a "
- "driver that didn't use the same lock. The lock checker "
- "used to trigger on this and dump core."];
-otp_6602(suite) ->
- [];
+%% Missed port lock when stealing control of fd from a
+%% driver that didn't use the same lock. The lock checker
+%% used to trigger on this and dump core.
otp_6602(Config) when is_list(Config) ->
- ?line {ok, Node} = start_node(Config),
- ?line Done = make_ref(),
- ?line Parent = self(),
- ?line Tester = spawn_link(Node,
- fun () ->
- %% Inet driver use port locking...
- {ok, S} = gen_udp:open(0),
- {ok, Fd} = inet:getfd(S),
- %% Steal fd (lock checker used to
- %% trigger here).
- {ok, _S2} = gen_udp:open(0,[{fd,Fd}]),
- Parent ! Done
- end),
- ?line receive Done -> ok end,
- ?line unlink(Tester),
- ?line stop_node(Node),
- ?line ok.
+ {ok, Node} = start_node(Config),
+ Done = make_ref(),
+ Parent = self(),
+ Tester = spawn_link(Node,
+ fun () ->
+ %% Inet driver use port locking...
+ {ok, S} = gen_udp:open(0),
+ {ok, Fd} = inet:getfd(S),
+ %% Steal fd (lock checker used to
+ %% trigger here).
+ {ok, _S2} = gen_udp:open(0,[{fd,Fd}]),
+ Parent ! Done
+ end),
+ receive Done -> ok end,
+ unlink(Tester),
+ stop_node(Node),
+ ok.
-define(EXPECTED_SYSTEM_INFO_NAMES1,
- ["drv_drv_vsn",
- "emu_drv_vsn",
- "erts_vsn",
- "otp_vsn",
- "thread",
- "smp"]).
+ ["drv_drv_vsn",
+ "emu_drv_vsn",
+ "erts_vsn",
+ "otp_vsn",
+ "thread",
+ "smp"]).
-define(EXPECTED_SYSTEM_INFO_NAMES2,
- (?EXPECTED_SYSTEM_INFO_NAMES1 ++
- ["async_thrs",
- "sched_thrs"])).
+ (?EXPECTED_SYSTEM_INFO_NAMES1 ++
+ ["async_thrs",
+ "sched_thrs"])).
-define(EXPECTED_SYSTEM_INFO_NAMES3,
- (?EXPECTED_SYSTEM_INFO_NAMES2 ++
- ["emu_nif_vsn"])).
+ (?EXPECTED_SYSTEM_INFO_NAMES2 ++
+ ["emu_nif_vsn"])).
-define(EXPECTED_SYSTEM_INFO_NAMES4,
- (?EXPECTED_SYSTEM_INFO_NAMES3 ++
- ["dirty_sched"])).
+ (?EXPECTED_SYSTEM_INFO_NAMES3 ++
+ ["dirty_sched"])).
-define(EXPECTED_SYSTEM_INFO_NAMES, ?EXPECTED_SYSTEM_INFO_NAMES4).
-'driver_system_info_base_ver'(doc) ->
- [];
-'driver_system_info_base_ver'(suite) ->
- [];
'driver_system_info_base_ver'(Config) when is_list(Config) ->
- ?line driver_system_info_test(Config, sys_info_base_drv).
+ driver_system_info_test(Config, sys_info_base_drv).
-'driver_system_info_prev_ver'(doc) ->
- [];
-'driver_system_info_prev_ver'(suite) ->
- [];
'driver_system_info_prev_ver'(Config) when is_list(Config) ->
- ?line driver_system_info_test(Config, sys_info_prev_drv).
+ driver_system_info_test(Config, sys_info_prev_drv).
-driver_system_info_current_ver(doc) ->
- [];
-driver_system_info_current_ver(suite) ->
- [];
driver_system_info_current_ver(Config) when is_list(Config) ->
- ?line driver_system_info_test(Config, sys_info_curr_drv).
+ driver_system_info_test(Config, sys_info_curr_drv).
driver_system_info_test(Config, Name) ->
- ?line Port = start_driver(Config, Name, false),
- ?line case erlang:port_control(Port, 0, []) of
- [$o,$k,$:,_ | Result] ->
- ?line check_driver_system_info_result(Result);
- [$e,$r,$r,$o,$r,$:,_ | Error] ->
- ?line ?t:fail(Error);
- Unexpected ->
- ?line ?t:fail({unexpected_result, Unexpected})
- end,
- ?line stop_driver(Port, Name),
- ?line ok.
+ Port = start_driver(Config, Name, false),
+ case erlang:port_control(Port, 0, []) of
+ [$o,$k,$:,_ | Result] ->
+ check_driver_system_info_result(Result);
+ [$e,$r,$r,$o,$r,$:,_ | Error] ->
+ ct:fail(Error);
+ Unexpected ->
+ ct:fail({unexpected_result, Unexpected})
+ end,
+ stop_driver(Port, Name),
+ ok.
check_driver_system_info_result(Result) ->
- ?line ?t:format("All names: ~p~n", [?EXPECTED_SYSTEM_INFO_NAMES]),
- ?line ?t:format("Result: ~p~n", [Result]),
- ?line {[], Ns, DDVSN} = chk_sis(lists:map(fun (Str) ->
- string:tokens(Str, "=")
- end,
- string:tokens(Result, " ")),
- ?EXPECTED_SYSTEM_INFO_NAMES),
- ?line case {DDVSN,
- drv_vsn_str2tup(erlang:system_info(driver_version))} of
- {DDVSN, DDVSN} ->
- ?line [] = Ns;
- %% {{1, 0}, _} ->
- %% ?line ExpNs = lists:sort(?EXPECTED_SYSTEM_INFO_NAMES
- %% -- ?EXPECTED_SYSTEM_INFO_NAMES1),
- %% ?line ExpNs = lists:sort(Ns);
- %% {{1, 1}, _} ->
- %% ?line ExpNs = lists:sort(?EXPECTED_SYSTEM_INFO_NAMES
- %% -- ?EXPECTED_SYSTEM_INFO_NAMES2),
- %% ?line ExpNs = lists:sort(Ns);
- {{3, 0}, _} ->
- ?line ExpNs = lists:sort(?EXPECTED_SYSTEM_INFO_NAMES
- -- ?EXPECTED_SYSTEM_INFO_NAMES3),
- ?line ExpNs = lists:sort(Ns)
- end.
+ io:format("All names: ~p~n", [?EXPECTED_SYSTEM_INFO_NAMES]),
+ io:format("Result: ~p~n", [Result]),
+ {[], Ns, DDVSN} = chk_sis(lists:map(fun (Str) ->
+ string:tokens(Str, "=")
+ end,
+ string:tokens(Result, " ")),
+ ?EXPECTED_SYSTEM_INFO_NAMES),
+ case {DDVSN,
+ drv_vsn_str2tup(erlang:system_info(driver_version))} of
+ {DDVSN, DDVSN} ->
+ [] = Ns;
+ %% {{1, 0}, _} ->
+ %% ExpNs = lists:sort(?EXPECTED_SYSTEM_INFO_NAMES
+ %% -- ?EXPECTED_SYSTEM_INFO_NAMES1),
+ %% ExpNs = lists:sort(Ns);
+ %% {{1, 1}, _} ->
+ %% ExpNs = lists:sort(?EXPECTED_SYSTEM_INFO_NAMES
+ %% -- ?EXPECTED_SYSTEM_INFO_NAMES2),
+ %% ExpNs = lists:sort(Ns);
+ {{3, 0}, _} ->
+ ExpNs = lists:sort(?EXPECTED_SYSTEM_INFO_NAMES
+ -- ?EXPECTED_SYSTEM_INFO_NAMES3),
+ ExpNs = lists:sort(Ns)
+ end.
chk_sis(SIs, Ns) ->
chk_sis(SIs, Ns, unknown).
chk_sis(SIs, [], DDVSN) ->
- ?line {SIs, [], DDVSN};
+ {SIs, [], DDVSN};
chk_sis([], Ns, DDVSN) ->
- ?line {[], Ns, DDVSN};
+ {[], Ns, DDVSN};
chk_sis([[N, _] = SI| SIs], Ns, DDVSN) ->
- ?line true = lists:member(N, Ns),
- ?line case check_si_res(SI) of
- {driver_version, NewDDVSN} ->
- ?line chk_sis(SIs, lists:delete(N, Ns), NewDDVSN);
- _ ->
- ?line chk_sis(SIs, lists:delete(N, Ns), DDVSN)
- end.
+ true = lists:member(N, Ns),
+ case check_si_res(SI) of
+ {driver_version, NewDDVSN} ->
+ chk_sis(SIs, lists:delete(N, Ns), NewDDVSN);
+ _ ->
+ chk_sis(SIs, lists:delete(N, Ns), DDVSN)
+ end.
%% Data in first version of driver_system_info() (driver version 1.0)
check_si_res(["drv_drv_vsn", Value]) ->
- ?line DDVSN = drv_vsn_str2tup(Value),
- ?line {Major, DMinor} = DDVSN,
- ?line {Major, EMinor} = drv_vsn_str2tup(erlang:system_info(driver_version)),
- ?line true = DMinor =< EMinor,
- ?line {driver_version, DDVSN};
+ DDVSN = drv_vsn_str2tup(Value),
+ {Major, DMinor} = DDVSN,
+ {Major, EMinor} = drv_vsn_str2tup(erlang:system_info(driver_version)),
+ true = DMinor =< EMinor,
+ {driver_version, DDVSN};
check_si_res(["emu_drv_vsn", Value]) ->
- ?line Value = erlang:system_info(driver_version);
+ Value = erlang:system_info(driver_version);
check_si_res(["erts_vsn", Value]) ->
- ?line Value = erlang:system_info(version);
+ Value = erlang:system_info(version);
check_si_res(["otp_vsn", Value]) ->
- ?line Value = erlang:system_info(otp_release);
+ Value = erlang:system_info(otp_release);
check_si_res(["thread", "true"]) ->
- ?line true = erlang:system_info(threads);
+ true = erlang:system_info(threads);
check_si_res(["thread", "false"]) ->
- ?line false = erlang:system_info(threads);
+ false = erlang:system_info(threads);
check_si_res(["smp", "true"]) ->
- ?line true = erlang:system_info(smp_support);
+ true = erlang:system_info(smp_support);
check_si_res(["smp", "false"]) ->
- ?line false = erlang:system_info(smp_support);
+ false = erlang:system_info(smp_support);
%% Data added in second version of driver_system_info() (driver version 1.1)
check_si_res(["async_thrs", Value]) ->
- ?line Value = integer_to_list(erlang:system_info(thread_pool_size));
+ Value = integer_to_list(erlang:system_info(thread_pool_size));
check_si_res(["sched_thrs", Value]) ->
- ?line Value = integer_to_list(erlang:system_info(schedulers));
+ Value = integer_to_list(erlang:system_info(schedulers));
%% Data added in 3rd version of driver_system_info() (driver version 1.5)
check_si_res(["emu_nif_vsn", Value]) ->
- ?line Value = erlang:system_info(nif_version);
+ Value = erlang:system_info(nif_version);
%% Data added in 4th version of driver_system_info() (driver version 3.1)
check_si_res(["dirty_sched", _Value]) ->
true;
check_si_res(Unexpected) ->
- ?line ?t:fail({unexpected_result, Unexpected}).
+ ct:fail({unexpected_result, Unexpected}).
-define(MON_OP_I_AM_IPID,1).
-define(MON_OP_MONITOR_ME,2).
@@ -1221,171 +1174,168 @@ check_si_res(Unexpected) ->
-define(MON_OP_MONITOR_ME_LATER,4).
-define(MON_OP_DO_DELAYED_MONITOR,5).
-driver_monitor(suite) ->
- [];
-driver_monitor(doc) ->
- ["Test monitoring of processes from drivers"];
+%% Test monitoring of processes from drivers
driver_monitor(Config) when is_list(Config) ->
- ?line Name = monitor_drv,
- ?line Port = start_driver(Config, Name, false),
- ?line "ok" = port_control(Port,?MON_OP_I_AM_IPID,[]),
- ?line "ok" = port_control(Port,?MON_OP_MONITOR_ME,[]),
- ?line "ok" = port_control(Port,?MON_OP_DEMONITOR_ME,[]),
- ?line {monitors, []} = erlang:port_info(Port,monitors),
-
- ?line "ok:"++Id1 = port_control(Port,?MON_OP_MONITOR_ME_LATER,[]),
- ?line {monitored_by, []} = process_info(self(),monitored_by),
- ?line "ok" = port_control(Port,?MON_OP_DO_DELAYED_MONITOR,Id1),
- ?line {monitored_by, [Port]} = process_info(self(),monitored_by),
- ?line "ok" = port_control(Port,?MON_OP_DEMONITOR_ME,[]),
- ?line {monitored_by, []} = process_info(self(),monitored_by),
-
- ?line "ok" = port_control(Port,?MON_OP_MONITOR_ME,[]),
- ?line Me = self(),
- ?line {Pid1,Ref1} =
- spawn_monitor(fun() ->
- Me ! port_control(Port,?MON_OP_MONITOR_ME,[]),
- Me ! process_info(self(),monitored_by),
- Me ! erlang:port_info(Port,monitors)
- end),
- ?line ok = receive
- "ok" ->
- ok
- after 1000 ->
- timeout
- end,
- ?line ok = receive
- {monitored_by, L} ->
- L2 = lists:sort(L),
- L3 = lists:sort([Me,Port]),
- case L2 of
- L3 ->
- ok;
- _ ->
- mismatch
- end
- after 1000 ->
- timeout
- end,
- ?line ok = receive
- {monitors, LL} ->
- LL2 = lists:sort(LL),
- LL3 = lists:sort([{process,Me},{process,Pid1}]),
- case LL2 of
- LL3 ->
- ok;
- _ ->
- mismatch
- end
- after 1000 ->
- timeout
- end,
- ?line ok = receive
- {'DOWN', Ref1, process, Pid1, _} ->
- ok
- after 1000 ->
- timeout
- end,
- ?line ok = receive
- {monitor_fired,Port,Pid1} ->
- ok
- after 1000 ->
- timeout
- end,
- ?line "ok" = port_control(Port,?MON_OP_DEMONITOR_ME,[]),
- ?line {monitors,[]} = erlang:port_info(Port,monitors),
- ?line {monitored_by, []} = process_info(self(),monitored_by),
-
- ?line "ok" = port_control(Port,?MON_OP_MONITOR_ME,[]),
- ?line {Pid2,Ref2} =
- spawn_monitor(fun() ->
- receive go -> ok end,
- Me ! port_control(Port,?MON_OP_MONITOR_ME_LATER,[]),
- Me ! process_info(self(),monitored_by),
- Me ! erlang:port_info(Port,monitors)
- end),
- ?line Pid2 ! go,
- ?line {ok,Id2} = receive
- "ok:"++II ->
- {ok,II}
- after 1000 ->
- timeout
- end,
- ?line ok = receive
- {monitored_by, [Me]} ->
- ok
- after 1000 ->
- timeout
- end,
- ?line ok = receive
- {monitors, [{process,Me}]} ->
- ok
- after 1000 ->
- timeout
- end,
- ?line ok = receive
- {'DOWN', Ref2, process, Pid2, _} ->
- ok
- after 1000 ->
- timeout
- end,
- ?line "noproc" = port_control(Port,?MON_OP_DO_DELAYED_MONITOR,Id2),
- ?line {monitors,[{process,Me}]} = erlang:port_info(Port,monitors),
- ?line "ok" = port_control(Port,?MON_OP_DEMONITOR_ME,[]),
- ?line "not_monitored" = port_control(Port,?MON_OP_DEMONITOR_ME,[]),
- ?line {monitors,[]} = erlang:port_info(Port,monitors),
- ?line {monitored_by, []} = process_info(self(),monitored_by),
-
-
- ?line "ok" = port_control(Port,?MON_OP_MONITOR_ME,[]),
- ?line {Pid3,Ref3} =
- spawn_monitor(fun() ->
- receive go -> ok end,
- Me ! port_control(Port,?MON_OP_MONITOR_ME_LATER,[]),
- Me ! process_info(self(),monitored_by),
- Me ! erlang:port_info(Port,monitors) ,
- receive die -> ok end
- end),
- ?line Pid3 ! go,
- ?line {ok,Id3} = receive
- "ok:"++III ->
- {ok,III}
- after 1000 ->
- timeout
- end,
- ?line ok = receive
- {monitored_by, [Me]} ->
- ok
- after 1000 ->
- timeout
- end,
- ?line ok = receive
- {monitors, [{process,Me}]} ->
- ok
- after 1000 ->
- timeout
- end,
- ?line "ok" = port_control(Port,?MON_OP_DO_DELAYED_MONITOR,Id3),
- ?line LLL1 = lists:sort([{process,Me},{process,Pid3}]),
- ?line {monitors,LLL2} = erlang:port_info(Port,monitors),
- ?line LLL1 = lists:sort(LLL2),
- ?line "ok" = port_control(Port,?MON_OP_DEMONITOR_ME,[]),
- ?line {monitors,[{process,Pid3}]} = erlang:port_info(Port,monitors),
- ?line Pid3 ! die,
- ?line ok = receive
- {'DOWN', Ref3, process, Pid3, _} ->
- ok
- after 1000 ->
- timeout
- end,
- ?line "not_found" = port_control(Port,?MON_OP_DO_DELAYED_MONITOR,Id2),
- ?line {monitors,[]} = erlang:port_info(Port,monitors),
- ?line "not_monitored" = port_control(Port,?MON_OP_DEMONITOR_ME,[]),
- ?line {monitors,[]} = erlang:port_info(Port,monitors),
- ?line {monitored_by, []} = process_info(self(),monitored_by),
-
- ?line stop_driver(Port, Name),
- ?line ok.
+ Name = monitor_drv,
+ Port = start_driver(Config, Name, false),
+ "ok" = port_control(Port,?MON_OP_I_AM_IPID,[]),
+ "ok" = port_control(Port,?MON_OP_MONITOR_ME,[]),
+ "ok" = port_control(Port,?MON_OP_DEMONITOR_ME,[]),
+ {monitors, []} = erlang:port_info(Port,monitors),
+
+ "ok:"++Id1 = port_control(Port,?MON_OP_MONITOR_ME_LATER,[]),
+ {monitored_by, []} = process_info(self(),monitored_by),
+ "ok" = port_control(Port,?MON_OP_DO_DELAYED_MONITOR,Id1),
+ {monitored_by, [Port]} = process_info(self(),monitored_by),
+ "ok" = port_control(Port,?MON_OP_DEMONITOR_ME,[]),
+ {monitored_by, []} = process_info(self(),monitored_by),
+
+ "ok" = port_control(Port,?MON_OP_MONITOR_ME,[]),
+ Me = self(),
+ {Pid1,Ref1} =
+ spawn_monitor(fun() ->
+ Me ! port_control(Port,?MON_OP_MONITOR_ME,[]),
+ Me ! process_info(self(),monitored_by),
+ Me ! erlang:port_info(Port,monitors)
+ end),
+ ok = receive
+ "ok" ->
+ ok
+ after 1000 ->
+ timeout
+ end,
+ ok = receive
+ {monitored_by, L} ->
+ L2 = lists:sort(L),
+ L3 = lists:sort([Me,Port]),
+ case L2 of
+ L3 ->
+ ok;
+ _ ->
+ mismatch
+ end
+ after 1000 ->
+ timeout
+ end,
+ ok = receive
+ {monitors, LL} ->
+ LL2 = lists:sort(LL),
+ LL3 = lists:sort([{process,Me},{process,Pid1}]),
+ case LL2 of
+ LL3 ->
+ ok;
+ _ ->
+ mismatch
+ end
+ after 1000 ->
+ timeout
+ end,
+ ok = receive
+ {'DOWN', Ref1, process, Pid1, _} ->
+ ok
+ after 1000 ->
+ timeout
+ end,
+ ok = receive
+ {monitor_fired,Port,Pid1} ->
+ ok
+ after 1000 ->
+ timeout
+ end,
+ "ok" = port_control(Port,?MON_OP_DEMONITOR_ME,[]),
+ {monitors,[]} = erlang:port_info(Port,monitors),
+ {monitored_by, []} = process_info(self(),monitored_by),
+
+ "ok" = port_control(Port,?MON_OP_MONITOR_ME,[]),
+ {Pid2,Ref2} =
+ spawn_monitor(fun() ->
+ receive go -> ok end,
+ Me ! port_control(Port,?MON_OP_MONITOR_ME_LATER,[]),
+ Me ! process_info(self(),monitored_by),
+ Me ! erlang:port_info(Port,monitors)
+ end),
+ Pid2 ! go,
+ {ok,Id2} = receive
+ "ok:"++II ->
+ {ok,II}
+ after 1000 ->
+ timeout
+ end,
+ ok = receive
+ {monitored_by, [Me]} ->
+ ok
+ after 1000 ->
+ timeout
+ end,
+ ok = receive
+ {monitors, [{process,Me}]} ->
+ ok
+ after 1000 ->
+ timeout
+ end,
+ ok = receive
+ {'DOWN', Ref2, process, Pid2, _} ->
+ ok
+ after 1000 ->
+ timeout
+ end,
+ "noproc" = port_control(Port,?MON_OP_DO_DELAYED_MONITOR,Id2),
+ {monitors,[{process,Me}]} = erlang:port_info(Port,monitors),
+ "ok" = port_control(Port,?MON_OP_DEMONITOR_ME,[]),
+ "not_monitored" = port_control(Port,?MON_OP_DEMONITOR_ME,[]),
+ {monitors,[]} = erlang:port_info(Port,monitors),
+ {monitored_by, []} = process_info(self(),monitored_by),
+
+
+ "ok" = port_control(Port,?MON_OP_MONITOR_ME,[]),
+ {Pid3,Ref3} =
+ spawn_monitor(fun() ->
+ receive go -> ok end,
+ Me ! port_control(Port,?MON_OP_MONITOR_ME_LATER,[]),
+ Me ! process_info(self(),monitored_by),
+ Me ! erlang:port_info(Port,monitors) ,
+ receive die -> ok end
+ end),
+ Pid3 ! go,
+ {ok,Id3} = receive
+ "ok:"++III ->
+ {ok,III}
+ after 1000 ->
+ timeout
+ end,
+ ok = receive
+ {monitored_by, [Me]} ->
+ ok
+ after 1000 ->
+ timeout
+ end,
+ ok = receive
+ {monitors, [{process,Me}]} ->
+ ok
+ after 1000 ->
+ timeout
+ end,
+ "ok" = port_control(Port,?MON_OP_DO_DELAYED_MONITOR,Id3),
+ LLL1 = lists:sort([{process,Me},{process,Pid3}]),
+ {monitors,LLL2} = erlang:port_info(Port,monitors),
+ LLL1 = lists:sort(LLL2),
+ "ok" = port_control(Port,?MON_OP_DEMONITOR_ME,[]),
+ {monitors,[{process,Pid3}]} = erlang:port_info(Port,monitors),
+ Pid3 ! die,
+ ok = receive
+ {'DOWN', Ref3, process, Pid3, _} ->
+ ok
+ after 1000 ->
+ timeout
+ end,
+ "not_found" = port_control(Port,?MON_OP_DO_DELAYED_MONITOR,Id2),
+ {monitors,[]} = erlang:port_info(Port,monitors),
+ "not_monitored" = port_control(Port,?MON_OP_DEMONITOR_ME,[]),
+ {monitors,[]} = erlang:port_info(Port,monitors),
+ {monitored_by, []} = process_info(self(),monitored_by),
+
+ stop_driver(Port, Name),
+ ok.
-define(IOQ_EXIT_READY_INPUT, 1).
@@ -1399,726 +1349,663 @@ driver_monitor(Config) when is_list(Config) ->
-define(IOQ_EXIT_EVENT_ASYNC, 9).
ioq_exit_test(Config, TestNo) ->
- ?line Drv = ioq_exit_drv,
- ?line try
- begin
- ?line case load_driver(?config(data_dir, Config),
- Drv) of
- ok -> ?line ok;
- {error, permanent} -> ?line ok;
- LoadError -> ?line ?t:fail({load_error, LoadError})
- end,
- case open_port({spawn, Drv}, []) of
- Port when is_port(Port) ->
- try port_control(Port, TestNo, "") of
- "ok" ->
- ?line ok;
- "nyiftos" ->
- ?line throw({skipped,
- "Not yet implemented for "
- "this OS"});
- [$s,$k,$i,$p,$:,$ | Comment] ->
- ?line throw({skipped, Comment});
- [$e,$r,$r,$o,$r,$:,$ | Error] ->
- ?line ?t:fail(Error)
- after
- Port ! {self(), close},
- receive {Port, closed} -> ok end,
- false = lists:member(Port, erlang:ports()),
- ok
- end;
- Error ->
- ?line ?t:fail({open_port_failed, Error})
- end
- end
- catch
- throw:Term -> ?line Term
- after
- erl_ddll:unload_driver(Drv)
- end.
-
-ioq_exit_ready_input(doc) -> [];
-ioq_exit_ready_input(suite) -> [];
+ Drv = ioq_exit_drv,
+ try
+ begin
+ case load_driver(proplists:get_value(data_dir, Config),
+ Drv) of
+ ok -> ok;
+ {error, permanent} -> ok;
+ LoadError -> ct:fail({load_error, LoadError})
+ end,
+ case open_port({spawn, Drv}, []) of
+ Port when is_port(Port) ->
+ try port_control(Port, TestNo, "") of
+ "ok" ->
+ ok;
+ "nyiftos" ->
+ throw({skipped,
+ "Not yet implemented for "
+ "this OS"});
+ [$s,$k,$i,$p,$:,$ | Comment] ->
+ throw({skipped, Comment});
+ [$e,$r,$r,$o,$r,$:,$ | Error] ->
+ ct:fail(Error)
+ after
+ Port ! {self(), close},
+ receive {Port, closed} -> ok end,
+ false = lists:member(Port, erlang:ports()),
+ ok
+ end;
+ Error ->
+ ct:fail({open_port_failed, Error})
+ end
+ end
+ catch
+ throw:Term -> Term
+ after
+ erl_ddll:unload_driver(Drv)
+ end.
+
ioq_exit_ready_input(Config) when is_list(Config) ->
ioq_exit_test(Config, ?IOQ_EXIT_READY_INPUT).
-ioq_exit_ready_output(doc) -> [];
-ioq_exit_ready_output(suite) -> [];
ioq_exit_ready_output(Config) when is_list(Config) ->
ioq_exit_test(Config, ?IOQ_EXIT_READY_OUTPUT).
-ioq_exit_timeout(doc) -> [];
-ioq_exit_timeout(suite) -> [];
ioq_exit_timeout(Config) when is_list(Config) ->
ioq_exit_test(Config, ?IOQ_EXIT_TIMEOUT).
-ioq_exit_ready_async(doc) -> [];
-ioq_exit_ready_async(suite) -> [];
ioq_exit_ready_async(Config) when is_list(Config) ->
ioq_exit_test(Config, ?IOQ_EXIT_READY_ASYNC).
-ioq_exit_event(doc) -> [];
-ioq_exit_event(suite) -> [];
ioq_exit_event(Config) when is_list(Config) ->
ioq_exit_test(Config, ?IOQ_EXIT_EVENT).
-ioq_exit_ready_input_async(doc) -> [];
-ioq_exit_ready_input_async(suite) -> [];
ioq_exit_ready_input_async(Config) when is_list(Config) ->
ioq_exit_test(Config, ?IOQ_EXIT_READY_INPUT_ASYNC).
-ioq_exit_ready_output_async(doc) -> [];
-ioq_exit_ready_output_async(suite) -> [];
ioq_exit_ready_output_async(Config) when is_list(Config) ->
ioq_exit_test(Config, ?IOQ_EXIT_READY_OUTPUT_ASYNC).
-ioq_exit_timeout_async(doc) -> [];
-ioq_exit_timeout_async(suite) -> [];
ioq_exit_timeout_async(Config) when is_list(Config) ->
ioq_exit_test(Config, ?IOQ_EXIT_TIMEOUT_ASYNC).
-ioq_exit_event_async(doc) -> [];
-ioq_exit_event_async(suite) -> [];
ioq_exit_event_async(Config) when is_list(Config) ->
ioq_exit_test(Config, ?IOQ_EXIT_EVENT_ASYNC).
vsn_mismatch_test(Config, LoadResult) ->
- ?line Path = ?config(data_dir, Config),
- ?line DrvName = ?config(testcase, Config),
- ?line LoadResult = load_driver(Path, DrvName),
- ?line case LoadResult of
- ok ->
- ?line Port = open_port({spawn, DrvName}, []),
- ?line true = is_port(Port),
- ?line true = port_close(Port),
- ?line ok = erl_ddll:unload_driver(DrvName);
- _ ->
- ?line ok
- end.
-
-zero_extended_marker_garb_drv(doc) -> [];
-zero_extended_marker_garb_drv(suite) -> [];
+ Path = proplists:get_value(data_dir, Config),
+ DrvName = proplists:get_value(testcase, Config),
+ LoadResult = load_driver(Path, DrvName),
+ case LoadResult of
+ ok ->
+ Port = open_port({spawn, DrvName}, []),
+ true = is_port(Port),
+ true = port_close(Port),
+ ok = erl_ddll:unload_driver(DrvName);
+ _ ->
+ ok
+ end.
+
zero_extended_marker_garb_drv(Config) when is_list(Config) ->
vsn_mismatch_test(Config, {error, driver_incorrect_version}).
-invalid_extended_marker_drv(doc) -> [];
-invalid_extended_marker_drv(suite) -> [];
invalid_extended_marker_drv(Config) when is_list(Config) ->
vsn_mismatch_test(Config, {error, driver_incorrect_version}).
-larger_major_vsn_drv(doc) -> [];
-larger_major_vsn_drv(suite) -> [];
larger_major_vsn_drv(Config) when is_list(Config) ->
vsn_mismatch_test(Config, {error, driver_incorrect_version}).
-larger_minor_vsn_drv(doc) -> [];
-larger_minor_vsn_drv(suite) -> [];
larger_minor_vsn_drv(Config) when is_list(Config) ->
vsn_mismatch_test(Config, {error, driver_incorrect_version}).
-smaller_major_vsn_drv(doc) -> [];
-smaller_major_vsn_drv(suite) -> [];
smaller_major_vsn_drv(Config) when is_list(Config) ->
vsn_mismatch_test(Config, {error, driver_incorrect_version}).
-smaller_minor_vsn_drv(doc) -> [];
-smaller_minor_vsn_drv(suite) -> [];
smaller_minor_vsn_drv(Config) when is_list(Config) ->
DrvVsnStr = erlang:system_info(driver_version),
case drv_vsn_str2tup(DrvVsnStr) of
- {_, 0} ->
- {skipped,
- "Cannot perform test when minor driver version is 0. "
- "Current driver version is " ++ DrvVsnStr ++ "."};
- _ ->
- vsn_mismatch_test(Config, ok)
+ {_, 0} ->
+ {skipped,
+ "Cannot perform test when minor driver version is 0. "
+ "Current driver version is " ++ DrvVsnStr ++ "."};
+ _ ->
+ vsn_mismatch_test(Config, ok)
end.
-define(PEEK_NONXQ_TEST, 0).
-define(PEEK_NONXQ_WAIT, 1).
-peek_non_existing_queue(doc) -> [];
-peek_non_existing_queue(suite) -> [];
peek_non_existing_queue(Config) when is_list(Config) ->
- ?line OTE = process_flag(trap_exit, true),
- ?line Drv = peek_non_existing_queue_drv,
- ?line try
- begin
- ?line case load_driver(?config(data_dir, Config),
- Drv) of
- ok -> ?line ok;
- {error, permanent} -> ?line ok;
- LoadError -> ?line ?t:fail({load_error, LoadError})
- end,
- case open_port({spawn, Drv}, []) of
- Port1 when is_port(Port1) ->
- try port_control(Port1, ?PEEK_NONXQ_TEST, "") of
- "ok" ->
- ?line ok;
- [$s,$k,$i,$p,$p,$e,$d,$:,$ | SkipReason] ->
- ?line throw({skipped, SkipReason});
- [$e,$r,$r,$o,$r,$:,$ | Error1] ->
- ?line ?t:fail(Error1)
- after
- exit(Port1, kill),
- receive {'EXIT', Port1, _} -> ok end
- end;
- Error1 ->
- ?line ?t:fail({open_port1_failed, Error1})
- end,
- case open_port({spawn, Drv}, []) of
- Port2 when is_port(Port2) ->
- try port_control(Port2, ?PEEK_NONXQ_WAIT, "") of
- "ok" ->
- ?line ok;
- [$e,$r,$r,$o,$r,$:,$ | Error2] ->
- ?line ?t:fail(Error2)
- after
- receive {Port2, test_successful} -> ok end,
- Port2 ! {self(), close},
- receive {Port2, closed} -> ok end
- end;
- Error2 ->
- ?line ?t:fail({open_port2_failed, Error2})
- end
- end
- catch
- throw:Term -> ?line Term
- after
- process_flag(trap_exit, OTE),
- erl_ddll:unload_driver(Drv)
- end.
-
-otp_6879(doc) ->
- [];
-otp_6879(suite) ->
- [];
+ OTE = process_flag(trap_exit, true),
+ Drv = peek_non_existing_queue_drv,
+ try
+ begin
+ case load_driver(proplists:get_value(data_dir, Config),
+ Drv) of
+ ok -> ok;
+ {error, permanent} -> ok;
+ LoadError -> ct:fail({load_error, LoadError})
+ end,
+ case open_port({spawn, Drv}, []) of
+ Port1 when is_port(Port1) ->
+ try port_control(Port1, ?PEEK_NONXQ_TEST, "") of
+ "ok" ->
+ ok;
+ [$s,$k,$i,$p,$p,$e,$d,$:,$ | SkipReason] ->
+ throw({skipped, SkipReason});
+ [$e,$r,$r,$o,$r,$:,$ | Error1] ->
+ ct:fail(Error1)
+ after
+ exit(Port1, kill),
+ receive {'EXIT', Port1, _} -> ok end
+ end;
+ Error1 ->
+ ct:fail({open_port1_failed, Error1})
+ end,
+ case open_port({spawn, Drv}, []) of
+ Port2 when is_port(Port2) ->
+ try port_control(Port2, ?PEEK_NONXQ_WAIT, "") of
+ "ok" ->
+ ok;
+ [$e,$r,$r,$o,$r,$:,$ | Error2] ->
+ ct:fail(Error2)
+ after
+ receive {Port2, test_successful} -> ok end,
+ Port2 ! {self(), close},
+ receive {Port2, closed} -> ok end
+ end;
+ Error2 ->
+ ct:fail({open_port2_failed, Error2})
+ end
+ end
+ catch
+ throw:Term -> Term
+ after
+ process_flag(trap_exit, OTE),
+ erl_ddll:unload_driver(Drv)
+ end.
+
otp_6879(Config) when is_list(Config) ->
- ?line Drv = 'otp_6879_drv',
- ?line Parent = self(),
- ?line ok = load_driver(?config(data_dir, Config), Drv),
- ?line Procs = lists:map(
- fun (No) ->
- spawn_link(
- fun () ->
- case open_port({spawn, Drv}, []) of
- Port when is_port(Port) ->
- Res = otp_6879_call(Port, No, 10000),
- erlang:port_close(Port),
- Parent ! {self(), Res};
- _ ->
- Parent ! {self(),
- open_port_failed}
- end
- end)
- end,
- lists:seq(1,10)),
- ?line lists:foreach(fun (P) ->
- ?line receive
- {P, ok} ->
- ?line ok;
- {P, Error} ->
- ?line ?t:fail({P, Error})
- end
- end,
- Procs),
+ Drv = 'otp_6879_drv',
+ Parent = self(),
+ ok = load_driver(proplists:get_value(data_dir, Config), Drv),
+ Procs = lists:map(
+ fun (No) ->
+ spawn_link(
+ fun () ->
+ case open_port({spawn, Drv}, []) of
+ Port when is_port(Port) ->
+ Res = otp_6879_call(Port, No, 10000),
+ erlang:port_close(Port),
+ Parent ! {self(), Res};
+ _ ->
+ Parent ! {self(),
+ open_port_failed}
+ end
+ end)
+ end,
+ lists:seq(1,10)),
+ lists:foreach(fun (P) ->
+ receive
+ {P, ok} ->
+ ok;
+ {P, Error} ->
+ ct:fail({P, Error})
+ end
+ end,
+ Procs),
%% Also try it when input exceeds default buffer (256 bytes)
- ?line Data = lists:seq(1, 1000),
- ?line case open_port({spawn, Drv}, []) of
- Port when is_port(Port) ->
- ?line ok = otp_6879_call(Port, Data, 10),
- ?line erlang:port_close(Port);
- _ ->
- ?line ?t:fail(open_port_failed)
- end,
- ?line erl_ddll:unload_driver(Drv),
- ?line ok.
+ Data = lists:seq(1, 1000),
+ case open_port({spawn, Drv}, []) of
+ Port when is_port(Port) ->
+ ok = otp_6879_call(Port, Data, 10),
+ erlang:port_close(Port);
+ _ ->
+ ct:fail(open_port_failed)
+ end,
+ erl_ddll:unload_driver(Drv),
+ ok.
otp_6879_call(_Port, _Data, 0) ->
ok;
otp_6879_call(Port, Data, N) ->
case catch erlang:port_call(Port, 0, Data) of
- Data -> otp_6879_call(Port, Data, N-1);
- BadData -> {mismatch, Data, BadData}
+ Data -> otp_6879_call(Port, Data, N-1);
+ BadData -> {mismatch, Data, BadData}
end.
-caller(doc) ->
- [];
-caller(suite) ->
- [];
caller(Config) when is_list(Config) ->
- ?line run_caller_test(Config, false),
- ?line run_caller_test(Config, true).
-
+ run_caller_test(Config, false),
+ run_caller_test(Config, true).
+
run_caller_test(Config, Outputv) ->
- ?line Drv = 'caller_drv',
- ?line Cmd = case Outputv of
- true ->
- ?line os:putenv("CALLER_DRV_USE_OUTPUTV",
- "true"),
- outputv;
- false ->
- ?line os:putenv("CALLER_DRV_USE_OUTPUTV",
- "false"),
- output
- end,
- ?line ok = load_driver(?config(data_dir, Config), Drv),
- ?line Port = open_port({spawn, Drv}, []),
- ?line true = is_port(Port),
- ?line chk_caller(Port, start, self()),
- ?line chk_caller(Port,
- Cmd,
- spawn_link(
- fun () ->
- port_command(Port, "")
- end)),
- ?line Port ! {self(), {command, ""}},
- ?line chk_caller(Port, Cmd, self()),
- ?line chk_caller(Port,
- control,
- spawn_link(
- fun () ->
- port_control(Port, 0, "")
- end)),
- ?line chk_caller(Port,
- call,
- spawn_link(
- fun () ->
- erlang:port_call(Port, 0, "")
- end)),
- ?line true = port_close(Port),
- ?line erl_ddll:unload_driver(Drv),
- ?line ok.
+ Drv = 'caller_drv',
+ Cmd = case Outputv of
+ true ->
+ os:putenv("CALLER_DRV_USE_OUTPUTV",
+ "true"),
+ outputv;
+ false ->
+ os:putenv("CALLER_DRV_USE_OUTPUTV",
+ "false"),
+ output
+ end,
+ ok = load_driver(proplists:get_value(data_dir, Config), Drv),
+ Port = open_port({spawn, Drv}, []),
+ true = is_port(Port),
+ chk_caller(Port, start, self()),
+ chk_caller(Port,
+ Cmd,
+ spawn_link(
+ fun () ->
+ port_command(Port, "")
+ end)),
+ Port ! {self(), {command, ""}},
+ chk_caller(Port, Cmd, self()),
+ chk_caller(Port,
+ control,
+ spawn_link(
+ fun () ->
+ port_control(Port, 0, "")
+ end)),
+ chk_caller(Port,
+ call,
+ spawn_link(
+ fun () ->
+ erlang:port_call(Port, 0, "")
+ end)),
+ true = port_close(Port),
+ erl_ddll:unload_driver(Drv),
+ ok.
chk_caller(Port, Callback, ExpectedCaller) ->
receive
- {caller, Port, Callback, Caller} ->
- ExpectedCaller = Caller
+ {caller, Port, Callback, Caller} ->
+ ExpectedCaller = Caller
end.
-many_events(suite) ->
- [];
-many_events(doc) ->
- ["Check that many simultaneously signalled events work (win32)"];
+%% Check that many simultaneously signalled events work (win32)
many_events(Config) when is_list(Config) ->
- ?line Name = 'many_events_drv',
- ?line Port = start_driver(Config, Name, false),
+ Name = 'many_events_drv',
+ Port = start_driver(Config, Name, false),
Number = "1000",
Port ! {self(), {command, Number}},
receive
- {Port, {data,Number}} ->
- ?line receive %% Just to make sure the emulator does not crash
- %% after this case is run (if faulty)
- after 2000 ->
- ok
- end
+ {Port, {data,Number}} ->
+ receive %% Just to make sure the emulator does not crash
+ %% after this case is run (if faulty)
+ after 2000 ->
+ ok
+ end
after 1000 ->
- ?line exit(the_driver_does_not_respond)
+ exit(the_driver_does_not_respond)
end,
- ?line stop_driver(Port, Name),
- ?line ok.
-
-
-missing_callbacks(doc) ->
- [];
-missing_callbacks(suite) ->
- [];
+ stop_driver(Port, Name),
+ ok.
+
+
missing_callbacks(Config) when is_list(Config) ->
- ?line Name = 'missing_callback_drv',
- ?line Port = start_driver(Config, Name, false),
+ Name = 'missing_callback_drv',
+ Port = start_driver(Config, Name, false),
- ?line Port ! {self(), {command, "tjenix"}},
- ?line true = erlang:port_command(Port, "halloj"),
- ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(Port, 4711, "mors")),
- ?line {'EXIT', {badarg, _}} = (catch erlang:port_call(Port, 17, "hej")),
+ Port ! {self(), {command, "tjenix"}},
+ true = erlang:port_command(Port, "halloj"),
+ {'EXIT', {badarg, _}} = (catch erlang:port_control(Port, 4711, "mors")),
+ {'EXIT', {badarg, _}} = (catch erlang:port_call(Port, 17, "hej")),
- ?line %% Give the (non-existing) ready_output(), ready_input(), event(),
- ?line %% and timeout() some time to be called.
- ?line receive after 1000 -> ok end,
+ %% Give the (non-existing) ready_output(), ready_input(), event(),
+ %% and timeout() some time to be called.
+ receive after 1000 -> ok end,
- ?line stop_driver(Port, Name),
- ?line ok.
+ stop_driver(Port, Name),
+ ok.
-smp_select(doc) ->
- ["Test concurrent calls to driver_select."];
-smp_select(suite) ->
- [];
+%% Test concurrent calls to driver_select.
smp_select(Config) when is_list(Config) ->
case os:type() of
- {win32,_} -> {skipped, "Test not implemented for this OS"};
- _ -> smp_select0(Config)
+ {win32,_} -> {skipped, "Test not implemented for this OS"};
+ _ -> smp_select0(Config)
end.
-
+
smp_select0(Config) ->
- ?line DrvName = 'chkio_drv',
- Path = ?config(data_dir, Config),
+ DrvName = 'chkio_drv',
+ Path = proplists:get_value(data_dir, Config),
erl_ddll:start(),
- ?line ok = load_driver(Path, DrvName),
+ ok = load_driver(Path, DrvName),
Master = self(),
ProcFun = fun()-> io:format("Worker ~p starting\n",[self()]),
- ?line Port = open_port({spawn, DrvName}, []),
- smp_select_loop(Port, 100000),
- sleep(1000), % wait for driver to handle pending events
- ?line true = erlang:port_close(Port),
- Master ! {ok,self()},
- io:format("Worker ~p finished\n",[self()])
- end,
- ?line Pids = lists:map(fun(_) -> spawn_link(ProcFun) end,
- lists:seq(1,4)),
+ Port = open_port({spawn, DrvName}, []),
+ smp_select_loop(Port, 100000),
+ sleep(1000), % wait for driver to handle pending events
+ true = erlang:port_close(Port),
+ Master ! {ok,self()},
+ io:format("Worker ~p finished\n",[self()])
+ end,
+ Pids = lists:map(fun(_) -> spawn_link(ProcFun) end,
+ lists:seq(1,4)),
TimeoutMsg = make_ref(),
{ok,TRef} = timer:send_after(5*1000, TimeoutMsg), % Limit test duration on slow machines
smp_select_wait(Pids, TimeoutMsg),
timer:cancel(TRef),
- ?line ok = erl_ddll:unload_driver(DrvName),
- ?line ok = erl_ddll:stop(),
+ ok = erl_ddll:unload_driver(DrvName),
+ ok = erl_ddll:stop(),
ok.
smp_select_loop(_, 0) ->
ok;
smp_select_loop(Port, N) ->
- ?line "ok" = erlang:port_control(Port, ?CHKIO_SMP_SELECT, []),
+ "ok" = erlang:port_control(Port, ?CHKIO_SMP_SELECT, []),
receive
- stop ->
- io:format("Worker ~p stopped with ~p laps left\n",[self(), N]),
- ok
+ stop ->
+ io:format("Worker ~p stopped with ~p laps left\n",[self(), N]),
+ ok
after 0 ->
- smp_select_loop(Port, N-1)
+ smp_select_loop(Port, N-1)
end.
smp_select_wait([], _) ->
ok;
smp_select_wait(Pids, TimeoutMsg) ->
receive
- {ok,Pid} when is_pid(Pid) ->
- smp_select_wait(lists:delete(Pid,Pids), TimeoutMsg);
- TimeoutMsg ->
- lists:foreach(fun(Pid)-> Pid ! stop end,
- Pids),
- smp_select_wait(Pids, TimeoutMsg)
+ {ok,Pid} when is_pid(Pid) ->
+ smp_select_wait(lists:delete(Pid,Pids), TimeoutMsg);
+ TimeoutMsg ->
+ lists:foreach(fun(Pid)-> Pid ! stop end,
+ Pids),
+ smp_select_wait(Pids, TimeoutMsg)
end.
-driver_select_use(doc) ->
- ["Test driver_select() with new ERL_DRV_USE flag."];
-driver_select_use(suite) ->
- [];
+%% Test driver_select() with new ERL_DRV_USE flag.
driver_select_use(Config) when is_list(Config) ->
case os:type() of
- {win32,_} -> {skipped, "Test not implemented for this OS"};
- _ -> driver_select_use0(Config)
+ {win32,_} -> {skipped, "Test not implemented for this OS"};
+ _ -> driver_select_use0(Config)
end.
-
+
driver_select_use0(Config) ->
- ?line DrvName = 'chkio_drv',
- Path = ?config(data_dir, Config),
+ DrvName = 'chkio_drv',
+ Path = proplists:get_value(data_dir, Config),
erl_ddll:start(),
- ?line ok = load_driver(Path, DrvName),
- ?line Port = open_port({spawn, DrvName}, []),
- ?line "ok" = erlang:port_control(Port, ?CHKIO_DRV_USE, []),
- ?line {Port,{data,"TheEnd"}} = receive Msg -> Msg
- after 10000 -> timeout end,
- ?line true = erlang:port_close(Port),
- ?line ok = erl_ddll:unload_driver(DrvName),
- ?line ok = erl_ddll:stop(),
+ ok = load_driver(Path, DrvName),
+ Port = open_port({spawn, DrvName}, []),
+ "ok" = erlang:port_control(Port, ?CHKIO_DRV_USE, []),
+ {Port,{data,"TheEnd"}} = receive Msg -> Msg
+ after 10000 -> timeout end,
+ true = erlang:port_close(Port),
+ ok = erl_ddll:unload_driver(DrvName),
+ ok = erl_ddll:stop(),
ok.
thread_mseg_alloc_cache_clean(Config) when is_list(Config) ->
case {erlang:system_info(threads),
- erlang:system_info({allocator,mseg_alloc}),
- driver_alloc_sbct()} of
- {_, false, _} ->
- ?line {skipped, "No mseg_alloc"};
- {false, _, _} ->
- ?line {skipped, "No threads"};
- {_, _, false} ->
- ?line {skipped, "driver_alloc() not using the alloc_util framework"};
- {_, _, SBCT} when is_integer(SBCT), SBCT > 10*1024*1024 ->
- ?line {skipped, "driver_alloc() using too large single block threshold"};
- {_, _, 0} ->
- ?line {skipped, "driver_alloc() using too low single block threshold"};
- {true, _MsegAllocInfo, SBCT} ->
- ?line DrvName = 'thr_alloc_drv',
- ?line Path = ?config(data_dir, Config),
- ?line erl_ddll:start(),
- ?line ok = load_driver(Path, DrvName),
- ?line Port = open_port({spawn, DrvName}, []),
- ?line CCI = 1000,
- ?line ?t:format("CCI = ~p~n", [CCI]),
- ?line CCC = mseg_alloc_ccc(),
- ?line ?t:format("CCC = ~p~n", [CCC]),
- ?line thread_mseg_alloc_cache_clean_test(Port,
- 10,
- CCI,
- SBCT+100),
- ?line true = erlang:port_close(Port),
- ?line ok = erl_ddll:unload_driver(DrvName),
- ?line ok = erl_ddll:stop(),
- ?line ok
+ erlang:system_info({allocator,mseg_alloc}),
+ driver_alloc_sbct()} of
+ {_, false, _} ->
+ {skipped, "No mseg_alloc"};
+ {false, _, _} ->
+ {skipped, "No threads"};
+ {_, _, false} ->
+ {skipped, "driver_alloc() not using the alloc_util framework"};
+ {_, _, SBCT} when is_integer(SBCT), SBCT > 10*1024*1024 ->
+ {skipped, "driver_alloc() using too large single block threshold"};
+ {_, _, 0} ->
+ {skipped, "driver_alloc() using too low single block threshold"};
+ {true, _MsegAllocInfo, SBCT} ->
+ DrvName = 'thr_alloc_drv',
+ Path = proplists:get_value(data_dir, Config),
+ erl_ddll:start(),
+ ok = load_driver(Path, DrvName),
+ Port = open_port({spawn, DrvName}, []),
+ CCI = 1000,
+ io:format("CCI = ~p~n", [CCI]),
+ CCC = mseg_alloc_ccc(),
+ io:format("CCC = ~p~n", [CCC]),
+ thread_mseg_alloc_cache_clean_test(Port,
+ 10,
+ CCI,
+ SBCT+100),
+ true = erlang:port_close(Port),
+ ok = erl_ddll:unload_driver(DrvName),
+ ok = erl_ddll:stop(),
+ ok
end.
mseg_alloc_cci(MsegAllocInfo) ->
- ?line {value,{options, OL}}
- = lists:keysearch(options, 1, MsegAllocInfo),
- ?line {value,{cci,CCI}} = lists:keysearch(cci,1,OL),
- ?line CCI.
+ {value,{options, OL}}
+ = lists:keysearch(options, 1, MsegAllocInfo),
+ {value,{cci,CCI}} = lists:keysearch(cci,1,OL),
+ CCI.
mseg_alloc_ccc() ->
mseg_alloc_ccc(mseg_inst_info(0)).
mseg_alloc_ccc(MsegAllocInfo) ->
- ?line {value,{memkind, MKL}} = lists:keysearch(memkind,1,MsegAllocInfo),
- ?line {value,{calls, CL}} = lists:keysearch(calls, 1, MKL),
- ?line {value,{mseg_check_cache, GigaCCC, CCC}}
- = lists:keysearch(mseg_check_cache, 1, CL),
- ?line GigaCCC*1000000000 + CCC.
+ {value,{memkind, MKL}} = lists:keysearch(memkind,1,MsegAllocInfo),
+ {value,{calls, CL}} = lists:keysearch(calls, 1, MKL),
+ {value,{mseg_check_cache, GigaCCC, CCC}}
+ = lists:keysearch(mseg_check_cache, 1, CL),
+ GigaCCC*1000000000 + CCC.
mseg_alloc_cached_segments() ->
mseg_alloc_cached_segments(mseg_inst_info(0)).
mseg_alloc_cached_segments(MsegAllocInfo) ->
- MemName = case is_halfword_vm() of
- true -> "high memory";
- false -> "all memory"
- end,
- ?line [{memkind,DrvMem}]
- = lists:filter(fun(E) -> case E of
- {memkind, [{name, MemName} | _]} -> true;
- _ -> false
- end end, MsegAllocInfo),
- ?line {value,{status, SL}}
- = lists:keysearch(status, 1, DrvMem),
- ?line {value,{cached_segments, CS}}
- = lists:keysearch(cached_segments, 1, SL),
- ?line CS.
+ MemName = "all memory",
+ [{memkind,DrvMem}]
+ = lists:filter(fun(E) -> case E of
+ {memkind, [{name, MemName} | _]} -> true;
+ _ -> false
+ end end, MsegAllocInfo),
+ {value,{status, SL}}
+ = lists:keysearch(status, 1, DrvMem),
+ {value,{cached_segments, CS}}
+ = lists:keysearch(cached_segments, 1, SL),
+ CS.
mseg_inst_info(I) ->
{value, {instance, I, Value}}
- = lists:keysearch(I,
- 2,
- erlang:system_info({allocator,mseg_alloc})),
+ = lists:keysearch(I,
+ 2,
+ erlang:system_info({allocator,mseg_alloc})),
Value.
-is_halfword_vm() ->
- case {erlang:system_info({wordsize, internal}),
- erlang:system_info({wordsize, external})} of
- {4, 8} -> true;
- {WS, WS} -> false
- end.
-
driver_alloc_sbct() ->
{_, _, _, As} = erlang:system_info(allocator),
case lists:keysearch(driver_alloc, 1, As) of
- {value,{driver_alloc,DAOPTs}} ->
- case lists:keysearch(sbct, 1, DAOPTs) of
- {value,{sbct,SBCT}} ->
- SBCT;
- _ ->
- false
- end;
- _ ->
- false
+ {value,{driver_alloc,DAOPTs}} ->
+ case lists:keysearch(sbct, 1, DAOPTs) of
+ {value,{sbct,SBCT}} ->
+ SBCT;
+ _ ->
+ false
+ end;
+ _ ->
+ false
end.
thread_mseg_alloc_cache_clean_test(_Port, 0, _CCI, _Size) ->
- ?line ok;
+ ok;
thread_mseg_alloc_cache_clean_test(Port, N, CCI, Size) ->
- ?line wait_until(fun () -> 0 == mseg_alloc_cached_segments() end),
- ?line receive after CCI+500 -> ok end,
- ?line OCCC = mseg_alloc_ccc(),
- ?line "ok" = erlang:port_control(Port, 0, integer_to_list(Size)),
- ?line receive after CCI+500 -> ok end,
- ?line CCC = mseg_alloc_ccc(),
- ?line ?t:format("CCC = ~p~n", [CCC]),
- ?line true = CCC > OCCC,
- ?line thread_mseg_alloc_cache_clean_test(Port, N-1, CCI, Size).
+ wait_until(fun () -> 0 == mseg_alloc_cached_segments() end),
+ receive after CCI+500 -> ok end,
+ OCCC = mseg_alloc_ccc(),
+ "ok" = erlang:port_control(Port, 0, integer_to_list(Size)),
+ receive after CCI+500 -> ok end,
+ CCC = mseg_alloc_ccc(),
+ io:format("CCC = ~p~n", [CCC]),
+ true = CCC > OCCC,
+ thread_mseg_alloc_cache_clean_test(Port, N-1, CCI, Size).
otp_9302(Config) when is_list(Config) ->
- ?line Path = ?config(data_dir, Config),
- ?line erl_ddll:start(),
- ?line ok = load_driver(Path, otp_9302_drv),
- ?line Port = open_port({spawn, otp_9302_drv}, []),
- ?line true = is_port(Port),
- ?line port_command(Port, ""),
- ?line {msg, block} = get_port_msg(Port, infinity),
- ?line {msg, job} = get_port_msg(Port, infinity),
- ?line C = case erlang:system_info(thread_pool_size) of
- 0 ->
- ?line {msg, cancel} = get_port_msg(Port, infinity),
- ?line {msg, job} = get_port_msg(Port, infinity),
- ?line false;
- _ ->
- case get_port_msg(Port, infinity) of
- {msg, cancel} -> %% Cancel always fail in Rel >= 15
- ?line {msg, job} = get_port_msg(Port, infinity),
- ?line false;
- {msg, job} ->
- ?line ok,
- ?line true
- end
- end,
- ?line {msg, end_of_jobs} = get_port_msg(Port, infinity),
- ?line no_msg = get_port_msg(Port, 2000),
- ?line port_close(Port),
- ?line case C of
- true ->
- ?line {comment, "Async job cancelled"};
- false ->
- ?line {comment, "Async job not cancelled"}
- end.
+ Path = proplists:get_value(data_dir, Config),
+ erl_ddll:start(),
+ ok = load_driver(Path, otp_9302_drv),
+ Port = open_port({spawn, otp_9302_drv}, []),
+ true = is_port(Port),
+ port_command(Port, ""),
+ {msg, block} = get_port_msg(Port, infinity),
+ {msg, job} = get_port_msg(Port, infinity),
+ C = case erlang:system_info(thread_pool_size) of
+ 0 ->
+ {msg, cancel} = get_port_msg(Port, infinity),
+ {msg, job} = get_port_msg(Port, infinity),
+ false;
+ _ ->
+ case get_port_msg(Port, infinity) of
+ {msg, cancel} -> %% Cancel always fail in Rel >= 15
+ {msg, job} = get_port_msg(Port, infinity),
+ false;
+ {msg, job} ->
+ ok,
+ true
+ end
+ end,
+ {msg, end_of_jobs} = get_port_msg(Port, infinity),
+ no_msg = get_port_msg(Port, 2000),
+ port_close(Port),
+ case C of
+ true ->
+ {comment, "Async job cancelled"};
+ false ->
+ {comment, "Async job not cancelled"}
+ end.
thr_free_drv(Config) when is_list(Config) ->
case erlang:system_info(threads) of
- false ->
- {skipped, "No thread support"};
- true ->
- thr_free_drv_do(Config)
+ false ->
+ {skipped, "No thread support"};
+ true ->
+ thr_free_drv_do(Config)
end.
thr_free_drv_do(Config) ->
- ?line Path = ?config(data_dir, Config),
- ?line erl_ddll:start(),
- ?line ok = load_driver(Path, thr_free_drv),
- ?line MemBefore = driver_alloc_size(),
-% io:format("SID=~p", [erlang:system_info(scheduler_id)]),
- ?line Port = open_port({spawn, thr_free_drv}, []),
- ?line MemPeek = driver_alloc_size(),
- ?line true = is_port(Port),
- ?line ok = thr_free_drv_control(Port, 0),
- ?line port_close(Port),
- ?line MemAfter = driver_alloc_size(),
- ?line io:format("MemPeek=~p~n", [MemPeek]),
- ?line io:format("MemBefore=~p, MemAfter=~p~n", [MemBefore, MemAfter]),
- ?line MemBefore = MemAfter,
- ?line case MemPeek of
- undefined -> ok;
- _ ->
- ?line true = MemPeek > MemBefore
- end,
- ?line ok.
+ Path = proplists:get_value(data_dir, Config),
+ erl_ddll:start(),
+ ok = load_driver(Path, thr_free_drv),
+ MemBefore = driver_alloc_size(),
+ % io:format("SID=~p", [erlang:system_info(scheduler_id)]),
+ Port = open_port({spawn, thr_free_drv}, []),
+ MemPeek = driver_alloc_size(),
+ true = is_port(Port),
+ ok = thr_free_drv_control(Port, 0),
+ port_close(Port),
+ MemAfter = driver_alloc_size(),
+ io:format("MemPeek=~p~n", [MemPeek]),
+ io:format("MemBefore=~p, MemAfter=~p~n", [MemBefore, MemAfter]),
+ MemBefore = MemAfter,
+ case MemPeek of
+ undefined -> ok;
+ _ ->
+ true = MemPeek > MemBefore
+ end,
+ ok.
thr_free_drv_control(Port, N) ->
case erlang:port_control(Port, 0, "") of
- "done" ->
- ok;
- "more" ->
- erlang:yield(),
-% io:format("N=~p, SID=~p", [N, erlang:system_info(scheduler_id)]),
- thr_free_drv_control(Port, N+1)
+ "done" ->
+ ok;
+ "more" ->
+ erlang:yield(),
+ % io:format("N=~p, SID=~p", [N, erlang:system_info(scheduler_id)]),
+ thr_free_drv_control(Port, N+1)
end.
-
+
async_blast(Config) when is_list(Config) ->
- ?line Path = ?config(data_dir, Config),
- ?line erl_ddll:start(),
- ?line ok = load_driver(Path, async_blast_drv),
- ?line SchedOnln = erlang:system_info(schedulers_online),
- ?line MemBefore = driver_alloc_size(),
- ?line Start = os:timestamp(),
- ?line Blast = fun () ->
- Port = open_port({spawn, async_blast_drv}, []),
- true = is_port(Port),
- port_command(Port, ""),
- receive
- {Port, done} ->
- ok
- end,
- port_close(Port)
- end,
- ?line Ps = lists:map(fun (N) ->
- spawn_opt(Blast,
- [{scheduler,
- (N rem SchedOnln)+ 1},
- monitor])
- end,
- lists:seq(1, 100)),
- ?line MemMid = driver_alloc_size(),
- ?line lists:foreach(fun ({Pid, Mon}) ->
- receive
- {'DOWN',Mon,process,Pid,_} -> ok
- end
- end, Ps),
- ?line End = os:timestamp(),
- ?line MemAfter = driver_alloc_size(),
- ?line io:format("MemBefore=~p, MemMid=~p, MemAfter=~p~n",
- [MemBefore, MemMid, MemAfter]),
- ?line AsyncBlastTime = timer:now_diff(End,Start)/1000000,
- ?line io:format("AsyncBlastTime=~p~n", [AsyncBlastTime]),
- ?line MemBefore = MemAfter,
- ?line erlang:display({async_blast_time, AsyncBlastTime}),
- ?line ok.
+ Path = proplists:get_value(data_dir, Config),
+ erl_ddll:start(),
+ ok = load_driver(Path, async_blast_drv),
+ SchedOnln = erlang:system_info(schedulers_online),
+ MemBefore = driver_alloc_size(),
+ Start = os:timestamp(),
+ Blast = fun () ->
+ Port = open_port({spawn, async_blast_drv}, []),
+ true = is_port(Port),
+ port_command(Port, ""),
+ receive
+ {Port, done} ->
+ ok
+ end,
+ port_close(Port)
+ end,
+ Ps = lists:map(fun (N) ->
+ spawn_opt(Blast,
+ [{scheduler,
+ (N rem SchedOnln)+ 1},
+ monitor])
+ end,
+ lists:seq(1, 100)),
+ MemMid = driver_alloc_size(),
+ lists:foreach(fun ({Pid, Mon}) ->
+ receive
+ {'DOWN',Mon,process,Pid,_} -> ok
+ end
+ end, Ps),
+ End = os:timestamp(),
+ MemAfter = driver_alloc_size(),
+ io:format("MemBefore=~p, MemMid=~p, MemAfter=~p~n",
+ [MemBefore, MemMid, MemAfter]),
+ AsyncBlastTime = timer:now_diff(End,Start)/1000000,
+ io:format("AsyncBlastTime=~p~n", [AsyncBlastTime]),
+ MemBefore = MemAfter,
+ erlang:display({async_blast_time, AsyncBlastTime}),
+ ok.
thr_msg_blast_receiver(_Port, N, N) ->
ok;
thr_msg_blast_receiver(Port, N, Max) ->
receive
- {Port, hi} ->
- thr_msg_blast_receiver(Port, N+1, Max)
+ {Port, hi} ->
+ thr_msg_blast_receiver(Port, N+1, Max)
end.
thr_msg_blast_receiver_proc(Port, Max, Parent, Done) ->
case port_control(Port, 0, "") of
- "receiver" ->
- spawn(fun () ->
- thr_msg_blast_receiver_proc(Port, Max+1, Parent, Done)
- end),
- thr_msg_blast_receiver(Port, 0, Max);
- "done" ->
- Parent ! Done
+ "receiver" ->
+ spawn(fun () ->
+ thr_msg_blast_receiver_proc(Port, Max+1, Parent, Done)
+ end),
+ thr_msg_blast_receiver(Port, 0, Max);
+ "done" ->
+ Parent ! Done
end.
thr_msg_blast(Config) when is_list(Config) ->
case erlang:system_info(smp_support) of
- false ->
- {skipped, "Non-SMP emulator; nothing to test..."};
- true ->
- Path = ?config(data_dir, Config),
- erl_ddll:start(),
- ok = load_driver(Path, thr_msg_blast_drv),
- MemBefore = driver_alloc_size(),
- Start = os:timestamp(),
- Port = open_port({spawn, thr_msg_blast_drv}, []),
- true = is_port(Port),
- Done = make_ref(),
- Me = self(),
- spawn(fun () ->
- thr_msg_blast_receiver_proc(Port, 1, Me, Done)
- end),
- receive
- Done -> ok
- end,
- ok = thr_msg_blast_receiver(Port, 0, 32*10000),
- port_close(Port),
- End = os:timestamp(),
- receive
- Garbage ->
- ?t:fail({received_garbage, Port, Garbage})
- after 2000 ->
- ok
- end,
- MemAfter = driver_alloc_size(),
- io:format("MemBefore=~p, MemAfter=~p~n",
- [MemBefore, MemAfter]),
- ThrMsgBlastTime = timer:now_diff(End,Start)/1000000,
- io:format("ThrMsgBlastTime=~p~n", [ThrMsgBlastTime]),
- MemBefore = MemAfter,
- Res = {thr_msg_blast_time, ThrMsgBlastTime},
- erlang:display(Res),
- Res
+ false ->
+ {skipped, "Non-SMP emulator; nothing to test..."};
+ true ->
+ Path = proplists:get_value(data_dir, Config),
+ erl_ddll:start(),
+ ok = load_driver(Path, thr_msg_blast_drv),
+ MemBefore = driver_alloc_size(),
+ Start = os:timestamp(),
+ Port = open_port({spawn, thr_msg_blast_drv}, []),
+ true = is_port(Port),
+ Done = make_ref(),
+ Me = self(),
+ spawn(fun () ->
+ thr_msg_blast_receiver_proc(Port, 1, Me, Done)
+ end),
+ receive
+ Done -> ok
+ end,
+ ok = thr_msg_blast_receiver(Port, 0, 32*10000),
+ port_close(Port),
+ End = os:timestamp(),
+ receive
+ Garbage ->
+ ct:fail({received_garbage, Port, Garbage})
+ after 2000 ->
+ ok
+ end,
+ MemAfter = driver_alloc_size(),
+ io:format("MemBefore=~p, MemAfter=~p~n",
+ [MemBefore, MemAfter]),
+ ThrMsgBlastTime = timer:now_diff(End,Start)/1000000,
+ io:format("ThrMsgBlastTime=~p~n", [ThrMsgBlastTime]),
+ MemBefore = MemAfter,
+ Res = {thr_msg_blast_time, ThrMsgBlastTime},
+ erlang:display(Res),
+ Res
end.
-define(IN_RANGE(LoW_, VaLuE_, HiGh_),
- case in_range(LoW_, VaLuE_, HiGh_) of
- true -> ok;
- false ->
- case erlang:system_info(lock_checking) of
- true ->
- ?t:format("~p:~p: Ignore bad sched count due to "
- "lock checking~n",
- [?MODULE,?LINE]);
- false ->
- ?t:fail({unexpected_sched_counts, VaLuE_})
- end
- end).
+ case in_range(LoW_, VaLuE_, HiGh_) of
+ true -> ok;
+ false ->
+ case erlang:system_info(lock_checking) of
+ true ->
+ io:format("~p:~p: Ignore bad sched count due to "
+ "lock checking~n",
+ [?MODULE,?LINE]);
+ false ->
+ ct:fail({unexpected_sched_counts, VaLuE_})
+ end
+ end).
consume_timeslice(Config) when is_list(Config) ->
@@ -2150,7 +2037,7 @@ consume_timeslice(Config) when is_list(Config) ->
%% the port instead.
%%
- Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
erl_ddll:start(),
ok = load_driver(Path, consume_timeslice_drv),
Port = open_port({spawn, consume_timeslice_drv}, [{parallelism, false}]),
@@ -2160,18 +2047,18 @@ consume_timeslice(Config) when is_list(Config) ->
"enabled" = port_control(Port, $E, ""),
Proc1 = spawn_link(fun () ->
- receive Go -> ok end,
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}}
- end),
+ receive Go -> ok end,
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}}
+ end),
receive after 100 -> ok end,
count_pp_sched_start(),
Proc1 ! Go,
@@ -2182,18 +2069,18 @@ consume_timeslice(Config) when is_list(Config) ->
"disabled" = port_control(Port, $D, ""),
Proc2 = spawn_link(fun () ->
- receive Go -> ok end,
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}},
- Port ! {Parent, {command, ""}}
- end),
+ receive Go -> ok end,
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}},
+ Port ! {Parent, {command, ""}}
+ end),
receive after 100 -> ok end,
count_pp_sched_start(),
Proc2 ! Go,
@@ -2204,18 +2091,18 @@ consume_timeslice(Config) when is_list(Config) ->
"enabled" = port_control(Port, $E, ""),
Proc3 = spawn_link(fun () ->
- receive Go -> ok end,
- port_command(Port, ""),
- port_command(Port, ""),
- port_command(Port, ""),
- port_command(Port, ""),
- port_command(Port, ""),
- port_command(Port, ""),
- port_command(Port, ""),
- port_command(Port, ""),
- port_command(Port, ""),
- port_command(Port, "")
- end),
+ receive Go -> ok end,
+ port_command(Port, ""),
+ port_command(Port, ""),
+ port_command(Port, ""),
+ port_command(Port, ""),
+ port_command(Port, ""),
+ port_command(Port, ""),
+ port_command(Port, ""),
+ port_command(Port, ""),
+ port_command(Port, ""),
+ port_command(Port, "")
+ end),
count_pp_sched_start(),
Proc3 ! Go,
wait_command_msgs(Port, 10),
@@ -2225,18 +2112,18 @@ consume_timeslice(Config) when is_list(Config) ->
"disabled" = port_control(Port, $D, ""),
Proc4 = spawn_link(fun () ->
- receive Go -> ok end,
- port_command(Port, ""),
- port_command(Port, ""),
- port_command(Port, ""),
- port_command(Port, ""),
- port_command(Port, ""),
- port_command(Port, ""),
- port_command(Port, ""),
- port_command(Port, ""),
- port_command(Port, ""),
- port_command(Port, "")
- end),
+ receive Go -> ok end,
+ port_command(Port, ""),
+ port_command(Port, ""),
+ port_command(Port, ""),
+ port_command(Port, ""),
+ port_command(Port, ""),
+ port_command(Port, ""),
+ port_command(Port, ""),
+ port_command(Port, ""),
+ port_command(Port, ""),
+ port_command(Port, "")
+ end),
count_pp_sched_start(),
Proc4 ! Go,
wait_command_msgs(Port, 10),
@@ -2248,43 +2135,43 @@ consume_timeslice(Config) when is_list(Config) ->
%% If only one scheduler use port with parallelism set to true,
%% in order to trigger scheduling of command signals
Port2 = case SOnl of
- 1 ->
- Port ! {self(), close},
- receive {Port, closed} -> ok end,
- open_port({spawn, consume_timeslice_drv},
- [{parallelism, true}]);
- _ ->
- process_flag(scheduler, 1),
- 1 = erlang:system_info(scheduler_id),
- Port
- end,
+ 1 ->
+ Port ! {self(), close},
+ receive {Port, closed} -> ok end,
+ open_port({spawn, consume_timeslice_drv},
+ [{parallelism, true}]);
+ _ ->
+ process_flag(scheduler, 1),
+ 1 = erlang:system_info(scheduler_id),
+ Port
+ end,
count_pp_sched_start(),
"enabled" = port_control(Port2, $E, ""),
W5 = case SOnl of
- 1 ->
- false;
- _ ->
- W1= spawn_opt(fun () ->
- 2 = erlang:system_info(scheduler_id),
- "sleeped" = port_control(Port2, $S, "")
- end, [link,{scheduler,2}]),
- receive after 100 -> ok end,
- W1
- end,
+ 1 ->
+ false;
+ _ ->
+ W1= spawn_opt(fun () ->
+ 2 = erlang:system_info(scheduler_id),
+ "sleeped" = port_control(Port2, $S, "")
+ end, [link,{scheduler,2}]),
+ receive after 100 -> ok end,
+ W1
+ end,
Proc5 = spawn_opt(fun () ->
- receive Go -> ok end,
- 1 = erlang:system_info(scheduler_id),
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}}
- end, [link,{scheduler,1}]),
+ receive Go -> ok end,
+ 1 = erlang:system_info(scheduler_id),
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}}
+ end, [link,{scheduler,1}]),
receive after 100 -> ok end,
Proc5 ! Go,
wait_procs_exit([W5, Proc5]),
@@ -2292,34 +2179,34 @@ consume_timeslice(Config) when is_list(Config) ->
[{Port2, Sprt5}, {Proc5, Sproc5}] = count_pp_sched_stop([Port2, Proc5]),
?IN_RANGE(2, Sproc5, 3),
?IN_RANGE(6, Sprt5, 20),
-
+
count_pp_sched_start(),
"disabled" = port_control(Port2, $D, ""),
W6 = case SOnl of
- 1 ->
- false;
- _ ->
- W2= spawn_opt(fun () ->
- 2 = erlang:system_info(scheduler_id),
- "sleeped" = port_control(Port2, $S, "")
- end, [link,{scheduler,2}]),
- receive after 100 -> ok end,
- W2
- end,
+ 1 ->
+ false;
+ _ ->
+ W2= spawn_opt(fun () ->
+ 2 = erlang:system_info(scheduler_id),
+ "sleeped" = port_control(Port2, $S, "")
+ end, [link,{scheduler,2}]),
+ receive after 100 -> ok end,
+ W2
+ end,
Proc6 = spawn_opt(fun () ->
- receive Go -> ok end,
- 1 = erlang:system_info(scheduler_id),
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}},
- Port2 ! {Parent, {command, ""}}
- end, [link,{scheduler,1}]),
+ receive Go -> ok end,
+ 1 = erlang:system_info(scheduler_id),
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}},
+ Port2 ! {Parent, {command, ""}}
+ end, [link,{scheduler,1}]),
receive after 100 -> ok end,
Proc6 ! Go,
wait_procs_exit([W6, Proc6]),
@@ -2339,19 +2226,19 @@ wait_command_msgs(_, 0) ->
ok;
wait_command_msgs(Port, N) ->
receive
- {Port, command} ->
- wait_command_msgs(Port, N-1)
+ {Port, command} ->
+ wait_command_msgs(Port, N-1)
end.
in_range(Low, Val, High) when is_integer(Low),
- is_integer(Val),
- is_integer(High),
- Low =< Val,
- Val =< High ->
+ is_integer(Val),
+ is_integer(High),
+ Low =< Val,
+ Val =< High ->
true;
in_range(Low, Val, High) when is_integer(Low),
- is_integer(Val),
- is_integer(High) ->
+ is_integer(Val),
+ is_integer(High) ->
false.
count_pp_sched_start() ->
@@ -2364,7 +2251,7 @@ count_pp_sched_stop(Ps) ->
PNs = lists:map(fun (P) -> {P, 0} end, Ps),
receive {trace_delivered, all, Td} -> ok end,
Res = count_proc_sched(Ps, PNs),
- ?t:format("Scheduling counts: ~p~n", [Res]),
+ io:format("Scheduling counts: ~p~n", [Res]),
erlang:display({scheduling_counts, Res}),
Res.
@@ -2377,22 +2264,22 @@ do_inc_pn(P, [PN|PNs]) ->
inc_pn(P, PNs) ->
try
- do_inc_pn(P, PNs)
+ do_inc_pn(P, PNs)
catch
- throw:undefined -> PNs
+ throw:undefined -> PNs
end.
count_proc_sched(Ps, PNs) ->
receive
- TT when element(1, TT) == trace, element(3, TT) == in ->
-% erlang:display(TT),
- count_proc_sched(Ps, inc_pn(element(2, TT), PNs));
- TT when element(1, TT) == trace, element(3, TT) == out ->
- count_proc_sched(Ps, PNs)
+ TT when element(1, TT) == trace, element(3, TT) == in ->
+ % erlang:display(TT),
+ count_proc_sched(Ps, inc_pn(element(2, TT), PNs));
+ TT when element(1, TT) == trace, element(3, TT) == out ->
+ count_proc_sched(Ps, PNs)
after 0 ->
- PNs
+ PNs
end.
-
+
a_test(Config) when is_list(Config) ->
check_io_debug().
@@ -2405,13 +2292,35 @@ z_test(Config) when is_list(Config) ->
check_io_debug() ->
get_stable_check_io_info(),
- {NoErrorFds, NoUsedFds, NoDrvSelStructs, NoDrvEvStructs}
- = erts_debug:get_internal_state(check_io_debug),
+ {NoErrorFds, NoUsedFds, NoDrvSelStructs, NoDrvEvStructs} = CheckIoDebug
+ = erts_debug:get_internal_state(check_io_debug),
+ HasGetHost = has_gethost(),
+ ct:log("check_io_debug: ~p~n"
+ "HasGetHost: ~p",[CheckIoDebug, HasGetHost]),
0 = NoErrorFds,
- NoUsedFds = NoDrvSelStructs,
+ if
+ NoUsedFds == NoDrvSelStructs ->
+ ok;
+ HasGetHost andalso (NoUsedFds == (NoDrvSelStructs - 1)) ->
+ %% If the inet_gethost port is alive, we may have
+ %% one extra used fd that is not selected on
+ ok
+ end,
0 = NoDrvEvStructs,
ok.
+has_gethost() ->
+ has_gethost(erlang:ports()).
+has_gethost([P|T]) ->
+ case erlang:port_info(P, name) of
+ {name,"inet_gethost"++_} ->
+ true;
+ _ ->
+ has_gethost(T)
+ end;
+has_gethost([]) ->
+ false.
+
%flush_msgs() ->
% receive
% M ->
@@ -2426,26 +2335,26 @@ wait_procs_exit([]) ->
wait_procs_exit([P|Ps]) when is_pid(P) ->
Mon = erlang:monitor(process, P),
receive
- {'DOWN', Mon, process, P, _} ->
- wait_procs_exit(Ps)
+ {'DOWN', Mon, process, P, _} ->
+ wait_procs_exit(Ps)
end;
wait_procs_exit([_|Ps]) ->
wait_procs_exit(Ps).
get_port_msg(Port, Timeout) ->
receive
- {Port, What} ->
- {msg, What}
+ {Port, What} ->
+ {msg, What}
after Timeout ->
- no_msg
+ no_msg
end.
wait_until(Fun) ->
case Fun() of
- true -> ok;
- false ->
- receive after 100 -> ok end,
- wait_until(Fun)
+ true -> ok;
+ false ->
+ receive after 100 -> ok end,
+ wait_until(Fun)
end.
drv_vsn_str2tup(Str) ->
@@ -2476,11 +2385,11 @@ transform_bins(_Transform, Other) -> Other.
make_sub_binaries(Term) ->
MakeSub = fun(Bin0) ->
- Bin1 = <<243:8,0:3,Bin0/binary,31:5,19:8>>,
- Sz = size(Bin0),
- <<243:8,0:3,Bin:Sz/binary,31:5,19:8>> = id(Bin1),
- Bin
- end,
+ Bin1 = <<243:8,0:3,Bin0/binary,31:5,19:8>>,
+ Sz = size(Bin0),
+ <<243:8,0:3,Bin:Sz/binary,31:5,19:8>> = id(Bin1),
+ Bin
+ end,
transform_bins(MakeSub, Term).
id(I) -> I.
@@ -2512,14 +2421,7 @@ random_char() ->
uniform(256) - 1.
uniform(N) ->
- case get(random_seed) of
- undefined ->
- {X, Y, Z} = time(),
- random:seed(X, Y, Z);
- _ ->
- ok
- end,
- random:uniform(N).
+ rand:uniform(N).
erl_millisecs() ->
erl_millisecs(erlang:monotonic_time()).
@@ -2529,7 +2431,7 @@ erl_millisecs(MonotonicTime) ->
%% Start/stop drivers.
start_driver(Config, Name, Binary) ->
- Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
erl_ddll:start(),
%% Load the driver
@@ -2537,31 +2439,31 @@ start_driver(Config, Name, Binary) ->
%% open port.
case Binary of
- true ->
- open_port({spawn, Name}, [binary]);
- false ->
- open_port({spawn, Name}, [])
+ true ->
+ open_port({spawn, Name}, [binary]);
+ false ->
+ open_port({spawn, Name}, [])
end.
stop_driver(Port, Name) ->
- ?line true = erlang:port_close(Port),
+ true = erlang:port_close(Port),
receive
- {Port,Message} ->
- ?t:fail({strange_message_from_port,Message})
+ {Port,Message} ->
+ ct:fail({strange_message_from_port,Message})
after 0 ->
- ok
+ ok
end,
%% Unload the driver.
ok = erl_ddll:unload_driver(Name),
- ?line ok = erl_ddll:stop().
+ ok = erl_ddll:stop().
load_driver(Dir, Driver) ->
case erl_ddll:load_driver(Dir, Driver) of
- ok -> ok;
- {error, Error} = Res ->
- io:format("~s\n", [erl_ddll:format_error(Error)]),
- Res
+ ok -> ok;
+ {error, Error} = Res ->
+ io:format("~s\n", [erl_ddll:format_error(Error)]),
+ Res
end.
sleep() ->
@@ -2576,50 +2478,50 @@ sleep(Ms) when is_integer(Ms), Ms >= 0 ->
start_node(Config) when is_list(Config) ->
Pa = filename:dirname(code:which(?MODULE)),
Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(?config(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(seconds))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))),
- ?t:start_node(Name, slave, [{args, "-pa "++Pa}]).
+ ++ "-"
+ ++ atom_to_list(proplists:get_value(testcase, Config))
+ ++ "-"
+ ++ integer_to_list(erlang:system_time(seconds))
+ ++ "-"
+ ++ integer_to_list(erlang:unique_integer([positive]))),
+ test_server:start_node(Name, slave, [{args, "-pa "++Pa}]).
stop_node(Node) ->
- ?t:stop_node(Node).
+ test_server:stop_node(Node).
wait_deallocations() ->
try
- erts_debug:set_internal_state(wait, deallocations)
+ erts_debug:set_internal_state(wait, deallocations)
catch error:undef ->
- erts_debug:set_internal_state(available_internal_state, true),
- wait_deallocations()
+ erts_debug:set_internal_state(available_internal_state, true),
+ wait_deallocations()
end.
driver_alloc_size() ->
case erlang:system_info(smp_support) of
- true ->
- ok;
- false ->
- %% driver_alloc also used by elements in lock-free queues,
- %% give these some time to be deallocated...
- receive after 100 -> ok end
+ true ->
+ ok;
+ false ->
+ %% driver_alloc also used by elements in lock-free queues,
+ %% give these some time to be deallocated...
+ receive after 100 -> ok end
end,
wait_deallocations(),
case erlang:system_info({allocator_sizes, driver_alloc}) of
- false ->
- undefined;
- MemInfo ->
- CS = lists:foldl(
- fun ({instance, _, L}, Acc) ->
- {value,{_,MBCS}} = lists:keysearch(mbcs, 1, L),
- {value,{_,SBCS}} = lists:keysearch(sbcs, 1, L),
- [MBCS,SBCS | Acc]
- end,
- [],
- MemInfo),
- lists:foldl(
- fun(L, Sz0) ->
- {value,{_,Sz,_,_}} = lists:keysearch(blocks_size, 1, L),
- Sz0+Sz
- end, 0, CS)
+ false ->
+ undefined;
+ MemInfo ->
+ CS = lists:foldl(
+ fun ({instance, _, L}, Acc) ->
+ {value,{_,MBCS}} = lists:keysearch(mbcs, 1, L),
+ {value,{_,SBCS}} = lists:keysearch(sbcs, 1, L),
+ [MBCS,SBCS | Acc]
+ end,
+ [],
+ MemInfo),
+ lists:foldl(
+ fun(L, Sz0) ->
+ {value,{_,Sz,_,_}} = lists:keysearch(blocks_size, 1, L),
+ Sz0+Sz
+ end, 0, CS)
end.
diff --git a/erts/emulator/test/efile_SUITE.erl b/erts/emulator/test/efile_SUITE.erl
index 4d8d89db9b..cefa35a3ee 100644
--- a/erts/emulator/test/efile_SUITE.erl
+++ b/erts/emulator/test/efile_SUITE.erl
@@ -18,34 +18,18 @@
%% %CopyrightEnd%
-module(efile_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
+-export([all/0, suite/0]).
-export([iter_max_files/1, async_dist/1]).
-export([do_iter_max_files/2, do_async_dist/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[iter_max_files, async_dist].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
do_async_dist(Dir) ->
X = 100,
AT = erlang:system_info(thread_pool_size),
@@ -70,59 +54,58 @@ file_keys(Dir,Num,FdList,FnList) ->
Name = "dummy"++integer_to_list(Num),
FN = filename:join([Dir,Name]),
case file:open(FN,[write,raw]) of
- {ok,FD} ->
- {file_descriptor,prim_file,{Port,_}} = FD,
- <<X:32/integer-big>> =
- iolist_to_binary(erlang:port_control(Port,$K,[])),
- [X | file_keys(Dir,Num-1,[FD|FdList],[FN|FnList])];
- {error,_} ->
- % Try freeing up FD's if there are any
- case FdList of
- [] ->
- exit({cannot_open_file,FN});
- _ ->
- [ file:close(FD) || FD <- FdList ],
- [ file:delete(F) || F <- FnList ],
- file_keys(Dir,Num,[],[])
- end
+ {ok,FD} ->
+ {file_descriptor,prim_file,{Port,_}} = FD,
+ <<X:32/integer-big>> =
+ iolist_to_binary(erlang:port_control(Port,$K,[])),
+ [X | file_keys(Dir,Num-1,[FD|FdList],[FN|FnList])];
+ {error,_} ->
+ % Try freeing up FD's if there are any
+ case FdList of
+ [] ->
+ exit({cannot_open_file,FN});
+ _ ->
+ [ file:close(FD) || FD <- FdList ],
+ [ file:delete(F) || F <- FnList ],
+ file_keys(Dir,Num,[],[])
+ end
end.
-async_dist(doc) ->
- "Check that the distribution of files over async threads is fair";
+%% Check that the distribution of files over async threads is fair
async_dist(Config) when is_list(Config) ->
- DataDir = ?config(data_dir,Config),
+ DataDir = proplists:get_value(data_dir,Config),
TestFile = filename:join(DataDir, "existing_file"),
Dir = filename:dirname(code:which(?MODULE)),
AsyncSizes = [7,10,100,255,256,64,63,65],
Max = 0.5,
lists:foreach(fun(Size) ->
- {ok,Node} =
- test_server:start_node
- (test_iter_max_files,slave,
- [{args,
- "+A "++integer_to_list(Size)++
- " -pa " ++ Dir}]),
- {Distr,SD} = rpc:call(Node,?MODULE,do_async_dist,
- [DataDir]),
- test_server:stop_node(Node),
- if
- SD > Max ->
- io:format("Bad async queue distribution for "
- "~p async threads:~n"
- " Standard deviation is ~p~n"
- " Key distribution:~n ~lp~n",
- [Size,SD,Distr]),
- exit({bad_async_dist,Size,SD,Distr});
- true ->
- io:format("OK async queue distribution for "
- "~p async threads:~n"
- " Standard deviation is ~p~n"
- " Key distribution:~n ~lp~n",
- [Size,SD,Distr]),
- ok
- end
- end, AsyncSizes),
+ {ok,Node} =
+ test_server:start_node
+ (test_iter_max_files,slave,
+ [{args,
+ "+A "++integer_to_list(Size)++
+ " -pa " ++ Dir}]),
+ {Distr,SD} = rpc:call(Node,?MODULE,do_async_dist,
+ [DataDir]),
+ test_server:stop_node(Node),
+ if
+ SD > Max ->
+ io:format("Bad async queue distribution for "
+ "~p async threads:~n"
+ " Standard deviation is ~p~n"
+ " Key distribution:~n ~lp~n",
+ [Size,SD,Distr]),
+ exit({bad_async_dist,Size,SD,Distr});
+ true ->
+ io:format("OK async queue distribution for "
+ "~p async threads:~n"
+ " Standard deviation is ~p~n"
+ " Key distribution:~n ~lp~n",
+ [Size,SD,Distr]),
+ ok
+ end
+ end, AsyncSizes),
ok.
%%
@@ -130,54 +113,53 @@ async_dist(Config) when is_list(Config) ->
%% that we get the same number of files every time.
%%
-iter_max_files(suite) -> [];
iter_max_files(Config) when is_list(Config) ->
- DataDir = ?config(data_dir,Config),
+ DataDir = proplists:get_value(data_dir,Config),
TestFile = filename:join(DataDir, "existing_file"),
N = 10,
%% Run on a different node in order to set the max ports
Dir = filename:dirname(code:which(?MODULE)),
{ok,Node} = test_server:start_node(test_iter_max_files,slave,
- [{args,"+Q 1524 -pa " ++ Dir}]),
+ [{args,"+Q 1524 -pa " ++ Dir}]),
L = rpc:call(Node,?MODULE,do_iter_max_files,[N, TestFile]),
test_server:stop_node(Node),
io:format("Number of files opened in each test:~n~w\n", [L]),
all_equal(L),
Head = hd(L),
if Head >= 2 -> ok;
- true -> ?line test_server:fail(too_few_files)
+ true -> ct:fail(too_few_files)
end,
{comment, "Max files: " ++ integer_to_list(hd(L))}.
do_iter_max_files(N, Name) when N > 0 ->
- ?line [max_files(Name)| do_iter_max_files(N-1, Name)];
+ [max_files(Name)| do_iter_max_files(N-1, Name)];
do_iter_max_files(_, _) ->
[].
all_equal([E, E| T]) ->
- ?line all_equal([E| T]);
+ all_equal([E| T]);
all_equal([_]) ->
ok;
all_equal([]) ->
ok.
-
+
max_files(Name) ->
- ?line Fds = open_files(Name),
- ?line N = length(Fds),
- ?line close_files(Fds),
+ Fds = open_files(Name),
+ N = length(Fds),
+ close_files(Fds),
N.
close_files([Fd| Fds]) ->
- ?line file:close(Fd),
- ?line close_files(Fds);
+ file:close(Fd),
+ close_files(Fds);
close_files([]) ->
ok.
open_files(Name) ->
- ?line case file:open(Name, [read,raw]) of
- {ok, Fd} ->
- [Fd| open_files(Name)];
- {error, _Reason} ->
-% io:format("Error reason: ~p", [_Reason]),
- []
- end.
+ case file:open(Name, [read,raw]) of
+ {ok, Fd} ->
+ [Fd| open_files(Name)];
+ {error, _Reason} ->
+ % io:format("Error reason: ~p", [_Reason]),
+ []
+ end.
diff --git a/erts/emulator/test/emulator.spec.ose b/erts/emulator/test/emulator.spec.ose
deleted file mode 100644
index 9f494609d9..0000000000
--- a/erts/emulator/test/emulator.spec.ose
+++ /dev/null
@@ -1,2 +0,0 @@
-{topcase, {dir, "../emulator_test"}}.
-{skip, {obsolete_SUITE, "Not on ose"}}.
diff --git a/erts/emulator/test/erl_drv_thread_SUITE.erl b/erts/emulator/test/erl_drv_thread_SUITE.erl
index 2cd569ce4f..41a761229c 100644
--- a/erts/emulator/test/erl_drv_thread_SUITE.erl
+++ b/erts/emulator/test/erl_drv_thread_SUITE.erl
@@ -20,12 +20,11 @@
-module(erl_drv_thread_SUITE).
-author('[email protected]').
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
+-export([all/0, suite/0]).
-export([basic/1, rwlock/1, tsd/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(DEFAULT_TIMETRAP_SECS, 240).
@@ -34,38 +33,17 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[basic, rwlock, tsd].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% %%
%% Testcases %%
%% %%
-basic(suite) -> [];
-basic(doc) -> [];
-basic(Cfg) -> ?line drv_case(Cfg, basic).
+basic(Cfg) -> drv_case(Cfg, basic).
-rwlock(suite) -> [];
-rwlock(doc) -> [];
-rwlock(Cfg) -> ?line drv_case(Cfg, rwlock).
+rwlock(Cfg) -> drv_case(Cfg, rwlock).
-tsd(suite) -> [];
-tsd(doc) -> [];
-tsd(Cfg) -> ?line drv_case(Cfg, tsd).
+tsd(Cfg) -> drv_case(Cfg, tsd).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% %%
@@ -81,58 +59,54 @@ drv_case(Config, CaseName, Command) when is_list(Command) ->
drv_case(Config, CaseName, Command, ?DEFAULT_TIMETRAP_SECS).
drv_case(Config, CaseName, TimeTrap, Command) when is_list(Command),
- is_integer(TimeTrap) ->
+ is_integer(TimeTrap) ->
drv_case(Config, CaseName, Command, TimeTrap);
drv_case(Config, CaseName, Command, TimeTrap) when is_list(Config),
- is_atom(CaseName),
- is_list(Command),
- is_integer(TimeTrap) ->
- case ?t:os_type() of
- {Family, _} when Family == unix; Family == win32 ->
- ?line run_drv_case(Config, CaseName, Command, TimeTrap);
- SkipOs ->
- ?line {skipped,
- lists:flatten(["Not run on "
- | io_lib:format("~p",[SkipOs])])}
+ is_atom(CaseName),
+ is_list(Command),
+ is_integer(TimeTrap) ->
+ case test_server:os_type() of
+ {Family, _} when Family == unix; Family == win32 ->
+ run_drv_case(Config, CaseName, Command, TimeTrap);
+ SkipOs ->
+ {skipped, lists:flatten(["Not run on " | io_lib:format("~p",[SkipOs])])}
end.
run_drv_case(Config, CaseName, Command, TimeTrap) ->
- ?line Dog = test_server:timetrap(test_server:seconds(TimeTrap)),
- ?line DataDir = ?config(data_dir,Config),
+ ct:timetrap({seconds, TimeTrap}),
+ DataDir = proplists:get_value(data_dir,Config),
case erl_ddll:load_driver(DataDir, CaseName) of
- ok -> ok;
- {error, Error} ->
- io:format("~s\n", [erl_ddll:format_error(Error)]),
- ?line ?t:fail()
+ ok -> ok;
+ {error, Error} ->
+ ct:fail(erl_ddll:format_error(Error))
+ end,
+ Port = open_port({spawn, atom_to_list(CaseName)}, []),
+ true = is_port(Port),
+ Port ! {self(), {command, Command}},
+ Result = receive_drv_result(Port, CaseName),
+ Port ! {self(), close},
+ receive
+ {Port, closed} ->
+ ok
end,
- ?line Port = open_port({spawn, atom_to_list(CaseName)}, []),
- ?line true = is_port(Port),
- ?line Port ! {self(), {command, Command}},
- ?line Result = receive_drv_result(Port, CaseName),
- ?line Port ! {self(), close},
- ?line receive
- {Port, closed} ->
- ok
- end,
- ?line ok = erl_ddll:unload_driver(CaseName),
- ?line test_server:timetrap_cancel(Dog),
- ?line Result.
+ ok = erl_ddll:unload_driver(CaseName),
+ Result.
receive_drv_result(Port, CaseName) ->
- ?line receive
- {print, Port, CaseName, Str} ->
- ?line ?t:format("~s", [Str]),
- ?line receive_drv_result(Port, CaseName);
- {'EXIT', Port, Error} ->
- ?line ?t:fail(Error);
- {'EXIT', error, Error} ->
- ?line ?t:fail(Error);
- {failed, Port, CaseName, Comment} ->
- ?line ?t:fail(Comment);
- {skipped, Port, CaseName, Comment} ->
- ?line {skipped, Comment};
- {succeeded, Port, CaseName, ""} ->
- ?line succeeded;
- {succeeded, Port, CaseName, Comment} ->
- ?line {comment, Comment}
- end.
+ receive
+ {print, Port, CaseName, Str} ->
+ io:format("~s", [Str]),
+ receive_drv_result(Port, CaseName);
+ {'EXIT', Port, Error} ->
+ ct:fail(Error);
+ {'EXIT', error, Error} ->
+ ct:fail(Error);
+ {failed, Port, CaseName, Comment} ->
+ ct:fail(Comment);
+ {skipped, Port, CaseName, Comment} ->
+ {skipped, Comment};
+ {succeeded, Port, CaseName, ""} ->
+ succeeded;
+ {succeeded, Port, CaseName, Comment} ->
+ {comment, Comment}
+ end.
diff --git a/erts/emulator/test/erl_link_SUITE.erl b/erts/emulator/test/erl_link_SUITE.erl
index a7a45046ca..56fdfc35c0 100644
--- a/erts/emulator/test/erl_link_SUITE.erl
+++ b/erts/emulator/test/erl_link_SUITE.erl
@@ -29,24 +29,23 @@
-author('[email protected]').
%-define(line_trace, 1).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
+-export([all/0, suite/0, init_per_suite/1, end_per_suite/1]).
% Test cases
-export([links/1,
- dist_links/1,
- monitor_nodes/1,
- process_monitors/1,
- dist_process_monitors/1,
- busy_dist_port_monitor/1,
- busy_dist_port_link/1,
- otp_5772_link/1,
- otp_5772_dist_link/1,
- otp_5772_monitor/1,
- otp_5772_dist_monitor/1,
- otp_7946/1]).
+ dist_links/1,
+ monitor_nodes/1,
+ process_monitors/1,
+ dist_process_monitors/1,
+ busy_dist_port_monitor/1,
+ busy_dist_port_link/1,
+ otp_5772_link/1,
+ otp_5772_dist_link/1,
+ otp_5772_monitor/1,
+ otp_5772_dist_monitor/1,
+ otp_7946/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
@@ -65,21 +64,20 @@
-record(erl_link, {type = ?LINK_UNDEF,
- pid = [],
- targets = []}).
+ pid = [],
+ targets = []}).
% This is to be kept in sync with erl_bif_info.c (make_monitor_list)
--record(erl_monitor, {
- type, % MON_ORIGIN or MON_TARGET (1 or 3)
- ref,
- pid, % Process or nodename
- name = [] % registered name or []
- }).
+-record(erl_monitor, {type, % MON_ORIGIN or MON_TARGET (1 or 3)
+ ref,
+ pid, % Process or nodename
+ name = []}). % registered name or []
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 1}}].
all() ->
[links, dist_links, monitor_nodes, process_monitors,
@@ -87,8 +85,15 @@ all() ->
busy_dist_port_link, otp_5772_link, otp_5772_dist_link,
otp_5772_monitor, otp_5772_dist_monitor, otp_7946].
-groups() ->
- [].
+init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
+ case catch erts_debug:get_internal_state(available_internal_state) of
+ true -> ok;
+ _ -> erts_debug:set_internal_state(available_internal_state, true)
+ end,
+ Config.
+
+end_per_testcase(_Func, _Config) ->
+ ok.
init_per_suite(Config) ->
Config.
@@ -96,419 +101,397 @@ init_per_suite(Config) ->
end_per_suite(_Config) ->
catch erts_debug:set_internal_state(available_internal_state, false).
-init_per_group(_GroupName, Config) ->
- Config.
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-links(doc) -> ["Tests node local links"];
-links(suite) -> [];
+%% Tests node local links
links(Config) when is_list(Config) ->
- ?line common_link_test(node(), node()),
- ?line true = link(self()),
- ?line [] = find_erl_link(self(), ?LINK_PID, self()),
- ?line true = unlink(self()),
- ?line ok.
-
-dist_links(doc) -> ["Tests distributed links"];
-dist_links(suite) -> [];
+ common_link_test(node(), node()),
+ true = link(self()),
+ [] = find_erl_link(self(), ?LINK_PID, self()),
+ true = unlink(self()),
+ ok.
+
+%% Tests distributed links
dist_links(Config) when is_list(Config) ->
- ?line [NodeName] = get_names(1, dist_link),
- ?line {ok, Node} = start_node(NodeName),
- ?line common_link_test(node(), Node),
- ?line TP4 = spawn(?MODULE, test_proc, []),
- ?line TP5 = spawn(?MODULE, test_proc, []),
- ?line TP6 = spawn(Node, ?MODULE, test_proc, []),
- ?line true = tp_call(TP6, fun() -> link(TP4) end),
- ?line check_link(TP4, TP6),
- ?line true = tp_call(TP5,
- fun() ->
- process_flag(trap_exit,true),
- link(TP6)
- end),
- ?line check_link(TP5, TP6),
- ?line rpc:cast(Node, erlang, halt, []),
- ?line wait_until(fun () -> ?line is_proc_dead(TP4) end),
- ?line check_unlink(TP4, TP6),
- ?line true = tp_call(TP5,
- fun() ->
- receive
- {'EXIT', TP6, noconnection} ->
- true
- end
- end),
- ?line check_unlink(TP5, TP6),
- ?line tp_cast(TP5, fun() -> exit(normal) end),
- ?line ok.
+ [NodeName] = get_names(1, dist_link),
+ {ok, Node} = start_node(NodeName),
+ common_link_test(node(), Node),
+ TP4 = spawn(?MODULE, test_proc, []),
+ TP5 = spawn(?MODULE, test_proc, []),
+ TP6 = spawn(Node, ?MODULE, test_proc, []),
+ true = tp_call(TP6, fun() -> link(TP4) end),
+ check_link(TP4, TP6),
+ true = tp_call(TP5,
+ fun() ->
+ process_flag(trap_exit,true),
+ link(TP6)
+ end),
+ check_link(TP5, TP6),
+ rpc:cast(Node, erlang, halt, []),
+ wait_until(fun () -> is_proc_dead(TP4) end),
+ check_unlink(TP4, TP6),
+ true = tp_call(TP5,
+ fun() ->
+ receive
+ {'EXIT', TP6, noconnection} ->
+ true
+ end
+ end),
+ check_unlink(TP5, TP6),
+ tp_cast(TP5, fun() -> exit(normal) end),
+ ok.
common_link_test(NodeA, NodeB) ->
- ?line TP1 = spawn(NodeA, ?MODULE, test_proc, []),
- ?line check_unlink(TP1, self()),
- ?line TP2 = tp_call(TP1,
- fun () ->
- spawn_link(NodeB, ?MODULE, test_proc, [])
- end),
- ?line check_link(TP1, TP2),
- ?line true = tp_call(TP2, fun() -> unlink(TP1) end),
- ?line check_unlink(TP1, TP2),
- ?line true = tp_call(TP2, fun() -> link(TP1) end),
- ?line check_link(TP1, TP2),
- ?line false = tp_call(TP2, fun() -> process_flag(trap_exit, true) end),
- ?line tp_cast(TP1, fun () -> exit(died) end),
- ?line true = tp_call(TP2, fun() ->
- receive
- {'EXIT', TP1, died} ->
- true
- end
- end),
- ?line check_unlink(TP1, TP2),
- ?line TP3 = tp_call(TP2,
- fun () ->
- spawn_link(NodeA, ?MODULE, test_proc, [])
- end),
- ?line check_link(TP3, TP2),
- ?line tp_cast(TP2, fun() -> exit(died) end),
- ?line wait_until(fun () -> ?line is_proc_dead(TP3) end),
- ?line check_unlink(TP3, TP2),
- ?line ok.
-
-monitor_nodes(doc) -> ["Tests monitor of nodes"];
-monitor_nodes(suite) -> [];
+ TP1 = spawn(NodeA, ?MODULE, test_proc, []),
+ check_unlink(TP1, self()),
+ TP2 = tp_call(TP1,
+ fun () ->
+ spawn_link(NodeB, ?MODULE, test_proc, [])
+ end),
+ check_link(TP1, TP2),
+ true = tp_call(TP2, fun() -> unlink(TP1) end),
+ check_unlink(TP1, TP2),
+ true = tp_call(TP2, fun() -> link(TP1) end),
+ check_link(TP1, TP2),
+ false = tp_call(TP2, fun() -> process_flag(trap_exit, true) end),
+ tp_cast(TP1, fun () -> exit(died) end),
+ true = tp_call(TP2, fun() ->
+ receive
+ {'EXIT', TP1, died} ->
+ true
+ end
+ end),
+ check_unlink(TP1, TP2),
+ TP3 = tp_call(TP2,
+ fun () ->
+ spawn_link(NodeA, ?MODULE, test_proc, [])
+ end),
+ check_link(TP3, TP2),
+ tp_cast(TP2, fun() -> exit(died) end),
+ wait_until(fun () -> is_proc_dead(TP3) end),
+ check_unlink(TP3, TP2),
+ ok.
+
+%% Tests monitor of nodes
monitor_nodes(Config) when is_list(Config) ->
- ?line [An, Bn, Cn, Dn] = get_names(4, dist_link),
- ?line {ok, A} = start_node(An),
- ?line {ok, B} = start_node(Bn),
- ?line C = list_to_atom(lists:concat([Cn, "@", hostname()])),
- ?line D = list_to_atom(lists:concat([Dn, "@", hostname()])),
- ?line 0 = no_of_monitor_node(self(), A),
- ?line 0 = no_of_monitor_node(self(), B),
- ?line monitor_node(A, true),
- ?line monitor_node(B, true),
- ?line monitor_node(D, true),
- ?line monitor_node(D, true),
+ [An, Bn, Cn, Dn] = get_names(4, dist_link),
+ {ok, A} = start_node(An),
+ {ok, B} = start_node(Bn),
+ C = list_to_atom(lists:concat([Cn, "@", hostname()])),
+ D = list_to_atom(lists:concat([Dn, "@", hostname()])),
+ 0 = no_of_monitor_node(self(), A),
+ 0 = no_of_monitor_node(self(), B),
+ monitor_node(A, true),
+ monitor_node(B, true),
+ monitor_node(D, true),
+ monitor_node(D, true),
%% Has been known to crash the emulator.
- ?line {memory,_} = process_info(self(), memory),
-
- ?line monitor_node(A, false),
- ?line monitor_node(B, true),
- ?line monitor_node(C, true),
- ?line monitor_node(C, false),
- ?line monitor_node(C, true),
- ?line monitor_node(B, true),
- ?line monitor_node(A, false),
- ?line monitor_node(B, true),
- ?line monitor_node(B, false),
- ?line monitor_node(A, true),
- ?line check_monitor_node(self(), A, 1),
- ?line check_monitor_node(self(), B, 3),
- ?line check_monitor_node(self(), C, 0),
- ?line check_monitor_node(self(), D, 0),
- ?line receive {nodedown, C} -> ok end,
- ?line receive {nodedown, C} -> ok end,
- ?line receive {nodedown, C} -> ok end,
- ?line receive {nodedown, D} -> ok end,
- ?line receive {nodedown, D} -> ok end,
- ?line stop_node(A),
- ?line receive {nodedown, A} -> ok end,
- ?line check_monitor_node(self(), A, 0),
- ?line check_monitor_node(self(), B, 3),
- ?line stop_node(B),
- ?line receive {nodedown, B} -> ok end,
- ?line receive {nodedown, B} -> ok end,
- ?line receive {nodedown, B} -> ok end,
- ?line check_monitor_node(self(), B, 0),
- ?line receive
- {nodedown, X} ->
- ?line ?t:fail({unexpected_nodedown, X})
- after 0 ->
- ?line ok
- end,
- ?line ok.
-
-
-process_monitors(doc) -> ["Tests node local process monitors"];
-process_monitors(suite) -> [];
+ {memory,_} = process_info(self(), memory),
+
+ monitor_node(A, false),
+ monitor_node(B, true),
+ monitor_node(C, true),
+ monitor_node(C, false),
+ monitor_node(C, true),
+ monitor_node(B, true),
+ monitor_node(A, false),
+ monitor_node(B, true),
+ monitor_node(B, false),
+ monitor_node(A, true),
+ check_monitor_node(self(), A, 1),
+ check_monitor_node(self(), B, 3),
+ check_monitor_node(self(), C, 0),
+ check_monitor_node(self(), D, 0),
+ receive {nodedown, C} -> ok end,
+ receive {nodedown, C} -> ok end,
+ receive {nodedown, C} -> ok end,
+ receive {nodedown, D} -> ok end,
+ receive {nodedown, D} -> ok end,
+ stop_node(A),
+ receive {nodedown, A} -> ok end,
+ check_monitor_node(self(), A, 0),
+ check_monitor_node(self(), B, 3),
+ stop_node(B),
+ receive {nodedown, B} -> ok end,
+ receive {nodedown, B} -> ok end,
+ receive {nodedown, B} -> ok end,
+ check_monitor_node(self(), B, 0),
+ receive
+ {nodedown, X} ->
+ ct:fail({unexpected_nodedown, X})
+ after 0 ->
+ ok
+ end,
+ ok.
+
+
+%% Tests node local process monitors
process_monitors(Config) when is_list(Config) ->
- ?line common_process_monitors(node(), node()),
- ?line Mon1 = erlang:monitor(process,self()),
- ?line [] = find_erl_monitor(self(), Mon1),
- ?line [Name] = get_names(1, process_monitors),
- ?line true = register(Name, self()),
- ?line Mon2 = erlang:monitor(process, Name),
- ?line [] = find_erl_monitor(self(), Mon2),
- ?line receive
- {'DOWN', Mon1, _, _, _} = Msg ->
- ?line ?t:fail({unexpected_down_msg, Msg});
- {'DOWN', Mon2, _, _, _} = Msg ->
- ?line ?t:fail({unexpected_down_msg, Msg})
- after 500 ->
- ?line true = erlang:demonitor(Mon1),
- ?line true = erlang:demonitor(Mon2),
- ?line ok
- end.
-
-dist_process_monitors(doc) -> ["Tests distributed process monitors"];
-dist_process_monitors(suite) -> [];
+ common_process_monitors(node(), node()),
+ Mon1 = erlang:monitor(process,self()),
+ [] = find_erl_monitor(self(), Mon1),
+ [Name] = get_names(1, process_monitors),
+ true = register(Name, self()),
+ Mon2 = erlang:monitor(process, Name),
+ [] = find_erl_monitor(self(), Mon2),
+ receive
+ {'DOWN', Mon1, _, _, _} = Msg ->
+ ct:fail({unexpected_down_msg, Msg});
+ {'DOWN', Mon2, _, _, _} = Msg ->
+ ct:fail({unexpected_down_msg, Msg})
+ after 500 ->
+ true = erlang:demonitor(Mon1),
+ true = erlang:demonitor(Mon2),
+ ok
+ end.
+
+%% Tests distributed process monitors
dist_process_monitors(Config) when is_list(Config) ->
- ?line [Name] = get_names(1,dist_process_monitors),
- ?line {ok, Node} = start_node(Name),
- ?line common_process_monitors(node(), Node),
- ?line TP1 = spawn(Node, ?MODULE, test_proc, []),
- ?line R1 = erlang:monitor(process, TP1),
- ?line TP1O = get_down_object(TP1, self()),
- ?line check_process_monitor(self(), TP1, R1),
- ?line tp_cast(TP1, fun () -> halt() end),
- ?line receive
- {'DOWN',R1,process,TP1O,noconnection} ->
- ?line ok
- end,
- ?line check_process_demonitor(self(), TP1, R1),
- ?line R2 = erlang:monitor(process, TP1),
- ?line receive
- {'DOWN',R2,process,TP1O,noconnection} ->
- ?line ok
- end,
- ?line check_process_demonitor(self(), TP1, R2),
- ?line ok.
+ [Name] = get_names(1,dist_process_monitors),
+ {ok, Node} = start_node(Name),
+ common_process_monitors(node(), Node),
+ TP1 = spawn(Node, ?MODULE, test_proc, []),
+ R1 = erlang:monitor(process, TP1),
+ TP1O = get_down_object(TP1, self()),
+ check_process_monitor(self(), TP1, R1),
+ tp_cast(TP1, fun () -> halt() end),
+ receive
+ {'DOWN',R1,process,TP1O,noconnection} ->
+ ok
+ end,
+ check_process_demonitor(self(), TP1, R1),
+ R2 = erlang:monitor(process, TP1),
+ receive
+ {'DOWN',R2,process,TP1O,noconnection} ->
+ ok
+ end,
+ check_process_demonitor(self(), TP1, R2),
+ ok.
common_process_monitors(NodeA, NodeB) ->
- ?line TP1 = spawn(NodeA, ?MODULE, test_proc, []),
- ?line TP2 = spawn(NodeB, ?MODULE, test_proc, []),
- ?line run_common_process_monitors(TP1, TP2),
- ?line TP3 = spawn(NodeA, ?MODULE, test_proc, []),
- ?line TP4 = spawn(NodeB, ?MODULE, test_proc, []),
- ?line [TP4N] = get_names(1, common_process_monitors),
- ?line true = tp_call(TP4, fun () -> register(TP4N,self()) end),
- ?line run_common_process_monitors(TP3,
- case node() == node(TP4) of
- true -> TP4N;
- false -> {TP4N, node(TP4)}
- end),
- ?line ok.
+ TP1 = spawn(NodeA, ?MODULE, test_proc, []),
+ TP2 = spawn(NodeB, ?MODULE, test_proc, []),
+ run_common_process_monitors(TP1, TP2),
+ TP3 = spawn(NodeA, ?MODULE, test_proc, []),
+ TP4 = spawn(NodeB, ?MODULE, test_proc, []),
+ [TP4N] = get_names(1, common_process_monitors),
+ true = tp_call(TP4, fun () -> register(TP4N,self()) end),
+ run_common_process_monitors(TP3,
+ case node() == node(TP4) of
+ true -> TP4N;
+ false -> {TP4N, node(TP4)}
+ end),
+ ok.
run_common_process_monitors(TP1, TP2) ->
- ?line R1 = tp_call(TP1, fun () -> erlang:monitor(process, TP2) end),
- ?line check_process_monitor(TP1, TP2, R1),
-
- ?line tp_call(TP2, fun () -> catch erlang:demonitor(R1) end),
- ?line check_process_monitor(TP1, TP2, R1),
-
- ?line true = tp_call(TP1, fun () -> erlang:demonitor(R1) end),
- ?line check_process_demonitor(TP1, TP2, R1),
-
- ?line R2 = tp_call(TP1, fun () -> erlang:monitor(process, TP2) end),
- ?line TP2O = get_down_object(TP2, TP1),
- ?line check_process_monitor(TP1, TP2, R2),
- ?line tp_cast(TP2, fun () -> exit(bye) end),
- ?line wait_until(fun () -> ?line is_proc_dead(TP2) end),
- ?line ok = tp_call(TP1, fun () ->
- ?line receive
- {'DOWN',R2,process,TP2O,bye} ->
- ?line ok
- end
- end),
- ?line check_process_demonitor(TP1, TP2, R2),
-
- ?line R3 = tp_call(TP1, fun () -> erlang:monitor(process, TP2) end),
- ?line ok = tp_call(TP1, fun () ->
- ?line receive
- {'DOWN',R3,process,TP2O,noproc} ->
- ?line ok
- end
- end),
- ?line check_process_demonitor(TP1, TP2, R3),
-
- ?line tp_cast(TP1, fun () -> exit(normal) end),
- ?line wait_until(fun () -> ?line is_proc_dead(TP1) end),
- ?line ok.
-
-
-busy_dist_port_monitor(doc) -> ["Tests distributed monitor/2, demonitor/1, "
- "and 'DOWN' message over busy distribution "
- "port"];
-busy_dist_port_monitor(suite) -> [];
+ R1 = tp_call(TP1, fun () -> erlang:monitor(process, TP2) end),
+ check_process_monitor(TP1, TP2, R1),
+
+ tp_call(TP2, fun () -> catch erlang:demonitor(R1) end),
+ check_process_monitor(TP1, TP2, R1),
+
+ true = tp_call(TP1, fun () -> erlang:demonitor(R1) end),
+ check_process_demonitor(TP1, TP2, R1),
+
+ R2 = tp_call(TP1, fun () -> erlang:monitor(process, TP2) end),
+ TP2O = get_down_object(TP2, TP1),
+ check_process_monitor(TP1, TP2, R2),
+ tp_cast(TP2, fun () -> exit(bye) end),
+ wait_until(fun () -> is_proc_dead(TP2) end),
+ ok = tp_call(TP1, fun () ->
+ receive
+ {'DOWN',R2,process,TP2O,bye} ->
+ ok
+ end
+ end),
+ check_process_demonitor(TP1, TP2, R2),
+
+ R3 = tp_call(TP1, fun () -> erlang:monitor(process, TP2) end),
+ ok = tp_call(TP1, fun () ->
+ receive
+ {'DOWN',R3,process,TP2O,noproc} ->
+ ok
+ end
+ end),
+ check_process_demonitor(TP1, TP2, R3),
+
+ tp_cast(TP1, fun () -> exit(normal) end),
+ wait_until(fun () -> is_proc_dead(TP1) end),
+ ok.
+
+
+%% Tests distributed monitor/2, demonitor/1, and 'DOWN' message
+%% over busy distribution port
busy_dist_port_monitor(Config) when is_list(Config) ->
- ?line Tracer = case os:getenv("TRACE_BUSY_DIST_PORT") of
- "true" -> start_busy_dist_port_tracer();
- _ -> false
- end,
+ Tracer = case os:getenv("TRACE_BUSY_DIST_PORT") of
+ "true" -> start_busy_dist_port_tracer();
+ _ -> false
+ end,
- ?line [An] = get_names(1, busy_dist_port_monitor),
- ?line {ok, A} = start_node(An),
- ?line TP1 = spawn(A, ?MODULE, test_proc, []),
+ [An] = get_names(1, busy_dist_port_monitor),
+ {ok, A} = start_node(An),
+ TP1 = spawn(A, ?MODULE, test_proc, []),
%% Check monitor over busy port
- ?line M1 = suspend_on_busy_test(A,
- "erlang:monitor(process, TP1)",
- fun () -> erlang:monitor(process, TP1) end),
- ?line check_process_monitor(self(), TP1, M1),
+ M1 = suspend_on_busy_test(A,
+ "erlang:monitor(process, TP1)",
+ fun () -> erlang:monitor(process, TP1) end),
+ check_process_monitor(self(), TP1, M1),
%% Check demonitor over busy port
- ?line suspend_on_busy_test(A,
- "erlang:demonitor(M1)",
- fun () -> erlang:demonitor(M1) end),
- ?line check_process_demonitor(self(), TP1, M1),
+ suspend_on_busy_test(A,
+ "erlang:demonitor(M1)",
+ fun () -> erlang:demonitor(M1) end),
+ check_process_demonitor(self(), TP1, M1),
%% Check down message over busy port
- ?line TP2 = spawn(?MODULE, test_proc, []),
- ?line M2 = tp_call(TP1, fun () -> erlang:monitor(process, TP2) end),
- ?line check_process_monitor(TP1, TP2, M2),
- ?line Ref = make_ref(),
- ?line Busy = make_busy(A, 1000),
- ?line receive after 100 -> ok end,
- ?line tp_cast(TP2, fun () -> exit(Ref) end),
- ?line receive after 100 -> ok end,
- ?line unmake_busy(Busy),
- ?line Ref = tp_call(TP1, fun () ->
- receive
- {'DOWN', M2, process, TP2, Ref} ->
- Ref
- end
- end),
- ?line tp_cast(TP1, fun () -> exit(normal) end),
- ?line stop_node(A),
- ?line stop_busy_dist_port_tracer(Tracer),
- ?line ok.
-
-busy_dist_port_link(doc) -> ["Tests distributed link/1, unlink/1, and 'EXIT'",
- " message over busy distribution port"];
-busy_dist_port_link(suite) -> [];
+ TP2 = spawn(?MODULE, test_proc, []),
+ M2 = tp_call(TP1, fun () -> erlang:monitor(process, TP2) end),
+ check_process_monitor(TP1, TP2, M2),
+ Ref = make_ref(),
+ Busy = make_busy(A, 1000),
+ receive after 100 -> ok end,
+ tp_cast(TP2, fun () -> exit(Ref) end),
+ receive after 100 -> ok end,
+ unmake_busy(Busy),
+ Ref = tp_call(TP1, fun () ->
+ receive
+ {'DOWN', M2, process, TP2, Ref} ->
+ Ref
+ end
+ end),
+ tp_cast(TP1, fun () -> exit(normal) end),
+ stop_node(A),
+ stop_busy_dist_port_tracer(Tracer),
+ ok.
+
+%% Tests distributed link/1, unlink/1, and 'EXIT'
+%% message over busy distribution port
busy_dist_port_link(Config) when is_list(Config) ->
- ?line Tracer = case os:getenv("TRACE_BUSY_DIST_PORT") of
- "true" -> start_busy_dist_port_tracer();
- _ -> false
- end,
-
- ?line [An] = get_names(1, busy_dist_port_link),
- ?line {ok, A} = start_node(An),
- ?line TP1 = spawn(A, ?MODULE, test_proc, []),
+ Tracer = case os:getenv("TRACE_BUSY_DIST_PORT") of
+ "true" -> start_busy_dist_port_tracer();
+ _ -> false
+ end,
+
+ [An] = get_names(1, busy_dist_port_link),
+ {ok, A} = start_node(An),
+ TP1 = spawn(A, ?MODULE, test_proc, []),
%% Check link over busy port
- ?line suspend_on_busy_test(A,
- "link(TP1)",
- fun () -> link(TP1) end),
- ?line check_link(self(), TP1),
+ suspend_on_busy_test(A,
+ "link(TP1)",
+ fun () -> link(TP1) end),
+ check_link(self(), TP1),
%% Check unlink over busy port
- ?line suspend_on_busy_test(A,
- "unlink(TP1)",
- fun () -> unlink(TP1) end),
- ?line check_unlink(self(), TP1),
+ suspend_on_busy_test(A,
+ "unlink(TP1)",
+ fun () -> unlink(TP1) end),
+ check_unlink(self(), TP1),
%% Check trap exit message over busy port
- ?line TP2 = spawn(?MODULE, test_proc, []),
- ?line ok = tp_call(TP1, fun () ->
- process_flag(trap_exit, true),
- link(TP2),
- ok
- end),
- ?line check_link(TP1, TP2),
- ?line Ref = make_ref(),
- ?line Busy = make_busy(A, 1000),
- ?line receive after 100 -> ok end,
- ?line tp_cast(TP2, fun () -> exit(Ref) end),
- ?line receive after 100 -> ok end,
- ?line unmake_busy(Busy),
- ?line Ref = tp_call(TP1, fun () ->
- receive
- {'EXIT', TP2, Ref} ->
- Ref
- end
- end),
- ?line tp_cast(TP1, fun () -> exit(normal) end),
- ?line stop_node(A),
- ?line stop_busy_dist_port_tracer(Tracer),
- ?line ok.
-
-
-otp_5772_link(doc) -> [];
-otp_5772_link(suite) -> [];
+ TP2 = spawn(?MODULE, test_proc, []),
+ ok = tp_call(TP1, fun () ->
+ process_flag(trap_exit, true),
+ link(TP2),
+ ok
+ end),
+ check_link(TP1, TP2),
+ Ref = make_ref(),
+ Busy = make_busy(A, 1000),
+ receive after 100 -> ok end,
+ tp_cast(TP2, fun () -> exit(Ref) end),
+ receive after 100 -> ok end,
+ unmake_busy(Busy),
+ Ref = tp_call(TP1, fun () ->
+ receive
+ {'EXIT', TP2, Ref} ->
+ Ref
+ end
+ end),
+ tp_cast(TP1, fun () -> exit(normal) end),
+ stop_node(A),
+ stop_busy_dist_port_tracer(Tracer),
+ ok.
+
+
otp_5772_link(Config) when is_list(Config) ->
- ?line otp_5772_link_test(node()).
+ otp_5772_link_test(node()).
-otp_5772_dist_link(doc) -> [];
-otp_5772_dist_link(suite) -> [];
otp_5772_dist_link(Config) when is_list(Config) ->
- ?line [An] = get_names(1, otp_5772_dist_link),
- ?line {ok, A} = start_node(An),
- ?line otp_5772_link_test(A),
- ?line stop_node(A).
+ [An] = get_names(1, otp_5772_dist_link),
+ {ok, A} = start_node(An),
+ otp_5772_link_test(A),
+ stop_node(A).
otp_5772_link_test(Node) ->
- ?line Prio = process_flag(priority, high),
- ?line TE = process_flag(trap_exit, true),
- ?line TP1 = spawn_opt(Node, ?MODULE, test_proc, [],
- [link, {priority, low}]),
+ Prio = process_flag(priority, high),
+ TE = process_flag(trap_exit, true),
+ TP1 = spawn_opt(Node, ?MODULE, test_proc, [],
+ [link, {priority, low}]),
exit(TP1, bang),
unlink(TP1),
- ?line receive
- {'EXIT', TP1, _} ->
- ?line ok
- after 0 ->
- ?line ok
- end,
- ?line receive
- {'EXIT', TP1, _} = Exit ->
- ?line ?t:fail({got_late_exit_message, Exit})
- after 1000 ->
- ?line ok
- end,
- ?line process_flag(trap_exit, TE),
- ?line process_flag(priority, Prio),
- ?line ok.
-
-otp_5772_monitor(doc) -> [];
-otp_5772_monitor(suite) -> [];
+ receive
+ {'EXIT', TP1, _} ->
+ ok
+ after 0 ->
+ ok
+ end,
+ receive
+ {'EXIT', TP1, _} = Exit ->
+ ct:fail({got_late_exit_message, Exit})
+ after 1000 ->
+ ok
+ end,
+ process_flag(trap_exit, TE),
+ process_flag(priority, Prio),
+ ok.
+
otp_5772_monitor(Config) when is_list(Config) ->
- ?line otp_5772_monitor_test(node()).
+ otp_5772_monitor_test(node()).
-otp_5772_dist_monitor(doc) -> [];
-otp_5772_dist_monitor(suite) -> [];
otp_5772_dist_monitor(Config) when is_list(Config) ->
- ?line [An] = get_names(1, otp_5772_dist_monitor),
- ?line {ok, A} = start_node(An),
- ?line otp_5772_monitor_test(A),
- ?line stop_node(A),
- ?line ok.
+ [An] = get_names(1, otp_5772_dist_monitor),
+ {ok, A} = start_node(An),
+ otp_5772_monitor_test(A),
+ stop_node(A),
+ ok.
otp_5772_monitor_test(Node) ->
- ?line Prio = process_flag(priority, high),
- ?line TP1 = spawn_opt(Node, ?MODULE, test_proc, [], [{priority, low}]),
- ?line M1 = erlang:monitor(process, TP1),
- ?line exit(TP1, bang),
- ?line erlang:demonitor(M1),
- ?line receive
- {'DOWN', M1, _, _, _} ->
- ?line ok
- after 0 ->
- ?line ok
- end,
- ?line receive
- {'DOWN', M1, _, _, _} = Down ->
- ?line ?t:fail({got_late_down_message, Down})
- after 1000 ->
- ?line ok
- end,
- ?line process_flag(priority, Prio),
- ?line ok.
+ Prio = process_flag(priority, high),
+ TP1 = spawn_opt(Node, ?MODULE, test_proc, [], [{priority, low}]),
+ M1 = erlang:monitor(process, TP1),
+ exit(TP1, bang),
+ erlang:demonitor(M1),
+ receive
+ {'DOWN', M1, _, _, _} ->
+ ok
+ after 0 ->
+ ok
+ end,
+ receive
+ {'DOWN', M1, _, _, _} = Down ->
+ ct:fail({got_late_down_message, Down})
+ after 1000 ->
+ ok
+ end,
+ process_flag(priority, Prio),
+ ok.
otp_7946(Config) when is_list(Config) ->
- ?line [NodeName] = get_names(1, otp_7946),
- ?line {ok, Node} = start_node(NodeName),
- ?line Proc = rpc:call(Node, erlang, whereis, [net_kernel]),
- ?line Mon = erlang:monitor(process, Proc),
- ?line rpc:cast(Node, erlang, halt, []),
- ?line receive {'DOWN', Mon, process, Proc , _} -> ok end,
- ?line {Linker, LMon} = spawn_monitor(fun () ->
- link(Proc),
- receive
- after infinity -> ok
- end
- end),
- ?line receive
- {'DOWN', LMon, process, Linker, Reason} ->
- ?line ?t:format("Reason=~p~n", [Reason]),
- ?line Reason = noconnection
- end.
+ [NodeName] = get_names(1, otp_7946),
+ {ok, Node} = start_node(NodeName),
+ Proc = rpc:call(Node, erlang, whereis, [net_kernel]),
+ Mon = erlang:monitor(process, Proc),
+ rpc:cast(Node, erlang, halt, []),
+ receive {'DOWN', Mon, process, Proc , _} -> ok end,
+ {Linker, LMon} = spawn_monitor(fun () ->
+ link(Proc),
+ receive
+ after infinity -> ok
+ end
+ end),
+ receive
+ {'DOWN', LMon, process, Linker, Reason} ->
+ io:format("Reason=~p~n", [Reason]),
+ Reason = noconnection
+ end.
%%
%% -- Internal utils --------------------------------------------------------
@@ -519,27 +502,27 @@ otp_7946(Config) when is_list(Config) ->
busy_data() ->
case get(?BUSY_DATA_KEY) of
- undefined ->
- set_busy_data([]);
- Data ->
- true = is_binary(Data),
- true = size(Data) == ?BUSY_DATA_SIZE,
- Data
+ undefined ->
+ set_busy_data([]);
+ Data ->
+ true = is_binary(Data),
+ true = size(Data) == ?BUSY_DATA_SIZE,
+ Data
end.
set_busy_data(SetData) ->
case get(?BUSY_DATA_KEY) of
- undefined ->
- Data = case SetData of
- D when is_binary(D), size(D) == ?BUSY_DATA_SIZE ->
- SetData;
- _ ->
- list_to_binary(lists:duplicate(?BUSY_DATA_SIZE, 253))
- end,
- put(?BUSY_DATA_KEY, Data),
- Data;
- OldData ->
- OldData
+ undefined ->
+ Data = case SetData of
+ D when is_binary(D), size(D) == ?BUSY_DATA_SIZE ->
+ SetData;
+ _ ->
+ list_to_binary(lists:duplicate(?BUSY_DATA_SIZE, 253))
+ end,
+ put(?BUSY_DATA_KEY, Data),
+ Data;
+ OldData ->
+ OldData
end.
freeze_node(Node, MS) ->
@@ -547,13 +530,13 @@ freeze_node(Node, MS) ->
DoingIt = make_ref(),
Freezer = self(),
spawn_link(Node,
- fun () ->
- erts_debug:set_internal_state(available_internal_state,
- true),
- dport_send(Freezer, DoingIt),
- receive after Own -> ok end,
- erts_debug:set_internal_state(block, MS+Own)
- end),
+ fun () ->
+ erts_debug:set_internal_state(available_internal_state,
+ true),
+ dport_send(Freezer, DoingIt),
+ receive after Own -> ok end,
+ erts_debug:set_internal_state(block, MS+Own)
+ end),
receive DoingIt -> ok end,
receive after Own -> ok end.
@@ -563,27 +546,27 @@ make_busy(Node, Time) when is_integer(Time) ->
Data = busy_data(),
%% first make port busy
Pid = spawn_link(fun () ->
- forever(fun () ->
- dport_reg_send(Node,
- '__noone__',
- Data)
- end)
- end),
+ forever(fun () ->
+ dport_reg_send(Node,
+ '__noone__',
+ Data)
+ end)
+ end),
receive after Own -> ok end,
wait_until(fun () ->
- case process_info(Pid, status) of
- {status, suspended} -> true;
- _ -> false
- end
- end),
+ case process_info(Pid, status) of
+ {status, suspended} -> true;
+ _ -> false
+ end
+ end),
%% then dist entry
make_busy(Node, [nosuspend], Data),
Pid.
make_busy(Node, Opts, Data) ->
case erlang:send({'__noone__', Node}, Data, Opts) of
- nosuspend -> nosuspend;
- _ -> make_busy(Node, Opts, Data)
+ nosuspend -> nosuspend;
+ _ -> make_busy(Node, Opts, Data)
end.
unmake_busy(Pid) ->
@@ -596,33 +579,33 @@ suspend_on_busy_test(Node, Doing, Fun) ->
Done = make_ref(),
Data = busy_data(),
spawn_link(fun () ->
- set_busy_data(Data),
- Busy = make_busy(Node, 1000),
- Tester ! DoIt,
- receive after 100 -> ok end,
- Info = process_info(Tester, [status, current_function]),
- unmake_busy(Busy),
- ?t:format("~p doing ~s: ~p~n", [Tester, Doing, Info]),
- Tester ! {Done, Info}
- end),
+ set_busy_data(Data),
+ Busy = make_busy(Node, 1000),
+ Tester ! DoIt,
+ receive after 100 -> ok end,
+ Info = process_info(Tester, [status, current_function]),
+ unmake_busy(Busy),
+ io:format("~p doing ~s: ~p~n", [Tester, Doing, Info]),
+ Tester ! {Done, Info}
+ end),
receive DoIt -> ok end,
Res = Fun(),
receive
- {Done, MyInfo} ->
- %% Don't match arity; it is different in
- %% debug and optimized emulator
- [{status, suspended},
- {current_function, {erlang, bif_return_trap, _}}] = MyInfo,
- ok
+ {Done, MyInfo} ->
+ %% Don't match arity; it is different in
+ %% debug and optimized emulator
+ [{status, suspended},
+ {current_function, {erlang, bif_return_trap, _}}] = MyInfo,
+ ok
end,
Res.
% get_node(Name) when is_atom(Name) ->
-% ?line node();
+% node();
% get_node({Name, Node}) when is_atom(Name) ->
-% ?line Node;
+% Node;
% get_node(NC) when is_pid(NC); is_port(NC); is_reference(NC) ->
-% ?line node(NC).
+% node(NC).
get_down_object(Item, _) when is_pid(Item) ->
Item;
@@ -637,90 +620,78 @@ get_down_object(Item, Watcher) when is_atom(Item), is_atom(Watcher) ->
is_proc_dead(P) ->
case is_proc_alive(P) of
- true -> false;
- false -> true
+ true -> false;
+ false -> true
end.
is_proc_alive(Pid) when is_pid(Pid), node(Pid) == node() ->
- ?line is_process_alive(Pid);
+ is_process_alive(Pid);
is_proc_alive(Name) when is_atom(Name) ->
- ?line case catch whereis(Name) of
- Pid when is_pid(Pid) ->
- ?line is_proc_alive(Pid);
- _ ->
- ?line false
- end;
+ case catch whereis(Name) of
+ Pid when is_pid(Pid) ->
+ is_proc_alive(Pid);
+ _ ->
+ false
+ end;
is_proc_alive({Name, Node}) when is_atom(Name), Node == node() ->
- ?line is_proc_alive(Name);
+ is_proc_alive(Name);
is_proc_alive(Proc) ->
- ?line is_remote_proc_alive(Proc).
+ is_remote_proc_alive(Proc).
is_remote_proc_alive({Name, Node}) when is_atom(Name), is_atom(Node) ->
- ?line is_remote_proc_alive(Name, Node);
+ is_remote_proc_alive(Name, Node);
is_remote_proc_alive(Pid) when is_pid(Pid) ->
- ?line is_remote_proc_alive(Pid, node(Pid));
+ is_remote_proc_alive(Pid, node(Pid));
is_remote_proc_alive(_) ->
- ?line false.
+ false.
is_remote_proc_alive(PN, Node) ->
- ?line S = self(),
- ?line R = make_ref(),
- ?line monitor_node(Node, true),
- ?line _P = spawn(Node, fun () -> S ! {R, is_proc_alive(PN)} end),
- ?line receive
- {R, Bool} ->
- ?line monitor_node(Node, false),
- ?line Bool;
- {nodedown, Node} ->
- ?line false
- end.
+ S = self(),
+ R = make_ref(),
+ monitor_node(Node, true),
+ _P = spawn(Node, fun () -> S ! {R, is_proc_alive(PN)} end),
+ receive
+ {R, Bool} ->
+ monitor_node(Node, false),
+ Bool;
+ {nodedown, Node} ->
+ false
+ end.
wait_until(Fun) ->
- ?line case Fun() of
- true ->
- ?line ok;
- _ ->
- ?line receive
- after 100 ->
- ?line wait_until(Fun)
- end
- end.
+ case Fun() of
+ true ->
+ ok;
+ _ ->
+ receive
+ after 100 ->
+ wait_until(Fun)
+ end
+ end.
forever(Fun) ->
Fun(),
forever(Fun).
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:minutes(1)),
- case catch erts_debug:get_internal_state(available_internal_state) of
- true -> ok;
- _ -> erts_debug:set_internal_state(available_internal_state, true)
- end,
- ?line [{watchdog, Dog}|Config].
-
-end_per_testcase(_Func, Config) ->
- ?line Dog = ?config(watchdog, Config),
- ?line ?t:timetrap_cancel(Dog).
-
tp_call(Tp, Fun) ->
- ?line R = make_ref(),
- ?line Tp ! {call, self(), R, Fun},
- ?line receive
- {R, Res} ->
- ?line Res
- end.
+ R = make_ref(),
+ Tp ! {call, self(), R, Fun},
+ receive
+ {R, Res} ->
+ Res
+ end.
tp_cast(Tp, Fun) ->
- ?line Tp ! {cast, Fun}.
+ Tp ! {cast, Fun}.
test_proc() ->
- ?line receive
- {call, From, Ref, Fun} ->
- ?line From ! {Ref, Fun()};
- {cast, Fun} ->
- ?line Fun()
- end,
- ?line test_proc().
+ receive
+ {call, From, Ref, Fun} ->
+ From ! {Ref, Fun()};
+ {cast, Fun} ->
+ Fun()
+ end,
+ test_proc().
expand_link_list([#erl_link{type = ?LINK_NODE, targets = N} = Rec | T]) ->
lists:duplicate(N,Rec#erl_link{targets = []}) ++ expand_link_list(T);
@@ -728,7 +699,7 @@ expand_link_list([#erl_link{targets = [#erl_link{pid = Pid}]} = Rec | T]) ->
[Rec#erl_link{targets = [Pid]} | expand_link_list(T)];
expand_link_list([#erl_link{targets = [#erl_link{pid = Pid}|TT]} = Rec | T]) ->
[ Rec#erl_link{targets = [Pid]} | expand_link_list(
- [Rec#erl_link{targets = TT} | T])];
+ [Rec#erl_link{targets = TT} | T])];
expand_link_list([#erl_link{targets = []} = Rec | T]) ->
[Rec | expand_link_list(T)];
expand_link_list([]) ->
@@ -736,19 +707,19 @@ expand_link_list([]) ->
get_local_link_list(Obj) ->
case catch erts_debug:get_internal_state({link_list, Obj}) of
- LL when is_list(LL) ->
- expand_link_list(LL);
- _ ->
- []
+ LL when is_list(LL) ->
+ expand_link_list(LL);
+ _ ->
+ []
end.
get_remote_link_list(Node, Obj) ->
case catch rpc:call(Node, erts_debug, get_internal_state,
- [{link_list, Obj}]) of
- LL when is_list(LL) ->
- expand_link_list(LL);
- _ ->
- []
+ [{link_list, Obj}]) of
+ LL when is_list(LL) ->
+ expand_link_list(LL);
+ _ ->
+ []
end.
@@ -758,30 +729,30 @@ get_link_list({Node, DistEntry}) when is_atom(Node), is_atom(DistEntry) ->
get_remote_link_list(Node, DistEntry);
get_link_list(P) when is_pid(P); is_port(P) ->
case node(P) of
- Node when Node == node() ->
- get_local_link_list(P);
- Node ->
- get_remote_link_list(Node, P)
- end;
+ Node when Node == node() ->
+ get_local_link_list(P);
+ Node ->
+ get_remote_link_list(Node, P)
+ end;
get_link_list(undefined) ->
[].
get_local_monitor_list(Obj) ->
case catch erts_debug:get_internal_state({monitor_list, Obj}) of
- LL when is_list(LL) ->
- LL;
- _ ->
- []
- end.
+ LL when is_list(LL) ->
+ LL;
+ _ ->
+ []
+ end.
get_remote_monitor_list(Node, Obj) ->
case catch rpc:call(Node, erts_debug, get_internal_state,
- [{monitor_list, Obj}]) of
- LL when is_list(LL) ->
- LL;
- _ ->
- []
- end.
+ [{monitor_list, Obj}]) of
+ LL when is_list(LL) ->
+ LL;
+ _ ->
+ []
+ end.
get_monitor_list({Node, DistEntry}) when Node == node(), is_atom(DistEntry) ->
@@ -790,242 +761,242 @@ get_monitor_list({Node, DistEntry}) when is_atom(Node), is_atom(DistEntry) ->
get_remote_monitor_list(Node, DistEntry);
get_monitor_list(P) when is_pid(P) ->
case node(P) of
- Node when Node == node() ->
- get_local_monitor_list(P);
- Node ->
- get_remote_monitor_list(Node, P)
- end;
+ Node when Node == node() ->
+ get_local_monitor_list(P);
+ Node ->
+ get_remote_monitor_list(Node, P)
+ end;
get_monitor_list(undefined) ->
[].
find_erl_monitor(Pid, Ref) when is_reference(Ref) ->
lists:foldl(fun (#erl_monitor{ref = R} = EL, Acc) when R == Ref ->
- [EL|Acc];
- (_, Acc) ->
- Acc
- end,
- [],
- get_monitor_list(Pid)).
+ [EL|Acc];
+ (_, Acc) ->
+ Acc
+ end,
+ [],
+ get_monitor_list(Pid)).
% find_erl_link(Obj, Ref) when is_reference(Ref) ->
-% ?line lists:foldl(fun (#erl_link{ref = R} = EL, Acc) when R == Ref ->
-% ?line [EL|Acc];
+% lists:foldl(fun (#erl_link{ref = R} = EL, Acc) when R == Ref ->
+% [EL|Acc];
% (_, Acc) ->
-% ?line Acc
+% Acc
% end,
% [],
% get_link_list(Obj)).
find_erl_link(Obj, Type, [Item, Data]) when is_pid(Item);
- is_port(Item);
- is_atom(Item) ->
+ is_port(Item);
+ is_atom(Item) ->
lists:foldl(fun (#erl_link{type = T, pid = I, targets = D} = EL,
- Acc) when T == Type, I == Item ->
- case Data of
- D ->
- [EL|Acc];
- [] ->
- [EL|Acc];
- _ ->
- Acc
- end;
- (_, Acc) ->
- Acc
- end,
- [],
- get_link_list(Obj));
+ Acc) when T == Type, I == Item ->
+ case Data of
+ D ->
+ [EL|Acc];
+ [] ->
+ [EL|Acc];
+ _ ->
+ Acc
+ end;
+ (_, Acc) ->
+ Acc
+ end,
+ [],
+ get_link_list(Obj));
find_erl_link(Obj, Type, Item) when is_pid(Item); is_port(Item); is_atom(Item) ->
find_erl_link(Obj, Type, [Item, []]).
-
+
check_link(A, B) ->
- ?line [#erl_link{type = ?LINK_PID,
- pid = B,
- targets = []}] = find_erl_link(A, ?LINK_PID, B),
- ?line [#erl_link{type = ?LINK_PID,
- pid = A,
- targets = []}] = find_erl_link(B, ?LINK_PID, A),
- ?line case node(A) == node(B) of
- false ->
- ?line [#erl_link{type = ?LINK_PID,
- pid = A,
- targets = [B]}] = find_erl_link({node(A),
- node(B)},
- ?LINK_PID,
- [A, [B]]),
- ?line [#erl_link{type = ?LINK_PID,
- pid = B,
- targets = [A]}] = find_erl_link({node(B),
- node(A)},
- ?LINK_PID,
- [B, [A]]);
- true ->
- ?line [] = find_erl_link({node(A), node(B)},
- ?LINK_PID,
- [A, [B]]),
- ?line [] = find_erl_link({node(B), node(A)},
- ?LINK_PID,
- [B, [A]])
- end,
- ?line ok.
+ [#erl_link{type = ?LINK_PID,
+ pid = B,
+ targets = []}] = find_erl_link(A, ?LINK_PID, B),
+ [#erl_link{type = ?LINK_PID,
+ pid = A,
+ targets = []}] = find_erl_link(B, ?LINK_PID, A),
+ case node(A) == node(B) of
+ false ->
+ [#erl_link{type = ?LINK_PID,
+ pid = A,
+ targets = [B]}] = find_erl_link({node(A),
+ node(B)},
+ ?LINK_PID,
+ [A, [B]]),
+ [#erl_link{type = ?LINK_PID,
+ pid = B,
+ targets = [A]}] = find_erl_link({node(B),
+ node(A)},
+ ?LINK_PID,
+ [B, [A]]);
+ true ->
+ [] = find_erl_link({node(A), node(B)},
+ ?LINK_PID,
+ [A, [B]]),
+ [] = find_erl_link({node(B), node(A)},
+ ?LINK_PID,
+ [B, [A]])
+ end,
+ ok.
check_unlink(A, B) ->
- ?line [] = find_erl_link(A, ?LINK_PID, B),
- ?line [] = find_erl_link(B, ?LINK_PID, A),
- ?line [] = find_erl_link({node(A), node(B)}, ?LINK_PID, [A, [B]]),
- ?line [] = find_erl_link({node(B), node(A)}, ?LINK_PID, [B, [A]]),
- ?line ok.
+ [] = find_erl_link(A, ?LINK_PID, B),
+ [] = find_erl_link(B, ?LINK_PID, A),
+ [] = find_erl_link({node(A), node(B)}, ?LINK_PID, [A, [B]]),
+ [] = find_erl_link({node(B), node(A)}, ?LINK_PID, [B, [A]]),
+ ok.
check_process_monitor(From, {Name, Node}, Ref) when is_pid(From),
- is_atom(Name),
- Node == node(From),
- is_reference(Ref) ->
- ?line check_process_monitor(From, Name, Ref);
+ is_atom(Name),
+ Node == node(From),
+ is_reference(Ref) ->
+ check_process_monitor(From, Name, Ref);
check_process_monitor(From, {Name, Node}, Ref) when is_pid(From),
- is_atom(Name),
- is_atom(Node),
- is_reference(Ref) ->
- ?line MonitoredPid = rpc:call(Node, erlang, whereis, [Name]),
- ?line [#erl_monitor{type = ?MON_ORIGIN,
- ref = Ref,
- pid = Node,
- name = Name}] = find_erl_monitor(From, Ref),
- ?line [#erl_monitor{type = ?MON_TARGET,
- ref = Ref,
- pid = From,
- name = Name}] = find_erl_monitor({node(From), Node}, Ref),
- ?line [#erl_monitor{type = ?MON_ORIGIN,
- ref = Ref,
- pid = MonitoredPid,
- name = Name}] = find_erl_monitor({Node, node(From)}, Ref),
- ?line [#erl_monitor{type = ?MON_TARGET,
- ref = Ref,
- pid = From,
- name = Name}] = find_erl_monitor(MonitoredPid, Ref),
- ?line ok;
+ is_atom(Name),
+ is_atom(Node),
+ is_reference(Ref) ->
+ MonitoredPid = rpc:call(Node, erlang, whereis, [Name]),
+ [#erl_monitor{type = ?MON_ORIGIN,
+ ref = Ref,
+ pid = Node,
+ name = Name}] = find_erl_monitor(From, Ref),
+ [#erl_monitor{type = ?MON_TARGET,
+ ref = Ref,
+ pid = From,
+ name = Name}] = find_erl_monitor({node(From), Node}, Ref),
+ [#erl_monitor{type = ?MON_ORIGIN,
+ ref = Ref,
+ pid = MonitoredPid,
+ name = Name}] = find_erl_monitor({Node, node(From)}, Ref),
+ [#erl_monitor{type = ?MON_TARGET,
+ ref = Ref,
+ pid = From,
+ name = Name}] = find_erl_monitor(MonitoredPid, Ref),
+ ok;
check_process_monitor(From, Name, Ref) when is_pid(From),
- is_atom(Name),
- undefined /= Name,
- is_reference(Ref) ->
- ?line MonitoredPid = rpc:call(node(From), erlang, whereis, [Name]),
-
- ?line [#erl_monitor{type = ?MON_ORIGIN,
- ref = Ref,
- pid = MonitoredPid,
- name = Name}] = find_erl_monitor(From, Ref),
-
-
- ?line [#erl_monitor{type = ?MON_TARGET,
- ref = Ref,
- pid = From,
- name = Name}] = find_erl_monitor(MonitoredPid,Ref),
+ is_atom(Name),
+ undefined /= Name,
+ is_reference(Ref) ->
+ MonitoredPid = rpc:call(node(From), erlang, whereis, [Name]),
+
+ [#erl_monitor{type = ?MON_ORIGIN,
+ ref = Ref,
+ pid = MonitoredPid,
+ name = Name}] = find_erl_monitor(From, Ref),
+
+
+ [#erl_monitor{type = ?MON_TARGET,
+ ref = Ref,
+ pid = From,
+ name = Name}] = find_erl_monitor(MonitoredPid,Ref),
ok;
check_process_monitor(From, To, Ref) when is_pid(From),
- is_pid(To),
- is_reference(Ref) ->
- ?line OriMon = [#erl_monitor{type = ?MON_ORIGIN,
- ref = Ref,
- pid = To}],
-
- ?line OriMon = find_erl_monitor(From, Ref),
-
- ?line TargMon = [#erl_monitor{type = ?MON_TARGET,
- ref = Ref,
- pid = From}],
- ?line TargMon = find_erl_monitor(To, Ref),
-
-
- ?line case node(From) == node(To) of
- false ->
- ?line TargMon = find_erl_monitor({node(From), node(To)}, Ref),
- ?line OriMon = find_erl_monitor({node(To), node(From)}, Ref);
- true ->
- ?line [] = find_erl_monitor({node(From), node(From)}, Ref)
- end,
- ?line ok.
+ is_pid(To),
+ is_reference(Ref) ->
+ OriMon = [#erl_monitor{type = ?MON_ORIGIN,
+ ref = Ref,
+ pid = To}],
+
+ OriMon = find_erl_monitor(From, Ref),
+
+ TargMon = [#erl_monitor{type = ?MON_TARGET,
+ ref = Ref,
+ pid = From}],
+ TargMon = find_erl_monitor(To, Ref),
+
+
+ case node(From) == node(To) of
+ false ->
+ TargMon = find_erl_monitor({node(From), node(To)}, Ref),
+ OriMon = find_erl_monitor({node(To), node(From)}, Ref);
+ true ->
+ [] = find_erl_monitor({node(From), node(From)}, Ref)
+ end,
+ ok.
check_process_demonitor(From, {undefined, Node}, Ref) when is_pid(From),
- is_reference(Ref) ->
- ?line [] = find_erl_monitor(From, Ref),
- ?line case node(From) == Node of
- false ->
- ?line [] = find_erl_monitor({node(From), Node}, Ref),
- ?line [] = find_erl_monitor({Node, node(From)}, Ref);
- true ->
- ?line [] = find_erl_monitor({Node, Node}, Ref)
- end,
- ?line ok;
+ is_reference(Ref) ->
+ [] = find_erl_monitor(From, Ref),
+ case node(From) == Node of
+ false ->
+ [] = find_erl_monitor({node(From), Node}, Ref),
+ [] = find_erl_monitor({Node, node(From)}, Ref);
+ true ->
+ [] = find_erl_monitor({Node, Node}, Ref)
+ end,
+ ok;
check_process_demonitor(From, {Name, Node}, Ref) when is_pid(From),
- is_atom(Name),
- Node == node(From),
- is_reference(Ref) ->
- ?line MonitoredPid = rpc:call(Node, erlang, whereis, [Name]),
- ?line case rpc:call(Node, erlang, whereis, [Name]) of
- undefined ->
- ?line check_process_demonitor(From, {undefined, Node}, Ref);
- MonitoredPid ->
- ?line check_process_demonitor(From, MonitoredPid, Ref)
- end;
+ is_atom(Name),
+ Node == node(From),
+ is_reference(Ref) ->
+ MonitoredPid = rpc:call(Node, erlang, whereis, [Name]),
+ case rpc:call(Node, erlang, whereis, [Name]) of
+ undefined ->
+ check_process_demonitor(From, {undefined, Node}, Ref);
+ MonitoredPid ->
+ check_process_demonitor(From, MonitoredPid, Ref)
+ end;
check_process_demonitor(From, {Name, Node}, Ref) when is_pid(From),
- is_atom(Name),
- is_atom(Node),
- is_reference(Ref) ->
- ?line MonitoredPid = rpc:call(Node, erlang, whereis, [Name]),
- ?line [] = find_erl_monitor(From, Ref),
- ?line [] = find_erl_monitor({node(From), Node}, Ref),
- ?line [] = find_erl_monitor({Node, node(From)}, Ref),
- ?line [] = find_erl_monitor(MonitoredPid, Ref),
- ?line ok;
+ is_atom(Name),
+ is_atom(Node),
+ is_reference(Ref) ->
+ MonitoredPid = rpc:call(Node, erlang, whereis, [Name]),
+ [] = find_erl_monitor(From, Ref),
+ [] = find_erl_monitor({node(From), Node}, Ref),
+ [] = find_erl_monitor({Node, node(From)}, Ref),
+ [] = find_erl_monitor(MonitoredPid, Ref),
+ ok;
check_process_demonitor(From, undefined, Ref) when is_pid(From),
- is_reference(Ref) ->
- ?line [] = find_erl_monitor(From, Ref),
- ?line case node(From) == node() of
- false ->
- ?line [] = find_erl_monitor({node(From), node()}, Ref),
- ?line [] = find_erl_monitor({node(), node(From)}, Ref);
- true ->
- ?line [] = find_erl_monitor({node(), node()}, Ref)
- end,
- ?line ok;
+ is_reference(Ref) ->
+ [] = find_erl_monitor(From, Ref),
+ case node(From) == node() of
+ false ->
+ [] = find_erl_monitor({node(From), node()}, Ref),
+ [] = find_erl_monitor({node(), node(From)}, Ref);
+ true ->
+ [] = find_erl_monitor({node(), node()}, Ref)
+ end,
+ ok;
check_process_demonitor(From, Name, Ref) when is_pid(From),
- is_atom(Name),
- undefined /= Name,
- is_reference(Ref) ->
- ?line check_process_demonitor(From, {Name, node()}, Ref);
+ is_atom(Name),
+ undefined /= Name,
+ is_reference(Ref) ->
+ check_process_demonitor(From, {Name, node()}, Ref);
check_process_demonitor(From, To, Ref) when is_pid(From),
- is_pid(To),
- is_reference(Ref) ->
- ?line [] = find_erl_monitor(From, Ref),
- ?line [] = find_erl_monitor(To, Ref),
- ?line case node(From) == node(To) of
- false ->
- ?line [] = find_erl_monitor({node(From), node(To)}, Ref),
- ?line [] = find_erl_monitor({node(To), node(From)}, Ref);
- true ->
- ?line [] = find_erl_monitor({node(From), node(From)}, Ref)
- end,
- ?line ok.
+ is_pid(To),
+ is_reference(Ref) ->
+ [] = find_erl_monitor(From, Ref),
+ [] = find_erl_monitor(To, Ref),
+ case node(From) == node(To) of
+ false ->
+ [] = find_erl_monitor({node(From), node(To)}, Ref),
+ [] = find_erl_monitor({node(To), node(From)}, Ref);
+ true ->
+ [] = find_erl_monitor({node(From), node(From)}, Ref)
+ end,
+ ok.
no_of_monitor_node(From, Node) when is_pid(From), is_atom(Node) ->
- ?line length(find_erl_link(From, ?LINK_NODE, Node)).
+ length(find_erl_link(From, ?LINK_NODE, Node)).
check_monitor_node(From, Node, No) when is_pid(From),
- is_atom(Node),
- is_integer(No),
- No >= 0 ->
- ?line LL = lists:duplicate(No, #erl_link{type = ?LINK_NODE, pid = Node}),
- ?line DLL = lists:duplicate(No, #erl_link{type = ?LINK_NODE, pid = From}),
- ?line LL = find_erl_link(From, ?LINK_NODE, Node),
- ?line DLL = find_erl_link({node(From), Node}, ?LINK_NODE, From),
- ?line ok.
+ is_atom(Node),
+ is_integer(No),
+ No >= 0 ->
+ LL = lists:duplicate(No, #erl_link{type = ?LINK_NODE, pid = Node}),
+ DLL = lists:duplicate(No, #erl_link{type = ?LINK_NODE, pid = From}),
+ LL = find_erl_link(From, ?LINK_NODE, Node),
+ DLL = find_erl_link({node(From), Node}, ?LINK_NODE, From),
+ ok.
hostname() ->
- ?line from($@, atom_to_list(node())).
+ from($@, atom_to_list(node())).
from(H, [H | T]) -> T;
from(H, [_ | T]) -> from(H, T);
@@ -1037,27 +1008,27 @@ get_names(0, _, Acc) ->
Acc;
get_names(N, T, Acc) ->
get_names(N-1, T, [list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(T)
- ++ "-"
- ++ integer_to_list(erlang:system_time(seconds))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))) | Acc]).
+ ++ "-"
+ ++ atom_to_list(T)
+ ++ "-"
+ ++ integer_to_list(erlang:system_time(seconds))
+ ++ "-"
+ ++ integer_to_list(erlang:unique_integer([positive]))) | Acc]).
start_node(Name) ->
- ?line start_node(Name, "").
+ start_node(Name, "").
start_node(Name, Args) ->
- ?line Pa = filename:dirname(code:which(?MODULE)),
- ?line Res = ?t:start_node(Name, slave, [{args, Args ++ " -pa " ++ Pa}]),
- ?line {ok, Node} = Res,
- ?line rpc:call(Node, erts_debug, set_internal_state,
- [available_internal_state, true]),
- ?line Res.
-
+ Pa = filename:dirname(code:which(?MODULE)),
+ Res = test_server:start_node(Name, slave, [{args, Args ++ " -pa " ++ Pa}]),
+ {ok, Node} = Res,
+ rpc:call(Node, erts_debug, set_internal_state,
+ [available_internal_state, true]),
+ Res.
+
stop_node(Node) ->
- ?line ?t:stop_node(Node).
+ test_server:stop_node(Node).
-define(COOKIE, '').
-define(DOP_LINK, 1).
@@ -1080,37 +1051,37 @@ stop_node(Node) ->
dport_send(To, Msg) ->
Node = node(To),
DPrt = case dport(Node) of
- undefined ->
- pong = net_adm:ping(Node),
- dport(Node);
- Prt ->
- Prt
- end,
+ undefined ->
+ pong = net_adm:ping(Node),
+ dport(Node);
+ Prt ->
+ Prt
+ end,
port_command(DPrt, [dmsg_hdr(),
- dmsg_ext({?DOP_SEND,
- ?COOKIE,
- To}),
- dmsg_ext(Msg)]).
+ dmsg_ext({?DOP_SEND,
+ ?COOKIE,
+ To}),
+ dmsg_ext(Msg)]).
dport_reg_send(Node, Name, Msg) ->
DPrt = case dport(Node) of
- undefined ->
- pong = net_adm:ping(Node),
- dport(Node);
- Prt ->
- Prt
- end,
+ undefined ->
+ pong = net_adm:ping(Node),
+ dport(Node);
+ Prt ->
+ Prt
+ end,
port_command(DPrt, [dmsg_hdr(),
- dmsg_ext({?DOP_REG_SEND,
- self(),
- ?COOKIE,
- Name}),
- dmsg_ext(Msg)]).
+ dmsg_ext({?DOP_REG_SEND,
+ self(),
+ ?COOKIE,
+ Name}),
+ dmsg_ext(Msg)]).
dport(Node) when is_atom(Node) ->
case catch erts_debug:get_internal_state(available_internal_state) of
- true -> true;
- _ -> erts_debug:set_internal_state(available_internal_state, true)
+ true -> true;
+ _ -> erts_debug:set_internal_state(available_internal_state, true)
end,
erts_debug:get_internal_state({dist_port, Node}).
@@ -1136,11 +1107,7 @@ stop_busy_dist_port_tracer(_) ->
busy_dist_port_tracer() ->
receive
- {monitor, _SuspendedProcess, busy_dist_port, _Port} = M ->
- erlang:display(M),
- busy_dist_port_tracer()
+ {monitor, _SuspendedProcess, busy_dist_port, _Port} = M ->
+ erlang:display(M),
+ busy_dist_port_tracer()
end.
-
-
-
-
diff --git a/erts/emulator/test/erts_debug_SUITE.erl b/erts/emulator/test/erts_debug_SUITE.erl
index 35677f9953..e757ebdb3d 100644
--- a/erts/emulator/test/erts_debug_SUITE.erl
+++ b/erts/emulator/test/erts_debug_SUITE.erl
@@ -19,42 +19,18 @@
%%
-module(erts_debug_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2,
- test_size/1,flat_size_big/1,df/1,
+-export([all/0, suite/0,
+ test_size/1,flat_size_big/1,df/1,term_type/1,
instructions/1]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 2}}].
all() ->
- [test_size, flat_size_big, df, instructions].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?t:timetrap(?t:minutes(2)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
+ [test_size, flat_size_big, df, instructions, term_type].
test_size(Config) when is_list(Config) ->
ConsCell1 = id([a|b]),
@@ -138,9 +114,50 @@ flat_size_big_1(Term, Size0, Limit) when Size0 < Limit ->
end;
flat_size_big_1(_, _, _) -> ok.
+
+term_type(Config) when is_list(Config) ->
+ Ts = [{fixnum, 1},
+ {fixnum, -1},
+ {bignum, 1 bsl 300},
+ {bignum, -(1 bsl 300)},
+ {hfloat, 0.0},
+ {hfloat, 0.0/-1},
+ {hfloat, 1.0/(1 bsl 302)},
+ {hfloat, 1.0*(1 bsl 302)},
+ {hfloat, -1.0/(1 bsl 302)},
+ {hfloat, -1.0*(1 bsl 302)},
+ {hfloat, 3.1416},
+ {hfloat, 1.0e18},
+ {hfloat, -3.1416},
+ {hfloat, -1.0e18},
+
+ {heap_binary, <<1,2,3>>},
+ {refc_binary, <<0:(8*80)>>},
+ {sub_binary, <<5:7>>},
+
+ {flatmap, #{ a => 1}},
+ {hashmap, maps:from_list([{I,I}||I <- lists:seq(1,76)])},
+
+ {list, [1,2,3]},
+ {nil, []},
+ {tuple, {1,2,3}},
+ {tuple, {}},
+
+ {export, fun lists:sort/1},
+ {'fun', fun() -> ok end},
+ {pid, self()},
+ {atom, atom}],
+ lists:foreach(fun({E,Val}) ->
+ R = erts_internal:term_type(Val),
+ io:format("expecting term type ~w, got ~w (~p)~n", [E,R,Val]),
+ E = R
+ end, Ts),
+ ok.
+
+
df(Config) when is_list(Config) ->
P0 = pps(),
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ok = file:set_cwd(PrivDir),
AllLoaded = [M || {M,_} <- code:all_loaded()],
diff --git a/erts/emulator/test/estone_SUITE.erl b/erts/emulator/test/estone_SUITE.erl
index d49ab3de4d..93728b299b 100644
--- a/erts/emulator/test/estone_SUITE.erl
+++ b/erts/emulator/test/estone_SUITE.erl
@@ -19,9 +19,8 @@
-module(estone_SUITE).
%% Test functions
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,estone/1,estone_bench/1]).
--export([init_per_testcase/2, end_per_testcase/2]).
+-export([all/0, suite/0, groups/0,
+ estone/1, estone_bench/1]).
%% Internal exports for EStone tests
-export([lists/1,
@@ -46,12 +45,9 @@
run_micro/3,p1/1,ppp/3,macro/2,micros/0]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("common_test/include/ct_event.hrl").
-%% Test suite defines
--define(default_timeout, ?t:minutes(10)).
-
%% EStone defines
-define(TOTAL, (3000 * 1000 * 100)). %% 300 secs
-define(BIGPROCS, 2).
@@ -66,17 +62,9 @@
str}). %% Header string
-
-
-init_per_testcase(_Case, Config) ->
- ?line Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
- ok.
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 4}}].
all() ->
[estone].
@@ -84,34 +72,18 @@ all() ->
groups() ->
[{estone_bench, [{repeat,50}],[estone_bench]}].
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-estone(suite) ->
- [];
-estone(doc) ->
- ["EStone Test"];
+%% EStone Test
estone(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line Mhz=get_cpu_speed(os:type(),DataDir),
- ?line L = ?MODULE:macro(?MODULE:micros(),DataDir),
- ?line {Total, Stones} = sum_micros(L, 0, 0),
- ?line pp(Mhz,Total,Stones,L),
- ?line {comment,Mhz ++ " MHz, " ++
- integer_to_list(Stones) ++ " ESTONES"}.
+ DataDir = proplists:get_value(data_dir,Config),
+ Mhz=get_cpu_speed(os:type(),DataDir),
+ L = ?MODULE:macro(?MODULE:micros(),DataDir),
+ {Total, Stones} = sum_micros(L, 0, 0),
+ pp(Mhz,Total,Stones,L),
+ {comment,Mhz ++ " MHz, " ++ integer_to_list(Stones) ++ " ESTONES"}.
estone_bench(Config) ->
- DataDir = ?config(data_dir,Config),
+ DataDir = proplists:get_value(data_dir,Config),
L = ?MODULE:macro(?MODULE:micros(),DataDir),
[ct_event:notify(
#event{name = benchmark_data,
@@ -1136,4 +1108,3 @@ wait_for_pids([P|Tail]) ->
send_procs([P|Tail], Msg) -> P ! Msg, send_procs(Tail, Msg);
send_procs([], _) -> ok.
-
diff --git a/erts/emulator/test/evil_SUITE.erl b/erts/emulator/test/evil_SUITE.erl
index 484d2a8bf5..5f5a0ef305 100644
--- a/erts/emulator/test/evil_SUITE.erl
+++ b/erts/emulator/test/evil_SUITE.erl
@@ -19,23 +19,22 @@
-module(evil_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2,
- heap_frag/1,
- encode_decode_ext/1,
- decode_integer_ext/1,
- decode_small_big_ext/1,
- decode_large_big_ext/1,
- decode_small_big_ext_neg/1,
- decode_large_big_ext_neg/1,
- decode_too_small/1,
- decode_pos_neg_zero/1
- ]).
-
--include_lib("test_server/include/test_server.hrl").
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+-export([all/0, suite/0,
+ heap_frag/1,
+ encode_decode_ext/1,
+ decode_integer_ext/1,
+ decode_small_big_ext/1,
+ decode_large_big_ext/1,
+ decode_small_big_ext_neg/1,
+ decode_large_big_ext_neg/1,
+ decode_too_small/1,
+ decode_pos_neg_zero/1]).
+
+-include_lib("common_test/include/ct.hrl").
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {seconds, 30}}].
all() ->
[heap_frag, encode_decode_ext, decode_integer_ext,
@@ -43,41 +42,16 @@ all() ->
decode_small_big_ext_neg, decode_large_big_ext_neg,
decode_too_small, decode_pos_neg_zero].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(_Case, Config) ->
- ?line Dog = test_server:timetrap(?t:minutes(0.5)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
heap_frag(Config) when is_list(Config) ->
N = 512,
Self = self(),
- ?line Pid = spawn_link(fun() -> appender(Self, N) end),
+ Pid = spawn_link(fun() -> appender(Self, N) end),
receive
- {Pid,Res} ->
- ?line Res = my_appender(N);
- Garbage ->
- io:format("Garbage: ~p\n", [Garbage]),
- ?line ?t:fail(got_garbage)
+ {Pid,Res} ->
+ Res = my_appender(N);
+ Garbage ->
+ io:format("Garbage: ~p\n", [Garbage]),
+ ct:fail(got_garbage)
end.
@@ -87,29 +61,28 @@ heap_frag(Config) when is_list(Config) ->
%% These test cases are not "evil" but the next test case is....
encode_decode_ext(Config) when is_list(Config) ->
- ?line enc_dec( 2, 0), % SMALL_INTEGER_EXT smallest
- ?line enc_dec( 2, 255), % SMALL_INTEGER_EXT largest
- ?line enc_dec( 5, 256), % INTEGER_EXT smallest pos (*)
- ?line enc_dec( 5, -1), % INTEGER_EXT largest neg
-
- ?line enc_dec( 5, 16#07ffffff), % INTEGER_EXT largest (28 bits)
- ?line enc_dec( 5,-16#08000000), % INTEGER_EXT smallest
- ?line enc_dec( 7, 16#08000000), % SMALL_BIG_EXT smallest pos(*)
- ?line enc_dec( 7,-16#08000001), % SMALL_BIG_EXT largest neg (*)
-
- ?line enc_dec( 7, 16#7fffffff), % SMALL_BIG_EXT largest i32
- ?line enc_dec( 7,-16#80000000), % SMALL_BIG_EXT smallest i32
-
- ?line enc_dec( 7, 16#80000000), % SMALL_BIG_EXT u32
- ?line enc_dec( 7, 16#ffffffff), % SMALL_BIG_EXT largest u32
-
- ?line enc_dec( 9, 16#7fffffffffff), % largest i48
- ?line enc_dec( 9,-16#800000000000), % smallest i48
- ?line enc_dec( 9, 16#ffffffffffff), % largest u48
- ?line enc_dec(11, 16#7fffffffffffffff), % largest i64
- ?line enc_dec(11,-16#8000000000000000), % smallest i64
- ?line enc_dec(11, 16#ffffffffffffffff), % largest u64
-
+ enc_dec( 2, 0), % SMALL_INTEGER_EXT smallest
+ enc_dec( 2, 255), % SMALL_INTEGER_EXT largest
+ enc_dec( 5, 256), % INTEGER_EXT smallest pos (*)
+ enc_dec( 5, -1), % INTEGER_EXT largest neg
+
+ enc_dec( 5, 16#07ffffff), % INTEGER_EXT largest (28 bits)
+ enc_dec( 5,-16#08000000), % INTEGER_EXT smallest
+ enc_dec( 7, 16#08000000), % SMALL_BIG_EXT smallest pos(*)
+ enc_dec( 7,-16#08000001), % SMALL_BIG_EXT largest neg (*)
+
+ enc_dec( 7, 16#7fffffff), % SMALL_BIG_EXT largest i32
+ enc_dec( 7,-16#80000000), % SMALL_BIG_EXT smallest i32
+
+ enc_dec( 7, 16#80000000), % SMALL_BIG_EXT u32
+ enc_dec( 7, 16#ffffffff), % SMALL_BIG_EXT largest u32
+
+ enc_dec( 9, 16#7fffffffffff), % largest i48
+ enc_dec( 9,-16#800000000000), % smallest i48
+ enc_dec( 9, 16#ffffffffffff), % largest u48
+ enc_dec(11, 16#7fffffffffffffff), % largest i64
+ enc_dec(11,-16#8000000000000000), % smallest i64
+ enc_dec(11, 16#ffffffffffffffff), % largest u64
ok.
@@ -125,213 +98,213 @@ encode_decode_ext(Config) when is_list(Config) ->
%% erl_interface, i.e. not how it is encoded in the test case below.
decode_integer_ext(Config) when is_list(Config) ->
- ?line decode( 0, <<131,98, 0:32>>), % SMALL_INTEGER_EXT
- ?line decode( 42, <<131,98, 42:32>>), % SMALL_INTEGER_EXT
- ?line decode(255, <<131,98,255:32>>), % SMALL_INTEGER_EXT
- ?line decode( 16#08000000, <<131,98, 16#08000000:32>>), % SMALL_BIG_EXT
- ?line decode(-16#08000001, <<131,98,-16#08000001:32>>), % SMALL_BIG_EXT
- ?line decode( 16#7fffffff, <<131,98, 16#7fffffff:32>>), % SMALL_BIG_EXT
- ?line decode(-16#80000000, <<131,98,-16#80000000:32>>), % SMALL_BIG_EXT
+ decode( 0, <<131,98, 0:32>>), % SMALL_INTEGER_EXT
+ decode( 42, <<131,98, 42:32>>), % SMALL_INTEGER_EXT
+ decode(255, <<131,98,255:32>>), % SMALL_INTEGER_EXT
+ decode( 16#08000000, <<131,98, 16#08000000:32>>), % SMALL_BIG_EXT
+ decode(-16#08000001, <<131,98,-16#08000001:32>>), % SMALL_BIG_EXT
+ decode( 16#7fffffff, <<131,98, 16#7fffffff:32>>), % SMALL_BIG_EXT
+ decode(-16#80000000, <<131,98,-16#80000000:32>>), % SMALL_BIG_EXT
ok.
decode_small_big_ext(Config) when is_list(Config) ->
- ?line decode(256,<<131,110,2,0,0,1>>), % INTEGER_EXT
- ?line decode(16#07ffffff,<<131,110,4,0,255,255,255,7>>), % INTEGER_EXT
- ?line decode(16#7fffffff,<<131,110,4,0,255,255,255,127>>), % SMALL_BIG_EXT
-
- ?line decode(42,<<131,110,1,0,42>>), % SMALL_INTEGER_EXT
- ?line decode(42,<<131,110,2,0,42,0>>), % Redundant zeros from now on
- ?line decode(42,<<131,110,3,0,42,0,0>>),
- ?line decode(42,<<131,110,4,0,42,0,0,0>>),
- ?line decode(42,<<131,110,5,0,42,0,0,0,0>>),
- ?line decode(42,<<131,110,6,0,42,0,0,0,0,0>>),
- ?line decode(42,<<131,110,7,0,42,0,0,0,0,0,0>>),
- ?line decode(42,<<131,110,8,0,42,0,0,0,0,0,0,0>>),
+ decode(256,<<131,110,2,0,0,1>>), % INTEGER_EXT
+ decode(16#07ffffff,<<131,110,4,0,255,255,255,7>>), % INTEGER_EXT
+ decode(16#7fffffff,<<131,110,4,0,255,255,255,127>>), % SMALL_BIG_EXT
+
+ decode(42,<<131,110,1,0,42>>), % SMALL_INTEGER_EXT
+ decode(42,<<131,110,2,0,42,0>>), % Redundant zeros from now on
+ decode(42,<<131,110,3,0,42,0,0>>),
+ decode(42,<<131,110,4,0,42,0,0,0>>),
+ decode(42,<<131,110,5,0,42,0,0,0,0>>),
+ decode(42,<<131,110,6,0,42,0,0,0,0,0>>),
+ decode(42,<<131,110,7,0,42,0,0,0,0,0,0>>),
+ decode(42,<<131,110,8,0,42,0,0,0,0,0,0,0>>),
ok.
decode_large_big_ext(Config) when is_list(Config) ->
- ?line decode(256,<<131,111,2:32,0,0,1>>), % INTEGER_EXT
- ?line decode(16#07ffffff,<<131,111,4:32,0,255,255,255,7>>), % INTEG_EXT
- ?line decode(16#7fffffff,<<131,111,4:32,0,255,255,255,127>>), % SMA_BIG
- ?line decode(16#ffffffff,<<131,111,4:32,0,255,255,255,255>>), % SMA_BIG
+ decode(256,<<131,111,2:32,0,0,1>>), % INTEGER_EXT
+ decode(16#07ffffff,<<131,111,4:32,0,255,255,255,7>>), % INTEG_EXT
+ decode(16#7fffffff,<<131,111,4:32,0,255,255,255,127>>), % SMA_BIG
+ decode(16#ffffffff,<<131,111,4:32,0,255,255,255,255>>), % SMA_BIG
N = largest_small_big(),
- ?line decode(N,<<131,111,255:32,0,N:2040/little>>), % SMALL_BIG_EXT
-
- ?line decode(42,<<131,111,1:32,0,42>>),
- ?line decode(42,<<131,111,2:32,0,42,0>>), % Redundant zeros from now on
- ?line decode(42,<<131,111,3:32,0,42,0,0>>),
- ?line decode(42,<<131,111,4:32,0,42,0,0,0>>),
- ?line decode(42,<<131,111,5:32,0,42,0,0,0,0>>),
- ?line decode(42,<<131,111,6:32,0,42,0,0,0,0,0>>),
- ?line decode(42,<<131,111,7:32,0,42,0,0,0,0,0,0>>),
- ?line decode(42,<<131,111,8:32,0,42,0,0,0,0,0,0,0>>),
+ decode(N,<<131,111,255:32,0,N:2040/little>>), % SMALL_BIG_EXT
+
+ decode(42,<<131,111,1:32,0,42>>),
+ decode(42,<<131,111,2:32,0,42,0>>), % Redundant zeros from now on
+ decode(42,<<131,111,3:32,0,42,0,0>>),
+ decode(42,<<131,111,4:32,0,42,0,0,0>>),
+ decode(42,<<131,111,5:32,0,42,0,0,0,0>>),
+ decode(42,<<131,111,6:32,0,42,0,0,0,0,0>>),
+ decode(42,<<131,111,7:32,0,42,0,0,0,0,0,0>>),
+ decode(42,<<131,111,8:32,0,42,0,0,0,0,0,0,0>>),
ok.
decode_small_big_ext_neg(Config) when is_list(Config) ->
- ?line decode(-1,<<131,110,1,1,1>>), % INTEGER_EXT
- ?line decode(-16#08000000,<<131,110,4,1,0,0,0,8>>), % INTEGER_EXT
- ?line decode(-16#80000000,<<131,110,4,1,0,0,0,128>>), % SMALL_BIG_EXT
- ?line decode(-16#ffffffff,<<131,110,4,1,255,255,255,255>>), % SMALL_BIG_EXT
+ decode(-1,<<131,110,1,1,1>>), % INTEGER_EXT
+ decode(-16#08000000,<<131,110,4,1,0,0,0,8>>), % INTEGER_EXT
+ decode(-16#80000000,<<131,110,4,1,0,0,0,128>>), % SMALL_BIG_EXT
+ decode(-16#ffffffff,<<131,110,4,1,255,255,255,255>>), % SMALL_BIG_EXT
N = largest_small_big(),
- ?line decode(-N,<<131,111,255:32,1,N:2040/little>>), % SMALL_BIG_EXT
-
- ?line decode(-42,<<131,110,1,1,42>>),
- ?line decode(-42,<<131,110,2,1,42,0>>), % Redundant zeros from now on
- ?line decode(-42,<<131,110,3,1,42,0,0>>),
- ?line decode(-42,<<131,110,4,1,42,0,0,0>>),
- ?line decode(-42,<<131,110,5,1,42,0,0,0,0>>),
- ?line decode(-42,<<131,110,6,1,42,0,0,0,0,0>>),
- ?line decode(-42,<<131,110,7,1,42,0,0,0,0,0,0>>),
- ?line decode(-42,<<131,110,8,1,42,0,0,0,0,0,0,0>>),
+ decode(-N,<<131,111,255:32,1,N:2040/little>>), % SMALL_BIG_EXT
+
+ decode(-42,<<131,110,1,1,42>>),
+ decode(-42,<<131,110,2,1,42,0>>), % Redundant zeros from now on
+ decode(-42,<<131,110,3,1,42,0,0>>),
+ decode(-42,<<131,110,4,1,42,0,0,0>>),
+ decode(-42,<<131,110,5,1,42,0,0,0,0>>),
+ decode(-42,<<131,110,6,1,42,0,0,0,0,0>>),
+ decode(-42,<<131,110,7,1,42,0,0,0,0,0,0>>),
+ decode(-42,<<131,110,8,1,42,0,0,0,0,0,0,0>>),
ok.
decode_large_big_ext_neg(Config) when is_list(Config) ->
- ?line decode(-1,<<131,111,1:32,1,1>>), % INTEGER_EXT
- ?line decode(-16#08000000,<<131,111,4:32,1,0,0,0,8>>), % INTEGER_EXT
- ?line decode(-16#80000000,<<131,111,4:32,1,0,0,0,128>>), % SMALL_BIG_EXT
-
- ?line decode(-42,<<131,111,1:32,1,42>>),
- ?line decode(-42,<<131,111,2:32,1,42,0>>), % Redundant zeros from now on
- ?line decode(-42,<<131,111,3:32,1,42,0,0>>),
- ?line decode(-42,<<131,111,4:32,1,42,0,0,0>>),
- ?line decode(-42,<<131,111,5:32,1,42,0,0,0,0>>),
- ?line decode(-42,<<131,111,6:32,1,42,0,0,0,0,0>>),
- ?line decode(-42,<<131,111,7:32,1,42,0,0,0,0,0,0>>),
- ?line decode(-42,<<131,111,8:32,1,42,0,0,0,0,0,0,0>>),
+ decode(-1,<<131,111,1:32,1,1>>), % INTEGER_EXT
+ decode(-16#08000000,<<131,111,4:32,1,0,0,0,8>>), % INTEGER_EXT
+ decode(-16#80000000,<<131,111,4:32,1,0,0,0,128>>), % SMALL_BIG_EXT
+
+ decode(-42,<<131,111,1:32,1,42>>),
+ decode(-42,<<131,111,2:32,1,42,0>>), % Redundant zeros from now on
+ decode(-42,<<131,111,3:32,1,42,0,0>>),
+ decode(-42,<<131,111,4:32,1,42,0,0,0>>),
+ decode(-42,<<131,111,5:32,1,42,0,0,0,0>>),
+ decode(-42,<<131,111,6:32,1,42,0,0,0,0,0>>),
+ decode(-42,<<131,111,7:32,1,42,0,0,0,0,0,0>>),
+ decode(-42,<<131,111,8:32,1,42,0,0,0,0,0,0,0>>),
ok.
decode_pos_neg_zero(Config) when is_list(Config) ->
- ?line decode( 0, <<131,110,0,0>>), % SMALL_BIG_EXT (positive zero)
- ?line decode( 0, <<131,110,1,0,0>>), % SMALL_BIG_EXT (positive zero)
- ?line decode( 0, <<131,110,0,1>>), % SMALL_BIG_EXT (negative zero)
- ?line decode( 0, <<131,110,1,1,0>>), % SMALL_BIG_EXT (negative zero)
+ decode( 0, <<131,110,0,0>>), % SMALL_BIG_EXT (positive zero)
+ decode( 0, <<131,110,1,0,0>>), % SMALL_BIG_EXT (positive zero)
+ decode( 0, <<131,110,0,1>>), % SMALL_BIG_EXT (negative zero)
+ decode( 0, <<131,110,1,1,0>>), % SMALL_BIG_EXT (negative zero)
- ?line decode( 0, <<131,111,0:32,0>>), % SMALL_BIG_EXT (positive zero)
- ?line decode( 0, <<131,111,1:32,0,0>>), % SMALL_BIG_EXT (positive zero)
- ?line decode( 0, <<131,111,0:32,1>>), % SMALL_BIG_EXT (negative zero)
- ?line decode( 0, <<131,111,1:32,1,0>>), % SMALL_BIG_EXT (negative zero)
+ decode( 0, <<131,111,0:32,0>>), % SMALL_BIG_EXT (positive zero)
+ decode( 0, <<131,111,1:32,0,0>>), % SMALL_BIG_EXT (positive zero)
+ decode( 0, <<131,111,0:32,1>>), % SMALL_BIG_EXT (negative zero)
+ decode( 0, <<131,111,1:32,1,0>>), % SMALL_BIG_EXT (negative zero)
N = largest_small_big(),
- ?line decode( N,<<131,110,255,0,N:2040/little>>), % largest SMALL_BIG_EXT
- ?line decode(-N,<<131,110,255,1,N:2040/little>>), % largest SMALL_BIG_EXT
+ decode( N,<<131,110,255,0,N:2040/little>>), % largest SMALL_BIG_EXT
+ decode(-N,<<131,110,255,1,N:2040/little>>), % largest SMALL_BIG_EXT
ok.
%% Test to decode uncompleted encodings for all in "erl_ext_dist.txt"
decode_too_small(Config) when is_list(Config) ->
- ?line decode_badarg(<<131, 97>>),
- ?line decode_badarg(<<131, 98>>),
- ?line decode_badarg(<<131, 98, 0>>),
- ?line decode_badarg(<<131, 98, 0, 0>>),
- ?line decode_badarg(<<131, 98, 0, 0, 0>>),
- ?line decode_badarg(<<131, 99>>),
- ?line decode_badarg(<<131, 99, 0>>),
- ?line decode_badarg(<<131, 99, 0:240>>),
-
- ?line decode_badarg(<<131,100>>),
- ?line decode_badarg(<<131,100, 1:16/big>>),
- ?line decode_badarg(<<131,100, 2:16/big>>),
- ?line decode_badarg(<<131,100, 2:16/big, "A">>),
+ decode_badarg(<<131, 97>>),
+ decode_badarg(<<131, 98>>),
+ decode_badarg(<<131, 98, 0>>),
+ decode_badarg(<<131, 98, 0, 0>>),
+ decode_badarg(<<131, 98, 0, 0, 0>>),
+ decode_badarg(<<131, 99>>),
+ decode_badarg(<<131, 99, 0>>),
+ decode_badarg(<<131, 99, 0:240>>),
+
+ decode_badarg(<<131,100>>),
+ decode_badarg(<<131,100, 1:16/big>>),
+ decode_badarg(<<131,100, 2:16/big>>),
+ decode_badarg(<<131,100, 2:16/big, "A">>),
% FIXME node name "A" seem ok, should it be?
-% ?line decode_badarg(<<131,101,100,1:16/big,"A",42:32/big,0>>),
-
- ?line decode_badarg(<<131,101>>),
- ?line decode_badarg(<<131,101,106>>),
- ?line decode_badarg(<<131,101,255>>),
- ?line decode_badarg(<<131,101,106,42:8/big>>),
- ?line decode_badarg(<<131,101,106,42:16/big>>),
- ?line decode_badarg(<<131,101,255,42:24/big>>),
- ?line decode_badarg(<<131,101,255,42:32/big,0>>),
- ?line decode_badarg(<<131,101,100,1:16/big,"A">>),
- ?line decode_badarg(<<131,101,100,1:16/big,"A",42:32/big>>),
-
- ?line decode_badarg(<<131,102>>),
- ?line decode_badarg(<<131,102,106,42:32/big,0>>),
- ?line decode_badarg(<<131,102,255,42:32/big,0>>),
- ?line decode_badarg(<<131,102,100,1:16/big,"A">>),
- ?line decode_badarg(<<131,102,100,1:16/big,"A",42:32/big>>),
-
- ?line decode_badarg(<<131,103>>),
- ?line decode_badarg(<<131,103,106,42:32/big,0>>),
- ?line decode_badarg(<<131,103,255,42:32/big,0>>),
- ?line decode_badarg(<<131,103,100,1:16/big,"A">>),
- ?line decode_badarg(<<131,103,100,1:16/big,"A",42:32/big>>),
- ?line decode_badarg(<<131,103,100,1:16/big,"A",4:32/big,2:32/big>>),
-
- ?line decode_badarg(<<131,104>>),
- ?line decode_badarg(<<131,104, 1>>),
- ?line decode_badarg(<<131,104, 2, 106>>),
- ?line decode_badarg(<<131,105, 1:32/big>>),
- ?line decode_badarg(<<131,105, 2:32/big, 106>>),
-
- ?line decode_badarg(<<131,107>>),
- ?line decode_badarg(<<131,107, 1:16/big>>),
- ?line decode_badarg(<<131,107, 2:16/big>>),
- ?line decode_badarg(<<131,107, 2:16/big, "A">>),
-
- ?line decode_badarg(<<131,108>>),
- ?line decode_badarg(<<131,108, 1:32/big>>),
- ?line decode_badarg(<<131,108, 2:32/big>>),
- ?line decode_badarg(<<131,108, 2:32/big, 106>>), % FIXME don't use NIL
-
- ?line decode_badarg(<<131,109>>),
- ?line decode_badarg(<<131,109, 1:32/big>>),
- ?line decode_badarg(<<131,109, 2:32/big>>),
- ?line decode_badarg(<<131,109, 2:32/big, 42>>),
+ % decode_badarg(<<131,101,100,1:16/big,"A",42:32/big,0>>),
+
+ decode_badarg(<<131,101>>),
+ decode_badarg(<<131,101,106>>),
+ decode_badarg(<<131,101,255>>),
+ decode_badarg(<<131,101,106,42:8/big>>),
+ decode_badarg(<<131,101,106,42:16/big>>),
+ decode_badarg(<<131,101,255,42:24/big>>),
+ decode_badarg(<<131,101,255,42:32/big,0>>),
+ decode_badarg(<<131,101,100,1:16/big,"A">>),
+ decode_badarg(<<131,101,100,1:16/big,"A",42:32/big>>),
+
+ decode_badarg(<<131,102>>),
+ decode_badarg(<<131,102,106,42:32/big,0>>),
+ decode_badarg(<<131,102,255,42:32/big,0>>),
+ decode_badarg(<<131,102,100,1:16/big,"A">>),
+ decode_badarg(<<131,102,100,1:16/big,"A",42:32/big>>),
+
+ decode_badarg(<<131,103>>),
+ decode_badarg(<<131,103,106,42:32/big,0>>),
+ decode_badarg(<<131,103,255,42:32/big,0>>),
+ decode_badarg(<<131,103,100,1:16/big,"A">>),
+ decode_badarg(<<131,103,100,1:16/big,"A",42:32/big>>),
+ decode_badarg(<<131,103,100,1:16/big,"A",4:32/big,2:32/big>>),
+
+ decode_badarg(<<131,104>>),
+ decode_badarg(<<131,104, 1>>),
+ decode_badarg(<<131,104, 2, 106>>),
+ decode_badarg(<<131,105, 1:32/big>>),
+ decode_badarg(<<131,105, 2:32/big, 106>>),
+
+ decode_badarg(<<131,107>>),
+ decode_badarg(<<131,107, 1:16/big>>),
+ decode_badarg(<<131,107, 2:16/big>>),
+ decode_badarg(<<131,107, 2:16/big, "A">>),
+
+ decode_badarg(<<131,108>>),
+ decode_badarg(<<131,108, 1:32/big>>),
+ decode_badarg(<<131,108, 2:32/big>>),
+ decode_badarg(<<131,108, 2:32/big, 106>>), % FIXME don't use NIL
+
+ decode_badarg(<<131,109>>),
+ decode_badarg(<<131,109, 1:32/big>>),
+ decode_badarg(<<131,109, 2:32/big>>),
+ decode_badarg(<<131,109, 2:32/big, 42>>),
N = largest_small_big(),
- ?line decode_badarg(<<131,110>>),
- ?line decode_badarg(<<131,110,1>>),
- ?line decode_badarg(<<131,110,1,0>>),
- ?line decode_badarg(<<131,110,1,1>>),
- ?line decode_badarg(<<131,110,2,0,42>>),
- ?line decode_badarg(<<131,110,2,1,42>>),
- ?line decode_badarg(<<131,110,255,0,N:2032/little>>),
- ?line decode_badarg(<<131,110,255,1,N:2032/little>>),
-
- ?line decode_badarg(<<131,111>>),
- ?line decode_badarg(<<131,111, 1:32/big>>),
- ?line decode_badarg(<<131,111, 1:32/big,0>>),
- ?line decode_badarg(<<131,111, 1:32/big,1>>),
- ?line decode_badarg(<<131,111, 2:32/big,0,42>>),
- ?line decode_badarg(<<131,111, 2:32/big,1,42>>),
- ?line decode_badarg(<<131,111,256:32/big,0,N:2032/little>>),
- ?line decode_badarg(<<131,111,256:32/big,1,N:2032/little>>),
- ?line decode_badarg(<<131,111,256:32/big,0,N:2040/little>>),
- ?line decode_badarg(<<131,111,256:32/big,1,N:2040/little>>),
- ?line decode_badarg(<<131,111,257:32/big,0,N:2048/little>>),
- ?line decode_badarg(<<131,111,257:32/big,1,N:2048/little>>),
+ decode_badarg(<<131,110>>),
+ decode_badarg(<<131,110,1>>),
+ decode_badarg(<<131,110,1,0>>),
+ decode_badarg(<<131,110,1,1>>),
+ decode_badarg(<<131,110,2,0,42>>),
+ decode_badarg(<<131,110,2,1,42>>),
+ decode_badarg(<<131,110,255,0,N:2032/little>>),
+ decode_badarg(<<131,110,255,1,N:2032/little>>),
+
+ decode_badarg(<<131,111>>),
+ decode_badarg(<<131,111, 1:32/big>>),
+ decode_badarg(<<131,111, 1:32/big,0>>),
+ decode_badarg(<<131,111, 1:32/big,1>>),
+ decode_badarg(<<131,111, 2:32/big,0,42>>),
+ decode_badarg(<<131,111, 2:32/big,1,42>>),
+ decode_badarg(<<131,111,256:32/big,0,N:2032/little>>),
+ decode_badarg(<<131,111,256:32/big,1,N:2032/little>>),
+ decode_badarg(<<131,111,256:32/big,0,N:2040/little>>),
+ decode_badarg(<<131,111,256:32/big,1,N:2040/little>>),
+ decode_badarg(<<131,111,257:32/big,0,N:2048/little>>),
+ decode_badarg(<<131,111,257:32/big,1,N:2048/little>>),
% Emulator dies if trying to create large bignum....
-% ?line decode_badarg(<<131,111,16#ffffffff:32/big,0>>),
-% ?line decode_badarg(<<131,111,16#ffffffff:32/big,1>>),
-
- ?line decode_badarg(<<131, 78>>),
- ?line decode_badarg(<<131, 78, 42>>),
- ?line decode_badarg(<<131, 78, 42, 1>>),
- ?line decode_badarg(<<131, 78, 42, 1:16/big>>),
- ?line decode_badarg(<<131, 78, 42, 2:16/big>>),
- ?line decode_badarg(<<131, 78, 42, 2:16/big, "A">>),
-
- ?line decode_badarg(<<131, 67>>),
-
- ?line decode_badarg(<<131,114>>),
- ?line decode_badarg(<<131,114,0>>),
- ?line decode_badarg(<<131,114,1:16/big>>),
- ?line decode_badarg(<<131,114,1:16/big,100>>),
- ?line decode_badarg(<<131,114,1:16/big,100,1:16/big>>),
- ?line decode_badarg(<<131,114,1:16/big,100,1:16/big,"A">>),
- ?line decode_badarg(<<131,114,1:16/big,100,1:16/big,"A",0>>),
- ?line decode_badarg(<<131,114,1:16/big,100,1:16/big,"A",0,42:8>>),
- ?line decode_badarg(<<131,114,1:16/big,100,1:16/big,"A",0,42:16>>),
- ?line decode_badarg(<<131,114,1:16/big,100,1:16/big,"A",0,42:24>>),
-
- ?line decode_badarg(<<131,117>>), % FIXME needs more tests
+ % decode_badarg(<<131,111,16#ffffffff:32/big,0>>),
+ % decode_badarg(<<131,111,16#ffffffff:32/big,1>>),
+
+ decode_badarg(<<131, 78>>),
+ decode_badarg(<<131, 78, 42>>),
+ decode_badarg(<<131, 78, 42, 1>>),
+ decode_badarg(<<131, 78, 42, 1:16/big>>),
+ decode_badarg(<<131, 78, 42, 2:16/big>>),
+ decode_badarg(<<131, 78, 42, 2:16/big, "A">>),
+
+ decode_badarg(<<131, 67>>),
+
+ decode_badarg(<<131,114>>),
+ decode_badarg(<<131,114,0>>),
+ decode_badarg(<<131,114,1:16/big>>),
+ decode_badarg(<<131,114,1:16/big,100>>),
+ decode_badarg(<<131,114,1:16/big,100,1:16/big>>),
+ decode_badarg(<<131,114,1:16/big,100,1:16/big,"A">>),
+ decode_badarg(<<131,114,1:16/big,100,1:16/big,"A",0>>),
+ decode_badarg(<<131,114,1:16/big,100,1:16/big,"A",0,42:8>>),
+ decode_badarg(<<131,114,1:16/big,100,1:16/big,"A",0,42:16>>),
+ decode_badarg(<<131,114,1:16/big,100,1:16/big,"A",0,42:24>>),
+
+ decode_badarg(<<131,117>>), % FIXME needs more tests
ok.
@@ -380,12 +353,11 @@ my_appender_1(N, T0) ->
U = rnd_term(),
T = [U|T0],
my_appender_1(N-1, T).
-
+
seed() ->
- random:seed(3172, 9815, 20129).
+ rand:seed(exsplus, {3172,9815,20129}).
rnd_term() ->
- U0 = random:uniform(),
+ U0 = rand:uniform(),
B = <<U0/float>>,
{U0,U0 * 2.5 + 3.14,[U0*2.3,B]}.
-
diff --git a/erts/emulator/test/exception_SUITE.erl b/erts/emulator/test/exception_SUITE.erl
index 11caea3698..1cad7e7920 100644
--- a/erts/emulator/test/exception_SUITE.erl
+++ b/erts/emulator/test/exception_SUITE.erl
@@ -20,67 +20,52 @@
-module(exception_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- badmatch/1, pending_errors/1, nil_arith/1,
+-export([all/0, suite/0,
+ badmatch/1, pending_errors/1, nil_arith/1,
stacktrace/1, nested_stacktrace/1, raise/1, gunilla/1, per/1,
- exception_with_heap_frag/1, line_numbers/1]).
+ exception_with_heap_frag/1, line_numbers/1]).
-export([bad_guy/2]).
-export([crash/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-import(lists, [foreach/2]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {seconds, 10}}].
all() ->
[badmatch, pending_errors, nil_arith, stacktrace,
nested_stacktrace, raise, gunilla, per,
exception_with_heap_frag, line_numbers].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-define(try_match(E),
- catch ?MODULE:bar(),
- {'EXIT', {{badmatch, nomatch}, _}} = (catch E = id(nomatch))).
+ catch ?MODULE:bar(),
+ {'EXIT', {{badmatch, nomatch}, _}} = (catch E = id(nomatch))).
%% Test that deliberately bad matches are reported correctly.
badmatch(Config) when is_list(Config) ->
- ?line ?try_match(a),
- ?line ?try_match(42),
- ?line ?try_match({a, b, c}),
- ?line ?try_match([]),
- ?line ?try_match(1.0),
+ ?try_match(a),
+ ?try_match(42),
+ ?try_match({a, b, c}),
+ ?try_match([]),
+ ?try_match(1.0),
ok.
%% Test various exceptions, in the presence of a previous error suppressed
%% in a guard.
pending_errors(Config) when is_list(Config) ->
- ?line pending(e_badmatch, {badmatch, b}),
- ?line pending(x, function_clause),
- ?line pending(e_case, {case_clause, xxx}),
- ?line pending(e_if, if_clause),
- ?line pending(e_badarith, badarith),
- ?line pending(e_undef, undef),
- ?line pending(e_timeoutval, timeout_value),
- ?line pending(e_badarg, badarg),
- ?line pending(e_badarg_spawn, badarg),
+ pending(e_badmatch, {badmatch, b}),
+ pending(x, function_clause),
+ pending(e_case, {case_clause, xxx}),
+ pending(e_if, if_clause),
+ pending(e_badarith, badarith),
+ pending(e_undef, undef),
+ pending(e_timeoutval, timeout_value),
+ pending(e_badarg, badarg),
+ pending(e_badarg_spawn, badarg),
ok.
bad_guy(pe_badarith, Other) when Other+1 == 0 -> % badarith (suppressed)
@@ -89,11 +74,11 @@ bad_guy(pe_badarg, Other) when length(Other) > 0 -> % badarg (suppressed)
ok;
bad_guy(_, e_case) ->
case id(xxx) of
- ok -> ok
+ ok -> ok
end; % case_clause
bad_guy(_, e_if) ->
if
- a == b -> ok
+ a == b -> ok
end; % if_clause
bad_guy(_, e_badarith) ->
1+b; % badarith
@@ -101,9 +86,9 @@ bad_guy(_, e_undef) ->
non_existing_module:foo(); % undef
bad_guy(_, e_timeoutval) ->
receive
- after arne -> % timeout_value
- ok
- end;
+ after arne -> % timeout_value
+ ok
+ end;
bad_guy(_, e_badarg) ->
node(xxx); % badarg
bad_guy(_, e_badarg_spawn) ->
@@ -122,30 +107,30 @@ pending(First, Second, Expected) ->
pending_catched(First, Second, Expected) ->
ok = io:format("Catching bad_guy(~p, ~p)", [First, Second]),
case catch bad_guy(First, Second) of
- {'EXIT', Reason} ->
- pending(Reason, bad_guy, [First, Second], Expected);
- Other ->
- test_server:fail({not_exit, Other})
+ {'EXIT', Reason} ->
+ pending(Reason, bad_guy, [First, Second], Expected);
+ Other ->
+ ct:fail({not_exit, Other})
end.
pending_exit_message(Args, Expected) ->
ok = io:format("Trapping EXITs from spawn_link(~p, ~p, ~p)",
- [?MODULE, bad_guy, Args]),
+ [?MODULE, bad_guy, Args]),
process_flag(trap_exit, true),
Pid = spawn_link(?MODULE, bad_guy, Args),
receive
- {'EXIT', Pid, Reason} ->
- pending(Reason, bad_guy, Args, Expected);
- Other ->
- test_server:fail({unexpected_message, Other})
+ {'EXIT', Pid, Reason} ->
+ pending(Reason, bad_guy, Args, Expected);
+ Other ->
+ ct:fail({unexpected_message, Other})
after 10000 ->
- test_server:fail(timeout)
+ ct:fail(timeout)
end,
process_flag(trap_exit, false).
pending({badarg,[{erlang,Bif,BifArgs,Loc1},
- {?MODULE,Func,Arity,Loc2}|_]},
- Func, Args, _Code)
+ {?MODULE,Func,Arity,Loc2}|_]},
+ Func, Args, _Code)
when is_atom(Bif), is_list(BifArgs), length(Args) =:= Arity,
is_list(Loc1), is_list(Loc2) ->
ok;
@@ -159,67 +144,67 @@ pending({Code,[{?MODULE,Func,Arity,Loc}|_]}, Func, Args, Code)
when length(Args) =:= Arity, is_list(Loc) ->
ok;
pending(Reason, _Function, _Args, _Code) ->
- test_server:fail({bad_exit_reason,Reason}).
+ ct:fail({bad_exit_reason,Reason}).
%% Test that doing arithmetics on [] gives a badarith EXIT and not a crash.
nil_arith(Config) when is_list(Config) ->
- ?line ba_plus_minus_times([], []),
-
- ?line ba_plus_minus_times([], 0),
- ?line ba_plus_minus_times([], 42),
- ?line ba_plus_minus_times([], 38724978123478923784),
- ?line ba_plus_minus_times([], 38.72),
-
- ?line ba_plus_minus_times(0, []),
- ?line ba_plus_minus_times(334, []),
- ?line ba_plus_minus_times(387249797813478923784, []),
- ?line ba_plus_minus_times(344.22, []),
-
- ?line ba_div_rem([], []),
-
- ?line ba_div_rem([], 0),
- ?line ba_div_rem([], 1),
- ?line ba_div_rem([], 42),
- ?line ba_div_rem([], 38724978123478923784),
- ?line ba_div_rem(344.22, []),
-
- ?line ba_div_rem(0, []),
- ?line ba_div_rem(1, []),
- ?line ba_div_rem(334, []),
- ?line ba_div_rem(387249797813478923784, []),
- ?line ba_div_rem(344.22, []),
-
- ?line ba_div_rem(344.22, 0.0),
- ?line ba_div_rem(1, 0.0),
- ?line ba_div_rem(392873498733971, 0.0),
-
- ?line ba_bop([], []),
- ?line ba_bop(0, []),
- ?line ba_bop(42, []),
- ?line ba_bop(-42342742987343, []),
- ?line ba_bop(238.342, []),
- ?line ba_bop([], 0),
- ?line ba_bop([], -243),
- ?line ba_bop([], 243),
- ?line ba_bop([], 2438724982478933),
- ?line ba_bop([], 3987.37),
-
- ?line ba_bnot([]),
- ?line ba_bnot(23.33),
-
- ?line ba_shift([], []),
- ?line ba_shift([], 0),
- ?line ba_shift([], 4),
- ?line ba_shift([], -4),
- ?line ba_shift([], 2343333333333),
- ?line ba_shift([], -333333333),
- ?line ba_shift([], 234.00),
- ?line ba_shift(23, []),
- ?line ba_shift(0, []),
- ?line ba_shift(-3433443433433323, []),
- ?line ba_shift(433443433433323, []),
- ?line ba_shift(343.93, []),
+ ba_plus_minus_times([], []),
+
+ ba_plus_minus_times([], 0),
+ ba_plus_minus_times([], 42),
+ ba_plus_minus_times([], 38724978123478923784),
+ ba_plus_minus_times([], 38.72),
+
+ ba_plus_minus_times(0, []),
+ ba_plus_minus_times(334, []),
+ ba_plus_minus_times(387249797813478923784, []),
+ ba_plus_minus_times(344.22, []),
+
+ ba_div_rem([], []),
+
+ ba_div_rem([], 0),
+ ba_div_rem([], 1),
+ ba_div_rem([], 42),
+ ba_div_rem([], 38724978123478923784),
+ ba_div_rem(344.22, []),
+
+ ba_div_rem(0, []),
+ ba_div_rem(1, []),
+ ba_div_rem(334, []),
+ ba_div_rem(387249797813478923784, []),
+ ba_div_rem(344.22, []),
+
+ ba_div_rem(344.22, 0.0),
+ ba_div_rem(1, 0.0),
+ ba_div_rem(392873498733971, 0.0),
+
+ ba_bop([], []),
+ ba_bop(0, []),
+ ba_bop(42, []),
+ ba_bop(-42342742987343, []),
+ ba_bop(238.342, []),
+ ba_bop([], 0),
+ ba_bop([], -243),
+ ba_bop([], 243),
+ ba_bop([], 2438724982478933),
+ ba_bop([], 3987.37),
+
+ ba_bnot([]),
+ ba_bnot(23.33),
+
+ ba_shift([], []),
+ ba_shift([], 0),
+ ba_shift([], 4),
+ ba_shift([], -4),
+ ba_shift([], 2343333333333),
+ ba_shift([], -333333333),
+ ba_shift([], 234.00),
+ ba_shift(23, []),
+ ba_shift(0, []),
+ ba_shift(-3433443433433323, []),
+ ba_shift(433443433433323, []),
+ ba_shift(343.93, []),
ok.
ba_plus_minus_times(A, B) ->
@@ -251,7 +236,7 @@ ba_shift(A, B) ->
{'EXIT', {badarith, _}} = (catch A bsl B),
io:format("~p bsr ~p", [A, B]),
{'EXIT', {badarith, _}} = (catch A bsr B).
-
+
ba_bnot(A) ->
io:format("bnot ~p", [A]),
{'EXIT', {badarith, _}} = (catch bnot A).
@@ -260,38 +245,38 @@ ba_bnot(A) ->
stacktrace(Conf) when is_list(Conf) ->
Tag = make_ref(),
- ?line {_,Mref} = spawn_monitor(fun() -> exit({Tag,erlang:get_stacktrace()}) end),
- ?line {Tag,[]} = receive {'DOWN',Mref,_,_,Info} -> Info end,
+ {_,Mref} = spawn_monitor(fun() -> exit({Tag,erlang:get_stacktrace()}) end),
+ {Tag,[]} = receive {'DOWN',Mref,_,_,Info} -> Info end,
V = [make_ref()|self()],
- ?line {value2,{caught1,badarg,[{erlang,abs,[V],_}|_]=St1}} =
- stacktrace_1({'abs',V}, error, {value,V}),
- ?line St1 = erase(stacktrace1),
- ?line St1 = erase(stacktrace2),
- ?line St1 = erlang:get_stacktrace(),
- ?line {caught2,{error,badarith},[{?MODULE,my_add,2,_}|_]=St2} =
- stacktrace_1({'div',{1,0}}, error, {'add',{0,a}}),
- ?line [{?MODULE,my_div,2,_}|_] = erase(stacktrace1),
- ?line St2 = erase(stacktrace2),
- ?line St2 = erlang:get_stacktrace(),
- ?line {caught2,{error,{try_clause,V}},[{?MODULE,stacktrace_1,3,_}|_]=St3} =
- stacktrace_1({value,V}, error, {value,V}),
- ?line St3 = erase(stacktrace1),
- ?line St3 = erase(stacktrace2),
- ?line St3 = erlang:get_stacktrace(),
- ?line {caught2,{throw,V},[{?MODULE,foo,1,_}|_]=St4} =
- stacktrace_1({value,V}, error, {throw,V}),
- ?line [{?MODULE,stacktrace_1,3,_}|_] = erase(stacktrace1),
- ?line St4 = erase(stacktrace2),
- ?line St4 = erlang:get_stacktrace(),
+ {value2,{caught1,badarg,[{erlang,abs,[V],_}|_]=St1}} =
+ stacktrace_1({'abs',V}, error, {value,V}),
+ St1 = erase(stacktrace1),
+ St1 = erase(stacktrace2),
+ St1 = erlang:get_stacktrace(),
+ {caught2,{error,badarith},[{?MODULE,my_add,2,_}|_]=St2} =
+ stacktrace_1({'div',{1,0}}, error, {'add',{0,a}}),
+ [{?MODULE,my_div,2,_}|_] = erase(stacktrace1),
+ St2 = erase(stacktrace2),
+ St2 = erlang:get_stacktrace(),
+ {caught2,{error,{try_clause,V}},[{?MODULE,stacktrace_1,3,_}|_]=St3} =
+ stacktrace_1({value,V}, error, {value,V}),
+ St3 = erase(stacktrace1),
+ St3 = erase(stacktrace2),
+ St3 = erlang:get_stacktrace(),
+ {caught2,{throw,V},[{?MODULE,foo,1,_}|_]=St4} =
+ stacktrace_1({value,V}, error, {throw,V}),
+ [{?MODULE,stacktrace_1,3,_}|_] = erase(stacktrace1),
+ St4 = erase(stacktrace2),
+ St4 = erlang:get_stacktrace(),
try
- ?line stacktrace_2()
+ stacktrace_2()
catch
- error:{badmatch,_} ->
- [{?MODULE,stacktrace_2,0,_},
- {?MODULE,stacktrace,1,_}|_] =
- erlang:get_stacktrace(),
- ok
+ error:{badmatch,_} ->
+ [{?MODULE,stacktrace_2,0,_},
+ {?MODULE,stacktrace,1,_}|_] =
+ erlang:get_stacktrace(),
+ ok
end.
stacktrace_1(X, C1, Y) ->
@@ -303,7 +288,7 @@ stacktrace_1(X, C1, Y) ->
C1:D1 -> {caught1,D1,erlang:get_stacktrace()}
after
put(stacktrace1, erlang:get_stacktrace()),
- foo(Y)
+ foo(Y)
end of
V2 -> {value2,V2}
catch
@@ -319,21 +304,21 @@ stacktrace_2() ->
nested_stacktrace(Conf) when is_list(Conf) ->
V = [{make_ref()}|[self()]],
- ?line value1 =
- nested_stacktrace_1({{value,{V,x1}},void,{V,x1}},
- {void,void,void}),
- ?line {caught1,
- [{?MODULE,my_add,2,_}|_],
- value2,
- [{?MODULE,my_add,2,_}|_]} =
- nested_stacktrace_1({{'add',{V,x1}},error,badarith},
- {{value,{V,x2}},void,{V,x2}}),
- ?line {caught1,
- [{?MODULE,my_add,2,_}|_],
- {caught2,[{erlang,abs,[V],_}|_]},
- [{erlang,abs,[V],_}|_]} =
- nested_stacktrace_1({{'add',{V,x1}},error,badarith},
- {{'abs',V},error,badarg}),
+ value1 =
+ nested_stacktrace_1({{value,{V,x1}},void,{V,x1}},
+ {void,void,void}),
+ {caught1,
+ [{?MODULE,my_add,2,_}|_],
+ value2,
+ [{?MODULE,my_add,2,_}|_]} =
+ nested_stacktrace_1({{'add',{V,x1}},error,badarith},
+ {{value,{V,x2}},void,{V,x2}}),
+ {caught1,
+ [{?MODULE,my_add,2,_}|_],
+ {caught2,[{erlang,abs,[V],_}|_]},
+ [{erlang,abs,[V],_}|_]} =
+ nested_stacktrace_1({{'add',{V,x1}},error,badarith},
+ {{'abs',V},error,badarg}),
ok.
nested_stacktrace_1({X1,C1,V1}, {X2,C2,V2}) ->
@@ -341,64 +326,64 @@ nested_stacktrace_1({X1,C1,V1}, {X2,C2,V2}) ->
V1 -> value1
catch
C1:V1 ->
- S1 = erlang:get_stacktrace(),
+ S1 = erlang:get_stacktrace(),
T2 =
- try foo(X2) of
- V2 -> value2
- catch
- C2:V2 -> {caught2,erlang:get_stacktrace()}
- end,
+ try foo(X2) of
+ V2 -> value2
+ catch
+ C2:V2 -> {caught2,erlang:get_stacktrace()}
+ end,
{caught1,S1,T2,erlang:get_stacktrace()}
end.
raise(Conf) when is_list(Conf) ->
- ?line erase(raise),
- ?line A =
- try
- ?line try foo({'div',{1,0}})
- catch
- error:badarith ->
- put(raise, A0 = erlang:get_stacktrace()),
- ?line erlang:raise(error, badarith, A0)
- end
- catch
- error:badarith ->
- ?line A1 = erlang:get_stacktrace(),
- ?line A1 = get(raise)
- end,
- ?line A = erlang:get_stacktrace(),
- ?line A = get(raise),
- ?line [{?MODULE,my_div,2,_}|_] = A,
+ erase(raise),
+ A =
+ try
+ try foo({'div',{1,0}})
+ catch
+ error:badarith ->
+ put(raise, A0 = erlang:get_stacktrace()),
+ erlang:raise(error, badarith, A0)
+ end
+ catch
+ error:badarith ->
+ A1 = erlang:get_stacktrace(),
+ A1 = get(raise)
+ end,
+ A = erlang:get_stacktrace(),
+ A = get(raise),
+ [{?MODULE,my_div,2,_}|_] = A,
%%
N = 8, % Must be even
- ?line N = erlang:system_flag(backtrace_depth, N),
- ?line B = odd_even(N, []),
- ?line try even(N)
- catch error:function_clause -> ok
- end,
- ?line B = erlang:get_stacktrace(),
+ N = erlang:system_flag(backtrace_depth, N),
+ B = odd_even(N, []),
+ try even(N)
+ catch error:function_clause -> ok
+ end,
+ B = erlang:get_stacktrace(),
%%
- ?line C0 = odd_even(N+1, []),
- ?line C = lists:sublist(C0, N),
- ?line try odd(N+1)
- catch error:function_clause -> ok
- end,
- ?line C = erlang:get_stacktrace(),
- ?line try erlang:raise(error, function_clause, C0)
- catch error:function_clause -> ok
- end,
- ?line C = erlang:get_stacktrace(),
+ C0 = odd_even(N+1, []),
+ C = lists:sublist(C0, N),
+ try odd(N+1)
+ catch error:function_clause -> ok
+ end,
+ C = erlang:get_stacktrace(),
+ try erlang:raise(error, function_clause, C0)
+ catch error:function_clause -> ok
+ end,
+ C = erlang:get_stacktrace(),
ok.
odd_even(N, R) when is_integer(N), N > 1 ->
odd_even(N-1,
- [if (N rem 2) == 0 ->
- {?MODULE,even,1,[{file,"odd_even.erl"},{line,3}]};
- true ->
- {?MODULE,odd,1,[{file,"odd_even.erl"},{line,6}]}
- end|R]);
+ [if (N rem 2) == 0 ->
+ {?MODULE,even,1,[{file,"odd_even.erl"},{line,3}]};
+ true ->
+ {?MODULE,odd,1,[{file,"odd_even.erl"},{line,6}]}
+ end|R]);
odd_even(1, R) ->
[{?MODULE,odd,[1],[{file,"odd_even.erl"},{line,5}]}|R].
@@ -428,18 +413,18 @@ my_add(A, B) ->
my_abs(X) -> abs(X).
gunilla(Config) when is_list(Config) ->
- ?line {throw,kalle} = gunilla_1(),
- ?line [] = erlang:get_stacktrace(),
+ {throw,kalle} = gunilla_1(),
+ [] = erlang:get_stacktrace(),
ok.
gunilla_1() ->
try try arne()
- after
- pelle
- end
+ after
+ pelle
+ end
catch
- C:R ->
- {C,R}
+ C:R ->
+ {C,R}
end.
arne() ->
@@ -448,18 +433,18 @@ arne() ->
per(Config) when is_list(Config) ->
try
- t1(0,pad,0),
- t2(0,pad,0)
+ t1(0,pad,0),
+ t2(0,pad,0)
catch
- error:badarith ->
- ok
+ error:badarith ->
+ ok
end.
t1(_,X,_) ->
- (1 bsl X) + 1.
+ (1 bsl X) + 1.
t2(_,X,_) ->
- (X bsl 1) + 1.
+ (X bsl 1) + 1.
%%
%% Make sure that even if a BIF builds an heap fragment, then causes an exception,
@@ -471,155 +456,155 @@ exception_with_heap_frag(Config) when is_list(Config) ->
%% Floats are only validated when the heap fragment has been allocated.
BadFloat = <<131,99,53,46,48,$X,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,101,45,48,49,0,0,0,0,0>>,
- ?line do_exception_with_heap_frag(BadFloat, Sizes),
+ do_exception_with_heap_frag(BadFloat, Sizes),
%% {Binary,BadFloat}: When the error in float is discovered, a refc-binary
%% has been allocated and the list of refc-binaries goes through the
%% heap fragment.
BinAndFloat =
- <<131,104,2,109,0,0,1,0,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,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,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,
- 71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
- 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,
- 116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,
- 135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,
- 154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,
- 173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
- 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,
- 211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
- 230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,
- 249,250,251,252,253,254,255,99,51,46,49,52,$B,$l,$u,$r,$f,48,48,48,48,48,48,
- 48,48,49,50,52,51,52,101,43,48,48,0,0,0,0,0>>,
- ?line do_exception_with_heap_frag(BinAndFloat, Sizes),
+ <<131,104,2,109,0,0,1,0,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,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,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,
+ 71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
+ 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,
+ 116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,
+ 135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,
+ 154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,
+ 173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,
+ 211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
+ 230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,
+ 249,250,251,252,253,254,255,99,51,46,49,52,$B,$l,$u,$r,$f,48,48,48,48,48,48,
+ 48,48,49,50,52,51,52,101,43,48,48,0,0,0,0,0>>,
+ do_exception_with_heap_frag(BinAndFloat, Sizes),
%% {Fun,BadFloat}
FunAndFloat =
- <<131,104,2,112,0,0,0,66,0,238,239,135,138,137,216,89,57,22,111,52,126,16,84,
- 71,8,0,0,0,0,0,0,0,0,100,0,1,116,97,0,98,5,175,169,123,103,100,0,13,110,111,
- 110,111,100,101,64,110,111,104,111,115,116,0,0,0,41,0,0,0,0,0,99,50,46,55,48,
- $Y,57,57,57,57,57,57,57,57,57,57,57,57,57,54,52,52,55,101,43,48,48,0,0,0,0,0>>,
- ?line do_exception_with_heap_frag(FunAndFloat, Sizes),
+ <<131,104,2,112,0,0,0,66,0,238,239,135,138,137,216,89,57,22,111,52,126,16,84,
+ 71,8,0,0,0,0,0,0,0,0,100,0,1,116,97,0,98,5,175,169,123,103,100,0,13,110,111,
+ 110,111,100,101,64,110,111,104,111,115,116,0,0,0,41,0,0,0,0,0,99,50,46,55,48,
+ $Y,57,57,57,57,57,57,57,57,57,57,57,57,57,54,52,52,55,101,43,48,48,0,0,0,0,0>>,
+ do_exception_with_heap_frag(FunAndFloat, Sizes),
%% [ExternalPid|BadFloat]
ExtPidAndFloat =
- <<131,108,0,0,0,1,103,100,0,13,107,97,108,108,101,64,115,116,114,105,100,101,
- 114,0,0,0,36,0,0,0,0,2,99,48,46,$@,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
- 48,48,48,48,48,101,43,48,48,0,0,0,0,0>>,
- ?line do_exception_with_heap_frag(ExtPidAndFloat, Sizes),
-
+ <<131,108,0,0,0,1,103,100,0,13,107,97,108,108,101,64,115,116,114,105,100,101,
+ 114,0,0,0,36,0,0,0,0,2,99,48,46,$@,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
+ 48,48,48,48,48,101,43,48,48,0,0,0,0,0>>,
+ do_exception_with_heap_frag(ExtPidAndFloat, Sizes),
+
ok.
do_exception_with_heap_frag(Bin, [Sz|Sizes]) ->
Filler = erlang:make_tuple(Sz, a),
spawn(fun() ->
- try
- binary_to_term(Bin)
- catch
- _:_ ->
- %% term_to_binary/1 is an easy way to traverse the
- %% entire stacktrace term to make sure that every part
- %% of it is OK.
- term_to_binary(erlang:get_stacktrace())
- end,
- id(Filler)
- end),
+ try
+ binary_to_term(Bin)
+ catch
+ _:_ ->
+ %% term_to_binary/1 is an easy way to traverse the
+ %% entire stacktrace term to make sure that every part
+ %% of it is OK.
+ term_to_binary(erlang:get_stacktrace())
+ end,
+ id(Filler)
+ end),
do_exception_with_heap_frag(Bin, Sizes);
do_exception_with_heap_frag(_, []) -> ok.
line_numbers(Config) when is_list(Config) ->
{'EXIT',{{case_clause,bad_tag},
- [{?MODULE,line1,2,
- [{file,"fake_file.erl"},{line,3}]},
- {?MODULE,line_numbers,1,_}|_]}} =
- (catch line1(bad_tag, 0)),
+ [{?MODULE,line1,2,
+ [{file,"fake_file.erl"},{line,3}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch line1(bad_tag, 0)),
{'EXIT',{badarith,
- [{?MODULE,line1,2,
- [{file,"fake_file.erl"},{line,5}]},
- {?MODULE,line_numbers,1,_}|_]}} =
- (catch line1(a, not_an_integer)),
+ [{?MODULE,line1,2,
+ [{file,"fake_file.erl"},{line,5}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch line1(a, not_an_integer)),
{'EXIT',{{badmatch,{ok,1}},
- [{?MODULE,line1,2,
- [{file,"fake_file.erl"},{line,7}]},
- {?MODULE,line_numbers,1,_}|_]}} =
- (catch line1(a, 0)),
+ [{?MODULE,line1,2,
+ [{file,"fake_file.erl"},{line,7}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch line1(a, 0)),
{'EXIT',{crash,
- [{?MODULE,crash,1,
- [{file,"fake_file.erl"},{line,14}]},
- {?MODULE,line_numbers,1,_}|_]}} =
- (catch line1(a, 41)),
+ [{?MODULE,crash,1,
+ [{file,"fake_file.erl"},{line,14}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch line1(a, 41)),
ModFile = ?MODULE_STRING++".erl",
[{?MODULE,maybe_crash,1,[{file,"call.erl"},{line,28}]},
{?MODULE,call1,0,[{file,"call.erl"},{line,14}]},
{?MODULE,close_calls,1,[{file,"call.erl"},{line,5}]},
{?MODULE,line_numbers,1,[{file,ModFile},{line,_}]}|_] =
- close_calls(call1),
+ close_calls(call1),
[{?MODULE,maybe_crash,1,[{file,"call.erl"},{line,28}]},
{?MODULE,call2,0,[{file,"call.erl"},{line,18}]},
{?MODULE,close_calls,1,[{file,"call.erl"},{line,6}]},
{?MODULE,line_numbers,1,[{file,ModFile},{line,_}]}|_] =
- close_calls(call2),
+ close_calls(call2),
[{?MODULE,maybe_crash,1,[{file,"call.erl"},{line,28}]},
{?MODULE,call3,0,[{file,"call.erl"},{line,22}]},
{?MODULE,close_calls,1,[{file,"call.erl"},{line,7}]},
{?MODULE,line_numbers,1,[{file,ModFile},{line,_}]}|_] =
- close_calls(call3),
+ close_calls(call3),
no_crash = close_calls(other),
<<0,0>> = build_binary1(16),
{'EXIT',{badarg,
- [{?MODULE,build_binary1,1,
- [{file,"bit_syntax.erl"},{line,72503}]},
- {?MODULE,line_numbers,1,
- [{file,ModFile},{line,_}]}|_]}} =
- (catch build_binary1(bad_size)),
+ [{?MODULE,build_binary1,1,
+ [{file,"bit_syntax.erl"},{line,72503}]},
+ {?MODULE,line_numbers,1,
+ [{file,ModFile},{line,_}]}|_]}} =
+ (catch build_binary1(bad_size)),
<<7,1,2,3>> = build_binary2(8, <<1,2,3>>),
{'EXIT',{badarg,
- [{?MODULE,build_binary2,2,
- [{file,"bit_syntax.erl"},{line,72507}]},
- {?MODULE,line_numbers,1,
- [{file,ModFile},{line,_}]}|_]}} =
- (catch build_binary2(bad_size, <<>>)),
+ [{?MODULE,build_binary2,2,
+ [{file,"bit_syntax.erl"},{line,72507}]},
+ {?MODULE,line_numbers,1,
+ [{file,ModFile},{line,_}]}|_]}} =
+ (catch build_binary2(bad_size, <<>>)),
{'EXIT',{badarg,
- [{erlang,bit_size,[bad_binary],[]},
- {?MODULE,build_binary2,2,
- [{file,"bit_syntax.erl"},{line,72507}]},
- {?MODULE,line_numbers,1,
- [{file,ModFile},{line,_}]}|_]}} =
- (catch build_binary2(8, bad_binary)),
+ [{erlang,bit_size,[bad_binary],[]},
+ {?MODULE,build_binary2,2,
+ [{file,"bit_syntax.erl"},{line,72507}]},
+ {?MODULE,line_numbers,1,
+ [{file,ModFile},{line,_}]}|_]}} =
+ (catch build_binary2(8, bad_binary)),
<<"abc",357:16>> = build_binary3(<<"abc">>),
{'EXIT',{badarg,[{?MODULE,build_binary3,1,
- [{file,"bit_syntax.erl"},{line,72511}]},
- {?MODULE,line_numbers,1,
- [{file,ModFile},{line,_}]}|_]}} =
- (catch build_binary3(no_binary)),
+ [{file,"bit_syntax.erl"},{line,72511}]},
+ {?MODULE,line_numbers,1,
+ [{file,ModFile},{line,_}]}|_]}} =
+ (catch build_binary3(no_binary)),
{'EXIT',{function_clause,
- [{?MODULE,do_call_abs,[y,y],
- [{file,"gc_bif.erl"},{line,18}]},
- {?MODULE,line_numbers,1,_}|_]}} =
- (catch do_call_abs(y, y)),
+ [{?MODULE,do_call_abs,[y,y],
+ [{file,"gc_bif.erl"},{line,18}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch do_call_abs(y, y)),
{'EXIT',{badarg,
- [{erlang,abs,[[]],[]},
- {?MODULE,do_call_abs,2,
- [{file,"gc_bif.erl"},{line,19}]},
- {?MODULE,line_numbers,1,_}|_]}} =
- (catch do_call_abs(x, [])),
+ [{erlang,abs,[[]],[]},
+ {?MODULE,do_call_abs,2,
+ [{file,"gc_bif.erl"},{line,19}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch do_call_abs(x, [])),
{'EXIT',{{badmatch,"42"},
- [{MODULE,applied_bif_1,1,[{file,"applied_bif.erl"},{line,5}]},
- {?MODULE,line_numbers,1,_}|_]}} =
- (catch applied_bif_1(42)),
+ [{MODULE,applied_bif_1,1,[{file,"applied_bif.erl"},{line,5}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch applied_bif_1(42)),
{'EXIT',{{badmatch,{current_location,
- {?MODULE,applied_bif_2,0,
- [{file,"applied_bif.erl"},{line,9}]}}},
- [{MODULE,applied_bif_2,0,[{file,"applied_bif.erl"},{line,10}]},
- {?MODULE,line_numbers,1,_}|_]}} =
- (catch applied_bif_2()),
+ {?MODULE,applied_bif_2,0,
+ [{file,"applied_bif.erl"},{line,9}]}}},
+ [{MODULE,applied_bif_2,0,[{file,"applied_bif.erl"},{line,10}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch applied_bif_2()),
ok.
@@ -646,13 +631,13 @@ odd(N) when is_integer(N), N > 1, (N rem 2) == 1 ->
-file("fake_file.erl", 1). %Line 1
line1(Tag, X) -> %Line 2
case Tag of %Line 3
- a ->
- Y = X + 1, %Line 5
- Res = id({ok,Y}), %Line 6
- ?MODULE:crash({ok,42} = Res); %Line 7
- b ->
- x = id(x), %Line 9
- ok %Line 10
+ a ->
+ Y = X + 1, %Line 5
+ Res = id({ok,Y}), %Line 6
+ ?MODULE:crash({ok,42} = Res); %Line 7
+ b ->
+ x = id(x), %Line 9
+ ok %Line 10
end. %Line 11
crash(_) -> %Line 13
@@ -662,12 +647,12 @@ crash(_) -> %Line 13
close_calls(Where) -> %Line 2
put(where_to_crash, Where), %Line 3
try
- call1(), %Line 5
- call2(), %Line 6
- call3(), %Line 7
- no_crash %Line 8
+ call1(), %Line 5
+ call2(), %Line 6
+ call3(), %Line 7
+ no_crash %Line 8
catch error:crash ->
- erlang:get_stacktrace() %Line 10
+ erlang:get_stacktrace() %Line 10
end. %Line 11
call1() -> %Line 13
@@ -684,10 +669,10 @@ call3() -> %Line 21
maybe_crash(Name) -> %Line 25
case get(where_to_crash) of %Line 26
- Name ->
- erlang:error(crash); %Line 28
- _ ->
- ok %Line 30
+ Name ->
+ erlang:error(crash); %Line 28
+ _ ->
+ ok %Line 30
end.
-file("bit_syntax.erl", 72500). %Line 72500
diff --git a/erts/emulator/test/float_SUITE.erl b/erts/emulator/test/float_SUITE.erl
index c1a76b8af4..78dec8c725 100644
--- a/erts/emulator/test/float_SUITE.erl
+++ b/erts/emulator/test/float_SUITE.erl
@@ -20,63 +20,40 @@
-module(float_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2,
- fpe/1,fp_drv/1,fp_drv_thread/1,denormalized/1,match/1,
- bad_float_unpack/1, write/1, cmp_zero/1, cmp_integer/1, cmp_bignum/1]).
+-export([all/0, suite/0, groups/0,
+ fpe/1,fp_drv/1,fp_drv_thread/1,denormalized/1,match/1,
+ t_mul_add_ops/1,
+ bad_float_unpack/1, write/1, cmp_zero/1, cmp_integer/1, cmp_bignum/1]).
-export([otp_7178/1]).
-export([hidden_inf/1]).
+-export([arith/1]).
-
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog = ?t:timetrap(?t:minutes(3)),
- [{watchdog, Dog},{testcase,Func}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 3}}].
all() ->
[fpe, fp_drv, fp_drv_thread, otp_7178, denormalized,
match, bad_float_unpack, write, {group, comparison}
,hidden_inf
- ].
+ ,arith, t_mul_add_ops].
groups() ->
[{comparison, [parallel], [cmp_zero, cmp_integer, cmp_bignum]}].
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
%%
%% OTP-7178, list_to_float on very small numbers should give 0.0
%% instead of exception, i.e. ignore underflow.
%%
-otp_7178(suite) ->
- [];
-otp_7178(doc) ->
- ["test that list_to_float on very small numbers give 0.0"];
+%% test that list_to_float on very small numbers give 0.0
otp_7178(Config) when is_list(Config) ->
- ?line X = list_to_float("1.0e-325"),
- ?line true = (X < 0.00000001) and (X > -0.00000001),
- ?line Y = list_to_float("1.0e-325325325"),
- ?line true = (Y < 0.00000001) and (Y > -0.00000001),
- ?line {'EXIT', {badarg,_}} = (catch list_to_float("1.0e83291083210")),
+ X = list_to_float("1.0e-325"),
+ true = (X < 0.00000001) and (X > -0.00000001),
+ Y = list_to_float("1.0e-325325325"),
+ true = (Y < 0.00000001) and (Y > -0.00000001),
+ {'EXIT', {badarg,_}} = (catch list_to_float("1.0e83291083210")),
ok.
%% Forces floating point exceptions and tests that subsequent, legal,
@@ -84,15 +61,15 @@ otp_7178(Config) when is_list(Config) ->
%% Strollo.
fpe(Config) when is_list(Config) ->
- ?line 0.0 = math:log(1.0),
- ?line {'EXIT', {badarith, _}} = (catch math:log(-1.0)),
- ?line 0.0 = math:log(1.0),
- ?line {'EXIT', {badarith, _}} = (catch math:log(0.0)),
- ?line 0.0 = math:log(1.0),
- ?line {'EXIT',{badarith,_}} = (catch 3.23e133 * id(3.57e257)),
- ?line 0.0 = math:log(1.0),
- ?line {'EXIT',{badarith,_}} = (catch 5.0/id(0.0)),
- ?line 0.0 = math:log(1.0),
+ 0.0 = math:log(1.0),
+ {'EXIT', {badarith, _}} = (catch math:log(-1.0)),
+ 0.0 = math:log(1.0),
+ {'EXIT', {badarith, _}} = (catch math:log(0.0)),
+ 0.0 = math:log(1.0),
+ {'EXIT',{badarith,_}} = (catch 3.23e133 * id(3.57e257)),
+ 0.0 = math:log(1.0),
+ {'EXIT',{badarith,_}} = (catch 5.0/id(0.0)),
+ 0.0 = math:log(1.0),
ok.
@@ -100,70 +77,70 @@ fpe(Config) when is_list(Config) ->
-define(ERTS_FP_THREAD_TEST, 1).
fp_drv(Config) when is_list(Config) ->
- fp_drv_test(?ERTS_FP_CONTROL_TEST, ?config(data_dir, Config)).
+ fp_drv_test(?ERTS_FP_CONTROL_TEST, proplists:get_value(data_dir, Config)).
fp_drv_thread(Config) when is_list(Config) ->
%% Run in a separate node since it used to crash the emulator...
- ?line Parent = self(),
- ?line DrvDir = ?config(data_dir, Config),
- ?line {ok,Node} = start_node(Config),
- ?line Tester = spawn_link(Node,
- fun () ->
- Parent !
- {self(),
- fp_drv_test(?ERTS_FP_THREAD_TEST,
- DrvDir)}
- end),
- ?line Result = receive {Tester, Res} -> Res end,
- ?line stop_node(Node),
- ?line Result.
+ Parent = self(),
+ DrvDir = proplists:get_value(data_dir, Config),
+ {ok,Node} = start_node(Config),
+ Tester = spawn_link(Node,
+ fun () ->
+ Parent !
+ {self(),
+ fp_drv_test(?ERTS_FP_THREAD_TEST,
+ DrvDir)}
+ end),
+ Result = receive {Tester, Res} -> Res end,
+ stop_node(Node),
+ Result.
fp_drv_test(Test, DrvDir) ->
- ?line Drv = fp_drv,
- ?line try
- begin
- ?line case erl_ddll:load_driver(DrvDir, Drv) of
- ok ->
- ok;
- {error, permanent} ->
- ok;
- {error, LoadError} ->
- exit({load_error,
- erl_ddll:format_error(LoadError)});
- LoadError ->
- exit({load_error, LoadError})
- end,
- case open_port({spawn, Drv}, []) of
- Port when is_port(Port) ->
- try port_control(Port, Test, "") of
- "ok" ->
- 0.0 = math:log(1.0),
- ok;
- [$s,$k,$i,$p,$:,$ | Reason] ->
- {skipped, Reason};
- Error ->
- exit(Error)
- after
- Port ! {self(), close},
- receive {Port, closed} -> ok end,
- false = lists:member(Port, erlang:ports()),
- ok
- end;
- Error ->
- exit({open_port_failed, Error})
- end
- end
- catch
- throw:Term -> ?line Term
- after
- erl_ddll:unload_driver(Drv)
- end.
+ Drv = fp_drv,
+ try
+ begin
+ case erl_ddll:load_driver(DrvDir, Drv) of
+ ok ->
+ ok;
+ {error, permanent} ->
+ ok;
+ {error, LoadError} ->
+ exit({load_error,
+ erl_ddll:format_error(LoadError)});
+ LoadError ->
+ exit({load_error, LoadError})
+ end,
+ case open_port({spawn, Drv}, []) of
+ Port when is_port(Port) ->
+ try port_control(Port, Test, "") of
+ "ok" ->
+ 0.0 = math:log(1.0),
+ ok;
+ [$s,$k,$i,$p,$:,$ | Reason] ->
+ {skipped, Reason};
+ Error ->
+ exit(Error)
+ after
+ Port ! {self(), close},
+ receive {Port, closed} -> ok end,
+ false = lists:member(Port, erlang:ports()),
+ ok
+ end;
+ Error ->
+ exit({open_port_failed, Error})
+ end
+ end
+ catch
+ throw:Term -> Term
+ after
+ erl_ddll:unload_driver(Drv)
+ end.
denormalized(Config) when is_list(Config) ->
- ?line Denormalized = 1.0e-307 / 1000,
- ?line roundtrip(Denormalized),
- ?line NegDenormalized = -1.0e-307 / 1000,
- ?line roundtrip(NegDenormalized),
+ Denormalized = 1.0e-307 / 1000,
+ roundtrip(Denormalized),
+ NegDenormalized = -1.0e-307 / 1000,
+ roundtrip(NegDenormalized),
ok.
roundtrip(N) ->
@@ -171,12 +148,12 @@ roundtrip(N) ->
N = binary_to_term(term_to_binary(N, [{minor_version,1}])).
match(Config) when is_list(Config) ->
- ?line one = match_1(1.0),
- ?line two = match_1(2.0),
- ?line a_lot = match_1(1000.0),
- ?line {'EXIT',_} = (catch match_1(0.5)),
+ one = match_1(1.0),
+ two = match_1(2.0),
+ a_lot = match_1(1000.0),
+ {'EXIT',_} = (catch match_1(0.5)),
ok.
-
+
match_1(1.0) -> one;
match_1(2.0) -> two;
match_1(1000.0) -> a_lot.
@@ -184,8 +161,8 @@ match_1(1000.0) -> a_lot.
%% Thanks to Per Gustafsson.
bad_float_unpack(Config) when is_list(Config) ->
- ?line Bin = <<-1:64>>,
- ?line -1 = bad_float_unpack_match(Bin),
+ Bin = <<-1:64>>,
+ -1 = bad_float_unpack_match(Bin),
ok.
bad_float_unpack_match(<<F:64/float>>) -> F;
@@ -237,75 +214,75 @@ span_cmp(Axis, Incr, Length) ->
%% Diff: How much the float and int should differ when comparing
span_cmp(Axis, Incr, Length, Diff) ->
[begin
- cmp(round(Axis*-1.0)+Diff+I*Incr,Axis*-1.0+I*Incr),
- cmp(Axis*-1.0+I*Incr,round(Axis*-1.0)-Diff+I*Incr)
+ cmp(round(Axis*-1.0)+Diff+I*Incr,Axis*-1.0+I*Incr),
+ cmp(Axis*-1.0+I*Incr,round(Axis*-1.0)-Diff+I*Incr)
end || I <- lists:seq((Length div 2)*-1,(Length div 2))],
[begin
- cmp(round(Axis)+Diff+I*Incr,Axis+I*Incr),
- cmp(Axis+I*Incr,round(Axis)-Diff+I*Incr)
+ cmp(round(Axis)+Diff+I*Incr,Axis+I*Incr),
+ cmp(Axis+I*Incr,round(Axis)-Diff+I*Incr)
end || I <- lists:seq((Length div 2)*-1,(Length div 2))].
cmp(Big,Small) when is_float(Big) ->
BigGtSmall = lists:flatten(
- io_lib:format("~f > ~p",[Big,Small])),
+ io_lib:format("~f > ~p",[Big,Small])),
BigLtSmall = lists:flatten(
- io_lib:format("~f < ~p",[Big,Small])),
+ io_lib:format("~f < ~p",[Big,Small])),
BigEqSmall = lists:flatten(
- io_lib:format("~f == ~p",[Big,Small])),
+ io_lib:format("~f == ~p",[Big,Small])),
SmallGtBig = lists:flatten(
- io_lib:format("~p > ~f",[Small,Big])),
+ io_lib:format("~p > ~f",[Small,Big])),
SmallLtBig = lists:flatten(
- io_lib:format("~p < ~f",[Small,Big])),
+ io_lib:format("~p < ~f",[Small,Big])),
SmallEqBig = lists:flatten(
- io_lib:format("~p == ~f",[Small,Big])),
+ io_lib:format("~p == ~f",[Small,Big])),
cmp(Big,Small,BigGtSmall,BigLtSmall,SmallGtBig,SmallLtBig,
- SmallEqBig,BigEqSmall);
+ SmallEqBig,BigEqSmall);
cmp(Big,Small) when is_float(Small) ->
BigGtSmall = lists:flatten(
- io_lib:format("~p > ~f",[Big,Small])),
+ io_lib:format("~p > ~f",[Big,Small])),
BigLtSmall = lists:flatten(
- io_lib:format("~p < ~f",[Big,Small])),
+ io_lib:format("~p < ~f",[Big,Small])),
BigEqSmall = lists:flatten(
- io_lib:format("~p == ~f",[Big,Small])),
+ io_lib:format("~p == ~f",[Big,Small])),
SmallGtBig = lists:flatten(
- io_lib:format("~f > ~p",[Small,Big])),
+ io_lib:format("~f > ~p",[Small,Big])),
SmallLtBig = lists:flatten(
- io_lib:format("~f < ~p",[Small,Big])),
+ io_lib:format("~f < ~p",[Small,Big])),
SmallEqBig = lists:flatten(
- io_lib:format("~f == ~p",[Small,Big])),
+ io_lib:format("~f == ~p",[Small,Big])),
cmp(Big,Small,BigGtSmall,BigLtSmall,SmallGtBig,SmallLtBig,
- SmallEqBig,BigEqSmall).
+ SmallEqBig,BigEqSmall).
cmp(Big,Small,BigGtSmall,BigLtSmall,SmallGtBig,SmallLtBig,
SmallEqBig,BigEqSmall) ->
{_,_,_,true} = {Big,Small,BigGtSmall,
- Big > Small},
+ Big > Small},
{_,_,_,false} = {Big,Small,BigLtSmall,
- Big < Small},
+ Big < Small},
{_,_,_,false} = {Big,Small,SmallGtBig,
- Small > Big},
+ Small > Big},
{_,_,_,true} = {Big,Small,SmallLtBig,
- Small < Big},
+ Small < Big},
{_,_,_,false} = {Big,Small,SmallEqBig,
- Small == Big},
+ Small == Big},
{_,_,_,false} = {Big,Small,BigEqSmall,
- Big == Small}.
+ Big == Small}.
id(I) -> I.
-
+
start_node(Config) when is_list(Config) ->
- ?line Pa = filename:dirname(code:which(?MODULE)),
- ?line Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(?config(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(seconds))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))),
- ?line ?t:start_node(Name, slave, [{args, "-pa "++Pa}]).
+ Pa = filename:dirname(code:which(?MODULE)),
+ Name = list_to_atom(atom_to_list(?MODULE)
+ ++ "-"
+ ++ atom_to_list(proplists:get_value(testcase, Config))
+ ++ "-"
+ ++ integer_to_list(erlang:system_time(seconds))
+ ++ "-"
+ ++ integer_to_list(erlang:unique_integer([positive]))),
+ test_server:start_node(Name, slave, [{args, "-pa "++Pa}]).
stop_node(Node) ->
- ?t:stop_node(Node).
+ test_server:stop_node(Node).
%% Test that operations that might hide infinite intermediate results
@@ -315,8 +292,8 @@ hidden_inf(Config) when is_list(Config) ->
ZeroN = id(ZeroP) * (-1),
[hidden_inf_1(A, B, Z, 9.23e307)
|| A <- [1.0, -1.0, 3.1415, -0.00001000131, 3.57e257, ZeroP, ZeroN],
- B <- [1.0, -1.0, 3.1415, -0.00001000131, 3.57e257, ZeroP, ZeroN],
- Z <- [ZeroP, ZeroN]],
+ B <- [1.0, -1.0, 3.1415, -0.00001000131, 3.57e257, ZeroP, ZeroN],
+ Z <- [ZeroP, ZeroN]],
ok.
hidden_inf_1(A, B, Zero, Huge) ->
@@ -328,3 +305,122 @@ hidden_inf_1(A, B, Zero, Huge) ->
{'EXIT',{badarith,_}} = (catch (B * (Huge + Huge))),
{'EXIT',{badarith,_}} = (catch (B / (-Huge - Huge))),
{'EXIT',{badarith,_}} = (catch (B * (-Huge - Huge))).
+
+%% Improve code coverage in our different arithmetic functions
+%% and make sure they yield consistent results.
+arith(_Config) ->
+ _TAG_IMMED1_SIZE = 4,
+
+ <<FLOAT_MAX/float>> = <<0:1, 16#7fe:11, -1:52>>,
+ <<FLOAT_MIN/float>> = <<0:1, 0:11, 1:52>>,
+ <<FloatNegZero/float>> = <<1:1, 0:11, 0:52>>,
+
+ WORD_BITS = erlang:system_info(wordsize) * 8,
+ SMALL_BITS = (WORD_BITS - _TAG_IMMED1_SIZE),
+ SMALL_MAX = (1 bsl (SMALL_BITS-1)) - 1,
+ SMALL_MIN = -(1 bsl (SMALL_BITS-1)),
+ BIG1_MAX = (1 bsl WORD_BITS) - 1,
+ BIG2_MAX = (1 bsl (WORD_BITS*2)) - 1,
+
+ fixnum = erts_internal:term_type(SMALL_MAX),
+ fixnum = erts_internal:term_type(SMALL_MIN),
+ bignum = erts_internal:term_type(SMALL_MAX + 1),
+ bignum = erts_internal:term_type(SMALL_MIN - 1),
+
+ L = [0, 0.0, FloatNegZero, 1, 1.0, 17, 17.0, 0.17,
+ FLOAT_MIN, FLOAT_MAX,
+ SMALL_MAX, SMALL_MAX+1,
+ SMALL_MIN, SMALL_MIN-1,
+ BIG1_MAX, BIG1_MAX+1,
+ BIG2_MAX, BIG2_MAX+1,
+ trunc(FLOAT_MAX), trunc(FLOAT_MAX)+1, trunc(FLOAT_MAX)*2,
+ immed_badarg,
+ "list badarg",
+ {"boxed badarg"}],
+
+ foreach_pair(fun(A,B) -> do_bin_ops(A,B) end, L).
+
+foreach_pair(F, L) ->
+ lists:foreach(
+ fun(A) -> lists:foreach(fun(B) -> F(A,B) end, L) end,
+ L).
+
+do_bin_ops(A, B) ->
+ Fun = fun(Op) ->
+ Op(A,B),
+ is_number(A) andalso Op(-A,B),
+ is_number(B) andalso Op(A,-B),
+ is_number(A) andalso is_number(B) andalso Op(-A,-B)
+ end,
+ lists:foreach(Fun,
+ [fun op_add/2, fun op_sub/2, fun op_mul/2, fun op_div/2]).
+
+op_add(A, B) ->
+ Info = [A,B],
+ R = unify(catch A + B, Info),
+ R = unify(my_apply(erlang,'+',[A,B]), Info),
+ case R of
+ _ when A + B =:= element(1,R) -> ok;
+ {{'EXIT',badarith}, Info} -> ok
+ end.
+
+op_sub(A, B) ->
+ Info = [A,B],
+ R = unify(catch A - B, Info),
+ R = unify(my_apply(erlang,'-',[A,B]), Info),
+ case R of
+ _ when A - B =:= element(1,R) -> ok;
+ {{'EXIT',badarith}, Info} -> ok
+ end.
+
+op_mul(A, B) ->
+ Info = [A,B],
+ R = unify(catch A * B, Info),
+ R = unify(my_apply(erlang,'*',[A,B]), Info),
+ case R of
+ _ when A * B =:= element(1,R) -> ok;
+ {{'EXIT',badarith}, Info} -> ok
+ end.
+
+op_div(A, B) ->
+ Info = [A,B],
+ R = unify(catch A / B, Info),
+ R = unify(my_apply(erlang,'/',[A,B]), Info),
+ case R of
+ _ when A / B =:= element(1,R) -> ok;
+ {{'EXIT',badarith}, Info} -> ok
+ end.
+
+my_apply(M, F, A) ->
+ catch apply(id(M), id(F), A).
+
+% Unify exceptions be removing stack traces.
+% and add argument info to make it easer to debug failed matches.
+unify({'EXIT',{Reason,_Stack}}, Info) ->
+ {{'EXIT', Reason}, Info};
+unify(Other, Info) ->
+ {Other, Info}.
+
+
+-define(epsilon, 1.0e-20).
+check_epsilon(R,Val) ->
+ if erlang:abs(R-Val) < ?epsilon -> ok;
+ true -> ct:fail({R,Val})
+ end.
+
+t_mul_add_ops(Config) when is_list(Config) ->
+ check_epsilon(op_mul_add(1, 2.0, 1.0, 0.0), 1.0),
+ check_epsilon(op_mul_add(2, 2.0, 1.0, 0.0), 3.0),
+ check_epsilon(op_mul_add(3, 2.0, 1.0, 0.0), 7.0),
+ check_epsilon(op_mul_add(4, 2.0, 1.0, 0.0), 15.0),
+ check_epsilon(op_mul_add(5, 2.0, 1.0, 0.0), 31.0),
+ check_epsilon(op_mul_add(6, 2.0, 1.0, 0.0), 63.0),
+ check_epsilon(op_mul_add(6, 2.0, 1.3, 0.0), 81.9),
+ check_epsilon(op_mul_add(6, 2.03, 1.3, 0.0), 87.06260151458997),
+ ok.
+
+
+op_mul_add(0, _, _, R) -> R;
+op_mul_add(N, A, B, R) when is_float(A), is_float(B), is_float(R) ->
+ op_mul_add(N - 1, A, B, R * A + B).
+
diff --git a/erts/emulator/test/float_SUITE_data/fp_drv.c b/erts/emulator/test/float_SUITE_data/fp_drv.c
index 5919dd8e2f..a91d622040 100644
--- a/erts/emulator/test/float_SUITE_data/fp_drv.c
+++ b/erts/emulator/test/float_SUITE_data/fp_drv.c
@@ -18,6 +18,7 @@
*/
#if defined(DEBUG) || 0
+# include <stdio.h>
# define PRINTF(X) printf X
#else
# define PRINTF(X)
diff --git a/erts/emulator/test/fun_SUITE.erl b/erts/emulator/test/fun_SUITE.erl
index b18f9f5c6b..044c6aabca 100644
--- a/erts/emulator/test/fun_SUITE.erl
+++ b/erts/emulator/test/fun_SUITE.erl
@@ -21,11 +21,7 @@
-module(fun_SUITE).
-compile({nowarn_deprecated_function, {erlang,hash,2}}).
--define(default_timeout, ?t:minutes(1)).
-
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2,
+-export([all/0, suite/0,
bad_apply/1,bad_fun_call/1,badarity/1,ext_badarity/1,
equality/1,ordering/1,
fun_to_port/1,t_hash/1,t_phash/1,t_phash2/1,md5/1,
@@ -35,9 +31,12 @@
-export([nothing/0]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 1}}].
-suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[bad_apply, bad_fun_call, badarity, ext_badarity,
@@ -46,45 +45,18 @@ all() ->
const_propagation, t_arity, t_is_function2, t_fun_info,
t_fun_info_mfa].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(_Case, Config) ->
- ?line Dog = test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-bad_apply(doc) ->
- "Test that the correct EXIT code is returned for all types of bad funs.";
-bad_apply(suite) -> [];
+%% Test that the correct EXIT code is returned for all types of bad funs.
bad_apply(Config) when is_list(Config) ->
- ?line bad_apply_fc(42, [0]),
- ?line bad_apply_fc(xx, [1]),
- ?line bad_apply_fc({}, [2]),
- ?line bad_apply_fc({1}, [3]),
- ?line bad_apply_fc({1,2,3}, [4]),
- ?line bad_apply_fc({1,2,3}, [5]),
- ?line bad_apply_fc({1,2,3,4}, [6]),
- ?line bad_apply_fc({1,2,3,4,5,6}, [7]),
- ?line bad_apply_fc({1,2,3,4,5}, [8]),
- ?line bad_apply_badarg({1,2}, [9]),
+ bad_apply_fc(42, [0]),
+ bad_apply_fc(xx, [1]),
+ bad_apply_fc({}, [2]),
+ bad_apply_fc({1}, [3]),
+ bad_apply_fc({1,2,3}, [4]),
+ bad_apply_fc({1,2,3}, [5]),
+ bad_apply_fc({1,2,3,4}, [6]),
+ bad_apply_fc({1,2,3,4,5,6}, [7]),
+ bad_apply_fc({1,2,3,4,5}, [8]),
+ bad_apply_badarg({1,2}, [9]),
ok.
bad_apply_fc(Fun, Args) ->
@@ -96,7 +68,7 @@ bad_apply_fc(Fun, Args) ->
ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res]);
Other ->
ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res]),
- ?t:fail({bad_result,Other})
+ ct:fail({bad_result,Other})
end.
bad_apply_badarg(Fun, Args) ->
@@ -108,23 +80,21 @@ bad_apply_badarg(Fun, Args) ->
ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res]);
Other ->
ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res]),
- ?t:fail({bad_result, Other})
+ ct:fail({bad_result, Other})
end.
-bad_fun_call(doc) ->
- "Try directly calling bad funs.";
-bad_fun_call(suite) -> [];
+%% Try directly calling bad funs.
bad_fun_call(Config) when is_list(Config) ->
- ?line bad_call_fc(42),
- ?line bad_call_fc(xx),
- ?line bad_call_fc({}),
- ?line bad_call_fc({1}),
- ?line bad_call_fc({1,2,3}),
- ?line bad_call_fc({1,2,3}),
- ?line bad_call_fc({1,2,3,4}),
- ?line bad_call_fc({1,2,3,4,5,6}),
- ?line bad_call_fc({1,2,3,4,5}),
- ?line bad_call_fc({1,2}),
+ bad_call_fc(42),
+ bad_call_fc(xx),
+ bad_call_fc({}),
+ bad_call_fc({1}),
+ bad_call_fc({1,2,3}),
+ bad_call_fc({1,2,3}),
+ bad_call_fc({1,2,3,4}),
+ bad_call_fc({1,2,3,4,5,6}),
+ bad_call_fc({1,2,3,4,5}),
+ bad_call_fc({1,2}),
ok.
bad_call_fc(Fun) ->
@@ -135,74 +105,74 @@ bad_call_fc(Fun) ->
ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]);
Other ->
ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]),
- ?t:fail({bad_result,Other})
+ ct:fail({bad_result,Other})
end.
%% Call and apply valid funs with wrong number of arguments.
badarity(Config) when is_list(Config) ->
- ?line Fun = fun() -> ok end,
- ?line Stupid = {stupid,arguments},
- ?line Args = [some,{stupid,arguments},here],
+ Fun = fun() -> ok end,
+ Stupid = {stupid,arguments},
+ Args = [some,{stupid,arguments},here],
%% Simple call.
- ?line Res = (catch Fun(some, Stupid, here)),
+ Res = (catch Fun(some, Stupid, here)),
erlang:garbage_collect(),
erlang:yield(),
case Res of
{'EXIT',{{badarity,{Fun,Args}},_}} ->
- ?line ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]);
+ ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]);
_ ->
- ?line ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]),
- ?line ?t:fail({bad_result,Res})
+ ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]),
+ ct:fail({bad_result,Res})
end,
%% Apply.
- ?line Res2 = (catch apply(Fun, Args)),
+ Res2 = (catch apply(Fun, Args)),
erlang:garbage_collect(),
erlang:yield(),
case Res2 of
{'EXIT',{{badarity,{Fun,Args}},_}} ->
- ?line ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]);
+ ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]);
_ ->
- ?line ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]),
- ?line ?t:fail({bad_result,Res2})
+ ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]),
+ ct:fail({bad_result,Res2})
end,
ok.
%% Call and apply valid external funs with wrong number of arguments.
ext_badarity(Config) when is_list(Config) ->
- ?line Fun = fun ?MODULE:nothing/0,
- ?line Stupid = {stupid,arguments},
- ?line Args = [some,{stupid,arguments},here],
+ Fun = fun ?MODULE:nothing/0,
+ Stupid = {stupid,arguments},
+ Args = [some,{stupid,arguments},here],
%% Simple call.
- ?line Res = (catch Fun(some, Stupid, here)),
+ Res = (catch Fun(some, Stupid, here)),
erlang:garbage_collect(),
erlang:yield(),
case Res of
{'EXIT',{{badarity,{Fun,Args}},_}} ->
- ?line ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]);
+ ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]);
_ ->
- ?line ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]),
- ?line ?t:fail({bad_result,Res})
+ ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]),
+ ct:fail({bad_result,Res})
end,
%% Apply.
- ?line Res2 = (catch apply(Fun, Args)),
+ Res2 = (catch apply(Fun, Args)),
erlang:garbage_collect(),
erlang:yield(),
case Res2 of
{'EXIT',{{badarity,{Fun,Args}},_}} ->
- ?line ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]);
+ ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]);
_ ->
- ?line ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]),
- ?line ?t:fail({bad_result,Res2})
+ ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]),
+ ct:fail({bad_result,Res2})
end,
ok.
@@ -214,29 +184,29 @@ nothing() ->
equality(Config) when is_list(Config) ->
F0 = fun() -> 1 end,
F0_copy = copy_term(F0),
- ?line true = eq(F0, F0),
- ?line true = eq(F0, F0_copy),
+ true = eq(F0, F0),
+ true = eq(F0, F0_copy),
%% Compare different arities.
F1 = fun(X) -> X + 1 end,
- ?line true = eq(F1, F1),
- ?line false = eq(F0, F1),
- ?line false = eq(F0_copy, F1),
+ true = eq(F1, F1),
+ false = eq(F0, F1),
+ false = eq(F0_copy, F1),
%% Compare different environments.
G1 = make_fun(1),
G2 = make_fun(2),
- ?line true = eq(G1, G1),
- ?line true = eq(G2, G2),
- ?line false = eq(G1, G2),
- ?line false = eq(G2, G1),
+ true = eq(G1, G1),
+ true = eq(G2, G2),
+ false = eq(G1, G2),
+ false = eq(G2, G1),
G1_copy = copy_term(G1),
- ?line true = eq(G1, G1_copy),
+ true = eq(G1, G1_copy),
%% Compare fun with binaries.
B = list_to_binary([7,8,9]),
- ?line false = eq(B, G1),
- ?line false = eq(G1, B),
+ false = eq(B, G1),
+ false = eq(G1, B),
%% Compare external funs.
FF0 = fun aa:blurf/0,
@@ -246,23 +216,23 @@ equality(Config) when is_list(Config) ->
FF3 = fun erlang:exit/2,
FF4 = fun z:ff/0,
- ?line true = eq(FF0, FF0),
- ?line true = eq(FF0, FF0_copy),
- ?line true = eq(FF1, FF1),
- ?line true = eq(FF2, FF2),
- ?line true = eq(FF3, FF3),
- ?line true = eq(FF4, FF4),
- ?line false = eq(FF0, FF1),
- ?line false = eq(FF0, FF2),
- ?line false = eq(FF0, FF3),
- ?line false = eq(FF0, FF4),
- ?line false = eq(FF1, FF0),
- ?line false = eq(FF1, FF2),
- ?line false = eq(FF1, FF3),
- ?line false = eq(FF1, FF4),
- ?line false = eq(FF2, FF3),
- ?line false = eq(FF2, FF4),
- ?line false = eq(FF3, FF4),
+ true = eq(FF0, FF0),
+ true = eq(FF0, FF0_copy),
+ true = eq(FF1, FF1),
+ true = eq(FF2, FF2),
+ true = eq(FF3, FF3),
+ true = eq(FF4, FF4),
+ false = eq(FF0, FF1),
+ false = eq(FF0, FF2),
+ false = eq(FF0, FF3),
+ false = eq(FF0, FF4),
+ false = eq(FF1, FF0),
+ false = eq(FF1, FF2),
+ false = eq(FF1, FF3),
+ false = eq(FF1, FF4),
+ false = eq(FF2, FF3),
+ false = eq(FF2, FF4),
+ false = eq(FF3, FF4),
%% EEP37
H1 = fun Fact(N) when N > 0 -> N * Fact(N - 1); Fact(0) -> 1 end,
@@ -285,7 +255,7 @@ copy_term(Term) ->
make_fun(X) ->
fun() -> X end.
-ordering(doc) -> "Tests ordering of funs.";
+%% Tests ordering of funs.
ordering(Config) when is_list(Config) ->
F1 = make_fun(1, 2),
F1_copy = copy_term(F1),
@@ -298,140 +268,139 @@ ordering(Config) when is_list(Config) ->
FF3 = fun erlang:exit/2,
FF4 = fun z:ff/0,
- ?line true = FF0 < FF1,
- ?line true = FF1 < FF2,
- ?line true = FF2 < FF3,
- ?line true = FF3 < FF4,
+ true = FF0 < FF1,
+ true = FF1 < FF2,
+ true = FF2 < FF3,
+ true = FF3 < FF4,
- ?line true = FF0 > F1,
- ?line true = FF0 > F2,
- ?line true = FF0 > F3,
- ?line true = FF4 > F1,
- ?line true = FF4 > F2,
- ?line true = FF4 > F3,
+ true = FF0 > F1,
+ true = FF0 > F2,
+ true = FF0 > F3,
+ true = FF4 > F1,
+ true = FF4 > F2,
+ true = FF4 > F3,
- ?line true = F1 == F1,
- ?line true = F1 == F1_copy,
- ?line true = F1 /= F2,
+ true = F1 == F1,
+ true = F1 == F1_copy,
+ true = F1 /= F2,
- ?line true = F1 < F2,
- ?line true = F2 > F1,
- ?line true = F2 < F3,
- ?line true = F3 > F2,
+ true = F1 < F2,
+ true = F2 > F1,
+ true = F2 < F3,
+ true = F3 > F2,
- ?line false = F1 > F2,
- ?line false = F2 > F3,
+ false = F1 > F2,
+ false = F2 > F3,
%% Compare with binaries.
B = list_to_binary([7,8,9,10]),
- ?line false = B == F1,
- ?line false = F1 == B,
+ false = B == F1,
+ false = F1 == B,
- ?line true = F1 < B,
- ?line true = B > F2,
+ true = F1 < B,
+ true = B > F2,
- ?line false = F1 > B,
- ?line false = B < F2,
+ false = F1 > B,
+ false = B < F2,
- ?line false = F1 >= B,
- ?line false = B =< F2,
+ false = F1 >= B,
+ false = B =< F2,
%% Compare module funs with binaries.
- ?line false = B == FF1,
- ?line false = FF1 == B,
+ false = B == FF1,
+ false = FF1 == B,
- ?line true = FF1 < B,
- ?line true = B > FF2,
+ true = FF1 < B,
+ true = B > FF2,
- ?line false = FF1 > B,
- ?line false = B < FF2,
+ false = FF1 > B,
+ false = B < FF2,
- ?line false = FF1 >= B,
- ?line false = B =< FF2,
+ false = FF1 >= B,
+ false = B =< FF2,
%% Create a port and ref.
- ?line Path = ?config(priv_dir, Config),
- ?line AFile = filename:join(Path, "vanilla_file"),
- ?line P = open_port(AFile, [out]),
- ?line R = make_ref(),
+ Path = proplists:get_value(priv_dir, Config),
+ AFile = filename:join(Path, "vanilla_file"),
+ P = open_port(AFile, [out]),
+ R = make_ref(),
%% Compare funs with ports and refs.
- ?line true = R < F3,
- ?line true = F3 > R,
- ?line true = F3 < P,
- ?line true = P > F3,
+ true = R < F3,
+ true = F3 > R,
+ true = F3 < P,
+ true = P > F3,
- ?line true = R =< F3,
- ?line true = F3 >= R,
- ?line true = F3 =< P,
- ?line true = P >= F3,
+ true = R =< F3,
+ true = F3 >= R,
+ true = F3 =< P,
+ true = P >= F3,
- ?line false = R > F3,
- ?line false = F3 < R,
- ?line false = F3 > P,
- ?line false = P < F3,
+ false = R > F3,
+ false = F3 < R,
+ false = F3 > P,
+ false = P < F3,
%% Compare funs with conses and nils.
- ?line true = F1 < [a],
- ?line true = F1 < [],
- ?line true = [a,b] > F1,
- ?line true = [] > F1,
+ true = F1 < [a],
+ true = F1 < [],
+ true = [a,b] > F1,
+ true = [] > F1,
- ?line false = [1] < F1,
- ?line false = [] < F1,
- ?line false = F1 > [2],
- ?line false = F1 > [],
+ false = [1] < F1,
+ false = [] < F1,
+ false = F1 > [2],
+ false = F1 > [],
- ?line false = [1] =< F1,
- ?line false = [] =< F1,
- ?line false = F1 >= [2],
- ?line false = F1 >= [],
+ false = [1] =< F1,
+ false = [] =< F1,
+ false = F1 >= [2],
+ false = F1 >= [],
%% Compare module funs with conses and nils.
- ?line true = FF1 < [a],
- ?line true = FF1 < [],
- ?line true = [a,b] > FF1,
- ?line true = [] > FF1,
+ true = FF1 < [a],
+ true = FF1 < [],
+ true = [a,b] > FF1,
+ true = [] > FF1,
- ?line false = [1] < FF1,
- ?line false = [] < FF1,
- ?line false = FF1 > [2],
- ?line false = FF1 > [],
+ false = [1] < FF1,
+ false = [] < FF1,
+ false = FF1 > [2],
+ false = FF1 > [],
- ?line false = [1] =< FF1,
- ?line false = [] =< FF1,
- ?line false = FF1 >= [2],
- ?line false = FF1 >= [],
+ false = [1] =< FF1,
+ false = [] =< FF1,
+ false = FF1 >= [2],
+ false = FF1 >= [],
ok.
make_fun(X, Y) ->
fun(A) -> A*X+Y end.
-fun_to_port(doc) -> "Try sending funs to ports (should fail).";
-fun_to_port(suite) -> [];
+%% Try sending funs to ports (should fail).
fun_to_port(Config) when is_list(Config) ->
- ?line fun_to_port(Config, xxx),
- ?line fun_to_port(Config, fun() -> 42 end),
- ?line fun_to_port(Config, [fun() -> 43 end]),
- ?line fun_to_port(Config, [1,fun() -> 44 end]),
- ?line fun_to_port(Config, [0,1|fun() -> 45 end]),
+ fun_to_port(Config, xxx),
+ fun_to_port(Config, fun() -> 42 end),
+ fun_to_port(Config, [fun() -> 43 end]),
+ fun_to_port(Config, [1,fun() -> 44 end]),
+ fun_to_port(Config, [0,1|fun() -> 45 end]),
B64K = build_io_list(65536),
- ?line fun_to_port(Config, [B64K,fun() -> 45 end]),
- ?line fun_to_port(Config, [B64K|fun() -> 45 end]),
+ fun_to_port(Config, [B64K,fun() -> 45 end]),
+ fun_to_port(Config, [B64K|fun() -> 45 end]),
ok.
fun_to_port(Config, IoList) ->
- Path = ?config(priv_dir, Config),
+ Path = proplists:get_value(priv_dir, Config),
AFile = filename:join(Path, "vanilla_file"),
Port = open_port(AFile, [out]),
case catch port_command(Port, IoList) of
{'EXIT',{badarg,_}} -> ok;
- Other -> ?t:fail({unexpected_retval,Other})
+ Other -> ct:fail({unexpected_retval,Other})
end.
build_io_list(0) -> [];
@@ -443,86 +412,83 @@ build_io_list(N) ->
1 -> [7,L|L]
end.
-t_hash(doc) -> "Test the hash/2 BIF on funs.";
-t_hash(suite) -> [];
+%% Test the hash/2 BIF on funs.
t_hash(Config) when is_list(Config) ->
F1 = fun(_X) -> 1 end,
F2 = fun(_X) -> 2 end,
- ?line true = hash(F1) /= hash(F2),
+ true = hash(F1) /= hash(F2),
G1 = make_fun(1, 2, 3),
G2 = make_fun(1, 2, 3),
G3 = make_fun(1, 2, 4),
- ?line true = hash(G1) == hash(G2),
- ?line true = hash(G2) /= hash(G3),
+ true = hash(G1) == hash(G2),
+ true = hash(G2) /= hash(G3),
FF0 = fun erlang:abs/1,
FF1 = fun erlang:exit/1,
FF2 = fun erlang:exit/2,
FF3 = fun blurf:exit/2,
- ?line true = hash(FF0) =/= hash(FF1),
- ?line true = hash(FF0) =/= hash(FF2),
- ?line true = hash(FF0) =/= hash(FF3),
- ?line true = hash(FF1) =/= hash(FF2),
- ?line true = hash(FF1) =/= hash(FF3),
- ?line true = hash(FF2) =/= hash(FF3),
+ true = hash(FF0) =/= hash(FF1),
+ true = hash(FF0) =/= hash(FF2),
+ true = hash(FF0) =/= hash(FF3),
+ true = hash(FF1) =/= hash(FF2),
+ true = hash(FF1) =/= hash(FF3),
+ true = hash(FF2) =/= hash(FF3),
ok.
hash(Term) ->
erlang:hash(Term, 16#7ffffff).
-t_phash(doc) -> "Test the phash/2 BIF on funs.";
-t_phash(suite) -> [];
+%% Test the phash/2 BIF on funs.
t_phash(Config) when is_list(Config) ->
F1 = fun(_X) -> 1 end,
F2 = fun(_X) -> 2 end,
- ?line true = phash(F1) /= phash(F2),
+ true = phash(F1) /= phash(F2),
G1 = make_fun(1, 2, 3),
G2 = make_fun(1, 2, 3),
G3 = make_fun(1, 2, 4),
- ?line true = phash(G1) == phash(G2),
- ?line true = phash(G2) /= phash(G3),
+ true = phash(G1) == phash(G2),
+ true = phash(G2) /= phash(G3),
FF0 = fun erlang:abs/1,
FF1 = fun erlang:exit/1,
FF2 = fun erlang:exit/2,
FF3 = fun blurf:exit/2,
- ?line true = phash(FF0) =/= phash(FF1),
- ?line true = phash(FF0) =/= phash(FF2),
- ?line true = phash(FF0) =/= phash(FF3),
- ?line true = phash(FF1) =/= phash(FF2),
- ?line true = phash(FF1) =/= phash(FF3),
- ?line true = phash(FF2) =/= phash(FF3),
+ true = phash(FF0) =/= phash(FF1),
+ true = phash(FF0) =/= phash(FF2),
+ true = phash(FF0) =/= phash(FF3),
+ true = phash(FF1) =/= phash(FF2),
+ true = phash(FF1) =/= phash(FF3),
+ true = phash(FF2) =/= phash(FF3),
ok.
phash(Term) ->
erlang:phash(Term, 16#7ffffff).
-t_phash2(doc) -> "Test the phash2/2 BIF on funs.";
-t_phash2(suite) -> [];
+%% Test the phash2/2 BIF on funs.
t_phash2(Config) when is_list(Config) ->
F1 = fun(_X) -> 1 end,
F2 = fun(_X) -> 2 end,
- ?line true = phash2(F1) /= phash2(F2),
+ true = phash2(F1) /= phash2(F2),
G1 = make_fun(1, 2, 3),
G2 = make_fun(1, 2, 3),
G3 = make_fun(1, 2, 4),
- ?line true = phash2(G1) == phash2(G2),
- ?line true = phash2(G2) /= phash2(G3),
+ true = phash2(G1) == phash2(G2),
+ true = phash2(G2) /= phash2(G3),
FF0 = fun erlang:abs/1,
FF1 = fun erlang:exit/1,
FF2 = fun erlang:exit/2,
FF3 = fun blurf:exit/2,
- ?line true = phash2(FF0) =/= phash2(FF1),
- ?line true = phash2(FF0) =/= phash2(FF2),
- ?line true = phash2(FF0) =/= phash2(FF3),
- ?line true = phash2(FF1) =/= phash2(FF2),
- ?line true = phash2(FF1) =/= phash2(FF3),
- ?line true = phash2(FF2) =/= phash2(FF3),
+ true = phash2(FF0) =/= phash2(FF1),
+ true = phash2(FF0) =/= phash2(FF2),
+ true = phash2(FF0) =/= phash2(FF3),
+ true = phash2(FF1) =/= phash2(FF2),
+ true = phash2(FF1) =/= phash2(FF3),
+ true = phash2(FF2) =/= phash2(FF3),
ok.
@@ -532,52 +498,51 @@ phash2(Term) ->
make_fun(X, Y, Z) ->
fun() -> {X,Y,Z} end.
-md5(doc) -> "Test that MD5 bifs reject funs properly.";
-md5(suite) -> [];
+%% Test that MD5 bifs reject funs properly.
md5(Config) when is_list(Config) ->
_ = size(erlang:md5_init()),
%% Try funs in the i/o list.
- ?line bad_md5(fun(_X) -> 42 end),
- ?line bad_md5([fun(_X) -> 43 end]),
- ?line bad_md5([1,fun(_X) -> 44 end]),
- ?line bad_md5([1|fun(_X) -> 45 end]),
- ?line B64K = build_io_list(65536),
- ?line bad_md5([B64K,fun(_X) -> 46 end]),
- ?line bad_md5([B64K|fun(_X) -> 46 end]),
+ bad_md5(fun(_X) -> 42 end),
+ bad_md5([fun(_X) -> 43 end]),
+ bad_md5([1,fun(_X) -> 44 end]),
+ bad_md5([1|fun(_X) -> 45 end]),
+ B64K = build_io_list(65536),
+ bad_md5([B64K,fun(_X) -> 46 end]),
+ bad_md5([B64K|fun(_X) -> 46 end]),
ok.
bad_md5(Bad) ->
{'EXIT',{badarg,_}} = (catch erlang:md5(Bad)).
refc(Config) when is_list(Config) ->
- ?line F1 = fun_factory(2),
- ?line {refc,2} = erlang:fun_info(F1, refc),
- ?line F2 = fun_factory(42),
- ?line {refc,3} = erlang:fun_info(F1, refc),
+ F1 = fun_factory(2),
+ {refc,2} = erlang:fun_info(F1, refc),
+ F2 = fun_factory(42),
+ {refc,3} = erlang:fun_info(F1, refc),
- ?line process_flag(trap_exit, true),
- ?line Pid = spawn_link(fun() -> {refc,4} = erlang:fun_info(F1, refc) end),
+ process_flag(trap_exit, true),
+ Pid = spawn_link(fun() -> {refc,4} = erlang:fun_info(F1, refc) end),
receive
{'EXIT',Pid,normal} -> ok;
- Other -> ?line ?t:fail({unexpected,Other})
+ Other -> ct:fail({unexpected,Other})
end,
- ?line process_flag(trap_exit, false),
- ?line {refc,3} = erlang:fun_info(F1, refc),
+ process_flag(trap_exit, false),
+ {refc,3} = erlang:fun_info(F1, refc),
%% Garbage collect. Only the F2 fun will be left.
- ?line 7 = F1(5),
- ?line true = erlang:garbage_collect(),
- ?line 40 = F2(-2),
- ?line {refc,2} = erlang:fun_info(F2, refc),
+ 7 = F1(5),
+ true = erlang:garbage_collect(),
+ 40 = F2(-2),
+ {refc,2} = erlang:fun_info(F2, refc),
ok.
fun_factory(Const) ->
fun(X) -> X + Const end.
refc_ets(Config) when is_list(Config) ->
- ?line F = fun(X) -> X + 33 end,
- ?line {refc,2} = erlang:fun_info(F, refc),
+ F = fun(X) -> X + 33 end,
+ {refc,2} = erlang:fun_info(F, refc),
refc_ets_set(F, [set]),
refc_ets_set(F, [ordered_set]),
@@ -586,115 +551,112 @@ refc_ets(Config) when is_list(Config) ->
ok.
refc_ets_set(F1, Options) ->
- ?line io:format("~p", [Options]),
- ?line Tab = ets:new(kalle, Options),
- ?line true = ets:insert(Tab, {a_key,F1}),
- ?line 3 = fun_refc(F1),
- ?line [{a_key,F3}] = ets:lookup(Tab, a_key),
- ?line 4 = fun_refc(F1),
- ?line true = ets:insert(Tab, {a_key,not_a_fun}),
- ?line 3 = fun_refc(F1),
- ?line true = ets:insert(Tab, {another_key,F1}),
- ?line 4 = fun_refc(F1),
- ?line true = ets:delete(Tab),
- ?line 3 = fun_refc(F1),
- ?line 10 = F3(-23),
- ?line true = erlang:garbage_collect(),
- ?line 2 = fun_refc(F1),
+ io:format("~p", [Options]),
+ Tab = ets:new(kalle, Options),
+ true = ets:insert(Tab, {a_key,F1}),
+ 3 = fun_refc(F1),
+ [{a_key,F3}] = ets:lookup(Tab, a_key),
+ 4 = fun_refc(F1),
+ true = ets:insert(Tab, {a_key,not_a_fun}),
+ 3 = fun_refc(F1),
+ true = ets:insert(Tab, {another_key,F1}),
+ 4 = fun_refc(F1),
+ true = ets:delete(Tab),
+ 3 = fun_refc(F1),
+ 10 = F3(-23),
+ true = erlang:garbage_collect(),
+ 2 = fun_refc(F1),
ok.
refc_ets_bag(F1, Options) ->
- ?line io:format("~p", [Options]),
- ?line Tab = ets:new(kalle, Options),
- ?line true = ets:insert(Tab, {a_key,F1}),
- ?line 3 = fun_refc(F1),
- ?line [{a_key,F3}] = ets:lookup(Tab, a_key),
- ?line 4 = fun_refc(F1),
- ?line true = ets:insert(Tab, {a_key,not_a_fun}),
- ?line 4 = fun_refc(F1),
- ?line true = ets:insert(Tab, {another_key,F1}),
- ?line 5 = fun_refc(F1),
- ?line true = ets:delete(Tab),
- ?line 3 = fun_refc(F1),
- ?line 10 = F3(-23),
- ?line true = erlang:garbage_collect(),
- ?line 2 = fun_refc(F1),
+ io:format("~p", [Options]),
+ Tab = ets:new(kalle, Options),
+ true = ets:insert(Tab, {a_key,F1}),
+ 3 = fun_refc(F1),
+ [{a_key,F3}] = ets:lookup(Tab, a_key),
+ 4 = fun_refc(F1),
+ true = ets:insert(Tab, {a_key,not_a_fun}),
+ 4 = fun_refc(F1),
+ true = ets:insert(Tab, {another_key,F1}),
+ 5 = fun_refc(F1),
+ true = ets:delete(Tab),
+ 3 = fun_refc(F1),
+ 10 = F3(-23),
+ true = erlang:garbage_collect(),
+ 2 = fun_refc(F1),
ok.
refc_dist(Config) when is_list(Config) ->
- ?line {ok,Node} = start_node(fun_SUITE_refc_dist),
- ?line process_flag(trap_exit, true),
- ?line Pid = spawn_link(Node,
- fun() -> receive
- Fun when is_function(Fun) ->
- 2 = fun_refc(Fun),
- exit({normal,Fun}) end
- end),
- ?line F = fun() -> 42 end,
- ?line 2 = fun_refc(F),
- ?line Pid ! F,
+ {ok,Node} = start_node(fun_SUITE_refc_dist),
+ process_flag(trap_exit, true),
+ Pid = spawn_link(Node, fun() -> receive
+ Fun when is_function(Fun) ->
+ 2 = fun_refc(Fun),
+ exit({normal,Fun}) end
+ end),
+ F = fun() -> 42 end,
+ 2 = fun_refc(F),
+ Pid ! F,
F2 = receive
{'EXIT',Pid,{normal,Fun}} -> Fun;
- Other -> ?line ?t:fail({unexpected,Other})
+ Other -> ct:fail({unexpected,Other})
end,
%% dist.c:net_mess2 have a reference to Fun for a while since
%% Fun is passed in an exit signal. Wait until it is gone.
- ?line wait_until(fun () -> 4 =/= fun_refc(F2) end),
- ?line 3 = fun_refc(F2),
- ?line true = erlang:garbage_collect(),
- ?line 2 = fun_refc(F),
+ wait_until(fun () -> 4 =/= fun_refc(F2) end),
+ 3 = fun_refc(F2),
+ true = erlang:garbage_collect(),
+ 2 = fun_refc(F),
refc_dist_send(Node, F).
refc_dist_send(Node, F) ->
- ?line Pid = spawn_link(Node,
- fun() -> receive
- {To,Fun} when is_function(Fun) ->
- wait_until(fun () ->
- 2 =:= fun_refc(Fun)
- end),
- To ! Fun
- end
- end),
- ?line 2 = fun_refc(F),
+ Pid = spawn_link(Node, fun() -> receive
+ {To,Fun} when is_function(Fun) ->
+ wait_until(fun () ->
+ 2 =:= fun_refc(Fun)
+ end),
+ To ! Fun
+ end
+ end),
+ 2 = fun_refc(F),
Pid ! {self(),F},
F2 = receive
Fun when is_function(Fun) -> Fun;
- Other -> ?line ?t:fail({unexpected,Other})
+ Other -> ct:fail({unexpected,Other})
end,
receive {'EXIT',Pid,normal} -> ok end,
%% No reference from dist.c:net_mess2 since Fun is passed
%% in an ordinary message.
- ?line 3 = fun_refc(F),
- ?line 3 = fun_refc(F2),
+ 3 = fun_refc(F),
+ 3 = fun_refc(F2),
refc_dist_reg_send(Node, F).
refc_dist_reg_send(Node, F) ->
- ?line true = erlang:garbage_collect(),
- ?line 2 = fun_refc(F),
- ?line Ref = make_ref(),
- ?line Me = self(),
- ?line Pid = spawn_link(Node,
- fun() ->
- true = register(my_fun_tester, self()),
- Me ! Ref,
- receive
- {Me,Fun} when is_function(Fun) ->
- 2 = fun_refc(Fun),
- Me ! Fun
- end
- end),
+ true = erlang:garbage_collect(),
+ 2 = fun_refc(F),
+ Ref = make_ref(),
+ Me = self(),
+ Pid = spawn_link(Node, fun() ->
+ true = register(my_fun_tester, self()),
+ Me ! Ref,
+ receive
+ {Me,Fun} when is_function(Fun) ->
+ 2 = fun_refc(Fun),
+ Me ! Fun
+ end
+ end),
erlang:yield(),
- ?line 2 = fun_refc(F),
+ 2 = fun_refc(F),
receive Ref -> ok end,
{my_fun_tester,Node} ! {self(),F},
F2 = receive
Fun when is_function(Fun) -> Fun;
- Other -> ?line ?t:fail({unexpected,Other})
+ Other -> ct:fail({unexpected,Other})
end,
receive {'EXIT',Pid,normal} -> ok end,
- ?line 3 = fun_refc(F),
- ?line 3 = fun_refc(F2),
+ 3 = fun_refc(F),
+ 3 = fun_refc(F2),
ok.
fun_refc(F) ->
@@ -702,67 +664,67 @@ fun_refc(F) ->
Count.
const_propagation(Config) when is_list(Config) ->
- ?line Fun1 = fun start_node/1,
- ?line 2 = fun_refc(Fun1),
- ?line Fun2 = Fun1,
- ?line my_cmp({Fun1,Fun2}),
-
- ?line Fun3 = fun() -> ok end,
- ?line 2 = fun_refc(Fun3),
- ?line Fun4 = Fun3,
- ?line my_cmp({Fun3,Fun4}),
+ Fun1 = fun start_node/1,
+ 2 = fun_refc(Fun1),
+ Fun2 = Fun1,
+ my_cmp({Fun1,Fun2}),
+
+ Fun3 = fun() -> ok end,
+ 2 = fun_refc(Fun3),
+ Fun4 = Fun3,
+ my_cmp({Fun3,Fun4}),
ok.
my_cmp({Fun,Fun}) -> ok;
my_cmp({Fun1,Fun2}) ->
io:format("Fun1: ~p", [erlang:fun_info(Fun1)]),
io:format("Fun2: ~p", [erlang:fun_info(Fun2)]),
- ?t:fail().
+ ct:fail(no_match).
t_arity(Config) when is_list(Config) ->
- ?line 0 = fun_arity(fun() -> ok end),
- ?line 0 = fun_arity(fun() -> Config end),
- ?line 1 = fun_arity(fun(X) -> X+1 end),
- ?line 1 = fun_arity(fun(X) -> Config =:= X end),
+ 0 = fun_arity(fun() -> ok end),
+ 0 = fun_arity(fun() -> Config end),
+ 1 = fun_arity(fun(X) -> X+1 end),
+ 1 = fun_arity(fun(X) -> Config =:= X end),
A = id(42),
%% Test that the arity is transferred properly.
- ?line process_flag(trap_exit, true),
- ?line {ok,Node} = start_node(fun_test_arity),
- ?line hello_world = spawn_call(Node, fun() -> hello_world end),
- ?line 0 = spawn_call(Node, fun(X) -> X end),
- ?line 42 = spawn_call(Node, fun(_X) -> A end),
- ?line 43 = spawn_call(Node, fun(X, Y) -> A+X+Y end),
- ?line 1 = spawn_call(Node, fun(X, Y) -> X+Y end),
- ?line 45 = spawn_call(Node, fun(X, Y, Z) -> A+X+Y+Z end),
+ process_flag(trap_exit, true),
+ {ok,Node} = start_node(fun_test_arity),
+ hello_world = spawn_call(Node, fun() -> hello_world end),
+ 0 = spawn_call(Node, fun(X) -> X end),
+ 42 = spawn_call(Node, fun(_X) -> A end),
+ 43 = spawn_call(Node, fun(X, Y) -> A+X+Y end),
+ 1 = spawn_call(Node, fun(X, Y) -> X+Y end),
+ 45 = spawn_call(Node, fun(X, Y, Z) -> A+X+Y+Z end),
ok.
t_is_function2(Config) when is_list(Config) ->
false = is_function(id({a,b}), 0),
false = is_function(id({a,b}), 234343434333433433),
- ?line true = is_function(fun() -> ok end, 0),
- ?line true = is_function(fun(_) -> ok end, 1),
- ?line false = is_function(fun(_) -> ok end, 0),
+ true = is_function(fun() -> ok end, 0),
+ true = is_function(fun(_) -> ok end, 1),
+ false = is_function(fun(_) -> ok end, 0),
- ?line true = is_function(fun erlang:abs/1, 1),
- ?line true = is_function(fun erlang:abs/99, 99),
- ?line false = is_function(fun erlang:abs/1, 0),
- ?line false = is_function(fun erlang:abs/99, 0),
+ true = is_function(fun erlang:abs/1, 1),
+ true = is_function(fun erlang:abs/99, 99),
+ false = is_function(fun erlang:abs/1, 0),
+ false = is_function(fun erlang:abs/99, 0),
- ?line false = is_function(id(self()), 0),
- ?line false = is_function(id({a,b,c}), 0),
- ?line false = is_function(id({a}), 0),
- ?line false = is_function(id([a,b,c]), 0),
+ false = is_function(id(self()), 0),
+ false = is_function(id({a,b,c}), 0),
+ false = is_function(id({a}), 0),
+ false = is_function(id([a,b,c]), 0),
%% Bad arity argument.
- ?line bad_arity(a),
- ?line bad_arity(-1),
- ?line bad_arity(-9738974938734938793873498378),
- ?line bad_arity([]),
- ?line bad_arity(fun() -> ok end),
- ?line bad_arity({}),
- ?line bad_arity({a,b}),
- ?line bad_arity(self()),
+ bad_arity(a),
+ bad_arity(-1),
+ bad_arity(-9738974938734938793873498378),
+ bad_arity([]),
+ bad_arity(fun() -> ok end),
+ bad_arity({}),
+ bad_arity({a,b}),
+ bad_arity(self()),
ok.
bad_arity(A) ->
@@ -771,59 +733,57 @@ bad_arity(A) ->
ok.
t_fun_info(Config) when is_list(Config) ->
- ?line F = fun t_fun_info/1,
- ?line try F(blurf) of
+ F = fun t_fun_info/1,
+ try F(blurf) of
FAny ->
- io:format("should fail; returned ~p\n", [FAny]),
- ?line ?t:fail()
+ ct:fail("should fail; returned ~p\n", [FAny])
catch
error:function_clause -> ok
end,
- ?line {module,?MODULE} = erlang:fun_info(F, module),
- ?line case erlang:fun_info(F, name) of
+ {module,?MODULE} = erlang:fun_info(F, module),
+ case erlang:fun_info(F, name) of
undefined ->
- ?line ?t:fail();
+ ct:fail(no_fun_info);
_ -> ok
end,
- ?line {arity,1} = erlang:fun_info(F, arity),
- ?line {env,[]} = erlang:fun_info(F, env),
- ?line verify_not_undef(F, index),
- ?line verify_not_undef(F, uniq),
- ?line verify_not_undef(F, new_index),
- ?line verify_not_undef(F, new_uniq),
- ?line verify_not_undef(F, refc),
- ?line {'EXIT',_} = (catch erlang:fun_info(F, blurf)),
+ {arity,1} = erlang:fun_info(F, arity),
+ {env,[]} = erlang:fun_info(F, env),
+ verify_not_undef(F, index),
+ verify_not_undef(F, uniq),
+ verify_not_undef(F, new_index),
+ verify_not_undef(F, new_uniq),
+ verify_not_undef(F, refc),
+ {'EXIT',_} = (catch erlang:fun_info(F, blurf)),
%% Module fun.
- ?line FF = fun ?MODULE:t_fun_info/1,
- ?line try FF(blurf) of
+ FF = fun ?MODULE:t_fun_info/1,
+ try FF(blurf) of
FFAny ->
- io:format("should fail; returned ~p\n", [FFAny]),
- ?line ?t:fail()
+ ct:fail("should fail; returned ~p\n", [FFAny])
catch
error:function_clause -> ok
end,
- ?line {module,?MODULE} = erlang:fun_info(FF, module),
- ?line {name,t_fun_info} = erlang:fun_info(FF, name),
- ?line {arity,1} = erlang:fun_info(FF, arity),
- ?line {env,[]} = erlang:fun_info(FF, env),
- ?line verify_undef(FF, index),
- ?line verify_undef(FF, uniq),
- ?line verify_undef(FF, new_index),
- ?line verify_undef(FF, new_uniq),
- ?line verify_undef(FF, refc),
- ?line {'EXIT',_} = (catch erlang:fun_info(FF, blurf)),
+ {module,?MODULE} = erlang:fun_info(FF, module),
+ {name,t_fun_info} = erlang:fun_info(FF, name),
+ {arity,1} = erlang:fun_info(FF, arity),
+ {env,[]} = erlang:fun_info(FF, env),
+ verify_undef(FF, index),
+ verify_undef(FF, uniq),
+ verify_undef(FF, new_index),
+ verify_undef(FF, new_uniq),
+ verify_undef(FF, refc),
+ {'EXIT',_} = (catch erlang:fun_info(FF, blurf)),
%% Not fun.
- ?line bad_info(abc),
- ?line bad_info(42),
- ?line bad_info({fun erlang:list_to_integer/1}),
- ?line bad_info([42]),
- ?line bad_info([]),
- ?line bad_info(self()),
- ?line bad_info(<<>>),
- ?line bad_info(<<1,2>>),
+ bad_info(abc),
+ bad_info(42),
+ bad_info({fun erlang:list_to_integer/1}),
+ bad_info([42]),
+ bad_info([]),
+ bad_info(self()),
+ bad_info(<<>>),
+ bad_info(<<1,2>>),
ok.
t_fun_info_mfa(Config) when is_list(Config) ->
@@ -847,8 +807,7 @@ t_fun_info_mfa(Config) when is_list(Config) ->
bad_info(Term) ->
try erlang:fun_info(Term, module) of
Any ->
- io:format("should fail; returned ~p\n", [Any]),
- ?t:fail()
+ ict:fail("should fail; returned ~p\n", [Any])
catch
error:badarg -> ok
end.
@@ -859,7 +818,7 @@ verify_undef(Fun, Tag) ->
verify_not_undef(Fun, Tag) ->
case erlang:fun_info(Fun, Tag) of
{Tag,undefined} ->
- ?t:fail();
+ ct:fail("tag ~w not defined in fun_info", [Tag]);
{Tag,_} -> ok
end.
@@ -884,15 +843,15 @@ spawn_call(Node, AFun) ->
Pid ! {AFun,AFun,AFun},
Res = receive
{result,R} -> R;
- Other -> ?t:fail({bad_message,Other})
+ Other -> ct:fail({bad_message,Other})
after 10000 ->
- ?t:fail(timeout_waiting_for_result)
+ ct:fail(timeout_waiting_for_result)
end,
receive
{'EXIT',Pid,normal} -> ok;
- Other2 -> ?t:fail({bad_message_waiting_for_exit,Other2})
+ Other2 -> ct:fail({bad_message_waiting_for_exit,Other2})
after 10000 ->
- ?t:fail(timeout_waiting_for_exit)
+ ct:fail(timeout_waiting_for_exit)
end,
Res.
@@ -911,6 +870,3 @@ wait_until(Fun) ->
true -> ok;
_ -> receive after 100 -> wait_until(Fun) end
end.
-
-% stop_node(Node) ->
-% test_server:stop_node(Node).
diff --git a/erts/emulator/test/fun_r13_SUITE.erl b/erts/emulator/test/fun_r13_SUITE.erl
index 7ab5e65cb3..d66026705b 100644
--- a/erts/emulator/test/fun_r13_SUITE.erl
+++ b/erts/emulator/test/fun_r13_SUITE.erl
@@ -21,77 +21,53 @@
-module(fun_r13_SUITE).
-compile(r13).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2,dist_old_release/1]).
+-export([all/0, suite/0,
+ dist_old_release/1]).
--define(default_timeout, ?t:minutes(1)).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 1}}].
all() ->
[dist_old_release].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(_Case, Config) ->
- ?line Dog = test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
dist_old_release(Config) when is_list(Config) ->
- case ?t:is_release_available("r12b") of
- true -> do_dist_old(Config);
- false -> {skip,"No R12B found"}
+ case test_server:is_release_available("r12b") of
+ true -> do_dist_old(Config);
+ false -> {skip,"No R12B found"}
end.
do_dist_old(Config) when is_list(Config) ->
- ?line Pa = filename:dirname(code:which(?MODULE)),
+ Pa = filename:dirname(code:which(?MODULE)),
Name = fun_dist_r12,
- ?line {ok,Node} = ?t:start_node(Name, peer,
- [{args,"-pa "++Pa},
- {erl,[{release,"r12b"}]}]),
-
- ?line Pid = spawn_link(Node,
- fun() ->
- receive
- Fun when is_function(Fun) ->
- R12BFun = fun(H) -> cons(H, [b,c]) end,
- Fun(Fun, R12BFun)
- end
- end),
+ {ok,Node} = test_server:start_node(Name, peer,
+ [{args,"-pa "++Pa},
+ {erl,[{release,"r12b"}]}]),
+
+ Pid = spawn_link(Node,
+ fun() ->
+ receive
+ Fun when is_function(Fun) ->
+ R12BFun = fun(H) -> cons(H, [b,c]) end,
+ Fun(Fun, R12BFun)
+ end
+ end),
Self = self(),
Fun = fun(F, R12BFun) ->
- {pid,Self} = erlang:fun_info(F, pid),
- {module,?MODULE} = erlang:fun_info(F, module),
- Self ! {ok,F,R12BFun}
- end,
- ?line Pid ! Fun,
- ?line receive
- {ok,Fun,R12BFun} ->
- ?line [a,b,c] = R12BFun(a);
- Other ->
- ?line ?t:fail({bad_message,Other})
- end,
+ {pid,Self} = erlang:fun_info(F, pid),
+ {module,?MODULE} = erlang:fun_info(F, module),
+ Self ! {ok,F,R12BFun}
+ end,
+ Pid ! Fun,
+ receive
+ {ok,Fun,R12BFun} ->
+ [a,b,c] = R12BFun(a);
+ Other ->
+ ct:fail({bad_message,Other})
+ end,
+ true = test_server:stop_node(Node),
ok.
cons(H, T) ->
diff --git a/erts/emulator/test/gc_SUITE.erl b/erts/emulator/test/gc_SUITE.erl
index 1e155e7b09..8e5f0b05a1 100644
--- a/erts/emulator/test/gc_SUITE.erl
+++ b/erts/emulator/test/gc_SUITE.erl
@@ -22,45 +22,27 @@
-module(gc_SUITE).
--include_lib("test_server/include/test_server.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
--define(default_timeout, ?t:minutes(10)).
+-include_lib("common_test/include/ct.hrl").
+-export([all/0, suite/0]).
-export([grow_heap/1, grow_stack/1, grow_stack_heap/1]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]}].
all() ->
[grow_heap, grow_stack, grow_stack_heap].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-grow_heap(doc) -> ["Produce a growing list of elements, ",
- "for X calls, then drop one item per call",
- "until the list is empty."];
+%% Produce a growing list of elements,
+%% for X calls, then drop one item per call
+%% until the list is empty.
grow_heap(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:minutes(40)),
+ ct:timetrap({minutes, 40}),
ok = grow_heap1(256),
ok = grow_heap1(512),
ok = grow_heap1(1024),
ok = grow_heap1(2048),
- test_server:timetrap_cancel(Dog),
ok.
grow_heap1(Len) ->
@@ -86,14 +68,13 @@ grow_heap1([_|List], MaxLen, CurLen, down) ->
-grow_stack(doc) -> ["Increase and decrease stack size, and ",
- "drop off some garbage from time to time."];
+%% Increase and decrease stack size, and
+%% drop off some garbage from time to time.
grow_stack(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:minutes(80)),
+ ct:timetrap({minutes, 80}),
show_heap("before:"),
grow_stack1(200, 0),
show_heap("after:"),
- test_server:timetrap_cancel(Dog),
ok.
grow_stack1(0, _) ->
@@ -110,14 +91,12 @@ grow_stack1(Recs, CurRecs) ->
%% Let's see how BEAM handles this one...
-grow_stack_heap(doc) -> ["While growing the heap, bounces the size ",
- "of the stack, and while reducing the heap",
- "bounces the stack usage."];
+%% While growing the heap, bounces the size of the
+%% stack, and while reducing the heap, bounces the stack usage.
grow_stack_heap(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:minutes(40)),
+ ct:timetrap({minutes, 40}),
grow_stack_heap1(16),
grow_stack_heap1(32),
- test_server:timetrap_cancel(Dog),
ok.
grow_stack_heap1(MaxLen) ->
diff --git a/erts/emulator/test/guard_SUITE.erl b/erts/emulator/test/guard_SUITE.erl
index b3a85c6423..6ad4456e6b 100644
--- a/erts/emulator/test/guard_SUITE.erl
+++ b/erts/emulator/test/guard_SUITE.erl
@@ -20,12 +20,12 @@
-module(guard_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2, bad_arith/1, bad_tuple/1,
+-export([all/0, suite/0,
+ bad_arith/1, bad_tuple/1,
test_heap_guards/1, guard_bifs/1,
type_tests/1,guard_bif_binary_part/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([init/3]).
-import(lists, [member/2]).
@@ -36,27 +36,12 @@ all() ->
[bad_arith, bad_tuple, test_heap_guards, guard_bifs,
type_tests, guard_bif_binary_part].
-groups() ->
- [].
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-bad_arith(doc) -> "Test that a bad arithmetic operation in a guard works correctly.";
+%% Test that a bad arithmetic operation in a guard works correctly.
bad_arith(Config) when is_list(Config) ->
- ?line 5 = bad_arith1(2, 3),
- ?line 10 = bad_arith1(1, infinity),
- ?line 10 = bad_arith1(infinity, 1),
+ 5 = bad_arith1(2, 3),
+ 10 = bad_arith1(1, infinity),
+ 10 = bad_arith1(infinity, 1),
ok.
bad_arith1(T1, T2) when T1+T2 < 10 ->
@@ -64,12 +49,12 @@ bad_arith1(T1, T2) when T1+T2 < 10 ->
bad_arith1(_, _) ->
10.
-bad_tuple(doc) -> "Test that bad arguments to element/2 are handled correctly.";
+%% Test that bad arguments to element/2 are handled correctly.
bad_tuple(Config) when is_list(Config) ->
- ?line error = bad_tuple1(a),
- ?line error = bad_tuple1({a, b}),
- ?line x = bad_tuple1({x, b}),
- ?line y = bad_tuple1({a, b, y}),
+ error = bad_tuple1(a),
+ error = bad_tuple1({a, b}),
+ x = bad_tuple1({x, b}),
+ y = bad_tuple1({a, b, y}),
ok.
bad_tuple1(T) when element(1, T) == x ->
@@ -79,26 +64,25 @@ bad_tuple1(T) when element(3, T) == y ->
bad_tuple1(_) ->
error.
-test_heap_guards(doc) -> "";
test_heap_guards(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(2)),
+ ct:timetrap({minutes, 2}),
- ?line process_flag(trap_exit, true),
- ?line Tuple = {a, tuple, is, built, here, xxx},
- ?line List = [a, list, is, built, here],
+ process_flag(trap_exit, true),
+ Tuple = {a, tuple, is, built, here, xxx},
+ List = [a, list, is, built, here],
- ?line 'try'(fun a_case/1, [Tuple], [Tuple]),
- ?line 'try'(fun a_case/1, [List], [List, List]),
- ?line 'try'(fun a_case/1, [a], [a]),
+ 'try'(fun a_case/1, [Tuple], [Tuple]),
+ 'try'(fun a_case/1, [List], [List, List]),
+ 'try'(fun a_case/1, [a], [a]),
- ?line 'try'(fun an_if/1, [Tuple], [Tuple]),
- ?line 'try'(fun an_if/1, [List], [List, List]),
- ?line 'try'(fun an_if/1, [a], [a]),
+ 'try'(fun an_if/1, [Tuple], [Tuple]),
+ 'try'(fun an_if/1, [List], [List, List]),
+ 'try'(fun an_if/1, [a], [a]),
- ?line 'try'(fun receive_test/1, [Tuple], [Tuple]),
- ?line 'try'(fun receive_test/1, [List], [List, List]),
- ?line 'try'(fun receive_test/1, [a], [a]),
- ?line test_server:timetrap_cancel(Dog).
+ 'try'(fun receive_test/1, [Tuple], [Tuple]),
+ 'try'(fun receive_test/1, [List], [List, List]),
+ 'try'(fun receive_test/1, [a], [a]),
+ ok.
a_case(V) ->
case V of
@@ -143,12 +127,11 @@ a_receive() ->
Pid = spawn_link(?MODULE, init, [Fun,Args,list_to_tuple(Filler)]),
receive
{'EXIT', Pid, {result, Result}} ->
- ?line 'try'(Iter-1, Fun, Args, Result, [0|Filler]);
+ 'try'(Iter-1, Fun, Args, Result, [0|Filler]);
{result, Other} ->
- ?line io:format("Expected ~p; got ~p~n", [Result, Other]),
- ?line test_server:fail();
+ ct:fail("Expected ~p; got ~p~n", [Result, Other]);
Other ->
- ?line test_server:fail({unexpected_message, Other})
+ ct:fail({unexpected_message, Other})
end.
init(Fun, Args, Filler) ->
@@ -165,15 +148,14 @@ mask_error({'EXIT',{Err,_}}) ->
mask_error(Else) ->
Else.
-guard_bif_binary_part(doc) ->
- ["Test the binary_part/2,3 guard BIF's extensively"];
+%% Test the binary_part/2,3 guard BIF's extensively
guard_bif_binary_part(Config) when is_list(Config) ->
%% Overflow tests that need to be unoptimized
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary_part(<<1,2,3>>,{16#FFFFFFFFFFFFFFFF,
-16#7FFFFFFFFFFFFFFF-1})),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary_part(<<1,2,3>>,{16#FFFFFFFFFFFFFFFF,
16#7FFFFFFFFFFFFFFF})),
@@ -198,66 +180,66 @@ guard_bif_binary_part(Config) when is_list(Config) ->
do_binary_part_guard() ->
- ?line 1 = bptest(<<1,2,3>>),
- ?line 2 = bptest(<<2,1,3>>),
- ?line error = bptest(<<1>>),
- ?line error = bptest(<<>>),
- ?line error = bptest(apa),
- ?line 3 = bptest(<<2,3,3>>),
+ 1 = bptest(<<1,2,3>>),
+ 2 = bptest(<<2,1,3>>),
+ error = bptest(<<1>>),
+ error = bptest(<<>>),
+ error = bptest(apa),
+ 3 = bptest(<<2,3,3>>),
% With one variable (pos)
- ?line 1 = bptest(<<1,2,3>>,1),
- ?line 2 = bptest(<<2,1,3>>,1),
- ?line error = bptest(<<1>>,1),
- ?line error = bptest(<<>>,1),
- ?line error = bptest(apa,1),
- ?line 3 = bptest(<<2,3,3>>,1),
+ 1 = bptest(<<1,2,3>>,1),
+ 2 = bptest(<<2,1,3>>,1),
+ error = bptest(<<1>>,1),
+ error = bptest(<<>>,1),
+ error = bptest(apa,1),
+ 3 = bptest(<<2,3,3>>,1),
% With one variable (length)
- ?line 1 = bptesty(<<1,2,3>>,1),
- ?line 2 = bptesty(<<2,1,3>>,1),
- ?line error = bptesty(<<1>>,1),
- ?line error = bptesty(<<>>,1),
- ?line error = bptesty(apa,1),
- ?line 3 = bptesty(<<2,3,3>>,2),
+ 1 = bptesty(<<1,2,3>>,1),
+ 2 = bptesty(<<2,1,3>>,1),
+ error = bptesty(<<1>>,1),
+ error = bptesty(<<>>,1),
+ error = bptesty(apa,1),
+ 3 = bptesty(<<2,3,3>>,2),
% With one variable (whole tuple)
- ?line 1 = bptestx(<<1,2,3>>,{1,1}),
- ?line 2 = bptestx(<<2,1,3>>,{1,1}),
- ?line error = bptestx(<<1>>,{1,1}),
- ?line error = bptestx(<<>>,{1,1}),
- ?line error = bptestx(apa,{1,1}),
- ?line 3 = bptestx(<<2,3,3>>,{1,2}),
+ 1 = bptestx(<<1,2,3>>,{1,1}),
+ 2 = bptestx(<<2,1,3>>,{1,1}),
+ error = bptestx(<<1>>,{1,1}),
+ error = bptestx(<<>>,{1,1}),
+ error = bptestx(apa,{1,1}),
+ 3 = bptestx(<<2,3,3>>,{1,2}),
% With two variables
- ?line 1 = bptest(<<1,2,3>>,1,1),
- ?line 2 = bptest(<<2,1,3>>,1,1),
- ?line error = bptest(<<1>>,1,1),
- ?line error = bptest(<<>>,1,1),
- ?line error = bptest(apa,1,1),
- ?line 3 = bptest(<<2,3,3>>,1,2),
+ 1 = bptest(<<1,2,3>>,1,1),
+ 2 = bptest(<<2,1,3>>,1,1),
+ error = bptest(<<1>>,1,1),
+ error = bptest(<<>>,1,1),
+ error = bptest(apa,1,1),
+ 3 = bptest(<<2,3,3>>,1,2),
% Direct (autoimported) call, these will be evaluated by the compiler...
- ?line <<2>> = binary_part(<<1,2,3>>,1,1),
- ?line <<1>> = binary_part(<<2,1,3>>,1,1),
+ <<2>> = binary_part(<<1,2,3>>,1,1),
+ <<1>> = binary_part(<<2,1,3>>,1,1),
% Compiler warnings due to constant evaluation expected (3)
- ?line badarg = ?MASK_ERROR(binary_part(<<1>>,1,1)),
- ?line badarg = ?MASK_ERROR(binary_part(<<>>,1,1)),
- ?line badarg = ?MASK_ERROR(binary_part(apa,1,1)),
- ?line <<3,3>> = binary_part(<<2,3,3>>,1,2),
+ badarg = ?MASK_ERROR(binary_part(<<1>>,1,1)),
+ badarg = ?MASK_ERROR(binary_part(<<>>,1,1)),
+ badarg = ?MASK_ERROR(binary_part(apa,1,1)),
+ <<3,3>> = binary_part(<<2,3,3>>,1,2),
% Direct call through apply
- ?line <<2>> = apply(erlang,binary_part,[<<1,2,3>>,1,1]),
- ?line <<1>> = apply(erlang,binary_part,[<<2,1,3>>,1,1]),
+ <<2>> = apply(erlang,binary_part,[<<1,2,3>>,1,1]),
+ <<1>> = apply(erlang,binary_part,[<<2,1,3>>,1,1]),
% Compiler warnings due to constant evaluation expected (3)
- ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<1>>,1,1])),
- ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<>>,1,1])),
- ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[apa,1,1])),
- ?line <<3,3>> = apply(erlang,binary_part,[<<2,3,3>>,1,2]),
+ badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<1>>,1,1])),
+ badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<>>,1,1])),
+ badarg = ?MASK_ERROR(apply(erlang,binary_part,[apa,1,1])),
+ <<3,3>> = apply(erlang,binary_part,[<<2,3,3>>,1,2]),
% Constant propagation
- ?line Bin = <<1,2,3>>,
- ?line ok = if
+ Bin = <<1,2,3>>,
+ ok = if
binary_part(Bin,1,1) =:= <<2>> ->
ok;
%% Compiler warning, clause cannot match (expected)
true ->
error
end,
- ?line ok = if
+ ok = if
binary_part(Bin,{1,1}) =:= <<2>> ->
ok;
%% Compiler warning, clause cannot match (expected)
@@ -323,91 +305,91 @@ bptest(_,_,_) ->
error.
-guard_bifs(doc) -> "Test all guard bifs with nasty (but legal arguments).";
+%% Test all guard bifs with nasty (but legal arguments).
guard_bifs(Config) when is_list(Config) ->
- ?line Big = -237849247829874297658726487367328971246284736473821617265433,
- ?line Float = 387924.874,
+ Big = -237849247829874297658726487367328971246284736473821617265433,
+ Float = 387924.874,
%% Succeding use of guard bifs.
- ?line try_gbif('abs/1', Big, -Big),
- ?line try_gbif('float/1', Big, float(Big)),
- ?line try_gbif('float/1', Big, float(id(Big))),
- ?line try_gbif('trunc/1', Float, 387924.0),
- ?line try_gbif('round/1', Float, 387925.0),
- ?line try_gbif('length/1', [], 0),
+ try_gbif('abs/1', Big, -Big),
+ try_gbif('float/1', Big, float(Big)),
+ try_gbif('float/1', Big, float(id(Big))),
+ try_gbif('trunc/1', Float, 387924.0),
+ try_gbif('round/1', Float, 387925.0),
+ try_gbif('length/1', [], 0),
- ?line try_gbif('length/1', [a], 1),
- ?line try_gbif('length/1', [a, b], 2),
- ?line try_gbif('length/1', lists:seq(0, 31), 32),
+ try_gbif('length/1', [a], 1),
+ try_gbif('length/1', [a, b], 2),
+ try_gbif('length/1', lists:seq(0, 31), 32),
- ?line try_gbif('hd/1', [a], a),
- ?line try_gbif('hd/1', [a, b], a),
+ try_gbif('hd/1', [a], a),
+ try_gbif('hd/1', [a, b], a),
- ?line try_gbif('tl/1', [a], []),
- ?line try_gbif('tl/1', [a, b], [b]),
- ?line try_gbif('tl/1', [a, b, c], [b, c]),
+ try_gbif('tl/1', [a], []),
+ try_gbif('tl/1', [a, b], [b]),
+ try_gbif('tl/1', [a, b, c], [b, c]),
- ?line try_gbif('size/1', {}, 0),
- ?line try_gbif('size/1', {a}, 1),
- ?line try_gbif('size/1', {a, b}, 2),
- ?line try_gbif('size/1', {a, b, c}, 3),
- ?line try_gbif('size/1', list_to_binary([]), 0),
- ?line try_gbif('size/1', list_to_binary([1]), 1),
- ?line try_gbif('size/1', list_to_binary([1, 2]), 2),
- ?line try_gbif('size/1', list_to_binary([1, 2, 3]), 3),
+ try_gbif('size/1', {}, 0),
+ try_gbif('size/1', {a}, 1),
+ try_gbif('size/1', {a, b}, 2),
+ try_gbif('size/1', {a, b, c}, 3),
+ try_gbif('size/1', list_to_binary([]), 0),
+ try_gbif('size/1', list_to_binary([1]), 1),
+ try_gbif('size/1', list_to_binary([1, 2]), 2),
+ try_gbif('size/1', list_to_binary([1, 2, 3]), 3),
- ?line try_gbif('bit_size/1', <<0:7>>, 7),
+ try_gbif('bit_size/1', <<0:7>>, 7),
- ?line try_gbif('element/2', {x}, {1, x}),
- ?line try_gbif('element/2', {x, y}, {1, x}),
- ?line try_gbif('element/2', {x, y}, {2, y}),
+ try_gbif('element/2', {x}, {1, x}),
+ try_gbif('element/2', {x, y}, {1, x}),
+ try_gbif('element/2', {x, y}, {2, y}),
- ?line try_gbif('self/0', 0, self()),
- ?line try_gbif('node/0', 0, node()),
- ?line try_gbif('node/1', self(), node()),
+ try_gbif('self/0', 0, self()),
+ try_gbif('node/0', 0, node()),
+ try_gbif('node/1', self(), node()),
%% Failing use of guard bifs.
- ?line try_fail_gbif('abs/1', Big, 1),
- ?line try_fail_gbif('abs/1', [], 1),
+ try_fail_gbif('abs/1', Big, 1),
+ try_fail_gbif('abs/1', [], 1),
- ?line try_fail_gbif('float/1', Big, 42),
- ?line try_fail_gbif('float/1', [], 42),
+ try_fail_gbif('float/1', Big, 42),
+ try_fail_gbif('float/1', [], 42),
- ?line try_fail_gbif('trunc/1', Float, 0.0),
- ?line try_fail_gbif('trunc/1', [], 0.0),
+ try_fail_gbif('trunc/1', Float, 0.0),
+ try_fail_gbif('trunc/1', [], 0.0),
- ?line try_fail_gbif('round/1', Float, 1.0),
- ?line try_fail_gbif('round/1', [], a),
+ try_fail_gbif('round/1', Float, 1.0),
+ try_fail_gbif('round/1', [], a),
- ?line try_fail_gbif('length/1', [], 1),
- ?line try_fail_gbif('length/1', [a], 0),
- ?line try_fail_gbif('length/1', a, 0),
- ?line try_fail_gbif('length/1', {a}, 0),
+ try_fail_gbif('length/1', [], 1),
+ try_fail_gbif('length/1', [a], 0),
+ try_fail_gbif('length/1', a, 0),
+ try_fail_gbif('length/1', {a}, 0),
- ?line try_fail_gbif('hd/1', [], 0),
- ?line try_fail_gbif('hd/1', [a], x),
- ?line try_fail_gbif('hd/1', x, x),
+ try_fail_gbif('hd/1', [], 0),
+ try_fail_gbif('hd/1', [a], x),
+ try_fail_gbif('hd/1', x, x),
- ?line try_fail_gbif('tl/1', [], 0),
- ?line try_fail_gbif('tl/1', [a], x),
- ?line try_fail_gbif('tl/1', x, x),
+ try_fail_gbif('tl/1', [], 0),
+ try_fail_gbif('tl/1', [a], x),
+ try_fail_gbif('tl/1', x, x),
- ?line try_fail_gbif('size/1', {}, 1),
- ?line try_fail_gbif('size/1', [], 0),
- ?line try_fail_gbif('size/1', [a], 1),
- ?line try_fail_gbif('size/1', fun() -> 1 end, 0),
- ?line try_fail_gbif('size/1', fun() -> 1 end, 1),
+ try_fail_gbif('size/1', {}, 1),
+ try_fail_gbif('size/1', [], 0),
+ try_fail_gbif('size/1', [a], 1),
+ try_fail_gbif('size/1', fun() -> 1 end, 0),
+ try_fail_gbif('size/1', fun() -> 1 end, 1),
- ?line try_fail_gbif('element/2', {}, {1, x}),
- ?line try_fail_gbif('element/2', {x}, {1, y}),
- ?line try_fail_gbif('element/2', [], {1, z}),
+ try_fail_gbif('element/2', {}, {1, x}),
+ try_fail_gbif('element/2', {x}, {1, y}),
+ try_fail_gbif('element/2', [], {1, z}),
- ?line try_fail_gbif('self/0', 0, list_to_pid("<0.0.0>")),
- ?line try_fail_gbif('node/0', 0, xxxx),
- ?line try_fail_gbif('node/1', self(), xxx),
- ?line try_fail_gbif('node/1', yyy, xxx),
+ try_fail_gbif('self/0', 0, list_to_pid("<0.0.0>")),
+ try_fail_gbif('node/0', 0, xxxx),
+ try_fail_gbif('node/1', self(), xxx),
+ try_fail_gbif('node/1', yyy, xxx),
ok.
try_gbif(Id, X, Y) ->
@@ -415,9 +397,7 @@ try_gbif(Id, X, Y) ->
{Id, X, Y} ->
io:format("guard_bif(~p, ~p, ~p) -- ok", [Id, X, Y]);
Other ->
- ?line ok = io:format("guard_bif(~p, ~p, ~p) -- bad result: ~p\n",
- [Id, X, Y, Other]),
- ?line test_server:fail()
+ ct:fail("guard_bif(~p, ~p, ~p) -- bad result: ~p\n", [Id, X, Y, Other])
end.
try_fail_gbif(Id, X, Y) ->
@@ -425,9 +405,7 @@ try_fail_gbif(Id, X, Y) ->
{'EXIT',{function_clause,[{?MODULE,guard_bif,[Id,X,Y],_}|_]}} ->
io:format("guard_bif(~p, ~p, ~p) -- ok", [Id,X,Y]);
Other ->
- ?line ok = io:format("guard_bif(~p, ~p, ~p) -- bad result: ~p\n",
- [Id, X, Y, Other]),
- ?line test_server:fail()
+ ct:fail("guard_bif(~p, ~p, ~p) -- bad result: ~p\n", [Id, X, Y, Other])
end.
guard_bif('abs/1', X, Y) when abs(X) == Y ->
@@ -457,22 +435,20 @@ guard_bif('node/0', X, Y) when node() == Y ->
guard_bif('node/1', X, Y) when node(X) == Y ->
{'node/1', X, Y}.
-type_tests(doc) -> "Test the type tests.";
+%% Test the type tests.
type_tests(Config) when is_list(Config) ->
- ?line Types = all_types(),
- ?line Tests = type_test_desc(),
- ?line put(errors, 0),
- ?line put(violations, 0),
- ?line type_tests(Tests, Types),
- ?line case {get(errors), get(violations)} of
+ Types = all_types(),
+ Tests = type_test_desc(),
+ put(errors, 0),
+ put(violations, 0),
+ type_tests(Tests, Types),
+ case {get(errors), get(violations)} of
{0, 0} ->
ok;
{0, N} ->
{comment, integer_to_list(N) ++ " standard violation(s)"};
{Errors, Violations} ->
- io:format("~p sub test(s) failed, ~p violation(s)",
- [Errors, Violations]),
- ?line test_server:fail()
+ ct:fail("~p sub test(s) failed, ~p violation(s)", [Errors, Violations])
end.
type_tests([{Test, AllowedTypes}| T], AllTypes) ->
@@ -499,7 +475,7 @@ type_tests(Test, [Type|T], Allowed) ->
when is_list(Loc) ->
ok;
{'EXIT',Other} ->
- ?line test_server:fail({unexpected_error_reason,Other});
+ ct:fail({unexpected_error_reason,Other});
tuple when is_function(Value) ->
io:format("Standard violation: Test ~p(~p) should fail",
[Test, Value]),
diff --git a/erts/emulator/test/hash_SUITE.erl b/erts/emulator/test/hash_SUITE.erl
index 2ea49467b8..be254f5543 100644
--- a/erts/emulator/test/hash_SUITE.erl
+++ b/erts/emulator/test/hash_SUITE.erl
@@ -50,7 +50,7 @@
-define(config(A,B),config(A,B)).
-export([config/2]).
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-endif.
-ifdef(debug).
@@ -70,86 +70,43 @@ config(priv_dir,_) ->
".".
-else.
%% When run in test server.
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
+-export([all/0, suite/0,
test_basic/1,test_cmp/1,test_range/1,test_spread/1,
test_phash2/1,otp_5292/1,bit_level_binaries/1,otp_7127/1,
- test_hash_zero/1,
- end_per_testcase/2,init_per_testcase/2]).
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(test_server:minutes(10)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+ test_hash_zero/1]).
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 10}}].
all() ->
[test_basic, test_cmp, test_range, test_spread,
test_phash2, otp_5292, bit_level_binaries, otp_7127,
- test_hash_zero
- ].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
+ test_hash_zero].
-test_basic(suite) ->
- [];
-test_basic(doc) ->
- ["Tests basic functionality of erlang:phash and that the "
- "hashes has not changed (neither hash nor phash)"];
+%% Tests basic functionality of erlang:phash and that the
+%% hashes has not changed (neither hash nor phash)
test_basic(Config) when is_list(Config) ->
basic_test().
-test_cmp(suite) ->
- [];
-test_cmp(doc) ->
- ["Compares integer hashes made by erlang:phash with those of a reference "
- "implementation"];
+%% Compares integer hashes made by erlang:phash with those of a reference implementation
test_cmp(Config) when is_list(Config) ->
cmp_test(10000).
-test_range(suite) ->
- [];
-test_range(doc) ->
- ["Tests ranges on erlang:phash from 1 to 2^32"];
+%% Tests ranges on erlang:phash from 1 to 2^32
test_range(Config) when is_list(Config) ->
range_test().
-test_spread(suite) ->
- [];
-test_spread(doc) ->
- ["Tests that the hashes are spread ok"];
+%% Tests that the hashes are spread ok
test_spread(Config) when is_list(Config) ->
spread_test(10).
-test_phash2(suite) ->
- [];
-test_phash2(doc) ->
- ["Tests phash2"];
+%% Tests phash2
test_phash2(Config) when is_list(Config) ->
phash2_test().
-otp_5292(suite) ->
- [];
-otp_5292(doc) ->
- ["Tests hash, phash and phash2 regarding integers."];
+%% Tests hash, phash and phash2 regarding integers.
otp_5292(Config) when is_list(Config) ->
otp_5292_test().
@@ -157,10 +114,7 @@ otp_5292(Config) when is_list(Config) ->
bit_level_binaries(Config) when is_list(Config) ->
bit_level_binaries_do().
-otp_7127(suite) ->
- [];
-otp_7127(doc) ->
- ["Tests phash2/1."];
+%% Tests phash2/1.
otp_7127(Config) when is_list(Config) ->
otp_7127_test().
@@ -223,11 +177,10 @@ basic_test() ->
range_test() ->
- random:seed(),
F = fun(From,From,_FF) ->
ok;
(From,To,FF) ->
- R = random:uniform(16#FFFFFFFFFFFFFFFF),
+ R = rand:uniform(16#FFFFFFFFFFFFFFFF),
X = erlang:phash(R, From),
Y = erlang:phash(R, 16#100000000) - 1,
Z = (Y rem From) + 1,
@@ -265,14 +218,13 @@ spread_test(N) ->
cmp_test(N) ->
- % No need to save seed, the error indicates what number caused it.
- random:seed(),
do_cmp_hashes(N,8).
+
do_cmp_hashes(0,_) ->
ok;
do_cmp_hashes(N,Steps) ->
- R0 = random:uniform(1 bsl Steps - 1) + random:uniform(16#FFFFFFFF),
- R = case random:uniform(2) of
+ R0 = rand:uniform(1 bsl Steps - 1) + rand:uniform(16#FFFFFFFF),
+ R = case rand:uniform(2) of
1 ->
R0;
_ ->
diff --git a/erts/emulator/test/hibernate_SUITE.erl b/erts/emulator/test/hibernate_SUITE.erl
index 4ac8c272db..45f0bdc4da 100644
--- a/erts/emulator/test/hibernate_SUITE.erl
+++ b/erts/emulator/test/hibernate_SUITE.erl
@@ -20,47 +20,25 @@
-module(hibernate_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2,
+-export([all/0, suite/0,
basic/1,dynamic_call/1,min_heap_size/1,bad_args/1,
- messages_in_queue/1,undefined_mfa/1,no_heap/1,wake_up_and_bif_trap/1]).
+ messages_in_queue/1,undefined_mfa/1,no_heap/1,
+ wake_up_and_bif_trap/1]).
%% Used by test cases.
--export([basic_hibernator/1,dynamic_call_hibernator/2,messages_in_queue_restart/2, no_heap_loop/0,characters_to_list_trap/1]).
+-export([basic_hibernator/1,dynamic_call_hibernator/2,messages_in_queue_restart/2,
+ no_heap_loop/0,characters_to_list_trap/1]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 3}}].
all() ->
[basic, dynamic_call, min_heap_size, bad_args, messages_in_queue,
undefined_mfa, no_heap, wake_up_and_bif_trap].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog = ?t:timetrap(?t:minutes(3)),
- [{watchdog,Dog}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
%%%
%%% Testing the basic functionality of erlang:hibernate/3.
%%%
@@ -69,9 +47,9 @@ basic(Config) when is_list(Config) ->
Ref = make_ref(),
Info = {self(),Ref},
ExpectedHeapSz = erts_debug:size([Info]),
- ?line Child = spawn_link(fun() -> basic_hibernator(Info) end),
- ?line hibernate_wake_up(100, ExpectedHeapSz, Child),
- ?line Child ! please_quit_now,
+ Child = spawn_link(fun() -> basic_hibernator(Info) end),
+ hibernate_wake_up(100, ExpectedHeapSz, Child),
+ Child ! please_quit_now,
ok.
hibernate_wake_up(0, _, _) -> ok;
@@ -85,35 +63,35 @@ hibernate_wake_up(N, ExpectedHeapSz, Child) ->
end;
1 -> ok
end,
- ?line Child ! {hibernate,self()},
- ?line wait_until(fun () ->
+ Child ! {hibernate,self()},
+ wait_until(fun () ->
{current_function,{erlang,hibernate,3}} ==
process_info(Child, current_function)
end),
- ?line {message_queue_len,0} = process_info(Child, message_queue_len),
- ?line {status,waiting} = process_info(Child, status),
- ?line {heap_size,ExpectedHeapSz} = process_info(Child, heap_size),
+ {message_queue_len,0} = process_info(Child, message_queue_len),
+ {status,waiting} = process_info(Child, status),
+ {heap_size,ExpectedHeapSz} = process_info(Child, heap_size),
io:format("Before hibernation: ~p After hibernation: ~p\n",
[Before,ExpectedHeapSz]),
- ?line Child ! {whats_up,self()},
- ?line receive
- {all_fine,X,Child,_Ref} ->
- if
- N =:= 1 -> io:format("~p\n", [X]);
- true -> ok
- end,
- {backtrace,Bin} = process_info(Child, backtrace),
- if
- size(Bin) > 1000 ->
- io:format("~s\n", [binary_to_list(Bin)]),
- ?line ?t:fail(stack_is_growing);
- true ->
- hibernate_wake_up(N-1, ExpectedHeapSz, Child)
- end;
- Other ->
- ?line io:format("~p\n", [Other]),
- ?line ?t:fail(unexpected_message)
- end.
+ Child ! {whats_up,self()},
+ receive
+ {all_fine,X,Child,_Ref} ->
+ if
+ N =:= 1 -> io:format("~p\n", [X]);
+ true -> ok
+ end,
+ {backtrace,Bin} = process_info(Child, backtrace),
+ if
+ size(Bin) > 1000 ->
+ io:format("~s\n", [binary_to_list(Bin)]),
+ ct:fail(stack_is_growing);
+ true ->
+ hibernate_wake_up(N-1, ExpectedHeapSz, Child)
+ end;
+ Other ->
+ io:format("~p\n", [Other]),
+ ct:fail(unexpected_message)
+ end.
basic_hibernator(Info) ->
{catchlevel,0} = process_info(self(), catchlevel),
@@ -165,9 +143,9 @@ dynamic_call(Config) when is_list(Config) ->
Ref = make_ref(),
Info = {self(),Ref},
ExpectedHeapSz = erts_debug:size([Info]),
- ?line Child = spawn_link(fun() -> ?MODULE:dynamic_call_hibernator(Info, hibernate) end),
- ?line hibernate_wake_up(100, ExpectedHeapSz, Child),
- ?line Child ! please_quit_now,
+ Child = spawn_link(fun() -> ?MODULE:dynamic_call_hibernator(Info, hibernate) end),
+ hibernate_wake_up(100, ExpectedHeapSz, Child),
+ Child ! please_quit_now,
ok.
dynamic_call_hibernator(Info, Function) ->
@@ -195,34 +173,32 @@ min_heap_size(Config) when is_list(Config) ->
end.
min_heap_size_1(Config) when is_list(Config) ->
- ?line erlang:trace(new, true, [call]),
+ erlang:trace(new, true, [call]),
MFA = {?MODULE,min_hibernator,1},
- ?line 1 = erlang:trace_pattern(MFA, true, [local]),
+ 1 = erlang:trace_pattern(MFA, true, [local]),
Ref = make_ref(),
Info = {self(),Ref},
- ?line Child = spawn_opt(fun() -> min_hibernator(Info) end,
+ Child = spawn_opt(fun() -> min_hibernator(Info) end,
[{min_heap_size,15000},link]),
receive
- {trace,Child,call,{?MODULE,min_hibernator,_}} ->
- ?line 1 = erlang:trace_pattern(MFA, false, [local]),
- ?line erlang:trace(new, false, [call])
+ {trace,Child,call,{?MODULE,min_hibernator,_}} ->
+ 1 = erlang:trace_pattern(MFA, false, [local]),
+ erlang:trace(new, false, [call])
end,
{heap_size,HeapSz} = process_info(Child, heap_size),
io:format("Heap size: ~p\n", [HeapSz]),
- ?line if
- HeapSz < 20 -> ok
- end,
- ?line Child ! wake_up,
+ if
+ HeapSz < 20 -> ok
+ end,
+ Child ! wake_up,
receive
{heap_size,AfterSize} ->
io:format("Heap size after wakeup: ~p\n", [AfterSize]),
- ?line
- if
- AfterSize >= 15000 -> ok
- end;
+ if
+ AfterSize >= 15000 -> ok
+ end;
Other ->
- io:format("Unexpected: ~p\n", [Other]),
- ?line ?t:fail()
+ ct:fail("Unexpected: ~p\n", [Other])
end.
min_hibernator({Parent,_Ref}) ->
@@ -239,23 +215,23 @@ min_hibernator_recv(Parent) ->
%%%
bad_args(Config) when is_list(Config) ->
- ?line bad_args(?MODULE, {name,glurf}, [0]),
- ?line {'EXIT',{system_limit,_}} =
+ bad_args(?MODULE, {name,glurf}, [0]),
+ {'EXIT',{system_limit,_}} =
(catch erlang:hibernate(x, y, lists:duplicate(5122, xxx))),
- ?line bad_args(42, name, [0]),
- ?line bad_args(xx, 42, [1]),
- ?line bad_args(xx, 42, glurf),
- ?line bad_args(xx, 42, {}),
- ?line bad_args({}, name, [2]),
- ?line bad_args({1}, name, [3]),
- ?line bad_args({1,2,3}, name, [4]),
- ?line bad_args({1,2,3}, name, [5]),
- ?line bad_args({1,2,3,4}, name, [6]),
- ?line bad_args({1,2,3,4,5,6}, name,[7]),
- ?line bad_args({1,2,3,4,5}, name, [8]),
- ?line bad_args({1,2}, name, [9]),
- ?line bad_args([1,2], name, [9]),
- ?line bad_args(55.0, name, [9]),
+ bad_args(42, name, [0]),
+ bad_args(xx, 42, [1]),
+ bad_args(xx, 42, glurf),
+ bad_args(xx, 42, {}),
+ bad_args({}, name, [2]),
+ bad_args({1}, name, [3]),
+ bad_args({1,2,3}, name, [4]),
+ bad_args({1,2,3}, name, [5]),
+ bad_args({1,2,3,4}, name, [6]),
+ bad_args({1,2,3,4,5,6}, name,[7]),
+ bad_args({1,2,3,4,5}, name, [8]),
+ bad_args({1,2}, name, [9]),
+ bad_args([1,2], name, [9]),
+ bad_args(55.0, name, [9]),
ok.
bad_args(Mod, Name, Args) ->
@@ -266,7 +242,7 @@ bad_args(Mod, Name, Args) ->
io:format("erlang:hibernate(~p, ~p, ~p) -> ~p\n", [Mod,Name,Args,Res]);
Other ->
io:format("erlang:hibernate(~p, ~p, ~p) -> ~p\n", [Mod,Name,Args,Res]),
- ?t:fail({bad_result,Other})
+ ct:fail({bad_result,Other})
end.
@@ -283,8 +259,8 @@ messages_in_queue(Config) when is_list(Config) ->
receive
done -> ok;
Other ->
- ?line io:format("~p\n", [Other]),
- ?line ?t:fail(unexpected_message)
+ io:format("~p\n", [Other]),
+ ct:fail(unexpected_message)
end.
messages_in_queue_1(Parent, ExpectedMsg) ->
@@ -296,13 +272,13 @@ messages_in_queue_1(Parent, ExpectedMsg) ->
[Parent,ExpectedMsg]).
messages_in_queue_restart(Parent, ExpectedMessage) ->
- ?line receive
- ExpectedMessage ->
- Parent ! done;
- Other ->
- io:format("~p\n", [Other]),
- ?t:fail(unexpected_message)
- end,
+ receive
+ ExpectedMessage ->
+ Parent ! done;
+ Other ->
+ io:format("~p\n", [Other]),
+ ct:fail(unexpected_message)
+ end,
ok.
@@ -312,36 +288,36 @@ messages_in_queue_restart(Parent, ExpectedMessage) ->
%%%
undefined_mfa(Config) when is_list(Config) ->
- ?line process_flag(trap_exit, true),
- ?line Pid = spawn_link(fun() ->
+ process_flag(trap_exit, true),
+ Pid = spawn_link(fun() ->
%% Will be a call_only instruction.
erlang:hibernate(?MODULE, blarf, []) end),
- ?line Pid ! {a,message},
- ?line receive
- {'EXIT',Pid,{undef,Undef}} ->
- io:format("~p\n", [Undef]),
- ok;
- Other ->
- ?line io:format("~p\n", [Other]),
- ?line ?t:fail(unexpected_message)
- end,
+ Pid ! {a,message},
+ receive
+ {'EXIT',Pid,{undef,Undef}} ->
+ io:format("~p\n", [Undef]),
+ ok;
+ Other ->
+ io:format("~p\n", [Other]),
+ ct:fail(unexpected_message)
+ end,
undefined_mfa_1().
undefined_mfa_1() ->
- ?line Pid = spawn_link(fun() ->
+ Pid = spawn_link(fun() ->
%% Force a call_last instruction by calling bar()
%% (if that is not obvious).
bar(),
erlang:hibernate(?MODULE, blarf, [])
end),
- ?line Pid ! {another,message},
- ?line receive
+ Pid ! {another,message},
+ receive
{'EXIT',Pid,{undef,Undef}} ->
io:format("~p\n", [Undef]),
ok;
Other ->
- ?line io:format("~p\n", [Other]),
- ?line ?t:fail(unexpected_message)
+ io:format("~p\n", [Other]),
+ ct:fail(unexpected_message)
end,
ok.
@@ -352,23 +328,17 @@ bar() ->
%% No heap
%%
-no_heap(doc) -> [];
-no_heap(suite) -> [];
no_heap(Config) when is_list(Config) ->
- ?line H = spawn_link(fun () -> clean_dict(), no_heap_loop() end),
- ?line lists:foreach(fun (_) ->
- wait_until(fun () -> is_hibernated(H) end),
- ?line [{heap_size,1},
- {total_heap_size,1}]
- = process_info(H,
- [heap_size,
- total_heap_size]),
- receive after 10 -> ok end,
- H ! again
- end,
- lists:seq(1, 100)),
- ?line unlink(H),
- ?line exit(H, bye).
+ H = spawn_link(fun () -> clean_dict(), no_heap_loop() end),
+ lists:foreach(fun (_) ->
+ wait_until(fun () -> is_hibernated(H) end),
+ [{heap_size,1}, {total_heap_size,1}]
+ = process_info(H, [heap_size, total_heap_size]),
+ receive after 10 -> ok end,
+ H ! again
+ end, lists:seq(1, 100)),
+ unlink(H),
+ exit(H, bye).
no_heap_loop() ->
flush(),
@@ -382,19 +352,17 @@ clean_dict() ->
%% Wake up and then immediatly bif trap with a lengthy computation.
%%
-wake_up_and_bif_trap(doc) -> [];
-wake_up_and_bif_trap(suite) -> [];
wake_up_and_bif_trap(Config) when is_list(Config) ->
- ?line Self = self(),
- ?line Pid = spawn_link(fun() -> erlang:hibernate(?MODULE, characters_to_list_trap, [Self]) end),
- ?line Pid ! wakeup,
- ?line receive
+ Self = self(),
+ Pid = spawn_link(fun() -> erlang:hibernate(?MODULE, characters_to_list_trap, [Self]) end),
+ Pid ! wakeup,
+ receive
{ok, Pid0} when Pid0 =:= Pid -> ok
after 5000 ->
- ?line ?t:fail(process_blocked)
+ ct:fail(process_blocked)
end,
- ?line unlink(Pid),
- ?line exit(Pid, bye).
+ unlink(Pid),
+ exit(Pid, bye).
%% Lengthy computation that traps (in characters_to_list_trap_3).
characters_to_list_trap(Parent) ->
diff --git a/erts/emulator/test/ignore_cores.erl b/erts/emulator/test/ignore_cores.erl
index 13f34cd10f..7373303a39 100644
--- a/erts/emulator/test/ignore_cores.erl
+++ b/erts/emulator/test/ignore_cores.erl
@@ -28,7 +28,7 @@
-module(ignore_cores).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([init/1, fini/1, setup/3, setup/4, restore/1, dir/1]).
@@ -53,7 +53,7 @@ init(Config) ->
fini(Config) ->
#ignore_cores{org_cwd = OrgCWD,
org_path = OrgPath,
- org_pwd_env = OrgPWD} = ?config(ignore_cores, Config),
+ org_pwd_env = OrgPWD} = proplists:get_value(ignore_cores, Config),
ok = file:set_cwd(OrgCWD),
true = code:set_path(OrgPath),
case OrgPWD of
@@ -70,10 +70,10 @@ setup(Suite, Testcase, Config, SetCwd) when is_atom(Suite),
is_list(Config) ->
#ignore_cores{org_cwd = OrgCWD,
org_path = OrgPath,
- org_pwd_env = OrgPWD} = ?config(ignore_cores, Config),
+ org_pwd_env = OrgPWD} = proplists:get_value(ignore_cores, Config),
Path = lists:map(fun (".") -> OrgCWD; (Dir) -> Dir end, OrgPath),
true = code:set_path(Path),
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
IgnDir = filename:join([PrivDir,
atom_to_list(Suite)
++ "_"
@@ -94,7 +94,7 @@ setup(Suite, Testcase, Config, SetCwd) when is_atom(Suite),
end,
ok = file:write_file(filename:join([IgnDir, "ignore_core_files"]), <<>>),
%% cores are dumped in /cores on MacOS X
- CoresDir = case {?t:os_type(), filelib:is_dir("/cores")} of
+ CoresDir = case {test_server:os_type(), filelib:is_dir("/cores")} of
{{unix,darwin}, true} ->
filelib:fold_files("/cores",
"^core.*$",
@@ -119,7 +119,7 @@ restore(Config) ->
org_path = OrgPath,
org_pwd_env = OrgPWD,
ign_dir = IgnDir,
- cores_dir = CoresDir} = ?config(ignore_cores, Config),
+ cores_dir = CoresDir} = proplists:get_value(ignore_cores, Config),
try
case CoresDir of
false ->
@@ -155,5 +155,5 @@ restore(Config) ->
dir(Config) ->
- #ignore_cores{ign_dir = Dir} = ?config(ignore_cores, Config),
+ #ignore_cores{ign_dir = Dir} = proplists:get_value(ignore_cores, Config),
Dir.
diff --git a/erts/emulator/test/list_bif_SUITE.erl b/erts/emulator/test/list_bif_SUITE.erl
index 9e930822cf..1f64a6a8e5 100644
--- a/erts/emulator/test/list_bif_SUITE.erl
+++ b/erts/emulator/test/list_bif_SUITE.erl
@@ -19,149 +19,108 @@
%%
-module(list_bif_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2]).
+-export([all/0, suite/0]).
-export([hd_test/1,tl_test/1,t_length/1,t_list_to_pid/1,
t_list_to_float/1,t_list_to_integer/1]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 1}}].
+
all() ->
[hd_test, tl_test, t_length, t_list_to_pid,
t_list_to_float, t_list_to_integer].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(_Case, Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(60)),
- [{watchdog,Dog}|Config].
-
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-t_list_to_integer(suite) ->
- [];
-t_list_to_integer(doc) ->
- ["tests list_to_integer and string:to_integer"];
+%% Tests list_to_integer and string:to_integer
t_list_to_integer(Config) when is_list(Config) ->
- ?line {'EXIT',{badarg,_}} = (catch list_to_integer("12373281903728109372810937209817320981321ABC")),
- ?line 12373281903728109372810937209817320981321 = (catch list_to_integer("12373281903728109372810937209817320981321")),
- ?line 12373 = (catch list_to_integer("12373")),
- ?line -12373 = (catch list_to_integer("-12373")),
- ?line 12373 = (catch list_to_integer("+12373")),
- ?line {'EXIT',{badarg,_}} = ( catch list_to_integer(abc)),
- ?line {'EXIT',{badarg,_}} = (catch list_to_integer("")),
- ?line {12373281903728109372810937209817320981321,"ABC"} = string:to_integer("12373281903728109372810937209817320981321ABC"),
- ?line {-12373281903728109372810937209817320981321,"ABC"} = string:to_integer("-12373281903728109372810937209817320981321ABC"),
- ?line {12,[345]} = string:to_integer([$1,$2,345]),
- ?line {12,[a]} = string:to_integer([$1,$2,a]),
- ?line {error,no_integer} = string:to_integer([$A]),
- ?line {error,not_a_list} = string:to_integer($A),
+ {'EXIT',{badarg,_}} = (catch list_to_integer("12373281903728109372810937209817320981321ABC")),
+ 12373281903728109372810937209817320981321 = (catch list_to_integer("12373281903728109372810937209817320981321")),
+ 12373 = (catch list_to_integer("12373")),
+ -12373 = (catch list_to_integer("-12373")),
+ 12373 = (catch list_to_integer("+12373")),
+ {'EXIT',{badarg,_}} = ( catch list_to_integer(abc)),
+ {'EXIT',{badarg,_}} = (catch list_to_integer("")),
+ {12373281903728109372810937209817320981321,"ABC"} = string:to_integer("12373281903728109372810937209817320981321ABC"),
+ {-12373281903728109372810937209817320981321,"ABC"} = string:to_integer("-12373281903728109372810937209817320981321ABC"),
+ {12,[345]} = string:to_integer([$1,$2,345]),
+ {12,[a]} = string:to_integer([$1,$2,a]),
+ {error,no_integer} = string:to_integer([$A]),
+ {error,not_a_list} = string:to_integer($A),
ok.
%% Test hd/1 with correct and incorrect arguments.
hd_test(Config) when is_list(Config) ->
- ?line $h = hd(id("hejsan")),
- ?line case catch hd(id($h)) of
- {'EXIT', {badarg, _}} -> ok;
- Res ->
- Str=io_lib:format("hd/1 with incorrect args "++
- "succeeded.~nResult: ~p", [Res]),
- test_server:fail(Str)
- end,
+ $h = hd(id("hejsan")),
+ case catch hd(id($h)) of
+ {'EXIT', {badarg, _}} -> ok;
+ Res ->
+ ct:fail("hd/1 with incorrect args succeeded.~nResult: ~p", [Res])
+ end,
ok.
%% Test tl/1 with correct and incorrect arguments.
tl_test(Config) when is_list(Config) ->
- ?line "ejsan" = tl(id("hejsan")),
- ?line case catch tl(id(104)) of
- {'EXIT', {badarg, _}} ->
- ok;
- Res ->
- Str=io_lib:format("tl/1 with incorrect args "++
- "succeeded.~nResult: ~p", [Res]),
- test_server:fail(Str)
- end,
+ "ejsan" = tl(id("hejsan")),
+ case catch tl(id(104)) of
+ {'EXIT', {badarg, _}} ->
+ ok;
+ Res ->
+ ct:fail("tl/1 with incorrect args succeeded.~nResult: ~p", [Res])
+ end,
ok.
%% Test length/1 with correct and incorrect arguments.
t_length(Config) when is_list(Config) ->
- ?line 0 = length(""),
- ?line 0 = length([]),
- ?line 1 = length([1]),
- ?line 2 = length([1,a]),
- ?line 2 = length("ab"),
- ?line 3 = length("abc"),
- ?line 4 = length(id([x|"abc"])),
- ?line 6 = length("hejsan"),
- ?line {'EXIT',{badarg,_}} = (catch length(id([a,b|c]))),
- ?line case catch length({tuple}) of
- {'EXIT', {badarg, _}} ->
- ok;
- Res ->
- Str = io_lib:format("length/1 with incorrect args "++
- "succeeded.~nResult: ~p", [Res]),
- ?line test_server:fail(Str)
- end,
+ 0 = length(""),
+ 0 = length([]),
+ 1 = length([1]),
+ 2 = length([1,a]),
+ 2 = length("ab"),
+ 3 = length("abc"),
+ 4 = length(id([x|"abc"])),
+ 6 = length("hejsan"),
+ {'EXIT',{badarg,_}} = (catch length(id([a,b|c]))),
+ case catch length({tuple}) of
+ {'EXIT', {badarg, _}} ->
+ ok;
+ Res ->
+ ct:fail("length/1 with incorrect args succeeded.~nResult: ~p", [Res])
+ end,
ok.
%% Test list_to_pid/1 with correct and incorrect arguments.
t_list_to_pid(Config) when is_list(Config) ->
- ?line Me = self(),
- ?line MyListedPid = pid_to_list(Me),
- ?line Me = list_to_pid(MyListedPid),
- ?line case catch list_to_pid(id("Incorrect list")) of
- {'EXIT', {badarg, _}} ->
- ok;
- Res ->
- Str=io_lib:format("list_to_pid/1 with incorrect "++
- "arg succeeded.~nResult: ~p",
- [Res]),
- test_server:fail(Str)
- end,
+ Me = self(),
+ MyListedPid = pid_to_list(Me),
+ Me = list_to_pid(MyListedPid),
+ case catch list_to_pid(id("Incorrect list")) of
+ {'EXIT', {badarg, _}} ->
+ ok;
+ Res ->
+ ct:fail("list_to_pid/1 with incorrect arg succeeded.~nResult: ~p", [Res])
+ end,
ok.
%% Test list_to_float/1 with correct and incorrect arguments.
t_list_to_float(Config) when is_list(Config) ->
- ?line 5.89000 = list_to_float(id("5.89")),
- ?line 5.89898 = list_to_float(id("5.89898")),
- ?line case catch list_to_float(id("58")) of
- {'EXIT', {badarg, _}} -> ok;
- Res ->
- Str=io_lib:format("list_to_float with incorrect "++
- "arg succeeded.~nResult: ~p",
- [Res]),
- test_server:fail(Str)
- end,
+ 5.89000 = list_to_float(id("5.89")),
+ 5.89898 = list_to_float(id("5.89898")),
+ case catch list_to_float(id("58")) of
+ {'EXIT', {badarg, _}} -> ok;
+ Res ->
+ ct:fail("list_to_float with incorrect arg succeeded.~nResult: ~p", [Res])
+ end,
ok.
id(I) -> I.
-
-
diff --git a/erts/emulator/test/map_SUITE.erl b/erts/emulator/test/map_SUITE.erl
index a256cf4195..956b82335c 100644
--- a/erts/emulator/test/map_SUITE.erl
+++ b/erts/emulator/test/map_SUITE.erl
@@ -17,73 +17,70 @@
%% %CopyrightEnd%
%%
-module(map_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2
- ]).
-
--export([
- t_build_and_match_literals/1, t_build_and_match_literals_large/1,
- t_update_literals/1, t_update_literals_large/1,
- t_match_and_update_literals/1, t_match_and_update_literals_large/1,
- t_update_map_expressions/1,
- t_update_assoc/1, t_update_assoc_large/1,
- t_update_exact/1, t_update_exact_large/1,
- t_guard_bifs/1,
- t_guard_sequence/1, t_guard_sequence_large/1,
- t_guard_update/1, t_guard_update_large/1,
- t_guard_receive/1, t_guard_receive_large/1,
- t_guard_fun/1,
- t_update_deep/1,
- t_list_comprehension/1,
- t_map_sort_literals/1,
- t_map_equal/1,
- t_map_compare/1,
- t_map_size/1,
- t_is_map/1,
-
- %% Specific Map BIFs
- t_bif_map_get/1,
- t_bif_map_find/1,
- t_bif_map_is_key/1,
- t_bif_map_keys/1,
- t_bif_map_merge/1,
- t_bif_map_new/1,
- t_bif_map_put/1,
- t_bif_map_remove/1,
- t_bif_map_update/1,
- t_bif_map_values/1,
- t_bif_map_to_list/1,
- t_bif_map_from_list/1,
-
- %% erlang
- t_erlang_hash/1,
- t_map_encode_decode/1,
- t_gc_rare_map_overflow/1,
-
- %% non specific BIF related
- t_bif_build_and_check/1,
- t_bif_merge_and_check/1,
-
- %% maps module not bifs
- t_maps_fold/1,
- t_maps_map/1,
- t_maps_size/1,
- t_maps_without/1,
-
- %% misc
- t_hashmap_balance/1,
- t_erts_internal_order/1,
- t_erts_internal_hash/1,
- t_pdict/1,
- t_ets/1,
- t_dets/1,
- t_tracing/1,
-
- %% instruction-level tests
- t_has_map_fields/1,
- y_regs/1,
- badmap_17/1
- ]).
+-export([all/0, suite/0]).
+-compile({nowarn_deprecated_function, {erlang,hash,2}}).
+
+-export([t_build_and_match_literals/1, t_build_and_match_literals_large/1,
+ t_update_literals/1, t_update_literals_large/1,
+ t_match_and_update_literals/1, t_match_and_update_literals_large/1,
+ t_update_map_expressions/1,
+ t_update_assoc/1, t_update_assoc_large/1,
+ t_update_exact/1, t_update_exact_large/1,
+ t_guard_bifs/1,
+ t_guard_sequence/1, t_guard_sequence_large/1,
+ t_guard_update/1, t_guard_update_large/1,
+ t_guard_receive/1, t_guard_receive_large/1,
+ t_guard_fun/1,
+ t_update_deep/1,
+ t_list_comprehension/1,
+ t_map_sort_literals/1,
+ t_map_equal/1,
+ t_map_compare/1,
+ t_map_size/1,
+ t_is_map/1,
+
+ %% Specific Map BIFs
+ t_bif_map_get/1,
+ t_bif_map_find/1,
+ t_bif_map_is_key/1,
+ t_bif_map_keys/1,
+ t_bif_map_merge/1,
+ t_bif_map_new/1,
+ t_bif_map_put/1,
+ t_bif_map_remove/1,
+ t_bif_map_update/1,
+ t_bif_map_values/1,
+ t_bif_map_to_list/1,
+ t_bif_map_from_list/1,
+
+ %% erlang
+ t_erlang_hash/1,
+ t_map_encode_decode/1,
+ t_gc_rare_map_overflow/1,
+
+ %% non specific BIF related
+ t_bif_build_and_check/1,
+ t_bif_merge_and_check/1,
+
+ %% maps module not bifs
+ t_maps_fold/1,
+ t_maps_map/1,
+ t_maps_size/1,
+ t_maps_without/1,
+
+ %% misc
+ t_hashmap_balance/1,
+ t_erts_internal_order/1,
+ t_erts_internal_hash/1,
+ t_pdict/1,
+ t_ets/1,
+ t_dets/1,
+ t_tracing/1,
+
+ %% instruction-level tests
+ t_has_map_fields/1,
+ y_regs/1,
+ badmap_17/1]).
-include_lib("stdlib/include/ms_transform.hrl").
@@ -96,65 +93,55 @@
suite() -> [].
-all() -> [
- t_build_and_match_literals, t_build_and_match_literals_large,
- t_update_literals, t_update_literals_large,
- t_match_and_update_literals, t_match_and_update_literals_large,
- t_update_map_expressions,
- t_update_assoc, t_update_assoc_large,
- t_update_exact, t_update_exact_large,
- t_guard_bifs,
- t_guard_sequence, t_guard_sequence_large,
- t_guard_update, t_guard_update_large,
- t_guard_receive, t_guard_receive_large,
- t_guard_fun, t_list_comprehension,
- t_update_deep,
- t_map_equal, t_map_compare,
- t_map_sort_literals,
-
- %% Specific Map BIFs
- t_bif_map_get,t_bif_map_find,t_bif_map_is_key,
- t_bif_map_keys, t_bif_map_merge, t_bif_map_new,
- t_bif_map_put,
- t_bif_map_remove, t_bif_map_update,
- t_bif_map_values,
- t_bif_map_to_list, t_bif_map_from_list,
-
- %% erlang
- t_erlang_hash, t_map_encode_decode,
- t_gc_rare_map_overflow,
- t_map_size, t_is_map,
-
- %% non specific BIF related
- t_bif_build_and_check,
- t_bif_merge_and_check,
-
- %% maps module
- t_maps_fold, t_maps_map,
- t_maps_size, t_maps_without,
-
-
- %% Other functions
- t_hashmap_balance,
- t_erts_internal_order,
- t_erts_internal_hash,
- t_pdict,
- t_ets,
- t_tracing,
-
- %% instruction-level tests
- t_has_map_fields,
- y_regs,
- badmap_17
- ].
-
-groups() -> [].
-
-init_per_suite(Config) -> Config.
-end_per_suite(_Config) -> ok.
-
-init_per_group(_GroupName, Config) -> Config.
-end_per_group(_GroupName, Config) -> Config.
+all() -> [t_build_and_match_literals, t_build_and_match_literals_large,
+ t_update_literals, t_update_literals_large,
+ t_match_and_update_literals, t_match_and_update_literals_large,
+ t_update_map_expressions,
+ t_update_assoc, t_update_assoc_large,
+ t_update_exact, t_update_exact_large,
+ t_guard_bifs,
+ t_guard_sequence, t_guard_sequence_large,
+ t_guard_update, t_guard_update_large,
+ t_guard_receive, t_guard_receive_large,
+ t_guard_fun, t_list_comprehension,
+ t_update_deep,
+ t_map_equal, t_map_compare,
+ t_map_sort_literals,
+
+ %% Specific Map BIFs
+ t_bif_map_get,t_bif_map_find,t_bif_map_is_key,
+ t_bif_map_keys, t_bif_map_merge, t_bif_map_new,
+ t_bif_map_put,
+ t_bif_map_remove, t_bif_map_update,
+ t_bif_map_values,
+ t_bif_map_to_list, t_bif_map_from_list,
+
+ %% erlang
+ t_erlang_hash, t_map_encode_decode,
+ t_gc_rare_map_overflow,
+ t_map_size, t_is_map,
+
+ %% non specific BIF related
+ t_bif_build_and_check,
+ t_bif_merge_and_check,
+
+ %% maps module
+ t_maps_fold, t_maps_map,
+ t_maps_size, t_maps_without,
+
+
+ %% Other functions
+ t_hashmap_balance,
+ t_erts_internal_order,
+ t_erts_internal_hash,
+ t_pdict,
+ t_ets,
+ t_tracing,
+
+ %% instruction-level tests
+ t_has_map_fields,
+ y_regs,
+ badmap_17].
%% tests
@@ -1511,11 +1498,8 @@ t_map_equal(Config) when is_list(Config) ->
t_map_compare(Config) when is_list(Config) ->
- Seed = {erlang:monotonic_time(),
- erlang:time_offset(),
- erlang:unique_integer()},
- io:format("seed = ~p\n", [Seed]),
- random:seed(Seed),
+ rand:seed(exsplus),
+ io:format("seed = ~p\n", [rand:export_seed()]),
repeat(100, fun(_) -> float_int_compare() end, []),
repeat(100, fun(_) -> recursive_compare() end, []),
ok.
@@ -1533,7 +1517,7 @@ float_int_compare() ->
numeric_keys(N) ->
lists:foldl(fun(_,Acc) ->
- Int = random:uniform(N*4) - N*2,
+ Int = rand:uniform(N*4) - N*2,
Float = float(Int),
[Int, Float, Float * 0.99, Float * 1.01 | Acc]
end,
@@ -1564,7 +1548,7 @@ do_compare([Gen1, Gen2]) ->
%% Change one key from int to float (or vice versa) and check compare
ML1 = maps:to_list(M1),
- {K1,V1} = lists:nth(random:uniform(length(ML1)), ML1),
+ {K1,V1} = lists:nth(rand:uniform(length(ML1)), ML1),
case K1 of
I when is_integer(I) ->
case maps:find(float(I),M1) of
@@ -1655,9 +1639,9 @@ cmp_others(T1, T2, _) ->
map_gen(Pairs, Size) ->
{_,L} = lists:foldl(fun(_, {Keys, Acc}) ->
- KI = random:uniform(size(Keys)),
+ KI = rand:uniform(size(Keys)),
K = element(KI,Keys),
- KV = element(random:uniform(size(K)), K),
+ KV = element(rand:uniform(size(K)), K),
{erlang:delete_element(KI,Keys), [KV | Acc]}
end,
{Pairs, []},
@@ -1697,20 +1681,19 @@ term_gen_recursive(Leafs, Flags, Depth) ->
MaxDepth = 10,
Rnd = case {Flags, Depth} of
{_, MaxDepth} -> % Only leafs
- random:uniform(size(Leafs)) + 3;
+ rand:uniform(size(Leafs)) + 3;
{0, 0} -> % Only containers
- random:uniform(3);
+ rand:uniform(3);
{0,_} -> % Anything
- random:uniform(size(Leafs)+3)
+ rand:uniform(size(Leafs)+3)
end,
case Rnd of
1 -> % Make map
- Size = random:uniform(size(Leafs)),
+ Size = rand:uniform(size(Leafs)),
lists:foldl(fun(_, {Acc1,Acc2}) ->
{K1,K2} = term_gen_recursive(Leafs, Flags,
Depth+1),
{V1,V2} = term_gen_recursive(Leafs, Flags, Depth+1),
- %%ok = check_keys(K1,K2, 0),
{maps:put(K1,V1, Acc1), maps:put(K2,V2, Acc2)}
end,
{maps:new(), maps:new()},
@@ -1720,7 +1703,7 @@ term_gen_recursive(Leafs, Flags, Depth) ->
{Cdr1,Cdr2} = term_gen_recursive(Leafs, Flags, Depth+1),
{[Car1 | Cdr1], [Car2 | Cdr2]};
3 -> % Make tuple
- Size = random:uniform(size(Leafs)),
+ Size = rand:uniform(size(Leafs)),
L = lists:map(fun(_) -> term_gen_recursive(Leafs, Flags, Depth+1) end,
lists:seq(1,Size)),
{L1, L2} = lists:unzip(L),
@@ -1729,7 +1712,7 @@ term_gen_recursive(Leafs, Flags, Depth) ->
N -> % Make leaf
case element(N-3, Leafs) of
I when is_integer(I) ->
- case random:uniform(4) of
+ case rand:uniform(4) of
1 -> {I, float(I)};
2 -> {float(I), I};
_ -> {I,I}
@@ -1738,26 +1721,6 @@ term_gen_recursive(Leafs, Flags, Depth) ->
end
end.
-check_keys(K1, K2, _) when K1 =:= K2 ->
- case erlang:phash3(K1) =:= erlang:phash3(K2) of
- true -> ok;
- false ->
- io:format("Same keys with different hash values !!!\nK1 = ~p\nK2 = ~p\n", [K1,K2]),
- error
- end;
-check_keys(K1, K2, 0) ->
- case {erlang:phash3(K1), erlang:phash3(K2)} of
- {H,H} -> check_keys(K1, K2, 1);
- {_,_} -> ok
- end;
-check_keys(K1, K2, L) when L < 10 ->
- case {erlang:phash3([L|K1]), erlang:phash3([L|K2])} of
- {H,H} -> check_keys(K1, K2, L+1);
- {_,_} -> ok
- end;
-check_keys(K1, K2, L) ->
- io:format("Same hash value at level ~p !!!\nK1 = ~p\nK2 = ~p\n", [L,K1,K2]),
- error.
%% BIFs
t_bif_map_get(Config) when is_list(Config) ->
@@ -2598,7 +2561,7 @@ hashmap_balance(KeyFun) ->
F = fun(I, {M0,Max0}) ->
Key = KeyFun(I),
M1 = M0#{Key => Key},
- Max1 = case erts_internal:map_type(M1) of
+ Max1 = case erts_internal:term_type(M1) of
hashmap ->
Nodes = hashmap_nodes(M1),
Avg = maps:size(M1) * 0.4,
@@ -2996,7 +2959,7 @@ id(I) -> I.
%% OTP-13146
%% Provoke major GC with a lot of "fat" maps on external format in msg queue
%% causing heap fragments to be allocated.
-t_gc_rare_map_overflow(Config) ->
+t_gc_rare_map_overflow(Config) when is_list(Config) ->
Pa = filename:dirname(code:which(?MODULE)),
{ok, Node} = test_server:start_node(gc_rare_map_overflow, slave, [{args, "-pa \""++Pa++"\""}]),
erts_debug:set_internal_state(available_internal_state, true),
@@ -3006,7 +2969,7 @@ t_gc_rare_map_overflow(Config) ->
Loop()
end),
FatMap = fatmap(34),
- false = (flatmap =:= erts_internal:map_type(FatMap)),
+ false = (flatmap =:= erts_internal:term_type(FatMap)),
t_gc_rare_map_overflow_do(Echo, FatMap, fun() -> erlang:garbage_collect() end),
@@ -3016,7 +2979,7 @@ t_gc_rare_map_overflow(Config) ->
unlink(Echo),
%% Test fatmap in exit signal
- Exiter = spawn_link(Node, fun Loop() -> receive {From,Msg} ->
+ Exiter = spawn_link(Node, fun Loop() -> receive {_From,Msg} ->
"not_a_map" = Msg % badmatch!
end,
Loop()
@@ -3034,7 +2997,7 @@ t_gc_rare_map_overflow(Config) ->
t_gc_rare_map_overflow_do(Echo, FatMap, GcFun) ->
Master = self(),
- true = receive M -> false after 0 -> true end, % assert empty msg queue
+ true = receive _M -> false after 0 -> true end, % assert empty msg queue
Echo ! {Master, token},
repeat(1000, fun(_) -> Echo ! {Master, FatMap} end, void),
diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl
index 3f986ca2ed..baa6eb8fe0 100644
--- a/erts/emulator/test/match_spec_SUITE.erl
+++ b/erts/emulator/test/match_spec_SUITE.erl
@@ -20,8 +20,7 @@
-module(match_spec_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2, not_run/1]).
+-export([all/0, suite/0, not_run/1]).
-export([test_1/1, test_2/1, test_3/1, bad_match_spec_bin/1,
trace_control_word/1, silent/1, silent_no_ms/1, silent_test/1,
ms_trace2/1, ms_trace3/1, boxed_and_small/1,
@@ -39,20 +38,11 @@
% This test suite assumes that tracing in general works. What we test is
% the match spec functionality.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([init_per_testcase/2, end_per_testcase/2]).
-
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?t:timetrap(?t:seconds(30)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {seconds, 30}}].
all() ->
case test_server:is_native(match_spec_SUITE) of
@@ -69,106 +59,87 @@ all() ->
true -> [not_run]
end.
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
not_run(Config) when is_list(Config) ->
{skipped, "Native Code"}.
-test_1(doc) ->
- [""];
-test_1(suite) -> [];
test_1(Config) when is_list(Config) ->
- ?line tr(fun() -> ?MODULE:f1(a) end,
- {?MODULE, f1, 1},
- [],
- [{call, {?MODULE, f1, [a]}}]),
-
- ?line tr(fun() -> ?MODULE:f2(a, a) end,
- {?MODULE, f2, 2},
- [{['$1','$1'],[{is_atom, '$1'}],[]}],
- [{call, {?MODULE, f2, [a, a]}}]),
-
- ?line tr(fun() -> ?MODULE:f2(a, a) end,
- {?MODULE, f2, 2},
- [{['$1','$1'],[{is_atom, '$1'}],[{message, false}]}],
- []),
-
- ?line tr(fun() -> ?MODULE:f2(a, a) end,
- {?MODULE, f2, 2},
- [{['$1','$1'],[{is_atom, '$1'}],[{message, 4711}]}],
- [{call, {?MODULE, f2, [a, a]}, 4711}]),
+ tr(fun() -> ?MODULE:f1(a) end,
+ {?MODULE, f1, 1},
+ [],
+ [{call, {?MODULE, f1, [a]}}]),
+
+ tr(fun() -> ?MODULE:f2(a, a) end,
+ {?MODULE, f2, 2},
+ [{['$1','$1'],[{is_atom, '$1'}],[]}],
+ [{call, {?MODULE, f2, [a, a]}}]),
+
+ tr(fun() -> ?MODULE:f2(a, a) end,
+ {?MODULE, f2, 2},
+ [{['$1','$1'],[{is_atom, '$1'}],[{message, false}]}],
+ []),
+
+ tr(fun() -> ?MODULE:f2(a, a) end,
+ {?MODULE, f2, 2},
+ [{['$1','$1'],[{is_atom, '$1'}],[{message, 4711}]}],
+ [{call, {?MODULE, f2, [a, a]}, 4711}]),
Ref = make_ref(),
- ?line tr(fun() -> ?MODULE:f2(Ref, Ref) end,
- {?MODULE, f2, 2},
- [{[Ref,'$1'],[{is_reference, '$1'}],[{message, 4711}]}],
- [{call, {?MODULE, f2, [Ref, Ref]}, 4711}]),
- ?line tr(fun() -> ?MODULE:f2(Ref, Ref) end,
- {?MODULE, f2, 2},
- [{['$1',Ref],[{is_reference, '$1'}],[{message, 4711}]}],
- [{call, {?MODULE, f2, [Ref, Ref]}, 4711}]),
-
- ?line tr(fun() -> ?MODULE:f2(a, a) end,
- {?MODULE, f2, 2},
- [{['$0','$0'],[{is_atom, '$0'}],[{message, 4711}]}],
- [{call, {?MODULE, f2, [a, a]}, 4711}]),
-
- ?line tr(fun() -> ?MODULE:f2(a, b) end,
- {?MODULE, f2, 2},
- [{['_','_'],[],[]}],
- [{call, {?MODULE, f2, [a, b]}}]),
-
- ?line tr(fun() -> ?MODULE:f2(a, b) end,
- {?MODULE, f2, 2},
- [{['_','_'],[],[{message, '$_'}]}],
- [{call, {?MODULE, f2, [a, b]}, [a, b]}]),
-
- ?line tr(fun() -> ?MODULE:f2(a, '$_') end,
- {?MODULE, f2, 2},
- [{['$1','$_'],[{is_atom, '$1'}],[]}],
- [{call, {?MODULE, f2, [a, '$_']}}]),
-
- ?line tr(fun() -> ?MODULE:f1({a}) end,
- {?MODULE, f1, 1},
- [{['$1'],[{'==', '$1', {const, {a}}}],[]}],
- [{call, {?MODULE, f1, [{a}]}}]),
-
- ?line tr(fun() -> ?MODULE:f1({a}) end,
- {?MODULE, f1, 1},
- [{['$1'],[{'==', '$1', {{a}}}],[]}],
- [{call, {?MODULE, f1, [{a}]}}]),
-
-%% Undocumented, currently.
- ?line tr(fun() -> ?MODULE:f2(a, a) end,
- {?MODULE, f2, 2},
- [{['$1','$1'],[{is_atom, '$1'}],[{message, 4711},
- {message, true}]}],
- [{call, {?MODULE, f2, [a, a]}}]),
-
- ?line tr(fun() -> ?MODULE:f2(a, a) end,
- {?MODULE, f2, 2},
- [{['$1','$1'],[{is_atom, '$1'}],[{message, 4711},
- {message, false}]}],
- []),
-
- ?line tr(fun() -> ?MODULE:f2(a, a) end,
- {?MODULE, f2, 2},
- [{['$1','$1'],[{is_atom, '$1'}],[kakalorum]}],
- [{call, {?MODULE, f2, [a, a]}}]),
+ tr(fun() -> ?MODULE:f2(Ref, Ref) end,
+ {?MODULE, f2, 2},
+ [{[Ref,'$1'],[{is_reference, '$1'}],[{message, 4711}]}],
+ [{call, {?MODULE, f2, [Ref, Ref]}, 4711}]),
+ tr(fun() -> ?MODULE:f2(Ref, Ref) end,
+ {?MODULE, f2, 2},
+ [{['$1',Ref],[{is_reference, '$1'}],[{message, 4711}]}],
+ [{call, {?MODULE, f2, [Ref, Ref]}, 4711}]),
+
+ tr(fun() -> ?MODULE:f2(a, a) end,
+ {?MODULE, f2, 2},
+ [{['$0','$0'],[{is_atom, '$0'}],[{message, 4711}]}],
+ [{call, {?MODULE, f2, [a, a]}, 4711}]),
+
+ tr(fun() -> ?MODULE:f2(a, b) end,
+ {?MODULE, f2, 2},
+ [{['_','_'],[],[]}],
+ [{call, {?MODULE, f2, [a, b]}}]),
+
+ tr(fun() -> ?MODULE:f2(a, b) end,
+ {?MODULE, f2, 2},
+ [{['_','_'],[],[{message, '$_'}]}],
+ [{call, {?MODULE, f2, [a, b]}, [a, b]}]),
+
+ tr(fun() -> ?MODULE:f2(a, '$_') end,
+ {?MODULE, f2, 2},
+ [{['$1','$_'],[{is_atom, '$1'}],[]}],
+ [{call, {?MODULE, f2, [a, '$_']}}]),
+
+ tr(fun() -> ?MODULE:f1({a}) end,
+ {?MODULE, f1, 1},
+ [{['$1'],[{'==', '$1', {const, {a}}}],[]}],
+ [{call, {?MODULE, f1, [{a}]}}]),
+
+ tr(fun() -> ?MODULE:f1({a}) end,
+ {?MODULE, f1, 1},
+ [{['$1'],[{'==', '$1', {{a}}}],[]}],
+ [{call, {?MODULE, f1, [{a}]}}]),
+
+ %% Undocumented, currently.
+ tr(fun() -> ?MODULE:f2(a, a) end,
+ {?MODULE, f2, 2},
+ [{['$1','$1'],[{is_atom, '$1'}],[{message, 4711},
+ {message, true}]}],
+ [{call, {?MODULE, f2, [a, a]}}]),
+
+ tr(fun() -> ?MODULE:f2(a, a) end,
+ {?MODULE, f2, 2},
+ [{['$1','$1'],[{is_atom, '$1'}],[{message, 4711},
+ {message, false}]}],
+ []),
+
+ tr(fun() -> ?MODULE:f2(a, a) end,
+ {?MODULE, f2, 2},
+ [{['$1','$1'],[{is_atom, '$1'}],[kakalorum]}],
+ [{call, {?MODULE, f2, [a, a]}}]),
%% Verify that 'process_dump' can handle a matchstate on the stack.
tr(fun() -> fbinmatch(<<0>>, 0) end,
@@ -176,56 +147,49 @@ test_1(Config) when is_list(Config) ->
[{['_'],[],[{message, {process_dump}}]}],
[fun({trace, _, call, {?MODULE, f1, [0]}, _Bin}) -> true end]),
-% Error cases
- ?line errchk([{['$1','$1'],[{is_atom, '$1'}],[{banka, kanin}]}]),
-
+ % Error cases
+ errchk([{['$1','$1'],[{is_atom, '$1'}],[{banka, kanin}]}]),
ok.
-test_2(doc) ->
- [""];
-test_2(suite) -> [];
test_2(Config) when is_list(Config) ->
- ?line tr(fun() -> ?MODULE:f2(a, a) end,
- {?MODULE, f2, 2},
- [{['$1','$1'],[{is_atom, '$1'}],[{return_trace}]}],
- [{call, {?MODULE, f2, [a, a]}},
- {return_from, {?MODULE, f2, 2}, {a, a}}]),
+ tr(fun() -> ?MODULE:f2(a, a) end,
+ {?MODULE, f2, 2},
+ [{['$1','$1'],[{is_atom, '$1'}],[{return_trace}]}],
+ [{call, {?MODULE, f2, [a, a]}},
+ {return_from, {?MODULE, f2, 2}, {a, a}}]),
ok.
-test_3(doc) ->
- ["Test the enable_trace/2 and caller/0 PAM instructions"];
-test_3(suite) -> [];
+%% Test the enable_trace/2 and caller/0 PAM instructions
test_3(Config) when is_list(Config) ->
- ?line Fun1 = fun() ->
+ Fun1 = fun() ->
register(fnoppelklopfer,self()),
?MODULE:f2(a, b),
?MODULE:f2(a, b)
end,
- ?line P1 = spawn(?MODULE, runner, [self(), Fun1]),
- ?line Pat = [{['$1','$1'],[],[{message,
- [{enable_trace, P1, call},{caller}]}]},
- {['_','_'],[],[{message,
- [{disable_trace, fnoppelklopfer, call}]}]}],
- ?line Fun2 = fun() -> ?MODULE:f3(a, a) end,
- ?line P2 = spawn(?MODULE, runner, [self(), Fun2]),
- ?line erlang:trace(P2, true, [call]),
- ?line erlang:trace_pattern({?MODULE, f2, 2}, Pat),
- ?line collect(P2, [{trace, P2, call, {?MODULE, f2, [a, a]}, [true,
+ P1 = spawn(?MODULE, runner, [self(), Fun1]),
+ Pat = [{['$1','$1'],[],[{message,
+ [{enable_trace, P1, call},{caller}]}]},
+ {['_','_'],[],[{message,
+ [{disable_trace, fnoppelklopfer, call}]}]}],
+ Fun2 = fun() -> ?MODULE:f3(a, a) end,
+ P2 = spawn(?MODULE, runner, [self(), Fun2]),
+ erlang:trace(P2, true, [call]),
+ erlang:trace_pattern({?MODULE, f2, 2}, Pat),
+ collect(P2, [{trace, P2, call, {?MODULE, f2, [a, a]}, [true,
{?MODULE,f3,2}]}]),
- ?line collect(P1, [{trace, P1, call, {?MODULE, f2, [a, b]}, [true]}]),
- ?line ok.
+ collect(P1, [{trace, P1, call, {?MODULE, f2, [a, b]}, [true]}]),
+ ok.
-otp_9422(doc) -> [];
otp_9422(Config) when is_list(Config) ->
Laps = 10000,
- ?line Fun1 = fun() -> otp_9422_tracee() end,
- ?line P1 = spawn_link(?MODULE, loop_runner, [self(), Fun1, Laps]),
+ Fun1 = fun() -> otp_9422_tracee() end,
+ P1 = spawn_link(?MODULE, loop_runner, [self(), Fun1, Laps]),
io:format("spawned ~p as tracee\n", [P1]),
- ?line erlang:trace(P1, true, [call, silent]),
+ erlang:trace(P1, true, [call, silent]),
- ?line Fun2 = fun() -> otp_9422_trace_changer() end,
- ?line P2 = spawn_link(?MODULE, loop_runner, [self(), Fun2, Laps]),
+ Fun2 = fun() -> otp_9422_trace_changer() end,
+ P2 = spawn_link(?MODULE, loop_runner, [self(), Fun2, Laps]),
io:format("spawned ~p as trace_changer\n", [P2]),
start_collect(P1),
@@ -244,9 +208,9 @@ otp_9422_tracee() ->
otp_9422_trace_changer() ->
Pat1 = [{[a], [], [{enable_trace, arity}]}],
- ?line erlang:trace_pattern({?MODULE, f1, 1}, Pat1),
+ erlang:trace_pattern({?MODULE, f1, 1}, Pat1),
Pat2 = [{[b], [], [{disable_trace, arity}]}],
- ?line erlang:trace_pattern({?MODULE, f1, 1}, Pat2).
+ erlang:trace_pattern({?MODULE, f1, 1}, Pat2).
@@ -261,261 +225,227 @@ bad_match_spec_bin(Config) when is_list(Config) ->
-trace_control_word(doc) ->
- ["Test the erlang:system_info(trace_control_word) and ",
- "erlang:system_flag(trace_control_word, Value) BIFs, ",
- "as well as the get_tcw/0 and set_tcw/1 PAM instructions"];
-trace_control_word(suite) -> [];
+%% Test the erlang:system_info(trace_control_word) and
+%% erlang:system_flag(trace_control_word, Value) BIFs,
+%% as well as the get_tcw/0 and set_tcw/1 PAM instructions
trace_control_word(Config) when is_list(Config) ->
- ?line 32 = Bits = tcw_bits(),
- ?line High = 1 bsl (Bits - 1),
- ?line erlang:system_flag(trace_control_word, 17),
- ?line tr(fun() -> ?MODULE:f1(a) end,
- {?MODULE, f1, 1},
- [{'_',[{'=:=', {get_tcw}, 17}],[]}],
- [{call, {?MODULE, f1, [a]}}]),
- ?line tr(fun() -> ?MODULE:f1(a) end,
- {?MODULE, f1, 1},
- [{'_',[{'=:=', {get_tcw}, 18}],[]}],
- []),
- ?line erlang:system_flag(trace_control_word, High),
- ?line tr(fun() -> ?MODULE:f1(a) end,
- {?MODULE, f1, 1},
- [{'_',[{'=:=', {get_tcw}, High}],[]}],
- [{call, {?MODULE, f1, [a]}}]),
- ?line erlang:system_flag(trace_control_word, 0),
- ?line tr(fun() ->
- ?MODULE:f1(a),
- ?MODULE:f1(start),
- ?MODULE:f1(b),
- ?MODULE:f1(c),
- ?MODULE:f1(high),
- ?MODULE:f1(d),
- ?MODULE:f1(stop),
- ?MODULE:f1(e)
- end,
- {?MODULE, f1, 1},
- [{[start],
- [],
- [{message, {set_tcw, 17}}]},
- {[stop],
- [],
- [{message, {set_tcw, 0}}]},
- {[high],
- [],
- [{message, {set_tcw, High}}]},
- {['_'],
- [{'>', {get_tcw}, 0}],
- [{set_tcw, {'+', 1, {get_tcw}}}, {message, {get_tcw}}] }],
- [{call, {?MODULE, f1, [start]}, 0},
- {call, {?MODULE, f1, [b]}, 18},
- {call, {?MODULE, f1, [c]}, 19},
- {call, {?MODULE, f1, [high]}, 19},
- {call, {?MODULE, f1, [d]}, High + 1},
- {call, {?MODULE, f1, [stop]}, High + 1}]),
- ?line 0 = erlang:system_info(trace_control_word),
+ 32 = Bits = tcw_bits(),
+ High = 1 bsl (Bits - 1),
+ erlang:system_flag(trace_control_word, 17),
+ tr(fun() -> ?MODULE:f1(a) end,
+ {?MODULE, f1, 1},
+ [{'_',[{'=:=', {get_tcw}, 17}],[]}],
+ [{call, {?MODULE, f1, [a]}}]),
+ tr(fun() -> ?MODULE:f1(a) end,
+ {?MODULE, f1, 1},
+ [{'_',[{'=:=', {get_tcw}, 18}],[]}],
+ []),
+ erlang:system_flag(trace_control_word, High),
+ tr(fun() -> ?MODULE:f1(a) end,
+ {?MODULE, f1, 1},
+ [{'_',[{'=:=', {get_tcw}, High}],[]}],
+ [{call, {?MODULE, f1, [a]}}]),
+ erlang:system_flag(trace_control_word, 0),
+ tr(fun() ->
+ ?MODULE:f1(a),
+ ?MODULE:f1(start),
+ ?MODULE:f1(b),
+ ?MODULE:f1(c),
+ ?MODULE:f1(high),
+ ?MODULE:f1(d),
+ ?MODULE:f1(stop),
+ ?MODULE:f1(e)
+ end,
+ {?MODULE, f1, 1},
+ [{[start],
+ [],
+ [{message, {set_tcw, 17}}]},
+ {[stop],
+ [],
+ [{message, {set_tcw, 0}}]},
+ {[high],
+ [],
+ [{message, {set_tcw, High}}]},
+ {['_'],
+ [{'>', {get_tcw}, 0}],
+ [{set_tcw, {'+', 1, {get_tcw}}}, {message, {get_tcw}}] }],
+ [{call, {?MODULE, f1, [start]}, 0},
+ {call, {?MODULE, f1, [b]}, 18},
+ {call, {?MODULE, f1, [c]}, 19},
+ {call, {?MODULE, f1, [high]}, 19},
+ {call, {?MODULE, f1, [d]}, High + 1},
+ {call, {?MODULE, f1, [stop]}, High + 1}]),
+ 0 = erlang:system_info(trace_control_word),
ok.
tcw_bits() ->
- ?line tcw_bits(erlang:system_flag(trace_control_word, 0), 0, 0).
+ tcw_bits(erlang:system_flag(trace_control_word, 0), 0, 0).
tcw_bits(Save, Prev, Bits) ->
- ?line Curr = 1 bsl Bits,
- ?line case catch erlang:system_flag(trace_control_word, Curr) of
- {'EXIT' , {badarg, _}} ->
- ?line Prev = erlang:system_flag(trace_control_word, Save),
- Bits;
- Prev ->
- ?line Curr = erlang:system_info(trace_control_word),
- tcw_bits(Save, Curr, Bits+1)
- end.
-
-
-
-silent(doc) ->
- ["Test the erlang:trace(_, _, [silent]) flag ",
- "as well as the silent/0 PAM instruction"];
-silent(suite) -> [];
+ Curr = 1 bsl Bits,
+ case catch erlang:system_flag(trace_control_word, Curr) of
+ {'EXIT' , {badarg, _}} ->
+ Prev = erlang:system_flag(trace_control_word, Save),
+ Bits;
+ Prev ->
+ Curr = erlang:system_info(trace_control_word),
+ tcw_bits(Save, Curr, Bits+1)
+ end.
+
+
+%% Test the erlang:trace(_, _, [silent]) flag
+%% as well as the silent/0 PAM instruction
silent(Config) when is_list(Config) ->
%% Global call trace
- ?line tr(fun() ->
- ?MODULE:f1(a), % No trace - not active
- ?MODULE:f1(miss), % No trace - no activation
- ?MODULE:f1(b), % No trace - still not active
- ?MODULE:f1(start), % Trace - activation
- ?MODULE:f1(c), % Trace - active
- f1(d), % No trace - local call
- ?MODULE:f1(miss), % Trace - no inactivation
- ?MODULE:f1(e), % Trace - still active
- ?MODULE:f1(stop), % No trace - inactivation
- ?MODULE:f1(f) % No trace - not active
- end,
- {?MODULE, f1, 1},
- [call, silent],
- [{[start],
- [],
- [{silent, false}, {message, start}]},
- {[stop],
- [],
- [{silent, true}, {message, stop}]},
- {[miss],
- [],
- [{silent, neither_true_nor_false}, {message, miss}]},
- {['$1'],
- [],
- [{message, '$1'}] }],
- [global],
- [{call, {?MODULE, f1, [start]}, start},
- {call, {?MODULE, f1, [c]}, c},
- {call, {?MODULE, f1, [miss]}, miss},
- {call, {?MODULE, f1, [e]}, e} ]),
+ tr(fun() ->
+ ?MODULE:f1(a), % No trace - not active
+ ?MODULE:f1(miss), % No trace - no activation
+ ?MODULE:f1(b), % No trace - still not active
+ ?MODULE:f1(start), % Trace - activation
+ ?MODULE:f1(c), % Trace - active
+ f1(d), % No trace - local call
+ ?MODULE:f1(miss), % Trace - no inactivation
+ ?MODULE:f1(e), % Trace - still active
+ ?MODULE:f1(stop), % No trace - inactivation
+ ?MODULE:f1(f) % No trace - not active
+ end,
+ {?MODULE, f1, 1},
+ [call, silent],
+ [{[start],
+ [],
+ [{silent, false}, {message, start}]},
+ {[stop],
+ [],
+ [{silent, true}, {message, stop}]},
+ {[miss],
+ [],
+ [{silent, neither_true_nor_false}, {message, miss}]},
+ {['$1'],
+ [],
+ [{message, '$1'}] }],
+ [global],
+ [{call, {?MODULE, f1, [start]}, start},
+ {call, {?MODULE, f1, [c]}, c},
+ {call, {?MODULE, f1, [miss]}, miss},
+ {call, {?MODULE, f1, [e]}, e} ]),
%% Local call trace
- ?line tr(fun() ->
- ?MODULE:f1(a), % No trace - not active
- f1(b), % No trace - not active
- ?MODULE:f1(start), % Trace - activation
- ?MODULE:f1(c), % Trace - active
- f1(d), % Trace - active
- f1(stop), % No trace - inactivation
- ?MODULE:f1(e), % No trace - not active
- f1(f) % No trace - not active
- end,
- {?MODULE, f1, 1},
- [call, silent],
- [{[start],
- [],
- [{silent, false}, {message, start}]},
- {[stop],
- [],
- [{silent, true}, {message, stop}]},
- {['$1'],
- [],
- [{message, '$1'}] }],
- [local],
- [{call, {?MODULE, f1, [start]}, start},
- {call, {?MODULE, f1, [c]}, c},
- {call, {?MODULE, f1, [d]}, d} ]),
+ tr(fun() ->
+ ?MODULE:f1(a), % No trace - not active
+ f1(b), % No trace - not active
+ ?MODULE:f1(start), % Trace - activation
+ ?MODULE:f1(c), % Trace - active
+ f1(d), % Trace - active
+ f1(stop), % No trace - inactivation
+ ?MODULE:f1(e), % No trace - not active
+ f1(f) % No trace - not active
+ end,
+ {?MODULE, f1, 1},
+ [call, silent],
+ [{[start],
+ [],
+ [{silent, false}, {message, start}]},
+ {[stop],
+ [],
+ [{silent, true}, {message, stop}]},
+ {['$1'],
+ [],
+ [{message, '$1'}] }],
+ [local],
+ [{call, {?MODULE, f1, [start]}, start},
+ {call, {?MODULE, f1, [c]}, c},
+ {call, {?MODULE, f1, [d]}, d} ]),
ok.
-silent_no_ms(doc) ->
- ["Test the erlang:trace(_, _, [silent]) flag without match specs"];
-silent_no_ms(suite) -> [];
+%% Test the erlang:trace(_, _, [silent]) flag without match specs
silent_no_ms(Config) when is_list(Config) ->
%% Global call trace
%%
%% Trace f2/2 and erlang:integer_to_list/1 without match spec
%% and use match spec on f1/1 to control silent flag.
- ?line tr(
- fun () ->
- ?MODULE:f1(a),
- ?MODULE:f2(b, c),
- _ = erlang:integer_to_list(id(1)),
- ?MODULE:f3(d, e),
- ?MODULE:f1(start),
- ?MODULE:f2(f, g),
- _ = erlang:integer_to_list(id(2)),
- ?MODULE:f3(h, i),
- ?MODULE:f1(stop),
- ?MODULE:f2(j, k),
- _ = erlang:integer_to_list(id(3)),
- ?MODULE:f3(l, m)
- end,
- fun (Tracee) ->
- ?line 1 =
- erlang:trace(Tracee, true,
- [call,silent,return_to]),
- ?line 1 =
- erlang:trace_pattern(
- {?MODULE,f2,2},
- [],
- [global]),
- ?line 1 =
- erlang:trace_pattern(
- {erlang,integer_to_list,1},
- [],
- [global]),
- ?line 1 =
- erlang:trace_pattern(
- {?MODULE,f1,1},
- [{[start],[],[{silent,false}]},
- {[stop],[],[{silent,true}]}],
- [global]),
- %%
- %% Expected: (no return_to for global call trace)
- %%
- ?line
- [{trace,Tracee,call,{?MODULE,f1,[start]}},
- {trace,Tracee,call,{?MODULE,f2,[f,g]}},
- {trace,Tracee,call,{erlang,integer_to_list,[2]}},
- {trace,Tracee,call,{?MODULE,f2,[h,i]}}]
- end),
+ tr(
+ fun () ->
+ ?MODULE:f1(a),
+ ?MODULE:f2(b, c),
+ _ = erlang:integer_to_list(id(1)),
+ ?MODULE:f3(d, e),
+ ?MODULE:f1(start),
+ ?MODULE:f2(f, g),
+ _ = erlang:integer_to_list(id(2)),
+ ?MODULE:f3(h, i),
+ ?MODULE:f1(stop),
+ ?MODULE:f2(j, k),
+ _ = erlang:integer_to_list(id(3)),
+ ?MODULE:f3(l, m)
+ end,
+ fun (Tracee) ->
+ 1 = erlang:trace(Tracee, true, [call,silent,return_to]),
+ 1 = erlang:trace_pattern( {?MODULE,f2,2}, [], [global]),
+ 1 = erlang:trace_pattern( {erlang,integer_to_list,1}, [], [global]),
+ 1 = erlang:trace_pattern(
+ {?MODULE,f1,1},
+ [{[start],[],[{silent,false}]},
+ {[stop],[],[{silent,true}]}],
+ [global]),
+ %%
+ %% Expected: (no return_to for global call trace)
+ %%
+ [{trace,Tracee,call,{?MODULE,f1,[start]}},
+ {trace,Tracee,call,{?MODULE,f2,[f,g]}},
+ {trace,Tracee,call,{erlang,integer_to_list,[2]}},
+ {trace,Tracee,call,{?MODULE,f2,[h,i]}}]
+ end),
%% Local call trace
%%
%% Trace f2/2 and erlang:integer_to_list/1 without match spec
%% and use match spec on f1/1 to control silent flag.
- ?line tr(
- fun () ->
- ?MODULE:f1(a),
- ?MODULE:f2(b, c),
- _ = erlang:integer_to_list(id(1)),
- ?MODULE:f3(d, e),
- ?MODULE:f1(start),
- ?MODULE:f2(f, g),
- _ = erlang:integer_to_list(id(2)),
- ?MODULE:f3(h, i),
- ?MODULE:f1(stop),
- ?MODULE:f2(j, k),
- _ = erlang:integer_to_list(id(3)),
- ?MODULE:f3(l, m)
- end,
- fun (Tracee) ->
- ?line 1 =
- erlang:trace(Tracee, true,
- [call,silent,return_to]),
- ?line 1 =
- erlang:trace_pattern(
- {?MODULE,f2,2},
- [],
- [local]),
- ?line 1 =
- erlang:trace_pattern(
- {erlang,integer_to_list,1},
- [],
- [local]),
- ?line 1 =
- erlang:trace_pattern(
- {?MODULE,f1,1},
- [{[start],[],[{silent,false}]},
- {[stop],[],[{silent,true}]}],
- [local]),
- %%
- %% Expected:
- %%
- ?line
- [{trace,Tracee,call,{?MODULE,f1,[start]}},
- {trace,Tracee,return_to,
- {?MODULE,'-silent_no_ms/1-fun-2-',0}},
- {trace,Tracee,call,{?MODULE,f2,[f,g]}},
- {trace,Tracee,return_to,
- {?MODULE,'-silent_no_ms/1-fun-2-',0}},
- {trace,Tracee,call,{erlang,integer_to_list,[2]}},
- {trace,Tracee,return_to,
- {?MODULE,'-silent_no_ms/1-fun-2-',0}},
- {trace,Tracee,call,{?MODULE,f2,[h,i]}},
- {trace,Tracee,return_to,{?MODULE,f3,2}}]
- end).
-
-silent_test(doc) ->
- ["Test that match_spec_test does not activate silent"];
+ tr(
+ fun () ->
+ ?MODULE:f1(a),
+ ?MODULE:f2(b, c),
+ _ = erlang:integer_to_list(id(1)),
+ ?MODULE:f3(d, e),
+ ?MODULE:f1(start),
+ ?MODULE:f2(f, g),
+ _ = erlang:integer_to_list(id(2)),
+ ?MODULE:f3(h, i),
+ ?MODULE:f1(stop),
+ ?MODULE:f2(j, k),
+ _ = erlang:integer_to_list(id(3)),
+ ?MODULE:f3(l, m)
+ end,
+ fun (Tracee) ->
+ 1 = erlang:trace(Tracee, true, [call,silent,return_to]),
+ 1 = erlang:trace_pattern( {?MODULE,f2,2}, [], [local]),
+ 1 = erlang:trace_pattern( {erlang,integer_to_list,1}, [], [local]),
+ 1 = erlang:trace_pattern(
+ {?MODULE,f1,1},
+ [{[start],[],[{silent,false}]},
+ {[stop],[],[{silent,true}]}],
+ [local]),
+ %%
+ %% Expected:
+ %%
+ [{trace,Tracee,call,{?MODULE,f1,[start]}},
+ {trace,Tracee,return_to,
+ {?MODULE,'-silent_no_ms/1-fun-2-',0}},
+ {trace,Tracee,call,{?MODULE,f2,[f,g]}},
+ {trace,Tracee,return_to,
+ {?MODULE,'-silent_no_ms/1-fun-2-',0}},
+ {trace,Tracee,call,{erlang,integer_to_list,[2]}},
+ {trace,Tracee,return_to,
+ {?MODULE,'-silent_no_ms/1-fun-2-',0}},
+ {trace,Tracee,call,{?MODULE,f2,[h,i]}},
+ {trace,Tracee,return_to,{?MODULE,f3,2}}]
+ end).
+
+%% Test that match_spec_test does not activate silent
silent_test(_Config) ->
{flags,[]} = erlang:trace_info(self(),flags),
erlang:match_spec_test([],[{'_',[],[{silent,true}]}],trace),
{flags,[]} = erlang:trace_info(self(),flags).
-ms_trace2(doc) ->
- ["Test the match spec functions {trace/2}"];
-ms_trace2(suite) -> [];
+%% Test the match spec functions {trace/2}
ms_trace2(Config) when is_list(Config) ->
Tracer = self(),
%% Meta trace init
@@ -523,75 +453,58 @@ ms_trace2(Config) when is_list(Config) ->
%% Trace global f1/1, local f2/2, global erlang:integer_to_list/1
%% without match spec. Use match spec functions
%% {trace/2} to control trace through fn/2,3.
- ?line tr(
- fun () ->
- ?MODULE:f1(a),
- ?MODULE:f2(b, c),
- _ = erlang:integer_to_list(id(1)),
- ?MODULE:f3(d, e),
- fn([all], [call,return_to,{tracer,Tracer}]),
- ?MODULE:f1(f),
- f2(g, h),
- f1(i),
- _ = erlang:integer_to_list(id(2)),
- ?MODULE:f3(j, k),
- fn([call,return_to], []),
- ?MODULE:f1(l),
- ?MODULE:f2(m, n),
- _ = erlang:integer_to_list(id(3)),
- ?MODULE:f3(o, p)
- end,
- fun (Tracee) ->
- ?line 1 =
- erlang:trace(Tracee, false, [all]),
- ?line 1 =
- erlang:trace_pattern(
- {?MODULE,f1,1},
- [],
- [global]),
- ?line 1 =
- erlang:trace_pattern(
- {?MODULE,f2,2},
- [],
- [local]),
- ?line 1 =
- erlang:trace_pattern(
- {erlang,integer_to_list,1},
- [],
- [global]),
- ?line 3 =
- erlang:trace_pattern(
- {?MODULE,fn,'_'},
- [{['$1','$2'],[],
- [{trace,'$1','$2'},{message,ms_trace2}]}],
- [meta]),
- %%
- %% Expected: (no return_to for global call trace)
- %%
- ?line Origin = {match_spec_SUITE,'-ms_trace2/1-fun-0-',1},
- ?line
- [{trace_ts,Tracee,call,
- {?MODULE,fn,
- [[all],[call,return_to,{tracer,Tracer}]]},
- ms_trace2},
- {trace,Tracee,call,{?MODULE,f1,[f]}},
- {trace,Tracee,call,{?MODULE,f2,[g,h]}},
- {trace,Tracee,return_to,Origin},
- {trace,Tracee,call,{erlang,integer_to_list,[2]}},
- {trace,Tracee,call,{?MODULE,f2,[j,k]}},
- {trace,Tracee,return_to,{?MODULE,f3,2}},
- {trace_ts,Tracee,call,
- {?MODULE,fn,
- [[call,return_to],[]]},
- ms_trace2}]
- end),
+ tr(
+ fun () ->
+ ?MODULE:f1(a),
+ ?MODULE:f2(b, c),
+ _ = erlang:integer_to_list(id(1)),
+ ?MODULE:f3(d, e),
+ fn([all], [call,return_to,{tracer,Tracer}]),
+ ?MODULE:f1(f),
+ f2(g, h),
+ f1(i),
+ _ = erlang:integer_to_list(id(2)),
+ ?MODULE:f3(j, k),
+ fn([call,return_to], []),
+ ?MODULE:f1(l),
+ ?MODULE:f2(m, n),
+ _ = erlang:integer_to_list(id(3)),
+ ?MODULE:f3(o, p)
+ end,
+ fun (Tracee) ->
+ 1 = erlang:trace(Tracee, false, [all]),
+ 1 = erlang:trace_pattern( {?MODULE,f1,1}, [], [global]),
+ 1 = erlang:trace_pattern( {?MODULE,f2,2}, [], [local]),
+ 1 = erlang:trace_pattern( {erlang,integer_to_list,1}, [], [global]),
+ 3 = erlang:trace_pattern(
+ {?MODULE,fn,'_'},
+ [{['$1','$2'],[],
+ [{trace,'$1','$2'},{message,ms_trace2}]}],
+ [meta]),
+ %%
+ %% Expected: (no return_to for global call trace)
+ %%
+ Origin = {match_spec_SUITE,'-ms_trace2/1-fun-0-',1},
+ [{trace_ts,Tracee,call,
+ {?MODULE,fn,
+ [[all],[call,return_to,{tracer,Tracer}]]},
+ ms_trace2},
+ {trace,Tracee,call,{?MODULE,f1,[f]}},
+ {trace,Tracee,call,{?MODULE,f2,[g,h]}},
+ {trace,Tracee,return_to,Origin},
+ {trace,Tracee,call,{erlang,integer_to_list,[2]}},
+ {trace,Tracee,call,{?MODULE,f2,[j,k]}},
+ {trace,Tracee,return_to,{?MODULE,f3,2}},
+ {trace_ts,Tracee,call,
+ {?MODULE,fn,
+ [[call,return_to],[]]},
+ ms_trace2}]
+ end),
ok.
-ms_trace3(doc) ->
- ["Test the match spec functions {trace/3}"];
-ms_trace3(suite) -> [];
+%% Test the match spec functions {trace/3}
ms_trace3(Config) when is_list(Config) ->
TraceeName = 'match_spec_SUITE:ms_trace3',
Tracer = self(),
@@ -602,134 +515,115 @@ ms_trace3(Config) when is_list(Config) ->
%% {trace/2} to control trace through fn/2,3.
Tag = make_ref(),
Controller =
- spawn_link(
- fun () ->
- receive
- {Tracee,Tag,start} ->
- fn(TraceeName, [all],
- [call,return_to,send,'receive',
- {tracer,Tracer}]),
- Tracee ! {self(),Tag,started},
- receive {Tracee,Tag,stop_1} -> ok end,
- fn(Tracee, [call,return_to], []),
- Tracee ! {self(),Tag,stopped_1},
- receive {Tracee,Tag,stop_2} -> ok end,
- fn(Tracee, [all], []),
- Tracee ! {self(),Tag,stopped_2}
- end
- end),
- ?line tr(
- fun () -> %% Action
- register(TraceeName, self()),
- ?MODULE:f1(a),
- ?MODULE:f2(b, c),
- _ = erlang:integer_to_list(id(1)),
- ?MODULE:f3(d, e),
- Controller ! {self(),Tag,start},
- receive {Controller,Tag,started} -> ok end,
- ?MODULE:f1(f),
- f2(g, h),
- f1(i),
- _ = erlang:integer_to_list(id(2)),
- ?MODULE:f3(j, k),
- Controller ! {self(),Tag,stop_1},
- receive {Controller,Tag,stopped_1} -> ok end,
- ?MODULE:f1(l),
- ?MODULE:f2(m, n),
- _ = erlang:integer_to_list(id(3)),
- ?MODULE:f3(o, p),
- Controller ! {self(),Tag,stop_2},
- receive {Controller,Tag,stopped_2} -> ok end,
- ?MODULE:f1(q),
- ?MODULE:f2(r, s),
- _ = erlang:integer_to_list(id(4)),
- ?MODULE:f3(t, u)
- end,
-
- fun (Tracee) -> %% Startup
- ?line 1 =
- erlang:trace(Tracee, false, [all]),
- ?line 1 =
- erlang:trace_pattern(
- {?MODULE,f1,1},
- [],
- [global]),
- ?line 1 =
- erlang:trace_pattern(
- {?MODULE,f2,2},
- [],
- [local]),
- ?line 1 =
- erlang:trace_pattern(
- {erlang,integer_to_list,1},
- [],
- [global]),
- ?line 3 =
- erlang:trace_pattern(
- {?MODULE,fn,'_'},
- [{['$1','$2','$3'],[],
- [{trace,'$1','$2','$3'},{message,Tag}]}],
- [meta]),
- %%
- %% Expected: (no return_to for global call trace)
- %%
- ?line Origin = {match_spec_SUITE,'-ms_trace3/1-fun-1-',2},
- ?line
- [{trace_ts,Controller,call,
- {?MODULE,fn,[TraceeName,[all],
- [call,return_to,send,'receive',
- {tracer,Tracer}]]},
- Tag},
- {trace,Tracee,'receive',{Controller,Tag,started}},
- {trace,Tracee,call,{?MODULE,f1,[f]}},
- {trace,Tracee,call,{?MODULE,f2,[g,h]}},
- {trace,Tracee,return_to,Origin},
- {trace,Tracee,call,{erlang,integer_to_list,[2]}},
- {trace,Tracee,call,{?MODULE,f2,[j,k]}},
- {trace,Tracee,return_to,{?MODULE,f3,2}},
- {trace,Tracee,send,{Tracee,Tag,stop_1},Controller},
- {trace_ts,Controller,call,
- {?MODULE,fn,[Tracee,[call,return_to],[]]},
- Tag},
- {trace_ts,Controller,call,
- {?MODULE,fn,[Tracee,[all],[]]},
- Tag}]
- end),
+ spawn_link(
+ fun () ->
+ receive
+ {Tracee,Tag,start} ->
+ fn(TraceeName, [all],
+ [call,return_to,send,'receive',
+ {tracer,Tracer}]),
+ Tracee ! {self(),Tag,started},
+ receive {Tracee,Tag,stop_1} -> ok end,
+ fn(Tracee, [call,return_to], []),
+ Tracee ! {self(),Tag,stopped_1},
+ receive {Tracee,Tag,stop_2} -> ok end,
+ fn(Tracee, [all], []),
+ Tracee ! {self(),Tag,stopped_2}
+ end
+ end),
+ tr(
+ fun () -> %% Action
+ register(TraceeName, self()),
+ ?MODULE:f1(a),
+ ?MODULE:f2(b, c),
+ _ = erlang:integer_to_list(id(1)),
+ ?MODULE:f3(d, e),
+ Controller ! {self(),Tag,start},
+ receive {Controller,Tag,started} -> ok end,
+ ?MODULE:f1(f),
+ f2(g, h),
+ f1(i),
+ _ = erlang:integer_to_list(id(2)),
+ ?MODULE:f3(j, k),
+ Controller ! {self(),Tag,stop_1},
+ receive {Controller,Tag,stopped_1} -> ok end,
+ ?MODULE:f1(l),
+ ?MODULE:f2(m, n),
+ _ = erlang:integer_to_list(id(3)),
+ ?MODULE:f3(o, p),
+ Controller ! {self(),Tag,stop_2},
+ receive {Controller,Tag,stopped_2} -> ok end,
+ ?MODULE:f1(q),
+ ?MODULE:f2(r, s),
+ _ = erlang:integer_to_list(id(4)),
+ ?MODULE:f3(t, u)
+ end,
+
+ fun (Tracee) -> %% Startup
+ 1 = erlang:trace(Tracee, false, [all]),
+ 1 = erlang:trace_pattern( {?MODULE,f1,1}, [], [global]),
+ 1 = erlang:trace_pattern( {?MODULE,f2,2}, [], [local]),
+ 1 = erlang:trace_pattern( {erlang,integer_to_list,1}, [], [global]),
+ 3 = erlang:trace_pattern(
+ {?MODULE,fn,'_'},
+ [{['$1','$2','$3'],[],
+ [{trace,'$1','$2','$3'},{message,Tag}]}],
+ [meta]),
+ %%
+ %% Expected: (no return_to for global call trace)
+ %%
+ Origin = {match_spec_SUITE,'-ms_trace3/1-fun-1-',2},
+ [{trace_ts,Controller,call,
+ {?MODULE,fn,[TraceeName,[all],
+ [call,return_to,send,'receive',
+ {tracer,Tracer}]]},
+ Tag},
+ {trace,Tracee,'receive',{Controller,Tag,started}},
+ {trace,Tracee,call,{?MODULE,f1,[f]}},
+ {trace,Tracee,call,{?MODULE,f2,[g,h]}},
+ {trace,Tracee,return_to,Origin},
+ {trace,Tracee,call,{erlang,integer_to_list,[2]}},
+ {trace,Tracee,call,{?MODULE,f2,[j,k]}},
+ {trace,Tracee,return_to,{?MODULE,f3,2}},
+ {trace,Tracee,send,{Tracee,Tag,stop_1},Controller},
+ {trace_ts,Controller,call,
+ {?MODULE,fn,[Tracee,[call,return_to],[]]},
+ Tag},
+ {trace_ts,Controller,call,
+ {?MODULE,fn,[Tracee,[all],[]]},
+ Tag}]
+ end),
ok.
-destructive_in_test_bif(doc) ->
- ["Test that destructive operations in test bif does not really happen"];
-destructive_in_test_bif(suite) -> [];
+%% Test that destructive operations in test bif does not really happen
destructive_in_test_bif(Config) when is_list(Config) ->
- ?line {ok,OldToken,_,_} = erlang:match_spec_test
+ {ok,OldToken,_,_} = erlang:match_spec_test
([],
[{'_',[],[{message,{get_seq_token}}]}],trace),
- ?line {ok,_,_,_} = erlang:match_spec_test
+ {ok,_,_,_} = erlang:match_spec_test
([],
[{'_',[],[{message,{set_seq_token, label, 1}}]}],
trace),
- ?line {ok,OldToken,_,_} = erlang:match_spec_test
+ {ok,OldToken,_,_} = erlang:match_spec_test
([],
[{'_',[],[{message,{get_seq_token}}]}],trace),
- ?line {ok, OldTCW,_,_} = erlang:match_spec_test
+ {ok, OldTCW,_,_} = erlang:match_spec_test
([],[{'_',[],[{message,{get_tcw}}]}],trace),
- ?line {ok,OldTCW,_,_} = erlang:match_spec_test
+ {ok,OldTCW,_,_} = erlang:match_spec_test
([],
[{'_',[],[{message,{set_tcw, OldTCW+1}}]}],
trace),
- ?line {ok, OldTCW,_,_} = erlang:match_spec_test
+ {ok, OldTCW,_,_} = erlang:match_spec_test
([],[{'_',[],[{message,{get_tcw}}]}],trace),
ok.
-boxed_and_small(doc) ->
- ["Test that the comparision between boxed and small does not crash emulator"];
-boxed_and_small(suite) -> [];
+%% Test that the comparision between boxed and small does not crash emulator
boxed_and_small(Config) when is_list(Config) ->
- ?line {ok, Node} = start_node(match_spec_suite_other),
- ?line ok = rpc:call(Node,?MODULE,do_boxed_and_small,[]),
- ?line stop_node(Node),
+ {ok, Node} = start_node(match_spec_suite_other),
+ ok = rpc:call(Node,?MODULE,do_boxed_and_small,[]),
+ stop_node(Node),
ok.
do_boxed_and_small() ->
@@ -739,13 +633,11 @@ do_boxed_and_small() ->
{ok, false, _, _} = erlang:match_spec_test({0,3},[{{make_ref(),'_'},[],['$_']}],table),
ok.
-faulty_seq_trace(doc) ->
- ["Test that faulty seq_trace_call does not crash emulator"];
-faulty_seq_trace(suite) -> [];
+%% Test that faulty seq_trace_call does not crash emulator
faulty_seq_trace(Config) when is_list(Config) ->
- ?line {ok, Node} = start_node(match_spec_suite_other),
- ?line ok = rpc:call(Node,?MODULE,do_faulty_seq_trace,[]),
- ?line stop_node(Node),
+ {ok, Node} = start_node(match_spec_suite_other),
+ ok = rpc:call(Node,?MODULE,do_faulty_seq_trace,[]),
+ stop_node(Node),
ok.
do_faulty_seq_trace() ->
@@ -757,63 +649,58 @@ errchk(Pat) ->
{'EXIT', {badarg, _}} ->
ok;
Other ->
- test_server:fail({noerror, Other})
+ ct:fail({noerror, Other})
end.
-unary_minus(suite) ->
- [];
-unary_minus(doc) ->
- ["Checks that unary minus works"];
+%% Checks that unary minus works
unary_minus(Config) when is_list(Config) ->
- ?line {ok,true,[],[]} = erlang:match_spec_test
+ {ok,true,[],[]} = erlang:match_spec_test
(5,
[{'$1',
[{'<',{'-','$1'},-4}],
[true]}],
table),
- ?line {ok,false,[],[]} = erlang:match_spec_test
+ {ok,false,[],[]} = erlang:match_spec_test
(5,
[{'$1',
[{'<',{'-','$1'},-6}],
[true]}],
table),
- ?line {ok,true,[],[]} = erlang:match_spec_test
+ {ok,true,[],[]} = erlang:match_spec_test
(5,
[{'$1',
[{'=:=',{'-','$1',2},3}],
[true]}],
table),
- ?line {ok,false,[],[]} = erlang:match_spec_test
+ {ok,false,[],[]} = erlang:match_spec_test
(hej,
[{'$1',
[{'=/=',{'-','$1'},0}],
[true]}],
table),
ok.
-unary_plus(suite) ->
- [];
-unary_plus(doc) ->
- ["Checks that unary plus works"];
+
+%% Checks that unary plus works
unary_plus(Config) when is_list(Config) ->
- ?line {ok,true,[],[]} = erlang:match_spec_test
+ {ok,true,[],[]} = erlang:match_spec_test
(5,
[{'$1',
[{'<',{'+','$1'},6}],
[true]}],
table),
- ?line {ok,false,[],[]} = erlang:match_spec_test
+ {ok,false,[],[]} = erlang:match_spec_test
(5,
[{'$1',
[{'<',{'+','$1'},4}],
[true]}],
table),
- ?line {ok,true,[],[]} = erlang:match_spec_test
+ {ok,true,[],[]} = erlang:match_spec_test
(5,
[{'$1',
[{'=:=',{'+','$1',2},7}],
[true]}],
table),
- ?line {ok,false,[],[]} = erlang:match_spec_test
+ {ok,false,[],[]} = erlang:match_spec_test
(hej,
[{'$1',
[{'=/=',{'+','$1'},0}],
@@ -824,53 +711,50 @@ unary_plus(Config) when is_list(Config) ->
-guard_exceptions(suite) ->
- [];
-guard_exceptions(doc) ->
- ["Checks that exceptions in guards are handled correctly"];
+%% Checks that exceptions in guards are handled correctly
guard_exceptions(Config) when is_list(Config) ->
- ?line {ok,false,[],[]} = erlang:match_spec_test
+ {ok,false,[],[]} = erlang:match_spec_test
(5,
[{'$1',
[{'or',{is_integer,'$1'},{'or','$1','$1'}}],
[true]}],
table),
- ?line {ok,true,[],[]} = erlang:match_spec_test
+ {ok,true,[],[]} = erlang:match_spec_test
(5,
[{'$1',
[{'orelse',{is_integer,'$1'},
{'or','$1','$1'}}],
[true]}],
table),
- ?line {ok,false,[],[]} = erlang:match_spec_test
+ {ok,false,[],[]} = erlang:match_spec_test
(5,
[{'$1',
[{'orelse',{'or','$1',true},
{is_integer,'$1'}}],
[true]}],
table),
- ?line {ok,false,[],[]} = erlang:match_spec_test
+ {ok,false,[],[]} = erlang:match_spec_test
(5,
[{'$1',
[{'or',{is_integer,'$1'},
{'orelse','$1',true}}],
[true]}],
table),
- ?line {ok,true,[],[]} = erlang:match_spec_test
+ {ok,true,[],[]} = erlang:match_spec_test
(5,
[{'$1',
[{'or',{is_integer,'$1'},
{'orelse',true,'$1'}}],
[true]}],
table),
- ?line {ok,true,[],[]} = erlang:match_spec_test
+ {ok,true,[],[]} = erlang:match_spec_test
(5,
[{'$1',
[{'or',{is_integer,'$1'},
{'andalso',false,'$1'}}],
[true]}],
table),
- ?line {ok,false,[],[]} = erlang:match_spec_test
+ {ok,false,[],[]} = erlang:match_spec_test
(5,
[{'$1',
[{'or',{is_integer,'$1'},
@@ -878,7 +762,7 @@ guard_exceptions(Config) when is_list(Config) ->
[true]}],
table),
- ?line {ok,false,[],[]} = erlang:match_spec_test
+ {ok,false,[],[]} = erlang:match_spec_test
(5,
[{'$1',
[{'or',{is_integer,'$1'},
@@ -888,19 +772,16 @@ guard_exceptions(Config) when is_list(Config) ->
ok.
-fpe(suite) ->
- [];
-fpe(doc) ->
- ["Checks floating point exceptions in match-specs"];
+%% Checks floating point exceptions in match-specs
fpe(Config) when is_list(Config) ->
MS = [{{'$1'},[],[{'/','$1',0}]}],
case catch (['EXIT','EXIT'] =
ets:match_spec_run([{1},{2}],ets:match_spec_compile(MS))) of
- {'EXIT',_} -> test_server:fail({error,
- "Floating point exceptions faulty"});
+ {'EXIT',_} -> ct:fail({error, "Floating point exceptions faulty"});
_ -> ok
end.
+%% Test maps in match-specs
maps(Config) when is_list(Config) ->
{ok,#{},[],[]} = erlang:match_spec_test(#{}, [{'_',[],['$_']}], table),
{ok,#{},[],[]} = erlang:match_spec_test(#{}, [{#{},[],['$_']}], table),
@@ -980,11 +861,11 @@ moving_labels(Config) when is_list(Config) ->
%% point at their correct target.
%%
Ms = [{{'$1','$2'},[],[{{ok,{'andalso','$1','$2'},[1,2,3]}}]}],
- ?line {ok,{ok,false,[1,2,3]},[],[]} =
+ {ok,{ok,false,[1,2,3]},[],[]} =
erlang:match_spec_test({true,false}, Ms, table),
Ms2 = [{{'$1','$2'},[],[{{ok,{'orelse','$1','$2'},[1,2,3]}}]}],
- ?line {ok,{ok,true,[1,2,3]},[],[]} =
+ {ok,{ok,true,[1,2,3]},[],[]} =
erlang:match_spec_test({true,false}, Ms2, table),
ok.
@@ -995,13 +876,13 @@ tr(Fun, MFA, Pat, Expected) ->
tr(Fun, MFA, TraceFlags, Pat, PatFlags, Expected0) ->
tr(Fun,
fun(P) ->
- erlang:trace(P, true, TraceFlags),
- erlang:trace_pattern(MFA, Pat, PatFlags),
- lists:map(
- fun(X) when is_function(X,1) -> X;
- (X) -> list_to_tuple([trace, P | tuple_to_list(X)])
- end,
- Expected0)
+ erlang:trace(P, true, TraceFlags),
+ erlang:trace_pattern(MFA, Pat, PatFlags),
+ lists:map(
+ fun(X) when is_function(X,1) -> X;
+ (X) -> list_to_tuple([trace, P | tuple_to_list(X)])
+ end,
+ Expected0)
end).
tr(RunFun, ControlFun) ->
@@ -1016,51 +897,51 @@ collect(P, TMs) ->
collect([]) ->
receive
M ->
- ?t:format("Got unexpected: ~p~n", [M]),
+ io:format("Got unexpected: ~p~n", [M]),
flush({got_unexpected,M})
after 17 ->
ok
end;
collect([TM | TMs]) ->
- ?t:format( "Expecting: ~p~n", [TM]),
+ io:format( "Expecting: ~p~n", [TM]),
receive
- M0 ->
- M = case element(1, M0) of
- trace_ts ->
- list_to_tuple(lists:reverse(
- tl(lists:reverse(tuple_to_list(M0)))));
- _ -> M0
- end,
- case is_function(TM,1) of
- true ->
- case (catch TM(M)) of
- true ->
- ?t:format("Got: ~p~n", [M]),
- collect(TMs);
- _ ->
- ?t:format("Got unexpected: ~p~n", [M]),
- flush({got_unexpected,M})
- end;
-
- false ->
- case M of
- TM ->
- ?t:format("Got: ~p~n", [M]),
- collect(TMs);
- _ ->
- ?t:format("Got unexpected: ~p~n", [M]),
- flush({got_unexpected,M})
- end
- end
+ M0 ->
+ M = case element(1, M0) of
+ trace_ts ->
+ list_to_tuple(lists:reverse(
+ tl(lists:reverse(tuple_to_list(M0)))));
+ _ -> M0
+ end,
+ case is_function(TM,1) of
+ true ->
+ case (catch TM(M)) of
+ true ->
+ io:format("Got: ~p~n", [M]),
+ collect(TMs);
+ _ ->
+ io:format("Got unexpected: ~p~n", [M]),
+ flush({got_unexpected,M})
+ end;
+
+ false ->
+ case M of
+ TM ->
+ io:format("Got: ~p~n", [M]),
+ collect(TMs);
+ _ ->
+ io:format("Got unexpected: ~p~n", [M]),
+ flush({got_unexpected,M})
+ end
+ end
end.
flush(Reason) ->
receive
- M ->
- ?t:format("In queue: ~p~n", [M]),
- flush(Reason)
+ M ->
+ io:format("In queue: ~p~n", [M]),
+ flush(Reason)
after 17 ->
- ?t:fail(Reason)
+ ct:fail(Reason)
end.
start_collect(P) ->
@@ -1071,33 +952,33 @@ stop_collect(P) ->
stop_collect(P, Order) ->
P ! {Order, self()},
receive
- {gone, P} ->
- ok
+ {gone, P} ->
+ ok
end.
runner(Collector, Fun) ->
receive
- {go, Collector} ->
- go
+ {go, Collector} ->
+ go
end,
Fun(),
receive
- {done, Collector} ->
- Collector ! {gone, self()}
+ {done, Collector} ->
+ Collector ! {gone, self()}
end.
loop_runner(Collector, Fun, Laps) ->
receive
- {go, Collector} ->
- go
+ {go, Collector} ->
+ go
end,
loop_runner_cont(Collector, Fun, 0, Laps).
loop_runner_cont(Collector, _Fun, Laps, Laps) ->
receive
- {done, Collector} -> ok;
- {abort, Collector} -> ok
+ {done, Collector} -> ok;
+ {abort, Collector} -> ok
end,
io:format("loop_runner ~p exit after ~p laps\n", [self(), Laps]),
Collector ! {gone, self()};
@@ -1105,11 +986,11 @@ loop_runner_cont(Collector, _Fun, Laps, Laps) ->
loop_runner_cont(Collector, Fun, N, Laps) ->
Fun(),
receive
- {abort, Collector} ->
- io:format("loop_runner ~p aborted after ~p of ~p laps\n", [self(), N+1, Laps]),
- Collector ! {gone, self()}
+ {abort, Collector} ->
+ io:format("loop_runner ~p aborted after ~p of ~p laps\n", [self(), N+1, Laps]),
+ Collector ! {gone, self()}
after 0 ->
- loop_runner_cont(Collector, Fun, N+1, Laps)
+ loop_runner_cont(Collector, Fun, N+1, Laps)
end.
@@ -1141,7 +1022,7 @@ start_node(Name) ->
Pa = filename:dirname(code:which(?MODULE)),
Cookie = atom_to_list(erlang:get_cookie()),
test_server:start_node(Name, slave,
- [{args, "-setcookie " ++ Cookie ++" -pa " ++ Pa}]).
+ [{args, "-setcookie " ++ Cookie ++" -pa " ++ Pa}]).
stop_node(Node) ->
test_server:stop_node(Node).
diff --git a/erts/emulator/test/message_queue_data_SUITE.erl b/erts/emulator/test/message_queue_data_SUITE.erl
new file mode 100644
index 0000000000..12c42d24aa
--- /dev/null
+++ b/erts/emulator/test/message_queue_data_SUITE.erl
@@ -0,0 +1,213 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2014. 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(message_queue_data_SUITE).
+
+-export([all/0, suite/0]).
+-export([basic/1, process_info_messages/1]).
+
+-export([basic_test/1]).
+
+-include_lib("common_test/include/ct.hrl").
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 2}}].
+
+all() ->
+ [basic, process_info_messages].
+
+%%
+%%
+%% Test cases
+%%
+%%
+
+basic(Config) when is_list(Config) ->
+
+ basic_test(erlang:system_info(message_queue_data)),
+
+ {ok, Node1} = start_node(Config, "+xmqd off_heap"),
+ ok = rpc:call(Node1, ?MODULE, basic_test, [off_heap]),
+ stop_node(Node1),
+
+ {ok, Node2} = start_node(Config, "+xmqd on_heap"),
+ ok = rpc:call(Node2, ?MODULE, basic_test, [on_heap]),
+ stop_node(Node2),
+
+ {ok, Node3} = start_node(Config, "+xmqd mixed"),
+ ok = rpc:call(Node3, ?MODULE, basic_test, [mixed]),
+ stop_node(Node3),
+
+ ok.
+
+is_valid_mqd_value(off_heap) ->
+ true;
+is_valid_mqd_value(on_heap) ->
+ true;
+is_valid_mqd_value(mixed) ->
+ true;
+is_valid_mqd_value(_) ->
+ false.
+
+
+basic_test(Default) ->
+
+ Default = erlang:system_info(message_queue_data),
+ true = is_valid_mqd_value(Default),
+
+ {message_queue_data, Default} = process_info(self(), message_queue_data),
+ Default = process_flag(message_queue_data, off_heap),
+ {message_queue_data, off_heap} = process_info(self(), message_queue_data),
+ off_heap = process_flag(message_queue_data, on_heap),
+ {message_queue_data, on_heap} = process_info(self(), message_queue_data),
+ on_heap = process_flag(message_queue_data, mixed),
+ {message_queue_data, mixed} = process_info(self(), message_queue_data),
+ mixed = process_flag(message_queue_data, Default),
+ {'EXIT', _} = (catch process_flag(message_queue_data, blupp)),
+
+ P1 = spawn_opt(fun () -> receive after infinity -> ok end end,
+ [link]),
+ {message_queue_data, Default} = process_info(P1, message_queue_data),
+ unlink(P1),
+ exit(P1, bye),
+
+ P2 = spawn_opt(fun () -> receive after infinity -> ok end end,
+ [link, {message_queue_data, off_heap}]),
+ {message_queue_data, off_heap} = process_info(P2, message_queue_data),
+ unlink(P2),
+ exit(P2, bye),
+
+ P3 = spawn_opt(fun () -> receive after infinity -> ok end end,
+ [link, {message_queue_data, on_heap}]),
+ {message_queue_data, on_heap} = process_info(P3, message_queue_data),
+ unlink(P3),
+ exit(P3, bye),
+
+ P4 = spawn_opt(fun () -> receive after infinity -> ok end end,
+ [link, {message_queue_data, mixed}]),
+ {message_queue_data, mixed} = process_info(P4, message_queue_data),
+ unlink(P4),
+ exit(P4, bye),
+
+ {'EXIT', _} = (catch spawn_opt(fun () -> receive after infinity -> ok end end,
+ [link, {message_queue_data, blapp}])),
+
+ ok.
+
+process_info_messages(Config) when is_list(Config) ->
+ Tester = self(),
+ P1 = spawn_opt(fun () ->
+ receive after 500 -> ok end,
+ mixed = process_flag(message_queue_data, off_heap),
+ Tester ! first,
+ receive after 500 -> ok end,
+ off_heap = process_flag(message_queue_data, on_heap),
+ Tester ! second,
+ receive after 500 -> ok end,
+ on_heap = process_flag(message_queue_data, mixed),
+ Tester ! third,
+ receive after 500 -> ok end,
+ mixed = process_flag(message_queue_data, off_heap),
+ Tester ! fourth,
+
+ receive after infinity -> ok end
+ end,
+ [link, {message_queue_data, mixed}]),
+
+ P1 ! "A",
+ receive first -> ok end,
+ P1 ! "B",
+ receive second -> ok end,
+ P1 ! "C",
+ receive third -> ok end,
+ P1 ! "D",
+ receive fourth -> ok end,
+ P1 ! "E",
+
+ {messages, ["A", "B", "C", "D", "E"]} = process_info(P1, messages),
+
+ P2 = spawn_opt(fun () ->
+ receive after 500 -> ok end,
+ mixed = process_flag(message_queue_data, off_heap),
+ Tester ! first,
+ receive after 500 -> ok end,
+ off_heap = process_flag(message_queue_data, on_heap),
+ Tester ! second,
+ receive after 500 -> ok end,
+ on_heap = process_flag(message_queue_data, mixed),
+ Tester ! third,
+ receive after 500 -> ok end,
+ mixed = process_flag(message_queue_data, off_heap),
+ Tester ! fourth,
+ receive after 500 -> ok end,
+
+ Tester ! process_info(self(), messages),
+
+ receive M1 -> M1 = "A" end,
+ receive M2 -> M2 = "B" end,
+ receive M3 -> M3 = "C" end,
+ receive M4 -> M4 = "D" end,
+ receive M5 -> M5 = "E" end,
+
+ Tester ! self()
+ end,
+ [link, {message_queue_data, mixed}]),
+
+ P2 ! "A",
+ receive first -> ok end,
+ P2 ! "B",
+ receive second -> ok end,
+ P2 ! "C",
+ receive third -> ok end,
+ P2 ! "D",
+ receive fourth -> ok end,
+ P2 ! "E",
+
+ receive
+ Msg ->
+ {messages, ["A", "B", "C", "D", "E"]} = Msg
+ end,
+
+ receive P2 -> ok end,
+
+ ok.
+
+%%
+%%
+%% helpers
+%%
+%%
+
+start_node(Config) ->
+ start_node(Config, []).
+start_node(Config, Opts) when is_list(Config), is_list(Opts) ->
+ Pa = filename:dirname(code:which(?MODULE)),
+ Name = list_to_atom(atom_to_list(?MODULE)
+ ++ "-"
+ ++ atom_to_list(proplists:get_value(testcase, Config))
+ ++ "-"
+ ++ integer_to_list(erlang:system_time(seconds))
+ ++ "-"
+ ++ integer_to_list(erlang:unique_integer([positive]))),
+ test_server:start_node(Name, slave, [{args, Opts++" -pa "++Pa}]).
+
+stop_node(Node) ->
+ test_server:stop_node(Node).
diff --git a/erts/emulator/test/module_info_SUITE.erl b/erts/emulator/test/module_info_SUITE.erl
index 7c2101ca05..f8208c5866 100644
--- a/erts/emulator/test/module_info_SUITE.erl
+++ b/erts/emulator/test/module_info_SUITE.erl
@@ -20,11 +20,9 @@
-module(module_info_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2,
+-export([all/0, suite/0,
exports/1,functions/1,deleted/1,native/1,info/1]).
%%-compile(native).
@@ -32,46 +30,23 @@
%% Helper.
-export([native_proj/1,native_filter/1]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 3}}].
all() ->
modules().
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
modules() ->
[exports, functions, deleted, native, info].
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog = ?t:timetrap(?t:minutes(3)),
- [{watchdog,Dog}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
%% Should return all functions exported from this module. (local)
all_exported() ->
All = add_arity(modules()),
- lists:sort([{all,0},{suite,0},{groups,0},
- {init_per_suite,1},{end_per_suite,1},
- {init_per_group,2},{end_per_group,2},
- {init_per_testcase,2},{end_per_testcase,2},
- {module_info,0},{module_info,1},{native_proj,1},
- {native_filter,1}|All]).
+ lists:sort([{all,0},{suite,0},
+ {module_info,0},{module_info,1},
+ {native_proj,1},
+ {native_filter,1}|All]).
%% Should return all functions in this module. (local)
all_functions() ->
@@ -95,7 +70,7 @@ functions(Config) when is_list(Config) ->
%% Test that deleted modules cause badarg
deleted(Config) when is_list(Config) ->
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
File = filename:join(Data, "module_info_test"),
{ok,module_info_test,Code} = compile:file(File, [binary]),
{module,module_info_test} = erlang:load_module(module_info_test, Code),
diff --git a/erts/emulator/test/monitor_SUITE.erl b/erts/emulator/test/monitor_SUITE.erl
index 4db17969c0..82e3a36c1e 100644
--- a/erts/emulator/test/monitor_SUITE.erl
+++ b/erts/emulator/test/monitor_SUITE.erl
@@ -20,21 +20,20 @@
-module(monitor_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- case_1/1, case_1a/1, case_2/1, case_2a/1, mon_e_1/1, demon_e_1/1, demon_1/1,
- demon_2/1, demon_3/1, demonitor_flush/1,
- local_remove_monitor/1, remote_remove_monitor/1, mon_1/1, mon_2/1,
- large_exit/1, list_cleanup/1, mixer/1, named_down/1, otp_5827/1,
- monitor_time_offset/1]).
-
--export([init_per_testcase/2, end_per_testcase/2]).
+-export([all/0, suite/0, groups/0,
+ case_1/1, case_1a/1, case_2/1, case_2a/1, mon_e_1/1, demon_e_1/1, demon_1/1,
+ demon_2/1, demon_3/1, demonitor_flush/1,
+ local_remove_monitor/1, remote_remove_monitor/1, mon_1/1, mon_2/1,
+ large_exit/1, list_cleanup/1, mixer/1, named_down/1, otp_5827/1,
+ monitor_time_offset/1]).
-export([y2/1, g/1, g0/0, g1/0, large_exit_sub/1]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 15}}].
all() ->
[case_1, case_1a, case_2, case_2a, mon_e_1, demon_e_1,
@@ -47,132 +46,103 @@ groups() ->
[{remove_monitor, [],
[local_remove_monitor, remote_remove_monitor]}].
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?t:timetrap(?t:minutes(15)),
- [{watchdog, Dog},{testcase, Func}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
-case_1(doc) ->
- "A monitors B, B kills A and then exits (yielded core dump)";
-case_1(suite) -> [];
+%% A monitors B, B kills A and then exits (yielded core dump)
case_1(Config) when is_list(Config) ->
- ?line process_flag(trap_exit, true),
- ?line spawn_link(?MODULE, g0, []),
- ?line receive _ -> ok end,
+ process_flag(trap_exit, true),
+ spawn_link(?MODULE, g0, []),
+ receive _ -> ok end,
ok.
-case_1a(doc) ->
- "A monitors B, B kills A and then exits (yielded core dump)";
+%% A monitors B, B kills A and then exits (yielded core dump)
case_1a(Config) when is_list(Config) ->
- ?line process_flag(trap_exit, true),
- ?line spawn_link(?MODULE, g1, []),
- ?line receive _ -> ok end,
+ process_flag(trap_exit, true),
+ spawn_link(?MODULE, g1, []),
+ receive _ -> ok end,
ok.
g0() ->
- ?line B = spawn(?MODULE, g, [self()]),
- ?line erlang:monitor(process, B),
- ?line B ! ok,
- ?line receive ok -> ok end,
+ B = spawn(?MODULE, g, [self()]),
+ erlang:monitor(process, B),
+ B ! ok,
+ receive ok -> ok end,
ok.
g1() ->
- ?line {B,_} = spawn_monitor(?MODULE, g, [self()]),
- ?line B ! ok,
- ?line receive ok -> ok end,
+ {B,_} = spawn_monitor(?MODULE, g, [self()]),
+ B ! ok,
+ receive ok -> ok end,
ok.
g(Parent) ->
- ?line receive ok -> ok end,
- ?line exit(Parent, foo),
- ?line ok.
+ receive ok -> ok end,
+ exit(Parent, foo),
+ ok.
-case_2(doc) ->
- "A monitors B, B demonitors A (yielded core dump)";
+%% A monitors B, B demonitors A (yielded core dump)
case_2(Config) when is_list(Config) ->
- ?line B = spawn(?MODULE, y2, [self()]),
- ?line R = erlang:monitor(process, B),
- ?line B ! R,
- ?line receive
- {'EXIT', _} -> ok;
- Other ->
- test_server:fail({rec, Other})
- end,
- ?line expect_down(R, B, normal),
+ B = spawn(?MODULE, y2, [self()]),
+ R = erlang:monitor(process, B),
+ B ! R,
+ receive
+ {'EXIT', _} -> ok;
+ Other ->
+ ct:fail({rec, Other})
+ end,
+ expect_down(R, B, normal),
ok.
-case_2a(doc) ->
- "A monitors B, B demonitors A (yielded core dump)";
+%% A monitors B, B demonitors A (yielded core dump)
case_2a(Config) when is_list(Config) ->
- ?line {B,R} = spawn_monitor(?MODULE, y2, [self()]),
- ?line B ! R,
- ?line receive
- {'EXIT', _} -> ok;
- Other ->
- test_server:fail({rec, Other})
- end,
- ?line expect_down(R, B, normal),
+ {B,R} = spawn_monitor(?MODULE, y2, [self()]),
+ B ! R,
+ receive
+ {'EXIT', _} -> ok;
+ Other ->
+ ct:fail({rec, Other})
+ end,
+ expect_down(R, B, normal),
ok.
y2(Parent) ->
- ?line R = receive T -> T end,
- ?line Parent ! (catch erlang:demonitor(R)),
+ R = receive T -> T end,
+ Parent ! (catch erlang:demonitor(R)),
ok.
expect_down(Ref, P) ->
receive
- {'DOWN', Ref, process, P, Reason} ->
- Reason;
- Other ->
- test_server:fail({rec, Other})
+ {'DOWN', Ref, process, P, Reason} ->
+ Reason;
+ Other ->
+ ct:fail({rec, Other})
end.
expect_down(Ref, P, Reason) ->
receive
- {'DOWN', Ref, process, P, Reason} ->
- ok;
- Other ->
- test_server:fail({rec, Other})
+ {'DOWN', Ref, process, P, Reason} ->
+ ok;
+ Other ->
+ ct:fail({rec, Other})
end.
expect_no_msg() ->
receive
- Msg ->
- test_server:fail({msg, Msg})
+ Msg ->
+ ct:fail({msg, Msg})
after 0 ->
- ok
+ ok
end.
%%% Error cases for monitor/2
-mon_e_1(doc) ->
- "Error cases for monitor/2";
-mon_e_1(suite) -> [];
mon_e_1(Config) when is_list(Config) ->
- ?line {ok, N} = test_server:start_node(hej, slave, []),
- ?line mon_error(plutt, self()),
- ?line mon_error(process, [bingo]),
- ?line mon_error(process, {rex, N, junk}),
- ?line mon_error(process, 1),
+ {ok, N} = test_server:start_node(hej, slave, []),
+ mon_error(plutt, self()),
+ mon_error(process, [bingo]),
+ mon_error(process, {rex, N, junk}),
+ mon_error(process, 1),
- ?line true = test_server:stop_node(N),
+ true = test_server:stop_node(N),
ok.
%%% We would also like to have a test case that tries to monitor something
@@ -185,155 +155,142 @@ mon_e_1(Config) when is_list(Config) ->
mon_error(Type, Item) ->
case catch erlang:monitor(Type, Item) of
- {'EXIT', _} ->
- ok;
- Other ->
- test_server:fail({err, Other})
+ {'EXIT', _} ->
+ ok;
+ Other ->
+ ct:fail({err, Other})
end.
%%% Error cases for demonitor/1
-demon_e_1(doc) ->
- "Error cases for demonitor/1";
-demon_e_1(suite) -> [];
demon_e_1(Config) when is_list(Config) ->
- ?line {ok, N} = test_server:start_node(hej, slave, []),
- ?line demon_error(plutt, badarg),
- ?line demon_error(1, badarg),
+ {ok, N} = test_server:start_node(hej, slave, []),
+ demon_error(plutt, badarg),
+ demon_error(1, badarg),
%% Demonitor with ref created at other node
- ?line R1 = rpc:call(N, erlang, make_ref, []),
- ?line demon_error(R1, badarg),
+ R1 = rpc:call(N, erlang, make_ref, []),
+ demon_error(R1, badarg),
%% Demonitor with ref created at wrong monitor link end
- ?line P0 = self(),
- ?line P2 = spawn(
- fun() ->
- P0 ! {self(), ref, erlang:monitor(process,P0)},
- receive {P0, stop} -> ok end
- end ),
- ?line receive
- {P2, ref, R2} ->
- ?line demon_error(R2, badarg),
- ?line P2 ! {self(), stop};
- Other2 ->
- test_server:fail({rec, Other2})
- end,
-
- ?line true = test_server:stop_node(N),
+ P0 = self(),
+ P2 = spawn(
+ fun() ->
+ P0 ! {self(), ref, erlang:monitor(process,P0)},
+ receive {P0, stop} -> ok end
+ end ),
+ receive
+ {P2, ref, R2} ->
+ demon_error(R2, badarg),
+ P2 ! {self(), stop};
+ Other2 ->
+ ct:fail({rec, Other2})
+ end,
+
+ true = test_server:stop_node(N),
ok.
demon_error(Ref, Reason) ->
case catch erlang:demonitor(Ref) of
- {'EXIT', {Reason, _}} ->
- ok;
- Other ->
- test_server:fail({err, Other})
+ {'EXIT', {Reason, _}} ->
+ ok;
+ Other ->
+ ct:fail({err, Other})
end.
%%% No-op cases for demonitor/1
-demon_1(doc) ->
- "demonitor/1";
-demon_1(suite) -> [];
demon_1(Config) when is_list(Config) ->
- ?line true = erlang:demonitor(make_ref()),
+ true = erlang:demonitor(make_ref()),
ok.
%%% Cases for demonitor/1
-demon_2(doc) ->
- "Cases for demonitor/1";
-demon_2(suite) -> [];
demon_2(Config) when is_list(Config) ->
- ?line R1 = erlang:monitor(process, self()),
- ?line true = erlang:demonitor(R1),
+ R1 = erlang:monitor(process, self()),
+ true = erlang:demonitor(R1),
%% Extra demonitor
- ?line true = erlang:demonitor(R1),
- ?line expect_no_msg(),
+ true = erlang:demonitor(R1),
+ expect_no_msg(),
%% Normal 'DOWN'
- ?line P2 = spawn(timer, sleep, [1]),
- ?line R2 = erlang:monitor(process, P2),
- ?line case expect_down(R2, P2) of
- normal -> ?line ok;
- noproc -> ?line ok;
- BadReason -> ?line ?t:fail({bad_reason, BadReason})
- end,
-
-%% OTP-5772
-% %% 'DOWN' before demonitor
-% ?line P3 = spawn(timer, sleep, [100000]),
-% ?line R3 = erlang:monitor(process, P3),
-% ?line exit(P3, frop),
-% ?line erlang:demonitor(R3),
-% ?line expect_down(R3, P3, frop),
+ P2 = spawn(timer, sleep, [1]),
+ R2 = erlang:monitor(process, P2),
+ case expect_down(R2, P2) of
+ normal -> ok;
+ noproc -> ok;
+ BadReason -> ct:fail({bad_reason, BadReason})
+ end,
+
+ %% OTP-5772
+ % %% 'DOWN' before demonitor
+ % P3 = spawn(timer, sleep, [100000]),
+ % R3 = erlang:monitor(process, P3),
+ % exit(P3, frop),
+ % erlang:demonitor(R3),
+ % expect_down(R3, P3, frop),
%% Demonitor before 'DOWN'
- ?line P4 = spawn(timer, sleep, [100000]),
- ?line R4 = erlang:monitor(process, P4),
- ?line erlang:demonitor(R4),
- ?line exit(P4, frop),
- ?line expect_no_msg(),
+ P4 = spawn(timer, sleep, [100000]),
+ R4 = erlang:monitor(process, P4),
+ erlang:demonitor(R4),
+ exit(P4, frop),
+ expect_no_msg(),
ok.
-demon_3(doc) ->
- "Distributed case for demonitor/1 (OTP-3499)";
-demon_3(suite) -> [];
+%% Distributed case for demonitor/1 (OTP-3499)
demon_3(Config) when is_list(Config) ->
- ?line {ok, N} = test_server:start_node(hej, slave, []),
+ {ok, N} = test_server:start_node(hej, slave, []),
%% 'DOWN' before demonitor
- ?line P2 = spawn(N, timer, sleep, [100000]),
- ?line R2 = erlang:monitor(process, P2),
- ?line true = test_server:stop_node(N),
- ?line true = erlang:demonitor(R2),
- ?line expect_down(R2, P2, noconnection),
+ P2 = spawn(N, timer, sleep, [100000]),
+ R2 = erlang:monitor(process, P2),
+ true = test_server:stop_node(N),
+ true = erlang:demonitor(R2),
+ expect_down(R2, P2, noconnection),
- ?line {ok, N2} = test_server:start_node(hej, slave, []),
+ {ok, N2} = test_server:start_node(hej, slave, []),
%% Demonitor before 'DOWN'
- ?line P3 = spawn(N2, timer, sleep, [100000]),
- ?line R3 = erlang:monitor(process, P3),
- ?line true = erlang:demonitor(R3),
- ?line true = test_server:stop_node(N2),
- ?line expect_no_msg(),
+ P3 = spawn(N2, timer, sleep, [100000]),
+ R3 = erlang:monitor(process, P3),
+ true = erlang:demonitor(R3),
+ true = test_server:stop_node(N2),
+ expect_no_msg(),
ok.
-demonitor_flush(suite) -> [];
-demonitor_flush(doc) -> [];
demonitor_flush(Config) when is_list(Config) ->
- ?line {'EXIT', {badarg, _}} = (catch erlang:demonitor(make_ref(), flush)),
- ?line {'EXIT', {badarg, _}} = (catch erlang:demonitor(make_ref(), [flus])),
- ?line {'EXIT', {badarg, _}} = (catch erlang:demonitor(x, [flush])),
- ?line {ok, N} = test_server:start_node(demonitor_flush, slave, []),
- ?line ok = demonitor_flush_test(N),
- ?line true = test_server:stop_node(N),
- ?line ok = demonitor_flush_test(node()).
-
+ {'EXIT', {badarg, _}} = (catch erlang:demonitor(make_ref(), flush)),
+ {'EXIT', {badarg, _}} = (catch erlang:demonitor(make_ref(), [flus])),
+ {'EXIT', {badarg, _}} = (catch erlang:demonitor(x, [flush])),
+ {ok, N} = test_server:start_node(demonitor_flush, slave, []),
+ ok = demonitor_flush_test(N),
+ true = test_server:stop_node(N),
+ ok = demonitor_flush_test(node()).
+
demonitor_flush_test(Node) ->
- ?line P = spawn(Node, timer, sleep, [100000]),
- ?line M1 = erlang:monitor(process, P),
- ?line M2 = erlang:monitor(process, P),
- ?line M3 = erlang:monitor(process, P),
- ?line M4 = erlang:monitor(process, P),
- ?line true = erlang:demonitor(M1, [flush, flush]),
- ?line exit(P, bang),
- ?line receive {'DOWN', M2, process, P, bang} -> ok end,
- ?line receive after 100 -> ok end,
- ?line true = erlang:demonitor(M3, [flush]),
- ?line true = erlang:demonitor(M4, []),
- ?line receive {'DOWN', M4, process, P, bang} -> ok end,
- ?line receive
- {'DOWN', M, _, _, _} =DM when M == M1,
- M == M3 ->
- ?line ?t:fail({unexpected_down_message, DM})
- after 100 ->
- ?line ok
- end.
+ P = spawn(Node, timer, sleep, [100000]),
+ M1 = erlang:monitor(process, P),
+ M2 = erlang:monitor(process, P),
+ M3 = erlang:monitor(process, P),
+ M4 = erlang:monitor(process, P),
+ true = erlang:demonitor(M1, [flush, flush]),
+ exit(P, bang),
+ receive {'DOWN', M2, process, P, bang} -> ok end,
+ receive after 100 -> ok end,
+ true = erlang:demonitor(M3, [flush]),
+ true = erlang:demonitor(M4, []),
+ receive {'DOWN', M4, process, P, bang} -> ok end,
+ receive
+ {'DOWN', M, _, _, _} =DM when M == M1,
+ M == M3 ->
+ ct:fail({unexpected_down_message, DM})
+ after 100 ->
+ ok
+ end.
-define(RM_MON_GROUPS, 100).
-define(RM_MON_GPROCS, 100).
@@ -341,33 +298,33 @@ demonitor_flush_test(Node) ->
local_remove_monitor(Config) when is_list(Config) ->
Gs = generate(fun () -> start_remove_monitor_group(node()) end,
- ?RM_MON_GROUPS),
+ ?RM_MON_GROUPS),
{True, False} = lists:foldl(fun (G, {T, F}) ->
- receive
- {rm_mon_res, G, {GT, GF}} ->
- {T+GT, F+GF}
- end
- end,
- {0, 0},
- Gs),
+ receive
+ {rm_mon_res, G, {GT, GF}} ->
+ {T+GT, F+GF}
+ end
+ end,
+ {0, 0},
+ Gs),
erlang:display({local_remove_monitor, True, False}),
{comment,
"True = "++integer_to_list(True)++"; False = "++integer_to_list(False)}.
-
+
remote_remove_monitor(Config) when is_list(Config) ->
- ?line {ok, N} = test_server:start_node(demonitor_flush, slave, []),
+ {ok, N} = test_server:start_node(demonitor_flush, slave, []),
Gs = generate(fun () -> start_remove_monitor_group(node()) end,
- ?RM_MON_GROUPS),
+ ?RM_MON_GROUPS),
{True, False} = lists:foldl(fun (G, {T, F}) ->
- receive
- {rm_mon_res, G, {GT, GF}} ->
- {T+GT, F+GF}
- end
- end,
- {0, 0},
- Gs),
+ receive
+ {rm_mon_res, G, {GT, GF}} ->
+ {T+GT, F+GF}
+ end
+ end,
+ {0, 0},
+ Gs),
erlang:display({remote_remove_monitor, True, False}),
- ?line true = test_server:stop_node(N),
+ true = test_server:stop_node(N),
{comment,
"True = "++integer_to_list(True)++"; False = "++integer_to_list(False)}.
@@ -375,161 +332,153 @@ start_remove_monitor_group(Node) ->
Master = self(),
spawn_link(
fun () ->
- Ms = generate(fun () ->
- P = spawn(Node, fun () -> ok end),
- erlang:monitor(process, P)
- end, ?RM_MON_GPROCS),
- Res = lists:foldl(fun (M, {T, F}) ->
- case erlang:demonitor(M, [info]) of
- true ->
- receive
- {'DOWN', M, _, _, _} ->
- exit(down_msg_found)
- after 0 ->
- ok
- end,
- {T+1, F};
- false ->
- receive
- {'DOWN', M, _, _, _} ->
- ok
- after 0 ->
- exit(no_down_msg_found)
- end,
- {T, F+1}
- end
- end,
- {0,0},
- Ms),
- Master ! {rm_mon_res, self(), Res}
+ Ms = generate(fun () ->
+ P = spawn(Node, fun () -> ok end),
+ erlang:monitor(process, P)
+ end, ?RM_MON_GPROCS),
+ Res = lists:foldl(fun (M, {T, F}) ->
+ case erlang:demonitor(M, [info]) of
+ true ->
+ receive
+ {'DOWN', M, _, _, _} ->
+ exit(down_msg_found)
+ after 0 ->
+ ok
+ end,
+ {T+1, F};
+ false ->
+ receive
+ {'DOWN', M, _, _, _} ->
+ ok
+ after 0 ->
+ exit(no_down_msg_found)
+ end,
+ {T, F+1}
+ end
+ end,
+ {0,0},
+ Ms),
+ Master ! {rm_mon_res, self(), Res}
end).
-
-
+
+
%%% Cases for monitor/2
-mon_1(doc) ->
- "Cases for monitor/2";
-mon_1(suite) -> [];
mon_1(Config) when is_list(Config) ->
%% Normal case
- ?line P2 = spawn(timer, sleep, [1]),
- ?line R2 = erlang:monitor(process, P2),
- ?line case expect_down(R2, P2) of
- normal -> ?line ok;
- noproc -> ?line ok;
- BadReason -> ?line ?t:fail({bad_reason, BadReason})
- end,
- ?line {P2A,R2A} = spawn_monitor(timer, sleep, [1]),
- ?line expect_down(R2A, P2A, normal),
+ P2 = spawn(timer, sleep, [1]),
+ R2 = erlang:monitor(process, P2),
+ case expect_down(R2, P2) of
+ normal -> ok;
+ noproc -> ok;
+ BadReason -> ct:fail({bad_reason, BadReason})
+ end,
+ {P2A,R2A} = spawn_monitor(timer, sleep, [1]),
+ expect_down(R2A, P2A, normal),
%% 'DOWN' with other reason
- ?line P3 = spawn(timer, sleep, [100000]),
- ?line R3 = erlang:monitor(process, P3),
- ?line exit(P3, frop),
- ?line expect_down(R3, P3, frop),
- ?line {P3A,R3A} = spawn_monitor(timer, sleep, [100000]),
- ?line exit(P3A, frop),
- ?line expect_down(R3A, P3A, frop),
+ P3 = spawn(timer, sleep, [100000]),
+ R3 = erlang:monitor(process, P3),
+ exit(P3, frop),
+ expect_down(R3, P3, frop),
+ {P3A,R3A} = spawn_monitor(timer, sleep, [100000]),
+ exit(P3A, frop),
+ expect_down(R3A, P3A, frop),
%% Monitor fails because process is dead
- ?line R4 = erlang:monitor(process, P3),
- ?line expect_down(R4, P3, noproc),
+ R4 = erlang:monitor(process, P3),
+ expect_down(R4, P3, noproc),
%% Normal case (named process)
- ?line P5 = start_jeeves(jeeves),
- ?line R5 = erlang:monitor(process, jeeves),
- ?line tell_jeeves(P5, stop),
- ?line expect_down(R5, {jeeves, node()}, normal),
+ P5 = start_jeeves(jeeves),
+ R5 = erlang:monitor(process, jeeves),
+ tell_jeeves(P5, stop),
+ expect_down(R5, {jeeves, node()}, normal),
%% 'DOWN' with other reason and node explicit activation
- ?line P6 = start_jeeves(jeeves),
- ?line R6 = erlang:monitor(process, {jeeves, node()}),
- ?line tell_jeeves(P6, {exit, frop}),
- ?line expect_down(R6, {jeeves, node()}, frop),
+ P6 = start_jeeves(jeeves),
+ R6 = erlang:monitor(process, {jeeves, node()}),
+ tell_jeeves(P6, {exit, frop}),
+ expect_down(R6, {jeeves, node()}, frop),
%% Monitor (named process) fails because process is dead
- ?line R7 = erlang:monitor(process, {jeeves, node()}),
- ?line expect_down(R7, {jeeves, node()}, noproc),
+ R7 = erlang:monitor(process, {jeeves, node()}),
+ expect_down(R7, {jeeves, node()}, noproc),
ok.
-mon_2(doc) ->
- "Distributed cases for monitor/2";
-mon_2(suite) -> [];
+%% Distributed cases for monitor/2
mon_2(Config) when is_list(Config) ->
- ?line {ok, N1} = test_server:start_node(hej1, slave, []),
+ {ok, N1} = test_server:start_node(hej1, slave, []),
%% Normal case
- ?line P2 = spawn(N1, timer, sleep, [4000]),
- ?line R2 = erlang:monitor(process, P2),
- ?line expect_down(R2, P2, normal),
+ P2 = spawn(N1, timer, sleep, [4000]),
+ R2 = erlang:monitor(process, P2),
+ expect_down(R2, P2, normal),
%% 'DOWN' with other reason
- ?line P3 = spawn(N1, timer, sleep, [100000]),
- ?line R3 = erlang:monitor(process, P3),
- ?line exit(P3, frop),
- ?line expect_down(R3, P3, frop),
+ P3 = spawn(N1, timer, sleep, [100000]),
+ R3 = erlang:monitor(process, P3),
+ exit(P3, frop),
+ expect_down(R3, P3, frop),
%% Monitor fails because process is dead
- ?line R4 = erlang:monitor(process, P3),
- ?line expect_down(R4, P3, noproc),
+ R4 = erlang:monitor(process, P3),
+ expect_down(R4, P3, noproc),
%% Other node goes down
- ?line P5 = spawn(N1, timer, sleep, [100000]),
- ?line R5 = erlang:monitor(process, P5),
+ P5 = spawn(N1, timer, sleep, [100000]),
+ R5 = erlang:monitor(process, P5),
- ?line true = test_server:stop_node(N1),
+ true = test_server:stop_node(N1),
- ?line expect_down(R5, P5, noconnection),
+ expect_down(R5, P5, noconnection),
%% Monitor fails because other node is dead
- ?line P6 = spawn(N1, timer, sleep, [100000]),
- ?line R6 = erlang:monitor(process, P6),
- ?line R6_Reason = expect_down(R6, P6),
- ?line true = (R6_Reason == noconnection) orelse (R6_Reason == noproc),
+ P6 = spawn(N1, timer, sleep, [100000]),
+ R6 = erlang:monitor(process, P6),
+ R6_Reason = expect_down(R6, P6),
+ true = (R6_Reason == noconnection) orelse (R6_Reason == noproc),
%% Start a new node that can load code in this module
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?line {ok, N2} = test_server:start_node
- (hej2, slave, [{args, "-pa " ++ PA}]),
+ PA = filename:dirname(code:which(?MODULE)),
+ {ok, N2} = test_server:start_node
+ (hej2, slave, [{args, "-pa " ++ PA}]),
%% Normal case (named process)
- ?line P7 = start_jeeves({jeeves, N2}),
- ?line R7 = erlang:monitor(process, {jeeves, N2}),
- ?line tell_jeeves(P7, stop),
- ?line expect_down(R7, {jeeves, N2}, normal),
+ P7 = start_jeeves({jeeves, N2}),
+ R7 = erlang:monitor(process, {jeeves, N2}),
+ tell_jeeves(P7, stop),
+ expect_down(R7, {jeeves, N2}, normal),
%% 'DOWN' with other reason (named process)
- ?line P8 = start_jeeves({jeeves, N2}),
- ?line R8 = erlang:monitor(process, {jeeves, N2}),
- ?line tell_jeeves(P8, {exit, frop}),
- ?line expect_down(R8, {jeeves, N2}, frop),
+ P8 = start_jeeves({jeeves, N2}),
+ R8 = erlang:monitor(process, {jeeves, N2}),
+ tell_jeeves(P8, {exit, frop}),
+ expect_down(R8, {jeeves, N2}, frop),
%% Monitor (named process) fails because process is dead
- ?line R9 = erlang:monitor(process, {jeeves, N2}),
- ?line expect_down(R9, {jeeves, N2}, noproc),
+ R9 = erlang:monitor(process, {jeeves, N2}),
+ expect_down(R9, {jeeves, N2}, noproc),
%% Other node goes down (named process)
- ?line _P10 = start_jeeves({jeeves, N2}),
- ?line R10 = erlang:monitor(process, {jeeves, N2}),
+ _P10 = start_jeeves({jeeves, N2}),
+ R10 = erlang:monitor(process, {jeeves, N2}),
- ?line true = test_server:stop_node(N2),
+ true = test_server:stop_node(N2),
- ?line expect_down(R10, {jeeves, N2}, noconnection),
+ expect_down(R10, {jeeves, N2}, noconnection),
%% Monitor (named process) fails because other node is dead
- ?line R11 = erlang:monitor(process, {jeeves, N2}),
- ?line expect_down(R11, {jeeves, N2}, noconnection),
+ R11 = erlang:monitor(process, {jeeves, N2}),
+ expect_down(R11, {jeeves, N2}, noconnection),
ok.
%%% Large exit reason. Crashed first attempt to release R5B.
-large_exit(doc) ->
- "Large exit reason";
-large_exit(suite) -> [];
large_exit(Config) when is_list(Config) ->
- ?line f(100),
+ f(100),
ok.
f(0) ->
@@ -539,23 +488,23 @@ f(N) ->
f(N-1).
f() ->
- ?line S0 = {big, tuple, with, [list, 4563784278]},
- ?line S = {S0, term_to_binary(S0)},
- ?line P = spawn(?MODULE, large_exit_sub, [S]),
- ?line R = erlang:monitor(process, P),
- ?line P ! hej,
+ S0 = {big, tuple, with, [list, 4563784278]},
+ S = {S0, term_to_binary(S0)},
+ P = spawn(?MODULE, large_exit_sub, [S]),
+ R = erlang:monitor(process, P),
+ P ! hej,
receive
- {'DOWN', R, process, P, X} ->
- ?line io:format(" -> ~p~n", [X]),
- if
- X == S ->
- ok;
- true ->
- test_server:fail({X, S})
- end;
- Other ->
- ?line io:format(" -> ~p~n", [Other]),
- exit({answer, Other})
+ {'DOWN', R, process, P, X} ->
+ io:format(" -> ~p~n", [X]),
+ if
+ X == S ->
+ ok;
+ true ->
+ ct:fail({X, S})
+ end;
+ Other ->
+ io:format(" -> ~p~n", [Other]),
+ exit({answer, Other})
end.
large_exit_sub(S) ->
@@ -566,105 +515,99 @@ large_exit_sub(S) ->
%%% by using erlang:process_info(self(), monitors)
%%% and erlang:process_info(self(), monitored_by)
-list_cleanup(doc) ->
- "Testing of monitor link list cleanup by using " ++
- "erlang:process_info/2";
-list_cleanup(suite) -> [];
list_cleanup(Config) when is_list(Config) ->
- ?line P0 = self(),
- ?line M = node(),
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?line true = register(master_bertie, self()),
+ P0 = self(),
+ M = node(),
+ PA = filename:dirname(code:which(?MODULE)),
+ true = register(master_bertie, self()),
%% Normal local case, monitor and demonitor
- ?line P1 = start_jeeves(jeeves),
- ?line {[], []} = monitors(),
- ?line expect_jeeves(P1, monitors, {monitors, {[], []}}),
- ?line R1a = erlang:monitor(process, P1),
- ?line {[{process, P1}], []} = monitors(),
- ?line expect_jeeves(P1, monitors, {monitors, {[], [P0]}}),
- ?line true = erlang:demonitor(R1a),
- ?line expect_no_msg(),
- ?line {[], []} = monitors(),
- ?line expect_jeeves(P1, monitors, {monitors, {[], []}}),
+ P1 = start_jeeves(jeeves),
+ {[], []} = monitors(),
+ expect_jeeves(P1, monitors, {monitors, {[], []}}),
+ R1a = erlang:monitor(process, P1),
+ {[{process, P1}], []} = monitors(),
+ expect_jeeves(P1, monitors, {monitors, {[], [P0]}}),
+ true = erlang:demonitor(R1a),
+ expect_no_msg(),
+ {[], []} = monitors(),
+ expect_jeeves(P1, monitors, {monitors, {[], []}}),
%% Remonitor named and try again, now exiting the monitored process
- ?line R1b = erlang:monitor(process, jeeves),
- ?line {[{process, {jeeves, M}}], []} = monitors(),
- ?line expect_jeeves(P1, monitors, {monitors, {[], [P0]}}),
- ?line tell_jeeves(P1, stop),
- ?line expect_down(R1b, {jeeves, node()}, normal),
- ?line {[], []} = monitors(),
+ R1b = erlang:monitor(process, jeeves),
+ {[{process, {jeeves, M}}], []} = monitors(),
+ expect_jeeves(P1, monitors, {monitors, {[], [P0]}}),
+ tell_jeeves(P1, stop),
+ expect_down(R1b, {jeeves, node()}, normal),
+ {[], []} = monitors(),
%% Slightly weird local case - the monitoring process crashes
- ?line P2 = start_jeeves(jeeves),
- ?line {[], []} = monitors(),
- ?line expect_jeeves(P2, monitors, {monitors, {[], []}}),
- ?line {monitor_process, _R2} =
- ask_jeeves(P2, {monitor_process, master_bertie}),
- ?line {[], [P2]} = monitors(),
- ?line expect_jeeves(P2, monitors,
- {monitors, {[{process, {master_bertie, node()}}], []}}),
- ?line tell_jeeves(P2, {exit, frop}),
+ P2 = start_jeeves(jeeves),
+ {[], []} = monitors(),
+ expect_jeeves(P2, monitors, {monitors, {[], []}}),
+ {monitor_process, _R2} =
+ ask_jeeves(P2, {monitor_process, master_bertie}),
+ {[], [P2]} = monitors(),
+ expect_jeeves(P2, monitors,
+ {monitors, {[{process, {master_bertie, node()}}], []}}),
+ tell_jeeves(P2, {exit, frop}),
timer:sleep(2000),
- ?line {[], []} = monitors(),
+ {[], []} = monitors(),
%% Start a new node that can load code in this module
- ?line {ok, J} = test_server:start_node
- (jeeves, slave, [{args, "-pa " ++ PA}]),
+ {ok, J} = test_server:start_node
+ (jeeves, slave, [{args, "-pa " ++ PA}]),
%% Normal remote case, monitor and demonitor
- ?line P3 = start_jeeves({jeeves, J}),
- ?line {[], []} = monitors(),
- ?line expect_jeeves(P3, monitors, {monitors, {[], []}}),
- ?line R3a = erlang:monitor(process, P3),
- ?line {[{process, P3}], []} = monitors(),
- ?line expect_jeeves(P3, monitors, {monitors, {[], [P0]}}),
- ?line true = erlang:demonitor(R3a),
- ?line expect_no_msg(),
- ?line {[], []} = monitors(),
- ?line expect_jeeves(P3, monitors, {monitors, {[], []}}),
+ P3 = start_jeeves({jeeves, J}),
+ {[], []} = monitors(),
+ expect_jeeves(P3, monitors, {monitors, {[], []}}),
+ R3a = erlang:monitor(process, P3),
+ {[{process, P3}], []} = monitors(),
+ expect_jeeves(P3, monitors, {monitors, {[], [P0]}}),
+ true = erlang:demonitor(R3a),
+ expect_no_msg(),
+ {[], []} = monitors(),
+ expect_jeeves(P3, monitors, {monitors, {[], []}}),
%% Remonitor named and try again, now exiting the monitored process
- ?line R3b = erlang:monitor(process, {jeeves, J}),
- ?line {[{process, {jeeves, J}}], []} = monitors(),
- ?line expect_jeeves(P3, monitors, {monitors, {[], [P0]}}),
- ?line tell_jeeves(P3, stop),
- ?line expect_down(R3b, {jeeves, J}, normal),
- ?line {[], []} = monitors(),
+ R3b = erlang:monitor(process, {jeeves, J}),
+ {[{process, {jeeves, J}}], []} = monitors(),
+ expect_jeeves(P3, monitors, {monitors, {[], [P0]}}),
+ tell_jeeves(P3, stop),
+ expect_down(R3b, {jeeves, J}, normal),
+ {[], []} = monitors(),
%% Slightly weird remote case - the monitoring process crashes
- ?line P4 = start_jeeves({jeeves, J}),
- ?line {[], []} = monitors(),
- ?line expect_jeeves(P4, monitors, {monitors, {[], []}}),
- ?line {monitor_process, _R4} =
- ask_jeeves(P4, {monitor_process, {master_bertie, M}}),
- ?line {[], [P4]} = monitors(),
- ?line expect_jeeves(P4, monitors,
- {monitors, {[{process, {master_bertie, M}}], []}} ),
- ?line tell_jeeves(P4, {exit, frop}),
+ P4 = start_jeeves({jeeves, J}),
+ {[], []} = monitors(),
+ expect_jeeves(P4, monitors, {monitors, {[], []}}),
+ {monitor_process, _R4} =
+ ask_jeeves(P4, {monitor_process, {master_bertie, M}}),
+ {[], [P4]} = monitors(),
+ expect_jeeves(P4, monitors,
+ {monitors, {[{process, {master_bertie, M}}], []}} ),
+ tell_jeeves(P4, {exit, frop}),
timer:sleep(2000),
- ?line {[], []} = monitors(),
-
+ {[], []} = monitors(),
+
%% Now, the monitoring remote node crashes
- ?line P5 = start_jeeves({jeeves, J}),
- ?line {[], []} = monitors(),
- ?line expect_jeeves(P5, monitors, {monitors, {[], []}}),
- ?line {monitor_process, _R5} =
- ask_jeeves(P5, {monitor_process, P0}),
- ?line {[], [P5]} = monitors(),
- ?line expect_jeeves(P5, monitors,
- {monitors, {[{process, P0}], []}} ),
- ?line test_server:stop_node(J),
+ P5 = start_jeeves({jeeves, J}),
+ {[], []} = monitors(),
+ expect_jeeves(P5, monitors, {monitors, {[], []}}),
+ {monitor_process, _R5} =
+ ask_jeeves(P5, {monitor_process, P0}),
+ {[], [P5]} = monitors(),
+ expect_jeeves(P5, monitors,
+ {monitors, {[{process, P0}], []}} ),
+ test_server:stop_node(J),
timer:sleep(4000),
- ?line {[], []} = monitors(),
-
- ?line true = unregister(master_bertie),
+ {[], []} = monitors(),
+
+ true = unregister(master_bertie),
ok.
-
+
%%% Mixed internal and external monitors
-mixer(doc) ->
- "Test mixing of internal and external monitors.";
mixer(Config) when is_list(Config) ->
PA = filename:dirname(code:which(?MODULE)),
NN = [j0,j1,j2],
@@ -748,115 +691,112 @@ mixer(Config) when is_list(Config) ->
[test_server:stop_node(K) || K <- NL0],
ok.
-named_down(doc) -> ["Test that DOWN message for a named monitor isn't"
- " delivered until name has been unregistered"];
-named_down(suite) -> [];
+%% Test that DOWN message for a named monitor isn't
+%% delivered until name has been unregistered
named_down(Config) when is_list(Config) ->
- ?line Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-named_down-"
- ++ integer_to_list(erlang:system_time(seconds))
- ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))),
- ?line Prio = process_flag(priority,high),
+ Name = list_to_atom(atom_to_list(?MODULE)
+ ++ "-named_down-"
+ ++ integer_to_list(erlang:system_time(seconds))
+ ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))),
+ Prio = process_flag(priority,high),
%% Spawn a bunch of high prio cpu bound processes to prevent
%% normal prio processes from terminating during the next
%% 500 ms...
- ?line Self = self(),
- ?line spawn_opt(fun () ->
- WFun = fun
- (F, hej) -> F(F, hopp);
- (F, hopp) -> F(F, hej)
- end,
- NoSchedulers = erlang:system_info(schedulers_online),
- lists:foreach(fun (_) ->
- spawn_opt(fun () ->
- WFun(WFun,
- hej)
- end,
- [{priority,high},
- link])
- end,
- lists:seq(1, NoSchedulers)),
- receive after 500 -> ok end,
- unlink(Self),
- exit(bang)
- end,
- [{priority,high}, link]),
- ?line NamedProc = spawn_link(fun () ->
- receive after infinity -> ok end
- end),
- ?line true = register(Name, NamedProc),
- ?line unlink(NamedProc),
- ?line exit(NamedProc, bang),
- ?line Mon = erlang:monitor(process, Name),
- ?line receive {'DOWN',Mon, _, _, _} -> ok end,
- ?line true = register(Name, self()),
- ?line true = unregister(Name),
- ?line process_flag(priority,Prio),
+ Self = self(),
+ spawn_opt(fun () ->
+ WFun = fun
+ (F, hej) -> F(F, hopp);
+(F, hopp) -> F(F, hej)
+ end,
+ NoSchedulers = erlang:system_info(schedulers_online),
+ lists:foreach(fun (_) ->
+ spawn_opt(fun () ->
+ WFun(WFun,
+ hej)
+ end,
+ [{priority,high},
+ link])
+ end,
+ lists:seq(1, NoSchedulers)),
+ receive after 500 -> ok end,
+ unlink(Self),
+ exit(bang)
+ end,
+ [{priority,high}, link]),
+ NamedProc = spawn_link(fun () ->
+ receive after infinity -> ok end
+ end),
+ true = register(Name, NamedProc),
+ unlink(NamedProc),
+ exit(NamedProc, bang),
+ Mon = erlang:monitor(process, Name),
+ receive {'DOWN',Mon, _, _, _} -> ok end,
+ true = register(Name, self()),
+ true = unregister(Name),
+ process_flag(priority,Prio),
ok.
-otp_5827(doc) -> [];
-otp_5827(suite) -> [];
otp_5827(Config) when is_list(Config) ->
%% Make a pid with the same nodename but with another creation
- ?line [CreEnd | RPTail]
- = lists:reverse(binary_to_list(term_to_binary(self()))),
- ?line NewCreEnd = case CreEnd of
- 0 -> 1;
- 1 -> 2;
- _ -> CreEnd - 1
- end,
- ?line OtherCreationPid
- = binary_to_term(list_to_binary(lists:reverse([NewCreEnd | RPTail]))),
+ [CreEnd | RPTail]
+ = lists:reverse(binary_to_list(term_to_binary(self()))),
+ NewCreEnd = case CreEnd of
+ 0 -> 1;
+ 1 -> 2;
+ _ -> CreEnd - 1
+ end,
+ OtherCreationPid
+ = binary_to_term(list_to_binary(lists:reverse([NewCreEnd | RPTail]))),
%% If the bug is present erlang:monitor(process, OtherCreationPid)
%% will hang...
- ?line Parent = self(),
- ?line Ok = make_ref(),
- ?line spawn(fun () ->
- Mon = erlang:monitor(process, OtherCreationPid),
- % Should get the DOWN message right away
- receive
- {'DOWN', Mon, process, OtherCreationPid, noproc} ->
- Parent ! Ok
- end
- end),
- ?line receive
- Ok ->
- ?line ok
- after 1000 ->
- ?line ?t:fail("erlang:monitor/2 hangs")
- end.
+ Parent = self(),
+ Ok = make_ref(),
+ spawn(fun () ->
+ Mon = erlang:monitor(process, OtherCreationPid),
+ % Should get the DOWN message right away
+ receive
+ {'DOWN', Mon, process, OtherCreationPid, noproc} ->
+ Parent ! Ok
+ end
+ end),
+ receive
+ Ok ->
+ ok
+ after 1000 ->
+ ct:fail("erlang:monitor/2 hangs")
+ end.
monitor_time_offset(Config) when is_list(Config) ->
{ok, Node} = start_node(Config, "+C single_time_warp"),
Me = self(),
PMs = lists:map(fun (_) ->
- Pid = spawn(Node,
- fun () ->
- check_monitor_time_offset(Me)
- end),
- {Pid, erlang:monitor(process, Pid)}
- end,
- lists:seq(1, 100)),
+ Pid = spawn(Node,
+ fun () ->
+ check_monitor_time_offset(Me)
+ end),
+ {Pid, erlang:monitor(process, Pid)}
+ end,
+ lists:seq(1, 100)),
lists:foreach(fun ({P, _M}) ->
- P ! check_no_change_message
- end, PMs),
+ P ! check_no_change_message
+ end, PMs),
lists:foreach(fun ({P, M}) ->
- receive
- {no_change_message_received, P} ->
- ok;
- {'DOWN', M, process, P, Reason} ->
- ?t:fail(Reason)
- end
- end, PMs),
+ receive
+ {no_change_message_received, P} ->
+ ok;
+ {'DOWN', M, process, P, Reason} ->
+ ct:fail(Reason)
+ end
+ end, PMs),
preliminary = rpc:call(Node, erlang, system_flag, [time_offset, finalize]),
lists:foreach(fun ({P, M}) ->
- receive
- {change_messages_received, P} ->
- erlang:demonitor(M, [flush]);
- {'DOWN', M, process, P, Reason} ->
- ?t:fail(Reason)
- end
- end, PMs),
+ receive
+ {change_messages_received, P} ->
+ erlang:demonitor(M, [flush]);
+ {'DOWN', M, process, P, Reason} ->
+ ct:fail(Reason)
+ end
+ end, PMs),
stop_node(Node),
ok.
@@ -867,42 +807,42 @@ check_monitor_time_offset(Leader) ->
Mon4 = erlang:monitor(time_offset, clock_service),
erlang:demonitor(Mon2, [flush]),
-
+
Mon5 = erlang:monitor(time_offset, clock_service),
Mon6 = erlang:monitor(time_offset, clock_service),
Mon7 = erlang:monitor(time_offset, clock_service),
receive check_no_change_message -> ok end,
receive
- {'CHANGE', _, time_offset, clock_service, _} ->
- exit(unexpected_change_message_received)
+ {'CHANGE', _, time_offset, clock_service, _} ->
+ exit(unexpected_change_message_received)
after 0 ->
- Leader ! {no_change_message_received, self()}
+ Leader ! {no_change_message_received, self()}
end,
receive after 100 -> ok end,
erlang:demonitor(Mon4, [flush]),
receive
- {'CHANGE', Mon3, time_offset, clock_service, _} ->
- ok
+ {'CHANGE', Mon3, time_offset, clock_service, _} ->
+ ok
end,
receive
- {'CHANGE', Mon6, time_offset, clock_service, _} ->
- ok
+ {'CHANGE', Mon6, time_offset, clock_service, _} ->
+ ok
end,
erlang:demonitor(Mon5, [flush]),
receive
- {'CHANGE', Mon7, time_offset, clock_service, _} ->
- ok
+ {'CHANGE', Mon7, time_offset, clock_service, _} ->
+ ok
end,
receive
- {'CHANGE', Mon1, time_offset, clock_service, _} ->
- ok
+ {'CHANGE', Mon1, time_offset, clock_service, _} ->
+ ok
end,
receive
- {'CHANGE', _, time_offset, clock_service, _} ->
- exit(unexpected_change_message_received)
+ {'CHANGE', _, time_offset, clock_service, _} ->
+ exit(unexpected_change_message_received)
after 1000 ->
- ok
+ ok
end,
Leader ! {change_messages_received, self()}.
@@ -916,17 +856,17 @@ wait_for_m(Monitors, MonitoredBy, N) ->
{monitors,M0} = process_info(self(),monitors),
{monitored_by,MB0} = process_info(self(),monitored_by),
case lists:sort(M0) of
- Monitors ->
- case lists:sort(MB0) of
- MonitoredBy ->
- ok;
- _ ->
- receive after 100 -> ok end,
- wait_for_m(Monitors,MonitoredBy,N-1)
- end;
- _ ->
- receive after 100 -> ok end,
- wait_for_m(Monitors,MonitoredBy,N-1)
+ Monitors ->
+ case lists:sort(MB0) of
+ MonitoredBy ->
+ ok;
+ _ ->
+ receive after 100 -> ok end,
+ wait_for_m(Monitors,MonitoredBy,N-1)
+ end;
+ _ ->
+ receive after 100 -> ok end,
+ wait_for_m(Monitors,MonitoredBy,N-1)
end.
% All permutations of a list...
@@ -950,32 +890,32 @@ jeeves(Parent, Name, Ref)
when is_pid(Parent), (is_atom(Name) or (Name =:= [])), is_reference(Ref) ->
%%io:format("monitor_SUITE:jeeves(~p, ~p)~n", [Parent, Name]),
case Name of
- Atom when is_atom(Atom) ->
- register(Name, self());
- [] ->
- ok
+ Atom when is_atom(Atom) ->
+ register(Name, self());
+ [] ->
+ ok
end,
Parent ! {self(), Ref},
jeeves_loop(Parent).
jeeves_loop(Parent) ->
receive
- {Parent, monitors} ->
- Parent ! {self(), {monitors, monitors()}},
- jeeves_loop(Parent);
- {Parent, {monitor_process, P}} ->
- Parent ! {self(), {monitor_process,
- catch erlang:monitor(process, P) }},
- jeeves_loop(Parent);
- {Parent, {demonitor, Ref}} ->
- Parent ! {self(), {demonitor, catch erlang:demonitor(Ref)}},
- jeeves_loop(Parent);
- {Parent, stop} ->
- ok;
- {Parent, {exit, Reason}} ->
- exit(Reason);
- Other ->
- io:format("~p:jeeves_loop received ~p~n", [?MODULE, Other])
+ {Parent, monitors} ->
+ Parent ! {self(), {monitors, monitors()}},
+ jeeves_loop(Parent);
+ {Parent, {monitor_process, P}} ->
+ Parent ! {self(), {monitor_process,
+ catch erlang:monitor(process, P) }},
+ jeeves_loop(Parent);
+ {Parent, {demonitor, Ref}} ->
+ Parent ! {self(), {demonitor, catch erlang:demonitor(Ref)}},
+ jeeves_loop(Parent);
+ {Parent, stop} ->
+ ok;
+ {Parent, {exit, Reason}} ->
+ exit(Reason);
+ Other ->
+ io:format("~p:jeeves_loop received ~p~n", [?MODULE, Other])
end.
@@ -985,10 +925,10 @@ start_jeeves({Name, Node})
Ref = make_ref(),
Pid = spawn(Node, fun() -> jeeves(Parent, Name, Ref) end),
receive
- {Pid, Ref} ->
- ok;
- Other ->
- test_server:fail({rec, Other})
+ {Pid, Ref} ->
+ ok;
+ Other ->
+ ct:fail({rec, Other})
end,
Pid;
start_jeeves(Name) when is_atom(Name) ->
@@ -1002,20 +942,20 @@ tell_jeeves(Pid, What) when is_pid(Pid) ->
ask_jeeves(Pid, Request) when is_pid(Pid) ->
Pid ! {self(), Request},
receive
- {Pid, Response} ->
- Response;
- Other ->
- test_server:fail({rec, Other})
+ {Pid, Response} ->
+ Response;
+ Other ->
+ ct:fail({rec, Other})
end.
expect_jeeves(Pid, Request, Response) when is_pid(Pid) ->
Pid ! {self(), Request},
receive
- {Pid, Response} ->
- ok;
- Other ->
- test_server:fail({rec, Other})
+ {Pid, Response} ->
+ ok;
+ Other ->
+ ct:fail({rec, Other})
end.
@@ -1036,20 +976,20 @@ start_node(Config) ->
start_node(Config, "").
start_node(Config, Args) ->
- TestCase = ?config(testcase, Config),
+ TestCase = proplists:get_value(testcase, Config),
PA = filename:dirname(code:which(?MODULE)),
ESTime = erlang:monotonic_time(1) + erlang:time_offset(1),
Unique = erlang:unique_integer([positive]),
Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(TestCase)
- ++ "-"
- ++ integer_to_list(ESTime)
- ++ "-"
- ++ integer_to_list(Unique)),
+ ++ "-"
+ ++ atom_to_list(TestCase)
+ ++ "-"
+ ++ integer_to_list(ESTime)
+ ++ "-"
+ ++ integer_to_list(Unique)),
test_server:start_node(Name,
- slave,
- [{args, "-pa " ++ PA ++ " " ++ Args}]).
+ slave,
+ [{args, "-pa " ++ PA ++ " " ++ Args}]).
stop_node(Node) ->
test_server:stop_node(Node).
diff --git a/erts/emulator/test/mtx_SUITE.erl b/erts/emulator/test/mtx_SUITE.erl
index 87dace4721..a17b11f3bf 100644
--- a/erts/emulator/test/mtx_SUITE.erl
+++ b/erts/emulator/test/mtx_SUITE.erl
@@ -29,9 +29,8 @@
-include_lib("common_test/include/ct.hrl").
--export([all/0,suite/0,groups/0,
- init_per_group/2,end_per_group/2, init_per_suite/1,
- end_per_suite/1, init_per_testcase/2, end_per_testcase/2]).
+-export([all/0,suite/0, init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2]).
-export([long_rwlock/1,
hammer_ets_rwlock/1,
@@ -56,8 +55,30 @@
hammer_sched_freqread_tryrwlock/1,
hammer_sched_freqread_tryrwlock_check/1]).
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 15}}].
+
+all() ->
+ [long_rwlock, hammer_rwlock_check, hammer_rwlock,
+ hammer_tryrwlock_check, hammer_tryrwlock,
+ hammer_ets_rwlock, hammer_sched_long_rwlock_check,
+ hammer_sched_long_rwlock,
+ hammer_sched_long_freqread_rwlock_check,
+ hammer_sched_long_freqread_rwlock,
+ hammer_sched_long_tryrwlock_check,
+ hammer_sched_long_tryrwlock,
+ hammer_sched_long_freqread_tryrwlock_check,
+ hammer_sched_long_freqread_tryrwlock,
+ hammer_sched_rwlock_check, hammer_sched_rwlock,
+ hammer_sched_freqread_rwlock_check,
+ hammer_sched_freqread_rwlock,
+ hammer_sched_tryrwlock_check, hammer_sched_tryrwlock,
+ hammer_sched_freqread_tryrwlock_check,
+ hammer_sched_freqread_tryrwlock].
+
init_per_suite(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
Lib = filename:join([DataDir, atom_to_list(?MODULE)]),
case {erlang:load_nif(Lib, none),erlang:system_info(threads)} of
{{error,_},false} ->
@@ -71,15 +92,13 @@ end_per_suite(Config) when is_list(Config) ->
Config.
init_per_testcase(_Case, Config) ->
- Dog = ?t:timetrap(?t:minutes(15)),
%% Wait for deallocations to complete since we measure
%% runtime in test cases.
wait_deallocations(),
- [{watchdog, Dog}|Config].
+ Config.
end_per_testcase(_Func, Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
+ ok.
wait_deallocations() ->
try
@@ -90,45 +109,15 @@ wait_deallocations() ->
wait_deallocations()
end.
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [long_rwlock, hammer_rwlock_check, hammer_rwlock,
- hammer_tryrwlock_check, hammer_tryrwlock,
- hammer_ets_rwlock, hammer_sched_long_rwlock_check,
- hammer_sched_long_rwlock,
- hammer_sched_long_freqread_rwlock_check,
- hammer_sched_long_freqread_rwlock,
- hammer_sched_long_tryrwlock_check,
- hammer_sched_long_tryrwlock,
- hammer_sched_long_freqread_tryrwlock_check,
- hammer_sched_long_freqread_tryrwlock,
- hammer_sched_rwlock_check, hammer_sched_rwlock,
- hammer_sched_freqread_rwlock_check,
- hammer_sched_freqread_rwlock,
- hammer_sched_tryrwlock_check, hammer_sched_tryrwlock,
- hammer_sched_freqread_tryrwlock_check,
- hammer_sched_freqread_tryrwlock].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
long_rwlock(Config) when is_list(Config) ->
statistics(runtime),
LLRes = long_rw_test(),
{_, RunTime} = statistics(runtime),
%% A very short run time is expected, since
%% threads in the test mostly wait
- ?t:format("RunTime=~p~n", [RunTime]),
- ?line true = RunTime < 400,
- ?line RunTimeStr = "Run-time during test was "++integer_to_list(RunTime)++" ms.",
+ io:format("RunTime=~p~n", [RunTime]),
+ true = RunTime < 400,
+ RunTimeStr = "Run-time during test was "++integer_to_list(RunTime)++" ms.",
case LLRes of
ok ->
{comment, RunTimeStr};
@@ -198,100 +187,100 @@ hammer_sched_long_freqread_tryrwlock_check(Config) when is_list(Config) ->
hammer_sched_rwlock_test(FreqRead, LockCheck, Blocking, WaitLocked, WaitUnlocked) ->
case create_rwlock(FreqRead, LockCheck) of
- enotsup ->
- {skipped, "Not supported."};
- RWLock ->
- Onln = erlang:system_info(schedulers_online),
- NWPs = case Onln div 3 of
- 1 -> case Onln < 4 of
- true -> 1;
- false -> 2
- end;
- X -> X
- end,
- NRPs = Onln - NWPs,
- NoLockOps = ((((50000000 div Onln)
- div case {Blocking, WaitLocked} of
- {false, 0} -> 1;
- _ -> 10
- end)
- div (case WaitLocked == 0 of
- true -> 1;
- false -> WaitLocked*250
- end))
- div handicap()),
- ?t:format("NoLockOps=~p~n", [NoLockOps]),
- Sleep = case Blocking of
- true -> NoLockOps;
- false -> NoLockOps div 10
- end,
- WPs = lists:map(
- fun (Sched) ->
- spawn_opt(
- fun () ->
- io:format("Writer on scheduler ~p.~n",
- [Sched]),
- Sched = erlang:system_info(scheduler_id),
- receive go -> gone end,
- hammer_sched_rwlock_proc(RWLock,
- Blocking,
- true,
- WaitLocked,
- WaitUnlocked,
- NoLockOps,
- Sleep),
- Sched = erlang:system_info(scheduler_id)
- end,
- [link, {scheduler, Sched}])
- end,
- lists:seq(1, NWPs)),
- RPs = lists:map(
- fun (Sched) ->
- spawn_opt(
- fun () ->
- io:format("Reader on scheduler ~p.~n",
- [Sched]),
- Sched = erlang:system_info(scheduler_id),
- receive go -> gone end,
- hammer_sched_rwlock_proc(RWLock,
- Blocking,
- false,
- WaitLocked,
- WaitUnlocked,
- NoLockOps,
- Sleep),
- Sched = erlang:system_info(scheduler_id)
- end,
- [link, {scheduler, Sched}])
- end,
- lists:seq(NWPs + 1, NWPs + NRPs)),
- Procs = WPs ++ RPs,
- case {Blocking, WaitLocked} of
- {_, 0} -> ok;
- {false, _} -> ok;
- _ -> statistics(runtime)
- end,
- lists:foreach(fun (P) -> P ! go end, Procs),
- lists:foreach(fun (P) ->
- M = erlang:monitor(process, P),
- receive
- {'DOWN', M, process, P, _} ->
- ok
- end
- end,
- Procs),
- case {Blocking, WaitLocked} of
- {_, 0} -> ok;
- {false, _} -> ok;
- _ ->
- {_, RunTime} = statistics(runtime),
- ?t:format("RunTime=~p~n", [RunTime]),
- ?line true = RunTime < 700,
- {comment,
- "Run-time during test was "
- ++ integer_to_list(RunTime)
- ++ " ms."}
- end
+ enotsup ->
+ {skipped, "Not supported."};
+ RWLock ->
+ Onln = erlang:system_info(schedulers_online),
+ NWPs = case Onln div 3 of
+ 1 -> case Onln < 4 of
+ true -> 1;
+ false -> 2
+ end;
+ X -> X
+ end,
+ NRPs = Onln - NWPs,
+ NoLockOps = ((((50000000 div Onln)
+ div case {Blocking, WaitLocked} of
+ {false, 0} -> 1;
+ _ -> 10
+ end)
+ div (case WaitLocked == 0 of
+ true -> 1;
+ false -> WaitLocked*250
+ end))
+ div handicap()),
+ io:format("NoLockOps=~p~n", [NoLockOps]),
+ Sleep = case Blocking of
+ true -> NoLockOps;
+ false -> NoLockOps div 10
+ end,
+ WPs = lists:map(
+ fun (Sched) ->
+ spawn_opt(
+ fun () ->
+ io:format("Writer on scheduler ~p.~n",
+ [Sched]),
+ Sched = erlang:system_info(scheduler_id),
+ receive go -> gone end,
+ hammer_sched_rwlock_proc(RWLock,
+ Blocking,
+ true,
+ WaitLocked,
+ WaitUnlocked,
+ NoLockOps,
+ Sleep),
+ Sched = erlang:system_info(scheduler_id)
+ end,
+ [link, {scheduler, Sched}])
+ end,
+ lists:seq(1, NWPs)),
+ RPs = lists:map(
+ fun (Sched) ->
+ spawn_opt(
+ fun () ->
+ io:format("Reader on scheduler ~p.~n",
+ [Sched]),
+ Sched = erlang:system_info(scheduler_id),
+ receive go -> gone end,
+ hammer_sched_rwlock_proc(RWLock,
+ Blocking,
+ false,
+ WaitLocked,
+ WaitUnlocked,
+ NoLockOps,
+ Sleep),
+ Sched = erlang:system_info(scheduler_id)
+ end,
+ [link, {scheduler, Sched}])
+ end,
+ lists:seq(NWPs + 1, NWPs + NRPs)),
+ Procs = WPs ++ RPs,
+ case {Blocking, WaitLocked} of
+ {_, 0} -> ok;
+ {false, _} -> ok;
+ _ -> statistics(runtime)
+ end,
+ lists:foreach(fun (P) -> P ! go end, Procs),
+ lists:foreach(fun (P) ->
+ M = erlang:monitor(process, P),
+ receive
+ {'DOWN', M, process, P, _} ->
+ ok
+ end
+ end,
+ Procs),
+ case {Blocking, WaitLocked} of
+ {_, 0} -> ok;
+ {false, _} -> ok;
+ _ ->
+ {_, RunTime} = statistics(runtime),
+ io:format("RunTime=~p~n", [RunTime]),
+ true = RunTime < 700,
+ {comment,
+ "Run-time during test was "
+ ++ integer_to_list(RunTime)
+ ++ " ms."}
+ end
end.
hammer_sched_rwlock_proc(_RWLock,
@@ -343,9 +332,9 @@ hammer_ets_rwlock(Config) when is_list(Config) ->
3 -> {2000, 50};
_ -> {200, 50}
end,
- ?t:format("Procs=~p~nOps=~p~n", [Procs, Ops]),
+ io:format("Procs=~p~nOps=~p~n", [Procs, Ops]),
lists:foreach(fun (XOpts) ->
- ?t:format("Running with extra opts: ~p", [XOpts]),
+ io:format("Running with extra opts: ~p", [XOpts]),
hammer_ets_rwlock_test(XOpts, true, 2, Ops,
Procs, false)
end,
@@ -408,65 +397,65 @@ hammer_ets_rwlock_init(_T, _N) ->
hammer_ets_rwlock_test(XOpts, UW, C, N, NP, SC) ->
receive after 100 -> ok end,
{TP, TM} = spawn_monitor(
- fun () ->
- _L = repeat_list(
- fun () ->
- Caller = self(),
- T = fun () ->
- Parent = self(),
- hammer_ets_rwlock_put_data(),
- T=ets:new(x, [public | XOpts]),
- hammer_ets_rwlock_init(T, 0),
- Ps0 = repeat_list(
- fun () ->
- spawn_link(
- fun () ->
- hammer_ets_rwlock_put_data(),
- receive go -> ok end,
- hammer_ets_rwlock_ops(T, UW, N, C, C, N),
- Parent ! {done, self()},
- receive after infinity -> ok end
- end)
- end,
- NP - case SC of
- false -> 0;
- _ -> 1
- end),
- Ps = case SC of
- false -> Ps0;
- _ -> [spawn_link(fun () ->
- hammer_ets_rwlock_put_data(),
- receive go -> ok end,
- hammer_ets_rwlock_ops(T, UW, N, SC, SC, N),
- Parent ! {done, self()},
- receive after infinity -> ok end
- end) | Ps0]
- end,
- Start = erlang:monotonic_time(),
- lists:foreach(fun (P) -> P ! go end, Ps),
- lists:foreach(fun (P) -> receive {done, P} -> ok end end, Ps),
- Stop = erlang:monotonic_time(),
- lists:foreach(fun (P) ->
- unlink(P),
- exit(P, bang),
- M = erlang:monitor(process, P),
- receive
- {'DOWN', M, process, P, _} -> ok
- end
- end, Ps),
- Res = (Stop-Start)/erlang:convert_time_unit(1,seconds,native),
- Caller ! {?MODULE, self(), Res}
- end,
- TP = spawn_link(T),
- receive
- {?MODULE, TP, Res} ->
- Res
- end
- end,
- ?HAMMER_ETS_RWLOCK_REPEAT_TIMES)
- end),
+ fun () ->
+ _L = repeat_list(
+ fun () ->
+ Caller = self(),
+ T = fun () ->
+ Parent = self(),
+ hammer_ets_rwlock_put_data(),
+ T=ets:new(x, [public | XOpts]),
+ hammer_ets_rwlock_init(T, 0),
+ Ps0 = repeat_list(
+ fun () ->
+ spawn_link(
+ fun () ->
+ hammer_ets_rwlock_put_data(),
+ receive go -> ok end,
+ hammer_ets_rwlock_ops(T, UW, N, C, C, N),
+ Parent ! {done, self()},
+ receive after infinity -> ok end
+ end)
+ end,
+ NP - case SC of
+ false -> 0;
+ _ -> 1
+ end),
+ Ps = case SC of
+ false -> Ps0;
+ _ -> [spawn_link(fun () ->
+ hammer_ets_rwlock_put_data(),
+ receive go -> ok end,
+ hammer_ets_rwlock_ops(T, UW, N, SC, SC, N),
+ Parent ! {done, self()},
+ receive after infinity -> ok end
+ end) | Ps0]
+ end,
+ Start = erlang:monotonic_time(),
+ lists:foreach(fun (P) -> P ! go end, Ps),
+ lists:foreach(fun (P) -> receive {done, P} -> ok end end, Ps),
+ Stop = erlang:monotonic_time(),
+ lists:foreach(fun (P) ->
+ unlink(P),
+ exit(P, bang),
+ M = erlang:monitor(process, P),
+ receive
+ {'DOWN', M, process, P, _} -> ok
+ end
+ end, Ps),
+ Res = (Stop-Start)/erlang:convert_time_unit(1,seconds,native),
+ Caller ! {?MODULE, self(), Res}
+ end,
+ TP = spawn_link(T),
+ receive
+ {?MODULE, TP, Res} ->
+ Res
+ end
+ end,
+ ?HAMMER_ETS_RWLOCK_REPEAT_TIMES)
+ end),
receive
- {'DOWN', TM, process, TP, _} -> ok
+ {'DOWN', TM, process, TP, _} -> ok
end.
repeat_list(Fun, N) ->
@@ -480,18 +469,17 @@ repeat_list(Fun, N, Acc) ->
handicap() ->
X0 = case catch (erlang:system_info(logical_processors_available) >=
- erlang:system_info(schedulers_online)) of
- true -> 1;
- _ -> 2
- end,
+ erlang:system_info(schedulers_online)) of
+ true -> 1;
+ _ -> 2
+ end,
case erlang:system_info(build_type) of
- opt ->
- X0;
- ReallySlow when ReallySlow == debug;
- ReallySlow == valgrind;
- ReallySlow == purify ->
- X0*3;
- _Slow ->
- X0*2
+ opt ->
+ X0;
+ ReallySlow when ReallySlow == debug;
+ ReallySlow == valgrind;
+ ReallySlow == purify ->
+ X0*3;
+ _Slow ->
+ X0*2
end.
-
diff --git a/erts/emulator/test/multi_load_SUITE.erl b/erts/emulator/test/multi_load_SUITE.erl
new file mode 100644
index 0000000000..784b239116
--- /dev/null
+++ b/erts/emulator/test/multi_load_SUITE.erl
@@ -0,0 +1,196 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-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(multi_load_SUITE).
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2,
+ many/1,on_load/1,errors/1]).
+
+-include_lib("common_test/include/ct.hrl").
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [many,on_load,errors].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+many(_Config) ->
+ Ms = make_modules(100, fun many_module/1),
+
+ io:put_chars("Light load\n"
+ "=========="),
+ many_measure(Ms),
+
+ _ = [spawn_link(fun many_worker/0) || _ <- lists:seq(1, 8)],
+ erlang:yield(),
+ io:put_chars("Heavy load\n"
+ "=========="),
+ many_measure(Ms),
+
+ ok.
+
+many_module(M) ->
+ ["-module("++M++").",
+ "-compile(export_all).",
+ "f1() -> ok.",
+ "f2() -> ok.",
+ "f3() -> ok.",
+ "f4() -> ok."].
+
+many_measure(Ms) ->
+ many_purge(Ms),
+ MsPrep1 = prepare_modules(Ms),
+ Us1 = ms(fun() -> many_load_seq(MsPrep1) end),
+ many_try_call(Ms),
+ many_purge(Ms),
+ MsPrep2 = prepare_modules(Ms),
+ Us2 = ms(fun() -> many_load_par(MsPrep2) end),
+ many_try_call(Ms),
+ io:format("# modules: ~9w\n"
+ "Sequential: ~9w µs\n"
+ "Parallel: ~9w µs\n"
+ "Ratio: ~9w\n",
+ [length(Ms),Us1,Us2,round(Us1/Us2)]),
+ ok.
+
+many_load_seq(Ms) ->
+ [erlang:finish_loading([M]) || M <- Ms],
+ ok.
+
+many_load_par(Ms) ->
+ erlang:finish_loading(Ms).
+
+many_purge(Ms) ->
+ _ = [catch erlang:purge_module(M) || {M,_} <- Ms],
+ ok.
+
+many_try_call(Ms) ->
+ _ = [begin
+ ok = M:f1(),
+ ok = M:f2(),
+ ok = M:f3(),
+ ok = M:f4()
+ end || {M,_} <- Ms],
+ ok.
+
+many_worker() ->
+ many_worker(lists:seq(1, 100)).
+
+many_worker(L) ->
+ N0 = length(L),
+ N1 = N0 * N0 * N0,
+ N2 = N1 div (N0 * N0),
+ N3 = N2 + 10,
+ _ = N3 - 10,
+ many_worker(L).
+
+
+on_load(_Config) ->
+ On = make_modules(2, fun on_load_module/1),
+ OnPrep = prepare_modules(On),
+ {'EXIT',{system_limit,_}} = (catch erlang:finish_loading(OnPrep)),
+
+ Normal = make_modules(1, fun on_load_normal/1),
+ Mixed = Normal ++ tl(On),
+ MixedPrep = prepare_modules(Mixed),
+ {'EXIT',{system_limit,_}} = (catch erlang:finish_loading(MixedPrep)),
+
+ [false,true] = [erlang:has_prepared_code_on_load(Code) ||
+ Code <- MixedPrep],
+ {'EXIT',{badarg,_}} = (catch erlang:has_prepared_code_on_load(<<1,2,3>>)),
+ Magic = ets:match_spec_compile([{'_',[true],['$_']}]),
+ {'EXIT',{badarg,_}} = (catch erlang:has_prepared_code_on_load(Magic)),
+
+ SingleOnPrep = tl(OnPrep),
+ {on_load,[OnLoadMod]} = erlang:finish_loading(SingleOnPrep),
+ ok = erlang:call_on_load_function(OnLoadMod),
+
+ ok.
+
+on_load_module(M) ->
+ ["-module("++M++").",
+ "-on_load(f/0).",
+ "f() -> ok."].
+
+on_load_normal(M) ->
+ ["-module("++M++")."].
+
+
+errors(_Config) ->
+ finish_loading_badarg(x),
+ finish_loading_badarg([x|y]),
+ finish_loading_badarg([x]),
+ finish_loading_badarg([<<>>]),
+
+ Mods = make_modules(2, fun errors_module/1),
+ Ms = lists:sort([M || {M,_} <- Mods]),
+ Prep = prepare_modules(Mods),
+ {duplicated,Dups} = erlang:finish_loading(Prep ++ Prep),
+ Ms = lists:sort(Dups),
+ ok.
+
+finish_loading_badarg(Arg) ->
+ {'EXIT',{badarg,[{erlang,finish_loading,[Arg],_}|_]}} =
+ (catch erlang:finish_loading(Arg)).
+
+errors_module(M) ->
+ ["-module("++M++").",
+ "-export([f/0]).",
+ "f() -> ok."].
+
+%%%
+%%% Common utilities
+%%%
+
+ms(Fun) ->
+ {Ms,ok} = timer:tc(Fun),
+ Ms.
+
+make_modules(0, _) ->
+ [];
+make_modules(N, Fun) ->
+ U = erlang:unique_integer([positive]),
+ M0 = "m__" ++ integer_to_list(N) ++ "_" ++ integer_to_list(U),
+ Contents = Fun(M0),
+ Forms = [make_form(S) || S <- Contents],
+ {ok,M,Code} = compile:forms(Forms),
+ [{M,Code}|make_modules(N-1, Fun)].
+
+make_form(S) ->
+ {ok,Toks,_} = erl_scan:string(S),
+ {ok,Form} = erl_parse:parse_form(Toks),
+ Form.
+
+prepare_modules(Ms) ->
+ [erlang:prepare_loading(M, Code) || {M,Code} <- Ms].
diff --git a/erts/emulator/test/nested_SUITE.erl b/erts/emulator/test/nested_SUITE.erl
index 7cfa837ee5..c13e19f857 100644
--- a/erts/emulator/test/nested_SUITE.erl
+++ b/erts/emulator/test/nested_SUITE.erl
@@ -20,90 +20,74 @@
-module(nested_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- case_in_case/1, case_in_after/1, catch_in_catch/1, bif_in_bif/1]).
+-export([all/0, suite/0,
+ case_in_case/1, case_in_after/1, catch_in_catch/1, bif_in_bif/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {seconds, 10}}].
all() ->
[case_in_case, case_in_after, catch_in_catch,
bif_in_bif].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
case_in_case(suite) -> [];
case_in_case(Config) when is_list(Config) ->
- ?line done = search_any([a], [{a, 1}]),
- ?line done = search_any([x], [{a, 1}]),
+ done = search_any([a], [{a, 1}]),
+ done = search_any([x], [{a, 1}]),
ok.
search_any([Key|Rest], List) ->
- ?line case case lists:keysearch(Key, 1, List) of
- {value, _} ->
- true;
- _ ->
- false
- end of
- true ->
- ok;
- false ->
- error;
- Other ->
- test_server:fail({other_result, Other})
- end,
- ?line search_any(Rest, List);
+ case case lists:keysearch(Key, 1, List) of
+ {value, _} ->
+ true;
+ _ ->
+ false
+ end of
+ true ->
+ ok;
+ false ->
+ error;
+ Other ->
+ ct:fail({other_result, Other})
+ end,
+ search_any(Rest, List);
search_any([], _) ->
done.
case_in_after(suite) -> [];
case_in_after(Config) when is_list(Config) ->
receive
- after case {x, y, z} of
- {x, y, z} -> 0
- end ->
- ok
- end,
+ after case {x, y, z} of
+ {x, y, z} -> 0
+ end ->
+ ok
+ end,
ok.
-catch_in_catch(doc) -> "Test a catch within a catch in the same function.";
-catch_in_catch(suite) -> [];
+%% Test a catch within a catch in the same function.
catch_in_catch(Config) when is_list(Config) ->
- ?line {outer, inner_exit} = catcher(),
+ {outer, inner_exit} = catcher(),
ok.
catcher() ->
case (catch
- case (catch ?MODULE:non_existing()) of % bogus function
- {'EXIT', _} ->
- inner_exit;
- Res1 ->
- {inner, Res1}
- end) of
- {'EXIT', _} ->
- outer_exit;
- Res2 ->
- {outer, Res2}
+ case (catch ?MODULE:non_existing()) of % bogus function
+ {'EXIT', _} ->
+ inner_exit;
+ Res1 ->
+ {inner, Res1}
+ end) of
+ {'EXIT', _} ->
+ outer_exit;
+ Res2 ->
+ {outer, Res2}
end.
-bif_in_bif(doc) -> "Test a BIF call within a BIF call.";
-bif_in_bif(suite) -> [];
+%% Test a BIF call within a BIF call.
bif_in_bif(Config) when is_list(Config) ->
Self = self(),
put(pid, Self),
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl
index 2400505159..84f5699890 100644
--- a/erts/emulator/test/nif_SUITE.erl
+++ b/erts/emulator/test/nif_SUITE.erl
@@ -22,14 +22,13 @@
%%-define(line_trace,true).
-define(CHECK(Exp,Got), check(Exp,Got,?LINE)).
-%%-define(CHECK(Exp,Got), ?line Exp = Got).
+%%-define(CHECK(Exp,Got), Exp = Got).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,
- end_per_testcase/2, basic/1, reload/1, upgrade/1, heap_frag/1,
+-export([all/0, suite/0,
+ init_per_testcase/2, end_per_testcase/2,
+ basic/1, reload/1, upgrade/1, heap_frag/1,
types/1, many_args/1, binaries/1, get_string/1, get_atom/1,
maps/1,
api_macros/1,
@@ -43,8 +42,7 @@
dirty_nif_exception/1, call_dirty_nif_exception/1, nif_schedule/1,
nif_exception/1, call_nif_exception/1,
nif_nan_and_inf/1, nif_atom_too_long/1,
- nif_monotonic_time/1, nif_time_offset/1, nif_convert_time_unit/1
- ]).
+ nif_monotonic_time/1, nif_time_offset/1, nif_convert_time_unit/1]).
-export([many_args_100/100]).
@@ -77,179 +75,156 @@ all() ->
nif_monotonic_time, nif_time_offset, nif_convert_time_unit
].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
init_per_testcase(_Case, Config) ->
-% ?line Dog = ?t:timetrap(?t:seconds(60*60*24)),
Config.
end_per_testcase(_Func, _Config) ->
- %%Dog = ?config(watchdog, Config),
- %%?t:timetrap_cancel(Dog),
P1 = code:purge(nif_mod),
Del = code:delete(nif_mod),
P2 = code:purge(nif_mod),
io:format("fin purged=~p, deleted=~p and then purged=~p\n",[P1,Del,P2]).
-basic(doc) -> ["Basic smoke test of load_nif and a simple NIF call"];
-basic(suite) -> [];
+%% Basic smoke test of load_nif and a simple NIF call
basic(Config) when is_list(Config) ->
ensure_lib_loaded(Config),
- ?line true = (lib_version() =/= undefined),
- ?line [{load,1,1,101},{lib_version,1,2,102}] = call_history(),
- ?line [] = call_history(),
- ?line true = lists:member(?MODULE, erlang:system_info(taints)),
+ true = (lib_version() =/= undefined),
+ [{load,1,1,101},{lib_version,1,2,102}] = call_history(),
+ [] = call_history(),
+ true = lists:member(?MODULE, erlang:system_info(taints)),
ok.
-reload(doc) -> ["Test reload callback in nif lib"];
-reload(suite) -> [];
+%% Test reload callback in nif lib
reload(Config) when is_list(Config) ->
TmpMem = tmpmem(),
ensure_lib_loaded(Config),
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "nif_mod"),
- ?line {ok,nif_mod,Bin} = compile:file(File, [binary,return_errors]),
- ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "nif_mod"),
+ {ok,nif_mod,Bin} = compile:file(File, [binary,return_errors]),
+ {module,nif_mod} = erlang:load_module(nif_mod,Bin),
- ?line ok = nif_mod:load_nif_lib(Config, 1),
+ ok = nif_mod:load_nif_lib(Config, 1),
- ?line hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()),
- ?line [{load,1,1,101},{get_priv_data_ptr,1,2,102}] = nif_mod_call_history(),
+ hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()),
+ [{load,1,1,101},{get_priv_data_ptr,1,2,102}] = nif_mod_call_history(),
- ?line ok = nif_mod:load_nif_lib(Config, 2),
- ?line 2 = nif_mod:lib_version(),
- ?line [{reload,2,1,201},{lib_version,2,2,202}] = nif_mod_call_history(),
+ ok = nif_mod:load_nif_lib(Config, 2),
+ 2 = nif_mod:lib_version(),
+ [{reload,2,1,201},{lib_version,2,2,202}] = nif_mod_call_history(),
- ?line ok = nif_mod:load_nif_lib(Config, 1),
- ?line 1 = nif_mod:lib_version(),
- ?line [{reload,1,1,101},{lib_version,1,2,102}] = nif_mod_call_history(),
+ ok = nif_mod:load_nif_lib(Config, 1),
+ 1 = nif_mod:lib_version(),
+ [{reload,1,1,101},{lib_version,1,2,102}] = nif_mod_call_history(),
- ?line true = erlang:delete_module(nif_mod),
- ?line [] = nif_mod_call_history(),
+ true = erlang:delete_module(nif_mod),
+ [] = nif_mod_call_history(),
- %%?line false= check_process_code(Pid, nif_mod),
- ?line true = erlang:purge_module(nif_mod),
- ?line [{unload,1,3,103}] = nif_mod_call_history(),
+ %%false= check_process_code(Pid, nif_mod),
+ true = erlang:purge_module(nif_mod),
+ [{unload,1,3,103}] = nif_mod_call_history(),
- ?line true = lists:member(?MODULE, erlang:system_info(taints)),
- ?line true = lists:member(nif_mod, erlang:system_info(taints)),
- ?line verify_tmpmem(TmpMem),
+ true = lists:member(?MODULE, erlang:system_info(taints)),
+ true = lists:member(nif_mod, erlang:system_info(taints)),
+ verify_tmpmem(TmpMem),
ok.
-upgrade(doc) -> ["Test upgrade callback in nif lib"];
-upgrade(suite) -> [];
+%% Test upgrade callback in nif lib
upgrade(Config) when is_list(Config) ->
TmpMem = tmpmem(),
ensure_lib_loaded(Config),
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "nif_mod"),
- ?line {ok,nif_mod,Bin} = compile:file(File, [binary,return_errors]),
- ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "nif_mod"),
+ {ok,nif_mod,Bin} = compile:file(File, [binary,return_errors]),
+ {module,nif_mod} = erlang:load_module(nif_mod,Bin),
- ?line ok = nif_mod:load_nif_lib(Config, 1),
- ?line {Pid,MRef} = nif_mod:start(),
- ?line 1 = call(Pid,lib_version),
+ ok = nif_mod:load_nif_lib(Config, 1),
+ {Pid,MRef} = nif_mod:start(),
+ 1 = call(Pid,lib_version),
- ?line hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()),
- ?line [{load,1,1,101},{lib_version,1,2,102},{get_priv_data_ptr,1,3,103}] = nif_mod_call_history(),
+ hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()),
+ [{load,1,1,101},{lib_version,1,2,102},{get_priv_data_ptr,1,3,103}] = nif_mod_call_history(),
%% Module upgrade with same lib-version
- ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin),
- ?line undefined = nif_mod:lib_version(),
- ?line 1 = call(Pid,lib_version),
- ?line [{lib_version,1,4,104}] = nif_mod_call_history(),
+ {module,nif_mod} = erlang:load_module(nif_mod,Bin),
+ undefined = nif_mod:lib_version(),
+ 1 = call(Pid,lib_version),
+ [{lib_version,1,4,104}] = nif_mod_call_history(),
- ?line ok = nif_mod:load_nif_lib(Config, 1),
- ?line 1 = nif_mod:lib_version(),
- ?line [{upgrade,1,5,105},{lib_version,1,6,106}] = nif_mod_call_history(),
+ ok = nif_mod:load_nif_lib(Config, 1),
+ 1 = nif_mod:lib_version(),
+ [{upgrade,1,5,105},{lib_version,1,6,106}] = nif_mod_call_history(),
- ?line upgraded = call(Pid,upgrade),
- ?line false = check_process_code(Pid, nif_mod),
- ?line true = erlang:purge_module(nif_mod),
- ?line [{unload,1,7,107}] = nif_mod_call_history(),
+ upgraded = call(Pid,upgrade),
+ false = check_process_code(Pid, nif_mod),
+ true = erlang:purge_module(nif_mod),
+ [{unload,1,7,107}] = nif_mod_call_history(),
- ?line 1 = nif_mod:lib_version(),
- ?line [{lib_version,1,8,108}] = nif_mod_call_history(),
+ 1 = nif_mod:lib_version(),
+ [{lib_version,1,8,108}] = nif_mod_call_history(),
- ?line true = erlang:delete_module(nif_mod),
- ?line [] = nif_mod_call_history(),
+ true = erlang:delete_module(nif_mod),
+ [] = nif_mod_call_history(),
- ?line Pid ! die,
- ?line {'DOWN', MRef, process, Pid, normal} = receive_any(),
- ?line false = check_process_code(Pid, nif_mod),
- ?line true = erlang:purge_module(nif_mod),
- ?line [{unload,1,9,109}] = nif_mod_call_history(),
+ Pid ! die,
+ {'DOWN', MRef, process, Pid, normal} = receive_any(),
+ false = check_process_code(Pid, nif_mod),
+ true = erlang:purge_module(nif_mod),
+ [{unload,1,9,109}] = nif_mod_call_history(),
%% Module upgrade with different lib version
- ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin),
- ?line undefined = nif_mod:lib_version(),
- ?line {Pid2,MRef2} = nif_mod:start(),
- ?line undefined = call(Pid2,lib_version),
-
- ?line ok = nif_mod:load_nif_lib(Config, 1),
- ?line hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()),
- ?line 1 = call(Pid2,lib_version),
- ?line [{load,1,1,101},{get_priv_data_ptr,1,2,102},{lib_version,1,3,103}] = nif_mod_call_history(),
-
- ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin),
- ?line undefined = nif_mod:lib_version(),
- ?line [] = nif_mod_call_history(),
- ?line 1 = call(Pid2,lib_version),
- ?line [{lib_version,1,4,104}] = nif_mod_call_history(),
-
- ?line ok = nif_mod:load_nif_lib(Config, 2),
- ?line 2 = nif_mod:lib_version(),
- ?line [{upgrade,2,1,201},{lib_version,2,2,202}] = nif_mod_call_history(),
-
- ?line 1 = call(Pid2,lib_version),
- ?line [{lib_version,1,5,105}] = nif_mod_call_history(),
-
- ?line upgraded = call(Pid2,upgrade),
- ?line false = check_process_code(Pid2, nif_mod),
- ?line true = erlang:purge_module(nif_mod),
- ?line [{unload,1,6,106}] = nif_mod_call_history(),
-
- ?line 2 = nif_mod:lib_version(),
- ?line [{lib_version,2,3,203}] = nif_mod_call_history(),
-
- ?line true = erlang:delete_module(nif_mod),
- ?line [] = nif_mod_call_history(),
-
- ?line Pid2 ! die,
- ?line {'DOWN', MRef2, process, Pid2, normal} = receive_any(),
- ?line false= check_process_code(Pid2, nif_mod),
- ?line true = erlang:purge_module(nif_mod),
- ?line [{unload,2,4,204}] = nif_mod_call_history(),
-
- ?line true = lists:member(?MODULE, erlang:system_info(taints)),
- ?line true = lists:member(nif_mod, erlang:system_info(taints)),
- ?line verify_tmpmem(TmpMem),
+ {module,nif_mod} = erlang:load_module(nif_mod,Bin),
+ undefined = nif_mod:lib_version(),
+ {Pid2,MRef2} = nif_mod:start(),
+ undefined = call(Pid2,lib_version),
+
+ ok = nif_mod:load_nif_lib(Config, 1),
+ hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()),
+ 1 = call(Pid2,lib_version),
+ [{load,1,1,101},{get_priv_data_ptr,1,2,102},{lib_version,1,3,103}] = nif_mod_call_history(),
+
+ {module,nif_mod} = erlang:load_module(nif_mod,Bin),
+ undefined = nif_mod:lib_version(),
+ [] = nif_mod_call_history(),
+ 1 = call(Pid2,lib_version),
+ [{lib_version,1,4,104}] = nif_mod_call_history(),
+
+ ok = nif_mod:load_nif_lib(Config, 2),
+ 2 = nif_mod:lib_version(),
+ [{upgrade,2,1,201},{lib_version,2,2,202}] = nif_mod_call_history(),
+
+ 1 = call(Pid2,lib_version),
+ [{lib_version,1,5,105}] = nif_mod_call_history(),
+
+ upgraded = call(Pid2,upgrade),
+ false = check_process_code(Pid2, nif_mod),
+ true = erlang:purge_module(nif_mod),
+ [{unload,1,6,106}] = nif_mod_call_history(),
+
+ 2 = nif_mod:lib_version(),
+ [{lib_version,2,3,203}] = nif_mod_call_history(),
+
+ true = erlang:delete_module(nif_mod),
+ [] = nif_mod_call_history(),
+
+ Pid2 ! die,
+ {'DOWN', MRef2, process, Pid2, normal} = receive_any(),
+ false= check_process_code(Pid2, nif_mod),
+ true = erlang:purge_module(nif_mod),
+ [{unload,2,4,204}] = nif_mod_call_history(),
+
+ true = lists:member(?MODULE, erlang:system_info(taints)),
+ true = lists:member(nif_mod, erlang:system_info(taints)),
+ verify_tmpmem(TmpMem),
ok.
-heap_frag(doc) -> ["Test NIF building heap fragments"];
-heap_frag(suite) -> [];
+%% Test NIF building heap fragments
heap_frag(Config) when is_list(Config) ->
TmpMem = tmpmem(),
ensure_lib_loaded(Config),
heap_frag_do(1,1000000),
- ?line verify_tmpmem(TmpMem),
+ verify_tmpmem(TmpMem),
ok.
heap_frag_do(N, Max) when N > Max ->
@@ -260,12 +235,11 @@ heap_frag_do(N, Max) ->
L = list_seq(N),
heap_frag_do(((N*5) div 4) + 1, Max).
-types(doc) -> ["Type tests"];
-types(suite) -> [];
+%% Type tests
types(Config) when is_list(Config) ->
TmpMem = tmpmem(),
ensure_lib_loaded(Config),
- ?line ok = type_test(),
+ ok = type_test(),
lists:foreach(fun(Tpl) ->
Lst = erlang:tuple_to_list(Tpl),
Lst = tuple_2_list(Tpl)
@@ -290,18 +264,18 @@ types(Config) when is_list(Config) ->
R1 = echo_int(I),
%%io:format("echo_int(~p) -> ~p\n", [I, R1]),
R2 = my_echo_int(I, Limits),
- ?line R1 = R2,
- ?line true = (R1 =:= R2),
- ?line true = (R1 == R2)
+ R1 = R2,
+ true = (R1 =:= R2),
+ true = (R1 == R2)
end, int_list()),
- ?line verify_tmpmem(TmpMem),
- ?line true = (compare(-1294536544000, -1178704800000) < 0),
- ?line true = (compare(-1178704800000, -1294536544000) > 0),
- ?line true = (compare(-295147905179352825856, -36893488147419103232) < 0),
- ?line true = (compare(-36893488147419103232, -295147905179352825856) > 0),
- ?line true = (compare(-29514790517935282585612345678, -36893488147419103232) < 0),
- ?line true = (compare(-36893488147419103232, -29514790517935282585612345678) > 0),
+ verify_tmpmem(TmpMem),
+ true = (compare(-1294536544000, -1178704800000) < 0),
+ true = (compare(-1178704800000, -1294536544000) > 0),
+ true = (compare(-295147905179352825856, -36893488147419103232) < 0),
+ true = (compare(-36893488147419103232, -295147905179352825856) > 0),
+ true = (compare(-29514790517935282585612345678, -36893488147419103232) < 0),
+ true = (compare(-36893488147419103232, -29514790517935282585612345678) > 0),
ok.
int_list() ->
@@ -329,15 +303,15 @@ eq_cmp(A,B) ->
eq_cmp_do({A,B},{A,B}).
eq_cmp_do(A,B) ->
- %%?t:format("compare ~p and ~p\n",[A,B]),
+ %%io:format("compare ~p and ~p\n",[A,B]),
Eq = (A =:= B),
- ?line Eq = is_identical(A,B),
- ?line Cmp = if
+ Eq = is_identical(A,B),
+ Cmp = if
A < B -> -1;
A == B -> 0;
A > B -> 1
end,
- ?line Cmp = case compare(A,B) of
+ Cmp = case compare(A,B) of
C when is_integer(C), C < 0 -> -1;
0 -> 0;
C when is_integer(C) -> 1
@@ -345,47 +319,45 @@ eq_cmp_do(A,B) ->
ok.
-many_args(doc) -> ["Test NIF with many arguments"];
-many_args(suite) -> [];
+%% Test NIF with many arguments
many_args(Config) when is_list(Config) ->
TmpMem = tmpmem(),
- ?line ensure_lib_loaded(Config ,1),
- ?line ok = apply(?MODULE,many_args_100,lists:seq(1,100)),
- ?line ok = many_args_100(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,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,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100),
- ?line verify_tmpmem(TmpMem),
+ ensure_lib_loaded(Config ,1),
+ ok = apply(?MODULE,many_args_100,lists:seq(1,100)),
+ ok = many_args_100(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,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,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100),
+ verify_tmpmem(TmpMem),
ok.
-binaries(doc) -> ["Test NIF binary handling."];
-binaries(suite) -> [];
+%% Test NIF binary handling.
binaries(Config) when is_list(Config) ->
TmpMem = tmpmem(),
- ?line ensure_lib_loaded(Config, 1),
- ?line RefcBin = list_to_binary(lists:seq(1,255)),
- ?line RefcBin = clone_bin(RefcBin),
- ?line HeapBin = list_to_binary(lists:seq(1,20)),
- ?line HeapBin = clone_bin(HeapBin),
- ?line <<_:8,Sub1:6/binary,_/binary>> = RefcBin,
- ?line <<_:8,Sub2:6/binary,_/binary>> = HeapBin,
- ?line Sub1 = Sub2,
- ?line Sub1 = clone_bin(Sub1),
- ?line Sub2 = clone_bin(Sub2),
- ?line <<_:9,Sub3:6/binary,_/bitstring>> = RefcBin,
- ?line <<_:9,Sub4:6/binary,_/bitstring>> = HeapBin,
- ?line Sub3 = Sub4,
- ?line Sub3 = clone_bin(Sub3),
- ?line Sub4 = clone_bin(Sub4),
+ ensure_lib_loaded(Config, 1),
+ RefcBin = list_to_binary(lists:seq(1,255)),
+ RefcBin = clone_bin(RefcBin),
+ HeapBin = list_to_binary(lists:seq(1,20)),
+ HeapBin = clone_bin(HeapBin),
+ <<_:8,Sub1:6/binary,_/binary>> = RefcBin,
+ <<_:8,Sub2:6/binary,_/binary>> = HeapBin,
+ Sub1 = Sub2,
+ Sub1 = clone_bin(Sub1),
+ Sub2 = clone_bin(Sub2),
+ <<_:9,Sub3:6/binary,_/bitstring>> = RefcBin,
+ <<_:9,Sub4:6/binary,_/bitstring>> = HeapBin,
+ Sub3 = Sub4,
+ Sub3 = clone_bin(Sub3),
+ Sub4 = clone_bin(Sub4),
%% When NIFs get bitstring support
- %%?line <<_:8,Sub5:27/bitstring,_/bitstring>> = RefcBin,
- %%?line <<_:8,Sub6:27/bitstring,_/bitstring>> = HeapBin,
- %%?line Sub5 = Sub6,
- %%?line Sub5 = clone_bin(Sub5),
- %%?line Sub6 = clone_bin(Sub6),
- %%?line <<_:9,Sub7:27/bitstring,_/bitstring>> = RefcBin,
- %%?line <<_:9,Sub8:27/bitstring,_/bitstring>> = HeapBin,
- %%?line Sub7 = Sub8,
- %%?line Sub7 = clone_bin(Sub7),
- %%?line Sub8 = clone_bin(Sub8),
- %%?line <<>> = clone_bin(<<>>),
+ %%<<_:8,Sub5:27/bitstring,_/bitstring>> = RefcBin,
+ %%<<_:8,Sub6:27/bitstring,_/bitstring>> = HeapBin,
+ %%Sub5 = Sub6,
+ %%Sub5 = clone_bin(Sub5),
+ %%Sub6 = clone_bin(Sub6),
+ %%<<_:9,Sub7:27/bitstring,_/bitstring>> = RefcBin,
+ %%<<_:9,Sub8:27/bitstring,_/bitstring>> = HeapBin,
+ %%Sub7 = Sub8,
+ %%Sub7 = clone_bin(Sub7),
+ %%Sub8 = clone_bin(Sub8),
+ %%<<>> = clone_bin(<<>>),
<<_:8,SubBinA:200/binary,_/binary>> = RefcBin,
<<_:9,SubBinB:200/binary,_/bitstring>> = RefcBin,
@@ -398,56 +370,53 @@ binaries(Config) when is_list(Config) ->
test_make_sub_bin(SubBinC),
test_make_sub_bin(SubBinD),
- ?line verify_tmpmem(TmpMem),
+ verify_tmpmem(TmpMem),
ok.
test_make_sub_bin(Bin) ->
Size = byte_size(Bin),
Rest10 = Size - 10,
Rest1 = Size - 1,
- ?line Bin = make_sub_bin(Bin, 0, Size),
+ Bin = make_sub_bin(Bin, 0, Size),
<<_:10/binary,Sub0:Rest10/binary>> = Bin,
- ?line Sub0 = make_sub_bin(Bin, 10, Rest10),
+ Sub0 = make_sub_bin(Bin, 10, Rest10),
<<Sub1:10/binary,_/binary>> = Bin,
- ?line Sub1 = make_sub_bin(Bin, 0, 10),
+ Sub1 = make_sub_bin(Bin, 0, 10),
<<_:7/binary,Sub2:10/binary,_/binary>> = Bin,
- ?line Sub2 = make_sub_bin(Bin, 7, 10),
- ?line <<>> = make_sub_bin(Bin, 0, 0),
- ?line <<>> = make_sub_bin(Bin, 10, 0),
- ?line <<>> = make_sub_bin(Bin, Rest1, 0),
- ?line <<>> = make_sub_bin(Bin, Size, 0),
+ Sub2 = make_sub_bin(Bin, 7, 10),
+ <<>> = make_sub_bin(Bin, 0, 0),
+ <<>> = make_sub_bin(Bin, 10, 0),
+ <<>> = make_sub_bin(Bin, Rest1, 0),
+ <<>> = make_sub_bin(Bin, Size, 0),
ok.
-get_string(doc) -> ["Test enif_get_string"];
-get_string(suite) -> [];
+%% Test enif_get_string
get_string(Config) when is_list(Config) ->
- ?line ensure_lib_loaded(Config, 1),
- ?line {7, <<"hejsan",0,_:3/binary>>} = string_to_bin("hejsan",10),
- ?line {7, <<"hejsan",0,_>>} = string_to_bin("hejsan",8),
- ?line {7, <<"hejsan",0>>} = string_to_bin("hejsan",7),
- ?line {-6, <<"hejsa",0>>} = string_to_bin("hejsan",6),
- ?line {-5, <<"hejs",0>>} = string_to_bin("hejsan",5),
- ?line {-1, <<0>>} = string_to_bin("hejsan",1),
- ?line {0, <<>>} = string_to_bin("hejsan",0),
- ?line {1, <<0>>} = string_to_bin("",1),
- ?line {0, <<>>} = string_to_bin("",0),
+ ensure_lib_loaded(Config, 1),
+ {7, <<"hejsan",0,_:3/binary>>} = string_to_bin("hejsan",10),
+ {7, <<"hejsan",0,_>>} = string_to_bin("hejsan",8),
+ {7, <<"hejsan",0>>} = string_to_bin("hejsan",7),
+ {-6, <<"hejsa",0>>} = string_to_bin("hejsan",6),
+ {-5, <<"hejs",0>>} = string_to_bin("hejsan",5),
+ {-1, <<0>>} = string_to_bin("hejsan",1),
+ {0, <<>>} = string_to_bin("hejsan",0),
+ {1, <<0>>} = string_to_bin("",1),
+ {0, <<>>} = string_to_bin("",0),
ok.
-get_atom(doc) -> ["Test enif_get_atom"];
-get_atom(suite) -> [];
+%% Test enif_get_atom
get_atom(Config) when is_list(Config) ->
- ?line ensure_lib_loaded(Config, 1),
- ?line {7, <<"hejsan",0,_:3/binary>>} = atom_to_bin(hejsan,10),
- ?line {7, <<"hejsan",0,_>>} = atom_to_bin(hejsan,8),
- ?line {7, <<"hejsan",0>>} = atom_to_bin(hejsan,7),
- ?line {0, <<_:6/binary>>} = atom_to_bin(hejsan,6),
- ?line {0, <<>>} = atom_to_bin(hejsan,0),
- ?line {1, <<0>>} = atom_to_bin('',1),
- ?line {0, <<>>} = atom_to_bin('',0),
+ ensure_lib_loaded(Config, 1),
+ {7, <<"hejsan",0,_:3/binary>>} = atom_to_bin(hejsan,10),
+ {7, <<"hejsan",0,_>>} = atom_to_bin(hejsan,8),
+ {7, <<"hejsan",0>>} = atom_to_bin(hejsan,7),
+ {0, <<_:6/binary>>} = atom_to_bin(hejsan,6),
+ {0, <<>>} = atom_to_bin(hejsan,0),
+ {1, <<0>>} = atom_to_bin('',1),
+ {0, <<>>} = atom_to_bin('',0),
ok.
-maps(doc) -> ["Test NIF maps handling."];
-maps(suite) -> [];
+%% Test NIF maps handling.
maps(Config) when is_list(Config) ->
TmpMem = tmpmem(),
Pairs = [{adam, "bert"}] ++
@@ -494,31 +463,28 @@ maps(Config) when is_list(Config) ->
ok.
-api_macros(doc) -> ["Test macros enif_make_list<N> and enif_make_tuple<N>"];
-api_macros(suite) -> [];
+%% Test macros enif_make_list<N> and enif_make_tuple<N>
api_macros(Config) when is_list(Config) ->
- ?line ensure_lib_loaded(Config, 1),
+ ensure_lib_loaded(Config, 1),
Expected = {[lists:seq(1,N) || N <- lists:seq(1,9)],
[list_to_tuple(lists:seq(1,N)) || N <- lists:seq(1,9)]
},
- ?line Expected = macros(list_to_tuple(lists:seq(1,9))),
+ Expected = macros(list_to_tuple(lists:seq(1,9))),
ok.
-from_array(doc) -> ["enif_make_[tuple|list]_from_array"];
-from_array(suite) -> [];
+%% enif_make_[tuple|list]_from_array
from_array(Config) when is_list(Config) ->
- ?line ensure_lib_loaded(Config, 1),
+ ensure_lib_loaded(Config, 1),
lists:foreach(fun(Tpl) ->
Lst = tuple_to_list(Tpl),
- ?line {Lst,Tpl} = tuple_2_list_and_tuple(Tpl)
+ {Lst,Tpl} = tuple_2_list_and_tuple(Tpl)
end,
[{}, {1,2,3}, {[4,5],[],{},{6,7}}, {{}}, {[]}]),
ok.
-iolist_as_binary(doc) -> ["enif_inspect_iolist_as_binary"];
-iolist_as_binary(suite) -> [];
+%% enif_inspect_iolist_as_binary
iolist_as_binary(Config) when is_list(Config) ->
- ?line ensure_lib_loaded(Config, 1),
+ ensure_lib_loaded(Config, 1),
TmpMem = tmpmem(),
List = [<<"hejsan">>, <<>>, [], [17], [<<>>],
[127,128,255,0],
@@ -527,18 +493,17 @@ iolist_as_binary(Config) when is_list(Config) ->
lists:foreach(fun(IoL) ->
B1 = erlang:iolist_to_binary(IoL),
- ?line B2 = iolist_2_bin(IoL),
- ?line B1 = B2
+ B2 = iolist_2_bin(IoL),
+ B1 = B2
end,
List),
- ?line verify_tmpmem(TmpMem),
+ verify_tmpmem(TmpMem),
ok.
-resource(doc) -> ["Test memory managed objects, aka 'resources'"];
-resource(suite) -> [];
+%% Test memory managed objects, aka 'resources'
resource(Config) when is_list(Config) ->
- ?line ensure_lib_loaded(Config, 1),
- ?line Type = get_resource_type(0),
+ ensure_lib_loaded(Config, 1),
+ Type = get_resource_type(0),
resource_hugo(Type),
resource_otto(Type),
resource_new(Type),
@@ -548,75 +513,75 @@ resource(Config) when is_list(Config) ->
resource_hugo(Type) ->
DtorCall = resource_hugo_do(Type),
erlang:garbage_collect(),
- ?line DtorCall = last_resource_dtor_call(),
+ DtorCall = last_resource_dtor_call(),
ok.
resource_hugo_do(Type) ->
HugoBin = <<"Hugo Hacker">>,
- ?line HugoPtr = alloc_resource(Type, HugoBin),
- ?line Hugo = make_resource(HugoPtr),
- ?line <<>> = Hugo,
+ HugoPtr = alloc_resource(Type, HugoBin),
+ Hugo = make_resource(HugoPtr),
+ <<>> = Hugo,
release_resource(HugoPtr),
erlang:garbage_collect(),
- ?line {HugoPtr,HugoBin} = get_resource(Type,Hugo),
+ {HugoPtr,HugoBin} = get_resource(Type,Hugo),
Pid = spawn_link(fun() ->
- receive {Pid, Type, Resource, Ptr, Bin} ->
- Pid ! {self(), got_it},
- receive {Pid, check_it} ->
- ?line {Ptr,Bin} = get_resource(Type,Resource),
- Pid ! {self(), ok}
- end
- end
- end),
+ receive {Pid, Type, Resource, Ptr, Bin} ->
+ Pid ! {self(), got_it},
+ receive {Pid, check_it} ->
+ {Ptr,Bin} = get_resource(Type,Resource),
+ Pid ! {self(), ok}
+ end
+ end
+ end),
Pid ! {self(), Type, Hugo, HugoPtr, HugoBin},
- ?line {Pid, got_it} = receive_any(),
+ {Pid, got_it} = receive_any(),
erlang:garbage_collect(), % just to make our ProcBin move in memory
Pid ! {self(), check_it},
- ?line {Pid, ok} = receive_any(),
- ?line [] = last_resource_dtor_call(),
- ?line {HugoPtr,HugoBin} = get_resource(Type,Hugo),
+ {Pid, ok} = receive_any(),
+ [] = last_resource_dtor_call(),
+ {HugoPtr,HugoBin} = get_resource(Type,Hugo),
{HugoPtr, HugoBin, 1}.
resource_otto(Type) ->
{OttoPtr, OttoBin} = resource_otto_do(Type),
erlang:garbage_collect(),
- ?line [] = last_resource_dtor_call(),
+ [] = last_resource_dtor_call(),
release_resource(OttoPtr),
- ?line {OttoPtr,OttoBin,1} = last_resource_dtor_call(),
+ {OttoPtr,OttoBin,1} = last_resource_dtor_call(),
ok.
resource_otto_do(Type) ->
OttoBin = <<"Otto Ordonnans">>,
- ?line OttoPtr = alloc_resource(Type, OttoBin),
- ?line Otto = make_resource(OttoPtr),
- ?line <<>> = Otto,
+ OttoPtr = alloc_resource(Type, OttoBin),
+ Otto = make_resource(OttoPtr),
+ <<>> = Otto,
%% forget resource term but keep referenced by NIF
{OttoPtr, OttoBin}.
resource_new(Type) ->
- ?line {PtrB,BinB} = resource_new_do1(Type),
+ {PtrB,BinB} = resource_new_do1(Type),
erlang:garbage_collect(),
- ?line {PtrB,BinB,1} = last_resource_dtor_call(),
+ {PtrB,BinB,1} = last_resource_dtor_call(),
ok.
resource_new_do1(Type) ->
- ?line {{PtrA,BinA}, {ResB,PtrB,BinB}} = resource_new_do2(Type),
+ {{PtrA,BinA}, {ResB,PtrB,BinB}} = resource_new_do2(Type),
erlang:garbage_collect(),
- ?line {PtrA,BinA,1} = last_resource_dtor_call(),
- ?line {PtrB,BinB} = get_resource(Type, ResB),
+ {PtrA,BinA,1} = last_resource_dtor_call(),
+ {PtrB,BinB} = get_resource(Type, ResB),
%% forget ResB and make it garbage
{PtrB,BinB}.
resource_new_do2(Type) ->
BinA = <<"NewA">>,
BinB = <<"NewB">>,
- ?line ResA = make_new_resource(Type, BinA),
- ?line ResB = make_new_resource(Type, BinB),
- ?line <<>> = ResA,
- ?line <<>> = ResB,
- ?line {PtrA,BinA} = get_resource(Type, ResA),
- ?line {PtrB,BinB} = get_resource(Type, ResB),
- ?line true = (PtrA =/= PtrB),
+ ResA = make_new_resource(Type, BinA),
+ ResB = make_new_resource(Type, BinB),
+ <<>> = ResA,
+ <<>> = ResB,
+ {PtrA,BinA} = get_resource(Type, ResA),
+ {PtrB,BinB} = get_resource(Type, ResB),
+ true = (PtrA =/= PtrB),
%% forget ResA and make it garbage
{{PtrA,BinA}, {ResB,PtrB,BinB}}.
@@ -625,22 +590,21 @@ resource_neg(TypeA) ->
catch exit(42), % dummy exception to purge saved stacktraces from earlier exception
erlang:garbage_collect(),
- ?line {_,_,2} = last_resource_dtor_call(),
+ {_,_,2} = last_resource_dtor_call(),
ok.
resource_neg_do(TypeA) ->
TypeB = get_resource_type(1),
ResA = make_new_resource(TypeA, <<"Arnold">>),
ResB= make_new_resource(TypeB, <<"Bobo">>),
- ?line {'EXIT',{badarg,_}} = (catch get_resource(TypeA, ResB)),
- ?line {'EXIT',{badarg,_}} = (catch get_resource(TypeB, ResA)),
+ {'EXIT',{badarg,_}} = (catch get_resource(TypeA, ResB)),
+ {'EXIT',{badarg,_}} = (catch get_resource(TypeB, ResA)),
ok.
-resource_binary(doc) -> ["Test enif_make_resource_binary"];
-resource_binary(suite) -> [];
+%% Test enif_make_resource_binary
resource_binary(Config) when is_list(Config) ->
- ?line ensure_lib_loaded(Config, 1),
- ?line {Ptr,Bin} = resource_binary_do(),
+ ensure_lib_loaded(Config, 1),
+ {Ptr,Bin} = resource_binary_do(),
erlang:garbage_collect(),
Last = last_resource_dtor_call(),
?CHECK({Ptr,Bin,1}, Last),
@@ -648,58 +612,57 @@ resource_binary(Config) when is_list(Config) ->
resource_binary_do() ->
Bin = <<"Hej Hopp i lingonskogen">>,
- ?line {Ptr,ResBin1} = make_new_resource_binary(Bin),
- ?line ResBin1 = Bin,
- ?line ResInfo = {Ptr,_} = get_resource(binary_resource_type,ResBin1),
+ {Ptr,ResBin1} = make_new_resource_binary(Bin),
+ ResBin1 = Bin,
+ ResInfo = {Ptr,_} = get_resource(binary_resource_type,ResBin1),
Papa = self(),
Forwarder = spawn_link(fun() -> forwarder(Papa) end),
io:format("sending to forwarder pid=~p\n",[Forwarder]),
Forwarder ! ResBin1,
ResBin2 = receive_any(),
- ?line ResBin2 = ResBin1,
- ?line ResInfo = get_resource(binary_resource_type,ResBin2),
+ ResBin2 = ResBin1,
+ ResInfo = get_resource(binary_resource_type,ResBin2),
Forwarder ! terminate,
- ?line {Forwarder, 1} = receive_any(),
+ {Forwarder, 1} = receive_any(),
erlang:garbage_collect(),
- ?line ResInfo = get_resource(binary_resource_type,ResBin1),
- ?line ResInfo = get_resource(binary_resource_type,ResBin2),
+ ResInfo = get_resource(binary_resource_type,ResBin1),
+ ResInfo = get_resource(binary_resource_type,ResBin2),
ResInfo.
-define(RT_CREATE,1).
-define(RT_TAKEOVER,2).
-resource_takeover(doc) -> ["Test resource takeover by module reload and upgrade"];
-resource_takeover(suite) -> [];
+%% Test resource takeover by module reload and upgrade
resource_takeover(Config) when is_list(Config) ->
TmpMem = tmpmem(),
ensure_lib_loaded(Config),
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "nif_mod"),
- ?line {ok,nif_mod,ModBin} = compile:file(File, [binary,return_errors]),
- ?line {module,nif_mod} = erlang:load_module(nif_mod,ModBin),
-
- ?line ok = nif_mod:load_nif_lib(Config, 1,
- [{resource_type, 0, ?RT_CREATE, "resource_type_A",resource_dtor_A,
- ?RT_CREATE},
- {resource_type, 1, ?RT_CREATE, "resource_type_null_A",null,
- ?RT_CREATE},
- {resource_type, 2, ?RT_CREATE bor ?RT_TAKEOVER, "resource_type_A_null",resource_dtor_A,
- ?RT_CREATE},
- {resource_type, 3, ?RT_CREATE, "resource_type_B_goneX",resource_dtor_B,
- ?RT_CREATE},
- {resource_type, 4, ?RT_CREATE, "resource_type_null_goneX",null,
- ?RT_CREATE},
- {resource_type, null, ?RT_TAKEOVER, "Pink unicorn", resource_dtor_A,
- ?RT_TAKEOVER}
- ]),
-
- ?line hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()),
- ?line [{load,1,1,101},{get_priv_data_ptr,1,2,102}] = nif_mod_call_history(),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "nif_mod"),
+ {ok,nif_mod,ModBin} = compile:file(File, [binary,return_errors]),
+ {module,nif_mod} = erlang:load_module(nif_mod,ModBin),
- ?line {Holder, _MRef} = spawn_opt(fun resource_holder/0, [link, monitor]),
+ ok = nif_mod:load_nif_lib(Config, 1,
+ [{resource_type, 0, ?RT_CREATE, "resource_type_A",resource_dtor_A,
+ ?RT_CREATE},
+ {resource_type, 1, ?RT_CREATE, "resource_type_null_A",null,
+ ?RT_CREATE},
+ {resource_type, 2, ?RT_CREATE bor ?RT_TAKEOVER, "resource_type_A_null",resource_dtor_A,
+ ?RT_CREATE},
+ {resource_type, 3, ?RT_CREATE, "resource_type_B_goneX",resource_dtor_B,
+ ?RT_CREATE},
+ {resource_type, 4, ?RT_CREATE, "resource_type_null_goneX",null,
+ ?RT_CREATE},
+ {resource_type, null, ?RT_TAKEOVER, "Pink unicorn", resource_dtor_A,
+ ?RT_TAKEOVER}
+ ]),
+
+ hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()),
+ [{load,1,1,101},{get_priv_data_ptr,1,2,102}] = nif_mod_call_history(),
+
+ {Holder, _MRef} = spawn_opt(fun resource_holder/0, [link, monitor]),
{A1,BinA1} = make_resource(0,Holder,"A1"),
{A2,BinA2} = make_resource(0,Holder,"A2"),
@@ -719,91 +682,91 @@ resource_takeover(Config) when is_list(Config) ->
{NGX1,_BinNGX1} = make_resource(4,Holder,"NGX1"),
{NGX2,_BinNGX2} = make_resource(4,Holder,"NGX2"),
- ?line [] = nif_mod_call_history(),
+ [] = nif_mod_call_history(),
- ?line ok = forget_resource(A1),
- ?line [{{resource_dtor_A_v1,BinA1},1,3,103}] = nif_mod_call_history(),
+ ok = forget_resource(A1),
+ [{{resource_dtor_A_v1,BinA1},1,3,103}] = nif_mod_call_history(),
- ?line ok = forget_resource(NA1),
- ?line [] = nif_mod_call_history(), % no dtor
+ ok = forget_resource(NA1),
+ [] = nif_mod_call_history(), % no dtor
- ?line ok = forget_resource(AN1),
+ ok = forget_resource(AN1),
?CHECK([{{resource_dtor_A_v1,BinAN1},1,4,104}] , nif_mod_call_history()),
- ?line ok = forget_resource(BGX1),
+ ok = forget_resource(BGX1),
?CHECK([{{resource_dtor_B_v1,BinBGX1},1,5,105}], nif_mod_call_history()),
- ?line ok = forget_resource(NGX1),
+ ok = forget_resource(NGX1),
?CHECK([], nif_mod_call_history()), % no dtor
- ?line ok = nif_mod:load_nif_lib(Config, 2,
- [{resource_type, 0, ?RT_TAKEOVER, "resource_type_A",resource_dtor_A,
- ?RT_TAKEOVER},
- {resource_type, 1, ?RT_TAKEOVER bor ?RT_CREATE, "resource_type_null_A",resource_dtor_A,
- ?RT_TAKEOVER},
- {resource_type, 2, ?RT_TAKEOVER, "resource_type_A_null",null,
- ?RT_TAKEOVER},
- {resource_type, null, ?RT_TAKEOVER, "Pink unicorn", resource_dtor_A,
- ?RT_TAKEOVER},
- {resource_type, null, ?RT_CREATE, "resource_type_B_goneX",resource_dtor_B,
- ?RT_CREATE},
- {resource_type, null, ?RT_CREATE, "resource_type_null_goneX",null,
- ?RT_CREATE},
- {resource_type, 3, ?RT_CREATE, "resource_type_B_goneY",resource_dtor_B,
- ?RT_CREATE},
- {resource_type, 4, ?RT_CREATE, "resource_type_null_goneY",null,
- ?RT_CREATE}
- ]),
+ ok = nif_mod:load_nif_lib(Config, 2,
+ [{resource_type, 0, ?RT_TAKEOVER, "resource_type_A",resource_dtor_A,
+ ?RT_TAKEOVER},
+ {resource_type, 1, ?RT_TAKEOVER bor ?RT_CREATE, "resource_type_null_A",resource_dtor_A,
+ ?RT_TAKEOVER},
+ {resource_type, 2, ?RT_TAKEOVER, "resource_type_A_null",null,
+ ?RT_TAKEOVER},
+ {resource_type, null, ?RT_TAKEOVER, "Pink unicorn", resource_dtor_A,
+ ?RT_TAKEOVER},
+ {resource_type, null, ?RT_CREATE, "resource_type_B_goneX",resource_dtor_B,
+ ?RT_CREATE},
+ {resource_type, null, ?RT_CREATE, "resource_type_null_goneX",null,
+ ?RT_CREATE},
+ {resource_type, 3, ?RT_CREATE, "resource_type_B_goneY",resource_dtor_B,
+ ?RT_CREATE},
+ {resource_type, 4, ?RT_CREATE, "resource_type_null_goneY",null,
+ ?RT_CREATE}
+ ]),
?CHECK([{reload,2,1,201}], nif_mod_call_history()),
- ?line BinA2 = read_resource(0,A2),
- ?line ok = forget_resource(A2),
+ BinA2 = read_resource(0,A2),
+ ok = forget_resource(A2),
?CHECK([{{resource_dtor_A_v2,BinA2},2,2,202}], nif_mod_call_history()),
- ?line ok = forget_resource(NA2),
+ ok = forget_resource(NA2),
?CHECK([{{resource_dtor_A_v2,BinNA2},2,3,203}], nif_mod_call_history()),
- ?line ok = forget_resource(AN2),
+ ok = forget_resource(AN2),
?CHECK([], nif_mod_call_history()), % no dtor
- ?line ok = forget_resource(BGX2), % calling dtor in orphan library v1 still loaded
+ ok = forget_resource(BGX2), % calling dtor in orphan library v1 still loaded
?CHECK([{{resource_dtor_B_v1,BinBGX2},1,6,106}], nif_mod_call_history()),
% How to test that lib v1 is closed here?
- ?line ok = forget_resource(NGX2),
+ ok = forget_resource(NGX2),
?CHECK([], nif_mod_call_history()), % no dtor
{BGY1,BinBGY1} = make_resource(3,Holder,"BGY1"),
{NGY1,_BinNGY1} = make_resource(4,Holder,"NGY1"),
%% Module upgrade with same lib-version
- ?line {module,nif_mod} = erlang:load_module(nif_mod,ModBin),
- ?line undefined = nif_mod:lib_version(),
- ?line ok = nif_mod:load_nif_lib(Config, 2,
- [{resource_type, 2, ?RT_TAKEOVER, "resource_type_A",resource_dtor_B,
- ?RT_TAKEOVER},
- {resource_type, 0, ?RT_TAKEOVER bor ?RT_CREATE, "resource_type_null_A",null,
- ?RT_TAKEOVER},
- {resource_type, 1, ?RT_TAKEOVER, "resource_type_A_null",resource_dtor_A,
- ?RT_TAKEOVER},
- {resource_type, null, ?RT_TAKEOVER, "Pink elephant", resource_dtor_A,
- ?RT_TAKEOVER},
- {resource_type, 3, ?RT_CREATE, "resource_type_B_goneZ",resource_dtor_B,
- ?RT_CREATE},
- {resource_type, 4, ?RT_CREATE, "resource_type_null_goneZ",null,
- ?RT_CREATE}
- ]),
-
- ?line 2 = nif_mod:lib_version(),
+ {module,nif_mod} = erlang:load_module(nif_mod,ModBin),
+ undefined = nif_mod:lib_version(),
+ ok = nif_mod:load_nif_lib(Config, 2,
+ [{resource_type, 2, ?RT_TAKEOVER, "resource_type_A",resource_dtor_B,
+ ?RT_TAKEOVER},
+ {resource_type, 0, ?RT_TAKEOVER bor ?RT_CREATE, "resource_type_null_A",null,
+ ?RT_TAKEOVER},
+ {resource_type, 1, ?RT_TAKEOVER, "resource_type_A_null",resource_dtor_A,
+ ?RT_TAKEOVER},
+ {resource_type, null, ?RT_TAKEOVER, "Pink elephant", resource_dtor_A,
+ ?RT_TAKEOVER},
+ {resource_type, 3, ?RT_CREATE, "resource_type_B_goneZ",resource_dtor_B,
+ ?RT_CREATE},
+ {resource_type, 4, ?RT_CREATE, "resource_type_null_goneZ",null,
+ ?RT_CREATE}
+ ]),
+
+ 2 = nif_mod:lib_version(),
?CHECK([{upgrade,2,4,204},{lib_version,2,5,205}], nif_mod_call_history()),
- ?line ok = forget_resource(A3),
+ ok = forget_resource(A3),
?CHECK([{{resource_dtor_B_v2,BinA3},2,6,206}], nif_mod_call_history()),
- ?line ok = forget_resource(NA3),
+ ok = forget_resource(NA3),
?CHECK([], nif_mod_call_history()),
- ?line ok = forget_resource(AN3),
+ ok = forget_resource(AN3),
?CHECK([{{resource_dtor_A_v2,BinAN3},2,7,207}], nif_mod_call_history()),
{A4,BinA4} = make_resource(2,Holder, "A4"),
@@ -813,19 +776,19 @@ resource_takeover(Config) when is_list(Config) ->
{BGZ1,BinBGZ1} = make_resource(3,Holder,"BGZ1"),
{NGZ1,_BinNGZ1} = make_resource(4,Holder,"NGZ1"),
- ?line false = code:purge(nif_mod),
- ?line [] = nif_mod_call_history(),
+ false = code:purge(nif_mod),
+ [] = nif_mod_call_history(),
- ?line ok = forget_resource(NGY1),
- ?line [] = nif_mod_call_history(),
+ ok = forget_resource(NGY1),
+ [] = nif_mod_call_history(),
- ?line ok = forget_resource(BGY1), % calling dtor in orphan library v2 still loaded
- ?line [{{resource_dtor_B_v2,BinBGY1},2,8,208},{unload,2,9,209}] = nif_mod_call_history(),
+ ok = forget_resource(BGY1), % calling dtor in orphan library v2 still loaded
+ [{{resource_dtor_B_v2,BinBGY1},2,8,208},{unload,2,9,209}] = nif_mod_call_history(),
%% Module upgrade with other lib-version
- ?line {module,nif_mod} = erlang:load_module(nif_mod,ModBin),
- ?line undefined = nif_mod:lib_version(),
- ?line ok = nif_mod:load_nif_lib(Config, 1,
+ {module,nif_mod} = erlang:load_module(nif_mod,ModBin),
+ undefined = nif_mod:lib_version(),
+ ok = nif_mod:load_nif_lib(Config, 1,
[{resource_type, 2, ?RT_TAKEOVER, "resource_type_A",resource_dtor_A,
?RT_TAKEOVER},
{resource_type, 0, ?RT_TAKEOVER bor ?RT_CREATE, "resource_type_null_A",resource_dtor_A,
@@ -836,28 +799,28 @@ resource_takeover(Config) when is_list(Config) ->
?RT_TAKEOVER}
]),
- ?line 1 = nif_mod:lib_version(),
- ?line [{upgrade,1,1,101},{lib_version,1,2,102}] = nif_mod_call_history(),
+ 1 = nif_mod:lib_version(),
+ [{upgrade,1,1,101},{lib_version,1,2,102}] = nif_mod_call_history(),
- %%?line false= check_process_code(Pid, nif_mod),
- ?line false = code:purge(nif_mod),
+ %%false= check_process_code(Pid, nif_mod),
+ false = code:purge(nif_mod),
%% no unload here as we still have instances with destructors
- ?line [] = nif_mod_call_history(),
+ [] = nif_mod_call_history(),
- ?line ok = forget_resource(BGZ1), % calling dtor in orphan library v2 still loaded
- ?line [{{resource_dtor_B_v2,BinBGZ1},2,10,210},{unload,2,11,211}] = nif_mod_call_history(),
+ ok = forget_resource(BGZ1), % calling dtor in orphan library v2 still loaded
+ [{{resource_dtor_B_v2,BinBGZ1},2,10,210},{unload,2,11,211}] = nif_mod_call_history(),
- ?line ok = forget_resource(NGZ1),
- ?line [] = nif_mod_call_history(),
+ ok = forget_resource(NGZ1),
+ [] = nif_mod_call_history(),
- ?line ok = forget_resource(A4),
- ?line [{{resource_dtor_A_v1,BinA4},1,3,103}] = nif_mod_call_history(),
+ ok = forget_resource(A4),
+ [{{resource_dtor_A_v1,BinA4},1,3,103}] = nif_mod_call_history(),
- ?line ok = forget_resource(NA4),
- ?line [{{resource_dtor_A_v1,BinNA4},1,4,104}] = nif_mod_call_history(),
+ ok = forget_resource(NA4),
+ [{{resource_dtor_A_v1,BinNA4},1,4,104}] = nif_mod_call_history(),
- ?line ok = forget_resource(AN4),
- ?line [] = nif_mod_call_history(),
+ ok = forget_resource(AN4),
+ [] = nif_mod_call_history(),
%%
@@ -979,8 +942,8 @@ resource_takeover(Config) when is_list(Config) ->
{return, 0} % SUCCESS
]),
- ?line hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()),
- ?line [{load,1,1,101},{get_priv_data_ptr,1,2,102}] = nif_mod_call_history(),
+ hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()),
+ [{load,1,1,101},{get_priv_data_ptr,1,2,102}] = nif_mod_call_history(),
{NA7,BinNA7} = make_resource(0, Holder, "NA7"),
{AN7,BinAN7} = make_resource(1, Holder, "AN7"),
@@ -991,15 +954,15 @@ resource_takeover(Config) when is_list(Config) ->
ok = forget_resource(AN7),
[] = nif_mod_call_history(),
- ?line true = lists:member(?MODULE, erlang:system_info(taints)),
- ?line true = lists:member(nif_mod, erlang:system_info(taints)),
- ?line verify_tmpmem(TmpMem),
+ true = lists:member(?MODULE, erlang:system_info(taints)),
+ true = lists:member(nif_mod, erlang:system_info(taints)),
+ verify_tmpmem(TmpMem),
ok.
make_resource(Type,Holder,Str) when is_list(Str) ->
Bin = list_to_binary(Str),
A1 = make_resource_do(Type,Holder,Bin),
- ?line Bin = read_resource(Type,A1),
+ Bin = read_resource(Type,A1),
{A1,Bin}.
make_resource_do(Type, Holder, Bin) ->
@@ -1026,7 +989,7 @@ resource_holder(List) ->
%%io:format("resource_holder got ~p with list = ~p\n", [Msg,List]),
case Msg of
{Pid, make, Type, Bin} ->
- ?line Resource = nif_mod:make_new_resource(Type, Bin),
+ Resource = nif_mod:make_new_resource(Type, Bin),
Id = {make_ref(),Bin},
Pid ! {self(), make_ok, Id},
resource_holder([{Id,Resource} | List]);
@@ -1048,7 +1011,7 @@ resource_holder(Pid,Reply,List) ->
resource_holder(List).
-threading(doc) -> ["Test the threading API functions (reuse tests from driver API)"];
+%% Test the threading API functions (reuse tests from driver API)
threading(Config) when is_list(Config) ->
case erlang:system_info(threads) of
true -> threading_do(Config);
@@ -1056,53 +1019,53 @@ threading(Config) when is_list(Config) ->
end.
threading_do(Config) ->
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "tester"),
- ?line {ok,tester,ModBin} = compile:file(File, [binary,return_errors]),
- ?line {module,tester} = erlang:load_module(tester,ModBin),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "tester"),
+ {ok,tester,ModBin} = compile:file(File, [binary,return_errors]),
+ {module,tester} = erlang:load_module(tester,ModBin),
- ?line ok = tester:load_nif_lib(Config, "basic"),
- ?line ok = tester:run(),
+ ok = tester:load_nif_lib(Config, "basic"),
+ ok = tester:run(),
- ?line ok = tester:load_nif_lib(Config, "rwlock"),
- ?line ok = tester:run(),
+ ok = tester:load_nif_lib(Config, "rwlock"),
+ ok = tester:run(),
- ?line ok = tester:load_nif_lib(Config, "tsd"),
- ?line ok = tester:run().
+ ok = tester:load_nif_lib(Config, "tsd"),
+ ok = tester:run().
-send(doc) -> ["Test NIF message sending"];
+%% Test NIF message sending
send(Config) when is_list(Config) ->
ensure_lib_loaded(Config),
N = 1500,
List = lists:seq(1,N),
- ?line {ok,1} = send_list_seq(N, self),
- ?line {ok,1} = send_list_seq(N, self()),
- ?line List = receive_any(),
- ?line List = receive_any(),
+ {ok,1} = send_list_seq(N, self),
+ {ok,1} = send_list_seq(N, self()),
+ List = receive_any(),
+ List = receive_any(),
Papa = self(),
- spawn_link(fun() -> ?line {ok,1} = send_list_seq(N, Papa) end),
- ?line List = receive_any(),
+ spawn_link(fun() -> {ok,1} = send_list_seq(N, Papa) end),
+ List = receive_any(),
- ?line {ok, 1, BlobS} = send_new_blob(self(), other_term()),
- ?line BlobR = receive_any(),
+ {ok, 1, BlobS} = send_new_blob(self(), other_term()),
+ BlobR = receive_any(),
io:format("Sent ~p\nGot ~p\n", [BlobS, BlobR]),
- ?line BlobR = BlobS,
+ BlobR = BlobS,
%% send to dead pid
{DeadPid, DeadMon} = spawn_monitor(fun() -> void end),
- ?line {'DOWN', DeadMon, process, DeadPid, normal} = receive_any(),
+ {'DOWN', DeadMon, process, DeadPid, normal} = receive_any(),
{ok,0} = send_list_seq(7, DeadPid),
ok.
-send2(doc) -> ["More NIF message sending"];
+%% More NIF message sending
send2(Config) when is_list(Config) ->
ensure_lib_loaded(Config),
send2_do1(fun send_blob_dbg/2),
ok.
-send_threaded(doc) -> ["Send msg from user thread"];
+%% Send msg from user thread
send_threaded(Config) when is_list(Config) ->
case erlang:system_info(smp_support) of
true ->
@@ -1123,44 +1086,44 @@ send2_do1(SendBlobF) ->
io:format("sending to forwarder pid=~p\n",[Forwarder]),
send2_do2(SendBlobF, Forwarder),
Forwarder ! terminate,
- ?line {Forwarder, 4} = receive_any(),
+ {Forwarder, 4} = receive_any(),
ok.
send2_do2(SendBlobF, To) ->
MsgEnv = alloc_msgenv(),
repeat(50, fun(_) -> grow_blob(MsgEnv,other_term()) end, []),
- ?line {ok,1,Blob0} = SendBlobF(MsgEnv, To),
- ?line Blob1 = receive_any(),
- ?line Blob1 = Blob0,
+ {ok,1,Blob0} = SendBlobF(MsgEnv, To),
+ Blob1 = receive_any(),
+ Blob1 = Blob0,
clear_msgenv(MsgEnv),
repeat(50, fun(_) -> grow_blob(MsgEnv,other_term()) end, []),
- ?line {ok,1,Blob2} = SendBlobF(MsgEnv, To),
- ?line Blob3 = receive_any(),
- ?line Blob3 = Blob2,
+ {ok,1,Blob2} = SendBlobF(MsgEnv, To),
+ Blob3 = receive_any(),
+ Blob3 = Blob2,
clear_msgenv(MsgEnv),
repeat(50, fun(_) -> grow_blob(MsgEnv,other_term()) end, []),
clear_msgenv(MsgEnv),
repeat(50, fun(_) -> grow_blob(MsgEnv,other_term()) end, []),
- ?line {ok,1,Blob4} = SendBlobF(MsgEnv, To),
- ?line Blob5 = receive_any(),
- ?line Blob5 = Blob4,
+ {ok,1,Blob4} = SendBlobF(MsgEnv, To),
+ Blob5 = receive_any(),
+ Blob5 = Blob4,
clear_msgenv(MsgEnv),
clear_msgenv(MsgEnv),
repeat(50, fun(_) -> grow_blob(MsgEnv,other_term()) end, []),
- ?line {ok,1,Blob6} = SendBlobF(MsgEnv, To),
- ?line Blob7 = receive_any(),
- ?line Blob7 = Blob6,
+ {ok,1,Blob6} = SendBlobF(MsgEnv, To),
+ Blob7 = receive_any(),
+ Blob7 = Blob6,
ok.
send_blob_thread_and_join(MsgEnv, To) ->
- ?line {ok,Blob} = send_blob_thread_dbg(MsgEnv, To, no_join),
- ?line {ok,SendRes} = join_send_thread(MsgEnv),
+ {ok,Blob} = send_blob_thread_dbg(MsgEnv, To, no_join),
+ {ok,SendRes} = join_send_thread(MsgEnv),
{ok,SendRes,Blob}.
send_blob_dbg(MsgEnv, To) ->
@@ -1188,21 +1151,18 @@ forwarder(To, N) ->
other_term() ->
{fun(X,Y) -> X*Y end, make_ref()}.
-send3(doc) -> ["Message sending stress test"];
+%% Message sending stress test
send3(Config) when is_list(Config) ->
%% Let a number of processes send random message blobs between each other
%% using enif_send. Kill and spawn new ones randomly to keep a ~constant
%% number of workers running.
- Seed = {erlang:monotonic_time(),
- erlang:time_offset(),
- erlang:unique_integer()},
- io:format("seed: ~p\n",[Seed]),
- random:seed(Seed),
+ rand:seed(exsplus),
+ io:format("seed: ~p\n",[rand:export_seed()]),
ets:new(nif_SUITE,[named_table,public]),
- ?line true = ets:insert(nif_SUITE,{send3,0,0,0,0}),
+ true = ets:insert(nif_SUITE,{send3,0,0,0,0}),
timer:send_after(10000, timeout), % Run for 10 seconds
SpawnCnt = send3_controller(0, [], [], 20),
- ?line [{_,Rcv,SndOk,SndFail,Balance}] = ets:lookup(nif_SUITE,send3),
+ [{_,Rcv,SndOk,SndFail,Balance}] = ets:lookup(nif_SUITE,send3),
io:format("spawns=~p received=~p, sent=~p send-failure=~p balance=~p\n",
[SpawnCnt,Rcv,SndOk,SndFail,Balance]),
ets:delete(nif_SUITE).
@@ -1230,13 +1190,13 @@ send3_controller(SpawnCnt0, Mons0, Pids0, Tick) ->
after Tick ->
Max = 20,
N = length(Pids0),
- PidN = random:uniform(Max),
+ PidN = rand:uniform(Max),
%%io:format("N=~p PidN=~p Pids0=~p\n", [N,PidN,Pids0]),
case PidN > N of
true ->
{NewPid,Mon} = spawn_opt(fun send3_proc/0, [link,monitor]),
lists:foreach(fun(P) -> P ! {is_born,NewPid} end, Pids0),
- ?line Balance = ets:lookup_element(nif_SUITE,send3,5),
+ Balance = ets:lookup_element(nif_SUITE,send3,5),
Inject = (Balance =< 0),
case Inject of
true -> ok;
@@ -1262,7 +1222,7 @@ send3_proc(Pids0, Counters={Rcv,SndOk,SndFail}, State0) ->
receive
{pids, Pids1, Inject} ->
%%io:format("~p: got ~p Inject=~p\n", [self(), Pids1, Inject]),
- ?line Pids0 = [self()],
+ Pids0 = [self()],
Pids2 = [self() | Pids1],
case Inject of
true -> send3_proc_send(Pids2, Counters, State0);
@@ -1294,7 +1254,7 @@ send3_proc(Pids0, Counters={Rcv,SndOk,SndFail}, State0) ->
end.
send3_proc_send(Pids, {Rcv,SndOk,SndFail}, State0) ->
- To = lists:nth(random:uniform(length(Pids)),Pids),
+ To = lists:nth(rand:uniform(length(Pids)),Pids),
Blob = send3_make_blob(),
State1 = send3_new_state(State0,Blob),
case send3_send(To, Blob) of
@@ -1306,12 +1266,12 @@ send3_proc_send(Pids, {Rcv,SndOk,SndFail}, State0) ->
send3_make_blob() ->
- case random:uniform(20)-1 of
+ case rand:uniform(20)-1 of
0 -> {term,[]};
N ->
MsgEnv = alloc_msgenv(),
repeat(N bsr 1,
- fun(_) -> grow_blob(MsgEnv,other_term(),random:uniform(1 bsl 20))
+ fun(_) -> grow_blob(MsgEnv,other_term(),rand:uniform(1 bsl 20))
end, void),
case (N band 1) of
0 -> {term,copy_blob(MsgEnv)};
@@ -1321,7 +1281,7 @@ send3_make_blob() ->
send3_send(Pid, Msg) ->
%% 90% enif_send and 10% normal bang
- case random:uniform(10) of
+ case rand:uniform(10) of
1 -> send3_send_bang(Pid,Msg);
_ -> send3_send_nif(Pid,Msg)
end.
@@ -1342,103 +1302,103 @@ send3_send_bang(Pid, {msgenv,MsgEnv}) ->
true.
send3_new_state(State, Blob) ->
- case random:uniform(5+2) of
+ case rand:uniform(5+2) of
N when N =< 5-> setelement(N, State, Blob);
_ -> State % Don't store blob
end.
-neg(doc) -> ["Negative testing of load_nif"];
+%% Negative testing of load_nif
neg(Config) when is_list(Config) ->
TmpMem = tmpmem(),
- ?line {'EXIT',{badarg,_}} = (catch erlang:load_nif(badarg, 0)),
- ?line {error,{load_failed,_}} = erlang:load_nif("pink_unicorn", 0),
+ {'EXIT',{badarg,_}} = (catch erlang:load_nif(badarg, 0)),
+ {error,{load_failed,_}} = erlang:load_nif("pink_unicorn", 0),
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "nif_mod"),
- ?line {ok,nif_mod,Bin} = compile:file(File, [binary,return_errors]),
- ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "nif_mod"),
+ {ok,nif_mod,Bin} = compile:file(File, [binary,return_errors]),
+ {module,nif_mod} = erlang:load_module(nif_mod,Bin),
- ?line {error,{bad_lib,_}} = nif_mod:load_nif_lib(Config, no_init),
- ?line verify_tmpmem(TmpMem),
- ?line ok.
+ {error,{bad_lib,_}} = nif_mod:load_nif_lib(Config, no_init),
+ verify_tmpmem(TmpMem),
+ ok.
-is_checks(doc) -> ["Test all enif_is functions"];
+%% Test all enif_is functions
is_checks(Config) when is_list(Config) ->
- ?line ensure_lib_loaded(Config, 1),
- ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ ensure_lib_loaded(Config, 1),
+ ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
self(), hd(erlang:ports()), [], [1,9,9,8],
{hejsan, "hejsan", [$h,"ejs",<<"an">>]}, 12),
- ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
self(), hd(erlang:ports()), [], [1,9,9,8],
{hejsan, "hejsan", [$h,"ejs",<<"an">>]}, -12),
- ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
self(), hd(erlang:ports()), [], [1,9,9,8],
{hejsan, "hejsan", [$h,"ejs",<<"an">>]}, 18446744073709551617),
- ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
self(), hd(erlang:ports()), [], [1,9,9,8],
{hejsan, "hejsan", [$h,"ejs",<<"an">>]}, -18446744073709551617),
- ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
self(), hd(erlang:ports()), [], [1,9,9,8],
{hejsan, "hejsan", [$h,"ejs",<<"an">>]}, 99.146),
- ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
self(), hd(erlang:ports()), [], [1,9,9,8],
{hejsan, "hejsan", [$h,"ejs",<<"an">>]}, -99.146),
- ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
self(), hd(erlang:ports()), [], [1,9,9,8],
{hejsan, "hejsan", [$h,"ejs",<<"an">>]}, 18446744073709551616.2e2),
- ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
+ ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end,
self(), hd(erlang:ports()), [], [1,9,9,8],
{hejsan, "hejsan", [$h,"ejs",<<"an">>]}, -18446744073709551616.2e2),
try
- ?line check_is_exception(),
- ?line throw(expected_badarg)
+ check_is_exception(),
+ throw(expected_badarg)
catch
error:badarg ->
- ?line ok
+ ok
end.
-get_length(doc) -> ["Test all enif_get_length functions"];
+%% Test all enif_get_length functions
get_length(Config) when is_list(Config) ->
- ?line ensure_lib_loaded(Config, 1),
- ?line ok = length_test(hejsan, "hejsan", [], [], not_a_list).
+ ensure_lib_loaded(Config, 1),
+ ok = length_test(hejsan, "hejsan", [], [], not_a_list, [1,2|3]).
ensure_lib_loaded(Config) ->
ensure_lib_loaded(Config, 1).
ensure_lib_loaded(Config, Ver) ->
- ?line case lib_version() of
+ case lib_version() of
undefined ->
- ?line Path = ?config(data_dir, Config),
- ?line Lib = "nif_SUITE." ++ integer_to_list(Ver),
- ?line ok = erlang:load_nif(filename:join(Path,Lib), []);
+ Path = proplists:get_value(data_dir, Config),
+ Lib = "nif_SUITE." ++ integer_to_list(Ver),
+ ok = erlang:load_nif(filename:join(Path,Lib), []);
Ver when is_integer(Ver) ->
ok
end.
make_atom(Config) when is_list(Config) ->
- ?line ensure_lib_loaded(Config, 1),
+ ensure_lib_loaded(Config, 1),
An0Atom = an0atom,
An0Atom0 = 'an\000atom\000',
- ?line Atoms = make_atoms(),
- ?line 7 = size(Atoms),
- ?line Atoms = {An0Atom,An0Atom,An0Atom,An0Atom0,An0Atom,An0Atom,An0Atom0}.
+ Atoms = make_atoms(),
+ 7 = size(Atoms),
+ Atoms = {An0Atom,An0Atom,An0Atom,An0Atom0,An0Atom,An0Atom,An0Atom0}.
make_string(Config) when is_list(Config) ->
- ?line ensure_lib_loaded(Config, 1),
- ?line Strings = make_strings(),
- ?line 5 = size(Strings),
+ ensure_lib_loaded(Config, 1),
+ Strings = make_strings(),
+ 5 = size(Strings),
A0String = "a0string",
A0String0 = [$a,0,$s,$t,$r,$i,$n,$g,0],
AStringWithAccents = [$E,$r,$l,$a,$n,$g,$ ,16#e4,$r,$ ,$e,$t,$t,$ ,$g,$e,$n,$e,$r,$e,$l,$l,$t,$ ,$p,$r,$o,$g,$r,$a,$m,$s,$p,$r,16#e5,$k],
- ?line Strings = {A0String,A0String,A0String,A0String0, AStringWithAccents}.
+ Strings = {A0String,A0String,A0String,A0String0, AStringWithAccents}.
reverse_list_test(Config) ->
- ?line ensure_lib_loaded(Config, 1),
+ ensure_lib_loaded(Config, 1),
List = lists:seq(1,100),
RevList = lists:reverse(List),
- ?line RevList = reverse_list(List),
- ?line badarg = reverse_list(foo).
+ RevList = reverse_list(List),
+ badarg = reverse_list(foo).
-otp_9668(doc) -> ["Memory leak of tmp-buffer when inspecting iolist or unaligned binary in unbound environment"];
+%% Memory leak of tmp-buffer when inspecting iolist or unaligned binary in unbound environment
otp_9668(Config) ->
ensure_lib_loaded(Config, 1),
TmpMem = tmpmem(),
@@ -1448,13 +1408,12 @@ otp_9668(Config) ->
<<_:5/bitstring,UnalignedBin:10/binary,_/bitstring>> = <<"Abuse me as unaligned">>,
otp_9668_nif(UnalignedBin),
- ?line verify_tmpmem(TmpMem),
+ verify_tmpmem(TmpMem),
ok.
-otp_9828(doc) -> ["Copy of writable binary"];
+%% Copy of writable binary
otp_9828(Config) ->
ensure_lib_loaded(Config, 1),
-
otp_9828_loop(<<"I'm alive!">>, 1000).
otp_9828_loop(Bin, 0) ->
@@ -1473,68 +1432,68 @@ consume_timeslice(Config) when is_list(Config) ->
Done = make_ref(),
DummyMFA = {?MODULE,dummy_call,1},
P = spawn(fun () ->
- receive Go -> ok end,
- {reductions, R1} = process_info(self(), reductions),
- 1 = consume_timeslice_nif(100, false),
- dummy_call(111),
- 0 = consume_timeslice_nif(90, false),
- dummy_call(222),
- 1 = consume_timeslice_nif(10, false),
- dummy_call(333),
- 0 = consume_timeslice_nif(25, false),
- 0 = consume_timeslice_nif(25, false),
- 0 = consume_timeslice_nif(25, false),
- 1 = consume_timeslice_nif(25, false),
- 0 = consume_timeslice_nif(25, false),
-
- ok = case consume_timeslice_nif(1, true) of
- Cnt when Cnt > 70, Cnt < 80 -> ok;
- Other -> Other
- end,
- dummy_call(444),
-
- {reductions, R2} = process_info(self(), reductions),
- Me ! {RedDiff, R2 - R1},
- exit(Done)
- end),
+ receive Go -> ok end,
+ {reductions, R1} = process_info(self(), reductions),
+ 1 = consume_timeslice_nif(100, false),
+ dummy_call(111),
+ 0 = consume_timeslice_nif(90, false),
+ dummy_call(222),
+ 1 = consume_timeslice_nif(10, false),
+ dummy_call(333),
+ 0 = consume_timeslice_nif(25, false),
+ 0 = consume_timeslice_nif(25, false),
+ 0 = consume_timeslice_nif(25, false),
+ 1 = consume_timeslice_nif(25, false),
+ 0 = consume_timeslice_nif(25, false),
+
+ ok = case consume_timeslice_nif(1, true) of
+ Cnt when Cnt > 70, Cnt < 80 -> ok;
+ Other -> Other
+ end,
+ dummy_call(444),
+
+ {reductions, R2} = process_info(self(), reductions),
+ Me ! {RedDiff, R2 - R1},
+ exit(Done)
+ end),
erlang:yield(),
erlang:trace_pattern(DummyMFA, [], [local]),
- ?line 1 = erlang:trace(P, true, [call, running, procs, {tracer, self()}]),
+ 1 = erlang:trace(P, true, [call, running, procs, {tracer, self()}]),
P ! Go,
%% receive Go -> ok end,
- ?line {trace, P, in, _} = next_tmsg(P),
+ {trace, P, in, _} = next_tmsg(P),
%% consume_timeslice_nif(100),
%% dummy_call(111)
- ?line {trace, P, out, _} = next_tmsg(P),
- ?line {trace, P, in, _} = next_tmsg(P),
- ?line {trace, P, call, {?MODULE,dummy_call,[111]}} = next_tmsg(P),
+ {trace, P, out, _} = next_tmsg(P),
+ {trace, P, in, _} = next_tmsg(P),
+ {trace, P, call, {?MODULE,dummy_call,[111]}} = next_tmsg(P),
%% consume_timeslice_nif(90),
%% dummy_call(222)
- ?line {trace, P, call, {?MODULE,dummy_call,[222]}} = next_tmsg(P),
+ {trace, P, call, {?MODULE,dummy_call,[222]}} = next_tmsg(P),
%% consume_timeslice_nif(10),
%% dummy_call(333)
- ?line {trace, P, out, _} = next_tmsg(P),
- ?line {trace, P, in, _} = next_tmsg(P),
- ?line {trace, P, call, {?MODULE,dummy_call,[333]}} = next_tmsg(P),
+ {trace, P, out, _} = next_tmsg(P),
+ {trace, P, in, _} = next_tmsg(P),
+ {trace, P, call, {?MODULE,dummy_call,[333]}} = next_tmsg(P),
%% 25,25,25,25, 25
- ?line {trace, P, out, {?MODULE,consume_timeslice_nif,2}} = next_tmsg(P),
- ?line {trace, P, in, {?MODULE,consume_timeslice_nif,2}} = next_tmsg(P),
+ {trace, P, out, {?MODULE,consume_timeslice_nif,2}} = next_tmsg(P),
+ {trace, P, in, {?MODULE,consume_timeslice_nif,2}} = next_tmsg(P),
%% consume_timeslice(1,true)
%% dummy_call(444)
- ?line {trace, P, out, DummyMFA} = next_tmsg(P),
- ?line {trace, P, in, DummyMFA} = next_tmsg(P),
- ?line {trace, P, call, {?MODULE,dummy_call,[444]}} = next_tmsg(P),
+ {trace, P, out, DummyMFA} = next_tmsg(P),
+ {trace, P, in, DummyMFA} = next_tmsg(P),
+ {trace, P, call, {?MODULE,dummy_call,[444]}} = next_tmsg(P),
%% exit(Done)
- ?line {trace, P, exit, Done} = next_tmsg(P),
+ {trace, P, exit, Done} = next_tmsg(P),
ExpReds = (100 + 90 + 10 + 25*5 + 75) * CONTEXT_REDS div 100,
receive
@@ -1542,7 +1501,7 @@ consume_timeslice(Config) when is_list(Config) ->
io:format("Reductions = ~p~n", [Reductions]),
ok;
{RedDiff, Reductions} ->
- ?t:fail({unexpected_reduction_count, Reductions})
+ ct:fail({unexpected_reduction_count, Reductions})
end,
none = next_msg(P),
@@ -1599,38 +1558,38 @@ dirty_nif_send(Config) when is_list(Config) ->
dirty_nif_exception(Config) when is_list(Config) ->
try erlang:system_info(dirty_cpu_schedulers) of
- N when is_integer(N) ->
- ensure_lib_loaded(Config),
- try
- %% this checks that the expected exception occurs when the
- %% dirty NIF returns the result of enif_make_badarg
- %% directly
- call_dirty_nif_exception(1),
- ?t:fail(expected_badarg)
- catch
- error:badarg ->
- [{?MODULE,call_dirty_nif_exception,[1],_}|_] =
- erlang:get_stacktrace(),
- ok
- end,
- try
- %% this checks that the expected exception occurs when the
- %% dirty NIF calls enif_make_badarg at some point but then
- %% returns a value that isn't an exception
- call_dirty_nif_exception(0),
- ?t:fail(expected_badarg)
- catch
- error:badarg ->
- [{?MODULE,call_dirty_nif_exception,[0],_}|_] =
- erlang:get_stacktrace(),
- ok
- end,
- %% this checks that a dirty NIF can raise various terms as
- %% exceptions
- ok = nif_raise_exceptions(call_dirty_nif_exception)
+ N when is_integer(N) ->
+ ensure_lib_loaded(Config),
+ try
+ %% this checks that the expected exception occurs when the
+ %% dirty NIF returns the result of enif_make_badarg
+ %% directly
+ call_dirty_nif_exception(1),
+ ct:fail(expected_badarg)
+ catch
+ error:badarg ->
+ [{?MODULE,call_dirty_nif_exception,[1],_}|_] =
+ erlang:get_stacktrace(),
+ ok
+ end,
+ try
+ %% this checks that the expected exception occurs when the
+ %% dirty NIF calls enif_make_badarg at some point but then
+ %% returns a value that isn't an exception
+ call_dirty_nif_exception(0),
+ ct:fail(expected_badarg)
+ catch
+ error:badarg ->
+ [{?MODULE,call_dirty_nif_exception,[0],_}|_] =
+ erlang:get_stacktrace(),
+ ok
+ end,
+ %% this checks that a dirty NIF can raise various terms as
+ %% exceptions
+ ok = nif_raise_exceptions(call_dirty_nif_exception)
catch
- error:badarg ->
- {skipped,"No dirty scheduler support"}
+ error:badarg ->
+ {skipped,"No dirty scheduler support"}
end.
nif_exception(Config) when is_list(Config) ->
@@ -1640,7 +1599,7 @@ nif_exception(Config) when is_list(Config) ->
%% calls enif_make_badarg at some point but then tries to return a
%% value that isn't an exception
call_nif_exception(0),
- ?t:fail(expected_badarg)
+ ct:fail(expected_badarg)
catch
error:badarg ->
ok
@@ -1653,21 +1612,21 @@ nif_nan_and_inf(Config) when is_list(Config) ->
ensure_lib_loaded(Config),
try
call_nif_nan_or_inf(nan),
- ?t:fail(expected_badarg)
+ ct:fail(expected_badarg)
catch
error:badarg ->
ok
end,
try
call_nif_nan_or_inf(inf),
- ?t:fail(expected_badarg)
+ ct:fail(expected_badarg)
catch
error:badarg ->
ok
end,
try
call_nif_nan_or_inf(tuple),
- ?t:fail(expected_badarg)
+ ct:fail(expected_badarg)
catch
error:badarg ->
ok
@@ -1677,14 +1636,14 @@ nif_atom_too_long(Config) when is_list(Config) ->
ensure_lib_loaded(Config),
try
call_nif_atom_too_long(all),
- ?t:fail(expected_badarg)
+ ct:fail(expected_badarg)
catch
error:badarg ->
ok
end,
try
call_nif_atom_too_long(len),
- ?t:fail(expected_badarg)
+ ct:fail(expected_badarg)
catch
error:badarg ->
ok
@@ -1692,19 +1651,19 @@ nif_atom_too_long(Config) when is_list(Config) ->
next_msg(_Pid) ->
receive
- M -> M
+ M -> M
after 100 ->
- none
+ none
end.
next_tmsg(Pid) ->
receive TMsg when is_tuple(TMsg),
- element(1, TMsg) == trace,
- element(2, TMsg) == Pid ->
- TMsg
- after 100 ->
- none
- end.
+ element(1, TMsg) == trace,
+ element(2, TMsg) == Pid ->
+ TMsg
+ after 100 ->
+ none
+ end.
dummy_call(_) ->
ok.
@@ -1744,9 +1703,7 @@ verify_tmpmem(MemInfo) ->
ok
end;
Other ->
- io:format("Expected: ~p", [MemInfo]),
- io:format("Actual: ~p", [Other]),
- ?t:fail()
+ ct:fail("Expected: ~p\nActual: ~p", [MemInfo, Other])
end.
call(Pid,Cmd) ->
@@ -1774,17 +1731,17 @@ check(Exp,Got,Line) ->
nif_raise_exceptions(NifFunc) ->
ExcTerms = [{error, test}, "a string", <<"a binary">>,
- 42, [1,2,3,4,5], [{p,1},{p,2},{p,3}]],
+ 42, [1,2,3,4,5], [{p,1},{p,2},{p,3}]],
lists:foldl(fun(Term, ok) ->
- try
- erlang:apply(?MODULE,NifFunc,[Term]),
- ?t:fail({expected,Term})
- catch
- error:Term ->
- [{?MODULE,NifFunc,[Term],_}|_] = erlang:get_stacktrace(),
- ok
- end
- end, ok, ExcTerms).
+ try
+ erlang:apply(?MODULE,NifFunc,[Term]),
+ ct:fail({expected,Term})
+ catch
+ error:Term ->
+ [{?MODULE,NifFunc,[Term],_}|_] = erlang:get_stacktrace(),
+ ok
+ end
+ end, ok, ExcTerms).
-define(ERL_NIF_TIME_ERROR, -9223372036854775808).
-define(TIME_UNITS, [seconds, milli_seconds, micro_seconds, nano_seconds]).
@@ -1810,7 +1767,7 @@ chk_mtime([TU|TUs]) ->
true = B =< C
catch
_ : _ ->
- ?t:fail({monotonic_time_missmatch, TU, A, B, C})
+ ct:fail({monotonic_time_missmatch, TU, A, B, C})
end,
chk_mtime(TUs).
@@ -1830,25 +1787,25 @@ chk_toffs([TU|TUs]) ->
TO = erlang:time_offset(TU),
NifTO = time_offset(TU),
case TO =:= NifTO of
- true ->
- ok;
- false ->
- case erlang:system_info(time_warp_mode) of
- no_time_warp ->
- ?t:fail({time_offset_mismatch, TU, TO, NifTO});
- _ ->
- %% Most frequent time offset change
- %% is currently only every 15:th
- %% second so this should currently
- %% work...
- NTO = erlang:time_offset(TU),
- case NifTO =:= NTO of
- true ->
- ok;
- false ->
- ?t:fail({time_offset_mismatch, TU, TO, NifTO, NTO})
- end
- end
+ true ->
+ ok;
+ false ->
+ case erlang:system_info(time_warp_mode) of
+ no_time_warp ->
+ ct:fail({time_offset_mismatch, TU, TO, NifTO});
+ _ ->
+ %% Most frequent time offset change
+ %% is currently only every 15:th
+ %% second so this should currently
+ %% work...
+ NTO = erlang:time_offset(TU),
+ case NifTO =:= NTO of
+ true ->
+ ok;
+ false ->
+ ct:fail({time_offset_mismatch, TU, TO, NifTO, NTO})
+ end
+ end
end,
chk_toffs(TUs).
@@ -1857,47 +1814,47 @@ nif_convert_time_unit(Config) ->
?ERL_NIF_TIME_ERROR = convert_time_unit(0, invalid_time_unit, seconds),
?ERL_NIF_TIME_ERROR = convert_time_unit(0, invalid_time_unit, invalid_time_unit),
lists:foreach(fun (Offset) ->
- lists:foreach(fun (Diff) ->
- chk_ctu(Diff+(Offset*1000*1000*1000))
- end,
- [999999999999,
- 99999999999,
- 9999999999,
- 999999999,
- 99999999,
- 9999999,
- 999999,
- 99999,
- 999,
- 99,
- 9,
- 1,
- 11,
- 101,
- 1001,
- 10001,
- 100001,
- 1000001,
- 10000001,
- 100000001,
- 1000000001,
- 100000000001,
- 1000000000001,
- 5,
- 50,
- 500,
- 5000,
- 50000,
- 500000,
- 5000000,
- 50000000,
- 500000000,
- 5000000000,
- 50000000000,
- 500000000000])
- end,
- [-4711, -1000, -475, -5, -4, -3, -2, -1, 0,
- 1, 2, 3, 4, 5, 475, 1000, 4711]),
+ lists:foreach(fun (Diff) ->
+ chk_ctu(Diff+(Offset*1000*1000*1000))
+ end,
+ [999999999999,
+ 99999999999,
+ 9999999999,
+ 999999999,
+ 99999999,
+ 9999999,
+ 999999,
+ 99999,
+ 999,
+ 99,
+ 9,
+ 1,
+ 11,
+ 101,
+ 1001,
+ 10001,
+ 100001,
+ 1000001,
+ 10000001,
+ 100000001,
+ 1000000001,
+ 100000000001,
+ 1000000000001,
+ 5,
+ 50,
+ 500,
+ 5000,
+ 50000,
+ 500000,
+ 5000000,
+ 50000000,
+ 500000000,
+ 5000000000,
+ 50000000000,
+ 500000000000])
+ end,
+ [-4711, -1000, -475, -5, -4, -3, -2, -1, 0,
+ 1, 2, 3, 4, 5, 475, 1000, 4711]),
ctu_loop(1000000).
ctu_loop(0) ->
@@ -1923,7 +1880,7 @@ chk_ctu(Time, FromTU, [ToTU|ToTUs]) ->
TN = convert_time_unit(T, FromTU, ToTU),
case TE =:= TN of
false ->
- ?t:fail({conversion_mismatch, FromTU, T, ToTU, TE, TN});
+ ct:fail({conversion_mismatch, FromTU, T, ToTU, TE, TN});
true ->
chk_ctu(Time, FromTU, ToTUs)
end.
@@ -1955,7 +1912,7 @@ last_resource_dtor_call() -> ?nif_stub.
make_new_resource(_,_) -> ?nif_stub.
check_is(_,_,_,_,_,_,_,_,_,_,_) -> ?nif_stub.
check_is_exception() -> ?nif_stub.
-length_test(_,_,_,_,_) -> ?nif_stub.
+length_test(_,_,_,_,_,_) -> ?nif_stub.
make_atoms() -> ?nif_stub.
make_strings() -> ?nif_stub.
make_new_resource_binary(_) -> ?nif_stub.
diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
index 8ebce4fef4..1acb270d1f 100644
--- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
+++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
@@ -914,6 +914,7 @@ static ERL_NIF_TERM check_is_exception(ErlNifEnv* env, int argc, const ERL_NIF_T
* argv[2] empty list
* argv[3] not an atom
* argv[4] not a list
+ * argv[5] improper list
*/
static ERL_NIF_TERM length_test(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
@@ -934,6 +935,9 @@ static ERL_NIF_TERM length_test(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
if (enif_get_list_length(env, argv[4], &len))
return enif_make_badarg(env);
+ if (enif_get_list_length(env, argv[5], &len))
+ return enif_make_badarg(env);
+
return enif_make_atom(env, "ok");
}
@@ -2002,7 +2006,7 @@ static ErlNifFunc nif_funcs[] =
{"make_new_resource", 2, make_new_resource},
{"check_is", 11, check_is},
{"check_is_exception", 0, check_is_exception},
- {"length_test", 5, length_test},
+ {"length_test", 6, length_test},
{"make_atoms", 0, make_atoms},
{"make_strings", 0, make_strings},
{"make_new_resource", 2, make_new_resource},
diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.erl b/erts/emulator/test/nif_SUITE_data/nif_mod.erl
index e65d4577c7..b6de046388 100644
--- a/erts/emulator/test/nif_SUITE_data/nif_mod.erl
+++ b/erts/emulator/test/nif_SUITE_data/nif_mod.erl
@@ -20,7 +20,7 @@
-module(nif_mod).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([load_nif_lib/2, load_nif_lib/3, start/0, lib_version/0, call_history/0,
get_priv_data_ptr/0, make_new_resource/2, get_resource/2]).
@@ -33,7 +33,7 @@ load_nif_lib(Config, Ver) ->
load_nif_lib(Config, Ver, []).
load_nif_lib(Config, Ver, LoadInfo) ->
- ?line Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
erlang:load_nif(filename:join(Path,libname(Ver)), LoadInfo).
libname(no_init) -> libname(3);
diff --git a/erts/emulator/test/nif_SUITE_data/tester.erl b/erts/emulator/test/nif_SUITE_data/tester.erl
index b393e29b82..f955f99c9a 100644
--- a/erts/emulator/test/nif_SUITE_data/tester.erl
+++ b/erts/emulator/test/nif_SUITE_data/tester.erl
@@ -1,12 +1,11 @@
-module(tester).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([load_nif_lib/2, run/0]).
-
load_nif_lib(Config, LibName) ->
- ?line Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
erlang:load_nif(filename:join(Path,LibName), []).
run() ->
diff --git a/erts/emulator/test/node_container_SUITE.erl b/erts/emulator/test/node_container_SUITE.erl
index fecaad5232..71400142af 100644
--- a/erts/emulator/test/node_container_SUITE.erl
+++ b/erts/emulator/test/node_container_SUITE.erl
@@ -30,35 +30,34 @@
%-define(line_trace, 1).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-%-compile(export_all).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2, init_per_testcase/2,
- end_per_testcase/2,
- node_container_refc_check/1]).
+-export([all/0, suite/0, init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2,
+ node_container_refc_check/1]).
-export([term_to_binary_to_term_eq/1,
- round_trip_eq/1,
- cmp/1,
- ref_eq/1,
- node_table_gc/1,
- dist_link_refc/1,
- dist_monitor_refc/1,
- node_controller_refc/1,
- ets_refc/1,
- match_spec_refc/1,
- timer_refc/1,
- otp_4715/1,
- pid_wrap/1,
- port_wrap/1,
- bad_nc/1,
- unique_pid/1,
- iter_max_procs/1]).
-
--define(DEFAULT_TIMEOUT, ?t:minutes(10)).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+ round_trip_eq/1,
+ cmp/1,
+ ref_eq/1,
+ node_table_gc/1,
+ dist_link_refc/1,
+ dist_monitor_refc/1,
+ node_controller_refc/1,
+ ets_refc/1,
+ match_spec_refc/1,
+ timer_refc/1,
+ otp_4715/1,
+ pid_wrap/1,
+ port_wrap/1,
+ bad_nc/1,
+ unique_pid/1,
+ iter_max_procs/1]).
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 10}}].
+
all() ->
[term_to_binary_to_term_eq, round_trip_eq, cmp, ref_eq,
@@ -67,9 +66,6 @@ all() ->
timer_refc, otp_4715, pid_wrap, port_wrap, bad_nc,
unique_pid, iter_max_procs].
-groups() ->
- [].
-
init_per_suite(Config) ->
Config.
@@ -78,36 +74,26 @@ end_per_suite(_Config) ->
erts_debug:set_internal_state(node_tab_delayed_delete, -1), %% restore original value
available_internal_state(false).
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
available_internal_state(Bool) when Bool == true; Bool == false ->
case {Bool,
- (catch erts_debug:get_internal_state(available_internal_state))} of
- {true, true} ->
- true;
- {false, true} ->
- erts_debug:set_internal_state(available_internal_state, false),
- true;
- {true, _} ->
- erts_debug:set_internal_state(available_internal_state, true),
- false;
- {false, _} ->
- false
+ (catch erts_debug:get_internal_state(available_internal_state))} of
+ {true, true} ->
+ true;
+ {false, true} ->
+ erts_debug:set_internal_state(available_internal_state, false),
+ true;
+ {true, _} ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ false;
+ {false, _} ->
+ false
end.
init_per_testcase(_Case, Config) when is_list(Config) ->
- Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
available_internal_state(true),
- [{watchdog, Dog}|Config].
+ Config.
end_per_testcase(_Case, Config) when is_list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
ok.
%%%
@@ -119,111 +105,103 @@ end_per_testcase(_Case, Config) when is_list(Config) ->
%%
%% Test case: term_to_binary_to_term_eq
%%
-term_to_binary_to_term_eq(doc) ->
- ["Tests that node container terms that are converted to external format "
- "and back stay equal to themselves."];
-term_to_binary_to_term_eq(suite) -> [];
+%% Tests that node container terms that are converted to external format
+%% and back stay equal to themselves.
term_to_binary_to_term_eq(Config) when is_list(Config) ->
- ?line ThisNode = {node(), erlang:system_info(creation)},
+ ThisNode = {node(), erlang:system_info(creation)},
% Get local node containers
- ?line LPid = self(),
- ?line LXPid = mk_pid(ThisNode, 32767, 8191),
- ?line LPort = hd(erlang:ports()),
- ?line LXPort = mk_port(ThisNode, 268435455),
- ?line LLRef = make_ref(),
- ?line LHLRef = mk_ref(ThisNode, [47, 11]),
- ?line LSRef = mk_ref(ThisNode, [4711]),
+ LPid = self(),
+ LXPid = mk_pid(ThisNode, 32767, 8191),
+ LPort = hd(erlang:ports()),
+ LXPort = mk_port(ThisNode, 268435455),
+ LLRef = make_ref(),
+ LHLRef = mk_ref(ThisNode, [47, 11]),
+ LSRef = mk_ref(ThisNode, [4711]),
% Test local nc:s
- ?line LPid = binary_to_term(term_to_binary(LPid)),
- ?line LXPid = binary_to_term(term_to_binary(LXPid)),
- ?line LPort = binary_to_term(term_to_binary(LPort)),
- ?line LXPort = binary_to_term(term_to_binary(LXPort)),
- ?line LLRef = binary_to_term(term_to_binary(LLRef)),
- ?line LHLRef = binary_to_term(term_to_binary(LHLRef)),
- ?line LSRef = binary_to_term(term_to_binary(LSRef)),
+ LPid = binary_to_term(term_to_binary(LPid)),
+ LXPid = binary_to_term(term_to_binary(LXPid)),
+ LPort = binary_to_term(term_to_binary(LPort)),
+ LXPort = binary_to_term(term_to_binary(LXPort)),
+ LLRef = binary_to_term(term_to_binary(LLRef)),
+ LHLRef = binary_to_term(term_to_binary(LHLRef)),
+ LSRef = binary_to_term(term_to_binary(LSRef)),
% Get remote node containers
- ?line RNode = {get_nodename(), 3},
- ?line RPid = mk_pid(RNode, 4711, 1),
- ?line RXPid = mk_pid(RNode, 32767, 8191),
- ?line RPort = mk_port(RNode, 4711),
- ?line RXPort = mk_port(RNode, 268435455),
- ?line RLRef = mk_ref(RNode, [4711, 4711, 4711]),
- ?line RHLRef = mk_ref(RNode, [4711, 4711]),
- ?line RSRef = mk_ref(RNode, [4711]),
+ RNode = {get_nodename(), 3},
+ RPid = mk_pid(RNode, 4711, 1),
+ RXPid = mk_pid(RNode, 32767, 8191),
+ RPort = mk_port(RNode, 4711),
+ RXPort = mk_port(RNode, 268435455),
+ RLRef = mk_ref(RNode, [4711, 4711, 4711]),
+ RHLRef = mk_ref(RNode, [4711, 4711]),
+ RSRef = mk_ref(RNode, [4711]),
% Test remote nc:s
- ?line RPid = binary_to_term(term_to_binary(RPid)),
- ?line RXPid = binary_to_term(term_to_binary(RXPid)),
- ?line RPort = binary_to_term(term_to_binary(RPort)),
- ?line RXPort = binary_to_term(term_to_binary(RXPort)),
- ?line RLRef = binary_to_term(term_to_binary(RLRef)),
- ?line RHLRef = binary_to_term(term_to_binary(RHLRef)),
- ?line RSRef = binary_to_term(term_to_binary(RSRef)),
- ?line nc_refc_check(node()),
- ?line ok.
+ RPid = binary_to_term(term_to_binary(RPid)),
+ RXPid = binary_to_term(term_to_binary(RXPid)),
+ RPort = binary_to_term(term_to_binary(RPort)),
+ RXPort = binary_to_term(term_to_binary(RXPort)),
+ RLRef = binary_to_term(term_to_binary(RLRef)),
+ RHLRef = binary_to_term(term_to_binary(RHLRef)),
+ RSRef = binary_to_term(term_to_binary(RSRef)),
+ nc_refc_check(node()),
+ ok.
%%
%% Test case: round_trip_eq
%%
-round_trip_eq(doc) ->
- ["Tests that node containers that are sent beteen nodes stay equal to "
- "themselves."];
-round_trip_eq(suite) -> [];
+%% Tests that node containers that are sent beteen nodes stay equal to themselves.
round_trip_eq(Config) when is_list(Config) ->
- ?line ThisNode = {node(), erlang:system_info(creation)},
- ?line NodeFirstName = get_nodefirstname(),
- ?line ?line {ok, Node} = start_node(NodeFirstName),
- ?line Self = self(),
- ?line RPid = spawn_link(Node,
- fun () ->
- receive
- {Self, Data} ->
- Self ! {self(), Data}
- end
- end),
- ?line SentPid = self(),
- ?line SentXPid = mk_pid(ThisNode, 17471, 8190),
- ?line SentPort = hd(erlang:ports()),
- ?line SentXPort = mk_port(ThisNode, 268435451),
- ?line SentLRef = make_ref(),
- ?line SentHLRef = mk_ref(ThisNode, [4711, 17]),
- ?line SentSRef = mk_ref(ThisNode, [4711]),
- ?line RPid ! {Self, {SentPid,
- SentXPid,
- SentPort,
- SentXPort,
- SentLRef,
- SentHLRef,
- SentSRef}},
+ ThisNode = {node(), erlang:system_info(creation)},
+ NodeFirstName = get_nodefirstname(),
+ {ok, Node} = start_node(NodeFirstName),
+ Self = self(),
+ RPid = spawn_link(Node,
+ fun () ->
+ receive
+ {Self, Data} ->
+ Self ! {self(), Data}
+ end
+ end),
+ SentPid = self(),
+ SentXPid = mk_pid(ThisNode, 17471, 8190),
+ SentPort = hd(erlang:ports()),
+ SentXPort = mk_port(ThisNode, 268435451),
+ SentLRef = make_ref(),
+ SentHLRef = mk_ref(ThisNode, [4711, 17]),
+ SentSRef = mk_ref(ThisNode, [4711]),
+ RPid ! {Self, {SentPid,
+ SentXPid,
+ SentPort,
+ SentXPort,
+ SentLRef,
+ SentHLRef,
+ SentSRef}},
receive
- {RPid, {RecPid,
- RecXPid,
- RecPort,
- RecXPort,
- RecLRef,
- RecHLRef,
- RecSRef}} ->
- ?line stop_node(Node),
- ?line SentPid = RecPid,
- ?line SentXPid = RecXPid,
- ?line SentPort = RecPort,
- ?line SentXPort = RecXPort,
- ?line SentLRef = RecLRef,
- ?line SentHLRef = RecHLRef,
- ?line SentSRef = RecSRef,
- ?line nc_refc_check(node()),
- ?line ok
+ {RPid, {RecPid,
+ RecXPid,
+ RecPort,
+ RecXPort,
+ RecLRef,
+ RecHLRef,
+ RecSRef}} ->
+ stop_node(Node),
+ SentPid = RecPid,
+ SentXPid = RecXPid,
+ SentPort = RecPort,
+ SentXPort = RecXPort,
+ SentLRef = RecLRef,
+ SentHLRef = RecHLRef,
+ SentSRef = RecSRef,
+ nc_refc_check(node()),
+ ok
end.
-
+
%%
%% Test case: cmp
%%
-cmp(doc) ->
- ["Tests that Erlang term comparison works as it should on node "
- "containers."];
-cmp(suite) -> [];
+%% Tests that Erlang term comparison works as it should on node containers.
cmp(Config) when is_list(Config) ->
%% Inter type comparison ---------------------------------------------------
@@ -234,103 +212,103 @@ cmp(Config) when is_list(Config) ->
IRef = make_ref(),
ERef = mk_ref({get_nodename(), 2}, [1,2,3]),
-
+
IPid = self(),
EPid = mk_pid(RNode, 1, 2),
IPort = hd(erlang:ports()),
EPort = mk_port(RNode, 1),
-
+
%% Test pids ----------------------------------------------------
- ?line true = 1 < IPid,
- ?line true = 1.3 < IPid,
- ?line true = (1 bsl 64) < IPid,
- ?line true = an_atom < IPid,
- ?line true = IRef < IPid,
- ?line true = ERef < IPid,
- ?line true = fun () -> a_fun end < IPid,
- ?line true = IPort < IPid,
- ?line true = EPort < IPid,
- ?line true = IPid < {a, tuple},
- ?line true = IPid < [],
- ?line true = IPid < [a|cons],
- ?line true = IPid < <<"a binary">>,
-
- ?line true = 1 < EPid,
- ?line true = 1.3 < EPid,
- ?line true = (1 bsl 64) < EPid,
- ?line true = an_atom < EPid,
- ?line true = IRef < EPid,
- ?line true = ERef < EPid,
- ?line true = fun () -> a_fun end < EPid,
- ?line true = IPort < EPid,
- ?line true = EPort < EPid,
- ?line true = EPid < {a, tuple},
- ?line true = EPid < [],
- ?line true = EPid < [a|cons],
- ?line true = EPid < <<"a binary">>,
+ true = 1 < IPid,
+ true = 1.3 < IPid,
+ true = (1 bsl 64) < IPid,
+ true = an_atom < IPid,
+ true = IRef < IPid,
+ true = ERef < IPid,
+ true = fun () -> a_fun end < IPid,
+ true = IPort < IPid,
+ true = EPort < IPid,
+ true = IPid < {a, tuple},
+ true = IPid < [],
+ true = IPid < [a|cons],
+ true = IPid < <<"a binary">>,
+
+ true = 1 < EPid,
+ true = 1.3 < EPid,
+ true = (1 bsl 64) < EPid,
+ true = an_atom < EPid,
+ true = IRef < EPid,
+ true = ERef < EPid,
+ true = fun () -> a_fun end < EPid,
+ true = IPort < EPid,
+ true = EPort < EPid,
+ true = EPid < {a, tuple},
+ true = EPid < [],
+ true = EPid < [a|cons],
+ true = EPid < <<"a binary">>,
%% Test ports --------------------------------------------------
- ?line true = 1 < IPort,
- ?line true = 1.3 < IPort,
- ?line true = (1 bsl 64) < IPort,
- ?line true = an_atom < IPort,
- ?line true = IRef < IPort,
- ?line true = ERef < IPort,
- ?line true = fun () -> a_fun end < IPort,
- ?line true = IPort < IPid,
- ?line true = IPort < EPid,
- ?line true = IPort < {a, tuple},
- ?line true = IPort < [],
- ?line true = IPort < [a|cons],
- ?line true = IPort < <<"a binary">>,
-
- ?line true = 1 < EPort,
- ?line true = 1.3 < EPort,
- ?line true = (1 bsl 64) < EPort,
- ?line true = an_atom < EPort,
- ?line true = IRef < EPort,
- ?line true = ERef < EPort,
- ?line true = fun () -> a_fun end < EPort,
- ?line true = EPort < IPid,
- ?line true = EPort < EPid,
- ?line true = EPort < {a, tuple},
- ?line true = EPort < [],
- ?line true = EPort < [a|cons],
- ?line true = EPort < <<"a binary">>,
+ true = 1 < IPort,
+ true = 1.3 < IPort,
+ true = (1 bsl 64) < IPort,
+ true = an_atom < IPort,
+ true = IRef < IPort,
+ true = ERef < IPort,
+ true = fun () -> a_fun end < IPort,
+ true = IPort < IPid,
+ true = IPort < EPid,
+ true = IPort < {a, tuple},
+ true = IPort < [],
+ true = IPort < [a|cons],
+ true = IPort < <<"a binary">>,
+
+ true = 1 < EPort,
+ true = 1.3 < EPort,
+ true = (1 bsl 64) < EPort,
+ true = an_atom < EPort,
+ true = IRef < EPort,
+ true = ERef < EPort,
+ true = fun () -> a_fun end < EPort,
+ true = EPort < IPid,
+ true = EPort < EPid,
+ true = EPort < {a, tuple},
+ true = EPort < [],
+ true = EPort < [a|cons],
+ true = EPort < <<"a binary">>,
%% Test refs ----------------------------------------------------
- ?line true = 1 < IRef,
- ?line true = 1.3 < IRef,
- ?line true = (1 bsl 64) < IRef,
- ?line true = an_atom < IRef,
- ?line true = IRef < fun () -> a_fun end,
- ?line true = IRef < IPort,
- ?line true = IRef < EPort,
- ?line true = IRef < IPid,
- ?line true = IRef < EPid,
- ?line true = IRef < {a, tuple},
- ?line true = IRef < [],
- ?line true = IRef < [a|cons],
- ?line true = IRef < <<"a binary">>,
-
- ?line true = 1 < ERef,
- ?line true = 1.3 < ERef,
- ?line true = (1 bsl 64) < ERef,
- ?line true = an_atom < ERef,
- ?line true = ERef < fun () -> a_fun end,
- ?line true = ERef < IPort,
- ?line true = ERef < EPort,
- ?line true = ERef < IPid,
- ?line true = ERef < EPid,
- ?line true = ERef < {a, tuple},
- ?line true = ERef < [],
- ?line true = ERef < [a|cons],
- ?line true = ERef < <<"a binary">>,
+ true = 1 < IRef,
+ true = 1.3 < IRef,
+ true = (1 bsl 64) < IRef,
+ true = an_atom < IRef,
+ true = IRef < fun () -> a_fun end,
+ true = IRef < IPort,
+ true = IRef < EPort,
+ true = IRef < IPid,
+ true = IRef < EPid,
+ true = IRef < {a, tuple},
+ true = IRef < [],
+ true = IRef < [a|cons],
+ true = IRef < <<"a binary">>,
+
+ true = 1 < ERef,
+ true = 1.3 < ERef,
+ true = (1 bsl 64) < ERef,
+ true = an_atom < ERef,
+ true = ERef < fun () -> a_fun end,
+ true = ERef < IPort,
+ true = ERef < EPort,
+ true = ERef < IPid,
+ true = ERef < EPid,
+ true = ERef < {a, tuple},
+ true = ERef < [],
+ true = ERef < [a|cons],
+ true = ERef < <<"a binary">>,
%% Intra type comparison ---------------------------------------------------
-
+
%% Test pids ----------------------------------------------------
%%
@@ -338,13 +316,13 @@ cmp(Config) when is_list(Config) ->
%% serial, number, nodename, creation
%%
- ?line Pid = mk_pid({b@b, 2}, 4711, 1),
+ Pid = mk_pid({b@b, 2}, 4711, 1),
- ?line true = mk_pid({a@b, 1}, 4710, 2) > Pid,
- ?line true = mk_pid({a@b, 1}, 4712, 1) > Pid,
- ?line true = mk_pid({c@b, 1}, 4711, 1) > Pid,
- ?line true = mk_pid({b@b, 3}, 4711, 1) > Pid,
- ?line true = mk_pid({b@b, 2}, 4711, 1) =:= Pid,
+ true = mk_pid({a@b, 1}, 4710, 2) > Pid,
+ true = mk_pid({a@b, 1}, 4712, 1) > Pid,
+ true = mk_pid({c@b, 1}, 4711, 1) > Pid,
+ true = mk_pid({b@b, 3}, 4711, 1) > Pid,
+ true = mk_pid({b@b, 2}, 4711, 1) =:= Pid,
%% Test ports ---------------------------------------------------
%%
@@ -356,12 +334,12 @@ cmp(Config) when is_list(Config) ->
%% Significance used to be: dist_slot, number,
%% creation.
- ?line Port = mk_port({b@b, 2}, 4711),
+ Port = mk_port({b@b, 2}, 4711),
- ?line true = mk_port({c@b, 1}, 4710) > Port,
- ?line true = mk_port({b@b, 3}, 4710) > Port,
- ?line true = mk_port({b@b, 2}, 4712) > Port,
- ?line true = mk_port({b@b, 2}, 4711) =:= Port,
+ true = mk_port({c@b, 1}, 4710) > Port,
+ true = mk_port({b@b, 3}, 4710) > Port,
+ true = mk_port({b@b, 2}, 4712) > Port,
+ true = mk_port({b@b, 2}, 4711) =:= Port,
%% Test refs ----------------------------------------------------
%% Significance (most -> least):
@@ -373,99 +351,96 @@ cmp(Config) when is_list(Config) ->
%% creation.
%%
- ?line Ref = mk_ref({b@b, 2}, [4711, 4711, 4711]),
+ Ref = mk_ref({b@b, 2}, [4711, 4711, 4711]),
- ?line true = mk_ref({c@b, 1}, [4710, 4710, 4710]) > Ref,
- ?line true = mk_ref({b@b, 3}, [4710, 4710, 4710]) > Ref,
- ?line true = mk_ref({b@b, 2}, [4710, 4710, 4712]) > Ref,
- ?line true = mk_ref({b@b, 2}, [4710, 4712, 4711]) > Ref,
- ?line true = mk_ref({b@b, 2}, [4712, 4711, 4711]) > Ref,
- ?line true = mk_ref({b@b, 2}, [4711, 4711, 4711]) =:= Ref,
+ true = mk_ref({c@b, 1}, [4710, 4710, 4710]) > Ref,
+ true = mk_ref({b@b, 3}, [4710, 4710, 4710]) > Ref,
+ true = mk_ref({b@b, 2}, [4710, 4710, 4712]) > Ref,
+ true = mk_ref({b@b, 2}, [4710, 4712, 4711]) > Ref,
+ true = mk_ref({b@b, 2}, [4712, 4711, 4711]) > Ref,
+ true = mk_ref({b@b, 2}, [4711, 4711, 4711]) =:= Ref,
ok.
%%
%% Test case: ref_eq
%%
-ref_eq(doc) -> ["Test that one word refs \"works\"."];
-ref_eq(suite) -> [];
+%% Test that one word refs works
ref_eq(Config) when is_list(Config) ->
- ?line ThisNode = {node(), erlang:system_info(creation)},
- ?line AnotherNode = {get_nodename(),2},
- ?line LLongRef = mk_ref(ThisNode, [4711, 0, 0]),
- ?line LHalfLongRef = mk_ref(ThisNode, [4711, 0]),
- ?line LShortRef = mk_ref(ThisNode, [4711]),
- ?line true = LLongRef =:= LShortRef,
- ?line true = LLongRef =:= LHalfLongRef,
- ?line true = LLongRef =:= LLongRef,
- ?line true = LHalfLongRef =:= LShortRef,
- ?line true = LHalfLongRef =:= LHalfLongRef,
- ?line true = LShortRef =:= LShortRef,
- ?line false = LShortRef == mk_ref(ThisNode, [4711, 0, 1]), % Not any more
- ?line RLongRef = mk_ref(AnotherNode, [4711, 0, 0]),
- ?line RHalfLongRef = mk_ref(AnotherNode, [4711, 0]),
- ?line RShortRef = mk_ref(AnotherNode, [4711]),
- ?line true = RLongRef =:= RShortRef,
- ?line true = RLongRef =:= RHalfLongRef,
- ?line true = RLongRef =:= RLongRef,
- ?line true = RHalfLongRef =:= RShortRef,
- ?line true = RHalfLongRef =:= RHalfLongRef,
- ?line true = RShortRef =:= RShortRef,
- ?line false = RShortRef == mk_ref(AnotherNode, [4711, 0, 1]), % Not any more
- ?line nc_refc_check(node()),
- ?line ok.
-
+ ThisNode = {node(), erlang:system_info(creation)},
+ AnotherNode = {get_nodename(),2},
+ LLongRef = mk_ref(ThisNode, [4711, 0, 0]),
+ LHalfLongRef = mk_ref(ThisNode, [4711, 0]),
+ LShortRef = mk_ref(ThisNode, [4711]),
+ true = LLongRef =:= LShortRef,
+ true = LLongRef =:= LHalfLongRef,
+ true = LLongRef =:= LLongRef,
+ true = LHalfLongRef =:= LShortRef,
+ true = LHalfLongRef =:= LHalfLongRef,
+ true = LShortRef =:= LShortRef,
+ false = LShortRef == mk_ref(ThisNode, [4711, 0, 1]), % Not any more
+ RLongRef = mk_ref(AnotherNode, [4711, 0, 0]),
+ RHalfLongRef = mk_ref(AnotherNode, [4711, 0]),
+ RShortRef = mk_ref(AnotherNode, [4711]),
+ true = RLongRef =:= RShortRef,
+ true = RLongRef =:= RHalfLongRef,
+ true = RLongRef =:= RLongRef,
+ true = RHalfLongRef =:= RShortRef,
+ true = RHalfLongRef =:= RHalfLongRef,
+ true = RShortRef =:= RShortRef,
+ false = RShortRef == mk_ref(AnotherNode, [4711, 0, 1]), % Not any more
+ nc_refc_check(node()),
+ ok.
+
%%
%% Test case: node_table_gc
%%
-node_table_gc(doc) ->
- ["Tests that node tables are garbage collected."];
-node_table_gc(suite) -> [];
+%% Tests that node tables are garbage collected.
node_table_gc(Config) when is_list(Config) ->
erts_debug:set_internal_state(available_internal_state, true),
erts_debug:set_internal_state(node_tab_delayed_delete, 0),
- ?line PreKnown = nodes(known),
- ?line ?t:format("PreKnown = ~p~n", [PreKnown]),
- ?line make_node_garbage(0, 200000, 1000, []),
- ?line PostKnown = nodes(known),
- ?line PostAreas = erlang:system_info(allocated_areas),
- ?line ?t:format("PostKnown = ~p~n", [PostKnown]),
- ?line ?t:format("PostAreas = ~p~n", [PostAreas]),
- ?line true = length(PostKnown) =< length(PreKnown),
- ?line nc_refc_check(node()),
+ PreKnown = nodes(known),
+ io:format("PreKnown = ~p~n", [PreKnown]),
+ make_node_garbage(0, 200000, 1000, []),
+ PostKnown = nodes(known),
+ PostAreas = erlang:system_info(allocated_areas),
+ io:format("PostKnown = ~p~n", [PostKnown]),
+ io:format("PostAreas = ~p~n", [PostAreas]),
+ true = length(PostKnown) =< length(PreKnown),
+ nc_refc_check(node()),
erts_debug:set_internal_state(node_tab_delayed_delete, -1), %% restore original value
- ?line ok.
+ ok.
make_node_garbage(N, L, I, Ps) when N < L ->
- ?line Self = self(),
- ?line P = spawn_link(fun () ->
- % Generate two node entries and one dist
- % entry per node name
- ?line PL1 = make_faked_pid_list(N,
- I div 2,
- 1),
- ?line put(a, PL1),
- ?line PL2 = make_faked_pid_list(N,
- I div 2,
- 2),
- ?line put(b, PL2),
- ?line Self ! {self(), length(nodes(known))}
- end),
- ?line receive
- {P, KnownLength} ->
- ?line true = KnownLength >= I div 2
- end,
- ?line make_node_garbage(N+(I div 2)*2, L, I, [P|Ps]);
+ Self = self(),
+ P = spawn_link(fun () ->
+ % Generate two node entries and one dist
+ % entry per node name
+ PL1 = make_faked_pid_list(N,
+ I div 2,
+ 1),
+ put(a, PL1),
+ PL2 = make_faked_pid_list(N,
+ I div 2,
+ 2),
+ put(b, PL2),
+ Self ! {self(), length(nodes(known))}
+ end),
+ receive
+ {P, KnownLength} ->
+ true = KnownLength >= I div 2
+ end,
+ make_node_garbage(N+(I div 2)*2, L, I, [P|Ps]);
make_node_garbage(_, _, _, Ps) ->
%% Cleanup garbage...
ProcIsCleanedUp
- = fun (Proc) ->
- undefined == erts_debug:get_internal_state({process_status,
- Proc})
- end,
+ = fun (Proc) ->
+ undefined == erts_debug:get_internal_state({process_status,
+ Proc})
+ end,
lists:foreach(fun (P) -> wait_until(fun () -> ProcIsCleanedUp(P) end) end,
- Ps),
- ?line ok.
+ Ps),
+ ok.
make_faked_pid_list(Start, No, Creation) ->
@@ -475,292 +450,274 @@ make_faked_pid_list(_Start, 0, _Creation, Acc) ->
Acc;
make_faked_pid_list(Start, No, Creation, Acc) ->
make_faked_pid_list(Start+1,
- No-1,
- Creation,
- [mk_pid({"faked_node-"
- ++ integer_to_list(Start rem 50000)
- ++ "@"
- ++ atom_to_list(?MODULE),
- Creation},
- 4711,
- 3) | Acc]).
+ No-1,
+ Creation,
+ [mk_pid({"faked_node-"
+ ++ integer_to_list(Start rem 50000)
+ ++ "@"
+ ++ atom_to_list(?MODULE),
+ Creation},
+ 4711,
+ 3) | Acc]).
%%
%% Test case: dist_link_refc
%%
-dist_link_refc(doc) ->
- ["Tests that external reference counts are incremented and decremented "
- "as they should for distributed links"];
-dist_link_refc(suite) -> [];
+%% Tests that external reference counts are incremented and decremented
+%% as they should for distributed links
dist_link_refc(Config) when is_list(Config) ->
- ?line NodeFirstName = get_nodefirstname(),
- ?line ?line {ok, Node} = start_node(NodeFirstName),
- ?line RP = spawn_execer(Node),
- ?line LP = spawn_link_execer(node()),
- ?line true = sync_exec(RP, fun () -> link(LP) end),
- ?line wait_until(fun () ->
- ?line {links, Links} = process_info(LP, links),
- ?line lists:member(RP, Links)
- end),
- ?line NodeCre = sync_exec(RP, fun() -> erlang:system_info(creation) end),
- ?line 1 = reference_type_count(
- link,
- refering_entity_id({process, LP},
- get_node_references({Node, NodeCre}))),
- ?line exec(RP, fun() -> exit(normal) end),
- ?line wait_until(fun () ->
- ?line {links, Links} = process_info(LP, links),
- ?line not lists:member(RP, Links)
- end),
- ?line 0 = reference_type_count(
- link,
- refering_entity_id({process, LP},
- get_node_references({Node, NodeCre}))),
- ?line exit(LP, normal),
- ?line stop_node(Node),
- ?line nc_refc_check(node()),
- ?line ok.
+ NodeFirstName = get_nodefirstname(),
+ {ok, Node} = start_node(NodeFirstName),
+ RP = spawn_execer(Node),
+ LP = spawn_link_execer(node()),
+ true = sync_exec(RP, fun () -> link(LP) end),
+ wait_until(fun () ->
+ {links, Links} = process_info(LP, links),
+ lists:member(RP, Links)
+ end),
+ NodeCre = sync_exec(RP, fun() -> erlang:system_info(creation) end),
+ 1 = reference_type_count(
+ link,
+ refering_entity_id({process, LP},
+ get_node_references({Node, NodeCre}))),
+ exec(RP, fun() -> exit(normal) end),
+ wait_until(fun () ->
+ {links, Links} = process_info(LP, links),
+ not lists:member(RP, Links)
+ end),
+ 0 = reference_type_count(
+ link,
+ refering_entity_id({process, LP},
+ get_node_references({Node, NodeCre}))),
+ exit(LP, normal),
+ stop_node(Node),
+ nc_refc_check(node()),
+ ok.
%%
%% Test case: dist_monitor_refc
%%
-dist_monitor_refc(doc) ->
- ["Tests that external reference counts are incremented and decremented "
- "as they should for distributed monitors"];
-dist_monitor_refc(suite) -> [];
+%% Tests that external reference counts are incremented and decremented
+%% as they should for distributed monitors
dist_monitor_refc(Config) when is_list(Config) ->
- ?line NodeFirstName = get_nodefirstname(),
- ?line {ok, Node} = start_node(NodeFirstName),
- ?line RP = spawn_execer(Node),
- ?line LP = spawn_link_execer(node()),
- ?line RMon = sync_exec(RP, fun () -> erlang:monitor(process, LP) end),
- ?line true = is_reference(RMon),
- ?line LMon = sync_exec(LP, fun () -> erlang:monitor(process, RP) end),
- ?line true = is_reference(LMon),
- ?line NodeCre = sync_exec(RP, fun() -> erlang:system_info(creation) end),
- ?line wait_until(fun () ->
- ?line {monitored_by, MonBy}
- = process_info(LP, monitored_by),
- ?line {monitors, Mon}
- = process_info(LP, monitors),
- ?line (lists:member(RP, MonBy)
- and lists:member({process,RP}, Mon))
- end),
- ?line 3 = reference_type_count(
- monitor,
- refering_entity_id({process, LP},
- get_node_references({Node, NodeCre}))),
- ?line exec(RP, fun () -> exit(normal) end),
- ?line wait_until(fun () ->
- ?line {monitored_by, MonBy}
- = process_info(LP, monitored_by),
- ?line {monitors, Mon}
- = process_info(LP, monitors),
- ?line ((not lists:member(RP, MonBy))
- and (not lists:member({process,RP}, Mon)))
- end),
- ?line ok = sync_exec(LP,
- fun () ->
- receive
- {'DOWN', LMon, process, _, _} ->
- ok
- end
- end),
- ?line 0 = reference_type_count(
- link,
- refering_entity_id({process, LP},
- get_node_references({Node, NodeCre}))),
- ?line exit(LP, normal),
- ?line stop_node(Node),
- ?line nc_refc_check(node()),
- ?line ok.
+ NodeFirstName = get_nodefirstname(),
+ {ok, Node} = start_node(NodeFirstName),
+ RP = spawn_execer(Node),
+ LP = spawn_link_execer(node()),
+ RMon = sync_exec(RP, fun () -> erlang:monitor(process, LP) end),
+ true = is_reference(RMon),
+ LMon = sync_exec(LP, fun () -> erlang:monitor(process, RP) end),
+ true = is_reference(LMon),
+ NodeCre = sync_exec(RP, fun() -> erlang:system_info(creation) end),
+ wait_until(fun () ->
+ {monitored_by, MonBy}
+ = process_info(LP, monitored_by),
+ {monitors, Mon}
+ = process_info(LP, monitors),
+ (lists:member(RP, MonBy)
+ and lists:member({process,RP}, Mon))
+ end),
+ 3 = reference_type_count(
+ monitor,
+ refering_entity_id({process, LP},
+ get_node_references({Node, NodeCre}))),
+ exec(RP, fun () -> exit(normal) end),
+ wait_until(fun () ->
+ {monitored_by, MonBy}
+ = process_info(LP, monitored_by),
+ {monitors, Mon}
+ = process_info(LP, monitors),
+ ((not lists:member(RP, MonBy))
+ and (not lists:member({process,RP}, Mon)))
+ end),
+ ok = sync_exec(LP,
+ fun () ->
+ receive
+ {'DOWN', LMon, process, _, _} ->
+ ok
+ end
+ end),
+ 0 = reference_type_count(
+ link,
+ refering_entity_id({process, LP},
+ get_node_references({Node, NodeCre}))),
+ exit(LP, normal),
+ stop_node(Node),
+ nc_refc_check(node()),
+ ok.
%%
%% Test case: node_controller_refc
%%
-node_controller_refc(doc) ->
- ["Tests that external reference counts are incremented and decremented "
- "as they should for entities controlling a connections."];
-node_controller_refc(suite) -> [];
+%% Tests that external reference counts are incremented and decremented
+%% as they should for entities controlling a connections.
node_controller_refc(Config) when is_list(Config) ->
erts_debug:set_internal_state(available_internal_state, true),
erts_debug:set_internal_state(node_tab_delayed_delete, 0),
- ?line NodeFirstName = get_nodefirstname(),
- ?line ?line {ok, Node} = start_node(NodeFirstName),
- ?line true = lists:member(Node, nodes()),
- ?line 1 = reference_type_count(control, get_dist_references(Node)),
- ?line P = spawn_link_execer(node()),
- ?line Node
- = sync_exec(P,
- fun () ->
- put(remote_net_kernel,
- rpc:call(Node,erlang,whereis,[net_kernel])),
- node(get(remote_net_kernel))
- end),
- ?line Creation = rpc:call(Node, erlang, system_info, [creation]),
- ?line monitor_node(Node,true),
- ?line stop_node(Node),
- ?line receive {nodedown, Node} -> ok end,
- ?line DistRefs = get_dist_references(Node),
- ?line true = reference_type_count(node, DistRefs) > 0,
- ?line 0 = reference_type_count(control, DistRefs),
+ NodeFirstName = get_nodefirstname(),
+ {ok, Node} = start_node(NodeFirstName),
+ true = lists:member(Node, nodes()),
+ 1 = reference_type_count(control, get_dist_references(Node)),
+ P = spawn_link_execer(node()),
+ Node
+ = sync_exec(P,
+ fun () ->
+ put(remote_net_kernel,
+ rpc:call(Node,erlang,whereis,[net_kernel])),
+ node(get(remote_net_kernel))
+ end),
+ Creation = rpc:call(Node, erlang, system_info, [creation]),
+ monitor_node(Node,true),
+ stop_node(Node),
+ receive {nodedown, Node} -> ok end,
+ DistRefs = get_dist_references(Node),
+ true = reference_type_count(node, DistRefs) > 0,
+ 0 = reference_type_count(control, DistRefs),
% Get rid of all references to Node
- ?line exec(P, fun () -> exit(normal) end),
- ?line wait_until(fun () -> not is_process_alive(P) end),
+ exec(P, fun () -> exit(normal) end),
+ wait_until(fun () -> not is_process_alive(P) end),
lists:foreach(fun (Proc) -> garbage_collect(Proc) end, processes()),
- ?line false = get_node_references({Node,Creation}),
- ?line false = get_dist_references(Node),
- ?line false = lists:member(Node, nodes(known)),
- ?line nc_refc_check(node()),
+ false = get_node_references({Node,Creation}),
+ false = get_dist_references(Node),
+ false = lists:member(Node, nodes(known)),
+ nc_refc_check(node()),
erts_debug:set_internal_state(node_tab_delayed_delete, -1), %% restore original value
- ?line ok.
+ ok.
%%
%% Test case: ets_refc
%%
-ets_refc(doc) ->
- ["Tests that external reference counts are incremented and decremented "
- "as they should for data stored in ets tables."];
-ets_refc(suite) -> [];
+%% Tests that external reference counts are incremented and decremented
+%% as they should for data stored in ets tables.
ets_refc(Config) when is_list(Config) ->
- ?line RNode = {get_nodename(), 1},
- ?line RPid = mk_pid(RNode, 4711, 2),
- ?line RPort = mk_port(RNode, 4711),
- ?line RRef = mk_ref(RNode, [4711, 47, 11]),
- ?line Tab = ets:new(ets_refc, []),
- ?line 0 = reference_type_count(ets, get_node_references(RNode)),
- ?line true = ets:insert(Tab, [{a, self()},
- {b, RPid},
- {c, hd(erlang:ports())},
- {d, RPort},
- {e, make_ref()}]),
- ?line 2 = reference_type_count(ets, get_node_references(RNode)),
- ?line true = ets:insert(Tab, {f, RRef}),
- ?line 3 = reference_type_count(ets, get_node_references(RNode)),
- ?line true = ets:delete(Tab, d),
- ?line 2 = reference_type_count(ets, get_node_references(RNode)),
- ?line true = ets:delete_all_objects(Tab),
- ?line 0 = reference_type_count(ets, get_node_references(RNode)),
- ?line true = ets:insert(Tab, [{b, RPid}, {e, make_ref()}]),
- ?line 1 = reference_type_count(ets, get_node_references(RNode)),
- ?line true = ets:delete(Tab),
- ?line 0 = reference_type_count(ets, get_node_references(RNode)),
- ?line nc_refc_check(node()),
- ?line ok.
+ RNode = {get_nodename(), 1},
+ RPid = mk_pid(RNode, 4711, 2),
+ RPort = mk_port(RNode, 4711),
+ RRef = mk_ref(RNode, [4711, 47, 11]),
+ Tab = ets:new(ets_refc, []),
+ 0 = reference_type_count(ets, get_node_references(RNode)),
+ true = ets:insert(Tab, [{a, self()},
+ {b, RPid},
+ {c, hd(erlang:ports())},
+ {d, RPort},
+ {e, make_ref()}]),
+ 2 = reference_type_count(ets, get_node_references(RNode)),
+ true = ets:insert(Tab, {f, RRef}),
+ 3 = reference_type_count(ets, get_node_references(RNode)),
+ true = ets:delete(Tab, d),
+ 2 = reference_type_count(ets, get_node_references(RNode)),
+ true = ets:delete_all_objects(Tab),
+ 0 = reference_type_count(ets, get_node_references(RNode)),
+ true = ets:insert(Tab, [{b, RPid}, {e, make_ref()}]),
+ 1 = reference_type_count(ets, get_node_references(RNode)),
+ true = ets:delete(Tab),
+ 0 = reference_type_count(ets, get_node_references(RNode)),
+ nc_refc_check(node()),
+ ok.
%%
%% Test case: match_spec_refc
%%
-match_spec_refc(doc) ->
- ["Tests that external reference counts are incremented and decremented "
- "as they should for data stored in match specifications."];
-match_spec_refc(suite) -> [];
+%% Tests that external reference counts are incremented and decremented
+%% as they should for data stored in match specifications.
match_spec_refc(Config) when is_list(Config) ->
- ?line RNode = {get_nodename(), 1},
- ?line RPid = mk_pid(RNode, 4711, 2),
- ?line RPort = mk_port(RNode, 4711),
- ?line RRef = mk_ref(RNode, [4711, 47, 11]),
- ?line ok = do_match_spec_test(RNode, RPid, RPort, RRef),
- ?line garbage_collect(),
- ?line NodeRefs = get_node_references(RNode),
- ?line 0 = reference_type_count(binary, NodeRefs),
- ?line 0 = reference_type_count(ets, NodeRefs),
- ?line nc_refc_check(node()),
- ?line ok.
+ RNode = {get_nodename(), 1},
+ RPid = mk_pid(RNode, 4711, 2),
+ RPort = mk_port(RNode, 4711),
+ RRef = mk_ref(RNode, [4711, 47, 11]),
+ ok = do_match_spec_test(RNode, RPid, RPort, RRef),
+ garbage_collect(),
+ NodeRefs = get_node_references(RNode),
+ 0 = reference_type_count(binary, NodeRefs),
+ 0 = reference_type_count(ets, NodeRefs),
+ nc_refc_check(node()),
+ ok.
do_match_spec_test(RNode, RPid, RPort, RRef) ->
- ?line Tab = ets:new(match_spec_refc, []),
- ?line true = ets:insert(Tab, [{a, RPid, RPort, RRef},
- {b, self(), RPort, RRef},
- {c, RPid, RPort, make_ref()},
- {d, RPid, RPort, RRef}]),
- ?line {M1, C1} = ets:select(Tab, [{{'$1',RPid,RPort,RRef},[],['$1']}], 1),
- ?line NodeRefs = get_node_references(RNode),
- ?line 3 = reference_type_count(binary, NodeRefs),
- ?line 10 = reference_type_count(ets, NodeRefs),
- ?line {M2, C2} = ets:select(C1),
- ?line '$end_of_table' = ets:select(C2),
- ?line ets:delete(Tab),
- ?line [a,d] = lists:sort(M1++M2),
- ?line ok.
-
+ Tab = ets:new(match_spec_refc, []),
+ true = ets:insert(Tab, [{a, RPid, RPort, RRef},
+ {b, self(), RPort, RRef},
+ {c, RPid, RPort, make_ref()},
+ {d, RPid, RPort, RRef}]),
+ {M1, C1} = ets:select(Tab, [{{'$1',RPid,RPort,RRef},[],['$1']}], 1),
+ NodeRefs = get_node_references(RNode),
+ 3 = reference_type_count(binary, NodeRefs),
+ 10 = reference_type_count(ets, NodeRefs),
+ {M2, C2} = ets:select(C1),
+ '$end_of_table' = ets:select(C2),
+ ets:delete(Tab),
+ [a,d] = lists:sort(M1++M2),
+ ok.
+
%%
%% Test case: ets_refc
%%
-timer_refc(doc) ->
- ["Tests that external reference counts are incremented and decremented "
- "as they should for data stored in bif timers."];
-timer_refc(suite) -> [];
+%% Tests that external reference counts are incremented and decremented
+%% as they should for data stored in bif timers.
timer_refc(Config) when is_list(Config) ->
- ?line RNode = {get_nodename(), 1},
- ?line RPid = mk_pid(RNode, 4711, 2),
- ?line RPort = mk_port(RNode, 4711),
- ?line RRef = mk_ref(RNode, [4711, 47, 11]),
- ?line 0 = reference_type_count(timer, get_node_references(RNode)),
- ?line Pid = spawn(fun () -> receive after infinity -> ok end end),
- ?line erlang:start_timer(10000, Pid, {RPid, RPort, RRef}),
- ?line 3 = reference_type_count(timer, get_node_references(RNode)),
- ?line exit(Pid, kill),
- ?line Mon = erlang:monitor(process, Pid),
- ?line receive {'DOWN', Mon, process, Pid, _} -> ok end,
- ?line 0 = reference_type_count(timer, get_node_references(RNode)),
- ?line erlang:send_after(500, Pid, {timer, RPid, RPort, RRef}),
- ?line 0 = reference_type_count(timer, get_node_references(RNode)),
- ?line erlang:send_after(500, self(), {timer, RPid, RPort, RRef}),
- ?line erlang:send_after(400, bananfluga, {timer, RPid, RPort, RRef}),
- ?line 6 = reference_type_count(timer, get_node_references(RNode)),
- ?line receive {timer, RPid, RPort, RRef} -> ok end,
- ?line 0 = reference_type_count(timer, get_node_references(RNode)),
- ?line nc_refc_check(node()),
- ?line ok.
-
-otp_4715(doc) -> [];
-otp_4715(suite) -> [];
+ RNode = {get_nodename(), 1},
+ RPid = mk_pid(RNode, 4711, 2),
+ RPort = mk_port(RNode, 4711),
+ RRef = mk_ref(RNode, [4711, 47, 11]),
+ 0 = reference_type_count(timer, get_node_references(RNode)),
+ Pid = spawn(fun () -> receive after infinity -> ok end end),
+ erlang:start_timer(10000, Pid, {RPid, RPort, RRef}),
+ 3 = reference_type_count(timer, get_node_references(RNode)),
+ exit(Pid, kill),
+ Mon = erlang:monitor(process, Pid),
+ receive {'DOWN', Mon, process, Pid, _} -> ok end,
+ 0 = reference_type_count(timer, get_node_references(RNode)),
+ erlang:send_after(500, Pid, {timer, RPid, RPort, RRef}),
+ 0 = reference_type_count(timer, get_node_references(RNode)),
+ erlang:send_after(500, self(), {timer, RPid, RPort, RRef}),
+ erlang:send_after(400, bananfluga, {timer, RPid, RPort, RRef}),
+ 6 = reference_type_count(timer, get_node_references(RNode)),
+ receive {timer, RPid, RPort, RRef} -> ok end,
+ 0 = reference_type_count(timer, get_node_references(RNode)),
+ nc_refc_check(node()),
+ ok.
+
otp_4715(Config) when is_list(Config) ->
- case ?t:is_release_available("r9b") of
- true -> otp_4715_1(Config);
- false -> {skip,"No R9B found"}
+ case test_server:is_release_available("r9b") of
+ true -> otp_4715_1(Config);
+ false -> {skip,"No R9B found"}
end.
otp_4715_1(Config) ->
case erlang:system_info(compat_rel) of
- 9 ->
- ?line run_otp_4715(Config);
- _ ->
- ?line Pa = filename:dirname(code:which(?MODULE)),
- ?line ?t:run_on_shielded_node(fun () ->
- run_otp_4715(Config)
- end,
- "+R9 -pa " ++ Pa)
+ 9 ->
+ run_otp_4715(Config);
+ _ ->
+ Pa = filename:dirname(code:which(?MODULE)),
+ test_server:run_on_shielded_node(fun () ->
+ run_otp_4715(Config)
+ end,
+ "+R9 -pa " ++ Pa)
end.
run_otp_4715(Config) when is_list(Config) ->
- ?line erts_debug:set_internal_state(available_internal_state, true),
- ?line PidList = [mk_pid({a@b, 1}, 4710, 2),
- mk_pid({a@b, 1}, 4712, 1),
- mk_pid({c@b, 1}, 4711, 1),
- mk_pid({b@b, 3}, 4711, 1),
- mk_pid({b@b, 2}, 4711, 1)],
-
- ?line R9Sorted = old_mod:sort_on_old_node(PidList),
- ?line R9Sorted = lists:sort(PidList).
-
-pid_wrap(doc) -> [];
-pid_wrap(suite) -> [];
-pid_wrap(Config) when is_list(Config) -> ?line pp_wrap(pid).
-
-port_wrap(doc) -> [];
-port_wrap(suite) -> [];
+ erts_debug:set_internal_state(available_internal_state, true),
+ PidList = [mk_pid({a@b, 1}, 4710, 2),
+ mk_pid({a@b, 1}, 4712, 1),
+ mk_pid({c@b, 1}, 4711, 1),
+ mk_pid({b@b, 3}, 4711, 1),
+ mk_pid({b@b, 2}, 4711, 1)],
+
+ R9Sorted = old_mod:sort_on_old_node(PidList),
+ R9Sorted = lists:sort(PidList).
+
+pid_wrap(Config) when is_list(Config) -> pp_wrap(pid).
+
port_wrap(Config) when is_list(Config) ->
- ?line case ?t:os_type() of
- {unix, _} ->
- ?line pp_wrap(port);
- _ ->
- ?line {skip, "Only run on unix"}
- end.
+ case test_server:os_type() of
+ {unix, _} ->
+ pp_wrap(port);
+ _ ->
+ {skip, "Only run on unix"}
+ end.
get_next_id(pid) ->
erts_debug:get_internal_state(next_pid);
@@ -773,167 +730,161 @@ set_next_id(port, N) ->
erts_debug:set_internal_state(next_port, N).
pp_wrap(What) ->
- ?line N = set_high_pp_next(What),
- ?line Cre = N + 100,
- ?line ?t:format("no creations = ~p~n", [Cre]),
- ?line PreCre = get_next_id(What),
- ?line ?t:format("pre creations = ~p~n", [PreCre]),
- ?line true = is_integer(PreCre),
- ?line do_pp_creations(What, Cre),
- ?line PostCre = get_next_id(What),
- ?line ?t:format("post creations = ~p~n", [PostCre]),
- ?line true = is_integer(PostCre),
- ?line true = PreCre > PostCre,
- ?line Now = set_next_id(What, ?MAX_PIDS_PORTS div 2),
- ?line ?t:format("reset to = ~p~n", [Now]),
- ?line true = is_integer(Now),
- ?line ok.
+ N = set_high_pp_next(What),
+ Cre = N + 100,
+ io:format("no creations = ~p~n", [Cre]),
+ PreCre = get_next_id(What),
+ io:format("pre creations = ~p~n", [PreCre]),
+ true = is_integer(PreCre),
+ do_pp_creations(What, Cre),
+ PostCre = get_next_id(What),
+ io:format("post creations = ~p~n", [PostCre]),
+ true = is_integer(PostCre),
+ true = PreCre > PostCre,
+ Now = set_next_id(What, ?MAX_PIDS_PORTS div 2),
+ io:format("reset to = ~p~n", [Now]),
+ true = is_integer(Now),
+ ok.
set_high_pp_next(What) ->
- ?line set_high_pp_next(What, ?MAX_PIDS_PORTS-1).
-
+ set_high_pp_next(What, ?MAX_PIDS_PORTS-1).
+
set_high_pp_next(What, N) ->
- ?line M = set_next_id(What, N),
- ?line true = is_integer(M),
- ?line case {M >= N, M =< ?MAX_PIDS_PORTS} of
- {true, true} ->
- ?line ?MAX_PIDS_PORTS - M + 1;
- _ ->
- ?line set_high_pp_next(What, N - 100)
- end.
+ M = set_next_id(What, N),
+ true = is_integer(M),
+ case {M >= N, M =< ?MAX_PIDS_PORTS} of
+ {true, true} ->
+ ?MAX_PIDS_PORTS - M + 1;
+ _ ->
+ set_high_pp_next(What, N - 100)
+ end.
do_pp_creations(_What, N) when is_integer(N), N =< 0 ->
- ?line done;
+ done;
do_pp_creations(pid, N) when is_integer(N) ->
%% Create new pid and make sure it works...
- ?line Me = self(),
- ?line Ref = make_ref(),
- ?line Pid = spawn_link(fun () ->
- receive
- Ref ->
- Me ! Ref
- end
- end),
- ?line Pid ! Ref,
- ?line receive
- Ref ->
- ?line do_pp_creations(pid, N - 1)
- end;
+ Me = self(),
+ Ref = make_ref(),
+ Pid = spawn_link(fun () ->
+ receive
+ Ref ->
+ Me ! Ref
+ end
+ end),
+ Pid ! Ref,
+ receive
+ Ref ->
+ do_pp_creations(pid, N - 1)
+ end;
do_pp_creations(port, N) when is_integer(N) ->
%% Create new port and make sure it works...
- ?line "hej" = os:cmd("echo hej") -- "\n",
- ?line do_pp_creations(port, N - 1).
+ "hej" = os:cmd("echo hej") -- "\n",
+ do_pp_creations(port, N - 1).
-bad_nc(doc) -> [];
-bad_nc(suite) -> [];
bad_nc(Config) when is_list(Config) ->
% Make sure emulator don't crash on bad node containers...
- ?line MaxPidNum = (1 bsl 15) - 1,
- ?line MaxPidSer = ?MAX_PIDS_PORTS bsr 15,
- ?line ThisNode = {node(), erlang:system_info(creation)},
- ?line {'EXIT', {badarg, mk_pid, _}}
- = (catch mk_pid(ThisNode, MaxPidNum + 1, 17)),
- ?line {'EXIT', {badarg, mk_pid, _}}
- = (catch mk_pid(ThisNode, 4711, MaxPidSer + 1)),
- ?line {'EXIT', {badarg, mk_port, _}}
- = (catch mk_port(ThisNode, ?MAX_PIDS_PORTS + 1)),
- ?line {'EXIT', {badarg, mk_ref, _}}
- = (catch mk_ref(ThisNode,[(1 bsl 18), 4711, 4711])),
- ?line {'EXIT', {badarg, mk_ref, _}}
- = (catch mk_ref(ThisNode, [4711, 4711, 4711, 4711, 4711, 4711, 4711])),
- ?line RemNode = {x@y, 2},
- ?line {'EXIT', {badarg, mk_pid, _}}
- = (catch mk_pid(RemNode, MaxPidNum + 1, MaxPidSer)),
- ?line {'EXIT', {badarg, mk_pid, _}}
- = (catch mk_pid(RemNode, MaxPidNum, MaxPidSer + 1)),
- ?line {'EXIT', {badarg, mk_port, _}}
- = (catch mk_port(RemNode, ?MAX_PIDS_PORTS + 1)),
- ?line {'EXIT', {badarg, mk_ref, _}}
- = (catch mk_ref(RemNode, [(1 bsl 18), 4711, 4711])),
- ?line {'EXIT', {badarg, mk_ref, _}}
- = (catch mk_ref(RemNode, [4711, 4711, 4711, 4711, 4711, 4711, 4711])),
- ?line BadNode = {x@y, 4},
- ?line {'EXIT', {badarg, mk_pid, _}}
- = (catch mk_pid(BadNode, 4711, 17)),
- ?line {'EXIT', {badarg, mk_port, _}}
- = (catch mk_port(BadNode, 4711)),
- ?line {'EXIT', {badarg, mk_ref, _}}
- = (catch mk_ref(BadNode, [4711, 4711, 17])),
- ?line ok.
+ MaxPidNum = (1 bsl 15) - 1,
+ MaxPidSer = ?MAX_PIDS_PORTS bsr 15,
+ ThisNode = {node(), erlang:system_info(creation)},
+ {'EXIT', {badarg, mk_pid, _}}
+ = (catch mk_pid(ThisNode, MaxPidNum + 1, 17)),
+ {'EXIT', {badarg, mk_pid, _}}
+ = (catch mk_pid(ThisNode, 4711, MaxPidSer + 1)),
+ {'EXIT', {badarg, mk_port, _}}
+ = (catch mk_port(ThisNode, ?MAX_PIDS_PORTS + 1)),
+ {'EXIT', {badarg, mk_ref, _}}
+ = (catch mk_ref(ThisNode,[(1 bsl 18), 4711, 4711])),
+ {'EXIT', {badarg, mk_ref, _}}
+ = (catch mk_ref(ThisNode, [4711, 4711, 4711, 4711, 4711, 4711, 4711])),
+ RemNode = {x@y, 2},
+ {'EXIT', {badarg, mk_pid, _}}
+ = (catch mk_pid(RemNode, MaxPidNum + 1, MaxPidSer)),
+ {'EXIT', {badarg, mk_pid, _}}
+ = (catch mk_pid(RemNode, MaxPidNum, MaxPidSer + 1)),
+ {'EXIT', {badarg, mk_port, _}}
+ = (catch mk_port(RemNode, ?MAX_PIDS_PORTS + 1)),
+ {'EXIT', {badarg, mk_ref, _}}
+ = (catch mk_ref(RemNode, [(1 bsl 18), 4711, 4711])),
+ {'EXIT', {badarg, mk_ref, _}}
+ = (catch mk_ref(RemNode, [4711, 4711, 4711, 4711, 4711, 4711, 4711])),
+ BadNode = {x@y, 4},
+ {'EXIT', {badarg, mk_pid, _}}
+ = (catch mk_pid(BadNode, 4711, 17)),
+ {'EXIT', {badarg, mk_port, _}}
+ = (catch mk_port(BadNode, 4711)),
+ {'EXIT', {badarg, mk_ref, _}}
+ = (catch mk_ref(BadNode, [4711, 4711, 17])),
+ ok.
-define(NO_PIDS, 1000000).
-unique_pid(doc) -> [];
-unique_pid(suite) -> [];
unique_pid(Config) when is_list(Config) ->
case catch erlang:system_info(modified_timing_level) of
- Level when is_integer(Level) ->
- {skip,
- "Modified timing (level " ++ integer_to_list(Level)
- ++ ") is enabled. spawn() is too slow for this "
- " test when modified timing is enabled."};
- _ ->
- ?line ?NO_PIDS = length(lists:usort(mkpidlist(?NO_PIDS, []))),
- ?line ok
+ Level when is_integer(Level) ->
+ {skip,
+ "Modified timing (level " ++ integer_to_list(Level)
+ ++ ") is enabled. spawn() is too slow for this "
+ " test when modified timing is enabled."};
+ _ ->
+ ?NO_PIDS = length(lists:usort(mkpidlist(?NO_PIDS, []))),
+ ok
end.
-
+
mkpidlist(0, Ps) -> Ps;
mkpidlist(N, Ps) -> mkpidlist(N-1, [spawn(fun () -> ok end)|Ps]).
-iter_max_procs(doc) -> [];
-iter_max_procs(suite) -> [];
iter_max_procs(Config) when is_list(Config) ->
- ?line NoMoreTests = make_ref(),
- ?line erlang:send_after(10000, self(), NoMoreTests),
- ?line Res = chk_max_proc_line(),
- ?line Res = chk_max_proc_line(),
- ?line done = chk_max_proc_line_until(NoMoreTests, Res),
- ?line {comment,
- io_lib:format("max processes = ~p; "
- "process line length = ~p",
- [element(2, Res), element(1, Res)])}.
-
-
+ NoMoreTests = make_ref(),
+ erlang:send_after(10000, self(), NoMoreTests),
+ Res = chk_max_proc_line(),
+ Res = chk_max_proc_line(),
+ done = chk_max_proc_line_until(NoMoreTests, Res),
+ {comment,
+ io_lib:format("max processes = ~p; "
+ "process line length = ~p",
+ [element(2, Res), element(1, Res)])}.
+
+
max_proc_line(Root, Parent, N) ->
Me = self(),
case catch spawn_link(fun () -> max_proc_line(Root, Me, N+1) end) of
- {'EXIT', {system_limit, _}} when Root /= self() ->
- Root ! {proc_line_length, N, self()},
- receive remove_proc_line -> Parent ! {exiting, Me} end;
- P when is_pid(P), Root =/= self() ->
- receive {exiting, P} -> Parent ! {exiting, Me} end;
- P when is_pid(P) ->
- P;
- Unexpected ->
- exit({unexpected_spawn_result, Unexpected})
+ {'EXIT', {system_limit, _}} when Root /= self() ->
+ Root ! {proc_line_length, N, self()},
+ receive remove_proc_line -> Parent ! {exiting, Me} end;
+ P when is_pid(P), Root =/= self() ->
+ receive {exiting, P} -> Parent ! {exiting, Me} end;
+ P when is_pid(P) ->
+ P;
+ Unexpected ->
+ exit({unexpected_spawn_result, Unexpected})
end.
chk_max_proc_line() ->
- ?line Child = max_proc_line(self(), self(), 0),
- ?line receive
- {proc_line_length, PLL, End} ->
- ?line PC = erlang:system_info(process_count),
- ?line LP = length(processes()),
- ?line ?t:format("proc line length = ~p; "
- "process count = ~p; "
- "length processes = ~p~n",
- [PLL, PC, LP]),
- ?line End ! remove_proc_line,
- ?line PC = LP,
- ?line receive {exiting, Child} -> ok end,
- ?line {PLL, PC}
- end.
+ Child = max_proc_line(self(), self(), 0),
+ receive
+ {proc_line_length, PLL, End} ->
+ PC = erlang:system_info(process_count),
+ LP = length(processes()),
+ io:format("proc line length = ~p; "
+ "process count = ~p; "
+ "length processes = ~p~n",
+ [PLL, PC, LP]),
+ End ! remove_proc_line,
+ PC = LP,
+ receive {exiting, Child} -> ok end,
+ {PLL, PC}
+ end.
chk_max_proc_line_until(NoMoreTests, Res) ->
receive
- NoMoreTests ->
- ?line done
+ NoMoreTests ->
+ done
after 0 ->
- ?line Res = chk_max_proc_line(),
- ?line chk_max_proc_line_until(NoMoreTests, Res)
+ Res = chk_max_proc_line(),
+ chk_max_proc_line_until(NoMoreTests, Res)
end.
%%
@@ -950,126 +901,126 @@ node_container_refc_check(Node) when is_atom(Node) ->
nc_refc_check(Node) when is_atom(Node) ->
Ref = make_ref(),
Self = self(),
- ?t:format("Starting reference count check of node ~w~n", [Node]),
+ io:format("Starting reference count check of node ~w~n", [Node]),
spawn_link(Node,
- fun () ->
- {{node_references, NodeRefs},
- {dist_references, DistRefs}} = ?ND_REFS,
- check_nd_refc({node(), erlang:system_info(creation)},
- NodeRefs,
- DistRefs,
- fun (ErrMsg) ->
- Self ! {Ref, ErrMsg, failed},
- exit(normal)
- end),
- Self ! {Ref, succeded}
- end),
+ fun () ->
+ {{node_references, NodeRefs},
+ {dist_references, DistRefs}} = ?ND_REFS,
+ check_nd_refc({node(), erlang:system_info(creation)},
+ NodeRefs,
+ DistRefs,
+ fun (ErrMsg) ->
+ Self ! {Ref, ErrMsg, failed},
+ exit(normal)
+ end),
+ Self ! {Ref, succeded}
+ end),
receive
- {Ref, ErrorMsg, failed} ->
- ?t:format("~s~n", [ErrorMsg]),
- ?t:fail(reference_count_check_failed);
- {Ref, succeded} ->
- ?t:format("Reference count check of node ~w succeded!~n", [Node]),
- ok
+ {Ref, ErrorMsg, failed} ->
+ io:format("~s~n", [ErrorMsg]),
+ ct:fail(reference_count_check_failed);
+ {Ref, succeded} ->
+ io:format("Reference count check of node ~w succeded!~n", [Node]),
+ ok
end.
check_nd_refc({ThisNodeName, ThisCreation}, NodeRefs, DistRefs, Fail) ->
case catch begin
- check_refc(ThisNodeName,ThisCreation,"node table",NodeRefs),
- check_refc(ThisNodeName,ThisCreation,"dist table",DistRefs),
- ok
- end of
- ok ->
- ok;
- {'EXIT', Reason} ->
- {Y,Mo,D} = date(),
- {H,Mi,S} = time(),
- ErrMsg = io_lib:format("~n"
- "*** Reference count check of node ~w "
- "failed (~p) at ~w~w~w ~w:~w:~w~n"
- "*** Node table references:~n ~p~n"
- "*** Dist table references:~n ~p~n",
- [node(), Reason, Y, Mo, D, H, Mi, S,
- NodeRefs, DistRefs]),
- Fail(lists:flatten(ErrMsg))
+ check_refc(ThisNodeName,ThisCreation,"node table",NodeRefs),
+ check_refc(ThisNodeName,ThisCreation,"dist table",DistRefs),
+ ok
+ end of
+ ok ->
+ ok;
+ {'EXIT', Reason} ->
+ {Y,Mo,D} = date(),
+ {H,Mi,S} = time(),
+ ErrMsg = io_lib:format("~n"
+ "*** Reference count check of node ~w "
+ "failed (~p) at ~w~w~w ~w:~w:~w~n"
+ "*** Node table references:~n ~p~n"
+ "*** Dist table references:~n ~p~n",
+ [node(), Reason, Y, Mo, D, H, Mi, S,
+ NodeRefs, DistRefs]),
+ Fail(lists:flatten(ErrMsg))
end.
check_refc(ThisNodeName,ThisCreation,Table,EntryList) when is_list(EntryList) ->
lists:foreach(
fun ({Entry, Refc, ReferrerList}) ->
- {DelayedDeleteTimer,
- FoundRefs} =
- lists:foldl(
- fun ({Referrer, ReferencesList}, {DDT, A1}) ->
- {case Referrer of
- {system,delayed_delete_timer} ->
- true;
- _ ->
- DDT
- end,
- A1 + lists:foldl(fun ({_T,Rs},A2) ->
- A2+Rs
- end,
- 0,
- ReferencesList)}
- end,
- {false, 0},
- ReferrerList),
-
- %% Reference count equals found references?
- case {Refc, FoundRefs, DelayedDeleteTimer} of
- {X, X, _} ->
- ok;
- {0, 1, true} ->
- ok;
- _ ->
- exit({invalid_reference_count, Table, Entry})
- end,
-
- %% All entries in table referred to?
- case {Entry, Refc} of
- {ThisNodeName, 0} -> ok;
- {{ThisNodeName, ThisCreation}, 0} -> ok;
- {_, 0} when DelayedDeleteTimer == false ->
- exit({not_referred_entry_in_table, Table, Entry});
- {_, _} -> ok
- end
+ {DelayedDeleteTimer,
+ FoundRefs} =
+ lists:foldl(
+ fun ({Referrer, ReferencesList}, {DDT, A1}) ->
+ {case Referrer of
+ {system,delayed_delete_timer} ->
+ true;
+ _ ->
+ DDT
+ end,
+ A1 + lists:foldl(fun ({_T,Rs},A2) ->
+ A2+Rs
+ end,
+ 0,
+ ReferencesList)}
+ end,
+ {false, 0},
+ ReferrerList),
+
+ %% Reference count equals found references?
+ case {Refc, FoundRefs, DelayedDeleteTimer} of
+ {X, X, _} ->
+ ok;
+ {0, 1, true} ->
+ ok;
+ _ ->
+ exit({invalid_reference_count, Table, Entry})
+ end,
+
+ %% All entries in table referred to?
+ case {Entry, Refc} of
+ {ThisNodeName, 0} -> ok;
+ {{ThisNodeName, ThisCreation}, 0} -> ok;
+ {_, 0} when DelayedDeleteTimer == false ->
+ exit({not_referred_entry_in_table, Table, Entry});
+ {_, _} -> ok
+ end
end,
EntryList),
ok.
get_node_references({NodeName, Creation} = Node) when is_atom(NodeName),
- is_integer(Creation) ->
+ is_integer(Creation) ->
{{node_references, NodeRefs},
- {dist_references, DistRefs}} = ?ND_REFS,
+ {dist_references, DistRefs}} = ?ND_REFS,
check_nd_refc({node(), erlang:system_info(creation)},
- NodeRefs,
- DistRefs,
- fun (ErrMsg) ->
- ?t:format("~s", [ErrMsg]),
- ?t:fail(reference_count_check_failed)
- end),
+ NodeRefs,
+ DistRefs,
+ fun (ErrMsg) ->
+ io:format("~s", [ErrMsg]),
+ ct:fail(reference_count_check_failed)
+ end),
find_references(Node, NodeRefs).
get_dist_references(NodeName) when is_atom(NodeName) ->
- ?line {{node_references, NodeRefs},
- {dist_references, DistRefs}} = ?ND_REFS,
- ?line check_nd_refc({node(), erlang:system_info(creation)},
- NodeRefs,
- DistRefs,
- fun (ErrMsg) ->
- ?line ?t:format("~s", [ErrMsg]),
- ?line ?t:fail(reference_count_check_failed)
- end),
- ?line find_references(NodeName, DistRefs).
+ {{node_references, NodeRefs},
+ {dist_references, DistRefs}} = ?ND_REFS,
+ check_nd_refc({node(), erlang:system_info(creation)},
+ NodeRefs,
+ DistRefs,
+ fun (ErrMsg) ->
+ io:format("~s", [ErrMsg]),
+ ct:fail(reference_count_check_failed)
+ end),
+ find_references(NodeName, DistRefs).
find_references(N, NRefList) ->
case lists:keysearch(N, 1, NRefList) of
- {value, {N, _, ReferrersList}} -> ReferrersList;
- _ -> false
- end.
+ {value, {N, _, ReferrersList}} -> ReferrersList;
+ _ -> false
+ end.
%% Currently unused
% refering_entity_type(RefererType, ReferingEntities) ->
@@ -1081,7 +1032,7 @@ find_references(N, NRefList) ->
% ReferingEntities).
refering_entity_id(ReferingEntityId, [{ReferingEntityId,_} = ReferingEntity
- | _ReferingEntities]) ->
+ | _ReferingEntities]) ->
ReferingEntity;
refering_entity_id(ReferingEntityId, [_ | ReferingEntities]) ->
refering_entity_id(ReferingEntityId, ReferingEntities);
@@ -1094,34 +1045,34 @@ reference_type_count(Type, {_, _ReferenceCountList} = ReferingEntity) ->
reference_type_count(Type, [ReferingEntity]);
reference_type_count(Type, ReferingEntities) when is_list(ReferingEntities) ->
lists:foldl(fun ({_, ReferenceCountList}, Acc1) ->
- lists:foldl(fun ({T, N}, Acc2) when T == Type ->
- N + Acc2;
- (_, Acc2) ->
- Acc2
- end,
- Acc1,
- ReferenceCountList)
- end,
- 0,
- ReferingEntities).
+ lists:foldl(fun ({T, N}, Acc2) when T == Type ->
+ N + Acc2;
+ (_, Acc2) ->
+ Acc2
+ end,
+ Acc1,
+ ReferenceCountList)
+ end,
+ 0,
+ ReferingEntities).
start_node(Name, Args) ->
- ?line Pa = filename:dirname(code:which(?MODULE)),
- ?line Res = test_server:start_node(Name,
- slave,
- [{args, "-pa "++Pa++" "++Args}]),
- ?line {ok, Node} = Res,
- ?line rpc:call(Node, erts_debug, set_internal_state,
- [available_internal_state, true]),
- ?line Res.
-
+ Pa = filename:dirname(code:which(?MODULE)),
+ Res = test_server:start_node(Name,
+ slave,
+ [{args, "-pa "++Pa++" "++Args}]),
+ {ok, Node} = Res,
+ rpc:call(Node, erts_debug, set_internal_state,
+ [available_internal_state, true]),
+ Res.
+
start_node(Name) ->
- ?line start_node(Name, "").
+ start_node(Name, "").
stop_node(Node) ->
- ?line nc_refc_check(Node),
- ?line true = test_server:stop_node(Node).
+ nc_refc_check(Node),
+ true = test_server:stop_node(Node).
hostname() ->
from($@, atom_to_list(node())).
@@ -1132,25 +1083,25 @@ from(_H, []) -> [].
wait_until(Pred) ->
case Pred() of
- true -> ok;
- false -> receive after 100 -> wait_until(Pred) end
+ true -> ok;
+ false -> receive after 100 -> wait_until(Pred) end
end.
get_nodefirstname_string() ->
atom_to_list(?MODULE)
- ++ "-"
- ++ integer_to_list(erlang:system_time(seconds))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive])).
+ ++ "-"
+ ++ integer_to_list(erlang:system_time(seconds))
+ ++ "-"
+ ++ integer_to_list(erlang:unique_integer([positive])).
get_nodefirstname() ->
list_to_atom(get_nodefirstname_string()).
get_nodename() ->
list_to_atom(get_nodefirstname_string()
- ++ "@"
- ++ hostname()).
-
+ ++ "@"
+ ++ hostname()).
+
-define(VERSION_MAGIC, 131).
@@ -1187,88 +1138,88 @@ mk_pid({NodeName, Creation}, Number, Serial) when is_atom(NodeName) ->
mk_pid({atom_to_list(NodeName), Creation}, Number, Serial);
mk_pid({NodeName, Creation}, Number, Serial) ->
case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
- ?PID_EXT,
- ?ATOM_EXT,
- uint16_be(length(NodeName)),
- NodeName,
- uint32_be(Number),
- uint32_be(Serial),
- uint8(Creation)])) of
- Pid when is_pid(Pid) ->
- Pid;
- {'EXIT', {badarg, _}} ->
- exit({badarg, mk_pid, [{NodeName, Creation}, Number, Serial]});
- Other ->
- exit({unexpected_binary_to_term_result, Other})
+ ?PID_EXT,
+ ?ATOM_EXT,
+ uint16_be(length(NodeName)),
+ NodeName,
+ uint32_be(Number),
+ uint32_be(Serial),
+ uint8(Creation)])) of
+ Pid when is_pid(Pid) ->
+ Pid;
+ {'EXIT', {badarg, _}} ->
+ exit({badarg, mk_pid, [{NodeName, Creation}, Number, Serial]});
+ Other ->
+ exit({unexpected_binary_to_term_result, Other})
end.
mk_port({NodeName, Creation}, Number) when is_atom(NodeName) ->
mk_port({atom_to_list(NodeName), Creation}, Number);
mk_port({NodeName, Creation}, Number) ->
case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
- ?PORT_EXT,
- ?ATOM_EXT,
- uint16_be(length(NodeName)),
- NodeName,
- uint32_be(Number),
- uint8(Creation)])) of
- Port when is_port(Port) ->
- Port;
- {'EXIT', {badarg, _}} ->
- exit({badarg, mk_port, [{NodeName, Creation}, Number]});
- Other ->
- exit({unexpected_binary_to_term_result, Other})
+ ?PORT_EXT,
+ ?ATOM_EXT,
+ uint16_be(length(NodeName)),
+ NodeName,
+ uint32_be(Number),
+ uint8(Creation)])) of
+ Port when is_port(Port) ->
+ Port;
+ {'EXIT', {badarg, _}} ->
+ exit({badarg, mk_port, [{NodeName, Creation}, Number]});
+ Other ->
+ exit({unexpected_binary_to_term_result, Other})
end.
mk_ref({NodeName, Creation}, Numbers) when is_atom(NodeName),
- is_integer(Creation),
- is_list(Numbers) ->
+ is_integer(Creation),
+ is_list(Numbers) ->
mk_ref({atom_to_list(NodeName), Creation}, Numbers);
mk_ref({NodeName, Creation}, [Number]) when is_list(NodeName),
- is_integer(Creation),
- is_integer(Number) ->
+ is_integer(Creation),
+ is_integer(Number) ->
case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
- ?REFERENCE_EXT,
- ?ATOM_EXT,
- uint16_be(length(NodeName)),
- NodeName,
- uint32_be(Number),
- uint8(Creation)])) of
- Ref when is_reference(Ref) ->
- Ref;
- {'EXIT', {badarg, _}} ->
- exit({badarg, mk_ref, [{NodeName, Creation}, [Number]]});
- Other ->
- exit({unexpected_binary_to_term_result, Other})
+ ?REFERENCE_EXT,
+ ?ATOM_EXT,
+ uint16_be(length(NodeName)),
+ NodeName,
+ uint32_be(Number),
+ uint8(Creation)])) of
+ Ref when is_reference(Ref) ->
+ Ref;
+ {'EXIT', {badarg, _}} ->
+ exit({badarg, mk_ref, [{NodeName, Creation}, [Number]]});
+ Other ->
+ exit({unexpected_binary_to_term_result, Other})
end;
mk_ref({NodeName, Creation}, Numbers) when is_list(NodeName),
- is_integer(Creation),
- is_list(Numbers) ->
+ is_integer(Creation),
+ is_list(Numbers) ->
case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
- ?NEW_REFERENCE_EXT,
- uint16_be(length(Numbers)),
- ?ATOM_EXT,
- uint16_be(length(NodeName)),
- NodeName,
- uint8(Creation),
- lists:map(fun (N) ->
- uint32_be(N)
- end,
- Numbers)])) of
- Ref when is_reference(Ref) ->
- Ref;
- {'EXIT', {badarg, _}} ->
- exit({badarg, mk_ref, [{NodeName, Creation}, Numbers]});
- Other ->
- exit({unexpected_binary_to_term_result, Other})
+ ?NEW_REFERENCE_EXT,
+ uint16_be(length(Numbers)),
+ ?ATOM_EXT,
+ uint16_be(length(NodeName)),
+ NodeName,
+ uint8(Creation),
+ lists:map(fun (N) ->
+ uint32_be(N)
+ end,
+ Numbers)])) of
+ Ref when is_reference(Ref) ->
+ Ref;
+ {'EXIT', {badarg, _}} ->
+ exit({badarg, mk_ref, [{NodeName, Creation}, Numbers]});
+ Other ->
+ exit({unexpected_binary_to_term_result, Other})
end.
exec_loop() ->
receive
- {exec_fun, Fun} when is_function(Fun) ->
- Fun();
- {sync_exec_fun, From, Fun} when is_pid(From), is_function(Fun) ->
- From ! {sync_exec_fun_res, self(), Fun()}
+ {exec_fun, Fun} when is_function(Fun) ->
+ Fun();
+ {sync_exec_fun, From, Fun} when is_pid(From), is_function(Fun) ->
+ From ! {sync_exec_fun_res, self(), Fun()}
end,
exec_loop().
@@ -1284,6 +1235,6 @@ exec(Pid, Fun) when is_pid(Pid), is_function(Fun) ->
sync_exec(Pid, Fun) when is_pid(Pid), is_function(Fun) ->
Pid ! {sync_exec_fun, self(), Fun},
receive
- {sync_exec_fun_res, Pid, Res} ->
- Res
+ {sync_exec_fun_res, Pid, Res} ->
+ Res
end.
diff --git a/erts/emulator/test/nofrag_SUITE.erl b/erts/emulator/test/nofrag_SUITE.erl
index 3660a58c56..9cc851f9cf 100644
--- a/erts/emulator/test/nofrag_SUITE.erl
+++ b/erts/emulator/test/nofrag_SUITE.erl
@@ -20,57 +20,33 @@
-module(nofrag_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2,
- error_handler/1,error_handler_apply/1,
- error_handler_fixed_apply/1,error_handler_fun/1,
- debug_breakpoint/1]).
+-export([all/0, suite/0,
+ error_handler/1,error_handler_apply/1,
+ error_handler_fixed_apply/1,error_handler_fun/1,
+ debug_breakpoint/1]).
%% Exported functions for an error_handler module.
-export([undefined_function/3,undefined_lambda/3,breakpoint/3]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 3}}].
all() ->
[error_handler, error_handler_apply,
error_handler_fixed_apply, error_handler_fun,
debug_breakpoint].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog = ?t:timetrap(?t:minutes(3)),
- [{watchdog,Dog}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
error_handler(Config) when is_list(Config) ->
- ?line process_flag(error_handler, ?MODULE),
+ process_flag(error_handler, ?MODULE),
%% The term_to_binary/1 - binary_to_term/1 roundtrip is a good way
%% to traverse the entire term.
- ?line Term = collect(1024),
- ?line Term = binary_to_term(term_to_binary(Term)),
- ?line 1024 = length(Term),
- ?line [[a,b,c,d,[e,f,g]]] = lists:usort(Term),
+ Term = collect(1024),
+ Term = binary_to_term(term_to_binary(Term)),
+ 1024 = length(Term),
+ [[a,b,c,d,[e,f,g]]] = lists:usort(Term),
ok.
collect(0) ->
@@ -105,25 +81,25 @@ collect_apply(N, Mod) ->
[C|Res].
error_handler_apply(Config) when is_list(Config) ->
- ?line process_flag(error_handler, ?MODULE),
+ process_flag(error_handler, ?MODULE),
%% The term_to_binary/1 - binary_to_term/1 roundtrip is a good way
%% to traverse the entire term.
- ?line Term = collect_apply(1024, fooblurfbar),
- ?line Term = binary_to_term(term_to_binary(Term)),
- ?line 1024 = length(Term),
- ?line [[{a,42},b,c,d,[e,f,g]]] = lists:usort(Term),
+ Term = collect_apply(1024, fooblurfbar),
+ Term = binary_to_term(term_to_binary(Term)),
+ 1024 = length(Term),
+ [[{a,42},b,c,d,[e,f,g]]] = lists:usort(Term),
ok.
error_handler_fixed_apply(Config) when is_list(Config) ->
- ?line process_flag(error_handler, ?MODULE),
+ process_flag(error_handler, ?MODULE),
%% The term_to_binary/1 - binary_to_term/1 roundtrip is a good way
%% to traverse the entire term.
- ?line Term = collect_fixed_apply(1024, fooblurfbar),
- ?line Term = binary_to_term(term_to_binary(Term)),
- ?line 1024 = length(Term),
- ?line [[{a,2},b,c,d,[e,f,g]]] = lists:usort(Term),
+ Term = collect_fixed_apply(1024, fooblurfbar),
+ Term = binary_to_term(term_to_binary(Term)),
+ 1024 = length(Term),
+ [[{a,2},b,c,d,[e,f,g]]] = lists:usort(Term),
ok.
collect_fixed_apply(0, _) ->
@@ -145,19 +121,19 @@ undefined_function(_Mod, _Name, Args) ->
Args.
error_handler_fun(Config) when is_list(Config) ->
- ?line process_flag(error_handler, ?MODULE),
+ process_flag(error_handler, ?MODULE),
%% fun(A, B, C) -> {A,B,C,X} end in module foobarblurf.
B = <<131,112,0,0,0,84,3,109,96,69,208,5,175,207,75,36,93,112,218,232,222,22,251,0,
- 0,0,0,0,0,0,1,100,0,11,102,111,111,98,97,114,98,108,117,114,102,97,0,98,5,
- 244,197,144,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,
- 0,0,0,46,0,0,0,0,0,104,3,97,1,97,2,97,3>>,
- ?line Fun = binary_to_term(B),
- ?line Term = collect_fun(1024, Fun),
- ?line Term = binary_to_term(term_to_binary(Term)),
- ?line 1024 = length(Term),
- ?line [[{foo,bar},{99,1.0},[e,f,g]]] = lists:usort(Term),
- ?line {env,[{1,2,3}]} = erlang:fun_info(Fun, env),
+ 0,0,0,0,0,0,1,100,0,11,102,111,111,98,97,114,98,108,117,114,102,97,0,98,5,
+ 244,197,144,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,
+ 0,0,0,46,0,0,0,0,0,104,3,97,1,97,2,97,3>>,
+ Fun = binary_to_term(B),
+ Term = collect_fun(1024, Fun),
+ Term = binary_to_term(term_to_binary(Term)),
+ 1024 = length(Term),
+ [[{foo,bar},{99,1.0},[e,f,g]]] = lists:usort(Term),
+ {env,[{1,2,3}]} = erlang:fun_info(Fun, env),
ok.
collect_fun(0, _) ->
@@ -179,13 +155,13 @@ undefined_lambda(foobarblurf, Fun, Args) when is_function(Fun) ->
Args.
debug_breakpoint(Config) when is_list(Config) ->
- ?line process_flag(error_handler, ?MODULE),
- ?line erts_debug:breakpoint({?MODULE,foobar,5}, true),
- ?line Term = break_collect(1024),
- ?line Term = binary_to_term(term_to_binary(Term)),
- ?line 1024 = length(Term),
- ?line [[a,b,c,{d,e},[f,g,h]]] = lists:usort(Term),
- ?line erts_debug:breakpoint({?MODULE,foobar,5}, false),
+ process_flag(error_handler, ?MODULE),
+ erts_debug:breakpoint({?MODULE,foobar,5}, true),
+ Term = break_collect(1024),
+ Term = binary_to_term(term_to_binary(Term)),
+ 1024 = length(Term),
+ [[a,b,c,{d,e},[f,g,h]]] = lists:usort(Term),
+ erts_debug:breakpoint({?MODULE,foobar,5}, false),
ok.
break_collect(0) ->
@@ -202,5 +178,3 @@ foobar(_, _, _, _, _) ->
exit(dont_execute_me).
id(I) -> I.
-
-
diff --git a/erts/emulator/test/num_bif_SUITE.erl b/erts/emulator/test/num_bif_SUITE.erl
index 90b6a36262..04a6f9d18d 100644
--- a/erts/emulator/test/num_bif_SUITE.erl
+++ b/erts/emulator/test/num_bif_SUITE.erl
@@ -1,8 +1,8 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 1997-2014. 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
@@ -14,13 +14,13 @@
%% 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(num_bif_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Tests the BIFs:
%% abs/1
@@ -36,22 +36,22 @@
%% integer_to_binary/2
%% binary_to_integer/1
--export([all/0, suite/0, groups/0, init_per_suite/1, end_per_suite/1,
+-export([all/0, suite/0, groups/0, init_per_suite/1, end_per_suite/1,
init_per_group/2, end_per_group/2, t_abs/1, t_float/1,
t_float_to_string/1, t_integer_to_string/1,
- t_string_to_integer/1,
+ t_string_to_integer/1, t_list_to_integer_edge_cases/1,
t_string_to_float_safe/1, t_string_to_float_risky/1,
t_round/1, t_trunc/1
]).
suite() -> [{ct_hooks,[ts_install_cth]}].
-all() ->
+all() ->
[t_abs, t_float, t_float_to_string, t_integer_to_string,
{group, t_string_to_float}, t_string_to_integer, t_round,
- t_trunc].
+ t_trunc, t_list_to_integer_edge_cases].
-groups() ->
+groups() ->
[{t_string_to_float, [],
[t_string_to_float_safe, t_string_to_float_risky]}].
@@ -73,7 +73,7 @@ t_abs(Config) when is_list(Config) ->
5.5 = abs(id(5.5)),
0.0 = abs(id(0.0)),
100.0 = abs(id(-100.0)),
-
+
%% Integers.
5 = abs(id(5)),
0 = abs(id(0)),
@@ -93,7 +93,7 @@ t_abs(Config) when is_list(Config) ->
BigNum = abs(BigNum),
BigNum = abs(-BigNum),
ok.
-
+
t_float(Config) when is_list(Config) ->
0.0 = float(id(0)),
2.5 = float(id(2.5)),
@@ -109,7 +109,7 @@ t_float(Config) when is_list(Config) ->
%% Extremly big bignums.
Big = id(list_to_integer(id(lists:duplicate(2000, $1)))),
{'EXIT', {badarg, _}} = (catch float(Big)),
-
+
ok.
@@ -183,7 +183,7 @@ t_float_to_string(Config) when is_list(Config) ->
test_fts("1.2300000000e+20",1.23e20, [{scientific, 10}, compact]),
test_fts("1.23000000000000000000e+20",1.23e20, []),
ok.
-
+
test_fts(Expect, Float) ->
Expect = float_to_list(Float),
BinExpect = list_to_binary(Expect),
@@ -255,7 +255,7 @@ t_round(Config) when is_list(Config) ->
256 = round(id(255.6)),
-1033 = round(id(-1033.3)),
-1034 = round(id(-1033.6)),
-
+
% OTP-3722:
X = id((1 bsl 27) - 1),
MX = -X,
@@ -345,9 +345,9 @@ t_integer_to_string(Config) when is_list(Config) ->
%% Invalid types
lists:foreach(fun(Value) ->
- {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch erlang:integer_to_binary(Value)),
- {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch erlang:integer_to_list(Value))
end,[atom,1.2,0.0,[$1,[$2]]]),
@@ -416,27 +416,27 @@ t_string_to_integer(Config) when is_list(Config) ->
%% Invalid types
lists:foreach(fun(Value) ->
- {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch binary_to_integer(Value)),
- {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch erlang:list_to_integer(Value))
end,[atom,1.2,0.0,[$1,[$2]]]),
-
+
% Default base error cases
lists:foreach(fun(Value) ->
- {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch erlang:binary_to_integer(
list_to_binary(Value))),
- {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch erlang:list_to_integer(Value))
end,["1.0"," 1"," -1","","+"]),
-
+
% Custom base error cases
lists:foreach(fun({Value,Base}) ->
- {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch binary_to_integer(
list_to_binary(Value),Base)),
- {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch erlang:list_to_integer(Value,Base))
end,[{" 1",1},{" 1",37},{"2",2},{"C",11},
{"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111z",16},
@@ -449,10 +449,61 @@ t_string_to_integer(Config) when is_list(Config) ->
ok.
+%% Tests edge cases for list_to_integer; compares with known good values
+
+t_list_to_integer_edge_cases(Config) when is_list(Config) ->
+ %% Take integer literals and compare to their representation in ExtTerm
+ T = [
+ {16, "0", <<131,97,0>>},
+ {16, "-0", <<131,97,0>>},
+
+ {16, "f", <<131,97,15>>},
+ {16, "-f", <<131,98,255,255,255,241>>},
+
+ {16, "0000000000000000000000000000000000000000000000000f",
+ <<131,97,15>>},
+ {16, "-0000000000000000000000000000000000000000000000000f",
+ <<131,98,255,255,255,241>>},
+
+ {16, "ffffffff", <<131,110,4,0,255,255,255,255>>},
+ {16, "-ffffffff", <<131,110,4,1,255,255,255,255>>},
+
+ {16, "7fffffff", <<131,110,4,0,255,255,255,127>>},
+ {16, "-7fffffff", <<131,98,128,0,0,1>>},
+
+ {16, "ffffffffffffffff",
+ <<131,110,8,0,255,255,255,255,255,255,255,255>>},
+ {16, "-ffffffffffffffff",
+ <<131,110,8,1,255,255,255,255,255,255,255,255>>},
+
+ {16, "7fffffffffffffff",
+ <<131,110,8,0,255,255,255,255,255,255,255,127>>},
+ {16, "-7fffffffffffffff",
+ <<131,110,8,1,255,255,255,255,255,255,255,127>>},
+
+ %% Alleged 32-bit corner case (should not happen on 64-bit). At 32-4
+ %% bits we may corrupt sign bit and fall out of SMALL_INT range.
+ {2, "1000000000000000000000000000", <<131,98,8,0,0,0>>},
+ {2, "-1000000000000000000000000000", <<131,98,248,0,0,0>>},
+
+ %% 64-bit corner case (should not happen on 32-bit) at 64-4 bits we
+ %% corrupt sign bit and fall out of SMALL_INT range (bam! all dead)
+ {2, "100000000000000000000000000000000000000000000000000000000000",
+ <<131,110,8,0,0,0,0,0,0,0,0,8>>},
+ {2, "-100000000000000000000000000000000000000000000000000000000000",
+ <<131,110,8,1,0,0,0,0,0,0,0,8>>}
+ ],
+ [begin
+ io:format("~s base ~p vs ~p~n", [Str, Base, Bin]),
+ FromStr = list_to_integer(Str, Base),
+ FromStr = binary_to_term(Bin)
+ end || {Base, Str, Bin} <- T],
+ ok.
+
test_sti(Num) ->
[begin
io:format("Testing ~p:~p",[Num,Base]),
- test_sti(Num,Base)
+ test_sti(Num,Base)
end|| Base <- lists:seq(2,36)].
test_sti(Num,Base) ->
diff --git a/erts/emulator/test/old_mod.erl b/erts/emulator/test/old_mod.erl
index 1586a024d8..0da40ec430 100644
--- a/erts/emulator/test/old_mod.erl
+++ b/erts/emulator/test/old_mod.erl
@@ -23,26 +23,26 @@
-export([sort_on_old_node/1, sorter/3]).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
sorter(Receiver, Ref, List) ->
Receiver ! {Ref, lists:sort(List)}.
sort_on_old_node(List) when is_list(List) ->
OldVersion = "r10",
- ?line Pa = filename:dirname(code:which(?MODULE)),
- ?line {X, Y, Z} = now(),
- ?line NodeName = list_to_atom(OldVersion
- ++ "_"
- ++ integer_to_list(X)
- ++ integer_to_list(Y)
- ++ integer_to_list(Z)),
- ?line {ok, Node} = ?t:start_node(NodeName,
- peer,
- [{args, " -pa " ++ Pa},
- {erl, [{release, OldVersion++"b_patched"}]}]),
- ?line Ref = make_ref(),
- ?line spawn_link(Node, ?MODULE, sorter, [self(), Ref, List]),
- ?line SortedPids = receive {Ref, SP} -> SP end,
- ?line true = ?t:stop_node(Node),
- ?line SortedPids.
+ Pa = filename:dirname(code:which(?MODULE)),
+ {X, Y, Z} = now(),
+ NodeName = list_to_atom(OldVersion
+ ++ "_"
+ ++ integer_to_list(X)
+ ++ integer_to_list(Y)
+ ++ integer_to_list(Z)),
+ {ok, Node} = test_server:start_node(NodeName,
+ peer,
+ [{args, " -pa " ++ Pa},
+ {erl, [{release, OldVersion++"b_patched"}]}]),
+ Ref = make_ref(),
+ spawn_link(Node, ?MODULE, sorter, [self(), Ref, List]),
+ SortedPids = receive {Ref, SP} -> SP end,
+ true = test_server:stop_node(Node),
+ SortedPids.
diff --git a/erts/emulator/test/old_scheduler_SUITE.erl b/erts/emulator/test/old_scheduler_SUITE.erl
index 97c99fe07b..9d40417d0a 100644
--- a/erts/emulator/test/old_scheduler_SUITE.erl
+++ b/erts/emulator/test/old_scheduler_SUITE.erl
@@ -20,43 +20,27 @@
-module(old_scheduler_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2, end_per_testcase/2]).
+-export([all/0, suite/0,
+ init_per_testcase/2, end_per_testcase/2]).
-export([equal/1, many_low/1, few_low/1, max/1, high/1]).
--define(default_timeout, ?t:minutes(11)).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 11}}].
all() ->
case catch erlang:system_info(modified_timing_level) of
- Level when is_integer(Level) ->
- {skipped,
- "Modified timing (level " ++
- integer_to_list(Level) ++
- ") is enabled. Testcases gets messed "
- "up by modfied timing."};
- _ -> [equal, many_low, few_low, max, high]
+ Level when is_integer(Level) ->
+ {skipped,
+ "Modified timing (level " ++
+ integer_to_list(Level) ++
+ ") is enabled. Testcases gets messed "
+ "up by modfied timing."};
+ _ -> [equal, many_low, few_low, max, high]
end.
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
%%-----------------------------------------------------------------------------------
%% TEST SUITE DESCRIPTION
@@ -78,35 +62,30 @@ end_per_group(_GroupName, Config) ->
%%-----------------------------------------------------------------------------------
init_per_testcase(_Case, Config) ->
- ?line Dog = test_server:timetrap(?default_timeout),
%% main test process needs max prio
- ?line Prio = process_flag(priority, max),
- ?line MS = erlang:system_flag(multi_scheduling, block),
- [{prio,Prio},{watchdog,Dog},{multi_scheduling, MS}|Config].
+ Prio = process_flag(priority, max),
+ MS = erlang:system_flag(multi_scheduling, block),
+ [{prio,Prio},{multi_scheduling, MS}|Config].
end_per_testcase(_Case, Config) ->
erlang:system_flag(multi_scheduling, unblock),
- Dog=?config(watchdog, Config),
- Prio=?config(prio, Config),
+ Prio=proplists:get_value(prio, Config),
process_flag(priority, Prio),
- test_server:timetrap_cancel(Dog),
ok.
ok(Config) when is_list(Config) ->
- case ?config(multi_scheduling, Config) of
- blocked ->
- {comment,
- "Multi-scheduling blocked during test. This testcase was not "
- "written to work with multiple schedulers."};
- _ -> ok
+ case proplists:get_value(multi_scheduling, Config) of
+ blocked ->
+ {comment,
+ "Multi-scheduling blocked during test. This testcase was not "
+ "written to work with multiple schedulers."};
+ _ -> ok
end.
%% Run equal number of low and normal prio processes.
-equal(suite) -> [];
-equal(doc) -> [];
equal(Config) when is_list(Config) ->
- ?line Self = self(),
+ Self = self(),
%% specify number of test processes to run
Normal = {normal,500},
@@ -116,102 +95,96 @@ equal(Config) when is_list(Config) ->
Time = 30,
%% start controllers
- ?line Receiver =
- spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Normal, Low) end),
- ?line Starter =
- spawn(fun() -> starter(Normal, Low, Receiver) end),
+ Receiver =
+ spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Normal, Low) end),
+ Starter =
+ spawn(fun() -> starter(Normal, Low, Receiver) end),
%% receive test data from Receiver
- ?line {NRs,NAvg,LRs,LAvg,Ratio} =
- receive
- {Receiver,Res} -> Res
- end,
+ {NRs,NAvg,LRs,LAvg,Ratio} =
+ receive
+ {Receiver,Res} -> Res
+ end,
%% stop controllers and test processes
- ?line exit(Starter, kill),
- ?line exit(Receiver, kill),
+ exit(Starter, kill),
+ exit(Receiver, kill),
io:format("Reports: ~w normal (~w/proc), ~w low (~w/proc). Ratio: ~w~n",
- [NRs,NAvg,LRs,LAvg,Ratio]),
+ [NRs,NAvg,LRs,LAvg,Ratio]),
%% runtime ratio between normal and low should be ~8
if Ratio < 7.5 ; Ratio > 8.5 ->
- ?t:fail({bad_ratio,Ratio});
+ ct:fail({bad_ratio,Ratio});
true ->
- ok(Config)
+ ok(Config)
end.
%% Run many low and few normal prio processes.
-many_low(suite) -> [];
-many_low(doc) -> [];
many_low(Config) when is_list(Config) ->
- ?line Self = self(),
+ Self = self(),
Normal = {normal,1},
Low = {low,1000},
%% specify time of test (in seconds)
Time = 30,
- ?line Receiver =
- spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Normal, Low) end),
- ?line Starter =
- spawn(fun() -> starter(Normal, Low, Receiver) end),
- ?line {NRs,NAvg,LRs,LAvg,Ratio} =
- receive
- {Receiver,Res} -> Res
- end,
- ?line exit(Starter, kill),
- ?line exit(Receiver, kill),
+ Receiver =
+ spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Normal, Low) end),
+ Starter =
+ spawn(fun() -> starter(Normal, Low, Receiver) end),
+ {NRs,NAvg,LRs,LAvg,Ratio} =
+ receive
+ {Receiver,Res} -> Res
+ end,
+ exit(Starter, kill),
+ exit(Receiver, kill),
io:format("Reports: ~w normal (~w/proc), ~w low (~w/proc). Ratio: ~w~n",
- [NRs,NAvg,LRs,LAvg,Ratio]),
+ [NRs,NAvg,LRs,LAvg,Ratio]),
if Ratio < 7.5 ; Ratio > 8.5 ->
- ?t:fail({bad_ratio,Ratio});
+ ct:fail({bad_ratio,Ratio});
true ->
- ok(Config)
+ ok(Config)
end.
%% Run few low and many normal prio processes.
-few_low(suite) -> [];
-few_low(doc) -> [];
few_low(Config) when is_list(Config) ->
- ?line Self = self(),
+ Self = self(),
Normal = {normal,1000},
Low = {low,1},
%% specify time of test (in seconds)
Time = 30,
- ?line Receiver =
- spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Normal, Low) end),
- ?line Starter =
- spawn(fun() -> starter(Normal, Low, Receiver) end),
- ?line {NRs,NAvg,LRs,LAvg,Ratio} =
- receive
- {Receiver,Res} -> Res
- end,
- ?line exit(Starter, kill),
- ?line exit(Receiver, kill),
+ Receiver =
+ spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Normal, Low) end),
+ Starter =
+ spawn(fun() -> starter(Normal, Low, Receiver) end),
+ {NRs,NAvg,LRs,LAvg,Ratio} =
+ receive
+ {Receiver,Res} -> Res
+ end,
+ exit(Starter, kill),
+ exit(Receiver, kill),
io:format("Reports: ~w normal (~w/proc), ~w low (~w/proc). Ratio: ~w~n",
- [NRs,NAvg,LRs,LAvg,Ratio]),
+ [NRs,NAvg,LRs,LAvg,Ratio]),
if Ratio < 7.0 ; Ratio > 8.5 ->
- ?t:fail({bad_ratio,Ratio});
+ ct:fail({bad_ratio,Ratio});
true ->
- ok(Config)
+ ok(Config)
end.
%% Run max prio processes and verify they get at least as much
%% runtime as high, normal and low.
-max(suite) -> [];
-max(doc) -> [];
max(Config) when is_list(Config) ->
max = process_flag(priority, max), % should already be max (init_per_tc)
- ?line Self = self(),
+ Self = self(),
Max = {max,2},
High = {high,2},
Normal = {normal,100},
@@ -220,69 +193,67 @@ max(Config) when is_list(Config) ->
%% specify time of test (in seconds)
Time = 30,
- ?line Receiver1 =
- spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Max, High) end),
- ?line Starter1 =
- spawn(fun() -> starter(Max, High, Receiver1) end),
- ?line {M1Rs,M1Avg,HRs,HAvg,Ratio1} =
- receive
- {Receiver1,Res1} -> Res1
- end,
- ?line exit(Starter1, kill),
- ?line exit(Receiver1, kill),
+ Receiver1 =
+ spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Max, High) end),
+ Starter1 =
+ spawn(fun() -> starter(Max, High, Receiver1) end),
+ {M1Rs,M1Avg,HRs,HAvg,Ratio1} =
+ receive
+ {Receiver1,Res1} -> Res1
+ end,
+ exit(Starter1, kill),
+ exit(Receiver1, kill),
io:format("Reports: ~w max (~w/proc), ~w high (~w/proc). Ratio: ~w~n",
- [M1Rs,M1Avg,HRs,HAvg,Ratio1]),
+ [M1Rs,M1Avg,HRs,HAvg,Ratio1]),
if Ratio1 < 1.0 ->
- ?t:fail({bad_ratio,Ratio1});
+ ct:fail({bad_ratio,Ratio1});
true ->
- ok(Config)
+ ok(Config)
end,
- ?line Receiver2 =
- spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Max, Normal) end),
- ?line Starter2 =
- spawn(fun() -> starter(Max, Normal, Receiver2) end),
- ?line {M2Rs,M2Avg,NRs,NAvg,Ratio2} =
- receive
- {Receiver2,Res2} -> Res2
- end,
- ?line exit(Starter2, kill),
- ?line exit(Receiver2, kill),
+ Receiver2 =
+ spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Max, Normal) end),
+ Starter2 =
+ spawn(fun() -> starter(Max, Normal, Receiver2) end),
+ {M2Rs,M2Avg,NRs,NAvg,Ratio2} =
+ receive
+ {Receiver2,Res2} -> Res2
+ end,
+ exit(Starter2, kill),
+ exit(Receiver2, kill),
io:format("Reports: ~w max (~w/proc), ~w normal (~w/proc). Ratio: ~w~n",
- [M2Rs,M2Avg,NRs,NAvg,Ratio2]),
+ [M2Rs,M2Avg,NRs,NAvg,Ratio2]),
if Ratio2 < 1.0 ->
- ?t:fail({bad_ratio,Ratio2});
+ ct:fail({bad_ratio,Ratio2});
true ->
- ok
+ ok
end,
- ?line Receiver3 =
- spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Max, Low) end),
- ?line Starter3 =
- spawn(fun() -> starter(Max, Low, Receiver3) end),
- ?line {M3Rs,M3Avg,LRs,LAvg,Ratio3} =
- receive
- {Receiver3,Res3} -> Res3
- end,
- ?line exit(Starter3, kill),
- ?line exit(Receiver3, kill),
+ Receiver3 =
+ spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Max, Low) end),
+ Starter3 =
+ spawn(fun() -> starter(Max, Low, Receiver3) end),
+ {M3Rs,M3Avg,LRs,LAvg,Ratio3} =
+ receive
+ {Receiver3,Res3} -> Res3
+ end,
+ exit(Starter3, kill),
+ exit(Receiver3, kill),
io:format("Reports: ~w max (~w/proc), ~w low (~w/proc). Ratio: ~w~n",
- [M3Rs,M3Avg,LRs,LAvg,Ratio3]),
+ [M3Rs,M3Avg,LRs,LAvg,Ratio3]),
if Ratio3 < 1.0 ->
- ?t:fail({bad_ratio,Ratio3});
+ ct:fail({bad_ratio,Ratio3});
true ->
- ok(Config)
+ ok(Config)
end.
%% Run high prio processes and verify they get at least as much
%% runtime as normal and low.
-high(suite) -> [];
-high(doc) -> [];
high(Config) when is_list(Config) ->
max = process_flag(priority, max), % should already be max (init_per_tc)
- ?line Self = self(),
+ Self = self(),
High = {high,2},
Normal = {normal,100},
Low = {low,100},
@@ -290,40 +261,40 @@ high(Config) when is_list(Config) ->
%% specify time of test (in seconds)
Time = 30,
- ?line Receiver1 =
- spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, High, Normal) end),
- ?line Starter1 =
- spawn(fun() -> starter(High, Normal, Receiver1) end),
- ?line {H1Rs,H1Avg,NRs,NAvg,Ratio1} =
- receive
- {Receiver1,Res1} -> Res1
- end,
- ?line exit(Starter1, kill),
- ?line exit(Receiver1, kill),
+ Receiver1 =
+ spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, High, Normal) end),
+ Starter1 =
+ spawn(fun() -> starter(High, Normal, Receiver1) end),
+ {H1Rs,H1Avg,NRs,NAvg,Ratio1} =
+ receive
+ {Receiver1,Res1} -> Res1
+ end,
+ exit(Starter1, kill),
+ exit(Receiver1, kill),
io:format("Reports: ~w high (~w/proc), ~w normal (~w/proc). Ratio: ~w~n",
- [H1Rs,H1Avg,NRs,NAvg,Ratio1]),
+ [H1Rs,H1Avg,NRs,NAvg,Ratio1]),
if Ratio1 < 1.0 ->
- ?t:fail({bad_ratio,Ratio1});
+ ct:fail({bad_ratio,Ratio1});
true ->
- ok
+ ok
end,
- ?line Receiver2 =
- spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, High, Low) end),
- ?line Starter2 =
- spawn(fun() -> starter(High, Low, Receiver2) end),
- ?line {H2Rs,H2Avg,LRs,LAvg,Ratio2} =
- receive
- {Receiver2,Res2} -> Res2
- end,
- ?line exit(Starter2, kill),
- ?line exit(Receiver2, kill),
+ Receiver2 =
+ spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, High, Low) end),
+ Starter2 =
+ spawn(fun() -> starter(High, Low, Receiver2) end),
+ {H2Rs,H2Avg,LRs,LAvg,Ratio2} =
+ receive
+ {Receiver2,Res2} -> Res2
+ end,
+ exit(Starter2, kill),
+ exit(Receiver2, kill),
io:format("Reports: ~w high (~w/proc), ~w low (~w/proc). Ratio: ~w~n",
- [H2Rs,H2Avg,LRs,LAvg,Ratio2]),
+ [H2Rs,H2Avg,LRs,LAvg,Ratio2]),
if Ratio2 < 1.0 ->
- ?t:fail({bad_ratio,Ratio2});
+ ct:fail({bad_ratio,Ratio2});
true ->
- ok(Config)
+ ok(Config)
end.
@@ -338,38 +309,38 @@ receiver(T0, TimeSec, Main, {P1,P1N}, {P2,P2N}) ->
%% uncomment lines below to get life sign (debug)
receiver(T0, Time, Main, P1,P1N,P1Rs, P2,P2N,P2Rs, 0) ->
-% T = erlang:convert_time_unit(erlang:monotonic_time() - T0, native, milli_seconds),
-% erlang:display({round(T/1000),P1Rs,P2Rs}),
+ % T = erlang:convert_time_unit(erlang:monotonic_time() - T0, native, milli_seconds),
+ % erlang:display({round(T/1000),P1Rs,P2Rs}),
receiver(T0, Time, Main, P1,P1N,P1Rs, P2,P2N,P2Rs, 100000);
receiver(T0, Time, Main, P1,P1N,P1Rs, P2,P2N,P2Rs, C) ->
Remain = Time - erlang:convert_time_unit(erlang:monotonic_time() - T0,
- native, milli_seconds), % test time remaining
+ native, milli_seconds), % test time remaining
Remain1 = if Remain < 0 ->
- 0;
- true ->
- Remain
- end,
+ 0;
+ true ->
+ Remain
+ end,
{P1Rs1,P2Rs1} =
- receive
- {_Pid,P1} -> % report from a P1 process
- {P1Rs+1,P2Rs};
- {_Pid,P2} -> % report from a P2 process
- {P1Rs,P2Rs+1}
- after Remain1 ->
- {P1Rs,P2Rs}
- end,
+ receive
+ {_Pid,P1} -> % report from a P1 process
+ {P1Rs+1,P2Rs};
+ {_Pid,P2} -> % report from a P2 process
+ {P1Rs,P2Rs+1}
+ after Remain1 ->
+ {P1Rs,P2Rs}
+ end,
if Remain > 0 -> % keep going
- receiver(T0, Time, Main, P1,P1N,P1Rs1, P2,P2N,P2Rs1, C-1);
+ receiver(T0, Time, Main, P1,P1N,P1Rs1, P2,P2N,P2Rs1, C-1);
true -> % finish
- %% calculate results and send to main test process
- P1Avg = P1Rs1/P1N,
- P2Avg = P2Rs1/P2N,
- Ratio = if P2Avg < 1.0 -> P1Avg;
- true -> P1Avg/P2Avg
- end,
- Main ! {self(),{P1Rs1,round(P1Avg),P2Rs1,round(P2Avg),Ratio}},
- flush_loop()
+ %% calculate results and send to main test process
+ P1Avg = P1Rs1/P1N,
+ P2Avg = P2Rs1/P2N,
+ Ratio = if P2Avg < 1.0 -> P1Avg;
+ true -> P1Avg/P2Avg
+ end,
+ Main ! {self(),{P1Rs1,round(P1Avg),P2Rs1,round(P2Avg),Ratio}},
+ flush_loop()
end.
starter({P1,P1N}, {P2,P2N}, Receiver) ->
@@ -395,8 +366,8 @@ p_loop(100, Prio, Receiver) ->
receive after 0 -> ok end,
%% if Receiver gone, we're done
case is_process_alive(Receiver) of
- false -> exit(bye);
- true -> ok
+ false -> exit(bye);
+ true -> ok
end,
%% send report
Receiver ! {self(),Prio},
@@ -404,10 +375,10 @@ p_loop(100, Prio, Receiver) ->
p_loop(N, Prio, Receiver) ->
p_loop(N+1, Prio, Receiver).
-
+
flush_loop() ->
receive _ ->
- ok
+ ok
end,
flush_loop().
diff --git a/erts/emulator/test/op_SUITE.erl b/erts/emulator/test/op_SUITE.erl
index 6eda78a57b..562cf1c92d 100644
--- a/erts/emulator/test/op_SUITE.erl
+++ b/erts/emulator/test/op_SUITE.erl
@@ -20,68 +20,44 @@
-module(op_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2,
- bsl_bsr/1,logical/1,t_not/1,relop_simple/1,relop/1,complex_relop/1]).
+-export([all/0, suite/0,
+ bsl_bsr/1,logical/1,t_not/1,relop_simple/1,relop/1,complex_relop/1]).
-export([]).
-import(lists, [foldl/3,flatmap/2]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 3}}].
all() ->
[bsl_bsr, logical, t_not, relop_simple, relop,
complex_relop].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog=?t:timetrap(?t:minutes(3)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
%% Test the bsl and bsr operators.
bsl_bsr(Config) when is_list(Config) ->
Vs = [unvalue(V) || V <- [-16#8000009-2,-1,0,1,2,73,16#8000000,bad,[]]],
Cases = [{Op,X,Y} || Op <- ['bsr','bsl'], X <- Vs, Y <- Vs],
- ?line run_test_module(Cases, false),
+ run_test_module(Cases, false),
{comment,integer_to_list(length(Cases)) ++ " cases"}.
-logical(doc) -> "Test the logical operators and internal BIFs.";
+%% Test the logical operators and internal BIFs.
logical(Config) when is_list(Config) ->
Vs0 = [true,false,bad],
Vs = [unvalue(V) || V <- Vs0],
Cases = [{Op,X,Y} || Op <- ['and','or','xor'], X <- Vs, Y <- Vs],
- ?line run_test_module(Cases, false),
+ run_test_module(Cases, false),
{comment,integer_to_list(length(Cases)) ++ " cases"}.
-t_not(doc) -> "Test the not operator and internal BIFs.";
+%% Test the not operator and internal BIFs.
t_not(Config) when is_list(Config) ->
- ?line Cases = [{'not',unvalue(V)} || V <- [true,false,42,bad]],
- ?line run_test_module(Cases, false),
+ Cases = [{'not',unvalue(V)} || V <- [true,false,42,bad]],
+ run_test_module(Cases, false),
{comment,integer_to_list(length(Cases)) ++ " cases"}.
-relop_simple(doc) -> "Test that simlpe relations between relation operators hold.";
+%% Test that simlpe relations between relation operators hold.
relop_simple(Config) when is_list(Config) ->
Big1 = 19738924729729787487784874,
Big2 = 38374938373887374983978484,
@@ -90,51 +66,52 @@ relop_simple(Config) when is_list(Config) ->
T1 = erlang:make_tuple(3,87),
T2 = erlang:make_tuple(3,87),
Terms = [-F2,Big2,-F1,-Big1,-33,-33.0,0,0.0,42,42.0,Big1,F1,Big2,F2,a,b,
- {T1,a},{T2,b},[T1,Big1],[T2,Big2]],
-
- ?line Combos = [{V1,V2} || V1 <- Terms, V2 <- Terms],
-
+ {T1,a},{T2,b},[T1,Big1],[T2,Big2]],
+
+ Combos = [{V1,V2} || V1 <- Terms, V2 <- Terms],
+
lists:foreach(fun({A,B}) -> relop_simple_do(A,B) end,
- Combos),
-
- repeat(fun() -> Size = random:uniform(100),
- Rnd1 = make_rand_term(Size),
- {Rnd2,0} = clone_and_mutate(Rnd1, random:uniform(Size)),
- relop_simple_do(Rnd1,Rnd2)
- end,
- 1000),
+ Combos),
+
+ repeat(fun() ->
+ Size = rand:uniform(100),
+ Rnd1 = make_rand_term(Size),
+ {Rnd2,0} = clone_and_mutate(Rnd1, rand:uniform(Size)),
+ relop_simple_do(Rnd1,Rnd2)
+ end,
+ 1000),
ok.
relop_simple_do(V1,V2) ->
%%io:format("compare ~p\n and ~p\n",[V1,V2]),
L = V1 < V2,
- ?line L = not (V1 >= V2),
- ?line L = V2 > V1,
- ?line L = not (V2 =< V1),
+ L = not (V1 >= V2),
+ L = V2 > V1,
+ L = not (V2 =< V1),
G = V1 > V2,
- ?line G = not (V1 =< V2),
- ?line G = V2 < V1,
- ?line G = not (V2 >= V1),
-
+ G = not (V1 =< V2),
+ G = V2 < V1,
+ G = not (V2 >= V1),
+
ID = V1 =:= V2,
- ?line ID = V2 =:= V1,
- ?line ID = not (V1 =/= V2),
- ?line ID = not (V2 =/= V1),
-
+ ID = V2 =:= V1,
+ ID = not (V1 =/= V2),
+ ID = not (V2 =/= V1),
+
EQ = V1 == V2,
- ?line EQ = V2 == V1,
- ?line EQ = not (V1 /= V2),
- ?line EQ = not (V2 /= V1),
-
- ?line case {L, EQ, ID, G, cmp_emu(V1,V2)} of
- { true, false, false, false, -1} -> ok;
- {false, true, false, false, 0} -> ok;
- {false, true, true, false, 0} -> ok;
- {false, false, false, true, +1} -> ok
- end.
-
+ EQ = V2 == V1,
+ EQ = not (V1 /= V2),
+ EQ = not (V2 /= V1),
+
+ case {L, EQ, ID, G, cmp_emu(V1,V2)} of
+ { true, false, false, false, -1} -> ok;
+ {false, true, false, false, 0} -> ok;
+ {false, true, true, false, 0} -> ok;
+ {false, false, false, true, +1} -> ok
+ end.
+
%% Emulate internal "cmp"
cmp_emu(A,B) when is_tuple(A), is_tuple(B) ->
SA = size(A),
@@ -145,8 +122,8 @@ cmp_emu(A,B) when is_tuple(A), is_tuple(B) ->
end;
cmp_emu([A|TA],[B|TB]) ->
case cmp_emu(A,B) of
- 0 -> cmp_emu(TA,TB);
- CMP -> CMP
+ 0 -> cmp_emu(TA,TB);
+ CMP -> CMP
end;
cmp_emu(A,B) ->
%% We cheat and use real "cmp" for the primitive types.
@@ -154,48 +131,48 @@ cmp_emu(A,B) ->
A > B -> +1;
true -> 0
end.
-
+
make_rand_term(1) ->
make_rand_term_single();
make_rand_term(Arity) ->
- case random:uniform(3) of
- 1 ->
- make_rand_list(Arity);
- 2 ->
- list_to_tuple(make_rand_list(Arity));
- 3 ->
- {Car,Rest} = make_rand_term_rand_size(Arity),
- [Car|make_rand_term(Rest)]
+ case rand:uniform(3) of
+ 1 ->
+ make_rand_list(Arity);
+ 2 ->
+ list_to_tuple(make_rand_list(Arity));
+ 3 ->
+ {Car,Rest} = make_rand_term_rand_size(Arity),
+ [Car|make_rand_term(Rest)]
end.
make_rand_term_single() ->
- Range = 1 bsl random:uniform(200),
- case random:uniform(12) of
- 1 -> random;
- 2 -> uniform;
- 3 -> random:uniform(Range) - (Range div 2);
- 4 -> Range * (random:uniform() - 0.5);
- 5 -> 0;
- 6 -> 0.0;
- 7 -> make_ref();
- 8 -> self();
- 9 -> term_to_binary(random:uniform(Range));
- 10 -> fun(X) -> X*Range end;
- 11 -> fun(X) -> X/Range end;
- 12 -> []
+ Range = 1 bsl rand:uniform(200),
+ case rand:uniform(12) of
+ 1 -> random;
+ 2 -> uniform;
+ 3 -> rand:uniform(Range) - (Range div 2);
+ 4 -> Range * (rand:uniform() - 0.5);
+ 5 -> 0;
+ 6 -> 0.0;
+ 7 -> make_ref();
+ 8 -> self();
+ 9 -> term_to_binary(rand:uniform(Range));
+ 10 -> fun(X) -> X*Range end;
+ 11 -> fun(X) -> X/Range end;
+ 12 -> []
end.
make_rand_term_rand_size(1) ->
{make_rand_term(1), 0};
make_rand_term_rand_size(MaxArity) ->
- Arity = random:uniform(MaxArity-1),
+ Arity = rand:uniform(MaxArity-1),
{make_rand_term(Arity), MaxArity-Arity}.
make_rand_list(0) -> [];
make_rand_list(Arity) ->
{Term, Rest} = make_rand_term_rand_size(Arity),
[Term | make_rand_list(Rest)].
-
+
clone_and_mutate(Term, 0) ->
{clone(Term), 0};
@@ -218,82 +195,81 @@ clone(Term) ->
my_list_to_tuple(List) ->
try list_to_tuple(List)
catch
- error:badarg ->
- %%io:format("my_list_to_tuple got badarg exception.\n"),
- list_to_tuple(purify_list(List))
+ error:badarg ->
+ %%io:format("my_list_to_tuple got badarg exception.\n"),
+ list_to_tuple(purify_list(List))
end.
-
+
purify_list(List) ->
lists:reverse(purify_list(List, [])).
purify_list([], Acc) -> Acc;
purify_list([H|T], Acc) -> purify_list(T, [H|Acc]);
purify_list(Other, Acc) -> [Other|Acc].
-
-relop(doc) -> "Test the relational operators and internal BIFs on literals.";
+
+%% Test the relational operators and internal BIFs on literals.
relop(Config) when is_list(Config) ->
Big1 = -38374938373887374983978484,
Big2 = 19738924729729787487784874,
F1 = float(Big1),
F2 = float(Big2),
Vs0 = [a,b,-33,-33.0,0,0.0,42,42.0,Big1,Big2,F1,F2],
- ?line Vs = [unvalue(V) || V <- Vs0],
+ Vs = [unvalue(V) || V <- Vs0],
Ops = ['==', '/=', '=:=', '=/=', '<', '=<', '>', '>='],
- ?line binop(Ops, Vs).
+ binop(Ops, Vs).
-complex_relop(doc) ->
- "Test the relational operators and internal BIFs on lists and tuples.";
+%% Test the relational operators and internal BIFs on lists and tuples.
complex_relop(Config) when is_list(Config) ->
Big = 99678557475484872464269855544643333,
Float = float(Big),
Vs0 = [an_atom,42.0,42,Big,Float],
Vs = flatmap(fun(X) -> [unvalue({X}),unvalue([X])] end, Vs0),
Ops = ['==', '/=', '=:=', '=/=', '<', '=<', '>', '>='],
- ?line binop(Ops, Vs).
+ binop(Ops, Vs).
binop(Ops, Vs) ->
- Run = fun(Op, N) -> ?line Cases = [{Op,V1,V2} || V1 <- Vs, V2 <- Vs],
- ?line run_test_module(Cases, true),
- N + length(Cases) end,
- ?line NumCases = foldl(Run, 0, Ops),
+ Run = fun(Op, N) -> Cases = [{Op,V1,V2} || V1 <- Vs, V2 <- Vs],
+ run_test_module(Cases, true),
+ N + length(Cases) end,
+ NumCases = foldl(Run, 0, Ops),
{comment,integer_to_list(NumCases) ++ " cases"}.
-
+
run_test_module(Cases, GuardsOk) ->
- ?line Es = [expr(C) || C <- Cases],
- ?line Ok = unvalue(ok),
- ?line Gts = case GuardsOk of
- true ->
- Ges = [guard_expr(C) || C <- Cases],
- ?line lists:foldr(fun guard_test/2, [Ok], Ges);
- false ->
- [Ok]
- end,
- ?line Fun1 = make_function(guard_tests, Gts),
- ?line Bts = lists:foldr(fun body_test/2, [Ok], Es),
- ?line Fun2 = make_function(body_tests, Bts),
- ?line Bbts = lists:foldr(fun internal_bif/2, [Ok], Es),
- ?line Fun3 = make_function(bif_tests, Bbts),
- ?line Id = {function,1,id,1,[{clause,1,[{var,1,'I'}],[],[{var,1,'I'}]}]},
+ Es = [expr(C) || C <- Cases],
+ Ok = unvalue(ok),
+ Gts = case GuardsOk of
+ true ->
+ Ges = [guard_expr(C) || C <- Cases],
+ lists:foldr(fun guard_test/2, [Ok], Ges);
+ false ->
+ [Ok]
+ end,
+ Fun1 = make_function(guard_tests, Gts),
+ Bts = lists:foldr(fun body_test/2, [Ok], Es),
+ Fun2 = make_function(body_tests, Bts),
+ Bbts = lists:foldr(fun internal_bif/2, [Ok], Es),
+ Fun3 = make_function(bif_tests, Bbts),
+ Id = {function,1,id,1,[{clause,1,[{var,1,'I'}],[],[{var,1,'I'}]}]},
Module0 = make_module(op_tests, [Fun1,Fun2,Fun3,Id]),
Module = erl_parse:new_anno(Module0),
- ?line lists:foreach(fun(F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Module),
+ lists:foreach(fun(F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Module),
%% Compile, load, and run the generated module.
- Native = case ?t:is_native(?MODULE) of
- true -> [native];
- false -> []
- end,
- ?line {ok,Mod,Code1} = compile:forms(Module, [time|Native]),
- ?line code:delete(Mod),
- ?line code:purge(Mod),
- ?line {module,Mod} = code:load_binary(Mod, Mod, Code1),
- ?line run_function(Mod, guard_tests),
- ?line run_function(Mod, body_tests),
- ?line run_function(Mod, bif_tests),
-
- ?line true = code:delete(Mod),
- ?line code:purge(Mod),
+ Native = case test_server:is_native(?MODULE) of
+ true -> [native];
+ false -> []
+ end,
+ {ok,Mod,Code1} = compile:forms(Module, [time|Native]),
+ code:delete(Mod),
+ code:purge(Mod),
+ {module,Mod} = code:load_binary(Mod, Mod, Code1),
+ run_function(Mod, guard_tests),
+ run_function(Mod, body_tests),
+ run_function(Mod, bif_tests),
+
+ true = code:delete(Mod),
+ code:purge(Mod),
ok.
@@ -317,19 +293,19 @@ guard_expr({Op,X,Y}) ->
run_function(Mod, Name) ->
case catch Mod:Name() of
- {'EXIT',Reason} ->
- io:format("~p", [get(last)]),
- ?t:fail({'EXIT',Reason});
- _Other ->
- ok
+ {'EXIT',Reason} ->
+ io:format("~p", [get(last)]),
+ ct:fail({'EXIT',Reason});
+ _Other ->
+ ok
end.
-
+
guard_test({E,Expr,Res}, Tail) ->
True = unvalue(true),
[save_term(Expr),
{match,1,unvalue(Res),
{'if',1,[{clause,1,[],[[E]],[True]},
- {clause,1,[],[[True]],[unvalue(false)]}]}}|Tail].
+ {clause,1,[],[[True]],[unvalue(false)]}]}}|Tail].
body_test({E,Expr,{'EXIT',_}}, Tail) ->
[save_term(Expr),
@@ -355,8 +331,8 @@ internal_bif(Op, Args, Expr, Res, Tail) ->
save_term(Term) ->
{call,1,
- {atom,1,put},
- [{atom,1,last},unvalue(Term)]}.
+ {atom,1,put},
+ [{atom,1,last},unvalue(Term)]}.
make_module(Name, Funcs) ->
[{attribute,1,module,Name},
@@ -366,18 +342,18 @@ make_module(Name, Funcs) ->
make_function(Name, Body) ->
{function,1,Name,0,[{clause,1,[],[],Body}]}.
-
+
eval(E0) ->
E = erl_parse:new_anno(E0),
- ?line case catch erl_eval:exprs(E, []) of
- {'EXIT',Reason} -> {'EXIT',Reason};
- {value,Val,_Bs} -> Val
- end.
+ case catch erl_eval:exprs(E, []) of
+ {'EXIT',Reason} -> {'EXIT',Reason};
+ {value,Val,_Bs} -> Val
+ end.
unvalue(V) ->
Abstr = erl_parse:abstract(V),
erl_parse:anno_to_term(Abstr).
-
+
value({nil,_}) -> [];
value({integer,_,X}) -> X;
value({string,_,X}) -> X;
diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl
index 3d0509a28c..328641f5b9 100644
--- a/erts/emulator/test/port_SUITE.erl
+++ b/erts/emulator/test/port_SUITE.erl
@@ -74,25 +74,26 @@
%%
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
- init_per_testcase/2, end_per_testcase/2,
- init_per_suite/1, end_per_suite/1,
- stream_small/1, stream_big/1,
- basic_ping/1, slow_writes/1, bad_packet/1, bad_port_messages/1,
- mul_basic/1, mul_slow_writes/1,
- dying_port/1, port_program_with_path/1,
- open_input_file_port/1, open_output_file_port/1,
- iter_max_ports/1, eof/1, input_only/1, output_only/1,
- name1/1,
- t_binary/1, parallell/1, t_exit/1,
- env/1, bad_env/1, cd/1, exit_status/1,
- tps_16_bytes/1, tps_1K/1, line/1, stderr_to_stdout/1,
- otp_3906/1, otp_4389/1, win_massive/1, win_massive_client/1,
- mix_up_ports/1, otp_5112/1, otp_5119/1, otp_6224/1,
- exit_status_multi_scheduling_block/1, ports/1,
- spawn_driver/1, spawn_executable/1, close_deaf_port/1,
- port_setget_data/1,
- unregister_name/1, parallelism_option/1]).
+-export([all/0, suite/0, groups/0,
+ init_per_testcase/2, end_per_testcase/2,
+ init_per_suite/1, end_per_suite/1,
+ stream_small/1, stream_big/1,
+ basic_ping/1, slow_writes/1, bad_packet/1, bad_port_messages/1,
+ mul_basic/1, mul_slow_writes/1,
+ dying_port/1, port_program_with_path/1,
+ open_input_file_port/1, open_output_file_port/1,
+ count_fds/1,
+ iter_max_ports/1, eof/1, input_only/1, output_only/1,
+ name1/1,
+ t_binary/1, parallell/1, t_exit/1,
+ env/1, huge_env/1, bad_env/1, cd/1, exit_status/1,
+ tps_16_bytes/1, tps_1K/1, line/1, stderr_to_stdout/1,
+ otp_3906/1, otp_4389/1, win_massive/1, win_massive_client/1,
+ mix_up_ports/1, otp_5112/1, otp_5119/1, otp_6224/1,
+ exit_status_multi_scheduling_block/1, ports/1,
+ spawn_driver/1, spawn_executable/1, close_deaf_port/1,
+ port_setget_data/1,
+ unregister_name/1, parallelism_option/1]).
-export([do_iter_max_ports/2]).
@@ -101,18 +102,20 @@
-export([otp_3906_forker/5, otp_3906_start_forker_starter/4]).
-export([env_slave_main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {seconds, 10}}].
all() ->
[otp_6224, {group, stream}, basic_ping, slow_writes,
bad_packet, bad_port_messages, {group, options},
{group, multiple_packets}, parallell, dying_port,
port_program_with_path, open_input_file_port,
- open_output_file_port, name1, env, bad_env, cd,
- exit_status, iter_max_ports, t_exit, {group, tps}, line,
+ open_output_file_port, name1, env, huge_env, bad_env, cd,
+ exit_status, iter_max_ports, count_fds, t_exit, {group, tps}, line,
stderr_to_stdout, otp_3906, otp_4389, win_massive,
mix_up_ports, otp_5112, otp_5119,
exit_status_multi_scheduling_block, ports, spawn_driver,
@@ -126,15 +129,6 @@ groups() ->
{multiple_packets, [], [mul_basic, mul_slow_writes]},
{tps, [], [tps_16_bytes, tps_1K]}].
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
--define(DEFAULT_TIMEOUT, ?t:minutes(5)).
-
init_per_testcase(Case, Config) ->
[{testcase, Case} |Config].
@@ -154,69 +148,63 @@ end_per_suite(Config) when is_list(Config) ->
%% on a Windows machine given the correct environment.
win_massive(Config) when is_list(Config) ->
case os:type() of
- {win32,_} ->
- do_win_massive();
- _ ->
- {skip,"Only on Windows."}
+ {win32,_} ->
+ do_win_massive();
+ _ ->
+ {skip,"Only on Windows."}
end.
do_win_massive() ->
- Dog = test_server:timetrap(test_server:seconds(360)),
+ ct:timetrap({minutes, 6}),
SuiteDir = filename:dirname(code:which(?MODULE)),
Ports = " +Q 8192",
{ok, Node} =
- test_server:start_node(win_massive,
- slave,
- [{args, " -pa " ++ SuiteDir ++ Ports}]),
+ test_server:start_node(win_massive,
+ slave,
+ [{args, " -pa " ++ SuiteDir ++ Ports}]),
ok = rpc:call(Node,?MODULE,win_massive_client,[3000]),
test_server:stop_node(Node),
- test_server:timetrap_cancel(Dog),
ok.
-
+
win_massive_client(N) ->
{ok,P}=gen_tcp:listen(?WIN_MASSIVE_PORT,[{reuseaddr,true}]),
L = win_massive_loop(P,N),
Len = length(L),
lists:foreach(fun(E) ->
- gen_tcp:close(E)
- end,
- L),
+ gen_tcp:close(E)
+ end,
+ L),
case Len div 2 of
- N ->
- ok;
- _Else ->
- {too_few, Len}
+ N ->
+ ok;
+ _Else ->
+ {too_few, Len}
end.
win_massive_loop(_,0) ->
[];
win_massive_loop(P,N) ->
case (catch gen_tcp:connect("localhost",?WIN_MASSIVE_PORT,[])) of
- {ok,A} ->
- case (catch gen_tcp:accept(P)) of
- {ok,B} ->
- %erlang:display(N),
- [A,B|win_massive_loop(P,N-1)];
- _Else ->
- [A]
- end;
- _Else0 ->
- []
+ {ok,A} ->
+ case (catch gen_tcp:accept(P)) of
+ {ok,B} ->
+ %erlang:display(N),
+ [A,B|win_massive_loop(P,N-1)];
+ _Else ->
+ [A]
+ end;
+ _Else0 ->
+ []
end.
-
-
-
%% Test that we can send a stream of bytes and get it back.
%% We will send only a small amount of data, to avoid deadlock.
stream_small(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
stream_ping(Config, 512, "", []),
stream_ping(Config, 1777, "", []),
stream_ping(Config, 1777, "-s512", []),
- test_server:timetrap_cancel(Dog),
ok.
%% Send big amounts of data (much bigger than the buffer size in port test).
@@ -224,22 +212,20 @@ stream_small(Config) when is_list(Config) ->
%% non-blocking reads and writes.
stream_big(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(180)),
+ ct:timetrap({seconds, 180}),
stream_ping(Config, 43755, "", []),
stream_ping(Config, 100000, "", []),
stream_ping(Config, 77777, " -s40000", []),
- test_server:timetrap_cancel(Dog),
ok.
%% Sends packet with header size of 1, 2, and 4, with packets of various
%% sizes.
basic_ping(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(120)),
+ ct:timetrap({minutes, 2}),
ping(Config, sizes(1), 1, "", []),
ping(Config, sizes(2), 2, "", []),
ping(Config, sizes(4), 4, "", []),
- test_server:timetrap_cancel(Dog),
ok.
%% Let the port program insert delays between characters sent back to
@@ -247,17 +233,13 @@ basic_ping(Config) when is_list(Config) ->
%% small chunks rather than all at once.
slow_writes(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(20)),
ping(Config, [8], 4, "-s1", []),
ping(Config, [10], 2, "-s2", []),
- test_server:timetrap_cancel(Dog),
ok.
-bad_packet(doc) ->
- ["Test that we get {'EXIT', Port, einval} if we try to send a bigger "
- "packet than the packet header allows."];
+%% Test that we get {'EXIT', Port, einval} if we try to send a bigger
+%% packet than the packet header allows.
bad_packet(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
PortTest = port_test(Config),
process_flag(trap_exit, true),
@@ -265,16 +247,14 @@ bad_packet(Config) when is_list(Config) ->
bad_packet(PortTest, 1, 257),
bad_packet(PortTest, 2, 65536),
bad_packet(PortTest, 2, 65537),
-
- test_server:timetrap_cancel(Dog),
ok.
bad_packet(PortTest, HeaderSize, PacketSize) ->
P = open_port({spawn, PortTest}, [{packet, HeaderSize}]),
P ! {self(), {command, make_zero_packet(PacketSize)}},
receive
- {'EXIT', P, einval} -> ok;
- Other -> test_server:fail({unexpected_message, Other})
+ {'EXIT', P, einval} -> ok;
+ Other -> ct:fail({unexpected_message, Other})
end.
make_zero_packet(0) -> [];
@@ -287,7 +267,6 @@ make_zero_packet(N) ->
%% Test sending bad messages to a port.
bad_port_messages(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
PortTest = port_test(Config),
process_flag(trap_exit, true),
@@ -295,16 +274,14 @@ bad_port_messages(Config) when is_list(Config) ->
bad_message(PortTest, {a}),
bad_message(PortTest, {self(),{command,bad_command}}),
bad_message(PortTest, {self(),{connect,no_pid}}),
-
- test_server:timetrap_cancel(Dog),
ok.
bad_message(PortTest, Message) ->
P = open_port({spawn,PortTest}, []),
P ! Message,
receive
- {'EXIT',P,badsig} -> ok;
- Other -> test_server:fail({unexpected_message, Other})
+ {'EXIT',P,badsig} -> ok;
+ Other -> ct:fail({unexpected_message, Other})
end.
%% Tests various options (stream and {packet, Number} are implicitly
@@ -314,7 +291,7 @@ bad_message(PortTest, Message) ->
%% Tests the 'binary' option for a port.
t_binary(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(300)),
+ ct:timetrap({seconds, 300}),
%% Packet mode.
ping(Config, sizes(1), 1, "", [binary]),
@@ -325,12 +302,10 @@ t_binary(Config) when is_list(Config) ->
stream_ping(Config, 435, "", [binary]),
stream_ping(Config, 43755, "", [binary]),
stream_ping(Config, 100000, "", [binary]),
-
- test_server:timetrap_cancel(Dog),
ok.
name1(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(100)),
+ ct:timetrap({seconds, 100}),
PortTest = port_test(Config),
Command = lists:concat([PortTest, " "]),
P = open_port({spawn, Command}, []),
@@ -347,13 +322,12 @@ name1(Config) when is_list(Config) ->
{P, closed} -> ok
end,
undefined = whereis(myport),
- test_server:timetrap_cancel(Dog),
ok.
%% Test that the 'eof' option works.
eof(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(100)),
+ ct:timetrap({seconds, 100}),
PortTest = port_test(Config),
Command = lists:concat([PortTest, " -h0 -q"]),
P = open_port({spawn, Command}, [eof]),
@@ -365,47 +339,49 @@ eof(Config) when is_list(Config) ->
receive
{P, closed} -> ok
end,
- test_server:timetrap_cancel(Dog),
ok.
%% Tests that the 'in' option for a port works.
input_only(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(300)),
+ ct:timetrap({seconds, 300}),
expect_input(Config, [0, 1, 10, 13, 127, 128, 255], 1, "", [in]),
expect_input(Config, [0, 1, 255, 2048], 2, "", [in]),
expect_input(Config, [0, 1, 255, 2048], 4, "", [in]),
expect_input(Config, [0, 1, 10, 13, 127, 128, 255],
1, "", [in, binary]),
- test_server:timetrap_cancel(Dog),
ok.
%% Tests that the 'out' option for a port works.
output_only(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(100)),
- Dir = ?config(priv_dir, Config),
+ ct:timetrap({seconds, 100}),
+ Dir = proplists:get_value(priv_dir, Config),
+
+ %% First we test that the port program gets the data
Filename = filename:join(Dir, "output_only_stream"),
- output_and_verify(Config, Filename, "-h0",
- random_packet(35777, "echo")),
- test_server:timetrap_cancel(Dog),
+ Data = random_packet(35777, "echo"),
+ output_and_verify(Config, ["-h0 -o", Filename], Data),
+ Wait_time = 500,
+ test_server:sleep(Wait_time),
+ {ok, Written} = file:read_file(Filename),
+ Data = binary_to_list(Written),
+
+ %% Then we test that any writes to stdout from
+ %% the port program is not sent to erlang
+ output_and_verify(Config, ["-h0"], Data),
ok.
-output_and_verify(Config, Filename, Options, Data) ->
+output_and_verify(Config, Options, Data) ->
PortTest = port_test(Config),
- Command = lists:concat([PortTest, " ",
- Options, " -o", Filename]),
+ Command = lists:concat([PortTest, " " | Options]),
Port = open_port({spawn, Command}, [out]),
Port ! {self(), {command, Data}},
Port ! {self(), close},
receive
- {Port, closed} -> ok
- end,
- Wait_time = 500,
- test_server:sleep(Wait_time),
- {ok, Written} = file:read_file(Filename),
- Data = binary_to_list(Written),
- ok.
+ {Port, closed} -> ok;
+ Msg -> ct:fail({received_unexpected_message, Msg})
+ end.
%% Test that receiving several packages written in the same
%% write operation works.
@@ -414,11 +390,10 @@ output_and_verify(Config, Filename, Options, Data) ->
%% Basic test of receiving multiple packages, written in
%% one operation by the other end.
mul_basic(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(600)),
+ ct:timetrap({minutes, 10}),
expect_input(Config, [0, 1, 255, 10, 13], 1, "", []),
expect_input(Config, [0, 10, 13, 1600, 32767, 65535], 2, "", []),
expect_input(Config, [10, 70000], 4, "", []),
- test_server:timetrap_cancel(Dog),
ok.
%% Test reading a buffer consisting of several packets, some
@@ -427,9 +402,8 @@ mul_basic(Config) when is_list(Config) ->
%% delays in between.)
mul_slow_writes(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(250)),
+ ct:timetrap({minutes, 4}),
expect_input(Config, [0, 20, 255, 10, 1], 1, "-s64", []),
- test_server:timetrap_cancel(Dog),
ok.
%% Runs several port tests in parallell. Each individual test
@@ -437,27 +411,26 @@ mul_slow_writes(Config) when is_list(Config) ->
%% should also finish in about 5 seconds.
parallell(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(300)),
+ ct:timetrap({minutes, 5}),
Testers = [
- fun() -> stream_ping(Config, 1007, "-s100", []) end,
- fun() -> stream_ping(Config, 10007, "-s1000", []) end,
- fun() -> stream_ping(Config, 10007, "-s1000", []) end,
+ fun() -> stream_ping(Config, 1007, "-s100", []) end,
+ fun() -> stream_ping(Config, 10007, "-s1000", []) end,
+ fun() -> stream_ping(Config, 10007, "-s1000", []) end,
- fun() -> expect_input(Config, [21, 22, 23, 24, 25], 1,
- "-s10", [in]) end,
+ fun() -> expect_input(Config, [21, 22, 23, 24, 25], 1,
+ "-s10", [in]) end,
- fun() -> ping(Config, [10], 1, "-d", []) end,
- fun() -> ping(Config, [20000], 2, "-d", []) end,
- fun() -> ping(Config, [101], 1, "-s10", []) end,
- fun() -> ping(Config, [1001], 2, "-s100", []) end,
- fun() -> ping(Config, [10001], 4, "-s1000", []) end,
+ fun() -> ping(Config, [10], 1, "-d", []) end,
+ fun() -> ping(Config, [20000], 2, "-d", []) end,
+ fun() -> ping(Config, [101], 1, "-s10", []) end,
+ fun() -> ping(Config, [1001], 2, "-s100", []) end,
+ fun() -> ping(Config, [10001], 4, "-s1000", []) end,
- fun() -> ping(Config, [501, 501], 2, "-s100", []) end,
- fun() -> ping(Config, [11, 12, 13, 14, 11], 1, "-s5", []) end],
+ fun() -> ping(Config, [501, 501], 2, "-s100", []) end,
+ fun() -> ping(Config, [11, 12, 13, 14, 11], 1, "-s5", []) end],
process_flag(trap_exit, true),
Pids = lists:map(fun fun_spawn/1, Testers),
wait_for(Pids),
- test_server:timetrap_cancel(Dog),
ok.
wait_for([]) ->
@@ -465,18 +438,17 @@ wait_for([]) ->
wait_for(Pids) ->
io:format("Waiting for ~p", [Pids]),
receive
- {'EXIT', Pid, normal} ->
- wait_for(lists:delete(Pid, Pids));
- Other ->
- test_server:fail({bad_exit, Other})
+ {'EXIT', Pid, normal} ->
+ wait_for(lists:delete(Pid, Pids));
+ Other ->
+ ct:fail({bad_exit, Other})
end.
%% Tests starting port programs that terminate by themselves.
%% This used to cause problems on Windows.
-dying_port(suite) -> [];
dying_port(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(150)),
+ ct:timetrap({minutes, 2}),
process_flag(trap_exit, true),
P1 = make_dying_port(Config),
@@ -497,14 +469,12 @@ dying_port(Config) when is_list(Config) ->
wait_for_port_exit(P3),
wait_for_port_exit(P4),
wait_for_port_exit(P5),
-
- test_server:timetrap_cancel(Dog),
ok.
wait_for_port_exit(Port) ->
receive
- {'EXIT', Port, _} ->
- ok
+ {'EXIT', Port, _} ->
+ ok
end.
make_dying_port(Config) when is_list(Config) ->
@@ -523,22 +493,21 @@ make_dying_port(Config) when is_list(Config) ->
%%
%% This testcase works on Unix, but is not very useful.
-port_program_with_path(suite) -> [];
port_program_with_path(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(100)),
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
-
+ ct:timetrap({minutes, 2}),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+
%% Create a copy of the port test program in a directory not
%% included in PATH (i.e. in priv_dir), with the name 'my_port_test.exe'.
%% Also, place a file named 'my_port_test' in the same directory.
%% This used to confuse the CreateProcess() call in spawn driver.
%% (On Unix, there will be a single file created, which will be
%% a copy of the port program.)
-
+
PortTest = os:find_executable("port_test", DataDir),
io:format("os:find_executable(~p, ~p) returned ~p",
- ["port_test", DataDir, PortTest]),
+ ["port_test", DataDir, PortTest]),
{ok, PortTestPgm} = file:read_file(PortTest),
NewName = filename:join(PrivDir, filename:basename(PortTest)),
RedHerring = filename:rootname(NewName),
@@ -546,12 +515,12 @@ port_program_with_path(Config) when is_list(Config) ->
ok = file:write_file(NewName, PortTestPgm),
ok = file:write_file_info(NewName, #file_info{mode=8#111}),
PgmWithPathAndNoExt = filename:rootname(NewName),
-
+
%% Open the port using the path to the copied port test program,
%% but without the .exe extension, and verified that it was started.
%%
%% If the bug is present the open_port call will fail with badarg.
-
+
Command = lists:concat([PgmWithPathAndNoExt, " -h2"]),
P = open_port({spawn, Command}, [{packet, 2}]),
Message = "echo back to me",
@@ -560,17 +529,14 @@ port_program_with_path(Config) when is_list(Config) ->
{P, {data, Message}} ->
ok
end,
- test_server:timetrap_cancel(Dog),
ok.
%% Tests that files can be read using open_port(Filename, [in]).
%% This used to fail on Windows.
-open_input_file_port(suite) -> [];
open_input_file_port(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
- PrivDir = ?config(priv_dir, Config),
-
+ PrivDir = proplists:get_value(priv_dir, Config),
+
%% Create a file with the file driver and read it back using
%% open_port/2.
@@ -578,20 +544,18 @@ open_input_file_port(Config) when is_list(Config) ->
FileData1 = "An input file",
ok = file:write_file(MyFile1, FileData1),
case open_port(MyFile1, [in]) of
- InputPort when is_port(InputPort) ->
- receive
- {InputPort, {data, FileData1}} ->
- ok
- end
+ InputPort when is_port(InputPort) ->
+ receive
+ {InputPort, {data, FileData1}} ->
+ ok
+ end
end,
- test_server:timetrap_cancel(Dog),
ok.
%% Tests that files can be written using open_port(Filename, [out]).
-open_output_file_port(suite) -> [];
open_output_file_port(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(100)),
- PrivDir = ?config(priv_dir, Config),
+ ct:timetrap({minutes, 2}),
+ PrivDir = proplists:get_value(priv_dir, Config),
%% Create a file with open_port/2 and read it back with
%% the file driver.
@@ -606,16 +570,44 @@ open_output_file_port(Config) when is_list(Config) ->
OutputPort ! {self(), close},
{ok, Bin} = file:read_file(MyFile2),
FileData2 = binary_to_list(Bin),
-
- test_server:timetrap_cancel(Dog),
ok.
+%% Tests that all appropriate fd's have been closed in the port program
+count_fds(Config) when is_list(Config) ->
+ case os:type() of
+ {unix, _} ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Filename = filename:join(PrivDir, "my_fd_counter"),
+
+ RunTest = fun(PortOpts) ->
+ PortTest = port_test(Config),
+ Command = lists:concat([PortTest, " -n -f -o", Filename]),
+ Port = open_port({spawn, Command}, PortOpts),
+ Port ! {self(), close},
+ receive
+ {Port, closed} -> ok
+ end,
+ test_server:sleep(500),
+ {ok, Written} = file:read_file(Filename),
+ Written
+ end,
+ <<4:32/native>> = RunTest([out, nouse_stdio]),
+ <<4:32/native>> = RunTest([in, nouse_stdio]),
+ <<5:32/native>> = RunTest([in, out, nouse_stdio]),
+ <<3:32/native>> = RunTest([out, use_stdio]),
+ <<3:32/native>> = RunTest([in, use_stdio]),
+ <<3:32/native>> = RunTest([in, out, use_stdio]),
+ <<3:32/native>> = RunTest([in, out, use_stdio, stderr_to_stdout]),
+ <<3:32/native>> = RunTest([out, use_stdio, stderr_to_stdout]);
+ _ ->
+ {skip, "Skipped on windows"}
+ end.
+
%%
%% Open as many ports as possible. Do this several times and check
%% that we get the same number of ports every time.
%%
-iter_max_ports(suite) -> [];
iter_max_ports(Config) when is_list(Config) ->
%% The child_setup program might dump core if we get out of memory.
%% This is hard to do anything about and is harmless. We run this test
@@ -624,31 +616,30 @@ iter_max_ports(Config) when is_list(Config) ->
%%
Config2 = ignore_cores:setup(?MODULE, iter_max_ports, Config, true),
try
- iter_max_ports_test(Config2)
+ iter_max_ports_test(Config2)
after
- ignore_cores:restore(Config2)
+ ignore_cores:restore(Config2)
end.
-
-
+
+
iter_max_ports_test(Config) ->
- Dog = test_server:timetrap(test_server:minutes(30)),
+ ct:timetrap({minutes, 30}),
PortTest = port_test(Config),
Command = lists:concat([PortTest, " -h0 -q"]),
Iters = case os:type() of
- {win32,_} -> 4;
- _ -> 10
- end,
+ {win32,_} -> 4;
+ _ -> 10
+ end,
%% Run on a different node in order to limit the effect if this test fails.
Dir = filename:dirname(code:which(?MODULE)),
{ok,Node} = test_server:start_node(test_iter_max_socks,slave,
- [{args,"+Q 2048 -pa " ++ Dir}]),
+ [{args,"+Q 2048 -pa " ++ Dir}]),
L = rpc:call(Node,?MODULE,do_iter_max_ports,[Iters, Command]),
test_server:stop_node(Node),
io:format("Result: ~p",[L]),
all_equal(L),
all_equal(L),
- test_server:timetrap_cancel(Dog),
{comment, "Max ports: " ++ integer_to_list(hd(L))}.
do_iter_max_ports(N, Command) when N > 0 ->
@@ -672,46 +663,54 @@ max_ports(Command) ->
close_ports([P|Ps]) ->
P ! {self(), close},
receive
- {P,closed} ->
- ok
+ {P,closed} ->
+ ok
end,
close_ports(Ps);
close_ports([]) ->
ok.
open_ports(Name, Settings) ->
- test_server:sleep(5),
+ case os:type() of
+ {unix, freebsd} ->
+ %% FreeBsd has issues with sendmsg/recvmsg in fork
+ %% implementation and we therefor have to spawn
+ %% slower to make sure that we always hit the same
+ %% make roof.
+ test_server:sleep(10);
+ _ ->
+ test_server:sleep(5)
+ end,
case catch open_port(Name, Settings) of
- P when is_port(P) ->
- [P| open_ports(Name, Settings)];
- {'EXIT', {Code, _}} ->
- case Code of
- enfile ->
- [];
- emfile ->
- [];
- system_limit ->
- [];
- enomem ->
- [];
- Other ->
- test_server:fail({open_ports, Other})
- end;
- Other ->
- test_server:fail({open_ports, Other})
+ P when is_port(P) ->
+ [P| open_ports(Name, Settings)];
+ {'EXIT', {Code, _}} ->
+ case Code of
+ enfile ->
+ [];
+ emfile ->
+ [];
+ system_limit ->
+ [];
+ enomem ->
+ [];
+ Other ->
+ ct:fail({open_ports, Other})
+ end;
+ Other ->
+ ct:fail({open_ports, Other})
end.
%% Tests that exit(Port, Term) works (has been known to crash the emulator).
-t_exit(suite) -> [];
t_exit(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Pid = fun_spawn(fun suicide_port/1, [Config]),
receive
- {'EXIT', Pid, die} ->
- ok;
- Other ->
- test_server:fail({bad_message, Other})
+ {'EXIT', Pid, die} ->
+ ok;
+ Other ->
+ ct:fail({bad_message, Other})
end.
suicide_port(Config) when is_list(Config) ->
@@ -720,118 +719,105 @@ suicide_port(Config) when is_list(Config) ->
receive after infinity -> ok end.
-tps_16_bytes(doc) -> "";
-tps_16_bytes(suite) -> [];
tps_16_bytes(Config) when is_list(Config) ->
tps(16, Config).
-tps_1K(doc) -> "";
-tps_1K(suite) -> [];
tps_1K(Config) when is_list(Config) ->
tps(1024, Config).
tps(Size, Config) ->
- Dog = test_server:timetrap(test_server:seconds(300)),
+ ct:timetrap({minutes, 5}),
PortTest = port_test(Config),
Packet = list_to_binary(random_packet(Size, "e")),
Port = open_port({spawn, PortTest}, [binary, {packet, 2}]),
Transactions = 10000,
{Elapsed, ok} = test_server:timecall(?MODULE, tps,
- [Port, Packet, Transactions]),
- test_server:timetrap_cancel(Dog),
+ [Port, Packet, Transactions]),
{comment, integer_to_list(trunc(Transactions/Elapsed+0.5)) ++ " transactions/s"}.
tps(_Port, _Packet, 0) -> ok;
tps(Port, Packet, N) ->
port_command(Port, Packet),
receive
- {Port, {data, Packet}} ->
- tps(Port, Packet, N-1);
- Other ->
- test_server:fail({bad_message, Other})
+ {Port, {data, Packet}} ->
+ tps(Port, Packet, N-1);
+ Other ->
+ ct:fail({bad_message, Other})
end.
%% Line I/O test
line(Config) when is_list(Config) ->
+ ct:timetrap({minutes, 5}),
Siz = 110,
- Dog = test_server:timetrap(test_server:seconds(300)),
Packet1 = random_packet(Siz),
Packet2 = random_packet(Siz div 2),
%% Test that packets are split into lines
port_expect(Config,[{lists:append([Packet1, io_lib:nl(), Packet2,
- io_lib:nl()]),
- [{eol, Packet1}, {eol, Packet2}]}],
- 0, "", [{line,Siz}]),
+ io_lib:nl()]),
+ [{eol, Packet1}, {eol, Packet2}]}],
+ 0, "", [{line,Siz}]),
%% Test the same for binaries
port_expect(Config,[{lists:append([Packet1, io_lib:nl(), Packet2,
- io_lib:nl()]),
- [{eol, Packet1}, {eol, Packet2}]}],
- 0, "", [{line,Siz},binary]),
+ io_lib:nl()]),
+ [{eol, Packet1}, {eol, Packet2}]}],
+ 0, "", [{line,Siz},binary]),
%% Test that too long lines get split
port_expect(Config,[{lists:append([Packet1, io_lib:nl(), Packet1,
- Packet2, io_lib:nl()]),
- [{eol, Packet1}, {noeol, Packet1},
- {eol, Packet2}]}], 0, "", [{line,Siz}]),
+ Packet2, io_lib:nl()]),
+ [{eol, Packet1}, {noeol, Packet1},
+ {eol, Packet2}]}], 0, "", [{line,Siz}]),
%% Test that last output from closing port program gets received.
L1 = lists:append([Packet1, io_lib:nl(), Packet2]),
S1 = lists:flatten(io_lib:format("-l~w", [length(L1)])),
io:format("S1 = ~w, L1 = ~w~n", [S1,L1]),
port_expect(Config,[{L1,
- [{eol, Packet1}, {noeol, Packet2}, eof]}], 0,
- S1, [{line,Siz},eof]),
+ [{eol, Packet1}, {noeol, Packet2}, eof]}], 0,
+ S1, [{line,Siz},eof]),
%% Test that lonely <CR> Don't get treated as newlines
port_expect(Config,[{lists:append([Packet1, [13], Packet2,
- io_lib:nl()]),
- [{noeol, Packet1}, {eol, [13 |Packet2]}]}],
- 0, "", [{line,Siz}]),
+ io_lib:nl()]),
+ [{noeol, Packet1}, {eol, [13 |Packet2]}]}],
+ 0, "", [{line,Siz}]),
%% Test that packets get built up to lines (delayed output from
%% port program)
port_expect(Config,[{Packet2,[]},
- {lists:append([Packet2, io_lib:nl(),
- Packet1, io_lib:nl()]),
- [{eol, lists:append(Packet2, Packet2)},
- {eol, Packet1}]}], 0, "-d", [{line,Siz}]),
+ {lists:append([Packet2, io_lib:nl(),
+ Packet1, io_lib:nl()]),
+ [{eol, lists:append(Packet2, Packet2)},
+ {eol, Packet1}]}], 0, "-d", [{line,Siz}]),
%% Test that we get badarg if trying both packet and line
bad_argument(Config, [{packet, 5}, {line, 5}]),
- test_server:timetrap_cancel(Dog),
ok.
-%%% Redirection of stderr test
-stderr_to_stdout(suite) ->
- [];
-stderr_to_stdout(doc) ->
- "Test that redirection of standard error to standard output works.";
+%% Test that redirection of standard error to standard output works.
stderr_to_stdout(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(60)),
+ ct:timetrap({minutes, 1}),
%% See that it works
Packet = random_packet(10),
port_expect(Config,[{Packet,[Packet]}], 0, "-e -l10",
- [stderr_to_stdout]),
+ [stderr_to_stdout]),
%% stream_ping(Config, 10, "-e", [stderr_to_stdout]),
%% See that it doesn't always happen (will generate garbage on stderr)
port_expect(Config,[{Packet,[eof]}], 0, "-e -l10", [line,eof]),
- test_server:timetrap_cancel(Dog),
ok.
bad_argument(Config, ArgList) ->
PortTest = port_test(Config),
case catch open_port({spawn, PortTest}, ArgList) of
- {'EXIT', {badarg, _}} ->
- ok
+ {'EXIT', {badarg, _}} ->
+ ok
end.
-
+
%% 'env' option
%% (Can perhaps be made smaller by calling the other utility functions
%% in this module.)
-env(suite) ->
- [];
-env(doc) ->
- ["Test that the 'env' option works"];
+%%
+%% Test that the 'env' option works
env(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(60)),
- Priv = ?config(priv_dir, Config),
+ ct:timetrap({minutes, 1}),
+ Priv = proplists:get_value(priv_dir, Config),
Temp = filename:join(Priv, "env_fun.bin"),
PluppVal = "dirty monkey",
@@ -841,36 +827,34 @@ env(Config) when is_list(Config) ->
os:putenv(Long, "nisse"),
env_slave(Temp, [{"plupp",PluppVal},
- {"DIR_PLUPP","###glurfrik"}],
- fun() ->
- PluppVal = os:getenv("plupp"),
- "###glurfrik" = os:getenv("DIR_PLUPP"),
- "nisse" = os:getenv(Long)
- end),
+ {"DIR_PLUPP","###glurfrik"}],
+ fun() ->
+ PluppVal = os:getenv("plupp"),
+ "###glurfrik" = os:getenv("DIR_PLUPP"),
+ "nisse" = os:getenv(Long)
+ end),
env_slave(Temp, [{"must_define_something","some_value"},
- {"certainly_not_existing",false},
- {"ends_with_equal", "value="},
- {Long,false},
- {"glurf","a glorfy string"}]),
+ {"certainly_not_existing",false},
+ {"ends_with_equal", "value="},
+ {Long,false},
+ {"glurf","a glorfy string"}]),
%% A lot of non existing variables (mingled with existing)
NotExistingList = [{lists:flatten(io_lib:format("V~p_not_existing",[X])),false}
- || X <- lists:seq(1,150)],
+ || X <- lists:seq(1,150)],
ExistingList = [{lists:flatten(io_lib:format("V~p_existing",[X])),"a_value"}
- || X <- lists:seq(1,150)],
+ || X <- lists:seq(1,150)],
env_slave(Temp, lists:sort(ExistingList ++ NotExistingList)),
-
- test_server:timetrap_cancel(Dog),
ok.
env_slave(File, Env) ->
F = fun() ->
- lists:foreach(fun({Name,Val}) ->
- Val = os:getenv(Name)
- end, Env)
- end,
+ lists:foreach(fun({Name,Val}) ->
+ Val = os:getenv(Name)
+ end, Env)
+ end,
env_slave(File, Env, F).
env_slave(File, Env, Body) ->
@@ -878,27 +862,26 @@ env_slave(File, Env, Body) ->
Program = atom_to_list(lib:progname()),
Dir = filename:dirname(code:which(?MODULE)),
Cmd = Program ++ " -pz " ++ Dir ++
- " -noinput -run " ++ ?MODULE_STRING ++ " env_slave_main " ++
- File ++ " -run erlang halt",
+ " -noinput -run " ++ ?MODULE_STRING ++ " env_slave_main " ++
+ File ++ " -run erlang halt",
Port = open_port({spawn, Cmd}, [{env,Env},{line,256}]),
receive
- {Port,{data,{eol,"ok"}}} ->
- ok;
- {Port,{data,{eol,Error}}} ->
- io:format("~p\n", [Error]),
- test_server:fail();
- Other ->
- test_server:fail(Other)
+ {Port,{data,{eol,"ok"}}} ->
+ ok;
+ {Port,{data,{eol,Error}}} ->
+ ct:fail("eol error ~p\n", [Error]);
+ Other ->
+ ct:fail(Other)
end.
env_slave_main([File]) ->
{ok,Body0} = file:read_file(File),
Body = binary_to_term(Body0),
case Body() of
- {'EXIT',Reason} ->
- io:format("Error: ~p\n", [Reason]);
- _ ->
- io:format("ok\n")
+ {'EXIT',Reason} ->
+ io:format("Error: ~p\n", [Reason]);
+ _ ->
+ io:format("ok\n")
end,
init:stop().
@@ -920,62 +903,93 @@ bad_env(Config) when is_list(Config) ->
try_bad_env(Env) ->
try open_port({spawn,"ls"}, [{env,Env}])
catch
- error:badarg -> ok
+ error:badarg -> ok
+ end.
+
+%% Test that we can handle a very very large environment gracefully.
+huge_env(Config) when is_list(Config) ->
+ ct:timetrap({seconds, 30}),
+ Vars = case os:type() of
+ {win32,_} -> 500;
+ _ ->
+ %% We create a huge environment,
+ %% 20000 variables is about 25MB
+ %% which seems to be the limit on Linux.
+ 20000
+ end,
+ Env = [{[$a + I div (25*25*25*25) rem 25,
+ $a + I div (25*25*25) rem 25,
+ $a + I div (25*25) rem 25,
+ $a+I div 25 rem 25, $a+I rem 25],
+ lists:duplicate(100,$a+I rem 25)}
+ || I <- lists:seq(1,Vars)],
+ try erlang:open_port({spawn,"ls"},[exit_status, {env, Env}]) of
+ P ->
+ receive
+ {P, {exit_status,N}} = M ->
+ %% We test that the exit status is an integer, this means
+ %% that the child program has started. If we get an atom
+ %% something went wrong in the driver which is not ok.
+ ct:log("Got ~p",[M]),
+ true = is_integer(N)
+ end
+ catch E:R ->
+ %% Have to catch the error here, as printing the stackdump
+ %% in the ct log is way to heavy for some test machines.
+ ct:fail("Open port failed ~p:~p",[E,R])
end.
+
+
%% 'cd' option
%% (Can perhaps be made smaller by calling the other utility functions
%% in this module.)
-cd(suite) ->
- [];
-cd(doc) ->
- ["Test that the 'cd' option works"];
+%%
+%% Test that the 'cd' option works
cd(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(60)),
+ ct:timetrap({minutes, 1}),
Program = atom_to_list(lib:progname()),
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
TestDir = filename:join(DataDir, "dir"),
Cmd = Program ++ " -pz " ++ DataDir ++
- " -noshell -s port_test pwd -s erlang halt",
+ " -noshell -s port_test pwd -s erlang halt",
_ = open_port({spawn, Cmd},
- [{cd, TestDir},
- {line, 256}]),
+ [{cd, TestDir},
+ {line, 256}]),
receive
- {_, {data, {eol, String}}} ->
- case filename_equal(String, TestDir) of
- true ->
- ok;
- false ->
- test_server:fail({cd, String})
- end;
- Other2 ->
- test_server:fail({env, Other2})
+ {_, {data, {eol, String}}} ->
+ case filename_equal(String, TestDir) of
+ true ->
+ ok;
+ false ->
+ ct:fail({cd, String})
+ end;
+ Other2 ->
+ ct:fail({env, Other2})
end,
_ = open_port({spawn, Cmd},
- [{cd, unicode:characters_to_binary(TestDir)},
- {line, 256}]),
+ [{cd, unicode:characters_to_binary(TestDir)},
+ {line, 256}]),
receive
- {_, {data, {eol, String2}}} ->
- case filename_equal(String2, TestDir) of
- true ->
- ok;
- false ->
- test_server:fail({cd, String2})
- end;
- Other3 ->
- test_server:fail({env, Other3})
+ {_, {data, {eol, String2}}} ->
+ case filename_equal(String2, TestDir) of
+ true ->
+ ok;
+ false ->
+ ct:fail({cd, String2})
+ end;
+ Other3 ->
+ ct:fail({env, Other3})
end,
-
- test_server:timetrap_cancel(Dog),
ok.
filename_equal(A, B) ->
case os:type() of
- {win32, _} ->
- win_filename_equal(A, B);
- _ ->
- A == B
+ {win32, _} ->
+ win_filename_equal(A, B);
+ _ ->
+ A == B
end.
win_filename_equal([], []) ->
@@ -986,10 +1000,10 @@ win_filename_equal(_, []) ->
false;
win_filename_equal([C1 | Rest1], [C2 | Rest2]) ->
case tolower(C1) == tolower(C2) of
- true ->
- win_filename_equal(Rest1, Rest2);
- false ->
- false
+ true ->
+ win_filename_equal(Rest1, Rest2);
+ false ->
+ false
end.
tolower(C) when C >= $A, C =< $Z ->
@@ -997,17 +1011,14 @@ tolower(C) when C >= $A, C =< $Z ->
tolower(C) ->
C.
-otp_3906(suite) ->
- [];
-otp_3906(doc) ->
- ["Tests that child process deaths are managed correctly when there are "
- " a large amount of concurrently dying children. See ticket OTP-3906."];
+%% Tests that child process deaths are managed correctly when there are
+%% a large amount of concurrently dying children. See ticket OTP-3906.
otp_3906(Config) when is_list(Config) ->
case os:type() of
- {unix, OSName} ->
- otp_3906(Config, OSName);
- _ ->
- {skipped, "Only run on Unix systems"}
+ {unix, OSName} ->
+ otp_3906(Config, OSName);
+ _ ->
+ {skipped, "Only run on Unix systems"}
end.
-define(OTP_3906_CHILDREN, 1000).
@@ -1020,83 +1031,83 @@ otp_3906(Config) when is_list(Config) ->
otp_3906(Config, OSName) ->
DataDir = filename:dirname(proplists:get_value(data_dir,Config)),
{ok, Variables} = file:consult(
- filename:join([DataDir,"..","..",
- "test_server","variables"])),
+ filename:join([DataDir,"..","..",
+ "test_server","variables"])),
case lists:keysearch('CC', 1, Variables) of
- {value,{'CC', CC}} ->
- SuiteDir = filename:dirname(code:which(?MODULE)),
- PrivDir = ?config(priv_dir, Config),
- Prog = otp_3906_make_prog(CC, PrivDir),
- {ok, Node} = test_server:start_node(otp_3906,
- slave,
- [{args, " -pa " ++ SuiteDir},
- {linked, false}]),
- OP = process_flag(priority, max),
- OTE = process_flag(trap_exit, true),
- FS = spawn_link(Node,
- ?MODULE,
- otp_3906_start_forker_starter,
- [?OTP_3906_CHILDREN, [], self(), Prog]),
- Result = receive
- {'EXIT', _ForkerStarter, Reason} ->
- {failed, Reason};
- {emulator_pid, EmPid} ->
- case otp_3906_wait_result(FS, 0, 0) of
- {succeded,
- ?OTP_3906_CHILDREN,
- ?OTP_3906_CHILDREN} ->
- succeded;
- {succeded, Forked, Exited} ->
- otp_3906_list_defunct(EmPid, OSName),
- {failed,
- {mismatch,
- {forked, Forked},
- {exited, Exited}}};
- Res ->
- otp_3906_list_defunct(EmPid, OSName),
- Res
- end
- end,
- process_flag(trap_exit, OTE),
- process_flag(priority, OP),
- test_server:stop_node(Node),
- case Result of
- succeded ->
- ok;
- _ ->
- test_server:fail(Result)
- end;
- _ ->
- {skipped, "No C compiler found"}
+ {value,{'CC', CC}} ->
+ SuiteDir = filename:dirname(code:which(?MODULE)),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Prog = otp_3906_make_prog(CC, PrivDir),
+ {ok, Node} = test_server:start_node(otp_3906,
+ slave,
+ [{args, " -pa " ++ SuiteDir},
+ {linked, false}]),
+ OP = process_flag(priority, max),
+ OTE = process_flag(trap_exit, true),
+ FS = spawn_link(Node,
+ ?MODULE,
+ otp_3906_start_forker_starter,
+ [?OTP_3906_CHILDREN, [], self(), Prog]),
+ Result = receive
+ {'EXIT', _ForkerStarter, Reason} ->
+ {failed, Reason};
+ {emulator_pid, EmPid} ->
+ case otp_3906_wait_result(FS, 0, 0) of
+ {succeded,
+ ?OTP_3906_CHILDREN,
+ ?OTP_3906_CHILDREN} ->
+ succeded;
+ {succeded, Forked, Exited} ->
+ otp_3906_list_defunct(EmPid, OSName),
+ {failed,
+ {mismatch,
+ {forked, Forked},
+ {exited, Exited}}};
+ Res ->
+ otp_3906_list_defunct(EmPid, OSName),
+ Res
+ end
+ end,
+ process_flag(trap_exit, OTE),
+ process_flag(priority, OP),
+ test_server:stop_node(Node),
+ case Result of
+ succeded ->
+ ok;
+ _ ->
+ ct:fail(Result)
+ end;
+ _ ->
+ {skipped, "No C compiler found"}
end.
otp_3906_list_defunct(EmPid, OSName) ->
% Guess ps switches to use and what to grep for (could be improved)
{Switches, Zombie} = case OSName of
- BSD when BSD == darwin;
- BSD == openbsd;
- BSD == netbsd;
- BSD == freebsd ->
- {"-ajx", "Z"};
- _ ->
- {"-ef", "[dD]efunct"}
- end,
- test_server:format("Emulator pid: ~s~n"
- "Listing of zombie processes:~n"
- "~s~n",
- [EmPid,
- otp_3906_htmlize(os:cmd("ps "
- ++ Switches
- ++ " | grep "
- ++ Zombie))]).
+ BSD when BSD == darwin;
+ BSD == openbsd;
+ BSD == netbsd;
+ BSD == freebsd ->
+ {"-ajx", "Z"};
+ _ ->
+ {"-ef", "[dD]efunct"}
+ end,
+ io:format("Emulator pid: ~s~n"
+ "Listing of zombie processes:~n"
+ "~s~n",
+ [EmPid,
+ otp_3906_htmlize(os:cmd("ps "
+ ++ Switches
+ ++ " | grep "
+ ++ Zombie))]).
otp_3906_htmlize([]) ->
[];
otp_3906_htmlize([C | Cs]) ->
case [C] of
- "<" -> "&lt;" ++ otp_3906_htmlize(Cs);
- ">" -> "&gt;" ++ otp_3906_htmlize(Cs);
- _ -> [C | otp_3906_htmlize(Cs)]
+ "<" -> "&lt;" ++ otp_3906_htmlize(Cs);
+ ">" -> "&gt;" ++ otp_3906_htmlize(Cs);
+ _ -> [C | otp_3906_htmlize(Cs)]
end.
otp_3906_make_prog(CC, PrivDir) ->
@@ -1104,12 +1115,12 @@ otp_3906_make_prog(CC, PrivDir) ->
TrgtFileName = filename:join(PrivDir, ?OTP_3906_PROGNAME),
{ok, SrcFile} = file:open(SrcFileName, write),
io:format(SrcFile,
- "int ~n"
- "main(void) ~n"
- "{ ~n"
- " return ~p; ~n"
- "} ~n",
- [?OTP_3906_EXIT_STATUS]),
+ "int ~n"
+ "main(void) ~n"
+ "{ ~n"
+ " return ~p; ~n"
+ "} ~n",
+ [?OTP_3906_EXIT_STATUS]),
file:close(SrcFile),
os:cmd(CC ++ " " ++ SrcFileName ++ " -o " ++ TrgtFileName),
TrgtFileName.
@@ -1117,21 +1128,21 @@ otp_3906_make_prog(CC, PrivDir) ->
otp_3906_wait_result(ForkerStarter, F, E) ->
receive
- {'EXIT', ForkerStarter, Reason} ->
- {failed, {Reason, {forked, F}, {exited, E}}};
- forked ->
- otp_3906_wait_result(ForkerStarter, F+1, E);
- exited ->
- otp_3906_wait_result(ForkerStarter, F, E+1);
- tick ->
- otp_3906_wait_result(ForkerStarter, F, E);
- succeded ->
- {succeded, F, E}
+ {'EXIT', ForkerStarter, Reason} ->
+ {failed, {Reason, {forked, F}, {exited, E}}};
+ forked ->
+ otp_3906_wait_result(ForkerStarter, F+1, E);
+ exited ->
+ otp_3906_wait_result(ForkerStarter, F, E+1);
+ tick ->
+ otp_3906_wait_result(ForkerStarter, F, E);
+ succeded ->
+ {succeded, F, E}
after
- ?OTP_3906_TICK_TIMEOUT ->
- unlink(ForkerStarter),
- exit(ForkerStarter, timeout),
- {failed, {timeout, {forked, F}, {exited, E}}}
+ ?OTP_3906_TICK_TIMEOUT ->
+ unlink(ForkerStarter),
+ exit(ForkerStarter, timeout),
+ {failed, {timeout, {forked, F}, {exited, E}}}
end.
otp_3906_collect([], _) ->
@@ -1141,17 +1152,17 @@ otp_3906_collect(RefList, Sup) ->
otp_3906_collect_one(RefList, Sup) ->
receive
- Ref when is_reference(Ref) ->
- Sup ! tick,
- lists:delete(Ref, RefList)
+ Ref when is_reference(Ref) ->
+ Sup ! tick,
+ lists:delete(Ref, RefList)
end.
-
+
otp_3906_start_forker(N, Sup, Prog) ->
Ref = make_ref(),
spawn_opt(?MODULE,
- otp_3906_forker,
- [N, self(), Ref, Sup, Prog],
- [link, {priority, max}]),
+ otp_3906_forker,
+ [N, self(), Ref, Sup, Prog],
+ [link, {priority, max}]),
Ref.
otp_3906_start_forker_starter(N, RefList, Sup, Prog) ->
@@ -1170,18 +1181,18 @@ otp_3906_forker_starter(N, RefList, Sup, Prog)
otp_3906_forker_starter(N, RefList, Sup, Prog)
when is_integer(N), N > ?OTP_3906_OSP_P_ERLP ->
otp_3906_forker_starter(N-?OTP_3906_OSP_P_ERLP,
- [otp_3906_start_forker(?OTP_3906_OSP_P_ERLP,
- Sup,
- Prog)|RefList],
- Sup,
- Prog);
+ [otp_3906_start_forker(?OTP_3906_OSP_P_ERLP,
+ Sup,
+ Prog)|RefList],
+ Sup,
+ Prog);
otp_3906_forker_starter(N, RefList, Sup, Prog) when is_integer(N) ->
otp_3906_forker_starter(0,
- [otp_3906_start_forker(N,
- Sup,
- Prog)|RefList],
- Sup,
- Prog).
+ [otp_3906_start_forker(N,
+ Sup,
+ Prog)|RefList],
+ Sup,
+ Prog).
otp_3906_forker(0, Parent, Ref, _, _) ->
unlink(Parent),
@@ -1190,183 +1201,165 @@ otp_3906_forker(N, Parent, Ref, Sup, Prog) ->
Port = erlang:open_port({spawn, Prog}, [exit_status, in]),
Sup ! forked,
receive
- {Port, {exit_status, ?OTP_3906_EXIT_STATUS}} ->
- Sup ! exited,
- otp_3906_forker(N-1, Parent, Ref, Sup, Prog);
- {Port, Res} ->
- exit(Res);
- Other ->
- exit(Other)
+ {Port, {exit_status, ?OTP_3906_EXIT_STATUS}} ->
+ Sup ! exited,
+ otp_3906_forker(N-1, Parent, Ref, Sup, Prog);
+ {Port, Res} ->
+ exit(Res);
+ Other ->
+ exit(Other)
end.
-otp_4389(suite) -> [];
-otp_4389(doc) -> [];
otp_4389(Config) when is_list(Config) ->
case os:type() of
- {unix, _} ->
- Dog = test_server:timetrap(test_server:seconds(240)),
- TCR = self(),
- case get_true_cmd() of
- True when is_list(True) ->
- lists:foreach(
- fun (P) ->
- receive
- {P, ok} -> ok;
- {P, Err} -> ?t:fail(Err)
- end
- end,
- lists:map(
- fun(_) ->
- spawn_link(
- fun() ->
- process_flag(trap_exit, true),
- case catch open_port({spawn, True},
- [stream,exit_status]) of
- P when is_port(P) ->
- receive
- {P,{exit_status,_}} ->
- TCR ! {self(),ok};
- {'EXIT',_,{R2,_}} when R2 == emfile;
- R2 == eagain ->
- TCR ! {self(),ok};
- Err2 ->
- TCR ! {self(),{msg,Err2}}
- end;
- {'EXIT',{R1,_}} when R1 == emfile;
- R1 == eagain ->
- TCR ! {self(),ok};
- Err1 ->
- TCR ! {self(), {open_port,Err1}}
- end
- end)
- end,
- lists:duplicate(1000,[]))),
- test_server:timetrap_cancel(Dog),
- {comment,
- "This test case doesn't always fail when the bug that "
- "it tests for is present (it is most likely to fail on"
- " a multi processor machine). If the test case fails it"
- " will fail by deadlocking the emulator."};
- _ ->
- {skipped, "\"true\" command not found"}
- end;
- _ ->
- {skip,"Only run on Unix"}
+ {unix, _} ->
+ ct:timetrap({minutes, 4}),
+ TCR = self(),
+ case get_true_cmd() of
+ True when is_list(True) ->
+ lists:foreach(
+ fun (P) ->
+ receive
+ {P, ok} -> ok;
+ {P, Err} -> ct:fail(Err)
+ end
+ end,
+ lists:map(
+ fun(_) ->
+ spawn_link(
+ fun() ->
+ process_flag(trap_exit, true),
+ case catch open_port({spawn, True},
+ [stream,exit_status]) of
+ P when is_port(P) ->
+ receive
+ {P,{exit_status,_}} ->
+ TCR ! {self(),ok};
+ {'EXIT',_,{R2,_}} when R2 == emfile;
+ R2 == eagain;
+ R2 == enomem ->
+ TCR ! {self(),ok};
+ Err2 ->
+ TCR ! {self(),{msg,Err2}}
+ end;
+ {'EXIT',{R1,_}} when R1 == emfile;
+ R1 == eagain;
+ R1 == enomem ->
+ TCR ! {self(),ok};
+ Err1 ->
+ TCR ! {self(), {open_port,Err1}}
+ end
+ end)
+ end,
+ lists:duplicate(1000,[]))),
+ {comment,
+ "This test case doesn't always fail when the bug that "
+ "it tests for is present (it is most likely to fail on"
+ " a multi processor machine). If the test case fails it"
+ " will fail by deadlocking the emulator."};
+ _ ->
+ {skipped, "\"true\" command not found"}
+ end;
+ _ ->
+ {skip,"Only run on Unix"}
end.
get_true_cmd() ->
DoFileExist = fun (FileName) ->
- case file:read_file_info(FileName) of
- {ok, _} -> throw(FileName);
- _ -> not_found
- end
- end,
+ case file:read_file_info(FileName) of
+ {ok, _} -> throw(FileName);
+ _ -> not_found
+ end
+ end,
catch begin
- %% First check in /usr/bin and /bin
- DoFileExist("/usr/bin/true"),
- DoFileExist("/bin/true"),
- %% Try which
- case filename:dirname(os:cmd("which true")) of
- "." -> not_found;
- TrueDir -> filename:join(TrueDir, "true")
- end
- end.
+ %% First check in /usr/bin and /bin
+ DoFileExist("/usr/bin/true"),
+ DoFileExist("/bin/true"),
+ %% Try which
+ case filename:dirname(os:cmd("which true")) of
+ "." -> not_found;
+ TrueDir -> filename:join(TrueDir, "true")
+ end
+ end.
%% 'exit_status' option
-exit_status(suite) ->
- [];
-exit_status(doc) ->
- ["Test that the 'exit_status' option works"];
+%%
+%% Test that the 'exit_status' option works
exit_status(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(60)),
- port_expect(Config,[{"x",
- [{exit_status, 5}]}],
- 1, "", [exit_status]),
- test_server:timetrap_cancel(Dog),
+ ct:timetrap({minutes, 1}),
+ port_expect(Config,
+ [{"x", [{exit_status, 5}]}],
+ 1, "", [exit_status]),
ok.
-spawn_driver(suite) ->
- [];
-spawn_driver(doc) ->
- ["Test spawning a driver specifically"];
+%% Test spawning a driver specifically
spawn_driver(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
- Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
ok = load_driver(Path, "echo_drv"),
Port = erlang:open_port({spawn_driver, "echo_drv"}, []),
Port ! {self(), {command, "Hello port!"}},
receive
- {Port, {data, "Hello port!"}} = Msg1 ->
- io:format("~p~n", [Msg1]),
- ok;
- Other ->
- test_server:fail({unexpected, Other})
- end,
+ {Port, {data, "Hello port!"}} = Msg1 ->
+ io:format("~p~n", [Msg1]),
+ ok;
+ Other ->
+ ct:fail({unexpected, Other})
+ end,
Port ! {self(), close},
receive {Port, closed} -> ok end,
Port2 = erlang:open_port({spawn_driver, "echo_drv -Hello port?"},
- []),
+ []),
receive
- {Port2, {data, "Hello port?"}} = Msg2 ->
- io:format("~p~n", [Msg2]),
- ok;
- Other2 ->
- test_server:fail({unexpected2, Other2})
- end,
+ {Port2, {data, "Hello port?"}} = Msg2 ->
+ io:format("~p~n", [Msg2]),
+ ok;
+ Other2 ->
+ ct:fail({unexpected2, Other2})
+ end,
Port2 ! {self(), close},
receive {Port2, closed} -> ok end,
{'EXIT',{badarg,_}} = (catch erlang:open_port({spawn_driver, "ls"}, [])),
{'EXIT',{badarg,_}} = (catch erlang:open_port({spawn_driver, "cmd"}, [])),
{'EXIT',{badarg,_}} = (catch erlang:open_port({spawn_driver, os:find_executable("erl")}, [])),
- test_server:timetrap_cancel(Dog),
ok.
-parallelism_option(suite) ->
- [];
-parallelism_option(doc) ->
- ["Test parallelism option of open_port"];
+%% Test parallelism option of open_port
parallelism_option(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Path = ?config(data_dir, Config),
- ?line ok = load_driver(Path, "echo_drv"),
- ?line Port = erlang:open_port({spawn_driver, "echo_drv"},
- [{parallelism, true}]),
- ?line {parallelism, true} = erlang:port_info(Port, parallelism),
- ?line Port ! {self(), {command, "Hello port!"}},
- ?line receive
- {Port, {data, "Hello port!"}} = Msg1 ->
- io:format("~p~n", [Msg1]),
- ok;
- Other ->
- test_server:fail({unexpected, Other})
- end,
- ?line Port ! {self(), close},
- ?line receive {Port, closed} -> ok end,
-
- ?line Port2 = erlang:open_port({spawn_driver, "echo_drv -Hello port?"},
- [{parallelism, false}]),
- ?line {parallelism, false} = erlang:port_info(Port2, parallelism),
- ?line receive
- {Port2, {data, "Hello port?"}} = Msg2 ->
- io:format("~p~n", [Msg2]),
- ok;
- Other2 ->
- test_server:fail({unexpected2, Other2})
- end,
- ?line Port2 ! {self(), close},
- ?line receive {Port2, closed} -> ok end,
- ?line test_server:timetrap_cancel(Dog),
+ Path = proplists:get_value(data_dir, Config),
+ ok = load_driver(Path, "echo_drv"),
+ Port = erlang:open_port({spawn_driver, "echo_drv"},
+ [{parallelism, true}]),
+ {parallelism, true} = erlang:port_info(Port, parallelism),
+ Port ! {self(), {command, "Hello port!"}},
+ receive
+ {Port, {data, "Hello port!"}} = Msg1 ->
+ io:format("~p~n", [Msg1]),
+ ok;
+ Other ->
+ ct:fail({unexpected, Other})
+ end,
+ Port ! {self(), close},
+ receive {Port, closed} -> ok end,
+
+ Port2 = erlang:open_port({spawn_driver, "echo_drv -Hello port?"},
+ [{parallelism, false}]),
+ {parallelism, false} = erlang:port_info(Port2, parallelism),
+ receive
+ {Port2, {data, "Hello port?"}} = Msg2 ->
+ io:format("~p~n", [Msg2]),
+ ok;
+ Other2 ->
+ ct:fail({unexpected2, Other2})
+ end,
+ Port2 ! {self(), close},
+ receive {Port2, closed} -> ok end,
ok.
-spawn_executable(suite) ->
- [];
-spawn_executable(doc) ->
- ["Test spawning an executable specifically"];
+%% Test spawning an executable specifically
spawn_executable(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
EchoArgs1 = filename:join([DataDir,"echo_args"]),
ExactFile1 = filename:nativename(os:find_executable(EchoArgs1)),
[ExactFile1] = run_echo_args(DataDir,[]),
@@ -1376,25 +1369,25 @@ spawn_executable(Config) when is_list(Config) ->
["echo_arguments"] = run_echo_args(DataDir,["echo_arguments"]),
["echo_arguments"] = run_echo_args(DataDir,[binary, "echo_arguments"]),
[ExactFile1,"hello world","dlrow olleh"] =
- run_echo_args(DataDir,[ExactFile1,"hello world","dlrow olleh"]),
+ run_echo_args(DataDir,[ExactFile1,"hello world","dlrow olleh"]),
[ExactFile1] = run_echo_args(DataDir,[default]),
[ExactFile1] = run_echo_args(DataDir,[binary, default]),
[ExactFile1,"hello world","dlrow olleh"] =
- run_echo_args(DataDir,[switch_order,ExactFile1,"hello world",
- "dlrow olleh"]),
+ run_echo_args(DataDir,[switch_order,ExactFile1,"hello world",
+ "dlrow olleh"]),
[ExactFile1,"hello world","dlrow olleh"] =
- run_echo_args(DataDir,[binary,switch_order,ExactFile1,"hello world",
- "dlrow olleh"]),
+ run_echo_args(DataDir,[binary,switch_order,ExactFile1,"hello world",
+ "dlrow olleh"]),
[ExactFile1,"hello world","dlrow olleh"] =
- run_echo_args(DataDir,[default,"hello world","dlrow olleh"]),
+ run_echo_args(DataDir,[default,"hello world","dlrow olleh"]),
[ExactFile1,"hello world","dlrow olleh"] =
- run_echo_args_2("\""++ExactFile1++"\" "++"\"hello world\" \"dlrow olleh\""),
+ run_echo_args_2("\""++ExactFile1++"\" "++"\"hello world\" \"dlrow olleh\""),
[ExactFile1,"hello world","dlrow olleh"] =
- run_echo_args_2(unicode:characters_to_binary("\""++ExactFile1++"\" "++"\"hello world\" \"dlrow olleh\"")),
+ run_echo_args_2(unicode:characters_to_binary("\""++ExactFile1++"\" "++"\"hello world\" \"dlrow olleh\"")),
- PrivDir = ?config(priv_dir, Config),
- SpaceDir =filename:join([PrivDir,"With Spaces"]),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ SpaceDir = filename:join([PrivDir,"With Spaces"]),
file:make_dir(SpaceDir),
Executable = filename:basename(ExactFile1),
file:copy(ExactFile1,filename:join([SpaceDir,Executable])),
@@ -1405,33 +1398,32 @@ spawn_executable(Config) when is_list(Config) ->
["echo_args"] = run_echo_args(SpaceDir,["echo_args"]),
["echo_arguments"] = run_echo_args(SpaceDir,["echo_arguments"]),
[ExactFile2,"hello world","dlrow olleh"] =
- run_echo_args(SpaceDir,[ExactFile2,"hello world","dlrow olleh"]),
+ run_echo_args(SpaceDir,[ExactFile2,"hello world","dlrow olleh"]),
[ExactFile2,"hello world","dlrow olleh"] =
- run_echo_args(SpaceDir,[binary, ExactFile2,"hello world","dlrow olleh"]),
+ run_echo_args(SpaceDir,[binary, ExactFile2,"hello world","dlrow olleh"]),
[ExactFile2,"hello \"world\"","\"dlrow\" olleh"] =
- run_echo_args(SpaceDir,[binary, ExactFile2,"hello \"world\"","\"dlrow\" olleh"]),
+ run_echo_args(SpaceDir,[binary, ExactFile2,"hello \"world\"","\"dlrow\" olleh"]),
[ExactFile2,"hello \"world\"","\"dlrow\" olleh"] =
- run_echo_args(SpaceDir,[binary, ExactFile2,"hello \"world\"","\"dlrow\" olleh"]),
+ run_echo_args(SpaceDir,[binary, ExactFile2,"hello \"world\"","\"dlrow\" olleh"]),
[ExactFile2] = run_echo_args(SpaceDir,[default]),
[ExactFile2,"hello world","dlrow olleh"] =
- run_echo_args(SpaceDir,[switch_order,ExactFile2,"hello world",
- "dlrow olleh"]),
+ run_echo_args(SpaceDir,[switch_order,ExactFile2,"hello world", "dlrow olleh"]),
[ExactFile2,"hello world","dlrow olleh"] =
- run_echo_args(SpaceDir,[default,"hello world","dlrow olleh"]),
+ run_echo_args(SpaceDir,[default,"hello world","dlrow olleh"]),
[ExactFile2,"hello world","dlrow olleh"] =
- run_echo_args_2("\""++ExactFile2++"\" "++"\"hello world\" \"dlrow olleh\""),
+ run_echo_args_2("\""++ExactFile2++"\" "++"\"hello world\" \"dlrow olleh\""),
[ExactFile2,"hello world","dlrow olleh"] =
- run_echo_args_2(unicode:characters_to_binary("\""++ExactFile2++"\" "++"\"hello world\" \"dlrow olleh\"")),
+ run_echo_args_2(unicode:characters_to_binary("\""++ExactFile2++"\" "++"\"hello world\" \"dlrow olleh\"")),
ExeExt =
- case string:to_lower(lists:last(string:tokens(ExactFile2,"."))) of
- "exe" ->
- ".exe";
- _ ->
- ""
- end,
+ case string:to_lower(lists:last(string:tokens(ExactFile2,"."))) of
+ "exe" ->
+ ".exe";
+ _ ->
+ ""
+ end,
Executable2 = "spoky name"++ExeExt,
file:copy(ExactFile1,filename:join([SpaceDir,Executable2])),
ExactFile3 = filename:nativename(filename:join([SpaceDir,Executable2])),
@@ -1440,38 +1432,37 @@ spawn_executable(Config) when is_list(Config) ->
["echo_args"] = run_echo_args(SpaceDir,Executable2,["echo_args"]),
["echo_arguments"] = run_echo_args(SpaceDir,Executable2,["echo_arguments"]),
[ExactFile3,"hello world","dlrow olleh"] =
- run_echo_args(SpaceDir,Executable2,[ExactFile3,"hello world","dlrow olleh"]),
+ run_echo_args(SpaceDir,Executable2,[ExactFile3,"hello world","dlrow olleh"]),
[ExactFile3] = run_echo_args(SpaceDir,Executable2,[default]),
[ExactFile3,"hello world","dlrow olleh"] =
- run_echo_args(SpaceDir,Executable2,
- [switch_order,ExactFile3,"hello world",
- "dlrow olleh"]),
+ run_echo_args(SpaceDir,Executable2,
+ [switch_order,ExactFile3,"hello world",
+ "dlrow olleh"]),
[ExactFile3,"hello world","dlrow olleh"] =
- run_echo_args(SpaceDir,Executable2,
- [default,"hello world","dlrow olleh"]),
+ run_echo_args(SpaceDir,Executable2,
+ [default,"hello world","dlrow olleh"]),
[ExactFile3,"hello world","dlrow olleh"] =
- run_echo_args_2("\""++ExactFile3++"\" "++"\"hello world\" \"dlrow olleh\""),
+ run_echo_args_2("\""++ExactFile3++"\" "++"\"hello world\" \"dlrow olleh\""),
[ExactFile3,"hello world","dlrow olleh"] =
- run_echo_args_2(unicode:characters_to_binary("\""++ExactFile3++"\" "++"\"hello world\" \"dlrow olleh\"")),
+ run_echo_args_2(unicode:characters_to_binary("\""++ExactFile3++"\" "++"\"hello world\" \"dlrow olleh\"")),
{'EXIT',{enoent,_}} = (catch run_echo_args(SpaceDir,"fnurflmonfi",
- [default,"hello world",
- "dlrow olleh"])),
+ [default,"hello world",
+ "dlrow olleh"])),
NonExec = "kronxfrt"++ExeExt,
file:write_file(filename:join([SpaceDir,NonExec]),
- <<"Not an executable">>),
+ <<"Not an executable">>),
{'EXIT',{eacces,_}} = (catch run_echo_args(SpaceDir,NonExec,
- [default,"hello world",
- "dlrow olleh"])),
+ [default,"hello world",
+ "dlrow olleh"])),
{'EXIT',{enoent,_}} = (catch open_port({spawn_executable,"cmd"},[])),
{'EXIT',{enoent,_}} = (catch open_port({spawn_executable,"sh"},[])),
case os:type() of
- {win32,_} ->
- test_bat_file(SpaceDir);
- {unix,_} ->
- test_sh_file(SpaceDir)
+ {win32,_} ->
+ test_bat_file(SpaceDir);
+ {unix,_} ->
+ test_sh_file(SpaceDir)
end,
- test_server:timetrap_cancel(Dog),
ok.
unregister_name(Config) when is_list(Config) ->
@@ -1482,29 +1473,29 @@ test_bat_file(Dir) ->
FN = "tf.bat",
Full = filename:join([Dir,FN]),
D = [<<"@echo off\r\n">>,
- <<"echo argv[0]:^|%0^|\r\n">>,
- <<"if \"%1\" == \"\" goto done\r\n">>,
- <<"echo argv[1]:^|%1^|\r\n">>,
- <<"if \"%2\" == \"\" goto done\r\n">>,
- <<"echo argv[2]:^|%2^|\r\n">>,
- <<"if \"%3\" == \"\" goto done\r\n">>,
- <<"echo argv[3]:^|%3^|\r\n">>,
- <<"if \"%4\" == \"\" goto done\r\n">>,
- <<"echo argv[4]:^|%4^|\r\n">>,
- <<"if \"%5\" == \"\" goto done\r\n">>,
- <<"echo argv[5]:^|%5^|\r\n">>,
- <<"\r\n">>,
- <<":done\r\n">>,
- <<"\r\n">>],
+ <<"echo argv[0]:^|%0^|\r\n">>,
+ <<"if \"%1\" == \"\" goto done\r\n">>,
+ <<"echo argv[1]:^|%1^|\r\n">>,
+ <<"if \"%2\" == \"\" goto done\r\n">>,
+ <<"echo argv[2]:^|%2^|\r\n">>,
+ <<"if \"%3\" == \"\" goto done\r\n">>,
+ <<"echo argv[3]:^|%3^|\r\n">>,
+ <<"if \"%4\" == \"\" goto done\r\n">>,
+ <<"echo argv[4]:^|%4^|\r\n">>,
+ <<"if \"%5\" == \"\" goto done\r\n">>,
+ <<"echo argv[5]:^|%5^|\r\n">>,
+ <<"\r\n">>,
+ <<":done\r\n">>,
+ <<"\r\n">>],
file:write_file(Full,list_to_binary(D)),
EF = filename:basename(FN),
[DN,"hello","world"] =
- run_echo_args(Dir,FN,
- [default,"hello","world"]),
+ run_echo_args(Dir,FN,
+ [default,"hello","world"]),
%% The arg0 argumant should be ignored when running batch files
[DN,"hello","world"] =
- run_echo_args(Dir,FN,
- ["knaskurt","hello","world"]),
+ run_echo_args(Dir,FN,
+ ["knaskurt","hello","world"]),
EF = filename:basename(DN),
ok.
@@ -1512,40 +1503,40 @@ test_sh_file(Dir) ->
FN = "tf.sh",
Full = filename:join([Dir,FN]),
D = [<<"#! /bin/sh\n">>,
- <<"echo 'argv[0]:|'$0'|'\n">>,
- <<"i=1\n">>,
- <<"while [ '!' -z \"$1\" ]; do\n">>,
- <<" echo 'argv['$i']:|'\"$1\"'|'\n">>,
- <<" shift\n">>,
- <<" i=`expr $i + 1`\n">>,
- <<"done\n">>],
+ <<"echo 'argv[0]:|'$0'|'\n">>,
+ <<"i=1\n">>,
+ <<"while [ '!' -z \"$1\" ]; do\n">>,
+ <<" echo 'argv['$i']:|'\"$1\"'|'\n">>,
+ <<" shift\n">>,
+ <<" i=`expr $i + 1`\n">>,
+ <<"done\n">>],
file:write_file(Full,list_to_binary(D)),
chmodplusx(Full),
[Full,"hello","world"] =
- run_echo_args(Dir,FN,
- [default,"hello","world"]),
+ run_echo_args(Dir,FN,
+ [default,"hello","world"]),
[Full,"hello","world of spaces"] =
- run_echo_args(Dir,FN,
- [default,"hello","world of spaces"]),
+ run_echo_args(Dir,FN,
+ [default,"hello","world of spaces"]),
file:write_file(filename:join([Dir,"testfile1"]),<<"testdata1">>),
file:write_file(filename:join([Dir,"testfile2"]),<<"testdata2">>),
Pattern = filename:join([Dir,"testfile*"]),
L = filelib:wildcard(Pattern),
2 = length(L),
[Full,"hello",Pattern] =
- run_echo_args(Dir,FN,
- [default,"hello",Pattern]),
- ok.
+ run_echo_args(Dir,FN,
+ [default,"hello",Pattern]),
+ ok.
+
-
chmodplusx(Filename) ->
case file:read_file_info(Filename) of
- {ok,FI} ->
- FI2 = FI#file_info{mode = ((FI#file_info.mode) bor 8#00100)},
- file:write_file_info(Filename,FI2);
- _ ->
- ok
+ {ok,FI} ->
+ FI2 = FI#file_info{mode = ((FI#file_info.mode) bor 8#00100)},
+ file:write_file_info(Filename,FI2);
+ _ ->
+ ok
end.
run_echo_args_2(FullnameAndArgs) ->
@@ -1554,7 +1545,7 @@ run_echo_args_2(FullnameAndArgs) ->
Port ! {self(), close},
receive {Port, closed} -> ok end,
parse_echo_args_output(Data).
-
+
run_echo_args(Where,Args) ->
run_echo_args(Where,"echo_args",Args).
@@ -1562,9 +1553,9 @@ run_echo_args(Where,Prog,Args) ->
{Binary, ArgvArg} = pack_argv(Args),
Command0 = filename:join([Where,Prog]),
Command = case Binary of
- true -> unicode:characters_to_binary(Command0);
- false -> Command0
- end,
+ true -> unicode:characters_to_binary(Command0);
+ false -> Command0
+ end,
Port = open_port({spawn_executable,Command},ArgvArg++[eof]),
Data = collect_data(Port),
Port ! {self(), close},
@@ -1578,14 +1569,14 @@ pack_argv(Args) ->
pack_argv(Args, Binary) ->
case Args of
- [] ->
- [];
- [default|T] ->
- [{args,[make_bin(Arg,Binary) || Arg <- T]}];
- [switch_order,H|T] ->
- [{args,[make_bin(Arg,Binary) || Arg <- T]},{arg0,make_bin(H,Binary)}];
- [H|T] ->
- [{arg0,make_bin(H,Binary)},{args,[make_bin(Arg,Binary) || Arg <- T]}]
+ [] ->
+ [];
+ [default|T] ->
+ [{args,[make_bin(Arg,Binary) || Arg <- T]}];
+ [switch_order,H|T] ->
+ [{args,[make_bin(Arg,Binary) || Arg <- T]},{arg0,make_bin(H,Binary)}];
+ [H|T] ->
+ [{arg0,make_bin(H,Binary)},{args,[make_bin(Arg,Binary) || Arg <- T]}]
end.
make_bin(Str, false) -> Str;
@@ -1593,54 +1584,49 @@ make_bin(Str, true) -> unicode:characters_to_binary(Str).
collect_data(Port) ->
receive
- {Port, {data, Data}} ->
- Data ++ collect_data(Port);
- {Port, eof} ->
- []
+ {Port, {data, Data}} ->
+ Data ++ collect_data(Port);
+ {Port, eof} ->
+ []
end.
parse_echo_args_output(Data) ->
[lists:last(string:tokens(S,"|")) || S <- string:tokens(Data,"\r\n")].
-mix_up_ports(suite) ->
- [];
-mix_up_ports(doc) ->
- ["Test that the emulator does not mix up ports when the port table wraps"];
+%% Test that the emulator does not mix up ports when the port table wraps
mix_up_ports(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
- Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
ok = load_driver(Path, "echo_drv"),
Port = erlang:open_port({spawn, "echo_drv"}, []),
Port ! {self(), {command, "Hello port!"}},
receive
- {Port, {data, "Hello port!"}} = Msg1 ->
- io:format("~p~n", [Msg1]),
- ok;
- Other ->
- test_server:fail({unexpected, Other})
- end,
+ {Port, {data, "Hello port!"}} = Msg1 ->
+ io:format("~p~n", [Msg1]),
+ ok;
+ Other ->
+ ct:fail({unexpected, Other})
+ end,
Port ! {self(), close},
receive {Port, closed} -> ok end,
loop(start, done,
- fun(P) ->
- Q =
- (catch erlang:open_port({spawn, "echo_drv"}, [])),
-%% io:format("~p ", [Q]),
- if is_port(Q) ->
- Q;
- true ->
- io:format("~p~n", [P]),
- done
- end
- end),
+ fun(P) ->
+ Q =
+ (catch erlang:open_port({spawn, "echo_drv"}, [])),
+ %% io:format("~p ", [Q]),
+ if is_port(Q) ->
+ Q;
+ true ->
+ io:format("~p~n", [P]),
+ done
+ end
+ end),
Port ! {self(), {command, "Hello again port!"}},
receive
- Msg2 ->
- test_server:fail({unexpected, Msg2})
- after 1000 ->
- ok
- end,
- test_server:timetrap_cancel(Dog),
+ Msg2 ->
+ ct:fail({unexpected, Msg2})
+ after 1000 ->
+ ok
+ end,
ok.
loop(Stop, Stop, Fun) when is_function(Fun) ->
@@ -1649,131 +1635,118 @@ loop(Start, Stop, Fun) when is_function(Fun) ->
loop(Fun(Start), Stop, Fun).
-otp_5112(suite) ->
- [];
-otp_5112(doc) ->
- ["Test that link to connected process is taken away when port calls",
- "driver_exit() also when the port index has wrapped"];
+%% Test that link to connected process is taken away when port calls
+%% driver_exit() also when the port index has wrapped
otp_5112(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
- Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
ok = load_driver(Path, "exit_drv"),
Port = otp_5112_get_wrapped_port(),
- ?t:format("Max ports: ~p~n",[max_ports()]),
- ?t:format("Port: ~p~n",[Port]),
+ io:format("Max ports: ~p~n",[max_ports()]),
+ io:format("Port: ~p~n",[Port]),
{links, Links1} = process_info(self(),links),
- ?t:format("Links1: ~p~n",[Links1]),
+ io:format("Links1: ~p~n",[Links1]),
true = lists:member(Port, Links1),
Port ! {self(), {command, ""}},
- ?line wait_until(fun () -> lists:member(Port, erlang:ports()) == false end),
+ wait_until(fun () -> lists:member(Port, erlang:ports()) == false end),
{links, Links2} = process_info(self(),links),
- ?t:format("Links2: ~p~n",[Links2]),
+ io:format("Links2: ~p~n",[Links2]),
false = lists:member(Port, Links2), %% This used to fail
- test_server:timetrap_cancel(Dog),
ok.
otp_5112_get_wrapped_port() ->
P1 = erlang:open_port({spawn, "exit_drv"}, []),
case port_ix(P1) < max_ports() of
- true ->
- ?t:format("Need to wrap port index (~p)~n", [P1]),
- otp_5112_wrap_port_ix([P1]),
- P2 = erlang:open_port({spawn, "exit_drv"}, []),
- false = port_ix(P2) < max_ports(),
- P2;
- false ->
- ?t:format("Port index already wrapped (~p)~n", [P1]),
- P1
- end.
+ true ->
+ io:format("Need to wrap port index (~p)~n", [P1]),
+ otp_5112_wrap_port_ix([P1]),
+ P2 = erlang:open_port({spawn, "exit_drv"}, []),
+ false = port_ix(P2) < max_ports(),
+ P2;
+ false ->
+ io:format("Port index already wrapped (~p)~n", [P1]),
+ P1
+ end.
otp_5112_wrap_port_ix(Ports) ->
case (catch erlang:open_port({spawn, "exit_drv"}, [])) of
- Port when is_port(Port) ->
- otp_5112_wrap_port_ix([Port|Ports]);
- _ ->
- %% Port table now full; empty port table
- lists:foreach(fun (P) -> P ! {self(), close} end,
- Ports),
- ok
- end.
+ Port when is_port(Port) ->
+ otp_5112_wrap_port_ix([Port|Ports]);
+ _ ->
+ %% Port table now full; empty port table
+ lists:foreach(fun (P) -> P ! {self(), close} end,
+ Ports),
+ ok
+ end.
-otp_5119(suite) ->
- [];
-otp_5119(doc) ->
- ["Test that port index is not unnecessarily wrapped"];
+%% Test that port index is not unnecessarily wrapped
otp_5119(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
- Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
ok = load_driver(Path, "exit_drv"),
PI1 = port_ix(otp_5119_fill_empty_port_tab([])),
Port2 = erlang:open_port({spawn, "exit_drv"}, []),
PI2 = port_ix(Port2),
{PortIx1, PortIx2} = case PI2 > PI1 of
- true ->
- {PI1, PI2};
- false ->
- {port_ix(otp_5119_fill_empty_port_tab([Port2])),
- port_ix(erlang:open_port({spawn, "exit_drv"}, []))}
- end,
+ true ->
+ {PI1, PI2};
+ false ->
+ {port_ix(otp_5119_fill_empty_port_tab([Port2])),
+ port_ix(erlang:open_port({spawn, "exit_drv"}, []))}
+ end,
MaxPorts = max_ports(),
- ?t:format("PortIx1 = ~p ~p~n", [PI1, PortIx1]),
- ?t:format("PortIx2 = ~p ~p~n", [PI2, PortIx2]),
- ?t:format("MaxPorts = ~p~n", [MaxPorts]),
+ io:format("PortIx1 = ~p ~p~n", [PI1, PortIx1]),
+ io:format("PortIx2 = ~p ~p~n", [PI2, PortIx2]),
+ io:format("MaxPorts = ~p~n", [MaxPorts]),
true = PortIx2 > PortIx1,
true = PortIx2 =< PortIx1 + MaxPorts,
- test_server:timetrap_cancel(Dog),
ok.
otp_5119_fill_empty_port_tab(Ports) ->
case (catch erlang:open_port({spawn, "exit_drv"}, [])) of
- Port when is_port(Port) ->
- otp_5119_fill_empty_port_tab([Port|Ports]);
- _ ->
- %% Port table now full; empty port table
- lists:foreach(fun (P) -> P ! {self(), close} end,
- Ports),
- [LastPort|_] = Ports,
- LastPort
- end.
+ Port when is_port(Port) ->
+ otp_5119_fill_empty_port_tab([Port|Ports]);
+ _ ->
+ %% Port table now full; empty port table
+ lists:foreach(fun (P) -> P ! {self(), close} end,
+ Ports),
+ [LastPort|_] = Ports,
+ LastPort
+ end.
max_ports() ->
erlang:system_info(port_limit).
port_ix(Port) when is_port(Port) ->
["#Port",_,PortIxStr] = string:tokens(erlang:port_to_list(Port),
- "<.>"),
+ "<.>"),
list_to_integer(PortIxStr).
-otp_6224(doc) -> ["Check that port command failure doesn't crash the emulator"];
-otp_6224(suite) -> [];
+%% Check that port command failure doesn't crash the emulator
otp_6224(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
- Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
ok = load_driver(Path, "failure_drv"),
Go = make_ref(),
Failer = spawn(fun () ->
- receive Go -> ok end,
- Port = open_port({spawn, "failure_drv"},
- []),
- Port ! {self(), {command, "Fail, please!"}},
- otp_6224_loop()
- end),
+ receive Go -> ok end,
+ Port = open_port({spawn, "failure_drv"},
+ []),
+ Port ! {self(), {command, "Fail, please!"}},
+ otp_6224_loop()
+ end),
Mon = erlang:monitor(process, Failer),
Failer ! Go,
receive
- {'DOWN', Mon, process, Failer, Reason} ->
- case Reason of
- {driver_failed, _} -> ok;
- driver_failed -> ok;
- _ -> ?t:fail({unexpected_exit_reason,
- Reason})
- end
- end,
- test_server:timetrap_cancel(Dog),
+ {'DOWN', Mon, process, Failer, Reason} ->
+ case Reason of
+ {driver_failed, _} -> ok;
+ driver_failed -> ok;
+ _ -> ct:fail({unexpected_exit_reason,
+ Reason})
+ end
+ end,
ok.
-
+
otp_6224_loop() ->
receive _ -> ok after 0 -> ok end,
otp_6224_loop().
@@ -1782,29 +1755,26 @@ otp_6224_loop() ->
-define(EXIT_STATUS_MSB_MAX_PROCS, 64).
-define(EXIT_STATUS_MSB_MAX_PORTS, 300).
-exit_status_multi_scheduling_block(doc) -> [];
-exit_status_multi_scheduling_block(suite) -> [];
exit_status_multi_scheduling_block(Config) when is_list(Config) ->
Repeat = 3,
- case ?t:os_type() of
- {unix, _} ->
- Dog = ?t:timetrap(test_server:minutes(2*Repeat)),
- SleepSecs = 6,
- try
- lists:foreach(fun (_) ->
- exit_status_msb_test(Config,
- SleepSecs)
- end,
- lists:seq(1, Repeat))
- after
- %% Wait for the system to recover (regardless
- %% of success or not) otherwise later testcases
- %% may unnecessarily fail.
- ?t:timetrap_cancel(Dog),
- receive after SleepSecs+500 -> ok end
- end;
- _ -> {skip, "Not implemented for this OS"}
- end.
+ case test_server:os_type() of
+ {unix, _} ->
+ ct:timetrap({minutes, 2*Repeat}),
+ SleepSecs = 6,
+ try
+ lists:foreach(fun (_) ->
+ exit_status_msb_test(Config,
+ SleepSecs)
+ end,
+ lists:seq(1, Repeat))
+ after
+ %% Wait for the system to recover (regardless
+ %% of success or not) otherwise later testcases
+ %% may unnecessarily fail.
+ receive after SleepSecs+500 -> ok end
+ end;
+ _ -> {skip, "Not implemented for this OS"}
+ end.
exit_status_msb_test(Config, SleepSecs) when is_list(Config) ->
%%
@@ -1814,131 +1784,131 @@ exit_status_msb_test(Config, SleepSecs) when is_list(Config) ->
%%
NoSchedsOnln = erlang:system_info(schedulers_online),
Parent = self(),
- ?t:format("SleepSecs = ~p~n", [SleepSecs]),
+ io:format("SleepSecs = ~p~n", [SleepSecs]),
PortProg = "sleep " ++ integer_to_list(SleepSecs),
Start = erlang:monotonic_time(micro_seconds),
NoProcs = case NoSchedsOnln of
- NProcs when NProcs < ?EXIT_STATUS_MSB_MAX_PROCS ->
- NProcs;
- _ ->
- ?EXIT_STATUS_MSB_MAX_PROCS
- end,
+ NProcs when NProcs < ?EXIT_STATUS_MSB_MAX_PROCS ->
+ NProcs;
+ _ ->
+ ?EXIT_STATUS_MSB_MAX_PROCS
+ end,
NoPortsPerProc = case 20*NoProcs of
- TNPorts when TNPorts < ?EXIT_STATUS_MSB_MAX_PORTS -> 20;
- _ -> ?EXIT_STATUS_MSB_MAX_PORTS div NoProcs
- end,
- ?t:format("NoProcs = ~p~nNoPortsPerProc = ~p~n",
- [NoProcs, NoPortsPerProc]),
+ TNPorts when TNPorts < ?EXIT_STATUS_MSB_MAX_PORTS -> 20;
+ _ -> ?EXIT_STATUS_MSB_MAX_PORTS div NoProcs
+ end,
+ io:format("NoProcs = ~p~nNoPortsPerProc = ~p~n",
+ [NoProcs, NoPortsPerProc]),
ProcFun
- = fun () ->
- PrtSIds = lists:map(
- fun (_) ->
- erlang:yield(),
- case catch open_port({spawn, PortProg},
- [exit_status]) of
- Prt when is_port(Prt) ->
- {Prt,
- erlang:system_info(scheduler_id)};
- {'EXIT', {Err, _}} when Err == eagain;
- Err == emfile ->
- noop;
- {'EXIT', Err} when Err == eagain;
- Err == emfile ->
- noop;
- Error ->
- ?t:fail(Error)
- end
- end,
- lists:seq(1, NoPortsPerProc)),
- SIds = lists:filter(fun (noop) -> false;
- (_) -> true
- end,
- lists:map(fun (noop) -> noop;
- ({_, SId}) -> SId
- end,
- PrtSIds)),
- process_flag(scheduler, 0),
- Parent ! {self(), started, SIds},
- lists:foreach(
- fun (noop) ->
- noop;
- ({Port, _}) ->
- receive
- {Port, {exit_status, 0}} ->
- ok;
- {Port, {exit_status, Status}} when Status > 128 ->
- %% Sometimes happens when we have created
- %% too many ports.
- ok;
- {Port, {exit_status, _}} = ESMsg ->
- {Port, {exit_status, 0}} = ESMsg
- end
- end,
- PrtSIds),
- Parent ! {self(), done}
- end,
+ = fun () ->
+ PrtSIds = lists:map(
+ fun (_) ->
+ erlang:yield(),
+ case catch open_port({spawn, PortProg},
+ [exit_status]) of
+ Prt when is_port(Prt) ->
+ {Prt,
+ erlang:system_info(scheduler_id)};
+ {'EXIT', {Err, _}} when Err == eagain;
+ Err == emfile;
+ Err == enomem ->
+ noop;
+ {'EXIT', Err} when Err == eagain;
+ Err == emfile;
+ Err == enomem ->
+ noop;
+ Error ->
+ ct:fail(Error)
+ end
+ end,
+ lists:seq(1, NoPortsPerProc)),
+ SIds = lists:filter(fun (noop) -> false;
+ (_) -> true
+ end,
+ lists:map(fun (noop) -> noop;
+ ({_, SId}) -> SId
+ end,
+ PrtSIds)),
+ process_flag(scheduler, 0),
+ Parent ! {self(), started, SIds},
+ lists:foreach(
+ fun (noop) ->
+ noop;
+ ({Port, _}) ->
+ receive
+ {Port, {exit_status, 0}} ->
+ ok;
+ {Port, {exit_status, Status}} when Status > 128 ->
+ %% Sometimes happens when we have created
+ %% too many ports.
+ ok;
+ {Port, {exit_status, _}} = ESMsg ->
+ {Port, {exit_status, 0}} = ESMsg
+ end
+ end,
+ PrtSIds),
+ Parent ! {self(), done}
+ end,
Procs = lists:map(fun (N) ->
- spawn_opt(ProcFun,
- [link,
- {scheduler,
- (N rem NoSchedsOnln)+1}])
- end,
- lists:seq(1, NoProcs)),
+ spawn_opt(ProcFun,
+ [link,
+ {scheduler,
+ (N rem NoSchedsOnln)+1}])
+ end,
+ lists:seq(1, NoProcs)),
SIds = lists:map(fun (P) ->
- receive {P, started, SIds} -> SIds end
- end,
- Procs),
+ receive {P, started, SIds} -> SIds end
+ end,
+ Procs),
StartedTime = (erlang:monotonic_time(micro_seconds) - Start)/1000000,
- ?t:format("StartedTime = ~p~n", [StartedTime]),
+ io:format("StartedTime = ~p~n", [StartedTime]),
true = StartedTime < SleepSecs,
erlang:system_flag(multi_scheduling, block),
lists:foreach(fun (P) -> receive {P, done} -> ok end end, Procs),
DoneTime = (erlang:monotonic_time(micro_seconds) - Start)/1000000,
- ?t:format("DoneTime = ~p~n", [DoneTime]),
+ io:format("DoneTime = ~p~n", [DoneTime]),
true = DoneTime > SleepSecs,
ok = verify_multi_scheduling_blocked(),
erlang:system_flag(multi_scheduling, unblock),
case {length(lists:usort(lists:flatten(SIds))), NoSchedsOnln} of
- {N, N} ->
- ok;
- {N, M} ->
- ?t:fail("Failed to create ports on all"
- ++ integer_to_list(M) ++ " available"
- "schedulers. Only created ports on "
- ++ integer_to_list(N) ++ " schedulers.")
- end.
+ {N, N} ->
+ ok;
+ {N, M} ->
+ ct:fail("Failed to create ports on all ~w available"
+ "schedulers. Only created ports on ~w schedulers.", [M, N])
+ end.
save_sid(SIds) ->
SId = erlang:system_info(scheduler_id),
case lists:member(SId, SIds) of
- true -> SIds;
- false -> [SId|SIds]
+ true -> SIds;
+ false -> [SId|SIds]
end.
sid_proc(SIds) ->
NewSIds = save_sid(SIds),
receive
- {From, want_sids} ->
- From ! {self(), sids, NewSIds}
+ {From, want_sids} ->
+ From ! {self(), sids, NewSIds}
after 0 ->
- sid_proc(NewSIds)
+ sid_proc(NewSIds)
end.
verify_multi_scheduling_blocked() ->
Procs = lists:map(fun (_) ->
- spawn_link(fun () -> sid_proc([]) end)
- end,
- lists:seq(1, 3*erlang:system_info(schedulers_online))),
+ spawn_link(fun () -> sid_proc([]) end)
+ end,
+ lists:seq(1, 3*erlang:system_info(schedulers_online))),
receive after 1000 -> ok end,
SIds = lists:map(fun (P) ->
- P ! {self(), want_sids},
- receive {P, sids, PSIds} -> PSIds end
- end,
- Procs),
+ P ! {self(), want_sids},
+ receive {P, sids, PSIds} -> PSIds end
+ end,
+ Procs),
1 = length(lists:usort(lists:flatten(SIds))),
ok.
-
-
+
+
%%% Pinging functions.
stream_ping(Config, Size, CmdLine, Options) ->
@@ -1947,10 +1917,10 @@ stream_ping(Config, Size, CmdLine, Options) ->
ping(Config, Sizes, HSize, CmdLine, Options) ->
Actions = lists:map(fun(Size) ->
- [$p|Packet] = random_packet(Size, "ping"),
- {[$p|Packet], [[$P|Packet]]}
- end,
- Sizes),
+ [$p|Packet] = random_packet(Size, "ping"),
+ {[$p|Packet], [[$P|Packet]]}
+ end,
+ Sizes),
port_expect(Config, Actions, HSize, CmdLine, Options).
%% expect_input(Sizes, HSize, CmdLine, Options)
@@ -1972,7 +1942,7 @@ expect_input1(Config, [Size|Rest], Params, Expect, ReplyCommand) ->
expect_input1(Config, [], {HSize, CmdLine0, Options}, Expect, ReplyCommand) ->
CmdLine = build_cmd_line(CmdLine0, ReplyCommand, []),
port_expect(Config, [{false, lists:reverse(Expect)}],
- HSize, CmdLine, Options).
+ HSize, CmdLine, Options).
build_cmd_line(FixedCmdLine, [Cmd|Rest], []) ->
build_cmd_line(FixedCmdLine, Rest, [Cmd]);
@@ -1995,15 +1965,15 @@ build_cmd_line(FixedCmdLine, [], Result) ->
%% Returns the port.
port_expect(Config, Actions, HSize, CmdLine, Options0) ->
-% io:format("port_expect(~p, ~p, ~p, ~p)",
-% [Actions, HSize, CmdLine, Options0]),
+ % io:format("port_expect(~p, ~p, ~p, ~p)",
+ % [Actions, HSize, CmdLine, Options0]),
PortTest = port_test(Config),
Cmd = lists:concat([PortTest, " -h", HSize, " ", CmdLine]),
PortType =
- case HSize of
- 0 -> stream;
- _ -> {packet, HSize}
- end,
+ case HSize of
+ 0 -> stream;
+ _ -> {packet, HSize}
+ end,
Options = [PortType|Options0],
io:format("open_port({spawn, ~p}, ~p)", [Cmd, Options]),
Port = open_port({spawn, Cmd}, Options),
@@ -2014,11 +1984,11 @@ port_expect(Port, [{Send, Expects}|Rest], Options) when is_list(Expects) ->
port_send(Port, Send),
IsBinaryPort = lists:member(binary, Options),
Receiver =
- case {lists:member(stream, Options), line_option(Options)} of
- {false, _} -> fun receive_all/2;
- {true,false} -> fun stream_receive_all/2;
- {_, true} -> fun receive_all/2
- end,
+ case {lists:member(stream, Options), line_option(Options)} of
+ {false, _} -> fun receive_all/2;
+ {true,false} -> fun stream_receive_all/2;
+ {_, true} -> fun receive_all/2
+ end,
Receiver(Port, maybe_to_binary(Expects, IsBinaryPort)),
port_expect(Port, Rest, Options);
port_expect(_, [], _) ->
@@ -2046,34 +2016,34 @@ maybe_to_binary(Expects, false) ->
port_send(_Port, false) -> ok;
port_send(Port, Send) when is_list(Send) ->
-% io:format("port_send(~p, ~p)", [Port, Send]),
+ % io:format("port_send(~p, ~p)", [Port, Send]),
Port ! {self(), {command, Send}}.
receive_all(Port, [Expect|Rest]) ->
-% io:format("receive_all(~p, [~p|Rest])", [Port, Expect]),
+ % io:format("receive_all(~p, [~p|Rest])", [Port, Expect]),
receive
- {Port, {data, Expect}} ->
- io:format("Received ~s", [format(Expect)]),
- ok;
- {Port, {data, Other}} ->
- io:format("Received ~s; expected ~s",
- [format(Other), format(Expect)]),
- test_server:fail(bad_message);
- Other ->
- %% (We're not yet prepared for receiving both 'eol' and
- %% 'exit_status'; remember that they may appear in any order.)
- case {Expect, Rest, Other} of
- {eof, [], {Port, eof}} ->
- io:format("Received soft EOF.",[]),
- ok;
- {{exit_status, S}, [], {Port, {exit_status, S}}} ->
- io:format("Received exit status ~p.",[S]),
- ok;
- _ ->
-%%% io:format("Unexpected message: ~s", [format(Other)]),
- io:format("Unexpected message: ~w", [Other]),
- test_server:fail(unexpected_message)
- end
+ {Port, {data, Expect}} ->
+ io:format("Received ~s", [format(Expect)]),
+ ok;
+ {Port, {data, Other}} ->
+ io:format("Received ~s; expected ~s",
+ [format(Other), format(Expect)]),
+ ct:fail(bad_message);
+ Other ->
+ %% (We're not yet prepared for receiving both 'eol' and
+ %% 'exit_status'; remember that they may appear in any order.)
+ case {Expect, Rest, Other} of
+ {eof, [], {Port, eof}} ->
+ io:format("Received soft EOF.",[]),
+ ok;
+ {{exit_status, S}, [], {Port, {exit_status, S}}} ->
+ io:format("Received exit status ~p.",[S]),
+ ok;
+ _ ->
+ %%% io:format("Unexpected message: ~s", [format(Other)]),
+ io:format("Unexpected message: ~w", [Other]),
+ ct:fail(unexpected_message)
+ end
end,
receive_all(Port, Rest);
receive_all(_Port, []) ->
@@ -2088,30 +2058,30 @@ stream_receive_all1(_Port, []) ->
ok;
stream_receive_all1(Port, Expect) ->
receive
- {Port, {data, Data}} ->
- Remaining = compare(Data, Expect),
- stream_receive_all1(Port, Remaining);
- Other ->
- test_server:fail({bad_message, Other})
+ {Port, {data, Data}} ->
+ Remaining = compare(Data, Expect),
+ stream_receive_all1(Port, Remaining);
+ Other ->
+ ct:fail({bad_message, Other})
end.
compare(B1, B2) when is_binary(B1), is_binary(B2), byte_size(B1) =< byte_size(B2) ->
case split_binary(B2, size(B1)) of
- {B1,Remaining} ->
- Remaining;
- _Other ->
- test_server:fail(nomatch)
+ {B1,Remaining} ->
+ Remaining;
+ _Other ->
+ ct:fail(nomatch)
end;
compare(B1, B2) when is_binary(B1), is_binary(B2) ->
- test_server:fail(too_much_data);
+ ct:fail(too_much_data);
compare([X|Rest1], [X|Rest2]) ->
compare(Rest1, Rest2);
compare([_|_], [_|_]) ->
- test_server:fail(nomatch);
+ ct:fail(nomatch);
compare([], Remaining) ->
Remaining;
compare(_Data, []) ->
- test_server:fail(too_much_data).
+ ct:fail(too_much_data).
maybe_to_list(Bin) when is_binary(Bin) ->
binary_to_list(Bin);
@@ -2122,10 +2092,10 @@ format({Eol,List}) ->
io_lib:format("tuple<~w,~s>",[Eol, maybe_to_list(List)]);
format(List) when is_list(List) ->
case list_at_least(50, List) of
- true ->
- io_lib:format("\"~-50s...\"", [List]);
- false ->
- io_lib:format("~p", [List])
+ true ->
+ io_lib:format("\"~-50s...\"", [List]);
+ false ->
+ io_lib:format("~p", [List])
end;
format(Bin) when is_binary(Bin), size(Bin) >= 50 ->
io_lib:format("binary<~-50s...>", [binary_to_list(Bin, 1, 50)]);
@@ -2152,17 +2122,17 @@ build_packet(0, Result, _NextChar) ->
lists:reverse(Result);
build_packet(Left, Result, NextChar0) ->
NextChar =
- if
- NextChar0 >= 126 ->
- 33;
- true ->
- NextChar0+1
- end,
+ if
+ NextChar0 >= 126 ->
+ 33;
+ true ->
+ NextChar0+1
+ end,
build_packet(Left-1, [NextChar0|Result], NextChar).
sizes() ->
[10, 13, 64, 127, 128, 255, 256, 1023, 1024,
- 32767, 32768, 65535, 65536].
+ 32767, 32768, 65535, 65536].
sizes(Header_Size) ->
sizes(Header_Size, sizes(), []).
@@ -2183,15 +2153,14 @@ random_char(Chars) ->
lists:nth(uniform(length(Chars)), Chars).
uniform(N) ->
- case get(random_seed) of
- undefined ->
- {X, Y, Z} = Seed = time(),
- io:format("Random seed = ~p\n",[Seed]),
- random:seed(X, Y, Z);
- _ ->
- ok
+ case rand:export_seed() of
+ undefined ->
+ rand:seed(exsplus),
+ io:format("Random seed = ~p\n", [rand:export_seed()]);
+ _ ->
+ ok
end,
- random:uniform(N).
+ rand:uniform(N).
fun_spawn(Fun) ->
fun_spawn(Fun, []).
@@ -2200,13 +2169,11 @@ fun_spawn(Fun, Args) ->
spawn_link(erlang, apply, [Fun, Args]).
port_test(Config) when is_list(Config) ->
- filename:join(?config(data_dir, Config), "port_test").
-
+ filename:join(proplists:get_value(data_dir, Config), "port_test").
-ports(doc) -> "Test that erlang:ports/0 returns a consistent snapshot of ports";
-ports(suite) -> [];
+%% Test that erlang:ports/0 returns a consistent snapshot of ports
ports(Config) when is_list(Config) ->
- Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
ok = load_driver(Path, "exit_drv"),
receive after 1000 -> ok end, % Wait for other ports to stabilize
@@ -2233,7 +2200,7 @@ ports_snapshots(Iter, TrafficPid, OtherPorts) ->
TrafficPid ! {self(), stop},
receive {TrafficPid, EventList, TrafficPorts} -> ok end,
-
+
%%io:format("Snapshot=~p\n", [Snapshot]),
ports_verify(Snapshot, OtherPorts ++ TrafficPorts, EventList),
@@ -2245,78 +2212,77 @@ ports_traffic(MaxPorts) ->
ports_traffic_stopped(MaxPorts, {PortList, PortCnt}) ->
receive
- start ->
- %%io:format("Traffic started in ~p\n",[self()]),
- ports_traffic_started(MaxPorts, {PortList, PortCnt}, []);
- {Pid,die} ->
- lists:foreach(fun(Port)-> erlang:port_close(Port) end,
- PortList),
- Pid ! {self(),dead}
+ start ->
+ %%io:format("Traffic started in ~p\n",[self()]),
+ ports_traffic_started(MaxPorts, {PortList, PortCnt}, []);
+ {Pid,die} ->
+ lists:foreach(fun(Port)-> erlang:port_close(Port) end,
+ PortList),
+ Pid ! {self(),dead}
end.
ports_traffic_started(MaxPorts, {PortList, PortCnt}, EventList) ->
receive
- {Pid, stop} ->
- %%io:format("Traffic stopped in ~p\n",[self()]),
- Pid ! {self(), EventList, PortList},
- ports_traffic_stopped(MaxPorts, {PortList, PortCnt})
+ {Pid, stop} ->
+ %%io:format("Traffic stopped in ~p\n",[self()]),
+ Pid ! {self(), EventList, PortList},
+ ports_traffic_stopped(MaxPorts, {PortList, PortCnt})
after 0 ->
- ports_traffic_do(MaxPorts, {PortList, PortCnt}, EventList)
+ ports_traffic_do(MaxPorts, {PortList, PortCnt}, EventList)
end.
ports_traffic_do(MaxPorts, {PortList, PortCnt}, EventList) ->
N = uniform(MaxPorts),
case N > PortCnt of
- true -> % Open port
- P = open_port({spawn, "exit_drv"}, []),
- %%io:format("Created port ~p\n",[P]),
- ports_traffic_started(MaxPorts, {[P|PortList], PortCnt+1},
- [{open,P}|EventList]);
-
- false -> % Close port
- P = lists:nth(N, PortList),
- %%io:format("Close port ~p\n",[P]),
- true = erlang:port_close(P),
- ports_traffic_started(MaxPorts, {lists:delete(P,PortList), PortCnt-1},
- [{close,P}|EventList])
+ true -> % Open port
+ P = open_port({spawn, "exit_drv"}, []),
+ %%io:format("Created port ~p\n",[P]),
+ ports_traffic_started(MaxPorts, {[P|PortList], PortCnt+1},
+ [{open,P}|EventList]);
+
+ false -> % Close port
+ P = lists:nth(N, PortList),
+ %%io:format("Close port ~p\n",[P]),
+ true = erlang:port_close(P),
+ ports_traffic_started(MaxPorts, {lists:delete(P,PortList), PortCnt-1},
+ [{close,P}|EventList])
end.
ports_verify(Ports, PortsAfter, EventList) ->
%%io:format("Candidate=~p\nEvents=~p\n", [PortsAfter, EventList]),
case lists:sort(Ports) =:= lists:sort(PortsAfter) of
- true ->
- io:format("Snapshot of ~p ports verified ok.\n",[length(Ports)]),
- ok;
- false ->
- %% Note that we track the event list "backwards", undoing open/close:
- case EventList of
- [{open,P} | Tail] ->
- ports_verify(Ports, lists:delete(P,PortsAfter), Tail);
-
- [{close,P} | Tail] ->
- ports_verify(Ports, [P | PortsAfter], Tail);
-
- [] ->
- test_server:fail("Inconsistent snapshot from erlang:ports()")
- end
+ true ->
+ io:format("Snapshot of ~p ports verified ok.\n",[length(Ports)]),
+ ok;
+ false ->
+ %% Note that we track the event list "backwards", undoing open/close:
+ case EventList of
+ [{open,P} | Tail] ->
+ ports_verify(Ports, lists:delete(P,PortsAfter), Tail);
+
+ [{close,P} | Tail] ->
+ ports_verify(Ports, [P | PortsAfter], Tail);
+
+ [] ->
+ ct:fail("Inconsistent snapshot from erlang:ports()")
+ end
end.
load_driver(Dir, Driver) ->
case erl_ddll:load_driver(Dir, Driver) of
- ok -> ok;
- {error, Error} = Res ->
- io:format("~s\n", [erl_ddll:format_error(Error)]),
- Res
+ ok -> ok;
+ {error, Error} = Res ->
+ io:format("~s\n", [erl_ddll:format_error(Error)]),
+ Res
end.
-close_deaf_port(doc) -> ["Send data to port program that does not read it, then close port."
- "Primary targeting Windows to test threaded_handle_closer in sys.c"];
-close_deaf_port(suite) -> [];
+%% Send data to port program that does not read it, then close port.
+%% Primary targeting Windows to test threaded_handle_closer in sys.c
close_deaf_port(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(100)),
- DataDir = ?config(data_dir, Config),
+ ct:timetrap({minutes, 2}),
+ DataDir = proplists:get_value(data_dir, Config),
DeadPort = os:find_executable("dead_port", DataDir),
Port = open_port({spawn,DeadPort++" 60"},[]),
erlang:port_command(Port,"Hello, can you hear me!?!?"),
@@ -2325,83 +2291,82 @@ close_deaf_port(Config) when is_list(Config) ->
Res = close_deaf_port_1(0, DeadPort),
io:format("Waiting for OS procs to terminate...\n"),
receive after 5*1000 -> ok end,
- test_server:timetrap_cancel(Dog),
Res.
close_deaf_port_1(200, _) ->
ok;
close_deaf_port_1(N, Cmd) ->
- Timeout = integer_to_list(random:uniform(5*1000)),
+ Timeout = integer_to_list(rand:uniform(5*1000)),
try open_port({spawn_executable,Cmd},[{args,[Timeout]}]) of
- Port ->
- erlang:port_command(Port,"Hello, can you hear me!?!?"),
- port_close(Port),
- close_deaf_port_1(N+1, Cmd)
+ Port ->
+ erlang:port_command(Port,"Hello, can you hear me!?!?"),
+ port_close(Port),
+ close_deaf_port_1(N+1, Cmd)
catch
- _:eagain ->
- {comment, "Could not spawn more than " ++ integer_to_list(N) ++ " OS processes."}
+ _:eagain ->
+ {comment, "Could not spawn more than " ++ integer_to_list(N) ++ " OS processes."}
end.
%% Test undocumented port_set_data/2 and port_get_data/1
%% Hammer from multiple processes a while
%% and then abrubtly close the port (OTP-12208).
port_setget_data(Config) when is_list(Config) ->
- ok = load_driver(?config(data_dir, Config), "echo_drv"),
+ ok = load_driver(proplists:get_value(data_dir, Config), "echo_drv"),
Port = erlang:open_port({spawn_driver, "echo_drv"}, []),
NSched = erlang:system_info(schedulers_online),
HeapData = {1,2,3,<<"A heap binary">>,fun()->"This is fun"end,
- list_to_binary(lists:seq(1,100))},
+ list_to_binary(lists:seq(1,100))},
PRs = lists:map(fun(I) ->
- spawn_opt(fun() -> port_setget_data_hammer(Port,HeapData,false,1) end,
- [monitor, {scheduler, I rem NSched}])
- end,
- lists:seq(1,10)),
+ spawn_opt(fun() -> port_setget_data_hammer(Port,HeapData,false,1) end,
+ [monitor, {scheduler, I rem NSched}])
+ end,
+ lists:seq(1,10)),
receive after 100 -> ok end,
Papa = self(),
lists:foreach(fun({Pid,_}) -> Pid ! {Papa,prepare_for_close} end, PRs),
lists:foreach(fun({Pid,_}) ->
- receive {Pid,prepare_for_close} -> ok end
- end,
- PRs),
+ receive {Pid,prepare_for_close} -> ok end
+ end,
+ PRs),
port_close(Port),
lists:foreach(fun({Pid,Ref}) ->
- receive {'DOWN', Ref, process, Pid, normal} -> ok end
- end,
- PRs),
+ receive {'DOWN', Ref, process, Pid, normal} -> ok end
+ end,
+ PRs),
ok.
port_setget_data_hammer(Port, HeapData, IsSet0, N) ->
- Rand = random:uniform(3),
+ Rand = rand:uniform(3),
IsSet1 = try case Rand of
- 1 -> true = erlang:port_set_data(Port, atom), true;
- 2 -> true = erlang:port_set_data(Port, HeapData), true;
- 3 -> case erlang:port_get_data(Port) of
- atom -> true;
- HeapData -> true;
- undefined -> false=IsSet0
- end
- end
- catch
- error:badarg ->
- true = get(prepare_for_close),
- io:format("~p did ~p rounds before port closed\n", [self(), N]),
- exit(normal)
- end,
+ 1 -> true = erlang:port_set_data(Port, atom), true;
+ 2 -> true = erlang:port_set_data(Port, HeapData), true;
+ 3 -> case erlang:port_get_data(Port) of
+ atom -> true;
+ HeapData -> true;
+ undefined -> false=IsSet0
+ end
+ end
+ catch
+ error:badarg ->
+ true = get(prepare_for_close),
+ io:format("~p did ~p rounds before port closed\n", [self(), N]),
+ exit(normal)
+ end,
receive {Papa, prepare_for_close} ->
- put(prepare_for_close, true),
- Papa ! {self(),prepare_for_close}
+ put(prepare_for_close, true),
+ Papa ! {self(),prepare_for_close}
after 0 ->
- ok
+ ok
end,
port_setget_data_hammer(Port, HeapData, IsSet1, N+1).
wait_until(Fun) ->
case catch Fun() of
- true ->
- ok;
- _ ->
- receive after 100 -> ok end,
- wait_until(Fun)
+ true ->
+ ok;
+ _ ->
+ receive after 100 -> ok end,
+ wait_until(Fun)
end.
diff --git a/erts/emulator/test/port_SUITE_data/port_test.c b/erts/emulator/test/port_SUITE_data/port_test.c
index 7abefab2e3..cc3ebdf0f8 100644
--- a/erts/emulator/test/port_SUITE_data/port_test.c
+++ b/erts/emulator/test/port_SUITE_data/port_test.c
@@ -13,6 +13,7 @@
#ifndef __WIN32__
#include <unistd.h>
+#include <limits.h>
#include <sys/time.h>
@@ -48,6 +49,7 @@ typedef struct {
* after reading the header for a packet
* before reading the rest.
*/
+ int fd_count; /* Count the number of open fds */
int break_mode; /* If set, this program will close standard
* input, which should case broken pipe
* error in the writer.
@@ -107,7 +109,7 @@ MAIN(argc, argv)
int argc;
char *argv[];
{
- int ret;
+ int ret, fd_count;
if((port_data = (PORT_TEST_DATA *) malloc(sizeof(PORT_TEST_DATA))) == NULL) {
fprintf(stderr, "Couldn't malloc for port_data");
exit(1);
@@ -115,6 +117,7 @@ char *argv[];
port_data->header_size = 0;
port_data->io_buf_size = 0;
port_data->delay_mode = 0;
+ port_data->fd_count = 0;
port_data->break_mode = 0;
port_data->quit_mode = 0;
port_data->slow_writes = 0;
@@ -144,6 +147,9 @@ char *argv[];
case 'e':
port_data->fd_to_erl = 2;
break;
+ case 'f':
+ port_data->fd_count = 1;
+ break;
case 'h': /* Header size for packets. */
switch (argv[1][2]) {
case '0': port_data->header_size = 0; break;
@@ -189,18 +195,31 @@ char *argv[];
/* XXX Add error printout here */
}
+ if (port_data->fd_count) {
+#ifdef __WIN32__
+ DWORD handles;
+ GetProcessHandleCount(GetCurrentProcess(), &handles);
+ fd_count = handles;
+#else
+ int i;
+ for (i = 0, fd_count = 0; i < 1024; i++)
+ if (fcntl(i, F_GETFD) >= 0) {
+ fd_count++;
+ }
+#endif
+ }
+
+ if (port_data->output_file)
+ replace_stdout(port_data->output_file);
+
+ if (port_data->fd_count)
+ reply(&fd_count, sizeof(fd_count));
+
if (port_data->no_packet_loop){
free(port_data);
exit(0);
}
- /*
- * If an output file was given, let it replace standard output.
- */
-
- if (port_data->output_file)
- replace_stdout(port_data->output_file);
-
ret = packet_loop();
if(port_data->io_buf_size > 0)
free(port_data->io_buf);
diff --git a/erts/emulator/test/port_bif_SUITE.erl b/erts/emulator/test/port_bif_SUITE.erl
index b65a22a528..9b794be415 100644
--- a/erts/emulator/test/port_bif_SUITE.erl
+++ b/erts/emulator/test/port_bif_SUITE.erl
@@ -21,8 +21,8 @@
-module(port_bif_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2, command/1,
+-export([all/0, suite/0, groups/0,
+ command/1,
command_e_1/1, command_e_2/1, command_e_3/1, command_e_4/1,
port_info1/1, port_info2/1,
port_info_os_pid/1, port_info_race/1,
@@ -30,11 +30,11 @@
-export([do_command_e_1/1, do_command_e_2/1, do_command_e_4/1]).
--export([init_per_testcase/2, end_per_testcase/2]).
+-include_lib("common_test/include/ct.hrl").
--include_lib("test_server/include/test_server.hrl").
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 10}}].
all() ->
[command, {group, port_info}, connect, control,
@@ -46,27 +46,6 @@ groups() ->
{port_info, [],
[port_info1, port_info2, port_info_os_pid, port_info_race]}].
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-
-init_per_testcase(_Func, Config) when is_list(Config) ->
- Dog=test_server:timetrap(test_server:minutes(10)),
- [{watchdog, Dog}|Config].
-end_per_testcase(_Func, Config) when is_list(Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog).
-
command(Config) when is_list(Config) ->
load_control_drv(Config),
@@ -87,17 +66,17 @@ do_command(P, Data) ->
{P,{data,Data0}} ->
case {list_to_binary(Data0),list_to_binary([Data])} of
{B,B} -> ok;
- _ -> test_server:fail({unexpected_data,Data0})
+ _ -> ct:fail({unexpected_data,Data0})
end;
Other ->
- test_server:fail({unexpected_message,Other})
+ ct:fail({unexpected_message,Other})
end.
%% port_command/2: badarg 1st arg
command_e_1(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
Program = filename:join(DataDir, "port_test"),
process_flag(trap_exit, true),
@@ -106,9 +85,9 @@ command_e_1(Config) when is_list(Config) ->
{'EXIT', Pid, {badarg, _}} when is_pid(Pid) ->
ok;
Other ->
- test_server:fail(Other)
+ ct:fail(Other)
after 10000 ->
- test_server:fail(timeout)
+ ct:fail(timeout)
end,
ok.
@@ -119,7 +98,7 @@ do_command_e_1(Program) ->
%% port_command/2: badarg 2nd arg
command_e_2(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
Program = filename:join(DataDir, "port_test"),
process_flag(trap_exit, true),
@@ -128,9 +107,9 @@ command_e_2(Config) when is_list(Config) ->
{'EXIT', Pid, {badarg, _}} when is_pid(Pid) ->
ok;
Other ->
- test_server:fail(Other)
+ ct:fail(Other)
after 10000 ->
- test_server:fail(timeout)
+ ct:fail(timeout)
end,
ok.
@@ -141,7 +120,7 @@ do_command_e_2(Program) ->
%% port_command/2: Posix signals trapped
command_e_3(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
Program = filename:join(DataDir, "port_test"),
process_flag(trap_exit, true),
@@ -152,15 +131,15 @@ command_e_3(Config) when is_list(Config) ->
{'EXIT', Port, einval} when is_port(Port) ->
ok;
Other ->
- test_server:fail(Other)
+ ct:fail(Other)
after 10000 ->
- test_server:fail(timeout)
+ ct:fail(timeout)
end,
ok.
%% port_command/2: Posix exit signals not trapped
command_e_4(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
Program = filename:join(DataDir, "port_test"),
process_flag(trap_exit, true),
@@ -169,9 +148,9 @@ command_e_4(Config) when is_list(Config) ->
{'EXIT', Pid, {einval, _}} when is_pid(Pid) ->
ok;
Other ->
- test_server:fail(Other)
+ ct:fail(Other)
after 10000 ->
- test_server:fail(timeout)
+ ct:fail(timeout)
end,
ok.
@@ -248,7 +227,7 @@ do_port_info_os_pid() ->
{os_pid, InfoOSPid} = erlang:port_info(P, os_pid),
EchoPidStr = receive
{P, {data, EchoPidStr0}} -> EchoPidStr0
- after 10000 -> test_server:fail(timeout)
+ after 10000 -> ct:fail(timeout)
end,
{ok, [EchoPid], []} = io_lib:fread("~u\n", EchoPidStr),
{value,{os_pid, InfoOSPid}}=lists:keysearch(os_pid, 1, A),
@@ -257,7 +236,7 @@ do_port_info_os_pid() ->
ok.
port_info_race(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
Program = filename:join(DataDir, "port_test"),
Top = self(),
P1 = open_port({spawn,Program}, [{packet,1}]),
@@ -283,10 +262,9 @@ output_test(_, _, Input, Output) when Output > 16#1fffffff ->
output_test(P, Bin, Input0, Output0) ->
erlang:port_command(P, Bin),
receive
- {P,{data,Bin}} -> ok;
- Other ->
- io:format("~p", [Other]),
- ?t:fail()
+ {P,{data,Bin}} -> ok;
+ Other ->
+ ct:fail("~p", [Other])
end,
Input = Input0 + size(Bin),
Output = Output0 + size(Bin),
@@ -296,8 +274,8 @@ output_test(P, Bin, Input0, Output0) ->
%% We can't test much here, but hopefully a debug-built emulator will crasch
%% if there is something wrong with the heap allocation.
case erlang:statistics(io) of
- {{input,In},{output,Out}} when is_integer(In), is_integer(Out) ->
- ok
+ {{input,In},{output,Out}} when is_integer(In), is_integer(Out) ->
+ ok
end,
output_test(P, Bin, Input, Output).
@@ -345,7 +323,7 @@ connect(Config) when is_list(Config) ->
exit(P, you_should_die),
receive
{'EXIT',RecPid,you_should_die} -> ok;
- Other -> ?line ?t:fail({bad_message,Other})
+ Other -> ct:fail({bad_message,Other})
end,
%% Done.
@@ -410,7 +388,7 @@ test_op(P, Op) ->
<<Op:32>> = list_to_binary(R).
echo_to_busy(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
+ ct:timetrap({seconds, 10}),
load_control_drv(Config),
P = open_port({spawn, control_drv}, []),
erlang:port_control(P, $b, [1]), % Set to busy.
@@ -422,11 +400,10 @@ echo_to_busy(Config) when is_list(Config) ->
{Echoer, done} ->
ok;
{Echoer, Other} ->
- test_server:fail(Other);
+ ct:fail(Other);
Other ->
- test_server:fail({unexpected_message, Other})
+ ct:fail({unexpected_message, Other})
end,
- test_server:timetrap_cancel(Dog),
ok.
echoer(P, ReplyTo) ->
@@ -451,7 +428,7 @@ echo(P, Size) ->
Packet = erlang:port_control(P, $e, [unaligned_sub_bin(Bin)]).
load_control_drv(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
erl_ddll:start(),
ok = load_driver(DataDir, "control_drv").
@@ -485,14 +462,7 @@ random_char(Chars) ->
lists:nth(uniform(length(Chars)), Chars).
uniform(N) ->
- case get(random_seed) of
- undefined ->
- {X, Y, Z} = time(),
- random:seed(X, Y, Z);
- _ ->
- ok
- end,
- random:uniform(N).
+ rand:uniform(N).
unaligned_sub_bin(Bin0) ->
Bin1 = <<0:3,Bin0/binary,31:5>>,
diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl
index 97aa5e573e..5bb216ff79 100644
--- a/erts/emulator/test/process_SUITE.erl
+++ b/erts/emulator/test/process_SUITE.erl
@@ -26,7 +26,7 @@
%% process_info/1,2
%% register/2 (partially)
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(heap_binary_size, 64).
@@ -41,6 +41,7 @@
process_info_2_list/1, process_info_lock_reschedule/1,
process_info_lock_reschedule2/1,
process_info_lock_reschedule3/1,
+ process_info_garbage_collection/1,
bump_reductions/1, low_prio/1, binary_owner/1, yield/1, yield2/1,
process_status_exiting/1,
otp_4725/1, bad_register/1, garbage_collect/1, otp_6237/1,
@@ -66,7 +67,9 @@
-export([hangaround/2, processes_bif_test/0, do_processes/1,
processes_term_proc_list_test/1]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 9}}].
all() ->
[spawn_with_binaries, t_exit_1, {group, t_exit_2},
@@ -75,7 +78,9 @@ all() ->
process_info_other_dist_msg, process_info_2_list,
process_info_lock_reschedule,
process_info_lock_reschedule2,
- process_info_lock_reschedule3, process_status_exiting,
+ process_info_lock_reschedule3,
+ process_info_garbage_collection,
+ process_status_exiting,
bump_reductions, low_prio, yield, yield2, otp_4725,
bad_register, garbage_collect, process_info_messages,
process_flag_badarg, process_flag_heap_size,
@@ -113,7 +118,7 @@ init_per_suite(Config) ->
[{started_apps, A}|Config].
end_per_suite(Config) ->
- As = ?config(started_apps, Config),
+ As = proplists:get_value(started_apps, Config),
lists:foreach(fun (A) -> application:stop(A) end, As),
catch erts_debug:set_internal_state(available_internal_state, false),
Config.
@@ -125,12 +130,10 @@ end_per_group(_GroupName, Config) ->
Config.
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?t:timetrap(?t:minutes(10)),
- [{watchdog, Dog},{testcase, Func}|Config].
+ [{testcase, Func}|Config].
end_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
+ ok.
fun_spawn(Fun) ->
spawn_link(erlang, apply, [Fun, []]).
@@ -155,11 +158,10 @@ binary_owner(Bin) when is_binary(Bin) ->
%% Tests exit/1 with a big message.
t_exit_1(Config) when is_list(Config) ->
+ ct:timetrap({seconds, 20}),
start_spawner(),
- Dog = test_server:timetrap(test_server:seconds(20)),
process_flag(trap_exit, true),
test_server:do_times(10, fun t_exit_1/0),
- test_server:timetrap_cancel(Dog),
stop_spawner(),
ok.
@@ -173,11 +175,10 @@ t_exit_1() ->
%% Tests exit/2 with a lot of data in the exit message.
t_exit_2_other(Config) when is_list(Config) ->
+ ct:timetrap({seconds, 20}),
start_spawner(),
- Dog = test_server:timetrap(test_server:seconds(20)),
process_flag(trap_exit, true),
test_server:do_times(10, fun t_exit_2_other/0),
- test_server:timetrap_cancel(Dog),
stop_spawner(),
ok.
@@ -191,34 +192,32 @@ t_exit_2_other() ->
%% Tests that exit(Pid, normal) does not kill another process.;
t_exit_2_other_normal(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(20)),
+ ct:timetrap({seconds, 20}),
process_flag(trap_exit, true),
Pid = fun_spawn(fun() -> receive x -> ok end end),
exit(Pid, normal),
receive
{'EXIT', Pid, Reason} ->
- test_server:fail({process_died, Reason})
+ ct:fail({process_died, Reason})
after 1000 ->
ok
end,
case process_info(Pid) of
undefined ->
- test_server:fail(process_died_on_normal);
+ ct:fail(process_died_on_normal);
List when is_list(List) ->
ok
end,
exit(Pid, kill),
- test_server:timetrap_cancel(Dog),
ok.
%% Tests that we can trap an exit message sent with exit/2 from
%% the same process.
self_exit(Config) when is_list(Config) ->
+ ct:timetrap({seconds, 10}),
start_spawner(),
- Dog = test_server:timetrap(test_server:seconds(10)),
process_flag(trap_exit, true),
test_server:do_times(200, fun self_exit/0),
- test_server:timetrap_cancel(Dog),
stop_spawner(),
ok.
@@ -237,7 +236,7 @@ normal_suicide_exit(Config) when is_list(Config) ->
Pid = fun_spawn(fun() -> exit(self(), normal) end),
receive
{'EXIT', Pid, normal} -> ok;
- Other -> test_server:fail({bad_message, Other})
+ Other -> ct:fail({bad_message, Other})
end.
%% Tests exit(self(), Term) is equivalent to exit(Term) for a process
@@ -248,7 +247,7 @@ abnormal_suicide_exit(Config) when is_list(Config) ->
Pid = fun_spawn(fun() -> exit(self(), Garbage) end),
receive
{'EXIT', Pid, Garbage} -> ok;
- Other -> test_server:fail({bad_message, Other})
+ Other -> ct:fail({bad_message, Other})
end.
%% Tests that exit(self(), die) cannot be catched.
@@ -257,21 +256,20 @@ t_exit_2_catch(Config) when is_list(Config) ->
Pid = fun_spawn(fun() -> catch exit(self(), die) end),
receive
{'EXIT', Pid, normal} ->
- test_server:fail(catch_worked);
+ ct:fail(catch_worked);
{'EXIT', Pid, die} ->
ok;
Other ->
- test_server:fail({bad_message, Other})
+ ct:fail({bad_message, Other})
end.
%% Tests trapping of an 'EXIT' message generated by a bad argument to
%% the abs/1 bif. The 'EXIT' message will intentionally be very big.
trap_exit_badarg(Config) when is_list(Config) ->
+ ct:timetrap({seconds, 10}),
start_spawner(),
- Dog = test_server:timetrap(test_server:seconds(10)),
process_flag(trap_exit, true),
test_server:do_times(10, fun trap_exit_badarg/0),
- test_server:timetrap_cancel(Dog),
stop_spawner(),
ok.
@@ -285,7 +283,7 @@ trap_exit_badarg() ->
ok;
Other ->
ok = io:format("Bad EXIT message: ~P", [Other, 30]),
- test_server:fail(bad_exit_message)
+ ct:fail(bad_exit_message)
end.
bad_guy(Arg) ->
@@ -317,10 +315,9 @@ big_binary(N, Acc) ->
%% Test receiving an EXIT message when spawning a BIF with bad arguments.
trap_exit_badarg_in_bif(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
+ ct:timetrap({seconds, 10}),
process_flag(trap_exit, true),
test_server:do_times(10, fun trap_exit_badarg_bif/0),
- test_server:timetrap_cancel(Dog),
ok.
trap_exit_badarg_bif() ->
@@ -329,7 +326,7 @@ trap_exit_badarg_bif() ->
{'EXIT', Pid, {badarg, _}} ->
ok;
Other ->
- test_server:fail({unexpected, Other})
+ ct:fail({unexpected, Other})
end.
%% The following sequences of events have crasched Beam.
@@ -342,15 +339,13 @@ trap_exit_badarg_bif() ->
%% 3) The process will crash the next time it executes 'receive'.
exit_and_timeout(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(20)),
+ ct:timetrap({seconds, 20}),
process_flag(trap_exit, true),
Parent = self(),
Low = fun_spawn(fun() -> eat_low(Parent) end),
High = fun_spawn(fun() -> eat_high(Low) end),
eat_wait_for(Low, High),
-
- test_server:timetrap_cancel(Dog),
ok.
@@ -361,7 +356,7 @@ eat_wait_for(Low, High) ->
{'EXIT', High, normal} ->
eat_wait_for(Low, High);
Other ->
- test_server:fail({bad_message, Other})
+ ct:fail({bad_message, Other})
end.
eat_low(_Parent) ->
@@ -394,14 +389,12 @@ loop(StopTime) ->
%% Tries to send two different exit messages to a process.
%% (The second one should be ignored.)
exit_twice(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(20)),
+ ct:timetrap({seconds, 20}),
process_flag(trap_exit, true),
Low = fun_spawn(fun etwice_low/0),
High = fun_spawn(fun() -> etwice_high(Low) end),
etwice_wait_for(Low, High),
-
- test_server:timetrap_cancel(Dog),
ok.
etwice_wait_for(Low, High) ->
@@ -409,11 +402,11 @@ etwice_wait_for(Low, High) ->
{'EXIT', Low, first} ->
ok;
{'EXIT', Low, Other} ->
- test_server:fail({wrong_exit_reason, Other});
+ ct:fail({wrong_exit_reason, Other});
{'EXIT', High, normal} ->
etwice_wait_for(Low, High);
Other ->
- test_server:fail({bad_message, Other})
+ ct:fail({bad_message, Other})
end.
etwice_low() ->
@@ -666,10 +659,6 @@ chk_pi_order([],[]) ->
chk_pi_order([{Arg, _}| Values], [Arg|Args]) ->
chk_pi_order(Values, Args).
-process_info_2_list(doc) ->
- [];
-process_info_2_list(suite) ->
- [];
process_info_2_list(Config) when is_list(Config) ->
Proc = spawn(fun () -> receive after infinity -> ok end end),
register(process_SUITE_process_info_2_list1, self()),
@@ -702,10 +691,6 @@ process_info_2_list(Config) when is_list(Config) ->
lists:foreach(fun ({backtrace, _}) -> ok end, V3),
ok.
-process_info_lock_reschedule(doc) ->
- [];
-process_info_lock_reschedule(suite) ->
- [];
process_info_lock_reschedule(Config) when is_list(Config) ->
%% We need a process that is running and an item that requires
%% process_info to take the main process lock.
@@ -738,7 +723,7 @@ process_info_lock_reschedule(Config) when is_list(Config) ->
exit(Target2, bang),
OkStatus;
{status, BadStatus} ->
- ?t:fail(BadStatus)
+ ct:fail(BadStatus)
end.
pi_loop(_Name, _Pid, 0) ->
@@ -747,10 +732,6 @@ pi_loop(Name, Pid, N) ->
{registered_name, Name} = process_info(Pid, registered_name),
pi_loop(Name, Pid, N-1).
-process_info_lock_reschedule2(doc) ->
- [];
-process_info_lock_reschedule2(suite) ->
- [];
process_info_lock_reschedule2(Config) when is_list(Config) ->
Parent = self(),
Fun = fun () ->
@@ -806,10 +787,6 @@ do_pi_msg_len(PT, AT) ->
lists:map(fun (_) -> ok end, [a,b,c,d]),
{message_queue_len, _} = process_info(element(2,PT), element(2,AT)).
-process_info_lock_reschedule3(doc) ->
- [];
-process_info_lock_reschedule3(suite) ->
- [];
process_info_lock_reschedule3(Config) when is_list(Config) ->
%% We need a process that is running and an item that requires
%% process_info to take the main process lock.
@@ -840,7 +817,7 @@ process_info_lock_reschedule3(Config) when is_list(Config) ->
exit(Target2, bang),
OkStatus;
{status, BadStatus} ->
- ?t:fail(BadStatus)
+ ct:fail(BadStatus)
end.
process_status_exiting(Config) when is_list(Config) ->
@@ -932,6 +909,48 @@ start_spawner() ->
stop_spawner() ->
ok.
+%% Tests erlang:process_info(Pid, garbage_collection_info)
+process_info_garbage_collection(_Config) ->
+ Parent = self(),
+ Pid = spawn_link(
+ fun() ->
+ receive go -> ok end,
+ (fun F(0) ->
+ Parent ! deep,
+ receive ok -> ok end,
+ [];
+ F(N) ->
+ timer:sleep(1),
+ [lists:seq(1,100) | F(N-1)]
+ end)(1000),
+ Parent ! shallow,
+ receive done -> ok end
+ end),
+ {garbage_collection_info, Before} =
+ erlang:process_info(Pid, garbage_collection_info),
+ Pid ! go, receive deep -> ok end,
+ {_, Deep} = erlang:process_info(Pid, garbage_collection_info),
+ Pid ! ok, receive shallow -> ok end,
+ {_, After} = erlang:process_info(Pid, garbage_collection_info),
+ Pid ! done,
+
+ %% Do some general checks to see if everything seems to be roughly correct
+ ct:log("Before: ~p",[Before]),
+ ct:log("Deep: ~p",[Deep]),
+ ct:log("After: ~p",[After]),
+
+ %% Check stack_size
+ true = proplists:get_value(stack_size, Before) < proplists:get_value(stack_size, Deep),
+ true = proplists:get_value(stack_size, After) < proplists:get_value(stack_size, Deep),
+
+ %% Check used heap size
+ true = proplists:get_value(heap_size, Before) + proplists:get_value(old_heap_size, Before)
+ < proplists:get_value(heap_size, Deep) + proplists:get_value(old_heap_size, Deep),
+ true = proplists:get_value(heap_size, Before) + proplists:get_value(old_heap_size, Before)
+ < proplists:get_value(heap_size, After) + proplists:get_value(old_heap_size, After),
+
+ ok.
+
%% Tests erlang:bump_reductions/1.
bump_reductions(Config) when is_list(Config) ->
erlang:garbage_collect(),
@@ -942,10 +961,10 @@ bump_reductions(Config) when is_list(Config) ->
case R2-R1 of
Diff when Diff < 100 ->
ok = io:format("R1 = ~w, R2 = ~w", [R1, R2]),
- test_server:fail({small_diff, Diff});
+ ct:fail({small_diff, Diff});
Diff when Diff > 110 ->
ok = io:format("R1 = ~w, R2 = ~w", [R1, R2]),
- test_server:fail({big_diff, Diff});
+ ct:fail({big_diff, Diff});
Diff ->
io:format("~p\n", [Diff]),
ok
@@ -1032,8 +1051,7 @@ make_unaligned_sub_binary(Bin0) ->
<<0:3,Bin:Sz/binary,31:5>> = id(Bin1),
Bin.
-yield(doc) ->
- "Tests erlang:yield/1.";
+%% Tests erlang:yield/1
yield(Config) when is_list(Config) ->
case catch erlang:system_info(modified_timing_level) of
Level when is_integer(Level) ->
@@ -1074,7 +1092,7 @@ yield_test() ->
{Diff, _} ->
ok = io:format("R1 = ~w, R2 = ~w, Schedcnt = ~w",
[R1, R2, Schedcnt]),
- test_server:fail({measurement_error, Diff, Schedcnt})
+ ct:fail({measurement_error, Diff, Schedcnt})
end.
call_yield() ->
@@ -1111,8 +1129,6 @@ schedcnt(stop, {Ref, Pid}) when is_reference(Ref), is_pid(Pid) ->
Cnt
end.
-yield2(doc) -> [];
-yield2(suite) -> [];
yield2(Config) when is_list(Config) ->
Me = self(),
Go = make_ref(),
@@ -1163,7 +1179,7 @@ yield2(Config) when is_list(Config) ->
io:format("Reductions = ~p~n", [Reductions]),
ok;
{RedDiff, Reductions} ->
- ?t:fail({unexpected_reduction_count, Reductions})
+ ct:fail({unexpected_reduction_count, Reductions})
end,
none = next_tmsg(P),
@@ -1204,8 +1220,6 @@ fail_register(Name, Process) ->
{'EXIT',{badarg,_}} = (catch Name ! anything_goes),
ok.
-garbage_collect(doc) -> [];
-garbage_collect(suite) -> [];
garbage_collect(Config) when is_list(Config) ->
Prio = process_flag(priority, high),
true = erlang:garbage_collect(),
@@ -1244,10 +1258,7 @@ garbage_collect(Config) when is_list(Config) ->
process_flag(priority, Prio),
ok.
-process_info_messages(doc) ->
- ["This used to cause the nofrag emulator to dump core"];
-process_info_messages(suite) ->
- [];
+%% This used to cause the nofrag emulator to dump core
process_info_messages(Config) when is_list(Config) ->
process_info_messages_test(),
ok.
@@ -1305,10 +1316,6 @@ process_info_messages_test() ->
chk_badarg(Fun) ->
try Fun(), exit(no_badarg) catch error:badarg -> ok end.
-process_flag_badarg(doc) ->
- [];
-process_flag_badarg(suite) ->
- [];
process_flag_badarg(Config) when is_list(Config) ->
chk_badarg(fun () -> process_flag(gurka, banan) end),
chk_badarg(fun () -> process_flag(trap_exit, gurka) end),
@@ -1326,8 +1333,6 @@ process_flag_badarg(Config) when is_list(Config) ->
-include_lib("stdlib/include/ms_transform.hrl").
-otp_6237(doc) -> [];
-otp_6237(suite) -> [];
otp_6237(Config) when is_list(Config) ->
Slctrs = lists:map(fun (_) ->
spawn_link(fun () ->
@@ -1394,10 +1399,6 @@ otp_6237_select_loop() ->
conses_per_red,
debug_level}).
-processes_large_tab(doc) ->
- [];
-processes_large_tab(suite) ->
- [];
processes_large_tab(Config) when is_list(Config) ->
sys_mem_cond_run(2048, fun () -> processes_large_tab_test(Config) end).
@@ -1425,7 +1426,7 @@ processes_large_tab_test(Config) ->
#ptab_list_bif_info{debug_level = Lvl} when Lvl > MaxDbgLvl ->
20;
#ptab_list_bif_info{debug_level = Lvl} when Lvl < 0 ->
- ?t:fail({debug_level, Lvl});
+ ct:fail({debug_level, Lvl});
#ptab_list_bif_info{debug_level = Lvl} ->
Lvl
end,
@@ -1443,15 +1444,11 @@ processes_large_tab_test(Config) ->
[processes_bif_info]) of
#ptab_list_bif_info{tab_chunks = Chunks} when is_integer(Chunks),
Chunks > 1 -> ok;
- PBInfo -> ?t:fail(PBInfo)
+ PBInfo -> ct:fail(PBInfo)
end,
stop_node(LargeNode),
chk_processes_bif_test_res(Res).
-processes_default_tab(doc) ->
- [];
-processes_default_tab(suite) ->
- [];
processes_default_tab(Config) when is_list(Config) ->
sys_mem_cond_run(1024, fun () -> processes_default_tab_test(Config) end).
@@ -1461,10 +1458,6 @@ processes_default_tab_test(Config) ->
stop_node(DefaultNode),
chk_processes_bif_test_res(Res).
-processes_small_tab(doc) ->
- [];
-processes_small_tab(suite) ->
- [];
processes_small_tab(Config) when is_list(Config) ->
{ok, SmallNode} = start_node(Config, "+P 1024"),
Res = rpc:call(SmallNode, ?MODULE, processes_bif_test, []),
@@ -1473,10 +1466,6 @@ processes_small_tab(Config) when is_list(Config) ->
true = PBInfo#ptab_list_bif_info.tab_chunks < 10,
chk_processes_bif_test_res(Res).
-processes_this_tab(doc) ->
- [];
-processes_this_tab(suite) ->
- [];
processes_this_tab(Config) when is_list(Config) ->
Mem = case {erlang:system_info(build_type),
erlang:system_info(allocator)} of
@@ -1490,7 +1479,7 @@ processes_this_tab(Config) when is_list(Config) ->
chk_processes_bif_test_res(ok) -> ok;
chk_processes_bif_test_res({comment, _} = Comment) -> Comment;
-chk_processes_bif_test_res(Failure) -> ?t:fail(Failure).
+chk_processes_bif_test_res(Failure) -> ct:fail(Failure).
print_processes_bif_info(#ptab_list_bif_info{min_start_reds = MinStartReds,
tab_chunks = TabChunks,
@@ -1501,7 +1490,7 @@ print_processes_bif_info(#ptab_list_bif_info{min_start_reds = MinStartReds,
term_procs_max_reds = TPMaxReds,
conses_per_red = ConsesPerRed,
debug_level = DbgLvl}) ->
- ?t:format("processes/0 bif info on node ~p:~n"
+ io:format("processes/0 bif info on node ~p:~n"
"Min start reductions = ~p~n"
"Process table chunks = ~p~n"
"Process table chunks size = ~p~n"
@@ -1542,7 +1531,7 @@ processes_unexpected_result(CorrectProcs, Procs) ->
status,
priority],
MissingProcs = CorrectProcs -- Procs,
- ?t:format("Missing processes: ~p",
+ io:format("Missing processes: ~p",
[lists:map(fun (Pid) ->
[{pid, Pid}
| case process_info(Pid, ProcInfo) of
@@ -1552,7 +1541,7 @@ processes_unexpected_result(CorrectProcs, Procs) ->
end,
MissingProcs)]),
SuperfluousProcs = Procs -- CorrectProcs,
- ?t:format("Superfluous processes: ~p",
+ io:format("Superfluous processes: ~p",
[lists:map(fun (Pid) ->
[{pid, Pid}
| case process_info(Pid, ProcInfo) of
@@ -1561,7 +1550,7 @@ processes_unexpected_result(CorrectProcs, Procs) ->
end]
end,
SuperfluousProcs)]),
- ?t:fail(unexpected_result).
+ ct:fail(unexpected_result).
hangaround(Cleaner, Type) ->
%% Type is only used to distinguish different processes from
@@ -1666,7 +1655,7 @@ do_processes_bif_test(WantReds, DieTest, Processes) ->
DoIt = make_ref(),
GetGoing = make_ref(),
{NoTestProcs, TestProcs} = spawn_initial_hangarounds(Cleaner),
- ?t:format("Testing with ~p processes~n", [NoTestProcs]),
+ io:format("Testing with ~p processes~n", [NoTestProcs]),
SpawnHangAround = fun () ->
spawn(?MODULE, hangaround, [Cleaner, new_hangaround])
end,
@@ -1708,7 +1697,7 @@ do_processes_bif_test(WantReds, DieTest, Processes) ->
Procs = lists:sort(Procs0),
CorrectProcs = lists:sort(CorrectProcs0),
LengthCorrectProcs = length(CorrectProcs),
- ?t:format("~p = length(CorrectProcs)~n", [LengthCorrectProcs]),
+ io:format("~p = length(CorrectProcs)~n", [LengthCorrectProcs]),
true = LengthCorrectProcs > NoTestProcs,
case CorrectProcs =:= Procs of
true ->
@@ -1729,12 +1718,12 @@ do_processes_bif_test(WantReds, DieTest, Processes) ->
do_processes_bif_die_test(false, _Processes) ->
- ?t:format("Skipping test killing process executing processes/0~n",[]),
+ io:format("Skipping test killing process executing processes/0~n",[]),
ok;
do_processes_bif_die_test(true, Processes) ->
do_processes_bif_die_test(5, Processes);
do_processes_bif_die_test(N, Processes) ->
- ?t:format("Doing test killing process executing processes/0~n",[]),
+ io:format("Doing test killing process executing processes/0~n",[]),
try
Tester = self(),
Oooh_Nooooooo = make_ref(),
@@ -1784,8 +1773,8 @@ do_processes_bif_die_test(N, Processes) ->
ok
catch
throw:{kill_in_trap, R} when N > 0 ->
- ?t:format("Failed to kill in trap: ~p~n", [R]),
- ?t:format("Trying again~n", []),
+ io:format("Failed to kill in trap: ~p~n", [R]),
+ io:format("Trying again~n", []),
do_processes_bif_die_test(N-1, Processes)
end.
@@ -1815,7 +1804,7 @@ wait_until_system_recover(Tmr) ->
receive
{timeout, Tmr, _} ->
Comment = "WARNING: Test processes still hanging around!",
- ?t:format("~s~n", [Comment]),
+ io:format("~s~n", [Comment]),
put(processes_bif_testcase_comment, Comment),
lists:foreach(
fun (P) when P == self() ->
@@ -1823,7 +1812,7 @@ wait_until_system_recover(Tmr) ->
(P) ->
case process_info(P, initial_call) of
{initial_call,{?MODULE, _, _} = MFA} ->
- ?t:format("~p ~p~n", [P, MFA]);
+ io:format("~p ~p~n", [P, MFA]);
{initial_call,{_, _, _}} ->
ok;
undefined ->
@@ -1839,10 +1828,6 @@ wait_until_system_recover(Tmr) ->
receive {timeout, Tmr, _} -> ok after 0 -> ok end,
ok.
-processes_last_call_trap(doc) ->
- [];
-processes_last_call_trap(suite) ->
- [];
processes_last_call_trap(Config) when is_list(Config) ->
enable_internal_state(),
Processes = fun () -> processes() end,
@@ -1865,10 +1850,6 @@ processes_last_call_trap(Config) when is_list(Config) ->
my_processes() ->
processes().
-processes_apply_trap(doc) ->
- [];
-processes_apply_trap(suite) ->
- [];
processes_apply_trap(Config) when is_list(Config) ->
enable_internal_state(),
PBInfo = erts_debug:get_internal_state(processes_bif_info),
@@ -1883,10 +1864,6 @@ processes_apply_trap(Config) when is_list(Config) ->
apply(erlang, processes, [])
end, lists:seq(1,100)).
-processes_gc_trap(doc) ->
- [];
-processes_gc_trap(suite) ->
- [];
processes_gc_trap(Config) when is_list(Config) ->
Tester = self(),
enable_internal_state(),
@@ -1925,10 +1902,6 @@ processes_gc_trap(Config) when is_list(Config) ->
exit(Suspendee, bang),
ok.
-process_flag_heap_size(doc) ->
- [];
-process_flag_heap_size(suite) ->
- [];
process_flag_heap_size(Config) when is_list(Config) ->
HSize = 2586, % must be gc fib+ number
VHSize = 318187, % must be gc fib+ number
@@ -1940,10 +1913,6 @@ process_flag_heap_size(Config) when is_list(Config) ->
VHSize = erlang:process_flag(min_bin_vheap_size, OldVHmin),
ok.
-spawn_opt_heap_size(doc) ->
- [];
-spawn_opt_heap_size(suite) ->
- [];
spawn_opt_heap_size(Config) when is_list(Config) ->
HSize = 987, % must be gc fib+ number
VHSize = 46422, % must be gc fib+ number
@@ -1954,10 +1923,6 @@ spawn_opt_heap_size(Config) when is_list(Config) ->
Pid ! stop,
ok.
-processes_term_proc_list(doc) ->
- [];
-processes_term_proc_list(suite) ->
- [];
processes_term_proc_list(Config) when is_list(Config) ->
Tester = self(),
as_expected = processes_term_proc_list_test(false),
@@ -2107,24 +2072,12 @@ processes_term_proc_list_test(MustChk) ->
as_expected.
-otp_7738_waiting(doc) ->
- [];
-otp_7738_waiting(suite) ->
- [];
otp_7738_waiting(Config) when is_list(Config) ->
otp_7738_test(waiting).
-otp_7738_suspended(doc) ->
- [];
-otp_7738_suspended(suite) ->
- [];
otp_7738_suspended(Config) when is_list(Config) ->
otp_7738_test(suspended).
-otp_7738_resume(doc) ->
- [];
-otp_7738_resume(suite) ->
- [];
otp_7738_resume(Config) when is_list(Config) ->
otp_7738_test(resume).
@@ -2193,8 +2146,8 @@ do_otp_7738_test(Type) ->
ok
after 2000 ->
I = process_info(R, [status, message_queue_len]),
- ?t:format("~p~n", [I]),
- ?t:fail(no_progress)
+ io:format("~p~n", [I]),
+ ct:fail(no_progress)
end,
ok.
@@ -2281,7 +2234,7 @@ no_priority_inversion2(Config) when is_list(Config) ->
RH = request_gc(PL, high),
receive
{garbage_collect, _, _} ->
- ?t:fail(unexpected_gc)
+ ct:fail(unexpected_gc)
after 1000 ->
ok
end,
@@ -2390,7 +2343,7 @@ gc_request_when_gc_disabled(Config) when is_list(Config) ->
async = garbage_collect(P, [{async, ReqId}]),
receive
{garbage_collect, ReqId, Result} ->
- ?t:fail({unexpected_gc, Result});
+ ct:fail({unexpected_gc, Result});
{P, gc_state, true} ->
ok
end,
@@ -2460,15 +2413,15 @@ start_node(Config, Args) when is_list(Config) ->
Pa = filename:dirname(code:which(?MODULE)),
Name = list_to_atom(atom_to_list(?MODULE)
++ "-"
- ++ atom_to_list(?config(testcase, Config))
+ ++ atom_to_list(proplists:get_value(testcase, Config))
++ "-"
++ integer_to_list(erlang:system_time(seconds))
++ "-"
++ integer_to_list(erlang:unique_integer([positive]))),
- ?t:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]).
+ test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]).
stop_node(Node) ->
- ?t:stop_node(Node).
+ test_server:stop_node(Node).
enable_internal_state() ->
case catch erts_debug:get_internal_state(available_internal_state) of
diff --git a/erts/emulator/test/random_iolist.erl b/erts/emulator/test/random_iolist.erl
index 9a0f034e72..6da7da04de 100644
--- a/erts/emulator/test/random_iolist.erl
+++ b/erts/emulator/test/random_iolist.erl
@@ -36,7 +36,7 @@ run2(Iter,Fun1,Fun2) ->
compare2(Iter,Fun1,Fun2).
random_byte() ->
- random:uniform(256) - 1.
+ rand:uniform(256) - 1.
random_list(0,Acc) ->
Acc;
@@ -45,7 +45,7 @@ random_list(N,Acc) ->
random_binary(N) ->
B = list_to_binary(random_list(N,[])),
- case {random:uniform(2),size(B)} of
+ case {rand:uniform(2),size(B)} of
{2,M} when M > 1 ->
S = M-1,
<<_:3,C:S/binary,_:5>> = B,
@@ -57,7 +57,7 @@ random_list(N) ->
random_list(N,[]).
front() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
10 ->
false;
_ ->
@@ -65,7 +65,7 @@ front() ->
end.
any_type() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
1 ->
list;
2 ->
@@ -77,7 +77,7 @@ any_type() ->
end.
tail_type() ->
- case random:uniform(5) of
+ case rand:uniform(5) of
1 ->
list;
2 ->
@@ -90,9 +90,9 @@ random_length(N) ->
UpperLimit = 255,
case N of
M when M > UpperLimit ->
- random:uniform(UpperLimit+1) - 1;
+ rand:uniform(UpperLimit+1) - 1;
_ ->
- random:uniform(N+1) - 1
+ rand:uniform(N+1) - 1
end.
random_iolist(0,Acc) ->
@@ -139,7 +139,7 @@ random_iolist(N) ->
standard_seed() ->
- random:seed(1201,855653,380975).
+ rand:seed(exsplus, {1201,855653,380975}).
do_comp(List,F1,F2) ->
X = F1(List),
diff --git a/erts/emulator/test/receive_SUITE.erl b/erts/emulator/test/receive_SUITE.erl
index ccae0df72e..6097e54219 100644
--- a/erts/emulator/test/receive_SUITE.erl
+++ b/erts/emulator/test/receive_SUITE.erl
@@ -22,15 +22,14 @@
%% Tests receive after.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
+-export([all/0, suite/0,
call_with_huge_message_queue/1,receive_in_between/1]).
--export([init_per_testcase/2,end_per_testcase/2]).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 3}}].
all() ->
[call_with_huge_message_queue, receive_in_between].
@@ -38,27 +37,6 @@ all() ->
groups() ->
[].
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?t:timetrap(?t:minutes(3)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
call_with_huge_message_queue(Config) when is_list(Config) ->
Pid = spawn_link(fun echo_loop/0),
@@ -77,8 +55,7 @@ call_with_huge_message_queue(Config) when is_list(Config) ->
Q when Q < 10 ->
ok;
Q ->
- io:format("Best Q = ~p", [Q]),
- ?t:fail()
+ ct:fail("Best Q = ~p", [Q])
end,
ok.
diff --git a/erts/emulator/test/ref_SUITE.erl b/erts/emulator/test/ref_SUITE.erl
index 1042c23d65..287a2ffb73 100644
--- a/erts/emulator/test/ref_SUITE.erl
+++ b/erts/emulator/test/ref_SUITE.erl
@@ -20,54 +20,29 @@
-module(ref_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2]).
+-export([all/0, suite/0]).
-export([wrap_1/1]).
-export([loop_ref/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-init_per_testcase(_, Config) ->
- ?line Dog=test_server:timetrap(test_server:minutes(2)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 2}}].
all() ->
[wrap_1].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-wrap_1(doc) -> "Check that refs don't wrap around easily.";
+%% Check that refs don't wrap around easily.
wrap_1(Config) when is_list(Config) ->
- ?line spawn_link(?MODULE, loop_ref, [self()]),
- ?line receive
- done ->
- test_server:fail(wrapfast)
- after 30000 ->
- ok
- end,
+ spawn_link(?MODULE, loop_ref, [self()]),
+ receive
+ done ->
+ ct:fail(wrapfast)
+ after 30000 ->
+ ok
+ end,
ok.
loop_ref(Parent) ->
diff --git a/erts/emulator/test/register_SUITE.erl b/erts/emulator/test/register_SUITE.erl
index 5ecca0f547..ad8a9c29f3 100644
--- a/erts/emulator/test/register_SUITE.erl
+++ b/erts/emulator/test/register_SUITE.erl
@@ -23,47 +23,20 @@
%-define(line_trace, 1).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%-compile(export_all).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2, end_per_testcase/2]).
+-export([all/0, suite/0]).
-export([otp_8099/1]).
--define(DEFAULT_TIMEOUT, ?t:minutes(2)).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 2}}].
all() ->
[otp_8099].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(Case, Config) when is_list(Config) ->
- Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, Dog}, {testcase, Case} | Config].
-
-end_per_testcase(_Case, Config) when is_list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
- ok.
-
%%
%% Test cases
%%
@@ -83,25 +56,20 @@ otp_8099(Config) when is_list(Config) ->
otp_8099_test(0) ->
ok;
otp_8099_test(N) ->
- ?line P = spawn(fun () -> otp_8099_proc() end),
- ?line case catch register(?OTP_8099_NAME, P) of
+ P = spawn(fun () -> otp_8099_proc() end),
+ case catch register(?OTP_8099_NAME, P) of
true ->
- ?line ok;
+ ok;
_ ->
- ?line OP = whereis(?OTP_8099_NAME),
- ?line (catch unregister(?OTP_8099_NAME)),
- ?line (catch exit(OP, kill)),
- ?line true = (catch register(?OTP_8099_NAME, P))
+ OP = whereis(?OTP_8099_NAME),
+ (catch unregister(?OTP_8099_NAME)),
+ (catch exit(OP, kill)),
+ true = (catch register(?OTP_8099_NAME, P))
end,
- ?line P = whereis(?OTP_8099_NAME),
- ?line exit(P, kill),
- ?line otp_8099_test(N-1).
+ P = whereis(?OTP_8099_NAME),
+ exit(P, kill),
+ otp_8099_test(N-1).
otp_8099_proc() ->
receive _ -> ok end,
otp_8099_proc().
-
-%%
-%% Utils
-%%
-
diff --git a/erts/emulator/test/save_calls_SUITE.erl b/erts/emulator/test/save_calls_SUITE.erl
index 544d841f16..bbdc2e6688 100644
--- a/erts/emulator/test/save_calls_SUITE.erl
+++ b/erts/emulator/test/save_calls_SUITE.erl
@@ -20,12 +20,9 @@
-module(save_calls_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,
- init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2]).
+-export([all/0, suite/0, init_per_testcase/2,end_per_testcase/2]).
-export([save_calls_1/1,dont_break_reductions/1]).
@@ -36,36 +33,21 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[save_calls_1, dont_break_reductions].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
init_per_testcase(dont_break_reductions,Config) ->
%% Skip on --enable-native-libs as hipe rescedules after each
%% function call.
case erlang:system_info(hipe_architecture) of
- undefined ->
- Config;
- Architecture ->
- {lists, ListsBinary, _ListsFilename} = code:get_object_code(lists),
- ChunkName = hipe_unified_loader:chunk_name(Architecture),
- NativeChunk = beam_lib:chunks(ListsBinary, [ChunkName]),
- case NativeChunk of
- {ok,{_,[{_,Bin}]}} when is_binary(Bin) ->
- {skip,"Does not work for --enable-native-libs"};
- {error, beam_lib, _} -> Config
- end
+ undefined ->
+ Config;
+ Architecture ->
+ {lists, ListsBinary, _ListsFilename} = code:get_object_code(lists),
+ ChunkName = hipe_unified_loader:chunk_name(Architecture),
+ NativeChunk = beam_lib:chunks(ListsBinary, [ChunkName]),
+ case NativeChunk of
+ {ok,{_,[{_,Bin}]}} when is_binary(Bin) ->
+ {skip,"Does not work for --enable-native-libs"};
+ {error, beam_lib, _} -> Config
+ end
end;
init_per_testcase(_,Config) ->
Config.
@@ -73,91 +55,88 @@ init_per_testcase(_,Config) ->
end_per_testcase(_,_Config) ->
ok.
-dont_break_reductions(suite) ->
- [];
-dont_break_reductions(doc) ->
- ["Check that save_calls dont break reduction-based scheduling"];
+%% Check that save_calls dont break reduction-based scheduling
dont_break_reductions(Config) when is_list(Config) ->
- ?line RPS1 = reds_per_sched(0),
- ?line RPS2 = reds_per_sched(20),
- ?line Diff = abs(RPS1 - RPS2),
- ?line true = (Diff < (0.05 * RPS1)),
+ RPS1 = reds_per_sched(0),
+ RPS2 = reds_per_sched(20),
+ Diff = abs(RPS1 - RPS2),
+ true = (Diff < (0.05 * RPS1)),
ok.
reds_per_sched(SaveCalls) ->
- ?line Parent = self(),
- ?line HowMany = 10000,
- ?line Pid = spawn(fun() ->
- process_flag(save_calls,SaveCalls),
- receive
- go ->
- carmichaels_below(HowMany),
- Parent ! erlang:process_info(self(),reductions)
- end
- end),
- ?line TH = spawn(fun() -> trace_handler(0,Parent,Pid) end),
- ?line erlang:trace(Pid, true,[running,procs,{tracer,TH}]),
- ?line Pid ! go,
- ?line {Sched,Reds} = receive
- {accumulated,X} ->
- receive {reductions,Y} ->
- {X,Y}
- after 30000 ->
- timeout
- end
- after 30000 ->
- timeout
- end,
- ?line Reds div Sched.
+ Parent = self(),
+ HowMany = 10000,
+ Pid = spawn(fun() ->
+ process_flag(save_calls,SaveCalls),
+ receive
+ go ->
+ carmichaels_below(HowMany),
+ Parent ! erlang:process_info(self(),reductions)
+ end
+ end),
+ TH = spawn(fun() -> trace_handler(0,Parent,Pid) end),
+ erlang:trace(Pid, true,[running,procs,{tracer,TH}]),
+ Pid ! go,
+ {Sched,Reds} = receive
+ {accumulated,X} ->
+ receive {reductions,Y} ->
+ {X,Y}
+ after 30000 ->
+ timeout
+ end
+ after 30000 ->
+ timeout
+ end,
+ Reds div Sched.
trace_handler(Acc,Parent,Client) ->
receive
- {trace,Client,out,_} ->
- trace_handler(Acc+1,Parent,Client);
- {trace,Client,exit,_} ->
- Parent ! {accumulated, Acc};
- _ ->
- trace_handler(Acc,Parent,Client)
+ {trace,Client,out,_} ->
+ trace_handler(Acc+1,Parent,Client);
+ {trace,Client,exit,_} ->
+ Parent ! {accumulated, Acc};
+ _ ->
+ trace_handler(Acc,Parent,Client)
after 10000 ->
- ok
+ ok
end.
-save_calls_1(doc) -> "Test call saving.";
+%% Test call saving.
save_calls_1(Config) when is_list(Config) ->
case test_server:is_native(?MODULE) of
- true -> {skipped,"Native code"};
- false -> save_calls_1()
+ true -> {skipped,"Native code"};
+ false -> save_calls_1()
end.
-
+
save_calls_1() ->
- ?line erlang:process_flag(self(), save_calls, 0),
- ?line {last_calls, false} = process_info(self(), last_calls),
-
- ?line erlang:process_flag(self(), save_calls, 10),
- ?line {last_calls, _L1} = process_info(self(), last_calls),
- ?line ?MODULE:do_bipp(),
- ?line {last_calls, L2} = process_info(self(), last_calls),
- ?line L21 = lists:filter(fun is_local_function/1, L2),
- ?line case L21 of
- [{?MODULE,do_bipp,0},
- timeout,
- 'send',
- {?MODULE,do_bopp,1},
- 'receive',
- timeout,
- {?MODULE,do_bepp,0}] ->
- ok;
- X ->
- test_server:fail({l21, X})
- end,
-
- ?line erlang:process_flag(self(), save_calls, 10),
- ?line {last_calls, L3} = process_info(self(), last_calls),
- ?line L31 = lists:filter(fun is_local_function/1, L3),
- ?line [] = L31,
+ erlang:process_flag(self(), save_calls, 0),
+ {last_calls, false} = process_info(self(), last_calls),
+
+ erlang:process_flag(self(), save_calls, 10),
+ {last_calls, _L1} = process_info(self(), last_calls),
+ ?MODULE:do_bipp(),
+ {last_calls, L2} = process_info(self(), last_calls),
+ L21 = lists:filter(fun is_local_function/1, L2),
+ case L21 of
+ [{?MODULE,do_bipp,0},
+ timeout,
+ 'send',
+ {?MODULE,do_bopp,1},
+ 'receive',
+ timeout,
+ {?MODULE,do_bepp,0}] ->
+ ok;
+ X ->
+ ct:fail({l21, X})
+ end,
+
+ erlang:process_flag(self(), save_calls, 10),
+ {last_calls, L3} = process_info(self(), last_calls),
+ L31 = lists:filter(fun is_local_function/1, L3),
+ [] = L31,
ok.
do_bipp() ->
@@ -172,7 +151,7 @@ do_bapp() ->
do_bopp(T) ->
receive
- X -> X
+ X -> X
after T -> ok
end.
@@ -189,25 +168,25 @@ is_local_function(_) ->
% Number crunching for reds test.
carmichaels_below(N) ->
- random:seed(3172,9814,20125),
+ rand:seed(exsplus, {3172,9814,20125}),
carmichaels_below(1,N).
carmichaels_below(N,N2) when N >= N2 ->
0;
carmichaels_below(N,N2) ->
X = case fast_prime(N,10) of
- false -> 0;
- true ->
- case fast_prime2(N,10) of
- true ->
- %io:format("Prime: ~p~n",[N]),
- 0;
- false ->
- io:format("Carmichael: ~p (dividable by ~p)~n",
- [N,smallest_divisor(N)]),
- 1
- end
- end,
+ false -> 0;
+ true ->
+ case fast_prime2(N,10) of
+ true ->
+ %io:format("Prime: ~p~n",[N]),
+ 0;
+ false ->
+ io:format("Carmichael: ~p (dividable by ~p)~n",
+ [N,smallest_divisor(N)]),
+ 1
+ end
+ end,
X+carmichaels_below(N+2,N2).
expmod(_,E,_) when E == 0 ->
@@ -219,7 +198,7 @@ expmod(Base,Exp,Mod) ->
(Base * expmod(Base,Exp - 1,Mod)) rem Mod.
uniform(N) ->
- random:uniform(N-1).
+ rand:uniform(N-1).
fermat(N) ->
R = uniform(N),
@@ -231,30 +210,30 @@ do_fast_prime(_N,0) ->
true;
do_fast_prime(N,Times) ->
case fermat(N) of
- true ->
- do_fast_prime(N,Times-1);
- false ->
- false
+ true ->
+ do_fast_prime(N,Times-1);
+ false ->
+ false
end.
-
+
fast_prime(N,T) ->
do_fast_prime(N,T).
expmod2(_,E,_) when E == 0 ->
1;
expmod2(Base,Exp,Mod) when (Exp rem 2) == 0 ->
-%% Uncomment the code below to simulate scheduling bug!
-% case erlang:process_info(self(),last_calls) of
-% {last_calls,false} -> ok;
-% _ -> erlang:yield()
-% end,
+ %% Uncomment the code below to simulate scheduling bug!
+ % case erlang:process_info(self(),last_calls) of
+ % {last_calls,false} -> ok;
+ % _ -> erlang:yield()
+ % end,
X = expmod2(Base,Exp div 2,Mod),
Y=(X*X) rem Mod,
if
- Y == 1, X =/= 1, X =/= (Mod - 1) ->
- 0;
- true ->
- Y rem Mod
+ Y == 1, X =/= 1, X =/= (Mod - 1) ->
+ 0;
+ true ->
+ Y rem Mod
end;
expmod2(Base,Exp,Mod) ->
(Base * expmod2(Base,Exp - 1,Mod)) rem Mod.
@@ -269,12 +248,12 @@ do_fast_prime2(_N,0) ->
true;
do_fast_prime2(N,Times) ->
case miller_rabbin(N) of
- true ->
- do_fast_prime2(N,Times-1);
- false ->
- false
+ true ->
+ do_fast_prime2(N,Times-1);
+ false ->
+ false
end.
-
+
fast_prime2(N,T) ->
do_fast_prime2(N,T).
@@ -283,17 +262,16 @@ smallest_divisor(N) ->
find_divisor(N,TD) ->
if
- TD*TD > N ->
- N;
- true ->
- case divides(TD,N) of
- true ->
- TD;
- false ->
- find_divisor(N,TD+1)
- end
+ TD*TD > N ->
+ N;
+ true ->
+ case divides(TD,N) of
+ true ->
+ TD;
+ false ->
+ find_divisor(N,TD+1)
+ end
end.
divides(A,B) ->
(B rem A) == 0.
-
diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl
index 986a73ebb1..64c280b198 100644
--- a/erts/emulator/test/scheduler_SUITE.erl
+++ b/erts/emulator/test/scheduler_SUITE.erl
@@ -31,12 +31,12 @@
%-define(line_trace, 1).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%-compile(export_all).
--export([all/0, suite/0,groups/0,init_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2, end_per_testcase/2, end_per_suite/1]).
+-export([all/0, suite/0, groups/0,
+ init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2]).
-export([equal/1,
few_low/1,
@@ -54,23 +54,25 @@
sct_cmd/1,
sbt_cmd/1,
scheduler_threads/1,
+ scheduler_suspend_basic/1,
scheduler_suspend/1,
dirty_scheduler_threads/1,
+ dirty_scheduler_exit/1,
reader_groups/1]).
--define(DEFAULT_TIMEOUT, ?t:minutes(15)).
-
--define(MIN_SCHEDULER_TEST_TIMEOUT, ?t:minutes(1)).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 15}}].
all() ->
[equal, few_low, many_low, equal_with_part_time_high,
equal_with_part_time_max,
equal_and_high_with_part_time_max, equal_with_high,
- equal_with_high_max, bound_process,
- {group, scheduler_bind}, scheduler_threads, scheduler_suspend,
- dirty_scheduler_threads,
+ equal_with_high_max,
+ bound_process,
+ {group, scheduler_bind}, scheduler_threads,
+ scheduler_suspend_basic, scheduler_suspend,
+ dirty_scheduler_threads, dirty_scheduler_exit,
reader_groups].
groups() ->
@@ -85,12 +87,6 @@ end_per_suite(Config) ->
catch erts_debug:set_internal_state(available_internal_state, false),
Config.
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
init_per_testcase(update_cpu_info, Config) ->
case os:find_executable("taskset") of
false ->
@@ -102,15 +98,12 @@ init_per_testcase(Case, Config) when is_list(Config) ->
init_per_tc(Case, Config).
init_per_tc(Case, Config) ->
- Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
process_flag(priority, max),
erlang:display({'------------', ?MODULE, Case, '------------'}),
OkRes = ok,
- [{watchdog, Dog}, {testcase, Case}, {ok_res, OkRes} |Config].
+ [{testcase, Case}, {ok_res, OkRes} |Config].
end_per_testcase(_Case, Config) when is_list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
ok.
-define(ERTS_RUNQ_CHECK_BALANCE_REDS_PER_SCHED, (2000*2000)).
@@ -130,130 +123,130 @@ many_low(Config) when is_list(Config) ->
low_normal_test(Config, 2*active_schedulers(), 1000).
low_normal_test(Config, NW, LW) ->
- ?line Tracer = start_tracer(),
- ?line Low = workers(LW, low),
- ?line Normal = workers(NW, normal),
- ?line Res = do_it(Tracer, Low, Normal, [], []),
- ?line chk_result(Res, LW, NW, 0, 0, true, false, false),
- ?line workers_exit([Low, Normal]),
- ?line ok(Res, Config).
+ Tracer = start_tracer(),
+ Low = workers(LW, low),
+ Normal = workers(NW, normal),
+ Res = do_it(Tracer, Low, Normal, [], []),
+ chk_result(Res, LW, NW, 0, 0, true, false, false),
+ workers_exit([Low, Normal]),
+ ok(Res, Config).
equal_with_part_time_high(Config) when is_list(Config) ->
- ?line NW = 500,
- ?line LW = 500,
- ?line HW = 1,
- ?line Tracer = start_tracer(),
- ?line Normal = workers(NW, normal),
- ?line Low = workers(LW, low),
- ?line High = part_time_workers(HW, high),
- ?line Res = do_it(Tracer, Low, Normal, High, []),
- ?line chk_result(Res, LW, NW, HW, 0, true, true, false),
- ?line workers_exit([Low, Normal, High]),
- ?line ok(Res, Config).
+ NW = 500,
+ LW = 500,
+ HW = 1,
+ Tracer = start_tracer(),
+ Normal = workers(NW, normal),
+ Low = workers(LW, low),
+ High = part_time_workers(HW, high),
+ Res = do_it(Tracer, Low, Normal, High, []),
+ chk_result(Res, LW, NW, HW, 0, true, true, false),
+ workers_exit([Low, Normal, High]),
+ ok(Res, Config).
equal_and_high_with_part_time_max(Config) when is_list(Config) ->
- ?line NW = 500,
- ?line LW = 500,
- ?line HW = 500,
- ?line MW = 1,
- ?line Tracer = start_tracer(),
- ?line Low = workers(LW, low),
- ?line Normal = workers(NW, normal),
- ?line High = workers(HW, high),
- ?line Max = part_time_workers(MW, max),
- ?line Res = do_it(Tracer, Low, Normal, High, Max),
- ?line chk_result(Res, LW, NW, HW, MW, false, true, true),
- ?line workers_exit([Low, Normal, Max]),
- ?line ok(Res, Config).
+ NW = 500,
+ LW = 500,
+ HW = 500,
+ MW = 1,
+ Tracer = start_tracer(),
+ Low = workers(LW, low),
+ Normal = workers(NW, normal),
+ High = workers(HW, high),
+ Max = part_time_workers(MW, max),
+ Res = do_it(Tracer, Low, Normal, High, Max),
+ chk_result(Res, LW, NW, HW, MW, false, true, true),
+ workers_exit([Low, Normal, Max]),
+ ok(Res, Config).
equal_with_part_time_max(Config) when is_list(Config) ->
- ?line NW = 500,
- ?line LW = 500,
- ?line MW = 1,
- ?line Tracer = start_tracer(),
- ?line Low = workers(LW, low),
- ?line Normal = workers(NW, normal),
- ?line Max = part_time_workers(MW, max),
- ?line Res = do_it(Tracer, Low, Normal, [], Max),
- ?line chk_result(Res, LW, NW, 0, MW, true, false, true),
- ?line workers_exit([Low, Normal, Max]),
- ?line ok(Res, Config).
+ NW = 500,
+ LW = 500,
+ MW = 1,
+ Tracer = start_tracer(),
+ Low = workers(LW, low),
+ Normal = workers(NW, normal),
+ Max = part_time_workers(MW, max),
+ Res = do_it(Tracer, Low, Normal, [], Max),
+ chk_result(Res, LW, NW, 0, MW, true, false, true),
+ workers_exit([Low, Normal, Max]),
+ ok(Res, Config).
equal_with_high(Config) when is_list(Config) ->
- ?line NW = 500,
- ?line LW = 500,
- ?line HW = 1,
- ?line Tracer = start_tracer(),
- ?line Low = workers(LW, low),
- ?line Normal = workers(NW, normal),
- ?line High = workers(HW, high),
- ?line Res = do_it(Tracer, Low, Normal, High, []),
- ?line LNExe = case active_schedulers() of
+ NW = 500,
+ LW = 500,
+ HW = 1,
+ Tracer = start_tracer(),
+ Low = workers(LW, low),
+ Normal = workers(NW, normal),
+ High = workers(HW, high),
+ Res = do_it(Tracer, Low, Normal, High, []),
+ LNExe = case active_schedulers() of
S when S =< HW -> false;
_ -> true
end,
- ?line chk_result(Res, LW, NW, HW, 0, LNExe, true, false),
- ?line workers_exit([Low, Normal, High]),
- ?line ok(Res, Config).
+ chk_result(Res, LW, NW, HW, 0, LNExe, true, false),
+ workers_exit([Low, Normal, High]),
+ ok(Res, Config).
equal_with_high_max(Config) when is_list(Config) ->
- ?line NW = 500,
- ?line LW = 500,
- ?line HW = 1,
- ?line MW = 1,
- ?line Tracer = start_tracer(),
- ?line Normal = workers(NW, normal),
- ?line Low = workers(LW, low),
- ?line High = workers(HW, high),
- ?line Max = workers(MW, max),
- ?line Res = do_it(Tracer, Low, Normal, High, Max),
- ?line {LNExe, HExe} = case active_schedulers() of
+ NW = 500,
+ LW = 500,
+ HW = 1,
+ MW = 1,
+ Tracer = start_tracer(),
+ Normal = workers(NW, normal),
+ Low = workers(LW, low),
+ High = workers(HW, high),
+ Max = workers(MW, max),
+ Res = do_it(Tracer, Low, Normal, High, Max),
+ {LNExe, HExe} = case active_schedulers() of
S when S =< MW -> {false, false};
S when S =< (MW + HW) -> {false, true};
_ -> {true, true}
end,
- ?line chk_result(Res, LW, NW, HW, MW, LNExe, HExe, true),
- ?line workers_exit([Low, Normal, Max]),
- ?line ok(Res, Config).
+ chk_result(Res, LW, NW, HW, MW, LNExe, HExe, true),
+ workers_exit([Low, Normal, Max]),
+ ok(Res, Config).
bound_process(Config) when is_list(Config) ->
case erlang:system_info(run_queues) == erlang:system_info(schedulers) of
- true ->
- ?line NStartBase = 20000,
- ?line NStart = case {erlang:system_info(debug_compiled),
- erlang:system_info(lock_checking)} of
- {true, true} -> NStartBase div 100;
- {_, true} -> NStartBase div 10;
- _ -> NStartBase
- end,
- ?line MStart = 100,
- ?line Seq = lists:seq(1, 100),
- ?line Tester = self(),
- ?line Procs = lists:map(
- fun (N) when N rem 2 == 0 ->
- spawn_opt(fun () ->
- bound_loop(NStart,
- NStart,
- MStart,
- 1),
- Tester ! {self(), done}
- end,
- [{scheduler, 1}, link]);
- (_N) ->
- spawn_link(fun () ->
- bound_loop(NStart,
- NStart,
- MStart,
- false),
- Tester ! {self(), done}
- end)
- end,
- Seq),
- ?line lists:foreach(fun (P) -> receive {P, done} -> ok end end,
- Procs),
- ?line ok;
- false ->
- {skipped, "Functionality not supported"}
+ true ->
+ NStartBase = 20000,
+ NStart = case {erlang:system_info(debug_compiled),
+ erlang:system_info(lock_checking)} of
+ {true, true} -> NStartBase div 100;
+ {_, true} -> NStartBase div 10;
+ _ -> NStartBase
+ end,
+ MStart = 100,
+ Seq = lists:seq(1, 100),
+ Tester = self(),
+ Procs = lists:map(
+ fun (N) when N rem 2 == 0 ->
+ spawn_opt(fun () ->
+ bound_loop(NStart,
+ NStart,
+ MStart,
+ 1),
+ Tester ! {self(), done}
+ end,
+ [{scheduler, 1}, link]);
+ (_N) ->
+ spawn_link(fun () ->
+ bound_loop(NStart,
+ NStart,
+ MStart,
+ false),
+ Tester ! {self(), done}
+ end)
+ end,
+ Seq),
+ lists:foreach(fun (P) -> receive {P, done} -> ok end end,
+ Procs),
+ ok;
+ false ->
+ {skipped, "Functionality not supported"}
end.
bound_loop(_, 0, 0, _) ->
@@ -487,59 +480,59 @@ bound_loop(NS, N, M, Sched) ->
":L30-31t0-1c15n3p0").
-define(TOPOLOGY_F_TERM,
- [{processor,[{node,[{core,[{thread,{logical,0}},
- {thread,{logical,1}}]},
- {core,[{thread,{logical,2}},
- {thread,{logical,3}}]},
- {core,[{thread,{logical,4}},
- {thread,{logical,5}}]},
- {core,[{thread,{logical,6}},
- {thread,{logical,7}}]}]},
- {node,[{core,[{thread,{logical,8}},
- {thread,{logical,9}}]},
- {core,[{thread,{logical,10}},
- {thread,{logical,11}}]},
- {core,[{thread,{logical,12}},
- {thread,{logical,13}}]},
- {core,[{thread,{logical,14}},
- {thread,{logical,15}}]}]},
- {node,[{core,[{thread,{logical,16}},
- {thread,{logical,17}}]},
- {core,[{thread,{logical,18}},
- {thread,{logical,19}}]},
- {core,[{thread,{logical,20}},
- {thread,{logical,21}}]},
- {core,[{thread,{logical,22}},
- {thread,{logical,23}}]}]},
- {node,[{core,[{thread,{logical,24}},
- {thread,{logical,25}}]},
- {core,[{thread,{logical,26}},
- {thread,{logical,27}}]},
- {core,[{thread,{logical,28}},
- {thread,{logical,29}}]},
- {core,[{thread,{logical,30}},
- {thread,{logical,31}}]}]}]}]).
+ [{processor,[{node,[{core,[{thread,{logical,0}},
+ {thread,{logical,1}}]},
+ {core,[{thread,{logical,2}},
+ {thread,{logical,3}}]},
+ {core,[{thread,{logical,4}},
+ {thread,{logical,5}}]},
+ {core,[{thread,{logical,6}},
+ {thread,{logical,7}}]}]},
+ {node,[{core,[{thread,{logical,8}},
+ {thread,{logical,9}}]},
+ {core,[{thread,{logical,10}},
+ {thread,{logical,11}}]},
+ {core,[{thread,{logical,12}},
+ {thread,{logical,13}}]},
+ {core,[{thread,{logical,14}},
+ {thread,{logical,15}}]}]},
+ {node,[{core,[{thread,{logical,16}},
+ {thread,{logical,17}}]},
+ {core,[{thread,{logical,18}},
+ {thread,{logical,19}}]},
+ {core,[{thread,{logical,20}},
+ {thread,{logical,21}}]},
+ {core,[{thread,{logical,22}},
+ {thread,{logical,23}}]}]},
+ {node,[{core,[{thread,{logical,24}},
+ {thread,{logical,25}}]},
+ {core,[{thread,{logical,26}},
+ {thread,{logical,27}}]},
+ {core,[{thread,{logical,28}},
+ {thread,{logical,29}}]},
+ {core,[{thread,{logical,30}},
+ {thread,{logical,31}}]}]}]}]).
bindings(Node, BindType) ->
Parent = self(),
Ref = make_ref(),
Pid = spawn_link(Node,
- fun () ->
- enable_internal_state(),
- Res = (catch erts_debug:get_internal_state(
- {fake_scheduler_bindings,
- BindType})),
- Parent ! {Ref, Res}
- end),
+ fun () ->
+ enable_internal_state(),
+ Res = (catch erts_debug:get_internal_state(
+ {fake_scheduler_bindings,
+ BindType})),
+ Parent ! {Ref, Res}
+ end),
receive
- {Ref, Res} ->
- ?t:format("~p: ~p~n", [BindType, Res]),
- unlink(Pid),
- Res
+ {Ref, Res} ->
+ io:format("~p: ~p~n", [BindType, Res]),
+ unlink(Pid),
+ Res
end.
scheduler_bind_types(Config) when is_list(Config) ->
- ?line OldRelFlags = clear_erl_rel_flags(),
+ OldRelFlags = clear_erl_rel_flags(),
try
scheduler_bind_types_test(Config,
?TOPOLOGY_A_TERM,
@@ -568,267 +561,267 @@ scheduler_bind_types(Config) when is_list(Config) ->
after
restore_erl_rel_flags(OldRelFlags)
end,
- ?line ok.
+ ok.
scheduler_bind_types_test(Config, Topology, CmdLine, TermLetter) ->
- ?line ?t:format("Testing (~p): ~p~n", [TermLetter, Topology]),
- ?line {ok, Node0} = start_node(Config),
- ?line _ = rpc:call(Node0, erlang, system_flag, [cpu_topology, Topology]),
- ?line cmp(Topology, rpc:call(Node0, erlang, system_info, [cpu_topology])),
- ?line check_bind_types(Node0, TermLetter),
- ?line stop_node(Node0),
- ?line {ok, Node1} = start_node(Config, CmdLine),
- ?line cmp(Topology, rpc:call(Node1, erlang, system_info, [cpu_topology])),
- ?line check_bind_types(Node1, TermLetter),
- ?line stop_node(Node1).
+ io:format("Testing (~p): ~p~n", [TermLetter, Topology]),
+ {ok, Node0} = start_node(Config),
+ _ = rpc:call(Node0, erlang, system_flag, [cpu_topology, Topology]),
+ cmp(Topology, rpc:call(Node0, erlang, system_info, [cpu_topology])),
+ check_bind_types(Node0, TermLetter),
+ stop_node(Node0),
+ {ok, Node1} = start_node(Config, CmdLine),
+ cmp(Topology, rpc:call(Node1, erlang, system_info, [cpu_topology])),
+ check_bind_types(Node1, TermLetter),
+ stop_node(Node1).
check_bind_types(Node, a) ->
- ?line {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
- = bindings(Node, no_spread),
- ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15}
- = bindings(Node, thread_spread),
- ?line {0,4,8,12,2,6,10,14,1,5,9,13,3,7,11,15}
- = bindings(Node, processor_spread),
- ?line {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}
- = bindings(Node, spread),
- ?line {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15}
- = bindings(Node, no_node_thread_spread),
- ?line {0,4,2,6,1,5,3,7,8,12,10,14,9,13,11,15}
- = bindings(Node, no_node_processor_spread),
- ?line {0,4,2,6,8,12,10,14,1,5,3,7,9,13,11,15}
- = bindings(Node, thread_no_node_processor_spread),
- ?line {0,4,2,6,8,12,10,14,1,5,3,7,9,13,11,15}
- = bindings(Node, default_bind),
- ?line ok;
+ {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
+ = bindings(Node, no_spread),
+ {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15}
+ = bindings(Node, thread_spread),
+ {0,4,8,12,2,6,10,14,1,5,9,13,3,7,11,15}
+ = bindings(Node, processor_spread),
+ {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}
+ = bindings(Node, spread),
+ {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15}
+ = bindings(Node, no_node_thread_spread),
+ {0,4,2,6,1,5,3,7,8,12,10,14,9,13,11,15}
+ = bindings(Node, no_node_processor_spread),
+ {0,4,2,6,8,12,10,14,1,5,3,7,9,13,11,15}
+ = bindings(Node, thread_no_node_processor_spread),
+ {0,4,2,6,8,12,10,14,1,5,3,7,9,13,11,15}
+ = bindings(Node, default_bind),
+ ok;
check_bind_types(Node, b) ->
- ?line {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
- = bindings(Node, no_spread),
- ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15}
- = bindings(Node, thread_spread),
- ?line {0,8,2,10,4,12,6,14,1,9,3,11,5,13,7,15}
- = bindings(Node, processor_spread),
- ?line {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}
- = bindings(Node, spread),
- ?line {0,2,1,3,4,6,5,7,8,10,9,11,12,14,13,15}
- = bindings(Node, no_node_thread_spread),
- ?line {0,2,1,3,4,6,5,7,8,10,9,11,12,14,13,15}
- = bindings(Node, no_node_processor_spread),
- ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15}
- = bindings(Node, thread_no_node_processor_spread),
- ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15}
- = bindings(Node, default_bind),
- ?line ok;
+ {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
+ = bindings(Node, no_spread),
+ {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15}
+ = bindings(Node, thread_spread),
+ {0,8,2,10,4,12,6,14,1,9,3,11,5,13,7,15}
+ = bindings(Node, processor_spread),
+ {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}
+ = bindings(Node, spread),
+ {0,2,1,3,4,6,5,7,8,10,9,11,12,14,13,15}
+ = bindings(Node, no_node_thread_spread),
+ {0,2,1,3,4,6,5,7,8,10,9,11,12,14,13,15}
+ = bindings(Node, no_node_processor_spread),
+ {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15}
+ = bindings(Node, thread_no_node_processor_spread),
+ {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15}
+ = bindings(Node, default_bind),
+ ok;
check_bind_types(Node, c) ->
- ?line {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,26,27,28,29,30,31} = bindings(Node, no_spread),
- ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15,
- 17,19,21,23,25,27,29,31} = bindings(Node, thread_spread),
- ?line {0,4,8,16,20,24,2,6,10,18,22,26,12,28,14,30,1,5,9,17,21,25,
- 3,7,11,19,23,27,13,29,15,31} = bindings(Node, processor_spread),
- ?line {0,8,16,24,4,20,12,28,2,10,18,26,6,22,14,30,1,9,17,25,5,21,13,29,3,11,
- 19,27,7,23,15,31} = bindings(Node, spread),
- ?line {0,2,4,6,1,3,5,7,8,10,9,11,12,14,13,15,16,18,20,22,17,19,21,23,24,26,
- 25,27,28,30,29,31} = bindings(Node, no_node_thread_spread),
- ?line {0,4,2,6,1,5,3,7,8,10,9,11,12,14,13,15,16,20,18,22,17,21,19,23,24,26,
- 25,27,28,30,29,31} = bindings(Node, no_node_processor_spread),
- ?line {0,4,2,6,8,10,12,14,16,20,18,22,24,26,28,30,1,5,3,7,9,11,13,15,17,21,
- 19,23,25,27,29,31} = bindings(Node, thread_no_node_processor_spread),
- ?line {0,4,2,6,8,10,12,14,16,20,18,22,24,26,28,30,1,5,3,7,9,11,13,15,17,21,
- 19,23,25,27,29,31} = bindings(Node, default_bind),
- ?line ok;
+ {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,26,27,28,29,30,31} = bindings(Node, no_spread),
+ {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15,
+ 17,19,21,23,25,27,29,31} = bindings(Node, thread_spread),
+ {0,4,8,16,20,24,2,6,10,18,22,26,12,28,14,30,1,5,9,17,21,25,
+ 3,7,11,19,23,27,13,29,15,31} = bindings(Node, processor_spread),
+ {0,8,16,24,4,20,12,28,2,10,18,26,6,22,14,30,1,9,17,25,5,21,13,29,3,11,
+ 19,27,7,23,15,31} = bindings(Node, spread),
+ {0,2,4,6,1,3,5,7,8,10,9,11,12,14,13,15,16,18,20,22,17,19,21,23,24,26,
+ 25,27,28,30,29,31} = bindings(Node, no_node_thread_spread),
+ {0,4,2,6,1,5,3,7,8,10,9,11,12,14,13,15,16,20,18,22,17,21,19,23,24,26,
+ 25,27,28,30,29,31} = bindings(Node, no_node_processor_spread),
+ {0,4,2,6,8,10,12,14,16,20,18,22,24,26,28,30,1,5,3,7,9,11,13,15,17,21,
+ 19,23,25,27,29,31} = bindings(Node, thread_no_node_processor_spread),
+ {0,4,2,6,8,10,12,14,16,20,18,22,24,26,28,30,1,5,3,7,9,11,13,15,17,21,
+ 19,23,25,27,29,31} = bindings(Node, default_bind),
+ ok;
check_bind_types(Node, d) ->
- ?line {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,26,27,28,29,30,31} = bindings(Node, no_spread),
- ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15,
- 17,19,21,23,25,27,29,31} = bindings(Node, thread_spread),
- ?line {0,8,12,16,24,28,2,10,14,18,26,30,4,20,6,22,1,9,13,17,25,29,3,11,15,
- 19,27,31,5,21,7,23} = bindings(Node, processor_spread),
- ?line {0,8,16,24,12,28,4,20,2,10,18,26,14,30,6,22,1,9,17,25,13,29,5,21,3,11,
- 19,27,15,31,7,23} = bindings(Node, spread),
- ?line {0,2,1,3,4,6,5,7,8,10,12,14,9,11,13,15,16,18,17,19,20,22,21,23,24,26,
- 28,30,25,27,29,31} = bindings(Node, no_node_thread_spread),
- ?line {0,2,1,3,4,6,5,7,8,12,10,14,9,13,11,15,16,18,17,19,20,22,21,23,24,28,
- 26,30,25,29,27,31} = bindings(Node, no_node_processor_spread),
- ?line {0,2,4,6,8,12,10,14,16,18,20,22,24,28,26,30,1,3,5,7,9,13,11,15,17,19,
- 21,23,25,29,27,31} = bindings(Node, thread_no_node_processor_spread),
- ?line {0,2,4,6,8,12,10,14,16,18,20,22,24,28,26,30,1,3,5,7,9,13,11,15,17,19,
- 21,23,25,29,27,31} = bindings(Node, default_bind),
- ?line ok;
+ {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,26,27,28,29,30,31} = bindings(Node, no_spread),
+ {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15,
+ 17,19,21,23,25,27,29,31} = bindings(Node, thread_spread),
+ {0,8,12,16,24,28,2,10,14,18,26,30,4,20,6,22,1,9,13,17,25,29,3,11,15,
+ 19,27,31,5,21,7,23} = bindings(Node, processor_spread),
+ {0,8,16,24,12,28,4,20,2,10,18,26,14,30,6,22,1,9,17,25,13,29,5,21,3,11,
+ 19,27,15,31,7,23} = bindings(Node, spread),
+ {0,2,1,3,4,6,5,7,8,10,12,14,9,11,13,15,16,18,17,19,20,22,21,23,24,26,
+ 28,30,25,27,29,31} = bindings(Node, no_node_thread_spread),
+ {0,2,1,3,4,6,5,7,8,12,10,14,9,13,11,15,16,18,17,19,20,22,21,23,24,28,
+ 26,30,25,29,27,31} = bindings(Node, no_node_processor_spread),
+ {0,2,4,6,8,12,10,14,16,18,20,22,24,28,26,30,1,3,5,7,9,13,11,15,17,19,
+ 21,23,25,29,27,31} = bindings(Node, thread_no_node_processor_spread),
+ {0,2,4,6,8,12,10,14,16,18,20,22,24,28,26,30,1,3,5,7,9,13,11,15,17,19,
+ 21,23,25,29,27,31} = bindings(Node, default_bind),
+ ok;
check_bind_types(Node, e) ->
- ?line {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
- = bindings(Node, no_spread),
- ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15}
- = bindings(Node, thread_spread),
- ?line {0,8,2,10,4,12,6,14,1,9,3,11,5,13,7,15}
- = bindings(Node, processor_spread),
- ?line {0,8,2,10,4,12,6,14,1,9,3,11,5,13,7,15}
- = bindings(Node, spread),
- ?line {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15}
- = bindings(Node, no_node_thread_spread),
- ?line {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15}
- = bindings(Node, no_node_processor_spread),
- ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15}
- = bindings(Node, thread_no_node_processor_spread),
- ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15}
- = bindings(Node, default_bind),
- ?line ok;
+ {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
+ = bindings(Node, no_spread),
+ {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15}
+ = bindings(Node, thread_spread),
+ {0,8,2,10,4,12,6,14,1,9,3,11,5,13,7,15}
+ = bindings(Node, processor_spread),
+ {0,8,2,10,4,12,6,14,1,9,3,11,5,13,7,15}
+ = bindings(Node, spread),
+ {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15}
+ = bindings(Node, no_node_thread_spread),
+ {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15}
+ = bindings(Node, no_node_processor_spread),
+ {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15}
+ = bindings(Node, thread_no_node_processor_spread),
+ {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15}
+ = bindings(Node, default_bind),
+ ok;
check_bind_types(Node, f) ->
- ?line {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,26,27,28,29,30,31} = bindings(Node, no_spread),
- ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15,
- 17,19,21,23,25,27,29,31} = bindings(Node, thread_spread),
- ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,
- 15,17,19,21,23,25,27,29,31} = bindings(Node, processor_spread),
- ?line {0,8,16,24,2,10,18,26,4,12,20,28,6,14,22,30,1,9,17,25,3,11,19,27,5,13,
- 21,29,7,15,23,31} = bindings(Node, spread),
- ?line {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15,16,18,20,22,17,19,21,23,24,26,
- 28,30,25,27,29,31} = bindings(Node, no_node_thread_spread),
- ?line {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15,16,18,20,22,17,19,21,23,24,26,
- 28,30,25,27,29,31} = bindings(Node, no_node_processor_spread),
- ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15,17,19,
- 21,23,25,27,29,31} = bindings(Node, thread_no_node_processor_spread),
- ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15,17,19,
- 21,23,25,27,29,31} = bindings(Node, default_bind),
- ?line ok;
+ {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,26,27,28,29,30,31} = bindings(Node, no_spread),
+ {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15,
+ 17,19,21,23,25,27,29,31} = bindings(Node, thread_spread),
+ {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,
+ 15,17,19,21,23,25,27,29,31} = bindings(Node, processor_spread),
+ {0,8,16,24,2,10,18,26,4,12,20,28,6,14,22,30,1,9,17,25,3,11,19,27,5,13,
+ 21,29,7,15,23,31} = bindings(Node, spread),
+ {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15,16,18,20,22,17,19,21,23,24,26,
+ 28,30,25,27,29,31} = bindings(Node, no_node_thread_spread),
+ {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15,16,18,20,22,17,19,21,23,24,26,
+ 28,30,25,27,29,31} = bindings(Node, no_node_processor_spread),
+ {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15,17,19,
+ 21,23,25,27,29,31} = bindings(Node, thread_no_node_processor_spread),
+ {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15,17,19,
+ 21,23,25,27,29,31} = bindings(Node, default_bind),
+ ok;
check_bind_types(Node, _) ->
- ?line bindings(Node, no_spread),
- ?line bindings(Node, thread_spread),
- ?line bindings(Node, processor_spread),
- ?line bindings(Node, spread),
- ?line bindings(Node, no_node_thread_spread),
- ?line bindings(Node, no_node_processor_spread),
- ?line bindings(Node, thread_no_node_processor_spread),
- ?line bindings(Node, default_bind),
- ?line ok.
+ bindings(Node, no_spread),
+ bindings(Node, thread_spread),
+ bindings(Node, processor_spread),
+ bindings(Node, spread),
+ bindings(Node, no_node_thread_spread),
+ bindings(Node, no_node_processor_spread),
+ bindings(Node, thread_no_node_processor_spread),
+ bindings(Node, default_bind),
+ ok.
cpu_topology(Config) when is_list(Config) ->
- ?line OldRelFlags = clear_erl_rel_flags(),
+ OldRelFlags = clear_erl_rel_flags(),
try
- ?line cpu_topology_test(
- Config,
- [{node,[{processor,[{core,{logical,0}},
- {core,{logical,1}}]}]},
- {processor,[{node,[{core,{logical,2}},
- {core,{logical,3}}]}]},
- {node,[{processor,[{core,{logical,4}},
- {core,{logical,5}}]}]},
- {processor,[{node,[{core,{logical,6}},
- {core,{logical,7}}]}]}],
- "+sct "
- "L0-1c0-1p0n0"
- ":L2-3c0-1n1p1"
- ":L4-5c0-1p2n2"
- ":L6-7c0-1n3p3"),
- ?line cpu_topology_test(
- Config,
- [{node,[{processor,[{core,{logical,0}},
- {core,{logical,1}}]},
- {processor,[{core,{logical,2}},
- {core,{logical,3}}]}]},
- {processor,[{node,[{core,{logical,4}},
- {core,{logical,5}}]},
- {node,[{core,{logical,6}},
- {core,{logical,7}}]}]},
- {node,[{processor,[{core,{logical,8}},
- {core,{logical,9}}]},
- {processor,[{core,{logical,10}},
- {core,{logical,11}}]}]},
- {processor,[{node,[{core,{logical,12}},
- {core,{logical,13}}]},
- {node,[{core,{logical,14}},
- {core,{logical,15}}]}]}],
- "+sct "
- "L0-1c0-1p0n0"
- ":L2-3c0-1p1n0"
- ":L4-5c0-1n1p2"
- ":L6-7c2-3n2p2"
- ":L8-9c0-1p3n3"
- ":L10-11c0-1p4n3"
- ":L12-13c0-1n4p5"
- ":L14-15c2-3n5p5"),
- ?line cpu_topology_test(
- Config,
- [{node,[{processor,[{core,{logical,0}},
- {core,{logical,1}}]}]},
- {processor,[{node,[{core,{logical,2}},
- {core,{logical,3}}]}]},
- {processor,[{node,[{core,{logical,4}},
- {core,{logical,5}}]}]},
- {node,[{processor,[{core,{logical,6}},
- {core,{logical,7}}]}]},
- {node,[{processor,[{core,{logical,8}},
- {core,{logical,9}}]}]},
- {processor,[{node,[{core,{logical,10}},
- {core,{logical,11}}]}]}],
- "+sct "
- "L0-1c0-1p0n0"
- ":L2-3c0-1n1p1"
- ":L4-5c0-1n2p2"
- ":L6-7c0-1p3n3"
- ":L8-9c0-1p4n4"
- ":L10-11c0-1n5p5")
+ cpu_topology_test(
+ Config,
+ [{node,[{processor,[{core,{logical,0}},
+ {core,{logical,1}}]}]},
+ {processor,[{node,[{core,{logical,2}},
+ {core,{logical,3}}]}]},
+ {node,[{processor,[{core,{logical,4}},
+ {core,{logical,5}}]}]},
+ {processor,[{node,[{core,{logical,6}},
+ {core,{logical,7}}]}]}],
+ "+sct "
+ "L0-1c0-1p0n0"
+ ":L2-3c0-1n1p1"
+ ":L4-5c0-1p2n2"
+ ":L6-7c0-1n3p3"),
+ cpu_topology_test(
+ Config,
+ [{node,[{processor,[{core,{logical,0}},
+ {core,{logical,1}}]},
+ {processor,[{core,{logical,2}},
+ {core,{logical,3}}]}]},
+ {processor,[{node,[{core,{logical,4}},
+ {core,{logical,5}}]},
+ {node,[{core,{logical,6}},
+ {core,{logical,7}}]}]},
+ {node,[{processor,[{core,{logical,8}},
+ {core,{logical,9}}]},
+ {processor,[{core,{logical,10}},
+ {core,{logical,11}}]}]},
+ {processor,[{node,[{core,{logical,12}},
+ {core,{logical,13}}]},
+ {node,[{core,{logical,14}},
+ {core,{logical,15}}]}]}],
+ "+sct "
+ "L0-1c0-1p0n0"
+ ":L2-3c0-1p1n0"
+ ":L4-5c0-1n1p2"
+ ":L6-7c2-3n2p2"
+ ":L8-9c0-1p3n3"
+ ":L10-11c0-1p4n3"
+ ":L12-13c0-1n4p5"
+ ":L14-15c2-3n5p5"),
+ cpu_topology_test(
+ Config,
+ [{node,[{processor,[{core,{logical,0}},
+ {core,{logical,1}}]}]},
+ {processor,[{node,[{core,{logical,2}},
+ {core,{logical,3}}]}]},
+ {processor,[{node,[{core,{logical,4}},
+ {core,{logical,5}}]}]},
+ {node,[{processor,[{core,{logical,6}},
+ {core,{logical,7}}]}]},
+ {node,[{processor,[{core,{logical,8}},
+ {core,{logical,9}}]}]},
+ {processor,[{node,[{core,{logical,10}},
+ {core,{logical,11}}]}]}],
+ "+sct "
+ "L0-1c0-1p0n0"
+ ":L2-3c0-1n1p1"
+ ":L4-5c0-1n2p2"
+ ":L6-7c0-1p3n3"
+ ":L8-9c0-1p4n4"
+ ":L10-11c0-1n5p5")
after
- restore_erl_rel_flags(OldRelFlags)
+ restore_erl_rel_flags(OldRelFlags)
end,
- ?line ok.
+ ok.
cpu_topology_test(Config, Topology, Cmd) ->
- ?line ?t:format("Testing~n ~p~n ~p~n", [Topology, Cmd]),
- ?line cpu_topology_bif_test(Config, Topology),
- ?line cpu_topology_cmdline_test(Config, Topology, Cmd),
- ?line ok.
+ io:format("Testing~n ~p~n ~p~n", [Topology, Cmd]),
+ cpu_topology_bif_test(Config, Topology),
+ cpu_topology_cmdline_test(Config, Topology, Cmd),
+ ok.
cpu_topology_bif_test(_Config, false) ->
- ?line ok;
+ ok;
cpu_topology_bif_test(Config, Topology) ->
- ?line {ok, Node} = start_node(Config),
- ?line _ = rpc:call(Node, erlang, system_flag, [cpu_topology, Topology]),
- ?line cmp(Topology, rpc:call(Node, erlang, system_info, [cpu_topology])),
- ?line stop_node(Node),
- ?line ok.
+ {ok, Node} = start_node(Config),
+ _ = rpc:call(Node, erlang, system_flag, [cpu_topology, Topology]),
+ cmp(Topology, rpc:call(Node, erlang, system_info, [cpu_topology])),
+ stop_node(Node),
+ ok.
cpu_topology_cmdline_test(_Config, _Topology, false) ->
- ?line ok;
+ ok;
cpu_topology_cmdline_test(Config, Topology, Cmd) ->
- ?line {ok, Node} = start_node(Config, Cmd),
- ?line cmp(Topology, rpc:call(Node, erlang, system_info, [cpu_topology])),
- ?line stop_node(Node),
- ?line ok.
+ {ok, Node} = start_node(Config, Cmd),
+ cmp(Topology, rpc:call(Node, erlang, system_info, [cpu_topology])),
+ stop_node(Node),
+ ok.
update_cpu_info(Config) when is_list(Config) ->
- ?line OldOnline = erlang:system_info(schedulers_online),
- ?line OldAff = get_affinity_mask(),
- ?line ?t:format("START - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n",
+ OldOnline = erlang:system_info(schedulers_online),
+ OldAff = get_affinity_mask(),
+ io:format("START - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n",
[OldAff, OldOnline, erlang:system_info(scheduler_bindings)]),
- ?line case {erlang:system_info(logical_processors_available), OldAff} of
+ case {erlang:system_info(logical_processors_available), OldAff} of
{Avail, _} when Avail == unknown; OldAff == unknown ->
%% Nothing much to test; just a smoke test
case erlang:system_info(update_cpu_info) of
- unchanged -> ?line ok;
- changed -> ?line ok
+ unchanged -> ok;
+ changed -> ok
end;
_ ->
try
- ?line adjust_schedulers_online(),
+ adjust_schedulers_online(),
case erlang:system_info(schedulers_online) of
1 ->
%% Nothing much to test; just a smoke test
- ?line ok;
+ ok;
Onln0 ->
%% unset least significant bit
- ?line Aff = (OldAff band (OldAff - 1)),
- ?line set_affinity_mask(Aff),
- ?line Onln1 = Onln0 - 1,
- ?line case adjust_schedulers_online() of
+ Aff = (OldAff band (OldAff - 1)),
+ set_affinity_mask(Aff),
+ Onln1 = Onln0 - 1,
+ case adjust_schedulers_online() of
{Onln0, Onln1} ->
- ?line Onln1 = erlang:system_info(schedulers_online),
- ?line receive after 500 -> ok end,
- ?line ?t:format("TEST - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n",
+ Onln1 = erlang:system_info(schedulers_online),
+ receive after 500 -> ok end,
+ io:format("TEST - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n",
[Aff, Onln1, erlang:system_info(scheduler_bindings)]),
- ?line unchanged = adjust_schedulers_online(),
- ?line ok;
+ unchanged = adjust_schedulers_online(),
+ ok;
Fail ->
- ?line ?t:fail(Fail)
+ ct:fail(Fail)
end
end
after
@@ -836,7 +829,7 @@ update_cpu_info(Config) when is_list(Config) ->
adjust_schedulers_online(),
erlang:system_flag(schedulers_online, OldOnline),
receive after 500 -> ok end,
- ?t:format("END - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n",
+ io:format("END - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n",
[get_affinity_mask(),
erlang:system_info(schedulers_online),
erlang:system_info(scheduler_bindings)])
@@ -883,7 +876,7 @@ get_affinity_mask(_Port, _Status, Affinity) ->
Affinity.
get_affinity_mask() ->
- case ?t:os_type() of
+ case test_server:os_type() of
{unix, linux} ->
case catch open_port({spawn, "taskset -p " ++ os:getpid()},
[exit_status]) of
@@ -927,21 +920,21 @@ set_affinity_mask(Mask) ->
end.
sct_cmd(Config) when is_list(Config) ->
- ?line Topology = ?TOPOLOGY_A_TERM,
- ?line OldRelFlags = clear_erl_rel_flags(),
+ Topology = ?TOPOLOGY_A_TERM,
+ OldRelFlags = clear_erl_rel_flags(),
try
- ?line {ok, Node} = start_node(Config, ?TOPOLOGY_A_CMD),
- ?line cmp(Topology,
+ {ok, Node} = start_node(Config, ?TOPOLOGY_A_CMD),
+ cmp(Topology,
rpc:call(Node, erlang, system_info, [cpu_topology])),
- ?line cmp(Topology,
+ cmp(Topology,
rpc:call(Node, erlang, system_flag, [cpu_topology, Topology])),
- ?line cmp(Topology,
+ cmp(Topology,
rpc:call(Node, erlang, system_info, [cpu_topology])),
- ?line stop_node(Node)
+ stop_node(Node)
after
restore_erl_rel_flags(OldRelFlags)
end,
- ?line ok.
+ ok.
-define(BIND_TYPES,
[{"u", unbound},
@@ -965,7 +958,7 @@ sbt_cmd(Config) when is_list(Config) ->
end,
case Bind of
notsup ->
- ?line {skipped, "Binding of schedulers not supported"};
+ {skipped, "Binding of schedulers not supported"};
go_for_it ->
CpuTCmd = case erlang:system_info({cpu_topology,detected}) of
undefined ->
@@ -988,14 +981,14 @@ sbt_cmd(Config) when is_list(Config) ->
end,
case CpuTCmd of
false ->
- ?line {skipped, "Don't know how to create cpu topology"};
+ {skipped, "Don't know how to create cpu topology"};
_ ->
case erlang:system_info(logical_processors) of
LP when is_integer(LP) ->
OldRelFlags = clear_erl_rel_flags(),
try
lists:foreach(fun ({ClBt, Bt}) ->
- ?line sbt_test(Config,
+ sbt_test(Config,
CpuTCmd,
ClBt,
Bt,
@@ -1005,44 +998,44 @@ sbt_cmd(Config) when is_list(Config) ->
after
restore_erl_rel_flags(OldRelFlags)
end,
- ?line ok;
+ ok;
_ ->
- ?line {skipped,
+ {skipped,
"Don't know the amount of logical processors"}
end
end
end.
sbt_test(Config, CpuTCmd, ClBt, Bt, LP) ->
- ?line ?t:format("Testing +sbt ~s (~p)~n", [ClBt, Bt]),
- ?line LPS = integer_to_list(LP),
- ?line Cmd = CpuTCmd++" +sbt "++ClBt++" +S"++LPS++":"++LPS,
- ?line {ok, Node} = start_node(Config, Cmd),
- ?line Bt = rpc:call(Node,
+ io:format("Testing +sbt ~s (~p)~n", [ClBt, Bt]),
+ LPS = integer_to_list(LP),
+ Cmd = CpuTCmd++" +sbt "++ClBt++" +S"++LPS++":"++LPS,
+ {ok, Node} = start_node(Config, Cmd),
+ Bt = rpc:call(Node,
erlang,
system_info,
[scheduler_bind_type]),
- ?line SB = rpc:call(Node,
+ SB = rpc:call(Node,
erlang,
system_info,
[scheduler_bindings]),
- ?line ?t:format("scheduler bindings: ~p~n", [SB]),
- ?line BS = case {Bt, erlang:system_info(logical_processors_available)} of
+ io:format("scheduler bindings: ~p~n", [SB]),
+ BS = case {Bt, erlang:system_info(logical_processors_available)} of
{unbound, _} -> 0;
{_, Int} when is_integer(Int) -> Int;
{_, _} -> LP
end,
- ?line lists:foldl(fun (S, 0) ->
- ?line unbound = S,
+ lists:foldl(fun (S, 0) ->
+ unbound = S,
0;
(S, N) ->
- ?line true = is_integer(S),
+ true = is_integer(S),
N-1
end,
BS,
tuple_to_list(SB)),
- ?line stop_node(Node),
- ?line ok.
+ stop_node(Node),
+ ok.
scheduler_threads(Config) when is_list(Config) ->
SmpSupport = erlang:system_info(smp_support),
@@ -1130,6 +1123,7 @@ dirty_schedulers_online_test(true) ->
dirty_schedulers_online_smp_test(erlang:system_info(schedulers_online)).
dirty_schedulers_online_smp_test(SchedOnln) when SchedOnln < 4 -> ok;
dirty_schedulers_online_smp_test(SchedOnln) ->
+ receive after 500 -> ok end,
DirtyCPUSchedOnln = erlang:system_info(dirty_cpu_schedulers_online),
SchedOnln = DirtyCPUSchedOnln,
HalfSchedOnln = SchedOnln div 2,
@@ -1138,9 +1132,11 @@ dirty_schedulers_online_smp_test(SchedOnln) ->
HalfDirtyCPUSchedOnln = erlang:system_flag(schedulers_online, SchedOnln),
DirtyCPUSchedOnln = erlang:system_flag(dirty_cpu_schedulers_online,
HalfDirtyCPUSchedOnln),
+ receive after 500 -> ok end,
HalfDirtyCPUSchedOnln = erlang:system_info(dirty_cpu_schedulers_online),
QrtrDirtyCPUSchedOnln = HalfDirtyCPUSchedOnln div 2,
SchedOnln = erlang:system_flag(schedulers_online, HalfSchedOnln),
+ receive after 500 -> ok end,
QrtrDirtyCPUSchedOnln = erlang:system_info(dirty_cpu_schedulers_online),
ok.
@@ -1166,49 +1162,208 @@ get_dsstate(Config, Cmd) ->
stop_node(Node),
{DSCPU, DSCPUOnln, DSIO}.
+dirty_scheduler_exit(Config) when is_list(Config) ->
+ try
+ erlang:system_info(dirty_cpu_schedulers),
+ dirty_scheduler_exit_test(Config)
+ catch
+ error:badarg ->
+ {skipped, "No dirty scheduler support"}
+ end.
+
+dirty_scheduler_exit_test(Config) ->
+ {ok, Node} = start_node(Config, "+SDio 1"),
+ [ok] = mcall(Node,
+ [fun() ->
+ Path = proplists:get_value(data_dir, Config),
+ Lib = atom_to_list(?MODULE),
+ ok = erlang:load_nif(filename:join(Path,Lib), []),
+ ok = test_dirty_scheduler_exit()
+ end]),
+ stop_node(Node),
+ ok.
+
+test_dirty_scheduler_exit() ->
+ process_flag(trap_exit,true),
+ test_dse(10,[]).
+test_dse(0,Pids) ->
+ timer:sleep(100),
+ kill_dse(Pids,[]);
+test_dse(N,Pids) ->
+ Pid = spawn_link(fun dirty_sleeper/0),
+ test_dse(N-1,[Pid|Pids]).
+kill_dse([],Killed) ->
+ wait_dse(Killed);
+kill_dse([Pid|Pids],AlreadyKilled) ->
+ exit(Pid,kill),
+ kill_dse(Pids,[Pid|AlreadyKilled]).
+wait_dse([]) ->
+ ok;
+wait_dse([Pid|Pids]) ->
+ receive
+ {'EXIT',Pid,killed} ->
+ ok
+ end,
+ wait_dse(Pids).
+
+dirty_sleeper() ->
+ erlang:nif_error({error,?MODULE}).
+
+scheduler_suspend_basic(Config) when is_list(Config) ->
+ case erlang:system_info(multi_scheduling) of
+ disabled ->
+ {skip, "Nothing to test"};
+ _ ->
+ Onln = erlang:system_info(schedulers_online),
+ try
+ scheduler_suspend_basic_test()
+ after
+ erlang:system_flag(schedulers_online, Onln)
+ end
+ end.
+
+scheduler_suspend_basic_test() ->
+ %% The receives after setting scheduler states are there
+ %% since the operation is not fully synchronous. For example,
+ %% we do not wait for dirty cpu schedulers online to complete
+ %% before returning from erlang:system_flag(schedulers_online, _).
+
+ erlang:system_flag(schedulers_online,
+ erlang:system_info(schedulers)),
+ try
+ erlang:system_flag(dirty_cpu_schedulers_online,
+ erlang:system_info(dirty_cpu_schedulers)),
+ receive after 500 -> ok end
+ catch
+ _ : _ ->
+ ok
+ end,
+
+ S0 = sched_state(),
+ io:format("~p~n", [S0]),
+ {{normal,NTot0,NOnln0,NAct0},
+ {dirty_cpu,DCTot0,DCOnln0,DCAct0},
+ {dirty_io,DITot0,DIOnln0,DIAct0}} = S0,
+ enabled = erlang:system_info(multi_scheduling),
+
+ DCOne = case DCTot0 of
+ 0 -> 0;
+ _ -> 1
+ end,
+
+ blocked_normal = erlang:system_flag(multi_scheduling, block_normal),
+ blocked_normal = erlang:system_info(multi_scheduling),
+ {{normal,NTot0,NOnln0,1},
+ {dirty_cpu,DCTot0,DCOnln0,DCAct0},
+ {dirty_io,DITot0,DIOnln0,DIAct0}} = sched_state(),
+
+ NOnln0 = erlang:system_flag(schedulers_online, 1),
+ receive after 500 -> ok end,
+ {{normal,NTot0,1,1},
+ {dirty_cpu,DCTot0,DCOne,DCOne},
+ {dirty_io,DITot0,DIOnln0,DIAct0}} = sched_state(),
+
+ 1 = erlang:system_flag(schedulers_online, NOnln0),
+ receive after 500 -> ok end,
+ {{normal,NTot0,NOnln0,1},
+ {dirty_cpu,DCTot0,DCOnln0,DCAct0},
+ {dirty_io,DITot0,DIOnln0,DIAct0}} = sched_state(),
+
+ blocked = erlang:system_flag(multi_scheduling, block),
+ blocked = erlang:system_info(multi_scheduling),
+ receive after 500 -> ok end,
+ {{normal,NTot0,NOnln0,1},
+ {dirty_cpu,DCTot0,DCOnln0,0},
+ {dirty_io,DITot0,DIOnln0,0}} = sched_state(),
+
+ NOnln0 = erlang:system_flag(schedulers_online, 1),
+ receive after 500 -> ok end,
+ {{normal,NTot0,1,1},
+ {dirty_cpu,DCTot0,DCOne,0},
+ {dirty_io,DITot0,DIOnln0,0}} = sched_state(),
+
+ 1 = erlang:system_flag(schedulers_online, NOnln0),
+ receive after 500 -> ok end,
+ {{normal,NTot0,NOnln0,1},
+ {dirty_cpu,DCTot0,DCOnln0,0},
+ {dirty_io,DITot0,DIOnln0,0}} = sched_state(),
+
+ blocked = erlang:system_flag(multi_scheduling, unblock_normal),
+ blocked = erlang:system_info(multi_scheduling),
+ {{normal,NTot0,NOnln0,1},
+ {dirty_cpu,DCTot0,DCOnln0,0},
+ {dirty_io,DITot0,DIOnln0,0}} = sched_state(),
+
+ enabled = erlang:system_flag(multi_scheduling, unblock),
+ enabled = erlang:system_info(multi_scheduling),
+ receive after 500 -> ok end,
+ {{normal,NTot0,NOnln0,NAct0},
+ {dirty_cpu,DCTot0,DCOnln0,DCAct0},
+ {dirty_io,DITot0,DIOnln0,DIAct0}} = sched_state(),
+
+ NOnln0 = erlang:system_flag(schedulers_online, 1),
+ receive after 500 -> ok end,
+ {{normal,NTot0,1,1},
+ {dirty_cpu,DCTot0,DCOne,DCOne},
+ {dirty_io,DITot0,DIOnln0,DIAct0}} = sched_state(),
+
+ 1 = erlang:system_flag(schedulers_online, NOnln0),
+ receive after 500 -> ok end,
+ {{normal,NTot0,NOnln0,NAct0},
+ {dirty_cpu,DCTot0,DCOnln0,DCAct0},
+ {dirty_io,DITot0,DIOnln0,DIAct0}} = sched_state(),
+
+ ok.
+
+
scheduler_suspend(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:minutes(5)),
- ?line lists:foreach(fun (S) -> scheduler_suspend_test(Config, S) end,
+ ct:timetrap({minutes, 5}),
+ lists:foreach(fun (S) -> scheduler_suspend_test(Config, S) end,
[64, 32, 16, default]),
- ?line ?t:timetrap_cancel(Dog),
- ?line ok.
+ ok.
scheduler_suspend_test(Config, Schedulers) ->
- ?line Cmd = case Schedulers of
+ Cmd = case Schedulers of
default ->
"";
_ ->
S = integer_to_list(Schedulers),
"+S"++S++":"++S
end,
- ?line {ok, Node} = start_node(Config, Cmd),
- ?line [SState] = mcall(Node, [fun () ->
- erlang:system_info(schedulers_state)
- end]),
- ?line ?t:format("SState=~p~n", [SState]),
- ?line {Sched, SchedOnln, _SchedAvail} = SState,
- ?line true = is_integer(Sched),
- ?line [ok] = mcall(Node, [fun () -> sst0_loop(300) end]),
- ?line [ok] = mcall(Node, [fun () -> sst1_loop(300) end]),
- ?line [ok] = mcall(Node, [fun () -> sst2_loop(300) end]),
- ?line [ok, ok, ok, ok, ok] = mcall(Node,
- [fun () -> sst0_loop(200) end,
- fun () -> sst1_loop(200) end,
- fun () -> sst2_loop(200) end,
- fun () -> sst2_loop(200) end,
- fun () -> sst3_loop(Sched, 200) end]),
- ?line [SState] = mcall(Node, [fun () ->
- case Sched == SchedOnln of
- false ->
- Sched = erlang:system_flag(
- schedulers_online,
- SchedOnln);
- true ->
- ok
- end,
- erlang:system_info(schedulers_state)
- end]),
- ?line stop_node(Node),
- ?line ok.
+ {ok, Node} = start_node(Config, Cmd),
+ [SState] = mcall(Node, [fun () ->
+ erlang:system_info(schedulers_state)
+ end]),
+
+ io:format("SState=~p~n", [SState]),
+ {Sched, SchedOnln, _SchedAvail} = SState,
+ true = is_integer(Sched),
+ [ok] = mcall(Node, [fun () -> sst0_loop(300) end]),
+ [ok] = mcall(Node, [fun () -> sst1_loop(300) end]),
+ [ok] = mcall(Node, [fun () -> sst2_loop(300) end]),
+ [ok] = mcall(Node, [fun () -> sst4_loop(300) end]),
+ [ok] = mcall(Node, [fun () -> sst5_loop(300) end]),
+ [ok, ok, ok, ok,
+ ok, ok, ok] = mcall(Node,
+ [fun () -> sst0_loop(200) end,
+ fun () -> sst1_loop(200) end,
+ fun () -> sst2_loop(200) end,
+ fun () -> sst2_loop(200) end,
+ fun () -> sst3_loop(Sched, 200) end,
+ fun () -> sst4_loop(200) end,
+ fun () -> sst5_loop(200) end]),
+ [SState] = mcall(Node, [fun () ->
+ case Sched == SchedOnln of
+ false ->
+ Sched = erlang:system_flag(
+ schedulers_online,
+ SchedOnln);
+ true ->
+ ok
+ end,
+ erlang:system_info(schedulers_state)
+ end]),
+ stop_node(Node),
+ ok.
sst0_loop(0) ->
@@ -1272,270 +1427,283 @@ sst3_loop_with_dirty_schedulers(S, DS, N) ->
erlang:system_flag(dirty_cpu_schedulers_online, DS),
sst3_loop_with_dirty_schedulers(S, DS, N-1).
+sst4_loop(0) ->
+ ok;
+sst4_loop(N) ->
+ erlang:system_flag(multi_scheduling, block_normal),
+ erlang:system_flag(multi_scheduling, unblock_normal),
+ sst4_loop(N-1).
+
+sst5_loop(0) ->
+ ok;
+sst5_loop(N) ->
+ erlang:system_flag(multi_scheduling, block_normal),
+ erlang:system_flag(multi_scheduling, unblock_normal),
+ sst5_loop(N-1).
+
reader_groups(Config) when is_list(Config) ->
%% White box testing. These results are correct, but other results
%% could be too...
%% The actual tilepro64 topology
CPUT0 = [{processor,[{node,[{core,{logical,0}},
- {core,{logical,1}},
- {core,{logical,2}},
- {core,{logical,8}},
- {core,{logical,9}},
- {core,{logical,10}},
- {core,{logical,11}},
- {core,{logical,16}},
- {core,{logical,17}},
- {core,{logical,18}},
- {core,{logical,19}},
- {core,{logical,24}},
- {core,{logical,25}},
- {core,{logical,27}},
- {core,{logical,29}}]},
- {node,[{core,{logical,3}},
- {core,{logical,4}},
- {core,{logical,5}},
- {core,{logical,6}},
- {core,{logical,7}},
- {core,{logical,12}},
- {core,{logical,13}},
- {core,{logical,14}},
- {core,{logical,15}},
- {core,{logical,20}},
- {core,{logical,21}},
- {core,{logical,22}},
- {core,{logical,23}},
- {core,{logical,28}},
- {core,{logical,30}}]},
- {node,[{core,{logical,31}},
- {core,{logical,36}},
- {core,{logical,37}},
- {core,{logical,38}},
- {core,{logical,44}},
- {core,{logical,45}},
- {core,{logical,46}},
- {core,{logical,47}},
- {core,{logical,51}},
- {core,{logical,52}},
- {core,{logical,53}},
- {core,{logical,54}},
- {core,{logical,55}},
- {core,{logical,60}},
- {core,{logical,61}}]},
- {node,[{core,{logical,26}},
- {core,{logical,32}},
- {core,{logical,33}},
- {core,{logical,34}},
- {core,{logical,35}},
- {core,{logical,39}},
- {core,{logical,40}},
- {core,{logical,41}},
- {core,{logical,42}},
- {core,{logical,43}},
- {core,{logical,48}},
- {core,{logical,49}},
- {core,{logical,50}},
- {core,{logical,58}}]}]}],
-
- ?line [{0,1},{1,1},{2,1},{3,3},{4,3},{5,3},{6,3},{7,3},{8,1},{9,1},{10,1},
- {11,1},{12,3},{13,3},{14,4},{15,4},{16,2},{17,2},{18,2},{19,2},
- {20,4},{21,4},{22,4},{23,4},{24,2},{25,2},{26,7},{27,2},{28,4},
- {29,2},{30,4},{31,5},{32,7},{33,7},{34,7},{35,7},{36,5},{37,5},
- {38,5},{39,7},{40,7},{41,8},{42,8},{43,8},{44,5},{45,5},{46,5},
- {47,6},{48,8},{49,8},{50,8},{51,6},{52,6},{53,6},{54,6},{55,6},
- {58,8},{60,6},{61,6}]
- = reader_groups_map(CPUT0, 8),
+ {core,{logical,1}},
+ {core,{logical,2}},
+ {core,{logical,8}},
+ {core,{logical,9}},
+ {core,{logical,10}},
+ {core,{logical,11}},
+ {core,{logical,16}},
+ {core,{logical,17}},
+ {core,{logical,18}},
+ {core,{logical,19}},
+ {core,{logical,24}},
+ {core,{logical,25}},
+ {core,{logical,27}},
+ {core,{logical,29}}]},
+ {node,[{core,{logical,3}},
+ {core,{logical,4}},
+ {core,{logical,5}},
+ {core,{logical,6}},
+ {core,{logical,7}},
+ {core,{logical,12}},
+ {core,{logical,13}},
+ {core,{logical,14}},
+ {core,{logical,15}},
+ {core,{logical,20}},
+ {core,{logical,21}},
+ {core,{logical,22}},
+ {core,{logical,23}},
+ {core,{logical,28}},
+ {core,{logical,30}}]},
+ {node,[{core,{logical,31}},
+ {core,{logical,36}},
+ {core,{logical,37}},
+ {core,{logical,38}},
+ {core,{logical,44}},
+ {core,{logical,45}},
+ {core,{logical,46}},
+ {core,{logical,47}},
+ {core,{logical,51}},
+ {core,{logical,52}},
+ {core,{logical,53}},
+ {core,{logical,54}},
+ {core,{logical,55}},
+ {core,{logical,60}},
+ {core,{logical,61}}]},
+ {node,[{core,{logical,26}},
+ {core,{logical,32}},
+ {core,{logical,33}},
+ {core,{logical,34}},
+ {core,{logical,35}},
+ {core,{logical,39}},
+ {core,{logical,40}},
+ {core,{logical,41}},
+ {core,{logical,42}},
+ {core,{logical,43}},
+ {core,{logical,48}},
+ {core,{logical,49}},
+ {core,{logical,50}},
+ {core,{logical,58}}]}]}],
+
+ [{0,1},{1,1},{2,1},{3,3},{4,3},{5,3},{6,3},{7,3},{8,1},{9,1},{10,1},
+ {11,1},{12,3},{13,3},{14,4},{15,4},{16,2},{17,2},{18,2},{19,2},
+ {20,4},{21,4},{22,4},{23,4},{24,2},{25,2},{26,7},{27,2},{28,4},
+ {29,2},{30,4},{31,5},{32,7},{33,7},{34,7},{35,7},{36,5},{37,5},
+ {38,5},{39,7},{40,7},{41,8},{42,8},{43,8},{44,5},{45,5},{46,5},
+ {47,6},{48,8},{49,8},{50,8},{51,6},{52,6},{53,6},{54,6},{55,6},
+ {58,8},{60,6},{61,6}]
+ = reader_groups_map(CPUT0, 8),
CPUT1 = [n([p([c([t(l(0)),t(l(1)),t(l(2)),t(l(3))]),
- c([t(l(4)),t(l(5)),t(l(6)),t(l(7))]),
- c([t(l(8)),t(l(9)),t(l(10)),t(l(11))]),
- c([t(l(12)),t(l(13)),t(l(14)),t(l(15))])]),
- p([c([t(l(16)),t(l(17)),t(l(18)),t(l(19))]),
- c([t(l(20)),t(l(21)),t(l(22)),t(l(23))]),
- c([t(l(24)),t(l(25)),t(l(26)),t(l(27))]),
- c([t(l(28)),t(l(29)),t(l(30)),t(l(31))])])]),
- n([p([c([t(l(32)),t(l(33)),t(l(34)),t(l(35))]),
- c([t(l(36)),t(l(37)),t(l(38)),t(l(39))]),
- c([t(l(40)),t(l(41)),t(l(42)),t(l(43))]),
- c([t(l(44)),t(l(45)),t(l(46)),t(l(47))])]),
- p([c([t(l(48)),t(l(49)),t(l(50)),t(l(51))]),
- c([t(l(52)),t(l(53)),t(l(54)),t(l(55))]),
- c([t(l(56)),t(l(57)),t(l(58)),t(l(59))]),
- c([t(l(60)),t(l(61)),t(l(62)),t(l(63))])])]),
- n([p([c([t(l(64)),t(l(65)),t(l(66)),t(l(67))]),
- c([t(l(68)),t(l(69)),t(l(70)),t(l(71))]),
- c([t(l(72)),t(l(73)),t(l(74)),t(l(75))]),
- c([t(l(76)),t(l(77)),t(l(78)),t(l(79))])]),
- p([c([t(l(80)),t(l(81)),t(l(82)),t(l(83))]),
- c([t(l(84)),t(l(85)),t(l(86)),t(l(87))]),
- c([t(l(88)),t(l(89)),t(l(90)),t(l(91))]),
- c([t(l(92)),t(l(93)),t(l(94)),t(l(95))])])]),
- n([p([c([t(l(96)),t(l(97)),t(l(98)),t(l(99))]),
- c([t(l(100)),t(l(101)),t(l(102)),t(l(103))]),
- c([t(l(104)),t(l(105)),t(l(106)),t(l(107))]),
- c([t(l(108)),t(l(109)),t(l(110)),t(l(111))])]),
- p([c([t(l(112)),t(l(113)),t(l(114)),t(l(115))]),
- c([t(l(116)),t(l(117)),t(l(118)),t(l(119))]),
- c([t(l(120)),t(l(121)),t(l(122)),t(l(123))]),
- c([t(l(124)),t(l(125)),t(l(126)),t(l(127))])])])],
-
- ?line [{0,1},{1,1},{2,1},{3,1},{4,2},{5,2},{6,2},{7,2},{8,3},{9,3},
- {10,3},{11,3},{12,4},{13,4},{14,4},{15,4},{16,5},{17,5},{18,5},
- {19,5},{20,6},{21,6},{22,6},{23,6},{24,7},{25,7},{26,7},{27,7},
- {28,8},{29,8},{30,8},{31,8},{32,9},{33,9},{34,9},{35,9},{36,10},
- {37,10},{38,10},{39,10},{40,11},{41,11},{42,11},{43,11},{44,12},
- {45,12},{46,12},{47,12},{48,13},{49,13},{50,13},{51,13},{52,14},
- {53,14},{54,14},{55,14},{56,15},{57,15},{58,15},{59,15},{60,16},
- {61,16},{62,16},{63,16},{64,17},{65,17},{66,17},{67,17},{68,18},
- {69,18},{70,18},{71,18},{72,19},{73,19},{74,19},{75,19},{76,20},
- {77,20},{78,20},{79,20},{80,21},{81,21},{82,21},{83,21},{84,22},
- {85,22},{86,22},{87,22},{88,23},{89,23},{90,23},{91,23},{92,24},
- {93,24},{94,24},{95,24},{96,25},{97,25},{98,25},{99,25},{100,26},
- {101,26},{102,26},{103,26},{104,27},{105,27},{106,27},{107,27},
- {108,28},{109,28},{110,28},{111,28},{112,29},{113,29},{114,29},
- {115,29},{116,30},{117,30},{118,30},{119,30},{120,31},{121,31},
- {122,31},{123,31},{124,32},{125,32},{126,32},{127,32}]
- = reader_groups_map(CPUT1, 128),
-
- ?line [{0,1},{1,1},{2,1},{3,1},{4,1},{5,1},{6,1},{7,1},{8,1},{9,1},{10,1},
- {11,1},{12,1},{13,1},{14,1},{15,1},{16,1},{17,1},{18,1},{19,1},
- {20,1},{21,1},{22,1},{23,1},{24,1},{25,1},{26,1},{27,1},{28,1},
- {29,1},{30,1},{31,1},{32,1},{33,1},{34,1},{35,1},{36,1},{37,1},
- {38,1},{39,1},{40,1},{41,1},{42,1},{43,1},{44,1},{45,1},{46,1},
- {47,1},{48,1},{49,1},{50,1},{51,1},{52,1},{53,1},{54,1},{55,1},
- {56,1},{57,1},{58,1},{59,1},{60,1},{61,1},{62,1},{63,1},{64,2},
- {65,2},{66,2},{67,2},{68,2},{69,2},{70,2},{71,2},{72,2},{73,2},
- {74,2},{75,2},{76,2},{77,2},{78,2},{79,2},{80,2},{81,2},{82,2},
- {83,2},{84,2},{85,2},{86,2},{87,2},{88,2},{89,2},{90,2},{91,2},
- {92,2},{93,2},{94,2},{95,2},{96,2},{97,2},{98,2},{99,2},{100,2},
- {101,2},{102,2},{103,2},{104,2},{105,2},{106,2},{107,2},{108,2},
- {109,2},{110,2},{111,2},{112,2},{113,2},{114,2},{115,2},{116,2},
- {117,2},{118,2},{119,2},{120,2},{121,2},{122,2},{123,2},{124,2},
- {125,2},{126,2},{127,2}]
- = reader_groups_map(CPUT1, 2),
-
- ?line [{0,1},{1,1},{2,1},{3,1},{4,2},{5,2},{6,2},{7,2},{8,3},{9,3},{10,3},
- {11,3},{12,3},{13,3},{14,3},{15,3},{16,4},{17,4},{18,4},{19,4},
- {20,4},{21,4},{22,4},{23,4},{24,5},{25,5},{26,5},{27,5},{28,5},
- {29,5},{30,5},{31,5},{32,6},{33,6},{34,6},{35,6},{36,6},{37,6},
- {38,6},{39,6},{40,7},{41,7},{42,7},{43,7},{44,7},{45,7},{46,7},
- {47,7},{48,8},{49,8},{50,8},{51,8},{52,8},{53,8},{54,8},{55,8},
- {56,9},{57,9},{58,9},{59,9},{60,9},{61,9},{62,9},{63,9},{64,10},
- {65,10},{66,10},{67,10},{68,10},{69,10},{70,10},{71,10},{72,11},
- {73,11},{74,11},{75,11},{76,11},{77,11},{78,11},{79,11},{80,12},
- {81,12},{82,12},{83,12},{84,12},{85,12},{86,12},{87,12},{88,13},
- {89,13},{90,13},{91,13},{92,13},{93,13},{94,13},{95,13},{96,14},
- {97,14},{98,14},{99,14},{100,14},{101,14},{102,14},{103,14},
- {104,15},{105,15},{106,15},{107,15},{108,15},{109,15},{110,15},
- {111,15},{112,16},{113,16},{114,16},{115,16},{116,16},{117,16},
- {118,16},{119,16},{120,17},{121,17},{122,17},{123,17},{124,17},
- {125,17},{126,17},{127,17}]
- = reader_groups_map(CPUT1, 17),
-
- ?line [{0,1},{1,1},{2,1},{3,1},{4,1},{5,1},{6,1},{7,1},{8,1},{9,1},{10,1},
- {11,1},{12,1},{13,1},{14,1},{15,1},{16,2},{17,2},{18,2},{19,2},
- {20,2},{21,2},{22,2},{23,2},{24,2},{25,2},{26,2},{27,2},{28,2},
- {29,2},{30,2},{31,2},{32,3},{33,3},{34,3},{35,3},{36,3},{37,3},
- {38,3},{39,3},{40,3},{41,3},{42,3},{43,3},{44,3},{45,3},{46,3},
- {47,3},{48,4},{49,4},{50,4},{51,4},{52,4},{53,4},{54,4},{55,4},
- {56,4},{57,4},{58,4},{59,4},{60,4},{61,4},{62,4},{63,4},{64,5},
- {65,5},{66,5},{67,5},{68,5},{69,5},{70,5},{71,5},{72,5},{73,5},
- {74,5},{75,5},{76,5},{77,5},{78,5},{79,5},{80,6},{81,6},{82,6},
- {83,6},{84,6},{85,6},{86,6},{87,6},{88,6},{89,6},{90,6},{91,6},
- {92,6},{93,6},{94,6},{95,6},{96,7},{97,7},{98,7},{99,7},{100,7},
- {101,7},{102,7},{103,7},{104,7},{105,7},{106,7},{107,7},{108,7},
- {109,7},{110,7},{111,7},{112,7},{113,7},{114,7},{115,7},{116,7},
- {117,7},{118,7},{119,7},{120,7},{121,7},{122,7},{123,7},{124,7},
- {125,7},{126,7},{127,7}]
- = reader_groups_map(CPUT1, 7),
-
- ?line CPUT2 = [p([c(l(0)),c(l(1)),c(l(2)),c(l(3)),c(l(4))]),
- p([t(l(5)),t(l(6)),t(l(7)),t(l(8)),t(l(9))]),
- p([t(l(10))]),
- p([c(l(11)),c(l(12)),c(l(13))]),
- p([c(l(14)),c(l(15))])],
-
- ?line [{0,1},{1,1},{2,1},{3,1},{4,1},
- {5,2},{6,2},{7,2},{8,2},{9,2},
- {10,3},
- {11,4},{12,4},{13,4},
- {14,5},{15,5}] = reader_groups_map(CPUT2, 5),
-
-
- ?line [{0,1},{1,1},{2,2},{3,2},{4,2},
- {5,3},{6,3},{7,3},{8,3},{9,3},
- {10,4},
- {11,5},{12,5},{13,5},
- {14,6},{15,6}] = reader_groups_map(CPUT2, 6),
-
- ?line [{0,1},{1,1},{2,2},{3,2},{4,2},
- {5,3},{6,3},{7,3},{8,3},{9,3},
- {10,4},
- {11,5},{12,6},{13,6},
- {14,7},{15,7}] = reader_groups_map(CPUT2, 7),
-
- ?line [{0,1},{1,1},{2,2},{3,2},{4,2},
- {5,3},{6,3},{7,3},{8,3},{9,3},
- {10,4},
- {11,5},{12,6},{13,6},
- {14,7},{15,8}] = reader_groups_map(CPUT2, 8),
-
- ?line [{0,1},{1,2},{2,2},{3,3},{4,3},
- {5,4},{6,4},{7,4},{8,4},{9,4},
- {10,5},
- {11,6},{12,7},{13,7},
- {14,8},{15,9}] = reader_groups_map(CPUT2, 9),
-
- ?line [{0,1},{1,2},{2,2},{3,3},{4,3},
- {5,4},{6,4},{7,4},{8,4},{9,4},
- {10,5},
- {11,6},{12,7},{13,8},
- {14,9},{15,10}] = reader_groups_map(CPUT2, 10),
-
- ?line [{0,1},{1,2},{2,3},{3,4},{4,4},
- {5,5},{6,5},{7,5},{8,5},{9,5},
- {10,6},
- {11,7},{12,8},{13,9},
- {14,10},{15,11}] = reader_groups_map(CPUT2, 11),
-
- ?line [{0,1},{1,2},{2,3},{3,4},{4,5},
- {5,6},{6,6},{7,6},{8,6},{9,6},
- {10,7},
- {11,8},{12,9},{13,10},
- {14,11},{15,12}] = reader_groups_map(CPUT2, 100),
+ c([t(l(4)),t(l(5)),t(l(6)),t(l(7))]),
+ c([t(l(8)),t(l(9)),t(l(10)),t(l(11))]),
+ c([t(l(12)),t(l(13)),t(l(14)),t(l(15))])]),
+ p([c([t(l(16)),t(l(17)),t(l(18)),t(l(19))]),
+ c([t(l(20)),t(l(21)),t(l(22)),t(l(23))]),
+ c([t(l(24)),t(l(25)),t(l(26)),t(l(27))]),
+ c([t(l(28)),t(l(29)),t(l(30)),t(l(31))])])]),
+ n([p([c([t(l(32)),t(l(33)),t(l(34)),t(l(35))]),
+ c([t(l(36)),t(l(37)),t(l(38)),t(l(39))]),
+ c([t(l(40)),t(l(41)),t(l(42)),t(l(43))]),
+ c([t(l(44)),t(l(45)),t(l(46)),t(l(47))])]),
+ p([c([t(l(48)),t(l(49)),t(l(50)),t(l(51))]),
+ c([t(l(52)),t(l(53)),t(l(54)),t(l(55))]),
+ c([t(l(56)),t(l(57)),t(l(58)),t(l(59))]),
+ c([t(l(60)),t(l(61)),t(l(62)),t(l(63))])])]),
+ n([p([c([t(l(64)),t(l(65)),t(l(66)),t(l(67))]),
+ c([t(l(68)),t(l(69)),t(l(70)),t(l(71))]),
+ c([t(l(72)),t(l(73)),t(l(74)),t(l(75))]),
+ c([t(l(76)),t(l(77)),t(l(78)),t(l(79))])]),
+ p([c([t(l(80)),t(l(81)),t(l(82)),t(l(83))]),
+ c([t(l(84)),t(l(85)),t(l(86)),t(l(87))]),
+ c([t(l(88)),t(l(89)),t(l(90)),t(l(91))]),
+ c([t(l(92)),t(l(93)),t(l(94)),t(l(95))])])]),
+ n([p([c([t(l(96)),t(l(97)),t(l(98)),t(l(99))]),
+ c([t(l(100)),t(l(101)),t(l(102)),t(l(103))]),
+ c([t(l(104)),t(l(105)),t(l(106)),t(l(107))]),
+ c([t(l(108)),t(l(109)),t(l(110)),t(l(111))])]),
+ p([c([t(l(112)),t(l(113)),t(l(114)),t(l(115))]),
+ c([t(l(116)),t(l(117)),t(l(118)),t(l(119))]),
+ c([t(l(120)),t(l(121)),t(l(122)),t(l(123))]),
+ c([t(l(124)),t(l(125)),t(l(126)),t(l(127))])])])],
+
+ [{0,1},{1,1},{2,1},{3,1},{4,2},{5,2},{6,2},{7,2},{8,3},{9,3},
+ {10,3},{11,3},{12,4},{13,4},{14,4},{15,4},{16,5},{17,5},{18,5},
+ {19,5},{20,6},{21,6},{22,6},{23,6},{24,7},{25,7},{26,7},{27,7},
+ {28,8},{29,8},{30,8},{31,8},{32,9},{33,9},{34,9},{35,9},{36,10},
+ {37,10},{38,10},{39,10},{40,11},{41,11},{42,11},{43,11},{44,12},
+ {45,12},{46,12},{47,12},{48,13},{49,13},{50,13},{51,13},{52,14},
+ {53,14},{54,14},{55,14},{56,15},{57,15},{58,15},{59,15},{60,16},
+ {61,16},{62,16},{63,16},{64,17},{65,17},{66,17},{67,17},{68,18},
+ {69,18},{70,18},{71,18},{72,19},{73,19},{74,19},{75,19},{76,20},
+ {77,20},{78,20},{79,20},{80,21},{81,21},{82,21},{83,21},{84,22},
+ {85,22},{86,22},{87,22},{88,23},{89,23},{90,23},{91,23},{92,24},
+ {93,24},{94,24},{95,24},{96,25},{97,25},{98,25},{99,25},{100,26},
+ {101,26},{102,26},{103,26},{104,27},{105,27},{106,27},{107,27},
+ {108,28},{109,28},{110,28},{111,28},{112,29},{113,29},{114,29},
+ {115,29},{116,30},{117,30},{118,30},{119,30},{120,31},{121,31},
+ {122,31},{123,31},{124,32},{125,32},{126,32},{127,32}]
+ = reader_groups_map(CPUT1, 128),
+
+ [{0,1},{1,1},{2,1},{3,1},{4,1},{5,1},{6,1},{7,1},{8,1},{9,1},{10,1},
+ {11,1},{12,1},{13,1},{14,1},{15,1},{16,1},{17,1},{18,1},{19,1},
+ {20,1},{21,1},{22,1},{23,1},{24,1},{25,1},{26,1},{27,1},{28,1},
+ {29,1},{30,1},{31,1},{32,1},{33,1},{34,1},{35,1},{36,1},{37,1},
+ {38,1},{39,1},{40,1},{41,1},{42,1},{43,1},{44,1},{45,1},{46,1},
+ {47,1},{48,1},{49,1},{50,1},{51,1},{52,1},{53,1},{54,1},{55,1},
+ {56,1},{57,1},{58,1},{59,1},{60,1},{61,1},{62,1},{63,1},{64,2},
+ {65,2},{66,2},{67,2},{68,2},{69,2},{70,2},{71,2},{72,2},{73,2},
+ {74,2},{75,2},{76,2},{77,2},{78,2},{79,2},{80,2},{81,2},{82,2},
+ {83,2},{84,2},{85,2},{86,2},{87,2},{88,2},{89,2},{90,2},{91,2},
+ {92,2},{93,2},{94,2},{95,2},{96,2},{97,2},{98,2},{99,2},{100,2},
+ {101,2},{102,2},{103,2},{104,2},{105,2},{106,2},{107,2},{108,2},
+ {109,2},{110,2},{111,2},{112,2},{113,2},{114,2},{115,2},{116,2},
+ {117,2},{118,2},{119,2},{120,2},{121,2},{122,2},{123,2},{124,2},
+ {125,2},{126,2},{127,2}]
+ = reader_groups_map(CPUT1, 2),
+
+ [{0,1},{1,1},{2,1},{3,1},{4,2},{5,2},{6,2},{7,2},{8,3},{9,3},{10,3},
+ {11,3},{12,3},{13,3},{14,3},{15,3},{16,4},{17,4},{18,4},{19,4},
+ {20,4},{21,4},{22,4},{23,4},{24,5},{25,5},{26,5},{27,5},{28,5},
+ {29,5},{30,5},{31,5},{32,6},{33,6},{34,6},{35,6},{36,6},{37,6},
+ {38,6},{39,6},{40,7},{41,7},{42,7},{43,7},{44,7},{45,7},{46,7},
+ {47,7},{48,8},{49,8},{50,8},{51,8},{52,8},{53,8},{54,8},{55,8},
+ {56,9},{57,9},{58,9},{59,9},{60,9},{61,9},{62,9},{63,9},{64,10},
+ {65,10},{66,10},{67,10},{68,10},{69,10},{70,10},{71,10},{72,11},
+ {73,11},{74,11},{75,11},{76,11},{77,11},{78,11},{79,11},{80,12},
+ {81,12},{82,12},{83,12},{84,12},{85,12},{86,12},{87,12},{88,13},
+ {89,13},{90,13},{91,13},{92,13},{93,13},{94,13},{95,13},{96,14},
+ {97,14},{98,14},{99,14},{100,14},{101,14},{102,14},{103,14},
+ {104,15},{105,15},{106,15},{107,15},{108,15},{109,15},{110,15},
+ {111,15},{112,16},{113,16},{114,16},{115,16},{116,16},{117,16},
+ {118,16},{119,16},{120,17},{121,17},{122,17},{123,17},{124,17},
+ {125,17},{126,17},{127,17}]
+ = reader_groups_map(CPUT1, 17),
+
+ [{0,1},{1,1},{2,1},{3,1},{4,1},{5,1},{6,1},{7,1},{8,1},{9,1},{10,1},
+ {11,1},{12,1},{13,1},{14,1},{15,1},{16,2},{17,2},{18,2},{19,2},
+ {20,2},{21,2},{22,2},{23,2},{24,2},{25,2},{26,2},{27,2},{28,2},
+ {29,2},{30,2},{31,2},{32,3},{33,3},{34,3},{35,3},{36,3},{37,3},
+ {38,3},{39,3},{40,3},{41,3},{42,3},{43,3},{44,3},{45,3},{46,3},
+ {47,3},{48,4},{49,4},{50,4},{51,4},{52,4},{53,4},{54,4},{55,4},
+ {56,4},{57,4},{58,4},{59,4},{60,4},{61,4},{62,4},{63,4},{64,5},
+ {65,5},{66,5},{67,5},{68,5},{69,5},{70,5},{71,5},{72,5},{73,5},
+ {74,5},{75,5},{76,5},{77,5},{78,5},{79,5},{80,6},{81,6},{82,6},
+ {83,6},{84,6},{85,6},{86,6},{87,6},{88,6},{89,6},{90,6},{91,6},
+ {92,6},{93,6},{94,6},{95,6},{96,7},{97,7},{98,7},{99,7},{100,7},
+ {101,7},{102,7},{103,7},{104,7},{105,7},{106,7},{107,7},{108,7},
+ {109,7},{110,7},{111,7},{112,7},{113,7},{114,7},{115,7},{116,7},
+ {117,7},{118,7},{119,7},{120,7},{121,7},{122,7},{123,7},{124,7},
+ {125,7},{126,7},{127,7}]
+ = reader_groups_map(CPUT1, 7),
+
+ CPUT2 = [p([c(l(0)),c(l(1)),c(l(2)),c(l(3)),c(l(4))]),
+ p([t(l(5)),t(l(6)),t(l(7)),t(l(8)),t(l(9))]),
+ p([t(l(10))]),
+ p([c(l(11)),c(l(12)),c(l(13))]),
+ p([c(l(14)),c(l(15))])],
+
+ [{0,1},{1,1},{2,1},{3,1},{4,1},
+ {5,2},{6,2},{7,2},{8,2},{9,2},
+ {10,3},
+ {11,4},{12,4},{13,4},
+ {14,5},{15,5}] = reader_groups_map(CPUT2, 5),
+
+
+ [{0,1},{1,1},{2,2},{3,2},{4,2},
+ {5,3},{6,3},{7,3},{8,3},{9,3},
+ {10,4},
+ {11,5},{12,5},{13,5},
+ {14,6},{15,6}] = reader_groups_map(CPUT2, 6),
+
+ [{0,1},{1,1},{2,2},{3,2},{4,2},
+ {5,3},{6,3},{7,3},{8,3},{9,3},
+ {10,4},
+ {11,5},{12,6},{13,6},
+ {14,7},{15,7}] = reader_groups_map(CPUT2, 7),
+
+ [{0,1},{1,1},{2,2},{3,2},{4,2},
+ {5,3},{6,3},{7,3},{8,3},{9,3},
+ {10,4},
+ {11,5},{12,6},{13,6},
+ {14,7},{15,8}] = reader_groups_map(CPUT2, 8),
+
+ [{0,1},{1,2},{2,2},{3,3},{4,3},
+ {5,4},{6,4},{7,4},{8,4},{9,4},
+ {10,5},
+ {11,6},{12,7},{13,7},
+ {14,8},{15,9}] = reader_groups_map(CPUT2, 9),
+
+ [{0,1},{1,2},{2,2},{3,3},{4,3},
+ {5,4},{6,4},{7,4},{8,4},{9,4},
+ {10,5},
+ {11,6},{12,7},{13,8},
+ {14,9},{15,10}] = reader_groups_map(CPUT2, 10),
+
+ [{0,1},{1,2},{2,3},{3,4},{4,4},
+ {5,5},{6,5},{7,5},{8,5},{9,5},
+ {10,6},
+ {11,7},{12,8},{13,9},
+ {14,10},{15,11}] = reader_groups_map(CPUT2, 11),
+
+ [{0,1},{1,2},{2,3},{3,4},{4,5},
+ {5,6},{6,6},{7,6},{8,6},{9,6},
+ {10,7},
+ {11,8},{12,9},{13,10},
+ {14,11},{15,12}] = reader_groups_map(CPUT2, 100),
CPUT3 = [p([t(l(5)),t(l(6)),t(l(7)),t(l(8)),t(l(9))]),
- p([t(l(10))]),
- p([c(l(11)),c(l(12)),c(l(13))]),
- p([c(l(14)),c(l(15))]),
- p([c(l(0)),c(l(1)),c(l(2)),c(l(3)),c(l(4))])],
+ p([t(l(10))]),
+ p([c(l(11)),c(l(12)),c(l(13))]),
+ p([c(l(14)),c(l(15))]),
+ p([c(l(0)),c(l(1)),c(l(2)),c(l(3)),c(l(4))])],
- ?line [{0,5},{1,5},{2,6},{3,6},{4,6},
- {5,1},{6,1},{7,1},{8,1},{9,1},
- {10,2},{11,3},{12,3},{13,3},
- {14,4},{15,4}] = reader_groups_map(CPUT3, 6),
+ [{0,5},{1,5},{2,6},{3,6},{4,6},
+ {5,1},{6,1},{7,1},{8,1},{9,1},
+ {10,2},{11,3},{12,3},{13,3},
+ {14,4},{15,4}] = reader_groups_map(CPUT3, 6),
CPUT4 = [p([t(l(0)),t(l(1)),t(l(2)),t(l(3)),t(l(4))]),
- p([t(l(5))]),
- p([c(l(6)),c(l(7)),c(l(8))]),
- p([c(l(9)),c(l(10))]),
- p([c(l(11)),c(l(12)),c(l(13)),c(l(14)),c(l(15))])],
-
- ?line [{0,1},{1,1},{2,1},{3,1},{4,1},
- {5,2},
- {6,3},{7,3},{8,3},
- {9,4},{10,4},
- {11,5},{12,5},{13,6},{14,6},{15,6}] = reader_groups_map(CPUT4, 6),
-
- ?line [{0,1},{1,1},{2,1},{3,1},{4,1},
- {5,2},
- {6,3},{7,4},{8,4},
- {9,5},{10,5},
- {11,6},{12,6},{13,7},{14,7},{15,7}] = reader_groups_map(CPUT4, 7),
-
- ?line [{0,1},{65535,2}] = reader_groups_map([c(l(0)),c(l(65535))], 10),
-
- ?line ok.
+ p([t(l(5))]),
+ p([c(l(6)),c(l(7)),c(l(8))]),
+ p([c(l(9)),c(l(10))]),
+ p([c(l(11)),c(l(12)),c(l(13)),c(l(14)),c(l(15))])],
+
+ [{0,1},{1,1},{2,1},{3,1},{4,1},
+ {5,2},
+ {6,3},{7,3},{8,3},
+ {9,4},{10,4},
+ {11,5},{12,5},{13,6},{14,6},{15,6}] = reader_groups_map(CPUT4, 6),
+
+ [{0,1},{1,1},{2,1},{3,1},{4,1},
+ {5,2},
+ {6,3},{7,4},{8,4},
+ {9,5},{10,5},
+ {11,6},{12,6},{13,7},{14,7},{15,7}] = reader_groups_map(CPUT4, 7),
+
+ [{0,1},{65535,2}] = reader_groups_map([c(l(0)),c(l(65535))], 10),
+ ok.
reader_groups_map(CPUT, Groups) ->
@@ -1550,6 +1718,34 @@ reader_groups_map(CPUT, Groups) ->
%% Utils
%%
+sched_state() ->
+ sched_state(erlang:system_info(all_schedulers_state),
+ undefined,
+ {dirty_cpu,0,0,0},
+ {dirty_io,0,0,0}).
+
+
+sched_state([], N, DC, DI) ->
+ try
+ chk_basic(N),
+ chk_basic(DC),
+ chk_basic(DI),
+ {N, DC, DI}
+ catch
+ _ : _ ->
+ ?t:fail({inconsisten_scheduler_state, {N, DC, DI}})
+ end;
+sched_state([{normal, _, _, _} = S | Rest], _S, DC, DI) ->
+ sched_state(Rest, S, DC, DI);
+sched_state([{dirty_cpu, _, _, _} = DC | Rest], S, _DC, DI) ->
+ sched_state(Rest, S, DC, DI);
+sched_state([{dirty_io, _, _, _} = DI | Rest], S, DC, _DI) ->
+ sched_state(Rest, S, DC, DI).
+
+chk_basic({_Type, Tot, Onln, Act}) ->
+ true = Tot >= Onln,
+ true = Onln >= Act.
+
l(Id) ->
{logical, Id}.
@@ -1568,21 +1764,21 @@ n(X) ->
mcall(Node, Funs) ->
Parent = self(),
Refs = lists:map(fun (Fun) ->
- Ref = make_ref(),
- spawn_link(Node,
- fun () ->
- Res = Fun(),
- unlink(Parent),
- Parent ! {Ref, Res}
- end),
- Ref
- end, Funs),
+ Ref = make_ref(),
+ spawn_link(Node,
+ fun () ->
+ Res = Fun(),
+ unlink(Parent),
+ Parent ! {Ref, Res}
+ end),
+ Ref
+ end, Funs),
lists:map(fun (Ref) ->
- receive
- {Ref, Res} ->
- Res
- end
- end, Refs).
+ receive
+ {Ref, Res} ->
+ Res
+ end
+ end, Refs).
erl_rel_flag_var() ->
"ERL_OTP"++erlang:system_info(otp_release)++"_FLAGS".
@@ -1606,101 +1802,101 @@ restore_erl_rel_flags(OldValue) ->
ok(too_slow, _Config) ->
{comment, "Too slow system to do any actual testing..."};
ok(_Res, Config) ->
- ?config(ok_res, Config).
+ proplists:get_value(ok_res, Config).
chk_result(too_slow,
- _LWorkers,
- _NWorkers,
- _HWorkers,
- _MWorkers,
- _LNShouldWork,
- _HShouldWork,
- _MShouldWork) ->
- ?line ok;
+ _LWorkers,
+ _NWorkers,
+ _HWorkers,
+ _MWorkers,
+ _LNShouldWork,
+ _HShouldWork,
+ _MShouldWork) ->
+ ok;
chk_result([{low, L, Lmin, _Lmax},
- {normal, N, Nmin, _Nmax},
- {high, H, Hmin, _Hmax},
- {max, M, Mmin, _Mmax}] = Res,
- LWorkers,
- NWorkers,
- HWorkers,
- MWorkers,
- LNShouldWork,
- HShouldWork,
- MShouldWork) ->
- ?line ?t:format("~p~n", [Res]),
- ?line Relax = relax_limits(),
+ {normal, N, Nmin, _Nmax},
+ {high, H, Hmin, _Hmax},
+ {max, M, Mmin, _Mmax}] = Res,
+ LWorkers,
+ NWorkers,
+ HWorkers,
+ MWorkers,
+ LNShouldWork,
+ HShouldWork,
+ MShouldWork) ->
+ io:format("~p~n", [Res]),
+ Relax = relax_limits(),
case {L, N} of
- {0, 0} ->
- ?line false = LNShouldWork;
- _ ->
- ?line {LminRatioLim,
- NminRatioLim,
- LNRatioLimMin,
- LNRatioLimMax} = case Relax of
- false -> {0.5, 0.5, 0.05, 0.25};
- true -> {0.05, 0.05, 0.01, 0.4}
- end,
- ?line Lavg = L/LWorkers,
- ?line Navg = N/NWorkers,
- ?line Ratio = Lavg/Navg,
- ?line LminRatio = Lmin/Lavg,
- ?line NminRatio = Nmin/Navg,
- ?line ?t:format("low min ratio=~p~n"
- "normal min ratio=~p~n"
- "low avg=~p~n"
- "normal avg=~p~n"
- "low/normal ratio=~p~n",
- [LminRatio, NminRatio, Lavg, Navg, Ratio]),
- erlang:display({low_min_ratio, LminRatio}),
- erlang:display({normal_min_ratio, NminRatio}),
- erlang:display({low_avg, Lavg}),
- erlang:display({normal_avg, Navg}),
- erlang:display({low_normal_ratio, Ratio}),
- ?line chk_lim(LminRatioLim, LminRatio, 1.0, low_min_ratio),
- ?line chk_lim(NminRatioLim, NminRatio, 1.0, normal_min_ratio),
- ?line chk_lim(LNRatioLimMin, Ratio, LNRatioLimMax, low_normal_ratio),
- ?line true = LNShouldWork,
- ?line ok
+ {0, 0} ->
+ false = LNShouldWork;
+ _ ->
+ {LminRatioLim,
+ NminRatioLim,
+ LNRatioLimMin,
+ LNRatioLimMax} = case Relax of
+ false -> {0.5, 0.5, 0.05, 0.25};
+ true -> {0.05, 0.05, 0.01, 0.4}
+ end,
+ Lavg = L/LWorkers,
+ Navg = N/NWorkers,
+ Ratio = Lavg/Navg,
+ LminRatio = Lmin/Lavg,
+ NminRatio = Nmin/Navg,
+ io:format("low min ratio=~p~n"
+ "normal min ratio=~p~n"
+ "low avg=~p~n"
+ "normal avg=~p~n"
+ "low/normal ratio=~p~n",
+ [LminRatio, NminRatio, Lavg, Navg, Ratio]),
+ erlang:display({low_min_ratio, LminRatio}),
+ erlang:display({normal_min_ratio, NminRatio}),
+ erlang:display({low_avg, Lavg}),
+ erlang:display({normal_avg, Navg}),
+ erlang:display({low_normal_ratio, Ratio}),
+ chk_lim(LminRatioLim, LminRatio, 1.0, low_min_ratio),
+ chk_lim(NminRatioLim, NminRatio, 1.0, normal_min_ratio),
+ chk_lim(LNRatioLimMin, Ratio, LNRatioLimMax, low_normal_ratio),
+ true = LNShouldWork,
+ ok
end,
case H of
- 0 ->
- ?line false = HShouldWork;
- _ ->
- ?line HminRatioLim = case Relax of
- false -> 0.5;
- true -> 0.1
- end,
- ?line Havg = H/HWorkers,
- ?line HminRatio = Hmin/Havg,
- erlang:display({high_min_ratio, HminRatio}),
- ?line chk_lim(HminRatioLim, HminRatio, 1.0, high_min_ratio),
- ?line true = HShouldWork,
- ?line ok
+ 0 ->
+ false = HShouldWork;
+ _ ->
+ HminRatioLim = case Relax of
+ false -> 0.5;
+ true -> 0.1
+ end,
+ Havg = H/HWorkers,
+ HminRatio = Hmin/Havg,
+ erlang:display({high_min_ratio, HminRatio}),
+ chk_lim(HminRatioLim, HminRatio, 1.0, high_min_ratio),
+ true = HShouldWork,
+ ok
end,
case M of
- 0 ->
- ?line false = MShouldWork;
- _ ->
- ?line MminRatioLim = case Relax of
- false -> 0.5;
- true -> 0.1
- end,
- ?line Mavg = M/MWorkers,
- ?line MminRatio = Mmin/Mavg,
- erlang:display({max_min_ratio, MminRatio}),
- ?line chk_lim(MminRatioLim, MminRatio, 1.0, max_min_ratio),
- ?line true = MShouldWork,
- ?line ok
+ 0 ->
+ false = MShouldWork;
+ _ ->
+ MminRatioLim = case Relax of
+ false -> 0.5;
+ true -> 0.1
+ end,
+ Mavg = M/MWorkers,
+ MminRatio = Mmin/Mavg,
+ erlang:display({max_min_ratio, MminRatio}),
+ chk_lim(MminRatioLim, MminRatio, 1.0, max_min_ratio),
+ true = MShouldWork,
+ ok
end,
- ?line ok.
+ ok.
chk_lim(Min, V, Max, _What) when Min =< V, V =< Max ->
ok;
chk_lim(_Min, V, _Max, What) ->
- ?t:fail({bad, What, V}).
+ ct:fail({bad, What, V}).
snd(_Msg, []) ->
[];
@@ -1711,7 +1907,7 @@ snd(Msg, [P|Ps]) ->
relax_limits() ->
case strange_system_scale() of
Scale when Scale > 1 ->
- ?t:format("Relaxing limits~n", []),
+ io:format("Relaxing limits~n", []),
true;
_ ->
false
@@ -1836,8 +2032,8 @@ do_it(Tracer, Low, Normal, High, Max, RedsPerSchedLimit) ->
EndWait = erlang:monotonic_time(milli_seconds),
BalanceWait = EndWait-StartWait,
erlang:display({balance_wait, BalanceWait}),
- Timeout = ?DEFAULT_TIMEOUT - ?t:minutes(4) - BalanceWait,
- Res = case Timeout < ?MIN_SCHEDULER_TEST_TIMEOUT of
+ Timeout = (15 - 4)*60*1000 - BalanceWait,
+ Res = case Timeout < 60*1000 of
true ->
stop_work(Low, Normal, High, Max),
too_slow;
@@ -1907,55 +2103,55 @@ part_time_workers(N, Prio) ->
tracer(Low, Normal, High, Max) ->
receive
- {tracees, Prio, Tracees} ->
- save_tracees(Prio, Tracees),
- case Prio of
- low -> tracer(Tracees++Low, Normal, High, Max);
- normal -> tracer(Low, Tracees++Normal, High, Max);
- high -> tracer(Low, Normal, Tracees++High, Max);
- max -> tracer(Low, Normal, High, Tracees++Max)
- end;
- {get_result, Ref, Who} ->
- Delivered = erlang:trace_delivered(all),
- receive
- {trace_delivered, all, Delivered} ->
- ok
- end,
- {Lc, Nc, Hc, Mc} = read_trace(),
- GetMinMax
- = fun (Prio, Procs) ->
- LargeNum = 1 bsl 64,
- case lists:foldl(fun (P, {Mn, Mx} = MnMx) ->
- {Prio, C} = get(P),
- case C < Mn of
- true ->
- case C > Mx of
- true ->
- {C, C};
- false ->
- {C, Mx}
- end;
- false ->
- case C > Mx of
- true -> {Mn, C};
- false -> MnMx
- end
- end
- end,
- {LargeNum, 0},
- Procs) of
- {LargeNum, 0} -> {0, 0};
- Res -> Res
- end
- end,
- {Lmin, Lmax} = GetMinMax(low, Low),
- {Nmin, Nmax} = GetMinMax(normal, Normal),
- {Hmin, Hmax} = GetMinMax(high, High),
- {Mmin, Mmax} = GetMinMax(max, Max),
- Who ! {trace_result, Ref, [{low, Lc, Lmin, Lmax},
- {normal, Nc, Nmin, Nmax},
- {high, Hc, Hmin, Hmax},
- {max, Mc, Mmin, Mmax}]}
+ {tracees, Prio, Tracees} ->
+ save_tracees(Prio, Tracees),
+ case Prio of
+ low -> tracer(Tracees++Low, Normal, High, Max);
+ normal -> tracer(Low, Tracees++Normal, High, Max);
+ high -> tracer(Low, Normal, Tracees++High, Max);
+ max -> tracer(Low, Normal, High, Tracees++Max)
+ end;
+ {get_result, Ref, Who} ->
+ Delivered = erlang:trace_delivered(all),
+ receive
+ {trace_delivered, all, Delivered} ->
+ ok
+ end,
+ {Lc, Nc, Hc, Mc} = read_trace(),
+ GetMinMax
+ = fun (Prio, Procs) ->
+ LargeNum = 1 bsl 64,
+ case lists:foldl(fun (P, {Mn, Mx} = MnMx) ->
+ {Prio, C} = get(P),
+ case C < Mn of
+ true ->
+ case C > Mx of
+ true ->
+ {C, C};
+ false ->
+ {C, Mx}
+ end;
+ false ->
+ case C > Mx of
+ true -> {Mn, C};
+ false -> MnMx
+ end
+ end
+ end,
+ {LargeNum, 0},
+ Procs) of
+ {LargeNum, 0} -> {0, 0};
+ Res -> Res
+ end
+ end,
+ {Lmin, Lmax} = GetMinMax(low, Low),
+ {Nmin, Nmax} = GetMinMax(normal, Normal),
+ {Hmin, Hmax} = GetMinMax(high, High),
+ {Mmin, Mmax} = GetMinMax(max, Max),
+ Who ! {trace_result, Ref, [{low, Lc, Lmin, Lmax},
+ {normal, Nc, Nmin, Nmax},
+ {high, Hc, Hmin, Hmax},
+ {max, Mc, Mmin, Mmax}]}
end.
read_trace() ->
@@ -2031,15 +2227,15 @@ start_node(Config, Args) when is_list(Config) ->
Pa = filename:dirname(code:which(?MODULE)),
Name = list_to_atom(atom_to_list(?MODULE)
++ "-"
- ++ atom_to_list(?config(testcase, Config))
+ ++ atom_to_list(proplists:get_value(testcase, Config))
++ "-"
++ integer_to_list(erlang:system_time(seconds))
++ "-"
++ integer_to_list(erlang:unique_integer([positive]))),
- ?line ?t:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]).
+ test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]).
stop_node(Node) ->
- ?t:stop_node(Node).
+ test_server:stop_node(Node).
enable_internal_state() ->
@@ -2051,7 +2247,7 @@ enable_internal_state() ->
cmp(X, X) ->
ok;
cmp(X, Y) ->
- ?t:format("cmp failed:~n X=~p~n Y=~p~n", [X,Y]),
+ io:format("cmp failed:~n X=~p~n Y=~p~n", [X,Y]),
cmp_aux(X, Y).
@@ -2063,7 +2259,7 @@ cmp_aux(T0, T1) when is_tuple(T0), is_tuple(T1), size(T0) == size(T1) ->
cmp_aux(X, X) ->
ok;
cmp_aux(F0, F1) ->
- ?t:fail({no_match, F0, F1}).
+ ct:fail({no_match, F0, F1}).
cmp_tuple(_T0, _T1, N, Sz) when N > Sz ->
ok;
diff --git a/erts/emulator/test/scheduler_SUITE_data/Makefile.src b/erts/emulator/test/scheduler_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..859112cf19
--- /dev/null
+++ b/erts/emulator/test/scheduler_SUITE_data/Makefile.src
@@ -0,0 +1,8 @@
+
+SCHEDULER_LIBS = scheduler_SUITE@dll@
+
+all: $(SCHEDULER_LIBS)
+
+@SHLIB_RULES@
+
+$(SCHEDULER_LIBS): scheduler_SUITE.c
diff --git a/erts/emulator/test/scheduler_SUITE_data/scheduler_SUITE.c b/erts/emulator/test/scheduler_SUITE_data/scheduler_SUITE.c
new file mode 100644
index 0000000000..022858c114
--- /dev/null
+++ b/erts/emulator/test/scheduler_SUITE_data/scheduler_SUITE.c
@@ -0,0 +1,31 @@
+#include <unistd.h>
+#include "erl_nif.h"
+
+static int
+load(ErlNifEnv* env, void** priv, ERL_NIF_TERM info)
+{
+ ErlNifSysInfo sys_info;
+ enif_system_info(&sys_info, sizeof(ErlNifSysInfo));
+ if (!sys_info.smp_support || !sys_info.dirty_scheduler_support)
+ return 1;
+ return 0;
+}
+
+static ERL_NIF_TERM
+dirty_sleeper(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+#ifdef ERL_NIF_DIRTY_SCHEDULER_SUPPORT
+ sleep(3);
+#endif
+ return enif_make_atom(env, "ok");
+}
+
+static ErlNifFunc funcs[] = {
+#ifdef ERL_NIF_DIRTY_SCHEDULER_SUPPORT
+ {"dirty_sleeper", 0, dirty_sleeper, ERL_NIF_DIRTY_JOB_IO_BOUND}
+#else
+ {"dirty_sleeper", 0, dirty_sleeper, 0}
+#endif
+};
+
+ERL_NIF_INIT(scheduler_SUITE, funcs, &load, NULL, NULL, NULL);
diff --git a/erts/emulator/test/send_term_SUITE.erl b/erts/emulator/test/send_term_SUITE.erl
index 670865cd3f..75161389b1 100644
--- a/erts/emulator/test/send_term_SUITE.erl
+++ b/erts/emulator/test/send_term_SUITE.erl
@@ -20,49 +20,25 @@
-module(send_term_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,basic/1]).
--export([init_per_testcase/2,end_per_testcase/2]).
+-export([all/0, suite/0, basic/1]).
-export([generate_external_terms_files/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?t:timetrap(?t:minutes(3)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 3}}].
all() ->
[basic].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
basic(Config) when is_list(Config) ->
Drv = "send_term_drv",
- ?line P = start_driver(Config, Drv),
+ P = start_driver(Config, Drv),
- ?line [] = term(P, 0),
- ?line Self = self(),
+ [] = term(P, 0),
+ Self = self(),
{blurf,42,[],[-42,{}|"abc"++P],"kalle",3.1416,Self,#{}} = term(P, 1),
Map41 = maps:from_list([{blurf, 42},
@@ -76,36 +52,36 @@ basic(Config) when is_list(Config) ->
{3.1416, Self},
{#{}, blurf}]),
Map42 = term(P, 42),
- ?line Deep = lists:seq(0, 199),
- ?line Deep = term(P, 2),
- ?line {B1,B2} = term(P, 3),
- ?line B1 = list_to_binary(lists:seq(0, 255)),
- ?line B2 = list_to_binary(lists:seq(23, 255-17)),
+ Deep = lists:seq(0, 199),
+ Deep = term(P, 2),
+ {B1,B2} = term(P, 3),
+ B1 = list_to_binary(lists:seq(0, 255)),
+ B2 = list_to_binary(lists:seq(23, 255-17)),
%% Pid sending. We need another process.
- ?line Child = spawn_link(fun() ->
+ Child = spawn_link(fun() ->
erlang:port_command(P, [4])
end),
- ?line {Self,Child} = receive_any(),
+ {Self,Child} = receive_any(),
%% ERL_DRV_EXT2TERM
- ?line ExpectExt2Term = expected_ext2term_drv(?config(data_dir, Config)),
- ?line ExpectExt2Term = term(P, 5),
+ ExpectExt2Term = expected_ext2term_drv(proplists:get_value(data_dir, Config)),
+ ExpectExt2Term = term(P, 5),
%% ERL_DRV_INT, ERL_DRV_UINT
- ?line case erlang:system_info({wordsize, external}) of
+ case erlang:system_info({wordsize, external}) of
4 ->
- ?line {-1, 4294967295} = term(P, 6);
+ {-1, 4294967295} = term(P, 6);
8 ->
- ?line {-1, 18446744073709551615} = term(P, 6)
+ {-1, 18446744073709551615} = term(P, 6)
end,
%% ERL_DRV_BUF2BINARY
- ?line ExpectedBinTup = {<<>>,
+ ExpectedBinTup = {<<>>,
<<>>,
list_to_binary(lists:duplicate(17,17)),
list_to_binary(lists:duplicate(1024,17))},
- ?line ExpectedBinTup = term(P, 7),
+ ExpectedBinTup = term(P, 7),
%% single terms
Singles = [{[], 8}, % ERL_DRV_NIL
@@ -140,35 +116,34 @@ basic(Config) when is_list(Config) ->
{-20233590931456, 38}, % ERL_DRV_INT64
{-9223372036854775808, 39},
{#{}, 40}], % ERL_DRV_MAP
- ?line {Terms, Ops} = lists:unzip(Singles),
- ?line Terms = term(P,Ops),
+ {Terms, Ops} = lists:unzip(Singles),
+ Terms = term(P,Ops),
AFloat = term(P, 26), % ERL_DRV_FLOAT
- ?line true = AFloat < 0.001,
- ?line true = AFloat > -0.001,
+ true = AFloat < 0.001,
+ true = AFloat > -0.001,
%% Failure cases.
- ?line [] = term(P, 127),
- ?line receive
+ [] = term(P, 127),
+ receive
Any ->
- ?line io:format("Unexpected: ~p\n", [Any]),
- ?line ?t:fail()
+ ct:fail("Unexpected: ~p\n", [Any])
after 0 ->
ok
end,
- ?line ok = chk_temp_alloc(),
+ ok = chk_temp_alloc(),
%% In a private heap system, verify that there are no binaries
%% left for the process.
- ?line erlang:garbage_collect(), %Get rid of binaries.
+ erlang:garbage_collect(), %Get rid of binaries.
case erlang:system_info(heap_type) of
private ->
- ?line {binary,[]} = process_info(self(), binary);
+ {binary,[]} = process_info(self(), binary);
_ -> ok
end,
- ?line stop_driver(P, Drv),
+ stop_driver(P, Drv),
ok.
term(P, Op) ->
@@ -184,28 +159,28 @@ chk_temp_alloc() ->
case erlang:system_info({allocator,temp_alloc}) of
false ->
%% Temp alloc is not enabled
- ?line ok;
+ ok;
TIL ->
%% Verify that we havn't got anything allocated by temp_alloc
lists:foreach(
fun ({instance, _, TI}) ->
- ?line {value, {mbcs, MBCInfo}}
+ {value, {mbcs, MBCInfo}}
= lists:keysearch(mbcs, 1, TI),
- ?line {value, {blocks, 0, _, _}}
+ {value, {blocks, 0, _, _}}
= lists:keysearch(blocks, 1, MBCInfo),
- ?line {value, {sbcs, SBCInfo}}
+ {value, {sbcs, SBCInfo}}
= lists:keysearch(sbcs, 1, TI),
- ?line {value, {blocks, 0, _, _}}
+ {value, {blocks, 0, _, _}}
= lists:keysearch(blocks, 1, SBCInfo)
end,
TIL),
- ?line ok
+ ok
end.
%% Start/stop drivers.
start_driver(Config, Name) ->
- Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
erl_ddll:start(),
ok = load_driver(Path, Name),
open_port({spawn, Name}, []).
@@ -219,17 +194,17 @@ load_driver(Dir, Driver) ->
end.
stop_driver(Port, Name) ->
- ?line true = erlang:port_close(Port),
+ true = erlang:port_close(Port),
receive
{Port,Message} ->
- ?t:fail({strange_message_from_port,Message})
+ ct:fail({strange_message_from_port,Message})
after 0 ->
ok
end,
%% Unload the driver.
ok = erl_ddll:unload_driver(Name),
- ?line ok = erl_ddll:stop().
+ ok = erl_ddll:stop().
get_external_terms(DataDir) ->
{ok, Bin} = file:read_file([DataDir, "ext_terms.bin"]),
@@ -261,37 +236,36 @@ generate_external_terms_files(BaseDir) ->
RPort = hd(rpc:call(Node, erlang, ports, [])),
true = is_port(RPort),
slave:stop(Node),
- Terms =
- [{4711, -4711, [an_atom, "a list"]},
- [1000000000000000000000,-1111111111111111, "blupp!", blipp],
- {RPid, {RRef, RPort}, self(), hd(erlang:ports()), make_ref()},
- {{}, [], [], fun () -> ok end, <<"hej hopp trallalaaaaaaaaaaaaaaa">>},
- [44444444444444444444444,-44444444444, "b!", blippppppp],
- {4711, RPid, {RRef, RPort}, -4711, [an_atom, "a list"]},
- {RPid, {RRef, RPort}, hd(processes()), hd(erlang:ports())},
- {4711, -4711, [an_atom, "a list"]},
- {4711, -4711, [atom, "list"]},
- {RPid, {RRef, RPort}, hd(processes()), hd(erlang:ports())},
- {4444444444444444444,-44444, {{{{{{{{{{{{}}}}}}}}}}}}, make_ref()},
- {444444444444444444444,-44444, [[[[[[[[[[[1]]]]]]]]]]], make_ref()},
- {444444444444444444,-44444, {{{{{{{{{{{{2}}}}}}}}}}}}, make_ref()},
- {4444444444444444444444,-44444, {{{{{{{{{{{{3}}}}}}}}}}}}, make_ref()},
- {44444444444444444444,-44444, {{{{{{{{{{{{4}}}}}}}}}}}}, make_ref()},
- {4444444444444444,-44444, [[[[[[[[[[[5]]]]]]]]]]], make_ref()},
- {444444444444444444444,-44444, {{{{{{{{{{{{6}}}}}}}}}}}}, make_ref()},
- {444444444444444,-44444, {{{{{{{{{{{{7}}}}}}}}}}}}, make_ref()},
- {4444444444444444444,-44444, {{{{{{{{{{{{8}}}}}}}}}}}}, make_ref()},
- #{},
- #{1 => 11, 2 => 22, 3 => 33},
- maps:from_list([{K,K*11} || K <- lists:seq(1,100)])],
+ Terms = [{4711, -4711, [an_atom, "a list"]},
+ [1000000000000000000000,-1111111111111111, "blupp!", blipp],
+ {RPid, {RRef, RPort}, self(), hd(erlang:ports()), make_ref()},
+ {{}, [], [], fun () -> ok end, <<"hej hopp trallalaaaaaaaaaaaaaaa">>},
+ [44444444444444444444444,-44444444444, "b!", blippppppp],
+ {4711, RPid, {RRef, RPort}, -4711, [an_atom, "a list"]},
+ {RPid, {RRef, RPort}, hd(processes()), hd(erlang:ports())},
+ {4711, -4711, [an_atom, "a list"]},
+ {4711, -4711, [atom, "list"]},
+ {RPid, {RRef, RPort}, hd(processes()), hd(erlang:ports())},
+ {4444444444444444444,-44444, {{{{{{{{{{{{}}}}}}}}}}}}, make_ref()},
+ {444444444444444444444,-44444, [[[[[[[[[[[1]]]]]]]]]]], make_ref()},
+ {444444444444444444,-44444, {{{{{{{{{{{{2}}}}}}}}}}}}, make_ref()},
+ {4444444444444444444444,-44444, {{{{{{{{{{{{3}}}}}}}}}}}}, make_ref()},
+ {44444444444444444444,-44444, {{{{{{{{{{{{4}}}}}}}}}}}}, make_ref()},
+ {4444444444444444,-44444, [[[[[[[[[[[5]]]]]]]]]]], make_ref()},
+ {444444444444444444444,-44444, {{{{{{{{{{{{6}}}}}}}}}}}}, make_ref()},
+ {444444444444444,-44444, {{{{{{{{{{{{7}}}}}}}}}}}}, make_ref()},
+ {4444444444444444444,-44444, {{{{{{{{{{{{8}}}}}}}}}}}}, make_ref()},
+ #{},
+ #{1 => 11, 2 => 22, 3 => 33},
+ maps:from_list([{K,K*11} || K <- lists:seq(1,100)])],
ok = file:write_file(filename:join([BaseDir,
- "send_term_SUITE_data",
- "ext_terms.bin"]),
- term_to_binary(Terms, [compressed])),
+ "send_term_SUITE_data",
+ "ext_terms.bin"]),
+ term_to_binary(Terms, [compressed])),
{ok, IoDev} = file:open(filename:join([BaseDir,
- "send_term_SUITE_data",
- "ext_terms.h"]),
- [write]),
+ "send_term_SUITE_data",
+ "ext_terms.h"]),
+ [write]),
write_ext_terms_h(IoDev, Terms),
file:close(IoDev).
@@ -301,12 +275,12 @@ write_ext_terms_h(IoDev, Terms) ->
io:format(IoDev, "#define EXT_TERMS_H__~n",[]),
{ExtTerms, MaxSize} = make_ext_terms(Terms),
io:format(IoDev,
- "static struct {~n"
- " unsigned char ext[~p];~n"
- " int ext_size;~n"
- " unsigned char cext[~p];~n"
- " int cext_size;~n"
- "} ext_terms[] = {~n",[MaxSize, MaxSize]),
+ "static struct {~n"
+ " unsigned char ext[~p];~n"
+ " int ext_size;~n"
+ " unsigned char cext[~p];~n"
+ " int cext_size;~n"
+ "} ext_terms[] = {~n",[MaxSize, MaxSize]),
E = write_ext_terms_h(IoDev, ExtTerms, 0),
io:format(IoDev, "};~n",[]),
io:format(IoDev, "#define NO_OF_EXT_TERMS ~p~n", [E]),
diff --git a/erts/emulator/test/sensitive_SUITE.erl b/erts/emulator/test/sensitive_SUITE.erl
index 2e51712737..e2236774a7 100644
--- a/erts/emulator/test/sensitive_SUITE.erl
+++ b/erts/emulator/test/sensitive_SUITE.erl
@@ -20,28 +20,20 @@
-module(sensitive_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2,
- stickiness/1,send_trace/1,recv_trace/1,proc_trace/1,call_trace/1,
- meta_trace/1,running_trace/1,gc_trace/1,seq_trace/1,
- t_process_info/1,t_process_display/1,save_calls/1]).
+-export([all/0, suite/0,
+ stickiness/1,send_trace/1,recv_trace/1,proc_trace/1,call_trace/1,
+ meta_trace/1,running_trace/1,gc_trace/1,seq_trace/1,
+ t_process_info/1,t_process_display/1,save_calls/1]).
-export([remote_process_display/0,an_exported_function/1]).
-import(lists, [keysearch/3,foreach/2,sort/1]).
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog = ?t:timetrap(?t:minutes(5)),
- [{watchdog,Dog}|Config].
-
-end_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 5}}].
all() ->
[stickiness, send_trace, recv_trace, proc_trace,
@@ -49,164 +41,148 @@ all() ->
seq_trace, t_process_info, t_process_display,
save_calls].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
stickiness(Config) when is_list(Config) ->
- ?line {Tracer,Mref} = spawn_monitor(fun() ->
- receive after infinity -> ok end
- end),
- ?line false = process_flag(sensitive, true),
+ {Tracer,Mref} = spawn_monitor(fun() ->
+ receive after infinity -> ok end
+ end),
+ false = process_flag(sensitive, true),
put(foo, bar),
Flags = sort([send,'receive',procs,call,running,garbage_collection,
- set_on_spawn,set_on_first_spawn,set_on_link,set_on_first_link]),
- ?line foreach(fun(F) ->
- 1 = erlang:trace(self(), true, [F,{tracer,Tracer}])
- end, Flags),
- ?line foreach(fun(F) ->
- 1 = erlang:trace(self(), false, [F,{tracer,Tracer}])
- end, Flags),
- ?line 1 = erlang:trace(self(), true, [{tracer,Tracer}|Flags]),
- ?line 1 = erlang:trace(self(), false, [{tracer,Tracer}|Flags]),
-
- ?line {messages,[]} = process_info(Tracer, messages),
+ set_on_spawn,set_on_first_spawn,set_on_link,set_on_first_link]),
+ foreach(fun(F) ->
+ 1 = erlang:trace(self(), true, [F,{tracer,Tracer}])
+ end, Flags),
+ foreach(fun(F) ->
+ 1 = erlang:trace(self(), false, [F,{tracer,Tracer}])
+ end, Flags),
+ 1 = erlang:trace(self(), true, [{tracer,Tracer}|Flags]),
+ 1 = erlang:trace(self(), false, [{tracer,Tracer}|Flags]),
+
+ {messages,[]} = process_info(Tracer, messages),
exit(Tracer, kill),
receive {'DOWN',Mref,_,_,_} -> ok end,
-
+
case process_info(self(), dictionary) of
- {dictionary,[]} -> ok;
- {dictionary,_} -> ?line ?t:fail(sensitive_flag_cleared)
+ {dictionary,[]} -> ok;
+ {dictionary,_} -> ct:fail(sensitive_flag_cleared)
end,
NewTracer = spawn_link(fun() -> receive after infinity -> ok end end),
- ?line 1 = erlang:trace(self(), true, [{tracer,NewTracer}|Flags]),
- ?line Flags = sort(element(2, erlang:trace_info(self(), flags))),
- ?line {tracer,NewTracer} = erlang:trace_info(self(), tracer),
+ 1 = erlang:trace(self(), true, [{tracer,NewTracer}|Flags]),
+ Flags = sort(element(2, erlang:trace_info(self(), flags))),
+ {tracer,NewTracer} = erlang:trace_info(self(), tracer),
%% Process still sensitive. Tracer should disappear when we clear
%% all trace flags.
- ?line 1 = erlang:trace(self(), false, [{tracer,NewTracer}|Flags]),
- ?line {tracer,[]} = erlang:trace_info(self(), tracer),
+ 1 = erlang:trace(self(), false, [{tracer,NewTracer}|Flags]),
+ {tracer,[]} = erlang:trace_info(self(), tracer),
- ?line unlink(NewTracer), exit(NewTracer, kill),
+ unlink(NewTracer), exit(NewTracer, kill),
ok.
send_trace(Config) when is_list(Config) ->
- ?line {Dead,Mref} = spawn_monitor(fun() -> ok end),
+ {Dead,Mref} = spawn_monitor(fun() -> ok end),
receive {'DOWN',Mref,_,_,_} -> ok end,
- ?line Tracer = spawn_link(fun() -> receive after infinity -> ok end end),
- ?line Sink = spawn_link(fun() -> receive after infinity -> ok end end),
+ Tracer = spawn_link(fun() -> receive after infinity -> ok end end),
+ Sink = spawn_link(fun() -> receive after infinity -> ok end end),
Self = self(),
- ?line 1 = erlang:trace(self(), true, [send,{tracer,Tracer}]),
- ?line Dead ! before,
- ?line Sink ! before,
- ?line false = process_flag(sensitive, true),
- ?line Sink ! {blurf,lists:seq(1, 50)},
- ?line true = process_flag(sensitive, true),
- ?line Sink ! lists:seq(1, 100),
- ?line Dead ! forget_me,
- ?line true = process_flag(sensitive, false),
- ?line Sink ! after1,
- ?line false = process_flag(sensitive, false),
- ?line Sink ! after2,
- ?line Dead ! after2,
- ?line wait_trace(Self),
-
- ?line {messages,Messages} = process_info(Tracer, messages),
- ?line [{trace,Self,send_to_non_existing_process,before,Dead},
- {trace,Self,send,before,Sink},
- {trace,Self,send,after1,Sink},
- {trace,Self,send,after2,Sink},
- {trace,Self,send_to_non_existing_process,after2,Dead}] = Messages,
-
- ?line unlink(Tracer), exit(Tracer, kill),
- ?line unlink(Sink), exit(Sink, kill),
+ 1 = erlang:trace(self(), true, [send,{tracer,Tracer}]),
+ Dead ! before,
+ Sink ! before,
+ false = process_flag(sensitive, true),
+ Sink ! {blurf,lists:seq(1, 50)},
+ true = process_flag(sensitive, true),
+ Sink ! lists:seq(1, 100),
+ Dead ! forget_me,
+ true = process_flag(sensitive, false),
+ Sink ! after1,
+ false = process_flag(sensitive, false),
+ Sink ! after2,
+ Dead ! after2,
+ wait_trace(Self),
+
+ {messages,Messages} = process_info(Tracer, messages),
+ [{trace,Self,send_to_non_existing_process,before,Dead},
+ {trace,Self,send,before,Sink},
+ {trace,Self,send,after1,Sink},
+ {trace,Self,send,after2,Sink},
+ {trace,Self,send_to_non_existing_process,after2,Dead}] = Messages,
+
+ unlink(Tracer), exit(Tracer, kill),
+ unlink(Sink), exit(Sink, kill),
ok.
recv_trace(Config) when is_list(Config) ->
Parent = self(),
- ?line Tracer = spawn_link(fun() -> receive after infinity -> ok end end),
- ?line Sender = spawn_link(fun() -> recv_trace_sender(Parent) end),
+ Tracer = spawn_link(fun() -> receive after infinity -> ok end end),
+ Sender = spawn_link(fun() -> recv_trace_sender(Parent) end),
- ?line 1 = erlang:trace(self(), true, ['receive',{tracer,Tracer}]),
+ 1 = erlang:trace(self(), true, ['receive',{tracer,Tracer}]),
Sender ! 1,
receive a -> wait_trace(Sender) end,
- ?line false = process_flag(sensitive, true),
+ false = process_flag(sensitive, true),
Sender ! 2,
receive {b,[x,y,z]} -> wait_trace(Sender) end,
-
- ?line true = process_flag(sensitive, false),
+
+ true = process_flag(sensitive, false),
Sender ! 3,
receive c -> wait_trace(Sender) end,
-
- ?line {messages,Messages} = process_info(Tracer, messages),
+
+ {messages,Messages} = process_info(Tracer, messages),
[{trace,Parent,'receive',a},
{trace,Parent,'receive',{trace_delivered,_,_}},
{trace,Parent,'receive',c}|_] = Messages,
- ?line unlink(Tracer), exit(Tracer, kill),
- ?line unlink(Sender), exit(Sender, kill),
+ unlink(Tracer), exit(Tracer, kill),
+ unlink(Sender), exit(Sender, kill),
ok.
recv_trace_sender(Pid) ->
receive
- 1 -> Pid ! a;
- 2 -> Pid ! {b,[x,y,z]};
- 3 -> Pid ! c
+ 1 -> Pid ! a;
+ 2 -> Pid ! {b,[x,y,z]};
+ 3 -> Pid ! c
end,
recv_trace_sender(Pid).
proc_trace(Config) when is_list(Config) ->
Self = self(),
- ?line Tracer = spawn_link(fun() -> receive after infinity -> ok end end),
+ Tracer = spawn_link(fun() -> receive after infinity -> ok end end),
- ?line 1 = erlang:trace(self(), true, [procs,{tracer,Tracer}]),
- ?line false = process_flag(sensitive, true),
+ 1 = erlang:trace(self(), true, [procs,{tracer,Tracer}]),
+ false = process_flag(sensitive, true),
spawn(fun() -> ok end),
- ?line register(nisse, self()),
- ?line unregister(nisse),
- ?line link(Tracer),
- ?line unlink(Tracer),
- ?line Linker0 = spawn_link(fun() -> ok end),
+ register(nisse, self()),
+ unregister(nisse),
+ link(Tracer),
+ unlink(Tracer),
+ Linker0 = spawn_link(fun() -> ok end),
Mref0 = erlang:monitor(process, Linker0),
- ?line {_,Mref} = spawn_monitor(fun() -> link(Self), unlink(Self) end),
+ {_,Mref} = spawn_monitor(fun() -> link(Self), unlink(Self) end),
receive {'DOWN',Mref0,_,_,_} -> ok end,
receive {'DOWN',Mref,_,_,_} -> ok end,
- ?line true = process_flag(sensitive, false),
+ true = process_flag(sensitive, false),
Dead = spawn(fun() -> ok end),
- ?line register(arne, self()),
- ?line unregister(arne),
- ?line {Linker,Mref2} = spawn_monitor(fun() -> link(Self), unlink(Self) end),
+ register(arne, self()),
+ unregister(arne),
+ {Linker,Mref2} = spawn_monitor(fun() -> link(Self), unlink(Self) end),
receive {'DOWN',Mref2,_,_,_} -> ok end,
- ?line Last = spawn_link(fun() -> ok end),
+ Last = spawn_link(fun() -> ok end),
receive after 10 -> ok end,
- ?line wait_trace(all),
- ?line {messages,Messages} = process_info(Tracer, messages),
+ wait_trace(all),
+ {messages,Messages} = process_info(Tracer, messages),
[{trace,Self,spawn,Dead,{erlang,apply,_}},
{trace,Self,register,arne},
{trace,Self,unregister,arne},
@@ -217,80 +193,80 @@ proc_trace(Config) when is_list(Config) ->
{trace,Self,link,Last},
{trace,Self,getting_unlinked,Last}] = Messages,
- ?line unlink(Tracer), exit(Tracer, kill),
+ unlink(Tracer), exit(Tracer, kill),
ok.
call_trace(Config) when is_list(Config) ->
Self = self(),
- ?line Tracer = spawn_link(fun() -> receive after infinity -> ok end end),
-
- ?line 1 = erlang:trace(self(), true, [call,{tracer,Tracer}]),
- ?line 1 = erlang:trace_pattern({?MODULE,an_exported_function,1},
- true, [global]),
- ?line 1 = erlang:trace_pattern({erlang,list_to_binary,1}, true, [global]),
- ?line 1 = erlang:trace_pattern({erlang,binary_to_list,1}, true, [local]),
- ?line Local = erlang:trace_pattern({?MODULE,'_','_'}, true, [local]),
-
- ?line false = process_flag(sensitive, true),
- ?line {ok,42} = a_local_function(42),
- ?line 7 = an_exported_function(6),
- ?line <<7,8,9,10>> = list_to_binary(id([7,8,9,10])),
- ?line [42,43] = binary_to_list(id(<<42,43>>)),
- ?line true = process_flag(sensitive, false),
-
- ?line {ok,{a,b}} = a_local_function({a,b}),
- ?line 1 = an_exported_function(0),
- ?line <<1,2,3>> = list_to_binary(id([1,2,3])),
- ?line [42,43,44] = binary_to_list(id(<<42,43,44>>)),
-
- ?line wait_trace(Self),
-
- ?line {messages,Messages} = process_info(Tracer, messages),
- ?line [{trace,Self,call,{?MODULE,a_local_function,[{a,b}]}},
- {trace,Self,call,{?MODULE,an_exported_function,[0]}},
- {trace,Self,call,{?MODULE,id,[_]}},
- {trace,Self,call,{erlang,list_to_binary,[[1,2,3]]}},
- {trace,Self,call,{sensitive_SUITE,id,[<<42,43,44>>]}},
- {trace,Self,call,{erlang,binary_to_list,[<<42,43,44>>]}},
- {trace,Self,call,{?MODULE,wait_trace,[Self]}}] = Messages,
-
- ?line Local = erlang:trace_pattern({?MODULE,'_','_'}, false, [local]),
- ?line erlang:trace_pattern({erlang,'_','_'}, false, [local]),
- ?line erlang:trace_pattern({'_','_','_'}, false, [global]),
-
- ?line unlink(Tracer), exit(Tracer, kill),
+ Tracer = spawn_link(fun() -> receive after infinity -> ok end end),
+
+ 1 = erlang:trace(self(), true, [call,{tracer,Tracer}]),
+ 1 = erlang:trace_pattern({?MODULE,an_exported_function,1},
+ true, [global]),
+ 1 = erlang:trace_pattern({erlang,list_to_binary,1}, true, [global]),
+ 1 = erlang:trace_pattern({erlang,binary_to_list,1}, true, [local]),
+ Local = erlang:trace_pattern({?MODULE,'_','_'}, true, [local]),
+
+ false = process_flag(sensitive, true),
+ {ok,42} = a_local_function(42),
+ 7 = an_exported_function(6),
+ <<7,8,9,10>> = list_to_binary(id([7,8,9,10])),
+ [42,43] = binary_to_list(id(<<42,43>>)),
+ true = process_flag(sensitive, false),
+
+ {ok,{a,b}} = a_local_function({a,b}),
+ 1 = an_exported_function(0),
+ <<1,2,3>> = list_to_binary(id([1,2,3])),
+ [42,43,44] = binary_to_list(id(<<42,43,44>>)),
+
+ wait_trace(Self),
+
+ {messages,Messages} = process_info(Tracer, messages),
+ [{trace,Self,call,{?MODULE,a_local_function,[{a,b}]}},
+ {trace,Self,call,{?MODULE,an_exported_function,[0]}},
+ {trace,Self,call,{?MODULE,id,[_]}},
+ {trace,Self,call,{erlang,list_to_binary,[[1,2,3]]}},
+ {trace,Self,call,{sensitive_SUITE,id,[<<42,43,44>>]}},
+ {trace,Self,call,{erlang,binary_to_list,[<<42,43,44>>]}},
+ {trace,Self,call,{?MODULE,wait_trace,[Self]}}] = Messages,
+
+ Local = erlang:trace_pattern({?MODULE,'_','_'}, false, [local]),
+ erlang:trace_pattern({erlang,'_','_'}, false, [local]),
+ erlang:trace_pattern({'_','_','_'}, false, [global]),
+
+ unlink(Tracer), exit(Tracer, kill),
ok.
meta_trace(Config) when is_list(Config) ->
Self = self(),
- ?line Tracer = spawn_link(fun() -> receive after infinity -> ok end end),
-
- ?line Local = erlang:trace_pattern({?MODULE,'_','_'}, true, [{meta,Tracer}]),
- ?line 1 = erlang:trace_pattern({erlang,list_to_binary,1}, true, [{meta,Tracer}]),
-
- ?line false = process_flag(sensitive, true),
- ?line {ok,blurf} = a_local_function(blurf),
- ?line 100 = an_exported_function(99),
- ?line <<8,9,10>> = list_to_binary(id([8,9,10])),
- ?line true = process_flag(sensitive, false),
-
- ?line {ok,{x,y}} = a_local_function({x,y}),
- ?line 1 = an_exported_function(0),
- ?line <<10>> = list_to_binary(id([10])),
- ?line wait_trace(Self),
-
- ?line Local = erlang:trace_pattern({?MODULE,'_','_'}, false, [meta]),
- ?line 1 = erlang:trace_pattern({erlang,list_to_binary,1}, false, [meta]),
- ?line a_local_function(0),
-
- ?line {messages,Messages} = process_info(Tracer, messages),
- ?line [{trace_ts,Self,call,{?MODULE,a_local_function,[{x,y}]},{_,_,_}},
- {trace_ts,Self,call,{?MODULE,an_exported_function,[0]},{_,_,_}},
- {trace_ts,Self,call,{?MODULE,id,[_]},{_,_,_}},
- {trace_ts,Self,call,{erlang,list_to_binary,[[10]]},{_,_,_}},
- {trace_ts,Self,call,{?MODULE,wait_trace,[Self]},{_,_,_}}] = Messages,
-
- ?line unlink(Tracer), exit(Tracer, kill),
+ Tracer = spawn_link(fun() -> receive after infinity -> ok end end),
+
+ Local = erlang:trace_pattern({?MODULE,'_','_'}, true, [{meta,Tracer}]),
+ 1 = erlang:trace_pattern({erlang,list_to_binary,1}, true, [{meta,Tracer}]),
+
+ false = process_flag(sensitive, true),
+ {ok,blurf} = a_local_function(blurf),
+ 100 = an_exported_function(99),
+ <<8,9,10>> = list_to_binary(id([8,9,10])),
+ true = process_flag(sensitive, false),
+
+ {ok,{x,y}} = a_local_function({x,y}),
+ 1 = an_exported_function(0),
+ <<10>> = list_to_binary(id([10])),
+ wait_trace(Self),
+
+ Local = erlang:trace_pattern({?MODULE,'_','_'}, false, [meta]),
+ 1 = erlang:trace_pattern({erlang,list_to_binary,1}, false, [meta]),
+ a_local_function(0),
+
+ {messages,Messages} = process_info(Tracer, messages),
+ [{trace_ts,Self,call,{?MODULE,a_local_function,[{x,y}]},{_,_,_}},
+ {trace_ts,Self,call,{?MODULE,an_exported_function,[0]},{_,_,_}},
+ {trace_ts,Self,call,{?MODULE,id,[_]},{_,_,_}},
+ {trace_ts,Self,call,{erlang,list_to_binary,[[10]]},{_,_,_}},
+ {trace_ts,Self,call,{?MODULE,wait_trace,[Self]},{_,_,_}}] = Messages,
+
+ unlink(Tracer), exit(Tracer, kill),
ok.
a_local_function(A) ->
@@ -301,66 +277,66 @@ an_exported_function(X) ->
running_trace(Config) when is_list(Config) ->
Self = self(),
- ?line Tracer = spawn_link(fun() -> receive after infinity -> ok end end),
+ Tracer = spawn_link(fun() -> receive after infinity -> ok end end),
- ?line false = process_flag(sensitive, true),
- ?line 1 = erlang:trace(Self, true, [running,{tracer,Tracer}]),
+ false = process_flag(sensitive, true),
+ 1 = erlang:trace(Self, true, [running,{tracer,Tracer}]),
erlang:yield(), erlang:yield(), erlang:yield(), erlang:yield(),
erlang:yield(), erlang:yield(), erlang:yield(), erlang:yield(),
- ?line true = process_flag(sensitive, false),
+ true = process_flag(sensitive, false),
erlang:yield(),
- ?line 1 = erlang:trace(Self, false, [running,{tracer,Tracer}]),
+ 1 = erlang:trace(Self, false, [running,{tracer,Tracer}]),
- ?line wait_trace(Self),
- ?line {messages,Messages} = process_info(Tracer, messages),
- ?line [{trace,Self,out,{sensitive_SUITE,running_trace,1}},
- {trace,Self,in,{sensitive_SUITE,running_trace,1}}] = Messages,
+ wait_trace(Self),
+ {messages,Messages} = process_info(Tracer, messages),
+ [{trace,Self,out,{sensitive_SUITE,running_trace,1}},
+ {trace,Self,in,{sensitive_SUITE,running_trace,1}}] = Messages,
- ?line unlink(Tracer), exit(Tracer, kill),
+ unlink(Tracer), exit(Tracer, kill),
ok.
gc_trace(Config) when is_list(Config) ->
Self = self(),
- ?line Tracer = spawn_link(fun() -> receive after infinity -> ok end end),
+ Tracer = spawn_link(fun() -> receive after infinity -> ok end end),
- ?line false = process_flag(sensitive, true),
- ?line 1 = erlang:trace(Self, true, [garbage_collection,{tracer,Tracer}]),
+ false = process_flag(sensitive, true),
+ 1 = erlang:trace(Self, true, [garbage_collection,{tracer,Tracer}]),
erlang:garbage_collect(), erlang:garbage_collect(),
erlang:garbage_collect(), erlang:garbage_collect(),
erlang:garbage_collect(), erlang:garbage_collect(),
erlang:garbage_collect(), erlang:garbage_collect(),
- ?line true = process_flag(sensitive, false),
+ true = process_flag(sensitive, false),
erlang:garbage_collect(),
- ?line 1 = erlang:trace(Self, false, [garbage_collection,{tracer,Tracer}]),
+ 1 = erlang:trace(Self, false, [garbage_collection,{tracer,Tracer}]),
- ?line wait_trace(Self),
- ?line {messages,Messages} = process_info(Tracer, messages),
- ?line [{trace,Self,gc_start,_},{trace,Self,gc_end,_}] = Messages,
+ wait_trace(Self),
+ {messages,Messages} = process_info(Tracer, messages),
+ [{trace,Self,gc_start,_},{trace,Self,gc_end,_}] = Messages,
- ?line unlink(Tracer), exit(Tracer, kill),
+ unlink(Tracer), exit(Tracer, kill),
ok.
seq_trace(Config) when is_list(Config) ->
Self = self(),
- ?line Tracer = spawn_link(fun() -> receive after infinity -> ok end end),
- ?line seq_trace:set_system_tracer(Tracer),
-
- ?line false = process_flag(sensitive, true),
-
- ?line Echo = spawn_link(fun() ->
- receive
- {Pid,Message} ->
- Pid ! {reply,Message}
- end
- end),
- ?line Sender = spawn_link(fun() ->
- seq_trace:set_token(label, 42),
- seq_trace:set_token('receive', true),
- seq_trace:set_token(send, true),
- seq_trace:set_token(print, true),
- seq_trace:print(42, "trace started"),
- Self ! blurf
- end),
+ Tracer = spawn_link(fun() -> receive after infinity -> ok end end),
+ seq_trace:set_system_tracer(Tracer),
+
+ false = process_flag(sensitive, true),
+
+ Echo = spawn_link(fun() ->
+ receive
+ {Pid,Message} ->
+ Pid ! {reply,Message}
+ end
+ end),
+ Sender = spawn_link(fun() ->
+ seq_trace:set_token(label, 42),
+ seq_trace:set_token('receive', true),
+ seq_trace:set_token(send, true),
+ seq_trace:set_token(print, true),
+ seq_trace:print(42, "trace started"),
+ Self ! blurf
+ end),
seq_trace:set_token(label, 17),
seq_trace:set_token('receive', true),
seq_trace:set_token(send, true),
@@ -370,49 +346,49 @@ seq_trace(Config) when is_list(Config) ->
receive {reply,hello} -> ok end,
receive blurf -> ok end,
- ?line wait_trace(all),
+ wait_trace(all),
+
+ {messages,Messages} = process_info(Tracer, messages),
+ [{seq_trace,17,{'receive',{0,2},Self,Echo,{Self,hello}}},
+ {seq_trace,17,{send,{2,3},Echo,Self,{reply,hello}}}] =
+ [M || {seq_trace,17,_}=M <- Messages],
- ?line {messages,Messages} = process_info(Tracer, messages),
- ?line [{seq_trace,17,{'receive',{0,2},Self,Echo,{Self,hello}}},
- {seq_trace,17,{send,{2,3},Echo,Self,{reply,hello}}}] =
- [M || {seq_trace,17,_}=M <- Messages],
+ [{seq_trace,42,{print,{0,1},Sender,[],"trace started"}},
+ {seq_trace,42,{send,{0,2},Sender,Self,blurf}}] =
+ [M || {seq_trace,42,_}=M <- Messages],
- ?line [{seq_trace,42,{print,{0,1},Sender,[],"trace started"}},
- {seq_trace,42,{send,{0,2},Sender,Self,blurf}}] =
- [M || {seq_trace,42,_}=M <- Messages],
-
- ?line unlink(Tracer), exit(Tracer, kill),
- ?line unlink(Echo), exit(Echo, kill),
- ?line unlink(Sender), exit(Sender, kill),
+ unlink(Tracer), exit(Tracer, kill),
+ unlink(Echo), exit(Echo, kill),
+ unlink(Sender), exit(Sender, kill),
ok.
t_process_info(Config) when is_list(Config) ->
Parent = self(),
- ?line Pid = spawn_link(fun() ->
- put(foo, bar),
- false = process_flag(sensitive, true),
- Parent ! go,
- receive
- revert ->
- true = process_flag(sensitive, false),
- Parent ! go_again,
- receive never -> ok end
- end end),
+ Pid = spawn_link(fun() ->
+ put(foo, bar),
+ false = process_flag(sensitive, true),
+ Parent ! go,
+ receive
+ revert ->
+ true = process_flag(sensitive, false),
+ Parent ! go_again,
+ receive never -> ok end
+ end end),
receive go -> ok end,
- ?line put(foo, bar),
- ?line self() ! Pid ! {i,am,a,message},
+ put(foo, bar),
+ self() ! Pid ! {i,am,a,message},
- ?line false = process_flag(sensitive, true),
- ?line t_process_info_suppressed(self()),
- ?line t_process_info_suppressed(Pid),
+ false = process_flag(sensitive, true),
+ t_process_info_suppressed(self()),
+ t_process_info_suppressed(Pid),
- ?line true = process_flag(sensitive, false),
+ true = process_flag(sensitive, false),
Pid ! revert,
receive go_again -> ok end,
- ?line t_process_info_normal(self()),
- ?line t_process_info_normal(Pid),
+ t_process_info_normal(self()),
+ t_process_info_normal(Pid),
ok.
t_process_info_suppressed(Pid) ->
@@ -423,7 +399,7 @@ t_process_info_suppressed(Pid) ->
t_process_info_normal(Pid) ->
{value,{foo,bar}} = keysearch(foo, 1, my_process_info(Pid, dictionary)),
case process_info(Pid, backtrace) of
- {backtrace,Bin} when size(Bin) > 20 -> ok
+ {backtrace,Bin} when size(Bin) > 20 -> ok
end,
[{i,am,a,message}] = my_process_info(Pid, messages).
@@ -431,16 +407,16 @@ my_process_info(Pid, Tag) ->
{Tag,Value} = process_info(Pid, Tag),
All = process_info(Pid),
case keysearch(Tag, 1, All) of
- false -> Value;
- {value,{Tag,Value}} -> Value
+ false -> Value;
+ {value,{Tag,Value}} -> Value
end.
t_process_display(Config) when is_list(Config) ->
- ?line Dir = filename:dirname(code:which(?MODULE)),
- ?line Cmd = atom_to_list(lib:progname()) ++ " -noinput -pa " ++ Dir ++
- " -run " ++ ?MODULE_STRING ++ " remote_process_display",
- ?line io:put_chars(Cmd),
- ?line P = open_port({spawn,Cmd}, [in,stderr_to_stdout,eof]),
+ Dir = filename:dirname(code:which(?MODULE)),
+ Cmd = atom_to_list(lib:progname()) ++ " -noinput -pa " ++ Dir ++
+ " -run " ++ ?MODULE_STRING ++ " remote_process_display",
+ io:put_chars(Cmd),
+ P = open_port({spawn,Cmd}, [in,stderr_to_stdout,eof]),
<<"done",_/binary>> = get_all(P),
ok.
@@ -456,27 +432,26 @@ get_all(P) ->
get_all(P, Acc) ->
receive
- {P,{data,S}} ->
- get_all(P, [Acc|S]);
- {P,eof} ->
- iolist_to_binary(Acc)
+ {P,{data,S}} ->
+ get_all(P, [Acc|S]);
+ {P,eof} ->
+ iolist_to_binary(Acc)
end.
save_calls(Config) when is_list(Config) ->
process_flag(save_calls, 10),
false = process_flag(sensitive, true),
- ?line {last_calls,LastCalls} = process_info(self(), last_calls),
- ?line [{erlang,process_flag,2}] = LastCalls,
- ?line [2,4,6] = lists:map(fun(E) -> 2*E end, [1,2,3]),
- ?line {last_calls,LastCalls} = process_info(self(), last_calls),
+ {last_calls,LastCalls} = process_info(self(), last_calls),
+ [{erlang,process_flag,2}] = LastCalls,
+ [2,4,6] = lists:map(fun(E) -> 2*E end, [1,2,3]),
+ {last_calls,LastCalls} = process_info(self(), last_calls),
ok.
wait_trace(Pid) ->
Ref = erlang:trace_delivered(Pid),
receive
- {trace_delivered,Pid,Ref} -> ok
+ {trace_delivered,Pid,Ref} -> ok
end.
-
+
id(I) -> I.
-
diff --git a/erts/emulator/test/signal_SUITE.erl b/erts/emulator/test/signal_SUITE.erl
index 4aa690fb0f..63397fbbb4 100644
--- a/erts/emulator/test/signal_SUITE.erl
+++ b/erts/emulator/test/signal_SUITE.erl
@@ -28,12 +28,10 @@
-module(signal_SUITE).
-author('[email protected]').
--define(DEFAULT_TIMEOUT_SECONDS, 120).
-
%-define(line_trace, 1).
--include_lib("test_server/include/test_server.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
+-include_lib("common_test/include/ct.hrl").
+-export([all/0, suite/0,init_per_suite/1, end_per_suite/1]).
+-export([init_per_testcase/2, end_per_testcase/2]).
% Test cases
-export([xm_sig_order/1,
@@ -51,16 +49,12 @@
pending_exit_group_leader/1,
exit_before_pending_exit/1]).
--export([init_per_testcase/2, end_per_testcase/2]).
-
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(?DEFAULT_TIMEOUT_SECONDS)),
available_internal_state(true),
- ?line [{testcase, Func},{watchdog, Dog}|Config].
+ [{testcase, Func}|Config].
end_per_testcase(_Func, Config) ->
- ?line Dog = ?config(watchdog, Config),
- ?line ?t:timetrap_cancel(Dog).
+ ok.
init_per_suite(Config) ->
Config.
@@ -70,7 +64,9 @@ end_per_suite(_Config) ->
catch erts_debug:set_internal_state(not_running_optimization, true),
available_internal_state(false).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 2}}].
all() ->
[xm_sig_order, pending_exit_unlink_process,
@@ -83,41 +79,30 @@ all() ->
pending_exit_process_info_2, pending_exit_group_leader,
exit_before_pending_exit].
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-xm_sig_order(doc) -> ["Test that exit signals and messages are received "
- "in correct order"];
-xm_sig_order(suite) -> [];
+%% Test that exit signals and messages are received in correct order
xm_sig_order(Config) when is_list(Config) ->
- ?line LNode = node(),
- ?line repeat(fun () -> xm_sig_order_test(LNode) end, 1000),
- ?line {ok, RNode} = start_node(Config),
- ?line repeat(fun () -> xm_sig_order_test(RNode) end, 1000),
- ?line stop_node(RNode),
- ?line ok.
+ LNode = node(),
+ repeat(fun () -> xm_sig_order_test(LNode) end, 1000),
+ {ok, RNode} = start_node(Config),
+ repeat(fun () -> xm_sig_order_test(RNode) end, 1000),
+ stop_node(RNode),
+ ok.
xm_sig_order_test(Node) ->
- ?line P = spawn(Node, fun () -> xm_sig_order_proc() end),
- ?line M = erlang:monitor(process, P),
- ?line P ! may_reach,
- ?line P ! may_reach,
- ?line P ! may_reach,
- ?line exit(P, good_signal_order),
- ?line P ! may_not_reach,
- ?line P ! may_not_reach,
- ?line P ! may_not_reach,
- ?line receive
+ P = spawn(Node, fun () -> xm_sig_order_proc() end),
+ M = erlang:monitor(process, P),
+ P ! may_reach,
+ P ! may_reach,
+ P ! may_reach,
+ exit(P, good_signal_order),
+ P ! may_not_reach,
+ P ! may_not_reach,
+ P ! may_not_reach,
+ receive
{'DOWN', M, process, P, R} ->
- ?line good_signal_order = R
+ good_signal_order = R
end.
xm_sig_order_proc() ->
@@ -128,168 +113,149 @@ xm_sig_order_proc() ->
end,
xm_sig_order_proc().
-pending_exit_unlink_process(doc) -> [];
-pending_exit_unlink_process(suite) -> [];
pending_exit_unlink_process(Config) when is_list(Config) ->
- ?line pending_exit_test(self(), unlink).
+ pending_exit_test(self(), unlink).
-pending_exit_unlink_dist_process(doc) -> [];
-pending_exit_unlink_dist_process(suite) -> [];
pending_exit_unlink_dist_process(Config) when is_list(Config) ->
- ?line {ok, Node} = start_node(Config),
- ?line From = spawn(Node, fun () -> receive after infinity -> ok end end),
- ?line Res = pending_exit_test(From, unlink),
- ?line stop_node(Node),
- ?line Res.
-
-pending_exit_unlink_port(doc) -> [];
-pending_exit_unlink_port(suite) -> [];
+ {ok, Node} = start_node(Config),
+ From = spawn(Node, fun () -> receive after infinity -> ok end end),
+ Res = pending_exit_test(From, unlink),
+ stop_node(Node),
+ Res.
+
pending_exit_unlink_port(Config) when is_list(Config) ->
- ?line pending_exit_test(hd(erlang:ports()), unlink).
+ pending_exit_test(hd(erlang:ports()), unlink).
-pending_exit_trap_exit(doc) -> [];
-pending_exit_trap_exit(suite) -> [];
pending_exit_trap_exit(Config) when is_list(Config) ->
- ?line pending_exit_test(self(), trap_exit).
+ pending_exit_test(self(), trap_exit).
-pending_exit_receive(doc) -> [];
-pending_exit_receive(suite) -> [];
pending_exit_receive(Config) when is_list(Config) ->
- ?line pending_exit_test(self(), 'receive').
+ pending_exit_test(self(), 'receive').
-pending_exit_exit(doc) -> [];
-pending_exit_exit(suite) -> [];
pending_exit_exit(Config) when is_list(Config) ->
- ?line pending_exit_test(self(), exit).
+ pending_exit_test(self(), exit).
-pending_exit_gc(doc) -> [];
-pending_exit_gc(suite) -> [];
pending_exit_gc(Config) when is_list(Config) ->
- ?line pending_exit_test(self(), gc).
+ pending_exit_test(self(), gc).
pending_exit_test(From, Type) ->
- ?line case catch erlang:system_info(smp_support) of
- true ->
- ?line OTE = process_flag(trap_exit, true),
- ?line Ref = make_ref(),
- ?line Master = self(),
- ?line ExitBySignal = case Type of
- gc ->
- lists:duplicate(10000,
- exit_by_signal);
- _ ->
- exit_by_signal
- end,
- ?line Pid = spawn_link(
- fun () ->
- receive go -> ok end,
- false = have_pending_exit(),
- exit = fake_exit(From,
- self(),
- ExitBySignal),
- true = have_pending_exit(),
- Master ! {self(), Ref, Type},
- case Type of
- gc ->
- force_gc(),
- erlang:yield();
- unlink ->
- unlink(From);
- trap_exit ->
- process_flag(trap_exit, true);
- 'receive' ->
- receive _ -> ok
- after 0 -> ok
- end;
- exit ->
- ok
- end,
- exit(exit_by_myself)
- end),
- ?line Mon = erlang:monitor(process, Pid),
- ?line Pid ! go,
- ?line Reason = receive
- {'DOWN', Mon, process, Pid, R} ->
- ?line receive
- {Pid, Ref, Type} ->
- ?line ok
- after 0 ->
- ?line ?t:fail(premature_exit)
- end,
- ?line case Type of
- exit ->
- ?line exit_by_myself = R;
- _ ->
- ?line ExitBySignal = R
- end
- end,
- ?line receive
- {'EXIT', Pid, R2} ->
- ?line Reason = R2
- end,
- ?line process_flag(trap_exit, OTE),
- ?line ok,
- {comment,
- "Test only valid with current SMP emulator."};
- _ ->
- {skipped,
- "SMP support not enabled. "
- "Test only valid with current SMP emulator."}
- end.
+ case catch erlang:system_info(smp_support) of
+ true ->
+ OTE = process_flag(trap_exit, true),
+ Ref = make_ref(),
+ Master = self(),
+ ExitBySignal = case Type of
+ gc ->
+ lists:duplicate(10000,
+ exit_by_signal);
+ _ ->
+ exit_by_signal
+ end,
+ Pid = spawn_link(
+ fun () ->
+ receive go -> ok end,
+ false = have_pending_exit(),
+ exit = fake_exit(From,
+ self(),
+ ExitBySignal),
+ true = have_pending_exit(),
+ Master ! {self(), Ref, Type},
+ case Type of
+ gc ->
+ force_gc(),
+ erlang:yield();
+ unlink ->
+ unlink(From);
+ trap_exit ->
+ process_flag(trap_exit, true);
+ 'receive' ->
+ receive _ -> ok
+ after 0 -> ok
+ end;
+ exit ->
+ ok
+ end,
+ exit(exit_by_myself)
+ end),
+ Mon = erlang:monitor(process, Pid),
+ Pid ! go,
+ Reason = receive
+ {'DOWN', Mon, process, Pid, R} ->
+ receive
+ {Pid, Ref, Type} ->
+ ok
+ after 0 ->
+ ct:fail(premature_exit)
+ end,
+ case Type of
+ exit ->
+ exit_by_myself = R;
+ _ ->
+ ExitBySignal = R
+ end
+ end,
+ receive
+ {'EXIT', Pid, R2} ->
+ Reason = R2
+ end,
+ process_flag(trap_exit, OTE),
+ ok,
+ {comment, "Test only valid with current SMP emulator."};
+ _ ->
+ {skipped, "SMP support not enabled. Test only valid with current SMP emulator."}
+ end.
-exit_before_pending_exit(doc) -> [];
-exit_before_pending_exit(suite) -> [];
exit_before_pending_exit(Config) when is_list(Config) ->
%% This is a testcase testcase very specific to the smp
%% implementation as it is of the time of writing.
%%
%% The testcase tries to check that a process can
%% exit by itself even though it has a pending exit.
- ?line OTE = process_flag(trap_exit, true),
- ?line Master = self(),
- ?line Tester = spawn_link(
- fun () ->
- Opts = case {erlang:system_info(run_queues),
- erlang:system_info(schedulers_online)} of
- {RQ, SO} when RQ =:= 1; SO =:= 1 -> [];
- _ ->
- process_flag(scheduler, 1),
- [{scheduler, 2}]
- end,
- P = self(),
- Exiter = spawn_opt(fun () ->
- receive
- {exit_me, P, R} ->
- exit(P, R)
- end
- end, Opts),
- erlang:yield(),
- Exiter ! {exit_me, self(), exited_by_exiter},
- %% We want to get a pending exit
- %% before we exit ourselves. We
- %% don't want to be scheduled out
- %% since we will then see the
- %% pending exit.
- %%
- %% Do something that takes
- %% relatively long time but
- %% consumes few reductions...
- repeat(fun() -> erlang:system_info(procs) end,10),
- %% ... then exit.
- Master ! {self(),
- pending_exit,
- have_pending_exit()},
- exit(exited_by_myself)
- end),
- ?line PendingExit = receive {Tester, pending_exit, PE} -> PE end,
- ?line receive
+ OTE = process_flag(trap_exit, true),
+ Master = self(),
+ Tester = spawn_link(
+ fun () ->
+ Opts = case {erlang:system_info(run_queues),
+ erlang:system_info(schedulers_online)} of
+ {RQ, SO} when RQ =:= 1; SO =:= 1 -> [];
+ _ ->
+ process_flag(scheduler, 1),
+ [{scheduler, 2}]
+ end,
+ P = self(),
+ Exiter = spawn_opt(fun () ->
+ receive
+ {exit_me, P, R} ->
+ exit(P, R)
+ end
+ end, Opts),
+ erlang:yield(),
+ Exiter ! {exit_me, self(), exited_by_exiter},
+ %% We want to get a pending exit
+ %% before we exit ourselves. We
+ %% don't want to be scheduled out
+ %% since we will then see the
+ %% pending exit.
+ %%
+ %% Do something that takes
+ %% relatively long time but
+ %% consumes few reductions...
+ repeat(fun() -> erlang:system_info(procs) end,10),
+ %% ... then exit.
+ Master ! {self(),
+ pending_exit,
+ have_pending_exit()},
+ exit(exited_by_myself)
+ end),
+ PendingExit = receive {Tester, pending_exit, PE} -> PE end,
+ receive
{'EXIT', Tester, exited_by_myself} ->
- ?line process_flag(trap_exit, OTE),
- ?line ok;
+ process_flag(trap_exit, OTE),
+ ok;
Msg ->
- ?line ?t:fail({unexpected_message, Msg})
+ ct:fail({unexpected_message, Msg})
end,
NoScheds = integer_to_list(erlang:system_info(schedulers_online)),
{comment,
@@ -304,101 +270,101 @@ exit_before_pending_exit(Config) when is_list(Config) ->
-define(PE_INFO_REPEAT, 100).
pending_exit_is_process_alive(Config) when is_list(Config) ->
- ?line S = exit_op_test_init(),
- ?line TestFun = fun (P) -> false = is_process_alive(P) end,
- ?line repeated_exit_op_test(TestFun, ?PE_INFO_REPEAT),
- ?line verify_pending_exit_success(S),
- ?line comment().
+ S = exit_op_test_init(),
+ TestFun = fun (P) -> false = is_process_alive(P) end,
+ repeated_exit_op_test(TestFun, ?PE_INFO_REPEAT),
+ verify_pending_exit_success(S),
+ comment().
pending_exit_process_info_1(Config) when is_list(Config) ->
- ?line S = exit_op_test_init(),
- ?line TestFun = fun (P) ->
+ S = exit_op_test_init(),
+ TestFun = fun (P) ->
undefined = process_info(P)
end,
- ?line repeated_exit_op_test(TestFun, ?PE_INFO_REPEAT),
- ?line verify_pending_exit_success(S),
- ?line comment().
+ repeated_exit_op_test(TestFun, ?PE_INFO_REPEAT),
+ verify_pending_exit_success(S),
+ comment().
pending_exit_process_info_2(Config) when is_list(Config) ->
- ?line S0 = exit_op_test_init(),
- ?line repeated_exit_op_test(fun (P) ->
+ S0 = exit_op_test_init(),
+ repeated_exit_op_test(fun (P) ->
undefined = process_info(P, messages)
end, ?PE_INFO_REPEAT),
- ?line S1 = verify_pending_exit_success(S0),
- ?line repeated_exit_op_test(fun (P) ->
+ S1 = verify_pending_exit_success(S0),
+ repeated_exit_op_test(fun (P) ->
undefined = process_info(P, status)
end, ?PE_INFO_REPEAT),
- ?line S2 = verify_pending_exit_success(S1),
- ?line repeated_exit_op_test(fun (P) ->
+ S2 = verify_pending_exit_success(S1),
+ repeated_exit_op_test(fun (P) ->
undefined = process_info(P, links)
end, ?PE_INFO_REPEAT),
- ?line S3 = verify_pending_exit_success(S2),
- ?line repeated_exit_op_test(fun (P) ->
+ S3 = verify_pending_exit_success(S2),
+ repeated_exit_op_test(fun (P) ->
undefined = process_info(P, [messages])
end, ?PE_INFO_REPEAT),
- ?line S4 = verify_pending_exit_success(S3),
- ?line repeated_exit_op_test(fun (P) ->
+ S4 = verify_pending_exit_success(S3),
+ repeated_exit_op_test(fun (P) ->
undefined = process_info(P, [status])
end, ?PE_INFO_REPEAT),
- ?line S5 = verify_pending_exit_success(S4),
- ?line repeated_exit_op_test(fun (P) ->
+ S5 = verify_pending_exit_success(S4),
+ repeated_exit_op_test(fun (P) ->
undefined = process_info(P, [links])
end, ?PE_INFO_REPEAT),
- ?line S6 = verify_pending_exit_success(S5),
- ?line repeated_exit_op_test(fun (P) ->
+ S6 = verify_pending_exit_success(S5),
+ repeated_exit_op_test(fun (P) ->
undefined = process_info(P, [status,
links])
end, ?PE_INFO_REPEAT),
- ?line S7 = verify_pending_exit_success(S6),
- ?line repeated_exit_op_test(fun (P) ->
+ S7 = verify_pending_exit_success(S6),
+ repeated_exit_op_test(fun (P) ->
undefined = process_info(P, [messages,
status])
end, ?PE_INFO_REPEAT),
- ?line S8 = verify_pending_exit_success(S7),
- ?line repeated_exit_op_test(fun (P) ->
+ S8 = verify_pending_exit_success(S7),
+ repeated_exit_op_test(fun (P) ->
undefined = process_info(P, [messages,
links])
end, ?PE_INFO_REPEAT),
- ?line S9 = verify_pending_exit_success(S8),
- ?line repeated_exit_op_test(
+ S9 = verify_pending_exit_success(S8),
+ repeated_exit_op_test(
fun (P) ->
undefined = process_info(P, [message_queue_len,
status])
end, ?PE_INFO_REPEAT),
- ?line S10 = verify_pending_exit_success(S9),
- ?line repeated_exit_op_test(fun (P) ->
+ S10 = verify_pending_exit_success(S9),
+ repeated_exit_op_test(fun (P) ->
undefined = process_info(P, [messages,
links,
status])
end, ?PE_INFO_REPEAT),
- ?line verify_pending_exit_success(S10),
- ?line comment().
+ verify_pending_exit_success(S10),
+ comment().
pending_exit_process_display(Config) when is_list(Config) ->
- ?line S = exit_op_test_init(),
- ?line TestFun = fun (P) ->
+ S = exit_op_test_init(),
+ TestFun = fun (P) ->
badarg = try
erlang:process_display(P, backtrace)
catch
error:badarg -> badarg
end
end,
- ?line repeated_exit_op_test(TestFun, ?PE_INFO_REPEAT),
- ?line verify_pending_exit_success(S),
- ?line comment().
+ repeated_exit_op_test(TestFun, ?PE_INFO_REPEAT),
+ verify_pending_exit_success(S),
+ comment().
pending_exit_group_leader(Config) when is_list(Config) ->
- ?line S = exit_op_test_init(),
- ?line TestFun = fun (P) ->
+ S = exit_op_test_init(),
+ TestFun = fun (P) ->
badarg = try
group_leader(self(), P)
catch
error:badarg -> badarg
end
end,
- ?line repeated_exit_op_test(TestFun, ?PE_INFO_REPEAT),
- ?line verify_pending_exit_success(S),
- ?line comment().
+ repeated_exit_op_test(TestFun, ?PE_INFO_REPEAT),
+ verify_pending_exit_success(S),
+ comment().
%%
%% -- Internal utils --------------------------------------------------------
@@ -517,14 +483,14 @@ repeat(Fun, N) when is_integer(N) ->
start_node(Config) ->
Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-" ++ atom_to_list(?config(testcase, Config))
+ ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config))
++ "-" ++ integer_to_list(erlang:system_time(seconds))
++ "-" ++ integer_to_list(erlang:unique_integer([positive]))),
Pa = filename:dirname(code:which(?MODULE)),
- ?t:start_node(Name, slave, [{args, "-pa " ++ Pa}]).
+ test_server:start_node(Name, slave, [{args, "-pa " ++ Pa}]).
stop_node(Node) ->
- ?t:stop_node(Node).
+ test_server:stop_node(Node).
have_pending_exit() ->
have_pending_exit(self()).
@@ -540,15 +506,15 @@ fake_exit(From, To, Reason) ->
available_internal_state(Bool) when Bool == true; Bool == false ->
case {Bool,
- (catch erts_debug:get_internal_state(available_internal_state))} of
- {true, true} ->
- true;
- {false, true} ->
- erts_debug:set_internal_state(available_internal_state, false),
- true;
- {true, _} ->
- erts_debug:set_internal_state(available_internal_state, true),
- false;
- {false, _} ->
- false
+ (catch erts_debug:get_internal_state(available_internal_state))} of
+ {true, true} ->
+ true;
+ {false, true} ->
+ erts_debug:set_internal_state(available_internal_state, false),
+ true;
+ {true, _} ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ false;
+ {false, _} ->
+ false
end.
diff --git a/erts/emulator/test/smoke_test_SUITE.erl b/erts/emulator/test/smoke_test_SUITE.erl
index 5bb98e5ad9..900dd124c0 100644
--- a/erts/emulator/test/smoke_test_SUITE.erl
+++ b/erts/emulator/test/smoke_test_SUITE.erl
@@ -20,38 +20,21 @@
-module(smoke_test_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%-compile(export_all).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
+-export([all/0, suite/0,
init_per_testcase/2, end_per_testcase/2]).
-export([boot_combo/1, native_atomics/1, jump_table/1]).
--define(DEFAULT_TIMEOUT, ?t:minutes(2)).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 2}}].
all() ->
[boot_combo, native_atomics, jump_table].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
init_per_testcase(boot_combo = Case, Config) when is_list(Config) ->
case erlang:system_info(build_type) of
opt ->
@@ -63,12 +46,9 @@ init_per_testcase(Case, Config) when is_list(Config) ->
init_per_tc(Case, Config).
init_per_tc(Case, Config) ->
- Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
- [{testcase, Case},{watchdog, Dog}|Config].
+ [{testcase, Case}|Config].
end_per_testcase(_Case, Config) when is_list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
ok.
%%%
@@ -111,13 +91,13 @@ native_atomics(Config) when is_list(Config) ->
NA64Key = "64-bit native atomics",
DWNAKey = "Double word native atomics",
EthreadInfo = erlang:system_info(ethread_info),
- ?t:format("~p~n", [EthreadInfo]),
+ io:format("~p~n", [EthreadInfo]),
{value,{NA32Key, NA32, _}} = lists:keysearch(NA32Key, 1, EthreadInfo),
{value,{NA64Key, NA64, _}} = lists:keysearch(NA64Key, 1, EthreadInfo),
{value,{DWNAKey, DWNA, _}} = lists:keysearch(DWNAKey, 1, EthreadInfo),
case {erlang:system_info(build_type), erlang:system_info(smp_support), NA32, NA64, DWNA} of
{opt, true, "no", "no", _} ->
- ?t:fail(optimized_smp_runtime_without_native_atomics);
+ ct:fail(optimized_smp_runtime_without_native_atomics);
{_, false, "no", "no", _} ->
{comment, "No native atomics"};
_ ->
@@ -134,7 +114,7 @@ jump_table(Config) when is_list(Config) ->
false ->
case erlang:system_info(build_type) of
opt ->
- ?t:fail(optimized_without_beam_jump_table);
+ ct:fail(optimized_without_beam_jump_table);
BT ->
{comment, "No beam jump table, but build type is " ++ atom_to_list(BT)}
end
@@ -149,7 +129,7 @@ chk_boot(Config, Args, Fun) ->
true = os:putenv("ERL_ZFLAGS", Args),
Success = make_ref(),
Parent = self(),
- ?t:format("--- Testing ~s~n", [Args]),
+ io:format("--- Testing ~s~n", [Args]),
{ok, Node} = start_node(Config),
Pid = spawn_link(Node, fun () ->
Fun(),
@@ -159,7 +139,7 @@ chk_boot(Config, Args, Fun) ->
{Pid, Success} ->
Node = node(Pid),
stop_node(Node),
- ?t:format("--- Success!~n", []),
+ io:format("--- Success!~n", []),
ok
end.
@@ -170,14 +150,14 @@ start_node(Config, Args) when is_list(Config) ->
Pa = filename:dirname(code:which(?MODULE)),
Name = list_to_atom(atom_to_list(?MODULE)
++ "-"
- ++ atom_to_list(?config(testcase, Config))
+ ++ atom_to_list(proplists:get_value(testcase, Config))
++ "-"
++ integer_to_list(erlang:system_time(seconds))
++ "-"
++ integer_to_list(erlang:unique_integer([positive]))),
Opts = [{args, "-pa "++Pa++" "++Args}],
- ?t:start_node(Name, slave, Opts).
+ test_server:start_node(Name, slave, Opts).
stop_node(Node) ->
- ?t:stop_node(Node).
+ test_server:stop_node(Node).
diff --git a/erts/emulator/test/statistics_SUITE.erl b/erts/emulator/test/statistics_SUITE.erl
index a6305d453c..7d5b07f21f 100644
--- a/erts/emulator/test/statistics_SUITE.erl
+++ b/erts/emulator/test/statistics_SUITE.erl
@@ -22,40 +22,31 @@
%% Tests the statistics/1 bif.
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,
- end_per_testcase/2,
+-export([all/0, suite/0, groups/0,
wall_clock_zero_diff/1, wall_clock_update/1,
runtime_zero_diff/1,
runtime_update/1, runtime_diff/1,
run_queue_one/1,
scheduler_wall_time/1,
reductions/1, reductions_big/1, garbage_collection/1, io/1,
- badarg/1, run_queues_lengths_active_tasks/1]).
+ badarg/1, run_queues_lengths_active_tasks/1, msacc/1]).
%% Internal exports.
-export([hog/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-init_per_testcase(_, Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(300)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 4}}].
all() ->
[{group, wall_clock}, {group, runtime}, reductions,
reductions_big, {group, run_queue}, scheduler_wall_time,
garbage_collection, io, badarg,
- run_queues_lengths_active_tasks].
+ run_queues_lengths_active_tasks,
+ msacc].
groups() ->
[{wall_clock, [],
@@ -64,61 +55,42 @@ groups() ->
[runtime_zero_diff, runtime_update, runtime_diff]},
{run_queue, [], [run_queue_one]}].
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-
%%% Testing statistics(wall_clock).
-
-
-wall_clock_zero_diff(doc) ->
- "Tests that the 'Wall clock since last call' element of the result "
- "is zero when statistics(runtime) is called twice in succession.";
+%% Tests that the 'Wall clock since last call' element of the result
+%% is zero when statistics(runtime) is called twice in succession.
wall_clock_zero_diff(Config) when is_list(Config) ->
wall_clock_zero_diff1(16).
wall_clock_zero_diff1(N) when N > 0 ->
- ?line {Time, _} = statistics(wall_clock),
- ?line case statistics(wall_clock) of
- {Time, 0} -> ok;
- _ -> wall_clock_zero_diff1(N-1)
+ {Time, _} = statistics(wall_clock),
+ case statistics(wall_clock) of
+ {Time, 0} -> ok;
+ _ -> wall_clock_zero_diff1(N-1)
end;
wall_clock_zero_diff1(0) ->
- ?line test_server:fail("Difference never zero.").
+ ct:fail("Difference never zero.").
-wall_clock_update(doc) ->
- "Test that the time differences returned by two calls to "
- "statistics(wall_clock) are compatible, and are within a small number "
- "of ms of the amount of real time we waited for.";
+%% Test that the time differences returned by two calls to
+%% statistics(wall_clock) are compatible, and are within a small number
+%% of ms of the amount of real time we waited for.
wall_clock_update(Config) when is_list(Config) ->
wall_clock_update1(6).
wall_clock_update1(N) when N > 0 ->
- ?line {T1_wc_time, _} = statistics(wall_clock),
- ?line receive after 1000 -> ok end,
- ?line {T2_wc_time, Wc_Diff} = statistics(wall_clock),
-
- ?line Wc_Diff = T2_wc_time - T1_wc_time,
- ?line test_server:format("Wall clock diff = ~p; should be = 1000..1040~n",
- [Wc_Diff]),
- case ?t:is_debug() of
- false ->
- ?line true = Wc_Diff =< 1040;
- true ->
- ?line true = Wc_Diff =< 2000 %Be more tolerant in debug-compiled emulator.
+ {T1_wc_time, _} = statistics(wall_clock),
+ receive after 1000 -> ok end,
+ {T2_wc_time, Wc_Diff} = statistics(wall_clock),
+
+ Wc_Diff = T2_wc_time - T1_wc_time,
+ io:format("Wall clock diff = ~p; should be = 1000..1040~n", [Wc_Diff]),
+ case test_server:is_debug() of
+ false ->
+ true = Wc_Diff =< 1040;
+ true ->
+ true = Wc_Diff =< 2000 %Be more tolerant in debug-compiled emulator.
end,
- ?line true = Wc_Diff >= 1000,
+ true = Wc_Diff >= 1000,
wall_clock_update1(N-1);
wall_clock_update1(0) ->
ok.
@@ -127,64 +99,60 @@ wall_clock_update1(0) ->
%%% Test statistics(runtime).
-runtime_zero_diff(doc) ->
- "Tests that the difference between the times returned from two consectuitive "
- "calls to statistics(runtime) is zero.";
+%% Tests that the difference between the times returned from two consectuitive
+%% calls to statistics(runtime) is zero.
runtime_zero_diff(Config) when is_list(Config) ->
- ?line runtime_zero_diff1(16).
+ runtime_zero_diff1(16).
runtime_zero_diff1(N) when N > 0 ->
- ?line {T1, _} = statistics(runtime),
- ?line case statistics(runtime) of
- {T1, 0} -> ok;
- _ -> runtime_zero_diff1(N-1)
- end;
+ {T1, _} = statistics(runtime),
+ case statistics(runtime) of
+ {T1, 0} -> ok;
+ _ -> runtime_zero_diff1(N-1)
+ end;
runtime_zero_diff1(0) ->
- ?line test_server:fail("statistics(runtime) never returned zero difference").
+ ct:fail("statistics(runtime) never returned zero difference").
-runtime_update(doc) ->
- "Test that the statistics(runtime) returns a substanstially "
- "updated difference after running a process that takes all CPU "
- " power of the Erlang process for a second.";
+%% Test that the statistics(runtime) returns a substanstially
+%% updated difference after running a process that takes all CPU
+%% power of the Erlang process for a second.
runtime_update(Config) when is_list(Config) ->
- case ?t:is_cover() of
- false ->
- ?line process_flag(priority, high),
- do_runtime_update(10);
- true ->
- {skip,"Cover-compiled"}
+ case test_server:is_cover() of
+ false ->
+ process_flag(priority, high),
+ do_runtime_update(10);
+ true ->
+ {skip,"Cover-compiled"}
end.
do_runtime_update(0) ->
{comment,"Never close enough"};
do_runtime_update(N) ->
- ?line {T1,Diff0} = statistics(runtime),
- ?line spawn_link(fun cpu_heavy/0),
+ {T1,Diff0} = statistics(runtime),
+ spawn_link(fun cpu_heavy/0),
receive after 1000 -> ok end,
- ?line {T2,Diff} = statistics(runtime),
- ?line true = is_integer(T1+T2+Diff0+Diff),
- ?line test_server:format("T1 = ~p, T2 = ~p, Diff = ~p, T2-T1 = ~p",
- [T1,T2,Diff,T2-T1]),
- ?line if
- T2 - T1 =:= Diff, 900 =< Diff, Diff =< 1500 -> ok;
- true -> do_runtime_update(N-1)
- end.
-
+ {T2,Diff} = statistics(runtime),
+ true = is_integer(T1+T2+Diff0+Diff),
+ io:format("T1 = ~p, T2 = ~p, Diff = ~p, T2-T1 = ~p", [T1,T2,Diff,T2-T1]),
+ if
+ T2 - T1 =:= Diff, 900 =< Diff, Diff =< 1500 -> ok;
+ true -> do_runtime_update(N-1)
+ end.
+
cpu_heavy() ->
cpu_heavy().
-runtime_diff(doc) ->
- "Test that the difference between two consecutive absolute runtimes is "
- "equal to the last relative runtime. The loop runs a lot of times since "
- "the bug which this test case tests for showed up only rarely.";
+%% Test that the difference between two consecutive absolute runtimes is
+%% equal to the last relative runtime. The loop runs a lot of times since
+%% the bug which this test case tests for showed up only rarely.
runtime_diff(Config) when is_list(Config) ->
runtime_diff1(1000).
runtime_diff1(N) when N > 0 ->
- ?line {T1_wc_time, _} = statistics(runtime),
- ?line do_much(),
- ?line {T2_wc_time, Wc_Diff} = statistics(runtime),
- ?line Wc_Diff = T2_wc_time - T1_wc_time,
+ {T1_wc_time, _} = statistics(runtime),
+ do_much(),
+ {T2_wc_time, Wc_Diff} = statistics(runtime),
+ Wc_Diff = T2_wc_time - T1_wc_time,
runtime_diff1(N-1);
runtime_diff1(0) ->
ok.
@@ -202,10 +170,9 @@ do_much(N) ->
do_much(N-1).
-reductions(doc) ->
- "Test that statistics(reductions) is callable, and that "
- "Total_Reductions and Reductions_Since_Last_Call make sense. "
- "(This to fail on pre-R3A version of JAM.";
+%% Test that statistics(reductions) is callable, and that
+%% Total_Reductions and Reductions_Since_Last_Call make sense.
+%% This to fail on pre-R3A version of JAM.
reductions(Config) when is_list(Config) ->
{Reductions, _} = statistics(reductions),
@@ -218,13 +185,13 @@ reductions(Config) when is_list(Config) ->
reductions(300, Reductions, Mask).
reductions(N, Previous, Mask) when N > 0 ->
- ?line {Reductions, Diff} = statistics(reductions),
- ?line build_some_garbage(),
- ?line if Reductions > 0 -> ok end,
- ?line if Diff >= 0 -> ok end,
+ {Reductions, Diff} = statistics(reductions),
+ build_some_garbage(),
+ if Reductions > 0 -> ok end,
+ if Diff >= 0 -> ok end,
io:format("Previous = ~p, Reductions = ~p, Diff = ~p, DiffShouldBe = ~p",
- [Previous, Reductions, Diff, (Reductions-Previous) band Mask]),
- ?line if Reductions == ((Previous+Diff) band Mask) -> reductions(N-1, Reductions, Mask) end;
+ [Previous, Reductions, Diff, (Reductions-Previous) band Mask]),
+ if Reductions == ((Previous+Diff) band Mask) -> reductions(N-1, Reductions, Mask) end;
reductions(0, _, _) ->
ok.
@@ -233,126 +200,123 @@ build_some_garbage() ->
%% a garbage collection in the scheduler.
processes().
-reductions_big(doc) ->
- "Test that the number of reductions can be returned as a big number.";
+%% Test that the number of reductions can be returned as a big number.
reductions_big(Config) when is_list(Config) ->
- ?line reductions_big_loop(),
+ reductions_big_loop(),
ok.
reductions_big_loop() ->
erlang:yield(),
case statistics(reductions) of
- {Red, Diff} when Red >= 16#7ffFFFF ->
- ok = io:format("Reductions = ~w, Diff = ~w", [Red, Diff]);
- _ ->
- reductions_big_loop()
+ {Red, Diff} when Red >= 16#7ffFFFF ->
+ ok = io:format("Reductions = ~w, Diff = ~w", [Red, Diff]);
+ _ ->
+ reductions_big_loop()
end.
%%% Tests of statistics(run_queue).
-run_queue_one(doc) ->
- "Tests that statistics(run_queue) returns 1 if we start a "
- "CPU-bound process.";
+%% Tests that statistics(run_queue) returns 1 if we start a
+%% CPU-bound process.
run_queue_one(Config) when is_list(Config) ->
- ?line MS = erlang:system_flag(multi_scheduling, block),
- ?line run_queue_one_test(Config),
- ?line erlang:system_flag(multi_scheduling, unblock),
+ MS = erlang:system_flag(multi_scheduling, block),
+ run_queue_one_test(Config),
+ erlang:system_flag(multi_scheduling, unblock),
case MS of
- blocked ->
- {comment,
- "Multi-scheduling blocked during test. This test-case "
- "was not written to work with multiple schedulers."};
- _ -> ok
+ blocked ->
+ {comment,
+ "Multi-scheduling blocked during test. This test-case "
+ "was not written to work with multiple schedulers."};
+ _ -> ok
end.
-
+
run_queue_one_test(Config) when is_list(Config) ->
- ?line _Hog = spawn_link(?MODULE, hog, [self()]),
- ?line receive
- hog_started -> ok
- end,
- ?line receive after 100 -> ok end, % Give hog a head start.
- ?line case statistics(run_queue) of
- N when N >= 1 -> ok;
- Other -> ?line ?t:fail({unexpected,Other})
- end,
+ _Hog = spawn_link(?MODULE, hog, [self()]),
+ receive
+ hog_started -> ok
+ end,
+ receive after 100 -> ok end, % Give hog a head start.
+ case statistics(run_queue) of
+ N when N >= 1 -> ok;
+ Other -> ct:fail({unexpected,Other})
+ end,
ok.
%% CPU-bound process, going at low priority. It will always be ready
%% to run.
hog(Pid) ->
- ?line process_flag(priority, low),
- ?line Pid ! hog_started,
- ?line Mon = erlang:monitor(process, Pid),
- ?line hog_iter(0, Mon).
+ process_flag(priority, low),
+ Pid ! hog_started,
+ Mon = erlang:monitor(process, Pid),
+ hog_iter(0, Mon).
hog_iter(N, Mon) when N > 0 ->
receive
- {'DOWN', Mon, _, _, _} -> ok
+ {'DOWN', Mon, _, _, _} -> ok
after 0 ->
- ?line hog_iter(N-1, Mon)
+ hog_iter(N-1, Mon)
end;
hog_iter(0, Mon) ->
- ?line hog_iter(10000, Mon).
+ hog_iter(10000, Mon).
%%% Tests of statistics(scheduler_wall_time).
-scheduler_wall_time(doc) ->
- "Tests that statistics(scheduler_wall_time) works as intended";
+%% Tests that statistics(scheduler_wall_time) works as intended
scheduler_wall_time(Config) when is_list(Config) ->
%% Should return undefined if system_flag is not turned on yet
undefined = statistics(scheduler_wall_time),
%% Turn on statistics
false = erlang:system_flag(scheduler_wall_time, true),
try
- Schedulers = erlang:system_info(schedulers_online),
- %% Let testserver and everyone else finish their work
- timer:sleep(1500),
- %% Empty load
- EmptyLoad = get_load(),
- {false, _} = {lists:any(fun(Load) -> Load > 50 end, EmptyLoad),EmptyLoad},
- MeMySelfAndI = self(),
- StartHog = fun() ->
- Pid = spawn(?MODULE, hog, [self()]),
- receive hog_started -> MeMySelfAndI ! go end,
- Pid
- end,
- P1 = StartHog(),
- %% Max on one, the other schedulers empty (hopefully)
- %% Be generous the process can jump between schedulers
- %% which is ok and we don't want the test to fail for wrong reasons
- _L1 = [S1Load|EmptyScheds1] = get_load(),
- {true,_} = {S1Load > 50,S1Load},
- {false,_} = {lists:any(fun(Load) -> Load > 50 end, EmptyScheds1),EmptyScheds1},
- {true,_} = {lists:sum(EmptyScheds1) < 60,EmptyScheds1},
-
- %% 50% load
- HalfHogs = [StartHog() || _ <- lists:seq(1, (Schedulers-1) div 2)],
- HalfLoad = lists:sum(get_load()) div Schedulers,
- if Schedulers < 2, HalfLoad > 80 -> ok; %% Ok only one scheduler online and one hog
- %% We want roughly 50% load
- HalfLoad > 40, HalfLoad < 60 -> ok;
- true -> exit({halfload, HalfLoad})
- end,
-
- %% 100% load
- LastHogs = [StartHog() || _ <- lists:seq(1, Schedulers div 2)],
- FullScheds = get_load(),
- {false,_} = {lists:any(fun(Load) -> Load < 80 end, FullScheds),FullScheds},
- FullLoad = lists:sum(FullScheds) div Schedulers,
- if FullLoad > 90 -> ok;
- true -> exit({fullload, FullLoad})
- end,
-
- [exit(Pid, kill) || Pid <- [P1|HalfHogs++LastHogs]],
- AfterLoad = get_load(),
- {false,_} = {lists:any(fun(Load) -> Load > 25 end, AfterLoad),AfterLoad},
- true = erlang:system_flag(scheduler_wall_time, false)
+ Schedulers = erlang:system_info(schedulers_online),
+ %% Let testserver and everyone else finish their work
+ timer:sleep(1500),
+ %% Empty load
+ EmptyLoad = get_load(),
+ {false, _} = {lists:any(fun(Load) -> Load > 50 end, EmptyLoad),EmptyLoad},
+ MeMySelfAndI = self(),
+ StartHog = fun() ->
+ Pid = spawn(?MODULE, hog, [self()]),
+ receive hog_started -> MeMySelfAndI ! go end,
+ Pid
+ end,
+ P1 = StartHog(),
+ %% Max on one, the other schedulers empty (hopefully)
+ %% Be generous the process can jump between schedulers
+ %% which is ok and we don't want the test to fail for wrong reasons
+ _L1 = [S1Load|EmptyScheds1] = get_load(),
+ {true,_} = {S1Load > 50,S1Load},
+ {false,_} = {lists:any(fun(Load) -> Load > 50 end, EmptyScheds1),EmptyScheds1},
+ {true,_} = {lists:sum(EmptyScheds1) < 60,EmptyScheds1},
+
+ %% 50% load
+ HalfHogs = [StartHog() || _ <- lists:seq(1, (Schedulers-1) div 2)],
+ HalfLoad = lists:sum(get_load()) div Schedulers,
+ if Schedulers < 2, HalfLoad > 80 -> ok; %% Ok only one scheduler online and one hog
+ %% We want roughly 50% load
+ HalfLoad > 40, HalfLoad < 60 -> ok;
+ true -> exit({halfload, HalfLoad})
+ end,
+
+ %% 100% load
+ LastHogs = [StartHog() || _ <- lists:seq(1, Schedulers div 2)],
+ FullScheds = get_load(),
+ {false,_} = {lists:any(fun(Load) -> Load < 80 end, FullScheds),FullScheds},
+ FullLoad = lists:sum(FullScheds) div Schedulers,
+ if FullLoad > 90 -> ok;
+ true -> exit({fullload, FullLoad})
+ end,
+
+ [exit(Pid, kill) || Pid <- [P1|HalfHogs++LastHogs]],
+ AfterLoad = get_load(),
+ {false,_} = {lists:any(fun(Load) -> Load > 25 end, AfterLoad),AfterLoad},
+ true = erlang:system_flag(scheduler_wall_time, false)
after
- erlang:system_flag(scheduler_wall_time, false)
+ erlang:system_flag(scheduler_wall_time, false)
end.
get_load() ->
@@ -366,62 +330,59 @@ load_percentage([{Id, WN, TN}|Ss], [{Id, WP, TP}|Ps]) ->
load_percentage([], []) -> [].
-garbage_collection(doc) ->
- "Tests that statistics(garbage_collection) is callable. "
- "It is not clear how to test anything more.";
+%% Tests that statistics(garbage_collection) is callable.
+%% It is not clear how to test anything more.
garbage_collection(Config) when is_list(Config) ->
- ?line Bin = list_to_binary(lists:duplicate(19999, 42)),
- ?line case statistics(garbage_collection) of
- {Gcs0,R,0} when is_integer(Gcs0), is_integer(R) ->
- ?line io:format("Reclaimed: ~p", [R]),
- ?line Gcs = garbage_collection_1(Gcs0, Bin),
- ?line io:format("Reclaimed: ~p",
- [element(2, statistics(garbage_collection))]),
- {comment,integer_to_list(Gcs-Gcs0)++" GCs"}
- end.
+ Bin = list_to_binary(lists:duplicate(19999, 42)),
+ case statistics(garbage_collection) of
+ {Gcs0,R,0} when is_integer(Gcs0), is_integer(R) ->
+ io:format("Reclaimed: ~p", [R]),
+ Gcs = garbage_collection_1(Gcs0, Bin),
+ io:format("Reclaimed: ~p",
+ [element(2, statistics(garbage_collection))]),
+ {comment,integer_to_list(Gcs-Gcs0)++" GCs"}
+ end.
garbage_collection_1(Gcs0, Bin) ->
case statistics(garbage_collection) of
- {Gcs,Reclaimed,0} when Gcs >= Gcs0 ->
- if
- Reclaimed > 16#7ffffff ->
- Gcs;
- true ->
- _ = binary_to_list(Bin),
- erlang:garbage_collect(),
- garbage_collection_1(Gcs, Bin)
- end
+ {Gcs,Reclaimed,0} when Gcs >= Gcs0 ->
+ if
+ Reclaimed > 16#7ffffff ->
+ Gcs;
+ true ->
+ _ = binary_to_list(Bin),
+ erlang:garbage_collect(),
+ garbage_collection_1(Gcs, Bin)
+ end
end.
-io(doc) ->
- "Tests that statistics(io) is callable. "
- "This could be improved to test something more.";
+%% Tests that statistics(io) is callable.
+%% This could be improved to test something more.
io(Config) when is_list(Config) ->
- ?line case statistics(io) of
- {{input,In},{output,Out}} when is_integer(In), is_integer(Out) -> ok
- end.
+ case statistics(io) of
+ {{input,In},{output,Out}} when is_integer(In), is_integer(Out) -> ok
+ end.
-badarg(doc) ->
- "Tests that some illegal arguments to statistics fails.";
+%% Tests that some illegal arguments to statistics fails.
badarg(Config) when is_list(Config) ->
- ?line case catch statistics(1) of
- {'EXIT', {badarg, _}} -> ok
- end,
- ?line case catch statistics(bad_atom) of
- {'EXIT', {badarg, _}} -> ok
- end.
+ case catch statistics(1) of
+ {'EXIT', {badarg, _}} -> ok
+ end,
+ case catch statistics(bad_atom) of
+ {'EXIT', {badarg, _}} -> ok
+ end.
tok_loop() ->
tok_loop().
run_queues_lengths_active_tasks(Config) ->
TokLoops = lists:map(fun (_) ->
- spawn_opt(fun () ->
- tok_loop()
- end,
- [link, {priority, low}])
- end,
- lists:seq(1,10)),
+ spawn_opt(fun () ->
+ tok_loop()
+ end,
+ [link, {priority, low}])
+ end,
+ lists:seq(1,10)),
TRQLs0 = statistics(total_run_queue_lengths),
TATs0 = statistics(total_active_tasks),
@@ -464,9 +425,119 @@ run_queues_lengths_active_tasks(Config) ->
erlang:system_flag(schedulers_online, SO),
lists:foreach(fun (P) ->
- unlink(P),
- exit(P, bang)
- end,
- TokLoops),
+ unlink(P),
+ exit(P, bang)
+ end,
+ TokLoops),
ok.
+
+%% Tests that statistics(microstate_statistics) works.
+msacc(Config) ->
+
+ %% Test if crypto nif is available
+ Niff = try crypto:strong_rand_bytes(1), ok catch _:_ -> nok end,
+ TmpFile = filename:join(proplists:get_value(priv_dir,Config),"file.tmp"),
+
+ false = erlang:system_flag(microstate_accounting, true),
+
+ msacc_test(TmpFile),
+
+ true = erlang:system_flag(microstate_accounting, false),
+
+ MsaccStats = erlang:statistics(microstate_accounting),
+
+ case os:type() of
+ {win32, _} ->
+ %% Some windows have a very poor accuracy on their
+ %% timing primitives, so we just make sure that
+ %% some state besides sleep has been triggered.
+ Sum = lists:sum(
+ lists:map(fun({sleep, _V}) -> 0;
+ ({_, V}) -> V
+ end, maps:to_list(msacc_sum_states()))
+ ),
+ if Sum > 0 ->
+ ok;
+ true ->
+ ct:fail({no_states_triggered, MsaccStats})
+ end;
+ _ ->
+
+ %% Make sure that all states were triggered at least once
+ maps:map(fun(nif, 0) ->
+ case Niff of
+ ok ->
+ ct:fail({zero_state,nif});
+ nok ->
+ ok
+ end;
+ (aux, 0) ->
+ %% aux will be zero if we do not have smp support
+ %% or no async threads
+ case erlang:system_info(smp_support) orelse
+ erlang:system_info(thread_pool_size) > 0
+ of
+ false ->
+ ok;
+ true ->
+ ct:log("msacc: ~p",[MsaccStats]),
+ ct:fail({zero_state,aux})
+ end;
+ (Key, 0) ->
+ ct:log("msacc: ~p",[MsaccStats]),
+ ct:fail({zero_state,Key});
+ (_,_) -> ok
+ end, msacc_sum_states())
+ end,
+
+ erlang:system_flag(microstate_accounting, reset),
+
+ msacc_test(TmpFile),
+
+ %% Make sure all counters are zero after stopping and resetting
+ maps:map(fun(_Key, 0) -> ok;
+ (Key,_) ->
+ ct:log("msacc: ~p",[erlang:statistics(microstate_accounting)]),
+ ct:fail({non_zero_state,Key})
+ end,msacc_sum_states()).
+
+%% This test tries to make sure to trigger all of the different available states
+msacc_test(TmpFile) ->
+
+ %% We write some data
+ [file:write_file(TmpFile,<<0:(1024*1024*8)>>,[raw]) || _ <- lists:seq(1,100)],
+
+ %% Do some ETS operations
+ Tid = ets:new(table, []),
+ ets:insert(Tid, {1, hello}),
+ ets:delete(Tid),
+
+ %% Collect some garbage
+ [erlang:garbage_collect() || _ <- lists:seq(1,100)],
+
+ %% Send some messages
+ [begin self() ! {hello},receive _ -> ok end end || _ <- lists:seq(1,100)],
+
+ %% Setup some timers
+ Refs = [erlang:send_after(10000,self(),ok) || _ <- lists:seq(1,100)],
+
+ %% Do some nif work
+ catch [crypto:strong_rand_bytes(128) || _ <- lists:seq(1,100)],
+
+ %% Cancel some timers
+ [erlang:cancel_timer(R) || R <- Refs],
+
+ %% Wait for a while
+ timer:sleep(100).
+
+msacc_sum_states() ->
+ Stats = erlang:statistics(microstate_accounting),
+ [#{ counters := C }|_] = Stats,
+ InitialCounters = maps:map(fun(_,_) -> 0 end,C),
+ lists:foldl(fun(#{ counters := Counters }, Cnt) ->
+ maps:fold(fun(Key, Value, Acc) ->
+ NewValue = Value+maps:get(Key,Acc),
+ maps:update(Key, NewValue, Acc)
+ end, Cnt, Counters)
+ end,InitialCounters,Stats).
diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl
index bee42c07d9..ffea5bc15b 100644
--- a/erts/emulator/test/system_info_SUITE.erl
+++ b/erts/emulator/test/system_info_SUITE.erl
@@ -31,55 +31,25 @@
%-define(line_trace, 1).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-%-compile(export_all).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2, end_per_testcase/2]).
+-export([all/0, suite/0]).
--export([process_count/1, system_version/1, misc_smoke_tests/1, heap_size/1, wordsize/1, memory/1,
- ets_limit/1]).
+-export([process_count/1, system_version/1, misc_smoke_tests/1,
+ heap_size/1, wordsize/1, memory/1, ets_limit/1]).
--define(DEFAULT_TIMEOUT, ?t:minutes(2)).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 2}}].
all() ->
[process_count, system_version, misc_smoke_tests,
heap_size, wordsize, memory, ets_limit].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(_Case, Config) when is_list(Config) ->
- Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) when is_list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
- ok.
-
%%%
%%% The test cases -------------------------------------------------------------
%%%
-process_count(doc) -> [];
-process_count(suite) -> [];
process_count(Config) when is_list(Config) ->
case catch erlang:system_info(modified_timing_level) of
Level when is_integer(Level) ->
@@ -92,37 +62,37 @@ process_count(Config) when is_list(Config) ->
end.
process_count_test() ->
- ?line OldPrio = process_flag(priority, max),
- ?line check_procs(10),
- ?line check_procs(11234),
- ?line check_procs(57),
- ?line check_procs(1030),
- ?line check_procs(687),
- ?line check_procs(7923),
- ?line check_procs(5302),
- ?line check_procs(12456),
- ?line check_procs(14),
- ?line check_procs(1125),
- ?line check_procs(236),
- ?line check_procs(125),
- ?line check_procs(2346),
- ?line process_flag(priority, OldPrio),
- ?line ok.
+ OldPrio = process_flag(priority, max),
+ check_procs(10),
+ check_procs(11234),
+ check_procs(57),
+ check_procs(1030),
+ check_procs(687),
+ check_procs(7923),
+ check_procs(5302),
+ check_procs(12456),
+ check_procs(14),
+ check_procs(1125),
+ check_procs(236),
+ check_procs(125),
+ check_procs(2346),
+ process_flag(priority, OldPrio),
+ ok.
check_procs(N) ->
- ?line CP = length(processes()),
- ?line Procs = start_procs(N),
- ?line check_pc(CP+N),
- ?line stop_procs(Procs),
- ?line check_pc(CP).
+ CP = length(processes()),
+ Procs = start_procs(N),
+ check_pc(CP+N),
+ stop_procs(Procs),
+ check_pc(CP).
check_pc(E) ->
- ?line P = length(processes()),
- ?line SI = erlang:system_info(process_count),
- ?line ?t:format("E=~p; P=~p; SI=~p~n", [E, P, SI]),
- ?line E = P,
- ?line P = SI.
+ P = length(processes()),
+ SI = erlang:system_info(process_count),
+ io:format("E=~p; P=~p; SI=~p~n", [E, P, SI]),
+ E = P,
+ P = SI.
start_procs(N) ->
lists:map(fun (_) ->
@@ -143,55 +113,44 @@ stop_procs(PMs) ->
end, PMs).
-system_version(doc) -> [];
-system_version(suite) -> [];
system_version(Config) when is_list(Config) ->
- ?line {comment, erlang:system_info(system_version)}.
+ {comment, erlang:system_info(system_version)}.
-misc_smoke_tests(doc) -> [];
-misc_smoke_tests(suite) -> [];
misc_smoke_tests(Config) when is_list(Config) ->
- ?line true = is_binary(erlang:system_info(info)),
- ?line true = is_binary(erlang:system_info(procs)),
- ?line true = is_binary(erlang:system_info(loaded)),
- ?line true = is_binary(erlang:system_info(dist)),
- ?line ok = try erlang:system_info({cpu_topology,erts_get_cpu_topology_error_case}), fail catch error:badarg -> ok end,
+ true = is_binary(erlang:system_info(info)),
+ true = is_binary(erlang:system_info(procs)),
+ true = is_binary(erlang:system_info(loaded)),
+ true = is_binary(erlang:system_info(dist)),
+ ok = try erlang:system_info({cpu_topology,erts_get_cpu_topology_error_case}), fail catch error:badarg -> ok end,
true = lists:member(erlang:system_info(tolerant_timeofday), [enabled, disabled]),
- ?line ok.
+ ok.
-heap_size(doc) -> [];
-heap_size(suite) -> [];
heap_size(Config) when is_list(Config) ->
- ?line {min_bin_vheap_size, VHmin} = erlang:system_info(min_bin_vheap_size),
- ?line {min_heap_size, Hmin} = erlang:system_info(min_heap_size),
- ?line GCinf = erlang:system_info(garbage_collection),
- ?line VHmin = proplists:get_value(min_bin_vheap_size, GCinf),
- ?line Hmin = proplists:get_value(min_heap_size, GCinf),
+ {min_bin_vheap_size, VHmin} = erlang:system_info(min_bin_vheap_size),
+ {min_heap_size, Hmin} = erlang:system_info(min_heap_size),
+ GCinf = erlang:system_info(garbage_collection),
+ VHmin = proplists:get_value(min_bin_vheap_size, GCinf),
+ Hmin = proplists:get_value(min_heap_size, GCinf),
ok.
-wordsize(suite) ->
- [];
-wordsize(doc) ->
- ["Tests the various wordsize variants"];
+%% Tests the various wordsize variants
wordsize(Config) when is_list(Config) ->
- ?line A = erlang:system_info(wordsize),
- ?line true = is_integer(A),
- ?line A = erlang:system_info({wordsize,internal}),
- ?line B = erlang:system_info({wordsize,external}),
- ?line true = A =< B,
+ A = erlang:system_info(wordsize),
+ true = is_integer(A),
+ A = erlang:system_info({wordsize,internal}),
+ B = erlang:system_info({wordsize,external}),
+ true = A =< B,
case {B,A} of
{4,4} ->
{comment, "True 32-bit emulator"};
{8,8} ->
{comment, "True 64-bit emulator"};
- {8,4} ->
- {comment, "Halfword 64-bit emulator"};
Other ->
exit({unexpected_wordsizes,Other})
end.
-memory(doc) -> ["Verify that erlang:memory/0 and memory results in crashdump produce are similar"];
+%% Verify that erlang:memory/0 and memory results in crashdump produce are similar
memory(Config) when is_list(Config) ->
%%
%% Verify that erlang:memory/0 and memory results in
@@ -246,8 +205,7 @@ memory_test(_Config) ->
end)
end,
1000 div erlang:system_info(schedulers_online))
- end,
- []),
+ end, []),
cmp_memory(MWs, "spawn procs"),
Ps = lists:flatten(DPs),
@@ -255,14 +213,12 @@ memory_test(_Config) ->
mem_workers_call(MWs,
fun () ->
lists:foreach(fun (P) -> link(P) end, Ps)
- end,
- []),
+ end, []),
cmp_memory(MWs, "link procs"),
mem_workers_call(MWs,
fun () ->
lists:foreach(fun (P) -> unlink(P) end, Ps)
- end,
- []),
+ end, []),
cmp_memory(MWs, "unlink procs"),
mem_workers_call(MWs,
@@ -279,8 +235,7 @@ memory_test(_Config) ->
true = is_reference(Tmr),
put('BIF_TMRS', [Tmr|Tmrs])
end, Ps)
- end,
- []),
+ end, []),
cmp_memory(MWs, "start BIF timer procs"),
mem_workers_call(MWs,
@@ -291,8 +246,7 @@ memory_test(_Config) ->
end, get('BIF_TMRS')),
put('BIF_TMRS', undefined),
garbage_collect()
- end,
- []),
+ end, []),
erts_debug:set_internal_state(wait, deallocations),
cmp_memory(MWs, "cancel BIF timer procs"),
@@ -301,8 +255,7 @@ memory_test(_Config) ->
lists:map(fun (P) ->
monitor(process, P)
end, Ps)
- end,
- []),
+ end, []),
cmp_memory(MWs, "monitor procs"),
Ms = lists:flatten(DMs),
mem_workers_call(MWs,
@@ -310,8 +263,7 @@ memory_test(_Config) ->
lists:foreach(fun (M) ->
demonitor(M)
end, Ms)
- end,
- []),
+ end, []),
cmp_memory(MWs, "demonitor procs"),
mem_workers_call(MWs,
@@ -319,8 +271,7 @@ memory_test(_Config) ->
lists:foreach(fun (P) ->
P ! {a, "message", make_ref()}
end, Ps)
- end,
- []),
+ end, []),
cmp_memory(MWs, "message procs"),
mem_workers_call(MWs,
@@ -343,8 +294,7 @@ memory_test(_Config) ->
fun () ->
put(binary_data,
mapn(fun (_) -> list_to_binary(lists:duplicate(256,$?)) end, 100))
- end,
- []),
+ end, []),
cmp_memory(MWs, "store binary data"),
@@ -352,8 +302,7 @@ memory_test(_Config) ->
fun () ->
put(binary_data, false),
garbage_collect()
- end,
- []),
+ end, []),
cmp_memory(MWs, "release binary data"),
mem_workers_call(MWs,
@@ -361,8 +310,7 @@ memory_test(_Config) ->
list_to_atom("an ugly atom "++integer_to_list(erlang:system_info(scheduler_id))),
list_to_atom("another ugly atom "++integer_to_list(erlang:system_info(scheduler_id))),
list_to_atom("yet another ugly atom "++integer_to_list(erlang:system_info(scheduler_id)))
- end,
- []),
+ end, []),
cmp_memory(MWs, "new atoms"),
@@ -373,16 +321,14 @@ memory_test(_Config) ->
ets:insert(T, {banan, lists:seq(1,1024)}),
ets:insert(T, {appelsin, make_ref()}),
put(ets_id, T)
- end,
- []),
+ end, []),
cmp_memory(MWs, "store ets data"),
mem_workers_call(MWs,
fun () ->
ets:delete(get(ets_id)),
put(ets_id, false)
- end,
- []),
+ end, []),
cmp_memory(MWs, "remove ets data"),
lists:foreach(fun (MW) ->
@@ -392,8 +338,7 @@ memory_test(_Config) ->
receive
{'DOWN', Mon, _, _, _} -> ok
end
- end,
- MWs),
+ end, MWs),
ok.
mem_worker() ->
@@ -408,22 +353,19 @@ mem_worker() ->
mem_workers_call(MWs, Fun, Args) ->
lists:foreach(fun (MW) ->
- MW ! {call, self(), Fun, Args}
- end,
- MWs),
+ MW ! {call, self(), Fun, Args}
+ end, MWs),
lists:map(fun (MW) ->
- receive
- {reply, MW, Res} ->
- Res
- end
- end,
- MWs).
+ receive
+ {reply, MW, Res} ->
+ Res
+ end
+ end, MWs).
mem_workers_cast(MWs, Fun, Args) ->
lists:foreach(fun (MW) ->
MW ! {cast, self(), Fun, Args}
- end,
- MWs).
+ end, MWs).
spawn_mem_workers() ->
spawn_mem_workers(erlang:system_info(schedulers_online)).
@@ -436,7 +378,6 @@ spawn_mem_workers(N) ->
link]) | spawn_mem_workers(N-1)].
-
mem_get(X, Mem) ->
case lists:keyfind(X, 1, Mem) of
{X, Val} -> Val;
@@ -504,25 +445,25 @@ cmp_memory(MWs, Str) ->
"crash dump memory = ~p~n",
[Str, EM, EDM]),
- ?line check_sane_memory(EM),
- ?line check_sane_memory(EDM),
+ check_sane_memory(EM),
+ check_sane_memory(EDM),
%% We expect these to always give us exactly the same result
- ?line cmp_memory(atom, EM, EDM, 1),
- ?line cmp_memory(atom_used, EM, EDM, 1),
- ?line cmp_memory(binary, EM, EDM, 1),
- ?line cmp_memory(code, EM, EDM, 1),
- ?line cmp_memory(ets, EM, EDM, 1),
+ cmp_memory(atom, EM, EDM, 1),
+ cmp_memory(atom_used, EM, EDM, 1),
+ cmp_memory(binary, EM, EDM, 1),
+ cmp_memory(code, EM, EDM, 1),
+ cmp_memory(ets, EM, EDM, 1),
%% Total, processes, processes_used, and system will seldom
%% give us exactly the same result since the two readings
%% aren't taken atomically.
- ?line cmp_memory(total, EM, EDM, 1.05),
- ?line cmp_memory(processes, EM, EDM, 1.05),
- ?line cmp_memory(processes_used, EM, EDM, 1.05),
- ?line cmp_memory(system, EM, EDM, 1.05),
+ cmp_memory(total, EM, EDM, 1.05),
+ cmp_memory(processes, EM, EDM, 1.05),
+ cmp_memory(processes_used, EM, EDM, 1.05),
+ cmp_memory(system, EM, EDM, 1.05),
ok.
@@ -531,9 +472,7 @@ mapn(_Fun, 0) ->
mapn(Fun, N) ->
[Fun(N) | mapn(Fun, N-1)].
-ets_limit(doc) ->
- "Verify system_info(ets_limit) reflects max ETS table settings.";
-ets_limit(suite) -> [];
+%% Verify system_info(ets_limit) reflects max ETS table settings.
ets_limit(Config0) when is_list(Config0) ->
Config = [{testcase,ets_limit}|Config0],
true = is_integer(get_ets_limit(Config)),
@@ -567,12 +506,12 @@ start_node(Config, Envs) when is_list(Config) ->
Pa = filename:dirname(code:which(?MODULE)),
Name = list_to_atom(atom_to_list(?MODULE)
++ "-"
- ++ atom_to_list(?config(testcase, Config))
+ ++ atom_to_list(proplists:get_value(testcase, Config))
++ "-"
++ integer_to_list(erlang:system_time(seconds))
++ "-"
++ integer_to_list(erlang:unique_integer([positive]))),
- ?t:start_node(Name, peer, [{args, "-pa "++Pa}, {env, Envs}]).
+ test_server:start_node(Name, peer, [{args, "-pa "++Pa}, {env, Envs}]).
stop_node(Node) ->
- ?t:stop_node(Node).
+ test_server:stop_node(Node).
diff --git a/erts/emulator/test/system_profile_SUITE.erl b/erts/emulator/test/system_profile_SUITE.erl
index 2ecb4a28a7..6d80d436ba 100644
--- a/erts/emulator/test/system_profile_SUITE.erl
+++ b/erts/emulator/test/system_profile_SUITE.erl
@@ -23,61 +23,28 @@
-module(system_profile_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
+-export([all/0, suite/0,
system_profile_on_and_off/1,
- runnable_procs/1,
- runnable_ports/1,
+ runnable_procs/1, runnable_ports/1,
dont_profile_profiler/1,
- scheduler/1
- ]).
-
--export([init_per_testcase/2, end_per_testcase/2]).
+ scheduler/1]).
-export([profiler_process/1, ring_loop/1, port_echo_start/0,
list_load/0, run_load/2]).
--include_lib("test_server/include/test_server.hrl").
-
--define(default_timeout, ?t:minutes(1)).
-
-init_per_testcase(_Case, Config) ->
- Dog=?t:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
- ok.
+-include_lib("common_test/include/ct.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 1}}].
all() ->
[system_profile_on_and_off, runnable_procs,
runnable_ports, scheduler, dont_profile_profiler].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
%% No specification clause needed for an init function in a conf case!!!
%% Test switching system_profiling on and off.
-system_profile_on_and_off(suite) ->
- [];
-system_profile_on_and_off(doc) ->
- ["Tests switching system_profiling on and off."];
system_profile_on_and_off(Config) when is_list(Config) ->
Pid = start_profiler_process(),
@@ -106,12 +73,7 @@ system_profile_on_and_off(Config) when is_list(Config) ->
exit(Pid,kill),
ok.
-%% Test runnable_procs
-
-runnable_procs(suite) ->
- [];
-runnable_procs(doc) ->
- ["Tests system_profiling with runnable_procs."];
+%% Tests system_profiling with runnable_procs.
runnable_procs(Config) when is_list(Config) ->
lists:foreach(fun (TsType) ->
Arg = case TsType of
@@ -148,10 +110,7 @@ do_runnable_procs({TsType, TsTypeFlag}) ->
exit(Pid,kill),
ok.
-runnable_ports(suite) ->
- [];
-runnable_ports(doc) ->
- ["Tests system_profiling with runnable_port."];
+%% Tests system_profiling with runnable_port.
runnable_ports(Config) when is_list(Config) ->
lists:foreach(fun (TsType) ->
Arg = case TsType of
@@ -184,10 +143,7 @@ do_runnable_ports({TsType, TsTypeFlag}, Config) ->
exit(Pid,kill),
ok.
-scheduler(suite) ->
- [];
-scheduler(doc) ->
- ["Tests system_profiling with scheduler."];
+%% Tests system_profiling with scheduler.
scheduler(Config) when is_list(Config) ->
case {erlang:system_info(smp_support), erlang:system_info(schedulers_online)} of
{false,_} -> {skipped, "No need for scheduler test when smp support is disabled."};
@@ -209,11 +165,7 @@ scheduler(Config) when is_list(Config) ->
strict_monotonic_timestamp])
end.
-% the profiler pid should not be profiled
-dont_profile_profiler(suite) ->
- [];
-dont_profile_profiler(doc) ->
- ["Ensure system profiler process is not profiled."];
+%% Ensure system profiler process is not profiled.
dont_profile_profiler(Config) when is_list(Config) ->
Pid = start_profiler_process(),
@@ -421,7 +373,7 @@ ring_loop(RelayTo) ->
%% API
echo(Config) ->
- Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
erl_ddll:load_driver(Path, echo_drv),
Pid = spawn_link(?MODULE, port_echo_start, []),
Pid ! {self(), get_ports},
@@ -481,7 +433,7 @@ check_ts(no_timestamp, Ts) ->
no_timestamp = Ts
catch
_ : _ ->
- ?t:fail({unexpected_timestamp, Ts})
+ ct:fail({unexpected_timestamp, Ts})
end,
ok;
check_ts(timestamp, Ts) ->
@@ -492,7 +444,7 @@ check_ts(timestamp, Ts) ->
true = is_integer(Us)
catch
_ : _ ->
- ?t:fail({unexpected_timestamp, Ts})
+ ct:fail({unexpected_timestamp, Ts})
end,
ok;
check_ts(monotonic_timestamp, Ts) ->
@@ -500,7 +452,7 @@ check_ts(monotonic_timestamp, Ts) ->
true = is_integer(Ts)
catch
_ : _ ->
- ?t:fail({unexpected_timestamp, Ts})
+ ct:fail({unexpected_timestamp, Ts})
end,
ok;
check_ts(strict_monotonic_timestamp, Ts) ->
@@ -510,7 +462,7 @@ check_ts(strict_monotonic_timestamp, Ts) ->
true = is_integer(UMI)
catch
_ : _ ->
- ?t:fail({unexpected_timestamp, Ts})
+ ct:fail({unexpected_timestamp, Ts})
end,
ok.
@@ -534,7 +486,7 @@ run_load(N, Pids) ->
run_load(N - 1, [Pid | Pids]).
list_load() ->
- ok = case math:sin(random:uniform(32451)) of
+ ok = case math:sin(rand:uniform(32451)) of
A when is_float(A) -> ok;
_ -> ok
end,
diff --git a/erts/emulator/test/time_SUITE.erl b/erts/emulator/test/time_SUITE.erl
index 787870588d..e6da5e89fa 100644
--- a/erts/emulator/test/time_SUITE.erl
+++ b/erts/emulator/test/time_SUITE.erl
@@ -48,7 +48,7 @@
-export([local_to_univ_utc/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([linear_time/1]).
@@ -69,7 +69,7 @@
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
[{testcase, Func}|Config].
-end_per_testcase(_Func, Config) ->
+end_per_testcase(_Func, _Config) ->
ok.
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -103,32 +103,29 @@ end_per_group(_GroupName, Config) ->
Config.
-local_to_univ_utc(suite) ->
- [];
-local_to_univ_utc(doc) ->
- ["Test that DST = true on timezones without DST is ignored"];
+%% Test that DST = true on timezones without DST is ignored
local_to_univ_utc(Config) when is_list(Config) ->
case os:type() of
{unix,_} ->
%% TZ variable has a meaning
- ?line {ok, Node} =
+ {ok, Node} =
test_server:start_node(local_univ_utc,peer,
[{args, "-env TZ UTC"}]),
- ?line {{2008,8,1},{0,0,0}} =
+ {{2008,8,1},{0,0,0}} =
rpc:call(Node,
erlang,localtime_to_universaltime,
[{{2008, 8, 1}, {0, 0, 0}},
false]),
- ?line {{2008,8,1},{0,0,0}} =
+ {{2008,8,1},{0,0,0}} =
rpc:call(Node,
erlang,localtime_to_universaltime,
[{{2008, 8, 1}, {0, 0, 0}},
true]),
- ?line [{{2008,8,1},{0,0,0}}] =
+ [{{2008,8,1},{0,0,0}}] =
rpc:call(Node,
calendar,local_time_to_universal_time_dst,
[{{2008, 8, 1}, {0, 0, 0}}]),
- ?line test_server:stop_node(Node),
+ test_server:stop_node(Node),
ok;
_ ->
{skip,"Only valid on Unix"}
@@ -138,24 +135,24 @@ local_to_univ_utc(Config) when is_list(Config) ->
%% Tests conversion from univeral to local time.
univ_to_local(Config) when is_list(Config) ->
- ?line test_univ_to_local(test_data()).
+ test_univ_to_local(test_data()).
test_univ_to_local([{Utc, Local}|Rest]) ->
- ?line io:format("Testing ~p => ~p~n", [Local, Utc]),
- ?line Local = erlang:universaltime_to_localtime(Utc),
- ?line test_univ_to_local(Rest);
+ io:format("Testing ~p => ~p~n", [Local, Utc]),
+ Local = erlang:universaltime_to_localtime(Utc),
+ test_univ_to_local(Rest);
test_univ_to_local([]) ->
ok.
%% Tests conversion from local to universal time.
local_to_univ(Config) when is_list(Config) ->
- ?line test_local_to_univ(test_data()).
+ test_local_to_univ(test_data()).
test_local_to_univ([{Utc, Local}|Rest]) ->
- ?line io:format("Testing ~p => ~p~n", [Utc, Local]),
- ?line Utc = erlang:localtime_to_universaltime(Local),
- ?line test_local_to_univ(Rest);
+ io:format("Testing ~p => ~p~n", [Utc, Local]),
+ Utc = erlang:localtime_to_universaltime(Local),
+ test_local_to_univ(Rest);
test_local_to_univ([]) ->
ok.
@@ -163,11 +160,11 @@ test_local_to_univ([]) ->
%% generate a badarg.
bad_univ_to_local(Config) when is_list(Config) ->
- ?line bad_test_univ_to_local(bad_dates()).
+ bad_test_univ_to_local(bad_dates()).
bad_test_univ_to_local([Utc|Rest]) ->
- ?line io:format("Testing ~p~n", [Utc]),
- ?line case catch erlang:universaltime_to_localtime(Utc) of
+ io:format("Testing ~p~n", [Utc]),
+ case catch erlang:universaltime_to_localtime(Utc) of
{'EXIT', {badarg, _}} -> bad_test_univ_to_local(Rest)
end;
bad_test_univ_to_local([]) ->
@@ -177,11 +174,11 @@ bad_test_univ_to_local([]) ->
%% generate a badarg.
bad_local_to_univ(Config) when is_list(Config) ->
- ?line bad_test_local_to_univ(bad_dates()).
+ bad_test_local_to_univ(bad_dates()).
bad_test_local_to_univ([Local|Rest]) ->
- ?line io:format("Testing ~p~n", [Local]),
- ?line case catch erlang:localtime_to_universaltime(Local) of
+ io:format("Testing ~p~n", [Local]),
+ case catch erlang:localtime_to_universaltime(Local) of
{'EXIT', {badarg, _}} -> bad_test_local_to_univ(Rest)
end;
bad_test_local_to_univ([]) ->
@@ -227,13 +224,13 @@ consistency(Config) when is_list(Config) ->
%% Daylight-saving calculations are incorrect from the last
%% Sunday of March and October to the end of the month.
- ?line ok = compare_date_time_and_localtime(16),
- ?line ok = compare_local_and_universal(16).
+ ok = compare_date_time_and_localtime(16),
+ ok = compare_local_and_universal(16).
compare_date_time_and_localtime(Times) when Times > 0 ->
- ?line {Year, Mon, Day} = date(),
- ?line {Hour, Min, Sec} = time(),
- ?line case erlang:localtime() of
+ {Year, Mon, Day} = date(),
+ {Hour, Min, Sec} = time(),
+ case erlang:localtime() of
{{Year, Mon, Day}, {Hour, Min, Sec}} -> ok;
_ -> compare_date_time_and_localtime(Times-1)
end;
@@ -315,10 +312,7 @@ effective_timezone1(_) ->
%% Test (the bif) os:timestamp/0, which is something quite like, but not
%% similar to erlang:now...
-timestamp(suite) ->
- [];
-timestamp(doc) ->
- ["Test that os:timestamp works."];
+%% Test that os:timestamp works.
timestamp(Config) when is_list(Config) ->
try
repeating_timestamp_check(100000)
@@ -334,7 +328,7 @@ timestamp(Config) when is_list(Config) ->
true ->
{skip, "Seems to be time warp test run..."};
false ->
- test_server:fail(Failure)
+ ct:fail(Failure)
end
end.
@@ -368,9 +362,7 @@ repeating_timestamp_check(N) ->
C < 1000000 ->
ok;
true ->
- test_server:fail(
- lists:flatten(
- io_lib:format("Strange return from os:timestamp/0 ~w~n",[TS])))
+ ct:fail("Strange return from os:timestamp/0 ~w~n",[TS])
end,
%% I assume the now and timestamp should not differ more than 1 hour,
%% which is safe assuming the system has not had a large time-warp
@@ -403,22 +395,22 @@ repeating_timestamp_check(N) ->
%% times (in microseconds).
now_unique(Config) when is_list(Config) ->
- ?line now_unique(1000, now(), []),
- ?line fast_now_unique(100000, now()).
+ now_unique(1000, now(), []),
+ fast_now_unique(100000, now()).
now_unique(N, Previous, Result) when N > 0 ->
- ?line case now() of
+ case now() of
Previous ->
- test_server:fail("now/0 returned the same value twice");
+ ct:fail("now/0 returned the same value twice");
New ->
now_unique(N-1, New, [New|Result])
end;
now_unique(0, _, [Then|Rest]) ->
- ?line now_calc_increment(Rest, microsecs(Then), []).
+ now_calc_increment(Rest, microsecs(Then), []).
now_calc_increment([Then|Rest], Previous, _Result) ->
- ?line This = microsecs(Then),
- ?line now_calc_increment(Rest, This, [Previous-This]);
+ This = microsecs(Then),
+ now_calc_increment(Rest, This, [Previous-This]);
now_calc_increment([], _, Differences) ->
{comment, "Median increment: " ++ integer_to_list(median(Differences))}.
@@ -426,15 +418,15 @@ fast_now_unique(0, _) -> ok;
fast_now_unique(N, Then) ->
case now() of
Then ->
- ?line ?t:fail("now/0 returned the same value twice");
+ ct:fail("now/0 returned the same value twice");
Now ->
fast_now_unique(N-1, Now)
end.
median(Unsorted_List) ->
- ?line Length = length(Unsorted_List),
- ?line List = lists:sort(Unsorted_List),
- ?line case Length rem 2 of
+ Length = length(Unsorted_List),
+ List = lists:sort(Unsorted_List),
+ case Length rem 2 of
0 -> % Even length.
[A, B] = lists:nthtail((Length div 2)-1, List),
(A+B)/2;
@@ -450,31 +442,30 @@ microsecs({Mega_Secs, Secs, Microsecs}) ->
%% calls to erlang:localtime().
now_update(Config) when is_list(Config) ->
- case ?t:is_debug() of
- false -> ?line now_update1(10);
+ case test_server:is_debug() of
+ false -> now_update1(10);
true -> {skip,"Unreliable in DEBUG build"}
end.
now_update1(N) when N > 0 ->
- ?line T1_linear = linear_time(erlang:localtime()),
- ?line T1_now = microsecs(now()),
+ T1_linear = linear_time(erlang:localtime()),
+ T1_now = microsecs(now()),
- ?line receive after 1008 -> ok end,
+ receive after 1008 -> ok end,
- ?line T2_linear = linear_time(erlang:localtime()),
- ?line T2_now = microsecs(now()),
+ T2_linear = linear_time(erlang:localtime()),
+ T2_now = microsecs(now()),
- ?line Linear_Diff = (T2_linear-T1_linear)*1000000,
- ?line Now_Diff = T2_now-T1_now,
- test_server:format("Localtime diff = ~p; now() diff = ~p",
- [Linear_Diff, Now_Diff]),
- ?line case abs(Linear_Diff - Now_Diff) of
+ Linear_Diff = (T2_linear-T1_linear)*1000000,
+ Now_Diff = T2_now-T1_now,
+ io:format("Localtime diff = ~p; now() diff = ~p", [Linear_Diff, Now_Diff]),
+ case abs(Linear_Diff - Now_Diff) of
Abs_Delta when Abs_Delta =< 40000 -> ok;
_ -> now_update1(N-1)
end;
now_update1(0) ->
- ?line test_server:fail().
+ ct:fail("now_update zero").
time_warp_modes(Config) when is_list(Config) ->
%% All time warp modes always supported in
@@ -551,14 +542,14 @@ check_time_warp_mode(Config, TimeCorrection, TimeWarpMode) ->
io:format("Uptime inconsistency", []),
case {TimeCorrection, erlang:system_info(time_correction)} of
{true, true} ->
- ?t:fail(uptime_inconsistency);
+ ct:fail(uptime_inconsistency);
{true, false} ->
_ = erlang:time_offset(),
receive
{'CHANGE', Mon, time_offset, clock_service, _} ->
ignore
after 1000 ->
- ?t:fail(uptime_inconsistency)
+ ct:fail(uptime_inconsistency)
end;
_ ->
ignore
@@ -728,10 +719,10 @@ check_time_offset_res_conv(Mon, Res) ->
TORes2 ->
case check_time_offset_change(Mon, TO, 1000) of
{TO, false} ->
- ?t:fail({time_unit_conversion_inconsistency,
+ ct:fail({time_unit_conversion_inconsistency,
TO, TORes, TORes2});
{_NewTO, true} ->
- ?t:format("time_offset changed", []),
+ io:format("time_offset changed", []),
check_time_offset_res_conv(Mon, Res)
end
end.
@@ -776,25 +767,21 @@ chk_strc(Res0, Res1) ->
ok.
chk_random_values(FR, TR) ->
-% case (FR rem TR == 0) orelse (TR rem FR == 0) of
-% true ->
- io:format("rand values ~p -> ~p~n", [FR, TR]),
- random:seed(268438039, 268440479, 268439161),
- Values = lists:map(fun (_) -> random:uniform(1 bsl 65) - (1 bsl 64) end,
- lists:seq(1, 100000)),
- CheckFun = fun (V) ->
- CV = erlang:convert_time_unit(V, FR, TR),
- case {(FR*CV) div TR =< V,
- (FR*(CV+1)) div TR >= V} of
- {true, true} ->
- ok;
- Failure ->
- ?t:fail({Failure, CV, V, FR, TR})
- end
- end,
- lists:foreach(CheckFun, Values).%;
-% false -> ok
-% end.
+ io:format("rand values ~p -> ~p~n", [FR, TR]),
+ rand:seed(exsplus, {268438039,268440479,268439161}),
+ Values = lists:map(fun (_) -> rand:uniform(1 bsl 65) - (1 bsl 64) end,
+ lists:seq(1, 100000)),
+ CheckFun = fun (V) ->
+ CV = erlang:convert_time_unit(V, FR, TR),
+ case {(FR*CV) div TR =< V,
+ (FR*(CV+1)) div TR >= V} of
+ {true, true} ->
+ ok;
+ Failure ->
+ ct:fail({Failure, CV, V, FR, TR})
+ end
+ end,
+ lists:foreach(CheckFun, Values).
chk_values_per_value(_FromRes, _ToRes,
@@ -805,7 +792,7 @@ chk_values_per_value(_FromRes, _ToRes,
case ((MinFromValuesPerToValue =< FromValueCount)
andalso (FromValueCount =< MaxFromValuesPerToValue)) of
false ->
- ?t:fail({MinFromValuesPerToValue,
+ ct:fail({MinFromValuesPerToValue,
FromValueCount,
MaxFromValuesPerToValue});
true ->
@@ -815,28 +802,28 @@ chk_values_per_value(FromRes, ToRes, Value, EndValue,
MinFromValuesPerToValue, MaxFromValuesPerToValue,
ToValue, FromValueCount) ->
case erlang:convert_time_unit(Value, FromRes, ToRes) of
- ToValue ->
- chk_values_per_value(FromRes, ToRes,
- Value+1, EndValue,
- MinFromValuesPerToValue,
- MaxFromValuesPerToValue,
- ToValue, FromValueCount+1);
- NewToValue ->
- case ((MinFromValuesPerToValue =< FromValueCount)
- andalso (FromValueCount =< MaxFromValuesPerToValue)) of
- false ->
- ?t:fail({MinFromValuesPerToValue,
- FromValueCount,
- MaxFromValuesPerToValue});
- true ->
-% io:format("~p -> ~p [~p]~n",
-% [Value, NewToValue, FromValueCount]),
- chk_values_per_value(FromRes, ToRes,
- Value+1, EndValue,
- MinFromValuesPerToValue,
- MaxFromValuesPerToValue,
- NewToValue, 1)
- end
+ ToValue ->
+ chk_values_per_value(FromRes, ToRes,
+ Value+1, EndValue,
+ MinFromValuesPerToValue,
+ MaxFromValuesPerToValue,
+ ToValue, FromValueCount+1);
+ NewToValue ->
+ case ((MinFromValuesPerToValue =< FromValueCount)
+ andalso (FromValueCount =< MaxFromValuesPerToValue)) of
+ false ->
+ ct:fail({MinFromValuesPerToValue,
+ FromValueCount,
+ MaxFromValuesPerToValue});
+ true ->
+ % io:format("~p -> ~p [~p]~n",
+ % [Value, NewToValue, FromValueCount]),
+ chk_values_per_value(FromRes, ToRes,
+ Value+1, EndValue,
+ MinFromValuesPerToValue,
+ MaxFromValuesPerToValue,
+ NewToValue, 1)
+ end
end.
erlang_timestamp(Config) when is_list(Config) ->
@@ -849,11 +836,11 @@ erlang_timestamp(Config) when is_list(Config) ->
check_erlang_timestamp(Done, Mon, TO) ->
receive
- {timeout, Done, timeout} ->
- erlang:demonitor(Mon, [flush]),
- ok
+ {timeout, Done, timeout} ->
+ erlang:demonitor(Mon, [flush]),
+ ok
after 0 ->
- do_check_erlang_timestamp(Done, Mon, TO)
+ do_check_erlang_timestamp(Done, Mon, TO)
end.
do_check_erlang_timestamp(Done, Mon, TO) ->
@@ -878,13 +865,13 @@ do_check_erlang_timestamp(Done, Mon, TO) ->
check_erlang_timestamp(Done, Mon, NewTO);
false ->
io:format("TsMin=~p TsTime=~p TsMax=~p~n", [TsMin, TsTime, TsMax]),
- ?t:format("Detected inconsistency; "
+ io:format("Detected inconsistency; "
"checking for time_offset change...", []),
case check_time_offset_change(Mon, TO, 1000) of
{TO, false} ->
- ?t:fail(timestamp_inconsistency);
+ ct:fail(timestamp_inconsistency);
{NewTO, true} ->
- ?t:format("time_offset changed", []),
+ io:format("time_offset changed", []),
check_erlang_timestamp(Done, Mon, NewTO)
end
end.
@@ -925,13 +912,13 @@ test_data() ->
_ ->
{?timezone,?dst_timezone}
end,
- ?line test_data(nondst_dates(), TZ) ++
+ test_data(nondst_dates(), TZ) ++
test_data(dst_dates(), DSTTZ) ++
crossover_test_data(crossover_dates(), TZ).
%% test_data1() ->
-%% ?line test_data(nondst_dates(), ?timezone) ++
+%% test_data(nondst_dates(), ?timezone) ++
%% test_data(dst_dates(), ?dst_timezone) ++
%% crossover_test_data(crossover_dates(), ?timezone).
@@ -939,16 +926,16 @@ crossover_test_data([{Year, Month, Day}|Rest], TimeZone) when TimeZone > 0 ->
Hour = 23,
Min = 35,
Sec = 55,
- ?line Utc = {{Year, Month, Day}, {Hour, Min, Sec}},
- ?line Local = {{Year, Month, Day+1}, {Hour+TimeZone-24, Min, Sec}},
- ?line [{Utc, Local}|crossover_test_data(Rest, TimeZone)];
+ Utc = {{Year, Month, Day}, {Hour, Min, Sec}},
+ Local = {{Year, Month, Day+1}, {Hour+TimeZone-24, Min, Sec}},
+ [{Utc, Local}|crossover_test_data(Rest, TimeZone)];
crossover_test_data([{Year, Month, Day}|Rest], TimeZone) when TimeZone < 0 ->
Hour = 0,
Min = 23,
Sec = 12,
- ?line Utc = {{Year, Month, Day}, {Hour, Min, Sec}},
- ?line Local = {{Year, Month, Day-1}, {Hour+TimeZone+24, Min, Sec}},
- ?line [{Utc, Local}|crossover_test_data(Rest, TimeZone)];
+ Utc = {{Year, Month, Day}, {Hour, Min, Sec}},
+ Local = {{Year, Month, Day-1}, {Hour+TimeZone+24, Min, Sec}},
+ [{Utc, Local}|crossover_test_data(Rest, TimeZone)];
crossover_test_data([], _) ->
[].
@@ -956,9 +943,9 @@ test_data([Date|Rest], TimeZone) ->
Hour = 12,
Min = 45,
Sec = 7,
- ?line Utc = {Date, {Hour, Min, Sec}},
- ?line Local = {Date, {Hour+TimeZone, Min, Sec}},
- ?line [{Utc, Local}|test_data(Rest, TimeZone)];
+ Utc = {Date, {Hour, Min, Sec}},
+ Local = {Date, {Hour+TimeZone, Min, Sec}},
+ [{Utc, Local}|test_data(Rest, TimeZone)];
test_data([], _) ->
[].
@@ -1049,7 +1036,7 @@ start_node(Config) ->
start_node(Config, "").
start_node(Config, Args) ->
- TestCase = ?config(testcase, Config),
+ TestCase = proplists:get_value(testcase, Config),
PA = filename:dirname(code:which(?MODULE)),
ESTime = erlang:monotonic_time(1) + erlang:time_offset(1),
Unique = erlang:unique_integer([positive]),
diff --git a/erts/emulator/test/timer_bif_SUITE.erl b/erts/emulator/test/timer_bif_SUITE.erl
index 51d59f09f3..fa72700604 100644
--- a/erts/emulator/test/timer_bif_SUITE.erl
+++ b/erts/emulator/test/timer_bif_SUITE.erl
@@ -20,8 +20,7 @@
-module(timer_bif_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
+-export([all/0, suite/0, init_per_suite/1, end_per_suite/1,
init_per_testcase/2,end_per_testcase/2]).
-export([start_timer_1/1, send_after_1/1, send_after_2/1, send_after_3/1,
cancel_timer_1/1,
@@ -33,23 +32,20 @@
% same_time_yielding_with_cancel_other_accessor/1,
auto_cancel_yielding/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(SHORT_TIMEOUT, 5000). %% Bif timers as short as this may be pre-allocated
-define(TIMEOUT_YIELD_LIMIT, 100).
-define(AUTO_CANCEL_YIELD_LIMIT, 100).
init_per_testcase(_Case, Config) ->
- ?line Dog=test_server:timetrap(test_server:seconds(30)),
case catch erts_debug:get_internal_state(available_internal_state) of
true -> ok;
_ -> erts_debug:set_internal_state(available_internal_state, true)
end,
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
init_per_suite(Config) ->
@@ -59,7 +55,9 @@ init_per_suite(Config) ->
end_per_suite(_Config) ->
catch erts_debug:set_internal_state(available_internal_state, false).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 5}}].
all() ->
[start_timer_1, send_after_1, send_after_2,
@@ -72,17 +70,8 @@ all() ->
% same_time_yielding_with_cancel_other_accessor,
auto_cancel_yielding].
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-start_timer_1(doc) -> ["Basic start_timer/3 functionality"];
+%% Basic start_timer/3 functionality
start_timer_1(Config) when is_list(Config) ->
Ref1 = erlang:start_timer(1000, self(), plopp),
ok = get(1100, {timeout, Ref1, plopp}),
@@ -102,54 +91,54 @@ start_timer_1(Config) when is_list(Config) ->
no_message = get(900, {timeout, Ref3, plopp}),
ok.
-send_after_1(doc) -> ["Basic send_after/3 functionality"];
+%% Basic send_after/3 functionality
send_after_1(Config) when is_list(Config) ->
- ?line Ref3 = erlang:send_after(1000, self(), plipp),
- ?line ok = get(1500, plipp),
- ?line false = erlang:read_timer(Ref3),
+ Ref3 = erlang:send_after(1000, self(), plipp),
+ ok = get(1500, plipp),
+ false = erlang:read_timer(Ref3),
ok.
-start_timer_big(doc) -> ["Big timeouts for start_timer/3"];
+%% Big timeouts for start_timer/3
start_timer_big(Config) when is_list(Config) ->
- ?line Big = 1 bsl 31,
- ?line R = erlang:start_timer(Big, self(), hej),
- ?line timer:sleep(200),
- ?line Left = erlang:cancel_timer(R),
- ?line case Big - Left of
- Diff when Diff >= 200, Diff < 10000 ->
- ok;
- _Diff ->
- test_server:fail({big, Big, Left})
- end,
+ Big = 1 bsl 31,
+ R = erlang:start_timer(Big, self(), hej),
+ timer:sleep(200),
+ Left = erlang:cancel_timer(R),
+ case Big - Left of
+ Diff when Diff >= 200, Diff < 10000 ->
+ ok;
+ _Diff ->
+ ct:fail({big, Big, Left})
+ end,
ok.
-send_after_big(doc) -> ["Big timeouts for send_after/3"];
+%% Big timeouts for send_after/3
send_after_big(Config) when is_list(Config) ->
- ?line Big = 1 bsl 31,
- ?line R = erlang:send_after(Big, self(), hej),
- ?line timer:sleep(200),
- ?line Left = erlang:cancel_timer(R),
- ?line case Big - Left of
- Diff when Diff >= 200, Diff < 10000 ->
- ok;
- _Diff ->
- test_server:fail({big, Big, Left})
- end,
+ Big = 1 bsl 31,
+ R = erlang:send_after(Big, self(), hej),
+ timer:sleep(200),
+ Left = erlang:cancel_timer(R),
+ case Big - Left of
+ Diff when Diff >= 200, Diff < 10000 ->
+ ok;
+ _Diff ->
+ ct:fail({big, Big, Left})
+ end,
ok.
-send_after_2(doc) -> ["send_after/3: messages in the right order, kind version"];
+%% send_after/3: messages in the right order, kind version
send_after_2(Config) when is_list(Config) ->
- ?line _ = erlang:send_after(5000, self(), last),
- ?line _ = erlang:send_after(0, self(), a0),
- ?line _ = erlang:send_after(200, self(), a2),
- ?line _ = erlang:send_after(100, self(), a1),
- ?line _ = erlang:send_after(500, self(), a5),
- ?line _ = erlang:send_after(300, self(), a3),
- ?line _ = erlang:send_after(400, self(), a4),
- ?line [a0,a1,a2,a3,a4,a5,last] = collect(last),
+ _ = erlang:send_after(5000, self(), last),
+ _ = erlang:send_after(0, self(), a0),
+ _ = erlang:send_after(200, self(), a2),
+ _ = erlang:send_after(100, self(), a1),
+ _ = erlang:send_after(500, self(), a5),
+ _ = erlang:send_after(300, self(), a3),
+ _ = erlang:send_after(400, self(), a4),
+ [a0,a1,a2,a3,a4,a5,last] = collect(last),
ok.
-send_after_3(doc) -> ["send_after/3: messages in the right order, worse than send_after_2"];
+%% send_after/3: messages in the right order, worse than send_after_2
send_after_3(Config) when is_list(Config) ->
_ = erlang:send_after(100, self(), b1),
_ = erlang:send_after(101, self(), b2),
@@ -157,74 +146,70 @@ send_after_3(Config) when is_list(Config) ->
_ = erlang:send_after(103, self(), last),
[b1, b2, b3, last] = collect(last),
-% This behaviour is not guaranteed:
-% ?line _ = erlang:send_after(100, self(), c1),
-% ?line _ = erlang:send_after(100, self(), c2),
-% ?line _ = erlang:send_after(100, self(), c3),
-% ?line _ = erlang:send_after(100, self(), last),
-% ?line [c1, c2, c3, last] = collect(last),
+ % This behaviour is not guaranteed:
+ % _ = erlang:send_after(100, self(), c1),
+ % _ = erlang:send_after(100, self(), c2),
+ % _ = erlang:send_after(100, self(), c3),
+ % _ = erlang:send_after(100, self(), last),
+ % [c1, c2, c3, last] = collect(last),
ok.
-cancel_timer_1(doc) -> ["Check trivial cancel_timer/1 behaviour"];
+%% Check trivial cancel_timer/1 behaviour
cancel_timer_1(Config) when is_list(Config) ->
- ?line false = erlang:cancel_timer(make_ref()),
+ false = erlang:cancel_timer(make_ref()),
ok.
-start_timer_e(doc) -> ["Error cases for start_timer/3"];
+%% Error cases for start_timer/3
start_timer_e(Config) when is_list(Config) ->
- ?line {'EXIT', _} = (catch erlang:start_timer(-4, self(), hej)),
- ?line {'EXIT', _} = (catch erlang:start_timer(1 bsl 64,
- self(), hej)),
+ {'EXIT', _} = (catch erlang:start_timer(-4, self(), hej)),
+ {'EXIT', _} = (catch erlang:start_timer(1 bsl 64,
+ self(), hej)),
- ?line {'EXIT', _} = (catch erlang:start_timer(4.5, self(), hej)),
- ?line {'EXIT', _} = (catch erlang:start_timer(a, self(), hej)),
+ {'EXIT', _} = (catch erlang:start_timer(4.5, self(), hej)),
+ {'EXIT', _} = (catch erlang:start_timer(a, self(), hej)),
- ?line Node = start_slave(),
- ?line Pid = spawn(Node, timer, sleep, [10000]),
- ?line {'EXIT', _} = (catch erlang:start_timer(1000, Pid, hej)),
- ?line stop_slave(Node),
+ Node = start_slave(),
+ Pid = spawn(Node, timer, sleep, [10000]),
+ {'EXIT', _} = (catch erlang:start_timer(1000, Pid, hej)),
+ stop_slave(Node),
ok.
-send_after_e(doc) -> ["Error cases for send_after/3"];
-send_after_e(suite) -> [];
+%% Error cases for send_after/3
send_after_e(Config) when is_list(Config) ->
- ?line {'EXIT', _} = (catch erlang:send_after(-4, self(), hej)),
- ?line {'EXIT', _} = (catch erlang:send_after(1 bsl 64,
- self(), hej)),
+ {'EXIT', _} = (catch erlang:send_after(-4, self(), hej)),
+ {'EXIT', _} = (catch erlang:send_after(1 bsl 64,
+ self(), hej)),
- ?line {'EXIT', _} = (catch erlang:send_after(4.5, self(), hej)),
- ?line {'EXIT', _} = (catch erlang:send_after(a, self(), hej)),
+ {'EXIT', _} = (catch erlang:send_after(4.5, self(), hej)),
+ {'EXIT', _} = (catch erlang:send_after(a, self(), hej)),
- ?line Node = start_slave(),
- ?line Pid = spawn(Node, timer, sleep, [10000]),
- ?line {'EXIT', _} = (catch erlang:send_after(1000, Pid, hej)),
- ?line stop_slave(Node),
+ Node = start_slave(),
+ Pid = spawn(Node, timer, sleep, [10000]),
+ {'EXIT', _} = (catch erlang:send_after(1000, Pid, hej)),
+ stop_slave(Node),
ok.
-cancel_timer_e(doc) -> ["Error cases for cancel_timer/1"];
-cancel_timer_e(suite) -> [];
+%% Error cases for cancel_timer/1
cancel_timer_e(Config) when is_list(Config) ->
- ?line {'EXIT', _} = (catch erlang:cancel_timer(1)),
- ?line {'EXIT', _} = (catch erlang:cancel_timer(self())),
- ?line {'EXIT', _} = (catch erlang:cancel_timer(a)),
+ {'EXIT', _} = (catch erlang:cancel_timer(1)),
+ {'EXIT', _} = (catch erlang:cancel_timer(self())),
+ {'EXIT', _} = (catch erlang:cancel_timer(a)),
ok.
-read_timer_trivial(doc) -> ["Trivial and error test cases for read_timer/1."];
-read_timer_trivial(suite) -> [];
+%% Trivial and error test cases for read_timer/1.
read_timer_trivial(Config) when is_list(Config) ->
- ?line false = erlang:read_timer(make_ref()),
- ?line {'EXIT', _} = (catch erlang:read_timer(42)),
- ?line {'EXIT', _} = (catch erlang:read_timer(423497834744444444457667444444)),
- ?line {'EXIT', _} = (catch erlang:read_timer(self())),
- ?line {'EXIT', _} = (catch erlang:read_timer(ab)),
+ false = erlang:read_timer(make_ref()),
+ {'EXIT', _} = (catch erlang:read_timer(42)),
+ {'EXIT', _} = (catch erlang:read_timer(423497834744444444457667444444)),
+ {'EXIT', _} = (catch erlang:read_timer(self())),
+ {'EXIT', _} = (catch erlang:read_timer(ab)),
ok.
-read_timer(doc) -> ["Test that read_timer/1 seems to return the correct values."];
-read_timer(suite) -> [];
+%% Test that read_timer/1 seems to return the correct values.
read_timer(Config) when is_list(Config) ->
process_flag(scheduler, 1),
Big = 1 bsl 31,
@@ -234,22 +219,21 @@ read_timer(Config) when is_list(Config) ->
Left = erlang:read_timer(R),
Left2 = erlang:cancel_timer(R),
case Left == Left2 of
- true -> ok;
- false -> Left = Left2 + 1
+ true -> ok;
+ false -> Left = Left2 + 1
end,
false = erlang:read_timer(R),
case Big - Left of
- Diff when Diff >= 200, Diff < 10000 ->
- ok;
- _Diff ->
- test_server:fail({big, Big, Left})
+ Diff when Diff >= 200, Diff < 10000 ->
+ ok;
+ _Diff ->
+ ct:fail({big, Big, Left})
end,
process_flag(scheduler, 0),
ok.
-read_timer_async(doc) -> ["Test that read_timer/1 seems to return the correct values."];
-read_timer_async(suite) -> [];
+%% Test that read_timer/1 seems to return the correct values.
read_timer_async(Config) when is_list(Config) ->
process_flag(scheduler, 1),
Big = 1 bsl 33,
@@ -266,73 +250,69 @@ read_timer_async(Config) when is_list(Config) ->
{read_timer, R, Left} = receive_one(),
{cancel_timer, R, Left2} = receive_one(),
case Left == Left2 of
- true -> ok;
- false -> Left = Left2 + 1
+ true -> ok;
+ false -> Left = Left2 + 1
end,
{read_timer, R, false} = receive_one(),
case Big - Left of
- Diff when Diff >= 200, Diff < 10000 ->
- ok;
- _Diff ->
- test_server:fail({big, Big, Left})
+ Diff when Diff >= 200, Diff < 10000 ->
+ ok;
+ _Diff ->
+ ct:fail({big, Big, Left})
end,
process_flag(scheduler, 0),
ok.
-cleanup(doc) -> [];
-cleanup(suite) -> [];
cleanup(Config) when is_list(Config) ->
- ?line Mem = mem(),
+ Mem = mem(),
%% Timer on dead process
- ?line P1 = spawn(fun () -> ok end),
- ?line wait_until(fun () -> process_is_cleaned_up(P1) end),
- ?line T1 = erlang:start_timer(?SHORT_TIMEOUT*2, P1, "hej"),
- ?line T2 = erlang:send_after(?SHORT_TIMEOUT*2, P1, "hej"),
+ P1 = spawn(fun () -> ok end),
+ wait_until(fun () -> process_is_cleaned_up(P1) end),
+ T1 = erlang:start_timer(?SHORT_TIMEOUT*2, P1, "hej"),
+ T2 = erlang:send_after(?SHORT_TIMEOUT*2, P1, "hej"),
receive after 1000 -> ok end,
- ?line Mem = mem(),
- ?line false = erlang:read_timer(T1),
- ?line false = erlang:read_timer(T2),
- ?line Mem = mem(),
+ Mem = mem(),
+ false = erlang:read_timer(T1),
+ false = erlang:read_timer(T2),
+ Mem = mem(),
%% Process dies before timeout
- ?line P2 = spawn(fun () -> receive after (?SHORT_TIMEOUT div 10) -> ok end end),
- ?line T3 = erlang:start_timer(?SHORT_TIMEOUT*2, P2, "hej"),
- ?line T4 = erlang:send_after(?SHORT_TIMEOUT*2, P2, "hej"),
- ?line true = mem_larger_than(Mem),
- ?line true = is_integer(erlang:read_timer(T3)),
- ?line true = is_integer(erlang:read_timer(T4)),
- ?line wait_until(fun () -> process_is_cleaned_up(P2) end),
+ P2 = spawn(fun () -> receive after (?SHORT_TIMEOUT div 10) -> ok end end),
+ T3 = erlang:start_timer(?SHORT_TIMEOUT*2, P2, "hej"),
+ T4 = erlang:send_after(?SHORT_TIMEOUT*2, P2, "hej"),
+ true = mem_larger_than(Mem),
+ true = is_integer(erlang:read_timer(T3)),
+ true = is_integer(erlang:read_timer(T4)),
+ wait_until(fun () -> process_is_cleaned_up(P2) end),
receive after 1000 -> ok end,
- ?line false = erlang:read_timer(T3),
- ?line false = erlang:read_timer(T4),
- ?line Mem = mem(),
+ false = erlang:read_timer(T3),
+ false = erlang:read_timer(T4),
+ Mem = mem(),
%% Cancel timer
- ?line P3 = spawn(fun () -> receive after ?SHORT_TIMEOUT*4 -> ok end end),
- ?line T5 = erlang:start_timer(?SHORT_TIMEOUT*2, P3, "hej"),
- ?line T6 = erlang:send_after(?SHORT_TIMEOUT*2, P3, "hej"),
- ?line true = mem_larger_than(Mem),
- ?line true = is_integer(erlang:cancel_timer(T5)),
- ?line true = is_integer(erlang:cancel_timer(T6)),
- ?line false = erlang:read_timer(T5),
- ?line false = erlang:read_timer(T6),
- ?line exit(P3, kill),
- ?line wait_until(fun () -> process_is_cleaned_up(P3) end),
- ?line Mem = mem(),
+ P3 = spawn(fun () -> receive after ?SHORT_TIMEOUT*4 -> ok end end),
+ T5 = erlang:start_timer(?SHORT_TIMEOUT*2, P3, "hej"),
+ T6 = erlang:send_after(?SHORT_TIMEOUT*2, P3, "hej"),
+ true = mem_larger_than(Mem),
+ true = is_integer(erlang:cancel_timer(T5)),
+ true = is_integer(erlang:cancel_timer(T6)),
+ false = erlang:read_timer(T5),
+ false = erlang:read_timer(T6),
+ exit(P3, kill),
+ wait_until(fun () -> process_is_cleaned_up(P3) end),
+ Mem = mem(),
%% Timeout
- ?line Ref = make_ref(),
- ?line T7 = erlang:start_timer(?SHORT_TIMEOUT+1, self(), Ref),
- ?line T8 = erlang:send_after(?SHORT_TIMEOUT+1, self(), Ref),
- ?line true = mem_larger_than(Mem),
- ?line true = is_integer(erlang:read_timer(T7)),
- ?line true = is_integer(erlang:read_timer(T8)),
- ?line receive {timeout, T7, Ref} -> ok end,
- ?line receive Ref -> ok end,
- ?line Mem = mem(),
- ?line ok.
-
-
-evil_timers(doc) -> [];
-evil_timers(suite) -> [];
+ Ref = make_ref(),
+ T7 = erlang:start_timer(?SHORT_TIMEOUT+1, self(), Ref),
+ T8 = erlang:send_after(?SHORT_TIMEOUT+1, self(), Ref),
+ true = mem_larger_than(Mem),
+ true = is_integer(erlang:read_timer(T7)),
+ true = is_integer(erlang:read_timer(T8)),
+ receive {timeout, T7, Ref} -> ok end,
+ receive Ref -> ok end,
+ Mem = mem(),
+ ok.
+
+
evil_timers(Config) when is_list(Config) ->
%% Create a composite term consisting of at least:
%% * externals (remote pids, ports, and refs)
@@ -344,38 +324,38 @@ evil_timers(Config) when is_list(Config) ->
%% * lists
%% since data of these types have to be adjusted if moved
%% in memory
- ?line Self = self(),
- ?line R1 = make_ref(),
- ?line Node = start_slave(),
- ?line spawn_link(Node,
- fun () ->
- Self ! {R1,
- [lists:sublist(erlang:ports(), 3),
- [make_ref(), make_ref(), make_ref()],
- lists:sublist(processes(), 3),
- [fun () -> gurka end,
- fun (A) -> A + 1 end,
- fun (A, B) -> A + B end]]}
- end),
- ?line ExtList = receive {R1, L} -> L end,
- ?line stop_slave(Node),
- ?line BinList = [<<"bla">>,
- <<"blipp">>,
- <<"blupp">>,
- list_to_binary(lists:duplicate(1000000,$a)),
- list_to_binary(lists:duplicate(1000000,$b)),
- list_to_binary(lists:duplicate(1000000,$c))],
- ?line FunList = [fun () -> gurka end,
- fun (A) -> A + 1 end,
- fun (A, B) -> A + B end],
- ?line PidList = lists:sublist(processes(), 3),
- ?line PortList = lists:sublist(erlang:ports(), 3),
- ?line RefList = [make_ref(), make_ref(), make_ref()],
- ?line BigList = [111111111111, 22222222222222, 333333333333333333],
- ?line Msg = {BinList,[FunList,{RefList,ExtList,PidList,PortList,BigList}]},
- %% ?line ?t:format("Msg=~p~n",[Msg]),
-
- ?line Prio = process_flag(priority, max),
+ Self = self(),
+ R1 = make_ref(),
+ Node = start_slave(),
+ spawn_link(Node,
+ fun () ->
+ Self ! {R1,
+ [lists:sublist(erlang:ports(), 3),
+ [make_ref(), make_ref(), make_ref()],
+ lists:sublist(processes(), 3),
+ [fun () -> gurka end,
+ fun (A) -> A + 1 end,
+ fun (A, B) -> A + B end]]}
+ end),
+ ExtList = receive {R1, L} -> L end,
+ stop_slave(Node),
+ BinList = [<<"bla">>,
+ <<"blipp">>,
+ <<"blupp">>,
+ list_to_binary(lists:duplicate(1000000,$a)),
+ list_to_binary(lists:duplicate(1000000,$b)),
+ list_to_binary(lists:duplicate(1000000,$c))],
+ FunList = [fun () -> gurka end,
+ fun (A) -> A + 1 end,
+ fun (A, B) -> A + B end],
+ PidList = lists:sublist(processes(), 3),
+ PortList = lists:sublist(erlang:ports(), 3),
+ RefList = [make_ref(), make_ref(), make_ref()],
+ BigList = [111111111111, 22222222222222, 333333333333333333],
+ Msg = {BinList,[FunList,{RefList,ExtList,PidList,PortList,BigList}]},
+ %% io:format("Msg=~p~n",[Msg]),
+
+ Prio = process_flag(priority, max),
%%
%% In the smp case there are four major cases we want to test:
%%
@@ -388,8 +368,8 @@ evil_timers(Config) when is_list(Config) ->
%% be allocated in the previously allocated message buffer along
%% with Msg, i.e. the previously allocated message buffer will be
%% reallocated and potentially moved.
- ?line TimeOutMsgs0 = evil_setup_timers(200, Self, Msg),
- ?line RecvTimeOutMsgs0 = evil_recv_timeouts(200),
+ TimeOutMsgs0 = evil_setup_timers(200, Self, Msg),
+ RecvTimeOutMsgs0 = evil_recv_timeouts(200),
%% 2. A timer started with erlang:start_timer(Time, Receiver, Msg),
%% where Msg is an immediate term, expires, and the receivers main
%% lock *can not* be acquired immediately (typically when the
@@ -397,8 +377,8 @@ evil_timers(Config) when is_list(Config) ->
%%
%% The wrap tuple will in this case be allocated in a new
%% message buffer.
- ?line TimeOutMsgs1 = evil_setup_timers(200, Self, immediate),
- ?line RecvTimeOutMsgs1 = evil_recv_timeouts(200),
+ TimeOutMsgs1 = evil_setup_timers(200, Self, immediate),
+ RecvTimeOutMsgs1 = evil_recv_timeouts(200),
%% 3. A timer started with erlang:start_timer(Time, Receiver, Msg),
%% where Msg is a composite term, expires, and the receivers main
%% lock *can* be acquired immediately (typically when the receiver
@@ -407,13 +387,13 @@ evil_timers(Config) when is_list(Config) ->
%% The wrap tuple will in this case be allocated on the receivers
%% heap, and Msg is passed in the previously allocated message
%% buffer.
- ?line R2 = make_ref(),
- ?line spawn_link(fun () ->
- Self ! {R2, evil_setup_timers(200, Self, Msg)}
- end),
- ?line receive after 1000 -> ok end,
- ?line TimeOutMsgs2 = receive {R2, TOM2} -> TOM2 end,
- ?line RecvTimeOutMsgs2 = evil_recv_timeouts(200),
+ R2 = make_ref(),
+ spawn_link(fun () ->
+ Self ! {R2, evil_setup_timers(200, Self, Msg)}
+ end),
+ receive after 1000 -> ok end,
+ TimeOutMsgs2 = receive {R2, TOM2} -> TOM2 end,
+ RecvTimeOutMsgs2 = evil_recv_timeouts(200),
%% 4. A timer started with erlang:start_timer(Time, Receiver, Msg),
%% where Msg is an immediate term, expires, and the Receivers main
%% lock *can* be acquired immediately (typically when the receiver
@@ -421,109 +401,107 @@ evil_timers(Config) when is_list(Config) ->
%%
%% The wrap tuple will in this case be allocated on the receivers
%% heap.
- ?line R3 = make_ref(),
- ?line spawn_link(fun () ->
- Self ! {R3, evil_setup_timers(200,Self,immediate)}
- end),
- ?line receive after 1000 -> ok end,
- ?line TimeOutMsgs3 = receive {R3, TOM3} -> TOM3 end,
- ?line RecvTimeOutMsgs3 = evil_recv_timeouts(200),
+ R3 = make_ref(),
+ spawn_link(fun () ->
+ Self ! {R3, evil_setup_timers(200,Self,immediate)}
+ end),
+ receive after 1000 -> ok end,
+ TimeOutMsgs3 = receive {R3, TOM3} -> TOM3 end,
+ RecvTimeOutMsgs3 = evil_recv_timeouts(200),
%% Garge collection will hopefully crash the emulator if something
%% is wrong...
- ?line garbage_collect(),
- ?line garbage_collect(),
- ?line garbage_collect(),
+ garbage_collect(),
+ garbage_collect(),
+ garbage_collect(),
%% Make sure we got the timeouts we expected
%%
%% Note timeouts are *not* guaranteed to be delivered in order
- ?line ok = match(lists:sort(RecvTimeOutMsgs0), lists:sort(TimeOutMsgs0)),
- ?line ok = match(lists:sort(RecvTimeOutMsgs1), lists:sort(TimeOutMsgs1)),
- ?line ok = match(lists:sort(RecvTimeOutMsgs2), lists:sort(TimeOutMsgs2)),
- ?line ok = match(lists:sort(RecvTimeOutMsgs3), lists:sort(TimeOutMsgs3)),
+ ok = match(lists:sort(RecvTimeOutMsgs0), lists:sort(TimeOutMsgs0)),
+ ok = match(lists:sort(RecvTimeOutMsgs1), lists:sort(TimeOutMsgs1)),
+ ok = match(lists:sort(RecvTimeOutMsgs2), lists:sort(TimeOutMsgs2)),
+ ok = match(lists:sort(RecvTimeOutMsgs3), lists:sort(TimeOutMsgs3)),
- ?line process_flag(priority, Prio),
- ?line ok.
+ process_flag(priority, Prio),
+ ok.
evil_setup_timers(N, Receiver, Msg) ->
- ?line evil_setup_timers(0, N, Receiver, Msg, []).
+ evil_setup_timers(0, N, Receiver, Msg, []).
evil_setup_timers(N, N, _Receiver, _Msg, TOs) ->
- ?line TOs;
+ TOs;
evil_setup_timers(N, Max, Receiver, Msg, TOs) ->
- ?line TRef = erlang:start_timer(N, Receiver, Msg),
- ?line evil_setup_timers(N+1, Max, Receiver, Msg, [{timeout,TRef,Msg}|TOs]).
+ TRef = erlang:start_timer(N, Receiver, Msg),
+ evil_setup_timers(N+1, Max, Receiver, Msg, [{timeout,TRef,Msg}|TOs]).
evil_recv_timeouts(M) ->
- ?line evil_recv_timeouts([], 0, M).
+ evil_recv_timeouts([], 0, M).
evil_recv_timeouts(TOs, N, N) ->
- ?line TOs;
+ TOs;
evil_recv_timeouts(TOs, N, M) ->
- ?line receive
- {timeout, _, _} = TO ->
- ?line evil_recv_timeouts([TO|TOs], N+1, M)
- after 0 ->
- ?line evil_recv_timeouts(TOs, N, M)
- end.
-
-registered_process(doc) -> [];
-registered_process(suite) -> [];
+ receive
+ {timeout, _, _} = TO ->
+ evil_recv_timeouts([TO|TOs], N+1, M)
+ after 0 ->
+ evil_recv_timeouts(TOs, N, M)
+ end.
+
registered_process(Config) when is_list(Config) ->
- ?line Mem = mem(),
+ Mem = mem(),
%% Cancel
- ?line T1 = erlang:start_timer(?SHORT_TIMEOUT+1, ?MODULE, "hej"),
- ?line T2 = erlang:send_after(?SHORT_TIMEOUT+1, ?MODULE, "hej"),
- ?line undefined = whereis(?MODULE),
- ?line true = mem_larger_than(Mem),
- ?line true = is_integer(erlang:cancel_timer(T1)),
- ?line true = is_integer(erlang:cancel_timer(T2)),
- ?line false = erlang:read_timer(T1),
- ?line false = erlang:read_timer(T2),
- ?line Mem = mem(),
+ T1 = erlang:start_timer(?SHORT_TIMEOUT+1, ?MODULE, "hej"),
+ T2 = erlang:send_after(?SHORT_TIMEOUT+1, ?MODULE, "hej"),
+ undefined = whereis(?MODULE),
+ true = mem_larger_than(Mem),
+ true = is_integer(erlang:cancel_timer(T1)),
+ true = is_integer(erlang:cancel_timer(T2)),
+ false = erlang:read_timer(T1),
+ false = erlang:read_timer(T2),
+ Mem = mem(),
%% Timeout register after start
- ?line Ref1 = make_ref(),
- ?line T3 = erlang:start_timer(?SHORT_TIMEOUT+1, ?MODULE, Ref1),
- ?line T4 = erlang:send_after(?SHORT_TIMEOUT+1, ?MODULE, Ref1),
- ?line undefined = whereis(?MODULE),
- ?line true = mem_larger_than(Mem),
- ?line true = is_integer(erlang:read_timer(T3)),
- ?line true = is_integer(erlang:read_timer(T4)),
- ?line true = register(?MODULE, self()),
- ?line receive {timeout, T3, Ref1} -> ok end,
- ?line receive Ref1 -> ok end,
- ?line Mem = mem(),
+ Ref1 = make_ref(),
+ T3 = erlang:start_timer(?SHORT_TIMEOUT+1, ?MODULE, Ref1),
+ T4 = erlang:send_after(?SHORT_TIMEOUT+1, ?MODULE, Ref1),
+ undefined = whereis(?MODULE),
+ true = mem_larger_than(Mem),
+ true = is_integer(erlang:read_timer(T3)),
+ true = is_integer(erlang:read_timer(T4)),
+ true = register(?MODULE, self()),
+ receive {timeout, T3, Ref1} -> ok end,
+ receive Ref1 -> ok end,
+ Mem = mem(),
%% Timeout register before start
- ?line Ref2 = make_ref(),
- ?line T5 = erlang:start_timer(?SHORT_TIMEOUT+1, ?MODULE, Ref2),
- ?line T6 = erlang:send_after(?SHORT_TIMEOUT+1, ?MODULE, Ref2),
- ?line true = mem_larger_than(Mem),
- ?line true = is_integer(erlang:read_timer(T5)),
- ?line true = is_integer(erlang:read_timer(T6)),
- ?line receive {timeout, T5, Ref2} -> ok end,
- ?line receive Ref2 -> ok end,
- ?line Mem = mem(),
- ?line true = unregister(?MODULE),
- ?line ok.
+ Ref2 = make_ref(),
+ T5 = erlang:start_timer(?SHORT_TIMEOUT+1, ?MODULE, Ref2),
+ T6 = erlang:send_after(?SHORT_TIMEOUT+1, ?MODULE, Ref2),
+ true = mem_larger_than(Mem),
+ true = is_integer(erlang:read_timer(T5)),
+ true = is_integer(erlang:read_timer(T6)),
+ receive {timeout, T5, Ref2} -> ok end,
+ receive Ref2 -> ok end,
+ Mem = mem(),
+ true = unregister(?MODULE),
+ ok.
same_time_yielding(Config) when is_list(Config) ->
Mem = mem(),
SchdlrsOnln = erlang:system_info(schedulers_online),
Tmo = erlang:monotonic_time(milli_seconds) + 3000,
Tmrs = lists:map(fun (I) ->
- process_flag(scheduler, (I rem SchdlrsOnln) + 1),
- erlang:start_timer(Tmo, self(), hej, [{abs, true}])
- end,
- lists:seq(1, (?TIMEOUT_YIELD_LIMIT*3+1)*SchdlrsOnln)),
+ process_flag(scheduler, (I rem SchdlrsOnln) + 1),
+ erlang:start_timer(Tmo, self(), hej, [{abs, true}])
+ end,
+ lists:seq(1, (?TIMEOUT_YIELD_LIMIT*3+1)*SchdlrsOnln)),
true = mem_larger_than(Mem),
lists:foreach(fun (Tmr) -> receive {timeout, Tmr, hej} -> ok end end, Tmrs),
Done = erlang:monotonic_time(milli_seconds),
true = Done >= Tmo,
case erlang:system_info(build_type) of
- opt -> true = Done < Tmo + 200;
- _ -> true = Done < Tmo + 1000
+ opt -> true = Done < Tmo + 200;
+ _ -> true = Done < Tmo + 1000
end,
Mem = mem(),
ok.
@@ -539,19 +517,19 @@ same_time_yielding_with_cancel_other(Config) when is_list(Config) ->
do_cancel_tmrs(Tmo, Tmrs, Tester) ->
BeginCancel = erlang:convert_time_unit(Tmo,
- milli_seconds,
- micro_seconds) - 100,
+ milli_seconds,
+ micro_seconds) - 100,
busy_wait_until(fun () ->
- erlang:monotonic_time(micro_seconds) >= BeginCancel
- end),
+ erlang:monotonic_time(micro_seconds) >= BeginCancel
+ end),
lists:foreach(fun (Tmr) ->
- erlang:cancel_timer(Tmr,
- [{async, true},
- {info, true}])
- end, Tmrs),
+ erlang:cancel_timer(Tmr,
+ [{async, true},
+ {info, true}])
+ end, Tmrs),
case Tester == self() of
- true -> ok;
- false -> forward_msgs(Tester)
+ true -> ok;
+ false -> forward_msgs(Tester)
end.
same_time_yielding_with_cancel_test(Other, Accessor) ->
@@ -560,57 +538,57 @@ same_time_yielding_with_cancel_test(Other, Accessor) ->
Tmo = erlang:monotonic_time(milli_seconds) + 3000,
Tester = self(),
Cancelor = case Other of
- false ->
- Tester;
- true ->
- spawn(fun () ->
- receive
- {timers, Tmrs} ->
- do_cancel_tmrs(Tmo, Tmrs, Tester)
- end
- end)
- end,
+ false ->
+ Tester;
+ true ->
+ spawn(fun () ->
+ receive
+ {timers, Tmrs} ->
+ do_cancel_tmrs(Tmo, Tmrs, Tester)
+ end
+ end)
+ end,
Opts = case Accessor of
- false -> [{abs, true}];
- true -> [{accessor, Cancelor}, {abs, true}]
- end,
+ false -> [{abs, true}];
+ true -> [{accessor, Cancelor}, {abs, true}]
+ end,
Tmrs = lists:map(fun (I) ->
- process_flag(scheduler, (I rem SchdlrsOnln) + 1),
- erlang:start_timer(Tmo, self(), hej, Opts)
- end,
- lists:seq(1, (?TIMEOUT_YIELD_LIMIT*3+1)*SchdlrsOnln)),
+ process_flag(scheduler, (I rem SchdlrsOnln) + 1),
+ erlang:start_timer(Tmo, self(), hej, Opts)
+ end,
+ lists:seq(1, (?TIMEOUT_YIELD_LIMIT*3+1)*SchdlrsOnln)),
true = mem_larger_than(Mem),
case Other of
- false ->
- do_cancel_tmrs(Tmo, Tmrs, Tester);
- true ->
- Cancelor ! {timers, Tmrs}
+ false ->
+ do_cancel_tmrs(Tmo, Tmrs, Tester);
+ true ->
+ Cancelor ! {timers, Tmrs}
end,
{Tmos, Cncls} = lists:foldl(fun (Tmr, {T, C}) ->
- receive
- {timeout, Tmr, hej} ->
- receive
- {cancel_timer, Tmr, Info} ->
- false = Info,
- {T+1, C}
- end;
- {cancel_timer, Tmr, false} ->
- receive
- {timeout, Tmr, hej} ->
- {T+1, C}
- end;
- {cancel_timer, Tmr, TimeLeft} ->
- true = is_integer(TimeLeft),
- {T, C+1}
- end
- end,
- {0, 0},
- Tmrs),
+ receive
+ {timeout, Tmr, hej} ->
+ receive
+ {cancel_timer, Tmr, Info} ->
+ false = Info,
+ {T+1, C}
+ end;
+ {cancel_timer, Tmr, false} ->
+ receive
+ {timeout, Tmr, hej} ->
+ {T+1, C}
+ end;
+ {cancel_timer, Tmr, TimeLeft} ->
+ true = is_integer(TimeLeft),
+ {T, C+1}
+ end
+ end,
+ {0, 0},
+ Tmrs),
io:format("Timeouts: ~p Cancels: ~p~n", [Tmos, Cncls]),
Mem = mem(),
case Other of
- true -> exit(Cancelor, bang);
- false -> ok
+ true -> exit(Cancelor, bang);
+ false -> ok
end,
{comment,
"Timeouts: " ++ integer_to_list(Tmos) ++ " Cancels: "
@@ -620,16 +598,16 @@ auto_cancel_yielding(Config) when is_list(Config) ->
Mem = mem(),
SchdlrsOnln = erlang:system_info(schedulers_online),
P = spawn(fun () ->
- lists:foreach(
- fun (I) ->
- process_flag(scheduler, (I rem SchdlrsOnln)+1),
- erlang:start_timer((1 bsl 28)+I*10, self(), hej)
- end,
- lists:seq(1,
- ((?AUTO_CANCEL_YIELD_LIMIT*3+1)
- *SchdlrsOnln))),
- receive after infinity -> ok end
- end),
+ lists:foreach(
+ fun (I) ->
+ process_flag(scheduler, (I rem SchdlrsOnln)+1),
+ erlang:start_timer((1 bsl 28)+I*10, self(), hej)
+ end,
+ lists:seq(1,
+ ((?AUTO_CANCEL_YIELD_LIMIT*3+1)
+ *SchdlrsOnln))),
+ receive after infinity -> ok end
+ end),
true = mem_larger_than(Mem),
exit(P, bang),
wait_until(fun () -> process_is_cleaned_up(P) end),
@@ -641,46 +619,46 @@ process_is_cleaned_up(P) when is_pid(P) ->
wait_until(Pred) when is_function(Pred) ->
case catch Pred() of
- true -> ok;
- _ -> receive after 50 -> ok end, wait_until(Pred)
+ true -> ok;
+ _ -> receive after 50 -> ok end, wait_until(Pred)
end.
busy_wait_until(Pred) when is_function(Pred) ->
case catch Pred() of
- true -> ok;
- _ -> busy_wait_until(Pred)
+ true -> ok;
+ _ -> busy_wait_until(Pred)
end.
forward_msgs(To) ->
receive
- Msg ->
- To ! Msg
+ Msg ->
+ To ! Msg
end,
forward_msgs(To).
get(Time, Msg) ->
receive
- Msg ->
- ok
+ Msg ->
+ ok
after Time
- ->
- no_message
+ ->
+ no_message
end.
get_msg() ->
receive
- Msg ->
- {ok, Msg}
+ Msg ->
+ {ok, Msg}
after 0 ->
- empty
+ empty
end.
start_slave() ->
- ?line Pa = filename:dirname(code:which(?MODULE)),
- ?line Name = atom_to_list(?MODULE)
- ++ "-" ++ integer_to_list(erlang:system_time(seconds))
- ++ "-" ++ integer_to_list(erlang:unique_integer([positive])),
- {ok, Node} = ?t:start_node(Name, slave, [{args, "-pa " ++ Pa}]),
+ Pa = filename:dirname(code:which(?MODULE)),
+ Name = atom_to_list(?MODULE)
+ ++ "-" ++ integer_to_list(erlang:system_time(seconds))
+ ++ "-" ++ integer_to_list(erlang:unique_integer([positive])),
+ {ok, Node} = test_server:start_node(Name, slave, [{args, "-pa " ++ Pa}]),
Node.
stop_slave(Node) ->
@@ -691,18 +669,18 @@ collect(Last) ->
receive_one() ->
receive
- Msg ->
- Msg
+ Msg ->
+ Msg
end.
collect(Last, Msgs0) ->
Msg = receive_one(),
Msgs = Msgs0 ++ [Msg],
case Msg of
- Last ->
- Msgs;
- _ ->
- collect(Last, Msgs)
+ Last ->
+ Msgs;
+ _ ->
+ collect(Last, Msgs)
end.
match(X, X) ->
@@ -751,8 +729,8 @@ mem() ->
erts_debug:set_internal_state(wait, timer_cancellations),
erts_debug:set_internal_state(wait, deallocations),
case mem_get() of
- {-1, -1} -> no_fix_alloc;
- {A, U} -> io:format("mem = ~p ~p~n", [A, U]), U
+ {-1, -1} -> no_fix_alloc;
+ {A, U} -> io:format("mem = ~p ~p~n", [A, U]), U
end.
mem_get() ->
@@ -765,8 +743,8 @@ mem_recv(0, _Ref, AU) ->
AU;
mem_recv(N, Ref, AU) ->
receive
- {Ref, _, IL} ->
- mem_recv(N-1, Ref, mem_parse_ilists(IL, AU))
+ {Ref, _, IL} ->
+ mem_recv(N-1, Ref, mem_parse_ilists(IL, AU))
end.
@@ -779,19 +757,19 @@ mem_parse_ilist({fix_alloc, false}, _) ->
{-1, -1};
mem_parse_ilist({fix_alloc, _, IDL}, {A, U}) ->
case lists:keyfind(fix_types, 1, IDL) of
- {fix_types, TL} ->
- {ThisA, ThisU} = mem_get_btm_aus(TL, 0, 0),
- {ThisA + A, ThisU + U};
- {fix_types, Mask, TL} ->
- {ThisA, ThisU} = mem_get_btm_aus(TL, 0, 0),
- {(ThisA + A) band Mask , (ThisU + U) band Mask}
+ {fix_types, TL} ->
+ {ThisA, ThisU} = mem_get_btm_aus(TL, 0, 0),
+ {ThisA + A, ThisU + U};
+ {fix_types, Mask, TL} ->
+ {ThisA, ThisU} = mem_get_btm_aus(TL, 0, 0),
+ {(ThisA + A) band Mask , (ThisU + U) band Mask}
end.
mem_get_btm_aus([], A, U) ->
{A, U};
mem_get_btm_aus([{BtmType, BtmA, BtmU} | Types],
- A, U) when BtmType == bif_timer;
- BtmType == accessor_bif_timer ->
+ A, U) when BtmType == bif_timer;
+ BtmType == accessor_bif_timer ->
mem_get_btm_aus(Types, BtmA+A, BtmU+U);
mem_get_btm_aus([_|Types], A, U) ->
mem_get_btm_aus(Types, A, U).
diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl
index 6eae182e45..dcd5e95434 100644
--- a/erts/emulator/test/trace_SUITE.erl
+++ b/erts/emulator/test/trace_SUITE.erl
@@ -24,8 +24,8 @@
%%% Tests the trace BIF.
%%%
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2, receive_trace/1, self_send/1,
+-export([all/0, suite/0,
+ receive_trace/1, self_send/1,
timeout_trace/1, send_trace/1,
procs_trace/1, dist_procs_trace/1,
suspend/1, mutual_suspend/1, suspend_exit/1, suspender_exit/1,
@@ -38,12 +38,14 @@
system_monitor_long_schedule/1,
bad_flag/1, trace_delivered/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%%% Internal exports
-export([process/1]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {seconds, 5}}].
all() ->
[cpu_timestamp, receive_trace, self_send, timeout_trace,
@@ -54,133 +56,101 @@ all() ->
set_on_first_spawn, system_monitor_args,
more_system_monitor_args, system_monitor_long_gc_1,
system_monitor_long_gc_2, system_monitor_large_heap_1,
- system_monitor_long_schedule,
+ system_monitor_long_schedule,
system_monitor_large_heap_2, bad_flag, trace_delivered].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
%% No longer testing anything, just reporting whether cpu_timestamp
%% is enabled or not.
cpu_timestamp(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
-
%% Test whether cpu_timestamp is implemented on this platform.
- ?line Works = try erlang:trace(all, true, [cpu_timestamp]) of
- _ ->
- ?line erlang:trace(all, false, [cpu_timestamp]),
- true
- catch
- error:badarg -> false
- end,
-
- ?line test_server:timetrap_cancel(Dog),
+ Works = try erlang:trace(all, true, [cpu_timestamp]) of
+ _ ->
+ erlang:trace(all, false, [cpu_timestamp]),
+ true
+ catch
+ error:badarg -> false
+ end,
{comment,case Works of
- false -> "cpu_timestamp is NOT implemented/does not work";
- true -> "cpu_timestamp works"
- end}.
+ false -> "cpu_timestamp is NOT implemented/does not work";
+ true -> "cpu_timestamp works"
+ end}.
%% Tests that trace(Pid, How, ['receive']) works.
receive_trace(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line Receiver = fun_spawn(fun receiver/0),
- ?line process_flag(trap_exit, true),
+ Receiver = fun_spawn(fun receiver/0),
+ process_flag(trap_exit, true),
%% Trace the process; make sure that we receive the trace messages.
- ?line 1 = erlang:trace(Receiver, true, ['receive']),
- ?line Hello = {hello, world},
- ?line Receiver ! Hello,
- ?line {trace, Receiver, 'receive', Hello} = receive_first(),
- ?line Hello2 = {hello, again, world},
- ?line Receiver ! Hello2,
- ?line {trace, Receiver, 'receive', Hello2} = receive_first(),
- ?line receive_nothing(),
+ 1 = erlang:trace(Receiver, true, ['receive']),
+ Hello = {hello, world},
+ Receiver ! Hello,
+ {trace, Receiver, 'receive', Hello} = receive_first(),
+ Hello2 = {hello, again, world},
+ Receiver ! Hello2,
+ {trace, Receiver, 'receive', Hello2} = receive_first(),
+ receive_nothing(),
%% Another process should not be able to trace Receiver.
- ?line Intruder = fun_spawn(fun() -> erlang:trace(Receiver, true, ['receive']) end),
- ?line {'EXIT', Intruder, {badarg, _}} = receive_first(),
+ Intruder = fun_spawn(fun() -> erlang:trace(Receiver, true, ['receive']) end),
+ {'EXIT', Intruder, {badarg, _}} = receive_first(),
%% Untrace the process; we should not receive anything.
- ?line 1 = erlang:trace(Receiver, false, ['receive']),
- ?line Receiver ! {hello, there},
- ?line Receiver ! any_garbage,
- ?line receive_nothing(),
-
- %% Done.
- ?line test_server:timetrap_cancel(Dog),
+ 1 = erlang:trace(Receiver, false, ['receive']),
+ Receiver ! {hello, there},
+ Receiver ! any_garbage,
+ receive_nothing(),
ok.
-self_send(doc) -> ["Test that traces are generated for messages sent ",
- "and received to/from self()."];
+%% Test that traces are generated for messages sent
+%% and received to/from self().
self_send(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line Fun =
- fun(Self, Parent) -> receive
- go_ahead ->
- self() ! from_myself,
- Self(Self, Parent);
- from_myself ->
- Parent ! done
- end
- end,
- ?line Self = self(),
- ?line SelfSender = fun_spawn(Fun, [Fun, Self]),
- ?line erlang:trace(SelfSender, true, ['receive', 'send']),
- ?line SelfSender ! go_ahead,
- ?line receive {trace, SelfSender, 'receive', go_ahead} -> ok end,
- ?line receive {trace, SelfSender, 'receive', from_myself} -> ok end,
- ?line receive
- {trace,SelfSender,send,from_myself,SelfSender} -> ok
- end,
- ?line receive {trace,SelfSender,send,done,Self} -> ok end,
- ?line receive done -> ok end,
-
- ?line test_server:timetrap_cancel(Dog),
+ Fun =
+ fun(Self, Parent) -> receive
+ go_ahead ->
+ self() ! from_myself,
+ Self(Self, Parent);
+ from_myself ->
+ Parent ! done
+ end
+ end,
+ Self = self(),
+ SelfSender = fun_spawn(Fun, [Fun, Self]),
+ erlang:trace(SelfSender, true, ['receive', 'send']),
+ SelfSender ! go_ahead,
+ receive {trace, SelfSender, 'receive', go_ahead} -> ok end,
+ receive {trace, SelfSender, 'receive', from_myself} -> ok end,
+ receive
+ {trace,SelfSender,send,from_myself,SelfSender} -> ok
+ end,
+ receive {trace,SelfSender,send,done,Self} -> ok end,
+ receive done -> ok end,
ok.
%% Test that we can receive timeout traces.
timeout_trace(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
-
- ?line Process = fun_spawn(fun process/0),
- ?line 1 = erlang:trace(Process, true, ['receive']),
- ?line Process ! timeout_please,
- ?line {trace, Process, 'receive', timeout_please} = receive_first(),
- ?line {trace, Process, 'receive', timeout} = receive_first(),
- ?line receive_nothing(),
-
- ?line test_server:timetrap_cancel(Dog),
+ Process = fun_spawn(fun process/0),
+ 1 = erlang:trace(Process, true, ['receive']),
+ Process ! timeout_please,
+ {trace, Process, 'receive', timeout_please} = receive_first(),
+ {trace, Process, 'receive', timeout} = receive_first(),
+ receive_nothing(),
ok.
%% Tests that trace(Pid, How, [send]) works.
send_trace(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line process_flag(trap_exit, true),
- ?line Sender = fun_spawn(fun sender/0),
- ?line Receiver = fun_spawn(fun receiver/0),
+ process_flag(trap_exit, true),
+ Sender = fun_spawn(fun sender/0),
+ Receiver = fun_spawn(fun receiver/0),
%% Check that a message sent to another process is traced.
- ?line 1 = erlang:trace(Sender, true, [send]),
- ?line Sender ! {send_please, Receiver, to_receiver},
- ?line {trace, Sender, send, to_receiver, Receiver} = receive_first(),
- ?line receive_nothing(),
+ 1 = erlang:trace(Sender, true, [send]),
+ Sender ! {send_please, Receiver, to_receiver},
+ {trace, Sender, send, to_receiver, Receiver} = receive_first(),
+ receive_nothing(),
%% Check that a message sent to another registered process is traced.
register(?MODULE,Receiver),
@@ -190,11 +160,11 @@ send_trace(Config) when is_list(Config) ->
unregister(?MODULE),
%% Check that a message sent to this process is traced.
- ?line Sender ! {send_please, self(), to_myself},
- ?line receive to_myself -> ok end,
- ?line Self = self(),
- ?line {trace, Sender, send, to_myself, Self} = receive_first(),
- ?line receive_nothing(),
+ Sender ! {send_please, self(), to_myself},
+ receive to_myself -> ok end,
+ Self = self(),
+ {trace, Sender, send, to_myself, Self} = receive_first(),
+ receive_nothing(),
%% Check that a message sent to dead process is traced.
{Pid,Ref} = spawn_monitor(fun() -> ok end),
@@ -212,174 +182,166 @@ send_trace(Config) when is_list(Config) ->
receive_nothing(),
%% Another process should not be able to trace Sender.
- ?line Intruder = fun_spawn(fun() -> erlang:trace(Sender, true, [send]) end),
- ?line {'EXIT', Intruder, {badarg, _}} = receive_first(),
+ Intruder = fun_spawn(fun() -> erlang:trace(Sender, true, [send]) end),
+ {'EXIT', Intruder, {badarg, _}} = receive_first(),
%% Untrace the sender process and make sure that we receive no more
%% trace messages.
- ?line 1 = erlang:trace(Sender, false, [send]),
- ?line Sender ! {send_please, Receiver, to_receiver},
- ?line Sender ! {send_please, self(), to_myself_again},
- ?line receive to_myself_again -> ok end,
- ?line receive_nothing(),
-
- %% Done.
- ?line test_server:timetrap_cancel(Dog),
+ 1 = erlang:trace(Sender, false, [send]),
+ Sender ! {send_please, Receiver, to_receiver},
+ Sender ! {send_please, self(), to_myself_again},
+ receive to_myself_again -> ok end,
+ receive_nothing(),
ok.
%% Test trace(Pid, How, [procs]).
procs_trace(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line Name = list_to_atom(atom_to_list(?MODULE)++"_procs_trace"),
- ?line Self = self(),
- ?line process_flag(trap_exit, true),
+ Name = list_to_atom(atom_to_list(?MODULE)++"_procs_trace"),
+ Self = self(),
+ process_flag(trap_exit, true),
%%
- ?line Proc1 = spawn_link(?MODULE, process, [Self]),
- ?line io:format("Proc1 = ~p ~n", [Proc1]),
- ?line Proc2 = spawn(?MODULE, process, [Self]),
- ?line io:format("Proc2 = ~p ~n", [Proc2]),
+ Proc1 = spawn_link(?MODULE, process, [Self]),
+ io:format("Proc1 = ~p ~n", [Proc1]),
+ Proc2 = spawn(?MODULE, process, [Self]),
+ io:format("Proc2 = ~p ~n", [Proc2]),
%%
- ?line 1 = erlang:trace(Proc1, true, [procs]),
- ?line MFA = {?MODULE, process, [Self]},
+ 1 = erlang:trace(Proc1, true, [procs]),
+ MFA = {?MODULE, process, [Self]},
%%
%% spawn, link
- ?line Proc1 ! {spawn_link_please, Self, MFA},
- ?line Proc3 = receive {spawned, Proc1, P3} -> P3 end,
- ?line {trace, Proc1, spawn, Proc3, MFA} = receive_first(),
- ?line io:format("Proc3 = ~p ~n", [Proc3]),
- ?line {trace, Proc1, link, Proc3} = receive_first(),
- ?line receive_nothing(),
+ Proc1 ! {spawn_link_please, Self, MFA},
+ Proc3 = receive {spawned, Proc1, P3} -> P3 end,
+ {trace, Proc1, spawn, Proc3, MFA} = receive_first(),
+ io:format("Proc3 = ~p ~n", [Proc3]),
+ {trace, Proc1, link, Proc3} = receive_first(),
+ receive_nothing(),
%%
%% getting_unlinked by exit()
- ?line Proc1 ! {trap_exit_please, true},
- ?line Reason3 = make_ref(),
- ?line Proc1 ! {send_please, Proc3, {exit_please, Reason3}},
- ?line receive {Proc1, {'EXIT', Proc3, Reason3}} -> ok end,
- ?line {trace, Proc1, getting_unlinked, Proc3} = receive_first(),
- ?line Proc1 ! {trap_exit_please, false},
- ?line receive_nothing(),
+ Proc1 ! {trap_exit_please, true},
+ Reason3 = make_ref(),
+ Proc1 ! {send_please, Proc3, {exit_please, Reason3}},
+ receive {Proc1, {'EXIT', Proc3, Reason3}} -> ok end,
+ {trace, Proc1, getting_unlinked, Proc3} = receive_first(),
+ Proc1 ! {trap_exit_please, false},
+ receive_nothing(),
%%
%% link
- ?line Proc1 ! {link_please, Proc2},
- ?line {trace, Proc1, link, Proc2} = receive_first(),
- ?line receive_nothing(),
+ Proc1 ! {link_please, Proc2},
+ {trace, Proc1, link, Proc2} = receive_first(),
+ receive_nothing(),
%%
%% unlink
- ?line Proc1 ! {unlink_please, Proc2},
- ?line {trace, Proc1, unlink, Proc2} = receive_first(),
- ?line receive_nothing(),
+ Proc1 ! {unlink_please, Proc2},
+ {trace, Proc1, unlink, Proc2} = receive_first(),
+ receive_nothing(),
%%
%% getting_linked
- ?line Proc2 ! {link_please, Proc1},
- ?line {trace, Proc1, getting_linked, Proc2} = receive_first(),
- ?line receive_nothing(),
+ Proc2 ! {link_please, Proc1},
+ {trace, Proc1, getting_linked, Proc2} = receive_first(),
+ receive_nothing(),
%%
%% getting_unlinked
- ?line Proc2 ! {unlink_please, Proc1},
- ?line {trace, Proc1, getting_unlinked, Proc2} = receive_first(),
- ?line receive_nothing(),
+ Proc2 ! {unlink_please, Proc1},
+ {trace, Proc1, getting_unlinked, Proc2} = receive_first(),
+ receive_nothing(),
%%
%% register
- ?line true = register(Name, Proc1),
- ?line {trace, Proc1, register, Name} = receive_first(),
- ?line receive_nothing(),
+ true = register(Name, Proc1),
+ {trace, Proc1, register, Name} = receive_first(),
+ receive_nothing(),
%%
%% unregister
- ?line true = unregister(Name),
- ?line {trace, Proc1, unregister, Name} = receive_first(),
- ?line receive_nothing(),
+ true = unregister(Name),
+ {trace, Proc1, unregister, Name} = receive_first(),
+ receive_nothing(),
%%
%% exit (with registered name, due to link)
- ?line Reason4 = make_ref(),
- ?line Proc1 ! {spawn_link_please, Self, MFA},
- ?line Proc4 = receive {spawned, Proc1, P4} -> P4 end,
- ?line {trace, Proc1, spawn, Proc4, MFA} = receive_first(),
- ?line io:format("Proc4 = ~p ~n", [Proc4]),
- ?line {trace, Proc1, link, Proc4} = receive_first(),
- ?line Proc1 ! {register_please, Name, Proc1},
- ?line {trace, Proc1, register, Name} = receive_first(),
- ?line Proc4 ! {exit_please, Reason4},
- ?line receive {'EXIT', Proc1, Reason4} -> ok end,
- ?line {trace, Proc1, exit, Reason4} = receive_first(),
- ?line {trace, Proc1, unregister, Name} = receive_first(),
- ?line receive_nothing(),
+ Reason4 = make_ref(),
+ Proc1 ! {spawn_link_please, Self, MFA},
+ Proc4 = receive {spawned, Proc1, P4} -> P4 end,
+ {trace, Proc1, spawn, Proc4, MFA} = receive_first(),
+ io:format("Proc4 = ~p ~n", [Proc4]),
+ {trace, Proc1, link, Proc4} = receive_first(),
+ Proc1 ! {register_please, Name, Proc1},
+ {trace, Proc1, register, Name} = receive_first(),
+ Proc4 ! {exit_please, Reason4},
+ receive {'EXIT', Proc1, Reason4} -> ok end,
+ {trace, Proc1, exit, Reason4} = receive_first(),
+ {trace, Proc1, unregister, Name} = receive_first(),
+ receive_nothing(),
%%
%% exit (not linked to tracing process)
- ?line 1 = erlang:trace(Proc2, true, [procs]),
- ?line Reason2 = make_ref(),
- ?line Proc2 ! {exit_please, Reason2},
- ?line {trace, Proc2, exit, Reason2} = receive_first(),
- ?line receive_nothing(),
- %%
- %% Done.
- ?line test_server:timetrap_cancel(Dog),
+ 1 = erlang:trace(Proc2, true, [procs]),
+ Reason2 = make_ref(),
+ Proc2 ! {exit_please, Reason2},
+ {trace, Proc2, exit, Reason2} = receive_first(),
+ receive_nothing(),
ok.
dist_procs_trace(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(15)),
- ?line OtherName = atom_to_list(?MODULE)++"_dist_procs_trace",
- ?line {ok, OtherNode} = start_node(OtherName),
- ?line Self = self(),
- ?line process_flag(trap_exit, true),
+ ct:timetrap({seconds, 15}),
+ OtherName = atom_to_list(?MODULE)++"_dist_procs_trace",
+ {ok, OtherNode} = start_node(OtherName),
+ Self = self(),
+ process_flag(trap_exit, true),
%%
- ?line Proc1 = spawn_link(?MODULE, process, [Self]),
- ?line io:format("Proc1 = ~p ~n", [Proc1]),
- ?line Proc2 = spawn(OtherNode, ?MODULE, process, [Self]),
- ?line io:format("Proc2 = ~p ~n", [Proc2]),
+ Proc1 = spawn_link(?MODULE, process, [Self]),
+ io:format("Proc1 = ~p ~n", [Proc1]),
+ Proc2 = spawn(OtherNode, ?MODULE, process, [Self]),
+ io:format("Proc2 = ~p ~n", [Proc2]),
%%
- ?line 1 = erlang:trace(Proc1, true, [procs]),
- ?line MFA = {?MODULE, process, [Self]},
+ 1 = erlang:trace(Proc1, true, [procs]),
+ MFA = {?MODULE, process, [Self]},
%%
%% getting_unlinked by exit()
- ?line Proc1 ! {spawn_link_please, Self, OtherNode, MFA},
- ?line Proc1 ! {trap_exit_please, true},
- ?line Proc3 = receive {spawned, Proc1, P3} -> P3 end,
- ?line io:format("Proc3 = ~p ~n", [Proc3]),
- ?line {trace, Proc1, getting_linked, Proc3} = receive_first(),
- ?line Reason3 = make_ref(),
- ?line Proc1 ! {send_please, Proc3, {exit_please, Reason3}},
- ?line receive {Proc1, {'EXIT', Proc3, Reason3}} -> ok end,
- ?line {trace, Proc1, getting_unlinked, Proc3} = receive_first(),
- ?line Proc1 ! {trap_exit_please, false},
- ?line receive_nothing(),
+ Proc1 ! {spawn_link_please, Self, OtherNode, MFA},
+ Proc1 ! {trap_exit_please, true},
+ Proc3 = receive {spawned, Proc1, P3} -> P3 end,
+ io:format("Proc3 = ~p ~n", [Proc3]),
+ {trace, Proc1, getting_linked, Proc3} = receive_first(),
+ Reason3 = make_ref(),
+ Proc1 ! {send_please, Proc3, {exit_please, Reason3}},
+ receive {Proc1, {'EXIT', Proc3, Reason3}} -> ok end,
+ {trace, Proc1, getting_unlinked, Proc3} = receive_first(),
+ Proc1 ! {trap_exit_please, false},
+ receive_nothing(),
%%
%% link
- ?line Proc1 ! {link_please, Proc2},
- ?line {trace, Proc1, link, Proc2} = receive_first(),
- ?line receive_nothing(),
+ Proc1 ! {link_please, Proc2},
+ {trace, Proc1, link, Proc2} = receive_first(),
+ receive_nothing(),
%%
%% unlink
- ?line Proc1 ! {unlink_please, Proc2},
- ?line {trace, Proc1, unlink, Proc2} = receive_first(),
- ?line receive_nothing(),
+ Proc1 ! {unlink_please, Proc2},
+ {trace, Proc1, unlink, Proc2} = receive_first(),
+ receive_nothing(),
%%
%% getting_linked
- ?line Proc2 ! {link_please, Proc1},
- ?line {trace, Proc1, getting_linked, Proc2} = receive_first(),
- ?line receive_nothing(),
+ Proc2 ! {link_please, Proc1},
+ {trace, Proc1, getting_linked, Proc2} = receive_first(),
+ receive_nothing(),
%%
%% getting_unlinked
- ?line Proc2 ! {unlink_please, Proc1},
- ?line {trace, Proc1, getting_unlinked, Proc2} = receive_first(),
- ?line receive_nothing(),
+ Proc2 ! {unlink_please, Proc1},
+ {trace, Proc1, getting_unlinked, Proc2} = receive_first(),
+ receive_nothing(),
%%
%% exit (with registered name, due to link)
- ?line Name = list_to_atom(OtherName),
- ?line Reason2 = make_ref(),
- ?line Proc1 ! {link_please, Proc2},
- ?line {trace, Proc1, link, Proc2} = receive_first(),
- ?line Proc1 ! {register_please, Name, Proc1},
- ?line {trace, Proc1, register, Name} = receive_first(),
- ?line Proc2 ! {exit_please, Reason2},
- ?line receive {'EXIT', Proc1, Reason2} -> ok end,
- ?line {trace, Proc1, exit, Reason2} = receive_first(),
- ?line {trace, Proc1, unregister, Name} = receive_first(),
- ?line receive_nothing(),
+ Name = list_to_atom(OtherName),
+ Reason2 = make_ref(),
+ Proc1 ! {link_please, Proc2},
+ {trace, Proc1, link, Proc2} = receive_first(),
+ Proc1 ! {register_please, Name, Proc1},
+ {trace, Proc1, register, Name} = receive_first(),
+ Proc2 ! {exit_please, Reason2},
+ receive {'EXIT', Proc1, Reason2} -> ok end,
+ {trace, Proc1, exit, Reason2} = receive_first(),
+ {trace, Proc1, unregister, Name} = receive_first(),
+ receive_nothing(),
%%
%% Done.
- ?line true = stop_node(OtherNode),
- ?line test_server:timetrap_cancel(Dog),
+ true = stop_node(OtherNode),
ok.
@@ -388,134 +350,117 @@ dist_procs_trace(Config) when is_list(Config) ->
%% Tests trace(Pid, How, [set_on_spawn]).
set_on_spawn(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line Listener = fun_spawn(fun process/0),
+ Listener = fun_spawn(fun process/0),
%% Create and trace a process with the set_on_spawn flag.
%% Make sure it is traced.
- ?line Father_SOS = fun_spawn(fun process/0),
- ?line 1 = erlang:trace(Father_SOS, true, [send, set_on_spawn]),
- ?line true = is_send_traced(Father_SOS, Listener, sos_father),
+ Father_SOS = fun_spawn(fun process/0),
+ 1 = erlang:trace(Father_SOS, true, [send, set_on_spawn]),
+ true = is_send_traced(Father_SOS, Listener, sos_father),
%% Have the process spawn of two children and test that they
%% are traced.
- ?line [Child1, Child2] = spawn_children(Father_SOS, 2),
- ?line true = is_send_traced(Child1, Listener, child1),
- ?line true = is_send_traced(Child2, Listener, child2),
+ [Child1, Child2] = spawn_children(Father_SOS, 2),
+ true = is_send_traced(Child1, Listener, child1),
+ true = is_send_traced(Child2, Listener, child2),
%% Second generation.
[Child11, Child12] = spawn_children(Child1, 2),
- ?line true = is_send_traced(Child11, Listener, child11),
- ?line true = is_send_traced(Child12, Listener, child12),
-
- %% Done.
- ?line test_server:timetrap_cancel(Dog),
+ true = is_send_traced(Child11, Listener, child11),
+ true = is_send_traced(Child12, Listener, child12),
ok.
%% Tests trace(Pid, How, [set_on_first_spawn]).
set_on_first_spawn(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Listener = fun_spawn(fun process/0),
+ ct:timetrap({seconds, 10}),
+ Listener = fun_spawn(fun process/0),
%% Create and trace a process with the set_on_first_spawn flag.
%% Make sure it is traced.
- ?line Parent = fun_spawn(fun process/0),
- ?line 1 = erlang:trace(Parent, true, [send, set_on_first_spawn]),
- ?line is_send_traced(Parent, Listener, sos_father),
+ Parent = fun_spawn(fun process/0),
+ 1 = erlang:trace(Parent, true, [send, set_on_first_spawn]),
+ is_send_traced(Parent, Listener, sos_father),
%% Have the process spawn off three children and test that the
%% first is traced.
- ?line [Child1, Child2, Child3] = spawn_children(Parent, 3),
- ?line true = is_send_traced(Child1, Listener, child1),
- ?line false = is_send_traced(Child2, Listener, child2),
- ?line false = is_send_traced(Child3, Listener, child3),
- ?line receive_nothing(),
-
- %% Done.
- ?line test_server:timetrap_cancel(Dog),
+ [Child1, Child2, Child3] = spawn_children(Parent, 3),
+ true = is_send_traced(Child1, Listener, child1),
+ false = is_send_traced(Child2, Listener, child2),
+ false = is_send_traced(Child3, Listener, child3),
+ receive_nothing(),
ok.
-system_monitor_args(doc) ->
- ["Tests arguments to erlang:system_monitor/0-2)"];
+%% Tests arguments to erlang:system_monitor/0,1,2
system_monitor_args(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line Self = self(),
+ Self = self(),
%%
- ?line OldMonitor = erlang:system_monitor(undefined),
- ?line undefined = erlang:system_monitor(Self, [{long_gc,0}]),
- ?line MinT = case erlang:system_monitor() of
- {Self,[{long_gc,T}]} when is_integer(T), T > 0 -> T;
- Other1 -> test_server:fault(Other1)
- end,
- ?line {Self,[{long_gc,MinT}]} = erlang:system_monitor(),
- ?line {Self,[{long_gc,MinT}]} =
- erlang:system_monitor({Self,[{large_heap,0}]}),
- ?line MinN = case erlang:system_monitor() of
- {Self,[{large_heap,N}]} when is_integer(N), N > 0 -> N;
- Other2 -> test_server:fault(Other2)
- end,
- ?line {Self,[{large_heap,MinN}]} = erlang:system_monitor(),
- ?line {Self,[{large_heap,MinN}]} =
- erlang:system_monitor(Self, [busy_port]),
- ?line {Self,[busy_port]} = erlang:system_monitor(),
- ?line {Self,[busy_port]} =
- erlang:system_monitor({Self,[busy_dist_port]}),
- ?line {Self,[busy_dist_port]} = erlang:system_monitor(),
- ?line All = lists:sort([busy_port,busy_dist_port,
- {long_gc,1},{large_heap,65535}]),
- ?line {Self,[busy_dist_port]} = erlang:system_monitor(Self, All),
- ?line {Self,A1} = erlang:system_monitor(),
- ?line All = lists:sort(A1),
- ?line {Self,A1} = erlang:system_monitor(Self, []),
- ?line Pid = spawn(fun () -> receive {Self,die} -> exit(die) end end),
- ?line Mref = erlang:monitor(process, Pid),
- ?line undefined = erlang:system_monitor(Pid, All),
- ?line {Pid,A2} = erlang:system_monitor(),
- ?line All = lists:sort(A2),
- ?line Pid ! {Self,die},
- ?line receive {'DOWN',Mref,_,_,_} -> ok end,
- ?line undefined = erlang:system_monitor(OldMonitor),
- ?line erlang:yield(),
- ?line OldMonitor = erlang:system_monitor(),
+ OldMonitor = erlang:system_monitor(undefined),
+ undefined = erlang:system_monitor(Self, [{long_gc,0}]),
+ MinT = case erlang:system_monitor() of
+ {Self,[{long_gc,T}]} when is_integer(T), T > 0 -> T;
+ Other1 -> test_server:fault(Other1)
+ end,
+ {Self,[{long_gc,MinT}]} = erlang:system_monitor(),
+ {Self,[{long_gc,MinT}]} =
+ erlang:system_monitor({Self,[{large_heap,0}]}),
+ MinN = case erlang:system_monitor() of
+ {Self,[{large_heap,N}]} when is_integer(N), N > 0 -> N;
+ Other2 -> test_server:fault(Other2)
+ end,
+ {Self,[{large_heap,MinN}]} = erlang:system_monitor(),
+ {Self,[{large_heap,MinN}]} =
+ erlang:system_monitor(Self, [busy_port]),
+ {Self,[busy_port]} = erlang:system_monitor(),
+ {Self,[busy_port]} =
+ erlang:system_monitor({Self,[busy_dist_port]}),
+ {Self,[busy_dist_port]} = erlang:system_monitor(),
+ All = lists:sort([busy_port,busy_dist_port,
+ {long_gc,1},{large_heap,65535}]),
+ {Self,[busy_dist_port]} = erlang:system_monitor(Self, All),
+ {Self,A1} = erlang:system_monitor(),
+ All = lists:sort(A1),
+ {Self,A1} = erlang:system_monitor(Self, []),
+ Pid = spawn(fun () -> receive {Self,die} -> exit(die) end end),
+ Mref = erlang:monitor(process, Pid),
+ undefined = erlang:system_monitor(Pid, All),
+ {Pid,A2} = erlang:system_monitor(),
+ All = lists:sort(A2),
+ Pid ! {Self,die},
+ receive {'DOWN',Mref,_,_,_} -> ok end,
+ undefined = erlang:system_monitor(OldMonitor),
+ erlang:yield(),
+ OldMonitor = erlang:system_monitor(),
%%
- ?line {'EXIT',{badarg,_}} = (catch erlang:system_monitor(atom)),
- ?line {'EXIT',{badarg,_}} = (catch erlang:system_monitor({})),
- ?line {'EXIT',{badarg,_}} = (catch erlang:system_monitor({1})),
- ?line {'EXIT',{badarg,_}} = (catch erlang:system_monitor({1,2,3})),
- ?line {'EXIT',{badarg,_}} =
- (catch erlang:system_monitor({Self,atom})),
- ?line {'EXIT',{badarg,_}} =
- (catch erlang:system_monitor(atom, atom)),
- ?line {'EXIT',{badarg,_}} =
- (catch erlang:system_monitor({Self,[busy_port|busy_dist_port]})),
- ?line {'EXIT',{badarg,_}} =
- (catch erlang:system_monitor(Self, [{long_gc,-1}])),
- ?line {'EXIT',{badarg,_}} =
- (catch erlang:system_monitor({Self,[{long_gc,atom}]})),
- ?line {'EXIT',{badarg,_}} =
- (catch erlang:system_monitor(Self,[{large_heap,-1}])),
- ?line {'EXIT',{badarg,_}} =
- (catch erlang:system_monitor({Self,[{large_heap,atom}]})),
- %% Done.
- ?line test_server:timetrap_cancel(Dog),
+ {'EXIT',{badarg,_}} = (catch erlang:system_monitor(atom)),
+ {'EXIT',{badarg,_}} = (catch erlang:system_monitor({})),
+ {'EXIT',{badarg,_}} = (catch erlang:system_monitor({1})),
+ {'EXIT',{badarg,_}} = (catch erlang:system_monitor({1,2,3})),
+ {'EXIT',{badarg,_}} =
+ (catch erlang:system_monitor({Self,atom})),
+ {'EXIT',{badarg,_}} =
+ (catch erlang:system_monitor(atom, atom)),
+ {'EXIT',{badarg,_}} =
+ (catch erlang:system_monitor({Self,[busy_port|busy_dist_port]})),
+ {'EXIT',{badarg,_}} =
+ (catch erlang:system_monitor(Self, [{long_gc,-1}])),
+ {'EXIT',{badarg,_}} =
+ (catch erlang:system_monitor({Self,[{long_gc,atom}]})),
+ {'EXIT',{badarg,_}} =
+ (catch erlang:system_monitor(Self,[{large_heap,-1}])),
+ {'EXIT',{badarg,_}} =
+ (catch erlang:system_monitor({Self,[{large_heap,atom}]})),
ok.
-more_system_monitor_args(doc) ->
- ["Tests arguments to erlang:system_monitor/0-2)"];
+%% Tests arguments to erlang:system_monitor/0,1,2
more_system_monitor_args(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
-
- ?line try_l(64000),
- ?line try_l(16#7ffffff),
- ?line try_l(16#3fffffff),
- ?line try_l(16#7fffffff),
- ?line try_l(16#ffffffff),
-
- %% Done.
- ?line test_server:timetrap_cancel(Dog),
+ try_l(64000),
+ try_l(16#7ffffff),
+ try_l(16#3fffffff),
+ try_l(16#7fffffff),
+ try_l(16#ffffffff),
ok.
try_l(Val) ->
@@ -523,29 +468,29 @@ try_l(Val) ->
Arbitrary1 = 77777,
Arbitrary2 = 88888,
- ?line erlang:system_monitor(undefined),
+ erlang:system_monitor(undefined),
- ?line undefined = erlang:system_monitor(Self, [{long_gc,Val},{large_heap,Arbitrary1}]),
+ undefined = erlang:system_monitor(Self, [{long_gc,Val},{large_heap,Arbitrary1}]),
- ?line {Self,Comb0} = erlang:system_monitor(Self, [{long_gc,Arbitrary2},{large_heap,Val}]),
- ?line [{large_heap,Arbitrary1},{long_gc,Val}] = lists:sort(Comb0),
+ {Self,Comb0} = erlang:system_monitor(Self, [{long_gc,Arbitrary2},{large_heap,Val}]),
+ [{large_heap,Arbitrary1},{long_gc,Val}] = lists:sort(Comb0),
- ?line {Self,Comb1} = erlang:system_monitor(undefined),
- ?line [{large_heap,Val},{long_gc,Arbitrary2}] = lists:sort(Comb1).
+ {Self,Comb1} = erlang:system_monitor(undefined),
+ [{large_heap,Val},{long_gc,Arbitrary2}] = lists:sort(Comb1).
monitor_sys(Parent) ->
receive
- {monitor,Pid,long_schedule,Data} when is_pid(Pid) ->
- io:format("Long schedule of ~w: ~w~n",[Pid,Data]),
- Parent ! {Pid,Data},
- monitor_sys(Parent);
- {monitor,Port,long_schedule,Data} when is_port(Port) ->
- {name,Name} = erlang:port_info(Port,name),
- io:format("Long schedule of ~w (~p): ~w~n",[Port,Name,Data]),
- Parent ! {Port,Data},
- monitor_sys(Parent);
- Other ->
- erlang:display(Other)
+ {monitor,Pid,long_schedule,Data} when is_pid(Pid) ->
+ io:format("Long schedule of ~w: ~w~n",[Pid,Data]),
+ Parent ! {Pid,Data},
+ monitor_sys(Parent);
+ {monitor,Port,long_schedule,Data} when is_port(Port) ->
+ {name,Name} = erlang:port_info(Port,name),
+ io:format("Long schedule of ~w (~p): ~w~n",[Port,Name,Data]),
+ Parent ! {Port,Data},
+ monitor_sys(Parent);
+ Other ->
+ erlang:display(Other)
end.
start_monitor() ->
@@ -555,18 +500,15 @@ start_monitor() ->
erlang:yield(), % Need to be rescheduled for the trace to take
ok.
-system_monitor_long_schedule(suite) ->
- [];
-system_monitor_long_schedule(doc) ->
- ["Tests erlang:system_monitor(Pid, [{long_schedule,Time}])"];
+%% Tests erlang:system_monitor(Pid, [{long_schedule,Time}])
system_monitor_long_schedule(Config) when is_list(Config) ->
- Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
erl_ddll:start(),
case (catch load_driver(Path, slow_drv)) of
- ok ->
- do_system_monitor_long_schedule();
- _Error ->
- {skip, "Unable to load slow_drv (windows or no usleep()?)"}
+ ok ->
+ do_system_monitor_long_schedule();
+ _Error ->
+ {skip, "Unable to load slow_drv (windows or no usleep()?)"}
end.
do_system_monitor_long_schedule() ->
start_monitor(),
@@ -574,18 +516,18 @@ do_system_monitor_long_schedule() ->
"ok" = erlang:port_control(Port,0,[]),
Self = self(),
receive
- {Self,L} when is_list(L) ->
- ok
+ {Self,L} when is_list(L) ->
+ ok
after 1000 ->
- ?t:fail(no_trace_of_pid)
+ ct:fail(no_trace_of_pid)
end,
"ok" = erlang:port_control(Port,1,[]),
"ok" = erlang:port_control(Port,2,[]),
receive
- {Port,LL} when is_list(LL) ->
- ok
+ {Port,LL} when is_list(LL) ->
+ ok
after 1000 ->
- ?t:fail(no_trace_of_port)
+ ct:fail(no_trace_of_port)
end,
port_close(Port),
erlang:system_monitor(undefined),
@@ -594,214 +536,200 @@ do_system_monitor_long_schedule() ->
-define(LONG_GC_SLEEP, 670).
-system_monitor_long_gc_1(suite) ->
- [];
-system_monitor_long_gc_1(doc) ->
- ["Tests erlang:system_monitor(Pid, [{long_gc,Time}])"];
+%% Tests erlang:system_monitor(Pid, [{long_gc,Time}])
system_monitor_long_gc_1(Config) when is_list(Config) ->
erts_debug:set_internal_state(available_internal_state, true),
try
- case erts_debug:get_internal_state(force_heap_frags) of
- true ->
- {skip,"emulator with FORCE_HEAP_FRAGS defined"};
- false ->
- %% Add ?LONG_GC_SLEEP ms to all gc
- ?line erts_debug:set_internal_state(test_long_gc_sleep,
- ?LONG_GC_SLEEP),
- ?line LoadFun = fun () ->
- garbage_collect(),
- self()
- end,
- ?line long_gc(LoadFun, false)
- end
+ case erts_debug:get_internal_state(force_heap_frags) of
+ true ->
+ {skip,"emulator with FORCE_HEAP_FRAGS defined"};
+ false ->
+ %% Add ?LONG_GC_SLEEP ms to all gc
+ erts_debug:set_internal_state(test_long_gc_sleep,
+ ?LONG_GC_SLEEP),
+ LoadFun = fun () ->
+ garbage_collect(),
+ self()
+ end,
+ long_gc(LoadFun, false)
+ end
after
- erts_debug:set_internal_state(test_long_gc_sleep, 0),
- erts_debug:set_internal_state(available_internal_state, false)
+ erts_debug:set_internal_state(test_long_gc_sleep, 0),
+ erts_debug:set_internal_state(available_internal_state, false)
end.
-system_monitor_long_gc_2(suite) ->
- [];
-system_monitor_long_gc_2(doc) ->
- ["Tests erlang:system_monitor(Pid, [{long_gc,Time}])"];
+%% Tests erlang:system_monitor(Pid, [{long_gc,Time}])
system_monitor_long_gc_2(Config) when is_list(Config) ->
erts_debug:set_internal_state(available_internal_state, true),
try
- case erts_debug:get_internal_state(force_heap_frags) of
- true ->
- {skip,"emulator with FORCE_HEAP_FRAGS defined"};
- false ->
- %% Add ?LONG_GC_SLEEP ms to all gc
- ?line erts_debug:set_internal_state(test_long_gc_sleep,
- ?LONG_GC_SLEEP),
- ?line Parent = self(),
- ?line LoadFun =
- fun () ->
- Ref = make_ref(),
- Pid =
- spawn_link(
- fun () ->
- garbage_collect(),
- Parent ! {Ref, self()}
- end),
- receive {Ref, Pid} -> Pid end
- end,
- ?line long_gc(LoadFun, true),
- ?line long_gc(LoadFun, true),
- ?line long_gc(LoadFun, true)
- end
+ case erts_debug:get_internal_state(force_heap_frags) of
+ true ->
+ {skip,"emulator with FORCE_HEAP_FRAGS defined"};
+ false ->
+ %% Add ?LONG_GC_SLEEP ms to all gc
+ erts_debug:set_internal_state(test_long_gc_sleep,
+ ?LONG_GC_SLEEP),
+ Parent = self(),
+ LoadFun =
+ fun () ->
+ Ref = make_ref(),
+ Pid =
+ spawn_link(
+ fun () ->
+ garbage_collect(),
+ Parent ! {Ref, self()}
+ end),
+ receive {Ref, Pid} -> Pid end
+ end,
+ long_gc(LoadFun, true),
+ long_gc(LoadFun, true),
+ long_gc(LoadFun, true)
+ end
after
- erts_debug:set_internal_state(test_long_gc_sleep, 0),
- erts_debug:set_internal_state(available_internal_state, false)
+ erts_debug:set_internal_state(test_long_gc_sleep, 0),
+ erts_debug:set_internal_state(available_internal_state, false)
end.
long_gc(LoadFun, ExpectMonMsg) ->
- ?line Self = self(),
- ?line Time = 1,
- ?line OldMonitor = erlang:system_monitor(Self, [{long_gc,Time}]),
- ?line Pid = LoadFun(),
- ?line Ref = erlang:trace_delivered(Pid),
- ?line receive {trace_delivered, Pid, Ref} -> ok end,
- ?line {Self,[{long_gc,Time}]} = erlang:system_monitor(OldMonitor),
- ?line case {long_gc_check(Pid, Time, undefined), ExpectMonMsg} of
- {ok, true} when Pid =/= Self ->
- ok;
- {ok, false} ->
- ?line ?t:fail(unexpected_system_monitor_message_received);
- {undefined, false} ->
- ok;
- {undefined, true} ->
- ?line ?t:fail(no_system_monitor_message_received)
- end.
+ Self = self(),
+ Time = 1,
+ OldMonitor = erlang:system_monitor(Self, [{long_gc,Time}]),
+ Pid = LoadFun(),
+ Ref = erlang:trace_delivered(Pid),
+ receive {trace_delivered, Pid, Ref} -> ok end,
+ {Self,[{long_gc,Time}]} = erlang:system_monitor(OldMonitor),
+ case {long_gc_check(Pid, Time, undefined), ExpectMonMsg} of
+ {ok, true} when Pid =/= Self ->
+ ok;
+ {ok, false} ->
+ ct:fail(unexpected_system_monitor_message_received);
+ {undefined, false} ->
+ ok;
+ {undefined, true} ->
+ ct:fail(no_system_monitor_message_received)
+ end.
long_gc_check(Pid, Time, Result) ->
receive
- {monitor,Pid,long_gc,L} = Monitor ->
- case lists:foldl(
- fun (_, error) ->
- error;
- ({timeout,T}, N) when is_integer(T),
- Time =< T, T =< 10*?LONG_GC_SLEEP ->
- %% OTP-7622. The time T must be within reasonable limits
- %% for the test to pass.
- N-1;
- ({heap_size,_}, N) ->
- N-1;
- ({old_heap_size,_}, N) ->
- N-1;
- ({stack_size,_}, N) ->
- N-1;
- ({mbuf_size,_}, N) ->
- N-1;
- ({heap_block_size,_}, N) ->
- N-1;
- ({old_heap_block_size,_}, N) ->
- N-1;
- (_, _) ->
- error
- end, 7, L) of
- 0 ->
- long_gc_check(Pid, Time, ok);
- error ->
- {error,Monitor}
- end;
- {monitor,_,long_gc,_} ->
- long_gc_check(Pid, Time, Result);
- Other ->
- {error,Other}
+ {monitor,Pid,long_gc,L} = Monitor ->
+ case lists:foldl(
+ fun (_, error) ->
+ error;
+ ({timeout,T}, N) when is_integer(T),
+ Time =< T, T =< 10*?LONG_GC_SLEEP ->
+ %% OTP-7622. The time T must be within reasonable limits
+ %% for the test to pass.
+ N-1;
+ ({heap_size,_}, N) ->
+ N-1;
+ ({old_heap_size,_}, N) ->
+ N-1;
+ ({stack_size,_}, N) ->
+ N-1;
+ ({mbuf_size,_}, N) ->
+ N-1;
+ ({heap_block_size,_}, N) ->
+ N-1;
+ ({old_heap_block_size,_}, N) ->
+ N-1;
+ (_, _) ->
+ error
+ end, 7, L) of
+ 0 ->
+ long_gc_check(Pid, Time, ok);
+ error ->
+ {error,Monitor}
+ end;
+ {monitor,_,long_gc,_} ->
+ long_gc_check(Pid, Time, Result);
+ Other ->
+ {error,Other}
after 0 ->
- Result
+ Result
end.
-system_monitor_large_heap_1(suite) ->
- [];
-system_monitor_large_heap_1(doc) ->
- ["Tests erlang:system_monitor(Pid, [{large_heap,Size}])"];
+%% Tests erlang:system_monitor(Pid, [{large_heap,Size}])
system_monitor_large_heap_1(Config) when is_list(Config) ->
- ?line LoadFun =
- fun (Size) ->
- List = seq(1,2*Size),
- garbage_collect(),
- true = lists:prefix([1], List),
- self()
- end,
- ?line large_heap(LoadFun, false).
-
-system_monitor_large_heap_2(suite) ->
- [];
-system_monitor_large_heap_2(doc) ->
- ["Tests erlang:system_monitor(Pid, [{large_heap,Size}])"];
+ LoadFun =
+ fun (Size) ->
+ List = seq(1,2*Size),
+ garbage_collect(),
+ true = lists:prefix([1], List),
+ self()
+ end,
+ large_heap(LoadFun, false).
+
+%% Tests erlang:system_monitor(Pid, [{large_heap,Size}])
system_monitor_large_heap_2(Config) when is_list(Config) ->
- ?line Parent = self(),
- ?line LoadFun =
- fun (Size) ->
- Ref = make_ref(),
- Pid =
- spawn_opt(fun () ->
- garbage_collect(),
- Parent ! {Ref, self()}
- end,
- [link, {min_heap_size, 2*Size}]),
- receive {Ref, Pid} -> Pid end
- end,
- ?line large_heap(LoadFun, true).
+ Parent = self(),
+ LoadFun =
+ fun (Size) ->
+ Ref = make_ref(),
+ Pid =
+ spawn_opt(fun () ->
+ garbage_collect(),
+ Parent ! {Ref, self()}
+ end,
+ [link, {min_heap_size, 2*Size}]),
+ receive {Ref, Pid} -> Pid end
+ end,
+ large_heap(LoadFun, true).
large_heap(LoadFun, ExpectMonMsg) ->
- ?line Dog = test_server:timetrap(test_server:seconds(20)),
+ ct:timetrap({seconds, 20}),
%%
- ?line Size = 65535,
- ?line Self = self(),
- ?line NewMonitor = {Self,[{large_heap,Size}]},
- ?line OldMonitor = erlang:system_monitor(NewMonitor),
- ?line Pid = LoadFun(Size),
- ?line Ref = erlang:trace_delivered(Pid),
- ?line receive {trace_delivered, Pid, Ref} -> ok end,
- ?line {Self,[{large_heap,Size}]} = erlang:system_monitor(OldMonitor),
- ?line case {large_heap_check(Pid, Size, undefined), ExpectMonMsg} of
- {ok, true} when Pid =/= Self ->
- ?line ok;
- {ok, false} ->
- ?line ?t:fail(unexpected_system_monitor_message_received);
- {undefined, false} ->
- ?line ok;
- {undefined, true} ->
- ?line ?t:fail(no_system_monitor_message_received)
- end,
- %%
- ?line test_server:timetrap_cancel(Dog),
+ Size = 65535,
+ Self = self(),
+ NewMonitor = {Self,[{large_heap,Size}]},
+ OldMonitor = erlang:system_monitor(NewMonitor),
+ Pid = LoadFun(Size),
+ Ref = erlang:trace_delivered(Pid),
+ receive {trace_delivered, Pid, Ref} -> ok end,
+ {Self,[{large_heap,Size}]} = erlang:system_monitor(OldMonitor),
+ case {large_heap_check(Pid, Size, undefined), ExpectMonMsg} of
+ {ok, true} when Pid =/= Self ->
+ ok;
+ {ok, false} ->
+ ct:fail(unexpected_system_monitor_message_received);
+ {undefined, false} ->
+ ok;
+ {undefined, true} ->
+ ct:fail(no_system_monitor_message_received)
+ end,
ok.
large_heap_check(Pid, Size, Result) ->
receive
- {monitor,Pid,large_heap,L} = Monitor ->
- case lists:foldl(
- fun (_, error) ->
- error;
- ({heap_size,_}, N) ->
- N-1;
- ({old_heap_size,_}, N) ->
- N-1;
- ({stack_size,_}, N) ->
- N-1;
- ({mbuf_size,_}, N) ->
- N-1;
- ({heap_block_size,_}, N) ->
- N-1;
- ({old_heap_block_size,_}, N) ->
- N-1;
- (_, _) ->
- error
- end, 6, L) of
- 0 ->
- large_heap_check(Pid, Size, ok);
- error ->
- {error,Monitor}
- end;
- {monitor,_,large_heap,_} ->
- large_heap_check(Pid, Size, Result);
- Other ->
- {error,Other}
+ {monitor,Pid,large_heap,L} = Monitor ->
+ case lists:foldl(
+ fun (_, error) ->
+ error;
+ ({heap_size,_}, N) ->
+ N-1;
+ ({old_heap_size,_}, N) ->
+ N-1;
+ ({stack_size,_}, N) ->
+ N-1;
+ ({mbuf_size,_}, N) ->
+ N-1;
+ ({heap_block_size,_}, N) ->
+ N-1;
+ ({old_heap_block_size,_}, N) ->
+ N-1;
+ (_, _) ->
+ error
+ end, 6, L) of
+ 0 ->
+ large_heap_check(Pid, Size, ok);
+ error ->
+ {error,Monitor}
+ end;
+ {monitor,_,large_heap,_} ->
+ large_heap_check(Pid, Size, Result);
+ Other ->
+ {error,Other}
after 0 ->
- Result
+ Result
end.
seq(N, M) ->
@@ -816,11 +744,11 @@ seq(N, M, R) ->
is_send_traced(Pid, Listener, Msg) ->
Pid ! {send_please, Listener, Msg},
receive
- Any ->
- {trace, Pid, send, Msg, Listener} = Any,
- true
+ Any ->
+ {trace, Pid, send, Msg, Listener} = Any,
+ true
after 1000 ->
- false
+ false
end.
%% This procedure assumes that the Parent process is send traced.
@@ -834,146 +762,131 @@ spawn_children(Parent, Number, Result) ->
Self = self(),
Parent ! {spawn_please, Self, fun process/0},
Child =
- receive
- {trace, Parent, send, {spawned, Pid}, Self} -> Pid
- end,
receive
- {spawned, Child} ->
- spawn_children(Parent, Number-1, [Child|Result])
+ {trace, Parent, send, {spawned, Pid}, Self} -> Pid
+ end,
+ receive
+ {spawned, Child} ->
+ spawn_children(Parent, Number-1, [Child|Result])
end.
-suspend(doc) -> "Test erlang:suspend/1 and erlang:resume/1.";
+%% Test erlang:suspend/1 and erlang:resume/1.
suspend(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(2)),
-
- ?line Worker = fun_spawn(fun worker/0),
+ ct:timetrap({minutes,2}),
+ Worker = fun_spawn(fun worker/0),
%% Suspend a process and test that it is suspended.
- ?line ok = do_suspend(Worker, 10000),
-
- %% Done.
- ?line test_server:timetrap_cancel(Dog),
+ ok = do_suspend(Worker, 10000),
ok.
do_suspend(_Pid, 0) ->
- ?line ok;
+ ok;
do_suspend(Pid, N) ->
%% Suspend a process and test that it is suspended.
- ?line true = erlang:suspend_process(Pid),
- ?line {status, suspended} = process_info(Pid, status),
+ true = erlang:suspend_process(Pid),
+ {status, suspended} = process_info(Pid, status),
%% Unsuspend the process and make sure it starts working.
- ?line true = erlang:resume_process(Pid),
- ?line case process_info(Pid, status) of
- {status, runnable} -> ?line ok;
- {status, running} -> ?line ok;
- {status, garbage_collecting} -> ?line ok;
- ST -> ?line ?t:fail(ST)
- end,
- ?line erlang:yield(),
- ?line do_suspend(Pid, N-1).
-
-
-
-mutual_suspend(doc) ->
- [];
-mutual_suspend(suite) ->
- [];
+ true = erlang:resume_process(Pid),
+ case process_info(Pid, status) of
+ {status, runnable} -> ok;
+ {status, running} -> ok;
+ {status, garbage_collecting} -> ok;
+ ST -> ct:fail(ST)
+ end,
+ erlang:yield(),
+ do_suspend(Pid, N-1).
+
+
+
mutual_suspend(Config) when is_list(Config) ->
- ?line TimeoutSecs = 5*60,
- ?line Dog = test_server:timetrap(test_server:minutes(TimeoutSecs)),
- ?line Parent = self(),
- ?line Fun = fun () ->
- receive
- {go, Pid} ->
- do_mutual_suspend(Pid, 100000)
- end,
- Parent ! {done, self()},
- receive after infinity -> ok end
- end,
- ?line P1 = spawn_link(Fun),
- ?line P2 = spawn_link(Fun),
- ?line T1 = erlang:start_timer((TimeoutSecs - 5)*1000, self(), oops),
- ?line T2 = erlang:start_timer((TimeoutSecs - 5)*1000, self(), oops),
- ?line P1 ! {go, P2},
- ?line P2 ! {go, P1},
- ?line Res1 = receive
- {done, P1} -> done;
- {timeout,T1,_} -> timeout
- end,
- ?line Res2 = receive
- {done, P2} -> done;
- {timeout,T2,_} -> timeout
- end,
- ?line P1S = process_info(P1, status),
- ?line P2S = process_info(P2, status),
- ?line ?t:format("P1S=~p P2S=~p", [P1S, P2S]),
- ?line false = {status, suspended} == P1S,
- ?line false = {status, suspended} == P2S,
- ?line unlink(P1), exit(P1, bang),
- ?line unlink(P2), exit(P2, bang),
- ?line done = Res1,
- ?line done = Res2,
- %% Done.
- ?line test_server:timetrap_cancel(Dog),
- ?line ok.
-
+ TimeoutSecs = 5*60,
+ ct:timetrap({seconds, TimeoutSecs}),
+ Parent = self(),
+ Fun = fun () ->
+ receive
+ {go, Pid} ->
+ do_mutual_suspend(Pid, 100000)
+ end,
+ Parent ! {done, self()},
+ receive after infinity -> ok end
+ end,
+ P1 = spawn_link(Fun),
+ P2 = spawn_link(Fun),
+ T1 = erlang:start_timer((TimeoutSecs - 5)*1000, self(), oops),
+ T2 = erlang:start_timer((TimeoutSecs - 5)*1000, self(), oops),
+ P1 ! {go, P2},
+ P2 ! {go, P1},
+ Res1 = receive
+ {done, P1} -> done;
+ {timeout,T1,_} -> timeout
+ end,
+ Res2 = receive
+ {done, P2} -> done;
+ {timeout,T2,_} -> timeout
+ end,
+ P1S = process_info(P1, status),
+ P2S = process_info(P2, status),
+ io:format("P1S=~p P2S=~p", [P1S, P2S]),
+ false = {status, suspended} == P1S,
+ false = {status, suspended} == P2S,
+ unlink(P1), exit(P1, bang),
+ unlink(P2), exit(P2, bang),
+ done = Res1,
+ done = Res2,
+ ok.
+
do_mutual_suspend(_Pid, 0) ->
- ?line ok;
+ ok;
do_mutual_suspend(Pid, N) ->
%% Suspend a process and test that it is suspended.
- ?line true = erlang:suspend_process(Pid),
- ?line {status, suspended} = process_info(Pid, status),
+ true = erlang:suspend_process(Pid),
+ {status, suspended} = process_info(Pid, status),
%% Unsuspend the process.
- ?line true = erlang:resume_process(Pid),
- ?line do_mutual_suspend(Pid, N-1).
+ true = erlang:resume_process(Pid),
+ do_mutual_suspend(Pid, N-1).
-suspend_exit(doc) ->
- [];
-suspend_exit(suite) ->
- [];
suspend_exit(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(2)),
- ?line random:seed(4711,17,4711),
- ?line do_suspend_exit(5000),
- ?line test_server:timetrap_cancel(Dog),
- ?line ok.
+ ct:timetrap({minutes, 2}),
+ rand:seed(exsplus, {4711,17,4711}),
+ do_suspend_exit(5000),
+ ok.
do_suspend_exit(0) ->
- ?line ok;
+ ok;
do_suspend_exit(N) ->
- ?line Work = random:uniform(50),
- ?line Parent = self(),
- ?line {Suspendee, Mon2}
- = spawn_monitor(fun () ->
- suspend_exit_work(Work),
- exit(normal)
- end),
- ?line {Suspender, Mon1}
- = spawn_monitor(
- fun () ->
- suspend_exit_work(Work div 2),
- Parent ! {doing_suspend, self()},
- case catch erlang:suspend_process(Suspendee) of
- {'EXIT', _} ->
- ok;
- true ->
- ?line erlang:resume_process(Suspendee)
- end
- end),
- ?line receive
- {doing_suspend, Suspender} ->
- case N rem 2 of
- 0 -> exit(Suspender, bang);
- 1 -> ok
- end
- end,
- ?line receive {'DOWN', Mon1, process, Suspender, _} -> ok end,
- ?line receive {'DOWN', Mon2, process, Suspendee, _} -> ok end,
- ?line do_suspend_exit(N-1).
-
-
-
-
+ Work = rand:uniform(50),
+ Parent = self(),
+ {Suspendee, Mon2}
+ = spawn_monitor(fun () ->
+ suspend_exit_work(Work),
+ exit(normal)
+ end),
+ {Suspender, Mon1}
+ = spawn_monitor(
+ fun () ->
+ suspend_exit_work(Work div 2),
+ Parent ! {doing_suspend, self()},
+ case catch erlang:suspend_process(Suspendee) of
+ {'EXIT', _} ->
+ ok;
+ true ->
+ erlang:resume_process(Suspendee)
+ end
+ end),
+ receive
+ {doing_suspend, Suspender} ->
+ case N rem 2 of
+ 0 -> exit(Suspender, bang);
+ 1 -> ok
+ end
+ end,
+ receive {'DOWN', Mon1, process, Suspender, _} -> ok end,
+ receive {'DOWN', Mon2, process, Suspendee, _} -> ok end,
+ do_suspend_exit(N-1).
+
+
+
+
suspend_exit_work(0) ->
ok;
suspend_exit_work(N) ->
@@ -985,320 +898,305 @@ suspend_exit_work(N) ->
chk_suspended(P, Bool, Line) ->
{Bool, Line} = {({status, suspended} == process_info(P, status)), Line}.
-suspender_exit(doc) ->
- [];
-suspender_exit(suite) ->
- [];
suspender_exit(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(3)),
- ?line P1 = spawn_link(fun () -> receive after infinity -> ok end end),
- ?line {'EXIT', _} = (catch erlang:resume_process(P1)),
- ?line {P2, M2} = spawn_monitor(
- fun () ->
- ?CHK_SUSPENDED(P1, false),
- erlang:suspend_process(P1),
- ?CHK_SUSPENDED(P1, true),
- erlang:suspend_process(P1),
- erlang:suspend_process(P1),
- erlang:suspend_process(P1),
- ?CHK_SUSPENDED(P1, true),
- erlang:resume_process(P1),
- erlang:resume_process(P1),
- erlang:resume_process(P1),
- ?CHK_SUSPENDED(P1, true),
- erlang:resume_process(P1),
- ?CHK_SUSPENDED(P1, false),
- erlang:suspend_process(P1),
- erlang:suspend_process(P1),
- erlang:suspend_process(P1),
- ?CHK_SUSPENDED(P1, true),
- exit(bang)
- end),
- ?line receive
- {'DOWN', M2,process,P2,R2} ->
- ?line bang = R2,
- ?line ?CHK_SUSPENDED(P1, false)
- end,
- ?line Parent = self(),
- ?line {P3, M3} = spawn_monitor(
- fun () ->
- erlang:suspend_process(P1),
- ?CHK_SUSPENDED(P1, true),
- Parent ! self(),
- receive after infinity -> ok end
- end),
- ?line {P4, M4} = spawn_monitor(
- fun () ->
- erlang:suspend_process(P1),
- ?CHK_SUSPENDED(P1, true),
- Parent ! self(),
- receive after infinity -> ok end
- end),
- ?line {P5, M5} = spawn_monitor(
- fun () ->
- erlang:suspend_process(P1),
- ?CHK_SUSPENDED(P1, true),
- Parent ! self(),
- receive after infinity -> ok end
- end),
- ?line {P6, M6} = spawn_monitor(
- fun () ->
- erlang:suspend_process(P1),
- ?CHK_SUSPENDED(P1, true),
- Parent ! self(),
- receive after infinity -> ok end
- end),
- ?line {P7, M7} = spawn_monitor(
- fun () ->
- erlang:suspend_process(P1),
- ?CHK_SUSPENDED(P1, true),
- Parent ! self(),
- receive after infinity -> ok end
- end),
- ?line receive P3 -> ok end,
- ?line receive P4 -> ok end,
- ?line receive P5 -> ok end,
- ?line receive P6 -> ok end,
- ?line receive P7 -> ok end,
- ?line ?CHK_SUSPENDED(P1, true),
- ?line exit(P3, bang),
- ?line receive
- {'DOWN',M3,process,P3,R3} ->
- ?line bang = R3,
- ?line ?CHK_SUSPENDED(P1, true)
- end,
- ?line exit(P4, bang),
- ?line receive
- {'DOWN',M4,process,P4,R4} ->
- ?line bang = R4,
- ?line ?CHK_SUSPENDED(P1, true)
- end,
- ?line exit(P5, bang),
- ?line receive
- {'DOWN',M5,process,P5,R5} ->
- ?line bang = R5,
- ?line ?CHK_SUSPENDED(P1, true)
- end,
- ?line exit(P6, bang),
- ?line receive
- {'DOWN',M6,process,P6,R6} ->
- ?line bang = R6,
- ?line ?CHK_SUSPENDED(P1, true)
- end,
- ?line exit(P7, bang),
- ?line receive
- {'DOWN',M7,process,P7,R7} ->
- ?line bang = R7,
- ?line ?CHK_SUSPENDED(P1, false)
- end,
- ?line unlink(P1),
- ?line exit(P1, bong),
- ?line test_server:timetrap_cancel(Dog),
- ?line ok.
-
-suspend_system_limit(doc) ->
- [];
-suspend_system_limit(suite) ->
- [];
+ ct:timetrap({minutes, 3}),
+ P1 = spawn_link(fun () -> receive after infinity -> ok end end),
+ {'EXIT', _} = (catch erlang:resume_process(P1)),
+ {P2, M2} = spawn_monitor(
+ fun () ->
+ ?CHK_SUSPENDED(P1, false),
+ erlang:suspend_process(P1),
+ ?CHK_SUSPENDED(P1, true),
+ erlang:suspend_process(P1),
+ erlang:suspend_process(P1),
+ erlang:suspend_process(P1),
+ ?CHK_SUSPENDED(P1, true),
+ erlang:resume_process(P1),
+ erlang:resume_process(P1),
+ erlang:resume_process(P1),
+ ?CHK_SUSPENDED(P1, true),
+ erlang:resume_process(P1),
+ ?CHK_SUSPENDED(P1, false),
+ erlang:suspend_process(P1),
+ erlang:suspend_process(P1),
+ erlang:suspend_process(P1),
+ ?CHK_SUSPENDED(P1, true),
+ exit(bang)
+ end),
+ receive
+ {'DOWN', M2,process,P2,R2} ->
+ bang = R2,
+ ?CHK_SUSPENDED(P1, false)
+ end,
+ Parent = self(),
+ {P3, M3} = spawn_monitor(
+ fun () ->
+ erlang:suspend_process(P1),
+ ?CHK_SUSPENDED(P1, true),
+ Parent ! self(),
+ receive after infinity -> ok end
+ end),
+ {P4, M4} = spawn_monitor(
+ fun () ->
+ erlang:suspend_process(P1),
+ ?CHK_SUSPENDED(P1, true),
+ Parent ! self(),
+ receive after infinity -> ok end
+ end),
+ {P5, M5} = spawn_monitor(
+ fun () ->
+ erlang:suspend_process(P1),
+ ?CHK_SUSPENDED(P1, true),
+ Parent ! self(),
+ receive after infinity -> ok end
+ end),
+ {P6, M6} = spawn_monitor(
+ fun () ->
+ erlang:suspend_process(P1),
+ ?CHK_SUSPENDED(P1, true),
+ Parent ! self(),
+ receive after infinity -> ok end
+ end),
+ {P7, M7} = spawn_monitor(
+ fun () ->
+ erlang:suspend_process(P1),
+ ?CHK_SUSPENDED(P1, true),
+ Parent ! self(),
+ receive after infinity -> ok end
+ end),
+ receive P3 -> ok end,
+ receive P4 -> ok end,
+ receive P5 -> ok end,
+ receive P6 -> ok end,
+ receive P7 -> ok end,
+ ?CHK_SUSPENDED(P1, true),
+ exit(P3, bang),
+ receive
+ {'DOWN',M3,process,P3,R3} ->
+ bang = R3,
+ ?CHK_SUSPENDED(P1, true)
+ end,
+ exit(P4, bang),
+ receive
+ {'DOWN',M4,process,P4,R4} ->
+ bang = R4,
+ ?CHK_SUSPENDED(P1, true)
+ end,
+ exit(P5, bang),
+ receive
+ {'DOWN',M5,process,P5,R5} ->
+ bang = R5,
+ ?CHK_SUSPENDED(P1, true)
+ end,
+ exit(P6, bang),
+ receive
+ {'DOWN',M6,process,P6,R6} ->
+ bang = R6,
+ ?CHK_SUSPENDED(P1, true)
+ end,
+ exit(P7, bang),
+ receive
+ {'DOWN',M7,process,P7,R7} ->
+ bang = R7,
+ ?CHK_SUSPENDED(P1, false)
+ end,
+ unlink(P1),
+ exit(P1, bong),
+ ok.
+
suspend_system_limit(Config) when is_list(Config) ->
case os:getenv("ERL_EXTREME_TESTING") of
- "true" ->
- ?line Dog = test_server:timetrap(test_server:minutes(3*60)),
- ?line P = spawn_link(fun () -> receive after infinity -> ok end end),
- ?line suspend_until_system_limit(P),
- ?line unlink(P),
- ?line exit(P, bye),
- ?line test_server:timetrap_cancel(Dog),
- ?line ok;
- _ ->
- {skip, "Takes too long time for normal testing"}
+ "true" ->
+ ct:timetrap({minutes, 3*60}),
+ P = spawn_link(fun () -> receive after infinity -> ok end end),
+ suspend_until_system_limit(P),
+ unlink(P),
+ exit(P, bye),
+ ok;
+ _ ->
+ {skip, "Takes too long time for normal testing"}
end.
suspend_until_system_limit(P) ->
- ?line suspend_until_system_limit(P, 0, 0).
+ suspend_until_system_limit(P, 0, 0).
suspend_until_system_limit(P, N, M) ->
NewM = case M of
- 1 ->
- ?line ?CHK_SUSPENDED(P, true), 2;
- 1000000 ->
- erlang:display(N), 1;
- _ ->
- M+1
- end,
- ?line case catch erlang:suspend_process(P) of
- true ->
- suspend_until_system_limit(P, N+1, NewM);
- {'EXIT', R} when R == system_limit;
- element(1, R) == system_limit ->
- ?line ?t:format("system limit at ~p~n", [N]),
- ?line resume_from_system_limit(P, N, 0);
- Error ->
- ?line ?t:fail(Error)
- end.
+ 1 ->
+ ?CHK_SUSPENDED(P, true), 2;
+ 1000000 ->
+ erlang:display(N), 1;
+ _ ->
+ M+1
+ end,
+ case catch erlang:suspend_process(P) of
+ true ->
+ suspend_until_system_limit(P, N+1, NewM);
+ {'EXIT', R} when R == system_limit;
+ element(1, R) == system_limit ->
+ io:format("system limit at ~p~n", [N]),
+ resume_from_system_limit(P, N, 0);
+ Error ->
+ ct:fail(Error)
+ end.
resume_from_system_limit(P, 0, _) ->
- ?line ?CHK_SUSPENDED(P, false),
- ?line {'EXIT', _} = (catch erlang:resume_process(P)),
- ?line ok;
+ ?CHK_SUSPENDED(P, false),
+ {'EXIT', _} = (catch erlang:resume_process(P)),
+ ok;
resume_from_system_limit(P, N, M) ->
- ?line NewM = case M of
- 1 ->
- ?line ?CHK_SUSPENDED(P, true), 2;
- 1000000 ->
- erlang:display(N), 1;
- _ ->
- M+1
- end,
- ?line erlang:resume_process(P),
- ?line resume_from_system_limit(P, N-1, NewM).
+ NewM = case M of
+ 1 ->
+ ?CHK_SUSPENDED(P, true), 2;
+ 1000000 ->
+ erlang:display(N), 1;
+ _ ->
+ M+1
+ end,
+ erlang:resume_process(P),
+ resume_from_system_limit(P, N-1, NewM).
-record(susp_info, {async = 0,
- dbl_async = 0,
- synced = 0,
- async_once = 0}).
-
-suspend_opts(doc) ->
- [];
-suspend_opts(suite) ->
- [];
+ dbl_async = 0,
+ synced = 0,
+ async_once = 0}).
+
suspend_opts(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(3)),
- ?line Self = self(),
- ?line wait_for_empty_runq(10),
- ?line Tok = spawn_link(fun () ->
- Self ! self(),
- tok_trace_loop(Self, 0, 1000000000)
- end),
- ?line TC = 1000,
- ?line receive Tok -> ok end,
- ?line SF = fun (N, #susp_info {async = A,
- dbl_async = AA,
- synced = S,
- async_once = AO} = Acc) ->
- ?line erlang:suspend_process(Tok, [asynchronous]),
- ?line Res = case {suspend_count(Tok), N rem 4} of
- {0, 2} ->
- ?line erlang:suspend_process(Tok,
- [asynchronous]),
- case suspend_count(Tok) of
- 2 ->
- ?line erlang:resume_process(Tok),
- ?line Acc#susp_info{async = A+1};
- 0 ->
- ?line erlang:resume_process(Tok),
- ?line Acc#susp_info{async = A+1,
- dbl_async = AA+1}
- end;
- {0, 1} ->
- ?line erlang:suspend_process(Tok,
- [asynchronous,
- unless_suspending]),
- case suspend_count(Tok) of
- 1 ->
- ?line Acc#susp_info{async = A+1};
- 0 ->
- ?line Acc#susp_info{async = A+1,
- async_once = AO+1}
- end;
- {0, 0} ->
- ?line erlang:suspend_process(Tok,
- [unless_suspending]),
- ?line 1 = suspend_count(Tok),
- ?line Acc#susp_info{async = A+1,
- synced = S+1};
- {0, _} ->
- ?line Acc#susp_info{async = A+1};
- _ ->
- Acc
- end,
- ?line erlang:resume_process(Tok),
- ?line erlang:yield(),
- ?line Res
- end,
- ?line SI = repeat_acc(SF, TC, #susp_info{}),
- ?line erlang:suspend_process(Tok, [asynchronous]),
+ ct:timetrap({minutes, 3}),
+ Self = self(),
+ wait_for_empty_runq(10),
+ Tok = spawn_link(fun () ->
+ Self ! self(),
+ tok_trace_loop(Self, 0, 1000000000)
+ end),
+ TC = 1000,
+ receive Tok -> ok end,
+ SF = fun (N, #susp_info {async = A,
+ dbl_async = AA,
+ synced = S,
+ async_once = AO} = Acc) ->
+ erlang:suspend_process(Tok, [asynchronous]),
+ Res = case {suspend_count(Tok), N rem 4} of
+ {0, 2} ->
+ erlang:suspend_process(Tok,
+ [asynchronous]),
+ case suspend_count(Tok) of
+ 2 ->
+ erlang:resume_process(Tok),
+ Acc#susp_info{async = A+1};
+ 0 ->
+ erlang:resume_process(Tok),
+ Acc#susp_info{async = A+1,
+ dbl_async = AA+1}
+ end;
+ {0, 1} ->
+ erlang:suspend_process(Tok,
+ [asynchronous,
+ unless_suspending]),
+ case suspend_count(Tok) of
+ 1 ->
+ Acc#susp_info{async = A+1};
+ 0 ->
+ Acc#susp_info{async = A+1,
+ async_once = AO+1}
+ end;
+ {0, 0} ->
+ erlang:suspend_process(Tok,
+ [unless_suspending]),
+ 1 = suspend_count(Tok),
+ Acc#susp_info{async = A+1,
+ synced = S+1};
+ {0, _} ->
+ Acc#susp_info{async = A+1};
+ _ ->
+ Acc
+ end,
+ erlang:resume_process(Tok),
+ erlang:yield(),
+ Res
+ end,
+ SI = repeat_acc(SF, TC, #susp_info{}),
+ erlang:suspend_process(Tok, [asynchronous]),
%% Verify that it eventually suspends
- ?line WaitTime0 = 10,
- ?line WaitTime1 = case {erlang:system_info(debug_compiled),
- erlang:system_info(lock_checking)} of
- {false, false} ->
- WaitTime0;
- {false, true} ->
- WaitTime0*5;
- _ ->
- WaitTime0*10
- end,
- ?line WaitTime = case {erlang:system_info(schedulers_online),
- erlang:system_info(logical_processors)} of
- {Schdlrs, CPUs} when is_integer(CPUs),
- Schdlrs =< CPUs ->
- WaitTime1;
- _ ->
- WaitTime1*10
- end,
- ?line receive after WaitTime -> ok end,
- ?line 1 = suspend_count(Tok),
- ?line erlang:suspend_process(Tok, [asynchronous]),
- ?line 2 = suspend_count(Tok),
- ?line erlang:suspend_process(Tok, [asynchronous]),
- ?line 3 = suspend_count(Tok),
- ?line erlang:suspend_process(Tok),
- ?line 4 = suspend_count(Tok),
- ?line erlang:suspend_process(Tok),
- ?line 5 = suspend_count(Tok),
- ?line erlang:suspend_process(Tok, [unless_suspending]),
- ?line 5 = suspend_count(Tok),
- ?line erlang:suspend_process(Tok, [unless_suspending,
- asynchronous]),
- ?line 5 = suspend_count(Tok),
- ?line erlang:resume_process(Tok),
- ?line erlang:resume_process(Tok),
- ?line erlang:resume_process(Tok),
- ?line erlang:resume_process(Tok),
- ?line 1 = suspend_count(Tok),
- ?line ?t:format("Main suspends: ~p~n"
- "Main async: ~p~n"
- "Double async: ~p~n"
- "Async once: ~p~n"
- "Synced: ~p~n",
- [TC,
- SI#susp_info.async,
- SI#susp_info.dbl_async,
- SI#susp_info.async_once,
- SI#susp_info.synced]),
- ?line case erlang:system_info(schedulers_online) of
- 1 ->
- ?line ok;
- _ ->
- ?line true = SI#susp_info.async =/= 0
- end,
- ?line unlink(Tok),
- ?line exit(Tok, bang),
- ?line test_server:timetrap_cancel(Dog),
- ?line ok.
+ WaitTime0 = 10,
+ WaitTime1 = case {erlang:system_info(debug_compiled),
+ erlang:system_info(lock_checking)} of
+ {false, false} ->
+ WaitTime0;
+ {false, true} ->
+ WaitTime0*5;
+ _ ->
+ WaitTime0*10
+ end,
+ WaitTime = case {erlang:system_info(schedulers_online),
+ erlang:system_info(logical_processors)} of
+ {Schdlrs, CPUs} when is_integer(CPUs),
+ Schdlrs =< CPUs ->
+ WaitTime1;
+ _ ->
+ WaitTime1*10
+ end,
+ receive after WaitTime -> ok end,
+ 1 = suspend_count(Tok),
+ erlang:suspend_process(Tok, [asynchronous]),
+ 2 = suspend_count(Tok),
+ erlang:suspend_process(Tok, [asynchronous]),
+ 3 = suspend_count(Tok),
+ erlang:suspend_process(Tok),
+ 4 = suspend_count(Tok),
+ erlang:suspend_process(Tok),
+ 5 = suspend_count(Tok),
+ erlang:suspend_process(Tok, [unless_suspending]),
+ 5 = suspend_count(Tok),
+ erlang:suspend_process(Tok, [unless_suspending,
+ asynchronous]),
+ 5 = suspend_count(Tok),
+ erlang:resume_process(Tok),
+ erlang:resume_process(Tok),
+ erlang:resume_process(Tok),
+ erlang:resume_process(Tok),
+ 1 = suspend_count(Tok),
+ io:format("Main suspends: ~p~n"
+ "Main async: ~p~n"
+ "Double async: ~p~n"
+ "Async once: ~p~n"
+ "Synced: ~p~n",
+ [TC,
+ SI#susp_info.async,
+ SI#susp_info.dbl_async,
+ SI#susp_info.async_once,
+ SI#susp_info.synced]),
+ case erlang:system_info(schedulers_online) of
+ 1 ->
+ ok;
+ _ ->
+ true = SI#susp_info.async =/= 0
+ end,
+ unlink(Tok),
+ exit(Tok, bang),
+ ok.
suspend_count(Suspendee) ->
suspend_count(self(), Suspendee).
suspend_count(Suspender, Suspendee) ->
{suspending, SList} = process_info(Suspender, suspending),
-
+
case lists:keysearch(Suspendee, 1, SList) of
- {value, {_Suspendee, 0, 0}} ->
- ?line ?t:fail({bad_suspendee_list, SList});
- {value, {Suspendee, Count, 0}} when is_integer(Count), Count > 0 ->
- {status, suspended} = process_info(Suspendee, status),
- Count;
- {value, {Suspendee, 0, Outstanding}} when is_integer(Outstanding),
- Outstanding > 0 ->
- 0;
- false ->
- 0;
- Error ->
- ?line ?t:fail({bad_suspendee_list, Error, SList})
+ {value, {_Suspendee, 0, 0}} ->
+ ct:fail({bad_suspendee_list, SList});
+ {value, {Suspendee, Count, 0}} when is_integer(Count), Count > 0 ->
+ {status, suspended} = process_info(Suspendee, status),
+ Count;
+ {value, {Suspendee, 0, Outstanding}} when is_integer(Outstanding),
+ Outstanding > 0 ->
+ 0;
+ false ->
+ 0;
+ Error ->
+ ct:fail({bad_suspendee_list, Error, SList})
end.
-
+
repeat_acc(Fun, N, Acc) ->
repeat_acc(Fun, 0, N, Acc).
@@ -1306,121 +1204,100 @@ repeat_acc(_Fun, N, N, Acc) ->
Acc;
repeat_acc(Fun, N, M, Acc) ->
repeat_acc(Fun, N+1, M, Fun(N, Acc)).
-
+
%% Tests that waiting process can be suspended
%% (bug in R2D and earlier; see OTP-1488).
-suspend_waiting(doc) -> "Test that a waiting process can be suspended.";
+%% Test that a waiting process can be suspended.
suspend_waiting(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
-
- ?line Process = fun_spawn(fun process/0),
- ?line receive after 1 -> ok end,
- ?line true = erlang:suspend_process(Process),
- ?line {status, suspended} = process_info(Process, status),
-
- %% Done.
- ?line test_server:timetrap_cancel(Dog),
+ Process = fun_spawn(fun process/0),
+ receive after 1 -> ok end,
+ true = erlang:suspend_process(Process),
+ {status, suspended} = process_info(Process, status),
ok.
-
-new_clear(doc) ->
- "Test that erlang:trace(new, true, ...) is cleared when tracer dies.";
+%% Test that erlang:trace(new, true, ...) is cleared when tracer dies.
new_clear(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
-
- ?line Tracer = spawn(fun receiver/0),
- ?line 0 = erlang:trace(new, true, [send, {tracer, Tracer}]),
- ?line {flags, [send]} = erlang:trace_info(new, flags),
- ?line {tracer, Tracer} = erlang:trace_info(new, tracer),
- ?line Mref = erlang:monitor(process, Tracer),
- ?line true = exit(Tracer, done),
+ Tracer = spawn(fun receiver/0),
+ 0 = erlang:trace(new, true, [send, {tracer, Tracer}]),
+ {flags, [send]} = erlang:trace_info(new, flags),
+ {tracer, Tracer} = erlang:trace_info(new, tracer),
+ Mref = erlang:monitor(process, Tracer),
+ true = exit(Tracer, done),
receive
- {'DOWN',Mref,_,_,_} -> ok
+ {'DOWN',Mref,_,_,_} -> ok
end,
- ?line {flags, []} = erlang:trace_info(new, flags),
- ?line {tracer, []} = erlang:trace_info(new, tracer),
-
- %% Done.
- ?line test_server:timetrap_cancel(Dog),
-
+ {flags, []} = erlang:trace_info(new, flags),
+ {tracer, []} = erlang:trace_info(new, tracer),
ok.
-existing_clear(doc) ->
- "Test that erlang:trace(all, false, ...) works without tracer.";
+%% Test that erlang:trace(all, false, ...) works without tracer.
existing_clear(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line Self = self(),
-
- ?line Tracer = fun_spawn(fun receiver/0),
- ?line N = erlang:trace(existing, true, [send, {tracer, Tracer}]),
- ?line {flags, [send]} = erlang:trace_info(Self, flags),
- ?line {tracer, Tracer} = erlang:trace_info(Self, tracer),
- ?line M = erlang:trace(all, false, [all]),
- ?line io:format("Started trace on ~p processes and stopped on ~p~n",
- [N, M]),
- ?line {flags, []} = erlang:trace_info(Self, flags),
- ?line {tracer, []} = erlang:trace_info(Self, tracer),
- ?line M = N + 1, % Since trace could not be enabled on the tracer.
+ Self = self(),
- %% Done.
- ?line test_server:timetrap_cancel(Dog),
+ Tracer = fun_spawn(fun receiver/0),
+ N = erlang:trace(existing, true, [send, {tracer, Tracer}]),
+ {flags, [send]} = erlang:trace_info(Self, flags),
+ {tracer, Tracer} = erlang:trace_info(Self, tracer),
+ M = erlang:trace(all, false, [all]),
+ io:format("Started trace on ~p processes and stopped on ~p~n",
+ [N, M]),
+ {flags, []} = erlang:trace_info(Self, flags),
+ {tracer, []} = erlang:trace_info(Self, tracer),
+ M = N + 1, % Since trace could not be enabled on the tracer.
ok.
-bad_flag(doc) -> "Test that an invalid flag cause badarg";
-bad_flag(suite) -> [];
+%% Test that an invalid flag cause badarg
bad_flag(Config) when is_list(Config) ->
%% A bad flag could deadlock the SMP emulator in erts-5.5
- ?line {'EXIT', {badarg, _}} = (catch erlang:trace(new,
- true,
- [not_a_valid_flag])),
- ?line ok.
+ {'EXIT', {badarg, _}} = (catch erlang:trace(new,
+ true,
+ [not_a_valid_flag])),
+ ok.
-trace_delivered(doc) -> "Test erlang:trace_delivered/1";
-trace_delivered(suite) -> [];
+%% Test erlang:trace_delivered/1
trace_delivered(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(60)),
- ?line TokLoops = 10000,
- ?line Go = make_ref(),
- ?line Parent = self(),
- ?line Tok = spawn(fun () ->
- receive Go -> gone end,
- tok_trace_loop(Parent, 0, TokLoops)
- end),
- ?line 1 = erlang:trace(Tok, true, [procs]),
- ?line Mon = erlang:monitor(process, Tok),
- ?line NoOfTraceMessages = 4*TokLoops + 1,
- ?line io:format("Expect a total of ~p trace messages~n",
- [NoOfTraceMessages]),
- ?line Tok ! Go,
- ?line NoOfTraceMessages = drop_trace_until_down(Tok, Mon),
- ?line receive
- Msg ->
- ?line ?t:fail({unexpected_message, Msg})
- after 1000 ->
- ?line test_server:timetrap_cancel(Dog),
- ?line ok
- end.
+ ct:timetrap({minutes, 1}),
+ TokLoops = 10000,
+ Go = make_ref(),
+ Parent = self(),
+ Tok = spawn(fun () ->
+ receive Go -> gone end,
+ tok_trace_loop(Parent, 0, TokLoops)
+ end),
+ 1 = erlang:trace(Tok, true, [procs]),
+ Mon = erlang:monitor(process, Tok),
+ NoOfTraceMessages = 4*TokLoops + 1,
+ io:format("Expect a total of ~p trace messages~n",
+ [NoOfTraceMessages]),
+ Tok ! Go,
+ NoOfTraceMessages = drop_trace_until_down(Tok, Mon),
+ receive
+ Msg ->
+ ct:fail({unexpected_message, Msg})
+ after 1000 ->
+ ok
+ end.
drop_trace_until_down(Proc, Mon) ->
drop_trace_until_down(Proc, Mon, false, 0, 0).
drop_trace_until_down(Proc, Mon, TDRef, N, D) ->
case receive Msg -> Msg end of
- {trace_delivered, Proc, TDRef} ->
- io:format("~p trace messages on 'DOWN'~n", [D]),
- io:format("Got a total of ~p trace messages~n", [N]),
- N;
- {'DOWN', Mon, process, Proc, _} ->
- Ref = erlang:trace_delivered(Proc),
- drop_trace_until_down(Proc, Mon, Ref, N, N);
- Trace when is_tuple(Trace),
- element(1, Trace) == trace,
- element(2, Trace) == Proc ->
- drop_trace_until_down(Proc, Mon, TDRef, N+1, D)
+ {trace_delivered, Proc, TDRef} ->
+ io:format("~p trace messages on 'DOWN'~n", [D]),
+ io:format("Got a total of ~p trace messages~n", [N]),
+ N;
+ {'DOWN', Mon, process, Proc, _} ->
+ Ref = erlang:trace_delivered(Proc),
+ drop_trace_until_down(Proc, Mon, Ref, N, N);
+ Trace when is_tuple(Trace),
+ element(1, Trace) == trace,
+ element(2, Trace) == Proc ->
+ drop_trace_until_down(Proc, Mon, TDRef, N+1, D)
end.
tok_trace_loop(_, N, N) ->
@@ -1437,17 +1314,17 @@ tok_trace_loop(Parent, N, M) ->
receive_first() ->
receive
- Any -> Any
+ Any -> Any
end.
%% Ensures that there is no message in the message queue.
receive_nothing() ->
receive
- Any ->
- test_server:fail({unexpected_message, Any})
+ Any ->
+ ct:fail({unexpected_message, Any})
after 200 ->
- ok
+ ok
end.
@@ -1455,39 +1332,39 @@ receive_nothing() ->
process(Dest) ->
receive
- {send_please, To, What} ->
- To ! What,
- process(Dest);
- {spawn_link_please, ReplyTo, {M, F, A}} ->
- Pid = spawn_link(M, F, A),
- ReplyTo ! {spawned, self(), Pid},
- process(Dest);
- {spawn_link_please, ReplyTo, Node, {M, F, A}} ->
- Pid = spawn_link(Node, M, F, A),
- ReplyTo ! {spawned, self(), Pid},
- process(Dest);
- {link_please, Pid} ->
- link(Pid),
- process(Dest);
- {unlink_please, Pid} ->
- unlink(Pid),
- process(Dest);
- {register_please, Name, Pid} ->
- register(Name, Pid),
- process(Dest);
- {unregister_please, Name} ->
- unregister(Name),
- process(Dest);
- {exit_please, Reason} ->
- exit(Reason);
- {trap_exit_please, State} ->
- process_flag(trap_exit, State),
- process(Dest);
- Other ->
- Dest ! {self(), Other},
- process(Dest)
+ {send_please, To, What} ->
+ To ! What,
+ process(Dest);
+ {spawn_link_please, ReplyTo, {M, F, A}} ->
+ Pid = spawn_link(M, F, A),
+ ReplyTo ! {spawned, self(), Pid},
+ process(Dest);
+ {spawn_link_please, ReplyTo, Node, {M, F, A}} ->
+ Pid = spawn_link(Node, M, F, A),
+ ReplyTo ! {spawned, self(), Pid},
+ process(Dest);
+ {link_please, Pid} ->
+ link(Pid),
+ process(Dest);
+ {unlink_please, Pid} ->
+ unlink(Pid),
+ process(Dest);
+ {register_please, Name, Pid} ->
+ register(Name, Pid),
+ process(Dest);
+ {unregister_please, Name} ->
+ unregister(Name),
+ process(Dest);
+ {exit_please, Reason} ->
+ exit(Reason);
+ {trap_exit_please, State} ->
+ process_flag(trap_exit, State),
+ process(Dest);
+ Other ->
+ Dest ! {self(), Other},
+ process(Dest)
after 3000 ->
- exit(timeout)
+ exit(timeout)
end.
@@ -1495,17 +1372,17 @@ process(Dest) ->
process() ->
receive
- {spawn_please, ReplyTo, Fun} ->
- Pid = fun_spawn(Fun),
- ReplyTo ! {spawned, Pid},
- process();
- {send_please, To, What} ->
- To ! What,
- process();
- timeout_please ->
- receive after 1 -> process() end;
- _Other ->
- process()
+ {spawn_please, ReplyTo, Fun} ->
+ Pid = fun_spawn(Fun),
+ ReplyTo ! {spawned, Pid},
+ process();
+ {send_please, To, What} ->
+ To ! What,
+ process();
+ timeout_please ->
+ receive after 1 -> process() end;
+ _Other ->
+ process()
end.
@@ -1513,9 +1390,9 @@ process() ->
sender() ->
receive
- {send_please, To, What} ->
- To ! What,
- sender()
+ {send_please, To, What} ->
+ To ! What,
+ sender()
end.
@@ -1523,7 +1400,7 @@ sender() ->
receiver() ->
receive
- _Any -> receiver()
+ _Any -> receiver()
end.
%% Works as long as it receives CPU time. Will always be RUNNABLE.
@@ -1545,7 +1422,7 @@ start_node(Name) ->
Pa = filename:dirname(code:which(?MODULE)),
Cookie = atom_to_list(erlang:get_cookie()),
test_server:start_node(Name, slave,
- [{args, "-setcookie " ++ Cookie ++" -pa " ++ Pa}]).
+ [{args, "-setcookie " ++ Cookie ++" -pa " ++ Pa}]).
stop_node(Node) ->
test_server:stop_node(Node).
@@ -1553,11 +1430,11 @@ stop_node(Node) ->
wait_for_empty_runq(DeadLine) ->
case statistics(run_queue) of
- 0 -> true;
- RQLen ->
- erlang:display("Waiting for empty run queue"),
- MSDL = DeadLine*1000,
- wait_for_empty_runq(MSDL, MSDL, RQLen)
+ 0 -> true;
+ RQLen ->
+ erlang:display("Waiting for empty run queue"),
+ MSDL = DeadLine*1000,
+ wait_for_empty_runq(MSDL, MSDL, RQLen)
end.
wait_for_empty_runq(DeadLine, Left, RQLen) when Left =< 0 ->
@@ -1568,48 +1445,48 @@ wait_for_empty_runq(DeadLine, Left, _RQLen) ->
UntilDeadLine = Left - Wait,
receive after Wait -> ok end,
case statistics(run_queue) of
- 0 ->
- erlang:display("Waited for "
- ++ integer_to_list(DeadLine
- - UntilDeadLine)
- ++ " ms for empty run queue."),
- true;
- NewRQLen ->
- wait_for_empty_runq(DeadLine,
- UntilDeadLine,
- NewRQLen)
+ 0 ->
+ erlang:display("Waited for "
+ ++ integer_to_list(DeadLine
+ - UntilDeadLine)
+ ++ " ms for empty run queue."),
+ true;
+ NewRQLen ->
+ wait_for_empty_runq(DeadLine,
+ UntilDeadLine,
+ NewRQLen)
end.
issue_non_empty_runq_warning(DeadLine, RQLen) ->
PIs = lists:foldl(
- fun (P, Acc) ->
- case process_info(P,
- [status,
- initial_call,
- current_function,
- registered_name,
- reductions,
- message_queue_len]) of
- [{status, Runnable} | _] = PI when Runnable /= waiting,
- Runnable /= suspended ->
- [[{pid, P} | PI] | Acc];
- _ ->
- Acc
- end
- end,
- [],
- processes()),
- ?t:format("WARNING: Unexpected runnable processes in system (waited ~p sec).~n"
- " Run queue length: ~p~n"
- " Self: ~p~n"
- " Processes info: ~p~n",
- [DeadLine div 1000, RQLen, self(), PIs]),
+ fun (P, Acc) ->
+ case process_info(P,
+ [status,
+ initial_call,
+ current_function,
+ registered_name,
+ reductions,
+ message_queue_len]) of
+ [{status, Runnable} | _] = PI when Runnable /= waiting,
+ Runnable /= suspended ->
+ [[{pid, P} | PI] | Acc];
+ _ ->
+ Acc
+ end
+ end,
+ [],
+ processes()),
+ io:format("WARNING: Unexpected runnable processes in system (waited ~p sec).~n"
+ " Run queue length: ~p~n"
+ " Self: ~p~n"
+ " Processes info: ~p~n",
+ [DeadLine div 1000, RQLen, self(), PIs]),
receive after 1000 -> ok end.
load_driver(Dir, Driver) ->
case erl_ddll:load_driver(Dir, Driver) of
- ok -> ok;
- {error, Error} = Res ->
- io:format("~s\n", [erl_ddll:format_error(Error)]),
- Res
+ ok -> ok;
+ {error, Error} = Res ->
+ io:format("~s\n", [erl_ddll:format_error(Error)]),
+ Res
end.
diff --git a/erts/emulator/test/trace_bif_SUITE.erl b/erts/emulator/test/trace_bif_SUITE.erl
index 96b7dd159f..b774210456 100644
--- a/erts/emulator/test/trace_bif_SUITE.erl
+++ b/erts/emulator/test/trace_bif_SUITE.erl
@@ -20,10 +20,9 @@
-module(trace_bif_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
+-export([all/0, suite/0]).
-export([trace_bif/1, trace_bif_timestamp/1, trace_on_and_off/1,
trace_bif_local/1,
trace_bif_timestamp_local/1, trace_bif_return/1, not_run/1,
@@ -42,99 +41,82 @@ all() ->
trace_bif_return, trace_info_old_code]
end.
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
not_run(Config) when is_list(Config) ->
{skipped,"Native code"}.
-trace_on_and_off(doc) ->
- "Tests switching tracing on and off.";
+%% Tests switching tracing on and off.
trace_on_and_off(Config) when is_list(Config) ->
- ?line Pid = spawn(?MODULE, bif_process, []),
- ?line Self = self(),
- ?line 1 = erlang:trace(Pid, true, [call,timestamp]),
- ?line {flags, Flags} = erlang:trace_info(Pid,flags),
- ?line [call,timestamp] = lists:sort(Flags),
- ?line {tracer, Self} = erlang:trace_info(Pid,tracer),
- ?line 1 = erlang:trace(Pid, false, [timestamp]),
- ?line {flags,[call]} = erlang:trace_info(Pid,flags),
- ?line {tracer, Self} = erlang:trace_info(Pid,tracer),
- ?line 1 = erlang:trace(Pid, false, [call]),
- ?line {flags,[]} = erlang:trace_info(Pid,flags),
- ?line {tracer, []} = erlang:trace_info(Pid,tracer),
- ?line exit(Pid,kill),
+ Pid = spawn(?MODULE, bif_process, []),
+ Self = self(),
+ 1 = erlang:trace(Pid, true, [call,timestamp]),
+ {flags, Flags} = erlang:trace_info(Pid,flags),
+ [call,timestamp] = lists:sort(Flags),
+ {tracer, Self} = erlang:trace_info(Pid,tracer),
+ 1 = erlang:trace(Pid, false, [timestamp]),
+ {flags,[call]} = erlang:trace_info(Pid,flags),
+ {tracer, Self} = erlang:trace_info(Pid,tracer),
+ 1 = erlang:trace(Pid, false, [call]),
+ {flags,[]} = erlang:trace_info(Pid,flags),
+ {tracer, []} = erlang:trace_info(Pid,tracer),
+ exit(Pid,kill),
ok.
-trace_bif(doc) -> "Test tracing BIFs.";
+%% Test tracing BIFs.
trace_bif(Config) when is_list(Config) ->
do_trace_bif([]).
-trace_bif_local(doc) -> "Test tracing BIFs with local flag.";
+%% Test tracing BIFs with local flag.
trace_bif_local(Config) when is_list(Config) ->
do_trace_bif([local]).
do_trace_bif(Flags) ->
- ?line Pid = spawn(?MODULE, bif_process, []),
- ?line 1 = erlang:trace(Pid, true, [call]),
- ?line erlang:trace_pattern({erlang,'_','_'}, [], Flags),
- ?line Pid ! {do_bif, time, []},
- ?line receive_trace_msg({trace,Pid,call,{erlang,time, []}}),
- ?line Pid ! {do_bif, statistics, [runtime]},
- ?line receive_trace_msg({trace,Pid,call,
- {erlang,statistics, [runtime]}}),
-
- ?line Pid ! {do_time_bif},
- ?line receive_trace_msg({trace,Pid,call,
- {erlang,time, []}}),
-
- ?line Pid ! {do_statistics_bif},
- ?line receive_trace_msg({trace,Pid,call,
- {erlang,statistics, [runtime]}}),
-
- ?line 1 = erlang:trace(Pid, false, [call]),
- ?line erlang:trace_pattern({erlang,'_','_'}, false, Flags),
- ?line exit(Pid, die),
+ Pid = spawn(?MODULE, bif_process, []),
+ 1 = erlang:trace(Pid, true, [call]),
+ erlang:trace_pattern({erlang,'_','_'}, [], Flags),
+ Pid ! {do_bif, time, []},
+ receive_trace_msg({trace,Pid,call,{erlang,time, []}}),
+ Pid ! {do_bif, statistics, [runtime]},
+ receive_trace_msg({trace,Pid,call,
+ {erlang,statistics, [runtime]}}),
+
+ Pid ! {do_time_bif},
+ receive_trace_msg({trace,Pid,call,
+ {erlang,time, []}}),
+
+ Pid ! {do_statistics_bif},
+ receive_trace_msg({trace,Pid,call,
+ {erlang,statistics, [runtime]}}),
+
+ 1 = erlang:trace(Pid, false, [call]),
+ erlang:trace_pattern({erlang,'_','_'}, false, Flags),
+ exit(Pid, die),
ok.
-trace_bif_timestamp(doc) -> "Test tracing BIFs with timestamps.";
+%% Test tracing BIFs with timestamps.
trace_bif_timestamp(Config) when is_list(Config) ->
do_trace_bif_timestamp([], timestamp, [timestamp]),
do_trace_bif_timestamp([], timestamp,
- [timestamp,
- monotonic_timestamp,
- strict_monotonic_timestamp]),
+ [timestamp,
+ monotonic_timestamp,
+ strict_monotonic_timestamp]),
do_trace_bif_timestamp([], strict_monotonic_timestamp,
- [strict_monotonic_timestamp]),
+ [strict_monotonic_timestamp]),
do_trace_bif_timestamp([], strict_monotonic_timestamp,
- [monotonic_timestamp, strict_monotonic_timestamp]),
+ [monotonic_timestamp, strict_monotonic_timestamp]),
do_trace_bif_timestamp([], monotonic_timestamp, [monotonic_timestamp]).
-
-trace_bif_timestamp_local(doc) ->
- "Test tracing BIFs with timestamps and local flag.";
+
+%% Test tracing BIFs with timestamps and local flag.
trace_bif_timestamp_local(Config) when is_list(Config) ->
do_trace_bif_timestamp([local], timestamp, [timestamp]),
do_trace_bif_timestamp([local], timestamp,
- [timestamp,
- monotonic_timestamp,
- strict_monotonic_timestamp]),
+ [timestamp,
+ monotonic_timestamp,
+ strict_monotonic_timestamp]),
do_trace_bif_timestamp([local], strict_monotonic_timestamp,
- [strict_monotonic_timestamp]),
+ [strict_monotonic_timestamp]),
do_trace_bif_timestamp([local], strict_monotonic_timestamp,
- [monotonic_timestamp, strict_monotonic_timestamp]),
+ [monotonic_timestamp, strict_monotonic_timestamp]),
do_trace_bif_timestamp([local], monotonic_timestamp, [monotonic_timestamp]).
do_trace_bif_timestamp(Flags, TsType, TsFlags) ->
@@ -146,22 +128,22 @@ do_trace_bif_timestamp(Flags, TsType, TsFlags) ->
Ts0 = make_ts(TsType),
Pid ! {do_bif, time, []},
Ts1 = receive_trace_msg_ts({trace_ts,Pid,call,{erlang,time,[]}},
- Ts0,TsType),
+ Ts0,TsType),
Pid ! {do_bif, statistics, [runtime]},
Ts2 = receive_trace_msg_ts({trace_ts,Pid,call,
- {erlang,statistics, [runtime]}},
- Ts1, TsType),
+ {erlang,statistics, [runtime]}},
+ Ts1, TsType),
Pid ! {do_time_bif},
Ts3 = receive_trace_msg_ts({trace_ts,Pid,call,
- {erlang,time, []}},
- Ts2, TsType),
+ {erlang,time, []}},
+ Ts2, TsType),
Pid ! {do_statistics_bif},
Ts4 = receive_trace_msg_ts({trace_ts,Pid,call,
- {erlang,statistics, [runtime]}},
- Ts3, TsType),
+ {erlang,statistics, [runtime]}},
+ Ts3, TsType),
check_ts(TsType, Ts4, make_ts(TsType)),
@@ -170,11 +152,11 @@ do_trace_bif_timestamp(Flags, TsType, TsFlags) ->
Pid ! {do_statistics_bif},
receive_trace_msg({trace,Pid,call,
- {erlang,statistics, [runtime]}}),
+ {erlang,statistics, [runtime]}}),
Pid ! {do_bif, statistics, [runtime]},
receive_trace_msg({trace,Pid,call,
- {erlang,statistics, [runtime]}}),
+ {erlang,statistics, [runtime]}}),
1 = erlang:trace(Pid, false, [call]),
erlang:trace_pattern({erlang,'_','_'}, false, Flags),
@@ -182,18 +164,17 @@ do_trace_bif_timestamp(Flags, TsType, TsFlags) ->
exit(Pid, die),
ok.
-trace_bif_return(doc) ->
- "Test tracing BIF's with return/return_to trace.";
+%% Test tracing BIF's with return/return_to trace.
trace_bif_return(Config) when is_list(Config) ->
do_trace_bif_return(timestamp, [timestamp]),
do_trace_bif_return(timestamp,
- [timestamp,
- monotonic_timestamp,
- strict_monotonic_timestamp]),
+ [timestamp,
+ monotonic_timestamp,
+ strict_monotonic_timestamp]),
do_trace_bif_return(strict_monotonic_timestamp,
- [strict_monotonic_timestamp]),
+ [strict_monotonic_timestamp]),
do_trace_bif_return(strict_monotonic_timestamp,
- [monotonic_timestamp, strict_monotonic_timestamp]),
+ [monotonic_timestamp, strict_monotonic_timestamp]),
do_trace_bif_return(monotonic_timestamp, [monotonic_timestamp]).
do_trace_bif_return(TsType, TsFlags) ->
@@ -201,114 +182,104 @@ do_trace_bif_return(TsType, TsFlags) ->
Pid=spawn(?MODULE, bif_process, []),
1 = erlang:trace(Pid, true, [call,return_to]++TsFlags),
erlang:trace_pattern({erlang,'_','_'}, [{'_',[],[{return_trace}]}],
- [local]),
+ [local]),
Ts0 = make_ts(TsType),
Pid ! {do_bif, time, []},
Ts1 = receive_trace_msg_ts({trace_ts,Pid,call,{erlang,time,[]}},
- Ts0, TsType),
+ Ts0, TsType),
Ts2 = receive_trace_msg_ts_return_from({trace_ts,Pid,return_from,
- {erlang,time,0}},
- Ts1, TsType),
+ {erlang,time,0}},
+ Ts1, TsType),
Ts3 = receive_trace_msg_ts_return_to({trace_ts,Pid,return_to,
- {?MODULE, bif_process,0}},
- Ts2, TsType),
-
-
+ {?MODULE, bif_process,0}},
+ Ts2, TsType),
+
+
Pid ! {do_bif, statistics, [runtime]},
Ts4 = receive_trace_msg_ts({trace_ts,Pid,call,
- {erlang,statistics, [runtime]}},
- Ts3, TsType),
+ {erlang,statistics, [runtime]}},
+ Ts3, TsType),
Ts5 = receive_trace_msg_ts_return_from({trace_ts,Pid,return_from,
- {erlang,statistics,1}},
- Ts4, TsType),
+ {erlang,statistics,1}},
+ Ts4, TsType),
Ts6 = receive_trace_msg_ts_return_to({trace_ts,Pid,return_to,
- {?MODULE, bif_process,0}},
- Ts5, TsType),
-
-
+ {?MODULE, bif_process,0}},
+ Ts5, TsType),
+
+
Pid ! {do_time_bif},
Ts7 = receive_trace_msg_ts({trace_ts,Pid,call,
- {erlang,time, []}},
- Ts6, TsType),
+ {erlang,time, []}},
+ Ts6, TsType),
Ts8 = receive_trace_msg_ts_return_from({trace_ts,Pid,return_from,
- {erlang,time,0}},
- Ts7, TsType),
+ {erlang,time,0}},
+ Ts7, TsType),
Ts9 = receive_trace_msg_ts_return_to({trace_ts,Pid,return_to,
- {?MODULE, bif_process,0}},
- Ts8, TsType),
+ {?MODULE, bif_process,0}},
+ Ts8, TsType),
Pid ! {do_statistics_bif},
Ts10 = receive_trace_msg_ts({trace_ts,Pid,call,
- {erlang,statistics, [runtime]}},
- Ts9, TsType),
+ {erlang,statistics, [runtime]}},
+ Ts9, TsType),
Ts11 = receive_trace_msg_ts_return_from({trace_ts,Pid,return_from,
- {erlang,statistics,1}},
- Ts10, TsType),
+ {erlang,statistics,1}},
+ Ts10, TsType),
Ts12 = receive_trace_msg_ts_return_to({trace_ts,Pid,return_to,
- {?MODULE, bif_process,0}},
- Ts11, TsType),
+ {?MODULE, bif_process,0}},
+ Ts11, TsType),
check_ts(TsType, Ts12, make_ts(TsType)),
ok.
-
-
+
+
receive_trace_msg(Mess) ->
receive
- Mess ->
- ok;
- Other ->
- io:format("Expected: ~p,~nGot: ~p~n", [Mess, Other]),
- ?t:fail()
+ Mess ->
+ ok;
+ Other ->
+ ct:fail("Expected: ~p,~nGot: ~p~n", [Mess, Other])
after 5000 ->
- io:format("Expected: ~p,~nGot: timeout~n", [Mess]),
- ?t:fail()
+ ct:fail("Expected: ~p,~nGot: timeout~n", [Mess])
end.
receive_trace_msg_ts({trace_ts, Pid, call, {erlang,F,A}}, PrevTs, TsType) ->
receive
- {trace_ts, Pid, call, {erlang, F, A}, Ts} ->
- check_ts(TsType, PrevTs, Ts),
- Ts;
- Other ->
- io:format("Expected: {trace, ~p, call, {~p, ~p, ~p}, TimeStamp}},~n"
- "Got: ~p~n",
- [Pid, erlang, F, A, Other]),
- ?t:fail()
- after 5000 ->
- io:format("Got timeout~n", []),
- ?t:fail()
+ {trace_ts, Pid, call, {erlang, F, A}, Ts} ->
+ check_ts(TsType, PrevTs, Ts),
+ Ts;
+ Other ->
+ ct:fail("Expected: {trace, ~p, call, {~p, ~p, ~p}, TimeStamp}},~n"
+ "Got: ~p~n",
+ [Pid, erlang, F, A, Other])
+ after 5000 ->
+ ct:fail("Got timeout~n", [])
end.
receive_trace_msg_ts_return_from({trace_ts, Pid, return_from, {erlang,F,A}}, PrevTs, TsType) ->
receive
- {trace_ts, Pid, return_from, {erlang, F, A}, _Value, Ts} ->
- check_ts(TsType, PrevTs, Ts),
- Ts;
- Other ->
- io:format("Expected: {trace_ts, ~p, return_from, {~p, ~p, ~p}, Value, TimeStamp}},~n"
- "Got: ~p~n",
- [Pid, erlang, F, A, Other]),
- ?t:fail()
- after 5000 ->
- io:format("Got timeout~n", []),
- ?t:fail()
+ {trace_ts, Pid, return_from, {erlang, F, A}, _Value, Ts} ->
+ check_ts(TsType, PrevTs, Ts),
+ Ts;
+ Other ->
+ ct:fail("Expected: {trace_ts, ~p, return_from, {~p, ~p, ~p}, Value, TimeStamp}},~n"
+ "Got: ~p~n", [Pid, erlang, F, A, Other])
+ after 5000 ->
+ ct:fail("Got timeout~n", [])
end.
receive_trace_msg_ts_return_to({trace_ts, Pid, return_to, {M,F,A}}, PrevTs, TsType) ->
receive
- {trace_ts, Pid, return_to, {M, F, A}, Ts} ->
- check_ts(TsType, PrevTs, Ts),
- Ts;
- Other ->
- io:format("Expected: {trace_ts, ~p, return_to, {~p, ~p, ~p}, TimeStamp}},~n"
- "Got: ~p~n",
- [Pid, M, F, A, Other]),
- ?t:fail()
- after 5000 ->
- io:format("Got timeout~n", []),
- ?t:fail()
+ {trace_ts, Pid, return_to, {M, F, A}, Ts} ->
+ check_ts(TsType, PrevTs, Ts),
+ Ts;
+ Other ->
+ ct:fail("Expected: {trace_ts, ~p, return_to, {~p, ~p, ~p}, TimeStamp}},~n"
+ "Got: ~p~n", [Pid, M, F, A, Other])
+ after 5000 ->
+ ct:fail("Got timeout~n", [])
end.
make_ts(timestamp) ->
@@ -340,37 +311,37 @@ check_ts(strict_monotonic_timestamp, PrevTs, Ts) ->
bif_process() ->
receive
- {do_bif, Name, Args} ->
- apply(erlang, Name, Args),
- bif_process();
- {do_time_bif} ->
- %% Match the return value to ensure that the time() call
- %% is not optimized away.
- {_,_,_} = time(),
- bif_process();
- {do_statistics_bif} ->
- statistics(runtime),
- bif_process();
- _Stuff ->
- bif_process()
+ {do_bif, Name, Args} ->
+ apply(erlang, Name, Args),
+ bif_process();
+ {do_time_bif} ->
+ %% Match the return value to ensure that the time() call
+ %% is not optimized away.
+ {_,_,_} = time(),
+ bif_process();
+ {do_statistics_bif} ->
+ statistics(runtime),
+ bif_process();
+ _Stuff ->
+ bif_process()
end.
-
-trace_info_old_code(doc) -> "trace_info on deleted module (OTP-5057).";
+
+%% trace_info on deleted module (OTP-5057).
trace_info_old_code(Config) when is_list(Config) ->
- ?line MFA = {M,F,0} = {test,foo,0},
- ?line Fname = atom_to_list(M)++".erl",
- ?line AbsForms =
- [{attribute,a(1),module,M}, % -module(M).
- {attribute,a(2),export,[{F,0}]}, % -export([F/0]).
- {function,a(3),F,0, % F() ->
- [{clause,a(4),[],[],[{atom,a(4),F}]}]}], % F.
+ MFA = {M,F,0} = {test,foo,0},
+ Fname = atom_to_list(M)++".erl",
+ AbsForms =
+ [{attribute,a(1),module,M}, % -module(M).
+ {attribute,a(2),export,[{F,0}]}, % -export([F/0]).
+ {function,a(3),F,0, % F() ->
+ [{clause,a(4),[],[],[{atom,a(4),F}]}]}], % F.
%%
- ?line {ok,M,Mbin} = compile:forms(AbsForms),
- ?line {module,M} = code:load_binary(M, Fname, Mbin),
- ?line true = erlang:delete_module(M),
- ?line {traced,undefined} = erlang:trace_info(MFA, traced),
+ {ok,M,Mbin} = compile:forms(AbsForms),
+ {module,M} = code:load_binary(M, Fname, Mbin),
+ true = erlang:delete_module(M),
+ {traced,undefined} = erlang:trace_info(MFA, traced),
ok.
a(L) ->
diff --git a/erts/emulator/test/trace_call_count_SUITE.erl b/erts/emulator/test/trace_call_count_SUITE.erl
index c7881bbd70..c849668e84 100644
--- a/erts/emulator/test/trace_call_count_SUITE.erl
+++ b/erts/emulator/test/trace_call_count_SUITE.erl
@@ -43,7 +43,7 @@
-define(config(A,B),config(A,B)).
-export([config/2]).
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-endif.
-ifdef(debug).
@@ -70,18 +70,17 @@ config(priv_dir,_) ->
pause_and_restart/1, combo/1]).
init_per_testcase(_Case, Config) ->
- ?line Dog=test_server:timetrap(test_server:seconds(30)),
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
+end_per_testcase(_Case, _Config) ->
erlang:trace_pattern({'_','_','_'}, false, [local,meta,call_count]),
erlang:trace_pattern(on_load, false, [local,meta,call_count]),
erlang:trace(all, false, [all]),
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 4}}].
all() ->
case test_server:is_native(trace_call_count_SUITE) of
@@ -109,38 +108,23 @@ end_per_group(_GroupName, Config) ->
not_run(Config) when is_list(Config) ->
{skipped,"Native code"}.
-basic(suite) ->
- [];
-basic(doc) ->
- ["Tests basic call count trace"];
+%% Tests basic call count trace
basic(Config) when is_list(Config) ->
basic_test().
-on_and_off(suite) ->
- [];
-on_and_off(doc) ->
- ["Tests turning trace parameters on and off"];
+%% Tests turning trace parameters on and off
on_and_off(Config) when is_list(Config) ->
on_and_off_test().
-info(suite) ->
- [];
-info(doc) ->
- ["Tests the trace_info BIF"];
+%% Tests the trace_info BIF
info(Config) when is_list(Config) ->
info_test().
-pause_and_restart(suite) ->
- [];
-pause_and_restart(doc) ->
- ["Tests pausing and restarting call counters"];
+%% Tests pausing and restarting call counters
pause_and_restart(Config) when is_list(Config) ->
pause_and_restart_test().
-combo(suite) ->
- [];
-combo(doc) ->
- ["Tests combining local call trace and meta trace with call count trace"];
+%% Tests combining local call trace and meta trace with call count trace
combo(Config) when is_list(Config) ->
combo_test().
@@ -161,168 +145,168 @@ combo(Config) when is_list(Config) ->
%%%
basic_test() ->
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_count]),
- ?line M = 1000,
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_count]),
+ M = 1000,
%%
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, true, [call_count]),
- ?line 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, true, [call_count]),
- ?line L = seq(1, M, fun(X) -> X+1 end),
- ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
- ?line {call_count,0} = erlang:trace_info({?MODULE,seq_r,3}, call_count),
- ?line Lr = seq_r(1, M, fun(X) -> X+1 end),
- ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
- ?line {call_count,1} = erlang:trace_info({?MODULE,seq_r,3}, call_count),
- ?line {call_count,M} = erlang:trace_info({?MODULE,seq_r,4}, call_count),
- ?line L = lists:reverse(Lr),
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, true, [call_count]),
+ 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, true, [call_count]),
+ L = seq(1, M, fun(X) -> X+1 end),
+ {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ {call_count,0} = erlang:trace_info({?MODULE,seq_r,3}, call_count),
+ Lr = seq_r(1, M, fun(X) -> X+1 end),
+ {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ {call_count,1} = erlang:trace_info({?MODULE,seq_r,3}, call_count),
+ {call_count,M} = erlang:trace_info({?MODULE,seq_r,4}, call_count),
+ L = lists:reverse(Lr),
%%
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_count]),
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_count]),
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
on_and_off_test() ->
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_count]),
- ?line M = 100,
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_count]),
+ M = 100,
%%
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, true, [call_count]),
- ?line L = seq(1, M, fun(X) -> X+1 end),
- ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
- ?line N = erlang:trace_pattern({?MODULE,'_','_'}, true, [call_count]),
- ?line L = seq(1, M, fun(X) -> X+1 end),
- ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
- ?line P = erlang:trace_pattern({'_','_','_'}, true, [call_count]),
- ?line L = seq(1, M, fun(X) -> X+1 end),
- ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, false, [call_count]),
- ?line {call_count,false} = erlang:trace_info({?MODULE,seq,3}, call_count),
- ?line L = seq(1, M, fun(X) -> X+1 end),
- ?line {call_count,false} = erlang:trace_info({?MODULE,seq,3}, call_count),
- ?line {call_count,0} = erlang:trace_info({?MODULE,seq_r,4}, call_count),
- ?line Lr = seq_r(1, M, fun(X) -> X+1 end),
- ?line {call_count,M} = erlang:trace_info({?MODULE,seq_r,4}, call_count),
- ?line N = erlang:trace_pattern({?MODULE,'_','_'}, false, [call_count]),
- ?line {call_count,false} = erlang:trace_info({?MODULE,seq_r,4}, call_count),
- ?line Lr = seq_r(1, M, fun(X) -> X+1 end),
- ?line {call_count,false} = erlang:trace_info({?MODULE,seq_r,4}, call_count),
- ?line L = lists:reverse(Lr),
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, true, [call_count]),
+ L = seq(1, M, fun(X) -> X+1 end),
+ {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ N = erlang:trace_pattern({?MODULE,'_','_'}, true, [call_count]),
+ L = seq(1, M, fun(X) -> X+1 end),
+ {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ P = erlang:trace_pattern({'_','_','_'}, true, [call_count]),
+ L = seq(1, M, fun(X) -> X+1 end),
+ {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, false, [call_count]),
+ {call_count,false} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ L = seq(1, M, fun(X) -> X+1 end),
+ {call_count,false} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ {call_count,0} = erlang:trace_info({?MODULE,seq_r,4}, call_count),
+ Lr = seq_r(1, M, fun(X) -> X+1 end),
+ {call_count,M} = erlang:trace_info({?MODULE,seq_r,4}, call_count),
+ N = erlang:trace_pattern({?MODULE,'_','_'}, false, [call_count]),
+ {call_count,false} = erlang:trace_info({?MODULE,seq_r,4}, call_count),
+ Lr = seq_r(1, M, fun(X) -> X+1 end),
+ {call_count,false} = erlang:trace_info({?MODULE,seq_r,4}, call_count),
+ L = lists:reverse(Lr),
%%
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_count]),
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_count]),
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
info_test() ->
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_count]),
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_count]),
%%
- ?line 1 = erlang:trace_pattern({?MODULE,seq,3}, true, [call_count]),
- ?line {call_count,0} = erlang:trace_info({?MODULE,seq,3}, call_count),
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, pause, [call_count]),
- ?line {call_count,0} = erlang:trace_info({?MODULE,seq,3}, call_count),
- ?line {all,[_|_]=L} = erlang:trace_info({?MODULE,seq,3}, all),
- ?line {value,{call_count,0}} = lists:keysearch(call_count, 1, L),
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, restart, [call_count]),
- ?line {call_count,0} = erlang:trace_info({?MODULE,seq,3}, call_count),
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, false, [call_count]),
- ?line {call_count,false} = erlang:trace_info({?MODULE,seq,3}, call_count),
- ?line {all,false} = erlang:trace_info({?MODULE,seq,3}, all),
+ 1 = erlang:trace_pattern({?MODULE,seq,3}, true, [call_count]),
+ {call_count,0} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, pause, [call_count]),
+ {call_count,0} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ {all,[_|_]=L} = erlang:trace_info({?MODULE,seq,3}, all),
+ {value,{call_count,0}} = lists:keysearch(call_count, 1, L),
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, restart, [call_count]),
+ {call_count,0} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, false, [call_count]),
+ {call_count,false} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ {all,false} = erlang:trace_info({?MODULE,seq,3}, all),
%%
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_count]),
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_count]),
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pause_and_restart_test() ->
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_count]),
- ?line M = 100,
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_count]),
+ M = 100,
%%
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, true, [call_count]),
- ?line {call_count,0} = erlang:trace_info({?MODULE,seq,3}, call_count),
- ?line L = seq(1, M, fun(X) -> X+1 end),
- ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, pause, [call_count]),
- ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
- ?line L = seq(1, M, fun(X) -> X+1 end),
- ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, restart, [call_count]),
- ?line {call_count,0} = erlang:trace_info({?MODULE,seq,3}, call_count),
- ?line L = seq(1, M, fun(X) -> X+1 end),
- ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, true, [call_count]),
+ {call_count,0} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ L = seq(1, M, fun(X) -> X+1 end),
+ {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, pause, [call_count]),
+ {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ L = seq(1, M, fun(X) -> X+1 end),
+ {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, restart, [call_count]),
+ {call_count,0} = erlang:trace_info({?MODULE,seq,3}, call_count),
+ L = seq(1, M, fun(X) -> X+1 end),
+ {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count),
%%
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_count]),
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_count]),
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
combo_test() ->
- ?line Self = self(),
-
- ?line MetaMatchSpec = [{'_',[],[{return_trace}]}],
- ?line Flags = lists:sort([call, return_to]),
- ?line LocalTracer = spawn_link(fun () -> relay_n(5, Self) end),
- ?line MetaTracer = spawn_link(fun () -> relay_n(9, Self) end),
- ?line 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, [], [local]),
- ?line 2 = erlang:trace_pattern({?MODULE,seq_r,'_'},
- MetaMatchSpec,
- [{meta,MetaTracer}, call_count]),
- ?line 1 = erlang:trace(Self, true, [{tracer,LocalTracer} | Flags]),
+ Self = self(),
+
+ MetaMatchSpec = [{'_',[],[{return_trace}]}],
+ Flags = lists:sort([call, return_to]),
+ LocalTracer = spawn_link(fun () -> relay_n(5, Self) end),
+ MetaTracer = spawn_link(fun () -> relay_n(9, Self) end),
+ 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, [], [local]),
+ 2 = erlang:trace_pattern({?MODULE,seq_r,'_'},
+ MetaMatchSpec,
+ [{meta,MetaTracer}, call_count]),
+ 1 = erlang:trace(Self, true, [{tracer,LocalTracer} | Flags]),
%%
- ?line {traced,local} =
- erlang:trace_info({?MODULE,seq_r,3}, traced),
- ?line {match_spec,[]} =
- erlang:trace_info({?MODULE,seq_r,3}, match_spec),
- ?line {meta,MetaTracer} =
- erlang:trace_info({?MODULE,seq_r,3}, meta),
- ?line {meta_match_spec,MetaMatchSpec} =
- erlang:trace_info({?MODULE,seq_r,3}, meta_match_spec),
- ?line {call_count,0} =
- erlang:trace_info({?MODULE,seq_r,3}, call_count),
+ {traced,local} =
+ erlang:trace_info({?MODULE,seq_r,3}, traced),
+ {match_spec,[]} =
+ erlang:trace_info({?MODULE,seq_r,3}, match_spec),
+ {meta,MetaTracer} =
+ erlang:trace_info({?MODULE,seq_r,3}, meta),
+ {meta_match_spec,MetaMatchSpec} =
+ erlang:trace_info({?MODULE,seq_r,3}, meta_match_spec),
+ {call_count,0} =
+ erlang:trace_info({?MODULE,seq_r,3}, call_count),
%%
- ?line {all,[_|_]=TraceInfo} =
- erlang:trace_info({?MODULE,seq_r,3}, all),
- ?line {value,{traced,local}} =
- lists:keysearch(traced, 1, TraceInfo),
- ?line {value,{match_spec,[]}} =
- lists:keysearch(match_spec, 1, TraceInfo),
- ?line {value,{meta,MetaTracer}} =
- lists:keysearch(meta, 1, TraceInfo),
- ?line {value,{meta_match_spec,MetaMatchSpec}} =
- lists:keysearch(meta_match_spec, 1, TraceInfo),
- ?line {value,{call_count,0}} =
- lists:keysearch(call_count, 1, TraceInfo),
+ {all,[_|_]=TraceInfo} =
+ erlang:trace_info({?MODULE,seq_r,3}, all),
+ {value,{traced,local}} =
+ lists:keysearch(traced, 1, TraceInfo),
+ {value,{match_spec,[]}} =
+ lists:keysearch(match_spec, 1, TraceInfo),
+ {value,{meta,MetaTracer}} =
+ lists:keysearch(meta, 1, TraceInfo),
+ {value,{meta_match_spec,MetaMatchSpec}} =
+ lists:keysearch(meta_match_spec, 1, TraceInfo),
+ {value,{call_count,0}} =
+ lists:keysearch(call_count, 1, TraceInfo),
%%
- ?line [3,2,1] = seq_r(1, 3, fun(X) -> X+1 end),
+ [3,2,1] = seq_r(1, 3, fun(X) -> X+1 end),
%%
- ?line List = collect(100),
- ?line {MetaR, LocalR} =
- lists:foldl(
- fun ({P,X}, {M,L}) when P == MetaTracer ->
- {[X|M],L};
- ({P,X}, {M,L}) when P == LocalTracer ->
- {M,[X|L]}
- end,
- {[],[]},
- List),
- ?line Meta = lists:reverse(MetaR),
- ?line Local = lists:reverse(LocalR),
- ?line [?CTT(Self,{?MODULE,seq_r,[1,3,_]}),
- ?CTT(Self,{?MODULE,seq_r,[1,3,_,[]]}),
- ?CTT(Self,{?MODULE,seq_r,[2,3,_,[1]]}),
- ?CTT(Self,{?MODULE,seq_r,[3,3,_,[2,1]]}),
- ?RFT(Self,{?MODULE,seq_r,4},[3,2,1]),
- ?RFT(Self,{?MODULE,seq_r,4},[3,2,1]),
- ?RFT(Self,{?MODULE,seq_r,4},[3,2,1]),
- ?RFT(Self,{?MODULE,seq_r,3},[3,2,1])] = Meta,
- ?line [?CT(Self,{?MODULE,seq_r,[1,3,_]}),
- ?CT(Self,{?MODULE,seq_r,[1,3,_,[]]}),
- ?CT(Self,{?MODULE,seq_r,[2,3,_,[1]]}),
- ?CT(Self,{?MODULE,seq_r,[3,3,_,[2,1]]}),
- ?RT(Self,{?MODULE,combo_test,0})] = Local,
- ?line {call_count,1} = erlang:trace_info({?MODULE,seq_r,3}, call_count),
- ?line {call_count,3} = erlang:trace_info({?MODULE,seq_r,4}, call_count),
+ List = collect(100),
+ {MetaR, LocalR} =
+ lists:foldl(
+ fun ({P,X}, {M,L}) when P == MetaTracer ->
+ {[X|M],L};
+ ({P,X}, {M,L}) when P == LocalTracer ->
+ {M,[X|L]}
+ end,
+ {[],[]},
+ List),
+ Meta = lists:reverse(MetaR),
+ Local = lists:reverse(LocalR),
+ [?CTT(Self,{?MODULE,seq_r,[1,3,_]}),
+ ?CTT(Self,{?MODULE,seq_r,[1,3,_,[]]}),
+ ?CTT(Self,{?MODULE,seq_r,[2,3,_,[1]]}),
+ ?CTT(Self,{?MODULE,seq_r,[3,3,_,[2,1]]}),
+ ?RFT(Self,{?MODULE,seq_r,4},[3,2,1]),
+ ?RFT(Self,{?MODULE,seq_r,4},[3,2,1]),
+ ?RFT(Self,{?MODULE,seq_r,4},[3,2,1]),
+ ?RFT(Self,{?MODULE,seq_r,3},[3,2,1])] = Meta,
+ [?CT(Self,{?MODULE,seq_r,[1,3,_]}),
+ ?CT(Self,{?MODULE,seq_r,[1,3,_,[]]}),
+ ?CT(Self,{?MODULE,seq_r,[2,3,_,[1]]}),
+ ?CT(Self,{?MODULE,seq_r,[3,3,_,[2,1]]}),
+ ?RT(Self,{?MODULE,combo_test,0})] = Local,
+ {call_count,1} = erlang:trace_info({?MODULE,seq_r,3}, call_count),
+ {call_count,3} = erlang:trace_info({?MODULE,seq_r,4}, call_count),
%%
- ?line erlang:trace_pattern({'_','_','_'}, false, [local,meta,call_count]),
- ?line erlang:trace_pattern(on_load, false, [local,meta,call_count]),
- ?line erlang:trace(all, false, [all]),
+ erlang:trace_pattern({'_','_','_'}, false, [local,meta,call_count]),
+ erlang:trace_pattern(on_load, false, [local,meta,call_count]),
+ erlang:trace(all, false, [all]),
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -352,8 +336,8 @@ relay_n(0, _) ->
ok;
relay_n(N, Dest) ->
receive Msg ->
- Dest ! {self(), Msg},
- relay_n(N-1, Dest)
+ Dest ! {self(), Msg},
+ relay_n(N-1, Dest)
end.
@@ -367,15 +351,15 @@ collect(Time) ->
collect(A, 0) ->
receive
- Mess ->
- collect([Mess | A], 0)
+ Mess ->
+ collect([Mess | A], 0)
after 0 ->
- A
+ A
end;
collect(A, Ref) ->
receive
- {timeout, Ref, done} ->
- collect(A, 0);
- Mess ->
- collect([Mess | A], Ref)
+ {timeout, Ref, done} ->
+ collect(A, 0);
+ Mess ->
+ collect([Mess | A], Ref)
end.
diff --git a/erts/emulator/test/trace_call_time_SUITE.erl b/erts/emulator/test/trace_call_time_SUITE.erl
index f359e1bd80..38972c9c02 100644
--- a/erts/emulator/test/trace_call_time_SUITE.erl
+++ b/erts/emulator/test/trace_call_time_SUITE.erl
@@ -58,32 +58,30 @@
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% When run in test server.
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
+-export([all/0, suite/0,
init_per_testcase/2, end_per_testcase/2, not_run/1]).
-export([basic/1, on_and_off/1, info/1,
pause_and_restart/1, scheduling/1, called_function/1, combo/1,
bif/1, nif/1]).
init_per_testcase(_Case, Config) ->
- ?line Dog=test_server:timetrap(test_server:seconds(400)),
erlang:trace_pattern({'_','_','_'}, false, [local,meta,call_time,call_count]),
erlang:trace_pattern(on_load, false, [local,meta,call_time,call_count]),
timer:now_diff(now(),now()),
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
+end_per_testcase(_Case, _Config) ->
erlang:trace_pattern({'_','_','_'}, false, [local,meta,call_time,call_count]),
erlang:trace_pattern(on_load, false, [local,meta,call_time,call_count]),
erlang:trace(all, false, [all]),
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 10}}].
all() ->
case test_server:is_native(trace_call_time_SUITE) of
@@ -93,382 +91,339 @@ all() ->
combo, bif, nif, called_function, dead_tracer]
end.
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
not_run(Config) when is_list(Config) ->
{skipped,"Native code"}.
-basic(suite) ->
- [];
-basic(doc) ->
- ["Tests basic call count trace"];
+%% Tests basic call time trace
basic(Config) when is_list(Config) ->
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
- ?line M = 1000,
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
+ M = 1000,
%%
- ?line 1 = erlang:trace_pattern({?MODULE,seq, '_'}, true, [call_time]),
- ?line 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, true, [call_time]),
- ?line Pid = setup(),
- ?line {L, T1} = execute(Pid, fun() -> seq(1, M, fun(X) -> (X+1) end) end),
- ?line ok = check_trace_info({?MODULE, seq, 3}, [{Pid, M, 0, 0}], T1),
- ?line ok = check_trace_info({?MODULE, seq_r, 3}, [], none),
-
- ?line {Lr, T2} = execute(Pid, fun() -> seq_r(1, M, fun(X) -> (X+1) end) end),
- ?line ok = check_trace_info({?MODULE, seq, 3}, [{Pid, M, 0, 0}], T1),
- ?line ok = check_trace_info({?MODULE, seq_r, 3}, [{Pid, 1, 0, 0}], T2/M),
- ?line ok = check_trace_info({?MODULE, seq_r, 4}, [{Pid, M, 0, 0}], T2),
- ?line L = lists:reverse(Lr),
+ 1 = erlang:trace_pattern({?MODULE,seq, '_'}, true, [call_time]),
+ 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, true, [call_time]),
+ Pid = setup(),
+ {L, T1} = execute(Pid, fun() -> seq(1, M, fun(X) -> (X+1) end) end),
+ ok = check_trace_info({?MODULE, seq, 3}, [{Pid, M, 0, 0}], T1),
+ ok = check_trace_info({?MODULE, seq_r, 3}, [], none),
+
+ {Lr, T2} = execute(Pid, fun() -> seq_r(1, M, fun(X) -> (X+1) end) end),
+ ok = check_trace_info({?MODULE, seq, 3}, [{Pid, M, 0, 0}], T1),
+ ok = check_trace_info({?MODULE, seq_r, 3}, [{Pid, 1, 0, 0}], T2/M),
+ ok = check_trace_info({?MODULE, seq_r, 4}, [{Pid, M, 0, 0}], T2),
+ L = lists:reverse(Lr),
%%
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
- ?line Pid ! quit,
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
+ Pid ! quit,
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-on_and_off(suite) ->
- [];
-on_and_off(doc) ->
- ["Tests turning trace parameters on and off"];
+%% "Tests turning trace parameters on and off
on_and_off(Config) when is_list(Config) ->
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
- ?line M = 100,
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
+ M = 100,
%%
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, true, [call_time]),
- ?line Pid = setup(),
- ?line {L, T1} = execute(Pid, {?MODULE, seq, [1, M, fun(X) -> X+1 end]}),
- ?line ok = check_trace_info({?MODULE, seq, 3}, [{Pid, M, 0, 0}], T1),
-
- ?line N = erlang:trace_pattern({?MODULE,'_','_'}, true, [call_time]),
- ?line {L, T2} = execute(Pid, fun() -> seq(1, M, fun(X) -> X+1 end) end),
- ?line ok = check_trace_info({?MODULE, seq, 3}, [{Pid, M, 0, 0}], T2),
-
- ?line P = erlang:trace_pattern({'_','_','_'}, true, [call_time]),
- ?line {L, T3} = execute(Pid, fun() -> seq(1, M, fun(X) -> X+1 end) end),
- ?line ok = check_trace_info({?MODULE, seq, 3}, [{Pid, M, 0, 0}], T3),
-
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, false, [call_time]),
- ?line ok = check_trace_info({?MODULE, seq, 3}, false, none),
- ?line {L, _T4} = execute(Pid, fun() -> seq(1, M, fun(X) -> X+1 end) end),
- ?line ok = check_trace_info({?MODULE, seq, 3}, false, none),
- ?line ok = check_trace_info({?MODULE, seq_r, 4}, [], none),
- ?line {Lr, T5} = execute(Pid, fun() -> seq_r(1, M, fun(X) -> X+1 end) end),
- ?line ok = check_trace_info({?MODULE, seq_r, 4}, [{Pid,M,0,0}], T5),
-
- ?line N = erlang:trace_pattern({?MODULE,'_','_'}, false, [call_time]),
- ?line ok = check_trace_info({?MODULE, seq_r, 4}, false, none),
- ?line {Lr, _T6} = execute(Pid, fun() -> seq_r(1, M, fun(X) -> X+1 end) end),
- ?line ok = check_trace_info({?MODULE, seq_r, 4}, false, none),
- ?line L = lists:reverse(Lr),
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, true, [call_time]),
+ Pid = setup(),
+ {L, T1} = execute(Pid, {?MODULE, seq, [1, M, fun(X) -> X+1 end]}),
+ ok = check_trace_info({?MODULE, seq, 3}, [{Pid, M, 0, 0}], T1),
+
+ N = erlang:trace_pattern({?MODULE,'_','_'}, true, [call_time]),
+ {L, T2} = execute(Pid, fun() -> seq(1, M, fun(X) -> X+1 end) end),
+ ok = check_trace_info({?MODULE, seq, 3}, [{Pid, M, 0, 0}], T2),
+
+ P = erlang:trace_pattern({'_','_','_'}, true, [call_time]),
+ {L, T3} = execute(Pid, fun() -> seq(1, M, fun(X) -> X+1 end) end),
+ ok = check_trace_info({?MODULE, seq, 3}, [{Pid, M, 0, 0}], T3),
+
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, false, [call_time]),
+ ok = check_trace_info({?MODULE, seq, 3}, false, none),
+ {L, _T4} = execute(Pid, fun() -> seq(1, M, fun(X) -> X+1 end) end),
+ ok = check_trace_info({?MODULE, seq, 3}, false, none),
+ ok = check_trace_info({?MODULE, seq_r, 4}, [], none),
+ {Lr, T5} = execute(Pid, fun() -> seq_r(1, M, fun(X) -> X+1 end) end),
+ ok = check_trace_info({?MODULE, seq_r, 4}, [{Pid,M,0,0}], T5),
+
+ N = erlang:trace_pattern({?MODULE,'_','_'}, false, [call_time]),
+ ok = check_trace_info({?MODULE, seq_r, 4}, false, none),
+ {Lr, _T6} = execute(Pid, fun() -> seq_r(1, M, fun(X) -> X+1 end) end),
+ ok = check_trace_info({?MODULE, seq_r, 4}, false, none),
+ L = lists:reverse(Lr),
%%
- ?line Pid ! quit,
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
+ Pid ! quit,
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-info(suite) ->
- [];
-info(doc) ->
- ["Tests the trace_info BIF"];
+%% Tests the trace_info BIF
info(Config) when is_list(Config) ->
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
%%
- ?line 1 = erlang:trace_pattern({?MODULE,seq,3}, true, [call_time]),
- ?line {call_time,[]} = erlang:trace_info({?MODULE,seq,3}, call_time),
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, pause, [call_time]),
- ?line {call_time,[]} = erlang:trace_info({?MODULE,seq,3}, call_time),
- ?line {all,[_|_]=L} = erlang:trace_info({?MODULE,seq,3}, all),
- ?line {value,{call_time,[]}} = lists:keysearch(call_time, 1, L),
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, restart, [call_time]),
- ?line {call_time,[]} = erlang:trace_info({?MODULE,seq,3}, call_time),
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, false, [call_time]),
- ?line {call_time,false} = erlang:trace_info({?MODULE,seq,3}, call_time),
- ?line {all,false} = erlang:trace_info({?MODULE,seq,3}, all),
+ 1 = erlang:trace_pattern({?MODULE,seq,3}, true, [call_time]),
+ {call_time,[]} = erlang:trace_info({?MODULE,seq,3}, call_time),
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, pause, [call_time]),
+ {call_time,[]} = erlang:trace_info({?MODULE,seq,3}, call_time),
+ {all,[_|_]=L} = erlang:trace_info({?MODULE,seq,3}, all),
+ {value,{call_time,[]}} = lists:keysearch(call_time, 1, L),
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, restart, [call_time]),
+ {call_time,[]} = erlang:trace_info({?MODULE,seq,3}, call_time),
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, false, [call_time]),
+ {call_time,false} = erlang:trace_info({?MODULE,seq,3}, call_time),
+ {all,false} = erlang:trace_info({?MODULE,seq,3}, all),
%%
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-pause_and_restart(suite) ->
- [];
-pause_and_restart(doc) ->
- ["Tests pausing and restarting call time counters"];
+%% Tests pausing and restarting call time counters
pause_and_restart(Config) when is_list(Config) ->
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
- ?line M = 100,
- ?line Pid = setup(),
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
+ M = 100,
+ Pid = setup(),
%%
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, true, [call_time]),
- ?line ok = check_trace_info({?MODULE, seq, 3}, [], none),
- ?line {L, T1} = execute(Pid, fun() -> seq(1, M, fun(X) -> X+1 end) end),
- ?line ok = check_trace_info({?MODULE, seq, 3}, [{Pid,M,0,0}], T1),
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, pause, [call_time]),
- ?line ok = check_trace_info({?MODULE, seq, 3}, [{Pid,M,0,0}], T1),
- ?line {L, T2} = execute(Pid, fun() -> seq(1, M, fun(X) -> X+1 end) end),
- ?line ok = check_trace_info({?MODULE, seq, 3}, [{Pid,M,0,0}], T2),
- ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, restart, [call_time]),
- ?line ok = check_trace_info({?MODULE, seq, 3}, [], none),
- ?line {L, T3} = execute(Pid, fun() -> seq(1, M, fun(X) -> X+1 end) end),
- ?line ok = check_trace_info({?MODULE, seq, 3}, [{Pid,M,0,0}], T3),
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, true, [call_time]),
+ ok = check_trace_info({?MODULE, seq, 3}, [], none),
+ {L, T1} = execute(Pid, fun() -> seq(1, M, fun(X) -> X+1 end) end),
+ ok = check_trace_info({?MODULE, seq, 3}, [{Pid,M,0,0}], T1),
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, pause, [call_time]),
+ ok = check_trace_info({?MODULE, seq, 3}, [{Pid,M,0,0}], T1),
+ {L, T2} = execute(Pid, fun() -> seq(1, M, fun(X) -> X+1 end) end),
+ ok = check_trace_info({?MODULE, seq, 3}, [{Pid,M,0,0}], T2),
+ 1 = erlang:trace_pattern({?MODULE,seq,'_'}, restart, [call_time]),
+ ok = check_trace_info({?MODULE, seq, 3}, [], none),
+ {L, T3} = execute(Pid, fun() -> seq(1, M, fun(X) -> X+1 end) end),
+ ok = check_trace_info({?MODULE, seq, 3}, [{Pid,M,0,0}], T3),
%%
- ?line Pid ! quit,
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
+ Pid ! quit,
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-scheduling(suite) ->
- [];
-scheduling(doc) ->
- ["Tests in/out scheduling of call time counters"];
+%% Tests in/out scheduling of call time counters
scheduling(Config) when is_list(Config) ->
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
- ?line M = 1000000,
- ?line Np = erlang:system_info(schedulers_online),
- ?line F = 12,
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
+ M = 1000000,
+ Np = erlang:system_info(schedulers_online),
+ F = 12,
%% setup load processes
%% (single, no internal calls)
- ?line erlang:trace_pattern({?MODULE,loaded,1}, true, [call_time]),
+ erlang:trace_pattern({?MODULE,loaded,1}, true, [call_time]),
- ?line Pids = [setup() || _ <- lists:seq(1, F*Np)],
- ?line {_Ls,T1} = execute(Pids, {?MODULE,loaded,[M]}),
- ?line [Pid ! quit || Pid <- Pids],
+ Pids = [setup() || _ <- lists:seq(1, F*Np)],
+ {_Ls,T1} = execute(Pids, {?MODULE,loaded,[M]}),
+ [Pid ! quit || Pid <- Pids],
%% logic dictates that each process will get ~ 1/F of the schedulers time
- ?line {call_time, CT} = erlang:trace_info({?MODULE,loaded,1}, call_time),
-
- ?line lists:foreach(fun (Pid) ->
- ?line ok = case check_process_time(lists:keysearch(Pid, 1, CT), M, F, T1) of
- schedule_time_error ->
- test_server:comment("Warning: Failed time ratio"),
- ok;
- Other -> Other
- end
- end, Pids),
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
+ {call_time, CT} = erlang:trace_info({?MODULE,loaded,1}, call_time),
+
+ lists:foreach(fun (Pid) ->
+ ok = case check_process_time(lists:keysearch(Pid, 1, CT), M, F, T1) of
+ schedule_time_error ->
+ test_server:comment("Warning: Failed time ratio"),
+ ok;
+ Other -> Other
+ end
+ end, Pids),
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-combo(suite) ->
- [];
-combo(doc) ->
- ["Tests combining local call trace and meta trace with call time trace"];
+%% "Tests combining local call trace and meta trace with call time trace
combo(Config) when is_list(Config) ->
- ?line Self = self(),
- ?line Nbc = 3,
- ?line MetaMs = [{'_',[],[{return_trace}]}],
- ?line Flags = lists:sort([call, return_to]),
- ?line LocalTracer = spawn_link(fun () -> relay_n(5 + Nbc + 3, Self) end),
- ?line MetaTracer = spawn_link(fun () -> relay_n(9 + Nbc + 3, Self) end),
- ?line 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, [], [local]),
- ?line 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, true, [call_time]),
- ?line 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, MetaMs, [{meta,MetaTracer}]),
- ?line 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, true, [call_count]),
+ Self = self(),
+ Nbc = 3,
+ MetaMs = [{'_',[],[{return_trace}]}],
+ Flags = lists:sort([call, return_to]),
+ LocalTracer = spawn_link(fun () -> relay_n(5 + Nbc + 3, Self) end),
+ MetaTracer = spawn_link(fun () -> relay_n(9 + Nbc + 3, Self) end),
+ 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, [], [local]),
+ 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, true, [call_time]),
+ 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, MetaMs, [{meta,MetaTracer}]),
+ 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, true, [call_count]),
% bifs
- ?line 2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, [], [local]),
- ?line 2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, true, [call_time]),
- ?line 2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, MetaMs, [{meta,MetaTracer}]),
+ 2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, [], [local]),
+ 2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, true, [call_time]),
+ 2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, MetaMs, [{meta,MetaTracer}]),
%% not implemented
- %?line 2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, true, [call_count]),
+ %2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, true, [call_count]),
- ?line 1 = erlang:trace(Self, true, [{tracer,LocalTracer} | Flags]),
+ 1 = erlang:trace(Self, true, [{tracer,LocalTracer} | Flags]),
%%
- ?line {traced,local} =
- erlang:trace_info({?MODULE,seq_r,3}, traced),
- ?line {match_spec,[]} =
- erlang:trace_info({?MODULE,seq_r,3}, match_spec),
- ?line {meta,MetaTracer} =
- erlang:trace_info({?MODULE,seq_r,3}, meta),
- ?line {meta_match_spec,MetaMs} =
- erlang:trace_info({?MODULE,seq_r,3}, meta_match_spec),
- ?line ok = check_trace_info({?MODULE, seq_r, 3}, [], none),
+ {traced,local} =
+ erlang:trace_info({?MODULE,seq_r,3}, traced),
+ {match_spec,[]} =
+ erlang:trace_info({?MODULE,seq_r,3}, match_spec),
+ {meta,MetaTracer} =
+ erlang:trace_info({?MODULE,seq_r,3}, meta),
+ {meta_match_spec,MetaMs} =
+ erlang:trace_info({?MODULE,seq_r,3}, meta_match_spec),
+ ok = check_trace_info({?MODULE, seq_r, 3}, [], none),
%% check empty trace_info for ?MODULE:seq_r/3
- ?line {all,[_|_]=TraceInfo} = erlang:trace_info({?MODULE,seq_r,3}, all),
- ?line {value,{traced,local}} = lists:keysearch(traced, 1, TraceInfo),
- ?line {value,{match_spec,[]}} = lists:keysearch(match_spec, 1, TraceInfo),
- ?line {value,{meta,MetaTracer}} = lists:keysearch(meta, 1, TraceInfo),
- ?line {value,{meta_match_spec,MetaMs}} = lists:keysearch(meta_match_spec, 1, TraceInfo),
- ?line {value,{call_count,0}} = lists:keysearch(call_count, 1, TraceInfo),
- ?line {value,{call_time,[]}} = lists:keysearch(call_time, 1, TraceInfo),
+ {all,[_|_]=TraceInfo} = erlang:trace_info({?MODULE,seq_r,3}, all),
+ {value,{traced,local}} = lists:keysearch(traced, 1, TraceInfo),
+ {value,{match_spec,[]}} = lists:keysearch(match_spec, 1, TraceInfo),
+ {value,{meta,MetaTracer}} = lists:keysearch(meta, 1, TraceInfo),
+ {value,{meta_match_spec,MetaMs}} = lists:keysearch(meta_match_spec, 1, TraceInfo),
+ {value,{call_count,0}} = lists:keysearch(call_count, 1, TraceInfo),
+ {value,{call_time,[]}} = lists:keysearch(call_time, 1, TraceInfo),
%% check empty trace_info for erlang:term_to_binary/1
- ?line {all, [_|_] = TraceInfoBif} = erlang:trace_info({erlang, term_to_binary, 1}, all),
- ?line {value,{traced,local}} = lists:keysearch(traced, 1, TraceInfoBif),
- ?line {value,{match_spec,[]}} = lists:keysearch(match_spec, 1, TraceInfoBif),
- ?line {value,{meta, MetaTracer}} = lists:keysearch(meta, 1, TraceInfoBif),
- ?line {value,{meta_match_spec,MetaMs}} = lists:keysearch(meta_match_spec, 1, TraceInfoBif),
+ {all, [_|_] = TraceInfoBif} = erlang:trace_info({erlang, term_to_binary, 1}, all),
+ {value,{traced,local}} = lists:keysearch(traced, 1, TraceInfoBif),
+ {value,{match_spec,[]}} = lists:keysearch(match_spec, 1, TraceInfoBif),
+ {value,{meta, MetaTracer}} = lists:keysearch(meta, 1, TraceInfoBif),
+ {value,{meta_match_spec,MetaMs}} = lists:keysearch(meta_match_spec, 1, TraceInfoBif),
%% not implemented
- ?line {value,{call_count,false}} = lists:keysearch(call_count, 1, TraceInfoBif),
- %?line {value,{call_count,0}} = lists:keysearch(call_count, 1, TraceInfoBif),
- ?line {value,{call_time,[]}} = lists:keysearch(call_time, 1, TraceInfoBif),
+ {value,{call_count,false}} = lists:keysearch(call_count, 1, TraceInfoBif),
+ %{value,{call_count,0}} = lists:keysearch(call_count, 1, TraceInfoBif),
+ {value,{call_time,[]}} = lists:keysearch(call_time, 1, TraceInfoBif),
%%
- ?line [3,2,1] = seq_r(1, 3, fun(X) -> X+1 end),
- ?line T0 = erlang:monotonic_time(),
- ?line with_bif(Nbc),
- ?line T1 = erlang:monotonic_time(),
- ?line TimeB = erlang:convert_time_unit(T1-T0, native, micro_seconds),
+ [3,2,1] = seq_r(1, 3, fun(X) -> X+1 end),
+ T0 = erlang:monotonic_time(),
+ with_bif(Nbc),
+ T1 = erlang:monotonic_time(),
+ TimeB = erlang:convert_time_unit(T1-T0, native, micro_seconds),
%%
- ?line List = collect(100),
- ?line {MetaR, LocalR} =
- lists:foldl(
- fun ({P,X}, {M,L}) when P == MetaTracer ->
- {[X|M],L};
- ({P,X}, {M,L}) when P == LocalTracer ->
- {M,[X|L]}
- end,
- {[],[]},
- List),
- ?line Meta = lists:reverse(MetaR),
- ?line Local = lists:reverse(LocalR),
-
- ?line [?CTT(Self,{?MODULE,seq_r,[1,3,_]}),
- ?CTT(Self,{?MODULE,seq_r,[1,3,_,[]]}),
- ?CTT(Self,{?MODULE,seq_r,[2,3,_,[1]]}),
- ?CTT(Self,{?MODULE,seq_r,[3,3,_,[2,1]]}),
- ?RFT(Self,{?MODULE,seq_r,4},[3,2,1]),
- ?RFT(Self,{?MODULE,seq_r,4},[3,2,1]),
- ?RFT(Self,{?MODULE,seq_r,4},[3,2,1]),
- ?RFT(Self,{?MODULE,seq_r,3},[3,2,1]),
- ?CTT(Self,{erlang,term_to_binary,[3]}), % bif
- ?RFT(Self,{erlang,term_to_binary,1},<<131,97,3>>),
- ?CTT(Self,{erlang,term_to_binary,[2]}),
- ?RFT(Self,{erlang,term_to_binary,1},<<131,97,2>>)
- ] = Meta,
-
- ?line [?CT(Self,{?MODULE,seq_r,[1,3,_]}),
- ?CT(Self,{?MODULE,seq_r,[1,3,_,[]]}),
- ?CT(Self,{?MODULE,seq_r,[2,3,_,[1]]}),
- ?CT(Self,{?MODULE,seq_r,[3,3,_,[2,1]]}),
- ?RT(Self,{?MODULE,combo,1}),
- ?CT(Self,{erlang,term_to_binary,[3]}), % bif
- ?RT(Self,{?MODULE,with_bif,1}),
- ?CT(Self,{erlang,term_to_binary,[2]}),
- ?RT(Self,{?MODULE,with_bif,1})
- ] = Local,
-
- ?line ok = check_trace_info({?MODULE, seq_r, 3}, [{Self,1,0,0}], 1),
- ?line ok = check_trace_info({?MODULE, seq_r, 4}, [{Self,3,0,0}], 1),
- ?line ok = check_trace_info({?MODULE, seq_r, 3}, [{Self,1,0,0}], 1),
- ?line ok = check_trace_info({?MODULE, seq_r, 4}, [{Self,3,0,0}], 1),
- ?line ok = check_trace_info({erlang, term_to_binary, 1}, [{self(), Nbc - 1, 0, 0}], TimeB),
+ List = collect(100),
+ {MetaR, LocalR} =
+ lists:foldl(
+ fun ({P,X}, {M,L}) when P == MetaTracer ->
+ {[X|M],L};
+ ({P,X}, {M,L}) when P == LocalTracer ->
+ {M,[X|L]}
+ end,
+ {[],[]},
+ List),
+ Meta = lists:reverse(MetaR),
+ Local = lists:reverse(LocalR),
+
+ [?CTT(Self,{?MODULE,seq_r,[1,3,_]}),
+ ?CTT(Self,{?MODULE,seq_r,[1,3,_,[]]}),
+ ?CTT(Self,{?MODULE,seq_r,[2,3,_,[1]]}),
+ ?CTT(Self,{?MODULE,seq_r,[3,3,_,[2,1]]}),
+ ?RFT(Self,{?MODULE,seq_r,4},[3,2,1]),
+ ?RFT(Self,{?MODULE,seq_r,4},[3,2,1]),
+ ?RFT(Self,{?MODULE,seq_r,4},[3,2,1]),
+ ?RFT(Self,{?MODULE,seq_r,3},[3,2,1]),
+ ?CTT(Self,{erlang,term_to_binary,[3]}), % bif
+ ?RFT(Self,{erlang,term_to_binary,1},<<131,97,3>>),
+ ?CTT(Self,{erlang,term_to_binary,[2]}),
+ ?RFT(Self,{erlang,term_to_binary,1},<<131,97,2>>)
+ ] = Meta,
+
+ [?CT(Self,{?MODULE,seq_r,[1,3,_]}),
+ ?CT(Self,{?MODULE,seq_r,[1,3,_,[]]}),
+ ?CT(Self,{?MODULE,seq_r,[2,3,_,[1]]}),
+ ?CT(Self,{?MODULE,seq_r,[3,3,_,[2,1]]}),
+ ?RT(Self,{?MODULE,combo,1}),
+ ?CT(Self,{erlang,term_to_binary,[3]}), % bif
+ ?RT(Self,{?MODULE,with_bif,1}),
+ ?CT(Self,{erlang,term_to_binary,[2]}),
+ ?RT(Self,{?MODULE,with_bif,1})
+ ] = Local,
+
+ ok = check_trace_info({?MODULE, seq_r, 3}, [{Self,1,0,0}], 1),
+ ok = check_trace_info({?MODULE, seq_r, 4}, [{Self,3,0,0}], 1),
+ ok = check_trace_info({?MODULE, seq_r, 3}, [{Self,1,0,0}], 1),
+ ok = check_trace_info({?MODULE, seq_r, 4}, [{Self,3,0,0}], 1),
+ ok = check_trace_info({erlang, term_to_binary, 1}, [{self(), Nbc - 1, 0, 0}], TimeB),
%%
- ?line erlang:trace_pattern({'_','_','_'}, false, [local,meta,call_time]),
- ?line erlang:trace_pattern(on_load, false, [local,meta,call_time]),
- ?line erlang:trace(all, false, [all]),
+ erlang:trace_pattern({'_','_','_'}, false, [local,meta,call_time]),
+ erlang:trace_pattern(on_load, false, [local,meta,call_time]),
+ erlang:trace(all, false, [all]),
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-bif(suite) ->
- [];
-bif(doc) ->
- ["Tests tracing of bifs"];
+%% Tests tracing of bifs
bif(Config) when is_list(Config) ->
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
- ?line M = 1000000,
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
+ M = 1000000,
%%
- ?line 2 = erlang:trace_pattern({erlang, binary_to_term, '_'}, true, [call_time]),
- ?line 2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, true, [call_time]),
- ?line Pid = setup(),
- ?line {L, T1} = execute(Pid, fun() -> with_bif(M) end),
+ 2 = erlang:trace_pattern({erlang, binary_to_term, '_'}, true, [call_time]),
+ 2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, true, [call_time]),
+ Pid = setup(),
+ {L, T1} = execute(Pid, fun() -> with_bif(M) end),
- ?line ok = check_trace_info({erlang, binary_to_term, 1}, [{Pid, M - 1, 0, 0}], T1/2),
- ?line ok = check_trace_info({erlang, term_to_binary, 1}, [{Pid, M - 1, 0, 0}], T1/2),
+ ok = check_trace_info({erlang, binary_to_term, 1}, [{Pid, M - 1, 0, 0}], T1/2),
+ ok = check_trace_info({erlang, term_to_binary, 1}, [{Pid, M - 1, 0, 0}], T1/2),
% disable term2binary
- ?line 2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, false, [call_time]),
+ 2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, false, [call_time]),
- ?line {L, T2} = execute(Pid, fun() -> with_bif(M) end),
+ {L, T2} = execute(Pid, fun() -> with_bif(M) end),
- ?line ok = check_trace_info({erlang, binary_to_term, 1}, [{Pid, M*2 - 2, 0, 0}], T1/2 + T2),
- ?line ok = check_trace_info({erlang, term_to_binary, 1}, false, none),
+ ok = check_trace_info({erlang, binary_to_term, 1}, [{Pid, M*2 - 2, 0, 0}], T1/2 + T2),
+ ok = check_trace_info({erlang, term_to_binary, 1}, false, none),
%%
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
- ?line Pid ! quit,
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
+ Pid ! quit,
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-nif(suite) ->
- [];
-nif(doc) ->
- ["Tests tracing of nifs"];
+%% Tests tracing of nifs
nif(Config) when is_list(Config) ->
load_nif(Config),
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
- ?line M = 1000000,
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
+ M = 1000000,
%%
- ?line 1 = erlang:trace_pattern({?MODULE, nif_dec, '_'}, true, [call_time]),
- ?line 1 = erlang:trace_pattern({?MODULE, with_nif, '_'}, true, [call_time]),
- ?line Pid = setup(),
- ?line {_, T1} = execute(Pid, fun() -> with_nif(M) end),
+ 1 = erlang:trace_pattern({?MODULE, nif_dec, '_'}, true, [call_time]),
+ 1 = erlang:trace_pattern({?MODULE, with_nif, '_'}, true, [call_time]),
+ Pid = setup(),
+ {_, T1} = execute(Pid, fun() -> with_nif(M) end),
% the nif is called M - 1 times, the last time the function with 'with_nif'
% returns ok and does not call the nif.
- ?line ok = check_trace_info({?MODULE, nif_dec, 1}, [{Pid, M-1, 0, 0}], T1/5*4),
- ?line ok = check_trace_info({?MODULE, with_nif, 1}, [{Pid, M, 0, 0}], T1/5),
+ ok = check_trace_info({?MODULE, nif_dec, 1}, [{Pid, M-1, 0, 0}], T1/5*4),
+ ok = check_trace_info({?MODULE, with_nif, 1}, [{Pid, M, 0, 0}], T1/5),
%%
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
- ?line Pid ! quit,
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
+ Pid ! quit,
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-called_function(suite) ->
- [];
-called_function(doc) ->
- ["Tests combining nested function calls and that the time accumulates to the right function"];
+%% Tests combining nested function calls and that the time accumulates to the right function
called_function(Config) when is_list(Config) ->
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
- ?line M = 2100,
- ?line Pid = setup(),
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
+ M = 2100,
+ Pid = setup(),
%%
- ?line 1 = erlang:trace_pattern({?MODULE,a_function,'_'}, true, [call_time]),
- ?line {L, T1} = execute(Pid, {?MODULE, a_function, [M]}),
- ?line ok = check_trace_info({?MODULE, a_function, 1}, [{Pid, M, 0, 0}], T1),
+ 1 = erlang:trace_pattern({?MODULE,a_function,'_'}, true, [call_time]),
+ {L, T1} = execute(Pid, {?MODULE, a_function, [M]}),
+ ok = check_trace_info({?MODULE, a_function, 1}, [{Pid, M, 0, 0}], T1),
- ?line 1 = erlang:trace_pattern({?MODULE,a_called_function,'_'}, true, [call_time]),
- ?line {L, T2} = execute(Pid, {?MODULE, a_function, [M]}),
- ?line ok = check_trace_info({?MODULE, a_function, 1}, [{Pid, M+M, 0, 0}], T1 + M*?SINGLE_CALL_US_TIME),
- ?line ok = check_trace_info({?MODULE, a_called_function, 1}, [{Pid, M, 0, 0}], T2),
+ 1 = erlang:trace_pattern({?MODULE,a_called_function,'_'}, true, [call_time]),
+ {L, T2} = execute(Pid, {?MODULE, a_function, [M]}),
+ ok = check_trace_info({?MODULE, a_function, 1}, [{Pid, M+M, 0, 0}], T1 + M*?SINGLE_CALL_US_TIME),
+ ok = check_trace_info({?MODULE, a_called_function, 1}, [{Pid, M, 0, 0}], T2),
- ?line 1 = erlang:trace_pattern({?MODULE,dec,'_'}, true, [call_time]),
- ?line {L, T3} = execute(Pid, {?MODULE, a_function, [M]}),
- ?line ok = check_trace_info({?MODULE, a_function, 1}, [{Pid, M+M+M, 0, 0}], T1 + (M+M)*?SINGLE_CALL_US_TIME),
- ?line ok = check_trace_info({?MODULE, a_called_function, 1}, [{Pid, M+M, 0, 0}], T2 + M*?SINGLE_CALL_US_TIME ),
- ?line ok = check_trace_info({?MODULE, dec, 1}, [{Pid, M, 0, 0}], T3),
+ 1 = erlang:trace_pattern({?MODULE,dec,'_'}, true, [call_time]),
+ {L, T3} = execute(Pid, {?MODULE, a_function, [M]}),
+ ok = check_trace_info({?MODULE, a_function, 1}, [{Pid, M+M+M, 0, 0}], T1 + (M+M)*?SINGLE_CALL_US_TIME),
+ ok = check_trace_info({?MODULE, a_called_function, 1}, [{Pid, M+M, 0, 0}], T2 + M*?SINGLE_CALL_US_TIME ),
+ ok = check_trace_info({?MODULE, dec, 1}, [{Pid, M, 0, 0}], T3),
- ?line Pid ! quit,
- ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
+ Pid ! quit,
+ P = erlang:trace_pattern({'_','_','_'}, false, [call_time]),
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -482,8 +437,8 @@ dead_tracer(Config) when is_list(Config) ->
Ref = erlang:monitor(process, FirstTracer),
FirstTracer ! quit,
receive
- {'DOWN',Ref,process,FirstTracer,normal} ->
- ok
+ {'DOWN',Ref,process,FirstTracer,normal} ->
+ ok
end,
erlang:yield(),
@@ -513,26 +468,26 @@ dead_tracer(Config) when is_list(Config) ->
other_than_self(Info) ->
[{Pid,MFA} || {MFA,[{Pid,_,_,_}]} <- Info,
- Pid =/= self()].
+ Pid =/= self()].
tell_tracer(Tracer, Fun) ->
Tracer ! {execute,self(),Fun},
receive
- {Tracer,executed} ->
- ok
+ {Tracer,executed} ->
+ ok
end.
tracer() ->
spawn_link(fun Loop() ->
- receive
- quit ->
- ok;
- {execute,From,Fun} ->
- Fun(),
- From ! {self(),executed},
- Loop()
- end
- end).
+ receive
+ quit ->
+ ok;
+ {execute,From,Fun} ->
+ Fun(),
+ From ! {self(),executed},
+ Loop()
+ end
+ end).
turn_on_tracing(Pid) ->
_ = erlang:trace(Pid, true, [call,set_on_spawn]),
@@ -542,18 +497,18 @@ turn_on_tracing(Pid) ->
collect_all_info() ->
collect_all_info([{?MODULE,F,A} || {F,A} <- module_info(functions)] ++
- erlang:system_info(snifs)).
+ erlang:system_info(snifs)).
collect_all_info([MFA|T]) ->
CallTime = erlang:trace_info(MFA, call_time),
erlang:trace_pattern(MFA, restart, [call_time]),
case CallTime of
- {call_time,false} ->
- collect_all_info(T);
- {call_time,[]} ->
- collect_all_info(T);
- {call_time,[_|_]=List} ->
- [{MFA,List}|collect_all_info(T)]
+ {call_time,false} ->
+ collect_all_info(T);
+ {call_time,[]} ->
+ collect_all_info(T);
+ {call_time,[_|_]=List} ->
+ [{MFA,List}|collect_all_info(T)]
end;
collect_all_info([]) -> [].
@@ -566,8 +521,8 @@ collect_all_info([]) -> [].
%% Local helpers
load_nif(Config) ->
- ?line Path = ?config(data_dir, Config),
- ?line ok = erlang:load_nif(filename:join(Path,"trace_nif"), 0).
+ Path = proplists:get_value(data_dir, Config),
+ ok = erlang:load_nif(filename:join(Path,"trace_nif"), 0).
%% Stack recursive seq
@@ -614,39 +569,39 @@ seq_r(Start, Stop, Succ, R) ->
% Check call time tracing data and print mismatches
check_trace_info(Mfa, [{Pid, C,_,_}] = Expect, Time) ->
case erlang:trace_info(Mfa, call_time) of
- % Time tests are somewhat problematic. We want to know if Time (EXPECTED_TIME) and S*1000000 + Us (ACTUAL_TIME)
- % is the same.
- % If the ratio EXPECTED_TIME/ACTUAL_TIME is ~ 1 or if EXPECTED_TIME - ACTUAL_TIME is near zero, the test is ok.
- {call_time,[{Pid,C,S,Us}]} when S >= 0, Us >= 0, abs(1 - Time/(S*1000000 + Us)) < ?R_ERROR; abs(Time - S*1000000 - Us) < ?US_ERROR ->
- ok;
- {call_time,[{Pid,C,S,Us}]} ->
- Sum = S*1000000 + Us,
- io:format("Expected ~p -> {call_time, ~p (Time ~p us)}~n - got ~w s. ~w us. = ~w us. - ~w -> delta ~w (ratio ~.2f, should be 1.0)~n",
- [Mfa, Expect, Time, S, Us, Sum, Time, Sum - Time, Time/Sum]),
- time_error;
- Other ->
- io:format("Expected ~p -> {call_time, ~p (Time ~p us)}~n - got ~p~n", [ Mfa, Expect, Time, Other]),
- time_count_error
+ % Time tests are somewhat problematic. We want to know if Time (EXPECTED_TIME) and S*1000000 + Us (ACTUAL_TIME)
+ % is the same.
+ % If the ratio EXPECTED_TIME/ACTUAL_TIME is ~ 1 or if EXPECTED_TIME - ACTUAL_TIME is near zero, the test is ok.
+ {call_time,[{Pid,C,S,Us}]} when S >= 0, Us >= 0, abs(1 - Time/(S*1000000 + Us)) < ?R_ERROR; abs(Time - S*1000000 - Us) < ?US_ERROR ->
+ ok;
+ {call_time,[{Pid,C,S,Us}]} ->
+ Sum = S*1000000 + Us,
+ io:format("Expected ~p -> {call_time, ~p (Time ~p us)}~n - got ~w s. ~w us. = ~w us. - ~w -> delta ~w (ratio ~.2f, should be 1.0)~n",
+ [Mfa, Expect, Time, S, Us, Sum, Time, Sum - Time, Time/Sum]),
+ time_error;
+ Other ->
+ io:format("Expected ~p -> {call_time, ~p (Time ~p us)}~n - got ~p~n", [ Mfa, Expect, Time, Other]),
+ time_count_error
end;
check_trace_info(Mfa, Expect, _) ->
case erlang:trace_info(Mfa, call_time) of
- {call_time, Expect} ->
- ok;
- Other ->
- io:format("Expected ~p -> {call_time, ~p}~n - got ~p~n", [Mfa, Expect, Other]),
- result_not_expected_error
+ {call_time, Expect} ->
+ ok;
+ Other ->
+ io:format("Expected ~p -> {call_time, ~p}~n - got ~p~n", [Mfa, Expect, Other]),
+ result_not_expected_error
end.
%check process time
check_process_time({value,{Pid, M, S, Us}}, M, F, Time) ->
- ?line Sum = S*1000000 + Us,
+ Sum = S*1000000 + Us,
if
- abs(1 - (F/(Time/Sum))) < ?R_ERROR ->
- ok;
- true ->
- io:format("- Pid ~p, Got ratio ~.2f, expected ratio ~w~n", [Pid, Time/Sum,F]),
- schedule_time_error
+ abs(1 - (F/(Time/Sum))) < ?R_ERROR ->
+ ok;
+ true ->
+ io:format("- Pid ~p, Got ratio ~.2f, expected ratio ~w~n", [Pid, Time/Sum,F]),
+ schedule_time_error
end;
check_process_time(Other, M, _, _) ->
io:format(" - Got ~p, expected count ~w~n", [Other, M]),
@@ -659,8 +614,8 @@ relay_n(0, _) ->
ok;
relay_n(N, Dest) ->
receive Msg ->
- Dest ! {self(), Msg},
- relay_n(N-1, Dest)
+ Dest ! {self(), Msg},
+ relay_n(N-1, Dest)
end.
@@ -674,17 +629,17 @@ collect(Time) ->
collect(A, 0) ->
receive
- Mess ->
- collect([Mess | A], 0)
+ Mess ->
+ collect([Mess | A], 0)
after 0 ->
- A
+ A
end;
collect(A, Ref) ->
receive
- {timeout, Ref, done} ->
- collect(A, 0);
- Mess ->
- collect([Mess | A], Ref)
+ {timeout, Ref, done} ->
+ collect(A, 0);
+ Mess ->
+ collect([Mess | A], Ref)
end.
setup() ->
@@ -712,12 +667,12 @@ execute(P, Mfa) ->
loop() ->
receive
- quit ->
- ok;
- {Pid, execute, Fun } when is_function(Fun) ->
- Pid ! {self(), answer, erlang:apply(Fun, [])},
- loop();
- {Pid, execute, {M, F, A}} ->
- Pid ! {self(), answer, erlang:apply(M, F, A)},
- loop()
+ quit ->
+ ok;
+ {Pid, execute, Fun } when is_function(Fun) ->
+ Pid ! {self(), answer, erlang:apply(Fun, [])},
+ loop();
+ {Pid, execute, {M, F, A}} ->
+ Pid ! {self(), answer, erlang:apply(M, F, A)},
+ loop()
end.
diff --git a/erts/emulator/test/trace_local_SUITE.erl b/erts/emulator/test/trace_local_SUITE.erl
index 7431099340..24864dcbef 100644
--- a/erts/emulator/test/trace_local_SUITE.erl
+++ b/erts/emulator/test/trace_local_SUITE.erl
@@ -29,69 +29,44 @@
-export([exported/1, exported_wrap/1, loop/4, apply_slave_async/5,
match/2, clause/2, id/1, undef/1, lists_reverse/2]).
-%%
-%% Define to run outside of test server
-%%
-%% (rotten feature)
-%%
-%%-define(STANDALONE,1).
-
+
%%
%% Define for debug output
%%
%%-define(debug,1).
--ifdef(STANDALONE).
--define(config(A,B),config(A,B)).
--export([config/2]).
--define(DEFAULT_RECEIVE_TIMEOUT, 1000).
--else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(DEFAULT_RECEIVE_TIMEOUT, infinity).
--endif.
-
+
-ifdef(debug).
--ifdef(STANDALONE).
--define(line, erlang:display({?MODULE,?LINE}), ).
--endif.
-define(dbgformat(A,B),io:format(A,B)).
-else.
--ifdef(STANDALONE).
--define(line, noop, ).
--endif.
-define(dbgformat(A,B),noop).
-endif.
-
--ifdef(STANDALONE).
-config(priv_dir,_) ->
- ".".
--else.
%%% When run in test server %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2, basic/1, bit_syntax/1,
- return/1, on_and_off/1, systematic_on_off/1,
- stack_grow/1,info/1, delete/1,
- exception/1, exception_apply/1,
- exception_function/1, exception_apply_function/1,
- exception_nocatch/1, exception_nocatch_apply/1,
- exception_nocatch_function/1, exception_nocatch_apply_function/1,
- exception_meta/1, exception_meta_apply/1,
- exception_meta_function/1, exception_meta_apply_function/1,
- exception_meta_nocatch/1, exception_meta_nocatch_apply/1,
- exception_meta_nocatch_function/1,
- exception_meta_nocatch_apply_function/1,
- concurrency/1,
- init_per_testcase/2, end_per_testcase/2]).
+-export([all/0, suite/0,
+ basic/1, bit_syntax/1,
+ return/1, on_and_off/1, systematic_on_off/1,
+ stack_grow/1,info/1, delete/1,
+ exception/1, exception_apply/1,
+ exception_function/1, exception_apply_function/1,
+ exception_nocatch/1, exception_nocatch_apply/1,
+ exception_nocatch_function/1, exception_nocatch_apply_function/1,
+ exception_meta/1, exception_meta_apply/1,
+ exception_meta_function/1, exception_meta_apply_function/1,
+ exception_meta_nocatch/1, exception_meta_nocatch_apply/1,
+ exception_meta_nocatch_function/1,
+ exception_meta_nocatch_apply_function/1,
+ concurrency/1,
+ init_per_testcase/2, end_per_testcase/2]).
+
init_per_testcase(_Case, Config) ->
- ?line Dog=test_server:timetrap(test_server:minutes(2)),
- [{watchdog, Dog}|Config].
+ Config.
end_per_testcase(_Case, Config) ->
shutdown(),
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
%% Reloading the module will clear all trace patterns, and
%% in a debug-compiled emulator run assertions of the counters
@@ -99,168 +74,127 @@ end_per_testcase(_Case, Config) ->
c:l(?MODULE).
-
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 2}}].
all() ->
case test_server:is_native(trace_local_SUITE) of
- true -> [not_run];
- false ->
- [basic, bit_syntax, return, on_and_off, systematic_on_off,
- stack_grow,
- info, delete, exception, exception_apply,
- exception_function, exception_apply_function,
- exception_nocatch, exception_nocatch_apply,
- exception_nocatch_function,
- exception_nocatch_apply_function, exception_meta,
- exception_meta_apply, exception_meta_function,
- exception_meta_apply_function, exception_meta_nocatch,
- exception_meta_nocatch_apply,
- exception_meta_nocatch_function,
- exception_meta_nocatch_apply_function,
- concurrency]
+ true -> [not_run];
+ false ->
+ [basic, bit_syntax, return, on_and_off, systematic_on_off,
+ stack_grow,
+ info, delete, exception, exception_apply,
+ exception_function, exception_apply_function,
+ exception_nocatch, exception_nocatch_apply,
+ exception_nocatch_function,
+ exception_nocatch_apply_function, exception_meta,
+ exception_meta_apply, exception_meta_function,
+ exception_meta_apply_function, exception_meta_nocatch,
+ exception_meta_nocatch_apply,
+ exception_meta_nocatch_function,
+ exception_meta_nocatch_apply_function,
+ concurrency]
end.
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
not_run(Config) when is_list(Config) ->
{skipped,"Native code"}.
-basic(doc) ->
- ["Tests basic local call-trace"];
+%% Tests basic local call-trace
basic(Config) when is_list(Config) ->
basic_test().
-bit_syntax(doc) ->
- "OTP-7399: Make sure that code that uses the optimized bit syntax matching "
- "can be traced without crashing the emulator.";
+%% OTP-7399: Make sure that code that uses the optimized bit syntax matching
+%% can be traced without crashing the emulator.
bit_syntax(Config) when is_list(Config) ->
bit_syntax_test().
-return(doc) ->
- ["Tests the different types of return trace"];
+%% Tests the different types of return trace
return(Config) when is_list(Config) ->
return_test().
-
-on_and_off(doc) ->
- ["Tests turning trace parameters on and off, "
- "both for trace and trace_pattern"];
+
+%% Tests turning trace parameters on and off,
+%% both for trace and trace_pattern
on_and_off(Config) when is_list(Config) ->
on_and_off_test().
-
-stack_grow(doc) ->
- ["Tests the stack growth during return traces"];
+
+%% Tests the stack growth during return traces
stack_grow(Config) when is_list(Config) ->
stack_grow_test().
-
-info(doc) ->
- ["Tests the trace_info BIF"];
+
+%% Tests the trace_info BIF
info(Config) when is_list(Config) ->
info_test().
-
-delete(doc) ->
- ["Tests putting trace on deleted modules"];
+
+%% Tests putting trace on deleted modules
delete(Config) when is_list(Config) ->
delete_test(Config).
-exception(doc) ->
- ["Tests exception_trace"];
+%% Tests exception_trace
exception(Config) when is_list(Config) ->
exception_test([]).
-exception_apply(doc) ->
- ["Tests exception_trace"];
+%% Tests exception_trace
exception_apply(Config) when is_list(Config) ->
exception_test([apply]).
-exception_function(doc) ->
- ["Tests exception_trace"];
+%% Tests exception_trace
exception_function(Config) when is_list(Config) ->
exception_test([function]).
-exception_apply_function(doc) ->
- ["Tests exception_trace"];
+%% Tests exception_trace
exception_apply_function(Config) when is_list(Config) ->
exception_test([apply,function]).
-exception_nocatch(doc) ->
- ["Tests exception_trace"];
+%% Tests exception_trace
exception_nocatch(Config) when is_list(Config) ->
exception_test([nocatch]).
-exception_nocatch_apply(doc) ->
- ["Tests exception_trace"];
+%% Tests exception_trace
exception_nocatch_apply(Config) when is_list(Config) ->
exception_test([nocatch,apply]).
-exception_nocatch_function(doc) ->
- ["Tests exception_trace"];
+%% Tests exception_trace
exception_nocatch_function(Config) when is_list(Config) ->
exception_test([nocatch,function]).
-exception_nocatch_apply_function(doc) ->
- ["Tests exception_trace"];
+%% Tests exception_trace
exception_nocatch_apply_function(Config) when is_list(Config) ->
exception_test([nocatch,apply,function]).
-exception_meta(doc) ->
- ["Tests meta exception_trace"];
+%% Tests meta exception_trace
exception_meta(Config) when is_list(Config) ->
exception_test([meta]).
-exception_meta_apply(doc) ->
- ["Tests meta exception_trace"];
+%% Tests meta exception_trace
exception_meta_apply(Config) when is_list(Config) ->
exception_test([meta,apply]).
-exception_meta_function(doc) ->
- ["Tests meta exception_trace"];
+%% Tests meta exception_trace
exception_meta_function(Config) when is_list(Config) ->
exception_test([meta,function]).
-exception_meta_apply_function(doc) ->
- ["Tests meta exception_trace"];
+%% Tests meta exception_trace
exception_meta_apply_function(Config) when is_list(Config) ->
exception_test([meta,apply,function]).
-exception_meta_nocatch(doc) ->
- ["Tests meta exception_trace"];
+%% Tests meta exception_trace
exception_meta_nocatch(Config) when is_list(Config) ->
exception_test([meta,nocatch]).
-exception_meta_nocatch_apply(doc) ->
- ["Tests meta exception_trace"];
+%% Tests meta exception_trace
exception_meta_nocatch_apply(Config) when is_list(Config) ->
exception_test([meta,nocatch,apply]).
-exception_meta_nocatch_function(doc) ->
- ["Tests meta exception_trace"];
+%% Tests meta exception_trace
exception_meta_nocatch_function(Config) when is_list(Config) ->
exception_test([meta,nocatch,function]).
-exception_meta_nocatch_apply_function(doc) ->
- ["Tests meta exception_trace"];
+%% Tests meta exception_trace
exception_meta_nocatch_apply_function(Config) when is_list(Config) ->
exception_test([meta,nocatch,apply,function]).
--endif.
-
-
%%% Message patterns and expect functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -309,28 +243,28 @@ expect_pid(Pid, Msg) when is_tuple(Msg) ->
same(Msg, expect_receive(Pid));
expect_pid(Pid, Fun) when is_function(Fun, 1) ->
case Fun(expect_receive(Pid)) of
- next ->
- expect_pid(Pid, Fun);
- done ->
- ok;
- Other ->
- expect_pid(Pid, Other)
+ next ->
+ expect_pid(Pid, Fun);
+ done ->
+ ok;
+ Other ->
+ expect_pid(Pid, Other)
end.
expect_receive(Pid) when is_pid(Pid) ->
receive
- Msg when is_tuple(Msg),
- element(1, Msg) == trace,
- element(2, Msg) =/= Pid;
- %%
- is_tuple(Msg),
- element(1, Msg) == trace_ts,
- element(2, Msg) =/= Pid ->
- expect_receive(Pid);
- Msg ->
- expect_msg(Pid, Msg)
+ Msg when is_tuple(Msg),
+ element(1, Msg) == trace,
+ element(2, Msg) =/= Pid;
+ %%
+ is_tuple(Msg),
+ element(1, Msg) == trace_ts,
+ element(2, Msg) =/= Pid ->
+ expect_receive(Pid);
+ Msg ->
+ expect_msg(Pid, Msg)
after 100 ->
- {nm}
+ {nm}
end.
expect_msg(P, ?pCT(P,M,F,Args)) -> {ct,{M,F},Args};
@@ -343,18 +277,18 @@ expect_msg(P, ?pRT(P,M,F,Arity)) -> {rt,{M,F,Arity}};
expect_msg(P, ?pRTT(P,M,F,Arity)) -> {rtt,{M,F,Arity}};
expect_msg(P, Msg) when is_tuple(Msg) ->
case tuple_to_list(Msg) of
- [trace,P|T] ->
- list_to_tuple([trace|T]);
- [trace_ts,P|[_|_]=T] ->
- list_to_tuple([trace_ts|reverse(tl(reverse(T)))]);
- _ ->
- Msg
+ [trace,P|T] ->
+ list_to_tuple([trace|T]);
+ [trace_ts,P|[_|_]=T] ->
+ list_to_tuple([trace_ts|reverse(tl(reverse(T)))]);
+ _ ->
+ Msg
end.
same(A, B) ->
case [A|B] of
- [X|X] ->
- ok
+ [X|X] ->
+ ok
end.
@@ -362,73 +296,73 @@ same(A, B) ->
%%% tests %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
basic_test() ->
- ?line setup([call]),
+ setup([call]),
NumMatches = erlang:trace_pattern({?MODULE,'_','_'},[],[local]),
NumMatches = erlang:trace_pattern({?MODULE,'_','_'},[],[local]),
- ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
- ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
- ?line ?CT(?MODULE,exported_wrap,[1]),
- ?line ?CT(?MODULE,exported,[1]),
- ?line ?CT(?MODULE,local,[1]),
- ?line ?CT(?MODULE,local2,[1]),
- ?line ?CT(?MODULE,local_tail,[1]),
- ?line erlang:trace_pattern({?MODULE,'_','_'},[],[]),
- ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
- ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
- ?line ?CT(?MODULE,exported_wrap,[1]),
- ?line [1,1,1,1] = lambda_slave(fun() ->
- exported_wrap(1)
- end),
- ?line ?NM,
- ?line erlang:trace_pattern({?MODULE,'_','_'},[],[local]),
- ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
- ?line [1,1,1,1] = lambda_slave(fun() ->
- exported_wrap(1)
- end),
- ?line ?CT(?MODULE,_,_), %% The fun
- ?line ?CT(?MODULE,exported_wrap,[1]),
- ?line ?CT(?MODULE,exported,[1]),
- ?line ?CT(?MODULE,local,[1]),
- ?line ?CT(?MODULE,local2,[1]),
- ?line ?CT(?MODULE,local_tail,[1]),
- ?line erlang:trace_pattern({?MODULE,'_','_'},false,[local]),
- ?line shutdown(),
- ?line ?NM,
+ erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
+ [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
+ ?CT(?MODULE,exported_wrap,[1]),
+ ?CT(?MODULE,exported,[1]),
+ ?CT(?MODULE,local,[1]),
+ ?CT(?MODULE,local2,[1]),
+ ?CT(?MODULE,local_tail,[1]),
+ erlang:trace_pattern({?MODULE,'_','_'},[],[]),
+ erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
+ [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
+ ?CT(?MODULE,exported_wrap,[1]),
+ [1,1,1,1] = lambda_slave(fun() ->
+ exported_wrap(1)
+ end),
+ ?NM,
+ erlang:trace_pattern({?MODULE,'_','_'},[],[local]),
+ erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
+ [1,1,1,1] = lambda_slave(fun() ->
+ exported_wrap(1)
+ end),
+ ?CT(?MODULE,_,_), %% The fun
+ ?CT(?MODULE,exported_wrap,[1]),
+ ?CT(?MODULE,exported,[1]),
+ ?CT(?MODULE,local,[1]),
+ ?CT(?MODULE,local2,[1]),
+ ?CT(?MODULE,local_tail,[1]),
+ erlang:trace_pattern({?MODULE,'_','_'},false,[local]),
+ shutdown(),
+ ?NM,
ok.
%% OTP-7399.
bit_syntax_test() ->
- ?line setup([call]),
- ?line erlang:trace_pattern({?MODULE,'_','_'},[],[local]),
- ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
-
- ?line lambda_slave(fun() ->
- 6 = bs_sum_a(<<1,2,3>>, 0),
- 10 = bs_sum_b(0, <<1,2,3,4>>),
- 26 = bs_sum_c(<<3:4,5:4,7:4,11:4>>, 0)
- end),
- ?line ?CT(?MODULE,_,[]), %Ignore call to the fun.
-
- ?line ?CT(?MODULE,bs_sum_a,[<<1,2,3>>,0]),
- ?line ?CT(?MODULE,bs_sum_a,[<<2,3>>,1]),
- ?line ?CT(?MODULE,bs_sum_a,[<<3>>,3]),
- ?line ?CT(?MODULE,bs_sum_a,[<<>>,6]),
-
- ?line ?CT(?MODULE,bs_sum_b,[0,<<1,2,3,4>>]),
- ?line ?CT(?MODULE,bs_sum_b,[1,<<2,3,4>>]),
- ?line ?CT(?MODULE,bs_sum_b,[3,<<3,4>>]),
- ?line ?CT(?MODULE,bs_sum_b,[6,<<4>>]),
- ?line ?CT(?MODULE,bs_sum_b,[10,<<>>]),
-
- ?line ?CT(?MODULE,bs_sum_c,[<<3:4,5:4,7:4,11:4>>, 0]),
- ?line ?CT(?MODULE,bs_sum_c,[<<5:4,7:4,11:4>>, 3]),
- ?line ?CT(?MODULE,bs_sum_c,[<<7:4,11:4>>, 8]),
- ?line ?CT(?MODULE,bs_sum_c,[<<11:4>>, 15]),
- ?line ?CT(?MODULE,bs_sum_c,[<<>>, 26]),
-
- ?line erlang:trace_pattern({?MODULE,'_','_'},false,[local]),
- ?line shutdown(),
- ?line ?NM,
+ setup([call]),
+ erlang:trace_pattern({?MODULE,'_','_'},[],[local]),
+ erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
+
+ lambda_slave(fun() ->
+ 6 = bs_sum_a(<<1,2,3>>, 0),
+ 10 = bs_sum_b(0, <<1,2,3,4>>),
+ 26 = bs_sum_c(<<3:4,5:4,7:4,11:4>>, 0)
+ end),
+ ?CT(?MODULE,_,[]), %Ignore call to the fun.
+
+ ?CT(?MODULE,bs_sum_a,[<<1,2,3>>,0]),
+ ?CT(?MODULE,bs_sum_a,[<<2,3>>,1]),
+ ?CT(?MODULE,bs_sum_a,[<<3>>,3]),
+ ?CT(?MODULE,bs_sum_a,[<<>>,6]),
+
+ ?CT(?MODULE,bs_sum_b,[0,<<1,2,3,4>>]),
+ ?CT(?MODULE,bs_sum_b,[1,<<2,3,4>>]),
+ ?CT(?MODULE,bs_sum_b,[3,<<3,4>>]),
+ ?CT(?MODULE,bs_sum_b,[6,<<4>>]),
+ ?CT(?MODULE,bs_sum_b,[10,<<>>]),
+
+ ?CT(?MODULE,bs_sum_c,[<<3:4,5:4,7:4,11:4>>, 0]),
+ ?CT(?MODULE,bs_sum_c,[<<5:4,7:4,11:4>>, 3]),
+ ?CT(?MODULE,bs_sum_c,[<<7:4,11:4>>, 8]),
+ ?CT(?MODULE,bs_sum_c,[<<11:4>>, 15]),
+ ?CT(?MODULE,bs_sum_c,[<<>>, 26]),
+
+ erlang:trace_pattern({?MODULE,'_','_'},false,[local]),
+ shutdown(),
+ ?NM,
ok.
@@ -442,149 +376,149 @@ bs_sum_c(<<H:4,T/bits>>, Acc) -> bs_sum_c(T, H+Acc);
bs_sum_c(<<>>, Acc) -> Acc.
return_test() ->
- ?line setup([call]),
- ?line erlang:trace_pattern({?MODULE,'_','_'},[{'_',[],[{return_trace}]}],
- [local]),
- ?line erlang:trace_pattern({erlang,hash,'_'},[{'_',[],[{return_trace}]}],
- [local]),
- ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
- ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
- ?line ?CT(?MODULE,exported_wrap,[1]),
- ?line ?CT(?MODULE,exported,[1]),
- ?line ?CT(?MODULE,local,[1]),
- ?line ?CT(?MODULE,local2,[1]),
- ?line ?CT(?MODULE,local_tail,[1]),
- ?line ?CT(erlang,hash,[1,1]),
- ?line ?RF(erlang,hash,2,1),
- ?line ?RF(?MODULE,local_tail,1,[1,1]),
- ?line ?RF(?MODULE,local2,1,[1,1]),
- ?line ?RF(?MODULE,local,1,[1,1,1]),
- ?line ?RF(?MODULE,exported,1,[1,1,1,1]),
- ?line ?RF(?MODULE,exported_wrap,1,[1,1,1,1]),
- ?line shutdown(),
- ?line setup([call,return_to]),
- ?line erlang:trace_pattern({?MODULE,'_','_'},[],
- [local]),
- ?line erlang:trace_pattern({erlang,hash,'_'},[],
- [local]),
- ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
- ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
- ?line ?CT(?MODULE,exported_wrap,[1]),
- ?line ?CT(?MODULE,exported,[1]),
- ?line ?CT(?MODULE,local,[1]),
- ?line ?CT(?MODULE,local2,[1]),
- ?line ?CT(?MODULE,local_tail,[1]),
- ?line ?CT(erlang,hash,[1,1]),
- ?line ?RT(?MODULE,local_tail,1),
- ?line ?RT(?MODULE,local,1),
- ?line ?RT(?MODULE,exported,1),
- ?line ?RT(?MODULE,slave,2),
- ?line shutdown(),
- ?line setup([call,return_to]),
- ?line erlang:trace_pattern({?MODULE,'_','_'},[{'_',[],[{return_trace}]}],
- [local]),
- ?line erlang:trace_pattern({erlang,hash,'_'},[{'_',[],[{return_trace}]}],
- [local]),
- ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
- ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
- ?line ?CT(?MODULE,exported_wrap,[1]),
- ?line ?CT(?MODULE,exported,[1]),
- ?line ?CT(?MODULE,local,[1]),
- ?line ?CT(?MODULE,local2,[1]),
- ?line ?CT(?MODULE,local_tail,[1]),
- ?line ?CT(erlang,hash,[1,1]),
- ?line ?RF(erlang,hash,2,1),
- ?line ?RT(?MODULE,local_tail,1),
- ?line ?RF(?MODULE,local_tail,1,[1,1]),
- ?line ?RF(?MODULE,local2,1,[1,1]),
- ?line ?RT(?MODULE,local,1),
- ?line ?RF(?MODULE,local,1,[1,1,1]),
- ?line ?RT(?MODULE,exported,1),
- ?line ?RF(?MODULE,exported,1,[1,1,1,1]),
- ?line ?RF(?MODULE,exported_wrap,1,[1,1,1,1]),
- ?line ?RT(?MODULE,slave,2),
- ?line shutdown(),
- ?line ?NM,
+ setup([call]),
+ erlang:trace_pattern({?MODULE,'_','_'},[{'_',[],[{return_trace}]}],
+ [local]),
+ erlang:trace_pattern({erlang,hash,'_'},[{'_',[],[{return_trace}]}],
+ [local]),
+ erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
+ [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
+ ?CT(?MODULE,exported_wrap,[1]),
+ ?CT(?MODULE,exported,[1]),
+ ?CT(?MODULE,local,[1]),
+ ?CT(?MODULE,local2,[1]),
+ ?CT(?MODULE,local_tail,[1]),
+ ?CT(erlang,hash,[1,1]),
+ ?RF(erlang,hash,2,1),
+ ?RF(?MODULE,local_tail,1,[1,1]),
+ ?RF(?MODULE,local2,1,[1,1]),
+ ?RF(?MODULE,local,1,[1,1,1]),
+ ?RF(?MODULE,exported,1,[1,1,1,1]),
+ ?RF(?MODULE,exported_wrap,1,[1,1,1,1]),
+ shutdown(),
+ setup([call,return_to]),
+ erlang:trace_pattern({?MODULE,'_','_'},[],
+ [local]),
+ erlang:trace_pattern({erlang,hash,'_'},[],
+ [local]),
+ erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
+ [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
+ ?CT(?MODULE,exported_wrap,[1]),
+ ?CT(?MODULE,exported,[1]),
+ ?CT(?MODULE,local,[1]),
+ ?CT(?MODULE,local2,[1]),
+ ?CT(?MODULE,local_tail,[1]),
+ ?CT(erlang,hash,[1,1]),
+ ?RT(?MODULE,local_tail,1),
+ ?RT(?MODULE,local,1),
+ ?RT(?MODULE,exported,1),
+ ?RT(?MODULE,slave,2),
+ shutdown(),
+ setup([call,return_to]),
+ erlang:trace_pattern({?MODULE,'_','_'},[{'_',[],[{return_trace}]}],
+ [local]),
+ erlang:trace_pattern({erlang,hash,'_'},[{'_',[],[{return_trace}]}],
+ [local]),
+ erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
+ [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
+ ?CT(?MODULE,exported_wrap,[1]),
+ ?CT(?MODULE,exported,[1]),
+ ?CT(?MODULE,local,[1]),
+ ?CT(?MODULE,local2,[1]),
+ ?CT(?MODULE,local_tail,[1]),
+ ?CT(erlang,hash,[1,1]),
+ ?RF(erlang,hash,2,1),
+ ?RT(?MODULE,local_tail,1),
+ ?RF(?MODULE,local_tail,1,[1,1]),
+ ?RF(?MODULE,local2,1,[1,1]),
+ ?RT(?MODULE,local,1),
+ ?RF(?MODULE,local,1,[1,1,1]),
+ ?RT(?MODULE,exported,1),
+ ?RF(?MODULE,exported,1,[1,1,1,1]),
+ ?RF(?MODULE,exported_wrap,1,[1,1,1,1]),
+ ?RT(?MODULE,slave,2),
+ shutdown(),
+ ?NM,
ok.
on_and_off_test() ->
- ?line Pid = setup([call]),
- ?line 1 = erlang:trace_pattern({?MODULE,local_tail,1},[],[local]),
- ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
- ?line LocalTail = fun() ->
- local_tail(1)
- end,
- ?line [1,1] = lambda_slave(LocalTail),
- ?line ?CT(?MODULE,local_tail,[1]),
- ?line erlang:trace(Pid,true,[return_to]),
- ?line [1,1] = lambda_slave(LocalTail),
- ?line ?CT(?MODULE,local_tail,[1]),
- ?line ?RT(?MODULE,_,_),
- ?line 0 = erlang:trace_pattern({?MODULE,local_tail,1},[],[global]),
- ?line [1,1] = lambda_slave(LocalTail),
- ?line ?NM,
- ?line 1 = erlang:trace_pattern({?MODULE,exported_wrap,1},[],[global]),
- ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
- ?line ?CT(?MODULE,exported_wrap,[1]),
- ?line 1 = erlang:trace_pattern({?MODULE,exported_wrap,1},[],[local]),
- ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
- ?line ?CT(?MODULE,exported_wrap,[1]),
- ?line ?RT(?MODULE,slave,2),
- ?line 1 = erlang:trace_pattern({erlang,hash,2},[],[local]),
- ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
- ?line ?CT(?MODULE,exported_wrap,[1]),
- ?line ?CT(erlang,hash,[1,1]),
- ?line ?RT(?MODULE,local_tail,1),
- ?line ?RT(?MODULE,slave,2),
- ?line erlang:trace(Pid,true,[timestamp]),
- ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
- ?line ?CTT(?MODULE,exported_wrap,[1]),
- ?line ?CTT(erlang,hash,[1,1]),
- ?line ?RTT(?MODULE,local_tail,1),
- ?line ?RTT(?MODULE,slave,2),
- ?line erlang:trace(Pid,false,[return_to,timestamp]),
- ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
- ?line ?CT(?MODULE,exported_wrap,[1]),
- ?line ?CT(erlang,hash,[1,1]),
- ?line erlang:trace(Pid,true,[return_to]),
- ?line 1 = erlang:trace_pattern({erlang,hash,2},[],[]),
- ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
- ?line ?CT(?MODULE,exported_wrap,[1]),
- ?line ?CT(erlang,hash,[1,1]),
- ?line ?RT(?MODULE,slave,2),
- ?line 1 = erlang:trace_pattern({?MODULE,exported_wrap,1},[],[]),
- ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
- ?line ?CT(?MODULE,exported_wrap,[1]),
- ?line ?CT(erlang,hash,[1,1]),
- ?line shutdown(),
- ?line erlang:trace_pattern({'_','_','_'},false,[local]),
- ?line N = erlang:trace_pattern({erlang,'_','_'},true,[local]),
- ?line case erlang:trace_pattern({erlang,'_','_'},false,[local]) of
- N ->
- ok;
- Else ->
- exit({number_mismatch, {expected, N}, {got, Else}})
- end,
- ?line case erlang:trace_pattern({erlang,'_','_'},false,[local]) of
- N ->
- ok;
- Else2 ->
- exit({number_mismatch, {expected, N}, {got, Else2}})
- end,
- ?line M = erlang:trace_pattern({erlang,'_','_'},true,[]),
- ?line case erlang:trace_pattern({erlang,'_','_'},false,[]) of
- M ->
- ok;
- Else3 ->
- exit({number_mismatch, {expected, N}, {got, Else3}})
- end,
- ?line case erlang:trace_pattern({erlang,'_','_'},false,[]) of
- M ->
- ok;
- Else4 ->
- exit({number_mismatch, {expected, N}, {got, Else4}})
- end,
- ?line ?NM,
+ Pid = setup([call]),
+ 1 = erlang:trace_pattern({?MODULE,local_tail,1},[],[local]),
+ erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
+ LocalTail = fun() ->
+ local_tail(1)
+ end,
+ [1,1] = lambda_slave(LocalTail),
+ ?CT(?MODULE,local_tail,[1]),
+ erlang:trace(Pid,true,[return_to]),
+ [1,1] = lambda_slave(LocalTail),
+ ?CT(?MODULE,local_tail,[1]),
+ ?RT(?MODULE,_,_),
+ 0 = erlang:trace_pattern({?MODULE,local_tail,1},[],[global]),
+ [1,1] = lambda_slave(LocalTail),
+ ?NM,
+ 1 = erlang:trace_pattern({?MODULE,exported_wrap,1},[],[global]),
+ [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
+ ?CT(?MODULE,exported_wrap,[1]),
+ 1 = erlang:trace_pattern({?MODULE,exported_wrap,1},[],[local]),
+ [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
+ ?CT(?MODULE,exported_wrap,[1]),
+ ?RT(?MODULE,slave,2),
+ 1 = erlang:trace_pattern({erlang,hash,2},[],[local]),
+ [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
+ ?CT(?MODULE,exported_wrap,[1]),
+ ?CT(erlang,hash,[1,1]),
+ ?RT(?MODULE,local_tail,1),
+ ?RT(?MODULE,slave,2),
+ erlang:trace(Pid,true,[timestamp]),
+ [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
+ ?CTT(?MODULE,exported_wrap,[1]),
+ ?CTT(erlang,hash,[1,1]),
+ ?RTT(?MODULE,local_tail,1),
+ ?RTT(?MODULE,slave,2),
+ erlang:trace(Pid,false,[return_to,timestamp]),
+ [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
+ ?CT(?MODULE,exported_wrap,[1]),
+ ?CT(erlang,hash,[1,1]),
+ erlang:trace(Pid,true,[return_to]),
+ 1 = erlang:trace_pattern({erlang,hash,2},[],[]),
+ [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
+ ?CT(?MODULE,exported_wrap,[1]),
+ ?CT(erlang,hash,[1,1]),
+ ?RT(?MODULE,slave,2),
+ 1 = erlang:trace_pattern({?MODULE,exported_wrap,1},[],[]),
+ [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]),
+ ?CT(?MODULE,exported_wrap,[1]),
+ ?CT(erlang,hash,[1,1]),
+ shutdown(),
+ erlang:trace_pattern({'_','_','_'},false,[local]),
+ N = erlang:trace_pattern({erlang,'_','_'},true,[local]),
+ case erlang:trace_pattern({erlang,'_','_'},false,[local]) of
+ N ->
+ ok;
+ Else ->
+ exit({number_mismatch, {expected, N}, {got, Else}})
+ end,
+ case erlang:trace_pattern({erlang,'_','_'},false,[local]) of
+ N ->
+ ok;
+ Else2 ->
+ exit({number_mismatch, {expected, N}, {got, Else2}})
+ end,
+ M = erlang:trace_pattern({erlang,'_','_'},true,[]),
+ case erlang:trace_pattern({erlang,'_','_'},false,[]) of
+ M ->
+ ok;
+ Else3 ->
+ exit({number_mismatch, {expected, N}, {got, Else3}})
+ end,
+ case erlang:trace_pattern({erlang,'_','_'},false,[]) of
+ M ->
+ ok;
+ Else4 ->
+ exit({number_mismatch, {expected, N}, {got, Else4}})
+ end,
+ ?NM,
ok.
systematic_on_off(Config) when is_list(Config) ->
@@ -634,12 +568,12 @@ systematic_on_off_1(Local) ->
verify_trace_info(Global, Local) ->
case erlang:trace_info({?MODULE,exported_wrap,1}, all) of
- {all,false} ->
- false = Global,
- [] = Local;
- {all,Ps} ->
- io:format("~p\n", [Ps]),
- [verify_trace_info(P, Global, Local) || P <- Ps]
+ {all,false} ->
+ false = Global,
+ [] = Local;
+ {all,Ps} ->
+ io:format("~p\n", [Ps]),
+ [verify_trace_info(P, Global, Local) || P <- Ps]
end,
global_call(Global, Local),
local_call(Local),
@@ -651,12 +585,10 @@ verify_trace_info({match_spec,[]}, _, _) -> ok;
verify_trace_info({meta_match_spec,[]}, _, _) -> ok;
verify_trace_info({LocalFlag,Bool}, _, Local) when is_boolean(Bool) ->
try
- Bool = lists:member(LocalFlag, Local)
+ Bool = lists:member(LocalFlag, Local)
catch
- error:_ ->
- io:format("Line ~p: {~p,~p}, false, ~p\n",
- [?LINE,LocalFlag,Bool,Local]),
- ?t:fail()
+ error:_ ->
+ ct:fail("Line ~p: {~p,~p}, false, ~p\n", [?LINE,LocalFlag,Bool,Local])
end;
verify_trace_info({meta,Pid}, false, Local) when is_pid(Pid) ->
true = lists:member(meta, Local);
@@ -668,10 +600,10 @@ verify_trace_info({call_count,_}, false, Local) ->
global_call(Global, Local) ->
apply_slave(?MODULE, exported_wrap, [global_call]),
case Global of
- false ->
- recv_local_call(Local, [global_call]);
- true ->
- ?CT(?MODULE, exported_wrap, [global_call])
+ false ->
+ recv_local_call(Local, [global_call]);
+ true ->
+ ?CT(?MODULE, exported_wrap, [global_call])
end.
local_call(Local) ->
@@ -680,16 +612,16 @@ local_call(Local) ->
recv_local_call(Local, Args) ->
case lists:member(local, Local) of
- false ->
- ok;
- true ->
- ?CT(?MODULE, exported_wrap, Args)
+ false ->
+ ok;
+ true ->
+ ?CT(?MODULE, exported_wrap, Args)
end,
case lists:member(meta, Local) of
- false ->
- ok;
- true ->
- ?CTT(?MODULE, exported_wrap, Args)
+ false ->
+ ok;
+ true ->
+ ?CTT(?MODULE, exported_wrap, Args)
end,
ok.
@@ -698,99 +630,99 @@ combinations([_]=One) ->
combinations([H|T]) ->
Cs = combinations(T),
[[H|C] || C <- Cs] ++ Cs.
-
+
stack_grow_test() ->
- ?line setup([call,return_to]),
- ?line 1 = erlang:trace_pattern({?MODULE,loop,4},
- [{'_',[],[{return_trace}]}],[local]),
- ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
- ?line Num = 1 bsl 15,
- ?line Fun =
- fun(_F,0) -> ok;
- (F,N) ->
- receive _A ->
- receive _B ->
- receive _C ->
- F(F,N-1)
- end
- end
- end
- end,
- ?line apply_slave_async(?MODULE,loop,[{hej,hopp},[a,b,c],4.5,Num]),
- ?line Fun(Fun,Num + 1),
- ?line ?NM,
+ setup([call,return_to]),
+ 1 = erlang:trace_pattern({?MODULE,loop,4},
+ [{'_',[],[{return_trace}]}],[local]),
+ erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
+ Num = 1 bsl 15,
+ Fun =
+ fun(_F,0) -> ok;
+ (F,N) ->
+ receive _A ->
+ receive _B ->
+ receive _C ->
+ F(F,N-1)
+ end
+ end
+ end
+ end,
+ apply_slave_async(?MODULE,loop,[{hej,hopp},[a,b,c],4.5,Num]),
+ Fun(Fun,Num + 1),
+ ?NM,
ok.
info_test() ->
- ?line Flags1 = lists:sort([call,return_to]),
- ?line Pid = setup(Flags1),
- ?line Prog = [{['$1'],[{is_integer,'$1'}],[{message, false}]},
- {'_',[],[]}],
- ?line erlang:trace_pattern({?MODULE,exported_wrap,1},Prog,[local]),
- ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
- ?line Self = self(),
- ?line {flags,L} = erlang:trace_info(Pid,flags),
- ?line case lists:sort(L) of
- Flags1 ->
- ok;
- Wrong1 ->
- exit({bad_result, {erlang,trace_info,[Pid,flags]},
- {expected, Flags1}, {got, Wrong1}})
- end,
- ?line {tracer,Tracer} = erlang:trace_info(Pid,tracer),
- ?line case Tracer of
- Self ->
- ok;
- Wrong2 ->
- exit({bad_result, {erlang,trace_info,[Pid,tracer]},
- {expected, Self}, {got, Wrong2}})
- end,
- ?line {traced,local} = erlang:trace_info({?MODULE,exported_wrap,1},traced),
- ?line {match_spec, MS} =
- erlang:trace_info({?MODULE,exported_wrap,1},match_spec),
- ?line case MS of
- Prog ->
- ok;
- Wrong3 ->
- exit({bad_result, {erlang,trace_info,
- [{?MODULE,exported_wrap,1},
- match_spec]},
- {expected, Prog}, {got, Wrong3}})
- end,
- ?line erlang:garbage_collect(self()),
- ?line receive
- after 1 ->
- ok
- end,
- ?line io:format("~p~n",[MS]),
- ?line {match_spec,MS2} =
- erlang:trace_info({?MODULE,exported_wrap,1},match_spec),
- ?line io:format("~p~n",[MS2]),
- ?line erlang:trace_pattern({?MODULE,exported_wrap,1},[],[]),
- ?line {traced,global} =
- erlang:trace_info({?MODULE,exported_wrap,1},traced),
- ?line {match_spec,[]} =
- erlang:trace_info({?MODULE,exported_wrap,1},match_spec),
- ?line {traced,undefined} =
- erlang:trace_info({?MODULE,exported_wrap,2},traced),
- ?line {match_spec,undefined} =
- erlang:trace_info({?MODULE,exported_wrap,2},match_spec),
- ?line {traced,false} = erlang:trace_info({?MODULE,exported,1},traced),
- ?line {match_spec,false} =
- erlang:trace_info({?MODULE,exported,1},match_spec),
- ?line shutdown(),
+ Flags1 = lists:sort([call,return_to]),
+ Pid = setup(Flags1),
+ Prog = [{['$1'],[{is_integer,'$1'}],[{message, false}]},
+ {'_',[],[]}],
+ erlang:trace_pattern({?MODULE,exported_wrap,1},Prog,[local]),
+ erlang:trace_pattern({?MODULE,slave,'_'},false,[local]),
+ Self = self(),
+ {flags,L} = erlang:trace_info(Pid,flags),
+ case lists:sort(L) of
+ Flags1 ->
+ ok;
+ Wrong1 ->
+ exit({bad_result, {erlang,trace_info,[Pid,flags]},
+ {expected, Flags1}, {got, Wrong1}})
+ end,
+ {tracer,Tracer} = erlang:trace_info(Pid,tracer),
+ case Tracer of
+ Self ->
+ ok;
+ Wrong2 ->
+ exit({bad_result, {erlang,trace_info,[Pid,tracer]},
+ {expected, Self}, {got, Wrong2}})
+ end,
+ {traced,local} = erlang:trace_info({?MODULE,exported_wrap,1},traced),
+ {match_spec, MS} =
+ erlang:trace_info({?MODULE,exported_wrap,1},match_spec),
+ case MS of
+ Prog ->
+ ok;
+ Wrong3 ->
+ exit({bad_result, {erlang,trace_info,
+ [{?MODULE,exported_wrap,1},
+ match_spec]},
+ {expected, Prog}, {got, Wrong3}})
+ end,
+ erlang:garbage_collect(self()),
+ receive
+ after 1 ->
+ ok
+ end,
+ io:format("~p~n",[MS]),
+ {match_spec,MS2} =
+ erlang:trace_info({?MODULE,exported_wrap,1},match_spec),
+ io:format("~p~n",[MS2]),
+ erlang:trace_pattern({?MODULE,exported_wrap,1},[],[]),
+ {traced,global} =
+ erlang:trace_info({?MODULE,exported_wrap,1},traced),
+ {match_spec,[]} =
+ erlang:trace_info({?MODULE,exported_wrap,1},match_spec),
+ {traced,undefined} =
+ erlang:trace_info({?MODULE,exported_wrap,2},traced),
+ {match_spec,undefined} =
+ erlang:trace_info({?MODULE,exported_wrap,2},match_spec),
+ {traced,false} = erlang:trace_info({?MODULE,exported,1},traced),
+ {match_spec,false} =
+ erlang:trace_info({?MODULE,exported,1},match_spec),
+ shutdown(),
ok.
delete_test(Config) ->
- ?line Priv = ?config(priv_dir, Config),
- ?line Data = ?config(data_dir, Config),
- ?line File = filename:join(Data, "trace_local_dummy"),
- ?line {ok,trace_local_dummy} = c:c(File, [{outdir,Priv}]),
- ?line code:purge(trace_local_dummy),
- ?line code:delete(trace_local_dummy),
- ?line 0 = erlang:trace_pattern({trace_local_dummy,'_','_'},true,[local]),
- ?line ?NM,
+ Priv = proplists:get_value(priv_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "trace_local_dummy"),
+ {ok,trace_local_dummy} = c:c(File, [{outdir,Priv}]),
+ code:purge(trace_local_dummy),
+ code:delete(trace_local_dummy),
+ 0 = erlang:trace_pattern({trace_local_dummy,'_','_'},true,[local]),
+ ?NM,
ok.
@@ -798,34 +730,34 @@ delete_test(Config) ->
%%% exception_test %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
exception_test(Opts) ->
- ?line {ProcFlags,PatFlags} =
- case proplists:get_bool(meta, Opts) of
- true -> {[timestamp],[meta]};
- false -> {[call,return_to,timestamp],[local]}
- end,
- ?line case proplists:get_bool(nocatch, Opts) of
- false ->
- ?line Exceptions = exceptions(),
- ?line exception_test_setup(ProcFlags, PatFlags),
- ?line lists:foreach(
- fun ({Func,Args}) ->
- ?line exception_test(Opts, Func, Args)
- end,
- Exceptions),
- ?line shutdown();
- true ->
- ?line Exceptions = exceptions(),
- ?line lists:foreach(
- fun ({Func,Args}) ->
- ?line exception_test_setup(
- [procs|ProcFlags],
- PatFlags),
- ?line exception_test(Opts, Func, Args),
- ?line shutdown()
- end,
- Exceptions)
- end,
- ?line ok.
+ {ProcFlags,PatFlags} =
+ case proplists:get_bool(meta, Opts) of
+ true -> {[timestamp],[meta]};
+ false -> {[call,return_to,timestamp],[local]}
+ end,
+ case proplists:get_bool(nocatch, Opts) of
+ false ->
+ Exceptions = exceptions(),
+ exception_test_setup(ProcFlags, PatFlags),
+ lists:foreach(
+ fun ({Func,Args}) ->
+ exception_test(Opts, Func, Args)
+ end,
+ Exceptions),
+ shutdown();
+ true ->
+ Exceptions = exceptions(),
+ lists:foreach(
+ fun ({Func,Args}) ->
+ exception_test_setup(
+ [procs|ProcFlags],
+ PatFlags),
+ exception_test(Opts, Func, Args),
+ shutdown()
+ end,
+ Exceptions)
+ end,
+ ok.
exceptions() ->
Ref = make_ref(),
@@ -848,65 +780,65 @@ exceptions() ->
{{?MODULE,lists_reverse}, [LL,[]]}].
exception_test_setup(ProcFlags, PatFlags) ->
- ?line Pid = setup(ProcFlags),
- ?line io:format("=== exception_test_setup(~p, ~p): ~p~n",
- [ProcFlags,PatFlags,Pid]),
- ?line Mprog = [{'_',[],[{exception_trace}]}],
- ?line erlang:trace_pattern({?MODULE,'_','_'}, Mprog, PatFlags),
- ?line erlang:trace_pattern({?MODULE,slave,'_'},false,PatFlags),
- ?line [1,1,1,1,1] =
- [erlang:trace_pattern({erlang,F,A}, Mprog, PatFlags)
- || {F,A} <- [{exit,1},{error,1},{error,2},{throw,1},{'++',2}]],
- ?line 1 = erlang:trace_pattern({lists,reverse,2}, Mprog, PatFlags),
- ?line ok.
+ Pid = setup(ProcFlags),
+ io:format("=== exception_test_setup(~p, ~p): ~p~n",
+ [ProcFlags,PatFlags,Pid]),
+ Mprog = [{'_',[],[{exception_trace}]}],
+ erlang:trace_pattern({?MODULE,'_','_'}, Mprog, PatFlags),
+ erlang:trace_pattern({?MODULE,slave,'_'},false,PatFlags),
+ [1,1,1,1,1] =
+ [erlang:trace_pattern({erlang,F,A}, Mprog, PatFlags)
+ || {F,A} <- [{exit,1},{error,1},{error,2},{throw,1},{'++',2}]],
+ 1 = erlang:trace_pattern({lists,reverse,2}, Mprog, PatFlags),
+ ok.
-record(exc_opts, {nocatch=false, meta=false}).
exception_test(Opts, Func0, Args0) ->
- ?line io:format("=== exception_test(~p, ~p, ~p)~n",
- [Opts,Func0,abbr(Args0)]),
- ?line Apply = proplists:get_bool(apply, Opts),
- ?line Function = proplists:get_bool(function, Opts),
- ?line Nocatch = proplists:get_bool(nocatch, Opts),
- ?line Meta = proplists:get_bool(meta, Opts),
- ?line ExcOpts = #exc_opts{nocatch=Nocatch,meta=Meta},
-
+ io:format("=== exception_test(~p, ~p, ~p)~n",
+ [Opts,Func0,abbr(Args0)]),
+ Apply = proplists:get_bool(apply, Opts),
+ Function = proplists:get_bool(function, Opts),
+ Nocatch = proplists:get_bool(nocatch, Opts),
+ Meta = proplists:get_bool(meta, Opts),
+ ExcOpts = #exc_opts{nocatch=Nocatch,meta=Meta},
+
%% Func0 and Args0 are for the innermost call, now we will
%% wrap them in wrappers...
- ?line {Func1,Args1} =
- case Function of
- true -> {fun exc/2,[Func0,Args0]};
- false -> {Func0,Args0}
- end,
-
- ?line {Func,Args} =
- case Apply of
- true -> {{erlang,apply},[Func1,Args1]};
- false -> {Func1,Args1}
- end,
-
- ?line R1 = exc_slave(ExcOpts, Func, Args),
- ?line Stack2 = [{?MODULE,exc_top,3,[]},{?MODULE,slave,2,[]}],
- ?line Stack3 = [{?MODULE,exc,2,[]}|Stack2],
- ?line Rs =
- case x_exc_top(ExcOpts, Func, Args) of % Emulation
- {crash,{Reason,Stack}}=R when is_list(Stack) ->
- [R,
- {crash,{Reason,Stack++Stack2}},
- {crash,{Reason,Stack++Stack3}}];
- R ->
- [R]
- end,
- ?line exception_validate(R1, Rs),
- ?line case R1 of
- {crash,Crash} ->
- ?line expect({trace_ts,exit,Crash});
- _ when not Meta ->
- ?line expect({rtt,{?MODULE,slave,2}});
- _ ->
- ok
- end,
- ?line expect({nm}).
+ {Func1,Args1} =
+ case Function of
+ true -> {fun exc/2,[Func0,Args0]};
+ false -> {Func0,Args0}
+ end,
+
+ {Func,Args} =
+ case Apply of
+ true -> {{erlang,apply},[Func1,Args1]};
+ false -> {Func1,Args1}
+ end,
+
+ R1 = exc_slave(ExcOpts, Func, Args),
+ Stack2 = [{?MODULE,exc_top,3,[]},{?MODULE,slave,2,[]}],
+ Stack3 = [{?MODULE,exc,2,[]}|Stack2],
+ Rs =
+ case x_exc_top(ExcOpts, Func, Args) of % Emulation
+ {crash,{Reason,Stack}}=R when is_list(Stack) ->
+ [R,
+ {crash,{Reason,Stack++Stack2}},
+ {crash,{Reason,Stack++Stack3}}];
+ R ->
+ [R]
+ end,
+ exception_validate(R1, Rs),
+ case R1 of
+ {crash,Crash} ->
+ expect({trace_ts,exit,Crash});
+ _ when not Meta ->
+ expect({rtt,{?MODULE,slave,2}});
+ _ ->
+ ok
+ end,
+ expect({nm}).
exception_validate(R0, Rs0) ->
R = clean_location(R0),
@@ -915,16 +847,16 @@ exception_validate(R0, Rs0) ->
exception_validate_1(R1, [R2|Rs]) ->
case [R1|R2] of
- [R|R] ->
- ok;
- [{crash,{badarg,[{lists,reverse,[L1a,L1b],_}|T]}}|
- {crash,{badarg,[{lists,reverse,[L2a,L2b],_}|T]}}] ->
- same({crash,{badarg,[{lists,reverse,
- [lists:reverse(L1b, L1a),[]],[]}|T]}},
- {crash,{badarg,[{lists,reverse,
- [lists:reverse(L2b, L2a),[]],[]}|T]}});
- _ when is_list(Rs), Rs =/= [] ->
- exception_validate(R1, Rs)
+ [R|R] ->
+ ok;
+ [{crash,{badarg,[{lists,reverse,[L1a,L1b],_}|T]}}|
+ {crash,{badarg,[{lists,reverse,[L2a,L2b],_}|T]}}] ->
+ same({crash,{badarg,[{lists,reverse,
+ [lists:reverse(L1b, L1a),[]],[]}|T]}},
+ {crash,{badarg,[{lists,reverse,
+ [lists:reverse(L2b, L2a),[]],[]}|T]}});
+ _ when is_list(Rs), Rs =/= [] ->
+ exception_validate(R1, Rs)
end.
clean_location({crash,{Reason,Stk0}}) ->
@@ -942,20 +874,20 @@ concurrency(_Config) ->
%% if an aligned word-sized write is not atomic.
Ps0 = [spawn_monitor(fun() -> infinite_loop() end) ||
- _ <- lists:seq(1, 2*N)],
+ _ <- lists:seq(1, 2*N)],
OnAndOff = fun() -> concurrency_on_and_off() end,
Ps1 = [spawn_monitor(OnAndOff)|Ps0],
- ?t:sleep(1000),
+ timer:sleep(1000),
%% Now spawn off N more processes that turn on off and off
%% a local trace pattern.
Ps = [spawn_monitor(OnAndOff) || _ <- lists:seq(1, N)] ++ Ps1,
- ?t:sleep(1000),
+ timer:sleep(1000),
%% Clean up.
[exit(Pid, kill) || {Pid,_} <- Ps],
[receive
- {'DOWN',Ref,process,Pid,killed} -> ok
+ {'DOWN',Ref,process,Pid,killed} -> ok
end || {Pid,Ref} <- Ps],
erlang:trace_pattern({?MODULE,infinite_loop,0}, false, [local]),
ok.
@@ -999,16 +931,16 @@ local_tail(Val) ->
exc_top(ExcOpts, Func, Args) ->
case ExcOpts#exc_opts.nocatch of
- false ->
- try exc_jump(Func, Args) of
- Value ->
- {value,Value}
- catch
- Class:Reason ->
- {Class,Reason}
- end;
- true ->
- {value,exc_jump(Func, Args)}
+ false ->
+ try exc_jump(Func, Args) of
+ Value ->
+ {value,Value}
+ catch
+ Class:Reason ->
+ {Class,Reason}
+ end;
+ true ->
+ {value,exc_jump(Func, Args)}
end.
%% x_* functions emulate the non-x_* ones.
@@ -1017,42 +949,42 @@ exc_top(ExcOpts, Func, Args) ->
%% The only possible place for exception
%% is below exc/2.
x_exc_top(ExcOpts, Func, Args) ->
- ?line Rtt = not ExcOpts#exc_opts.meta,
- ?line expect({ctt,{?MODULE,exc_top},[ExcOpts,Func,Args]}),
- ?line case x_exc_jump(ExcOpts, Func, Args) of
- Result when not ExcOpts#exc_opts.nocatch ->
- ?line expect([Rtt,{rtt,{?MODULE,exc_top,3}},
- ?LINE,{rft,{?MODULE,exc_top,3},Result}]),
- ?line Result;
- {value,_}=Result ->
-
- ?line expect([Rtt,{rtt,{?MODULE,exc_top,3}},
- ?LINE,{rft,{?MODULE,exc_top,3},Result}]),
- ?line Result;
- {exit,Reason}=CR ->
- ?line expect({eft,{?MODULE,exc_top,3},CR}),
- ?line {crash,Reason};
- {error,Reason}=CR ->
- ?line expect({eft,{?MODULE,exc_top,3},CR}),
- ?line {crash,{Reason,x_exc_stacktrace()}};
- CR ->
- ?line expect({eft,{?MODULE,exc_top,3},CR}),
- ?line {crash,CR}
- end.
+ Rtt = not ExcOpts#exc_opts.meta,
+ expect({ctt,{?MODULE,exc_top},[ExcOpts,Func,Args]}),
+ case x_exc_jump(ExcOpts, Func, Args) of
+ Result when not ExcOpts#exc_opts.nocatch ->
+ expect([Rtt,{rtt,{?MODULE,exc_top,3}},
+ ?LINE,{rft,{?MODULE,exc_top,3},Result}]),
+ Result;
+ {value,_}=Result ->
+
+ expect([Rtt,{rtt,{?MODULE,exc_top,3}},
+ ?LINE,{rft,{?MODULE,exc_top,3},Result}]),
+ Result;
+ {exit,Reason}=CR ->
+ expect({eft,{?MODULE,exc_top,3},CR}),
+ {crash,Reason};
+ {error,Reason}=CR ->
+ expect({eft,{?MODULE,exc_top,3},CR}),
+ {crash,{Reason,x_exc_stacktrace()}};
+ CR ->
+ expect({eft,{?MODULE,exc_top,3},CR}),
+ {crash,CR}
+ end.
exc_jump(Func, Args) ->
exc(Func, Args, jump).
x_exc_jump(ExcOpts, Func, Args) ->
- ?line expect({ctt,{?MODULE,exc_jump},[Func,Args]}),
- ?line case x_exc(ExcOpts, Func, Args, jump) of
- {value,Value}=Result ->
- ?line expect({rft,{?MODULE,exc_jump,2},Value}),
- ?line Result;
- CR ->
- ?line expect({eft,{?MODULE,exc_jump,2},CR}),
- ?line CR
- end.
+ expect({ctt,{?MODULE,exc_jump},[Func,Args]}),
+ case x_exc(ExcOpts, Func, Args, jump) of
+ {value,Value}=Result ->
+ expect({rft,{?MODULE,exc_jump,2},Value}),
+ Result;
+ CR ->
+ expect({eft,{?MODULE,exc_jump,2},CR}),
+ CR
+ end.
exc(Func, Args, jump) ->
exc(Func, Args, do);
@@ -1060,25 +992,25 @@ exc(Func, Args, do) ->
exc(Func, Args).
x_exc(ExcOpts, Func, Args, jump) ->
- ?line expect({ctt,{?MODULE,exc},[Func,Args,jump]}),
- ?line case x_exc(ExcOpts, Func, Args, do) of
- {value,Value}=Result ->
- ?line expect({rft,{?MODULE,exc,3},Value}),
- ?line Result;
- CR ->
- ?line expect({eft,{?MODULE,exc,3},CR}),
- ?line CR
- end;
+ expect({ctt,{?MODULE,exc},[Func,Args,jump]}),
+ case x_exc(ExcOpts, Func, Args, do) of
+ {value,Value}=Result ->
+ expect({rft,{?MODULE,exc,3},Value}),
+ Result;
+ CR ->
+ expect({eft,{?MODULE,exc,3},CR}),
+ CR
+ end;
x_exc(ExcOpts, Func, Args, do) ->
- ?line expect({ctt,{?MODULE,exc},[Func,Args,do]}),
- ?line case x_exc(ExcOpts, Func, Args) of
- {value,Value}=Result ->
- ?line expect({rft,{?MODULE,exc,3},Value}),
- ?line Result;
- CR ->
- ?line expect({eft,{?MODULE,exc,3},CR}),
- ?line CR
- end.
+ expect({ctt,{?MODULE,exc},[Func,Args,do]}),
+ case x_exc(ExcOpts, Func, Args) of
+ {value,Value}=Result ->
+ expect({rft,{?MODULE,exc,3},Value}),
+ Result;
+ CR ->
+ expect({eft,{?MODULE,exc,3},CR}),
+ CR
+ end.
exc({erlang,apply}, [{M,F},A]) ->
erlang:apply(M, F, id(A));
@@ -1108,114 +1040,114 @@ exc(Func, [A,B]) when is_function(Func, 2) ->
Func(A, id(B)).
x_exc(ExcOpts, {erlang,apply}=Func0, [{_,_}=Func,Args]=Args0) ->
- ?line expect({ctt,{?MODULE,exc},[Func0,Args0]}),
- ?line x_exc_body(ExcOpts, Func, Args, true);
+ expect({ctt,{?MODULE,exc},[Func0,Args0]}),
+ x_exc_body(ExcOpts, Func, Args, true);
x_exc(ExcOpts, {erlang,apply}=Func0, [Func,Args]=Args0)
when is_function(Func, 2)->
- ?line expect({ctt,{?MODULE,exc},[Func0,Args0]}),
- ?line x_exc_func(ExcOpts, Func, Args, Args);
+ expect({ctt,{?MODULE,exc},[Func0,Args0]}),
+ x_exc_func(ExcOpts, Func, Args, Args);
x_exc(ExcOpts, {_,_}=Func, Args) ->
- ?line expect({ctt,{?MODULE,exc},[Func,Args]}),
- ?line x_exc_body(ExcOpts, Func, Args, false);
+ expect({ctt,{?MODULE,exc},[Func,Args]}),
+ x_exc_body(ExcOpts, Func, Args, false);
x_exc(ExcOpts, Func0, [_,Args]=Args0)
when is_function(Func0, 2) ->
- ?line expect({ctt,{?MODULE,exc},[Func0,Args0]}),
- ?line x_exc_func(ExcOpts, Func0, Args0, Args).
+ expect({ctt,{?MODULE,exc},[Func0,Args0]}),
+ x_exc_func(ExcOpts, Func0, Args0, Args).
x_exc_func(ExcOpts, Func, [Func1,Args1]=Args, Id) ->
%% Assumes the called fun =:= fun exc/2,
%% will utterly fail otherwise.
- ?line Rtt = not ExcOpts#exc_opts.meta,
- ?line {module,M} = erlang:fun_info(Func, module),
- ?line {name,F} = erlang:fun_info(Func, name),
- ?line expect([{ctt,{?MODULE,id},[Id]},
- ?LINE,{rft,{?MODULE,id,1},Id},
- ?LINE,Rtt,{rtt,{?MODULE,exc,2}},
- ?LINE,{ctt,{M,F},Args}]),
- ?line case x_exc(ExcOpts, Func1, Args1) of
- {value,Value}=Result ->
- ?line expect([{rft,{M,F,2},Value},
- ?LINE,{rft,{?MODULE,exc,2},Value}]),
- ?line Result;
- CR ->
- ?line expect([{eft,{M,F,2},CR},
- ?LINE,{eft,{?MODULE,exc,2},CR}]),
- ?line CR
- end.
+ Rtt = not ExcOpts#exc_opts.meta,
+ {module,M} = erlang:fun_info(Func, module),
+ {name,F} = erlang:fun_info(Func, name),
+ expect([{ctt,{?MODULE,id},[Id]},
+ ?LINE,{rft,{?MODULE,id,1},Id},
+ ?LINE,Rtt,{rtt,{?MODULE,exc,2}},
+ ?LINE,{ctt,{M,F},Args}]),
+ case x_exc(ExcOpts, Func1, Args1) of
+ {value,Value}=Result ->
+ expect([{rft,{M,F,2},Value},
+ ?LINE,{rft,{?MODULE,exc,2},Value}]),
+ Result;
+ CR ->
+ expect([{eft,{M,F,2},CR},
+ ?LINE,{eft,{?MODULE,exc,2},CR}]),
+ CR
+ end.
x_exc_body(ExcOpts, {M,F}=Func, Args, Apply) ->
- ?line Nocatch = ExcOpts#exc_opts.nocatch,
- ?line Rtt = not ExcOpts#exc_opts.meta,
- ?line Id = case Apply of
- true -> Args;
- false -> lists:last(Args)
- end,
- ?line expect([{ctt,{?MODULE,id},[Id]},
- ?LINE,{rft,{?MODULE,id,1},Id},
- ?LINE,Rtt,{rtt,{?MODULE,exc,2}},
- ?LINE,{ctt,{M,F},Args}]),
- ?line Arity = length(Args),
- ?line try exc(Func, Args) of
- Value ->
- ?line x_exc_value(Rtt, M, F, Args, Arity, Value),
- ?line case expect() of
- {rtt,{M,F,Arity}} when Rtt, Apply ->
- %% We may get the above when
- %% applying a BIF.
- ?line expect({rft,{?MODULE,exc,2},Value});
- {rtt,{?MODULE,exc,2}} when Rtt, not Apply ->
- %% We may get the above when
- %% calling a BIF.
- ?line expect({rft,{?MODULE,exc,2},Value});
- {rft,{?MODULE,exc,2},Value} ->
- ?line ok
- end,
- ?line {value,Value}
- catch
- Thrown when Nocatch ->
- ?line CR = {error,{nocatch,Thrown}},
- ?line x_exc_exception(Rtt, M, F, Args, Arity, CR),
- ?line expect({eft,{?MODULE,exc,2},CR}),
- ?line CR;
- Class:Reason ->
- ?line CR = {Class,Reason},
- ?line x_exc_exception(Rtt, M, F, Args, Arity, CR),
- ?line expect({eft,{?MODULE,exc,2},CR}),
- ?line CR
- end.
+ Nocatch = ExcOpts#exc_opts.nocatch,
+ Rtt = not ExcOpts#exc_opts.meta,
+ Id = case Apply of
+ true -> Args;
+ false -> lists:last(Args)
+ end,
+ expect([{ctt,{?MODULE,id},[Id]},
+ ?LINE,{rft,{?MODULE,id,1},Id},
+ ?LINE,Rtt,{rtt,{?MODULE,exc,2}},
+ ?LINE,{ctt,{M,F},Args}]),
+ Arity = length(Args),
+ try exc(Func, Args) of
+ Value ->
+ x_exc_value(Rtt, M, F, Args, Arity, Value),
+ case expect() of
+ {rtt,{M,F,Arity}} when Rtt, Apply ->
+ %% We may get the above when
+ %% applying a BIF.
+ expect({rft,{?MODULE,exc,2},Value});
+ {rtt,{?MODULE,exc,2}} when Rtt, not Apply ->
+ %% We may get the above when
+ %% calling a BIF.
+ expect({rft,{?MODULE,exc,2},Value});
+ {rft,{?MODULE,exc,2},Value} ->
+ ok
+ end,
+ {value,Value}
+ catch
+ Thrown when Nocatch ->
+ CR = {error,{nocatch,Thrown}},
+ x_exc_exception(Rtt, M, F, Args, Arity, CR),
+ expect({eft,{?MODULE,exc,2},CR}),
+ CR;
+ Class:Reason ->
+ CR = {Class,Reason},
+ x_exc_exception(Rtt, M, F, Args, Arity, CR),
+ expect({eft,{?MODULE,exc,2},CR}),
+ CR
+ end.
x_exc_value(Rtt, ?MODULE, lists_reverse, [La,Lb], 2, R) ->
- ?line L = lists:reverse(Lb, La),
- ?line expect([fun ({ctt,{lists,reverse},[L1,L2]}) ->
- ?line same(L, lists:reverse(L2, L1)),
- ?line next;
- (Msg) ->
- ?line same({rft,{lists,reverse,2},R}, Msg),
- ?line same(R, lists:reverse(L, [])),
- ?line done
- end,
- ?LINE,Rtt,{rtt,{?MODULE,lists_reverse,2}},
- ?LINE,{rft,{?MODULE,lists_reverse,2},R}]);
+ L = lists:reverse(Lb, La),
+ expect([fun ({ctt,{lists,reverse},[L1,L2]}) ->
+ same(L, lists:reverse(L2, L1)),
+ next;
+ (Msg) ->
+ same({rft,{lists,reverse,2},R}, Msg),
+ same(R, lists:reverse(L, [])),
+ done
+ end,
+ ?LINE,Rtt,{rtt,{?MODULE,lists_reverse,2}},
+ ?LINE,{rft,{?MODULE,lists_reverse,2},R}]);
x_exc_value(_Rtt, M, F, _, Arity, Value) ->
- ?line expect({rft,{M,F,Arity},Value}).
+ expect({rft,{M,F,Arity},Value}).
x_exc_exception(_Rtt, ?MODULE, lists_reverse, [La,Lb], 2, CR) ->
- ?line L = lists:reverse(Lb, La),
- ?line expect([fun ({ctt,{lists,reverse},[L1,L2]}) ->
- ?line same(L, lists:reverse(L2, L1)),
- ?line next;
- (Msg) ->
- ?line same({eft,{lists,reverse,2},CR}, Msg),
- ?line done
- end,
- ?LINE,{eft,{?MODULE,lists_reverse,2},CR}]);
+ L = lists:reverse(Lb, La),
+ expect([fun ({ctt,{lists,reverse},[L1,L2]}) ->
+ same(L, lists:reverse(L2, L1)),
+ next;
+ (Msg) ->
+ same({eft,{lists,reverse,2},CR}, Msg),
+ done
+ end,
+ ?LINE,{eft,{?MODULE,lists_reverse,2},CR}]);
x_exc_exception(Rtt, ?MODULE, undef, [_], 1, {Class,Reason}=CR) ->
- ?line expect([{ctt,{erlang,Class},[Reason]},
- ?LINE,{eft,{erlang,Class,1},CR},
- ?LINE,Rtt,{rtt,{error_handler,crash,1}},
- ?LINE,{eft,{?MODULE,undef,1},CR}]);
+ expect([{ctt,{erlang,Class},[Reason]},
+ ?LINE,{eft,{erlang,Class,1},CR},
+ ?LINE,Rtt,{rtt,{error_handler,crash,1}},
+ ?LINE,{eft,{?MODULE,undef,1},CR}]);
x_exc_exception(_Rtt, M, F, _, Arity, CR) ->
- ?line expect({eft,{M,F,Arity},CR}).
+ expect({eft,{M,F,Arity},CR}).
x_exc_stacktrace() ->
x_exc_stacktrace(erlang:get_stacktrace()).
@@ -1252,24 +1184,24 @@ lists_reverse(A, B) ->
slave(Dest, Sync) ->
Dest ! Sync,
receive
- {From,Tag,{apply,M,F,A}} when is_pid(From) ->
- ?line ?dbgformat("Apply: ~p:~p/~p (~p)~n",[M,F,length(A),A]),
- ?line Res = apply(M,F,A),
- ?line ?dbgformat("done Apply: ~p:~p/~p (~p)~n",[M,F,length(A),A]),
- From ! {Tag,Res},
- slave(From, Tag);
- {From,Tag,{lambda,Fun}} when is_pid(From) ->
- Res = Fun(),
- From ! {Tag,Res},
- slave(From, Tag);
- {From,Tag,{exc_top,Catch,Func,Args}} when is_pid(From) ->
- ?line ?dbgformat("Exc: ~p ~p~p ~n",[Catch,Func,Args]),
- ?line Res = exc_top(Catch, Func, Args),
- ?line ?dbgformat("done Exc: ~p ~p~p ~n",[Catch,Func,Args]),
- From ! {Tag,Res},
- slave(From,Tag);
- die ->
- exit(normal)
+ {From,Tag,{apply,M,F,A}} when is_pid(From) ->
+ ?dbgformat("Apply: ~p:~p/~p (~p)~n",[M,F,length(A),A]),
+ Res = apply(M,F,A),
+ ?dbgformat("done Apply: ~p:~p/~p (~p)~n",[M,F,length(A),A]),
+ From ! {Tag,Res},
+ slave(From, Tag);
+ {From,Tag,{lambda,Fun}} when is_pid(From) ->
+ Res = Fun(),
+ From ! {Tag,Res},
+ slave(From, Tag);
+ {From,Tag,{exc_top,Catch,Func,Args}} when is_pid(From) ->
+ ?dbgformat("Exc: ~p ~p~p ~n",[Catch,Func,Args]),
+ Res = exc_top(Catch, Func, Args),
+ ?dbgformat("done Exc: ~p ~p~p ~n",[Catch,Func,Args]),
+ From ! {Tag,Res},
+ slave(From,Tag);
+ die ->
+ exit(normal)
end.
setup(ProcFlags) ->
@@ -1280,30 +1212,30 @@ setup(ProcFlags) ->
Pid = spawn(fun () -> slave(Self, Sync) end),
Mref = erlang:monitor(process, Pid),
receive
- Sync ->
- put(slave, {Pid,Mref}),
- case ProcFlags of
- [] -> ok;
- _ ->
- erlang:trace(Pid, true, ProcFlags)
- end,
- Pid
+ Sync ->
+ put(slave, {Pid,Mref}),
+ case ProcFlags of
+ [] -> ok;
+ _ ->
+ erlang:trace(Pid, true, ProcFlags)
+ end,
+ Pid
end.
shutdown() ->
trace_off(),
{Pid,Mref} = get(slave),
try erlang:is_process_alive(Pid) of
- true ->
- Pid ! die,
- receive
- {'DOWN',Mref,process,Pid,Reason} ->
- Reason
- end;
- _ ->
- not_alive
+ true ->
+ Pid ! die,
+ receive
+ {'DOWN',Mref,process,Pid,Reason} ->
+ Reason
+ end;
+ _ ->
+ not_alive
catch _:_ ->
- undefined
+ undefined
end.
trace_off() ->
@@ -1311,7 +1243,7 @@ trace_off() ->
erlang:trace_pattern({'_','_','_'},false,[local]),
erlang:trace_pattern({'_','_','_'},false,[meta]),
erlang:trace(all, false, [all]).
-
+
apply_slave_async(M,F,A) ->
{Pid,Mref} = get(slave),
@@ -1332,8 +1264,8 @@ lambda_slave(Fun) ->
exc_slave(Opts, Func, Args) ->
try request({exc_top,Opts,Func,Args})
catch
- Reason ->
- {crash,Reason}
+ Reason ->
+ {crash,Reason}
end.
request(Request) ->
@@ -1344,13 +1276,13 @@ request(Request) ->
result(Tag, Mref) ->
receive
- {Tag,Result} ->
- receive
- Tag ->
- Result
- end;
- {'DOWN',Mref,process,_Pid,Reason} ->
- throw(Reason)
+ {Tag,Result} ->
+ receive
+ Tag ->
+ Result
+ end;
+ {'DOWN',Mref,process,_Pid,Reason} ->
+ throw(Reason)
end.
@@ -1363,25 +1295,25 @@ receive_next() ->
receive_next(TO) ->
receive
- M ->
- M
+ M ->
+ M
after TO ->
- ?t:fail(timeout)
+ ct:fail(timeout)
end.
receive_no_next(TO) ->
receive M ->
- ?t:fail({unexpected_message,[M|flush(TO)]})
+ ct:fail({unexpected_message,[M|flush(TO)]})
after TO ->
- ok
+ ok
end.
flush(T) ->
receive
- M ->
- [M|flush(T)]
+ M ->
+ [M|flush(T)]
after T ->
- []
+ []
end.
@@ -1416,19 +1348,19 @@ abbr(Term, _) -> Term.
%%
abbr_tuple(Tuple, N, J) when J =< size(Tuple) ->
if J > N; N =< 0 ->
- ['...'];
+ ['...'];
true ->
- [abbr(element(J, Tuple), N-1)|abbr_tuple(Tuple, J+1, N)]
+ [abbr(element(J, Tuple), N-1)|abbr_tuple(Tuple, J+1, N)]
end;
abbr_tuple(_, _, _) ->
[].
%%
abbr_list(_, 0, R) ->
case io_lib:printable_list(R) of
- true ->
- reverse(R, "...");
- false ->
- reverse(R, '...')
+ true ->
+ reverse(R, "...");
+ false ->
+ reverse(R, '...')
end;
abbr_list([H|T], N, R) ->
M = N-1,
diff --git a/erts/emulator/test/trace_meta_SUITE.erl b/erts/emulator/test/trace_meta_SUITE.erl
index 3b105ec6fe..dcc2cc807b 100644
--- a/erts/emulator/test/trace_meta_SUITE.erl
+++ b/erts/emulator/test/trace_meta_SUITE.erl
@@ -46,7 +46,7 @@
-define(config(A,B),config(A,B)).
-export([config/2]).
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-endif.
-ifdef(debug).
@@ -66,22 +66,21 @@ config(priv_dir,_) ->
".".
-else.
%% When run in test server.
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
+-export([all/0, suite/0,
init_per_testcase/2, end_per_testcase/2, not_run/1]).
-export([basic/1, return/1, on_and_off/1, stack_grow/1,
info/1, tracer/1, combo/1, nosilent/1]).
init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(test_server:minutes(5)),
- [{watchdog, Dog}|Config].
+ Config.
end_per_testcase(_Case, Config) ->
shutdown(),
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 5}}].
all() ->
case test_server:is_native(trace_meta_SUITE) of
@@ -91,74 +90,39 @@ case test_server:is_native(trace_meta_SUITE) of
combo, nosilent]
end.
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
not_run(Config) when is_list(Config) ->
{skipped,"Native code"}.
-basic(suite) ->
- [];
-basic(doc) ->
- ["Tests basic meta trace"];
+%% Tests basic meta trace
basic(Config) when is_list(Config) ->
basic_test().
-return(suite) ->
- [];
-return(doc) ->
- ["Tests return trace"];
+%% Tests return trace
return(Config) when is_list(Config) ->
return_test().
-on_and_off(suite) ->
- [];
-on_and_off(doc) ->
- ["Tests turning trace parameters on and off"];
+%% Tests turning trace parameters on and off
on_and_off(Config) when is_list(Config) ->
on_and_off_test().
-stack_grow(doc) ->
- ["Tests the stack growth during return traces"];
+%% Tests the stack growth during return traces
stack_grow(Config) when is_list(Config) ->
stack_grow_test().
-info(doc) ->
- ["Tests the trace_info BIF"];
+%% Tests the trace_info BIF
info(Config) when is_list(Config) ->
info_test().
-tracer(suite) ->
- [];
-tracer(doc) ->
- ["Tests stopping and changing tracer process"];
+%% Tests stopping and changing tracer process
tracer(Config) when is_list(Config) ->
tracer_test().
-combo(suite) ->
- [];
-combo(doc) ->
- ["Tests combining local call trace with meta trace"];
+%% Tests combining local call trace with meta trace
combo(Config) when is_list(Config) ->
combo_test().
-nosilent(suite) ->
- [];
-nosilent(doc) ->
- ["Tests that meta trace is not silenced by the silent process flag"];
+%% Tests that meta trace is not silenced by the silent process flag
nosilent(Config) when is_list(Config) ->
nosilent_test().
@@ -546,7 +510,7 @@ combo_test() ->
{?RT(Slave,{?MODULE,receiver,1}),
?RF(Slave,{erlang,phash2,2},0)} ->
ok;
- Error1 -> ?t:fail({unexpected_message, Error1})
+ Error1 -> ct:fail({unexpected_message, Error1})
end,
case {receive_next_bytag(LocalTracer),
receive_next_bytag(LocalTracer)} of
@@ -556,7 +520,7 @@ combo_test() ->
{?RT(Slave,{?MODULE,slave,1}),
?RF(Slave,{?MODULE,receiver,1},Ref)} ->
ok;
- Error2 -> ?t:fail({unexpected_message, Error2})
+ Error2 -> ct:fail({unexpected_message, Error2})
end,
shutdown(),
?NM,
@@ -745,13 +709,13 @@ receive_next(TO) ->
M ->
M
after TO ->
- ?t:fail(timeout)
+ ct:fail(timeout)
end.
receive_no_next(TO) ->
receive
M ->
- ?t:fail({unexpected_message, M})
+ ct:fail({unexpected_message, M})
after
TO ->
ok
diff --git a/erts/emulator/test/trace_nif_SUITE.erl b/erts/emulator/test/trace_nif_SUITE.erl
index 1cd50350e3..49757a414d 100644
--- a/erts/emulator/test/trace_nif_SUITE.erl
+++ b/erts/emulator/test/trace_nif_SUITE.erl
@@ -20,10 +20,9 @@
-module(trace_nif_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
+-export([all/0, suite/0]).
-export([trace_nif/1,
trace_nif_timestamp/1,
trace_nif_local/1,
@@ -45,259 +44,230 @@ all() ->
trace_nif_return]
end.
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
not_run(Config) when is_list(Config) ->
{skipped,"Native code"}.
-trace_nif(doc) -> "Test tracing NIFs.";
+%% Test tracing NIFs.
trace_nif(Config) when is_list(Config) ->
load_nif(Config),
-
+
do_trace_nif([]).
-trace_nif_local(doc) -> "Test tracing NIFs with local flag.";
+%% Test tracing NIFs with local flag.
trace_nif_local(Config) when is_list(Config) ->
load_nif(Config),
do_trace_nif([local]).
-trace_nif_meta(doc) -> "Test tracing NIFs with meta flag.";
+%% Test tracing NIFs with meta flag.
trace_nif_meta(Config) when is_list(Config) ->
load_nif(Config),
- ?line Pid=spawn_link(?MODULE, nif_process, []),
- ?line erlang:trace_pattern({?MODULE,nif,'_'}, [], [meta]),
-
- ?line Pid ! {apply_nif, nif, []},
- ?line receive_trace_msg_ts({trace_ts,Pid,call,{?MODULE,nif,[]}}),
-
- ?line Pid ! {apply_nif, nif, ["Arg1"]},
- ?line receive_trace_msg_ts({trace_ts,Pid,call,
- {?MODULE,nif, ["Arg1"]}}),
-
- ?line Pid ! {call_nif, nif, []},
- ?line receive_trace_msg_ts({trace_ts,Pid,call,
- {?MODULE,nif, []}}),
-
- ?line Pid ! {call_nif, nif, ["Arg1"]},
- ?line receive_trace_msg_ts({trace_ts,Pid,call,
- {?MODULE,nif, ["Arg1"]}}),
+ Pid=spawn_link(?MODULE, nif_process, []),
+ erlang:trace_pattern({?MODULE,nif,'_'}, [], [meta]),
+
+ Pid ! {apply_nif, nif, []},
+ receive_trace_msg_ts({trace_ts,Pid,call,{?MODULE,nif,[]}}),
+
+ Pid ! {apply_nif, nif, ["Arg1"]},
+ receive_trace_msg_ts({trace_ts,Pid,call,
+ {?MODULE,nif, ["Arg1"]}}),
+
+ Pid ! {call_nif, nif, []},
+ receive_trace_msg_ts({trace_ts,Pid,call,
+ {?MODULE,nif, []}}),
+
+ Pid ! {call_nif, nif, ["Arg1"]},
+ receive_trace_msg_ts({trace_ts,Pid,call,
+ {?MODULE,nif, ["Arg1"]}}),
ok.
do_trace_nif(Flags) ->
- ?line Pid = spawn(?MODULE, nif_process, []),
- ?line 1 = erlang:trace(Pid, true, [call]),
- ?line erlang:trace_pattern({?MODULE,nif,'_'}, [], Flags),
- ?line Pid ! {apply_nif, nif, []},
- ?line receive_trace_msg({trace,Pid,call,{?MODULE,nif, []}}),
- ?line Pid ! {apply_nif, nif, ["Arg1"]},
- ?line receive_trace_msg({trace,Pid,call,{?MODULE,nif, ["Arg1"]}}),
+ Pid = spawn(?MODULE, nif_process, []),
+ 1 = erlang:trace(Pid, true, [call]),
+ erlang:trace_pattern({?MODULE,nif,'_'}, [], Flags),
+ Pid ! {apply_nif, nif, []},
+ receive_trace_msg({trace,Pid,call,{?MODULE,nif, []}}),
+ Pid ! {apply_nif, nif, ["Arg1"]},
+ receive_trace_msg({trace,Pid,call,{?MODULE,nif, ["Arg1"]}}),
+
+ Pid ! {call_nif, nif, []},
+ receive_trace_msg({trace, Pid, call, {?MODULE,nif, []}}),
- ?line Pid ! {call_nif, nif, []},
- ?line receive_trace_msg({trace, Pid, call, {?MODULE,nif, []}}),
+ Pid ! {call_nif, nif, ["Arg1"]},
+ receive_trace_msg({trace, Pid, call, {?MODULE,nif, ["Arg1"]}}),
- ?line Pid ! {call_nif, nif, ["Arg1"]},
- ?line receive_trace_msg({trace, Pid, call, {?MODULE,nif, ["Arg1"]}}),
-
%% Switch off
- ?line 1 = erlang:trace(Pid, false, [call]),
+ 1 = erlang:trace(Pid, false, [call]),
- ?line Pid ! {apply_nif, nif, []},
+ Pid ! {apply_nif, nif, []},
receive_nothing(),
- ?line Pid ! {apply_nif, nif, ["Arg1"]},
+ Pid ! {apply_nif, nif, ["Arg1"]},
receive_nothing(),
- ?line Pid ! {call_nif, nif, []},
+ Pid ! {call_nif, nif, []},
receive_nothing(),
- ?line Pid ! {call_nif, nif, ["Arg1"]},
+ Pid ! {call_nif, nif, ["Arg1"]},
receive_nothing(),
%% Switch on again
- ?line 1 = erlang:trace(Pid, true, [call]),
- ?line erlang:trace_pattern({?MODULE,nif,'_'}, [], Flags),
- ?line Pid ! {apply_nif, nif, []},
- ?line receive_trace_msg({trace,Pid,call,{?MODULE,nif, []}}),
- ?line Pid ! {apply_nif, nif, ["Arg1"]},
- ?line receive_trace_msg({trace,Pid,call,{?MODULE,nif, ["Arg1"]}}),
-
- ?line Pid ! {call_nif, nif, []},
- ?line receive_trace_msg({trace, Pid, call, {?MODULE,nif, []}}),
-
- ?line Pid ! {call_nif, nif, ["Arg1"]},
- ?line receive_trace_msg({trace, Pid, call, {?MODULE,nif, ["Arg1"]}}),
-
- ?line 1 = erlang:trace(Pid, false, [call]),
- ?line erlang:trace_pattern({?MODULE,nif,'_'}, false, Flags),
- ?line exit(Pid, die),
+ 1 = erlang:trace(Pid, true, [call]),
+ erlang:trace_pattern({?MODULE,nif,'_'}, [], Flags),
+ Pid ! {apply_nif, nif, []},
+ receive_trace_msg({trace,Pid,call,{?MODULE,nif, []}}),
+ Pid ! {apply_nif, nif, ["Arg1"]},
+ receive_trace_msg({trace,Pid,call,{?MODULE,nif, ["Arg1"]}}),
+
+ Pid ! {call_nif, nif, []},
+ receive_trace_msg({trace, Pid, call, {?MODULE,nif, []}}),
+
+ Pid ! {call_nif, nif, ["Arg1"]},
+ receive_trace_msg({trace, Pid, call, {?MODULE,nif, ["Arg1"]}}),
+
+ 1 = erlang:trace(Pid, false, [call]),
+ erlang:trace_pattern({?MODULE,nif,'_'}, false, Flags),
+ exit(Pid, die),
ok.
-trace_nif_timestamp(doc) -> "Test tracing NIFs with timestamps.";
+%% Test tracing NIFs with timestamps.
trace_nif_timestamp(Config) when is_list(Config) ->
load_nif(Config),
do_trace_nif_timestamp([]).
-trace_nif_timestamp_local(doc) ->
- "Test tracing NIFs with timestamps and local flag.";
+%% Test tracing NIFs with timestamps and local flag.
trace_nif_timestamp_local(Config) when is_list(Config) ->
load_nif(Config),
do_trace_nif_timestamp([local]).
do_trace_nif_timestamp(Flags) ->
- ?line Pid=spawn(?MODULE, nif_process, []),
- ?line 1 = erlang:trace(Pid, true, [call,timestamp]),
- ?line erlang:trace_pattern({?MODULE,nif,'_'}, [], Flags),
-
- ?line Pid ! {apply_nif, nif, []},
- ?line receive_trace_msg_ts({trace_ts,Pid,call,{?MODULE,nif,[]}}),
-
- ?line Pid ! {apply_nif, nif, ["Arg1"]},
- ?line receive_trace_msg_ts({trace_ts,Pid,call,
- {?MODULE,nif, ["Arg1"]}}),
-
- ?line Pid ! {call_nif, nif, []},
- ?line receive_trace_msg_ts({trace_ts,Pid,call,
- {?MODULE,nif, []}}),
-
- ?line Pid ! {call_nif, nif, ["Arg1"]},
- ?line receive_trace_msg_ts({trace_ts,Pid,call,
- {?MODULE,nif, ["Arg1"]}}),
-
+ Pid=spawn(?MODULE, nif_process, []),
+ 1 = erlang:trace(Pid, true, [call,timestamp]),
+ erlang:trace_pattern({?MODULE,nif,'_'}, [], Flags),
+
+ Pid ! {apply_nif, nif, []},
+ receive_trace_msg_ts({trace_ts,Pid,call,{?MODULE,nif,[]}}),
+
+ Pid ! {apply_nif, nif, ["Arg1"]},
+ receive_trace_msg_ts({trace_ts,Pid,call,
+ {?MODULE,nif, ["Arg1"]}}),
+
+ Pid ! {call_nif, nif, []},
+ receive_trace_msg_ts({trace_ts,Pid,call,
+ {?MODULE,nif, []}}),
+
+ Pid ! {call_nif, nif, ["Arg1"]},
+ receive_trace_msg_ts({trace_ts,Pid,call,
+ {?MODULE,nif, ["Arg1"]}}),
+
%% We should be able to turn off the timestamp.
- ?line 1 = erlang:trace(Pid, false, [timestamp]),
-
- ?line Pid ! {call_nif, nif, []},
- ?line receive_trace_msg({trace,Pid,call,
- {?MODULE,nif, []}}),
-
- ?line Pid ! {apply_nif, nif, ["tjoho"]},
- ?line receive_trace_msg({trace,Pid,call,
- {?MODULE,nif, ["tjoho"]}}),
-
- ?line 1 = erlang:trace(Pid, false, [call]),
- ?line erlang:trace_pattern({erlang,'_','_'}, false, Flags),
-
- ?line exit(Pid, die),
+ 1 = erlang:trace(Pid, false, [timestamp]),
+
+ Pid ! {call_nif, nif, []},
+ receive_trace_msg({trace,Pid,call,
+ {?MODULE,nif, []}}),
+
+ Pid ! {apply_nif, nif, ["tjoho"]},
+ receive_trace_msg({trace,Pid,call,
+ {?MODULE,nif, ["tjoho"]}}),
+
+ 1 = erlang:trace(Pid, false, [call]),
+ erlang:trace_pattern({erlang,'_','_'}, false, Flags),
+
+ exit(Pid, die),
ok.
-trace_nif_return(doc) ->
- "Test tracing NIF's with return/return_to trace.";
+%% Test tracing NIF's with return/return_to trace.
trace_nif_return(Config) when is_list(Config) ->
load_nif(Config),
- ?line Pid=spawn(?MODULE, nif_process, []),
- ?line 1 = erlang:trace(Pid, true, [call,timestamp,return_to]),
- ?line erlang:trace_pattern({?MODULE,nif,'_'}, [{'_',[],[{return_trace}]}],
- [local]),
-
- ?line Pid ! {apply_nif, nif, []},
- ?line receive_trace_msg_ts({trace_ts,Pid,call,{?MODULE,nif,[]}}),
- ?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from,
- {?MODULE,nif,0}}),
- ?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to,
- {?MODULE, nif_process,0}}),
-
- ?line Pid ! {call_nif, nif, ["Arg1"]},
- ?line receive_trace_msg_ts({trace_ts,Pid,call,
- {?MODULE,nif, ["Arg1"]}}),
- ?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from,
- {?MODULE,nif,1}}),
- ?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to,
- {?MODULE, nif_process,0}}),
+ Pid=spawn(?MODULE, nif_process, []),
+ 1 = erlang:trace(Pid, true, [call,timestamp,return_to]),
+ erlang:trace_pattern({?MODULE,nif,'_'}, [{'_',[],[{return_trace}]}],
+ [local]),
+
+ Pid ! {apply_nif, nif, []},
+ receive_trace_msg_ts({trace_ts,Pid,call,{?MODULE,nif,[]}}),
+ receive_trace_msg_ts_return_from({trace_ts,Pid,return_from,
+ {?MODULE,nif,0}}),
+ receive_trace_msg_ts_return_to({trace_ts,Pid,return_to,
+ {?MODULE, nif_process,0}}),
+
+ Pid ! {call_nif, nif, ["Arg1"]},
+ receive_trace_msg_ts({trace_ts,Pid,call,
+ {?MODULE,nif, ["Arg1"]}}),
+ receive_trace_msg_ts_return_from({trace_ts,Pid,return_from,
+ {?MODULE,nif,1}}),
+ receive_trace_msg_ts_return_to({trace_ts,Pid,return_to,
+ {?MODULE, nif_process,0}}),
ok.
receive_trace_msg(Mess) ->
receive
- Mess ->
- ok;
- Other ->
- io:format("Expected: ~p,~nGot: ~p~n", [Mess, Other]),
- ?t:fail()
+ Mess ->
+ ok;
+ Other ->
+ ct:fail("Expected: ~p,~nGot: ~p~n", [Mess, Other])
after 5000 ->
- io:format("Expected: ~p,~nGot: timeout~n", [Mess]),
- ?t:fail()
+ ct:fail("Expected: ~p,~nGot: timeout~n", [Mess])
end.
receive_nothing() ->
- ?line timeout = receive M -> M after 100 -> timeout end.
+ timeout = receive M -> M after 100 -> timeout end.
receive_trace_msg_ts({trace_ts, Pid, call, {M,F,A}}) ->
receive
- {trace_ts, Pid, call, {M, F, A}, _Ts} ->
- ok;
- Other ->
- io:format("Expected: {trace, ~p, call, {~p, ~p, ~p}, TimeStamp}},~n"
- "Got: ~p~n",
- [Pid, M, F, A, Other]),
- ?t:fail()
+ {trace_ts, Pid, call, {M, F, A}, _Ts} ->
+ ok;
+ Other ->
+ ct:fail("Expected: {trace, ~p, call, {~p, ~p, ~p}, TimeStamp}},~n"
+ "Got: ~p~n", [Pid, M, F, A, Other])
after 5000 ->
- io:format("Got timeout~n", []),
- ?t:fail()
+ ct:fail("Got timeout~n", [])
end.
receive_trace_msg_ts_return_from({trace_ts, Pid, return_from, {M,F,A}}) ->
receive
- {trace_ts, Pid, return_from, {M, F, A}, _Value, _Ts} ->
- ok;
- Other ->
- io:format("Expected: {trace_ts, ~p, return_from, {~p, ~p, ~p}, Value, TimeStamp}},~n"
- "Got: ~p~n",
- [Pid, M, F, A, Other]),
- ?t:fail()
+ {trace_ts, Pid, return_from, {M, F, A}, _Value, _Ts} ->
+ ok;
+ Other ->
+ ct:fail("Expected: {trace_ts, ~p, return_from, {~p, ~p, ~p}, Value, TimeStamp}},~n"
+ "Got: ~p~n", [Pid, M, F, A, Other])
after 5000 ->
- io:format("Got timeout~n", []),
- ?t:fail()
+ ct:fail("Got timeout~n", [])
end.
receive_trace_msg_ts_return_to({trace_ts, Pid, return_to, {M,F,A}}) ->
receive
- {trace_ts, Pid, return_to, {M, F, A}, _Ts} ->
- ok;
- Other ->
- io:format("Expected: {trace_ts, ~p, return_to, {~p, ~p, ~p}, TimeStamp}},~n"
- "Got: ~p~n",
- [Pid, M, F, A, Other]),
- ?t:fail()
+ {trace_ts, Pid, return_to, {M, F, A}, _Ts} ->
+ ok;
+ Other ->
+ ct:fail("Expected: {trace_ts, ~p, return_to, {~p, ~p, ~p}, TimeStamp}},~n"
+ "Got: ~p~n", [Pid, M, F, A, Other])
after 5000 ->
- io:format("Got timeout~n", []),
- ?t:fail()
+ ct:fail("Got timeout~n", [])
end.
nif_process() ->
receive
- {apply_nif, Name, Args} ->
- ?line {ok,Args} = apply(?MODULE, Name, Args);
-
- {call_nif, Name, []} ->
- ?line {ok, []} = ?MODULE:Name();
-
- {call_nif, Name, [A1]} ->
- ?line {ok, [A1]} = ?MODULE:Name(A1);
-
- {call_nif, Name, [A1,A2]} ->
- ?line {ok,[A1,A2]} = ?MODULE:Name(A1,A2);
-
- {call_nif, Name, [A1,A2,A3]} ->
- ?line {ok,[A1,A2,A3]} = ?MODULE:Name(A1,A2,A3)
+ {apply_nif, Name, Args} ->
+ {ok,Args} = apply(?MODULE, Name, Args);
+
+ {call_nif, Name, []} ->
+ {ok, []} = ?MODULE:Name();
+
+ {call_nif, Name, [A1]} ->
+ {ok, [A1]} = ?MODULE:Name(A1);
+
+ {call_nif, Name, [A1,A2]} ->
+ {ok,[A1,A2]} = ?MODULE:Name(A1,A2);
+
+ {call_nif, Name, [A1,A2,A3]} ->
+ {ok,[A1,A2,A3]} = ?MODULE:Name(A1,A2,A3)
end,
nif_process().
load_nif(Config) ->
- ?line Path = ?config(data_dir, Config),
-
- ?line ok = erlang:load_nif(filename:join(Path,"trace_nif"), 0).
+ Path = proplists:get_value(data_dir, Config),
+
+ ok = erlang:load_nif(filename:join(Path,"trace_nif"), 0).
nif() ->
@@ -305,4 +275,3 @@ nif() ->
nif(A1) ->
{"Stub1",[A1]}. %exit(["nif/1 stub called",A1]).
-
diff --git a/erts/emulator/test/trace_port_SUITE.erl b/erts/emulator/test/trace_port_SUITE.erl
index a77710205e..d33f18543a 100644
--- a/erts/emulator/test/trace_port_SUITE.erl
+++ b/erts/emulator/test/trace_port_SUITE.erl
@@ -21,9 +21,7 @@
-module(trace_port_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2,
+-export([all/0, suite/0,
call_trace/1,
return_trace/1,
send/1,
@@ -38,9 +36,13 @@
default_tracer/1,
tracer_port_crash/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-test_cases() ->
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {seconds, 30}}].
+
+all() ->
[call_trace, return_trace, send, receive_trace,
process_events, schedule, fake_schedule,
fake_schedule_after_register,
@@ -48,212 +50,183 @@ test_cases() ->
fake_schedule_after_getting_unlinked, gc,
default_tracer, tracer_port_crash].
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- test_cases().
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog = ?t:timetrap(?t:seconds(30)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
-call_trace(doc) -> "Test sending call trace messages to a port.";
+%% Test sending call trace messages to a port.
call_trace(Config) when is_list(Config) ->
case test_server:is_native(?MODULE) orelse
- test_server:is_native(lists) of
- true ->
- {skip,"Native code"};
- false ->
- ?line start_tracer(Config),
- Self = self(),
- ?line trace_func({lists,reverse,1}, []),
- ?line trace_pid(Self, true, [call]),
- ?line trace_info(Self, flags),
- ?line trace_info(Self, tracer),
- ?line [b,a] = lists:reverse([a,b]),
- ?line expect({trace,Self,call,{lists,reverse,[[a,b]]}}),
-
- ?line trace_pid(Self, true, [timestamp]),
- ?line trace_info(Self, flags),
- ?line Huge = huge_data(),
- ?line lists:reverse(Huge),
- ?line expect({trace_ts,Self,call,{lists,reverse,[Huge]},ts}),
-
- ?line trace_pid(Self, true, [arity]),
- ?line trace_info(Self, flags),
- ?line [y,x] = lists:reverse([x,y]),
- ?line expect({trace_ts,Self,call,{lists,reverse,1},ts}),
-
- ?line trace_pid(Self, false, [timestamp]),
- ?line trace_info(Self, flags),
- ?line [z,y,x] = lists:reverse([x,y,z]),
- ?line expect({trace,Self,call,{lists,reverse,1}}),
-
- %% OTP-7399. Delayed sub-binary creation optimization.
- ?line trace_pid(Self, false, [arity]),
- ?line trace_info(Self, flags),
- ?line trace_func({?MODULE,bs_sum_c,2}, [], [local]),
- ?line 26 = bs_sum_c(<<3:4,5:4,7:4,11:4>>, 0),
- ?line trace_func({?MODULE,bs_sum_c,2}, false, [local]),
- ?line expect({trace,Self,call,{?MODULE,bs_sum_c,[<<3:4,5:4,7:4,11:4>>,0]}}),
- ?line expect({trace,Self,call,{?MODULE,bs_sum_c,[<<5:4,7:4,11:4>>,3]}}),
- ?line expect({trace,Self,call,{?MODULE,bs_sum_c,[<<7:4,11:4>>,8]}}),
- ?line expect({trace,Self,call,{?MODULE,bs_sum_c,[<<11:4>>,15]}}),
- ?line expect({trace,Self,call,{?MODULE,bs_sum_c,[<<>>,26]}}),
-
- ?line trace_func({lists,reverse,1}, false),
- ok
+ test_server:is_native(lists) of
+ true ->
+ {skip,"Native code"};
+ false ->
+ start_tracer(Config),
+ Self = self(),
+ trace_func({lists,reverse,1}, []),
+ trace_pid(Self, true, [call]),
+ trace_info(Self, flags),
+ trace_info(Self, tracer),
+ [b,a] = lists:reverse([a,b]),
+ expect({trace,Self,call,{lists,reverse,[[a,b]]}}),
+
+ trace_pid(Self, true, [timestamp]),
+ trace_info(Self, flags),
+ Huge = huge_data(),
+ lists:reverse(Huge),
+ expect({trace_ts,Self,call,{lists,reverse,[Huge]},ts}),
+
+ trace_pid(Self, true, [arity]),
+ trace_info(Self, flags),
+ [y,x] = lists:reverse([x,y]),
+ expect({trace_ts,Self,call,{lists,reverse,1},ts}),
+
+ trace_pid(Self, false, [timestamp]),
+ trace_info(Self, flags),
+ [z,y,x] = lists:reverse([x,y,z]),
+ expect({trace,Self,call,{lists,reverse,1}}),
+
+ %% OTP-7399. Delayed sub-binary creation optimization.
+ trace_pid(Self, false, [arity]),
+ trace_info(Self, flags),
+ trace_func({?MODULE,bs_sum_c,2}, [], [local]),
+ 26 = bs_sum_c(<<3:4,5:4,7:4,11:4>>, 0),
+ trace_func({?MODULE,bs_sum_c,2}, false, [local]),
+ expect({trace,Self,call,{?MODULE,bs_sum_c,[<<3:4,5:4,7:4,11:4>>,0]}}),
+ expect({trace,Self,call,{?MODULE,bs_sum_c,[<<5:4,7:4,11:4>>,3]}}),
+ expect({trace,Self,call,{?MODULE,bs_sum_c,[<<7:4,11:4>>,8]}}),
+ expect({trace,Self,call,{?MODULE,bs_sum_c,[<<11:4>>,15]}}),
+ expect({trace,Self,call,{?MODULE,bs_sum_c,[<<>>,26]}}),
+
+ trace_func({lists,reverse,1}, false),
+ ok
end.
bs_sum_c(<<H:4,T/bits>>, Acc) -> bs_sum_c(T, H+Acc);
bs_sum_c(<<>>, Acc) -> Acc.
-return_trace(doc) -> "Test the new return trace.";
+%% Test the new return trace.
return_trace(Config) when is_list(Config) ->
case test_server:is_native(?MODULE) orelse
- test_server:is_native(lists) of
- true ->
- {skip,"Native code"};
- false ->
- ?line start_tracer(Config),
- Self = self(),
- MFA = {lists,reverse,1},
-
- %% Plain (no timestamp, small data).
-
- ?line trace_func(MFA, [{['$1'],[],[{return_trace},
- {message,false}]}]),
- ?line trace_pid(Self, true, [call]),
- ?line trace_info(Self, flags),
- ?line trace_info(Self, tracer),
- ?line trace_info(MFA, match_spec),
- ?line {traced,global} = trace_info(MFA, traced),
- ?line [b,a] = lists:reverse([a,b]),
- ?line expect({trace,Self,return_from,MFA,[b,a]}),
-
- %% Timestamp, huge data.
- ?line trace_pid(Self, true, [timestamp]),
- ?line Result = lists:reverse(huge_data()),
- ?line expect({trace_ts,Self,return_from,MFA,Result,ts}),
-
- %% Turn off trace.
- ?line trace_func(MFA, false),
- ?line trace_info(MFA, match_spec),
- ?line {traced,false} = trace_info(MFA, traced),
- ok
+ test_server:is_native(lists) of
+ true ->
+ {skip,"Native code"};
+ false ->
+ start_tracer(Config),
+ Self = self(),
+ MFA = {lists,reverse,1},
+
+ %% Plain (no timestamp, small data).
+
+ trace_func(MFA, [{['$1'],[],[{return_trace},
+ {message,false}]}]),
+ trace_pid(Self, true, [call]),
+ trace_info(Self, flags),
+ trace_info(Self, tracer),
+ trace_info(MFA, match_spec),
+ {traced,global} = trace_info(MFA, traced),
+ [b,a] = lists:reverse([a,b]),
+ expect({trace,Self,return_from,MFA,[b,a]}),
+
+ %% Timestamp, huge data.
+ trace_pid(Self, true, [timestamp]),
+ Result = lists:reverse(huge_data()),
+ expect({trace_ts,Self,return_from,MFA,Result,ts}),
+
+ %% Turn off trace.
+ trace_func(MFA, false),
+ trace_info(MFA, match_spec),
+ {traced,false} = trace_info(MFA, traced),
+ ok
end.
-send(doc) -> "Test sending send trace messages to a port.";
+%% Test sending send trace messages to a port.
send(Config) when is_list(Config) ->
- ?line Tracer = start_tracer(Config),
+ Tracer = start_tracer(Config),
Self = self(),
- ?line Sender = fun_spawn(fun sender/0),
- ?line trac(Sender, true, [send]),
+ Sender = fun_spawn(fun sender/0),
+ trac(Sender, true, [send]),
%% Simple message, no timestamp.
- ?line Bin = list_to_binary(lists:seq(1, 10)),
- ?line Msg = {some_data,Bin},
+ Bin = list_to_binary(lists:seq(1, 10)),
+ Msg = {some_data,Bin},
Sender ! {send_please,self(),Msg},
receive Msg -> ok end,
- ?line expect({trace,Sender,send,Msg,Self}),
+ expect({trace,Sender,send,Msg,Self}),
%% Timestamp.
BiggerMsg = {even_bigger,Msg},
- ?line trac(Sender, true, [send,timestamp]),
+ trac(Sender, true, [send,timestamp]),
Sender ! {send_please,self(),BiggerMsg},
receive BiggerMsg -> ok end,
- ?line expect({trace_ts,Sender,send,BiggerMsg,Self,ts}),
+ expect({trace_ts,Sender,send,BiggerMsg,Self,ts}),
%% Huge message.
- ?line HugeMsg = huge_data(),
+ HugeMsg = huge_data(),
Sender ! {send_please,self(),HugeMsg},
receive HugeMsg -> ok end,
- ?line expect({trace_ts,Sender,send,HugeMsg,Self,ts}),
+ expect({trace_ts,Sender,send,HugeMsg,Self,ts}),
%% Kill trace port and force a trace. The emulator should not crasch.
- ?line unlink(Tracer),
- ?line exit(Tracer, kill),
+ unlink(Tracer),
+ exit(Tracer, kill),
erlang:yield(), % Make sure that port gets killed.
Sender ! {send_please,Self,good_bye},
receive good_bye -> ok end,
ok.
-receive_trace(doc) -> "Test sending receive traces to a port.";
+%% Test sending receive traces to a port.
receive_trace(Config) when is_list(Config) ->
- ?line start_tracer(Config),
- ?line Receiver = fun_spawn(fun receiver/0),
- ?line trac(Receiver, true, ['receive']),
+ start_tracer(Config),
+ Receiver = fun_spawn(fun receiver/0),
+ trac(Receiver, true, ['receive']),
Receiver ! {hello,world},
- ?line expect({trace,Receiver,'receive',{hello,world}}),
+ expect({trace,Receiver,'receive',{hello,world}}),
- ?line trac(Receiver, true, ['receive',timestamp]),
+ trac(Receiver, true, ['receive',timestamp]),
Huge = {hello,huge_data()},
Receiver ! {hello,huge_data()},
- ?line expect({trace_ts,Receiver,'receive',Huge,ts}),
+ expect({trace_ts,Receiver,'receive',Huge,ts}),
ok.
-process_events(doc) -> "Tests a few process events (like getting linked).";
+%% Tests a few process events (like getting linked).
process_events(Config) when is_list(Config) ->
- ?line start_tracer(Config),
+ start_tracer(Config),
Self = self(),
- ?line Receiver = fun_spawn(fun receiver/0),
- ?line trac(Receiver, true, [procs]),
+ Receiver = fun_spawn(fun receiver/0),
+ trac(Receiver, true, [procs]),
unlink(Receiver), %It is already linked.
- ?line expect({trace,Receiver,getting_unlinked,Self}),
+ expect({trace,Receiver,getting_unlinked,Self}),
link(Receiver),
- ?line expect({trace,Receiver,getting_linked,Self}),
- ?line trac(Receiver, true, [procs,timestamp]),
+ expect({trace,Receiver,getting_linked,Self}),
+ trac(Receiver, true, [procs,timestamp]),
unlink(Receiver),
- ?line expect({trace_ts,Receiver,getting_unlinked,Self,ts}),
+ expect({trace_ts,Receiver,getting_unlinked,Self,ts}),
link(Receiver),
- ?line expect({trace_ts,Receiver,getting_linked,Self,ts}),
+ expect({trace_ts,Receiver,getting_linked,Self,ts}),
unlink(Receiver),
- ?line expect({trace_ts,Receiver,getting_unlinked,Self,ts}),
+ expect({trace_ts,Receiver,getting_unlinked,Self,ts}),
Huge = huge_data(),
exit(Receiver, Huge),
- ?line expect({trace_ts,Receiver,exit,Huge,ts}),
+ expect({trace_ts,Receiver,exit,Huge,ts}),
ok.
-schedule(doc) -> "Test sending scheduling events to a port.";
+%% Test sending scheduling events to a port.
schedule(Config) when is_list(Config) ->
- ?line start_tracer(Config),
- ?line Receiver = fun_spawn(fun receiver/0),
- ?line trac(Receiver, true, [running]),
+ start_tracer(Config),
+ Receiver = fun_spawn(fun receiver/0),
+ trac(Receiver, true, [running]),
Receiver ! hi,
expect({trace,Receiver,in,{?MODULE,receiver,0}}),
expect({trace,Receiver,out,{?MODULE,receiver,0}}),
- ?line trac(Receiver, true, [running,timestamp]),
+ trac(Receiver, true, [running,timestamp]),
Receiver ! hi_again,
expect({trace_ts,Receiver,in,{?MODULE,receiver,0},ts}),
@@ -262,252 +235,248 @@ schedule(Config) when is_list(Config) ->
ok.
run_fake_sched_test(Fun, Config) when is_function(Fun), is_list(Config) ->
- ?line case catch erlang:system_info(smp_support) of
- true ->
- ?line {skipped,
- "No need for faked schedule out/in trace messages "
- "when smp support is enabled"};
- _ ->
- ?line Fun(Config)
- end.
-
-fake_schedule(doc) -> "Tests time compensating fake out/in scheduling.";
+ case catch erlang:system_info(smp_support) of
+ true ->
+ {skipped,
+ "No need for faked schedule out/in trace messages "
+ "when smp support is enabled"};
+ _ ->
+ Fun(Config)
+ end.
+
+%% Tests time compensating fake out/in scheduling.
fake_schedule(Config) when is_list(Config) ->
- ?line run_fake_sched_test(fun fake_schedule_test/1, Config).
+ run_fake_sched_test(fun fake_schedule_test/1, Config).
fake_schedule_test(Config) when is_list(Config) ->
- ?line Tracer = start_tracer(Config),
- ?line Port = get(tracer_port),
- ?line General = fun_spawn(fun general/0),
+ Tracer = start_tracer(Config),
+ Port = get(tracer_port),
+ General = fun_spawn(fun general/0),
%%
- ?line trac(General, true, [send, running]),
+ trac(General, true, [send, running]),
%%
%% Test that fake out/in scheduling is not generated unless
%% both 'running' and 'timestamp' is active.
- ?line [] = erlang:port_control(Port, $h, []),
- ?line General ! nop,
- ?line expect({trace, General, in, {?MODULE, general, 0}}),
- ?line expect({trace, General, out, {?MODULE, general, 0}}),
- ?line expect(),
+ [] = erlang:port_control(Port, $h, []),
+ General ! nop,
+ expect({trace, General, in, {?MODULE, general, 0}}),
+ expect({trace, General, out, {?MODULE, general, 0}}),
+ expect(),
%%
- ?line trac(General, false, [running]),
- ?line trac(General, true, [timestamp]),
+ trac(General, false, [running]),
+ trac(General, true, [timestamp]),
%%
- ?line Ref1 = make_ref(),
- ?line Msg1 = {Port, {data, term_to_binary(Ref1)}},
- ?line [] = erlang:port_control(Port, $h, []),
- ?line General ! {send, Tracer, Msg1},
- ?line expect({trace_ts, General, send, Msg1, Tracer, ts}),
- ?line expect(Ref1),
- ?line expect(),
+ Ref1 = make_ref(),
+ Msg1 = {Port, {data, term_to_binary(Ref1)}},
+ [] = erlang:port_control(Port, $h, []),
+ General ! {send, Tracer, Msg1},
+ expect({trace_ts, General, send, Msg1, Tracer, ts}),
+ expect(Ref1),
+ expect(),
%%
- ?line trac(General, true, [running]),
+ trac(General, true, [running]),
%%
%% Test that fake out/in scheduling can be generated by the driver
- ?line Ref2 = make_ref(),
- ?line Msg2 = {Port, {data, term_to_binary(Ref2)}},
- ?line [] = erlang:port_control(Port, $h, []),
- ?line General ! {send, Tracer, Msg2},
- ?line {_,_,_,_,Ts} =
- expect({trace_ts, General, in, {?MODULE, general, 0}, ts}),
- ?line expect({trace_ts, General, out, 0, Ts}),
- ?line expect({trace_ts, General, in, 0, ts}),
- ?line expect({trace_ts, General, send, Msg2, Tracer, ts}),
- ?line expect(Ref2),
- ?line expect({trace_ts, General, out, {?MODULE, general, 0}, ts}),
- ?line expect(),
+ Ref2 = make_ref(),
+ Msg2 = {Port, {data, term_to_binary(Ref2)}},
+ [] = erlang:port_control(Port, $h, []),
+ General ! {send, Tracer, Msg2},
+ {_,_,_,_,Ts} =
+ expect({trace_ts, General, in, {?MODULE, general, 0}, ts}),
+ expect({trace_ts, General, out, 0, Ts}),
+ expect({trace_ts, General, in, 0, ts}),
+ expect({trace_ts, General, send, Msg2, Tracer, ts}),
+ expect(Ref2),
+ expect({trace_ts, General, out, {?MODULE, general, 0}, ts}),
+ expect(),
%%
%% Test that fake out/in scheduling is not generated after an
%% 'out' scheduling event
- ?line Ref3 = make_ref(),
- ?line Msg3 = {Port, {data, term_to_binary(Ref3)}},
- ?line General ! {apply, {erlang, port_control, [Port, $h, []]}},
- ?line expect({trace_ts, General, in, {?MODULE, general, 0}, ts}),
- ?line expect({trace_ts, General, out, {?MODULE, general, 0}, ts}),
- ?line General ! {send, Tracer, Msg3},
- ?line expect({trace_ts, General, in, {?MODULE, general, 0}, ts}),
- ?line expect({trace_ts, General, send, Msg3, Tracer, ts}),
- ?line expect(Ref3),
- ?line expect({trace_ts, General, out, {?MODULE, general, 0}, ts}),
- ?line expect(),
+ Ref3 = make_ref(),
+ Msg3 = {Port, {data, term_to_binary(Ref3)}},
+ General ! {apply, {erlang, port_control, [Port, $h, []]}},
+ expect({trace_ts, General, in, {?MODULE, general, 0}, ts}),
+ expect({trace_ts, General, out, {?MODULE, general, 0}, ts}),
+ General ! {send, Tracer, Msg3},
+ expect({trace_ts, General, in, {?MODULE, general, 0}, ts}),
+ expect({trace_ts, General, send, Msg3, Tracer, ts}),
+ expect(Ref3),
+ expect({trace_ts, General, out, {?MODULE, general, 0}, ts}),
+ expect(),
%%
ok.
-fake_schedule_after_register(doc) ->
- "Tests fake out/in scheduling contents.";
+%% Tests fake out/in scheduling contents.
fake_schedule_after_register(Config) when is_list(Config) ->
- ?line run_fake_sched_test(fun fake_schedule_after_register_test/1, Config).
+ run_fake_sched_test(fun fake_schedule_after_register_test/1, Config).
fake_schedule_after_register_test(Config) when is_list(Config) ->
- ?line start_tracer(Config),
- ?line Port = get(tracer_port),
- ?line G1 = fun_spawn(fun general/0),
- ?line G2 = fun_spawn(fun general/0),
+ start_tracer(Config),
+ Port = get(tracer_port),
+ G1 = fun_spawn(fun general/0),
+ G2 = fun_spawn(fun general/0),
%%
- ?line trac(G1, true, [running, timestamp, procs]),
- ?line trac(G2, true, [running, timestamp]),
+ trac(G1, true, [running, timestamp, procs]),
+ trac(G2, true, [running, timestamp]),
%%
%% Test fake out/in scheduling after certain messages
- ?line erlang:yield(),
- ?line G2 ! {apply, {erlang, port_control, [Port, $h, []]}},
- ?line G2 ! {apply, {erlang, register, [fake_schedule_after_register, G1]}},
- ?line expect({trace_ts, G2, in, {?MODULE, general, 0}, ts}),
- ?line {_,_,_,_,Ts} =
- expect({trace_ts, G1, register, fake_schedule_after_register, ts}),
- ?line expect({trace_ts, G2, out, 0, Ts}),
- ?line expect({trace_ts, G2, in, 0, ts}),
- ?line expect({trace_ts, G2, out, {?MODULE, general, 0}, ts}),
- ?line expect(),
+ erlang:yield(),
+ G2 ! {apply, {erlang, port_control, [Port, $h, []]}},
+ G2 ! {apply, {erlang, register, [fake_schedule_after_register, G1]}},
+ expect({trace_ts, G2, in, {?MODULE, general, 0}, ts}),
+ {_,_,_,_,Ts} =
+ expect({trace_ts, G1, register, fake_schedule_after_register, ts}),
+ expect({trace_ts, G2, out, 0, Ts}),
+ expect({trace_ts, G2, in, 0, ts}),
+ expect({trace_ts, G2, out, {?MODULE, general, 0}, ts}),
+ expect(),
%%
ok.
-fake_schedule_after_getting_linked(doc) ->
- "Tests fake out/in scheduling contents.";
+%% Tests fake out/in scheduling contents.
fake_schedule_after_getting_linked(Config) when is_list(Config) ->
- ?line run_fake_sched_test(fun fake_schedule_after_getting_linked_test/1,
- Config).
+ run_fake_sched_test(fun fake_schedule_after_getting_linked_test/1,
+ Config).
fake_schedule_after_getting_linked_test(Config) when is_list(Config) ->
- ?line start_tracer(Config),
- ?line Port = get(tracer_port),
- ?line G1 = fun_spawn(fun general/0),
- ?line G2 = fun_spawn(fun general/0),
+ start_tracer(Config),
+ Port = get(tracer_port),
+ G1 = fun_spawn(fun general/0),
+ G2 = fun_spawn(fun general/0),
%%
- ?line trac(G1, true, [running, timestamp, procs]),
- ?line trac(G2, true, [running, timestamp]),
+ trac(G1, true, [running, timestamp, procs]),
+ trac(G2, true, [running, timestamp]),
%%
%% Test fake out/in scheduling after certain messages
- ?line erlang:yield(),
- ?line G2 ! {apply, {erlang, port_control, [Port, $h, []]}},
- ?line G2 ! {apply, {erlang, link, [G1]}},
- ?line expect({trace_ts, G2, in, {?MODULE, general, 0}, ts}),
- ?line {_,_,_,_,Ts} =
- expect({trace_ts, G1, getting_linked, G2, ts}),
- ?line expect({trace_ts, G2, out, 0, Ts}),
- ?line expect({trace_ts, G2, in, 0, ts}),
- ?line expect({trace_ts, G2, out, {?MODULE, general, 0}, ts}),
- ?line expect(),
+ erlang:yield(),
+ G2 ! {apply, {erlang, port_control, [Port, $h, []]}},
+ G2 ! {apply, {erlang, link, [G1]}},
+ expect({trace_ts, G2, in, {?MODULE, general, 0}, ts}),
+ {_,_,_,_,Ts} =
+ expect({trace_ts, G1, getting_linked, G2, ts}),
+ expect({trace_ts, G2, out, 0, Ts}),
+ expect({trace_ts, G2, in, 0, ts}),
+ expect({trace_ts, G2, out, {?MODULE, general, 0}, ts}),
+ expect(),
%%
ok.
-fake_schedule_after_getting_unlinked(doc) ->
- "Tests fake out/in scheduling contents.";
+%% Tests fake out/in scheduling contents.
fake_schedule_after_getting_unlinked(Config) when is_list(Config) ->
- ?line run_fake_sched_test(fun fake_schedule_after_getting_unlinked_test/1,
- Config).
+ run_fake_sched_test(fun fake_schedule_after_getting_unlinked_test/1,
+ Config).
fake_schedule_after_getting_unlinked_test(Config) when is_list(Config) ->
- ?line start_tracer(Config),
- ?line Port = get(tracer_port),
- ?line G1 = fun_spawn(fun general/0),
- ?line G2 = fun_spawn(fun general/0),
+ start_tracer(Config),
+ Port = get(tracer_port),
+ G1 = fun_spawn(fun general/0),
+ G2 = fun_spawn(fun general/0),
%%
- ?line trac(G1, true, [running, procs]),
- ?line trac(G2, true, [running, timestamp]),
+ trac(G1, true, [running, procs]),
+ trac(G2, true, [running, timestamp]),
%%
%% Test fake out/in scheduling after certain messages
- ?line erlang:yield(),
- ?line G2 ! {apply, {erlang, link, [G1]}},
- ?line G2 ! {apply, {erlang, port_control, [Port, $h, []]}},
- ?line G2 ! {apply, {erlang, unlink, [G1]}},
- ?line expect({trace_ts, G2, in, {?MODULE, general, 0}, ts}),
- ?line expect({trace, G1, getting_linked, G2}),
- ?line expect({trace, G1, getting_unlinked, G2}),
- ?line expect({trace_ts, G2, out, 0, ts}),
- ?line expect({trace_ts, G2, in, 0, ts}),
- ?line expect({trace_ts, G2, out, {?MODULE, general, 0}, ts}),
- ?line expect(),
+ erlang:yield(),
+ G2 ! {apply, {erlang, link, [G1]}},
+ G2 ! {apply, {erlang, port_control, [Port, $h, []]}},
+ G2 ! {apply, {erlang, unlink, [G1]}},
+ expect({trace_ts, G2, in, {?MODULE, general, 0}, ts}),
+ expect({trace, G1, getting_linked, G2}),
+ expect({trace, G1, getting_unlinked, G2}),
+ expect({trace_ts, G2, out, 0, ts}),
+ expect({trace_ts, G2, in, 0, ts}),
+ expect({trace_ts, G2, out, {?MODULE, general, 0}, ts}),
+ expect(),
%%
ok.
-gc(doc) -> "Test sending garbage collection events to a port.";
+%% Test sending garbage collection events to a port.
gc(Config) when is_list(Config) ->
- ?line start_tracer(Config),
- ?line Garber = fun_spawn(fun garber/0, [{min_heap_size, 5000}]),
- ?line trac(Garber, true, [garbage_collection]),
- ?line trace_info(Garber, flags),
+ start_tracer(Config),
+ Garber = fun_spawn(fun garber/0, [{min_heap_size, 5000}]),
+ trac(Garber, true, [garbage_collection]),
+ trace_info(Garber, flags),
- ?line trace_info(Garber, flags),
+ trace_info(Garber, flags),
Garber ! hi,
expect({trace,Garber,gc_start,info}),
expect({trace,Garber,gc_end,info}),
- ?line trac(Garber, true, [garbage_collection,timestamp]),
+ trac(Garber, true, [garbage_collection,timestamp]),
Garber ! hi,
expect({trace_ts,Garber,gc_start,info,ts}),
expect({trace_ts,Garber,gc_end,info,ts}),
ok.
-default_tracer(doc) ->
- "Test a port as default tracer.";
+%% Test a port as default tracer.
default_tracer(Config) when is_list(Config) ->
- ?line Tracer = start_tracer(Config),
- ?line TracerMonitor = erlang:monitor(process, Tracer),
- ?line Port = get(tracer_port),
+ Tracer = start_tracer(Config),
+ TracerMonitor = erlang:monitor(process, Tracer),
+ Port = get(tracer_port),
%%
- ?line N = erlang:trace(all, true, [send, {tracer, Port}]),
- ?line {flags, [send]} = erlang:trace_info(self(), flags),
- ?line {tracer, Port} = erlang:trace_info(self(), tracer),
- ?line {flags, [send]} = erlang:trace_info(new, flags),
- ?line {tracer, Port} = erlang:trace_info(new, tracer),
- ?line G1 = fun_spawn(fun general/0),
- ?line {flags, [send]} = erlang:trace_info(G1, flags),
- ?line {tracer, Port} = erlang:trace_info(G1, tracer),
- ?line unlink(Tracer),
- ?line exit(Port, done),
- ?line receive
- {'DOWN', TracerMonitor, process, Tracer, TracerExitReason} ->
- ?line done = TracerExitReason
- end,
- ?line {flags, []} = erlang:trace_info(self(), flags),
- ?line {tracer, []} = erlang:trace_info(self(), tracer),
- ?line {flags, []} = erlang:trace_info(new, flags),
- ?line {tracer, []} = erlang:trace_info(new, tracer),
- ?line M = erlang:trace(all, false, [all]),
- ?line {flags, []} = erlang:trace_info(self(), flags),
- ?line {tracer, []} = erlang:trace_info(self(), tracer),
- ?line {flags, []} = erlang:trace_info(G1, flags),
- ?line {tracer, []} = erlang:trace_info(G1, tracer),
- ?line G1 ! {apply,{erlang,exit,[normal]}},
- ?line io:format("~p = ~p.~n", [M, N]),
- ?line M = N,
+ N = erlang:trace(all, true, [send, {tracer, Port}]),
+ {flags, [send]} = erlang:trace_info(self(), flags),
+ {tracer, Port} = erlang:trace_info(self(), tracer),
+ {flags, [send]} = erlang:trace_info(new, flags),
+ {tracer, Port} = erlang:trace_info(new, tracer),
+ G1 = fun_spawn(fun general/0),
+ {flags, [send]} = erlang:trace_info(G1, flags),
+ {tracer, Port} = erlang:trace_info(G1, tracer),
+ unlink(Tracer),
+ exit(Port, done),
+ receive
+ {'DOWN', TracerMonitor, process, Tracer, TracerExitReason} ->
+ done = TracerExitReason
+ end,
+ {flags, []} = erlang:trace_info(self(), flags),
+ {tracer, []} = erlang:trace_info(self(), tracer),
+ {flags, []} = erlang:trace_info(new, flags),
+ {tracer, []} = erlang:trace_info(new, tracer),
+ M = erlang:trace(all, false, [all]),
+ {flags, []} = erlang:trace_info(self(), flags),
+ {tracer, []} = erlang:trace_info(self(), tracer),
+ {flags, []} = erlang:trace_info(G1, flags),
+ {tracer, []} = erlang:trace_info(G1, tracer),
+ G1 ! {apply,{erlang,exit,[normal]}},
+ io:format("~p = ~p.~n", [M, N]),
+ M = N,
ok.
tracer_port_crash(Config) when is_list(Config) ->
case test_server:is_native(?MODULE) orelse
- test_server:is_native(lists) of
- true ->
- {skip,"Native code"};
- false ->
- Tr = start_tracer(Config),
- Port = get(tracer_port),
- Tracee = spawn(fun () ->
- register(trace_port_linker, self()),
- link(Port),
- receive go -> ok end,
- lists:reverse([1,b,c]),
- receive die -> ok end
- end),
- Tr ! {unlink_tracer_port, self()},
- receive {unlinked_tracer_port, Tr} -> ok end,
- port_control(Port, $c, []), %% Make port commands crash tracer port...
- trace_func({lists,reverse,1}, []),
- trace_pid(Tracee, true, [call]),
- trace_info(Tracee, flags),
- trace_info(self(), tracer),
- Tracee ! go,
- receive after 1000 -> ok end,
- case whereis(trace_port_linker) of
- undefined ->
- ok;
- Id ->
-% erts_debug:set_internal_state(available_internal_state, true),
-% erts_debug:set_internal_state(abort, {trace_port_linker, Id})
- ?t:fail({trace_port_linker, Id})
- end,
- undefined = process_info(Tracee),
- ok
+ test_server:is_native(lists) of
+ true ->
+ {skip,"Native code"};
+ false ->
+ Tr = start_tracer(Config),
+ Port = get(tracer_port),
+ Tracee = spawn(fun () ->
+ register(trace_port_linker, self()),
+ link(Port),
+ receive go -> ok end,
+ lists:reverse([1,b,c]),
+ receive die -> ok end
+ end),
+ Tr ! {unlink_tracer_port, self()},
+ receive {unlinked_tracer_port, Tr} -> ok end,
+ port_control(Port, $c, []), %% Make port commands crash tracer port...
+ trace_func({lists,reverse,1}, []),
+ trace_pid(Tracee, true, [call]),
+ trace_info(Tracee, flags),
+ trace_info(self(), tracer),
+ Tracee ! go,
+ receive after 1000 -> ok end,
+ case whereis(trace_port_linker) of
+ undefined ->
+ ok;
+ Id ->
+ % erts_debug:set_internal_state(available_internal_state, true),
+ % erts_debug:set_internal_state(abort, {trace_port_linker, Id})
+ ct:fail({trace_port_linker, Id})
+ end,
+ undefined = process_info(Tracee),
+ ok
end.
%%% Help functions.
@@ -523,106 +492,106 @@ huge_data(N) ->
expect() ->
receive
- Other ->
- ok = io:format("Unexpected; got ~p", [Other]),
- test_server:fail({unexpected, Other})
+ Other ->
+ ok = io:format("Unexpected; got ~p", [Other]),
+ ct:fail({unexpected, Other})
after 200 ->
- ok
+ ok
end.
expect({trace_ts,E1,E2,info,ts}=Message) ->
receive
- {trace_ts,E1,E2,_Info,_Ts}=MessageTs ->
- ok = io:format("Expected and got ~p", [MessageTs]),
- MessageTs;
- Other ->
- io:format("Expected ~p; got ~p", [Message,Other]),
- test_server:fail({unexpected,Other})
+ {trace_ts,E1,E2,_Info,_Ts}=MessageTs ->
+ ok = io:format("Expected and got ~p", [MessageTs]),
+ MessageTs;
+ Other ->
+ io:format("Expected ~p; got ~p", [Message,Other]),
+ ct:fail({unexpected,Other})
after 5000 ->
- io:format("Expected ~p; got nothing", [Message]),
- test_server:fail(no_trace_message)
+ io:format("Expected ~p; got nothing", [Message]),
+ ct:fail(no_trace_message)
end;
expect({trace,E1,E2,info}=Message) ->
receive
- {trace,E1,E2,_Info}=MessageTs ->
- ok = io:format("Expected and got ~p", [MessageTs]),
- MessageTs;
- Other ->
- io:format("Expected ~p; got ~p", [Message,Other]),
- test_server:fail({unexpected,Other})
+ {trace,E1,E2,_Info}=MessageTs ->
+ ok = io:format("Expected and got ~p", [MessageTs]),
+ MessageTs;
+ Other ->
+ io:format("Expected ~p; got ~p", [Message,Other]),
+ ct:fail({unexpected,Other})
after 5000 ->
- io:format("Expected ~p; got nothing", [Message]),
- test_server:fail(no_trace_message)
+ io:format("Expected ~p; got nothing", [Message]),
+ ct:fail(no_trace_message)
end;
expect({trace_ts,E1,E2,E3,ts}=Message) ->
receive
- {trace_ts,E1,E2,E3,_Ts}=MessageTs ->
- ok = io:format("Expected and got ~p", [MessageTs]),
- MessageTs;
- Other ->
- io:format("Expected ~p; got ~p", [Message,Other]),
- test_server:fail({unexpected,Other})
+ {trace_ts,E1,E2,E3,_Ts}=MessageTs ->
+ ok = io:format("Expected and got ~p", [MessageTs]),
+ MessageTs;
+ Other ->
+ io:format("Expected ~p; got ~p", [Message,Other]),
+ ct:fail({unexpected,Other})
after 5000 ->
- io:format("Expected ~p; got nothing", [Message]),
- test_server:fail(no_trace_message)
+ io:format("Expected ~p; got nothing", [Message]),
+ ct:fail(no_trace_message)
end;
expect({trace_ts,E1,E2,E3,E4,ts}=Message) ->
receive
- {trace_ts,E1,E2,E3,E4,_Ts}=MessageTs ->
- ok = io:format("Expected and got ~p", [MessageTs]),
- MessageTs;
- Other ->
- io:format("Expected ~p; got ~p", [Message,Other]),
- test_server:fail({unexpected,Other})
+ {trace_ts,E1,E2,E3,E4,_Ts}=MessageTs ->
+ ok = io:format("Expected and got ~p", [MessageTs]),
+ MessageTs;
+ Other ->
+ io:format("Expected ~p; got ~p", [Message,Other]),
+ ct:fail({unexpected,Other})
after 5000 ->
- io:format("Expected ~p; got nothing", [Message]),
- test_server:fail(no_trace_message)
+ io:format("Expected ~p; got nothing", [Message]),
+ ct:fail(no_trace_message)
end;
expect(Message) ->
receive
- Message ->
- ok = io:format("Expected and got ~p", [Message]),
- Message;
- Other ->
- io:format("Expected ~p; got ~p", [Message,Other]),
- test_server:fail({unexpected,Other})
+ Message ->
+ ok = io:format("Expected and got ~p", [Message]),
+ Message;
+ Other ->
+ io:format("Expected ~p; got ~p", [Message,Other]),
+ ct:fail({unexpected,Other})
after 5000 ->
- io:format("Expected ~p; got nothing", [Message]),
- test_server:fail(no_trace_message)
+ io:format("Expected ~p; got nothing", [Message]),
+ ct:fail(no_trace_message)
end.
trac(What, On, Flags0) ->
Flags = [{tracer,get(tracer_port)}|Flags0],
get(tracer) ! {apply,self(),{erlang,trace,[What,On,Flags]}},
Res = receive
- {apply_result,Result} -> Result
- end,
+ {apply_result,Result} -> Result
+ end,
ok = io:format("erlang:trace(~p, ~p, ~p) -> ~p",
- [What,On,Flags,Res]),
+ [What,On,Flags,Res]),
Res.
-
+
trace_info(What, Key) ->
get(tracer) ! {apply,self(),{erlang,trace_info,[What,Key]}},
Res = receive
- {apply_result,Result} -> Result
- end,
+ {apply_result,Result} -> Result
+ end,
ok = io:format("erlang:trace_info(~p, ~p) -> ~p",
- [What,Key,Res]),
+ [What,Key,Res]),
Res.
-
+
trace_func(MFA, MatchProg) ->
get(tracer) ! {apply,self(),{erlang,trace_pattern,[MFA,MatchProg]}},
Res = receive
- {apply_result,Result} -> Result
- end,
+ {apply_result,Result} -> Result
+ end,
ok = io:format("erlang:trace_pattern(~p, ~p) -> ~p", [MFA,MatchProg,Res]),
Res.
trace_func(MFA, MatchProg, Flags) ->
get(tracer) ! {apply,self(),{erlang,trace_pattern,[MFA,MatchProg,Flags]}},
Res = receive
- {apply_result,Result} -> Result
- end,
+ {apply_result,Result} -> Result
+ end,
ok = io:format("erlang:trace_pattern(~p, ~p) -> ~p", [MFA,MatchProg,Res]),
Res.
@@ -630,29 +599,29 @@ trace_pid(Pid, On, Flags0) ->
Flags = [{tracer,get(tracer_port)}|Flags0],
get(tracer) ! {apply,self(),{erlang,trace,[Pid,On,Flags]}},
Res = receive
- {apply_result,Result} -> Result
- end,
+ {apply_result,Result} -> Result
+ end,
ok = io:format("erlang:trace(~p, ~p, ~p) -> ~p",
- [Pid,On,Flags,Res]),
+ [Pid,On,Flags,Res]),
Res.
start_tracer(Config) ->
- Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
ok = load_driver(Path, echo_drv),
Self = self(),
put(tracer, fun_spawn(fun() -> tracer(Self) end)),
receive
- {started,Port} ->
- put(tracer_port, Port)
+ {started,Port} ->
+ put(tracer_port, Port)
end,
get(tracer).
load_driver(Dir, Driver) ->
case erl_ddll:load_driver(Dir, Driver) of
- ok -> ok;
- {error, Error} = Res ->
- io:format("~s\n", [erl_ddll:format_error(Error)]),
- Res
+ ok -> ok;
+ {error, Error} = Res ->
+ io:format("~s\n", [erl_ddll:format_error(Error)]),
+ Res
end.
tracer(RelayTo) ->
@@ -662,18 +631,18 @@ tracer(RelayTo) ->
tracer_loop(RelayTo, Port) ->
receive
- {apply,From,{M,F,A}} ->
- From ! {apply_result,apply(M, F, A)},
- tracer_loop(RelayTo, Port);
- {Port,{data,Msg}} ->
- RelayTo ! binary_to_term(Msg),
- tracer_loop(RelayTo, Port);
- {unlink_tracer_port, From} ->
- unlink(Port),
- From ! {unlinked_tracer_port, self()},
- tracer_loop(RelayTo, Port);
- Other ->
- exit({bad_message,Other})
+ {apply,From,{M,F,A}} ->
+ From ! {apply_result,apply(M, F, A)},
+ tracer_loop(RelayTo, Port);
+ {Port,{data,Msg}} ->
+ RelayTo ! binary_to_term(Msg),
+ tracer_loop(RelayTo, Port);
+ {unlink_tracer_port, From} ->
+ unlink(Port),
+ From ! {unlinked_tracer_port, self()},
+ tracer_loop(RelayTo, Port);
+ Other ->
+ exit({bad_message,Other})
end.
fun_spawn(Fun) ->
@@ -697,43 +666,43 @@ fun_spawn(Fun, Opts) ->
sender() ->
receive
- {send_please, To, What} ->
- To ! What,
- sender()
+ {send_please, To, What} ->
+ To ! What,
+ sender()
end.
%% Just consumes messages from its message queue.
receiver() ->
receive
- _Any -> receiver()
+ _Any -> receiver()
end.
%% Does a garbage collection when it receives a message.
garber() ->
receive
- _Any ->
- lists:seq(1, 100),
- erlang:garbage_collect(),
- garber()
+ _Any ->
+ lists:seq(1, 100),
+ erlang:garbage_collect(),
+ garber()
end.
%% All-purpose process
general() ->
receive
- {apply, {M, F, Args}} ->
- erlang:apply(M, F, Args),
- general();
- {send, Dest, Msg} ->
- Dest ! Msg,
- general();
- {call_f_1, Arg} ->
- f(Arg),
- general();
- nop ->
- general()
+ {apply, {M, F, Args}} ->
+ erlang:apply(M, F, Args),
+ general();
+ {send, Dest, Msg} ->
+ Dest ! Msg,
+ general();
+ {call_f_1, Arg} ->
+ f(Arg),
+ general();
+ nop ->
+ general()
end.
f(Arg) ->
diff --git a/erts/emulator/test/tuple_SUITE.erl b/erts/emulator/test/tuple_SUITE.erl
index f1f077be6b..d59d7d12d3 100644
--- a/erts/emulator/test/tuple_SUITE.erl
+++ b/erts/emulator/test/tuple_SUITE.erl
@@ -26,7 +26,7 @@
t_make_tuple_2/1, t_make_upper_boundry_tuple_2/1, t_make_tuple_3/1,
t_append_element/1, t_append_element_upper_boundry/1,
build_and_match/1, tuple_with_case/1, tuple_in_guard/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Tests tuples and the BIFs:
%%
@@ -64,7 +64,7 @@ init_per_suite(Config) ->
[{started_apps, A}|Config].
end_per_suite(Config) ->
- As = ?config(started_apps, Config),
+ As = proplists:get_value(started_apps, Config),
lists:foreach(fun (A) -> application:stop(A) end, As),
Config.
@@ -259,7 +259,7 @@ t_make_tuple(Size, Element) ->
lists:foreach(fun(El) when El =:= Element ->
ok;
(Other) ->
- test_server:fail({got, Other, expected, Element})
+ ct:fail({got, Other, expected, Element})
end, tuple_to_list(Tuple)).
%% Tests the erlang:make_tuple/3 BIF.
@@ -385,14 +385,14 @@ tuple_in_guard(Config) when is_list(Config) ->
Tuple1 == {element(1, Tuple2),element(2, Tuple2)} ->
ok;
true ->
- test_server:fail()
+ ct:fail("failed")
end,
if
Tuple2 == {element(1, Tuple2),element(2, Tuple2),
element(3, Tuple2)} ->
ok;
true ->
- test_server:fail()
+ ct:fail("failed")
end,
ok.
diff --git a/erts/emulator/test/unique_SUITE.erl b/erts/emulator/test/unique_SUITE.erl
index 6fa634b886..e8537e6152 100644
--- a/erts/emulator/test/unique_SUITE.erl
+++ b/erts/emulator/test/unique_SUITE.erl
@@ -20,38 +20,25 @@
-module(unique_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2]).
+-export([all/0, suite/0, init_per_suite/1, end_per_suite/1]).
-export([unique_monotonic_integer_white_box/1,
unique_integer_white_box/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%-define(P(V), V).
-define(P(V), print_ret_val(?FILE, ?LINE, V)).
-define(PRINT(V), print_ret_val(?FILE, ?LINE, V)).
-
-init_per_testcase(Case, Config) ->
- ?line Dog=test_server:timetrap(test_server:minutes(2)),
- [{watchdog, Dog}, {testcase, Case}|Config].
-
-end_per_testcase(_, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 4}}].
all() ->
[unique_monotonic_integer_white_box,
unique_integer_white_box].
-groups() ->
- [].
-
init_per_suite(Config) ->
erts_debug:set_internal_state(available_internal_state, true),
Config.
@@ -60,12 +47,6 @@ end_per_suite(_Config) ->
erts_debug:set_internal_state(available_internal_state, false),
ok.
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
%%
%%
%% Unique counter white box test case
@@ -80,15 +61,15 @@ unique_monotonic_integer_white_box(Config) when is_list(Config) ->
%% the system when moving the strict monotonic counter
%% around in a non-strict monotonic way...
Test = spawn(Node,
- fun () ->
- unique_monotonic_integer_white_box_test(TestServer, Success)
- end),
+ fun () ->
+ unique_monotonic_integer_white_box_test(TestServer, Success)
+ end),
Mon = erlang:monitor(process, Test),
receive
- {'DOWN', Mon, process, Test, Error} ->
- ?t:fail(Error);
- Success ->
- ok
+ {'DOWN', Mon, process, Test, Error} ->
+ ct:fail(Error);
+ Success ->
+ ok
end,
erlang:demonitor(Mon, [flush]),
stop_node(Node),
@@ -96,9 +77,9 @@ unique_monotonic_integer_white_box(Config) when is_list(Config) ->
set_unique_monotonic_integer_state(MinCounter, NextValue) ->
true = erts_debug:set_internal_state(unique_monotonic_integer_state,
- NextValue-MinCounter-1).
-
-
+ NextValue-MinCounter-1).
+
+
unique_monotonic_integer_white_box_test(TestServer, Success) ->
erts_debug:set_internal_state(available_internal_state, true),
@@ -130,10 +111,10 @@ unique_monotonic_integer_white_box_test(TestServer, Success) ->
?PRINT({max_counter, MaxCounter}),
case WordSize of
- 4 ->
- MinCounter = MinSint64;
- 8 ->
- MinCounter = MinSmall
+ 4 ->
+ MinCounter = MinSint64;
+ 8 ->
+ MinCounter = MinSmall
end,
StartState = erts_debug:get_internal_state(unique_monotonic_integer_state),
@@ -141,20 +122,20 @@ unique_monotonic_integer_white_box_test(TestServer, Success) ->
%% Verify that we get expected results over all internal limits...
case MinCounter < MinSmall of
- false ->
- 8 = WordSize,
- ok;
- true ->
- 4 = WordSize,
- ?PRINT(over_min_small),
- set_unique_monotonic_integer_state(MinCounter, MinSmall-2),
- true = (?P(erlang:unique_integer([monotonic])) == MinSmall - 2),
- true = (?P(erlang:unique_integer([monotonic])) == MinSmall - 1),
- true = (?P(erlang:unique_integer([monotonic])) == MinSmall),
- true = (?P(erlang:unique_integer([monotonic])) == MinSmall + 1),
- true = (?P(erlang:unique_integer([monotonic])) == MinSmall + 2),
- garbage_collect(),
- ok
+ false ->
+ 8 = WordSize,
+ ok;
+ true ->
+ 4 = WordSize,
+ ?PRINT(over_min_small),
+ set_unique_monotonic_integer_state(MinCounter, MinSmall-2),
+ true = (?P(erlang:unique_integer([monotonic])) == MinSmall - 2),
+ true = (?P(erlang:unique_integer([monotonic])) == MinSmall - 1),
+ true = (?P(erlang:unique_integer([monotonic])) == MinSmall),
+ true = (?P(erlang:unique_integer([monotonic])) == MinSmall + 1),
+ true = (?P(erlang:unique_integer([monotonic])) == MinSmall + 2),
+ garbage_collect(),
+ ok
end,
?PRINT(over_zero), %% Not really an interesting limit, but...
@@ -176,27 +157,27 @@ unique_monotonic_integer_white_box_test(TestServer, Success) ->
garbage_collect(),
case MaxCounter > MaxSint64 of
- false ->
- 4 = WordSize,
- ok;
- true ->
- 8 = WordSize,
- ?PRINT(over_max_sint64),
- set_unique_monotonic_integer_state(MinCounter, MaxSint64-2),
- true = (?P(erlang:unique_integer([monotonic])) == MaxSint64 - 2),
- true = (?P(erlang:unique_integer([monotonic])) == MaxSint64 - 1),
- true = (?P(erlang:unique_integer([monotonic])) == MaxSint64),
- true = (?P(erlang:unique_integer([monotonic])) == MaxSint64 + 1),
- true = (?P(erlang:unique_integer([monotonic])) == MaxSint64 + 2),
- garbage_collect()
+ false ->
+ 4 = WordSize,
+ ok;
+ true ->
+ 8 = WordSize,
+ ?PRINT(over_max_sint64),
+ set_unique_monotonic_integer_state(MinCounter, MaxSint64-2),
+ true = (?P(erlang:unique_integer([monotonic])) == MaxSint64 - 2),
+ true = (?P(erlang:unique_integer([monotonic])) == MaxSint64 - 1),
+ true = (?P(erlang:unique_integer([monotonic])) == MaxSint64),
+ true = (?P(erlang:unique_integer([monotonic])) == MaxSint64 + 1),
+ true = (?P(erlang:unique_integer([monotonic])) == MaxSint64 + 2),
+ garbage_collect()
end,
?PRINT(over_max_min_counter),
set_unique_monotonic_integer_state(MinCounter, if MaxCounter == MaxSint64 ->
- MaxCounter-2;
- true ->
- MinCounter-3
- end),
+ MaxCounter-2;
+ true ->
+ MinCounter-3
+ end),
true = (?P(erlang:unique_integer([monotonic])) == MaxCounter - 2),
true = (?P(erlang:unique_integer([monotonic])) == MaxCounter - 1),
true = (?P(erlang:unique_integer([monotonic])) == MaxCounter),
@@ -208,7 +189,7 @@ unique_monotonic_integer_white_box_test(TestServer, Success) ->
%% Restore initial state and hope we didn't mess it up for the
%% system...
true = erts_debug:set_internal_state(unique_monotonic_integer_state,
- StartState),
+ StartState),
TestServer ! Success.
@@ -219,16 +200,16 @@ unique_monotonic_integer_white_box_test(TestServer, Success) ->
%%
-record(uniqint_info, {min_int,
- max_int,
- max_small,
- schedulers,
- sched_bits}).
+ max_int,
+ max_small,
+ schedulers,
+ sched_bits}).
unique_integer_white_box(Config) when is_list(Config) ->
UinqintInfo = init_uniqint_info(),
#uniqint_info{min_int = MinInt,
- max_int = MaxInt,
- max_small = MaxSmall} = UinqintInfo,
+ max_int = MaxInt,
+ max_small = MaxSmall} = UinqintInfo,
io:format("****************************************************~n", []),
io:format("*** Around MIN_UNIQ_INT ~p ***~n", [MinInt]),
io:format("****************************************************~n", []),
@@ -258,7 +239,7 @@ unique_integer_white_box(Config) when is_list(Config) ->
io:format("****************************************************~n", []),
check_unique_integer_around(MaxInt, UinqintInfo),
ok.
-
+
%%% Internal unique_integer_white_box/1 test case
@@ -267,10 +248,21 @@ calc_sched_bits(NoScheds, Shift) when NoScheds < 1 bsl Shift ->
calc_sched_bits(NoScheds, Shift) ->
calc_sched_bits(NoScheds, Shift+1).
+schedulers() ->
+ S = erlang:system_info(schedulers),
+ try
+ DCPUS = erlang:system_info(dirty_cpu_schedulers),
+ DIOS = erlang:system_info(dirty_io_schedulers),
+ S+DCPUS+DIOS
+ catch
+ _ : _ ->
+ S
+ end.
+
init_uniqint_info() ->
SmallBits = erlang:system_info({wordsize, internal})*8-4,
io:format("SmallBits=~p~n", [SmallBits]),
- Schedulers = erlang:system_info(schedulers),
+ Schedulers = schedulers(),
io:format("Schedulers=~p~n", [Schedulers]),
MinSmall = -1*(1 bsl (SmallBits-1)),
io:format("MinSmall=~p~n", [MinSmall]),
@@ -281,33 +273,33 @@ init_uniqint_info() ->
MaxInt = ((((1 bsl 64) - 1) bsl SchedBits) bor Schedulers) + MinSmall,
io:format("MaxInt=~p~n", [MaxInt]),
#uniqint_info{min_int = MinSmall,
- max_int = MaxInt,
- max_small = MaxSmall,
- schedulers = Schedulers,
- sched_bits = SchedBits}.
+ max_int = MaxInt,
+ max_small = MaxSmall,
+ schedulers = Schedulers,
+ sched_bits = SchedBits}.
valid_uniqint(Int, #uniqint_info{min_int = MinInt} = UinqintInfo) when Int < MinInt ->
valid_uniqint(MinInt, UinqintInfo);
valid_uniqint(Int, #uniqint_info{min_int = MinInt,
- sched_bits = SchedBits,
- schedulers = Scheds}) ->
+ sched_bits = SchedBits,
+ schedulers = Scheds}) ->
Int1 = Int - MinInt,
{Inc, ThreadNo} = case Int1 band ((1 bsl SchedBits) - 1) of
- TN when TN > Scheds ->
- {1, Scheds};
- TN ->
- {0, TN}
- end,
+ TN when TN > Scheds ->
+ {1, Scheds};
+ TN ->
+ {0, TN}
+ end,
Counter = ((Int1 bsr SchedBits) + Inc) rem (1 bsl 64),
((Counter bsl SchedBits) bor ThreadNo) + MinInt.
smaller_valid_uniqint(Int, UinqintInfo) ->
Cand = Int-1,
case valid_uniqint(Cand, UinqintInfo) of
- RI when RI < Int ->
- RI;
- _ ->
- smaller_valid_uniqint(Cand, UinqintInfo)
+ RI when RI < Int ->
+ RI;
+ _ ->
+ smaller_valid_uniqint(Cand, UinqintInfo)
end.
int32_to_bigendian_list(Int) ->
@@ -318,7 +310,7 @@ int32_to_bigendian_list(Int) ->
Int band 16#ff].
mk_uniqint(Int, #uniqint_info {min_int = MinInt,
- sched_bits = SchedBits} = _UinqintInfo) ->
+ sched_bits = SchedBits} = _UinqintInfo) ->
Int1 = Int - MinInt,
ThrId = Int1 band ((1 bsl SchedBits) - 1),
Value = (Int1 bsr SchedBits) band ((1 bsl 64) - 1),
@@ -334,36 +326,36 @@ check_uniqint(Int, UinqintInfo) ->
UniqInt = mk_uniqint(Int, UinqintInfo),
io:format("UniqInt=~p ", [UniqInt]),
case UniqInt =:= Int of
- true ->
- io:format("OK~n~n", []);
- false ->
- io:format("result UniqInt=~p FAILED~n", [UniqInt]),
- exit(badres)
+ true ->
+ io:format("OK~n~n", []);
+ false ->
+ io:format("result Int=~p FAILED~n", [Int]),
+ exit(badres)
end.
check_unique_integer_around(Int, #uniqint_info{min_int = MinInt,
- max_int = MaxInt} = UinqintInfo) ->
+ max_int = MaxInt} = UinqintInfo) ->
{Start, End} = case {Int =< MinInt+100, Int >= MaxInt-100} of
- {true, false} ->
- {MinInt, MinInt+100};
- {false, false} ->
- {smaller_valid_uniqint(Int-100, UinqintInfo),
- valid_uniqint(Int+100, UinqintInfo)};
- {false, true} ->
- {MaxInt-100, MaxInt}
- end,
+ {true, false} ->
+ {MinInt, MinInt+100};
+ {false, false} ->
+ {smaller_valid_uniqint(Int-100, UinqintInfo),
+ valid_uniqint(Int+100, UinqintInfo)};
+ {false, true} ->
+ {MaxInt-100, MaxInt}
+ end,
lists:foldl(fun (I, OldRefInt) ->
- RefInt = valid_uniqint(I, UinqintInfo),
- case OldRefInt =:= RefInt of
- true ->
- ok;
- false ->
- check_uniqint(RefInt, UinqintInfo)
- end,
- RefInt
- end,
- none,
- lists:seq(Start, End)).
+ RefInt = valid_uniqint(I, UinqintInfo),
+ case OldRefInt =:= RefInt of
+ true ->
+ ok;
+ false ->
+ check_uniqint(RefInt, UinqintInfo)
+ end,
+ RefInt
+ end,
+ none,
+ lists:seq(Start, End)).
%% helpers
@@ -375,17 +367,17 @@ print_ret_val(File, Line, Value) ->
start_node(Config) ->
start_node(Config, []).
start_node(Config, Opts) when is_list(Config), is_list(Opts) ->
- ?line Pa = filename:dirname(code:which(?MODULE)),
- ?line A = erlang:monotonic_time(1) + erlang:time_offset(1),
- ?line B = erlang:unique_integer([positive]),
- ?line Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(?config(testcase, Config))
- ++ "-"
- ++ integer_to_list(A)
- ++ "-"
- ++ integer_to_list(B)),
- ?line ?t:start_node(Name, slave, [{args, Opts++" -pa "++Pa}]).
+ Pa = filename:dirname(code:which(?MODULE)),
+ A = erlang:monotonic_time(1) + erlang:time_offset(1),
+ B = erlang:unique_integer([positive]),
+ Name = list_to_atom(atom_to_list(?MODULE)
+ ++ "-"
+ ++ atom_to_list(proplists:get_value(testcase, Config))
+ ++ "-"
+ ++ integer_to_list(A)
+ ++ "-"
+ ++ integer_to_list(B)),
+ test_server:start_node(Name, slave, [{args, Opts++" -pa "++Pa}]).
stop_node(Node) ->
- ?t:stop_node(Node).
+ test_server:stop_node(Node).
diff --git a/erts/emulator/test/z_SUITE.erl b/erts/emulator/test/z_SUITE.erl
index f4d9030255..93a03e8f91 100644
--- a/erts/emulator/test/z_SUITE.erl
+++ b/erts/emulator/test/z_SUITE.erl
@@ -30,148 +30,117 @@
%-define(line_trace, 1).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-%-compile(export_all).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2, init_per_testcase/2,
- end_per_testcase/2]).
+-export([all/0, suite/0]).
-export([schedulers_alive/1, node_container_refc_check/1,
long_timers/1, pollset_size/1,
check_io_debug/1, get_check_io_info/0]).
--define(DEFAULT_TIMEOUT, ?t:minutes(5)).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 5}}].
all() ->
[schedulers_alive, node_container_refc_check,
long_timers, pollset_size, check_io_debug].
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(_Case, Config) when is_list(Config) ->
- Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) when is_list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
- ok.
-
%%%
%%% The test cases -------------------------------------------------------------
%%%
-schedulers_alive(doc) -> ["Tests that all schedulers are actually used"];
-schedulers_alive(suite) -> [];
+%% Tests that all schedulers are actually used
schedulers_alive(Config) when is_list(Config) ->
- ?line Master = self(),
- ?line NoSchedulersOnline = erlang:system_flag(
- schedulers_online,
- erlang:system_info(schedulers)),
- ?line NoSchedulers = erlang:system_info(schedulers),
+ Master = self(),
+ NoSchedulersOnline = erlang:system_flag(
+ schedulers_online,
+ erlang:system_info(schedulers)),
+ NoSchedulers = erlang:system_info(schedulers),
UsedScheds =
- try
- ?line ?t:format("Number of schedulers configured: ~p~n", [NoSchedulers]),
- ?line case erlang:system_info(multi_scheduling) of
- blocked ->
- ?line ?t:fail(multi_scheduling_blocked);
- disabled ->
- ?line ok;
- enabled ->
- ?t:format("Testing blocking process exit~n"),
- BF = fun () ->
- blocked = erlang:system_flag(multi_scheduling,
- block),
- Master ! {self(), blocking},
- receive after infinity -> ok end
- end,
- ?line Blocker = spawn_link(BF),
- ?line Mon = erlang:monitor(process, Blocker),
- ?line receive {Blocker, blocking} -> ok end,
- ?line [Blocker]
- = erlang:system_info(multi_scheduling_blockers),
- ?line unlink(Blocker),
- ?line exit(Blocker, kill),
- ?line receive {'DOWN', Mon, _, _, _} -> ok end,
- ?line enabled = erlang:system_info(multi_scheduling),
- ?line [] = erlang:system_info(multi_scheduling_blockers),
- ?line ok
- end,
- ?t:format("Testing blocked~n"),
- ?line erlang:system_flag(multi_scheduling, block),
- ?line case erlang:system_info(multi_scheduling) of
- enabled ->
- ?line ?t:fail(multi_scheduling_enabled);
- blocked ->
- ?line [Master] = erlang:system_info(multi_scheduling_blockers);
- disabled -> ?line ok
- end,
- ?line Ps = lists:map(
- fun (_) ->
- spawn_link(fun () ->
- run_on_schedulers(none,
- [],
- Master)
- end)
- end,
- lists:seq(1,NoSchedulers)),
- ?line receive after 1000 -> ok end,
- ?line {_, 1} = verify_all_schedulers_used({[],0}, 1),
- ?line lists:foreach(fun (P) ->
- unlink(P),
- exit(P, bang)
- end,
- Ps),
- ?line case erlang:system_flag(multi_scheduling, unblock) of
- blocked -> ?line ?t:fail(multi_scheduling_blocked);
- disabled -> ?line ok;
- enabled -> ?line ok
- end,
- erts_debug:set_internal_state(available_internal_state, true),
- %% node_and_dist_references will use emulator interal thread blocking...
- erts_debug:get_internal_state(node_and_dist_references),
- erts_debug:set_internal_state(available_internal_state, false),
- ?t:format("Testing not blocked~n"),
- ?line Ps2 = lists:map(
- fun (_) ->
- spawn_link(fun () ->
- run_on_schedulers(none,
- [],
- Master)
- end)
- end,
- lists:seq(1,NoSchedulers)),
- ?line receive after 1000 -> ok end,
- ?line {_, NoSIDs} = verify_all_schedulers_used({[],0},NoSchedulers),
- ?line lists:foreach(fun (P) ->
- unlink(P),
- exit(P, bang)
- end,
- Ps2),
- NoSIDs
- after
- NoSchedulers = erlang:system_flag(schedulers_online,
- NoSchedulersOnline),
- NoSchedulersOnline = erlang:system_info(schedulers_online)
- end,
- ?line {comment, "Number of schedulers " ++ integer_to_list(UsedScheds)}.
+ try
+ io:format("Number of schedulers configured: ~p~n", [NoSchedulers]),
+ case erlang:system_info(multi_scheduling) of
+ blocked ->
+ ct:fail(multi_scheduling_blocked);
+ disabled ->
+ ok;
+ enabled ->
+ io:format("Testing blocking process exit~n"),
+ BF = fun () ->
+ blocked = erlang:system_flag(multi_scheduling,
+ block),
+ Master ! {self(), blocking},
+ receive after infinity -> ok end
+ end,
+ Blocker = spawn_link(BF),
+ Mon = erlang:monitor(process, Blocker),
+ receive {Blocker, blocking} -> ok end,
+ [Blocker]
+ = erlang:system_info(multi_scheduling_blockers),
+ unlink(Blocker),
+ exit(Blocker, kill),
+ receive {'DOWN', Mon, _, _, _} -> ok end,
+ enabled = erlang:system_info(multi_scheduling),
+ [] = erlang:system_info(multi_scheduling_blockers),
+ ok
+ end,
+ io:format("Testing blocked~n"),
+ erlang:system_flag(multi_scheduling, block),
+ case erlang:system_info(multi_scheduling) of
+ enabled ->
+ ct:fail(multi_scheduling_enabled);
+ blocked ->
+ [Master] = erlang:system_info(multi_scheduling_blockers);
+ disabled -> ok
+ end,
+ Ps = lists:map(
+ fun (_) ->
+ spawn_link(fun () ->
+ run_on_schedulers(none,
+ [],
+ Master)
+ end)
+ end,
+ lists:seq(1,NoSchedulers)),
+ receive after 1000 -> ok end,
+ {_, 1} = verify_all_schedulers_used({[],0}, 1),
+ lists:foreach(fun (P) ->
+ unlink(P),
+ exit(P, bang)
+ end, Ps),
+ case erlang:system_flag(multi_scheduling, unblock) of
+ blocked -> ct:fail(multi_scheduling_blocked);
+ disabled -> ok;
+ enabled -> ok
+ end,
+ erts_debug:set_internal_state(available_internal_state, true),
+ %% node_and_dist_references will use emulator interal thread blocking...
+ erts_debug:get_internal_state(node_and_dist_references),
+ erts_debug:set_internal_state(available_internal_state, false),
+ io:format("Testing not blocked~n"),
+ Ps2 = lists:map(
+ fun (_) ->
+ spawn_link(fun () ->
+ run_on_schedulers(none,
+ [],
+ Master)
+ end)
+ end,
+ lists:seq(1,NoSchedulers)),
+ receive after 1000 -> ok end,
+ {_, NoSIDs} = verify_all_schedulers_used({[],0},NoSchedulers),
+ lists:foreach(fun (P) ->
+ unlink(P),
+ exit(P, bang)
+ end, Ps2),
+ NoSIDs
+ after
+ NoSchedulers = erlang:system_flag(schedulers_online,
+ NoSchedulersOnline),
+ NoSchedulersOnline = erlang:system_info(schedulers_online)
+ end,
+ {comment, "Number of schedulers " ++ integer_to_list(UsedScheds)}.
run_on_schedulers(LastSID, SIDs, ReportTo) ->
@@ -198,65 +167,56 @@ wait_on_used_scheduler({SIDs, SIDsLen} = State) ->
true ->
wait_on_used_scheduler(State);
false ->
- ?t:format("Scheduler ~p used~n", [SID]),
+ io:format("Scheduler ~p used~n", [SID]),
{[SID|SIDs], SIDsLen+1}
end
end.
verify_all_schedulers_used({UsedSIDs, UsedSIDsLen} = State, NoSchedulers) ->
- ?line case NoSchedulers of
+ case NoSchedulers of
UsedSIDsLen ->
- ?line State;
+ State;
NoSchdlrs when NoSchdlrs < UsedSIDsLen ->
- ?line ?t:fail({more_schedulers_used_than_exist,
+ ct:fail({more_schedulers_used_than_exist,
{existing_schedulers, NoSchdlrs},
{used_schedulers, UsedSIDsLen},
{used_scheduler_ids, UsedSIDs}});
_ ->
- ?line NewState = wait_on_used_scheduler(State),
- ?line verify_all_schedulers_used(NewState, NoSchedulers)
+ NewState = wait_on_used_scheduler(State),
+ verify_all_schedulers_used(NewState, NoSchedulers)
end.
-node_container_refc_check(doc) -> [];
-node_container_refc_check(suite) -> [];
node_container_refc_check(Config) when is_list(Config) ->
- ?line node_container_SUITE:node_container_refc_check(node()),
- ?line ok.
+ node_container_SUITE:node_container_refc_check(node()),
+ ok.
-long_timers(doc) ->
- [];
-long_timers(suite) ->
- [];
long_timers(Config) when is_list(Config) ->
- ?line ok = long_timers_test:check_result().
+ ok = long_timers_test:check_result().
-pollset_size(doc) ->
- [];
-pollset_size(suite) ->
- [];
pollset_size(Config) when is_list(Config) ->
- ?line Name = pollset_size_testcase_initial_state_holder,
- ?line Mon = erlang:monitor(process, Name),
- ?line (catch Name ! {get_initial_check_io_result, self()}),
- ?line InitChkIo = receive
+ Name = pollset_size_testcase_initial_state_holder,
+ Mon = erlang:monitor(process, Name),
+ (catch Name ! {get_initial_check_io_result, self()}),
+ InitChkIo = receive
{initial_check_io_result, ICIO} ->
- ?line erlang:demonitor(Mon, [flush]),
- ?line ICIO;
+ erlang:demonitor(Mon, [flush]),
+ ICIO;
{'DOWN', Mon, _, _, Reason} ->
- ?line ?t:fail({non_existing, Name, Reason})
+ ct:fail({non_existing, Name, Reason})
end,
- ?line FinChkIo = get_check_io_info(),
- ?line io:format("Initial: ~p~nFinal: ~p~n", [InitChkIo, FinChkIo]),
- ?line InitPollsetSize = lists:keysearch(total_poll_set_size, 1, InitChkIo),
- ?line FinPollsetSize = lists:keysearch(total_poll_set_size, 1, FinChkIo),
- ?line case InitPollsetSize =:= FinPollsetSize of
+ FinChkIo = get_check_io_info(),
+ io:format("Initial: ~p~nFinal: ~p~n", [InitChkIo, FinChkIo]),
+ InitPollsetSize = lists:keysearch(total_poll_set_size, 1, InitChkIo),
+ FinPollsetSize = lists:keysearch(total_poll_set_size, 1, FinChkIo),
+ HasGethost = case has_gethost() of true -> 1; _ -> 0 end,
+ case InitPollsetSize =:= FinPollsetSize of
true ->
case InitPollsetSize of
{value, {total_poll_set_size, Size}} ->
- ?line {comment,
+ {comment,
"Pollset size: " ++ integer_to_list(Size)};
_ ->
- ?line {skipped,
+ {skipped,
"Pollset size information not available"}
end;
false ->
@@ -265,40 +225,59 @@ pollset_size(Config) when is_list(Config) ->
%% that is ok as long as there are at least 2
%% descriptors (dist listen socket and
%% epmd socket) in the pollset.
- ?line {value, {total_poll_set_size, InitSize}}
+ {value, {total_poll_set_size, InitSize}}
= InitPollsetSize,
- ?line {value, {total_poll_set_size, FinSize}}
+ {value, {total_poll_set_size, FinSize}}
= FinPollsetSize,
- ?line true = FinSize < InitSize,
- ?line true = 2 =< FinSize,
- ?line {comment,
+ true = FinSize < (InitSize + HasGethost),
+ true = 2 =< FinSize,
+ {comment,
"Start pollset size: "
++ integer_to_list(InitSize)
++ " End pollset size: "
++ integer_to_list(FinSize)}
end.
-check_io_debug(doc) ->
- [];
-check_io_debug(suite) ->
- [];
check_io_debug(Config) when is_list(Config) ->
- ?line case lists:keysearch(name, 1, erlang:system_info(check_io)) of
- {value, {name, erts_poll}} -> ?line check_io_debug_test();
- _ -> ?line {skipped, "Not implemented in this emulator"}
+ case lists:keysearch(name, 1, erlang:system_info(check_io)) of
+ {value, {name, erts_poll}} -> check_io_debug_test();
+ _ -> {skipped, "Not implemented in this emulator"}
end.
check_io_debug_test() ->
- ?line erlang:display(get_check_io_info()),
- ?line erts_debug:set_internal_state(available_internal_state, true),
- ?line {NoErrorFds, NoUsedFds, NoDrvSelStructs, NoDrvEvStructs}
+ erlang:display(get_check_io_info()),
+ erts_debug:set_internal_state(available_internal_state, true),
+ {NoErrorFds, NoUsedFds, NoDrvSelStructs, NoDrvEvStructs} = CheckIoDebug
= erts_debug:get_internal_state(check_io_debug),
- ?line erts_debug:set_internal_state(available_internal_state, false),
- ?line 0 = NoErrorFds,
- ?line NoUsedFds = NoDrvSelStructs,
- ?line 0 = NoDrvEvStructs,
- ?line ok.
+ erts_debug:set_internal_state(available_internal_state, false),
+ HasGetHost = has_gethost(),
+ ct:log("check_io_debug: ~p~n"
+ "HasGetHost: ~p",[CheckIoDebug, HasGetHost]),
+ 0 = NoErrorFds,
+ if
+ NoUsedFds == NoDrvSelStructs ->
+ ok;
+ HasGetHost andalso (NoUsedFds == (NoDrvSelStructs - 1)) ->
+ %% If the inet_gethost port is alive, we may have
+ %% one extra used fd that is not selected on.
+ %% This happens when the initial setup of the
+ %% port returns an EAGAIN
+ ok
+ end,
+ 0 = NoDrvEvStructs,
+ ok.
+has_gethost() ->
+ has_gethost(erlang:ports()).
+has_gethost([P|T]) ->
+ case erlang:port_info(P, name) of
+ {name,"inet_gethost"++_} ->
+ true;
+ _ ->
+ has_gethost(T)
+ end;
+has_gethost([]) ->
+ false.
%%
@@ -332,6 +311,3 @@ get_check_io_info() ->
receive after 100 -> ok end,
get_check_io_info()
end.
-
-
-
diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops
index 9a8c3585e6..f805e7cc64 100755
--- a/erts/emulator/utils/beam_makeops
+++ b/erts/emulator/utils/beam_makeops
@@ -48,12 +48,17 @@ $pack_shift[4] = ['0', 'BEAM_LOOSE_SHIFT', # Only for 64 bit wordsize
'(3*BEAM_LOOSE_SHIFT)'];
$pack_mask[2] = ['BEAM_LOOSE_MASK', $WHOLE_WORD];
-$pack_mask[3] = ['BEAM_TIGHT_MASK', 'BEAM_TIGHT_MASK', 'BEAM_TIGHT_MASK'];
+$pack_mask[3] = ['BEAM_TIGHT_MASK', 'BEAM_TIGHT_MASK', $WHOLE_WORD];
$pack_mask[4] = ['BEAM_LOOSE_MASK', # Only for 64 bit wordsize
'BEAM_LOOSE_MASK',
'BEAM_LOOSE_MASK',
$WHOLE_WORD];
+# Mapping from packagable arguments to number of packed arguments per
+# word. Initialized after the wordsize is known.
+
+my @args_per_word;
+
# There are two types of instructions: generic and specific.
# The generic instructions are those generated by the Beam compiler.
# Corresponding to each generic instruction, there is generally a
@@ -176,11 +181,12 @@ sub define_type_bit {
}
# Composed types.
- define_type_bit('d', $type_bit{'x'} | $type_bit{'y'} | $type_bit{'r'});
+ define_type_bit('d', $type_bit{'x'} | $type_bit{'y'});
define_type_bit('c', $type_bit{'i'} | $type_bit{'a'} |
$type_bit{'n'} | $type_bit{'q'});
define_type_bit('s', $type_bit{'d'} | $type_bit{'i'} |
- $type_bit{'a'} | $type_bit{'n'});
+ $type_bit{'a'} | $type_bit{'n'} |
+ $type_bit{'q'});
define_type_bit('j', $type_bit{'f'} | $type_bit{'p'});
# Aliases (for matching purposes).
@@ -236,6 +242,20 @@ while (@ARGV && $ARGV[0] =~ /^-(.*)/) {
}
#
+# Initialize number of arguments per packed word.
+#
+
+$args_per_word[2] = 2;
+$args_per_word[3] = 3;
+$args_per_word[4] = 2;
+$args_per_word[5] = 3;
+$args_per_word[6] = 3;
+
+if ($wordsize == 64) {
+ $args_per_word[4] = 4;
+}
+
+#
# Parse the input files.
#
@@ -527,12 +547,16 @@ sub emulator_output {
my(@bits) = (0) x ($max_spec_operands/2);
my($i);
+ my $involves_r = 0;
for ($i = 0; $i < $max_spec_operands && defined $args[$i]; $i++) {
my $t = $args[$i];
- if (defined $type_bit{$t}) {
- my $shift = $max_genop_types * ($i % 2);
- $bits[int($i/2)] |= $type_bit{$t} << $shift;
+ my $bits = $type_bit{$t};
+ if ($t eq 'r') {
+ $bits |= $type_bit{'x'};
+ $involves_r |= 1 << $i;
}
+ my $shift = $max_genop_types * ($i % 2);
+ $bits[int($i/2)] |= $bits << $shift;
}
printf "/* %3d */ ", $spec_opnum;
@@ -544,7 +568,7 @@ sub emulator_output {
$sep = ",";
}
$init .= "}";
- &init_item($print_name, $init, $size, $pack, $sign, 0);
+ init_item($print_name, $init, $involves_r, $size, $pack, $sign, 0);
$op_to_name[$spec_opnum] = $instr;
$spec_opnum++;
}
@@ -601,15 +625,12 @@ sub emulator_output {
print "#define MAX_GENERIC_OPCODE ", $num_file_opcodes-1, "\n";
print "#define NUM_GENERIC_OPS ", scalar(@gen_opname), "\n";
print "#define NUM_SPECIFIC_OPS ", scalar(@op_to_name), "\n";
+ print "#define SCRATCH_X_REG 1023\n";
print "\n";
print "#ifdef ARCH_64\n";
print "# define BEAM_WIDE_MASK 0xFFFFUL\n";
- print "# define BEAM_LOOSE_MASK 0x1FFFUL\n";
- print "#if HALFWORD_HEAP\n";
- print "# define BEAM_TIGHT_MASK 0x1FFCUL\n";
- print "#else\n";
- print "# define BEAM_TIGHT_MASK 0x1FF8UL\n";
- print "#endif\n";
+ print "# define BEAM_LOOSE_MASK 0xFFFFUL\n";
+ print "# define BEAM_TIGHT_MASK 0xFFFFUL\n";
print "# define BEAM_WIDE_SHIFT 32\n";
print "# define BEAM_LOOSE_SHIFT 16\n";
print "# define BEAM_TIGHT_SHIFT 16\n";
@@ -734,7 +755,7 @@ sub init_item {
print "${sep}NULL";
} elsif (/^\{/) {
print "$sep$_";
- } elsif (/^-?\d/) {
+ } elsif (/^-?\d+$/) {
print "$sep$_";
} else {
print "$sep\"$_\"";
@@ -896,6 +917,7 @@ sub basic_generator {
my($var_decls) = '';
my($gen_dest_arg) = 'StoreSimpleDest';
my($i);
+ my($no_prefetch) = 0;
# The following argument types should be included as macro arguments.
my(%incl_arg) = ('c' => 1,
@@ -994,6 +1016,7 @@ sub basic_generator {
#
$flags =~ /-fail_action/ and do {
+ $no_prefetch = 1;
if (!defined $fail_type) {
my($i);
for ($i = 0; $i < @f_types; $i++) {
@@ -1040,6 +1063,12 @@ sub basic_generator {
"I += $size + 1;",
"goto $goto;",
"}");
+ } elsif ($no_prefetch) {
+ $code = join("\n",
+ "{ $var_decls",
+ $macro_code,
+ "Next($size);",
+ "}", "");
} else {
$code = join("\n",
"{ $var_decls",
@@ -1061,6 +1090,7 @@ sub do_pack {
my($packable_args) = 0;
my @is_packable; # Packability (boolean) for each argument.
my $wide_packing = 0;
+ my(@orig_args) = @args;
#
# Count the number of packable arguments. If we encounter any 's' or 'd'
@@ -1081,6 +1111,18 @@ sub do_pack {
}
} elsif ($arg =~ /^[sd]/) {
return ('', '', @args);
+ } elsif ($arg =~ /^[scq]/ and $packable_args > 0) {
+ # When packing, this operand will be picked up from the
+ # code array, put onto the packing stack, and later put
+ # back into a different location in the code. The problem
+ # is that if this operand is a literal, the original
+ # location in the code would have been remembered in a
+ # literal patch. For packing to work, we would have to
+ # adjust the position in the literal patch. For the
+ # moment, adding additional instructions to the packing
+ # engine to handle this does not seem worth it, so we will
+ # just turn off packing.
+ return ('', '', @args);
} else {
push @is_packable, 0;
}
@@ -1090,7 +1132,6 @@ sub do_pack {
# Get out of here if too few or too many arguments.
#
return ('', '', @args) if $packable_args < 2;
- &error("too many packable arguments") if $packable_args > 4;
my($size) = 0;
my($pack_prefix) = '';
@@ -1098,14 +1139,8 @@ sub do_pack {
# beginning).
my($up) = ''; # Pack commands (storing back while
# moving forward).
- my $args_per_word;
- if ($packable_args < 4 or $wordsize == 64) {
- $args_per_word = $packable_args;
- } else {
- # 4 packable argument, 32 bit wordsize. Need 2 words.
- $args_per_word = 2;
- }
+ my $args_per_word = $args_per_word[$packable_args];
my @shift;
my @mask;
my @instr;
@@ -1299,6 +1334,8 @@ sub tr_parse_op {
foreach (split('', $type)) {
&error("bad type in $op")
unless defined $type_bit{$_} or $type eq '*';
+ $_ eq 'r' and
+ error("$op: 'r' is not allowed in transformations")
}
}
@@ -1332,7 +1369,10 @@ sub tr_parse_op {
}
# Get an optional value. (In destination.)
+ $type_val = $type eq 'x' ? 1023 : 0;
if (/^=(.*)/) {
+ error("value not allowed in source: $op")
+ if $src;
$type_val = $1;
$_ = '';
}
@@ -1351,11 +1391,6 @@ sub tr_parse_op {
if $var && $type;
}
- # Test that source has no values.
- if ($src) {
- error("value not allowed in source: $op")
- if $type_val;
- }
($var,$type,$type_val,$cond,$cond_val);
}
diff --git a/erts/emulator/valgrind/suppress.halfword b/erts/emulator/valgrind/suppress.halfword
deleted file mode 100644
index 8fe448d897..0000000000
--- a/erts/emulator/valgrind/suppress.halfword
+++ /dev/null
@@ -1,56 +0,0 @@
-# Extra suppressions specific for the halfword emulator.
-
-# --- Suppress all offheap binaries ---
-# Valgrinds leak check does not recognize pointers that are stored
-# at unaligned addresses. In halfword emulator we store 64-bit pointers
-# to offheap data on 32-bit aligned heaps.
-# We solve this by suppressing allocation of all offheap structures
-# that are not referenced by other tables (ie binaries).
-
-{
-Halfword erts_bin_nrml_alloc
-Memcheck:Leak
-...
-fun:erts_bin_nrml_alloc
-...
-}
-
-{
-Halfword erts_bin_realloc
-Memcheck:Leak
-...
-fun:erts_bin_realloc
-...
-}
-
-{
-Halfword erts_bin_realloc_fnf
-Memcheck:Leak
-...
-fun:erts_bin_realloc_fnf
-...
-}
-
-{
-Halfword erts_bin_drv_alloc
-Memcheck:Leak
-...
-fun:erts_bin_drv_alloc
-...
-}
-
-{
-Halfword erts_bin_drv_alloc_fnf
-Memcheck:Leak
-...
-fun:erts_bin_drv_alloc_fnf
-...
-}
-
-{
-Halfword erts_create_magic_binary
-Memcheck:Leak
-...
-fun:erts_create_magic_binary
-...
-}
diff --git a/erts/epmd/src/Makefile.in b/erts/epmd/src/Makefile.in
index b6e3ba7762..1266be44cb 100644
--- a/erts/epmd/src/Makefile.in
+++ b/erts/epmd/src/Makefile.in
@@ -19,10 +19,6 @@
#
include $(ERL_TOP)/make/target.mk
-ifeq ($(findstring ose,$(TARGET)),ose)
-include $(ERL_TOP)/make/$(TARGET)/ose_lm.mk
-endif
-
ifeq ($(TYPE),debug)
PURIFY =
TYPEMARKER = .debug
@@ -32,21 +28,13 @@ else
ifeq ($(TYPE),purify)
PURIFY = purify
TYPEMARKER =
-ifeq ($(findstring ose,$(TARGET)),ose)
- TYPE_FLAGS = -DPURIFY
-else
- TYPE_FLAGS = -O2 -DPURIFY
-endif
+TYPE_FLAGS = -O2 -DPURIFY
else
override TYPE = opt
PURIFY =
TYPEMARKER =
-ifeq ($(findstring ose,$(TARGET)),ose)
- TYPE_FLAGS =
-else
- TYPE_FLAGS = -O2
-endif
+TYPE_FLAGS = -O2
endif
endif
@@ -68,13 +56,9 @@ else
ifeq ($(findstring vxworks,$(TARGET)),vxworks)
ERTS_INTERNAL_LIBS=-L../../lib/internal/$(TARGET) -lerts_internal$(ERTS_LIB_TYPEMARKER) @ERTS_INTERNAL_X_LIBS@
else
-ifeq ($(findstring ose,$(TARGET)),ose)
-ERTS_INTERNAL_LIBS=-L../../lib/internal/$(TARGET) -lerts_internal$(ERTS_LIB_TYPEMARKER) @ERTS_INTERNAL_X_LIBS@
-else
ERTS_INTERNAL_LIBS=-L../../lib/internal/$(TARGET) -lerts_internal$(ERTS_LIB_TYPEMARKER) @ERTS_INTERNAL_X_LIBS@ -lm
endif
endif
-endif
ERTS_LIB = $(ERL_TOP)/erts/lib_src/obj/$(TARGET)/$(TYPE)/MADE
@@ -82,11 +66,7 @@ CC = @CC@
WFLAGS = @WFLAGS@
CFLAGS = @CFLAGS@ @DEFS@ $(TYPE_FLAGS) $(WFLAGS) $(ERTS_INCL)
LD = @LD@
-ifeq ($(findstring ose,$(TARGET)),ose)
-LIBS = $(ERTS_INTERNAL_LIBS) @LIBS@
-else
LIBS = @LIBS@ @SYSTEMD_DAEMON_LIBS@ $(ERTS_INTERNAL_LIBS)
-endif
LDFLAGS = @LDFLAGS@
@@ -135,25 +115,12 @@ clean:
rm -f *.o
rm -f *~ core
-ifeq ($(findstring ose,$(TARGET)),ose)
-$(OBJDIR)/ose_confd.o: $(OSE_CONFD)
- $(V_CC) $(CFLAGS) -o $@ -c $<
-$(OBJDIR)/crt0_lm.o: $(CRT0_LM)
- $(V_CC) $(CFLAGS) -o $@ -c $<
-OSE_LM_OBJS += $(OBJDIR)/ose_confd.o $(OBJDIR)/crt0_lm.o
-endif
-
#
# Objects & executables
#
-ifeq ($(findstring ose,$(TARGET)),ose)
-$(BINDIR)/$(EPMD): $(EPMD_OBJS) $(ERTS_LIB) $(OSE_LM_OBJS)
- $(call build-ose-load-module, $@, $(EPMD_OBJS) $(OSE_LM_OBJS), $(LIBS), $(EPMD_LMCONF))
-else
$(BINDIR)/$(EPMD): $(EPMD_OBJS) $(ERTS_LIB)
$(ld_verbose)$(PURIFY) $(LD) $(LDFLAGS) -o $@ $(EPMD_OBJS) $(LIBS)
-endif
$(OBJDIR)/%.o: %.c epmd.h epmd_int.h
$(V_CC) $(CFLAGS) $(EPMD_FLAGS) -o $@ -c $<
diff --git a/erts/epmd/src/epmd.c b/erts/epmd/src/epmd.c
index 5513cb2d7e..324ae6ac40 100644
--- a/erts/epmd/src/epmd.c
+++ b/erts/epmd/src/epmd.c
@@ -397,7 +397,7 @@ static void run_daemon(EpmdVars *g)
}
#endif
-#if defined(VXWORKS) || defined(__OSE__)
+#if defined(VXWORKS)
static void run_daemon(EpmdVars *g)
{
run(g);
diff --git a/erts/epmd/src/epmd_int.h b/erts/epmd/src/epmd_int.h
index 09317094c7..e127eff097 100644
--- a/erts/epmd/src/epmd_int.h
+++ b/erts/epmd/src/epmd_int.h
@@ -37,13 +37,6 @@
#define DONT_USE_MAIN
#endif
-#ifdef __OSE__
-# define NO_DAEMON
-# define NO_SYSLOG
-# define NO_SYSCONF
-# define NO_FCNTL
-#endif
-
/* ************************************************************************ */
/* Standard includes */
@@ -101,12 +94,7 @@
#endif /* ! WIN32 */
#include <ctype.h>
-
-#if !defined(__OSE__)
-# include <signal.h>
-#endif
-
-
+#include <signal.h>
#include <errno.h>
#ifdef HAVE_SYSLOG_H
@@ -123,10 +111,6 @@
#include <stdarg.h>
-#ifdef __OSE__
-# include "sys/select.h"
-#endif
-
#ifdef HAVE_SYSTEMD_DAEMON
# include <systemd/sd-daemon.h>
#endif /* HAVE_SYSTEMD_DAEMON */
diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c
index e1bac99ef9..75a33f28cb 100644
--- a/erts/epmd/src/epmd_srv.c
+++ b/erts/epmd/src/epmd_srv.c
@@ -30,11 +30,6 @@
# define INADDR_NONE 0xffffffff
#endif
-#if defined(__OSE__)
-# include "sys/ioctl.h"
-# define sleep(x) delay(x*1000)
-#endif
-
/*
*
* This server is a local name server for Erlang nodes. Erlang nodes can
@@ -335,7 +330,7 @@ void run(EpmdVars *g)
}
#endif /* HAVE_SYSTEMD_DAEMON */
-#if !defined(__WIN32__) && !defined(__OSE__)
+#if !defined(__WIN32__)
/* We ignore the SIGPIPE signal that is raised when we call write
twice on a socket closed by the other end. */
signal(SIGPIPE, SIG_IGN);
diff --git a/erts/epmd/test/epmd_SUITE.erl b/erts/epmd/test/epmd_SUITE.erl
index d5837e5b8c..44d3c5a880 100644
--- a/erts/epmd/test/epmd_SUITE.erl
+++ b/erts/epmd/test/epmd_SUITE.erl
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
%%
-module(epmd_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
diff --git a/erts/etc/common/Makefile.in b/erts/etc/common/Makefile.in
index 8e55fa78c9..05d925f19f 100644
--- a/erts/etc/common/Makefile.in
+++ b/erts/etc/common/Makefile.in
@@ -21,10 +21,6 @@
include $(ERL_TOP)/make/output.mk
include $(ERL_TOP)/make/target.mk
-ifeq ($(findstring ose,$(TARGET)),ose)
-include $(ERL_TOP)/make/$(TARGET)/ose_lm.mk
-endif
-
ERTS_LIB_TYPEMARKER=.$(TYPE)
USING_MINGW=@MIXED_CYGWIN_MINGW@
@@ -85,18 +81,13 @@ EMUOSDIR = $(ERL_TOP)/erts/emulator/@ERLANG_OSTYPE@
SYSDIR = $(ERL_TOP)/erts/emulator/sys/@ERLANG_OSTYPE@
DRVDIR = $(ERL_TOP)/erts/emulator/drivers/@ERLANG_OSTYPE@
UXETC = ../unix
-OSEETC = ../ose
WINETC = ../win32
ifeq ($(TARGET), win32)
ETC = $(WINETC)
else
-ifeq ($(findstring ose,$(TARGET)),ose)
-ETC = $(OSEETC)
-else
ETC = $(UXETC)
endif
-endif
ifeq ($(TARGET), win32)
ERLEXEC = erlexec.dll
@@ -180,25 +171,6 @@ PORT_ENTRY_POINT=erl_port_entry
ENTRY_LDFLAGS=-entry:$(PORT_ENTRY_POINT)
else
-ifeq ($(findstring ose,$(TARGET)),ose)
-ENTRY_LDFLAGS=
-ENTRY_OBJ=
-ERLSRV_OBJECTS=
-MC_OUTPUTS=
-INET_GETHOST =
-INSTALL_EMBEDDED_PROGS = $(BINDIR)/run_erl_lm
-INSTALL_EMBEDDED_DATA =
-INSTALL_TOP = Install
-INSTALL_TOP_BIN =
-INSTALL_MISC =
-INSTALL_SRC =
-ERLEXECDIR = .
-INSTALL_LIBS =
-INSTALL_OBJS =
-INSTALL_INCLUDES =
-TEXTFILES = Install erl.src
-INSTALL_PROGS = $(INSTALL_EMBEDDED_PROGS)
-else # UNIX (!win32 && !ose)
ENTRY_LDFLAGS=
ENTRY_OBJ=
ERLSRV_OBJECTS=
@@ -223,7 +195,6 @@ INSTALL_PROGS = \
$(BINDIR)/$(ERLEXEC) \
$(INSTALL_EMBEDDED_PROGS)
endif
-endif
.PHONY: etc
etc: $(ENTRY_OBJ) $(INSTALL_PROGS) $(INSTALL_LIBS) $(TEXTFILES) $(INSTALL_TOP_BIN)
@@ -269,8 +240,8 @@ endif
rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/to_erl.o
rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/dyn_erl.o
rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/safe_string.o
- rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/run_erl_common.o
- rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/to_erl_common.o
+ rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/run_erl.o
+ rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/to_erl.o
rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/typer.o
rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/ct_run.o
rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/vxcall.o
@@ -423,28 +394,24 @@ $(BINDIR)/inet_gethost@EXEEXT@: $(OBJDIR)/inet_gethost.o $(ENTRY_OBJ) $(ERTS_LIB
$(ld_verbose)$(PURIFY) $(LD) $(LDFLAGS) $(ENTRY_LDFLAGS) -o $@ $(OBJDIR)/inet_gethost.o $(ENTRY_OBJ) $(LIBS) $(ERTS_INTERNAL_LIBS)
# run_erl
-$(BINDIR)/run_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o $(OBJDIR)/run_erl_common.o
- $(V_LD) $(LDFLAGS) -o $@ $^ $(LIBS)
-$(OBJDIR)/run_erl.o: $(ETC)/run_erl.c ../common/run_erl_common.h $(RC_GENERATED)
- $(V_CC) $(CFLAGS) -I ../common/ -o $@ -c $(ETC)/run_erl.c
-$(OBJDIR)/run_erl_common.o: ../common/run_erl_common.c ../common/run_erl_common.h $(RC_GENERATED)
- $(V_CC) $(CFLAGS) -o $@ -c $<
+$(BINDIR)/run_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o
+ $(V_LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o $(LIBS)
+$(OBJDIR)/run_erl.o: $(ETC)/run_erl.c $(RC_GENERATED)
+ $(V_CC) $(CFLAGS) -o $@ -c $(ETC)/run_erl.c
# to_erl
-$(BINDIR)/to_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/to_erl.o $(OBJDIR)/to_erl_common.o
- $(V_LD) $(LDFLAGS) -o $@ $^
-$(OBJDIR)/to_erl.o: $(ETC)/to_erl.c ../common/safe_string.h $(RC_GENERATED)
- $(V_CC) $(CFLAGS) -I ../common/ -o $@ -c $(ETC)/to_erl.c
-$(OBJDIR)/to_erl_common.o: ../common/to_erl_common.c ../common/to_erl_common.h $(RC_GENERATED)
- $(V_CC) $(CFLAGS) -o $@ -c $<
+$(BINDIR)/to_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/to_erl.o
+ $(V_LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/to_erl.o
+$(OBJDIR)/to_erl.o: $(ETC)/to_erl.c $(RC_GENERATED)
+ $(V_CC) $(CFLAGS) -o $@ -c $(ETC)/to_erl.c
# dyn_erl
$(BINDIR)/dyn_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/dyn_erl.o
$(V_LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/dyn_erl.o
$(OBJDIR)/dyn_erl.o: $(UXETC)/dyn_erl.c $(RC_GENERATED)
$(V_CC) $(CFLAGS) -o $@ -c $(UXETC)/dyn_erl.c
-$(OBJDIR)/safe_string.o: ../common/safe_string.c $(RC_GENERATED)
- $(V_CC) $(CFLAGS) -o $@ -c ../common/safe_string.c
+$(OBJDIR)/safe_string.o: $(ETC)/safe_string.c $(RC_GENERATED)
+ $(V_CC) $(CFLAGS) -o $@ -c $(ETC)/safe_string.c
ifneq ($(TARGET),win32)
$(BINDIR)/$(ERLEXEC): $(OBJDIR)/$(ERLEXEC).o $(ERTS_LIB)
@@ -499,30 +466,6 @@ erl.src: $(UXETC)/erl.src.src ../../vsn.mk $(TARGET)/Makefile
-e 's;%VSN%;$(VSN);' \
$(UXETC)/erl.src.src > erl.src
-#---------------------------------------------------------
-# OSE specific targets
-#---------------------------------------------------------
-ifeq ($(findstring ose,$(TARGET)),ose)
-$(OBJDIR)/ose_confd.o: $(OSE_CONFD)
- $(V_CC) $(CFLAGS) -o $@ -c $<
-$(OBJDIR)/crt0_lm.o: $(CRT0_LM)
- $(V_CC) $(CFLAGS) -o $@ -c $<
-OSE_LM_OBJS += $(OBJDIR)/ose_confd.o $(OBJDIR)/crt0_lm.o
-
-$(BINDIR)/run_erl_lm: $(OBJDIR)/run_erl_main.o $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o $(OBJDIR)/run_erl_common.o $(OBJDIR)/to_erl_common.o $(OSE_LM_OBJS)
- $(call build-ose-load-module, $@, $^, $(LIBS), $(RUN_ERL_LMCONF))
-
-
-$(OBJDIR)/run_erl_main.o: $(OSEETC)/run_erl_main.c $(OSEETC)/run_erl.h ../common/to_erl_common.h $(RC_GENERATED)
- $(V_CC) $(CFLAGS) -I ../common/ -o $@ -c $(OSEETC)/run_erl_main.c
-
-endif
-
-#---------------------------------------------------------
-# End of ose specific targets.
-#---------------------------------------------------------
-
-
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
@@ -537,11 +480,9 @@ endif
$(INSTALL_DIR) "$(RELEASE_PATH)/erts-$(VSN)/bin"
ifneq ($(TARGET), win32)
ifneq ($(findstring vxworks,$(TARGET)), vxworks)
-ifneq ($(findstring ose,$(TARGET)), ose)
$(INSTALL_SCRIPT) erl.src "$(RELEASE_PATH)/erts-$(VSN)/bin"
endif
endif
-endif
ifneq ($(INSTALL_PROGS),)
$(INSTALL_PROGRAM) $(INSTALL_PROGS) "$(RELEASE_PATH)/erts-$(VSN)/bin"
endif
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index af1c198281..54da59e50d 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -65,6 +65,7 @@
static const char plusM_au_allocs[]= {
'u', /* all alloc_util allocators */
'B', /* binary_alloc */
+ 'I', /* literal_alloc */
'D', /* std_alloc */
'E', /* ets_alloc */
'F', /* fix_alloc */
@@ -121,6 +122,7 @@ static char *plusM_other_switches[] = {
"Ym",
"Ytp",
"Ytt",
+ "Iscs",
NULL
};
@@ -156,6 +158,12 @@ static char *plusr_val_switches[] = {
NULL
};
+/* +x arguments with values */
+static char *plusx_val_switches[] = {
+ "mqd",
+ NULL
+};
+
/* +z arguments with values */
static char *plusz_val_switches[] = {
"dbbl",
@@ -976,6 +984,20 @@ int main(int argc, char **argv)
add_Eargs(argv[i+1]);
i++;
break;
+ case 'x':
+ if (!is_one_of_strings(&argv[i][2], plusx_val_switches)) {
+ goto the_default;
+ } else {
+ if (i+1 >= argc
+ || argv[i+1][0] == '-'
+ || argv[i+1][0] == '+')
+ usage(argv[i]);
+ argv[i][0] = '-';
+ add_Eargs(argv[i]);
+ add_Eargs(argv[i+1]);
+ i++;
+ }
+ break;
case 'z':
if (!is_one_of_strings(&argv[i][2], plusz_val_switches)) {
goto the_default;
@@ -1176,7 +1198,7 @@ usage_aux(void)
"[+S NO_SCHEDULERS:NO_SCHEDULERS_ONLINE] "
"[+SP PERCENTAGE_SCHEDULERS:PERCENTAGE_SCHEDULERS_ONLINE] "
"[+T LEVEL] [+V] [+v] "
- "[+W<i|w|e>] [+z MISC_OPTION] [args ...]\n");
+ "[+W<i|w|e>] [+x DEFAULT_PROC_FLAGS] [+z MISC_OPTION] [args ...]\n");
exit(1);
}
diff --git a/erts/etc/common/run_erl_common.c b/erts/etc/common/run_erl_common.c
deleted file mode 100644
index c03d5e3ae2..0000000000
--- a/erts/etc/common/run_erl_common.c
+++ /dev/null
@@ -1,696 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2014. 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%
- */
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-
-#ifdef __ANDROID__
-# include <termios.h>
-#endif
-
-#ifdef HAVE_SYSLOG_H
-# include <syslog.h>
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-
-#ifdef __OSE__
-# include "ramlog.h"
-#endif
-
-#include "run_erl_common.h"
-#include "safe_string.h"
-
-#define DEFAULT_LOG_GENERATIONS 5
-#define LOG_MAX_GENERATIONS 1000 /* No more than 1000 log files */
-#define LOG_MIN_GENERATIONS 2 /* At least two to switch between */
-#define DEFAULT_LOG_MAXSIZE 100000
-#define LOG_MIN_MAXSIZE 1000 /* Smallast value for changing log file */
-#define LOG_STUBNAME "erlang.log."
-#define LOG_PERM 0664
-#define DEFAULT_LOG_ACTIVITY_MINUTES 5
-#define DEFAULT_LOG_ALIVE_MINUTES 15
-#define DEFAULT_LOG_ALIVE_FORMAT "%a %b %e %T %Z %Y"
-#define ALIVE_BUFFSIZ 1024
-
-#define STATUSFILENAME "/run_erl.log"
-
-#define PIPE_STUBNAME "erlang.pipe"
-#define PIPE_STUBLEN strlen(PIPE_STUBNAME)
-#define PERM (S_IWUSR | S_IRUSR | S_IWOTH | S_IROTH | S_IWGRP | S_IRGRP)
-
-/* OSE has defined O_SYNC but it is not recognized by open */
-#if !defined(O_SYNC) || defined(__OSE__)
-#undef O_SYNC
-#define O_SYNC 0
-#define USE_FSYNC 1
-#endif
-
-/* Global variable definitions
- * We need this complex way of handling global variables because of how
- * OSE works here. We want to make it possible to run the shell command
- * run_erl multiple times with different global variables without them
- * effecting eachother.
- */
-
-#define STATUSFILE (RE_DATA->statusfile)
-#define LOG_DIR (RE_DATA->log_dir)
-#define STDSTATUS (RE_DATA->stdstatus)
-#define LOG_GENERATIONS (RE_DATA->log_generations)
-#define LOG_MAXSIZE (RE_DATA->log_maxsize)
-#define LOG_ACTIVITY_MINUTES (RE_DATA->log_activity_minutes)
-#define LOG_ALIVE_IN_GMT (RE_DATA->log_alive_in_gmt)
-#define LOG_ALIVE_FORMAT (RE_DATA->log_alive_format)
-#define RUN_DAEMON (RE_DATA->run_daemon)
-#define LOG_ALIVE_MINUTES (RE_DATA->log_alive_minutes)
-#define LOG_NUM (RE_DATA->log_num)
-#define LFD (RE_DATA->lfd)
-#define PROTOCOL_VER (RE_DATA->protocol_ver)
-
-struct run_erl_ {
- /* constant config data */
- char statusfile[FILENAME_BUFSIZ];
- char log_dir[FILENAME_BUFSIZ];
- FILE *stdstatus;
- int log_generations;
- int log_maxsize;
- int log_activity_minutes;
- int log_alive_in_gmt;
- char log_alive_format[ALIVE_BUFFSIZ+1];
- int run_daemon;
- int log_alive_minutes;
- /* Current log number and log fd */
- int log_num;
- int lfd;
- unsigned protocol_ver;
-};
-
-typedef struct run_erl_ run_erl;
-
-#ifdef __OSE__
-static OSPPDKEY run_erl_pp_key;
-#define RE_DATA (*(run_erl**)ose_get_ppdata(run_erl_pp_key))
-#else
-static run_erl re;
-#define RE_DATA (&re)
-#endif
-
-/* prototypes */
-
-static int next_log(int log_num);
-static int prev_log(int log_num);
-static int find_next_log_num(void);
-static int open_log(int log_num, int flags);
-
-/*
- * getenv_int:
- */
-static char *getenv_int(const char *name) {
-#ifdef __OSE__
- return get_env(get_bid(current_process()),name);
-#else
- return getenv(name);
-#endif
-}
-
-/*
- * next_log:
- * Returns the index number that follows the given index number.
- * (Wrapping after log_generations)
- */
-static int next_log(int log_num) {
- return log_num>=LOG_GENERATIONS?1:log_num+1;
-}
-
-/*
- * prev_log:
- * Returns the index number that precedes the given index number.
- * (Wrapping after log_generations)
- */
-static int prev_log(int log_num) {
- return log_num<=1?LOG_GENERATIONS:log_num-1;
-}
-
-/*
- * find_next_log_num()
- * Searches through the log directory to check which logs that already
- * exist. It finds the "hole" in the sequence, and returns the index
- * number for the last log in the log sequence. If there is no hole, index
- * 1 is returned.
- */
-static int find_next_log_num(void) {
- int i, next_gen, log_gen;
- DIR *dirp;
- struct dirent *direntp;
- int log_exists[LOG_MAX_GENERATIONS+1];
- int stub_len = strlen(LOG_STUBNAME);
-
- /* Initialize exiting log table */
-
- for(i=LOG_GENERATIONS; i>=0; i--)
- log_exists[i] = 0;
- dirp = opendir(LOG_DIR);
- if(!dirp) {
- ERRNO_ERR1(LOG_ERR,"Can't access log directory '%s'", LOG_DIR);
- exit(1);
- }
-
- /* Check the directory for existing logs */
-
- while((direntp=readdir(dirp)) != NULL) {
- if(strncmp(direntp->d_name,LOG_STUBNAME,stub_len)==0) {
- int num = atoi(direntp->d_name+stub_len);
- if(num < 1 || num > LOG_GENERATIONS)
- continue;
- log_exists[num] = 1;
- }
- }
- closedir(dirp);
-
- /* Find out the next available log file number */
-
- next_gen = 0;
- for(i=LOG_GENERATIONS; i>=0; i--) {
- if(log_exists[i])
- if(next_gen)
- break;
- else
- ;
- else
- next_gen = i;
- }
-
- /* Find out the current log file number */
-
- if(next_gen)
- log_gen = prev_log(next_gen);
- else
- log_gen = 1;
-
- return log_gen;
-} /* find_next_log_num() */
-
-static int open_log(int log_num, int flags)
-{
- char buf[FILENAME_MAX];
- time_t now;
- struct tm *tmptr;
- char log_buffer[ALIVE_BUFFSIZ+1];
-
- /* Remove the next log (to keep a "hole" in the log sequence) */
- sn_printf(buf, sizeof(buf), "%s/%s%d",
- LOG_DIR, LOG_STUBNAME, next_log(log_num));
- unlink(buf);
-
- /* Create or continue on the current log file */
- sn_printf(buf, sizeof(buf), "%s/%s%d", LOG_DIR, LOG_STUBNAME, log_num);
-
- LFD = sf_open(buf, flags, LOG_PERM);
-
- if(LFD <0){
- ERRNO_ERR1(LOG_ERR,"Can't open log file '%s'.", buf);
- exit(1);
- }
-
- /* Write a LOGGING STARTED and time stamp into the log file */
- time(&now);
- if (LOG_ALIVE_IN_GMT) {
- tmptr = gmtime(&now);
- } else {
- tmptr = localtime(&now);
- }
- if (!strftime(log_buffer, ALIVE_BUFFSIZ, LOG_ALIVE_FORMAT,
- tmptr)) {
- strn_cpy(log_buffer, sizeof(log_buffer),
- "(could not format time in 256 positions "
- "with current format string.)");
- }
- log_buffer[ALIVE_BUFFSIZ] = '\0';
-
- sn_printf(buf, sizeof(buf), "\n=====\n===== LOGGING STARTED %s\n=====\n",
- log_buffer);
- if (erts_run_erl_write_all(LFD, buf, strlen(buf)) < 0)
- erts_run_erl_log_status("Error in writing to log.\n");
-
-#if USE_FSYNC
- fsync(LFD);
-#endif
-
- return LFD;
-}
-
-/* Instead of making sure basename exists, we do our own */
-char *simple_basename(char *path)
-{
- char *ptr;
- for (ptr = path; *ptr != '\0'; ++ptr) {
- if (*ptr == '/') {
- path = ptr + 1;
- }
- }
- return path;
-}
-
-ssize_t sf_read(int fd, void *buffer, size_t len) {
- ssize_t n = 0;
-
- do { n = read(fd, buffer, len); } while (n < 0 && errno == EINTR);
-
- return n;
-}
-
-ssize_t sf_write(int fd, const void *buffer, size_t len) {
- ssize_t n = 0;
-
- do { n = write(fd, buffer, len); } while (n < 0 && errno == EINTR);
-
- return n;
-}
-
-int sf_open(const char *path, int type, mode_t mode) {
- int fd = 0;
-
- do { fd = open(path, type, mode); } while(fd < 0 && errno == EINTR);
-
- return fd;
-}
-
-int sf_close(int fd) {
- int res = 0;
-
- do { res = close(fd); } while(res < 0 && errno == EINTR);
-
- return res;
-}
-
-/* Call write() until entire buffer has been written or error.
- * Return len or -1.
- */
-int erts_run_erl_write_all(int fd, const char* buf, int len)
-{
- int left = len;
- int written;
- for (;;) {
- do {
- written = write(fd,buf,left);
- } while (written < 0 && errno == EINTR);
- if (written == left) {
- return len;
- }
- if (written < 0) {
- return -1;
- }
- left -= written;
- buf += written;
- }
- return written;
-}
-
-/* erts_run_erl_log_status()
- * Prints the arguments to a status file
- * Works like printf (see vfrpintf)
- */
-void erts_run_erl_log_status(const char *format,...)
-{
- va_list args;
- time_t now;
-
- if (STDSTATUS == NULL)
- STDSTATUS = fopen(STATUSFILE, "w");
- if (STDSTATUS == NULL)
- return;
- now = time(NULL);
- fprintf(STDSTATUS, "run_erl [%d] %s",
-#ifdef __OSE__
- (int)current_process(),
-#else
- (int)getpid(),
-#endif
- ctime(&now));
- va_start(args, format);
- vfprintf(STDSTATUS, format, args);
- va_end(args);
- fflush(STDSTATUS);
- return;
-}
-
-/* Fetch the current log alive minutes */
-int erts_run_erl_log_alive_minutes() {
- return LOG_ALIVE_MINUTES;
-}
-
-/* error_logf()
- * Prints the arguments to stderr or syslog
- * Works like printf (see vfprintf)
- */
-void erts_run_erl_log_error(int priority, int line, const char *format, ...)
-{
- va_list args;
- va_start(args, format);
-
-#ifdef HAVE_SYSLOG_H
- if (RUN_DAEMON) {
- vsyslog(priority,format,args);
- }
- else
-#endif
-#ifdef __OSE__
- if (RUN_DAEMON) {
- char *buff = malloc(sizeof(char)*1024);
- vsnprintf(buff,1024,format, args);
- ramlog_printf(buff);
- }
- else
-#endif
- {
- time_t now = time(NULL);
- fprintf(stderr, "run_erl:%d [%d] %s", line,
-#ifdef __OSE__
- (int)current_process(),
-#else
- (int)getpid(),
-#endif
- ctime(&now));
- vfprintf(stderr, format, args);
- }
- va_end(args);
-}
-
-/* erts_run_erl_log_write()
- * Writes a message to lfd. If the current log file is full,
- * a new log file is opened.
- */
-int erts_run_erl_log_write(char* buf, size_t len)
-{
- int size;
- ssize_t res;
- /* Decide if new logfile needed, and open if so */
-
- size = lseek(LFD,0,SEEK_END);
- if(size+len > LOG_MAXSIZE) {
- int res;
- do {
- res = close(LFD);
- } while (res < 0 && errno == EINTR);
- LOG_NUM = next_log(LOG_NUM);
- LFD = open_log(LOG_NUM, O_RDWR|O_CREAT|O_TRUNC|O_SYNC);
- }
-
- /* Write to log file */
-
- if ((res = erts_run_erl_write_all(LFD, buf, len)) < 0) {
- erts_run_erl_log_status("Error in writing to log.\n");
- }
-
-#if USE_FSYNC
- fsync(LFD);
-#endif
- return res;
-}
-
-int erts_run_erl_log_activity(int timeout,time_t now,time_t last_activity) {
- char log_alive_buffer[ALIVE_BUFFSIZ+1];
- char buf[BUFSIZ];
-
- if (timeout || now - last_activity > LOG_ACTIVITY_MINUTES*60) {
- /* Either a time out: 15 minutes without action, */
- /* or something is coming in right now, but it's a long time */
- /* since last time, so let's write a time stamp this message */
- struct tm *tmptr;
- if (LOG_ALIVE_IN_GMT) {
- tmptr = gmtime(&now);
- } else {
- tmptr = localtime(&now);
- }
- if (!strftime(log_alive_buffer, ALIVE_BUFFSIZ, LOG_ALIVE_FORMAT,
- tmptr)) {
- strn_cpy(log_alive_buffer, sizeof(log_alive_buffer),
- "(could not format time in 256 positions "
- "with current format string.)");
- }
- log_alive_buffer[ALIVE_BUFFSIZ] = '\0';
-
- sn_printf(buf, sizeof(buf), "\n===== %s%s\n",
- timeout?"ALIVE ":"", log_alive_buffer);
- return erts_run_erl_log_write(buf, strlen(buf));
- }
- return 0;
-}
-
-int erts_run_erl_log_open() {
-
- LOG_NUM = find_next_log_num();
- LFD = open_log(LOG_NUM, O_RDWR|O_APPEND|O_CREAT|O_SYNC);
- return 0;
-}
-
-int erts_run_erl_log_init(int daemon, char* logdir) {
- char *p;
-
-#ifdef __OSE__
- run_erl **re_pp;
- if (!run_erl_pp_key)
- ose_create_ppdata("run_erl_ppdata",&run_erl_pp_key);
- re_pp = (run_erl **)ose_get_ppdata(run_erl_pp_key);
- *re_pp = malloc(sizeof(run_erl));
-#endif
-
- STDSTATUS = NULL;
- LOG_GENERATIONS = DEFAULT_LOG_GENERATIONS;
- LOG_MAXSIZE = DEFAULT_LOG_MAXSIZE;
- LOG_ACTIVITY_MINUTES = DEFAULT_LOG_ACTIVITY_MINUTES;
- LOG_ALIVE_IN_GMT = 0;
- RUN_DAEMON = 0;
- LOG_ALIVE_MINUTES = DEFAULT_LOG_ALIVE_MINUTES;
- LFD = 0;
- PROTOCOL_VER = RUN_ERL_LO_VER; /* assume lowest to begin with */
-
- /* Get values for LOG file handling from the environment */
- if ((p = getenv_int("RUN_ERL_LOG_ALIVE_MINUTES"))) {
- LOG_ALIVE_MINUTES = atoi(p);
- if (!LOG_ALIVE_MINUTES) {
- ERROR1(LOG_ERR,"Minimum value for RUN_ERL_LOG_ALIVE_MINUTES is 1 "
- "(current value is %s)",p);
- }
- LOG_ACTIVITY_MINUTES = LOG_ALIVE_MINUTES / 3;
- if (!LOG_ACTIVITY_MINUTES) {
- ++LOG_ACTIVITY_MINUTES;
- }
- }
- if ((p = getenv_int(
- "RUN_ERL_LOG_ACTIVITY_MINUTES"))) {
- LOG_ACTIVITY_MINUTES = atoi(p);
- if (!LOG_ACTIVITY_MINUTES) {
- ERROR1(LOG_ERR,"Minimum value for RUN_ERL_LOG_ACTIVITY_MINUTES is 1 "
- "(current value is %s)",p);
- }
- }
- if ((p = getenv_int("RUN_ERL_LOG_ALIVE_FORMAT"))) {
- if (strlen(p) > ALIVE_BUFFSIZ) {
- ERROR1(LOG_ERR, "RUN_ERL_LOG_ALIVE_FORMAT can contain a maximum of "
- "%d characters", ALIVE_BUFFSIZ);
- }
- strn_cpy(LOG_ALIVE_FORMAT, sizeof(LOG_ALIVE_FORMAT), p);
- } else {
- strn_cpy(LOG_ALIVE_FORMAT, sizeof(LOG_ALIVE_FORMAT),
- DEFAULT_LOG_ALIVE_FORMAT);
- }
- if ((p = getenv_int("RUN_ERL_LOG_ALIVE_IN_UTC"))
- && strcmp(p,"0")) {
- ++LOG_ALIVE_IN_GMT;
- }
- if ((p = getenv_int("RUN_ERL_LOG_GENERATIONS"))) {
- LOG_GENERATIONS = atoi(p);
- if (LOG_GENERATIONS < LOG_MIN_GENERATIONS)
- ERROR1(LOG_ERR,"Minimum RUN_ERL_LOG_GENERATIONS is %d",
- LOG_MIN_GENERATIONS);
- if (LOG_GENERATIONS > LOG_MAX_GENERATIONS)
- ERROR1(LOG_ERR,"Maximum RUN_ERL_LOG_GENERATIONS is %d",
- LOG_MAX_GENERATIONS);
- }
-
- if ((p = getenv_int("RUN_ERL_LOG_MAXSIZE"))) {
- LOG_MAXSIZE = atoi(p);
- if (LOG_MAXSIZE < LOG_MIN_MAXSIZE)
- ERROR1(LOG_ERR,"Minimum RUN_ERL_LOG_MAXSIZE is %d", LOG_MIN_MAXSIZE);
- }
-
- RUN_DAEMON = daemon;
-
- strn_cpy(LOG_DIR, sizeof(LOG_DIR), logdir);
- strn_cpy(STATUSFILE, sizeof(STATUSFILE), LOG_DIR);
- strn_cat(STATUSFILE, sizeof(STATUSFILE), STATUSFILENAME);
-
- return 0;
-}
-
-/* create_fifo()
- * Creates a new fifo with the given name and permission.
- */
-static int create_fifo(char *name, int perm)
-{
- if ((mkfifo(name, perm) < 0) && (errno != EEXIST))
- return -1;
- return 0;
-}
-
-/*
- * w- and r_pipename have to be pre-allocated of atleast FILENAME_MAX size
- */
-int erts_run_erl_open_fifo(char *pipename,char *w_pipename,char *r_pipename) {
- int calculated_pipename = 0;
- int highest_pipe_num = 0;
- int fd;
-
- /*
- * Create FIFOs and open them
- */
-
- if(*pipename && pipename[strlen(pipename)-1] == '/') {
- /* The user wishes us to find a unique pipe name in the specified */
- /* directory */
- DIR *dirp;
- struct dirent *direntp;
-
- calculated_pipename = 1;
- dirp = opendir(pipename);
- if(!dirp) {
- ERRNO_ERR1(LOG_ERR,"Can't access pipe directory '%s'.", pipename);
- return 1;
- }
-
- /* Check the directory for existing pipes */
-
- while((direntp=readdir(dirp)) != NULL) {
- if(strncmp(direntp->d_name,PIPE_STUBNAME,PIPE_STUBLEN)==0) {
- int num = atoi(direntp->d_name+PIPE_STUBLEN+1);
- if(num > highest_pipe_num)
- highest_pipe_num = num;
- }
- }
- closedir(dirp);
- strn_catf(pipename, BUFSIZ, "%s.%d",
- PIPE_STUBNAME, highest_pipe_num+1);
- } /* if */
-
- for(;;) {
- /* write FIFO - is read FIFO for `to_erl' program */
- strn_cpy(w_pipename, BUFSIZ, pipename);
- strn_cat(w_pipename, BUFSIZ, ".r");
- if (create_fifo(w_pipename, PERM) < 0) {
- ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for writing.",
- w_pipename);
- return 1;
- }
-
- /* read FIFO - is write FIFO for `to_erl' program */
- strn_cpy(r_pipename, BUFSIZ, pipename);
- strn_cat(r_pipename, BUFSIZ, ".w");
-
- /* Check that nobody is running run_erl already */
- if ((fd = sf_open(r_pipename, O_WRONLY|DONT_BLOCK_PLEASE, 0)) >= 0) {
- /* Open as client succeeded -- run_erl is already running! */
- sf_close(fd);
- if (calculated_pipename) {
- ++highest_pipe_num;
- strn_catf(pipename, BUFSIZ, "%s.%d",
- PIPE_STUBNAME, highest_pipe_num+1);
- continue;
- }
- ERROR1(LOG_ERR, "Erlang already running on pipe %s.\n", pipename);
- unlink(w_pipename);
- return 1;
- }
- if (create_fifo(r_pipename, PERM) < 0) {
- unlink(w_pipename);
- ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for reading.",
- r_pipename);
- return 1;
- }
- break;
- }
- return 0;
-}
-
-/* Extract any control sequences that are ment only for run_erl
- * and should not be forwarded to the pty.
- */
-int erts_run_erl_extract_ctrl_seq(char* buf, int len, int mfd)
-{
- static const char prefix[] = "\033_";
- static const char suffix[] = "\033\\";
- char* bufend = buf + len;
- char* start = buf;
- char* command;
- char* end;
-
- for (;;) {
- start = find_str(start, bufend-start, prefix);
- if (!start) break;
-
- command = start + strlen(prefix);
- end = find_str(command, bufend-command, suffix);
- if (end) {
- unsigned col, row;
- if (sscanf(command,"version=%u", &PROTOCOL_VER)==1) {
- /*fprintf(stderr,"to_erl v%u\n", protocol_ver);*/
- }
- else if (sscanf(command,"winsize=%u,%u", &col, &row)==2) {
-#ifdef TIOCSWINSZ
- struct winsize ws;
- ws.ws_col = col;
- ws.ws_row = row;
- if (ioctl(mfd, TIOCSWINSZ, &ws) < 0) {
- ERRNO_ERR0(LOG_ERR,"Failed to set window size");
- }
-#endif
- }
- else {
- ERROR2(LOG_ERR, "Ignoring unknown ctrl command '%.*s'\n",
- (int)(end-command), command);
- }
-
- /* Remove ctrl sequence from buf */
- end += strlen(suffix);
- memmove(start, end, bufend-end);
- bufend -= end - start;
- }
- else {
- ERROR2(LOG_ERR, "Missing suffix in ctrl sequence '%.*s'\n",
- (int)(bufend-start), start);
- break;
- }
- }
- return bufend - buf;
-}
diff --git a/erts/etc/common/run_erl_common.h b/erts/etc/common/run_erl_common.h
deleted file mode 100644
index cecf7521f9..0000000000
--- a/erts/etc/common/run_erl_common.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2013. 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%
- */
-/*
- * Functions that are common to both OSE and unix implementations of run_erl
- */
-#ifndef ERL_RUN_ERL_LOG_H
-#define ERL_RUN_ERL_LOG_H
-
-#include <stdio.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "run_erl_vsn.h"
-
-/* Log handling */
-int erts_run_erl_log_init(int run_daemon, char* logdir);
-int erts_run_erl_log_open(void);
-int erts_run_erl_log_close(void);
-int erts_run_erl_log_write(char *buff, size_t len);
-int erts_run_erl_log_activity(int timeout, time_t now, time_t last_activity);
-
-void erts_run_erl_log_status(const char *format,...);
-void erts_run_erl_log_error(int priority, int line, const char *format,...);
-
-int erts_run_erl_open_fifo(char *pipename,char *w_pipename,char *r_pipename);
-int erts_run_erl_log_alive_minutes(void);
-int erts_run_erl_extract_ctrl_seq(char* buf, int len, int mfd);
-
-/* File operations */
-ssize_t sf_read(int fd, void *buffer, size_t len);
-ssize_t sf_write(int fd, const void *buffer, size_t len);
-int sf_open(const char *path, int type, mode_t mode);
-int sf_close(int fd);
-int erts_run_erl_write_all(int fd, const char* buf, int len);
-char *simple_basename(char *path);
-
-#ifndef LOG_ERR
-#ifdef __OSE__
-#define LOG_ERR 0
-#else
-#define LOG_ERR NULL
-#endif
-#endif
-
-#define ERROR0(Prio,Format) erts_run_erl_log_error(Prio,__LINE__,Format"\n")
-#define ERROR1(Prio,Format,A1) erts_run_erl_log_error(Prio,__LINE__,Format"\n",A1)
-#define ERROR2(Prio,Format,A1,A2) erts_run_erl_log_error(Prio,__LINE__,Format"\n",A1,A2)
-
-#ifdef HAVE_STRERROR
-# define ADD_ERRNO(Format) "errno=%d '%s'\n"Format"\n",errno,strerror(errno)
-#else
-# define ADD_ERRNO(Format) "errno=%d\n"Format"\n",errno
-#endif
-#define ERRNO_ERR0(Prio,Format) erts_run_erl_log_error(Prio,__LINE__,ADD_ERRNO(Format))
-#define ERRNO_ERR1(Prio,Format,A1) erts_run_erl_log_error(Prio,__LINE__,ADD_ERRNO(Format),A1)
-#define ERRNO_ERR2(Prio,Format,A1,A2) erts_run_erl_log_error(Prio,__LINE__,ADD_ERRNO(Format),A1,A2)
-
-#define RUN_ERL_USAGE \
- "%s (pipe_name|pipe_dir/) log_dir \"command [parameters ...]\"" \
- "\n\nDESCRIPTION:\n" \
- "You may also set the environment variables RUN_ERL_LOG_GENERATIONS\n" \
- "and RUN_ERL_LOG_MAXSIZE to the number of log files to use and the\n" \
- "size of the log file when to switch to the next log file\n"
-
-#ifndef FILENAME_MAX
-#define FILENAME_MAX 250
-#endif
-
-#define FILENAME_BUFSIZ FILENAME_MAX
-
-#ifdef O_NONBLOCK
-# define DONT_BLOCK_PLEASE O_NONBLOCK
-#else
-# define DONT_BLOCK_PLEASE O_NDELAY
-# ifndef EAGAIN
-# define EAGAIN -3898734
-# endif
-#endif
-
-#endif
diff --git a/erts/etc/common/to_erl_common.c b/erts/etc/common/to_erl_common.c
deleted file mode 100644
index 8aa94ccfa4..0000000000
--- a/erts/etc/common/to_erl_common.c
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-2013. 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: to_erl.c
- *
- * This module implements a process that opens two specified FIFOs, one
- * for reading and one for writing; reads from its stdin, and writes what
- * it has read to the write FIF0; reads from the read FIFO, and writes to
- * its stdout.
- *
- ________ _________
- | |--<-- pipe.r (fifo1) --<--| |
- | to_erl | | run_erl | (parent)
- |________|-->-- pipe.w (fifo2) -->--|_________|
- ^ master pty
- |
- | slave pty
- ____V____
- | |
- | "erl" | (child)
- |_________|
- */
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <dirent.h>
-#include <errno.h>
-
-#ifdef __OSE__
-#include <aio.h>
-#include "ose.h"
-#include "efs.h"
-#include "ose_spi/fm.sig"
-#else /* __UNIX__ */
-#include <termios.h>
-#include <signal.h>
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-
-#include "to_erl_common.h"
-#include "run_erl_vsn.h"
-#include "safe_string.h" /* strn_cpy, strn_catf, sn_printf, etc. */
-
-#if defined(O_NONBLOCK)
-# define DONT_BLOCK_PLEASE O_NONBLOCK
-#else
-# define DONT_BLOCK_PLEASE O_NDELAY
-# if !defined(EAGAIN)
-# define EAGAIN -3898734
-# endif
-#endif
-
-#ifdef HAVE_STRERROR
-# define STRERROR(x) strerror(x)
-#else
-# define STRERROR(x) ""
-#endif
-
-#define noDEBUG
-
-#ifdef __OSE__
-#define PIPE_DIR "/pipe/"
-#else
-#define PIPE_DIR "/tmp/"
-#endif
-#define PIPE_STUBNAME "erlang.pipe"
-#define PIPE_STUBLEN strlen(PIPE_STUBNAME)
-
-#ifdef DEBUG
-#define STATUS(s) { fprintf(stderr, (s)); fflush(stderr); }
-#else
-#define STATUS(s)
-#endif
-
-#ifndef FILENAME_MAX
-#define FILENAME_MAX 250
-#endif
-
-static int tty_eof = 0;
-static int protocol_ver = RUN_ERL_LO_VER; /* assume lowest to begin with */
-
-static int write_all(int fd, const char* buf, int len);
-static int version_handshake(char* buf, int len, int wfd);
-
-
-#ifdef __OSE__
-
-#define SET_AIO(REQ,FD,SIZE,BUFF) \
- /* Make sure to clean data structure of previous request */ \
- memset(&(REQ),0,sizeof(REQ)); \
- (REQ).aio_fildes = FD; \
- (REQ).aio_offset = FM_POSITION_CURRENT; \
- (REQ).aio_nbytes = SIZE; \
- (REQ).aio_buf = BUFF; \
- (REQ).aio_sigevent.sigev_notify = SIGEV_NONE
-
-#define READ_AIO(REQ,FD,SIZE,BUFF) \
- SET_AIO(REQ,FD,SIZE,BUFF); \
- if (aio_read(&(REQ)) != 0) \
- fprintf(stderr,"aio_read of child_read_req(%d) failed" \
- "with error %d\n",FD,errno)
-
-union SIGNAL {
- SIGSELECT signo;
- struct FmReadPtr fm_read_ptr;
-};
-
-#else /* __UNIX__ */
-static int recv_sig = 0;
-static struct termios tty_smode, tty_rmode;
-static int window_size_seq(char* buf, size_t bufsz);
-#ifdef DEBUG
-static void show_terminal_settings(struct termios *);
-#endif
-
-static void handle_ctrlc(int sig)
-{
- /* Reinstall the handler, and signal break flag */
- signal(SIGINT,handle_ctrlc);
- recv_sig = SIGINT;
-}
-
-static void handle_sigwinch(int sig)
-{
- recv_sig = SIGWINCH;
-}
-#endif
-
-static void usage(char *pname)
-{
- fprintf(stderr, "Usage: ");
- fprintf(stderr,TO_ERL_USAGE,pname);
-}
-
-int to_erl(int argc, char **argv)
-{
- char FIFO1[FILENAME_MAX], FIFO2[FILENAME_MAX];
- int i, len, wfd, rfd;
- char pipename[FILENAME_MAX];
- int pipeIx = 1;
- int force_lock = 0;
- int got_some = 0;
-
-#ifdef __OSE__
- struct aiocb stdin_read_req, pipe_read_req;
- FmHandle stdin_fh, pipe_fh;
- char *stdin_buf, *pipe_buf;
- char *buf;
- union SIGNAL *sig;
-#else /* __UNIX__ */
- char buf[BUFSIZ];
- fd_set readfds;
-#endif
-
- if (argc >= 2 && argv[1][0]=='-') {
- switch (argv[1][1]) {
- case 'h':
- usage(argv[0]);
- exit(1);
- case 'F':
- force_lock = 1;
- break;
- default:
- fprintf(stderr,"Invalid option '%s'\n",argv[1]);
- exit(1);
- }
- pipeIx = 2;
- }
-
-#ifdef DEBUG
- fprintf(stderr, "%s: pid is : %d\n", argv[0],(int)
-#ifdef __OSE__
- current_process()
-#else /* __UNIX__ */
- getpid()
-#endif
- );
-#endif
-
- strn_cpy(pipename, sizeof(pipename),
- (argv[pipeIx] ? argv[pipeIx] : PIPE_DIR));
-
- if(*pipename && pipename[strlen(pipename)-1] == '/') {
- /* The user wishes us to find a pipe name in the specified */
- /* directory */
- int highest_pipe_num = 0;
- DIR *dirp;
- struct dirent *direntp;
-
- dirp = opendir(pipename);
- if(!dirp) {
- fprintf(stderr, "Can't access pipe directory %s: %s\n", pipename, strerror(errno));
- exit(1);
- }
-
- /* Check the directory for existing pipes */
-
- while((direntp=readdir(dirp)) != NULL) {
- if(strncmp(direntp->d_name,PIPE_STUBNAME,PIPE_STUBLEN)==0) {
- int num = atoi(direntp->d_name+PIPE_STUBLEN+1);
- if(num > highest_pipe_num)
- highest_pipe_num = num;
- }
- }
- closedir(dirp);
- strn_catf(pipename, sizeof(pipename), (highest_pipe_num?"%s.%d":"%s"),
- PIPE_STUBNAME, highest_pipe_num);
- } /* if */
-
- /* read FIFO */
- sn_printf(FIFO1,sizeof(FIFO1),"%s.r",pipename);
- /* write FIFO */
- sn_printf(FIFO2,sizeof(FIFO2),"%s.w",pipename);
-
-#ifndef __OSE__
- /* Check that nobody is running to_erl on this pipe already */
- if ((wfd = open (FIFO1, O_WRONLY|DONT_BLOCK_PLEASE, 0)) >= 0) {
- /* Open as server succeeded -- to_erl is already running! */
- close(wfd);
- fprintf(stderr, "Another to_erl process already attached to pipe "
- "%s.\n", pipename);
- if (force_lock) {
- fprintf(stderr, "But we proceed anyway by force (-F).\n");
- }
- else {
- exit(1);
- }
- }
-#endif
-
- if ((rfd = open (FIFO1, O_RDONLY|DONT_BLOCK_PLEASE, 0)) < 0) {
-#ifdef DEBUG
- fprintf(stderr, "Could not open FIFO %s for reading.\n", FIFO1);
-#endif
- fprintf(stderr, "No running Erlang on pipe %s: %s\n", pipename, strerror(errno));
- exit(1);
- }
-#ifdef DEBUG
- fprintf(stderr, "to_erl: %s opened for reading\n", FIFO1);
-#endif
-
- if ((wfd = open (FIFO2, O_WRONLY|DONT_BLOCK_PLEASE, 0)) < 0) {
-#ifdef DEBUG
- fprintf(stderr, "Could not open FIFO %s for writing.\n", FIFO2);
-#endif
- fprintf(stderr, "No running Erlang on pipe %s: %s\n", pipename, strerror(errno));
- close(rfd);
- exit(1);
- }
-#ifdef DEBUG
- fprintf(stderr, "to_erl: %s opened for writing\n", FIFO2);
-#endif
-
-#ifndef __OSE__
- fprintf(stderr, "Attaching to %s (^D to exit)\n\n", pipename);
-#else
- fprintf(stderr, "Attaching to %s (^C to exit)\n\n", pipename);
-#endif
-
-#ifndef __OSE__
- /* Set break handler to our handler */
- signal(SIGINT,handle_ctrlc);
-
- /*
- * Save the current state of the terminal, and set raw mode.
- */
- if (tcgetattr(0, &tty_rmode) , 0) {
- fprintf(stderr, "Cannot get terminals current mode\n");
- exit(-1);
- }
- tty_smode = tty_rmode;
- tty_eof = '\004'; /* Ctrl+D to exit */
-#ifdef DEBUG
- show_terminal_settings(&tty_rmode);
-#endif
- tty_smode.c_iflag =
- 1*BRKINT |/*Signal interrupt on break.*/
- 1*IGNPAR |/*Ignore characters with parity errors.*/
- 1*ISTRIP |/*Strip character.*/
- 0;
-
-#if 0
-0*IGNBRK |/*Ignore break condition.*/
-0*PARMRK |/*Mark parity errors.*/
-0*INPCK |/*Enable input parity check.*/
-0*INLCR |/*Map NL to CR on input.*/
-0*IGNCR |/*Ignore CR.*/
-0*ICRNL |/*Map CR to NL on input.*/
-0*IUCLC |/*Map upper-case to lower-case on input.*/
-0*IXON |/*Enable start/stop output control.*/
-0*IXANY |/*Enable any character to restart output.*/
-0*IXOFF |/*Enable start/stop input control.*/
-0*IMAXBEL|/*Echo BEL on input line too long.*/
-#endif
-
- tty_smode.c_oflag =
- 1*OPOST |/*Post-process output.*/
- 1*ONLCR |/*Map NL to CR-NL on output.*/
-#ifdef XTABS
- 1*XTABS |/*Expand tabs to spaces. (Linux)*/
-#endif
-#ifdef OXTABS
- 1*OXTABS |/*Expand tabs to spaces. (FreeBSD)*/
-#endif
-#ifdef NL0
- 1*NL0 |/*Select newline delays*/
-#endif
-#ifdef CR0
- 1*CR0 |/*Select carriage-return delays*/
-#endif
-#ifdef TAB0
- 1*TAB0 |/*Select horizontal tab delays*/
-#endif
-#ifdef BS0
- 1*BS0 |/*Select backspace delays*/
-#endif
-#ifdef VT0
- 1*VT0 |/*Select vertical tab delays*/
-#endif
-#ifdef FF0
- 1*FF0 |/*Select form feed delays*/
-#endif
- 0;
-
-#if 0
-0*OLCUC |/*Map lower case to upper on output.*/
-0*OCRNL |/*Map CR to NL on output.*/
-0*ONOCR |/*No CR output at column 0.*/
-0*ONLRET |/*NL performs CR function.*/
-0*OFILL |/*Use fill characters for delay.*/
-0*OFDEL |/*Fill is DEL, else NULL.*/
-0*NL1 |
-0*CR1 |
-0*CR2 |
-0*CR3 |
-0*TAB1 |
-0*TAB2 |
-0*TAB3 |/*Expand tabs to spaces.*/
-0*BS1 |
-0*VT1 |
-0*FF1 |
-#endif
-
- /* JALI: removed setting the tty_smode.c_cflag flags, since this is not */
- /* advisable if this is a *real* terminal, such as the console. In fact */
- /* this may hang the entire machine, deep, deep down (signalling break */
- /* or toggling the abort switch doesn't help) */
-
- tty_smode.c_lflag =
- 0;
-
-#if 0
-0*ISIG |/*Enable signals.*/
-0*ICANON |/*Canonical input (erase and kill processing).*/
-0*XCASE |/*Canonical upper/lower presentation.*/
-0*ECHO |/*Enable echo.*/
-0*ECHOE |/*Echo erase character as BS-SP-BS.*/
-0*ECHOK |/*Echo NL after kill character.*/
-0*ECHONL |/*Echo NL.*/
-0*NOFLSH |/*Disable flush after interrupt or quit.*/
-0*TOSTOP |/*Send SIGTTOU for background output.*/
-0*ECHOCTL|/*Echo control characters as ^char, delete as ^?.*/
-0*ECHOPRT|/*Echo erase character as character erased.*/
-0*ECHOKE |/*BS-SP-BS erase entire line on line kill.*/
-0*FLUSHO |/*Output is being flushed.*/
-0*PENDIN |/*Retype pending input at next read or input character.*/
-0*IEXTEN |/*Enable extended (implementation-defined) functions.*/
-#endif
-
- tty_smode.c_cc[VMIN] =0;/* Note that VMIN is the same as VEOF! */
- tty_smode.c_cc[VTIME] =0;/* Note that VTIME is the same as VEOL! */
- tty_smode.c_cc[VINTR] =3;
-
- tcsetattr(0, TCSADRAIN, &tty_smode);
-
-#ifdef DEBUG
- show_terminal_settings(&tty_smode);
-#endif
-
-#endif /* !__OSE__ */
- /*
- * "Write a ^L to the FIFO which causes the other end to redisplay
- * the input line."
- * This does not seem to work as was intended in old comment above.
- * However, this control character is now (R12B-3) used by run_erl
- * to trigger the version handshaking between to_erl and run_erl
- * at the start of every new to_erl-session.
- */
-
- if (write(wfd, "\014", 1) < 0) {
- fprintf(stderr, "Error in writing ^L to FIFO.\n");
- }
-
-#ifdef __OSE__
- /* we have a tiny stack so we malloc the buffers */
- stdin_buf = malloc(sizeof(char) * BUFSIZ);
- pipe_buf = malloc(sizeof(char) * BUFSIZ);
-
- efs_examine_fd(rfd,FLIB_FD_HANDLE,&pipe_fh);
- efs_examine_fd(0,FLIB_FD_HANDLE,&stdin_fh);
- READ_AIO(stdin_read_req,0,BUFSIZ,stdin_buf);
- READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_buf);
-#endif
-
- /*
- * read and write
- */
- while (1) {
-#ifndef __OSE__
- FD_ZERO(&readfds);
- FD_SET(0, &readfds);
- FD_SET(rfd, &readfds);
- if (select(rfd + 1, &readfds, NULL, NULL, NULL) < 0) {
- if (recv_sig) {
- FD_ZERO(&readfds);
- }
- else {
- fprintf(stderr, "Error in select.\n");
- break;
- }
- }
- len = 0;
-
- /*
- * Read from terminal and write to FIFO
- */
- if (recv_sig) {
- switch (recv_sig) {
- case SIGINT:
- fprintf(stderr, "[Break]\n\r");
- buf[0] = '\003';
- len = 1;
- break;
- case SIGWINCH:
- len = window_size_seq(buf,sizeof(buf));
- break;
- default:
- fprintf(stderr,"Unexpected signal: %u\n",recv_sig);
- }
- recv_sig = 0;
- }
- else
-#else /* __OSE__ */
- SIGSELECT sigsel[] = {0};
- sig = receive(sigsel);
- len = 0;
-#endif
-#ifndef __OSE__
- if (FD_ISSET(0,&readfds)) {
- len = read(0, buf, sizeof(buf));
-#else /* __OSE__ */
- if (sig->signo == FM_READ_PTR_REPLY &&
- sig->fm_read_ptr.handle == stdin_fh) {
- len = sig->fm_read_ptr.status == EFS_SUCCESS ? sig->fm_read_ptr.actual : -1;
- buf = sig->fm_read_ptr.buffer;
-#endif
- if (len <= 0) {
- close(rfd);
- close(wfd);
- if (len < 0) {
- fprintf(stderr, "Error in reading from stdin.\n");
- } else {
- fprintf(stderr, "[EOF]\n\r");
- }
- break;
- }
- /* check if there is an eof character in input */
- for (i = 0; i < len-1 && buf[i] != tty_eof; i++);
- if (buf[i] == tty_eof) {
- fprintf(stderr, "[Quit]\n\r");
- break;
- }
- }
-
- if (len) {
-#ifdef DEBUG
- if(write(1, buf, len));
-#endif
- if (write_all(wfd, buf, len) != len) {
- fprintf(stderr, "Error in writing to FIFO.\n");
- close(rfd);
- close(wfd);
- break;
- }
- STATUS("\" OK\r\n");
-#ifdef __OSE__
- aio_dispatch(sig);
- READ_AIO(stdin_read_req, 0, BUFSIZ, stdin_buf);
-#endif
- }
-
- /*
- * Read from FIFO, write to terminal.
- */
-#ifndef __OSE__
- if (FD_ISSET(rfd, &readfds)) {
- STATUS("FIFO read: ");
- len = read(rfd, buf, BUFSIZ);
-#else /* __OSE__ */
- if (sig->signo == FM_READ_PTR_REPLY &&
- sig->fm_read_ptr.handle == pipe_fh) {
- len = sig->fm_read_ptr.status == EFS_SUCCESS ? sig->fm_read_ptr.actual : -1;
- buf = sig->fm_read_ptr.buffer;
-#endif
- if (len < 0 && errno == EAGAIN) {
- /*
- * No data this time, but the writing end of the FIFO is still open.
- * Do nothing.
- */
- ;
- } else if (len <= 0) {
- /*
- * Either an error or end of file. In either case, break out
- * of the loop.
- */
- close(rfd);
- close(wfd);
- if (len < 0) {
- fprintf(stderr, "Error in reading from FIFO.\n");
- } else
- fprintf(stderr, "[End]\n\r");
- break;
- } else {
- if (!got_some) {
- if ((len=version_handshake(buf,len,wfd)) < 0) {
- close(rfd);
- close(wfd);
- break;
- }
-#ifndef __OSE__
- if (protocol_ver >= 1) {
- /* Tell run_erl size of terminal window */
- signal(SIGWINCH, handle_sigwinch);
- raise(SIGWINCH);
- }
-#endif
- got_some = 1;
- }
-
- /*
- * We successfully read at least one character. Write what we got.
- */
- STATUS("Terminal write: \"");
- if (write_all(1, buf, len) != len) {
- fprintf(stderr, "Error in writing to terminal.\n");
- close(rfd);
- close(wfd);
- break;
- }
- STATUS("\" OK\r\n");
-#ifdef __OSE__
- aio_dispatch(sig);
- READ_AIO(pipe_read_req, rfd, BUFSIZ, pipe_buf);
-#endif
- }
- }
- }
-
-#ifndef __OSE__
- /*
- * Reset terminal characterstics
- * XXX
- */
- tcsetattr(0, TCSADRAIN, &tty_rmode);
-#endif
- return 0;
-}
-
-/* Call write() until entire buffer has been written or error.
- * Return len or -1.
- */
-static int write_all(int fd, const char* buf, int len)
-{
- int left = len;
- int written;
- while (left) {
- written = write(fd,buf,left);
- if (written < 0) {
- return -1;
- }
- left -= written;
- buf += written;
- }
- return len;
-}
-
-#ifndef __OSE__
-static int window_size_seq(char* buf, size_t bufsz)
-{
-#ifdef TIOCGWINSZ
- struct winsize ws;
- static const char prefix[] = "\033_";
- static const char suffix[] = "\033\\";
- /* This Esc sequence is called "Application Program Command"
- and seems suitable to use for our own customized stuff. */
-
- if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0) {
- int len = sn_printf(buf, bufsz, "%swinsize=%u,%u%s",
- prefix, ws.ws_col, ws.ws_row, suffix);
- return len;
- }
-#endif /* TIOCGWINSZ */
- return 0;
-}
-#endif /* !__OSE__ */
-
-/* to_erl run_erl
- * | |
- * |---------- '\014' -------->| (session start)
- * | |
- * |<---- "[run_erl v1-0]" ----| (version interval)
- * | |
- * |--- Esc_"version=1"Esc\ -->| (common version)
- * | |
- */
-static int version_handshake(char* buf, int len, int wfd)
-{
- unsigned re_high=0, re_low;
- char *end = find_str(buf,len,"]\n");
-
- if (end && sscanf(buf,"[run_erl v%u-%u",&re_high,&re_low)==2) {
- char wbuf[30];
- int wlen;
-
- if (re_low > RUN_ERL_HI_VER || re_high < RUN_ERL_LO_VER) {
- fprintf(stderr,"Incompatible versions: to_erl=v%u-%u run_erl=v%u-%u\n",
- RUN_ERL_HI_VER, RUN_ERL_LO_VER, re_high, re_low);
- return -1;
- }
- /* Choose highest common version */
- protocol_ver = re_high < RUN_ERL_HI_VER ? re_high : RUN_ERL_HI_VER;
-
- wlen = sn_printf(wbuf, sizeof(wbuf), "\033_version=%u\033\\",
- protocol_ver);
- if (write_all(wfd, wbuf, wlen) < 0) {
- fprintf(stderr,"Failed to send version handshake\n");
- return -1;
- }
- end += 2;
- len -= (end-buf);
- memmove(buf,end,len);
-
- }
- else { /* we assume old run_erl without version handshake */
- protocol_ver = 0;
- }
-
- if (re_high != RUN_ERL_HI_VER) {
- fprintf(stderr,"run_erl has different version, "
- "using common protocol level %u\n", protocol_ver);
- }
-
- return len;
-}
-
-
-#if defined(DEBUG) && !defined(__OSE__)
-#define S(x) ((x) > 0 ? 1 : 0)
-
-static void show_terminal_settings(struct termios *t)
-{
- fprintf(stderr,"c_iflag:\n");
- fprintf(stderr,"Signal interrupt on break: BRKINT %d\n", S(t->c_iflag & BRKINT));
- fprintf(stderr,"Map CR to NL on input: ICRNL %d\n", S(t->c_iflag & ICRNL));
- fprintf(stderr,"Ignore break condition: IGNBRK %d\n", S(t->c_iflag & IGNBRK));
- fprintf(stderr,"Ignore CR: IGNCR %d\n", S(t->c_iflag & IGNCR));
- fprintf(stderr,"Ignore char with par. err's: IGNPAR %d\n", S(t->c_iflag & IGNPAR));
- fprintf(stderr,"Map NL to CR on input: INLCR %d\n", S(t->c_iflag & INLCR));
- fprintf(stderr,"Enable input parity check: INPCK %d\n", S(t->c_iflag & INPCK));
- fprintf(stderr,"Strip character ISTRIP %d\n", S(t->c_iflag & ISTRIP));
- fprintf(stderr,"Enable start/stop input ctrl IXOFF %d\n", S(t->c_iflag & IXOFF));
- fprintf(stderr,"ditto output ctrl IXON %d\n", S(t->c_iflag & IXON));
- fprintf(stderr,"Mark parity errors PARMRK %d\n", S(t->c_iflag & PARMRK));
- fprintf(stderr,"\n");
- fprintf(stderr,"c_oflag:\n");
- fprintf(stderr,"Perform output processing OPOST %d\n", S(t->c_oflag & OPOST));
- fprintf(stderr,"\n");
- fprintf(stderr,"c_cflag:\n");
- fprintf(stderr,"Ignore modem status lines CLOCAL %d\n", S(t->c_cflag & CLOCAL));
- fprintf(stderr,"\n");
- fprintf(stderr,"c_local:\n");
- fprintf(stderr,"Enable echo ECHO %d\n", S(t->c_lflag & ECHO));
- fprintf(stderr,"\n");
- fprintf(stderr,"c_cc:\n");
- fprintf(stderr,"c_cc[VEOF] %d\n", t->c_cc[VEOF]);
-}
-#endif /* DEBUG && !__OSE__ */
diff --git a/erts/etc/common/to_erl_common.h b/erts/etc/common/to_erl_common.h
deleted file mode 100644
index a139da418f..0000000000
--- a/erts/etc/common/to_erl_common.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2013. 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%
- */
-#ifndef ERL_TO_ERL_H
-#define ERL_TO_ERL_H
-
-#define TO_ERL_USAGE "to_erl [-h|-F] %s\n" \
- "\t-h\tThis help text.\n" \
- "\t-f\tForce connection even though pipe is locked by other to_erl process."
-
-int to_erl(int argc, char **argv);
-
-#endif
diff --git a/erts/etc/ose/etc.lmconf b/erts/etc/ose/etc.lmconf
deleted file mode 100644
index b402b325b1..0000000000
--- a/erts/etc/ose/etc.lmconf
+++ /dev/null
@@ -1,20 +0,0 @@
-OSE_LM_STACK_SIZES=256,512,1024,2048,4096,8192,16384,65536
-OSE_LM_SIGNAL_SIZES=31,63,127,255,1023,4095,16383,65535
-OSE_LM_POOL_SIZE=0x200000
-OSE_LM_MAIN_NAME=main
-OSE_LM_MAIN_STACK_SIZE=0xF000
-OSE_LM_MAIN_PRIORITY=20
-## Has to be of a type that allows MAM
-OSE_LM_PROGRAM_TYPE=APP_RAM
-OSE_LM_DATA_INIT=YES
-OSE_LM_BSS_INIT=YES
-OSE_LM_EXEC_MODEL=SHARED
-HEAP_MAX_SIZE=1000000000
-HEAP_SMALL_BUF_INIT_SIZE=64000000
-HEAP_LARGE_BUF_THRESHOLD=16000000
-HEAP_LOCK_TYPE=2
-
-# Setting the environment variable EFS_RESOLVE_TMO on the block to 0.
-# This will eliminiate delays when trying to open files on not mounted
-# volumes.
-EFS_RESOLVE_TMO=0
diff --git a/erts/etc/ose/run_erl.c b/erts/etc/ose/run_erl.c
deleted file mode 100644
index 6775525297..0000000000
--- a/erts/etc/ose/run_erl.c
+++ /dev/null
@@ -1,664 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2013. 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: run_erl.c
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-/* System includes */
-#include <aio.h>
-#include <errno.h>
-#include <dirent.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-/* OSE includes */
-#include "ose.h"
-#include "ose_spi/ose_spi.h"
-#include "efs.h"
-#include "pm.h"
-#include "ose_spi/fm.sig"
-
-/* erts includes */
-#include "run_erl.h"
-#include "run_erl_common.h"
-#include "safe_string.h" /* sn_printf, strn_cpy, strn_cat, etc */
-
-typedef struct RunErlSetup_ {
- SIGSELECT signo;
- int run_daemon;
- char *logdir;
- char *command;
- char *pipename;
- char *blockname;
-} RunErlSetup;
-
-typedef struct ProgramState_ {
- /* child process */
- int ifd, ofd;
- OSDOMAIN domain;
- PROCESS progpid, mainbid;
- struct PmProgramInfo *info;
- /* to_erl */
- char w_pipe[FILENAME_BUFSIZ],
- r_pipe[FILENAME_BUFSIZ];
-} ProgramState;
-
-union SIGNAL {
- SIGSELECT signo;
- RunErlSetup setup;
- struct FmReadPtr fm_read_ptr;
- struct FmWritePtr fm_write_ptr;
-};
-
-static OSBOOLEAN hunt_in_block(char *block_name,
- char *process_name,
- PROCESS *pid);
-static int create_child_process(char *command_string, char *blockname,
- ProgramState *state);
-
-
-static OSBOOLEAN hunt_in_block(char *block_name,
- char *process_name,
- PROCESS *pid) {
- struct OS_pid_list *list;
- PROCESS block_id = OSE_ILLEGAL_PROCESS;
- int i;
- char *name;
-
- *pid = OSE_ILLEGAL_PROCESS;
-
- list = get_bid_list(0);
-
- if (!list)
- return 0;
-
- for (i = 0; i < list->count; i++) {
-
- if (list->list[i] == get_bid(current_process()))
- continue;
-
- name = (char*)get_pid_info(list->list[i], OSE_PI_NAME);
- if (name) {
- if (strcmp(name,block_name) == 0) {
- block_id = list->list[i];
- free_buf((union SIGNAL**)&name);
- break;
- }
- free_buf((union SIGNAL**)&name);
- }
- }
-
- free_buf((union SIGNAL**)&list);
-
- if (block_id == OSE_ILLEGAL_PROCESS)
- return 0;
-
- list = get_pid_list(block_id);
-
- if (!list)
- return 0;
-
- for (i = 0; i < list->count; i++) {
- name = (char*)get_pid_info(list->list[i], OSE_PI_NAME);
- if (name) {
- if (strcmp(name,process_name) == 0) {
- *pid = list->list[i];
- free_buf((union SIGNAL**)&name);
- break;
- }
- free_buf((union SIGNAL**)&name);
- }
- }
-
- free_buf((union SIGNAL**)&list);
-
- if (*pid == OSE_ILLEGAL_PROCESS)
- return 0;
-
- return 1;
-
-}
-
-
-static int create_child_process(char *command_string, char *blockname,
- ProgramState *state) {
- char *command = command_string;
- char *argv;
- int i = 0;
- int ret_status;
- PmStatus pm_status;
- int tmp_io[2];
- int fd_arr[3];
- int ifd[2], ofd[2];
- char *handle;
- struct PmLoadModuleInfoReply *mod_info;
-
- /* Parse out cmd and argv from the command string */
- while (1) {
- if (command[i] == ' ' || command[i] == '\0') {
- if (command[i] == '\0')
- argv = NULL;
- else {
- command[i] = '\0';
- argv = command_string + i + 1;
- }
- break;
- }
- i++;
- }
-
- if (blockname)
- handle = blockname;
- else
- handle = simple_basename(command);
-
- if (ose_pm_load_module_info(handle,&mod_info) == PM_SUCCESS) {
- /* Already installed */
- free_buf((union SIGNAL**)&mod_info);
- } else if ((pm_status = ose_pm_install_load_module(0,"ELF",command,handle,0,0,NULL))
- != PM_SUCCESS) {
- ERROR1(LOG_ERR,"ose_pm_install_load_module failed - pmstatus: 0x%08x\n",
- pm_status);
- return 0;
- }
-
- state->domain = PM_NEW_DOMAIN;
-
- pm_status = ose_pm_create_program(&state->domain, handle, 0, 0 , NULL,
- &state->progpid, &state->mainbid);
-
- if (pm_status != PM_SUCCESS) {
- if (pm_status == PM_EINSTALL_HANDLE_IN_USE)
- ERROR1(LOG_ERR,"ose_pm_create_program failed - "
- "install handle \"%s\" is in use. You can specify another "
- "install handle by using the -block option to run_erl.\n",handle);
- else
- ERROR1(LOG_ERR,"ose_pm_create_program failed - pmstatus: 0x%08x\n",
- pm_status);
- return 0;
- }
-
- pm_status = ose_pm_program_info(state->progpid, &state->info);
- /* FIXME don't forget to free this ((union SIGNAL **)&info) */
- if (pm_status != PM_SUCCESS) {
- ERROR1(LOG_ERR,"ose_pm_program_info failed - pmstatus: 0x%08x\n",
- pm_status);
- return 0;
- }
-
- /* We only clone stdin+stdout, what about stderr? */
-
- /* create pipes */
- if (pipe(ifd) < 0) {
- if (errno == ENOENT)
- ERRNO_ERR0(LOG_ERR,"The /pipe file system is not available\n");
- else
- ERRNO_ERR0(LOG_ERR,"pipe ifd failed\n");
- return 0;
- }
-
- if (pipe(ofd) < 0) {
- ERRNO_ERR0(LOG_ERR,"pipe ofd failed\n");
- return 0;
- }
-
- /* FIXME Lock? */
-
- /* backup our stdin stdout */
- if ((tmp_io[0] = dup(0)) < 0) {
- ERRNO_ERR0(LOG_ERR,"dup 0 failed\n");
- return 0;
- }
-
- if ((tmp_io[1] = dup(1)) < 0) {
- ERRNO_ERR0(LOG_ERR,"dup 1 failed\n");
- return 0;
- }
-
- /* set new pipe to fd 0,1 */
- if (dup2(ifd[1], 1) < 0) {
- ERRNO_ERR0(LOG_ERR,"dup2 1 failed\n");
- return 0;
- }
-
- if (dup2(ofd[0], 0) < 0) {
- ERRNO_ERR0(LOG_ERR,"dup2 0 failed\n");
- return 0;
- }
-
- /* clone array to newly created */
- fd_arr[0] = 2; /* Number of fd's */
- fd_arr[1] = 0;
- fd_arr[2] = 1;
-
- if ((ret_status = efs_clone_array(state->info->main_process, fd_arr))
- != EFS_SUCCESS) {
- ERROR1(LOG_ERR,"efs_close_array filed, errcode: %d\n", ret_status);
- return 0;
- }
-
- if (dup2(tmp_io[1], 1) < 0) {
- ERRNO_ERR0(LOG_ERR,"restoring dup2 1 failed\n");
- return 0;
- }
-
- if (dup2(tmp_io[0], 0) < 0) {
- ERRNO_ERR0(LOG_ERR,"restoring dup2 1 failed\n");
- return 0;
- }
-
- /* close loose-ends */
- sf_close(tmp_io[0]);
- sf_close(tmp_io[1]);
- sf_close(ifd[1]);
- sf_close(ofd[0]);
- state->ifd = ifd[0];
- state->ofd = ofd[1];
-
- if (argv && set_env(state->progpid, "ARGV", argv)) {
- ERRNO_ERR0(LOG_ERR,"something went wrong with set_env\n");
- }
-
- /*
- * Start the program.
- */
- pm_status = ose_pm_start_program(state->progpid);
- if (pm_status != PM_SUCCESS) {
- ERROR1(LOG_ERR,"ose_pm_install_load_module failed - pmstatus: 0x%08x\n",
- pm_status);
- return 0;
- }
-
- return 1;
-}
-
-#define SET_AIO(REQ,FD,SIZE,BUFF) \
- /* Make sure to clean data structure of previous request */ \
- memset(&(REQ),0,sizeof(REQ)); \
- (REQ).aio_fildes = FD; \
- (REQ).aio_offset = FM_POSITION_CURRENT; \
- (REQ).aio_nbytes = SIZE; \
- (REQ).aio_buf = BUFF; \
- (REQ).aio_sigevent.sigev_notify = SIGEV_NONE
-
-#define READ_AIO(REQ,FD,SIZE,BUFF) do { \
- SET_AIO(REQ,FD,SIZE,BUFF); \
- if (aio_read(&(REQ)) != 0) \
- ERRNO_ERR1(LOG_ERR,"aio_read of child_read_req(%d) failed\n",FD); \
- } while (0)
-
-#define WRITE_AIO(FD,SIZE,BUFF) do { \
- struct aiocb *write_req = malloc(sizeof(struct aiocb)); \
- char *write_buff = malloc(sizeof(char)*SIZE); \
- memcpy(write_buff,BUFF,SIZE); \
- SET_AIO(*write_req,FD,SIZE,write_buff); \
- if (aio_write(write_req) != 0) \
- ERRNO_ERR1(LOG_ERR,"aio_write of write_req(%d) failed\n",FD); \
- } while(0)
-
-int pass_on(ProgramState *state);
-int pass_on(ProgramState *s) {
- SIGSELECT sigsel[] = {0,FM_READ_PTR_REPLY};
- union SIGNAL *sig;
- char child_read_buff[BUFSIZ], pipe_read_buff[BUFSIZ];
- struct aiocb child_read_req, pipe_read_req;
- int rfd, wfd = 0;
- FmHandle rfh, child_rfh;
- int outstanding_writes = 0, got_some = 0, child_done = 0;
-
- if ((rfd = sf_open(s->r_pipe, O_RDONLY, 0)) < 0) {
- ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.\n", s->r_pipe);
- rfd = 0;
- return 1;
- }
-
- attach(NULL,s->progpid);
-
- /* Open the log file */
- erts_run_erl_log_open();
-
- efs_examine_fd(rfd,FLIB_FD_HANDLE,&rfh);
- efs_examine_fd(s->ifd,FLIB_FD_HANDLE,&child_rfh);
-
- READ_AIO(child_read_req,s->ifd,BUFSIZ,child_read_buff);
- READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_read_buff);
-
- while (1) {
- time_t now,last_activity;
-
- time(&last_activity);
- sig = receive_w_tmo(erts_run_erl_log_alive_minutes()*60000,sigsel);
-
- time(&now);
-
- if (sig) {
- erts_run_erl_log_activity(0,now,last_activity);
- } else {
- /* timeout */
- erts_run_erl_log_activity(1,now,last_activity);
- continue;
- }
-
- switch (sig->signo) {
- case OS_ATTACH_SIG: {
- if (rfd) { sf_close(rfd); rfd = 0; }
- free_buf(&sig);
- child_done = 1;
- /* Make sure to to let all outstanding write request finish */
- if (outstanding_writes)
- break;
- if (wfd) sf_close(wfd);
- return 0;
- }
- case FM_WRITE_PTR_REPLY: {
- if (sig->fm_write_ptr.status == EFS_SUCCESS) {
- if (sig->fm_write_ptr.actual < sig->fm_write_ptr.requested) {
- WRITE_AIO(wfd, sig->fm_write_ptr.requested-sig->fm_write_ptr.actual,
- sig->fm_write_ptr.buffer+sig->fm_write_ptr.actual);
- }
- } else {
- /* Assume to_erl has terminated. */
- sf_close(wfd);
- wfd = 0;
- }
- free((char*)sig->fm_write_ptr.buffer);
- aio_dispatch(sig);
- if ((--outstanding_writes == 0) && child_done) {
- if (wfd) sf_close(wfd);
- return 0;
- }
- break;
- }
- case FM_READ_PTR_REPLY: {
- /* Child fd */
- if (sig->fm_read_ptr.handle == child_rfh) {
-
- /* Child terminated */
- if (sig->fm_read_ptr.status != EFS_SUCCESS ||
- sig->fm_read_ptr.actual == 0) {
-
- if (rfd) { sf_close(rfd); rfd = 0; }
-
- if (sig->fm_read_ptr.status != EFS_SUCCESS) {
- ERROR0(LOG_ERR,"Erlang closed the connection.");
- aio_dispatch(sig);
- return 1;
- }
-
- /* child closed connection gracefully */
- aio_dispatch(sig);
- if (outstanding_writes) {
- child_done = 1;
- break;
- }
-
- if (wfd) sf_close(wfd);
-
- return 0;
- } else {
- erts_run_erl_log_write(sig->fm_read_ptr.buffer,
- sig->fm_read_ptr.actual);
- if (wfd) {
- WRITE_AIO(wfd, sig->fm_read_ptr.actual, sig->fm_read_ptr.buffer);
- outstanding_writes++;
- }
- aio_dispatch(sig);
- READ_AIO(child_read_req, s->ifd,BUFSIZ, child_read_buff);
- }
- /* pipe fd */
- } else if (sig->fm_read_ptr.handle == rfh) {
- if (sig->fm_read_ptr.status != EFS_SUCCESS) {
- if(rfd) sf_close(rfd);
- if(wfd) sf_close(wfd);
- aio_dispatch(sig);
- ERRNO_ERR0(LOG_ERR,"Error in reading from FIFO.");
- return 1;
- }
- if (sig->fm_read_ptr.actual == 0) {
- /* to_erl closed its end of the pipe */
- aio_dispatch(sig);
- sf_close(rfd);
- rfd = sf_open(s->r_pipe,O_RDONLY|DONT_BLOCK_PLEASE, 0);
- if (rfd < 0) {
- ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.",
- s->r_pipe);
- rfd = 0;
- } else {
- READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_read_buff);
- }
- got_some = 0; /* reset for next session */
- } else {
- int len = sig->fm_read_ptr.actual;
- char *buffer = sig->fm_read_ptr.buffer;
- if (!wfd) {
- /* Try to open the write pipe to to_erl. Now that we got some data
- * from to_erl, to_erl should already be reading this pipe - open
- * should succeed. But in case of error, we just ignore it.
- */
- if ((wfd = sf_open(s->w_pipe, O_WRONLY|DONT_BLOCK_PLEASE, 0)) < 0) {
- erts_run_erl_log_status("Client expected on FIFO %s, "
- "but can't open (len=%d)\n",
- s->w_pipe, sig->fm_read_ptr.actual);
- sf_close(rfd);
- rfd = sf_open(s->r_pipe, O_RDONLY|DONT_BLOCK_PLEASE, 0);
- if (rfd < 0) {
- ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.",
- s->r_pipe);
- return 1;
- }
- wfd = 0;
- } else {
-#ifdef DEBUG
- erts_run_erl_log_status("run_erl: %s opened for writing\n",
- s->w_pipe);
-#endif
- }
- }
-
- if (!got_some && wfd && buffer[0] == '\014') {
- char wbuf[30];
- int wlen = sn_printf(wbuf,sizeof(wbuf),"[run_erl v%u-%u]\n",
- RUN_ERL_HI_VER, RUN_ERL_LO_VER);
- /* For some reason this, the first write aio seems to
- not get an FM_WRITE_PTR_REPLY, so we do not do:
- outstanding_writes++;
- */
- WRITE_AIO(wfd, wlen, wbuf);
- }
- got_some = 1;
-
- /* Write the message */
-#ifdef DEBUG
- erts_run_erl_log_status("Pty master write; ");
-#endif
- len = erts_run_erl_extract_ctrl_seq(buffer,len, s->ofd);
-
- if (len > 0) {
- int wlen = erts_run_erl_write_all(s->ofd, buffer, len);
- if (wlen != len) {
- aio_dispatch(sig);
- ERRNO_ERR0(LOG_ERR,"Error in writing to terminal.");
- if(rfd) sf_close(rfd);
- if(wfd) sf_close(wfd);
- return 1;
- }
- }
-#ifdef DEBUG
- erts_run_erl_log_status("OK\n");
-#endif
- aio_dispatch(sig);
- READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_read_buff);
- }
- }
- break;
- }
- default: {
- free_buf(&sig);
- break;
- }
- }
- }
-}
-
-OS_PROCESS(run_erl_process) {
- char *logdir, *command, *blockname;
- SIGSELECT sigsel[] = {1,ERTS_SIGNAL_RUN_ERL_SETUP};
- union SIGNAL *sig = receive(sigsel);
- ProgramState state;
- char pipename[FILENAME_BUFSIZ];
-
- state.info = NULL;
-
- logdir = strdup(sig->setup.logdir);
- command = strdup(sig->setup.command);
- strn_cpy(pipename,sizeof(pipename),sig->setup.pipename);
-
- if (sig->setup.blockname)
- blockname = strdup(sig->setup.blockname);
- else
- blockname = NULL;
-
- erts_run_erl_log_init(sig->setup.run_daemon, logdir);
-
- free_buf(&sig);
-
- if (erts_run_erl_open_fifo(pipename,state.w_pipe,state.r_pipe))
- kill_proc(current_process());
-
- if (create_child_process(command,blockname,&state))
- pass_on(&state);
-
- free(logdir);
- free(command);
- if (blockname)
- free(blockname);
-
- if (state.info)
- free_buf(((union SIGNAL**)&state.info));
-
- sf_close(state.ifd);
- sf_close(state.ofd);
-
- unlink(state.w_pipe);
- unlink(state.r_pipe);
-
- kill_proc(current_process());
-}
-
-int run_erl(int argc,char **argv) {
- char *pipename, *logdir, *command, *blockname = NULL;
- int pipename_len, logdir_len, command_len, blockname_len = 0;
- int i = 1, run_daemon = 0;
- PROCESS pid;
- SIGSELECT sigsel[] = {0};
- union SIGNAL *sig;
-
- if(argc < 4) {
- fprintf(stderr,RUN_ERL_USAGE,"run_erl");
- return 1;
- }
-
- while (1) {
- if (argv[i][0] != '-')
- break;
- if (!strcmp(argv[i],"-daemon")) {
- run_daemon = 1;
- i++;
- continue;
- }
- if (!strcmp(argv[i],"-block")) {
- blockname = argv[i+1];
- blockname_len = strlen(argv[i+1]) + 1;
- i+=2;
- continue;
- }
- fprintf(stderr,RUN_ERL_USAGE,"run_erl");
- return 1;
- }
-
- pipename = argv[i++];
- logdir = argv[i++];
- command = argv[i++];
-
- /* + 1 to include NULL at end */
- logdir_len = strlen(logdir) + 1;
- command_len = strlen(command) + 1;
- pipename_len = strlen(pipename) + 1;
-
- if (run_daemon) {
- /* We request that the run_erl_process should be started from the
- main process so that it does not die when the shell command
- returns */
- PROCESS main_pid;
- hunt_in_block("run_erl","main",&main_pid);
- sig = alloc(sizeof(*sig),ERTS_SIGNAL_RUN_ERL_DAEMON);
- send(&sig,main_pid);
- sig = receive(sigsel);
- pid = sender(&sig);
- free_buf(&sig);
- } else {
- pid = create_process(OS_BG_PROC,"run_erl_process",
- run_erl_process, 0x800,
- 0, 0, 0, NULL, 0, 0);
- }
-
- sig = alloc(sizeof(RunErlSetup)+
- logdir_len+command_len+pipename_len+blockname_len,
- ERTS_SIGNAL_RUN_ERL_SETUP);
- sig->setup.run_daemon = run_daemon;
- sig->setup.logdir = ((char*)sig)+sizeof(RunErlSetup);
- sig->setup.command = ((char*)sig)+sizeof(RunErlSetup)+logdir_len;
- sig->setup.pipename = ((char*)sig)+sizeof(RunErlSetup)+logdir_len+command_len;
- if (blockname)
- sig->setup.blockname = ((char*)sig)+sizeof(RunErlSetup)+
- logdir_len+command_len+pipename_len;
- else
- sig->setup.blockname = NULL;
-
- strcpy(sig->setup.logdir,logdir);
- strcpy(sig->setup.command,command);
- strcpy(sig->setup.pipename,pipename);
- if (blockname) strcpy(sig->setup.blockname,blockname);
-
- send(&sig,pid);
-
- if (run_daemon) {
- /* We are a daemon, error msgs will be sent to ramlog */
- start(pid);
- return 1;
- }
-
- /* We are not daemon, error msgs will be sent to stderr and we block here */
- efs_clone(pid);
- start(pid);
-
- attach(NULL,pid);
- sig = receive(sigsel);
-
- return 1;
-}
diff --git a/erts/etc/ose/run_erl.h b/erts/etc/ose/run_erl.h
deleted file mode 100644
index bdc8b6c355..0000000000
--- a/erts/etc/ose/run_erl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2013. 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%
- */
-#ifndef ERL_RUN_ERL_H
-#define ERL_RUN_ERL_H
-
-#include "ose.h"
-
-#include "erts.sig"
-
-int run_erl(int argc, char **argv);
-OS_PROCESS(run_erl_process);
-
-#endif
diff --git a/erts/etc/ose/run_erl_main.c b/erts/etc/ose/run_erl_main.c
deleted file mode 100644
index 8895c773a1..0000000000
--- a/erts/etc/ose/run_erl_main.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2013. 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: run_erl_main.c
- *
- * Container for load module that installs both run_erl and to_erl command.
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <stdio.h>
-
-#include "ose.h"
-#include "shell.h"
-
-#include "run_erl_common.h"
-#include "run_erl.h"
-#include "to_erl_common.h"
-
-union SIGNAL {
- SIGSELECT signo;
-};
-
-int main(int argc, char **argv)
-{
-
- char run_erl_usage[320],
- to_erl_usage[120];
-
- (void)stdin;(void)stdout;(void)stderr;
-
- sprintf(run_erl_usage,RUN_ERL_USAGE,"run_erl [-daemon] [-block blockname]");
- sprintf(to_erl_usage,TO_ERL_USAGE,"pipename");
-
- shell_add_cmd_attrs(
- "run_erl",run_erl_usage,
- "Redirect Erlang input and output streams",
- run_erl,DEFAULT_PROC_TYPE,DEFAULT_PRIORITY,DEFAULT_STACK_SIZE);
-
- shell_add_cmd_attrs(
- "to_erl",to_erl_usage,
- "Attach to redirected Erlang input and output streams",
- to_erl,DEFAULT_PROC_TYPE,DEFAULT_PRIORITY,DEFAULT_STACK_SIZE);
-
- while (1) {
- static const SIGSELECT sigsel[] = {0};
- union SIGNAL *sig = receive(sigsel);
-
- if (sig->signo == ERTS_SIGNAL_RUN_ERL_DAEMON) {
- PROCESS pid = create_process(OS_BG_PROC,"run_erl_daemon",
- run_erl_process, 0x800,
- 0, 0, 0, NULL, 0, 0);
- send_w_s(&sig,pid,sender(&sig));
- } else {
- printf("Got unexpected signal!");
- free_buf(&sig);
- }
- }
-
- return 1;
-}
diff --git a/erts/etc/unix/etp-commands.in b/erts/etc/unix/etp-commands.in
index 19d67de92f..7b554e71f2 100644
--- a/erts/etc/unix/etp-commands.in
+++ b/erts/etc/unix/etp-commands.in
@@ -774,7 +774,7 @@ define etp-pid-1
#
set $etp_pid_1 = (Eterm)($arg0)
if ($etp_pid_1 & 0xF) == 0x3
- if (etp_arch_bits == 64 && etp_halfword == 0)
+ if (etp_arch_bits == 64)
if (etp_big_endian)
set $etp_pid_data = (unsigned) ((((Uint64) $etp_pid_1) >> 36) & 0x0fffffff)
else
@@ -834,7 +834,7 @@ define etp-port-1
#
set $etp_port_1 = (Eterm)($arg0)
if ($etp_port_1 & 0xF) == 0x7
- if (etp_arch_bits == 64 && etp_halfword == 0)
+ if (etp_arch_bits == 64)
if (etp_big_endian)
set $etp_port_data = (unsigned) ((((Uint64) $etp_port_1) >> 36) & 0x0fffffff)
else
@@ -1577,7 +1577,7 @@ define etp-term-dump-pid
#
set $etp_pid_1 = (Eterm)($arg0)
if ($etp_pid_1 & 0xF) == 0x3
- if (etp_arch_bits == 64 && etp_halfword == 0)
+ if (etp_arch_bits == 64)
if (etp_big_endian)
set $etp_pid_data = (unsigned) ((((Uint64) $etp_pid_1) >> 36) & 0x0fffffff)
else
@@ -1622,7 +1622,7 @@ end
define etp-pid2pix-1
# Args: Eterm
#
- if (etp_arch_bits == 64 && etp_halfword == 0)
+ if (etp_arch_bits == 64)
if (etp_big_endian)
set $etp_pix = (int) (((Uint64) $arg0) & 0x0fffffff)
else
@@ -1965,7 +1965,7 @@ end
define etp-port-id2pix-1
# Args: Eterm
#
- if (etp_arch_bits == 64 && etp_halfword == 0)
+ if (etp_arch_bits == 64)
if (etp_big_endian)
set $etp_pix = (int) (((Uint64) $arg0) & 0x0fffffff)
elser
@@ -2493,12 +2493,6 @@ define etp-system-info
printf "Little\n"
end
printf "Word size: %d-bit\n", etp_arch_bits
- printf "Halfword: "
- if (etp_halfword)
- printf "yes\n"
- else
- printf "no\n"
- end
printf "HiPE support: "
if (etp_hipe)
printf "yes\n"
diff --git a/erts/etc/unix/run_erl.c b/erts/etc/unix/run_erl.c
index c8414030ca..44efb975ba 100644
--- a/erts/etc/unix/run_erl.c
+++ b/erts/etc/unix/run_erl.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2013. All Rights Reserved.
+ * Copyright Ericsson AB 1996-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.
@@ -41,13 +41,11 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-
#ifdef HAVE_WORKING_POSIX_OPENPT
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
#endif
#endif
-
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
@@ -65,6 +63,11 @@
#include <dirent.h>
#include <termios.h>
#include <time.h>
+
+#ifdef __ANDROID__
+# include <termios.h>
+#endif
+
#ifdef HAVE_SYSLOG_H
# include <syslog.h>
#endif
@@ -84,25 +87,81 @@
# include <stropts.h>
#endif
-#include "run_erl_common.h"
+#include "run_erl.h"
#include "safe_string.h" /* sn_printf, strn_cpy, strn_cat, etc */
+#ifdef O_NONBLOCK
+# define DONT_BLOCK_PLEASE O_NONBLOCK
+#else
+# define DONT_BLOCK_PLEASE O_NDELAY
+# ifndef EAGAIN
+# define EAGAIN -3898734
+# endif
+#endif
+
+#define noDEBUG
+
+#define DEFAULT_LOG_GENERATIONS 5
+#define LOG_MAX_GENERATIONS 1000 /* No more than 1000 log files */
+#define LOG_MIN_GENERATIONS 2 /* At least two to switch between */
+#define DEFAULT_LOG_MAXSIZE 100000
+#define LOG_MIN_MAXSIZE 1000 /* Smallast value for changing log file */
+#define LOG_STUBNAME "erlang.log."
+#define LOG_PERM 0664
+#define DEFAULT_LOG_ACTIVITY_MINUTES 5
+#define DEFAULT_LOG_ALIVE_MINUTES 15
+#define DEFAULT_LOG_ALIVE_FORMAT "%a %b %e %T %Z %Y"
+#define ALIVE_BUFFSIZ 256
+
+#define PERM 0600
+#define STATUSFILENAME "/run_erl.log"
+#define PIPE_STUBNAME "erlang.pipe"
+#define PIPE_STUBLEN strlen(PIPE_STUBNAME)
+
+#ifndef FILENAME_MAX
+#define FILENAME_MAX 250
+#endif
+
+#ifndef O_SYNC
+#define O_SYNC 0
+#define USE_FSYNC 1
+#endif
+
#define MAX(x,y) ((x) > (y) ? (x) : (y))
+#define FILENAME_BUFSIZ FILENAME_MAX
+
/* prototypes */
static void usage(char *);
+static int create_fifo(char *name, int perm);
static int open_pty_master(char **name, int *sfd);
static int open_pty_slave(char *name);
static void pass_on(pid_t);
static void exec_shell(char **);
+static void status(const char *format,...);
+static void error_logf(int priority, int line, const char *format,...);
static void catch_sigchild(int);
+static int next_log(int log_num);
+static int prev_log(int log_num);
+static int find_next_log_num(void);
+static int open_log(int log_num, int flags);
+static void write_to_log(int* lfd, int* log_num, char* buf, int len);
static void daemon_init(void);
+static char *simple_basename(char *path);
static void init_outbuf(void);
static int outbuf_size(void);
static void clear_outbuf(void);
static char* outbuf_first(void);
static void outbuf_delete(int bytes);
static void outbuf_append(const char* bytes, int n);
+static int write_all(int fd, const char* buf, int len);
+static int extract_ctrl_seq(char* buf, int len);
+static void set_window_size(unsigned col, unsigned row);
+
+static ssize_t sf_write(int fd, const void *buffer, size_t len);
+static ssize_t sf_read(int fd, void *buffer, size_t len);
+static int sf_open(const char *path, int flags, mode_t mode);
+static int sf_close(int fd);
#ifdef DEBUG
static void show_terminal_settings(struct termios *t);
@@ -110,11 +169,20 @@ static void show_terminal_settings(struct termios *t);
/* static data */
static char fifo1[FILENAME_BUFSIZ], fifo2[FILENAME_BUFSIZ];
+static char statusfile[FILENAME_BUFSIZ];
+static char log_dir[FILENAME_BUFSIZ];
static char pipename[FILENAME_BUFSIZ];
static FILE *stdstatus = NULL;
+static int log_generations = DEFAULT_LOG_GENERATIONS;
+static int log_maxsize = DEFAULT_LOG_MAXSIZE;
+static int log_alive_minutes = DEFAULT_LOG_ALIVE_MINUTES;
+static int log_activity_minutes = DEFAULT_LOG_ACTIVITY_MINUTES;
+static int log_alive_in_gmt = 0;
+static char log_alive_format[ALIVE_BUFFSIZ+1];
static int run_daemon = 0;
static char *program_name;
static int mfd; /* master pty fd */
+static unsigned protocol_ver = RUN_ERL_LO_VER; /* assume lowest to begin with */
/*
* Output buffer.
@@ -145,13 +213,29 @@ static char* outbuf_in;
LOG_PID|LOG_CONS|LOG_NOWAIT,LOG_USER)
#endif
+#define ERROR0(Prio,Format) error_logf(Prio,__LINE__,Format"\n")
+#define ERROR1(Prio,Format,A1) error_logf(Prio,__LINE__,Format"\n",A1)
+#define ERROR2(Prio,Format,A1,A2) error_logf(Prio,__LINE__,Format"\n",A1,A2)
+
+#ifdef HAVE_STRERROR
+# define ADD_ERRNO(Format) "errno=%d '%s'\n"Format"\n",errno,strerror(errno)
+#else
+# define ADD_ERRNO(Format) "errno=%d\n"Format"\n",errno
+#endif
+#define ERRNO_ERR0(Prio,Format) error_logf(Prio,__LINE__,ADD_ERRNO(Format))
+#define ERRNO_ERR1(Prio,Format,A1) error_logf(Prio,__LINE__,ADD_ERRNO(Format),A1)
+
+
int main(int argc, char **argv)
{
int childpid;
int sfd = -1;
- char *ptyslave=NULL;
+ int fd;
+ char *p, *ptyslave=NULL;
int i = 1;
int off_argv;
+ int calculated_pipename = 0;
+ int highest_pipe_num = 0;
program_name = argv[0];
@@ -169,16 +253,122 @@ int main(int argc, char **argv)
off_argv = i;
strn_cpy(pipename, sizeof(pipename), argv[i++]);
-
- erts_run_erl_log_init(run_daemon,argv[i]);
+ strn_cpy(log_dir, sizeof(log_dir), argv[i]);
+ strn_cpy(statusfile, sizeof(statusfile), log_dir);
+ strn_cat(statusfile, sizeof(statusfile), STATUSFILENAME);
#ifdef DEBUG
- erts_run_erl_log_status("%s: pid is : %d\n", argv[0], getpid());
+ status("%s: pid is : %d\n", argv[0], getpid());
#endif
- /* Open read and write fifo */
- if (erts_run_erl_open_fifo(pipename,fifo1,fifo2))
- exit(1);
+ /* Get values for LOG file handling from the environment */
+ if ((p = getenv("RUN_ERL_LOG_ALIVE_MINUTES"))) {
+ log_alive_minutes = atoi(p);
+ if (!log_alive_minutes) {
+ ERROR1(LOG_ERR,"Minimum value for RUN_ERL_LOG_ALIVE_MINUTES is 1 "
+ "(current value is %s)",p);
+ }
+ log_activity_minutes = log_alive_minutes / 3;
+ if (!log_activity_minutes) {
+ ++log_activity_minutes;
+ }
+ }
+ if ((p = getenv("RUN_ERL_LOG_ACTIVITY_MINUTES"))) {
+ log_activity_minutes = atoi(p);
+ if (!log_activity_minutes) {
+ ERROR1(LOG_ERR,"Minimum value for RUN_ERL_LOG_ACTIVITY_MINUTES is 1 "
+ "(current value is %s)",p);
+ }
+ }
+ if ((p = getenv("RUN_ERL_LOG_ALIVE_FORMAT"))) {
+ if (strlen(p) > ALIVE_BUFFSIZ) {
+ ERROR1(LOG_ERR, "RUN_ERL_LOG_ALIVE_FORMAT can contain a maximum of "
+ "%d characters", ALIVE_BUFFSIZ);
+ }
+ strn_cpy(log_alive_format, sizeof(log_alive_format), p);
+ } else {
+ strn_cpy(log_alive_format, sizeof(log_alive_format), DEFAULT_LOG_ALIVE_FORMAT);
+ }
+ if ((p = getenv("RUN_ERL_LOG_ALIVE_IN_UTC")) && strcmp(p,"0")) {
+ ++log_alive_in_gmt;
+ }
+ if ((p = getenv("RUN_ERL_LOG_GENERATIONS"))) {
+ log_generations = atoi(p);
+ if (log_generations < LOG_MIN_GENERATIONS)
+ ERROR1(LOG_ERR,"Minimum RUN_ERL_LOG_GENERATIONS is %d", LOG_MIN_GENERATIONS);
+ if (log_generations > LOG_MAX_GENERATIONS)
+ ERROR1(LOG_ERR,"Maximum RUN_ERL_LOG_GENERATIONS is %d", LOG_MAX_GENERATIONS);
+ }
+
+ if ((p = getenv("RUN_ERL_LOG_MAXSIZE"))) {
+ log_maxsize = atoi(p);
+ if (log_maxsize < LOG_MIN_MAXSIZE)
+ ERROR1(LOG_ERR,"Minimum RUN_ERL_LOG_MAXSIZE is %d", LOG_MIN_MAXSIZE);
+ }
+
+ /*
+ * Create FIFOs and open them
+ */
+
+ if(*pipename && pipename[strlen(pipename)-1] == '/') {
+ /* The user wishes us to find a unique pipe name in the specified */
+ /* directory */
+ DIR *dirp;
+ struct dirent *direntp;
+
+ calculated_pipename = 1;
+ dirp = opendir(pipename);
+ if(!dirp) {
+ ERRNO_ERR1(LOG_ERR,"Can't access pipe directory '%s'.", pipename);
+ exit(1);
+ }
+
+ /* Check the directory for existing pipes */
+
+ while((direntp=readdir(dirp)) != NULL) {
+ if(strncmp(direntp->d_name,PIPE_STUBNAME,PIPE_STUBLEN)==0) {
+ int num = atoi(direntp->d_name+PIPE_STUBLEN+1);
+ if(num > highest_pipe_num)
+ highest_pipe_num = num;
+ }
+ }
+ closedir(dirp);
+ strn_catf(pipename, sizeof(pipename), "%s.%d",
+ PIPE_STUBNAME, highest_pipe_num+1);
+ } /* if */
+
+ for(;;) {
+ /* write FIFO - is read FIFO for `to_erl' program */
+ strn_cpy(fifo1, sizeof(fifo1), pipename);
+ strn_cat(fifo1, sizeof(fifo1), ".r");
+ if (create_fifo(fifo1, PERM) < 0) {
+ ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for writing.", fifo1);
+ exit(1);
+ }
+
+ /* read FIFO - is write FIFO for `to_erl' program */
+ strn_cpy(fifo2, sizeof(fifo2), pipename);
+ strn_cat(fifo2, sizeof(fifo2), ".w");
+
+ /* Check that nobody is running run_erl already */
+ if ((fd = sf_open(fifo2, O_WRONLY|DONT_BLOCK_PLEASE, 0)) >= 0) {
+ /* Open as client succeeded -- run_erl is already running! */
+ sf_close(fd);
+ if (calculated_pipename) {
+ ++highest_pipe_num;
+ strn_catf(pipename, sizeof(pipename), "%s.%d",
+ PIPE_STUBNAME, highest_pipe_num+1);
+ continue;
+ }
+ fprintf(stderr, "Erlang already running on pipe %s.\n", pipename);
+ exit(1);
+ }
+ if (create_fifo(fifo2, PERM) < 0) {
+ ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for reading.", fifo2);
+ exit(1);
+ }
+ break;
+ }
/*
* Open master pseudo-terminal
@@ -250,7 +440,7 @@ int main(int argc, char **argv)
sf_close(2);
if (dup(sfd) != 0 || dup(sfd) != 1 || dup(sfd) != 2) {
- erts_run_erl_log_status("Cannot dup\n");
+ status("Cannot dup\n");
}
sf_close(sfd);
exec_shell(argv+off_argv); /* exec_shell expects argv[2] to be */
@@ -293,7 +483,9 @@ static void pass_on(pid_t childpid)
struct timeval timeout;
time_t last_activity;
char buf[BUFSIZ];
- int rfd, wfd=0;
+ char log_alive_buffer[ALIVE_BUFFSIZ+1];
+ int lognum;
+ int rfd, wfd=0, lfd=0;
int maxfd;
int ready;
int got_some = 0; /* from to_erl */
@@ -308,12 +500,13 @@ static void pass_on(pid_t childpid)
}
#ifdef DEBUG
- erts_run_erl_log_status("run_erl: %s opened for reading\n", fifo2);
+ status("run_erl: %s opened for reading\n", fifo2);
#endif
/* Open the log file */
- erts_run_erl_log_open();
+ lognum = find_next_log_num();
+ lfd = open_log(lognum, O_RDWR|O_APPEND|O_CREAT|O_SYNC);
/* Enter the work loop */
@@ -332,8 +525,7 @@ static void pass_on(pid_t childpid)
writefds_ptr = &writefds;
}
time(&last_activity);
- /* don't assume old BSD bug */
- timeout.tv_sec = erts_run_erl_log_alive_minutes()*60;
+ timeout.tv_sec = log_alive_minutes*60; /* don't assume old BSD bug */
timeout.tv_usec = 0;
ready = select(maxfd + 1, &readfds, writefds_ptr, NULL, &timeout);
if (ready < 0) {
@@ -363,7 +555,28 @@ static void pass_on(pid_t childpid)
/* Check how long time we've been inactive */
time(&now);
- erts_run_erl_log_activity(!ready,now,last_activity);
+ if(!ready || now - last_activity > log_activity_minutes*60) {
+ /* Either a time out: 15 minutes without action, */
+ /* or something is coming in right now, but it's a long time */
+ /* since last time, so let's write a time stamp this message */
+ struct tm *tmptr;
+ if (log_alive_in_gmt) {
+ tmptr = gmtime(&now);
+ } else {
+ tmptr = localtime(&now);
+ }
+ if (!strftime(log_alive_buffer, ALIVE_BUFFSIZ, log_alive_format,
+ tmptr)) {
+ strn_cpy(log_alive_buffer, sizeof(log_alive_buffer),
+ "(could not format time in 256 positions "
+ "with current format string.)");
+ }
+ log_alive_buffer[ALIVE_BUFFSIZ] = '\0';
+
+ sn_printf(buf, sizeof(buf), "\n===== %s%s\n",
+ ready?"":"ALIVE ", log_alive_buffer);
+ write_to_log(&lfd, &lognum, buf, strlen(buf));
+ }
}
/*
@@ -398,7 +611,7 @@ static void pass_on(pid_t childpid)
*/
if (FD_ISSET(mfd, &readfds)) {
#ifdef DEBUG
- erts_run_erl_log_status("Pty master read; ");
+ status("Pty master read; ");
#endif
if ((len = sf_read(mfd, buf, BUFSIZ)) <= 0) {
sf_close(rfd);
@@ -416,7 +629,7 @@ static void pass_on(pid_t childpid)
exit(0);
}
- erts_run_erl_log_write(buf, len);
+ write_to_log(&lfd, &lognum, buf, len);
/*
* Save in the output queue.
@@ -432,7 +645,7 @@ static void pass_on(pid_t childpid)
*/
if (FD_ISSET(rfd, &readfds)) {
#ifdef DEBUG
- erts_run_erl_log_status("FIFO read; ");
+ status("FIFO read; ");
#endif
if ((len = sf_read(rfd, buf, BUFSIZ)) < 0) {
sf_close(rfd);
@@ -461,7 +674,7 @@ static void pass_on(pid_t childpid)
* should succeed. But in case of error, we just ignore it.
*/
if ((wfd = sf_open(fifo1, O_WRONLY|DONT_BLOCK_PLEASE, 0)) < 0) {
- erts_run_erl_log_status("Client expected on FIFO %s, but can't open (len=%d)\n",
+ status("Client expected on FIFO %s, but can't open (len=%d)\n",
fifo1, len);
sf_close(rfd);
rfd = sf_open(fifo2, O_RDONLY|DONT_BLOCK_PLEASE, 0);
@@ -473,7 +686,7 @@ static void pass_on(pid_t childpid)
}
else {
#ifdef DEBUG
- erts_run_erl_log_status("run_erl: %s opened for writing\n", fifo1);
+ status("run_erl: %s opened for writing\n", fifo1);
#endif
}
}
@@ -489,15 +702,14 @@ static void pass_on(pid_t childpid)
/* Write the message */
#ifdef DEBUG
- erts_run_erl_log_status("Pty master write; ");
+ status("Pty master write; ");
#endif
- len = erts_run_erl_extract_ctrl_seq(buf, len, mfd);
+ len = extract_ctrl_seq(buf, len);
if(len==1 && buf[0] == '\003') {
kill(childpid,SIGINT);
- }
- else if (len>0 && erts_run_erl_write_all(mfd, buf, len) != len)
- {
+ }
+ else if (len>0 && write_all(mfd, buf, len) != len) {
ERRNO_ERR0(LOG_ERR,"Error in writing to terminal.");
sf_close(rfd);
if(wfd) sf_close(wfd);
@@ -506,7 +718,7 @@ static void pass_on(pid_t childpid)
}
}
#ifdef DEBUG
- erts_run_erl_log_status("OK\n");
+ status("OK\n");
#endif
}
}
@@ -516,6 +728,173 @@ static void catch_sigchild(int sig)
{
}
+/*
+ * next_log:
+ * Returns the index number that follows the given index number.
+ * (Wrapping after log_generations)
+ */
+static int next_log(int log_num) {
+ return log_num>=log_generations?1:log_num+1;
+}
+
+/*
+ * prev_log:
+ * Returns the index number that precedes the given index number.
+ * (Wrapping after log_generations)
+ */
+static int prev_log(int log_num) {
+ return log_num<=1?log_generations:log_num-1;
+}
+
+/*
+ * find_next_log_num()
+ * Searches through the log directory to check which logs that already
+ * exist. It finds the "hole" in the sequence, and returns the index
+ * number for the last log in the log sequence. If there is no hole, index
+ * 1 is returned.
+ */
+static int find_next_log_num(void) {
+ int i, next_gen, log_gen;
+ DIR *dirp;
+ struct dirent *direntp;
+ int log_exists[LOG_MAX_GENERATIONS+1];
+ int stub_len = strlen(LOG_STUBNAME);
+
+ /* Initialize exiting log table */
+
+ for(i=log_generations; i>=0; i--)
+ log_exists[i] = 0;
+ dirp = opendir(log_dir);
+ if(!dirp) {
+ ERRNO_ERR1(LOG_ERR,"Can't access log directory '%s'", log_dir);
+ exit(1);
+ }
+
+ /* Check the directory for existing logs */
+
+ while((direntp=readdir(dirp)) != NULL) {
+ if(strncmp(direntp->d_name,LOG_STUBNAME,stub_len)==0) {
+ int num = atoi(direntp->d_name+stub_len);
+ if(num < 1 || num > log_generations)
+ continue;
+ log_exists[num] = 1;
+ }
+ }
+ closedir(dirp);
+
+ /* Find out the next available log file number */
+
+ next_gen = 0;
+ for(i=log_generations; i>=0; i--) {
+ if(log_exists[i])
+ if(next_gen)
+ break;
+ else
+ ;
+ else
+ next_gen = i;
+ }
+
+ /* Find out the current log file number */
+
+ if(next_gen)
+ log_gen = prev_log(next_gen);
+ else
+ log_gen = 1;
+
+ return log_gen;
+} /* find_next_log_num() */
+
+/* open_log()
+ * Opens a log file (with given index) for writing. Writing may be
+ * at the end or a trucnating write, according to flags.
+ * A LOGGING STARTED and time stamp message is inserted into the log file
+ */
+static int open_log(int log_num, int flags)
+{
+ char buf[FILENAME_MAX];
+ time_t now;
+ struct tm *tmptr;
+ char log_buffer[ALIVE_BUFFSIZ+1];
+ int lfd;
+
+ /* Remove the next log (to keep a "hole" in the log sequence) */
+ sn_printf(buf, sizeof(buf), "%s/%s%d",
+ log_dir, LOG_STUBNAME, next_log(log_num));
+ unlink(buf);
+
+ /* Create or continue on the current log file */
+ sn_printf(buf, sizeof(buf), "%s/%s%d", log_dir, LOG_STUBNAME, log_num);
+ if((lfd = sf_open(buf, flags, LOG_PERM))<0){
+ ERRNO_ERR1(LOG_ERR,"Can't open log file '%s'.", buf);
+ exit(1);
+ }
+
+ /* Write a LOGGING STARTED and time stamp into the log file */
+ time(&now);
+ if (log_alive_in_gmt) {
+ tmptr = gmtime(&now);
+ } else {
+ tmptr = localtime(&now);
+ }
+ if (!strftime(log_buffer, ALIVE_BUFFSIZ, log_alive_format,
+ tmptr)) {
+ strn_cpy(log_buffer, sizeof(log_buffer),
+ "(could not format time in 256 positions "
+ "with current format string.)");
+ }
+ log_buffer[ALIVE_BUFFSIZ] = '\0';
+
+ sn_printf(buf, sizeof(buf), "\n=====\n===== LOGGING STARTED %s\n=====\n",
+ log_buffer);
+ if (write_all(lfd, buf, strlen(buf)) < 0)
+ status("Error in writing to log.\n");
+
+#if USE_FSYNC
+ fsync(lfd);
+#endif
+
+ return lfd;
+}
+
+/* write_to_log()
+ * Writes a message to a log file. If the current log file is full,
+ * a new log file is opened.
+ */
+static void write_to_log(int* lfd, int* log_num, char* buf, int len)
+{
+ int size;
+
+ /* Decide if new logfile needed, and open if so */
+
+ size = lseek(*lfd,0,SEEK_END);
+ if(size+len > log_maxsize) {
+ sf_close(*lfd);
+ *log_num = next_log(*log_num);
+ *lfd = open_log(*log_num, O_RDWR|O_CREAT|O_TRUNC|O_SYNC);
+ }
+
+ /* Write to log file */
+
+ if (write_all(*lfd, buf, len) < 0) {
+ status("Error in writing to log.\n");
+ }
+
+#if USE_FSYNC
+ fsync(*lfd);
+#endif
+}
+
+/* create_fifo()
+ * Creates a new fifo with the given name and permission.
+ */
+static int create_fifo(char *name, int perm)
+{
+ if ((mkfifo(name, perm) < 0) && (errno != EEXIST))
+ return -1;
+ return 0;
+}
+
/* open_pty_master()
* Find a master device, open and return fd and slave device name.
@@ -712,9 +1091,9 @@ static void exec_shell(char **argv)
else
argv[0] = sh;
argv[1] = "-c";
- erts_run_erl_log_status("Args before exec of shell:\n");
+ status("Args before exec of shell:\n");
for (vp = argv, i = 0; *vp; vp++, i++)
- erts_run_erl_log_status("argv[%d] = %s\n", i, *vp);
+ status("argv[%d] = %s\n", i, *vp);
if (stdstatus) {
fclose(stdstatus);
}
@@ -725,6 +1104,26 @@ static void exec_shell(char **argv)
ERRNO_ERR0(LOG_ERR,"Could not execv");
}
+/* status()
+ * Prints the arguments to a status file
+ * Works like printf (see vfrpintf)
+ */
+static void status(const char *format,...)
+{
+ va_list args;
+ time_t now;
+
+ if (stdstatus == NULL)
+ stdstatus = fopen(statusfile, "w");
+ if (stdstatus == NULL)
+ return;
+ now = time(NULL);
+ fprintf(stdstatus, "run_erl [%d] %s", (int)getpid(), ctime(&now));
+ va_start(args, format);
+ vfprintf(stdstatus, format, args);
+ va_end(args);
+ fflush(stdstatus);
+}
static void daemon_init(void)
/* As R Stevens wants it, to a certain extent anyway... */
@@ -764,10 +1163,47 @@ static void daemon_init(void)
run_daemon = 1;
}
+/* error_logf()
+ * Prints the arguments to stderr or syslog
+ * Works like printf (see vfprintf)
+ */
+static void error_logf(int priority, int line, const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+
+#ifdef HAVE_SYSLOG_H
+ if (run_daemon) {
+ vsyslog(priority,format,args);
+ }
+ else
+#endif
+ {
+ time_t now = time(NULL);
+ fprintf(stderr, "run_erl:%d [%d] %s", line, (int)getpid(), ctime(&now));
+ vfprintf(stderr, format, args);
+ }
+ va_end(args);
+}
+
static void usage(char *pname)
{
- fprintf(stderr, "Usage: ");
- fprintf(stderr, RUN_ERL_USAGE, pname);
+ fprintf(stderr, "Usage: %s (pipe_name|pipe_dir/) log_dir \"command [parameters ...]\"\n", pname);
+ fprintf(stderr, "\nYou may also set the environment variables RUN_ERL_LOG_GENERATIONS\n");
+ fprintf(stderr, "and RUN_ERL_LOG_MAXSIZE to the number of log files to use and the\n");
+ fprintf(stderr, "size of the log file when to switch to the next log file\n");
+}
+
+/* Instead of making sure basename exists, we do our own */
+static char *simple_basename(char *path)
+{
+ char *ptr;
+ for (ptr = path; *ptr != '\0'; ++ptr) {
+ if (*ptr == '/') {
+ path = ptr + 1;
+ }
+ }
+ return path;
}
static void init_outbuf(void)
@@ -838,6 +1274,114 @@ static void outbuf_append(const char* buf, int n)
outbuf_in += n;
}
+/* Call write() until entire buffer has been written or error.
+ * Return len or -1.
+ */
+static int write_all(int fd, const char* buf, int len)
+{
+ int left = len;
+ int written;
+ for (;;) {
+ written = sf_write(fd,buf,left);
+ if (written == left) {
+ return len;
+ }
+ if (written < 0) {
+ return -1;
+ }
+ left -= written;
+ buf += written;
+ }
+}
+
+static ssize_t sf_read(int fd, void *buffer, size_t len) {
+ ssize_t n = 0;
+
+ do { n = read(fd, buffer, len); } while (n < 0 && errno == EINTR);
+
+ return n;
+}
+
+static ssize_t sf_write(int fd, const void *buffer, size_t len) {
+ ssize_t n = 0;
+
+ do { n = write(fd, buffer, len); } while (n < 0 && errno == EINTR);
+
+ return n;
+}
+
+static int sf_open(const char *path, int type, mode_t mode) {
+ int fd = 0;
+
+ do { fd = open(path, type, mode); } while(fd < 0 && errno == EINTR);
+
+ return fd;
+}
+static int sf_close(int fd) {
+ int res = 0;
+
+ do { res = close(fd); } while(fd < 0 && errno == EINTR);
+
+ return res;
+}
+/* Extract any control sequences that are ment only for run_erl
+ * and should not be forwarded to the pty.
+ */
+static int extract_ctrl_seq(char* buf, int len)
+{
+ static const char prefix[] = "\033_";
+ static const char suffix[] = "\033\\";
+ char* bufend = buf + len;
+ char* start = buf;
+ char* command;
+ char* end;
+
+ for (;;) {
+ start = find_str(start, bufend-start, prefix);
+ if (!start) break;
+
+ command = start + strlen(prefix);
+ end = find_str(command, bufend-command, suffix);
+ if (end) {
+ unsigned col, row;
+ if (sscanf(command,"version=%u", &protocol_ver)==1) {
+ /*fprintf(stderr,"to_erl v%u\n", protocol_ver);*/
+ }
+ else if (sscanf(command,"winsize=%u,%u", &col, &row)==2) {
+ set_window_size(col,row);
+ }
+ else {
+ ERROR2(LOG_ERR, "Ignoring unknown ctrl command '%.*s'\n",
+ (int)(end-command), command);
+ }
+
+ /* Remove ctrl sequence from buf */
+ end += strlen(suffix);
+ memmove(start, end, bufend-end);
+ bufend -= end - start;
+ }
+ else {
+ ERROR2(LOG_ERR, "Missing suffix in ctrl sequence '%.*s'\n",
+ (int)(bufend-start), start);
+ break;
+ }
+ }
+ return bufend - buf;
+}
+
+static void set_window_size(unsigned col, unsigned row)
+{
+#ifdef TIOCSWINSZ
+ struct winsize ws;
+ ws.ws_col = col;
+ ws.ws_row = row;
+ if (ioctl(mfd, TIOCSWINSZ, &ws) < 0) {
+ ERRNO_ERR0(LOG_ERR,"Failed to set window size");
+ }
+#endif
+}
+
+
#ifdef DEBUG
#define S(x) ((x) > 0 ? 1 : 0)
diff --git a/erts/etc/common/run_erl_vsn.h b/erts/etc/unix/run_erl.h
index 2c3e67e81c..cc70a98e52 100644
--- a/erts/etc/common/run_erl_vsn.h
+++ b/erts/etc/unix/run_erl.h
@@ -1,8 +1,8 @@
/*
* %CopyrightBegin%
- *
+ *
* Copyright Ericsson AB 2008-2009. 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
@@ -14,7 +14,7 @@
* 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%
*/
@@ -28,3 +28,4 @@
* 0: Older, without version handshake
* 1: R12B-3, version handshake + window size ctrl
*/
+
diff --git a/erts/etc/common/safe_string.c b/erts/etc/unix/safe_string.c
index cdcdbf16f0..a5c11d41d8 100644
--- a/erts/etc/common/safe_string.c
+++ b/erts/etc/unix/safe_string.c
@@ -1,8 +1,8 @@
/*
* %CopyrightBegin%
- *
+ *
* Copyright Ericsson AB 2008-2009. 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
@@ -14,12 +14,12 @@
* 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: safe_string.c
- *
+ *
* This is a bunch of generic string operation
* that are safe regarding buffer overflow.
*
@@ -121,3 +121,4 @@ void* memmove(void *dest, const void *src, size_t n)
return dest;
}
#endif /* HAVE_MEMMOVE */
+
diff --git a/erts/etc/common/safe_string.h b/erts/etc/unix/safe_string.h
index f9d2b2023a..5a471f10de 100644
--- a/erts/etc/common/safe_string.h
+++ b/erts/etc/unix/safe_string.h
@@ -1,8 +1,8 @@
/*
* %CopyrightBegin%
- *
+ *
* Copyright Ericsson AB 2008-2009. 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
@@ -14,12 +14,12 @@
* 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: safe_string.h
- *
+ *
* This is an interface to a bunch of generic string operation
* that are safe regarding buffer overflow.
*
@@ -63,3 +63,4 @@ char* find_str(const char* haystack, int size, const char* needle);
#ifndef HAVE_MEMMOVE
void* memmove(void *dest, const void *src, size_t n);
#endif
+
diff --git a/erts/etc/unix/to_erl.c b/erts/etc/unix/to_erl.c
index 82d3218964..0bd469727c 100644
--- a/erts/etc/unix/to_erl.c
+++ b/erts/etc/unix/to_erl.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2013. All Rights Reserved.
+ * Copyright Ericsson AB 1996-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.
@@ -17,9 +17,592 @@
*
* %CopyrightEnd%
*/
+/*
+ * Module: to_erl.c
+ *
+ * This module implements a process that opens two specified FIFOs, one
+ * for reading and one for writing; reads from its stdin, and writes what
+ * it has read to the write FIF0; reads from the read FIFO, and writes to
+ * its stdout.
+ *
+ ________ _________
+ | |--<-- pipe.r (fifo1) --<--| |
+ | to_erl | | run_erl | (parent)
+ |________|-->-- pipe.w (fifo2) -->--|_________|
+ ^ master pty
+ |
+ | slave pty
+ ____V____
+ | |
+ | "erl" | (child)
+ |_________|
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <dirent.h>
+#include <signal.h>
+#include <errno.h>
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+
+#include "run_erl.h"
+#include "safe_string.h" /* strn_cpy, strn_catf, sn_printf, etc. */
+
+#if defined(O_NONBLOCK)
+# define DONT_BLOCK_PLEASE O_NONBLOCK
+#else
+# define DONT_BLOCK_PLEASE O_NDELAY
+# if !defined(EAGAIN)
+# define EAGAIN -3898734
+# endif
+#endif
+
+#ifdef HAVE_STRERROR
+# define STRERROR(x) strerror(x)
+#else
+# define STRERROR(x) ""
+#endif
+
+#define noDEBUG
+
+#define PIPE_DIR "/tmp/"
+#define PIPE_STUBNAME "erlang.pipe"
+#define PIPE_STUBLEN strlen(PIPE_STUBNAME)
+
+#ifdef DEBUG
+#define STATUS(s) { fprintf(stderr, (s)); fflush(stderr); }
+#else
+#define STATUS(s)
+#endif
+
+#ifndef FILENAME_MAX
+#define FILENAME_MAX 250
+#endif
+
+static struct termios tty_smode, tty_rmode;
+static int tty_eof = 0;
+static int recv_sig = 0;
+static int protocol_ver = RUN_ERL_LO_VER; /* assume lowest to begin with */
+
+static int write_all(int fd, const char* buf, int len);
+static int window_size_seq(char* buf, size_t bufsz);
+static int version_handshake(char* buf, int len, int wfd);
+#ifdef DEBUG
+static void show_terminal_settings(struct termios *);
+#endif
+
+static void handle_ctrlc(int sig)
+{
+ /* Reinstall the handler, and signal break flag */
+ signal(SIGINT,handle_ctrlc);
+ recv_sig = SIGINT;
+}
+
+static void handle_sigwinch(int sig)
+{
+ recv_sig = SIGWINCH;
+}
+
+static void usage(char *pname)
+{
+ fprintf(stderr, "Usage: %s [-h|-F] [pipe_name|pipe_dir/]\n", pname);
+ fprintf(stderr, "\t-h\tThis help text.\n");
+ fprintf(stderr, "\t-F\tForce connection even though pipe is locked by other to_erl process.\n");
+}
+
+int main(int argc, char **argv)
+{
+ char FIFO1[FILENAME_MAX], FIFO2[FILENAME_MAX];
+ int i, len, wfd, rfd;
+ fd_set readfds;
+ char buf[BUFSIZ];
+ char pipename[FILENAME_MAX];
+ int pipeIx = 1;
+ int force_lock = 0;
+ int got_some = 0;
+
+ if (argc >= 2 && argv[1][0]=='-') {
+ switch (argv[1][1]) {
+ case 'h':
+ usage(argv[0]);
+ exit(1);
+ case 'F':
+ force_lock = 1;
+ break;
+ default:
+ fprintf(stderr,"Invalid option '%s'\n",argv[1]);
+ exit(1);
+ }
+ pipeIx = 2;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "%s: pid is : %d\n", argv[0], (int)getpid());
+#endif
+
+ strn_cpy(pipename, sizeof(pipename),
+ (argv[pipeIx] ? argv[pipeIx] : PIPE_DIR));
+
+ if(*pipename && pipename[strlen(pipename)-1] == '/') {
+ /* The user wishes us to find a pipe name in the specified */
+ /* directory */
+ int highest_pipe_num = 0;
+ DIR *dirp;
+ struct dirent *direntp;
+
+ dirp = opendir(pipename);
+ if(!dirp) {
+ fprintf(stderr, "Can't access pipe directory %s: %s\n", pipename, strerror(errno));
+ exit(1);
+ }
+
+ /* Check the directory for existing pipes */
+
+ while((direntp=readdir(dirp)) != NULL) {
+ if(strncmp(direntp->d_name,PIPE_STUBNAME,PIPE_STUBLEN)==0) {
+ int num = atoi(direntp->d_name+PIPE_STUBLEN+1);
+ if(num > highest_pipe_num)
+ highest_pipe_num = num;
+ }
+ }
+ closedir(dirp);
+ strn_catf(pipename, sizeof(pipename), (highest_pipe_num?"%s.%d":"%s"),
+ PIPE_STUBNAME, highest_pipe_num);
+ } /* if */
+
+ /* read FIFO */
+ sn_printf(FIFO1,sizeof(FIFO1),"%s.r",pipename);
+ /* write FIFO */
+ sn_printf(FIFO2,sizeof(FIFO2),"%s.w",pipename);
+
+ /* Check that nobody is running to_erl on this pipe already */
+ if ((wfd = open (FIFO1, O_WRONLY|DONT_BLOCK_PLEASE, 0)) >= 0) {
+ /* Open as server succeeded -- to_erl is already running! */
+ close(wfd);
+ fprintf(stderr, "Another to_erl process already attached to pipe "
+ "%s.\n", pipename);
+ if (force_lock) {
+ fprintf(stderr, "But we proceed anyway by force (-F).\n");
+ }
+ else {
+ exit(1);
+ }
+ }
+
+ if ((rfd = open (FIFO1, O_RDONLY|DONT_BLOCK_PLEASE, 0)) < 0) {
+#ifdef DEBUG
+ fprintf(stderr, "Could not open FIFO %s for reading.\n", FIFO1);
+#endif
+ fprintf(stderr, "No running Erlang on pipe %s: %s\n", pipename, strerror(errno));
+ exit(1);
+ }
+#ifdef DEBUG
+ fprintf(stderr, "to_erl: %s opened for reading\n", FIFO1);
+#endif
+
+ if ((wfd = open (FIFO2, O_WRONLY|DONT_BLOCK_PLEASE, 0)) < 0) {
+#ifdef DEBUG
+ fprintf(stderr, "Could not open FIFO %s for writing.\n", FIFO2);
+#endif
+ fprintf(stderr, "No running Erlang on pipe %s: %s\n", pipename, strerror(errno));
+ close(rfd);
+ exit(1);
+ }
+#ifdef DEBUG
+ fprintf(stderr, "to_erl: %s opened for writing\n", FIFO2);
+#endif
+
+ fprintf(stderr, "Attaching to %s (^D to exit)\n\n", pipename);
+
+ /* Set break handler to our handler */
+ signal(SIGINT,handle_ctrlc);
+
+ /*
+ * Save the current state of the terminal, and set raw mode.
+ */
+ if (tcgetattr(0, &tty_rmode) , 0) {
+ fprintf(stderr, "Cannot get terminals current mode\n");
+ exit(-1);
+ }
+ tty_smode = tty_rmode;
+ tty_eof = '\004'; /* Ctrl+D to exit */
+#ifdef DEBUG
+ show_terminal_settings(&tty_rmode);
+#endif
+ tty_smode.c_iflag =
+ 1*BRKINT |/*Signal interrupt on break.*/
+ 1*IGNPAR |/*Ignore characters with parity errors.*/
+ 1*ISTRIP |/*Strip character.*/
+ 0;
+
+#if 0
+0*IGNBRK |/*Ignore break condition.*/
+0*PARMRK |/*Mark parity errors.*/
+0*INPCK |/*Enable input parity check.*/
+0*INLCR |/*Map NL to CR on input.*/
+0*IGNCR |/*Ignore CR.*/
+0*ICRNL |/*Map CR to NL on input.*/
+0*IUCLC |/*Map upper-case to lower-case on input.*/
+0*IXON |/*Enable start/stop output control.*/
+0*IXANY |/*Enable any character to restart output.*/
+0*IXOFF |/*Enable start/stop input control.*/
+0*IMAXBEL|/*Echo BEL on input line too long.*/
+#endif
+
+ tty_smode.c_oflag =
+ 1*OPOST |/*Post-process output.*/
+ 1*ONLCR |/*Map NL to CR-NL on output.*/
+#ifdef XTABS
+ 1*XTABS |/*Expand tabs to spaces. (Linux)*/
+#endif
+#ifdef OXTABS
+ 1*OXTABS |/*Expand tabs to spaces. (FreeBSD)*/
+#endif
+#ifdef NL0
+ 1*NL0 |/*Select newline delays*/
+#endif
+#ifdef CR0
+ 1*CR0 |/*Select carriage-return delays*/
+#endif
+#ifdef TAB0
+ 1*TAB0 |/*Select horizontal tab delays*/
+#endif
+#ifdef BS0
+ 1*BS0 |/*Select backspace delays*/
+#endif
+#ifdef VT0
+ 1*VT0 |/*Select vertical tab delays*/
+#endif
+#ifdef FF0
+ 1*FF0 |/*Select form feed delays*/
+#endif
+ 0;
+
+#if 0
+0*OLCUC |/*Map lower case to upper on output.*/
+0*OCRNL |/*Map CR to NL on output.*/
+0*ONOCR |/*No CR output at column 0.*/
+0*ONLRET |/*NL performs CR function.*/
+0*OFILL |/*Use fill characters for delay.*/
+0*OFDEL |/*Fill is DEL, else NULL.*/
+0*NL1 |
+0*CR1 |
+0*CR2 |
+0*CR3 |
+0*TAB1 |
+0*TAB2 |
+0*TAB3 |/*Expand tabs to spaces.*/
+0*BS1 |
+0*VT1 |
+0*FF1 |
+#endif
+
+ /* JALI: removed setting the tty_smode.c_cflag flags, since this is not */
+ /* advisable if this is a *real* terminal, such as the console. In fact */
+ /* this may hang the entire machine, deep, deep down (signalling break */
+ /* or toggling the abort switch doesn't help) */
+
+ tty_smode.c_lflag =
+ 0;
+
+#if 0
+0*ISIG |/*Enable signals.*/
+0*ICANON |/*Canonical input (erase and kill processing).*/
+0*XCASE |/*Canonical upper/lower presentation.*/
+0*ECHO |/*Enable echo.*/
+0*ECHOE |/*Echo erase character as BS-SP-BS.*/
+0*ECHOK |/*Echo NL after kill character.*/
+0*ECHONL |/*Echo NL.*/
+0*NOFLSH |/*Disable flush after interrupt or quit.*/
+0*TOSTOP |/*Send SIGTTOU for background output.*/
+0*ECHOCTL|/*Echo control characters as ^char, delete as ^?.*/
+0*ECHOPRT|/*Echo erase character as character erased.*/
+0*ECHOKE |/*BS-SP-BS erase entire line on line kill.*/
+0*FLUSHO |/*Output is being flushed.*/
+0*PENDIN |/*Retype pending input at next read or input character.*/
+0*IEXTEN |/*Enable extended (implementation-defined) functions.*/
+#endif
+
+ tty_smode.c_cc[VMIN] =0;/* Note that VMIN is the same as VEOF! */
+ tty_smode.c_cc[VTIME] =0;/* Note that VTIME is the same as VEOL! */
+ tty_smode.c_cc[VINTR] =3;
+
+ tcsetattr(0, TCSADRAIN, &tty_smode);
+
+#ifdef DEBUG
+ show_terminal_settings(&tty_smode);
+#endif
+ /*
+ * "Write a ^L to the FIFO which causes the other end to redisplay
+ * the input line."
+ * This does not seem to work as was intended in old comment above.
+ * However, this control character is now (R12B-3) used by run_erl
+ * to trigger the version handshaking between to_erl and run_erl
+ * at the start of every new to_erl-session.
+ */
+
+ if (write(wfd, "\014", 1) < 0) {
+ fprintf(stderr, "Error in writing ^L to FIFO.\n");
+ }
+
+ /*
+ * read and write
+ */
+ while (1) {
+ FD_ZERO(&readfds);
+ FD_SET(0, &readfds);
+ FD_SET(rfd, &readfds);
+ if (select(rfd + 1, &readfds, NULL, NULL, NULL) < 0) {
+ if (recv_sig) {
+ FD_ZERO(&readfds);
+ }
+ else {
+ fprintf(stderr, "Error in select.\n");
+ break;
+ }
+ }
+ len = 0;
+
+ /*
+ * Read from terminal and write to FIFO
+ */
+ if (recv_sig) {
+ switch (recv_sig) {
+ case SIGINT:
+ fprintf(stderr, "[Break]\n\r");
+ buf[0] = '\003';
+ len = 1;
+ break;
+ case SIGWINCH:
+ len = window_size_seq(buf,sizeof(buf));
+ break;
+ default:
+ fprintf(stderr,"Unexpected signal: %u\n",recv_sig);
+ }
+ recv_sig = 0;
+ }
+ else if (FD_ISSET(0, &readfds)) {
+ len = read(0, buf, sizeof(buf));
+ if (len <= 0) {
+ close(rfd);
+ close(wfd);
+ if (len < 0) {
+ fprintf(stderr, "Error in reading from stdin.\n");
+ } else {
+ fprintf(stderr, "[EOF]\n\r");
+ }
+ break;
+ }
+ /* check if there is an eof character in input */
+ for (i = 0; i < len && buf[i] != tty_eof; i++);
+ if (buf[i] == tty_eof) {
+ fprintf(stderr, "[Quit]\n\r");
+ break;
+ }
+ }
+
+ if (len) {
+#ifdef DEBUG
+ if(write(1, buf, len));
+#endif
+ if (write_all(wfd, buf, len) != len) {
+ fprintf(stderr, "Error in writing to FIFO.\n");
+ close(rfd);
+ close(wfd);
+ break;
+ }
+ STATUS("\" OK\r\n");
+ }
+
+ /*
+ * Read from FIFO, write to terminal.
+ */
+ if (FD_ISSET(rfd, &readfds)) {
+ STATUS("FIFO read: ");
+ len = read(rfd, buf, BUFSIZ);
+ if (len < 0 && errno == EAGAIN) {
+ /*
+ * No data this time, but the writing end of the FIFO is still open.
+ * Do nothing.
+ */
+ ;
+ } else if (len <= 0) {
+ /*
+ * Either an error or end of file. In either case, break out
+ * of the loop.
+ */
+ close(rfd);
+ close(wfd);
+ if (len < 0) {
+ fprintf(stderr, "Error in reading from FIFO.\n");
+ } else
+ fprintf(stderr, "[End]\n\r");
+ break;
+ } else {
+ if (!got_some) {
+ if ((len=version_handshake(buf,len,wfd)) < 0) {
+ close(rfd);
+ close(wfd);
+ break;
+ }
+ if (protocol_ver >= 1) {
+ /* Tell run_erl size of terminal window */
+ signal(SIGWINCH, handle_sigwinch);
+ raise(SIGWINCH);
+ }
+ got_some = 1;
+ }
+
+ /*
+ * We successfully read at least one character. Write what we got.
+ */
+ STATUS("Terminal write: \"");
+ if (write_all(1, buf, len) != len) {
+ fprintf(stderr, "Error in writing to terminal.\n");
+ close(rfd);
+ close(wfd);
+ break;
+ }
+ STATUS("\" OK\r\n");
+ }
+ }
+ }
+
+ /*
+ * Reset terminal characterstics
+ * XXX
+ */
+ tcsetattr(0, TCSADRAIN, &tty_rmode);
+ return 0;
+}
+
+/* Call write() until entire buffer has been written or error.
+ * Return len or -1.
+ */
+static int write_all(int fd, const char* buf, int len)
+{
+ int left = len;
+ int written;
+ while (left) {
+ written = write(fd,buf,left);
+ if (written < 0) {
+ return -1;
+ }
+ left -= written;
+ buf += written;
+ }
+ return len;
+}
+
+static int window_size_seq(char* buf, size_t bufsz)
+{
+#ifdef TIOCGWINSZ
+ struct winsize ws;
+ static const char prefix[] = "\033_";
+ static const char suffix[] = "\033\\";
+ /* This Esc sequence is called "Application Program Command"
+ and seems suitable to use for our own customized stuff. */
+
+ if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0) {
+ int len = sn_printf(buf, bufsz, "%swinsize=%u,%u%s",
+ prefix, ws.ws_col, ws.ws_row, suffix);
+ return len;
+ }
+#endif /* TIOCGWINSZ */
+ return 0;
+}
+
+/* to_erl run_erl
+ * | |
+ * |---------- '\014' -------->| (session start)
+ * | |
+ * |<---- "[run_erl v1-0]" ----| (version interval)
+ * | |
+ * |--- Esc_"version=1"Esc\ -->| (common version)
+ * | |
+ */
+static int version_handshake(char* buf, int len, int wfd)
+{
+ unsigned re_high=0, re_low;
+ char *end = find_str(buf,len,"]\n");
+
+ if (end && sscanf(buf,"[run_erl v%u-%u",&re_high,&re_low)==2) {
+ char wbuf[30];
+ int wlen;
+
+ if (re_low > RUN_ERL_HI_VER || re_high < RUN_ERL_LO_VER) {
+ fprintf(stderr,"Incompatible versions: to_erl=v%u-%u run_erl=v%u-%u\n",
+ RUN_ERL_HI_VER, RUN_ERL_LO_VER, re_high, re_low);
+ return -1;
+ }
+ /* Choose highest common version */
+ protocol_ver = re_high < RUN_ERL_HI_VER ? re_high : RUN_ERL_HI_VER;
+
+ wlen = sn_printf(wbuf, sizeof(wbuf), "\033_version=%u\033\\",
+ protocol_ver);
+ if (write_all(wfd, wbuf, wlen) < 0) {
+ fprintf(stderr,"Failed to send version handshake\n");
+ return -1;
+ }
+ end += 2;
+ len -= (end-buf);
+ memmove(buf,end,len);
+
+ }
+ else { /* we assume old run_erl without version handshake */
+ protocol_ver = 0;
+ }
+
+ if (re_high != RUN_ERL_HI_VER) {
+ fprintf(stderr,"run_erl has different version, "
+ "using common protocol level %u\n", protocol_ver);
+ }
+
+ return len;
+}
+
-#include "to_erl_common.h"
+#ifdef DEBUG
+#define S(x) ((x) > 0 ? 1 : 0)
-int main(int argc,char **argv) {
- return to_erl(argc,argv);
+static void show_terminal_settings(struct termios *t)
+{
+ fprintf(stderr,"c_iflag:\n");
+ fprintf(stderr,"Signal interrupt on break: BRKINT %d\n", S(t->c_iflag & BRKINT));
+ fprintf(stderr,"Map CR to NL on input: ICRNL %d\n", S(t->c_iflag & ICRNL));
+ fprintf(stderr,"Ignore break condition: IGNBRK %d\n", S(t->c_iflag & IGNBRK));
+ fprintf(stderr,"Ignore CR: IGNCR %d\n", S(t->c_iflag & IGNCR));
+ fprintf(stderr,"Ignore char with par. err's: IGNPAR %d\n", S(t->c_iflag & IGNPAR));
+ fprintf(stderr,"Map NL to CR on input: INLCR %d\n", S(t->c_iflag & INLCR));
+ fprintf(stderr,"Enable input parity check: INPCK %d\n", S(t->c_iflag & INPCK));
+ fprintf(stderr,"Strip character ISTRIP %d\n", S(t->c_iflag & ISTRIP));
+ fprintf(stderr,"Enable start/stop input ctrl IXOFF %d\n", S(t->c_iflag & IXOFF));
+ fprintf(stderr,"ditto output ctrl IXON %d\n", S(t->c_iflag & IXON));
+ fprintf(stderr,"Mark parity errors PARMRK %d\n", S(t->c_iflag & PARMRK));
+ fprintf(stderr,"\n");
+ fprintf(stderr,"c_oflag:\n");
+ fprintf(stderr,"Perform output processing OPOST %d\n", S(t->c_oflag & OPOST));
+ fprintf(stderr,"\n");
+ fprintf(stderr,"c_cflag:\n");
+ fprintf(stderr,"Ignore modem status lines CLOCAL %d\n", S(t->c_cflag & CLOCAL));
+ fprintf(stderr,"\n");
+ fprintf(stderr,"c_local:\n");
+ fprintf(stderr,"Enable echo ECHO %d\n", S(t->c_lflag & ECHO));
+ fprintf(stderr,"\n");
+ fprintf(stderr,"c_cc:\n");
+ fprintf(stderr,"c_cc[VEOF] %d\n", t->c_cc[VEOF]);
}
+#endif
diff --git a/erts/include/erl_int_sizes_config.h.in b/erts/include/erl_int_sizes_config.h.in
index b18f5ebc00..88c74cdeff 100644
--- a/erts/include/erl_int_sizes_config.h.in
+++ b/erts/include/erl_int_sizes_config.h.in
@@ -35,6 +35,3 @@
/* The size of a pointer. */
#undef SIZEOF_VOID_P
-
-/* Define if building a halfword-heap 64bit emulator (needed for NIF's) */
-#undef HALFWORD_HEAP_EMULATOR
diff --git a/erts/include/internal/erl_printf_format.h b/erts/include/internal/erl_printf_format.h
index efd926be99..953022017a 100644
--- a/erts/include/internal/erl_printf_format.h
+++ b/erts/include/internal/erl_printf_format.h
@@ -44,7 +44,6 @@ typedef long long ErlPfSWord;
#error Found no appropriate type to use for 'Eterm', 'Uint' and 'Sint'
#endif
-
typedef int (*fmtfn_t)(void*, char*, size_t);
extern int erts_printf_format(fmtfn_t, void*, char*, va_list);
@@ -57,17 +56,9 @@ extern int erts_printf_uword(fmtfn_t, void*, char, int, int, ErlPfUWord);
extern int erts_printf_sword(fmtfn_t, void*, char, int, int, ErlPfSWord);
extern int erts_printf_double(fmtfn_t, void *, char, int, int, double);
-#ifdef HALFWORD_HEAP_EMULATOR
-# if SIZEOF_INT != 4
-# error Unsupported integer size for HALFWORD_HEAP_EMULATOR
-# endif
-typedef unsigned int ErlPfEterm;
-#else
typedef ErlPfUWord ErlPfEterm;
-#endif
-
-extern int (*erts_printf_eterm_func)(fmtfn_t, void*, ErlPfEterm, long, ErlPfEterm*);
+extern int (*erts_printf_eterm_func)(fmtfn_t, void*, ErlPfEterm, long);
#endif /* ERL_PRINTF_FORMAT_H__ */
diff --git a/erts/include/internal/ethr_internal.h b/erts/include/internal/ethr_internal.h
index d4ded6ff05..693b34df61 100644
--- a/erts/include/internal/ethr_internal.h
+++ b/erts/include/internal/ethr_internal.h
@@ -92,7 +92,6 @@ void ethr_run_exit_handlers__(void);
void ethr_ts_event_destructor__(void *vtsep);
#if defined(ETHR_X86_RUNTIME_CONF__)
-int ethr_x86_have_cpuid__(void);
void ethr_x86_cpuid__(int *eax, int *ebx, int *ecx, int *edx);
#endif
diff --git a/erts/include/internal/ethr_mutex.h b/erts/include/internal/ethr_mutex.h
index f76c4262ca..b402a139f5 100644
--- a/erts/include/internal/ethr_mutex.h
+++ b/erts/include/internal/ethr_mutex.h
@@ -98,7 +98,7 @@ void LeaveCriticalSection(CRITICAL_SECTION *);
#if 0
# define ETHR_MTX_Q_LOCK_SPINLOCK__
# define ETHR_MTX_QLOCK_TYPE__ ethr_spinlock_t
-#elif defined(ETHR_PTHREADS) || defined(ETHR_OSE_THREADS)
+#elif defined(ETHR_PTHREADS)
# define ETHR_MTX_Q_LOCK_PTHREAD_MUTEX__
# define ETHR_MTX_QLOCK_TYPE__ pthread_mutex_t
#elif defined(ETHR_WIN32_THREADS)
@@ -211,7 +211,7 @@ struct ethr_cond_ {
#endif
};
-#elif (defined(ETHR_PTHREADS) || defined(ETHR_OSE_THREADS)) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
+#elif defined(ETHR_PTHREADS) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
typedef struct ethr_mutex_ ethr_mutex;
struct ethr_mutex_ {
@@ -355,7 +355,7 @@ void ethr_rwmutex_rwunlock(ethr_rwmutex *);
#ifdef ETHR_MTX_HARD_DEBUG
#define ETHR_MTX_HARD_ASSERT(A) \
- ((void) ((A) ? 1 : ethr_assert_failed(__FILE__, __LINE__, __func__,#A)))
+ ((void) ((A) ? 1 : ethr_assert_failed(__FILE__, __LINE__, __func__, #A)))
#else
#define ETHR_MTX_HARD_ASSERT(A) ((void) 1)
#endif
@@ -634,7 +634,7 @@ ETHR_INLINE_MTX_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
#endif /* ETHR_TRY_INLINE_FUNCS */
-#elif (defined(ETHR_PTHREADS) || defined(ETHR_OSE_THREADS)) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
+#elif defined(ETHR_PTHREADS) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_MUTEX_IMPL__)
diff --git a/erts/include/internal/ethread.h b/erts/include/internal/ethread.h
index 8964f95652..e5c5cdfa33 100644
--- a/erts/include/internal/ethread.h
+++ b/erts/include/internal/ethread.h
@@ -194,28 +194,6 @@ typedef DWORD ethr_tsd_key;
#define ETHR_YIELD() (Sleep(0), 0)
-#elif defined(ETHR_OSE_THREADS)
-
-#include "ose.h"
-#undef NIL
-
-#if defined(ETHR_HAVE_PTHREAD_H)
-#include <pthread.h>
-#endif
-
-typedef struct {
- PROCESS id;
- unsigned int tsd_key_index;
- void *res;
-} ethr_tid;
-
-typedef OSPPDKEY ethr_tsd_key;
-
-#undef ETHR_HAVE_ETHR_SIG_FUNCS
-
-/* Out own RW mutexes are probably faster, but use OSEs mutexes */
-#define ETHR_USE_OWN_RWMTX_IMPL__
-
#else /* No supported thread lib found */
#ifdef ETHR_NO_SUPP_THR_LIB_NOT_FATAL
@@ -296,14 +274,40 @@ ETHR_PROTO_NORETURN__ ethr_fatal_error__(const char *file,
|| (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64))))
# define ETHR_X86_RUNTIME_CONF__
-# define ETHR_X86_RUNTIME_CONF_HAVE_DW_CMPXCHG__ \
- (__builtin_expect(ethr_runtime__.conf.have_dw_cmpxchg != 0, 1))
-# define ETHR_X86_RUNTIME_CONF_HAVE_NO_DW_CMPXCHG__ \
- (__builtin_expect(ethr_runtime__.conf.have_dw_cmpxchg == 0, 0))
-# define ETHR_X86_RUNTIME_CONF_HAVE_SSE2__ \
- (__builtin_expect(ethr_runtime__.conf.have_sse2 != 0, 1))
-# define ETHR_X86_RUNTIME_CONF_HAVE_NO_SSE2__ \
- (__builtin_expect(ethr_runtime__.conf.have_sse2 == 0, 0))
+# define ETHR_X86_RUNTIME_CONF_HAVE_META(feature) \
+ (__builtin_expect(ethr_runtime__.conf.have_##feature != 0, 1))
+# define ETHR_X86_RUNTIME_CONF_HAVE_NO_META(feature) \
+ (__builtin_expect(ethr_runtime__.conf.have_##feature == 0, 0))
+
+# define ETHR_X86_RUNTIME_CONF_HAVE_DW_CMPXCHG__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_META(dw_cmpxchg)
+# define ETHR_X86_RUNTIME_CONF_HAVE_NO_DW_CMPXCHG__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_NO_META(dw_cmpxchg)
+# define ETHR_X86_RUNTIME_CONF_HAVE_SSE2__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_META(sse2)
+# define ETHR_X86_RUNTIME_CONF_HAVE_NO_SSE2__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_NO_META(sse2)
+# define ETHR_X86_RUNTIME_CONF_HAVE_RDTSCP__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_META(rdtscp)
+# define ETHR_X86_RUNTIME_CONF_HAVE_NO_RDTSCP__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_NO_META(rdtscp)
+# define ETHR_X86_RUNTIME_CONF_HAVE_CONSTANT_TSC__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_META(constant_tsc)
+# define ETHR_X86_RUNTIME_CONF_HAVE_NO_CONSTANT_TSC__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_NO_META(nonstop_tsc)
+# define ETHR_X86_RUNTIME_CONF_HAVE_NONSTOP_TSC__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_META(nonstop_tsc)
+# define ETHR_X86_RUNTIME_CONF_HAVE_NO_NONSTOP_TSC__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_NO_META(nonstop_tsc)
+# define ETHR_X86_RUNTIME_CONF_HAVE_TSC_RELIABLE__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_META(tsc_reliable)
+# define ETHR_X86_RUNTIME_CONF_HAVE_NO_TSC_RELIABLE_TSC__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_NO_META(tsc_reliable)
+# define ETHR_X86_RUNTIME_CONF_HAVE_NONSTOP_TSC_S3__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_META(nonstop_tsc_s3)
+# define ETHR_X86_RUNTIME_CONF_HAVE_NO_NONSTOP_TSC_S3__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_NO_META(nonstop_tsc_s3)
+
#endif
#if (defined(__GNUC__) \
@@ -322,6 +326,11 @@ typedef struct {
#if defined(ETHR_X86_RUNTIME_CONF__)
int have_dw_cmpxchg;
int have_sse2;
+ int have_rdtscp;
+ int have_constant_tsc;
+ int have_tsc_reliable;
+ int have_nonstop_tsc;
+ int have_nonstop_tsc_s3;
#endif
#if defined(ETHR_PPC_RUNTIME_CONF__)
int have_lwsync;
@@ -383,19 +392,7 @@ extern ethr_runtime_t ethr_runtime__;
#include "ethr_atomics.h" /* The atomics API */
-#if defined (ETHR_OSE_THREADS)
-static ETHR_INLINE void
-ose_yield(void)
-{
- if (get_ptype(current_process()) == OS_PRI_PROC) {
- set_pri(get_pri(current_process()));
- } else {
- delay(1);
- }
-}
-#endif
-
-#if defined(__GNUC__) && !defined(ETHR_OSE_THREADS)
+#if defined(__GNUC__)
# ifndef ETHR_SPIN_BODY
# if defined(__i386__) || defined(__x86_64__)
# define ETHR_SPIN_BODY __asm__ __volatile__("rep;nop" : : : "memory")
@@ -411,20 +408,9 @@ ose_yield(void)
# ifndef ETHR_SPIN_BODY
# define ETHR_SPIN_BODY do {YieldProcessor();ETHR_COMPILER_BARRIER;} while(0)
# endif
-#elif defined(ETHR_OSE_THREADS)
-# ifndef ETHR_SPIN_BODY
-# define ETHR_SPIN_BODY ose_yield()
-# else
-# error "OSE should use ose_yield()"
-# endif
#endif
-#ifndef ETHR_OSE_THREADS
#define ETHR_YIELD_AFTER_BUSY_LOOPS 50
-#else
-#define ETHR_YIELD_AFTER_BUSY_LOOPS 0
-#endif
-
#ifndef ETHR_SPIN_BODY
# define ETHR_SPIN_BODY ETHR_COMPILER_BARRIER
@@ -447,18 +433,13 @@ ose_yield(void)
# else
# define ETHR_YIELD() (pthread_yield(), 0)
# endif
-# elif defined(ETHR_OSE_THREADS)
-# define ETHR_YIELD() (ose_yield(), 0)
# else
# define ETHR_YIELD() (ethr_compiler_barrier(), 0)
# endif
#endif
-#if defined(VALGRIND) || defined(ETHR_OSE_THREADS)
-/* mutex as fallback for spinlock for VALGRIND and OSE.
- OSE cannot use spinlocks as processes working on the
- same execution unit have a tendency to deadlock.
- */
+#if defined(VALGRIND)
+/* mutex as fallback for spinlock for VALGRIND. */
# undef ETHR_HAVE_NATIVE_SPINLOCKS
# undef ETHR_HAVE_NATIVE_RWSPINLOCKS
#else
@@ -505,16 +486,9 @@ typedef struct {
int detached; /* boolean (default false) */
int suggested_stack_size; /* kilo words (default sys dependent) */
char *name; /* max 14 char long (default no-name) */
-#ifdef ETHR_OSE_THREADS
- U32 coreNo;
-#endif
} ethr_thr_opts;
-#if defined(ETHR_OSE_THREADS)
-#define ETHR_THR_OPTS_DEFAULT_INITER {0, -1, NULL, 0}
-#else
#define ETHR_THR_OPTS_DEFAULT_INITER {0, -1, NULL}
-#endif
#if !defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_AUX_IMPL__)
# define ETHR_NEED_SPINLOCK_PROTOTYPES__
@@ -628,8 +602,6 @@ typedef struct ethr_ts_event_ ethr_ts_event; /* Needed by ethr_mutex.h */
# include "win/ethr_event.h"
#elif defined(ETHR_PTHREADS)
# include "pthread/ethr_event.h"
-#elif defined(ETHR_OSE_THREADS)
-# include "ose/ethr_event.h"
#endif
int ethr_set_main_thr_status(int, int);
@@ -719,37 +691,6 @@ ETHR_INLINE_FUNC_NAME_(ethr_leave_ts_event)(ethr_ts_event *tsep)
#endif
-#elif defined (ETHR_OSE_THREADS)
-
-#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHREAD_IMPL__)
-
-extern ethr_tsd_key ethr_ts_event_key__;
-
-static ETHR_INLINE ethr_ts_event *
-ETHR_INLINE_FUNC_NAME_(ethr_get_ts_event)(void)
-{
- ethr_ts_event *tsep = *(ethr_ts_event**)ose_get_ppdata(ethr_ts_event_key__);
- if (!tsep) {
- int res = ethr_get_tmp_ts_event__(&tsep);
- if (res != 0)
- ETHR_FATAL_ERROR__(res);
- ETHR_ASSERT(tsep);
- }
- return tsep;
-}
-
-static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_leave_ts_event)(ethr_ts_event *tsep)
-{
- if (tsep->iflgs & ETHR_TS_EV_TMP) {
- int res = ethr_free_ts_event__(tsep);
- if (res != 0)
- ETHR_FATAL_ERROR__(res);
- }
-}
-
-#endif
-
#endif
#include "ethr_mutex.h" /* Need atomic declarations and tse */
diff --git a/erts/include/internal/ose/ethr_event.h b/erts/include/internal/ose/ethr_event.h
deleted file mode 100644
index c18f30aa4a..0000000000
--- a/erts/include/internal/ose/ethr_event.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2009-2011. 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%
- */
-
-/*
- * Author: Rickard Green
- */
-
-//#define USE_PTHREAD_API
-
-#define ETHR_EVENT_OFF_WAITER__ -1L
-#define ETHR_EVENT_OFF__ 1L
-#define ETHR_EVENT_ON__ 0L
-
-#ifdef USE_PTHREAD_API
-
-typedef struct {
- ethr_atomic32_t state;
- pthread_mutex_t mtx;
- pthread_cond_t cnd;
-} ethr_event;
-
-#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_EVENT_IMPL__)
-
-static void ETHR_INLINE
-ETHR_INLINE_FUNC_NAME_(ethr_event_set)(ethr_event *e)
-{
- ethr_sint32_t val;
- val = ethr_atomic32_xchg_mb(&e->state, ETHR_EVENT_ON__);
- if (val == ETHR_EVENT_OFF_WAITER__) {
- int res = pthread_mutex_lock(&e->mtx);
- if (res != 0)
- ETHR_FATAL_ERROR__(res);
- res = pthread_cond_signal(&e->cnd);
- if (res != 0)
- ETHR_FATAL_ERROR__(res);
- res = pthread_mutex_unlock(&e->mtx);
- if (res != 0)
- ETHR_FATAL_ERROR__(res);
- }
-}
-
-static void ETHR_INLINE
-ETHR_INLINE_FUNC_NAME_(ethr_event_reset)(ethr_event *e)
-{
- ethr_atomic32_set(&e->state, ETHR_EVENT_OFF__);
- ETHR_MEMORY_BARRIER;
-}
-
-#endif
-
-#else
-
-typedef struct {
- ethr_atomic32_t state;
- PROCESS proc;
-} ethr_event;
-
-#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_EVENT_IMPL__)
-
-static void ETHR_INLINE
-ETHR_INLINE_FUNC_NAME_(ethr_event_set)(ethr_event *e)
-{
- ethr_sint32_t val = ethr_atomic32_xchg_mb(&e->state, ETHR_EVENT_ON__);
- if (val == ETHR_EVENT_OFF_WAITER__) {
-#ifdef DEBUG
- OSFSEMVAL fsem_val = get_fsem(e->proc);
-
- /* There is a race in this assert.
- This is because the state is set before the wait call in wait__.
- We hope that a delay of 10 ms is enough */
- if (fsem_val == 0)
- delay(10);
- ETHR_ASSERT(get_fsem(e->proc) == -1);
-#endif
- signal_fsem(e->proc);
- }
-}
-
-static void ETHR_INLINE
-ETHR_INLINE_FUNC_NAME_(ethr_event_reset)(ethr_event *e)
-{
- ethr_atomic32_set(&e->state, ETHR_EVENT_OFF__);
- ETHR_MEMORY_BARRIER;
-}
-
-#endif
-
-#endif
-
-int ethr_event_init(ethr_event *e);
-int ethr_event_destroy(ethr_event *e);
-int ethr_event_wait(ethr_event *e);
-int ethr_event_swait(ethr_event *e, int spincount);
-#if !defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_EVENT_IMPL__)
-void ethr_event_set(ethr_event *e);
-void ethr_event_reset(ethr_event *e);
-#endif
diff --git a/erts/lib_src/common/erl_misc_utils.c b/erts/lib_src/common/erl_misc_utils.c
index 1262c50718..053217304b 100644
--- a/erts/lib_src/common/erl_misc_utils.c
+++ b/erts/lib_src/common/erl_misc_utils.c
@@ -160,8 +160,6 @@ erts_milli_sleep(long ms)
if (ms > 0) {
#ifdef __WIN32__
Sleep((DWORD) ms);
-#elif defined(__OSE__)
- delay(ms);
#else
struct timeval tv;
tv.tv_sec = ms / 1000;
@@ -320,10 +318,6 @@ erts_cpu_info_update(erts_cpu_info_t *cpuinfo)
online = 0;
#endif
}
-#elif defined(__OSE__)
- online = ose_num_cpus();
- configured = ose_num_cpus();
- available = ose_num_cpus();
#endif
if (online > configured)
diff --git a/erts/lib_src/common/erl_printf_format.c b/erts/lib_src/common/erl_printf_format.c
index 307680505c..e7d5d4413e 100644
--- a/erts/lib_src/common/erl_printf_format.c
+++ b/erts/lib_src/common/erl_printf_format.c
@@ -78,15 +78,7 @@
#endif
#ifndef ERTS_SIZEOF_ETERM
-# ifdef HALFWORD_HEAP_EMULATOR
-# if SIZEOF_VOID_P == 8
-# define ERTS_SIZEOF_ETERM 4
-# else
-# error "HALFWORD_HEAP_EMULATOR only allowed on 64-bit architecture"
-# endif
-# else
-# define ERTS_SIZEOF_ETERM SIZEOF_VOID_P
-# endif
+#define ERTS_SIZEOF_ETERM SIZEOF_VOID_P
#endif
#if defined(__GNUC__)
@@ -102,7 +94,7 @@
#endif
#define FMTC_d 0x0000
-#define FMTC_R 0x0001
+/*empty 0x0001 was RELATIVE */
#define FMTC_o 0x0002
#define FMTC_u 0x0003
#define FMTC_x 0x0004
@@ -166,7 +158,7 @@ static char heX[] = "0123456789ABCDEF";
#define SIGN(X) ((X) > 0 ? 1 : ((X) < 0 ? -1 : 0))
#define USIGN(X) ((X) == 0 ? 0 : 1)
-int (*erts_printf_eterm_func)(fmtfn_t, void*, ErlPfEterm, long, ErlPfEterm*) = NULL;
+int (*erts_printf_eterm_func)(fmtfn_t, void*, ErlPfEterm, long) = NULL;
static int
noop_fn(void *vfp, char* buf, size_t len)
@@ -645,7 +637,6 @@ int erts_printf_format(fmtfn_t fn, void* arg, char* fmt, va_list ap)
case 'p': ptr++; fmt |= FMTC_p; break;
case 'n': ptr++; fmt |= FMTC_n; break;
case 'T': ptr++; fmt |= FMTC_T; break;
- case 'R': ptr++; fmt |= FMTC_R; break;
case '%':
FMT(fn,arg,ptr,1,count);
ptr++;
@@ -820,11 +811,9 @@ int erts_printf_format(fmtfn_t fn, void* arg, char* fmt, va_list ap)
default: *va_arg(ap,int*) = count; break;
}
break;
- case FMTC_T: /* Eterm */
- case FMTC_R: { /* Eterm, Eterm* base (base ignored if !HALFWORD_HEAP) */
+ case FMTC_T: { /* Eterm */
long prec;
ErlPfEterm eterm;
- ErlPfEterm* eterm_base;
if (!erts_printf_eterm_func)
return -EINVAL;
@@ -835,16 +824,14 @@ int erts_printf_format(fmtfn_t fn, void* arg, char* fmt, va_list ap)
else
prec = (long) precision;
eterm = va_arg(ap, ErlPfEterm);
- eterm_base = ((fmt & FMTC_MASK) == FMTC_R) ?
- va_arg(ap, ErlPfEterm*) : NULL;
if (width > 0 && !(fmt & FMTF_adj)) {
- res = (*erts_printf_eterm_func)(noop_fn, NULL, eterm, prec, eterm_base);
+ res = (*erts_printf_eterm_func)(noop_fn, NULL, eterm, prec);
if (res < 0)
return res;
if (width > res)
BLANKS(fn, arg, width - res, count);
}
- res = (*erts_printf_eterm_func)(fn, arg, eterm, prec, eterm_base);
+ res = (*erts_printf_eterm_func)(fn, arg, eterm, prec);
if (res < 0)
return res;
count += res;
diff --git a/erts/lib_src/common/ethr_aux.c b/erts/lib_src/common/ethr_aux.c
index 0cbb1b2fb8..3e7aad16c7 100644
--- a/erts/lib_src/common/ethr_aux.c
+++ b/erts/lib_src/common/ethr_aux.c
@@ -139,6 +139,38 @@ x86_init(void)
#endif
/* bit 26 of edx is set if we have sse2 */
ethr_runtime__.conf.have_sse2 = (edx & (1 << 26));
+
+ /* check if we have extended feature set */
+ eax = 0x80000000;
+ ethr_x86_cpuid__(&eax, &ebx, &ecx, &edx);
+
+ if (eax < 0x80000001)
+ return;
+
+ if (eax >= 0x80000007) {
+ /* Advanced Power Management Information */
+ eax = 0x80000007;
+ ethr_x86_cpuid__(&eax, &ebx, &ecx, &edx);
+
+ /* I got the values below from:
+ http://lxr.free-electrons.com/source/arch/x86/include/asm/cpufeature.h
+ They can be gotten from the intel/amd manual as well.
+ */
+
+ ethr_runtime__.conf.have_constant_tsc = (edx & (1 << 8));
+ ethr_runtime__.conf.have_tsc_reliable = (edx & (1 << 23));
+ ethr_runtime__.conf.have_nonstop_tsc = (edx & (1 << 24));
+ ethr_runtime__.conf.have_nonstop_tsc_s3 = (edx & (1 << 30));
+
+ }
+
+ /* Extended Processor Info and Feature Bits */
+ eax = 0x80000001;
+ ethr_x86_cpuid__(&eax, &ebx, &ecx, &edx);
+
+ /* bit 27 of edx is set if we have rdtscp */
+ ethr_runtime__.conf.have_rdtscp = (edx & (1 << 27));
+
}
#endif /* ETHR_X86_RUNTIME_CONF__ */
@@ -207,18 +239,7 @@ ethr_init_common__(ethr_init_data *id)
ethr_min_stack_size__ = ETHR_B2KW(ethr_min_stack_size__);
-#ifdef __OSE__
- /* For supervisor processes, OSE adds a number of bytes to the requested stack. With this
- * addition, the resulting size must not exceed the largest available stack size. The number
- * of bytes that will be added is configured in the monolith and can therefore not be
- * specified here. We simply assume that it is less than 0x1000. The available stack sizes
- * are configured in the .lmconf file and the largest one is usually 65536 bytes.
- * Consequently, the requested stack size is limited to 0xF000.
- */
- ethr_max_stack_size__ = 0xF000;
-#else
ethr_max_stack_size__ = 32*1024*1024;
-#endif
#if SIZEOF_VOID_P == 8
ethr_max_stack_size__ *= 2;
#endif
@@ -664,10 +685,6 @@ ETHR_IMPL_NORETURN__ ethr_fatal_error__(const char *file,
int ethr_assert_failed(const char *file, int line, const char *func, char *a)
{
fprintf(stderr, "%s:%d: %s(): Assertion failed: %s\n", file, line, func, a);
-#ifdef __OSE__
- ramlog_printf("%d: %s:%d: %s(): Assertion failed: %s\n",
- current_process(),file, line, func, a);
-#endif
ethr_abort__();
return 0;
}
diff --git a/erts/lib_src/common/ethr_mutex.c b/erts/lib_src/common/ethr_mutex.c
index 72aa34ec1c..a596e6c31c 100644
--- a/erts/lib_src/common/ethr_mutex.c
+++ b/erts/lib_src/common/ethr_mutex.c
@@ -1250,7 +1250,7 @@ ethr_cond_wait(ethr_cond *cnd, ethr_mutex *mtx)
return 0;
}
-#elif (defined(ETHR_PTHREADS) || defined(ETHR_OSE_THREADS)) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
+#elif defined(ETHR_PTHREADS) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
/* -- pthread mutex and condition variables -------------------------------- */
int
diff --git a/erts/lib_src/ose/ethr_event.c b/erts/lib_src/ose/ethr_event.c
deleted file mode 100644
index 24ea191c4b..0000000000
--- a/erts/lib_src/ose/ethr_event.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2009-2010. 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%
- */
-
-/*
- * Author: Rickard Green
- */
-
-#define ETHR_INLINE_FUNC_NAME_(X) X ## __
-#define ETHR_EVENT_IMPL__
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "ethread.h"
-
-#ifdef USE_PTHREAD_API
-
-int
-ethr_event_init(ethr_event *e)
-{
- int res;
- ethr_atomic32_init(&e->state, ETHR_EVENT_OFF__);
- res = pthread_mutex_init(&e->mtx, NULL);
- if (res != 0)
- return res;
- res = pthread_cond_init(&e->cnd, NULL);
- if (res != 0) {
- pthread_mutex_destroy(&e->mtx);
- return res;
- }
- return 0;
-}
-
-int
-ethr_event_destroy(ethr_event *e)
-{
- int res;
- res = pthread_mutex_destroy(&e->mtx);
- if (res != 0)
- return res;
- res = pthread_cond_destroy(&e->cnd);
- if (res != 0)
- return res;
- return 0;
-}
-
-static ETHR_INLINE int
-wait__(ethr_event *e, int spincount)
-{
- int sc = spincount;
- ethr_sint32_t val;
- int res, ulres;
- int until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS;
-
- if (spincount < 0)
- ETHR_FATAL_ERROR__(EINVAL);
-
- while (1) {
- val = ethr_atomic32_read(&e->state);
- if (val == ETHR_EVENT_ON__)
- return 0;
- if (sc == 0)
- break;
- sc--;
- ETHR_SPIN_BODY;
- if (--until_yield == 0) {
- until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS;
- res = ETHR_YIELD();
- if (res != 0)
- ETHR_FATAL_ERROR__(res);
- }
- }
-
- if (val != ETHR_EVENT_OFF_WAITER__) {
- val = ethr_atomic32_cmpxchg(&e->state,
- ETHR_EVENT_OFF_WAITER__,
- ETHR_EVENT_OFF__);
- if (val == ETHR_EVENT_ON__)
- return 0;
- ETHR_ASSERT(val == ETHR_EVENT_OFF__);
- }
-
- ETHR_ASSERT(val == ETHR_EVENT_OFF_WAITER__
- || val == ETHR_EVENT_OFF__);
-
- res = pthread_mutex_lock(&e->mtx);
- if (res != 0)
- ETHR_FATAL_ERROR__(res);
-
- while (1) {
-
- val = ethr_atomic32_read(&e->state);
- if (val == ETHR_EVENT_ON__)
- break;
-
- res = pthread_cond_wait(&e->cnd, &e->mtx);
- if (res == EINTR)
- break;
- if (res != 0)
- ETHR_FATAL_ERROR__(res);
- }
-
- ulres = pthread_mutex_unlock(&e->mtx);
- if (ulres != 0)
- ETHR_FATAL_ERROR__(ulres);
-
- return res; /* 0 || EINTR */
-}
-
-#else
-/* --- OSE implementation of events ---------------------------- */
-
-#ifdef DEBUG
-union SIGNAL {
- SIGSELECT signo;
-};
-#endif
-
-int
-ethr_event_init(ethr_event *e)
-{
- ethr_atomic32_init(&e->state, ETHR_EVENT_OFF__);
- e->proc = current_process();
- return 0;
-}
-
-int
-ethr_event_destroy(ethr_event *e)
-{
- return 0;
-}
-
-static ETHR_INLINE int
-wait__(ethr_event *e, int spincount)
-{
- int sc = spincount;
- int res;
- int until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS;
-
- if (spincount < 0)
- ETHR_FATAL_ERROR__(EINVAL);
-
- ETHR_ASSERT(e->proc == current_process());
- ETHR_ASSERT(get_fsem(current_process()) == 0);
-
- while (1) {
- ethr_sint32_t val;
- while (1) {
- val = ethr_atomic32_read(&e->state);
- if (val == ETHR_EVENT_ON__)
- return 0;
- if (sc == 0)
- break;
- sc--;
- ETHR_SPIN_BODY;
- if (--until_yield == 0) {
- until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS;
- res = ETHR_YIELD();
- if (res != 0)
- ETHR_FATAL_ERROR__(res);
- }
- }
- if (val != ETHR_EVENT_OFF_WAITER__) {
- val = ethr_atomic32_cmpxchg(&e->state,
- ETHR_EVENT_OFF_WAITER__,
- ETHR_EVENT_OFF__);
- if (val == ETHR_EVENT_ON__)
- return 0;
- ETHR_ASSERT(val == ETHR_EVENT_OFF__);
- }
-
- wait_fsem(1);
-
- ETHR_ASSERT(get_fsem(current_process()) == 0);
- }
-}
-
-#endif
-
-void
-ethr_event_reset(ethr_event *e)
-{
- ethr_event_reset__(e);
-}
-
-void
-ethr_event_set(ethr_event *e)
-{
- ethr_event_set__(e);
-}
-
-int
-ethr_event_wait(ethr_event *e)
-{
- return wait__(e, 0);
-}
-
-int
-ethr_event_swait(ethr_event *e, int spincount)
-{
- return wait__(e, spincount);
-}
diff --git a/erts/lib_src/ose/ethread.c b/erts/lib_src/ose/ethread.c
deleted file mode 100644
index dc16acdd08..0000000000
--- a/erts/lib_src/ose/ethread.c
+++ /dev/null
@@ -1,833 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2010-2011. 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%
- */
-
-/*
- * Description: OSE implementation of the ethread library
- * Author: Lukas Larsson
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdio.h"
-#ifdef ETHR_TIME_WITH_SYS_TIME
-# include "time.h"
-# include "sys/time.h"
-#else
-# ifdef ETHR_HAVE_SYS_TIME_H
-# include "sys/time.h"
-# else
-# include "time.h"
-# endif
-#endif
-#include "sys/types.h"
-#include "unistd.h"
-
-#include "limits.h"
-
-#define ETHR_INLINE_FUNC_NAME_(X) X ## __
-#define ETHREAD_IMPL__
-
-#include "ethread.h"
-#include "ethr_internal.h"
-
-#include "erl_printf.h"
-#include "efs.h"
-#include "ose.h"
-
-#include "ose_spi.h"
-
-#include "string.h"
-#include "ctype.h"
-#include "stdlib.h"
-
-#ifndef ETHR_HAVE_ETHREAD_DEFINES
-#error Missing configure defines
-#endif
-
-#define ETHR_INVALID_TID_ID -1
-
-#define DEFAULT_PRIO_NAME "ERTS_ETHR_DEFAULT_PRIO"
-
-/* Set the define to 1 to get some logging */
-#if 0
-#include "ramlog.h"
-#define LOG(output) ramlog_printf output
-#else
-#define LOG(output)
-#endif
-
-static ethr_tid main_thr_tid;
-static const char* own_tid_key = "ethread_own_tid";
-ethr_tsd_key ethr_ts_event_key__;
-
-#define ETHREADWRAPDATASIG 1
-
-/* Init data sent to thr_wrapper() */
-typedef struct {
- SIGSELECT sig_no;
- ethr_ts_event *tse;
- ethr_tid *tid;
- ethr_sint32_t result;
- void *(*thr_func)(void *);
- void *arg;
- void *prep_func_res;
- const char *name;
-} ethr_thr_wrap_data__;
-
-union SIGNAL {
- SIGSELECT sig_no;
- ethr_thr_wrap_data__ data;
-};
-
-#define ETHR_GET_OWN_TID__ ((ethr_tid *) get_envp(current_process(),\
- own_tid_key))
-
-/*
- * --------------------------------------------------------------------------
- * Static functions
- * --------------------------------------------------------------------------
- */
-
-/* Will retrive the instrinsic name by removing the 'prefix' and the
- * suffix from 'name'.
- * The 'prefix' is given as an inparameter. If NULL or an empty string no
- * prefix will be removed.
- * If 'strip_suffix' is 1 suffixes in the form of '_123' will be removed.
- * Will return a pointer to a newly allocated buffer containing the intrinsic
- * name in uppercase characters.
- * The caller must remember to free this buffer when no lnger needed.
- */
-static char *
-ethr_intrinsic_name(const char *name, const char *prefix, int strip_suffix)
-{
- const char *start = name;
- const char *end = name + strlen(name);
- char *intrinsic_name = NULL;
- int i;
-
- if (name == NULL) {
- LOG(("ERTS - ethr_intrinsic_namNo input name.\n"));
- return NULL;
- }
-
- /* take care of the prefix */
- if ((prefix != NULL) && (*prefix != '\0')) {
- const char *found = strstr(name, prefix);
-
- if (found == name) {
- /* found the prefix at the beginning */
- start += strlen(prefix);
- }
- }
-
- /* take care of the suffix */
- if (strip_suffix) {
- const char *suffix_start = strrchr(start, '_');
-
- if (suffix_start != NULL) {
- const char *ch;
- int only_numbers = 1;
-
- for (ch = suffix_start + 1; *ch != '\0'; ch++) {
- if (strchr("0123456789", *ch) == NULL) {
- only_numbers = 0;
- break;
- }
- }
-
- if (only_numbers) {
- end = suffix_start;
- }
- }
- }
-
- intrinsic_name = malloc(end - start + 1);
- for (i = 0; (start + i) < end; i++) {
- intrinsic_name[i] = toupper(start[i]);
- }
- intrinsic_name[i] = '\0';
-
- return intrinsic_name;
-}
-
-static char *
-ethr_get_amended_env(const char *name, const char *prefix, const char *suffix)
-{
- unsigned len;
- char *env_name = NULL;
- char *env_value = NULL;
-
- if (name == NULL) {
- return NULL;
- }
-
- len = strlen(name);
-
- if (prefix != NULL) {
- len += strlen(prefix);
- }
-
- if (suffix != NULL) {
- len += strlen(suffix);
- }
-
- env_name = malloc(len + 1);
- sprintf(env_name, "%s%s%s", (prefix != NULL) ? prefix : "",
- name,
- (suffix != NULL) ? suffix : "");
- env_value = get_env(get_bid(current_process()), env_name);
-
- if (env_value == NULL) {
- LOG(("ERTS - ethr_get_amended_env(): %s environment variable not present\n", env_name));
- } else {
- LOG(("ERTS - ethr_get_amended_env(): Found %s environment variable: %s.\n", env_name, env_value));
- }
- free(env_name);
-
- return env_value;
-}
-
-/* Reads the environment variable derived from 'name' and interprets it as as an
- * OSE priority. If successfull it will update 'out_prio'.
- * Returns: 0 if successfull
- * -1 orherwise.
- */
-static int
-ethr_get_prio(const char *name, OSPRIORITY *out_prio)
-{
- int rc = -1;
- char *intrinsic_name = NULL;
- char *prio_env = NULL;
- long prio;
- char *endptr = NULL;
-
- LOG(("ERTS - ethr_get_prio(): name: %s.\n", name));
-
- intrinsic_name = ethr_intrinsic_name(name, NULL, 1);
- LOG(("ERTS - ethr_get_prio(): Intrinsic name: %s.\n", intrinsic_name));
-
- prio_env = ethr_get_amended_env(intrinsic_name, "ERTS_", "_PRIO");
- if (prio_env == NULL) {
- goto fini;
- }
-
- prio = efs_str_to_long(prio_env, (const char **)&endptr);
- if (endptr != NULL) {
- LOG(("ERTS - ethr_get_prio(): Environment varible for '%s' includes "
- "non-numerical characters: '%s'.\n", intrinsic_name, prio_env));
- goto fini;
- }
-
- if ((prio < 0) || (prio > 32)) {
- LOG(("ERTS - ethr_get_prio(): prio for '%s' (%d) is out of bounds (0-32).\n",
- intrinsic_name, prio));
- goto fini;
- }
-
- /* Success */
- *out_prio = (OSPRIORITY)prio;
- rc = 0;
-
-fini:
- if (intrinsic_name != NULL) {
- free(intrinsic_name);
- }
- if (prio_env != NULL) {
- free_buf((union SIGNAL **) &prio_env);
- }
-
- return rc;
-}
-
-static PROCESS blockId(void) {
- static PROCESS bid = (PROCESS)0;
-
- /* For now we only use the same block. */
- /* if (bid == 0) {
- bid = create_block("Erlang-VM", 0, 0, 0, 0);
- }
- return bid; */
- return 0;
-}
-
-static void thr_exit_cleanup(ethr_tid *tid, void *res)
-{
-
- ETHR_ASSERT(tid == ETHR_GET_OWN_TID__);
-
- tid->res = res;
-
- ethr_run_exit_handlers__();
- ethr_ts_event_destructor__((void *) ethr_get_tse__());
-}
-
-//static OS_PROCESS(thr_wrapper);
-static OS_PROCESS(thr_wrapper)
-{
- ethr_tid my_tid;
- ethr_sint32_t result;
- void *res;
- void *(*thr_func)(void *);
- void *arg;
- ethr_ts_event *tsep = NULL;
-
-#ifdef DEBUG
- {
- PROCESS pid = current_process();
-
- const char *execMode;
-
- PROCESS bid = get_bid(pid);
-
- /* In the call below, 16 is a secret number provided by frbr that makes
- * the function return current domain. */
- OSADDRESS domain = get_pid_info(current_process(), 16);
-
-#ifdef HAVE_OSE_SPI_H
- execMode = get_pid_info(pid, OSE_PI_SUPERVISOR)
- ? "Supervisor"
- : "User";
-#else
- execMode = "unknown";
-#endif
-
- fprintf(stderr,"[0x%x] New process. Bid:0x%x, domain:%d, exec mode:%s\n",
- current_process(), bid, domain, execMode);
- }
-#endif
-
- {
- SIGSELECT sigsel[] = {1,ETHREADWRAPDATASIG};
- union SIGNAL *init_msg = receive(sigsel);
-
- thr_func = init_msg->data.thr_func;
- arg = init_msg->data.arg;
-
- result = (ethr_sint32_t) ethr_make_ts_event__(&tsep);
-
- if (result == 0) {
- tsep->iflgs |= ETHR_TS_EV_ETHREAD;
- my_tid = *init_msg->data.tid;
- set_envp(current_process(), own_tid_key, (OSADDRESS)&my_tid);
- if (ethr_thr_child_func__)
- ethr_thr_child_func__(init_msg->data.prep_func_res);
- }
-
- init_msg->data.result = result;
-
- send(&init_msg,sender(&init_msg));
- }
-
- /* pthread mutex api says we have to do this */
- signal_fsem(current_process());
- ETHR_ASSERT(get_fsem(current_process()) == 0);
-
- res = result == 0 ? (*thr_func)(arg) : NULL;
-
- ethr_thr_exit(&res);
-}
-
-/* internal exports */
-
-int ethr_set_tse__(ethr_ts_event *tsep)
-{
- return ethr_tsd_set(ethr_ts_event_key__,(void *) tsep);
-}
-
-ethr_ts_event *ethr_get_tse__(void)
-{
- return (ethr_ts_event *) ethr_tsd_get(ethr_ts_event_key__);
-}
-
-#if defined(ETHR_PPC_RUNTIME_CONF__)
-
-static int
-ppc_init__(void)
-{
- int pid;
-
-
- ethr_runtime__.conf.have_lwsync = 0;
-
- return 0;
-}
-
-#endif
-
-#if defined(ETHR_X86_RUNTIME_CONF__)
-
-void
-ethr_x86_cpuid__(int *eax, int *ebx, int *ecx, int *edx)
-{
-#if ETHR_SIZEOF_PTR == 4
- int have_cpuid;
- /*
- * If it is possible to toggle eflags bit 21,
- * we have the cpuid instruction.
- */
- __asm__ ("pushf\n\t"
- "popl %%eax\n\t"
- "movl %%eax, %%ecx\n\t"
- "xorl $0x200000, %%eax\n\t"
- "pushl %%eax\n\t"
- "popf\n\t"
- "pushf\n\t"
- "popl %%eax\n\t"
- "movl $0x0, %0\n\t"
- "xorl %%ecx, %%eax\n\t"
- "jz no_cpuid\n\t"
- "movl $0x1, %0\n\t"
- "no_cpuid:\n\t"
- : "=r"(have_cpuid)
- :
- : "%eax", "%ecx", "cc");
- if (!have_cpuid) {
- *eax = *ebx = *ecx = *edx = 0;
- return;
- }
-#endif
-#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
- /*
- * When position independet code is used in 32-bit mode, the B register
- * is used for storage of global offset table address, and we may not
- * use it as input or output in an asm. We need to save and restore the
- * B register explicitly (for some reason gcc doesn't provide this
- * service to us).
- */
- __asm__ ("pushl %%ebx\n\t"
- "cpuid\n\t"
- "movl %%ebx, %1\n\t"
- "popl %%ebx\n\t"
- : "=a"(*eax), "=r"(*ebx), "=c"(*ecx), "=d"(*edx)
- : "0"(*eax)
- : "cc");
-#else
- __asm__ ("cpuid\n\t"
- : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
- : "0"(*eax)
- : "cc");
-#endif
-}
-
-#endif /* ETHR_X86_RUNTIME_CONF__ */
-
-/*
- * --------------------------------------------------------------------------
- * Exported functions
- * --------------------------------------------------------------------------
- */
-
-int
-ethr_init(ethr_init_data *id)
-{
- int res;
-
- if (!ethr_not_inited__)
- return EINVAL;
-
-
-#if defined(ETHR_PPC_RUNTIME_CONF__)
- res = ppc_init__();
- if (res != 0)
- goto error;
-#endif
-
- res = ethr_init_common__(id);
- if (res != 0)
- goto error;
-
- main_thr_tid.id = current_process();
- main_thr_tid.tsd_key_index = 0;
-
- set_envp(current_process(),own_tid_key,(OSADDRESS)&main_thr_tid);
- signal_fsem(current_process());
-
-
- ETHR_ASSERT(&main_thr_tid == ETHR_GET_OWN_TID__);
-
- ethr_not_inited__ = 0;
-
- ethr_tsd_key_create(&ethr_ts_event_key__,"ethread_tse");
-
- return 0;
- error:
- ethr_not_inited__ = 1;
- return res;
-
-}
-
-int
-ethr_late_init(ethr_late_init_data *id)
-{
- int res = ethr_late_init_common__(id);
- if (res != 0)
- return res;
- ethr_not_completely_inited__ = 0;
- return res;
-}
-
-int
-ethr_thr_create(ethr_tid *tid, void * (*func)(void *), void *arg,
- ethr_thr_opts *opts)
-{
- int res;
- int use_stack_size = (opts && opts->suggested_stack_size >= 0
- ? opts->suggested_stack_size
- : 0x200 /* Use system default */);
- OSPRIORITY use_prio;
- char *use_name;
- char default_thr_name[20];
- static int no_of_thr = 0;
- cpuid_t use_core;
-
- union SIGNAL *init_msg;
- SIGSELECT sigsel[] = {1,ETHREADWRAPDATASIG};
- void *prep_func_res;
-
-
- if (opts != NULL) {
- LOG(("ERTS - ethr_thr_create(): opts supplied: name: %s, coreNo: %u.\n",
- opts->name, opts->coreNo));
- use_name = opts->name;
- use_core = opts->coreNo;
- if (0 != ethr_get_prio(use_name, &use_prio)) {
- if (0 != ethr_get_prio("DEFAULT", &use_prio)) {
- use_prio = get_pri(current_process());
- LOG(("ERTS - ethr_thr_create(): Using current process' prio: %d.\n", use_prio));
- } else {
- LOG(("ERTS - ethr_thr_create(): Using default prio: %d.\n", use_prio));
- }
- } else {
- LOG(("ERTS - ethr_thr_create(): Using configured prio: %d.\n", use_prio));
- }
- } else {
- LOG(("ERTS - ethr_thr_create(): opts not supplied. Using defaults.\n"));
- no_of_thr++;
- sprintf(default_thr_name, "ethread_%d", no_of_thr);
- use_name = default_thr_name;
- use_core = ose_cpu_id();
-
- if (0 != ethr_get_prio("DEFAULT", &use_prio)) {
- use_prio = get_pri(current_process());
- LOG(("ERTS - ethr_thr_create(): Using current process' prio: %d.\n", use_prio));
- }
- }
-
-#ifdef ETHR_MODIFIED_DEFAULT_STACK_SIZE
- if (use_stack_size < 0)
- use_stack_size = ETHR_MODIFIED_DEFAULT_STACK_SIZE;
-#endif
-
-#if ETHR_XCHK
- if (ethr_not_completely_inited__) {
- ETHR_ASSERT(0);
- return EACCES;
- }
- if (!tid || !func) {
- ETHR_ASSERT(0);
- return EINVAL;
- }
-#endif
-
- if (use_stack_size >= 0) {
- size_t suggested_stack_size = (size_t) use_stack_size;
- size_t stack_size;
-#ifdef ETHR_DEBUG
- suggested_stack_size /= 2; /* Make sure we got margin */
-#endif
-#ifdef ETHR_STACK_GUARD_SIZE
- /* The guard is at least on some platforms included in the stack size
- passed when creating threads */
- suggested_stack_size += ETHR_B2KW(ETHR_STACK_GUARD_SIZE);
-#endif
-
- if (suggested_stack_size < ethr_min_stack_size__)
- stack_size = ETHR_KW2B(ethr_min_stack_size__);
- else if (suggested_stack_size > ethr_max_stack_size__)
- stack_size = ETHR_KW2B(ethr_max_stack_size__);
- else
- stack_size = ETHR_PAGE_ALIGN(ETHR_KW2B(suggested_stack_size));
- use_stack_size = stack_size;
- }
-
- init_msg = alloc(sizeof(ethr_thr_wrap_data__), ETHREADWRAPDATASIG);
-
- /* Call prepare func if it exist */
- if (ethr_thr_prepare_func__)
- init_msg->data.prep_func_res = ethr_thr_prepare_func__();
- else
- init_msg->data.prep_func_res = NULL;
-
- LOG(("ERTS - ethr_thr_create(): Process [0x%x] is creating '%s', coreNo = %u, prio:%u\n",
- current_process(), use_name, use_core, use_prio));
-
- tid->id = create_process(OS_PRI_PROC, use_name, thr_wrapper,
- use_stack_size, use_prio, 0,
- get_bid(current_process()), NULL, 0, 0);
- if (ose_bind_process(tid->id, use_core)) {
- LOG(("ERTS - ethr_thr_create(): Bound pid 0x%x (%s) to core no %u.\n",
- tid->id, use_name, use_core));
- } else {
- LOG(("ERTS - ethr_thr_create(): Failed binding pid 0x%x (%s) to core no %u.\n",
- tid->id, use_name, use_core));
- }
-
- /*FIXME!!! Normally this shouldn't be used in shared mode. Still there is
- * a problem with stdin fd in fd_ processes which should be further
- * investigated */
- efs_clone(tid->id);
-
- tid->tsd_key_index = 0;
- tid->res = NULL;
-
- init_msg->data.tse = ethr_get_ts_event();
- init_msg->data.thr_func = func;
- init_msg->data.arg = arg;
- init_msg->data.tid = tid;
- init_msg->data.name = opts->name;
-
- send(&init_msg, tid->id);
-
- start(tid->id);
- init_msg = receive(sigsel);
-
- res = init_msg->data.result;
- prep_func_res = init_msg->data.prep_func_res;
-
- free_buf(&init_msg);
- /* Cleanup... */
-
- if (ethr_thr_parent_func__)
- ethr_thr_parent_func__(prep_func_res);
-
- LOG(("ERTS - ethr_thr_create(): Exiting.\n"));
- return res;
-}
-
-int
-ethr_thr_join(ethr_tid tid, void **res)
-{
- SIGSELECT sigsel[] = {1,OS_ATTACH_SIG};
-#if ETHR_XCHK
- if (ethr_not_inited__) {
- ETHR_ASSERT(0);
- return EACCES;
- }
-#endif
-
- if (tid.id == ETHR_INVALID_TID_ID)
- return EINVAL;
-
- attach(NULL,tid.id);
- receive(sigsel);
-
- if (res)
- *res = tid.res;
-
- return 0;
-}
-
-int
-ethr_thr_detach(ethr_tid tid)
-{
-#if ETHR_XCHK
- if (ethr_not_inited__) {
- ETHR_ASSERT(0);
- return EACCES;
- }
-#endif
- return 0;
-}
-
-void
-ethr_thr_exit(void *res)
-{
- ethr_tid *tid;
-#if ETHR_XCHK
- if (ethr_not_inited__) {
- ETHR_ASSERT(0);
- return;
- }
-#endif
- tid = ETHR_GET_OWN_TID__;
- if (!tid) {
- ETHR_ASSERT(0);
- kill_proc(current_process());
- }
- thr_exit_cleanup(tid, res);
- /* Harakiri possible? */
- kill_proc(current_process());
-}
-
-ethr_tid
-ethr_self(void)
-{
- ethr_tid *tid;
-#if ETHR_XCHK
- if (ethr_not_inited__) {
- ethr_tid dummy_tid = {ETHR_INVALID_TID_ID, 0, NULL};
- ETHR_ASSERT(0);
- return dummy_tid;
- }
-#endif
- tid = ETHR_GET_OWN_TID__;
- if (!tid) {
- ethr_tid dummy_tid = {ETHR_INVALID_TID_ID, 0, NULL};
- return dummy_tid;
- }
- return *tid;
-}
-
-int
-ethr_equal_tids(ethr_tid tid1, ethr_tid tid2)
-{
- return tid1.id == tid2.id && tid1.id != ETHR_INVALID_TID_ID;
-}
-
-
-/*
- * Thread specific events
- */
-
-ethr_ts_event *
-ethr_get_ts_event(void)
-{
- return ethr_get_ts_event__();
-}
-
-void
-ethr_leave_ts_event(ethr_ts_event *tsep)
-{
- ethr_leave_ts_event__(tsep);
-}
-
-/*
- * Thread specific data
- */
-
-int
-ethr_tsd_key_create(ethr_tsd_key *keyp, char *keyname)
-{
-
-#if ETHR_XCHK
- if (ethr_not_inited__) {
- ETHR_ASSERT(0);
- return EACCES;
- }
- if (!keyp) {
- ETHR_ASSERT(0);
- return EINVAL;
- }
-#endif
-
- ose_create_ppdata(keyname,keyp);
-
- return 0;
-}
-
-int
-ethr_tsd_key_delete(ethr_tsd_key key)
-{
-#if ETHR_XCHK
- if (ethr_not_inited__) {
- ETHR_ASSERT(0);
- return EACCES;
- }
-#endif
- /* Not possible to delete ppdata */
-
- return 0;
-}
-
-int
-ethr_tsd_set(ethr_tsd_key key, void *value)
-{
- void **ppdp;
-#if ETHR_XCHK
- if (ethr_not_inited__) {
- ETHR_ASSERT(0);
- return EACCES;
- }
-#endif
- ppdp = (void **)ose_get_ppdata(key);
- *ppdp = value;
- return 0;
-}
-
-void *
-ethr_tsd_get(ethr_tsd_key key)
-{
-#if ETHR_XCHK
- if (ethr_not_inited__) {
- ETHR_ASSERT(0);
- return NULL;
- }
-#endif
- return *(void**)ose_get_ppdata(key);
-}
-
-/*
- * Signal functions
- */
-
-#if ETHR_HAVE_ETHR_SIG_FUNCS
-
-int ethr_sigmask(int how, const sigset_t *set, sigset_t *oset)
-{
-#if ETHR_XCHK
- if (ethr_not_inited__) {
- ETHR_ASSERT(0);
- return EACCES;
- }
- if (!set && !oset) {
- ETHR_ASSERT(0);
- return EINVAL;
- }
-#endif
- return pthread_sigmask(how, set, oset);
-}
-
-int ethr_sigwait(const sigset_t *set, int *sig)
-{
-#if ETHR_XCHK
- if (ethr_not_inited__) {
- ETHR_ASSERT(0);
- return EACCES;
- }
- if (!set || !sig) {
- ETHR_ASSERT(0);
- return EINVAL;
- }
-#endif
- if (sigwait(set, sig) < 0)
- return errno;
- return 0;
-}
-
-#endif /* #if ETHR_HAVE_ETHR_SIG_FUNCS */
-
-ETHR_IMPL_NORETURN__
-ethr_abort__(void)
-{
- abort();
-}
diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam
index f1ae49150b..6d777fa811 100644
--- a/erts/preloaded/ebin/erl_prim_loader.beam
+++ b/erts/preloaded/ebin/erl_prim_loader.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam
index 990973c57d..2ea2de4c70 100644
--- a/erts/preloaded/ebin/erlang.beam
+++ b/erts/preloaded/ebin/erlang.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erts_code_purger.beam b/erts/preloaded/ebin/erts_code_purger.beam
new file mode 100644
index 0000000000..4188e5fd9b
--- /dev/null
+++ b/erts/preloaded/ebin/erts_code_purger.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam
index 7461e3bc5b..88da34b192 100644
--- a/erts/preloaded/ebin/erts_internal.beam
+++ b/erts/preloaded/ebin/erts_internal.beam
Binary files differ
diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam
index 0060a2cf42..8ac7f5b471 100644
--- a/erts/preloaded/ebin/init.beam
+++ b/erts/preloaded/ebin/init.beam
Binary files differ
diff --git a/erts/preloaded/ebin/otp_ring0.beam b/erts/preloaded/ebin/otp_ring0.beam
index b1868d7e10..3cd2515ba8 100644
--- a/erts/preloaded/ebin/otp_ring0.beam
+++ b/erts/preloaded/ebin/otp_ring0.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_eval.beam b/erts/preloaded/ebin/prim_eval.beam
index dc16909d26..9a208d1545 100644
--- a/erts/preloaded/ebin/prim_eval.beam
+++ b/erts/preloaded/ebin/prim_eval.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam
index f6e15ba499..426e764127 100644
--- a/erts/preloaded/ebin/prim_file.beam
+++ b/erts/preloaded/ebin/prim_file.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam
index 673627498e..d68d18ecba 100644
--- a/erts/preloaded/ebin/prim_inet.beam
+++ b/erts/preloaded/ebin/prim_inet.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_zip.beam b/erts/preloaded/ebin/prim_zip.beam
index 813060c41d..01b3b1feb8 100644
--- a/erts/preloaded/ebin/prim_zip.beam
+++ b/erts/preloaded/ebin/prim_zip.beam
Binary files differ
diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam
index 5ce932aeec..7252d866bb 100644
--- a/erts/preloaded/ebin/zlib.beam
+++ b/erts/preloaded/ebin/zlib.beam
Binary files differ
diff --git a/erts/preloaded/src/Makefile b/erts/preloaded/src/Makefile
index 52034a0881..31383dda83 100644
--- a/erts/preloaded/src/Makefile
+++ b/erts/preloaded/src/Makefile
@@ -41,6 +41,7 @@ PRE_LOADED_ERL_MODULES = \
zlib \
prim_zip \
otp_ring0 \
+ erts_code_purger \
erlang \
erts_internal
diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl
index 9f6cba33bd..cbcced5512 100644
--- a/erts/preloaded/src/erl_prim_loader.erl
+++ b/erts/preloaded/src/erl_prim_loader.erl
@@ -42,7 +42,7 @@
-include("inet_boot.hrl").
%% Public
--export([start/3, set_path/1, get_path/0, get_file/1, get_files/2,
+-export([start/0, set_path/1, get_path/0, get_file/1,
list_dir/1, read_file_info/1, read_link_info/1, get_cwd/0, get_cwd/1]).
%% Used by erl_boot_server
@@ -50,30 +50,31 @@
prim_read_file_info/3, prim_get_cwd/2]).
%% Used by escript and code
--export([set_primary_archive/4, release_archives/0]).
+-export([set_primary_archive/4]).
+
+%% Used by test suites
+-export([purge_archive_cache/0]).
+
+%% Used by init and the code server.
+-export([get_modules/3]).
-include_lib("kernel/include/file.hrl").
-type host() :: atom().
-record(prim_state, {debug :: boolean(),
- cache,
primary_archive}).
-type prim_state() :: #prim_state{}.
-record(state,
{loader :: 'efile' | 'inet',
hosts = [] :: [host()], % hosts list (to boot from)
- id, % not used any more?
data :: 'noport' | port(), % data port etc
- timeout :: timeout(), % idle timeout
- %% Number of timeouts before archives are released
- n_timeouts :: non_neg_integer(),
- multi_get = false :: boolean(),
+ timeout :: timeout(), % idle timeout
prim_state :: prim_state()}). % state for efile code loader
--define(IDLE_TIMEOUT, 60000). %% tear inet connection after 1 minutes
--define(N_TIMEOUTS, 6). %% release efile archive after 6 minutes
+-define(EFILE_IDLE_TIMEOUT, (6*60*1000)). %purge archives
+-define(INET_IDLE_TIMEOUT, (60*1000)). %tear down connection timeout
%% Defines for inet as prim_loader
-define(INET_FAMILY, inet).
@@ -103,26 +104,13 @@ debug(#prim_state{debug = Deb}, Term) ->
%%% Interface Functions.
%%% --------------------------------------------------------
--spec start(Id, Loader, Hosts) ->
+-spec start() ->
{'ok', Pid} | {'error', What} when
- Id :: term(),
- Loader :: atom() | string(),
- Hosts :: Host | [Host],
- Host :: host(),
Pid :: pid(),
What :: term().
-start(Id, Pgm, Hosts) when is_atom(Hosts) ->
- start(Id, Pgm, [Hosts]);
-start(Id, Pgm0, Hosts) ->
- Pgm = if
- is_atom(Pgm0) ->
- atom_to_list(Pgm0);
- true ->
- Pgm0
- end,
+start() ->
Self = self(),
- Pid = spawn_link(fun() -> start_it(Pgm, Id, Self, Hosts) end),
- register(erl_prim_loader, Pid),
+ Pid = spawn_link(fun() -> start_it(Self) end),
receive
{Pid,ok} ->
{ok,Pid};
@@ -130,26 +118,39 @@ start(Id, Pgm0, Hosts) ->
{error,Reason}
end.
-%% Hosts must be a list of form ['1.2.3.4' ...]
-start_it("inet", Id, Pid, Hosts) ->
+start_it(Parent) ->
process_flag(trap_exit, true),
- ?dbg(inet, {Id,Pid,Hosts}),
+ register(erl_prim_loader, self()),
+ Loader = case init:get_argument(loader) of
+ {ok,[[Loader0]]} ->
+ Loader0;
+ error ->
+ "efile"
+ end,
+ case Loader of
+ "efile" -> start_efile(Parent);
+ "inet" -> start_inet(Parent)
+ end.
+
+%% Hosts must be a list of form ['1.2.3.4' ...]
+start_inet(Parent) ->
+ Hosts = case init:get_argument(hosts) of
+ {ok,[Hosts0]} -> Hosts0;
+ _ -> []
+ end,
AL = ipv4_list(Hosts),
?dbg(addresses, AL),
{ok,Tcp} = find_master(AL),
- init_ack(Pid),
+ init_ack(Parent),
PS = prim_init(),
State = #state {loader = inet,
hosts = AL,
- id = Id,
data = Tcp,
- timeout = ?IDLE_TIMEOUT,
- n_timeouts = ?N_TIMEOUTS,
+ timeout = ?INET_IDLE_TIMEOUT,
prim_state = PS},
- loop(State, Pid, []);
+ loop(State, Parent, []).
-start_it("efile", Id, Pid, _Hosts) ->
- process_flag(trap_exit, true),
+start_efile(Parent) ->
{ok, Port} = prim_file:start(),
%% Check that we started in a valid directory.
case prim_file:get_cwd(Port) of
@@ -160,20 +161,14 @@ start_it("efile", Id, Pid, _Hosts) ->
erlang:display(Report),
exit({error, invalid_current_directory});
_ ->
- init_ack(Pid)
+ init_ack(Parent)
end,
- MultiGet = case erlang:system_info(thread_pool_size) of
- 0 -> false;
- _ -> true
- end,
PS = prim_init(),
State = #state {loader = efile,
- id = Id,
data = Port,
- timeout = infinity,
- multi_get = MultiGet,
+ timeout = ?EFILE_IDLE_TIMEOUT,
prim_state = PS},
- loop(State, Pid, []).
+ loop(State, Parent, []).
init_ack(Pid) ->
Pid ! {self(),ok},
@@ -198,20 +193,6 @@ get_file(File) when is_atom(File) ->
get_file(File) ->
check_file_result(get_file, File, request({get_file,File})).
--spec get_files([{atom(), string()}],
- fun((atom(),binary(),string()) -> 'ok' | {'error', atom()})) ->
- 'ok' | {'error', atom()}.
-get_files(ModFiles, Fun) ->
- case request({get_files,{ModFiles,Fun}}) of
- E = {error,_M} ->
- E;
- {error,Reason,M} ->
- check_file_result(get_files, M, {error,Reason}),
- {error,M};
- ok ->
- ok
- end.
-
-spec list_dir(Dir) -> {'ok', Filenames} | 'error' when
Dir :: string(),
Filenames :: [Filename :: string()].
@@ -250,10 +231,23 @@ set_primary_archive(File, ArchiveBin, FileInfo, ParserFun)
when is_list(File), is_binary(ArchiveBin), is_record(FileInfo, file_info) ->
request({set_primary_archive, File, ArchiveBin, FileInfo, ParserFun}).
--spec release_archives() -> 'ok' | {'error', _}.
+%% NOTE: Does not close the primary archive. Only closes all
+%% open zip files kept in the cache. Should be called before an archive
+%% file is to be removed (for example in the test suites).
-release_archives() ->
- request(release_archives).
+-spec purge_archive_cache() -> 'ok' | {'error', _}.
+purge_archive_cache() ->
+ request(purge_archive_cache).
+
+
+-spec get_modules([module()],
+ fun((atom(), string(), binary()) ->
+ {'ok',any()} | {'error',any()}),
+ [string()]) ->
+ {'ok',{[any()],[any()]}}.
+
+get_modules(Modules, Fun, Path) ->
+ request({get_modules,{Modules,Fun,Path}}).
request(Req) ->
Loader = whereis(erl_prim_loader),
@@ -310,76 +304,61 @@ check_file_result(_, _, Other) ->
%%% The main loop.
%%% --------------------------------------------------------
-loop(State, Parent, Paths) ->
+loop(St0, Parent, Paths) ->
receive
+ {Pid,{set_path,NewPaths}} when is_pid(Pid) ->
+ Pid ! {self(),ok},
+ loop(St0, Parent, to_strs(NewPaths));
{Pid,Req} when is_pid(Pid) ->
- %% erlang:display(Req),
- {Resp,State2,Paths2} =
- case Req of
- {set_path,NewPaths} ->
- {ok,State,to_strs(NewPaths)};
- {get_path,_} ->
- {{ok,Paths},State,Paths};
- {get_file,File} ->
- {Res,State1} = handle_get_file(State, Paths, File),
- {Res,State1,Paths};
- {get_files,{ModFiles,Fun}} ->
- {Res,State1} = handle_get_files(State, ModFiles, Paths, Fun),
- {Res,State1,Paths};
- {list_dir,Dir} ->
- {Res,State1} = handle_list_dir(State, Dir),
- {Res,State1,Paths};
- {read_file_info,File} ->
- {Res,State1} = handle_read_file_info(State, File),
- {Res,State1,Paths};
- {read_link_info,File} ->
- {Res,State1} = handle_read_link_info(State, File),
- {Res,State1,Paths};
- {get_cwd,[]} ->
- {Res,State1} = handle_get_cwd(State, []),
- {Res,State1,Paths};
- {get_cwd,[_]=Args} ->
- {Res,State1} = handle_get_cwd(State, Args),
- {Res,State1,Paths};
- {set_primary_archive,File,ArchiveBin,FileInfo,ParserFun} ->
- {Res,State1} =
- handle_set_primary_archive(State, File,
- ArchiveBin, FileInfo,
- ParserFun),
- {Res,State1,Paths};
- release_archives ->
- {Res,State1} = handle_release_archives(State),
- {Res,State1,Paths};
- _Other ->
- {ignore,State,Paths}
- end,
- if Resp =:= ignore -> ok;
- true -> Pid ! {self(),Resp}, ok
- end,
- if
- is_record(State2, state) ->
- loop(State2, Parent, Paths2);
- true ->
- exit({bad_state, Req, State2})
+ case handle_request(Req, Paths, St0) of
+ ignore ->
+ ok;
+ {Resp,#state{}=St1} ->
+ Pid ! {self(),Resp},
+ loop(St1, Parent, Paths);
+ {_,State2,_} ->
+ exit({bad_state,Req,State2})
end;
{'EXIT',Parent,W} ->
- _State1 = handle_stop(State),
+ _ = handle_stop(St0),
exit(W);
{'EXIT',P,W} ->
- State1 = handle_exit(State, P, W),
- loop(State1, Parent, Paths);
+ St1 = handle_exit(St0, P, W),
+ loop(St1, Parent, Paths);
_Message ->
- loop(State, Parent, Paths)
- after State#state.timeout ->
- State1 = handle_timeout(State, Parent),
- loop(State1, Parent, Paths)
+ loop(St0, Parent, Paths)
+ after St0#state.timeout ->
+ St1 = handle_timeout(St0, Parent),
+ loop(St1, Parent, Paths)
+ end.
+
+handle_request(Req, Paths, St0) ->
+ case Req of
+ {get_path,_} ->
+ {{ok,Paths},St0};
+ {get_file,File} ->
+ handle_get_file(St0, Paths, File);
+ {get_modules,{Modules,Fun,ModPaths}} ->
+ handle_get_modules(St0, Modules, Fun, ModPaths);
+ {list_dir,Dir} ->
+ handle_list_dir(St0, Dir);
+ {read_file_info,File} ->
+ handle_read_file_info(St0, File);
+ {read_link_info,File} ->
+ handle_read_link_info(St0, File);
+ {get_cwd,[]} ->
+ handle_get_cwd(St0, []);
+ {get_cwd,[_]=Args} ->
+ handle_get_cwd(St0, Args);
+ {set_primary_archive,File,ArchiveBin,FileInfo,ParserFun} ->
+ handle_set_primary_archive(St0, File, ArchiveBin,
+ FileInfo, ParserFun);
+ purge_archive_cache ->
+ handle_purge_archive_cache(St0);
+ _ ->
+ ignore
end.
-handle_get_files(State = #state{multi_get = true}, ModFiles, Paths, Fun) ->
- ?SAFE2(efile_multi_get_file_from_port(State, ModFiles, Paths, Fun), State);
-handle_get_files(State, _ModFiles, _Paths, _Fun) -> % no multi get
- {{error,no_multi_get},State}.
-
handle_get_file(State = #state{loader = efile}, Paths, File) ->
?SAFE2(efile_get_file_from_port(State, File, Paths), State);
handle_get_file(State = #state{loader = inet}, Paths, File) ->
@@ -388,8 +367,9 @@ handle_get_file(State = #state{loader = inet}, Paths, File) ->
handle_set_primary_archive(State= #state{loader = efile}, File, ArchiveBin, FileInfo, ParserFun) ->
?SAFE2(efile_set_primary_archive(State, File, ArchiveBin, FileInfo, ParserFun), State).
-handle_release_archives(State= #state{loader = efile}) ->
- ?SAFE2(efile_release_archives(State), State).
+handle_purge_archive_cache(#state{loader = efile}=State) ->
+ prim_purge_cache(),
+ {ok,State}.
handle_list_dir(State = #state{loader = efile}, Dir) ->
?SAFE2(efile_list_dir(State, Dir), State);
@@ -430,53 +410,6 @@ handle_timeout(State = #state{loader = inet}, Parent) ->
%%% Functions which handle efile as prim_loader (default).
%%% --------------------------------------------------------
-%%% Reading many files in parallel is an optimization.
-%%% See also comment in init.erl.
-
-%% -> {ok,State} | {{error,Module},State} | {{error,Reason,Module},State}
-efile_multi_get_file_from_port(State, ModFiles, Paths, Fun) ->
- Ref = make_ref(),
- %% More than 200 processes is no gain.
- Max = erlang:min(200, erlang:system_info(thread_pool_size)),
- efile_multi_get_file_from_port2(ModFiles, 0, Max, State, Paths, Fun, Ref, ok).
-
-efile_multi_get_file_from_port2([MF | MFs], Out, Max, State, Paths, Fun, Ref, Ret) when Out < Max ->
- Self = self(),
- _Pid = spawn(fun() -> efile_par_get_file(Ref, State, MF, Paths, Self, Fun) end),
- efile_multi_get_file_from_port2(MFs, Out+1, Max, State, Paths, Fun, Ref, Ret);
-efile_multi_get_file_from_port2(MFs, Out, Max, _State, Paths, Fun, Ref, Ret) when Out > 0 ->
- receive
- {Ref, ok, State1} ->
- efile_multi_get_file_from_port2(MFs, Out-1, Max, State1, Paths, Fun, Ref, Ret);
- {Ref, {error,_Mod} = Error, State1} ->
- efile_multi_get_file_from_port2(MFs, Out-1, Max, State1, Paths, Fun, Ref, Error);
- {Ref, MF, {error,emfile,State1}} ->
- %% Max can take negative values. Out cannot.
- efile_multi_get_file_from_port2([MF | MFs], Out-1, Max-1, State1, Paths, Fun, Ref, Ret);
- {Ref, {M,_F}, {error,Error,State1}} ->
- efile_multi_get_file_from_port2(MFs, Out-1, 0, State1, Paths, Fun, Ref, {error,Error,M})
- end;
-efile_multi_get_file_from_port2(_MFs, 0, _Max, State, _Paths, _Fun, _Ref, Ret) ->
- {Ret,State}.
-
-efile_par_get_file(Ref, State, {Mod,File} = MF, Paths, Pid, Fun) ->
- %% One port for each file read in "parallel":
- case prim_file:start() of
- {ok, Port} ->
- Port0 = State#state.data,
- State1 = State#state{data = Port},
- R = case efile_get_file_from_port(State1, File, Paths) of
- {{error,Reason},State2} ->
- {Ref,MF,{error,Reason,State2}};
- {{ok,BinFile,Full},State2} ->
- %% Fun(...) -> ok | {error,Mod}
- {Ref,Fun(Mod, BinFile, Full),State2#state{data=Port0}}
- end,
- prim_file:close(Port),
- Pid ! R;
- {error, Error} ->
- Pid ! {Ref,MF,{error,Error,State}}
- end.
%% -> {{ok,BinFile,File},State} | {{error,Reason},State}
efile_get_file_from_port(State, File, Paths) ->
@@ -521,10 +454,6 @@ efile_set_primary_archive(#state{prim_state = PS} = State, File,
FileInfo, ParserFun),
{Res,State#state{prim_state = PS2}}.
-efile_release_archives(#state{prim_state = PS} = State) ->
- {Res, PS2} = prim_release_archives(PS),
- {Res,State#state{prim_state = PS2}}.
-
efile_list_dir(#state{prim_state = PS} = State, Dir) ->
{Res, PS2} = prim_list_dir(PS, Dir),
{Res, State#state{prim_state = PS2}}.
@@ -546,15 +475,128 @@ efile_exit_port(State, Port, Reason) when State#state.data =:= Port ->
efile_exit_port(State, _Port, _Reason) ->
State.
-efile_timeout_handler(#state{n_timeouts = N} = State, _Parent) ->
- if
- N =< 0 ->
- {_Res, State2} = efile_release_archives(State),
- State2#state{n_timeouts = ?N_TIMEOUTS};
- true ->
- State#state{n_timeouts = N - 1}
+efile_timeout_handler(State, _Parent) ->
+ prim_purge_cache(),
+ State.
+
+%%% --------------------------------------------------------
+%%% Read and process severals modules in parallel.
+%%% --------------------------------------------------------
+
+handle_get_modules(#state{loader=efile}=St, Ms, Process, Paths) ->
+ Primary = (St#state.prim_state)#prim_state.primary_archive,
+ Res = case efile_any_archives(Paths, Primary) of
+ false ->
+ efile_get_mods_par(Ms, Process, Paths);
+ true ->
+ Get = fun efile_get_file_from_port/3,
+ gm_get_mods(St, Get, Ms, Process, Paths)
+ end,
+ {Res,St};
+handle_get_modules(#state{loader=inet}=St, Ms, Process, Paths) ->
+ Get = fun inet_get_file_from_port/3,
+ {gm_get_mods(St, Get, Ms, Process, Paths),St}.
+
+efile_get_mods_par(Ms, Process, Paths) ->
+ Self = self(),
+ Ref = make_ref(),
+ GmSpawn = fun() ->
+ efile_gm_spawn({Self,Ref}, Ms, Process, Paths)
+ end,
+ _ = spawn_link(GmSpawn),
+ N = length(Ms),
+ efile_gm_recv(N, Ref, [], []).
+
+efile_any_archives([H|T], Primary) ->
+ case name_split(Primary, H) of
+ {file,_} -> efile_any_archives(T, Primary);
+ {archive,_,_} -> true
+ end;
+efile_any_archives([], _) ->
+ false.
+
+efile_gm_recv(0, _Ref, Succ, Fail) ->
+ {ok,{Succ,Fail}};
+efile_gm_recv(N, Ref, Succ, Fail) ->
+ receive
+ {Ref,Mod,{ok,Res}} ->
+ efile_gm_recv(N-1, Ref, [{Mod,Res}|Succ], Fail);
+ {Ref,Mod,{error,Res}} ->
+ efile_gm_recv(N-1, Ref, Succ, [{Mod,Res}|Fail])
end.
+efile_gm_spawn(ParentRef, Ms, Process, Paths) ->
+ efile_gm_spawn_1(0, Ms, ParentRef, Process, Paths).
+
+efile_gm_spawn_1(N, Ms, ParentRef, Process, Paths) when N >= 32 ->
+ receive
+ {'DOWN',_,process,_,_} ->
+ efile_gm_spawn_1(N-1, Ms, ParentRef, Process, Paths)
+ end;
+efile_gm_spawn_1(N, [M|Ms], ParentRef, Process, Paths) ->
+ Get = fun() -> efile_gm_get(Paths, M, ParentRef, Process) end,
+ _ = spawn_monitor(Get),
+ efile_gm_spawn_1(N+1, Ms, ParentRef, Process, Paths);
+efile_gm_spawn_1(_, [], _, _, _) ->
+ ok.
+
+efile_gm_get(Paths, Mod, ParentRef, Process) ->
+ File = atom_to_list(Mod) ++ init:objfile_extension(),
+ efile_gm_get_1(Paths, File, Mod, ParentRef, Process).
+
+efile_gm_get_1([P|Ps], File0, Mod, {Parent,Ref}=PR, Process) ->
+ File = join(P, File0),
+ Res = try prim_file:read_file(File) of
+ {ok,Bin} ->
+ gm_process(Mod, File, Bin, Process);
+ {error,enoent} ->
+ efile_gm_get_1(Ps, File0, Mod, PR, Process);
+ Error ->
+ check_file_result(get_modules, File, Error),
+ Error
+ catch
+ _:Reason ->
+ {error,{crash,Reason}}
+ end,
+ Parent ! {Ref,Mod,Res};
+efile_gm_get_1([], _, Mod, {Parent,Ref}, _Process) ->
+ Parent ! {Ref,Mod,{error,enoent}}.
+
+gm_get_mods(St, Get, Ms, Process, Paths) ->
+ gm_get_mods(St, Get, Ms, Process, Paths, [], []).
+
+gm_get_mods(St, Get, [M|Ms], Process, Paths, Succ, Fail) ->
+ File = atom_to_list(M) ++ init:objfile_extension(),
+ case gm_arch_get(St, Get, M, File, Paths, Process) of
+ {ok,Res} ->
+ gm_get_mods(St, Get, Ms, Process, Paths,
+ [{M,Res}|Succ], Fail);
+ {error,Res} ->
+ gm_get_mods(St, Get, Ms, Process, Paths,
+ Succ, [{M,Res}|Fail])
+ end;
+gm_get_mods(_St, _Get, [], _, _, Succ, Fail) ->
+ {ok,{Succ,Fail}}.
+
+gm_arch_get(St, Get, Mod, File, Paths, Process) ->
+ case Get(St, File, Paths) of
+ {{error,_}=E,_} ->
+ E;
+ {{ok,Bin,Full},_} ->
+ gm_process(Mod, Full, Bin, Process)
+ end.
+
+gm_process(Mod, File, Bin, Process) ->
+ try Process(Mod, File, Bin) of
+ {ok,_}=Res -> Res;
+ {error,_}=Res -> Res;
+ Other -> {error,{bad_return,Other}}
+ catch
+ _:Error ->
+ {error,{crash,Error}}
+ end.
+
+
%%% --------------------------------------------------------
%%% Functions which handle inet prim_loader
%%% --------------------------------------------------------
@@ -694,7 +736,7 @@ inet_get_file_from_port1(_File, [], State) ->
inet_send_and_rcv(Msg, Tag, State) when State#state.data =:= noport ->
{ok,Tcp} = find_master(State#state.hosts), %% reconnect
inet_send_and_rcv(Msg, Tag, State#state{data = Tcp,
- timeout = ?IDLE_TIMEOUT});
+ timeout = ?INET_IDLE_TIMEOUT});
inet_send_and_rcv(Msg, Tag, #state{data = Tcp, timeout = Timeout} = State) ->
prim_inet:send(Tcp, term_to_binary(Msg)),
receive
@@ -819,32 +861,19 @@ prim_init() ->
end,
cache_new(#prim_state{debug = Deb}).
-prim_release_archives(PS) ->
- debug(PS, release_archives),
- {Res, PS2} = prim_do_release_archives(PS, get(), []),
- debug(PS2, {return, Res}),
- {Res, PS2}.
-
-prim_do_release_archives(PS, [{ArchiveFile, DictVal} | KeyVals], Acc) ->
- Res =
- case DictVal of
- {primary, _PrimZip, _FI, _ParserFun} ->
- ok; % Keep primary archive
- {Cache, _FI} ->
- debug(PS, {release, cache, ArchiveFile}),
- erase(ArchiveFile),
- clear_cache(ArchiveFile, Cache)
- end,
- case Res of
- ok ->
- prim_do_release_archives(PS, KeyVals, Acc);
- {error, Reason} ->
- prim_do_release_archives(PS, KeyVals, [{ArchiveFile, Reason} | Acc])
- end;
-prim_do_release_archives(PS, [], []) ->
- {ok, PS#prim_state{primary_archive = undefined}};
-prim_do_release_archives(PS, [], Errors) ->
- {{error, Errors}, PS#prim_state{primary_archive = undefined}}.
+prim_purge_cache() ->
+ do_prim_purge_cache(get()).
+
+do_prim_purge_cache([{Key,Val}|T]) ->
+ case Val of
+ {Cache,_FI} ->
+ catch clear_cache(Key, Cache);
+ _ ->
+ ok
+ end,
+ do_prim_purge_cache(T);
+do_prim_purge_cache([]) ->
+ ok.
prim_set_primary_archive(PS, undefined, undefined, undefined, _ParserFun) ->
debug(PS, {set_primary_archive, clean}),
@@ -1287,70 +1316,62 @@ path_join([Path],Acc) ->
path_join([Path|Paths],Acc) ->
path_join(Paths,"/" ++ reverse(Path) ++ Acc).
-name_split(ArchiveFile, File0) ->
- File = absname(File0),
- do_name_split(ArchiveFile, File).
-
-do_name_split(undefined, File) ->
+name_split(undefined, File) ->
%% Ignore primary archive
- case string_split(File, init:archive_extension(), []) of
+ RevExt = reverse(init:archive_extension()),
+ case archive_split(File, RevExt, []) of
no_split ->
- %% Plain file
{file, File};
- {split, _RevArchiveBase, RevArchiveFile, []} ->
- %% Top dir in archive
- ArchiveFile = reverse(RevArchiveFile),
- {archive, ArchiveFile, []};
- {split, _RevArchiveBase, RevArchiveFile, [$/ | FileInArchive]} ->
- %% File in archive
- ArchiveFile = reverse(RevArchiveFile),
- {archive, ArchiveFile, FileInArchive};
- {split, _RevArchiveBase, _RevArchiveFile, _FileInArchive} ->
- %% False match. Assume plain file
- {file, File}
+ Archive ->
+ Archive
end;
-do_name_split(ArchiveFile, File) ->
+name_split(ArchiveFile, File0) ->
%% Look first in primary archive
- case string_match(real_path(File), ArchiveFile, []) of
+ File = absname(File0),
+ case string_match(real_path(File), ArchiveFile) of
no_match ->
%% Archive or plain file
- do_name_split(undefined, File);
- {match, _RevPrimArchiveFile, FileInArchive} ->
+ name_split(undefined, File);
+ {match, FileInArchive} ->
%% Primary archive
{archive, ArchiveFile, FileInArchive}
end.
-string_match([Char | File], [Char | Archive], RevTop) ->
- string_match(File, Archive, [Char | RevTop]);
-string_match([] = File, [], RevTop) ->
- {match, RevTop, File};
-string_match([$/ | File], [], RevTop) ->
- {match, RevTop, File};
-string_match(_File, _Archive, _RevTop) ->
+string_match([Char | File], [Char | Archive]) ->
+ string_match(File, Archive);
+string_match([] = File, []) ->
+ {match, File};
+string_match([$/ | File], []) ->
+ {match, File};
+string_match(_File, _Archive) ->
no_match.
-string_split([Char | File], [Char | Ext] = FullExt, RevTop) ->
- RevTop2 = [Char | RevTop],
- string_split2(File, Ext, RevTop, RevTop2, File, FullExt, RevTop2);
-string_split([Char | File], Ext, RevTop) ->
- string_split(File, Ext, [Char | RevTop]);
-string_split([], _Ext, _RevTop) ->
- no_split.
-
-string_split2([Char | File], [Char | Ext], RevBase, RevTop, SaveFile, SaveExt, SaveTop) ->
- string_split2(File, Ext, RevBase, [Char | RevTop], SaveFile, SaveExt, SaveTop);
-string_split2(File, [], RevBase, RevTop, _SaveFile, _SaveExt, _SaveTop) ->
- {split, RevBase, RevTop, File};
-string_split2(_, _Ext, _RevBase, _RevTop, SaveFile, SaveExt, SaveTop) ->
- string_split(SaveFile, SaveExt, SaveTop).
+archive_split("/"++File, RevExt, Acc) ->
+ case is_prefix(RevExt, Acc) of
+ false ->
+ archive_split(File, RevExt, [$/|Acc]);
+ true ->
+ ArchiveFile = absname(reverse(Acc)),
+ {archive, ArchiveFile, File}
+ end;
+archive_split([H|T], RevExt, Acc) ->
+ archive_split(T, RevExt, [H|Acc]);
+archive_split([], RevExt, Acc) ->
+ case is_prefix(RevExt, Acc) of
+ false ->
+ no_split;
+ true ->
+ ArchiveFile = absname(reverse(Acc)),
+ {archive, ArchiveFile, []}
+ end.
+
+is_prefix([H|T1], [H|T2]) -> is_prefix(T1, T2);
+is_prefix([_|_], _) -> false;
+is_prefix([], _ ) -> true.
%% Parse list of ipv4 addresses
ipv4_list([H | T]) ->
- IPV = if is_atom(H) -> ipv4_address(atom_to_list(H));
- is_list(H) -> ipv4_address(H);
- true -> {error,einal}
- end,
- case IPV of
+ case ipv4_address(H) of
{ok,IP} -> [IP | ipv4_list(T)];
_ -> ipv4_list(T)
end;
@@ -1415,8 +1436,6 @@ absname_vr([Drive, $\: | NameRest], _) ->
%% Assumes normalized name
pathtype(Name) when is_list(Name) ->
case erlang:system_info(os_type) of
- {ose, _} ->
- unix_pathtype(Name);
{unix, _} ->
unix_pathtype(Name);
{win32, _} ->
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 063b9a1f26..dfbd116d6e 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -71,7 +71,8 @@
| 'milli_seconds'
| 'micro_seconds'
| 'nano_seconds'
- | 'native'.
+ | 'native'
+ | 'perf_counter'.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Native code BIF stubs and their types
@@ -104,7 +105,9 @@
-export([garbage_collect/0, garbage_collect/1, garbage_collect/2]).
-export([garbage_collect_message_area/0, get/0, get/1, get_keys/0, get_keys/1]).
-export([get_module_info/1, get_stacktrace/0, group_leader/0]).
--export([group_leader/2, halt/0, halt/1, halt/2, hash/2, hibernate/3]).
+-export([group_leader/2]).
+-export([halt/0, halt/1, halt/2, hash/2,
+ has_prepared_code_on_load/1, hibernate/3]).
-export([insert_element/3]).
-export([integer_to_binary/1, integer_to_list/1]).
-export([iolist_size/1, iolist_to_binary/1]).
@@ -469,7 +472,7 @@ check_old_code(_Module) ->
CheckResult :: boolean().
check_process_code(Pid, Module) ->
try
- erlang:check_process_code(Pid, Module, [{allow_gc, true}])
+ erts_internal:check_process_code(Pid, Module, [{allow_gc, true}])
catch
error:Error -> erlang:error(Error, [Pid, Module])
end.
@@ -484,51 +487,11 @@ check_process_code(Pid, Module) ->
CheckResult :: boolean() | aborted.
check_process_code(Pid, Module, OptionList) ->
try
- {Async, AllowGC} = get_cpc_opts(OptionList, sync, true),
- case Async of
- {async, ReqId} ->
- {priority, Prio} = erlang:process_info(erlang:self(),
- priority),
- erts_internal:request_system_task(Pid,
- Prio,
- {check_process_code,
- ReqId,
- Module,
- AllowGC}),
- async;
- sync ->
- case Pid == erlang:self() of
- true ->
- erts_internal:check_process_code(Module,
- [{allow_gc, AllowGC}]);
- false ->
- {priority, Prio} = erlang:process_info(erlang:self(),
- priority),
- ReqId = erlang:make_ref(),
- erts_internal:request_system_task(Pid,
- Prio,
- {check_process_code,
- ReqId,
- Module,
- AllowGC}),
- receive
- {check_process_code, ReqId, CheckResult} ->
- CheckResult
- end
- end
- end
+ erts_internal:check_process_code(Pid, Module, OptionList)
catch
error:Error -> erlang:error(Error, [Pid, Module, OptionList])
end.
-% gets async and allow_gc opts and verify valid option list
-get_cpc_opts([{async, _ReqId} = AsyncTuple | Options], _OldAsync, AllowGC) ->
- get_cpc_opts(Options, AsyncTuple, AllowGC);
-get_cpc_opts([{allow_gc, AllowGC} | Options], Async, _OldAllowGC) ->
- get_cpc_opts(Options, Async, AllowGC);
-get_cpc_opts([], Async, AllowGC) ->
- {Async, AllowGC}.
-
%% crc32/1
-spec erlang:crc32(Data) -> non_neg_integer() when
Data :: iodata().
@@ -1036,6 +999,12 @@ halt(_Status, _Options) ->
hash(_Term, _Range) ->
erlang:nif_error(undefined).
+%% has_prepared_code_on_load/1
+-spec erlang:has_prepared_code_on_load(PreparedCode) -> boolean() when
+ PreparedCode :: binary().
+has_prepared_code_on_load(_PreparedCode) ->
+ erlang:nif_error(undefined).
+
%% hibernate/3
-spec erlang:hibernate(Module, Function, Args) -> no_return() when
Module :: module(),
@@ -1387,6 +1356,7 @@ convert_time_unit(Time, FromUnit, ToUnit) ->
try
FU = case FromUnit of
native -> erts_internal:time_unit();
+ perf_counter -> erts_internal:perf_counter_unit();
nano_seconds -> 1000*1000*1000;
micro_seconds -> 1000*1000;
milli_seconds -> 1000;
@@ -1395,6 +1365,7 @@ convert_time_unit(Time, FromUnit, ToUnit) ->
end,
TU = case ToUnit of
native -> erts_internal:time_unit();
+ perf_counter -> erts_internal:perf_counter_unit();
nano_seconds -> 1000*1000*1000;
micro_seconds -> 1000*1000;
milli_seconds -> 1000;
@@ -1473,8 +1444,16 @@ processes() ->
%% purge_module/1
-spec purge_module(Module) -> true when
Module :: atom().
-purge_module(_Module) ->
- erlang:nif_error(undefined).
+purge_module(Module) when erlang:is_atom(Module) ->
+ case erts_code_purger:purge(Module) of
+ {false, _} ->
+ erlang:error(badarg, [Module]);
+ {true, _} ->
+ true
+ end;
+purge_module(Arg) ->
+ erlang:error(badarg, [Arg]).
+
%% put/2
-spec put(Key, Val) -> term() when
@@ -2036,12 +2015,21 @@ nodes(_Arg) ->
| eof
| {parallelism, Boolean :: boolean()}
| hide.
-open_port(_PortName,_PortSettings) ->
- erlang:nif_error(undefined).
+open_port(PortName, PortSettings) ->
+ case case erts_internal:open_port(PortName, PortSettings) of
+ Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end;
+ Res -> Res
+ end of
+ Port when erlang:is_port(Port) -> Port;
+ Error -> erlang:error(Error, [PortName, PortSettings])
+ end.
-type priority_level() ::
low | normal | high | max.
+-type message_queue_data() ::
+ off_heap | on_heap | mixed.
+
-spec process_flag(trap_exit, Boolean) -> OldBoolean when
Boolean :: boolean(),
OldBoolean :: boolean();
@@ -2054,6 +2042,9 @@ open_port(_PortName,_PortSettings) ->
(min_bin_vheap_size, MinBinVHeapSize) -> OldMinBinVHeapSize when
MinBinVHeapSize :: non_neg_integer(),
OldMinBinVHeapSize :: non_neg_integer();
+ (message_queue_data, MQD) -> OldMQD when
+ MQD :: message_queue_data(),
+ OldMQD :: message_queue_data();
(priority, Level) -> OldLevel when
Level :: priority_level(),
OldLevel :: priority_level();
@@ -2080,6 +2071,7 @@ process_flag(_Flag, _Value) ->
dictionary |
error_handler |
garbage_collection |
+ garbage_collection_info |
group_leader |
heap_size |
initial_call |
@@ -2092,6 +2084,7 @@ process_flag(_Flag, _Value) ->
min_bin_vheap_size |
monitored_by |
monitors |
+ message_queue_data |
priority |
reductions |
registered_name |
@@ -2119,6 +2112,7 @@ process_flag(_Flag, _Value) ->
{dictionary, Dictionary :: [{Key :: term(), Value :: term()}]} |
{error_handler, Module :: module()} |
{garbage_collection, GCInfo :: [{atom(),non_neg_integer()}]} |
+ {garbage_collection_info, GCInfo :: [{atom(),non_neg_integer()}]} |
{group_leader, GroupLeader :: pid()} |
{heap_size, Size :: non_neg_integer()} |
{initial_call, mfa()} |
@@ -2133,6 +2127,7 @@ process_flag(_Flag, _Value) ->
{monitors,
Monitors :: [{process, Pid :: pid() |
{RegName :: atom(), Node :: node()}}]} |
+ {message_queue_data, MQD :: message_queue_data()} |
{priority, Level :: priority_level()} |
{reductions, Number :: non_neg_integer()} |
{registered_name, Atom :: atom()} |
@@ -2230,6 +2225,16 @@ spawn_opt(_Tuple) ->
(io) -> {{input, Input}, {output, Output}} when
Input :: non_neg_integer(),
Output :: non_neg_integer();
+ (microstate_accounting) -> [MSAcc_Thread] | undefined when
+ MSAcc_Thread :: #{ type => MSAcc_Thread_Type,
+ id => MSAcc_Thread_Id,
+ counters => MSAcc_Counters},
+ MSAcc_Thread_Type :: scheduler | async | aux,
+ MSAcc_Thread_Id :: non_neg_integer(),
+ MSAcc_Counters :: #{ MSAcc_Thread_State => non_neg_integer() },
+ MSAcc_Thread_State :: alloc | aux | bif | busy_wait | check_io |
+ emulator | ets | gc | gc_fullsweep | nif |
+ other | port | send | sleep | timers;
(reductions) -> {Total_Reductions,
Reductions_Since_Last_Call} when
Total_Reductions :: non_neg_integer(),
@@ -2284,6 +2289,9 @@ subtract(_,_) ->
(fullsweep_after, Number) -> OldNumber when
Number :: non_neg_integer(),
OldNumber :: non_neg_integer();
+ (microstate_accounting, Action) -> OldState when
+ Action :: true | false | reset,
+ OldState :: true | false;
(min_heap_size, MinHeapSize) -> OldMinHeapSize when
MinHeapSize :: non_neg_integer(),
OldMinHeapSize :: non_neg_integer();
@@ -2292,8 +2300,8 @@ subtract(_,_) ->
MinBinVHeapSize :: non_neg_integer(),
OldMinBinVHeapSize :: non_neg_integer();
(multi_scheduling, BlockState) -> OldBlockState when
- BlockState :: block | unblock,
- OldBlockState :: block | unblock | enabled;
+ BlockState :: block | unblock | block_normal | unblock_normal,
+ OldBlockState :: blocked | disabled | enabled;
(scheduler_bind_type, How) -> OldBindType when
How :: scheduler_bind_type() | default_bind,
OldBindType :: scheduler_bind_type();
@@ -2438,13 +2446,15 @@ tuple_to_list(_Tuple) ->
logical_processors_available |
logical_processors_online) -> unknown | pos_integer();
(machine) -> string();
+ (message_queue_data) -> message_queue_data();
(min_heap_size) -> {min_heap_size, MinHeapSize :: pos_integer()};
(min_bin_vheap_size) -> {min_bin_vheap_size,
MinBinVHeapSize :: pos_integer()};
(modified_timing_level) -> integer() | undefined;
- (multi_scheduling) -> disabled | blocked | enabled;
+ (multi_scheduling) -> disabled | blocked | blocked_normal | enabled;
(multi_scheduling_blockers) -> [Pid :: pid()];
(nif_version) -> string();
+ (normal_multi_scheduling_blockers) -> [Pid :: pid()];
(otp_release) -> string();
(os_monotonic_time_source) -> [{atom(),term()}];
(os_system_time_source) -> [{atom(),term()}];
@@ -2572,14 +2582,19 @@ spawn_monitor(M, F, A) when erlang:is_atom(M),
spawn_monitor(M, F, A) ->
erlang:error(badarg, [M,F,A]).
+
+-type spawn_opt_option() ::
+ link
+ | monitor
+ | {priority, Level :: priority_level()}
+ | {fullsweep_after, Number :: non_neg_integer()}
+ | {min_heap_size, Size :: non_neg_integer()}
+ | {min_bin_vheap_size, VSize :: non_neg_integer()}
+ | {message_queue_data, MQD :: message_queue_data()}.
+
-spec spawn_opt(Fun, Options) -> pid() | {pid(), reference()} when
Fun :: function(),
- Options :: [Option],
- Option :: link | monitor
- | {priority, Level :: priority_level()}
- | {fullsweep_after, Number :: non_neg_integer()}
- | {min_heap_size, Size :: non_neg_integer()}
- | {min_bin_vheap_size, VSize :: non_neg_integer()}.
+ Options :: [spawn_opt_option()].
spawn_opt(F, O) when erlang:is_function(F) ->
spawn_opt(erlang, apply, [F, []], O);
spawn_opt({M,F}=MF, O) when erlang:is_atom(M), erlang:is_atom(F) ->
@@ -2592,12 +2607,7 @@ spawn_opt(F, O) ->
-spec spawn_opt(Node, Fun, Options) -> pid() | {pid(), reference()} when
Node :: node(),
Fun :: function(),
- Options :: [Option],
- Option :: link | monitor
- | {priority, Level :: priority_level()}
- | {fullsweep_after, Number :: non_neg_integer()}
- | {min_heap_size, Size :: non_neg_integer()}
- | {min_bin_vheap_size, VSize :: non_neg_integer()}.
+ Options :: [spawn_opt_option()].
spawn_opt(N, F, O) when N =:= erlang:node() ->
spawn_opt(F, O);
spawn_opt(N, F, O) when erlang:is_function(F) ->
@@ -2684,12 +2694,7 @@ spawn_link(N,M,F,A) ->
Module :: module(),
Function :: atom(),
Args :: [term()],
- Options :: [Option],
- Option :: link | monitor
- | {priority, Level :: priority_level()}
- | {fullsweep_after, Number :: non_neg_integer()}
- | {min_heap_size, Size :: non_neg_integer()}
- | {min_bin_vheap_size, VSize :: non_neg_integer()}.
+ Options :: [spawn_opt_option()].
spawn_opt(M, F, A, Opts) ->
case catch erlang:spawn_opt({M,F,A,Opts}) of
{'EXIT',{Reason,_}} ->
@@ -2704,12 +2709,7 @@ spawn_opt(M, F, A, Opts) ->
Module :: module(),
Function :: atom(),
Args :: [term()],
- Options :: [Option],
- Option :: link | monitor
- | {priority, Level :: priority_level()}
- | {fullsweep_after, Number :: non_neg_integer()}
- | {min_heap_size, Size :: non_neg_integer()}
- | {min_bin_vheap_size, VSize :: non_neg_integer()}.
+ Options :: [spawn_opt_option()].
spawn_opt(N, M, F, A, O) when N =:= erlang:node(),
erlang:is_atom(M), erlang:is_atom(F),
erlang:is_list(A), erlang:is_list(O) ->
diff --git a/erts/preloaded/src/erts.app.src b/erts/preloaded/src/erts.app.src
index 8442aaf7e8..e53b6e5bab 100644
--- a/erts/preloaded/src/erts.app.src
+++ b/erts/preloaded/src/erts.app.src
@@ -27,6 +27,7 @@
erts_internal,
init,
otp_ring0,
+ erts_code_purger,
prim_eval,
prim_file,
prim_inet,
diff --git a/erts/preloaded/src/erts_code_purger.erl b/erts/preloaded/src/erts_code_purger.erl
new file mode 100644
index 0000000000..d1e64342e0
--- /dev/null
+++ b/erts/preloaded/src/erts_code_purger.erl
@@ -0,0 +1,299 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(erts_code_purger).
+
+%% Purpose : Implement system process erts_code_purger
+%% to handle code module purging.
+
+-export([start/0, purge/1, soft_purge/1]).
+
+-spec start() -> term().
+start() ->
+ register(erts_code_purger, self()),
+ process_flag(trap_exit, true),
+ loop().
+
+loop() ->
+ _ = receive
+ {purge,Mod,From,Ref} when is_atom(Mod), is_pid(From) ->
+ Res = do_purge(Mod),
+ From ! {reply, purge, Res, Ref};
+
+ {soft_purge,Mod,From,Ref} when is_atom(Mod), is_pid(From) ->
+ Res = do_soft_purge(Mod),
+ From ! {reply, soft_purge, Res, Ref};
+
+ _Other -> ignore
+ end,
+ loop().
+
+
+%% purge(Module)
+%% Kill all processes running code from *old* Module, and then purge the
+%% module. Return {WasOld, DidKill}:
+%% {false, false} there was no old module to purge
+%% {true, false} module purged, no process killed
+%% {true, true} module purged, at least one process killed
+
+purge(Mod) when is_atom(Mod) ->
+ Ref = make_ref(),
+ erts_code_purger ! {purge, Mod, self(), Ref},
+ receive
+ {reply, purge, Result, Ref} ->
+ Result
+ end.
+
+
+do_purge(Mod) ->
+ case erts_internal:copy_literals(Mod, true) of
+ false ->
+ {false, false};
+ true ->
+ DidKill = check_proc_code(erlang:processes(), Mod, true),
+ true = erts_internal:copy_literals(Mod, false),
+ WasPurged = erts_internal:purge_module(Mod),
+ {WasPurged, DidKill}
+ end.
+
+%% soft_purge(Module)
+%% Purge old code only if no procs remain that run old code.
+%% Return true in that case, false if procs remain (in this
+%% case old code is not purged)
+
+soft_purge(Mod) ->
+ Ref = make_ref(),
+ erts_code_purger ! {soft_purge, Mod, self(), Ref},
+ receive
+ {reply, soft_purge, Result, Ref} ->
+ Result
+ end.
+
+
+do_soft_purge(Mod) ->
+ case erts_internal:copy_literals(Mod, true) of
+ false ->
+ true;
+ true ->
+ DoPurge = check_proc_code(erlang:processes(), Mod, false),
+ true = erts_internal:copy_literals(Mod, false),
+ case DoPurge of
+ false ->
+ false;
+ true ->
+ erts_internal:purge_module(Mod),
+ true
+ end
+ end.
+
+%%
+%% check_proc_code(Pids, Mod, Hard) - Send asynchronous
+%% requests to all processes to perform a check_process_code
+%% operation. Each process will check their own state and
+%% reply with the result. If 'Hard' equals
+%% - true, processes that refer 'Mod' will be killed. If
+%% any processes were killed true is returned; otherwise,
+%% false.
+%% - false, and any processes refer 'Mod', false will
+%% returned; otherwise, true.
+%%
+%% Requests will be sent to all processes identified by
+%% Pids at once, but without allowing GC to be performed.
+%% Check process code operations that are aborted due to
+%% GC need, will be restarted allowing GC. However, only
+%% ?MAX_CPC_GC_PROCS outstanding operation allowing GC at
+%% a time will be allowed. This in order not to blow up
+%% memory wise.
+%%
+%% We also only allow ?MAX_CPC_NO_OUTSTANDING_KILLS
+%% outstanding kills. This both in order to avoid flooding
+%% our message queue with 'DOWN' messages and limiting the
+%% amount of memory used to keep references to all
+%% outstanding kills.
+%%
+
+%% We maybe should allow more than two outstanding
+%% GC requests, but for now we play it safe...
+-define(MAX_CPC_GC_PROCS, 2).
+-define(MAX_CPC_NO_OUTSTANDING_KILLS, 10).
+
+-record(cpc_static, {hard, module, tag}).
+
+-record(cpc_kill, {outstanding = [],
+ no_outstanding = 0,
+ waiting = [],
+ killed = false}).
+
+check_proc_code(Pids, Mod, Hard) ->
+ Tag = erlang:make_ref(),
+ CpcS = #cpc_static{hard = Hard,
+ module = Mod,
+ tag = Tag},
+ check_proc_code(CpcS, cpc_init(CpcS, Pids, 0), 0, [], #cpc_kill{}, true).
+
+check_proc_code(#cpc_static{hard = true}, 0, 0, [],
+ #cpc_kill{outstanding = [], waiting = [], killed = Killed},
+ true) ->
+ %% No outstanding requests. We did a hard check, so result is whether or
+ %% not we killed any processes...
+ Killed;
+check_proc_code(#cpc_static{hard = false}, 0, 0, [], _KillState, Success) ->
+ %% No outstanding requests and we did a soft check...
+ Success;
+check_proc_code(#cpc_static{hard = false, tag = Tag} = CpcS, NoReq0, NoGcReq0,
+ [], _KillState, false) ->
+ %% Failed soft check; just cleanup the remaining replies corresponding
+ %% to the requests we've sent...
+ {NoReq1, NoGcReq1} = receive
+ {check_process_code, {Tag, _P, GC}, _Res} ->
+ case GC of
+ false -> {NoReq0-1, NoGcReq0};
+ true -> {NoReq0, NoGcReq0-1}
+ end
+ end,
+ check_proc_code(CpcS, NoReq1, NoGcReq1, [], _KillState, false);
+check_proc_code(#cpc_static{tag = Tag} = CpcS, NoReq0, NoGcReq0, NeedGC0,
+ KillState0, Success) ->
+
+ %% Check if we should request a GC operation
+ {NoGcReq1, NeedGC1} = case NoGcReq0 < ?MAX_CPC_GC_PROCS of
+ GcOpAllowed when GcOpAllowed == false;
+ NeedGC0 == [] ->
+ {NoGcReq0, NeedGC0};
+ _ ->
+ {NoGcReq0+1, cpc_request_gc(CpcS,NeedGC0)}
+ end,
+
+ %% Wait for a cpc reply or 'DOWN' message
+ {NoReq1, NoGcReq2, Pid, Result, KillState1} = cpc_recv(Tag,
+ NoReq0,
+ NoGcReq1,
+ KillState0),
+
+ %% Check the result of the reply
+ case Result of
+ aborted ->
+ %% Operation aborted due to the need to GC in order to
+ %% determine if the process is referring the module.
+ %% Schedule the operation for restart allowing GC...
+ check_proc_code(CpcS, NoReq1, NoGcReq2, [Pid|NeedGC1], KillState1,
+ Success);
+ false ->
+ %% Process not referring the module; done with this process...
+ check_proc_code(CpcS, NoReq1, NoGcReq2, NeedGC1, KillState1,
+ Success);
+ true ->
+ %% Process referring the module...
+ case CpcS#cpc_static.hard of
+ false ->
+ %% ... and soft check. The whole operation failed so
+ %% no point continuing; clean up and fail...
+ check_proc_code(CpcS, NoReq1, NoGcReq2, [], KillState1,
+ false);
+ true ->
+ %% ... and hard check; schedule kill of it...
+ check_proc_code(CpcS, NoReq1, NoGcReq2, NeedGC1,
+ cpc_sched_kill(Pid, KillState1), Success)
+ end;
+ 'DOWN' ->
+ %% Handled 'DOWN' message
+ check_proc_code(CpcS, NoReq1, NoGcReq2, NeedGC1,
+ KillState1, Success)
+ end.
+
+cpc_recv(Tag, NoReq, NoGcReq, #cpc_kill{outstanding = []} = KillState) ->
+ receive
+ {check_process_code, {Tag, Pid, GC}, Res} ->
+ cpc_handle_cpc(NoReq, NoGcReq, GC, Pid, Res, KillState)
+ end;
+cpc_recv(Tag, NoReq, NoGcReq,
+ #cpc_kill{outstanding = [R0, R1, R2, R3, R4 | _]} = KillState) ->
+ receive
+ {'DOWN', R, process, _, _} when R == R0;
+ R == R1;
+ R == R2;
+ R == R3;
+ R == R4 ->
+ cpc_handle_down(NoReq, NoGcReq, R, KillState);
+ {check_process_code, {Tag, Pid, GC}, Res} ->
+ cpc_handle_cpc(NoReq, NoGcReq, GC, Pid, Res, KillState)
+ end;
+cpc_recv(Tag, NoReq, NoGcReq, #cpc_kill{outstanding = [R|_]} = KillState) ->
+ receive
+ {'DOWN', R, process, _, _} ->
+ cpc_handle_down(NoReq, NoGcReq, R, KillState);
+ {check_process_code, {Tag, Pid, GC}, Res} ->
+ cpc_handle_cpc(NoReq, NoGcReq, GC, Pid, Res, KillState)
+ end.
+
+cpc_handle_down(NoReq, NoGcReq, R, #cpc_kill{outstanding = Rs,
+ no_outstanding = N} = KillState) ->
+ {NoReq, NoGcReq, undefined, 'DOWN',
+ cpc_sched_kill_waiting(KillState#cpc_kill{outstanding = cpc_list_rm(R, Rs),
+ no_outstanding = N-1})}.
+
+cpc_list_rm(R, [R|Rs]) ->
+ Rs;
+cpc_list_rm(R0, [R1|Rs]) ->
+ [R1|cpc_list_rm(R0, Rs)].
+
+cpc_handle_cpc(NoReq, NoGcReq, false, Pid, Res, KillState) ->
+ {NoReq-1, NoGcReq, Pid, Res, KillState};
+cpc_handle_cpc(NoReq, NoGcReq, true, Pid, Res, KillState) ->
+ {NoReq, NoGcReq-1, Pid, Res, KillState}.
+
+cpc_sched_kill_waiting(#cpc_kill{waiting = []} = KillState) ->
+ KillState;
+cpc_sched_kill_waiting(#cpc_kill{outstanding = Rs,
+ no_outstanding = N,
+ waiting = [P|Ps]} = KillState) ->
+ R = erlang:monitor(process, P),
+ exit(P, kill),
+ KillState#cpc_kill{outstanding = [R|Rs],
+ no_outstanding = N+1,
+ waiting = Ps,
+ killed = true}.
+
+cpc_sched_kill(Pid, #cpc_kill{no_outstanding = N, waiting = Pids} = KillState)
+ when N >= ?MAX_CPC_NO_OUTSTANDING_KILLS ->
+ KillState#cpc_kill{waiting = [Pid|Pids]};
+cpc_sched_kill(Pid,
+ #cpc_kill{outstanding = Rs, no_outstanding = N} = KillState) ->
+ R = erlang:monitor(process, Pid),
+ exit(Pid, kill),
+ KillState#cpc_kill{outstanding = [R|Rs],
+ no_outstanding = N+1,
+ killed = true}.
+
+cpc_request(#cpc_static{tag = Tag, module = Mod}, Pid, AllowGc) ->
+ erts_internal:check_process_code(Pid, Mod, [{async, {Tag, Pid, AllowGc}},
+ {allow_gc, AllowGc},
+ {copy_literals, true}]).
+
+cpc_request_gc(CpcS, [Pid|Pids]) ->
+ cpc_request(CpcS, Pid, true),
+ Pids.
+
+cpc_init(_CpcS, [], NoReqs) ->
+ NoReqs;
+cpc_init(CpcS, [Pid|Pids], NoReqs) ->
+ cpc_request(CpcS, Pid, false),
+ cpc_init(CpcS, Pids, NoReqs+1).
+
+% end of check_proc_code() implementation.
diff --git a/erts/preloaded/src/erts_internal.erl b/erts/preloaded/src/erts_internal.erl
index 6db77a8482..330fcc4a9c 100644
--- a/erts/preloaded/src/erts_internal.erl
+++ b/erts/preloaded/src/erts_internal.erl
@@ -31,8 +31,8 @@
-export([await_port_send_result/3]).
-export([cmp_term/2]).
--export([map_to_tuple_keys/1, map_type/1, map_hashmap_children/1]).
--export([port_command/3, port_connect/2, port_close/1,
+-export([map_to_tuple_keys/1, term_type/1, map_hashmap_children/1]).
+-export([open_port/2, port_command/3, port_connect/2, port_close/1,
port_control/3, port_call/3, port_info/1, port_info/2]).
-export([system_check/1,
@@ -40,16 +40,24 @@
-export([request_system_task/3]).
--export([check_process_code/2]).
+-export([check_process_code/3]).
+-export([copy_literals/2]).
+-export([purge_module/1]).
-export([flush_monitor_messages/3]).
-export([await_result/1, gather_io_bytes/2]).
--export([time_unit/0]).
+-export([time_unit/0, perf_counter_unit/0]).
-export([is_system_process/1]).
+-export([await_microstate_accounting_modifications/3,
+ gather_microstate_accounting_result/2]).
+
+%% Auto-import name clash
+-export([check_process_code/2]).
+
%%
%% Await result of send to port
%%
@@ -91,6 +99,13 @@ gather_io_bytes(Ref, No, InAcc, OutAcc) ->
%% Statically linked port NIFs
%%
+-spec erts_internal:open_port(PortName, PortSettings) -> Result when
+ PortName :: tuple(),
+ PortSettings :: term(),
+ Result :: port() | reference() | atom().
+open_port(_PortName, _PortSettings) ->
+ erlang:nif_error(undefined).
+
-spec erts_internal:port_command(Port, Data, OptionList) -> Result when
Port :: port() | atom(),
Data :: iodata(),
@@ -187,17 +202,86 @@ port_info(_Result, _Item) ->
-spec request_system_task(Pid, Prio, Request) -> 'ok' when
Prio :: 'max' | 'high' | 'normal' | 'low',
Request :: {'garbage_collect', term()}
- | {'check_process_code', term(), module(), boolean()},
+ | {'check_process_code', term(), module(), non_neg_integer()},
Pid :: pid().
request_system_task(_Pid, _Prio, _Request) ->
erlang:nif_error(undefined).
--spec check_process_code(Module, OptionList) -> boolean() when
+-define(ERTS_CPC_ALLOW_GC, (1 bsl 0)).
+-define(ERTS_CPC_COPY_LITERALS, (1 bsl 1)).
+
+-spec check_process_code(Module, Flags) -> boolean() when
+ Module :: module(),
+ Flags :: non_neg_integer().
+check_process_code(_Module, _Flags) ->
+ erlang:nif_error(undefined).
+
+-spec check_process_code(Pid, Module, OptionList) -> CheckResult | async when
+ Pid :: pid(),
+ Module :: module(),
+ RequestId :: term(),
+ Option :: {async, RequestId} | {allow_gc, boolean()} | {copy_literals, boolean()},
+ OptionList :: [Option],
+ CheckResult :: boolean() | aborted.
+check_process_code(Pid, Module, OptionList) ->
+ {Async, Flags} = get_cpc_opts(OptionList, sync, ?ERTS_CPC_ALLOW_GC),
+ case Async of
+ {async, ReqId} ->
+ {priority, Prio} = erlang:process_info(erlang:self(),
+ priority),
+ erts_internal:request_system_task(Pid,
+ Prio,
+ {check_process_code,
+ ReqId,
+ Module,
+ Flags}),
+ async;
+ sync ->
+ case Pid == erlang:self() of
+ true ->
+ erts_internal:check_process_code(Module, Flags);
+ false ->
+ {priority, Prio} = erlang:process_info(erlang:self(),
+ priority),
+ ReqId = erlang:make_ref(),
+ erts_internal:request_system_task(Pid,
+ Prio,
+ {check_process_code,
+ ReqId,
+ Module,
+ Flags}),
+ receive
+ {check_process_code, ReqId, CheckResult} ->
+ CheckResult
+ end
+ end
+ end.
+
+% gets async and flag opts and verify valid option list
+get_cpc_opts([{async, _ReqId} = AsyncTuple | Options], _OldAsync, Flags) ->
+ get_cpc_opts(Options, AsyncTuple, Flags);
+get_cpc_opts([{allow_gc, AllowGC} | Options], Async, Flags) ->
+ get_cpc_opts(Options, Async, cpc_flags(Flags, ?ERTS_CPC_ALLOW_GC, AllowGC));
+get_cpc_opts([{copy_literals, CopyLit} | Options], Async, Flags) ->
+ get_cpc_opts(Options, Async, cpc_flags(Flags, ?ERTS_CPC_COPY_LITERALS, CopyLit));
+get_cpc_opts([], Async, Flags) ->
+ {Async, Flags}.
+
+cpc_flags(OldFlags, Bit, true) ->
+ OldFlags bor Bit;
+cpc_flags(OldFlags, Bit, false) ->
+ OldFlags band (bnot Bit).
+
+-spec copy_literals(Module,Bool) -> 'true' | 'false' | 'aborted' when
Module :: module(),
- Option :: {allow_gc, boolean()},
- OptionList :: [Option].
-check_process_code(_Module, _OptionList) ->
+ Bool :: boolean().
+copy_literals(_Mod, _Bool) ->
+ erlang:nif_error(undefined).
+
+-spec purge_module(Module) -> boolean() when
+ Module :: module().
+purge_module(_Module) ->
erlang:nif_error(undefined).
-spec system_check(Type) -> 'ok' when
@@ -235,12 +319,18 @@ cmp_term(_A,_B) ->
map_to_tuple_keys(_M) ->
erlang:nif_error(undefined).
-%% return the internal map type
--spec map_type(M) -> Type when
- M :: map(),
- Type :: 'flatmap' | 'hashmap' | 'hashmap_node'.
-
-map_type(_M) ->
+%% return the internal term type
+-spec term_type(T) -> Type when
+ T :: term(),
+ Type :: 'flatmap' | 'hashmap' | 'hashmap_node'
+ | 'fixnum' | 'bignum' | 'hfloat'
+ | 'list' | 'tuple' | 'export' | 'fun'
+ | 'refc_binary' | 'heap_binary' | 'sub_binary'
+ | 'reference' | 'external_reference'
+ | 'pid' | 'external_pid' | 'port' | 'external_port'
+ | 'atom' | 'catch' | 'nil'.
+
+term_type(_T) ->
erlang:nif_error(undefined).
%% return the internal hashmap sub-nodes from
@@ -278,8 +368,38 @@ flush_monitor_messages(Ref, Multi, Res) when is_reference(Ref) ->
time_unit() ->
erlang:nif_error(undefined).
+-spec erts_internal:perf_counter_unit() -> pos_integer().
+
+perf_counter_unit() ->
+ erlang:nif_error(undefined).
+
-spec erts_internal:is_system_process(Pid) -> boolean() when
Pid :: pid().
is_system_process(_Pid) ->
erlang:nif_error(undefined).
+
+-spec await_microstate_accounting_modifications(Ref, Result, Threads) -> boolean() when
+ Ref :: reference(),
+ Result :: boolean(),
+ Threads :: pos_integer().
+
+await_microstate_accounting_modifications(Ref, Result, Threads) ->
+ _ = microstate_accounting(Ref,Threads),
+ Result.
+
+-spec gather_microstate_accounting_result(Ref, Threads) -> [#{}] when
+ Ref :: reference(),
+ Threads :: pos_integer().
+
+gather_microstate_accounting_result(Ref, Threads) ->
+ microstate_accounting(Ref, Threads).
+
+microstate_accounting(_Ref, 0) ->
+ [];
+microstate_accounting(Ref, Threads) ->
+ receive
+ Ref -> microstate_accounting(Ref, Threads - 1);
+ {Ref, Res} ->
+ [Res | microstate_accounting(Ref, Threads - 1)]
+ end.
diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl
index 0ad5824ad1..ed65c57c0d 100644
--- a/erts/preloaded/src/init.erl
+++ b/erts/preloaded/src/init.erl
@@ -23,7 +23,6 @@
%% a local file or distributed from another erlang node.
%%
%% Flags:
-%% -id Identity : identity of the system.
%% -boot File : Absolute file name of the boot script.
%% -boot_var Var Value
%% : $Var in the boot script is expanded to
@@ -75,6 +74,19 @@
subscribed = []}).
-type state() :: #state{}.
+%% Data for eval_script/2.
+-record(es,
+ {init,
+ debug,
+ path,
+ pa,
+ pz,
+ path_choice,
+ prim_load,
+ load_mode,
+ vars
+ }).
+
-define(ON_LOAD_HANDLER, init__boot__on_load_handler).
debug(false, _) -> ok;
@@ -169,8 +181,7 @@ boot(BootArgs) ->
process_flag(trap_exit, true),
{Start0,Flags,Args} = parse_boot_args(BootArgs),
Start = map(fun prepare_run_args/1, Start0),
- Flags0 = flags_to_atoms_again(Flags),
- boot(Start,Flags0,Args).
+ boot(Start, Flags, Args).
prepare_run_args({eval, [Expr]}) ->
{eval,Expr};
@@ -202,16 +213,6 @@ map(_F, []) ->
map(F, [X|Rest]) ->
[F(X) | map(F, Rest)].
-flags_to_atoms_again([]) ->
- [];
-flags_to_atoms_again([{F0,L0}|Rest]) ->
- L = L0,
- F = b2a(F0),
- [{F,L}|flags_to_atoms_again(Rest)];
-flags_to_atoms_again([{F0}|Rest]) ->
- F = b2a(F0),
- [{F}|flags_to_atoms_again(Rest)].
-
-spec code_path_choice() -> 'relaxed' | 'strict'.
code_path_choice() ->
case get_argument(code_path_choice) of
@@ -337,7 +338,7 @@ boot_loop(BootPid, State) ->
end.
ensure_loaded(Module, Loaded) ->
- File = concat([Module,objfile_extension()]),
+ File = atom_to_list(Module) ++ objfile_extension(),
case catch load_mod(Module,File) of
{ok, FullName} ->
{{module, Module}, [{Module, FullName}|Loaded]};
@@ -451,9 +452,9 @@ do_handle_msg(Msg,State) ->
%%% -------------------------------------------------
make_permanent(Boot,Config,Flags0,State) ->
- case set_flag('-boot',Boot,Flags0) of
+ case set_flag(boot, Boot, Flags0) of
{ok,Flags1} ->
- case set_flag('-config',Config,Flags1) of
+ case set_flag(config, Config, Flags1) of
{ok,Flags} ->
{ok,State#state{flags = Flags}};
Error ->
@@ -635,9 +636,9 @@ unload(_) ->
do_unload(sub([heart|erlang:pre_loaded()],erlang:loaded())).
do_unload([M|Mods]) ->
- catch erlang:purge_module(M),
+ catch erts_internal:purge_module(M),
catch erlang:delete_module(M),
- catch erlang:purge_module(M),
+ catch erts_internal:purge_module(M),
do_unload(Mods);
do_unload([]) ->
purge_all_hipe_refs(),
@@ -691,17 +692,15 @@ sleep(T) -> receive after T -> ok end.
%%% The loader shall run for ever!
%%% -------------------------------------------------
-start_prim_loader(Init,Id,Pgm,Nodes,Path,{Pa,Pz}) ->
- case erl_prim_loader:start(Id,Pgm,Nodes) of
- {ok,Pid} when Path =:= false ->
- InitPath = append(Pa,["."|Pz]),
- erl_prim_loader:set_path(InitPath),
- add_to_kernel(Init,Pid),
- Pid;
+start_prim_loader(Init, Path0, {Pa,Pz}) ->
+ Path = case Path0 of
+ false -> Pa ++ ["."|Pz];
+ _ -> Path0
+ end,
+ case erl_prim_loader:start() of
{ok,Pid} ->
erl_prim_loader:set_path(Path),
- add_to_kernel(Init,Pid),
- Pid;
+ add_to_kernel(Init, Pid);
{error,Reason} ->
erlang:display({"cannot start loader",Reason}),
exit(Reason)
@@ -715,13 +714,6 @@ add_to_kernel(Init,Pid) ->
ok
end.
-prim_load_flags(Flags) ->
- PortPgm = get_flag('-loader',Flags,<<"efile">>),
- Hosts = get_flag_list('-hosts', Flags, []),
- Id = get_flag('-id',Flags,none),
- Path = get_flag_list('-path',Flags,false),
- {PortPgm, Hosts, Id, Path}.
-
%%% -------------------------------------------------
%%% The boot process fetches a boot script and loads
%%% all modules specified and starts spec. processes.
@@ -734,24 +726,23 @@ do_boot(Flags,Start) ->
do_boot(Init,Flags,Start) ->
process_flag(trap_exit,true),
- {Pgm0,Nodes,Id,Path} = prim_load_flags(Flags),
- Root = b2s(get_flag('-root',Flags)),
- PathFls = path_flags(Flags),
- Pgm = b2s(Pgm0),
- _Pid = start_prim_loader(Init,b2a(Id),Pgm,bs2as(Nodes),
- bs2ss(Path),PathFls),
+ Root = get_root(Flags),
+ Path = get_flag_list(path, Flags, false),
+ {Pa,Pz} = PathFls = path_flags(Flags),
+ start_prim_loader(Init, bs2ss(Path), PathFls),
BootFile = bootfile(Flags,Root),
BootList = get_boot(BootFile,Root),
- LoadMode = b2a(get_flag('-mode',Flags,false)),
- Deb = b2a(get_flag('-init_debug',Flags,false)),
+ LoadMode = b2a(get_flag(mode, Flags, false)),
+ Deb = b2a(get_flag(init_debug, Flags, false)),
catch ?ON_LOAD_HANDLER ! {init_debug_flag,Deb},
- BootVars = get_flag_args('-boot_var',Flags),
- ParallelLoad =
- (Pgm =:= "efile") and (erlang:system_info(thread_pool_size) > 0),
+ BootVars = get_boot_vars(Root, Flags),
PathChoice = code_path_choice(),
- eval_script(BootList,Init,PathFls,{Root,BootVars},Path,
- {true,LoadMode,ParallelLoad},Deb,PathChoice),
+ Es = #es{init=Init,debug=Deb,path=Path,pa=Pa,pz=Pz,
+ path_choice=PathChoice,
+ prim_load=true,load_mode=LoadMode,
+ vars=BootVars},
+ eval_script(BootList, Es),
%% To help identifying Purify windows that pop up,
%% print the node name into the Purify log.
@@ -759,21 +750,43 @@ do_boot(Init,Flags,Start) ->
start_em(Start).
+get_root(Flags) ->
+ case get_argument(root, Flags) of
+ {ok,[[Root]]} ->
+ Root;
+ _ ->
+ exit(no_or_multiple_root_variables)
+ end.
+
+get_boot_vars(Root, Flags) ->
+ BootVars = get_boot_vars_1(#{}, Flags),
+ RootKey = <<"ROOT">>,
+ BootVars#{RootKey=>Root}.
+
+get_boot_vars_1(Vars, [{boot_var,[Key,Value]}|T]) ->
+ get_boot_vars_1(Vars#{Key=>Value}, T);
+get_boot_vars_1(_, [{boot_var,_}|_]) ->
+ exit(invalid_boot_var_argument);
+get_boot_vars_1(Vars, [_|T]) ->
+ get_boot_vars_1(Vars, T);
+get_boot_vars_1(Vars, []) ->
+ Vars.
+
bootfile(Flags,Root) ->
- b2s(get_flag('-boot',Flags,concat([Root,"/bin/start"]))).
+ b2s(get_flag(boot, Flags, Root++"/bin/start")).
path_flags(Flags) ->
- Pa = append(reverse(get_flag_args('-pa',Flags))),
- Pz = append(get_flag_args('-pz',Flags)),
+ Pa = append(reverse(get_flag_args(pa, Flags))),
+ Pz = append(get_flag_args(pz, Flags)),
{bs2ss(Pa),bs2ss(Pz)}.
get_boot(BootFile0,Root) ->
- BootFile = concat([BootFile0,".boot"]),
+ BootFile = BootFile0 ++ ".boot",
case get_boot(BootFile) of
{ok, CmdList} ->
CmdList;
not_found -> %% Check for default.
- BootF = concat([Root,"/bin/",BootFile]),
+ BootF = Root ++ "/bin/" ++ BootFile,
case get_boot(BootF) of
{ok, CmdList} ->
CmdList;
@@ -807,93 +820,67 @@ get_boot(BootFile) ->
%% boot process hangs (we want to ensure syncronicity).
%%
-eval_script([{progress,Info}|CfgL],Init,PathFs,Vars,P,Ph,Deb,PathChoice) ->
- debug(Deb,{progress,Info}),
+eval_script([{progress,Info}=Progress|T], #es{debug=Deb}=Es) ->
+ debug(Deb, Progress),
init ! {self(),progress,Info},
- eval_script(CfgL,Init,PathFs,Vars,P,Ph,Deb,PathChoice);
-eval_script([{preLoaded,_}|CfgL],Init,PathFs,Vars,P,Ph,Deb,PathChoice) ->
- eval_script(CfgL,Init,PathFs,Vars,P,Ph,Deb,PathChoice);
-eval_script([{path,Path}|CfgL],Init,{Pa,Pz},Vars,false,Ph,Deb,PathChoice) ->
+ eval_script(T, Es);
+eval_script([{preLoaded,_}|T], #es{}=Es) ->
+ eval_script(T, Es);
+eval_script([{path,Path}|T], #es{path=false,pa=Pa,pz=Pz,
+ path_choice=PathChoice,
+ vars=Vars}=Es) ->
RealPath0 = make_path(Pa, Pz, Path, Vars),
RealPath = patch_path(RealPath0, PathChoice),
erl_prim_loader:set_path(RealPath),
- eval_script(CfgL,Init,{Pa,Pz},Vars,false,Ph,Deb,PathChoice);
-eval_script([{path,_}|CfgL],Init,PathFs,Vars,P,Ph,Deb,PathChoice) ->
+ eval_script(T, Es);
+eval_script([{path,_}|T], #es{}=Es) ->
%% Ignore, use the command line -path flag.
- eval_script(CfgL,Init,PathFs,Vars,P,Ph,Deb,PathChoice);
-eval_script([{kernel_load_completed}|CfgL],Init,PathFs,Vars,P,{_,embedded,Par},Deb,PathChoice) ->
- eval_script(CfgL,Init,PathFs,Vars,P,{true,embedded,Par},Deb,PathChoice);
-eval_script([{kernel_load_completed}|CfgL],Init,PathFs,Vars,P,{_,E,Par},Deb,PathChoice) ->
- eval_script(CfgL,Init,PathFs,Vars,P,{false,E,Par},Deb,PathChoice);
-eval_script([{primLoad,Mods}|CfgL],Init,PathFs,Vars,P,{true,E,Par},Deb,PathChoice)
+ eval_script(T, Es);
+eval_script([{kernel_load_completed}|T], #es{load_mode=Mode}=Es0) ->
+ Es = case Mode of
+ embedded -> Es0;
+ _ -> Es0#es{prim_load=false}
+ end,
+ eval_script(T, Es);
+eval_script([{primLoad,[Mod]}|T], #es{prim_load=true}=Es) ->
+ %% Common special case (loading of error_handler). Nothing
+ %% to gain by parallel loading.
+ File = atom_to_list(Mod) ++ objfile_extension(),
+ {ok,Full} = load_mod(Mod, File),
+ init ! {self(),loaded,{Mod,Full}}, % Tell init about loaded module
+ eval_script(T, Es);
+eval_script([{primLoad,Mods}|T], #es{init=Init,prim_load=PrimLoad}=Es)
when is_list(Mods) ->
- if
- Par =:= true ->
- par_load_modules(Mods,Init);
+ case PrimLoad of
true ->
- load_modules(Mods)
+ load_modules(Mods, Init);
+ false ->
+ %% Do not load now, code_server does that dynamically!
+ ok
end,
- eval_script(CfgL,Init,PathFs,Vars,P,{true,E,Par},Deb,PathChoice);
-eval_script([{primLoad,_Mods}|CfgL],Init,PathFs,Vars,P,{false,E,Par},Deb,PathChoice) ->
- %% Do not load now, code_server does that dynamically!
- eval_script(CfgL,Init,PathFs,Vars,P,{false,E,Par},Deb,PathChoice);
-eval_script([{kernelProcess,Server,{Mod,Fun,Args}}|CfgL],Init,
- PathFs,Vars,P,Ph,Deb,PathChoice) ->
- debug(Deb,{start,Server}),
- start_in_kernel(Server,Mod,Fun,Args,Init),
- eval_script(CfgL,Init,PathFs,Vars,P,Ph,Deb,PathChoice);
-eval_script([{apply,{Mod,Fun,Args}}|CfgL],Init,PathFs,Vars,P,Ph,Deb,PathChoice) ->
- debug(Deb,{apply,{Mod,Fun,Args}}),
- apply(Mod,Fun,Args),
- eval_script(CfgL,Init,PathFs,Vars,P,Ph,Deb,PathChoice);
-eval_script([],_,_,_,_,_,_,_) ->
+ eval_script(T, Es);
+eval_script([{kernelProcess,Server,{Mod,Fun,Args}}|T],
+ #es{init=Init,debug=Deb}=Es) ->
+ debug(Deb, {start,Server}),
+ start_in_kernel(Server, Mod, Fun, Args, Init),
+ eval_script(T, Es);
+eval_script([{apply,{Mod,Fun,Args}}=Apply|T], #es{debug=Deb}=Es) ->
+ debug(Deb, Apply),
+ apply(Mod, Fun, Args),
+ eval_script(T, Es);
+eval_script([], #es{}) ->
ok;
-eval_script(What,_,_,_,_,_,_,_) ->
+eval_script(What, #es{}) ->
exit({'unexpected command in bootfile',What}).
-load_modules([Mod|Mods]) ->
- File = concat([Mod,objfile_extension()]),
+load_modules([Mod|Mods], Init) ->
+ File = atom_to_list(Mod) ++ objfile_extension(),
{ok,Full} = load_mod(Mod,File),
- init ! {self(),loaded,{Mod,Full}}, %% Tell init about loaded module
- load_modules(Mods);
-load_modules([]) ->
+ Init ! {self(),loaded,{Mod,Full}}, %Tell init about loaded module
+ load_modules(Mods, Init);
+load_modules([], _) ->
ok.
-%%% An optimization: erl_prim_loader gets the chance of loading many
-%%% files in parallel, using threads. This will reduce the seek times,
-%%% and loaded code can be processed while other threads are waiting
-%%% for the disk. The optimization is not tried unless the loader is
-%%% "efile" and there is a non-empty pool of threads.
-%%%
-%%% Many threads are needed to get a good result, so it would be
-%%% beneficial to load several applications in parallel. However,
-%%% measurements show that the file system handles one directory at a
-%%% time, regardless if parallel threads are created for files on
-%%% several directories (a guess: writing the meta information when
-%%% the file was last read ('mtime'), forces the file system to sync
-%%% between directories).
-
-par_load_modules(Mods,Init) ->
- Ext = objfile_extension(),
- ModFiles = [{Mod,concat([Mod,Ext])} || Mod <- Mods,
- not erlang:module_loaded(Mod)],
- Self = self(),
- Fun = fun(Mod, BinCode, FullName) ->
- case catch load_mod_code(Mod, BinCode, FullName) of
- {ok, _} ->
- Init ! {Self,loaded,{Mod,FullName}},
- ok;
- _EXIT ->
- {error, Mod}
- end
- end,
- case erl_prim_loader:get_files(ModFiles, Fun) of
- ok ->
- ok;
- {error,Mod} ->
- exit({'cannot load',Mod,get_files})
- end.
-
make_path(Pa, Pz, Path, Vars) ->
append([Pa,append([fix_path(Path,Vars),Pz])]).
@@ -908,34 +895,25 @@ fix_path([Path|Ps], Vars) ->
fix_path(_, _) ->
[].
-add_var("$ROOT/" ++ Path, {Root,_}) ->
- concat([Root, "/", Path]);
-add_var([$$|Path0], {_,VarList}) ->
- {Var,Path} = extract_var(Path0,[]),
- Value = b2s(get_var_value(list_to_binary(Var),VarList)),
- concat([Value, "/", Path]);
-add_var(Path, _) ->
+add_var("$"++Path0, Vars) ->
+ {Var,Path} = extract_var(Path0, []),
+ Key = list_to_binary(Var),
+ case Vars of
+ #{Key:=Value0} ->
+ Value = b2s(Value0),
+ Value ++ "/" ++ Path;
+ _ ->
+ Error0 = "cannot expand $" ++ Var ++ " in bootfile",
+ Error = list_to_atom(Error0),
+ exit(Error)
+ end;
+add_var(Path, _) ->
Path.
extract_var([$/|Path],Var) -> {reverse(Var),Path};
extract_var([H|T],Var) -> extract_var(T,[H|Var]);
extract_var([],Var) -> {reverse(Var),[]}.
-%% get_var_value(Var, [Vars]) where Vars == [atom()]
-get_var_value(Var,[Vars|VarList]) ->
- case get_var_val(Var,Vars) of
- {ok, Value} ->
- Value;
- _ ->
- get_var_value(Var,VarList)
- end;
-get_var_value(Var,[]) ->
- exit(list_to_atom(concat(["cannot expand \$", Var, " in bootfile"]))).
-
-get_var_val(Var,[Var,Value|_]) -> {ok, Value};
-get_var_val(Var,[_,_|Vars]) -> get_var_val(Var,Vars);
-get_var_val(_,_) -> false.
-
patch_path(Dirs, strict) ->
Dirs;
patch_path(Dirs, relaxed) ->
@@ -1049,18 +1027,10 @@ start_it({eval,Bin}) ->
{value, _Value, _Bs} = erl_eval:exprs(Expr, erl_eval:new_bindings()),
ok;
start_it([_|_]=MFA) ->
- Ref = make_ref(),
- case catch {Ref,case MFA of
- [M] -> M:start();
- [M,F] -> M:F();
- [M,F|Args] -> M:F(Args) % Args is a list
- end} of
- {Ref,R} ->
- R;
- {'EXIT',Reason} ->
- exit(Reason);
- Other ->
- throw(Other)
+ case MFA of
+ [M] -> M:start();
+ [M,F] -> M:F();
+ [M,F|Args] -> M:F(Args) % Args is a list
end.
%%
@@ -1102,7 +1072,7 @@ load_mod_code(Mod, BinCode, FullName) ->
%% --------------------------------------------------------
shutdown_timer(Flags) ->
- case get_flag('-shutdown_time',Flags,infinity) of
+ case get_flag(shutdown_time, Flags, infinity) of
infinity ->
self();
Time ->
@@ -1152,14 +1122,10 @@ parse_boot_args([B|Bs], Ss, Fs, As) ->
eval_arg ->
{Expr,Rest} = get_args(Bs, []),
parse_boot_args(Rest, [{eval, Expr}|Ss], Fs, As);
- flag ->
+ {flag,A} ->
{F,Rest} = get_args(Bs, []),
- Fl = case F of
- [] -> [B];
- FF -> [B,FF]
- end,
- parse_boot_args(Rest, Ss,
- [list_to_tuple(Fl)|Fs], As);
+ Fl = {A,F},
+ parse_boot_args(Rest, Ss, [Fl|Fs], As);
arg ->
parse_boot_args(Bs, Ss, Fs, [B|As]);
end_args ->
@@ -1173,12 +1139,8 @@ check(<<"-s">>) -> start_arg;
check(<<"-run">>) -> start_arg2;
check(<<"-eval">>) -> eval_arg;
check(<<"--">>) -> end_args;
-check(X) when is_binary(X) ->
- case binary_to_list(X) of
- [$-|_Rest] -> flag;
- _Chars -> arg %Even empty atoms
- end;
-check(_X) -> arg. %This should never occur
+check(<<"-",Flag/binary>>) -> {flag,b2a(Flag)};
+check(_) -> arg.
get_args([B|Bs], As) ->
case check(B) of
@@ -1187,7 +1149,7 @@ get_args([B|Bs], As) ->
start_arg2 -> {reverse(As), [B|Bs]};
eval_arg -> {reverse(As), [B|Bs]};
end_args -> {reverse(As), Bs};
- flag -> {reverse(As), [B|Bs]};
+ {flag,_} -> {reverse(As), [B|Bs]};
arg ->
get_args(Bs, [B|As])
end;
@@ -1199,44 +1161,28 @@ get_args([], As) -> {reverse(As),[]}.
%% atom() if a single arg was given.
%% list(atom()) if several args were given.
%%
-get_flag(F,Flags,Default) ->
- case catch get_flag(F,Flags) of
- {'EXIT',_} ->
- Default;
- Value ->
- Value
- end.
-
-get_flag(F,Flags) ->
- case search(F,Flags) of
- {value,{F,[V]}} ->
+get_flag(F, Flags, Default) ->
+ case lists:keyfind(F, 1, Flags) of
+ {F,[]} ->
+ true;
+ {F,[V]} ->
V;
- {value,{F,V}} ->
+ {F,V} ->
V;
- {value,{F}} -> % Flag given!
- true;
_ ->
- exit(list_to_atom(concat(["no ",F," flag"])))
+ Default
end.
%%
%% Internal get_flag function, with default value.
%% Return: list(atom())
%%
-get_flag_list(F,Flags,Default) ->
- case catch get_flag_list(F,Flags) of
- {'EXIT',_} ->
- Default;
- Value ->
- Value
- end.
-
-get_flag_list(F,Flags) ->
- case search(F,Flags) of
- {value,{F,V}} ->
+get_flag_list(F, Flags, Default) ->
+ case lists:keyfind(F, 1, Flags) of
+ {F,[_|_]=V} ->
V;
_ ->
- exit(list_to_atom(concat(["no ",F," flag"])))
+ Default
end.
%%
@@ -1246,21 +1192,15 @@ get_flag_list(F,Flags) ->
%%
get_flag_args(F,Flags) -> get_flag_args(F,Flags,[]).
-get_flag_args(F,[{F,V}|Flags],Acc) when is_list(V) ->
- get_flag_args(F,Flags,[V|Acc]);
get_flag_args(F,[{F,V}|Flags],Acc) ->
- get_flag_args(F,Flags,[[V]|Acc]);
+ get_flag_args(F,Flags,[V|Acc]);
get_flag_args(F,[_|Flags],Acc) ->
get_flag_args(F,Flags,Acc);
get_flag_args(_,[],Acc) ->
reverse(Acc).
get_arguments([{F,V}|Flags]) ->
- [$-|Fl] = atom_to_list(F),
- [{list_to_atom(Fl),to_strings(V)}|get_arguments(Flags)];
-get_arguments([{F}|Flags]) ->
- [$-|Fl] = atom_to_list(F),
- [{list_to_atom(Fl),[]}|get_arguments(Flags)];
+ [{F,to_strings(V)}|get_arguments(Flags)];
get_arguments([]) ->
[].
@@ -1268,44 +1208,26 @@ to_strings([H|T]) when is_atom(H) -> [atom_to_list(H)|to_strings(T)];
to_strings([H|T]) when is_binary(H) -> [b2s(H)|to_strings(T)];
to_strings([]) -> [].
-get_argument(Arg,Flags) ->
- Args = get_arguments(Flags),
- case get_argument1(Arg,Args) of
- [] ->
- error;
- Value ->
- {ok,Value}
+get_argument(Arg, Flags) ->
+ case get_argument1(Arg, Flags) of
+ [] -> error;
+ Value -> {ok,Value}
end.
-get_argument1(Arg,[{Arg,V}|Args]) ->
- [V|get_argument1(Arg,Args)];
-get_argument1(Arg,[_|Args]) ->
- get_argument1(Arg,Args);
-get_argument1(_,[]) ->
+get_argument1(Arg, [{Arg,V}|Args]) ->
+ [to_strings(V)|get_argument1(Arg, Args)];
+get_argument1(Arg, [_|Args]) ->
+ get_argument1(Arg, Args);
+get_argument1(_, []) ->
[].
set_argument([{Flag,_}|Flags],Flag,Value) ->
[{Flag,[Value]}|Flags];
-set_argument([{Flag}|Flags],Flag,Value) ->
- [{Flag,[Value]}|Flags];
set_argument([Item|Flags],Flag,Value) ->
[Item|set_argument(Flags,Flag,Value)];
set_argument([],Flag,Value) ->
[{Flag,[Value]}].
-concat([A|T]) when is_atom(A) ->
- atom_to_list(A) ++ concat(T);
-concat([C|T]) when is_integer(C), 0 =< C, C =< 255 ->
- [C|concat(T)];
-concat([Bin|T]) when is_binary(Bin) ->
- binary_to_list(Bin) ++ concat(T);
-concat([S|T]) ->
- S ++ concat(T);
-concat([]) ->
- [].
-
-append(L, Z) -> L ++ Z.
-
append([E]) -> E;
append([H|T]) ->
H ++ append(T);
@@ -1320,13 +1242,6 @@ reverse([A, B]) ->
reverse([A, B | L]) ->
lists:reverse(L, [B, A]). % BIF
-search(Key, [H|_T]) when is_tuple(H), element(1, H) =:= Key ->
- {value, H};
-search(Key, [_|T]) ->
- search(Key, T);
-search(_Key, []) ->
- false.
-
-spec objfile_extension() -> nonempty_string().
objfile_extension() ->
".beam".
diff --git a/erts/test/Makefile b/erts/test/Makefile
index 5263d8cd4f..a01d67e34f 100644
--- a/erts/test/Makefile
+++ b/erts/test/Makefile
@@ -54,7 +54,7 @@ RELSYSDIR = $(RELEASE_PATH)/system_test
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_COMPILE_FLAGS +=
# ----------------------------------------------------
# Targets
diff --git a/erts/test/erl_print_SUITE.erl b/erts/test/erl_print_SUITE.erl
index 3b0c083702..f0fee49024 100644
--- a/erts/test/erl_print_SUITE.erl
+++ b/erts/test/erl_print_SUITE.erl
@@ -40,7 +40,7 @@
-export([erlang_display/1, integer/1, float/1,
string/1, character/1, snprintf/1, quote/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
diff --git a/erts/test/erlc_SUITE.erl b/erts/test/erlc_SUITE.erl
index c21064fd3f..7e44be1fe0 100644
--- a/erts/test/erlc_SUITE.erl
+++ b/erts/test/erlc_SUITE.erl
@@ -27,7 +27,7 @@
compile_mib/1, good_citizen/1, deep_cwd/1, arg_overflow/1,
make_dep_options/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
diff --git a/erts/test/erlexec_SUITE.erl b/erts/test/erlexec_SUITE.erl
index 9279872d25..6440cbf0d7 100644
--- a/erts/test/erlexec_SUITE.erl
+++ b/erts/test/erlexec_SUITE.erl
@@ -38,7 +38,7 @@
-export([args_file/1, evil_args_file/1, env/1, args_file_env/1, otp_7461/1, otp_7461_remote/1, otp_8209/1, zdbbl_dist_buf_busy_limit/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
init_per_testcase(Case, Config) ->
diff --git a/erts/test/ethread_SUITE.erl b/erts/test/ethread_SUITE.erl
index 4a40dbb11e..8ad2a32278 100644
--- a/erts/test/ethread_SUITE.erl
+++ b/erts/test/ethread_SUITE.erl
@@ -51,7 +51,7 @@
atomic/1,
dw_atomic_massage/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
tests() ->
[create_join_thread,
@@ -123,38 +123,6 @@ try_lock_mutex(suite) ->
try_lock_mutex(Config) ->
run_case(Config, "try_lock_mutex", "").
-%% Remove dead code?
-
-% wd_dispatch(P) ->
-% receive
-% bye ->
-% ?line true = port_command(P, "-1 "),
-% ?line bye;
-% L when is_list(L) ->
-% ?line true = port_command(P, L),
-% ?line wd_dispatch(P)
-% end.
-%
-% watchdog(Port) ->
-% ?line process_flag(priority, max),
-% ?line receive after 500 -> ok end,
-%
-% ?line random:seed(),
-% ?line true = port_command(Port, "0 "),
-% ?line lists:foreach(fun (T) ->
-% erlang:send_after(T,
-% self(),
-% integer_to_list(T)
-% ++ " ")
-% end,
-% lists:usort(lists:map(fun (_) ->
-% random:uniform(4500)+500
-% end,
-% lists:duplicate(50,0)))),
-% ?line erlang:send_after(5100, self(), bye),
-%
-% wd_dispatch(Port).
-
cond_wait(doc) ->
["Tests ethr_cond_wait with ethr_cond_signal and ethr_cond_broadcast."];
cond_wait(suite) ->
diff --git a/erts/test/ignore_cores.erl b/erts/test/ignore_cores.erl
index 13f34cd10f..e40b91392c 100644
--- a/erts/test/ignore_cores.erl
+++ b/erts/test/ignore_cores.erl
@@ -28,7 +28,7 @@
-module(ignore_cores).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([init/1, fini/1, setup/3, setup/4, restore/1, dir/1]).
diff --git a/erts/test/install_SUITE.erl b/erts/test/install_SUITE.erl
index b380b064bd..d6df1aab6b 100644
--- a/erts/test/install_SUITE.erl
+++ b/erts/test/install_SUITE.erl
@@ -52,7 +52,7 @@
-define(DEFAULT_TIMEOUT, ?t:minutes(1)).
-define(JOIN(A,B,C), filename:join(A, B, C)).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record(inst, {mkdirs = true,
symlinks = true,
diff --git a/erts/test/nt_SUITE.erl b/erts/test/nt_SUITE.erl
index dbae8df7fe..1ddaaaaeb5 100644
--- a/erts/test/nt_SUITE.erl
+++ b/erts/test/nt_SUITE.erl
@@ -20,7 +20,7 @@
%%% Purpose: Test NT specific utilities
-module(nt_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl
index 69a0d19719..2efb5ae200 100644
--- a/erts/test/otp_SUITE.erl
+++ b/erts/test/otp_SUITE.erl
@@ -27,7 +27,7 @@
call_to_size_1/1,call_to_now_0/1,strong_components/1,
erl_file_encoding/1,xml_file_encoding/1,runtime_dependencies/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-import(lists, [filter/2,foldl/3,foreach/2]).
@@ -290,7 +290,7 @@ call_to_deprecated(Config) when is_list(Config) ->
call_to_size_1(Config) when is_list(Config) ->
%% Applications that do not call erlang:size/1:
Apps = [asn1,compiler,debugger,kernel,observer,parsetools,
- runtime_tools,stdlib,tools,webtool],
+ runtime_tools,stdlib,tools],
not_recommended_calls(Config, Apps, {erlang,size,1}).
call_to_now_0(Config) when is_list(Config) ->
@@ -298,12 +298,14 @@ call_to_now_0(Config) when is_list(Config) ->
Apps = [asn1,common_test,compiler,debugger,dialyzer,
gs,kernel,mnesia,observer,parsetools,reltool,
runtime_tools,sasl,stdlib,syntax_tools,
- test_server,tools,webtool],
+ tools],
not_recommended_calls(Config, Apps, {erlang,now,0}).
-not_recommended_calls(Config, Apps, MFA) ->
+not_recommended_calls(Config, Apps0, MFA) ->
Server = ?config(xref_server, Config),
+ Apps = [App || App <- Apps0, is_present_application(App, Server)],
+
Fs = [MFA],
Q1 = io_lib:format("E || ~p : Fun", [Fs]),
@@ -337,11 +339,28 @@ not_recommended_calls(Config, Apps, MFA) ->
end,
case CallsToMFA of
[] ->
- ok;
+ SkippedApps = ordsets:subtract(ordsets:from_list(Apps0),
+ ordsets:from_list(Apps)),
+ case SkippedApps of
+ [] ->
+ ok;
+ _ ->
+ AppStrings = [atom_to_list(A) || A <- SkippedApps],
+ Mess = io_lib:format("Application(s) not present: ~s\n",
+ [string:join(AppStrings, ", ")]),
+ {comment, Mess}
+ end;
_ ->
?t:fail({length(CallsToMFA),calls_to_size_1})
end.
+is_present_application(Name, Server) ->
+ Q = io_lib:format("~w : App", [Name]),
+ case xref:q(Server, lists:flatten(Q)) of
+ {ok,[Name]} -> true;
+ {error,_,_} -> false
+ end.
+
strong_components(Config) when is_list(Config) ->
Server = ?config(xref_server, Config),
?line {ok,Cs} = xref:q(Server, "components AE"),
@@ -440,24 +459,7 @@ runtime_dependencies(Config) ->
end,
{undefined, []},
SAE),
- [] = lists:filter(fun ({missing_runtime_dependency,
- AppFile,
- common_test}) ->
- %% The test_server app is contaminated by
- %% common_test when run in a source tree. It
- %% should however *not* be contaminated
- %% when run in an installation.
- case {filename:basename(AppFile),
- is_run_in_src_tree()} of
- {"test_server.app", true} ->
- false;
- _ ->
- true
- end;
- (_) ->
- true
- end,
- check_apps_deps([AppDep|AppDeps], IgnoreApps)),
+ check_apps_deps([AppDep|AppDeps], IgnoreApps),
case IgnoreApps of
[] ->
ok;
@@ -469,17 +471,6 @@ runtime_dependencies(Config) ->
{comment, Comment}
end.
-is_run_in_src_tree() ->
- %% At least currently run_erl is not present in <code-root>/bin
- %% in the source tree, but present in <code-root>/bin of an
- %% ordinary installation.
- case file:read_file_info(filename:join([code:root_dir(),
- "bin",
- "run_erl"])) of
- {ok, _} -> false;
- {error, _} -> true
- end.
-
have_rdep(_App, [], _Dep) ->
false;
have_rdep(App, [RDep | RDeps], Dep) ->
diff --git a/erts/test/run_erl_SUITE.erl b/erts/test/run_erl_SUITE.erl
index 328477d870..e3c563d3d9 100644
--- a/erts/test/run_erl_SUITE.erl
+++ b/erts/test/run_erl_SUITE.erl
@@ -26,7 +26,7 @@
basic/1,heavy/1,heavier/1,defunct/1]).
-export([ping_me_back/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
init_per_testcase(_Case, Config) ->
Dog = ?t:timetrap(?t:minutes(2)),
@@ -141,12 +141,10 @@ heavier_1(Config) ->
?line ToErl = open_port({spawn,"to_erl "++Pipe}, []),
io:format("ToErl = ~p\n", [ToErl]),
- X = 1,
- Y = 555,
- Z = 42,
- ?line random:seed(X, Y, Z),
- SeedCmd = lists:flatten(io_lib:format("random:seed(~p, ~p, ~p). \r\n",
- [X,Y,Z])),
+ Seed = {1,555,42},
+ rand:seed(exsplus, Seed),
+ SeedCmd = lists:flatten(io_lib:format("rand:seed(exsplus, ~p). \r\n",
+ [Seed])),
?line io:format("~p\n", [SeedCmd]),
?line erlang:port_command(ToErl, SeedCmd),
@@ -157,9 +155,9 @@ heavier_1(Config) ->
"F = fun(F,0) -> ok; "++
"(F,N) -> " ++
"io:format(\"\\\"~s\\\"~n\","++
- "[[35|[random:uniform(25)+65 || " ++
+ "[[35|[rand:uniform(25)+65 || " ++
"_ <- lists:seq(1, "++
- "random:uniform("++
+ "rand:uniform("++
integer_to_list(MaxLen)++
"))]]]), "++
"F(F,N-1) "++
@@ -189,8 +187,8 @@ receive_all(Iter, ToErl, MaxLen) ->
receive_all_1(0, _, _, _) -> ok;
receive_all_1(Iter, Line, ToErl, MaxLen) ->
- NumChars = random:uniform(MaxLen),
- Pattern = [random:uniform(25)+65 || _ <- lists:seq(1, NumChars)],
+ NumChars = rand:uniform(MaxLen),
+ Pattern = [rand:uniform(25)+65 || _ <- lists:seq(1, NumChars)],
receive_all_2(Iter, {NumChars,Pattern}, Line, ToErl, MaxLen).
diff --git a/erts/vsn.mk b/erts/vsn.mk
index a42b7d758e..6ad3680213 100644
--- a/erts/vsn.mk
+++ b/erts/vsn.mk
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2013. All Rights Reserved.
+# 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.
@@ -18,7 +18,7 @@
# %CopyrightEnd%
#
-VSN = 7.3
+VSN = 8.0
# Port number 4365 in 4.2
# Port number 4366 in 4.3
diff --git a/lib/Makefile b/lib/Makefile
index 34c2fe9a9e..82c7cb6e18 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -25,8 +25,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
ERTS_APPLICATIONS = stdlib sasl kernel compiler
# Then these have to be build
-ERLANG_APPLICATIONS = tools test_server common_test runtime_tools \
- inets parsetools
+ERLANG_APPLICATIONS = tools common_test runtime_tools inets parsetools
# These are only build if -a is given to otp_build or make is used directly
ALL_ERLANG_APPLICATIONS = xmerl edoc erl_docgen snmp otp_mibs erl_interface \
@@ -35,8 +34,8 @@ ALL_ERLANG_APPLICATIONS = xmerl edoc erl_docgen snmp otp_mibs erl_interface \
ic mnesia crypto orber os_mon syntax_tools \
public_key ssl observer odbc diameter \
cosTransactions cosEvent cosTime cosNotification \
- cosProperty cosFileTransfer cosEventDomain et megaco webtool \
- eunit ssh typer percept eldap dialyzer hipe ose
+ cosProperty cosFileTransfer cosEventDomain et megaco \
+ eunit ssh typer percept eldap dialyzer hipe
ifdef BUILD_ALL
ERLANG_APPLICATIONS += $(ALL_ERLANG_APPLICATIONS)
diff --git a/lib/asn1/c_src/Makefile b/lib/asn1/c_src/Makefile
index 2b72e1a214..e0d4f09a70 100644
--- a/lib/asn1/c_src/Makefile
+++ b/lib/asn1/c_src/Makefile
@@ -97,12 +97,7 @@ endif
_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
-ifneq ($(findstring ose,$(TARGET)),ose)
opt: $(NIF_SHARED_OBJ_FILE)
-else
-# Do not build dynamic files on OSE
-opt:
-endif
debug: opt
@@ -140,9 +135,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
-ifneq ($(findstring ose,$(TARGET)),ose)
$(INSTALL_PROGRAM) $(NIF_SHARED_OBJ_FILE) "$(RELSYSDIR)/priv/lib"
-endif
$(INSTALL_DIR) "$(RELSYSDIR)/c_src"
$(INSTALL_DATA) *.c "$(RELSYSDIR)/c_src"
diff --git a/lib/asn1/src/asn1ct_value.erl b/lib/asn1/src/asn1ct_value.erl
index 7f20d57b1e..61a5661a11 100644
--- a/lib/asn1/src/asn1ct_value.erl
+++ b/lib/asn1/src/asn1ct_value.erl
@@ -353,10 +353,7 @@ random_unnamed_bit_string(M, C) ->
%% end.
random(Upper) ->
- _ = random:seed(erlang:phash2([erlang:node()]),
- erlang:monotonic_time(),
- erlang:unique_integer()),
- random:uniform(Upper).
+ rand:uniform(Upper).
size_random(C) ->
case get_constraint(C,'SizeConstraint') of
diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl
index 6dea1787a8..7214c4b300 100644
--- a/lib/asn1/test/asn1_SUITE.erl
+++ b/lib/asn1/test/asn1_SUITE.erl
@@ -28,7 +28,7 @@
-compile(export_all).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%%------------------------------------------------------------------------------
%% Suite definition
diff --git a/lib/asn1/test/asn1_SUITE_data/test_records.erl b/lib/asn1/test/asn1_SUITE_data/test_records.erl
index adfc98600c..65716bb0dc 100644
--- a/lib/asn1/test/asn1_SUITE_data/test_records.erl
+++ b/lib/asn1/test/asn1_SUITE_data/test_records.erl
@@ -23,9 +23,6 @@
-export(['check_record_names_OTP-5812'/1]).
-%-include("test_server.hrl").
-%-include_lib("test_server/include/test_server.hrl").
-
-define(line,put(test_server_loc,{?MODULE,?LINE}),).
-include("NBAP-PDU-Discriptions.hrl").
diff --git a/lib/asn1/test/asn1_test_lib.erl b/lib/asn1/test/asn1_test_lib.erl
index ae2e5641ec..dbb2600b41 100644
--- a/lib/asn1/test/asn1_test_lib.erl
+++ b/lib/asn1/test/asn1_test_lib.erl
@@ -26,7 +26,7 @@
parallel/0,
roundtrip/3,roundtrip/4,roundtrip_enc/3,roundtrip_enc/4]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
run_dialyzer() ->
false.
diff --git a/lib/asn1/test/error_SUITE.erl b/lib/asn1/test/error_SUITE.erl
index a3413d1b3d..caae845592 100644
--- a/lib/asn1/test/error_SUITE.erl
+++ b/lib/asn1/test/error_SUITE.erl
@@ -27,7 +27,7 @@
object_sets/1,parameterization/1,
syntax/1,table_constraints/1,tags/1,values/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks, [ts_install_cth]}].
diff --git a/lib/asn1/test/h323test.erl b/lib/asn1/test/h323test.erl
index 39097a9330..566abd9714 100644
--- a/lib/asn1/test/h323test.erl
+++ b/lib/asn1/test/h323test.erl
@@ -21,7 +21,7 @@
-module(h323test).
-export([run/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
run(per) -> run();
run(_Rules) -> ok.
diff --git a/lib/asn1/test/syntax_SUITE.erl b/lib/asn1/test/syntax_SUITE.erl
index 2c23416433..a354b75062 100644
--- a/lib/asn1/test/syntax_SUITE.erl
+++ b/lib/asn1/test/syntax_SUITE.erl
@@ -33,7 +33,7 @@
types/1,
values/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks, [ts_install_cth]}].
diff --git a/lib/asn1/test/testChoExtension.erl b/lib/asn1/test/testChoExtension.erl
index 33515403d1..f4dc00b33c 100644
--- a/lib/asn1/test/testChoExtension.erl
+++ b/lib/asn1/test/testChoExtension.erl
@@ -22,7 +22,7 @@
-export([extension/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
extension(_Rules) ->
diff --git a/lib/asn1/test/testChoExternal.erl b/lib/asn1/test/testChoExternal.erl
index 980b837475..fd9bcf4406 100644
--- a/lib/asn1/test/testChoExternal.erl
+++ b/lib/asn1/test/testChoExternal.erl
@@ -21,7 +21,7 @@
-module(testChoExternal).
-export([external/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("External.hrl").
external(_Rules) ->
diff --git a/lib/asn1/test/testChoPrim.erl b/lib/asn1/test/testChoPrim.erl
index abf3fcdb81..14518285aa 100644
--- a/lib/asn1/test/testChoPrim.erl
+++ b/lib/asn1/test/testChoPrim.erl
@@ -23,7 +23,7 @@
-export([bool/1]).
-export([int/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
bool(Rules) ->
roundtrip('ChoCon', {bool0,true}),
diff --git a/lib/asn1/test/testChoRecursive.erl b/lib/asn1/test/testChoRecursive.erl
index a307d448ed..040aeabe48 100644
--- a/lib/asn1/test/testChoRecursive.erl
+++ b/lib/asn1/test/testChoRecursive.erl
@@ -23,7 +23,7 @@
-export([recursive/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('ChoRec_something',{a, b, c}).
-record('ChoRec2_something',{a, b, c}).
diff --git a/lib/asn1/test/testChoTypeRefCho.erl b/lib/asn1/test/testChoTypeRefCho.erl
index 378a43fa59..b0a9fd68bd 100644
--- a/lib/asn1/test/testChoTypeRefCho.erl
+++ b/lib/asn1/test/testChoTypeRefCho.erl
@@ -22,7 +22,7 @@
-export([choice/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
choice(_Rules) ->
roundtrip('ChoTRcho', {choCho,{choInt,88}}),
diff --git a/lib/asn1/test/testChoTypeRefPrim.erl b/lib/asn1/test/testChoTypeRefPrim.erl
index 3541277674..59d23a8683 100644
--- a/lib/asn1/test/testChoTypeRefPrim.erl
+++ b/lib/asn1/test/testChoTypeRefPrim.erl
@@ -22,7 +22,7 @@
-export([prim/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
prim(_Rules) ->
roundtrip('ChoTR', {bool,true}),
diff --git a/lib/asn1/test/testChoTypeRefSeq.erl b/lib/asn1/test/testChoTypeRefSeq.erl
index c582d6f0fc..87c94fc888 100644
--- a/lib/asn1/test/testChoTypeRefSeq.erl
+++ b/lib/asn1/test/testChoTypeRefSeq.erl
@@ -22,7 +22,7 @@
-export([seq/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('ChoSeq', {seqInt, seqOs}).
-record('ChoSeqImp', {seqInt, seqOs}).
diff --git a/lib/asn1/test/testChoTypeRefSet.erl b/lib/asn1/test/testChoTypeRefSet.erl
index 2d4f6cce4b..d2ff48af91 100644
--- a/lib/asn1/test/testChoTypeRefSet.erl
+++ b/lib/asn1/test/testChoTypeRefSet.erl
@@ -22,7 +22,7 @@
-export([set/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('ChoSet', {setInt, setOs}).
-record('ChoSetImp', {setInt, setOs}).
diff --git a/lib/asn1/test/testChoiceIndefinite.erl b/lib/asn1/test/testChoiceIndefinite.erl
index d796871620..f5ae3ff882 100644
--- a/lib/asn1/test/testChoiceIndefinite.erl
+++ b/lib/asn1/test/testChoiceIndefinite.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
main(per) -> ok;
main(ber) ->
diff --git a/lib/asn1/test/testConstraints.erl b/lib/asn1/test/testConstraints.erl
index 60b7994929..7da3ea3d38 100644
--- a/lib/asn1/test/testConstraints.erl
+++ b/lib/asn1/test/testConstraints.erl
@@ -23,7 +23,7 @@
-export([int_constraints/1,refed_NNL_name/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
int_constraints(Rules) ->
diff --git a/lib/asn1/test/testContextSwitchingTypes.erl b/lib/asn1/test/testContextSwitchingTypes.erl
index f1af6cf0e5..3779f61f2f 100644
--- a/lib/asn1/test/testContextSwitchingTypes.erl
+++ b/lib/asn1/test/testContextSwitchingTypes.erl
@@ -22,7 +22,7 @@
-export([test/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
test(Config) ->
ValT_1 = 'ContextSwitchingTypes':'val1-T'(),
diff --git a/lib/asn1/test/testDER.erl b/lib/asn1/test/testDER.erl
index 195d8fe5a4..edaaa12eba 100644
--- a/lib/asn1/test/testDER.erl
+++ b/lib/asn1/test/testDER.erl
@@ -22,7 +22,7 @@
-export([test/0]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
test() ->
Val = {'Set',12,{version,214},true},
diff --git a/lib/asn1/test/testDeepTConstr.erl b/lib/asn1/test/testDeepTConstr.erl
index 50291bf645..ed37df7204 100644
--- a/lib/asn1/test/testDeepTConstr.erl
+++ b/lib/asn1/test/testDeepTConstr.erl
@@ -24,7 +24,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
main(_Erule) ->
Val1 = {substrings,
diff --git a/lib/asn1/test/testDef.erl b/lib/asn1/test/testDef.erl
index c07665d097..5fa5711473 100644
--- a/lib/asn1/test/testDef.erl
+++ b/lib/asn1/test/testDef.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('Def1',{bool0,
bool1 = asn1_DEFAULT,
diff --git a/lib/asn1/test/testDoubleEllipses.erl b/lib/asn1/test/testDoubleEllipses.erl
index 8dcd979d6a..4a054a14ed 100644
--- a/lib/asn1/test/testDoubleEllipses.erl
+++ b/lib/asn1/test/testDoubleEllipses.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('Seq',{a, c}).
-record('SeqV1',{a, b}).
diff --git a/lib/asn1/test/testEnumExt.erl b/lib/asn1/test/testEnumExt.erl
index 122d198205..057fcb694b 100644
--- a/lib/asn1/test/testEnumExt.erl
+++ b/lib/asn1/test/testEnumExt.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
main(Rule) when Rule =:= per; Rule =:= uper ->
io:format("main(~p)~n",[Rule]),
diff --git a/lib/asn1/test/testINSTANCE_OF.erl b/lib/asn1/test/testINSTANCE_OF.erl
index afff05a4c5..b9079d8e95 100644
--- a/lib/asn1/test/testINSTANCE_OF.erl
+++ b/lib/asn1/test/testINSTANCE_OF.erl
@@ -21,7 +21,7 @@
-module(testINSTANCE_OF).
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
main(_Erule) ->
Int = roundtrip('Int', 3),
diff --git a/lib/asn1/test/testInfObjectClass.erl b/lib/asn1/test/testInfObjectClass.erl
index 271be63fc8..a7d0f2b6bd 100644
--- a/lib/asn1/test/testInfObjectClass.erl
+++ b/lib/asn1/test/testInfObjectClass.erl
@@ -24,7 +24,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
main(Rule) ->
%% this test is added for OTP-4591, to test that elements in decoded
diff --git a/lib/asn1/test/testMegaco.erl b/lib/asn1/test/testMegaco.erl
index b1b1c866be..61794ec02d 100644
--- a/lib/asn1/test/testMegaco.erl
+++ b/lib/asn1/test/testMegaco.erl
@@ -23,7 +23,7 @@
-export([compile/3,main/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
compile(Config, Erule, Options) ->
asn1_test_lib:compile("MEDIA-GATEWAY-CONTROL.asn", Config, [Erule|Options]),
diff --git a/lib/asn1/test/testMergeCompile.erl b/lib/asn1/test/testMergeCompile.erl
index 6bf7aaa1d6..5011c7d576 100644
--- a/lib/asn1/test/testMergeCompile.erl
+++ b/lib/asn1/test/testMergeCompile.erl
@@ -23,7 +23,7 @@
-export([main/1,mvrasn/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('InitiatingMessage',{procedureCode,criticality,value}).
-record('Iu-ReleaseCommand',{protocolIEs,protocolExtensions}).
diff --git a/lib/asn1/test/testNBAPsystem.erl b/lib/asn1/test/testNBAPsystem.erl
index e0eeb9fe0c..2a7e39597a 100644
--- a/lib/asn1/test/testNBAPsystem.erl
+++ b/lib/asn1/test/testNBAPsystem.erl
@@ -22,7 +22,7 @@
-export([compile/2,test/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('InitiatingMessage',{
procedureID, criticality, messageDiscriminator, transactionID, value}).
diff --git a/lib/asn1/test/testOpenTypeImplicitTag.erl b/lib/asn1/test/testOpenTypeImplicitTag.erl
index 01e0a5e07f..fc2f2a81e6 100644
--- a/lib/asn1/test/testOpenTypeImplicitTag.erl
+++ b/lib/asn1/test/testOpenTypeImplicitTag.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
main(_Rules) ->
roundtrip('Seq', {'Seq',<<1,1,255>>,<<1,1,255>>,12,<<1,1,255>>}),
diff --git a/lib/asn1/test/testOpt.erl b/lib/asn1/test/testOpt.erl
index 1f96331966..a15aa28f02 100644
--- a/lib/asn1/test/testOpt.erl
+++ b/lib/asn1/test/testOpt.erl
@@ -21,7 +21,7 @@
-module(testOpt).
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('Opt1',{bool0,
bool1 = asn1_NOVALUE,
diff --git a/lib/asn1/test/testParamBasic.erl b/lib/asn1/test/testParamBasic.erl
index f4a696ff38..768c5ad2fa 100644
--- a/lib/asn1/test/testParamBasic.erl
+++ b/lib/asn1/test/testParamBasic.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('T11',{number, string=asn1_DEFAULT}).
-record('T12',{number, string=asn1_DEFAULT}).
diff --git a/lib/asn1/test/testParameterizedInfObj.erl b/lib/asn1/test/testParameterizedInfObj.erl
index 592dc693f0..8b0353522d 100644
--- a/lib/asn1/test/testParameterizedInfObj.erl
+++ b/lib/asn1/test/testParameterizedInfObj.erl
@@ -23,7 +23,7 @@
-export([main/2,param/1,ranap/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('AllocationOrRetentionPriority',{priorityLevel,iE_Extensions}).
-record('ProtocolExtensionField',{id,criticality,extensionValue}).
diff --git a/lib/asn1/test/testPrim.erl b/lib/asn1/test/testPrim.erl
index dc2e0fa2e7..82da953ca1 100644
--- a/lib/asn1/test/testPrim.erl
+++ b/lib/asn1/test/testPrim.erl
@@ -28,7 +28,7 @@
-export([null/1]).
-export([real/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
bool(Rules) ->
Types = ['Bool','BoolCon','BoolPri','BoolApp',
diff --git a/lib/asn1/test/testPrimExternal.erl b/lib/asn1/test/testPrimExternal.erl
index 56252241d4..79c8a3a045 100644
--- a/lib/asn1/test/testPrimExternal.erl
+++ b/lib/asn1/test/testPrimExternal.erl
@@ -22,7 +22,7 @@
-export([external/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
external(_Rules) ->
Types = ['NT',
diff --git a/lib/asn1/test/testPrimStrings.erl b/lib/asn1/test/testPrimStrings.erl
index 46793c6bff..042b1757ba 100644
--- a/lib/asn1/test/testPrimStrings.erl
+++ b/lib/asn1/test/testPrimStrings.erl
@@ -33,7 +33,7 @@
-export([utf8_string/1]).
-export([fragmented/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
fragmented(Rules) ->
Lens = fragmented_lengths(),
@@ -54,7 +54,7 @@ fragmented_strings(Len, Types) ->
ok.
make_ns_value(0) -> [];
-make_ns_value(N) -> [($0 - 1) + random:uniform(10)|make_ns_value(N-1)].
+make_ns_value(N) -> [($0 - 1) + rand:uniform(10)|make_ns_value(N-1)].
fragmented_lengths() ->
K16 = 1 bsl 14,
diff --git a/lib/asn1/test/testRfcs.erl b/lib/asn1/test/testRfcs.erl
index 20eaee9982..fa4389b904 100644
--- a/lib/asn1/test/testRfcs.erl
+++ b/lib/asn1/test/testRfcs.erl
@@ -23,7 +23,7 @@
-export([compile/3,test/0]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
compile(Config, Erules, Options0) ->
Options = [no_ok_wrapper|Options0],
diff --git a/lib/asn1/test/testSSLspecs.erl b/lib/asn1/test/testSSLspecs.erl
index 9e51021ad2..7dc7eedd50 100644
--- a/lib/asn1/test/testSSLspecs.erl
+++ b/lib/asn1/test/testSSLspecs.erl
@@ -23,7 +23,7 @@
-export([compile/2,run/1,compile_combined/2,run_combined/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
compile(Config, Options) ->
DataDir = ?config(data_dir, Config),
diff --git a/lib/asn1/test/testSelectionTypes.erl b/lib/asn1/test/testSelectionTypes.erl
index d33cfcc694..7039f6da4e 100644
--- a/lib/asn1/test/testSelectionTypes.erl
+++ b/lib/asn1/test/testSelectionTypes.erl
@@ -21,7 +21,7 @@
-module(testSelectionTypes).
-export([test/0]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
test() ->
["Es"] = Val2 = ['SelectionType':einsteinium()],
diff --git a/lib/asn1/test/testSeq2738.erl b/lib/asn1/test/testSeq2738.erl
index 3c9e4a744e..a75d058259 100644
--- a/lib/asn1/test/testSeq2738.erl
+++ b/lib/asn1/test/testSeq2738.erl
@@ -21,7 +21,7 @@
-module(testSeq2738).
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('SeqOptFake',{int, opt = asn1_NOVALUE}).
-record('OptSeqFake',{bool = false}).
diff --git a/lib/asn1/test/testSeqDefault.erl b/lib/asn1/test/testSeqDefault.erl
index db0914bf0a..ac3cf202b7 100644
--- a/lib/asn1/test/testSeqDefault.erl
+++ b/lib/asn1/test/testSeqDefault.erl
@@ -23,7 +23,7 @@
-include("External.hrl").
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('SeqDef1',{bool1 = asn1_DEFAULT, int1, seq1 = asn1_DEFAULT}).
-record('SeqDef1Imp',{bool1 = asn1_DEFAULT, int1, seq1 = asn1_DEFAULT}).
diff --git a/lib/asn1/test/testSeqExtension.erl b/lib/asn1/test/testSeqExtension.erl
index 6b49b29047..a84b6fb27c 100644
--- a/lib/asn1/test/testSeqExtension.erl
+++ b/lib/asn1/test/testSeqExtension.erl
@@ -23,7 +23,7 @@
-include("External.hrl").
-export([main/3]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('SeqExt1',{}).
-record('SeqExt2',{bool, int}).
diff --git a/lib/asn1/test/testSeqExternal.erl b/lib/asn1/test/testSeqExternal.erl
index a48794924f..9ad2c03208 100644
--- a/lib/asn1/test/testSeqExternal.erl
+++ b/lib/asn1/test/testSeqExternal.erl
@@ -23,7 +23,7 @@
-include("External.hrl").
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('SeqXSet1',{set, bool, int}).
-record('SeqXSet2',{bool, set, int}).
diff --git a/lib/asn1/test/testSeqOf.erl b/lib/asn1/test/testSeqOf.erl
index 898b8c1e15..f4a4181f51 100644
--- a/lib/asn1/test/testSeqOf.erl
+++ b/lib/asn1/test/testSeqOf.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('Seq1',{bool1, int1, seq1 = asn1_DEFAULT}).
-record('Seq2',{seq2 = asn1_DEFAULT, bool2, int2}).
diff --git a/lib/asn1/test/testSeqOfCho.erl b/lib/asn1/test/testSeqOfCho.erl
index 82ac56ac50..7bd1ce7aa6 100644
--- a/lib/asn1/test/testSeqOfCho.erl
+++ b/lib/asn1/test/testSeqOfCho.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('SeqChoDef',{bool1, int1, seq1 = asn1_DEFAULT}).
-record('SeqChoOpt',{bool1, int1, seq1 = asn1_NOVALUE}).
diff --git a/lib/asn1/test/testSeqOfExternal.erl b/lib/asn1/test/testSeqOfExternal.erl
index 560fdecb64..de95e081d5 100644
--- a/lib/asn1/test/testSeqOfExternal.erl
+++ b/lib/asn1/test/testSeqOfExternal.erl
@@ -21,7 +21,7 @@
-module(testSeqOfExternal).
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("External.hrl").
-record('NT',{os, bool}).
diff --git a/lib/asn1/test/testSeqOfIndefinite.erl b/lib/asn1/test/testSeqOfIndefinite.erl
index 4a0101834a..bebd516c5c 100644
--- a/lib/asn1/test/testSeqOfIndefinite.erl
+++ b/lib/asn1/test/testSeqOfIndefinite.erl
@@ -22,7 +22,7 @@
-export([main/0]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
main() ->
?line ok = test(isd),
diff --git a/lib/asn1/test/testSeqOfTag.erl b/lib/asn1/test/testSeqOfTag.erl
index 55f807199f..cacbc85093 100644
--- a/lib/asn1/test/testSeqOfTag.erl
+++ b/lib/asn1/test/testSeqOfTag.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("External.hrl").
diff --git a/lib/asn1/test/testSeqOptional.erl b/lib/asn1/test/testSeqOptional.erl
index db615d6e4d..92b49e9c0d 100644
--- a/lib/asn1/test/testSeqOptional.erl
+++ b/lib/asn1/test/testSeqOptional.erl
@@ -23,7 +23,7 @@
-include("External.hrl").
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('SeqOpt1',{bool1 = asn1_NOVALUE, int1, seq1 = asn1_NOVALUE}).
-record('SeqOpt1Imp',{bool1 = asn1_NOVALUE, int1, seq1 = asn1_NOVALUE}).
diff --git a/lib/asn1/test/testSeqPrim.erl b/lib/asn1/test/testSeqPrim.erl
index 6af0ce9287..5872902ce7 100644
--- a/lib/asn1/test/testSeqPrim.erl
+++ b/lib/asn1/test/testSeqPrim.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('Seq',{bool, boolCon, boolPri, boolApp, boolExpCon, boolExpPri, boolExpApp}).
-record('Empty',{}).
diff --git a/lib/asn1/test/testSeqSetDefaultVal.erl b/lib/asn1/test/testSeqSetDefaultVal.erl
index 86ab07a4a8..1c41f64078 100644
--- a/lib/asn1/test/testSeqSetDefaultVal.erl
+++ b/lib/asn1/test/testSeqSetDefaultVal.erl
@@ -22,7 +22,7 @@
-export([main/2]).
-include("External.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('SeqInts',{a = asn1_DEFAULT,
b = asn1_DEFAULT,
diff --git a/lib/asn1/test/testSeqSetIndefinite.erl b/lib/asn1/test/testSeqSetIndefinite.erl
index 8948e10ece..41e09f7796 100644
--- a/lib/asn1/test/testSeqSetIndefinite.erl
+++ b/lib/asn1/test/testSeqSetIndefinite.erl
@@ -21,7 +21,7 @@
-module(testSeqSetIndefinite).
-export([main/0]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
main() ->
seq_indefinite(),
diff --git a/lib/asn1/test/testSeqTag.erl b/lib/asn1/test/testSeqTag.erl
index baa79ed428..6959e2f7e2 100644
--- a/lib/asn1/test/testSeqTag.erl
+++ b/lib/asn1/test/testSeqTag.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("External.hrl").
-record('SeqTag',{nt, imp, exp}).
diff --git a/lib/asn1/test/testSeqTypeRefCho.erl b/lib/asn1/test/testSeqTypeRefCho.erl
index 372be0c637..4a9ba53291 100644
--- a/lib/asn1/test/testSeqTypeRefCho.erl
+++ b/lib/asn1/test/testSeqTypeRefCho.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("External.hrl").
-record('SeqTRcho',{seqCho, seqChoE, 'seqCho-E', 'seqChoE-E'}).
diff --git a/lib/asn1/test/testSeqTypeRefPrim.erl b/lib/asn1/test/testSeqTypeRefPrim.erl
index 42554e758e..e0c3277156 100644
--- a/lib/asn1/test/testSeqTypeRefPrim.erl
+++ b/lib/asn1/test/testSeqTypeRefPrim.erl
@@ -21,7 +21,7 @@
-module(testSeqTypeRefPrim).
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('SeqTR',{octStr, octStrI, octStrE, 'octStr-I', 'octStrI-I', 'octStrE-I', 'octStr-E', 'octStrI-E', 'octStrE-E'}).
diff --git a/lib/asn1/test/testSeqTypeRefSeq.erl b/lib/asn1/test/testSeqTypeRefSeq.erl
index ee30937af5..befbe5f457 100644
--- a/lib/asn1/test/testSeqTypeRefSeq.erl
+++ b/lib/asn1/test/testSeqTypeRefSeq.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('Seq1',{bool1, int1, seq1}).
-record('Seq2',{seq2, bool2, int2}).
diff --git a/lib/asn1/test/testSeqTypeRefSet.erl b/lib/asn1/test/testSeqTypeRefSet.erl
index ba690b4503..48c94a8b06 100644
--- a/lib/asn1/test/testSeqTypeRefSet.erl
+++ b/lib/asn1/test/testSeqTypeRefSet.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('SeqTRset',{seqSet, seqSetI, seqSetE, 'seqSet-I', 'seqSetI-I', 'seqSetE-I', 'seqSet-E', 'seqSetI-E', 'seqSetE-E'}).
-record('SeqSet',{setInt, setOs}).
diff --git a/lib/asn1/test/testSetDefault.erl b/lib/asn1/test/testSetDefault.erl
index 4e34c01a52..e91a526add 100644
--- a/lib/asn1/test/testSetDefault.erl
+++ b/lib/asn1/test/testSetDefault.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('SetDef1',{bool1 = asn1_DEFAULT, int1, set1 = asn1_DEFAULT}).
-record('SetDef2',{set2 = asn1_DEFAULT, bool2, int2}).
diff --git a/lib/asn1/test/testSetExtension.erl b/lib/asn1/test/testSetExtension.erl
index 67977a2a31..89f27a7fef 100644
--- a/lib/asn1/test/testSetExtension.erl
+++ b/lib/asn1/test/testSetExtension.erl
@@ -22,7 +22,7 @@
-include("External.hrl").
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('SetExt1',{}).
-record('SetExt2',{bool, int}).
diff --git a/lib/asn1/test/testSetExternal.erl b/lib/asn1/test/testSetExternal.erl
index e265cf1f3e..f5d01e23a8 100644
--- a/lib/asn1/test/testSetExternal.erl
+++ b/lib/asn1/test/testSetExternal.erl
@@ -22,7 +22,7 @@
-export([main/1]).
-include("External.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('SetXSeq1',{seq, bool, int}).
-record('SetXSeq2',{bool, seq, int}).
diff --git a/lib/asn1/test/testSetOf.erl b/lib/asn1/test/testSetOf.erl
index 4ff90676aa..02009dc8d5 100644
--- a/lib/asn1/test/testSetOf.erl
+++ b/lib/asn1/test/testSetOf.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('Set1',{bool1, int1, set1 = asn1_DEFAULT}).
-record('Set2',{set2 = asn1_DEFAULT, bool2, int2}).
diff --git a/lib/asn1/test/testSetOfCho.erl b/lib/asn1/test/testSetOfCho.erl
index 002fa9be0a..be199b4688 100644
--- a/lib/asn1/test/testSetOfCho.erl
+++ b/lib/asn1/test/testSetOfCho.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('SetChoDef',{bool1, int1, set1 = asn1_DEFAULT}).
-record('SetChoOpt',{bool1, int1, set1 = asn1_NOVALUE}).
diff --git a/lib/asn1/test/testSetOfExternal.erl b/lib/asn1/test/testSetOfExternal.erl
index 60bde33962..7abed66167 100644
--- a/lib/asn1/test/testSetOfExternal.erl
+++ b/lib/asn1/test/testSetOfExternal.erl
@@ -21,7 +21,7 @@
-module(testSetOfExternal).
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("External.hrl").
-record('NT',{os, bool}).
diff --git a/lib/asn1/test/testSetOfTag.erl b/lib/asn1/test/testSetOfTag.erl
index 96dc9942d7..ce77e2848f 100644
--- a/lib/asn1/test/testSetOfTag.erl
+++ b/lib/asn1/test/testSetOfTag.erl
@@ -21,7 +21,7 @@
-module(testSetOfTag).
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("External.hrl").
-record('SetTagNt',{nt}).
diff --git a/lib/asn1/test/testSetPrim.erl b/lib/asn1/test/testSetPrim.erl
index a4b8bb2f09..47913178f3 100644
--- a/lib/asn1/test/testSetPrim.erl
+++ b/lib/asn1/test/testSetPrim.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('Set',{bool, boolCon, boolPri, boolApp, boolExpCon, boolExpPri, boolExpApp}).
-record('Empty',{}).
diff --git a/lib/asn1/test/testSetTag.erl b/lib/asn1/test/testSetTag.erl
index b963ecb4b3..2e95fb6793 100644
--- a/lib/asn1/test/testSetTag.erl
+++ b/lib/asn1/test/testSetTag.erl
@@ -21,7 +21,7 @@
-module(testSetTag).
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("External.hrl").
-record('SetTag',{nt, imp, exp}).
diff --git a/lib/asn1/test/testSetTypeRefCho.erl b/lib/asn1/test/testSetTypeRefCho.erl
index adffb646fb..ac5bf5ab02 100644
--- a/lib/asn1/test/testSetTypeRefCho.erl
+++ b/lib/asn1/test/testSetTypeRefCho.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("External.hrl").
-record('SetTRcho',{setCho, setChoE, 'setCho-E', 'setChoE-E'}).
diff --git a/lib/asn1/test/testSetTypeRefPrim.erl b/lib/asn1/test/testSetTypeRefPrim.erl
index e20b6c57ab..51190e2ba4 100644
--- a/lib/asn1/test/testSetTypeRefPrim.erl
+++ b/lib/asn1/test/testSetTypeRefPrim.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('SetTR',{octStr, octStrI, octStrE, 'octStr-I', 'octStrI-I', 'octStrE-I', 'octStr-E', 'octStrI-E', 'octStrE-E'}).
diff --git a/lib/asn1/test/testSetTypeRefSeq.erl b/lib/asn1/test/testSetTypeRefSeq.erl
index 0d2bd6b32d..44a7910526 100644
--- a/lib/asn1/test/testSetTypeRefSeq.erl
+++ b/lib/asn1/test/testSetTypeRefSeq.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('SetTRseq',{setSeq, setSeqI, setSeqE, 'setSeq-I', 'setSeqI-I', 'setSeqE-I', 'setSeq-E', 'setSeqI-E', 'setSeqE-E'}).
-record('SetSeq',{seqInt, seqOs}).
diff --git a/lib/asn1/test/testSetTypeRefSet.erl b/lib/asn1/test/testSetTypeRefSet.erl
index 85d9bf52cd..7a67e6434c 100644
--- a/lib/asn1/test/testSetTypeRefSet.erl
+++ b/lib/asn1/test/testSetTypeRefSet.erl
@@ -22,7 +22,7 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-record('Set1',{bool1, int1, set1}).
-record('Set2',{set2, bool2, int2}).
diff --git a/lib/asn1/test/testTCAP.erl b/lib/asn1/test/testTCAP.erl
index 6c66d73feb..6e777875f6 100644
--- a/lib/asn1/test/testTCAP.erl
+++ b/lib/asn1/test/testTCAP.erl
@@ -22,7 +22,7 @@
-export([compile/2,test/2,compile_asn1config/2,test_asn1config/0]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
compile(Config, Options) ->
Files = ["Remote-Operations-Information-Objects",
diff --git a/lib/asn1/test/testTimer.erl b/lib/asn1/test/testTimer.erl
index 30e31796e2..6fecee3d78 100644
--- a/lib/asn1/test/testTimer.erl
+++ b/lib/asn1/test/testTimer.erl
@@ -21,7 +21,7 @@
-module(testTimer).
-export([go/0]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(times, 5000).
diff --git a/lib/asn1/test/test_compile_options.erl b/lib/asn1/test/test_compile_options.erl
index 8be3a29763..1af614f49a 100644
--- a/lib/asn1/test/test_compile_options.erl
+++ b/lib/asn1/test/test_compile_options.erl
@@ -21,7 +21,7 @@
-module(test_compile_options).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([wrong_path/1,comp/2,path/1,ticket_6143/1,noobj/1,
diff --git a/lib/asn1/test/test_modified_x420.erl b/lib/asn1/test/test_modified_x420.erl
index f9a29d1436..c0a32e2a37 100644
--- a/lib/asn1/test/test_modified_x420.erl
+++ b/lib/asn1/test/test_modified_x420.erl
@@ -21,7 +21,7 @@
-module(test_modified_x420).
-export([test/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
test(Config) ->
DataDir = ?config(data_dir,Config),
diff --git a/lib/asn1/test/test_partial_incomplete_decode.erl b/lib/asn1/test/test_partial_incomplete_decode.erl
index d5eacc5a4d..64f2ce22ae 100644
--- a/lib/asn1/test/test_partial_incomplete_decode.erl
+++ b/lib/asn1/test/test_partial_incomplete_decode.erl
@@ -22,7 +22,7 @@
-export([test/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
test(Config) ->
FMsg = msg('F'),
diff --git a/lib/asn1/test/test_selective_decode.erl b/lib/asn1/test/test_selective_decode.erl
index 079351db19..d7870057a8 100644
--- a/lib/asn1/test/test_selective_decode.erl
+++ b/lib/asn1/test/test_selective_decode.erl
@@ -21,7 +21,7 @@
-module(test_selective_decode).
-export([test/0]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
test() ->
FMsg = msg('F'),
diff --git a/lib/asn1/test/test_special_decode_performance.erl b/lib/asn1/test/test_special_decode_performance.erl
index 7bb324c902..6cf7ee2805 100644
--- a/lib/asn1/test/test_special_decode_performance.erl
+++ b/lib/asn1/test/test_special_decode_performance.erl
@@ -22,7 +22,7 @@
-export([go/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
go(all) ->
{Time_S_s,Time_S_e,Time_S_c}=go(10000,'PartialDecSeq'),
diff --git a/lib/asn1/test/test_undecoded_rest.erl b/lib/asn1/test/test_undecoded_rest.erl
index 6264530fff..77147d59cc 100644
--- a/lib/asn1/test/test_undecoded_rest.erl
+++ b/lib/asn1/test/test_undecoded_rest.erl
@@ -22,7 +22,7 @@
-export([test/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% testing OTP-5104
diff --git a/lib/asn1/test/test_x691.erl b/lib/asn1/test/test_x691.erl
index 56c1b9bf71..8ef62960ff 100644
--- a/lib/asn1/test/test_x691.erl
+++ b/lib/asn1/test/test_x691.erl
@@ -21,7 +21,7 @@
-module(test_x691).
-export([cases/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
cases(Erule) ->
_ = [begin
diff --git a/lib/common_test/include/ct.hrl b/lib/common_test/include/ct.hrl
index 53bc43fc24..5806f75806 100644
--- a/lib/common_test/include/ct.hrl
+++ b/lib/common_test/include/ct.hrl
@@ -18,8 +18,6 @@
%% %CopyrightEnd%
%%
--include_lib("test_server/include/test_server.hrl").
-
%% the log level is used as argument to any CT logging function
-define(MIN_IMPORTANCE, 0 ).
-define(LOW_IMPORTANCE, 25).
@@ -37,3 +35,9 @@
%% name of process executing the CT Hook init and terminate function
-define(CT_HOOK_INIT_PROCESS, ct_util_server).
-define(CT_HOOK_TERMINATE_PROCESS, ct_util_server).
+
+%% Backward compatibility for test_server test suites.
+%% DO NOT USE IN NEW TEST SUITES.
+-define(line,).
+-define(t,test_server).
+-define(config,test_server:lookup_config).
diff --git a/lib/common_test/src/Makefile b/lib/common_test/src/Makefile
index 987345c679..91c1e8ede8 100644
--- a/lib/common_test/src/Makefile
+++ b/lib/common_test/src/Makefile
@@ -79,7 +79,15 @@ MODULES= \
cth_conn_log \
ct_groups \
ct_property_test \
- ct_release_test
+ ct_release_test \
+ erl2html2 \
+ test_server_ctrl \
+ test_server_gl \
+ test_server_io \
+ test_server_node \
+ test_server \
+ test_server_sup
+
TARGET_MODULES= $(MODULES:%=$(EBIN)/%)
BEAM_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
@@ -101,8 +109,7 @@ DTD_FILES = \
# FLAGS
# ----------------------------------------------------
ERL_COMPILE_FLAGS += -pa ../ebin -I../include -I $(ERL_TOP)/lib/snmp/include/ \
- -I../../test_server/include -I../../xmerl/inc/ \
- -I $(ERL_TOP)/lib/kernel/include -Werror
+ -I../../xmerl/inc/ -I $(ERL_TOP)/lib/kernel/include -Werror
# ----------------------------------------------------
# Targets
diff --git a/lib/common_test/src/common_test.app.src b/lib/common_test/src/common_test.app.src
index d847907d75..26bcf00824 100644
--- a/lib/common_test/src/common_test.app.src
+++ b/lib/common_test/src/common_test.app.src
@@ -53,7 +53,13 @@
ct_slave,
cth_log_redirect,
cth_conn_log,
- cth_surefire
+ cth_surefire,
+ erl2html2,
+ test_server_ctrl,
+ test_server,
+ test_server_io,
+ test_server_node,
+ test_server_sup
]},
{registered, [ct_logs,
ct_util_server,
@@ -61,13 +67,27 @@
ct_make_ref,
vts,
ct_master,
- ct_master_logs]},
+ ct_master_logs,
+ test_server_ctrl,
+ test_server,
+ test_server_break_process]},
{applications, [kernel,stdlib]},
{env, []},
- {runtime_dependencies,["xmerl-1.3.8","tools-2.8",
- "test_server-3.9","stdlib-2.5","ssh-4.0",
- "snmp-5.1.2","sasl-2.4.2","runtime_tools-1.8.16",
- "kernel-4.0","inets-6.0","erts-7.0",
- "debugger-4.1","crypto-3.6","compiler-6.0",
- "observer-2.1"]}]}.
+ {runtime_dependencies,
+ ["compiler-6.0",
+ "crypto-3.6",
+ "debugger-4.1",
+ "erts-7.0",
+ "inets-6.0",
+ "kernel-4.0",
+ "observer-2.1",
+ "runtime_tools-1.8.16",
+ "sasl-2.4.2",
+ "snmp-5.1.2",
+ "ssh-4.0",
+ "stdlib-2.5",
+ "syntax_tools-1.7",
+ "tools-2.8",
+ "xmerl-1.3.8"
+ ]}]}.
diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl
index 251204aa75..33efe7a14a 100644
--- a/lib/common_test/src/ct_config.erl
+++ b/lib/common_test/src/ct_config.erl
@@ -694,11 +694,10 @@ make_crypto_key(String) ->
{[K1,K2,K3],IVec}.
random_bytes(N) ->
- random:seed(os:timestamp()),
random_bytes_1(N, []).
random_bytes_1(0, Acc) -> Acc;
-random_bytes_1(N, Acc) -> random_bytes_1(N-1, [random:uniform(255)|Acc]).
+random_bytes_1(N, Acc) -> random_bytes_1(N-1, [rand:uniform(255)|Acc]).
check_callback_load(Callback) ->
case code:is_loaded(Callback) of
diff --git a/lib/common_test/src/ct_make.erl b/lib/common_test/src/ct_make.erl
index f4b81a0ef6..e7a9cfa843 100644
--- a/lib/common_test/src/ct_make.erl
+++ b/lib/common_test/src/ct_make.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2009-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.
@@ -324,10 +324,11 @@ check_includes(File, IncludePath, ObjMTime) ->
end.
check_includes2(Epp, File, ObjMTime) ->
+ A1 = erl_anno:new(1),
case epp:parse_erl_form(Epp) of
- {ok, {attribute, 1, file, {File, 1}}} ->
+ {ok, {attribute, A1, file, {File, A1}}} ->
check_includes2(Epp, File, ObjMTime);
- {ok, {attribute, 1, file, {IncFile, 1}}} ->
+ {ok, {attribute, A1, file, {IncFile, A1}}} ->
case file:read_file_info(IncFile) of
{ok, #file_info{mtime=MTime}} when MTime>ObjMTime ->
epp:close(Epp),
diff --git a/lib/common_test/src/ct_release_test.erl b/lib/common_test/src/ct_release_test.erl
index 5d7e945cc3..6c38f51363 100644
--- a/lib/common_test/src/ct_release_test.erl
+++ b/lib/common_test/src/ct_release_test.erl
@@ -766,7 +766,7 @@ create_relfile(AppsVsns,CreateDir,RelName0,RelVsn) ->
%% Should test tools really be included? Some library functions
%% here could be used by callback, but not everything since
%% processes of these applications will not be running.
- TestToolAppsVsns0 = get_vsns([test_server,common_test]),
+ TestToolAppsVsns0 = get_vsns([common_test]),
TestToolAppsVsns =
[{A,V,none} || {A,V} <- TestToolAppsVsns0,
false == lists:keymember(A,1,AllAppsVsns0)],
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index ceb94ceee5..e156c9b773 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -2634,11 +2634,9 @@ run_make(Targets, TestDir0, Mod, UserInclude) ->
data=TestDir}),
{ok,Cwd} = file:get_cwd(),
ok = file:set_cwd(TestDir),
- TestServerInclude = get_dir(test_server, "include"),
CtInclude = get_dir(common_test, "include"),
XmerlInclude = get_dir(xmerl, "include"),
- ErlFlags = UserInclude ++ [{i,TestServerInclude},
- {i,CtInclude},
+ ErlFlags = UserInclude ++ [{i,CtInclude},
{i,XmerlInclude},
debug_info],
Result =
diff --git a/lib/test_server/src/erl2html2.erl b/lib/common_test/src/erl2html2.erl
index e69383acea..d440d0940d 100644
--- a/lib/test_server/src/erl2html2.erl
+++ b/lib/common_test/src/erl2html2.erl
@@ -170,23 +170,32 @@ get_line(Anno) ->
%%%-----------------------------------------------------------------
%%% Find the line number of the last expression in the function
find_clause_lines([{clause,CL,_Params,_Op,Exprs}], CLs) -> % last clause
- try tuple_to_list(lists:last(Exprs)) of
- [_Type,ExprLine | _] when is_integer(ExprLine) ->
- {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(ExprLine)};
- [tree,_ | Exprs1] ->
+ case classify_exprs(Exprs) of
+ {anno, Anno} ->
+ {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(Anno)};
+ {tree, Exprs1} ->
find_clause_lines([{clause,CL,undefined,undefined,Exprs1}], CLs);
- [macro,{_var,ExprLine,_MACRO} | _] when is_integer(ExprLine) ->
- {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(ExprLine)};
- _ ->
- {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(CL)}
- catch
- _:_ ->
+ unknown ->
{lists:reverse([{clause,get_line(CL)}|CLs]), get_line(CL)}
end;
-
find_clause_lines([{clause,CL,_Params,_Op,_Exprs} | Cs], CLs) ->
find_clause_lines(Cs, [{clause,get_line(CL)}|CLs]).
+classify_exprs(Exprs) ->
+ case tuple_to_list(lists:last(Exprs)) of
+ [macro,{_var,Anno,_MACRO} | _] ->
+ {anno, Anno};
+ [T,ExprAnno | Exprs1] ->
+ case erl_anno:is_anno(ExprAnno) of
+ true ->
+ {anno, ExprAnno};
+ false when T =:= tree ->
+ {tree, Exprs1};
+ false ->
+ unknown
+ end
+ end.
+
%%%-----------------------------------------------------------------
%%% Add a link target for each line and one for each function definition.
build_html(SFd,DFd,Encoding,FuncsAndCs) ->
diff --git a/lib/test_server/src/test_server.erl b/lib/common_test/src/test_server.erl
index 34acad6fd1..34acad6fd1 100644
--- a/lib/test_server/src/test_server.erl
+++ b/lib/common_test/src/test_server.erl
diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/common_test/src/test_server_ctrl.erl
index e0975ab744..833d99907e 100644
--- a/lib/test_server/src/test_server_ctrl.erl
+++ b/lib/common_test/src/test_server_ctrl.erl
@@ -3164,11 +3164,17 @@ delete_prop([], Props) ->
%% Shuffles the order of Cases.
shuffle_cases(Ref, Cases, undefined) ->
- shuffle_cases(Ref, Cases, ?now);
+ shuffle_cases(Ref, Cases, rand:seed_s(exsplus));
-shuffle_cases(Ref, [{conf,Ref,_,_}=Start | Cases], Seed) ->
+shuffle_cases(Ref, [{conf,Ref,_,_}=Start | Cases], Seed0) ->
{N,CasesToShuffle,Rest} = cases_to_shuffle(Ref, Cases),
- ShuffledCases = random_order(N, random:uniform_s(N, Seed), CasesToShuffle, []),
+ Seed = case Seed0 of
+ {X,Y,Z} when is_integer(X+Y+Z) ->
+ rand:seed(exsplus, Seed0);
+ _ ->
+ Seed0
+ end,
+ ShuffledCases = random_order(N, rand:uniform_s(N, Seed), CasesToShuffle, []),
[Start|ShuffledCases] ++ Rest.
cases_to_shuffle(Ref, Cases) ->
@@ -3202,7 +3208,7 @@ random_order(1, {_Pos,Seed}, [{_Ix,CaseOrGroup}], Shuffled) ->
Shuffled++CaseOrGroup;
random_order(N, {Pos,NewSeed}, IxCases, Shuffled) ->
{First,[{_Ix,CaseOrGroup}|Rest]} = lists:split(Pos-1, IxCases),
- random_order(N-1, random:uniform_s(N-1, NewSeed),
+ random_order(N-1, rand:uniform_s(N-1, NewSeed),
First++Rest, Shuffled++CaseOrGroup).
diff --git a/lib/test_server/src/test_server_gl.erl b/lib/common_test/src/test_server_gl.erl
index 0acc73047c..233e59172b 100644
--- a/lib/test_server/src/test_server_gl.erl
+++ b/lib/common_test/src/test_server_gl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2012-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.
@@ -30,7 +30,7 @@
-export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2]).
-record(st, {tc_supervisor :: 'none'|pid(), %Test case supervisor
- tc :: mfa(), %Current test case MFA
+ tc :: mfa() | 'undefined', %Current test case MFA
minor :: 'none'|pid(), %Minor fd
minor_monitor, %Monitor ref for minor fd
capture :: 'none'|pid(), %Capture output
diff --git a/lib/test_server/src/test_server_internal.hrl b/lib/common_test/src/test_server_internal.hrl
index 1ec2d83417..1ec2d83417 100644
--- a/lib/test_server/src/test_server_internal.hrl
+++ b/lib/common_test/src/test_server_internal.hrl
diff --git a/lib/test_server/src/test_server_io.erl b/lib/common_test/src/test_server_io.erl
index 0d881d0ada..0d881d0ada 100644
--- a/lib/test_server/src/test_server_io.erl
+++ b/lib/common_test/src/test_server_io.erl
diff --git a/lib/test_server/src/test_server_node.erl b/lib/common_test/src/test_server_node.erl
index 37f8941d24..c64399e485 100644
--- a/lib/test_server/src/test_server_node.erl
+++ b/lib/common_test/src/test_server_node.erl
@@ -627,8 +627,7 @@ do_quote_progname([Prog,Arg|Args]) ->
end.
random_element(L) ->
- random:seed(os:timestamp()),
- lists:nth(random:uniform(length(L)), L).
+ lists:nth(rand:uniform(length(L)), L).
find_release(latest) ->
"/usr/local/otp/releases/latest/bin/erl";
diff --git a/lib/test_server/src/test_server_sup.erl b/lib/common_test/src/test_server_sup.erl
index c4530ba62f..c4530ba62f 100644
--- a/lib/test_server/src/test_server_sup.erl
+++ b/lib/common_test/src/test_server_sup.erl
diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile
index a1cead4550..fd96d06aab 100644
--- a/lib/common_test/test/Makefile
+++ b/lib/common_test/test/Makefile
@@ -66,9 +66,13 @@ MODULES= \
ct_groups_search_SUITE \
ct_surefire_SUITE \
ct_telnet_SUITE \
+ erl2html2_SUITE \
+ test_server_SUITE \
+ test_server_test_lib \
ct_release_test_SUITE
ERL_FILES= $(MODULES:%=%.erl)
+HRL_FILES= test_server_test_lib.hrl
TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
INSTALL_PROGS= $(TARGET_FILES)
@@ -85,8 +89,8 @@ RELSYSDIR = $(RELEASE_PATH)/common_test_test
# FLAGS
# ----------------------------------------------------
-ERL_MAKE_FLAGS += -pa $(ERL_TOP)/lib/test_server/ebin
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_MAKE_FLAGS +=
+ERL_COMPILE_FLAGS +=
EBIN = .
@@ -119,7 +123,7 @@ release_spec: opt
release_tests_spec:
$(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(ERL_FILES) $(COVERFILE) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(COVERFILE) "$(RELSYSDIR)"
$(INSTALL_DATA) common_test.spec common_test.cover "$(RELSYSDIR)"
chmod -R u+w "$(RELSYSDIR)"
@tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
diff --git a/lib/common_test/test/common_test.cover b/lib/common_test/test/common_test.cover
index 87d00c420f..e8e01a9312 100644
--- a/lib/common_test/test/common_test.cover
+++ b/lib/common_test/test/common_test.cover
@@ -1,9 +1,2 @@
%% -*- erlang -*-
{incl_app,common_test,details}.
-{cross,common_test,[{test_server,[erl2html2,
- test_server,
- test_server_ctrl,
- test_server_gl,
- test_server_io,
- test_server_node,
- test_server_sup]}]}.
diff --git a/lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl b/lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl
index 28c85ee2db..29c25bf151 100644
--- a/lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl
+++ b/lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl
@@ -27,7 +27,7 @@
-behaviour(gen_event).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("common_test/include/ct_event.hrl").
%% gen_event callbacks
diff --git a/lib/common_test/test/ct_hooks_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE.erl
index 8353f5936c..5ec88b438e 100644
--- a/lib/common_test/test/ct_hooks_SUITE.erl
+++ b/lib/common_test/test/ct_hooks_SUITE.erl
@@ -30,7 +30,7 @@
-compile(export_all).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("common_test/include/ct_event.hrl").
-define(eh, ct_test_support_eh).
diff --git a/lib/common_test/test/ct_master_SUITE.erl b/lib/common_test/test/ct_master_SUITE.erl
index 15b49c67c0..55837352e2 100644
--- a/lib/common_test/test/ct_master_SUITE.erl
+++ b/lib/common_test/test/ct_master_SUITE.erl
@@ -135,7 +135,7 @@ make_spec(DataDir, FileName, NodeNames, Suites, Config) ->
C = lists:map(
fun(NodeName) ->
- Rnd = random:uniform(2),
+ Rnd = rand:uniform(2),
if Rnd == 1->
{config,NodeName,filename:join(DataDir,
"master/config.txt")};
diff --git a/lib/common_test/test/ct_misc_1_SUITE.erl b/lib/common_test/test/ct_misc_1_SUITE.erl
index 1db8bcc794..a562719296 100644
--- a/lib/common_test/test/ct_misc_1_SUITE.erl
+++ b/lib/common_test/test/ct_misc_1_SUITE.erl
@@ -31,7 +31,6 @@
-compile(export_all).
-include_lib("common_test/include/ct.hrl").
--include_lib("test_server/include/test_server_line.hrl").
-include_lib("common_test/include/ct_event.hrl").
-define(eh, ct_test_support_eh).
diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl
index 8e7ac9395c..0ee83f45b8 100644
--- a/lib/common_test/test/ct_test_support.erl
+++ b/lib/common_test/test/ct_test_support.erl
@@ -414,14 +414,14 @@ ct_rpc({M,F,A}, Config) ->
%%%-----------------------------------------------------------------
%%% random_error/1
random_error(Config) when is_list(Config) ->
- random:seed(os:timestamp()),
+ rand:seed(exsplus),
Gen = fun(0,_) -> ok; (N,Fun) -> Fun(N-1, Fun) end,
- Gen(random:uniform(100), Gen),
+ Gen(rand:uniform(100), Gen),
ErrorTypes = ['BADMATCH','BADARG','CASE_CLAUSE','FUNCTION_CLAUSE',
'EXIT','THROW','UNDEF'],
- Type = lists:nth(random:uniform(length(ErrorTypes)), ErrorTypes),
- Where = case random:uniform(2) of
+ Type = lists:nth(rand:uniform(length(ErrorTypes)), ErrorTypes),
+ Where = case rand:uniform(2) of
1 ->
io:format("ct_test_support *returning* error of type ~w",
[Type]),
diff --git a/lib/common_test/test/ct_test_support_eh.erl b/lib/common_test/test/ct_test_support_eh.erl
index 7c3d137901..f3d933da04 100644
--- a/lib/common_test/test/ct_test_support_eh.erl
+++ b/lib/common_test/test/ct_test_support_eh.erl
@@ -27,7 +27,7 @@
-behaviour(gen_event).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("common_test/include/ct_event.hrl").
%% gen_event callbacks
diff --git a/lib/test_server/test/erl2html2_SUITE.erl b/lib/common_test/test/erl2html2_SUITE.erl
index 8e9f6e773a..8e9f6e773a 100644
--- a/lib/test_server/test/erl2html2_SUITE.erl
+++ b/lib/common_test/test/erl2html2_SUITE.erl
diff --git a/lib/test_server/test/erl2html2_SUITE_data/Makefile.src b/lib/common_test/test/erl2html2_SUITE_data/Makefile.src
index 942ac0584b..942ac0584b 100644
--- a/lib/test_server/test/erl2html2_SUITE_data/Makefile.src
+++ b/lib/common_test/test/erl2html2_SUITE_data/Makefile.src
diff --git a/lib/test_server/test/erl2html2_SUITE_data/header1.hrl b/lib/common_test/test/erl2html2_SUITE_data/header1.hrl
index 53d1b79ac5..53d1b79ac5 100644
--- a/lib/test_server/test/erl2html2_SUITE_data/header1.hrl
+++ b/lib/common_test/test/erl2html2_SUITE_data/header1.hrl
diff --git a/lib/test_server/test/erl2html2_SUITE_data/include/header2.hrl b/lib/common_test/test/erl2html2_SUITE_data/include/header2.hrl
index e69de29bb2..e69de29bb2 100644
--- a/lib/test_server/test/erl2html2_SUITE_data/include/header2.hrl
+++ b/lib/common_test/test/erl2html2_SUITE_data/include/header2.hrl
diff --git a/lib/test_server/test/erl2html2_SUITE_data/include/header3.hrl b/lib/common_test/test/erl2html2_SUITE_data/include/header3.hrl
index 2a20850a3a..2a20850a3a 100644
--- a/lib/test_server/test/erl2html2_SUITE_data/include/header3.hrl
+++ b/lib/common_test/test/erl2html2_SUITE_data/include/header3.hrl
diff --git a/lib/test_server/test/erl2html2_SUITE_data/m1.erl b/lib/common_test/test/erl2html2_SUITE_data/m1.erl
index 1d405963a5..1d405963a5 100644
--- a/lib/test_server/test/erl2html2_SUITE_data/m1.erl
+++ b/lib/common_test/test/erl2html2_SUITE_data/m1.erl
diff --git a/lib/test_server/test/test_server_SUITE.erl b/lib/common_test/test/test_server_SUITE.erl
index 6adf5b8a78..d1c789f34c 100644
--- a/lib/test_server/test/test_server_SUITE.erl
+++ b/lib/common_test/test/test_server_SUITE.erl
@@ -330,7 +330,7 @@ generate_and_run_unicode_test(Config0,Encoding) ->
%% Compile the suite
Node = proplists:get_value(node,Config),
- {ok,Mod} = rpc:call(Node,compile,file,[Suite,[{outdir,DataDir}]]),
+ {ok,Mod} = rpc:call(Node,compile,file,[Suite,[report,{outdir,DataDir}]]),
ModStr = atom_to_list(Mod),
%% Clean logdir
@@ -383,7 +383,7 @@ create_unicode_test_suite(Dir,Encoding) ->
"-export([init_per_testcase/2, end_per_testcase/2]).\n"
"-export([tc_äöå/1]).\n"
"\n"
- "-include_lib(\"test_server/include/test_server.hrl\").\n"
+ "-include_lib(\"common_test/include/ct.hrl\").\n"
"\n"
"all(suite) ->\n"
" [tc_äöå].\n"
diff --git a/lib/test_server/test/test_server_SUITE_data/Makefile.src b/lib/common_test/test/test_server_SUITE_data/Makefile.src
index 5aeb035572..5aeb035572 100644
--- a/lib/test_server/test/test_server_SUITE_data/Makefile.src
+++ b/lib/common_test/test/test_server_SUITE_data/Makefile.src
diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_SUITE.erl b/lib/common_test/test/test_server_SUITE_data/test_server_SUITE.erl
index 79d8defb22..c3d4315cb8 100644
--- a/lib/test_server/test/test_server_SUITE_data/test_server_SUITE.erl
+++ b/lib/common_test/test/test_server_SUITE_data/test_server_SUITE.erl
@@ -22,8 +22,7 @@
%%% Test Server self test.
%%%------------------------------------------------------------------
-module(test_server_SUITE).
--include_lib("test_server/include/test_server.hrl").
--include_lib("test_server/include/test_server_line.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
-export([all/1]).
diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_SUITE_data/dummy_file b/lib/common_test/test/test_server_SUITE_data/test_server_SUITE_data/dummy_file
index 65c88fbd75..65c88fbd75 100644
--- a/lib/test_server/test/test_server_SUITE_data/test_server_SUITE_data/dummy_file
+++ b/lib/common_test/test/test_server_SUITE_data/test_server_SUITE_data/dummy_file
diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_break_SUITE.erl b/lib/common_test/test/test_server_SUITE_data/test_server_break_SUITE.erl
index ae9f018bc8..171f83df0f 100644
--- a/lib/test_server/test/test_server_SUITE_data/test_server_break_SUITE.erl
+++ b/lib/common_test/test/test_server_SUITE_data/test_server_break_SUITE.erl
@@ -28,7 +28,7 @@
break_in_end_tc_after_abort/1,
check_all_breaks/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
all(suite) ->
[break_in_init_tc,
diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_conf01_SUITE.erl b/lib/common_test/test/test_server_SUITE_data/test_server_conf01_SUITE.erl
index f634bc3a46..e4f40f6c03 100644
--- a/lib/test_server/test/test_server_SUITE_data/test_server_conf01_SUITE.erl
+++ b/lib/common_test/test/test_server_SUITE_data/test_server_conf01_SUITE.erl
@@ -22,7 +22,7 @@
%%% Test Server self test.
%%%------------------------------------------------------------------
-module(test_server_conf01_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-compile(export_all).
diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_conf02_SUITE.erl b/lib/common_test/test/test_server_SUITE_data/test_server_conf02_SUITE.erl
index f9cca8653b..1c6fe6dd0b 100644
--- a/lib/test_server/test/test_server_SUITE_data/test_server_conf02_SUITE.erl
+++ b/lib/common_test/test/test_server_SUITE_data/test_server_conf02_SUITE.erl
@@ -22,7 +22,7 @@
%%% Test Server self test.
%%%------------------------------------------------------------------
-module(test_server_conf02_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-compile(export_all).
diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE.erl b/lib/common_test/test/test_server_SUITE_data/test_server_cover_SUITE.erl
index ab5ccec7a2..3371418980 100644
--- a/lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE.erl
+++ b/lib/common_test/test/test_server_SUITE_data/test_server_cover_SUITE.erl
@@ -23,7 +23,7 @@
-export([init_per_testcase/2, end_per_testcase/2]).
-export([tc1/1, tc2/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
all(suite) ->
[tc1,tc2].
diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE_data/cover_helper.erl b/lib/common_test/test/test_server_SUITE_data/test_server_cover_SUITE_data/cover_helper.erl
index 6c74eb4e8a..6c74eb4e8a 100644
--- a/lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE_data/cover_helper.erl
+++ b/lib/common_test/test/test_server_SUITE_data/test_server_cover_SUITE_data/cover_helper.erl
diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_parallel01_SUITE.erl b/lib/common_test/test/test_server_SUITE_data/test_server_parallel01_SUITE.erl
index 0385435710..ad639b585d 100644
--- a/lib/test_server/test/test_server_SUITE_data/test_server_parallel01_SUITE.erl
+++ b/lib/common_test/test/test_server_SUITE_data/test_server_parallel01_SUITE.erl
@@ -22,7 +22,7 @@
%%% Test Server self test.
%%%------------------------------------------------------------------
-module(test_server_parallel01_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-compile(export_all).
diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_shuffle01_SUITE.erl b/lib/common_test/test/test_server_SUITE_data/test_server_shuffle01_SUITE.erl
index 847c7b6bdd..0f7118a810 100644
--- a/lib/test_server/test/test_server_SUITE_data/test_server_shuffle01_SUITE.erl
+++ b/lib/common_test/test/test_server_SUITE_data/test_server_shuffle01_SUITE.erl
@@ -22,7 +22,7 @@
%%% Test Server self test.
%%%------------------------------------------------------------------
-module(test_server_shuffle01_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-compile(export_all).
@@ -224,7 +224,7 @@ conf5_end(_Config) ->
ok.
conf6_init(Config) when is_list(Config) ->
- [{shuffle,{_,_,_}}] = ?config(tc_group_properties,Config),
+ validate_shuffle(Config),
test_server:comment("Shuffle (random)"),
init = ?config(suite,Config),
[{cc6,conf6}|Config].
@@ -242,23 +242,28 @@ conf5(suite) -> % test specification
conf7_init(Config) when is_list(Config) ->
test_server:comment("Group 7, Shuffle (random seed)"),
- case proplists:get_value(shuffle,?config(tc_group_properties,Config)) of
- {_,_,_} -> ok
- end,
+ validate_shuffle(Config),
[{cc7,conf7}|Config].
conf7_end(_Config) ->
ok.
conf8_init(Config) when is_list(Config) ->
test_server:comment("Group 8, Shuffle (user start seed)"),
- case proplists:get_value(shuffle,?config(tc_group_properties,Config)) of
- {_,_,_} -> ok
- end,
+ validate_shuffle(Config),
init = ?config(suite,Config),
[{cc8,conf8}|Config].
conf8_end(_Config) ->
ok.
+validate_shuffle(Config) ->
+ case proplists:get_value(shuffle, ?config(tc_group_properties,Config)) of
+ {_,_,_} ->
+ ok;
+ Seed ->
+ %% Must be a valid seed.
+ _ = rand:seed_s(rand:export_seed_s(Seed))
+ end.
+
%%---------- test cases ----------
diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_skip_SUITE.erl b/lib/common_test/test/test_server_SUITE_data/test_server_skip_SUITE.erl
index 871bd21ee7..ae2321c6ad 100644
--- a/lib/test_server/test/test_server_SUITE_data/test_server_skip_SUITE.erl
+++ b/lib/common_test/test/test_server_SUITE_data/test_server_skip_SUITE.erl
@@ -22,8 +22,7 @@
-export([all/1, init_per_suite/1, end_per_suite/1]).
-export([dummy/1]).
--include_lib("test_server/include/test_server.hrl").
--include_lib("test_server/include/test_server_line.hrl").
+-include_lib("common_test/include/ct.hrl").
all(suite) ->
[dummy].
diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_unicode_SUITE.erl b/lib/common_test/test/test_server_SUITE_data/test_server_unicode_SUITE.erl
index 3a3366218b..0cabce995f 100644
--- a/lib/test_server/test/test_server_SUITE_data/test_server_unicode_SUITE.erl
+++ b/lib/common_test/test/test_server_SUITE_data/test_server_unicode_SUITE.erl
@@ -25,7 +25,7 @@
print_and_log_unicode/1,
print_and_log_latin1/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
all(suite) ->
['#=@: difficult_case_name_äöå',
diff --git a/lib/test_server/test/test_server_test_lib.erl b/lib/common_test/test/test_server_test_lib.erl
index e2680938e0..e2680938e0 100644
--- a/lib/test_server/test/test_server_test_lib.erl
+++ b/lib/common_test/test/test_server_test_lib.erl
diff --git a/lib/test_server/test/test_server_test_lib.hrl b/lib/common_test/test/test_server_test_lib.hrl
index 27b7be9618..27b7be9618 100644
--- a/lib/test_server/test/test_server_test_lib.hrl
+++ b/lib/common_test/test/test_server_test_lib.hrl
diff --git a/lib/webtool/src/Makefile b/lib/common_test/test_server/Makefile
index a5a8eaf5dc..0adf64b837 100644
--- a/lib/webtool/src/Makefile
+++ b/lib/common_test/test_server/Makefile
@@ -1,8 +1,8 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2001-2012. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 1996-2013. 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
@@ -14,85 +14,83 @@
# 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=$(WEBTOOL_VSN)
+include $(ERL_TOP)/make/target.mk
# ----------------------------------------------------
-# Release directory specification
+# Configuration info.
# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/webtool-$(VSN)
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
# ----------------------------------------------------
# Target Specs
# ----------------------------------------------------
-MODULES= webtool \
- webtool_sup
-
-
-
-ERL_FILES= $(MODULES:%=%.erl)
+EBIN=.
-TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+TS_MODULES= \
+ ts \
+ ts_run \
+ ts_lib \
+ ts_make \
+ ts_erl_config \
+ ts_autoconf_win32 \
+ ts_install \
+ ts_install_cth \
+ ts_benchmark
-APP_FILE= webtool.app
-APPUP_FILE= webtool.appup
+TARGET_MODULES= $(MODULES:%=$(EBIN)/%)
+TS_TARGET_MODULES= $(TS_MODULES:%=$(EBIN)/%)
-APP_SRC= $(APP_FILE).src
-APPUP_SRC= $(APPUP_FILE).src
+TS_ERL_FILES = $(TS_MODULES:=.erl)
+TS_HRL_FILES = ts.hrl
+AUTOCONF_FILES = configure.in conf_vars.in
+PROGRAMS = configure config.sub config.guess install-sh
+CONFIG = ts.config ts.unix.config ts.win32.config
+TS_TARGET_FILES = $(TS_MODULES:%=$(EBIN)/%.$(EMULATOR))
-APP_TARGET= $(EBIN)/$(APP_FILE)
-APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
+TS_TARGETS = $(TS_MODULES:%=$(EBIN)/%.$(EMULATOR))
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-ERL_COMPILE_FLAGS += +warn_obsolete_guard
-
+ERL_COMPILE_FLAGS += -I../include -Werror
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+tests debug opt: $(TS_TARGETS)
clean:
- rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TS_TARGET_FILES)
rm -f core
docs:
+configure: configure.in
+ autoconf configure.in > configure
+
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(APP_TARGET): $(APP_SRC) ../vsn.mk
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
-
-$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
-
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) \
- "$(RELSYSDIR)/ebin"
+release_tests_spec: opt
+ $(INSTALL_DIR) "$(RELEASE_PATH)/test_server"
+ $(INSTALL_DATA) $(TS_ERL_FILES) $(TS_HRL_FILES) \
+ $(TS_TARGET_FILES) \
+ $(AUTOCONF_FILES) $(CONFIG) \
+ "$(RELEASE_PATH)/test_server"
+ $(INSTALL_SCRIPT) $(PROGRAMS) "$(RELEASE_PATH)/test_server"
release_docs_spec:
diff --git a/lib/test_server/src/conf_vars.in b/lib/common_test/test_server/conf_vars.in
index 7c55d7b9ed..7c55d7b9ed 100644
--- a/lib/test_server/src/conf_vars.in
+++ b/lib/common_test/test_server/conf_vars.in
diff --git a/lib/test_server/src/configure.in b/lib/common_test/test_server/configure.in
index 001de72a1e..001de72a1e 100644
--- a/lib/test_server/src/configure.in
+++ b/lib/common_test/test_server/configure.in
diff --git a/lib/test_server/src/cross.cover b/lib/common_test/test_server/cross.cover
index 07bf0bed5c..07bf0bed5c 100644
--- a/lib/test_server/src/cross.cover
+++ b/lib/common_test/test_server/cross.cover
diff --git a/lib/test_server/src/ts.config b/lib/common_test/test_server/ts.config
index cf3d269616..cf3d269616 100644
--- a/lib/test_server/src/ts.config
+++ b/lib/common_test/test_server/ts.config
diff --git a/lib/test_server/src/ts.erl b/lib/common_test/test_server/ts.erl
index 8bbdc8f8cf..8bbdc8f8cf 100644
--- a/lib/test_server/src/ts.erl
+++ b/lib/common_test/test_server/ts.erl
diff --git a/lib/test_server/src/ts.hrl b/lib/common_test/test_server/ts.hrl
index 4c940fdc4f..4c940fdc4f 100644
--- a/lib/test_server/src/ts.hrl
+++ b/lib/common_test/test_server/ts.hrl
diff --git a/lib/test_server/src/ts.unix.config b/lib/common_test/test_server/ts.unix.config
index 1ba5d9033e..1ba5d9033e 100644
--- a/lib/test_server/src/ts.unix.config
+++ b/lib/common_test/test_server/ts.unix.config
diff --git a/lib/test_server/src/ts.win32.config b/lib/common_test/test_server/ts.win32.config
index cae587bea8..cae587bea8 100644
--- a/lib/test_server/src/ts.win32.config
+++ b/lib/common_test/test_server/ts.win32.config
diff --git a/lib/test_server/src/ts_autoconf_win32.erl b/lib/common_test/test_server/ts_autoconf_win32.erl
index 288305b406..288305b406 100644
--- a/lib/test_server/src/ts_autoconf_win32.erl
+++ b/lib/common_test/test_server/ts_autoconf_win32.erl
diff --git a/lib/test_server/src/ts_benchmark.erl b/lib/common_test/test_server/ts_benchmark.erl
index 3e55edefb0..3e55edefb0 100644
--- a/lib/test_server/src/ts_benchmark.erl
+++ b/lib/common_test/test_server/ts_benchmark.erl
diff --git a/lib/test_server/src/ts_erl_config.erl b/lib/common_test/test_server/ts_erl_config.erl
index ab7363c106..ab7363c106 100644
--- a/lib/test_server/src/ts_erl_config.erl
+++ b/lib/common_test/test_server/ts_erl_config.erl
diff --git a/lib/test_server/src/ts_install.erl b/lib/common_test/test_server/ts_install.erl
index 600a576820..600a576820 100644
--- a/lib/test_server/src/ts_install.erl
+++ b/lib/common_test/test_server/ts_install.erl
diff --git a/lib/test_server/src/ts_install_cth.erl b/lib/common_test/test_server/ts_install_cth.erl
index 0462e62611..0462e62611 100644
--- a/lib/test_server/src/ts_install_cth.erl
+++ b/lib/common_test/test_server/ts_install_cth.erl
diff --git a/lib/test_server/src/ts_lib.erl b/lib/common_test/test_server/ts_lib.erl
index 7c3f450194..7c3f450194 100644
--- a/lib/test_server/src/ts_lib.erl
+++ b/lib/common_test/test_server/ts_lib.erl
diff --git a/lib/test_server/src/ts_make.erl b/lib/common_test/test_server/ts_make.erl
index 0178f4d836..921edb264a 100644
--- a/lib/test_server/src/ts_make.erl
+++ b/lib/common_test/test_server/ts_make.erl
@@ -21,7 +21,7 @@
-export([make/1,make/3,unmake/1]).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Functions to be called from make test cases.
diff --git a/lib/test_server/src/ts_run.erl b/lib/common_test/test_server/ts_run.erl
index 188094921d..188094921d 100644
--- a/lib/test_server/src/ts_run.erl
+++ b/lib/common_test/test_server/ts_run.erl
diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile
index 299b2892fc..f75beaba20 100644
--- a/lib/compiler/src/Makefile
+++ b/lib/compiler/src/Makefile
@@ -50,6 +50,7 @@ MODULES = \
beam_asm \
beam_block \
beam_bool \
+ beam_bs \
beam_bsm \
beam_clean \
beam_dead \
@@ -62,6 +63,7 @@ MODULES = \
beam_opcodes \
beam_peep \
beam_receive \
+ beam_reorder \
beam_split \
beam_trim \
beam_type \
diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl
index a3201b0f4a..95be471de3 100644
--- a/lib/compiler/src/beam_asm.erl
+++ b/lib/compiler/src/beam_asm.erl
@@ -30,11 +30,12 @@
module(Code, Abst, SourceFile, Opts) ->
{ok,assemble(Code, Abst, SourceFile, Opts)}.
-assemble({Mod,Exp,Attr0,Asm0,NumLabels}, Abst, SourceFile, Opts) ->
+assemble({Mod,Exp0,Attr0,Asm0,NumLabels}, Abst, SourceFile, Opts) ->
{1,Dict0} = beam_dict:atom(Mod, beam_dict:new()),
{0,Dict1} = beam_dict:fname(atom_to_list(Mod) ++ ".erl", Dict0),
NumFuncs = length(Asm0),
{Asm,Attr} = on_load(Asm0, Attr0),
+ Exp = cerl_sets:from_list(Exp0),
{Code,Dict2} = assemble_1(Asm, Exp, Dict1, []),
build_file(Code, Attr, Dict2, NumLabels, NumFuncs, Abst, SourceFile, Opts).
@@ -61,7 +62,7 @@ insert_on_load_instruction(Is0, Entry) ->
Bef ++ [El,on_load|Is].
assemble_1([{function,Name,Arity,Entry,Asm}|T], Exp, Dict0, Acc) ->
- Dict1 = case member({Name,Arity}, Exp) of
+ Dict1 = case cerl_sets:is_element({Name,Arity}, Exp) of
true ->
beam_dict:export(Name, Arity, Entry, Dict0);
false ->
diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl
index 0321b1c07b..d1052303e0 100644
--- a/lib/compiler/src/beam_block.erl
+++ b/lib/compiler/src/beam_block.erl
@@ -23,14 +23,13 @@
-module(beam_block).
-export([module/2]).
--import(lists, [mapfoldl/3,reverse/1,reverse/2,foldl/3,member/2]).
--define(MAXREG, 1024).
+-import(lists, [reverse/1,reverse/2,foldl/3,member/2]).
-module({Mod,Exp,Attr,Fs0,Lc0}, _Opt) ->
- {Fs,Lc} = mapfoldl(fun function/2, Lc0, Fs0),
+module({Mod,Exp,Attr,Fs0,Lc}, _Opt) ->
+ Fs = [function(F) || F <- Fs0],
{ok,{Mod,Exp,Attr,Fs,Lc}}.
-function({function,Name,Arity,CLabel,Is0}, Lc0) ->
+function({function,Name,Arity,CLabel,Is0}) ->
try
%% Collect basic blocks and optimize them.
Is1 = blockify(Is0),
@@ -40,11 +39,8 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) ->
Is5 = opt_blocks(Is4),
Is6 = beam_utils:delete_live_annos(Is5),
- %% Optimize bit syntax.
- {Is,Lc} = bsm_opt(Is6, Lc0),
-
%% Done.
- {{function,Name,Arity,CLabel,Is},Lc}
+ {function,Name,Arity,CLabel,Is6}
catch
Class:Error ->
Stack = erlang:get_stacktrace(),
@@ -62,56 +58,22 @@ blockify(Is) ->
blockify([{loop_rec,{f,Fail},{x,0}},{loop_rec_end,_Lbl},{label,Fail}|Is], Acc) ->
%% Useless instruction sequence.
blockify(Is, Acc);
-blockify([{test,is_atom,{f,Fail},[Reg]}=I|
- [{select,select_val,Reg,{f,Fail},
- [{atom,false},{f,_}=BrFalse,
- {atom,true}=AtomTrue,{f,_}=BrTrue]}|Is]=Is0],
- [{block,Bl}|_]=Acc) ->
- case is_last_bool(Bl, Reg) of
- false ->
- blockify(Is0, [I|Acc]);
- true ->
- %% The last instruction is a boolean operator/guard BIF that can't fail.
- %% We can convert the three-way branch to a two-way branch (eliminating
- %% the reference to the failure label).
- blockify(Is, [{jump,BrTrue},
- {test,is_eq_exact,BrFalse,[Reg,AtomTrue]}|Acc])
- end;
-blockify([{test,is_atom,{f,Fail},[Reg]}=I|
- [{select,select_val,Reg,{f,Fail},
- [{atom,true}=AtomTrue,{f,_}=BrTrue,
- {atom,false},{f,_}=BrFalse]}|Is]=Is0],
- [{block,Bl}|_]=Acc) ->
- case is_last_bool(Bl, Reg) of
- false ->
- blockify(Is0, [I|Acc]);
- true ->
- blockify(Is, [{jump,BrTrue},
- {test,is_eq_exact,BrFalse,[Reg,AtomTrue]}|Acc])
- end;
+blockify([{get_map_elements,F,S,{list,Gets}}|Is0], Acc) ->
+ %% A get_map_elements instruction is only safe at the beginning of
+ %% a block because of the failure label.
+ {Ss,Ds} = beam_utils:split_even(Gets),
+ I = {set,Ds,[S|Ss],{get_map_elements,F}},
+ {Block,Is} = collect_block(Is0, [I]),
+ blockify(Is, [{block,Block}|Acc]);
blockify([I|Is0]=IsAll, Acc) ->
- case is_bs_put(I) of
- true ->
- {BsPuts0,Is} = collect_bs_puts(IsAll),
- BsPuts = opt_bs_puts(BsPuts0),
- blockify(Is, reverse(BsPuts, Acc));
- false ->
- case collect(I) of
- error -> blockify(Is0, [I|Acc]);
- Instr when is_tuple(Instr) ->
- {Block,Is} = collect_block(IsAll),
- blockify(Is, [{block,Block}|Acc])
- end
+ case collect(I) of
+ error -> blockify(Is0, [I|Acc]);
+ Instr when is_tuple(Instr) ->
+ {Block,Is} = collect_block(IsAll),
+ blockify(Is, [{block,Block}|Acc])
end;
blockify([], Acc) -> reverse(Acc).
-is_last_bool([{set,[Reg],As,{bif,N,_}}], Reg) ->
- Ar = length(As),
- erl_internal:new_type_test(N, Ar) orelse erl_internal:comp_op(N, Ar)
- orelse erl_internal:bool_op(N, Ar);
-is_last_bool([_|Is], Reg) -> is_last_bool(Is, Reg);
-is_last_bool([], _) -> false.
-
collect_block(Is) ->
collect_block(Is, []).
@@ -146,10 +108,10 @@ collect({get_list,S,D1,D2}) -> {set,[D1,D2],[S],get_list};
collect(remove_message) -> {set,[],[],remove_message};
collect({put_map,F,Op,S,D,R,{list,Puts}}) ->
{set,[D],[S|Puts],{alloc,R,{put_map,Op,F}}};
-collect({get_map_elements,F,S,{list,Gets}}) ->
- {Ss,Ds} = beam_utils:split_even(Gets),
- {set,Ds,[S|Ss],{get_map_elements,F}};
-collect({'catch',R,L}) -> {set,[R],[],{'catch',L}};
+collect({'catch'=Op,R,L}) ->
+ {set,[R],[],{try_catch,Op,L}};
+collect({'try'=Op,R,L}) ->
+ {set,[R],[],{try_catch,Op,L}};
collect(fclearerror) -> {set,[],[],fclearerror};
collect({fcheckerror,{f,0}}) -> {set,[],[],fcheckerror};
collect({fmove,S,D}) -> {set,[D],[S],fmove};
@@ -183,7 +145,9 @@ opt_blocks([I|Is]) ->
opt_blocks([]) -> [].
opt_block(Is0) ->
- Is = find_fixpoint(fun opt/1, Is0),
+ Is = find_fixpoint(fun(Is) ->
+ opt_tuple_element(opt(Is))
+ end, Is0),
opt_alloc(Is).
find_fixpoint(OptFun, Is0) ->
@@ -279,76 +243,151 @@ opt_moves([X0,Y0], Is0) ->
not_possible -> {[X,Y0],Is2};
{X,_} -> {[X,Y0],Is2};
{Y,Is} -> {[X,Y],Is}
- end;
-opt_moves(Ds, Is) ->
- %% multiple destinations -> pass through
- {Ds,Is}.
-
+ end.
%% opt_move(Dest, [Instruction]) -> {UpdatedDest,[Instruction]} | not_possible
%% If there is a {move,Dest,FinalDest} instruction
%% in the instruction stream, remove the move instruction
%% and let FinalDest be the destination.
-%%
-%% For this optimization to be safe, we must be sure that
-%% Dest will not be referenced in any other by other instructions
-%% in the rest of the instruction stream. Not even the indirect
-%% reference by an instruction that may allocate (such as
-%% test_heap/2 or a GC Bif) is allowed.
opt_move(Dest, Is) ->
- opt_move_1(Dest, Is, ?MAXREG, []).
-
-opt_move_1(R, [{set,_,_,{alloc,Live,_}}|_]=Is, SafeRegs, Acc) when Live < SafeRegs ->
- %% Downgrade number of safe regs and rescan the instruction, as it most probably
- %% is a gc_bif instruction.
- opt_move_1(R, Is, Live, Acc);
-opt_move_1(R, [{set,[{x,X}=D],[R],move}|Is], SafeRegs, Acc) ->
- case X < SafeRegs andalso beam_utils:is_killed_block(R, Is) of
- true -> opt_move_2(D, Acc, Is);
- false -> not_possible
+ opt_move_1(Dest, Is, []).
+
+opt_move_1(R, [{set,[D],[R],move}|Is0], Acc) ->
+ %% Provided that the source register is killed by instructions
+ %% that follow, the optimization is safe.
+ case eliminate_use_of_from_reg(Is0, R, D, []) of
+ {yes,Is} -> opt_move_rev(D, Acc, Is);
+ no -> not_possible
end;
-opt_move_1(R, [{set,[D],[R],move}|Is], _SafeRegs, Acc) ->
- case beam_utils:is_killed_block(R, Is) of
- true -> opt_move_2(D, Acc, Is);
- false -> not_possible
+opt_move_1({x,_}, [{set,_,_,{alloc,_,_}}|_], _) ->
+ %% The optimization is not possible. If the X register is not
+ %% killed by allocation, the optimization would not be safe.
+ %% If the X register is killed, it means that there cannot
+ %% follow a 'move' instruction with this X register as the
+ %% source.
+ not_possible;
+opt_move_1(R, [{set,_,_,_}=I|Is], Acc) ->
+ %% If the source register is either killed or used by this
+ %% instruction, the optimimization is not possible.
+ case is_killed_or_used(R, I) of
+ true -> not_possible;
+ false -> opt_move_1(R, Is, [I|Acc])
end;
-opt_move_1(R, [I|Is], SafeRegs, Acc) ->
- case is_transparent(R, I) of
- false -> not_possible;
- true -> opt_move_1(R, Is, SafeRegs, [I|Acc])
- end.
+opt_move_1(_, _, _) ->
+ not_possible.
+
+%% opt_tuple_element([Instruction]) -> [Instruction]
+%% If possible, move get_tuple_element instructions forward
+%% in the instruction stream to a move instruction, eliminating
+%% the move instruction. Example:
+%%
+%% get_tuple_element Tuple Pos Dst1
+%% ...
+%% move Dst1 Dst2
+%%
+%% This code may be possible to rewrite to:
+%%
+%% %%(Moved get_tuple_element instruction)
+%% ...
+%% get_tuple_element Tuple Pos Dst2
+%%
+
+opt_tuple_element([{set,[D],[S],{get_tuple_element,_}}=I|Is0]) ->
+ case opt_tuple_element_1(Is0, I, {S,D}, []) of
+ no ->
+ [I|opt_tuple_element(Is0)];
+ {yes,Is} ->
+ opt_tuple_element(Is)
+ end;
+opt_tuple_element([I|Is]) ->
+ [I|opt_tuple_element(Is)];
+opt_tuple_element([]) -> [].
+
+opt_tuple_element_1([{set,_,_,{alloc,_,_}}|_], _, _, _) ->
+ no;
+opt_tuple_element_1([{set,_,_,{try_catch,_,_}}|_], _, _, _) ->
+ no;
+opt_tuple_element_1([{set,[D],[S],move}|Is0], I0, {_,S}, Acc) ->
+ case eliminate_use_of_from_reg(Is0, S, D, []) of
+ no ->
+ no;
+ {yes,Is} ->
+ {set,[S],Ss,Op} = I0,
+ I = {set,[D],Ss,Op},
+ {yes,reverse(Acc, [I|Is])}
+ end;
+opt_tuple_element_1([{set,Ds,Ss,_}=I|Is], MovedI, {S,D}=Regs, Acc) ->
+ case member(S, Ds) orelse member(D, Ss) of
+ true ->
+ no;
+ false ->
+ opt_tuple_element_1(Is, MovedI, Regs, [I|Acc])
+ end;
+opt_tuple_element_1(_, _, _, _) -> no.
-%% Reverse the instructions, while checking that there are no instructions that
-%% would interfere with using the new destination register chosen.
+%% Reverse the instructions, while checking that there are no
+%% instructions that would interfere with using the new destination
+%% register (D).
-opt_move_2(D, [I|Is], Acc) ->
- case is_transparent(D, I) of
- false -> not_possible;
- true -> opt_move_2(D, Is, [I|Acc])
+opt_move_rev(D, [I|Is], Acc) ->
+ case is_killed_or_used(D, I) of
+ true -> not_possible;
+ false -> opt_move_rev(D, Is, [I|Acc])
end;
-opt_move_2(D, [], Acc) -> {D,Acc}.
-
-%% is_transparent(Register, Instruction) -> true | false
-%% Returns true if Instruction does not in any way references Register
-%% (even indirectly by an allocation instruction).
-%% Returns false if Instruction does reference Register, or we are
-%% not sure.
-
-is_transparent({x,X}, {set,_,_,{alloc,Live,_}}) when X < Live ->
- false;
-is_transparent(R, {set,Ds,Ss,_Op}) ->
- case member(R, Ds) of
- true -> false;
- false -> not member(R, Ss)
+opt_move_rev(D, [], Acc) -> {D,Acc}.
+
+%% is_killed_or_used(Register, {set,_,_,_}) -> bool()
+%% Test whether the register is used by the instruction.
+
+is_killed_or_used(R, {set,Ss,Ds,_}) ->
+ member(R, Ds) orelse member(R, Ss).
+
+%% eliminate_use_of_from_reg([Instruction], FromRegister, ToRegister, Acc) ->
+%% {yes,Is} | no
+%% Eliminate any use of FromRegister in the instruction sequence
+%% by replacing uses of FromRegister with ToRegister. If FromRegister
+%% is referenced by an allocation instruction, return 'no' to indicate
+%% that FromRegister is still used and that the optimization is not
+%% possible.
+
+eliminate_use_of_from_reg([{set,_,_,{alloc,Live,_}}|_]=Is0, {x,X}, _, Acc) ->
+ if
+ X < Live ->
+ no;
+ true ->
+ {yes,reverse(Acc, Is0)}
+ end;
+eliminate_use_of_from_reg([{set,Ds,Ss0,Op}=I0|Is], From, To, Acc) ->
+ I = case member(From, Ss0) of
+ true ->
+ Ss = [case S of
+ From -> To;
+ _ -> S
+ end || S <- Ss0],
+ {set,Ds,Ss,Op};
+ false ->
+ I0
+ end,
+ case member(From, Ds) of
+ true ->
+ {yes,reverse(Acc, [I|Is])};
+ false ->
+ eliminate_use_of_from_reg(Is, From, To, [I|Acc])
end;
-is_transparent(_, _) -> false.
+eliminate_use_of_from_reg([I]=Is, From, _To, Acc) ->
+ case beam_utils:is_killed_block(From, [I]) of
+ true ->
+ {yes,reverse(Acc, Is)};
+ false ->
+ no
+ end.
%% opt_alloc(Instructions) -> Instructions'
%% Optimises all allocate instructions.
opt_alloc([{set,[],[],{alloc,R,{_,Ns,Nh,[]}}}|Is]) ->
- [{set,[],[],opt_alloc(Is, Ns, Nh, R)}|opt(Is)];
+ [{set,[],[],opt_alloc(Is, Ns, Nh, R)}|Is];
opt_alloc([I|Is]) -> [I|opt_alloc(Is)];
opt_alloc([]) -> [].
@@ -414,234 +453,3 @@ 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.
-
-%%%
-%%% Evaluation of constant bit fields.
-%%%
-
-is_bs_put({bs_put,_,{bs_put_integer,_,_},_}) -> true;
-is_bs_put({bs_put,_,{bs_put_float,_,_},_}) -> true;
-is_bs_put(_) -> false.
-
-collect_bs_puts(Is) ->
- collect_bs_puts_1(Is, []).
-
-collect_bs_puts_1([I|Is]=Is0, Acc) ->
- case is_bs_put(I) of
- false -> {reverse(Acc),Is0};
- true -> collect_bs_puts_1(Is, [I|Acc])
- end.
-
-opt_bs_puts(Is) ->
- opt_bs_1(Is, []).
-
-opt_bs_1([{bs_put,Fail,
- {bs_put_float,1,Flags0},[{integer,Sz},Src]}=I0|Is], Acc) ->
- try eval_put_float(Src, Sz, Flags0) of
- <<Int:Sz>> ->
- Flags = force_big(Flags0),
- I = {bs_put,Fail,{bs_put_integer,1,Flags},
- [{integer,Sz},{integer,Int}]},
- opt_bs_1([I|Is], Acc)
- catch
- error:_ ->
- opt_bs_1(Is, [I0|Acc])
- end;
-opt_bs_1([{bs_put,_,{bs_put_integer,1,_},[{integer,8},{integer,_}]}|_]=IsAll,
- Acc0) ->
- {Is,Acc} = bs_collect_string(IsAll, Acc0),
- opt_bs_1(Is, Acc);
-opt_bs_1([{bs_put,Fail,{bs_put_integer,1,F},[{integer,Sz},{integer,N}]}=I|Is0],
- Acc) when Sz > 8 ->
- case field_endian(F) of
- big ->
- %% We can do this optimization for any field size without risk
- %% for code explosion.
- case bs_split_int(N, Sz, Fail, Is0) of
- no_split -> opt_bs_1(Is0, [I|Acc]);
- Is -> opt_bs_1(Is, Acc)
- end;
- little when Sz < 128 ->
- %% We only try to optimize relatively small fields, to avoid
- %% an explosion in code size.
- <<Int:Sz>> = <<N:Sz/little>>,
- Flags = force_big(F),
- Is = [{bs_put,Fail,{bs_put_integer,1,Flags},
- [{integer,Sz},{integer,Int}]}|Is0],
- opt_bs_1(Is, Acc);
- _ -> %native or too wide little field
- opt_bs_1(Is0, [I|Acc])
- end;
-opt_bs_1([{bs_put,Fail,{Op,U,F},[{integer,Sz},Src]}|Is], Acc) when U > 1 ->
- opt_bs_1([{bs_put,Fail,{Op,1,F},[{integer,U*Sz},Src]}|Is], Acc);
-opt_bs_1([I|Is], Acc) ->
- opt_bs_1(Is, [I|Acc]);
-opt_bs_1([], Acc) -> reverse(Acc).
-
-eval_put_float(Src, Sz, Flags) when Sz =< 256 -> %Only evaluate if Sz is reasonable.
- Val = value(Src),
- case field_endian(Flags) of
- little -> <<Val:Sz/little-float-unit:1>>;
- big -> <<Val:Sz/big-float-unit:1>>
- %% native intentionally not handled here - we can't optimize it.
- end.
-
-value({integer,I}) -> I;
-value({float,F}) -> F.
-
-bs_collect_string(Is, [{bs_put,_,{bs_put_string,Len,{string,Str}},[]}|Acc]) ->
- bs_coll_str_1(Is, Len, reverse(Str), Acc);
-bs_collect_string(Is, Acc) ->
- bs_coll_str_1(Is, 0, [], Acc).
-
-bs_coll_str_1([{bs_put,_,{bs_put_integer,U,_},[{integer,Sz},{integer,V}]}|Is],
- Len, StrAcc, IsAcc) when U*Sz =:= 8 ->
- Byte = V band 16#FF,
- bs_coll_str_1(Is, Len+1, [Byte|StrAcc], IsAcc);
-bs_coll_str_1(Is, Len, StrAcc, IsAcc) ->
- {Is,[{bs_put,{f,0},{bs_put_string,Len,{string,reverse(StrAcc)}},[]}|IsAcc]}.
-
-field_endian({field_flags,F}) -> field_endian_1(F).
-
-field_endian_1([big=E|_]) -> E;
-field_endian_1([little=E|_]) -> E;
-field_endian_1([native=E|_]) -> E;
-field_endian_1([_|Fs]) -> field_endian_1(Fs).
-
-force_big({field_flags,F}) ->
- {field_flags,force_big_1(F)}.
-
-force_big_1([big|_]=Fs) -> Fs;
-force_big_1([little|Fs]) -> [big|Fs];
-force_big_1([F|Fs]) -> [F|force_big_1(Fs)].
-
-bs_split_int(0, Sz, _, _) when Sz > 64 ->
- %% We don't want to split in this case because the
- %% string will consist of only zeroes.
- no_split;
-bs_split_int(-1, Sz, _, _) when Sz > 64 ->
- %% We don't want to split in this case because the
- %% string will consist of only 255 bytes.
- no_split;
-bs_split_int(N, Sz, Fail, Acc) ->
- FirstByteSz = case Sz rem 8 of
- 0 -> 8;
- Rem -> Rem
- end,
- bs_split_int_1(N, FirstByteSz, Sz, Fail, Acc).
-
-bs_split_int_1(-1, _, Sz, Fail, Acc) when Sz > 64 ->
- I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}},
- [{integer,Sz},{integer,-1}]},
- [I|Acc];
-bs_split_int_1(0, _, Sz, Fail, Acc) when Sz > 64 ->
- I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}},
- [{integer,Sz},{integer,0}]},
- [I|Acc];
-bs_split_int_1(N, ByteSz, Sz, Fail, Acc) when Sz > 0 ->
- Mask = (1 bsl ByteSz) - 1,
- I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}},
- [{integer,ByteSz},{integer,N band Mask}]},
- bs_split_int_1(N bsr ByteSz, 8, Sz-ByteSz, Fail, [I|Acc]);
-bs_split_int_1(_, _, _, _, Acc) -> Acc.
-
-
-%%%
-%%% Optimization of new bit syntax matching: get rid
-%%% of redundant bs_restore2/2 instructions across select_val
-%%% instructions, as well as a few other simple peep-hole optimizations.
-%%%
-
-bsm_opt(Is0, Lc0) ->
- {Is1,D0,Lc} = bsm_scan(Is0, [], Lc0, []),
- Is2 = case D0 of
- [] ->
- Is1;
- _ ->
- D = gb_trees:from_orddict(orddict:from_list(D0)),
- bsm_reroute(Is1, D, none, [])
- end,
- Is = beam_clean:bs_clean_saves(Is2),
- {bsm_opt_2(Is, []),Lc}.
-
-bsm_scan([{label,L}=Lbl,{bs_restore2,_,Save}=R|Is], D0, Lc, Acc0) ->
- D = [{{L,Save},Lc}|D0],
- Acc = [{label,Lc},R,Lbl|Acc0],
- bsm_scan(Is, D, Lc+1, Acc);
-bsm_scan([I|Is], D, Lc, Acc) ->
- bsm_scan(Is, D, Lc, [I|Acc]);
-bsm_scan([], D, Lc, Acc) ->
- {reverse(Acc),D,Lc}.
-
-bsm_reroute([{bs_save2,Reg,Save}=I|Is], D, _, Acc) ->
- bsm_reroute(Is, D, {Reg,Save}, [I|Acc]);
-bsm_reroute([{bs_restore2,Reg,Save}=I|Is], D, _, Acc) ->
- bsm_reroute(Is, D, {Reg,Save}, [I|Acc]);
-bsm_reroute([{label,_}=I|Is], D, S, Acc) ->
- bsm_reroute(Is, D, S, [I|Acc]);
-bsm_reroute([{select,select_val,Reg,F0,Lbls0}|Is], D, {_,Save}=S, Acc0) ->
- [F|Lbls] = bsm_subst_labels([F0|Lbls0], Save, D),
- Acc = [{select,select_val,Reg,F,Lbls}|Acc0],
- bsm_reroute(Is, D, S, Acc);
-bsm_reroute([{test,TestOp,F0,TestArgs}=I|Is], D, {_,Save}=S, Acc0) ->
- F = bsm_subst_label(F0, Save, D),
- Acc = [{test,TestOp,F,TestArgs}|Acc0],
- case bsm_not_bs_test(I) of
- true ->
- %% The test instruction will not update the bit offset for the
- %% binary being matched. Therefore the save position can be kept.
- bsm_reroute(Is, D, S, Acc);
- false ->
- %% The test instruction might update the bit offset. Kill our
- %% remembered Save position.
- bsm_reroute(Is, D, none, Acc)
- end;
-bsm_reroute([{test,TestOp,F0,Live,TestArgs,Dst}|Is], D, {_,Save}, Acc0) ->
- F = bsm_subst_label(F0, Save, D),
- Acc = [{test,TestOp,F,Live,TestArgs,Dst}|Acc0],
- %% The test instruction will update the bit offset. Kill our
- %% remembered Save position.
- bsm_reroute(Is, D, none, Acc);
-bsm_reroute([{block,[{set,[],[],{alloc,_,_}}]}=Bl,
- {bs_context_to_binary,_}=I|Is], D, S, Acc) ->
- %% To help further bit syntax optimizations.
- bsm_reroute([I,Bl|Is], D, S, Acc);
-bsm_reroute([I|Is], D, _, Acc) ->
- bsm_reroute(Is, D, none, [I|Acc]);
-bsm_reroute([], _, _, Acc) -> reverse(Acc).
-
-bsm_opt_2([{test,bs_test_tail2,F,[Ctx,Bits]}|Is],
- [{test,bs_skip_bits2,F,[Ctx,{integer,I},Unit,_Flags]}|Acc]) ->
- bsm_opt_2(Is, [{test,bs_test_tail2,F,[Ctx,Bits+I*Unit]}|Acc]);
-bsm_opt_2([{test,bs_skip_bits2,F,[Ctx,{integer,I1},Unit1,_]}|Is],
- [{test,bs_skip_bits2,F,[Ctx,{integer,I2},Unit2,Flags]}|Acc]) ->
- bsm_opt_2(Is, [{test,bs_skip_bits2,F,
- [Ctx,{integer,I1*Unit1+I2*Unit2},1,Flags]}|Acc]);
-bsm_opt_2([I|Is], Acc) ->
- bsm_opt_2(Is, [I|Acc]);
-bsm_opt_2([], Acc) -> reverse(Acc).
-
-%% bsm_not_bs_test({test,Name,_,Operands}) -> true|false.
-%% Test whether is the test is a "safe", i.e. does not move the
-%% bit offset for a binary.
-%%
-%% 'true' means that the test is safe, 'false' that we don't know or
-%% that the test moves the offset (e.g. bs_get_integer2).
-
-bsm_not_bs_test({test,bs_test_tail2,_,[_,_]}) -> true;
-bsm_not_bs_test(Test) -> beam_utils:is_pure_test(Test).
-
-bsm_subst_labels(Fs, Save, D) ->
- bsm_subst_labels_1(Fs, Save, D, []).
-
-bsm_subst_labels_1([F|Fs], Save, D, Acc) ->
- bsm_subst_labels_1(Fs, Save, D, [bsm_subst_label(F, Save, D)|Acc]);
-bsm_subst_labels_1([], _, _, Acc) ->
- reverse(Acc).
-
-bsm_subst_label({f,Lbl0}=F, Save, D) ->
- case gb_trees:lookup({Lbl0,Save}, D) of
- {value,Lbl} -> {f,Lbl};
- none -> F
- end;
-bsm_subst_label(Other, _, _) -> Other.
diff --git a/lib/compiler/src/beam_bool.erl b/lib/compiler/src/beam_bool.erl
index d14be83496..efd935f666 100644
--- a/lib/compiler/src/beam_bool.erl
+++ b/lib/compiler/src/beam_bool.erl
@@ -25,8 +25,6 @@
-import(lists, [reverse/1,reverse/2,foldl/3,mapfoldl/3,map/2]).
--define(MAXREG, 1024).
-
-record(st,
{next, %Next label number.
ll %Live regs at labels.
diff --git a/lib/compiler/src/beam_bs.erl b/lib/compiler/src/beam_bs.erl
new file mode 100644
index 0000000000..55fa7ce10c
--- /dev/null
+++ b/lib/compiler/src/beam_bs.erl
@@ -0,0 +1,278 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2013. 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%
+%%
+%% Purpose : Partitions assembly instructions into basic blocks and
+%% optimizes them.
+
+-module(beam_bs).
+
+-export([module/2]).
+-import(lists, [mapfoldl/3,reverse/1]).
+
+module({Mod,Exp,Attr,Fs0,Lc0}, _Opt) ->
+ {Fs,Lc} = mapfoldl(fun function/2, Lc0, Fs0),
+ {ok,{Mod,Exp,Attr,Fs,Lc}}.
+
+function({function,Name,Arity,CLabel,Is0}, Lc0) ->
+ try
+ Is1 = bs_put_opt(Is0),
+ {Is,Lc} = bsm_opt(Is1, Lc0),
+ {{function,Name,Arity,CLabel,Is},Lc}
+ catch
+ Class:Error ->
+ Stack = erlang:get_stacktrace(),
+ io:fwrite("Function: ~w/~w\n", [Name,Arity]),
+ erlang:raise(Class, Error, Stack)
+ end.
+
+%%%
+%%% Evaluation of constant bit fields.
+%%%
+
+bs_put_opt([{bs_put,_,_,_}=I|Is0]) ->
+ {BsPuts0,Is} = collect_bs_puts(Is0, [I]),
+ BsPuts = opt_bs_puts(BsPuts0),
+ BsPuts ++ bs_put_opt(Is);
+bs_put_opt([I|Is]) ->
+ [I|bs_put_opt(Is)];
+bs_put_opt([]) -> [].
+
+collect_bs_puts([{bs_put,_,_,_}=I|Is], Acc) ->
+ collect_bs_puts(Is, [I|Acc]);
+collect_bs_puts([_|_]=Is, Acc) ->
+ {reverse(Acc),Is}.
+
+opt_bs_puts(Is) ->
+ opt_bs_1(Is, []).
+
+opt_bs_1([{bs_put,Fail,
+ {bs_put_float,1,Flags0},[{integer,Sz},Src]}=I0|Is], Acc) ->
+ try eval_put_float(Src, Sz, Flags0) of
+ <<Int:Sz>> ->
+ Flags = force_big(Flags0),
+ I = {bs_put,Fail,{bs_put_integer,1,Flags},
+ [{integer,Sz},{integer,Int}]},
+ opt_bs_1([I|Is], Acc)
+ catch
+ error:_ ->
+ opt_bs_1(Is, [I0|Acc])
+ end;
+opt_bs_1([{bs_put,_,{bs_put_integer,1,_},[{integer,8},{integer,_}]}|_]=IsAll,
+ Acc0) ->
+ {Is,Acc} = bs_collect_string(IsAll, Acc0),
+ opt_bs_1(Is, Acc);
+opt_bs_1([{bs_put,Fail,{bs_put_integer,1,F},[{integer,Sz},{integer,N}]}=I|Is0],
+ Acc) when Sz > 8 ->
+ case field_endian(F) of
+ big ->
+ %% We can do this optimization for any field size without
+ %% risk for code explosion.
+ case bs_split_int(N, Sz, Fail, Is0) of
+ no_split -> opt_bs_1(Is0, [I|Acc]);
+ Is -> opt_bs_1(Is, Acc)
+ end;
+ little when Sz < 128 ->
+ %% We only try to optimize relatively small fields, to
+ %% avoid an explosion in code size.
+ <<Int:Sz>> = <<N:Sz/little>>,
+ Flags = force_big(F),
+ Is = [{bs_put,Fail,{bs_put_integer,1,Flags},
+ [{integer,Sz},{integer,Int}]}|Is0],
+ opt_bs_1(Is, Acc);
+ _ -> %native or too wide little field
+ opt_bs_1(Is0, [I|Acc])
+ end;
+opt_bs_1([{bs_put,Fail,{Op,U,F},[{integer,Sz},Src]}|Is], Acc) when U > 1 ->
+ opt_bs_1([{bs_put,Fail,{Op,1,F},[{integer,U*Sz},Src]}|Is], Acc);
+opt_bs_1([I|Is], Acc) ->
+ opt_bs_1(Is, [I|Acc]);
+opt_bs_1([], Acc) -> reverse(Acc).
+
+eval_put_float(Src, Sz, Flags) when Sz =< 256 ->
+ %%Only evaluate if Sz is reasonable.
+ Val = value(Src),
+ case field_endian(Flags) of
+ little -> <<Val:Sz/little-float-unit:1>>;
+ big -> <<Val:Sz/big-float-unit:1>>
+ %% native intentionally not handled here - we can't optimize
+ %% it.
+ end.
+
+value({integer,I}) -> I;
+value({float,F}) -> F.
+
+bs_collect_string(Is, [{bs_put,_,{bs_put_string,Len,{string,Str}},[]}|Acc]) ->
+ bs_coll_str_1(Is, Len, reverse(Str), Acc);
+bs_collect_string(Is, Acc) ->
+ bs_coll_str_1(Is, 0, [], Acc).
+
+bs_coll_str_1([{bs_put,_,{bs_put_integer,U,_},[{integer,Sz},{integer,V}]}|Is],
+ Len, StrAcc, IsAcc) when U*Sz =:= 8 ->
+ Byte = V band 16#FF,
+ bs_coll_str_1(Is, Len+1, [Byte|StrAcc], IsAcc);
+bs_coll_str_1(Is, Len, StrAcc, IsAcc) ->
+ {Is,[{bs_put,{f,0},{bs_put_string,Len,{string,reverse(StrAcc)}},[]}|IsAcc]}.
+
+field_endian({field_flags,F}) -> field_endian_1(F).
+
+field_endian_1([big=E|_]) -> E;
+field_endian_1([little=E|_]) -> E;
+field_endian_1([native=E|_]) -> E;
+field_endian_1([_|Fs]) -> field_endian_1(Fs).
+
+force_big({field_flags,F}) ->
+ {field_flags,force_big_1(F)}.
+
+force_big_1([big|_]=Fs) -> Fs;
+force_big_1([little|Fs]) -> [big|Fs];
+force_big_1([F|Fs]) -> [F|force_big_1(Fs)].
+
+bs_split_int(0, Sz, _, _) when Sz > 64 ->
+ %% We don't want to split in this case because the
+ %% string will consist of only zeroes.
+ no_split;
+bs_split_int(-1, Sz, _, _) when Sz > 64 ->
+ %% We don't want to split in this case because the
+ %% string will consist of only 255 bytes.
+ no_split;
+bs_split_int(N, Sz, Fail, Acc) ->
+ FirstByteSz = case Sz rem 8 of
+ 0 -> 8;
+ Rem -> Rem
+ end,
+ bs_split_int_1(N, FirstByteSz, Sz, Fail, Acc).
+
+bs_split_int_1(-1, _, Sz, Fail, Acc) when Sz > 64 ->
+ I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}},
+ [{integer,Sz},{integer,-1}]},
+ [I|Acc];
+bs_split_int_1(0, _, Sz, Fail, Acc) when Sz > 64 ->
+ I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}},
+ [{integer,Sz},{integer,0}]},
+ [I|Acc];
+bs_split_int_1(N, ByteSz, Sz, Fail, Acc) when Sz > 0 ->
+ Mask = (1 bsl ByteSz) - 1,
+ I = {bs_put,Fail,{bs_put_integer,1,{field_flags,[big]}},
+ [{integer,ByteSz},{integer,N band Mask}]},
+ bs_split_int_1(N bsr ByteSz, 8, Sz-ByteSz, Fail, [I|Acc]);
+bs_split_int_1(_, _, _, _, Acc) -> Acc.
+
+%%%
+%%% Optimization of bit syntax matching: get rid
+%%% of redundant bs_restore2/2 instructions across select_val
+%%% instructions, as well as a few other simple peep-hole
+%%% optimizations.
+%%%
+
+bsm_opt(Is0, Lc0) ->
+ {Is1,D0,Lc} = bsm_scan(Is0, [], Lc0, []),
+ Is2 = case D0 of
+ [] ->
+ %% No bit syntax matching in this function.
+ Is1;
+ [_|_] ->
+ %% Optimize the bit syntax matching.
+ D = gb_trees:from_orddict(orddict:from_list(D0)),
+ bsm_reroute(Is1, D, none, [])
+ end,
+ Is = beam_clean:bs_clean_saves(Is2),
+ {bsm_opt_2(Is, []),Lc}.
+
+bsm_scan([{label,L}=Lbl,{bs_restore2,_,Save}=R|Is], D0, Lc, Acc0) ->
+ D = [{{L,Save},Lc}|D0],
+ Acc = [{label,Lc},R,Lbl|Acc0],
+ bsm_scan(Is, D, Lc+1, Acc);
+bsm_scan([I|Is], D, Lc, Acc) ->
+ bsm_scan(Is, D, Lc, [I|Acc]);
+bsm_scan([], D, Lc, Acc) ->
+ {reverse(Acc),D,Lc}.
+
+bsm_reroute([{bs_save2,Reg,Save}=I|Is], D, _, Acc) ->
+ bsm_reroute(Is, D, {Reg,Save}, [I|Acc]);
+bsm_reroute([{bs_restore2,Reg,Save}=I|Is], D, _, Acc) ->
+ bsm_reroute(Is, D, {Reg,Save}, [I|Acc]);
+bsm_reroute([{label,_}=I|Is], D, S, Acc) ->
+ bsm_reroute(Is, D, S, [I|Acc]);
+bsm_reroute([{select,select_val,Reg,F0,Lbls0}|Is], D, {_,Save}=S, Acc0) ->
+ [F|Lbls] = bsm_subst_labels([F0|Lbls0], Save, D),
+ Acc = [{select,select_val,Reg,F,Lbls}|Acc0],
+ bsm_reroute(Is, D, S, Acc);
+bsm_reroute([{test,TestOp,F0,TestArgs}=I|Is], D, {_,Save}=S, Acc0) ->
+ F = bsm_subst_label(F0, Save, D),
+ Acc = [{test,TestOp,F,TestArgs}|Acc0],
+ case bsm_not_bs_test(I) of
+ true ->
+ %% The test instruction will not update the bit offset for
+ %% the binary being matched. Therefore the save position
+ %% can be kept.
+ bsm_reroute(Is, D, S, Acc);
+ false ->
+ %% The test instruction might update the bit offset. Kill
+ %% our remembered Save position.
+ bsm_reroute(Is, D, none, Acc)
+ end;
+bsm_reroute([{test,TestOp,F0,Live,TestArgs,Dst}|Is], D, {_,Save}, Acc0) ->
+ F = bsm_subst_label(F0, Save, D),
+ Acc = [{test,TestOp,F,Live,TestArgs,Dst}|Acc0],
+ %% The test instruction will update the bit offset. Kill our
+ %% remembered Save position.
+ bsm_reroute(Is, D, none, Acc);
+bsm_reroute([{block,[{set,[],[],{alloc,_,_}}]}=Bl,
+ {bs_context_to_binary,_}=I|Is], D, S, Acc) ->
+ %% To help further bit syntax optimizations.
+ bsm_reroute([I,Bl|Is], D, S, Acc);
+bsm_reroute([I|Is], D, _, Acc) ->
+ bsm_reroute(Is, D, none, [I|Acc]);
+bsm_reroute([], _, _, Acc) -> reverse(Acc).
+
+bsm_opt_2([{test,bs_test_tail2,F,[Ctx,Bits]}|Is],
+ [{test,bs_skip_bits2,F,[Ctx,{integer,I},Unit,_Flags]}|Acc]) ->
+ bsm_opt_2(Is, [{test,bs_test_tail2,F,[Ctx,Bits+I*Unit]}|Acc]);
+bsm_opt_2([{test,bs_skip_bits2,F,[Ctx,{integer,I1},Unit1,_]}|Is],
+ [{test,bs_skip_bits2,F,[Ctx,{integer,I2},Unit2,Flags]}|Acc]) ->
+ bsm_opt_2(Is, [{test,bs_skip_bits2,F,
+ [Ctx,{integer,I1*Unit1+I2*Unit2},1,Flags]}|Acc]);
+bsm_opt_2([I|Is], Acc) ->
+ bsm_opt_2(Is, [I|Acc]);
+bsm_opt_2([], Acc) -> reverse(Acc).
+
+%% bsm_not_bs_test({test,Name,_,Operands}) -> true|false.
+%% Test whether is the test is a "safe", i.e. does not move the
+%% bit offset for a binary.
+%%
+%% 'true' means that the test is safe, 'false' that we don't know or
+%% that the test moves the offset (e.g. bs_get_integer2).
+
+bsm_not_bs_test({test,bs_test_tail2,_,[_,_]}) -> true;
+bsm_not_bs_test(Test) -> beam_utils:is_pure_test(Test).
+
+bsm_subst_labels(Fs, Save, D) ->
+ bsm_subst_labels_1(Fs, Save, D, []).
+
+bsm_subst_labels_1([F|Fs], Save, D, Acc) ->
+ bsm_subst_labels_1(Fs, Save, D, [bsm_subst_label(F, Save, D)|Acc]);
+bsm_subst_labels_1([], _, _, Acc) ->
+ reverse(Acc).
+
+bsm_subst_label({f,Lbl0}=F, Save, D) ->
+ case gb_trees:lookup({Lbl0,Save}, D) of
+ {value,Lbl} -> {f,Lbl};
+ none -> F
+ end;
+bsm_subst_label(Other, _, _) -> Other.
diff --git a/lib/compiler/src/beam_clean.erl b/lib/compiler/src/beam_clean.erl
index 919ee3ee7d..d9108c383d 100644
--- a/lib/compiler/src/beam_clean.erl
+++ b/lib/compiler/src/beam_clean.erl
@@ -141,7 +141,7 @@ renumber_labels([{bif,is_record,{f,_},
renumber_labels(Is, Acc, St);
renumber_labels([{test,is_record,{f,_}=Fail,
[Term,{atom,Tag}=TagAtom,{integer,Arity}]}|Is0], Acc, St) ->
- Tmp = {x,1023},
+ Tmp = {x,1022},
Is = case is_record_tuple(Term, Tag, Arity) of
yes ->
Is0;
@@ -190,17 +190,11 @@ replace([{test,Test,{f,Lbl},Ops}|Is], Acc, D) ->
replace([{test,Test,{f,Lbl},Live,Ops,Dst}|Is], Acc, D) ->
replace(Is, [{test,Test,{f,label(Lbl, D)},Live,Ops,Dst}|Acc], D);
replace([{select,I,R,{f,Fail0},Vls0}|Is], Acc, D) ->
- Vls1 = map(fun ({f,L}) -> {f,label(L, D)};
- (Other) -> Other end, Vls0),
+ Vls = map(fun ({f,L}) -> {f,label(L, D)};
+ (Other) -> Other
+ end, Vls0),
Fail = label(Fail0, D),
- case redundant_values(Vls1, Fail, []) of
- [] ->
- %% Oops, no choices left. The loader will not accept that.
- %% Convert to a plain jump.
- replace(Is, [{jump,{f,Fail}}|Acc], D);
- Vls ->
- replace(Is, [{select,I,R,{f,Fail},Vls}|Acc], D)
- end;
+ replace(Is, [{select,I,R,{f,Fail},Vls}|Acc], D);
replace([{'try',R,{f,Lbl}}|Is], Acc, D) ->
replace(Is, [{'try',R,{f,label(Lbl, D)}}|Acc], D);
replace([{'catch',R,{f,Lbl}}|Is], Acc, D) ->
@@ -241,12 +235,6 @@ label(Old, D) ->
{value,Val} -> Val;
none -> throw({error,{undefined_label,Old}})
end.
-
-redundant_values([_,{f,Fail}|Vls], Fail, Acc) ->
- redundant_values(Vls, Fail, Acc);
-redundant_values([Val,Lbl|Vls], Fail, Acc) ->
- redundant_values(Vls, Fail, [Lbl,Val|Acc]);
-redundant_values([], _, Acc) -> reverse(Acc).
%%%
%%% Final fixup of bs_start_match2/5,bs_save2/bs_restore2 instructions for
diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl
index ead88b57e9..11129c39bc 100644
--- a/lib/compiler/src/beam_dead.erl
+++ b/lib/compiler/src/beam_dead.erl
@@ -239,11 +239,26 @@ backward([{test,is_eq_exact,Fail,[Dst,{integer,Arity}]}=I|
backward([{label,Lbl}=L|Is], D, Acc) ->
backward(Is, beam_utils:index_label(Lbl, Acc, D), [L|Acc]);
backward([{select,select_val,Reg,{f,Fail0},List0}|Is], D, Acc) ->
- List = shortcut_select_list(List0, Reg, D, []),
+ List1 = shortcut_select_list(List0, Reg, D, []),
Fail1 = shortcut_label(Fail0, D),
Fail = shortcut_bs_test(Fail1, Is, D),
- Sel = {select,select_val,Reg,{f,Fail},List},
- backward(Is, D, [Sel|Acc]);
+ List = prune_redundant(List1, Fail),
+ case List of
+ [] ->
+ Jump = {jump,{f,Fail}},
+ backward([Jump|Is], D, Acc);
+ [V,F] ->
+ Test = {test,is_eq_exact,{f,Fail},[Reg,V]},
+ Jump = {jump,F},
+ backward([Jump,Test|Is], D, Acc);
+ [{atom,B1},F,{atom,B2},F] when B1 =:= not B2 ->
+ Test = {test,is_boolean,{f,Fail},[Reg]},
+ Jump = {jump,F},
+ backward([Jump,Test|Is], D, Acc);
+ [_|_] ->
+ Sel = {select,select_val,Reg,{f,Fail},List},
+ backward(Is, D, [Sel|Acc])
+ end;
backward([{jump,{f,To0}},{move,Src,Reg}=Move|Is], D, Acc) ->
To = shortcut_select_label(To0, Reg, Src, D),
Jump = {jump,{f,To}},
@@ -257,14 +272,17 @@ backward([{jump,{f,To}}=J|[{bif,Op,_,Ops,Reg}|Is]=Is0], D, Acc) ->
catch
throw:not_possible -> backward(Is0, D, [J|Acc])
end;
-backward([{test,bs_start_match2,F,_,[R,_],Ctxt}=I|Is], D,
+backward([{test,bs_start_match2,F,Live,[R,_]=Args,Ctxt}|Is], D,
[{test,bs_match_string,F,[Ctxt,Bs]},
{test,bs_test_tail2,F,[Ctxt,0]}|Acc0]=Acc) ->
+ {f,To0} = F,
+ To = shortcut_bs_start_match(To0, R, D),
case beam_utils:is_killed(Ctxt, Acc0, D) of
true ->
- Eq = {test,is_eq_exact,F,[R,{literal,Bs}]},
+ Eq = {test,is_eq_exact,{f,To},[R,{literal,Bs}]},
backward(Is, D, [Eq|Acc0]);
false ->
+ I = {test,bs_start_match2,{f,To},Live,Args,Ctxt},
backward(Is, D, [I|Acc])
end;
backward([{test,bs_start_match2,{f,To0},Live,[Src|_]=Info,Dst}|Is], D, Acc) ->
@@ -295,7 +313,28 @@ backward([{test,Op,{f,To0},Ops0}|Is], D, Acc) ->
is_eq_exact -> combine_eqs(To, Ops0, D, Acc);
_ -> {test,Op,{f,To},Ops0}
end,
- backward(Is, D, [I|Acc]);
+ case {I,Acc} of
+ {{test,is_atom,Fail,Ops0},[{test,is_boolean,Fail,Ops0}|_]} ->
+ %% An is_atom test before an is_boolean test (with the
+ %% same failure label) is redundant.
+ backward(Is, D, Acc);
+ {{test,is_atom,Fail,[R]},
+ [{test,is_eq_exact,Fail,[R,{atom,_}]}|_]} ->
+ %% An is_atom test before a comparison with an atom (with
+ %% the same failure label) is redundant.
+ backward(Is, D, Acc);
+ {{test,is_integer,Fail,[R]},
+ [{test,is_eq_exact,Fail,[R,{integer,_}]}|_]} ->
+ %% An is_integer test before a comparison with an integer
+ %% (with the same failure label) is redundant.
+ backward(Is, D, Acc);
+ {{test,_,_,_},_} ->
+ %% Still a test instruction. Done.
+ backward(Is, D, [I|Acc]);
+ {_,_} ->
+ %% Rewritten to a select_val. Rescan.
+ backward([I|Is], D, Acc)
+ end;
backward([{test,Op,{f,To0},Live,Ops0,Dst}|Is], D, Acc) ->
To1 = shortcut_bs_test(To0, Is, D),
To2 = shortcut_label(To1, D),
@@ -348,6 +387,12 @@ shortcut_label(To0, D) ->
shortcut_select_label(To, Reg, Lit, D) ->
shortcut_rel_op(To, is_ne_exact, [Reg,Lit], D).
+prune_redundant([_,{f,Fail}|T], Fail) ->
+ prune_redundant(T, Fail);
+prune_redundant([V,F|T], Fail) ->
+ [V,F|prune_redundant(T, Fail)];
+prune_redundant([], _) -> [].
+
%% Replace a comparison operator with a test instruction and a jump.
%% For example, if we have this code:
%%
diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl
index 2b5f8c1b7f..654fb47dbd 100644
--- a/lib/compiler/src/beam_dict.erl
+++ b/lib/compiler/src/beam_dict.erl
@@ -44,7 +44,7 @@
locals = [] :: [{label(), arity(), label()}],
imports = gb_trees:empty() :: import_tab(),
strings = <<>> :: binary(), %String pool
- lambdas = [], %[{...}]
+ lambdas = {0,[]}, %[{...}]
literals = dict:new() :: literal_tab(),
fnames = #{} :: fname_tab(),
lines = #{} :: line_tab(),
@@ -145,15 +145,14 @@ string(Str, Dict) when is_list(Str) ->
-spec lambda(label(), non_neg_integer(), bdict()) ->
{non_neg_integer(), bdict()}.
-lambda(Lbl, NumFree, #asm{lambdas=Lambdas0}=Dict) ->
- OldIndex = length(Lambdas0),
+lambda(Lbl, NumFree, #asm{lambdas={OldIndex,Lambdas0}}=Dict) ->
%% Set Index the same as OldIndex.
Index = OldIndex,
%% Initialize OldUniq to 0. It will be set to an unique value
%% based on the MD5 checksum of the BEAM code for the module.
OldUniq = 0,
Lambdas = [{Lbl,{OldIndex,Lbl,Index,NumFree,OldUniq}}|Lambdas0],
- {OldIndex,Dict#asm{lambdas=Lambdas}}.
+ {OldIndex,Dict#asm{lambdas={OldIndex+1,Lambdas}}}.
%% Returns the index for a literal (adding it to the literal table if necessary).
%% literal(Literal, Dict) -> {Index,Dict'}
@@ -236,13 +235,13 @@ string_table(#asm{strings=Strings,string_offset=Size}) ->
-spec lambda_table(bdict()) -> {non_neg_integer(), [<<_:192>>]}.
-lambda_table(#asm{locals=Loc0,lambdas=Lambdas0}) ->
+lambda_table(#asm{locals=Loc0,lambdas={NumLambdas,Lambdas0}}) ->
Lambdas1 = sofs:relation(Lambdas0),
Loc = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Loc0]),
Lambdas2 = sofs:relative_product1(Lambdas1, Loc),
Lambdas = [<<F:32,A:32,Lbl:32,Index:32,NumFree:32,OldUniq:32>> ||
{{_,Lbl,Index,NumFree,OldUniq},{F,A}} <- sofs:to_external(Lambdas2)],
- {length(Lambdas),Lambdas}.
+ {NumLambdas,Lambdas}.
%% Returns the literal table.
%% literal_table(Dict) -> {NumLiterals, [<<TermSize>>,TermInExternalFormat]}
diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl
index 5e58e0f6ac..3b6eb19fe8 100644
--- a/lib/compiler/src/beam_jump.erl
+++ b/lib/compiler/src/beam_jump.erl
@@ -495,7 +495,7 @@ is_label_used_in_block({set,_,_,Info}, Lbl) ->
{alloc,_,{gc_bif,_,{f,F}}} -> F =:= Lbl;
{alloc,_,{put_map,_,{f,F}}} -> F =:= Lbl;
{get_map_elements,{f,F}} -> F =:= Lbl;
- {'catch',{f,F}} -> F =:= Lbl;
+ {try_catch,_,{f,F}} -> F =:= Lbl;
{alloc,_,_} -> false;
{put_tuple,_} -> false;
{get_tuple_element,_} -> false;
diff --git a/lib/compiler/src/beam_peep.erl b/lib/compiler/src/beam_peep.erl
index 17fd2e502a..0c1abfe6a0 100644
--- a/lib/compiler/src/beam_peep.erl
+++ b/lib/compiler/src/beam_peep.erl
@@ -65,18 +65,6 @@ function({function,Name,Arity,CLabel,Is0}) ->
%% InEncoding =:= latin1, OutEncoding =:= unicode;
%% InEncoding =:= latin1, OutEncoding =:= utf8 ->
%%
-%% (2) A select_val/4 instruction that only verifies that
-%% its argument is either 'true' or 'false' can be
-%% be replaced with an is_boolean/2 instruction. That is:
-%%
-%% select_val Reg Fail [ true Next false Next ]
-%% Next: ...
-%%
-%% can be rewritten to
-%%
-%% is_boolean Fail Reg
-%% Next: ...
-%%
peep(Is) ->
peep(Is, gb_sets:empty(), []).
@@ -95,12 +83,16 @@ peep([{gc_bif,_,_,_,_,Dst}=I|Is], SeenTests0, Acc) ->
%% Kill all remembered tests that depend on the destination register.
SeenTests = kill_seen(Dst, SeenTests0),
peep(Is, SeenTests, [I|Acc]);
-peep([{test,is_boolean,{f,Fail},Ops}|_]=Is, SeenTests,
- [{test,is_atom,{f,Fail},Ops}|Acc]) ->
- %% The previous is_atom/2 test (with the same failure label) is redundant.
- %% (If is_boolean(Src) is true, is_atom(Src) is also true, so it is
- %% OK to still remember that we have seen is_atom/1.)
- peep(Is, SeenTests, Acc);
+peep([{select,Op,R,F,Vls0}|Is], _, Acc) ->
+ case prune_redundant_values(Vls0, F) of
+ [] ->
+ %% No values left. Must convert to plain jump.
+ I = {jump,F},
+ peep(Is, gb_sets:empty(), [I|Acc]);
+ [_|_]=Vls ->
+ I = {select,Op,R,F,Vls},
+ peep(Is, gb_sets:empty(), [I|Acc])
+ end;
peep([{test,Op,_,Ops}=I|Is], SeenTests0, Acc) ->
case beam_utils:is_pure_test(I) of
false ->
@@ -121,16 +113,6 @@ peep([{test,Op,_,Ops}=I|Is], SeenTests0, Acc) ->
peep(Is, SeenTests, [I|Acc])
end
end;
-peep([{select,select_val,Src,Fail,
- [{atom,false},{f,L},{atom,true},{f,L}]}|
- [{label,L}|_]=Is], SeenTests, Acc) ->
- I = {test,is_boolean,Fail,[Src]},
- peep([I|Is], SeenTests, Acc);
-peep([{select,select_val,Src,Fail,
- [{atom,true},{f,L},{atom,false},{f,L}]}|
- [{label,L}|_]=Is], SeenTests, Acc) ->
- I = {test,is_boolean,Fail,[Src]},
- peep([I|Is], SeenTests, Acc);
peep([I|Is], _, Acc) ->
%% An unknown instruction. Throw away all information we
%% have collected about test instructions.
@@ -155,3 +137,9 @@ kill_seen_1([{_,Ops}=Test|T], Dst) ->
false -> [Test|kill_seen_1(T, Dst)]
end;
kill_seen_1([], _) -> [].
+
+prune_redundant_values([_Val,F|Vls], F) ->
+ prune_redundant_values(Vls, F);
+prune_redundant_values([Val,Lbl|Vls], F) ->
+ [Val,Lbl|prune_redundant_values(Vls, F)];
+prune_redundant_values([], _) -> [].
diff --git a/lib/compiler/src/beam_reorder.erl b/lib/compiler/src/beam_reorder.erl
new file mode 100644
index 0000000000..41586a7bf2
--- /dev/null
+++ b/lib/compiler/src/beam_reorder.erl
@@ -0,0 +1,139 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2013. 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(beam_reorder).
+
+-export([module/2]).
+-import(lists, [member/2,reverse/1]).
+
+module({Mod,Exp,Attr,Fs0,Lc}, _Opt) ->
+ Fs = [function(F) || F <- Fs0],
+ {ok,{Mod,Exp,Attr,Fs,Lc}}.
+
+function({function,Name,Arity,CLabel,Is0}) ->
+ try
+ Is = reorder(Is0),
+ {function,Name,Arity,CLabel,Is}
+ catch
+ Class:Error ->
+ Stack = erlang:get_stacktrace(),
+ io:fwrite("Function: ~w/~w\n", [Name,Arity]),
+ erlang:raise(Class, Error, Stack)
+ end.
+
+%% reorder(Instructions0) -> Instructions
+%% Reorder instructions before the beam_block pass, because reordering
+%% will be more cumbersome when the blocks are in place.
+%%
+%% Execution of get_tuple_element instructions can be delayed until
+%% they are actually needed. Consider the sequence:
+%%
+%% get_tuple_element Tuple Pos Dst
+%% test Test Fail Operands
+%%
+%% If Dst is killed at label Fail (and not referenced in Operands),
+%% we can can swap the instructions:
+%%
+%% test Test Fail Operands
+%% get_tuple_element Tuple Pos Dst
+%%
+%% That can be beneficial in two ways: Firstly, if the branch is taken
+%% we have avoided execution of the get_tuple_element instruction.
+%% Secondly, even if the branch is not taken, subsequent optimization
+%% (opt_blocks/1) may be able to change Dst to the final destination
+%% register and eliminate a 'move' instruction.
+
+reorder(Is) ->
+ D = beam_utils:index_labels(Is),
+ reorder_1(Is, D, []).
+
+reorder_1([{Op,_,_}=TryCatch|[I|Is]=Is0], D, Acc)
+ when Op =:= 'catch'; Op =:= 'try' ->
+ %% Don't allow 'try' or 'catch' instructions to split blocks if
+ %% it can be avoided.
+ case is_safe(I) of
+ false ->
+ reorder_1(Is0, D, [TryCatch|Acc]);
+ true ->
+ reorder_1([TryCatch|Is], D, [I|Acc])
+ end;
+reorder_1([{label,L}=I|_], D, Acc) ->
+ Is = beam_utils:code_at(L, D),
+ reorder_1(Is, D, [I|Acc]);
+reorder_1([{test,is_nonempty_list,_,_}=I|Is], D, Acc) ->
+ %% The run-time system may combine the is_nonempty_list test with
+ %% the following get_list instruction.
+ reorder_1(Is, D, [I|Acc]);
+reorder_1([{test,_,_,_}=I,
+ {select,_,_,_,_}=S|Is], D, Acc) ->
+ %% There is nothing to gain by inserting a get_tuple_element
+ %% instruction between the test instruction and the select
+ %% instruction.
+ reorder_1(Is, D, [S,I|Acc]);
+reorder_1([{test,_,{f,L},Ss}=I|Is0], D0,
+ [{get_tuple_element,_,_,El}=G|Acc0]=Acc) ->
+ case member(El, Ss) of
+ true ->
+ reorder_1(Is0, D0, [I|Acc]);
+ false ->
+ case beam_utils:is_killed_at(El, L, D0) of
+ true ->
+ Is = [I,G|Is0],
+ reorder_1(Is, D0, Acc0);
+ false ->
+ case beam_utils:is_killed(El, Is0, D0) of
+ true ->
+ Code0 = beam_utils:code_at(L, D0),
+ Code = [G|Code0],
+ D = beam_utils:index_label(L, Code, D0),
+ Is = [I|Is0],
+ reorder_1(Is, D, Acc0);
+ false ->
+ reorder_1(Is0, D0, [I|Acc])
+ end
+ end
+ end;
+reorder_1([{allocate_zero,N,Live}=I0|Is], D,
+ [{get_tuple_element,{x,Tup},_,{x,Dst}}=G|Acc]=Acc0) ->
+ case Tup < Dst andalso Dst+1 =:= Live of
+ true ->
+ %% Move allocation instruction upwards past
+ %% get_tuple_element instructions to create more
+ %% opportunities for moving get_tuple_element
+ %% instructions.
+ I = {allocate_zero,N,Dst},
+ reorder_1([I,G|Is], D, Acc);
+ false ->
+ reorder_1(Is, D, [I0|Acc0])
+ end;
+reorder_1([I|Is], D, Acc) ->
+ reorder_1(Is, D, [I|Acc]);
+reorder_1([], _, Acc) -> reverse(Acc).
+
+%% is_safe(Instruction) -> true|false
+%% Test whether an instruction is safe (cannot cause an exception).
+
+is_safe({kill,_}) -> true;
+is_safe({move,_,_}) -> true;
+is_safe({put,_}) -> true;
+is_safe({put_list,_,_,_}) -> true;
+is_safe({put_tuple,_,_}) -> true;
+is_safe({test_heap,_,_}) -> true;
+is_safe(_) -> false.
diff --git a/lib/compiler/src/beam_split.erl b/lib/compiler/src/beam_split.erl
index 3be9311080..bb1c0e23a9 100644
--- a/lib/compiler/src/beam_split.erl
+++ b/lib/compiler/src/beam_split.erl
@@ -57,8 +57,8 @@ split_block([{set,[D],[S|Puts],{alloc,R,{put_map,Op,{f,Lbl}=Fail}}}|Is],
split_block([{set,Ds,[S|Ss],{get_map_elements,Fail}}|Is], Bl, Acc) ->
Gets = beam_utils:join_even(Ss,Ds),
split_block(Is, [], [{get_map_elements,Fail,S,{list,Gets}}|make_block(Bl, Acc)]);
-split_block([{set,[R],[],{'catch',L}}|Is], Bl, Acc) ->
- split_block(Is, [], [{'catch',R,L}|make_block(Bl, Acc)]);
+split_block([{set,[R],[],{try_catch,Op,L}}|Is], Bl, Acc) ->
+ split_block(Is, [], [{Op,R,L}|make_block(Bl, Acc)]);
split_block([{set,[],[],{line,_}=Line}|Is], Bl, Acc) ->
split_block(Is, [], [Line|make_block(Bl, Acc)]);
split_block([I|Is], Bl, Acc) ->
diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
index 5298589f83..4b45c28623 100644
--- a/lib/compiler/src/beam_type.erl
+++ b/lib/compiler/src/beam_type.erl
@@ -23,7 +23,8 @@
-export([module/2]).
--import(lists, [foldl/3,reverse/1,filter/2]).
+-import(lists, [filter/2,foldl/3,keyfind/3,member/2,
+ reverse/1,reverse/2,sort/1]).
module({Mod,Exp,Attr,Fs0,Lc}, _Opts) ->
Fs = [function(F) || F <- Fs0],
@@ -92,8 +93,19 @@ simplify_basic_1([{set,[D],[TupleReg],{get_tuple_element,0}}=I|Is0], Ts0, Acc) -
Ts = update(I, Ts0),
simplify_basic_1(Is0, Ts, [I|Acc])
end;
-simplify_basic_1([{set,_,_,{'catch',_}}=I|Is], _Ts, Acc) ->
+simplify_basic_1([{set,_,_,{try_catch,_,_}}=I|Is], _Ts, Acc) ->
simplify_basic_1(Is, tdb_new(), [I|Acc]);
+simplify_basic_1([{test,is_atom,_,[R]}=I|Is], Ts, Acc) ->
+ case tdb_find(R, Ts) of
+ boolean -> simplify_basic_1(Is, Ts, Acc);
+ _ -> simplify_basic_1(Is, Ts, [I|Acc])
+ end;
+simplify_basic_1([{test,is_integer,_,[R]}=I|Is], Ts, Acc) ->
+ case tdb_find(R, Ts) of
+ integer -> simplify_basic_1(Is, Ts, Acc);
+ {integer,_} -> simplify_basic_1(Is, Ts, Acc);
+ _ -> simplify_basic_1(Is, Ts, [I|Acc])
+ end;
simplify_basic_1([{test,is_tuple,_,[R]}=I|Is], Ts, Acc) ->
case tdb_find(R, Ts) of
{tuple,_,_} -> simplify_basic_1(Is, Ts, Acc);
@@ -137,6 +149,16 @@ simplify_basic_1([{test,is_record,_,[R,{atom,_}=Tag,{integer,Arity}]}=I|Is], Ts0
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} ->
+ simplify_select_val_int(I0, Range);
+ boolean ->
+ simplify_select_val_bool(I0);
+ _ ->
+ I0
+ end,
+ simplify_basic_1(Is, tdb_new(), [I|Acc]);
simplify_basic_1([I|Is], Ts0, Acc) ->
Ts = update(I, Ts0),
simplify_basic_1(Is, Ts, [I|Acc]);
@@ -144,6 +166,32 @@ simplify_basic_1([], Ts, Acc) ->
Is = reverse(Acc),
{Is,Ts}.
+simplify_select_val_int({select,select_val,R,_,L0}=I, {Min,Max}) ->
+ Vs = sort([V || {integer,V} <- L0]),
+ case eq_ranges(Vs, Min, Max) of
+ false -> I;
+ true -> simplify_select_val_1(L0, {integer,Max}, R, [])
+ end.
+
+simplify_select_val_bool({select,select_val,R,_,L}=I) ->
+ Vs = sort([V || {atom,V} <- L]),
+ case Vs of
+ [false,true] ->
+ simplify_select_val_1(L, {atom,false}, R, []);
+ _ ->
+ I
+ end.
+
+simplify_select_val_1([Val,F|T], Val, R, Acc) ->
+ L = reverse(Acc, T),
+ {select,select_val,R,F,L};
+simplify_select_val_1([V,F|T], Val, R, Acc) ->
+ simplify_select_val_1(T, Val, R, [F,V|Acc]).
+
+eq_ranges([H], H, H) -> true;
+eq_ranges([H|T], H, Max) -> eq_ranges(T, H+1, Max);
+eq_ranges(_, _, _) -> false.
+
%% simplify_float([Instruction], TypeDatabase) ->
%% {[Instruction],TypeDatabase'} | not_possible
%% Simplify floating point operations in blocks.
@@ -199,7 +247,7 @@ simplify_float_1([{set,[D0],[A0,B0],{alloc,_,{gc_bif,Op0,{f,0}}}}=I|Is]=Is0,
Ts = tdb_update([{D0,float}], Ts0),
simplify_float_1(Is, Ts, Rs, Acc)
end;
-simplify_float_1([{set,_,_,{'catch',_}}=I|Is]=Is0, _Ts, Rs0, Acc0) ->
+simplify_float_1([{set,_,_,{try_catch,_,_}}=I|Is]=Is0, _Ts, Rs0, Acc0) ->
Acc = flush_all(Rs0, Is0, Acc0),
simplify_float_1(Is, tdb_new(), Rs0, [I|Acc]);
simplify_float_1([{set,_,_,{line,_}}=I|Is], Ts, Rs, Acc) ->
@@ -311,7 +359,7 @@ flt_need_heap_2({set,_,_,{get_tuple_element,_}}, H, Fl) ->
{[],H,Fl};
flt_need_heap_2({set,_,_,get_list}, H, Fl) ->
{[],H,Fl};
-flt_need_heap_2({set,_,_,{'catch',_}}, H, Fl) ->
+flt_need_heap_2({set,_,_,{try_catch,_,_}}, H, Fl) ->
{[],H,Fl};
%% All other instructions should cause the insertion of an allocation
%% instruction if needed.
@@ -382,6 +430,17 @@ update({set,[D],[{integer,I},Reg],{bif,element,_}}, Ts0) ->
tdb_update([{Reg,{tuple,I,[]}},{D,kill}], Ts0);
update({set,[D],[_Index,Reg],{bif,element,_}}, Ts0) ->
tdb_update([{Reg,{tuple,0,[]}},{D,kill}], Ts0);
+update({set,[D],Args,{bif,N,_}}, Ts0) ->
+ Ar = length(Args),
+ BoolOp = erl_internal:new_type_test(N, Ar) orelse
+ erl_internal:comp_op(N, Ar) orelse
+ erl_internal:bool_op(N, Ar),
+ case BoolOp of
+ true ->
+ tdb_update([{D,boolean}], Ts0);
+ false ->
+ tdb_update([{D,kill}], Ts0)
+ end;
update({set,[D],[S],{get_tuple_element,0}}, Ts) ->
tdb_update([{D,{tuple_element,S,0}}], Ts);
update({set,[D],[S],{alloc,_,{gc_bif,float,{f,0}}}}, Ts0) ->
@@ -390,6 +449,13 @@ update({set,[D],[S],{alloc,_,{gc_bif,float,{f,0}}}}, Ts0) ->
true -> tdb_update([{D,float}], Ts0);
false -> Ts0
end;
+update({set,[D],[S1,S2],{alloc,_,{gc_bif,'band',{f,0}}}}, Ts) ->
+ case keyfind(integer, 1, [S1,S2]) of
+ {integer,N} ->
+ update_band(N, D, Ts);
+ false ->
+ tdb_update([{D,integer}], Ts)
+ end;
update({set,[D],[S1,S2],{alloc,_,{gc_bif,'/',{f,0}}}}, Ts0) ->
%% Make sure we reject non-numeric literals.
case possibly_numeric(S1) andalso possibly_numeric(S2) of
@@ -397,15 +463,17 @@ update({set,[D],[S1,S2],{alloc,_,{gc_bif,'/',{f,0}}}}, Ts0) ->
false -> Ts0
end;
update({set,[D],[S1,S2],{alloc,_,{gc_bif,Op,{f,0}}}}, Ts0) ->
- case arith_op(Op) of
- no ->
- tdb_update([{D,kill}], Ts0);
- {yes,_} ->
+ case op_type(Op) of
+ integer ->
+ tdb_update([{D,integer}], Ts0);
+ {float,_} ->
case {tdb_find(S1, Ts0),tdb_find(S2, Ts0)} of
{float,_} -> tdb_update([{D,float}], Ts0);
{_,float} -> tdb_update([{D,float}], Ts0);
{_,_} -> tdb_update([{D,kill}], Ts0)
- end
+ end;
+ unknown ->
+ tdb_update([{D,kill}], Ts0)
end;
update({set,[],_Src,_Op}, Ts0) -> Ts0;
update({set,[D],_Src,_Op}, Ts0) ->
@@ -437,6 +505,8 @@ update({test,is_record,_Fail,[Src,Tag,{integer,Arity}]}, Ts) ->
tdb_update([{Src,{tuple,Arity,[Tag]}}], Ts);
update({test,_Test,_Fail,_Other}, Ts) ->
Ts;
+update({test,bs_get_integer2,_,_,Args,Dst}, Ts) ->
+ tdb_update([{Dst,get_bs_integer_type(Args)}], Ts);
update({call_ext,Ar,{extfunc,math,Math,Ar}}, Ts) ->
case is_math_bif(Math, Ar) of
true -> tdb_update([{{x,0},float}], Ts);
@@ -453,10 +523,43 @@ update({call,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts);
update({call_ext,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts);
update({make_fun2,_,_,_,_}, Ts) -> tdb_kill_xregs(Ts);
update({line,_}, Ts) -> Ts;
+update({bs_save2,_,_}, Ts) -> Ts;
+update({bs_restore2,_,_}, Ts) -> Ts;
%% The instruction is unknown. Kill all information.
update(_I, _Ts) -> tdb_new().
+update_band(N, Reg, Ts) ->
+ Type = update_band_1(N, 0),
+ tdb_update([{Reg,Type}], Ts).
+
+update_band_1(N, Bits) when Bits < 64 ->
+ case 1 bsl Bits of
+ P when P =:= N + 1 ->
+ {integer,{0,N}};
+ P when P > N + 1 ->
+ integer;
+ _ ->
+ update_band_1(N, Bits+1)
+ end;
+update_band_1(_, _) ->
+ %% Negative or large positive number. Give up.
+ integer.
+
+get_bs_integer_type([_,{integer,N},U,{field_flags,Fl}])
+ when N*U < 64 ->
+ NumBits = N*U,
+ case member(unsigned, Fl) of
+ true ->
+ {integer,{0,(1 bsl NumBits)-1}};
+ false ->
+ %% Signed integer. Don't bother.
+ integer
+ end;
+get_bs_integer_type(_) ->
+ %% Avoid creating ranges with a huge upper limit.
+ integer.
+
is_math_bif(cos, 1) -> true;
is_math_bif(cosh, 1) -> true;
is_math_bif(sin, 1) -> true;
@@ -545,11 +648,22 @@ load_reg(V, Ts, Rs0, Is0) ->
{Rs,Is}
end.
-arith_op('+') -> {yes,fadd};
-arith_op('-') -> {yes,fsub};
-arith_op('*') -> {yes,fmul};
-arith_op('/') -> {yes,fdiv};
-arith_op(_) -> no.
+arith_op(Op) ->
+ case op_type(Op) of
+ {float,Instr} -> {yes,Instr};
+ _ -> no
+ end.
+
+op_type('+') -> {float,fadd};
+op_type('-') -> {float,fsub};
+op_type('*') -> {float,fmul};
+%% '/' and 'band' are specially handled.
+op_type('bor') -> integer;
+op_type('bxor') -> integer;
+op_type('bsl') -> integer;
+op_type('bsr') -> integer;
+op_type('div') -> integer;
+op_type(_) -> unknown.
flush(Rs, [{set,[_],[],{put_tuple,_}}|_]=Is0, Acc0) ->
Acc = flush_all(Rs, Is0, Acc0),
@@ -618,7 +732,6 @@ checkerror(Is) ->
checkerror_1(Is, Is).
checkerror_1([{set,[],[],fcheckerror}|_], OrigIs) -> OrigIs;
-checkerror_1([{set,[],[],fclearerror}|_], OrigIs) -> OrigIs;
checkerror_1([{set,_,_,{bif,fadd,_}}|_], OrigIs) -> checkerror_2(OrigIs);
checkerror_1([{set,_,_,{bif,fsub,_}}|_], OrigIs) -> checkerror_2(OrigIs);
checkerror_1([{set,_,_,{bif,fmul,_}}|_], OrigIs) -> checkerror_2(OrigIs);
@@ -640,6 +753,9 @@ checkerror_2(OrigIs) -> [{set,[],[],fcheckerror}|OrigIs].
%%% of the first element).
%%%
%%% 'float' means that the register contains a float.
+%%%
+%%% 'integer' or {integer,{Min,Max}} that the register contains an
+%%% integer.
%% tdb_new() -> EmptyDataBase
%% Creates a new, empty type database.
@@ -729,10 +845,20 @@ merge_type_info({tuple,Sz1,[]}, {tuple,_Sz2,First}=Tuple2) ->
merge_type_info({tuple,Sz1,First}, Tuple2);
merge_type_info({tuple,_Sz1,First}=Tuple1, {tuple,Sz2,_}) ->
merge_type_info(Tuple1, {tuple,Sz2,First});
+merge_type_info(integer, {integer,_}=Int) ->
+ Int;
+merge_type_info({integer,_}=Int, integer) ->
+ Int;
+merge_type_info({integer,{Min1,Max1}}, {integer,{Min2,Max2}}) ->
+ {integer,{max(Min1, Min2),min(Max1, Max2)}};
merge_type_info(NewType, _) ->
verify_type(NewType),
NewType.
+verify_type(boolean) -> ok;
+verify_type(integer) -> ok;
+verify_type({integer,{Min,Max}})
+ when is_integer(Min), is_integer(Max) -> ok;
verify_type(map) -> ok;
verify_type(nonempty_list) -> ok;
verify_type({tuple,Sz,[]}) when is_integer(Sz) -> ok;
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index fbcd5de1bb..68d6105cfa 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -484,6 +484,15 @@ check_liveness(R, [{get_map_elements,{f,Fail},S,{list,L}}|Is], St0) ->
Other
end
end;
+check_liveness(R, [{test_heap,N,Live}|Is], St) ->
+ I = {block,[{set,[],[],{alloc,Live,{nozero,nostack,N,[]}}}]},
+ check_liveness(R, [I|Is], St);
+check_liveness(R, [{allocate_zero,N,Live}|Is], St) ->
+ I = {block,[{set,[],[],{alloc,Live,{zero,N,0,[]}}}]},
+ check_liveness(R, [I|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, Is, St) when is_list(Is) ->
%% case Is of
%% [I|_] ->
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index 6004f1974e..fd38fc0095 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -31,15 +31,6 @@
-import(lists, [reverse/1,foldl/3,foreach/2,dropwhile/2]).
--define(MAXREG, 1024).
-
-%%-define(DEBUG, 1).
--ifdef(DEBUG).
--define(DBG_FORMAT(F, D), (io:format((F), (D)))).
--else.
--define(DBG_FORMAT(F, D), ok).
--endif.
-
%% To be called by the compiler.
module({Mod,Exp,Attr,Fs,Lc}=Code, _Opts)
when is_atom(Mod), is_list(Exp), is_list(Attr), is_integer(Lc) ->
@@ -170,29 +161,18 @@ validate_0(Module, [{function,Name,Ar,Entry,Code}|Fs], Ft) ->
% in the module (those that start with bs_start_match2).
}).
--ifdef(DEBUG).
-print_st(#st{x=Xs,y=Ys,numy=NumY,h=H,ct=Ct}) ->
- io:format(" #st{x=~p~n"
- " y=~p~n"
- " numy=~p,h=~p,ct=~w~n",
- [gb_trees:to_list(Xs),gb_trees:to_list(Ys),NumY,H,Ct]).
--endif.
-
validate_1(Is, Name, Arity, Entry, Ft) ->
validate_2(labels(Is), Name, Arity, Entry, Ft).
validate_2({Ls1,[{func_info,{atom,Mod},{atom,Name},Arity}=_F|Is]},
Name, Arity, Entry, Ft) ->
- lists:foreach(fun (_L) -> ?DBG_FORMAT(" ~p.~n", [{label,_L}]) end, Ls1),
- ?DBG_FORMAT(" ~p.~n", [_F]),
validate_3(labels(Is), Name, Arity, Entry, Mod, Ls1, Ft);
validate_2({Ls1,Is}, Name, Arity, _Entry, _Ft) ->
error({{'_',Name,Arity},{first(Is),length(Ls1),illegal_instruction}}).
validate_3({Ls2,Is}, Name, Arity, Entry, Mod, Ls1, Ft) ->
- lists:foreach(fun (_L) -> ?DBG_FORMAT(" ~p.~n", [{label,_L}]) end, Ls2),
Offset = 1 + length(Ls1) + 1 + length(Ls2),
- EntryOK = (Entry =:= undefined) orelse lists:member(Entry, Ls2),
+ EntryOK = lists:member(Entry, Ls2),
if
EntryOK ->
St = init_state(Arity),
@@ -260,7 +240,6 @@ valfun([], MFA, _Offset, #vst{branched=Targets0,labels=Labels0}=Vst) ->
error({MFA,Error})
end;
valfun([I|Is], MFA, Offset, Vst0) ->
- ?DBG_FORMAT(" ~p.\n", [I]),
valfun(Is, MFA, Offset+1,
try
Vst = val_dsetel(I, Vst0),
@@ -278,7 +257,6 @@ valfun_1({label,Lbl}, #vst{current=St0,branched=B,labels=Lbls}=Vst) ->
valfun_1(_I, #vst{current=none}=Vst) ->
%% Ignore instructions after erlang:error/1,2, which
%% the original R10B compiler thought would return.
- ?DBG_FORMAT("Ignoring ~p\n", [_I]),
Vst;
valfun_1({badmatch,Src}, Vst) ->
assert_term(Src, Vst),
@@ -980,9 +958,9 @@ get_fls(#vst{current=#st{fls=Fls}}) when is_atom(Fls) -> Fls.
init_fregs() -> 0.
-set_freg({fr,Fr}, #vst{current=#st{f=Fregs0}=St}=Vst)
+set_freg({fr,Fr}=Freg, #vst{current=#st{f=Fregs0}=St}=Vst)
when is_integer(Fr), 0 =< Fr ->
- limit_check(Fr),
+ check_limit(Freg),
Bit = 1 bsl Fr,
if
Fregs0 band Bit =:= 0 ->
@@ -995,9 +973,10 @@ set_freg(Fr, _) -> error({bad_target,Fr}).
assert_freg_set({fr,Fr}=Freg, #vst{current=#st{f=Fregs}})
when is_integer(Fr), 0 =< Fr ->
if
- Fregs band (1 bsl Fr) =/= 0 ->
- limit_check(Fr);
- true -> error({uninitialized_reg,Freg})
+ (Fregs bsr Fr) band 1 =:= 0 ->
+ error({uninitialized_reg,Freg});
+ true ->
+ ok
end;
assert_freg_set(Fr, _) -> error({bad_source,Fr}).
@@ -1076,16 +1055,16 @@ set_type(Type, {x,_}=Reg, Vst) -> set_type_reg(Type, Reg, Vst);
set_type(Type, {y,_}=Reg, Vst) -> set_type_y(Type, Reg, Vst);
set_type(_, _, #vst{}=Vst) -> Vst.
-set_type_reg(Type, {x,X}, #vst{current=#st{x=Xs}=St}=Vst)
+set_type_reg(Type, {x,X}=Reg, #vst{current=#st{x=Xs}=St}=Vst)
when is_integer(X), 0 =< X ->
- limit_check(X),
+ check_limit(Reg),
Vst#vst{current=St#st{x=gb_trees:enter(X, Type, Xs)}};
set_type_reg(Type, Reg, Vst) ->
set_type_y(Type, Reg, Vst).
set_type_y(Type, {y,Y}=Reg, #vst{current=#st{y=Ys0}=St}=Vst)
when is_integer(Y), 0 =< Y ->
- limit_check(Y),
+ check_limit(Reg),
Ys = case gb_trees:lookup(Y, Ys0) of
none ->
error({invalid_store,Reg,Type});
@@ -1612,17 +1591,19 @@ return_type_math(pow, 2) -> {float,[]};
return_type_math(pi, 0) -> {float,[]};
return_type_math(F, A) when is_atom(F), is_integer(A), A >= 0 -> term.
-limit_check(Num) when is_integer(Num), Num >= ?MAXREG ->
- error(limit);
-limit_check(_) -> ok.
+check_limit({x,X}) when is_integer(X), X < 1023 ->
+ %% Note: x(1023) is reserved for use by the BEAM loader.
+ ok;
+check_limit({y,Y}) when is_integer(Y), Y < 1024 ->
+ ok;
+check_limit({fr,Fr}) when is_integer(Fr), Fr < 1024 ->
+ ok;
+check_limit(_) ->
+ error(limit).
min(A, B) when is_integer(A), is_integer(B), A < B -> A;
min(A, B) when is_integer(A), is_integer(B) -> B.
gb_trees_from_list(L) -> gb_trees:from_orddict(lists:sort(L)).
--ifdef(DEBUG).
-error(Error) -> exit(Error).
--else.
error(Error) -> throw(Error).
--endif.
diff --git a/lib/compiler/src/cerl_trees.erl b/lib/compiler/src/cerl_trees.erl
index 58bb18e34a..b86be95cab 100644
--- a/lib/compiler/src/cerl_trees.erl
+++ b/lib/compiler/src/cerl_trees.erl
@@ -27,7 +27,7 @@
-module(cerl_trees).
-export([depth/1, fold/3, free_variables/1, get_label/1, label/1, label/2,
- map/2, mapfold/3, size/1, variables/1]).
+ map/2, mapfold/3, mapfold/4, size/1, variables/1]).
-import(cerl, [alias_pat/1, alias_var/1, ann_c_alias/3, ann_c_apply/3,
ann_c_binary/2, ann_c_bitstr/6, ann_c_call/4,
@@ -340,136 +340,162 @@ fold_pairs(_, S, []) ->
%% starting with the given value <code>Initial</code>, while doing a
%% post-order traversal of the tree, much like <code>fold/3</code>.
%%
+%% This is the same as mapfold/4, with an identity function as the
+%% pre-operation.
+%%
%% @see map/2
%% @see fold/3
+%% @see mapfold/4
-spec mapfold(fun((cerl:cerl(), term()) -> {cerl:cerl(), term()}),
term(), cerl:cerl()) -> {cerl:cerl(), term()}.
mapfold(F, S0, T) ->
+ mapfold(fun(T0, A) -> {T0, A} end, F, S0, T).
+
+
+%% @spec mapfold(Pre, Post, Initial::term(), Tree::cerl()) ->
+%% {cerl(), term()}
+%%
+%% Pre = Post = (cerl(), term()) -> {cerl(), term()}
+%%
+%% @doc Does a combined map/fold operation on the nodes of the
+%% tree. It begins by calling <code>Pre</code> on the tree, using the
+%% <code>Initial</code> value. It then deconstructs the top node of
+%% the returned tree and recurses on the children, using the returned
+%% value as the new initial and carrying the returned values from one
+%% call to the next. Finally it reassembles the top node from the
+%% children, calls <code>Post</code> on it and returns the result.
+
+-spec mapfold(fun((cerl:cerl(), term()) -> {cerl:cerl(), term()}),
+ fun((cerl:cerl(), term()) -> {cerl:cerl(), term()}),
+ term(), cerl:cerl()) -> {cerl:cerl(), term()}.
+
+mapfold(Pre, Post, S00, T0) ->
+ {T, S0} = Pre(T0, S00),
case type(T) of
literal ->
case concrete(T) of
[_ | _] ->
- {T1, S1} = mapfold(F, S0, cons_hd(T)),
- {T2, S2} = mapfold(F, S1, cons_tl(T)),
- F(update_c_cons(T, T1, T2), S2);
+ {T1, S1} = mapfold(Pre, Post, S0, cons_hd(T)),
+ {T2, S2} = mapfold(Pre, Post, S1, cons_tl(T)),
+ Post(update_c_cons(T, T1, T2), S2);
V when tuple_size(V) > 0 ->
- {Ts, S1} = mapfold_list(F, S0, tuple_es(T)),
- F(update_c_tuple(T, Ts), S1);
+ {Ts, S1} = mapfold_list(Pre, Post, S0, tuple_es(T)),
+ Post(update_c_tuple(T, Ts), S1);
_ ->
- F(T, S0)
+ Post(T, S0)
end;
var ->
- F(T, S0);
+ Post(T, S0);
values ->
- {Ts, S1} = mapfold_list(F, S0, values_es(T)),
- F(update_c_values(T, Ts), S1);
+ {Ts, S1} = mapfold_list(Pre, Post, S0, values_es(T)),
+ Post(update_c_values(T, Ts), S1);
cons ->
- {T1, S1} = mapfold(F, S0, cons_hd(T)),
- {T2, S2} = mapfold(F, S1, cons_tl(T)),
- F(update_c_cons_skel(T, T1, T2), S2);
+ {T1, S1} = mapfold(Pre, Post, S0, cons_hd(T)),
+ {T2, S2} = mapfold(Pre, Post, S1, cons_tl(T)),
+ Post(update_c_cons_skel(T, T1, T2), S2);
tuple ->
- {Ts, S1} = mapfold_list(F, S0, tuple_es(T)),
- F(update_c_tuple_skel(T, Ts), S1);
+ {Ts, S1} = mapfold_list(Pre, Post, S0, tuple_es(T)),
+ Post(update_c_tuple_skel(T, Ts), S1);
map ->
- {M , S1} = mapfold(F, S0, map_arg(T)),
- {Ts, S2} = mapfold_list(F, S1, map_es(T)),
- F(update_c_map(T, M, Ts), S2);
+ {M , S1} = mapfold(Pre, Post, S0, map_arg(T)),
+ {Ts, S2} = mapfold_list(Pre, Post, S1, map_es(T)),
+ Post(update_c_map(T, M, Ts), S2);
map_pair ->
- {Op, S1} = mapfold(F, S0, map_pair_op(T)),
- {Key, S2} = mapfold(F, S1, map_pair_key(T)),
- {Val, S3} = mapfold(F, S2, map_pair_val(T)),
- F(update_c_map_pair(T,Op,Key,Val), S3);
+ {Op, S1} = mapfold(Pre, Post, S0, map_pair_op(T)),
+ {Key, S2} = mapfold(Pre, Post, S1, map_pair_key(T)),
+ {Val, S3} = mapfold(Pre, Post, S2, map_pair_val(T)),
+ Post(update_c_map_pair(T,Op,Key,Val), S3);
'let' ->
- {Vs, S1} = mapfold_list(F, S0, let_vars(T)),
- {A, S2} = mapfold(F, S1, let_arg(T)),
- {B, S3} = mapfold(F, S2, let_body(T)),
- F(update_c_let(T, Vs, A, B), S3);
+ {Vs, S1} = mapfold_list(Pre, Post, S0, let_vars(T)),
+ {A, S2} = mapfold(Pre, Post, S1, let_arg(T)),
+ {B, S3} = mapfold(Pre, Post, S2, let_body(T)),
+ Post(update_c_let(T, Vs, A, B), S3);
seq ->
- {A, S1} = mapfold(F, S0, seq_arg(T)),
- {B, S2} = mapfold(F, S1, seq_body(T)),
- F(update_c_seq(T, A, B), S2);
+ {A, S1} = mapfold(Pre, Post, S0, seq_arg(T)),
+ {B, S2} = mapfold(Pre, Post, S1, seq_body(T)),
+ Post(update_c_seq(T, A, B), S2);
apply ->
- {E, S1} = mapfold(F, S0, apply_op(T)),
- {As, S2} = mapfold_list(F, S1, apply_args(T)),
- F(update_c_apply(T, E, As), S2);
+ {E, S1} = mapfold(Pre, Post, S0, apply_op(T)),
+ {As, S2} = mapfold_list(Pre, Post, S1, apply_args(T)),
+ Post(update_c_apply(T, E, As), S2);
call ->
- {M, S1} = mapfold(F, S0, call_module(T)),
- {N, S2} = mapfold(F, S1, call_name(T)),
- {As, S3} = mapfold_list(F, S2, call_args(T)),
- F(update_c_call(T, M, N, As), S3);
+ {M, S1} = mapfold(Pre, Post, S0, call_module(T)),
+ {N, S2} = mapfold(Pre, Post, S1, call_name(T)),
+ {As, S3} = mapfold_list(Pre, Post, S2, call_args(T)),
+ Post(update_c_call(T, M, N, As), S3);
primop ->
- {N, S1} = mapfold(F, S0, primop_name(T)),
- {As, S2} = mapfold_list(F, S1, primop_args(T)),
- F(update_c_primop(T, N, As), S2);
+ {N, S1} = mapfold(Pre, Post, S0, primop_name(T)),
+ {As, S2} = mapfold_list(Pre, Post, S1, primop_args(T)),
+ Post(update_c_primop(T, N, As), S2);
'case' ->
- {A, S1} = mapfold(F, S0, case_arg(T)),
- {Cs, S2} = mapfold_list(F, S1, case_clauses(T)),
- F(update_c_case(T, A, Cs), S2);
+ {A, S1} = mapfold(Pre, Post, S0, case_arg(T)),
+ {Cs, S2} = mapfold_list(Pre, Post, S1, case_clauses(T)),
+ Post(update_c_case(T, A, Cs), S2);
clause ->
- {Ps, S1} = mapfold_list(F, S0, clause_pats(T)),
- {G, S2} = mapfold(F, S1, clause_guard(T)),
- {B, S3} = mapfold(F, S2, clause_body(T)),
- F(update_c_clause(T, Ps, G, B), S3);
+ {Ps, S1} = mapfold_list(Pre, Post, S0, clause_pats(T)),
+ {G, S2} = mapfold(Pre, Post, S1, clause_guard(T)),
+ {B, S3} = mapfold(Pre, Post, S2, clause_body(T)),
+ Post(update_c_clause(T, Ps, G, B), S3);
alias ->
- {V, S1} = mapfold(F, S0, alias_var(T)),
- {P, S2} = mapfold(F, S1, alias_pat(T)),
- F(update_c_alias(T, V, P), S2);
+ {V, S1} = mapfold(Pre, Post, S0, alias_var(T)),
+ {P, S2} = mapfold(Pre, Post, S1, alias_pat(T)),
+ Post(update_c_alias(T, V, P), S2);
'fun' ->
- {Vs, S1} = mapfold_list(F, S0, fun_vars(T)),
- {B, S2} = mapfold(F, S1, fun_body(T)),
- F(update_c_fun(T, Vs, B), S2);
+ {Vs, S1} = mapfold_list(Pre, Post, S0, fun_vars(T)),
+ {B, S2} = mapfold(Pre, Post, S1, fun_body(T)),
+ Post(update_c_fun(T, Vs, B), S2);
'receive' ->
- {Cs, S1} = mapfold_list(F, S0, receive_clauses(T)),
- {E, S2} = mapfold(F, S1, receive_timeout(T)),
- {A, S3} = mapfold(F, S2, receive_action(T)),
- F(update_c_receive(T, Cs, E, A), S3);
+ {Cs, S1} = mapfold_list(Pre, Post, S0, receive_clauses(T)),
+ {E, S2} = mapfold(Pre, Post, S1, receive_timeout(T)),
+ {A, S3} = mapfold(Pre, Post, S2, receive_action(T)),
+ Post(update_c_receive(T, Cs, E, A), S3);
'try' ->
- {E, S1} = mapfold(F, S0, try_arg(T)),
- {Vs, S2} = mapfold_list(F, S1, try_vars(T)),
- {B, S3} = mapfold(F, S2, try_body(T)),
- {Evs, S4} = mapfold_list(F, S3, try_evars(T)),
- {H, S5} = mapfold(F, S4, try_handler(T)),
- F(update_c_try(T, E, Vs, B, Evs, H), S5);
+ {E, S1} = mapfold(Pre, Post, S0, try_arg(T)),
+ {Vs, S2} = mapfold_list(Pre, Post, S1, try_vars(T)),
+ {B, S3} = mapfold(Pre, Post, S2, try_body(T)),
+ {Evs, S4} = mapfold_list(Pre, Post, S3, try_evars(T)),
+ {H, S5} = mapfold(Pre, Post, S4, try_handler(T)),
+ Post(update_c_try(T, E, Vs, B, Evs, H), S5);
'catch' ->
- {B, S1} = mapfold(F, S0, catch_body(T)),
- F(update_c_catch(T, B), S1);
+ {B, S1} = mapfold(Pre, Post, S0, catch_body(T)),
+ Post(update_c_catch(T, B), S1);
binary ->
- {Ds, S1} = mapfold_list(F, S0, binary_segments(T)),
- F(update_c_binary(T, Ds), S1);
+ {Ds, S1} = mapfold_list(Pre, Post, S0, binary_segments(T)),
+ Post(update_c_binary(T, Ds), S1);
bitstr ->
- {Val, S1} = mapfold(F, S0, bitstr_val(T)),
- {Size, S2} = mapfold(F, S1, bitstr_size(T)),
- {Unit, S3} = mapfold(F, S2, bitstr_unit(T)),
- {Type, S4} = mapfold(F, S3, bitstr_type(T)),
- {Flags, S5} = mapfold(F, S4, bitstr_flags(T)),
- F(update_c_bitstr(T, Val, Size, Unit, Type, Flags), S5);
+ {Val, S1} = mapfold(Pre, Post, S0, bitstr_val(T)),
+ {Size, S2} = mapfold(Pre, Post, S1, bitstr_size(T)),
+ {Unit, S3} = mapfold(Pre, Post, S2, bitstr_unit(T)),
+ {Type, S4} = mapfold(Pre, Post, S3, bitstr_type(T)),
+ {Flags, S5} = mapfold(Pre, Post, S4, bitstr_flags(T)),
+ Post(update_c_bitstr(T, Val, Size, Unit, Type, Flags), S5);
letrec ->
- {Ds, S1} = mapfold_pairs(F, S0, letrec_defs(T)),
- {B, S2} = mapfold(F, S1, letrec_body(T)),
- F(update_c_letrec(T, Ds, B), S2);
+ {Ds, S1} = mapfold_pairs(Pre, Post, S0, letrec_defs(T)),
+ {B, S2} = mapfold(Pre, Post, S1, letrec_body(T)),
+ Post(update_c_letrec(T, Ds, B), S2);
module ->
- {N, S1} = mapfold(F, S0, module_name(T)),
- {Es, S2} = mapfold_list(F, S1, module_exports(T)),
- {As, S3} = mapfold_pairs(F, S2, module_attrs(T)),
- {Ds, S4} = mapfold_pairs(F, S3, module_defs(T)),
- F(update_c_module(T, N, Es, As, Ds), S4)
+ {N, S1} = mapfold(Pre, Post, S0, module_name(T)),
+ {Es, S2} = mapfold_list(Pre, Post, S1, module_exports(T)),
+ {As, S3} = mapfold_pairs(Pre, Post, S2, module_attrs(T)),
+ {Ds, S4} = mapfold_pairs(Pre, Post, S3, module_defs(T)),
+ Post(update_c_module(T, N, Es, As, Ds), S4)
end.
-mapfold_list(F, S0, [T | Ts]) ->
- {T1, S1} = mapfold(F, S0, T),
- {Ts1, S2} = mapfold_list(F, S1, Ts),
+mapfold_list(Pre, Post, S0, [T | Ts]) ->
+ {T1, S1} = mapfold(Pre, Post, S0, T),
+ {Ts1, S2} = mapfold_list(Pre, Post, S1, Ts),
{[T1 | Ts1], S2};
-mapfold_list(_, S, []) ->
+mapfold_list(_, _, S, []) ->
{[], S}.
-mapfold_pairs(F, S0, [{T1, T2} | Ps]) ->
- {T3, S1} = mapfold(F, S0, T1),
- {T4, S2} = mapfold(F, S1, T2),
- {Ps1, S3} = mapfold_pairs(F, S2, Ps),
+mapfold_pairs(Pre, Post, S0, [{T1, T2} | Ps]) ->
+ {T3, S1} = mapfold(Pre, Post, S0, T1),
+ {T4, S2} = mapfold(Pre, Post, S1, T2),
+ {Ps1, S3} = mapfold_pairs(Pre, Post, S2, Ps),
{[{T3, T4} | Ps1], S3};
-mapfold_pairs(_, S, []) ->
+mapfold_pairs(_, _, S, []) ->
{[], S}.
@@ -640,8 +666,8 @@ vars_in_list([], _, A) ->
vars_in_defs(Ds, S) ->
vars_in_defs(Ds, S, []).
-vars_in_defs([{_, F} | Ds], S, A) ->
- vars_in_defs(Ds, S, ordsets:union(variables(F, S), A));
+vars_in_defs([{_, Post} | Ds], S, A) ->
+ vars_in_defs(Ds, S, ordsets:union(variables(Post, S), A));
vars_in_defs([], _, A) ->
A.
@@ -703,13 +729,14 @@ label(T, N, Env) ->
%% Constant literals are not labeled.
{T, N};
var ->
- case dict:find(var_name(T), Env) of
- {ok, L} ->
- {As, _} = label_ann(T, L),
- N1 = N;
- error ->
- {As, N1} = label_ann(T, N)
- end,
+ {As, N1} =
+ case dict:find(var_name(T), Env) of
+ {ok, L} ->
+ {A, _} = label_ann(T, L),
+ {A, N};
+ error ->
+ label_ann(T, N)
+ end,
{set_ann(T, As), N1};
values ->
{Ts, N1} = label_list(values_es(T), N, Env),
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index e0a29fe9b1..46917905de 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -40,6 +40,8 @@
%%----------------------------------------------------------------------
+-type abstract_code() :: [erl_parse:abstract_form()].
+
-type option() :: atom() | {atom(), term()} | {'d', atom(), term()}.
-type err_info() :: {erl_anno:line() | 'none',
@@ -48,6 +50,9 @@
-type warnings() :: [{file:filename(), [err_info()]}].
-type mod_ret() :: {'ok', module()}
| {'ok', module(), cerl:c_module()} %% with option 'to_core'
+ | {'ok', %% with option 'to_pp'
+ module() | [], %% module() if 'to_exp'
+ abstract_code()}
| {'ok', module(), warnings()}.
-type bin_ret() :: {'ok', module(), binary()}
| {'ok', module(), binary(), warnings()}.
@@ -78,7 +83,11 @@ file(File, Opts) when is_list(Opts) ->
file(File, Opt) ->
file(File, [Opt|?DEFAULT_OPTIONS]).
-forms(File) -> forms(File, ?DEFAULT_OPTIONS).
+-spec forms(abstract_code()) -> comp_ret().
+
+forms(Forms) -> forms(Forms, ?DEFAULT_OPTIONS).
+
+-spec forms(abstract_code(), [option()] | option()) -> comp_ret().
forms(Forms, Opts) when is_list(Opts) ->
do_compile({forms,Forms}, [binary|Opts++env_default_opts()]);
@@ -106,6 +115,8 @@ noenv_file(File, Opts) when is_list(Opts) ->
noenv_file(File, Opt) ->
noenv_file(File, [Opt|?DEFAULT_OPTIONS]).
+-spec noenv_forms(abstract_code(), [option()] | option()) -> comp_ret().
+
noenv_forms(Forms, Opts) when is_list(Opts) ->
do_compile({forms,Forms}, [binary|Opts]);
noenv_forms(Forms, Opt) when is_atom(Opt) ->
@@ -671,11 +682,16 @@ asm_passes() ->
%% Assembly level optimisations.
[{delay,
[{pass,beam_a},
+ {iff,da,{listing,"a"}},
{unless,no_postopt,
- [{pass,beam_block},
+ [{unless,no_reorder,{pass,beam_reorder}},
+ {iff,dre,{listing,"reorder"}},
+ {pass,beam_block},
{iff,dblk,{listing,"block"}},
{unless,no_except,{pass,beam_except}},
{iff,dexcept,{listing,"except"}},
+ {unless,no_bs_opt,{pass,beam_bs}},
+ {iff,dbs,{listing,"bs"}},
{unless,no_bopt,{pass,beam_bool}},
{iff,dbool,{listing,"bool"}},
{unless,no_topt,{pass,beam_type}},
@@ -703,6 +719,7 @@ asm_passes() ->
{iff,no_postopt,[{pass,beam_clean}]},
{pass,beam_z},
+ {iff,dz,{listing,"z"}},
{iff,dopt,{listing,"optimize"}},
{iff,'S',{listing,"S"}},
{iff,'to_asm',{done,"S"}}]},
@@ -1300,21 +1317,12 @@ generate_key(String) when is_list(String) ->
encrypt({des3_cbc=Type,Key,IVec,BlockSize}, Bin0) ->
Bin1 = case byte_size(Bin0) rem BlockSize of
0 -> Bin0;
- N -> list_to_binary([Bin0,random_bytes(BlockSize-N)])
+ N -> list_to_binary([Bin0,crypto:rand_bytes(BlockSize-N)])
end,
Bin = crypto:block_encrypt(Type, Key, IVec, Bin1),
TypeString = atom_to_list(Type),
list_to_binary([0,length(TypeString),TypeString,Bin]).
-random_bytes(N) ->
- _ = random:seed(erlang:time_offset(),
- erlang:monotonic_time(),
- erlang:unique_integer()),
- random_bytes_1(N, []).
-
-random_bytes_1(0, Acc) -> Acc;
-random_bytes_1(N, Acc) -> random_bytes_1(N-1, [random:uniform(255)|Acc]).
-
save_core_code(St) ->
{ok,St#compile{core_code=cerl:from_records(St#compile.code)}}.
@@ -1612,11 +1620,8 @@ output_encoding(F, #compile{encoding = Encoding}) ->
ok = io:setopts(F, [{encoding, Encoding}]),
ok = io:fwrite(F, <<"%% ~s\n">>, [epp:encoding_to_string(Encoding)]).
-restore_expanded_types("P", Fs) ->
- epp:restore_typed_record_fields(Fs);
restore_expanded_types("E", {M,I,Fs0}) ->
- Fs1 = restore_expand_module(Fs0),
- Fs = epp:restore_typed_record_fields(Fs1),
+ Fs = restore_expand_module(Fs0),
{M,I,Fs};
restore_expanded_types(_Ext, Code) -> Code.
@@ -1628,6 +1633,8 @@ restore_expand_module([{attribute,Line,spec,[Arg]}|Fs]) ->
[{attribute,Line,spec,Arg}|restore_expand_module(Fs)];
restore_expand_module([{attribute,Line,callback,[Arg]}|Fs]) ->
[{attribute,Line,callback,Arg}|restore_expand_module(Fs)];
+restore_expand_module([{attribute,Line,record,[R]}|Fs]) ->
+ [{attribute,Line,record,R}|restore_expand_module(Fs)];
restore_expand_module([F|Fs]) ->
[F|restore_expand_module(Fs)];
restore_expand_module([]) -> [].
diff --git a/lib/compiler/src/compiler.app.src b/lib/compiler/src/compiler.app.src
index afb85f4710..a2b2a1d277 100644
--- a/lib/compiler/src/compiler.app.src
+++ b/lib/compiler/src/compiler.app.src
@@ -25,6 +25,7 @@
beam_asm,
beam_block,
beam_bool,
+ beam_bs,
beam_bsm,
beam_clean,
beam_dead,
@@ -37,6 +38,7 @@
beam_opcodes,
beam_peep,
beam_receive,
+ beam_reorder,
beam_split,
beam_trim,
beam_type,
diff --git a/lib/compiler/src/core_lib.erl b/lib/compiler/src/core_lib.erl
index 3abb520485..839c736ff2 100644
--- a/lib/compiler/src/core_lib.erl
+++ b/lib/compiler/src/core_lib.erl
@@ -21,52 +21,16 @@
-module(core_lib).
--deprecated({get_anno,1,next_major_release}).
--deprecated({set_anno,2,next_major_release}).
--deprecated({is_literal,1,next_major_release}).
--deprecated({is_literal_list,1,next_major_release}).
--deprecated({literal_value,1,next_major_release}).
-
--export([get_anno/1,set_anno/2]).
--export([is_literal/1,is_literal_list/1]).
--export([literal_value/1]).
-export([make_values/1]).
-export([is_var_used/2]).
-include("core_parse.hrl").
-%%
-%% Generic get/set annotation that should be used only with cerl() structures.
-%%
--spec get_anno(cerl:cerl()) -> term().
-
-get_anno(C) -> cerl:get_ann(C).
-
--spec set_anno(cerl:cerl(), term()) -> cerl:cerl().
-
-set_anno(C, A) -> cerl:set_ann(C, A).
-
--spec is_literal(cerl:cerl()) -> boolean().
-
-is_literal(Cerl) ->
- cerl:is_literal(cerl:fold_literal(Cerl)).
-
--spec is_literal_list([cerl:cerl()]) -> boolean().
-
-is_literal_list(Es) -> lists:all(fun is_literal/1, Es).
-
-%% Return the value of LitExpr.
--spec literal_value(cerl:c_literal() | cerl:c_binary() |
- cerl:c_map() | cerl:c_cons() | cerl:c_tuple()) -> term().
-
-literal_value(Cerl) ->
- cerl:concrete(cerl:fold_literal(Cerl)).
-
%% Make a suitable values structure, expr or values, depending on Expr.
-spec make_values([cerl:cerl()] | cerl:cerl()) -> cerl:cerl().
make_values([E]) -> E;
-make_values([H|_]=Es) -> #c_values{anno=get_anno(H),es=Es};
+make_values([H|_]=Es) -> #c_values{anno=cerl:get_ann(H),es=Es};
make_values([]) -> #c_values{es=[]};
make_values(E) -> E.
diff --git a/lib/compiler/src/core_lint.erl b/lib/compiler/src/core_lint.erl
index cc54f6e411..7d3513c0ba 100644
--- a/lib/compiler/src/core_lint.erl
+++ b/lib/compiler/src/core_lint.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1999-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.
@@ -73,7 +73,7 @@
%% Define the lint state record.
-record(lint, {module :: module(), % Current module
- func :: fa(), % Current function
+ func :: fa() | 'undefined', % Current function
errors = [] :: [error()], % Errors
warnings= [] :: [warning()]}). % Warnings
diff --git a/lib/compiler/src/rec_env.erl b/lib/compiler/src/rec_env.erl
index 0e9e12d1ad..5a4a870769 100644
--- a/lib/compiler/src/rec_env.erl
+++ b/lib/compiler/src/rec_env.erl
@@ -598,7 +598,16 @@ start_range(Env) ->
%% (pseudo-)randomly distributed over the range.
generate(_N, Range) ->
- random:uniform(Range). % works well
+ %% We must use the same sequence of random variables to ensure
+ %% that two compilations of the same source code generates the
+ %% same BEAM code.
+ case rand:export_seed() of
+ undefined ->
+ rand:seed(exsplus, {1,42,2053});
+ _ ->
+ ok
+ end,
+ rand:uniform(Range). % works well
%% =====================================================================
diff --git a/lib/compiler/src/sys_core_dsetel.erl b/lib/compiler/src/sys_core_dsetel.erl
index ac32db10fe..c6cfdbae7e 100644
--- a/lib/compiler/src/sys_core_dsetel.erl
+++ b/lib/compiler/src/sys_core_dsetel.erl
@@ -72,7 +72,7 @@ module(M0, _Options) ->
{ok,M}.
visit_module(#c_module{defs=Ds0}=R) ->
- Env = dict:new(),
+ Env = #{},
Ds = visit_module_1(Ds0, Env, []),
R#c_module{defs=Ds}.
@@ -95,9 +95,11 @@ visit(Env, #c_var{name={_,_}}=R) ->
{R, Env};
visit(Env0, #c_var{name=X}=R) ->
%% There should not be any free variables. If there are,
- %% the next line will cause an exception.
- {ok, N} = dict:find(X, Env0),
- {R, dict:store(X, N+1, Env0)};
+ %% the case will fail with an exception.
+ case Env0 of
+ #{X:=N} ->
+ {R, Env0#{X:=N+1}}
+ end;
visit(Env, #c_literal{}=R) ->
{R, Env};
visit(Env0, #c_tuple{es=Es0}=R) ->
@@ -203,7 +205,7 @@ bind_vars(Vs, Env) ->
bind_vars(Vs, Env, []).
bind_vars([#c_var{name=X}|Vs], Env0, Xs)->
- bind_vars(Vs, dict:store(X, 0, Env0), [X|Xs]);
+ bind_vars(Vs, Env0#{X=>0}, [X|Xs]);
bind_vars([], Env,Xs) ->
{Xs, Env}.
@@ -217,7 +219,7 @@ visit_pats([], Env, Vs) ->
{Vs, Env}.
visit_pat(Env0, #c_var{name=V}, Vs) ->
- {[V|Vs], dict:store(V, 0, Env0)};
+ {[V|Vs], Env0#{V=>0}};
visit_pat(Env0, #c_tuple{es=Es}, Vs) ->
visit_pats(Es, Env0, Vs);
visit_pat(Env0, #c_map{es=Es}, Vs) ->
@@ -235,23 +237,25 @@ visit_pat(Env0, #c_bitstr{val=Val,size=Sz}, Vs0) ->
case Sz of
#c_var{name=V} ->
%% We don't tolerate free variables.
- {ok, N} = dict:find(V, Env0),
- {Vs0, dict:store(V, N+1, Env0)};
+ case Env0 of
+ #{V:=N} ->
+ {Vs0, Env0#{V:=N+1}}
+ end;
_ ->
visit_pat(Env0, Sz, Vs0)
end,
visit_pat(Env1, Val, Vs1);
visit_pat(Env0, #c_alias{pat=P,var=#c_var{name=V}}, Vs) ->
- visit_pat(dict:store(V, 0, Env0), P, [V|Vs]);
+ visit_pat(Env0#{V=>0}, P, [V|Vs]);
visit_pat(Env, #c_literal{}, Vs) ->
{Vs, Env}.
restore_vars([V|Vs], Env0, Env1) ->
- case dict:find(V, Env0) of
- {ok, N} ->
- restore_vars(Vs, Env0, dict:store(V, N, Env1));
- error ->
- restore_vars(Vs, Env0, dict:erase(V, Env1))
+ case Env0 of
+ #{V:=N} ->
+ restore_vars(Vs, Env0, Env1#{V=>N});
+ _ ->
+ restore_vars(Vs, Env0, maps:remove(V, Env1))
end;
restore_vars([], _, Env1) ->
Env1.
@@ -349,8 +353,8 @@ is_safe(#c_literal{}) -> true;
is_safe(_) -> false.
is_single_use(V, Env) ->
- case dict:find(V, Env) of
- {ok, 1} ->
+ case Env of
+ #{V:=1} ->
true;
_ ->
false
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index 65699ccda9..ab67c8164b 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -277,7 +277,7 @@ expr(#c_fun{}=Fun, effect, _) ->
add_warning(Fun, useless_building),
void();
expr(#c_fun{vars=Vs0,body=B0}=Fun, Ctxt0, Sub0) ->
- {Vs1,Sub1} = pattern_list(Vs0, Sub0),
+ {Vs1,Sub1} = var_list(Vs0, Sub0),
Ctxt = case Ctxt0 of
{letrec,Ctxt1} -> Ctxt1;
value -> value
@@ -420,13 +420,13 @@ expr(#c_try{anno=A,arg=E0,vars=Vs0,body=B0,evars=Evs0,handler=H0}=Try, _, Sub0)
%% Here is the general try/catch construct outside of guards.
%% We can remove try if the value is simple and replace it with a let.
E1 = body(E0, value, Sub0),
- {Vs1,Sub1} = pattern_list(Vs0, Sub0),
+ {Vs1,Sub1} = var_list(Vs0, Sub0),
B1 = body(B0, value, Sub1),
case is_safe_simple(E1, Sub0) of
true ->
expr(#c_let{anno=A,vars=Vs1,arg=E1,body=B1}, value, Sub0);
false ->
- {Evs1,Sub2} = pattern_list(Evs0, Sub0),
+ {Evs1,Sub2} = var_list(Evs0, Sub0),
H1 = body(H0, value, Sub2),
Try#c_try{arg=E1,vars=Vs1,body=B1,evars=Evs1,handler=H1}
end.
@@ -1078,15 +1078,28 @@ is_atom_or_var(_) -> false.
%% clause(Clause, Cepxr, Context, Sub) -> Clause.
-clause(#c_clause{pats=Ps0,guard=G0,body=B0}=Cl, Cexpr, Ctxt, Sub0) ->
- {Ps1,Sub1} = pattern_list(Ps0, Sub0),
+clause(#c_clause{pats=Ps0}=Cl, Cexpr, Ctxt, Sub0) ->
+ try pattern_list(Ps0, Sub0) of
+ {Ps1,Sub1} ->
+ clause_1(Cl, Ps1, Cexpr, Ctxt, Sub1)
+ catch
+ nomatch ->
+ Cl#c_clause{anno=[compiler_generated],
+ guard=#c_literal{val=false}}
+ end.
+
+clause_1(#c_clause{guard=G0,body=B0}=Cl, Ps1, Cexpr, Ctxt, Sub1) ->
Sub2 = update_types(Cexpr, Ps1, Sub1),
- GSub = case {Cexpr,Ps1} of
- {#c_var{name='_'},_} ->
+ GSub = case {Cexpr,Ps1,G0} of
+ {_,_,#c_literal{}} ->
+ %% No need for substitution tricks when the guard
+ %% does not contain any variables.
+ Sub2;
+ {#c_var{name='_'},_,_} ->
%% In a 'receive', Cexpr is the variable '_', which represents the
%% message being matched. We must NOT do any extra substiutions.
Sub2;
- {#c_var{},[#c_var{}=Var]} ->
+ {#c_var{},[#c_var{}=Var],_} ->
%% The idea here is to optimize expressions such as
%%
%% case A of A -> ...
@@ -1120,7 +1133,7 @@ clause(#c_clause{pats=Ps0,guard=G0,body=B0}=Cl, Cexpr, Ctxt, Sub0) ->
%% the unsubstituted variables and values.
let_substs(Vs0, As0, Sub0) ->
- {Vs1,Sub1} = pattern_list(Vs0, Sub0),
+ {Vs1,Sub1} = var_list(Vs0, Sub0),
{Vs2,As1,Ss} = let_substs_1(Vs1, As0, Sub1),
Sub2 = sub_add_scope([V || #c_var{name=V} <- Vs2], Sub1),
{Vs2,As1,
@@ -1206,20 +1219,132 @@ bin_pattern_list(Ps0, Isub, Osub0) ->
{Ps,{_,Osub}} = mapfoldl(fun bin_pattern/2, {Isub,Osub0}, Ps0),
{Ps,Osub}.
-bin_pattern(#c_bitstr{val=E0,size=Size0}=Pat, {Isub0,Osub0}) ->
+bin_pattern(#c_bitstr{val=E0,size=Size0}=Pat0, {Isub0,Osub0}) ->
Size1 = expr(Size0, Isub0),
{E1,Osub} = pattern(E0, Isub0, Osub0),
Isub = case E0 of
#c_var{} -> sub_set_var(E0, E1, Isub0);
_ -> Isub0
end,
- {Pat#c_bitstr{val=E1,size=Size1},{Isub,Osub}}.
+ Pat = Pat0#c_bitstr{val=E1,size=Size1},
+ bin_pat_warn(Pat),
+ {Pat,{Isub,Osub}}.
pattern_list(Ps, Sub) -> pattern_list(Ps, Sub, Sub).
pattern_list(Ps0, Isub, Osub0) ->
mapfoldl(fun (P, Osub) -> pattern(P, Isub, Osub) end, Osub0, Ps0).
+%% var_list([Var], InSub) -> {Pattern,OutSub}.
+%% Works like pattern_list/2 but only accept variables and is
+%% guaranteed not to throw an exception.
+
+var_list(Vs, Sub0) ->
+ mapfoldl(fun (#c_var{}=V, Sub) ->
+ pattern(V, Sub, Sub)
+ end, Sub0, Vs).
+
+
+%%%
+%%% Generate warnings for binary patterns that will not match.
+%%%
+
+bin_pat_warn(#c_bitstr{type=#c_literal{val=Type},
+ val=Val0,
+ size=#c_literal{val=Sz},
+ unit=#c_literal{val=Unit},
+ flags=Fl}=Pat) ->
+ case {Type,Sz} of
+ {_,_} when is_integer(Sz), Sz >= 0 -> ok;
+ {binary,all} -> ok;
+ {utf8,undefined} -> ok;
+ {utf16,undefined} -> ok;
+ {utf32,undefined} -> ok;
+ {_,_} ->
+ add_warning(Pat, {nomatch_bit_syntax_size,Sz}),
+ throw(nomatch)
+ end,
+ case {Type,Val0} of
+ {integer,#c_literal{val=Val}} when is_integer(Val) ->
+ Signedness = signedness(Fl),
+ TotalSz = Sz * Unit,
+ bit_pat_warn_int(Val, TotalSz, Signedness, Pat);
+ {float,#c_literal{val=Val}} when is_float(Val) ->
+ ok;
+ {utf8,#c_literal{val=Val}} when is_integer(Val) ->
+ bit_pat_warn_unicode(Val, Pat);
+ {utf16,#c_literal{val=Val}} when is_integer(Val) ->
+ bit_pat_warn_unicode(Val, Pat);
+ {utf32,#c_literal{val=Val}} when is_integer(Val) ->
+ bit_pat_warn_unicode(Val, Pat);
+ {_,#c_literal{val=Val}} ->
+ add_warning(Pat, {nomatch_bit_syntax_type,Val,Type}),
+ throw(nomatch);
+ {_,_} ->
+ ok
+ end;
+bin_pat_warn(#c_bitstr{type=#c_literal{val=Type},val=Val0,flags=Fl}=Pat) ->
+ %% Size is variable. Not much that we can check.
+ case {Type,Val0} of
+ {integer,#c_literal{val=Val}} when is_integer(Val) ->
+ case signedness(Fl) of
+ unsigned when Val < 0 ->
+ add_warning(Pat, {nomatch_bit_syntax_unsigned,Val}),
+ throw(nomatch);
+ _ ->
+ ok
+ end;
+ {float,#c_literal{val=Val}} when is_float(Val) ->
+ ok;
+ {_,#c_literal{val=Val}} ->
+ add_warning(Pat, {nomatch_bit_syntax_type,Val,Type}),
+ throw(nomatch);
+ {_,_} ->
+ ok
+ end.
+
+bit_pat_warn_int(Val, 0, signed, Pat) ->
+ if
+ Val =:= 0 ->
+ ok;
+ true ->
+ add_warning(Pat, {nomatch_bit_syntax_truncated,signed,Val,0}),
+ throw(nomatch)
+ end;
+bit_pat_warn_int(Val, Sz, signed, Pat) ->
+ if
+ Val < 0, Val bsr (Sz - 1) =/= -1 ->
+ add_warning(Pat, {nomatch_bit_syntax_truncated,signed,Val,Sz}),
+ throw(nomatch);
+ Val > 0, Val bsr (Sz - 1) =/= 0 ->
+ add_warning(Pat, {nomatch_bit_syntax_truncated,signed,Val,Sz}),
+ throw(nomatch);
+ true ->
+ ok
+ end;
+bit_pat_warn_int(Val, _Sz, unsigned, Pat) when Val < 0 ->
+ add_warning(Pat, {nomatch_bit_syntax_unsigned,Val}),
+ throw(nomatch);
+bit_pat_warn_int(Val, Sz, unsigned, Pat) ->
+ if
+ Val bsr Sz =:= 0 ->
+ ok;
+ true ->
+ add_warning(Pat, {nomatch_bit_syntax_truncated,unsigned,Val,Sz}),
+ throw(nomatch)
+ end.
+
+bit_pat_warn_unicode(U, _Pat) when 0 =< U, U =< 16#10FFFF ->
+ ok;
+bit_pat_warn_unicode(U, Pat) ->
+ add_warning(Pat, {nomatch_bit_syntax_unicode,U}),
+ throw(nomatch).
+
+signedness(#c_literal{val=Flags}) ->
+ [S] = [F || F <- Flags, F =:= signed orelse F =:= unsigned],
+ S.
+
+
%% is_subst(Expr) -> true | false.
%% Test whether an expression is a suitable substitution.
@@ -2251,11 +2376,11 @@ move_let_into_expr(#c_let{vars=InnerVs0,body=InnerBody0}=Inner,
%%
Arg = body(Arg0, Sub0),
ScopeSub0 = sub_subst_scope(Sub0#sub{t=#{}}),
- {OuterVs,ScopeSub} = pattern_list(OuterVs0, ScopeSub0),
+ {OuterVs,ScopeSub} = var_list(OuterVs0, ScopeSub0),
OuterBody = body(OuterBody0, ScopeSub),
- {InnerVs,Sub} = pattern_list(InnerVs0, Sub0),
+ {InnerVs,Sub} = var_list(InnerVs0, Sub0),
InnerBody = body(InnerBody0, Sub),
Outer#c_let{vars=OuterVs,arg=Arg,
body=Inner#c_let{vars=InnerVs,arg=OuterBody,body=InnerBody}};
@@ -2271,39 +2396,49 @@ move_let_into_expr(#c_let{vars=Lvs0,body=Lbody0}=Let,
case {TwoClauses,is_failing_clause(Ca0),is_failing_clause(Cb0)} of
{true,false,true} ->
%% let <Lvars> = case <Case-expr> of
- %% <Cvars> -> <Clause-body>;
- %% <OtherCvars> -> erlang:error(...)
+ %% <Cpats> -> <Clause-body>;
+ %% <OtherCpats> -> erlang:error(...)
%% end
%% in <Let-body>
%%
%% ==>
%%
%% case <Case-expr> of
- %% <Cvars> ->
+ %% <Cpats> ->
%% let <Lvars> = <Clause-body>
%% in <Let-body>;
- %% <OtherCvars> -> erlang:error(...)
+ %% <OtherCpats> -> erlang:error(...)
%% end
Cexpr = body(Cexpr0, Sub0),
- CaVars0 = Ca0#c_clause.pats,
+ CaPats0 = Ca0#c_clause.pats,
G0 = Ca0#c_clause.guard,
B0 = Ca0#c_clause.body,
ScopeSub0 = sub_subst_scope(Sub0#sub{t=#{}}),
- {CaVars,ScopeSub} = pattern_list(CaVars0, ScopeSub0),
- G = guard(G0, ScopeSub),
-
- B1 = body(B0, ScopeSub),
-
- {Lvs,B2,Sub1} = let_substs(Lvs0, B1, Sub0),
- Sub2 = Sub1#sub{s=cerl_sets:union(ScopeSub#sub.s,
- Sub1#sub.s)},
- Lbody = body(Lbody0, Sub2),
- B = Let#c_let{vars=Lvs,arg=core_lib:make_values(B2),body=Lbody},
-
- Ca = Ca0#c_clause{pats=CaVars,guard=G,body=B},
- Cb = clause(Cb0, Cexpr, value, Sub0),
- Case#c_case{arg=Cexpr,clauses=[Ca,Cb]};
+ try pattern_list(CaPats0, ScopeSub0) of
+ {CaPats,ScopeSub} ->
+ G = guard(G0, ScopeSub),
+
+ B1 = body(B0, ScopeSub),
+
+ {Lvs,B2,Sub1} = let_substs(Lvs0, B1, Sub0),
+ Sub2 = Sub1#sub{s=cerl_sets:union(ScopeSub#sub.s,
+ Sub1#sub.s)},
+ Lbody = body(Lbody0, Sub2),
+ B = Let#c_let{vars=Lvs,
+ arg=core_lib:make_values(B2),
+ body=Lbody},
+
+ Ca = Ca0#c_clause{pats=CaPats,guard=G,body=B},
+ Cb = clause(Cb0, Cexpr, value, Sub0),
+ Case#c_case{arg=Cexpr,clauses=[Ca,Cb]}
+ catch
+ nomatch ->
+ %% This is not a defeat. The code will eventually
+ %% be optimized to erlang:error(...) by the other
+ %% optimizations done in this module.
+ impossible
+ end;
{_,_,_} -> impossible
end;
move_let_into_expr(#c_let{vars=Lvs0,body=Lbody0}=Let,
@@ -2595,7 +2730,7 @@ move_case_into_arg(#c_case{arg=#c_let{vars=OuterVars0,arg=OuterArg,
%% in case <InnerArg> of <InnerClauses> end
%%
ScopeSub0 = sub_subst_scope(Sub#sub{t=#{}}),
- {OuterVars,ScopeSub} = pattern_list(OuterVars0, ScopeSub0),
+ {OuterVars,ScopeSub} = var_list(OuterVars0, ScopeSub0),
InnerArg = body(InnerArg0, ScopeSub),
Outer#c_let{vars=OuterVars,arg=OuterArg,
body=Inner#c_case{arg=InnerArg,clauses=InnerClauses}};
@@ -2624,14 +2759,18 @@ move_case_into_arg(#c_case{arg=#c_case{arg=OuterArg,
%% end
%%
ScopeSub0 = sub_subst_scope(Sub#sub{t=#{}}),
- {OuterPats,ScopeSub} = pattern_list(OuterPats0, ScopeSub0),
- OuterGuard = guard(OuterGuard0, ScopeSub),
- InnerArg = body(InnerArg0, ScopeSub),
- Inner = Inner0#c_case{arg=InnerArg,clauses=InnerClauses},
- OuterCa = OuterCa0#c_clause{pats=OuterPats,guard=OuterGuard,
- body=Inner},
- Outer#c_case{arg=OuterArg,
- clauses=[OuterCa,OuterCb]};
+
+ %% We KNOW that pattern_list/2 has already been called for OuterPats0;
+ %% therefore, it cannot throw an exception.
+ {OuterPats,ScopeSub} = pattern_list(OuterPats0, ScopeSub0),
+ OuterGuard = guard(OuterGuard0, ScopeSub),
+ InnerArg = body(InnerArg0, ScopeSub),
+ Inner = Inner0#c_case{arg=InnerArg,clauses=InnerClauses},
+ OuterCa = OuterCa0#c_clause{pats=OuterPats,
+ guard=OuterGuard,
+ body=Inner},
+ Outer#c_case{arg=OuterArg,
+ clauses=[OuterCa,OuterCb]};
false ->
impossible
end;
@@ -2793,12 +2932,18 @@ extract_type_1(Expr, Sub) ->
true -> bool
end.
+returns_integer('band', [_,_]) -> true;
+returns_integer('bnot', [_]) -> true;
+returns_integer('bor', [_,_]) -> true;
+returns_integer('bxor', [_,_]) -> true;
returns_integer(bit_size, [_]) -> true;
returns_integer('bsl', [_,_]) -> true;
returns_integer('bsr', [_,_]) -> true;
returns_integer(byte_size, [_]) -> true;
+returns_integer('div', [_,_]) -> true;
returns_integer(length, [_]) -> true;
returns_integer('rem', [_,_]) -> true;
+returns_integer('round', [_]) -> true;
returns_integer(size, [_]) -> true;
returns_integer(tuple_size, [_]) -> true;
returns_integer(trunc, [_]) -> true;
@@ -3207,6 +3352,29 @@ format_error(nomatch_shadow) ->
"this clause cannot match because a previous clause always matches";
format_error(nomatch_guard) ->
"the guard for this clause evaluates to 'false'";
+format_error({nomatch_bit_syntax_truncated,Signess,Val,Sz}) ->
+ S = case Signess of
+ signed -> "a 'signed'";
+ unsigned -> "an 'unsigned'"
+ end,
+ F = "this clause cannot match because the value ~P"
+ " will not fit in ~s binary segment of size ~p",
+ flatten(io_lib:format(F, [Val,10,S,Sz]));
+format_error({nomatch_bit_syntax_unsigned,Val}) ->
+ F = "this clause cannot match because the negative value ~P"
+ " will never match the value of an 'unsigned' binary segment",
+ flatten(io_lib:format(F, [Val,10]));
+format_error({nomatch_bit_syntax_size,Sz}) ->
+ F = "this clause cannot match because '~P' is not a valid size for a binary segment",
+ flatten(io_lib:format(F, [Sz,10]));
+format_error({nomatch_bit_syntax_type,Val,Type}) ->
+ F = "this clause cannot match because '~P' is not of the"
+ " expected type '~p'",
+ flatten(io_lib:format(F, [Val,10,Type]));
+format_error({nomatch_bit_syntax_unicode,Val}) ->
+ F = "this clause cannot match because the value ~p"
+ " is not a valid Unicode code point",
+ flatten(io_lib:format(F, [Val]));
format_error(no_clause_match) ->
"no clause will ever match";
format_error(nomatch_clause_type) ->
diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl
index d9cc4b530c..7ab4e1845c 100644
--- a/lib/compiler/src/sys_pre_expand.erl
+++ b/lib/compiler/src/sys_pre_expand.erl
@@ -29,30 +29,26 @@
%% Main entry point.
-export([module/2]).
--import(ordsets, [from_list/1,union/2]).
-import(lists, [member/2,foldl/3,foldr/3]).
--include("../include/erl_bits.hrl").
-
-type fa() :: {atom(), arity()}.
-record(expand, {module=[], %Module name
exports=[], %Exports
- imports=[], %Imports
attributes=[], %Attributes
callbacks=[], %Callbacks
optional_callbacks=[] :: [fa()], %Optional callbacks
- defined, %Defined functions (gb_set)
vcount=0, %Variable counter
func=[], %Current function
arity=[], %Arity for current function
- fcount=0 %Local fun count
+ fcount=0, %Local fun count
+ ctype %Call type map
}).
%% module(Forms, CompileOptions)
%% {ModuleName,Exports,TransformedForms,CompileOptions'}
-%% Expand the forms in one module. N.B.: the lists of predefined
-%% exports and imports are really ordsets!
+%% Expand the forms in one module.
+%%
%% CompileOptions is augmented with options from -compile attributes.
module(Fs0, Opts0) ->
@@ -65,19 +61,28 @@ module(Fs0, Opts0) ->
%% Set pre-defined exported functions.
PreExp = [{module_info,0},{module_info,1}],
+ %% Build the set of defined functions and the initial call
+ %% type map.
+ Defined = defined_functions(Fs, PreExp),
+ Ctype = maps:from_list([{K,local} || K <- Defined]),
+
%% Build initial expand record.
St0 = #expand{exports=PreExp,
- defined=PreExp
+ ctype=Ctype
},
+
%% Expand the functions.
- {Tfs,St1} = forms(Fs, define_functions(Fs, St0)),
+ {Tfs,St1} = forms(Fs, St0),
+
%% Get the correct list of exported functions.
Exports = case member(export_all, Opts) of
- true -> gb_sets:to_list(St1#expand.defined);
+ true -> Defined;
false -> St1#expand.exports
end,
+ St2 = St1#expand{exports=Exports,ctype=undefined},
+
%% Generate all functions from stored info.
- {Ats,St3} = module_attrs(St1#expand{exports = Exports}),
+ {Ats,St3} = module_attrs(St2),
{Mfs,St4} = module_predef_funcs(St3),
{St4#expand.module, St4#expand.exports, Ats ++ Tfs ++ Mfs,
Opts}.
@@ -85,14 +90,14 @@ module(Fs0, Opts0) ->
compiler_options(Forms) ->
lists:flatten([C || {attribute,_,compile,C} <- Forms]).
-%% define_function(Form, State) -> State.
+%% defined_function(Forms, Predef) -> Functions.
%% Add function to defined if form is a function.
-define_functions(Forms, #expand{defined=Predef}=St) ->
+defined_functions(Forms, Predef) ->
Fs = foldl(fun({function,_,N,A,_Cs}, Acc) -> [{N,A}|Acc];
(_, Acc) -> Acc
end, Predef, Forms),
- St#expand{defined=gb_sets:from_list(Fs)}.
+ ordsets:from_list(Fs).
module_attrs(#expand{attributes=Attributes}=St) ->
Attrs = [{attribute,Line,Name,Val} || {Name,Line,Val} <- Attributes],
@@ -113,23 +118,21 @@ is_fa_list([{FuncName, Arity}|L])
is_fa_list([]) -> true;
is_fa_list(_) -> false.
-module_predef_funcs(St) ->
- {Mpf1,St1}=module_predef_func_beh_info(St),
- {Mpf2,St2}=module_predef_funcs_mod_info(St1),
+module_predef_funcs(St0) ->
+ {Mpf1,St1} = module_predef_func_beh_info(St0),
+ Mpf2 = module_predef_funcs_mod_info(St1),
Mpf = [erl_parse:new_anno(F) || F <- Mpf1++Mpf2],
- {Mpf,St2}.
+ {Mpf,St1}.
module_predef_func_beh_info(#expand{callbacks=[]}=St) ->
{[], St};
module_predef_func_beh_info(#expand{callbacks=Callbacks,
optional_callbacks=OptionalCallbacks,
- defined=Defined,
exports=Exports}=St) ->
- PreDef=[{behaviour_info,1}],
- PreExp=PreDef,
+ PreDef0 = [{behaviour_info,1}],
+ PreDef = ordsets:from_list(PreDef0),
{[gen_beh_info(Callbacks, OptionalCallbacks)],
- St#expand{defined=gb_sets:union(gb_sets:from_list(PreDef), Defined),
- exports=union(from_list(PreExp), Exports)}}.
+ St#expand{exports=ordsets:union(PreDef, Exports)}}.
gen_beh_info(Callbacks, OptionalCallbacks) ->
List = make_list(Callbacks),
@@ -156,20 +159,16 @@ make_optional_list([{Name,Arity}|Rest]) ->
{integer,0,Arity}]},
make_optional_list(Rest)}.
-module_predef_funcs_mod_info(St) ->
- PreDef = [{module_info,0},{module_info,1}],
- PreExp = PreDef,
- {[{function,0,module_info,0,
- [{clause,0,[],[],
+module_predef_funcs_mod_info(#expand{module=Mod}) ->
+ ModAtom = {atom,0,Mod},
+ [{function,0,module_info,0,
+ [{clause,0,[],[],
[{call,0,{remote,0,{atom,0,erlang},{atom,0,get_module_info}},
- [{atom,0,St#expand.module}]}]}]},
- {function,0,module_info,1,
- [{clause,0,[{var,0,'X'}],[],
+ [ModAtom]}]}]},
+ {function,0,module_info,1,
+ [{clause,0,[{var,0,'X'}],[],
[{call,0,{remote,0,{atom,0,erlang},{atom,0,get_module_info}},
- [{atom,0,St#expand.module},{var,0,'X'}]}]}]}],
- St#expand{defined=gb_sets:union(gb_sets:from_list(PreDef),
- St#expand.defined),
- exports=union(from_list(PreExp), St#expand.exports)}}.
+ [ModAtom,{var,0,'X'}]}]}]}].
%% forms(Forms, State) ->
%% {TransformedForms,State'}
@@ -196,7 +195,8 @@ attribute(module, Module, _L, St) ->
true = is_atom(Module),
St#expand{module=Module};
attribute(export, Es, _L, St) ->
- St#expand{exports=union(from_list(Es), St#expand.exports)};
+ St#expand{exports=ordsets:union(ordsets:from_list(Es),
+ St#expand.exports)};
attribute(import, Is, _L, St) ->
import(Is, St);
attribute(compile, _C, _L, St) ->
@@ -231,8 +231,6 @@ head(As, St) -> pattern_list(As, St).
%% {TransformedPattern,State'}
%%
-pattern({var,_,'_'}=Var, St) -> %Ignore anonymous variable.
- {Var,St};
pattern({var,_,_}=Var, St) ->
{Var,St};
pattern({char,_,_}=Char, St) ->
@@ -385,19 +383,19 @@ expr({block,Line,Es0}, St0) ->
{Es,St1} = exprs(Es0, St0),
{{block,Line,Es},St1};
expr({'if',Line,Cs0}, St0) ->
- {Cs,St1} = icr_clauses(Cs0, St0),
+ {Cs,St1} = clauses(Cs0, St0),
{{'if',Line,Cs},St1};
expr({'case',Line,E0,Cs0}, St0) ->
{E,St1} = expr(E0, St0),
- {Cs,St2} = icr_clauses(Cs0, St1),
+ {Cs,St2} = clauses(Cs0, St1),
{{'case',Line,E,Cs},St2};
expr({'receive',Line,Cs0}, St0) ->
- {Cs,St1} = icr_clauses(Cs0, St0),
+ {Cs,St1} = clauses(Cs0, St0),
{{'receive',Line,Cs},St1};
expr({'receive',Line,Cs0,To0,ToEs0}, St0) ->
{To,St1} = expr(To0, St0),
{ToEs,St2} = exprs(ToEs0, St1),
- {Cs,St3} = icr_clauses(Cs0, St2),
+ {Cs,St3} = clauses(Cs0, St2),
{{'receive',Line,Cs,To,ToEs},St3};
expr({'fun',Line,Body}, St) ->
fun_tq(Line, Body, St);
@@ -406,21 +404,15 @@ expr({named_fun,Line,Name,Cs}, St) ->
expr({call,Line,{atom,La,N}=Atom,As0}, St0) ->
{As,St1} = expr_list(As0, St0),
Ar = length(As),
- case defined(N,Ar,St1) of
- true ->
+ Key = {N,Ar},
+ case St1#expand.ctype of
+ #{Key:=local} ->
{{call,Line,Atom,As},St1};
+ #{Key:={imported,Mod}} ->
+ {{call,Line,{remote,La,{atom,La,Mod},Atom},As},St1};
_ ->
- case imported(N, Ar, St1) of
- {yes,Mod} ->
- {{call,Line,{remote,La,{atom,La,Mod},Atom},As},St1};
- no ->
- case erl_internal:bif(N, Ar) of
- true ->
- {{call,Line,{remote,La,{atom,La,erlang},Atom},As},St1};
- false -> %% This should have been handled by erl_lint
- {{call,Line,Atom,As},St1}
- end
- end
+ true = erl_internal:bif(N, Ar),
+ {{call,Line,{remote,La,{atom,La,erlang},Atom},As},St1}
end;
expr({call,Line,{remote,Lr,M0,F},As0}, St0) ->
{[M1,F1|As1],St1} = expr_list([M0,F|As0], St0),
@@ -430,12 +422,11 @@ expr({call,Line,F,As0}, St0) ->
{{call,Line,Fun1,As1},St1};
expr({'try',Line,Es0,Scs0,Ccs0,As0}, St0) ->
{Es1,St1} = exprs(Es0, St0),
- {Scs1,St2} = icr_clauses(Scs0, St1),
- {Ccs1,St3} = icr_clauses(Ccs0, St2),
+ {Scs1,St2} = clauses(Scs0, St1),
+ {Ccs1,St3} = clauses(Ccs0, St2),
{As1,St4} = exprs(As0, St3),
{{'try',Line,Es1,Scs1,Ccs1,As1},St4};
expr({'catch',Line,E0}, St0) ->
- %% Catch exports no new variables.
{E,St1} = expr(E0, St0),
{{'catch',Line,E},St1};
expr({match,Line,P0,E0}, St0) ->
@@ -456,21 +447,6 @@ expr_list([E0|Es0], St0) ->
{[E|Es],St2};
expr_list([], St) -> {[],St}.
-%% icr_clauses([Clause], State) -> {[TransformedClause],State'}
-%% Be very careful here to return the variables that are really used
-%% and really new.
-
-icr_clauses([], St) -> {[],St};
-icr_clauses(Clauses, St) -> icr_clauses2(Clauses, St).
-
-icr_clauses2([{clause,Line,H0,G0,B0}|Cs0], St0) ->
- {H,St1} = head(H0, St0),
- {G,St2} = guard(G0, St1),
- {B,St3} = exprs(B0, St2),
- {Cs,St4} = icr_clauses2(Cs0, St3),
- {[{clause,Line,H,G,B}|Cs],St4};
-icr_clauses2([], St) -> {[],St}.
-
%% lc_tq(Line, Qualifiers, State) ->
%% {[TransQual],State'}
@@ -486,16 +462,9 @@ lc_tq(Line, [{b_generate,Lg,P0,G0}|Qs0], St0) ->
{Qs1,St3} = lc_tq(Line, Qs0, St2),
{[{b_generate,Lg,P1,G1}|Qs1],St3};
lc_tq(Line, [F0 | Qs0], St0) ->
- case erl_lint:is_guard_test(F0) of
- true ->
- {F1,St1} = guard_test(F0, St0),
- {Qs1,St2} = lc_tq(Line, Qs0, St1),
- {[F1|Qs1],St2};
- false ->
- {F1,St1} = expr(F0, St0),
- {Qs1,St2} = lc_tq(Line, Qs0, St1),
- {[F1 | Qs1],St2}
- end;
+ {F1,St1} = expr(F0, St0),
+ {Qs1,St2} = lc_tq(Line, Qs0, St1),
+ {[F1|Qs1],St2};
lc_tq(_Line, [], St0) ->
{[],St0}.
@@ -527,7 +496,7 @@ fun_tq(L, {function,M,F,A}, St) when is_atom(M), is_atom(F), is_integer(A) ->
fun_tq(Lf, {function,_,_,_}=ExtFun, St) ->
{{'fun',Lf,ExtFun},St};
fun_tq(Lf, {clauses,Cs0}, St0) ->
- {Cs1,St1} = fun_clauses(Cs0, St0),
+ {Cs1,St1} = clauses(Cs0, St0),
{Fname,St2} = new_fun_name(St1),
%% Set dummy values for Index and Uniq -- the real values will
%% be assigned by beam_asm.
@@ -535,18 +504,10 @@ fun_tq(Lf, {clauses,Cs0}, St0) ->
{{'fun',Lf,{clauses,Cs1},{Index,Uniq,Fname}},St2}.
fun_tq(Line, Cs0, St0, Name) ->
- {Cs1,St1} = fun_clauses(Cs0, St0),
+ {Cs1,St1} = clauses(Cs0, St0),
{Fname,St2} = new_fun_name(St1, Name),
{{named_fun,Line,Name,Cs1,{0,0,Fname}},St2}.
-fun_clauses([{clause,L,H0,G0,B0}|Cs0], St0) ->
- {H,St1} = head(H0, St0),
- {G,St2} = guard(G0, St1),
- {B,St3} = exprs(B0, St2),
- {Cs,St4} = fun_clauses(Cs0, St3),
- {[{clause,L,H,G,B}|Cs],St4};
-fun_clauses([], St) -> {[],St}.
-
%% new_fun_name(State) -> {FunName,State}.
new_fun_name(St) ->
@@ -571,7 +532,6 @@ pattern_element({bin_element,Line,Expr0,Size0,Type0}, {Es,St0}) ->
{[{bin_element,Line,Expr,Size,Type}|Es],St2}.
pat_bit_size(default, St) -> {default,St};
-pat_bit_size({atom,_La,all}=All, St) -> {All,St};
pat_bit_size({var,_Lv,_V}=Var, St) -> {Var,St};
pat_bit_size(Size, St) ->
Line = element(2, Size),
@@ -592,8 +552,7 @@ coerce_to_float({integer,L,I}=E, [float|_]) ->
try
{float,L,float(I)}
catch
- error:badarg -> E;
- error:badarith -> E
+ error:badarg -> E
end;
coerce_to_float(E, _) -> E.
@@ -647,25 +606,11 @@ string_to_conses(Line, Cs, Tail) ->
%% import(Line, Imports, State) ->
%% State'
-%% imported(Name, Arity, State) ->
-%% {yes,Module} | no
-%% Handle import declarations and test for imported functions. No need to
-%% check when building imports as code is correct.
+%% Handle import declarations.
-import({Mod,Fs}, St) ->
+import({Mod,Fs}, #expand{ctype=Ctype0}=St) ->
true = is_atom(Mod),
- Mfs = from_list(Fs),
- St#expand{imports=add_imports(Mod, Mfs, St#expand.imports)}.
-
-add_imports(Mod, [F|Fs], Is) ->
- add_imports(Mod, Fs, orddict:store(F, Mod, Is));
-add_imports(_, [], Is) -> Is.
-
-imported(F, A, St) ->
- case orddict:find({F,A}, St#expand.imports) of
- {ok,Mod} -> {yes,Mod};
- error -> no
- end.
-
-defined(F, A, St) ->
- gb_sets:is_element({F,A}, St#expand.defined).
+ Ctype = foldl(fun(F, A) ->
+ A#{F=>{imported,Mod}}
+ end, Ctype0, Fs),
+ St#expand{ctype=Ctype}.
diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl
index 2a89305f4d..6f1912c616 100644
--- a/lib/compiler/src/v3_codegen.erl
+++ b/lib/compiler/src/v3_codegen.erl
@@ -827,21 +827,24 @@ select_extract_bin([{var,Hd},{var,Tl}], Size0, Unit, Type, Flags, Vf,
{bs_save2,CtxReg,{Ctx,Tl}}],Int1}
end,
{Es,clear_dead(Aft, I, Vdb),St};
-select_extract_bin([{var,Hd}], Size0, Unit, binary, Flags, Vf,
+select_extract_bin([{var,Hd}], Size, Unit, binary, Flags, Vf,
I, Vdb, Bef, Ctx, Body, St) ->
- SizeReg = get_bin_size_reg(Size0, Bef),
+ %% Match the last segment of a binary. We KNOW that the size
+ %% must be 'all'.
+ Size = {atom,all}, %Assertion.
{Es,Aft} =
case vdb_find(Hd, Vdb) of
{_,_,Lhd} when Lhd =< I ->
+ %% The result will not be used. Furthermore, since we
+ %% we are at the end of the binary, the position will
+ %% not be used again; thus, it is safe to do a cheaper
+ %% test of the unit.
CtxReg = fetch_var(Ctx, Bef),
- {case SizeReg =:= {atom,all} andalso is_context_unused(Body) of
- true when Unit =:= 1 ->
+ {case Unit of
+ 1 ->
[];
- true ->
- [{test,bs_test_unit,{f,Vf},[CtxReg,Unit]}];
- false ->
- [{test,bs_skip_bits2,{f,Vf},
- [CtxReg,SizeReg,Unit,{field_flags,Flags}]}]
+ _ ->
+ [{test,bs_test_unit,{f,Vf},[CtxReg,Unit]}]
end,Bef};
{_,_,_} ->
case is_context_unused(Body) of
@@ -853,7 +856,7 @@ select_extract_bin([{var,Hd}], Size0, Unit, binary, Flags, Vf,
Name = bs_get_binary2,
Live = max_reg(Bef#sr.reg),
{[{test,Name,{f,Vf},Live,
- [CtxReg,SizeReg,Unit,{field_flags,Flags}],Rhd}],
+ [CtxReg,Size,Unit,{field_flags,Flags}],Rhd}],
Int1};
true ->
%% Since the matching context will not be used again,
@@ -868,7 +871,7 @@ select_extract_bin([{var,Hd}], Size0, Unit, binary, Flags, Vf,
Name = bs_get_binary2,
Live = max_reg(Int1#sr.reg),
{[{test,Name,{f,Vf},Live,
- [CtxReg,SizeReg,Unit,{field_flags,Flags}],CtxReg}],
+ [CtxReg,Size,Unit,{field_flags,Flags}],CtxReg}],
Int1}
end
end,
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index 7d93e2ae16..830dd9973a 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -469,7 +469,8 @@ unforce_tree([#iset{var=#c_var{name=V},arg=Arg0}|Es], D0) ->
unforce_tree(Es, D);
unforce_tree([#icall{}=Call], D) ->
unforce_tree_subst(Call, D);
-unforce_tree([Top], _) -> Top.
+unforce_tree([#c_var{name=V}], D) ->
+ gb_trees:get(V, D).
unforce_tree_subst(#icall{module=#c_literal{val=erlang},
name=#c_literal{val='=:='},
@@ -1079,13 +1080,39 @@ bc_tq1(Line, E, [#igen{anno=GAnno,ceps=Ceps,
bc_tq1(Line, E, [#ifilter{}=Filter|Qs], Mc, St) ->
filter_tq(Line, E, Filter, Mc, St, Qs, fun bc_tq1/5);
bc_tq1(_, {bin,Bl,Elements}, [], AccVar, St0) ->
- {E,Pre,St} = expr({bin,Bl,[{bin_element,Bl,
- {var,Bl,AccVar#c_var.name},
- {atom,Bl,all},
- [binary,{unit,1}]}|Elements]}, St0),
+ bc_tq_build(Bl, [], AccVar, Elements, St0);
+bc_tq1(Line, E0, [], AccVar, St0) ->
+ BsFlags = [binary,{unit,1}],
+ BsSize = {atom,Line,all},
+ {E1,Pre0,St1} = safe(E0, St0),
+ case E1 of
+ #c_var{name=VarName} ->
+ Var = {var,Line,VarName},
+ Els = [{bin_element,Line,Var,BsSize,BsFlags}],
+ bc_tq_build(Line, Pre0, AccVar, Els, St1);
+ #c_literal{val=Val} when is_bitstring(Val) ->
+ Bits = bit_size(Val),
+ <<Int0:Bits>> = Val,
+ Int = {integer,Line,Int0},
+ Sz = {integer,Line,Bits},
+ Els = [{bin_element,Line,Int,Sz,[integer,{unit,1},big]}],
+ bc_tq_build(Line, Pre0, AccVar, Els, St1);
+ _ ->
+ %% Any other safe (cons, tuple, literal) is not a
+ %% bitstring. Force the evaluation to fail (and
+ %% generate a warning).
+ Els = [{bin_element,Line,{atom,Line,bad_value},BsSize,BsFlags}],
+ bc_tq_build(Line, Pre0, AccVar, Els, St1)
+ end.
+
+bc_tq_build(Line, Pre0, #c_var{name=AccVar}, Elements0, St0) ->
+ Elements = [{bin_element,Line,{var,Line,AccVar},{atom,Line,all},
+ [binary,{unit,1}]}|Elements0],
+ {E,Pre,St} = expr({bin,Line,Elements}, St0),
#a{anno=A} = Anno0 = get_anno(E),
Anno = Anno0#a{anno=[compiler_generated,single_use|A]},
- {set_anno(E, Anno),Pre,St}.
+ {set_anno(E, Anno),Pre0++Pre,St}.
+
%% filter_tq(Line, Expr, Filter, Mc, State, [Qualifier], TqFun) ->
%% {Case,[PreExpr],State}.
@@ -1306,7 +1333,9 @@ bc_elem_size({bin,_,El}, St0) ->
Vs = [V || {_,#c_var{name=V}} <- Vars0],
{E,Pre,St} = bc_mul_pairs(F, #c_literal{val=Bits}, [], St0),
{E,Pre,Vs,St}
- end.
+ end;
+bc_elem_size(_, _) ->
+ throw(impossible).
bc_elem_size_1([{bin_element,_,_,{integer,_,N},Flags}|Es], Bits, Vars) ->
{unit,U} = keyfind(unit, 1, Flags),
@@ -1652,10 +1681,12 @@ pat_alias_map_pairs_1([]) -> [].
pat_bin(Ps, St) -> [pat_segment(P, St) || P <- Ps].
-pat_segment({bin_element,_,Val,Size,[Type,{unit,Unit}|Flags]}, St) ->
+pat_segment({bin_element,L,Val,Size,[Type,{unit,Unit}|Flags]}, St) ->
+ Anno = lineno_anno(L, St),
{Pval,[],St1} = pattern(Val,St),
{Psize,[],_St2} = pattern(Size,St1),
- #c_bitstr{val=Pval,size=Psize,
+ #c_bitstr{anno=Anno,
+ val=Pval,size=Psize,
unit=#c_literal{val=Unit},
type=#c_literal{val=Type},
flags=#c_literal{val=Flags}}.
@@ -1852,27 +1883,22 @@ uguard(Pg, Gs0, Ks, St0) ->
%% uexprs([Kexpr], [KnownVar], State) -> {[Kexpr],State}.
uexprs([#imatch{anno=A,pat=P0,arg=Arg,fc=Fc}|Les], Ks, St0) ->
- %% Optimise for simple set of unbound variable.
- case upattern(P0, Ks, St0) of
- {#c_var{},[],_Pvs,_Pus,_} ->
- %% Throw our work away and just set to iset.
+ case upat_is_new_var(P0, Ks) of
+ true ->
+ %% Assignment to a new variable.
uexprs([#iset{var=P0,arg=Arg}|Les], Ks, St0);
- _Other ->
- %% Throw our work away and set to icase.
- if
- Les =:= [] ->
- %% Need to explicitly return match "value", make
- %% safe for efficiency.
- {La0,Lps,St1} = force_safe(Arg, St0),
- La = mark_compiler_generated(La0),
- Mc = #iclause{anno=A,pats=[P0],guard=[],body=[La]},
- uexprs(Lps ++ [#icase{anno=A,
- args=[La0],clauses=[Mc],fc=Fc}], Ks, St1);
- true ->
- Mc = #iclause{anno=A,pats=[P0],guard=[],body=Les},
- uexprs([#icase{anno=A,args=[Arg],
- clauses=[Mc],fc=Fc}], Ks, St0)
- end
+ false when Les =:= [] ->
+ %% Need to explicitly return match "value", make
+ %% safe for efficiency.
+ {La0,Lps,St1} = force_safe(Arg, St0),
+ La = mark_compiler_generated(La0),
+ Mc = #iclause{anno=A,pats=[P0],guard=[],body=[La]},
+ uexprs(Lps ++ [#icase{anno=A,
+ args=[La0],clauses=[Mc],fc=Fc}], Ks, St1);
+ false ->
+ Mc = #iclause{anno=A,pats=[P0],guard=[],body=Les},
+ uexprs([#icase{anno=A,args=[Arg],
+ clauses=[Mc],fc=Fc}], Ks, St0)
end;
uexprs([Le0|Les0], Ks, St0) ->
{Le1,St1} = uexpr(Le0, Ks, St0),
@@ -1880,6 +1906,15 @@ uexprs([Le0|Les0], Ks, St0) ->
{[Le1|Les1],St2};
uexprs([], _, St) -> {[],St}.
+%% upat_is_new_var(Pattern, [KnownVar]) -> true|false.
+%% Test whether the pattern is a single, previously unknown
+%% variable.
+
+upat_is_new_var(#c_var{name=V}, Ks) ->
+ not is_element(V, Ks);
+upat_is_new_var(_, _) ->
+ false.
+
%% Mark a "safe" as compiler-generated.
mark_compiler_generated(#c_cons{anno=A,hd=H,tl=T}) ->
ann_c_cons([compiler_generated|A], mark_compiler_generated(H),
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index 7ee564683b..4446d5ff1d 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1999-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.
@@ -117,7 +117,7 @@ copy_anno(Kdst, Ksrc) ->
fcount=0, %Fun counter
ds=cerl_sets:new() :: cerl_sets:set(), %Defined variables
funs=[], %Fun functions
- free=[], %Free variables
+ free=#{}, %Free variables
ws=[] :: [warning()], %Warnings.
guard_refc=0}). %> 0 means in guard
@@ -143,8 +143,10 @@ attributes([]) -> [].
include_attribute(type) -> false;
include_attribute(spec) -> false;
+include_attribute(callback) -> false;
include_attribute(opaque) -> false;
include_attribute(export_type) -> false;
+include_attribute(record) -> false;
include_attribute(_) -> true.
function({#c_var{name={F,Arity}=FA},Body}, St0) ->
@@ -1837,14 +1839,17 @@ handle_reuse_anno_1(V, _St) -> V.
%% get_free(Name, Arity, State) -> [Free].
%% store_free(Name, Arity, [Free], State) -> State.
-get_free(F, A, St) ->
- case orddict:find({F,A}, St#kern.free) of
- {ok,Val} -> Val;
- error -> []
+get_free(F, A, #kern{free=FreeMap}) ->
+ Key = {F,A},
+ case FreeMap of
+ #{Key:=Val} -> Val;
+ _ -> []
end.
-store_free(F, A, Free, St) ->
- St#kern{free=orddict:store({F,A}, Free, St#kern.free)}.
+store_free(F, A, Free, #kern{free=FreeMap0}=St) ->
+ Key = {F,A},
+ FreeMap = FreeMap0#{Key=>Free},
+ St#kern{free=FreeMap}.
break_rets({break,Rs}) -> Rs;
break_rets(return) -> [].
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile
index 6553d10077..85118502e3 100644
--- a/lib/compiler/test/Makefile
+++ b/lib/compiler/test/Makefile
@@ -8,9 +8,12 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
MODULES= \
andor_SUITE \
apply_SUITE \
+ beam_block_SUITE \
beam_validator_SUITE \
beam_disasm_SUITE \
beam_except_SUITE \
+ beam_reorder_SUITE \
+ beam_type_SUITE \
beam_utils_SUITE \
bs_bincomp_SUITE \
bs_bit_binaries_SUITE \
@@ -42,7 +45,10 @@ MODULES= \
NO_OPT= \
andor \
apply \
+ beam_block \
beam_except \
+ beam_reorder \
+ beam_type \
beam_utils \
bs_construct \
bs_match \
@@ -63,6 +69,7 @@ NO_OPT= \
INLINE= \
andor \
apply \
+ beam_block \
beam_utils \
bs_bincomp \
bs_bit_binaries \
@@ -105,7 +112,7 @@ RELSYSDIR = $(RELEASE_PATH)/compiler_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include +clint +clint0
+ERL_COMPILE_FLAGS += +clint +clint0
EBIN = .
diff --git a/lib/compiler/test/andor_SUITE.erl b/lib/compiler/test/andor_SUITE.erl
index fae9597c8a..9736f75fe8 100644
--- a/lib/compiler/test/andor_SUITE.erl
+++ b/lib/compiler/test/andor_SUITE.erl
@@ -25,7 +25,7 @@
combined/1,in_case/1,before_and_inside_if/1,
slow_compilation/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -54,28 +54,28 @@ end_per_group(_GroupName, Config) ->
t_case(Config) when is_list(Config) ->
%% We test boolean cases almost but not quite like cases
%% generated by andalso/orelse.
- ?line less = t_case_a(1, 2),
- ?line not_less = t_case_a(2, 2),
- ?line {'EXIT',{{case_clause,false},_}} = (catch t_case_b({x,y,z}, 2)),
- ?line {'EXIT',{{case_clause,true},_}} = (catch t_case_b(a, a)),
- ?line eq = t_case_c(a, a),
- ?line ne = t_case_c(42, []),
- ?line t = t_case_d(x, x, true),
- ?line f = t_case_d(x, x, false),
- ?line f = t_case_d(x, y, true),
- ?line {'EXIT',{badarg,_}} = (catch t_case_d(x, y, blurf)),
- ?line true = (catch t_case_e({a,b}, {a,b})),
- ?line false = (catch t_case_e({a,b}, 42)),
-
- ?line true = t_case_xy(42, 100, 700),
- ?line true = t_case_xy(42, 100, whatever),
- ?line false = t_case_xy(42, wrong, 700),
- ?line false = t_case_xy(42, wrong, whatever),
-
- ?line true = t_case_xy(0, whatever, 700),
- ?line true = t_case_xy(0, 100, 700),
- ?line false = t_case_xy(0, whatever, wrong),
- ?line false = t_case_xy(0, 100, wrong),
+ less = t_case_a(1, 2),
+ not_less = t_case_a(2, 2),
+ {'EXIT',{{case_clause,false},_}} = (catch t_case_b({x,y,z}, 2)),
+ {'EXIT',{{case_clause,true},_}} = (catch t_case_b(a, a)),
+ eq = t_case_c(a, a),
+ ne = t_case_c(42, []),
+ t = t_case_d(x, x, true),
+ f = t_case_d(x, x, false),
+ f = t_case_d(x, y, true),
+ {'EXIT',{badarg,_}} = (catch t_case_d(x, y, blurf)),
+ true = (catch t_case_e({a,b}, {a,b})),
+ false = (catch t_case_e({a,b}, 42)),
+
+ true = t_case_xy(42, 100, 700),
+ true = t_case_xy(42, 100, whatever),
+ false = t_case_xy(42, wrong, 700),
+ false = t_case_xy(42, wrong, whatever),
+
+ true = t_case_xy(0, whatever, 700),
+ true = t_case_xy(0, 100, 700),
+ false = t_case_xy(0, whatever, wrong),
+ false = t_case_xy(0, 100, wrong),
ok.
@@ -135,35 +135,35 @@ t_case_y(X, Y, Z) ->
end).
t_and_or(Config) when is_list(Config) ->
- ?line true = true and true,
- ?line false = true and false,
- ?line false = false and true,
- ?line false = false and false,
-
- ?line true = id(true) and true,
- ?line false = id(true) and false,
- ?line false = id(false) and true,
- ?line false = id(false) and false,
-
- ?line true = true and id(true),
- ?line false = true and id(false),
- ?line false = false and id(true),
- ?line false = false and id(false),
-
- ?line true = true or true,
- ?line true = true or false,
- ?line true = false or true,
- ?line false = false or false,
-
- ?line true = id(true) or true,
- ?line true = id(true) or false,
- ?line true = id(false) or true,
- ?line false = id(false) or false,
-
- ?line true = true or id(true),
- ?line true = true or id(false),
- ?line true = false or id(true),
- ?line false = false or id(false),
+ true = true and true,
+ false = true and false,
+ false = false and true,
+ false = false and false,
+
+ true = id(true) and true,
+ false = id(true) and false,
+ false = id(false) and true,
+ false = id(false) and false,
+
+ true = true and id(true),
+ false = true and id(false),
+ false = false and id(true),
+ false = false and id(false),
+
+ true = true or true,
+ true = true or false,
+ true = false or true,
+ false = false or false,
+
+ true = id(true) or true,
+ true = id(true) or false,
+ true = id(false) or true,
+ false = id(false) or false,
+
+ true = true or id(true),
+ true = true or id(false),
+ true = false or id(true),
+ false = false or id(false),
True = id(true),
@@ -187,28 +187,28 @@ t_andalso(Config) when is_list(Config) ->
Ps = [{X,Y} || X <- Bs, Y <- Bs],
lists:foreach(fun (P) -> t_andalso_1(P) end, Ps),
- ?line true = true andalso true,
- ?line false = true andalso false,
- ?line false = false andalso true,
- ?line false = false andalso false,
+ true = true andalso true,
+ false = true andalso false,
+ false = false andalso true,
+ false = false andalso false,
- ?line true = ?GUARD(true andalso true),
- ?line false = ?GUARD(true andalso false),
- ?line false = ?GUARD(false andalso true),
- ?line false = ?GUARD(false andalso false),
+ true = ?GUARD(true andalso true),
+ false = ?GUARD(true andalso false),
+ false = ?GUARD(false andalso true),
+ false = ?GUARD(false andalso false),
- ?line false = false andalso glurf,
- ?line false = false andalso exit(exit_now),
+ false = false andalso glurf,
+ false = false andalso exit(exit_now),
- ?line true = not id(false) andalso not id(false),
- ?line false = not id(false) andalso not id(true),
- ?line false = not id(true) andalso not id(false),
- ?line false = not id(true) andalso not id(true),
+ true = not id(false) andalso not id(false),
+ false = not id(false) andalso not id(true),
+ false = not id(true) andalso not id(false),
+ false = not id(true) andalso not id(true),
- ?line {'EXIT',{badarg,_}} = (catch not id(glurf) andalso id(true)),
- ?line {'EXIT',{badarg,_}} = (catch not id(false) andalso not id(glurf)),
- ?line false = id(false) andalso not id(glurf),
- ?line false = false andalso not id(glurf),
+ {'EXIT',{badarg,_}} = (catch not id(glurf) andalso id(true)),
+ {'EXIT',{badarg,_}} = (catch not id(false) andalso not id(glurf)),
+ false = id(false) andalso not id(glurf),
+ false = false andalso not id(glurf),
true = begin (X1 = true) andalso X1, X1 end,
false = false = begin (X2 = false) andalso X2, X2 end,
@@ -220,28 +220,28 @@ t_orelse(Config) when is_list(Config) ->
Ps = [{X,Y} || X <- Bs, Y <- Bs],
lists:foreach(fun (P) -> t_orelse_1(P) end, Ps),
- ?line true = true orelse true,
- ?line true = true orelse false,
- ?line true = false orelse true,
- ?line false = false orelse false,
+ true = true orelse true,
+ true = true orelse false,
+ true = false orelse true,
+ false = false orelse false,
- ?line true = ?GUARD(true orelse true),
- ?line true = ?GUARD(true orelse false),
- ?line true = ?GUARD(false orelse true),
- ?line false = ?GUARD(false orelse false),
+ true = ?GUARD(true orelse true),
+ true = ?GUARD(true orelse false),
+ true = ?GUARD(false orelse true),
+ false = ?GUARD(false orelse false),
- ?line true = true orelse glurf,
- ?line true = true orelse exit(exit_now),
+ true = true orelse glurf,
+ true = true orelse exit(exit_now),
- ?line true = not id(false) orelse not id(false),
- ?line true = not id(false) orelse not id(true),
- ?line true = not id(true) orelse not id(false),
- ?line false = not id(true) orelse not id(true),
+ true = not id(false) orelse not id(false),
+ true = not id(false) orelse not id(true),
+ true = not id(true) orelse not id(false),
+ false = not id(true) orelse not id(true),
- ?line {'EXIT',{badarg,_}} = (catch not id(glurf) orelse id(true)),
- ?line {'EXIT',{badarg,_}} = (catch not id(true) orelse not id(glurf)),
- ?line true = id(true) orelse not id(glurf),
- ?line true = true orelse not id(glurf),
+ {'EXIT',{badarg,_}} = (catch not id(glurf) orelse id(true)),
+ {'EXIT',{badarg,_}} = (catch not id(true) orelse not id(glurf)),
+ true = id(true) orelse not id(glurf),
+ true = true orelse not id(glurf),
true = begin (X1 = true) orelse X1, X1 end,
false = begin (X2 = false) orelse X2, X2 end,
@@ -255,7 +255,7 @@ t_andalso_1({X,Y}) ->
X andalso Y -> true;
true -> false
end,
- check(V1, X and Y).
+ V1 = id(X and Y).
t_orelse_1({X,Y}) ->
io:fwrite("~w orelse ~w: ",[X,Y]),
@@ -264,19 +264,19 @@ t_orelse_1({X,Y}) ->
X orelse Y -> true;
true -> false
end,
- check(V1, X or Y).
+ V1 = id(X or Y).
inside(Config) when is_list(Config) ->
- ?line true = inside(-8, 1),
- ?line false = inside(-53.5, -879798),
- ?line false = inside(1.0, -879),
- ?line false = inside(59, -879),
- ?line false = inside(-11, 1.0),
- ?line false = inside(100, 0.2),
- ?line false = inside(100, 1.2),
- ?line false = inside(-53.5, 4),
- ?line false = inside(1.0, 5.3),
- ?line false = inside(59, 879),
+ true = inside(-8, 1),
+ false = inside(-53.5, -879798),
+ false = inside(1.0, -879),
+ false = inside(59, -879),
+ false = inside(-11, 1.0),
+ false = inside(100, 0.2),
+ false = inside(100, 1.2),
+ false = inside(-53.5, 4),
+ false = inside(1.0, 5.3),
+ false = inside(59, 879),
ok.
inside(Xm, Ym) ->
@@ -311,15 +311,15 @@ inside_guard(Xm, Ym, X, Y, W, H) ->
{false,Xm,Ym,X,Y,W,H}.
overlap(Config) when is_list(Config) ->
- ?line true = overlap(7.0, 2.0, 8.0, 0.5),
- ?line true = overlap(7.0, 2.0, 8.0, 2.5),
- ?line true = overlap(7.0, 2.0, 5.3, 2),
- ?line true = overlap(7.0, 2.0, 0.0, 100.0),
-
- ?line false = overlap(-1, 2, -35, 0.5),
- ?line false = overlap(-1, 2, 777, 0.5),
- ?line false = overlap(-1, 2, 2, 10),
- ?line false = overlap(2, 10, 12, 55.3),
+ true = overlap(7.0, 2.0, 8.0, 0.5),
+ true = overlap(7.0, 2.0, 8.0, 2.5),
+ true = overlap(7.0, 2.0, 5.3, 2),
+ true = overlap(7.0, 2.0, 0.0, 100.0),
+
+ false = overlap(-1, 2, -35, 0.5),
+ false = overlap(-1, 2, 777, 0.5),
+ false = overlap(-1, 2, 2, 10),
+ false = overlap(2, 10, 12, 55.3),
ok.
overlap(Pos1, Len1, Pos2, Len2) ->
@@ -343,33 +343,33 @@ overlap(Pos1, Len1, Pos2, Len2) ->
-define(COMB(A,B,C), (A andalso B orelse C)).
combined(Config) when is_list(Config) ->
- ?line false = comb(false, false, false),
- ?line true = comb(false, false, true),
- ?line false = comb(false, true, false),
- ?line true = comb(false, true, true),
-
- ?line false = comb(true, false, false),
- ?line true = comb(true, true, false),
- ?line true = comb(true, false, true),
- ?line true = comb(true, true, true),
-
- ?line false = comb(false, blurf, false),
- ?line true = comb(false, blurf, true),
- ?line true = comb(true, true, blurf),
-
- ?line false = ?COMB(false, false, false),
- ?line true = ?COMB(false, false, true),
- ?line false = ?COMB(false, true, false),
- ?line true = ?COMB(false, true, true),
-
- ?line false = ?COMB(true, false, false),
- ?line true = ?COMB(true, true, false),
- ?line true = ?COMB(true, false, true),
- ?line true = ?COMB(true, true, true),
-
- ?line false = ?COMB(false, blurf, false),
- ?line true = ?COMB(false, blurf, true),
- ?line true = ?COMB(true, true, blurf),
+ false = comb(false, false, false),
+ true = comb(false, false, true),
+ false = comb(false, true, false),
+ true = comb(false, true, true),
+
+ false = comb(true, false, false),
+ true = comb(true, true, false),
+ true = comb(true, false, true),
+ true = comb(true, true, true),
+
+ false = comb(false, blurf, false),
+ true = comb(false, blurf, true),
+ true = comb(true, true, blurf),
+
+ false = ?COMB(false, false, false),
+ true = ?COMB(false, false, true),
+ false = ?COMB(false, true, false),
+ true = ?COMB(false, true, true),
+
+ false = ?COMB(true, false, false),
+ true = ?COMB(true, true, false),
+ true = ?COMB(true, false, true),
+ true = ?COMB(true, true, true),
+
+ false = ?COMB(false, blurf, false),
+ true = ?COMB(false, blurf, true),
+ true = ?COMB(true, true, blurf),
false = simple_comb(false, false),
false = simple_comb(false, true),
@@ -412,13 +412,13 @@ simple_comb(A, B) ->
%% Test that a boolean expression in a case expression is properly
%% optimized (in particular, that the error behaviour is correct).
in_case(Config) when is_list(Config) ->
- ?line edge_rings = in_case_1(1, 1, 1, 1, 1),
- ?line not_loop = in_case_1(0.5, 1, 1, 1, 1),
- ?line loop = in_case_1(0.5, 0.9, 1.1, 1, 4),
- ?line {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, 0)),
- ?line {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, nan)),
- ?line {'EXIT',{badarg,_}} = (catch in_case_1(1, 1, 1, blurf, 1)),
- ?line {'EXIT',{badarith,_}} = (catch in_case_1([nan], 1, 1, 1, 1)),
+ edge_rings = in_case_1(1, 1, 1, 1, 1),
+ not_loop = in_case_1(0.5, 1, 1, 1, 1),
+ loop = in_case_1(0.5, 0.9, 1.1, 1, 4),
+ {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, 0)),
+ {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, nan)),
+ {'EXIT',{badarg,_}} = (catch in_case_1(1, 1, 1, blurf, 1)),
+ {'EXIT',{badarith,_}} = (catch in_case_1([nan], 1, 1, 1, 1)),
ok.
in_case_1(LenUp, LenDw, LenN, Rotation, Count) ->
@@ -451,23 +451,23 @@ in_case_1_guard(LenUp, LenDw, LenN, Rotation, Count) ->
end.
before_and_inside_if(Config) when is_list(Config) ->
- ?line no = before_and_inside_if([a], [b], delete),
- ?line no = before_and_inside_if([a], [b], x),
- ?line no = before_and_inside_if([a], [], delete),
- ?line no = before_and_inside_if([a], [], x),
- ?line no = before_and_inside_if([], [], delete),
- ?line yes = before_and_inside_if([], [], x),
- ?line yes = before_and_inside_if([], [b], delete),
- ?line yes = before_and_inside_if([], [b], x),
-
- ?line {ch1,ch2} = before_and_inside_if_2([a], [b], blah),
- ?line {ch1,ch2} = before_and_inside_if_2([a], [b], xx),
- ?line {ch1,ch2} = before_and_inside_if_2([a], [], blah),
- ?line {ch1,ch2} = before_and_inside_if_2([a], [], xx),
- ?line {no,no} = before_and_inside_if_2([], [b], blah),
- ?line {no,no} = before_and_inside_if_2([], [b], xx),
- ?line {ch1,no} = before_and_inside_if_2([], [], blah),
- ?line {no,ch2} = before_and_inside_if_2([], [], xx),
+ no = before_and_inside_if([a], [b], delete),
+ no = before_and_inside_if([a], [b], x),
+ no = before_and_inside_if([a], [], delete),
+ no = before_and_inside_if([a], [], x),
+ no = before_and_inside_if([], [], delete),
+ yes = before_and_inside_if([], [], x),
+ yes = before_and_inside_if([], [b], delete),
+ yes = before_and_inside_if([], [b], x),
+
+ {ch1,ch2} = before_and_inside_if_2([a], [b], blah),
+ {ch1,ch2} = before_and_inside_if_2([a], [b], xx),
+ {ch1,ch2} = before_and_inside_if_2([a], [], blah),
+ {ch1,ch2} = before_and_inside_if_2([a], [], xx),
+ {no,no} = before_and_inside_if_2([], [b], blah),
+ {no,no} = before_and_inside_if_2([], [b], xx),
+ {ch1,no} = before_and_inside_if_2([], [], blah),
+ {no,ch2} = before_and_inside_if_2([], [], xx),
ok.
%% Thanks to Simon Cornish and Kostis Sagonas.
@@ -539,14 +539,6 @@ slow_compilation_1(T, _) when element(1, T) == a ->
%% Utilities.
-check(V1, V0) ->
- if V1 /= V0 ->
- io:fwrite("error: ~w.\n", [V1]),
- ?t:fail();
- true ->
- io:fwrite("ok: ~w.\n", [V1])
- end.
-
echo(X) ->
io:fwrite("eval(~w); ",[X]),
X.
diff --git a/lib/compiler/test/apply_SUITE.erl b/lib/compiler/test/apply_SUITE.erl
index 3425553fed..8abcfe9dac 100644
--- a/lib/compiler/test/apply_SUITE.erl
+++ b/lib/compiler/test/apply_SUITE.erl
@@ -24,7 +24,7 @@
-export([foo/0,bar/1,baz/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -53,44 +53,44 @@ end_per_group(_GroupName, Config) ->
-define(APPLY2(M, F, A1, A2), (fun(Res) -> Res = M:F(A1, A2) end)(apply(M, F, [A1,A2]))).
mfa(Config) when is_list(Config) ->
- ?line ok = ?APPLY0(?MODULE, foo),
- ?line {[a,b]} = ?APPLY1(?MODULE, bar, [a,b]),
- ?line {39,{a}} = ?APPLY2(?MODULE, baz, 39, {a}),
-
- ?line Mod = id(?MODULE),
- ?line ok = ?APPLY0(Mod, foo),
- ?line {[a,b]} = ?APPLY1(Mod, bar, [a,b]),
- ?line {39,{a}} = ?APPLY2(Mod, baz, 39, {a}),
-
- ?line ok = ?APPLY0(?MODULE, (id(foo))),
- ?line {[a,b]} = ?APPLY1(?MODULE, (id(bar)), [a,b]),
- ?line {39,{a}} = ?APPLY2(?MODULE, (id(baz)), 39, {a}),
-
- ?line ok = ?APPLY0(Mod, (id(foo))),
- ?line {[a,b]} = ?APPLY1(Mod, (id(bar)), [a,b]),
- ?line {39,{a}} = ?APPLY2(Mod, (id(baz)), 39, {a}),
-
- ?line {'EXIT',_} = (catch ?APPLY2(Mod, (id(bazzzzzz)), a, b)),
- ?line {'EXIT',_} = (catch ?APPLY2({}, baz, a, b)),
- ?line {'EXIT',_} = (catch ?APPLY2(?MODULE, [], a, b)),
-
- ?line ok = apply(Mod, foo, id([])),
- ?line {[a,b|c]} = apply(Mod, bar, id([[a,b|c]])),
- ?line {[xx],{a}} = apply(?MODULE, baz, id([[xx],{a}])),
-
- ?line Erlang = id(erlang),
- ?line Self = self(),
- ?line Self = ?APPLY0(Erlang, self),
- ?line 42.0 = ?APPLY1(Erlang, abs, -42.0),
- ?line b = ?APPLY2(Erlang, element, 2, {a,b,c}),
- ?line true = ?APPLY1(Erlang, is_function, fun erlang:list_to_binary/1),
- ?line true = ?APPLY1(Erlang, is_function, fun() -> ok end),
- ?line false = ?APPLY1(Erlang, is_function, blurf),
- ?line true = ?APPLY2(Erlang, is_function, fun erlang:list_to_binary/1, 1),
- ?line true = ?APPLY2(Erlang, is_function, fun() -> ok end, 0),
- ?line false = ?APPLY2(Erlang, is_function, blurf, 0),
-
- ?line apply(Mod, foo, []).
+ ok = ?APPLY0(?MODULE, foo),
+ {[a,b]} = ?APPLY1(?MODULE, bar, [a,b]),
+ {39,{a}} = ?APPLY2(?MODULE, baz, 39, {a}),
+
+ Mod = id(?MODULE),
+ ok = ?APPLY0(Mod, foo),
+ {[a,b]} = ?APPLY1(Mod, bar, [a,b]),
+ {39,{a}} = ?APPLY2(Mod, baz, 39, {a}),
+
+ ok = ?APPLY0(?MODULE, (id(foo))),
+ {[a,b]} = ?APPLY1(?MODULE, (id(bar)), [a,b]),
+ {39,{a}} = ?APPLY2(?MODULE, (id(baz)), 39, {a}),
+
+ ok = ?APPLY0(Mod, (id(foo))),
+ {[a,b]} = ?APPLY1(Mod, (id(bar)), [a,b]),
+ {39,{a}} = ?APPLY2(Mod, (id(baz)), 39, {a}),
+
+ {'EXIT',_} = (catch ?APPLY2(Mod, (id(bazzzzzz)), a, b)),
+ {'EXIT',_} = (catch ?APPLY2({}, baz, a, b)),
+ {'EXIT',_} = (catch ?APPLY2(?MODULE, [], a, b)),
+
+ ok = apply(Mod, foo, id([])),
+ {[a,b|c]} = apply(Mod, bar, id([[a,b|c]])),
+ {[xx],{a}} = apply(?MODULE, baz, id([[xx],{a}])),
+
+ Erlang = id(erlang),
+ Self = self(),
+ Self = ?APPLY0(Erlang, self),
+ 42.0 = ?APPLY1(Erlang, abs, -42.0),
+ b = ?APPLY2(Erlang, element, 2, {a,b,c}),
+ true = ?APPLY1(Erlang, is_function, fun erlang:list_to_binary/1),
+ true = ?APPLY1(Erlang, is_function, fun() -> ok end),
+ false = ?APPLY1(Erlang, is_function, blurf),
+ true = ?APPLY2(Erlang, is_function, fun erlang:list_to_binary/1, 1),
+ true = ?APPLY2(Erlang, is_function, fun() -> ok end, 0),
+ false = ?APPLY2(Erlang, is_function, blurf, 0),
+
+ apply(Mod, foo, []).
foo() ->
ok.
@@ -106,21 +106,21 @@ baz(A, B) ->
-define(FUNAPPLY2(F, A1, A2), (fun(Res) -> Res = F(A1, A2) end)(apply(F, [A1,A2]))).
fun_apply(Config) when is_list(Config) ->
- ?line Self = self(),
+ Self = self(),
- ?line Self = ?FUNAPPLY0(fun() -> self() end),
- ?line Self = ?FUNAPPLY0((id(fun() -> self() end))),
- ?line ok = ?FUNAPPLY0(fun ?MODULE:foo/0),
- ?line ok = ?FUNAPPLY0((id(fun ?MODULE:foo/0))),
+ Self = ?FUNAPPLY0(fun() -> self() end),
+ Self = ?FUNAPPLY0((id(fun() -> self() end))),
+ ok = ?FUNAPPLY0(fun ?MODULE:foo/0),
+ ok = ?FUNAPPLY0((id(fun ?MODULE:foo/0))),
- ?line -42 = ?FUNAPPLY1(fun(A) -> -A end, 42),
- ?line [x,yy] = ?FUNAPPLY1((id(fun(T) -> [x|T] end)), [yy]),
- ?line {[a|b]} = ?FUNAPPLY1(fun ?MODULE:bar/1, [a|b]),
- ?line {[a|b]} = ?FUNAPPLY1((id(fun ?MODULE:bar/1)), [a|b]),
+ -42 = ?FUNAPPLY1(fun(A) -> -A end, 42),
+ [x,yy] = ?FUNAPPLY1((id(fun(T) -> [x|T] end)), [yy]),
+ {[a|b]} = ?FUNAPPLY1(fun ?MODULE:bar/1, [a|b]),
+ {[a|b]} = ?FUNAPPLY1((id(fun ?MODULE:bar/1)), [a|b]),
- ?line {a,b} = ?FUNAPPLY2(fun(A, B) -> {A,B} end, a, b),
- ?line {a,[b]} = ?FUNAPPLY2((id(fun(A, B) -> {A,B} end)), a, [b]),
- ?line {42,{a}} = ?FUNAPPLY2((id(fun ?MODULE:baz/2)), 42, {a}),
+ {a,b} = ?FUNAPPLY2(fun(A, B) -> {A,B} end, a, b),
+ {a,[b]} = ?FUNAPPLY2((id(fun(A, B) -> {A,B} end)), a, [b]),
+ {42,{a}} = ?FUNAPPLY2((id(fun ?MODULE:baz/2)), 42, {a}),
ok.
diff --git a/lib/compiler/test/beam_block_SUITE.erl b/lib/compiler/test/beam_block_SUITE.erl
new file mode 100644
index 0000000000..7b6f2066be
--- /dev/null
+++ b/lib/compiler/test/beam_block_SUITE.erl
@@ -0,0 +1,66 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(beam_block_SUITE).
+
+-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
+ init_per_group/2,end_per_group/2,
+ get_map_elements/1]).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ test_lib:recompile(?MODULE),
+ [{group,p}].
+
+groups() ->
+ [{p,[parallel],
+ [get_map_elements
+ ]}].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+get_map_elements(_Config) ->
+ [{pred,var}] = get_map_elements([{pred,var}], #{}, []),
+ [{pred,var}] = get_map_elements([{pred,var}], #{pred=>[]}, []),
+ acc = get_map_elements([], #{pred=>[]}, acc),
+ ok.
+
+get_map_elements([{Pred,Var}|Left], Map, Acc) ->
+ case Map of
+ #{Var := List} ->
+ case lists:keyfind(Pred, 1, List) of
+ false ->
+ get_map_elements(Left, Map, [{Pred,Var}|Acc])
+ end;
+ #{} ->
+ get_map_elements(Left, Map, [{Pred,Var}|Acc])
+ end;
+get_map_elements([], _Map, Acc) ->
+ Acc.
diff --git a/lib/compiler/test/beam_disasm_SUITE.erl b/lib/compiler/test/beam_disasm_SUITE.erl
index 4dd92e7ed9..90598d9639 100644
--- a/lib/compiler/test/beam_disasm_SUITE.erl
+++ b/lib/compiler/test/beam_disasm_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(beam_disasm_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
@@ -46,21 +46,20 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-stripped(doc) ->
- ["Check that stripped beam files can be disassembled"];
+%% Check that stripped beam files can be disassembled.
stripped(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line SrcName = filename:join(PrivDir, "tmp.erl"),
- ?line BeamName = filename:join(PrivDir, "tmp.beam"),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ SrcName = filename:join(PrivDir, "tmp.erl"),
+ BeamName = filename:join(PrivDir, "tmp.beam"),
Prog = <<"-module(tmp).\n-export([tmp/0]).\ntmp()->ok.\n">>,
- ?line ok = file:write_file(SrcName, Prog),
- ?line {ok, tmp} =
+ ok = file:write_file(SrcName, Prog),
+ {ok, tmp} =
compile:file(SrcName, [{outdir, PrivDir}]),
- ?line {beam_file, tmp, _, Attr, CompileInfo, [_|_]} =
+ {beam_file, tmp, _, Attr, CompileInfo, [_|_]} =
beam_disasm:file(BeamName),
- ?line true = is_list(Attr),
- ?line true = is_list(CompileInfo),
- ?line {ok, {tmp, _}} = beam_lib:strip(BeamName),
- ?line {beam_file, tmp, _, [], [], [_|_]} =
+ true = is_list(Attr),
+ true = is_list(CompileInfo),
+ {ok, {tmp, _}} = beam_lib:strip(BeamName),
+ {beam_file, tmp, _, [], [], [_|_]} =
beam_disasm:file(BeamName),
ok.
diff --git a/lib/compiler/test/beam_reorder_SUITE.erl b/lib/compiler/test/beam_reorder_SUITE.erl
new file mode 100644
index 0000000000..4b2262f65b
--- /dev/null
+++ b/lib/compiler/test/beam_reorder_SUITE.erl
@@ -0,0 +1,69 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(beam_reorder_SUITE).
+
+-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
+ init_per_group/2,end_per_group/2,
+ alloc/1]).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ test_lib:recompile(?MODULE),
+ [{group,p}].
+
+groups() ->
+ [{p,[parallel],
+ [alloc
+ ]}].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+-record(alloc, {version}).
+
+alloc(_Config) ->
+ {ok,42} = alloc_a(1, 2, #alloc{version=42}),
+ {a,b,c} = alloc_b(1, 2, #alloc{version={a,b,c}}),
+ ok.
+
+alloc_a(_U1, _U2, R) ->
+ V = R#alloc.version,
+ Res = id({ok,V}),
+ _ = id(0),
+ Res.
+
+alloc_b(_U1, _U2, R) ->
+ V = R#alloc.version,
+ Res = id(V),
+ _ = id(0),
+ Res.
+
+id(I) ->
+ I.
diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl
new file mode 100644
index 0000000000..8d5c0190ed
--- /dev/null
+++ b/lib/compiler/test/beam_type_SUITE.erl
@@ -0,0 +1,98 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(beam_type_SUITE).
+
+-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]).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ test_lib:recompile(?MODULE),
+ [{group,p}].
+
+groups() ->
+ [{p,[parallel],
+ [integers,
+ coverage,
+ booleans
+ ]}].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+integers(_Config) ->
+ a = do_integers_1(2#11000),
+ b = do_integers_1(2#11001),
+
+ a = do_integers_2(<<0:1>>),
+ {'EXIT',{{case_clause,-1},_}} = (catch do_integers_2(<<1:1>>)),
+
+ ok.
+
+do_integers_1(B0) ->
+ B = B0 band 1,
+ case B band 15 of
+ 0 -> a;
+ 1 -> b
+ end.
+
+do_integers_2(Bin) ->
+ <<B:1/signed>> = Bin,
+ case B of
+ 0 -> a;
+ 1 -> b
+ end.
+
+coverage(_Config) ->
+ {'EXIT',{badarith,_}} = (catch id(1) bsl 0.5),
+ {'EXIT',{badarith,_}} = (catch id(2.0) bsl 2),
+ {'EXIT',{badarith,_}} = (catch a + 0.5),
+ {'EXIT',{badarith,_}} = (catch 2.0 * b),
+
+ {'EXIT',{badarith,_}} = (catch id(42.0) / (1 bsl 2000)),
+
+ id(id(42) band 387439739874298734983787934283479243879),
+ id(-1 band id(13)),
+
+ ok.
+
+booleans(_Config) ->
+ {'EXIT',{{case_clause,_},_}} = (catch do_booleans(42)),
+ ok.
+
+do_booleans(B) ->
+ case is_integer(B) of
+ yes -> yes;
+ no -> no
+ end.
+
+id(I) ->
+ I.
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl
index 69391b15eb..d27512b6eb 100644
--- a/lib/compiler/test/beam_validator_SUITE.erl
+++ b/lib/compiler/test/beam_validator_SUITE.erl
@@ -34,18 +34,17 @@
undef_label/1,illegal_instruction/1,failing_gc_guard_bif/1,
map_field_lists/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog = test_server:timetrap(?t:minutes(10)),
- [{watchdog,Dog}|Config].
+ Config.
end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,10}}].
all() ->
test_lib:recompile(?MODULE),
@@ -78,7 +77,7 @@ end_per_group(_GroupName, Config) ->
compiler_bug(Config) when is_list(Config) ->
%% Check that the compiler returns an error if we try to
%% assemble one of the bad '.S' files.
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
File = filename:join(Data, "compiler_bug"),
error = compile:file(File, [from_asm,report_errors,time]),
@@ -93,43 +92,41 @@ compiler_bug(Config) when is_list(Config) ->
%% The following code is stupid but it should compile.
stupid_but_valid(Config) when is_list(Config) ->
AnAtom = nisse,
- ?line try setelement(5, setelement(6, AnAtom, value), another_value) of
- Term -> ?line ?t:fail({what_happened,Term})
- catch
- error:badarg -> ok
- end,
+ try setelement(5, setelement(6, AnAtom, value), another_value) of
+ Term -> ct:fail({what_happened,Term})
+ catch
+ error:badarg -> ok
+ end,
ok.
xrange(Config) when is_list(Config) ->
Errors = do_val(xrange, Config),
- ?line
- [{{t,sum_1,2},
- {{bif,'+',{f,0},[{x,-1},{x,1}],{x,0}},4,
- {uninitialized_reg,{x,-1}}}},
- {{t,sum_2,2},
- {{bif,'+',{f,0},[{x,0},{x,1024}],{x,0}},4,
- {uninitialized_reg,{x,1024}}}},
- {{t,sum_3,2},
- {{bif,'+',{f,0},[{x,0},{x,1}],{x,-1}},4,
- {invalid_store,{x,-1},number}}},
- {{t,sum_4,2},
- {{bif,'+',{f,0},[{x,0},{x,1}],{x,1024}},4,limit}}] = Errors,
+ [{{t,sum_1,2},
+ {{bif,'+',{f,0},[{x,-1},{x,1}],{x,0}},4,
+ {uninitialized_reg,{x,-1}}}},
+ {{t,sum_2,2},
+ {{bif,'+',{f,0},[{x,0},{x,1023}],{x,0}},4,
+ {uninitialized_reg,{x,1023}}}},
+ {{t,sum_3,2},
+ {{bif,'+',{f,0},[{x,0},{x,1}],{x,-1}},4,
+ {invalid_store,{x,-1},number}}},
+ {{t,sum_4,2},
+ {{bif,'+',{f,0},[{x,0},{x,1}],{x,1023}},4,limit}}] = Errors,
ok.
yrange(Config) when is_list(Config) ->
Errors = do_val(yrange, Config),
- ?line
- [{{t,sum_1,2},
- {{move,{x,1},{y,-1}},5,
- {invalid_store,{y,-1},term}}},
- {{t,sum_2,2},
- {{bif,'+',{f,0},[{x,0},{y,1024}],{x,0}},7,
- {uninitialized_reg,{y,1024}}}},
- {{t,sum_3,2},
- {{move,{x,1},{y,1024}},5,limit}},
- {{t,sum_4,2},
- {{move,{x,1},{y,-1}},5,
- {invalid_store,{y,-1},term}}}] = Errors,
+ [{{t,sum_1,2},
+ {{move,{x,1},{y,-1}},5,
+ {invalid_store,{y,-1},term}}},
+ {{t,sum_2,2},
+ {{bif,'+',{f,0},[{x,0},{y,1024}],{x,0}},7,
+ {uninitialized_reg,{y,1024}}}},
+ {{t,sum_3,2},
+ {{move,{x,1},{y,1024}},5,limit}},
+ {{t,sum_4,2},
+ {{move,{x,1},{y,-1}},5,
+ {invalid_store,{y,-1},term}}}] = Errors,
ok.
stack(Config) when is_list(Config) ->
@@ -163,25 +160,23 @@ merge_undefined(Config) when is_list(Config) ->
uninit(Config) when is_list(Config) ->
Errors = do_val(uninit, Config),
- ?line
- [{{t,sum_1,2},
- {{move,{y,0},{x,0}},5,{uninitialized_reg,{y,0}}}},
- {{t,sum_2,2},
- {{call,1,{f,8}},5,{uninitialized_reg,{y,0}}}},
- {{t,sum_3,2},
- {{bif,'+',{f,0},[{x,0},{y,0}],{x,0}},
- 6,
- {unassigned,{y,0}}}}] = Errors,
+ [{{t,sum_1,2},
+ {{move,{y,0},{x,0}},5,{uninitialized_reg,{y,0}}}},
+ {{t,sum_2,2},
+ {{call,1,{f,8}},5,{uninitialized_reg,{y,0}}}},
+ {{t,sum_3,2},
+ {{bif,'+',{f,0},[{x,0},{y,0}],{x,0}},
+ 6,
+ {unassigned,{y,0}}}}] = Errors,
ok.
unsafe_catch(Config) when is_list(Config) ->
Errors = do_val(unsafe_catch, Config),
- ?line
- [{{t,small,2},
- {{bs_put_integer,{f,0},{integer,16},1,
- {field_flags,[unsigned,big]},{y,0}},
- 20,
- {unassigned,{y,0}}}}] = Errors,
+ [{{t,small,2},
+ {{bs_put_integer,{f,0},{integer,16},1,
+ {field_flags,[unsigned,big]},{y,0}},
+ 20,
+ {unassigned,{y,0}}}}] = Errors,
ok.
dead_code(Config) when is_list(Config) ->
@@ -190,16 +185,14 @@ dead_code(Config) when is_list(Config) ->
overwrite_catchtag(Config) when is_list(Config) ->
Errors = do_val(overwrite_catchtag, Config),
- ?line
- [{{overwrite_catchtag,foo,1},
- {{move,{x,0},{y,0}},6,{catchtag,_}}}] = Errors,
+ [{{overwrite_catchtag,foo,1},
+ {{move,{x,0},{y,0}},6,{catchtag,_}}}] = Errors,
ok.
overwrite_trytag(Config) when is_list(Config) ->
Errors = do_val(overwrite_trytag, Config),
- ?line
- [{{overwrite_trytag,foo,1},
- {{kill,{y,2}},8,{trytag,_}}}] = Errors,
+ [{{overwrite_trytag,foo,1},
+ {{kill,{y,2}},8,{trytag,_}}}] = Errors,
ok.
accessing_tags(Config) when is_list(Config) ->
@@ -231,82 +224,77 @@ bad_catch_try(Config) when is_list(Config) ->
cons_guard(Config) when is_list(Config) ->
Errors = do_val(cons, Config),
- ?line
- [{{cons,foo,1},
- {{get_list,{x,0},{x,1},{x,2}},
- 5,
- {bad_type,{needed,cons},{actual,term}}}}] = Errors,
+ [{{cons,foo,1},
+ {{get_list,{x,0},{x,1},{x,2}},
+ 5,
+ {bad_type,{needed,cons},{actual,term}}}}] = Errors,
ok.
freg_range(Config) when is_list(Config) ->
Errors = do_val(freg_range, Config),
- ?line
- [{{t,sum_1,2},
- {{bif,fadd,{f,0},[{fr,-1},{fr,1}],{fr,0}},
- 5,
- {bad_source,{fr,-1}}}},
- {{t,sum_2,2},
- {{bif,fadd,{f,0},[{fr,0},{fr,1024}],{fr,0}},
- 6,
- {uninitialized_reg,{fr,1024}}}},
- {{t,sum_3,2},
- {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,-1}},
- 7,
- {bad_target,{fr,-1}}}},
- {{t,sum_4,2},
- {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,1024}},
- 7,
- limit}}] = Errors,
+ [{{t,sum_1,2},
+ {{bif,fadd,{f,0},[{fr,-1},{fr,1}],{fr,0}},
+ 5,
+ {bad_source,{fr,-1}}}},
+ {{t,sum_2,2},
+ {{bif,fadd,{f,0},[{fr,0},{fr,1024}],{fr,0}},
+ 6,
+ {uninitialized_reg,{fr,1024}}}},
+ {{t,sum_3,2},
+ {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,-1}},
+ 7,
+ {bad_target,{fr,-1}}}},
+ {{t,sum_4,2},
+ {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,1024}},
+ 7,
+ limit}}] = Errors,
ok.
freg_uninit(Config) when is_list(Config) ->
Errors = do_val(freg_uninit, Config),
- ?line
- [{{t,sum_1,2},
- {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}},
- 6,
- {uninitialized_reg,{fr,1}}}},
- {{t,sum_2,2},
- {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}},
- 9,
- {uninitialized_reg,{fr,0}}}}] = Errors,
+ [{{t,sum_1,2},
+ {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}},
+ 6,
+ {uninitialized_reg,{fr,1}}}},
+ {{t,sum_2,2},
+ {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}},
+ 9,
+ {uninitialized_reg,{fr,0}}}}] = Errors,
ok.
freg_state(Config) when is_list(Config) ->
Errors = do_val(freg_state, Config),
- ?line
- [{{t,sum_1,2},
- {{bif,fmul,{f,0},[{fr,0},{fr,1}],{fr,0}},
- 6,
- {bad_floating_point_state,undefined}}},
- {{t,sum_2,2},
- {{fmove,{fr,0},{x,0}},
- 8,
- {bad_floating_point_state,cleared}}},
- {{t,sum_3,2},
- {{bif,'-',{f,0},[{x,1},{x,0}],{x,1}},
- 8,
- {unsafe_instruction,{float_error_state,cleared}}}},
- {{t,sum_4,2},
- {{fcheckerror,{f,0}},
- 4,
- {bad_floating_point_state,undefined}}},
- {{t,sum_5,2},
- {fclearerror,5,{bad_floating_point_state,cleared}}}] = Errors,
+ [{{t,sum_1,2},
+ {{bif,fmul,{f,0},[{fr,0},{fr,1}],{fr,0}},
+ 6,
+ {bad_floating_point_state,undefined}}},
+ {{t,sum_2,2},
+ {{fmove,{fr,0},{x,0}},
+ 8,
+ {bad_floating_point_state,cleared}}},
+ {{t,sum_3,2},
+ {{bif,'-',{f,0},[{x,1},{x,0}],{x,1}},
+ 8,
+ {unsafe_instruction,{float_error_state,cleared}}}},
+ {{t,sum_4,2},
+ {{fcheckerror,{f,0}},
+ 4,
+ {bad_floating_point_state,undefined}}},
+ {{t,sum_5,2},
+ {fclearerror,5,{bad_floating_point_state,cleared}}}] = Errors,
ok.
bad_bin_match(Config) when is_list(Config) ->
- [{{t,t,1},{return,5,{match_context,{x,0}}}}] =
- do_val(bad_bin_match, Config),
- ok.
+ [{{t,t,1},{return,5,{match_context,{x,0}}}}] =
+ do_val(bad_bin_match, Config),
+ ok.
bad_dsetel(Config) when is_list(Config) ->
Errors = do_val(bad_dsetel, Config),
- ?line
- [{{t,t,1},
- {{set_tuple_element,{x,1},{x,0},1},
- 17,
- illegal_context_for_set_tuple_element}}] = Errors,
+ [{{t,t,1},
+ {{set_tuple_element,{x,1},{x,0},1},
+ 17,
+ illegal_context_for_set_tuple_element}}] = Errors,
ok.
state_after_fault_in_catch(Config) when is_list(Config) ->
@@ -382,9 +370,9 @@ illegal_instruction(Config) when is_list(Config) ->
%% (Thanks to Kiran Khaladkar.)
%%
failing_gc_guard_bif(Config) when is_list(Config) ->
- ?line ok = process_request(lists:seq(1, 36)),
- ?line error = process_request([]),
- ?line error = process_request(not_a_list),
+ ok = process_request(lists:seq(1, 36)),
+ error = process_request([]),
+ error = process_request(not_a_list),
ok.
process_request(ConfId) ->
@@ -421,7 +409,7 @@ map_field_lists(Config) ->
%%%-------------------------------------------------------------------------
do_val(Mod, Config) ->
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
Base = atom_to_list(Mod),
File = filename:join(Data, Base),
case compile:file(File, [from_asm,no_postopt,return_errors]) of
diff --git a/lib/compiler/test/beam_validator_SUITE_data/xrange.S b/lib/compiler/test/beam_validator_SUITE_data/xrange.S
index c6f20288f7..a76408dde3 100644
--- a/lib/compiler/test/beam_validator_SUITE_data/xrange.S
+++ b/lib/compiler/test/beam_validator_SUITE_data/xrange.S
@@ -20,7 +20,7 @@
{label,3}.
{func_info,{atom,t},{atom,sum_2},2}.
{label,4}.
- {bif,'+',{f,0},[{x,0},{x,1024}],{x,0}}.
+ {bif,'+',{f,0},[{x,0},{x,1023}],{x,0}}.
{'%live',1}.
return.
@@ -38,7 +38,7 @@
{label,7}.
{func_info,{atom,t},{atom,sum_4},2}.
{label,8}.
- {bif,'+',{f,0},[{x,0},{x,1}],{x,1024}}.
+ {bif,'+',{f,0},[{x,0},{x,1}],{x,1023}}.
{'%live',1}.
return.
diff --git a/lib/compiler/test/bs_bincomp_SUITE.erl b/lib/compiler/test/bs_bincomp_SUITE.erl
index 1bf4e9d4a7..5e5f6e2169 100644
--- a/lib/compiler/test/bs_bincomp_SUITE.erl
+++ b/lib/compiler/test/bs_bincomp_SUITE.erl
@@ -26,9 +26,9 @@
init_per_group/2,end_per_group/2,
byte_aligned/1,bit_aligned/1,extended_byte_aligned/1,
extended_bit_aligned/1,mixed/1,filters/1,trim_coverage/1,
- nomatch/1,sizes/1]).
+ nomatch/1,sizes/1,general_expressions/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -36,7 +36,7 @@ all() ->
test_lib:recompile(?MODULE),
[byte_aligned, bit_aligned, extended_byte_aligned,
extended_bit_aligned, mixed, filters, trim_coverage,
- nomatch, sizes].
+ nomatch, sizes, general_expressions].
groups() ->
[].
@@ -55,110 +55,114 @@ end_per_group(_GroupName, Config) ->
byte_aligned(Config) when is_list(Config) ->
cs_init(),
- ?line <<"abcdefg">> = cs(<< <<(X+32)>> || <<X>> <= <<"ABCDEFG">> >>),
+ <<"abcdefg">> = cs(<< <<(X+32)>> || <<X>> <= <<"ABCDEFG">> >>),
<<1:32/little,2:32/little,3:32/little,4:32/little>> =
cs(<< <<X:32/little>> || <<X:32>> <= <<1:32,2:32,3:32,4:32>> >>),
- ?line cs(<<1:32/little,2:32/little,3:32/little,4:32/little>> =
- << <<X:32/little>> || <<X:16>> <= <<1:16,2:16,3:16,4:16>> >>),
+ cs(<<1:32/little,2:32/little,3:32/little,4:32/little>> =
+ << <<X:32/little>> || <<X:16>> <= <<1:16,2:16,3:16,4:16>> >>),
cs_end().
bit_aligned(Config) when is_list(Config) ->
cs_init(),
- ?line <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> =
+ <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> =
cs(<< <<(X+32):7>> || <<X>> <= <<"ABCDEFG">> >>),
- ?line <<"ABCDEFG">> =
+ <<"ABCDEFG">> =
cs(<< <<(X-32)>> || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> >>),
- ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> =
+ <<1:31/little,2:31/little,3:31/little,4:31/little>> =
cs(<< <<X:31/little>> || <<X:31>> <= <<1:31,2:31,3:31,4:31>> >>),
- ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> =
+ <<1:31/little,2:31/little,3:31/little,4:31/little>> =
cs(<< <<X:31/little>> || <<X:15>> <= <<1:15,2:15,3:15,4:15>> >>),
cs_end().
extended_byte_aligned(Config) when is_list(Config) ->
cs_init(),
- ?line <<"abcdefg">> = cs(<< <<(X+32)>> || X <- "ABCDEFG" >>),
- ?line "abcdefg" = [(X+32) || <<X>> <= <<"ABCDEFG">>],
- ?line <<1:32/little,2:32/little,3:32/little,4:32/little>> =
+ <<"abcdefg">> = cs(<< <<(X+32)>> || X <- "ABCDEFG" >>),
+ "abcdefg" = [(X+32) || <<X>> <= <<"ABCDEFG">>],
+ <<1:32/little,2:32/little,3:32/little,4:32/little>> =
cs(<< <<X:32/little>> || X <- [1,2,3,4] >>),
- ?line [256,512,768,1024] =
+ [256,512,768,1024] =
[X || <<X:16/little>> <= <<1:16,2:16,3:16,4:16>>],
cs_end().
extended_bit_aligned(Config) when is_list(Config) ->
cs_init(),
- ?line <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> =
+ <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> =
cs(<< <<(X+32):7>> || X <- "ABCDEFG" >>),
- ?line "ABCDEFG" = [(X-32) || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>],
- ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> =
+ "ABCDEFG" = [(X-32) || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>],
+ <<1:31/little,2:31/little,3:31/little,4:31/little>> =
cs(<< <<X:31/little>> || X <- [1,2,3,4] >>),
- ?line [256,512,768,1024] =
+ [256,512,768,1024] =
[X || <<X:15/little>> <= <<1:15,2:15,3:15,4:15>>],
cs_end().
mixed(Config) when is_list(Config) ->
cs_init(),
- ?line <<2,3,3,4,4,5,5,6>> =
+ <<2,3,3,4,4,5,5,6>> =
cs(<< <<(X+Y)>> || <<X>> <= <<1,2,3,4>>, <<Y>> <= <<1,2>> >>),
- ?line <<2,3,3,4,4,5,5,6>> =
+ <<2,3,3,4,4,5,5,6>> =
<< <<(X+Y)>> || <<X>> <= <<1,2,3,4>>, Y <- [1,2] >>,
- ?line <<2,3,3,4,4,5,5,6>> =
+ <<2,3,3,4,4,5,5,6>> =
cs(<< <<(X+Y)>> || X <- [1,2,3,4], Y <- [1,2] >>),
One = id([1,2,3,4]),
Two = id([1,2]),
- ?line <<2,3,3,4,4,5,5,6>> =
+ <<2,3,3,4,4,5,5,6>> =
cs(<< <<(X+Y)>> || X <- One, Y <- Two >>),
- ?line [2,3,3,4,4,5,5,6] =
+ [2,3,3,4,4,5,5,6] =
[(X+Y) || <<X>> <= <<1,2,3,4>>, <<Y>> <= <<1,2>>],
- ?line [2,3,3,4,4,5,5,6] =
+ [2,3,3,4,4,5,5,6] =
[(X+Y) || <<X>> <= <<1,2,3,4>>, Y <- [1,2]],
- ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
+ <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
cs(<< <<(X+Y):3>> || <<X:3>> <= <<1:3,2:3,3:3,4:3>>,
<<Y:3>> <= <<1:3,2:3>> >>),
- ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
+ <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
cs(<< <<(X+Y):3>> || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, Y <- [1,2] >>),
- ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
+ <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
cs(<< <<(X+Y):3>> || X <- [1,2,3,4], Y <- [1,2] >>),
- ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
+ <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
cs_default(<< <<(X+Y):3>> || {X,Y} <- [{1,1},{1,2},{2,1},{2,2},
{3,1},{3,2},{4,1},{4,2}] >>),
- ?line [2,3,3,4,4,5,5,6] =
+ [2,3,3,4,4,5,5,6] =
[(X+Y) || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, <<Y:3>> <= <<1:3,2:3>>],
- ?line [2,3,3,4,4,5,5,6] =
+ [2,3,3,4,4,5,5,6] =
[(X+Y) || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, {_,Y} <- [{a,1},{b,2}]],
cs_end().
filters(Config) when is_list(Config) ->
cs_init(),
- ?line <<"BDF">> =
- cs_default(<< <<(X-32)>> || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>,
- X rem 2 == 0>>),
- ?line <<"abc">> = cs_default(<< <<(X+32)>> || X <- "ABCDEFG",
- is_less_than(X, $D)>>),
- ?line <<"efg">> = cs_default(<< <<(X+32)>> || X <- "ABCDEFG",
- not is_less_than(X, $E)>>),
- ?line <<"b">> = cs_default(<< <<(X+32)>> || X <- "ABCDEFG",
- is_less_than(X, $D),
- X rem 2 == 0>>),
- ?line <<"eg">> = cs_default(<< <<(X+32)>> || X <- "ABCDEFG",
- not is_less_than(X, $E),
- X rem 2 == 1>>),
+ <<"BDF">> =
+ cs_default(<< <<(X-32)>> ||
+ <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>,
+ X rem 2 == 0>>),
+ <<"abc">> = cs_default(<< <<(X+32)>> ||
+ X <- "ABCDEFG",
+ is_less_than(X, $D)>>),
+ <<"efg">> = cs_default(<< <<(X+32)>> ||
+ X <- "ABCDEFG",
+ not is_less_than(X, $E)>>),
+ <<"b">> = cs_default(<< <<(X+32)>> ||
+ X <- "ABCDEFG",
+ is_less_than(X, $D),
+ X rem 2 == 0>>),
+ <<"eg">> = cs_default(<< <<(X+32)>> ||
+ X <- "ABCDEFG",
+ not is_less_than(X, $E),
+ X rem 2 == 1>>),
%% Filtering by a non-matching pattern.
- ?line <<"abd">> = cs_default(<< <<X:8>> ||
- <<0:1,X:7>> <= <<$a:8,$b:8,1:1,$c:7,$d:8,
- 1:1,$e:7,0:4>> >>),
+ <<"abd">> = cs_default(<< <<X:8>> ||
+ <<0:1,X:7>> <= <<$a:8,$b:8,1:1,$c:7,$d:8,
+ 1:1,$e:7,0:4>> >>),
- ?line <<42,42>> = cs_default(<< <<42:8>> ||
- 42 <- [1,2,3,42,43,42] >>),
+ <<42,42>> = cs_default(<< <<42:8>> || 42 <- [1,2,3,42,43,42] >>),
cs_end().
is_less_than(X, C) when X < C -> true;
is_less_than(_, _) -> false.
trim_coverage(Config) when is_list(Config) ->
- ?line <<0,0,0,2,0,0,5,48,0,11,219,174,0,0,0,0>> = coverage_materialiv(a, b, {1328,777134}),
- ?line <<67,40,0,0,66,152,0,0,69,66,64,0>> = coverage_trimmer([42,19,777]),
- ?line <<0,0,2,43,0,0,3,9,0,0,0,3,64,8,0,0,0,0,0,0,
+ <<0,0,0,2,0,0,5,48,0,11,219,174,0,0,0,0>> = coverage_materialiv(a, b, {1328,777134}),
+ <<67,40,0,0,66,152,0,0,69,66,64,0>> = coverage_trimmer([42,19,777]),
+ <<0,0,2,43,0,0,3,9,0,0,0,3,64,8,0,0,0,0,0,0,
64,68,0,0,0,0,0,0,192,171,198,0,0,0,0,0>> =
coverage_lightfv(555, 777, {3.0,40.0,-3555.0}),
ok.
@@ -186,111 +190,153 @@ coverage_trimmer(Params) ->
coverage_summer(A, B, C, D) -> A+B+C+D.
nomatch(Config) when is_list(Config) ->
- ?line <<>> = << <<X:8>> || X = {_,_} = [_|_] <- [1,2,3] >>,
+ <<>> = << <<X:8>> || X = {_,_} = [_|_] <- [1,2,3] >>,
ok.
sizes(Config) when is_list(Config) ->
- ?line cs_init(),
+ cs_init(),
Fun0 = fun(List) ->
cs(<< <<E:8>> || E <- List >>)
end,
- ?line <<>> = Fun0([]),
- ?line <<1>> = Fun0([1]),
- ?line <<1,2>> = Fun0([1,2]),
- ?line <<1,2,3>> = Fun0([1,2,3]),
+ <<>> = Fun0([]),
+ <<1>> = Fun0([1]),
+ <<1,2>> = Fun0([1,2]),
+ <<1,2,3>> = Fun0([1,2,3]),
Fun1 = fun(List) ->
cs(<< <<E:16>> || E <- List >>)
end,
- ?line <<>> = Fun1([]),
- ?line <<1:16>> = Fun1([1]),
- ?line <<1:16,2:16>> = Fun1([1,2]),
- ?line <<1:16,2:16,3:16>> = Fun1([1,2,3]),
+ <<>> = Fun1([]),
+ <<1:16>> = Fun1([1]),
+ <<1:16,2:16>> = Fun1([1,2]),
+ <<1:16,2:16,3:16>> = Fun1([1,2,3]),
Fun2 = fun(List) ->
cs(<< <<E:4>> || E <- List >>)
end,
- ?line <<>> = Fun2([]),
- ?line <<1:4>> = Fun2([1]),
- ?line <<1:4,13:4>> = Fun2([1,13]),
- ?line <<1:4,13:4,7:4>> = Fun2([1,13,7]),
- ?line <<0:1000/unit:8>> = Fun2(lists:duplicate(2000, 0)),
+ <<>> = Fun2([]),
+ <<1:4>> = Fun2([1]),
+ <<1:4,13:4>> = Fun2([1,13]),
+ <<1:4,13:4,7:4>> = Fun2([1,13,7]),
+ <<0:1000/unit:8>> = Fun2(lists:duplicate(2000, 0)),
Fun3 = fun(List) ->
cs(<< <<E:3>> || E <- List >>)
end,
- ?line <<>> = Fun3([]),
- ?line <<40,177,29:5>> = Fun3([1,2,1,3,0,7,5]),
- ?line <<0:512/unit:3>> = Fun3(lists:duplicate(512, 0)),
+ <<>> = Fun3([]),
+ <<40,177,29:5>> = Fun3([1,2,1,3,0,7,5]),
+ <<0:512/unit:3>> = Fun3(lists:duplicate(512, 0)),
Fun4 = fun(List, Size) ->
cs(<< <<E:Size>> || E <- List >>)
end,
- ?line <<>> = Fun4([], 8),
- ?line <<42:6>> = Fun4([42], 6),
- ?line <<42:16>> = Fun4([42], 16),
+ <<>> = Fun4([], 8),
+ <<42:6>> = Fun4([42], 6),
+ <<42:16>> = Fun4([42], 16),
Fun5 = fun(List, Sz1, Sz2, Sz3) ->
cs(<< <<E:Sz1,(E+1):Sz2/unit:8,(E+2):Sz3/unit:8>> || E <- List >>)
end,
- ?line <<>> = Fun5([], 1, 1, 1),
- ?line <<7:3,8:40,9:56>> = Fun5([7], 3, 5, 7),
+ <<>> = Fun5([], 1, 1, 1),
+ <<7:3,8:40,9:56>> = Fun5([7], 3, 5, 7),
Fun6 = fun(List, Size) ->
cs(<< <<E:8,(E+1):Size>> || E <- List >>)
end,
- ?line <<>> = Fun6([], 42),
- ?line <<42,43:20>> = Fun6([42], 20),
+ <<>> = Fun6([], 42),
+ <<42,43:20>> = Fun6([42], 20),
%% Binary generators.
Fun10 = fun(Bin) ->
cs(<< <<E:16>> || <<E:8>> <= Bin >>)
end,
- ?line <<>> = Fun10(<<>>),
- ?line <<1:16>> = Fun10(<<1>>),
- ?line <<1:16,2:16>> = Fun10(<<1,2>>),
+ <<>> = Fun10(<<>>),
+ <<1:16>> = Fun10(<<1>>),
+ <<1:16,2:16>> = Fun10(<<1,2>>),
Fun11 = fun(Bin) ->
cs(<< <<E:8>> || <<E:16>> <= Bin >>)
end,
- ?line <<>> = Fun11(<<>>),
- ?line <<1>> = Fun11(<<1:16>>),
- ?line <<1,2>> = Fun11(<<1:16,2:16>>),
- ?line <<1,2>> = Fun11(<<1:16,2:16,0:1>>),
- ?line <<1,2>> = Fun11(<<1:16,2:16,0:7>>),
- ?line <<1,2>> = Fun11(<<1:16,2:16,42:8>>),
- ?line <<1,2>> = Fun11(<<1:16,2:16,42:9>>),
- ?line <<1,2>> = Fun11(<<1:16,2:16,255:15>>),
+ <<>> = Fun11(<<>>),
+ <<1>> = Fun11(<<1:16>>),
+ <<1,2>> = Fun11(<<1:16,2:16>>),
+ <<1,2>> = Fun11(<<1:16,2:16,0:1>>),
+ <<1,2>> = Fun11(<<1:16,2:16,0:7>>),
+ <<1,2>> = Fun11(<<1:16,2:16,42:8>>),
+ <<1,2>> = Fun11(<<1:16,2:16,42:9>>),
+ <<1,2>> = Fun11(<<1:16,2:16,255:15>>),
Fun12 = fun(Bin, Sz1, Sz2) ->
cs(<< <<E:Sz1>> || <<E:Sz2>> <= Bin >>)
end,
- ?line <<>> = Fun12(<<>>, 1, 1),
- ?line Binary = list_to_binary(lists:seq(0, 255)),
- ?line Binary = Fun12(Binary, 1, 1),
- ?line Binary = Fun12(Binary, 4, 4),
- ?line Binary = Fun12(Binary, 8, 8),
- ?line <<17:9,19:9>> = Fun12(<<17:6,19:6>>, 9, 6),
+ <<>> = Fun12(<<>>, 1, 1),
+ Binary = list_to_binary(lists:seq(0, 255)),
+ Binary = Fun12(Binary, 1, 1),
+ Binary = Fun12(Binary, 4, 4),
+ Binary = Fun12(Binary, 8, 8),
+ <<17:9,19:9>> = Fun12(<<17:6,19:6>>, 9, 6),
Fun13 = fun(Sz) ->
cs_default(<< <<C:8>> || <<C:4>> <= <<1:4,2:4,3:4,0:Sz>> >>)
end,
- ?line <<1,2,3>> = Fun13(0),
- ?line <<1,2,3,0>> = Fun13(4),
- ?line <<1,2,3,0>> = Fun13(5),
- ?line <<1,2,3,0>> = Fun13(6),
- ?line <<1,2,3,0>> = Fun13(7),
- ?line <<1,2,3,0,0>> = Fun13(8),
+ <<1,2,3>> = Fun13(0),
+ <<1,2,3,0>> = Fun13(4),
+ <<1,2,3,0>> = Fun13(5),
+ <<1,2,3,0>> = Fun13(6),
+ <<1,2,3,0>> = Fun13(7),
+ <<1,2,3,0,0>> = Fun13(8),
<<0:3>> = cs_default(<< <<0:S>> || S <- [0,1,2] >>),
<<0:3>> = cs_default(<< <<0:S>> || <<S>> <= <<0,1,2>> >>),
- ?line {'EXIT',_} = (catch << <<C:4>> || <<C:8>> <= {1,2,3} >>),
+ {'EXIT',_} = (catch << <<C:4>> || <<C:8>> <= {1,2,3} >>),
+
+ cs_end(),
+ ok.
+
+-define(BAD(E), {'EXIT',{badarg,_}} = (catch << (E) || _ <- [1,2,3] >>)).
+-define(BAD_V(E), {'EXIT',{badarg,_}} = (catch << (E) || I <- [1,2,3] >>)).
+
+general_expressions(_) ->
+ <<1,2,3>> = << begin <<1,2,3>> end || _ <- [1] >>,
+ <<"abc">> = << begin <<"abc">> end || _ <- [1] >>,
+ <<1,2,3>> = << begin
+ I = <<(I0+1)>>,
+ id(I)
+ end || <<I0>> <= <<0,1,2>> >>,
+ <<1,2,3>> = << I || I <- [<<1,2>>,<<3>>] >>,
+ <<1,2,3>> = << (id(<<I>>)) || I <- [1,2,3] >>,
+ <<2,4>> = << case I rem 2 of
+ 0 -> <<I>>;
+ 1 -> <<>>
+ end || I <- [1,2,3,4,5] >>,
+ <<2,3,4,5,6,7>> = << << (id(<<J>>)) || J <- [2*I,2*I+1] >> ||
+ I <- [1,2,3] >>,
+ <<1,2,2,3,4,4>> = << if
+ I rem 2 =:= 0 -> <<I,I>>;
+ true -> <<I>>
+ end || I <- [1,2,3,4] >>,
+ self() ! <<42>>,
+ <<42>> = << receive B -> B end || _ <- [1] >>,
+ <<10,5,3>> = << try
+ <<(10 div I)>>
+ catch _:_ ->
+ <<>>
+ end || I <- [0,1,2,3] >>,
+
+ %% Failing expressions.
+ ?BAD(bad_atom),
+ ?BAD(42),
+ ?BAD(42.0),
+ ?BAD_V({ok,I}),
+ ?BAD_V([I]),
+ ?BAD_V(fun() -> I end),
- ?line cs_end(),
ok.
+-undef(BAD).
+
cs_init() ->
erts_debug:set_internal_state(available_internal_state, true),
ok.
diff --git a/lib/compiler/test/bs_bit_binaries_SUITE.erl b/lib/compiler/test/bs_bit_binaries_SUITE.erl
index afee52c9b9..c1f8f12bf1 100644
--- a/lib/compiler/test/bs_bit_binaries_SUITE.erl
+++ b/lib/compiler/test/bs_bit_binaries_SUITE.erl
@@ -29,7 +29,7 @@
big_binary_to_and_from_list/1,send_and_receive/1,
send_and_receive_alot/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -59,9 +59,9 @@ end_per_group(_GroupName, Config) ->
misc(Config) when is_list(Config) ->
- ?line <<1:100>> = <<1:100>>,
- ?line {ok,ok} = {match(7),match(9)},
- ?line {ok,ok} = {match1(15),match1(31)},
+ <<1:100>> = <<1:100>>,
+ {ok,ok} = {match(7),match(9)},
+ {ok,ok} = {match1(15),match1(31)},
ok.
@@ -74,75 +74,75 @@ match1(N) ->
ok.
test_bit_size(Config) when is_list(Config) ->
- ?line 101 = erlang:bit_size(<<1:101>>),
- ?line 1001 = erlang:bit_size(<<1:1001>>),
- ?line 1001 = erlang:bit_size(<<-10:1001>>),
- ?line 80 = erlang:bit_size(<<1:80>>),
- ?line 800 = erlang:bit_size(<<1:800>>),
- ?line Bin = <<0:16#1000000>>,
- ?line BigBin = list_to_bitstring([Bin||_ <- lists:seq(1,16#10)]++[<<1:1>>]),
- ?line 16#10000001 = erlang:bit_size(BigBin),
+ 101 = erlang:bit_size(<<1:101>>),
+ 1001 = erlang:bit_size(<<1:1001>>),
+ 1001 = erlang:bit_size(<<-10:1001>>),
+ 80 = erlang:bit_size(<<1:80>>),
+ 800 = erlang:bit_size(<<1:800>>),
+ Bin = <<0:16#1000000>>,
+ BigBin = list_to_bitstring([Bin||_ <- lists:seq(1,16#10)]++[<<1:1>>]),
+ 16#10000001 = erlang:bit_size(BigBin),
%% Only run these on computers with lots of memory
%% HugeBin = list_to_bitstring([BigBin||_ <- lists:seq(1,16#10)]++[<<1:1>>]),
%% 16#100000011 = erlang:bit_size(HugeBin),
- ?line 0 = erlang:bit_size(<<>>),
+ 0 = erlang:bit_size(<<>>),
ok.
horrid_match(Config) when is_list(Config) ->
- ?line <<1:4,B:24/bitstring>> = <<1:4,42:24/little>>,
- ?line <<42:24/little>> = B,
+ <<1:4,B:24/bitstring>> = <<1:4,42:24/little>>,
+ <<42:24/little>> = B,
ok.
test_bitstr(Config) when is_list(Config) ->
- ?line <<1:7,B/bitstring>> = <<1:7,<<1:1,6>>/bitstring>>,
- ?line <<1:1,6>> = B,
- ?line B = <<1:1,6>>,
+ <<1:7,B/bitstring>> = <<1:7,<<1:1,6>>/bitstring>>,
+ <<1:1,6>> = B,
+ B = <<1:1,6>>,
ok.
asymmetric_tests(Config) when is_list(Config) ->
- ?line <<1:12>> = <<0,1:4>>,
- ?line <<0,1:4>> = <<1:12>>,
- ?line <<1:1,X/bitstring>> = <<128,255,0,0:2>>,
- ?line <<1,254,0,0:1>> = X,
- ?line X = <<1,254,0,0:1>>,
- ?line <<1:1,X1:25/bitstring>> = <<128,255,0,0:2>>,
- ?line <<1,254,0,0:1>> = X1,
- ?line X1 = <<1,254,0,0:1>>,
+ <<1:12>> = <<0,1:4>>,
+ <<0,1:4>> = <<1:12>>,
+ <<1:1,X/bitstring>> = <<128,255,0,0:2>>,
+ <<1,254,0,0:1>> = X,
+ X = <<1,254,0,0:1>>,
+ <<1:1,X1:25/bitstring>> = <<128,255,0,0:2>>,
+ <<1,254,0,0:1>> = X1,
+ X1 = <<1,254,0,0:1>>,
ok.
big_asymmetric_tests(Config) when is_list(Config) ->
- ?line <<1:875,1:12>> = <<1:875,0,1:4>>,
- ?line <<1:875,0,1:4>> = <<1:875,1:12>>,
- ?line <<1:1,X/bitstring>> = <<128,255,0,0:2,1:875>>,
- ?line <<1,254,0,0:1,1:875>> = X,
- ?line X = <<1,254,0,0:1,1:875>>,
- ?line <<1:1,X1:900/bitstring>> = <<128,255,0,0:2,1:875>>,
- ?line <<1,254,0,0:1,1:875>> = X1,
- ?line X1 = <<1,254,0,0:1,1:875>>,
+ <<1:875,1:12>> = <<1:875,0,1:4>>,
+ <<1:875,0,1:4>> = <<1:875,1:12>>,
+ <<1:1,X/bitstring>> = <<128,255,0,0:2,1:875>>,
+ <<1,254,0,0:1,1:875>> = X,
+ X = <<1,254,0,0:1,1:875>>,
+ <<1:1,X1:900/bitstring>> = <<128,255,0,0:2,1:875>>,
+ <<1,254,0,0:1,1:875>> = X1,
+ X1 = <<1,254,0,0:1,1:875>>,
ok.
binary_to_and_from_list(Config) when is_list(Config) ->
- ?line <<1,2,3,4,1:1>> = list_to_bitstring(bitstring_to_list(<<1,2,3,4,1:1>>)),
- ?line [1,2,3,4,<<1:1>>] = bitstring_to_list(<<1,2,3,4,1:1>>),
- ?line <<1:1,1,2,3,4>> = list_to_bitstring([<<1:1>>,1,2,3,4]),
- ?line [128,129,1,130,<<0:1>>] = bitstring_to_list(<<1:1,1,2,3,4>>),
+ <<1,2,3,4,1:1>> = list_to_bitstring(bitstring_to_list(<<1,2,3,4,1:1>>)),
+ [1,2,3,4,<<1:1>>] = bitstring_to_list(<<1,2,3,4,1:1>>),
+ <<1:1,1,2,3,4>> = list_to_bitstring([<<1:1>>,1,2,3,4]),
+ [128,129,1,130,<<0:1>>] = bitstring_to_list(<<1:1,1,2,3,4>>),
ok.
big_binary_to_and_from_list(Config) when is_list(Config) ->
- ?line <<1:800,2,3,4,1:1>> =
+ <<1:800,2,3,4,1:1>> =
list_to_bitstring(bitstring_to_list(<<1:800,2,3,4,1:1>>)),
- ?line [1,2,3,4|_Rest1] = bitstring_to_list(<<1,2,3,4,1:800,1:1>>),
- ?line <<1:801,1,2,3,4>> = list_to_bitstring([<<1:801>>,1,2,3,4]),
+ [1,2,3,4|_Rest1] = bitstring_to_list(<<1,2,3,4,1:800,1:1>>),
+ <<1:801,1,2,3,4>> = list_to_bitstring([<<1:801>>,1,2,3,4]),
ok.
send_and_receive(Config) when is_list(Config) ->
- ?line Bin = <<1,2:7>>,
+ Bin = <<1,2:7>>,
Pid = spawn_link(fun() -> receiver(Bin) end),
- ?line Pid ! {self(),<<1:7,8:5,Bin/bitstring>>},
- ?line receive
- ok ->
- ok
- end.
+ Pid ! {self(),<<1:7,8:5,Bin/bitstring>>},
+ receive
+ ok ->
+ ok
+ end.
receiver(Bin) ->
receive
diff --git a/lib/compiler/test/bs_construct_SUITE.erl b/lib/compiler/test/bs_construct_SUITE.erl
index 87cfaaf73c..d94e870e21 100644
--- a/lib/compiler/test/bs_construct_SUITE.erl
+++ b/lib/compiler/test/bs_construct_SUITE.erl
@@ -31,9 +31,11 @@
nasty_literals/1,coerce_to_float/1,side_effect/1,
opt/1,otp_7556/1,float_arith/1,otp_8054/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
test_lib:recompile(?MODULE),
@@ -60,12 +62,9 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog = test_server:timetrap(?t:minutes(1)),
- [{watchdog,Dog}|Config].
+ Config.
end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
ok.
two(Config) when is_list(Config) ->
@@ -86,7 +85,7 @@ id(I) -> I.
-define(T(B, L), {B, ??B, L}).
-define(N(B), {B, ??B, unknown}).
--define(FAIL(Expr), ?line {'EXIT',{badarg,_}} = (catch Expr)).
+-define(FAIL(Expr), {'EXIT',{badarg,_}} = (catch Expr)).
l(I_13, I_big1, I_16, Bin) ->
[
@@ -200,7 +199,7 @@ one_test({C_bin, E_bin, Str, Bytes}) when is_list(Bytes) ->
true ->
io:format("ERROR: Compiled: ~p. Expected ~p. Got ~p.~n",
[Str, Bytes, bitstring_to_list(C_bin)]),
- test_server:fail(comp)
+ ct:fail(comp)
end,
if
E_bin == Bin ->
@@ -208,7 +207,7 @@ one_test({C_bin, E_bin, Str, Bytes}) when is_list(Bytes) ->
true ->
io:format("ERROR: Interpreted: ~p. Expected ~p. Got ~p.~n",
[Str, Bytes, bitstring_to_list(E_bin)]),
- test_server:fail(comp)
+ ct:fail(comp)
end;
one_test({C_bin, E_bin, Str, Result}) ->
io:format(" ~s ~p~n", [Str, C_bin]),
@@ -229,7 +228,7 @@ one_test({C_bin, E_bin, Str, Result}) ->
io:format("ERROR: Compiled not equal to interpreted:"
"~n ~p, ~p.~n",
[bitstring_to_list(C_bin), bitstring_to_list(E_bin)]),
- test_server:fail(comp);
+ ct:fail(comp);
0 ->
ok;
%% For situations where the final bits may not matter, like
@@ -261,15 +260,15 @@ equal_lists(A, B, R) ->
end.
test1(Config) when is_list(Config) ->
- ?line I_13 = i(13),
- ?line I_big1 = big(1),
- ?line I_16 = i(16),
- ?line Bin = i(<<16#A5,16#5A,16#C3>>),
- ?line Vars = lists:sort([{'I_13',I_13},
- {'I_big1',I_big1},
- {'I_16',I_16},
- {'Bin',Bin}]),
- ?line lists:foreach(fun one_test/1, eval_list(l(I_13, I_big1, I_16, Bin), Vars)).
+ I_13 = i(13),
+ I_big1 = big(1),
+ I_16 = i(16),
+ Bin = i(<<16#A5,16#5A,16#C3>>),
+ Vars = lists:sort([{'I_13',I_13},
+ {'I_big1',I_big1},
+ {'I_16',I_16},
+ {'Bin',Bin}]),
+ lists:foreach(fun one_test/1, eval_list(l(I_13, I_big1, I_16, Bin), Vars)).
fail(Config) when is_list(Config) ->
I_minus_777 = i(-777),
@@ -278,68 +277,68 @@ fail(Config) when is_list(Config) ->
%% One negative field size, but the sum of field sizes will be 1 byte.
%% Make sure that we reject that properly.
- ?line {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8,
- 57:I_minus_2047/unit:8>>),
+ {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8,
+ 57:I_minus_2047/unit:8>>),
%% Same thing, but use literals.
- ?line {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8,
- 57:(-2047)/unit:8>>),
+ {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8,
+ 57:(-2047)/unit:8>>),
%% Not numbers.
- ?line {'EXIT',{badarg,_}} = (catch <<45:(i(not_a_number))>>),
- ?line {'EXIT',{badarg,_}} = (catch <<13:8,45:(i(not_a_number))>>),
+ {'EXIT',{badarg,_}} = (catch <<45:(i(not_a_number))>>),
+ {'EXIT',{badarg,_}} = (catch <<13:8,45:(i(not_a_number))>>),
%% Unaligned sizes.
BadSz = i(7),
Bitstr = i(<<42:17>>),
- ?line {'EXIT',{badarg,_}} = (catch <<Bitstr:4/binary>>),
- ?line {'EXIT',{badarg,_}} = (catch <<Bitstr:BadSz/binary>>),
+ {'EXIT',{badarg,_}} = (catch <<Bitstr:4/binary>>),
+ {'EXIT',{badarg,_}} = (catch <<Bitstr:BadSz/binary>>),
- ?line [] = [X || {X} <- [], X == <<Bitstr:BadSz/binary>>],
- ?line [] = [X || {X} <- [], X == <<Bitstr:4/binary>>],
+ [] = [X || {X} <- [], X == <<Bitstr:BadSz/binary>>],
+ [] = [X || {X} <- [], X == <<Bitstr:4/binary>>],
%% Literals with incorrect type.
- ?line {'EXIT',{badarg,_}} = (catch <<42.0/integer>>),
- ?line {'EXIT',{badarg,_}} = (catch <<42/binary>>),
- ?line {'EXIT',{badarg,_}} = (catch <<an_atom/integer>>),
+ {'EXIT',{badarg,_}} = (catch <<42.0/integer>>),
+ {'EXIT',{badarg,_}} = (catch <<42/binary>>),
+ {'EXIT',{badarg,_}} = (catch <<an_atom/integer>>),
ok.
float_bin(Config) when is_list(Config) ->
%% Some more coverage.
- ?line {<<1,2,3>>,7.0} = float_bin_1(4),
+ {<<1,2,3>>,7.0} = float_bin_1(4),
F = 42.0,
- ?line <<42,0,0,0,0,0,0,69,64>> = <<(id(42)),F/little-float>>,
+ <<42,0,0,0,0,0,0,69,64>> = <<(id(42)),F/little-float>>,
ok.
float_bin_1(F) ->
{<<1,2,3>>,F+3.0}.
in_guard(Config) when is_list(Config) ->
- ?line 1 = in_guard_1(<<16#74ad:16>>, 16#e95, 5),
- ?line 2 = in_guard_1(<<16#3A,16#F7,"hello">>, 16#3AF7, <<"hello">>),
- ?line 3 = in_guard_1(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415),
- ?line 3 = in_guard_1(<<16#FBCD:14,3/float,3:2>>, 16#FBCD, 3),
- ?line 3 = in_guard_1(<<16#FBCD:14,(2 bsl 226)/float,3:2>>, 16#FBCD, 2 bsl 226),
- ?line nope = in_guard_1(<<1>>, 42, b),
- ?line nope = in_guard_1(<<1>>, a, b),
- ?line nope = in_guard_1(<<1,2>>, 1, 1),
- ?line nope = in_guard_1(<<4,5>>, 1, 2.71),
- ?line nope = in_guard_1(<<4,5>>, 1, <<12,13>>),
-
- ?line 1 = in_guard_2(<<0,56>>, 7, blurf),
- ?line 2 = in_guard_2(<<1,255>>, 511, blurf),
- ?line 3 = in_guard_2(<<0,3>>, 0, blurf),
- ?line 4 = in_guard_2(<<>>, 1, {<<7:16>>}),
- ?line nope = in_guard_2(<<4,5>>, 1, blurf),
-
- ?line 42 = in_guard_3(<<1,2,3,42>>, <<1,2,3>>),
- ?line 42 = in_guard_3(<<1,2,3,42>>, <<1,2,3>>),
- ?line nope = in_guard_3(<<>>, <<>>),
-
- ?line ok = in_guard_4(<<15:4>>, 255),
- ?line nope = in_guard_4(<<15:8>>, 255),
+ 1 = in_guard_1(<<16#74ad:16>>, 16#e95, 5),
+ 2 = in_guard_1(<<16#3A,16#F7,"hello">>, 16#3AF7, <<"hello">>),
+ 3 = in_guard_1(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415),
+ 3 = in_guard_1(<<16#FBCD:14,3/float,3:2>>, 16#FBCD, 3),
+ 3 = in_guard_1(<<16#FBCD:14,(2 bsl 226)/float,3:2>>, 16#FBCD, 2 bsl 226),
+ nope = in_guard_1(<<1>>, 42, b),
+ nope = in_guard_1(<<1>>, a, b),
+ nope = in_guard_1(<<1,2>>, 1, 1),
+ nope = in_guard_1(<<4,5>>, 1, 2.71),
+ nope = in_guard_1(<<4,5>>, 1, <<12,13>>),
+
+ 1 = in_guard_2(<<0,56>>, 7, blurf),
+ 2 = in_guard_2(<<1,255>>, 511, blurf),
+ 3 = in_guard_2(<<0,3>>, 0, blurf),
+ 4 = in_guard_2(<<>>, 1, {<<7:16>>}),
+ nope = in_guard_2(<<4,5>>, 1, blurf),
+
+ 42 = in_guard_3(<<1,2,3,42>>, <<1,2,3>>),
+ 42 = in_guard_3(<<1,2,3,42>>, <<1,2,3>>),
+ nope = in_guard_3(<<>>, <<>>),
+
+ ok = in_guard_4(<<15:4>>, 255),
+ nope = in_guard_4(<<15:8>>, 255),
ok.
in_guard_1(Bin, A, B) when <<A:13,B:3>> == Bin -> 1;
@@ -361,10 +360,10 @@ in_guard_4(Bin, A) when <<A:4>> =:= Bin -> ok;
in_guard_4(_, _) -> nope.
in_catch(Config) when is_list(Config) ->
- ?line <<42,0,5>> = small(42, 5),
- ?line <<255>> = small(255, <<1,2,3,4,5,6,7,8,9>>),
- ?line <<1,2>> = small(<<7,8,9,10>>, 258),
- ?line <<>> = small(<<1,2,3,4,5>>, <<7,8,9,10>>),
+ <<42,0,5>> = small(42, 5),
+ <<255>> = small(255, <<1,2,3,4,5,6,7,8,9>>),
+ <<1,2>> = small(<<7,8,9,10>>, 258),
+ <<>> = small(<<1,2,3,4,5>>, <<7,8,9,10>>),
<<15,240,0,42>> = small2(255, 42),
<<7:20>> = small2(<<1,2,3>>, 7),
@@ -413,20 +412,20 @@ small2(A, B) ->
nasty_literals(Config) when is_list(Config) ->
case erlang:system_info(endian) of
big ->
- ?line [0,42] = binary_to_list(id(<<42:16/native>>));
+ [0,42] = binary_to_list(id(<<42:16/native>>));
little ->
- ?line [42,0] = binary_to_list(id(<<42:16/native>>))
+ [42,0] = binary_to_list(id(<<42:16/native>>))
end,
- ?line Bin0 = id(<<1,2,3,0:10000000,4,5,6>>),
- ?line 1250006 = size(Bin0),
- ?line <<1,2,3,0:10000000,4,5,6>> = Bin0,
+ Bin0 = id(<<1,2,3,0:10000000,4,5,6>>),
+ 1250006 = size(Bin0),
+ <<1,2,3,0:10000000,4,5,6>> = Bin0,
- ?line Bin1 = id(<<0:10000000,7,8,-1:10000000,9,10,0:10000000>>),
- ?line 3750004 = size(Bin1),
- ?line <<0:10000000,7,8,-1:10000000/signed,9,10,0:10000000>> = Bin1,
+ Bin1 = id(<<0:10000000,7,8,-1:10000000,9,10,0:10000000>>),
+ 3750004 = size(Bin1),
+ <<0:10000000,7,8,-1:10000000/signed,9,10,0:10000000>> = Bin1,
- ?line <<255,255,0,0,0>> = id(<<255,255,0,0,0>>),
+ <<255,255,0,0,0>> = id(<<255,255,0,0,0>>),
%% Coverage.
I = 16#7777FFFF7777FFFF7777FFFF7777FFFF7777FFFF7777FFFF,
@@ -435,18 +434,18 @@ nasty_literals(Config) when is_list(Config) ->
ok.
-define(COF(Int0),
- ?line (fun(Int) ->
- true = <<Int:32/float>> =:= <<(float(Int)):32/float>>,
- true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
- end)(nonliteral(Int0)),
- ?line true = <<Int0:32/float>> =:= <<(float(Int0)):32/float>>,
- ?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>).
+ (fun(Int) ->
+ true = <<Int:32/float>> =:= <<(float(Int)):32/float>>,
+ true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
+ end)(nonliteral(Int0)),
+ true = <<Int0:32/float>> =:= <<(float(Int0)):32/float>>,
+ true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>).
-define(COF64(Int0),
- ?line (fun(Int) ->
- true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
- end)(nonliteral(Int0)),
- ?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>).
+ (fun(Int) ->
+ true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
+ end)(nonliteral(Int0)),
+ true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>).
nonliteral(X) -> X.
@@ -467,7 +466,7 @@ coerce_to_float(Config) when is_list(Config) ->
side_effect(Config) when is_list(Config) ->
{'EXIT',{badarg,_}} = (catch side_effect_1(a)),
{'EXIT',{badarg,_}} = (catch side_effect_1(<<>>)),
- ?line ok = side_effect_1(42),
+ ok = side_effect_1(42),
ok.
side_effect_1(A) ->
@@ -477,32 +476,32 @@ side_effect_1(A) ->
-record(otp_7029, {a,b}).
opt(Config) when is_list(Config) ->
- ?line 42 = otp_7029(#otp_7029{a = <<>>,b = 42}),
+ 42 = otp_7029(#otp_7029{a = <<>>,b = 42}),
N = 16,
- ?line <<1,3,65>> = id(<<1,833:N>>),
- ?line <<1,66,3>> = id(<<1,834:N/little>>),
- ?line <<1,65,136,0,0>> = id(<<1,17.0:32/float>>),
- ?line <<1,64,8,0,0,0,0,0,0>> = id(<<1,3.0:N/float-unit:4>>),
- ?line <<1,0,0,0,0,0,0,8,64>> = id(<<1,3.0:N/little-float-unit:4>>),
- ?line {'EXIT',{badarg,_}} = (catch id(<<3.1416:N/float>>)),
+ <<1,3,65>> = id(<<1,833:N>>),
+ <<1,66,3>> = id(<<1,834:N/little>>),
+ <<1,65,136,0,0>> = id(<<1,17.0:32/float>>),
+ <<1,64,8,0,0,0,0,0,0>> = id(<<1,3.0:N/float-unit:4>>),
+ <<1,0,0,0,0,0,0,8,64>> = id(<<1,3.0:N/little-float-unit:4>>),
+ {'EXIT',{badarg,_}} = (catch id(<<3.1416:N/float>>)),
B = <<1,2,3,4,5>>,
- ?line <<0,1,2,3,4,5>> = id(<<0,B/binary>>),
- ?line <<1,2,3,4,5,19>> = id(<<B:5/binary,19>>),
- ?line <<1,2,3,42>> = id(<<B:3/binary,42>>),
+ <<0,1,2,3,4,5>> = id(<<0,B/binary>>),
+ <<1,2,3,4,5,19>> = id(<<B:5/binary,19>>),
+ <<1,2,3,42>> = id(<<B:3/binary,42>>),
- ?line {'EXIT',_} = (catch <<<<23,56,0,2>>:(2.5)/binary>>),
- ?line {'EXIT',_} = (catch <<<<23,56,0,2>>:(-16)/binary>>),
- ?line {'EXIT',_} = (catch <<<<23,56,0,2>>:(anka)>>),
- ?line {'EXIT',_} = (catch <<<<23,56,0,2>>:64/float>>),
- ?line {'EXIT',_} = (catch <<<<23,56,0,2:7>>/binary>>),
+ {'EXIT',_} = (catch <<<<23,56,0,2>>:(2.5)/binary>>),
+ {'EXIT',_} = (catch <<<<23,56,0,2>>:(-16)/binary>>),
+ {'EXIT',_} = (catch <<<<23,56,0,2>>:(anka)>>),
+ {'EXIT',_} = (catch <<<<23,56,0,2>>:64/float>>),
+ {'EXIT',_} = (catch <<<<23,56,0,2:7>>/binary>>),
%% Test constant propagation - there should be a warning.
BadSz = 2.5,
{'EXIT',_} = (catch <<<<N,56,0,2>>:BadSz/binary>>),
case id(false) of
- true -> ?line opt_dont_call_me();
+ true -> opt_dont_call_me();
false -> ok
end,
@@ -530,7 +529,7 @@ otp_7556(Bin, A, B, C) ->
%% for a binary construction with a later allocation).
float_arith(Config) when is_list(Config) ->
- ?line {<<1,2,3,64,69,0,0,0,0,0,0>>,21.0} = do_float_arith(<<1,2,3>>, 42, 2),
+ {<<1,2,3,64,69,0,0,0,0,0,0>>,21.0} = do_float_arith(<<1,2,3>>, 42, 2),
ok.
do_float_arith(Bin0, X, Y) ->
@@ -538,7 +537,7 @@ do_float_arith(Bin0, X, Y) ->
{Bin,X / Y}.
otp_8054(Config) when is_list(Config) ->
- ?line <<"abc">> = otp_8054_1([null,1,2,3], <<"abc">>),
+ <<"abc">> = otp_8054_1([null,1,2,3], <<"abc">>),
ok.
otp_8054_1([H|T], Bin) ->
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 7fb0a16540..7fa26b6c26 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -36,15 +36,19 @@
match_string/1,zero_width/1,bad_size/1,haystack/1,
cover_beam_bool/1,matched_out_size/1,follow_fail_branch/1,
no_partition/1,calling_a_binary/1,binary_in_map/1,
- match_string_opt/1,map_and_binary/1,
- unsafe_branch_caching/1]).
+ match_string_opt/1,select_on_integer/1,
+ map_and_binary/1,unsafe_branch_caching/1,
+ bad_literals/1,good_literals/1]).
-export([coverage_id/1,coverage_external_ignore/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
+-include_lib("syntax_tools/include/merl.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
test_lib:recompile(?MODULE),
@@ -63,8 +67,9 @@ groups() ->
otp_7498,match_string,zero_width,bad_size,haystack,
cover_beam_bool,matched_out_size,follow_fail_branch,
no_partition,calling_a_binary,binary_in_map,
- match_string_opt,map_and_binary,
- unsafe_branch_caching]}].
+ match_string_opt,select_on_integer,
+ map_and_binary,unsafe_branch_caching,
+ bad_literals,good_literals]}].
init_per_suite(Config) ->
@@ -81,20 +86,17 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog = test_server:timetrap(?t:minutes(1)),
- [{watchdog,Dog}|Config].
+ Config.
end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
ok.
fun_shadow(Config) when is_list(Config) ->
%% OTP-5270
- ?line 7 = fun_shadow_1(),
- ?line 7 = fun_shadow_2(8),
- ?line 7 = fun_shadow_3(),
- ?line no = fun_shadow_4(8),
+ 7 = fun_shadow_1(),
+ 7 = fun_shadow_2(8),
+ 7 = fun_shadow_3(),
+ no = fun_shadow_4(8),
ok.
fun_shadow_1() ->
@@ -118,71 +120,78 @@ fun_shadow_4(L) ->
int_float(Config) when is_list(Config) ->
%% OTP-5323
- ?line <<103133.0:64/float>> = <<103133:64/float>>,
- ?line <<103133:64/float>> = <<103133:64/float>>,
- ok.
+ <<103133.0:64/float>> = <<103133:64/float>>,
+ <<103133:64/float>> = <<103133:64/float>>,
+
+ %% Coverage of error cases in sys_pre_expand:coerce_to_float/2.
+ case id(default) of
+ <<(1 bsl 1024):64/float>> ->
+ ct:fail(should_not_match);
+ default ->
+ ok
+ end.
%% Stolen from erl_eval_SUITE and modified.
%% OTP-5269. Bugs in the bit syntax.
otp_5269(Config) when is_list(Config) ->
- ?line check(fun() -> L = 8,
- F = fun(<<A:L,B:A>>) -> B end,
- F(<<16:8, 7:16>>)
+ check(fun() -> L = 8,
+ F = fun(<<A:L,B:A>>) -> B end,
+ F(<<16:8, 7:16>>)
end,
7),
- ?line check(fun() -> L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end,
- 7),
- ?line check(fun() -> U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end,
- 32),
- ?line check(fun() -> U = 8, [U || <<U:U>> <- [<<32:8>>]] end,
- [32]),
- ?line check(fun() -> [X || <<A:8,
- B:A>> <- [<<16:8,19:16>>],
- <<X:8>> <- [<<B:8>>]] end,
- [19]),
- ?line check(fun() -> A = 4, B = 28, bit_size(<<13:(A+(X=B))>>), X end,
- 28),
- ?line check(fun() ->
- <<Size,B:Size/binary,Rest/binary>> = <<2,"AB","CD">>,
- {Size,B,Rest}
- end,
- {2,<<"AB">>,<<"CD">>}),
- ?line check(fun() -> X = 32,
- [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end,
- %% "binsize variable" ^
- [1,2]),
- ?line check(fun() ->
- (fun (<<A:1/binary, B:8/integer, _C:B/binary>>) ->
- case A of
- B -> wrong;
- _ -> ok
- end
- end)(<<1,2,3,4>>) end,
- ok),
+ check(fun() -> L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end,
+ 7),
+ check(fun() -> U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end,
+ 32),
+ check(fun() -> U = 8, [U || <<U:U>> <- [<<32:8>>]] end,
+ [32]),
+ check(fun() -> [X || <<A:8,
+ B:A>> <- [<<16:8,19:16>>],
+ <<X:8>> <- [<<B:8>>]] end,
+ [19]),
+ check(fun() -> A = 4, B = 28, bit_size(<<13:(A+(X=B))>>), X end,
+ 28),
+ check(fun() ->
+ <<Size,B:Size/binary,Rest/binary>> = <<2,"AB","CD">>,
+ {Size,B,Rest}
+ end,
+ {2,<<"AB">>,<<"CD">>}),
+ check(fun() -> X = 32,
+ [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end,
+ %% "binsize variable" ^
+ [1,2]),
+ check(fun() ->
+ (fun (<<A:1/binary, B:8/integer, _C:B/binary>>) ->
+ case A of
+ B -> wrong;
+ _ -> ok
+ end
+ end)(<<1,2,3,4>>) end,
+ ok),
ok.
null_fields(Config) when is_list(Config) ->
- ?line check(fun() ->
- W = id(0),
- F = fun(<<_:W>>) -> tail;
- (<<>>) -> empty
- end,
- F(<<>>)
- end, tail),
- ?line check(fun() ->
- F = fun(<<_/binary>>) -> tail;
- (<<>>) -> empty
- end,
- F(<<>>)
- end, tail),
+ check(fun() ->
+ W = id(0),
+ F = fun(<<_:W>>) -> tail;
+ (<<>>) -> empty
+ end,
+ F(<<>>)
+ end, tail),
+ check(fun() ->
+ F = fun(<<_/binary>>) -> tail;
+ (<<>>) -> empty
+ end,
+ F(<<>>)
+ end, tail),
ok.
wiger(Config) when is_list(Config) ->
- ?line ok1 = wcheck(<<3>>),
- ?line ok2 = wcheck(<<1,2,3>>),
- ?line ok3 = wcheck(<<4>>),
- ?line {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>),
- ?line {error,<<>>} = wcheck(<<>>),
+ ok1 = wcheck(<<3>>),
+ ok2 = wcheck(<<1,2,3>>),
+ ok3 = wcheck(<<4>>),
+ {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>),
+ {error,<<>>} = wcheck(<<>>),
ok.
wcheck(<<A>>) when A==3->
@@ -196,24 +205,24 @@ wcheck(Other) ->
bin_tail(Config) when is_list(Config) ->
S = <<"abcde">>,
- ?line $a = bin_tail_c(S, 0),
- ?line $c = bin_tail_c(S, 2),
- ?line $e = bin_tail_c(S, 4),
- ?line {'EXIT',_} = (catch bin_tail_c(S, 5)),
- ?line {'EXIT',_} = (catch bin_tail_c_var(S, 5)),
-
- ?line $a = bin_tail_d(S, 0),
- ?line $b = bin_tail_d(S, 8),
- ?line $d = bin_tail_d(S, 3*8),
- ?line {'EXIT',_} = (catch bin_tail_d_dead(S, 1)),
- ?line {'EXIT',_} = (catch bin_tail_d_dead(S, 9)),
- ?line {'EXIT',_} = (catch bin_tail_d_dead(S, 5*8)),
- ?line {'EXIT',_} = (catch bin_tail_d_var(S, 1)),
-
- ?line ok = bin_tail_e(<<2:2,0:1,1:5>>),
- ?line ok = bin_tail_e(<<2:2,1:1,1:5,42:64>>),
- ?line error = bin_tail_e(<<3:2,1:1,1:5,42:64>>),
- ?line error = bin_tail_e(<<>>),
+ $a = bin_tail_c(S, 0),
+ $c = bin_tail_c(S, 2),
+ $e = bin_tail_c(S, 4),
+ {'EXIT',_} = (catch bin_tail_c(S, 5)),
+ {'EXIT',_} = (catch bin_tail_c_var(S, 5)),
+
+ $a = bin_tail_d(S, 0),
+ $b = bin_tail_d(S, 8),
+ $d = bin_tail_d(S, 3*8),
+ {'EXIT',_} = (catch bin_tail_d_dead(S, 1)),
+ {'EXIT',_} = (catch bin_tail_d_dead(S, 9)),
+ {'EXIT',_} = (catch bin_tail_d_dead(S, 5*8)),
+ {'EXIT',_} = (catch bin_tail_d_var(S, 1)),
+
+ ok = bin_tail_e(<<2:2,0:1,1:5>>),
+ ok = bin_tail_e(<<2:2,1:1,1:5,42:64>>),
+ error = bin_tail_e(<<3:2,1:1,1:5,42:64>>),
+ error = bin_tail_e(<<>>),
ok.
bin_tail_c(Bin, Offset) ->
@@ -272,34 +281,34 @@ bin_tail_e_var(Bin) ->
end.
save_restore(Config) when is_list(Config) ->
- ?line 0 = save_restore_1(<<0:2,42:6>>),
- ?line {1,3456} = save_restore_1(<<1:2,3456:14>>),
- ?line {2,7981234} = save_restore_1(<<2:2,7981234:30>>),
- ?line {3,763967493838} = save_restore_1(<<0:2,763967493838:62>>),
+ 0 = save_restore_1(<<0:2,42:6>>),
+ {1,3456} = save_restore_1(<<1:2,3456:14>>),
+ {2,7981234} = save_restore_1(<<2:2,7981234:30>>),
+ {3,763967493838} = save_restore_1(<<0:2,763967493838:62>>),
A = <<" x">>,
B = <<".x">>,
C = <<"-x">>,
- ?line {" ",<<"x">>} = lll(A),
- ?line {" ",<<"x">>} = mmm(A),
- ?line {" ",<<"x">>} = nnn(A),
- ?line {" ",<<"x">>} = ooo(A),
+ {" ",<<"x">>} = lll(A),
+ {" ",<<"x">>} = mmm(A),
+ {" ",<<"x">>} = nnn(A),
+ {" ",<<"x">>} = ooo(A),
- ?line {".",<<"x">>} = lll(B),
- ?line {".",<<"x">>} = mmm(B),
- ?line {".",<<"x">>} = nnn(B),
- ?line {".",<<"x">>} = ooo(B),
+ {".",<<"x">>} = lll(B),
+ {".",<<"x">>} = mmm(B),
+ {".",<<"x">>} = nnn(B),
+ {".",<<"x">>} = ooo(B),
- ?line {"-",<<"x">>} = lll(C),
- ?line {"-",<<"x">>} = mmm(C),
- ?line {"-",<<"x">>} = nnn(C),
- ?line {"-",<<"x">>} = ooo(C),
+ {"-",<<"x">>} = lll(C),
+ {"-",<<"x">>} = mmm(C),
+ {"-",<<"x">>} = nnn(C),
+ {"-",<<"x">>} = ooo(C),
Bin = <<-1:64>>,
case bad_float_unpack_match(Bin) of
-1 -> ok;
- _Other -> ?line ?t:fail(bad_return_value_probably_NaN)
+ _Other -> ct:fail(bad_return_value_probably_NaN)
end.
save_restore_1(Bin) ->
@@ -328,18 +337,18 @@ bad_float_unpack_match(<<I:64/integer-signed>>) -> I.
partitioned_bs_match(Config) when is_list(Config) ->
- ?line <<1,2,3>> = partitioned_bs_match(blurf, <<42,1,2,3>>),
- ?line error = partitioned_bs_match(10, <<7,8,15,13>>),
- ?line error = partitioned_bs_match(100, {a,tuple,is,'not',a,binary}),
- ?line ok = partitioned_bs_match(0, <<>>),
- ?line fc(partitioned_bs_match, [-1,blurf],
+ <<1,2,3>> = partitioned_bs_match(blurf, <<42,1,2,3>>),
+ error = partitioned_bs_match(10, <<7,8,15,13>>),
+ error = partitioned_bs_match(100, {a,tuple,is,'not',a,binary}),
+ ok = partitioned_bs_match(0, <<>>),
+ fc(partitioned_bs_match, [-1,blurf],
catch partitioned_bs_match(-1, blurf)),
- ?line fc(partitioned_bs_match, [-1,<<1,2,3>>],
+ fc(partitioned_bs_match, [-1,<<1,2,3>>],
catch partitioned_bs_match(-1, <<1,2,3>>)),
- ?line {17,<<1,2,3>>} = partitioned_bs_match_2(1, <<17,1,2,3>>),
- ?line {7,<<1,2,3>>} = partitioned_bs_match_2(7, <<17,1,2,3>>),
+ {17,<<1,2,3>>} = partitioned_bs_match_2(1, <<17,1,2,3>>),
+ {7,<<1,2,3>>} = partitioned_bs_match_2(7, <<17,1,2,3>>),
- ?line fc(partitioned_bs_match_2, [4,<<0:17>>],
+ fc(partitioned_bs_match_2, [4,<<0:17>>],
catch partitioned_bs_match_2(4, <<0:17>>)),
anything = partitioned_bs_match_3(anything, <<42>>),
@@ -392,25 +401,25 @@ function_clause_2(<<_:4>>) ->
ok.
unit(Config) when is_list(Config) ->
- ?line 42 = peek1(<<42>>),
- ?line 43 = peek1(<<43,1,2>>),
- ?line 43 = peek1(<<43,1,2,(-1):1>>),
- ?line 43 = peek1(<<43,1,2,(-1):2>>),
- ?line 43 = peek1(<<43,1,2,(-1):7>>),
-
- ?line 99 = peek8(<<99>>),
- ?line 100 = peek8(<<100,101>>),
- ?line fc(peek8, [<<100,101,0:1>>], catch peek8(<<100,101,0:1>>)),
-
- ?line 37484 = peek16(<<37484:16>>),
- ?line 37489 = peek16(<<37489:16,5566:16>>),
- ?line fc(peek16, [<<8>>], catch peek16(<<8>>)),
- ?line fc(peek16, [<<42:15>>], catch peek16(<<42:15>>)),
- ?line fc(peek16, [<<1,2,3,4,5>>], catch peek16(<<1,2,3,4,5>>)),
-
- ?line 127 = peek7(<<127:7>>),
- ?line 100 = peek7(<<100:7,19:7>>),
- ?line fc(peek7, [<<1,2>>], catch peek7(<<1,2>>)),
+ 42 = peek1(<<42>>),
+ 43 = peek1(<<43,1,2>>),
+ 43 = peek1(<<43,1,2,(-1):1>>),
+ 43 = peek1(<<43,1,2,(-1):2>>),
+ 43 = peek1(<<43,1,2,(-1):7>>),
+
+ 99 = peek8(<<99>>),
+ 100 = peek8(<<100,101>>),
+ fc(peek8, [<<100,101,0:1>>], catch peek8(<<100,101,0:1>>)),
+
+ 37484 = peek16(<<37484:16>>),
+ 37489 = peek16(<<37489:16,5566:16>>),
+ fc(peek16, [<<8>>], catch peek16(<<8>>)),
+ fc(peek16, [<<42:15>>], catch peek16(<<42:15>>)),
+ fc(peek16, [<<1,2,3,4,5>>], catch peek16(<<1,2,3,4,5>>)),
+
+ 127 = peek7(<<127:7>>),
+ 100 = peek7(<<100:7,19:7>>),
+ fc(peek7, [<<1,2>>], catch peek7(<<1,2>>)),
ok.
peek1(<<B:8,_/bitstring>>) -> B.
@@ -422,7 +431,7 @@ peek8(<<B:8,_/binary>>) -> B.
peek16(<<B:16,_/binary-unit:16>>) -> B.
shared_sub_bins(Config) when is_list(Config) ->
- ?line {15,[<<>>,<<5>>,<<4,5>>,<<3,4,5>>,<<2,3,4,5>>]} = sum(<<1,2,3,4,5>>, [], 0),
+ {15,[<<>>,<<5>>,<<4,5>>,<<3,4,5>>,<<2,3,4,5>>]} = sum(<<1,2,3,4,5>>, [], 0),
ok.
sum(<<B,T/binary>>, Acc, Sum) ->
@@ -431,7 +440,7 @@ sum(<<>>, Last, Sum) -> {Sum,Last}.
bin_and_float(Config) when is_list(Config) ->
- ?line 14.0 = bin_and_float(<<1.0/float,2.0/float,3.0/float>>, 0.0),
+ 14.0 = bin_and_float(<<1.0/float,2.0/float,3.0/float>>, 0.0),
ok.
bin_and_float(<<X/float,Y/float,Z/float,T/binary>>, Sum) when is_float(X),
@@ -441,10 +450,10 @@ bin_and_float(<<X/float,Y/float,Z/float,T/binary>>, Sum) when is_float(X),
bin_and_float(<<>>, Sum) -> Sum.
dec_subidentifiers(Config) when is_list(Config) ->
- ?line {[],<<1,2,3>>} =
+ {[],<<1,2,3>>} =
do_dec_subidentifiers(<<1:1,42:7,1:1,99:7,1,2,3>>, 0, [], 2),
- ?line {[5389],<<1,2,3>>} = do_dec_subidentifiers(<<1:1,42:7,0:1,13:7,1,2,3>>, 0, [], 2),
- ?line {[3,2,1],not_a_binary} = dec_subidentifiers(not_a_binary, any, [1,2,3], 0),
+ {[5389],<<1,2,3>>} = do_dec_subidentifiers(<<1:1,42:7,0:1,13:7,1,2,3>>, 0, [], 2),
+ {[3,2,1],not_a_binary} = dec_subidentifiers(not_a_binary, any, [1,2,3], 0),
ok.
do_dec_subidentifiers(Buffer, Av, Al, Len) ->
@@ -500,18 +509,18 @@ skip_optional_tag(_, _) -> missing.
wfbm(Config) when is_list(Config) ->
%% check_for_dot_or_space and get_tail is from wfbm4 by Steve Vinoski,
%% with modifications.
- ?line {nomatch,0} = check_for_dot_or_space(<<" ">>),
- ?line {nomatch,0} = check_for_dot_or_space(<<" abc">>),
- ?line {ok,<<"abcde">>} = check_for_dot_or_space(<<"abcde 34555">>),
- ?line {nomatch,0} = check_for_dot_or_space(<<".gurka">>),
- ?line {nomatch,1} = check_for_dot_or_space(<<"g.urka">>),
-
- ?line nomatch = get_tail(<<>>),
- ?line {ok,<<"2007/10/23/blurf">>} = get_tail(<<"200x/2007/10/23/blurf ">>),
- ?line {skip,?DATELEN+5} = get_tail(<<"200x/2007/10/23/blurf.">>),
- ?line nomatch = get_tail(<<"200y.2007.10.23.blurf ">>),
- ?line {'EXIT',_} = (catch get_tail({no,binary,at,all})),
- ?line {'EXIT',_} = (catch get_tail(no_binary)),
+ {nomatch,0} = check_for_dot_or_space(<<" ">>),
+ {nomatch,0} = check_for_dot_or_space(<<" abc">>),
+ {ok,<<"abcde">>} = check_for_dot_or_space(<<"abcde 34555">>),
+ {nomatch,0} = check_for_dot_or_space(<<".gurka">>),
+ {nomatch,1} = check_for_dot_or_space(<<"g.urka">>),
+
+ nomatch = get_tail(<<>>),
+ {ok,<<"2007/10/23/blurf">>} = get_tail(<<"200x/2007/10/23/blurf ">>),
+ {skip,?DATELEN+5} = get_tail(<<"200x/2007/10/23/blurf.">>),
+ nomatch = get_tail(<<"200y.2007.10.23.blurf ">>),
+ {'EXIT',_} = (catch get_tail({no,binary,at,all})),
+ {'EXIT',_} = (catch get_tail(no_binary)),
ok.
check_for_dot_or_space(Bin) ->
@@ -544,13 +553,13 @@ get_tail(Bin) ->
end.
degenerated_match(Config) when is_list(Config) ->
- ?line error = degenerated_match_1(<<>>),
- ?line 1 = degenerated_match_1(<<1:1>>),
- ?line 2 = degenerated_match_1(<<42,43>>),
+ error = degenerated_match_1(<<>>),
+ 1 = degenerated_match_1(<<1:1>>),
+ 2 = degenerated_match_1(<<42,43>>),
- ?line error = degenerated_match_2(<<>>),
- ?line no_split = degenerated_match_2(<<1,2>>),
- ?line {<<1,2,3,4>>,<<5>>} = degenerated_match_2(<<1,2,3,4,5>>),
+ error = degenerated_match_2(<<>>),
+ no_split = degenerated_match_2(<<1,2>>),
+ {<<1,2,3,4>>,<<5>>} = degenerated_match_2(<<1,2,3,4,5>>),
ok.
@@ -567,25 +576,25 @@ degenerated_match_2(Bin) ->
end.
bs_sum(Config) when is_list(Config) ->
- ?line 0 = bs_sum_1([]),
- ?line 0 = bs_sum_1(<<>>),
- ?line 42 = bs_sum_1([42]),
- ?line 1 = bs_sum_1(<<1>>),
- ?line 10 = bs_sum_1([1,2,3,4]),
- ?line 15 = bs_sum_1(<<1,2,3,4,5>>),
- ?line 21 = bs_sum_1([1,2,3|<<4,5,6>>]),
- ?line 15 = bs_sum_1([1,2,3|{4,5}]),
- ?line 6 = bs_sum_1([1,2,3|zero]),
- ?line 6 = bs_sum_1([1,2,3|0]),
- ?line 7 = bs_sum_1([1,2,3|one]),
-
- ?line fc(catch bs_sum_1({too,big,tuple})),
- ?line fc(catch bs_sum_1([1,2,3|{too,big,tuple}])),
-
- ?line [] = sneaky_alias(<<>>),
- ?line [559,387655] = sneaky_alias(id(<<559:32,387655:32>>)),
- ?line fc(sneaky_alias, [<<1>>], catch sneaky_alias(id(<<1>>))),
- ?line fc(sneaky_alias, [[1,2,3,4]], catch sneaky_alias(lists:seq(1, 4))),
+ 0 = bs_sum_1([]),
+ 0 = bs_sum_1(<<>>),
+ 42 = bs_sum_1([42]),
+ 1 = bs_sum_1(<<1>>),
+ 10 = bs_sum_1([1,2,3,4]),
+ 15 = bs_sum_1(<<1,2,3,4,5>>),
+ 21 = bs_sum_1([1,2,3|<<4,5,6>>]),
+ 15 = bs_sum_1([1,2,3|{4,5}]),
+ 6 = bs_sum_1([1,2,3|zero]),
+ 6 = bs_sum_1([1,2,3|0]),
+ 7 = bs_sum_1([1,2,3|one]),
+
+ fc(catch bs_sum_1({too,big,tuple})),
+ fc(catch bs_sum_1([1,2,3|{too,big,tuple}])),
+
+ [] = sneaky_alias(<<>>),
+ [559,387655] = sneaky_alias(id(<<559:32,387655:32>>)),
+ fc(sneaky_alias, [<<1>>], catch sneaky_alias(id(<<1>>))),
+ fc(sneaky_alias, [[1,2,3,4]], catch sneaky_alias(lists:seq(1, 4))),
ok.
bs_sum_1(<<H,T/binary>>) -> H+bs_sum_1(T);
@@ -601,31 +610,31 @@ sneaky_alias(<<>>=L) -> binary_to_list(L);
sneaky_alias(<<From:32,L/binary>>) -> [From|sneaky_alias(L)].
coverage(Config) when is_list(Config) ->
- ?line 0 = coverage_fold(fun(B, A) -> A+B end, 0, <<>>),
- ?line 6 = coverage_fold(fun(B, A) -> A+B end, 0, <<1,2,3>>),
- ?line fc(catch coverage_fold(fun(B, A) ->
+ 0 = coverage_fold(fun(B, A) -> A+B end, 0, <<>>),
+ 6 = coverage_fold(fun(B, A) -> A+B end, 0, <<1,2,3>>),
+ fc(catch coverage_fold(fun(B, A) ->
A+B
end, 0, [a,b,c])),
- ?line {<<42.0:64/float>>,float} = coverage_build(<<>>, <<42>>, float),
- ?line {<<>>,not_a_tuple} = coverage_build(<<>>, <<>>, not_a_tuple),
- ?line {<<16#76,"abc",16#A9,"abc">>,{x,42,43}} =
+ {<<42.0:64/float>>,float} = coverage_build(<<>>, <<42>>, float),
+ {<<>>,not_a_tuple} = coverage_build(<<>>, <<>>, not_a_tuple),
+ {<<16#76,"abc",16#A9,"abc">>,{x,42,43}} =
coverage_build(<<>>, <<16#7,16#A>>, {x,y,z}),
- ?line [<<2>>,<<1>>] = coverage_bc(<<1,2>>, []),
+ [<<2>>,<<1>>] = coverage_bc(<<1,2>>, []),
- ?line {x,<<"abc">>,z} = coverage_setelement(<<2,"abc">>, {x,y,z}),
+ {x,<<"abc">>,z} = coverage_setelement(<<2,"abc">>, {x,y,z}),
- ?line [42] = coverage_apply(<<42>>, [coverage_id]),
- ?line 42 = coverage_external(<<42>>),
+ [42] = coverage_apply(<<42>>, [coverage_id]),
+ 42 = coverage_external(<<42>>),
- ?line do_coverage_bin_to_term_list([]),
- ?line do_coverage_bin_to_term_list([lists:seq(0, 10),{a,b,c},<<23:42>>]),
- ?line fc(coverage_bin_to_term_list, [<<0,0,0,7>>],
+ do_coverage_bin_to_term_list([]),
+ do_coverage_bin_to_term_list([lists:seq(0, 10),{a,b,c},<<23:42>>]),
+ fc(coverage_bin_to_term_list, [<<0,0,0,7>>],
catch do_coverage_bin_to_term_list_1(<<7:32>>)),
- ?line <<>> = coverage_per_key(<<4:32>>),
- ?line <<$a,$b,$c>> = coverage_per_key(<<7:32,"abc">>),
+ <<>> = coverage_per_key(<<4:32>>),
+ <<$a,$b,$c>> = coverage_per_key(<<7:32,"abc">>),
ok.
@@ -718,9 +727,9 @@ coverage_per_key(<<BinSize:32,Bin/binary>> = B) ->
Bin.
multiple_uses(Config) when is_list(Config) ->
- ?line {344,62879,345,<<245,159,1,89>>} = multiple_uses_1(<<1,88,245,159,1,89>>),
- ?line true = multiple_uses_2(<<0,0,197,18>>),
- ?line <<42,43>> = multiple_uses_3(<<0,0,42,43>>, fun id/1),
+ {344,62879,345,<<245,159,1,89>>} = multiple_uses_1(<<1,88,245,159,1,89>>),
+ true = multiple_uses_2(<<0,0,197,18>>),
+ <<42,43>> = multiple_uses_3(<<0,0,42,43>>, fun id/1),
ok.
multiple_uses_1(<<X:16,Tail/binary>>) ->
@@ -743,8 +752,8 @@ multiple_uses_cmp(<<Y:16>>, <<Y:16>>) -> true;
multiple_uses_cmp(<<_:16>>, <<_:16>>) -> false.
zero_label(Config) when is_list(Config) ->
- ?line <<"nosemouth">> = read_pols(<<"FACE","nose","mouth">>),
- ?line <<"CE">> = read_pols(<<"noFACE">>),
+ <<"nosemouth">> = read_pols(<<"FACE","nose","mouth">>),
+ <<"CE">> = read_pols(<<"noFACE">>),
ok.
read_pols(Data) ->
@@ -772,14 +781,14 @@ matching_meets_construction(Config) when is_list(Config) ->
Bin = id(<<"abc">>),
Len = id(2),
Tail0 = id(<<1,2,3,4,5>>),
- ?line <<_:Len/binary,Tail/binary>> = Tail0,
- ?line Res = <<Tail/binary,Bin/binary>>,
- ?line <<3,4,5,"abc">> = Res,
- ?line {'EXIT',{badarg,_}} = (catch matching_meets_construction_1(<<"Abc">>)),
- ?line {'EXIT',{badarg,_}} = (catch matching_meets_construction_2(<<"Abc">>)),
- ?line <<"Bbc">> = matching_meets_construction_3(<<"Abc">>),
-
- ?line <<1,2>> = encode_octet_string(<<1,2,3>>, 2),
+ <<_:Len/binary,Tail/binary>> = Tail0,
+ Res = <<Tail/binary,Bin/binary>>,
+ <<3,4,5,"abc">> = Res,
+ {'EXIT',{badarg,_}} = (catch matching_meets_construction_1(<<"Abc">>)),
+ {'EXIT',{badarg,_}} = (catch matching_meets_construction_2(<<"Abc">>)),
+ <<"Bbc">> = matching_meets_construction_3(<<"Abc">>),
+
+ <<1,2>> = encode_octet_string(<<1,2,3>>, 2),
ok.
matching_meets_construction_1(<<"A",H/binary>>) -> <<"B",H>>.
@@ -792,14 +801,14 @@ encode_octet_string(<<OctetString/binary>>, Len) ->
<<OctetString:Len/binary-unit:8>>.
simon(Config) when is_list(Config) ->
- ?line one = simon(blurf, <<>>),
- ?line two = simon(0, <<42>>),
- ?line fc(simon, [17,<<1>>], catch simon(17, <<1>>)),
- ?line fc(simon, [0,<<1,2,3>>], catch simon(0, <<1,2,3>>)),
-
- ?line one = simon2(blurf, <<9>>),
- ?line two = simon2(0, <<9,1>>),
- ?line fc(simon2, [0,<<9,10,11>>], catch simon2(0, <<9,10,11>>)),
+ one = simon(blurf, <<>>),
+ two = simon(0, <<42>>),
+ fc(simon, [17,<<1>>], catch simon(17, <<1>>)),
+ fc(simon, [0,<<1,2,3>>], catch simon(0, <<1,2,3>>)),
+
+ one = simon2(blurf, <<9>>),
+ two = simon2(0, <<9,1>>),
+ fc(simon2, [0,<<9,10,11>>], catch simon2(0, <<9,10,11>>)),
ok.
simon(_, <<>>) -> one;
@@ -811,10 +820,10 @@ simon2(0, <<_:16>>) -> two.
%% OTP-7113: Crash in v3_codegen.
matching_and_andalso(Config) when is_list(Config) ->
- ?line ok = matching_and_andalso_1(<<1,2,3>>, 3),
- ?line {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, -8)),
- ?line {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, blurf)),
- ?line {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, 19)),
+ ok = matching_and_andalso_1(<<1,2,3>>, 3),
+ {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, -8)),
+ {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, blurf)),
+ {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, 19)),
{"abc",<<"xyz">>} = matching_and_andalso_2("abc", <<"-xyz">>),
{"abc",<<"">>} = matching_and_andalso_2("abc", <<($a-1)>>),
@@ -847,7 +856,7 @@ otp_7188(Config) when is_list(Config) ->
0,0,0,0,0,0,50,48,48,48,50,48,48,48,32,45,32,66,101,115,
116,32,79,102,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,12>>,
- ?line {ok,{"ID3v1",
+ {ok,{"ID3v1",
[{title,<<68,117,154,105,232,107,121>>},
{artist,<<"Daniel Landa">>},
{album,<<"Best Of">>}]}} = parse_v1_or_v11_tag(MP3).
@@ -891,11 +900,11 @@ skip_blanks_and_zero(L) ->
-record(rec_otp_7233, {key, val}).
otp_7233(Config) when is_list(Config) ->
- ?line otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[{"xxxxxxxx",42}]}),
- ?line [<<"XXabcde">>,{"xxxxxxxx",42}] = get(io_format),
+ otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[{"xxxxxxxx",42}]}),
+ [<<"XXabcde">>,{"xxxxxxxx",42}] = get(io_format),
erase(io_format),
- ?line otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[]}),
- ?line undefined = get(io_format),
+ otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[]}),
+ undefined = get(io_format),
ok.
otp_7233_1(Rec) ->
@@ -903,32 +912,34 @@ otp_7233_1(Rec) ->
case K of
<<"XX">> ->
Value = Rec#rec_otp_7233.val,
- case lists:keysearch("xxxxxxxx", 1, Value) of
- {value,T} -> put(io_format, [Rec#rec_otp_7233.key,T]);
- false -> ok
+ case lists:keyfind("xxxxxxxx", 1, Value) of
+ false ->
+ ok;
+ T ->
+ put(io_format, [Rec#rec_otp_7233.key,T])
end;
_ -> ok
end.
otp_7240(Config) when is_list(Config) ->
- ?line a = otp_7240_a(0, <<>>),
- ?line b = otp_7240_a(1, 2),
+ a = otp_7240_a(0, <<>>),
+ b = otp_7240_a(1, 2),
- ?line a = otp_7240_b(anything, <<>>),
- ?line b = otp_7240_b(1, {x,y}),
+ a = otp_7240_b(anything, <<>>),
+ b = otp_7240_b(1, {x,y}),
- ?line a = otp_7240_c(anything, <<>>),
- ?line b = otp_7240_c(1, <<2>>),
+ a = otp_7240_c(anything, <<>>),
+ b = otp_7240_c(1, <<2>>),
- ?line a = otp_7240_d(anything, <<>>),
- ?line b = otp_7240_d(again, <<2>>),
+ a = otp_7240_d(anything, <<>>),
+ b = otp_7240_d(again, <<2>>),
- ?line a = otp_7240_e(anything, <<>>),
- ?line b = otp_7240_e(1, 41),
+ a = otp_7240_e(anything, <<>>),
+ b = otp_7240_e(1, 41),
- ?line a = otp_7240_f(anything, <<>>),
- ?line b = otp_7240_f(1, {}),
+ a = otp_7240_f(anything, <<>>),
+ b = otp_7240_f(1, {}),
ok.
@@ -951,15 +962,15 @@ otp_7240_f(_, <<>>) -> a;
otp_7240_f(1, B) when is_tuple(B) -> b.
otp_7498(Config) when is_list(Config) ->
- ?line <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 0),
- ?line <<2,3>> = otp_7498_foo(<<1,2,3>>, 1),
- ?line <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 2),
+ <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 0),
+ <<2,3>> = otp_7498_foo(<<1,2,3>>, 1),
+ <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 2),
- ?line <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 0),
- ?line <<2,3>> = otp_7498_bar(<<1,2,3>>, 1),
- ?line <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 2),
- ?line <<>> = otp_7498_bar(<<>>, 2),
- ?line <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 3),
+ <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 0),
+ <<2,3>> = otp_7498_bar(<<1,2,3>>, 1),
+ <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 2),
+ <<>> = otp_7498_bar(<<>>, 2),
+ <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 3),
ok.
@@ -988,19 +999,19 @@ match_string(Config) when is_list(Config) ->
%% check the coverage for the v3_kernel module.
case erlang:system_info(endian) of
little ->
- ?line do_match_string_native(<<$a,0,$b,0>>);
+ do_match_string_native(<<$a,0,$b,0>>);
big ->
- ?line do_match_string_native(<<0,$a,0,$b>>)
+ do_match_string_native(<<0,$a,0,$b>>)
end,
- ?line do_match_string_big(<<0,$a,0,$b>>),
- ?line do_match_string_little(<<$a,0,$b,0>>),
+ do_match_string_big(<<0,$a,0,$b>>),
+ do_match_string_little(<<$a,0,$b,0>>),
- ?line do_match_string_big_signed(<<255,255>>),
- ?line do_match_string_little_signed(<<255,255>>),
+ do_match_string_big_signed(<<255,255>>),
+ do_match_string_little_signed(<<255,255>>),
- ?line plain = no_match_string_opt(<<"abc">>),
- ?line strange = no_match_string_opt(<<$a:9,$b:9,$c:9>>),
+ plain = no_match_string_opt(<<"abc">>),
+ strange = no_match_string_opt(<<$a:9,$b:9,$c:9>>),
ok.
@@ -1021,13 +1032,13 @@ no_match_string_opt(<<$a:9,$b:9,$c:9>>) -> strange.
%% OTP-7591: A zero-width segment in matching would crash the compiler.
zero_width(Config) when is_list(Config) ->
- ?line <<Len:16/little, Str:Len/binary, 0:0>> = <<2, 0, $h, $i, 0:0>>,
- ?line 2 = Len,
- ?line Str = <<"hi">>,
+ <<Len:16/little, Str:Len/binary, 0:0>> = <<2, 0, $h, $i, 0:0>>,
+ 2 = Len,
+ Str = <<"hi">>,
%% Match sure that values that cannot fit in a segment will not match.
case id(<<0:8>>) of
- <<256:8>> -> ?line ?t:fail();
+ <<256:8>> -> ct:fail(should_not_match);
_ -> ok
end,
ok.
@@ -1036,14 +1047,14 @@ zero_width(Config) when is_list(Config) ->
%% OTP_7650: A invalid size for binary segments could crash the compiler.
bad_size(Config) when is_list(Config) ->
Tuple = {a,b,c},
- ?line {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Tuple>> = id(<<>>)),
+ {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Tuple>> = id(<<>>)),
Binary = <<1,2,3>>,
- ?line {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Binary>> = id(<<>>)),
+ {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Binary>> = id(<<>>)),
ok.
haystack(Config) when is_list(Config) ->
- ?line <<0:10/unit:8>> = haystack_1(<<0:10/unit:8>>),
- ?line [<<0:10/unit:8>>,
+ <<0:10/unit:8>> = haystack_1(<<0:10/unit:8>>),
+ [<<0:10/unit:8>>,
<<0:20/unit:8>>] = haystack_2(<<1:8192>>),
ok.
@@ -1078,10 +1089,10 @@ fc(_, Args, {'EXIT',{{case_clause,ActualArgs},_}})
%% Cover the clause handling bs_context to binary in
%% beam_block:initialized_regs/2.
cover_beam_bool(Config) when is_list(Config) ->
- ?line ok = do_cover_beam_bool(<<>>, 3),
- ?line <<19>> = do_cover_beam_bool(<<19>>, 2),
- ?line <<42>> = do_cover_beam_bool(<<42>>, 1),
- ?line <<17>> = do_cover_beam_bool(<<13,17>>, 0),
+ ok = do_cover_beam_bool(<<>>, 3),
+ <<19>> = do_cover_beam_bool(<<19>>, 2),
+ <<42>> = do_cover_beam_bool(<<42>>, 1),
+ <<17>> = do_cover_beam_bool(<<13,17>>, 0),
ok.
do_cover_beam_bool(Bin, X) when X > 0 ->
@@ -1227,6 +1238,21 @@ match_string_opt(Config) when is_list(Config) ->
do_match_string_opt({<<1>>,{v,V}}=T) ->
{x,V,T}.
+select_on_integer(Config) when is_list(Config) ->
+ 42 = do_select_on_integer(<<42>>),
+ <<"abc">> = do_select_on_integer(<<128,"abc">>),
+
+ {'EXIT',_} = (catch do_select_on_integer(<<0:1>>)),
+ {'EXIT',_} = (catch do_select_on_integer(<<1:1>>)),
+ {'EXIT',_} = (catch do_select_on_integer(<<0:1,0:15>>)),
+ ok.
+
+%% The ASN.1 compiler frequently generates code like this.
+do_select_on_integer(<<0:1,I:7>>) ->
+ I;
+do_select_on_integer(<<1:1,_:7,Bin/binary>>) ->
+ Bin.
+
%% If 'bin_opt_info' was given the warning would lack filename
%% and line number.
@@ -1271,6 +1297,96 @@ do_unsafe_branch_caching(<<Code/integer, Bin/binary>>) ->
_ -> Bin2
end.
+bad_literals(_Config) ->
+ Mod = list_to_atom(?MODULE_STRING ++ "_" ++
+ atom_to_list(?FUNCTION_NAME)),
+ S = [signed_lit_match(V, Sz) || V <- lists:seq(-8, 8),
+ Sz <- [0,1,2,3]] ++
+ [unsigned_lit_match(V, Sz) || V <- lists:seq(-2, 8),
+ Sz <- [0,1,2]] ++
+ [unicode_match(V) ||
+ V <- [-100,-1,0,1,2|lists:seq(16#10FFFC, 16#110004)]],
+ Code = ?Q(["-module('@Mod@').\n"
+ "-export([f/0]).\n"
+ "f() ->\n"
+ "_@S,\n"
+ "ok.\n"]),
+ merl:print(Code),
+ Opts = test_lib:opt_opts(?MODULE),
+ {ok,_} = merl:compile_and_load(Code, Opts),
+ Mod:f(),
+
+ {'EXIT',<<42>>} = (catch bad_literals_1()),
+
+ Sz = id(8),
+ {'EXIT',{{badmatch,_},_}} = (catch <<-1:Sz>> = <<-1>>),
+ ok.
+
+bad_literals_1() ->
+ BadSz = bad,
+ case case <<42>> of
+ <<42:BadSz>> -> ok;
+ Val -> exit(Val)
+ end of
+ ok -> ok;
+ error -> error
+ end.
+
+signed_lit_match(V, Sz) ->
+ case <<V:Sz>> of
+ <<V:Sz/signed>> ->
+ ?Q("<<_@V@:_@Sz@/signed>> = <<_@V@:_@Sz@>>");
+ _ ->
+ ?Q(["case <<_@V@:_@Sz@>> of\n",
+ " <<_@V@:_@Sz@/signed>> ->\n",
+ " ct:fail(should_not_match);\n",
+ " _ ->\n",
+ " ok\n",
+ "end\n"])
+ end.
+
+unsigned_lit_match(V, Sz) ->
+ case <<V:Sz>> of
+ <<V:Sz/unsigned>> ->
+ ?Q("<<_@V@:_@Sz@>> = <<_@V@:_@Sz@>>");
+ _ ->
+ ?Q(["case <<_@V@:_@Sz@>> of\n",
+ " <<_@V@:_@Sz@/unsigned>> ->\n",
+ " ct:fail(should_not_match);\n",
+ " _ ->\n",
+ " ok\n",
+ "end\n"])
+ end.
+
+unicode_match(V) ->
+ try <<V/utf8>> of
+ <<V/utf8>> ->
+ ?Q(["<<_@V@/utf8>> = <<_@V@/utf8>>,\n",
+ "<<_@V@/utf16>> = <<_@V@/utf16>>,\n",
+ "<<_@V@/utf32>> = <<_@V@/utf32>>\n"])
+ catch
+ error:badarg ->
+ ?Q(["case <<_@V@:32>> of\n",
+ " <<_@V@/utf32>> ->\n",
+ " ct:fail(should_not_match);\n",
+ " _ ->\n",
+ " ok\n",
+ "end\n"])
+ end.
+
+%% Test a few legal but rare cases.
+
+good_literals(_Config) ->
+ Sz = id(64),
+
+ %% Variable size.
+ <<42:Sz>> = id(<<42:Sz>>),
+ <<42.0:Sz/float>> = id(<<42:Sz/float>>),
+
+ %% unit > 1
+ <<16#cafebeef:4/unit:8>> = id(<<16#cafebeef:32>>),
+ ok.
+
check(F, R) ->
R = F().
diff --git a/lib/compiler/test/bs_utf_SUITE.erl b/lib/compiler/test/bs_utf_SUITE.erl
index e6d292d9e6..518e89a9cb 100644
--- a/lib/compiler/test/bs_utf_SUITE.erl
+++ b/lib/compiler/test/bs_utf_SUITE.erl
@@ -26,7 +26,7 @@
utf32_roundtrip/1,guard/1,extreme_tripping/1,
literals/1,coverage/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -53,14 +53,14 @@ end_per_group(_GroupName, Config) ->
utf8_roundtrip(Config) when is_list(Config) ->
- ?line [utf8_roundtrip_1(P) || P <- utf_data()],
+ [utf8_roundtrip_1(P) || P <- utf_data()],
ok.
utf8_roundtrip_1({Str,Bin,Bin}) ->
- ?line Str = utf8_to_list(Bin),
- ?line Bin = list_to_utf8(Str),
- ?line [ok = utf8_guard(C, <<42,C/utf8>>) || C <- Str],
- ?line [error = utf8_guard(C, <<C/utf8>>) || C <- Str],
+ Str = utf8_to_list(Bin),
+ Bin = list_to_utf8(Str),
+ [ok = utf8_guard(C, <<42,C/utf8>>) || C <- Str],
+ [error = utf8_guard(C, <<C/utf8>>) || C <- Str],
ok.
utf8_guard(C, Bin) when <<42,C/utf8>> =:= Bin -> ok;
@@ -90,14 +90,14 @@ utf8_len(<<_/utf8,T/binary>>, N) ->
utf8_len(<<>>, N) -> N.
utf16_roundtrip(Config) when is_list(Config) ->
- ?line {Str,Big,Big,Little,Little} = utf16_data(),
- ?line 4 = utf16_big_len(Big),
- ?line 4 = utf16_little_len(Little),
- ?line Str = big_utf16_to_list(Big),
- ?line Str = little_utf16_to_list(Little),
+ {Str,Big,Big,Little,Little} = utf16_data(),
+ 4 = utf16_big_len(Big),
+ 4 = utf16_little_len(Little),
+ Str = big_utf16_to_list(Big),
+ Str = little_utf16_to_list(Little),
- ?line Big = list_to_big_utf16(Str),
- ?line Little = list_to_little_utf16(Str),
+ Big = list_to_big_utf16(Str),
+ Little = list_to_little_utf16(Str),
ok.
@@ -138,14 +138,14 @@ little_utf16_to_list(<<H/little-utf16,T/binary>>) ->
little_utf16_to_list(<<>>) -> [].
utf32_roundtrip(Config) when is_list(Config) ->
- ?line {Str,Big,Big,Little,Little} = utf32_data(),
- ?line 4 = utf32_big_len(Big),
- ?line 4 = utf32_little_len(Little),
- ?line Str = big_utf32_to_list(Big),
- ?line Str = little_utf32_to_list(Little),
+ {Str,Big,Big,Little,Little} = utf32_data(),
+ 4 = utf32_big_len(Big),
+ 4 = utf32_little_len(Little),
+ Str = big_utf32_to_list(Big),
+ Str = little_utf32_to_list(Little),
- ?line Big = list_to_big_utf32(Str),
- ?line Little = list_to_little_utf32(Str),
+ Big = list_to_big_utf32(Str),
+ Little = list_to_little_utf32(Str),
ok.
@@ -187,7 +187,7 @@ little_utf32_to_list(<<>>) -> [].
guard(Config) when is_list(Config) ->
- ?line error = do_guard(16#D800),
+ error = do_guard(16#D800),
ok.
do_guard(C) when byte_size(<<C/utf8>>) =/= 42 -> ok;
@@ -199,13 +199,13 @@ do_guard(_) -> error.
%% the delayed creation of sub-binaries works.
extreme_tripping(Config) when is_list(Config) ->
- ?line Unicode = lists:seq(0, 1024),
- ?line Utf8 = unicode_to_utf8(Unicode, <<>>),
- ?line Utf16 = utf8_to_utf16(Utf8, <<>>),
- ?line Utf32 = utf8_to_utf32(Utf8, <<>>),
- ?line Utf32 = utf16_to_utf32(Utf16, <<>>),
- ?line Utf8 = utf32_to_utf8(Utf32, <<>>),
- ?line Unicode = utf32_to_unicode(Utf32),
+ Unicode = lists:seq(0, 1024),
+ Utf8 = unicode_to_utf8(Unicode, <<>>),
+ Utf16 = utf8_to_utf16(Utf8, <<>>),
+ Utf32 = utf8_to_utf32(Utf8, <<>>),
+ Utf32 = utf16_to_utf32(Utf16, <<>>),
+ Utf8 = utf32_to_utf8(Utf32, <<>>),
+ Unicode = utf32_to_unicode(Utf32),
ok.
unicode_to_utf8([C|T], Bin) ->
@@ -233,58 +233,58 @@ utf32_to_unicode(<<C/utf32,T/binary>>) ->
utf32_to_unicode(<<>>) -> [].
literals(Config) when is_list(Config) ->
- ?line abc_utf8 = match_literal(<<"abc"/utf8>>),
- ?line abc_utf8 = match_literal(<<$a,$b,$c>>),
-
- ?line abc_utf16be = match_literal(<<"abc"/utf16>>),
- ?line abc_utf16be = match_literal(<<$a:16,$b:16,$c:16>>),
- ?line abc_utf16le = match_literal(<<"abc"/little-utf16>>),
- ?line abc_utf16le = match_literal(<<$a:16/little,$b:16/little,$c:16/little>>),
-
- ?line abc_utf32be = match_literal(<<"abc"/utf32>>),
- ?line abc_utf32be = match_literal(<<$a:32,$b:32,$c:32>>),
- ?line abc_utf32le = match_literal(<<"abc"/little-utf32>>),
- ?line abc_utf32le = match_literal(<<$a:32/little,$b:32/little,$c:32/little>>),
-
- ?line bjorn_utf8 = match_literal(<<"bj\366rn"/utf8>>),
- ?line bjorn_utf8 = match_literal(<<$b,$j,195,182,$r,$n>>),
-
- ?line bjorn_utf16be = match_literal(<<"bj\366rn"/utf16>>),
- ?line bjorn_utf16be = match_literal(<<$b:16,$j:16,246:16,$r:16,$n:16>>),
- ?line bjorn_utf16le = match_literal(<<"bj\366rn"/little-utf16>>),
- ?line bjorn_utf16le = match_literal(<<$b:16/little,$j:16/little,
+ abc_utf8 = match_literal(<<"abc"/utf8>>),
+ abc_utf8 = match_literal(<<$a,$b,$c>>),
+
+ abc_utf16be = match_literal(<<"abc"/utf16>>),
+ abc_utf16be = match_literal(<<$a:16,$b:16,$c:16>>),
+ abc_utf16le = match_literal(<<"abc"/little-utf16>>),
+ abc_utf16le = match_literal(<<$a:16/little,$b:16/little,$c:16/little>>),
+
+ abc_utf32be = match_literal(<<"abc"/utf32>>),
+ abc_utf32be = match_literal(<<$a:32,$b:32,$c:32>>),
+ abc_utf32le = match_literal(<<"abc"/little-utf32>>),
+ abc_utf32le = match_literal(<<$a:32/little,$b:32/little,$c:32/little>>),
+
+ bjorn_utf8 = match_literal(<<"bj\366rn"/utf8>>),
+ bjorn_utf8 = match_literal(<<$b,$j,195,182,$r,$n>>),
+
+ bjorn_utf16be = match_literal(<<"bj\366rn"/utf16>>),
+ bjorn_utf16be = match_literal(<<$b:16,$j:16,246:16,$r:16,$n:16>>),
+ bjorn_utf16le = match_literal(<<"bj\366rn"/little-utf16>>),
+ bjorn_utf16le = match_literal(<<$b:16/little,$j:16/little,
246:16/little,$r:16/little,
$n:16/little>>),
- ?line <<244,143,191,191>> = <<16#10ffff/utf8>>,
+ <<244,143,191,191>> = <<16#10ffff/utf8>>,
%% Invalid literals.
I = 0,
- ?line {'EXIT',{badarg,_}} = (catch <<(-1)/utf8,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<(-1)/utf16,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<(-1)/little-utf16,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<(-1)/utf32,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<(-1)/little-utf32,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf8,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf16,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#D800/little-utf16,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf32,I/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<16#D800/little-utf32,I/utf8>>),
+ {'EXIT',{badarg,_}} = (catch <<(-1)/utf8,I/utf8>>),
+ {'EXIT',{badarg,_}} = (catch <<(-1)/utf16,I/utf8>>),
+ {'EXIT',{badarg,_}} = (catch <<(-1)/little-utf16,I/utf8>>),
+ {'EXIT',{badarg,_}} = (catch <<(-1)/utf32,I/utf8>>),
+ {'EXIT',{badarg,_}} = (catch <<(-1)/little-utf32,I/utf8>>),
+ {'EXIT',{badarg,_}} = (catch <<16#D800/utf8,I/utf8>>),
+ {'EXIT',{badarg,_}} = (catch <<16#D800/utf16,I/utf8>>),
+ {'EXIT',{badarg,_}} = (catch <<16#D800/little-utf16,I/utf8>>),
+ {'EXIT',{badarg,_}} = (catch <<16#D800/utf32,I/utf8>>),
+ {'EXIT',{badarg,_}} = (catch <<16#D800/little-utf32,I/utf8>>),
B = 16#10FFFF+1,
- ?line {'EXIT',{badarg,_}} = (catch <<B/utf8>>),
- ?line {'EXIT',{badarg,_}} = (catch <<B/utf16>>),
- ?line {'EXIT',{badarg,_}} = (catch <<B/little-utf16>>),
- ?line {'EXIT',{badarg,_}} = (catch <<B/utf32>>),
- ?line {'EXIT',{badarg,_}} = (catch <<B/little-utf32>>),
+ {'EXIT',{badarg,_}} = (catch <<B/utf8>>),
+ {'EXIT',{badarg,_}} = (catch <<B/utf16>>),
+ {'EXIT',{badarg,_}} = (catch <<B/little-utf16>>),
+ {'EXIT',{badarg,_}} = (catch <<B/utf32>>),
+ {'EXIT',{badarg,_}} = (catch <<B/little-utf32>>),
%% Matching of bad literals.
- ?line error = bad_literal_match(<<237,160,128>>), %16#D800 in UTF-8
- ?line error = bad_literal_match(<<244,144,128,128>>), %16#110000 in UTF-8
+ error = bad_literal_match(<<237,160,128>>), %16#D800 in UTF-8
+ error = bad_literal_match(<<244,144,128,128>>), %16#110000 in UTF-8
- ?line error = bad_literal_match(<<16#D800:32>>),
- ?line error = bad_literal_match(<<16#110000:32>>),
- ?line error = bad_literal_match(<<16#D800:32/little>>),
- ?line error = bad_literal_match(<<16#110000:32/little>>),
+ error = bad_literal_match(<<16#D800:32>>),
+ error = bad_literal_match(<<16#110000:32>>),
+ error = bad_literal_match(<<16#D800:32/little>>),
+ error = bad_literal_match(<<16#110000:32/little>>),
ok.
@@ -307,13 +307,13 @@ bad_literal_match(_) -> error.
coverage(Config) when is_list(Config) ->
%% Cover bit syntax matching optimizations in v3_kernel.
- ?line 0 = coverage_1(<<4096/utf8,65536/utf8,0>>),
- ?line 1 = coverage_1(<<4096/utf8,65536/utf8,1>>),
+ 0 = coverage_1(<<4096/utf8,65536/utf8,0>>),
+ 1 = coverage_1(<<4096/utf8,65536/utf8,1>>),
- ?line 0 = coverage_2(<<4096/utf8,65536/utf8,0>>),
- ?line 1 = coverage_2(<<1024/utf8,1025/utf8,1>>),
+ 0 = coverage_2(<<4096/utf8,65536/utf8,0>>),
+ 1 = coverage_2(<<1024/utf8,1025/utf8,1>>),
- ?line fc(catch coverage_3(1)),
+ fc(catch coverage_3(1)),
%% Cover beam_flatten (combining the heap allocation in
%% a subsequent test_heap instruction into the bs_init2
diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl
index 2715a3aec5..76b7e852f1 100644
--- a/lib/compiler/test/compilation_SUITE.erl
+++ b/lib/compiler/test/compilation_SUITE.erl
@@ -20,11 +20,13 @@
-module(compilation_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-compile(export_all).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,10}}].
all() ->
test_lib:recompile(?MODULE),
@@ -164,11 +166,9 @@ split({int, N}, <<N:16,B:N/binary,T/binary>>) ->
?comp(on_load).
?comp(on_load_inline).
-beam_compiler_7(doc) ->
- "Code snippet submitted from Ulf Wiger which fails in R3 Beam.";
-beam_compiler_7(suite) -> [];
+%% Code snippet submitted from Ulf Wiger which fails in R3 Beam.
beam_compiler_7(Config) when is_list(Config) ->
- ?line done = empty(2, false).
+ done = empty(2, false).
empty(N, Toggle) when N > 0 ->
%% R3 Beam copies the second argument to the first before call.
@@ -194,16 +194,17 @@ redundant_case_1(4) -> d;
redundant_case_1(_) -> d.
failure(Module, Conf) ->
- ?line Src = filename:join(?config(data_dir, Conf), atom_to_list(Module)),
- ?line Out = ?config(priv_dir,Conf),
- ?line io:format("Compiling: ~ts\n", [Src]),
- ?line CompRc = compile:file(Src, [{outdir,Out},return,time]),
- ?line io:format("Result: ~p\n",[CompRc]),
- ?line case CompRc of
- error -> ok;
- {error,Errors,_} -> check_errors(Errors);
- _ -> test_server:fail({no_error, CompRc})
- end,
+ Src = filename:join(proplists:get_value(data_dir, Conf),
+ atom_to_list(Module)),
+ Out = proplists:get_value(priv_dir, Conf),
+ io:format("Compiling: ~ts\n", [Src]),
+ CompRc = compile:file(Src, [{outdir,Out},return,time]),
+ io:format("Result: ~p\n",[CompRc]),
+ case CompRc of
+ error -> ok;
+ {error,Errors,_} -> check_errors(Errors);
+ _ -> ct:fail({no_error, CompRc})
+ end,
ok.
check_errors([{_,Eds}|T]) ->
@@ -224,7 +225,7 @@ check_error_1(Str0) ->
io:format("~s\n", [Str]),
case Str of
"internal"++_=Str ->
- ?t:fail(internal_compiler_error);
+ ct:fail(internal_compiler_error);
_ ->
ok
end.
@@ -234,51 +235,51 @@ check_error_1(Str0) ->
try_it(Module, Conf) ->
%% Change 'false' to 'true' to start a new node for every module.
try_it(false, Module, Conf).
-
+
try_it(StartNode, Module, Conf) ->
- ?line OtherOpts = [], %Can be changed to [time] if needed
- ?line Src = filename:join(?config(data_dir, Conf), atom_to_list(Module)),
- ?line Out = ?config(priv_dir,Conf),
- ?line io:format("Compiling: ~s\n", [Src]),
- ?line CompRc0 = compile:file(Src, [clint,{outdir,Out},report,
+ try_it(StartNode, Module, {minutes,10}, Conf).
+
+try_it(StartNode, Module, Timetrap, Conf) ->
+ OtherOpts = [], %Can be changed to [time] if needed
+ Src = filename:join(proplists:get_value(data_dir, Conf),
+ atom_to_list(Module)),
+ Out = proplists:get_value(priv_dir,Conf),
+ io:format("Compiling: ~s\n", [Src]),
+ CompRc0 = compile:file(Src, [clint,{outdir,Out},report,
bin_opt_info|OtherOpts]),
- ?line io:format("Result: ~p\n",[CompRc0]),
- ?line {ok,_Mod} = CompRc0,
+ io:format("Result: ~p\n",[CompRc0]),
+ {ok,_Mod} = CompRc0,
- ?line Dog = test_server:timetrap(test_server:minutes(10)),
Node = case StartNode of
false ->
node();
true ->
- ?line Pa = "-pa " ++ filename:dirname(code:which(?MODULE)),
- ?line {ok,Node0} = start_node(compiler, Pa),
+ Pa = "-pa " ++ filename:dirname(code:which(?MODULE)),
+ {ok,Node0} = start_node(compiler, Pa),
Node0
end,
- ?line ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]),
- ?line load_and_call(Out, Module),
- ?line test_server:timetrap_cancel(Dog),
+ ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]),
+ load_and_call(Out, Module),
- ?line NewDog = test_server:timetrap(test_server:minutes(10)),
- ?line io:format("Compiling (without optimization): ~s\n", [Src]),
- ?line CompRc1 = compile:file(Src,
+ ct:timetrap(Timetrap),
+ io:format("Compiling (without optimization): ~s\n", [Src]),
+ CompRc1 = compile:file(Src,
[no_copt,no_postopt,{outdir,Out},report|OtherOpts]),
- ?line io:format("Result: ~p\n",[CompRc1]),
- ?line {ok,_Mod} = CompRc1,
- ?line ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]),
- ?line test_server:timetrap_cancel(NewDog),
+ io:format("Result: ~p\n",[CompRc1]),
+ {ok,_Mod} = CompRc1,
+ ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]),
- ?line LastDog = test_server:timetrap(test_server:minutes(10)),
- ?line io:format("Compiling (with old inliner): ~s\n", [Src]),
- ?line CompRc2 = compile:file(Src, [{outdir,Out},report,bin_opt_info,
+ ct:timetrap(Timetrap),
+ io:format("Compiling (with old inliner): ~s\n", [Src]),
+ CompRc2 = compile:file(Src, [{outdir,Out},report,bin_opt_info,
{inline,1000}|OtherOpts]),
- ?line io:format("Result: ~p\n",[CompRc2]),
- ?line {ok,_Mod} = CompRc2,
- ?line ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]),
- ?line test_server:timetrap_cancel(LastDog),
+ io:format("Result: ~p\n",[CompRc2]),
+ {ok,_Mod} = CompRc2,
+ ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]),
- AsmDog = test_server:timetrap(test_server:minutes(10)),
+ ct:timetrap(Timetrap),
io:format("Compiling (from assembly): ~s\n", [Src]),
{ok,_} = compile:file(Src, [to_asm,{outdir,Out},report|OtherOpts]),
Asm = filename:join(Out, lists:concat([Module, ".S"])),
@@ -286,28 +287,26 @@ try_it(StartNode, Module, Conf) ->
io:format("Result: ~p\n",[CompRc3]),
{ok,_} = CompRc3,
ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]),
- test_server:timetrap_cancel(AsmDog),
case StartNode of
false -> ok;
- true -> ?line test_server:stop_node(Node)
+ true -> test_server:stop_node(Node)
end,
- ?line test_server:timetrap_cancel(LastDog),
ok.
load_and_call(Out, Module) ->
- ?line io:format("Loading...\n",[]),
- ?line {module,Module} = code:load_abs(filename:join(Out, Module)),
+ io:format("Loading...\n",[]),
+ {module,Module} = code:load_abs(filename:join(Out, Module)),
- ?line io:format("Calling...\n",[]),
+ io:format("Calling...\n",[]),
%% Call M:M, and expect ok back, that's our interface
- ?line CallRc = Module:Module(),
- ?line io:format("Got value: ~p\n",[CallRc]),
+ CallRc = Module:Module(),
+ io:format("Got value: ~p\n",[CallRc]),
- ?line ok = CallRc,
+ ok = CallRc,
%% Smoke-test of beam disassembler.
- ?line test_lib:smoke_disasm(Module),
+ test_lib:smoke_disasm(Module),
_ = code:delete(Module),
_ = code:purge(Module),
@@ -330,7 +329,7 @@ start_node(Name, Args) ->
{ok, Node} ->
{ok, Node};
Error ->
- ?line test_server:fail(Error)
+ ct:fail(Error)
end.
from(H, [H | T]) -> T;
@@ -338,84 +337,78 @@ from(H, [_ | T]) -> from(H, T);
from(_, []) -> [].
-vsn_1(doc) ->
- "Test generation of 'vsn' attribute";
-vsn_1(suite) -> [];
+%% Test generation of 'vsn' attribute.
vsn_1(Conf) when is_list(Conf) ->
- ?line M = vsn_1,
-
- ?line compile_load(M, ?config(data_dir, Conf), Conf),
- ?line Vsn1 = get_vsn(M),
- ?line timer:sleep(1000),
-
- ?line compile_load(M, ?config(data_dir, Conf), Conf),
- ?line Vsn2 = get_vsn(M),
-
- ?line compile_load(M, filename:join(?config(data_dir, Conf), "other"),
- Conf),
- ?line Vsn3 = get_vsn(M),
- ?line if
- Vsn1 == Vsn2, Vsn2 == Vsn3 ->
- ok;
- true ->
- test_server:fail({vsn, Vsn1, Vsn2, Vsn3})
- end,
+ M = vsn_1,
+
+ compile_load(M, proplists:get_value(data_dir, Conf), Conf),
+ Vsn1 = get_vsn(M),
+ timer:sleep(1000),
+
+ compile_load(M, proplists:get_value(data_dir, Conf), Conf),
+ Vsn2 = get_vsn(M),
+
+ compile_load(M, filename:join(proplists:get_value(data_dir, Conf),
+ "other"),
+ Conf),
+ Vsn3 = get_vsn(M),
+ if
+ Vsn1 == Vsn2, Vsn2 == Vsn3 ->
+ ok;
+ true ->
+ ct:fail({vsn, Vsn1, Vsn2, Vsn3})
+ end,
ok.
-vsn_2(doc) ->
- "Test overriding of generation of 'vsn' attribute";
-vsn_2(suite) -> [];
+%% Test overriding of generation of 'vsn' attribute.
vsn_2(Conf) when is_list(Conf) ->
- ?line M = vsn_2,
-
- ?line compile_load(M, ?config(data_dir, Conf), Conf),
- ?line Vsn = get_vsn(M),
- ?line case Vsn of
- [34] ->
- ok;
- _ ->
- test_server:fail({vsn, Vsn})
- end,
+ M = vsn_2,
+
+ compile_load(M, proplists:get_value(data_dir, Conf), Conf),
+ Vsn = get_vsn(M),
+ case Vsn of
+ [34] ->
+ ok;
+ _ ->
+ ct:fail({vsn, Vsn})
+ end,
ok.
-vsn_3(doc) ->
- "Test that different code yields different generated 'vsn'";
-vsn_3(suite) -> [];
+%% Test that different code yields different generated 'vsn'.
vsn_3(Conf) when is_list(Conf) ->
- ?line M = vsn_3,
-
- ?line compile_load(M, ?config(data_dir, Conf), Conf),
- ?line Vsn1 = get_vsn(M),
-
- ?line compile_load(M, filename:join(?config(data_dir, Conf), "other"),
- Conf),
- ?line Vsn2 = get_vsn(M),
- ?line if
- Vsn1 /= Vsn2 ->
- ok;
- true ->
- test_server:fail({vsn, Vsn1, Vsn2})
- end,
+ M = vsn_3,
+
+ compile_load(M, proplists:get_value(data_dir, Conf), Conf),
+ Vsn1 = get_vsn(M),
+
+ compile_load(M, filename:join(proplists:get_value(data_dir, Conf),
+ "other"),
+ Conf),
+ Vsn2 = get_vsn(M),
+ if
+ Vsn1 /= Vsn2 ->
+ ok;
+ true ->
+ ct:fail({vsn, Vsn1, Vsn2})
+ end,
ok.
get_vsn(M) ->
- {value, {vsn, V}} = lists:keysearch(vsn, 1, M:module_info(attributes)),
+ {vsn,V} = lists:keyfind(vsn, 1, M:module_info(attributes)),
V.
long_string(Config) when is_list(Config) ->
%% The test must complete in one minute - it should be plenty of time.
- ?line Dog = test_server:timetrap(test_server:minutes(1)),
- ?line try_it(long_string, Config),
- ?line test_server:timetrap_cancel(Dog),
+ try_it(false, long_string, {minutes,1}, Config),
ok.
compile_load(Module, Dir, Conf) ->
- ?line Src = filename:join(Dir, atom_to_list(Module)),
- ?line Out = ?config(priv_dir,Conf),
- ?line CompRc = compile:file(Src, [{outdir,Out}]),
- ?line {ok, Module} = CompRc,
- ?line code:purge(Module),
- ?line {module, Module} =
+ Src = filename:join(Dir, atom_to_list(Module)),
+ Out = proplists:get_value(priv_dir,Conf),
+ CompRc = compile:file(Src, [{outdir,Out}]),
+ {ok, Module} = CompRc,
+ code:purge(Module),
+ {module, Module} =
code:load_abs(filename:join(Out, atom_to_list(Module))),
ok.
@@ -428,9 +421,9 @@ self_compile_old_inliner(Config) when is_list(Config) ->
self_compile_1(Config, "old", [verbose,{inline,500}]).
self_compile_1(Config, Prefix, Opts) ->
- Dog = test_server:timetrap(test_server:minutes(40)),
+ ct:timetrap({minutes,40}),
- Priv = ?config(priv_dir,Config),
+ Priv = proplists:get_value(priv_dir,Config),
Version = compiler_version(),
%% Compile the compiler. (In this node to get better coverage.)
@@ -449,11 +442,10 @@ self_compile_1(Config, Prefix, Opts) ->
%% be equal (except for beam_asm that contains the compiler version).
compare_compilers(CompA, CompB),
- test_server:timetrap_cancel(Dog),
ok.
self_compile_node(CompilerDir, OutDir, Version, Opts) ->
- Dog = test_server:timetrap(test_server:minutes(15)),
+ ct:timetrap({minutes,15}),
Pa = "-pa " ++ filename:dirname(code:which(?MODULE)) ++
" -pa " ++ CompilerDir,
Files = compiler_src(),
@@ -462,11 +454,11 @@ self_compile_node(CompilerDir, OutDir, Version, Opts) ->
%% because it will load the same cover-compiled code as on this
%% node. Use a shielded node to prevent the cover server from
%% being started.
- ?t:run_on_shielded_node(
- fun() ->
- compile_compiler(Files, OutDir, Version, Opts)
- end, Pa),
- test_server:timetrap_cancel(Dog),
+ test_server:run_on_shielded_node(
+ fun() ->
+ compile_compiler(Files, OutDir, Version, Opts)
+ end, Pa),
+
ok.
compile_compiler(Files, OutDir, Version, InlineOpts) ->
@@ -619,11 +611,11 @@ otp_7345(ObjRef, _RdEnv, Args) ->
%% Check the generation of the string table.
string_table(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line File = filename:join(DataDir, "string_table.erl"),
- ?line {ok,string_table,Beam,[]} = compile:file(File, [return, binary]),
- ?line {ok,{string_table,[StringTableChunk]}} = beam_lib:chunks(Beam, ["StrT"]),
- ?line {"StrT", <<"stringtable">>} = StringTableChunk,
+ DataDir = proplists:get_value(data_dir, Config),
+ File = filename:join(DataDir, "string_table.erl"),
+ {ok,string_table,Beam,[]} = compile:file(File, [return, binary]),
+ {ok,{string_table,[StringTableChunk]}} = beam_lib:chunks(Beam, ["StrT"]),
+ {"StrT", <<"stringtable">>} = StringTableChunk,
ok.
otp_8949_a(Config) when is_list(Config) ->
@@ -650,8 +642,8 @@ do_otp_8949_a() ->
otp_8949_b(Config) when is_list(Config) ->
self() ! something,
- ?line value = otp_8949_b([], false),
- ?line {'EXIT',_} = (catch otp_8949_b([], true)),
+ value = otp_8949_b([], false),
+ {'EXIT',_} = (catch otp_8949_b([], true)),
ok.
%% Would cause an endless loop in beam_utils.
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index cbdd9ce8cd..b2e9558cba 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -21,7 +21,7 @@
%% Tests compile:file/1 and compile:file/2 with various options.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
@@ -29,7 +29,7 @@
file_1/1, forms_2/1, module_mismatch/1, big_file/1, outdir/1,
binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1,
other_output/1, encrypted_abstr/1,
- bad_record_use1/1, bad_record_use2/1, strict_record/1,
+ strict_record/1,
missing_testheap/1, cover/1, env/1, core/1, asm/1,
sys_pre_attributes/1, dialyzer/1,
warnings/1
@@ -48,13 +48,12 @@ all() ->
[app_test, appup_test, file_1, forms_2, module_mismatch, big_file, outdir,
binary, makedep, cond_and_ifdef, listings, listings_big,
other_output, encrypted_abstr,
- {group, bad_record_use}, strict_record,
+ strict_record,
missing_testheap, cover, env, core, asm,
sys_pre_attributes, dialyzer, warnings].
groups() ->
- [{bad_record_use, [],
- [bad_record_use1, bad_record_use2]}].
+ [].
init_per_suite(Config) ->
Config.
@@ -72,58 +71,55 @@ end_per_group(_GroupName, Config) ->
%% Test that the Application file has no `basic' errors.";
app_test(Config) when is_list(Config) ->
- ?line ?t:app_test(compiler).
+ test_server:app_test(compiler).
%% Test that the Application upgrade file has no `basic' errors.";
appup_test(Config) when is_list(Config) ->
- ok = ?t:appup_test(compiler).
+ ok = test_server:appup_test(compiler).
%% Tests that we can compile and run a simple Erlang program,
%% using compile:file/1.
file_1(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(5)),
-
process_flag(trap_exit, true),
- ?line {Simple, Target} = files(Config, "file_1"),
- ?line {ok, Cwd} = file:get_cwd(),
- ?line ok = file:set_cwd(filename:dirname(Target)),
+ {Simple, Target} = get_files(Config, simple, "file_1"),
+ {ok, Cwd} = file:get_cwd(),
+ ok = file:set_cwd(filename:dirname(Target)),
%% Native from BEAM without compilation info.
- ?line {ok,simple} = compile:file(Simple, [slim]), %Smoke test only.
- ?line {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test.
+ {ok,simple} = compile:file(Simple, [slim]), %Smoke test only.
+ {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test.
%% Native from BEAM with compilation info.
- ?line {ok,simple} = compile:file(Simple), %Smoke test only.
- ?line {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test.
+ {ok,simple} = compile:file(Simple), %Smoke test only.
+ {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test.
- ?line {ok,simple} = compile:file(Simple, [native,report]), %Smoke test.
+ {ok,simple} = compile:file(Simple, [native,report]), %Smoke test.
- ?line compile_and_verify(Simple, Target, []),
- ?line compile_and_verify(Simple, Target, [native]),
- ?line compile_and_verify(Simple, Target, [debug_info]),
- ?line {ok,simple} = compile:file(Simple, [no_line_info]), %Coverage
+ compile_and_verify(Simple, Target, []),
+ compile_and_verify(Simple, Target, [native]),
+ compile_and_verify(Simple, Target, [debug_info]),
+ {ok,simple} = compile:file(Simple, [no_line_info]), %Coverage
{ok,simple} = compile:file(Simple, [{eprof,beam_z}]), %Coverage
- ?line ok = file:set_cwd(Cwd),
- ?line true = exists(Target),
- ?line passed = run(Target, test, []),
+ ok = file:set_cwd(Cwd),
+ true = exists(Target),
+ passed = run(Target, test, []),
%% Cleanup.
- ?line ok = file:delete(Target),
- ?line ok = file:del_dir(filename:dirname(Target)),
+ ok = file:delete(Target),
+ ok = file:del_dir(filename:dirname(Target)),
%% There should not be any messages in the messages.
receive
Any ->
- ?t:fail({unexpected,Any})
+ ct:fail({unexpected,Any})
after 10 ->
ok
end,
- ?line test_server:timetrap_cancel(Dog),
ok.
forms_2(Config) when is_list(Config) ->
@@ -147,121 +143,110 @@ forms_2(Config) when is_list(Config) ->
ok.
module_mismatch(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line File = filename:join(DataDir, "wrong_module_name.erl"),
+ DataDir = proplists:get_value(data_dir, Config),
+ File = filename:join(DataDir, "wrong_module_name.erl"),
{error,[{"wrong_module_name.beam",
[{none,compile,{module_name,arne,"wrong_module_name"}}]}],
[]} = compile:file(File, [return]),
- ?line error = compile:file(File, [report]),
+ error = compile:file(File, [report]),
- ?line {ok,arne,[]} = compile:file(File,
+ {ok,arne,[]} = compile:file(File,
[return,no_error_module_mismatch]),
ok.
big_file(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(5)),
- ?line DataDir = ?config(data_dir, Config),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Big = filename:join(DataDir, "big.erl"),
- ?line Target = filename:join(PrivDir, "big.beam"),
- ?line ok = file:set_cwd(PrivDir),
- ?line compile_and_verify(Big, Target, []),
- ?line compile_and_verify(Big, Target, [debug_info]),
- ?line compile_and_verify(Big, Target, [no_postopt]),
+ {Big,Target} = get_files(Config, big, "big_file"),
+ ok = file:set_cwd(filename:dirname(Target)),
+ compile_and_verify(Big, Target, []),
+ compile_and_verify(Big, Target, [debug_info]),
+ compile_and_verify(Big, Target, [no_postopt]),
%% Cleanup.
- ?line ok = file:delete(Target),
- ?line test_server:timetrap_cancel(Dog),
+ ok = file:delete(Target),
ok.
%% Tests that the {outdir, Dir} option works.
outdir(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(60)),
- ?line {Simple, Target} = files(Config, "outdir"),
- ?line {ok, simple} = compile:file(Simple, [{outdir, filename:dirname(Target)}]),
- ?line true = exists(Target),
- ?line passed = run(Target, test, []),
- ?line ok = file:delete(Target),
- ?line ok = file:del_dir(filename:dirname(Target)),
- ?line test_server:timetrap_cancel(Dog),
+ {Simple, Target} = get_files(Config, simple, "outdir"),
+ {ok, simple} = compile:file(Simple, [{outdir, filename:dirname(Target)}]),
+ true = exists(Target),
+ passed = run(Target, test, []),
+ ok = file:delete(Target),
+ ok = file:del_dir(filename:dirname(Target)),
ok.
%% Tests that the binary option works.
binary(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(60)),
- ?line {Simple, Target} = files(Config, "binary"),
- ?line {ok, simple, Binary} = compile:file(Simple, [binary]),
- ?line code:load_binary(simple, Target, Binary),
- ?line passed = simple:test(),
- ?line true = code:delete(simple),
- ?line false = code:purge(simple),
- ?line ok = file:del_dir(filename:dirname(Target)),
- ?line test_server:timetrap_cancel(Dog),
+ {Simple, Target} = get_files(Config, simple, "binary"),
+ {ok, simple, Binary} = compile:file(Simple, [binary]),
+ code:load_binary(simple, Target, Binary),
+ passed = simple:test(),
+ true = code:delete(simple),
+ false = code:purge(simple),
+ ok = file:del_dir(filename:dirname(Target)),
ok.
%% Tests that the dependencies-Makefile-related options work.
makedep(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(60)),
- ?line {Simple,Target} = files(Config, "makedep"),
- ?line DataDir = ?config(data_dir, Config),
- ?line SimpleRootname = filename:rootname(Simple),
- ?line IncludeDir = filename:join(filename:dirname(Simple), "include"),
- ?line IncludeOptions = [
- {d,need_foo},
- {d,foo_value,42},
- {d,include_generated},
- {i,IncludeDir}
- ],
+ {Simple,Target} = get_files(Config, simple, "makedep"),
+ DataDir = proplists:get_value(data_dir, Config),
+ SimpleRootname = filename:rootname(Simple),
+ IncludeDir = filename:join(filename:dirname(Simple), "include"),
+ IncludeOptions = [
+ {d,need_foo},
+ {d,foo_value,42},
+ {d,include_generated},
+ {i,IncludeDir}
+ ],
%% Basic rule.
- ?line BasicMf1Name = SimpleRootname ++ "-basic1.mk",
- ?line {ok,BasicMf1} = file:read_file(BasicMf1Name),
- ?line {ok,_,Mf1} = compile:file(Simple, [binary,makedep]),
- ?line BasicMf1 = makedep_canonicalize_result(Mf1, DataDir),
+ BasicMf1Name = SimpleRootname ++ "-basic1.mk",
+ {ok,BasicMf1} = file:read_file(BasicMf1Name),
+ {ok,_,Mf1} = compile:file(Simple, [binary,makedep]),
+ BasicMf1 = makedep_canonicalize_result(Mf1, DataDir),
%% Basic rule with one existing header.
- ?line BasicMf2Name = SimpleRootname ++ "-basic2.mk",
- ?line {ok,BasicMf2} = file:read_file(BasicMf2Name),
- ?line {ok,_,Mf2} = compile:file(Simple, [binary,makedep|IncludeOptions]),
- ?line BasicMf2 = makedep_canonicalize_result(Mf2, DataDir),
+ BasicMf2Name = SimpleRootname ++ "-basic2.mk",
+ {ok,BasicMf2} = file:read_file(BasicMf2Name),
+ {ok,_,Mf2} = compile:file(Simple, [binary,makedep|IncludeOptions]),
+ BasicMf2 = makedep_canonicalize_result(Mf2, DataDir),
%% Rule with one existing header and one missing header.
- ?line MissingMfName = SimpleRootname ++ "-missing.mk",
- ?line {ok,MissingMf} = file:read_file(MissingMfName),
- ?line {ok,_,Mf3} = compile:file(Simple,
+ MissingMfName = SimpleRootname ++ "-missing.mk",
+ {ok,MissingMf} = file:read_file(MissingMfName),
+ {ok,_,Mf3} = compile:file(Simple,
[binary,makedep,makedep_add_missing|IncludeOptions]),
- ?line MissingMf = makedep_canonicalize_result(Mf3, DataDir),
+ MissingMf = makedep_canonicalize_result(Mf3, DataDir),
%% Rule with modified target.
- ?line TargetMf1Name = SimpleRootname ++ "-target1.mk",
- ?line {ok,TargetMf1} = file:read_file(TargetMf1Name),
- ?line {ok,_,Mf4} = compile:file(Simple,
+ TargetMf1Name = SimpleRootname ++ "-target1.mk",
+ {ok,TargetMf1} = file:read_file(TargetMf1Name),
+ {ok,_,Mf4} = compile:file(Simple,
[binary,makedep,{makedep_target,"$target"}|IncludeOptions]),
- ?line TargetMf1 = makedep_modify_target(
+ TargetMf1 = makedep_modify_target(
makedep_canonicalize_result(Mf4, DataDir), "$$target"),
%% Rule with quoted modified target.
- ?line TargetMf2Name = SimpleRootname ++ "-target2.mk",
- ?line {ok,TargetMf2} = file:read_file(TargetMf2Name),
- ?line {ok,_,Mf5} = compile:file(Simple,
+ TargetMf2Name = SimpleRootname ++ "-target2.mk",
+ {ok,TargetMf2} = file:read_file(TargetMf2Name),
+ {ok,_,Mf5} = compile:file(Simple,
[binary,makedep,{makedep_target,"$target"},makedep_quote_target|
IncludeOptions]),
- ?line TargetMf2 = makedep_modify_target(
+ TargetMf2 = makedep_modify_target(
makedep_canonicalize_result(Mf5, DataDir), "$$target"),
%% Basic rule written to some file.
- ?line {ok,_} = compile:file(Simple,
+ {ok,_} = compile:file(Simple,
[makedep,{makedep_output,Target}|IncludeOptions]),
- ?line {ok,Mf6} = file:read_file(Target),
- ?line BasicMf2 = makedep_canonicalize_result(Mf6, DataDir),
+ {ok,Mf6} = file:read_file(Target),
+ BasicMf2 = makedep_canonicalize_result(Mf6, DataDir),
%% Rule with creating phony target.
- ?line PhonyMfName = SimpleRootname ++ "-phony.mk",
- ?line {ok,PhonyMf} = file:read_file(PhonyMfName),
- ?line {ok,_,Mf7} = compile:file(Simple,
+ PhonyMfName = SimpleRootname ++ "-phony.mk",
+ {ok,PhonyMf} = file:read_file(PhonyMfName),
+ {ok,_,Mf7} = compile:file(Simple,
[binary,makedep,makedep_phony|IncludeOptions]),
- ?line PhonyMf = makedep_canonicalize_result(Mf7, DataDir),
+ PhonyMf = makedep_canonicalize_result(Mf7, DataDir),
- ?line ok = file:delete(Target),
- ?line ok = file:del_dir(filename:dirname(Target)),
- ?line test_server:timetrap_cancel(Dog),
+ ok = file:delete(Target),
+ ok = file:del_dir(filename:dirname(Target)),
ok.
makedep_canonicalize_result(Mf, DataDir) ->
@@ -281,30 +266,26 @@ makedep_modify_target(Mf, Target) ->
%% Tests that conditional compilation, defining values, including files work.
cond_and_ifdef(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(60)),
- ?line {Simple, Target} = files(Config, "cond_and_ifdef"),
- ?line IncludeDir = filename:join(filename:dirname(Simple), "include"),
- ?line Options = [{outdir, filename:dirname(Target)},
+ {Simple, Target} = get_files(Config, simple, "cond_and_ifdef"),
+ IncludeDir = filename:join(filename:dirname(Simple), "include"),
+ Options = [{outdir, filename:dirname(Target)},
{d, need_foo}, {d, foo_value, 42},
{i, IncludeDir}, report],
- ?line {ok, simple} = compile:file(Simple, Options),
- ?line true = exists(Target),
- ?line {hiker, 42} = run(Target, foo, []),
- ?line ok = file:delete(Target),
- ?line ok = file:del_dir(filename:dirname(Target)),
- ?line test_server:timetrap_cancel(Dog),
+ {ok, simple} = compile:file(Simple, Options),
+ true = exists(Target),
+ {hiker, 42} = run(Target, foo, []),
+ ok = file:delete(Target),
+ ok = file:del_dir(filename:dirname(Target)),
ok.
listings(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:minutes(8)),
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ok = do_file_listings(DataDir, PrivDir, [
"simple",
"small",
"small_maps"
]),
- test_server:timetrap_cancel(Dog),
ok.
do_file_listings(_, _, []) -> ok;
@@ -330,6 +311,8 @@ do_file_listings(DataDir, PrivDir, [File|Files]) ->
do_listing(Simple, TargetDir, dlife, ".life"),
do_listing(Simple, TargetDir, dcg, ".codegen"),
do_listing(Simple, TargetDir, dblk, ".block"),
+ do_listing(Simple, TargetDir, dexcept, ".except"),
+ do_listing(Simple, TargetDir, dbs, ".bs"),
do_listing(Simple, TargetDir, dbool, ".bool"),
do_listing(Simple, TargetDir, dtype, ".type"),
do_listing(Simple, TargetDir, ddead, ".dead"),
@@ -359,159 +342,146 @@ do_file_listings(DataDir, PrivDir, [File|Files]) ->
do_file_listings(DataDir,PrivDir,Files).
listings_big(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(10)),
- ?line DataDir = ?config(data_dir, Config),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Big = filename:join(DataDir, big),
- ?line TargetDir = filename:join(PrivDir, listings_big),
- ?line ok = file:make_dir(TargetDir),
- ?line do_listing(Big, TargetDir, 'S'),
- ?line do_listing(Big, TargetDir, 'E'),
- ?line do_listing(Big, TargetDir, 'P'),
- ?line do_listing(Big, TargetDir, dkern, ".kernel"),
-
- ?line Target = filename:join(TargetDir, big),
- {ok,big} = compile:file(Target, [from_asm,{outdir,TargetDir}]),
+ {Big,Target} = get_files(Config, big, listings_big),
+ TargetDir = filename:dirname(Target),
+ do_listing(Big, TargetDir, 'S'),
+ do_listing(Big, TargetDir, 'E'),
+ do_listing(Big, TargetDir, 'P'),
+ do_listing(Big, TargetDir, dkern, ".kernel"),
+
+ TargetNoext = filename:rootname(Target, code:objfile_extension()),
+ {ok,big} = compile:file(TargetNoext, [from_asm,{outdir,TargetDir}]),
%% Cleanup.
- ?line ok = file:delete(Target ++ ".beam"),
- ?line lists:foreach(fun(F) -> ok = file:delete(F) end,
- filelib:wildcard(filename:join(TargetDir, "*"))),
- ?line ok = file:del_dir(TargetDir),
- ?line test_server:timetrap_cancel(Dog),
+ ok = file:delete(Target),
+ lists:foreach(fun(F) -> ok = file:delete(F) end,
+ filelib:wildcard(filename:join(TargetDir, "*"))),
+ ok = file:del_dir(TargetDir),
ok.
other_output(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(8)),
- ?line DataDir = ?config(data_dir, Config),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Simple = filename:join(DataDir, simple),
- ?line TargetDir = filename:join(PrivDir, other_output),
- ?line ok = file:make_dir(TargetDir),
+ {Simple,_Target} = get_files(Config, simple, "other_output"),
io:put_chars("to_pp"),
- ?line {ok,[],PP} = compile:file(Simple, [to_pp,binary,time]),
- ?line [] = [E || E <- PP,
- begin
- case element(1, E) of
- attribute -> false;
- function -> false;
- eof -> false
- end
- end],
+ {ok,[],PP} = compile:file(Simple, [to_pp,binary,time]),
+ [] = [E || E <- PP,
+ begin
+ case element(1, E) of
+ attribute -> false;
+ function -> false;
+ eof -> false
+ end
+ end],
io:put_chars("to_exp (file)"),
- ?line {ok,simple,Expand} = compile:file(Simple, [to_exp,binary,time]),
- ?line case Expand of
- {simple,Exports,Forms} when is_list(Exports), is_list(Forms) -> ok
- end,
+ {ok,simple,Expand} = compile:file(Simple, [to_exp,binary,time]),
+ case Expand of
+ {simple,Exports,Forms} when is_list(Exports), is_list(Forms) -> ok
+ end,
io:put_chars("to_exp (forms)"),
- ?line {ok,simple,Expand} = compile:forms(PP, [to_exp,binary,time]),
+ {ok,simple,Expand} = compile:forms(PP, [to_exp,binary,time]),
io:put_chars("to_core (file)"),
- ?line {ok,simple,Core} = compile:file(Simple, [to_core,binary,time]),
- ?line c_module = element(1, Core),
- ?line {ok,_} = core_lint:module(Core),
+ {ok,simple,Core} = compile:file(Simple, [to_core,binary,time]),
+ c_module = element(1, Core),
+ {ok,_} = core_lint:module(Core),
io:put_chars("to_core (forms)"),
- ?line {ok,simple,Core} = compile:forms(PP, [to_core,binary,time]),
+ {ok,simple,Core} = compile:forms(PP, [to_core,binary,time]),
io:put_chars("to_kernel (file)"),
- ?line {ok,simple,Kernel} = compile:file(Simple, [to_kernel,binary,time]),
- ?line k_mdef = element(1, Kernel),
+ {ok,simple,Kernel} = compile:file(Simple, [to_kernel,binary,time]),
+ k_mdef = element(1, Kernel),
io:put_chars("to_kernel (forms)"),
- ?line {ok,simple,Kernel} = compile:forms(PP, [to_kernel,binary,time]),
+ {ok,simple,Kernel} = compile:forms(PP, [to_kernel,binary,time]),
io:put_chars("to_asm (file)"),
- ?line {ok,simple,Asm} = compile:file(Simple, [to_asm,binary,time]),
- ?line {simple,_,_,_,_} = Asm,
+ {ok,simple,Asm} = compile:file(Simple, [to_asm,binary,time]),
+ {simple,_,_,_,_} = Asm,
io:put_chars("to_asm (forms)"),
- ?line {ok,simple,Asm} = compile:forms(PP, [to_asm,binary,time]),
+ {ok,simple,Asm} = compile:forms(PP, [to_asm,binary,time]),
- ?line test_server:timetrap_cancel(Dog),
ok.
encrypted_abstr(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(10)),
- ?line {Simple,Target} = files(Config, "encrypted_abstr"),
+ {Simple,Target} = get_files(Config, simple, "encrypted_abstr"),
Res = case has_crypto() of
false ->
%% No crypto.
- ?line encrypted_abstr_no_crypto(Simple, Target),
+ encrypted_abstr_no_crypto(Simple, Target),
{comment,"The crypto application is missing or broken"};
true ->
%% Simulate not having crypto by removing
%% the crypto application from the path.
- ?line OldPath = code:get_path(),
+ OldPath = code:get_path(),
try
- ?line NewPath = OldPath -- [filename:dirname(code:which(crypto))],
- ?line (catch crypto:stop()),
- ?line code:delete(crypto),
- ?line code:purge(crypto),
- ?line code:set_path(NewPath),
- ?line encrypted_abstr_no_crypto(Simple, Target)
+ NewPath = OldPath -- [filename:dirname(code:which(crypto))],
+ (catch crypto:stop()),
+ code:delete(crypto),
+ code:purge(crypto),
+ code:set_path(NewPath),
+ encrypted_abstr_no_crypto(Simple, Target)
after
code:set_path(OldPath)
end,
%% Now run the tests that require crypto.
- ?line encrypted_abstr_1(Simple, Target),
- ?line ok = file:delete(Target),
- ?line ok = file:del_dir(filename:dirname(Target))
+ encrypted_abstr_1(Simple, Target),
+ ok = file:delete(Target),
+ ok = file:del_dir(filename:dirname(Target))
end,
%% Cleanup.
- ?line test_server:timetrap_cancel(Dog),
Res.
encrypted_abstr_1(Simple, Target) ->
- ?line TargetDir = filename:dirname(Target),
- ?line Key = "ablurf123BX#$;3",
- ?line install_crypto_key(Key),
- ?line {ok,simple} = compile:file(Simple,
+ TargetDir = filename:dirname(Target),
+ Key = "ablurf123BX#$;3",
+ install_crypto_key(Key),
+ {ok,simple} = compile:file(Simple,
[debug_info,{debug_info_key,Key},
{outdir,TargetDir}]),
- ?line verify_abstract(Target),
+ verify_abstract(Target),
- ?line {ok,simple} = compile:file(Simple,
+ {ok,simple} = compile:file(Simple,
[{debug_info_key,Key},
{outdir,TargetDir}]),
- ?line verify_abstract(Target),
+ verify_abstract(Target),
- ?line {ok,simple} = compile:file(Simple,
+ {ok,simple} = compile:file(Simple,
[debug_info,{debug_info_key,{des3_cbc,Key}},
{outdir,TargetDir}]),
- ?line verify_abstract(Target),
+ verify_abstract(Target),
- ?line {ok,{simple,[{compile_info,CInfo}]}} =
+ {ok,{simple,[{compile_info,CInfo}]}} =
beam_lib:chunks(Target, [compile_info]),
- ?line {value,{_,Opts}} = lists:keysearch(options, 1, CInfo),
- ?line {value,{_,'********'}} = lists:keysearch(debug_info_key, 1, Opts),
+ {_,Opts} = lists:keyfind(options, 1, CInfo),
+ {_,'********'} = lists:keyfind(debug_info_key, 1, Opts),
%% Try some illegal forms of crypto keys.
- ?line error = compile:file(Simple,
+ error = compile:file(Simple,
[debug_info,{debug_info_key,{blurf,"ss"}},report]),
- ?line error = compile:file(Simple,
+ error = compile:file(Simple,
[debug_info,{debug_info_key,{blurf,1,"ss"}},report]),
- ?line error = compile:file(Simple,
+ error = compile:file(Simple,
[debug_info,{debug_info_key,42},report]),
%% Place the crypto key in .erlang.crypt.
- ?line beam_lib:clear_crypto_key_fun(),
- ?line {ok,OldCwd} = file:get_cwd(),
- ?line ok = file:set_cwd(TargetDir),
-
- ?line error = compile:file(Simple, [encrypt_debug_info,report]),
-
- ?line NewKey = "better use another key here",
- ?line write_crypt_file(["[{debug_info,des3_cbc,simple,\"",NewKey,"\"}].\n"]),
- ?line {ok,simple} = compile:file(Simple, [encrypt_debug_info,report]),
- ?line verify_abstract("simple.beam"),
- ?line ok = file:delete(".erlang.crypt"),
- ?line beam_lib:clear_crypto_key_fun(),
- ?line {error,beam_lib,{key_missing_or_invalid,"simple.beam",abstract_code}} =
+ beam_lib:clear_crypto_key_fun(),
+ {ok,OldCwd} = file:get_cwd(),
+ ok = file:set_cwd(TargetDir),
+
+ error = compile:file(Simple, [encrypt_debug_info,report]),
+
+ NewKey = "better use another key here",
+ write_crypt_file(["[{debug_info,des3_cbc,simple,\"",NewKey,"\"}].\n"]),
+ {ok,simple} = compile:file(Simple, [encrypt_debug_info,report]),
+ verify_abstract("simple.beam"),
+ ok = file:delete(".erlang.crypt"),
+ beam_lib:clear_crypto_key_fun(),
+ {error,beam_lib,{key_missing_or_invalid,"simple.beam",abstract_code}} =
beam_lib:chunks("simple.beam", [abstract_code]),
- ?line ok = file:set_cwd(OldCwd),
+ ok = file:set_cwd(OldCwd),
%% Test key compatibility by reading a BEAM file produced before
%% the update to the new crypto functions.
@@ -532,9 +502,9 @@ write_crypt_file(Contents0) ->
encrypted_abstr_no_crypto(Simple, Target) ->
io:format("simpe: ~p~n", [Simple]),
- ?line TargetDir = filename:dirname(Target),
- ?line Key = "ablurf123BX#$;3",
- ?line error = compile:file(Simple,
+ TargetDir = filename:dirname(Target),
+ Key = "ablurf123BX#$;3",
+ error = compile:file(Simple,
[debug_info,{debug_info_key,Key},
{outdir,TargetDir},report]),
ok.
@@ -562,7 +532,7 @@ install_crypto_key(Key) ->
%% Miscellanous tests, mainly to get better coverage.
cover(Config) when is_list(Config) ->
- ?line io:format("~p\n", [compile:options()]),
+ io:format("~p\n", [compile:options()]),
ok.
do_listing(Source, TargetDir, Type) ->
@@ -573,31 +543,31 @@ do_listing(Source, TargetDir, Type, Ext) ->
[Source, TargetDir, Type, Ext]),
case compile:file(Source, [Type, time, {outdir, TargetDir}]) of
{ok, _} -> ok;
- Other -> test_server:fail({unexpected_result, Other})
+ Other -> ct:fail({unexpected_result, Other})
end,
SourceBase = filename:rootname(filename:basename(Source)),
Target = filename:join(TargetDir, SourceBase ++ Ext),
true = exists(Target).
-files(Config, Name) ->
- ?line code:delete(simple),
- ?line code:purge(simple),
- ?line DataDir = ?config(data_dir, Config),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Simple = filename:join(DataDir, "simple"),
- ?line TargetDir = filename:join(PrivDir, Name),
- ?line ok = file:make_dir(TargetDir),
- ?line Target = filename:join(TargetDir, "simple"++code:objfile_extension()),
- {Simple, Target}.
-
+get_files(Config, Module, OutputName) ->
+ code:delete(Module),
+ code:purge(Module),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Src = filename:join(DataDir, atom_to_list(Module)),
+ TargetDir = filename:join(PrivDir, OutputName),
+ ok = file:make_dir(TargetDir),
+ File = atom_to_list(Module) ++ code:objfile_extension(),
+ Target = filename:join(TargetDir, File),
+ {Src, Target}.
run(Target, Func, Args) ->
- ?line Module = list_to_atom(filename:rootname(filename:basename(Target))),
- ?line {module, Module} = code:load_abs(filename:rootname(Target)),
- ?line Result = (catch apply(Module, Func, Args)),
- ?line true = code:delete(Module),
- ?line false = code:purge(Module),
+ Module = list_to_atom(filename:rootname(filename:basename(Target))),
+ {module, Module} = code:load_abs(filename:rootname(Target)),
+ Result = (catch apply(Module, Func, Args)),
+ true = code:delete(Module),
+ false = code:purge(Module),
Result.
exists(Name) ->
@@ -607,49 +577,27 @@ exists(Name) ->
end.
-%% Tests that the compiler does not accept
-%% bad use of records.
-bad_record_use1(Config) when is_list(Config) ->
- ?line {ok, Cwd} = file:get_cwd(),
- ?line file:set_cwd(?config(data_dir, Config)),
- ?line true=exists("bad_record_use.erl"),
- ?line Ret=c:c(bad_record_use),
- ?line file:set_cwd(Cwd),
- ?line error=Ret,
- ok.
-
-%% Tests that the compiler does not accept
-%% bad use of records.
-bad_record_use2(Config) when is_list(Config) ->
- ?line {ok, Cwd} = file:get_cwd(),
- ?line file:set_cwd(?config(data_dir, Config)),
- ?line true=exists("bad_record_use2.erl"),
- ?line Ret=c:c(bad_record_use),
- ?line file:set_cwd(Cwd),
- ?line error=Ret,
- ok.
-
strict_record(Config) when is_list(Config) ->
- ?line Priv = ?config(priv_dir, Config),
- ?line file:set_cwd(?config(data_dir, Config)),
- ?line Opts = [{outdir,Priv},report_errors],
+ Priv = proplists:get_value(priv_dir, Config),
+ ok = file:set_cwd(proplists:get_value(data_dir, Config)),
+ Opts = [{outdir,Priv},report_errors],
M = record_access,
- ?line {ok,M} = c:c(M, [strict_record_tests|Opts]),
- ?line Turtle = test_strict(),
+ {ok,M} = c:c(M, [strict_record_tests|Opts]),
+ Turtle = test_strict(),
- ?line {ok,M} = c:c(M, [no_strict_record_tests|Opts]),
- ?line Turtle = test_sloppy(),
+ {ok,M} = c:c(M, [no_strict_record_tests|Opts]),
+ Turtle = test_sloppy(),
%% The option first given wins.
- ?line {ok,M} = c:c(M, [no_strict_record_tests,strict_record_tests|Opts]),
- ?line Turtle = test_sloppy(),
- ?line {ok,M} = c:c(M, [strict_record_tests,no_strict_record_tests|Opts]),
- ?line Turtle = test_strict(),
+ {ok,M} = c:c(M, [no_strict_record_tests,strict_record_tests|Opts]),
+ Turtle = test_sloppy(),
+ {ok,M} = c:c(M, [strict_record_tests,no_strict_record_tests|Opts]),
+ Turtle = test_strict(),
%% Default (possibly influenced by ERL_COMPILER_OPTIONS).
- ?line {ok,M} = c:c(M, [{outdir,Priv},report_errors]),
- ?line try
+ {ok,M} = c:c(M, [{outdir,Priv},report_errors]),
+ try
{1,2} = record_access:test(Turtle),
{comment,"Default: no_strict_record_tests"}
catch
@@ -659,7 +607,7 @@ strict_record(Config) when is_list(Config) ->
test_strict() ->
Turtle = record_access:turtle(),
- ?line try
+ try
record_access:test(Turtle)
catch
error:{badrecord,tortoise} ->
@@ -673,19 +621,19 @@ test_sloppy() ->
Turtle.
missing_testheap(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Opts = [{outdir,PrivDir}],
OldPath = code:get_path(),
try
code:add_patha(PrivDir),
c:c(filename:join(DataDir, "missing_testheap1"), Opts),
c:c(filename:join(DataDir, "missing_testheap2"), Opts),
- ?line ok = test(fun() ->
- missing_testheap1:f({a,self()},{state,true,b})
- end, {a,b}),
- ?line ok = test(fun() ->
- missing_testheap2:f({a,self()},16#80000000) end,
+ ok = test(fun() ->
+ missing_testheap1:f({a,self()},{state,true,b})
+ end, {a,b}),
+ ok = test(fun() ->
+ missing_testheap2:f({a,self()},16#80000000) end,
bigger)
after
code:set_path(OldPath),
@@ -706,47 +654,47 @@ test(Iter, Fun, Result, Filler) ->
test(Iter-1, Fun, Result, [0|Filler]);
{result, Other} ->
io:format("Expected ~p; got ~p~n", [Result, Other]),
- test_server:fail()
+ ct:fail(failed)
end.
init(ReplyTo, Fun, _Filler) ->
ReplyTo ! {result, Fun()}.
env(Config) when is_list(Config) ->
- ?line {Simple,Target} = files(Config, "file_1"),
- ?line {ok,Cwd} = file:get_cwd(),
- ?line ok = file:set_cwd(filename:dirname(Target)),
+ {Simple,Target} = get_files(Config, simple, env),
+ {ok,Cwd} = file:get_cwd(),
+ ok = file:set_cwd(filename:dirname(Target)),
true = os:putenv("ERL_COMPILER_OPTIONS", "binary"),
try
env_1(Simple, Target)
after
true = os:putenv("ERL_COMPILER_OPTIONS", "ignore_me"),
- file:set_cwd(Cwd),
- file:delete(Target),
- file:del_dir(filename:dirname(Target))
+ file:set_cwd(Cwd),
+ file:delete(Target),
+ file:del_dir(filename:dirname(Target))
end,
ok.
env_1(Simple, Target) ->
%% file
- ?line {ok,simple,<<_/binary>>} = compile:file(Simple),
- ?line {ok,simple} = compile:noenv_file(Simple, [debug_info]),
- ?line true = exists(Target),
- ?line {ok,{simple,[{abstract_code,Abstr0}]}} =
+ {ok,simple,<<_/binary>>} = compile:file(Simple),
+ {ok,simple} = compile:noenv_file(Simple, [debug_info]),
+ true = exists(Target),
+ {ok,{simple,[{abstract_code,Abstr0}]}} =
beam_lib:chunks(Target, [abstract_code]),
- ?line {raw_abstract_v1,Forms} = Abstr0,
+ {raw_abstract_v1,Forms} = Abstr0,
%% forms
- ?line true = os:putenv("ERL_COMPILER_OPTIONS", "strong_validation"),
- ?line {ok,simple} = compile:forms(Forms),
- ?line {ok,simple,<<"FOR1",_/binary>>} = compile:noenv_forms(Forms, []),
+ true = os:putenv("ERL_COMPILER_OPTIONS", "strong_validation"),
+ {ok,simple} = compile:forms(Forms),
+ {ok,simple,<<"FOR1",_/binary>>} = compile:noenv_forms(Forms, []),
%% output_generated
- ?line false = compile:output_generated([]),
- ?line true = compile:noenv_output_generated([]),
+ false = compile:output_generated([]),
+ true = compile:noenv_output_generated([]),
- ?line ok = file:delete(Target),
+ ok = file:delete(Target),
ok.
@@ -754,7 +702,7 @@ env_1(Simple, Target) ->
%% compile the generated Core Erlang files.
core(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Outdir = filename:join(PrivDir, "core"),
ok = file:make_dir(Outdir),
@@ -817,15 +765,13 @@ compile_forms(Forms, Opts) ->
%% run .S through the compiler again.
asm(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(20)),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Outdir = filename:join(PrivDir, "asm"),
- ?line ok = file:make_dir(Outdir),
-
- ?line Wc = filename:join(filename:dirname(code:which(?MODULE)), "*.beam"),
- ?line TestBeams = filelib:wildcard(Wc),
- ?line Res = test_lib:p_run(fun(F) -> do_asm(F, Outdir) end, TestBeams),
- ?line test_server:timetrap_cancel(Dog),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Outdir = filename:join(PrivDir, "asm"),
+ ok = file:make_dir(Outdir),
+
+ Wc = filename:join(filename:dirname(code:which(?MODULE)), "*.beam"),
+ TestBeams = filelib:wildcard(Wc),
+ Res = test_lib:p_run(fun(F) -> do_asm(F, Outdir) end, TestBeams),
Res.
@@ -853,7 +799,7 @@ do_asm(Beam, Outdir) ->
end.
sys_pre_attributes(Config) ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
File = filename:join(DataDir, "attributes.erl"),
Mod = attributes,
CommonOpts = [binary,report,verbose,
@@ -885,8 +831,8 @@ sys_pre_attributes(Config) ->
%% Test the dialyzer option to cover more code.
dialyzer(Config) ->
- Priv = ?config(priv_dir, Config),
- file:set_cwd(?config(data_dir, Config)),
+ Priv = proplists:get_value(priv_dir, Config),
+ ok = file:set_cwd(proplists:get_value(data_dir, Config)),
Opts = [{outdir,Priv},report_errors],
M = dialyzer_test,
{ok,M} = c:c(M, [dialyzer|Opts]),
diff --git a/lib/compiler/test/compile_SUITE_data/bad_record_use.erl b/lib/compiler/test/compile_SUITE_data/bad_record_use.erl
deleted file mode 100644
index 0fb6fc3045..0000000000
--- a/lib/compiler/test/compile_SUITE_data/bad_record_use.erl
+++ /dev/null
@@ -1,29 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2009. 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(bad_record_use).
--export([test/0]).
-
--record(bad_use, {a=undefined,
- b=undefined,
- c=undefined}).
-
-test() ->
- NewRecord=#bad_use{a=1, b=2, a=2}.
-
diff --git a/lib/compiler/test/compile_SUITE_data/bad_record_use2.erl b/lib/compiler/test/compile_SUITE_data/bad_record_use2.erl
deleted file mode 100644
index 7c898af00f..0000000000
--- a/lib/compiler/test/compile_SUITE_data/bad_record_use2.erl
+++ /dev/null
@@ -1,30 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2009. 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(bad_record_use2).
--export([test/0]).
-
--record(bad_use, {a=undefined,
- b=undefined,
- c=undefined}).
-
-test() ->
- R=#bad_use{a=1, b=2},
- R2=R#bad_use{a=1, b=2, a=2},
- ok.
diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl
index 25f8564ce4..22f6443a77 100644
--- a/lib/compiler/test/core_SUITE.erl
+++ b/lib/compiler/test/core_SUITE.erl
@@ -29,21 +29,20 @@
bs_shadowed_size_var/1
]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(comp(N),
N(Config) when is_list(Config) -> try_it(N, Config)).
init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog = test_server:timetrap(?t:minutes(5)),
- [{watchdog,Dog}|Config].
+ Config.
end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,5}}].
all() ->
test_lib:recompile(?MODULE),
@@ -86,7 +85,8 @@ end_per_group(_GroupName, Config) ->
try_it(Mod, Conf) ->
- Src = filename:join(?config(data_dir, Conf), atom_to_list(Mod)),
+ Src = filename:join(proplists:get_value(data_dir, Conf),
+ atom_to_list(Mod)),
compile_and_load(Src, []),
compile_and_load(Src, [no_copt]).
diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl
index 016ea9d0d9..ee2a2c523f 100644
--- a/lib/compiler/test/core_fold_SUITE.erl
+++ b/lib/compiler/test/core_fold_SUITE.erl
@@ -29,7 +29,7 @@
-export([foo/0,foo/1,foo/2,foo/3]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -61,8 +61,8 @@ end_per_group(_GroupName, Config) ->
t_element(Config) when is_list(Config) ->
X = make_ref(),
- ?line X = id(element(1, {X,y,z})),
- ?line b = id(element(2, {a,b,c,d})),
+ X = id(element(1, {X,y,z})),
+ b = id(element(2, {a,b,c,d})),
(fun() ->
case {a,#{k=>X}} of
{a,#{k:=X}}=Tuple ->
@@ -73,21 +73,21 @@ t_element(Config) when is_list(Config) ->
%% No optimization, but should work.
Tuple = id({x,y,z}),
Pos = id(3),
- ?line x = id(element(1, Tuple)),
- ?line c = id(element(Pos, {a,b,c,d})),
- ?line X = id(element(Pos, {a,b,X,d})),
- ?line z = id(element(Pos, Tuple)),
+ x = id(element(1, Tuple)),
+ c = id(element(Pos, {a,b,c,d})),
+ X = id(element(Pos, {a,b,X,d})),
+ z = id(element(Pos, Tuple)),
%% Calls that will fail.
- ?line {'EXIT',{badarg,_}} = (catch element(5, {a,b,c,d})),
- ?line {'EXIT',{badarg,_}} = (catch element(5, {a,b,X,d})),
- ?line {'EXIT',{badarg,_}} = (catch element(5.0, {a,b,X,d})),
+ {'EXIT',{badarg,_}} = (catch element(5, {a,b,c,d})),
+ {'EXIT',{badarg,_}} = (catch element(5, {a,b,X,d})),
+ {'EXIT',{badarg,_}} = (catch element(5.0, {a,b,X,d})),
{'EXIT',{badarg,_}} = (catch element(2, not_a_tuple)),
{'EXIT',{badarg,_}} = (catch element(2, [])),
{'EXIT',{badarg,_}} = (catch element(2, Tuple == 3)),
case id({a,b,c}) of
{_,_,_}=Tup ->
- ?line {'EXIT',{badarg,_}} = (catch element(4, Tup))
+ {'EXIT',{badarg,_}} = (catch element(4, Tup))
end,
{'EXIT',{badarg,_}} = (catch element(1, tuple_size(Tuple))),
@@ -96,16 +96,16 @@ t_element(Config) when is_list(Config) ->
setelement(Config) when is_list(Config) ->
X = id(b),
New = id([1,2,3]),
- ?line {y,b,c} = id(setelement(1, {a,b,c}, y)),
- ?line {y,b,c} = id(setelement(1, {a,X,c}, y)),
- ?line {a,y,c} = id(setelement(2, {a,X,c}, y)),
- ?line {a,[1,2,3],c} = id(setelement(2, {a,b,c}, New)),
- ?line {a,[1,2,3],c} = id(setelement(2, {a,X,c}, New)),
- ?line {a,b,[1,2,3]} = id(setelement(3, {a,b,c}, New)),
- ?line {a,b,[1,2,3]} = id(setelement(3, {a,X,c}, New)),
+ {y,b,c} = id(setelement(1, {a,b,c}, y)),
+ {y,b,c} = id(setelement(1, {a,X,c}, y)),
+ {a,y,c} = id(setelement(2, {a,X,c}, y)),
+ {a,[1,2,3],c} = id(setelement(2, {a,b,c}, New)),
+ {a,[1,2,3],c} = id(setelement(2, {a,X,c}, New)),
+ {a,b,[1,2,3]} = id(setelement(3, {a,b,c}, New)),
+ {a,b,[1,2,3]} = id(setelement(3, {a,X,c}, New)),
- ?line {'EXIT',{badarg,_}} = (catch setelement_crash({a,b,c,d,e,f})),
- ?line error = setelement_crash_2({a,b,c,d,e,f}, <<42>>),
+ {'EXIT',{badarg,_}} = (catch setelement_crash({a,b,c,d,e,f})),
+ error = setelement_crash_2({a,b,c,d,e,f}, <<42>>),
{'EXIT',{badarg,_}} = (catch setelement(1, not_a_tuple, New)),
{'EXIT',{badarg,_}} = (catch setelement(3, {a,b}, New)),
@@ -132,19 +132,19 @@ setelement_crash_2(Tuple, Bin) ->
t_length(Config) when is_list(Config) ->
Blurf = id({blurf,a,b}),
Tail = id([42,43,44,45]),
- ?line 0 = id(length([])),
- ?line 1 = id(length([x])),
- ?line 2 = id(length([x,Blurf])),
- ?line 4 = id(length([x,Blurf,a,b])),
+ 0 = id(length([])),
+ 1 = id(length([x])),
+ 2 = id(length([x,Blurf])),
+ 4 = id(length([x,Blurf,a,b])),
%% No or partial optimization.
- ?line 4 = length(Tail),
- ?line 5 = id(length([x|Tail])),
+ 4 = length(Tail),
+ 5 = id(length([x|Tail])),
%% Will fail.
- ?line {'EXIT',{badarg,_}} = (catch id(length([a,b|c]))),
- ?line {'EXIT',{badarg,_}} = (catch id(length([a,Blurf|c]))),
- ?line {'EXIT',{badarg,_}} = (catch id(length(atom))),
+ {'EXIT',{badarg,_}} = (catch id(length([a,b|c]))),
+ {'EXIT',{badarg,_}} = (catch id(length([a,Blurf|c]))),
+ {'EXIT',{badarg,_}} = (catch id(length(atom))),
ok.
@@ -156,34 +156,34 @@ t_length(Config) when is_list(Config) ->
append(Config) when is_list(Config) ->
A = id(0),
- ?line [a,b,c,d,e,f,g,h,i,j,k] = id(?APPEND([a,b,c,d,e,f],[g,h,i,j,k])),
- ?line [a,b,c,d,e] = id(?APPEND([a,b,c],id([d,e]))),
- ?line [0,1,2,3,4,5,6] = id(?APPEND([A,1,2,3],[4,5,6])),
- ?line {'EXIT',{badarg,_}} = (catch id(?APPEND([A|blurf],[4,5,6]))),
+ [a,b,c,d,e,f,g,h,i,j,k] = id(?APPEND([a,b,c,d,e,f],[g,h,i,j,k])),
+ [a,b,c,d,e] = id(?APPEND([a,b,c],id([d,e]))),
+ [0,1,2,3,4,5,6] = id(?APPEND([A,1,2,3],[4,5,6])),
+ {'EXIT',{badarg,_}} = (catch id(?APPEND([A|blurf],[4,5,6]))),
ok.
t_apply(Config) when is_list(Config) ->
- ?line ok = apply(?MODULE, foo, []),
- ?line 4 = apply(?MODULE, foo, [3]),
- ?line 7 = apply(?MODULE, foo, [3,4]),
- ?line 12 = apply(?MODULE, foo, [id(8),4]),
- ?line 21 = apply(?MODULE, foo, [8,id(9),4]),
- ?line 20 = apply(?MODULE, foo, [8,8,id(4)]),
- ?line 24 = apply(?MODULE, foo, [id(10),10,4]),
+ ok = apply(?MODULE, foo, []),
+ 4 = apply(?MODULE, foo, [3]),
+ 7 = apply(?MODULE, foo, [3,4]),
+ 12 = apply(?MODULE, foo, [id(8),4]),
+ 21 = apply(?MODULE, foo, [8,id(9),4]),
+ 20 = apply(?MODULE, foo, [8,8,id(4)]),
+ 24 = apply(?MODULE, foo, [id(10),10,4]),
M = id(?MODULE),
- ?line ok = apply(M, foo, []),
- ?line 4 = apply(M, foo, [3]),
- ?line 16.0 = apply(M, foo, [12.0,4]),
+ ok = apply(M, foo, []),
+ 4 = apply(M, foo, [3]),
+ 16.0 = apply(M, foo, [12.0,4]),
%% Will fail.
- ?line {'EXIT',{badarg,_}} = (catch apply([a,b,c], foo, [])),
- ?line {'EXIT',{badarg,_}} = (catch apply(42, foo, [])),
- ?line {'EXIT',{badarg,_}} = (catch apply(?MODULE, 45, [xx])),
- ?line {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, {a,b})),
- ?line {'EXIT',{badarg,_}} = (catch apply(M, M, [1009|10010])),
- ?line {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, [10000|9999])),
- ?line {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, a)),
+ {'EXIT',{badarg,_}} = (catch apply([a,b,c], foo, [])),
+ {'EXIT',{badarg,_}} = (catch apply(42, foo, [])),
+ {'EXIT',{badarg,_}} = (catch apply(?MODULE, 45, [xx])),
+ {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, {a,b})),
+ {'EXIT',{badarg,_}} = (catch apply(M, M, [1009|10010])),
+ {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, [10000|9999])),
+ {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, a)),
ok.
@@ -210,13 +210,13 @@ bifs(Config) when is_list(Config) ->
-define(CMP_DIFF(A0, B), (fun(A) -> false = A == B, true = A /= B end)(id(A0))).
eq(Config) when is_list(Config) ->
- ?line ?CMP_SAME([a,b,c], [a,b,c]),
- ?line ?CMP_SAME([42.0], [42.0]),
- ?line ?CMP_SAME([42], [42]),
- ?line ?CMP_SAME([42.0], [42]),
+ ?CMP_SAME([a,b,c], [a,b,c]),
+ ?CMP_SAME([42.0], [42.0]),
+ ?CMP_SAME([42], [42]),
+ ?CMP_SAME([42.0], [42]),
- ?line ?CMP_DIFF(a, [a]),
- ?line ?CMP_DIFF(a, {1,2,3}),
+ ?CMP_DIFF(a, [a]),
+ ?CMP_DIFF(a, {1,2,3}),
?CMP_SAME(#{a=>1.0,b=>2}, #{b=>2.0,a=>1}),
?CMP_SAME(#{a=>[1.0],b=>[2]}, #{b=>[2.0],a=>[1]}),
@@ -232,7 +232,7 @@ eq(Config) when is_list(Config) ->
%% OTP-7117.
nested_call_in_case(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Dir = test_lib:get_data_dir(Config),
Core = filename:join(Dir, "nested_call_in_case"),
Opts = [from_core,{outdir,PrivDir}|test_lib:opt_opts(?MODULE)],
@@ -265,12 +265,12 @@ do_guard_try_catch(K, V) ->
-record(cover_opt_guard_try, {list=[]}).
coverage(Config) when is_list(Config) ->
- ?line {'EXIT',{{case_clause,{a,b,c}},_}} =
+ {'EXIT',{{case_clause,{a,b,c}},_}} =
(catch cover_will_match_list_type({a,b,c})),
- ?line {'EXIT',{{case_clause,{a,b,c,d}},_}} =
+ {'EXIT',{{case_clause,{a,b,c,d}},_}} =
(catch cover_will_match_list_type({a,b,c,d})),
- ?line a = cover_remove_non_vars_alias({a,b,c}),
- ?line error = cover_will_match_lit_list(),
+ a = cover_remove_non_vars_alias({a,b,c}),
+ error = cover_will_match_lit_list(),
{ok,[a]} = cover_is_safe_bool_expr(a),
ok = cover_opt_guard_try(#cover_opt_guard_try{list=[a]}),
@@ -347,7 +347,7 @@ bsm_an_inlined(<<_:8>>, _) -> ok;
bsm_an_inlined(_, _) -> error.
unused_multiple_values_error(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Dir = test_lib:get_data_dir(Config),
Core = filename:join(Dir, "unused_multiple_values_error"),
Opts = [no_copt,clint,return,from_core,{outdir,PrivDir}
diff --git a/lib/compiler/test/error_SUITE.erl b/lib/compiler/test/error_SUITE.erl
index 2962e3ff77..dd2e766599 100644
--- a/lib/compiler/test/error_SUITE.erl
+++ b/lib/compiler/test/error_SUITE.erl
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
-module(error_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
@@ -65,7 +65,7 @@ bif_clashes(Config) when is_list(Config) ->
[return_warnings],
{error,
[{4, erl_lint,{call_to_redefined_old_bif,{length,1}}}], []} }],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
Ts1 = [{bif_clashes2,
<<"
-export([t/0]).
@@ -76,7 +76,7 @@ bif_clashes(Config) when is_list(Config) ->
[return_warnings],
{error,
[{3, erl_lint,{redefine_old_bif_import,{length,1}}}], []} }],
- ?line [] = run(Config, Ts1),
+ [] = run(Config, Ts1),
Ts00 = [{bif_clashes3,
<<"
-export([t/0]).
@@ -89,7 +89,7 @@ bif_clashes(Config) when is_list(Config) ->
">>,
[return_warnings],
[]}],
- ?line [] = run(Config, Ts00),
+ [] = run(Config, Ts00),
Ts11 = [{bif_clashes4,
<<"
-export([t/0]).
@@ -100,7 +100,7 @@ bif_clashes(Config) when is_list(Config) ->
">>,
[return_warnings],
[]}],
- ?line [] = run(Config, Ts11),
+ [] = run(Config, Ts11),
Ts000 = [{bif_clashes5,
<<"
-export([t/0]).
@@ -113,7 +113,7 @@ bif_clashes(Config) when is_list(Config) ->
[return_warnings],
{warning,
[{4, erl_lint,{call_to_redefined_bif,{binary_part,3}}}]} }],
- ?line [] = run(Config, Ts000),
+ [] = run(Config, Ts000),
Ts111 = [{bif_clashes6,
<<"
-export([t/0]).
@@ -124,7 +124,7 @@ bif_clashes(Config) when is_list(Config) ->
[return_warnings],
{warning,
[{3, erl_lint,{redefine_bif_import,{binary_part,3}}}]} }],
- ?line [] = run(Config, Ts111),
+ [] = run(Config, Ts111),
Ts2 = [{bif_clashes7,
<<"
-export([t/0]).
@@ -139,7 +139,7 @@ bif_clashes(Config) when is_list(Config) ->
{error,
[{7,erl_lint,{define_import,{length,1}}}],
[]} }],
- ?line [] = run2(Config, Ts2),
+ [] = run2(Config, Ts2),
Ts3 = [{bif_clashes8,
<<"
-export([t/1]).
@@ -153,7 +153,7 @@ bif_clashes(Config) when is_list(Config) ->
{error,
[{4,erl_lint,{illegal_guard_local_call,{length,1}}}],
[]} }],
- ?line [] = run2(Config, Ts3),
+ [] = run2(Config, Ts3),
Ts4 = [{bif_clashes9,
<<"
-export([t/1]).
@@ -166,7 +166,7 @@ bif_clashes(Config) when is_list(Config) ->
{error,
[{5,erl_lint,{illegal_guard_local_call,{length,1}}}],
[]} }],
- ?line [] = run2(Config, Ts4),
+ [] = run2(Config, Ts4),
ok.
@@ -175,23 +175,23 @@ bif_clashes(Config) when is_list(Config) ->
%% Tests that a head mismatch is reported on the correct line (OTP-2125).
head_mismatch_line(Config) when is_list(Config) ->
- ?line [E|_] = get_compilation_errors(Config, "head_mismatch_line"),
- ?line {26, Mod, Reason} = E,
- ?line Mod:format_error(Reason),
+ [E|_] = get_compilation_errors(Config, "head_mismatch_line"),
+ {26, Mod, Reason} = E,
+ Mod:format_error(Reason),
ok.
%% Compiles a test file and returns the list of errors.
get_compilation_errors(Config, Filename) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line File = filename:join(DataDir, Filename),
- ?line {error, [{_Name, E}|_], []} = compile:file(File, [return_errors]),
+ DataDir = proplists:get_value(data_dir, Config),
+ File = filename:join(DataDir, Filename),
+ {error, [{_Name, E}|_], []} = compile:file(File, [return_errors]),
E.
warnings_as_errors(Config) when is_list(Config) ->
- ?line TestFile = test_filename(Config),
- ?line BeamFile = filename:rootname(TestFile, ".erl") ++ ".beam",
- ?line OutDir = ?config(priv_dir, Config),
+ TestFile = test_filename(Config),
+ BeamFile = filename:rootname(TestFile, ".erl") ++ ".beam",
+ OutDir = proplists:get_value(priv_dir, Config),
Ts1 = [{warnings_as_errors,
<<"
@@ -203,8 +203,8 @@ warnings_as_errors(Config) when is_list(Config) ->
{error,
[],
[{3,erl_lint,{unused_var,'A'}}]} }],
- ?line [] = run(Ts1, TestFile, write_beam),
- ?line false = filelib:is_regular(BeamFile),
+ [] = run(Ts1, TestFile, write_beam),
+ false = filelib:is_regular(BeamFile),
Ts2 = [{warning_unused_var,
<<"
@@ -216,9 +216,9 @@ warnings_as_errors(Config) when is_list(Config) ->
{warning,
[{3,erl_lint,{unused_var,'A'}}]} }],
- ?line [] = run(Ts2, TestFile, write_beam),
- ?line true = filelib:is_regular(BeamFile),
- ?line ok = file:delete(BeamFile),
+ [] = run(Ts2, TestFile, write_beam),
+ true = filelib:is_regular(BeamFile),
+ ok = file:delete(BeamFile),
ok.
@@ -295,7 +295,7 @@ bad_utf8(Config) ->
run(Config, Tests) ->
- ?line File = test_filename(Config),
+ File = test_filename(Config),
run(Tests, File, dont_write_beam).
run(Tests, File, WriteBeam) ->
@@ -304,7 +304,7 @@ run(Tests, File, WriteBeam) ->
E ->
BadL;
Bad ->
- ?t:format("~nTest ~p failed. Expected~n ~p~n"
+ io:format("~nTest ~p failed. Expected~n ~p~n"
"but got~n ~p~n", [N, E, Bad]),
fail()
end
@@ -312,7 +312,7 @@ run(Tests, File, WriteBeam) ->
lists:foldl(F, [], Tests).
run2(Config, Tests) ->
- ?line File = test_filename(Config),
+ File = test_filename(Config),
run2(Tests, File, dont_write_beam).
run2(Tests, File, WriteBeam) ->
@@ -321,7 +321,7 @@ run2(Tests, File, WriteBeam) ->
E ->
BadL;
Bad ->
- ?t:format("~nTest ~p failed. Expected~n ~p~n"
+ io:format("~nTest ~p failed. Expected~n ~p~n"
"but got~n ~p~n", [N, E, Bad]),
fail()
end
@@ -338,56 +338,45 @@ filter(X) ->
test_filename(Conf) ->
Filename = ["errors_test_",test_lib:uniq(),".erl"],
- DataDir = ?config(priv_dir, Conf),
+ DataDir = proplists:get_value(priv_dir, Conf),
filename:join(DataDir, Filename).
run_test(Test0, File, Warnings, WriteBeam) ->
ModName = filename:rootname(filename:basename(File), ".erl"),
Mod = list_to_atom(ModName),
Test = ["-module(",ModName,"). ",Test0],
- ?line Opts = case WriteBeam of
- dont_write_beam ->
- [binary,return_errors|Warnings];
- write_beam ->
- [return_errors|Warnings]
- end,
- ?line ok = file:write_file(File, Test),
+ Opts = case WriteBeam of
+ dont_write_beam ->
+ [binary,return_errors|Warnings];
+ write_beam ->
+ [return_errors|Warnings]
+ end,
+ ok = file:write_file(File, Test),
%% Compile once just to print all errors and warnings.
- ?line compile:file(File, [binary,report|Warnings]),
+ compile:file(File, [binary,report|Warnings]),
%% Test result of compilation.
io:format("~p\n", [Opts]),
- ?line Res = case compile:file(File, Opts) of
- {ok,Mod,_,[{_File,Ws}]} ->
- %io:format("compile:file(~s,~p) ->~n~p~n",
- % [File,Opts,Ws]),
- {warning,Ws};
- {ok,Mod,_,[]} ->
- %io:format("compile:file(~s,~p) ->~n~p~n",
- % [File,Opts,Ws]),
- [];
- {ok,Mod,[{_File,Ws}]} ->
- {warning,Ws};
- {ok,Mod,[]} ->
- [];
- {error,[{XFile,Es}],Ws} = _ZZ when is_list(XFile) ->
- %io:format("compile:file(~s,~p) ->~n~p~n",
- % [File,Opts,_ZZ]),
- {error,Es,Ws};
- {error,[{XFile,Es1},{XFile,Es2}],Ws} = _ZZ
- when is_list(XFile) ->
- %io:format("compile:file(~s,~p) ->~n~p~n",
- % [File,Opts,_ZZ]),
- {error,Es1++Es2,Ws};
- {error,Es,[{_File,Ws}]} = _ZZ->
- %io:format("compile:file(~s,~p) ->~n~p~n",
- % [File,Opts,_ZZ]),
- {error,Es,Ws}
- end,
+ Res = case compile:file(File, Opts) of
+ {ok,Mod,_,[{_File,Ws}]} ->
+ {warning,Ws};
+ {ok,Mod,_,[]} ->
+ [];
+ {ok,Mod,[{_File,Ws}]} ->
+ {warning,Ws};
+ {ok,Mod,[]} ->
+ [];
+ {error,[{XFile,Es}],Ws} = _ZZ when is_list(XFile) ->
+ {error,Es,Ws};
+ {error,[{XFile,Es1},{XFile,Es2}],Ws} = _ZZ
+ when is_list(XFile) ->
+ {error,Es1++Es2,Ws};
+ {error,Es,[{_File,Ws}]} = _ZZ->
+ {error,Es,Ws}
+ end,
file:delete(File),
Res.
fail() ->
- io:format("failed~n"),
- ?t:fail().
+ ct:fail(failed).
diff --git a/lib/compiler/test/float_SUITE.erl b/lib/compiler/test/float_SUITE.erl
index 1b313ad021..771016812b 100644
--- a/lib/compiler/test/float_SUITE.erl
+++ b/lib/compiler/test/float_SUITE.erl
@@ -22,7 +22,7 @@
init_per_group/2,end_per_group/2,
pending/1,bif_calls/1,math_functions/1,mixed_float_and_int/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -51,11 +51,11 @@ end_per_group(_GroupName, Config) ->
%% Shows the effect of pending exceptions on the x86.
pending(Config) when is_list(Config) ->
- ?line case catch float_mul(1, 1.1e300, 3.14e300) of
- {'EXIT',{badarith,_}} -> ok;
- Other -> ?t:fail({expected_exception,Other})
- end,
- ?line 0.0 = float_sub(2.0).
+ case catch float_mul(1, 1.1e300, 3.14e300) of
+ {'EXIT',{badarith,_}} -> ok;
+ Other -> ct:fail({expected_exception,Other})
+ end,
+ 0.0 = float_sub(2.0).
float_sub(A)->
catch A - 2.0.
@@ -69,11 +69,11 @@ float_mul(Iter, A, B) when is_float(A), is_float(B) ->
%% Thanks to Mikael Pettersson and Tobias Lindahl (HiPE).
bif_calls(Config) when is_list(Config) ->
- ?line {'EXIT',{badarith,_}} = (catch bad_arith(2.0, 1.7)),
- ?line {'EXIT',{badarith,_}} = (catch bad_arith_again(2.0, [])),
- ?line {'EXIT',{badarith,_}} = (catch bad_arith_xor(2.0, [])),
- ?line {'EXIT',{badarith,_}} = (catch bad_arith_hd(2.0, [])),
- ?line {'EXIT',{badarith,_}} = (catch bad_negate(2.0, 1.7)),
+ {'EXIT',{badarith,_}} = (catch bad_arith(2.0, 1.7)),
+ {'EXIT',{badarith,_}} = (catch bad_arith_again(2.0, [])),
+ {'EXIT',{badarith,_}} = (catch bad_arith_xor(2.0, [])),
+ {'EXIT',{badarith,_}} = (catch bad_arith_hd(2.0, [])),
+ {'EXIT',{badarith,_}} = (catch bad_negate(2.0, 1.7)),
ok.
bad_arith(X, Y) when is_float(X) ->
@@ -114,51 +114,51 @@ bad_negate(X, Y) when is_float(X) ->
math_functions(Config) when is_list(Config) ->
%% Mostly silly coverage.
- ?line 0.0 = math:tan(0),
- ?line 0.0 = math:atan2(0, 1),
- ?line 0.0 = math:sinh(0),
- ?line 1.0 = math:cosh(0),
- ?line 0.0 = math:tanh(0),
+ 0.0 = math:tan(0),
+ 0.0 = math:atan2(0, 1),
+ 0.0 = math:sinh(0),
+ 1.0 = math:cosh(0),
+ 0.0 = math:tanh(0),
1.0 = math:log2(2),
- ?line 1.0 = math:log10(10),
- ?line -1.0 = math:cos(math:pi()),
- ?line 1.0 = math:exp(0),
- ?line 1.0 = math:pow(math:pi(), 0),
- ?line 0.0 = math:log(1),
- ?line 0.0 = math:asin(0),
- ?line 0.0 = math:acos(1),
- ?line ?OPTIONAL(0.0, math:asinh(0)),
- ?line ?OPTIONAL(0.0, math:acosh(1)),
- ?line ?OPTIONAL(0.0, math:atanh(0)),
- ?line ?OPTIONAL(0.0, math:erf(0)),
- ?line ?OPTIONAL(1.0, math:erfc(0)),
-
- ?line 0.0 = math:tan(id(0)),
- ?line 0.0 = math:atan2(id(0), 1),
- ?line 0.0 = math:sinh(id(0)),
- ?line 1.0 = math:cosh(id(0)),
- ?line 0.0 = math:tanh(id(0)),
+ 1.0 = math:log10(10),
+ -1.0 = math:cos(math:pi()),
+ 1.0 = math:exp(0),
+ 1.0 = math:pow(math:pi(), 0),
+ 0.0 = math:log(1),
+ 0.0 = math:asin(0),
+ 0.0 = math:acos(1),
+ ?OPTIONAL(0.0, math:asinh(0)),
+ ?OPTIONAL(0.0, math:acosh(1)),
+ ?OPTIONAL(0.0, math:atanh(0)),
+ ?OPTIONAL(0.0, math:erf(0)),
+ ?OPTIONAL(1.0, math:erfc(0)),
+
+ 0.0 = math:tan(id(0)),
+ 0.0 = math:atan2(id(0), 1),
+ 0.0 = math:sinh(id(0)),
+ 1.0 = math:cosh(id(0)),
+ 0.0 = math:tanh(id(0)),
1.0 = math:log2(id(2)),
- ?line 1.0 = math:log10(id(10)),
- ?line 1.0 = math:exp(id(0)),
- ?line 0.0 = math:log(id(1)),
- ?line 0.0 = math:asin(id(0)),
- ?line 0.0 = math:acos(id(1)),
- ?line ?OPTIONAL(0.0, math:asinh(id(0))),
- ?line ?OPTIONAL(0.0, math:acosh(id(1))),
- ?line ?OPTIONAL(0.0, math:atanh(id(0))),
- ?line ?OPTIONAL(0.0, math:erf(id(0))),
- ?line ?OPTIONAL(1.0, math:erfc(id(0))),
+ 1.0 = math:log10(id(10)),
+ 1.0 = math:exp(id(0)),
+ 0.0 = math:log(id(1)),
+ 0.0 = math:asin(id(0)),
+ 0.0 = math:acos(id(1)),
+ ?OPTIONAL(0.0, math:asinh(id(0))),
+ ?OPTIONAL(0.0, math:acosh(id(1))),
+ ?OPTIONAL(0.0, math:atanh(id(0))),
+ ?OPTIONAL(0.0, math:erf(id(0))),
+ ?OPTIONAL(1.0, math:erfc(id(0))),
%% Only for coverage (of beam_type.erl).
- ?line {'EXIT',{undef,_}} = (catch math:fnurfla(0)),
- ?line {'EXIT',{undef,_}} = (catch math:fnurfla(0, 0)),
- ?line {'EXIT',{badarg,_}} = (catch float(kalle)),
- ?line {'EXIT',{badarith,_}} = (catch name/1),
+ {'EXIT',{undef,_}} = (catch math:fnurfla(0)),
+ {'EXIT',{undef,_}} = (catch math:fnurfla(0, 0)),
+ {'EXIT',{badarg,_}} = (catch float(kalle)),
+ {'EXIT',{badarith,_}} = (catch name/1),
ok.
mixed_float_and_int(Config) when is_list(Config) ->
- ?line 129.0 = pc(77, 23, 5),
+ 129.0 = pc(77, 23, 5),
ok.
pc(Cov, NotCov, X) ->
diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl
index 36a4d6fce2..77559ae2e6 100644
--- a/lib/compiler/test/fun_SUITE.erl
+++ b/lib/compiler/test/fun_SUITE.erl
@@ -27,7 +27,7 @@
%% Internal exports.
-export([call_me/1,dup1/0,dup2/0]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -60,9 +60,8 @@ l1() ->
?T((begin G = fun(1=0) -> ok end, {'EXIT',_} = (catch G(2)), ok end), ok)
].
-test1(suite) -> [];
test1(Config) when is_list(Config) ->
- ?line lists:foreach(fun one_test/1, eval_list(l1(), [])),
+ lists:foreach(fun one_test/1, eval_list(l1(), [])),
ok.
evaluate(Str, Vars) ->
@@ -93,7 +92,7 @@ one_test({C, E, Str, Correct}) ->
true ->
io:format("ERROR: Compiled: ~p. Expected ~p. Got ~p.~n",
[Str, Correct, C]),
- test_server:fail(comp)
+ ct:fail(comp)
end,
if
E == Correct ->
@@ -101,7 +100,7 @@ one_test({C, E, Str, Correct}) ->
true ->
io:format("ERROR: Interpreted: ~p. Expected ~p. Got ~p.~n",
[Str, Correct, E]),
- test_server:fail(comp)
+ ct:fail(comp)
end.
-record(b, {c}).
@@ -109,9 +108,9 @@ one_test({C, E, Str, Correct}) ->
%% OTP-7102. (Thanks to Simon Cornish.)
overwritten_fun(Config) when is_list(Config) ->
- ?line {a2,a} = overwritten_fun_1(a),
- ?line {a2,{b,c}} = overwritten_fun_1(#b{c=c}),
- ?line one = overwritten_fun_1(#b{c=[]}),
+ {a2,a} = overwritten_fun_1(a),
+ {a2,{b,c}} = overwritten_fun_1(#b{c=c}),
+ one = overwritten_fun_1(#b{c=[]}),
ok.
overwritten_fun_1(A) ->
@@ -153,8 +152,8 @@ otp_7202_func() ->
no_value.
bif_fun(Config) when is_list(Config) ->
- ?line F = fun abs/1,
- ?line 5 = F(-5),
+ F = fun abs/1,
+ 5 = F(-5),
ok.
-define(APPLY(M, F, A), (fun(Fun) -> {ok,{a,b}} = Fun({a,b}) end)(fun M:F/A)).
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index 47eb1ba78b..129db039e1 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(guard_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
@@ -69,23 +69,23 @@ end_per_group(_GroupName, Config) ->
misc(Config) when is_list(Config) ->
- ?line 42 = case id(42) of
- X when -X -> ok;
- X -> X
- end,
- ?line {a,b,c} = misc_1([{{a,b,c}},{[4]},{[3]},{-2}]),
- ?line none = misc_1([{{a,b,c}},{[4]},{[3]},{-3}]),
- ?line none = misc_1([{{a,b,c}},{[4]},{[7]},{-2}]),
- ?line none = misc_1([{{a,b,c}},{[4]},{[3]},{[1,2,3]}]),
-
- ?line {ok,buf,<<>>} = get_data({o,true,raw}, 0, buf),
- ?line {ok,buf,<<>>} = get_data({o,true,raw}, 42, buf),
- ?line {ok,buf,<<>>} = get_data({o,false,raw}, 0, buf),
- ?line error = get_data({o,false,raw}, 42, buf),
- ?line {ok,buf,<<>>} = get_data({o,true,0}, 0, buf),
- ?line {ok,buf,<<>>} = get_data({o,true,0}, 42, buf),
- ?line {ok,buf,<<>>} = get_data({o,false,0}, 0, buf),
- ?line error = get_data({o,false,0}, 42, buf),
+ 42 = case id(42) of
+ X when -X -> ok;
+ X -> X
+ end,
+ {a,b,c} = misc_1([{{a,b,c}},{[4]},{[3]},{-2}]),
+ none = misc_1([{{a,b,c}},{[4]},{[3]},{-3}]),
+ none = misc_1([{{a,b,c}},{[4]},{[7]},{-2}]),
+ none = misc_1([{{a,b,c}},{[4]},{[3]},{[1,2,3]}]),
+
+ {ok,buf,<<>>} = get_data({o,true,raw}, 0, buf),
+ {ok,buf,<<>>} = get_data({o,true,raw}, 42, buf),
+ {ok,buf,<<>>} = get_data({o,false,raw}, 0, buf),
+ error = get_data({o,false,raw}, 42, buf),
+ {ok,buf,<<>>} = get_data({o,true,0}, 0, buf),
+ {ok,buf,<<>>} = get_data({o,true,0}, 42, buf),
+ {ok,buf,<<>>} = get_data({o,false,0}, 0, buf),
+ error = get_data({o,false,0}, 42, buf),
ok.
@@ -107,11 +107,11 @@ get_data({o,Active,Raw}, BytesToRead, Buffer)
end.
const_cond(Config) when is_list(Config) ->
- ?line ok = const_cond({}, 0),
- ?line ok = const_cond({a}, 1),
- ?line error = const_cond({a,b}, 3),
- ?line error = const_cond({a}, 0),
- ?line error = const_cond({a,b}, 1),
+ ok = const_cond({}, 0),
+ ok = const_cond({a}, 1),
+ error = const_cond({a,b}, 3),
+ error = const_cond({a}, 0),
+ error = const_cond({a,b}, 1),
ok.
const_cond(T, Sz) ->
@@ -132,80 +132,80 @@ basic_not(Config) when is_list(Config) ->
D = id(5),
ATuple = {False,True,Glurf},
- ?line check(fun() -> if not false -> ok; true -> error end end, ok),
- ?line check(fun() -> if not true -> ok; true -> error end end, error),
- ?line check(fun() -> if not False -> ok; true -> error end end, ok),
- ?line check(fun() -> if not True -> ok; true -> error end end, error),
+ check(fun() -> if not false -> ok; true -> error end end, ok),
+ check(fun() -> if not true -> ok; true -> error end end, error),
+ check(fun() -> if not False -> ok; true -> error end end, ok),
+ check(fun() -> if not True -> ok; true -> error end end, error),
- ?line check(fun() -> if A > B -> gt; A < B -> lt; A == B -> eq end end, lt),
- ?line check(fun() -> if A > C -> gt; A < C -> lt; A == C -> eq end end, gt),
- ?line check(fun() -> if A > D -> gt; A < D -> lt; A == D -> eq end end, eq),
+ check(fun() -> if A > B -> gt; A < B -> lt; A == B -> eq end end, lt),
+ check(fun() -> if A > C -> gt; A < C -> lt; A == C -> eq end end, gt),
+ check(fun() -> if A > D -> gt; A < D -> lt; A == D -> eq end end, eq),
- ?line check(fun() -> if not (7 > 453) -> le; not (7 < 453) -> ge;
- not (7 == 453) -> ne; true -> eq end end, le),
- ?line check(fun() -> if not (7 > -8) -> le; not (7 < -8) -> ge;
- not (7 == -8) -> ne; true -> eq end end, ge),
- ?line check(fun() -> if not (7 > 7) -> le; not (7 < 7) -> ge;
- not (7 == 7) -> ne; true -> eq end end, le),
+ check(fun() -> if not (7 > 453) -> le; not (7 < 453) -> ge;
+ not (7 == 453) -> ne; true -> eq end end, le),
+ check(fun() -> if not (7 > -8) -> le; not (7 < -8) -> ge;
+ not (7 == -8) -> ne; true -> eq end end, ge),
+ check(fun() -> if not (7 > 7) -> le; not (7 < 7) -> ge;
+ not (7 == 7) -> ne; true -> eq end end, le),
- ?line check(fun() -> if not (A > B) -> le; not (A < B) -> ge;
- not (A == B) -> ne; true -> eq end end, le),
- ?line check(fun() -> if not (A > C) -> le; not (A < C) -> ge;
- not (A == C) -> ne; true -> eq end end, ge),
- ?line check(fun() -> if not (A > D) -> le; not (A < D) -> ge;
- not (A == D) -> ne; true -> eq end end, le),
+ check(fun() -> if not (A > B) -> le; not (A < B) -> ge;
+ not (A == B) -> ne; true -> eq end end, le),
+ check(fun() -> if not (A > C) -> le; not (A < C) -> ge;
+ not (A == C) -> ne; true -> eq end end, ge),
+ check(fun() -> if not (A > D) -> le; not (A < D) -> ge;
+ not (A == D) -> ne; true -> eq end end, le),
- ?line check(fun() -> if not element(1, ATuple) -> ok; true -> error end end, ok),
- ?line check(fun() -> if not element(2, ATuple) -> ok; true -> error end end, error),
- ?line check(fun() -> if not element(3, ATuple) -> ok; true -> error end end, error),
+ check(fun() -> if not element(1, ATuple) -> ok; true -> error end end, ok),
+ check(fun() -> if not element(2, ATuple) -> ok; true -> error end end, error),
+ check(fun() -> if not element(3, ATuple) -> ok; true -> error end end, error),
- ?line check(fun() -> if not glurf -> ok; true -> error end end, error),
- ?line check(fun() -> if not Glurf -> ok; true -> error end end, error),
+ check(fun() -> if not glurf -> ok; true -> error end end, error),
+ check(fun() -> if not Glurf -> ok; true -> error end end, error),
ok.
complex_not(Config) when is_list(Config) ->
ATuple = id({false,true,gurka}),
- ?line check(fun() -> if not(element(1, ATuple)) -> ok; true -> error end end, ok),
- ?line check(fun() -> if not(element(2, ATuple)) -> ok; true -> error end end, error),
+ check(fun() -> if not(element(1, ATuple)) -> ok; true -> error end end, ok),
+ check(fun() -> if not(element(2, ATuple)) -> ok; true -> error end end, error),
- ?line check(fun() -> if not(element(3, ATuple) == gurka) -> ok;
- true -> error end end, error),
- ?line check(fun() -> if not(element(3, ATuple) =/= gurka) -> ok;
- true -> error end end, ok),
+ check(fun() -> if not(element(3, ATuple) == gurka) -> ok;
+ true -> error end end, error),
+ check(fun() -> if not(element(3, ATuple) =/= gurka) -> ok;
+ true -> error end end, ok),
- ?line check(fun() -> if {a,not(element(2, ATuple))} == {a,false} -> ok;
- true -> error end end, ok),
- ?line check(fun() -> if {a,not(element(1, ATuple))} == {a,false} -> ok;
- true -> error end end, error),
+ check(fun() -> if {a,not(element(2, ATuple))} == {a,false} -> ok;
+ true -> error end end, ok),
+ check(fun() -> if {a,not(element(1, ATuple))} == {a,false} -> ok;
+ true -> error end end, error),
- ?line check(fun() -> if not(element(1, ATuple) or element(3, ATuple)) -> ok;
- true -> error end end, error),
+ check(fun() -> if not(element(1, ATuple) or element(3, ATuple)) -> ok;
+ true -> error end end, error),
%% orelse
- ?line check(fun() -> if not(element(1, ATuple) orelse element(3, ATuple)) -> ok;
- true -> error end end, error),
+ check(fun() -> if not(element(1, ATuple) orelse element(3, ATuple)) -> ok;
+ true -> error end end, error),
ok.
nested_nots(Config) when is_list(Config) ->
- ?line true = nested_not_1(0, 0),
- ?line true = nested_not_1(0, 1),
- ?line true = nested_not_1(a, b),
- ?line true = nested_not_1(10, 0),
- ?line false = nested_not_1(z, a),
- ?line false = nested_not_1(3.4, {anything,goes}),
- ?line false = nested_not_1(3.4, atom),
- ?line true = nested_not_1(3.0, [list]),
-
- ?line true = nested_not_2(false, false, 42),
- ?line true = nested_not_2(false, true, 42),
- ?line true = nested_not_2(true, false, 42),
- ?line true = nested_not_2(true, true, 42),
- ?line true = nested_not_2(false, false, atom),
- ?line false = nested_not_2(false, true, atom),
- ?line false = nested_not_2(true, false, atom),
- ?line false = nested_not_2(true, true, atom),
+ true = nested_not_1(0, 0),
+ true = nested_not_1(0, 1),
+ true = nested_not_1(a, b),
+ true = nested_not_1(10, 0),
+ false = nested_not_1(z, a),
+ false = nested_not_1(3.4, {anything,goes}),
+ false = nested_not_1(3.4, atom),
+ true = nested_not_1(3.0, [list]),
+
+ true = nested_not_2(false, false, 42),
+ true = nested_not_2(false, true, 42),
+ true = nested_not_2(true, false, 42),
+ true = nested_not_2(true, true, 42),
+ true = nested_not_2(false, false, atom),
+ false = nested_not_2(false, true, atom),
+ false = nested_not_2(true, false, atom),
+ false = nested_not_2(true, true, atom),
ok.
nested_not_1(X, Y) when not (((X>Y) or not(is_atom(X))) and
@@ -227,112 +227,112 @@ semicolon(Config) when is_list(Config) ->
%% True/false combined using ';' (literal atoms).
- ?line check(fun() -> if true; false -> ok end end, ok),
- ?line check(fun() -> if false; true -> ok end end, ok),
- ?line check(fun() -> if true; true -> ok end end, ok),
- ?line check(fun() -> if false; false -> ok; true -> error end end, error),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} = (catch if false; false -> ok end),
- exit
- end, exit),
+ check(fun() -> if true; false -> ok end end, ok),
+ check(fun() -> if false; true -> ok end end, ok),
+ check(fun() -> if true; true -> ok end end, ok),
+ check(fun() -> if false; false -> ok; true -> error end end, error),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if false; false -> ok end),
+ exit
+ end, exit),
%% True/false combined used ';'.
True = id(true),
False = id(false),
- ?line check(fun() -> if True; False -> ok end end, ok),
- ?line check(fun() -> if False; True -> ok end end, ok),
- ?line check(fun() -> if True; True -> ok end end, ok),
- ?line check(fun() -> if False; False -> ok; true -> error end end, error),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} = (catch if False; False -> ok end),
- exit
- end, exit),
+ check(fun() -> if True; False -> ok end end, ok),
+ check(fun() -> if False; True -> ok end end, ok),
+ check(fun() -> if True; True -> ok end end, ok),
+ check(fun() -> if False; False -> ok; true -> error end end, error),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if False; False -> ok end),
+ exit
+ end, exit),
%% Combine true/false with a non-boolean value.
Glurf = id(glurf),
- ?line check(fun() -> if True; Glurf -> ok end end, ok),
- ?line check(fun() -> if Glurf; True -> ok end end, ok),
- ?line check(fun() -> if Glurf; Glurf -> ok; true -> error end end, error),
- ?line check(fun() -> if False; Glurf -> ok; true -> error end end, error),
- ?line check(fun() -> if Glurf; False -> ok; true -> error end end, error),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} = (catch if Glurf; Glurf -> ok end),
- exit
- end, exit),
+ check(fun() -> if True; Glurf -> ok end end, ok),
+ check(fun() -> if Glurf; True -> ok end end, ok),
+ check(fun() -> if Glurf; Glurf -> ok; true -> error end end, error),
+ check(fun() -> if False; Glurf -> ok; true -> error end end, error),
+ check(fun() -> if Glurf; False -> ok; true -> error end end, error),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if Glurf; Glurf -> ok end),
+ exit
+ end, exit),
%% Combine true/false with errors.
ATuple = id({false,true,gurka}),
- ?line check(fun() -> if True; element(42, ATuple) -> ok end end, ok),
- ?line check(fun() -> if element(42, ATuple); True -> ok end end, ok),
- ?line check(fun() -> if element(42, ATuple); element(42, ATuple) -> ok;
- true -> error end end, error),
- ?line check(fun() -> if False; element(42, ATuple) -> ok;
- true -> error end end, error),
- ?line check(fun() -> if element(42, ATuple);
- False -> ok; true -> error end end, error),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} =
- (catch if element(42, ATuple);
- element(42, ATuple) -> ok end),
- exit
- end, exit),
+ check(fun() -> if True; element(42, ATuple) -> ok end end, ok),
+ check(fun() -> if element(42, ATuple); True -> ok end end, ok),
+ check(fun() -> if element(42, ATuple); element(42, ATuple) -> ok;
+ true -> error end end, error),
+ check(fun() -> if False; element(42, ATuple) -> ok;
+ true -> error end end, error),
+ check(fun() -> if element(42, ATuple);
+ False -> ok; true -> error end end, error),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if element(42, ATuple);
+ element(42, ATuple) -> ok end),
+ exit
+ end, exit),
ok.
complex_semicolon(Config) when is_list(Config) ->
- ?line ok = csemi1(int, {blurf}),
- ?line ok = csemi1(string, {blurf}),
- ?line ok = csemi1(float, [a]),
- ?line error = csemi1(35, 42),
+ ok = csemi1(int, {blurf}),
+ ok = csemi1(string, {blurf}),
+ ok = csemi1(float, [a]),
+ error = csemi1(35, 42),
%% 2
- ?line ok = csemi2({}, {a,b,c}),
- ?line ok = csemi2({1,3.5}, {a,b,c}),
- ?line ok = csemi2(dum, {a,b,c}),
+ ok = csemi2({}, {a,b,c}),
+ ok = csemi2({1,3.5}, {a,b,c}),
+ ok = csemi2(dum, {a,b,c}),
- ?line ok = csemi2({45,-19.3}, {}),
- ?line ok = csemi2({45,-19.3}, {dum}),
- ?line ok = csemi2({45,-19.3}, {dum,dum}),
+ ok = csemi2({45,-19.3}, {}),
+ ok = csemi2({45,-19.3}, {dum}),
+ ok = csemi2({45,-19.3}, {dum,dum}),
- ?line error = csemi2({45}, {dum}),
- ?line error = csemi2([], {dum}),
- ?line error = csemi2({dum}, []),
- ?line error = csemi2([], []),
+ error = csemi2({45}, {dum}),
+ error = csemi2([], {dum}),
+ error = csemi2({dum}, []),
+ error = csemi2([], []),
%% 3
- ?line csemi3(fun csemi3a/4),
- ?line csemi3(fun csemi3b/4),
- ?line csemi3(fun csemi3c/4),
+ csemi3(fun csemi3a/4),
+ csemi3(fun csemi3b/4),
+ csemi3(fun csemi3c/4),
%% 4
- ?line csemi4(fun csemi4a/4),
- ?line csemi4(fun csemi4b/4),
- ?line csemi4(fun csemi4c/4),
- ?line csemi4(fun csemi4d/4),
+ csemi4(fun csemi4a/4),
+ csemi4(fun csemi4b/4),
+ csemi4(fun csemi4c/4),
+ csemi4(fun csemi4d/4),
%% 4, 'orelse' instead of 'or'
- ?line csemi4_orelse(fun csemi4_orelse_a/4),
- ?line csemi4_orelse(fun csemi4_orelse_b/4),
- ?line csemi4_orelse(fun csemi4_orelse_c/4),
- ?line csemi4_orelse(fun csemi4_orelse_d/4),
+ csemi4_orelse(fun csemi4_orelse_a/4),
+ csemi4_orelse(fun csemi4_orelse_b/4),
+ csemi4_orelse(fun csemi4_orelse_c/4),
+ csemi4_orelse(fun csemi4_orelse_d/4),
%% 5
- ?line error = csemi5(0, 0),
- ?line ok = csemi5(5, 0),
- ?line ok = csemi5(4, -4),
- ?line ok = csemi5(10, -4),
+ error = csemi5(0, 0),
+ ok = csemi5(5, 0),
+ ok = csemi5(4, -4),
+ ok = csemi5(10, -4),
%% 6
- ?line error = csemi6({a}, 0),
- ?line ok = csemi6({a,b}, 0),
- ?line ok = csemi6({}, 3),
- ?line ok = csemi6({a,b,c}, 3),
+ error = csemi6({a}, 0),
+ ok = csemi6({a,b}, 0),
+ ok = csemi6({}, 3),
+ ok = csemi6({a,b,c}, 3),
%% 7
error = csemi7(#{a=>1}, 1, 0),
@@ -427,7 +427,7 @@ csemi4_orelse(Test) ->
ok = Test({}, 2, blurf, 0),
ok = Test({}, 2, {1}, 2),
- ?line error = Test([], 1, {}, 0),
+ error = Test([], 1, {}, 0),
ok.
@@ -460,72 +460,72 @@ comma(Config) when is_list(Config) ->
%% ',' combinations of literal true/false.
- ?line check(fun() -> if true, false -> ok; true -> error end end, error),
- ?line check(fun() -> if false, true -> ok; true -> error end end, error),
- ?line check(fun() -> if true, true -> ok end end, ok),
- ?line check(fun() -> if false, false -> ok; true -> error end end, error),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} =
- (catch if true, false -> ok;
- false, true -> ok;
- false, false -> ok
- end),
- exit
- end, exit),
+ check(fun() -> if true, false -> ok; true -> error end end, error),
+ check(fun() -> if false, true -> ok; true -> error end end, error),
+ check(fun() -> if true, true -> ok end end, ok),
+ check(fun() -> if false, false -> ok; true -> error end end, error),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if true, false -> ok;
+ false, true -> ok;
+ false, false -> ok
+ end),
+ exit
+ end, exit),
%% ',' combinations of true/false in variables.
True = id(true),
False = id(false),
- ?line check(fun() -> if True, False -> ok; true -> error end end, error),
- ?line check(fun() -> if False, True -> ok; true -> error end end, error),
- ?line check(fun() -> if True, True -> ok end end, ok),
- ?line check(fun() -> if False, False -> ok; true -> error end end, error),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} =
- (catch if True, False -> ok;
- False, True -> ok;
- False, False -> ok
- end),
- exit
- end, exit),
+ check(fun() -> if True, False -> ok; true -> error end end, error),
+ check(fun() -> if False, True -> ok; true -> error end end, error),
+ check(fun() -> if True, True -> ok end end, ok),
+ check(fun() -> if False, False -> ok; true -> error end end, error),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True, False -> ok;
+ False, True -> ok;
+ False, False -> ok
+ end),
+ exit
+ end, exit),
%% ',' combinations of true/false, and non-boolean in variables.
Glurf = id(glurf),
- ?line check(fun() -> if True, Glurf -> ok; true -> error end end, error),
- ?line check(fun() -> if Glurf, True -> ok; true -> error end end, error),
- ?line check(fun() -> if True, True -> ok end end, ok),
- ?line check(fun() -> if Glurf, Glurf -> ok; true -> error end end, error),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} =
- (catch if True, Glurf -> ok;
- Glurf, True -> ok;
- Glurf, Glurf -> ok
- end),
- exit
- end, exit),
+ check(fun() -> if True, Glurf -> ok; true -> error end end, error),
+ check(fun() -> if Glurf, True -> ok; true -> error end end, error),
+ check(fun() -> if True, True -> ok end end, ok),
+ check(fun() -> if Glurf, Glurf -> ok; true -> error end end, error),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True, Glurf -> ok;
+ Glurf, True -> ok;
+ Glurf, Glurf -> ok
+ end),
+ exit
+ end, exit),
%% ',' combinations of true/false with errors.
ATuple = id({a,b,c}),
- ?line check(fun() -> if True, element(42, ATuple) -> ok;
- true -> error end end, error),
- ?line check(fun() -> if element(42, ATuple), True -> ok;
- true -> error end end, error),
- ?line check(fun() -> if True, True -> ok end end, ok),
- ?line check(fun() -> if element(42, ATuple), element(42, ATuple) -> ok;
- true -> error end end, error),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} =
- (catch if True, element(42, ATuple) -> ok;
- element(42, ATuple), True -> ok;
- element(42, ATuple), element(42, ATuple) -> ok
- end),
- exit
- end, exit),
+ check(fun() -> if True, element(42, ATuple) -> ok;
+ true -> error end end, error),
+ check(fun() -> if element(42, ATuple), True -> ok;
+ true -> error end end, error),
+ check(fun() -> if True, True -> ok end end, ok),
+ check(fun() -> if element(42, ATuple), element(42, ATuple) -> ok;
+ true -> error end end, error),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True, element(42, ATuple) -> ok;
+ element(42, ATuple), True -> ok;
+ element(42, ATuple), element(42, ATuple) -> ok
+ end),
+ exit
+ end, exit),
ok.
@@ -535,35 +535,35 @@ or_guard(Config) when is_list(Config) ->
Glurf = id(glurf),
%% 'or' combinations of literal true/false.
- ?line check(fun() -> if true or false -> ok end end, ok),
- ?line check(fun() -> if false or true -> ok end end, ok),
- ?line check(fun() -> if true or true -> ok end end, ok),
- ?line check(fun() -> if false or false -> ok; true -> error end end, error),
+ check(fun() -> if true or false -> ok end end, ok),
+ check(fun() -> if false or true -> ok end end, ok),
+ check(fun() -> if true or true -> ok end end, ok),
+ check(fun() -> if false or false -> ok; true -> error end end, error),
- ?line check(fun() -> if glurf or true -> ok; true -> error end end, error),
- ?line check(fun() -> if true or glurf -> ok; true -> error end end, error),
- ?line check(fun() -> if glurf or glurf -> ok; true -> error end end, error),
+ check(fun() -> if glurf or true -> ok; true -> error end end, error),
+ check(fun() -> if true or glurf -> ok; true -> error end end, error),
+ check(fun() -> if glurf or glurf -> ok; true -> error end end, error),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} = (catch if false or false -> ok end),
- exit
- end, exit),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if false or false -> ok end),
+ exit
+ end, exit),
%% 'or' combinations using variables containing true/false.
- ?line check(fun() -> if True or False -> ok end end, ok),
- ?line check(fun() -> if False or True -> ok end end, ok),
- ?line check(fun() -> if True or True -> ok end end, ok),
- ?line check(fun() -> if False or False -> ok; true -> error end end, error),
+ check(fun() -> if True or False -> ok end end, ok),
+ check(fun() -> if False or True -> ok end end, ok),
+ check(fun() -> if True or True -> ok end end, ok),
+ check(fun() -> if False or False -> ok; true -> error end end, error),
- ?line check(fun() -> if True or Glurf -> ok; true -> error end end, error),
- ?line check(fun() -> if Glurf or True -> ok; true -> error end end, error),
- ?line check(fun() -> if Glurf or Glurf -> ok; true -> error end end, error),
+ check(fun() -> if True or Glurf -> ok; true -> error end end, error),
+ check(fun() -> if Glurf or True -> ok; true -> error end end, error),
+ check(fun() -> if Glurf or Glurf -> ok; true -> error end end, error),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} = (catch if False or False -> ok end),
- exit
- end, exit),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if False or False -> ok end),
+ exit
+ end, exit),
ok.
@@ -572,142 +572,142 @@ more_or_guards(Config) when is_list(Config) ->
False = id(false),
ATuple = id({false,true,gurka}),
- ?line check(fun() ->
- if element(42, ATuple) or False -> ok;
- true -> error end
- end, error),
-
- ?line check(fun() ->
- if False or element(42, ATuple) -> ok;
- true -> error end
- end, error),
-
- ?line check(fun() ->
- if element(18, ATuple) or element(42, ATuple) -> ok;
- true -> error end
- end, error),
-
- ?line check(fun() ->
- if True or element(42, ATuple) -> ok;
- true -> error end
- end, error),
-
- ?line check(fun() ->
- if element(42, ATuple) or True -> ok;
- true -> error end
- end, error),
-
- ?line check(fun() ->
- if element(1, ATuple) or element(42, ATuple) or True -> ok;
- true -> error end
- end, error),
-
- ?line check(fun() ->
- if element(1, ATuple) or True or element(42, ATuple) -> ok;
- true -> error end
- end, error),
-
- ?line check(fun() ->
- if
- (<<False:8>> == <<0>>) or element(2, ATuple) -> ok;
- true -> error end
- end, error),
-
- ?line check(fun() ->
- if
- element(2, ATuple) or (<<True:8>> == <<1>>) -> ok;
- true -> error end
- end, error),
-
- ?line check(fun() ->
- if element(2, ATuple) or element(42, ATuple) -> ok;
- true -> error end
- end, error),
-
- ?line check(fun() ->
- if
- element(1, ATuple) or
- element(2, ATuple) or
- element(19, ATuple) -> ok;
- true -> error end
- end, error),
+ check(fun() ->
+ if element(42, ATuple) or False -> ok;
+ true -> error end
+ end, error),
+
+ check(fun() ->
+ if False or element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ check(fun() ->
+ if element(18, ATuple) or element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ check(fun() ->
+ if True or element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ check(fun() ->
+ if element(42, ATuple) or True -> ok;
+ true -> error end
+ end, error),
+
+ check(fun() ->
+ if element(1, ATuple) or element(42, ATuple) or True -> ok;
+ true -> error end
+ end, error),
+
+ check(fun() ->
+ if element(1, ATuple) or True or element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ check(fun() ->
+ if
+ (<<False:8>> == <<0>>) or element(2, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ check(fun() ->
+ if
+ element(2, ATuple) or (<<True:8>> == <<1>>) -> ok;
+ true -> error end
+ end, error),
+
+ check(fun() ->
+ if element(2, ATuple) or element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ check(fun() ->
+ if
+ element(1, ATuple) or
+ element(2, ATuple) or
+ element(19, ATuple) -> ok;
+ true -> error end
+ end, error),
ok.
complex_or_guards(Config) when is_list(Config) ->
%% complex_or_1/2
- ?line ok = complex_or_1({a,b,c,d}, {1,2,3}),
- ?line ok = complex_or_1({a,b,c,d}, {1}),
- ?line ok = complex_or_1({a}, {1,2,3}),
- ?line error = complex_or_1({a}, {1}),
+ ok = complex_or_1({a,b,c,d}, {1,2,3}),
+ ok = complex_or_1({a,b,c,d}, {1}),
+ ok = complex_or_1({a}, {1,2,3}),
+ error = complex_or_1({a}, {1}),
- ?line error = complex_or_1(1, 2),
- ?line error = complex_or_1([], {a,b,c,d}),
- ?line error = complex_or_1({a,b,c,d}, []),
+ error = complex_or_1(1, 2),
+ error = complex_or_1([], {a,b,c,d}),
+ error = complex_or_1({a,b,c,d}, []),
%% complex_or_2/1
- ?line ok = complex_or_2({true,{}}),
- ?line ok = complex_or_2({false,{a}}),
- ?line ok = complex_or_2({false,{a,b,c}}),
- ?line ok = complex_or_2({true,{a,b,c,d}}),
+ ok = complex_or_2({true,{}}),
+ ok = complex_or_2({false,{a}}),
+ ok = complex_or_2({false,{a,b,c}}),
+ ok = complex_or_2({true,{a,b,c,d}}),
- ?line error = complex_or_2({blurf,{a,b,c}}),
+ error = complex_or_2({blurf,{a,b,c}}),
- ?line error = complex_or_2({true}),
- ?line error = complex_or_2({true,no_tuple}),
- ?line error = complex_or_2({true,[]}),
+ error = complex_or_2({true}),
+ error = complex_or_2({true,no_tuple}),
+ error = complex_or_2({true,[]}),
%% complex_or_3/2
- ?line ok = complex_or_3({true}, {}),
- ?line ok = complex_or_3({false}, {a}),
- ?line ok = complex_or_3({false}, {a,b,c}),
- ?line ok = complex_or_3({true}, {a,b,c,d}),
- ?line ok = complex_or_3({false}, <<1,2,3>>),
- ?line ok = complex_or_3({true}, <<1,2,3,4>>),
+ ok = complex_or_3({true}, {}),
+ ok = complex_or_3({false}, {a}),
+ ok = complex_or_3({false}, {a,b,c}),
+ ok = complex_or_3({true}, {a,b,c,d}),
+ ok = complex_or_3({false}, <<1,2,3>>),
+ ok = complex_or_3({true}, <<1,2,3,4>>),
- ?line error = complex_or_3(blurf, {a,b,c}),
+ error = complex_or_3(blurf, {a,b,c}),
- ?line error = complex_or_3({false}, <<1,2,3,4>>),
- ?line error = complex_or_3([], <<1,2>>),
- ?line error = complex_or_3({true}, 45),
- ?line error = complex_or_3(<<>>, <<>>),
+ error = complex_or_3({false}, <<1,2,3,4>>),
+ error = complex_or_3([], <<1,2>>),
+ error = complex_or_3({true}, 45),
+ error = complex_or_3(<<>>, <<>>),
%% complex_or_4/2
- ?line ok = complex_or_4(<<1,2,3>>, {true}),
- ?line ok = complex_or_4(<<1,2,3>>, {false}),
- ?line ok = complex_or_4(<<1,2,3>>, {true}),
- ?line ok = complex_or_4({1,2,3}, {true}),
- ?line error = complex_or_4({1,2,3,4}, {false}),
+ ok = complex_or_4(<<1,2,3>>, {true}),
+ ok = complex_or_4(<<1,2,3>>, {false}),
+ ok = complex_or_4(<<1,2,3>>, {true}),
+ ok = complex_or_4({1,2,3}, {true}),
+ error = complex_or_4({1,2,3,4}, {false}),
- ?line error = complex_or_4(<<1,2,3,4>>, []),
- ?line error = complex_or_4([], {true}),
+ error = complex_or_4(<<1,2,3,4>>, []),
+ error = complex_or_4([], {true}),
%% complex_or_5/2
- ?line ok = complex_or_5(<<1>>, {false}),
- ?line ok = complex_or_5(<<1,2,3>>, {true}),
- ?line ok = complex_or_5(<<1,2,3,4>>, {false}),
- ?line ok = complex_or_5({1,2,3}, {false}),
- ?line ok = complex_or_5({1,2,3,4}, {false}),
+ ok = complex_or_5(<<1>>, {false}),
+ ok = complex_or_5(<<1,2,3>>, {true}),
+ ok = complex_or_5(<<1,2,3,4>>, {false}),
+ ok = complex_or_5({1,2,3}, {false}),
+ ok = complex_or_5({1,2,3,4}, {false}),
- ?line error = complex_or_5(blurf, {false}),
- ?line error = complex_or_5(<<1>>, klarf),
- ?line error = complex_or_5(blurf, klarf),
+ error = complex_or_5(blurf, {false}),
+ error = complex_or_5(<<1>>, klarf),
+ error = complex_or_5(blurf, klarf),
%% complex_or_6/2
- ?line ok = complex_or_6({true,true}, {1,2,3,4}),
- ?line ok = complex_or_6({true,true}, <<1,2,3,4>>),
- ?line ok = complex_or_6({false,false}, <<1,2,3,4>>),
- ?line ok = complex_or_6({false,true}, <<1>>),
- ?line ok = complex_or_6({true,false}, {1}),
- ?line ok = complex_or_6({true,true}, {1}),
+ ok = complex_or_6({true,true}, {1,2,3,4}),
+ ok = complex_or_6({true,true}, <<1,2,3,4>>),
+ ok = complex_or_6({false,false}, <<1,2,3,4>>),
+ ok = complex_or_6({false,true}, <<1>>),
+ ok = complex_or_6({true,false}, {1}),
+ ok = complex_or_6({true,true}, {1}),
- ?line error = complex_or_6({false,false}, {1}),
+ error = complex_or_6({false,false}, {1}),
- ?line error = complex_or_6({true}, {1,2,3,4}),
- ?line error = complex_or_6({}, {1,2,3,4}),
- ?line error = complex_or_6([], {1,2,3,4}),
- ?line error = complex_or_6([], {1,2,3,4}),
- ?line error = complex_or_6({true,false}, klurf),
+ error = complex_or_6({true}, {1,2,3,4}),
+ error = complex_or_6({}, {1,2,3,4}),
+ error = complex_or_6([], {1,2,3,4}),
+ error = complex_or_6([], {1,2,3,4}),
+ error = complex_or_6({true,false}, klurf),
ok.
@@ -753,79 +753,79 @@ and_guard(Config) when is_list(Config) ->
%% 'and' combinations of literal true/false.
- ?line check(fun() -> if true and false -> ok; true -> error end end, error),
- ?line check(fun() -> if false and true -> ok; true -> error end end, error),
- ?line check(fun() -> if true and true -> ok end end, ok),
- ?line check(fun() -> if false and false -> ok; true -> error end end, error),
-
- ?line check(fun() -> if glurf and true -> ok; true -> error end end, error),
- ?line check(fun() -> if true and glurf -> ok; true -> error end end, error),
- ?line check(fun() -> if glurf and glurf -> ok; true -> error end end, error),
-
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} =
- (catch if true and false -> ok;
- false and true -> ok;
- false and false -> ok
- end),
- exit
- end, exit),
+ check(fun() -> if true and false -> ok; true -> error end end, error),
+ check(fun() -> if false and true -> ok; true -> error end end, error),
+ check(fun() -> if true and true -> ok end end, ok),
+ check(fun() -> if false and false -> ok; true -> error end end, error),
+
+ check(fun() -> if glurf and true -> ok; true -> error end end, error),
+ check(fun() -> if true and glurf -> ok; true -> error end end, error),
+ check(fun() -> if glurf and glurf -> ok; true -> error end end, error),
+
+ check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if true and false -> ok;
+ false and true -> ok;
+ false and false -> ok
+ end),
+ exit
+ end, exit),
%% 'and' combinations of true/false in variables.
True = id(true),
False = id(false),
- ?line check(fun() -> if True and False -> ok; true -> error end end, error),
- ?line check(fun() -> if False and True -> ok; true -> error end end, error),
- ?line check(fun() -> if True and True -> ok end end, ok),
- ?line check(fun() -> if False and False -> ok; true -> error end end, error),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} =
- (catch if True and False -> ok;
- False and True -> ok;
- False and False -> ok
- end),
- exit
- end, exit),
+ check(fun() -> if True and False -> ok; true -> error end end, error),
+ check(fun() -> if False and True -> ok; true -> error end end, error),
+ check(fun() -> if True and True -> ok end end, ok),
+ check(fun() -> if False and False -> ok; true -> error end end, error),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True and False -> ok;
+ False and True -> ok;
+ False and False -> ok
+ end),
+ exit
+ end, exit),
%% 'and' combinations of true/false and a non-boolean in variables.
Glurf = id(glurf),
- ?line check(fun() -> if True and Glurf -> ok; true -> error end end, error),
- ?line check(fun() -> if Glurf and True -> ok; true -> error end end, error),
- ?line check(fun() -> if True and True -> ok end end, ok),
- ?line check(fun() -> if Glurf and Glurf -> ok; true -> error end end, error),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} =
- (catch if True and Glurf -> ok;
- Glurf and True -> ok;
- Glurf and Glurf -> ok
- end),
- exit
- end, exit),
+ check(fun() -> if True and Glurf -> ok; true -> error end end, error),
+ check(fun() -> if Glurf and True -> ok; true -> error end end, error),
+ check(fun() -> if True and True -> ok end end, ok),
+ check(fun() -> if Glurf and Glurf -> ok; true -> error end end, error),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True and Glurf -> ok;
+ Glurf and True -> ok;
+ Glurf and Glurf -> ok
+ end),
+ exit
+ end, exit),
%% 'and' combinations of true/false with errors.
ATuple = id({a,b,c}),
- ?line check(fun() -> if True and element(42, ATuple) -> ok;
- true -> error end end, error),
- ?line check(fun() -> if element(42, ATuple) and True -> ok;
- true -> error end end, error),
- ?line check(fun() -> if True and True -> ok end end, ok),
- ?line check(fun() -> if element(42, ATuple) and element(42, ATuple) -> ok;
- true -> error end end, error),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} =
- (catch if True and element(42, ATuple) -> ok;
- element(42, ATuple) and True -> ok;
- element(42, ATuple) and element(42, ATuple) -> ok
- end),
+ check(fun() -> if True and element(42, ATuple) -> ok;
+ true -> error end end, error),
+ check(fun() -> if element(42, ATuple) and True -> ok;
+ true -> error end end, error),
+ check(fun() -> if True and True -> ok end end, ok),
+ check(fun() -> if element(42, ATuple) and element(42, ATuple) -> ok;
+ true -> error end end, error),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} =
+ (catch if True and element(42, ATuple) -> ok;
+ element(42, ATuple) and True -> ok;
+ element(42, ATuple) and element(42, ATuple) -> ok
+ end),
exit
end, exit),
- ?line ok = relprod({'Set',a,b}, {'Set',a,b}),
+ ok = relprod({'Set',a,b}, {'Set',a,b}),
ok = and_same_var(42),
{'EXIT',{if_clause,_}} = (catch and_same_var(x)),
@@ -844,18 +844,18 @@ relprod(R1, R2) when (erlang:size(R1) =:= 3) and (erlang:element(1,R1) =:= 'Set'
xor_guard(Config) when is_list(Config) ->
%% 'xor' combinations of literal true/false.
- ?line check(fun() -> if true xor false -> ok end end, ok),
- ?line check(fun() -> if false xor true -> ok end end, ok),
- ?line check(fun() -> if true xor true -> ok; true -> error end end, error),
- ?line check(fun() -> if false xor false -> ok; true -> error end end, error),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} = (catch if false xor false -> ok end),
- exit
- end, exit),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} = (catch if true xor true -> ok end),
- exit
- end, exit),
+ check(fun() -> if true xor false -> ok end end, ok),
+ check(fun() -> if false xor true -> ok end end, ok),
+ check(fun() -> if true xor true -> ok; true -> error end end, error),
+ check(fun() -> if false xor false -> ok; true -> error end end, error),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if false xor false -> ok end),
+ exit
+ end, exit),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if true xor true -> ok end),
+ exit
+ end, exit),
%% 'xor' combinations using variables containing true/false.
@@ -863,18 +863,18 @@ xor_guard(Config) when is_list(Config) ->
True = id(true),
False = id(false),
- ?line check(fun() -> if True xor False -> ok end end, ok),
- ?line check(fun() -> if False xor True -> ok end end, ok),
- ?line check(fun() -> if True xor True -> ok; true -> error end end, error),
- ?line check(fun() -> if False xor False -> ok; true -> error end end, error),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} = (catch if False xor False -> ok end),
- exit
- end, exit),
- ?line check(fun() ->
- {'EXIT',{if_clause,_}} = (catch if True xor True -> ok end),
- exit
- end, exit),
+ check(fun() -> if True xor False -> ok end end, ok),
+ check(fun() -> if False xor True -> ok end end, ok),
+ check(fun() -> if True xor True -> ok; true -> error end end, error),
+ check(fun() -> if False xor False -> ok; true -> error end end, error),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if False xor False -> ok end),
+ exit
+ end, exit),
+ check(fun() ->
+ {'EXIT',{if_clause,_}} = (catch if True xor True -> ok end),
+ exit
+ end, exit),
ok.
@@ -883,53 +883,53 @@ more_xor_guards(Config) when is_list(Config) ->
False = id(false),
ATuple = id({false,true,gurka}),
- ?line check(fun() ->
- if element(42, ATuple) xor False -> ok;
- true -> error end
- end, error),
-
- ?line check(fun() ->
- if False xor element(42, ATuple) xor False -> ok;
- true -> error end
- end, error),
-
- ?line check(fun() ->
- if element(18, ATuple) xor element(42, ATuple) -> ok;
- true -> error end
- end, error),
-
- ?line check(fun() ->
- if True xor element(42, ATuple) -> ok;
- true -> error end
- end, error),
-
- ?line check(fun() ->
- if element(42, ATuple) xor True -> ok;
- true -> error end
- end, error),
+ check(fun() ->
+ if element(42, ATuple) xor False -> ok;
+ true -> error end
+ end, error),
+
+ check(fun() ->
+ if False xor element(42, ATuple) xor False -> ok;
+ true -> error end
+ end, error),
+
+ check(fun() ->
+ if element(18, ATuple) xor element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ check(fun() ->
+ if True xor element(42, ATuple) -> ok;
+ true -> error end
+ end, error),
+
+ check(fun() ->
+ if element(42, ATuple) xor True -> ok;
+ true -> error end
+ end, error),
ok.
build_in_guard(Config) when is_list(Config) ->
SubBin = <<5.0/float>>,
- ?line B = <<1,SubBin/binary,3.5/float>>,
- ?line if
- B =:= <<1,SubBin/binary,3.5/float>> -> ok
- end.
+ B = <<1,SubBin/binary,3.5/float>>,
+ if
+ B =:= <<1,SubBin/binary,3.5/float>> -> ok
+ end.
old_guard_tests(Config) when list(Config) ->
%% Check that all the old guard tests are still recognized.
- ?line list = og(Config),
- ?line atom = og(an_atom),
- ?line binary = og(<<1,2>>),
- ?line float = og(3.14),
- ?line integer = og(43),
- ?line a_function = og(fun() -> ok end),
- ?line pid = og(self()),
- ?line reference = og(make_ref()),
- ?line tuple = og({}),
-
- ?line number = on(45.333),
- ?line number = on(-19),
+ list = og(Config),
+ atom = og(an_atom),
+ binary = og(<<1,2>>),
+ float = og(3.14),
+ integer = og(43),
+ a_function = og(fun() -> ok end),
+ pid = og(self()),
+ reference = og(make_ref()),
+ tuple = og({}),
+
+ number = on(45.333),
+ number = on(-19),
ok.
og(V) when atom(V) -> atom;
@@ -948,8 +948,8 @@ on(V) when number(V) -> number;
on(_) -> not_number.
gbif(Config) when is_list(Config) ->
- ?line error = gbif_1(1, {false,true}),
- ?line ok = gbif_1(2, {false,true}),
+ error = gbif_1(1, {false,true}),
+ ok = gbif_1(2, {false,true}),
ok.
gbif_1(P, T) when element(P, T) -> ok;
@@ -957,57 +957,57 @@ gbif_1(_, _) -> error.
t_is_boolean(Config) when is_list(Config) ->
- ?line true = is_boolean(true),
- ?line true = is_boolean(false),
- ?line true = is_boolean(id(true)),
- ?line true = is_boolean(id(false)),
-
- ?line false = is_boolean(glurf),
- ?line false = is_boolean(id(glurf)),
-
- ?line false = is_boolean([]),
- ?line false = is_boolean(id([])),
- ?line false = is_boolean(42),
- ?line false = is_boolean(id(-42)),
-
- ?line false = is_boolean(math:pi()),
- ?line false = is_boolean(384793478934378924978439789873478934897),
-
- ?line false = is_boolean(id(self())),
- ?line false = is_boolean(id({x,y,z})),
- ?line false = is_boolean(id([a,b,c])),
- ?line false = is_boolean(id(make_ref())),
- ?line false = is_boolean(id(<<1,2,3>>)),
- ?line false = is_boolean({id(x),y,z}),
- ?line false = is_boolean([id(a),b,c]),
-
- ?line ok = bool(true),
- ?line ok = bool(false),
- ?line ok = bool(id(true)),
- ?line ok = bool(id(false)),
-
- ?line error = bool(glurf),
- ?line error = bool(id(glurf)),
-
- ?line error = bool([]),
- ?line error = bool(id([])),
- ?line error = bool(42),
- ?line error = bool(id(-42)),
-
- ?line error = bool(math:pi()),
- ?line error = bool(384793478934378924978439789873478934897),
-
- ?line error = bool(id(self())),
- ?line error = bool(id({x,y,z})),
- ?line error = bool(id([a,b,c])),
- ?line error = bool(id(make_ref())),
- ?line error = bool(id(<<1,2,3>>)),
-
- ?line true = my_is_bool(true),
- ?line true = my_is_bool(false),
- ?line false = my_is_bool([]),
- ?line false = my_is_bool([1,2,3,4]),
- ?line false = my_is_bool({a,b,c}),
+ true = is_boolean(true),
+ true = is_boolean(false),
+ true = is_boolean(id(true)),
+ true = is_boolean(id(false)),
+
+ false = is_boolean(glurf),
+ false = is_boolean(id(glurf)),
+
+ false = is_boolean([]),
+ false = is_boolean(id([])),
+ false = is_boolean(42),
+ false = is_boolean(id(-42)),
+
+ false = is_boolean(math:pi()),
+ false = is_boolean(384793478934378924978439789873478934897),
+
+ false = is_boolean(id(self())),
+ false = is_boolean(id({x,y,z})),
+ false = is_boolean(id([a,b,c])),
+ false = is_boolean(id(make_ref())),
+ false = is_boolean(id(<<1,2,3>>)),
+ false = is_boolean({id(x),y,z}),
+ false = is_boolean([id(a),b,c]),
+
+ ok = bool(true),
+ ok = bool(false),
+ ok = bool(id(true)),
+ ok = bool(id(false)),
+
+ error = bool(glurf),
+ error = bool(id(glurf)),
+
+ error = bool([]),
+ error = bool(id([])),
+ error = bool(42),
+ error = bool(id(-42)),
+
+ error = bool(math:pi()),
+ error = bool(384793478934378924978439789873478934897),
+
+ error = bool(id(self())),
+ error = bool(id({x,y,z})),
+ error = bool(id([a,b,c])),
+ error = bool(id(make_ref())),
+ error = bool(id(<<1,2,3>>)),
+
+ true = my_is_bool(true),
+ true = my_is_bool(false),
+ false = my_is_bool([]),
+ false = my_is_bool([1,2,3,4]),
+ false = my_is_bool({a,b,c}),
ok.
@@ -1048,18 +1048,18 @@ is_function_2(Config) when is_list(Config) ->
end.
tricky(Config) when is_list(Config) ->
- ?line not_ok = tricky_1(1, 2),
- ?line not_ok = tricky_1(1, blurf),
- ?line not_ok = tricky_1(foo, 2),
- ?line not_ok = tricky_1(a, b),
-
- ?line error = tricky_2(0.5),
- ?line error = tricky_2(a),
- ?line error = tricky_2({a,b,c}),
-
- ?line false = rb(100000, [1], 42),
- ?line true = rb(100000, [], 42),
- ?line true = rb(555, [a,b,c], 19),
+ not_ok = tricky_1(1, 2),
+ not_ok = tricky_1(1, blurf),
+ not_ok = tricky_1(foo, 2),
+ not_ok = tricky_1(a, b),
+
+ error = tricky_2(0.5),
+ error = tricky_2(a),
+ error = tricky_2({a,b,c}),
+
+ false = rb(100000, [1], 42),
+ true = rb(100000, [], 42),
+ true = rb(555, [a,b,c], 19),
ok.
tricky_1(X, Y) when abs((X == 1) or (Y == 2)) -> ok;
@@ -1097,40 +1097,40 @@ rb(_, _, _) -> false.
rel_ops(Config) when is_list(Config) ->
- ?line ?T(=/=, 1, 1.0),
- ?line ?F(=/=, 2, 2),
- ?line ?F(=/=, {a}, {a}),
+ ?T(=/=, 1, 1.0),
+ ?F(=/=, 2, 2),
+ ?F(=/=, {a}, {a}),
- ?line ?F(/=, a, a),
- ?line ?F(/=, 0, 0.0),
- ?line ?T(/=, 0, 1),
- ?line ?F(/=, {a}, {a}),
+ ?F(/=, a, a),
+ ?F(/=, 0, 0.0),
+ ?T(/=, 0, 1),
+ ?F(/=, {a}, {a}),
- ?line ?T(==, 1, 1.0),
- ?line ?F(==, a, {}),
+ ?T(==, 1, 1.0),
+ ?F(==, a, {}),
- ?line ?F(=:=, 1, 1.0),
- ?line ?T(=:=, 42.0, 42.0),
+ ?F(=:=, 1, 1.0),
+ ?T(=:=, 42.0, 42.0),
- ?line ?F(>, a, b),
- ?line ?T(>, 42, 1.0),
- ?line ?F(>, 42, 42.0),
+ ?F(>, a, b),
+ ?T(>, 42, 1.0),
+ ?F(>, 42, 42.0),
- ?line ?T(<, a, b),
- ?line ?F(<, 42, 1.0),
- ?line ?F(<, 42, 42.0),
+ ?T(<, a, b),
+ ?F(<, 42, 1.0),
+ ?F(<, 42, 42.0),
- ?line ?T(=<, 1.5, 5),
- ?line ?F(=<, -9, -100.344),
- ?line ?T(=<, 42, 42.0),
+ ?T(=<, 1.5, 5),
+ ?F(=<, -9, -100.344),
+ ?T(=<, 42, 42.0),
- ?line ?T(>=, 42, 42.0),
- ?line ?F(>=, a, b),
- ?line ?T(>=, 1.0, 0),
+ ?T(>=, 42, 42.0),
+ ?F(>=, a, b),
+ ?T(>=, 1.0, 0),
%% Coverage of beam_block:is_exact_eq_ok/1 and collect/1.
- ?line true = any_atom /= id(42),
- ?line true = [] /= id(42),
+ true = any_atom /= id(42),
+ true = [] /= id(42),
ok.
@@ -1371,10 +1371,10 @@ literal_type_tests(Config) when is_list(Config) ->
literal_type_tests_1(Config) ->
%% Generate an Erlang module with all different type of type tests.
- ?line Tests = make_test([{T,L} || T <- type_tests(), L <- literals()] ++
+ Tests = make_test([{T,L} || T <- type_tests(), L <- literals()] ++
[{is_function,L1,L2} ||
L1 <- literals(), L2 <- literals()]),
- ?line Mod = literal_test,
+ Mod = literal_test,
Anno = erl_anno:new(0),
Func = {function, Anno, test, 0, [{clause,Anno,[],[],Tests}]},
Form = [{attribute,Anno,module,Mod},
@@ -1382,24 +1382,24 @@ literal_type_tests_1(Config) ->
Func, {eof,Anno}],
%% Print generated code for inspection.
- ?line lists:foreach(fun (F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Form),
+ lists:foreach(fun (F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Form),
%% Test compile:form/1. This implies full optimization (default).
- ?line {ok,Mod,Code1} = compile:forms(Form),
- ?line smoke_disasm(Config, Mod, Code1),
- ?line {module,Mod} = code:load_binary(Mod, Mod, Code1),
- ?line Mod:test(),
- ?line true = code:delete(Mod),
- ?line code:purge(Mod),
+ {ok,Mod,Code1} = compile:forms(Form),
+ smoke_disasm(Config, Mod, Code1),
+ {module,Mod} = code:load_binary(Mod, Mod, Code1),
+ Mod:test(),
+ true = code:delete(Mod),
+ code:purge(Mod),
%% Test compile:form/2. Turn off all optimizations.
- ?line {ok,Mod,Code2} = compile:forms(Form, [binary,report,time,
+ {ok,Mod,Code2} = compile:forms(Form, [binary,report,time,
no_copt,no_postopt]),
- ?line smoke_disasm(Config, Mod, Code2),
- ?line {module,Mod} = code:load_binary(Mod, Mod, Code2),
- ?line Mod:test(),
- ?line true = code:delete(Mod),
- ?line code:purge(Mod),
+ smoke_disasm(Config, Mod, Code2),
+ {module,Mod} = code:load_binary(Mod, Mod, Code2),
+ Mod:test(),
+ true = code:delete(Mod),
+ code:purge(Mod),
ok.
make_test([{T,L1,L2}|Ts]) ->
@@ -1427,7 +1427,7 @@ test(T, L1, L2) ->
{match,Anno,{atom,Anno,Val},hd(E)}.
smoke_disasm(Config, Mod, Bin) ->
- Priv = ?config(priv_dir, Config),
+ Priv = proplists:get_value(priv_dir, Config),
File = filename:join(Priv, atom_to_list(Mod)++".beam"),
ok = file:write_file(File, Bin),
test_lib:smoke_disasm(File).
@@ -1459,30 +1459,30 @@ type_tests() ->
is_function].
basic_andalso_orelse(Config) when is_list(Config) ->
- ?line T = id({type,integers,23,42}),
- ?line 65 = if
- ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso
- element(2, T)) == integers ->
- element(3, T) + element(4, T);
- true -> error
- end,
- ?line 65 = case [] of
- [] when ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso
- element(2, T)) == integers ->
- element(3, T) + element(4, T)
- end,
-
- ?line 42 = basic_rt({type,integers,40,2}),
- ?line 5.0 = basic_rt({vector,{3.0,4.0}}),
- ?line 20 = basic_rt(['+',3,7]),
- ?line {'Set',a,b} = basic_rt({{'Set',a,b},{'Set',a,b}}),
- ?line 12 = basic_rt({klurf,4}),
-
- ?line error = basic_rt({type,integers,40,2,3}),
- ?line error = basic_rt({kalle,integers,40,2}),
- ?line error = basic_rt({kalle,integers,40,2}),
- ?line error = basic_rt({1,2}),
- ?line error = basic_rt([]),
+ T = id({type,integers,23,42}),
+ 65 = if
+ ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso
+ element(2, T)) == integers ->
+ element(3, T) + element(4, T);
+ true -> error
+ end,
+ 65 = case [] of
+ [] when ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso
+ element(2, T)) == integers ->
+ element(3, T) + element(4, T)
+ end,
+
+ 42 = basic_rt({type,integers,40,2}),
+ 5.0 = basic_rt({vector,{3.0,4.0}}),
+ 20 = basic_rt(['+',3,7]),
+ {'Set',a,b} = basic_rt({{'Set',a,b},{'Set',a,b}}),
+ 12 = basic_rt({klurf,4}),
+
+ error = basic_rt({type,integers,40,2,3}),
+ error = basic_rt({kalle,integers,40,2}),
+ error = basic_rt({kalle,integers,40,2}),
+ error = basic_rt({1,2}),
+ error = basic_rt([]),
RelProdBody =
fun(R1, R2) ->
@@ -1493,7 +1493,7 @@ basic_andalso_orelse(Config) when is_list(Config) ->
end
end,
- ?line ok = RelProdBody({'Set',a,b}, {'Set',a,b}),
+ ok = RelProdBody({'Set',a,b}, {'Set',a,b}),
%% 'andalso'/'orelse' with calls known to fail already at compile time.
%% Used to crash the code generator.
@@ -1564,14 +1564,14 @@ traverse_dcd({Cont,Recs},Log,Fun) ->
check_qlc_hrl(Config) when is_list(Config) ->
St = {r1,false,dum},
- ?line foo = cqlc(qlc, q, [{lc,1,2,3}], St),
- ?line foo = cqlc(qlc, q, [{lc,1,2,3},b], St),
- ?line St = cqlc(qlc, q, [], St),
- ?line St = cqlc(qlc, blurf, [{lc,1,2,3},b], St),
- ?line St = cqlc(q, q, [{lc,1,2,3},b], St),
- ?line St = cqlc(qlc, q, [{lc,1,2,3},b,c], St),
- ?line St = cqlc(qlc, q, [a,b], St),
- ?line {r1,true,kalle} = cqlc(qlc, q, [{lc,1,2,3},b], {r1,true,kalle}),
+ foo = cqlc(qlc, q, [{lc,1,2,3}], St),
+ foo = cqlc(qlc, q, [{lc,1,2,3},b], St),
+ St = cqlc(qlc, q, [], St),
+ St = cqlc(qlc, blurf, [{lc,1,2,3},b], St),
+ St = cqlc(q, q, [{lc,1,2,3},b], St),
+ St = cqlc(qlc, q, [{lc,1,2,3},b,c], St),
+ St = cqlc(qlc, q, [a,b], St),
+ {r1,true,kalle} = cqlc(qlc, q, [{lc,1,2,3},b], {r1,true,kalle}),
ok.
%% From erl_lint.erl; original name was check_qlc_hrl/4.
@@ -1588,13 +1588,13 @@ cqlc(M, F, As, St) ->
%% OTP-7679: Thanks to Hunter Morris.
andalso_semi(Config) when is_list(Config) ->
- ?line ok = andalso_semi_foo(0),
- ?line ok = andalso_semi_foo(1),
- ?line fc(catch andalso_semi_foo(2)),
+ ok = andalso_semi_foo(0),
+ ok = andalso_semi_foo(1),
+ fc(catch andalso_semi_foo(2)),
- ?line ok = andalso_semi_bar([a,b,c]),
- ?line ok = andalso_semi_bar(1),
- ?line fc(catch andalso_semi_bar([a,b])),
+ ok = andalso_semi_bar([a,b,c]),
+ ok = andalso_semi_bar(1),
+ fc(catch andalso_semi_bar([a,b])),
ok.
andalso_semi_foo(Bar) when is_integer(Bar) andalso Bar =:= 0; Bar =:= 1 ->
@@ -1605,20 +1605,20 @@ andalso_semi_bar(Bar) when is_list(Bar) andalso length(Bar) =:= 3; Bar =:= 1 ->
t_tuple_size(Config) when is_list(Config) ->
- ?line 10 = do_tuple_size({1,2,3,4}),
- ?line fc(catch do_tuple_size({1,2,3})),
- ?line fc(catch do_tuple_size(42)),
+ 10 = do_tuple_size({1,2,3,4}),
+ fc(catch do_tuple_size({1,2,3})),
+ fc(catch do_tuple_size(42)),
- ?line error = ludicrous_tuple_size({a,b,c}),
- ?line error = ludicrous_tuple_size([a,b,c]),
+ error = ludicrous_tuple_size({a,b,c}),
+ error = ludicrous_tuple_size([a,b,c]),
%% Test the "unsafe case" - the register assigned the tuple size is
%% not killed.
- ?line DataDir = test_lib:get_data_dir(Config),
- ?line File = filename:join(DataDir, "guard_SUITE_tuple_size"),
- ?line {ok,Mod,Code} = compile:file(File, [from_asm,binary]),
- ?line code:load_binary(Mod, File, Code),
- ?line 14 = Mod:t({1,2,3,4}),
+ DataDir = test_lib:get_data_dir(Config),
+ File = filename:join(DataDir, "guard_SUITE_tuple_size"),
+ {ok,Mod,Code} = compile:file(File, [from_asm,binary]),
+ code:load_binary(Mod, File, Code),
+ 14 = Mod:t({1,2,3,4}),
_ = code:delete(Mod),
_ = code:purge(Mod),
@@ -1647,71 +1647,70 @@ mask_error({'EXIT',{Err,_}}) ->
mask_error(Else) ->
Else.
-binary_part(doc) ->
- ["Tests the binary_part/2,3 guard (GC) bif's"];
+%% Test the binary_part/2,3 guard (GC) BIFs.
binary_part(Config) when is_list(Config) ->
%% This is more or less a copy of what the guard_SUITE in emulator
%% does to cover the guard bif's
- ?line 1 = bptest(<<1,2,3>>),
- ?line 2 = bptest(<<2,1,3>>),
- ?line error = bptest(<<1>>),
- ?line error = bptest(<<>>),
- ?line error = bptest(apa),
- ?line 3 = bptest(<<2,3,3>>),
+ 1 = bptest(<<1,2,3>>),
+ 2 = bptest(<<2,1,3>>),
+ error = bptest(<<1>>),
+ error = bptest(<<>>),
+ error = bptest(apa),
+ 3 = bptest(<<2,3,3>>),
% With one variable (pos)
- ?line 1 = bptest(<<1,2,3>>,1),
- ?line 2 = bptest(<<2,1,3>>,1),
- ?line error = bptest(<<1>>,1),
- ?line error = bptest(<<>>,1),
- ?line error = bptest(apa,1),
- ?line 3 = bptest(<<2,3,3>>,1),
+ 1 = bptest(<<1,2,3>>,1),
+ 2 = bptest(<<2,1,3>>,1),
+ error = bptest(<<1>>,1),
+ error = bptest(<<>>,1),
+ error = bptest(apa,1),
+ 3 = bptest(<<2,3,3>>,1),
% With one variable (length)
- ?line 1 = bptesty(<<1,2,3>>,1),
- ?line 2 = bptesty(<<2,1,3>>,1),
- ?line error = bptesty(<<1>>,1),
- ?line error = bptesty(<<>>,1),
- ?line error = bptesty(apa,1),
- ?line 3 = bptesty(<<2,3,3>>,2),
+ 1 = bptesty(<<1,2,3>>,1),
+ 2 = bptesty(<<2,1,3>>,1),
+ error = bptesty(<<1>>,1),
+ error = bptesty(<<>>,1),
+ error = bptesty(apa,1),
+ 3 = bptesty(<<2,3,3>>,2),
% With one variable (whole tuple)
- ?line 1 = bptestx(<<1,2,3>>,{1,1}),
- ?line 2 = bptestx(<<2,1,3>>,{1,1}),
- ?line error = bptestx(<<1>>,{1,1}),
- ?line error = bptestx(<<>>,{1,1}),
- ?line error = bptestx(apa,{1,1}),
- ?line 3 = bptestx(<<2,3,3>>,{1,2}),
+ 1 = bptestx(<<1,2,3>>,{1,1}),
+ 2 = bptestx(<<2,1,3>>,{1,1}),
+ error = bptestx(<<1>>,{1,1}),
+ error = bptestx(<<>>,{1,1}),
+ error = bptestx(apa,{1,1}),
+ 3 = bptestx(<<2,3,3>>,{1,2}),
% With two variables
- ?line 1 = bptest(<<1,2,3>>,1,1),
- ?line 2 = bptest(<<2,1,3>>,1,1),
- ?line error = bptest(<<1>>,1,1),
- ?line error = bptest(<<>>,1,1),
- ?line error = bptest(apa,1,1),
- ?line 3 = bptest(<<2,3,3>>,1,2),
+ 1 = bptest(<<1,2,3>>,1,1),
+ 2 = bptest(<<2,1,3>>,1,1),
+ error = bptest(<<1>>,1,1),
+ error = bptest(<<>>,1,1),
+ error = bptest(apa,1,1),
+ 3 = bptest(<<2,3,3>>,1,2),
% Direct (autoimported) call, these will be evaluated by the compiler...
- ?line <<2>> = binary_part(<<1,2,3>>,1,1),
- ?line <<1>> = binary_part(<<2,1,3>>,1,1),
+ <<2>> = binary_part(<<1,2,3>>,1,1),
+ <<1>> = binary_part(<<2,1,3>>,1,1),
% Compiler warnings due to constant evaluation expected (3)
- ?line badarg = ?MASK_ERROR(binary_part(<<1>>,1,1)),
- ?line badarg = ?MASK_ERROR(binary_part(<<>>,1,1)),
- ?line badarg = ?MASK_ERROR(binary_part(apa,1,1)),
- ?line <<3,3>> = binary_part(<<2,3,3>>,1,2),
+ badarg = ?MASK_ERROR(binary_part(<<1>>,1,1)),
+ badarg = ?MASK_ERROR(binary_part(<<>>,1,1)),
+ badarg = ?MASK_ERROR(binary_part(apa,1,1)),
+ <<3,3>> = binary_part(<<2,3,3>>,1,2),
% Direct call through apply
- ?line <<2>> = apply(erlang,binary_part,[<<1,2,3>>,1,1]),
- ?line <<1>> = apply(erlang,binary_part,[<<2,1,3>>,1,1]),
+ <<2>> = apply(erlang,binary_part,[<<1,2,3>>,1,1]),
+ <<1>> = apply(erlang,binary_part,[<<2,1,3>>,1,1]),
% Compiler warnings due to constant evaluation expected (3)
- ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<1>>,1,1])),
- ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<>>,1,1])),
- ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[apa,1,1])),
- ?line <<3,3>> = apply(erlang,binary_part,[<<2,3,3>>,1,2]),
+ badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<1>>,1,1])),
+ badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<>>,1,1])),
+ badarg = ?MASK_ERROR(apply(erlang,binary_part,[apa,1,1])),
+ <<3,3>> = apply(erlang,binary_part,[<<2,3,3>>,1,2]),
% Constant propagation
- ?line Bin = <<1,2,3>>,
- ?line ok = if
+ Bin = <<1,2,3>>,
+ ok = if
binary_part(Bin,1,1) =:= <<2>> ->
ok;
%% Compiler warning, clause cannot match (expected)
true ->
error
end,
- ?line ok = if
+ ok = if
binary_part(Bin,{1,1}) =:= <<2>> ->
ok;
%% Compiler warning, clause cannot match (expected)
@@ -1778,24 +1777,24 @@ bptest(_,_,_) ->
-define(FAILING(C),
if
- C -> ?t:fail(should_fail);
+ C -> ct:fail(should_fail);
true -> ok
end,
if
- true, C -> ?t:fail(should_fail);
+ true, C -> ct:fail(should_fail);
true -> ok
end).
bad_constants(Config) when is_list(Config) ->
- ?line ?FAILING(false),
- ?line ?FAILING([]),
- ?line ?FAILING([a]),
- ?line ?FAILING([Config]),
- ?line ?FAILING({a,b}),
- ?line ?FAILING({a,Config}),
- ?line ?FAILING(<<1>>),
- ?line ?FAILING(42),
- ?line ?FAILING(3.14),
+ ?FAILING(false),
+ ?FAILING([]),
+ ?FAILING([a]),
+ ?FAILING([Config]),
+ ?FAILING({a,b}),
+ ?FAILING({a,Config}),
+ ?FAILING(<<1>>),
+ ?FAILING(42),
+ ?FAILING(3.14),
ok.
bad_guards(Config) when is_list(Config) ->
@@ -1915,7 +1914,7 @@ check(F, Result) ->
Other ->
io:format("Expected: ~p\n", [Result]),
io:format(" Got: ~p\n", [Other]),
- test_server:fail()
+ ct:fail(check_failed)
end.
fc({'EXIT',{function_clause,_}}) -> ok;
diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl
index 0b92a784de..4c53b96fe6 100644
--- a/lib/compiler/test/inline_SUITE.erl
+++ b/lib/compiler/test/inline_SUITE.erl
@@ -21,7 +21,7 @@
-module(inline_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-compile(export_all).
-compile({inline,[badarg/2]}).
@@ -47,8 +47,8 @@ init_per_suite(Config) ->
[{testing_node,Node}|Config].
end_per_suite(Config) ->
- Node = ?config(testing_node, Config),
- ?t:stop_node(Node),
+ Node = proplists:get_value(testing_node, Config),
+ test_server:stop_node(Node),
ok.
init_per_group(_GroupName, Config) ->
@@ -60,16 +60,16 @@ end_per_group(_GroupName, Config) ->
attribute(Config) when is_list(Config) ->
Name = "attribute",
- ?line Src = filename:join(?config(data_dir, Config), Name),
- ?line Out = ?config(priv_dir,Config),
+ Src = filename:join(proplists:get_value(data_dir, Config), Name),
+ Out = proplists:get_value(priv_dir,Config),
- ?line {ok,attribute=Mod} = compile:file(Src, [{outdir,Out},report,time]),
- ?line Outfile = filename:join(Out, Name++".beam"),
- ?line {ok,{Mod,[{locals,Locals}]}} = beam_lib:chunks(Outfile, [locals]),
- ?line io:format("locals: ~p\n", [Locals]),
+ {ok,attribute=Mod} = compile:file(Src, [{outdir,Out},report,time]),
+ Outfile = filename:join(Out, Name++".beam"),
+ {ok,{Mod,[{locals,Locals}]}} = beam_lib:chunks(Outfile, [locals]),
+ io:format("locals: ~p\n", [Locals]),
%% The inliner should have removed all local functions.
- ?line [] = Locals,
+ [] = Locals,
ok.
@@ -89,48 +89,46 @@ attribute(Config) when is_list(Config) ->
?comp(maps_inline_test).
try_inline(Mod, Config) ->
- Node = ?config(testing_node, Config),
- ?line Src = filename:join(?config(data_dir, Config), atom_to_list(Mod)),
- ?line Out = ?config(priv_dir,Config),
+ Node = proplists:get_value(testing_node, Config),
+ Src = filename:join(proplists:get_value(data_dir, Config),
+ atom_to_list(Mod)),
+ Out = proplists:get_value(priv_dir,Config),
%% Normal compilation.
- ?line io:format("Compiling: ~s\n", [Src]),
- ?line {ok,Mod} = compile:file(Src, [{outdir,Out},report,bin_opt_info,clint]),
+ io:format("Compiling: ~s\n", [Src]),
+ {ok,Mod} = compile:file(Src, [{outdir,Out},report,bin_opt_info,clint]),
- ?line Dog = test_server:timetrap(test_server:minutes(10)),
- ?line NormalResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]),
- ?line test_server:timetrap_cancel(Dog),
+ ct:timetrap({minutes,10}),
+ NormalResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]),
%% Inlining.
- ?line io:format("Compiling with old inliner: ~s\n", [Src]),
- ?line {ok,Mod} = compile:file(Src, [{outdir,Out},report,bin_opt_info,
+ io:format("Compiling with old inliner: ~s\n", [Src]),
+ {ok,Mod} = compile:file(Src, [{outdir,Out},report,bin_opt_info,
{inline,1000},clint]),
%% Run inlined code.
- ?line Dog3 = test_server:timetrap(test_server:minutes(10)),
- ?line OldInlinedResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]),
- ?line test_server:timetrap_cancel(Dog3),
+ ct:timetrap({minutes,10}),
+ OldInlinedResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]),
%% Compare results.
- ?line compare(NormalResult, OldInlinedResult),
- ?line NormalResult = OldInlinedResult,
+ compare(NormalResult, OldInlinedResult),
+ NormalResult = OldInlinedResult,
%% Inlining.
- ?line io:format("Compiling with new inliner: ~s\n", [Src]),
- ?line {ok,Mod} = compile:file(Src, [{outdir,Out},report,
+ io:format("Compiling with new inliner: ~s\n", [Src]),
+ {ok,Mod} = compile:file(Src, [{outdir,Out},report,
bin_opt_info,inline,clint]),
%% Run inlined code.
- ?line Dog4 = test_server:timetrap(test_server:minutes(10)),
- ?line InlinedResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]),
- ?line test_server:timetrap_cancel(Dog4),
+ ct:timetrap({minutes,10}),
+ InlinedResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]),
%% Compare results.
- ?line compare(NormalResult, InlinedResult),
- ?line NormalResult = InlinedResult,
+ compare(NormalResult, InlinedResult),
+ NormalResult = InlinedResult,
%% Delete Beam file.
- ?line ok = file:delete(filename:join(Out, atom_to_list(Mod)++code:objfile_extension())),
+ ok = file:delete(filename:join(Out, atom_to_list(Mod)++code:objfile_extension())),
ok.
@@ -142,24 +140,24 @@ compare([{X,Y,RGB1}|T1], [{X,Y,RGB2}|T2]) ->
compare(T1, T2);
compare([H1|_], [H2|_]) ->
io:format("Normal = ~p, Inlined = ~p\n", [H1,H2]),
- ?t:fail();
+ ct:fail(different);
compare([], []) -> ok.
start_node(Name, Args) ->
case test_server:start_node(Name, slave, [{args,Args}]) of
{ok,Node} -> {ok, Node};
- Error -> ?line test_server:fail(Error)
+ Error -> ct:fail(Error)
end.
load_and_call(Out, Module) ->
- ?line io:format("Loading...\n",[]),
- ?line code:purge(Module),
- ?line LoadRc = code:load_abs(filename:join(Out, Module)),
- ?line {module,Module} = LoadRc,
-
- ?line io:format("Calling...\n",[]),
- ?line {Time,CallResult} = timer:tc(Module, Module, []),
- ?line io:format("Time: ~p\n", [Time]),
+ io:format("Loading...\n",[]),
+ code:purge(Module),
+ LoadRc = code:load_abs(filename:join(Out, Module)),
+ {module,Module} = LoadRc,
+
+ io:format("Calling...\n",[]),
+ {Time,CallResult} = timer:tc(Module, Module, []),
+ io:format("Time: ~p\n", [Time]),
CallResult.
%% Macros used by lists/1 below.
@@ -195,69 +193,78 @@ load_and_call(Out, Module) ->
%% Note: This module must be compiled with the inline_lists_funcs option.
lists(Config) when is_list(Config) ->
- ?line List = lists:seq(1, 20),
+ List = lists:seq(1, 20),
%% lists:map/2
- ?line ?TestHighOrder_2(map, (fun(E) ->
- R = E band 16#ff,
- put(?MODULE, [E|get(?MODULE)]),
- R
- end), List),
+ ?TestHighOrder_2(map,
+ (fun(E) ->
+ R = E band 16#ff,
+ put(?MODULE, [E|get(?MODULE)]),
+ R
+ end), List),
%% lists:flatmap/2
- ?line ?TestHighOrder_2(flatmap, (fun(E) ->
- R = lists:duplicate(E, E),
- put(?MODULE, [E|get(?MODULE)]),
- R
- end), List),
+ ?TestHighOrder_2(flatmap,
+ (fun(E) ->
+ R = lists:duplicate(E, E),
+ put(?MODULE, [E|get(?MODULE)]),
+ R
+ end), List),
%% lists:foreach/2
- ?line ?TestHighOrder_2(foreach,
- (fun(E) ->
- put(?MODULE, [E bor 7|get(?MODULE)])
- end), List),
+ ?TestHighOrder_2(foreach,
+ (fun(E) ->
+ put(?MODULE, [E bor 7|get(?MODULE)])
+ end), List),
%% lists:filter/2
- ?line ?TestHighOrder_2(filter, (fun(E) ->
- put(?MODULE, [E|get(?MODULE)]),
- (E bsr 1) band 1 =/= 0
- end), List),
+ ?TestHighOrder_2(filter,
+ (fun(E) ->
+ put(?MODULE, [E|get(?MODULE)]),
+ (E bsr 1) band 1 =/= 0
+ end), List),
%% lists:any/2
- ?line ?TestHighOrder_2(any, (fun(E) ->
- put(?MODULE, [E|get(?MODULE)]),
- false %Force it to go through all.
- end), List),
+ ?TestHighOrder_2(any,
+ (fun(E) ->
+ put(?MODULE, [E|get(?MODULE)]),
+ false %Force it to go through all.
+ end), List),
%% lists:all/2
- ?line ?TestHighOrder_2(all, (fun(E) ->
- put(?MODULE, [E|get(?MODULE)]),
- true %Force it to go through all.
- end), List),
+ ?TestHighOrder_2(all,
+ (fun(E) ->
+ put(?MODULE, [E|get(?MODULE)]),
+ true %Force it to go through all.
+ end), List),
%% lists:foldl/3
- ?line ?TestHighOrder_3(foldl, (fun(E, A) ->
- put(?MODULE, [E|get(?MODULE)]),
- A bxor E
- end), 0, List),
+ ?TestHighOrder_3(foldl,
+ (fun(E, A) ->
+ put(?MODULE, [E|get(?MODULE)]),
+ A bxor E
+ end), 0, List),
%% lists:foldr/3
- ?line ?TestHighOrder_3(foldr, (fun(E, A) ->
- put(?MODULE, [E|get(?MODULE)]),
- A bxor (bnot E)
- end), 0, List),
+ ?TestHighOrder_3(foldr,
+ (fun(E, A) ->
+ put(?MODULE, [E|get(?MODULE)]),
+ A bxor (bnot E)
+ end), 0, List),
%% lists:mapfoldl/3
- ?line ?TestHighOrder_3(mapfoldl, (fun(E, A) ->
- put(?MODULE, [E|get(?MODULE)]),
- {bnot E,A bxor (bnot E)}
- end), 0, List),
+ ?TestHighOrder_3(mapfoldl,
+ (fun(E, A) ->
+ put(?MODULE, [E|get(?MODULE)]),
+ {bnot E,A bxor (bnot E)}
+ end), 0, List),
%% lists:mapfoldr/3
- ?line ?TestHighOrder_3(mapfoldr, (fun(E, A) ->
- put(?MODULE, [E|get(?MODULE)]),
- {bnot E,A bxor (bnot E)}
- end), 0, List),
+ ?TestHighOrder_3(mapfoldr,
+ (fun(E, A) ->
+ put(?MODULE, [E|get(?MODULE)]),
+ {bnot E,A bxor (bnot E)}
+ end), 0, List),
%% Cleanup.
erase(?MODULE),
@@ -330,7 +337,7 @@ badarg(Reply, _A) ->
Reply.
otp_7223(Config) when is_list(Config) ->
- ?line {'EXIT', {{case_clause,{1}},_}} = (catch otp_7223_1(1)),
+ {'EXIT', {{case_clause,{1}},_}} = (catch otp_7223_1(1)),
ok.
-compile({inline,[{otp_7223_1,1}]}).
@@ -343,7 +350,7 @@ otp_7223_2({a}) ->
coverage(Config) when is_list(Config) ->
Mod = bsdecode,
- Src = filename:join(?config(data_dir, Config), Mod),
+ Src = filename:join(proplists:get_value(data_dir, Config), Mod),
{ok,Mod,_} = compile:file(Src, [binary,report,{inline,0},clint]),
{ok,Mod,_} = compile:file(Src, [binary,report,{inline,20},
verbose,clint]),
diff --git a/lib/compiler/test/lc_SUITE.erl b/lib/compiler/test/lc_SUITE.erl
index d10839ccf2..70c80d3353 100644
--- a/lib/compiler/test/lc_SUITE.erl
+++ b/lib/compiler/test/lc_SUITE.erl
@@ -26,9 +26,11 @@
empty_generator/1,no_export/1,shadow/1,
effect/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
test_lib:recompile(?MODULE),
@@ -59,12 +61,9 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog = test_server:timetrap(?t:minutes(1)),
- [{watchdog,Dog}|Config].
+ Config.
end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
ok.
basic(Config) when is_list(Config) ->
@@ -171,7 +170,7 @@ no_gen_verify(Res, A, B) ->
ShouldBe -> ok;
_ ->
io:format("A = ~p; B = ~p; Expected = ~p, actual = ~p", [A,B,ShouldBe,Res]),
- ?t:fail()
+ ct:fail(failed)
end.
no_gen_eval(Fun, Res) ->
diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl
index cff3b5deb4..14d175b92c 100644
--- a/lib/compiler/test/map_SUITE.erl
+++ b/lib/compiler/test/map_SUITE.erl
@@ -1479,7 +1479,7 @@ t_guard_fun(Config) when is_list(Config) ->
{'EXIT', {function_clause,[{?MODULE,_,[#{s:=none,v:=none}],_}|_]}} -> ok;
{'EXIT', {{case_clause,_},_}} -> {comment,inlined};
Other ->
- test_server:fail({no_match, Other})
+ ct:fail({no_match, Other})
end.
@@ -1565,7 +1565,7 @@ t_build_and_match_empty_val(Config) when is_list(Config) ->
{'EXIT',{function_clause,_}} -> ok;
{'EXIT', {{case_clause,_},_}} -> {comment,inlined};
Other ->
- test_server:fail({no_match, Other})
+ ct:fail({no_match, Other})
end.
t_build_and_match_val(Config) when is_list(Config) ->
@@ -1583,7 +1583,7 @@ t_build_and_match_val(Config) when is_list(Config) ->
{'EXIT',{function_clause,_}} -> ok;
{'EXIT', {{case_clause,_},_}} -> {comment,inlined};
Other ->
- test_server:fail({no_match, Other})
+ ct:fail({no_match, Other})
end.
t_build_and_match_nil(Config) when is_list(Config) ->
@@ -1885,7 +1885,7 @@ register_corruption_dummy_call(A,B,C) -> {A,B,C}.
t_frequency_table(Config) when is_list(Config) ->
- random:seed({13,1337,54}), % pseudo random
+ rand:seed(exsplus, {13,1337,54}), % pseudo random
N = 100000,
Ts = rand_terms(N),
#{ n:=N, tf := Tf } = frequency_table(Ts,#{ n=>0, tf => #{}}),
@@ -1928,7 +1928,7 @@ rand_terms(0) -> [];
rand_terms(N) -> [rand_term()|rand_terms(N-1)].
rand_term() ->
- case random:uniform(6) of
+ case rand:uniform(6) of
1 -> rand_binary();
2 -> rand_number();
3 -> rand_atom();
@@ -1938,21 +1938,21 @@ rand_term() ->
end.
rand_binary() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> <<>>;
2 -> <<"hi">>;
3 -> <<"message text larger than 64 bytes. yep, message text larger than 64 bytes.">>
end.
rand_number() ->
- case random:uniform(3) of
- 1 -> random:uniform(5);
- 2 -> float(random:uniform(5));
- 3 -> 1 bsl (63 + random:uniform(3))
+ case rand:uniform(3) of
+ 1 -> rand:uniform(5);
+ 2 -> float(rand:uniform(5));
+ 3 -> 1 bsl (63 + rand:uniform(3))
end.
rand_atom() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> hi;
2 -> some_atom;
3 -> some_other_atom
@@ -1960,21 +1960,21 @@ rand_atom() ->
rand_tuple() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> {ok, rand_term()}; % careful
2 -> {1, 2, 3};
3 -> {<<"yep">>, 1337}
end.
rand_list() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> "hi";
2 -> [1,rand_term()]; % careful
3 -> [improper|list]
end.
rand_map() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> #{ hi => 3 };
2 -> #{ wat => rand_term(), other => 3 }; % careful
3 -> #{ hi => 42, other => 42, yet_anoter => 1337 }
diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl
index 67d668f650..41fa1603ef 100644
--- a/lib/compiler/test/match_SUITE.erl
+++ b/lib/compiler/test/match_SUITE.erl
@@ -26,7 +26,7 @@
selectify/1,underscore/1,match_map/1,map_vars_used/1,
coverage/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -55,10 +55,10 @@ end_per_group(_GroupName, Config) ->
pmatch(Config) when is_list(Config) ->
- ?line ok = doit(1),
- ?line ok = doit(2),
- ?line {error,baz} = doit(3),
- ?line {error,foobar} = doit(4),
+ ok = doit(1),
+ ok = doit(2),
+ {error,baz} = doit(3),
+ {error,foobar} = doit(4),
ok.
%% Thanks to Tobias Lindahl (HiPE).
@@ -78,13 +78,13 @@ doit(X) ->
end.
mixed(Config) when is_list(Config) ->
- ?line glufs = mixit(1),
- ?line klafs = mixit(2),
- ?line fnurra = mixit(3),
- ?line usch = mixit(4),
- ?line {error,blurf} = mixit(5),
- ?line {error,87987987} = mixit(6),
- ?line {error,{a,b,c}} = mixit(7),
+ glufs = mixit(1),
+ klafs = mixit(2),
+ fnurra = mixit(3),
+ usch = mixit(4),
+ {error,blurf} = mixit(5),
+ {error,87987987} = mixit(6),
+ {error,{a,b,c}} = mixit(7),
ok.
mixit(X) ->
@@ -106,41 +106,41 @@ mixit(X) ->
aliases(Config) when is_list(Config) ->
%% Lists/strings.
- ?line ok = str_alias("abc"),
- ?line ok = str_alias("def"),
- ?line ok = str_alias("ghi"),
- ?line ok = str_alias("klm"),
- ?line ok = str_alias("qrs"),
- ?line ok = str_alias("xy"),
- ?line ok = str_alias(""),
- ?line ok = str_alias([]),
- ?line error = str_alias("blurf"),
+ ok = str_alias("abc"),
+ ok = str_alias("def"),
+ ok = str_alias("ghi"),
+ ok = str_alias("klm"),
+ ok = str_alias("qrs"),
+ ok = str_alias("xy"),
+ ok = str_alias(""),
+ ok = str_alias([]),
+ error = str_alias("blurf"),
%% Characters/integers.
- ?line ok = char_alias($v),
- ?line ok = char_alias(118),
- ?line ok = char_alias($w),
- ?line ok = char_alias(119),
- ?line ok = char_alias(42),
- ?line ok = char_alias(3.0),
- ?line error = char_alias($_),
- ?line error = char_alias(0),
-
- ?line {42,42,42} = three(42),
-
- ?line {1,42,99,1,42,99} = tuple_alias({1,42,99}),
- ?line {-10,20,-10,20,-10,20} = tuple_alias({-10,20}),
- ?line 6 = tup_lit_alias({1,2,3}),
- ?line 6 = tup_lit_alias_rev({1,2,3}),
-
- ?line {42,42,42,42} = multiple_aliases_1(42),
- ?line {7,7,7} = multiple_aliases_2(7),
- ?line {{a,b},{a,b},{a,b}} = multiple_aliases_3({a,b}),
+ ok = char_alias($v),
+ ok = char_alias(118),
+ ok = char_alias($w),
+ ok = char_alias(119),
+ ok = char_alias(42),
+ ok = char_alias(3.0),
+ error = char_alias($_),
+ error = char_alias(0),
+
+ {42,42,42} = three(42),
+
+ {1,42,99,1,42,99} = tuple_alias({1,42,99}),
+ {-10,20,-10,20,-10,20} = tuple_alias({-10,20}),
+ 6 = tup_lit_alias({1,2,3}),
+ 6 = tup_lit_alias_rev({1,2,3}),
+
+ {42,42,42,42} = multiple_aliases_1(42),
+ {7,7,7} = multiple_aliases_2(7),
+ {{a,b},{a,b},{a,b}} = multiple_aliases_3({a,b}),
%% Lists/literals.
- ?line {a,b} = list_alias1([a,b]),
- ?line {a,b} = list_alias2([a,b]),
- ?line {a,b} = list_alias3([a,b]),
+ {a,b} = list_alias1([a,b]),
+ {a,b} = list_alias2([a,b]),
+ {a,b} = list_alias3([a,b]),
%% Non-matching aliases.
none = mixed_aliases(<<42>>),
@@ -261,14 +261,14 @@ mixed_aliases(_) -> none.
%% OTP-7018.
match_in_call(Config) when is_list(Config) ->
- ?line mac_a(0),
- ?line mac_b(1),
- ?line mac_c(42),
- ?line mac_d(42),
- ?line mac_e({gurka,42}),
+ mac_a(0),
+ mac_b(1),
+ mac_c(42),
+ mac_d(42),
+ mac_e({gurka,42}),
- ?line [{2,2},{2,2}] = mac_lc([{2,any},{2,2}]),
- ?line {'EXIT',_} = (catch mac_lc([{1,1}])),
+ [{2,2},{2,2}] = mac_lc([{2,any},{2,2}]),
+ {'EXIT',_} = (catch mac_lc([{1,1}])),
ok.
@@ -313,8 +313,8 @@ gurka({gurka,X}, X) -> ok.
untuplify(Config) when is_list(Config) ->
%% We do this to cover sys_core_fold:unalias_pat/1.
- ?line {1,2,3,4,alias,{[1,2],{3,4},alias}} = untuplify_1([1,2], {3,4}, alias),
- ?line error = untuplify_1([1,2], {3,4}, 42),
+ {1,2,3,4,alias,{[1,2],{3,4},alias}} = untuplify_1([1,2], {3,4}, alias),
+ error = untuplify_1([1,2], {3,4}, 42),
ok.
untuplify_1(A, B, C) ->
@@ -329,11 +329,11 @@ untuplify_1(A, B, C) ->
%% Coverage of beam_dead:shortcut_boolean_label/4.
shortcut_boolean(Config) when is_list(Config) ->
- ?line false = shortcut_boolean_1([0]),
- ?line true = shortcut_boolean_1({42}),
- ?line maybe = shortcut_boolean_1(self()),
- ?line {'EXIT',_} = (catch shortcut_boolean_1([a,b])),
- ?line {'EXIT',_} = (catch shortcut_boolean_1({a,b})),
+ false = shortcut_boolean_1([0]),
+ true = shortcut_boolean_1({42}),
+ maybe = shortcut_boolean_1(self()),
+ {'EXIT',_} = (catch shortcut_boolean_1([a,b])),
+ {'EXIT',_} = (catch shortcut_boolean_1({a,b})),
ok.
shortcut_boolean_1(X) ->
@@ -352,8 +352,8 @@ shortcut_boolean_1(X) ->
%% Test sys_core_fold:letify_guard/3.
letify_guard(Config) when is_list(Config) ->
- ?line {-15,a} = letify_guard(-15, a),
- ?line 5 = letify_guard(2, 3),
+ {-15,a} = letify_guard(-15, a),
+ 5 = letify_guard(2, 3),
ok.
letify_guard(A, B) ->
@@ -369,18 +369,18 @@ letify_guard(A, B) ->
%% instructions in beam_dead and beam_peep.
selectify(Config) when is_list(Config) ->
- ?line integer = sel_different_types({r,42}),
- ?line atom = sel_different_types({r,forty_two}),
- ?line none = sel_different_types({r,18}),
- ?line {'EXIT',_} = (catch sel_different_types([a,b,c])),
-
- ?line integer = sel_same_value({r,42}),
- ?line error = sel_same_value({r,100}),
- ?line error = sel_same_value(a),
-
- ?line integer42 = sel_same_value2(42),
- ?line integer43 = sel_same_value2(43),
- ?line error = sel_same_value2(44),
+ integer = sel_different_types({r,42}),
+ atom = sel_different_types({r,forty_two}),
+ none = sel_different_types({r,18}),
+ {'EXIT',_} = (catch sel_different_types([a,b,c])),
+
+ integer = sel_same_value({r,42}),
+ error = sel_same_value({r,100}),
+ error = sel_same_value(a),
+
+ integer42 = sel_same_value2(42),
+ integer43 = sel_same_value2(43),
+ error = sel_same_value2(44),
ok.
sel_different_types({r,_}=T) when element(2, T) =:= forty_two ->
@@ -449,7 +449,10 @@ do_map_vars_used(X, Y, Map) ->
coverage(Config) when is_list(Config) ->
%% Cover beam_dead.
ok = coverage_1(x, a),
- ok = coverage_1(x, b).
+ ok = coverage_1(x, b),
+
+ %% Cover sys_pre_expand.
+ ok = coverage_3("abc").
coverage_1(B, Tag) ->
case Tag of
@@ -460,4 +463,6 @@ coverage_1(B, Tag) ->
coverage_2(1, a, x) -> ok;
coverage_2(2, b, x) -> ok.
+coverage_3([$a]++[]++"bc") -> ok.
+
id(I) -> I.
diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl
index 8606935504..8a639f741f 100644
--- a/lib/compiler/test/misc_SUITE.erl
+++ b/lib/compiler/test/misc_SUITE.erl
@@ -25,7 +25,7 @@
tobias/1,empty_string/1,md5/1,silly_coverage/1,
confused_literals/1,integer_encoding/1,override_bif/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% For the override_bif testcase.
%% NB, no other testcases in this testsuite can use these without erlang:prefix!
@@ -38,22 +38,25 @@
-compile({no_auto_import,[byte_size/1]}).
-import(erlang,[byte_size/1]).
-
+%% Cover the code for callback handling.
+-callback must_define_this_one() -> 'ok'.
+-callback do_something_strange(atom()) -> 'ok'.
+-optional_callbacks([do_something_strange/1]).
+-optional_callbacks([ignore_me]). %Invalid; ignored.
%% Include an opaque declaration to cover the stripping of
%% opaque types from attributes in v3_kernel.
-opaque misc_SUITE_test_cases() :: [atom()].
init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog = test_server:timetrap(?t:minutes(10)),
- [{watchdog,Dog}|Config].
+ Config.
end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,10}}].
-spec all() -> misc_SUITE_test_cases().
all() ->
@@ -88,32 +91,27 @@ abs(_N) ->
binary_part(_,_,_) ->
dummy_bp.
-% Make sure that auto-imported BIF's are overridden correctly
-
-override_bif(suite) ->
- [];
-override_bif(doc) ->
- ["Test dat local functions and imports override auto-imported BIFs."];
+%% Test that local functions and imports override auto-imported BIFs.
override_bif(Config) when is_list(Config) ->
- ?line dummy_abs = abs(1),
- ?line dummy_bp = binary_part(<<"hello">>,1,1),
- ?line dummy = binary_part(<<"hello">>,{1,1}),
- ?line 1 = erlang:abs(1),
- ?line <<"e">> = erlang:binary_part(<<"hello">>,1,1),
- ?line <<"e">> = erlang:binary_part(<<"hello">>,{1,1}),
+ dummy_abs = abs(1),
+ dummy_bp = binary_part(<<"hello">>,1,1),
+ dummy = binary_part(<<"hello">>,{1,1}),
+ 1 = erlang:abs(1),
+ <<"e">> = erlang:binary_part(<<"hello">>,1,1),
+ <<"e">> = erlang:binary_part(<<"hello">>,{1,1}),
F = fun(X) when byte_size(X) =:= 4 ->
four;
(X) ->
byte_size(X)
end,
- ?line four = F(<<1,2,3,4>>),
- ?line 5 = F(<<1,2,3,4,5>>),
+ four = F(<<1,2,3,4>>),
+ 5 = F(<<1,2,3,4,5>>),
ok.
%% A bug reported by Tobias Lindahl for a development version of R11B.
tobias(Config) when is_list(Config) ->
- ?line 1 = tobias_1([1,2,3]),
+ 1 = tobias_1([1,2,3]),
ok.
tobias_1([H|_T]) ->
@@ -134,7 +132,7 @@ tobias_2(_, _) ->
-record(r, {s = ""}).
empty_string(Config) when is_list(Config) ->
- ?line #r{s="x"} = empty_string_1(#r{}),
+ #r{s="x"} = empty_string_1(#r{}),
ok.
empty_string_1(T) ->
@@ -149,15 +147,15 @@ md5(Config) when is_list(Config) ->
end.
md5() ->
- ?line Dir = filename:dirname(code:which(?MODULE)),
- ?line Beams = filelib:wildcard(filename:join(Dir, "*.beam")),
- ?line io:format("Found ~w beam files", [length(Beams)]),
- ?line lists:foreach(fun md5_1/1, Beams).
+ Dir = filename:dirname(code:which(?MODULE)),
+ Beams = filelib:wildcard(filename:join(Dir, "*.beam")),
+ io:format("Found ~w beam files", [length(Beams)]),
+ lists:foreach(fun md5_1/1, Beams).
md5_1(Beam) ->
- ?line {ok,{Mod,[Vsn]}} = beam_lib:version(Beam),
- ?line {ok,Code} = file:read_file(Beam),
- ?line {Mod,<<Vsn:128>>} = {Mod,code:module_md5(Code)}.
+ {ok,{Mod,[Vsn]}} = beam_lib:version(Beam),
+ {ok,Code} = file:read_file(Beam),
+ {Mod,<<Vsn:128>>} = {Mod,code:module_md5(Code)}.
%% Cover some code that handles internal errors.
@@ -166,9 +164,9 @@ silly_coverage(Config) when is_list(Config) ->
BadCoreErlang = {c_module,[],
name,[],[],
[{{c_var,[],{foo,2}},seriously_bad_body}]},
- ?line expect_error(fun() -> sys_core_fold:module(BadCoreErlang, []) end),
- ?line expect_error(fun() -> sys_core_dsetel:module(BadCoreErlang, []) end),
- ?line expect_error(fun() -> v3_kernel:module(BadCoreErlang, []) end),
+ expect_error(fun() -> sys_core_fold:module(BadCoreErlang, []) end),
+ expect_error(fun() -> sys_core_dsetel:module(BadCoreErlang, []) end),
+ expect_error(fun() -> v3_kernel:module(BadCoreErlang, []) end),
%% v3_life
BadKernel = {k_mdef,[],?MODULE,
@@ -178,11 +176,11 @@ silly_coverage(Config) when is_list(Config) ->
{k,[],[],[]},
f,0,[],
seriously_bad_body}]},
- ?line expect_error(fun() -> v3_life:module(BadKernel, []) end),
+ expect_error(fun() -> v3_life:module(BadKernel, []) end),
%% v3_codegen
CodegenInput = {?MODULE,[{foo,0}],[],[{function,foo,0,[a|b],a,b,[]}]},
- ?line expect_error(fun() -> v3_codegen:module(CodegenInput, []) end),
+ expect_error(fun() -> v3_codegen:module(CodegenInput, []) end),
%% beam_a
BeamAInput = {?MODULE,[{foo,0}],[],
@@ -192,13 +190,25 @@ silly_coverage(Config) when is_list(Config) ->
{label,2}|non_proper_list]}],99},
expect_error(fun() -> beam_a:module(BeamAInput, []) end),
+ %% beam_reorder
+ BlockInput = {?MODULE,[{foo,0}],[],
+ [{function,foo,0,2,
+ [{label,1},
+ {func_info,{atom,?MODULE},{atom,foo},0},
+ {label,2}|non_proper_list]}],99},
+ expect_error(fun() -> beam_reorder:module(BlockInput, []) end),
+
%% beam_block
BlockInput = {?MODULE,[{foo,0}],[],
[{function,foo,0,2,
[{label,1},
{func_info,{atom,?MODULE},{atom,foo},0},
{label,2}|non_proper_list]}],99},
- ?line expect_error(fun() -> beam_block:module(BlockInput, []) end),
+ expect_error(fun() -> beam_block:module(BlockInput, []) end),
+
+ %% beam_bs
+ BsInput = BlockInput,
+ expect_error(fun() -> beam_bs:module(BsInput, []) end),
%% beam_type
TypeInput = {?MODULE,[{foo,0}],[],
@@ -224,7 +234,7 @@ silly_coverage(Config) when is_list(Config) ->
[{label,1},
{func_info,{atom,?MODULE},{atom,foo},0},
{label,2}|non_proper_list]}],99},
- ?line expect_error(fun() -> beam_bool:module(BoolInput, []) end),
+ expect_error(fun() -> beam_bool:module(BoolInput, []) end),
%% beam_dead. This is tricky. Our function must look OK to
%% beam_utils:clean_labels/1, but must crash beam_dead.
@@ -243,7 +253,7 @@ silly_coverage(Config) when is_list(Config) ->
{func_info,{atom,?MODULE},{atom,foo},0},
{label,2},
{jump,{f,42}}]}],99},
- ?line expect_error(fun() -> beam_clean:module(CleanInput, []) end),
+ expect_error(fun() -> beam_clean:module(CleanInput, []) end),
%% beam_peep
PeepInput = {?MODULE,[{foo,0}],[],
@@ -251,7 +261,7 @@ silly_coverage(Config) when is_list(Config) ->
[{label,1},
{func_info,{atom,?MODULE},{atom,foo},0},
{label,2}|non_proper_list]}],99},
- ?line expect_error(fun() -> beam_peep:module(PeepInput, []) end),
+ expect_error(fun() -> beam_peep:module(PeepInput, []) end),
%% beam_bsm. This is tricky. Our function must be sane enough to not crash
%% btb_index/1, but must crash the main optimization pass.
@@ -262,7 +272,7 @@ silly_coverage(Config) when is_list(Config) ->
{label,2},
{test,bs_get_binary2,{f,99},0,[{x,0},{atom,all},1,[]],{x,0}},
{block,[a|b]}]}],0},
- ?line expect_error(fun() -> beam_bsm:module(BsmInput, []) end),
+ expect_error(fun() -> beam_bsm:module(BsmInput, []) end),
%% beam_receive.
ReceiveInput = {?MODULE,[{foo,0}],[],
@@ -272,7 +282,7 @@ silly_coverage(Config) when is_list(Config) ->
{label,2},
{call_ext,0,{extfunc,erlang,make_ref,0}},
{block,[a|b]}]}],0},
- ?line expect_error(fun() -> beam_receive:module(ReceiveInput, []) end),
+ expect_error(fun() -> beam_receive:module(ReceiveInput, []) end),
BeamZInput = {?MODULE,[{foo,0}],[],
[{function,foo,0,2,
@@ -295,27 +305,30 @@ expect_error(Fun) ->
try Fun() of
Any ->
io:format("~p", [Any]),
- ?t:fail(call_was_supposed_to_fail)
+ ct:fail(call_was_supposed_to_fail)
catch
Class:Reason ->
Stk = erlang:get_stacktrace(),
io:format("~p:~p\n~p\n", [Class,Reason,Stk]),
case {Class,Reason} of
{error,undef} ->
- ?t:fail(not_supposed_to_fail_with_undef);
+ ct:fail(not_supposed_to_fail_with_undef);
{_,_} ->
ok
end
end.
confused_literals(Config) when is_list(Config) ->
- ?line {0,infinity} = confused_literals_1(int),
- ?line {0.0,infinity} = confused_literals_1(float),
+ {0,infinity} = confused_literals_1(int),
+ {0.0,infinity} = confused_literals_1(float),
ok.
confused_literals_1(int) -> {0,infinity};
confused_literals_1(float) -> {0.0,infinity}.
+integer_encoding() ->
+ [{timetrap,{minutes,4}}].
+
integer_encoding(Config) when is_list(Config) ->
case ?MODULE of
misc_SUITE -> integer_encoding_1(Config);
@@ -323,22 +336,21 @@ integer_encoding(Config) when is_list(Config) ->
end.
integer_encoding_1(Config) ->
- Dog = test_server:timetrap(?t:minutes(4)),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line SrcFile = filename:join(PrivDir, "misc_SUITE_integer_encoding.erl"),
- ?line DataFile = filename:join(PrivDir, "integer_encoding.data"),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ SrcFile = filename:join(PrivDir, "misc_SUITE_integer_encoding.erl"),
+ DataFile = filename:join(PrivDir, "integer_encoding.data"),
Mod = misc_SUITE_integer_encoding,
%% Create files.
- ?line {ok,Src} = file:open(SrcFile, [write]),
- ?line {ok,Data} = file:open(DataFile, [write]),
+ {ok,Src} = file:open(SrcFile, [write]),
+ {ok,Data} = file:open(DataFile, [write]),
io:format(Src, "-module(~s).\n", [Mod]),
io:put_chars(Src, "-export([t/1]).\n"),
io:put_chars(Src, "t(Last) ->[\n"),
io:put_chars(Data, "[\n"),
- ?line do_integer_encoding(-(id(1) bsl 10000), Src, Data),
- ?line do_integer_encoding(id(1) bsl 10000, Src, Data),
+ do_integer_encoding(-(id(1) bsl 10000), Src, Data),
+ do_integer_encoding(id(1) bsl 10000, Src, Data),
do_integer_encoding(1024, 0, Src, Data),
_ = [begin
B = 1 bsl I,
@@ -350,32 +362,31 @@ integer_encoding_1(Config) ->
do_integer_encoding(B+1, Src, Data)
end || I <- lists:seq(1, 128)],
io:put_chars(Src, "Last].\n\n"),
- ?line ok = file:close(Src),
+ ok = file:close(Src),
io:put_chars(Data, "0].\n\n"),
- ?line ok = file:close(Data),
+ ok = file:close(Data),
%% Compile and load Erlang module.
- ?line SrcRoot = filename:rootname(SrcFile),
- ?line {ok,Mod,Binary} = compile:file(SrcRoot, [binary,report]),
- ?line {module,Mod} = code:load_binary(Mod, SrcRoot, Binary),
+ SrcRoot = filename:rootname(SrcFile),
+ {ok,Mod,Binary} = compile:file(SrcRoot, [binary,report]),
+ {module,Mod} = code:load_binary(Mod, SrcRoot, Binary),
%% Compare lists.
- ?line List = Mod:t(0),
- ?line {ok,[List]} = file:consult(DataFile),
+ List = Mod:t(0),
+ {ok,[List]} = file:consult(DataFile),
OneBsl10000 = id(1) bsl 10000,
- ?line [-(1 bsl 10000),OneBsl10000|_] = List,
+ [-(1 bsl 10000),OneBsl10000|_] = List,
%% Cleanup.
- ?line file:delete(SrcFile),
- ?line file:delete(DataFile),
- ?t:timetrap_cancel(Dog),
+ file:delete(SrcFile),
+ file:delete(DataFile),
ok.
do_integer_encoding(0, _, _, _) -> ok;
do_integer_encoding(N, I0, Src, Data) ->
- I1 = (I0 bsl 5) bor (random:uniform(32) - 1),
+ I1 = (I0 bsl 5) bor (rand:uniform(32) - 1),
do_integer_encoding(I1, Src, Data),
- I2 = -(I1 bxor (random:uniform(32) - 1)),
+ I2 = -(I1 bxor (rand:uniform(32) - 1)),
do_integer_encoding(I2, Src, Data),
do_integer_encoding(N-1, I1, Src, Data).
diff --git a/lib/compiler/test/num_bif_SUITE.erl b/lib/compiler/test/num_bif_SUITE.erl
index d54fa203f0..78f6fdc3c7 100644
--- a/lib/compiler/test/num_bif_SUITE.erl
+++ b/lib/compiler/test/num_bif_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(num_bif_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Tests optimization of the BIFs:
%% abs/1
@@ -65,68 +65,68 @@ end_per_group(_GroupName, Config) ->
t_abs(Config) when is_list(Config) ->
%% Floats.
- ?line 5.5 = abs(5.5),
- ?line 0.0 = abs(0.0),
- ?line 100.0 = abs(-100.0),
+ 5.5 = abs(5.5),
+ 0.0 = abs(0.0),
+ 100.0 = abs(-100.0),
%% Integers.
- ?line 5 = abs(5),
- ?line 0 = abs(0),
- ?line 100 = abs(-100),
+ 5 = abs(5),
+ 0 = abs(0),
+ 100 = abs(-100),
%% The largest smallnum. OTP-3190.
- ?line X = (1 bsl 27) - 1,
- ?line X = abs(X),
- ?line X = abs(X-1)+1,
- ?line X = abs(X+1)-1,
- ?line X = abs(-X),
- ?line X = abs(-X-1)-1,
- ?line X = abs(-X+1)+1,
+ X = (1 bsl 27) - 1,
+ X = abs(X),
+ X = abs(X-1)+1,
+ X = abs(X+1)-1,
+ X = abs(-X),
+ X = abs(-X-1)-1,
+ X = abs(-X+1)+1,
%% Bignums.
BigNum = 13984792374983749,
- ?line BigNum = abs(BigNum),
- ?line BigNum = abs(-BigNum),
+ BigNum = abs(BigNum),
+ BigNum = abs(-BigNum),
ok.
t_float(Config) when is_list(Config) ->
- ?line 0.0 = float(0),
- ?line 2.5 = float(2.5),
- ?line 0.0 = float(0.0),
- ?line -100.55 = float(-100.55),
- ?line 42.0 = float(42),
- ?line -100.0 = float(-100),
+ 0.0 = float(0),
+ 2.5 = float(2.5),
+ 0.0 = float(0.0),
+ -100.55 = float(-100.55),
+ 42.0 = float(42),
+ -100.0 = float(-100),
%% Bignums.
- ?line 4294967305.0 = float(4294967305),
- ?line -4294967305.0 = float(-4294967305),
+ 4294967305.0 = float(4294967305),
+ -4294967305.0 = float(-4294967305),
%% Extremly big bignums.
- ?line Big = list_to_integer(lists:duplicate(2000, $1)),
- ?line {'EXIT', {badarg, _}} = (catch float(Big)),
+ Big = list_to_integer(lists:duplicate(2000, $1)),
+ {'EXIT', {badarg, _}} = (catch float(Big)),
%% Invalid types and lists.
- ?line {'EXIT', {badarg, _}} = (catch list_to_integer(atom)),
- ?line {'EXIT', {badarg, _}} = (catch list_to_integer(123)),
- ?line {'EXIT', {badarg, _}} = (catch list_to_integer([$1, [$2]])),
- ?line {'EXIT', {badarg, _}} = (catch list_to_integer("1.2")),
- ?line {'EXIT', {badarg, _}} = (catch list_to_integer("a")),
- ?line {'EXIT', {badarg, _}} = (catch list_to_integer("")),
+ {'EXIT', {badarg, _}} = (catch list_to_integer(atom)),
+ {'EXIT', {badarg, _}} = (catch list_to_integer(123)),
+ {'EXIT', {badarg, _}} = (catch list_to_integer([$1, [$2]])),
+ {'EXIT', {badarg, _}} = (catch list_to_integer("1.2")),
+ {'EXIT', {badarg, _}} = (catch list_to_integer("a")),
+ {'EXIT', {badarg, _}} = (catch list_to_integer("")),
ok.
%% Tests float_to_list/1.
t_float_to_list(Config) when is_list(Config) ->
- ?line test_ftl("0.0e+0", 0.0),
- ?line test_ftl("2.5e+1", 25.0),
- ?line test_ftl("2.5e+0", 2.5),
- ?line test_ftl("2.5e-1", 0.25),
- ?line test_ftl("-3.5e+17", -350.0e15),
+ test_ftl("0.0e+0", 0.0),
+ test_ftl("2.5e+1", 25.0),
+ test_ftl("2.5e+0", 2.5),
+ test_ftl("2.5e-1", 0.25),
+ test_ftl("-3.5e+17", -350.0e15),
ok.
test_ftl(Expect, Float) ->
- %% No ?line on the next line -- we want the line number from t_float_to_list.
+ %% No on the next line -- we want the line number from t_float_to_list.
Expect = remove_zeros(lists:reverse(float_to_list(Float)), []).
%% Removes any non-significant zeros in a floating point number.
@@ -148,36 +148,36 @@ remove_zeros([], Result) ->
%% Tests integer_to_list/1.
t_integer_to_list(Config) when is_list(Config) ->
- ?line "0" = integer_to_list(0),
- ?line "42" = integer_to_list(42),
- ?line "-42" = integer_to_list(-42),
- ?line "-42" = integer_to_list(-42),
- ?line "32768" = integer_to_list(32768),
- ?line "268435455" = integer_to_list(268435455),
- ?line "-268435455" = integer_to_list(-268435455),
- ?line "123456932798748738738" = integer_to_list(123456932798748738738),
- ?line Big_List = lists:duplicate(2000, $1),
- ?line Big = list_to_integer(Big_List),
- ?line Big_List = integer_to_list(Big),
+ "0" = integer_to_list(0),
+ "42" = integer_to_list(42),
+ "-42" = integer_to_list(-42),
+ "-42" = integer_to_list(-42),
+ "32768" = integer_to_list(32768),
+ "268435455" = integer_to_list(268435455),
+ "-268435455" = integer_to_list(-268435455),
+ "123456932798748738738" = integer_to_list(123456932798748738738),
+ Big_List = lists:duplicate(2000, $1),
+ Big = list_to_integer(Big_List),
+ Big_List = integer_to_list(Big),
ok.
%% Tests list_to_float/1.
t_list_to_float_safe(Config) when is_list(Config) ->
- ?line 0.0 = list_to_float("0.0"),
- ?line 0.0 = list_to_float("-0.0"),
- ?line 0.5 = list_to_float("0.5"),
- ?line -0.5 = list_to_float("-0.5"),
- ?line 100.0 = list_to_float("1.0e2"),
- ?line 127.5 = list_to_float("127.5"),
- ?line -199.5 = list_to_float("-199.5"),
-
- ?line {'EXIT', {badarg, _}} = (catch list_to_float("0")),
- ?line {'EXIT', {badarg, _}} = (catch list_to_float("0..0")),
- ?line {'EXIT', {badarg, _}} = (catch list_to_float("0e12")),
- ?line {'EXIT', {badarg, _}} = (catch list_to_float("--0.0")),
-%% ?line {'EXIT', {badarg, _}} = (catch list_to_float("0.0e+99999999")),
+ 0.0 = list_to_float("0.0"),
+ 0.0 = list_to_float("-0.0"),
+ 0.5 = list_to_float("0.5"),
+ -0.5 = list_to_float("-0.5"),
+ 100.0 = list_to_float("1.0e2"),
+ 127.5 = list_to_float("127.5"),
+ -199.5 = list_to_float("-199.5"),
+
+ {'EXIT', {badarg, _}} = (catch list_to_float("0")),
+ {'EXIT', {badarg, _}} = (catch list_to_float("0..0")),
+ {'EXIT', {badarg, _}} = (catch list_to_float("0e12")),
+ {'EXIT', {badarg, _}} = (catch list_to_float("--0.0")),
+%% {'EXIT', {badarg, _}} = (catch list_to_float("0.0e+99999999")),
ok.
@@ -185,101 +185,101 @@ t_list_to_float_safe(Config) when is_list(Config) ->
%% (Known to crash the Unix version of Erlang 4.4.1)
t_list_to_float_risky(Config) when is_list(Config) ->
- ?line Many_Ones = lists:duplicate(25000, $1),
- ?line _ = list_to_float("2."++Many_Ones),
- ?line {'EXIT', {badarg, _}} = (catch list_to_float("2"++Many_Ones)),
+ Many_Ones = lists:duplicate(25000, $1),
+ _ = list_to_float("2."++Many_Ones),
+ {'EXIT', {badarg, _}} = (catch list_to_float("2"++Many_Ones)),
ok.
%% Tests list_to_integer/1.
t_list_to_integer(Config) when is_list(Config) ->
- ?line 0 = list_to_integer("0"),
- ?line 0 = list_to_integer("00"),
- ?line 0 = list_to_integer("-0"),
- ?line 1 = list_to_integer("1"),
- ?line -1 = list_to_integer("-1"),
- ?line 42 = list_to_integer("42"),
- ?line -12 = list_to_integer("-12"),
- ?line 32768 = list_to_integer("32768"),
- ?line 268435455 = list_to_integer("268435455"),
- ?line -268435455 = list_to_integer("-268435455"),
+ 0 = list_to_integer("0"),
+ 0 = list_to_integer("00"),
+ 0 = list_to_integer("-0"),
+ 1 = list_to_integer("1"),
+ -1 = list_to_integer("-1"),
+ 42 = list_to_integer("42"),
+ -12 = list_to_integer("-12"),
+ 32768 = list_to_integer("32768"),
+ 268435455 = list_to_integer("268435455"),
+ -268435455 = list_to_integer("-268435455"),
%% Bignums.
- ?line 123456932798748738738 = list_to_integer("123456932798748738738"),
- ?line _ = list_to_integer(lists:duplicate(2000, $1)),
+ 123456932798748738738 = list_to_integer("123456932798748738738"),
+ _ = list_to_integer(lists:duplicate(2000, $1)),
ok.
%% Tests round/1.
t_round(Config) when is_list(Config) ->
- ?line 0 = round(0.0),
- ?line 0 = round(0.4),
- ?line 1 = round(0.5),
- ?line 0 = round(-0.4),
- ?line -1 = round(-0.5),
- ?line 255 = round(255.3),
- ?line 256 = round(255.6),
- ?line -1033 = round(-1033.3),
- ?line -1034 = round(-1033.6),
+ 0 = round(0.0),
+ 0 = round(0.4),
+ 1 = round(0.5),
+ 0 = round(-0.4),
+ -1 = round(-0.5),
+ 255 = round(255.3),
+ 256 = round(255.6),
+ -1033 = round(-1033.3),
+ -1034 = round(-1033.6),
% OTP-3722:
- ?line X = (1 bsl 27) - 1,
- ?line MX = -X,
- ?line MXm1 = -X-1,
- ?line MXp1 = -X+1,
- ?line F = X + 0.0,
- ?line X = round(F),
- ?line X = round(F+1)-1,
- ?line X = round(F-1)+1,
- ?line MX = round(-F),
- ?line MXm1 = round(-F-1),
- ?line MXp1 = round(-F+1),
-
- ?line X = round(F+0.1),
- ?line X = round(F+1+0.1)-1,
- ?line X = round(F-1+0.1)+1,
- ?line MX = round(-F+0.1),
- ?line MXm1 = round(-F-1+0.1),
- ?line MXp1 = round(-F+1+0.1),
-
- ?line X = round(F-0.1),
- ?line X = round(F+1-0.1)-1,
- ?line X = round(F-1-0.1)+1,
- ?line MX = round(-F-0.1),
- ?line MXm1 = round(-F-1-0.1),
- ?line MXp1 = round(-F+1-0.1),
-
- ?line 0.5 = abs(round(F+0.5)-(F+0.5)),
- ?line 0.5 = abs(round(F-0.5)-(F-0.5)),
- ?line 0.5 = abs(round(-F-0.5)-(-F-0.5)),
- ?line 0.5 = abs(round(-F+0.5)-(-F+0.5)),
+ X = (1 bsl 27) - 1,
+ MX = -X,
+ MXm1 = -X-1,
+ MXp1 = -X+1,
+ F = X + 0.0,
+ X = round(F),
+ X = round(F+1)-1,
+ X = round(F-1)+1,
+ MX = round(-F),
+ MXm1 = round(-F-1),
+ MXp1 = round(-F+1),
+
+ X = round(F+0.1),
+ X = round(F+1+0.1)-1,
+ X = round(F-1+0.1)+1,
+ MX = round(-F+0.1),
+ MXm1 = round(-F-1+0.1),
+ MXp1 = round(-F+1+0.1),
+
+ X = round(F-0.1),
+ X = round(F+1-0.1)-1,
+ X = round(F-1-0.1)+1,
+ MX = round(-F-0.1),
+ MXm1 = round(-F-1-0.1),
+ MXp1 = round(-F+1-0.1),
+
+ 0.5 = abs(round(F+0.5)-(F+0.5)),
+ 0.5 = abs(round(F-0.5)-(F-0.5)),
+ 0.5 = abs(round(-F-0.5)-(-F-0.5)),
+ 0.5 = abs(round(-F+0.5)-(-F+0.5)),
%% Bignums.
- ?line 4294967296 = round(4294967296.1),
- ?line 4294967297 = round(4294967296.9),
- ?line -4294967296 = -round(4294967296.1),
- ?line -4294967297 = -round(4294967296.9),
+ 4294967296 = round(4294967296.1),
+ 4294967297 = round(4294967296.9),
+ -4294967296 = -round(4294967296.1),
+ -4294967297 = -round(4294967296.9),
ok.
t_trunc(Config) when is_list(Config) ->
- ?line 0 = trunc(0.0),
- ?line 5 = trunc(5.3333),
- ?line -10 = trunc(-10.978987),
+ 0 = trunc(0.0),
+ 5 = trunc(5.3333),
+ -10 = trunc(-10.978987),
% The largest smallnum, converted to float (OTP-3722):
- ?line X = (1 bsl 27) - 1,
- ?line F = X + 0.0,
+ X = (1 bsl 27) - 1,
+ F = X + 0.0,
io:format("X = ~p/~w/~w, F = ~p/~w/~w, trunc(F) = ~p/~w/~w~n",
[X, X, binary_to_list(term_to_binary(X)),
F, F, binary_to_list(term_to_binary(F)),
trunc(F), trunc(F), binary_to_list(term_to_binary(trunc(F)))]),
- ?line X = trunc(F),
- ?line X = trunc(F+1)-1,
- ?line X = trunc(F-1)+1,
- ?line X = -trunc(-F),
- ?line X = -trunc(-F-1)-1,
- ?line X = -trunc(-F+1)+1,
+ X = trunc(F),
+ X = trunc(F+1)-1,
+ X = trunc(F-1)+1,
+ X = -trunc(-F),
+ X = -trunc(-F-1)-1,
+ X = -trunc(-F+1)+1,
%% Bignums.
- ?line 4294967305 = trunc(4294967305.7),
- ?line -4294967305 = trunc(-4294967305.7),
+ 4294967305 = trunc(4294967305.7),
+ -4294967305 = trunc(-4294967305.7),
ok.
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl
index 4016fac0b5..8d2c78aae2 100644
--- a/lib/compiler/test/receive_SUITE.erl
+++ b/lib/compiler/test/receive_SUITE.erl
@@ -27,18 +27,17 @@
export/1,recv/1,coverage/1,otp_7980/1,ref_opt/1,
wait/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
init_per_testcase(_Case, Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(2)),
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,2}}].
all() ->
test_lib:recompile(?MODULE),
@@ -64,21 +63,21 @@ end_per_group(_GroupName, Config) ->
-record(state, {ena = true}).
recv(Config) when is_list(Config) ->
- ?line Pid = spawn_link(fun() -> loop(#state{}) end),
+ Pid = spawn_link(fun() -> loop(#state{}) end),
Self = self(),
- ?line Pid ! {Self,test},
+ Pid ! {Self,test},
receive
{ok,test} -> ok;
{error,Other} ->
io:format("Got unpexected ~p", [Other]),
- ?line ?t:fail()
+ ct:fail(unexpected)
after 10000 ->
- ?line ?t:fail(no_answer)
+ ct:fail(no_answer)
end,
receive
X ->
io:format("Unexpected extra message: ~p", [X]),
- ?line ?t:fail()
+ ct:fail(unexpected)
after 10 ->
ok
end,
@@ -116,9 +115,9 @@ coverage(Config) when is_list(Config) ->
self() ! 17,
self() ! 19,
- ?line 59 = tuple_to_values(infinity, x),
- ?line 61 = tuple_to_values(999999, x),
- ?line 0 = tuple_to_values(1, x),
+ 59 = tuple_to_values(infinity, x),
+ 61 = tuple_to_values(999999, x),
+ 0 = tuple_to_values(1, x),
ok.
receive_all() ->
@@ -188,8 +187,8 @@ ref_opt(Config) when is_list(Config) ->
end.
ref_opt_1(Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Sources = filelib:wildcard(filename:join([DataDir,"ref_opt","*.{erl,S}"])),
test_lib:p_run(fun(Src) ->
do_ref_opt(Src, PrivDir)
@@ -257,9 +256,9 @@ cover_recv_instructions() ->
export(Config) when is_list(Config) ->
Ref = make_ref(),
- ?line self() ! {result,Ref,42},
- ?line 42 = export_1(Ref),
- ?line {error,timeout} = export_1(Ref),
+ self() ! {result,Ref,42},
+ 42 = export_1(Ref),
+ {error,timeout} = export_1(Ref),
ok.
export_1(Reference) ->
diff --git a/lib/compiler/test/record_SUITE.erl b/lib/compiler/test/record_SUITE.erl
index 2ef379e43f..680bd38317 100644
--- a/lib/compiler/test/record_SUITE.erl
+++ b/lib/compiler/test/record_SUITE.erl
@@ -21,7 +21,7 @@
-module(record_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
@@ -31,15 +31,14 @@
nested_access/1,coverage/1]).
init_per_testcase(_Case, Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(2)),
- [{watchdog,Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,2}}].
all() ->
test_lib:recompile(?MODULE),
@@ -71,18 +70,18 @@ end_per_group(_GroupName, Config) ->
errors(Config) when is_list(Config) ->
Foo = #foo{a=1,b=2,c=3,d=4},
- ?line #foo{a=19,b=42,c=3,d=4} = update_foo(Foo, 19, 42),
-
- ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19)),
- ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35)),
- ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17)),
- ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17, 42)),
-
- ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19)),
- ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35)),
- ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17)),
- ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17, 42)),
- ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19,
+ #foo{a=19,b=42,c=3,d=4} = update_foo(Foo, 19, 42),
+
+ {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19)),
+ {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35)),
+ {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17)),
+ {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17, 42)),
+
+ {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19)),
+ {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35)),
+ {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17)),
+ {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17, 42)),
+ {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19,
35, 17, 42, -2)),
ok.
@@ -118,72 +117,72 @@ update_foo_barf(#foo{}=R, A, _B, C, D, E) ->
R#barf{a=A,b=A,c=C,d=D,e=E}.
--define(TrueGuard(Expr), if Expr -> ok; true -> ?t:fail() end).
--define(FalseGuard(Expr), if Expr -> ?t:fail(); true -> ok end).
+-define(TrueGuard(Expr), if Expr -> ok; true -> ct:fail(failed) end).
+-define(FalseGuard(Expr), if Expr -> ct:fail(failed); true -> ok end).
record_test_2(Config) when is_list(Config) ->
- ?line true = is_record(#foo{}, foo),
- ?line false = is_record(#foo{}, barf),
- ?line false = is_record({foo}, foo),
+ true = is_record(#foo{}, foo),
+ false = is_record(#foo{}, barf),
+ false = is_record({foo}, foo),
- ?line true = erlang:is_record(#foo{}, foo),
- ?line false = erlang:is_record(#foo{}, barf),
- ?line false = erlang:is_record({foo}, foo),
+ true = erlang:is_record(#foo{}, foo),
+ false = erlang:is_record(#foo{}, barf),
+ false = erlang:is_record({foo}, foo),
- ?line false = is_record([], foo),
- ?line false = is_record(Config, foo),
+ false = is_record([], foo),
+ false = is_record(Config, foo),
- ?line ?TrueGuard(is_record(#foo{}, foo)),
- ?line ?FalseGuard(is_record(#foo{}, barf)),
- ?line ?FalseGuard(is_record({foo}, foo)),
+ ?TrueGuard(is_record(#foo{}, foo)),
+ ?FalseGuard(is_record(#foo{}, barf)),
+ ?FalseGuard(is_record({foo}, foo)),
- ?line ?TrueGuard(erlang:is_record(#foo{}, foo)),
- ?line ?FalseGuard(erlang:is_record(#foo{}, barf)),
- ?line ?FalseGuard(erlang:is_record({foo}, foo)),
+ ?TrueGuard(erlang:is_record(#foo{}, foo)),
+ ?FalseGuard(erlang:is_record(#foo{}, barf)),
+ ?FalseGuard(erlang:is_record({foo}, foo)),
- ?line ?FalseGuard(is_record([], foo)),
- ?line ?FalseGuard(is_record(Config, foo)),
+ ?FalseGuard(is_record([], foo)),
+ ?FalseGuard(is_record(Config, foo)),
%% 'not is_record/2' to test guard optimization.
- ?line ?FalseGuard(not is_record(#foo{}, foo)),
- ?line ?TrueGuard(not is_record(#foo{}, barf)),
- ?line ?TrueGuard(not is_record({foo}, foo)),
+ ?FalseGuard(not is_record(#foo{}, foo)),
+ ?TrueGuard(not is_record(#foo{}, barf)),
+ ?TrueGuard(not is_record({foo}, foo)),
- ?line ?FalseGuard(not erlang:is_record(#foo{}, foo)),
- ?line ?TrueGuard(not erlang:is_record(#foo{}, barf)),
- ?line ?TrueGuard(not erlang:is_record({foo}, foo)),
+ ?FalseGuard(not erlang:is_record(#foo{}, foo)),
+ ?TrueGuard(not erlang:is_record(#foo{}, barf)),
+ ?TrueGuard(not erlang:is_record({foo}, foo)),
Foo = id(#foo{}),
- ?line ?FalseGuard(not erlang:is_record(Foo, foo)),
- ?line ?TrueGuard(not erlang:is_record(Foo, barf)),
+ ?FalseGuard(not erlang:is_record(Foo, foo)),
+ ?TrueGuard(not erlang:is_record(Foo, barf)),
- ?line ?TrueGuard(not is_record(Config, foo)),
+ ?TrueGuard(not is_record(Config, foo)),
- ?line ?TrueGuard(not is_record(a, foo)),
- ?line ?TrueGuard(not is_record([], foo)),
+ ?TrueGuard(not is_record(a, foo)),
+ ?TrueGuard(not is_record([], foo)),
%% Pass non-literal first argument.
- ?line true = is_record(id(#foo{}), foo),
- ?line false = is_record(id(#foo{}), barf),
- ?line false = is_record(id({foo}), foo),
+ true = is_record(id(#foo{}), foo),
+ false = is_record(id(#foo{}), barf),
+ false = is_record(id({foo}), foo),
- ?line true = erlang:is_record(id(#foo{}), foo),
- ?line false = erlang:is_record(id(#foo{}), barf),
- ?line false = erlang:is_record(id({foo}), foo),
+ true = erlang:is_record(id(#foo{}), foo),
+ false = erlang:is_record(id(#foo{}), barf),
+ false = erlang:is_record(id({foo}), foo),
NoRec1 = id(blurf),
NoRec2 = id([]),
- ?line ?TrueGuard(not is_record(NoRec1, foo)),
- ?line ?TrueGuard(not is_record(NoRec2, foo)),
+ ?TrueGuard(not is_record(NoRec1, foo)),
+ ?TrueGuard(not is_record(NoRec2, foo)),
%% The optimizer attempts to move expressions to guards,
%% but it must not move an is_record/2 call that is not
%% allowed in a guard in the first place.
- ?line ok = case is_record(id({a}), id(a)) of
+ ok = case is_record(id({a}), id(a)) of
true -> ok;
false -> error
end,
@@ -191,61 +190,61 @@ record_test_2(Config) when is_list(Config) ->
%% Force the use of guard bifs by using the 'xor' operation.
False = id(false),
- ?line ?TrueGuard(is_record(#foo{}, foo) xor False),
- ?line ?FalseGuard(is_record(#foo{}, barf) xor False),
- ?line ?FalseGuard(is_record({foo}, foo) xor False ),
+ ?TrueGuard(is_record(#foo{}, foo) xor False),
+ ?FalseGuard(is_record(#foo{}, barf) xor False),
+ ?FalseGuard(is_record({foo}, foo) xor False ),
- ?line ?TrueGuard(is_record(Foo, foo) xor False),
- ?line ?FalseGuard(is_record(Foo, barf) xor False),
+ ?TrueGuard(is_record(Foo, foo) xor False),
+ ?FalseGuard(is_record(Foo, barf) xor False),
%% Implicit guards by using a list comprehension.
List = id([1,#foo{a=2},3,#bar{d=4},5,#foo{a=6},7]),
- ?line [#foo{a=2},#foo{a=6}] = [X || X <- List, is_record(X, foo)],
- ?line [#bar{d=4}] = [X || X <- List, is_record(X, bar)],
- ?line [1,#foo{a=2},3,5,#foo{a=6},7] =
+ [#foo{a=2},#foo{a=6}] = [X || X <- List, is_record(X, foo)],
+ [#bar{d=4}] = [X || X <- List, is_record(X, bar)],
+ [1,#foo{a=2},3,5,#foo{a=6},7] =
[X || X <- List, not is_record(X, bar)],
- ?line [1,3,5,7] =
+ [1,3,5,7] =
[X || X <- List, ((not is_record(X, bar)) and (not is_record(X, foo)))],
- ?line [#foo{a=2},#bar{d=4},#foo{a=6}] =
+ [#foo{a=2},#bar{d=4},#foo{a=6}] =
[X || X <- List, ((is_record(X, bar)) or (is_record(X, foo)))],
- ?line [1,3,#bar{d=4}] =
+ [1,3,#bar{d=4}] =
[X || X <- List, ((is_record(X, bar)) or (X < 5))],
- ?line MyList = [#foo{a=3},x,[],{a,b}],
- ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo)],
- ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo)],
- ?line [#foo{a=3}] = [X || X <- MyList, begin is_record(X, foo) end],
- ?line [x,[],{a,b}] = [X || X <- MyList, begin not is_record(X, foo) end],
- ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, is_record(X, foo) or
- not is_binary(X)],
- ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or
- not is_binary(X)],
- ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo) or is_reference(X)],
- ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or
- is_reference(X)],
- ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList,
- begin is_record(X, foo) or
- not is_binary(X) end],
- ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList,
- begin not is_record(X, foo) or
- not is_binary(X) end],
- ?line [#foo{a=3}] = [X || X <- MyList,
- begin is_record(X, foo) or is_reference(X) end],
- ?line [x,[],{a,b}] = [X || X <- MyList,
- begin not is_record(X, foo) or
- is_reference(X) end],
+ MyList = [#foo{a=3},x,[],{a,b}],
+ [#foo{a=3}] = [X || X <- MyList, is_record(X, foo)],
+ [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo)],
+ [#foo{a=3}] = [X || X <- MyList, begin is_record(X, foo) end],
+ [x,[],{a,b}] = [X || X <- MyList, begin not is_record(X, foo) end],
+ [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, is_record(X, foo) or
+ not is_binary(X)],
+ [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or
+ not is_binary(X)],
+ [#foo{a=3}] = [X || X <- MyList, is_record(X, foo) or is_reference(X)],
+ [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or
+ is_reference(X)],
+ [#foo{a=3},x,[],{a,b}] = [X || X <- MyList,
+ begin is_record(X, foo) or
+ not is_binary(X) end],
+ [#foo{a=3},x,[],{a,b}] = [X || X <- MyList,
+ begin not is_record(X, foo) or
+ not is_binary(X) end],
+ [#foo{a=3}] = [X || X <- MyList,
+ begin is_record(X, foo) or is_reference(X) end],
+ [x,[],{a,b}] = [X || X <- MyList,
+ begin not is_record(X, foo) or
+ is_reference(X) end],
%% Call is_record/2 with illegal arguments.
- ?line [] = [X || X <- [], is_record(t, id(X))],
- ?line {'EXIT',{badarg,_}} = (catch [X || X <- [1], is_record(t, id(X))]),
+ [] = [X || X <- [], is_record(t, id(X))],
+ {'EXIT',{badarg,_}} = (catch [X || X <- [1], is_record(t, id(X))]),
%% Update several fields with a string literal.
- ?line #barf{} = Barf0 = id(#barf{}),
- ?line Barf = update_barf(Barf0),
- ?line #barf{a="abc",b=1} = id(Barf),
+ #barf{} = Barf0 = id(#barf{}),
+ Barf = update_barf(Barf0),
+ #barf{a="abc",b=1} = id(Barf),
%% Test optimization of is_record/3.
false = case id({a,b}) of
@@ -258,125 +257,125 @@ record_test_2(Config) when is_list(Config) ->
ok.
record_test_3(Config) when is_list(Config) ->
- ?line true = is_record(#foo{}, foo, 5),
- ?line false = is_record(#foo{}, barf, 5),
- ?line false = is_record(#foo{}, barf, 6),
- ?line false = is_record({foo}, foo, 5),
+ true = is_record(#foo{}, foo, 5),
+ false = is_record(#foo{}, barf, 5),
+ false = is_record(#foo{}, barf, 6),
+ false = is_record({foo}, foo, 5),
- ?line true = erlang:is_record(#foo{}, foo, 5),
- ?line false = erlang:is_record(#foo{}, barf, 5),
- ?line false = erlang:is_record({foo}, foo, 5),
+ true = erlang:is_record(#foo{}, foo, 5),
+ false = erlang:is_record(#foo{}, barf, 5),
+ false = erlang:is_record({foo}, foo, 5),
- ?line false = is_record([], foo),
- ?line false = is_record(Config, foo),
+ false = is_record([], foo),
+ false = is_record(Config, foo),
- ?line ?TrueGuard(is_record(#foo{}, foo, 5)),
- ?line ?FalseGuard(is_record(#foo{}, barf, 5)),
- ?line ?FalseGuard(is_record(#foo{}, barf, 6)),
- ?line ?FalseGuard(is_record({foo}, foo, 5)),
+ ?TrueGuard(is_record(#foo{}, foo, 5)),
+ ?FalseGuard(is_record(#foo{}, barf, 5)),
+ ?FalseGuard(is_record(#foo{}, barf, 6)),
+ ?FalseGuard(is_record({foo}, foo, 5)),
- ?line ?TrueGuard(erlang:is_record(#foo{}, foo, 5)),
- ?line ?FalseGuard(erlang:is_record(#foo{}, barf, 5)),
- ?line ?FalseGuard(erlang:is_record(#foo{}, barf, 6)),
- ?line ?FalseGuard(erlang:is_record({foo}, foo, 5)),
+ ?TrueGuard(erlang:is_record(#foo{}, foo, 5)),
+ ?FalseGuard(erlang:is_record(#foo{}, barf, 5)),
+ ?FalseGuard(erlang:is_record(#foo{}, barf, 6)),
+ ?FalseGuard(erlang:is_record({foo}, foo, 5)),
- ?line ?FalseGuard(is_record([], foo, 5)),
- ?line ?FalseGuard(is_record(Config, foo, 5)),
+ ?FalseGuard(is_record([], foo, 5)),
+ ?FalseGuard(is_record(Config, foo, 5)),
%% 'not is_record/2' to test guard optimization.
- ?line ?FalseGuard(not is_record(#foo{}, foo, 5)),
- ?line ?TrueGuard(not is_record(#foo{}, barf, 6)),
- ?line ?TrueGuard(not is_record({foo}, foo, 5)),
+ ?FalseGuard(not is_record(#foo{}, foo, 5)),
+ ?TrueGuard(not is_record(#foo{}, barf, 6)),
+ ?TrueGuard(not is_record({foo}, foo, 5)),
- ?line ?FalseGuard(not erlang:is_record(#foo{}, foo, 5)),
- ?line ?TrueGuard(not erlang:is_record(#foo{}, barf, 5)),
- ?line ?TrueGuard(not erlang:is_record({foo}, foo, 5)),
+ ?FalseGuard(not erlang:is_record(#foo{}, foo, 5)),
+ ?TrueGuard(not erlang:is_record(#foo{}, barf, 5)),
+ ?TrueGuard(not erlang:is_record({foo}, foo, 5)),
Foo = id(#foo{}),
- ?line ?FalseGuard(not erlang:is_record(Foo, foo, 5)),
- ?line ?TrueGuard(not erlang:is_record(Foo, barf, 6)),
+ ?FalseGuard(not erlang:is_record(Foo, foo, 5)),
+ ?TrueGuard(not erlang:is_record(Foo, barf, 6)),
- ?line ?TrueGuard(not is_record(Config, foo, 5)),
+ ?TrueGuard(not is_record(Config, foo, 5)),
- ?line ?TrueGuard(not is_record(a, foo, 5)),
- ?line ?TrueGuard(not is_record([], foo, 5)),
+ ?TrueGuard(not is_record(a, foo, 5)),
+ ?TrueGuard(not is_record([], foo, 5)),
%% Pass non-literal first argument.
- ?line true = is_record(id(#foo{}), foo, 5),
- ?line false = is_record(id(#foo{}), barf, 6),
- ?line false = is_record(id({foo}), foo, 5),
+ true = is_record(id(#foo{}), foo, 5),
+ false = is_record(id(#foo{}), barf, 6),
+ false = is_record(id({foo}), foo, 5),
- ?line true = erlang:is_record(id(#foo{}), foo, 5),
- ?line false = erlang:is_record(id(#foo{}), barf, 6),
- ?line false = erlang:is_record(id({foo}), foo, 5),
+ true = erlang:is_record(id(#foo{}), foo, 5),
+ false = erlang:is_record(id(#foo{}), barf, 6),
+ false = erlang:is_record(id({foo}), foo, 5),
NoRec1 = id(blurf),
NoRec2 = id([]),
- ?line ?TrueGuard(not is_record(NoRec1, foo, 5)),
- ?line ?TrueGuard(not is_record(NoRec2, foo, 5)),
+ ?TrueGuard(not is_record(NoRec1, foo, 5)),
+ ?TrueGuard(not is_record(NoRec2, foo, 5)),
%% Force the use of guard bifs by using the 'xor' operation.
False = id(false),
- ?line ?TrueGuard(is_record(#foo{}, foo, 5) xor False),
- ?line ?FalseGuard(is_record(#foo{}, barf, 6) xor False),
- ?line ?FalseGuard(is_record({foo}, foo, 5) xor False ),
+ ?TrueGuard(is_record(#foo{}, foo, 5) xor False),
+ ?FalseGuard(is_record(#foo{}, barf, 6) xor False),
+ ?FalseGuard(is_record({foo}, foo, 5) xor False ),
- ?line ?TrueGuard(is_record(Foo, foo, 5) xor False),
- ?line ?FalseGuard(is_record(Foo, barf, 6) xor False),
+ ?TrueGuard(is_record(Foo, foo, 5) xor False),
+ ?FalseGuard(is_record(Foo, barf, 6) xor False),
%% Implicit guards by using a list comprehension.
List = id([1,#foo{a=2},3,#bar{d=4},5,#foo{a=6},7]),
- ?line [#foo{a=2},#foo{a=6}] = [X || X <- List, is_record(X, foo, 5)],
- ?line [#bar{d=4}] = [X || X <- List, is_record(X, bar, 5)],
- ?line [1,#foo{a=2},3,5,#foo{a=6},7] =
+ [#foo{a=2},#foo{a=6}] = [X || X <- List, is_record(X, foo, 5)],
+ [#bar{d=4}] = [X || X <- List, is_record(X, bar, 5)],
+ [1,#foo{a=2},3,5,#foo{a=6},7] =
[X || X <- List, not is_record(X, bar, 5)],
- ?line [1,3,5,7] =
+ [1,3,5,7] =
[X || X <- List, ((not is_record(X, bar, 5)) and (not is_record(X, foo, 5)))],
- ?line [#foo{a=2},#bar{d=4},#foo{a=6}] =
+ [#foo{a=2},#bar{d=4},#foo{a=6}] =
[X || X <- List, ((is_record(X, bar, 5)) or (is_record(X, foo, 5)))],
- ?line [1,3,#bar{d=4}] =
+ [1,3,#bar{d=4}] =
[X || X <- List, ((is_record(X, bar, 5)) or (X < 5))],
- ?line MyList = [#foo{a=3},x,[],{a,b}],
- ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo, 5)],
- ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo, 5)],
- ?line [#foo{a=3}] = [X || X <- MyList, begin is_record(X, foo, 5) end],
- ?line [x,[],{a,b}] = [X || X <- MyList, begin not is_record(X, foo, 5) end],
- ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, is_record(X, foo, 5) or
- not is_binary(X)],
- ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo, 5) or
- not is_binary(X)],
- ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo) or is_reference(X)],
- ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or
- is_reference(X)],
- ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList,
- begin is_record(X, foo, 5) or
- not is_binary(X) end],
- ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList,
- begin not is_record(X, foo, 5) or
- not is_binary(X) end],
- ?line [#foo{a=3}] = [X || X <- MyList,
- begin is_record(X, foo, 5) or is_reference(X) end],
- ?line [x,[],{a,b}] = [X || X <- MyList,
- begin not is_record(X, foo, 5) or
- is_reference(X) end],
+ MyList = [#foo{a=3},x,[],{a,b}],
+ [#foo{a=3}] = [X || X <- MyList, is_record(X, foo, 5)],
+ [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo, 5)],
+ [#foo{a=3}] = [X || X <- MyList, begin is_record(X, foo, 5) end],
+ [x,[],{a,b}] = [X || X <- MyList, begin not is_record(X, foo, 5) end],
+ [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, is_record(X, foo, 5) or
+ not is_binary(X)],
+ [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo, 5) or
+ not is_binary(X)],
+ [#foo{a=3}] = [X || X <- MyList, is_record(X, foo) or is_reference(X)],
+ [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or
+ is_reference(X)],
+ [#foo{a=3},x,[],{a,b}] = [X || X <- MyList,
+ begin is_record(X, foo, 5) or
+ not is_binary(X) end],
+ [#foo{a=3},x,[],{a,b}] = [X || X <- MyList,
+ begin not is_record(X, foo, 5) or
+ not is_binary(X) end],
+ [#foo{a=3}] = [X || X <- MyList,
+ begin is_record(X, foo, 5) or is_reference(X) end],
+ [x,[],{a,b}] = [X || X <- MyList,
+ begin not is_record(X, foo, 5) or
+ is_reference(X) end],
%% Update several fields with a string literal.
- ?line #barf{} = Barf0 = id(#barf{}),
- ?line Barf = update_barf(Barf0),
- ?line #barf{a="abc",b=1} = id(Barf),
+ #barf{} = Barf0 = id(#barf{}),
+ Barf = update_barf(Barf0),
+ #barf{a="abc",b=1} = id(Barf),
%% Non-literal arguments.
- ?line true = is_record(id(#barf{}), id(barf), id(6)),
- ?line false = is_record(id(#barf{}), id(barf), id(42)),
- ?line false = is_record(id(#barf{}), id(foo), id(6)),
+ true = is_record(id(#barf{}), id(barf), id(6)),
+ false = is_record(id(#barf{}), id(barf), id(42)),
+ false = is_record(id(#barf{}), id(foo), id(6)),
Rec = id(#barf{}),
Good = id(barf),
@@ -389,15 +388,15 @@ record_test_3(Config) when is_list(Config) ->
ok.
record_access_in_guards(Config) when is_list(Config) ->
- ?line Priv = ?config(priv_dir, Config),
- ?line file:set_cwd(test_lib:get_data_dir(Config)),
- ?line Opts0 = [{outdir,Priv},report_errors|test_lib:opt_opts(?MODULE)],
+ Priv = proplists:get_value(priv_dir, Config),
+ file:set_cwd(test_lib:get_data_dir(Config)),
+ Opts0 = [{outdir,Priv},report_errors|test_lib:opt_opts(?MODULE)],
M = record_access_in_guards,
Opts = [strict_record_tests|Opts0],
- ?line io:format("Options: ~p\n", [Opts]),
- ?line {ok,M} = c:c(M, Opts),
- ?line ok = M:t(),
+ io:format("Options: ~p\n", [Opts]),
+ {ok,M} = c:c(M, Opts),
+ ok = M:t(),
ok.
@@ -487,19 +486,19 @@ update_barf(R) ->
R#barf{a="abc",b=1}.
eval_once(Config) when is_list(Config) ->
- ?line once(fun(GetRec) ->
+ once(fun(GetRec) ->
true = erlang:is_record(GetRec(), foo)
end, #foo{}),
- ?line once(fun(GetRec) ->
+ once(fun(GetRec) ->
(GetRec())#foo{a=1}
end, #foo{}),
- ?line once(fun(GetRec) ->
+ once(fun(GetRec) ->
(GetRec())#foo{a=1,b=2}
end, #foo{}),
- ?line once(fun(GetRec) ->
+ once(fun(GetRec) ->
(GetRec())#foo{a=1,b=2,c=3}
end, #foo{}),
- ?line once(fun(GetRec) ->
+ once(fun(GetRec) ->
(GetRec())#foo{a=1,b=2,c=3,d=4}
end, #foo{}),
ok.
@@ -515,7 +514,7 @@ once(Test, Record) ->
1 -> ok;
N ->
io:format("Evaluated ~w times\n", [N]),
- ?t:fail()
+ ct:fail(more_than_once)
end,
Result.
@@ -571,21 +570,21 @@ nested_access(Config) when is_list(Config) ->
N0 = #nrec0{},
N1 = #nrec1{},
N2 = #nrec2{},
- ?line <<"nested0">> = N0#nrec0.name,
- ?line <<"nested1">> = N1#nrec1.name,
- ?line <<"nested2">> = N2#nrec2.name,
- ?line <<"nested0">> = N1#nrec1.nrec0#nrec0.name,
- ?line <<"nested0">> = N2#nrec2.nrec1#nrec1.nrec0#nrec0.name,
- ?line <<"nested1">> = N2#nrec2.nrec1#nrec1.name,
- ?line <<"nested0">> = ((N2#nrec2.nrec1)#nrec1.nrec0)#nrec0.name,
+ <<"nested0">> = N0#nrec0.name,
+ <<"nested1">> = N1#nrec1.name,
+ <<"nested2">> = N2#nrec2.name,
+ <<"nested0">> = N1#nrec1.nrec0#nrec0.name,
+ <<"nested0">> = N2#nrec2.nrec1#nrec1.nrec0#nrec0.name,
+ <<"nested1">> = N2#nrec2.nrec1#nrec1.name,
+ <<"nested0">> = ((N2#nrec2.nrec1)#nrec1.nrec0)#nrec0.name,
N1a = N2#nrec2.nrec1#nrec1{name = <<"nested1a">>},
- ?line <<"nested1a">> = N1a#nrec1.name,
+ <<"nested1a">> = N1a#nrec1.name,
N2a = N2#nrec2.nrec1#nrec1.nrec0#nrec0{name = <<"nested0a">>},
N2b = ((N2#nrec2.nrec1)#nrec1.nrec0)#nrec0{name = <<"nested0a">>},
- ?line <<"nested0a">> = N2a#nrec0.name,
- ?line N2a = N2b,
+ <<"nested0a">> = N2a#nrec0.name,
+ N2a = N2b,
ok.
-record(rr, {a,b,c}).
diff --git a/lib/compiler/test/regressions_SUITE.erl b/lib/compiler/test/regressions_SUITE.erl
index 716a9693ed..3fd4645529 100644
--- a/lib/compiler/test/regressions_SUITE.erl
+++ b/lib/compiler/test/regressions_SUITE.erl
@@ -19,28 +19,25 @@
%% Test specific code snippets that has crashed the compiler in the past.
-module(regressions_SUITE).
--include_lib("test_server/include/test_server.hrl").
-
--export([all/0, groups/0, init_per_testcase/2,end_per_testcase/2]).
+-include_lib("common_test/include/ct.hrl").
+-export([all/0,groups/0,init_per_testcase/2,end_per_testcase/2,suite/0]).
-export([maps/1]).
groups() ->
[{p,test_lib:parallel(),
[maps]}].
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(2)).
-
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,2}}].
+
all() ->
test_lib:recompile(?MODULE),
[{group,p}].
@@ -62,7 +59,8 @@ run(Config, Tests) ->
io:format("Compiling test for: ~w~n", [N]),
case catch run_test(Config, P) of
{'EXIT', Reason} ->
- ?t:format("~nTest ~p failed.~nReason: ~p~n", [N, Reason]),
+ io:format("~nTest ~p failed.~nReason: ~p~n",
+ [N, Reason]),
fail();
_ -> ok
end
@@ -73,7 +71,7 @@ run(Config, Tests) ->
run_test(Conf, Test0) ->
Module = "regressions_"++test_lib:uniq(),
Filename = Module ++ ".erl",
- DataDir = ?config(priv_dir, Conf),
+ DataDir = proplists:get_value(priv_dir, Conf),
Test = ["-module(", Module, "). ", Test0],
File = filename:join(DataDir, Filename),
Def = [binary,export_all,return],
@@ -94,5 +92,4 @@ run_test(Conf, Test0) ->
ok.
fail() ->
- io:format("failed~n"),
- ?t:fail().
+ ct:fail(failed).
diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl
index 09ec8f3c81..3ca93fb021 100644
--- a/lib/compiler/test/test_lib.erl
+++ b/lib/compiler/test/test_lib.erl
@@ -19,7 +19,7 @@
%%
-module(test_lib).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-compile({no_auto_import,[binary_part/2]}).
-export([id/1,recompile/1,parallel/0,uniq/0,opt_opts/1,get_data_dir/1,
smoke_disasm/1,p_run/2,binary_part/2]).
@@ -52,7 +52,7 @@ smoke_disasm(File) when is_list(File) ->
%% be slower than running them sequentially.
parallel() ->
- case ?t:is_cover() orelse erlang:system_info(schedulers) =:= 1 of
+ case test_server:is_cover() orelse erlang:system_info(schedulers) =:= 1 of
true -> [];
false -> [parallel]
end.
@@ -66,7 +66,7 @@ uniq() ->
opt_opts(Mod) ->
Comp = Mod:module_info(compile),
- {value,{options,Opts}} = lists:keysearch(options, 1, Comp),
+ {options,Opts} = lists:keyfind(options, 1, Comp),
lists:filter(fun(no_copt) -> true;
(no_postopt) -> true;
(no_float_opt) -> true;
@@ -85,7 +85,7 @@ opt_opts(Mod) ->
%% This function retrieves the path to the original data directory.
get_data_dir(Config) ->
- Data0 = ?config(data_dir, Config),
+ Data0 = proplists:get_value(data_dir, Config),
Opts = [{return,list}],
Data1 = re:replace(Data0, "_no_opt_SUITE", "_SUITE", Opts),
Data = re:replace(Data1, "_post_opt_SUITE", "_SUITE", Opts),
@@ -96,7 +96,7 @@ get_data_dir(Config) ->
p_run(Test, List) ->
S = erlang:system_info(schedulers),
- N = case ?t:is_cover() of
+ N = case test_server:is_cover() of
false ->
S + 1;
true ->
@@ -118,7 +118,8 @@ p_run_loop(_, [], _, [], Errors, Ws) ->
1 -> {comment,"1 warning"};
N -> {comment,integer_to_list(N)++" warnings"}
end;
- N -> ?t:fail({N,errors})
+ N ->
+ ct:fail({N,errors})
end;
p_run_loop(Test, [H|T], N, Refs, Errors, Ws) when length(Refs) < N ->
{_,Ref} = erlang:spawn_monitor(fun() -> exit(Test(H)) end),
diff --git a/lib/compiler/test/trycatch_SUITE.erl b/lib/compiler/test/trycatch_SUITE.erl
index adcab8ef67..82e3c86649 100644
--- a/lib/compiler/test/trycatch_SUITE.erl
+++ b/lib/compiler/test/trycatch_SUITE.erl
@@ -28,7 +28,7 @@
plain_catch_coverage/1,andalso_orelse/1,get_in_try/1,
hockey/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -60,32 +60,32 @@ end_per_group(_GroupName, Config) ->
basic(Conf) when is_list(Conf) ->
- ?line 2 =
+ 2 =
try my_div(4, 2)
catch
Class:Reason -> {Class,Reason}
end,
- ?line error =
+ error =
try my_div(1, 0)
catch
error:badarith -> error
end,
- ?line error =
+ error =
try 1.0 / zero()
catch
error:badarith -> error
end,
- ?line ok =
+ ok =
try my_add(53, atom)
catch
error:badarith -> ok
end,
- ?line exit_nisse =
+ exit_nisse =
try exit(nisse)
catch
exit:nisse -> exit_nisse
end,
- ?line ok =
+ ok =
try throw(kalle)
catch
kalle -> ok
@@ -94,27 +94,27 @@ basic(Conf) when is_list(Conf) ->
%% Try some stuff where the compiler will optimize away the try.
V = id({a,variable}),
- ?line V = try V catch nisse -> error end,
- ?line 42 = try 42 catch nisse -> error end,
- ?line [V] = try [V] catch nisse -> error end,
- ?line {ok,V} = try {ok,V} catch nisse -> error end,
+ V = try V catch nisse -> error end,
+ 42 = try 42 catch nisse -> error end,
+ [V] = try [V] catch nisse -> error end,
+ {ok,V} = try {ok,V} catch nisse -> error end,
%% Same idea, but use an after too.
- ?line V = try V catch nisse -> error after after_call() end,
- ?line after_clean(),
- ?line 42 = try 42 after after_call() end,
- ?line after_clean(),
- ?line [V] = try [V] catch nisse -> error after after_call() end,
- ?line after_clean(),
- ?line {ok,V} = try {ok,V} after after_call() end,
+ V = try V catch nisse -> error after after_call() end,
+ after_clean(),
+ 42 = try 42 after after_call() end,
+ after_clean(),
+ [V] = try [V] catch nisse -> error after after_call() end,
+ after_clean(),
+ {ok,V} = try {ok,V} after after_call() end,
%% Try/of
- ?line ok = try V of
- {a,variable} -> ok
- catch nisse -> erro
- end,
-
+ ok = try V of
+ {a,variable} -> ok
+ catch nisse -> erro
+ end,
+
ok.
after_call() ->
@@ -125,24 +125,24 @@ after_clean() ->
lean_throw(Conf) when is_list(Conf) ->
- ?line {throw,kalle} =
+ {throw,kalle} =
try throw(kalle)
catch
Kalle -> {throw,Kalle}
end,
- ?line {exit,kalle} =
+ {exit,kalle} =
try exit(kalle)
catch
Throw1 -> {throw,Throw1};
exit:Reason1 -> {exit,Reason1}
end,
- ?line {exit,kalle} =
+ {exit,kalle} =
try exit(kalle)
catch
exit:Reason2 -> {exit,Reason2};
Throw2 -> {throw,Throw2}
end,
- ?line {exit,kalle} =
+ {exit,kalle} =
try try exit(kalle)
catch
Throw3 -> {throw,Throw3}
@@ -155,25 +155,25 @@ lean_throw(Conf) when is_list(Conf) ->
try_of(Conf) when is_list(Conf) ->
- ?line {ok,{some,content}} =
+ {ok,{some,content}} =
try_of_1({value,{good,{some,content}}}),
- ?line {error,[other,content]} =
+ {error,[other,content]} =
try_of_1({value,{bad,[other,content]}}),
- ?line {caught,{exit,{ex,it,[reason]}}} =
+ {caught,{exit,{ex,it,[reason]}}} =
try_of_1({exit,{ex,it,[reason]}}),
- ?line {caught,{throw,[term,{in,a,{tuple}}]}} =
+ {caught,{throw,[term,{in,a,{tuple}}]}} =
try_of_1({throw,[term,{in,a,{tuple}}]}),
- ?line {caught,{error,[bad,arg]}} =
+ {caught,{error,[bad,arg]}} =
try_of_1({error,[bad,arg]}),
- ?line {caught,{error,badarith}} =
+ {caught,{error,badarith}} =
try_of_1({'div',{1,0}}),
- ?line {caught,{error,badarith}} =
+ {caught,{error,badarith}} =
try_of_1({'add',{a,0}}),
- ?line {caught,{error,badarg}} =
+ {caught,{error,badarg}} =
try_of_1({'abs',x}),
- ?line {caught,{error,function_clause}} =
+ {caught,{error,function_clause}} =
try_of_1(illegal),
- ?line {error,{try_clause,{some,other_garbage}}} =
+ {error,{try_clause,{some,other_garbage}}} =
try try_of_1({value,{some,other_garbage}})
catch error:Reason -> {error,Reason}
end,
@@ -191,29 +191,29 @@ try_of_1(X) ->
try_after(Conf) when is_list(Conf) ->
- ?line {{ok,[some,value],undefined},finalized} =
+ {{ok,[some,value],undefined},finalized} =
try_after_1({value,{ok,[some,value]}},finalized),
- ?line {{error,badarith,undefined},finalized} =
+ {{error,badarith,undefined},finalized} =
try_after_1({'div',{1,0}},finalized),
- ?line {{error,badarith,undefined},finalized} =
+ {{error,badarith,undefined},finalized} =
try_after_1({'add',{1,a}},finalized),
- ?line {{error,badarg,undefined},finalized} =
+ {{error,badarg,undefined},finalized} =
try_after_1({'abs',a},finalized),
- ?line {{error,[the,{reason}],undefined},finalized} =
+ {{error,[the,{reason}],undefined},finalized} =
try_after_1({error,[the,{reason}]},finalized),
- ?line {{throw,{thrown,[reason]},undefined},finalized} =
+ {{throw,{thrown,[reason]},undefined},finalized} =
try_after_1({throw,{thrown,[reason]}},finalized),
- ?line {{exit,{exited,{reason}},undefined},finalized} =
+ {{exit,{exited,{reason}},undefined},finalized} =
try_after_1({exit,{exited,{reason}}},finalized),
- ?line {{error,function_clause,undefined},finalized} =
+ {{error,function_clause,undefined},finalized} =
try_after_1(function_clause,finalized),
- ?line ok =
+ ok =
try try_after_1({'add',{1,1}}, finalized)
catch
error:{try_clause,2} -> ok
end,
- ?line finalized = erase(try_after),
- ?line ok =
+ finalized = erase(try_after),
+ ok =
try try foo({exit,[reaso,{n}]})
after put(try_after, finalized)
end
@@ -242,7 +242,7 @@ try_after_1(X, Y) ->
after_bind(Conf) when is_list(Conf) ->
V = [make_ref(),self()|value],
- ?line {value,{value,V}} =
+ {value,{value,V}} =
after_bind_1({value,V}, V, {value,V}),
ok.
@@ -269,12 +269,12 @@ after_bind_1(X, V, Y) ->
catch_oops(Conf) when is_list(Conf) ->
V = {v,[a,l|u],{e},self()},
- ?line {value,V} = catch_oops_1({value,V}),
- ?line {value,1} = catch_oops_1({'div',{1,1}}),
- ?line {error,badarith} = catch_oops_1({'div',{1,0}}),
- ?line {error,function_clause} = catch_oops_1(function_clause),
- ?line {throw,V} = catch_oops_1({throw,V}),
- ?line {exit,V} = catch_oops_1({exit,V}),
+ {value,V} = catch_oops_1({value,V}),
+ {value,1} = catch_oops_1({'div',{1,1}}),
+ {error,badarith} = catch_oops_1({'div',{1,0}}),
+ {error,function_clause} = catch_oops_1(function_clause),
+ {throw,V} = catch_oops_1({throw,V}),
+ {exit,V} = catch_oops_1({exit,V}),
ok.
catch_oops_1(X) ->
@@ -293,10 +293,10 @@ catch_oops_1(X) ->
after_oops(Conf) when is_list(Conf) ->
V = {self(),make_ref()},
- ?line {{value,V},V} = after_oops_1({value,V}, {value,V}),
- ?line {{exit,V},V} = after_oops_1({exit,V}, {value,V}),
- ?line {{error,V},undefined} = after_oops_1({value,V}, {error,V}),
- ?line {{error,function_clause},undefined} =
+ {{value,V},V} = after_oops_1({value,V}, {value,V}),
+ {{exit,V},V} = after_oops_1({exit,V}, {value,V}),
+ {{error,V},undefined} = after_oops_1({value,V}, {error,V}),
+ {{error,function_clause},undefined} =
after_oops_1({exit,V}, function_clause),
ok.
@@ -317,39 +317,39 @@ after_oops_1(X, Y) ->
eclectic(Conf) when is_list(Conf) ->
V = {make_ref(),3.1415926535,[[]|{}]},
- ?line {{value,{value,V},V},V} =
+ {{value,{value,V},V},V} =
eclectic_1({foo,{value,{value,V}}}, undefined, {value,V}),
- ?line {{'EXIT',{V,[{?MODULE,foo,1,_}|_]}},V} =
+ {{'EXIT',{V,[{?MODULE,foo,1,_}|_]}},V} =
eclectic_1({catch_foo,{error,V}}, undefined, {value,V}),
- ?line {{error,{exit,V},{'EXIT',V}},V} =
+ {{error,{exit,V},{'EXIT',V}},V} =
eclectic_1({foo,{error,{exit,V}}}, error, {value,V}),
- ?line {{value,{value,V},V},
+ {{value,{value,V},V},
{'EXIT',{badarith,[{?MODULE,my_add,2,_}|_]}}} =
eclectic_1({foo,{value,{value,V}}}, undefined, {'add',{0,a}}),
- ?line {{'EXIT',V},V} =
+ {{'EXIT',V},V} =
eclectic_1({catch_foo,{exit,V}}, undefined, {throw,V}),
- ?line {{error,{'div',{1,0}},{'EXIT',{badarith,[{?MODULE,my_div,2,_}|_]}}},
+ {{error,{'div',{1,0}},{'EXIT',{badarith,[{?MODULE,my_div,2,_}|_]}}},
{'EXIT',V}} =
eclectic_1({foo,{error,{'div',{1,0}}}}, error, {exit,V}),
- ?line {{{error,V},{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},
+ {{{error,V},{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},
{'EXIT',V}} =
eclectic_1({catch_foo,{throw,{error,V}}}, undefined, {exit,V}),
%%
- ?line {{value,{value,{value,V},V}},V} =
+ {{value,{value,{value,V},V}},V} =
eclectic_2({value,{value,V}}, undefined, {value,V}),
- ?line {{value,{throw,{value,V},V}},V} =
+ {{value,{throw,{value,V},V}},V} =
eclectic_2({throw,{value,V}}, throw, {value,V}),
- ?line {{caught,{'EXIT',V}},undefined} =
+ {{caught,{'EXIT',V}},undefined} =
eclectic_2({value,{value,V}}, undefined, {exit,V}),
- ?line {{caught,{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},undefined} =
+ {{caught,{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},undefined} =
eclectic_2({error,{value,V}}, throw, {error,V}),
- ?line {{caught,{'EXIT',{badarg,[{erlang,abs,[V],_}|_]}}},V} =
+ {{caught,{'EXIT',{badarg,[{erlang,abs,[V],_}|_]}}},V} =
eclectic_2({value,{'abs',V}}, undefined, {value,V}),
- ?line {{caught,{'EXIT',{badarith,[{?MODULE,my_add,2,_}|_]}}},V} =
+ {{caught,{'EXIT',{badarith,[{?MODULE,my_add,2,_}|_]}}},V} =
eclectic_2({exit,{'add',{0,a}}}, exit, {value,V}),
- ?line {{caught,{'EXIT',V}},undefined} =
+ {{caught,{'EXIT',V}},undefined} =
eclectic_2({value,{error,V}}, undefined, {exit,V}),
- ?line {{caught,{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},undefined} =
+ {{caught,{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},undefined} =
eclectic_2({throw,{'div',{1,0}}}, throw, {error,V}),
ok.
@@ -377,44 +377,44 @@ eclectic_2(X, C, Y) ->
Catch =
case
catch
- {Done,
- try foo(X) of
- V -> {value,V,foo(V)}
- catch
- C:D -> {C,D,foo(D)}
- after
- put(eclectic, foo(Y))
- end} of
- {Done,Z} -> {value,Z};
- Z -> {caught,Z}
- end,
+ {Done,
+ try foo(X) of
+ V -> {value,V,foo(V)}
+ catch
+ C:D -> {C,D,foo(D)}
+ after
+ put(eclectic, foo(Y))
+ end} of
+ {Done,Z} -> {value,Z};
+ Z -> {caught,Z}
+ end,
{Catch,erase(eclectic)}.
rethrow(Conf) when is_list(Conf) ->
V = {a,[b,{c,self()},make_ref]},
- ?line {value2,value1} =
+ {value2,value1} =
rethrow_1({value,V}, V),
- ?line {caught2,{error,V}} =
+ {caught2,{error,V}} =
rethrow_2({error,V}, undefined),
- ?line {caught2,{exit,V}} =
+ {caught2,{exit,V}} =
rethrow_1({exit,V}, error),
- ?line {caught2,{throw,V}} =
+ {caught2,{throw,V}} =
rethrow_1({throw,V}, undefined),
- ?line {caught2,{throw,V}} =
+ {caught2,{throw,V}} =
rethrow_2({throw,V}, undefined),
- ?line {caught2,{error,badarith}} =
+ {caught2,{error,badarith}} =
rethrow_1({'add',{0,a}}, throw),
- ?line {caught2,{error,function_clause}} =
+ {caught2,{error,function_clause}} =
rethrow_2(function_clause, undefined),
- ?line {caught2,{error,{try_clause,V}}} =
+ {caught2,{error,{try_clause,V}}} =
rethrow_1({value,V}, exit),
- ?line {value2,{caught1,V}} =
+ {value2,{caught1,V}} =
rethrow_1({error,V}, error),
- ?line {value2,{caught1,V}} =
+ {value2,{caught1,V}} =
rethrow_1({exit,V}, exit),
- ?line {value2,caught1} =
+ {value2,caught1} =
rethrow_2({throw,V}, V),
ok.
@@ -444,91 +444,91 @@ rethrow_2(X, C1) ->
nested_of(Conf) when is_list(Conf) ->
V = {[self()|make_ref()],1.4142136},
- ?line {{value,{value1,{V,x2}}},
- {V,x3},
- {V,x4},
- finalized} =
+ {{value,{value1,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
nested_of_1({{value,{V,x1}},void,{V,x1}},
{value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
- ?line {{caught,{throw,{V,x2}}},
- {V,x3},
- {V,x4},
- finalized} =
+ {{caught,{throw,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
nested_of_1({{value,{V,x1}},void,{V,x1}},
{throw,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
- ?line {{caught,{error,badarith}},
- undefined,
- {V,x4},
- finalized} =
+ {{caught,{error,badarith}},
+ undefined,
+ {V,x4},
+ finalized} =
nested_of_1({{value,{V,x1}},void,{V,x1}},
{throw,{V,x2}}, {'div',{1,0}}, {value,{V,x4}}),
- ?line {{caught,{error,badarith}},
- undefined,
- undefined,
- finalized} =
+ {{caught,{error,badarith}},
+ undefined,
+ undefined,
+ finalized} =
nested_of_1({{value,{V,x1}},void,{V,x1}},
{throw,{V,x2}}, {'div',{1,0}}, {'add',{0,b}}),
%%
- ?line {{caught,{error,{try_clause,{V,x1}}}},
- {V,x3},
- {V,x4},
- finalized} =
+ {{caught,{error,{try_clause,{V,x1}}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
nested_of_1({{value,{V,x1}},void,try_clause},
void, {value,{V,x3}}, {value,{V,x4}}),
- ?line {{caught,{exit,{V,x3}}},
- undefined,
- {V,x4},
- finalized} =
+ {{caught,{exit,{V,x3}}},
+ undefined,
+ {V,x4},
+ finalized} =
nested_of_1({{value,{V,x1}},void,try_clause},
void, {exit,{V,x3}}, {value,{V,x4}}),
- ?line {{caught,{throw,{V,x4}}},
- undefined,
- undefined,
- finalized} =
+ {{caught,{throw,{V,x4}}},
+ undefined,
+ undefined,
+ finalized} =
nested_of_1({{value,{V,x1}},void,try_clause},
void, {exit,{V,x3}}, {throw,{V,x4}}),
%%
- ?line {{value,{caught1,{V,x2}}},
- {V,x3},
- {V,x4},
- finalized} =
+ {{value,{caught1,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
nested_of_1({{error,{V,x1}},error,{V,x1}},
{value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
- ?line {{caught,{error,badarith}},
- {V,x3},
- {V,x4},
- finalized} =
+ {{caught,{error,badarith}},
+ {V,x3},
+ {V,x4},
+ finalized} =
nested_of_1({{error,{V,x1}},error,{V,x1}},
{'add',{1,c}}, {value,{V,x3}}, {value,{V,x4}}),
- ?line {{caught,{error,badarith}},
- undefined,
- {V,x4},
- finalized} =
+ {{caught,{error,badarith}},
+ undefined,
+ {V,x4},
+ finalized} =
nested_of_1({{error,{V,x1}},error,{V,x1}},
{'add',{1,c}}, {'div',{17,0}}, {value,{V,x4}}),
- ?line {{caught,{error,badarg}},
- undefined,
- undefined,
- finalized} =
+ {{caught,{error,badarg}},
+ undefined,
+ undefined,
+ finalized} =
nested_of_1({{error,{V,x1}},error,{V,x1}},
{'add',{1,c}}, {'div',{17,0}}, {'abs',V}),
%%
- ?line {{caught,{error,badarith}},
- {V,x3},
- {V,x4},
- finalized} =
+ {{caught,{error,badarith}},
+ {V,x3},
+ {V,x4},
+ finalized} =
nested_of_1({{'add',{2,c}},rethrow,void},
void, {value,{V,x3}}, {value,{V,x4}}),
- ?line {{caught,{error,badarg}},
- undefined,
- {V,x4},
- finalized} =
+ {{caught,{error,badarg}},
+ undefined,
+ {V,x4},
+ finalized} =
nested_of_1({{'add',{2,c}},rethrow,void},
void, {'abs',V}, {value,{V,x4}}),
- ?line {{caught,{error,function_clause}},
- undefined,
- undefined,
- finalized} =
+ {{caught,{error,function_clause}},
+ undefined,
+ undefined,
+ finalized} =
nested_of_1({{'add',{2,c}},rethrow,void},
void, {'abs',V}, function_clause),
ok.
@@ -569,93 +569,93 @@ nested_of_1({X1,C1,V1},
nested_catch(Conf) when is_list(Conf) ->
V = {[make_ref(),1.4142136,self()]},
- ?line {{value,{value1,{V,x2}}},
- {V,x3},
- {V,x4},
- finalized} =
+ {{value,{value1,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
nested_catch_1({{value,{V,x1}},void,{V,x1}},
- {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
- ?line {{caught,{throw,{V,x2}}},
- {V,x3},
- {V,x4},
- finalized} =
+ {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
+ {{caught,{throw,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
nested_catch_1({{value,{V,x1}},void,{V,x1}},
- {throw,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
- ?line {{caught,{error,badarith}},
- undefined,
- {V,x4},
- finalized} =
+ {throw,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
+ {{caught,{error,badarith}},
+ undefined,
+ {V,x4},
+ finalized} =
nested_catch_1({{value,{V,x1}},void,{V,x1}},
- {throw,{V,x2}}, {'div',{1,0}}, {value,{V,x4}}),
- ?line {{caught,{error,badarith}},
- undefined,
- undefined,
- finalized} =
+ {throw,{V,x2}}, {'div',{1,0}}, {value,{V,x4}}),
+ {{caught,{error,badarith}},
+ undefined,
+ undefined,
+ finalized} =
nested_catch_1({{value,{V,x1}},void,{V,x1}},
- {throw,{V,x2}}, {'div',{1,0}}, {'add',{0,b}}),
+ {throw,{V,x2}}, {'div',{1,0}}, {'add',{0,b}}),
%%
- ?line {{caught,{error,{try_clause,{V,x1}}}},
- {V,x3},
- {V,x4},
- finalized} =
+ {{caught,{error,{try_clause,{V,x1}}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
nested_catch_1({{value,{V,x1}},void,try_clause},
- void, {value,{V,x3}}, {value,{V,x4}}),
- ?line {{caught,{exit,{V,x3}}},
- undefined,
- {V,x4},
- finalized} =
+ void, {value,{V,x3}}, {value,{V,x4}}),
+ {{caught,{exit,{V,x3}}},
+ undefined,
+ {V,x4},
+ finalized} =
nested_catch_1({{value,{V,x1}},void,try_clause},
- void, {exit,{V,x3}}, {value,{V,x4}}),
- ?line {{caught,{throw,{V,x4}}},
- undefined,
- undefined,
- finalized} =
+ void, {exit,{V,x3}}, {value,{V,x4}}),
+ {{caught,{throw,{V,x4}}},
+ undefined,
+ undefined,
+ finalized} =
nested_catch_1({{value,{V,x1}},void,try_clause},
- void, {exit,{V,x3}}, {throw,{V,x4}}),
+ void, {exit,{V,x3}}, {throw,{V,x4}}),
%%
- ?line {{value,{caught1,{V,x2}}},
- {V,x3},
- {V,x4},
- finalized} =
+ {{value,{caught1,{V,x2}}},
+ {V,x3},
+ {V,x4},
+ finalized} =
nested_catch_1({{error,{V,x1}},error,{V,x1}},
- {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
- ?line {{caught,{error,badarith}},
- {V,x3},
- {V,x4},
- finalized} =
+ {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}),
+ {{caught,{error,badarith}},
+ {V,x3},
+ {V,x4},
+ finalized} =
nested_catch_1({{error,{V,x1}},error,{V,x1}},
- {'add',{1,c}}, {value,{V,x3}}, {value,{V,x4}}),
- ?line {{caught,{error,badarith}},
- undefined,
- {V,x4},
- finalized} =
+ {'add',{1,c}}, {value,{V,x3}}, {value,{V,x4}}),
+ {{caught,{error,badarith}},
+ undefined,
+ {V,x4},
+ finalized} =
nested_catch_1({{error,{V,x1}},error,{V,x1}},
- {'add',{1,c}}, {'div',{17,0}}, {value,{V,x4}}),
- ?line {{caught,{error,badarg}},
- undefined,
- undefined,
- finalized} =
+ {'add',{1,c}}, {'div',{17,0}}, {value,{V,x4}}),
+ {{caught,{error,badarg}},
+ undefined,
+ undefined,
+ finalized} =
nested_catch_1({{error,{V,x1}},error,{V,x1}},
- {'add',{1,c}}, {'div',{17,0}}, {'abs',V}),
+ {'add',{1,c}}, {'div',{17,0}}, {'abs',V}),
%%
- ?line {{caught,{error,badarith}},
- {V,x3},
- {V,x4},
- finalized} =
+ {{caught,{error,badarith}},
+ {V,x3},
+ {V,x4},
+ finalized} =
nested_catch_1({{'add',{2,c}},rethrow,void},
- void, {value,{V,x3}}, {value,{V,x4}}),
- ?line {{caught,{error,badarg}},
- undefined,
- {V,x4},
- finalized} =
+ void, {value,{V,x3}}, {value,{V,x4}}),
+ {{caught,{error,badarg}},
+ undefined,
+ {V,x4},
+ finalized} =
nested_catch_1({{'add',{2,c}},rethrow,void},
- void, {'abs',V}, {value,{V,x4}}),
- ?line {{caught,{error,function_clause}},
- undefined,
- undefined,
- finalized} =
+ void, {'abs',V}, {value,{V,x4}}),
+ {{caught,{error,function_clause}},
+ undefined,
+ undefined,
+ finalized} =
nested_catch_1({{'add',{2,c}},rethrow,void},
- void, {'abs',V}, function_clause),
+ void, {'abs',V}, function_clause),
ok.
nested_catch_1({X1,C1,V1},
@@ -694,64 +694,64 @@ nested_catch_1({X1,C1,V1},
nested_after(Conf) when is_list(Conf) ->
V = [{make_ref(),1.4142136,self()}],
- ?line {value,
+ {value,
{V,x3},
{value1,{V,x2}},
finalized} =
nested_after_1({{value,{V,x1}},void,{V,x1}},
{value,{V,x2}}, {value,{V,x3}}),
- ?line {{caught,{error,{V,x2}}},
+ {{caught,{error,{V,x2}}},
{V,x3},
undefined,
finalized} =
nested_after_1({{value,{V,x1}},void,{V,x1}},
{error,{V,x2}}, {value,{V,x3}}),
- ?line {{caught,{exit,{V,x3}}},
+ {{caught,{exit,{V,x3}}},
undefined,
undefined,
finalized} =
nested_after_1({{value,{V,x1}},void,{V,x1}},
{error,{V,x2}}, {exit,{V,x3}}),
%%
- ?line {{caught,{error,{try_clause,{V,x1}}}},
+ {{caught,{error,{try_clause,{V,x1}}}},
{V,x3},
undefined,
finalized} =
nested_after_1({{value,{V,x1}},void,try_clause},
void, {value,{V,x3}}),
- ?line {{caught,{error,badarith}},
+ {{caught,{error,badarith}},
undefined,
undefined,
finalized} =
nested_after_1({{value,{V,x1}},void,try_clause},
void, {'div',{17,0}}),
%%
- ?line {value,
+ {value,
{V,x3},
{caught1,{V,x2}},
finalized} =
nested_after_1({{throw,{V,x1}},throw,{V,x1}},
{value,{V,x2}}, {value,{V,x3}}),
- ?line {{caught,{error,badarith}},
+ {{caught,{error,badarith}},
{V,x3},
undefined,
finalized} =
nested_after_1({{throw,{V,x1}},throw,{V,x1}},
{'add',{a,b}}, {value,{V,x3}}),
- ?line {{caught,{error,badarg}},
+ {{caught,{error,badarg}},
undefined,
undefined,
finalized} =
nested_after_1({{throw,{V,x1}},throw,{V,x1}},
{'add',{a,b}}, {'abs',V}),
%%
- ?line {{caught,{throw,{V,x1}}},
+ {{caught,{throw,{V,x1}}},
{V,x3},
undefined,
finalized} =
nested_after_1({{throw,{V,x1}},rethrow,void},
void, {value,{V,x3}}),
- ?line {{caught,{error,badarith}},
+ {{caught,{error,badarith}},
undefined,
undefined,
finalized} =
@@ -843,12 +843,12 @@ my_abs(X) -> abs(X).
last_call_optimization(Config) when is_list(Config) ->
- ?line error = in_tail(dum),
- ?line StkSize0 = in_tail(0),
- ?line StkSize = in_tail(50000),
+ error = in_tail(dum),
+ StkSize0 = in_tail(0),
+ StkSize = in_tail(50000),
io:format("StkSize0 = ~p", [StkSize0]),
io:format("StkSize = ~p", [StkSize]),
- ?line StkSize = StkSize0,
+ StkSize = StkSize0,
ok.
in_tail(E) ->
@@ -891,20 +891,20 @@ do_bool(A0, B) ->
plain_catch_coverage(Config) when is_list(Config) ->
%% Cover some code in beam_block:alloc_may_pass/1.
- ?line {a,[42]} = do_plain_catch_list(42).
+ {a,[42]} = do_plain_catch_list(42).
do_plain_catch_list(X) ->
B = [X],
catch id({a,B}).
andalso_orelse(Config) when is_list(Config) ->
- ?line {2,{a,42}} = andalso_orelse_1(true, {a,42}),
- ?line {b,{b}} = andalso_orelse_1(false, {b}),
- ?line {catched,no_tuple} = andalso_orelse_1(false, no_tuple),
+ {2,{a,42}} = andalso_orelse_1(true, {a,42}),
+ {b,{b}} = andalso_orelse_1(false, {b}),
+ {catched,no_tuple} = andalso_orelse_1(false, no_tuple),
- ?line ok = andalso_orelse_2({type,[a]}),
- ?line also_ok = andalso_orelse_2({type,[]}),
- ?line also_ok = andalso_orelse_2({type,{a}}),
+ ok = andalso_orelse_2({type,[a]}),
+ also_ok = andalso_orelse_2({type,[]}),
+ also_ok = andalso_orelse_2({type,{a}}),
ok.
andalso_orelse_1(A, B) ->
diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl
index a964afe5a1..d66f2d5053 100644
--- a/lib/compiler/test/warnings_SUITE.erl
+++ b/lib/compiler/test/warnings_SUITE.erl
@@ -27,9 +27,9 @@
-define(privdir, "warnings_SUITE_priv").
-define(t, test_server).
-else.
--include_lib("test_server/include/test_server.hrl").
--define(datadir, ?config(data_dir, Conf)).
--define(privdir, ?config(priv_dir, Conf)).
+-include_lib("common_test/include/ct.hrl").
+-define(datadir, proplists:get_value(data_dir, Conf)).
+-define(privdir, proplists:get_value(priv_dir, Conf)).
-endif.
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -41,21 +41,18 @@
files/1,effect/1,bin_opt_info/1,bin_construction/1,
comprehensions/1,maps/1,maps_bin_opt_info/1,
redundant_boolean_clauses/1,
- latin1_fallback/1,underscore/1,no_warnings/1]).
-
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(2)).
+ latin1_fallback/1,underscore/1,no_warnings/1,
+ bit_syntax/1]).
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,2}}].
all() ->
test_lib:recompile(?MODULE),
@@ -68,7 +65,7 @@ groups() ->
bin_opt_info,bin_construction,comprehensions,maps,
maps_bin_opt_info,
redundant_boolean_clauses,latin1_fallback,
- underscore,no_warnings]}].
+ underscore,no_warnings,bit_syntax]}].
init_per_suite(Config) ->
Config.
@@ -103,7 +100,7 @@ pattern(Config) when is_list(Config) ->
[{2,v3_core,nomatch},
{6,v3_core,nomatch},
{11,v3_core,nomatch} ] }}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
pattern2(Config) when is_list(Config) ->
@@ -127,7 +124,7 @@ pattern2(Config) when is_list(Config) ->
{4,sys_core_fold,no_clause_match},
{5,sys_core_fold,nomatch_clause_type},
{6,sys_core_fold,nomatch_clause_type}]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
%% Disable Core Erlang optimizations. v3_kernel should produce
%% a warning for the clause that didn't match.
@@ -136,7 +133,7 @@ pattern2(Config) when is_list(Config) ->
[nowarn_unused_vars,no_copt],
{warnings,
[{2,v3_kernel,{nomatch_shadow,1}}]}}],
- ?line [] = run(Config, Ts2),
+ [] = run(Config, Ts2),
ok.
pattern3(Config) when is_list(Config) ->
@@ -152,7 +149,7 @@ pattern3(Config) when is_list(Config) ->
[nowarn_unused_vars],
{warnings,
[{4,v3_kernel,{nomatch_shadow,2}}]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
@@ -213,7 +210,7 @@ pattern4(Config) when is_list(Config) ->
{23,sys_core_fold,no_clause_match},
{33,sys_core_fold,no_clause_match}
]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
@@ -256,7 +253,7 @@ guard(Config) when is_list(Config) ->
{11,sys_core_fold,nomatch_guard},
{11,sys_core_fold,{eval_failure,badarg}}
]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
@@ -321,7 +318,7 @@ bool_cases(Config) when is_list(Config) ->
[{6,sys_core_fold,nomatch_shadow},
{13,sys_core_fold,nomatch_shadow},
{18,sys_core_fold,nomatch_clause_type} ]} }],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
bad_apply(Config) when is_list(Config) ->
@@ -340,11 +337,11 @@ bad_apply(Config) when is_list(Config) ->
{4,v3_kernel,bad_call},
{5,v3_kernel,bad_call},
{6,v3_kernel,bad_call}]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
%% Also verify that the generated code generates the correct error.
- ?line try erlang:42() of
- _ -> ?line ?t:fail()
+ try erlang:42() of
+ _ -> ct:fail(should_fail)
catch
error:badarg -> ok
end,
@@ -368,7 +365,7 @@ files(Config) when is_list(Config) ->
[{"file1",[{17,sys_core_fold,{eval_failure,badarith}}]},
{"file2",[{10,sys_core_fold,{eval_failure,badarith}}]}]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
%% Test warnings for term construction and BIF calls in effect context.
@@ -514,7 +511,7 @@ effect(Config) when is_list(Config) ->
{28,sys_core_fold,useless_building},
{36,sys_core_fold,{no_effect,{erlang,'=:=',2}}},
{38,sys_core_fold,{no_effect,{erlang,get_cookie,0}}}]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
bin_opt_info(Config) when is_list(Config) ->
@@ -537,14 +534,14 @@ bin_opt_info(Config) when is_list(Config) ->
{5,beam_bsm,{no_bin_opt,{{t1,1},no_suitable_bs_start_match}}},
{9,beam_bsm,{no_bin_opt,
{binary_used_in,{extfunc,erlang,split_binary,2}}}} ]}}],
- ?line [] = run(Config, Ts1),
+ [] = run(Config, Ts1),
%% For coverage: don't give the bin_opt_info option.
Ts2 = [{bsm2,
Code,
[],
[]}],
- ?line [] = run(Config, Ts2),
+ [] = run(Config, Ts2),
ok.
bin_construction(Config) when is_list(Config) ->
@@ -561,7 +558,7 @@ bin_construction(Config) when is_list(Config) ->
[],
{warnings,[{4,sys_core_fold,embedded_binary_size},
{8,sys_core_fold,{embedded_unit,8,28}}]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
@@ -783,6 +780,50 @@ no_warnings(Config) when is_list(Config) ->
run(Config, Ts),
ok.
+bit_syntax(Config) ->
+ Ts = [{?FUNCTION_NAME,
+ <<"a(<<-1>>) -> ok;
+ a(<<1023>>) -> ok;
+ a(<<777/signed>>) -> ok;
+ a(<<a/binary>>) -> ok;
+ a(<<a/integer>>) -> ok;
+ a(<<a/float>>) -> ok;
+ a(<<a/utf8>>) -> ok;
+ a(<<a/utf16>>) -> ok;
+ a(<<a/utf32>>) -> ok;
+ a(<<a/utf32>>) -> ok.
+ b(Bin) -> Sz = bad, <<42:Sz>> = Bin.
+ c(Sz, Bin) ->
+ case Bin of
+ <<-42:Sz/unsigned>> -> ok;
+ <<42:Sz/float>> -> ok;
+ <<42:Sz/binary>> -> ok
+ end.
+ ">>,
+ [],
+ {warnings,[{1,sys_core_fold,no_clause_match},
+ {1,sys_core_fold,{nomatch_bit_syntax_unsigned,-1}},
+ {2,sys_core_fold,{nomatch_bit_syntax_truncated,
+ unsigned,1023,8}},
+ {3,sys_core_fold,{nomatch_bit_syntax_truncated,
+ signed,777,8}},
+ {4,sys_core_fold,{nomatch_bit_syntax_type,a,binary}},
+ {5,sys_core_fold,{nomatch_bit_syntax_type,a,integer}},
+ {6,sys_core_fold,{nomatch_bit_syntax_type,a,float}},
+ {7,sys_core_fold,{nomatch_bit_syntax_type,a,utf8}},
+ {8,sys_core_fold,{nomatch_bit_syntax_type,a,utf16}},
+ {9,sys_core_fold,{nomatch_bit_syntax_type,a,utf32}},
+ {10,sys_core_fold,{nomatch_bit_syntax_type,a,utf32}},
+ {11,sys_core_fold,no_clause_match},
+ {11,sys_core_fold,{nomatch_bit_syntax_size,bad}},
+ {14,sys_core_fold,{nomatch_bit_syntax_unsigned,-42}},
+ {16,sys_core_fold,{nomatch_bit_syntax_type,42,binary}}
+ ]}
+ }],
+ run(Config, Ts),
+ ok.
+
+
%%%
%%% End of test cases.
%%%
@@ -793,7 +834,7 @@ run(Config, Tests) ->
E ->
BadL;
Bad ->
- ?t:format("~nTest ~p failed. Expected~n ~p~n"
+ io:format("~nTest ~p failed. Expected~n ~p~n"
"but got~n ~p~n", [N, E, Bad]),
fail()
end
@@ -806,33 +847,32 @@ run(Config, Tests) ->
run_test(Conf, Test0, Warnings) ->
Module = "warnings_"++test_lib:uniq(),
Filename = Module ++ ".erl",
- ?line DataDir = ?privdir,
+ DataDir = ?privdir,
Test = ["-module(", Module, "). ", Test0],
- ?line File = filename:join(DataDir, Filename),
- ?line Opts = [binary,export_all,return|Warnings],
- ?line ok = file:write_file(File, Test),
+ File = filename:join(DataDir, Filename),
+ Opts = [binary,export_all,return|Warnings],
+ ok = file:write_file(File, Test),
%% Compile once just to print all warnings.
- ?line compile:file(File, [binary,export_all,report|Warnings]),
+ compile:file(File, [binary,export_all,report|Warnings]),
%% Test result of compilation.
- ?line Res = case compile:file(File, Opts) of
- {ok, _M, Bin, []} when is_binary(Bin) ->
- [];
- {ok, _M, Bin, Ws0} when is_binary(Bin) ->
- %% We are not interested in warnings from
- %% erl_lint here.
- WsL = [{F,[W || {_,Mod,_}=W <- Ws,
- Mod =/= erl_lint]} ||
- {F,Ws} <- Ws0],
- case WsL of
- [{_File,Ws}] -> {warnings, Ws};
- _ -> list_to_tuple([warnings, WsL])
- end
- end,
+ Res = case compile:file(File, Opts) of
+ {ok, _M, Bin, []} when is_binary(Bin) ->
+ [];
+ {ok, _M, Bin, Ws0} when is_binary(Bin) ->
+ %% We are not interested in warnings from
+ %% erl_lint here.
+ WsL = [{F,[W || {_,Mod,_}=W <- Ws,
+ Mod =/= erl_lint]} ||
+ {F,Ws} <- Ws0],
+ case WsL of
+ [{_File,Ws}] -> {warnings, Ws};
+ _ -> list_to_tuple([warnings, WsL])
+ end
+ end,
file:delete(File),
Res.
fail() ->
- io:format("failed~n"),
- ?t:fail().
+ ct:fail(failed).
diff --git a/lib/cosEvent/test/Makefile b/lib/cosEvent/test/Makefile
index 2d29afd20d..028b0221b6 100644
--- a/lib/cosEvent/test/Makefile
+++ b/lib/cosEvent/test/Makefile
@@ -96,12 +96,10 @@ TARGET_FILES = \
ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/orber/ebin -pa $(ERL_TOP)/lib/ic/ebin
ERL_COMPILE_FLAGS += $(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/test_server/ebin \
-pa $(ERL_TOP)/lib/cosEvent/ebin \
-pa $(ERL_TOP)/lib/cosEvent/test/idl_output \
-I$(ERL_TOP)/lib/cosEvent \
- -I$(ERL_TOP)/lib/cosEvent/test/$(IDLOUTDIR) \
- -I$(ERL_TOP)/lib/test_server/include
+ -I$(ERL_TOP)/lib/cosEvent/test/$(IDLOUTDIR)
# ----------------------------------------------------
# Targets
diff --git a/lib/cosEvent/test/event_channel_SUITE.erl b/lib/cosEvent/test/event_channel_SUITE.erl
index 0d67a94520..3a01a0eab6 100644
--- a/lib/cosEvent/test/event_channel_SUITE.erl
+++ b/lib/cosEvent/test/event_channel_SUITE.erl
@@ -23,7 +23,7 @@
-module(event_channel_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming.hrl").
-include_lib("orber/src/orber_iiop.hrl").
diff --git a/lib/cosEvent/test/generated_SUITE.erl b/lib/cosEvent/test/generated_SUITE.erl
index 40fe94386a..1533c0be9c 100644
--- a/lib/cosEvent/test/generated_SUITE.erl
+++ b/lib/cosEvent/test/generated_SUITE.erl
@@ -26,7 +26,7 @@
-module(generated_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-define(default_timeout, ?t:minutes(3)).
diff --git a/lib/cosEventDomain/test/Makefile b/lib/cosEventDomain/test/Makefile
index 1bbd1f1693..d8f6a863d6 100644
--- a/lib/cosEventDomain/test/Makefile
+++ b/lib/cosEventDomain/test/Makefile
@@ -61,15 +61,13 @@ ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/orber/ebin -pa $(ERL_TOP)/lib/ic/ebin
ERL_COMPILE_FLAGS += \
$(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/test_server/ebin \
-pa $(ERL_TOP)/lib/cosEventDomain/ebin \
-pa $(ERL_TOP)/lib/cosEventDomain/include \
-pa $(ERL_TOP)/lib/cosNotification/ebin \
-pa $(ERL_TOP)/lib/cosNotification/include \
-I$(ERL_TOP)/lib/cosEventDomain/include \
-I$(ERL_TOP)/lib/cosNotification/include \
- -I$(ERL_TOP)/lib/cosNotification/ebin \
- -I$(ERL_TOP)/lib/test_server/include
+ -I$(ERL_TOP)/lib/cosNotification/ebin
# ----------------------------------------------------
# Targets
diff --git a/lib/cosEventDomain/test/event_domain_SUITE.erl b/lib/cosEventDomain/test/event_domain_SUITE.erl
index 75835b03a0..37a04a34aa 100644
--- a/lib/cosEventDomain/test/event_domain_SUITE.erl
+++ b/lib/cosEventDomain/test/event_domain_SUITE.erl
@@ -23,7 +23,7 @@
-module(event_domain_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("cosNotification/include/CosNotifyChannelAdmin.hrl").
-include_lib("cosNotification/include/CosNotification.hrl").
diff --git a/lib/cosEventDomain/test/generated_SUITE.erl b/lib/cosEventDomain/test/generated_SUITE.erl
index 553516bed1..afaa70db0a 100644
--- a/lib/cosEventDomain/test/generated_SUITE.erl
+++ b/lib/cosEventDomain/test/generated_SUITE.erl
@@ -26,7 +26,7 @@
-module(generated_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-define(default_timeout, ?t:minutes(3)).
diff --git a/lib/cosFileTransfer/test/Makefile b/lib/cosFileTransfer/test/Makefile
index 39512d83bd..332f90cb39 100644
--- a/lib/cosFileTransfer/test/Makefile
+++ b/lib/cosFileTransfer/test/Makefile
@@ -85,7 +85,6 @@ ERL_COMPILE_FLAGS += \
$(ERL_IDL_FLAGS) \
-pa $(ERL_TOP)/lib/orber/include \
-pa $(ERL_TOP)/lib/cosProperty/include \
- -pa $(ERL_TOP)/internal_tools/test_server/ebin \
-pa $(ERL_TOP)/lib/cosFileTransfer/ebin \
-pa $(ERL_TOP)/lib/cosFileTransfer/include \
-pa $(ERL_TOP)/lib/cosFileTransfer/test/idl_output \
@@ -94,8 +93,7 @@ ERL_COMPILE_FLAGS += \
-I$(ERL_TOP)/lib/cosFileTransfer/src \
-I$(ERL_TOP)/lib/cosFileTransfer/include \
-I$(ERL_TOP)/lib/cosFileTransfer \
- -I$(ERL_TOP)/lib/cosFileTransfer/test/$(IDLOUTDIR) \
- -I$(ERL_TOP)/lib/test_server/include
+ -I$(ERL_TOP)/lib/cosFileTransfer/test/$(IDLOUTDIR)
# ----------------------------------------------------
# Targets
diff --git a/lib/cosFileTransfer/test/fileTransfer_SUITE.erl b/lib/cosFileTransfer/test/fileTransfer_SUITE.erl
index 3fb08dbcdd..173cf71e61 100644
--- a/lib/cosFileTransfer/test/fileTransfer_SUITE.erl
+++ b/lib/cosFileTransfer/test/fileTransfer_SUITE.erl
@@ -29,7 +29,7 @@
%%--------------- INCLUDES -----------------------------------
-include_lib("cosFileTransfer/src/cosFileTransferApp.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%%--------------- DEFINES ------------------------------------
-define(default_timeout, ?t:minutes(20)).
diff --git a/lib/cosNotification/test/Makefile b/lib/cosNotification/test/Makefile
index 1db6d2bc14..5a4c5e18aa 100644
--- a/lib/cosNotification/test/Makefile
+++ b/lib/cosNotification/test/Makefile
@@ -128,7 +128,6 @@ ERL_IDL_FLAGS += \
ERL_COMPILE_FLAGS += \
$(ERL_IDL_FLAGS) \
-pa $(ERL_TOP)/lib/orber/include \
- -pa $(ERL_TOP)/internal_tools/test_server/ebin \
-pa $(ERL_TOP)/lib/cosEvent/ebin \
-pa $(ERL_TOP)/lib/cosNotification/ebin \
-pa $(ERL_TOP)/lib/cosNotification/test/idl_output \
@@ -142,8 +141,7 @@ ERL_COMPILE_FLAGS += \
-I$(ERL_TOP)/lib/cosNotification/src \
-I$(ERL_TOP)/lib/cosNotification/include \
-I$(ERL_TOP)/lib/cosNotification \
- -I$(ERL_TOP)/lib/cosNotification/test/$(IDLOUTDIR) \
- -I$(ERL_TOP)/lib/test_server/include
+ -I$(ERL_TOP)/lib/cosNotification/test/$(IDLOUTDIR)
# ----------------------------------------------------
# Targets
diff --git a/lib/cosNotification/test/eventDB_SUITE.erl b/lib/cosNotification/test/eventDB_SUITE.erl
index 0f0faed065..2d095adfae 100644
--- a/lib/cosNotification/test/eventDB_SUITE.erl
+++ b/lib/cosNotification/test/eventDB_SUITE.erl
@@ -42,7 +42,7 @@
-include("idl_output/notify_test.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%%--------------- DEFINES ------------------------------------
-define(default_timeout, ?t:minutes(20)).
diff --git a/lib/cosNotification/test/generated_SUITE.erl b/lib/cosNotification/test/generated_SUITE.erl
index fe186f24e8..8e29989e30 100644
--- a/lib/cosNotification/test/generated_SUITE.erl
+++ b/lib/cosNotification/test/generated_SUITE.erl
@@ -26,7 +26,7 @@
-module(generated_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-define(default_timeout, ?t:minutes(3)).
diff --git a/lib/cosNotification/test/grammar_SUITE.erl b/lib/cosNotification/test/grammar_SUITE.erl
index eb0741ce04..b17ddba1c4 100644
--- a/lib/cosNotification/test/grammar_SUITE.erl
+++ b/lib/cosNotification/test/grammar_SUITE.erl
@@ -43,7 +43,7 @@
-include("idl_output/notify_test.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%%--------------- DEFINES ------------------------------------
-define(default_timeout, ?t:minutes(20)).
diff --git a/lib/cosNotification/test/notification_SUITE.erl b/lib/cosNotification/test/notification_SUITE.erl
index b3884e7968..6824a2805f 100644
--- a/lib/cosNotification/test/notification_SUITE.erl
+++ b/lib/cosNotification/test/notification_SUITE.erl
@@ -41,7 +41,7 @@
-include("idl_output/notify_test.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%%--------------- DEFINES ------------------------------------
-define(default_timeout, ?t:minutes(20)).
diff --git a/lib/cosProperty/test/Makefile b/lib/cosProperty/test/Makefile
index ec928a9789..b5e063129d 100644
--- a/lib/cosProperty/test/Makefile
+++ b/lib/cosProperty/test/Makefile
@@ -82,14 +82,12 @@ ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/cosProperty/ebin \
ERL_COMPILE_FLAGS += \
$(ERL_IDL_FLAGS) \
-pa $(ERL_TOP)/lib/orber/include \
- -pa $(ERL_TOP)/internal_tools/test_server/ebin \
-pa $(ERL_TOP)/lib/cosProperty/ebin \
-pa $(ERL_TOP)/lib/cosProperty/test/idl_output \
-I$(ERL_TOP)/lib/orber/include \
-I$(ERL_TOP)/lib/cosProperty/src \
-I$(ERL_TOP)/lib/cosProperty \
- -I$(ERL_TOP)/lib/cosProperty/test/$(IDLOUTDIR) \
- -I$(ERL_TOP)/lib/test_server/include
+ -I$(ERL_TOP)/lib/cosProperty/test/$(IDLOUTDIR)
# ----------------------------------------------------
# Targets
diff --git a/lib/cosProperty/test/generated_SUITE.erl b/lib/cosProperty/test/generated_SUITE.erl
index 0422e0d018..1789650cbd 100644
--- a/lib/cosProperty/test/generated_SUITE.erl
+++ b/lib/cosProperty/test/generated_SUITE.erl
@@ -26,7 +26,7 @@
-module(generated_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-define(default_timeout, ?t:minutes(3)).
diff --git a/lib/cosProperty/test/property_SUITE.erl b/lib/cosProperty/test/property_SUITE.erl
index 94765e7479..ae508fa7b6 100644
--- a/lib/cosProperty/test/property_SUITE.erl
+++ b/lib/cosProperty/test/property_SUITE.erl
@@ -33,7 +33,7 @@
-include_lib("cosProperty/src/cosProperty.hrl").
-include_lib("cosProperty/include/CosPropertyService.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%%--------------- DEFINES ------------------------------------
-define(default_timeout, ?t:minutes(20)).
diff --git a/lib/cosTime/test/Makefile b/lib/cosTime/test/Makefile
index aabf855af5..003ea886a3 100644
--- a/lib/cosTime/test/Makefile
+++ b/lib/cosTime/test/Makefile
@@ -85,7 +85,6 @@ ERL_COMPILE_FLAGS += \
$(ERL_IDL_FLAGS) \
-pa $(ERL_TOP)/lib/orber/include \
-pa $(ERL_TOP)/lib/cosNotification/include \
- -pa $(ERL_TOP)/internal_tools/test_server/ebin \
-pa $(ERL_TOP)/lib/cosTime/ebin \
-pa $(ERL_TOP)/lib/cosTime/include \
-pa $(ERL_TOP)/lib/cosTime/test/idl_output \
@@ -94,8 +93,7 @@ ERL_COMPILE_FLAGS += \
-I$(ERL_TOP)/lib/cosTime/src \
-I$(ERL_TOP)/lib/cosTime/include \
-I$(ERL_TOP)/lib/cosTime \
- -I$(ERL_TOP)/lib/cosTime/test/$(IDLOUTDIR) \
- -I$(ERL_TOP)/lib/test_server/include
+ -I$(ERL_TOP)/lib/cosTime/test/$(IDLOUTDIR)
# ----------------------------------------------------
# Targets
diff --git a/lib/cosTime/test/generated_SUITE.erl b/lib/cosTime/test/generated_SUITE.erl
index 2e63b6f50e..03dffedc05 100644
--- a/lib/cosTime/test/generated_SUITE.erl
+++ b/lib/cosTime/test/generated_SUITE.erl
@@ -26,7 +26,7 @@
-module(generated_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-define(default_timeout, ?t:minutes(3)).
diff --git a/lib/cosTime/test/time_SUITE.erl b/lib/cosTime/test/time_SUITE.erl
index 0e805aed05..7213680b99 100644
--- a/lib/cosTime/test/time_SUITE.erl
+++ b/lib/cosTime/test/time_SUITE.erl
@@ -30,7 +30,7 @@
%%--------------- INCLUDES -----------------------------------
-include_lib("cosTime/src/cosTimeApp.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%%--------------- DEFINES ------------------------------------
-define(default_timeout, ?t:minutes(20)).
diff --git a/lib/cosTransactions/test/Makefile b/lib/cosTransactions/test/Makefile
index 3cdb05e7ef..9bcd461f04 100644
--- a/lib/cosTransactions/test/Makefile
+++ b/lib/cosTransactions/test/Makefile
@@ -93,13 +93,11 @@ ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/cosTransactions/ebin\
ERL_COMPILE_FLAGS += \
$(ERL_IDL_FLAGS) \
-pa $(ERL_TOP)/lib/orber/include \
- -pa $(ERL_TOP)/lib/test_server/ebin \
-pa $(ERL_TOP)/lib/cosTransactions/ebin \
-pa $(ERL_TOP)/lib/cosTransactions/test/idl_output \
-I$(ERL_TOP)/lib/orber/include \
-I$(ERL_TOP)/lib/cosTransactions \
- -I$(ERL_TOP)/lib/cosTransactions/test/$(IDLOUTDIR) \
- -I$(ERL_TOP)/lib/test_server/include
+ -I$(ERL_TOP)/lib/cosTransactions/test/$(IDLOUTDIR)
# ----------------------------------------------------
# Targets
diff --git a/lib/cosTransactions/test/generated_SUITE.erl b/lib/cosTransactions/test/generated_SUITE.erl
index 9d5cfb154a..c4bd86a892 100644
--- a/lib/cosTransactions/test/generated_SUITE.erl
+++ b/lib/cosTransactions/test/generated_SUITE.erl
@@ -27,7 +27,7 @@
-module(generated_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-define(default_timeout, ?t:minutes(3)).
diff --git a/lib/cosTransactions/test/transactions_SUITE.erl b/lib/cosTransactions/test/transactions_SUITE.erl
index 0f06c3d262..63ec04f74f 100644
--- a/lib/cosTransactions/test/transactions_SUITE.erl
+++ b/lib/cosTransactions/test/transactions_SUITE.erl
@@ -29,7 +29,7 @@
-include_lib("cosTransactions/include/CosTransactions.hrl").
-include("etrap_test_lib.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(default_timeout, ?t:minutes(20)).
diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile
index 24db75bf91..fbf108c410 100644
--- a/lib/crypto/Makefile
+++ b/lib/crypto/Makefile
@@ -24,11 +24,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# Macros
#
-ifneq ($(findstring ose,$(TARGET)),ose)
SUB_DIRECTORIES = src c_src doc/src
-else
-SUB_DIRECTORIES = src doc/src
-endif
static_lib: SUB_DIRECTORIES = c_src
include vsn.mk
diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in
index e66c0ca916..e7f750b60a 100644
--- a/lib/crypto/c_src/Makefile.in
+++ b/lib/crypto/c_src/Makefile.in
@@ -127,12 +127,7 @@ ALL_STATIC_CFLAGS = $(DED_STATIC_CFLAGS) $(INCLUDES)
_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
-ifneq ($(findstring ose,$(TARGET)),ose)
debug opt valgrind: $(NIF_LIB) $(CALLBACK_LIB)
-else
-# Do not build dynamic files on OSE
-debug opt valgrind:
-endif
static_lib: $(NIF_ARCHIVE)
@@ -203,14 +198,12 @@ release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/priv/obj"
$(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
$(INSTALL_DATA) $(NIF_MAKEFILE) "$(RELSYSDIR)/priv/obj"
-ifneq ($(findstring ose,$(TARGET)),ose)
$(INSTALL_PROGRAM) $(CRYPTO_OBJS) "$(RELSYSDIR)/priv/obj"
$(INSTALL_PROGRAM) $(NIF_LIB) "$(RELSYSDIR)/priv/lib"
ifeq ($(DYNAMIC_CRYPTO_LIB),yes)
$(INSTALL_PROGRAM) $(CALLBACK_OBJS) "$(RELSYSDIR)/priv/obj"
$(INSTALL_PROGRAM) $(CALLBACK_LIB) "$(RELSYSDIR)/priv/lib"
endif
-endif
release_docs_spec:
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 4966701e41..d1f620d892 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -91,6 +91,7 @@
#endif
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL
+# define HAVE_EVP_AES_CTR
# define HAVE_GCM
#endif
@@ -98,6 +99,10 @@
# define HAVE_CHACHA20_POLY1305
#endif
+#if OPENSSL_VERSION_NUMBER <= 0x009080cfL
+# define HAVE_ECB_IVEC_BUG
+#endif
+
#if defined(HAVE_EC)
#include <openssl/ec.h>
#include <openssl/ecdh.h>
@@ -193,57 +198,20 @@ static void unload(ErlNifEnv* env, void* priv_data);
/* The NIFs: */
static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha224_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha224_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha384_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha384_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha512_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha512_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM des_ede3_cfb_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hmac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hmac_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hmac_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_cfb_8_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -252,13 +220,10 @@ static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -270,10 +235,6 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T
static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -291,32 +252,7 @@ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ER
/* helpers */
static void init_algorithms_types(ErlNifEnv*);
static void init_digest_types(ErlNifEnv* env);
-static void hmac_md5(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-static void hmac_sha1(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-#ifdef HAVE_SHA224
-static void hmac_sha224(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-#endif
-#ifdef HAVE_SHA256
-static void hmac_sha256(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-#endif
-#ifdef HAVE_SHA384
-static void hmac_sha384(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-#endif
-#ifdef HAVE_SHA512
-static void hmac_sha512(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-#endif
+static void init_cipher_types(ErlNifEnv* env);
#ifdef HAVE_EC
static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg);
static int term2point(ErlNifEnv* env, ERL_NIF_TERM term,
@@ -328,60 +264,25 @@ static int library_refc = 0; /* number of users of this dynamic library */
static ErlNifFunc nif_funcs[] = {
{"info_lib", 0, info_lib},
{"algorithms", 0, algorithms},
- {"md5", 1, md5},
- {"md5_init", 0, md5_init},
- {"md5_update", 2, md5_update},
- {"md5_final", 1, md5_final},
- {"ripemd160", 1, ripemd160},
- {"ripemd160_init", 0, ripemd160_init},
- {"ripemd160_update", 2, ripemd160_update},
- {"ripemd160_final", 1, ripemd160_final},
- {"sha", 1, sha},
- {"sha_init", 0, sha_init},
- {"sha_update", 2, sha_update},
- {"sha_final", 1, sha_final},
- {"sha224_nif", 1, sha224_nif},
- {"sha224_init_nif", 0, sha224_init_nif},
- {"sha224_update_nif", 2, sha224_update_nif},
- {"sha224_final_nif", 1, sha224_final_nif},
- {"sha256_nif", 1, sha256_nif},
- {"sha256_init_nif", 0, sha256_init_nif},
- {"sha256_update_nif", 2, sha256_update_nif},
- {"sha256_final_nif", 1, sha256_final_nif},
- {"sha384_nif", 1, sha384_nif},
- {"sha384_init_nif", 0, sha384_init_nif},
- {"sha384_update_nif", 2, sha384_update_nif},
- {"sha384_final_nif", 1, sha384_final_nif},
- {"sha512_nif", 1, sha512_nif},
- {"sha512_init_nif", 0, sha512_init_nif},
- {"sha512_update_nif", 2, sha512_update_nif},
- {"sha512_final_nif", 1, sha512_final_nif},
- {"md4", 1, md4},
- {"md4_init", 0, md4_init},
- {"md4_update", 2, md4_update},
- {"md4_final", 1, md4_final},
- {"md5_mac_n", 3, md5_mac_n},
- {"sha_mac_n", 3, sha_mac_n},
- {"sha224_mac_nif", 3, sha224_mac_nif},
- {"sha256_mac_nif", 3, sha256_mac_nif},
- {"sha384_mac_nif", 3, sha384_mac_nif},
- {"sha512_mac_nif", 3, sha512_mac_nif},
- {"hmac_init", 2, hmac_init},
- {"hmac_update", 2, hmac_update},
- {"hmac_final", 1, hmac_final},
- {"hmac_final_n", 2, hmac_final},
- {"des_cbc_crypt", 4, des_cbc_crypt},
- {"des_cfb_crypt", 4, des_cfb_crypt},
- {"des_ecb_crypt", 3, des_ecb_crypt},
- {"des_ede3_cbc_crypt", 6, des_ede3_cbc_crypt},
- {"des_ede3_cfb_crypt_nif", 6, des_ede3_cfb_crypt_nif},
- {"aes_cfb_8_crypt", 4, aes_cfb_8_crypt},
- {"aes_cfb_128_crypt", 4, aes_cfb_128_crypt},
+ {"hash_nif", 2, hash_nif},
+ {"hash_init_nif", 1, hash_init_nif},
+ {"hash_update_nif", 2, hash_update_nif},
+ {"hash_final_nif", 1, hash_final_nif},
+ {"hmac_nif", 3, hmac_nif},
+ {"hmac_nif", 4, hmac_nif},
+ {"hmac_init_nif", 2, hmac_init_nif},
+ {"hmac_update_nif", 2, hmac_update_nif},
+ {"hmac_final_nif", 1, hmac_final_nif},
+ {"hmac_final_nif", 2, hmac_final_nif},
+ {"block_crypt_nif", 5, block_crypt_nif},
+ {"block_crypt_nif", 4, block_crypt_nif},
+ {"aes_ige_crypt_nif", 4, aes_ige_crypt_nif},
+
{"aes_ctr_encrypt", 3, aes_ctr_encrypt},
{"aes_ctr_decrypt", 3, aes_ctr_encrypt},
+ {"aes_ctr_stream_init", 2, aes_ctr_stream_init},
{"aes_ctr_stream_encrypt", 2, aes_ctr_stream_encrypt},
{"aes_ctr_stream_decrypt", 2, aes_ctr_stream_encrypt},
- {"aes_ecb_crypt", 3, aes_ecb_crypt},
{"rand_bytes", 1, rand_bytes_1},
{"strong_rand_bytes_nif", 1, strong_rand_bytes_nif},
{"rand_bytes", 3, rand_bytes_3},
@@ -390,13 +291,10 @@ static ErlNifFunc nif_funcs[] = {
{"mod_exp_nif", 4, mod_exp_nif},
{"dss_verify_nif", 4, dss_verify_nif},
{"rsa_verify_nif", 4, rsa_verify_nif},
- {"aes_cbc_crypt", 4, aes_cbc_crypt},
- {"aes_ige_crypt_nif", 4, aes_ige_crypt_nif},
{"do_exor", 2, do_exor},
{"rc4_encrypt", 2, rc4_encrypt},
{"rc4_set_key", 1, rc4_set_key},
{"rc4_encrypt_with_state", 2, rc4_encrypt_with_state},
- {"rc2_cbc_crypt", 4, rc2_cbc_crypt},
{"rsa_sign_nif", 3, rsa_sign_nif},
{"dss_sign_nif", 3, dss_sign_nif},
{"rsa_public_crypt", 4, rsa_public_crypt},
@@ -408,10 +306,6 @@ static ErlNifFunc nif_funcs[] = {
{"srp_value_B_nif", 5, srp_value_B_nif},
{"srp_user_secret_nif", 7, srp_user_secret_nif},
{"srp_host_secret_nif", 5, srp_host_secret_nif},
- {"bf_cfb64_crypt", 4, bf_cfb64_crypt},
- {"bf_cbc_crypt", 4, bf_cbc_crypt},
- {"bf_ecb_crypt", 3, bf_ecb_crypt},
- {"blowfish_ofb64_encrypt", 3, blowfish_ofb64_encrypt},
{"ec_key_generate", 2, ec_key_generate},
{"ecdsa_sign_nif", 4, ecdsa_sign_nif},
@@ -432,37 +326,14 @@ static ErlNifFunc nif_funcs[] = {
ERL_NIF_INIT(crypto,nif_funcs,load,NULL,upgrade,unload)
-#define MD5_CTX_LEN (sizeof(MD5_CTX))
-#define MD5_LEN 16
-#define MD5_LEN_96 12
-#define MD4_CTX_LEN (sizeof(MD4_CTX))
-#define MD4_LEN 16
+#define MD5_CTX_LEN (sizeof(MD5_CTX))
+#define MD4_CTX_LEN (sizeof(MD4_CTX))
#define RIPEMD160_CTX_LEN (sizeof(RIPEMD160_CTX))
-#define RIPEMD160_LEN 20
-#define SHA_CTX_LEN (sizeof(SHA_CTX))
-#define SHA_LEN 20
-#define SHA_LEN_96 12
-#define SHA224_LEN (224/8)
-#define SHA256_LEN (256/8)
-#define SHA384_LEN (384/8)
-#define SHA512_LEN (512/8)
-#define HMAC_INT_LEN 64
-#define HMAC_INT2_LEN 128
-
-#define HMAC_IPAD 0x36
-#define HMAC_OPAD 0x5c
static ERL_NIF_TERM atom_true;
static ERL_NIF_TERM atom_false;
static ERL_NIF_TERM atom_sha;
-static ERL_NIF_TERM atom_sha224;
-static ERL_NIF_TERM atom_sha256;
-static ERL_NIF_TERM atom_sha384;
-static ERL_NIF_TERM atom_sha512;
-static ERL_NIF_TERM atom_md5;
-static ERL_NIF_TERM atom_md4;
-static ERL_NIF_TERM atom_ripemd160;
static ERL_NIF_TERM atom_error;
static ERL_NIF_TERM atom_rsa_pkcs1_padding;
static ERL_NIF_TERM atom_rsa_pkcs1_oaep_padding;
@@ -489,6 +360,14 @@ static ERL_NIF_TERM atom_ppbasis;
static ERL_NIF_TERM atom_onbasis;
#endif
+static ERL_NIF_TERM atom_aes_cfb8;
+static ERL_NIF_TERM atom_aes_cfb128;
+#ifdef HAVE_ECB_IVEC_BUG
+static ERL_NIF_TERM atom_aes_ecb;
+static ERL_NIF_TERM atom_des_ecb;
+static ERL_NIF_TERM atom_blowfish_ecb;
+#endif
+
static ErlNifResourceType* hmac_context_rtype;
struct hmac_context
{
@@ -498,6 +377,91 @@ struct hmac_context
};
static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context*);
+struct digest_type_t {
+ const char* type_str;
+ const EVP_MD* (*md_func)(void); /* NULL if notsup */
+ ERL_NIF_TERM type_atom;
+};
+
+struct digest_type_t digest_types[] =
+{
+ {"md4", &EVP_md4},
+ {"md5", &EVP_md5},
+ {"ripemd160", &EVP_ripemd160},
+ {"sha", &EVP_sha1},
+ {"sha224",
+#ifdef HAVE_SHA224
+ &EVP_sha224
+#else
+ NULL
+#endif
+ },
+ {"sha256",
+#ifdef HAVE_SHA256
+ &EVP_sha256
+#else
+ NULL
+#endif
+ },
+ {"sha384",
+#ifdef HAVE_SHA384
+ &EVP_sha384
+#else
+ NULL
+#endif
+ },
+ {"sha512",
+#ifdef HAVE_SHA512
+ &EVP_sha512
+#else
+ NULL
+#endif
+ },
+ {NULL}
+};
+
+static struct digest_type_t* get_digest_type(ERL_NIF_TERM type);
+
+struct cipher_type_t {
+ const char* type_str;
+ const EVP_CIPHER* (*cipher_func)(void); /* NULL if notsup */
+ const size_t key_len; /* != 0 to also match on key_len */
+ ERL_NIF_TERM type_atom;
+};
+
+struct cipher_type_t cipher_types[] =
+{
+ {"rc2_cbc", &EVP_rc2_cbc},
+ {"des_cbc", &EVP_des_cbc},
+ {"des_cfb", &EVP_des_cfb8},
+ {"des_ecb", &EVP_des_ecb},
+ {"des_ede3_cbc", &EVP_des_ede3_cbc},
+ {"des_ede3_cbf",
+#ifdef HAVE_DES_ede3_cfb_encrypt
+ &EVP_des_ede3_cfb8
+#else
+ NULL
+#endif
+ },
+ {"blowfish_cbc", &EVP_bf_cbc},
+ {"blowfish_cfb64", &EVP_bf_cfb64},
+ {"blowfish_ofb64", &EVP_bf_ofb},
+ {"blowfish_ecb", &EVP_bf_ecb},
+ {"aes_cbc", &EVP_aes_128_cbc, 16},
+ {"aes_cbc", &EVP_aes_192_cbc, 24},
+ {"aes_cbc", &EVP_aes_256_cbc, 32},
+ {"aes_cbc128", &EVP_aes_128_cbc},
+ {"aes_cbc256", &EVP_aes_256_cbc},
+ {"aes_cfb8", &EVP_aes_128_cfb8},
+ {"aes_cfb128", &EVP_aes_128_cfb128},
+ {"aes_ecb", &EVP_aes_128_ecb, 16},
+ {"aes_ecb", &EVP_aes_192_ecb, 24},
+ {"aes_ecb", &EVP_aes_256_ecb, 32},
+ {NULL}
+};
+
+static struct cipher_type_t* get_cipher_type(ERL_NIF_TERM type, size_t key_len);
+
/*
#define PRINTF_ERR0(FMT) enif_fprintf(stderr, FMT "\n")
#define PRINTF_ERR1(FMT, A1) enif_fprintf(stderr, FMT "\n", A1)
@@ -507,47 +471,21 @@ static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context*);
#define PRINTF_ERR1(FMT,A1)
#define PRINTF_ERR2(FMT,A1,A2)
-#ifdef __OSE__
-
-/* For crypto on OSE we have to initialize the crypto library on each
- process that uses it. So since we do not know which scheduler is going
- to execute the nif we have to check before each nif call that we have
- initialized crypto in that process. */
-
-#include "ose.h"
-#include "openssl/osessl.h"
-
-static ErlNifTSDKey crypto_init_key;
-static int check_ose_crypto(void);
-static int init_ose_crypto(void);
-
-static int check_ose_crypto() {
- int key = (int)enif_tsd_get(crypto_init_key);
- if (!key) {
- if (!CRYPTO_OSE5_init()) {
- PRINTF_ERR0("CRYPTO: Call to CRYPTO_OSE5_init failed");
- return 0;
- }
- enif_tsd_set(crypto_init_key,1);
- }
- return 1;
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+/* Define resource types for OpenSSL context structures. */
+static ErlNifResourceType* evp_md_ctx_rtype;
+static void evp_md_ctx_dtor(ErlNifEnv* env, EVP_MD_CTX* ctx) {
+ EVP_MD_CTX_cleanup(ctx);
}
+#endif
-static int init_ose_crypto() {
- /* Crypto nif upgrade does not work on OSE so no need to
- destroy this key */
- enif_tsd_key_create("crypto_init_key", &crypto_init_key);
- return check_ose_crypto();
+#ifdef HAVE_EVP_AES_CTR
+static ErlNifResourceType* evp_cipher_ctx_rtype;
+static void evp_cipher_ctx_dtor(ErlNifEnv* env, EVP_CIPHER_CTX* ctx) {
+ EVP_CIPHER_CTX_cleanup(ctx);
}
-
-#define INIT_OSE_CRYPTO() init_ose_crypto()
-#define CHECK_OSE_CRYPTO() check_ose_crypto()
-#else
-#define INIT_OSE_CRYPTO() 1
-#define CHECK_OSE_CRYPTO()
#endif
-
static int verify_lib_version(void)
{
const unsigned long libv = SSLeay();
@@ -563,7 +501,6 @@ static int verify_lib_version(void)
return 1;
}
-
#ifdef HAVE_DYNAMIC_CRYPTO_LIB
# if defined(DEBUG)
@@ -599,7 +536,9 @@ static void error_handler(void* null, const char* errstr)
static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
{
+#ifdef OPENSSL_THREADS
ErlNifSysInfo sys_info;
+#endif
get_crypto_callbacks_t* funcp;
struct crypto_callbacks* ccb;
int nlocks = 0;
@@ -609,9 +548,6 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
ErlNifBinary lib_bin;
char lib_buf[1000];
- if (!INIT_OSE_CRYPTO())
- return 0;
-
if (!verify_lib_version())
return 0;
@@ -634,7 +570,26 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
PRINTF_ERR0("CRYPTO: Could not open resource type 'hmac_context'");
return 0;
}
-
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+ evp_md_ctx_rtype = enif_open_resource_type(env, NULL, "EVP_MD_CTX",
+ (ErlNifResourceDtor*) evp_md_ctx_dtor,
+ ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER,
+ NULL);
+ if (!evp_md_ctx_rtype) {
+ PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_MD_CTX'");
+ return 0;
+ }
+#endif
+#ifdef HAVE_EVP_AES_CTR
+ evp_cipher_ctx_rtype = enif_open_resource_type(env, NULL, "EVP_CIPHER_CTX",
+ (ErlNifResourceDtor*) evp_cipher_ctx_dtor,
+ ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER,
+ NULL);
+ if (!evp_cipher_ctx_rtype) {
+ PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_CIPHER_CTX'");
+ return 0;
+ }
+#endif
if (library_refc > 0) {
/* Repeated loading of this library (module upgrade).
* Atoms and callbacks are already set, we are done.
@@ -642,16 +597,9 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
return 1;
}
- atom_true = enif_make_atom(env,"true");
+ atom_true = enif_make_atom(env,"true");
atom_false = enif_make_atom(env,"false");
atom_sha = enif_make_atom(env,"sha");
- atom_sha224 = enif_make_atom(env,"sha224");
- atom_sha256 = enif_make_atom(env,"sha256");
- atom_sha384 = enif_make_atom(env,"sha384");
- atom_sha512 = enif_make_atom(env,"sha512");
- atom_md4 = enif_make_atom(env,"md4");
- atom_md5 = enif_make_atom(env,"md5");
- atom_ripemd160 = enif_make_atom(env,"ripemd160");
atom_error = enif_make_atom(env,"error");
atom_rsa_pkcs1_padding = enif_make_atom(env,"rsa_pkcs1_padding");
atom_rsa_pkcs1_oaep_padding = enif_make_atom(env,"rsa_pkcs1_oaep_padding");
@@ -676,8 +624,16 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
atom_ppbasis = enif_make_atom(env,"ppbasis");
atom_onbasis = enif_make_atom(env,"onbasis");
#endif
+ atom_aes_cfb8 = enif_make_atom(env, "aes_cfb8");
+ atom_aes_cfb128 = enif_make_atom(env, "aes_cfb128");
+#ifdef HAVE_ECB_IVEC_BUG
+ atom_aes_ecb = enif_make_atom(env, "aes_ecb");
+ atom_des_ecb = enif_make_atom(env, "des_ecb");
+ atom_blowfish_ecb = enif_make_atom(env, "blowfish_ecb");
+#endif
init_digest_types(env);
+ init_cipher_types(env);
init_algorithms_types(env);
#ifdef HAVE_DYNAMIC_CRYPTO_LIB
@@ -762,46 +718,67 @@ static void unload(ErlNifEnv* env, void* priv_data)
static int algo_hash_cnt;
static ERL_NIF_TERM algo_hash[8]; /* increase when extending the list */
static int algo_pubkey_cnt;
-static ERL_NIF_TERM algo_pubkey[3]; /* increase when extending the list */
+static ERL_NIF_TERM algo_pubkey[7]; /* increase when extending the list */
static int algo_cipher_cnt;
-static ERL_NIF_TERM algo_cipher[4]; /* increase when extending the list */
+static ERL_NIF_TERM algo_cipher[20]; /* increase when extending the list */
static void init_algorithms_types(ErlNifEnv* env)
{
algo_hash_cnt = 0;
- algo_hash[algo_hash_cnt++] = atom_md4;
- algo_hash[algo_hash_cnt++] = atom_md5;
algo_hash[algo_hash_cnt++] = atom_sha;
- algo_hash[algo_hash_cnt++] = atom_ripemd160;
#ifdef HAVE_SHA224
- algo_hash[algo_hash_cnt++] = atom_sha224;
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha224");
#endif
#ifdef HAVE_SHA256
- algo_hash[algo_hash_cnt++] = atom_sha256;
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha256");
#endif
#ifdef HAVE_SHA384
- algo_hash[algo_hash_cnt++] = atom_sha384;
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha384");
#endif
#ifdef HAVE_SHA512
- algo_hash[algo_hash_cnt++] = atom_sha512;
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha512");
#endif
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "md4");
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "md5");
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "ripemd160");
algo_pubkey_cnt = 0;
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "rsa");
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "dss");
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "dh");
#if defined(HAVE_EC)
#if !defined(OPENSSL_NO_EC2M)
- algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env,"ec_gf2m");
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "ec_gf2m");
#endif
- algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env,"ecdsa");
- algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env,"ecdh");
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "ecdsa");
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "ecdh");
#endif
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "srp");
algo_cipher_cnt = 0;
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des3_cbc");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des_ede3");
#ifdef HAVE_DES_ede3_cfb_encrypt
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des3_cbf");
#endif
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc128");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cfb8");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cfb128");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc256");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_ctr");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_ecb");
#ifdef HAVE_AES_IGE
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_ige256");
#endif
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"des_cbc");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"des_cfb");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_cbc");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_cfb64");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_ofb64");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_ecb");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"rc2_cbc");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"rc4");
#if defined(HAVE_GCM)
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_gcm");
#endif
@@ -816,10 +793,13 @@ static void init_algorithms_types(ErlNifEnv* env)
static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
+ int hash_cnt = algo_hash_cnt;
+ int pubkey_cnt = algo_pubkey_cnt;
+ int cipher_cnt = algo_cipher_cnt;
return enif_make_tuple3(env,
- enif_make_list_from_array(env, algo_hash, algo_hash_cnt),
- enif_make_list_from_array(env, algo_pubkey, algo_pubkey_cnt),
- enif_make_list_from_array(env, algo_cipher, algo_cipher_cnt));
+ enif_make_list_from_array(env, algo_hash, hash_cnt),
+ enif_make_list_from_array(env, algo_pubkey, pubkey_cnt),
+ enif_make_list_from_array(env, algo_cipher, cipher_cnt));
}
static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -849,601 +829,383 @@ static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
ver_term));
}
-static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
- }
- MD5((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,MD5_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-}
-static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- MD5_Init((MD5_CTX *) enif_make_new_binary(env, MD5_CTX_LEN, &ret));
- return ret;
-}
-static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
- MD5_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin)
- || ctx_bin.size != MD5_CTX_LEN
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type, Data) */
+ struct digest_type_t *digp = NULL;
+ const EVP_MD *md;
+ ErlNifBinary data;
+ ERL_NIF_TERM ret;
+ unsigned ret_size;
+
+ digp = get_digest_type(argv[0]);
+ if (!digp ||
+ !enif_inspect_iolist_as_binary(env, argv[1], &data)) {
return enif_make_badarg(env);
}
- new_ctx = (MD5_CTX*) enif_make_new_binary(env,MD5_CTX_LEN, &ret);
- memcpy(new_ctx, ctx_bin.data, MD5_CTX_LEN);
- MD5_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
- ErlNifBinary ctx_bin;
- MD5_CTX ctx_clone;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD5_CTX_LEN) {
- return enif_make_badarg(env);
+ if (!digp->md_func) {
+ return atom_notsup;
}
- memcpy(&ctx_clone, ctx_bin.data, MD5_CTX_LEN); /* writable */
- MD5_Final(enif_make_new_binary(env, MD5_LEN, &ret), &ctx_clone);
- return ret;
-}
-static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
+ md = digp->md_func();
+ ret_size = (unsigned)EVP_MD_size(md);
+ ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE);
+ if (!EVP_Digest(data.data, data.size,
+ enif_make_new_binary(env, ret_size, &ret), &ret_size,
+ md, NULL)) {
+ return atom_notsup;
}
- RIPEMD160((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,RIPEMD160_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-}
-static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- RIPEMD160_Init((RIPEMD160_CTX *) enif_make_new_binary(env, RIPEMD160_CTX_LEN, &ret));
+ ASSERT(ret_size == (unsigned)EVP_MD_size(md));
+
+ CONSUME_REDS(env, data);
return ret;
}
-static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
- RIPEMD160_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin)
- || ctx_bin.size != RIPEMD160_CTX_LEN
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+
+static ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type) */
+ struct digest_type_t *digp = NULL;
+ EVP_MD_CTX *ctx;
+ ERL_NIF_TERM ret;
+
+ digp = get_digest_type(argv[0]);
+ if (!digp) {
return enif_make_badarg(env);
}
- new_ctx = (RIPEMD160_CTX*) enif_make_new_binary(env,RIPEMD160_CTX_LEN, &ret);
- memcpy(new_ctx, ctx_bin.data, RIPEMD160_CTX_LEN);
- RIPEMD160_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env, data_bin);
- return ret;
-}
-static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
- ErlNifBinary ctx_bin;
- RIPEMD160_CTX ctx_clone;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != RIPEMD160_CTX_LEN) {
- return enif_make_badarg(env);
+ if (!digp->md_func) {
+ return atom_notsup;
}
- memcpy(&ctx_clone, ctx_bin.data, RIPEMD160_CTX_LEN); /* writable */
- RIPEMD160_Final(enif_make_new_binary(env, RIPEMD160_LEN, &ret), &ctx_clone);
- return ret;
-}
-
-static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
+ ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(EVP_MD_CTX));
+ if (!EVP_DigestInit(ctx, digp->md_func())) {
+ enif_release_resource(ctx);
+ return atom_notsup;
}
- SHA1((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,SHA_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-}
-static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- SHA1_Init((SHA_CTX *) enif_make_new_binary(env, SHA_CTX_LEN, &ret));
+ ret = enif_make_resource(env, ctx);
+ enif_release_resource(ctx);
return ret;
}
-static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context, Data) */
- SHA_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
+ EVP_MD_CTX *ctx, *new_ctx;
+ ErlNifBinary data;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != SHA_CTX_LEN
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
+
+ if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx) ||
+ !enif_inspect_iolist_as_binary(env, argv[1], &data)) {
+ return enif_make_badarg(env);
}
- new_ctx = (SHA_CTX*) enif_make_new_binary(env,SHA_CTX_LEN, &ret);
- memcpy(new_ctx, ctx_bin.data, SHA_CTX_LEN);
- SHA1_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
+
+ new_ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(EVP_MD_CTX));
+ if (!EVP_MD_CTX_copy(new_ctx, ctx) ||
+ !EVP_DigestUpdate(new_ctx, data.data, data.size)) {
+ enif_release_resource(new_ctx);
+ return atom_notsup;
+ }
+
+ ret = enif_make_resource(env, new_ctx);
+ enif_release_resource(new_ctx);
+ CONSUME_REDS(env, data);
return ret;
}
-static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context) */
- ErlNifBinary ctx_bin;
- SHA_CTX ctx_clone;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != SHA_CTX_LEN) {
- return enif_make_badarg(env);
+ EVP_MD_CTX *ctx, new_ctx;
+ ERL_NIF_TERM ret;
+ unsigned ret_size;
+
+ if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx)) {
+ return enif_make_badarg(env);
}
- memcpy(&ctx_clone, ctx_bin.data, SHA_CTX_LEN); /* writable */
- SHA1_Final(enif_make_new_binary(env, SHA_LEN, &ret), &ctx_clone);
- return ret;
-}
-static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
-#ifdef HAVE_SHA224
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
+ ret_size = (unsigned)EVP_MD_CTX_size(ctx);
+ ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE);
+
+ if (!EVP_MD_CTX_copy(&new_ctx, ctx) ||
+ !EVP_DigestFinal(&new_ctx,
+ enif_make_new_binary(env, ret_size, &ret),
+ &ret_size)) {
+ return atom_notsup;
}
- SHA224((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,SHA224_LEN, &ret));
- CONSUME_REDS(env,ibin);
+ ASSERT(ret_size == (unsigned)EVP_MD_CTX_size(ctx));
+
return ret;
-#else
- return atom_notsup;
-#endif
}
-static ERL_NIF_TERM sha224_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
-#ifdef HAVE_SHA224
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- SHA224_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret));
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
-#ifdef HAVE_SHA224
- SHA256_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+
+#else /* if OPENSSL_VERSION_NUMBER < 1.0 */
+
+static ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type) */
+ typedef int (*init_fun)(unsigned char*);
+ struct digest_type_t *digp = NULL;
+ ERL_NIF_TERM ctx;
+ size_t ctx_size = 0;
+ init_fun ctx_init = 0;
+
+ digp = get_digest_type(argv[0]);
+ if (!digp) {
return enif_make_badarg(env);
}
- new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret);
- memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX));
- SHA224_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-static ERL_NIF_TERM sha224_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
-#ifdef HAVE_SHA224
- ErlNifBinary ctx_bin;
- SHA256_CTX ctx_clone;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) {
- return enif_make_badarg(env);
+ if (!digp->md_func) {
+ return atom_notsup;
}
- memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA256_CTX)); /* writable */
- SHA224_Final(enif_make_new_binary(env, SHA224_LEN, &ret), &ctx_clone);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
-#ifdef HAVE_SHA256
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
- }
- SHA256((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,SHA256_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-#else
- return atom_notsup;
+ switch (EVP_MD_type(digp->md_func()))
+ {
+ case NID_md4:
+ ctx_size = MD4_CTX_LEN;
+ ctx_init = (init_fun)(&MD4_Init);
+ break;
+ case NID_md5:
+ ctx_size = MD5_CTX_LEN;
+ ctx_init = (init_fun)(&MD5_Init);
+ break;
+ case NID_ripemd160:
+ ctx_size = RIPEMD160_CTX_LEN;
+ ctx_init = (init_fun)(&RIPEMD160_Init);
+ break;
+ case NID_sha1:
+ ctx_size = sizeof(SHA_CTX);
+ ctx_init = (init_fun)(&SHA1_Init);
+ break;
+#ifdef HAVE_SHA224
+ case NID_sha224:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_init = (init_fun)(&SHA224_Init);
+ break;
#endif
-}
-static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
#ifdef HAVE_SHA256
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- SHA256_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret));
- return ret;
-#else
- return atom_notsup;
+ case NID_sha256:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_init = (init_fun)(&SHA256_Init);
+ break;
#endif
-}
-static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
-#ifdef HAVE_SHA256
- SHA256_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
+#ifdef HAVE_SHA384
+ case NID_sha384:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_init = (init_fun)(&SHA384_Init);
+ break;
+#endif
+#ifdef HAVE_SHA512
+ case NID_sha512:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_init = (init_fun)(&SHA512_Init);
+ break;
+#endif
+ default:
+ return atom_notsup;
+ }
+ ASSERT(ctx_size);
+ ASSERT(ctx_init);
+
+ ctx_init(enif_make_new_binary(env, ctx_size, &ctx));
+ return enif_make_tuple2(env, argv[0], ctx);
+}
+static ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* ({Type, Context}, Data) */
+ typedef int (*update_fun)(unsigned char*, const unsigned char*, size_t);
+ ERL_NIF_TERM new_ctx;
+ ErlNifBinary ctx, data;
+ const ERL_NIF_TERM *tuple;
+ int arity;
+ struct digest_type_t *digp = NULL;
+ unsigned char *ctx_buff;
+ size_t ctx_size = 0;
+ update_fun ctx_update = 0;
+
+ if (!enif_get_tuple(env, argv[0], &arity, &tuple) ||
+ arity != 2 ||
+ !(digp = get_digest_type(tuple[0])) ||
+ !enif_inspect_binary(env, tuple[1], &ctx) ||
+ !enif_inspect_iolist_as_binary(env, argv[1], &data)) {
+ return enif_make_badarg(env);
}
- new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret);
- memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX));
- SHA256_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-#else
- return atom_notsup;
+ if (!digp->md_func) {
+ return atom_notsup;
+ }
+
+ switch (EVP_MD_type(digp->md_func()))
+ {
+ case NID_md4:
+ ctx_size = MD4_CTX_LEN;
+ ctx_update = (update_fun)(&MD4_Update);
+ break;
+ case NID_md5:
+ ctx_size = MD5_CTX_LEN;
+ ctx_update = (update_fun)(&MD5_Update);
+ break;
+ case NID_ripemd160:
+ ctx_size = RIPEMD160_CTX_LEN;
+ ctx_update = (update_fun)(&RIPEMD160_Update);
+ break;
+ case NID_sha1:
+ ctx_size = sizeof(SHA_CTX);
+ ctx_update = (update_fun)(&SHA1_Update);
+ break;
+#ifdef HAVE_SHA224
+ case NID_sha224:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_update = (update_fun)(&SHA224_Update);
+ break;
#endif
-}
-static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
#ifdef HAVE_SHA256
- ErlNifBinary ctx_bin;
- SHA256_CTX ctx_clone;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) {
- return enif_make_badarg(env);
- }
- memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA256_CTX)); /* writable */
- SHA256_Final(enif_make_new_binary(env, SHA256_LEN, &ret), &ctx_clone);
- return ret;
-#else
- return atom_notsup;
+ case NID_sha256:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_update = (update_fun)(&SHA256_Update);
+ break;
#endif
-}
-
-static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
#ifdef HAVE_SHA384
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
- }
- SHA384((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,SHA384_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-#else
- return atom_notsup;
+ case NID_sha384:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_update = (update_fun)(&SHA384_Update);
+ break;
#endif
-}
-static ERL_NIF_TERM sha384_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
-#ifdef HAVE_SHA384
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- SHA384_Init((SHA512_CTX *) enif_make_new_binary(env, sizeof(SHA512_CTX), &ret));
- return ret;
-#else
- return atom_notsup;
+#ifdef HAVE_SHA512
+ case NID_sha512:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_update = (update_fun)(&SHA512_Update);
+ break;
#endif
-}
-static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
-#ifdef HAVE_SHA384
- SHA512_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
+ default:
+ return atom_notsup;
}
- new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret);
- memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX));
- SHA384_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-static ERL_NIF_TERM sha384_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
-#ifdef HAVE_SHA384
- ErlNifBinary ctx_bin;
- SHA512_CTX ctx_clone;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) {
- return enif_make_badarg(env);
+ ASSERT(ctx_size);
+ ASSERT(ctx_update);
+
+ if (ctx.size != ctx_size) {
+ return enif_make_badarg(env);
}
- memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA512_CTX)); /* writable */
- SHA384_Final(enif_make_new_binary(env, SHA384_LEN, &ret), &ctx_clone);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
-#ifdef HAVE_SHA512
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
+ ctx_buff = enif_make_new_binary(env, ctx_size, &new_ctx);
+ memcpy(ctx_buff, ctx.data, ctx_size);
+ ctx_update(ctx_buff, data.data, data.size);
+
+ CONSUME_REDS(env, data);
+ return enif_make_tuple2(env, tuple[0], new_ctx);
+}
+static ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* ({Type, Context}) */
+ typedef int (*final_fun)(unsigned char*, void*);
+ ERL_NIF_TERM ret;
+ ErlNifBinary ctx;
+ const ERL_NIF_TERM *tuple;
+ int arity;
+ struct digest_type_t *digp = NULL;
+ const EVP_MD *md;
+ void *new_ctx;
+ size_t ctx_size = 0;
+ final_fun ctx_final = 0;
+
+ if (!enif_get_tuple(env, argv[0], &arity, &tuple) ||
+ arity != 2 ||
+ !(digp = get_digest_type(tuple[0])) ||
+ !enif_inspect_binary(env, tuple[1], &ctx)) {
+ return enif_make_badarg(env);
}
- SHA512((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,SHA512_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-#else
- return atom_notsup;
+ if (!digp->md_func) {
+ return atom_notsup;
+ }
+
+ md = digp->md_func();
+
+ switch (EVP_MD_type(md))
+ {
+ case NID_md4:
+ ctx_size = MD4_CTX_LEN;
+ ctx_final = (final_fun)(&MD4_Final);
+ break;
+ case NID_md5:
+ ctx_size = MD5_CTX_LEN;
+ ctx_final = (final_fun)(&MD5_Final);
+ break;
+ case NID_ripemd160:
+ ctx_size = RIPEMD160_CTX_LEN;
+ ctx_final = (final_fun)(&RIPEMD160_Final);
+ break;
+ case NID_sha1:
+ ctx_size = sizeof(SHA_CTX);
+ ctx_final = (final_fun)(&SHA1_Final);
+ break;
+#ifdef HAVE_SHA224
+ case NID_sha224:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_final = (final_fun)(&SHA224_Final);
+ break;
#endif
-}
-static ERL_NIF_TERM sha512_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
-#ifdef HAVE_SHA512
- ERL_NIF_TERM ret;
- SHA512_Init((SHA512_CTX *) enif_make_new_binary(env, sizeof(SHA512_CTX), &ret));
- return ret;
-#else
- return atom_notsup;
+#ifdef HAVE_SHA256
+ case NID_sha256:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_final = (final_fun)(&SHA256_Final);
+ break;
#endif
-}
-static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
-#ifdef HAVE_SHA512
- SHA512_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
- }
- new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret);
- memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX));
- SHA512_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-#else
- return atom_notsup;
+#ifdef HAVE_SHA384
+ case NID_sha384:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_final = (final_fun)(&SHA384_Final);
+ break;
#endif
-}
-static ERL_NIF_TERM sha512_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
#ifdef HAVE_SHA512
- ErlNifBinary ctx_bin;
- SHA512_CTX ctx_clone;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) {
- return enif_make_badarg(env);
- }
- memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA512_CTX)); /* writable */
- SHA512_Final(enif_make_new_binary(env, SHA512_LEN, &ret), &ctx_clone);
- return ret;
-#else
- return atom_notsup;
+ case NID_sha512:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_final = (final_fun)(&SHA512_Final);
+ break;
#endif
-}
-
-
-static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
+ default:
+ return atom_notsup;
}
- MD4((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,MD4_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-}
-static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- MD4_Init((MD4_CTX *) enif_make_new_binary(env, MD4_CTX_LEN, &ret));
- return ret;
-}
-static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
- MD4_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD4_CTX_LEN
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
- }
- new_ctx = (MD4_CTX*) enif_make_new_binary(env,MD4_CTX_LEN, &ret);
- memcpy(new_ctx, ctx_bin.data, MD4_CTX_LEN);
- MD4_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
- ErlNifBinary ctx_bin;
- MD4_CTX ctx_clone;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD4_CTX_LEN) {
- return enif_make_badarg(env);
- }
- memcpy(&ctx_clone, ctx_bin.data, MD4_CTX_LEN); /* writable */
- MD4_Final(enif_make_new_binary(env, MD4_LEN, &ret), &ctx_clone);
- return ret;
-}
+ ASSERT(ctx_size);
+ ASSERT(ctx_final);
-static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > MD5_LEN) {
- return enif_make_badarg(env);
+ if (ctx.size != ctx_size) {
+ return enif_make_badarg(env);
}
- hmac_md5(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret), hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
- return ret;
-}
-static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA_LEN) {
- return enif_make_badarg(env);
- }
- hmac_sha1(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret),
- hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
- return ret;
-}
+ new_ctx = enif_alloc(ctx_size);
+ memcpy(new_ctx, ctx.data, ctx_size);
+ ctx_final(enif_make_new_binary(env, (size_t)EVP_MD_size(md), &ret),
+ new_ctx);
+ enif_free(new_ctx);
-static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
-#ifdef HAVE_SHA224
- unsigned char hmacbuf[SHA224_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA224_DIGEST_LENGTH) {
- return enif_make_badarg(env);
- }
- hmac_sha224(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret),
- hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
return ret;
-#else
- return atom_notsup;
-#endif
}
+#endif /* OPENSSL_VERSION_NUMBER < 1.0 */
-static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
-#ifdef HAVE_SHA256
- unsigned char hmacbuf[SHA256_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA256_DIGEST_LENGTH) {
- return enif_make_badarg(env);
- }
- hmac_sha256(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret),
- hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
+static ERL_NIF_TERM hmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type, Key, Data) or (Type, Key, Data, MacSize) */
+ struct digest_type_t *digp = NULL;
+ ErlNifBinary key, data;
+ unsigned char buff[EVP_MAX_MD_SIZE];
+ unsigned size = 0, req_size = 0;
+ ERL_NIF_TERM ret;
-static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
-#ifdef HAVE_SHA384
- unsigned char hmacbuf[SHA384_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA384_DIGEST_LENGTH) {
- return enif_make_badarg(env);
+ digp = get_digest_type(argv[0]);
+ if (!digp ||
+ !enif_inspect_iolist_as_binary(env, argv[1], &key) ||
+ !enif_inspect_iolist_as_binary(env, argv[2], &data) ||
+ (argc == 4 && !enif_get_uint(env, argv[3], &req_size))) {
+ return enif_make_badarg(env);
}
- hmac_sha384(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret),
- hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
+ if (!digp->md_func ||
+ !HMAC(digp->md_func(),
+ key.data, key.size,
+ data.data, data.size,
+ buff, &size)) {
+ return atom_notsup;
+ }
+ ASSERT(0 < size && size <= EVP_MAX_MD_SIZE);
+ CONSUME_REDS(env, data);
-static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
-#ifdef HAVE_SHA512
- unsigned char hmacbuf[SHA512_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA512_DIGEST_LENGTH) {
- return enif_make_badarg(env);
+ if (argc == 4) {
+ if (req_size <= size) {
+ size = req_size;
+ }
+ else {
+ return enif_make_badarg(env);
+ }
}
- hmac_sha512(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret),
- hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
+ memcpy(enif_make_new_binary(env, size, &ret), buff, size);
return ret;
-#else
- return atom_notsup;
-#endif
}
static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context *obj)
@@ -1455,55 +1217,46 @@ static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context *obj)
enif_mutex_destroy(obj->mtx);
}
-static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM hmac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type, Key) */
- ErlNifBinary key;
- struct hmac_context* obj;
- const EVP_MD *md;
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
+ struct digest_type_t *digp = NULL;
+ ErlNifBinary key;
+ ERL_NIF_TERM ret;
+ struct hmac_context *obj;
- if (argv[0] == atom_sha) md = EVP_sha1();
-#ifdef HAVE_SHA224
- else if (argv[0] == atom_sha224) md = EVP_sha224();
-#endif
-#ifdef HAVE_SHA256
- else if (argv[0] == atom_sha256) md = EVP_sha256();
-#endif
-#ifdef HAVE_SHA384
- else if (argv[0] == atom_sha384) md = EVP_sha384();
-#endif
-#ifdef HAVE_SHA512
- else if (argv[0] == atom_sha512) md = EVP_sha512();
-#endif
- else if (argv[0] == atom_md5) md = EVP_md5();
- else if (argv[0] == atom_ripemd160) md = EVP_ripemd160();
- else goto badarg;
-
- if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) {
- badarg:
- return enif_make_badarg(env);
+ digp = get_digest_type(argv[0]);
+ if (!digp ||
+ !enif_inspect_iolist_as_binary(env, argv[1], &key)) {
+ return enif_make_badarg(env);
+ }
+ if (!digp->md_func) {
+ return atom_notsup;
}
obj = enif_alloc_resource(hmac_context_rtype, sizeof(struct hmac_context));
obj->mtx = enif_mutex_create("crypto.hmac");
obj->alive = 1;
- HMAC_CTX_init(&obj->ctx);
- HMAC_Init(&obj->ctx, key.data, key.size, md);
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+ // Check the return value of HMAC_Init: it may fail in FIPS mode
+ // for disabled algorithms
+ if (!HMAC_Init(&obj->ctx, key.data, key.size, digp->md_func())) {
+ enif_release_resource(obj);
+ return atom_notsup;
+ }
+#else
+ HMAC_Init(&obj->ctx, key.data, key.size, digp->md_func());
+#endif
ret = enif_make_resource(env, obj);
enif_release_resource(obj);
return ret;
}
-static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM hmac_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context, Data) */
ErlNifBinary data;
struct hmac_context* obj;
- CHECK_OSE_CRYPTO();
-
if (!enif_get_resource(env, argv[0], hmac_context_rtype, (void**)&obj)
|| !enif_inspect_iolist_as_binary(env, argv[1], &data)) {
return enif_make_badarg(env);
@@ -1520,7 +1273,7 @@ static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
return argv[0];
}
-static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM hmac_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context) or (Context, HashLen) */
ERL_NIF_TERM ret;
struct hmac_context* obj;
@@ -1529,8 +1282,6 @@ static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
unsigned int req_len = 0;
unsigned int mac_len;
- CHECK_OSE_CRYPTO();
-
if (!enif_get_resource(env,argv[0],hmac_context_rtype, (void**)&obj)
|| (argc == 2 && !enif_get_uint(env, argv[1], &req_len))) {
return enif_make_badarg(env);
@@ -1557,206 +1308,197 @@ static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
return ret;
}
-static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Ivec, Text, IsEncrypt) */
- ErlNifBinary key, ivec, text;
- DES_key_schedule schedule;
- DES_cblock ivec_clone; /* writable copy */
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
+static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type, Key, Ivec, Text, IsEncrypt) or (Type, Key, Text, IsEncrypt) */
+ struct cipher_type_t *cipherp = NULL;
+ const EVP_CIPHER *cipher;
+ ErlNifBinary key, ivec, text;
+ EVP_CIPHER_CTX ctx;
+ ERL_NIF_TERM ret;
+ unsigned char *out;
+ int ivec_size, out_size = 0;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8
- || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &text)
- || text.size % 8 != 0) {
- return enif_make_badarg(env);
+ if (!enif_inspect_iolist_as_binary(env, argv[1], &key)
+ || !(cipherp = get_cipher_type(argv[0], key.size))
+ || !enif_inspect_iolist_as_binary(env, argv[argc - 2], &text)) {
+ return enif_make_badarg(env);
}
- memcpy(&ivec_clone, ivec.data, 8);
- DES_set_key((const_DES_cblock*)key.data, &schedule);
- DES_ncbc_encrypt(text.data, enif_make_new_binary(env, text.size, &ret),
- text.size, &schedule, &ivec_clone, (argv[3] == atom_true));
- CONSUME_REDS(env,text);
- return ret;
-}
-
-static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Ivec, Text, IsEncrypt) */
- ErlNifBinary key, ivec, text;
- DES_key_schedule schedule;
- DES_cblock ivec_clone; /* writable copy */
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8
- || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
- return enif_make_badarg(env);
+ if (!cipherp->cipher_func) {
+ return enif_raise_exception(env, atom_notsup);
}
- memcpy(&ivec_clone, ivec.data, 8);
- DES_set_key((const_DES_cblock*)key.data, &schedule);
- DES_cfb_encrypt(text.data, enif_make_new_binary(env, text.size, &ret),
- 8, text.size, &schedule, &ivec_clone, (argv[3] == atom_true));
- CONSUME_REDS(env,text);
- return ret;
-}
-static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Text/Cipher, IsEncrypt) */
- ErlNifBinary key, text;
- DES_key_schedule schedule;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8 ||
- !enif_inspect_iolist_as_binary(env, argv[1], &text) || text.size != 8) {
- return enif_make_badarg(env);
+ if ((argv[0] == atom_aes_cfb8 || argv[0] == atom_aes_cfb128)
+ && (key.size == 24 || key.size == 32)) {
+ /* Why do EVP_CIPHER_CTX_set_key_length() fail on these key sizes?
+ * Fall back on low level API
+ */
+ return aes_cfb_8_crypt(env, argc-1, argv+1);
}
- DES_set_key((const_DES_cblock*)key.data, &schedule);
- DES_ecb_encrypt((const_DES_cblock*)text.data,
- (DES_cblock*)enif_make_new_binary(env, 8, &ret),
- &schedule, (argv[2] == atom_true));
- CONSUME_REDS(env,text);
- return ret;
-}
-static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key1, Key2, Key3, IVec, Text/Cipher, IsEncrypt) */
- ErlNifBinary key1, key2, key3, ivec, text;
- DES_key_schedule schedule1, schedule2, schedule3;
- DES_cblock ivec_clone; /* writable copy */
- ERL_NIF_TERM ret;
+ cipher = cipherp->cipher_func();
+ ivec_size = EVP_CIPHER_iv_length(cipher);
- CHECK_OSE_CRYPTO();
+#ifdef HAVE_ECB_IVEC_BUG
+ if (argv[0] == atom_aes_ecb || argv[0] == atom_blowfish_ecb ||
+ argv[0] == atom_des_ecb)
+ ivec_size = 0; /* 0.9.8l returns faulty ivec_size */
+#endif
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &key3) || key3.size != 8
- || !enif_inspect_binary(env, argv[3], &ivec) || ivec.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[4], &text)
- || text.size % 8 != 0) {
- return enif_make_badarg(env);
+ if (text.size % EVP_CIPHER_block_size(cipher) != 0 ||
+ (ivec_size == 0 ? argc != 4
+ : (argc != 5 ||
+ !enif_inspect_iolist_as_binary(env, argv[2], &ivec) ||
+ ivec.size != ivec_size))) {
+ return enif_make_badarg(env);
}
- memcpy(&ivec_clone, ivec.data, 8);
- DES_set_key((const_DES_cblock*)key1.data, &schedule1);
- DES_set_key((const_DES_cblock*)key2.data, &schedule2);
- DES_set_key((const_DES_cblock*)key3.data, &schedule3);
- DES_ede3_cbc_encrypt(text.data, enif_make_new_binary(env,text.size,&ret),
- text.size, &schedule1, &schedule2, &schedule3,
- &ivec_clone, (argv[5] == atom_true));
- CONSUME_REDS(env,text);
- return ret;
-}
+ out = enif_make_new_binary(env, text.size, &ret);
-static ERL_NIF_TERM des_ede3_cfb_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key1, Key2, Key3, IVec, Text/Cipher, IsEncrypt) */
-#ifdef HAVE_DES_ede3_cfb_encrypt
- ErlNifBinary key1, key2, key3, ivec, text;
- DES_key_schedule schedule1, schedule2, schedule3;
- DES_cblock ivec_clone; /* writable copy */
- ERL_NIF_TERM ret;
+ EVP_CIPHER_CTX_init(&ctx);
+ if (!EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, NULL,
+ (argv[argc - 1] == atom_true)) ||
+ !EVP_CIPHER_CTX_set_key_length(&ctx, key.size) ||
+ !(EVP_CIPHER_type(cipher) != NID_rc2_cbc ||
+ EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_SET_RC2_KEY_BITS, key.size * 8, NULL)) ||
+ !EVP_CipherInit_ex(&ctx, NULL, NULL,
+ key.data, ivec_size ? ivec.data : NULL, -1) ||
+ !EVP_CIPHER_CTX_set_padding(&ctx, 0)) {
- CHECK_OSE_CRYPTO();
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return enif_raise_exception(env, atom_notsup);
+ }
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &key3) || key3.size != 8
- || !enif_inspect_binary(env, argv[3], &ivec) || ivec.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[4], &text)) {
- return enif_make_badarg(env);
+ if (text.size > 0 && /* OpenSSL 0.9.8h asserts text.size > 0 */
+ (!EVP_CipherUpdate(&ctx, out, &out_size, text.data, text.size)
+ || (ASSERT(out_size == text.size), 0)
+ || !EVP_CipherFinal_ex(&ctx, out + out_size, &out_size))) {
+
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return enif_raise_exception(env, atom_notsup);
}
+ ASSERT(out_size == 0);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ CONSUME_REDS(env, text);
- memcpy(&ivec_clone, ivec.data, 8);
- DES_set_key((const_DES_cblock*)key1.data, &schedule1);
- DES_set_key((const_DES_cblock*)key2.data, &schedule2);
- DES_set_key((const_DES_cblock*)key3.data, &schedule3);
- DES_ede3_cfb_encrypt(text.data, enif_make_new_binary(env,text.size,&ret),
- 8, text.size, &schedule1, &schedule2, &schedule3,
- &ivec_clone, (argv[5] == atom_true));
- CONSUME_REDS(env,text);
return ret;
-#else
- return atom_notsup;
-#endif
}
static ERL_NIF_TERM aes_cfb_8_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, IVec, Data, IsEncrypt) */
- ErlNifBinary key, ivec, text;
- AES_KEY aes_key;
- unsigned char ivec_clone[16]; /* writable copy */
- int new_ivlen = 0;
- ERL_NIF_TERM ret;
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !(key.size == 16 || key.size == 24 || key.size == 32)
- || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16
- || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
- return enif_make_badarg(env);
- }
-
- memcpy(ivec_clone, ivec.data, 16);
- AES_set_encrypt_key(key.data, key.size * 8, &aes_key);
- AES_cfb8_encrypt((unsigned char *) text.data,
- enif_make_new_binary(env, text.size, &ret),
- text.size, &aes_key, ivec_clone, &new_ivlen,
- (argv[3] == atom_true));
- CONSUME_REDS(env,text);
- return ret;
+{/* (Key, IVec, Data, IsEncrypt) */
+ ErlNifBinary key, ivec, text;
+ AES_KEY aes_key;
+ unsigned char ivec_clone[16]; /* writable copy */
+ int new_ivlen = 0;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+ || !(key.size == 16 || key.size == 24 || key.size == 32)
+ || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16
+ || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
+ return enif_make_badarg(env);
+ }
+
+ memcpy(ivec_clone, ivec.data, 16);
+ AES_set_encrypt_key(key.data, key.size * 8, &aes_key);
+ AES_cfb8_encrypt((unsigned char *) text.data,
+ enif_make_new_binary(env, text.size, &ret),
+ text.size, &aes_key, ivec_clone, &new_ivlen,
+ (argv[3] == atom_true));
+ CONSUME_REDS(env,text);
+ return ret;
}
-static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, IVec, Data, IsEncrypt) */
- ErlNifBinary key, ivec, text;
+static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, IVec, Data, IsEncrypt) */
+#ifdef HAVE_AES_IGE
+ ErlNifBinary key_bin, ivec_bin, data_bin;
AES_KEY aes_key;
- unsigned char ivec_clone[16]; /* writable copy */
- int new_ivlen = 0;
+ unsigned char ivec[32];
+ int i;
+ unsigned char* ret_ptr;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
+ || (key_bin.size != 16 && key_bin.size != 32)
+ || !enif_inspect_binary(env, argv[1], &ivec_bin)
+ || ivec_bin.size != 32
+ || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
+ || data_bin.size % 16 != 0) {
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !(key.size == 16 || key.size == 24 || key.size == 32)
- || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16
- || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
- return enif_make_badarg(env);
+ return enif_make_badarg(env);
}
- memcpy(ivec_clone, ivec.data, 16);
- AES_set_encrypt_key(key.data, key.size * 8, &aes_key);
- AES_cfb128_encrypt((unsigned char *) text.data,
- enif_make_new_binary(env, text.size, &ret),
- text.size, &aes_key, ivec_clone, &new_ivlen,
- (argv[3] == atom_true));
- CONSUME_REDS(env,text);
+ if (argv[3] == atom_true) {
+ i = AES_ENCRYPT;
+ AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key);
+ }
+ else {
+ i = AES_DECRYPT;
+ AES_set_decrypt_key(key_bin.data, key_bin.size*8, &aes_key);
+ }
+
+ ret_ptr = enif_make_new_binary(env, data_bin.size, &ret);
+ memcpy(ivec, ivec_bin.data, 32); /* writable copy */
+ AES_ige_encrypt(data_bin.data, ret_ptr, data_bin.size, &aes_key, ivec, i);
+ CONSUME_REDS(env,data_bin);
return ret;
+#else
+ return atom_notsup;
+#endif
}
/* Common for both encrypt and decrypt
*/
static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, IVec, Data) */
- ErlNifBinary key, ivec, text;
- AES_KEY aes_key;
- unsigned char ivec_clone[16]; /* writable copy */
- unsigned char ecount_buf[AES_BLOCK_SIZE];
- unsigned int num = 0;
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
+ ErlNifBinary key, ivec, text;
+#ifdef HAVE_EVP_AES_CTR
+ const EVP_CIPHER *cipher;
+ EVP_CIPHER_CTX ctx;
+ unsigned char *out;
+ int outl = 0;
+#else
+ AES_KEY aes_key;
+ unsigned char ivec_clone[16]; /* writable copy */
+ unsigned char ecount_buf[AES_BLOCK_SIZE];
+ unsigned int num = 0;
+#endif
+ ERL_NIF_TERM ret;
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+#ifndef HAVE_EVP_AES_CTR
|| AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
+#endif
|| !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16
|| !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
return enif_make_badarg(env);
}
+#ifdef HAVE_EVP_AES_CTR
+ switch (key.size)
+ {
+ case 16: cipher = EVP_aes_128_ctr(); break;
+ case 24: cipher = EVP_aes_192_ctr(); break;
+ case 32: cipher = EVP_aes_256_ctr(); break;
+ default: return enif_make_badarg(env);
+ }
+
+ out = enif_make_new_binary(env,text.size,&ret);
+ EVP_CIPHER_CTX_init(&ctx);
+ EVP_CipherInit_ex(&ctx, cipher, NULL,
+ key.data, ivec.data, (argv[3] == atom_true));
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+ EVP_CipherUpdate(&ctx, out, &outl, text.data, text.size);
+ ASSERT(outl == text.size);
+ EVP_CipherFinal_ex(&ctx, out + outl, &outl);
+ ASSERT(outl == 0);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+#else
memcpy(ivec_clone, ivec.data, 16);
memset(ecount_buf, 0, sizeof(ecount_buf));
AES_ctr128_encrypt((unsigned char *) text.data,
enif_make_new_binary(env, text.size, &ret),
text.size, &aes_key, ivec_clone, ecount_buf, &num);
+#endif
CONSUME_REDS(env,text);
/* To do an incremental {en|de}cryption, the state to to keep between calls
@@ -1766,6 +1508,81 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
/* Initializes state for ctr streaming (de)encryption
*/
+#ifdef HAVE_EVP_AES_CTR
+static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, IVec) */
+ ErlNifBinary key_bin, ivec_bin;
+ EVP_CIPHER_CTX *ctx;
+ const EVP_CIPHER *cipher;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
+ || !enif_inspect_binary(env, argv[1], &ivec_bin)
+ || ivec_bin.size != 16) {
+ return enif_make_badarg(env);
+ }
+
+ switch (key_bin.size)
+ {
+ case 16: cipher = EVP_aes_128_ctr(); break;
+ case 24: cipher = EVP_aes_192_ctr(); break;
+ case 32: cipher = EVP_aes_256_ctr(); break;
+ default: return enif_make_badarg(env);
+ }
+
+ ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(EVP_CIPHER_CTX));
+ EVP_CIPHER_CTX_init(ctx);
+ EVP_CipherInit_ex(ctx, cipher, NULL,
+ key_bin.data, ivec_bin.data, 1);
+ EVP_CIPHER_CTX_set_padding(ctx, 0);
+ ret = enif_make_resource(env, ctx);
+ enif_release_resource(ctx);
+ return ret;
+}
+static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context, Data) */
+ EVP_CIPHER_CTX *ctx, *new_ctx;
+ ErlNifBinary data_bin;
+ ERL_NIF_TERM ret, cipher_term;
+ unsigned char *out;
+ int outl = 0;
+
+ if (!enif_get_resource(env, argv[0], evp_cipher_ctx_rtype, (void**)&ctx)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
+ }
+ new_ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(EVP_CIPHER_CTX));
+ EVP_CIPHER_CTX_init(new_ctx);
+ EVP_CIPHER_CTX_copy(new_ctx, ctx);
+ out = enif_make_new_binary(env, data_bin.size, &cipher_term);
+ EVP_CipherUpdate(new_ctx, out, &outl, data_bin.data, data_bin.size);
+ ASSERT(outl == data_bin.size);
+
+ ret = enif_make_tuple2(env, enif_make_resource(env, new_ctx), cipher_term);
+ enif_release_resource(new_ctx);
+ CONSUME_REDS(env,data_bin);
+ return ret;
+}
+
+#else /* if not HAVE_EVP_AES_CTR */
+
+static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, IVec) */
+ ErlNifBinary key_bin, ivec_bin;
+ ERL_NIF_TERM ecount_bin;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
+ || !enif_inspect_binary(env, argv[1], &ivec_bin)
+ || !(key_bin.size == 16 || key_bin.size == 24 || key_bin.size ==32)
+ || ivec_bin.size != 16) {
+ return enif_make_badarg(env);
+ }
+
+ memset(enif_make_new_binary(env, AES_BLOCK_SIZE, &ecount_bin),
+ 0, AES_BLOCK_SIZE);
+ return enif_make_tuple4(env, argv[0], argv[1], ecount_bin, enif_make_int(env, 0));
+}
+
static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* ({Key, IVec, ECount, Num}, Data) */
ErlNifBinary key_bin, ivec_bin, text_bin, ecount_bin;
@@ -1777,8 +1594,6 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N
unsigned char * ivec2_buf;
unsigned char * ecount2_buf;
- CHECK_OSE_CRYPTO();
-
if (!enif_get_tuple(env, argv[0], &state_arity, &state_term)
|| state_arity != 4
|| !enif_inspect_iolist_as_binary(env, state_term[0], &key_bin)
@@ -1806,70 +1621,86 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N
CONSUME_REDS(env,text_bin);
return ret;
}
+#endif /* !HAVE_EVP_AES_CTR */
static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key,Iv,AAD,In) */
#if defined(HAVE_GCM)
- GCM128_CONTEXT *ctx = NULL;
+ EVP_CIPHER_CTX ctx;
+ const EVP_CIPHER *cipher = NULL;
ErlNifBinary key, iv, aad, in;
- AES_KEY aes_key;
- unsigned char *outp;
+ unsigned char *outp, *tagp;
ERL_NIF_TERM out, out_tag;
-
- CHECK_OSE_CRYPTO();
+ int len;
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
+ || (key.size != 16 && key.size != 24 && key.size != 32)
|| !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0
|| !enif_inspect_iolist_as_binary(env, argv[2], &aad)
|| !enif_inspect_iolist_as_binary(env, argv[3], &in)) {
return enif_make_badarg(env);
}
- if (!(ctx = CRYPTO_gcm128_new(&aes_key, (block128_f)AES_encrypt)))
- return atom_error;
+ if (key.size == 16)
+ cipher = EVP_aes_128_gcm();
+ else if (key.size == 24)
+ cipher = EVP_aes_192_gcm();
+ else if (key.size == 32)
+ cipher = EVP_aes_256_gcm();
- CRYPTO_gcm128_setiv(ctx, iv.data, iv.size);
+ EVP_CIPHER_CTX_init(&ctx);
- if (CRYPTO_gcm128_aad(ctx, aad.data, aad.size))
- goto out_err;
+ if (EVP_EncryptInit_ex(&ctx, cipher, NULL, NULL, NULL) != 1)
+ goto out_err;
+
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+ if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
+ goto out_err;
+ if (EVP_EncryptInit_ex(&ctx, NULL, NULL, key.data, iv.data) != 1)
+ goto out_err;
+ if (EVP_EncryptUpdate(&ctx, NULL, &len, aad.data, aad.size) != 1)
+ goto out_err;
outp = enif_make_new_binary(env, in.size, &out);
- /* encrypt */
- if (CRYPTO_gcm128_encrypt(ctx, in.data, outp, in.size))
- goto out_err;
+ if (EVP_EncryptUpdate(&ctx, outp, &len, in.data, in.size) != 1)
+ goto out_err;
+ if (EVP_EncryptFinal_ex(&ctx, outp+len, &len) != 1)
+ goto out_err;
+
+ tagp = enif_make_new_binary(env, EVP_GCM_TLS_TAG_LEN, &out_tag);
- /* calculate the tag */
- CRYPTO_gcm128_tag(ctx, enif_make_new_binary(env, EVP_GCM_TLS_TAG_LEN, &out_tag), EVP_GCM_TLS_TAG_LEN);
- CRYPTO_gcm128_release(ctx);
+ if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, EVP_GCM_TLS_TAG_LEN, tagp) != 1)
+ goto out_err;
+
+ EVP_CIPHER_CTX_cleanup(&ctx);
CONSUME_REDS(env, in);
return enif_make_tuple2(env, out, out_tag);
out_err:
- CRYPTO_gcm128_release(ctx);
+ EVP_CIPHER_CTX_cleanup(&ctx);
return atom_error;
#else
- return atom_notsup;
+ return enif_raise_exception(env, atom_notsup);
#endif
}
static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key,Iv,AAD,In,Tag) */
#if defined(HAVE_GCM)
- GCM128_CONTEXT *ctx;
+ EVP_CIPHER_CTX ctx;
+ const EVP_CIPHER *cipher = NULL;
ErlNifBinary key, iv, aad, in, tag;
- AES_KEY aes_key;
unsigned char *outp;
ERL_NIF_TERM out;
-
- CHECK_OSE_CRYPTO();
+ int len;
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
+ || (key.size != 16 && key.size != 24 && key.size != 32)
|| !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0
|| !enif_inspect_iolist_as_binary(env, argv[2], &aad)
|| !enif_inspect_iolist_as_binary(env, argv[3], &in)
@@ -1877,34 +1708,45 @@ static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
return enif_make_badarg(env);
}
- if (!(ctx = CRYPTO_gcm128_new(&aes_key, (block128_f)AES_encrypt)))
- return atom_error;
+ if (key.size == 16)
+ cipher = EVP_aes_128_gcm();
+ else if (key.size == 24)
+ cipher = EVP_aes_192_gcm();
+ else if (key.size == 32)
+ cipher = EVP_aes_256_gcm();
- CRYPTO_gcm128_setiv(ctx, iv.data, iv.size);
+ EVP_CIPHER_CTX_init(&ctx);
- if (CRYPTO_gcm128_aad(ctx, aad.data, aad.size))
- goto out_err;
+ if (EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL) != 1)
+ goto out_err;
+ if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
+ goto out_err;
+ if (EVP_DecryptInit_ex(&ctx, NULL, NULL, key.data, iv.data) != 1)
+ goto out_err;
+ if (EVP_DecryptUpdate(&ctx, NULL, &len, aad.data, aad.size) != 1)
+ goto out_err;
outp = enif_make_new_binary(env, in.size, &out);
- /* decrypt */
- if (CRYPTO_gcm128_decrypt(ctx, in.data, outp, in.size))
- goto out_err;
+ if (EVP_DecryptUpdate(&ctx, outp, &len, in.data, in.size) != 1)
+ goto out_err;
+ if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, EVP_GCM_TLS_TAG_LEN, tag.data) != 1)
+ goto out_err;
+ if (EVP_DecryptFinal_ex(&ctx, outp+len, &len) != 1)
+ goto out_err;
- /* calculate and check the tag */
- if (CRYPTO_gcm128_finish(ctx, tag.data, EVP_GCM_TLS_TAG_LEN))
- goto out_err;
+ EVP_CIPHER_CTX_cleanup(&ctx);
- CRYPTO_gcm128_release(ctx);
CONSUME_REDS(env, in);
return out;
out_err:
- CRYPTO_gcm128_release(ctx);
+ EVP_CIPHER_CTX_cleanup(&ctx);
return atom_error;
+
#else
- return atom_notsup;
+ return enif_raise_exception(env, atom_notsup);
#endif
}
@@ -1937,8 +1779,6 @@ static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ER
unsigned char poly1305_key[32];
poly1305_state poly1305;
- CHECK_OSE_CRYPTO();
-
if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
|| !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN
|| !enif_inspect_iolist_as_binary(env, argv[2], &aad)
@@ -1976,7 +1816,7 @@ static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ER
return enif_make_tuple2(env, out, out_tag);
#else
- return atom_notsup;
+ return enif_raise_exception(env, atom_notsup);
#endif
}
@@ -1991,8 +1831,6 @@ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ER
unsigned char mac[POLY1305_TAG_LEN];
poly1305_state poly1305;
- CHECK_OSE_CRYPTO();
-
if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
|| !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN
|| !enif_inspect_iolist_as_binary(env, argv[2], &aad)
@@ -2033,51 +1871,16 @@ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ER
return out;
#else
- return atom_notsup;
+ return enif_raise_exception(env, atom_notsup);
#endif
}
-static ERL_NIF_TERM aes_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, IsEncrypt) */
- ErlNifBinary key_bin, data_bin;
- AES_KEY aes_key;
- int i;
- int j;
- unsigned char* ret_ptr;
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || (key_bin.size != 16 && key_bin.size != 32)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)
- || data_bin.size % 16 != 0) {
- return enif_make_badarg(env);
- }
-
- if (argv[2] == atom_true) {
- i = AES_ENCRYPT;
- AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key);
- }
- else {
- i = AES_DECRYPT;
- AES_set_decrypt_key(key_bin.data, key_bin.size*8, &aes_key);
- }
-
- ret_ptr = enif_make_new_binary(env, data_bin.size, &ret);
- for (j = 0; j < data_bin.size; j += 16) {
- AES_ecb_encrypt(data_bin.data+j, ret_ptr+j, &aes_key, i);
- }
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Bytes) */
unsigned bytes;
unsigned char* data;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
+
if (!enif_get_uint(env, argv[0], &bytes)) {
return enif_make_badarg(env);
}
@@ -2091,7 +1894,7 @@ static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NI
unsigned bytes;
unsigned char* data;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
+
if (!enif_get_uint(env, argv[0], &bytes)) {
return enif_make_badarg(env);
}
@@ -2109,7 +1912,7 @@ static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
unsigned char* data;
unsigned top_mask, bot_mask;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
+
if (!enif_get_uint(env, argv[0], &bytes)
|| !enif_get_uint(env, argv[1], &top_mask)
|| !enif_get_uint(env, argv[2], &bot_mask)) {
@@ -2133,8 +1936,6 @@ static ERL_NIF_TERM strong_rand_mpint_nif(ErlNifEnv* env, int argc, const ERL_NI
unsigned dlen;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!enif_get_uint(env, argv[0], &bits)
|| !enif_get_int(env, argv[1], &top)
|| !enif_get_int(env, argv[2], &bottom)) {
@@ -2203,8 +2004,6 @@ static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
unsigned dlen;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!get_bn_from_mpint(env, argv[0], &bn_from)
|| !get_bn_from_mpint(env, argv[1], &bn_rand)) {
if (bn_from) BN_free(bn_from);
@@ -2236,8 +2035,6 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
unsigned extra_byte;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!get_bn_from_bin(env, argv[0], &bn_base)
|| !get_bn_from_bin(env, argv[1], &bn_exponent)
|| !get_bn_from_bin(env, argv[2], &bn_modulo)
@@ -2269,46 +2066,17 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
}
static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (DigestType|none, Data|{digest,Digest}, Signature,Key=[P, Q, G, Y]) */
- ErlNifBinary data_bin, sign_bin;
+{/* (sha, Digest, Signature,Key=[P, Q, G, Y]) */
+ ErlNifBinary digest_bin, sign_bin;
BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_y = NULL;
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
- unsigned char* digest;
ERL_NIF_TERM head, tail;
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
DSA *dsa;
int i;
- CHECK_OSE_CRYPTO();
-
- if (argv[0] == atom_sha) {
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != SHA_DIGEST_LENGTH) {
-
- return enif_make_badarg(env);
- }
- digest = data_bin.data;
- }
- else {
- if (!enif_inspect_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
- }
- SHA1(data_bin.data, data_bin.size, hmacbuf);
- digest = hmacbuf;
- }
- }
- else if (argv[0] == atom_none && enif_inspect_binary(env, argv[1], &data_bin)
- && data_bin.size == SHA_DIGEST_LENGTH) {
- digest = data_bin.data;
- }
- else {
- return enif_make_badarg(env);
- }
-
- if (!enif_inspect_binary(env, argv[2], &sign_bin)
+ if (!argv[0] == atom_sha
+ || !enif_inspect_binary(env, argv[1], &digest_bin)
+ || digest_bin.size != SHA_DIGEST_LENGTH
+ || !enif_inspect_binary(env, argv[2], &sign_bin)
|| !enif_get_list_cell(env, argv[3], &head, &tail)
|| !get_bn_from_bin(env, head, &dsa_p)
|| !enif_get_list_cell(env, tail, &head, &tail)
@@ -2332,94 +2100,27 @@ static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
dsa->g = dsa_g;
dsa->priv_key = NULL;
dsa->pub_key = dsa_y;
- i = DSA_verify(0, digest, SHA_DIGEST_LENGTH,
+ i = DSA_verify(0, digest_bin.data, SHA_DIGEST_LENGTH,
sign_bin.data, sign_bin.size, dsa);
DSA_free(dsa);
return(i > 0) ? atom_true : atom_false;
}
-
-static void md5_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
-{
- MD5(in, in_len, out);
-}
-static void sha1_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
-{
- SHA1(in, in_len, out);
-}
-#ifdef HAVE_SHA224
-static void sha224_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
-{
- SHA224(in, in_len, out);
-}
-#endif
-#ifdef HAVE_SHA256
-static void sha256_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
-{
- SHA256(in, in_len, out);
-}
-#endif
-#ifdef HAVE_SHA384
-static void sha384_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
-{
- SHA384(in, in_len, out);
-}
-#endif
-#ifdef HAVE_SHA512
-static void sha512_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
+static void init_digest_types(ErlNifEnv* env)
{
- SHA512(in, in_len, out);
-}
-#endif
+ struct digest_type_t* p = digest_types;
-struct digest_type_t {
- const char* type_str;
- unsigned len; /* 0 if notsup */
- int NID_type;
- void (*funcp)(unsigned char* in, unsigned int in_len, unsigned char* out);
- ERL_NIF_TERM type_atom;
-};
+ for (p = digest_types; p->type_str; p++) {
+ p->type_atom = enif_make_atom(env, p->type_str);
+ }
-struct digest_type_t digest_types[] =
-{
- {"md5", MD5_DIGEST_LENGTH, NID_md5, md5_digest},
- {"sha", SHA_DIGEST_LENGTH, NID_sha1, sha1_digest},
- {"sha224",
-#ifdef HAVE_SHA224
- SHA224_LEN, NID_sha224, sha224_digest
-#else
- 0
-#endif
- },
- {"sha256",
-#ifdef HAVE_SHA256
- SHA256_LEN, NID_sha256, sha256_digest
-#else
- 0
-#endif
- },
- {"sha384",
-#ifdef HAVE_SHA384
- SHA384_LEN, NID_sha384, sha384_digest
-#else
- 0
-#endif
- },
- {"sha512",
-#ifdef HAVE_SHA512
- SHA512_LEN, NID_sha512, sha512_digest
-#else
- 0
-#endif
- },
- {NULL}
-};
+}
-static void init_digest_types(ErlNifEnv* env)
+static void init_cipher_types(ErlNifEnv* env)
{
- struct digest_type_t* p = digest_types;
+ struct cipher_type_t* p = cipher_types;
- for (p = digest_types; p->type_str; p++) {
+ for (p = cipher_types; p->type_str; p++) {
p->type_atom = enif_make_atom(env, p->type_str);
}
@@ -2436,32 +2137,45 @@ static struct digest_type_t* get_digest_type(ERL_NIF_TERM type)
return NULL;
}
-static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data|{digest,Digest}, Signature, Key=[E,N]) */
- ErlNifBinary data_bin, sign_bin;
- unsigned char hmacbuf[SHA512_LEN];
- ERL_NIF_TERM head, tail, ret;
- int i;
- RSA* rsa;
- const ERL_NIF_TERM type = argv[0];
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
- struct digest_type_t* digp = NULL;
- unsigned char* digest = NULL;
+static struct cipher_type_t* get_cipher_type(ERL_NIF_TERM type, size_t key_len)
+{
+ struct cipher_type_t* p = NULL;
+ for (p = cipher_types; p->type_str; p++) {
+ if (type == p->type_atom && (!p->key_len || key_len == p->key_len)) {
+ return p;
+ }
+ }
+ return NULL;
+}
- CHECK_OSE_CRYPTO();
+static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type, Digest, Signature, Key=[E,N]) */
+ ErlNifBinary digest_bin, sign_bin;
+ ERL_NIF_TERM head, tail, ret;
+ int i;
+ RSA *rsa;
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+ EVP_PKEY *pkey;
+ EVP_PKEY_CTX *ctx;
+#endif
+ const EVP_MD *md;
+ const ERL_NIF_TERM type = argv[0];
+ struct digest_type_t *digp = NULL;
digp = get_digest_type(type);
if (!digp) {
return enif_make_badarg(env);
}
- if (!digp->len) {
+ if (!digp->md_func) {
return atom_notsup;
}
rsa = RSA_new();
+ md = digp->md_func();
- if (!enif_inspect_binary(env, argv[2], &sign_bin)
+ if (!enif_inspect_binary(env, argv[1], &digest_bin)
+ || digest_bin.size != EVP_MD_size(md)
+ || !enif_inspect_binary(env, argv[2], &sign_bin)
|| !enif_get_list_cell(env, argv[3], &head, &tail)
|| !get_bn_from_bin(env, head, &rsa->e)
|| !enif_get_list_cell(env, tail, &head, &tail)
@@ -2471,27 +2185,24 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
ret = enif_make_badarg(env);
goto done;
}
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != digp->len) {
- ret = enif_make_badarg(env);
- goto done;
- }
- digest = data_bin.data;
- }
- else if (enif_inspect_binary(env, argv[1], &data_bin)) {
- digest = hmacbuf;
- digp->funcp(data_bin.data, data_bin.size, digest);
- }
- else {
- ret = enif_make_badarg(env);
- goto done;
- }
-
- i = RSA_verify(digp->NID_type, digest, digp->len,
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+ pkey = EVP_PKEY_new();
+ EVP_PKEY_set1_RSA(pkey, rsa);
+
+ ctx = EVP_PKEY_CTX_new(pkey, NULL);
+ EVP_PKEY_verify_init(ctx);
+ EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);
+ EVP_PKEY_CTX_set_signature_md(ctx, md);
+
+ i = EVP_PKEY_verify(ctx, sign_bin.data, sign_bin.size,
+ digest_bin.data, digest_bin.size);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+#else
+ i = RSA_verify(md->type, digest_bin.data, EVP_MD_size(md),
sign_bin.data, sign_bin.size, rsa);
+#endif
ret = (i==1 ? atom_true : atom_false);
@@ -2500,109 +2211,6 @@ done:
return ret;
}
-
-static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, IVec, Data, IsEncrypt) */
- ErlNifBinary key_bin, ivec_bin, data_bin;
- unsigned char ivec[16];
- int enc, i = 0, outlen = 0;
- EVP_CIPHER_CTX ctx;
- const EVP_CIPHER *cipher = NULL;
- unsigned char* ret_ptr;
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || (key_bin.size != 16 && key_bin.size != 32)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 16
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
- || data_bin.size % 16 != 0) {
-
- return enif_make_badarg(env);
- }
-
- if (argv[3] == atom_true)
- enc = 1;
- else
- enc = 0;
-
- EVP_CIPHER_CTX_init(&ctx);
-
- if (key_bin.size == 16)
- cipher = EVP_aes_128_cbc();
- else if (key_bin.size == 32)
- cipher = EVP_aes_256_cbc();
-
- memcpy(ivec, ivec_bin.data, 16); /* writeable copy */
-
- /* openssl docs say we need to leave at least 3 blocks available
- at the end of the buffer for EVP calls. let's be safe */
- ret_ptr = enif_make_new_binary(env, data_bin.size + 16*3, &ret);
-
- if (EVP_CipherInit_ex(&ctx, cipher, NULL, key_bin.data, ivec, enc) != 1)
- return enif_make_badarg(env);
-
- /* disable padding, we only handle whole blocks */
- EVP_CIPHER_CTX_set_padding(&ctx, 0);
-
- if (EVP_CipherUpdate(&ctx, ret_ptr, &i, data_bin.data, data_bin.size) != 1)
- return enif_make_badarg(env);
- outlen += i;
- if (EVP_CipherFinal_ex(&ctx, ret_ptr + outlen, &i) != 1)
- return enif_make_badarg(env);
- outlen += i;
-
- EVP_CIPHER_CTX_cleanup(&ctx);
-
- CONSUME_REDS(env,data_bin);
-
- /* the garbage collector is going to love this */
- return enif_make_sub_binary(env, ret, 0, outlen);
-}
-
-static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, IVec, Data, IsEncrypt) */
-#ifdef HAVE_AES_IGE
- ErlNifBinary key_bin, ivec_bin, data_bin;
- AES_KEY aes_key;
- unsigned char ivec[32];
- int i;
- unsigned char* ret_ptr;
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || (key_bin.size != 16 && key_bin.size != 32)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 32
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
- || data_bin.size % 16 != 0) {
-
- return enif_make_badarg(env);
- }
-
- if (argv[3] == atom_true) {
- i = AES_ENCRYPT;
- AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key);
- }
- else {
- i = AES_DECRYPT;
- AES_set_decrypt_key(key_bin.data, key_bin.size*8, &aes_key);
- }
-
- ret_ptr = enif_make_new_binary(env, data_bin.size, &ret);
- memcpy(ivec, ivec_bin.data, 32); /* writable copy */
- AES_ige_encrypt(data_bin.data, ret_ptr, data_bin.size, &aes_key, ivec, i);
- CONSUME_REDS(env,data_bin);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-
static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Data1, Data2) */
ErlNifBinary d1, d2;
@@ -2610,8 +2218,6 @@ static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
int i;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!enif_inspect_iolist_as_binary(env,argv[0], &d1)
|| !enif_inspect_iolist_as_binary(env,argv[1], &d2)
|| d1.size != d2.size) {
@@ -2632,8 +2238,6 @@ static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
RC4_KEY rc4_key;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!enif_inspect_iolist_as_binary(env,argv[0], &key)
|| !enif_inspect_iolist_as_binary(env,argv[1], &data)) {
return enif_make_badarg(env);
@@ -2650,8 +2254,6 @@ static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
ErlNifBinary key;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!enif_inspect_iolist_as_binary(env,argv[0], &key)) {
return enif_make_badarg(env);
}
@@ -2667,8 +2269,6 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N
RC4_KEY* rc4_key;
ERL_NIF_TERM new_state, new_data;
- CHECK_OSE_CRYPTO();
-
if (!enif_inspect_iolist_as_binary(env,argv[0], &state)
|| state.size != sizeof(RC4_KEY)
|| !enif_inspect_iolist_as_binary(env,argv[1], &data)) {
@@ -2682,35 +2282,6 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N
return enif_make_tuple2(env,new_state,new_data);
}
-static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key,IVec,Data,IsEncrypt) */
- ErlNifBinary key_bin, ivec_bin, data_bin;
- RC2_KEY rc2_key;
- ERL_NIF_TERM ret;
- unsigned char iv_copy[8];
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || (key_bin.size != 5 && key_bin.size != 8 && key_bin.size != 16)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
- || data_bin.size % 8 != 0) {
- return enif_make_badarg(env);
- }
-
- RC2_set_key(&rc2_key, key_bin.size, key_bin.data, key_bin.size*8);
- memcpy(iv_copy, ivec_bin.data, 8);
- RC2_cbc_encrypt(data_bin.data,
- enif_make_new_binary(env, data_bin.size, &ret),
- data_bin.size, &rc2_key,
- iv_copy,
- (argv[3] == atom_true));
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
static int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa)
{
/* key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C] */
@@ -2740,42 +2311,32 @@ static int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa)
}
static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data|{digest,Digest}, Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C]) */
- ErlNifBinary data_bin, ret_bin;
- unsigned char hmacbuf[SHA512_LEN];
- unsigned rsa_s_len;
- RSA* rsa;
- int i;
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
+{/* (Type, Digest, Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C]) */
+ ErlNifBinary digest_bin, ret_bin;
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+ EVP_PKEY *pkey;
+ EVP_PKEY_CTX *ctx;
+ size_t rsa_s_len;
+#else
+ unsigned rsa_s_len, len;
+#endif
+ RSA *rsa;
+ int i;
struct digest_type_t *digp;
- unsigned char* digest;
-
- CHECK_OSE_CRYPTO();
+ const EVP_MD *md;
digp = get_digest_type(argv[0]);
if (!digp) {
return enif_make_badarg(env);
}
- if (!digp->len) {
+ if (!digp->md_func) {
return atom_notsup;
}
+ md = digp->md_func();
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != digp->len) {
-
- return enif_make_badarg(env);
- }
- digest = data_bin.data;
- }
- else {
- if (!enif_inspect_binary(env,argv[1],&data_bin)) {
- return enif_make_badarg(env);
- }
- digest = hmacbuf;
- digp->funcp(data_bin.data, data_bin.size, digest);
+ if (!enif_inspect_binary(env,argv[1],&digest_bin)
+ || digest_bin.size != EVP_MD_size(md)) {
+ return enif_make_badarg(env);
}
rsa = RSA_new();
@@ -2785,14 +2346,33 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
}
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+ pkey = EVP_PKEY_new();
+ EVP_PKEY_set1_RSA(pkey, rsa);
+ rsa_s_len=(size_t)EVP_PKEY_size(pkey);
+ enif_alloc_binary(rsa_s_len, &ret_bin);
+
+ ctx = EVP_PKEY_CTX_new(pkey, NULL);
+ EVP_PKEY_sign_init(ctx);
+ EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);
+ EVP_PKEY_CTX_set_signature_md(ctx, md);
+
+ i = EVP_PKEY_sign(ctx, ret_bin.data, &rsa_s_len,
+ digest_bin.data, digest_bin.size);
+ ASSERT(i<=0 || rsa_s_len <= ret_bin.size);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+#else
enif_alloc_binary(RSA_size(rsa), &ret_bin);
+ len = EVP_MD_size(md);
- ERL_VALGRIND_ASSERT_MEM_DEFINED(digest, digp->len);
- i = RSA_sign(digp->NID_type, digest, digp->len,
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(digest_bin.data, len);
+ i = RSA_sign(md->type, digest_bin.data, len,
ret_bin.data, &rsa_s_len, rsa);
+#endif
RSA_free(rsa);
- if (i) {
+ if (i > 0) {
ERL_VALGRIND_MAKE_MEM_DEFINED(ret_bin.data, rsa_s_len);
if (rsa_s_len != ret_bin.size) {
enif_realloc_binary(&ret_bin, rsa_s_len);
@@ -2808,44 +2388,16 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (DigesType|none, Data|{digest,Digest}, Key=[P,Q,G,PrivKey]) */
- ErlNifBinary data_bin, ret_bin;
+{/* (sha, Digest, Key=[P,Q,G,PrivKey]) */
+ ErlNifBinary digest_bin, ret_bin;
ERL_NIF_TERM head, tail;
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
unsigned int dsa_s_len;
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
- unsigned char* digest = NULL;
DSA* dsa;
int i;
- CHECK_OSE_CRYPTO();
-
- if (argv[0] == atom_sha) {
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != SHA_DIGEST_LENGTH) {
-
- return enif_make_badarg(env);
- }
- digest = data_bin.data;
- }
- else {
- if (!enif_inspect_binary(env,argv[1],&data_bin)) {
- return enif_make_badarg(env);
- }
- SHA1(data_bin.data, data_bin.size, hmacbuf);
- digest = hmacbuf;
- }
- }
- else if (argv[0] == atom_none
- && enif_inspect_binary(env,argv[1],&data_bin)
- && data_bin.size == SHA_DIGEST_LENGTH) {
-
- digest = data_bin.data;
- }
- else {
+ if (!argv[0] == atom_sha
+ || !enif_inspect_binary(env, argv[1], &digest_bin)
+ || digest_bin.size != SHA_DIGEST_LENGTH) {
return enif_make_badarg(env);
}
@@ -2866,7 +2418,7 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
}
enif_alloc_binary(DSA_size(dsa), &ret_bin);
- i = DSA_sign(NID_sha1, digest, SHA_DIGEST_LENGTH,
+ i = DSA_sign(NID_sha1, digest_bin.data, SHA_DIGEST_LENGTH,
ret_bin.data, &dsa_s_len, dsa);
DSA_free(dsa);
if (i) {
@@ -2906,8 +2458,6 @@ static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TER
int padding, i;
RSA* rsa;
- CHECK_OSE_CRYPTO();
-
rsa = RSA_new();
if (!enif_inspect_binary(env, argv[0], &data_bin)
@@ -2956,8 +2506,6 @@ static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE
int padding, i;
RSA* rsa;
- CHECK_OSE_CRYPTO();
-
rsa = RSA_new();
if (!enif_inspect_binary(env, argv[0], &data_bin)
@@ -3004,8 +2552,6 @@ static ERL_NIF_TERM dh_generate_parameters_nif(ErlNifEnv* env, int argc, const E
unsigned char *p_ptr, *g_ptr;
ERL_NIF_TERM ret_p, ret_g;
- CHECK_OSE_CRYPTO();
-
if (!enif_get_int(env, argv[0], &prime_len)
|| !enif_get_int(env, argv[1], &generator)) {
@@ -3033,8 +2579,6 @@ static ERL_NIF_TERM dh_check(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
int i;
ERL_NIF_TERM ret, head, tail;
- CHECK_OSE_CRYPTO();
-
dh_params = DH_new();
if (!enif_get_list_cell(env, argv[0], &head, &tail)
@@ -3069,8 +2613,6 @@ static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_
ERL_NIF_TERM ret, ret_pub, ret_prv, head, tail;
int mpint; /* 0 or 4 */
- CHECK_OSE_CRYPTO();
-
dh_params = DH_new();
if (!(get_bn_from_bin(env, argv[0], &dh_params->priv_key)
@@ -3115,8 +2657,6 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T
ErlNifBinary ret_bin;
ERL_NIF_TERM ret, head, tail;
- CHECK_OSE_CRYPTO();
-
dh_params = DH_new();
if (!get_bn_from_bin(env, argv[0], &pubkey)
@@ -3139,7 +2679,7 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T
ret = enif_make_binary(env, &ret_bin);
}
else {
- enif_release_binary(&ret_bin);
+ enif_release_binary(&ret_bin);
ret = atom_error;
}
}
@@ -3157,8 +2697,6 @@ static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
unsigned dlen;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!get_bn_from_bin(env, argv[0], &bn_multiplier)
|| !get_bn_from_bin(env, argv[1], &bn_verifier)
|| !get_bn_from_bin(env, argv[2], &bn_generator)
@@ -3219,8 +2757,6 @@ static ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_
unsigned dlen;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!get_bn_from_bin(env, argv[0], &bn_a)
|| !get_bn_from_bin(env, argv[1], &bn_u)
|| !get_bn_from_bin(env, argv[2], &bn_B)
@@ -3300,8 +2836,6 @@ static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_
unsigned dlen;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!get_bn_from_bin(env, argv[0], &bn_verifier)
|| !get_bn_from_bin(env, argv[1], &bn_b)
|| !get_bn_from_bin(env, argv[2], &bn_u)
@@ -3354,103 +2888,6 @@ static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_
return ret;
}
-static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Ivec, Data, IsEncrypt) */
- ErlNifBinary key_bin, ivec_bin, data_bin;
- BF_KEY bf_key; /* blowfish key 8 */
- unsigned char bf_tkey[8]; /* blowfish ivec */
- int bf_n = 0; /* blowfish ivec pos */
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)) {
- return enif_make_badarg(env);
- }
-
- BF_set_key(&bf_key, key_bin.size, key_bin.data);
- memcpy(bf_tkey, ivec_bin.data, 8);
- BF_cfb64_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
- data_bin.size, &bf_key, bf_tkey, &bf_n,
- (argv[3] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
-static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Ivec, Data, IsEncrypt) */
- ErlNifBinary key_bin, ivec_bin, data_bin;
- BF_KEY bf_key; /* blowfish key 8 */
- unsigned char bf_tkey[8]; /* blowfish ivec */
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
- || data_bin.size % 8 != 0) {
- return enif_make_badarg(env);
- }
-
- BF_set_key(&bf_key, key_bin.size, key_bin.data);
- memcpy(bf_tkey, ivec_bin.data, 8);
- BF_cbc_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
- data_bin.size, &bf_key, bf_tkey,
- (argv[3] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
-static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, IsEncrypt) */
- ErlNifBinary key_bin, data_bin;
- BF_KEY bf_key; /* blowfish key 8 */
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)
- || data_bin.size < 8) {
- return enif_make_badarg(env);
- }
- BF_set_key(&bf_key, key_bin.size, key_bin.data);
- BF_ecb_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
- &bf_key, (argv[2] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
-static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, IVec, Data) */
- ErlNifBinary key_bin, ivec_bin, data_bin;
- BF_KEY bf_key; /* blowfish key 8 */
- unsigned char bf_tkey[8]; /* blowfish ivec */
- int bf_n = 0; /* blowfish ivec pos */
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)) {
- return enif_make_badarg(env);
- }
-
- BF_set_key(&bf_key, key_bin.size, key_bin.data);
- memcpy(bf_tkey, ivec_bin.data, 8);
- BF_ofb64_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
- data_bin.size, &bf_key, bf_tkey, &bf_n);
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
#if defined(HAVE_EC)
static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg)
{
@@ -3762,8 +3199,6 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM
ERL_NIF_TERM priv_key;
ERL_NIF_TERM pub_key = atom_undefined;
- CHECK_OSE_CRYPTO();
-
if (!get_ec_key(env, argv[0], argv[1], atom_undefined, &key))
goto badarg;
@@ -3793,51 +3228,33 @@ badarg:
}
static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data|{digest,Digest}, Curve, Key) */
+{/* (Type, Digest, Curve, Key) */
#if defined(HAVE_EC)
- ErlNifBinary data_bin, ret_bin;
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
+ ErlNifBinary digest_bin, ret_bin;
unsigned int dsa_s_len;
EC_KEY* key = NULL;
- int i;
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
+ int i, len;
struct digest_type_t *digp;
- unsigned char* digest;
-
- CHECK_OSE_CRYPTO();
+ const EVP_MD *md;
digp = get_digest_type(argv[0]);
if (!digp) {
return enif_make_badarg(env);
}
- if (!digp->len) {
+ if (!digp->md_func) {
return atom_notsup;
}
+ md = digp->md_func();
+ len = EVP_MD_size(md);
- if (!get_ec_key(env, argv[2], argv[3], atom_undefined, &key))
+ if (!enif_inspect_binary(env,argv[1],&digest_bin)
+ || digest_bin.size != len
+ || !get_ec_key(env, argv[2], argv[3], atom_undefined, &key))
goto badarg;
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != digp->len) {
-
- goto badarg;
- }
- digest = data_bin.data;
- }
- else {
- if (!enif_inspect_binary(env,argv[1],&data_bin)) {
- goto badarg;
- }
- digest = hmacbuf;
- digp->funcp(data_bin.data, data_bin.size, digest);
- }
-
enif_alloc_binary(ECDSA_size(key), &ret_bin);
- i = ECDSA_sign(digp->NID_type, digest, digp->len,
+ i = ECDSA_sign(md->type, digest_bin.data, len,
ret_bin.data, &dsa_s_len, key);
EC_KEY_free(key);
@@ -3862,50 +3279,32 @@ badarg:
}
static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data|{digest,Digest}, Signature, Curve, Key) */
+{/* (Type, Digest, Signature, Curve, Key) */
#if defined(HAVE_EC)
- ErlNifBinary data_bin, sign_bin;
- unsigned char hmacbuf[SHA512_LEN];
- int i;
+ ErlNifBinary digest_bin, sign_bin;
+ int i, len;
EC_KEY* key = NULL;
const ERL_NIF_TERM type = argv[0];
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
- struct digest_type_t* digp = NULL;
- unsigned char* digest = NULL;
-
- CHECK_OSE_CRYPTO();
+ struct digest_type_t *digp = NULL;
+ const EVP_MD *md;
digp = get_digest_type(type);
if (!digp) {
return enif_make_badarg(env);
}
- if (!digp->len) {
+ if (!digp->md_func) {
return atom_notsup;
}
+ md = digp->md_func();
+ len = EVP_MD_size(md);
- if (!enif_inspect_binary(env, argv[2], &sign_bin)
+ if (!enif_inspect_binary(env, argv[1], &digest_bin)
+ || digest_bin.size != len
+ || !enif_inspect_binary(env, argv[2], &sign_bin)
|| !get_ec_key(env, argv[3], atom_undefined, argv[4], &key))
goto badarg;
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != digp->len) {
-
- goto badarg;
- }
- digest = data_bin.data;
- }
- else if (enif_inspect_binary(env, argv[1], &data_bin)) {
- digest = hmacbuf;
- digp->funcp(data_bin.data, data_bin.size, digest);
- }
- else {
- goto badarg;
- }
-
- i = ECDSA_verify(digp->NID_type, digest, digp->len,
+ i = ECDSA_verify(md->type, digest_bin.data, len,
sign_bin.data, sign_bin.size, key);
EC_KEY_free(key);
@@ -3939,8 +3338,6 @@ static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF
EC_POINT *my_ecpoint;
EC_KEY *other_ecdh = NULL;
- CHECK_OSE_CRYPTO();
-
if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key))
return enif_make_badarg(env);
@@ -3984,253 +3381,9 @@ out_err:
static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary seed_bin;
- CHECK_OSE_CRYPTO();
+
if (!enif_inspect_binary(env, argv[0], &seed_bin))
return enif_make_badarg(env);
RAND_seed(seed_bin.data,seed_bin.size);
return atom_ok;
}
-
-
-/* HMAC */
-
-static void hmac_md5(unsigned char *key, int klen, unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- MD5_CTX ctx;
- char ipad[HMAC_INT_LEN];
- char opad[HMAC_INT_LEN];
- unsigned char nkey[MD5_LEN];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT_LEN) {
- MD5(key, klen, nkey);
- key = nkey;
- klen = MD5_LEN;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner MD5 */
- MD5_Init(&ctx);
- MD5_Update(&ctx, ipad, HMAC_INT_LEN);
- MD5_Update(&ctx, dbuf, dlen);
- MD5_Final((unsigned char *) hmacbuf, &ctx);
- /* outer MD5 */
- MD5_Init(&ctx);
- MD5_Update(&ctx, opad, HMAC_INT_LEN);
- MD5_Update(&ctx, hmacbuf, MD5_LEN);
- MD5_Final((unsigned char *) hmacbuf, &ctx);
-}
-
-static void hmac_sha1(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- SHA_CTX ctx;
- char ipad[HMAC_INT_LEN];
- char opad[HMAC_INT_LEN];
- unsigned char nkey[SHA_LEN];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT_LEN) {
- SHA1(key, klen, nkey);
- key = nkey;
- klen = SHA_LEN;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner SHA */
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, ipad, HMAC_INT_LEN);
- SHA1_Update(&ctx, dbuf, dlen);
- SHA1_Final((unsigned char *) hmacbuf, &ctx);
- /* outer SHA */
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, opad, HMAC_INT_LEN);
- SHA1_Update(&ctx, hmacbuf, SHA_LEN);
- SHA1_Final((unsigned char *) hmacbuf, &ctx);
-}
-
-#ifdef HAVE_SHA224
-static void hmac_sha224(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- SHA256_CTX ctx;
- char ipad[HMAC_INT_LEN];
- char opad[HMAC_INT_LEN];
- unsigned char nkey[SHA224_DIGEST_LENGTH];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT_LEN) {
- SHA224(key, klen, nkey);
- key = nkey;
- klen = SHA224_DIGEST_LENGTH;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner SHA */
- SHA224_Init(&ctx);
- SHA224_Update(&ctx, ipad, HMAC_INT_LEN);
- SHA224_Update(&ctx, dbuf, dlen);
- SHA224_Final((unsigned char *) hmacbuf, &ctx);
- /* outer SHA */
- SHA224_Init(&ctx);
- SHA224_Update(&ctx, opad, HMAC_INT_LEN);
- SHA224_Update(&ctx, hmacbuf, SHA224_DIGEST_LENGTH);
- SHA224_Final((unsigned char *) hmacbuf, &ctx);
-}
-#endif
-
-#ifdef HAVE_SHA256
-static void hmac_sha256(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- SHA256_CTX ctx;
- char ipad[HMAC_INT_LEN];
- char opad[HMAC_INT_LEN];
- unsigned char nkey[SHA256_DIGEST_LENGTH];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT_LEN) {
- SHA256(key, klen, nkey);
- key = nkey;
- klen = SHA256_DIGEST_LENGTH;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner SHA */
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, ipad, HMAC_INT_LEN);
- SHA256_Update(&ctx, dbuf, dlen);
- SHA256_Final((unsigned char *) hmacbuf, &ctx);
- /* outer SHA */
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, opad, HMAC_INT_LEN);
- SHA256_Update(&ctx, hmacbuf, SHA256_DIGEST_LENGTH);
- SHA256_Final((unsigned char *) hmacbuf, &ctx);
-}
-#endif
-
-#ifdef HAVE_SHA384
-static void hmac_sha384(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- SHA512_CTX ctx;
- char ipad[HMAC_INT2_LEN];
- char opad[HMAC_INT2_LEN];
- unsigned char nkey[SHA384_DIGEST_LENGTH];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT2_LEN) {
- SHA384(key, klen, nkey);
- key = nkey;
- klen = SHA384_DIGEST_LENGTH;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT2_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner SHA */
- SHA384_Init(&ctx);
- SHA384_Update(&ctx, ipad, HMAC_INT2_LEN);
- SHA384_Update(&ctx, dbuf, dlen);
- SHA384_Final((unsigned char *) hmacbuf, &ctx);
- /* outer SHA */
- SHA384_Init(&ctx);
- SHA384_Update(&ctx, opad, HMAC_INT2_LEN);
- SHA384_Update(&ctx, hmacbuf, SHA384_DIGEST_LENGTH);
- SHA384_Final((unsigned char *) hmacbuf, &ctx);
-}
-#endif
-
-#ifdef HAVE_SHA512
-static void hmac_sha512(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- SHA512_CTX ctx;
- char ipad[HMAC_INT2_LEN];
- char opad[HMAC_INT2_LEN];
- unsigned char nkey[SHA512_DIGEST_LENGTH];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT2_LEN) {
- SHA512(key, klen, nkey);
- key = nkey;
- klen = SHA512_DIGEST_LENGTH;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT2_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner SHA */
- SHA512_Init(&ctx);
- SHA512_Update(&ctx, ipad, HMAC_INT2_LEN);
- SHA512_Update(&ctx, dbuf, dlen);
- SHA512_Final((unsigned char *) hmacbuf, &ctx);
- /* outer SHA */
- SHA512_Init(&ctx);
- SHA512_Update(&ctx, opad, HMAC_INT2_LEN);
- SHA512_Update(&ctx, hmacbuf, SHA512_DIGEST_LENGTH);
- SHA512_Final((unsigned char *) hmacbuf, &ctx);
-}
-#endif
diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c
index e0de16074c..af9545bd63 100644
--- a/lib/crypto/c_src/crypto_callback.c
+++ b/lib/crypto/c_src/crypto_callback.c
@@ -43,6 +43,10 @@
#ifdef __WIN32__
# define DLLEXPORT __declspec(dllexport)
+#elif defined(__GNUC__) && __GNUC__ >= 4
+# define DLLEXPORT __attribute__ ((visibility("default")))
+#elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+# define DLLEXPORT __global
#else
# define DLLEXPORT
#endif
@@ -51,8 +55,6 @@
DLLEXPORT struct crypto_callbacks* get_crypto_callbacks(int nlocks);
-static ErlNifRWLock** lock_vec = NULL; /* Static locks used by openssl */
-
static void nomem(size_t size, const char* op)
{
fprintf(stderr, "Out of memory abort. Crypto failed to %s %zu bytes.\r\n",
@@ -84,6 +86,8 @@ static void crypto_free(void* ptr)
#ifdef OPENSSL_THREADS /* vvvvvvvvvvvvvvv OPENSSL_THREADS vvvvvvvvvvvvvvvv */
+static ErlNifRWLock** lock_vec = NULL; /* Static locks used by openssl */
+
#include <openssl/crypto.h>
static INLINE void locking(int mode, ErlNifRWLock* lock)
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 563a090e98..d3e827b3e6 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -135,9 +135,8 @@
<code>stream_cipher() = rc4 | aes_ctr </code>
- <code>block_cipher() = aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_ige256 | blowfish_cbc |
- blowfish_cfb64 | des_cbc | des_cfb | des3_cbc | des3_cbf
- | des_ede3 | rc2_cbc </code>
+ <code>block_cipher() = aes_cbc | aes_cfb8 | aes_cfb128 | aes_ige256 | blowfish_cbc |
+ blowfish_cfb64 | des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | rc2_cbc </code>
<code>aead_cipher() = aes_gcm | chacha20_poly1305 </code>
@@ -160,8 +159,9 @@
<code> hash_algorithms() = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512 </code> <p>md4 is also supported for hash_init/1 and hash/2.
Note that both md4 and md5 are recommended only for compatibility with existing applications.
</p>
- <code> cipher_algorithms() = des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 |
- blowfish_cbc | blowfish_cfb64 | aes_cbc128 | aes_cfb8 | aes_cfb128| aes_cbc256 | aes_ige256 | aes_gcm | chacha20_poly1305 | rc2_cbc | aes_ctr| rc4 </code>
+ <code> cipher_algorithms() = aes_cbc | aes_cfb8 | aes_cfb128 | aes_ctr | aes_gcm |
+ aes_ige256 | blowfish_cbc | blowfish_cfb64 | chacha20_poly1305 | des_cbc | des_cfb |
+ des3_cbc | des3_cbf | des_ede3 | rc2_cbc | rc4 </code>
<code> public_key_algorithms() = rsa |dss | ecdsa | dh | ecdh | ec_gf2m</code>
<p>Note that ec_gf2m is not strictly a public key algorithm, but a restriction on what curves are supported
with ecdsa and ecdh.
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 38e71591f3..3e24ff2b0a 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -210,10 +210,8 @@ supports()->
{Hashs, PubKeys, Ciphers} = algorithms(),
[{hashs, Hashs},
- {ciphers, [des_cbc, des_cfb, des3_cbc, des_ede3, blowfish_cbc,
- blowfish_cfb64, blowfish_ofb64, blowfish_ecb, aes_cbc128, aes_cfb8, aes_cfb128,
- aes_cbc256, rc2_cbc, aes_ctr, rc4, aes_ecb] ++ Ciphers},
- {public_keys, [rsa, dss, dh, srp] ++ PubKeys}
+ {ciphers, Ciphers},
+ {public_keys, PubKeys}
].
info_lib() -> ?nif_stub.
@@ -222,20 +220,14 @@ info_lib() -> ?nif_stub.
hash(Hash, Data0) ->
Data = iolist_to_binary(Data0),
- MaxByts = max_bytes(),
- hash(Hash, Data, erlang:byte_size(Data), MaxByts, initial).
+ MaxBytes = max_bytes(),
+ hash(Hash, Data, erlang:byte_size(Data), MaxBytes).
-spec hash_init('md5'|'md4'|'ripemd160'|
'sha'|'sha224'|'sha256'|'sha384'|'sha512') -> any().
-hash_init(md5) -> {md5, md5_init()};
-hash_init(md4) -> {md4, md4_init()};
-hash_init(sha) -> {sha, sha_init()};
-hash_init(ripemd160) -> {ripemd160, ripemd160_init()};
-hash_init(sha224) -> {sha224, sha224_init()};
-hash_init(sha256) -> {sha256, sha256_init()};
-hash_init(sha384) -> {sha384, sha384_init()};
-hash_init(sha512) -> {sha512, sha512_init()}.
+hash_init(Hash) ->
+ notsup_to_error(hash_init_nif(Hash)).
-spec hash_update(_, iodata()) -> any().
@@ -246,14 +238,8 @@ hash_update(State, Data0) ->
-spec hash_final(_) -> binary().
-hash_final({md5,Context}) -> md5_final(Context);
-hash_final({md4,Context}) -> md4_final(Context);
-hash_final({sha,Context}) -> sha_final(Context);
-hash_final({ripemd160,Context}) -> ripemd160_final(Context);
-hash_final({sha224,Context}) -> sha224_final(Context);
-hash_final({sha256,Context}) -> sha256_final(Context);
-hash_final({sha384,Context}) -> sha384_final(Context);
-hash_final({sha512,Context}) -> sha512_final(Context).
+hash_final(State) ->
+ notsup_to_error(hash_final_nif(State)).
-spec hmac(_, iodata(), iodata()) -> binary().
@@ -265,151 +251,132 @@ hash_final({sha512,Context}) -> sha512_final(Context).
hmac(Type, Key, Data0) ->
Data = iolist_to_binary(Data0),
- hmac(Type, Key, Data, undefined, erlang:byte_size(Data), max_bytes(), initial).
+ hmac(Type, Key, Data, undefined, erlang:byte_size(Data), max_bytes()).
hmac(Type, Key, Data0, MacSize) ->
Data = iolist_to_binary(Data0),
- hmac(Type, Key, Data, MacSize, erlang:byte_size(Data), max_bytes(), initial).
-
+ hmac(Type, Key, Data, MacSize, erlang:byte_size(Data), max_bytes()).
-hmac_init(_Type, _Key) -> ?nif_stub.
+hmac_init(Type, Key) ->
+ notsup_to_error(hmac_init_nif(Type, Key)).
hmac_update(State, Data0) ->
Data = iolist_to_binary(Data0),
hmac_update(State, Data, erlang:byte_size(Data), max_bytes()).
-hmac_final(_Context) -> ? nif_stub.
-hmac_final_n(_Context, _HashLen) -> ? nif_stub.
+
+hmac_final(Context) ->
+ notsup_to_error(hmac_final_nif(Context)).
+hmac_final_n(Context, HashLen) ->
+ notsup_to_error(hmac_final_nif(Context, HashLen)).
%% Ecrypt/decrypt %%%
--spec block_encrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc |
- blowfish_cfb64 | aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | rc2_cbc,
+-spec block_encrypt(des_cbc | des_cfb |
+ des3_cbc | des3_cbf | des_ede3 |
+ blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 |
+ aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 |
+ aes_cbc |
+ rc2_cbc,
Key::iodata(), Ivec::binary(), Data::iodata()) -> binary();
(aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata()}) -> {binary(), binary()}.
-block_encrypt(des_cbc, Key, Ivec, Data) ->
- des_cbc_encrypt(Key, Ivec, Data);
-block_encrypt(des_cfb, Key, Ivec, Data) ->
- des_cfb_encrypt(Key, Ivec, Data);
-block_encrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data);
-block_encrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cfb_encrypt(Key1, Key2, Key3, Ivec, Data);
-block_encrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) ->
- des_ede3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data);
-block_encrypt(blowfish_cbc, Key, Ivec, Data) ->
- blowfish_cbc_encrypt(Key, Ivec, Data);
-block_encrypt(blowfish_cfb64, Key, Ivec, Data) ->
- blowfish_cfb64_encrypt(Key, Ivec, Data);
-block_encrypt(blowfish_ofb64, Key, Ivec, Data) ->
- blowfish_ofb64_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cbc128, Key, Ivec, Data) ->
- aes_cbc_128_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cbc256, Key, Ivec, Data) ->
- aes_cbc_256_encrypt(Key, Ivec, Data);
+block_encrypt(Type, Key, Ivec, Data) when Type =:= des_cbc;
+ Type =:= des_cfb;
+ Type =:= blowfish_cbc;
+ Type =:= blowfish_cfb64;
+ Type =:= blowfish_ofb64;
+ Type =:= aes_cbc128;
+ Type =:= aes_cfb8;
+ Type =:= aes_cfb128;
+ Type =:= aes_cbc256;
+ Type =:= aes_cbc;
+ Type =:= rc2_cbc ->
+ block_crypt_nif(Type, Key, Ivec, Data, true);
+block_encrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc;
+ Type =:= des_ede3 ->
+ Key = check_des3_key(Key0),
+ block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, true);
+block_encrypt(des3_cbf, Key0, Ivec, Data) ->
+ Key = check_des3_key(Key0),
+ block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, true);
block_encrypt(aes_ige256, Key, Ivec, Data) ->
- aes_ige_256_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cfb8, Key, Ivec, Data) ->
- aes_cfb_8_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cfb128, Key, Ivec, Data) ->
- aes_cfb_128_encrypt(Key, Ivec, Data);
+ aes_ige_crypt_nif(Key, Ivec, Data, true);
block_encrypt(aes_gcm, Key, Ivec, {AAD, Data}) ->
- case aes_gcm_encrypt(Key, Ivec, AAD, Data) of
- notsup -> erlang:error(notsup);
- Return -> Return
- end;
+ aes_gcm_encrypt(Key, Ivec, AAD, Data);
block_encrypt(chacha20_poly1305, Key, Ivec, {AAD, Data}) ->
- case chacha20_poly1305_encrypt(Key, Ivec, AAD, Data) of
- notsup -> erlang:error(notsup);
- Return -> Return
- end;
-block_encrypt(rc2_cbc, Key, Ivec, Data) ->
- rc2_cbc_encrypt(Key, Ivec, Data).
-
--spec block_decrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc |
- blowfish_cfb64 | blowfish_ofb64 | aes_cbc128 | aes_cbc256 | aes_ige256 |
- aes_cfb8 | aes_cfb128 | rc2_cbc,
+ chacha20_poly1305_encrypt(Key, Ivec, AAD, Data).
+
+-spec block_decrypt(des_cbc | des_cfb |
+ des3_cbc | des3_cbf | des_ede3 |
+ blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 |
+ aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 |
+ aes_cbc |
+ rc2_cbc,
Key::iodata(), Ivec::binary(), Data::iodata()) -> binary();
(aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(),
{AAD::binary(), Data::iodata(), Tag::binary()}) -> binary() | error.
-block_decrypt(des_cbc, Key, Ivec, Data) ->
- des_cbc_decrypt(Key, Ivec, Data);
-block_decrypt(des_cfb, Key, Ivec, Data) ->
- des_cfb_decrypt(Key, Ivec, Data);
-block_decrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data);
-block_decrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cfb_decrypt(Key1, Key2, Key3, Ivec, Data);
-block_decrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) ->
- des_ede3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data);
-block_decrypt(blowfish_cbc, Key, Ivec, Data) ->
- blowfish_cbc_decrypt(Key, Ivec, Data);
-block_decrypt(blowfish_cfb64, Key, Ivec, Data) ->
- blowfish_cfb64_decrypt(Key, Ivec, Data);
-block_decrypt(blowfish_ofb64, Key, Ivec, Data) ->
- blowfish_ofb64_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cbc128, Key, Ivec, Data) ->
- aes_cbc_128_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cbc256, Key, Ivec, Data) ->
- aes_cbc_256_decrypt(Key, Ivec, Data);
+block_decrypt(Type, Key, Ivec, Data) when Type =:= des_cbc;
+ Type =:= des_cfb;
+ Type =:= blowfish_cbc;
+ Type =:= blowfish_cfb64;
+ Type =:= blowfish_ofb64;
+ Type =:= aes_cbc;
+ Type =:= aes_cbc128;
+ Type =:= aes_cfb8;
+ Type =:= aes_cfb128;
+ Type =:= aes_cbc256;
+ Type =:= rc2_cbc ->
+ block_crypt_nif(Type, Key, Ivec, Data, false);
+block_decrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc;
+ Type =:= des_ede3 ->
+ Key = check_des3_key(Key0),
+ block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, false);
+block_decrypt(des3_cbf, Key0, Ivec, Data) ->
+ Key = check_des3_key(Key0),
+ block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, false);
block_decrypt(aes_ige256, Key, Ivec, Data) ->
- aes_ige_256_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cfb8, Key, Ivec, Data) ->
- aes_cfb_8_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cfb128, Key, Ivec, Data) ->
- aes_cfb_128_decrypt(Key, Ivec, Data);
+ notsup_to_error(aes_ige_crypt_nif(Key, Ivec, Data, false));
block_decrypt(aes_gcm, Key, Ivec, {AAD, Data, Tag}) ->
- case aes_gcm_decrypt(Key, Ivec, AAD, Data, Tag) of
- notsup -> erlang:error(notsup);
- Return -> Return
- end;
+ aes_gcm_decrypt(Key, Ivec, AAD, Data, Tag);
block_decrypt(chacha20_poly1305, Key, Ivec, {AAD, Data, Tag}) ->
- case chacha20_poly1305_decrypt(Key, Ivec, AAD, Data, Tag) of
- notsup -> erlang:error(notsup);
- Return -> Return
- end;
-block_decrypt(rc2_cbc, Key, Ivec, Data) ->
- rc2_cbc_decrypt(Key, Ivec, Data).
+ chacha20_poly1305_decrypt(Key, Ivec, AAD, Data, Tag).
-spec block_encrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary().
-block_encrypt(des_ecb, Key, Data) ->
- des_ecb_encrypt(Key, Data);
-block_encrypt(blowfish_ecb, Key, Data) ->
- blowfish_ecb_encrypt(Key, Data);
-block_encrypt(aes_ecb, Key, Data) ->
- aes_ecb_encrypt(Key, Data).
+block_encrypt(Type, Key, Data) ->
+ block_crypt_nif(Type, Key, Data, true).
-spec block_decrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary().
-block_decrypt(des_ecb, Key, Data) ->
- des_ecb_decrypt(Key, Data);
-block_decrypt(blowfish_ecb, Key, Data) ->
- blowfish_ecb_decrypt(Key, Data);
-block_decrypt(aes_ecb, Key, Data) ->
- aes_ecb_decrypt(Key, Data).
+block_decrypt(Type, Key, Data) ->
+ block_crypt_nif(Type, Key, Data, false).
-spec next_iv(des_cbc | des3_cbc | aes_cbc | aes_ige, Data::iodata()) -> binary().
-next_iv(des_cbc, Data) ->
- des_cbc_ivec(Data);
-next_iv(des3_cbc, Data) ->
- des_cbc_ivec(Data);
-next_iv(aes_cbc, Data) ->
- aes_cbc_ivec(Data);
-next_iv(aes_ige, Data) ->
- aes_ige_ivec(Data).
+next_iv(Type, Data) when is_binary(Data) ->
+ IVecSize = case Type of
+ des_cbc -> 8;
+ des3_cbc -> 8;
+ aes_cbc -> 16;
+ aes_ige -> 32
+ end,
+ {_, IVec} = split_binary(Data, size(Data) - IVecSize),
+ IVec;
+next_iv(Type, Data) when is_list(Data) ->
+ next_iv(Type, list_to_binary(Data)).
-spec next_iv(des_cfb, Data::iodata(), Ivec::binary()) -> binary().
-next_iv(des_cfb, Data, Ivec) ->
- des_cfb_ivec(Ivec, Data);
+next_iv(des_cfb, Data, IVec) ->
+ IVecAndData = list_to_binary([IVec, Data]),
+ {_, NewIVec} = split_binary(IVecAndData, byte_size(IVecAndData) - 8),
+ NewIVec;
next_iv(Type, Data, _Ivec) ->
next_iv(Type, Data).
stream_init(aes_ctr, Key, Ivec) ->
{aes_ctr, aes_ctr_stream_init(Key, Ivec)}.
stream_init(rc4, Key) ->
- {rc4, rc4_set_key(Key)}.
+ {rc4, notsup_to_error(rc4_set_key(Key))}.
stream_encrypt(State, Data0) ->
Data = iolist_to_binary(Data0),
@@ -485,35 +452,31 @@ verify(dss, none, Data, Signature, Key) when is_binary(Data) ->
verify(dss, sha, {digest, Data}, Signature, Key);
verify(Alg, Type, Data, Signature, Key) when is_binary(Data) ->
verify(Alg, Type, {digest, hash(Type, Data)}, Signature, Key);
-verify(dss, Type, Data, Signature, Key) ->
- dss_verify_nif(Type, Data, Signature, map_ensure_int_as_bin(Key));
-verify(rsa, Type, DataOrDigest, Signature, Key) ->
- case rsa_verify_nif(Type, DataOrDigest, Signature, map_ensure_int_as_bin(Key)) of
- notsup -> erlang:error(notsup);
- Bool -> Bool
- end;
-verify(ecdsa, Type, DataOrDigest, Signature, [Key, Curve]) ->
- case ecdsa_verify_nif(Type, DataOrDigest, Signature, nif_curve_params(Curve), ensure_int_as_bin(Key)) of
- notsup -> erlang:error(notsup);
- Bool -> Bool
- end.
+verify(dss, Type, {digest, Digest}, Signature, Key) ->
+ dss_verify_nif(Type, Digest, Signature, map_ensure_int_as_bin(Key));
+verify(rsa, Type, {digest, Digest}, Signature, Key) ->
+ notsup_to_error(
+ rsa_verify_nif(Type, Digest, Signature, map_ensure_int_as_bin(Key)));
+verify(ecdsa, Type, {digest, Digest}, Signature, [Key, Curve]) ->
+ notsup_to_error(
+ ecdsa_verify_nif(Type, Digest, Signature, nif_curve_params(Curve), ensure_int_as_bin(Key))).
sign(dss, none, Data, Key) when is_binary(Data) ->
sign(dss, sha, {digest, Data}, Key);
sign(Alg, Type, Data, Key) when is_binary(Data) ->
sign(Alg, Type, {digest, hash(Type, Data)}, Key);
-sign(rsa, Type, DataOrDigest, Key) ->
- case rsa_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [Type,DataOrDigest,Key]);
+sign(rsa, Type, {digest, Digest}, Key) ->
+ case rsa_sign_nif(Type, Digest, map_ensure_int_as_bin(Key)) of
+ error -> erlang:error(badkey, [Type,Digest,Key]);
Sign -> Sign
end;
-sign(dss, Type, DataOrDigest, Key) ->
- case dss_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [DataOrDigest, Key]);
+sign(dss, Type, {digest, Digest}, Key) ->
+ case dss_sign_nif(Type, Digest, map_ensure_int_as_bin(Key)) of
+ error -> erlang:error(badkey, [Digest, Key]);
Sign -> Sign
end;
-sign(ecdsa, Type, DataOrDigest, [Key, Curve]) ->
- case ecdsa_sign_nif(Type, DataOrDigest, nif_curve_params(Curve), ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [Type,DataOrDigest,Key]);
+sign(ecdsa, Type, {digest, Digest}, [Key, Curve]) ->
+ case ecdsa_sign_nif(Type, Digest, nif_curve_params(Curve), ensure_int_as_bin(Key)) of
+ error -> erlang:error(badkey, [Type,Digest,Key]);
Sign -> Sign
end.
@@ -618,8 +581,9 @@ compute_key(srp, HostPublic, {UserPublic, UserPrivate},
HostPubBin, Prime);
[S] -> S
end,
+ notsup_to_error(
srp_user_secret_nif(ensure_int_as_bin(UserPrivate), Scrambler, HostPubBin,
- Multiplier, Generator, DerivedKey, Prime);
+ Multiplier, Generator, DerivedKey, Prime));
compute_key(srp, UserPublic, {HostPublic, HostPrivate},
{host,[Verifier, Prime, Version | ScramblerArg]}) when
@@ -631,8 +595,9 @@ compute_key(srp, UserPublic, {HostPublic, HostPrivate},
[] -> srp_scrambler(Version, UserPubBin, ensure_int_as_bin(HostPublic), Prime);
[S] -> S
end,
+ notsup_to_error(
srp_host_secret_nif(Verifier, ensure_int_as_bin(HostPrivate), Scrambler,
- UserPubBin, Prime);
+ UserPubBin, Prime));
compute_key(ecdh, Others, My, Curve) ->
ecdh_compute_key_nif(ensure_int_as_bin(Others),
@@ -677,7 +642,8 @@ on_load() ->
end
end,
Lib = filename:join([PrivDir, "lib", LibName]),
- Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,path2bin(Lib)}) of
+ LibBin = path2bin(Lib),
+ Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,LibBin}) of
ok -> ok;
{error, {load_failed, _}}=Error1 ->
ArchLibDir =
@@ -689,7 +655,8 @@ on_load() ->
[] -> Error1;
_ ->
ArchLib = filename:join([ArchLibDir, LibName]),
- erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,path2bin(ArchLib)})
+ ArchBin = path2bin(ArchLib),
+ erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,ArchBin})
end;
Error1 -> Error1
end,
@@ -714,46 +681,30 @@ path2bin(Path) when is_list(Path) ->
max_bytes() ->
?MAX_BYTES_TO_NIF.
+notsup_to_error(notsup) ->
+ erlang:error(notsup);
+notsup_to_error(Other) ->
+ Other.
+
%% HASH --------------------------------------------------------------------
-hash(Hash, Data, Size, Max, initial) when Size =< Max ->
- do_hash(Hash, Data);
-hash(State0, Data, Size, Max, continue) when Size =< Max ->
- State = do_hash_update(State0, Data),
- hash_final(State);
-hash(Hash, Data, _Size, Max, initial) ->
- <<Increment:Max/binary, Rest/binary>> = Data,
+hash(Hash, Data, Size, Max) when Size =< Max ->
+ notsup_to_error(hash_nif(Hash, Data));
+hash(Hash, Data, Size, Max) ->
State0 = hash_init(Hash),
- State = do_hash_update(State0, Increment),
- hash(State, Rest, erlang:byte_size(Rest), max_bytes(), continue);
-hash(State0, Data, _Size, MaxByts, continue) ->
- <<Increment:MaxByts/binary, Rest/binary>> = Data,
- State = do_hash_update(State0, Increment),
- hash(State, Rest, erlang:byte_size(Rest), max_bytes(), continue).
-
-do_hash(md5, Data) -> md5(Data);
-do_hash(md4, Data) -> md4(Data);
-do_hash(sha, Data) -> sha(Data);
-do_hash(ripemd160, Data) -> ripemd160(Data);
-do_hash(sha224, Data) -> sha224(Data);
-do_hash(sha256, Data) -> sha256(Data);
-do_hash(sha384, Data) -> sha384(Data);
-do_hash(sha512, Data) -> sha512(Data).
+ State1 = hash_update(State0, Data, Size, Max),
+ hash_final(State1).
hash_update(State, Data, Size, MaxBytes) when Size =< MaxBytes ->
- do_hash_update(State, Data);
+ notsup_to_error(hash_update_nif(State, Data));
hash_update(State0, Data, _, MaxBytes) ->
<<Increment:MaxBytes/binary, Rest/binary>> = Data,
- State = do_hash_update(State0, Increment),
+ State = notsup_to_error(hash_update_nif(State0, Increment)),
hash_update(State, Rest, erlang:byte_size(Rest), MaxBytes).
-do_hash_update({md5,Context}, Data) -> {md5, md5_update(Context,Data)};
-do_hash_update({md4,Context}, Data) -> {md4, md4_update(Context,Data)};
-do_hash_update({sha,Context}, Data) -> {sha, sha_update(Context,Data)};
-do_hash_update({ripemd160,Context}, Data) -> {ripemd160, ripemd160_update(Context,Data)};
-do_hash_update({sha224,Context}, Data) -> {sha224, sha224_update(Context,Data)};
-do_hash_update({sha256,Context}, Data) -> {sha256, sha256_update(Context,Data)};
-do_hash_update({sha384,Context}, Data) -> {sha384, sha384_update(Context,Data)};
-do_hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data)}.
+hash_nif(_Hash, _Data) -> ?nif_stub.
+hash_init_nif(_Hash) -> ?nif_stub.
+hash_update_nif(_State, _Data) -> ?nif_stub.
+hash_final_nif(_State) -> ?nif_stub.
%%
@@ -765,10 +716,14 @@ do_hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data
-spec md5_update(binary(), iodata()) -> binary().
-spec md5_final(binary()) -> binary().
-md5(_Data) -> ?nif_stub.
-md5_init() -> ?nif_stub.
-md5_update(_Context, _Data) -> ?nif_stub.
-md5_final(_Context) -> ?nif_stub.
+md5(Data) ->
+ hash(md5, Data).
+md5_init() ->
+ hash_init(md5).
+md5_update(Context, Data) ->
+ hash_update(Context, Data).
+md5_final(Context) ->
+ hash_final(Context).
%%
%% MD4
@@ -778,24 +733,14 @@ md5_final(_Context) -> ?nif_stub.
-spec md4_update(binary(), iodata()) -> binary().
-spec md4_final(binary()) -> binary().
-md4(_Data) -> ?nif_stub.
-md4_init() -> ?nif_stub.
-md4_update(_Context, _Data) -> ?nif_stub.
-md4_final(_Context) -> ?nif_stub.
-
-%%
-%% RIPEMD160
-%%
-
--spec ripemd160(iodata()) -> binary().
--spec ripemd160_init() -> binary().
--spec ripemd160_update(binary(), iodata()) -> binary().
--spec ripemd160_final(binary()) -> binary().
-
-ripemd160(_Data) -> ?nif_stub.
-ripemd160_init() -> ?nif_stub.
-ripemd160_update(_Context, _Data) -> ?nif_stub.
-ripemd160_final(_Context) -> ?nif_stub.
+md4(Data) ->
+ hash(md4, Data).
+md4_init() ->
+ hash_init(md4).
+md4_update(Context, Data) ->
+ hash_update(Context, Data).
+md4_final(Context) ->
+ hash_final(Context).
%%
%% SHA
@@ -805,196 +750,44 @@ ripemd160_final(_Context) -> ?nif_stub.
-spec sha_update(binary(), iodata()) -> binary().
-spec sha_final(binary()) -> binary().
-sha(_Data) -> ?nif_stub.
-sha_init() -> ?nif_stub.
-sha_update(_Context, _Data) -> ?nif_stub.
-sha_final(_Context) -> ?nif_stub.
-
-%
-%% SHA224
-%%
--spec sha224(iodata()) -> binary().
--spec sha224_init() -> binary().
--spec sha224_update(binary(), iodata()) -> binary().
--spec sha224_final(binary()) -> binary().
-
-sha224(Data) ->
- case sha224_nif(Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha224_init() ->
- case sha224_init_nif() of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha224_update(Context, Data) ->
- case sha224_update_nif(Context, Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha224_final(Context) ->
- case sha224_final_nif(Context) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha224_nif(_Data) -> ?nif_stub.
-sha224_init_nif() -> ?nif_stub.
-sha224_update_nif(_Context, _Data) -> ?nif_stub.
-sha224_final_nif(_Context) -> ?nif_stub.
-
-%
-%% SHA256
-%%
--spec sha256(iodata()) -> binary().
--spec sha256_init() -> binary().
--spec sha256_update(binary(), iodata()) -> binary().
--spec sha256_final(binary()) -> binary().
-
-sha256(Data) ->
- case sha256_nif(Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha256_init() ->
- case sha256_init_nif() of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha256_update(Context, Data) ->
- case sha256_update_nif(Context, Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha256_final(Context) ->
- case sha256_final_nif(Context) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha256_nif(_Data) -> ?nif_stub.
-sha256_init_nif() -> ?nif_stub.
-sha256_update_nif(_Context, _Data) -> ?nif_stub.
-sha256_final_nif(_Context) -> ?nif_stub.
-
-%
-%% SHA384
-%%
--spec sha384(iodata()) -> binary().
--spec sha384_init() -> binary().
--spec sha384_update(binary(), iodata()) -> binary().
--spec sha384_final(binary()) -> binary().
-
-sha384(Data) ->
- case sha384_nif(Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha384_init() ->
- case sha384_init_nif() of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha384_update(Context, Data) ->
- case sha384_update_nif(Context, Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha384_final(Context) ->
- case sha384_final_nif(Context) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha384_nif(_Data) -> ?nif_stub.
-sha384_init_nif() -> ?nif_stub.
-sha384_update_nif(_Context, _Data) -> ?nif_stub.
-sha384_final_nif(_Context) -> ?nif_stub.
-
-%
-%% SHA512
-%%
--spec sha512(iodata()) -> binary().
--spec sha512_init() -> binary().
--spec sha512_update(binary(), iodata()) -> binary().
--spec sha512_final(binary()) -> binary().
-
-sha512(Data) ->
- case sha512_nif(Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha512_init() ->
- case sha512_init_nif() of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha512_update(Context, Data) ->
- case sha512_update_nif(Context, Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha512_final(Context) ->
- case sha512_final_nif(Context) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha512_nif(_Data) -> ?nif_stub.
-sha512_init_nif() -> ?nif_stub.
-sha512_update_nif(_Context, _Data) -> ?nif_stub.
-sha512_final_nif(_Context) -> ?nif_stub.
+sha(Data) ->
+ hash(sha, Data).
+sha_init() ->
+ hash_init(sha).
+sha_update(Context, Data) ->
+ hash_update(Context, Data).
+sha_final(Context) ->
+ hash_final(Context).
%% HMAC --------------------------------------------------------------------
-hmac(Type, Key, Data, MacSize, Size, MaxBytes, initial) when Size =< MaxBytes ->
+hmac(Type, Key, Data, MacSize, Size, MaxBytes) when Size =< MaxBytes ->
+ notsup_to_error(
case MacSize of
- undefined ->
- do_hmac(Type, Key, Data);
- _ ->
- do_hmac(Type, Key, Data, MacSize)
- end;
-hmac(Type, Key, Data, MacSize, _, MaxBytes, initial) ->
- <<Increment:MaxBytes/binary, Rest/binary>> = Data,
+ undefined -> hmac_nif(Type, Key, Data);
+ _ -> hmac_nif(Type, Key, Data, MacSize)
+ end);
+hmac(Type, Key, Data, MacSize, Size, MaxBytes) ->
State0 = hmac_init(Type, Key),
- State = hmac_update(State0, Increment),
- hmac(State, Rest, MacSize, erlang:byte_size(Rest), max_bytes(), continue).
-hmac(State0, Data, MacSize, Size, MaxBytes, continue) when Size =< MaxBytes ->
- State = hmac_update(State0, Data),
+ State1 = hmac_update(State0, Data, Size, MaxBytes),
case MacSize of
- undefined ->
- hmac_final(State);
- _ ->
- hmac_final_n(State, MacSize)
- end;
-hmac(State0, Data, MacSize, _Size, MaxBytes, continue) ->
- <<Increment:MaxBytes/binary, Rest/binary>> = Data,
- State = hmac_update(State0, Increment),
- hmac(State, Rest, MacSize, erlang:byte_size(Rest), max_bytes(), continue).
+ undefined -> hmac_final(State1);
+ _ -> hmac_final_n(State1, MacSize)
+ end.
hmac_update(State, Data, Size, MaxBytes) when Size =< MaxBytes ->
- do_hmac_update(State, Data);
+ notsup_to_error(hmac_update_nif(State, Data));
hmac_update(State0, Data, _, MaxBytes) ->
<<Increment:MaxBytes/binary, Rest/binary>> = Data,
- State = do_hmac_update(State0, Increment),
+ State = notsup_to_error(hmac_update_nif(State0, Increment)),
hmac_update(State, Rest, erlang:byte_size(Rest), MaxBytes).
-do_hmac(md5, Key, Data) -> md5_mac(Key, Data);
-do_hmac(sha, Key, Data) -> sha_mac(Key, Data);
-do_hmac(sha224, Key, Data) -> sha224_mac(Key, Data);
-do_hmac(sha256, Key, Data) -> sha256_mac(Key, Data);
-do_hmac(sha384, Key, Data) -> sha384_mac(Key, Data);
-do_hmac(sha512, Key, Data) -> sha512_mac(Key, Data).
-
-do_hmac(md5, Key, Data, Size) -> md5_mac_n(Key, Data, Size);
-do_hmac(sha, Key, Data, Size) -> sha_mac_n(Key, Data, Size);
-do_hmac(sha224, Key, Data, Size) -> sha224_mac(Key, Data, Size);
-do_hmac(sha256, Key, Data, Size) -> sha256_mac(Key, Data, Size);
-do_hmac(sha384, Key, Data, Size) -> sha384_mac(Key, Data, Size);
-do_hmac(sha512, Key, Data, Size) -> sha512_mac(Key, Data, Size).
-
-do_hmac_update(_Context, _Data) -> ? nif_stub.
+hmac_nif(_Type, _Key, _Data) -> ?nif_stub.
+hmac_nif(_Type, _Key, _Data, _MacSize) -> ?nif_stub.
+hmac_init_nif(_Type, _Key) -> ?nif_stub.
+hmac_update_nif(_Context, _Data) -> ?nif_stub.
+hmac_final_nif(_Context) -> ?nif_stub.
+hmac_final_nif(_Context, _MacSize) -> ?nif_stub.
%%
%% MD5_MAC
@@ -1002,97 +795,37 @@ do_hmac_update(_Context, _Data) -> ? nif_stub.
-spec md5_mac(iodata(), iodata()) -> binary().
-spec md5_mac_96(iodata(), iodata()) -> binary().
-md5_mac(Key, Data) ->
- md5_mac_n(Key,Data,16).
+md5_mac(Key, Data) -> hmac(md5, Key, Data).
-md5_mac_96(Key, Data) ->
- md5_mac_n(Key,Data,12).
+md5_mac_96(Key, Data) -> hmac(md5, Key, Data, 12).
-md5_mac_n(_Key,_Data,_MacSz) -> ?nif_stub.
-
%%
%% SHA_MAC
%%
-spec sha_mac(iodata(), iodata()) -> binary().
-spec sha_mac_96(iodata(), iodata()) -> binary().
-sha_mac(Key, Data) ->
- sha_mac_n(Key,Data,20).
-
-sha_mac(Key, Data, Size) ->
- sha_mac_n(Key, Data, Size).
+sha_mac(Key, Data) -> hmac(sha, Key, Data).
-sha_mac_96(Key, Data) ->
- sha_mac_n(Key,Data,12).
-
-sha_mac_n(_Key,_Data,_MacSz) -> ?nif_stub.
-
-%%
-%% SHA224_MAC
-%%
--spec sha224_mac(iodata(), iodata()) -> binary().
+sha_mac(Key, Data, Size) -> hmac(sha, Key, Data, Size).
-sha224_mac(Key, Data) ->
- sha224_mac(Key, Data, 224 div 8).
+sha_mac_96(Key, Data) -> hmac(sha, Key, Data, 12).
-sha224_mac(Key, Data, Size) ->
- case sha224_mac_nif(Key, Data, Size) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha224_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
-
-%%
-%% SHA256_MAC
-%%
--spec sha256_mac(iodata(), iodata()) -> binary().
-
-sha256_mac(Key, Data) ->
- sha256_mac(Key, Data, 256 div 8).
-
-sha256_mac(Key, Data, Size) ->
- case sha256_mac_nif(Key, Data, Size) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha256_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
-
-%%
-%% SHA384_MAC
-%%
--spec sha384_mac(iodata(), iodata()) -> binary().
-
-sha384_mac(Key, Data) ->
- sha384_mac(Key, Data, 384 div 8).
-
-sha384_mac(Key, Data, Size) ->
- case sha384_mac_nif(Key, Data, Size) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha384_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
-
-%%
-%% SHA512_MAC
-%%
--spec sha512_mac(iodata(), iodata()) -> binary().
-
-sha512_mac(Key, Data) ->
- sha512_mac(Key, Data, 512 div 8).
+%% CIPHERS --------------------------------------------------------------------
-sha512_mac(Key, Data, MacSz) ->
- case sha512_mac_nif(Key, Data, MacSz) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
+block_crypt_nif(_Type, _Key, _Ivec, _Text, _IsEncrypt) -> ?nif_stub.
+block_crypt_nif(_Type, _Key, _Text, _IsEncrypt) -> ?nif_stub.
+
+check_des3_key(Key) ->
+ case lists:map(fun erlang:iolist_to_binary/1, Key) of
+ ValidKey = [B1, B2, B3] when byte_size(B1) =:= 8,
+ byte_size(B2) =:= 8,
+ byte_size(B3) =:= 8 ->
+ ValidKey;
+ _ ->
+ error(badarg)
end.
-sha512_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
-
-%% CIPHERS --------------------------------------------------------------------
-
%%
%% DES - in electronic codebook mode (ECB)
%%
@@ -1100,10 +833,9 @@ sha512_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
-spec des_ecb_decrypt(iodata(), iodata()) -> binary().
des_ecb_encrypt(Key, Data) ->
- des_ecb_crypt(Key, Data, true).
+ block_encrypt(des_ecb, Key, Data).
des_ecb_decrypt(Key, Data) ->
- des_ecb_crypt(Key, Data, false).
-des_ecb_crypt(_Key, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(des_ecb, Key, Data).
%%
%% DES3 - in cipher block chaining mode (CBC)
@@ -1114,16 +846,14 @@ des_ecb_crypt(_Key, _Data, _IsEncrypt) -> ?nif_stub.
binary().
des3_cbc_encrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, true).
+ block_encrypt(des3_cbc, [Key1, Key2, Key3], IVec, Data).
des_ede3_cbc_encrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, true).
+ block_encrypt(des_ede3, [Key1, Key2, Key3], IVec, Data).
des3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, false).
+ block_decrypt(des3_cbc, [Key1, Key2, Key3], IVec, Data).
des_ede3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, false).
-
-des_ede3_cbc_crypt(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(des_ede3, [Key1, Key2, Key3], IVec, Data).
%%
%% DES3 - in 8-bits cipher feedback mode (CFB)
@@ -1134,18 +864,10 @@ des_ede3_cbc_crypt(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
binary().
des3_cfb_encrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cfb_crypt(Key1, Key2, Key3, IVec, Data, true).
+ block_encrypt(des3_cbf, [Key1, Key2, Key3], IVec, Data).
des3_cfb_decrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cfb_crypt(Key1, Key2, Key3, IVec, Data, false).
-
-des_ede3_cfb_crypt(Key1, Key2, Key3, IVec, Data, IsEncrypt) ->
- case des_ede3_cfb_crypt_nif(Key1,Key2,Key3,IVec,Data,IsEncrypt) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-des_ede3_cfb_crypt_nif(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(des3_cbf, [Key1, Key2, Key3], IVec, Data).
%%
%% Blowfish
@@ -1159,62 +881,38 @@ des_ede3_cfb_crypt_nif(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_st
-spec blowfish_ofb64_encrypt(iodata(), binary(), iodata()) -> binary().
blowfish_ecb_encrypt(Key, Data) ->
- bf_ecb_crypt(Key,Data, true).
+ block_encrypt(blowfish_ecb, Key, Data).
blowfish_ecb_decrypt(Key, Data) ->
- bf_ecb_crypt(Key,Data, false).
-
-bf_ecb_crypt(_Key,_Data,_IsEncrypt) -> ?nif_stub.
+ block_decrypt(blowfish_ecb, Key, Data).
blowfish_cbc_encrypt(Key, IVec, Data) ->
- bf_cbc_crypt(Key,IVec,Data,true).
+ block_encrypt(blowfish_cbc, Key, IVec, Data).
blowfish_cbc_decrypt(Key, IVec, Data) ->
- bf_cbc_crypt(Key,IVec,Data,false).
-
-bf_cbc_crypt(_Key,_IVec,_Data,_IsEncrypt) -> ?nif_stub.
+ block_decrypt(blowfish_cbc, Key, IVec, Data).
blowfish_cfb64_encrypt(Key, IVec, Data) ->
- bf_cfb64_crypt(Key, IVec, Data, true).
+ block_encrypt(blowfish_cfb64, Key, IVec, Data).
blowfish_cfb64_decrypt(Key, IVec, Data) ->
- bf_cfb64_crypt(Key, IVec, Data, false).
-
-bf_cfb64_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-
-blowfish_ofb64_decrypt(Key, Ivec, Data) ->
- blowfish_ofb64_encrypt(Key, Ivec, Data).
+ block_decrypt(blowfish_cfb64, Key, IVec, Data).
-blowfish_ofb64_encrypt(_Key, _IVec, _Data) -> ?nif_stub.
+blowfish_ofb64_encrypt(Key, IVec, Data) ->
+ block_encrypt(blowfish_ofb64, Key, IVec, Data).
%%
-%% AES in cipher feedback mode (CFB) - 8 bit shift
-%%
--spec aes_cfb_8_encrypt(iodata(), binary(), iodata()) -> binary().
--spec aes_cfb_8_decrypt(iodata(), binary(), iodata()) -> binary().
-
-aes_cfb_8_encrypt(Key, IVec, Data) ->
- aes_cfb_8_crypt(Key, IVec, Data, true).
-
-aes_cfb_8_decrypt(Key, IVec, Data) ->
- aes_cfb_8_crypt(Key, IVec, Data, false).
-
-aes_cfb_8_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-
-%%
%% AES in cipher feedback mode (CFB) - 128 bit shift
%%
-spec aes_cfb_128_encrypt(iodata(), binary(), iodata()) -> binary().
-spec aes_cfb_128_decrypt(iodata(), binary(), iodata()) -> binary().
aes_cfb_128_encrypt(Key, IVec, Data) ->
- aes_cfb_128_crypt(Key, IVec, Data, true).
+ block_encrypt(aes_cfb128, Key, IVec, Data).
aes_cfb_128_decrypt(Key, IVec, Data) ->
- aes_cfb_128_crypt(Key, IVec, Data, false).
-
-aes_cfb_128_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(aes_cfb128, Key, IVec, Data).
%%
%% AES - in Galois/Counter Mode (GCM)
@@ -1235,12 +933,10 @@ chacha20_poly1305_decrypt(_Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
-spec des_cbc_decrypt(iodata(), binary(), iodata()) -> binary().
des_cbc_encrypt(Key, IVec, Data) ->
- des_cbc_crypt(Key, IVec, Data, true).
+ block_encrypt(des_cbc, Key, IVec, Data).
des_cbc_decrypt(Key, IVec, Data) ->
- des_cbc_crypt(Key, IVec, Data, false).
-
-des_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(des_cbc, Key, IVec, Data).
%%
%% dec_cbc_ivec(Data) -> binary()
@@ -1250,11 +946,8 @@ des_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
%%
-spec des_cbc_ivec(iodata()) -> binary().
-des_cbc_ivec(Data) when is_binary(Data) ->
- {_, IVec} = split_binary(Data, size(Data) - 8),
- IVec;
-des_cbc_ivec(Data) when is_list(Data) ->
- des_cbc_ivec(list_to_binary(Data)).
+des_cbc_ivec(Data) ->
+ next_iv(des_cbc, Data).
%%
%% DES - in 8-bits cipher feedback mode (CFB)
@@ -1263,12 +956,10 @@ des_cbc_ivec(Data) when is_list(Data) ->
-spec des_cfb_decrypt(iodata(), binary(), iodata()) -> binary().
des_cfb_encrypt(Key, IVec, Data) ->
- des_cfb_crypt(Key, IVec, Data, true).
+ block_encrypt(des_cfb, Key, IVec, Data).
des_cfb_decrypt(Key, IVec, Data) ->
- des_cfb_crypt(Key, IVec, Data, false).
-
-des_cfb_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(des_cfb, Key, IVec, Data).
%%
%% dec_cfb_ivec(IVec, Data) -> binary()
@@ -1280,9 +971,7 @@ des_cfb_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-spec des_cfb_ivec(iodata(), iodata()) -> binary().
des_cfb_ivec(IVec, Data) ->
- IVecAndData = list_to_binary([IVec, Data]),
- {_, NewIVec} = split_binary(IVecAndData, byte_size(IVecAndData) - 8),
- NewIVec.
+ next_iv(des_cfb, Data, IVec).
%%
@@ -1298,18 +987,16 @@ des_cfb_ivec(IVec, Data) ->
binary().
aes_cbc_128_encrypt(Key, IVec, Data) ->
- aes_cbc_crypt(Key, IVec, Data, true).
+ block_encrypt(aes_cbc128, Key, IVec, Data).
aes_cbc_128_decrypt(Key, IVec, Data) ->
- aes_cbc_crypt(Key, IVec, Data, false).
+ block_decrypt(aes_cbc128, Key, IVec, Data).
aes_cbc_256_encrypt(Key, IVec, Data) ->
- aes_cbc_crypt(Key, IVec, Data, true).
+ block_encrypt(aes_cbc256, Key, IVec, Data).
aes_cbc_256_decrypt(Key, IVec, Data) ->
- aes_cbc_crypt(Key, IVec, Data, false).
-
-aes_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(aes_cbc256, Key, IVec, Data).
%%
%% aes_cbc_ivec(Data) -> binary()
@@ -1318,47 +1005,15 @@ aes_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
%% aes_cbc_*_[encrypt|decrypt].
%% IVec size: 16 bytes
%%
-aes_cbc_ivec(Data) when is_binary(Data) ->
- {_, IVec} = split_binary(Data, size(Data) - 16),
- IVec;
-aes_cbc_ivec(Data) when is_list(Data) ->
- aes_cbc_ivec(list_to_binary(Data)).
-
+aes_cbc_ivec(Data) ->
+ next_iv(aes_cbc, Data).
%%
%% AES - with 256 bit key in infinite garble extension mode (IGE)
%%
--spec aes_ige_256_decrypt(iodata(), binary(), iodata()) ->
- binary().
-
-aes_ige_256_encrypt(Key, IVec, Data) ->
- aes_ige_crypt(Key, IVec, Data, true).
-
-aes_ige_256_decrypt(Key, IVec, Data) ->
- aes_ige_crypt(Key, IVec, Data, false).
-
-aes_ige_crypt(Key, IVec, Data, IsEncrypt) ->
- case aes_ige_crypt_nif(Key,IVec,Data,IsEncrypt) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
aes_ige_crypt_nif(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-%%
-%% aes_ige_ivec(Data) -> binary()
-%%
-%% Returns the IVec to be used in the next iteration of
-%% aes_ige_*_[encrypt|decrypt].
-%% IVec size: 32 bytes
-%%
-aes_ige_ivec(Data) when is_binary(Data) ->
- {_, IVec} = split_binary(Data, size(Data) - 32),
- IVec;
-aes_ige_ivec(Data) when is_list(Data) ->
- aes_ige_ivec(list_to_binary(Data)).
-
%% Stream ciphers --------------------------------------------------------------------
@@ -1397,22 +1052,11 @@ do_stream_decrypt({rc4, State0}, Data) ->
aes_ctr_encrypt(_Key, _IVec, _Data) -> ?nif_stub.
aes_ctr_decrypt(_Key, _IVec, _Cipher) -> ?nif_stub.
-%%
-%% AES - in electronic codebook mode (ECB)
-%%
-aes_ecb_encrypt(Key, Data) ->
- aes_ecb_crypt(Key, Data, true).
-
-aes_ecb_decrypt(Key, Data) ->
- aes_ecb_crypt(Key, Data, false).
-
-aes_ecb_crypt(_Key, __Data, _IsEncrypt) -> ?nif_stub.
-
%%
%% AES - in counter mode (CTR) with state maintained for multi-call streaming
%%
--type ctr_state() :: { iodata(), binary(), binary(), integer() }.
+-type ctr_state() :: { iodata(), binary(), binary(), integer() } | binary().
-spec aes_ctr_stream_init(iodata(), binary()) -> ctr_state().
-spec aes_ctr_stream_encrypt(ctr_state(), binary()) ->
@@ -1420,10 +1064,9 @@ aes_ecb_crypt(_Key, __Data, _IsEncrypt) -> ?nif_stub.
-spec aes_ctr_stream_decrypt(ctr_state(), binary()) ->
{ ctr_state(), binary() }.
-aes_ctr_stream_init(Key, IVec) ->
- {Key, IVec, << 0:128 >>, 0}.
-aes_ctr_stream_encrypt({_Key, _IVec, _ECount, _Num}=_State, _Data) -> ?nif_stub.
-aes_ctr_stream_decrypt({_Key, _IVec, _ECount, _Num}=_State, _Cipher) -> ?nif_stub.
+aes_ctr_stream_init(_Key, _IVec) -> ?nif_stub.
+aes_ctr_stream_encrypt(_State, _Data) -> ?nif_stub.
+aes_ctr_stream_decrypt(_State, _Cipher) -> ?nif_stub.
%%
%% RC4 - symmetric stream cipher
@@ -1438,21 +1081,19 @@ rc4_encrypt_with_state(_State, _Data) -> ?nif_stub.
%% RC2 block cipher
rc2_cbc_encrypt(Key, IVec, Data) ->
- rc2_cbc_crypt(Key,IVec,Data,true).
+ block_encrypt(rc2_cbc, Key, IVec, Data).
rc2_cbc_decrypt(Key, IVec, Data) ->
- rc2_cbc_crypt(Key,IVec,Data,false).
-
-rc2_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(rc2_cbc, Key, IVec, Data).
%%
%% RC2 - 40 bits block cipher - Backwards compatibility not documented.
%%
rc2_40_cbc_encrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
- rc2_cbc_crypt(Key,IVec,Data,true).
+ block_encrypt(rc2_cbc, Key, IVec, Data).
rc2_40_cbc_decrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
- rc2_cbc_crypt(Key,IVec,Data,false).
+ block_decrypt(rc2_cbc, Key, IVec, Data).
%% Secure remote password -------------------------------------------------------------------
@@ -1470,16 +1111,18 @@ host_srp_gen_key(Private, Verifier, Generator, Prime, Version) ->
case srp_value_B_nif(Multiplier, Verifier, Generator, Private, Prime) of
error ->
error;
+ notsup ->
+ erlang:error(notsup);
Public ->
{Public, Private}
end.
srp_multiplier('6a', Generator, Prime) ->
%% k = SHA1(N | PAD(g)) from http://srp.stanford.edu/design.html
- C0 = sha_init(),
- C1 = sha_update(C0, Prime),
- C2 = sha_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)),
- sha_final(C2);
+ C0 = hash_init(sha),
+ C1 = hash_update(C0, Prime),
+ C2 = hash_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)),
+ hash_final(C2);
srp_multiplier('6', _, _) ->
<<3/integer>>;
srp_multiplier('3', _, _) ->
@@ -1488,10 +1131,10 @@ srp_multiplier('3', _, _) ->
srp_scrambler(Version, UserPublic, HostPublic, Prime) when Version == '6'; Version == '6a'->
%% SHA1(PAD(A) | PAD(B)) from http://srp.stanford.edu/design.html
PadLength = erlang:byte_size(Prime),
- C0 = sha_init(),
- C1 = sha_update(C0, srp_pad_to(PadLength, UserPublic)),
- C2 = sha_update(C1, srp_pad_to(PadLength, HostPublic)),
- sha_final(C2);
+ C0 = hash_init(sha),
+ C1 = hash_update(C0, srp_pad_to(PadLength, UserPublic)),
+ C2 = hash_update(C1, srp_pad_to(PadLength, HostPublic)),
+ hash_final(C2);
srp_scrambler('3', _, HostPublic, _Prime) ->
%% The parameter u is a 32-bit unsigned integer which takes its value
%% from the first 32 bits of the SHA1 hash of B, MSB first.
@@ -1515,13 +1158,13 @@ srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_s
%% Digital signatures --------------------------------------------------------------------
-rsa_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
-dss_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
-ecdsa_sign_nif(_Type, _DataOrDigest, _Curve, _Key) -> ?nif_stub.
+rsa_sign_nif(_Type,_Digest,_Key) -> ?nif_stub.
+dss_sign_nif(_Type,_Digest,_Key) -> ?nif_stub.
+ecdsa_sign_nif(_Type, _Digest, _Curve, _Key) -> ?nif_stub.
-dss_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
-rsa_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
-ecdsa_verify_nif(_Type, _DataOrDigest, _Signature, _Curve, _Key) -> ?nif_stub.
+dss_verify_nif(_Type, _Digest, _Signature, _Key) -> ?nif_stub.
+rsa_verify_nif(_Type, _Digest, _Signature, _Key) -> ?nif_stub.
+ecdsa_verify_nif(_Type, _Digest, _Signature, _Curve, _Key) -> ?nif_stub.
%% Public Keys --------------------------------------------------------------------
%% DH Diffie-Hellman functions
diff --git a/lib/crypto/test/Makefile b/lib/crypto/test/Makefile
index 07e5c1b754..928a1b1d73 100644
--- a/lib/crypto/test/Makefile
+++ b/lib/crypto/test/Makefile
@@ -28,7 +28,7 @@ RELSYSDIR = $(RELEASE_PATH)/crypto_test
# FLAGS
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_COMPILE_FLAGS +=
EBIN = .
MAKE_EMAKE = $(wildcard $(ERL_TOP)/make/make_emakefile)
diff --git a/lib/crypto/test/blowfish_SUITE.erl b/lib/crypto/test/blowfish_SUITE.erl
index b0d6954820..19f60450e9 100644
--- a/lib/crypto/test/blowfish_SUITE.erl
+++ b/lib/crypto/test/blowfish_SUITE.erl
@@ -24,8 +24,7 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
--include_lib("test_server/include/test_server.hrl").
--include("test_server_line.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(TIMEOUT, 120000). % 2 min
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 307fc4b019..f34d27649a 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -66,6 +66,7 @@ all() ->
{group, aes_ctr},
{group, aes_gcm},
{group, chacha20_poly1305},
+ {group, aes_cbc},
mod_pow,
exor,
rand_uniform
@@ -107,7 +108,8 @@ groups() ->
{rc4, [], [stream]},
{aes_ctr, [], [stream]},
{aes_gcm, [], [aead]},
- {chacha20_poly1305, [], [aead]}
+ {chacha20_poly1305, [], [aead]},
+ {aes_cbc, [], [block]}
].
%%-------------------------------------------------------------------
@@ -118,10 +120,10 @@ init_per_suite(Config) ->
_ ->
Config
catch error:low_entropy ->
- %% Make sure we are on OSE, otherwise we want to crash
- {ose,_} = os:type(),
+ %% We are testing on an OS with low entropy in its random
+ %% seed. So we have to seed it with a binary to get started.
- %% This is NOT how you want to seed this, it is just here
+ %% This is NOT how you want to do seeding, it is just here
%% to make the tests pass. Check your OS manual for how you
%% really want to seed.
{H,M,L} = erlang:now(),
@@ -363,6 +365,21 @@ block_cipher({Type, Key, IV, PlainText}) ->
ok;
Other ->
ct:fail({{crypto, block_decrypt, [Type, Key, IV, CipherText]}, {expected, Plain}, {got, Other}})
+ end;
+
+block_cipher({Type, Key, IV, PlainText, CipherText}) ->
+ Plain = iolist_to_binary(PlainText),
+ case crypto:block_encrypt(Type, Key, IV, Plain) of
+ CipherText ->
+ ok;
+ Other0 ->
+ ct:fail({{crypto, block_encrypt, [Type, Key, IV, Plain]}, {expected, CipherText}, {got, Other0}})
+ end,
+ case crypto:block_decrypt(Type, Key, IV, CipherText) of
+ Plain ->
+ ok;
+ Other1 ->
+ ct:fail({{crypto, block_decrypt, [Type, Key, IV, CipherText]}, {expected, Plain}, {got, Other1}})
end.
block_cipher_increment({Type, Key, IV, PlainTexts}) when Type == des_cbc;
@@ -370,7 +387,11 @@ block_cipher_increment({Type, Key, IV, PlainTexts}) when Type == des_cbc;
Type == aes_cbc;
Type == des_cbf
->
- block_cipher_increment(Type, Key, IV, IV, PlainTexts, iolist_to_binary(PlainTexts), []);
+ block_cipher_increment(Type, Key, IV, IV, PlainTexts, iolist_to_binary(PlainTexts), []);
+block_cipher_increment({Type, Key, IV, PlainTexts, _CipherText}) when Type == aes_cbc ->
+ Plain = iolist_to_binary(PlainTexts),
+ Blocks = [iolistify(Block) || << Block:128/bitstring >> <= Plain],
+ block_cipher_increment(Type, Key, IV, IV, Blocks, Plain, []);
block_cipher_increment({_Type, _, _, _}) ->
ok;
block_cipher_increment({_,_,_}) ->
@@ -552,7 +573,9 @@ do_block_iolistify({des_ede3 = Type, Key, IV, PlainText}) ->
do_block_iolistify({Type, Key, PlainText}) ->
{Type, iolistify(Key), iolistify(PlainText)};
do_block_iolistify({Type, Key, IV, PlainText}) ->
- {Type, iolistify(Key), IV, iolistify(PlainText)}.
+ {Type, iolistify(Key), IV, iolistify(PlainText)};
+do_block_iolistify({Type, Key, IV, PlainText, CipherText}) ->
+ {Type, iolistify(Key), IV, iolistify(PlainText), CipherText}.
iolistify(<<"Test With Truncation">>)->
%% Do not iolistify as it spoils this special case
@@ -803,6 +826,9 @@ group_config(aes_gcm, Config) ->
group_config(chacha20_poly1305, Config) ->
AEAD = chacha20_poly1305(),
[{aead, AEAD} | Config];
+group_config(aes_cbc, Config) ->
+ Block = aes_cbc(),
+ [{block, Block} | Config];
group_config(_, Config) ->
Config.
@@ -1166,6 +1192,50 @@ rc2_cbc() ->
<<72,91,135,182,25,42,35,210>>,
<<36,245,206,158,168,230,58,69,148,137,32,192,250,41,237,181,181,251, 192,2,175,135,177,171,57,30,111,117,159,149,15,28,88,158,28,81,28,115, 85,219,241,82,117,222,91,85,73,117,164,25,182,52,191,64,123,57,26,19, 211,27,253,31,194,219,231,104,247,240,172,130,119,21,225,154,101,247, 32,216,42,216,133,169,78,22,97,27,227,26,196,224,172,168,17,9,148,55, 203,91,252,40,61,226,236,221,215,160,78,63,13,181,68,57,196,241,185, 207, 116,129,152,237,60,139,247,153,27,146,161,246,222,98,185,222,152, 187,135, 236,86,34,7,110,91,230,173,34,160,242,202,222,121,127,181,140, 101,203,195, 190,88,250,86,147,127,87,72,126,171,16,71,47,110,248,88, 14,29,143,161,152, 129,236,148,22,152,186,208,119,70,8,174,193,203,100, 193,203,200,117,102,242, 134,142,96,125,135,200,217,190,76,117,50,70, 209,186,101,241,200,91,40,193,54, 90,195,38,47,59,197,38,234,86,223,16, 51,253,204,129,20,171,66,21,241,26,135,216, 196,114,110,91,15,53,40, 164,201,136,113,95,247,51,181,208,241,68,168,98,151,36, 155,72,24,57, 42,191,14,125,204,10,167,214,233,138,115,125,234,121,134,227,26,247, 77,200,117,110,117,111,168,156,206,67,159,149,189,173,150,193,91,199, 216,153,22, 189,137,185,89,160,13,131,132,58,109,28,110,246,252,251,14, 232,91,38,52,29,101,188,69,123,50,0,130,178,93,73,239,118,7,77,35,59, 253,10,159,45,86,142,37,78,232,48>>
}].
+
+%% AES CBC test vectors from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+aes_cbc() ->
+ [
+ %% F.2.1 CBC-AES128.Encrypt, F.2.2 CBC-AES128.Decrypt
+ {aes_cbc,
+ hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"), %% Key
+ hexstr2bin("000102030405060708090a0b0c0d0e0f"), %% IV
+ hexstr2bin("6bc1bee22e409f96e93d7e117393172a" %% PlainText
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710"),
+ hexstr2bin("7649abac8119b246cee98e9b12e9197d" %% CipherText
+ "5086cb9b507219ee95db113a917678b2"
+ "73bed6b8e3c1743b7116e69e22229516"
+ "3ff1caa1681fac09120eca307586e1a7")},
+ %% F.2.3 CBC-AES192.Encrypt, F.2.4 CBC-AES192.Decrypt
+ {aes_cbc,
+ hexstr2bin("8e73b0f7da0e6452c810f32b809079e5" %% Key
+ "62f8ead2522c6b7b"),
+ hexstr2bin("000102030405060708090a0b0c0d0e0f"), %% IV
+ hexstr2bin("6bc1bee22e409f96e93d7e117393172a" %% PlainText
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710"),
+ hexstr2bin("4f021db243bc633d7178183a9fa071e8" %% CipherText
+ "b4d9ada9ad7dedf4e5e738763f69145a"
+ "571b242012fb7ae07fa9baac3df102e0"
+ "08b0e27988598881d920a9e64f5615cd")},
+ %% F.2.5 CBC-AES256.Encrypt, F.2.6 CBC-AES256.Decrypt
+ {aes_cbc,
+ hexstr2bin("603deb1015ca71be2b73aef0857d7781" %% Key
+ "1f352c073b6108d72d9810a30914dff4"),
+ hexstr2bin("000102030405060708090a0b0c0d0e0f"), %% IV
+ hexstr2bin("6bc1bee22e409f96e93d7e117393172a" %% PlainText
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710"),
+ hexstr2bin("f58c4c04d6e5f1ba779eabfb5f7bfbd6" %% CipherText
+ "9cfc4e967edb808d679f777bc6702c7d"
+ "39f23369a9d9bacfa530e26304231461"
+ "b2eb05e2c39be9fcda6c19078c6a9d1b")}
+ ].
+
aes_cbc128() ->
[{aes_cbc128,
hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"),
@@ -1310,6 +1380,14 @@ aes_ecb() ->
"ae2d8a571e03ac9c9eb76fac45af8e51"
"30c81c46a35ce411e5fbc1191a0a52ef"
"f69f2445df4f9b17ad2b417be66c3710")},
+ %% F.1.3 ECB-AES192.Encrypt, F.1.4 ECB-AES192.Decrypt
+ {aes_ecb,
+ hexstr2bin("8e73b0f7da0e6452c810f32b809079e5"
+ "62f8ead2522c6b7b"),
+ hexstr2bin("6bc1bee22e409f96e93d7e117393172a"
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710")},
%% F.1.5 ECB-AES256.Encrypt, F.1.6 ECB-AES256.Decrypt
{aes_ecb,
hexstr2bin("603deb1015ca71be2b73aef0857d7781"
diff --git a/lib/crypto/test/old_crypto_SUITE.erl b/lib/crypto/test/old_crypto_SUITE.erl
index 1e7f3a1438..37cce2ebd2 100644
--- a/lib/crypto/test/old_crypto_SUITE.erl
+++ b/lib/crypto/test/old_crypto_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(old_crypto_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2,
init_per_testcase/2,
diff --git a/lib/debugger/src/dbg_iload.erl b/lib/debugger/src/dbg_iload.erl
index 2a8bcd32d8..369b456524 100644
--- a/lib/debugger/src/dbg_iload.erl
+++ b/lib/debugger/src/dbg_iload.erl
@@ -39,7 +39,7 @@
%% dbg_iserver. We are suspended until the module has been loaded.
%%--------------------------------------------------------------------
-spec load_mod(Mod, file:filename(), binary(), ets:tid()) ->
- {'ok', Mod} when is_subtype(Mod, atom()).
+ {'ok', Mod} when Mod :: atom().
load_mod(Mod, File, Binary, Db) ->
Flag = process_flag(trap_exit, true),
@@ -541,7 +541,7 @@ fun_clauses([]) -> [].
new_map(Fs0, Anno, F) ->
Line = ln(Anno),
Fs1 = map_fields(Fs0, F),
- Fs2 = [{ln(A),K,V} || {map_field_assoc,A,K,V} <- Fs1],
+ Fs2 = [{L,K,V} || {map_field_assoc,L,K,V} <- Fs1],
try
{value,Line,map_literal(Fs2, #{})}
catch
diff --git a/lib/debugger/src/dbg_wx_win.erl b/lib/debugger/src/dbg_wx_win.erl
index 63f74392b5..1ff8818bbe 100644
--- a/lib/debugger/src/dbg_wx_win.erl
+++ b/lib/debugger/src/dbg_wx_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2008-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.
@@ -95,10 +95,9 @@ create_menu_item(Menu, [{Name, _N, cascade, Items}|Is], Win, Id0,Connect) ->
false -> Acc
end
end,
- Filter = fun(_,_) ->
+ Filter = fun(Ev,_) ->
Enabled = lists:foldl(IsChecked, [], Butts),
- Self ! #wx{userData={Name, Enabled},
- event=#wxCommand{type=command_menu_selected}}
+ Self ! Ev#wx{userData={Name, Enabled}}
end,
wxMenu:connect(Win, command_menu_selected,
[{id,Id0},{lastId, Id-1},{callback,Filter}]),
diff --git a/lib/debugger/src/int.erl b/lib/debugger/src/int.erl
index 4f54beb45b..1e43d1858a 100644
--- a/lib/debugger/src/int.erl
+++ b/lib/debugger/src/int.erl
@@ -547,7 +547,7 @@ load({Mod, Src, Beam, BeamBin, Exp, Abst}, Dist) ->
check_module(Mod) ->
case code:which(Mod) of
Beam when is_list(Beam) ->
- case find_src(Beam) of
+ case find_src(Mod, Beam) of
Src when is_list(Src) ->
check_application(Src),
case check_beam(Beam) of
@@ -608,7 +608,7 @@ check_application2("gs-"++_) -> throw({error,{app,gs}});
check_application2("debugger-"++_) -> throw({error,{app,debugger}});
check_application2(_) -> ok.
-find_src(Beam) ->
+find_src(Mod, Beam) ->
Src0 = filename:rootname(Beam) ++ ".erl",
case is_file(Src0) of
true -> Src0;
@@ -618,10 +618,22 @@ find_src(Beam) ->
filename:basename(Src0)]),
case is_file(Src) of
true -> Src;
- false -> error
+ false -> find_src_from_module(Mod)
end
end.
+find_src_from_module(Mod) ->
+ Compile = Mod:module_info(compile),
+ case lists:keyfind(source, 1, Compile) of
+ {source, Src} ->
+ case is_file(Src) of
+ true -> Src;
+ false -> error
+ end;
+ false ->
+ error
+ end.
+
find_beam(Mod, Src) ->
SrcDir = filename:dirname(Src),
BeamFile = atom_to_list(Mod) ++ code:objfile_extension(),
diff --git a/lib/debugger/test/Makefile b/lib/debugger/test/Makefile
index 82f49c155f..1594c891b4 100644
--- a/lib/debugger/test/Makefile
+++ b/lib/debugger/test/Makefile
@@ -68,7 +68,7 @@ RELSYSDIR = $(RELEASE_PATH)/debugger_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_COMPILE_FLAGS +=
EBIN = .
diff --git a/lib/debugger/test/andor_SUITE.erl b/lib/debugger/test/andor_SUITE.erl
index 384b6c7c77..9750fa018d 100644
--- a/lib/debugger/test/andor_SUITE.erl
+++ b/lib/debugger/test/andor_SUITE.erl
@@ -27,7 +27,7 @@
t_andalso/1,t_orelse/1,inside/1,overlap/1,
combined/1,in_case/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
diff --git a/lib/debugger/test/bs_bincomp_SUITE.erl b/lib/debugger/test/bs_bincomp_SUITE.erl
index 0750c6793d..18b4198354 100644
--- a/lib/debugger/test/bs_bincomp_SUITE.erl
+++ b/lib/debugger/test/bs_bincomp_SUITE.erl
@@ -30,7 +30,7 @@
byte_aligned/1,bit_aligned/1,extended_byte_aligned/1,
extended_bit_aligned/1,mixed/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
diff --git a/lib/debugger/test/bs_construct_SUITE.erl b/lib/debugger/test/bs_construct_SUITE.erl
index f62512568f..966c096c3a 100644
--- a/lib/debugger/test/bs_construct_SUITE.erl
+++ b/lib/debugger/test/bs_construct_SUITE.erl
@@ -36,7 +36,7 @@
copy_writable_binary/1, dynamic/1,
otp_7422/1, zero_width/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
diff --git a/lib/debugger/test/bs_match_bin_SUITE.erl b/lib/debugger/test/bs_match_bin_SUITE.erl
index a61b56501c..98c1013210 100644
--- a/lib/debugger/test/bs_match_bin_SUITE.erl
+++ b/lib/debugger/test/bs_match_bin_SUITE.erl
@@ -27,7 +27,7 @@
init_per_suite/1,end_per_suite/1,
byte_split_binary/1,bit_split_binary/1,match_huge_bin/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
diff --git a/lib/debugger/test/bs_match_int_SUITE.erl b/lib/debugger/test/bs_match_int_SUITE.erl
index fd77530dd5..11b5e30efd 100644
--- a/lib/debugger/test/bs_match_int_SUITE.erl
+++ b/lib/debugger/test/bs_match_int_SUITE.erl
@@ -26,7 +26,7 @@
integer/1,signed_integer/1,dynamic/1,more_dynamic/1,mml/1,
match_huge_int/1,bignum/1,unaligned_32_bit/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-import(lists, [seq/2]).
diff --git a/lib/debugger/test/bs_match_misc_SUITE.erl b/lib/debugger/test/bs_match_misc_SUITE.erl
index 2221cfe08b..7196026dc7 100644
--- a/lib/debugger/test/bs_match_misc_SUITE.erl
+++ b/lib/debugger/test/bs_match_misc_SUITE.erl
@@ -29,7 +29,7 @@
writable_binary_matched/1,otp_7198/1,
unordered_bindings/1,float_middle_endian/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
diff --git a/lib/debugger/test/bs_match_tail_SUITE.erl b/lib/debugger/test/bs_match_tail_SUITE.erl
index 9ec93978ed..f4201ee7db 100644
--- a/lib/debugger/test/bs_match_tail_SUITE.erl
+++ b/lib/debugger/test/bs_match_tail_SUITE.erl
@@ -26,7 +26,7 @@
init_per_suite/1,end_per_suite/1,
aligned/1,unaligned/1,zero_tail/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
diff --git a/lib/debugger/test/bs_utf_SUITE.erl b/lib/debugger/test/bs_utf_SUITE.erl
index 90c4d6c7b9..5bf776226a 100644
--- a/lib/debugger/test/bs_utf_SUITE.erl
+++ b/lib/debugger/test/bs_utf_SUITE.erl
@@ -28,7 +28,7 @@
utf8_roundtrip/1,unused_utf_char/1,utf16_roundtrip/1,
utf32_roundtrip/1,guard/1,extreme_tripping/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-compile([no_jopt,time]).
suite() -> [{ct_hooks,[ts_install_cth]}].
diff --git a/lib/debugger/test/bug_SUITE.erl b/lib/debugger/test/bug_SUITE.erl
index 542db3f41e..516d9f4b8d 100644
--- a/lib/debugger/test/bug_SUITE.erl
+++ b/lib/debugger/test/bug_SUITE.erl
@@ -21,7 +21,7 @@
%%
-module(bug_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
diff --git a/lib/debugger/test/cleanup.erl b/lib/debugger/test/cleanup.erl
index b40ae5f82c..58f3c9380f 100644
--- a/lib/debugger/test/cleanup.erl
+++ b/lib/debugger/test/cleanup.erl
@@ -23,7 +23,7 @@
-export([all/0,groups/0,init_per_group/2,end_per_group/2, cleanup/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
all() ->
[cleanup].
diff --git a/lib/debugger/test/dbg_ui_SUITE.erl b/lib/debugger/test/dbg_ui_SUITE.erl
index f0f4e09aa8..39ecb51b57 100644
--- a/lib/debugger/test/dbg_ui_SUITE.erl
+++ b/lib/debugger/test/dbg_ui_SUITE.erl
@@ -22,7 +22,7 @@
-module(dbg_ui_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
% Test server specific exports
diff --git a/lib/debugger/test/debugger_SUITE.erl b/lib/debugger/test/debugger_SUITE.erl
index 9207df38e4..678ca0e5c3 100644
--- a/lib/debugger/test/debugger_SUITE.erl
+++ b/lib/debugger/test/debugger_SUITE.erl
@@ -23,7 +23,7 @@
%% Test break points.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
diff --git a/lib/debugger/test/erl_eval_SUITE.erl b/lib/debugger/test/erl_eval_SUITE.erl
index af9b0a6e6e..c75e4012f3 100644
--- a/lib/debugger/test/erl_eval_SUITE.erl
+++ b/lib/debugger/test/erl_eval_SUITE.erl
@@ -60,7 +60,7 @@
config(priv_dir,_) ->
".".
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([init_per_testcase/2, end_per_testcase/2]).
% Default timetrap timeout (set in init_per_testcase).
-define(default_timeout, ?t:minutes(1)).
diff --git a/lib/debugger/test/exception_SUITE.erl b/lib/debugger/test/exception_SUITE.erl
index f42dbc7776..e35326a798 100644
--- a/lib/debugger/test/exception_SUITE.erl
+++ b/lib/debugger/test/exception_SUITE.erl
@@ -28,7 +28,7 @@
-export([bad_guy/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
diff --git a/lib/debugger/test/fun_SUITE.erl b/lib/debugger/test/fun_SUITE.erl
index fabee16cee..b8092ab16c 100644
--- a/lib/debugger/test/fun_SUITE.erl
+++ b/lib/debugger/test/fun_SUITE.erl
@@ -30,7 +30,7 @@
%% Internal exports.
-export([nothing/0,call_me/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
diff --git a/lib/debugger/test/guard_SUITE.erl b/lib/debugger/test/guard_SUITE.erl
index 880c89532b..2b87ef23ba 100644
--- a/lib/debugger/test/guard_SUITE.erl
+++ b/lib/debugger/test/guard_SUITE.erl
@@ -39,7 +39,7 @@
check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1,
bad_constants/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([init/4]).
-import(lists, [member/2]).
diff --git a/lib/debugger/test/int_SUITE.erl b/lib/debugger/test/int_SUITE.erl
index 5f2e4dd84d..ec4de88331 100644
--- a/lib/debugger/test/int_SUITE.erl
+++ b/lib/debugger/test/int_SUITE.erl
@@ -20,7 +20,7 @@
%%
-module(int_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -245,14 +245,13 @@ interpretable(Config) when is_list(Config) ->
?line true = int:interpretable(filename:join([DataDir,lists1])),
?line true = code:del_path(DataDir),
- %% {error, no_src}
- ?line PrivDir = filename:join(?config(priv_dir, Config), ""),
- ?line {ok, _} = file:copy(filename:join([DataDir,"lists1.beam"]),
+ %% true (from source)
+ PrivDir = filename:join(?config(priv_dir, Config), ""),
+ {ok, _} = file:copy(filename:join([DataDir,"lists1.beam"]),
filename:join([PrivDir,"lists1.beam"])),
- ?line true = code:add_patha(PrivDir),
-
- ?line {error, no_src} = int:interpretable(lists1),
- ?line ok = file:delete(filename:join([PrivDir,"lists1.beam"])),
+ true = code:add_patha(PrivDir),
+ true = int:interpretable(lists1),
+ ok = file:delete(filename:join([PrivDir,"lists1.beam"])),
%% {error, no_beam}
Src = filename:join([PrivDir,"lists1.erl"]),
@@ -267,6 +266,11 @@ interpretable(Config) when is_list(Config) ->
?line ok = file:delete(Src),
?line true = code:del_path(PrivDir),
+ %% {error, no_src}
+ {ok, lists2, Binary} = compile:forms([{attribute,1,module,lists2}], []),
+ code:load_binary(lists2, "unknown", Binary),
+ {error, no_src} = int:interpretable(lists2),
+
%% {error, badarg}
?line {error, badarg} = int:interpretable(pride),
?line {error, badarg} = int:interpretable("prejudice.erl"),
diff --git a/lib/debugger/test/int_break_SUITE.erl b/lib/debugger/test/int_break_SUITE.erl
index 21b53a8d30..75bdd69a7d 100644
--- a/lib/debugger/test/int_break_SUITE.erl
+++ b/lib/debugger/test/int_break_SUITE.erl
@@ -22,7 +22,7 @@
%% Test break points.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
diff --git a/lib/debugger/test/int_eval_SUITE.erl b/lib/debugger/test/int_eval_SUITE.erl
index f30d386de9..3f3c03492e 100644
--- a/lib/debugger/test/int_eval_SUITE.erl
+++ b/lib/debugger/test/int_eval_SUITE.erl
@@ -36,7 +36,7 @@
-define(IM, my_int_eval_module).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,1}}].
diff --git a/lib/debugger/test/lc_SUITE.erl b/lib/debugger/test/lc_SUITE.erl
index aca4c4de7c..851d0fbc20 100644
--- a/lib/debugger/test/lc_SUITE.erl
+++ b/lib/debugger/test/lc_SUITE.erl
@@ -28,7 +28,7 @@
basic/1,deeply_nested/1,no_generator/1,
empty_generator/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
diff --git a/lib/debugger/test/line_number_SUITE.erl b/lib/debugger/test/line_number_SUITE.erl
index 6ec5ef5d5a..592f0a1f32 100644
--- a/lib/debugger/test/line_number_SUITE.erl
+++ b/lib/debugger/test/line_number_SUITE.erl
@@ -26,7 +26,7 @@
line_numbers/1]).
-export([crash/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
diff --git a/lib/debugger/test/map_SUITE.erl b/lib/debugger/test/map_SUITE.erl
index 0ef634f7aa..eabcdcbf42 100644
--- a/lib/debugger/test/map_SUITE.erl
+++ b/lib/debugger/test/map_SUITE.erl
@@ -2219,7 +2219,7 @@ map_guard_sequence_mixed(K1,K2,M) ->
t_frequency_table(Config) when is_list(Config) ->
- random:seed({13,1337,54}), % pseudo random
+ rand:seed(exsplus, {13,1337,54}), % pseudo random
N = 1000,
Ts = rand_terms(N),
#{ n:=N, tf := Tf } = frequency_table(Ts,#{ n=>0, tf => #{}}),
@@ -2262,7 +2262,7 @@ rand_terms(0) -> [];
rand_terms(N) -> [rand_term()|rand_terms(N-1)].
rand_term() ->
- case random:uniform(6) of
+ case rand:uniform(6) of
1 -> rand_binary();
2 -> rand_number();
3 -> rand_atom();
@@ -2272,21 +2272,21 @@ rand_term() ->
end.
rand_binary() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> <<>>;
2 -> <<"hi">>;
3 -> <<"message text larger than 64 bytes. yep, message text larger than 64 bytes.">>
end.
rand_number() ->
- case random:uniform(3) of
- 1 -> random:uniform(5);
- 2 -> float(random:uniform(5));
- 3 -> 1 bsl (63 + random:uniform(3))
+ case rand:uniform(3) of
+ 1 -> rand:uniform(5);
+ 2 -> float(rand:uniform(5));
+ 3 -> 1 bsl (63 + rand:uniform(3))
end.
rand_atom() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> hi;
2 -> some_atom;
3 -> some_other_atom
@@ -2294,21 +2294,21 @@ rand_atom() ->
rand_tuple() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> {ok, rand_term()}; % careful
2 -> {1, 2, 3};
3 -> {<<"yep">>, 1337}
end.
rand_list() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> "hi";
2 -> [1,rand_term()]; % careful
3 -> [improper|list]
end.
rand_map() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> #{ hi => 3 };
2 -> #{ wat => rand_term(), other => 3 }; % careful
3 -> #{ hi => 42, other => 42, yet_anoter => 1337 }
diff --git a/lib/debugger/test/record_SUITE.erl b/lib/debugger/test/record_SUITE.erl
index 2f663e2dfc..115e65c685 100644
--- a/lib/debugger/test/record_SUITE.erl
+++ b/lib/debugger/test/record_SUITE.erl
@@ -23,7 +23,7 @@
-module(record_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
diff --git a/lib/debugger/test/trycatch_SUITE.erl b/lib/debugger/test/trycatch_SUITE.erl
index 7fdd98fc71..0303d1bd82 100644
--- a/lib/debugger/test/trycatch_SUITE.erl
+++ b/lib/debugger/test/trycatch_SUITE.erl
@@ -28,7 +28,7 @@
catch_oops/1,after_oops/1,eclectic/1,rethrow/1,
nested_of/1,nested_catch/1,nested_after/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
diff --git a/lib/dialyzer/doc/src/dialyzer.xml b/lib/dialyzer/doc/src/dialyzer.xml
index 3fd34241b2..619db125b1 100644
--- a/lib/dialyzer/doc/src/dialyzer.xml
+++ b/lib/dialyzer/doc/src/dialyzer.xml
@@ -254,7 +254,7 @@
analysis that finds data races performs intra-procedural data flow analysis
and can sometimes explode in time. Enable it at your own risk.
</item>
-i <tag><c><![CDATA[-Wunderspecs]]></c>***</tag>
+ <tag><c><![CDATA[-Wunderspecs]]></c>***</tag>
<item>Warn about underspecified functions
(the -spec is strictly more allowing than the success typing).</item>
<tag><c><![CDATA[-Wunknown]]></c>***</tag>
diff --git a/lib/dialyzer/src/Makefile b/lib/dialyzer/src/Makefile
index 770af2140f..fd75cd5cd8 100644
--- a/lib/dialyzer/src/Makefile
+++ b/lib/dialyzer/src/Makefile
@@ -61,6 +61,7 @@ MODULES = \
dialyzer_gui_wx \
dialyzer_options \
dialyzer_plt \
+ dialyzer_race_data_server \
dialyzer_races \
dialyzer_succ_typings \
dialyzer_timing \
@@ -140,6 +141,7 @@ $(EBIN)/dialyzer_explanation.beam: dialyzer.hrl
$(EBIN)/dialyzer_gui_wx.beam: dialyzer.hrl dialyzer_gui_wx.hrl
$(EBIN)/dialyzer_options.beam: dialyzer.hrl
$(EBIN)/dialyzer_plt.beam: dialyzer.hrl
+$(EBIN)/dialyzer_race_data_server.beam: dialyzer.hrl
$(EBIN)/dialyzer_races.beam: dialyzer.hrl
$(EBIN)/dialyzer_succ_typings.beam: dialyzer.hrl
$(EBIN)/dialyzer_typesig.beam: dialyzer.hrl
diff --git a/lib/dialyzer/src/dialyzer.app.src b/lib/dialyzer/src/dialyzer.app.src
index 8ac6dc1367..003d7f2ba4 100644
--- a/lib/dialyzer/src/dialyzer.app.src
+++ b/lib/dialyzer/src/dialyzer.app.src
@@ -37,6 +37,7 @@
dialyzer_gui_wx,
dialyzer_options,
dialyzer_plt,
+ dialyzer_race_data_server,
dialyzer_races,
dialyzer_succ_typings,
dialyzer_typesig,
@@ -44,7 +45,7 @@
dialyzer_timing,
dialyzer_worker]},
{registered, []},
- {applications, [compiler, gs, hipe, kernel, stdlib, wx]},
+ {applications, [compiler, hipe, kernel, stdlib, wx]},
{env, []},
{runtime_dependencies, ["wx-1.2","syntax_tools-1.6.14","stdlib-2.5",
"kernel-3.0","hipe-3.13","erts-7.0",
diff --git a/lib/dialyzer/src/dialyzer.hrl b/lib/dialyzer/src/dialyzer.hrl
index de236f91ab..601e2e954b 100644
--- a/lib/dialyzer/src/dialyzer.hrl
+++ b/lib/dialyzer/src/dialyzer.hrl
@@ -2,7 +2,7 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2006-2014. All Rights Reserved.
+%%% Copyright Ericsson AB 2006-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.
@@ -123,10 +123,12 @@
%% Record declarations used by various files
%%--------------------------------------------------------------------
--record(analysis, {analysis_pid :: pid(),
+-type doc_plt() :: 'undefined' | dialyzer_plt:plt().
+
+-record(analysis, {analysis_pid :: pid() | 'undefined',
type = succ_typings :: anal_type(),
defines = [] :: [dial_define()],
- doc_plt :: dialyzer_plt:plt(),
+ doc_plt :: doc_plt(),
files = [] :: [file:filename()],
include_dirs = [] :: [file:filename()],
start_from = byte_code :: start_from(),
@@ -135,7 +137,7 @@
race_detection = false :: boolean(),
behaviours_chk = false :: boolean(),
timing = false :: boolean() | 'debug',
- timing_server :: dialyzer_timing:timing_server(),
+ timing_server = none :: dialyzer_timing:timing_server(),
callgraph_file = "" :: file:filename(),
solvers :: [solver()]}).
diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
index 8537878dfc..50fc1d8471 100644
--- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
+++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
@@ -2,7 +2,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2006-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.
@@ -31,14 +31,17 @@
-export([start/3]).
+%%% Export for dialyzer_coordinator...
-export([compile_init_result/0,
- add_to_result/4,
- start_compilation/2,
+ add_to_result/4]).
+%%% ... and export for dialyzer_worker.
+-export([start_compilation/2,
continue_compilation/2]).
-export_type([compile_init_data/0,
- one_file_result/0,
- compile_result/0]).
+ one_file_mid_error/0,
+ one_file_result_ok/0,
+ compile_result/0]).
-include("dialyzer.hrl").
@@ -153,8 +156,7 @@ analysis_start(Parent, Analysis, LegalWarnings) ->
MergedExpTypes = sets:union(NewExpTypes, OldExpTypes1),
TmpCServer1 = dialyzer_codeserver:set_temp_records(MergedRecords, TmpCServer0),
TmpCServer2 =
- dialyzer_codeserver:insert_temp_exported_types(MergedExpTypes,
- TmpCServer1),
+ dialyzer_codeserver:finalize_exported_types(MergedExpTypes, TmpCServer1),
?timing(State#analysis_state.timing_server, "remote",
begin
TmpCServer3 =
@@ -247,6 +249,10 @@ compile_and_store(Files, #analysis_state{codeserver = CServer,
{T1, _} = statistics(wall_clock),
Callgraph = dialyzer_callgraph:new(),
CompileInit = make_compile_init(State, Callgraph),
+ %% Spawn a worker per file - where each worker calls
+ %% start_compilation on its file, asks next label to coordinator and
+ %% calls continue_compilation - and let coordinator aggregate
+ %% results using (compile_init_result and) add_to_result.
{{Failed, Modules}, NextLabel} =
?timing(Timing, "compile", _C1,
dialyzer_coordinator:parallel_job(compile, Files,
@@ -278,16 +284,18 @@ compile_and_store(Files, #analysis_state{codeserver = CServer,
send_log(Parent, Msg2),
{Callgraph, CServer2}.
--type compile_init_data() :: #compile_init{}.
--type error_reason() :: string().
--type compile_result() :: {[{file:filename(), error_reason()}],
- [module()]}. %%opaque
--type one_file_result() :: {error, error_reason()} |
- {ok, [dialyzer_callgraph:callgraph_edge()],
- [mfa_or_funlbl()], module()}. %%opaque
--type compile_mid_data() :: {module(), cerl:cerl(),
- dialyzer_callgraph:callgraph(),
- dialyzer_codeserver:codeserver()}.
+-opaque compile_init_data() :: #compile_init{}.
+-type error_reason() :: string().
+-opaque compile_result() :: {[{file:filename(), error_reason()}],
+ [module()]}.
+-type one_file_mid_error() :: {error, error_reason()}.
+-opaque one_file_result_ok() :: {ok, [dialyzer_callgraph:callgraph_edge()],
+ [mfa_or_funlbl()], module()}.
+-type one_file_result() :: one_file_mid_error() |
+ one_file_result_ok().
+-type compile_mid_data() :: {module(), cerl:cerl(),
+ dialyzer_callgraph:callgraph(),
+ dialyzer_codeserver:codeserver()}.
-spec compile_init_result() -> compile_result().
@@ -428,7 +436,8 @@ store_core(Mod, Core, Callgraph, CServer) ->
CoreSize = cerl_trees:size(CoreTree),
{ok, CoreSize, {Mod, CoreTree, Callgraph, CServer}}.
--spec continue_compilation(integer(), compile_mid_data()) -> one_file_result().
+-spec continue_compilation(integer(), compile_mid_data()) ->
+ one_file_result_ok().
continue_compilation(NextLabel, {Mod, CoreTree, Callgraph, CServer}) ->
{LabeledTree, _NewNextLabel} = cerl_trees:label(CoreTree, NextLabel),
diff --git a/lib/dialyzer/src/dialyzer_callgraph.erl b/lib/dialyzer/src/dialyzer_callgraph.erl
index 9e53e171c0..50abb22009 100644
--- a/lib/dialyzer/src/dialyzer_callgraph.erl
+++ b/lib/dialyzer/src/dialyzer_callgraph.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2006-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.
@@ -96,26 +96,28 @@
%% whenever applicable.
%%-----------------------------------------------------------------------------
+%% Types with comment 'race' are due to dialyzer_races.erl.
-record(callgraph, {digraph = digraph:new() :: digraph:graph(),
- active_digraph :: active_digraph(),
- esc :: ets:tid(),
- letrec_map :: ets:tid(),
+ active_digraph :: active_digraph()
+ | 'undefined', % race
+ esc :: ets:tid()
+ | 'undefined', % race
+ letrec_map :: ets:tid()
+ | 'undefined', % race
name_map :: ets:tid(),
rev_name_map :: ets:tid(),
- rec_var_map :: ets:tid(),
- self_rec :: ets:tid(),
- calls :: ets:tid(),
+ rec_var_map :: ets:tid()
+ | 'undefined', % race
+ self_rec :: ets:tid()
+ | 'undefined', % race
+ calls :: ets:tid()
+ | 'undefined', % race
race_detection = false :: boolean(),
- race_data_server = new_race_data_server() :: pid()}).
-
--record(race_data_state, {race_code = dict:new() :: dict:dict(),
- public_tables = [] :: [label()],
- named_tables = [] :: [string()],
- beh_api_calls = [] :: [{mfa(), mfa()}]}).
+ race_data_server = dialyzer_race_data_server:new() :: pid()}).
%% Exported Types
--type callgraph() :: #callgraph{}.
+-opaque callgraph() :: #callgraph{}.
-type active_digraph() :: {'d', digraph:graph()} | {'e', ets:tid(), ets:tid()}.
@@ -609,45 +611,30 @@ digraph_reaching_subgraph(Funs, DG) ->
renew_race_info(#callgraph{race_data_server = RaceDataServer} = CG,
RaceCode, PublicTables, NamedTables) ->
- ok = race_data_server_cast(
+ ok = dialyzer_race_data_server:cast(
{renew_race_info, {RaceCode, PublicTables, NamedTables}},
RaceDataServer),
CG.
-renew_race_info({RaceCode, PublicTables, NamedTables},
- #race_data_state{} = State) ->
- State#race_data_state{race_code = RaceCode,
- public_tables = PublicTables,
- named_tables = NamedTables}.
-
-spec renew_race_code(dialyzer_races:races(), callgraph()) -> callgraph().
renew_race_code(Races, #callgraph{race_data_server = RaceDataServer} = CG) ->
Fun = dialyzer_races:get_curr_fun(Races),
FunArgs = dialyzer_races:get_curr_fun_args(Races),
Code = lists:reverse(dialyzer_races:get_race_list(Races)),
- ok = race_data_server_cast(
+ ok = dialyzer_race_data_server:cast(
{renew_race_code, {Fun, FunArgs, Code}},
RaceDataServer),
CG.
-renew_race_code_handler({Fun, FunArgs, Code},
- #race_data_state{race_code = RaceCode} = State) ->
- State#race_data_state{race_code = dict:store(Fun, [FunArgs, Code], RaceCode)}.
-
-spec renew_race_public_tables(label(), callgraph()) -> callgraph().
renew_race_public_tables(VarLabel,
#callgraph{race_data_server = RaceDataServer} = CG) ->
ok =
- race_data_server_cast({renew_race_public_tables, VarLabel}, RaceDataServer),
+ dialyzer_race_data_server:cast({renew_race_public_tables, VarLabel}, RaceDataServer),
CG.
-renew_race_public_tables_handler(VarLabel,
- #race_data_state{public_tables = PT}
- = State) ->
- State#race_data_state{public_tables = ordsets:add_element(VarLabel, PT)}.
-
-spec cleanup(callgraph()) -> callgraph().
cleanup(#callgraph{digraph = Digraph,
@@ -657,18 +644,18 @@ cleanup(#callgraph{digraph = Digraph,
#callgraph{digraph = Digraph,
name_map = NameMap,
rev_name_map = RevNameMap,
- race_data_server = race_data_server_call(dup, RaceDataServer)}.
+ race_data_server = dialyzer_race_data_server:duplicate(RaceDataServer)}.
-spec duplicate(callgraph()) -> callgraph().
duplicate(#callgraph{race_data_server = RaceDataServer} = Callgraph) ->
Callgraph#callgraph{
- race_data_server = race_data_server_call(dup, RaceDataServer)}.
+ race_data_server = dialyzer_race_data_server:duplicate(RaceDataServer)}.
-spec dispose_race_server(callgraph()) -> ok.
dispose_race_server(#callgraph{race_data_server = RaceDataServer}) ->
- race_data_server_cast(stop, RaceDataServer).
+ dialyzer_race_data_server:stop(RaceDataServer).
-spec get_digraph(callgraph()) -> digraph:graph().
@@ -678,17 +665,17 @@ get_digraph(#callgraph{digraph = Digraph}) ->
-spec get_named_tables(callgraph()) -> [string()].
get_named_tables(#callgraph{race_data_server = RaceDataServer}) ->
- race_data_server_call(get_named_tables, RaceDataServer).
+ dialyzer_race_data_server:call(get_named_tables, RaceDataServer).
-spec get_public_tables(callgraph()) -> [label()].
get_public_tables(#callgraph{race_data_server = RaceDataServer}) ->
- race_data_server_call(get_public_tables, RaceDataServer).
+ dialyzer_race_data_server:call(get_public_tables, RaceDataServer).
-spec get_race_code(callgraph()) -> dict:dict().
get_race_code(#callgraph{race_data_server = RaceDataServer}) ->
- race_data_server_call(get_race_code, RaceDataServer).
+ dialyzer_race_data_server:call(get_race_code, RaceDataServer).
-spec get_race_detection(callgraph()) -> boolean().
@@ -698,12 +685,12 @@ get_race_detection(#callgraph{race_detection = RD}) ->
-spec get_behaviour_api_calls(callgraph()) -> [{mfa(), mfa()}].
get_behaviour_api_calls(#callgraph{race_data_server = RaceDataServer}) ->
- race_data_server_call(get_behaviour_api_calls, RaceDataServer).
+ dialyzer_race_data_server:call(get_behaviour_api_calls, RaceDataServer).
-spec race_code_new(callgraph()) -> callgraph().
race_code_new(#callgraph{race_data_server = RaceDataServer} = CG) ->
- ok = race_data_server_cast(race_code_new, RaceDataServer),
+ ok = dialyzer_race_data_server:cast(race_code_new, RaceDataServer),
CG.
-spec put_digraph(digraph:graph(), callgraph()) -> callgraph().
@@ -714,7 +701,7 @@ put_digraph(Digraph, Callgraph) ->
-spec put_race_code(dict:dict(), callgraph()) -> callgraph().
put_race_code(RaceCode, #callgraph{race_data_server = RaceDataServer} = CG) ->
- ok = race_data_server_cast({put_race_code, RaceCode}, RaceDataServer),
+ ok = dialyzer_race_data_server:cast({put_race_code, RaceCode}, RaceDataServer),
CG.
-spec put_race_detection(boolean(), callgraph()) -> callgraph().
@@ -726,78 +713,23 @@ put_race_detection(RaceDetection, Callgraph) ->
put_named_tables(NamedTables,
#callgraph{race_data_server = RaceDataServer} = CG) ->
- ok = race_data_server_cast({put_named_tables, NamedTables}, RaceDataServer),
+ ok = dialyzer_race_data_server:cast({put_named_tables, NamedTables}, RaceDataServer),
CG.
-spec put_public_tables([label()], callgraph()) -> callgraph().
put_public_tables(PublicTables,
#callgraph{race_data_server = RaceDataServer} = CG) ->
- ok = race_data_server_cast({put_public_tables, PublicTables}, RaceDataServer),
+ ok = dialyzer_race_data_server:cast({put_public_tables, PublicTables}, RaceDataServer),
CG.
-spec put_behaviour_api_calls([{mfa(), mfa()}], callgraph()) -> callgraph().
put_behaviour_api_calls(Calls,
#callgraph{race_data_server = RaceDataServer} = CG) ->
- ok = race_data_server_cast({put_behaviour_api_calls, Calls}, RaceDataServer),
+ ok = dialyzer_race_data_server:cast({put_behaviour_api_calls, Calls}, RaceDataServer),
CG.
-
-new_race_data_server() ->
- spawn_link(fun() -> race_data_server_loop(#race_data_state{}) end).
-
-race_data_server_loop(State) ->
- receive
- {call, From, Ref, Query} ->
- Reply = race_data_server_handle_call(Query, State),
- From ! {Ref, Reply},
- race_data_server_loop(State);
- {cast, stop} ->
- ok;
- {cast, Message} ->
- NewState = race_data_server_handle_cast(Message, State),
- race_data_server_loop(NewState)
- end.
-
-race_data_server_call(Query, Server) ->
- Ref = make_ref(),
- Server ! {call, self(), Ref, Query},
- receive
- {Ref, Reply} -> Reply
- end.
-
-race_data_server_cast(Message, Server) ->
- Server ! {cast, Message},
- ok.
-
-race_data_server_handle_cast(race_code_new, State) ->
- State#race_data_state{race_code = dict:new()};
-race_data_server_handle_cast({Tag, Data}, State) ->
- case Tag of
- renew_race_info -> renew_race_info(Data, State);
- renew_race_code -> renew_race_code_handler(Data, State);
- renew_race_public_tables -> renew_race_public_tables_handler(Data, State);
- put_race_code -> State#race_data_state{race_code = Data};
- put_public_tables -> State#race_data_state{public_tables = Data};
- put_named_tables -> State#race_data_state{named_tables = Data};
- put_behaviour_api_calls -> State#race_data_state{beh_api_calls = Data}
- end.
-
-race_data_server_handle_call(Query,
- #race_data_state{race_code = RaceCode,
- public_tables = PublicTables,
- named_tables = NamedTables,
- beh_api_calls = BehApiCalls}
- = State) ->
- case Query of
- dup -> spawn_link(fun() -> race_data_server_loop(State) end);
- get_race_code -> RaceCode;
- get_public_tables -> PublicTables;
- get_named_tables -> NamedTables;
- get_behaviour_api_calls -> BehApiCalls
- end.
-
%%=============================================================================
%% Utilities for 'dot'
%%=============================================================================
diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl
index 9354b8007e..50ff5304d6 100644
--- a/lib/dialyzer/src/dialyzer_cl.erl
+++ b/lib/dialyzer/src/dialyzer_cl.erl
@@ -36,7 +36,7 @@
-include_lib("kernel/include/file.hrl"). % needed for #file_info{}
-record(cl_state,
- {backend_pid :: pid(),
+ {backend_pid :: pid() | 'undefined',
erlang_mode = false :: boolean(),
external_calls = [] :: [mfa()],
external_types = [] :: [mfa()],
diff --git a/lib/dialyzer/src/dialyzer_codeserver.erl b/lib/dialyzer/src/dialyzer_codeserver.erl
index 978ecd3843..03cd9671af 100644
--- a/lib/dialyzer/src/dialyzer_codeserver.erl
+++ b/lib/dialyzer/src/dialyzer_codeserver.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2006-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.
@@ -81,10 +81,10 @@
-record(codeserver, {next_core_label = 0 :: label(),
code :: dict_ets(),
- exported_types :: set_ets(), % set(mfa())
- records :: dict_ets(),
- contracts :: dict_ets(),
- callbacks :: dict_ets(),
+ exported_types :: set_ets() | 'undefined', % set(mfa())
+ records :: dict_ets() | 'undefined',
+ contracts :: dict_ets() | 'undefined',
+ callbacks :: dict_ets() | 'undefined',
fun_meta_info :: dict_ets(), % {mfa(), meta_info()}
exports :: 'clean' | set_ets(), % set(mfa())
temp_exported_types :: 'clean' | set_ets(), % set(mfa())
diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl
index 7251de8b10..e03e4d5bb4 100644
--- a/lib/dialyzer/src/dialyzer_contracts.erl
+++ b/lib/dialyzer/src/dialyzer_contracts.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2007-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.
@@ -126,13 +126,19 @@ butlast([H|T]) -> [H|butlast(T)].
constraints_to_string([]) ->
"";
-constraints_to_string([{type, _, constraint, [{atom, _, What}, Types]}]) ->
- atom_to_list(What) ++ "(" ++
- sequence([erl_types:t_form_to_string(T) || T <- Types], ",") ++ ")";
constraints_to_string([{type, _, constraint, [{atom, _, What}, Types]}|Rest]) ->
- atom_to_list(What) ++ "(" ++
- sequence([erl_types:t_form_to_string(T) || T <- Types], ",")
- ++ "), " ++ constraints_to_string(Rest).
+ S = constraint_to_string(What, Types),
+ case Rest of
+ [] -> S;
+ _ -> S ++ ", " ++ constraints_to_string(Rest)
+ end.
+
+constraint_to_string(is_subtype, [{var, _, Var}, T]) ->
+ atom_to_list(Var) ++ " :: " ++ erl_types:t_form_to_string(T);
+constraint_to_string(What, Types) ->
+ atom_to_list(What) ++ "("
+ ++ sequence([erl_types:t_form_to_string(T) || T <- Types], ",")
+ ++ ")".
sequence([], _Delimiter) -> "";
sequence([H], _Delimiter) -> H;
@@ -161,8 +167,7 @@ process_contract_remote_types(CodeServer) ->
dialyzer_codeserver:finalize_contracts(NewContractDict, NewCallbackDict,
CodeServer).
--type opaques() :: [erl_types:erl_type()] | 'universe'.
--type opaques_fun() :: fun((module()) -> opaques()).
+-type opaques_fun() :: fun((module()) -> [erl_types:erl_type()]).
-type fun_types() :: dict:dict(label(), erl_types:type_table()).
diff --git a/lib/dialyzer/src/dialyzer_coordinator.erl b/lib/dialyzer/src/dialyzer_coordinator.erl
index 612f379d32..87cbd25b30 100644
--- a/lib/dialyzer/src/dialyzer_coordinator.erl
+++ b/lib/dialyzer/src/dialyzer_coordinator.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2006-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.
@@ -29,8 +29,8 @@
%%% Export for dialyzer main process
-export([parallel_job/4]).
-%%% Exports for all possible workers
--export([wait_activation/0, job_done/3]).
+%%% Export for all possible workers
+-export([job_done/3]).
%%% Exports for the typesig and dataflow analysis workers
-export([sccs_to_pids/2, request_activation/1]).
@@ -38,7 +38,7 @@
%%% Exports for the compilation workers
-export([get_next_label/2]).
--export_type([coordinator/0, mode/0, init_data/0, result/0]).
+-export_type([coordinator/0, mode/0, init_data/0, result/0, job/0]).
%%--------------------------------------------------------------------
@@ -46,16 +46,18 @@
-type regulator() :: pid().
-type scc_to_pid() :: ets:tid() | 'unused'.
--type coordinator() :: {collector(), regulator(), scc_to_pid()}. %%opaque
+-opaque coordinator() :: {collector(), regulator(), scc_to_pid()}.
-type timing() :: dialyzer_timing:timing_server().
-type scc() :: [mfa_or_funlbl()].
-type mode() :: 'typesig' | 'dataflow' | 'compile' | 'warnings'.
--type compile_jobs() :: [file:filename()].
--type typesig_jobs() :: [scc()].
--type dataflow_jobs() :: [module()].
--type warnings_jobs() :: [module()].
+-type compile_job() :: file:filename().
+-type typesig_job() :: scc().
+-type dataflow_job() :: module().
+-type warnings_job() :: module().
+
+-type job() :: compile_job() | typesig_job() | dataflow_job() | warnings_job().
-type compile_init_data() :: dialyzer_analysis_callgraph:compile_init_data().
-type typesig_init_data() :: dialyzer_succ_typings:typesig_init_data().
@@ -73,9 +75,9 @@
-type result() :: compile_result() | typesig_result() |
dataflow_result() | warnings_result().
--type job() :: scc() | module() | file:filename().
--type job_result() :: dialyzer_analysis_callgraph:one_file_result() |
- typesig_result() | dataflow_result() | warnings_result().
+-type job_result() :: dialyzer_analysis_callgraph:one_file_mid_error() |
+ dialyzer_analysis_callgraph:one_file_result_ok() |
+ typesig_result() | dataflow_result() | warnings_result().
-record(state, {mode :: mode(),
active = 0 :: integer(),
@@ -90,13 +92,13 @@
%%--------------------------------------------------------------------
--spec parallel_job('compile', compile_jobs(), compile_init_data(), timing()) ->
+-spec parallel_job('compile', [compile_job()], compile_init_data(), timing()) ->
{compile_result(), integer()};
- ('typesig', typesig_jobs(), typesig_init_data(), timing()) ->
+ ('typesig', [typesig_job()], typesig_init_data(), timing()) ->
typesig_result();
- ('dataflow', dataflow_jobs(), dataflow_init_data(),
+ ('dataflow', [dataflow_job()], dataflow_init_data(),
timing()) -> dataflow_result();
- ('warnings', warnings_jobs(), warnings_init_data(),
+ ('warnings', [warnings_job()], warnings_init_data(),
timing()) -> warnings_result().
parallel_job(Mode, Jobs, InitData, Timing) ->
@@ -118,7 +120,7 @@ spawn_jobs(Mode, Jobs, InitData, Timing) ->
Pid = dialyzer_worker:launch(Mode, Job, InitData, Coordinator),
case TypesigOrDataflow of
true -> true = ets:insert(SCCtoPID, {Job, Pid}), ok;
- false -> request_activation(Regulator, Pid)
+ false -> ok
end,
Count + 1
end,
@@ -217,10 +219,6 @@ request_activation({_Collector, Regulator, _SCCtoPID}) ->
Regulator ! {req, self()},
wait_activation().
-request_activation(Regulator, Pid) ->
- Regulator ! {req, Pid},
- ok.
-
spawn_regulator() ->
InitTickets = dialyzer_utils:parallelism(),
spawn_link(fun() -> regulator_loop(InitTickets, queue:new()) end).
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl
index cabc5e9e0d..6e49043551 100644
--- a/lib/dialyzer/src/dialyzer_dataflow.erl
+++ b/lib/dialyzer/src/dialyzer_dataflow.erl
@@ -99,19 +99,29 @@
-define(BITS, 128).
--record(state, {callgraph :: dialyzer_callgraph:callgraph(),
- codeserver :: dialyzer_codeserver:codeserver(),
- envs :: env_tab(),
- fun_tab :: fun_tab(),
- fun_homes :: dict:dict(label(), mfa()),
- plt :: dialyzer_plt:plt(),
- opaques :: [type()],
+%% Types with comment 'race' are due to dialyzer_races.erl.
+-record(state, {callgraph :: dialyzer_callgraph:callgraph()
+ | 'undefined', % race
+ codeserver :: dialyzer_codeserver:codeserver()
+ | 'undefined', % race
+ envs :: env_tab()
+ | 'undefined', % race
+ fun_tab :: fun_tab()
+ | 'undefined', % race
+ fun_homes :: dict:dict(label(), mfa())
+ | 'undefined', % race
+ plt :: dialyzer_plt:plt()
+ | 'undefined', % race
+ opaques :: [type()]
+ | 'undefined', % race
races = dialyzer_races:new() :: dialyzer_races:races(),
records = dict:new() :: types(),
- tree_map :: dict:dict(label(), cerl:cerl()),
+ tree_map :: dict:dict(label(), cerl:cerl())
+ | 'undefined', % race
warning_mode = false :: boolean(),
warnings = [] :: [raw_warning()],
- work :: {[_], [_], sets:set()},
+ work :: {[_], [_], sets:set()}
+ | 'undefined', % race
module :: module(),
curr_fun :: curr_fun()
}).
diff --git a/lib/dialyzer/src/dialyzer_gui_wx.erl b/lib/dialyzer/src/dialyzer_gui_wx.erl
index ff54a91ce1..9f344d87ff 100644
--- a/lib/dialyzer/src/dialyzer_gui_wx.erl
+++ b/lib/dialyzer/src/dialyzer_gui_wx.erl
@@ -2,7 +2,7 @@
%%------------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2009-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.
@@ -52,7 +52,6 @@
add_dir :: wx:wx_object(),
add_rec :: wx:wx_object(),
chosen_box :: wx:wx_object(),
- analysis_pid :: pid(),
del_file :: wx:wx_object(),
doc_plt :: dialyzer_plt:plt(),
clear_chosen :: wx:wx_object(),
@@ -72,11 +71,11 @@
stop :: wx:wx_object(),
frame :: wx:wx_object(),
warnings_box :: wx:wx_object(),
- explanation_box :: wx:wx_object(),
+ explanation_box :: wx:wx_object() | 'undefined',
wantedWarnings :: list(),
rawWarnings :: list(),
- backend_pid :: pid(),
- expl_pid :: pid()}).
+ backend_pid :: pid() | 'undefined',
+ expl_pid :: pid() | 'undefined'}).
%%------------------------------------------------------------------------
diff --git a/lib/dialyzer/src/dialyzer_race_data_server.erl b/lib/dialyzer/src/dialyzer_race_data_server.erl
new file mode 100644
index 0000000000..3600491809
--- /dev/null
+++ b/lib/dialyzer/src/dialyzer_race_data_server.erl
@@ -0,0 +1,134 @@
+%% -*- erlang-indent-level: 2 -*-
+%%-----------------------------------------------------------------------
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-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%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File : dialyzer_race_data_server.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description :
+%%%
+%%% Created : 18 Sep 2015 by Luca Favatella <[email protected]>
+%%%-------------------------------------------------------------------
+-module(dialyzer_race_data_server).
+
+-export([new/0,
+ duplicate/1,
+ stop/1,
+ call/2,
+ cast/2]).
+
+-include("dialyzer.hrl").
+
+%%----------------------------------------------------------------------
+
+-record(state, {race_code = dict:new() :: dict:dict(),
+ public_tables = [] :: [label()],
+ named_tables = [] :: [string()],
+ beh_api_calls = [] :: [{mfa(), mfa()}]}).
+
+%%----------------------------------------------------------------------
+
+-spec new() -> pid().
+
+new() ->
+ spawn_link(fun() -> loop(#state{}) end).
+
+-spec duplicate(pid()) -> pid().
+
+duplicate(Server) ->
+ call(dup, Server).
+
+-spec stop(pid()) -> ok.
+
+stop(Server) ->
+ cast(stop, Server).
+
+-spec call(atom(), pid()) -> term().
+
+call(Query, Server) ->
+ Ref = make_ref(),
+ Server ! {call, self(), Ref, Query},
+ receive
+ {Ref, Reply} -> Reply
+ end.
+
+-spec cast(atom() | {atom(), term()}, pid()) -> ok.
+
+cast(Message, Server) ->
+ Server ! {cast, Message},
+ ok.
+
+%%----------------------------------------------------------------------
+
+loop(State) ->
+ receive
+ {call, From, Ref, Query} ->
+ Reply = handle_call(Query, State),
+ From ! {Ref, Reply},
+ loop(State);
+ {cast, stop} ->
+ ok;
+ {cast, Message} ->
+ NewState = handle_cast(Message, State),
+ loop(NewState)
+ end.
+
+handle_cast(race_code_new, State) ->
+ State#state{race_code = dict:new()};
+handle_cast({Tag, Data}, State) ->
+ case Tag of
+ renew_race_info -> renew_race_info_handler(Data, State);
+ renew_race_code -> renew_race_code_handler(Data, State);
+ renew_race_public_tables -> renew_race_public_tables_handler(Data, State);
+ put_race_code -> State#state{race_code = Data};
+ put_public_tables -> State#state{public_tables = Data};
+ put_named_tables -> State#state{named_tables = Data};
+ put_behaviour_api_calls -> State#state{beh_api_calls = Data}
+ end.
+
+handle_call(Query,
+ #state{race_code = RaceCode,
+ public_tables = PublicTables,
+ named_tables = NamedTables,
+ beh_api_calls = BehApiCalls}
+ = State) ->
+ case Query of
+ dup -> spawn_link(fun() -> loop(State) end);
+ get_race_code -> RaceCode;
+ get_public_tables -> PublicTables;
+ get_named_tables -> NamedTables;
+ get_behaviour_api_calls -> BehApiCalls
+ end.
+
+%%----------------------------------------------------------------------
+
+renew_race_info_handler({RaceCode, PublicTables, NamedTables},
+ #state{} = State) ->
+ State#state{race_code = RaceCode,
+ public_tables = PublicTables,
+ named_tables = NamedTables}.
+
+renew_race_code_handler({Fun, FunArgs, Code},
+ #state{race_code = RaceCode} = State) ->
+ State#state{race_code = dict:store(Fun, [FunArgs, Code], RaceCode)}.
+
+renew_race_public_tables_handler(VarLabel,
+ #state{public_tables = PT} = State) ->
+ State#state{public_tables = ordsets:add_element(VarLabel, PT)}.
diff --git a/lib/dialyzer/src/dialyzer_races.erl b/lib/dialyzer/src/dialyzer_races.erl
index 39de071bde..bb43d1dcb8 100644
--- a/lib/dialyzer/src/dialyzer_races.erl
+++ b/lib/dialyzer/src/dialyzer_races.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2008-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.
@@ -92,27 +92,28 @@
-type race_warn_tag() :: ?WARN_WHEREIS_REGISTER | ?WARN_WHEREIS_UNREGISTER
| ?WARN_ETS_LOOKUP_INSERT | ?WARN_MNESIA_DIRTY_READ_WRITE.
--record(beg_clause, {arg :: var_to_map1(),
- pats :: var_to_map1(),
- guard :: cerl:cerl()}).
--record(end_clause, {arg :: var_to_map1(),
- pats :: var_to_map1(),
- guard :: cerl:cerl()}).
+-record(beg_clause, {arg :: var_to_map1() | 'undefined',
+ pats :: var_to_map1() | 'undefined',
+ guard :: cerl:cerl() | 'undefined'}).
+-record(end_clause, {arg :: var_to_map1() | 'undefined',
+ pats :: var_to_map1() | 'undefined',
+ guard :: cerl:cerl() | 'undefined'}).
-record(end_case, {clauses :: [#end_clause{}]}).
--record(curr_fun, {status :: 'in' | 'out',
- mfa :: dialyzer_callgraph:mfa_or_funlbl(),
- label :: label(),
- def_vars :: [core_vars()],
- arg_types :: [erl_types:erl_type()],
- call_vars :: [core_vars()],
- var_map :: dict:dict()}).
+-record(curr_fun, {status :: 'in' | 'out' | 'undefined',
+ mfa :: dialyzer_callgraph:mfa_or_funlbl()
+ | 'undefined',
+ label :: label() | 'undefined',
+ def_vars :: [core_vars()] | 'undefined',
+ arg_types :: [erl_types:erl_type()] | 'undefined',
+ call_vars :: [core_vars()] | 'undefined',
+ var_map :: dict:dict() | 'undefined'}).
-record(dep_call, {call_name :: dep_calls(),
- args :: args(),
+ args :: args() | 'undefined',
arg_types :: [erl_types:erl_type()],
vars :: [core_vars()],
state :: dialyzer_dataflow:state(),
file_line :: file_line(),
- var_map :: dict:dict()}).
+ var_map :: dict:dict() | 'undefined'}).
-record(fun_call, {caller :: dialyzer_callgraph:mfa_or_funlbl(),
callee :: dialyzer_callgraph:mfa_or_funlbl(),
arg_types :: [erl_types:erl_type()],
@@ -121,7 +122,7 @@
arg :: var_to_map1()}).
-record(warn_call, {call_name :: warn_calls(),
args :: args(),
- var_map :: dict:dict()}).
+ var_map :: dict:dict() | 'undefined'}).
-type case_tags() :: 'beg_case' | #beg_clause{} | #end_clause{} | #end_case{}.
-type code() :: [#dep_call{} | #fun_call{} | #warn_call{} |
@@ -139,8 +140,9 @@
fun_mfa :: dialyzer_callgraph:mfa_or_funlbl(),
fun_label :: label()}).
--record(races, {curr_fun :: dialyzer_callgraph:mfa_or_funlbl(),
- curr_fun_label :: label(),
+-record(races, {curr_fun :: dialyzer_callgraph:mfa_or_funlbl()
+ | 'undefined',
+ curr_fun_label :: label() | 'undefined',
curr_fun_args = 'empty' :: core_args(),
new_table = 'no_t' :: table(),
race_list = [] :: code(),
diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl
index 18f02e6742..987da3aecf 100644
--- a/lib/dialyzer/src/dialyzer_succ_typings.erl
+++ b/lib/dialyzer/src/dialyzer_succ_typings.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2006-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.
@@ -134,7 +134,6 @@ get_refined_success_typings(SCCs, #st{callgraph = Callgraph,
end
end.
--type doc_plt() :: 'undefined' | dialyzer_plt:plt().
-spec get_warnings(dialyzer_callgraph:callgraph(), dialyzer_plt:plt(),
doc_plt(), dialyzer_codeserver:codeserver(),
dialyzer_timing:timing_server(), [solver()], pid()) ->
diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl
index 0b8b244cc9..5f0881bbcd 100644
--- a/lib/dialyzer/src/dialyzer_typesig.erl
+++ b/lib/dialyzer/src/dialyzer_typesig.erl
@@ -68,7 +68,7 @@
-type type_var() :: erl_types:erl_type(). %% actually: {'c','var',_,_}
-record(fun_var, {'fun' :: fun((_) -> erl_types:erl_type()), deps :: [dep()],
- origin :: integer()}).
+ origin :: integer() | 'undefined'}).
-type constr_op() :: 'eq' | 'sub'.
-type fvar_or_type() :: #fun_var{} | erl_types:erl_type().
@@ -83,9 +83,9 @@
-record(constraint_list, {type :: 'conj' | 'disj',
list :: [constr()],
deps :: [dep()],
- masks :: [{dep(),[non_neg_integer()]}] |
- {'d',dict:dict(dep(), [non_neg_integer()])},
- id :: {'list', dep()}}).
+ masks = [] :: [{dep(),[non_neg_integer()]}] |
+ {'d',dict:dict(dep(), [non_neg_integer()])},
+ id :: {'list', dep()} | 'undefined'}).
-type constraint_list() :: #constraint_list{}.
@@ -104,7 +104,8 @@
-type dict_or_ets() :: {'d', prop_types()} | {'e', ets:tid()}.
--record(state, {callgraph :: dialyzer_callgraph:callgraph(),
+-record(state, {callgraph :: dialyzer_callgraph:callgraph()
+ | 'undefined',
cs = [] :: [constr()],
cmap = {'d', dict:new()} :: dict_or_ets(),
fun_map = [] :: typesig_funmap(),
@@ -116,7 +117,8 @@
cerl:c_fun()),
next_label = 0 :: label(),
self_rec :: 'false' | erl_types:erl_type(),
- plt :: dialyzer_plt:plt(),
+ plt :: dialyzer_plt:plt()
+ | 'undefined',
prop_types = {'d', dict:new()} :: dict_or_ets(),
records = dict:new() :: types(),
scc = [] :: [type_var()],
@@ -1746,7 +1748,10 @@ minimize_state(#state{
fun_arities = FunArities,
self_rec = SelfRec,
prop_types = {e, ETSPropTypes},
- solvers = Solvers
+ solvers = Solvers,
+ callgraph = undefined,
+ plt = undefined,
+ mfas = []
}.
dispose_state(#state{cmap = {e, ETSCMap},
@@ -2884,8 +2889,7 @@ mk_constraint(Lhs, Op, Rhs) ->
case t_is_any(Lhs) orelse constraint_opnd_is_any(Rhs) of
false ->
Deps = find_constraint_deps([Lhs, Rhs]),
- C0 = mk_constraint_1(Lhs, Op, Rhs),
- C = C0#constraint{deps = Deps},
+ C = mk_constraint_1(Lhs, Op, Rhs, Deps),
case Deps =:= [] of
true ->
%% This constraint is constant. Solve it immediately.
@@ -2903,8 +2907,7 @@ mk_constraint(Lhs, Op, Rhs) ->
end.
mk_constraint_any(Op) ->
- C = mk_constraint_1(t_any(), Op, t_any()),
- C#constraint{deps = []}.
+ mk_constraint_1(t_any(), Op, t_any(), []).
%% the following function is used so that we do not call
%% erl_types:t_is_any/1 with a term other than an erl_type()
@@ -2952,12 +2955,12 @@ find_constraint_deps([Type|Tail], Acc) ->
find_constraint_deps([], Acc) ->
lists:flatten(Acc).
-mk_constraint_1(Lhs, eq, Rhs) when Lhs < Rhs ->
- #constraint{lhs = Lhs, op = eq, rhs = Rhs};
-mk_constraint_1(Lhs, eq, Rhs) ->
- #constraint{lhs = Rhs, op = eq, rhs = Lhs};
-mk_constraint_1(Lhs, Op, Rhs) ->
- #constraint{lhs = Lhs, op = Op, rhs = Rhs}.
+mk_constraint_1(Lhs, eq, Rhs, Deps) when Lhs < Rhs ->
+ #constraint{lhs = Lhs, op = eq, rhs = Rhs, deps = Deps};
+mk_constraint_1(Lhs, eq, Rhs, Deps) ->
+ #constraint{lhs = Rhs, op = eq, rhs = Lhs, deps = Deps};
+mk_constraint_1(Lhs, Op, Rhs, Deps) ->
+ #constraint{lhs = Lhs, op = Op, rhs = Rhs, deps = Deps}.
mk_constraints([Lhs|LhsTail], Op, [Rhs|RhsTail]) ->
[mk_constraint(Lhs, Op, Rhs) |
diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl
index 7fe982a992..5fc1c0e691 100644
--- a/lib/dialyzer/src/dialyzer_utils.erl
+++ b/lib/dialyzer/src/dialyzer_utils.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2006-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.
@@ -83,7 +83,7 @@ print_types1([{record, _Name} = Key|T], RecDict) ->
%% ----------------------------------------------------------------------------
--type abstract_code() :: [tuple()]. %% XXX: import from somewhere
+-type abstract_code() :: [erl_parse:abstract_form()].
-type comp_options() :: [compile:option()].
-type mod_or_fname() :: module() | file:filename().
-type fa() :: {atom(), arity()}.
@@ -297,8 +297,8 @@ get_record_fields([], _RecDict, Acc) ->
%% The field types are cached. Used during analysis when handling records.
process_record_remote_types(CServer) ->
TempRecords = dialyzer_codeserver:get_temp_records(CServer),
- TempExpTypes = dialyzer_codeserver:get_temp_exported_types(CServer),
- TempRecords1 = process_opaque_types0(TempRecords, TempExpTypes),
+ ExpTypes = dialyzer_codeserver:get_exported_types(CServer),
+ TempRecords1 = process_opaque_types0(TempRecords, ExpTypes),
ModuleFun =
fun(Module, Record) ->
RecordFun =
@@ -310,7 +310,7 @@ process_record_remote_types(CServer) ->
Site = {record, {Module, Name, Arity}},
[{FieldName, Field,
erl_types:t_from_form(Field,
- TempExpTypes,
+ ExpTypes,
Site,
TempRecords1)}
|| {FieldName, Field, _} <- Fields]
@@ -323,9 +323,8 @@ process_record_remote_types(CServer) ->
dict:map(RecordFun, Record)
end,
NewRecords = dict:map(ModuleFun, TempRecords1),
- ok = check_record_fields(NewRecords, TempExpTypes),
- CServer1 = dialyzer_codeserver:finalize_records(NewRecords, CServer),
- dialyzer_codeserver:finalize_exported_types(TempExpTypes, CServer1).
+ ok = check_record_fields(NewRecords, ExpTypes),
+ dialyzer_codeserver:finalize_records(NewRecords, CServer).
%% erl_types:t_from_form() substitutes the declaration of opaque types
%% for the expanded type in some cases. To make sure the initial type,
diff --git a/lib/dialyzer/src/dialyzer_worker.erl b/lib/dialyzer/src/dialyzer_worker.erl
index 4be93c75bf..b9ab27c11d 100644
--- a/lib/dialyzer/src/dialyzer_worker.erl
+++ b/lib/dialyzer/src/dialyzer_worker.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2006-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.
@@ -21,20 +21,20 @@
-module(dialyzer_worker).
--export([launch/4, sequential/4]).
+-export([launch/4]).
-export_type([worker/0]).
--type worker() :: pid(). %%opaque
+-opaque worker() :: pid().
-type mode() :: dialyzer_coordinator:mode().
-type coordinator() :: dialyzer_coordinator:coordinator().
-type init_data() :: dialyzer_coordinator:init_data().
--type result() :: dialyzer_coordinator:result().
+-type job() :: dialyzer_coordinator:job().
-record(state, {
mode :: mode(),
- job :: mfa_or_funlbl() | file:filename(),
+ job :: job(),
coordinator :: coordinator(),
init_data :: init_data(),
depends_on = [] :: list()
@@ -52,23 +52,28 @@
%%--------------------------------------------------------------------
--spec launch(mode(), [mfa_or_funlbl()], init_data(), coordinator()) -> worker().
+-spec launch(mode(), job(), init_data(), coordinator()) -> worker().
launch(Mode, Job, InitData, Coordinator) ->
State = #state{mode = Mode,
job = Job,
init_data = InitData,
coordinator = Coordinator},
- InitState =
- case Mode of
- X when X =:= 'typesig'; X =:= 'dataflow' -> initializing;
- X when X =:= 'compile'; X =:= 'warnings' -> running
- end,
- spawn_link(fun() -> loop(InitState, State) end).
+ spawn_link(fun() -> init(State) end).
%%--------------------------------------------------------------------
-loop(updating, State) ->
+init(#state{job = SCC, mode = Mode, init_data = InitData} = State) when
+ Mode =:= 'typesig'; Mode =:= 'dataflow' ->
+ DependsOn = dialyzer_succ_typings:find_depends_on(SCC, InitData),
+ ?debug("Deps ~p: ~p\n",[SCC, DependsOn]),
+ loop(updating, State#state{depends_on = DependsOn});
+init(#state{mode = Mode} = State) when
+ Mode =:= 'compile'; Mode =:= 'warnings' ->
+ loop(running, State).
+
+loop(updating, #state{mode = Mode} = State) when
+ Mode =:= 'typesig'; Mode =:= 'dataflow' ->
?debug("Update: ~p\n",[State#state.job]),
NextStatus =
case waits_more_success_typings(State) of
@@ -76,16 +81,13 @@ loop(updating, State) ->
false -> running
end,
loop(NextStatus, State);
-loop(initializing, #state{job = SCC, init_data = InitData} = State) ->
- DependsOn = dialyzer_succ_typings:find_depends_on(SCC, InitData),
- ?debug("Deps ~p: ~p\n",[State#state.job, DependsOn]),
- loop(updating, State#state{depends_on = DependsOn});
-loop(waiting, State) ->
+loop(waiting, #state{mode = Mode} = State) when
+ Mode =:= 'typesig'; Mode =:= 'dataflow' ->
?debug("Wait: ~p\n",[State#state.job]),
NewState = wait_for_success_typings(State),
loop(updating, NewState);
loop(running, #state{mode = 'compile'} = State) ->
- dialyzer_coordinator:wait_activation(),
+ dialyzer_coordinator:request_activation(State#state.coordinator),
?debug("Compile: ~s\n",[State#state.job]),
Result =
case start_compilation(State) of
@@ -97,7 +99,7 @@ loop(running, #state{mode = 'compile'} = State) ->
end,
report_to_coordinator(Result, State);
loop(running, #state{mode = 'warnings'} = State) ->
- dialyzer_coordinator:wait_activation(),
+ dialyzer_coordinator:request_activation(State#state.coordinator),
?debug("Warning: ~s\n",[State#state.job]),
Result = collect_warnings(State),
report_to_coordinator(Result, State);
@@ -169,22 +171,3 @@ continue_compilation(Label, Data) ->
collect_warnings(#state{job = Job, init_data = InitData}) ->
dialyzer_succ_typings:collect_warnings(Job, InitData).
-
-%%------------------------------------------------------------------------------
-
--type extra() :: label() | 'unused'.
-
--spec sequential(mode(), [mfa_or_funlbl()], init_data(), extra()) -> result().
-
-sequential('compile', Job, InitData, Extra) ->
- case dialyzer_analysis_callgraph:start_compilation(Job, InitData) of
- {ok, EstimatedSize, Data} ->
- {EstimatedSize, continue_compilation(Extra, Data)};
- {error, _Reason} = Error -> {0, Error}
- end;
-sequential('typesig', Job, InitData, _Extra) ->
- dialyzer_succ_typings:find_succ_types_for_scc(Job, InitData);
-sequential('dataflow', Job, InitData, _Extra) ->
- dialyzer_succ_typings:refine_one_module(Job, InitData);
-sequential('warnings', Job, InitData, _Extra) ->
- dialyzer_succ_typings:collect_warnings(Job, InitData).
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs b/lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs
index 33d135048e..38999e8919 100644
--- a/lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/callbacks_and_specs
@@ -1,5 +1,5 @@
-my_callbacks_wrong.erl:26: The return type #state{parent::'undefined' | pid(),status::'closed' | 'init' | 'open',subscribe::[{pid(),integer()}],counter::integer()} in the specification of callback_init/1 is not a subtype of {'ok',_}, which is the expected return type for the callback of my_behaviour behaviour
-my_callbacks_wrong.erl:28: The inferred return type of callback_init/1 (#state{parent::'undefined' | pid(),status::'init',subscribe::[],counter::1}) has nothing in common with {'ok',_}, which is the expected return type for the callback of my_behaviour behaviour
-my_callbacks_wrong.erl:30: The return type {'reply',#state{parent::'undefined' | pid(),status::'closed' | 'init' | 'open',subscribe::[{pid(),integer()}],counter::integer()}} in the specification of callback_cast/3 is not a subtype of {'noreply',_}, which is the expected return type for the callback of my_behaviour behaviour
+my_callbacks_wrong.erl:26: The return type #state{parent::pid(),status::'closed' | 'init' | 'open',subscribe::[{pid(),integer()}],counter::integer()} in the specification of callback_init/1 is not a subtype of {'ok',_}, which is the expected return type for the callback of my_behaviour behaviour
+my_callbacks_wrong.erl:28: The inferred return type of callback_init/1 (#state{parent::pid(),status::'init',subscribe::[],counter::1}) has nothing in common with {'ok',_}, which is the expected return type for the callback of my_behaviour behaviour
+my_callbacks_wrong.erl:30: The return type {'reply',#state{parent::pid(),status::'closed' | 'init' | 'open',subscribe::[{pid(),integer()}],counter::integer()}} in the specification of callback_cast/3 is not a subtype of {'noreply',_}, which is the expected return type for the callback of my_behaviour behaviour
my_callbacks_wrong.erl:39: The specified type for the 2nd argument of callback_call/3 (atom()) is not a supertype of pid(), which is expected type for this argument in the callback of the my_behaviour behaviour
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/supervisor_incorrect_return b/lib/dialyzer/test/behaviour_SUITE_data/results/supervisor_incorrect_return
index 4103a2d8b4..89eb295604 100644
--- a/lib/dialyzer/test/behaviour_SUITE_data/results/supervisor_incorrect_return
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/supervisor_incorrect_return
@@ -1,2 +1,2 @@
-supervisor_incorrect_return.erl:14: The inferred return type of init/1 ({'ok',{{'one_against_one',0,1},[{_,_,_,_,_,_},...]}}) has nothing in common with 'ignore' | {'ok',{{'one_for_all',non_neg_integer(),pos_integer()} | {'one_for_one',non_neg_integer(),pos_integer()} | {'rest_for_one',non_neg_integer(),pos_integer()} | {'simple_one_for_one',non_neg_integer(),pos_integer()} | #{},[{_,{atom() | tuple(),atom(),'undefined' | [any()]},'permanent' | 'temporary' | 'transient','brutal_kill' | 'infinity' | non_neg_integer(),'supervisor' | 'worker','dynamic' | [atom() | tuple()]} | #{}]}}, which is the expected return type for the callback of supervisor behaviour
+supervisor_incorrect_return.erl:14: The inferred return type of init/1 ({'ok',{{'one_against_one',0,1},[{_,_,_,_,_,_},...]}}) has nothing in common with 'ignore' | {'ok',{{'one_for_all',non_neg_integer(),pos_integer()} | {'one_for_one',non_neg_integer(),pos_integer()} | {'rest_for_one',non_neg_integer(),pos_integer()} | {'simple_one_for_one',non_neg_integer(),pos_integer()} | #{},[{_,{atom(),atom(),'undefined' | [any()]},'permanent' | 'temporary' | 'transient','brutal_kill' | 'infinity' | non_neg_integer(),'supervisor' | 'worker','dynamic' | [atom()]} | #{}]}}, which is the expected return type for the callback of supervisor behaviour
diff --git a/lib/dialyzer/test/dialyzer_SUITE.erl b/lib/dialyzer/test/dialyzer_SUITE.erl
index 80f4508ec6..8a2324a7c2 100644
--- a/lib/dialyzer/test/dialyzer_SUITE.erl
+++ b/lib/dialyzer/test/dialyzer_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(dialyzer_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Default timetrap timeout (set in init_per_testcase).
-define(default_timeout, ?t:minutes(1)).
diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/crash b/lib/dialyzer/test/opaque_SUITE_data/results/crash
index 69bdc00257..d63389f79c 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/results/crash
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/crash
@@ -1,6 +1,6 @@
-crash_1.erl:45: Record construction #targetlist{list::[]} violates the declared type of field list::'undefined' | crash_1:target()
-crash_1.erl:48: The call crash_1:get_using_branch2(Branch::maybe_improper_list(),L::'undefined' | crash_1:target()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),maybe_improper_list())
-crash_1.erl:50: The pattern <_Branch, []> can never match the type <maybe_improper_list(),'undefined' | crash_1:target()>
-crash_1.erl:52: The pattern <Branch, [H = {'target', _, _} | _T]> can never match the type <maybe_improper_list(),'undefined' | crash_1:target()>
-crash_1.erl:54: The pattern <Branch, [{'target', _, _} | T]> can never match the type <maybe_improper_list(),'undefined' | crash_1:target()>
+crash_1.erl:45: Record construction #targetlist{list::[]} violates the declared type of field list::crash_1:target()
+crash_1.erl:48: The call crash_1:get_using_branch2(Branch::maybe_improper_list(),L::crash_1:target()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),maybe_improper_list())
+crash_1.erl:50: The pattern <_Branch, []> can never match the type <maybe_improper_list(),crash_1:target()>
+crash_1.erl:52: The pattern <Branch, [H = {'target', _, _} | _T]> can never match the type <maybe_improper_list(),crash_1:target()>
+crash_1.erl:54: The pattern <Branch, [{'target', _, _} | T]> can never match the type <maybe_improper_list(),crash_1:target()>
diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/simple b/lib/dialyzer/test/opaque_SUITE_data/results/simple
index 1a7a139d6e..391c37664e 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/results/simple
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/simple
@@ -18,7 +18,7 @@ rec_api.erl:104: Matching of pattern {'r2', 10} tagged with a record name violat
rec_api.erl:113: The attempt to match a term of type #r3{f1::queue:queue(_)} against the pattern {'r3', 'a'} breaks the opaqueness of queue:queue(_)
rec_api.erl:118: Record construction #r3{f1::10} violates the declared type of field f1::queue:queue(_)
rec_api.erl:123: The attempt to match a term of type #r3{f1::10} against the pattern {'r3', 10} breaks the opaqueness of queue:queue(_)
-rec_api.erl:24: Record construction #r1{f1::10} violates the declared type of field f1::'undefined' | rec_api:a()
+rec_api.erl:24: Record construction #r1{f1::10} violates the declared type of field f1::rec_api:a()
rec_api.erl:29: Matching of pattern {'r1', 10} tagged with a record name violates the declared type of #r1{f1::10}
rec_api.erl:33: The attempt to match a term of type rec_adt:r1() against the pattern {'r1', 'a'} breaks the opaqueness of the term
rec_api.erl:35: Invalid type specification for function rec_api:adt_t1/1. The success typing is (#r1{f1::'a'}) -> #r1{f1::'a'}
@@ -70,8 +70,8 @@ simple1_api.erl:478: The call 'foo':A(A::simple1_adt:a()) breaks the opaqueness
simple1_api.erl:486: The call A:'foo'(A::simple1_adt:a()) breaks the opaqueness of the term A :: simple1_adt:a()
simple1_api.erl:499: The call 'foo':A(A::simple1_api:i()) requires that A is of type atom() not simple1_api:i()
simple1_api.erl:503: The call 'foo':A(A::simple1_adt:i()) requires that A is of type atom() not simple1_adt:i()
-simple1_api.erl:507: The call A:'foo'(A::simple1_api:i()) requires that A is of type atom() | tuple() not simple1_api:i()
-simple1_api.erl:511: The call A:'foo'(A::simple1_adt:i()) requires that A is of type atom() | tuple() not simple1_adt:i()
+simple1_api.erl:507: The call A:'foo'(A::simple1_api:i()) requires that A is of type atom() not simple1_api:i()
+simple1_api.erl:511: The call A:'foo'(A::simple1_adt:i()) requires that A is of type atom() not simple1_adt:i()
simple1_api.erl:519: Guard test A::simple1_adt:d2() == B::simple1_adt:d1() contains opaque terms as 1st and 2nd arguments
simple1_api.erl:534: Guard test A::simple1_adt:d1() >= 3 contains an opaque term as 1st argument
simple1_api.erl:536: Guard test A::simple1_adt:d1() == 3 contains an opaque term as 1st argument
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl b/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl
index b6cab5e24b..1677b4efb8 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl
@@ -781,7 +781,8 @@ add_mod_info({attribute,_Line,record,{RecName,Fields}},
true ->
ModInfo;
false ->
- TypedRecord = {attribute,0,type,{{record,RecName},Fields,[]}},
+ A = erl_anno:new(0),
+ TypedRecord = {attribute,A,type,{{record,RecName},Fields,[]}},
add_mod_info(TypedRecord, ModInfo)
end;
add_mod_info({attribute,_Line,Kind,{Name,TypeForm,VarForms}},
diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia
index b73943422a..bf67447ee7 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia
+++ b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia
@@ -6,7 +6,7 @@ mnesia_bup.erl:111: The created fun has no local return
mnesia_bup.erl:574: Function fallback_receiver/2 has no local return
mnesia_bup.erl:967: Function uninstall_fallback_master/2 has no local return
mnesia_checkpoint.erl:1014: The variable Error can never match since previous clauses completely covered the type {'ok',#checkpoint_args{nodes::[any()],retainers::[any(),...]}}
-mnesia_checkpoint.erl:894: The call sys:handle_system_msg(Msg::any(),From::any(),'no_parent','mnesia_checkpoint',[],Cp::#checkpoint_args{}) breaks the contract (Msg,From,Parent,Module,Debug,Misc) -> no_return() when is_subtype(Msg,term()), is_subtype(From,{pid(),Tag::_}), is_subtype(Parent,pid()), is_subtype(Module,module()), is_subtype(Debug,[dbg_opt()]), is_subtype(Misc,term())
+mnesia_checkpoint.erl:894: The call sys:handle_system_msg(Msg::any(),From::any(),'no_parent','mnesia_checkpoint',[],Cp::#checkpoint_args{}) breaks the contract (Msg,From,Parent,Module,Debug,Misc) -> no_return() when Msg :: term(), From :: {pid(),Tag::_}, Parent :: pid(), Module :: module(), Debug :: [dbg_opt()], Misc :: term()
mnesia_controller.erl:1666: The variable Tab can never match since previous clauses completely covered the type [any()]
mnesia_controller.erl:1679: The pattern {'stop', Reason, Reply, State2} can never match the type {'noreply',_} | {'reply',_,_} | {'stop','shutdown',#state{}}
mnesia_controller.erl:1685: The pattern {'noreply', State2, _Timeout} can never match the type {'reply',_,_}
@@ -35,6 +35,6 @@ mnesia_schema.erl:1258: Guard test FromS::'disc_copies' | 'disc_only_copies' | '
mnesia_schema.erl:1639: The pattern {'false', 'mandatory'} can never match the type {'false','optional'}
mnesia_schema.erl:2434: The variable Reason can never match since previous clauses completely covered the type {'error',_} | {'ok',_}
mnesia_schema.erl:451: Guard test UseDirAnyway::'false' == 'true' can never succeed
-mnesia_text.erl:180: The variable T can never match since previous clauses completely covered the type {'error',{integer(),atom() | tuple(),_}} | {'ok',_}
+mnesia_text.erl:180: The variable T can never match since previous clauses completely covered the type {'error',{non_neg_integer(),atom(),_}} | {'ok',_}
mnesia_tm.erl:1522: Function commit_participant/5 has no local return
mnesia_tm.erl:2169: Function system_terminate/4 has no local return
diff --git a/lib/dialyzer/test/small_SUITE_data/results/app_call b/lib/dialyzer/test/small_SUITE_data/results/app_call
index cc1a63f944..1af649815a 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/app_call
+++ b/lib/dialyzer/test/small_SUITE_data/results/app_call
@@ -1,3 +1,3 @@
-app_call.erl:6: The call M:'foo'() requires that M is of type atom() | tuple() not 42
+app_call.erl:6: The call M:'foo'() requires that M is of type atom() not 42
app_call.erl:9: The call 'mod':F() requires that F is of type atom() not {'gazonk',[]}
diff --git a/lib/dialyzer/test/small_SUITE_data/results/bif1 b/lib/dialyzer/test/small_SUITE_data/results/bif1
new file mode 100644
index 0000000000..289b6f821f
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/bif1
@@ -0,0 +1,3 @@
+
+bif1.erl:13: Function string_chars/0 has no local return
+bif1.erl:16: The call string:chars(S::65,10,L2::bif1_adt:s()) contains an opaque term as 3rd argument when terms of different types are expected in these positions
diff --git a/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes b/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes
index a9fbfb6068..d2a3ebb766 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes
+++ b/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes
@@ -1,15 +1,15 @@
-contracts_with_subtypes.erl:106: The call contracts_with_subtypes:rec_arg({'a','b'}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A})
-contracts_with_subtypes.erl:107: The call contracts_with_subtypes:rec_arg({'b','a'}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A})
-contracts_with_subtypes.erl:109: The call contracts_with_subtypes:rec_arg({'b',{'a','b'}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A})
-contracts_with_subtypes.erl:135: The call contracts_with_subtypes:rec2({'a','b'}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab())
-contracts_with_subtypes.erl:136: The call contracts_with_subtypes:rec2({'b','a'}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab())
-contracts_with_subtypes.erl:137: The call contracts_with_subtypes:rec2({'a',{'b','a'}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab())
-contracts_with_subtypes.erl:138: The call contracts_with_subtypes:rec2({'b',{'a','b'}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab())
-contracts_with_subtypes.erl:139: The call contracts_with_subtypes:rec2({'a',{'b',{'a','b'}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab())
-contracts_with_subtypes.erl:140: The call contracts_with_subtypes:rec2({'b',{'a',{'b','a'}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab())
-contracts_with_subtypes.erl:141: The call contracts_with_subtypes:rec2({'a',{'b',{'a',{'b','a'}}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab())
-contracts_with_subtypes.erl:142: The call contracts_with_subtypes:rec2({'b',{'a',{'b',{'a','b'}}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab())
+contracts_with_subtypes.erl:106: The call contracts_with_subtypes:rec_arg({'a','b'}) breaks the contract (Arg) -> 'ok' when Arg :: {'a',A} | {'b',B}, A :: 'a' | {'b',B}, B :: 'b' | {'a',A}
+contracts_with_subtypes.erl:107: The call contracts_with_subtypes:rec_arg({'b','a'}) breaks the contract (Arg) -> 'ok' when Arg :: {'a',A} | {'b',B}, A :: 'a' | {'b',B}, B :: 'b' | {'a',A}
+contracts_with_subtypes.erl:109: The call contracts_with_subtypes:rec_arg({'b',{'a','b'}}) breaks the contract (Arg) -> 'ok' when Arg :: {'a',A} | {'b',B}, A :: 'a' | {'b',B}, B :: 'b' | {'a',A}
+contracts_with_subtypes.erl:135: The call contracts_with_subtypes:rec2({'a','b'}) breaks the contract (Arg) -> 'ok' when Arg :: ab()
+contracts_with_subtypes.erl:136: The call contracts_with_subtypes:rec2({'b','a'}) breaks the contract (Arg) -> 'ok' when Arg :: ab()
+contracts_with_subtypes.erl:137: The call contracts_with_subtypes:rec2({'a',{'b','a'}}) breaks the contract (Arg) -> 'ok' when Arg :: ab()
+contracts_with_subtypes.erl:138: The call contracts_with_subtypes:rec2({'b',{'a','b'}}) breaks the contract (Arg) -> 'ok' when Arg :: ab()
+contracts_with_subtypes.erl:139: The call contracts_with_subtypes:rec2({'a',{'b',{'a','b'}}}) breaks the contract (Arg) -> 'ok' when Arg :: ab()
+contracts_with_subtypes.erl:140: The call contracts_with_subtypes:rec2({'b',{'a',{'b','a'}}}) breaks the contract (Arg) -> 'ok' when Arg :: ab()
+contracts_with_subtypes.erl:141: The call contracts_with_subtypes:rec2({'a',{'b',{'a',{'b','a'}}}}) breaks the contract (Arg) -> 'ok' when Arg :: ab()
+contracts_with_subtypes.erl:142: The call contracts_with_subtypes:rec2({'b',{'a',{'b',{'a','b'}}}}) breaks the contract (Arg) -> 'ok' when Arg :: ab()
contracts_with_subtypes.erl:175: The pattern 1 can never match the type string()
contracts_with_subtypes.erl:178: The pattern 'alpha' can never match the type {'ok',_} | {'ok',_,string()}
contracts_with_subtypes.erl:180: The pattern 42 can never match the type {'ok',_} | {'ok',_,string()}
@@ -24,13 +24,13 @@ contracts_with_subtypes.erl:23: Invalid type specification for function contract
contracts_with_subtypes.erl:240: The pattern {'ok', 42} can never match the type {'ok',_,string()}
contracts_with_subtypes.erl:241: The pattern 42 can never match the type {'ok',_,string()}
contracts_with_subtypes.erl:267: Function flat_ets_new_t/0 has no local return
-contracts_with_subtypes.erl:268: The call contracts_with_subtypes:flat_ets_new(12,[]) breaks the contract (Name,Options) -> atom() when is_subtype(Name,atom()), is_subtype(Options,[Option]), is_subtype(Option,'set' | 'ordered_set' | 'bag' | 'duplicate_bag' | 'public' | 'protected' | 'private' | 'named_table' | {'keypos',integer()} | {'heir',pid(),term()} | {'heir','none'} | {'write_concurrency',boolean()} | {'read_concurrency',boolean()} | 'compressed')
+contracts_with_subtypes.erl:268: The call contracts_with_subtypes:flat_ets_new(12,[]) breaks the contract (Name,Options) -> atom() when Name :: atom(), Options :: [Option], Option :: 'set' | 'ordered_set' | 'bag' | 'duplicate_bag' | 'public' | 'protected' | 'private' | 'named_table' | {'keypos',integer()} | {'heir',pid(),term()} | {'heir','none'} | {'write_concurrency',boolean()} | {'read_concurrency',boolean()} | 'compressed'
contracts_with_subtypes.erl:294: Function factored_ets_new_t/0 has no local return
-contracts_with_subtypes.erl:295: The call contracts_with_subtypes:factored_ets_new(12,[]) breaks the contract (Name,Options) -> atom() when is_subtype(Name,atom()), is_subtype(Options,[Option]), is_subtype(Option,Type | Access | 'named_table' | {'keypos',Pos} | {'heir',Pid::pid(),HeirData} | {'heir','none'} | Tweaks), is_subtype(Type,type()), is_subtype(Access,access()), is_subtype(Tweaks,{'write_concurrency',boolean()} | {'read_concurrency',boolean()} | 'compressed'), is_subtype(Pos,pos_integer()), is_subtype(HeirData,term())
-contracts_with_subtypes.erl:77: The call contracts_with_subtypes:foo1(5) breaks the contract (Arg1) -> Res when is_subtype(Arg1,atom()), is_subtype(Res,atom())
-contracts_with_subtypes.erl:78: The call contracts_with_subtypes:foo2(5) breaks the contract (Arg1) -> Res when is_subtype(Arg1,Arg2), is_subtype(Arg2,atom()), is_subtype(Res,atom())
-contracts_with_subtypes.erl:79: The call contracts_with_subtypes:foo3(5) breaks the contract (Arg1) -> Res when is_subtype(Arg2,atom()), is_subtype(Arg1,Arg2), is_subtype(Res,atom())
+contracts_with_subtypes.erl:295: The call contracts_with_subtypes:factored_ets_new(12,[]) breaks the contract (Name,Options) -> atom() when Name :: atom(), Options :: [Option], Option :: Type | Access | 'named_table' | {'keypos',Pos} | {'heir',Pid::pid(),HeirData} | {'heir','none'} | Tweaks, Type :: type(), Access :: access(), Tweaks :: {'write_concurrency',boolean()} | {'read_concurrency',boolean()} | 'compressed', Pos :: pos_integer(), HeirData :: term()
+contracts_with_subtypes.erl:77: The call contracts_with_subtypes:foo1(5) breaks the contract (Arg1) -> Res when Arg1 :: atom(), Res :: atom()
+contracts_with_subtypes.erl:78: The call contracts_with_subtypes:foo2(5) breaks the contract (Arg1) -> Res when Arg1 :: Arg2, Arg2 :: atom(), Res :: atom()
+contracts_with_subtypes.erl:79: The call contracts_with_subtypes:foo3(5) breaks the contract (Arg1) -> Res when Arg2 :: atom(), Arg1 :: Arg2, Res :: atom()
contracts_with_subtypes.erl:7: Invalid type specification for function contracts_with_subtypes:extract/0. The success typing is () -> 'something'
-contracts_with_subtypes.erl:80: The call contracts_with_subtypes:foo4(5) breaks the contract (Type) -> Type when is_subtype(Type,atom())
+contracts_with_subtypes.erl:80: The call contracts_with_subtypes:foo4(5) breaks the contract (Type) -> Type when Type :: atom()
contracts_with_subtypes.erl:81: The call contracts_with_subtypes:foo5(5) breaks the contract (Type::atom()) -> Type::atom()
-contracts_with_subtypes.erl:82: The call contracts_with_subtypes:foo6(5) breaks the contract (Type) -> Type when is_subtype(Type,atom())
+contracts_with_subtypes.erl:82: The call contracts_with_subtypes:foo6(5) breaks the contract (Type) -> Type when Type :: atom()
diff --git a/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes2 b/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes2
index 9f5433a13d..1a8aeb13d0 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes2
+++ b/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes2
@@ -1,3 +1,3 @@
contracts_with_subtypes2.erl:18: Function t/0 has no local return
-contracts_with_subtypes2.erl:19: The call contracts_with_subtypes2:t({'a',{'b',{'c',{'d',{'e',{'g',3}}}}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A}), is_subtype(A,{'b',B}), is_subtype(B,{'c',C}), is_subtype(C,{'d',D}), is_subtype(D,{'e',E}), is_subtype(E,{'f',_})
+contracts_with_subtypes2.erl:19: The call contracts_with_subtypes2:t({'a',{'b',{'c',{'d',{'e',{'g',3}}}}}}) breaks the contract (Arg) -> 'ok' when Arg :: {'a',A}, A :: {'b',B}, B :: {'c',C}, C :: {'d',D}, D :: {'e',E}, E :: {'f',_}
diff --git a/lib/dialyzer/test/small_SUITE_data/results/literals b/lib/dialyzer/test/small_SUITE_data/results/literals
index 03e161ca71..222d2c0cdb 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/literals
+++ b/lib/dialyzer/test/small_SUITE_data/results/literals
@@ -1,14 +1,14 @@
literals.erl:11: Function t1/0 has no local return
-literals.erl:12: Record construction #r{id::'a'} violates the declared type of field id::'integer' | 'undefined'
+literals.erl:12: Record construction #r{id::'a'} violates the declared type of field id::'integer'
literals.erl:14: Function t2/0 has no local return
-literals.erl:15: Record construction #r{id::'a'} violates the declared type of field id::'integer' | 'undefined'
+literals.erl:15: Record construction #r{id::'a'} violates the declared type of field id::'integer'
literals.erl:17: Function t3/0 has no local return
-literals.erl:18: Record construction #r{id::'a'} violates the declared type of field id::'integer' | 'undefined'
-literals.erl:21: Record construction #r{id::'a'} violates the declared type of field id::'integer' | 'undefined'
+literals.erl:18: Record construction #r{id::'a'} violates the declared type of field id::'integer'
+literals.erl:21: Record construction #r{id::'a'} violates the declared type of field id::'integer'
literals.erl:23: Function m1/1 has no local return
-literals.erl:23: Matching of pattern {'r', 'a'} tagged with a record name violates the declared type of #r{id::'integer' | 'undefined'}
+literals.erl:23: Matching of pattern {'r', 'a'} tagged with a record name violates the declared type of #r{id::'integer'}
literals.erl:26: Function m2/1 has no local return
-literals.erl:26: Matching of pattern {'r', 'a'} tagged with a record name violates the declared type of #r{id::'integer' | 'undefined'}
+literals.erl:26: Matching of pattern {'r', 'a'} tagged with a record name violates the declared type of #r{id::'integer'}
literals.erl:29: Function m3/1 has no local return
literals.erl:29: The pattern {{'r', 'a'}} can never match the type any()
diff --git a/lib/dialyzer/test/small_SUITE_data/results/maps1 b/lib/dialyzer/test/small_SUITE_data/results/maps1
index 5a78d66a92..e88c91f21f 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/maps1
+++ b/lib/dialyzer/test/small_SUITE_data/results/maps1
@@ -1,4 +1,4 @@
maps1.erl:43: Function t3/0 has no local return
maps1.erl:44: The call maps1:foo(~{'greger'=>3, ~{'arne'=>'anka'}~=>45}~,1) will never return since it differs in the 2nd argument from the success typing arguments: (#{},'b')
-maps1.erl:52: The call Mod:'function'(~{'literal'=>'map'}~,'another_arg') requires that Mod is of type atom() | tuple() not #{}
+maps1.erl:52: The call Mod:'function'(~{'literal'=>'map'}~,'another_arg') requires that Mod is of type atom() not #{}
diff --git a/lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring b/lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring
index 0ad6eee766..e148e5cf22 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring
+++ b/lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring
@@ -1,3 +1,3 @@
pretty_bitstring.erl:7: Function t/0 has no local return
-pretty_bitstring.erl:8: The call binary:copy(#{#<1>(8, 1, 'integer', ['unsigned', 'big']), #<2>(8, 1, 'integer', ['unsigned', 'big']), #<3>(3, 1, 'integer', ['unsigned', 'big'])}#,2) breaks the contract (Subject,N) -> binary() when is_subtype(Subject,binary()), is_subtype(N,non_neg_integer())
+pretty_bitstring.erl:8: The call binary:copy(#{#<1>(8, 1, 'integer', ['unsigned', 'big']), #<2>(8, 1, 'integer', ['unsigned', 'big']), #<3>(3, 1, 'integer', ['unsigned', 'big'])}#,2) breaks the contract (Subject,N) -> binary() when Subject :: binary(), N :: non_neg_integer()
diff --git a/lib/dialyzer/test/small_SUITE_data/results/record_creation_diffs b/lib/dialyzer/test/small_SUITE_data/results/record_creation_diffs
index f00c4b10ff..c971935bbf 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/record_creation_diffs
+++ b/lib/dialyzer/test/small_SUITE_data/results/record_creation_diffs
@@ -1,3 +1,3 @@
record_creation_diffs.erl:10: Function foo/1 has no local return
-record_creation_diffs.erl:11: Record construction #bar{some_list::{'this','is','a','tuple'}} violates the declared type of field some_list::'undefined' | [any()]
+record_creation_diffs.erl:11: Record construction #bar{some_list::{'this','is','a','tuple'}} violates the declared type of field some_list::[any()]
diff --git a/lib/dialyzer/test/small_SUITE_data/results/record_pat b/lib/dialyzer/test/small_SUITE_data/results/record_pat
index a46be6c451..8317ea041a 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/record_pat
+++ b/lib/dialyzer/test/small_SUITE_data/results/record_pat
@@ -1,2 +1,2 @@
-record_pat.erl:14: Matching of pattern {'foo', 'baz'} tagged with a record name violates the declared type of #foo{bar::'undefined' | integer()}
+record_pat.erl:14: Matching of pattern {'foo', 'baz'} tagged with a record name violates the declared type of #foo{bar::integer()}
diff --git a/lib/dialyzer/test/small_SUITE_data/results/relevant_record_warning b/lib/dialyzer/test/small_SUITE_data/results/relevant_record_warning
index 2e417e1b2a..ea3ac92d96 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/relevant_record_warning
+++ b/lib/dialyzer/test/small_SUITE_data/results/relevant_record_warning
@@ -1,3 +1,3 @@
relevant_record_warning.erl:22: Function test/1 has no local return
-relevant_record_warning.erl:23: Record construction #r{field::<<_:8>>} violates the declared type of field field::'binary' | 'undefined'
+relevant_record_warning.erl:23: Record construction #r{field::<<_:8>>} violates the declared type of field field::'binary'
diff --git a/lib/dialyzer/test/small_SUITE_data/results/undefined b/lib/dialyzer/test/small_SUITE_data/results/undefined
new file mode 100644
index 0000000000..9daa8640d3
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/undefined
@@ -0,0 +1,2 @@
+
+r.erl:16: Record construction #r{a::{'fi'},b::{'a','b'},c::[],d::'undefined',e::[],f::'undefined'} violates the declared type of field b::[any()] and d::[any()] and f::[any()]
diff --git a/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1.erl b/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1.erl
new file mode 100644
index 0000000000..bc746538d3
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1.erl
@@ -0,0 +1,16 @@
+-module(bif1).
+
+%% Other set of warnings due to removed of functions from
+%% erl_bif_types.
+
+-export([ets_rename/0, string_chars/0]).
+
+ets_rename() ->
+ A = ets:new(fipp, []),
+ true = not is_atom(A),
+ ets:rename(A, fopp). % No warning
+
+string_chars() ->
+ L2 = bif1_adt:opaque_string(),
+ S = $A,
+ string:chars(S, 10, L2). % Warning
diff --git a/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1_adt.erl b/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1_adt.erl
new file mode 100644
index 0000000000..01b0bccc68
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/bif1/bif1_adt.erl
@@ -0,0 +1,12 @@
+-module(bif1_adt).
+
+-export([opaque_string/0]).
+
+-export_type([s/0]).
+
+-opaque s() :: string().
+
+-spec opaque_string() -> s().
+
+opaque_string() ->
+ "string".
diff --git a/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl b/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl
index ab84e94106..9ad4810a5e 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl
@@ -36,7 +36,7 @@
%% Start of Abstract Format
--type line() :: erl_scan:line().
+-type line() :: erl_anno:line().
-export_type([af_record_index/0, af_record_field/1, af_record_name/0,
af_field_name/0, af_function_decl/0]).
@@ -332,8 +332,8 @@
%% End of Abstract Format
-type error_description() :: term().
--type error_info() :: {erl_scan:line(), module(), error_description()}.
--type token() :: {Tag :: atom(), Line :: erl_scan:line()}.
+-type error_info() :: {erl_anno:line(), module(), error_description()}.
+-type token() :: {Tag :: atom(), Line :: erl_scan:anno()}.
%% mkop(Op, Arg) -> {op,Line,Op,Arg}.
%% mkop(Left, Op, Right) -> {op,Line,Op,Left,Right}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl b/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl
index fc7c5241a8..fe567ff10d 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl
@@ -36,7 +36,7 @@
%% Start of Abstract Format
--type line() :: erl_scan:line().
+-type line() :: erl_anno:line().
-export_type([af_module/0, af_export/0, af_import/0, af_fa_list/0,
af_compile/0, af_file/0, af_record_decl/0,
@@ -329,8 +329,8 @@
%% End of Abstract Format
-type error_description() :: term().
--type error_info() :: {erl_scan:line(), module(), error_description()}.
--type token() :: {Tag :: atom(), Line :: erl_scan:line()}.
+-type error_info() :: {erl_anno:line(), module(), error_description()}.
+-type token() :: {Tag :: atom(), Line :: erl_anno:line()}.
%% mkop(Op, Arg) -> {op,Line,Op,Arg}.
%% mkop(Left, Op, Right) -> {op,Line,Op,Left,Right}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/trec.erl b/lib/dialyzer/test/small_SUITE_data/src/trec.erl
index 06706162c1..516358f7c6 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/trec.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/trec.erl
@@ -8,7 +8,7 @@
-module(trec).
-export([test/0, mk_foo_exp/2]).
--record(foo, {a :: integer(), b :: [atom()]}).
+-record(foo, {a :: integer() | 'undefined', b :: [atom()]}).
%%
%% For these functions we currently get the following warnings:
diff --git a/lib/dialyzer/test/small_SUITE_data/undefined.erl b/lib/dialyzer/test/small_SUITE_data/undefined.erl
new file mode 100644
index 0000000000..8549f2e161
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/undefined.erl
@@ -0,0 +1,29 @@
+-module(undefined).
+
+-export([t/0]).
+
+%% As of OTP 19.0 'undefined' is no longer added to fields with a type
+%% declaration but without an initializer. The pretty printing of
+%% records (erl_types:t_to_string()) is updated to reflect this: if a
+%% field is of type 'undefined', it is output if 'undefined' is not in
+%% the declared type of the field. (It used to be the case that the
+%% singleton type 'undefined' was never output.)
+%%
+%% One consequence is shown by the example below: the warning about
+%% the record construction violating the the declared type shows
+%% #r{..., d::'undefined', ...} which is meant to be of help to the
+%% user, who could otherwise get confused the first time (s)he gets
+%% confronted by the warning.
+
+-record(r,
+ {
+ a = {fi},
+ b = {a,b} :: list(), % violation
+ c = {a,b} :: list(),
+ d :: list(), % violation
+ e = [] :: list(),
+ f = undefined :: list() % violation
+ }).
+
+t() ->
+ #r{c = []}.
diff --git a/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu b/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu
index d1f8f4caf2..626e677524 100644
--- a/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu
+++ b/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu
@@ -6,7 +6,7 @@ wsp_pdu.erl:2403: The call wsp_pdu:d_date(Data1::binary()) will never return sin
wsp_pdu.erl:2406: Guard test is_integer(Sec::{[byte()] | byte() | {'long',binary()} | {'short',binary()},binary()}) can never succeed
wsp_pdu.erl:2408: The pattern {'short', Data2} can never match the type {[byte()] | byte() | {'long',binary()} | {'short',binary()},binary()}
wsp_pdu.erl:2755: Function parse_push_flag/1 has no local return
-wsp_pdu.erl:2756: The call erlang:integer_to_list(Value::[any()]) breaks the contract (Integer) -> string() when is_subtype(Integer,integer())
+wsp_pdu.erl:2756: The call erlang:integer_to_list(Value::[any()]) breaks the contract (Integer) -> string() when Integer :: integer()
wsp_pdu.erl:2875: The call wsp_pdu:d_text_string(Data::byte()) will never return since it differs in the 1st argument from the success typing arguments: (binary())
wsp_pdu.erl:2976: The call wsp_pdu:d_q_value(QData::byte()) will never return since it differs in the 1st argument from the success typing arguments: (<<_:8,_:_*8>>)
wsp_pdu.erl:3336: The call wsp_pdu:encode_typed_field(Ver::any(),'Q-value',ParamValue::any()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),'Constrained-encoding' | 'Date-value' | 'No-value' | 'Short-integer' | 'Text-string' | 'Text-value' | 'Well-known-charset',any())
diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl
index 2b23183d18..fb874013a3 100644
--- a/lib/diameter/src/base/diameter_peer_fsm.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm.erl
@@ -117,7 +117,7 @@
parent :: pid(), %% watchdog process
transport :: pid(), %% transport process
dictionary :: module(), %% common dictionary
- service :: #diameter_service{},
+ service :: #diameter_service{} | undefined,
dpr = false :: false
| true %% DPR received, DPA sent
| {boolean(), uint32(), uint32()},
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
index 87ef2e522d..efa4cc9108 100644
--- a/lib/diameter/src/base/diameter_service.erl
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -128,7 +128,7 @@
%% Record representing an RFC 3539 watchdog process implemented by
%% diameter_watchdog.
-record(watchdog,
- {pid :: match(pid()),
+ {pid :: match(pid()) | undefined,
type :: match(connect | accept),
ref :: match(reference()), %% key into diameter_config
options :: match([diameter:transport_opt()]),%% from start_transport
diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl
index 678dc9b5d6..8a80ce630a 100644
--- a/lib/diameter/src/transport/diameter_sctp.erl
+++ b/lib/diameter/src/transport/diameter_sctp.erl
@@ -84,16 +84,18 @@
%% Accepting/connecting transport process state.
-record(transport,
- {parent :: pid(),
+ {parent :: pid() | undefined,
mode :: {accept, pid()}
| accept
| {connect, {[inet:ip_address()], uint(), list()}}
%% {RAs, RP, Errors}
| connect,
- socket :: gen_sctp:sctp_socket(),
+ socket :: gen_sctp:sctp_socket() | undefined,
assoc_id :: gen_sctp:assoc_id(), %% association identifier
- peer :: {[inet:ip_address()], uint()}, %% {RAs, RP}
- streams :: {uint(), uint()}, %% {InStream, OutStream} counts
+ peer :: {[inet:ip_address()], uint()} %% {RAs, RP}
+ | undefined,
+ streams :: {uint(), uint()} %% {InStream, OutStream} counts
+ | undefined,
os = 0 :: uint()}). %% next output stream
%% Listener process state.
@@ -102,7 +104,7 @@
socket :: gen_sctp:sctp_socket(),
count = 0 :: uint(), %% attached transport processes
pending = {0, queue:new()},
- tref :: reference(),
+ tref :: reference() | undefined,
accept :: [match()]}).
%% Field pending implements two queues: the first of transport-to-be
%% processes to which an association has been assigned but for which
diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl
index 005b2442c0..c79d85820b 100644
--- a/lib/diameter/src/transport/diameter_tcp.erl
+++ b/lib/diameter/src/transport/diameter_tcp.erl
@@ -73,7 +73,7 @@
%% Listener process state.
-record(listener, {socket :: inet:socket(),
count = 1 :: non_neg_integer(),
- tref :: reference()}).
+ tref :: reference() | undefined}).
%% Monitor process state.
-record(monitor,
diff --git a/lib/edoc/test/Makefile b/lib/edoc/test/Makefile
index 2033e003b3..7a03ddeba9 100644
--- a/lib/edoc/test/Makefile
+++ b/lib/edoc/test/Makefile
@@ -25,7 +25,7 @@ RELSYSDIR = $(RELEASE_PATH)/edoc_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_COMPILE_FLAGS +=
EBIN = .
diff --git a/lib/edoc/test/edoc_SUITE.erl b/lib/edoc/test/edoc_SUITE.erl
index 2e2d5584f0..00d7550bed 100644
--- a/lib/edoc/test/edoc_SUITE.erl
+++ b/lib/edoc/test/edoc_SUITE.erl
@@ -16,7 +16,7 @@
%%
-module(edoc_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
diff --git a/lib/eldap/src/eldap.erl b/lib/eldap/src/eldap.erl
index 0c03021bd0..dc236f8a44 100644
--- a/lib/eldap/src/eldap.erl
+++ b/lib/eldap/src/eldap.erl
@@ -272,7 +272,7 @@ modify_dn(Handle, Entry, NewRDN, DelOldRDN, NewSup, Controls)
%%% Sanity checks !
-bool_p(Bool) when Bool==true;Bool==false -> Bool.
+bool_p(Bool) when is_boolean(Bool) -> Bool.
optional([]) -> asn1_NOVALUE;
optional(Value) -> Value.
@@ -1101,10 +1101,13 @@ log(_, _, _, _) ->
%%% Misc. routines
%%% --------------------------------------------------------------------
-send(To,Msg) -> To ! {self(),Msg}.
+send(To,Msg) ->
+ To ! {self(), Msg},
+ ok.
+
recv(From) ->
receive
- {From,Msg} -> Msg;
+ {From, Msg} -> Msg;
{'EXIT', From, Reason} ->
{error, {internal_error, Reason}}
end.
diff --git a/lib/eldap/test/eldap_basic_SUITE.erl b/lib/eldap/test/eldap_basic_SUITE.erl
index 8414ca6e46..4c1c2f8144 100644
--- a/lib/eldap/test/eldap_basic_SUITE.erl
+++ b/lib/eldap/test/eldap_basic_SUITE.erl
@@ -23,7 +23,7 @@
-compile(export_all).
%%-include_lib("common_test/include/ct.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("eldap/include/eldap.hrl").
-include_lib("eldap/ebin/ELDAPv3.hrl").
diff --git a/lib/erl_docgen/priv/css/otp_doc.css b/lib/erl_docgen/priv/css/otp_doc.css
index 0b531db701..347782eb1e 100644
--- a/lib/erl_docgen/priv/css/otp_doc.css
+++ b/lib/erl_docgen/priv/css/otp_doc.css
@@ -37,7 +37,7 @@ a:visited { color: blue; text-decoration: none }
top: 0;
bottom: 0;
left: 0;
- width: 200px;
+ width: 300px;
overflow:auto;
margin: 0;
padding: 1px;
@@ -45,7 +45,7 @@ a:visited { color: blue; text-decoration: none }
}
#content {
- margin-left: 240px; /* set left value to WidthOfFrameDiv */
+ margin-left: 340px; /* set left value to WidthOfFrameDiv */
}
.frontpage
diff --git a/lib/erl_docgen/test/Makefile b/lib/erl_docgen/test/Makefile
index 9f4cc04105..9e58157023 100644
--- a/lib/erl_docgen/test/Makefile
+++ b/lib/erl_docgen/test/Makefile
@@ -25,7 +25,7 @@ RELSYSDIR = $(RELEASE_PATH)/erl_docgen_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_COMPILE_FLAGS +=
EBIN = .
diff --git a/lib/erl_interface/src/Makefile.in b/lib/erl_interface/src/Makefile.in
index 777d709b1e..d6176ec053 100644
--- a/lib/erl_interface/src/Makefile.in
+++ b/lib/erl_interface/src/Makefile.in
@@ -126,11 +126,7 @@ else
WARNFLAGS = @WFLAGS@
endif
-ifneq ($(findstring ose,$(TARGET)),ose)
CFLAGS = @LIB_CFLAGS@ $(WARNFLAGS) $(INCFLAGS) $(TYPE_FLAGS)
-else
-CFLAGS = @CFLAGS@ $(INCFLAGS)
-endif
PROG_CFLAGS = @CFLAGS@ $(WARNFLAGS) $(INCFLAGS) $(TYPE_FLAGS) -Ilegacy
ifeq ($(findstring vxworks,$(TARGET)),vxworks)
@@ -210,12 +206,8 @@ MDD_ERLLIB = $(OBJDIR)/$(LIBPRE)erl_interface_mdd$(LIBEXT)
# Specify targets to build
###########################################################################
-ifneq ($(findstring ose,$(TARGET)),ose)
EXE_TARGETS = \
$(ERL_CALL)
-else
-EXE_TARGETS =
-endif
ifeq ($(USING_VC),yes)
@@ -480,44 +472,6 @@ ERLSOURCES = \
SOURCES = $(EISOURCES) $(ERLSOURCES)
-OSE_EISOURCES = \
- $(DECODESRC) \
- $(ENCODESRC) \
- misc/ei_decode_term.c \
- misc/ei_format.c \
- misc/ei_locking.c \
- misc/ei_malloc.c \
- misc/ei_printterm.c \
- misc/ei_pthreads.c \
- misc/ei_trace.c \
- misc/ei_x_encode.c \
- misc/eimd5.c \
- misc/get_type.c \
- misc/show_msg.c \
- misc/ei_compat.c \
- registry/hash_dohash.c \
- registry/hash_foreach.c \
- registry/hash_freetab.c \
- registry/hash_insert.c \
- registry/hash_isprime.c \
- registry/hash_lookup.c \
- registry/hash_newtab.c \
- registry/hash_remove.c \
- registry/hash_resize.c \
- registry/hash_rlookup.c
-
-OSE_ERLSOURCES = \
- legacy/decode_term.c \
- legacy/encode_term.c \
- legacy/erl_error.c \
- legacy/erl_eterm.c \
- legacy/erl_fix_alloc.c \
- legacy/erl_format.c \
- legacy/erl_malloc.c \
- legacy/erl_marshal.c
-
-OSE_SOURCES = $(OSE_EISOURCES) $(OSE_ERLSOURCES)
-
NEVERUSED = \
whereis.c \
ei_send.c \
@@ -532,13 +486,8 @@ ERLCALL = \
# Note that encode/decode_term.c defines ei functions that is
# located in the erl_interface library, not ei library.
-ifneq ($(findstring ose,$(TARGET)),ose)
ST_EIOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(EISOURCES:.c=.o)))
ST_ERLOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(ERLSOURCES:.c=.o)))
-else
-ST_EIOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(OSE_EISOURCES:.c=.o)))
-ST_ERLOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(OSE_ERLSOURCES:.c=.o)))
-endif
MT_EIOBJECTS = $(addprefix $(MT_OBJDIR)/,$(notdir $(EISOURCES:.c=.o)))
MT_ERLOBJECTS = $(addprefix $(MT_OBJDIR)/,$(notdir $(ERLSOURCES:.c=.o)))
MD_EIOBJECTS = $(addprefix $(MD_OBJDIR)/,$(notdir $(EISOURCES:.c=.o)))
@@ -587,14 +536,6 @@ $(TARGET)/config.h:
$(V_at)echo "#define HAVE_SOCKLEN_T 1" >> $@
endif
-ifeq ($(findstring ose,$(TARGET)),ose)
-$(TARGET)/config.h:
- $(gen_verbose)
- $(V_at)echo "/* Generated by Makefile */" > $@
- $(V_at)echo "#define HAVE_STRERROR 1" >> $@
- $(V_at)echo "#define HAVE_SOCKLEN_T 1" >> $@
-endif
-
###########################################################################
# Default rules, normal and threaded
###########################################################################
@@ -719,9 +660,6 @@ $(ST_OBJDIR)/erl_start.o: prog/erl_start.c
$(V_CC) $(CFLAGS) -c $< -o $@
else
-ifeq ($(findstring ose,$(TARGET)),ose)
-$(ERL_CALL):
-else
ifdef THR_DEFS
$(ERL_CALL): $(ERLCALL) ../include/ei.h $(MT_EILIB)
$(ld_verbose)$(PURIFY) $(CC) $(PROG_CFLAGS) $(THR_DEFS) $(LDFLAGS) -o $@ $(ERLCALL) \
@@ -733,7 +671,6 @@ $(ERL_CALL): $(ERLCALL) ../include/ei.h $(ST_EILIB)
endif
endif
endif
-endif
###########################################################################
# Fake application targets used to test header files and linking
diff --git a/lib/erl_interface/test/ei_accept_SUITE.erl b/lib/erl_interface/test/ei_accept_SUITE.erl
index 144ec99e0a..db3587339e 100644
--- a/lib/erl_interface/test/ei_accept_SUITE.erl
+++ b/lib/erl_interface/test/ei_accept_SUITE.erl
@@ -21,7 +21,7 @@
%%
-module(ei_accept_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("ei_accept_SUITE_data/ei_accept_test_cases.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
diff --git a/lib/erl_interface/test/ei_connect_SUITE.erl b/lib/erl_interface/test/ei_connect_SUITE.erl
index 3385d1eb6c..c94ac37af4 100644
--- a/lib/erl_interface/test/ei_connect_SUITE.erl
+++ b/lib/erl_interface/test/ei_connect_SUITE.erl
@@ -21,7 +21,7 @@
%%
-module(ei_connect_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("ei_connect_SUITE_data/ei_connect_test_cases.hrl").
-export([
diff --git a/lib/erl_interface/test/ei_decode_SUITE.erl b/lib/erl_interface/test/ei_decode_SUITE.erl
index 0abcf50fb5..91357c99f2 100644
--- a/lib/erl_interface/test/ei_decode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_SUITE.erl
@@ -21,7 +21,7 @@
%%
-module(ei_decode_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("ei_decode_SUITE_data/ei_decode_test_cases.hrl").
-export(
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE.erl b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
index 3c7e4bf70d..6a25b98209 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
@@ -21,7 +21,7 @@
%%
-module(ei_decode_encode_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("ei_decode_encode_SUITE_data/ei_decode_encode_test_cases.hrl").
-export(
diff --git a/lib/erl_interface/test/ei_encode_SUITE.erl b/lib/erl_interface/test/ei_encode_SUITE.erl
index 6213916314..d94f3adf42 100644
--- a/lib/erl_interface/test/ei_encode_SUITE.erl
+++ b/lib/erl_interface/test/ei_encode_SUITE.erl
@@ -21,7 +21,7 @@
%%
-module(ei_encode_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("ei_encode_SUITE_data/ei_encode_test_cases.hrl").
-export(
diff --git a/lib/erl_interface/test/ei_format_SUITE.erl b/lib/erl_interface/test/ei_format_SUITE.erl
index 11cbae31db..ed6a755f9b 100644
--- a/lib/erl_interface/test/ei_format_SUITE.erl
+++ b/lib/erl_interface/test/ei_format_SUITE.erl
@@ -21,7 +21,7 @@
%%
-module(ei_format_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("ei_format_SUITE_data/ei_format_test_cases.hrl").
-export([
diff --git a/lib/erl_interface/test/ei_print_SUITE.erl b/lib/erl_interface/test/ei_print_SUITE.erl
index 4309b883bb..36ee90c7ee 100644
--- a/lib/erl_interface/test/ei_print_SUITE.erl
+++ b/lib/erl_interface/test/ei_print_SUITE.erl
@@ -21,7 +21,7 @@
%%
-module(ei_print_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("ei_print_SUITE_data/ei_print_test_cases.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
diff --git a/lib/erl_interface/test/ei_tmo_SUITE.erl b/lib/erl_interface/test/ei_tmo_SUITE.erl
index 689499f42f..f506b3dbb0 100644
--- a/lib/erl_interface/test/ei_tmo_SUITE.erl
+++ b/lib/erl_interface/test/ei_tmo_SUITE.erl
@@ -21,7 +21,7 @@
%%
-module(ei_tmo_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/inet.hrl").
-include("ei_tmo_SUITE_data/ei_tmo_test_cases.hrl").
diff --git a/lib/erl_interface/test/erl_connect_SUITE.erl b/lib/erl_interface/test/erl_connect_SUITE.erl
index f621310a1c..d3fe020bce 100644
--- a/lib/erl_interface/test/erl_connect_SUITE.erl
+++ b/lib/erl_interface/test/erl_connect_SUITE.erl
@@ -21,7 +21,7 @@
%%
-module(erl_connect_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("erl_connect_SUITE_data/erl_connect_test_cases.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
diff --git a/lib/erl_interface/test/erl_eterm_SUITE.erl b/lib/erl_interface/test/erl_eterm_SUITE.erl
index 8fbef35309..230310f63b 100644
--- a/lib/erl_interface/test/erl_eterm_SUITE.erl
+++ b/lib/erl_interface/test/erl_eterm_SUITE.erl
@@ -21,7 +21,7 @@
%%
-module(erl_eterm_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("erl_eterm_SUITE_data/eterm_test_cases.hrl").
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/erl_interface/test/erl_ext_SUITE.erl b/lib/erl_interface/test/erl_ext_SUITE.erl
index f73c15e15f..cbc93b4cfb 100644
--- a/lib/erl_interface/test/erl_ext_SUITE.erl
+++ b/lib/erl_interface/test/erl_ext_SUITE.erl
@@ -21,7 +21,7 @@
%%
-module(erl_ext_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("erl_ext_SUITE_data/ext_test_cases.hrl").
-export([
diff --git a/lib/erl_interface/test/erl_format_SUITE.erl b/lib/erl_interface/test/erl_format_SUITE.erl
index 8c01a9914f..afbbe6a241 100644
--- a/lib/erl_interface/test/erl_format_SUITE.erl
+++ b/lib/erl_interface/test/erl_format_SUITE.erl
@@ -21,7 +21,7 @@
%%
-module(erl_format_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("erl_format_SUITE_data/format_test_cases.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
diff --git a/lib/erl_interface/test/erl_global_SUITE.erl b/lib/erl_interface/test/erl_global_SUITE.erl
index b719ad5c6a..493ad576c9 100644
--- a/lib/erl_interface/test/erl_global_SUITE.erl
+++ b/lib/erl_interface/test/erl_global_SUITE.erl
@@ -21,7 +21,7 @@
%%
-module(erl_global_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("erl_global_SUITE_data/erl_global_test_cases.hrl").
-export([all/0,suite/0,init_per_suite/1,end_per_suite/1,
diff --git a/lib/erl_interface/test/erl_match_SUITE.erl b/lib/erl_interface/test/erl_match_SUITE.erl
index d8f7bd89b4..ecdebad212 100644
--- a/lib/erl_interface/test/erl_match_SUITE.erl
+++ b/lib/erl_interface/test/erl_match_SUITE.erl
@@ -21,7 +21,7 @@
%%
-module(erl_match_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("erl_match_SUITE_data/match_test_cases.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
diff --git a/lib/erl_interface/test/port_call_SUITE.erl b/lib/erl_interface/test/port_call_SUITE.erl
index b0f5ed4fe9..3bc1a03eab 100644
--- a/lib/erl_interface/test/port_call_SUITE.erl
+++ b/lib/erl_interface/test/port_call_SUITE.erl
@@ -34,7 +34,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, basic/1]).
% Private exports
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
diff --git a/lib/eunit/src/eunit_surefire.erl b/lib/eunit/src/eunit_surefire.erl
index f3e58a3d1c..1b468551d8 100644
--- a/lib/eunit/src/eunit_surefire.erl
+++ b/lib/eunit/src/eunit_surefire.erl
@@ -56,7 +56,11 @@
{
name :: chars(),
description :: chars(),
- result :: ok | {failed, tuple()} | {aborted, tuple()} | {skipped, term()},
+ result :: ok
+ | {failed, tuple()}
+ | {aborted, tuple()}
+ | {skipped, term()}
+ | undefined,
time :: integer(),
output :: binary()
}).
diff --git a/lib/eunit/test/Makefile b/lib/eunit/test/Makefile
index 8721bacf89..6f166f99aa 100644
--- a/lib/eunit/test/Makefile
+++ b/lib/eunit/test/Makefile
@@ -41,8 +41,8 @@ RELSYSDIR = $(RELEASE_PATH)/eunit_test
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-ERL_MAKE_FLAGS += -pa $(ERL_TOP)/lib/test_server/ebin
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_MAKE_FLAGS +=
+ERL_COMPILE_FLAGS +=
EBIN = .
diff --git a/lib/gs/Makefile b/lib/gs/Makefile
index 02c8fc3467..b95d435461 100644
--- a/lib/gs/Makefile
+++ b/lib/gs/Makefile
@@ -26,7 +26,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# Macros
#
-SUB_DIRECTORIES = src tcl contribs examples doc/src
+SUB_DIRECTORIES = src tcl examples doc/src
include vsn.mk
VSN = $(GS_VSN)
diff --git a/lib/gs/contribs/Makefile b/lib/gs/contribs/Makefile
deleted file mode 100644
index 061fae86c1..0000000000
--- a/lib/gs/contribs/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-2009. 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
-
-SUB_DIRECTORIES = bonk cols mandel othello
-SPECIAL_TARGETS =
-
-#
-# Default Subdir Targets
-#
-include $(ERL_TOP)/make/otp_subdir.mk
-
diff --git a/lib/gs/contribs/bonk/Makefile b/lib/gs/contribs/bonk/Makefile
deleted file mode 100644
index b7508a97c9..0000000000
--- a/lib/gs/contribs/bonk/Makefile
+++ /dev/null
@@ -1,109 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-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%
-#
-
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(GS_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/gs-$(VSN)/contribs
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES= \
- bonk \
- bonk_sound \
- bonk_square \
- sounder
-
-HRL_FILES=
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=../ebin/%.$(EMULATOR)) $(TARGET_TOOLBOX_FILES)
-
-BITMAPS= bitmaps/bonkbomb bitmaps/bonkface bitmaps/bonklogo bitmaps/bonkmiss \
- bitmaps/bonktom bitmaps/bonkx bitmaps/erl-e bitmaps/erl-text
-SOUNDS= sounds/bonk.au sounds/damn.au sounds/explosion.au sounds/gameover.au \
- sounds/hehee.au sounds/level.au sounds/missedme.au sounds/music.au \
- sounds/ouch!!!.au sounds/praisejesus.au sounds/trumpet.au sounds/yes.au
-
-TOOLNAME = bonk
-
-EXTRA_FILES= $(TOOLNAME).txt
-TOOLBOX_FILES= $(TOOLNAME).tool $(TOOLNAME).gif
-TARGET_TOOLBOX_FILES= $(TOOLBOX_FILES:%=$(EBIN)/%)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_COMPILE_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(TARGET_FILES)
-
-docs:
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f core
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-$(EBIN)/$(TOOLNAME).gif: $(TOOLNAME).gif
- $(gen_verbose)rm -f $@
- $(V_at)cp $(TOOLNAME).gif $@
-
-$(EBIN)/$(TOOLNAME).tool: $(TOOLNAME).tool
- $(gen_verbose)rm -f $@
- $(V_at)cp $(TOOLNAME).tool $@
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/bonk/bitmaps"
- $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) "$(RELSYSDIR)/bonk/bitmaps"
- $(INSTALL_DIR) "$(RELSYSDIR)/bonk/sounds"
- $(INSTALL_DATA) $(SOUNDS) "$(RELSYSDIR)/bonk/sounds"
- $(INSTALL_DIR) "$(RELSYSDIR)/bonk"
- $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/bonk"
-
-
-release_docs_spec:
-
diff --git a/lib/gs/contribs/bonk/bitmaps/bonkbomb b/lib/gs/contribs/bonk/bitmaps/bonkbomb
deleted file mode 100644
index 8b121db9e8..0000000000
--- a/lib/gs/contribs/bonk/bitmaps/bonkbomb
+++ /dev/null
@@ -1,66 +0,0 @@
-#define bonkbomb_width 75
-#define bonkbomb_height 75
-static char bonkbomb_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x04, 0x10, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
- 0x10, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x21,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x11, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x90, 0x08, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x80, 0x90, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x04, 0x51, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
- 0x12, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x94, 0x18,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, 0x06, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0xbb, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
- 0x99, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x18, 0x19,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x62, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x84, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x80, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
- 0x3b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x1f, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0xb8, 0x0e, 0x80, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x5c, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0xaf, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff,
- 0xff, 0x57, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xaf,
- 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x5f, 0x1d, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xbf, 0x0e, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xfc, 0xff, 0xff, 0x7f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xfe, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
- 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xff, 0xff,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xff, 0xff, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x80, 0x7f, 0xfc, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x80, 0x3f, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80,
- 0x0f, 0xf0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0xc0,
- 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7f, 0xf0, 0xff, 0xff,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xf8, 0xff, 0xff, 0x07, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x80,
- 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
- 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
- 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x7f, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xf0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xe0, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff,
- 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/lib/gs/contribs/bonk/bitmaps/bonkface b/lib/gs/contribs/bonk/bitmaps/bonkface
deleted file mode 100644
index 964fb93098..0000000000
--- a/lib/gs/contribs/bonk/bitmaps/bonkface
+++ /dev/null
@@ -1,66 +0,0 @@
-#define bonkface_width 75
-#define bonkface_height 75
-static char bonkface_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x3c, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
- 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
- 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30, 0x00, 0x60,
- 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x03, 0x06, 0x00, 0x0f, 0x00, 0x00,
- 0x00, 0x40, 0xff, 0x00, 0x00, 0x00, 0xf8, 0x17, 0x00, 0x00, 0x00, 0x40,
- 0xfe, 0x1f, 0x00, 0xc0, 0xff, 0x13, 0x00, 0x00, 0x00, 0x20, 0xf8, 0xff,
- 0x03, 0xfe, 0xff, 0x20, 0x00, 0x00, 0x00, 0x20, 0xf0, 0xff, 0xff, 0xff,
- 0x7f, 0x20, 0x00, 0x00, 0x00, 0x20, 0xc0, 0xff, 0xdf, 0xff, 0x1f, 0x20,
- 0x00, 0x00, 0x00, 0x20, 0x00, 0xff, 0xdf, 0xff, 0x07, 0x20, 0x00, 0x00,
- 0x00, 0x10, 0x00, 0xfe, 0x8f, 0xff, 0x03, 0x40, 0x00, 0x00, 0x00, 0x10,
- 0x00, 0xf8, 0x8f, 0xff, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xf0,
- 0x07, 0x7f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xc0, 0x07, 0x1f,
- 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03, 0x06, 0x00, 0x40,
- 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
- 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xe0,
- 0x00, 0x38, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0xf0, 0x01, 0x7c,
- 0x40, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x06, 0x03, 0x40, 0x40,
- 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0xf8, 0x00, 0x40, 0x40, 0x00, 0x00,
- 0x00, 0x10, 0x30, 0x00, 0x00, 0x00, 0x60, 0x40, 0x00, 0x00, 0x00, 0x10,
- 0x70, 0x00, 0x00, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x10, 0xf0, 0x01,
- 0x00, 0x00, 0x7c, 0x40, 0x00, 0x00, 0x00, 0x20, 0xf0, 0x0f, 0x00, 0x80,
- 0x7f, 0x20, 0x00, 0x00, 0x00, 0x20, 0xf0, 0xff, 0x03, 0xfe, 0x7f, 0x20,
- 0x00, 0x00, 0x00, 0x20, 0xf0, 0x7f, 0xfe, 0xff, 0x7f, 0x20, 0x00, 0x00,
- 0x00, 0x20, 0xe0, 0x7f, 0xfe, 0xff, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x40,
- 0xe0, 0x7f, 0xfe, 0xff, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x40, 0xc0, 0xff,
- 0xff, 0xff, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xff, 0xff, 0xff,
- 0x1f, 0x08, 0x00, 0x00, 0x00, 0x80, 0x80, 0xff, 0xff, 0xff, 0x0f, 0x08,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x07, 0x04, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0xfe, 0xff, 0xff, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0xfc, 0xff, 0xfc, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0xf0,
- 0xff, 0x7c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xff, 0x1c,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xff, 0x07, 0x40, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
- 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xc0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x3c, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/lib/gs/contribs/bonk/bitmaps/bonklogo b/lib/gs/contribs/bonk/bitmaps/bonklogo
deleted file mode 100644
index 3adc59984a..0000000000
--- a/lib/gs/contribs/bonk/bitmaps/bonklogo
+++ /dev/null
@@ -1,320 +0,0 @@
-#define bonklogo_width 300
-#define bonklogo_height 100
-static char bonklogo_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x3f, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00,
- 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
- 0x83, 0xff, 0x9f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x3c, 0xf8, 0xff, 0x7f, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x87, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x80, 0xf9, 0xff, 0xff, 0xff, 0x13, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x27,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff,
- 0xff, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
- 0xff, 0xff, 0xff, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x0f,
- 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
- 0xff, 0x2f, 0xf8, 0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0xdf, 0xff, 0x2f, 0xf0, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x80, 0xc3, 0xff, 0x2f, 0xf0, 0xff, 0x09, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xff, 0x2f, 0xe0, 0xff, 0x0b, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x80, 0xff, 0x09,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x2f, 0xc0, 0xff,
- 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0,
- 0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x27,
- 0xc0, 0xff, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x01,
- 0x00, 0xc0, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
- 0xff, 0x17, 0xc0, 0xff, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
- 0x7f, 0x01, 0x00, 0xe0, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xe0, 0xff, 0x17, 0xc0, 0xff, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xfc, 0x7f, 0x01, 0x00, 0xe0, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff, 0x17, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0x7f, 0xff, 0x3f, 0xe0, 0x7f, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff, 0x17, 0xc0,
- 0xff, 0x7f, 0xe0, 0xff, 0x3f, 0xfc, 0x7f, 0x00, 0x20, 0xe0, 0x7f, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff,
- 0x17, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20, 0xfc, 0x7f, 0xfe, 0x2f, 0xf0,
- 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17,
- 0x80, 0xff, 0x17, 0xe0, 0xff, 0x1f, 0xe1, 0xff, 0x2f, 0xfc, 0x7f, 0xfe,
- 0x2f, 0xf0, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
- 0xff, 0x17, 0x80, 0xff, 0x17, 0xf0, 0xff, 0x7f, 0xe6, 0xff, 0x4f, 0xfc,
- 0x7f, 0xfe, 0x2f, 0xf0, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff, 0x17, 0xf8, 0xff, 0xff, 0xe8, 0xff,
- 0x4f, 0xfc, 0x7f, 0xfe, 0x2f, 0xf8, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff, 0x17, 0xfe, 0xff, 0xff,
- 0xeb, 0xff, 0x5f, 0xfc, 0x7f, 0xfe, 0x2f, 0xf8, 0x9f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff, 0x17, 0xfe,
- 0xff, 0xff, 0xe3, 0xff, 0x5f, 0xfc, 0x7f, 0xfe, 0x2f, 0xf8, 0x5f, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0xc0, 0xff,
- 0x17, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x5f, 0xfc, 0x7f, 0xfe, 0x2f, 0xfc,
- 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17,
- 0xc0, 0xff, 0x93, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x5f, 0xfc, 0x7f, 0xfe,
- 0x2f, 0xfc, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
- 0xff, 0x17, 0xc0, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x9f, 0xfc,
- 0x7f, 0xfe, 0x2f, 0xfc, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xe0, 0xff, 0x13, 0xe0, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xcf, 0xff,
- 0xbf, 0xfc, 0x7f, 0xfe, 0x2f, 0xfc, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0xff, 0x0b, 0xf2, 0xff, 0xcd, 0xff, 0xff, 0xff,
- 0xcf, 0xff, 0xbf, 0xfc, 0x7f, 0xfe, 0x2f, 0xfe, 0x17, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x0b, 0xf9, 0xff, 0xd9, 0xff,
- 0xff, 0xff, 0x1f, 0xff, 0xbf, 0xfc, 0x7f, 0xfe, 0x2f, 0xfe, 0x13, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xcb, 0xfc, 0xff,
- 0xc0, 0xff, 0x8f, 0xff, 0x1f, 0xff, 0xbf, 0xfc, 0x7f, 0xfe, 0x2f, 0xfe,
- 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x2b,
- 0xfe, 0xff, 0x87, 0xff, 0x03, 0xff, 0x3f, 0xff, 0xbf, 0xfc, 0x7f, 0xfe,
- 0x2f, 0xff, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0xff, 0x9b, 0xff, 0xff, 0x3f, 0xff, 0x01, 0xfe, 0x3f, 0xff, 0x3f, 0xfd,
- 0x7f, 0xfe, 0x2f, 0xff, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0xff, 0xc3, 0xff, 0xff, 0x7f, 0xfe, 0x05, 0xfc, 0x3f, 0xff,
- 0x7f, 0xfd, 0x7f, 0xfe, 0x2f, 0xff, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfc, 0x04, 0xfc,
- 0x3f, 0xff, 0x7f, 0xfd, 0x7f, 0xfe, 0x2f, 0xff, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
- 0x02, 0xf8, 0x3f, 0xff, 0x7f, 0xfd, 0x7f, 0xfe, 0xaf, 0xff, 0x04, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xfd, 0x02, 0xf8, 0x3f, 0xff, 0x7f, 0xfc, 0x7f, 0xfe, 0xaf, 0xff,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xf9, 0x02, 0xf8, 0x3f, 0xff, 0x7f, 0xfc, 0x7f, 0xfe,
- 0x8f, 0x7f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfc,
- 0x7f, 0xfe, 0xcf, 0x7f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x02, 0xf8, 0x3f, 0xff,
- 0xff, 0xfc, 0x7f, 0xfe, 0xcf, 0x7f, 0x01, 0x00, 0x00, 0x38, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x02, 0xf8,
- 0x3f, 0xff, 0xff, 0xfc, 0x7f, 0xfe, 0xcf, 0x3f, 0x01, 0x00, 0x00, 0x38,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xf7,
- 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfc, 0x7f, 0xfe, 0xef, 0x3f, 0x01, 0x00,
- 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x80, 0xff,
- 0xff, 0xe7, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfc, 0x7f, 0xfe, 0xef, 0x9f,
- 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01,
- 0x00, 0xff, 0xff, 0xe7, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfd, 0x7f, 0xfe,
- 0xef, 0xdf, 0x00, 0x00, 0x00, 0x30, 0xd8, 0x07, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
- 0xff, 0x05, 0x00, 0xff, 0xff, 0xe7, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfd,
- 0x7f, 0xfe, 0xef, 0x9f, 0x00, 0x00, 0x00, 0x38, 0xfc, 0x07, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf8, 0xff, 0x05, 0x00, 0xff, 0xff, 0xef, 0x02, 0xf8, 0x3f, 0xff,
- 0xff, 0xfd, 0x7f, 0xfe, 0xff, 0xbf, 0x00, 0x00, 0x00, 0x38, 0x7c, 0x0e,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf8, 0xff, 0x05, 0x00, 0xfe, 0xff, 0xef, 0x02, 0xf8,
- 0x3f, 0xff, 0xff, 0xfd, 0x7f, 0xfe, 0xff, 0x3f, 0x01, 0x00, 0x00, 0x38,
- 0x3e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x05, 0x00, 0xfe, 0xff, 0xef,
- 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfd, 0x7f, 0xfe, 0xff, 0x7f, 0x02, 0x00,
- 0x00, 0x38, 0x3e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x05, 0x00, 0xfc,
- 0xff, 0xcf, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfd, 0x7f, 0xfe, 0xff, 0xff,
- 0x02, 0x00, 0x00, 0x38, 0x3b, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x04,
- 0x00, 0xfc, 0xff, 0xcf, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0x7f, 0xfe,
- 0xff, 0xff, 0x04, 0x00, 0x00, 0xb8, 0x39, 0x2e, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
- 0xff, 0x02, 0x00, 0xfc, 0xff, 0xcf, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xff,
- 0x7f, 0xfe, 0xff, 0xff, 0x05, 0x00, 0x00, 0xf0, 0x39, 0x3c, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf8, 0xff, 0x02, 0x00, 0xfc, 0xff, 0xcf, 0x04, 0xf8, 0x3f, 0xff,
- 0xfd, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x09, 0x00, 0x00, 0xf0, 0x38, 0x1c,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf8, 0xff, 0x02, 0x00, 0xfc, 0xff, 0xcf, 0x05, 0xf8,
- 0x3f, 0xff, 0xfd, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x13, 0x00, 0x00, 0x60,
- 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, 0x00, 0xfc, 0xff, 0xcf,
- 0x0d, 0xf8, 0x3f, 0xff, 0xfd, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x17, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, 0x00, 0xfe,
- 0xff, 0xcf, 0x09, 0xfd, 0x3f, 0xff, 0xfd, 0xff, 0x7f, 0xfe, 0xff, 0xff,
- 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02,
- 0x00, 0xfe, 0xff, 0xcf, 0xcb, 0xfc, 0x3f, 0xff, 0xfd, 0xff, 0x7f, 0xfe,
- 0xff, 0xff, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
- 0xff, 0x02, 0x00, 0xfe, 0xff, 0xcf, 0x33, 0xfe, 0x3f, 0xff, 0xf9, 0xff,
- 0x7f, 0xfe, 0xff, 0xff, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xfc, 0xff, 0x02, 0x00, 0xfe, 0xff, 0xcf, 0x07, 0xff, 0x3f, 0xff,
- 0xf9, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, 0x00, 0xfe, 0xff, 0xcf, 0xcf, 0xff,
- 0x3f, 0xff, 0xf9, 0xff, 0x7f, 0xfe, 0x7f, 0xff, 0x3f, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, 0x40, 0xfe, 0xff, 0xcf,
- 0xff, 0xff, 0x3f, 0xff, 0xf9, 0xff, 0x7f, 0xfe, 0x7f, 0xfe, 0x3f, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, 0x3c, 0xff,
- 0xff, 0xc7, 0xff, 0xff, 0x3f, 0xff, 0xf9, 0xff, 0x7f, 0xfe, 0x7f, 0xfe,
- 0x7f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x82,
- 0x87, 0xff, 0xff, 0xe7, 0xff, 0xff, 0x3f, 0xff, 0xf1, 0xff, 0x7f, 0xfe,
- 0x3f, 0xfc, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
- 0xff, 0x72, 0xf0, 0xff, 0xff, 0xe7, 0xff, 0xff, 0x3f, 0xff, 0xf1, 0xff,
- 0x7f, 0xfe, 0xbf, 0xf8, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xfc, 0xff, 0x0e, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0x9f, 0xff,
- 0xf5, 0xff, 0x7f, 0xfe, 0xbf, 0xf8, 0xff, 0x09, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff,
- 0x9f, 0xff, 0xf5, 0xff, 0x7f, 0xfe, 0x9f, 0xf0, 0xff, 0x0b, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7,
- 0xff, 0xff, 0x9f, 0xff, 0xf5, 0xff, 0x7f, 0xfe, 0x5f, 0xf0, 0xff, 0x13,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xfe, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xf3, 0xff, 0xff, 0xdf, 0xff, 0xf5, 0xff, 0x7f, 0xfe, 0x4f, 0xe0,
- 0xff, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xfe, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xcf, 0xff, 0xe5, 0xff, 0x7f, 0xfe,
- 0x2f, 0xe0, 0xff, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xcf, 0xff, 0xe5, 0xff,
- 0x7f, 0xfe, 0x2f, 0xc0, 0xff, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xe7, 0xff,
- 0xe5, 0xff, 0x7f, 0xfe, 0x2f, 0xc0, 0xff, 0x9f, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf8, 0xff, 0xff,
- 0xe7, 0xff, 0xe5, 0xff, 0x7f, 0xfe, 0x2f, 0x80, 0xff, 0x9f, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc,
- 0xff, 0xff, 0xf7, 0xff, 0xe5, 0xff, 0x7f, 0xfe, 0x2f, 0x00, 0xff, 0x3f,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x1f, 0xfe, 0xff, 0xff, 0xf3, 0xff, 0xc5, 0xff, 0x7f, 0xfe, 0x2f, 0x00,
- 0xff, 0x7f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xc5, 0xff, 0x7f, 0xfe,
- 0x2f, 0x00, 0xfe, 0x7f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x23, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xc5, 0xff,
- 0x7f, 0xfe, 0x2f, 0x00, 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0xfe, 0xff, 0xff, 0xf5, 0xff,
- 0xc5, 0xff, 0x7f, 0xfe, 0x2f, 0x00, 0xfc, 0xff, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x0c, 0xfc, 0xff, 0xff,
- 0xf4, 0xff, 0xc5, 0xff, 0x7f, 0xfe, 0x2f, 0x00, 0xfc, 0xff, 0x09, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x02, 0xfc,
- 0xff, 0x7f, 0xf2, 0xff, 0xc5, 0xff, 0x7f, 0xfe, 0x2f, 0x00, 0xf8, 0xff,
- 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x01,
- 0x00, 0xe0, 0xff, 0x3f, 0xf1, 0xff, 0x85, 0xff, 0x7f, 0xfe, 0x2f, 0x00,
- 0xf8, 0xff, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff,
- 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x85, 0xff, 0x7f, 0xfe,
- 0x2f, 0x00, 0xf0, 0xff, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff,
- 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x85, 0xff,
- 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xf0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/lib/gs/contribs/bonk/bitmaps/bonkmiss b/lib/gs/contribs/bonk/bitmaps/bonkmiss
deleted file mode 100644
index 862e4839fc..0000000000
--- a/lib/gs/contribs/bonk/bitmaps/bonkmiss
+++ /dev/null
@@ -1,66 +0,0 @@
-#define bonkmiss_width 75
-#define bonkmiss_height 75
-static char bonkmiss_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x60, 0x80, 0x19, 0x3c, 0xc0, 0x83, 0xff, 0xf9, 0x01, 0x00, 0x60, 0x80,
- 0x19, 0x7e, 0xe0, 0x87, 0xff, 0xf9, 0x03, 0x00, 0xe0, 0xc0, 0x19, 0xe7,
- 0x70, 0x8e, 0x01, 0x18, 0x07, 0x00, 0xe0, 0xc0, 0x99, 0xc3, 0x39, 0x9c,
- 0x01, 0x18, 0x0e, 0x00, 0xe0, 0xe1, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18,
- 0x0c, 0x00, 0xe0, 0xe1, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x1c, 0x00,
- 0xe0, 0xf3, 0x99, 0x01, 0x18, 0x80, 0x01, 0x18, 0x18, 0x00, 0x60, 0xb3,
- 0x99, 0x01, 0x18, 0x80, 0x01, 0x18, 0x18, 0x00, 0x60, 0xb3, 0x99, 0x03,
- 0x38, 0x80, 0x01, 0x18, 0x18, 0x00, 0x60, 0x9e, 0x19, 0x07, 0x70, 0x80,
- 0x01, 0x18, 0x18, 0x00, 0x60, 0x9e, 0x19, 0x3e, 0xe0, 0x83, 0x1f, 0x18,
- 0x18, 0x00, 0x60, 0x8c, 0x19, 0x7c, 0xc0, 0x87, 0x1f, 0x18, 0x18, 0x00,
- 0x60, 0x80, 0x19, 0xe0, 0x00, 0x8e, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80,
- 0x19, 0xc0, 0x01, 0x9c, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x19, 0x80,
- 0x01, 0x98, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x19, 0x80, 0x01, 0x98,
- 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x19, 0x80, 0x01, 0x98, 0x01, 0x18,
- 0x18, 0x00, 0x60, 0x80, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x18, 0x00,
- 0x60, 0x80, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80,
- 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x99, 0x81,
- 0x19, 0x98, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x99, 0x81, 0x19, 0x98,
- 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18,
- 0x18, 0x00, 0x60, 0x80, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x1c, 0x00,
- 0x60, 0x80, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x0c, 0x00, 0x60, 0x80,
- 0x99, 0xc3, 0x39, 0x9c, 0x01, 0x18, 0x0e, 0x00, 0x60, 0x80, 0x19, 0xe7,
- 0x70, 0x8e, 0x01, 0x18, 0x07, 0x00, 0x60, 0x80, 0x19, 0x7e, 0xe0, 0x87,
- 0xff, 0xf9, 0x03, 0x00, 0x60, 0x80, 0x19, 0x3c, 0xc0, 0x83, 0xff, 0xf9,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0xff, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0xff, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x1c, 0x38, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x1c, 0x38, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
- 0x3c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x3e, 0x03, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x36, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x6c, 0x36, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xcc, 0x33, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc,
- 0x33, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x31, 0x3f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
- 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
- 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0c, 0x30, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
- 0x30, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/lib/gs/contribs/bonk/bitmaps/bonktom b/lib/gs/contribs/bonk/bitmaps/bonktom
deleted file mode 100644
index defbc32cc9..0000000000
--- a/lib/gs/contribs/bonk/bitmaps/bonktom
+++ /dev/null
@@ -1,66 +0,0 @@
-#define bonktom_width 75
-#define bonktom_height 75
-static char bonktom_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/lib/gs/contribs/bonk/bitmaps/bonkx b/lib/gs/contribs/bonk/bitmaps/bonkx
deleted file mode 100644
index 70cd89bdb7..0000000000
--- a/lib/gs/contribs/bonk/bitmaps/bonkx
+++ /dev/null
@@ -1,66 +0,0 @@
-#define bonkx_width 75
-#define bonkx_height 75
-static char bonkx_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x3e, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xf0, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xf8, 0x03, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01,
- 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xf0, 0x07,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xe0, 0x0f, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0xfe, 0x03,
- 0x00, 0xc0, 0x1f, 0x00, 0x80, 0x3f, 0x00, 0xe0, 0x01, 0x3c, 0x00, 0xe0,
- 0x0f, 0x00, 0x00, 0x7f, 0x00, 0x18, 0x00, 0xc0, 0x00, 0xf0, 0x07, 0x00,
- 0x00, 0xfe, 0x00, 0x06, 0x00, 0x00, 0x03, 0xf8, 0x03, 0x00, 0x00, 0xfc,
- 0x81, 0x01, 0x00, 0x00, 0x0c, 0xfc, 0x01, 0x00, 0x00, 0xf8, 0x43, 0x00,
- 0x00, 0x00, 0x10, 0xfe, 0x00, 0x00, 0x00, 0xf0, 0x27, 0x00, 0x00, 0x00,
- 0x20, 0x7f, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0x3f,
- 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00,
- 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00,
- 0x7f, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0xff, 0x08,
- 0x00, 0x80, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x31, 0x00, 0x60,
- 0xfc, 0x05, 0x00, 0x00, 0x00, 0x80, 0xf8, 0xc3, 0x00, 0x18, 0xfe, 0x08,
- 0x00, 0x00, 0x00, 0x80, 0xf7, 0x07, 0x03, 0x06, 0x7f, 0x0f, 0x00, 0x00,
- 0x00, 0x40, 0xff, 0x0f, 0x00, 0x80, 0xff, 0x17, 0x00, 0x00, 0x00, 0x40,
- 0xfe, 0x1f, 0x00, 0xc0, 0xff, 0x13, 0x00, 0x00, 0x00, 0x20, 0xf8, 0xff,
- 0x03, 0xfe, 0xff, 0x20, 0x00, 0x00, 0x00, 0x20, 0xf0, 0xff, 0xff, 0xff,
- 0x7f, 0x20, 0x00, 0x00, 0x00, 0x20, 0xc0, 0xff, 0xdf, 0xff, 0x1f, 0x20,
- 0x00, 0x00, 0x00, 0x20, 0x00, 0xff, 0xdf, 0xff, 0x07, 0x20, 0x00, 0x00,
- 0x00, 0x10, 0x00, 0xfe, 0x8f, 0xff, 0x03, 0x40, 0x00, 0x00, 0x00, 0x10,
- 0x00, 0xf8, 0x8f, 0xff, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xf0,
- 0x8f, 0x7f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xc0, 0xdf, 0x1f,
- 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0xff, 0x0f, 0x00, 0x40,
- 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xff, 0x07, 0x00, 0x40, 0x00, 0x00,
- 0x00, 0x10, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10,
- 0x00, 0x00, 0xfc, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xe0,
- 0xfe, 0x3b, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0xf0, 0xff, 0x7f,
- 0x40, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0x80, 0xff, 0x0f, 0x40, 0x40,
- 0x00, 0x00, 0x00, 0x10, 0x10, 0xc0, 0xff, 0x1f, 0x40, 0x40, 0x00, 0x00,
- 0x00, 0x10, 0x30, 0xe0, 0x8f, 0x3f, 0x60, 0x40, 0x00, 0x00, 0x00, 0x10,
- 0x70, 0xf0, 0x07, 0x7f, 0x70, 0x40, 0x00, 0x00, 0x00, 0x10, 0xf0, 0xf9,
- 0x03, 0xfe, 0x7c, 0x40, 0x00, 0x00, 0x00, 0x20, 0xf0, 0xff, 0x01, 0xfc,
- 0x7f, 0x20, 0x00, 0x00, 0x00, 0x20, 0xf0, 0xff, 0x03, 0xfe, 0x7f, 0x20,
- 0x00, 0x00, 0x00, 0x20, 0xf0, 0x7f, 0xfe, 0xff, 0x7f, 0x20, 0x00, 0x00,
- 0x00, 0x20, 0xe0, 0x7f, 0xfe, 0xff, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x40,
- 0xe0, 0x7f, 0xfe, 0xff, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x40, 0xe0, 0xff,
- 0xff, 0xff, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x80, 0xf0, 0xff, 0xff, 0xff,
- 0x7f, 0x08, 0x00, 0x00, 0x00, 0x80, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x08,
- 0x00, 0x00, 0x00, 0x00, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x05, 0x00, 0x00,
- 0x00, 0x00, 0xff, 0xfe, 0xff, 0xff, 0xfb, 0x07, 0x00, 0x00, 0x00, 0x00,
- 0x7f, 0xfc, 0xff, 0xfc, 0xf1, 0x07, 0x00, 0x00, 0x00, 0x80, 0x3f, 0xf0,
- 0xff, 0x7c, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0xc0, 0xff, 0x1c,
- 0xc0, 0x1f, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0xff, 0x07, 0xc0, 0x3f,
- 0x00, 0x00, 0x00, 0xf0, 0x27, 0x00, 0x00, 0x00, 0x20, 0x7f, 0x00, 0x00,
- 0x00, 0xf8, 0x43, 0x00, 0x00, 0x00, 0x10, 0xfe, 0x00, 0x00, 0x00, 0xfc,
- 0x81, 0x01, 0x00, 0x00, 0x0c, 0xfc, 0x01, 0x00, 0x00, 0xfe, 0x00, 0x06,
- 0x00, 0x00, 0x03, 0xf8, 0x03, 0x00, 0x00, 0x7f, 0x00, 0x18, 0x00, 0xc0,
- 0x00, 0xf0, 0x07, 0x00, 0x80, 0x3f, 0x00, 0xe0, 0x01, 0x3c, 0x00, 0xe0,
- 0x0f, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0xfe, 0x03, 0x00, 0xc0, 0x1f, 0x00,
- 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0xf0, 0x07,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xf8, 0x03, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xfc, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xf8, 0x03, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03,
- 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x1e, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/lib/gs/contribs/bonk/bitmaps/erl-e b/lib/gs/contribs/bonk/bitmaps/erl-e
deleted file mode 100644
index 41ad14f404..0000000000
--- a/lib/gs/contribs/bonk/bitmaps/erl-e
+++ /dev/null
@@ -1,106 +0,0 @@
-#define erl-e_width 108
-#define erl-e_height 88
-static char erl-e_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xe0, 0xff, 0xf7, 0xfc, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xf7, 0xfc, 0x7f, 0x00, 0x00,
- 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x80, 0xff, 0xf7, 0xfc, 0x3f,
- 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf7,
- 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xf7, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00,
- 0x00, 0x00, 0xfe, 0xf7, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff,
- 0x01, 0x00, 0x00, 0x00, 0xfe, 0xf7, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0xe0,
- 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0xfc, 0xf7, 0xfc, 0x0f, 0x00, 0x00,
- 0x00, 0xf0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0xfc, 0xf7, 0xfc, 0x07,
- 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0xf8, 0xf7,
- 0xfc, 0x07, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
- 0xf8, 0xf7, 0xfc, 0x03, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x0f, 0x00,
- 0x00, 0x00, 0xf8, 0xf7, 0xfc, 0x03, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
- 0x0f, 0x00, 0x00, 0x00, 0xf0, 0xf7, 0xfc, 0x01, 0x00, 0x00, 0x00, 0xfc,
- 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf0, 0xf7, 0xfc, 0x01, 0x00, 0x00,
- 0x00, 0xfc, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf0, 0xf7, 0xfc, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf0, 0xf7,
- 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xf0, 0xf7, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xe0, 0xf7, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x7c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x7c, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xe0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xe0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x3c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x3c, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7,
- 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xe0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xc0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf7, 0x3c, 0x00, 0x00, 0x00,
- 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00,
- 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7,
- 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00,
- 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00,
- 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7,
- 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x7c, 0x00, 0x00, 0x00,
- 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x7c, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xf7, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff,
- 0x7f, 0xfe, 0xff, 0xf7, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
- 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xf7, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xf8,
- 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0xff, 0xf7, 0xfc, 0x00, 0x00, 0x00,
- 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xc0, 0xff, 0xf7, 0xfc, 0x01,
- 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xfe, 0xf7,
- 0xfc, 0x01, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
- 0xf8, 0xf7, 0xfc, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff,
- 0x03, 0x00, 0xe0, 0xf7, 0xfc, 0x03, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff,
- 0xff, 0xff, 0x03, 0x00, 0xc0, 0xf7, 0xfc, 0x03, 0x00, 0x00, 0x00, 0xc0,
- 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x80, 0xf7, 0xfc, 0x07, 0x00, 0x00,
- 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0xf7, 0xfc, 0x07,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x80, 0xf7,
- 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x1f, 0x00, 0x00,
- 0xc0, 0xf7, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x0f,
- 0x00, 0x00, 0xe0, 0xf7, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
- 0xff, 0x07, 0x00, 0x00, 0xe0, 0xf7, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00,
- 0xf0, 0xff, 0xff, 0x03, 0x00, 0x00, 0xf0, 0xf7, 0xfc, 0x3f, 0x00, 0x00,
- 0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00, 0x00, 0xf8, 0xf7, 0xfc, 0x7f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0xfc, 0xf7,
- 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xfc, 0xf7, 0xfc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xfe, 0xf7, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xf7, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xf7, 0xfc, 0xff, 0x07, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xf7, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0};
diff --git a/lib/gs/contribs/bonk/bitmaps/erl-text b/lib/gs/contribs/bonk/bitmaps/erl-text
deleted file mode 100644
index e20a9e5a28..0000000000
--- a/lib/gs/contribs/bonk/bitmaps/erl-text
+++ /dev/null
@@ -1,106 +0,0 @@
-#define erl-text_width 108
-#define erl-text_height 88
-static char erl-text_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0xfc, 0x03, 0xf8, 0x00, 0x70, 0x00, 0x80, 0x03, 0x80, 0x03, 0x07, 0x00,
- 0x3e, 0xf0, 0xfc, 0x03, 0xf8, 0x03, 0x70, 0x00, 0x80, 0x03, 0x80, 0x07,
- 0x07, 0x80, 0xff, 0xf0, 0xfc, 0x03, 0xf8, 0x07, 0x70, 0x00, 0xc0, 0x07,
- 0x80, 0x07, 0x07, 0xe0, 0xff, 0xf1, 0x1c, 0x00, 0x38, 0x07, 0x70, 0x00,
- 0xc0, 0x07, 0x80, 0x0f, 0x07, 0xe0, 0xc1, 0xf3, 0x1c, 0x00, 0x38, 0x0e,
- 0x70, 0x00, 0xe0, 0x0f, 0x80, 0x1f, 0x07, 0xf0, 0x80, 0xf3, 0x1c, 0x00,
- 0x38, 0x0f, 0x70, 0x00, 0xe0, 0x0e, 0x80, 0x1f, 0x07, 0x78, 0x00, 0xf0,
- 0xfc, 0x03, 0xf8, 0x07, 0x70, 0x00, 0xe0, 0x0e, 0x80, 0x3f, 0x07, 0x78,
- 0x00, 0xf0, 0xfc, 0x03, 0xf8, 0x03, 0x70, 0x00, 0x70, 0x1c, 0x80, 0x7b,
- 0x07, 0x38, 0x00, 0xf0, 0xfc, 0x03, 0xf8, 0x01, 0x70, 0x00, 0x70, 0x1c,
- 0x80, 0xf3, 0x07, 0x38, 0xf8, 0xf7, 0x1c, 0x00, 0xf8, 0x01, 0x70, 0x00,
- 0x70, 0x1c, 0x80, 0xe3, 0x07, 0x78, 0xf8, 0xf7, 0x1c, 0x00, 0xf8, 0x03,
- 0x70, 0x00, 0xf8, 0x3f, 0x80, 0xe3, 0x07, 0x70, 0x80, 0xf7, 0x1c, 0x00,
- 0xb8, 0x03, 0x70, 0x00, 0xf8, 0x3f, 0x80, 0xc3, 0x07, 0xf0, 0x80, 0xf3,
- 0xfc, 0x03, 0x38, 0x07, 0xf0, 0x07, 0x38, 0x38, 0x80, 0x83, 0x07, 0xe0,
- 0xe3, 0xf3, 0xfc, 0x03, 0x38, 0x07, 0xf0, 0x07, 0x1c, 0x70, 0x80, 0x83,
- 0x07, 0xc0, 0xff, 0xf1, 0xfc, 0x03, 0x38, 0x0e, 0xf0, 0x07, 0x1c, 0x70,
- 0x80, 0x03, 0x07, 0x00, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0};
diff --git a/lib/gs/contribs/bonk/bonk.erl b/lib/gs/contribs/bonk/bonk.erl
deleted file mode 100644
index bbbc656b34..0000000000
--- a/lib/gs/contribs/bonk/bonk.erl
+++ /dev/null
@@ -1,584 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-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(bonk).
--compile([{nowarn_deprecated_function,{gs,config,2}},
- {nowarn_deprecated_function,{gs,create,3}},
- {nowarn_deprecated_function,{gs,create,4}},
- {nowarn_deprecated_function,{gs,destroy,1}},
- {nowarn_deprecated_function,{gs,start,0}}]).
-
--export([run/0, run/1,bonk_dir/0,start/0]).
-
--record(colors, {miss, x, bomb, face}).
--record(scores, {points, level, bombs, hits, showed, bonus}).
-
-start() ->
- spawn(bonk, run, []).
-
-run() ->
- run(color).
-
-run([ColorMode]) -> % This is for the start script...
- run(ColorMode);
-
-run(ColorMode) when is_atom(ColorMode) ->
- GS = gs:start(),
- SoundPid = spawn_link(bonk_sound,start,[]),
- {H,M,S} = time(),
- random:seed(H*13,M*7,S*3),
- {SqrPids, Bmps, Colors} = create_board(GS, ColorMode),
- {ScoreL,_File} = get_highscore(),
- display_highscore(ScoreL),
- put(colormode, ColorMode),
- SoundPid ! music,
- sleep(6500),
- gs:config(aboutButton, [{enable,true}]),
- gs:config(newButton, [{enable,true}]),
- gs:config(quitButton, [{enable,true}]),
- idle(SoundPid, SqrPids, Bmps, Colors).
-
-%% This is not an application so we don't have their way of knowing
-%% a private data directory where the GIF files are located (this directory).
-%% We can find GS and makes it relative from there /kgb
-%%
-%% Note the silly slash that is added. The rest of the code uses
-%% append to contruct file names and assumes that the directory ends
-%% in slash. If filename:join was used and the problem is gone.
-
--define(EbinFromGsPriv,"../contribs/bonk").
-
-bonk_dir() ->
- GsPrivDir = code:priv_dir(gs),
- filename:join(GsPrivDir,?EbinFromGsPriv) ++ "/".
-
-
-idle(SoundPid, SqrPids, Bmps, Colors) ->
- receive
- {gs, newButton, click, _Data, _Args} ->
- init(SoundPid, SqrPids, Bmps, Colors);
- {gs, aboutButton, click, _Data, _Args} ->
- display_about(),
- idle(SoundPid, SqrPids, Bmps, Colors);
- {gs, quitButton, click, _Data, _Args} ->
- SoundPid ! quit,
- send_to_all(SqrPids, quit);
- _Other ->
- %%io:format("Got ~w in idle~n", [_Other]),
- idle(SoundPid, SqrPids, Bmps, Colors)
- end.
-
-
-
-init(SoundPid, SqrPids, Bmps, Colors) ->
- clear_board(Bmps),
- SoundPid ! start,
- gs:config(newButton, [{enable,false}]),
- gs:config(endButton, [{enable,true}]),
- gs:config(aboutButton, [{enable,false}]),
- Scores = #scores{points=0, level=1, bombs=0, hits=0, showed=0, bonus=10},
- clear_scores(Scores),
- flush(),
- send_to_all(SqrPids, start),
- game(SoundPid, SqrPids, Bmps, Colors, Scores).
-
-
-game(SoundPid, SqrPids, Bmps, Colors, Scores) ->
- receive
- {gs, _Square, buttonpress, SqrPid, [1 | _Rest]} when is_pid(SqrPid) ->
- SqrPid ! bonk,
- game(SoundPid, SqrPids, Bmps, Colors, Scores);
- {gs, _Id, buttonpress, _Data, [Butt | _Rest]} when Butt =/= 1 ->
- NewScores = bomb(SoundPid, SqrPids, Scores),
- game(SoundPid, SqrPids, Bmps, Colors, NewScores);
- {show, Square, Rect} ->
- NewScores = show_face(Square, Rect, Colors, Scores),
- game(SoundPid, SqrPids, Bmps, Colors, NewScores);
- {hide, Square, Rect} ->
- NewScores = hide_face(Square, Rect, Colors, Scores),
- game(SoundPid, SqrPids, Bmps, Colors, NewScores);
- {missed, Square, Rect} ->
- case miss_face(SoundPid, Square, Rect, Colors, Scores) of
- {continue, NewScores} ->
- game(SoundPid, SqrPids, Bmps, Colors, NewScores);
- {game_over, NewScores} ->
- game_over(SoundPid, SqrPids, Bmps, Colors, NewScores)
- end;
- {bonked, Square, Rect} ->
- NewScores = bonked(SoundPid, SqrPids, Square, Rect, Scores, Colors),
- game(SoundPid, SqrPids, Bmps, Colors, NewScores);
- {bombed, Square, Rect} ->
- NewScores = bombed(SoundPid, SqrPids, Square, Rect, Scores, Colors),
- game(SoundPid, SqrPids, Bmps, Colors, NewScores);
- {gs, endButton, click, _Data, _Args} ->
- game_over(SoundPid, SqrPids, Bmps, Colors, Scores);
- {gs, quitButton, click, _Data, _Args} ->
- quit(SoundPid, SqrPids, Bmps, Colors, Scores);
- _Other ->
- game(SoundPid, SqrPids, Bmps, Colors, Scores)
- end.
-
-
-
-game_over(SoundPid, SqrPids, Bmps, Colors, Scores) ->
- SoundPid ! game_over,
- send_to_all(SqrPids, stop),
- flush(),
- sleep(2000),
- update_scorelist(SoundPid, Scores),
- gs:config(newButton, [{enable,true}]),
- gs:config(endButton, [{enable,false}]),
- gs:config(aboutButton, [{enable,true}]),
- idle(SoundPid, SqrPids, Bmps, Colors).
-
-
-quit(SoundPid, SqrPids, _Bmps, _Colors, _Scores) ->
- SoundPid ! quit,
- send_to_all(SqrPids, quit),
- true.
-
-
-
-bomb(SoundPid, SqrPids, Scores) ->
- case Scores#scores.bombs of
- Bombs when Bombs > 0 ->
- send_to_all(SqrPids, bomb),
- SoundPid ! bomb,
- gs:config(bombOut,[{text,integer_to_list(Bombs-1)}]),
- Scores#scores{bombs=Bombs-1};
- _Other ->
- Scores
- end.
-
-show_face(Square, Rect, Colors, Scores) ->
- Showed = Scores#scores.showed,
- if
- Showed == Scores#scores.level+1 ->
- Square ! sleep,
- Scores;
- true ->
- FaceColors = Colors#colors.face,
- FaceColor = lists:nth(random:uniform(length(FaceColors)), FaceColors),
- gs:config(Rect, [{bitmap,lists:append(bonk_dir(),"bitmaps/bonkface")},{fg, FaceColor}]),
- Scores#scores{showed=Showed+1}
- end.
-
-hide_face(_Square, Rect, _Colors, Scores) ->
- Showed = Scores#scores.showed,
- gs:config(Rect, [{bitmap,lists:append(bonk_dir(),"bitmaps/bonktom")}]),
- Scores#scores{showed=Showed-1}.
-
-
-miss_face(SoundPid, _Square, Rect, Colors, Scores) ->
- SoundPid ! missed,
- gs:config(Rect, [{bitmap,lists:append(bonk_dir(),"bitmaps/bonkmiss")}, {fg, Colors#colors.miss}]),
- Bonus = Scores#scores.bonus,
- if
- Bonus > 1 ->
- gs:config(bonusOut, [{text,integer_to_list(Bonus-1)}]),
- {continue, Scores#scores{bonus=Bonus-1}};
- true ->
- gs:config(bonusOut, [{text,"0"}]),
- {game_over, Scores}
- end.
-
-bonked(SoundPid, SqrPids, _Square, Rect, Scores, Colors) ->
- gs:config(Rect, [{bitmap,lists:append(bonk_dir(),"bitmaps/bonkx")}, {fg, Colors#colors.x}]),
- SoundPid ! bonk,
- update_score(SoundPid, SqrPids, Scores).
-
-bombed(SoundPid, SqrPids, _Square, Rect, Scores, Colors) ->
- gs:config(Rect, [{bitmap,lists:append(bonk_dir(),"bitmaps/bonkbomb")}, {fg, Colors#colors.bomb}]),
- update_score(SoundPid, SqrPids, Scores).
-
-
-update_score(SoundPid, SqrPids, Scores) ->
- Points = Scores#scores.points,
- Level = Scores#scores.level,
- NewPoints = Points+Level,
- gs:config(scoreOut,[{text,integer_to_list(NewPoints)}]),
- case Scores#scores.hits of
- 24 ->
- SoundPid ! new_level,
- NewLevel = Level+1,
- NewBombs = Scores#scores.bombs+1,
- send_to_all(SqrPids, {new_level, NewLevel}),
- gs:config(levelOut,[{text,integer_to_list(NewLevel)}]),
- gs:config(bombOut,[{text,integer_to_list(NewBombs)}]),
- Scores#scores{points=NewPoints, level=NewLevel, hits=0, bombs=NewBombs};
- Hits ->
- Scores#scores{points=NewPoints, hits=Hits+1}
- end.
-
-
-send_to_all([], _Msg) ->
- true;
-send_to_all([Pid|Rest],Msg) when is_pid(Pid) ->
- Pid ! Msg,
- send_to_all(Rest,Msg);
-send_to_all([_Else|Rest],Msg) ->
- send_to_all(Rest,Msg).
-
-
-create_board(GS, ColorMode) ->
- Colors =
- case ColorMode of
- bw -> #colors{miss=white, x=white, bomb=white, face=[white]};
- _Color -> #colors{miss=red, x=green, bomb=white,
- face=[lightblue, orange, magenta, peachpuff, pink]}
- end,
- BGCol = if ColorMode==bw -> black; true -> black end, % background color
- TextCol = if ColorMode==bw -> white; true -> pink end, % status texts
- NrCol = if ColorMode==bw -> white; true -> purple end, % status figures
- LogoCol = if ColorMode==bw -> white; true -> green end, % bonk logo
- BLineCol = if ColorMode==bw -> white; true -> grey end, % button line
- SLineCol = if ColorMode==bw -> white; true -> red end, % status line
- BTextCol = if ColorMode==bw -> white; true -> orange end, % button text
- HiHeadCol = if ColorMode==bw -> white; true -> red end, % high score label
- HiCol = if ColorMode==bw -> white; true -> cyan end, % high scores
- SquareCol = if ColorMode==bw -> white; true -> yellow end, % game squares
- ErlFgCol = if ColorMode==bw -> white; true -> red end, %
- ErlBGCol = if ColorMode==bw -> black; true -> white end, %
- ErlTxtCol = if ColorMode==bw -> white; true -> black end, %
-
- Width = 550, % width of bonk window
- Height = 550, % Height of bonk window
-
- BX = 0, % x-pos for first button
- DBX = 100, % space between buttons
- BY = 0, % y-pos for buttons
- BLineY = 30, % y-pos of button line
- LogoX = (Width-320) div 2, % x-pos of bonk logo (logo is 320 pix wide)
- LogoY = BLineY+2, % y-pos of bonk logo
- ErlLogoX = LogoX + 200, % x-pos of Erlang e
- ErlLogoY = LogoY + 10, % y-pos of Erlang e
- SLineY = Height-22, % status line position
- TextWidth = 50, % text width of status items
- SX = 2, % x-pos for first status item
- DSX = TextWidth+94, % pixels between status items
- SY = SLineY+2, % y-pos status items
- HiWidth = 100, % width of high score field
- _HiHeight = 180, % height of the same
- HiX = Width-HiWidth, % high score text position
- HiY = BLineY+10,
- DHY = 20, % space between title & scores
- SquareSize = 76, % size of each game square
- SquareSpace = 1, % space between game squares
- SquareX = 40,
- SquareY = 65,
-
- gs:create(window, bonkWin, GS, [{width, Width}, {height, Height},
- {bg, BGCol},
- {title, "Bonk the game"},
- {iconname, "Bonk!"},
- {map, false}]),
- gs:create(canvas, bonkCanvas, bonkWin, [{width, Width},
- {height, Height},
- {bg, BGCol}]),
- gs:create(image, bonkCanvas, [{bitmap,lists:append(bonk_dir(), "bitmaps/bonklogo")},
- {coords, [{LogoX, LogoY}]},
- {fg, LogoCol},
- {bg, BGCol}]),
- gs:create(image, bonkCanvas, [{bitmap,lists:append(bonk_dir(), "bitmaps/erl-e")},
- {coords, [{ErlLogoX, ErlLogoY}]},
- {fg, ErlFgCol},
- {bg, ErlBGCol}]),
- gs:create(image, bonkCanvas, [{bitmap,lists:append(bonk_dir(), "bitmaps/erl-text")},
- {coords, [{ErlLogoX, ErlLogoY}]},
- {fg, ErlTxtCol}]),
- gs:create(line, bLine, bonkCanvas, [{coords, [{0,BLineY}, {Width,BLineY}]},
- {fg, BLineCol},
- {width, 2}]),
- gs:create(line, bLine, bonkCanvas, [{coords, [{0,SLineY}, {Width, SLineY}]},
- {fg, SLineCol},
- {width, 2}]),
- gs:create(text, scoreText, bonkCanvas, [{coords, [{SX, SY}]},
- {fg, TextCol},
- {text, "Score:"}]),
- gs:create(text, scoreOut, bonkCanvas, [{coords, [{SX+TextWidth, SY}]},
- {fg, NrCol},
- {width, DSX-TextWidth},
- {text, ""}]),
- gs:create(text, bombText, bonkCanvas, [{coords, [{SX+DSX, SY}]},
- {fg, TextCol},
- {text, "Bombs:"}]),
- gs:create(text, bombOut, bonkCanvas, [{coords, [{SX+DSX+TextWidth, SY}]},
- {fg, NrCol},
- {width, DSX-TextWidth},
- {text, ""}]),
- gs:create(text, bonusText, bonkCanvas, [{coords, [{SX+2*DSX, SY}]},
- {fg, TextCol},
- {text, "Bonus:"}]),
- gs:create(text, bonusOut, bonkCanvas, [{coords, [{SX+2*DSX+TextWidth, SY}]},
- {fg, NrCol},
- {width, DSX-TextWidth},
- {text, ""}]),
- gs:create(text, levelText,bonkCanvas, [{coords, [{SX+3*DSX, SY}]},
- {fg, TextCol},
- {text, "Level:"}]),
- gs:create(text, levelOut, bonkCanvas, [{coords, [{SX+3*DSX+TextWidth, SY}]},
- {fg, NrCol},
- {width, DSX-TextWidth},
- {text, ""}]),
- gs:create(text, hiScoreText, bonkCanvas, [{coords, [{HiX, HiY}]},
- {fg, HiHeadCol},
- {text, "High Scores"}]),
- gs:create(text, hiScoreOut, bonkCanvas, [{coords, [{HiX, HiY+DHY}]},
- {fg, HiCol},
- {justify, left},
- {width, HiWidth}]),
- gs:create(button, newButton,bonkWin, [{x, BX},{y, BY},
- {enable,false},
- {label, {text, "New Game"}},
- {click, true},
- {fg, BTextCol},
- {bg, BGCol},
- {relief, flat},
- {activefg, BTextCol},
- {activebg, BGCol},
- {align, center}]),
- gs:create(button, endButton,bonkWin, [{x, BX+DBX},{y, BY},
- {enable,false},
- {label, {text, "End Game"}},
- {click, true},
- {fg, BTextCol},
- {bg, BGCol},
- {relief, flat},
- {activefg, BTextCol},
- {activebg, BGCol},
- {align, center}]),
- gs:create(button, aboutButton,bonkWin, [{x, BX+2*DBX},{y, BY},
- {enable,false},
- {label, {text, "About"}},
- {click, true},
- {fg, BTextCol},
- {bg, BGCol},
- {relief, flat},
- {activefg, BTextCol},
- {activebg, BGCol},
- {align, center}]),
- gs:create(button, quitButton, bonkWin, [{x, BX+3*DBX},{y, BY},
- {enable,false},
- {label, {text, "Quit"}},
- {click, true},
- {fg, BTextCol},
- {bg, BGCol},
- {relief, flat},
- {activefg, BTextCol},
- {activebg, BGCol},
- {align, center}]),
-
- {SqrPids, Bmps} =
- create_squares(SquareX, SquareY, SquareSize, SquareCol, SquareSpace),
- gs:config(bonkWin, [{map, true}]),
- {SqrPids, Bmps, Colors}.
-
-
-
-create_squares(X, Y, Size, Color, Spc) ->
- create_squares(X, Y, Size, Color, Spc, 1, 1, [], []).
-
-
-create_squares(_X, _Y, _Size, _Color, _Spc, 4, 5, Pids, Bmps) ->
- {Pids, Bmps};
-
-create_squares(X, Y, Size, Color, Spc, Row, 5, Pids, Bmps) ->
- create_squares(X, Y, Size, Color, Spc, Row+1, 1, Pids, Bmps);
-
-create_squares(X, Y, Size, Color, Spc, Row, Col, Pids, Bmps) ->
- Xpos = X+Col*Size+(Col-1)*Spc,
- Ypos = Y+Row*Size+(Row-1)*Spc,
- gs:create(rectangle, bonkCanvas,
- [{coords, [{Xpos,Ypos},{Xpos+Size, Ypos+Size}]},
- {bw, 2},{fg, Color},{buttonpress,true}]),
- Bmp = gs:create(image, bonkCanvas,
- [{coords, [{Xpos+1, Ypos+1}]},
- {bitmap,lists:append(bonk_dir(), "bitmaps/bonktom")},
- {buttonpress, true},{fg, Color}]),
- Pid = bonk_square:start(Bmp),
- gs:config(Bmp, [{data, Pid}]),
- create_squares(X, Y, Size, Color, Spc, Row, Col+1, [Pid|Pids], [Bmp|Bmps]).
-
-
-
-clear_board([]) ->
- true;
-clear_board([Square | Rest]) ->
- gs:config(Square, [{bitmap,lists:append(bonk_dir(), "bitmaps/bonktom")}]),
- clear_board(Rest).
-
-
-%% Prints the list on the screen.
-%% The list is on the form [[Score,Name],[Score,Name]..].
-
-display_highscore(ScoreList) ->
- display_highscore("",ScoreList,0).
-
-display_highscore(Scores,[],_N) ->
- gs:config(hiScoreOut,[{text,Scores}]);
-
-display_highscore(Scores,_ScoreList,10) -> % This is max number of items.
- display_highscore(Scores,[], 10);
-
-display_highscore(Scores,[[Score,Name]|Rest],N) ->
- NewScores = lists:append(Scores,lists:append(lists:append(Score, [32 | Name]), [10])),
- display_highscore(NewScores,Rest,N+1).
-
-
-%% Reads the highscorelist from the file "bonk.score".
-%% The list should be an sorted erlang-list.
-
-get_highscore() ->
- case file:consult("bonk.score") of
- {ok,[Score_list]} ->
- {Score_list,"./bonk.score"};
- {error,_} ->
- {[],"./bonk.score"}
- end.
-
-
-%% Prints out the highscorelist and places the new score in the
-%% list if it is high enough.
-
-update_scorelist(SoundPid, Scores) ->
- case Scores#scores.points of
- 0 -> true;
- Score ->
- {ScoreL,FileName} = get_highscore(),
- New_scorelist=update_scorelist_2(ScoreL, Score, 0, SoundPid),
- display_highscore(New_scorelist),
- case file:open(FileName, [write]) of
- {error,_} ->
- true;
- {ok,FD} ->
- io:format(FD,"~w~s~n",[New_scorelist,"."]),
- file:close(FD)
- end
- end.
-
-
-update_scorelist_2([], Score, N, _SoundPid) when N < 10 ->
- [[integer_to_list(Score),getuser()]];
-
-update_scorelist_2(_, _, N, _SoundPid) when N >= 10 ->
- [];
-
-update_scorelist_2([[Sc, Name] | Rest], Score, N, SoundPid) ->
- case list_to_integer(Sc) of
- Sc_int when Sc_int < Score ->
- if
- N == 0 -> SoundPid ! best_score;
- true -> SoundPid ! high_score
- end,
- lists:append([[integer_to_list(Score),getuser()]],
- update_scorelist_3([[Sc,Name]|Rest],N+1));
- _Other ->
- lists:append([[Sc,Name]],update_scorelist_2(Rest, Score, N+1, SoundPid))
- end.
-
-
-update_scorelist_3([],_) ->
- [];
-
-update_scorelist_3(_,N) when N >= 10 ->
- [];
-
-update_scorelist_3([Item|Rest],N) ->
- lists:append([Item],update_scorelist_3(Rest,N+1)).
-
-getuser() ->
- case os:type() of
- {unix,_} ->
- lists:delete(10,os:cmd("whoami"));
- _ ->
- "Unknown"
- end.
-
-%% Prints out the initial values of scores, bonus, level and bombs.
-
-clear_scores(Scores) ->
- Score = integer_to_list(Scores#scores.points),
- Bombs = integer_to_list(Scores#scores.bombs),
- Bonus = integer_to_list(Scores#scores.bonus),
- Level = integer_to_list(Scores#scores.level),
- gs:config(scoreOut,{text,Score}),
- gs:config(bombOut,{text,Bombs}),
- gs:config(bonusOut,{text,Bonus}),
- gs:config(levelOut,{text,Level}).
-
-
-%% Removes everything that is present in the message-que.
-
-flush() ->
- receive
- _X ->
- flush()
- after
- 0 ->
- true
- end.
-
-sleep(X) ->
- receive after X -> true end.
-
-%% Opens a window and shows the contents of the file: "bonk.txt".
-%% The window will be removed before the function ends.
-
-display_about() ->
- {BGColor,TextColor,Bfg} =
- case get(colormode) of
- bw -> {black, white, white};
- _Color -> {black, peachpuff1, orange}
- end,
- Wid = 500, Hei = 635,
- GS = gs:start(),
- gs:create(window, aboutWin, GS, [{width, Wid}, {height,Hei},
- {map, false},
- {bg, BGColor},
- {title, "About Bonk!"}]),
- gs:create(canvas, aboutCan, aboutWin, [{width, Wid},{height, Hei},
- {bg, black}]),
- gs:create(button, okButton, aboutWin, [{x, Wid div 2 - 50},{y, Hei - 40},
- {label,{text, "Ok"}}, {click, true},
- {fg, Bfg}, {bg, BGColor},
- {relief, flat},
- {activefg, Bfg},
- {activebg, BGColor}]),
- gs:create(text, aboutText, aboutCan, [{width, Wid-30}, {coords, [{15, 0}]},
- {fg, TextColor}, {justify, center}]),
- case file:open(lists:append(bonk_dir(),"bonk.txt"), [read]) of
- {ok, Fd} ->
- write_text(Fd, "", io:get_line(Fd, "")),
- file:close(Fd);
- {error, _Reason} ->
- gs:config(aboutText, {text, "Error: could not read the about file"})
- end,
-
- gs:config(aboutWin, [{map,true}]),
- receive
- {gs, okButton, click, _, _} ->
- gs:destroy(aboutWin)
- end.
-
-write_text(_Fd, Text, eof) ->
- gs:config(aboutText, {text, Text});
-write_text(Fd, Text, More) ->
- write_text(Fd, lists:append(Text, More), io:get_line(Fd, "")).
diff --git a/lib/gs/contribs/bonk/bonk.gif b/lib/gs/contribs/bonk/bonk.gif
deleted file mode 100644
index 3c2299686b..0000000000
--- a/lib/gs/contribs/bonk/bonk.gif
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/bonk.tool b/lib/gs/contribs/bonk/bonk.tool
deleted file mode 100644
index 79ad8f6701..0000000000
--- a/lib/gs/contribs/bonk/bonk.tool
+++ /dev/null
@@ -1,6 +0,0 @@
-{version,"0.1"}.
-{{tool,"Bonk"},
- {start,{bonk,start,[]}},
- {icon,"bonk.gif"},
- {message,"Bonk - The Game"},
- {html,"../bonk/bonk.txt"}}.
diff --git a/lib/gs/contribs/bonk/bonk.txt b/lib/gs/contribs/bonk/bonk.txt
deleted file mode 100644
index 69c912dbee..0000000000
--- a/lib/gs/contribs/bonk/bonk.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-BONK! In Erlang for You
-by
-LENNART OHMAN & MARCUS ARENDT
-
-After an idea of Mike Darweesh.
-Special thanks to Peter Jansson for creating the bitmaps.
-Ported to GS 1.1 by Markus Torpvret and Anders Dahlin.
-
-
-INSTRUCTIONS
-- Hit as many creatures as possible using the left mouse-button.
-- After every 25 hits You will advance one level. For each level You get one bomb.
-- Pushing the middle or right mouse-button, in any square, drops a bomb which
-wipes out everything.
-- The game ends when 10 creatures has escaped from beeing bonked.
-
-
-ABOUT ERLANG
-Erlang is a programming language for building robust concurrent systems. It is a single assignment, symbolic language with built in concurrency. It provides unique facilities for error handling and for reloading updated modules in running systems. Erlang was designed and implemented by Joe Armstrong, Robert Virding, and Mike Williams at Ellemtel (now Ericsson Utvecklings AB).
-
-Please make enquiries about Erlang to:
-
-Ericsson Software Technology AB
-Erlang Systems
-Torshamnsgatan 39B
-Box 1214
-164 28 Kista
-Sweden
-
-http://www.ericsson.se/erlang \ No newline at end of file
diff --git a/lib/gs/contribs/bonk/bonk_sound.erl b/lib/gs/contribs/bonk/bonk_sound.erl
deleted file mode 100644
index 9a0db80e5d..0000000000
--- a/lib/gs/contribs/bonk/bonk_sound.erl
+++ /dev/null
@@ -1,82 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. 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(bonk_sound).
--export([start/0]).
-
-start() ->
- random:seed(),
- sounder:start(),
- {ok,Bonk}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/bonk.au")),
- {ok,Ouch}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/ouch!!!.au")),
- {ok,Damn}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/damn.au")),
- {ok,Bomb}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/explosion.au")),
- {ok,Missed}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/missedme.au")),
- {ok,Game_over}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/gameover.au")),
- {ok,New_level}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/level.au")),
- {ok,Music}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/trumpet.au")),
- {ok,Start}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/hehee.au")),
- {ok,BestS}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/praisejesus.au")),
- {ok,HighS}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/yes.au")),
- loop(Bonk, Ouch, Damn, Bomb, Missed, Game_over, New_level,
- Music, Start, BestS, HighS).
-
-
-loop(Bonk, Ouch, Damn, Bomb, Missed, Game_over, New_level, Music, Start, BestS, HighS) ->
- R=random:uniform(1000),
- receive
- bonk ->
- if
- R < 75 -> play_sound(Damn);
- R < 275 -> play_sound(Ouch);
- true -> play_sound(Bonk)
- end;
- bomb -> play_sound(Bomb);
- missed -> play_sound(Missed);
- game_over -> play_sound(Game_over);
- new_level -> play_sound(New_level);
- music -> play_sound(Music);
- start -> play_sound(Start);
- best_score -> play_sound(BestS);
- high_score -> play_sound(HighS);
- quit ->
- sounder:stop(),
- exit(normal)
- end,
- loop(Bonk, Ouch, Damn, Bomb, Missed, Game_over, New_level, Music, Start, BestS, HighS).
-
-play_sound(Snd) ->
- case catch sounder:play(Snd) of
- {'EXIT', _Reason} ->
- io:format("Cannot use audio device!\n"),
- sounder:stop(),
- silent_loop();
- _Other ->
- true
- end.
-
-silent_loop() ->
- receive
- quit ->
- exit(normal);
- _Other ->
- silent_loop()
- end.
diff --git a/lib/gs/contribs/bonk/bonk_square.erl b/lib/gs/contribs/bonk/bonk_square.erl
deleted file mode 100644
index 98af91944b..0000000000
--- a/lib/gs/contribs/bonk/bonk_square.erl
+++ /dev/null
@@ -1,146 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. 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(bonk_square).
--export([start/1,init/5,alarm/3]).
-
-
-
-start(Bmp) ->
- spawn_link(bonk_square, init, [Bmp, self(),
- random:uniform(10000),
- random:uniform(10000),
- random:uniform(10000)]).
-
-init(Bmp, BoardPid, Seed1, Seed2, Seed3) ->
- random:seed(Seed1,Seed2,Seed3),
- idle(Bmp, BoardPid).
-
-
-idle(Bmp, BoardPid) ->
- receive
- start ->
- Level = 1,
- sleep(Level, Bmp, BoardPid, alarm(sleep_time(Level), wake_up));
- quit ->
- exit(normal);
- _Other ->
- idle(Bmp, BoardPid)
- end.
-
-
-sleep(Level, Bmp, BoardPid, Alarm) ->
- receive
- stop ->
- Alarm ! quit,
- idle(Bmp, BoardPid);
- quit ->
- Alarm ! quit,
- exit(normal);
- {new_level, NewLevel} ->
- sleep(NewLevel, Bmp, BoardPid, Alarm);
- {Alarm, wake_up} ->
- show_me(BoardPid, Bmp),
- show(Level, Bmp, BoardPid, alarm(2500, missed));
- _Other ->
- sleep(Level, Bmp, BoardPid, Alarm)
- end.
-
-
-show(Level, Bmp, BoardPid, Alarm) ->
- receive
- stop ->
- Alarm ! quit,
- idle(Bmp, BoardPid);
- quit ->
- Alarm ! quit,
- exit(normal);
- {new_level, NewLevel} ->
- show(NewLevel, Bmp, BoardPid, Alarm);
- sleep -> % The board was too crowded.
- Alarm ! quit,
- sleep(Level, Bmp, BoardPid, alarm(sleep_time(Level), wake_up));
- bonk ->
- bonk_me(BoardPid, Bmp),
- Alarm ! quit,
- bbmed(Level, Bmp, BoardPid, alarm(1500, hide));
- bomb ->
- bomb_me(BoardPid, Bmp),
- Alarm ! quit,
- bbmed(Level, Bmp, BoardPid, alarm(1000, hide));
- {Alarm, missed} ->
- missed_me(BoardPid, Bmp),
- bbmed(Level, Bmp, BoardPid, alarm(1500, hide));
- _Other ->
- show(Level, Bmp, BoardPid, Alarm)
- end.
-
-%% bonked, bombed or missed
-bbmed(Level, Bmp, BoardPid, Alarm) ->
- receive
- stop ->
- Alarm ! quit,
- idle(Bmp, BoardPid);
- quit ->
- Alarm ! quit,
- exit(normal);
- {new_level, NewLevel} ->
- bbmed(NewLevel, Bmp, BoardPid, Alarm);
- {Alarm, hide} ->
- hide_me(BoardPid, Bmp),
- sleep(Level, Bmp, BoardPid, alarm(sleep_time(Level), wake_up));
- _Other ->
- bbmed(Level, Bmp, BoardPid, Alarm)
- end.
-
-
-show_me(BoardPid, Bmp) ->
- BoardPid ! {show, self(), Bmp}.
-
-hide_me(BoardPid, Bmp) ->
- BoardPid ! {hide, self(), Bmp}.
-
-bonk_me(BoardPid, Bmp) ->
- BoardPid ! {bonked, self(), Bmp}.
-
-bomb_me(BoardPid, Bmp) ->
- BoardPid ! {bombed, self(), Bmp}.
-
-missed_me(BoardPid, Bmp) ->
- BoardPid ! {missed, self(), Bmp}.
-
-
-%% Count sleep time
-
-sleep_time(Level) ->
- random:uniform((19000 div (Level+1))*2+1500).
-
-%% Set an alarm
-
-alarm(Time, Msg) ->
- spawn(bonk_square, alarm, [Time, Msg, self()]).
-
-alarm(Time, Msg, Pid) ->
- receive
- quit -> exit(normal)
- after
- Time -> Pid ! {self(), Msg}
- end.
diff --git a/lib/gs/contribs/bonk/sounder.erl b/lib/gs/contribs/bonk/sounder.erl
deleted file mode 100644
index aabcaa1950..0000000000
--- a/lib/gs/contribs/bonk/sounder.erl
+++ /dev/null
@@ -1,160 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2011. 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(sounder).
--export([start/0,play/1,new/1,go/0,stop/0,nosound/0,silent/0]).
--include_lib("kernel/include/file.hrl").
-%%----------------------------------------------------------------------
-%% sounder.erl - An interface to /dev/audio
-%%
-%% Created by: {lennarto,mike}@erix.ericsson.se
-%% Modified by: EV,[email protected]
-%%
-%% Mod: 6 Jun 1996 by [email protected]
-%% The executable sounder will no be looked for in the
-%% same directory as from where sounder.jam is loaded.
-%%
-%%
-%% start() - Returns either: ok ,or: silent ,where silent means
-%% that no audio capabilities exists but the sounder
-%% will work "silently" in order to not break any code.
-%%
-%% stop() - Returns: ok
-%%
-%% new(File) - Tries to load the File. At success, a number refering
-%% to the File is returned that shall be used with send/1.
-%% Otherwise {error,Reason} is returned.
-%%
-%% play(No) - Tries to execute the sound registered with the number No
-%% Returns: ok , or: {error,Reason}
-%%
-%% silent() - Returns: true ,if no audio capabilities exists, else: false
-%%
-%% Note: It is also possible to receive: {error,sounder_not_started}
-%%
-%%----------------------------------------------------------------------
-
-start() ->
- case whereis(sounder) of
- undefined ->
- %% first we check if the workstation has audio capabilities
- case file:read_file_info('/dev/audio') of
- {ok, FI} when FI#file_info.access==read_write ->
- register(sounder, spawn(sounder,go,[])),
- ok;
- _Other ->
- register(sounder, spawn(sounder,nosound,[])),
- silent
- end;
- _Pid ->
- ok
- end.
-
-stop() ->
- catch begin check(),
- sounder ! {stop},
- ok end.
-
-new(File) when is_list(File) -> new(list_to_atom(File));
-new(File) when is_atom(File) ->
- catch begin check(),
- sounder ! {new,File,self()},
- wait_for_ack(sounder) end.
-
-play(No) when is_integer(No) ->
- catch begin check(),
- sounder ! {play, No, self()},
- wait_for_ack(sounder) end.
-
-silent() ->
- catch begin check(),
- sounder ! {play,silent,self()},
- receive {sounder,Answer} -> Answer end end.
-
-go() ->
- Port = open_port({spawn,lists:append(bonk:bonk_dir(), "sounder")},[{packet, 2}]),
- loop(Port).
-
-loop(Port) ->
- receive
- {new, File, From} when is_atom(File) ->
- Port ! {self(),{command,lists:append([0],atom_to_list(File))}},
- From ! {sounder,wait_for_ack(Port)},
- loop(Port);
- {play,silent,From} ->
- From ! {sounder,false},
- loop(Port);
- {play,No,From} when is_integer(No) ->
- Port ! {self(),{command,[No]}},
- From ! {sounder,wait_for_ack(Port)},
- loop(Port);
- {stop} ->
- Port ! {self(),close},
- exit(normal);
- _ ->
- loop(Port)
- end.
-
-%% The application using sounds can check on silence itself
-%% and refrain from playing sounds.
-%% Or it can try to play sounds that will be "consumed in silence"
-
-nosound() ->
- receive
- {new,File,From} when is_atom(File) ->
- From ! {sounder,{ok,silent}},
- nosound();
- {play,silent,From} ->
- From ! {sounder,true},
- nosound();
- {play,No,From} when is_integer(No) ->
- From ! {sounder,{error,no_audio_cap}},
- nosound();
- {stop} ->
- exit(normal);
- _ ->
- nosound()
- end.
-
-wait_for_ack(sounder) ->
- receive {sounder,Res} -> Res end;
-wait_for_ack(Port) when is_port(Port) ->
- receive
- {Port,{data,"ok"}} ->
- ok;
- {Port,{data,[No]}} ->
- {ok,No};
- {Port,{data,Msg}} ->
- {error,list_to_atom(Msg)};
- {'EXIT',Port,_} ->
- exit(port_exited)
- end.
-
-check() ->
- case whereis(sounder) of
- Pid when is_pid(Pid) ->
- ok;
- undefined ->
- throw({error,sounder_not_started})
- end.
-
-
-
diff --git a/lib/gs/contribs/bonk/sounds/bonk.au b/lib/gs/contribs/bonk/sounds/bonk.au
deleted file mode 100644
index 5e6518898b..0000000000
--- a/lib/gs/contribs/bonk/sounds/bonk.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/damn.au b/lib/gs/contribs/bonk/sounds/damn.au
deleted file mode 100644
index 6117506fb4..0000000000
--- a/lib/gs/contribs/bonk/sounds/damn.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/explosion.au b/lib/gs/contribs/bonk/sounds/explosion.au
deleted file mode 100644
index 78a6964f1a..0000000000
--- a/lib/gs/contribs/bonk/sounds/explosion.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/gameover.au b/lib/gs/contribs/bonk/sounds/gameover.au
deleted file mode 100644
index ca7628f3c6..0000000000
--- a/lib/gs/contribs/bonk/sounds/gameover.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/hehee.au b/lib/gs/contribs/bonk/sounds/hehee.au
deleted file mode 100644
index 10cd16b596..0000000000
--- a/lib/gs/contribs/bonk/sounds/hehee.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/level.au b/lib/gs/contribs/bonk/sounds/level.au
deleted file mode 100644
index 0508c2a6ae..0000000000
--- a/lib/gs/contribs/bonk/sounds/level.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/missedme.au b/lib/gs/contribs/bonk/sounds/missedme.au
deleted file mode 100644
index 4c07c9d428..0000000000
--- a/lib/gs/contribs/bonk/sounds/missedme.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/music.au b/lib/gs/contribs/bonk/sounds/music.au
deleted file mode 100644
index ead6ec79b2..0000000000
--- a/lib/gs/contribs/bonk/sounds/music.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/ouch!!!.au b/lib/gs/contribs/bonk/sounds/ouch!!!.au
deleted file mode 100644
index 78bcf48074..0000000000
--- a/lib/gs/contribs/bonk/sounds/ouch!!!.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/praisejesus.au b/lib/gs/contribs/bonk/sounds/praisejesus.au
deleted file mode 100644
index e299bf66d6..0000000000
--- a/lib/gs/contribs/bonk/sounds/praisejesus.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/trumpet.au b/lib/gs/contribs/bonk/sounds/trumpet.au
deleted file mode 100644
index 2f551b436a..0000000000
--- a/lib/gs/contribs/bonk/sounds/trumpet.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/yes.au b/lib/gs/contribs/bonk/sounds/yes.au
deleted file mode 100644
index c1ce7dfb69..0000000000
--- a/lib/gs/contribs/bonk/sounds/yes.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/cols/Makefile b/lib/gs/contribs/cols/Makefile
deleted file mode 100644
index 34a900e5ab..0000000000
--- a/lib/gs/contribs/cols/Makefile
+++ /dev/null
@@ -1,103 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-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%
-#
-
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(GS_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/gs-$(VSN)/contribs
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES= \
- cols \
- highscore
-
-HRL_FILES=
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=../ebin/%.$(EMULATOR)) $(TARGET_TOOLBOX_FILES)
-
-TOOLNAME = cols
-
-EXTRA_FILES=
-TOOLBOX_FILES= $(TOOLNAME).tool $(TOOLNAME).gif help.gif
-TARGET_TOOLBOX_FILES= $(TOOLBOX_FILES:%=$(EBIN)/%)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_COMPILE_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(TARGET_FILES)
-
-docs:
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f core
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-$(EBIN)/$(TOOLNAME).gif: $(TOOLNAME).gif
- $(gen_verbose)rm -f $@
- $(V_at)cp $(TOOLNAME).gif $@
-
-$(EBIN)/$(TOOLNAME).tool: $(TOOLNAME).tool
- $(gen_verbose)rm -f $@
- $(V_at)cp $(TOOLNAME).tool $@
-
-$(EBIN)/help.gif: help.gif
- $(gen_verbose)rm -f $@
- $(V_at)cp help.gif $@
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/cols/bitmaps"
- $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) "$(RELSYSDIR)/cols/bitmaps"
- $(INSTALL_DIR) "$(RELSYSDIR)/cols"
- $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/cols"
-
-release_docs_spec:
-
diff --git a/lib/gs/contribs/cols/cols.erl b/lib/gs/contribs/cols/cols.erl
deleted file mode 100644
index 265f2b6ee8..0000000000
--- a/lib/gs/contribs/cols/cols.erl
+++ /dev/null
@@ -1,625 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-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(cols).
--compile([{nowarn_deprecated_function,{gs,config,2}},
- {nowarn_deprecated_function,{gs,create,3}},
- {nowarn_deprecated_function,{gs,create,4}},
- {nowarn_deprecated_function,{gs,destroy,1}},
- {nowarn_deprecated_function,{gs,read,2}},
- {nowarn_deprecated_function,{gs,start,0}}]).
-
--export([start/0, init/0]).
-
-%% internal export.
--export([make_board_elem/3]).
-
-%%======================================================================
-%% Contents
-%%=====================
-%% 1. The actual program
-%% 2. Graphics
-%% 3. Data structures and stuff
-%% 4. Lambdas
-%%======================================================================
-
-
--define(COLORS, {red,green,blue,grey,yellow,{66,153,130}}).
--define(HIGHFILE, "./cols.high").
--define(HEIGHT, 17).
--define(LEFT, 50).
--define(SIZE, 15).
--define(VERSION, "v0.9").
--define(WIDTH, 8).
-
--record(state, {bit,board,nextbit,ticks, score=0}).
-%%----------------------------------------------------------------------
-%% Consists of three boxes.
-%%----------------------------------------------------------------------
--record(bit, {x,y,topColor, middleColor, bottomColor,
- top_gsobj,mid_gsobj,bot_gsobj}).
-
-%%======================================================================
-%% 1. The actual program
-%%======================================================================
-
-start() ->
- spawn_link(cols,init,[]).
-
-init() ->
- make_graphics(),
- {A,B,C} = erlang:now(),
- random:seed(A,B,C),
- NextBit = make_bit(),
- Board = make_screen_board(),
- S = #state{bit=make_bit(), board=Board, ticks=update_timer(1),
- score=make_score(), nextbit=new_bit_xy(NextBit, -2,5)},
- gs:config(win, [{map, true}]),
- loop(S).
-
-make_graphics() ->
- G = gs:start(),
- H = ?HEIGHT*?SIZE,
- W = ?WIDTH*?SIZE,
- BotMargin = 100,
- gs:create(window, win, G, [{destroy,true},{map, true},{title, "cols"},
- {height, H+BotMargin}, {width, W+?LEFT+10},
- {bg, grey},{keypress,true}]),
- gs:create(canvas, can, win, [{bg, black},
- {height, H+BotMargin},
- {width, W+?LEFT+20}]),
- gs:create(text, can, [{text, "Next"}, {coords, [{5, 45}]}, {fg, red}]),
- gs:create(image, help, can, [{coords,[{5,7}]},
- {load_gif, dir() ++ "/help.gif"},
- {buttonpress,true}]),
- draw_borders().
-
-loop(State) ->
- receive
- Event -> loop(update(Event, State))
- end.
-
-%%----------------------------------------------------------------------
-%% How fast speed should be doubled
-%%----------------------------------------------------------------------
--define(DBL_TICKS, 300).
-
-update_timer(Ticks) ->
- K = 0.001/?DBL_TICKS,
- M = 1.001-K,
- Q = K*Ticks+M,
- Timeout = round(1/math:log(Q)),
- timer:send_after(Timeout, self(), fall_timeout),
- Ticks+1.
-
-add_score({ScoreObj, NScore}, DScore) ->
- NScore2 = NScore + DScore,
- gs:config(ScoreObj, [{text, io_lib:format("Score: ~w", [NScore2])}]),
- {ScoreObj, NScore2}.
-
-
-update({gs,_Obj,keypress,_Data, ['Left'|_]}, State) ->
- #state{bit=Bit, board = Board} = State,
- #bit{x=X,y=Y} = Bit,
- if X > 0 ->
- case is_board_empty(Board, X-1,Y) of
- true ->
- State#state{bit=new_bit_xy(Bit, X-1, Y)};
- false ->
- State
- end;
- true -> State
- end;
-
-update({gs,_Obj,keypress,_Data, ['Right'|_]}, State) ->
- #state{bit=Bit, board = Board} = State,
- #bit{x=X,y=Y} = Bit,
- if X < ?WIDTH - 1 ->
- case is_board_empty(Board, X+1, Y) of
- true ->
- State#state{bit=new_bit_xy(Bit, X+1, Y)};
- false ->
- State
- end;
- true -> State
- end;
-
-update({gs,_Obj,keypress,_Data, ['Up'|_]}, State) ->
- State#state{bit=shift_bits(State#state.bit)};
-
-update({gs,_Obj,keypress,_Data, [Key|_]}, State) ->
- case drop_key(Key) of
- true ->
- #state{bit=Bit, board=Board, score=Score} = State,
- #bit{x=X,y=Y} = Bit,
- {NewX, NewY, NewScore} = drop(X,Y,Score,Board),
- fasten_bit(State#state{bit=new_bit_xy(Bit,NewX, NewY),
- score=NewScore});
- false -> State
- end;
-
-update(fall_timeout, State) ->
- #state{bit=Bit, board=Board, ticks = Ticks, score=Score} = State,
- NewY = Bit#bit.y+1,
- X = Bit#bit.x,
- case is_fall_ok(Board, X, NewY) of
- true ->
- State#state{bit=new_bit_xy(Bit, X, NewY),
- ticks=update_timer(Ticks), score=add_score(Score, 1)};
- false ->
- S1 = fasten_bit(State),
- S1#state{ticks=update_timer(Ticks)}
- end;
-
-update({gs,_,destroy,_,_}, _State) ->
- exit(normal);
-
-update({gs,help,buttonpress,_,_}, State) ->
- show_help(),
- State;
-
-update(OtherEvent, State) ->
- ok=io:format("got other! ~w~n", [OtherEvent]), State.
-
-drop_key('Down') -> true;
-drop_key(space) -> true;
-drop_key(_) -> false.
-
-is_board_empty(Board, X, Y) ->
- case {color_at(Board, X, Y),
- color_at(Board, X, Y + 1),
- color_at(Board, X, Y + 2)} of
- {black, black, black} -> true;
- _ -> false
- end.
-
-%%----------------------------------------------------------------------
-%% Returns: NewState
-%%----------------------------------------------------------------------
-fasten_bit(State) ->
- #state{board=Board, bit=Bit, nextbit=NextBit, score=Score} = State,
- #bit{x=X,y=Y,topColor=C1,middleColor=C2,bottomColor=C3} = Bit,
- B1 = update_screen_element(Board, X, Y, C1),
- B2 = update_screen_element(B1, X, Y+1, C2),
- B3 = update_screen_element(B2, X, Y+2, C3),
- destroy_bit(Bit),
- #bit{topColor=NC1,middleColor=NC2,bottomColor=NC3} = NextBit,
- {B4, ExtraScore} = erase_bits(B3, [{X,Y},{X,Y+1},{X,Y+2}], 0),
- NewBit = make_bit(NC1,NC2,NC3),
- case is_board_empty(B4, NewBit#bit.x, NewBit#bit.y) of
- true ->
- State#state{score=add_score(Score, ExtraScore),
- bit=NewBit, nextbit=new_colors(NextBit),board=B4};
- false ->
- {_GsObj,Score2}=State#state.score,
- highscore:run(Score2,?HIGHFILE),
- exit(normal)
- end.
-
-%%----------------------------------------------------------------------
-%% Args: Check: list of {X,Y} to check.
-%% Returns: {NewBoard, ExtraScore}
-%%----------------------------------------------------------------------
-erase_bits(Board, Checks, ExtraScore) ->
- ElemsToDelete = elems2del(Checks,Board,[]),
- NDel = length(ElemsToDelete),
- if
- NDel > 0 ->
- Board2 = delete_elems(Board, ElemsToDelete),
- {NewBoard, NewCheck} = fall_down(Board2, ElemsToDelete),
- if NDel > 3 ->
- {B,ES}=erase_bits(NewBoard,NewCheck,ExtraScore+2*NDel),
- {NewBoard2, NewCheck2} = bonus(B, NewCheck),
- erase_bits(NewBoard2, NewCheck2, ES);
- true ->
- erase_bits(NewBoard, NewCheck, 2*NDel)
- end;
- true -> {Board, ExtraScore}
- end.
-
-bonus(Board, Check) ->
- Cols = collect_bottom_bits(0,Board),
- NewBoard = randomize_columns(5, Board, Cols),
- NewCheck = update_check(Check, Cols),
- {NewBoard, NewCheck}.
-
-randomize_columns(0, Board, _) -> Board;
-randomize_columns(N, Board, Cols) ->
- NewBoard = randomize_columns(Cols,Board),
- randomize_columns(N-1, NewBoard, Cols).
-
-randomize_columns([],Board) -> Board;
-randomize_columns([X|Xs],Board) ->
- flush(),
- timer:sleep(50),
- randomize_columns(Xs,update_screen_element(Board,X,?HEIGHT-1,rndColor())).
-
-%%----------------------------------------------------------------------
-%% Returns: NewBoard
-%%----------------------------------------------------------------------
-delete_elems(Board, Elems2Del) ->
- OrgObjs = org_objs(Elems2Del,Board),
- visual_effect(?SIZE, OrgObjs),
- NewBoard = update_board(Elems2Del, Board),
- put_back(OrgObjs),
- NewBoard.
-
-visual_effect(0,_OrgObjs) -> done;
-visual_effect(Size,OrgObjs) ->
- set_size(OrgObjs,Size),
- flush(),
- timer:sleep(20),
- visual_effect(Size-1,OrgObjs).
-
-set_size([],_Size) -> done;
-set_size([{GsObj,[{X1,Y1},{_X2,_Y2}]}|T],Size) ->
- gs:config(GsObj, [{coords, [{X1,Y1},{X1+Size,Y1+Size}]}]),
- set_size(T,Size).
-
-%%----------------------------------------------------------------------
-%% Note: Loop over columns where something is removed only. (efficiency)
-%% Returns: {ReversedNewColumns (perhaps shorter), Checks}
-%% cols:fall_column([a,b,black,black,c,f,black,d,black], 3, 15, [], []).
-%% should return: {[a,b,c,f,d],[{3,11},{3,12},{3,13}]}
-%%----------------------------------------------------------------------
-fall_column([], _X, _Y, ColumnAcc, ChecksAcc) ->
- {ColumnAcc, ChecksAcc};
-fall_column([black|Colors], X, Y, ColumnAcc, ChecksAcc) ->
- case find_box(Colors) of
- false -> {ColumnAcc, ChecksAcc};
- NewColors when is_list(NewColors) ->
- fall_one_step(NewColors, X, Y, ColumnAcc, ChecksAcc)
- end;
-fall_column([Color|Colors], X, Y, ColumnAcc, ChecksAcc) ->
- fall_column(Colors, X, Y-1, [Color | ColumnAcc], ChecksAcc).
-
-find_box([]) -> false;
-find_box([black|Colors]) ->
- find_box(Colors);
-find_box([Color|Colors]) -> [Color|Colors].
-
-%%----------------------------------------------------------------------
-%% Enters: ([a,b, , ,c,d], 3, 8, Q)
-%% Leaves: ([b,a|Q], [ , , ,c,d], 10, [{3,8},{4,9}])
-%%----------------------------------------------------------------------
-fall_one_step([], X, Y, ColumnAcc, Checks) ->
- fall_column([], X, Y, ColumnAcc, Checks);
-fall_one_step([black|Colors], X, Y, ColumnAcc, Checks) ->
- fall_column([black|Colors], X, Y, ColumnAcc, Checks);
-fall_one_step([Color|Colors], X, Y, ColumnAcc, Checks) ->
- fall_one_step(Colors, X, Y-1, [Color|ColumnAcc],[{X,Y}|Checks]).
-
-%%----------------------------------------------------------------------
-%% Returns: {NewBoard, NewChecks}
-%%----------------------------------------------------------------------
-fall_down(Board1, Elems2Del) ->
- UpDatedCols = updated_cols(Elems2Del, []),
- fall_column(UpDatedCols, Board1, []).
-
-fall_column([], NewBoard, NewChecks) -> {NewBoard, NewChecks};
-fall_column([X|Xs], BoardAcc, ChecksAcc) ->
- OrgColumn = boardcolumn_to_tuple(BoardAcc, X),
- Column = columntuple_to_list(OrgColumn),
- {NewColumn, NewChecksAcc} = fall_column(Column, X,?HEIGHT-1,[],ChecksAcc),
- NewBoardAcc =
- set_board_column(BoardAcc,X,new_column_list(NewColumn,OrgColumn)),
- fall_column(Xs,NewBoardAcc,NewChecksAcc).
-
-new_column_list(NewColumn, ColumnTuple) ->
- Nempty = ?HEIGHT - length(NewColumn),
- L = make_list(black, Nempty) ++ NewColumn,
- new_column_list(L, 1, ColumnTuple).
-
-new_column_list([H|T], N, Tuple) ->
- {GsObj, Color} = element(N, Tuple),
- [update_screen_element({GsObj, Color},H) | new_column_list(T, N+1, Tuple)];
-new_column_list([], _, _) -> [].
-
-
-%%----------------------------------------------------------------------
-%% Returns: a reversed list of colors.
-%%----------------------------------------------------------------------
-columntuple_to_list(ColumnTuple) when is_tuple(ColumnTuple) ->
- columntuple_to_list(tuple_to_list(ColumnTuple),[]).
-
-columntuple_to_list([],Acc) -> Acc;
-columntuple_to_list([{_GsObj, Color}|T],Acc) ->
- columntuple_to_list(T,[Color|Acc]).
-
-%%======================================================================
-%% 2. Graphics
-%%======================================================================
-
-make_bit() ->
- make_bit(rndColor(),rndColor(),rndColor()).
-
-make_bit(Tc,Mc,Bc) ->
- X = ?WIDTH div 2,
- Y = 0,
- #bit{x=X,y=Y,topColor= Tc, middleColor=Mc, bottomColor=Bc,
- top_gsobj = make_box(X,Y,Tc), mid_gsobj=make_box(X,Y+1,Mc),
- bot_gsobj=make_box(X,Y+2,Bc)}.
-
-new_colors(Bit) ->
- #bit{top_gsobj=T,mid_gsobj=M,bot_gsobj=B} = Bit,
- Tc = rndColor(),
- Mc = rndColor(),
- Bc = rndColor(),
- gs:config(T, [{fill, Tc}]),
- gs:config(M, [{fill, Mc}]),
- gs:config(B, [{fill, Bc}]),
- Bit#bit{topColor= Tc, middleColor=Mc, bottomColor=Bc}.
-
-new_bit_xy(Bit, NewX, NewY) ->
- #bit{x=X,y=Y,top_gsobj=T,mid_gsobj=M,bot_gsobj=B} = Bit,
- Dx = (NewX - X) * ?SIZE,
- Dy = (NewY - Y) * ?SIZE,
- gs:config(T, [{move, {Dx, Dy}}]),
- gs:config(M, [{move, {Dx, Dy}}]),
- gs:config(B, [{move, {Dx, Dy}}]),
- Bit#bit{x=NewX, y=NewY}.
-
-destroy_bit(#bit{top_gsobj=T,mid_gsobj=M,bot_gsobj=B}) ->
- gs:destroy(T),
- gs:destroy(M),
- gs:destroy(B).
-
-shift_bits(Bit) ->
- #bit{topColor=C1,middleColor=C2,bottomColor=C3,
- top_gsobj=T,mid_gsobj=M,bot_gsobj=B} = Bit,
- gs:config(T, {fill,C2}),
- gs:config(M, {fill,C3}),
- gs:config(B, {fill,C1}),
- Bit#bit{topColor=C2, middleColor=C3, bottomColor=C1}.
-
-rndColor() ->
- Siz = size(?COLORS),
- element(random:uniform(Siz), ?COLORS).
-
-make_score() ->
- {gs:create(text, can, [{text, "Score: 0"}, {fg, red},
- {coords, [{5,?HEIGHT*?SIZE+10}]}]), 0}.
-
-make_screen_board() ->
- xy_loop({cols,make_board_elem}, make_board(), ?WIDTH, ?HEIGHT).
-
-make_board_elem(X,Y,Board) ->
- set_board_element(Board,X,Y,{make_box(X,Y,black),black}).
-
-flush() -> gs:read(can, bg).
-
-draw_borders() ->
- BotY = ?HEIGHT*?SIZE,
- RightX = ?LEFT + ?SIZE*?WIDTH,
- LeftX = ?LEFT - 1,
- gs:create(line,can,[{coords,[{LeftX,0},{LeftX,BotY}]},{fg,white}]),
- gs:create(line,can,[{coords,[{LeftX,BotY},{RightX,BotY}]},{fg,white}]),
- gs:create(line,can,[{coords,[{RightX,0},{RightX, BotY}]}, {fg,white}]).
-
-update_screen_element(ScrBoard, X, Y, Color) ->
- case board_element(ScrBoard,X,Y) of
- {_GsObj, Color} ->
- ScrBoard; % don't have to update screen
- {GsObj, _ScreenColor} ->
- gs:config(GsObj, color_args(Color)),
- set_board_element(ScrBoard, X, Y, {GsObj, Color})
- end.
-
-update_screen_element(ScrElem, Color) ->
- case ScrElem of
- {_GsObj, Color} ->
- ScrElem; % don't have to update screen
- {GsObj, _ScreenColor} ->
- gs:config(GsObj, color_args(Color)),
- {GsObj, Color}
- end.
-
-
-color_args(black) -> [{fg,black},{fill,black}];
-color_args(Color) -> [{fg,white},{fill,Color}].
-
-%%======================================================================
-%% 3. Data structures and stuff
-%%======================================================================
-
-xy_loop(Fun, Acc, XMax, YMax) ->
- xy_loop(Fun, Acc, 0, 0, XMax, YMax).
-
-xy_loop(_Fun, Acc, _X, YMax, _XMax, YMax) -> Acc;
-xy_loop(Fun, Acc, XMax, Y, XMax, YMax) ->
- xy_loop(Fun, Acc, 0, Y+1, XMax, YMax);
-xy_loop(Fun, Acc, X, Y, XMax, YMax) ->
- xy_loop(Fun, apply(Fun, [X, Y,Acc]), X+1,Y,XMax, YMax).
-
-%%----------------------------------------------------------------------
-%% Returns: a sorted list of {X,Y} to delete.
-%% Pre: PrevDelElems is sorted.
-%%----------------------------------------------------------------------
-erase_bits_at(Board, PrevDelElems, X,Y) ->
- C = color_at(Board, X, Y),
- erase_bits_at([vert, horiz, slash, backslash],X,Y,C,Board,PrevDelElems).
-
-erase_bits_at([], _X,_Y,_C,_Board, Elems2Del) -> Elems2Del;
-erase_bits_at([Dir|Ds],X,Y,C,Board, Elems2DelAcc) ->
- Dx = dx(Dir),
- Dy = dy(Dir),
- DelElems = lists:append(check_dir(Board, X-Dx,Y-Dy,-Dx,-Dy,C),
- check_dir(Board, X,Y,Dx,Dy,C)),
- N_in_a_row = length(DelElems),
- if N_in_a_row >= 3 ->
- erase_bits_at(Ds,X,Y,C,Board,
- ordsets:union(lists:sort(DelElems),Elems2DelAcc));
- true -> erase_bits_at(Ds,X,Y,C,Board,Elems2DelAcc)
- end.
-
-dx(vert) -> 0;
-dx(horiz) -> 1;
-dx(slash) -> 1;
-dx(backslash) -> -1.
-
-dy(vert) -> -1;
-dy(horiz) -> 0;
-dy(slash) -> -1;
-dy(backslash) -> -1.
-
-
-%%----------------------------------------------------------------------
-%% Returns: list of {X,Y} to delete.
-%%----------------------------------------------------------------------
-check_dir(Board, X, Y, Dx, Dy, Color)
- when X >= 0, X < ?WIDTH, Y >= 0, Y < ?HEIGHT ->
- case color_at(Board, X, Y) of
- Color ->
- [{X,Y} | check_dir(Board, X+Dx, Y+Dy, Dx, Dy, Color)];
- _OtherColor ->
- []
- end;
-check_dir(_Board, _X, _Y, _Dx, _Dy, _Color) -> [].
-
-make_box(X, Y, Color) ->
- make_box(X, Y, 1, 1, Color).
-
-%%----------------------------------------------------------------------
-%% Returns: GsObj
-%%----------------------------------------------------------------------
-make_box(X, Y, Height, Width, Color) ->
- Opts = if Color == black -> [{fg, black}, {fill, black}];
- true -> [{fill, Color}, {fg, white}] end,
- gs:create(rectangle, can, [{coords, [{?LEFT + X * ?SIZE, Y * ?SIZE},
- {?LEFT + X * ?SIZE + (?SIZE*Width)-1,
- Y * ?SIZE + (?SIZE*Height)-1}]}|Opts]).
-
-is_fall_ok(_Board, _NewX, NewY) when NewY+2 >= ?HEIGHT -> false;
-is_fall_ok(Board, NewX, NewY) ->
- case color_at(Board, NewX, NewY+2) of
- black ->
- true;
- _ -> false
- end.
-
-color_at(Board, X, Y) ->
- {_GsObj, Color} = board_element(Board, X, Y),
- Color.
-
-
-%%----------------------------------------------------------------------
-%% X:0..?WIDTH-1, Y:0..?HEIGHT
-%%----------------------------------------------------------------------
-make_board() ->
- list_to_tuple(make_list(make_column(), ?WIDTH)).
-
-board_element(Board, X, Y) ->
- element(Y+1, element(X+1, Board)).
-
-set_board_element(Board, X, Y, NewValue) ->
- Col = element(X+1, Board),
- NewCol=setelement(Y+1,Col, NewValue),
- setelement(X+1, Board, NewCol).
-
-make_column() ->
- list_to_tuple(make_list(black, ?HEIGHT)).
-
-make_list(_Elem, 0) -> [];
-make_list(Elem, N) -> [Elem|make_list(Elem,N-1)].
-
-boardcolumn_to_tuple(Board, X) ->
- element(X+1, Board).
-
-set_board_column(Board, X, NewCol) when length(NewCol) == ?HEIGHT ->
- setelement(X+1, Board, list_to_tuple(NewCol)).
-
-show_help() ->
- W = gs:create(window, win, [{title, "cols Help"}, {width, 300},
- {height,300}, {map, true}]),
- gs:create(label, W, [{x,0},{y,0},{height, 200},{width,300},{justify,center},
- {label, {text,
- "cols $Revision: 1.23 $"
- "\nby\n"
- "Klas Eriksson, [email protected]\n\n"
- "Help: Use arrows and space keys.\n"
- " Try to get 3 in-a-row.\n"
- " More than 3 gives bonus."}}]),
- B=gs:create(button, W, [{x,100},{y,250}, {label, {text, "Dismiss"}}]),
- receive
- {gs, B, click, _, _} -> ok
- end,
- gs:destroy(W).
-
-%%======================================================================
-%% 4. Lambdas
-%%======================================================================
-
-drop(X,Y,Score,Board) ->
- case is_fall_ok(Board, X, Y+1) of
- true -> drop(X,Y+1,add_score(Score, 1),Board);
- false -> {X,Y, Score}
- end.
-
-elems2del([], _Board,Elems2DelAcc) -> Elems2DelAcc;
-elems2del([{X,Y}|Checks],Board,Elems2DelAcc) ->
- NewElems2DelAcc = ordsets:union(erase_bits_at(Board,Elems2DelAcc,X,Y),
- Elems2DelAcc),
- elems2del(Checks,Board,NewElems2DelAcc).
-
-collect_bottom_bits(?WIDTH,_Board) -> [];
-collect_bottom_bits(X,Board) ->
- case color_at(Board, X, ?HEIGHT-1) of
- black -> collect_bottom_bits(X+1,Board);
- _AcolorHere -> [X|collect_bottom_bits(X+1,Board)]
- end.
-
-update_check(_Check,[]) -> [];
-update_check(Check,[X|Xs]) ->
- case lists:member({X, ?HEIGHT-1}, Check) of
- true -> update_check(Check,Xs);
- false -> [{X, ?HEIGHT-1}|update_check(Check,Xs)]
- end.
-
-org_objs([],_Board) -> [];
-org_objs([{X,Y}|XYs],Board) ->
- {GsObj, _Color} = board_element(Board, X, Y),
- [{GsObj, lists:sort(gs:read(GsObj, coords))}|org_objs(XYs,Board)].
-
-update_board([],Board) -> Board;
-update_board([{X,Y}|XYs], Board) ->
- update_board(XYs,update_screen_element(Board, X, Y, black)).
-
-put_back([]) -> done;
-put_back([{GsObj, Coords}|Objs]) ->
- gs:config(GsObj, [{coords, Coords}]),
- put_back(Objs).
-
-updated_cols([], UpdColsAcc) -> UpdColsAcc;
-updated_cols([{X,_Y}|XYs], UpdColsAcc) ->
- case lists:member(X,UpdColsAcc) of
- true -> updated_cols(XYs,UpdColsAcc);
- false -> updated_cols(XYs,[X|UpdColsAcc])
- end.
-
-%% This is not an application so we don't have their way of knowing
-%% a private data directory where the GIF files are located (this directory).
-%% We can find GS and makes it relative from there /kgb
-
--define(EbinFromGsPriv,"../contribs/ebin").
-
-dir()->
- GsPrivDir = code:priv_dir(gs),
- filename:join(GsPrivDir,?EbinFromGsPriv).
diff --git a/lib/gs/contribs/cols/cols.gif b/lib/gs/contribs/cols/cols.gif
deleted file mode 100644
index 96e7c1ed4a..0000000000
--- a/lib/gs/contribs/cols/cols.gif
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/cols/cols.tool b/lib/gs/contribs/cols/cols.tool
deleted file mode 100644
index 673c3d8efa..0000000000
--- a/lib/gs/contribs/cols/cols.tool
+++ /dev/null
@@ -1,5 +0,0 @@
-{version,"0.1"}.
-{{tool,"Cols"},
- {start,{cols,start,[]}},
- {icon,"cols.gif"},
- {message,"Cols - The Game"}}.
diff --git a/lib/gs/contribs/cols/help.gif b/lib/gs/contribs/cols/help.gif
deleted file mode 100644
index 59baef1fec..0000000000
--- a/lib/gs/contribs/cols/help.gif
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/cols/highscore.erl b/lib/gs/contribs/cols/highscore.erl
deleted file mode 100644
index 94f68a043a..0000000000
--- a/lib/gs/contribs/cols/highscore.erl
+++ /dev/null
@@ -1,103 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-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(highscore).
--compile([{nowarn_deprecated_function,{gs,button,2}},
- {nowarn_deprecated_function,{gs,create,3}},
- {nowarn_deprecated_function,{gs,destroy,1}},
- {nowarn_deprecated_function,{gs,grid,2}},
- {nowarn_deprecated_function,{gs,read,2}},
- {nowarn_deprecated_function,{gs,start,0}},
- {nowarn_deprecated_function,{gs,window,2}}]).
-
--export([run/2]).
-
-run(NScore, File) ->
- Scores = read_scores(File),
- case find_pos(NScore, 1, Scores) of
- false ->
- display(Scores);
- Pos ->
- NewScores = new_highscore(Scores, Pos, NScore),
- write_scores(NewScores,File),
- display(NewScores)
- end.
-
-
-new_highscore(Scores, Pos, NScore) ->
- Txt = io_lib:format("You entered position ~w", [Pos]),
- W = gs:create(window, gs:start(), [{width, 200},{height, 110},{map,true},
- {title, "New Highscore!!!"}]),
- gs:create(label, W, [{label, {text, Txt}}, {x, 0}, {y,0}, {align, center},
- {width, 190},{height, 30}]),
- Entry = gs:create(entry, W, [{x, 0}, {y, 40}, {height, 30}, {width, 200}]),
- Ok = gs:create(button, W, [{label, {text, "Ok"}}, {x, 40}, {y, 75}]),
- receive
- {gs, Ok, click, _,_} ->
- T = gs:read(Entry, text),
- gs:destroy(W),
- lists:sublist(lists:reverse(
- lists:keysort(1, [{NScore, T} | Scores])), 1, 10)
- end.
-
-
-
-read_scores(File) ->
- case file:read_file(File) of
- {ok, Bin} -> binary_to_term(Bin);
- {error, _Reason} ->
- mk_empty_high(10)
- end.
-
-mk_empty_high(0) -> [];
-mk_empty_high(N) -> [{N,"Erlang"}|mk_empty_high(N-1)].
-
-find_pos(_NScore, _N, []) -> false;
-find_pos(NScore, N, [{Score, _Name} | Scores]) when Score > NScore ->
- find_pos(NScore, N+1, Scores);
-find_pos(_NScore, N, _) -> N.
-
-write_scores(Scores,File) ->
- file:write_file(File, term_to_binary(Scores)).
-
-display(Scores) ->
- Win = gs:window(gs:start(), [{width, 300},{height, 250},{map,true},
- {title, "Highscores"}]),
- {W,H} = gs:read(Win,{font_wh,{{screen,12},"aaaaaaa"}}),
- G = gs:grid(Win,[{rows,{1,11}},{columnwidths,[W,4*W]},{hscroll,false},
- {width, 300},{height, 220},{vscroll,false},
- {cellheight,H+2},{font,{screen,12}}]),
- insert_scores(G,2,Scores),
- Ok = gs:button(Win, [{label, {text, "OK"}}, {x, 100}, {y, 220}]),
- receive
- {gs, Ok, click, _,_} -> gs:destroy(Win),
- ok
- end.
-
-insert_scores(Grid,_N,[]) ->
- gs:create(gridline,Grid,[{row,1},{font,{screen,bold,12}},
- {text,{1,"SCORE"}},{text,{2,"NAME"}}]);
-
-insert_scores(Grid,Row,[{Score,Name}|Ss]) ->
- gs:create(gridline,Grid,[{row,Row},{text,{1,io_lib:format("~w",[Score])}},
- {text,{2,Name}}]),
- insert_scores(Grid,Row+1,Ss).
-
diff --git a/lib/gs/contribs/mandel/Makefile b/lib/gs/contribs/mandel/Makefile
deleted file mode 100644
index b806cc7801..0000000000
--- a/lib/gs/contribs/mandel/Makefile
+++ /dev/null
@@ -1,101 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-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%
-#
-
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(GS_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/gs-$(VSN)/contribs
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES= \
- mandel
-
-HRL_FILES=
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=../ebin/%.$(EMULATOR)) $(TARGET_TOOLBOX_FILES)
-
-TOOLNAME = mandel
-
-EXTRA_FILES= $(TOOLNAME).html
-TOOLBOX_FILES= $(TOOLNAME).tool $(TOOLNAME).gif
-TARGET_TOOLBOX_FILES= $(TOOLBOX_FILES:%=$(EBIN)/%)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_COMPILE_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(TARGET_FILES)
-
-docs:
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f core
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-$(EBIN)/$(TOOLNAME).gif: $(TOOLNAME).gif
- $(gen_verbose)rm -f $@
- $(V_at)cp $(TOOLNAME).gif $@
-
-$(EBIN)/$(TOOLNAME).tool: $(TOOLNAME).tool
- $(gen_verbose)rm -f $@
- $(V_at)cp $(TOOLNAME).tool $@
-
-$(EBIN)/help.gif: help.gif
- $(gen_verbose)rm -f $@
- $(V_at)cp help.gif $@
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/mandel/bitmaps"
- $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) "$(RELSYSDIR)/mandel/bitmaps"
- $(INSTALL_DIR) "$(RELSYSDIR)/mandel"
- $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/mandel"
-
-release_docs_spec:
diff --git a/lib/gs/contribs/mandel/mandel.erl b/lib/gs/contribs/mandel/mandel.erl
deleted file mode 100644
index e6061ba77d..0000000000
--- a/lib/gs/contribs/mandel/mandel.erl
+++ /dev/null
@@ -1,351 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2013. 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(mandel).
--compile([{nowarn_deprecated_function,{gs,assq,2}},
- {nowarn_deprecated_function,{gs,config,2}},
- {nowarn_deprecated_function,{gs,create,4}},
- {nowarn_deprecated_function,{gs,image,2}},
- {nowarn_deprecated_function,{gs,start,0}}]).
--author('(mbj,eklas)@erlang.ericsson.se').
-
-%% User's interface
--export([start/0,start/1]).
-
-%% Internal exports:
--export([start_client/2,refresher/1,start_server/1,respond/2]).
-
-%%%-----------------------------------------------------------------
-%%% Distributed Mandelbrot program.
-%%% Originally written i C++/rpc/lwp/interviews by Klas Eriksson.(1200 lines)
-%%% Rewritten in Erlang by Klas Eriksson and Martin Björklund.
-%%%-----------------------------------------------------------------
-
-%% unix>erl -sname foo (all nodes will get the same name)
-%% (foo@data)1>mandel:start([{hosts,["computer1","computer2"]},{window,400}]).
-
-%% unix>erl
-%% 1> mandel:start().
-
--record(state,{image,width,height,xmax,ymax,range,
- maxiter,colortable,zoomstep}).
--record(job,{left,right,ymin,ymax,height,width,maxiter,data=[]}).
--define(JOBWIDTH,10).
-
-%%-----------------------------------------------------------------
-%% This is the client start function.
-%%-----------------------------------------------------------------
-start() ->
- start([]).
-
-%%----------------------------------------------------------------------
-%% Option is list of Option. Option is:
-%% {xmax,float()}|{ymax,float()}|{range,float()}|
-%% {maxiter,integer()}|{window,integer()}|{zoomstep,float()}|
-%% {hosts,(list of string())|all_found_nodes}
-%%----------------------------------------------------------------------
-start(Opts) ->
- Nodes1 = nodes(),
- Nodes = case get_option(hosts,Opts,all_found_nodes) of
- all_found_nodes when Nodes1 == [] ->
- N = [node()],
- spawn(mandel,start_server,[N]),
- N;
- all_found_nodes ->
- start_nodes(dir(),Nodes1),
- Nodes1;
- Hosts ->
- start_slaves(Hosts),
- start_nodes(dir(),Nodes1),
- Nodes1
- end,
- spawn(mandel,start_client,[Opts,Nodes]).
-
-%% This is not an application so we don't have their way of knowing
-%% a private data directory where the GIF files are located (this directory).
-%% We can find GS and makes it relative from there /kgb
-
--define(EbinFromGsPriv,"../contribs/ebin").
-
-dir()->
- GsPrivDir = code:priv_dir(gs),
- filename:join(GsPrivDir,?EbinFromGsPriv).
-
-
-start_slaves([]) -> ok;
-start_slaves([Host|Hs]) ->
- {ok,Name}=slave:start(Host),
- io:format("host ~p is up~n", [Name]),
- start_slaves(Hs).
-
-start_nodes(_Dir,[]) -> ok;
-start_nodes(Dir,[Node|Nodes]) ->
- rpc:call(Node,code,add_path,[Dir]), % hack? should be done in .erlang
- spawn_link(Node,mandel,start_server,[[node()]]),
- io:format("started mandelserver at node: ~p~n", [Node]),
- start_nodes(Dir,Nodes).
-
-start_client(Opts,Nodes) ->
- Wt = get_option(window,Opts,100) div ?JOBWIDTH * ?JOBWIDTH,
- Ht = get_option(window,Opts,100) div ?JOBWIDTH * ?JOBWIDTH,
- S=gs:start(),
- Win=gs:create(window,win1,S,[{title,"Mandel"},{width,Wt-1},{height,Ht-1},
- {configure,true}]),
- Canvas=gs:create(canvas,can1,Win,[{width,Wt},{height,Ht}]),
- Image=gs:image(Canvas,[{buttonpress,true}]),
- MaxIters = get_option(maxiter,Opts,100),
- timer:apply_after(8000,mandel,refresher,[Image]),
- CT = make_color_table(MaxIters),
- State2=#state{image=Image,width=Wt,height=Ht,
- xmax=try_random(get_option(xmax,Opts,2),-2,2),
- ymax=try_random(get_option(ymax,Opts,2),-2,2),
- range=try_random(get_option(range,Opts,4),0,4),
- maxiter=MaxIters,colortable=CT,
- zoomstep=get_option(zoomstep,Opts,1.7)},
- ToDo = make_jobs(State2),
- gs:config(Win,[{map,true}]),
- main(State2, [], Nodes, ToDo).
-
-try_random(random,Low,High) ->
- random:uniform()*(High-Low)+Low;
-try_random(Float,_Low,_High) when is_number(Float) -> Float.
-
-
-%%-----------------------------------------------------------------
-%% Distribute work to the nodes. When a node returns, that
-%% node is the first to be used if there's any job left.
-%%-----------------------------------------------------------------
-main(State, [], PassiveNodes, []) ->
- wait_event(State,[],PassiveNodes,[]);
-main(State, ActiveNodes, PassiveNodes, []) ->
- % No jobs left, but some nodes are still active.
- % Wait_Event for their results
- wait_event(State,ActiveNodes,PassiveNodes,[]);
-main(State, ActiveNodes, [Node|PassiveNodes], [Job|ToDo]) ->
- % We have work to do, and at least one passive node.
- % Let him do it.
- distribute_job(Node, Job),
- main(State, [Node|ActiveNodes], PassiveNodes, ToDo);
-main(State, ActiveNodes, [], ToDo) ->
- % We have work to do, but all nodes are active.
- _Node = wait_event(State,ActiveNodes,[],ToDo).
-
-wait_event(State,ActiveNodes,PassiveNodes,ToDo) ->
- receive
- {calculation_done, {Node, Job}} ->
- if % a small hack. we want to discard data for old pictures
- Job#job.ymax==State#state.ymax ->
- draw(State, Node, Job);
- true -> true
- end,
- main(State,lists:delete(Node,ActiveNodes),[Node|PassiveNodes],ToDo);
- {gs,_Img,buttonpress,_Data,[_Butt,X,Y|_]} ->
- #state{width=W,height=H,ymax=Ymax,xmax=Xmax,range=R,zoomstep=ZS} =
- State,
- RX = Xmax-R+(X/W)*R,
- RY = Ymax-R+(1-(Y/H))*R,
- R2 = R/ZS,
- Xmax2 = RX + R2/2,
- Ymax2 = RY + R2/2,
- State2 = State#state{xmax=Xmax2,ymax=Ymax2,range=R2},
- io:format("{xmax,~w},{ymax,~w},{range,~w}~n", [Xmax2,Ymax2,R2]),
- ToDo2=make_jobs(State2),
- main(State2,ActiveNodes,PassiveNodes,ToDo2);
- {gs,_Win,destroy,_,_} ->
- kill_nodes(lists:append(ActiveNodes,PassiveNodes));
- {gs,_Win,configure,_Data,[W,H|_]}
- when State#state.width==W+1, State#state.height==H+1->
- main(State,ActiveNodes,PassiveNodes,ToDo);
- {gs,_Win,configure,_Data,[W|_]} ->
- gs:config(can1,[{width,W},{height,W}]),
- gs:config(win1,{configure,false}),
- gs:config(win1,[{width,W-1},{height,W-1}]),
- gs:config(win1,{configure,true}),
- State2 = State#state{width=W,height=W},
- ToDo2=make_jobs(State2),
- main(State2,ActiveNodes,PassiveNodes,ToDo2)
- end.
-
-kill_nodes([]) ->
- done;
-kill_nodes([Node|Nodes]) ->
- exit(rpc:call(Node,erlang,whereis,[mandel_server]),kill),
- kill_nodes(Nodes).
-
-
-distribute_job(Node, Job) ->
- {mandel_server, Node} ! {mandel_job, {self(), Job}}.
-
-draw(#state{image=Image, width=Wt, height=Ht, xmax=Xmax,
- maxiter=MI,colortable=ColorTable,range=R}, Node, Job) ->
- #job{left=Left,data=Data}=Job,
- io:format("Got data from node ~30w~n", [Node]),
-%% PixelX = K * RealX + M
-%% 0 = K * Xmin + M
-%% Width-1= K * Xmax + M
- K=(1-Wt)/-R,
- M=Wt-1-K*Xmax,
- Xbegin = round(Left*K+M),
- draw_cols(Image, Xbegin, Ht, lists:reverse(Data),MI,ColorTable).
-
-draw_cols(Image, X, Ht, [H|T],MaxIter,ColorTable) ->
- draw_col(Image, X, 0, H,MaxIter,ColorTable),
- draw_cols(Image, X+1, Ht, T,MaxIter,ColorTable);
-draw_cols(_Image, _X, _, [],_MaxIter,_ColorTable) ->
- done.
-
-draw_col(_Image, _X,_Y,[{no_first_color,0}],_MaxIter,_ColorTable) ->
- done;
-draw_col(Image, X,Y,[{Color,1}|T],MaxIter,ColorTable) ->
- gs:config(Image,[{pix_val,{{X,Y},
- element(Color+1,ColorTable)}}]),
- draw_col(Image, X,Y+1,T,MaxIter,ColorTable);
-draw_col(Image, X,Y,[{Color,Height}|T],MaxIter,ColorTable) ->
- gs:config(Image,[{pix_val,{{{X,Y},{X+1,Y+Height}},
- element(Color+1,ColorTable)}}]),
- draw_col(Image, X,Y+Height,T,MaxIter,ColorTable).
-
-make_jobs(#state{width=W,height=H,range=R,
- xmax=Xmax,ymax=Ymax,maxiter=MI}) ->
- make_jobs(Xmax-R,Xmax,Ymax-R,Ymax,H,W,MI).
-
-make_jobs(Xmin,Xmax,Ymin,Ymax,Ht,Wt,MaxIter) ->
- NoJobs = Wt/?JOBWIDTH, % Each job is ?JOBWIDTH pixel-col
- DX = (Xmax - Xmin)/NoJobs,
- make_jobs(DX,Xmin,Xmax,#job{ymin=Ymin,ymax=Ymax,height=Ht,width=Wt/NoJobs,
- maxiter=MaxIter},[]).
-
-make_jobs(DX,Left,Xmax,JobSkel,Res) when Left =< Xmax ->
- Right = Left + DX,
- Job = JobSkel#job{left=Left,right=Right},
- make_jobs(DX,Right,Xmax,JobSkel,[Job | Res]);
-make_jobs(_DX,_Left,_Xmax,_JobSkel,Res) -> Res.
-
-%%----------------------------------------------------------------------
-%% A small process that refreshes the screen now and then.
-%%----------------------------------------------------------------------
-refresher(Image) ->
- gs:config(Image,flush),
- timer:apply_after(8000,mandel,refresher,[Image]).
-
-%%-----------------------------------------------------------------
-%% This is the server start function.
-%%-----------------------------------------------------------------
-start_server([ClientNode]) ->
- register(mandel_server, self()),
- erlang:monitor_node(ClientNode, true),
- server_loop().
-
-server_loop() ->
- receive
- {mandel_job, {Pid, Job}} ->
- spawn_link(mandel, respond, [Pid, Job]),
- server_loop()
- end.
-
-respond(Pid, Job) ->
- Data = do_job(Job),
- Pid ! {calculation_done, {node(), Data}}.
-
-do_job(Job) ->
- calculate_area(Job).
-
-calculate_area(Job) ->
- #job{ymin=Ymin,ymax=Ymax,height=Ht,width=Wt,left=Xmin,right=Xmax}=Job,
- Job#job{data=x_loop(0,[],Wt,(Xmax-Xmin)/Wt,(Ymax-Ymin)/Ht,Xmin,Job)}.
-
-x_loop(IX,Res,Wt,Dx,Dy,X,Job) when IX < Wt ->
- #job{ymin=Ymin,height=Ht,maxiter=MaxIter}=Job,
- Cols = y_loop(0,Ht,[],MaxIter,Dy,X,Ymin,no_first_color,0),
- x_loop(IX+1,[Cols|Res],Wt,Dx,Dy,X+Dx,Job);
-x_loop(_,Res,_,_,_,_,_) ->
- Res.
-
-y_loop(IY,Ht,Res,MaxIter,Dy,X,Y,PrevColor,NprevColor) when IY < Ht ->
- Color = color_loop(1,MaxIter,0,0,0,0,X,Y),
- if
- Color == PrevColor ->
- y_loop(IY+1,Ht,Res,MaxIter,Dy,X,Y+Dy,PrevColor,NprevColor+1);
- true ->
- y_loop(IY+1,Ht,[{PrevColor,NprevColor}|Res],MaxIter,
- Dy,X,Y+Dy,Color,1)
- end;
-
-y_loop(_,_,Res,_,_,_,_,PC,N) ->
- [{PC,N}|Res].
-
-color_loop(Color,MaxIter,Za,Zb,Za2,Zb2,X,Y)
- when Za2 + Zb2 < 4, Color < MaxIter->
- Ztmp = Za2 - Zb2 + X,
- ZbN = 2 * Za * Zb + Y,
- color_loop(Color+1,MaxIter,Ztmp,ZbN,Ztmp * Ztmp,ZbN * ZbN,X,Y);
-color_loop(MaxIter,MaxIter,_Za,_Zb,_Za2,_Zb2,_X,_Y) ->
- 0; % black
-color_loop(Color,_,_,_,_,_,_,_) ->
- Color.
-
-%%----------------------------------------------------------------------
-%% The "colormodel".
-%%----------------------------------------------------------------------
-make_color_table(MaxColors) ->
- list_to_tuple([{0,0,0}|colors(MaxColors)]).
-
-colors(Ncolors) ->
- {A,B,C}=erlang:now(),
- random:seed(A,B,C),
- Colors = random_colors(Ncolors),
- Colors2 = best_insert([hd(Colors)],tl(Colors)),
- Colors2.
-
-random_colors(0) -> [];
-random_colors(N) ->
- R = random:uniform(256)-1,
- G = random:uniform(256)-1,
- B = random:uniform(256)-1,
- [{R,G,B}|random_colors(N-1)].
-
-best_insert(Sorted,[RGB|Unsorted]) ->
- best_insert(insert_at(best_pos(RGB,Sorted),RGB,Sorted),Unsorted);
-best_insert(Sorted,[]) -> Sorted.
-
-insert_at(1,Elem,L) -> [Elem|L];
-insert_at(N,Elem,[H|T]) -> [H|insert_at(N-1,Elem,T)].
-
-best_pos(RGB, Sorted) ->
- D = distances(RGB,Sorted),
- pos_for_smallest_distance(D,1,1000,-1).
-
-pos_for_smallest_distance([],_CurPos,_SmallestDist,Pos) -> Pos;
-pos_for_smallest_distance([Dist|T],CurPos,SmallDist,_Pos)
- when Dist < SmallDist ->
- pos_for_smallest_distance(T,CurPos+1,Dist,CurPos);
-pos_for_smallest_distance([_|T],CurPos,Smallest,Pos) ->
- pos_for_smallest_distance(T,CurPos+1,Smallest,Pos).
-
-distances(_RGB,[]) ->
- [];
-distances({R,G,B},[{R2,G2,B2}|T]) ->
- [lists:max([abs(R-R2),abs(G-G2),abs(B-B2)])|distances({R,G,B},T)].
-
-get_option(Option, Options, Default) ->
- case gs:assq(Option, Options) of
- {value, Val} -> Val;
- false -> Default
- end.
diff --git a/lib/gs/contribs/mandel/mandel.gif b/lib/gs/contribs/mandel/mandel.gif
deleted file mode 100644
index 49ed1985cb..0000000000
--- a/lib/gs/contribs/mandel/mandel.gif
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/mandel/mandel.html b/lib/gs/contribs/mandel/mandel.html
deleted file mode 100644
index f69cfa3c6a..0000000000
--- a/lib/gs/contribs/mandel/mandel.html
+++ /dev/null
@@ -1,74 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
-<!--
- ``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.
-
- The Initial Developer of the Original Code is Ericsson Utvecklings AB.
- Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
- AB. All Rights Reserved.''
-
- $Id$
--->
-<HTML>
-<HEAD>
- <TITLE></TITLE>
- <META NAME="GENERATOR" CONTENT="Mozilla/3.01Gold (X11; I; SunOS 5.5.1 sun4m) [Netscape]">
-</HEAD>
-<BODY>
-
-<H1>Distributed Mandelbrot program</H1>
-
-<P>Originally written i C++/rpc/lwp/interviews by Klas Eriksson.(1200 lines)
-<BR>
-Rewritten in Erlang by Klas Eriksson and Martin Bj&ouml;rklund. </P>
-
-<P><A HREF="http://www.bush.edu/~nick/nick.html">What is the Mandelbrot
-function?</A> </P>
-
-<H2>A small manual</H2>
-
-<UL>
-<LI>Try starting erlang in distributed mode. The mandel program will use<BR>
-all connected nodes for mandel calculations!</LI>
-
-<LI>Resizing the window will restart the calculation.</LI>
-
-<LI>Press left mouse button to zoom.</LI>
-</UL>
-
-<P><TT>mandel:start(list of Option)</TT> can be used to give the program
-different options.</P>
-
-<P><BR>
-Available options are:</P>
-
-<UL>
-<LI>{xmax,float()}</LI>
-
-<LI>{ymax,float()}</LI>
-
-<LI>{range,float()}|</LI>
-
-<LI>{maxiter,integer()}</LI>
-
-<LI>{window,integer()}</LI>
-
-<LI>{zoomstep,float()}</LI>
-
-<LI>{hosts,(list of string())|all_found_nodes}</LI>
-</UL>
-
-<P><BR>
-</P>
-
-</BODY>
-</HTML>
diff --git a/lib/gs/contribs/mandel/mandel.tool b/lib/gs/contribs/mandel/mandel.tool
deleted file mode 100644
index b59941268e..0000000000
--- a/lib/gs/contribs/mandel/mandel.tool
+++ /dev/null
@@ -1,6 +0,0 @@
-{version,"0.1"}.
-{{tool,"Mandel"},
- {start,{mandel,start,[]}},
- {icon,"mandel.gif"},
- {message,"Mandelbrot"},
- {html,"../mandel/mandel.html"}}.
diff --git a/lib/gs/contribs/othello/Makefile b/lib/gs/contribs/othello/Makefile
deleted file mode 100644
index 8a66e17ec5..0000000000
--- a/lib/gs/contribs/othello/Makefile
+++ /dev/null
@@ -1,101 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-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%
-#
-
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(GS_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/gs-$(VSN)/contribs
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES= \
- othello \
- othello_adt \
- othello_board
-
-HRL_FILES=
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=../ebin/%.$(EMULATOR)) $(TARGET_TOOLBOX_FILES)
-
-TOOLNAME = othello
-
-EXTRA_FILES=
-TOOLBOX_FILES= $(TOOLNAME).tool $(TOOLNAME).gif
-TARGET_TOOLBOX_FILES= $(TOOLBOX_FILES:%=$(EBIN)/%)
-BITMAPS= priv/marker.bm priv/square.bm
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_COMPILE_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(TARGET_FILES)
-
-docs:
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f core
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-$(EBIN)/$(TOOLNAME).gif: $(TOOLNAME).gif
- $(gen_verbose)rm -f $@
- $(V_at)cp $(TOOLNAME).gif $@
-
-$(EBIN)/$(TOOLNAME).tool: $(TOOLNAME).tool
- $(gen_verbose)rm -f $@
- $(V_at)cp $(TOOLNAME).tool $@
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/othello"
- $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/othello"
- $(INSTALL_DIR) "$(RELSYSDIR)/othello/priv"
- $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) "$(RELSYSDIR)/othello/priv"
-
-release_docs_spec:
-
diff --git a/lib/gs/contribs/othello/othello.erl b/lib/gs/contribs/othello/othello.erl
deleted file mode 100644
index c6ad0a76ec..0000000000
--- a/lib/gs/contribs/othello/othello.erl
+++ /dev/null
@@ -1,237 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. 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(othello).
--export([start/0,new_game/4,start1/5]).
-
-
-
-%%----------------------------------------------------------------------
-%% The Othello program now uses the gs graphical package instead of the
-%% pxw package. See module othello_board for details
-%%
-%%----------------------------------------------------------------------
-
-
-start() -> othello_board:start().
-
-new_game(Computer,Player,Depth,Init) ->
- spawn_link(othello,start1,[self(),Computer,Player,Depth,Init]).
-
-start1(Win,Computer,Player,Depth,Init) ->
- Board = othello_adt:new(t),
- random:seed(),
- init_display(Board,Win,Init),
- play(Computer,Player,Board,Depth,Win,1).
-
-play(Computer,Player,Board,Depth,Win,NoDs) ->
- tell_win(Win,Computer,Player),
- case catch continue(Player,Board) of
- {game_over,Result} ->
- game_over(Board,Player,Result,Win);
- {omit_draw,Player} ->
- omit(Player,Win),
- play(Computer,swap(Player),Board,Depth,Win,NoDs);
- ok ->
- Draw = choose_draw(Computer,Player,Board,Depth,Win,NoDs),
- Win ! {self(),draw,Draw},
- Board1 = othello_adt:set(Draw,Player,Board),
- display(Board1,Board,Win),
- play(Computer,swap(Player),Board1,Depth,Win,NoDs+1)
- end.
-
-continue(Player,Board) ->
- Draws = game_over(Player,Board),
- not_allowed(Draws,Player),
- ok.
-
-choose_draw(Computer,Computer,Board,Depth,_Win,NoDs) -> % Depth > 0 !!
- {Draw,_Value} = alpha_beta(Depth,Board,-11000,11000,Computer,NoDs),
-% io:format('Choosen draw is {~w,~w} : (~w)~n',
-% [othello_adt:col(Draw),othello_adt:row(Draw),Value]),
-% io:format('=====================~n',[]),
- Draw;
-choose_draw(Computer,Player,Board,Depth,Win,NoDs) ->
- receive
- {Win,position,Draw} ->
- flush(Win),
- case othello_adt:is_draw(Draw,Player,Board) of
- false ->
- Win ! {self(),illegal_draw,Draw},
- choose_draw(Computer,Player,Board,Depth,Win,NoDs);
- true ->
- Draw
- end
- end.
-
-flush(Win) ->
- receive
- {Win,position,_} ->
- flush(Win)
- after 1 ->
- true
- end.
-
-tell_win(Win,Computer,Player) ->
- Win ! {self(),player,Computer,Player},
- receive
- {Win,go_on_play} -> true
- end.
-
-alpha_beta(0,Board,_,_,Player,_) ->
- {-1,othello_adt:evaluate_board(Player,Board)};
-alpha_beta(Depth,Board,Alpha,Beta,Player,NoDs) ->
- case compute(Player,Board,NoDs) of
- [] ->
- Player1 = swap(Player),
- case compute(Player1,Board,NoDs) of
- [] ->
- dead_lock(Board,Player);
- PosDraws1 ->
- choose(PosDraws1,Board,Depth-1,-Beta,-Alpha,-1,
- Player1,NoDs)
- end;
- PosDraws ->
- choose(PosDraws,Board,Depth-1,-Beta,-Alpha,-1,Player,NoDs)
-% A = choose(PosDraws,Board,Depth-1,-Beta,-Alpha,-1,Player,NoDs),
-% io:format('Alpha-Beta (~w) ==> ~w~n',[Depth,A]),
-% A
- end.
-
-choose([Draw|Draws],Board,Depth,Alpha,Beta,Record,Player,NoDs) ->
- Player1 = swap(Player),
- Board1 = othello_adt:set(Draw,Player,Board),
-% io:format('Alpha <~w> Beta <~w> ~n',[Alpha,Beta]),
- {_,Value} = alpha_beta(Depth,Board1,Alpha,Beta,Player1,NoDs+1),
- Value1 = -Value,
- cutoff(Draw,Value1,Depth,Alpha,Beta,Draws,Board,Record,Player,NoDs);
-choose([],_,_,Alpha,_,Draw,_,_) ->
- {Draw,Alpha}.
-
-cutoff(Draw,Value,_,_,Beta,_,_,_,_,_) when Value >= Beta ->
- {Draw,Value};
-cutoff(Draw,Value,Depth,Alpha,Beta,Draws,Board,_,Player,NoDs)
- when Alpha < Value, Value < Beta ->
- choose(Draws,Board,Depth,Value,Beta,Draw,Player,NoDs);
-cutoff(Draw,Value,Depth,Alpha,Beta,Draws,Board,Record,Player,NoDs)
- when Value == Alpha, NoDs < 13 ->
- choose(Draws,Board,Depth,Alpha,Beta,random_choice(Draw,Record),
- Player,NoDs);
-cutoff(_Draw,Value,Depth,Alpha,Beta,Draws,Board,Record,Player,NoDs)
- when Value =< Alpha ->
- choose(Draws,Board,Depth,Alpha,Beta,Record,Player,NoDs).
-
-compute(Player,Board,NoOfDraws) when NoOfDraws < 13 ->
- case othello_adt:possible_draws(Player,Board,begin_play) of
- [] ->
- othello_adt:possible_draws(Player,Board,playing);
- Draws ->
- Draws
- end;
-compute(Player,Board,_) ->
- othello_adt:possible_draws(Player,Board,playing).
-
-%%----------------------------------------------------------
-%% Randomly choose between two draws with the same value.
-%%----------------------------------------------------------
-
-random_choice(Draw,Draw1) ->
- case random:uniform(2) of
- 1 ->
- Draw;
- 2 ->
- Draw1
- end.
-
-dead_lock(Board,Player) ->
- case win_or_loose(Board,Player) of
- 0 -> {-1,0};
- Value when Value > 0 -> {-1,10000};
- _ -> {-1,-10000}
- end.
-
-win_or_loose(Board,Player) ->
- Player1 = swap(Player),
- othello_adt:pieces(Player,Board) - othello_adt:pieces(Player1,Board).
-
-game_over(Player,Board) ->
- case othello_adt:possible_draws(Player,Board,playing) of
- [] ->
- Player1 = swap(Player),
- case othello_adt:possible_draws(Player1,Board,playing) of
- [] ->
- throw({game_over,{{Player,othello_adt:pieces(Player,Board)},
- {Player1,othello_adt:pieces(Player1,Board)}}});
- _ ->
- [] % Player`s Draws !!
- end;
- Draws ->
- Draws
- end.
-
-game_over(_Board,_Player,Result,Win) ->
- Win ! {self(),game_over,white_res(Result),black_res(Result)}.
-
-white_res({{white,Res},_}) -> Res;
-white_res({_,{white,Res}}) -> Res.
-
-black_res({{black,Res},_}) -> Res;
-black_res({_,{black,Res}}) -> Res.
-
-not_allowed([],Player) ->
- throw({omit_draw, Player});
-not_allowed(_,_Player) ->
- ok.
-
-omit(Player,Win) ->
- Win ! {self(),omit_draw,Player},
- receive
- {Win,continue} ->
- ok
- end.
-
-init_display(_Board,_Win,first_time) ->
- true;
-init_display(Board,Win,_) ->
- display(Board,Win).
-
-display(Board,Win) ->
- All = othello_adt:all_pos(Board),
- display1(All,Win),
- Win ! {self(),score,othello_adt:pieces(white,Board),
- othello_adt:pieces(black,Board)}.
-
-display(Board,OldB,Win) ->
- Diff = othello_adt:diff(Board,OldB),
- display1(Diff,Win),
- Win ! {self(),score,othello_adt:pieces(white,Board),
- othello_adt:pieces(black,Board)}.
-
-display1([{Pos,Colour}|Diff],Win) ->
- Win ! {self(),new_mark,Pos,Colour},
- display1(Diff,Win);
-display1(_,_) ->
- true.
-
-swap(white) -> black;
-swap(black) -> white.
-
-
diff --git a/lib/gs/contribs/othello/othello.gif b/lib/gs/contribs/othello/othello.gif
deleted file mode 100644
index 5970c50209..0000000000
--- a/lib/gs/contribs/othello/othello.gif
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/othello/othello.tool b/lib/gs/contribs/othello/othello.tool
deleted file mode 100644
index 47550a581d..0000000000
--- a/lib/gs/contribs/othello/othello.tool
+++ /dev/null
@@ -1,6 +0,0 @@
-{version,"0.1"}.
-{{tool,"Othello"},
- {start,{othello,start,[]}},
- {icon,"othello.gif"},
- {message,"Othello - The Game"},
- {html,"http://www.armory.com/~iioa/othguide.html"}}.
diff --git a/lib/gs/contribs/othello/othello_adt.erl b/lib/gs/contribs/othello/othello_adt.erl
deleted file mode 100644
index e69c1c4d72..0000000000
--- a/lib/gs/contribs/othello/othello_adt.erl
+++ /dev/null
@@ -1,540 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2010. 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(othello_adt).
--compile(export_all).
-%%-------------------------------------------------------
-%% Use three main states for the strategy:
-%%
-%% BeginPlay: Stay in the inner square as long as possible.
-%% Use the possible_draws/3.
-%%
-%% MiddlePlay: Try to choose stable markers (?)
-%% Use stable/3
-%%
-%% EndPlay: Try to flip as many markers as possible
-%%
-%% The transition from Begin to Middle is obvious. From Middle
-%% to End however, is can be discussed.
-%%-------------------------------------------------------
-
-test(N,B) ->
- X=new(B),
- statistics(wall_clock),
- test0(N,X),
- {_,T} = statistics(wall_clock),
- {time_was,T/N}.
-
-
-test0(0,_) -> true;
-test0(N,X) ->
- possible_draws(black,X,begin_play),
- test0(N-1,X).
-
-%%-------------------------------------------------------
-%% new/1 - returns a new board
-%%
-%% Uses a tuple for storing the board
-%%-------------------------------------------------------
-
-new(B) ->
- Board = mk_board(B),
- {ordsets:from_list([18,19,20,21,26,29,34,37,42,43,44,45]),Board}.
-
-mk_board(t) ->
- Tup = list_to_tuple(gen_list(64,grey)),
- Tup1 = setelement(28+1, Tup, white),
- Tup2 = setelement(35+1, Tup1, white),
- Tup3 = setelement(27+1, Tup2, black),
- gen_score_board(),
- setelement(36+1, Tup3, black).
-
-gen_list(0,_) -> [];
-gen_list(I,Def) -> [Def|gen_list(I-1,Def)].
-
-gen_score_board() -> put(score,list_to_tuple(gen_list(64,0))).
-
-%%-------------------------------------------------------
-%% pos(Col,Row) - returns a position describing column
-%% and row.
-%% Col and Row have the range 1 - 8.
-%%-------------------------------------------------------
-
-pos(Col,Row) -> ((Row - 1) bsl 3) + (Col - 1).
-
-%%-------------------------------------------------------
-%% col(Pos) - returns the column of the Pos position
-%%-------------------------------------------------------
-
-col(Pos) -> (Pos band 7) + 1.
-
-%%-------------------------------------------------------
-%% row(Pos) - returns the row of the Pos position
-%%-------------------------------------------------------
-
-row(Pos) -> (Pos bsr 3) + 1.
-
-%%-------------------------------------------------------
-%% is_draw(Pos,Colour,Board) - returns true if Pos is a
-%% correct draw.
-%%-------------------------------------------------------
-
-is_draw(Pos,Colour,{Bset,Board}) ->
- case ordsets:is_element(Pos,Bset) of
- true ->
- case catch is_good(Colour,Pos,Board) of
- true ->
- true;
- _ ->
- false
- end;
- _ ->
- false
- end.
-
-%%-------------------------------------------------------
-%% set(Pos,Colour,Board) - returns an updated board
-%%-------------------------------------------------------
-
-set(Pos,Colour,{Bset,Board}) ->
- case ordsets:is_element(Pos,Bset) of
- true ->
- NewBoard = setelement(Pos+1,Board,Colour),
- Empty = empty_neighbour(Pos,NewBoard),
- NewBset = ordsets:union(Empty,ordsets:del_element(Pos,Bset)),
- turn(Colour,Pos,{NewBset,NewBoard});
- _ ->
- {error,invalid_position}
- end.
-
-empty_neighbour(Pos,Board) ->
- ordsets:from_list(empty_neighbour(Pos,Board,deltas())).
-
-empty_neighbour(_,_,[]) -> [];
-empty_neighbour(Pos,Board,[H|T]) ->
- case is_empty(Pos+H,dir(Pos,H),Board) of
- true -> [Pos+H|empty_neighbour(Pos,Board,T)];
- _ -> empty_neighbour(Pos,Board,T)
- end.
-
-is_empty(_,false,_) -> false;
-is_empty(X,_,_Board) when X<0 -> false;
-is_empty(X,_,_Board) when X>63 -> false;
-is_empty(X,_,Board) ->
- case element(X+1,Board) of
- grey -> true; % Empty
- _ -> false
- end.
-
-%%-------------------------------------------------------
-%% get(Pos,Board) - returns the contents in Pos
-%%-------------------------------------------------------
-
-get(Pos,{_Bset,Board}) -> element(Pos+1,Board).
-
-%%-------------------------------------------------------
-%% pieces(Colour,Board) - returns the number of Colour
-%% pieces.
-%%-------------------------------------------------------
-
-pieces(Colour,{_Bset,Board}) ->
- pieces(Colour,Board,0,0).
-
-pieces(Colour,Board,Pos,Count) when Pos < 64 ->
- case element(Pos+1,Board) of
- Colour ->
- pieces(Colour,Board,Pos+1,Count+1);
- _ ->
- pieces(Colour,Board,Pos+1,Count)
- end;
-pieces(_,_,_,Count) ->
- Count.
-
-%%-------------------------------------------------------
-%% possible_draws(Colour, Board, State)
-%%
-%% Returns a list of possible draws regarding the current
-%% strategy state.
-%%-------------------------------------------------------
-
-possible_draws(Colour,{Bset,Board},begin_play) ->
- Dset = ordsets:intersection(Bset,inner_square()),
- possible_draws_0(Colour,Dset,Board);
-possible_draws(Colour,{Bset,Board},_) ->
- possible_draws_0(Colour,Bset,Board).
-
-possible_draws(Colour,{Bset,Board}) ->
- possible_draws_0(Colour,Bset,Board).
-
-possible_draws_0(_,[],_) -> [];
-possible_draws_0(Colour,[H|T],Board) ->
- case catch is_good(Colour,H,Board) of
- true -> [H|possible_draws_0(Colour,T,Board)];
- false -> possible_draws_0(Colour,T,Board)
- end.
-
-
-%%-------------------------------------------------------
-%% evaluate_board(Colour,Board) - returns the value of
-%% the board from Colours
-%% point of view.
-%%-------------------------------------------------------
-
-evaluate_board(Colour,{_Bset,Board}) ->
- Score = get(score), % Initialized (zeroed) score board !!
- Colour1 = swap(Colour),
- Score1 = eval_board(Colour,Colour1,Score,Board,0),
- Score2 = cnt_corner(0,Score1,Board,Colour,Colour1),
- Score3 = cnt_corner(7,Score2,Board,Colour,Colour1),
- Score4 = cnt_corner(56,Score3,Board,Colour,Colour1),
- Score5 = cnt_corner(63,Score4,Board,Colour,Colour1),
- count(Score5,0).
-% A = count(Score5,0),
-% io:format('Score = ~w~n',[A]),
-% A.
-
-eval_board(MyCol,OtCol,Score,Board,Pos) when Pos < 64 ->
- case element(Pos+1,Board) of
- MyCol ->
- Score1 = setelement(Pos+1,Score,score(Pos)),
- eval_board(MyCol,OtCol,Score1,Board,Pos+1);
- OtCol ->
- Score1 = setelement(Pos+1,Score,-score(Pos)),
- eval_board(MyCol,OtCol,Score1,Board,Pos+1);
- _ ->
- eval_board(MyCol,OtCol,Score,Board,Pos+1)
- end;
-eval_board(_,_,Score,_,_) ->
- Score.
-
-cnt_corner(Corner,Score,Board,MyCol,OtCol) ->
- case element(Corner+1,Board) of
- MyCol ->
- cnt_corn(Corner,setelement(Corner+1,Score,50),
- Board,50,MyCol);
- OtCol ->
- cnt_corn(Corner,setelement(Corner+1,Score,-50),
- Board,-50,OtCol);
- _ ->
- Score
- end.
-
-cnt_corn(0,Score,Board,Value,Colour) ->
- Score1 = cnt_corn(0,1,8,Score,Board,Value,Colour),
- cnt_corn(0,8,1,Score1,Board,Value,Colour);
-cnt_corn(7,Score,Board,Value,Colour) ->
- Score1 = cnt_corn(7,-1,8,Score,Board,Value,Colour),
- cnt_corn(7,8,-1,Score1,Board,Value,Colour);
-cnt_corn(56,Score,Board,Value,Colour) ->
- Score1 = cnt_corn(56,1,-8,Score,Board,Value,Colour),
- cnt_corn(56,-8,1,Score1,Board,Value,Colour);
-cnt_corn(63,Score,Board,Value,Colour) ->
- Score1 = cnt_corn(63,-1,-8,Score,Board,Value,Colour),
- cnt_corn(63,-8,-1,Score1,Board,Value,Colour).
-
-cnt_corn(Pos,Dir,LineDir,Score,Board,Value,Colour) ->
- case dir(Pos,Dir) of
- Dir ->
- NextEdge = Pos+Dir,
- case element(NextEdge+1,Board) of
- Colour ->
- Score1 = setelement(NextEdge+1,Score,Value),
- Score2 = cnt_line(NextEdge,LineDir,Score1,Board,
- Colour,Value),
- cnt_corn(NextEdge,Dir,LineDir,Score2,Board,Value,Colour);
- _ ->
- Score
- end;
- _ ->
- Score
- end.
-
-cnt_line(Pos,Dir,Score,Board,Colour,Value) ->
- case dir(Pos,Dir) of
- Dir ->
- OnLinePos = Pos+Dir,
- case element(OnLinePos+1,Board) of
- Colour ->
- Score1 = setelement(OnLinePos+1,Score,Value),
- cnt_line(OnLinePos,Dir,Score1,Board,Colour,Value);
- _ ->
- Score
- end;
- _ ->
- Score
- end.
-
-count(Score,Pos) when Pos < 64 ->
- element(Pos+1,Score) + count(Score,Pos+1);
-count(_,_) ->
- 0.
-
-swap(white) -> black;
-swap(black) -> white.
-
-%%-------------------------------------------------------
-%% stable(Colour,Pos,Board) - returns a value 0-8
-%%
-%% A high value is regarded as more stable than a lower one.
-%% The stability means how many "friendly" neighbours there
-%% are, i.e markers of the same colour. Neighbours positions
-%% outside the board are regarded as friendly.
-%%-------------------------------------------------------
-
-stable(Colour,Pos,{_,Board}) ->
- stable(deltas(),Colour,Pos,Board).
-
-stable([],_,_,_) -> 0;
-stable([H|T],Colour,Pos,Board) ->
- stable_val(Colour,Pos,H,Board) + stable(T,Colour,Pos,Board).
-
-stable_val(_,H,D,_) when H+D<0 -> 1;
-stable_val(_,H,D,_) when H+D>63 -> 1;
-stable_val(black,H,D,Board) ->
- case element((H+D)+1,Board) of
- black -> 1;
- _ -> 0
- end;
-stable_val(white,H,D,Board) ->
- case element((H+D)+1,Board) of
- white -> 1;
- _ -> 0
- end.
-
-%%-------------------------------------------------------
-%% diff(Board,OldBoard) - return a list of the positions
-%% with changed pieces.
-%% [{Pos1,Colour1},...]
-%%-------------------------------------------------------
-
-diff(Board,OldBoard) -> diff(0,Board,OldBoard).
-
-diff(Pos,Board,OldBoard) when Pos < 64 ->
- OldP = get(Pos,OldBoard),
- case get(Pos,Board) of
- OldP ->
- diff(Pos+1,Board,OldBoard);
- NewP ->
- [{Pos,NewP}|diff(Pos+1,Board,OldBoard)]
- end;
-diff(_,_,_) ->
- [].
-
-%%-------------------------------------------------------
-%% all_pos(Board) - return a list of the positions colour.
-%% [{Pos1,Colour1},...]
-%%-------------------------------------------------------
-
-all_pos(Board) -> all_pos(0,Board).
-
-all_pos(Pos,Board) when Pos < 64 ->
- [{Pos,get(Pos,Board)}|all_pos(Pos+1,Board)];
-all_pos(_,_) ->
- [].
-
-%%-------------------------------------------------------
-%% Internal stuff
-%%-------------------------------------------------------
-
-deltas() -> [9,8,7,1,-1,-7,-8,-9].
-
-inner_square() ->
- [18,19,20,21,26,27,28,29,34,35,36,37,42,43,44,45]. % Is already an ordset
- % Save list traversing.
-% ordsets:list_to_set([18,19,20,21,26,27,28,29,34,35,36,37,42,43,44,45]).
-
-inv(black) -> white;
-inv(white) -> black.
-
-is_good(Colour,H,Board) ->
- is_good_0(Colour,H,dir(H,-9),Board),
- is_good_0(Colour,H,dir(H,-8),Board),
- is_good_0(Colour,H,dir(H,-7),Board),
- is_good_0(Colour,H,dir(H,-1),Board),
- is_good_0(Colour,H,dir(H,1),Board),
- is_good_0(Colour,H,dir(H,7),Board),
- is_good_0(Colour,H,dir(H,8),Board),
- is_good_0(Colour,H,dir(H,9),Board),
- false.
-
-is_good_0(_,_,false,_) -> false;
-is_good_0(_,H,D,_) when is_integer(H), is_integer(D), H+D<0 -> false;
-is_good_0(_,H,D,_) when is_integer(H), is_integer(D), H+D>63 -> false;
-is_good_0(black,H,D,Board) when is_integer(H), is_integer(D) ->
- case element((H+D)+1,Board) of
- white -> is_good_1(black,H+D,dir(H+D,D),Board);
- _ -> false
- end;
-is_good_0(white,H,D,Board) when is_integer(H), is_integer(D) ->
- case element((H+D)+1,Board) of
- black -> is_good_1(white,H+D,dir(H+D,D),Board);
- _ -> false
- end.
-
-is_good_1(_,_,false,_) -> false;
-is_good_1(_,H,D,_) when is_integer(H), is_integer(D), H+D<0 -> false;
-is_good_1(_,H,D,_) when is_integer(H), is_integer(D), H+D>63 -> false;
-is_good_1(black,H,D,Board) when is_integer(H), is_integer(D) ->
- case element((H+D)+1,Board) of
- white -> is_good_1(black,H+D,dir(H+D,D),Board);
- black -> throw(true);
- _ -> false
- end;
-is_good_1(white,H,D,Board) when is_integer(H), is_integer(D) ->
- case element((H+D)+1,Board) of
- black -> is_good_1(white,H+D,dir(H+D,D),Board);
- white -> throw(true);
- _ -> false
- end.
-
-%%-------------------------------------------------------
-%% turn(Colour,Draw,Board) - returns an updated board
-%% turn all possible pieces
-%% on the board
-%% Neighbours are not changed !!
-%%-------------------------------------------------------
-
-turn(Colour,Draw,{Bset,Board}) ->
- {Bset,turn(Colour,Draw,-9,
- turn(Colour,Draw,-8,
- turn(Colour,Draw,-7,
- turn(Colour,Draw,-1,
- turn(Colour,Draw,1,
- turn(Colour,Draw,7,
- turn(Colour,Draw,8,
- turn(Colour,Draw,9,Board))))))))}.
-
-turn(Colour,H,D,Board) ->
- case catch is_good_0(Colour,H,dir(H,D),Board) of
- true ->
- turn_0(Colour,H,D,Board);
- false ->
- Board
- end.
-
-turn_0(_,H,D,B) when is_integer(H), is_integer(D), H+D<0 -> B;
-turn_0(_,H,D,B) when is_integer(H), is_integer(D), H+D>63 -> B;
-turn_0(black,H,D,Board) when is_integer(H), is_integer(D) ->
- E = H+D,
- case element(E+1,Board) of
- white -> turn_0(black,H+D,D,swap(black,E,Board));
- _ -> Board
- end;
-turn_0(white,H,D,Board) when is_integer(H), is_integer(D) ->
- E = H+D,
- case element(E+1,Board) of
- black -> turn_0(white,H+D,D,swap(white,E,Board));
- _ -> Board
- end.
-
-%%-------------------------------------------------------
-%% swap(Colour,Pos,Board) - returns an updated board
-%% turn a piece on the board
-%% Neighbours are not changed !!
-%%-------------------------------------------------------
-
-swap(Colour,Pos,Board) when is_integer(Pos) ->
- setelement(Pos+1,Board,Colour).
-
-score(Pos) -> score1({col(Pos),row(Pos)}).
-
-score1({Column,1}) when Column >= 3, Column =< 6 -> 20;
-score1({Column,8}) when Column >= 3, Column =< 6 -> 20;
-score1({1,Line}) when Line >= 3, Line =< 6 -> 20;
-score1({8,Line}) when Line >= 3, Line =< 6 -> 20;
-score1({Column,2}) when Column >= 3, Column =< 6 -> -7;
-score1({Column,7}) when Column >= 3, Column =< 6 -> -7;
-score1({2,Line}) when Line >= 3, Line =< 6 -> -7;
-score1({7,Line}) when Line >= 3, Line =< 6 -> -7;
-score1({Column,Line}) when Column >= 3, Column =< 6,
- Line >= 3, Line =< 6 -> 1;
-score1({1,1}) -> 100;
-score1({1,8}) -> 100;
-score1({8,1}) -> 100;
-score1({8,8}) -> 100;
-score1({2,1}) -> -30;
-score1({7,1}) -> -30;
-score1({1,2}) -> -30;
-score1({8,2}) -> -30;
-score1({1,7}) -> -30;
-score1({8,7}) -> -30;
-score1({2,8}) -> -30;
-score1({7,8}) -> -30;
-score1({2,2}) -> -50;
-score1({7,2}) -> -50;
-score1({2,7}) -> -50;
-score1({7,7}) -> -50.
-
-%%-------------------------------------------------------
-%% dir(Pos,Dir) - return Dir if allowed direction at Pos.
-%% else return false.
-%%-------------------------------------------------------
-
-dir(0,1) -> 1; % {1,1}
-dir(0,8) -> 8;
-dir(0,9) -> 9;
-dir(0,_) -> false;
-
-dir(7,-1) -> -1; % {8,1}
-dir(7,7) -> 7;
-dir(7,8) -> 8;
-dir(7,_) -> false;
-
-dir(56,-8) -> -8; % {1,8}
-dir(56,-7) -> -7;
-dir(56,1) -> 1;
-dir(56,_) -> false;
-
-dir(63,-9) -> -9; % {8,8}
-dir(63,-8) -> -8;
-dir(63,-1) -> -1;
-dir(63,_) -> false;
-
-dir(Pos,-1) when (Pos bsr 3) == 0 -> -1; % {_,1}
-dir(Pos,1) when (Pos bsr 3) == 0 -> 1;
-dir(Pos,7) when (Pos bsr 3) == 0 -> 7;
-dir(Pos,8) when (Pos bsr 3) == 0 -> 8;
-dir(Pos,9) when (Pos bsr 3) == 0 -> 9;
-dir(Pos,_) when (Pos bsr 3) == 0 -> false;
-
-dir(Pos,-9) when (Pos bsr 3) == 7 -> -9; % {_,8}
-dir(Pos,-8) when (Pos bsr 3) == 7 -> -8;
-dir(Pos,-7) when (Pos bsr 3) == 7 -> -7;
-dir(Pos,-1) when (Pos bsr 3) == 7 -> -1;
-dir(Pos,1) when (Pos bsr 3) == 7 -> 1;
-dir(Pos,_) when (Pos bsr 3) == 7 -> false;
-
-dir(Pos,-8) when (Pos band 7) == 0 -> -8; % {1,_}
-dir(Pos,-7) when (Pos band 7) == 0 -> -7;
-dir(Pos,1) when (Pos band 7) == 0 -> 1;
-dir(Pos,8) when (Pos band 7) == 0 -> 8;
-dir(Pos,9) when (Pos band 7) == 0 -> 9;
-dir(Pos,_) when (Pos band 7) == 0 -> false;
-
-dir(Pos,-9) when (Pos band 7) == 7 -> -9; % {8,_}
-dir(Pos,-8) when (Pos band 7) == 7 -> -8;
-dir(Pos,-1) when (Pos band 7) == 7 -> -1;
-dir(Pos,7) when (Pos band 7) == 7 -> 7;
-dir(Pos,8) when (Pos band 7) == 7 -> 8;
-dir(Pos,_) when (Pos band 7) == 7 -> false;
-
-dir(_Pos,Dir) -> Dir.
-
diff --git a/lib/gs/contribs/othello/othello_board.erl b/lib/gs/contribs/othello/othello_board.erl
deleted file mode 100644
index cc055b1fa1..0000000000
--- a/lib/gs/contribs/othello/othello_board.erl
+++ /dev/null
@@ -1,649 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-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(othello_board).
--compile([{nowarn_deprecated_function,{gs,config,2}},
- {nowarn_deprecated_function,{gs,create,3}},
- {nowarn_deprecated_function,{gs,create,4}},
- {nowarn_deprecated_function,{gs,destroy,1}},
- {nowarn_deprecated_function,{gs,start,0}}]).
-
--export([start/0,stop/0,init/0]).
-
-
-%%----------------------------------------------------------------------
-%% The Othello program now uses the gs graphical package instead of the
-%% pxw package.
-%%
-%% Differences are, explanation why and source of change in parenthesis:
-%%
-%% - Buttons looks different (gs feature)
-%% - The black box around "Black to draw" have been removed. (me)
-%% - The Colour and Level menues have been moved directly down to the
-%% 'Status' box. (usability update, my addition)
-%% - The mouse pointer does not change into a watch when the computer
-%% is thinking (not supported in gs)
-%% - Buttons does not flash when being beeped. (not supported in gs)
-%%
-%%
-%% /Peter
-%%
-%%----------------------------------------------------------------------
-
-
--define(BGCOL,forestgreen).
-
-start() ->
- spawn(othello_board,init,[]).
-
-stop() ->
- ok.
-
-%% This is not an application so we don't have their way of knowing
-%% a private data directory where the GIF files are located (this directory).
-%% We can find GS and makes it relative from there /kgb
-
--define(BitmapPath,"../contribs/othello/priv").
-
-setup_path() ->
- GsPrivDir = code:priv_dir(gs),
- Path = filename:join(GsPrivDir,?BitmapPath),
- put(path,Path).
-
-path() -> get(path).
-
-
-
-%%
-%% The button area are the Quit, Rules buttons at the top of the window.
-%% The Status area is the black and white scores level and colour etc
-%% inbetween the buttons and the othello board.
-%% The board is the 8x8 board where othello battles are fought.
-%%
-init() ->
- process_flag(trap_exit,true),
- setup_path(),
- S = gs:start(),
- put(windowroot,S), % Ugly global store
-
- %% Shell coordinates
- W = 496,
- H = 636,
-
- %% Fix top window
- Shell = gs:create(window, S, [{title,"Othello"},
- {width, W},{height, H}]),
-
-
- %% Setup window contents
-
- setup_buttons(Shell,0,0,W,40), % Fix Menubar
- setup_status_box(Shell,0,40,W,100), % Fix Status area
- setup_board(Shell,0,140,496,496), % Combat board
-
- GamePid = othello:new_game(white,black,1,first_time),
-
- %% Default settings
- Options = {white,black,1},
- %%Wids = {Status,B,W,Dr,Le,Co},
- Wids = {change,this,at,later,stage,ponto},
- write_options(Options,Wids),
-
- gs:config(Shell, {map, true}), %Make win visible
-
- loop(computer,GamePid,Shell,Wids,Options).
-
-
-
-
-
-
-loop(User,GamePid,Shell,Wids,Options) ->
- receive
- {gs,ButtId, click,_ButtId1,[Button]} ->
- GamePid1 = but_pressed(Button,ButtId,User,GamePid,Shell,
- Wids,Options),
- loop(User,GamePid1,Shell,Wids,Options);
-
- {gs,_, click,_,[MenuItem,_MenuIndex]} ->
- Ops = menu_selected(MenuItem,User,GamePid,Wids,Options),
- loop(User,GamePid,Shell,Wids,Ops);
-
- {'EXIT',GamePid,_} ->
- loop(User,null,Shell,Wids,Options);
-
- {'EXIT',_,_} ->
- loop(User,GamePid,Shell,Wids,Options);
-
- GameMsg ->
- game_msg(GameMsg,User,GamePid,Shell,Wids,Options)
- end.
-
-but_pressed("Quit",_ButtId,_User,_GamePid,_Shell,_Wids,_Op) ->
- stop(),
- exit(quit);
-but_pressed("Rules",_ButtId,_User,GamePid,_Shell,_Wids,_Op) ->
- io:format("No rules, do as you wish~n",[]),
- GamePid;
-but_pressed("Help",_ButtId,_User,GamePid,_Shell,_Wids,_Op) ->
- io:format("Othello game~n",[]),
- io:format("------------~n",[]),
- io:format(" Put markers by clicking in squares~n",[]),
- io:format(" Change level by clicking on it~n",[]),
- io:format(" Change colour by clicking on it~n",[]),
- io:format("~n",[]),
- GamePid;
-but_pressed("Newgame",_ButtId,_User,GamePid,_Shell,Wids,Options) ->
- new_game(GamePid,Wids,Options);
-but_pressed([],ButtId,User,GamePid,_Shell,_Wids,_Op)
- when is_pid(GamePid),User == player ->
- [C,R] = atom_to_list(ButtId),
- GamePid ! {self(),position,othello_adt:pos(C-96,translate(R-48))},
- GamePid;
-but_pressed([],ButtId,_User,GamePid,_Shell,_Wids,_Op) ->
- [C,R] = atom_to_list(ButtId),
- beep(othello_adt:pos(C-96,translate(R-48))),
- GamePid;
-but_pressed(Button,ButtId,_User,GamePid,_Shell,_Wids,_Op) ->
- io:format('Not implemented button pressed ~p, ~p!!!~n',[ButtId,Button]),
- GamePid.
-
-menu_selected("Black",_User,_GamePid,Wids,Options) ->
- Op0 = setelement(1,Options,white),
- Op1 = setelement(2,Op0,white),
- write_options(Op1,Wids),
- Op1;
-menu_selected("White",_User,_GamePid,Wids,Options) ->
- Op0 = setelement(1,Options,black),
- Op1 = setelement(2,Op0,black),
- write_options(Op1,Wids),
- Op1;
-menu_selected("Black (begin)",_User,_GamePid,Wids,Options) ->
- Op0 = setelement(1,Options,white),
- Op1 = setelement(2,Op0,black),
- write_options(Op1,Wids),
- Op1;
-menu_selected("White (begin)",_User,_GamePid,Wids,Options) ->
- Op0 = setelement(1,Options,black),
- Op1 = setelement(2,Op0,white),
- write_options(Op1,Wids),
- Op1;
-menu_selected("Beginner",_User,_GamePid,Wids,Options) ->
- Op1 = setelement(3,Options,1),
- write_options(Op1,Wids),
- Op1;
-menu_selected("Intermediate",_User,_GamePid,Wids,Options) ->
- Op1 = setelement(3,Options,2),
- write_options(Op1,Wids),
- Op1;
-menu_selected("Advanced",_User,_GamePid,Wids,Options) ->
- Op1 = setelement(3,Options,3),
- write_options(Op1,Wids),
- Op1;
-menu_selected("Expert",_User,_GamePid,Wids,Options) ->
- Op1 = setelement(3,Options,4),
- write_options(Op1,Wids),
- Op1;
-menu_selected(What,_User,_GamePid,_Wids,Options) ->
- io:format('Menu item not implemented <~s>~n',[What]),
- Options.
-
-game_msg(Msg,User,GamePid,Shell,Wids,Options) ->
- case Msg of
- {GamePid,new_mark,Pos,Colour} ->
- new_mark(Pos,Colour),
- loop(User,GamePid,Shell,Wids,Options);
-
- {GamePid,illegal_draw,Draw} ->
- beep(Draw),
- loop(User,GamePid,Shell,Wids,Options);
-
- {GamePid,player,Computer,Computer} ->
- show_player(element(1,Wids),Computer),
- cursor("watch"),
- GamePid ! {self(),go_on_play},
- loop(computer,GamePid,Shell,Wids,Options);
-
- {GamePid,player,_Computer,Player} ->
- show_player(element(1,Wids),Player),
- cursor("top_left_arrow"),
- GamePid ! {self(),go_on_play},
- loop(player,GamePid,Shell,Wids,Options);
-
- {GamePid,omit_draw,Player} ->
- omit_draw(GamePid,Player),
- loop(User,GamePid,Shell,Wids,Options);
-
- {GamePid,score,WhiteRes,BlackRes} ->
- write_score(Wids,WhiteRes,BlackRes),
- loop(User,GamePid,Shell,Wids,Options);
-
- {GamePid,draw,Draw} ->
- write_draw(Wids,Draw),
- loop(User,GamePid,Shell,Wids,Options);
-
- {GamePid,game_over,WhiteRes,BlackRes} ->
- game_over(WhiteRes,BlackRes),
- loop(User,GamePid,Shell,Wids,Options);
-
- What ->
- io:format('game_msg received: ~w~n',[What]),
- loop(User,GamePid,Shell,Wids,Options)
- end.
-
-
-new_game(GamePid,Wids,Options) when is_pid(GamePid) ->
- exit(GamePid,kill),
- new_game(Wids,Options);
-new_game(_,Wids,Options) ->
- new_game(Wids,Options).
-
-new_game(_Wids,Options) ->
- label("",lastdraw),
- Computer = element(1,Options),
- Start = element(2,Options),
- Depth = element(3,Options),
- othello:new_game(Computer,Start,Depth,restart).
-
-new_mark(Pos,Colour) ->
- Col = othello_adt:col(Pos),
- Row = othello_adt:row(Pos),
- Name = [Col+96,translate(Row)+48],
- Button = get(Name),
- butbit(Button,Colour).
-
-beep(Draw) ->
- Col = othello_adt:col(Draw),
- Row = othello_adt:row(Draw),
- Name = [Col+96,translate(Row)+48],
- Button = get(Name),
- bell(Button).
-
-show_player(_Status,white) ->
- label("White to draw",todraw);
-show_player(_Status,black) ->
- label("Black to draw",todraw).
-
-write_score(_Wids,WhiteRes,BlackRes) ->
- label(integer_to_list(BlackRes),bscore),
- label(integer_to_list(WhiteRes),wscore).
-
-write_draw(_Wids,Draw) ->
- Col = othello_adt:col(Draw),
- Row = othello_adt:row(Draw),
- label(lists:flatten(io_lib:format('{~w,~w}',[Col,Row])), lastdraw).
-
-write_options(Options,Wids) ->
- write_colour(Options,Wids),
- write_level(Options,Wids).
-
-write_colour(Options,Wids) ->
- write_colour(element(1,Options),element(2,Options),Wids).
-
-write_colour(black,white,_Wids) -> label("White (begin)",colour);
-write_colour(black,black,_Wids) -> label("White",colour);
-write_colour(white,black,_Wids) -> label("Black (begin)",colour);
-write_colour(white,white,_Wids) -> label("Black",colour).
-
-write_level(Options,_Wids) ->
- case element(3,Options) of
- 1 -> label("Beginner",level);
- 2 -> label("Intermediate",level);
- 3 -> label("Advanced",level);
- 4 -> label("Expert",level)
- end.
-
-cursor(_What) ->
- done.
-%cursor(What) -> cursor(get(),What).
-
-%cursor([{[C,R],Button}|Buts],What) ->
-% set_widget(Button,"cursor",What),
-% cursor(Buts,What);
-%cursor([_|Buts],What) ->
-% cursor(Buts,What);
-%cursor([],_) ->
-% true.
-
-translate(1) -> 8;
-translate(2) -> 7;
-translate(3) -> 6;
-translate(4) -> 5;
-translate(5) -> 4;
-translate(6) -> 3;
-translate(7) -> 2;
-translate(8) -> 1.
-
-bitmap(grey) -> bitmap_path("square.bm");
-bitmap(black) -> bitmap_path("marker.bm");
-bitmap(white) -> bitmap_path("marker.bm").
-
-bitmap_path(Bitmap) ->
- filename:join(path(),Bitmap).
-
-xy_position([[Letter,Digit],_,_]) ->
- LettPos = Letter - 97,
- X = LettPos*60 ,
- Y = (8 - list_to_integer([Digit])) * 60,
- {X+6,Y+6};
-xy_position(X) ->
- io:format("xy_position: ~w~n",[{error,X}]).
-
-
-board() ->
- [["a1",grey,nil],
- ["b1",grey,nil],
- ["c1",grey,nil],
- ["d1",grey,nil],
- ["e1",grey,nil],
- ["f1",grey,nil],
- ["g1",grey,nil],
- ["h1",grey,nil],
-
- ["a2",grey,nil],
- ["b2",grey,nil],
- ["c2",grey,nil],
- ["d2",grey,nil],
- ["e2",grey,nil],
- ["f2",grey,nil],
- ["g2",grey,nil],
- ["h2",grey,nil],
-
- ["a3",grey,nil],
- ["b3",grey,nil],
- ["c3",grey,nil],
- ["d3",grey,nil],
- ["e3",grey,nil],
- ["f3",grey,nil],
- ["g3",grey,nil],
- ["h3",grey,nil],
-
- ["a4",grey,nil],
- ["b4",grey,nil],
- ["c4",grey,nil],
- ["d4",white,nil],
- ["e4",black,nil],
- ["f4",grey,nil],
- ["g4",grey,nil],
- ["h4",grey,nil],
-
- ["a5",grey,nil],
- ["b5",grey,nil],
- ["c5",grey,nil],
- ["d5",black,nil],
- ["e5",white,nil],
- ["f5",grey,nil],
- ["g5",grey,nil],
- ["h5",grey,nil],
-
- ["a6",grey,nil],
- ["b6",grey,nil],
- ["c6",grey,nil],
- ["d6",grey,nil],
- ["e6",grey,nil],
- ["f6",grey,nil],
- ["g6",grey,nil],
- ["h6",grey,nil],
-
- ["a7",grey,nil],
- ["b7",grey,nil],
- ["c7",grey,nil],
- ["d7",grey,nil],
- ["e7",grey,nil],
- ["f7",grey,nil],
- ["g7",grey,nil],
- ["h7",grey,nil],
-
- ["a8",grey,nil],
- ["b8",grey,nil],
- ["c8",grey,nil],
- ["d8",grey,nil],
- ["e8",grey,nil],
- ["f8",grey,nil],
- ["g8",grey,nil],
- ["h8",grey,nil]].
-
-
-omit_draw(GamePid,Player) ->
-% %% Find mouse coords first
-% %% This was not possible in gs
-
- W = 200, H = 100, Root = get(windowroot),
- Box = gs:create(window, Root, [{title,"OMIT"}, {width, W},{height, H}]),
-
- mk_label_c(lists:flatten(io_lib:format('~w has to omit draw !',[Player])),
- Box, W, 10),
-
- mk_button_c("Ok", Box, W, H-40, 80, 30),
-
- gs:config(Box, {map, true}), %Make win visible
-
- receive
- {gs,_, click,_,["Ok"]} ->
- gs:destroy(Box),
- GamePid ! {self(),continue}
- end.
-
-game_over(WhiteRes,BlackRes) ->
-% %% Find mouse coords first
-% %% This was not possible in gs
-
- W = 200, H = 160,
- Root = get(windowroot),
- Box = gs:create(window, Root, [{title,"GAME OVER"},
- {width, W},{height, H}]),
-
- mk_label_c("GAME OVER", Box, W, 10),
-
- mk_label_c(lists:flatten(io_lib:format('White score: ~w',[WhiteRes])),
- Box,W,40),
- mk_label_c(lists:flatten(io_lib:format('Black score: ~w',[BlackRes])),
- Box,W,70),
-
- mk_button_c("Ok", Box, W, H-40, 80, 30),
-
- gs:config(Box, {map, true}), %Make win visible
-
- receive
- {gs,_, click,_,["Ok"]} ->
- gs:destroy(Box)
- end.
-
-
-
-%% ----------------------------------------------------------------
-%% Library functions.
-%% ----------------------------------------------------------------
-
-bell(Widget) ->
- %% gs does not support bells,
- Widget.
-
-label(Text,Label) ->
- gs:config(Label,[{label,{text,Text}}]).
-
-%% mk_label in centered version
-mk_label_c(Label,Parent,Width,Y) ->
- W = 8*length(Label),
- X = trunc((Width-W)/2),
- gs:create(label,Parent,[{width,W}, {height, 20}, {x,X}, {y,Y},
- {label, {text, Label}}]).
-
-
-
-
-setup_buttons(Shell,X,Y,W,H) ->
- ButBox = gs:create(frame, Shell,[{x,X}, {y,Y},{bg,white},
- {width,W}, {height,H}]),
- C = gs:create(canvas,ButBox,[{x,X}, {y,Y}, {width, W}, {height, H},
- {bg,white}]),
- gs:create(line, C, [{coords, [{0,H-1},{W,H-1}]}]),
-
-
- mk_button("Quit",ButBox, 10, 10, 70, 20),
- mk_button("Rules",ButBox, 80, 10, 70, 20),
- mk_button("Newgame",ButBox, 150, 10, 70, 20),
- mk_button("Help",ButBox, 220, 10, 70, 20),
-%% mk_button("Level",ButBox, 290, 10, 70, 20),
-
- done.
-
-
-
-
-
-%%----------------------------------------
-%% Sets up the middle window w. all the status info in.
-%% The labels are given names:
-%% bscore, wscore, lastdraw, todraw, level and colour to simplify
-%% their frequent setting
-%%
-setup_status_box(Shell,X,Y,W,H) ->
- F = gs:create(frame, Shell,[{x,X}, {y,Y},
- {width,W}, {height,H},{bg,white}]),
- C = gs:create(canvas,F,[{x,0}, {y,0}, {width, W}, {height, H},{bg,white}]),
- gs:create(line, C, [{coords, [{0,H-1},{W,H-1}]}]),
-
- %% Left side
- gs:create(label,F,[{align,w},{x,10}, {y,5}, {width, 100},
- {label,{text, "Black score:"}},{bg,white}]),
- gs:create(label,bscore,F,[{align,w},{x,110}, {y,5}, {width, 40},
- {label,{text, "2"}},{bg,white}]),
- gs:create(label,F,[{align,w},{x,10}, {y,35}, {width, 100},
- {label,{text, "White score:"}},{bg,white}]),
- gs:create(label,wscore,F,[{align,w},{x,110}, {y,35}, {width, 40},
- {label,{text, "2"}},{bg,white}]),
- gs:create(label,F,[{align,w},{x,10}, {y,65}, {width, 100},
- {label,{text, "Last draw:"}},{bg,white}]),
- gs:create(label,lastdraw,F,[{align,w},{x,110}, {y,65}, {width, 40},
- {label,{text, ""}},{bg,white}]),
-
-
- %% Right side
- X2 = trunc(W/2)+10,
- gs:create(label,todraw,F,[{align,w},{x,X2}, {y,5}, {width, 100},
- {label,{text, "Black to draw:"}},{bg,white}]),
-
- gs:create(label,F,[{align,w},{x,X2}, {y,35}, {width, 80},
- {label,{text, "Level:"}},{bg,white}]),
- setup_level_menu(F,X2+80,35),
-
-%% gs:create(label,level,F,[{align,w},{x,X2+80}, {y,35}, {width, 130},
-%% {label,{text, "Intermediate"}},{bg,white}]),
- gs:create(label,F,[{align,w},{x,X2}, {y,65}, {width, 80},
- {label,{text, "Colour:"}},{bg,white}]),
- setup_col_menu(F,X2+80,65),
-
-%% gs:create(label,colour,F,[{align,w},{x,X2+80}, {y,65}, {width, 120},
-%% {label,{text, "black (begin)"}},{bg,white}]),
-
- done.
-
-
-setup_col_menu(P,X,Y) ->
- MB = gs:create(menubutton,colour,P,
- [{x,X}, {y,Y}, {bw,3},
- %%{width,W}, {height,H},
- {align,w}, {bg,white},
- {relief, raised},
- {activefg,white}, {activebg,black},
- {label, {text,"Colours"}}]),
-
- M = gs:create(menu,MB,[]),
- gs:create(menuitem,M,[{label,{text,"Black (begin)"}}]),
- gs:create(menuitem,M,[{label,{text,"Black"}}]),
- gs:create(menuitem,M,[{label,{text,"White (begin)"}}]),
- gs:create(menuitem,M,[{label,{text,"White"}}]),
- done.
-
-setup_level_menu(P,X,Y) ->
- MB = gs:create(menubutton,level,P,
- [{x,X}, {y,Y},
- %%{width,W}, {height,H},
- {relief, raised},
- {activefg,white}, {activebg,black},
- {align,w}, {bg,white},
- {label, {text,"Colours"}}]),
-
- M = gs:create(menu,MB,[]),
- gs:create(menuitem,M,[{label,{text,"Beginner"}}]),
- gs:create(menuitem,M,[{label,{text,"Intermediate"}}]),
- gs:create(menuitem,M,[{label,{text,"Advanced"}}]),
- gs:create(menuitem,M,[{label,{text,"Expert"}}]),
- done.
-
-
-setup_board(Shell,X,Y,W,H) ->
- F = gs:create(frame, Shell,[{x,X}, {y,Y},
- {width,W}, {height,H},{bg,white}]),
- display_board(F).
-
-
-mk_button(Label, Parent, X, Y, W, H) ->
- gs:create(button,Parent,[{width,W}, {height, H}, {x,X}, {y,Y},
- {label, {text, Label}}, {bg,white},
- {activefg,white}, {activebg,black}]).
-
-%% Centers a button around Width
-mk_button_c(Label, Parent, Width, Y, W, H) ->
- X = trunc((Width-W)/2),
- gs:create(button,Parent,[{width,W}, {height, H}, {x,X}, {y,Y},
- {label, {text, Label}}, {bg,white}]).
-
-
-butbit(Button,Col) ->
- gs:config(Button,[
- {label,{image,bitmap(Col)}},
- {fg, Col},
- {activefg,Col},
- {label, {image, bitmap(Col)}}]),
- Button.
-
-mk_board_butt(Top,Name,X,Y,Col) ->
- B = gs:create(button,list_to_atom(Name), Top,
- [{x,X}, {y,Y}, {width,60}, {height,60},
- {padx,5},{pady,5},
- {relief,flat},
- {bg,?BGCOL}, {activebg,?BGCOL}]),
- butbit(B,Col),
- B.
-
-
-
-display_board(Top) ->
- Board = board(),
- display_board(Top,Board,1).
-
-display_board(_,_,65) -> true;
-display_board(Top,[H|T],Place) ->
- [Name,Colour,_] = H,
- {X,Y} = xy_position(H),
- Button = mk_board_butt(Top,Name,X,Y,Colour),
- %%Button = mk_button("",Name,Top,X,Y,60,60),
- put(Name,Button),
- %%Bitmap = bitmap(Colour),
- %%butbit(Button,Bitmap),
- %%set_widget(Button,"internalWidth","1"),
- %%set_widget(Button,"internalHeight","1"),
- %%borderWidth(2,Button),
- display_board(Top,T,Place+1).
-
-
diff --git a/lib/gs/contribs/othello/priv/marker.bm b/lib/gs/contribs/othello/priv/marker.bm
deleted file mode 100644
index fe7f3df820..0000000000
--- a/lib/gs/contribs/othello/priv/marker.bm
+++ /dev/null
@@ -1,43 +0,0 @@
-#define marker2_width 60
-#define marker2_height 60
-static unsigned char marker2_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
- 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x0f, 0x00, 0x00,
- 0x00, 0x00, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
- 0xff, 0x3f, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
- 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xf8, 0xff, 0xff,
- 0xff, 0xff, 0x03, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00,
- 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xfe, 0xff, 0xff,
- 0xff, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
- 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0x7f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00,
- 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x00, 0xc0, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0x7f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x00,
- 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff,
- 0xff, 0x3f, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x3f, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x9f, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0xcf, 0x1f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xc7, 0x0f, 0x00,
- 0x00, 0xfc, 0xff, 0xff, 0xff, 0xe7, 0x07, 0x00, 0x00, 0xf8, 0xff, 0xff,
- 0x7f, 0xf1, 0x03, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xbf, 0xfc, 0x03, 0x00,
- 0x00, 0xf0, 0xff, 0xff, 0x59, 0xff, 0x01, 0x00, 0x00, 0xe0, 0xff, 0xff,
- 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00,
- 0x00, 0x00, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
- 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00,
- 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/lib/gs/contribs/othello/priv/square.bm b/lib/gs/contribs/othello/priv/square.bm
deleted file mode 100644
index 4e6880b330..0000000000
--- a/lib/gs/contribs/othello/priv/square.bm
+++ /dev/null
@@ -1,43 +0,0 @@
-#define square_width 60
-#define square_height 60
-static unsigned char square_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/lib/gs/test/Makefile b/lib/gs/test/Makefile
index 493770745f..067e1adbb6 100644
--- a/lib/gs/test/Makefile
+++ b/lib/gs/test/Makefile
@@ -25,7 +25,7 @@ RELSYSDIR = $(RELEASE_PATH)/gs_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_COMPILE_FLAGS +=
EBIN = .
diff --git a/lib/hipe/cerl/cerl_cconv.erl b/lib/hipe/cerl/cerl_cconv.erl
index 0fc28be5f3..ac9d01ab0e 100644
--- a/lib/hipe/cerl/cerl_cconv.erl
+++ b/lib/hipe/cerl/cerl_cconv.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-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.
@@ -710,7 +710,7 @@ ren__new() ->
ren__add(Key, Value, Ren) ->
dict:store(Key, Value, Ren).
-ren__map(Key, Ren) ->
+ren__map(Key, Ren) ->
case dict:find(Key, Ren) of
{ok, Value} ->
Value;
@@ -722,11 +722,14 @@ ren__map(Key, Ren) ->
%% ---------------------------------------------------------------------
%% State
--record(state, {module :: module(), function :: {atom(), arity()},
- names, refs, defs = []}).
+-record(state, {module :: module(),
+ function :: {atom(), arity()} | 'undefined',
+ names = sets:new() :: sets:set(), %% XXX: refine
+ refs = dict:new() :: dict:dict(), %% XXX: refine
+ defs = []}).
s__new(Module) ->
- #state{module = Module, names = sets:new(), refs = dict:new()}.
+ #state{module = Module}.
s__add_function_name(Name, S) ->
S#state{names = sets:add_element(Name, S#state.names)}.
diff --git a/lib/hipe/cerl/cerl_hipeify.erl b/lib/hipe/cerl/cerl_hipeify.erl
index 8691e80cac..6611abd204 100644
--- a/lib/hipe/cerl/cerl_hipeify.erl
+++ b/lib/hipe/cerl/cerl_hipeify.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2003-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.
@@ -623,12 +623,12 @@ ren__map(Key, Ren) ->
%% ---------------------------------------------------------------------
%% State
-%% pmatch = 'true' | 'false' | 'no_duplicates' | 'duplicate_all'
+-type pmatch() :: 'true' | 'false' | 'no_duplicates' | 'duplicate_all'.
--record(state, {module::atom(),
- function::{atom(), 0..256},
- pmatch=true,
- revisit = false}).
+-record(state, {module :: module(),
+ function :: {atom(), arity()} | 'undefined',
+ pmatch = true :: pmatch(),
+ revisit = false :: boolean()}).
s__new(Module) ->
#state{module = Module}.
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index 9f23b6a9b3..7684dc4a81 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -46,7 +46,6 @@
t_bitstr/0,
t_boolean/0,
t_byte/0,
- t_char/0,
t_cons/0,
t_cons/2,
t_cons_hd/1,
@@ -87,7 +86,6 @@
t_is_port/2,
t_is_maybe_improper_list/2,
t_is_reference/2,
- t_is_string/1,
t_is_subtype/2,
t_is_tuple/2,
t_list/0,
@@ -139,7 +137,7 @@ type(M, F, A) ->
type(M, F, A, Xs) ->
type(M, F, A, Xs, 'universe').
--type opaques() :: 'universe' | [erl_types:erl_type()].
+-type opaques() :: erl_types:opaques().
-type arg_types() :: [erl_types:erl_type()].
@@ -552,9 +550,6 @@ type(erlang, bit_size, 1, Xs, Opaques) ->
type(erlang, byte_size, 1, Xs, Opaques) ->
strict(erlang, byte_size, 1, Xs,
fun (_) -> t_non_neg_integer() end, Opaques);
-type(erlang, disconnect_node, 1, Xs, Opaques) ->
- strict(erlang, disconnect_node, 1, Xs,
- fun (_) -> t_sup([t_boolean(), t_atom('ignored')]) end, Opaques);
%% Guard bif, needs to be here.
%% Also much more expressive than anything you could write in a spec...
type(erlang, element, 2, Xs, Opaques) ->
@@ -583,16 +578,9 @@ type(erlang, element, 2, Xs, Opaques) ->
%% Guard bif, needs to be here.
type(erlang, float, 1, Xs, Opaques) ->
strict(erlang, float, 1, Xs, fun (_) -> t_float() end, Opaques);
-type(erlang, fun_info, 1, Xs, Opaques) ->
- strict(erlang, fun_info, 1, Xs,
- fun (_) -> t_list(t_tuple([t_atom(), t_any()])) end, Opaques);
-type(erlang, get_cookie, 0, _, _Opaques) -> t_atom(); % | t_atom('nocookie')
%% Guard bif, needs to be here.
type(erlang, hd, 1, Xs, Opaques) ->
strict(erlang, hd, 1, Xs, fun ([X]) -> t_cons_hd(X) end, Opaques);
-type(erlang, integer_to_list, 2, Xs, Opaques) ->
- strict(erlang, integer_to_list, 2, Xs,
- fun (_) -> t_string() end, Opaques);
type(erlang, info, 1, Xs, _) -> type(erlang, system_info, 1, Xs); % alias
%% All type tests are guard BIF's and may be implemented in ways that
%% cannot be expressed in a type spec, why they are kept in erl_bif_types.
@@ -796,8 +784,6 @@ type(erlang, make_tuple, 3, Xs, Opaques) ->
_Other -> t_tuple()
end
end, Opaques);
-type(erlang, memory, 0, _, _Opaques) ->
- t_list(t_tuple([t_atom(), t_non_neg_fixnum()]));
type(erlang, nif_error, 1, Xs, Opaques) ->
%% this BIF and the next one are stubs for NIFs and never return
strict(erlang, nif_error, 1, Xs, fun (_) -> t_any() end, Opaques);
@@ -813,8 +799,6 @@ type(erlang, round, 1, Xs, Opaques) ->
strict(erlang, round, 1, Xs, fun (_) -> t_integer() end, Opaques);
%% Guard bif, needs to be here.
type(erlang, self, 0, _, _Opaques) -> t_pid();
-type(erlang, set_cookie, 2, Xs, Opaques) ->
- strict(erlang, set_cookie, 2, Xs, fun (_) -> t_atom('true') end, Opaques);
type(erlang, setelement, 3, Xs, Opaques) ->
strict(erlang, setelement, 3, Xs,
fun ([X1, X2, X3]) ->
@@ -849,19 +833,7 @@ type(erlang, setelement, 3, Xs, Opaques) ->
%% Guard bif, needs to be here.
type(erlang, size, 1, Xs, Opaques) ->
strict(erlang, size, 1, Xs, fun (_) -> t_non_neg_integer() end, Opaques);
-type(erlang, spawn, 1, Xs, Opaques) ->
- strict(erlang, spawn, 1, Xs, fun (_) -> t_pid() end, Opaques);
-type(erlang, spawn, 2, Xs, Opaques) ->
- strict(erlang, spawn, 2, Xs, fun (_) -> t_pid() end, Opaques);
-type(erlang, spawn, 4, Xs, Opaques) ->
- strict(erlang, spawn, 4, Xs, fun (_) -> t_pid() end, Opaques);
-type(erlang, spawn_link, 1, Xs, _) -> type(erlang, spawn, 1, Xs); % same
-type(erlang, spawn_link, 2, Xs, _) -> type(erlang, spawn, 2, Xs); % same
-type(erlang, spawn_link, 4, Xs, _) -> type(erlang, spawn, 4, Xs); % same
type(erlang, subtract, 2, Xs, _Opaques) -> type(erlang, '--', 2, Xs); % alias
-type(erlang, suspend_process, 1, Xs, Opaques) ->
- strict(erlang, suspend_process, 1, Xs,
- fun (_) -> t_atom('true') end, Opaques);
type(erlang, system_info, 1, Xs, Opaques) ->
strict(erlang, system_info, 1, Xs,
fun ([Type]) ->
@@ -926,8 +898,7 @@ type(erlang, system_info, 1, Xs, Opaques) ->
t_list(t_pid());
['os_type'] ->
t_tuple([t_sup([t_atom('unix'),
- t_atom('win32'),
- t_atom('ose')]),
+ t_atom('win32')]),
t_atom()]);
['os_version'] ->
t_sup(t_tuple([t_non_neg_fixnum(),
@@ -1015,10 +986,6 @@ type(erlang, tuple_to_list, 1, Xs, Opaques) ->
end
end
end, Opaques);
-type(erlang, yield, 0, _, _Opaques) -> t_atom('true');
-%%-- ets ----------------------------------------------------------------------
-type(ets, rename, 2, Xs, Opaques) ->
- strict(ets, rename, 2, Xs, fun ([_, Name]) -> Name end, Opaques);
%%-- hipe_bifs ----------------------------------------------------------------
type(hipe_bifs, add_ref, 2, Xs, Opaques) ->
strict(hipe_bifs, add_ref, 2, Xs, fun (_) -> t_nil() end, Opaques);
@@ -1678,25 +1645,6 @@ type(lists, zipwith3, 4, Xs, Opaques) ->
fun ([F,_As,_Bs,_Cs]) -> t_sup(t_list(t_fun_range(F, Opaques)),
t_nil()) end, Opaques);
-%%-- string -------------------------------------------------------------------
-type(string, chars, 2, Xs, Opaques) -> % NOTE: added to avoid loss of info
- strict(string, chars, 2, Xs, fun (_) -> t_string() end, Opaques);
-type(string, chars, 3, Xs, Opaques) -> % NOTE: added to avoid loss of info
- strict(string, chars, 3, Xs,
- fun ([Char, N, Tail]) ->
- case t_is_nil(Tail) of
- true ->
- type(string, chars, 2, [Char, N]);
- false ->
- case t_is_string(Tail) of
- true ->
- t_string();
- false ->
- t_sup(t_sup(t_string(), Tail), t_cons(Char, Tail))
- end
- end
- end, Opaques);
-
%%-----------------------------------------------------------------------------
type(M, F, A, Xs, _O) when is_atom(M), is_atom(F),
is_integer(A), 0 =< A, A =< 255 ->
@@ -2301,8 +2249,6 @@ arg_types(erlang, bit_size, 1) ->
%% Guard bif, needs to be here.
arg_types(erlang, byte_size, 1) ->
[t_bitstr()];
-arg_types(erlang, disconnect_node, 1) ->
- [t_node()];
arg_types(erlang, halt, 0) ->
[];
arg_types(erlang, halt, 1) ->
@@ -2322,17 +2268,11 @@ arg_types(erlang, element, 2) ->
%% Guard bif, needs to be here.
arg_types(erlang, float, 1) ->
[t_number()];
-arg_types(erlang, fun_info, 1) ->
- [t_fun()];
-arg_types(erlang, get_cookie, 0) ->
- [];
%% Guard bif, needs to be here.
arg_types(erlang, hd, 1) ->
[t_cons()];
arg_types(erlang, info, 1) ->
arg_types(erlang, system_info, 1); % alias
-arg_types(erlang, integer_to_list, 2) ->
- [t_integer(), t_from_range(2, 36)];
arg_types(erlang, is_atom, 1) ->
[t_any()];
arg_types(erlang, is_binary, 1) ->
@@ -2379,8 +2319,6 @@ arg_types(erlang, make_tuple, 2) ->
[t_non_neg_fixnum(), t_any()]; % the value 0 is OK as first argument
arg_types(erlang, make_tuple, 3) ->
[t_non_neg_fixnum(), t_any(), t_list(t_tuple([t_pos_integer(), t_any()]))];
-arg_types(erlang, memory, 0) ->
- [];
arg_types(erlang, nif_error, 1) ->
[t_any()];
arg_types(erlang, nif_error, 2) ->
@@ -2397,29 +2335,13 @@ arg_types(erlang, round, 1) ->
%% Guard bif, needs to be here.
arg_types(erlang, self, 0) ->
[];
-arg_types(erlang, set_cookie, 2) ->
- [t_node(), t_atom()];
arg_types(erlang, setelement, 3) ->
[t_pos_integer(), t_tuple(), t_any()];
%% Guard bif, needs to be here.
arg_types(erlang, size, 1) ->
[t_sup(t_tuple(), t_binary())];
-arg_types(erlang, spawn, 1) -> %% TODO: Tuple?
- [t_fun()];
-arg_types(erlang, spawn, 2) -> %% TODO: Tuple?
- [t_node(), t_fun()];
-arg_types(erlang, spawn, 4) -> %% TODO: Tuple?
- [t_node(), t_atom(), t_atom(), t_list()];
-arg_types(erlang, spawn_link, 1) ->
- arg_types(erlang, spawn, 1); % same
-arg_types(erlang, spawn_link, 2) ->
- arg_types(erlang, spawn, 2); % same
-arg_types(erlang, spawn_link, 4) ->
- arg_types(erlang, spawn, 4); % same
arg_types(erlang, subtract, 2) ->
arg_types(erlang, '--', 2);
-arg_types(erlang, suspend_process, 1) ->
- [t_pid()];
arg_types(erlang, system_info, 1) ->
[t_sup([t_atom(), % documented
t_tuple([t_atom(), t_any()]), % documented
@@ -2438,11 +2360,6 @@ arg_types(erlang, tuple_size, 1) ->
[t_tuple()];
arg_types(erlang, tuple_to_list, 1) ->
[t_tuple()];
-arg_types(erlang, yield, 0) ->
- [];
-%%------- ets -----------------------------------------------------------------
-arg_types(ets, rename, 2) ->
- [t_atom(), t_atom()];
%%------- hipe_bifs -----------------------------------------------------------
arg_types(hipe_bifs, add_ref, 2) ->
[t_mfa(), t_tuple([t_mfa(),
@@ -2639,13 +2556,6 @@ arg_types(lists, zipwith, 3) ->
[t_fun([t_any(), t_any()], t_any()), t_list(), t_list()];
arg_types(lists, zipwith3, 4) ->
[t_fun([t_any(), t_any(), t_any()], t_any()), t_list(), t_list(), t_list()];
-
-%%------- string --------------------------------------------------------------
-arg_types(string, chars, 2) ->
- [t_char(), t_non_neg_integer()];
-arg_types(string, chars, 3) ->
- [t_char(), t_non_neg_integer(), t_any()];
-%%-----------------------------------------------------------------------------
arg_types(M, F, A) when is_atom(M), is_atom(F),
is_integer(A), 0 =< A, A =< 255 ->
unknown. % safe approximation for all functions.
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index 7a2abc226f..fae12d7421 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -140,7 +140,6 @@
t_is_port/1, t_is_port/2,
t_is_maybe_improper_list/1, t_is_maybe_improper_list/2,
t_is_reference/1, t_is_reference/2,
- t_is_remote/1,
t_is_string/1,
t_is_subtype/2,
t_is_tuple/1, t_is_tuple/2,
@@ -173,14 +172,12 @@
t_number_vals/1, t_number_vals/2,
t_opaque_from_records/1,
t_opaque_structure/1,
- %% t_parameterized_module/0,
t_pid/0,
t_port/0,
t_maybe_improper_list/0,
%% t_maybe_improper_list/2,
t_product/1,
t_reference/0,
- t_remote/3,
t_string/0,
t_struct_from_opaque/2,
t_subst/2,
@@ -208,7 +205,6 @@
type_is_defined/4,
record_field_diffs_to_string/2,
subst_all_vars_to_any/1,
- subst_all_remote/2,
lift_list_to_pos_empty/1, lift_list_to_pos_empty/2,
is_opaque_type/2,
is_erl_type/1,
@@ -228,7 +224,7 @@
-export([t_is_identifier/1]).
-endif.
--export_type([erl_type/0, type_table/0, var_table/0]).
+-export_type([erl_type/0, opaques/0, type_table/0, var_table/0]).
%%-define(DEBUG, true).
@@ -280,7 +276,6 @@
-define(number_tag, number).
-define(opaque_tag, opaque).
-define(product_tag, product).
--define(remote_tag, remote).
-define(tuple_set_tag, tuple_set).
-define(tuple_tag, tuple).
-define(union_tag, union).
@@ -288,7 +283,7 @@
-type tag() :: ?atom_tag | ?binary_tag | ?function_tag | ?identifier_tag
| ?list_tag | ?map_tag | ?matchstate_tag | ?nil_tag | ?number_tag
- | ?opaque_tag | ?product_tag | ?remote_tag
+ | ?opaque_tag | ?product_tag
| ?tuple_tag | ?tuple_set_tag | ?union_tag | ?var_tag.
-define(float_qual, float).
@@ -320,7 +315,7 @@
%% Auxiliary types and convenient macros
%%
--type parse_form() :: {atom(), _, _} | {atom(), _, _, _} | {'op', _, _, _, _}. %% XXX: Temporarily
+-type parse_form() :: erl_parse:abstract_expr().
-type rng_elem() :: 'pos_inf' | 'neg_inf' | integer().
-record(int_set, {set :: [integer()]}).
@@ -330,7 +325,6 @@
%% was updated to 2.7 due to this change.
-record(opaque, {mod :: module(), name :: atom(),
args = [] :: [erl_type()], struct :: erl_type()}).
--record(remote, {mod:: module(), name :: atom(), args = [] :: [erl_type()]}).
-define(atom(Set), #c{tag=?atom_tag, elements=Set}).
-define(bitstr(Unit, Base), #c{tag=?binary_tag, elements=[Unit,Base]}).
@@ -350,7 +344,6 @@
-define(map(Pairs), #c{tag=?map_tag, elements=Pairs}).
-define(opaque(Optypes), #c{tag=?opaque_tag, elements=Optypes}).
-define(product(Types), #c{tag=?product_tag, elements=Types}).
--define(remote(RemTypes), #c{tag=?remote_tag, elements=RemTypes}).
-define(tuple(Types, Arity, Qual), #c{tag=?tuple_tag, elements=Types,
qualifier={Arity, Qual}}).
-define(tuple_set(Tuples), #c{tag=?tuple_set_tag, elements=Tuples}).
@@ -371,8 +364,8 @@
-type type_key() :: {'type' | 'opaque', atom(), arity()}.
-type record_value() :: [{atom(), erl_parse:abstract_expr(), erl_type()}].
-type type_value() :: {module(), erl_type(), atom()}.
--type type_table() :: dict:dict(record_key(), record_value())
- | dict:dict(type_key(), type_value()).
+-type type_table() :: dict:dict(record_key() | type_key(),
+ record_value() | type_value()).
-type var_table() :: dict:dict(atom(), erl_type()).
@@ -380,19 +373,18 @@
%% Unions
%%
--define(union(List), #c{tag=?union_tag, elements=[_,_,_,_,_,_,_,_,_,_,_]=List}).
-
--define(atom_union(T), ?union([T,?none,?none,?none,?none,?none,?none,?none,?none,?none,?none])).
--define(bitstr_union(T), ?union([?none,T,?none,?none,?none,?none,?none,?none,?none,?none,?none])).
--define(function_union(T), ?union([?none,?none,T,?none,?none,?none,?none,?none,?none,?none,?none])).
--define(identifier_union(T), ?union([?none,?none,?none,T,?none,?none,?none,?none,?none,?none,?none])).
--define(list_union(T), ?union([?none,?none,?none,?none,T,?none,?none,?none,?none,?none,?none])).
--define(number_union(T), ?union([?none,?none,?none,?none,?none,T,?none,?none,?none,?none,?none])).
--define(tuple_union(T), ?union([?none,?none,?none,?none,?none,?none,T,?none,?none,?none,?none])).
--define(matchstate_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,T,?none,?none,?none])).
--define(opaque_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,T,?none,?none])).
--define(remote_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,?none,T,?none])).
--define(map_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,?none,?none,T])).
+-define(union(List), #c{tag=?union_tag, elements=[_,_,_,_,_,_,_,_,_,_]=List}).
+
+-define(atom_union(T), ?union([T,?none,?none,?none,?none,?none,?none,?none,?none,?none])).
+-define(bitstr_union(T), ?union([?none,T,?none,?none,?none,?none,?none,?none,?none,?none])).
+-define(function_union(T), ?union([?none,?none,T,?none,?none,?none,?none,?none,?none,?none])).
+-define(identifier_union(T), ?union([?none,?none,?none,T,?none,?none,?none,?none,?none,?none])).
+-define(list_union(T), ?union([?none,?none,?none,?none,T,?none,?none,?none,?none,?none])).
+-define(number_union(T), ?union([?none,?none,?none,?none,?none,T,?none,?none,?none,?none])).
+-define(tuple_union(T), ?union([?none,?none,?none,?none,?none,?none,T,?none,?none,?none])).
+-define(matchstate_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,T,?none,?none])).
+-define(opaque_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,T,?none])).
+-define(map_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,?none,T])).
-define(integer_union(T), ?number_union(T)).
-define(float_union(T), ?number_union(T)).
-define(nil_union(T), ?list_union(T)).
@@ -679,8 +671,8 @@ list_decorate(List, L, Opaques) ->
union_decorate(U1, U2, Opaques) ->
Union = union_decorate(U1, U2, Opaques, 0, []),
- [A,B,F,I,L,N,T,M,_,_R,Map] = U1,
- [_,_,_,_,_,_,_,_,Opaque,_,_] = U2,
+ [A,B,F,I,L,N,T,M,_,Map] = U1,
+ [_,_,_,_,_,_,_,_,Opaque,_] = U2,
List = [A,B,F,I,L,N,T,M,Map],
DecList = [Dec ||
E <- List,
@@ -792,21 +784,6 @@ list_struct_from_opaque(Types, Opaques) ->
[t_struct_from_opaque(Type, Opaques) || Type <- Types].
%%-----------------------------------------------------------------------------
-%% Remote types: these types are used for preprocessing;
-%% they should never reach the analysis stage.
-
--spec t_remote(atom(), atom(), [erl_type()]) -> erl_type().
-
-t_remote(Mod, Name, Args) ->
- ?remote(set_singleton(#remote{mod = Mod, name = Name, args = Args})).
-
--spec t_is_remote(erl_type()) -> boolean().
-
-t_is_remote(Type) ->
- do_opaque(Type, 'universe', fun is_remote/1).
-
-is_remote(?remote(_)) -> true;
-is_remote(_) -> false.
-type mod_records() :: dict:dict(module(), type_table()).
@@ -1807,7 +1784,7 @@ t_mfa() ->
-spec t_module() -> erl_type().
t_module() ->
- t_sup(t_atom(), t_parameterized_module()).
+ t_atom().
-spec t_node() -> erl_type().
@@ -1833,11 +1810,6 @@ t_iolist(N, T) when N > 0 ->
t_iolist(0, T) ->
t_maybe_improper_list(t_any(), t_sup(T, t_nil())).
--spec t_parameterized_module() -> erl_type().
-
-t_parameterized_module() ->
- t_tuple().
-
-spec t_timeout() -> erl_type().
t_timeout() ->
@@ -2178,8 +2150,6 @@ t_sup(?opaque(Set1), ?opaque(Set2)) ->
%% io:format("Debug: t_sup executed with args ~w and ~w~n",[T1, T2]), ?none;
%%t_sup(T1, T2=?opaque(_,_,_)) ->
%% io:format("Debug: t_sup executed with args ~w and ~w~n",[T1, T2]), ?none;
-t_sup(?remote(Set1), ?remote(Set2)) ->
- ?remote(set_union_no_limit(Set1, Set2));
t_sup(?matchstate(Pres1, Slots1), ?matchstate(Pres2, Slots2)) ->
?matchstate(t_sup(Pres1, Pres2), t_sup(Slots1, Slots2));
t_sup(?nil, ?nil) -> ?nil;
@@ -2373,7 +2343,6 @@ force_union(T = ?list(_, _, _)) -> ?list_union(T);
force_union(T = ?nil) -> ?list_union(T);
force_union(T = ?number(_, _)) -> ?number_union(T);
force_union(T = ?opaque(_)) -> ?opaque_union(T);
-force_union(T = ?remote(_)) -> ?remote_union(T);
force_union(T = ?map(_)) -> ?map_union(T);
force_union(T = ?tuple(_, _, _)) -> ?tuple_union(T);
force_union(T = ?tuple_set(_)) -> ?tuple_union(T);
@@ -2450,8 +2419,7 @@ t_inf(T1, T2) ->
t_inf(T1, T2, 'universe').
%% 'match' should be used from t_find_unknown_opaque() only
--type t_inf_opaques() :: 'universe'
- | [erl_type()] | {'match', [erl_type() | 'universe']}.
+-type t_inf_opaques() :: opaques() | {'match', [erl_type() | 'universe']}.
-spec t_inf(erl_type(), erl_type(), t_inf_opaques()) -> erl_type().
@@ -2886,8 +2854,8 @@ inf_tuples_in_sets2(_, [], Acc, _Opaques) -> lists:reverse(Acc).
inf_union(U1, U2, Opaques) ->
OpaqueFun =
fun(Union1, Union2, InfFun) ->
- [_,_,_,_,_,_,_,_,Opaque,_,_] = Union1,
- [A,B,F,I,L,N,T,M,_,_R,Map] = Union2,
+ [_,_,_,_,_,_,_,_,Opaque,_] = Union1,
+ [A,B,F,I,L,N,T,M,_,Map] = Union2,
List = [A,B,F,I,L,N,T,M,Map],
inf_union_collect(List, Opaque, InfFun, [], [])
end,
@@ -3066,18 +3034,6 @@ t_subst_aux(?union(List), VarMap) ->
?union([t_subst_aux(E, VarMap) || E <- List]);
t_subst_aux(T, _VarMap) ->
T.
-
--spec subst_all_remote(erl_type(), erl_type()) -> erl_type().
-
-subst_all_remote(Type0, Substitute) ->
- Map =
- fun(Type) ->
- case t_is_remote(Type) of
- true -> Substitute;
- false -> Type
- end
- end,
- t_map(Map, Type0).
%%-----------------------------------------------------------------------------
%% Unification
@@ -3181,11 +3137,11 @@ unify_union1(?union(List), T1, T2) ->
end.
unify_union(List) ->
- [A,B,F,I,L,N,T,M,O,R,Map] = List,
+ [A,B,F,I,L,N,T,M,O,Map] = List,
if O =:= ?none -> no;
true ->
S = t_opaque_structure(O),
- {yes, t_sup([A,B,F,I,L,N,T,M,S,R,Map])}
+ {yes, t_sup([A,B,F,I,L,N,T,M,S,Map])}
end.
-spec is_opaque_type(erl_type(), [erl_type()]) -> boolean().
@@ -3543,10 +3499,10 @@ t_subtract_lists([], [], Acc) ->
-spec subtract_union([erl_type(),...], [erl_type(),...]) -> erl_type().
subtract_union(U1, U2) ->
- [A1,B1,F1,I1,L1,N1,T1,M1,O1,R1,Map1] = U1,
- [A2,B2,F2,I2,L2,N2,T2,M2,O2,R2,Map2] = U2,
- List1 = [A1,B1,F1,I1,L1,N1,T1,M1,?none,R1,Map1],
- List2 = [A2,B2,F2,I2,L2,N2,T2,M2,?none,R2,Map2],
+ [A1,B1,F1,I1,L1,N1,T1,M1,O1,Map1] = U1,
+ [A2,B2,F2,I2,L2,N2,T2,M2,O2,Map2] = U2,
+ List1 = [A1,B1,F1,I1,L1,N1,T1,M1,?none,Map1],
+ List2 = [A2,B2,F2,I2,L2,N2,T2,M2,?none,Map2],
Sub1 = subtract_union(List1, List2, 0, []),
O = if O1 =:= ?none -> O1;
true -> t_subtract(O1, ?union(U2))
@@ -3641,7 +3597,7 @@ t_is_instance(ConcreteType, Type) ->
t_unopaque(T) ->
t_unopaque(T, 'universe').
--spec t_unopaque(erl_type(), 'universe' | [erl_type()]) -> erl_type().
+-spec t_unopaque(erl_type(), opaques()) -> erl_type().
t_unopaque(?opaque(_) = T, Opaques) ->
case Opaques =:= 'universe' orelse is_opaque_type(T, Opaques) of
@@ -3662,7 +3618,7 @@ t_unopaque(?product(Types), Opaques) ->
?product([t_unopaque(T, Opaques) || T <- Types]);
t_unopaque(?function(Domain, Range), Opaques) ->
?function(t_unopaque(Domain, Opaques), t_unopaque(Range, Opaques));
-t_unopaque(?union([A,B,F,I,L,N,T,M,O,R,Map]), Opaques) ->
+t_unopaque(?union([A,B,F,I,L,N,T,M,O,Map]), Opaques) ->
UL = t_unopaque(L, Opaques),
UT = t_unopaque(T, Opaques),
UF = t_unopaque(F, Opaques),
@@ -3671,7 +3627,7 @@ t_unopaque(?union([A,B,F,I,L,N,T,M,O,R,Map]), Opaques) ->
?opaque(_) = O1 -> {O1, []};
Type -> {?none, [Type]}
end,
- t_sup([?union([A,B,UF,I,UL,N,UT,M,OF,R,UMap])|UO]);
+ t_sup([?union([A,B,UF,I,UL,N,UT,M,OF,UMap])|UO]);
t_unopaque(T, _) ->
T.
@@ -3938,16 +3894,6 @@ t_to_string(?float, _RecDict) -> "float()";
t_to_string(?number(?any, ?unknown_qual), _RecDict) -> "number()";
t_to_string(?product(List), RecDict) ->
"<" ++ comma_sequence(List, RecDict) ++ ">";
-t_to_string(?remote(Set), RecDict) ->
- string:join([case Args =:= [] of
- true -> flat_format("~w:~w()", [Mod, Name]);
- false ->
- ArgString = comma_sequence(Args, RecDict),
- flat_format("~w:~w(~s)", [Mod, Name, ArgString])
- end
- || #remote{mod = Mod, name = Name, args = Args} <-
- set_to_list(Set)],
- " | ");
t_to_string(?map(Pairs), RecDict) ->
"#{" ++ map_pairs_to_string(Pairs,RecDict) ++ "}";
t_to_string(?tuple(?any, ?any, ?any), _RecDict) -> "tuple()";
@@ -3980,18 +3926,17 @@ record_to_string(Tag, [_|Fields], FieldNames, RecDict) ->
FieldStrings = record_fields_to_string(Fields, FieldNames, RecDict, []),
"#" ++ atom_to_string(Tag) ++ "{" ++ string:join(FieldStrings, ",") ++ "}".
-record_fields_to_string([F|Fs], [{FName, _Abstr, _DefType}|FDefs],
+record_fields_to_string([F|Fs], [{FName, _Abstr, DefType}|FDefs],
RecDict, Acc) ->
NewAcc =
- case t_is_equal(F, t_any()) orelse t_is_any_atom('undefined', F) of
+ case
+ t_is_equal(F, t_any()) orelse
+ (t_is_any_atom('undefined', F) andalso
+ not t_is_none(t_inf(F, DefType)))
+ of
true -> Acc;
false ->
StrFV = atom_to_string(FName) ++ "::" ++ t_to_string(F, RecDict),
- %% ActualDefType = t_subtract(DefType, t_atom('undefined')),
- %% Str = case t_is_any(ActualDefType) of
- %% true -> StrFV;
- %% false -> StrFV ++ "::" ++ t_to_string(ActualDefType, RecDict)
- %% end,
[StrFV|Acc]
end,
record_fields_to_string(Fs, FDefs, RecDict, NewAcc);
@@ -4831,13 +4776,13 @@ do_opaque(?opaque(_) = Type, Opaques, Pred) ->
false -> Pred(Type)
end;
do_opaque(?union(List) = Type, Opaques, Pred) ->
- [A,B,F,I,L,N,T,M,O,R,Map] = List,
+ [A,B,F,I,L,N,T,M,O,Map] = List,
if O =:= ?none -> Pred(Type);
true ->
case Opaques =:= 'universe' orelse is_opaque_type(O, Opaques) of
true ->
S = t_opaque_structure(O),
- do_opaque(t_sup([A,B,F,I,L,N,T,M,S,R,Map]), Opaques, Pred);
+ do_opaque(t_sup([A,B,F,I,L,N,T,M,S,Map]), Opaques, Pred);
false -> Pred(Type)
end
end;
@@ -4871,10 +4816,6 @@ set_union(S1, S2) ->
_ -> ?any
end.
-set_union_no_limit(?any, _) -> ?any;
-set_union_no_limit(_, ?any) -> ?any;
-set_union_no_limit(S1, S2) -> ordsets:union(S1, S2).
-
%% The intersection and subtraction can return ?none.
%% This should always be handled right away since ?none is not a valid set.
%% However, ?any is considered a valid set.
diff --git a/lib/hipe/flow/cfg.hrl b/lib/hipe/flow/cfg.hrl
index f79fff4efe..641ec102db 100644
--- a/lib/hipe/flow/cfg.hrl
+++ b/lib/hipe/flow/cfg.hrl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2014. All Rights Reserved.
+%% 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.
@@ -34,11 +34,13 @@
%%
-record(cfg_info, {'fun' :: mfa(),
start_label :: cfg_lbl(),
+ %% TODO: merge is_closure and closure_arity into one field
is_closure :: boolean(),
- closure_arity :: arity(),
+ closure_arity = none :: 'none' | arity(),
is_leaf :: boolean(),
params, % :: list()
info = []}). %% this field seems not needed; take out??
+-type cfg_info() :: #cfg_info{}.
%%
%% Data is a triple with a dict of constants, a list of labels and an integer
@@ -49,6 +51,6 @@
%% The following is to be used by other modules
%%
-record(cfg, {table = gb_trees:empty() :: gb_trees:tree(),
- info :: #cfg_info{},
+ info :: cfg_info(),
data :: cfg_data()}).
-type cfg() :: #cfg{}.
diff --git a/lib/hipe/icode/hipe_icode.erl b/lib/hipe/icode/hipe_icode.erl
index 5c7003b0ed..07d230491d 100644
--- a/lib/hipe/icode/hipe_icode.erl
+++ b/lib/hipe/icode/hipe_icode.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-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.
@@ -631,59 +631,59 @@ mk_icode(Fun, Params, IsClosure, IsLeaf, Code, VarRange, LabelRange) ->
-spec mk_icode(mfa(), [icode_var()], boolean(), boolean(), [icode_instr()],
hipe_consttab(), {non_neg_integer(),non_neg_integer()},
- {icode_lbl(),icode_lbl()}) -> #icode{}.
+ {icode_lbl(),icode_lbl()}) -> icode().
mk_icode(Fun, Params, IsClosure, IsLeaf, Code, Data, VarRange, LabelRange) ->
#icode{'fun'=Fun, params=Params, code=Code,
data=Data, is_closure=IsClosure, is_leaf=IsLeaf,
var_range=VarRange, label_range=LabelRange}.
--spec icode_fun(#icode{}) -> mfa().
+-spec icode_fun(icode()) -> mfa().
icode_fun(#icode{'fun' = MFA}) -> MFA.
--spec icode_params(#icode{}) -> [icode_var()].
+-spec icode_params(icode()) -> [icode_var()].
icode_params(#icode{params = Params}) -> Params.
--spec icode_params_update(#icode{}, [icode_var()]) -> #icode{}.
+-spec icode_params_update(icode(), [icode_var()]) -> icode().
icode_params_update(Icode, Params) ->
Icode#icode{params = Params}.
--spec icode_is_closure(#icode{}) -> boolean().
+-spec icode_is_closure(icode()) -> boolean().
icode_is_closure(#icode{is_closure = Closure}) -> Closure.
--spec icode_is_leaf(#icode{}) -> boolean().
+-spec icode_is_leaf(icode()) -> boolean().
icode_is_leaf(#icode{is_leaf = Leaf}) -> Leaf.
--spec icode_code(#icode{}) -> icode_instrs().
+-spec icode_code(icode()) -> icode_instrs().
icode_code(#icode{code = Code}) -> Code.
--spec icode_code_update(#icode{}, icode_instrs()) -> #icode{}.
+-spec icode_code_update(icode(), icode_instrs()) -> icode().
icode_code_update(Icode, NewCode) ->
Vmax = highest_var(NewCode),
Lmax = highest_label(NewCode),
Icode#icode{code = NewCode, var_range = {0,Vmax}, label_range = {0,Lmax}}.
--spec icode_data(#icode{}) -> hipe_consttab().
+-spec icode_data(icode()) -> hipe_consttab().
icode_data(#icode{data=Data}) -> Data.
-%% %% -spec icode_data_update(#icode{}, hipe_consttab()) -> #icode{}.
+%% %% -spec icode_data_update(icode(), hipe_consttab()) -> icode().
%% icode_data_update(Icode, NewData) -> Icode#icode{data=NewData}.
--spec icode_var_range(#icode{}) -> {non_neg_integer(), non_neg_integer()}.
+-spec icode_var_range(icode()) -> {non_neg_integer(), non_neg_integer()}.
icode_var_range(#icode{var_range = VarRange}) -> VarRange.
--spec icode_label_range(#icode{}) -> {non_neg_integer(), non_neg_integer()}.
+-spec icode_label_range(icode()) -> {non_neg_integer(), non_neg_integer()}.
icode_label_range(#icode{label_range = LabelRange}) -> LabelRange.
--spec icode_info(#icode{}) -> icode_info().
+-spec icode_info(icode()) -> icode_info().
icode_info(#icode{info = Info}) -> Info.
--spec icode_info_update(#icode{}, icode_info()) -> #icode{}.
+-spec icode_info_update(icode(), icode_info()) -> icode().
icode_info_update(Icode, Info) -> Icode#icode{info = Info}.
--spec icode_closure_arity(#icode{}) -> arity().
+-spec icode_closure_arity(icode()) -> arity().
icode_closure_arity(#icode{closure_arity = Arity}) -> Arity.
--spec icode_closure_arity_update(#icode{}, arity()) -> #icode{}.
+-spec icode_closure_arity_update(icode(), arity()) -> icode().
icode_closure_arity_update(Icode, Arity) -> Icode#icode{closure_arity = Arity}.
@@ -1376,12 +1376,12 @@ remove_constants(L) ->
%% Substitution: replace occurrences of X by Y if {X,Y} is in the
%% Subst_list.
--spec subst([{_,_}], I) -> I when is_subtype(I, icode_instr()).
+-spec subst([{_,_}], I) -> I when I :: icode_instr().
subst(Subst, I) ->
subst_defines(Subst, subst_uses(Subst, I)).
--spec subst_uses([{_,_}], I) -> I when is_subtype(I, icode_instr()).
+-spec subst_uses([{_,_}], I) -> I when I :: icode_instr().
subst_uses(Subst, I) ->
case I of
@@ -1405,7 +1405,7 @@ subst_uses(Subst, I) ->
#icode_label{} -> I
end.
--spec subst_defines([{_,_}], I) -> I when is_subtype(I, icode_instr()).
+-spec subst_defines([{_,_}], I) -> I when I :: icode_instr().
subst_defines(Subst, I) ->
case I of
@@ -1709,7 +1709,7 @@ mk_new_label() ->
%% @doc Removes comments from Icode.
%%
--spec strip_comments(#icode{}) -> #icode{}.
+-spec strip_comments(icode()) -> icode().
strip_comments(ICode) ->
icode_code_update(ICode, no_comments(icode_code(ICode))).
diff --git a/lib/hipe/icode/hipe_icode.hrl b/lib/hipe/icode/hipe_icode.hrl
index 9b24c4914e..3bb7bae019 100644
--- a/lib/hipe/icode/hipe_icode.hrl
+++ b/lib/hipe/icode/hipe_icode.hrl
@@ -170,8 +170,9 @@
-record(icode, {'fun' :: mfa(),
params :: [icode_var()],
+ %% TODO: merge is_closure and closure_arity into one field
is_closure :: boolean(),
- closure_arity :: arity(),
+ closure_arity = none :: 'none' | arity(),
is_leaf :: boolean(),
code = [] :: icode_instrs(),
data :: hipe_consttab(),
diff --git a/lib/hipe/icode/hipe_icode_exceptions.erl b/lib/hipe/icode/hipe_icode_exceptions.erl
index 41556ab80f..f03ce2faaa 100644
--- a/lib/hipe/icode/hipe_icode_exceptions.erl
+++ b/lib/hipe/icode/hipe_icode_exceptions.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2004-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.
@@ -85,7 +85,7 @@
%%----------------------------------------------------------------------------
--spec fix_catches(#cfg{}) -> #cfg{}.
+-spec fix_catches(cfg()) -> cfg().
fix_catches(CFG) ->
{Map, State} = build_mapping(find_catches(init_state(CFG))),
@@ -393,10 +393,10 @@ get_renaming(C, Map) ->
%%---------------------------------------------------------------------
%% State abstraction
--record(state, {cfg :: #cfg{},
+-record(state, {cfg :: cfg(),
changed = false :: boolean(),
- succ :: #cfg{},
- pred :: #cfg{},
+ succ :: cfg(),
+ pred :: cfg(),
start_labels :: [icode_lbl(),...],
visited = hipe_icode_cfg:none_visited() :: gb_sets:set(),
out = gb_trees:empty() :: gb_trees:tree(),
@@ -404,13 +404,8 @@ get_renaming(C, Map) ->
}).
init_state(CFG) ->
- State = #state{cfg = CFG},
- refresh_state_cache(State).
-
-refresh_state_cache(State) ->
- CFG = State#state.cfg,
SLs = [hipe_icode_cfg:start_label(CFG)],
- State#state{succ = CFG, pred = CFG, start_labels = SLs}.
+ #state{cfg = CFG, succ = CFG, pred = CFG, start_labels = SLs}.
get_cfg(State) ->
State#state.cfg.
@@ -466,7 +461,8 @@ get_bb_code(L, State) ->
set_bb_code(L, Code, State) ->
CFG = State#state.cfg,
CFG1 = hipe_icode_cfg:bb_add(CFG, L, hipe_bb:mk_bb(Code)),
- refresh_state_cache(State#state{cfg = CFG1}).
+ SLs = [hipe_icode_cfg:start_label(CFG1)],
+ State#state{cfg = CFG1, succ = CFG1, pred = CFG1, start_labels = SLs}.
get_new_catches_in(L, State) ->
Ps = get_pred(L, State),
diff --git a/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl b/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl
index e350a6ff18..7613024787 100644
--- a/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl
+++ b/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2014. All Rights Reserved.
+%% 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.
@@ -314,7 +314,7 @@ node_create(Label, Pred, Succ) ->
%% tree - the tree of nodes, with labels as keys and node records as values
-record(nodes, {
- domtree :: hipe_dominators:domTree(),
+ domtree = none :: 'none' | hipe_dominators:domTree(),
labels = none :: 'none' | [icode_lbl()],
postorder = none :: 'none' | [icode_lbl()],
start_label = none :: 'none' | icode_lbl(),
@@ -390,7 +390,7 @@ update_del_red_test_set(Update) ->
%%-----------------------------------------------------------------------------
%% Main function called from the hipe_main module
--spec struct_reuse(#cfg{}) -> #cfg{}.
+-spec struct_reuse(cfg()) -> cfg().
struct_reuse(CFG) ->
%% debug_init_case_count(?SR_INSTR_TYPE),
diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl
index 1a4bbf179f..0e32da1d36 100644
--- a/lib/hipe/main/hipe.erl
+++ b/lib/hipe/main/hipe.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-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.
@@ -764,7 +764,8 @@ finalize(OrigList, Mod, Exports, WholeModule, Opts) ->
finalize_fun(MfaIcodeList, Exports, Opts) ->
case proplists:get_value(concurrent_comp, Opts) of
FalseVal when (FalseVal =:= undefined) orelse (FalseVal =:= false) ->
- [finalize_fun_sequential(MFAIcode, Opts, #comp_servers{})
+ NoServers = #comp_servers{pp_server = none, range = none, type = none},
+ [finalize_fun_sequential(MFAIcode, Opts, NoServers)
|| {_MFA, _Icode} = MFAIcode <- MfaIcodeList];
TrueVal when (TrueVal =:= true) orelse (TrueVal =:= debug) ->
finalize_fun_concurrent(MfaIcodeList, Exports, Opts)
diff --git a/lib/hipe/main/hipe.hrl.src b/lib/hipe/main/hipe.hrl.src
index ba27878a84..3be824ac34 100644
--- a/lib/hipe/main/hipe.hrl.src
+++ b/lib/hipe/main/hipe.hrl.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-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.
@@ -299,7 +299,8 @@
%% Records defined in the hipe module used in other parts of the compiler
%%----------------------------------------------------------------------------
--record(comp_servers, {pp_server :: pid(), range :: pid(), type :: pid()}).
+-type mpid() :: 'none' | pid().
+-record(comp_servers, {pp_server :: mpid(), range :: mpid(), type :: mpid()}).
%%----------------------------------------------------------------------------
%% Basic types of the 'hipe' application used in other parts of the system
diff --git a/lib/hipe/main/hipe_main.erl b/lib/hipe/main/hipe_main.erl
index 5753169961..be5050e155 100644
--- a/lib/hipe/main/hipe_main.erl
+++ b/lib/hipe/main/hipe_main.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-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.
@@ -55,7 +55,7 @@
%%=====================================================================
%% @spec compile_icode(MFA::mfa(),
-%% LinearIcode::#icode{},
+%% LinearIcode::icode(),
%% CompilerOptions::comp_options(),
%% CompServers::#comp_servers()) ->
%% {native,Platform,{unprofiled,NativeCode}} | {rtl,RTLCode}
@@ -69,7 +69,7 @@
%% generated). The compiler options must have already been expanded
%% (cf. `<a href="hipe.html">hipe:expand_options</a>'). </p>
--spec compile_icode(mfa(), #icode{}, comp_options(), #comp_servers{}) ->
+-spec compile_icode(mfa(), icode(), comp_options(), #comp_servers{}) ->
comp_icode_ret().
compile_icode(MFA, LinearIcode, Options, Servers) ->
@@ -230,10 +230,12 @@ get_pp_module(icode_liveness) -> hipe_icode_liveness;
get_pp_module(rtl_liveness) -> hipe_rtl_liveness.
perform_io(no_fun, _) -> ok;
-perform_io(Fun,PPServer) when is_pid(PPServer) ->
- PPServer ! {print,Fun};
-perform_io(Fun, undefined) ->
- Fun().
+perform_io(Fun, PPServer) when is_pid(PPServer) ->
+ PPServer ! {print, Fun},
+ ok;
+perform_io(Fun, none) ->
+ Fun(),
+ ok.
%%--------------------------------------------------------------------
diff --git a/lib/hipe/test/Makefile b/lib/hipe/test/Makefile
index d781e4f9be..09f4fd2129 100644
--- a/lib/hipe/test/Makefile
+++ b/lib/hipe/test/Makefile
@@ -36,7 +36,7 @@ RELSYSDIR = $(RELEASE_PATH)/hipe_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_COMPILE_FLAGS +=
EBIN = .
diff --git a/lib/hipe/test/bs_SUITE_data/bs_utf.erl b/lib/hipe/test/bs_SUITE_data/bs_utf.erl
index 24526f574d..368ad0cd20 100644
--- a/lib/hipe/test/bs_SUITE_data/bs_utf.erl
+++ b/lib/hipe/test/bs_SUITE_data/bs_utf.erl
@@ -9,7 +9,7 @@
-export([test/0]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
test() ->
ok = utf8_cm65(),
diff --git a/lib/ic/test/Makefile b/lib/ic/test/Makefile
index 576ffc4eff..93cbaf4dfe 100644
--- a/lib/ic/test/Makefile
+++ b/lib/ic/test/Makefile
@@ -209,10 +209,8 @@ ERL_LOCAL_FLAGS += -pa $(ERL_TOP)/lib/orber/ebin -pa $(ERL_TOP)/lib/ic/ebin
ERL_COMPILE_FLAGS += \
$(ERL_LOCAL_FLAGS) \
- -pa $(ERL_TOP)/lib/test_server/ebin \
-pa $(ERL_TOP)/lib/orber/ebin \
- -I$(ERL_TOP)/lib/orber \
- -I$(ERL_TOP)/lib/test_server/include
+ -I$(ERL_TOP)/lib/orber
# ----------------------------------------------------
# Targets
diff --git a/lib/ic/test/ic_SUITE.erl b/lib/ic/test/ic_SUITE.erl
index bca75b8349..c9fbf49a55 100644
--- a/lib/ic/test/ic_SUITE.erl
+++ b/lib/ic/test/ic_SUITE.erl
@@ -23,7 +23,7 @@
%%%----------------------------------------------------------------------
-module(ic_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
diff --git a/lib/ic/test/ic_be_SUITE.erl b/lib/ic/test/ic_be_SUITE.erl
index 42c30fc86e..49dd9953cb 100644
--- a/lib/ic/test/ic_be_SUITE.erl
+++ b/lib/ic/test/ic_be_SUITE.erl
@@ -23,7 +23,7 @@
%%%----------------------------------------------------------------------
-module(ic_be_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
diff --git a/lib/ic/test/ic_pp_SUITE.erl b/lib/ic/test/ic_pp_SUITE.erl
index ab22d532a1..e85ce788e3 100644
--- a/lib/ic/test/ic_pp_SUITE.erl
+++ b/lib/ic/test/ic_pp_SUITE.erl
@@ -23,7 +23,7 @@
%%----------------------------------------------------------------------
-module(ic_pp_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
diff --git a/lib/ic/test/ic_pragma_SUITE.erl b/lib/ic/test/ic_pragma_SUITE.erl
index e0ab43e178..c6e23a1f8c 100644
--- a/lib/ic/test/ic_pragma_SUITE.erl
+++ b/lib/ic/test/ic_pragma_SUITE.erl
@@ -28,7 +28,7 @@
%%-----------------------------------------------------------------
-module(ic_pragma_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
%%-----------------------------------------------------------------
%% External exports
diff --git a/lib/ic/test/ic_register_SUITE.erl b/lib/ic/test/ic_register_SUITE.erl
index e402692940..86d89e72d5 100644
--- a/lib/ic/test/ic_register_SUITE.erl
+++ b/lib/ic/test/ic_register_SUITE.erl
@@ -27,7 +27,7 @@
%%-----------------------------------------------------------------
-module(ic_register_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
%%-----------------------------------------------------------------
%% External exports
diff --git a/lib/ic/test/java_client_erl_server_SUITE.erl b/lib/ic/test/java_client_erl_server_SUITE.erl
index e95b3d5026..a670c5546e 100644
--- a/lib/ic/test/java_client_erl_server_SUITE.erl
+++ b/lib/ic/test/java_client_erl_server_SUITE.erl
@@ -23,7 +23,7 @@
%%%----------------------------------------------------------------------
-module(java_client_erl_server_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
diff --git a/lib/inets/src/tftp/tftp_engine.erl b/lib/inets/src/tftp/tftp_engine.erl
index 493a29a68f..22dd2f3336 100644
--- a/lib/inets/src/tftp/tftp_engine.erl
+++ b/lib/inets/src/tftp/tftp_engine.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-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.
@@ -63,7 +63,8 @@
-record(file_info, {peer_req, pid}).
-record(sys_misc, {module, function, arguments}).
-record(error, {where, code, text, filename}).
--record(prepared, {status :: prep_status(), result, block_no, next_data, prev_data}).
+-record(prepared, {status :: prep_status() | 'undefined',
+ result, block_no, next_data, prev_data}).
-record(transfer_res, {status, decoded_msg, prepared}).
-define(ERROR(Where, Code, Text, Filename),
#error{where = Where, code = Code, text = Text, filename = Filename}).
diff --git a/lib/inets/test/Makefile b/lib/inets/test/Makefile
index 607ec7c182..67c979bd59 100644
--- a/lib/inets/test/Makefile
+++ b/lib/inets/test/Makefile
@@ -42,7 +42,6 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
INCLUDES = -I. \
- -I$(ERL_TOP)/lib/test_server/include/ \
-I$(ERL_TOP)/lib/inets/src/inets_app \
-I$(ERL_TOP)/lib/inets/src/http_lib \
-I$(ERL_TOP)/lib/inets/src/http_client \
@@ -238,7 +237,6 @@ RELTESTSYSBINDIR = $(RELTESTSYSALLDATADIR)/bin
# running the target "targets".
# ----------------------------------------------------
ERL_COMPILE_FLAGS += \
- -pa ../../../internal_tools/test_server/ebin \
$(INCLUDES) \
$(FTP_FLAGS) \
$(INETS_FLAGS)
diff --git a/lib/inets/test/ftp_format_SUITE.erl b/lib/inets/test/ftp_format_SUITE.erl
index 7ed94b9c61..9b71d2944b 100644
--- a/lib/inets/test/ftp_format_SUITE.erl
+++ b/lib/inets/test/ftp_format_SUITE.erl
@@ -22,7 +22,6 @@
-author('[email protected]').
-include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-include("ftp_internal.hrl").
%% Test server specific exports
diff --git a/lib/inets/test/ftp_suite_lib.erl b/lib/inets/test/ftp_suite_lib.erl
index 6d30f3aa62..f15fa2fa8d 100644
--- a/lib/inets/test/ftp_suite_lib.erl
+++ b/lib/inets/test/ftp_suite_lib.erl
@@ -22,8 +22,7 @@
-module(ftp_suite_lib).
--include_lib("test_server/include/test_server.hrl").
--include_lib("test_server/include/test_server_line.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("inets_test_lib.hrl").
%% Test server specific exports
diff --git a/lib/inets/test/httpc_cookie_SUITE.erl b/lib/inets/test/httpc_cookie_SUITE.erl
index 9a62bdb43f..2efca9a5c8 100644
--- a/lib/inets/test/httpc_cookie_SUITE.erl
+++ b/lib/inets/test/httpc_cookie_SUITE.erl
@@ -20,7 +20,7 @@
%%
-module(httpc_cookie_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
%% Test server specific exports
diff --git a/lib/inets/test/httpd_load.erl b/lib/inets/test/httpd_load.erl
index 39c2280f23..fef693d818 100644
--- a/lib/inets/test/httpd_load.erl
+++ b/lib/inets/test/httpd_load.erl
@@ -21,8 +21,7 @@
-module(httpd_load).
--include("test_server.hrl").
--include("test_server_line.hrl").
+-include_lib("common_test/include/ct.hrl").
%% General testcases bodies called from httpd_SUITE
-export([load_test/5]).
diff --git a/lib/inets/test/httpd_mod.erl b/lib/inets/test/httpd_mod.erl
index 847586a903..016989a22e 100644
--- a/lib/inets/test/httpd_mod.erl
+++ b/lib/inets/test/httpd_mod.erl
@@ -21,8 +21,7 @@
-module(httpd_mod).
--include("test_server.hrl").
--include("test_server_line.hrl").
+-include_lib("common_test/include/ct.hrl").
%% General testcases bodies called from httpd_SUITE
-export([alias/4, actions/4, security/5, auth/4, auth_api/6,
diff --git a/lib/inets/test/old_httpd_SUITE.erl b/lib/inets/test/old_httpd_SUITE.erl
index aaaf69fbec..f972f0f435 100644
--- a/lib/inets/test/old_httpd_SUITE.erl
+++ b/lib/inets/test/old_httpd_SUITE.erl
@@ -21,8 +21,7 @@
-module(old_httpd_SUITE).
--include_lib("test_server/include/test_server.hrl").
--include("test_server_line.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("inets_test_lib.hrl").
-include_lib("kernel/include/file.hrl").
diff --git a/lib/jinterface/test/jinterface_SUITE.erl b/lib/jinterface/test/jinterface_SUITE.erl
index 6d34a21209..5c4618dcde 100644
--- a/lib/jinterface/test/jinterface_SUITE.erl
+++ b/lib/jinterface/test/jinterface_SUITE.erl
@@ -46,7 +46,6 @@
]).
-include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-define(debug,true).
-ifdef(debug).
diff --git a/lib/jinterface/test/nc_SUITE.erl b/lib/jinterface/test/nc_SUITE.erl
index c5f3198c21..9910334749 100644
--- a/lib/jinterface/test/nc_SUITE.erl
+++ b/lib/jinterface/test/nc_SUITE.erl
@@ -21,7 +21,6 @@
-include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-define(VERSION_MAGIC, 131).
diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml
index 1bd52040a0..819da544c3 100644
--- a/lib/kernel/doc/src/code.xml
+++ b/lib/kernel/doc/src/code.xml
@@ -101,30 +101,6 @@
</section>
<section>
- <title>Code Path Cache</title>
- <p>The code server incorporates a code path cache. The cache
- functionality is disabled by default. To activate it, start
- the emulator with the command line flag <c>-code_path_cache</c>
- or call <c>code:rehash()</c>. When the cache is created (or
- updated), the code server searches for modules in the code path
- directories. This may take some time if the the code path is long.
- After the cache creation, the time for loading modules in a large
- system (one with a large directory structure) is significantly
- reduced compared to having the cache disabled. The code server
- is able to look up the location of a module from the cache in
- constant time instead of having to search through the code path
- directories.</p>
- <p>Application resource files (<c>.app</c> files) are also stored
- in the code path cache. This feature is used by the application
- controller (see
- <seealso marker="application">application(3)</seealso>) to load
- applications efficiently in large systems.</p>
- <p>Note that when the code path cache is created (or updated), any
- relative directory names in the code path are converted to
- absolute.</p>
- </section>
-
- <section>
<title>Loading of Code From Archive Files</title>
<warning><p>The support for loading of code from archive files is
@@ -334,6 +310,10 @@
<datatype>
<name name="load_error_rsn"/>
</datatype>
+ <datatype>
+ <name name="prepared_code"/>
+ <desc>An opaque term holding prepared code.</desc>
+ </datatype>
</datatypes>
<funcs>
@@ -503,6 +483,138 @@
</desc>
</func>
<func>
+ <name name="atomic_load" arity="1"/>
+ <fsummary>Load a list of modules atomically</fsummary>
+ <desc>
+ <p>Tries to load all of the modules in the list
+ <c><anno>Modules</anno></c> atomically. That means that
+ either all modules are loaded at the same time, or
+ none of the modules are loaded if there is a problem with any
+ of the modules.</p>
+ <p>Loading can fail for one the following reasons:</p>
+ <taglist>
+ <tag><c>badfile</c></tag>
+ <item>
+ <p>The object code has an incorrect format or the module
+ name in the object code is not the expected module name.</p>
+ </item>
+ <tag><c>nofile</c></tag>
+ <item>
+ <p>No file with object code exists.</p>
+ </item>
+ <tag><c>on_load_not_allowed</c></tag>
+ <item>
+ <p>A module contains an
+ <seealso marker="doc/reference_manual:code_loading#on_load">-on_load function</seealso>.</p>
+ </item>
+ <tag><c>duplicated</c></tag>
+ <item>
+ <p>A module is included more than once in
+ <c><anno>Modules</anno></c>.</p>
+ </item>
+ <tag><c>not_purged</c></tag>
+ <item>
+ <p>The object code can not be loaded because an old version
+ of the code already exists.</p>
+ </item>
+ <tag><c>sticky_directory</c></tag>
+ <item>
+ <p>The object code resides in a sticky directory.</p>
+ </item>
+ <tag><c>pending_on_load</c></tag>
+ <item>
+ <p>A previously loaded module contains an
+ <c>-on_load</c> function that never finished.</p>
+ </item>
+ </taglist>
+ <p>If it is important to minimize the time that an application
+ is inactive while changing code, use
+ <seealso marker="#prepare_loading/1">prepare_loading/1</seealso>
+ and
+ <seealso marker="#finish_loading/1">finish_loading/1</seealso>
+ instead of <c>atomic_load/1</c>. Here is an example:</p>
+<pre>
+{ok,Prepared} = code:prepare_loading(Modules),
+%% Put the application into an inactive state or do any
+%% other preparation needed before changing the code.
+ok = code:finish_loading(Prepared),
+%% Resume the application.</pre>
+ </desc>
+ </func>
+ <func>
+ <name name="prepare_loading" arity="1"/>
+ <fsummary>Prepare a list of modules atomically</fsummary>
+ <desc>
+ <p>Prepares to load the modules in the list
+ <c><anno>Modules</anno></c>.
+ Finish the loading by calling
+ <seealso marker="#finish_loading/1">finish_loading(Prepared)</seealso>.</p>
+ <p>This function can fail with one of the following error reasons:</p>
+ <taglist>
+ <tag><c>badfile</c></tag>
+ <item>
+ <p>The object code has an incorrect format or the module
+ name in the object code is not the expected module name.</p>
+ </item>
+ <tag><c>nofile</c></tag>
+ <item>
+ <p>No file with object code exists.</p>
+ </item>
+ <tag><c>on_load_not_allowed</c></tag>
+ <item>
+ <p>A module contains an
+ <seealso marker="doc/reference_manual:code_loading#on_load">-on_load function</seealso>.</p>
+ </item>
+ <tag><c>duplicated</c></tag>
+ <item>
+ <p>A module is included more than once in
+ <c><anno>Modules</anno></c>.</p>
+ </item>
+ </taglist>
+ </desc>
+ </func>
+ <func>
+ <name name="finish_loading" arity="1"/>
+ <fsummary>Finish loading a list of prepared modules atomically</fsummary>
+ <desc>
+ <p>Tries to load code for all modules that have been previously
+ prepared by
+ <seealso marker="#prepare_loading/1">prepare_loading/1</seealso>.
+ The loading occurs atomically, meaning that
+ either all modules are loaded at the same time, or
+ none of the modules are loaded.</p>
+ <p>This function can fail with one of the following error reasons:</p>
+ <taglist>
+ <tag><c>not_purged</c></tag>
+ <item>
+ <p>The object code can not be loaded because an old version
+ of the code already exists.</p>
+ </item>
+ <tag><c>sticky_directory</c></tag>
+ <item>
+ <p>The object code resides in a sticky directory.</p>
+ </item>
+ <tag><c>pending_on_load</c></tag>
+ <item>
+ <p>A previously loaded module contains an
+ <c>-on_load</c> function that never finished.</p>
+ </item>
+ </taglist>
+ </desc>
+ </func>
+ <func>
+ <name name="ensure_modules_loaded" arity="1"/>
+ <fsummary>Ensure that a list of modules is loaded</fsummary>
+ <desc>
+ <p>Tries to load any modules not already loaded in the list
+ <c><anno>Modules</anno></c> in the same way as
+ <seealso marker="#load_file/1">load_file/1</seealso>.</p>
+ <p>Returns <c>ok</c> if successful, or
+ <c>{error,[{Module,Reason}]}</c> if loading of some modules fails.
+ See <seealso marker="#error_reasons">Error Reasons for Code-Loading Functions</seealso> for a description of other possible error reasons.</p>
+ </desc>
+ </func>
+ <func>
<name name="delete" arity="1"/>
<fsummary>Removes current code for a module</fsummary>
<desc>
@@ -733,13 +845,6 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="rehash" arity="0"/>
- <fsummary>Rehash or create code path cache</fsummary>
- <desc>
- <p>This function creates or rehashes the code path cache.</p>
- </desc>
- </func>
- <func>
<name name="where_is_file" arity="1"/>
<fsummary>Full name of a file located in the code path</fsummary>
<desc>
@@ -747,10 +852,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
arbitrary type. If found, the full name is returned.
<c>non_existing</c> is returned if the file cannot be found.
The function can be useful, for example, to locate
- application resource files. If the code path cache is used,
- the code server will efficiently read the full name from
- the cache, provided that <c><anno>Filename</anno></c> is an object code
- file or an <c>.app</c> file.</p>
+ application resource files.</p>
</desc>
</func>
<func>
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index cf5777d4be..504f85abc2 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -623,8 +623,7 @@
Erlang/OTP has been ported to the realtime operating
system OSE. The port supports both smp and non-smp
emulator. For details around the port and how to started
- see the User's Guide in the <seealso
- marker="ose:ose_intro">ose</seealso> application. </p>
+ see the User's Guide in the ose application. </p>
<p>
Note that not all parts of Erlang/OTP has been ported. </p>
<p>
diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml
index 682d4a2eac..165160a909 100644
--- a/lib/kernel/doc/src/os.xml
+++ b/lib/kernel/doc/src/os.xml
@@ -37,6 +37,7 @@
use these functions can be of help in enabling a program to run on
most platforms.</p>
</description>
+
<funcs>
<func>
<name name="cmd" arity="1"/>
@@ -210,6 +211,30 @@ format_utc_timestamp() ->
</desc>
</func>
<func>
+ <name name="perf_counter" arity="0"/>
+ <fsummary>Returns a performance counter</fsummary>
+ <desc>
+ <p>Returns the current performance counter value in <c>perf_counter</c>
+ <seealso marker="erts:erlang#type_time_unit">time unit</seealso>.
+ This is a highly optimized call that might not be traceable.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="perf_counter" arity="1"/>
+ <fsummary>Returns a performance counter</fsummary>
+ <desc><p>Returns a performance counter that can be used as a very fast and
+ high resolution timestamp. This counter is read directly from the hardware or operating
+ system with the same guarantees. This means that two consecutive calls
+ to the function are not guaranteed to be monotonic, though it most likely will be.
+ The performance counter till be converted to the resolution passed as an argument.</p>
+ <pre>1> <input>T1 = os:perf_counter(1000),receive after 10000 -> ok end,T2 = os:perf_counter(1000).</input>
+176525861
+2> <input>T2 - T1.</input>
+10004</pre>
+ </desc>
+ </func>
+ <func>
<name name="type" arity="0"/>
<fsummary>Return the OS family and, in some cases, OS name of the current operating system</fsummary>
<desc>
diff --git a/lib/kernel/doc/src/ref_man.xml.src b/lib/kernel/doc/src/ref_man.xml.src
deleted file mode 100644
index 7eb48a5f1d..0000000000
--- a/lib/kernel/doc/src/ref_man.xml.src
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE application SYSTEM "application.dtd">
-
-<application xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1996</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Kernel Reference Manual</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The <em>Kernel</em> application has all the code necessary to run
- the Erlang runtime system itself: file servers and code servers
- and so on.</p>
- </description>
- <xi:include href="kernel_app.xml"/>
- <xi:include href="application.xml"/>
- <xi:include href="auth.xml"/>
- <xi:include href="code.xml"/>
- <xi:include href="disk_log.xml"/>
- <xi:include href="erl_boot_server.xml"/>
- <xi:include href="erl_ddll.xml"/>
- <xi:include href="erl_prim_loader_stub.xml"/>
- <xi:include href="erlang_stub.xml"/>
- <xi:include href="error_handler.xml"/>
- <xi:include href="error_logger.xml"/>
- <xi:include href="file.xml"/>
- <xi:include href="gen_tcp.xml"/>
- <xi:include href="gen_udp.xml"/>
- <xi:include href="gen_sctp.xml"/>
- <xi:include href="global.xml"/>
- <xi:include href="global_group.xml"/>
- <xi:include href="heart.xml"/>
- <xi:include href="inet.xml"/>
- <xi:include href="inet_res.xml"/>
- <xi:include href="init_stub.xml"/>
- <xi:include href="net_adm.xml"/>
- <xi:include href="net_kernel.xml"/>
- <xi:include href="os.xml"/>
- <xi:include href="pg2.xml"/>
- <xi:include href="rpc.xml"/>
- <xi:include href="seq_trace.xml"/>
- <xi:include href="user.xml"/>
- <xi:include href="wrap_log_reader.xml"/>
- <xi:include href="zlib_stub.xml"/>
- <xi:include href="app.xml"/>
- <xi:include href="config.xml"/>
-</application>
diff --git a/lib/kernel/doc/src/seq_trace.xml b/lib/kernel/doc/src/seq_trace.xml
index f4fcd222ec..857444e338 100644
--- a/lib/kernel/doc/src/seq_trace.xml
+++ b/lib/kernel/doc/src/seq_trace.xml
@@ -150,13 +150,13 @@ seq_trace:set_token(OldToken), % activate the trace token again
format and value as produced by
<c>erlang:monotonic_time(nano_seconds)</c>.</p>
</item>
+ </taglist>
<p>If multiple timestamp flags are passed, <c>timestamp</c> has
precedence over <c>strict_monotonic_timestamp</c> which
in turn has precedence over <c>monotonic_timestamp</c>. All
timestamp flags are remembered, so if two are passed
and the one with highest precedence later is disabled
the other one will become active.</p>
- </taglist>
</desc>
</func>
<func>
diff --git a/lib/kernel/include/file.hrl b/lib/kernel/include/file.hrl
index 7cf033f7f5..36112bb040 100644
--- a/lib/kernel/include/file.hrl
+++ b/lib/kernel/include/file.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1997-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.
@@ -23,37 +23,40 @@
%%--------------------------------------------------------------------------
-record(file_info,
- {size :: non_neg_integer(), % Size of file in bytes.
- type :: 'device' | 'directory' | 'other' | 'regular' | 'symlink',
- access :: 'read' | 'write' | 'read_write' | 'none',
- atime :: file:date_time() | non_neg_integer(),
+ {size :: non_neg_integer() | 'undefined', % Size of file in bytes.
+ type :: 'device' | 'directory' | 'other' | 'regular' | 'symlink'
+ | 'undefined',
+ access :: 'read' | 'write' | 'read_write' | 'none' | 'undefined',
+ atime :: file:date_time() | non_neg_integer() | 'undefined',
% The local time the file was last read:
% {{Year, Mon, Day}, {Hour, Min, Sec}}.
% atime, ctime, mtime may also be unix epochs()
- mtime :: file:date_time() | non_neg_integer(),
+ mtime :: file:date_time() | non_neg_integer() | 'undefined',
% The local time the file was last written.
- ctime :: file:date_time() | non_neg_integer(),
+ ctime :: file:date_time() | non_neg_integer() | 'undefined',
% The interpretation of this time field
% is dependent on operating system.
% On Unix it is the last time the file
% or the inode was changed. On Windows,
% it is the creation time.
- mode :: non_neg_integer(), % File permissions. On Windows,
+ mode :: non_neg_integer() | 'undefined',
+ % File permissions. On Windows,
% the owner permissions will be
% duplicated for group and user.
- links :: non_neg_integer(),
+ links :: non_neg_integer() | 'undefined',
% Number of links to the file (1 if the
% filesystem doesn't support links).
- major_device :: non_neg_integer(),
+ major_device :: non_neg_integer() | 'undefined',
% Identifies the file system (Unix),
% or the drive number (A: = 0, B: = 1)
% (Windows).
%% The following are Unix specific.
%% They are set to zero on other operating systems.
- minor_device :: non_neg_integer(), % Only valid for devices.
- inode :: non_neg_integer(), % Inode number for file.
- uid :: non_neg_integer(), % User id for owner.
- gid :: non_neg_integer()}). % Group id for owner.
+ minor_device :: non_neg_integer() | 'undefined',
+ % Only valid for devices.
+ inode :: non_neg_integer() | 'undefined', % Inode number for file.
+ uid :: non_neg_integer() | 'undefined', % User id for owner.
+ gid :: non_neg_integer() | 'undefined'}). % Group id for owner.
-record(file_descriptor,
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index 7237550786..0882cb170c 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -28,11 +28,15 @@
get_path/0,
load_file/1,
ensure_loaded/1,
+ ensure_modules_loaded/1,
load_abs/1,
load_abs/2,
load_binary/3,
load_native_partial/2,
load_native_sticky/3,
+ atomic_load/1,
+ prepare_loading/1,
+ finish_loading/1,
delete/1,
purge/1,
soft_purge/1,
@@ -60,7 +64,7 @@
del_path/1,
replace_path/2,
rehash/0,
- start_link/0, start_link/1,
+ start_link/0,
which/1,
where_is_file/1,
where_is_file/2,
@@ -68,7 +72,10 @@
clash/0,
get_mode/0]).
+-deprecated({rehash,0,next_major_release}).
+
-export_type([load_error_rsn/0, load_ret/0]).
+-export_type([prepared_code/0]).
-include_lib("kernel/include/file.hrl").
@@ -86,6 +93,11 @@
-type loaded_ret_atoms() :: 'cover_compiled' | 'preloaded'.
-type loaded_filename() :: (Filename :: file:filename()) | loaded_ret_atoms().
+-define(PREPARED, '$prepared$').
+-opaque prepared_code() ::
+ {?PREPARED,[{module(),{binary(),string(),_}}]}.
+
+
%%% BIFs
-export([get_chunk/2, is_module_native/1, make_stub_module/3, module_md5/1]).
@@ -294,23 +306,328 @@ replace_path(Name, Dir) when (is_atom(Name) orelse is_list(Name)),
call({replace_path,Name,Dir}).
-spec rehash() -> 'ok'.
-rehash() -> call(rehash).
+rehash() ->
+ cache_warning(),
+ ok.
-spec get_mode() -> 'embedded' | 'interactive'.
get_mode() -> call(get_mode).
+%%%
+%%% Loading of several modules in parallel.
+%%%
+
+-spec ensure_modules_loaded([Module]) ->
+ 'ok' | {'error',[{Module,What}]} when
+ Module :: module(),
+ What :: badfile | nofile | on_load_failure.
+
+ensure_modules_loaded(Modules) when is_list(Modules) ->
+ case prepare_ensure(Modules, []) of
+ Ms when is_list(Ms) ->
+ ensure_modules_loaded_1(Ms);
+ error ->
+ error(function_clause, [Modules])
+ end.
+
+ensure_modules_loaded_1(Ms0) ->
+ Ms = lists:usort(Ms0),
+ {Prep,Error0} = load_mods(Ms),
+ {OnLoad,Normal} = partition_on_load(Prep),
+ Error1 = case finish_loading(Normal, true) of
+ ok -> Error0;
+ {error,Err} -> Err ++ Error0
+ end,
+ ensure_modules_loaded_2(OnLoad, Error1).
+
+ensure_modules_loaded_2([{M,_}|Ms], Errors) ->
+ case ensure_loaded(M) of
+ {module,M} ->
+ ensure_modules_loaded_2(Ms, Errors);
+ {error,Err} ->
+ ensure_modules_loaded_2(Ms, [{M,Err}|Errors])
+ end;
+ensure_modules_loaded_2([], []) ->
+ ok;
+ensure_modules_loaded_2([], [_|_]=Errors) ->
+ {error,Errors}.
+
+prepare_ensure([M|Ms], Acc) when is_atom(M) ->
+ case erlang:module_loaded(M) of
+ true ->
+ prepare_ensure(Ms, Acc);
+ false ->
+ prepare_ensure(Ms, [M|Acc])
+ end;
+prepare_ensure([], Acc) ->
+ Acc;
+prepare_ensure(_, _) ->
+ error.
+
+-spec atomic_load(Modules) -> 'ok' | {'error',[{Module,What}]} when
+ Modules :: [Module | {Module, Filename, Binary}],
+ Module :: module(),
+ Filename :: file:filename(),
+ Binary :: binary(),
+ What :: 'badfile' | 'nofile' | 'on_load_not_allowed' | 'duplicated' |
+ 'not_purged' | 'sticky_directory' | 'pending_on_load'.
+
+atomic_load(Modules) ->
+ case do_prepare_loading(Modules) of
+ {ok,Prep} ->
+ finish_loading(Prep, false);
+ {error,_}=Error ->
+ Error;
+ badarg ->
+ error(function_clause, [Modules])
+ end.
+
+-spec prepare_loading(Modules) ->
+ {'ok',Prepared} | {'error',[{Module,What}]} when
+ Modules :: [Module | {Module, Filename, Binary}],
+ Module :: module(),
+ Filename :: file:filename(),
+ Binary :: binary(),
+ Prepared :: prepared_code(),
+ What :: 'badfile' | 'nofile' | 'on_load_not_allowed' | 'duplicated'.
+
+prepare_loading(Modules) ->
+ case do_prepare_loading(Modules) of
+ {ok,Prep} ->
+ {ok,{?PREPARED,Prep}};
+ {error,_}=Error ->
+ Error;
+ badarg ->
+ error(function_clause, [Modules])
+ end.
+
+-spec finish_loading(Prepared) -> 'ok' | {'error',[{Module,What}]} when
+ Prepared :: prepared_code(),
+ Module :: module(),
+ What :: 'not_purged' | 'sticky_directory' | 'pending_on_load'.
+
+finish_loading({?PREPARED,Prepared}=Arg) when is_list(Prepared) ->
+ case verify_prepared(Prepared) of
+ ok ->
+ finish_loading(Prepared, false);
+ error ->
+ error(function_clause, [Arg])
+ end.
+
+partition_load([Item|T], Bs, Ms) ->
+ case Item of
+ {M,File,Bin} when is_atom(M) andalso
+ is_list(File) andalso
+ is_binary(Bin) ->
+ partition_load(T, [Item|Bs], Ms);
+ M when is_atom(M) ->
+ partition_load(T, Bs, [Item|Ms]);
+ _ ->
+ error
+ end;
+partition_load([], Bs, Ms) ->
+ {Bs,Ms}.
+
+do_prepare_loading(Modules) ->
+ case partition_load(Modules, [], []) of
+ {ModBins,Ms} ->
+ case prepare_loading_1(ModBins, Ms) of
+ {error,_}=Error ->
+ Error;
+ Prep when is_list(Prep) ->
+ {ok,Prep}
+ end;
+ error ->
+ badarg
+ end.
+
+prepare_loading_1(ModBins, Ms) ->
+ %% erlang:finish_loading/1 *will* detect duplicates.
+ %% However, we want to detect all errors that can be detected
+ %% by only examining the input data before call the LastAction
+ %% fun.
+ case prepare_check_uniq(ModBins, Ms) of
+ ok ->
+ prepare_loading_2(ModBins, Ms);
+ Error ->
+ Error
+ end.
+
+prepare_loading_2(ModBins, Ms) ->
+ {Prep0,Error0} = load_bins(ModBins),
+ {Prep1,Error1} = load_mods(Ms),
+ case Error0 ++ Error1 of
+ [] ->
+ prepare_loading_3(Prep0 ++ Prep1);
+ [_|_]=Error ->
+ {error,Error}
+ end.
+
+prepare_loading_3(Prep) ->
+ case partition_on_load(Prep) of
+ {[_|_]=OnLoad,_} ->
+ Error = [{M,on_load_not_allowed} || {M,_} <- OnLoad],
+ {error,Error};
+ {[],_} ->
+ Prep
+ end.
+
+prepare_check_uniq([{M,_,_}|T], Ms) ->
+ prepare_check_uniq(T, [M|Ms]);
+prepare_check_uniq([], Ms) ->
+ prepare_check_uniq_1(lists:sort(Ms), []).
+
+prepare_check_uniq_1([M|[M|_]=Ms], Acc) ->
+ prepare_check_uniq_1(Ms, [{M,duplicated}|Acc]);
+prepare_check_uniq_1([_|Ms], Acc) ->
+ prepare_check_uniq_1(Ms, Acc);
+prepare_check_uniq_1([], []) ->
+ ok;
+prepare_check_uniq_1([], [_|_]=Errors) ->
+ {error,Errors}.
+
+partition_on_load(Prep) ->
+ P = fun({_,{Bin,_,_}}) ->
+ erlang:has_prepared_code_on_load(Bin)
+ end,
+ lists:partition(P, Prep).
+
+verify_prepared([{M,{Prep,Name,_Native}}|T])
+ when is_atom(M), is_binary(Prep), is_list(Name) ->
+ try erlang:has_prepared_code_on_load(Prep) of
+ false ->
+ verify_prepared(T);
+ _ ->
+ error
+ catch
+ error:_ ->
+ error
+ end;
+verify_prepared([]) ->
+ ok;
+verify_prepared(_) ->
+ error.
+
+finish_loading(Prepared0, EnsureLoaded) ->
+ Prepared = [{M,{Bin,File}} || {M,{Bin,File,_}} <- Prepared0],
+ Native0 = [{M,Code} || {M,{_,_,Code}} <- Prepared0,
+ Code =/= undefined],
+ case call({finish_loading,Prepared,EnsureLoaded}) of
+ ok ->
+ finish_loading_native(Native0);
+ {error,Errors}=E when EnsureLoaded ->
+ S0 = sofs:relation(Errors),
+ S1 = sofs:domain(S0),
+ R0 = sofs:relation(Native0),
+ R1 = sofs:drestriction(R0, S1),
+ Native = sofs:to_external(R1),
+ finish_loading_native(Native),
+ E;
+ {error,_}=E ->
+ E
+ end.
+
+finish_loading_native([{Mod,Code}|Ms]) ->
+ _ = load_native_partial(Mod, Code),
+ finish_loading_native(Ms);
+finish_loading_native([]) ->
+ ok.
+
+load_mods([]) ->
+ {[],[]};
+load_mods(Mods) ->
+ Path = get_path(),
+ F = prepare_loading_fun(),
+ {ok,{Succ,Error0}} = erl_prim_loader:get_modules(Mods, F, Path),
+ Error = [case E of
+ badfile -> {M,E};
+ _ -> {M,nofile}
+ end || {M,E} <- Error0],
+ {Succ,Error}.
+
+load_bins([]) ->
+ {[],[]};
+load_bins(BinItems) ->
+ F = prepare_loading_fun(),
+ do_par(F, BinItems).
+
+-type prep_fun_type() :: fun((module(), file:filename(), binary()) ->
+ {ok,_} | {error,_}).
+
+-spec prepare_loading_fun() -> prep_fun_type().
+
+prepare_loading_fun() ->
+ GetNative = get_native_fun(),
+ fun(Mod, FullName, Beam) ->
+ case erlang:prepare_loading(Mod, Beam) of
+ Prepared when is_binary(Prepared) ->
+ {ok,{Prepared,FullName,GetNative(Beam)}};
+ {error,_}=Error ->
+ Error
+ end
+ end.
+
+get_native_fun() ->
+ Architecture = erlang:system_info(hipe_architecture),
+ try hipe_unified_loader:chunk_name(Architecture) of
+ ChunkTag ->
+ fun(Beam) -> code:get_chunk(Beam, ChunkTag) end
+ catch _:_ ->
+ fun(_) -> undefined end
+ end.
+
+do_par(Fun, L) ->
+ {_,Ref} = spawn_monitor(do_par_fun(Fun, L)),
+ receive
+ {'DOWN',Ref,process,_,Res} ->
+ Res
+ end.
+
+-spec do_par_fun(prep_fun_type(), list()) -> fun(() -> no_return()).
+
+do_par_fun(Fun, L) ->
+ fun() ->
+ _ = [spawn_monitor(do_par_fun_2(Fun, Item)) ||
+ Item <- L],
+ exit(do_par_recv(length(L), [], []))
+ end.
+
+-spec do_par_fun_2(prep_fun_type(),
+ {module(),file:filename(),binary()}) ->
+ fun(() -> no_return()).
+
+do_par_fun_2(Fun, Item) ->
+ fun() ->
+ {Mod,Filename,Bin} = Item,
+ try Fun(Mod, Filename, Bin) of
+ {ok,Res} ->
+ exit({good,{Mod,Res}});
+ {error,Error} ->
+ exit({bad,{Mod,Error}})
+ catch
+ _:Error ->
+ exit({bad,{Mod,Error}})
+ end
+ end.
+
+do_par_recv(0, Good, Bad) ->
+ {Good,Bad};
+do_par_recv(N, Good, Bad) ->
+ receive
+ {'DOWN',_,process,_,{good,Res}} ->
+ do_par_recv(N-1, [Res|Good], Bad);
+ {'DOWN',_,process,_,{bad,Res}} ->
+ do_par_recv(N-1, Good, [Res|Bad])
+ end.
+
%%-----------------------------------------------------------------
call(Req) ->
- code_server:call(code_server, Req).
+ code_server:call(Req).
-spec start_link() -> {'ok', pid()} | {'error', 'crash'}.
start_link() ->
- start_link([stick]).
-
--spec start_link(Flags :: [atom()]) -> {'ok', pid()} | {'error', 'crash'}.
-start_link(Flags) ->
- do_start(Flags).
+ do_start().
%%-----------------------------------------------------------------
%% In the init phase, code must not use any modules not yet loaded,
@@ -322,35 +639,21 @@ start_link(Flags) ->
%% us, so the module is loaded.
%%-----------------------------------------------------------------
-do_start(Flags) ->
+do_start() ->
+ maybe_warn_for_cache(),
load_code_server_prerequisites(),
- Mode = get_mode(Flags),
- case init:get_argument(root) of
- {ok,[[Root0]]} ->
- Root = filename:join([Root0]), % Normalize. Use filename
- case code_server:start_link([Root,Mode]) of
- {ok,_Pid} = Ok2 ->
- if
- Mode =:= interactive ->
- case lists:member(stick, Flags) of
- true -> do_stick_dirs();
- _ -> ok
- end;
- true ->
- ok
- end,
- %% Quietly load native code for all modules loaded so far
- Architecture = erlang:system_info(hipe_architecture),
- load_native_code_for_all_loaded(Architecture),
- Ok2;
- Other ->
- Other
- end;
- Other ->
- error_logger:error_msg("Can not start code server ~w ~n", [Other]),
- {error, crash}
- end.
+ {ok,[[Root0]]} = init:get_argument(root),
+ Mode = start_get_mode(),
+ Root = filename:join([Root0]), % Normalize.
+ Res = code_server:start_link([Root,Mode]),
+
+ maybe_stick_dirs(Mode),
+
+ %% Quietly load native code for all modules loaded so far.
+ Architecture = erlang:system_info(hipe_architecture),
+ load_native_code_for_all_loaded(Architecture),
+ Res.
%% Make sure that all modules that the code_server process calls
%% (directly or indirectly) are loaded. Otherwise the code_server
@@ -370,6 +673,16 @@ load_code_server_prerequisites() ->
_ = [M = M:module_info(module) || M <- Needed],
ok.
+maybe_stick_dirs(interactive) ->
+ case init:get_argument(nostick) of
+ {ok,[[]]} ->
+ ok;
+ _ ->
+ do_stick_dirs()
+ end;
+maybe_stick_dirs(_) ->
+ ok.
+
do_stick_dirs() ->
do_s(compiler),
do_s(stdlib),
@@ -387,19 +700,12 @@ do_s(Lib) ->
ok
end.
-get_mode(Flags) ->
- case lists:member(embedded, Flags) of
- true ->
+start_get_mode() ->
+ case init:get_argument(mode) of
+ {ok,[["embedded"]]} ->
embedded;
- _Otherwise ->
- case init:get_argument(mode) of
- {ok,[["embedded"]]} ->
- embedded;
- {ok,[["minimal"]]} ->
- minimal;
- _Else ->
- interactive
- end
+ _ ->
+ interactive
end.
%% Find out which version of a particular module we would
@@ -453,30 +759,14 @@ which(File, Base, [Directory|Tail]) ->
Filename :: file:filename(),
Absname :: file:filename().
where_is_file(File) when is_list(File) ->
- case call({is_cached,File}) of
- no ->
- Path = get_path(),
- which(File, ".", Path);
- Dir ->
- filename:join(Dir, File)
- end.
+ Path = get_path(),
+ which(File, ".", Path).
-spec where_is_file(Path :: file:filename(), Filename :: file:filename()) ->
file:filename() | 'non_existing'.
where_is_file(Path, File) when is_list(Path), is_list(File) ->
- CodePath = get_path(),
- if
- Path =:= CodePath ->
- case call({is_cached, File}) of
- no ->
- which(File, ".", Path);
- Dir ->
- filename:join(Dir, File)
- end;
- true ->
- which(File, ".", Path)
- end.
+ which(File, ".", Path).
-spec set_primary_archive(ArchiveFile :: file:filename(),
ArchiveBin :: binary(),
@@ -554,6 +844,22 @@ has_ext(Ext, Extlen, File) ->
end.
%%%
+%%% Warning for deprecated code path cache.
+%%%
+
+maybe_warn_for_cache() ->
+ case init:get_argument(code_path_cache) of
+ {ok, _} ->
+ cache_warning();
+ error ->
+ ok
+ end.
+
+cache_warning() ->
+ W = "The code path cache functionality has been removed",
+ error_logger:warning_report(W).
+
+%%%
%%% Silently load native code for all modules loaded so far.
%%%
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index 614219794c..6262407354 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -22,29 +22,28 @@
%% This file holds the server part of the code_server.
-export([start_link/1,
- call/2,
- system_continue/3,
- system_terminate/4,
+ call/1,
system_code_change/4,
error_msg/2, info_msg/2
]).
-include_lib("kernel/include/file.hrl").
+-include_lib("stdlib/include/ms_transform.hrl").
-import(lists, [foreach/2]).
--define(ANY_NATIVE_CODE_LOADED, any_native_code_loaded).
+-type on_load_item() :: {reference(),module(),file:name_all(),[pid()]}.
--record(state, {supervisor,
- root,
- path,
- moddb,
- namedb,
- cache = no_cache,
- mode = interactive,
- on_load = []}).
+-record(state, {supervisor :: pid(),
+ root :: file:name_all(),
+ path :: [file:name_all()],
+ moddb :: ets:tab(),
+ namedb :: ets:tab(),
+ mode = interactive :: 'interactive' | 'embedded',
+ on_load = [] :: [on_load_item()]}).
-type state() :: #state{}.
+-spec start_link([term()]) -> {'ok', pid()}.
start_link(Args) ->
Ref = make_ref(),
Parent = self(),
@@ -59,7 +58,7 @@ start_link(Args) ->
%% Init the code_server process.
%% -----------------------------------------------------------
-init(Ref, Parent, [Root,Mode0]) ->
+init(Ref, Parent, [Root,Mode]) ->
register(?MODULE, self()),
process_flag(trap_exit, true),
@@ -70,12 +69,6 @@ init(Ref, Parent, [Root,Mode0]) ->
end, erlang:pre_loaded()),
ets:insert(Db, init:fetch_loaded()),
- Mode =
- case Mode0 of
- minimal -> interactive;
- _ -> Mode0
- end,
-
IPath =
case Mode of
interactive ->
@@ -89,24 +82,15 @@ init(Ref, Parent, [Root,Mode0]) ->
end,
Path = add_loader_path(IPath, Mode),
- State0 = #state{root = Root,
- path = Path,
- moddb = Db,
- namedb = init_namedb(Path),
- mode = Mode},
-
- State =
- case init:get_argument(code_path_cache) of
- {ok, _} ->
- create_cache(State0);
- error ->
- State0
- end,
-
- put(?ANY_NATIVE_CODE_LOADED, false),
+ State = #state{supervisor = Parent,
+ root = Root,
+ path = Path,
+ moddb = Db,
+ namedb = init_namedb(Path),
+ mode = Mode},
Parent ! {Ref,{ok,self()}},
- loop(State#state{supervisor = Parent}).
+ loop(State).
get_user_lib_dirs() ->
case os:getenv("ERL_LIBS") of
@@ -142,8 +126,9 @@ split_paths([C|T], S, Path, Paths) ->
split_paths([], _S, Path, Paths) ->
lists:reverse(Paths, [lists:reverse(Path)]).
-call(Name, Req) ->
- Name ! {code_call, self(), Req},
+-spec call(term()) -> term().
+call(Req) ->
+ ?MODULE ! {code_call, self(), Req},
receive
{?MODULE, Reply} ->
Reply
@@ -255,59 +240,33 @@ handle_call({dir,Dir}, {_From,_Tag}, S) ->
Resp = do_dir(Root,Dir,S#state.namedb),
{reply,Resp,S};
-handle_call({load_file,Mod}, Caller, St) ->
- case modp(Mod) of
- false ->
- {reply,{error,badarg},St};
- true ->
- load_file(Mod, Caller, St)
- end;
+handle_call({load_file,Mod}, Caller, St) when is_atom(Mod) ->
+ load_file(Mod, Caller, St);
handle_call({add_path,Where,Dir0}, {_From,_Tag},
- #state{cache=Cache0,namedb=Namedb,path=Path0}=S) ->
- case Cache0 of
- no_cache ->
- {Resp,Path} = add_path(Where, Dir0, Path0, Namedb),
- {reply,Resp,S#state{path=Path}};
- _ ->
- Dir = absname(Dir0), %% Cache always expands the path
- {Resp,Path} = add_path(Where, Dir, Path0, Namedb),
- Cache = update_cache([Dir], Where, Cache0),
- {reply,Resp,S#state{path=Path,cache=Cache}}
- end;
+ #state{namedb=Namedb,path=Path0}=S) ->
+ {Resp,Path} = add_path(Where, Dir0, Path0, Namedb),
+ {reply,Resp,S#state{path=Path}};
handle_call({add_paths,Where,Dirs0}, {_From,_Tag},
- #state{cache=Cache0,namedb=Namedb,path=Path0}=S) ->
- case Cache0 of
- no_cache ->
- {Resp,Path} = add_paths(Where, Dirs0, Path0, Namedb),
- {reply,Resp,S#state{path=Path}};
- _ ->
- %% Cache always expands the path
- Dirs = [absname(Dir) || Dir <- Dirs0],
- {Resp,Path} = add_paths(Where, Dirs, Path0, Namedb),
- Cache=update_cache(Dirs,Where,Cache0),
- {reply,Resp,S#state{cache=Cache,path=Path}}
- end;
+ #state{namedb=Namedb,path=Path0}=S) ->
+ {Resp,Path} = add_paths(Where, Dirs0, Path0, Namedb),
+ {reply,Resp,S#state{path=Path}};
handle_call({set_path,PathList}, {_From,_Tag},
#state{path=Path0,namedb=Namedb}=S) ->
{Resp,Path,NewDb} = set_path(PathList, Path0, Namedb),
- {reply,Resp,rehash_cache(S#state{path=Path,namedb=NewDb})};
+ {reply,Resp,S#state{path=Path,namedb=NewDb}};
handle_call({del_path,Name}, {_From,_Tag},
#state{path=Path0,namedb=Namedb}=S) ->
{Resp,Path} = del_path(Name, Path0, Namedb),
- {reply,Resp,rehash_cache(S#state{path=Path})};
+ {reply,Resp,S#state{path=Path}};
handle_call({replace_path,Name,Dir}, {_From,_Tag},
#state{path=Path0,namedb=Namedb}=S) ->
{Resp,Path} = replace_path(Name, Dir, Path0, Namedb),
- {reply,Resp,rehash_cache(S#state{path=Path})};
-
-handle_call(rehash, {_From,_Tag}, S0) ->
- S = create_cache(S0),
- {reply,ok,S};
+ {reply,Resp,S#state{path=Path}};
handle_call(get_path, {_From,_Tag}, S) ->
{reply,S#state.path,S};
@@ -321,75 +280,60 @@ handle_call({load_abs,File,Mod}, Caller, S) when is_atom(Mod) ->
load_abs(File, Mod, Caller, S)
end;
-handle_call({load_binary,Mod,File,Bin}, Caller, S) ->
+handle_call({load_binary,Mod,File,Bin}, Caller, S) when is_atom(Mod) ->
do_load_binary(Mod, File, Bin, Caller, S);
handle_call({load_native_partial,Mod,Bin}, {_From,_Tag}, S) ->
Architecture = erlang:system_info(hipe_architecture),
Result = (catch hipe_unified_loader:load(Mod, Bin, Architecture)),
- Status = hipe_result_to_status(Result),
+ Status = hipe_result_to_status(Result, S),
{reply,Status,S};
handle_call({load_native_sticky,Mod,Bin,WholeModule}, {_From,_Tag}, S) ->
Architecture = erlang:system_info(hipe_architecture),
Result = (catch hipe_unified_loader:load_module(Mod, Bin, WholeModule,
Architecture)),
- Status = hipe_result_to_status(Result),
+ Status = hipe_result_to_status(Result, S),
{reply,Status,S};
-handle_call({ensure_loaded,Mod0}, Caller, St0) ->
- Fun = fun (M, St) ->
- case erlang:module_loaded(M) of
- true ->
- {reply,{module,M},St};
- false when St#state.mode =:= interactive ->
- load_file(M, Caller, St);
- false ->
- {reply,{error,embedded},St}
- end
- end,
- do_mod_call(Fun, Mod0, {error,badarg}, St0);
-
-handle_call({delete,Mod0}, {_From,_Tag}, S) ->
- Fun = fun (M, St) ->
- case catch erlang:delete_module(M) of
- true ->
- ets:delete(St#state.moddb, M),
- {reply,true,St};
- _ ->
- {reply,false,St}
- end
- end,
- do_mod_call(Fun, Mod0, false, S);
+handle_call({ensure_loaded,Mod}, Caller, St) when is_atom(Mod) ->
+ case erlang:module_loaded(Mod) of
+ true ->
+ {reply,{module,Mod},St};
+ false when St#state.mode =:= interactive ->
+ load_file(Mod, Caller, St);
+ false ->
+ {reply,{error,embedded},St}
+ end;
+
+handle_call({delete,Mod}, {_From,_Tag}, St) when is_atom(Mod) ->
+ case catch erlang:delete_module(Mod) of
+ true ->
+ ets:delete(St#state.moddb, Mod),
+ {reply,true,St};
+ _ ->
+ {reply,false,St}
+ end;
-handle_call({purge,Mod0}, {_From,_Tag}, St0) ->
- do_mod_call(fun (M, St) ->
- {reply,do_purge(M),St}
- end, Mod0, false, St0);
+handle_call({purge,Mod}, {_From,_Tag}, St) when is_atom(Mod) ->
+ {reply,do_purge(Mod),St};
-handle_call({soft_purge,Mod0}, {_From,_Tag}, St0) ->
- do_mod_call(fun (M, St) ->
- {reply,do_soft_purge(M),St}
- end, Mod0, true, St0);
+handle_call({soft_purge,Mod}, {_From,_Tag}, St) when is_atom(Mod) ->
+ {reply,do_soft_purge(Mod),St};
-handle_call({is_loaded,Mod0}, {_From,_Tag}, St0) ->
- do_mod_call(fun (M, St) ->
- {reply,is_loaded(M, St#state.moddb),St}
- end, Mod0, false, St0);
+handle_call({is_loaded,Mod}, {_From,_Tag}, St) when is_atom(Mod) ->
+ {reply,is_loaded(Mod, St#state.moddb),St};
handle_call(all_loaded, {_From,_Tag}, S) ->
Db = S#state.moddb,
{reply,all_loaded(Db),S};
-handle_call({get_object_code,Mod0}, {_From,_Tag}, St0) ->
- Fun = fun(M, St) ->
- Path = St#state.path,
- case mod_to_bin(Path, atom_to_list(M)) of
- {_,Bin,FName} -> {reply,{M,Bin,FName},St};
- Error -> {reply,Error,St}
- end
- end,
- do_mod_call(Fun, Mod0, error, St0);
+handle_call({get_object_code,Mod}, {_From,_Tag}, St) when is_atom(Mod) ->
+ Path = St#state.path,
+ case mod_to_bin(Path, Mod) of
+ {_,Bin,FName} -> {reply,{Mod,Bin,FName},St};
+ Error -> {reply,Error,St}
+ end;
handle_call({is_sticky, Mod}, {_From,_Tag}, S) ->
Db = S#state.moddb,
@@ -398,9 +342,6 @@ handle_call({is_sticky, Mod}, {_From,_Tag}, S) ->
handle_call(stop,{_From,_Tag}, S) ->
{stop,normal,stopped,S};
-handle_call({is_cached,_File}, {_From,_Tag}, S=#state{cache=no_cache}) ->
- {reply, no, S};
-
handle_call({set_primary_archive, File, ArchiveBin, FileInfo, ParserFun}, {_From,_Tag}, S=#state{mode=Mode}) ->
case erl_prim_loader:set_primary_archive(File, ArchiveBin, FileInfo, ParserFun) of
{ok, Files} ->
@@ -409,107 +350,16 @@ handle_call({set_primary_archive, File, ArchiveBin, FileInfo, ParserFun}, {_From
{reply, Error, S}
end;
-handle_call({is_cached,File}, {_From,_Tag}, S=#state{cache=Cache}) ->
- ObjExt = objfile_extension(),
- Ext = filename:extension(File),
- Type = case Ext of
- ObjExt -> obj;
- ".app" -> app;
- _ -> undef
- end,
- if Type =:= undef ->
- {reply, no, S};
- true ->
- Key = {Type,list_to_atom(filename:rootname(File, Ext))},
- case ets:lookup(Cache, Key) of
- [] ->
- {reply, no, S};
- [{Key,Dir}] ->
- {reply, Dir, S}
- end
- end;
-
handle_call(get_mode, {_From,_Tag}, S=#state{mode=Mode}) ->
{reply, Mode, S};
+handle_call({finish_loading,Prepared,EnsureLoaded}, {_,_}, S) ->
+ {reply,finish_loading(Prepared, EnsureLoaded, S),S};
+
handle_call(Other,{_From,_Tag}, S) ->
error_msg(" ** Codeserver*** ignoring ~w~n ",[Other]),
{noreply,S}.
-do_mod_call(Action, Module, _Error, St) when is_atom(Module) ->
- Action(Module, St);
-do_mod_call(Action, Module, Error, St) ->
- try list_to_atom(Module) of
- Atom when is_atom(Atom) ->
- Action(Atom, St)
- catch
- error:badarg ->
- {reply,Error,St}
- end.
-
-%% --------------------------------------------------------------
-%% Cache functions
-%% --------------------------------------------------------------
-
-create_cache(St = #state{cache = no_cache}) ->
- Cache = ets:new(code_cache, [protected]),
- rehash_cache(Cache, St);
-create_cache(St) ->
- rehash_cache(St).
-
-rehash_cache(St = #state{cache = no_cache}) ->
- St;
-rehash_cache(St = #state{cache = OldCache}) ->
- ets:delete(OldCache),
- Cache = ets:new(code_cache, [protected]),
- rehash_cache(Cache, St).
-
-rehash_cache(Cache, St = #state{path = Path}) ->
- Exts = [{obj,objfile_extension()}, {app,".app"}],
- {Cache,NewPath} = locate_mods(lists:reverse(Path), first, Exts, Cache, []),
- St#state{cache = Cache, path=NewPath}.
-
-update_cache(Dirs, Where, Cache0) ->
- Exts = [{obj,objfile_extension()}, {app,".app"}],
- {Cache, _} = locate_mods(Dirs, Where, Exts, Cache0, []),
- Cache.
-
-locate_mods([Dir0|Path], Where, Exts, Cache, Acc) ->
- Dir = absname(Dir0), %% Cache always expands the path
- case erl_prim_loader:list_dir(Dir) of
- {ok, Files} ->
- Cache = filter_mods(Files, Where, Exts, Dir, Cache),
- locate_mods(Path, Where, Exts, Cache, [Dir|Acc]);
- error ->
- locate_mods(Path, Where, Exts, Cache, Acc)
- end;
-locate_mods([], _, _, Cache, Path) ->
- {Cache,Path}.
-
-filter_mods([File|Rest], Where, Exts, Dir, Cache) ->
- Ext = filename:extension(File),
- Root = list_to_atom(filename:rootname(File, Ext)),
- case lists:keyfind(Ext, 2, Exts) of
- {Type, _} ->
- Key = {Type,Root},
- case Where of
- first ->
- true = ets:insert(Cache, {Key,Dir});
- last ->
- case ets:lookup(Cache, Key) of
- [] ->
- true = ets:insert(Cache, {Key,Dir});
- _ ->
- ignore
- end
- end;
- false ->
- ok
- end,
- filter_mods(Rest, Where, Exts, Dir, Cache);
-filter_mods([], _, _, _, Cache) ->
- Cache.
-
%% --------------------------------------------------------------
%% Path handling functions.
%% --------------------------------------------------------------
@@ -1207,9 +1057,9 @@ add_paths(_,_,Path,_) ->
{ok,Path}.
do_load_binary(Module, File, Binary, Caller, St) ->
- case modp(Module) andalso modp(File) andalso is_binary(Binary) of
+ case modp(File) andalso is_binary(Binary) of
true ->
- case erlang:module_loaded(to_atom(Module)) of
+ case erlang:module_loaded(Module) of
true -> do_purge(Module);
false -> ok
end,
@@ -1233,21 +1083,10 @@ load_abs(File, Mod, Caller, St) ->
{reply,{error,nofile},St}
end.
-try_load_module(Mod, Dir, Caller, St) ->
- File = filename:append(Dir, to_list(Mod) ++
- objfile_extension()),
- case erl_prim_loader:get_file(File) of
- error ->
- {reply,error,St};
- {ok,Binary,FName} ->
- try_load_module(absname(FName), Mod, Binary, Caller, St)
- end.
-
try_load_module(File, Mod, Bin, {From,_}=Caller, St0) ->
- M = to_atom(Mod),
- case pending_on_load(M, From, St0) of
+ case pending_on_load(Mod, From, St0) of
no ->
- try_load_module_1(File, M, Bin, Caller, St0);
+ try_load_module_1(File, Mod, Bin, Caller, St0);
{yes,St} ->
{noreply,St}
end.
@@ -1266,9 +1105,9 @@ try_load_module_2(File, Mod, Bin, Caller, undefined, St) ->
try_load_module_3(File, Mod, Bin, Caller, undefined, St);
try_load_module_2(File, Mod, Bin, Caller, Architecture,
#state{moddb=Db}=St) ->
- case catch load_native_code(Mod, Bin, Architecture) of
+ case catch hipe_unified_loader:load_native_code(Mod, Bin, Architecture) of
{module,Mod} = Module ->
- ets:insert(Db, {Mod,File}),
+ ets:insert(Db, [{{native,Mod},true},{Mod,File}]),
{reply,Module,St};
no_native ->
try_load_module_3(File, Mod, Bin, Caller, Architecture, St);
@@ -1282,7 +1121,7 @@ try_load_module_3(File, Mod, Bin, Caller, Architecture,
case erlang:load_module(Mod, Bin) of
{module,Mod} = Module ->
ets:insert(Db, {Mod,File}),
- post_beam_load(Mod, Architecture),
+ post_beam_load([Mod], Architecture, St),
{reply,Module,St};
{error,on_load} ->
handle_on_load(Mod, File, Caller, St);
@@ -1291,79 +1130,45 @@ try_load_module_3(File, Mod, Bin, Caller, Architecture,
{reply,Error,St}
end.
-load_native_code(Mod, Bin, Architecture) ->
- %% During bootstrapping of Open Source Erlang, we don't have any hipe
- %% loader modules, but the Erlang emulator might be hipe enabled.
- %% Therefore we must test for that the loader modules are available
- %% before trying to to load native code.
- case erlang:module_loaded(hipe_unified_loader) of
- false ->
- no_native;
- true ->
- Result = hipe_unified_loader:load_native_code(Mod, Bin,
- Architecture),
- case Result of
- {module,_} ->
- put(?ANY_NATIVE_CODE_LOADED, true);
- _ ->
- ok
- end,
- Result
- end.
-
-hipe_result_to_status(Result) ->
+hipe_result_to_status(Result, #state{moddb=Db}) ->
case Result of
- {module,_} ->
- put(?ANY_NATIVE_CODE_LOADED, true),
+ {module,Mod} ->
+ ets:insert(Db, [{{native,Mod},true}]),
Result;
_ ->
{error,Result}
end.
-post_beam_load(Mod, Architecture) ->
+post_beam_load(_, undefined, _) ->
+ %% HiPE is disabled.
+ ok;
+post_beam_load(Mods0, _Architecture, #state{moddb=Db}) ->
%% post_beam_load/2 can potentially be very expensive because it
- %% blocks multi-scheduling; thus we want to avoid the call if we
- %% know that it is not needed.
- case get(?ANY_NATIVE_CODE_LOADED) of
- true -> hipe_unified_loader:post_beam_load(Mod, Architecture);
- false -> ok
- end.
+ %% blocks multi-scheduling. Therefore, we only want to call
+ %% it with modules that are known to have native code loaded.
+ Mods = [M || M <- Mods0, ets:member(Db, {native,M})],
+ hipe_unified_loader:post_beam_load(Mods).
int_list([H|T]) when is_integer(H) -> int_list(T);
int_list([_|_]) -> false;
int_list([]) -> true.
-load_file(Mod0, {From,_}=Caller, St0) ->
- Mod = to_atom(Mod0),
+load_file(Mod, {From,_}=Caller, St0) ->
case pending_on_load(Mod, From, St0) of
no -> load_file_1(Mod, Caller, St0);
{yes,St} -> {noreply,St}
end.
-load_file_1(Mod, Caller, #state{path=Path,cache=no_cache}=St) ->
+load_file_1(Mod, Caller, #state{path=Path}=St) ->
case mod_to_bin(Path, Mod) of
error ->
{reply,{error,nofile},St};
{Mod,Binary,File} ->
- try_load_module(File, Mod, Binary, Caller, St)
- end;
-load_file_1(Mod, Caller, #state{cache=Cache}=St0) ->
- Key = {obj,Mod},
- case ets:lookup(Cache, Key) of
- [] ->
- St = rehash_cache(St0),
- case ets:lookup(St#state.cache, Key) of
- [] ->
- {reply,{error,nofile},St};
- [{Key,Dir}] ->
- try_load_module(Mod, Dir, Caller, St)
- end;
- [{Key,Dir}] ->
- try_load_module(Mod, Dir, Caller, St0)
+ try_load_module_1(File, Mod, Binary, Caller, St)
end.
mod_to_bin([Dir|Tail], Mod) ->
- File = filename:append(Dir, to_list(Mod) ++ objfile_extension()),
+ File = filename:append(Dir, atom_to_list(Mod) ++ objfile_extension()),
case erl_prim_loader:get_file(File) of
error ->
mod_to_bin(Tail, Mod);
@@ -1416,248 +1221,76 @@ absname_vr([[X, $:]|Name], _, _AbsBase) ->
absname(filename:join(Name), Dcwd).
-%% do_purge(Module)
-%% Kill all processes running code from *old* Module, and then purge the
-%% module. Return true if any processes killed, else false.
-
-do_purge(Mod0) ->
- Mod = to_atom(Mod0),
- case erlang:check_old_code(Mod) of
- false ->
- false;
- true ->
- Res = check_proc_code(erlang:processes(), Mod, true),
- try
- erlang:purge_module(Mod)
- catch
- _:_ -> ignore
- end,
- Res
+is_loaded(M, Db) ->
+ case ets:lookup(Db, M) of
+ [{M,File}] -> {file,File};
+ [] -> false
end.
-%% do_soft_purge(Module)
-%% Purge old code only if no procs remain that run old code.
-%% Return true in that case, false if procs remain (in this
-%% case old code is not purged)
-
-do_soft_purge(Mod0) ->
- Mod = to_atom(Mod0),
- case erlang:check_old_code(Mod) of
- false ->
- true;
- true ->
- case check_proc_code(erlang:processes(), Mod, false) of
- false ->
- false;
- true ->
- try
- erlang:purge_module(Mod)
- catch
- _:_ -> ignore
- end,
- true
- end
+do_purge(Mod) ->
+ {_WasOld, DidKill} = erts_code_purger:purge(Mod),
+ DidKill.
+
+do_soft_purge(Mod) ->
+ erts_code_purger:soft_purge(Mod).
+
+
+%%%
+%%% Loading of multiple modules in parallel.
+%%%
+
+finish_loading(Prepared, EnsureLoaded, #state{moddb=Db}=St) ->
+ Ps = [fun(L) -> finish_loading_ensure(L, EnsureLoaded) end,
+ fun(L) -> abort_if_pending_on_load(L, St) end,
+ fun(L) -> abort_if_sticky(L, Db) end,
+ fun(L) -> do_finish_loading(L, St) end],
+ run(Ps, Prepared).
+
+finish_loading_ensure(Prepared, true) ->
+ {ok,[P || {M,_}=P <- Prepared, not erlang:module_loaded(M)]};
+finish_loading_ensure(Prepared, false) ->
+ {ok,Prepared}.
+
+abort_if_pending_on_load(L, #state{on_load=[]}) ->
+ {ok,L};
+abort_if_pending_on_load(L, #state{on_load=OnLoad}) ->
+ Pending = [{M,pending_on_load} ||
+ {M,_} <- L,
+ lists:keymember(M, 2, OnLoad)],
+ case Pending of
+ [] -> {ok,L};
+ [_|_] -> {error,Pending}
end.
-%%
-%% check_proc_code(Pids, Mod, Hard) - Send asynchronous
-%% requests to all processes to perform a check_process_code
-%% operation. Each process will check their own state and
-%% reply with the result. If 'Hard' equals
-%% - true, processes that refer 'Mod' will be killed. If
-%% any processes were killed true is returned; otherwise,
-%% false.
-%% - false, and any processes refer 'Mod', false will
-%% returned; otherwise, true.
-%%
-%% Requests will be sent to all processes identified by
-%% Pids at once, but without allowing GC to be performed.
-%% Check process code operations that are aborted due to
-%% GC need, will be restarted allowing GC. However, only
-%% ?MAX_CPC_GC_PROCS outstanding operation allowing GC at
-%% a time will be allowed. This in order not to blow up
-%% memory wise.
-%%
-%% We also only allow ?MAX_CPC_NO_OUTSTANDING_KILLS
-%% outstanding kills. This both in order to avoid flooding
-%% our message queue with 'DOWN' messages and limiting the
-%% amount of memory used to keep references to all
-%% outstanding kills.
-%%
-
-%% We maybe should allow more than two outstanding
-%% GC requests, but for now we play it safe...
--define(MAX_CPC_GC_PROCS, 2).
--define(MAX_CPC_NO_OUTSTANDING_KILLS, 10).
-
--record(cpc_static, {hard, module, tag}).
-
--record(cpc_kill, {outstanding = [],
- no_outstanding = 0,
- waiting = [],
- killed = false}).
-
-check_proc_code(Pids, Mod, Hard) ->
- Tag = erlang:make_ref(),
- CpcS = #cpc_static{hard = Hard,
- module = Mod,
- tag = Tag},
- check_proc_code(CpcS, cpc_init(CpcS, Pids, 0), 0, [], #cpc_kill{}, true).
-
-check_proc_code(#cpc_static{hard = true}, 0, 0, [],
- #cpc_kill{outstanding = [], waiting = [], killed = Killed},
- true) ->
- %% No outstanding requests. We did a hard check, so result is whether or
- %% not we killed any processes...
- Killed;
-check_proc_code(#cpc_static{hard = false}, 0, 0, [], _KillState, Success) ->
- %% No outstanding requests and we did a soft check...
- Success;
-check_proc_code(#cpc_static{hard = false, tag = Tag} = CpcS, NoReq0, NoGcReq0,
- [], _KillState, false) ->
- %% Failed soft check; just cleanup the remaining replies corresponding
- %% to the requests we've sent...
- {NoReq1, NoGcReq1} = receive
- {check_process_code, {Tag, _P, GC}, _Res} ->
- case GC of
- false -> {NoReq0-1, NoGcReq0};
- true -> {NoReq0, NoGcReq0-1}
- end
- end,
- check_proc_code(CpcS, NoReq1, NoGcReq1, [], _KillState, false);
-check_proc_code(#cpc_static{tag = Tag} = CpcS, NoReq0, NoGcReq0, NeedGC0,
- KillState0, Success) ->
-
- %% Check if we should request a GC operation
- {NoGcReq1, NeedGC1} = case NoGcReq0 < ?MAX_CPC_GC_PROCS of
- GcOpAllowed when GcOpAllowed == false;
- NeedGC0 == [] ->
- {NoGcReq0, NeedGC0};
- _ ->
- {NoGcReq0+1, cpc_request_gc(CpcS,NeedGC0)}
- end,
-
- %% Wait for a cpc reply or 'DOWN' message
- {NoReq1, NoGcReq2, Pid, Result, KillState1} = cpc_recv(Tag,
- NoReq0,
- NoGcReq1,
- KillState0),
-
- %% Check the result of the reply
- case Result of
- aborted ->
- %% Operation aborted due to the need to GC in order to
- %% determine if the process is referring the module.
- %% Schedule the operation for restart allowing GC...
- check_proc_code(CpcS, NoReq1, NoGcReq2, [Pid|NeedGC1], KillState1,
- Success);
- false ->
- %% Process not referring the module; done with this process...
- check_proc_code(CpcS, NoReq1, NoGcReq2, NeedGC1, KillState1,
- Success);
- true ->
- %% Process referring the module...
- case CpcS#cpc_static.hard of
- false ->
- %% ... and soft check. The whole operation failed so
- %% no point continuing; clean up and fail...
- check_proc_code(CpcS, NoReq1, NoGcReq2, [], KillState1,
- false);
- true ->
- %% ... and hard check; schedule kill of it...
- check_proc_code(CpcS, NoReq1, NoGcReq2, NeedGC1,
- cpc_sched_kill(Pid, KillState1), Success)
- end;
- 'DOWN' ->
- %% Handled 'DOWN' message
- check_proc_code(CpcS, NoReq1, NoGcReq2, NeedGC1,
- KillState1, Success)
+abort_if_sticky(L, Db) ->
+ Sticky = [{M,sticky_directory} || {M,_} <- L, is_sticky(M, Db)],
+ case Sticky of
+ [] -> {ok,L};
+ [_|_] -> {error,Sticky}
end.
-cpc_recv(Tag, NoReq, NoGcReq, #cpc_kill{outstanding = []} = KillState) ->
- receive
- {check_process_code, {Tag, Pid, GC}, Res} ->
- cpc_handle_cpc(NoReq, NoGcReq, GC, Pid, Res, KillState)
- end;
-cpc_recv(Tag, NoReq, NoGcReq,
- #cpc_kill{outstanding = [R0, R1, R2, R3, R4 | _]} = KillState) ->
- receive
- {'DOWN', R, process, _, _} when R == R0;
- R == R1;
- R == R2;
- R == R3;
- R == R4 ->
- cpc_handle_down(NoReq, NoGcReq, R, KillState);
- {check_process_code, {Tag, Pid, GC}, Res} ->
- cpc_handle_cpc(NoReq, NoGcReq, GC, Pid, Res, KillState)
- end;
-cpc_recv(Tag, NoReq, NoGcReq, #cpc_kill{outstanding = [R|_]} = KillState) ->
- receive
- {'DOWN', R, process, _, _} ->
- cpc_handle_down(NoReq, NoGcReq, R, KillState);
- {check_process_code, {Tag, Pid, GC}, Res} ->
- cpc_handle_cpc(NoReq, NoGcReq, GC, Pid, Res, KillState)
+do_finish_loading(Prepared, #state{moddb=Db}=St) ->
+ MagicBins = [B || {_,{B,_}} <- Prepared],
+ case erlang:finish_loading(MagicBins) of
+ ok ->
+ MFs = [{M,F} || {M,{_,F}} <- Prepared],
+ true = ets:insert(Db, MFs),
+ Ms = [M || {M,_} <- MFs],
+ Architecture = erlang:system_info(hipe_architecture),
+ post_beam_load(Ms, Architecture, St),
+ ok;
+ {Reason,Ms} ->
+ {error,[{M,Reason} || M <- Ms]}
end.
-cpc_handle_down(NoReq, NoGcReq, R, #cpc_kill{outstanding = Rs,
- no_outstanding = N} = KillState) ->
- {NoReq, NoGcReq, undefined, 'DOWN',
- cpc_sched_kill_waiting(KillState#cpc_kill{outstanding = cpc_list_rm(R, Rs),
- no_outstanding = N-1})}.
-
-cpc_list_rm(R, [R|Rs]) ->
- Rs;
-cpc_list_rm(R0, [R1|Rs]) ->
- [R1|cpc_list_rm(R0, Rs)].
-
-cpc_handle_cpc(NoReq, NoGcReq, false, Pid, Res, KillState) ->
- {NoReq-1, NoGcReq, Pid, Res, KillState};
-cpc_handle_cpc(NoReq, NoGcReq, true, Pid, Res, KillState) ->
- {NoReq, NoGcReq-1, Pid, Res, KillState}.
-
-cpc_sched_kill_waiting(#cpc_kill{waiting = []} = KillState) ->
- KillState;
-cpc_sched_kill_waiting(#cpc_kill{outstanding = Rs,
- no_outstanding = N,
- waiting = [P|Ps]} = KillState) ->
- R = erlang:monitor(process, P),
- exit(P, kill),
- KillState#cpc_kill{outstanding = [R|Rs],
- no_outstanding = N+1,
- waiting = Ps,
- killed = true}.
-
-cpc_sched_kill(Pid, #cpc_kill{no_outstanding = N, waiting = Pids} = KillState)
- when N >= ?MAX_CPC_NO_OUTSTANDING_KILLS ->
- KillState#cpc_kill{waiting = [Pid|Pids]};
-cpc_sched_kill(Pid,
- #cpc_kill{outstanding = Rs, no_outstanding = N} = KillState) ->
- R = erlang:monitor(process, Pid),
- exit(Pid, kill),
- KillState#cpc_kill{outstanding = [R|Rs],
- no_outstanding = N+1,
- killed = true}.
-
-cpc_request(#cpc_static{tag = Tag, module = Mod}, Pid, AllowGc) ->
- erlang:check_process_code(Pid, Mod, [{async, {Tag, Pid, AllowGc}},
- {allow_gc, AllowGc}]).
-
-cpc_request_gc(CpcS, [Pid|Pids]) ->
- cpc_request(CpcS, Pid, true),
- Pids.
-
-cpc_init(_CpcS, [], NoReqs) ->
- NoReqs;
-cpc_init(CpcS, [Pid|Pids], NoReqs) ->
- cpc_request(CpcS, Pid, false),
- cpc_init(CpcS, Pids, NoReqs+1).
-
-% end of check_proc_code() implementation.
-
-is_loaded(M, Db) ->
- case ets:lookup(Db, M) of
- [{M,File}] -> {file,File};
- [] -> false
+run([F], Data) ->
+ F(Data);
+run([F|Fs], Data0) ->
+ case F(Data0) of
+ {ok,Data} ->
+ run(Fs, Data);
+ {error,_}=Error ->
+ Error
end.
%% -------------------------------------------------------
@@ -1741,26 +1374,16 @@ finish_on_load_report(Mod, Term) ->
%% -------------------------------------------------------
all_loaded(Db) ->
- all_l(Db, ets:slot(Db, 0), 1, []).
-
-all_l(_Db, '$end_of_table', _, Acc) ->
- Acc;
-all_l(Db, ModInfo, N, Acc) ->
- NewAcc = strip_mod_info(ModInfo,Acc),
- all_l(Db, ets:slot(Db, N), N + 1, NewAcc).
+ Ms = ets:fun2ms(fun({M,_}=T) when is_atom(M) -> T end),
+ ets:select(Db, Ms).
-
-strip_mod_info([{{sticky,_},_}|T], Acc) -> strip_mod_info(T, Acc);
-strip_mod_info([H|T], Acc) -> strip_mod_info(T, [H|Acc]);
-strip_mod_info([], Acc) -> Acc.
-
-% error_msg(Format) ->
-% error_msg(Format,[]).
+-spec error_msg(io:format(), [term()]) -> 'ok'.
error_msg(Format, Args) ->
Msg = {notify,{error, group_leader(), {self(), Format, Args}}},
error_logger ! Msg,
ok.
+-spec info_msg(io:format(), [term()]) -> 'ok'.
info_msg(Format, Args) ->
Msg = {notify,{info_msg, group_leader(), {self(), Format, Args}}},
error_logger ! Msg,
@@ -1774,6 +1397,3 @@ archive_extension() ->
to_list(X) when is_list(X) -> X;
to_list(X) when is_atom(X) -> atom_to_list(X).
-
-to_atom(X) when is_atom(X) -> X;
-to_atom(X) when is_list(X) -> list_to_atom(X).
diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl
index f5450f30af..9b44021872 100644
--- a/lib/kernel/src/disk_log.erl
+++ b/lib/kernel/src/disk_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1997-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.
@@ -1310,13 +1310,20 @@ compare_arg(_Attr, _Val, _A) ->
%% -> {ok, Res, log(), Cnt} | Error
do_open(A) ->
- L = #log{name = A#arg.name,
- filename = A#arg.file,
- size = A#arg.size,
- head = mk_head(A#arg.head, A#arg.format),
- mode = A#arg.mode,
- version = A#arg.version},
- do_open2(L, A).
+ #arg{type = Type, format = Format, name = Name, head = Head0,
+ file = FName, repair = Repair, size = Size, mode = Mode,
+ version = V} = A,
+ Head = mk_head(Head0, Format),
+ case do_open2(Type, Format, Name, FName, Repair, Size, Mode, Head, V) of
+ {ok, Ret, Extra, FormatType, NoItems} ->
+ L = #log{name = Name, type = Type, format = Format,
+ filename = FName, size = Size,
+ format_type = FormatType, head = Head, mode = Mode,
+ version = V, extra = Extra},
+ {ok, Ret, L, NoItems};
+ Error ->
+ Error
+ end.
mk_head({head, Term}, internal) -> {ok, term_to_binary(Term)};
mk_head({head, Bytes}, external) -> {ok, check_bytes(Bytes)};
@@ -1432,57 +1439,44 @@ do_inc_wrap_file(L) ->
%%-----------------------------------------------------------------
%% -> {ok, Reply, log(), Cnt} | Error
%% Note: the header is always written, even if the log size is too small.
-do_open2(L, #arg{type = halt, format = internal, name = Name,
- file = FName, repair = Repair, size = Size, mode = Mode}) ->
- case catch disk_log_1:int_open(FName, Repair, Mode, L#log.head) of
+do_open2(halt, internal, Name, FName, Repair, Size, Mode, Head, _V) ->
+ case catch disk_log_1:int_open(FName, Repair, Mode, Head) of
{ok, {_Alloc, FdC, {NoItems, _NoBytes}, FileSize}} ->
Halt = #halt{fdc = FdC, curB = FileSize, size = Size},
- {ok, {ok, Name}, L#log{format_type = halt_int, extra = Halt},
- NoItems};
+ {ok, {ok, Name}, Halt, halt_int, NoItems};
{repaired, FdC, Rec, Bad, FileSize} ->
Halt = #halt{fdc = FdC, curB = FileSize, size = Size},
{ok, {repaired, Name, {recovered, Rec}, {badbytes, Bad}},
- L#log{format_type = halt_int, extra = Halt},
- Rec};
+ Halt, halt_int, Rec};
Error ->
Error
end;
-do_open2(L, #arg{type = wrap, format = internal, size = {MaxB, MaxF},
- name = Name, repair = Repair, file = FName, mode = Mode,
- version = V}) ->
+do_open2(wrap, internal, Name, FName, Repair, Size, Mode, Head, V) ->
+ {MaxB, MaxF} = Size,
case catch
- disk_log_1:mf_int_open(FName, MaxB, MaxF, Repair, Mode, L#log.head, V) of
+ disk_log_1:mf_int_open(FName, MaxB, MaxF, Repair, Mode, Head, V) of
{ok, Handle, Cnt} ->
- {ok, {ok, Name}, L#log{type = wrap,
- format_type = wrap_int,
- extra = Handle}, Cnt};
+ {ok, {ok, Name}, Handle, wrap_int, Cnt};
{repaired, Handle, Rec, Bad, Cnt} ->
{ok, {repaired, Name, {recovered, Rec}, {badbytes, Bad}},
- L#log{type = wrap, format_type = wrap_int, extra = Handle}, Cnt};
+ Handle, wrap_int, Cnt};
Error ->
Error
end;
-do_open2(L, #arg{type = halt, format = external, file = FName, name = Name,
- size = Size, repair = Repair, mode = Mode}) ->
- case catch disk_log_1:ext_open(FName, Repair, Mode, L#log.head) of
+do_open2(halt, external, Name, FName, Repair, Size, Mode, Head, _V) ->
+ case catch disk_log_1:ext_open(FName, Repair, Mode, Head) of
{ok, {_Alloc, FdC, {NoItems, _NoBytes}, FileSize}} ->
Halt = #halt{fdc = FdC, curB = FileSize, size = Size},
- {ok, {ok, Name},
- L#log{format_type = halt_ext, format = external, extra = Halt},
- NoItems};
+ {ok, {ok, Name}, Halt, halt_ext, NoItems};
Error ->
Error
end;
-do_open2(L, #arg{type = wrap, format = external, size = {MaxB, MaxF},
- name = Name, file = FName, repair = Repair, mode = Mode,
- version = V}) ->
+do_open2(wrap, external, Name, FName, Repair, Size, Mode, Head, V) ->
+ {MaxB, MaxF} = Size,
case catch
- disk_log_1:mf_ext_open(FName, MaxB, MaxF, Repair, Mode, L#log.head, V) of
+ disk_log_1:mf_ext_open(FName, MaxB, MaxF, Repair, Mode, Head, V) of
{ok, Handle, Cnt} ->
- {ok, {ok, Name}, L#log{type = wrap,
- format_type = wrap_ext,
- extra = Handle,
- format = external}, Cnt};
+ {ok, {ok, Name}, Handle, wrap_ext, Cnt};
Error ->
Error
end.
diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl
index 6c0aea070f..3262d979ee 100644
--- a/lib/kernel/src/disk_log.hrl
+++ b/lib/kernel/src/disk_log.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-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.
@@ -152,8 +152,8 @@
users = 0 :: non_neg_integer(), %% non-linked users
filename :: file:filename(), %% real name of the file
owners = [] :: [{pid(), boolean()}],%% [{pid, notify}]
- type = halt :: dlog_type(),
- format = internal :: dlog_format(),
+ type :: dlog_type(),
+ format :: dlog_format(),
format_type :: dlog_format_type(),
head = none, %% none | {head, H} | {M,F,A}
%% called when wraplog wraps
diff --git a/lib/kernel/src/erl_distribution.erl b/lib/kernel/src/erl_distribution.erl
index 99db7a8bf0..559e2a853b 100644
--- a/lib/kernel/src/erl_distribution.erl
+++ b/lib/kernel/src/erl_distribution.erl
@@ -21,20 +21,47 @@
-behaviour(supervisor).
--export([start_link/0,start_link/1,init/1,start/1,stop/0]).
+-export([start_link/0,start_link/2,init/1,start/1,stop/0]).
-define(DBG,erlang:display([?MODULE,?LINE])).
+%% Called during system start-up.
+
start_link() ->
- case catch start_p() of
- {ok,Args} ->
- start_link(Args);
- _ ->
- ignore
+ do_start_link([{sname,shortnames},{name,longnames}]).
+
+%% Called from net_kernel:start/1 to start distribution after the
+%% system has already started.
+
+start(Args) ->
+ C = {net_sup_dynamic, {?MODULE,start_link,[Args,false]}, permanent,
+ 1000, supervisor, [erl_distribution]},
+ supervisor:start_child(kernel_sup, C).
+
+%% Stop distribution.
+
+stop() ->
+ case supervisor:terminate_child(kernel_sup, net_sup_dynamic) of
+ ok ->
+ supervisor:delete_child(kernel_sup, net_sup_dynamic);
+ Error ->
+ case whereis(net_sup) of
+ Pid when is_pid(Pid) ->
+ %% Dist. started through -sname | -name flags
+ {error, not_allowed};
+ _ ->
+ Error
+ end
end.
-start_link(Args) ->
- supervisor:start_link({local,net_sup},erl_distribution,Args).
+%%%
+%%% Internal helper functions.
+%%%
+
+%% Helper start function.
+
+start_link(Args, CleanHalt) ->
+ supervisor:start_link({local,net_sup}, ?MODULE, [Args,CleanHalt]).
init(NetArgs) ->
Epmd =
@@ -47,31 +74,20 @@ init(NetArgs) ->
permanent,2000,worker,[EpmdMod]}]
end,
Auth = {auth,{auth,start_link,[]},permanent,2000,worker,[auth]},
- Kernel = {net_kernel,{net_kernel,start_link,[NetArgs]},
+ Kernel = {net_kernel,{net_kernel,start_link,NetArgs},
permanent,2000,worker,[net_kernel]},
EarlySpecs = net_kernel:protocol_childspecs(),
{ok,{{one_for_all,0,1}, EarlySpecs ++ Epmd ++ [Auth,Kernel]}}.
-start_p() ->
- sname(),
- lname(),
- false.
-
-sname() ->
- case init:get_argument(sname) of
+do_start_link([{Arg,Flag}|T]) ->
+ case init:get_argument(Arg) of
{ok,[[Name]]} ->
- throw({ok,[list_to_atom(Name),shortnames|ticktime()]});
+ start_link([list_to_atom(Name),Flag|ticktime()], true);
_ ->
- false
- end.
-
-lname() ->
- case init:get_argument(name) of
- {ok,[[Name]]} ->
- throw({ok,[list_to_atom(Name),longnames|ticktime()]});
- _ ->
- false
- end.
+ do_start_link(T)
+ end;
+do_start_link([]) ->
+ ignore.
ticktime() ->
%% catch, in case the system was started with boot file start_old,
@@ -84,23 +100,3 @@ ticktime() ->
_ ->
[]
end.
-
-start(Args) ->
- C = {net_sup_dynamic, {erl_distribution, start_link, [Args]}, permanent,
- 1000, supervisor, [erl_distribution]},
- supervisor:start_child(kernel_sup, C).
-
-stop() ->
- case supervisor:terminate_child(kernel_sup, net_sup_dynamic) of
- ok ->
- supervisor:delete_child(kernel_sup, net_sup_dynamic);
- Error ->
- case whereis(net_sup) of
- Pid when is_pid(Pid) ->
- %% Dist. started through -sname | -name flags
- {error, not_allowed};
- _ ->
- Error
- end
- end.
-
diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl
index eb231fd155..30a9457bb3 100644
--- a/lib/kernel/src/error_logger.erl
+++ b/lib/kernel/src/error_logger.erl
@@ -435,5 +435,82 @@ add_node(X, Pid) ->
%% Can't do io_lib:format
-display2(Tag,F,A) ->
- erlang:display({error_logger,Tag,F,A}).
+display2({{_Y,_Mo,_D},{_H,_Mi,_S}} = Date, F, A) ->
+ display_date(Date),
+ display3(string_p(F), F, A).
+
+display_date({{Y,Mo,D},{H,Mi,S}}) ->
+ erlang:display_string(
+ integer_to_list(Y) ++ "-" ++
+ two_digits(Mo) ++ "-" ++
+ two_digits(D) ++ " " ++
+ two_digits(H) ++ ":" ++
+ two_digits(Mi) ++ ":" ++
+ two_digits(S) ++ " ").
+
+two_digits(N) when 0 =< N, N =< 9 ->
+ [$0, $0 + N];
+two_digits(N) ->
+ integer_to_list(N).
+
+display3(true, F, A) ->
+ %% Format string with arguments
+ erlang:display_string(F ++ "\n"),
+ [begin
+ erlang:display_string("\t"),
+ erlang:display(Arg)
+ end || Arg <- A],
+ ok;
+display3(false, Atom, A) when is_atom(Atom) ->
+ %% The widest atom seems to be 'supervisor_report' at 17.
+ ColumnWidth = 20,
+ AtomString = atom_to_list(Atom),
+ AtomLength = length(AtomString),
+ Padding = lists:duplicate(ColumnWidth - AtomLength, $\s),
+ erlang:display_string(AtomString ++ Padding),
+ display4(A);
+display3(_, F, A) ->
+ erlang:display({F, A}).
+
+display4([A, []]) ->
+ %% Not sure why crash reports look like this.
+ display4(A);
+display4(A = [_|_]) ->
+ case lists:all(fun({Key,_Value}) -> is_atom(Key); (_) -> false end, A) of
+ true ->
+ erlang:display_string("\n"),
+ lists:foreach(
+ fun({Key, Value}) ->
+ erlang:display_string(
+ " " ++
+ atom_to_list(Key) ++
+ ": "),
+ erlang:display(Value)
+ end, A);
+ false ->
+ erlang:display(A)
+ end;
+display4(A) ->
+ erlang:display(A).
+
+string_p([]) ->
+ false;
+string_p(Term) ->
+ string_p1(Term).
+
+string_p1([H|T]) when is_integer(H), H >= $\s, H < 255 ->
+ string_p1(T);
+string_p1([$\n|T]) -> string_p1(T);
+string_p1([$\r|T]) -> string_p1(T);
+string_p1([$\t|T]) -> string_p1(T);
+string_p1([$\v|T]) -> string_p1(T);
+string_p1([$\b|T]) -> string_p1(T);
+string_p1([$\f|T]) -> string_p1(T);
+string_p1([$\e|T]) -> string_p1(T);
+string_p1([H|T]) when is_list(H) ->
+ case string_p1(H) of
+ true -> string_p1(T);
+ _ -> false
+ end;
+string_p1([]) -> true;
+string_p1(_) -> false.
diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl
index 39308c0043..8e2b5ad214 100644
--- a/lib/kernel/src/erts_debug.erl
+++ b/lib/kernel/src/erts_debug.erl
@@ -34,7 +34,8 @@
-export([breakpoint/2, disassemble/1, display/1, dist_ext_to_term/2,
dump_monitors/1, dump_links/1, flat_size/1,
get_internal_state/1, instructions/0, lock_counters/1,
- map_info/1, same/2, set_internal_state/2]).
+ map_info/1, same/2, set_internal_state/2,
+ size_shared/1, copy_shared/1]).
-spec breakpoint(MFA, Flag) -> non_neg_integer() when
MFA :: {Module :: module(),
@@ -86,6 +87,18 @@ dump_links(_) ->
flat_size(_) ->
erlang:nif_error(undef).
+-spec size_shared(Term) -> non_neg_integer() when
+ Term :: term().
+
+size_shared(_) ->
+ erlang:nif_error(undef).
+
+-spec copy_shared(Term) -> term() when
+ Term :: term().
+
+copy_shared(_) ->
+ erlang:nif_error(undef).
+
-spec get_internal_state(W) -> term() when
W :: reds_left | node_and_dist_references | monitoring_nodes
| next_pid | 'DbTable_words' | check_io_debug
@@ -230,7 +243,7 @@ map_size(Map,Seen0,Sum0) ->
%% is not allowed to leak anywhere. They are only allowed in
%% containers (cons cells and tuples, not maps), in gc and
%% in erts_debug:same/2
- case erts_internal:map_type(Map) of
+ case erts_internal:term_type(Map) of
flatmap ->
Kt = erts_internal:map_to_tuple_keys(Map),
Vs = maps:values(Map),
diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl
index 2be1efaf24..0c73ead7c5 100644
--- a/lib/kernel/src/global.erl
+++ b/lib/kernel/src/global.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-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.
@@ -459,17 +459,17 @@ init([]) ->
no_trace
end,
+ Ca = case init:get_argument(connect_all) of
+ {ok, [["false"]]} ->
+ false;
+ _ ->
+ true
+ end,
S = #state{the_locker = start_the_locker(DoTrace),
trace = T0,
- the_registrar = start_the_registrar()},
- S1 = trace_message(S, {init, node()}, []),
-
- case init:get_argument(connect_all) of
- {ok, [["false"]]} ->
- {ok, S1#state{connect_all = false}};
- _ ->
- {ok, S1#state{connect_all = true}}
- end.
+ the_registrar = start_the_registrar(),
+ connect_all = Ca},
+ {ok, trace_message(S, {init, node()}, [])}.
%%-----------------------------------------------------------------
%% Connection algorithm
@@ -2068,23 +2068,17 @@ get_known() ->
gen_server:call(global_name_server, get_known, infinity).
random_sleep(Times) ->
- case (Times rem 10) of
- 0 -> erase(random_seed);
- _ -> ok
- end,
- case get(random_seed) of
- undefined ->
- _ = random:seed(erlang:phash2([erlang:node()]),
- erlang:monotonic_time(),
- erlang:unique_integer()),
- ok;
- _ -> ok
- end,
+ _ = case Times rem 10 of
+ 0 ->
+ _ = rand:seed(exsplus);
+ _ ->
+ ok
+ end,
%% First time 1/4 seconds, then doubling each time up to 8 seconds max.
Tmax = if Times > 5 -> 8000;
true -> ((1 bsl Times) * 1000) div 8
end,
- T = random:uniform(Tmax),
+ T = rand:uniform(Tmax),
?trace({random_sleep, {me,self()}, {times,Times}, {t,T}, {tmax,Tmax}}),
receive after T -> ok end.
diff --git a/lib/kernel/src/global_group.erl b/lib/kernel/src/global_group.erl
index 848df13c39..e71f83f9d3 100644
--- a/lib/kernel/src/global_group.erl
+++ b/lib/kernel/src/global_group.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1998-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.
@@ -273,7 +273,7 @@ init([]) ->
{ok, #state{publish_type = PT, group_publish_type = PubTpGrp,
sync_state = synced, group_name = DefGroupName,
no_contact = lists:sort(DefNodes),
- other_grps = DefOther}}
+ other_grps = DefOther, connect_all = Ca}}
end.
diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl
index ddbbc548dd..087cceb5d8 100644
--- a/lib/kernel/src/hipe_unified_loader.erl
+++ b/lib/kernel/src/hipe_unified_loader.erl
@@ -44,7 +44,7 @@
-export([chunk_name/1,
%% Only the code and code_server modules may call the entries below!
load_native_code/3,
- post_beam_load/2,
+ post_beam_load/1,
load_module/4,
load/3]).
@@ -105,7 +105,7 @@ load_native_code(Mod, Bin, Architecture) when is_atom(Mod), is_binary(Bin) ->
case code:get_chunk(Bin, chunk_name(Architecture)) of
undefined -> no_native;
NativeCode when is_binary(NativeCode) ->
- erlang:system_flag(multi_scheduling, block),
+ erlang:system_flag(multi_scheduling, block_normal),
try
OldReferencesToPatch = patch_to_emu_step1(Mod),
case load_module(Mod, NativeCode, Bin, OldReferencesToPatch,
@@ -114,23 +114,23 @@ load_native_code(Mod, Bin, Architecture) when is_atom(Mod), is_binary(Bin) ->
Result -> Result
end
after
- erlang:system_flag(multi_scheduling, unblock)
+ erlang:system_flag(multi_scheduling, unblock_normal)
end
end.
%%========================================================================
--spec post_beam_load(atom(), hipe_architecture()) -> 'ok'.
+-spec post_beam_load([module()]) -> 'ok'.
-%% does nothing on a hipe-disabled system
-post_beam_load(_Mod, undefined) ->
+post_beam_load([])->
ok;
-post_beam_load(Mod, _) when is_atom(Mod) ->
- erlang:system_flag(multi_scheduling, block),
+post_beam_load([_|_]=Mods) ->
+ erlang:system_flag(multi_scheduling, block_normal),
try
- patch_to_emu(Mod)
+ _ = [patch_to_emu(Mod) || Mod <- Mods],
+ ok
after
- erlang:system_flag(multi_scheduling, unblock)
+ erlang:system_flag(multi_scheduling, unblock_normal)
end,
ok.
@@ -151,11 +151,11 @@ version_check(Version, Mod) when is_atom(Mod) ->
'bad_crc' | {'module', Mod} when Mod :: atom().
load_module(Mod, Bin, Beam, Architecture) ->
- erlang:system_flag(multi_scheduling, block),
+ erlang:system_flag(multi_scheduling, block_normal),
try
load_module_nosmp(Mod, Bin, Beam, Architecture)
after
- erlang:system_flag(multi_scheduling, unblock)
+ erlang:system_flag(multi_scheduling, unblock_normal)
end.
load_module_nosmp(Mod, Bin, Beam, Architecture) ->
@@ -173,11 +173,11 @@ load_module(Mod, Bin, Beam, OldReferencesToPatch, Architecture) ->
'bad_crc' | {'module', Mod} when Mod :: atom().
load(Mod, Bin, Architecture) ->
- erlang:system_flag(multi_scheduling, block),
+ erlang:system_flag(multi_scheduling, block_normal),
try
load_nosmp(Mod, Bin, Architecture)
after
- erlang:system_flag(multi_scheduling, unblock)
+ erlang:system_flag(multi_scheduling, unblock_normal)
end.
load_nosmp(Mod, Bin, Architecture) ->
diff --git a/lib/kernel/src/inet_config.erl b/lib/kernel/src/inet_config.erl
index 803fae846e..a0d5344f11 100644
--- a/lib/kernel/src/inet_config.erl
+++ b/lib/kernel/src/inet_config.erl
@@ -188,9 +188,6 @@ do_load_resolv({win32,Type}, longnames) ->
win32_load_from_registry(Type),
inet_db:set_lookup([native]);
-do_load_resolv({ose,_}, _) ->
- inet_db:set_lookup([file]);
-
do_load_resolv(_, _) ->
inet_db:set_lookup([native]).
diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src
index 419dc0a2fc..7452c6bc98 100644
--- a/lib/kernel/src/kernel.app.src
+++ b/lib/kernel/src/kernel.app.src
@@ -116,6 +116,6 @@
{applications, []},
{env, [{error_logger, tty}]},
{mod, {kernel, []}},
- {runtime_dependencies, ["erts-7.3", "stdlib-2.6", "sasl-2.6"]}
+ {runtime_dependencies, ["erts-8.0", "stdlib-2.6", "sasl-2.6"]}
]
}.
diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src
index cc9e6f771a..a13819a183 100644
--- a/lib/kernel/src/kernel.appup.src
+++ b/lib/kernel/src/kernel.appup.src
@@ -18,9 +18,9 @@
%% %CopyrightEnd%
{"%VSN%",
%% Up from - max one major revision back
- [{<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.*
- {<<"3\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17
+ [{<<"5\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.*
+ {<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-18.*
%% Down to - max one major revision back
- [{<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.*
- {<<"3\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17
+ [{<<"5\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.*
+ {<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-18.*
}.
diff --git a/lib/kernel/src/kernel.erl b/lib/kernel/src/kernel.erl
index 5f33f25a0d..40544da6c3 100644
--- a/lib/kernel/src/kernel.erl
+++ b/lib/kernel/src/kernel.erl
@@ -98,7 +98,7 @@ init([]) ->
{kernel_config, start_link, []},
permanent, 2000, worker, [kernel_config]},
Code = {code_server,
- {code, start_link, get_code_args()},
+ {code, start_link, []},
permanent, 2000, worker, [code]},
File = {file_server_2,
{file_server, start_link, []},
@@ -158,12 +158,6 @@ init(safe) ->
{ok, {SupFlags, Boot ++ DiskLog ++ Pg2}}.
-get_code_args() ->
- case init:get_argument(nostick) of
- {ok, [[]]} -> [[nostick]];
- _ -> []
- end.
-
start_dist_ac() ->
Spec = [{dist_ac,{dist_ac,start_link,[]},permanent,2000,worker,[dist_ac]}],
case application:get_env(kernel, start_dist_ac) of
diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl
index 35a54f591e..a19c116388 100644
--- a/lib/kernel/src/net_kernel.erl
+++ b/lib/kernel/src/net_kernel.erl
@@ -53,18 +53,25 @@
-define(tckr_dbg(X), ok).
-endif.
-%% User Interface Exports
--export([start/1, start_link/1, stop/0,
- kernel_apply/3,
+%% Documented API functions.
+
+-export([allow/1,
+ connect_node/1,
monitor_nodes/1,
monitor_nodes/2,
+ start/1,
+ stop/0]).
+
+%% Exports for internal use.
+
+-export([start_link/2,
+ kernel_apply/3,
longnames/0,
- allow/1,
protocol_childspecs/0,
epmd_module/0]).
-export([connect/1, disconnect/1, hidden_connect/1, passive_cnct/1]).
--export([connect_node/1, hidden_connect_node/1]). %% explicit connect
+-export([hidden_connect_node/1]). %% explicit connect
-export([set_net_ticktime/1, set_net_ticktime/2, get_net_ticktime/0]).
-export([node_info/1, node_info/2, nodes_info/0,
@@ -73,7 +80,8 @@
-export([publish_on_node/1, update_publish_nodes/1]).
-%% Internal Exports
+%% Internal exports for spawning processes.
+
-export([do_spawn/3,
spawn_func/6,
ticker/2,
@@ -341,18 +349,18 @@ request(Req) ->
start(Args) ->
erl_distribution:start(Args).
-%% This is the main startup routine for net_kernel
-%% The defaults are longnames and a ticktime of 15 secs to the tcp_drv.
+%% This is the main startup routine for net_kernel (only for internal
+%% use by the Kernel application.
-start_link([Name]) ->
- start_link([Name, longnames]);
+start_link([Name], CleanHalt) ->
+ start_link([Name, longnames], CleanHalt);
+start_link([Name, LongOrShortNames], CleanHalt) ->
+ start_link([Name, LongOrShortNames, 15000], CleanHalt);
-start_link([Name, LongOrShortNames]) ->
- start_link([Name, LongOrShortNames, 15000]);
-
-start_link([Name, LongOrShortNames, Ticktime]) ->
- case gen_server:start_link({local, net_kernel}, net_kernel,
- {Name, LongOrShortNames, Ticktime}, []) of
+start_link([Name, LongOrShortNames, Ticktime], CleanHalt) ->
+ Args = {Name, LongOrShortNames, Ticktime, CleanHalt},
+ case gen_server:start_link({local, net_kernel}, ?MODULE,
+ Args, []) of
{ok, Pid} ->
{ok, Pid};
{error, {already_started, Pid}} ->
@@ -361,12 +369,9 @@ start_link([Name, LongOrShortNames, Ticktime]) ->
exit(nodistribution)
end.
-%% auth:get_cookie should only be able to return an atom
-%% tuple cookies are unknowns
-
-init({Name, LongOrShortNames, TickT}) ->
+init({Name, LongOrShortNames, TickT, CleanHalt}) ->
process_flag(trap_exit,true),
- case init_node(Name, LongOrShortNames) of
+ case init_node(Name, LongOrShortNames, CleanHalt) of
{ok, Node, Listeners} ->
process_flag(priority, max),
Ticktime = to_integer(TickT),
@@ -1201,12 +1206,12 @@ get_proto_mod(_Family, _Protocol, []) ->
%% -------- Initialisation functions ------------------------
-init_node(Name, LongOrShortNames) ->
- {NameWithoutHost,_Host} = lists:splitwith(fun($@)->false;(_)->true end,
- atom_to_list(Name)),
+init_node(Name, LongOrShortNames, CleanHalt) ->
+ {NameWithoutHost0,_Host} = split_node(Name),
case create_name(Name, LongOrShortNames, 1) of
{ok,Node} ->
- case start_protos(list_to_atom(NameWithoutHost),Node) of
+ NameWithoutHost = list_to_atom(NameWithoutHost0),
+ case start_protos(NameWithoutHost, Node, CleanHalt) of
{ok, Ls} ->
{ok, Node, Ls};
Error ->
@@ -1240,8 +1245,7 @@ create_name(Name, LongOrShortNames, Try) ->
end.
create_hostpart(Name, LongOrShortNames) ->
- {Head,Host} = lists:splitwith(fun($@)->false;(_)->true end,
- atom_to_list(Name)),
+ {Head,Host} = split_node(Name),
Host1 = case {Host,LongOrShortNames} of
{[$@,_|_],longnames} ->
{ok,Host};
@@ -1268,6 +1272,9 @@ create_hostpart(Name, LongOrShortNames) ->
end,
{Head,Host1}.
+split_node(Name) ->
+ lists:splitwith(fun(C) -> C =/= $@ end, atom_to_list(Name)).
+
%%
%%
%%
@@ -1307,21 +1314,26 @@ epmd_module() ->
%% Start all protocols
%%
-start_protos(Name,Node) ->
+start_protos(Name, Node, CleanHalt) ->
case init:get_argument(proto_dist) of
{ok, [Protos]} ->
- start_protos(Name,Protos, Node);
+ start_protos(Name, Protos, Node, CleanHalt);
_ ->
- start_protos(Name,["inet_tcp"], Node)
+ start_protos(Name, ["inet_tcp"], Node, CleanHalt)
end.
-start_protos(Name,Ps, Node) ->
- case start_protos(Name, Ps, Node, []) of
- [] -> {error, badarg};
- Ls -> {ok, Ls}
+start_protos(Name, Ps, Node, CleanHalt) ->
+ case start_protos(Name, Ps, Node, [], CleanHalt) of
+ [] ->
+ case CleanHalt of
+ true -> halt(1);
+ false -> {error, badarg}
+ end;
+ Ls ->
+ {ok, Ls}
end.
-start_protos(Name, [Proto | Ps], Node, Ls) ->
+start_protos(Name, [Proto | Ps], Node, Ls, CleanHalt) ->
Mod = list_to_atom(Proto ++ "_dist"),
case catch Mod:listen(Name) of
{ok, {Socket, Address, Creation}} ->
@@ -1334,33 +1346,48 @@ start_protos(Name, [Proto | Ps], Node, Ls) ->
address = Address,
accept = AcceptPid,
module = Mod },
- start_protos(Name,Ps, Node, [L|Ls]);
+ start_protos(Name,Ps, Node, [L|Ls], CleanHalt);
_ ->
Mod:close(Socket),
- error_logger:info_msg("Invalid node name: ~p~n", [Node]),
- start_protos(Name, Ps, Node, Ls)
+ S = "invalid node name: " ++ atom_to_list(Node),
+ proto_error(CleanHalt, Proto, S),
+ start_protos(Name, Ps, Node, Ls, CleanHalt)
end;
{'EXIT', {undef,_}} ->
- error_logger:info_msg("Protocol: ~tp: not supported~n", [Proto]),
- start_protos(Name,Ps, Node, Ls);
+ proto_error(CleanHalt, Proto, "not supported"),
+ start_protos(Name, Ps, Node, Ls, CleanHalt);
{'EXIT', Reason} ->
- error_logger:info_msg("Protocol: ~tp: register error: ~tp~n",
- [Proto, Reason]),
- start_protos(Name,Ps, Node, Ls);
+ register_error(CleanHalt, Proto, Reason),
+ start_protos(Name, Ps, Node, Ls, CleanHalt);
{error, duplicate_name} ->
- error_logger:info_msg("Protocol: ~tp: the name " ++
- atom_to_list(Node) ++
- " seems to be in use by another Erlang node",
- [Proto]),
- start_protos(Name,Ps, Node, Ls);
+ S = "the name " ++ atom_to_list(Node) ++
+ " seems to be in use by another Erlang node",
+ proto_error(CleanHalt, Proto, S),
+ start_protos(Name, Ps, Node, Ls, CleanHalt);
{error, Reason} ->
- error_logger:info_msg("Protocol: ~tp: register/listen error: ~tp~n",
- [Proto, Reason]),
- start_protos(Name,Ps, Node, Ls)
+ register_error(CleanHalt, Proto, Reason),
+ start_protos(Name, Ps, Node, Ls, CleanHalt)
end;
-start_protos(_,[], _Node, Ls) ->
+start_protos(_, [], _Node, Ls, _CleanHalt) ->
Ls.
+register_error(false, Proto, Reason) ->
+ S = io_lib:format("register/listen error: ~p", [Reason]),
+ proto_error(false, Proto, lists:flatten(S));
+register_error(true, Proto, Reason) ->
+ S = "Protocol '" ++ Proto ++ "': register/listen error: ",
+ erlang:display_string(S),
+ erlang:display(Reason).
+
+proto_error(CleanHalt, Proto, String) ->
+ S = "Protocol '" ++ Proto ++ "': " ++ String ++ "\n",
+ case CleanHalt of
+ false ->
+ error_logger:info_msg(S);
+ true ->
+ erlang:display_string(S)
+ end.
+
set_node(Node, Creation) when node() =:= nonode@nohost ->
case catch erlang:setnode(Node, Creation) of
true ->
diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl
index 3330b38d84..4947088635 100644
--- a/lib/kernel/src/os.erl
+++ b/lib/kernel/src/os.erl
@@ -27,7 +27,9 @@
%%% BIFs
--export([getenv/0, getenv/1, getenv/2, getpid/0, putenv/2, system_time/0, system_time/1,
+-export([getenv/0, getenv/1, getenv/2, getpid/0,
+ perf_counter/0, perf_counter/1,
+ putenv/2, system_time/0, system_time/1,
timestamp/0, unsetenv/1]).
-spec getenv() -> [string()].
@@ -60,6 +62,18 @@ getenv(VarName, DefaultValue) ->
getpid() ->
erlang:nif_error(undef).
+-spec perf_counter() -> Counter when
+ Counter :: integer().
+
+perf_counter() ->
+ erlang:nif_error(undef).
+
+-spec perf_counter(Unit) -> integer() when
+ Unit :: erlang:time_unit().
+
+perf_counter(Unit) ->
+ erlang:convert_time_unit(os:perf_counter(), perf_counter, Unit).
+
-spec putenv(VarName, Value) -> true when
VarName :: string(),
Value :: string().
@@ -93,7 +107,7 @@ unsetenv(_) ->
%%% End of BIFs
-spec type() -> {Osfamily, Osname} when
- Osfamily :: unix | win32 | ose,
+ Osfamily :: unix | win32,
Osname :: atom().
type() ->
@@ -212,174 +226,33 @@ extensions() ->
Command :: atom() | io_lib:chars().
cmd(Cmd) ->
validate(Cmd),
- Bytes = case type() of
- {unix, _} ->
- unix_cmd(Cmd);
- {win32, Wtype} ->
- Command0 = case {os:getenv("COMSPEC"),Wtype} of
- {false,windows} -> lists:concat(["command.com /c", Cmd]);
- {false,_} -> lists:concat(["cmd /c", Cmd]);
- {Cspec,_} -> lists:concat([Cspec," /c",Cmd])
- end,
- %% open_port/2 awaits string() in Command, but io_lib:chars() can be
- %% deep lists according to io_lib module description.
- Command = lists:flatten(Command0),
- Port = open_port({spawn, Command}, [stream, in, eof, hide]),
- get_data(Port, [])
- end,
- String = unicode:characters_to_list(list_to_binary(Bytes)),
+ {SpawnCmd, SpawnOpts, SpawnInput} = mk_cmd(os:type(), Cmd),
+ Port = open_port({spawn, SpawnCmd}, [binary, stderr_to_stdout,
+ stream, in, eof, hide | SpawnOpts]),
+ true = port_command(Port, SpawnInput),
+ Bytes = get_data(Port, []),
+ String = unicode:characters_to_list(Bytes),
if %% Convert to unicode list if possible otherwise return bytes
is_list(String) -> String;
- true -> Bytes
- end.
-
-unix_cmd(Cmd) ->
- Tag = make_ref(),
- {Pid,Mref} = erlang:spawn_monitor(
- fun() ->
- process_flag(trap_exit, true),
- Port = start_port(),
- erlang:port_command(Port, mk_cmd(Cmd)),
- exit({Tag,unix_get_data(Port)})
- end),
- receive
- {'DOWN',Mref,_,Pid,{Tag,Result}} ->
- Result;
- {'DOWN',Mref,_,Pid,Reason} ->
- exit(Reason)
+ true -> binary_to_list(Bytes)
end.
-%% The -s flag implies that only the positional parameters are set,
-%% and the commands are read from standard input. We set the
-%% $1 parameter for easy identification of the resident shell.
-%%
--define(ROOT, "/").
--define(ROOT_ANDROID, "/system").
--define(SHELL, "bin/sh -s unix:cmd 2>&1").
--define(PORT_CREATOR_NAME, os_cmd_port_creator).
-
-%%
-%% Serializing open_port through a process to avoid smp lock contention
-%% when many concurrent os:cmd() want to do vfork (OTP-7890).
-%%
--spec start_port() -> port().
-start_port() ->
- Ref = make_ref(),
- Request = {Ref,self()},
- {Pid, Mon} = case whereis(?PORT_CREATOR_NAME) of
- undefined ->
- spawn_monitor(fun() ->
- start_port_srv(Request)
- end);
- P ->
- P ! Request,
- M = erlang:monitor(process, P),
- {P, M}
- end,
- receive
- {Ref, Port} when is_port(Port) ->
- erlang:demonitor(Mon, [flush]),
- Port;
- {Ref, Error} ->
- erlang:demonitor(Mon, [flush]),
- exit(Error);
- {'DOWN', Mon, process, Pid, _Reason} ->
- start_port()
- end.
-
-start_port_srv(Request) ->
- %% We don't want a group leader of some random application. Use
- %% kernel_sup's group leader.
- {group_leader, GL} = process_info(whereis(kernel_sup),
- group_leader),
- true = group_leader(GL, self()),
- process_flag(trap_exit, true),
- StayAlive = try register(?PORT_CREATOR_NAME, self())
- catch
- error:_ -> false
- end,
- start_port_srv_handle(Request),
- case StayAlive of
- true -> start_port_srv_loop();
- false -> exiting
- end.
-
-start_port_srv_handle({Ref,Client}) ->
- Path = case lists:reverse(erlang:system_info(system_architecture)) of
- % androideabi
- "ibaediordna" ++ _ -> filename:join([?ROOT_ANDROID, ?SHELL]);
- _ -> filename:join([?ROOT, ?SHELL])
- end,
- Reply = try open_port({spawn, Path},[stream]) of
- Port when is_port(Port) ->
- (catch port_connect(Port, Client)),
- unlink(Port),
- Port
- catch
- error:Reason ->
- {Reason,erlang:get_stacktrace()}
- end,
- Client ! {Ref,Reply},
- ok.
-
-start_port_srv_loop() ->
- receive
- {Ref, Client} = Request when is_reference(Ref),
- is_pid(Client) ->
- start_port_srv_handle(Request);
- _Junk ->
- ok
- end,
- start_port_srv_loop().
-
-%%
-%% unix_get_data(Port) -> Result
-%%
-unix_get_data(Port) ->
- unix_get_data(Port, []).
-
-unix_get_data(Port, Sofar) ->
- receive
- {Port,{data, Bytes}} ->
- case eot(Bytes) of
- {done, Last} ->
- lists:flatten([Sofar|Last]);
- more ->
- unix_get_data(Port, [Sofar|Bytes])
- end;
- {'EXIT', Port, _} ->
- lists:flatten(Sofar)
- end.
-
-%%
-%% eot(String) -> more | {done, Result}
-%%
-eot(Bs) ->
- eot(Bs, []).
-
-eot([4| _Bs], As) ->
- {done, lists:reverse(As)};
-eot([B| Bs], As) ->
- eot(Bs, [B| As]);
-eot([], _As) ->
- more.
-
-%%
-%% mk_cmd(Cmd) -> {ok, ShellCommandString} | {error, ErrorString}
-%%
-%% We do not allow any input to Cmd (hence commands that want
-%% to read from standard input will return immediately).
-%% Standard error is redirected to standard output.
-%%
-%% We use ^D (= EOT = 4) to mark the end of the stream.
-%%
-mk_cmd(Cmd) when is_atom(Cmd) -> % backward comp.
- mk_cmd(atom_to_list(Cmd));
-mk_cmd(Cmd) ->
- %% We insert a new line after the command, in case the command
- %% contains a comment character.
- [$(, unicode:characters_to_binary(Cmd), "\n) </dev/null; echo \"\^D\"\n"].
-
+mk_cmd({win32,Wtype}, Cmd) ->
+ Command = case {os:getenv("COMSPEC"),Wtype} of
+ {false,windows} -> lists:concat(["command.com /c", Cmd]);
+ {false,_} -> lists:concat(["cmd /c", Cmd]);
+ {Cspec,_} -> lists:concat([Cspec," /c",Cmd])
+ end,
+ {Command, [], []};
+mk_cmd(OsType,Cmd) when is_atom(Cmd) ->
+ mk_cmd(OsType, atom_to_list(Cmd));
+mk_cmd(_,Cmd) ->
+ %% Have to send command in like this in order to make sh commands like
+ %% cd and ulimit available
+ {"/bin/sh -s unix:cmd", [out],
+ %% We insert a new line after the command, in case the command
+ %% contains a comment character.
+ ["(", unicode:characters_to_binary(Cmd), "\n); exit\n"]}.
validate(Atom) when is_atom(Atom) ->
ok;
@@ -397,7 +270,7 @@ validate1([]) ->
get_data(Port, Sofar) ->
receive
{Port, {data, Bytes}} ->
- get_data(Port, [Sofar|Bytes]);
+ get_data(Port, [Sofar,Bytes]);
{Port, eof} ->
Port ! {self(), close},
receive
@@ -410,5 +283,5 @@ get_data(Port, Sofar) ->
after 1 -> % force context switch
ok
end,
- lists:flatten(Sofar)
+ iolist_to_binary(Sofar)
end.
diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl
index d3db8eb80a..b9284487d2 100644
--- a/lib/kernel/src/rpc.erl
+++ b/lib/kernel/src/rpc.erl
@@ -357,8 +357,12 @@ do_call(Node, Request, Timeout) ->
rpc_check_t({'EXIT', {timeout,_}}) -> {badrpc, timeout};
rpc_check_t(X) -> rpc_check(X).
-rpc_check({'EXIT', {{nodedown,_},_}}) -> {badrpc, nodedown};
-rpc_check({'EXIT', X}) -> exit(X);
+rpc_check({'EXIT', {{nodedown,_},_}}) ->
+ {badrpc, nodedown};
+rpc_check({'EXIT', _}=Exit) ->
+ %% Should only happen if the rex process on the other node
+ %% died.
+ {badrpc, Exit};
rpc_check(X) -> X.
diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile
index 9e972b4f95..7b233741e0 100644
--- a/lib/kernel/test/Makefile
+++ b/lib/kernel/test/Makefile
@@ -79,7 +79,8 @@ MODULES= \
zlib_SUITE \
loose_node \
sendfile_SUITE \
- standard_error_SUITE
+ standard_error_SUITE \
+ multi_load_SUITE
APP_FILES = \
appinc.app \
@@ -112,7 +113,7 @@ RELSYSDIR = $(RELEASE_PATH)/kernel_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_COMPILE_FLAGS +=
EBIN = .
diff --git a/lib/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl
index 0c198b90ae..a0a7632d1b 100644
--- a/lib/kernel/test/application_SUITE.erl
+++ b/lib/kernel/test/application_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(application_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2
@@ -40,14 +40,14 @@
shutdown_func/1, do_shutdown/1, shutdown_timeout/1, shutdown_deadlock/1]).
-define(TESTCASE, testcase_name).
--define(testcase, ?config(?TESTCASE, Config)).
+-define(testcase, proplists:get_value(?TESTCASE, Config)).
-export([init_per_testcase/2, end_per_testcase/2, start_type/0,
start_phase/0, conf_change/0]).
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(2)).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,2}}].
all() ->
[failover, failover_comp, permissions, load,
@@ -81,21 +81,15 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(otp_2973=Case, Config) ->
- code:add_path(?config(data_dir,Config)),
- Dog = test_server:timetrap(?default_timeout),
- [{?TESTCASE, Case}, {watchdog, Dog}|Config];
+ code:add_path(proplists:get_value(data_dir,Config)),
+ [{?TESTCASE, Case}|Config];
init_per_testcase(Case, Config) ->
- Dog = test_server:timetrap(?default_timeout),
- [{?TESTCASE, Case}, {watchdog, Dog}|Config].
+ [{?TESTCASE, Case}|Config].
end_per_testcase(otp_2973, Config) ->
- code:del_path(?config(data_dir,Config)),
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+ code:del_path(proplists:get_value(data_dir,Config)),
ok;
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
-define(UNTIL(Seq), loop_until_true(fun() -> Seq end)).
@@ -120,10 +114,8 @@ loop_until_true(Fun) ->
%% Should be started in a CC view with:
%% erl -sname XXX -rsh ctrsh where XX not in [cp1, cp2, cp3]
%%-----------------------------------------------------------------
-failover(suite) -> [];
-failover(doc) ->
- ["Tests failover and takeover for distributed applications. Tests",
- "start, load etc implicitly."];
+%% Tests failover and takeover for distributed applications. Tests
+%% start, load etc implicitly.
failover(Conf) when is_list(Conf) ->
%% start a help process to check the start type
StPid = spawn_link(?MODULE, start_type, []),
@@ -133,14 +125,14 @@ failover(Conf) when is_list(Conf) ->
NoSyncTime = config_fun_fast(config_fo(NodeNames)),
WithSyncTime = config_fun(config_fo(NodeNames)),
- % Test [cp1, cp2, cp3]
+ %% Test [cp1, cp2, cp3]
{ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf),
{ok, Cp2} = start_node_config(Ncp2, NoSyncTime, Conf),
{ok, Cp3} = start_node_config(Ncp3, WithSyncTime, Conf),
Cps = [Cp1, Cp2, Cp3],
wait_for_ready_net(),
- % Start app1 and make sure cp1 starts it
+ %% Start app1 and make sure cp1 starts it
{[ok,ok,ok],[]} =
rpc:multicall(Cps, application, load, [app1()]),
?UNTIL(is_loaded(app1, Cps)),
@@ -150,12 +142,12 @@ failover(Conf) when is_list(Conf) ->
false = is_started(app1, Cp2),
ok = get_start_type(#st{normal = 3}),
- % Stop cp1 and make sure cp2 starts app1
+ %% Stop cp1 and make sure cp2 starts app1
stop_node_nice(Cp1),
?UNTIL(is_started(app1, Cp2)),
ok = get_start_type(#st{normal = 3}),
- % Restart cp1 and make sure it restarts app1
+ %% Restart cp1 and make sure it restarts app1
{ok, Cp1_2} = start_node_config(Ncp1, NoSyncTime, Conf),
global:sync(),
ok = rpc:call(Cp1_2, application, load, [app1()]),
@@ -164,8 +156,8 @@ failover(Conf) when is_list(Conf) ->
?UNTIL(not is_started(app1, Cp2)),
ok = get_start_type(#st{takeover = 3}),
- % Test [{cp1, cp2}, cp3]
- % Start app_sp and make sure cp2 starts it (cp1 has more apps started)
+ %% Test [{cp1, cp2}, cp3]
+ %% Start app_sp and make sure cp2 starts it (cp1 has more apps started)
{[ok,ok,ok],[]} =
rpc:multicall([Cp1_2, Cp2, Cp3], application, load, [app_sp()]),
{[ok,ok,ok],[]} =
@@ -175,17 +167,17 @@ failover(Conf) when is_list(Conf) ->
false = is_started(app_sp, Cp3),
ok = get_start_type(#st{normal = 3}),
- % Stop cp2 and make sure cp1 starts app_sp
+ %% Stop cp2 and make sure cp1 starts app_sp
stop_node_nice(Cp2),
?UNTIL(is_started(app_sp, Cp1_2)),
ok = get_start_type(#st{failover = 3}),
- % Stop cp1 and make sure cp3 starts app_sp
+ %% Stop cp1 and make sure cp3 starts app_sp
stop_node_nice(Cp1_2),
?UNTIL(is_started(app_sp, Cp3)),
ok = get_start_type(#st{normal = 3, failover = 3}),
- % Restart cp2 and make sure it restarts app_sp
+ %% Restart cp2 and make sure it restarts app_sp
{ok, Cp2_2} = start_node_config(Ncp2, NoSyncTime, Conf),
global:sync(),
ok = rpc:call(Cp2_2, application, load, [app_sp()]),
@@ -194,16 +186,16 @@ failover(Conf) when is_list(Conf) ->
?UNTIL(not is_started(app_sp, Cp3)),
ok = get_start_type(#st{takeover = 3}),
- % Restart cp1 and make sure it doesn't restart app_sp
+ %% Restart cp1 and make sure it doesn't restart app_sp
{ok, Cp1_3} = start_node_config(Ncp1, NoSyncTime, Conf),
global:sync(),
ok = rpc:call(Cp1_3, application, load, [app_sp()]),
ok = rpc:call(Cp1_3, application, start, [app_sp, permanent]),
- test_server:sleep(500),
+ ct:sleep(500),
false = is_started(app_sp, Cp1_3),
true = is_started(app_sp, Cp2_2),
- % Force takeover to cp1
+ %% Force takeover to cp1
ok = rpc:call(Cp1_3, application, takeover, [app_sp, permanent]),
?UNTIL(is_started(app_sp, Cp1_3)),
?UNTIL(not is_started(app_sp, Cp2_2)),
@@ -225,11 +217,9 @@ failover(Conf) when is_list(Conf) ->
%% Should be started in a CC view with:
%% erl -sname XXX -rsh ctrsh where XX not in [cp1, cp2, cp3]
%%-----------------------------------------------------------------
-failover_comp(suite) -> [];
-failover_comp(doc) ->
- ["Tests failover and takeover for distributed applications. Tests",
- "start, load etc implicitly. The applications do not use start_phases,"
- "i.e the failover should be trasfered to normal start type."];
+%% Tests failover and takeover for distributed applications. Tests
+%% start, load etc implicitly. The applications do not use start_phases
+%% i.e. the failover should be transfered to normal start type.
failover_comp(Conf) when is_list(Conf) ->
%% start a help process to check the start type
StPid = spawn_link(?MODULE, start_type, []),
@@ -239,14 +229,14 @@ failover_comp(Conf) when is_list(Conf) ->
NoSyncTime = config_fun_fast(config(NodeNames)),
WithSyncTime = config_fun(config(NodeNames)),
- % Test [cp1, cp2, cp3]
+ %% Test [cp1, cp2, cp3]
{ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf),
{ok, Cp2} = start_node_config(Ncp2, NoSyncTime, Conf),
{ok, Cp3} = start_node_config(Ncp3, WithSyncTime, Conf),
Cps = [Cp1, Cp2, Cp3],
wait_for_ready_net(),
- % Start app1 and make sure cp1 starts it
+ %% Start app1 and make sure cp1 starts it
{[ok,ok,ok],[]} =
rpc:multicall(Cps, application, load, [app1()]),
?UNTIL(is_loaded(app1, Cps)),
@@ -256,12 +246,12 @@ failover_comp(Conf) when is_list(Conf) ->
false = is_started(app1, Cp2),
ok = get_start_type(#st{normal = 3}),
- % Stop cp1 and make sure cp2 starts app1
+ %% Stop cp1 and make sure cp2 starts app1
stop_node_nice(Cp1),
?UNTIL(is_started(app1, Cp2)),
ok = get_start_type(#st{normal = 3}),
- % Restart cp1 and make sure it restarts app1
+ %% Restart cp1 and make sure it restarts app1
{ok, Cp1_2} = start_node_config(Ncp1, NoSyncTime, Conf),
global:sync(),
ok = rpc:call(Cp1_2, application, load, [app1()]),
@@ -271,8 +261,8 @@ failover_comp(Conf) when is_list(Conf) ->
?UNTIL(not is_started(app1, Cp2)),
ok = get_start_type(#st{takeover = 3}),
- % Test [{cp1, cp2}, cp3]
- % Start app3 and make sure cp2 starts it (cp1 has more apps started)
+ %% Test [{cp1, cp2}, cp3]
+ %% Start app3 and make sure cp2 starts it (cp1 has more apps started)
{[ok,ok,ok],[]} =
rpc:multicall([Cp1_2, Cp2, Cp3], application, load, [app3()]),
?UNTIL(is_loaded(app3, [Cp1_2, Cp2, Cp3])),
@@ -283,17 +273,17 @@ failover_comp(Conf) when is_list(Conf) ->
false = is_started(app3, Cp3),
ok = get_start_type(#st{normal = 3}),
- % Stop cp2 and make sure cp1 starts app3
+ %% Stop cp2 and make sure cp1 starts app3
stop_node_nice(Cp2),
?UNTIL(is_started(app3, Cp1_2)),
ok = get_start_type(#st{normal = 3}),
- % Stop cp1 and make sure cp3 starts app3
+ %% Stop cp1 and make sure cp3 starts app3
stop_node_nice(Cp1_2),
?UNTIL(is_started(app3, Cp3)),
ok = get_start_type(#st{normal = 6}),
- % Restart cp2 and make sure it restarts app3
+ %% Restart cp2 and make sure it restarts app3
{ok, Cp2_2} = start_node_config(Ncp2, NoSyncTime, Conf),
global:sync(),
ok = rpc:call(Cp2_2, application, load, [app3()]),
@@ -303,17 +293,17 @@ failover_comp(Conf) when is_list(Conf) ->
?UNTIL(not is_started(app3, Cp3)),
ok = get_start_type(#st{takeover = 3}),
- % Restart cp1 and make sure it doesn't restart app3
+ %% Restart cp1 and make sure it doesn't restart app3
{ok, Cp1_3} = start_node_config(Ncp1, NoSyncTime, Conf),
global:sync(),
ok = rpc:call(Cp1_3, application, load, [app3()]),
true = is_loaded(app3, Cp1_3),
ok = rpc:call(Cp1_3, application, start, [app3, permanent]),
- test_server:sleep(5000),
+ ct:sleep(5000),
false = is_started(app3, Cp1_3),
true = is_started(app3, Cp2_2),
- % Force takeover to cp1
+ %% Force takeover to cp1
ok = rpc:call(Cp1_3, application, takeover, [app3, permanent]),
?UNTIL(is_started(app3, Cp1_3)),
?UNTIL(not is_started(app3, Cp2_2)),
@@ -335,23 +325,21 @@ failover_comp(Conf) when is_list(Conf) ->
%% Should be started in a CC view with:
%% erl -sname XXX -rsh ctrsh where XX not in [cp1, cp2, cp3]
%%-----------------------------------------------------------------
-permissions(suite) -> [];
-permissions(doc) ->
- ["Tests permissions for distributed applications."];
+%% Tests permissions for distributed applications.
permissions(Conf) when is_list(Conf) ->
NodeNames = [Ncp1, Ncp2, Ncp3] = node_names([cp1, cp2, cp3], Conf),
NoSyncTime = config_fun_fast(config2(NodeNames)),
WithSyncTime = config_fun(config2(NodeNames)),
- % Test [cp1, cp2, cp3]
+ %% Test [cp1, cp2, cp3]
{ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf),
{ok, Cp2} = start_node_config(Ncp2, NoSyncTime, Conf),
{ok, Cp3} = start_node_config(Ncp3, WithSyncTime, Conf),
Cps = [Cp1, Cp2, Cp3],
wait_for_ready_net(),
- % Start app1 and make sure cp1 starts it
+ %% Start app1 and make sure cp1 starts it
{[ok,ok,ok],[]} =
rpc:multicall(Cps, application, load, [app1()]),
?UNTIL(is_loaded(app1, Cps)),
@@ -360,50 +348,50 @@ permissions(Conf) when is_list(Conf) ->
?UNTIL(is_started(app1, Cp1)),
false = is_started(app1, Cp2),
- % Unpermit app1 on cp1, make sure cp2 starts it
+ %% Unpermit app1 on cp1, make sure cp2 starts it
ok = rpc:call(Cp1, application, permit, [app1, false]),
false = is_started(app1, Cp1),
true = is_started(app1, Cp2),
- % Unpermit app1 on cp2, make sure cp3 starts it
+ %% Unpermit app1 on cp2, make sure cp3 starts it
ok = rpc:call(Cp2, application, permit, [app1, false]),
false = is_started(app1, Cp1),
false = is_started(app1, Cp2),
true = is_started(app1, Cp3),
- % Permit cp2 again
+ %% Permit cp2 again
ok = rpc:call(Cp2, application, permit, [app1, true]),
false = is_started(app1, Cp1),
false = is_started(app1, Cp3),
true = is_started(app1, Cp2),
- % Start app3, make sure noone starts it
+ %% Start app3, make sure noone starts it
{[ok,ok,ok],[]} =
rpc:multicall(Cps, application, load, [app3()]),
?UNTIL(is_loaded(app3, Cps)),
{[ok,ok,ok],[]} =
rpc:multicall(Cps, application, start, [app3, permanent]),
- test_server:sleep(1000),
+ ct:sleep(1000),
false = is_started(app3, Cp1),
false = is_started(app3, Cp2),
false = is_started(app3, Cp3),
- % Permit app3 on Cp3
+ %% Permit app3 on Cp3
ok = rpc:call(Cp3, application, permit, [app3, true]),
true = is_started(app3, Cp3),
- % Permit app3 on Cp2, make sure it starts it
+ %% Permit app3 on Cp2, make sure it starts it
ok = rpc:call(Cp2, application, permit, [app3, true]),
true = is_started(app3, Cp2),
false = is_started(app3, Cp3),
- % Permit app3 on Cp1, make sure it doesn't start it
+ %% Permit app3 on Cp1, make sure it doesn't start it
ok = rpc:call(Cp1, application, permit, [app3, true]),
false = is_started(app3, Cp1),
true = is_started(app3, Cp2),
false = is_started(app3, Cp3),
- % Stop Cp2, make sure Cp1 starts app3
+ %% Stop Cp2, make sure Cp1 starts app3
stop_node_nice(Cp2),
?UNTIL(is_started(app3, Cp1)),
@@ -415,15 +403,13 @@ permissions(Conf) when is_list(Conf) ->
%% Should be started in a CC view with:
%% erl -sname XXX -rsh ctrsh where XX not in [cp1, cp2, cp3]
%%-----------------------------------------------------------------
-load(suite) -> [];
-load(doc) ->
- ["Tests loading of distributed applications."];
+%% Tests loading of distributed applications.
load(Conf) when is_list(Conf) ->
NodeNames = [Ncp1, Ncp2, Ncp3] = node_names([cp1, cp2, cp3], Conf),
NoSyncTime = config_fun_fast(config3(NodeNames)),
WithSyncTime = config_fun(config3(NodeNames)),
- % Test [cp1, cp2, cp3]
+ %% Test [cp1, cp2, cp3]
{ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf),
{ok, Cp2} = start_node_config(Ncp2, NoSyncTime, Conf),
{ok, Cp3} = start_node_config(Ncp3, WithSyncTime, Conf),
@@ -439,7 +425,7 @@ load(Conf) when is_list(Conf) ->
false = is_started(app1, Cp2),
false = is_started(app1, Cp3),
- % Load app1 with different specs and make sure we get an error
+ %% Load app1 with different specs and make sure we get an error
{[{error,_},{error,_}],[]} =
rpc:multicall([Cp1, Cp2], application, load, [app1(), d1(NodeNames)]),
{error, _} = rpc:call(Cp3, application, load, [app1(), d2(NodeNames)]),
@@ -452,15 +438,13 @@ load(Conf) when is_list(Conf) ->
%%-----------------------------------------------------------------
%% Same test as load/1, only with code path cache enabled.
%%-----------------------------------------------------------------
-load_use_cache(suite) -> [];
-load_use_cache(doc) ->
- ["Tests loading of distributed applications. Code path cache enabled."];
+%% Tests loading of distributed applications. Code path cache enabled.
load_use_cache(Conf) when is_list(Conf) ->
NodeNames = [Ncp1, Ncp2, Ncp3] = node_names([cp1, cp2, cp3], Conf),
NoSyncTime = config_fun_fast(config3(NodeNames)),
WithSyncTime = config_fun(config3(NodeNames)),
- % Test [cp1, cp2, cp3]
+ %% Test [cp1, cp2, cp3]
{ok, Cp1} = start_node_with_cache(Ncp1, NoSyncTime, Conf),
{ok, Cp2} = start_node_with_cache(Ncp2, NoSyncTime, Conf),
{ok, Cp3} = start_node_with_cache(Ncp3, WithSyncTime, Conf),
@@ -475,7 +459,7 @@ load_use_cache(Conf) when is_list(Conf) ->
?UNTIL(is_started(app1, Cp1)),
false = is_started(app1, Cp2),
- % Load app1 with different specs and make sure we get an error
+ %% Load app1 with different specs and make sure we get an error
{[{error,_},{error,_}],[]} =
rpc:multicall([Cp1, Cp2], application, load, [app1(), d1(NodeNames)]),
{error, _} = rpc:call(Cp3, application, load, [app1(), d2(NodeNames)]),
@@ -489,9 +473,7 @@ load_use_cache(Conf) when is_list(Conf) ->
%% Should be started in a CC view with:
%% erl -sname XXX -rsh ctrsh where XX not in [cp1, cp2, cp3]
%%-----------------------------------------------------------------
-start_phases(suite) -> [];
-start_phases(doc) ->
- ["Tests new start phases and failover."];
+%% Tests new start phases and failover.
start_phases(Conf) when is_list(Conf) ->
%% start a help process to check the start type
SpPid = spawn_link(?MODULE, start_phase, []),
@@ -553,17 +535,15 @@ start_phases(Conf) when is_list(Conf) ->
ok.
-script_start(doc) ->
- ["Start distributed applications from within a boot script. Test ",
- "same as failover."];
-script_start(suite) -> [];
+%% Start distributed applications from within a boot script. Test
+%% same as failover.
script_start(Conf) when is_list(Conf) ->
%% start a help process to check the start type
StPid = spawn_link(?MODULE, start_type, []),
yes = global:register_name(st_type, StPid),
- % Create the .app files and the boot script
+ %% Create the .app files and the boot script
ok = create_app(),
{{KernelVer,StdlibVer}, _} = create_script("latest"),
case is_real_system(KernelVer, StdlibVer) of
@@ -578,7 +558,7 @@ script_start(Conf) when is_list(Conf) ->
NoSyncTime = config_fun_fast(config_fo(NodeNames)),
WithSyncTime = config_fun(config_fo(NodeNames)),
- % Test [cp1, cp2, cp3]
+ %% Test [cp1, cp2, cp3]
{ok, Cp1} = start_node_boot_config(Ncp1, NoSyncTime, Conf, latest),
{ok, Cp2} = start_node_boot_config(Ncp2, NoSyncTime, Conf, latest),
{ok, Cp3} = start_node_boot_config(Ncp3, WithSyncTime, Conf, latest),
@@ -590,16 +570,16 @@ script_start(Conf) when is_list(Conf) ->
false = is_started(app1, Cp2),
ok = get_start_type(#st{normal = 9}),
- % Stop cp1 and make sure cp2 starts app1, app2 normally (no
- % start_phases defined) and app_sp as failover (start_phases
- % defined)
+ %% Stop cp1 and make sure cp2 starts app1, app2 normally (no
+ %% start_phases defined) and app_sp as failover (start_phases
+ %% defined)
stop_node_nice(Cp1),
?UNTIL(is_started(app1, Cp2)),
?UNTIL(is_started(app2, Cp2)),
?UNTIL(is_started(app_sp, Cp2)),
ok = get_start_type(#st{normal = 6, failover = 3}),
- % Restart cp1, Cp1 takesover app1 and app2
+ %% Restart cp1, Cp1 takesover app1 and app2
{ok, Cp1_2} = start_node_boot_config(Ncp1, NoSyncTime, Conf, latest),
global:sync(),
?UNTIL(is_started(app1, Cp1_2)),
@@ -610,20 +590,20 @@ script_start(Conf) when is_list(Conf) ->
?UNTIL(not is_started(app2, Cp2)),
ok = get_start_type(#st{takeover = 6}),
- % Stop cp2 and make sure cp1 starts app_sp.
+ %% Stop cp2 and make sure cp1 starts app_sp.
false = is_started(app_sp, Cp1_2),
stop_node_nice(Cp2),
?UNTIL(is_started(app_sp, Cp1_2)),
ok = get_start_type(#st{failover = 3}),
- % Stop cp1 and make sure cp3 starts app1, app2 and app_sp
+ %% Stop cp1 and make sure cp3 starts app1, app2 and app_sp
stop_node_nice(Cp1_2),
?UNTIL(is_started(app_sp, Cp3)),
?UNTIL(is_started(app1, Cp3)),
?UNTIL(is_started(app2, Cp3)),
ok = get_start_type(#st{normal = 6, failover = 3}),
- % Restart cp2 and make sure it takesover app1, app2 and app_sp
+ %% Restart cp2 and make sure it takesover app1, app2 and app_sp
{ok, Cp2_2} = start_node_boot_config(Ncp2, NoSyncTime, Conf, latest),
global:sync(),
?UNTIL(is_started(app_sp, Cp2_2)),
@@ -634,7 +614,7 @@ script_start(Conf) when is_list(Conf) ->
?UNTIL(not is_started(app2, Cp3)),
ok = get_start_type(#st{takeover = 9}),
- % Restart cp1 and make sure it takesover app1, app2
+ %% Restart cp1 and make sure it takesover app1, app2
{ok, Cp1_3} = start_node_boot_config(Ncp1, NoSyncTime, Conf, latest),
global:sync(),
?UNTIL(is_started(app1, Cp1_3)),
@@ -645,7 +625,7 @@ script_start(Conf) when is_list(Conf) ->
?UNTIL(not is_started(app2, Cp2_2)),
ok = get_start_type(#st{takeover = 6}),
- % Force takeover to cp1
+ %% Force takeover to cp1
ok = rpc:call(Cp1_3, application, takeover, [app_sp, permanent]),
?UNTIL(is_started(app_sp, Cp1_3)),
?UNTIL(not is_started(app_sp, Cp2_2)),
@@ -668,15 +648,13 @@ script_start(Conf) when is_list(Conf) ->
ok.
-permit_false_start_local(doc) ->
- ["Start local applications with permission false. Set",
- "permit true on different nodes."];
-permit_false_start_local(suite) -> [];
+%% Start local applications with permission false. Set
+%% permit true on different nodes.
permit_false_start_local(Conf) when is_list(Conf) ->
%% This configuration does not start dist_ac.
Config = write_config_file(fun config_perm/1, Conf),
- % Test [cp1, cp2, cp3]
+ %% Test [cp1, cp2, cp3]
[Ncp1, Ncp2, Ncp3] = node_names([cp1, cp2, cp3], Conf),
{ok, Cp1} = start_node(Ncp1, Config),
{ok, Cp2} = start_node(Ncp2, Config),
@@ -694,99 +672,99 @@ permit_false_start_local(Conf) when is_list(Conf) ->
{[ok,ok,ok],[]} =
rpc:multicall([Cp1, Cp2, Cp3], application, load, [app3()]),
- test_server:sleep(1000),
+ ct:sleep(1000),
false = is_started(app1, Cp1),
false = is_started(app1, Cp2),
false = is_started(app1, Cp3),
- %Permit a not started application
+ %% Permit a not started application
ok = rpc:call(Cp1, application, permit, [app3, true]),
- test_server:sleep(1000),
+ ct:sleep(1000),
false = is_started(app3, Cp1),
false = is_started(app3, Cp2),
false = is_started(app3, Cp3),
- %Permit a not loaded application
+ %% Permit a not loaded application
{error,{not_loaded,app_notloaded}} =
rpc:call(Cp1, application, permit, [app_notloaded, true]),
- test_server:sleep(1000),
+ ct:sleep(1000),
false = is_started(app_notloaded, Cp1),
false = is_started(app_notloaded, Cp2),
false = is_started(app_notloaded, Cp3),
- %Unpermit a not started application
+ %% Unpermit a not started application
ok = rpc:call(Cp1, application, permit, [app3, false]),
- test_server:sleep(1000),
+ ct:sleep(1000),
false = is_started(app3, Cp1),
false = is_started(app3, Cp2),
false = is_started(app3, Cp3),
- %Unpermit a not loaded application
+ %% Unpermit a not loaded application
{error,{not_loaded,app_notloaded}} =
rpc:call(Cp1, application, permit, [app_notloaded, false]),
- test_server:sleep(1000),
+ ct:sleep(1000),
false = is_started(app_notloaded, Cp1),
false = is_started(app_notloaded, Cp2),
false = is_started(app_notloaded, Cp3),
- % Permit app1 on CP1 and make sure it is started
+ %% Permit app1 on CP1 and make sure it is started
ok = rpc:call(Cp1, application, permit, [app1, true]),
?UNTIL(is_started(app1, Cp1)),
false = is_started(app1, Cp2),
false = is_started(app1, Cp3),
- % Permit it again
+ %% Permit it again
ok = rpc:call(Cp1, application, permit, [app1, true]),
- test_server:sleep(1000),
+ ct:sleep(1000),
true = is_started(app1, Cp1),
false = is_started(app1, Cp2),
false = is_started(app1, Cp3),
- % Permit app2 on CP1 and make sure it is started
+ %% Permit app2 on CP1 and make sure it is started
ok = rpc:call(Cp1, application, permit, [app2, true]),
?UNTIL(is_started(app2, Cp1)),
false = is_started(app2, Cp2),
false = is_started(app2, Cp3),
- % Permit app1 on CP2 and make sure it is started
+ %% Permit app1 on CP2 and make sure it is started
ok = rpc:call(Cp2, application, permit, [app1, true]),
?UNTIL(is_started(app1, Cp2)),
true = is_started(app1, Cp1),
false = is_started(app1, Cp3),
- % Unpermit app1 on CP1 and make sure it is stopped
+ %% Unpermit app1 on CP1 and make sure it is stopped
ok = rpc:call(Cp1, application, permit, [app1, false]),
?UNTIL(false =:= is_started(app1, Cp1)),
true = is_started(app1, Cp2),
false = is_started(app1, Cp3),
- % Unpermit it agin
+ %% Unpermit it agin
ok = rpc:call(Cp1, application, permit, [app1, false]),
- test_server:sleep(1000),
+ ct:sleep(1000),
false = is_started(app1, Cp1),
true = is_started(app1, Cp2),
false = is_started(app1, Cp3),
- % Permit app1 on CP1 and make sure it is started
+ %% Permit app1 on CP1 and make sure it is started
ok = rpc:call(Cp1, application, permit, [app1, true]),
?UNTIL(is_started(app1, Cp1)),
true = is_started(app1, Cp2),
false = is_started(app1, Cp3),
- % Unpermit app1 on CP1 and make sure it is stopped
+ %% Unpermit app1 on CP1 and make sure it is stopped
ok = rpc:call(Cp1, application, permit, [app1, false]),
?UNTIL(false =:= is_started(app1, Cp1)),
true = is_started(app1, Cp2),
false = is_started(app1, Cp3),
- % Unpermit app1 on CP2 and make sure it is stopped
+ %% Unpermit app1 on CP2 and make sure it is stopped
ok = rpc:call(Cp2, application, permit, [app1, false]),
- test_server:sleep(1000),
+ ct:sleep(1000),
?UNTIL(false =:= is_started(app1, Cp2)),
false = is_started(app1, Cp1),
false = is_started(app1, Cp3),
- % Unpermit app2 on CP1 and make sure it is stopped
+ %% Unpermit app2 on CP1 and make sure it is stopped
ok = rpc:call(Cp1, application, permit, [app2, false]),
?UNTIL(false =:= is_started(app2, Cp2)),
false = is_started(app2, Cp1),
@@ -798,16 +776,14 @@ permit_false_start_local(Conf) when is_list(Conf) ->
ok.
-permit_false_start_dist(doc) ->
- ["Start distributed applications with permission false. Set",
- "permit true on different nodes."];
-permit_false_start_dist(suite) -> [];
+%% Start distributed applications with permission false. Set
+%% permit true on different nodes.
permit_false_start_dist(Conf) when is_list(Conf) ->
NodeNames = [Ncp1, Ncp2, Ncp3] = node_names([cp1, cp2, cp3], Conf),
NoSyncTime = config_fun_fast(config_perm2(NodeNames)),
WithSyncTime = config_fun(config_perm2(NodeNames)),
- % Test [cp1, cp2, cp3]
+ %% Test [cp1, cp2, cp3]
{ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf),
{ok, Cp2} = start_node_config(Ncp2, NoSyncTime, Conf),
{ok, Cp3} = start_node_config(Ncp3, WithSyncTime, Conf),
@@ -822,36 +798,36 @@ permit_false_start_dist(Conf) when is_list(Conf) ->
{[ok,ok,ok],[]} =
rpc:multicall(Cps, application, load, [app2()]),
- test_server:sleep(1000),
+ ct:sleep(1000),
false = is_started(app1, Cp1),
false = is_started(app1, Cp2),
false = is_started(app1, Cp3),
- %Permit a not started application
+ %% Permit a not started application
ok = rpc:call(Cp1, application, permit, [app2, true]),
- test_server:sleep(1000),
+ ct:sleep(1000),
false = is_started(app2, Cp1),
false = is_started(app2, Cp2),
false = is_started(app2, Cp3),
- %Permit a not loaded application
+ %% Permit a not loaded application
{error,{not_loaded,app3}} =
rpc:call(Cp1, application, permit, [app3, true]),
- test_server:sleep(1000),
+ ct:sleep(1000),
false = is_started(app3, Cp1),
false = is_started(app3, Cp2),
false = is_started(app3, Cp3),
- %Unpermit a not started application
+ %% Unpermit a not started application
ok = rpc:call(Cp1, application, permit, [app2, false]),
{[ok,ok,ok],[]} =
rpc:multicall([Cp1, Cp2, Cp3], application, start, [app2, permanent]),
- test_server:sleep(1000),
+ ct:sleep(1000),
false = is_started(app2, Cp1),
false = is_started(app2, Cp2),
false = is_started(app2, Cp3),
- %Unpermit a not loaded application
+ %% Unpermit a not loaded application
{error,{not_loaded,app3}} =
rpc:call(Cp1, application, permit, [app3, false]),
{[ok,ok,ok],[]} =
@@ -859,42 +835,42 @@ permit_false_start_dist(Conf) when is_list(Conf) ->
?UNTIL(is_loaded(app3, Cps)),
{[ok,ok,ok],[]} =
rpc:multicall(Cps, application, start, [app3, permanent]),
- test_server:sleep(1000),
+ ct:sleep(1000),
false = is_started(app3, Cp1),
false = is_started(app3, Cp2),
false = is_started(app3, Cp3),
- % Permit app1 on CP1 and make sure it is started
+ %% Permit app1 on CP1 and make sure it is started
ok = rpc:call(Cp1, application, permit, [app1, true]),
?UNTIL(is_started(app1, Cp1)),
false = is_started(app1, Cp2),
false = is_started(app1, Cp3),
- % Permit it again
+ %% Permit it again
ok = rpc:call(Cp1, application, permit, [app1, true]),
?UNTIL(is_started(app1, Cp1)),
false = is_started(app1, Cp2),
false = is_started(app1, Cp3),
- % Permit app2 on CP1 and make sure it is started
+ %% Permit app2 on CP1 and make sure it is started
ok = rpc:call(Cp1, application, permit, [app2, true]),
?UNTIL(is_started(app2, Cp1)),
false = is_started(app2, Cp2),
false = is_started(app2, Cp3),
- % Permit app1 on CP2 and make sure it is not started
+ %% Permit app1 on CP2 and make sure it is not started
ok = rpc:call(Cp2, application, permit, [app1, true]),
- test_server:sleep(1000),
+ ct:sleep(1000),
true = is_started(app1, Cp1),
false = is_started(app1, Cp2),
false = is_started(app1, Cp3),
- % Crash CP1 and make sure app1, but not app2, is started on CP2
+ %% Crash CP1 and make sure app1, but not app2, is started on CP2
stop_node_nice(Cp1),
?UNTIL(is_started(app1, Cp2)),
false = is_started(app2, Cp2),
- % Restart CP1 again, check nothing is running on it
+ %% Restart CP1 again, check nothing is running on it
{ok, Cp1_2} = start_node_config(Ncp1, NoSyncTime, Conf),
global:sync(),
ok = rpc:call(Cp1_2, application, load, [app1()]),
@@ -909,19 +885,19 @@ permit_false_start_dist(Conf) when is_list(Conf) ->
false = is_started(app1, Cp1_2),
false = is_started(app2, Cp1_2),
- % Permit app3 on CP3 and make sure it is started
+ %% Permit app3 on CP3 and make sure it is started
ok = rpc:call(Cp3, application, permit, [app3, true]),
?UNTIL(is_started(app3, Cp3)),
false = is_started(app3, Cp1_2),
false = is_started(app3, Cp2),
- % Permit app3 on CP1 and make sure it is moved there from CP3
+ %% Permit app3 on CP1 and make sure it is moved there from CP3
ok = rpc:call(Cp1_2, application, permit, [app3, true]),
?UNTIL(is_started(app3, Cp1_2)),
false = is_started(app3, Cp2),
false = is_started(app3, Cp3),
- % Unpermit app3 on CP3 and CP1 and make sure it is stopped
+ %% Unpermit app3 on CP3 and CP1 and make sure it is stopped
ok = rpc:call(Cp3, application, permit, [app3, false]),
ok = rpc:call(Cp1_2, application, permit, [app3, false]),
?UNTIL(false =:= is_started(app3, Cp1_2)),
@@ -933,27 +909,25 @@ permit_false_start_dist(Conf) when is_list(Conf) ->
stop_node_nice(Cp3),
ok.
-nodedown_start(doc) ->
- ["app1 distributed as [cp1, cp2]. Call application:start(app1) on",
- "cp2, but not on cp1. Kill cp1. Make sure app1 is started on cp2."];
-nodedown_start(suite) -> [];
+%% app1 distributed as [cp1, cp2]. Call application:start(app1) on
+%% cp2, but not on cp1. Kill cp1. Make sure app1 is started on cp2.
nodedown_start(Conf) when is_list(Conf) ->
NodeNames = [Ncp1, Ncp2] = node_names([cp1, cp2], Conf),
NoSyncTime = config_fun_fast(config4(NodeNames)),
WithSyncTime = config_fun(config4(NodeNames)),
- % Test [cp1, cp2]
+ %% Test [cp1, cp2]
{ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf),
{ok, Cp2} = start_node_config(Ncp2, WithSyncTime, Conf),
wait_for_ready_net(),
- % Start app1 and make sure cp1 starts it
+ %% Start app1 and make sure cp1 starts it
{[ok,ok],[]} =
rpc:multicall([Cp1, Cp2], application, load, [app1()]),
_ = rpc:cast(Cp2, application, start, [app1, permanent]),
- test_server:sleep(1000),
+ ct:sleep(1000),
- % Crash CP1 and make sure app1 is started on CP2
+ %% Crash CP1 and make sure app1 is started on CP2
stop_node_nice(Cp1),
?UNTIL(is_started(app1, Cp2)),
@@ -961,8 +935,7 @@ nodedown_start(Conf) when is_list(Conf) ->
ok.
-ensure_started(suite) -> [];
-ensure_started(doc) -> ["Test application:ensure_started/1."];
+%% Test application:ensure_started/1.
ensure_started(_Conf) ->
{ok, Fd} = file:open("app1.app", [write]),
@@ -981,8 +954,7 @@ ensure_started(_Conf) ->
ok = application:unload(app1),
ok.
-ensure_all_started(suite) -> [];
-ensure_all_started(doc) -> ["Test application:ensure_all_started/1-2."];
+%% Test application:ensure_all_started/1-2.
ensure_all_started(_Conf) ->
{ok, Fd1} = file:open("app1.app", [write]),
@@ -1069,11 +1041,9 @@ ensure_all_started(_Conf) ->
%% Ticket: OTP-1586
%% Slogan: recursive load of applications fails
%%-----------------------------------------------------------------
-otp_1586(suite) -> [];
-otp_1586(doc) ->
- ["Test recursive load of applications."];
+%% Test recursive load of applications.
otp_1586(Conf) when is_list(Conf) ->
- Dir = ?config(priv_dir,Conf),
+ Dir = proplists:get_value(priv_dir,Conf),
{ok, Fd} = file:open(filename:join(Dir, "app5.app"), [write]),
w_app5(Fd),
file:close(Fd),
@@ -1090,21 +1060,19 @@ otp_1586(Conf) when is_list(Conf) ->
%% Slogan: start of distrib apps fails when the nodes start
%% simultaneously
%%-----------------------------------------------------------------
-otp_2078(suite) -> [];
-otp_2078(doc) ->
- ["Test start of distrib apps fails when the nodes start simultaneously."];
+%% Test start of distrib apps fails when the nodes start simultaneously.
otp_2078(Conf) when is_list(Conf) ->
NodeNames = [Ncp1, Ncp2] = node_names([cp1, cp2], Conf),
NoSyncTime = config_fun_fast(config4(NodeNames)),
WithSyncTime = config_fun(config4(NodeNames)),
- % Test [cp1, cp2]
+ %% Test [cp1, cp2]
{ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf),
{ok, Cp2} = start_node_config(Ncp2, WithSyncTime, Conf),
Cps = [Cp1, Cp2],
wait_for_ready_net(),
- % Start app1 and make sure cp1 starts it
+ %% Start app1 and make sure cp1 starts it
{[ok,ok],[]} =
rpc:multicall(Cps, application, load, [app1()]),
?UNTIL(is_loaded(app1, Cps)),
@@ -1112,8 +1080,8 @@ otp_2078(Conf) when is_list(Conf) ->
?UNTIL(is_started(app1, Cp1)),
false = is_started(app1, Cp2),
- % Start app1 on cp2; make sure it works (the bug was that this start
- % returned error)
+ %% Start app1 on cp2; make sure it works (the bug was that this start
+ %% returned error)
ok = rpc:call(Cp2, application, start, [app1, permanent]),
true = is_started(app1, Cp1),
false = is_started(app1, Cp2),
@@ -1122,15 +1090,13 @@ otp_2078(Conf) when is_list(Conf) ->
stop_node_nice(Cp2),
ok.
-otp_2012(suite) -> [];
-otp_2012(doc) ->
- ["Test change of configuration parameters without changing code."];
+%% Test change of configuration parameters without changing code.
otp_2012(Conf) when is_list(Conf) ->
%% start a help process to check the config change
CcPid = spawn_link(?MODULE, conf_change, []),
yes = global:register_name(conf_change, CcPid),
- % Write a .app file
+ %% Write a .app file
{ok, Fd} = file:open("app1.app", [write]),
w_app1(Fd),
file:close(Fd),
@@ -1138,7 +1104,7 @@ otp_2012(Conf) when is_list(Conf) ->
w_app1(Fd2),
file:close(Fd2),
- % Start app1
+ %% Start app1
ok = application:load(app1()),
ok = application:start(app1, permanent),
@@ -1149,7 +1115,7 @@ otp_2012(Conf) when is_list(Conf) ->
ok = application_controller:config_change(EnvBefore),
ok = get_conf_change([{[], [{new1, hi}, {new2, moi}], []}]),
- % Start app2
+ %% Start app2
ok = application:load(app2()),
ok = application:start(app2, permanent),
@@ -1173,11 +1139,9 @@ otp_2012(Conf) when is_list(Conf) ->
%% Ticket: OTP-2718
%% Slogan: transient app which fails during start is ignored
%%-----------------------------------------------------------------
-otp_2718(suite) -> [];
-otp_2718(doc) ->
- ["Test fail of transient app at start."];
+%% Test fail of transient app at start.
otp_2718(Conf) when is_list(Conf) ->
- {ok, Cp1} = start_node_args(cp1, "-pa " ++ ?config(data_dir,Conf)),
+ {ok, Cp1} = start_node_args(cp1, "-pa " ++ proplists:get_value(data_dir,Conf)),
wait_for_ready_net(),
%% normal exit from the application
@@ -1185,7 +1149,7 @@ otp_2718(Conf) when is_list(Conf) ->
?UNTIL(is_loaded(trans_normal, Cp1)),
{error, {{'EXIT',normal},_}} =
rpc:call(Cp1, application, start, [trans_normal, transient]),
- test_server:sleep(2000),
+ ct:sleep(2000),
false = is_started(trans_normal, Cp1),
%% abnormal exit from the application
@@ -1193,7 +1157,7 @@ otp_2718(Conf) when is_list(Conf) ->
{error, {bad_return,{{trans_abnormal_sup,start,[normal,[]]},
{'EXIT',abnormal}}}} =
rpc:call(Cp1, application, start, [trans_abnormal, transient]),
- test_server:sleep(3000),
+ ct:sleep(3000),
{badrpc,nodedown} = which_applications(Cp1),
ok.
@@ -1201,11 +1165,9 @@ otp_2718(Conf) when is_list(Conf) ->
%% Ticket: OTP-2973
%% Slogan: application:start does not test if an appl is already starting...
%%-----------------------------------------------------------------
-otp_2973(suite) -> [];
-otp_2973(doc) ->
- ["Test of two processes simultanously starting the same application."];
+%% Test of two processes simultanously starting the same application.
otp_2973(Conf) when is_list(Conf) ->
- % Write a .app file
+ %% Write a .app file
{ok, Fd} = file:open("app0.app", [write]),
w_app(Fd, app0()),
file:close(Fd),
@@ -1222,14 +1184,14 @@ otp_2973(Conf) when is_list(Conf) ->
{Pid2, res, Res2x} ->
{Res1x, Res2x}
after 2000 ->
- test_server:fail(timeout_pid2)
+ ct:fail(timeout_pid2)
end;
{Pid2, res, Res2x} ->
receive
{Pid1, res, Res1x} ->
{Res1x, Res2x}
after 2000 ->
- test_server:fail(timeout_pid1)
+ ct:fail(timeout_pid1)
end
end,
@@ -1243,11 +1205,11 @@ otp_2973(Conf) when is_list(Conf) ->
_ ->
Txt = io_lib:format("Illegal results from start: ~p ~p ",
[Res1, Res2]),
- test_server:fail(lists:flatten(Txt))
+ ct:fail(lists:flatten(Txt))
end,
- % Write a .app file
+ %% Write a .app file
{ok, Fda} = file:open("app_start_error.app", [write]),
w_app_start_error(Fda),
file:close(Fda),
@@ -1261,14 +1223,14 @@ otp_2973(Conf) when is_list(Conf) ->
{Pid2, res, Res2y} ->
{Res1y, Res2y}
after 2000 ->
- test_server:fail(timeout_pid2)
+ ct:fail(timeout_pid2)
end;
{Pid2, res, Res2y} ->
receive
{Pid1, res, Res1y} ->
{Res1y, Res2y}
after 2000 ->
- test_server:fail(timeout_pid1)
+ ct:fail(timeout_pid1)
end
end,
@@ -1278,7 +1240,7 @@ otp_2973(Conf) when is_list(Conf) ->
ok;
_ ->
Txta = io_lib:format("Illegal results from start ~p ~p ",[Res1a, Res2a]),
- test_server:fail(lists:flatten(Txta))
+ ct:fail(lists:flatten(Txta))
end,
ok.
@@ -1289,36 +1251,34 @@ otp_2973(Conf) when is_list(Conf) ->
%% Ticket: OTP-3184
%% Slogan: crash the node if permanent appl has illegal env parameter values
%%-----------------------------------------------------------------
-otp_3184(suite) -> [];
-otp_3184(doc) ->
- ["When a distributed application is started the permit flag is checked "
- "that the permit flag is not changed during the start. "
- "Te check must only be made if the application is started on the own node"];
+%% When a distributed application is started the permit flag is checked
+%% that the permit flag is not changed during the start.
+%% The check must only be made if the application is started on the own node.
otp_3184(Conf) when is_list(Conf) ->
NodeNames = [Ncp1, Ncp2] = node_names([cp1, cp2], Conf),
NoSyncTime = config_fun_fast(config3184(NodeNames)),
WithSyncTime = config_fun(config3184(NodeNames)),
- % Test [cp1, cp2]
+ %% Test [cp1, cp2]
{ok, Cp1} = start_node_config(Ncp1, NoSyncTime, Conf),
{ok, Cp2} = start_node_config(Ncp2, WithSyncTime, Conf),
wait_for_ready_net(),
- % Start app1 and make sure it is not started
+ %% Start app1 and make sure it is not started
{[ok,ok],[]} =
rpc:multicall([Cp1, Cp2], application, load, [app1()]),
- test_server:sleep(3000),
+ ct:sleep(3000),
false = is_started(app1, Cp1),
false = is_started(app1, Cp2),
- % Start app1 on cp1
+ %% Start app1 on cp1
ok = rpc:call(Cp1, application, permit, [app1, true]),
ok = rpc:call(Cp1, application, start, [app1, permanent]),
ok = rpc:call(Cp2, application, start, [app1, permanent]),
?UNTIL(is_started(app1, Cp1)),
false = is_started(app1, Cp2),
- % Check that the application is marked as running in application_controller
+ %% Check that the application is marked as running in application_controller
X = rpc:call(Cp1, application_controller, info, []),
{value, {running, Xrunning}} = lists:keysearch(running, 1, X),
{value, Xapp1} = lists:keysearch(app1, 1, Xrunning),
@@ -1337,15 +1297,13 @@ otp_3184(Conf) when is_list(Conf) ->
%% Ticket: OTP-3002
%% Slogan: crash the node if permanent appl has illegal env parameter values
%%-----------------------------------------------------------------
-otp_3002(suite) -> [];
-otp_3002(doc) ->
- ["crash the node if permanent appl has illegal env parameter values."];
+%% crash the node if permanent appl has illegal env parameter values.
otp_3002(Conf) when is_list(Conf) ->
- % Create the boot script
+ %% Create the boot script
{{KernelVer,StdlibVer}, {LatestDir, LatestName}} =
create_script_3002("script_3002"),
- ?t:format(0, "LatestDir = ~p~n", [LatestDir]),
- ?t:format(0, "LatestName = ~p~n", [LatestName]),
+ ct:pal(?HI_VERBOSITY, "LatestDir = ~p~n", [LatestDir]),
+ ct:pal(?HI_VERBOSITY, "LatestName = ~p~n", [LatestName]),
case is_real_system(KernelVer, StdlibVer) of
true ->
@@ -1371,10 +1329,9 @@ otp_3002(Conf) when is_list(Conf) ->
%% when it received dist_ac_app_stopped).
%%-----------------------------------------------------------------
-otp_4066(suite) -> [];
-otp_4066(doc) -> ["Check that application stop don't cause dist_ac crash"];
+%% Check that application stop don't cause dist_ac crash.
otp_4066(Conf) when is_list(Conf) ->
- % Write config files
+ %% Write config files
[Ncp1, Ncp2] = node_names([cp1, cp2], Conf),
Host = from($@, atom_to_list(node())),
Cp1 = list_to_atom(Ncp1 ++ "@" ++ Host),
@@ -1382,12 +1339,12 @@ otp_4066(Conf) when is_list(Conf) ->
AllNodes = [Cp1, Cp2],
App1Nodes = {app1, AllNodes},
- Dir = ?config(priv_dir,Conf),
+ Dir = proplists:get_value(priv_dir,Conf),
{ok, FdC} = file:open(filename:join(Dir, "otp_4066.config"), [write]),
write_config(FdC, config_4066(AllNodes, 5000, [App1Nodes])),
file:close(FdC),
- % Write the app1.app file
+ %% Write the app1.app file
{ok, FdA12} = file:open(filename:join(Dir, "app1.app"), [write]),
w_app1(FdA12),
file:close(FdA12),
@@ -1402,29 +1359,29 @@ otp_4066(Conf) when is_list(Conf) ->
ok = rpc:call(Cp1, application, start, [app1]),
wait_until_started(app1, [Cp1]),
- test_server:format("--- App1 started at Cp1 ---~n", []),
+ io:format("--- App1 started at Cp1 ---~n", []),
print_dac_state(AllNodes),
- % Cp2 previously crashed on this stop
+ %% Cp2 previously crashed on this stop
ok = rpc:call(Cp1, application, stop, [app1]),
wait_until_stopped(app1, [Cp1]),
- test_server:format("--- App1 stopped at Cp1 ---~n", []),
+ io:format("--- App1 stopped at Cp1 ---~n", []),
print_dac_state(AllNodes),
ok = rpc:call(Cp1, application, start, [app1]),
wait_until_started(app1, [Cp1]),
- test_server:format("--- App1 started at Cp1 ---~n", []),
+ io:format("--- App1 started at Cp1 ---~n", []),
print_dac_state(AllNodes),
ok = rpc:call(Cp2, application, load, [app1, App1Nodes]),
ok = rpc:call(Cp2, application, start, [app1]),
- test_server:format("--- App1 started at Cp2 ---~n", []),
+ io:format("--- App1 started at Cp2 ---~n", []),
print_dac_state(AllNodes),
stop_node_nice(Cp1),
wait_until_started(app1, [Cp2]),
- test_server:format("--- Cp1 crashed; failover to Cp2 ---~n", []),
+ io:format("--- Cp1 crashed; failover to Cp2 ---~n", []),
print_dac_state(Cp2),
stop_node_nice(Cp2),
@@ -1440,7 +1397,7 @@ write_config(Fd, Config) ->
print_dac_state(Node) when is_atom(Node) ->
State = gen_server:call({dist_ac, Node}, info),
- test_server:format(" * dist_ac state on node ~p:~n ~p~n",
+ io:format(" * dist_ac state on node ~p:~n ~p~n",
[Node, State]);
print_dac_state(Nodes) when is_list(Nodes) ->
lists:foreach(fun (N) -> print_dac_state(N) end, Nodes).
@@ -1450,9 +1407,7 @@ print_dac_state(Nodes) when is_list(Nodes) ->
%% Ticket: OTP-4227
%% Slogan: Bad return value from application.
%%-----------------------------------------------------------------
-otp_4227(suite) -> [];
-otp_4227(doc) ->
- ["Test start of depending app when required app crashed."];
+%% Test start of depending app when required app crashed.
otp_4227(Conf) when is_list(Conf) ->
NodeNames = [Ncp1, Ncp2] = node_names([cp1, cp2], Conf),
NoSyncTime = config_fun_fast(config_4227(NodeNames)),
@@ -1475,11 +1430,11 @@ otp_4227(Conf) when is_list(Conf) ->
%% Start app9 and brutally kill it, then try to start app10
ok = rpc:call(Cp1, application, start, [app9]),
- test_server:sleep(1000),
+ ct:sleep(1000),
Pid9 = rpc:call(Cp1, erlang, whereis, [ch_sup19]),
true = erlang:is_pid(Pid9),
true = erlang:exit(Pid9, kill),
- test_server:sleep(1000),
+ ct:sleep(1000),
%% This gave {error, no_report} before the patch
{error, {not_running, app9}} =
@@ -1518,7 +1473,7 @@ otp_5363(Conf) when is_list(Conf) ->
%% the code, but only that the correct processes ARE killed.
OldPath = code:get_path(),
- code:add_patha(?config(data_dir,Conf)),
+ code:add_patha(proplists:get_value(data_dir,Conf)),
try
ok = application:load(app_group_leader()),
ok = application:start(group_leader),
@@ -1532,7 +1487,7 @@ otp_5363(Conf) when is_list(Conf) ->
undefined = whereis(nisse);
Bad ->
io:format("~p\n", [Bad]),
- ?t:fail()
+ ct:fail(failed)
end
after
code:set_path(OldPath)
@@ -1543,14 +1498,12 @@ otp_5363(Conf) when is_list(Conf) ->
%% Ticket: OTP-5606
%% Slogan: Problems with starting a distributed application
%%-----------------------------------------------------------------
-otp_5606(suite) -> [];
-otp_5606(doc) ->
- ["Test of several processes simultanously starting the same "
- "distributed application."];
+%% Test of several processes simultanously starting the same
+%% distributed application.
otp_5606(Conf) when is_list(Conf) ->
%% Write a config file
- Dir = ?config(priv_dir, Conf),
+ Dir = proplists:get_value(priv_dir, Conf),
{ok, Fd} = file:open(filename:join(Dir, "sys.config"), [write]),
NodeNames = [Ncp1, Ncp2] = node_names([cp1, cp2], Conf),
(config4(NodeNames))(Fd, 10000),
@@ -1586,7 +1539,7 @@ otp_5606(Conf) when is_list(Conf) ->
[Res1, Res2, Res3, Res4] ->
Txt = io_lib:format("Illegal results from start ~p ~p ~p ~p",
[Res1, Res2, Res3, Res4]),
- test_server:fail(lists:flatten(Txt))
+ ct:fail(lists:flatten(Txt))
end,
{error, {already_started, app1}} =
@@ -1601,7 +1554,7 @@ otp_5606_loop(ResL) when length(ResL)<4 ->
{_Pid, Res} ->
otp_5606_loop([Res|ResL])
after 5000 ->
- test_server:fail(timeout_waiting_for_res)
+ ct:fail(timeout_waiting_for_res)
end;
otp_5606_loop(ResL) ->
ResL.
@@ -1613,9 +1566,7 @@ loop5606(Pid) ->
Pid ! {self(), Res}
end.
-get_env(suite) -> [];
-get_env(doc) ->
- ["Tests get_env/* functions"];
+%% Tests get_env/* functions.
get_env(Conf) when is_list(Conf) ->
{ok, _} = application:get_env(kernel, error_logger),
undefined = application:get_env(undefined_app, a),
@@ -1627,14 +1578,12 @@ get_env(Conf) when is_list(Conf) ->
%% Should be started in a CC view with:
%% erl -sname XXX -rsh ctrsh where XX not in [cp1, cp2, cp3]
%%-----------------------------------------------------------------
-get_key(suite) -> [];
-get_key(doc) ->
- ["Tests read the .app keys."];
+%% Tests read the .app keys.
get_key(Conf) when is_list(Conf) ->
NodeNames = [Ncp1, _Ncp2, _Ncp3] = node_names([cp1, cp2, cp3], Conf),
WithSyncTime = config_fun(config_inc(NodeNames)),
- % Test [cp1, cp2, cp3]
+ %% Test [cp1, cp2, cp3]
{ok, Cp1} = start_node_config(Ncp1, WithSyncTime, Conf),
ok = rpc:call(Cp1, application, load, [appinc(), d3(NodeNames)]),
@@ -1731,8 +1680,7 @@ get_key(Conf) when is_list(Conf) ->
%%% Testing of change of distributed parameter.
%%%-----------------------------------------------------------------
-distr_changed_tc1(suite) -> [];
-distr_changed_tc1(doc) -> ["Test change of distributed parameter."];
+%% Test change of distributed parameter.
distr_changed_tc1(Conf) when is_list(Conf) ->
{OldKernel, OldEnv, {Cp1, Cp2, Cp3}, {_Ncp1, _Ncp2, _Ncp3}, _Config2} =
@@ -1757,7 +1705,7 @@ distr_changed_tc1(Conf) when is_list(Conf) ->
rpc:multicall([Cp1, Cp2, Cp3],
application_controller, config_change, [OldEnv]),
- test_server:sleep(7000),
+ ct:sleep(7000),
DcInfo1 = rpc:call(Cp1, dist_ac, info, []),
DcInfo2 = rpc:call(Cp2, dist_ac, info, []),
@@ -1778,7 +1726,7 @@ distr_changed_tc1(Conf) when is_list(Conf) ->
ok;
EWa1 ->
X1 = io_lib:format("distribution error: Cp1 ~p ",[EWa1]),
- test_server:fail(lists:flatten(X1))
+ ct:fail(lists:flatten(X1))
end,
case lists:sort(Wa2) of
@@ -1786,7 +1734,7 @@ distr_changed_tc1(Conf) when is_list(Conf) ->
ok;
EWa2 ->
X2 = io_lib:format("distribution error: Cp2 ~p ",[EWa2]),
- test_server:fail(lists:flatten(X2))
+ ct:fail(lists:flatten(X2))
end,
case lists:sort(Wa3) of
@@ -1794,7 +1742,7 @@ distr_changed_tc1(Conf) when is_list(Conf) ->
ok;
EWa3 ->
X3 = io_lib:format("distribution error: Cp3 ~p ",[EWa3]),
- test_server:fail(lists:flatten(X3))
+ ct:fail(lists:flatten(X3))
end,
DcInfo1n = rpc:call(Cp1, dist_ac, info, []),
@@ -1816,9 +1764,7 @@ distr_changed_tc1(Conf) when is_list(Conf) ->
ok.
-distr_changed_tc2(suite) -> [];
-distr_changed_tc2(doc) -> ["Test change of distributed parameter, "
- "move appls by crashing a node."];
+%% Test change of distributed parameter, move appls by crashing a node.
distr_changed_tc2(Conf) when is_list(Conf) ->
{OldKernel, OldEnv, {Cp1, Cp2, Cp3}, {Ncp1, _Ncp2, _Ncp3}, Config2} =
@@ -1843,21 +1789,16 @@ distr_changed_tc2(Conf) when is_list(Conf) ->
rpc:multicall([Cp1, Cp2, Cp3],
application_controller, config_change, [OldEnv]),
- test_server:sleep(4000),
+ ct:sleep(4000),
stop_node_nice(Cp1),
- test_server:sleep(10000),
+ ct:sleep(10000),
-% _DcInfo1 = rpc:call(Cp1, dist_ac, info, []),
_DcInfo2 = rpc:call(Cp2, dist_ac, info, []),
_DcInfo3 = rpc:call(Cp3, dist_ac, info, []),
-% ?t:format(0,"#### DcInfo1 ~n~p~n",[_DcInfo1]),
-% DcWa1 = which_applications(Cp1),
DcWa2 = which_applications(Cp2),
DcWa3 = which_applications(Cp3),
-% Wa1 = lists:foldl(fun({A1, _N1, _V1}, AccIn) -> [A1 | AccIn] end,
-% [], DcWa1),
Wa2 = lists:foldl(fun({A2, _N2, _V2}, AccIn) -> [A2 | AccIn] end,
[], DcWa2),
Wa3 = lists:foldl(fun({A3, _N3, _V3}, AccIn) -> [A3 | AccIn] end,
@@ -1869,7 +1810,7 @@ distr_changed_tc2(Conf) when is_list(Conf) ->
ok;
EWa2 ->
X2 = io_lib:format("distribution error: Cp2 ~p ",[EWa2]),
- test_server:fail(lists:flatten(X2))
+ ct:fail(lists:flatten(X2))
end,
case lists:sort(Wa3) of
@@ -1877,12 +1818,12 @@ distr_changed_tc2(Conf) when is_list(Conf) ->
ok;
EWa3 ->
X3 = io_lib:format("distribution error: Cp3 ~p ",[EWa3]),
- test_server:fail(lists:flatten(X3))
+ ct:fail(lists:flatten(X3))
end,
{ok, Cp1} = start_node_boot(Ncp1, Config2, dc),
- test_server:sleep(10000),
+ ct:sleep(10000),
_DcInfo1rs = rpc:call(Cp1, dist_ac, info, []),
_DcInfo2rs = rpc:call(Cp2, dist_ac, info, []),
@@ -1904,7 +1845,7 @@ distr_changed_tc2(Conf) when is_list(Conf) ->
ok;
EWa1rs ->
X1rs = io_lib:format("distribution error: Cp1 ~p ",[EWa1rs]),
- test_server:fail(lists:flatten(X1rs))
+ ct:fail(lists:flatten(X1rs))
end,
case lists:sort(Wa2rs) of
@@ -1912,7 +1853,7 @@ distr_changed_tc2(Conf) when is_list(Conf) ->
ok;
EWa2rs ->
X2rs = io_lib:format("distribution error: Cp2 ~p ",[EWa2rs]),
- test_server:fail(lists:flatten(X2rs))
+ ct:fail(lists:flatten(X2rs))
end,
case lists:sort(Wa3rs) of
@@ -1920,7 +1861,7 @@ distr_changed_tc2(Conf) when is_list(Conf) ->
ok;
EWa3rs ->
X3rs = io_lib:format("distribution error: Cp3 ~p ",[EWa3rs]),
- test_server:fail(lists:flatten(X3rs))
+ ct:fail(lists:flatten(X3rs))
end,
@@ -1939,15 +1880,12 @@ distr_changed_tc2(Conf) when is_list(Conf) ->
%%%-----------------------------------------------------------------
%%% Testing of application configuration change
%%%-----------------------------------------------------------------
-config_change(suite) ->
- [];
-config_change(doc) ->
- ["Test change of application configuration"];
+%% Test change of application configuration.
config_change(Conf) when is_list(Conf) ->
%% Change to data_dir
{ok, CWD} = file:get_cwd(),
- DataDir = ?config(data_dir, Conf),
+ DataDir = proplists:get_value(data_dir, Conf),
ok = file:set_cwd(DataDir),
%% Find out application data from boot script
@@ -2009,10 +1947,7 @@ get_appls([], Res) ->
Res.
-persistent_env(suite) ->
- [];
-persistent_env(doc) ->
- ["Test set_env/4 and unset_env/3 with persistent true"];
+%% Test set_env/4 and unset_env/3 with persistent true.
persistent_env(Conf) when is_list(Conf) ->
ok = application:set_env(appinc, own2, persist, [{persistent, true}]),
ok = application:set_env(appinc, key1, persist, [{persistent, true}]),
@@ -2056,10 +1991,7 @@ persistent_env(Conf) when is_list(Conf) ->
%%%-----------------------------------------------------------------
%%% Tests the 'shutdown_func' kernel config parameter
%%%-----------------------------------------------------------------
-shutdown_func(suite) ->
- [];
-shutdown_func(doc) ->
- ["Tests the 'shutdown_func' kernel config parameter"];
+%% Tests the 'shutdown_func' kernel config parameter.
shutdown_func(Config) when is_list(Config) ->
{ok,Cp1} = start_node(?MODULE_STRING++"_shutdown_func"),
wait_for_ready_net(),
@@ -2077,10 +2009,10 @@ shutdown_func(Config) when is_list(Config) ->
{'DOWN', Mref, _, Pid, noconnection} ->
ok
after 10000 ->
- test_server:fail(timeout)
+ ct:fail(timeout)
end
after 10000 ->
- test_server:fail(timeout)
+ ct:fail(timeout)
end.
@@ -2098,7 +2030,7 @@ do_shutdown(Reason) ->
%%% Tests the 'shutdown_timeout' kernel config parameter
%%%-----------------------------------------------------------------
shutdown_timeout(Config) when is_list(Config) ->
- DataDir = ?config(data_dir,Config),
+ DataDir = proplists:get_value(data_dir,Config),
{ok,Cp1} = start_node(?MODULE_STRING++"_shutdown_timeout"),
wait_for_ready_net(),
ok = rpc:call(Cp1, application, set_env, [kernel, shutdown_timeout, 1000]),
@@ -2121,7 +2053,7 @@ shutdown_timeout(Config) when is_list(Config) ->
%%% Provokes a (previous) application shutdown deadlock
%%%-----------------------------------------------------------------
shutdown_deadlock(Config) when is_list(Config) ->
- DataDir = ?config(data_dir,Config),
+ DataDir = proplists:get_value(data_dir,Config),
code:add_path(filename:join([DataDir,deadlock])),
%% ok = rpc:call(Cp1, application, start, [sasl]),
ok = application:start(deadlock),
@@ -2596,7 +2528,7 @@ is_started(Name, Node) ->
false -> false
end.
-% Waits until application Name is started on at least one node.
+%% Waits until application Name is started on at least one node.
wait_until_started(Name, Nodes) ->
case lists:member(true,
lists:map(fun (N) ->
@@ -2606,11 +2538,11 @@ wait_until_started(Name, Nodes) ->
true ->
true;
false ->
- test_server:sleep(500),
+ ct:sleep(500),
wait_until_started(Name, Nodes)
end.
-% Waits until application Name is stopped on all nodes.
+%% Waits until application Name is stopped on all nodes.
wait_until_stopped(Name, Nodes) ->
case lists:member(true,
lists:map(fun (N) ->
@@ -2620,7 +2552,7 @@ wait_until_stopped(Name, Nodes) ->
false ->
true;
true ->
- test_server:sleep(500),
+ ct:sleep(500),
wait_until_stopped(Name, Nodes)
end.
@@ -2662,13 +2594,13 @@ start_node_args(Name, Args) ->
start_node_boot_3002(Name, Boot) ->
Pa = filename:dirname(code:which(?MODULE)),
- ?t:format(0, "start_node_boot ~p~n",
- [" -pa " ++ Pa ++ " -env ERL_CRASH_DUMP erl_crash_dump." ++
- atom_to_list(Name) ++ " -boot " ++ Boot ++
- " -sasl dummy \"missing "]),
+ ct:pal(?HI_VERBOSITY, "start_node_boot ~p~n",
+ [" -pa " ++ Pa ++ " -env ERL_CRASH_DUMP erl_crash_dump." ++
+ atom_to_list(Name) ++ " -boot " ++ Boot ++
+ " -sasl dummy \"missing "]),
test_server:start_node(Name, slave,
[{args, " -pa " ++ Pa ++
- " -env ERL_CRASH_DUMP erl_crash_dump." ++
+ " -env ERL_CRASH_DUMP erl_crash_dump." ++
atom_to_list(Name) ++ " -boot " ++ Boot ++
" -sasl dummy \"missing "}]).
@@ -2678,18 +2610,20 @@ start_node_boot_config(Name, SysConfigFun, Conf, Boot) ->
start_node_boot(Name, Config, Boot) ->
Pa = filename:dirname(code:which(?MODULE)),
- ?t:format(0, "start_node_boot ~p~n",[" -pa " ++ Pa ++ " -config " ++ Config ++
- " -boot " ++ atom_to_list(Boot)]),
- test_server:start_node(Name, slave, [{args, " -pa " ++ Pa ++ " -config " ++ Config ++
- " -boot " ++ atom_to_list(Boot)}]).
+ ct:pal(?HI_VERBOSITY,
+ "start_node_boot ~p~n",[" -pa " ++ Pa ++ " -config " ++ Config ++
+ " -boot " ++ atom_to_list(Boot)]),
+ test_server:start_node(Name, slave,
+ [{args, " -pa " ++ Pa ++ " -config " ++ Config ++
+ " -boot " ++ atom_to_list(Boot)}]).
start_node_config_sf(Name, SysConfigFun, Conf) ->
ConfigFile = write_config_file(SysConfigFun, Conf),
- DataDir = ?config(data_dir, Conf), % is it used?
+ DataDir = proplists:get_value(data_dir, Conf), % is it used?
start_node(Name, ConfigFile, " -pa " ++ DataDir).
write_config_file(SysConfigFun, Conf) ->
- Dir = ?config(priv_dir, Conf),
+ Dir = proplists:get_value(priv_dir, Conf),
{ok, Fd} = file:open(filename:join(Dir, "sys.config"), [write]),
SysConfigFun(Fd),
file:close(Fd),
@@ -2713,8 +2647,8 @@ get_start_type(Expected) ->
get_start_type(Expected, 30*5, #st{}).
get_start_type(_Expected, 0, Ack) ->
- test_server:format("====== ~p ======~n", [Ack]),
- test_server:fail(not_valid_start_type);
+ io:format("====== ~p ======~n", [Ack]),
+ ct:fail(not_valid_start_type);
get_start_type(Expected, Times, Ack0) ->
#st{normal = N0, local = L0, takeover = T0, failover = F0} = Ack0,
global:send(st_type, {st, read, self()}),
@@ -2760,13 +2694,13 @@ get_start_phase(Expected) ->
Expected ->
ok;
{sp, T1, I1, So1, Sp1, G1} ->
- test_server:format("=============== {sp,T,I,So,Sp,G} ~p ~n",[" "]),
- test_server:format("=========== got ~p ~n",
+ io:format("=============== {sp,T,I,So,Sp,G} ~p ~n",[" "]),
+ io:format("=========== got ~p ~n",
[{sp, T1, I1, So1, Sp1, G1}]),
- test_server:format("====== expected ~p ~n", [Expected]),
- test_server:fail(not_valid_start_phase)
+ io:format("====== expected ~p ~n", [Expected]),
+ ct:fail(not_valid_start_phase)
after 5000 ->
- test_server:fail(not_valid_start_phase)
+ ct:fail(not_valid_start_phase)
end.
start_phase() ->
@@ -2797,10 +2731,10 @@ get_conf_change(Expected) ->
{cc, Expected} ->
ok;
{cc, List} ->
- test_server:format("====== ~p ======~n",[{cc, List}]),
- test_server:fail(not_valid_conf_change)
+ io:format("====== ~p ======~n",[{cc, List}]),
+ ct:fail(not_valid_conf_change)
after 5000 ->
- test_server:fail(not_valid_conf_change_to)
+ ct:fail(not_valid_conf_change_to)
end.
conf_change() ->
@@ -2896,7 +2830,7 @@ create_script_3002(ScriptName) ->
distr_changed_prep(Conf) when is_list(Conf) ->
- % Write .app files
+ %% Write .app files
{ok, Fd1} = file:open("app1.app", [write]),
w_app1(Fd1),
file:close(Fd1),
@@ -2917,7 +2851,7 @@ distr_changed_prep(Conf) when is_list(Conf) ->
file:close(Fd6),
- % Create the .app files and the boot script
+ %% Create the .app files and the boot script
{{KernelVer,StdlibVer}, _} = create_script_dc("dc"),
case is_real_system(KernelVer, StdlibVer) of
@@ -2933,13 +2867,13 @@ distr_changed_prep(Conf) when is_list(Conf) ->
NoSyncTime = config_fun_fast(config_dc(NodeNames)),
WithSyncTime = config_fun(config_dc(NodeNames)),
- Dir = ?config(priv_dir,Conf),
+ Dir = proplists:get_value(priv_dir,Conf),
{ok, Fd_dc2} = file:open(filename:join(Dir, "sys2.config"), [write]),
(config_dc2(NodeNames))(Fd_dc2),
file:close(Fd_dc2),
Config2 = filename:join(Dir, "sys2"),
- % Test [cp1, cp2, cp3]
+ %% Test [cp1, cp2, cp3]
{ok, Cp1} = start_node_boot_config(Ncp1, NoSyncTime, Conf, dc),
{ok, Cp2} = start_node_boot_config(Ncp2, NoSyncTime, Conf, dc),
{ok, Cp3} = start_node_boot_config(Ncp3, WithSyncTime, Conf, dc),
diff --git a/lib/kernel/test/bif_SUITE.erl b/lib/kernel/test/bif_SUITE.erl
index dd3010567a..54c0f1cec4 100644
--- a/lib/kernel/test/bif_SUITE.erl
+++ b/lib/kernel/test/bif_SUITE.erl
@@ -22,36 +22,33 @@
init_per_group/2,end_per_group/2]).
-export([
- spawn1/1, spawn2/1, spawn3/1, spawn4/1,
+ spawn1/1, spawn2/1, spawn3/1, spawn4/1,
-
- spawn_link1/1, spawn_link2/1, spawn_link3/1, spawn_link4/1,
-
- spawn_opt2/1, spawn_opt3/1, spawn_opt4/1, spawn_opt5/1,
+ spawn_link1/1, spawn_link2/1, spawn_link3/1, spawn_link4/1,
- spawn_failures/1,
- run_fun/1,
- decode_packet_delim/1,
- wilderness/1]).
+ spawn_opt2/1, spawn_opt3/1, spawn_opt4/1, spawn_opt5/1,
--export([init_per_testcase/2, end_per_testcase/2]).
+ spawn_failures/1,
+
+ run_fun/1,
+ decode_packet_delim/1,
+ wilderness/1]).
--include_lib("test_server/include/test_server.hrl").
+-export([init_per_testcase/2, end_per_testcase/2]).
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
+-include_lib("common_test/include/ct.hrl").
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+ Config.
+
+end_per_testcase(_Case, _Config) ->
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[{group, spawn_tests}, {group, spawn_link_tests},
@@ -77,360 +74,333 @@ end_per_group(_GroupName, Config) ->
Config.
-spawn1(doc) -> ["Test spawn/1"];
-spawn1(suite) ->
- [];
+%% Test spawn/1.
spawn1(Config) when is_list(Config) ->
- ?line Node = node(),
- ?line Parent = self(),
- ?line {_, _, FA, _} = fetch_proc_vals(self()),
-
- % spawn
- ?line P = spawn(fun() -> Parent ! {self(), fetch_proc_vals(self())} end),
- ?line receive
- {P, PV} ->
- ?line Node = node(P),
- ?line check_proc_vals(false, normal, FA, 0, PV)
- end,
+ Node = node(),
+ Parent = self(),
+ {_, _, FA, _} = fetch_proc_vals(self()),
+
+ %% spawn
+ P = spawn(fun() -> Parent ! {self(), fetch_proc_vals(self())} end),
+ receive
+ {P, PV} ->
+ Node = node(P),
+ check_proc_vals(false, normal, FA, 0, PV)
+ end,
ok.
-spawn2(doc) -> ["Test spawn/2"];
-spawn2(suite) ->
- [];
+%% Test spawn/2.
spawn2(Config) when is_list(Config) ->
- ?line {ok, Node} = start_node(spawn2),
+ {ok, Node} = start_node(spawn2),
- ?line Parent = self(),
- ?line {_, _, FA, _} = fetch_proc_vals(self()),
+ Parent = self(),
+ {_, _, FA, _} = fetch_proc_vals(self()),
- % spawn_link
- ?line P = spawn(Node,
- fun() -> Parent ! {self(), fetch_proc_vals(self())} end),
- ?line receive
- {P, PV} ->
- ?line Node = node(P),
- ?line check_proc_vals(false, normal, FA, 0, PV)
- end,
+ %% spawn_link
+ P = spawn(Node,
+ fun() -> Parent ! {self(), fetch_proc_vals(self())} end),
+ receive
+ {P, PV} ->
+ Node = node(P),
+ check_proc_vals(false, normal, FA, 0, PV)
+ end,
- ?line true = stop_node(Node),
+ true = stop_node(Node),
ok.
-spawn3(doc) -> ["Test spawn/3"];
-spawn3(suite) ->
- [];
+%% Test spawn/3.
spawn3(Config) when is_list(Config) ->
- ?line Node = node(),
-
- ?line Parent = self(),
- ?line {_, _, FA, _} = fetch_proc_vals(self()),
-
- % spawn_link
- ?line P = spawn(?MODULE,
- run_fun,
- [fun() ->
- Parent ! {self(), fetch_proc_vals(self())}
- end]),
- ?line receive
- {P, PV} ->
- ?line Node = node(P),
- ?line check_proc_vals(false, normal, FA, 0, PV)
- end,
+ Node = node(),
+
+ Parent = self(),
+ {_, _, FA, _} = fetch_proc_vals(self()),
+
+ %% spawn_link
+ P = spawn(?MODULE,
+ run_fun,
+ [fun() ->
+ Parent ! {self(), fetch_proc_vals(self())}
+ end]),
+ receive
+ {P, PV} ->
+ Node = node(P),
+ check_proc_vals(false, normal, FA, 0, PV)
+ end,
ok.
-spawn4(doc) -> ["Test spawn/4"];
-spawn4(suite) ->
- [];
+%% Test spawn/4.
spawn4(Config) when is_list(Config) ->
- ?line {ok, Node} = start_node(spawn4),
-
- ?line Parent = self(),
- ?line {_, _, FA, _} = fetch_proc_vals(self()),
-
- % spawn_link
- ?line P = spawn(Node,
- ?MODULE,
- run_fun,
- [fun() ->
- Parent ! {self(), fetch_proc_vals(self())}
- end]),
- ?line receive
- {P, PV} ->
- ?line Node = node(P),
- ?line check_proc_vals(false, normal, FA, 0, PV)
- end,
-
- ?line true = stop_node(Node),
+ {ok, Node} = start_node(spawn4),
+
+ Parent = self(),
+ {_, _, FA, _} = fetch_proc_vals(self()),
+
+ %% spawn_link
+ P = spawn(Node,
+ ?MODULE,
+ run_fun,
+ [fun() ->
+ Parent ! {self(), fetch_proc_vals(self())}
+ end]),
+ receive
+ {P, PV} ->
+ Node = node(P),
+ check_proc_vals(false, normal, FA, 0, PV)
+ end,
+
+ true = stop_node(Node),
ok.
-spawn_link1(doc) -> ["Test spawn_link/1"];
-spawn_link1(suite) ->
- [];
+%% Test spawn_link/1.
spawn_link1(Config) when is_list(Config) ->
- ?line Node = node(),
- ?line Parent = self(),
- ?line {_, _, FA, _} = fetch_proc_vals(self()),
-
- % spawn_link
- ?line P = spawn_link(fun() -> Parent ! {self(), fetch_proc_vals(self())} end),
- ?line receive
- {P, PV} ->
- ?line Node = node(P),
- ?line check_proc_vals(true, normal, FA, 0, PV)
- end,
+ Node = node(),
+ Parent = self(),
+ {_, _, FA, _} = fetch_proc_vals(self()),
+
+ %% spawn_link
+ P = spawn_link(fun() -> Parent ! {self(), fetch_proc_vals(self())} end),
+ receive
+ {P, PV} ->
+ Node = node(P),
+ check_proc_vals(true, normal, FA, 0, PV)
+ end,
ok.
-spawn_link2(doc) -> ["Test spawn_link/2"];
-spawn_link2(suite) ->
- [];
+%% Test spawn_link/2.
spawn_link2(Config) when is_list(Config) ->
- ?line {ok, Node} = start_node(spawn_link2),
+ {ok, Node} = start_node(spawn_link2),
- ?line Parent = self(),
- ?line {_, _, FA, _} = fetch_proc_vals(self()),
+ Parent = self(),
+ {_, _, FA, _} = fetch_proc_vals(self()),
- % spawn_link
- ?line P = spawn_link(Node,
- fun() -> Parent ! {self(), fetch_proc_vals(self())} end),
- ?line receive
- {P, PV} ->
- ?line Node = node(P),
- ?line check_proc_vals(true, normal, FA, 0, PV)
- end,
+ %% spawn_link
+ P = spawn_link(Node,
+ fun() -> Parent ! {self(), fetch_proc_vals(self())} end),
+ receive
+ {P, PV} ->
+ Node = node(P),
+ check_proc_vals(true, normal, FA, 0, PV)
+ end,
- ?line true = stop_node(Node),
+ true = stop_node(Node),
ok.
-spawn_link3(doc) -> ["Test spawn_link/3"];
-spawn_link3(suite) ->
- [];
+%% Test spawn_link/3.
spawn_link3(Config) when is_list(Config) ->
- ?line Node = node(),
-
- ?line Parent = self(),
- ?line {_, _, FA, _} = fetch_proc_vals(self()),
-
- % spawn_link
- ?line P = spawn_link(?MODULE,
- run_fun,
- [fun() ->
- Parent ! {self(), fetch_proc_vals(self())}
- end]),
- ?line receive
- {P, PV} ->
- ?line Node = node(P),
- ?line check_proc_vals(true, normal, FA, 0, PV)
- end,
+ Node = node(),
+
+ Parent = self(),
+ {_, _, FA, _} = fetch_proc_vals(self()),
+
+ %% spawn_link
+ P = spawn_link(?MODULE,
+ run_fun,
+ [fun() ->
+ Parent ! {self(), fetch_proc_vals(self())}
+ end]),
+ receive
+ {P, PV} ->
+ Node = node(P),
+ check_proc_vals(true, normal, FA, 0, PV)
+ end,
ok.
-spawn_link4(doc) -> ["Test spawn_link/4"];
-spawn_link4(suite) ->
- [];
+%% Test spawn_link/4.
spawn_link4(Config) when is_list(Config) ->
- ?line {ok, Node} = start_node(spawn_link4),
-
- ?line Parent = self(),
- ?line {_, _, FA, _} = fetch_proc_vals(self()),
-
- % spawn_link
- ?line P = spawn_link(Node,
- ?MODULE,
- run_fun,
- [fun() ->
- Parent ! {self(), fetch_proc_vals(self())}
- end]),
- ?line receive
- {P, PV} ->
- ?line Node = node(P),
- ?line check_proc_vals(true, normal, FA, 0, PV)
- end,
-
- ?line true = stop_node(Node),
+ {ok, Node} = start_node(spawn_link4),
+
+ Parent = self(),
+ {_, _, FA, _} = fetch_proc_vals(self()),
+
+ %% spawn_link
+ P = spawn_link(Node,
+ ?MODULE,
+ run_fun,
+ [fun() ->
+ Parent ! {self(), fetch_proc_vals(self())}
+ end]),
+ receive
+ {P, PV} ->
+ Node = node(P),
+ check_proc_vals(true, normal, FA, 0, PV)
+ end,
+
+ true = stop_node(Node),
ok.
-spawn_opt2(doc) -> ["Test spawn_opt/2"];
-spawn_opt2(suite) ->
- [];
+%% Test spawn_opt/2.
spawn_opt2(Config) when is_list(Config) ->
- ?line Node = node(),
- ?line Parent = self(),
- ?line {_, _, FA, _} = fetch_proc_vals(self()),
-
- ?line P1 = spawn_opt(fun() ->
- Parent ! {self(), fetch_proc_vals(self())}
- end,
- [{fullsweep_after, 0},{min_heap_size, 1000},
- link, {priority, max}]),
- ?line receive
- {P1, PV1} ->
- ?line Node = node(P1),
- ?line check_proc_vals(true, max, 0, 1000, PV1)
- end,
- ?line P2 = spawn_opt(fun() -> Parent ! {self(), fetch_proc_vals(self())} end,
- [{min_heap_size, 10}]),
- ?line receive
- {P2, PV2} ->
- ?line Node = node(P2),
- ?line check_proc_vals(false, normal, FA, 10, PV2)
- end,
+ Node = node(),
+ Parent = self(),
+ {_, _, FA, _} = fetch_proc_vals(self()),
+
+ P1 = spawn_opt(fun() ->
+ Parent ! {self(), fetch_proc_vals(self())}
+ end,
+ [{fullsweep_after, 0},{min_heap_size, 1000},
+ link, {priority, max}]),
+ receive
+ {P1, PV1} ->
+ Node = node(P1),
+ check_proc_vals(true, max, 0, 1000, PV1)
+ end,
+ P2 = spawn_opt(fun() -> Parent ! {self(), fetch_proc_vals(self())} end,
+ [{min_heap_size, 10}]),
+ receive
+ {P2, PV2} ->
+ Node = node(P2),
+ check_proc_vals(false, normal, FA, 10, PV2)
+ end,
ok.
-spawn_opt3(doc) -> ["Test spawn_opt/3"];
-spawn_opt3(suite) ->
- [];
+%% Test spawn_opt/3.
spawn_opt3(Config) when is_list(Config) ->
- ?line {ok, Node} = start_node(spawn_opt3),
- ?line Parent = self(),
- ?line {_, _, FA, _} = fetch_proc_vals(self()),
- ?line P1 = spawn_opt(Node,
- fun() ->
- Parent ! {self(), fetch_proc_vals(self())}
- end,
- [{fullsweep_after,0}, {min_heap_size,1000},
- link, {priority, max}]),
- ?line receive
- {P1, PV1} ->
- ?line Node = node(P1),
- ?line check_proc_vals(true, max, 0, 1000, PV1)
- end,
- ?line P2 = spawn_opt(Node,
- fun() -> Parent ! {self(), fetch_proc_vals(self())} end,
- [{min_heap_size, 10}]),
- ?line receive
- {P2, PV2} ->
- ?line Node = node(P2),
- ?line check_proc_vals(false, normal, FA, 10, PV2)
- end,
- ?line true = stop_node(Node),
+ {ok, Node} = start_node(spawn_opt3),
+ Parent = self(),
+ {_, _, FA, _} = fetch_proc_vals(self()),
+ P1 = spawn_opt(Node,
+ fun() ->
+ Parent ! {self(), fetch_proc_vals(self())}
+ end,
+ [{fullsweep_after,0}, {min_heap_size,1000},
+ link, {priority, max}]),
+ receive
+ {P1, PV1} ->
+ Node = node(P1),
+ check_proc_vals(true, max, 0, 1000, PV1)
+ end,
+ P2 = spawn_opt(Node,
+ fun() -> Parent ! {self(), fetch_proc_vals(self())} end,
+ [{min_heap_size, 10}]),
+ receive
+ {P2, PV2} ->
+ Node = node(P2),
+ check_proc_vals(false, normal, FA, 10, PV2)
+ end,
+ true = stop_node(Node),
ok.
-spawn_opt4(doc) -> ["Test spawn_opt/4"];
-spawn_opt4(suite) ->
- [];
+%% Test spawn_opt/4.
spawn_opt4(Config) when is_list(Config) ->
- ?line Node = node(),
- ?line Parent = self(),
- ?line {_, _, FA, _} = fetch_proc_vals(self()),
- ?line P1 = spawn_opt(?MODULE,
- run_fun,
- [fun() ->
- Parent ! {self(), fetch_proc_vals(self())}
- end],
- [{fullsweep_after,0}, {min_heap_size,1000},
- link, {priority, max}]),
- ?line receive
- {P1, PV1} ->
- ?line Node = node(P1),
- ?line check_proc_vals(true, max, 0, 1000, PV1)
- end,
- ?line P2 = spawn_opt(?MODULE,
- run_fun,
- [fun() ->
- Parent ! {self(), fetch_proc_vals(self())}
- end],
- [{min_heap_size, 10}]),
- ?line receive
- {P2, PV2} ->
- ?line Node = node(P2),
- ?line check_proc_vals(false, normal, FA, 10, PV2)
- end,
+ Node = node(),
+ Parent = self(),
+ {_, _, FA, _} = fetch_proc_vals(self()),
+ P1 = spawn_opt(?MODULE,
+ run_fun,
+ [fun() ->
+ Parent ! {self(), fetch_proc_vals(self())}
+ end],
+ [{fullsweep_after,0}, {min_heap_size,1000},
+ link, {priority, max}]),
+ receive
+ {P1, PV1} ->
+ Node = node(P1),
+ check_proc_vals(true, max, 0, 1000, PV1)
+ end,
+ P2 = spawn_opt(?MODULE,
+ run_fun,
+ [fun() ->
+ Parent ! {self(), fetch_proc_vals(self())}
+ end],
+ [{min_heap_size, 10}]),
+ receive
+ {P2, PV2} ->
+ Node = node(P2),
+ check_proc_vals(false, normal, FA, 10, PV2)
+ end,
ok.
-spawn_opt5(doc) -> ["Test spawn_opt/5"];
-spawn_opt5(suite) ->
- [];
+%% Test spawn_opt/5.
spawn_opt5(Config) when is_list(Config) ->
- ?line {ok, Node} = start_node(spawn_opt5),
- ?line Parent = self(),
- ?line {_, _, FA, _} = fetch_proc_vals(self()),
- ?line P1 = spawn_opt(Node,
- ?MODULE,
- run_fun,
- [fun() ->
- Parent ! {self(), fetch_proc_vals(self())}
- end],
- [{fullsweep_after,0}, {min_heap_size,1000},
- link, {priority, max}]),
- ?line receive
- {P1, PV1} ->
- ?line Node = node(P1),
- ?line check_proc_vals(true, max, 0, 1000, PV1)
- end,
- ?line P2 = spawn_opt(Node,
- ?MODULE,
- run_fun,
- [fun() ->
- Parent ! {self(), fetch_proc_vals(self())}
- end],
- [{min_heap_size, 10}]),
- ?line receive
- {P2, PV2} ->
- ?line Node = node(P2),
- ?line check_proc_vals(false, normal, FA, 10, PV2)
- end,
- ?line true = stop_node(Node),
+ {ok, Node} = start_node(spawn_opt5),
+ Parent = self(),
+ {_, _, FA, _} = fetch_proc_vals(self()),
+ P1 = spawn_opt(Node,
+ ?MODULE,
+ run_fun,
+ [fun() ->
+ Parent ! {self(), fetch_proc_vals(self())}
+ end],
+ [{fullsweep_after,0}, {min_heap_size,1000},
+ link, {priority, max}]),
+ receive
+ {P1, PV1} ->
+ Node = node(P1),
+ check_proc_vals(true, max, 0, 1000, PV1)
+ end,
+ P2 = spawn_opt(Node,
+ ?MODULE,
+ run_fun,
+ [fun() ->
+ Parent ! {self(), fetch_proc_vals(self())}
+ end],
+ [{min_heap_size, 10}]),
+ receive
+ {P2, PV2} ->
+ Node = node(P2),
+ check_proc_vals(false, normal, FA, 10, PV2)
+ end,
+ true = stop_node(Node),
ok.
-spawn_failures(doc) ->
- ["Test failure behavior of spawn bifs"];
-spawn_failures(suite) ->
- [];
+%% Test failure behavior of spawn bifs.
spawn_failures(Config) when is_list(Config) ->
- ?line ThisNode = node(),
- ?line {ok, Node} = start_node(spawn_remote_failure),
-
- % unknown nodes
- test_server:format("Testing unknown nodes~n", []),
- ?line CrashPid1 = (catch spawn_opt('unknown@node',
- erlang,
- nodes,
- [],
- [])),
- ?line true = is_pid(CrashPid1),
- ?line ThisNode = node(CrashPid1),
- ?line CrashPid2 = (catch spawn_opt('unknown@node',
- fun () -> erlang:nodes() end,
- [])),
- ?line true = is_pid(CrashPid2),
- ?line ThisNode = node(CrashPid2),
-
- ?line CrashPid3 = (catch spawn('unknown@node',
- erlang,
- nodes,
- [])),
- ?line true = is_pid(CrashPid3),
- ?line ThisNode = node(CrashPid3),
- ?line CrashPid4 = (catch spawn('unknown@node',
- fun () -> erlang:nodes() end)),
- ?line true = is_pid(CrashPid4),
- ?line ThisNode = node(CrashPid4),
-
- ?line OTE = process_flag(trap_exit,true),
- ?line CrashPid5 = (catch spawn_link('unknown@node',
- erlang,
- nodes,
- [])),
+ ThisNode = node(),
+ {ok, Node} = start_node(spawn_remote_failure),
+
+ %% unknown nodes
+ io:format("Testing unknown nodes~n", []),
+ CrashPid1 = (catch spawn_opt('unknown@node',
+ erlang,
+ nodes,
+ [],
+ [])),
+ true = is_pid(CrashPid1),
+ ThisNode = node(CrashPid1),
+ CrashPid2 = (catch spawn_opt('unknown@node',
+ fun () -> erlang:nodes() end,
+ [])),
+ true = is_pid(CrashPid2),
+ ThisNode = node(CrashPid2),
+
+ CrashPid3 = (catch spawn('unknown@node',
+ erlang,
+ nodes,
+ [])),
+ true = is_pid(CrashPid3),
+ ThisNode = node(CrashPid3),
+ CrashPid4 = (catch spawn('unknown@node',
+ fun () -> erlang:nodes() end)),
+ true = is_pid(CrashPid4),
+ ThisNode = node(CrashPid4),
+
+ OTE = process_flag(trap_exit,true),
+ CrashPid5 = (catch spawn_link('unknown@node',
+ erlang,
+ nodes,
+ [])),
receive
{'EXIT', CrashPid5, noconnection} ->
- ?line true = is_pid(CrashPid5),
- ?line ThisNode = node(CrashPid5)
+ true = is_pid(CrashPid5),
+ ThisNode = node(CrashPid5)
end,
- ?line CrashPid6 = (catch spawn_link('unknown@node',
- fun () -> erlang:nodes() end)),
+ CrashPid6 = (catch spawn_link('unknown@node',
+ fun () -> erlang:nodes() end)),
receive
{'EXIT', CrashPid6, noconnection} ->
- ?line true = is_pid(CrashPid6),
- ?line ThisNode = node(CrashPid6)
+ true = is_pid(CrashPid6),
+ ThisNode = node(CrashPid6)
end,
process_flag(trap_exit,OTE),
case OTE of
false ->
receive
{'EXIT', P, R} ->
- ?line test_server:fail({'EXIT', P, R})
+ ct:fail({'EXIT', P, R})
after 0 ->
ok
end;
@@ -438,132 +408,125 @@ spawn_failures(Config) when is_list(Config) ->
ok
end,
- % bad node
- test_server:format("Testing bad nodes~n", []),
- ?line {'EXIT', {badarg, _}} = (catch spawn_opt("Node",erlang,nodes,[],[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn_opt("Node",
- fun () ->
- erlang:nodes()
- end,
- [])),
- ?line {'EXIT', {badarg, _}} = (catch spawn_link("Node",
- fun () ->
- erlang:nodes()
- end)),
- ?line {'EXIT', {badarg, _}} = (catch spawn("Node",erlang,nodes,[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn("Node",
- fun () ->
- erlang:nodes()
- end)),
-
- % bad module
- test_server:format("Testing bad modules~n", []),
- ?line {'EXIT', {badarg, _}} = (catch spawn_opt(Node,"erlang",nodes,[],[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn_opt("erlang",nodes,[],[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn_link(Node,"erlang",nodes,[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn_link("erlang",nodes,[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn(Node,"erlang",nodes,[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn("erlang",nodes,[])),
-
- % bad function
- test_server:format("Testing bad functions~n", []),
- ?line {'EXIT', {badarg, _}} = (catch spawn_opt(Node,erlang,"nodes",[],[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn_opt(Node,not_a_fun,[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn_opt(erlang,"nodes",[],[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn_opt(not_a_fun,[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn_link(Node,erlang,"nodes",[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn_link(Node,not_a_fun)),
- ?line {'EXIT', {badarg, _}} = (catch spawn_link(erlang,"nodes",[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn_link(not_a_fun)),
- ?line {'EXIT', {badarg, _}} = (catch spawn(Node,erlang,"nodes",[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn(Node,not_a_fun)),
- ?line {'EXIT', {badarg, _}} = (catch spawn(erlang,"nodes",[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn(not_a_fun)),
-
-
- % bad argument
- test_server:format("Testing bad arguments~n", []),
- ?line {'EXIT', {badarg, _}} = (catch spawn_opt(Node,erlang,nodes,[a|b],[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn_opt(erlang,nodes,[a|b],[])),
- ?line {'EXIT', {badarg, _}} = (catch spawn_link(Node,erlang,nodes,[a|b])),
- ?line {'EXIT', {badarg, _}} = (catch spawn_link(erlang,nodes,[a|b])),
- ?line {'EXIT', {badarg, _}} = (catch spawn(Node,erlang,nodes,[a|b])),
- ?line {'EXIT', {badarg, _}} = (catch spawn(erlang,nodes,[a|b])),
-
- % bad option
- test_server:format("Testing bad options~n", []),
- ?line {'EXIT', {badarg, _}} = (catch spawn_opt(Node,erlang,nodes,[],[a|b])),
- ?line {'EXIT', {badarg, _}} = (catch spawn_opt(erlang,nodes,[],[a|b])),
-
-
- ?line true = stop_node(Node),
+ %% bad node
+ io:format("Testing bad nodes~n", []),
+ {'EXIT', {badarg, _}} = (catch spawn_opt("Node",erlang,nodes,[],[])),
+ {'EXIT', {badarg, _}} = (catch spawn_opt("Node",
+ fun () ->
+ erlang:nodes()
+ end,
+ [])),
+ {'EXIT', {badarg, _}} = (catch spawn_link("Node",
+ fun () ->
+ erlang:nodes()
+ end)),
+ {'EXIT', {badarg, _}} = (catch spawn("Node",erlang,nodes,[])),
+ {'EXIT', {badarg, _}} = (catch spawn("Node",
+ fun () ->
+ erlang:nodes()
+ end)),
+
+ %% bad module
+ io:format("Testing bad modules~n", []),
+ {'EXIT', {badarg, _}} = (catch spawn_opt(Node,"erlang",nodes,[],[])),
+ {'EXIT', {badarg, _}} = (catch spawn_opt("erlang",nodes,[],[])),
+ {'EXIT', {badarg, _}} = (catch spawn_link(Node,"erlang",nodes,[])),
+ {'EXIT', {badarg, _}} = (catch spawn_link("erlang",nodes,[])),
+ {'EXIT', {badarg, _}} = (catch spawn(Node,"erlang",nodes,[])),
+ {'EXIT', {badarg, _}} = (catch spawn("erlang",nodes,[])),
+
+ %% bad function
+ io:format("Testing bad functions~n", []),
+ {'EXIT', {badarg, _}} = (catch spawn_opt(Node,erlang,"nodes",[],[])),
+ {'EXIT', {badarg, _}} = (catch spawn_opt(Node,not_a_fun,[])),
+ {'EXIT', {badarg, _}} = (catch spawn_opt(erlang,"nodes",[],[])),
+ {'EXIT', {badarg, _}} = (catch spawn_opt(not_a_fun,[])),
+ {'EXIT', {badarg, _}} = (catch spawn_link(Node,erlang,"nodes",[])),
+ {'EXIT', {badarg, _}} = (catch spawn_link(Node,not_a_fun)),
+ {'EXIT', {badarg, _}} = (catch spawn_link(erlang,"nodes",[])),
+ {'EXIT', {badarg, _}} = (catch spawn_link(not_a_fun)),
+ {'EXIT', {badarg, _}} = (catch spawn(Node,erlang,"nodes",[])),
+ {'EXIT', {badarg, _}} = (catch spawn(Node,not_a_fun)),
+ {'EXIT', {badarg, _}} = (catch spawn(erlang,"nodes",[])),
+ {'EXIT', {badarg, _}} = (catch spawn(not_a_fun)),
+
+
+ %% bad argument
+ io:format("Testing bad arguments~n", []),
+ {'EXIT', {badarg, _}} = (catch spawn_opt(Node,erlang,nodes,[a|b],[])),
+ {'EXIT', {badarg, _}} = (catch spawn_opt(erlang,nodes,[a|b],[])),
+ {'EXIT', {badarg, _}} = (catch spawn_link(Node,erlang,nodes,[a|b])),
+ {'EXIT', {badarg, _}} = (catch spawn_link(erlang,nodes,[a|b])),
+ {'EXIT', {badarg, _}} = (catch spawn(Node,erlang,nodes,[a|b])),
+ {'EXIT', {badarg, _}} = (catch spawn(erlang,nodes,[a|b])),
+
+ %% bad option
+ io:format("Testing bad options~n", []),
+ {'EXIT', {badarg, _}} = (catch spawn_opt(Node,erlang,nodes,[],[a|b])),
+ {'EXIT', {badarg, _}} = (catch spawn_opt(erlang,nodes,[],[a|b])),
+
+
+ true = stop_node(Node),
ok.
check_proc_vals(Link, Priority, FullsweepAfter, MinHeapSize, {Ls, P, FA, HS}) ->
- ?line Link = lists:member(self(), Ls),
- ?line Priority = P,
+ Link = lists:member(self(), Ls),
+ Priority = P,
FullsweepAfter = FA,
true = (HS >= MinHeapSize),
- ?line ok.
+ ok.
fetch_proc_vals(Pid) ->
- ?line PI = process_info(Pid),
- ?line {value,{links, Ls}} = lists:keysearch(links, 1, PI),
- ?line {value,{priority,P}} = lists:keysearch(priority, 1, PI),
+ PI = process_info(Pid),
+ {value,{links, Ls}} = lists:keysearch(links, 1, PI),
+ {value,{priority,P}} = lists:keysearch(priority, 1, PI),
{value,{garbage_collection,Gs}} =
lists:keysearch(garbage_collection, 1, PI),
{value,{fullsweep_after,FA}} =
lists:keysearch(fullsweep_after, 1, Gs),
{value,{heap_size,HS}} = lists:keysearch(heap_size, 1, PI),
- ?line {Ls, P, FA, HS}.
-
-decode_packet_delim(doc) ->
- ["Test erlang:packet_delim/3 with {line_delimiter,0} option"];
-decode_packet_delim(suite) ->
- [];
+ {Ls, P, FA, HS}.
+
+%% Test erlang:packet_delim/3 with {line_delimiter,0} option.
decode_packet_delim(Config) when is_list(Config) ->
{ok,<<"abc",0>>,<<"efg",0>>} =
erlang:decode_packet(line, <<"abc",0,"efg",0>>, [{line_delimiter, 0}]),
{more, undefined} = erlang:decode_packet(line, <<"abc",0,"efg",0>>, []).
-% This testcase should probably be moved somewhere else
-wilderness(doc) ->
- ["Test that memory allocation command line options affecting the"
- "wilderness of the heap are interpreted correct by the emulator "];
-wilderness(suite) ->
- [];
+%% This testcase should probably be moved somewhere else
+
+%% Test that memory allocation command line options affecting the
+%% wilderness of the heap are interpreted correct by the emulator.
wilderness(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- ?line OKParams = {512, 8},
- ?line Alloc = erlang:system_info(allocator),
- ?line test_server:format("Test server allocator info:~n~p", [Alloc]),
+ OKParams = {512, 8},
+ Alloc = erlang:system_info(allocator),
+ io:format("Test server allocator info:~n~p", [Alloc]),
Result = case Alloc of
{Allocator, _, _, _} when Allocator == glibc;
Allocator == dlmalloc ->
- ?line run_wilderness_test(OKParams, OKParams),
- ?line {comment,
- "Allocator used: " ++ atom_to_list(Allocator)};
+ run_wilderness_test(OKParams, OKParams),
+ {comment,
+ "Allocator used: " ++ atom_to_list(Allocator)};
{OtherAllocator, _, _, _} ->
- ?line {skipped,
- "Only run when glibc is used. "
- "Allocator used: "
- ++ atom_to_list(OtherAllocator)}
+ {skipped,
+ "Only run when glibc is used. "
+ "Allocator used: "
+ ++ atom_to_list(OtherAllocator)}
end,
- ?line test_server:timetrap_cancel(Dog),
Result.
-
+
run_wilderness_test({Set_tt, Set_tp}, {Exp_tt, Exp_tp}) ->
Self = self(),
Ref = make_ref(),
SuiteDir = filename:dirname(code:which(?MODULE)),
- ?line {ok, Node} = test_server:start_node(allocator_test,
- slave,
- [{args,
- " -pa "
- ++ SuiteDir
- ++" +MYtt "++to_string(Set_tt)
- ++" +MYtp "++to_string(Set_tp)},
- {linked, false}]),
+ {ok, Node} = test_server:start_node(allocator_test,
+ slave,
+ [{args,
+ " -pa "
+ ++ SuiteDir
+ ++" +MYtt "++to_string(Set_tt)
+ ++" +MYtp "++to_string(Set_tp)},
+ {linked, false}]),
spawn(Node, fun () ->
Self ! {Ref, erlang:system_info(allocator)}
end),
@@ -571,15 +534,15 @@ run_wilderness_test({Set_tt, Set_tp}, {Exp_tt, Exp_tp}) ->
{Ref, {A, V, F, S}} ->
Ett = Exp_tt*1024,
Etp = Exp_tp*1024,
- ?line test_server:format("Test allocator info:~n~p",
- [{A, V, F, S}]),
- ?line {value, {sys_alloc, SA_Opts}}
+ io:format("Test allocator info:~n~p",
+ [{A, V, F, S}]),
+ {value, {sys_alloc, SA_Opts}}
= lists:keysearch(sys_alloc, 1, S),
- ?line {value, {tt, Ett}} = lists:keysearch(tt, 1, SA_Opts),
- ?line {value, {tp, Etp}} = lists:keysearch(tp, 1, SA_Opts)
+ {value, {tt, Ett}} = lists:keysearch(tt, 1, SA_Opts),
+ {value, {tp, Etp}} = lists:keysearch(tp, 1, SA_Opts)
end,
stop_node(Node).
-
+
to_string(X) when is_integer(X) ->
integer_to_list(X);
to_string(X) when is_atom(X) ->
@@ -605,12 +568,12 @@ get_nodenames(N, T, Acc) ->
++ integer_to_list(C)) | Acc]).
start_node(TestCase) ->
- ?line [Name] = get_nodenames(1, TestCase),
- ?line Pa = filename:dirname(code:which(?MODULE)),
- ?line test_server:start_node(Name, slave, [{args, "-pa " ++ Pa}]).
+ [Name] = get_nodenames(1, TestCase),
+ Pa = filename:dirname(code:which(?MODULE)),
+ test_server:start_node(Name, slave, [{args, "-pa " ++ Pa}]).
stop_node(Node) ->
- ?line true = test_server:stop_node(Node).
+ true = test_server:stop_node(Node).
run_fun(Fun) ->
Fun().
diff --git a/lib/kernel/test/cleanup.erl b/lib/kernel/test/cleanup.erl
index 7eb0a9e140..26000b545f 100644
--- a/lib/kernel/test/cleanup.erl
+++ b/lib/kernel/test/cleanup.erl
@@ -21,7 +21,7 @@
-export([all/0,groups/0,init_per_group/2,end_per_group/2, cleanup/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
all() ->
[cleanup].
@@ -36,15 +36,14 @@ end_per_group(_GroupName, Config) ->
Config.
-cleanup(suite) -> [];
cleanup(_) ->
- ?line Localhost = list_to_atom(net_adm:localhost()),
- ?line net_adm:world_list([Localhost]),
- ?line case nodes() of
- [] ->
- ok;
- Nodes when is_list(Nodes) ->
- Kill = fun(Node) -> spawn(Node, erlang, halt, []) end,
- ?line lists:foreach(Kill, Nodes),
- ?line test_server:fail({nodes_left, Nodes})
- end.
+ Localhost = list_to_atom(net_adm:localhost()),
+ net_adm:world_list([Localhost]),
+ case nodes() of
+ [] ->
+ ok;
+ Nodes when is_list(Nodes) ->
+ Kill = fun(Node) -> spawn(Node, erlang, halt, []) end,
+ lists:foreach(Kill, Nodes),
+ ct:fail({nodes_left, Nodes})
+ end.
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl
index 73ade14fa1..298c1f7d6b 100644
--- a/lib/kernel/test/code_SUITE.erl
+++ b/lib/kernel/test/code_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(code_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
-export([set_path/1, get_path/1, add_path/1, add_paths/1, del_path/1,
@@ -30,8 +30,7 @@
upgrade/1,
sticky_dir/1, pa_pz_option/1, add_del_path/1,
dir_disappeared/1, ext_mod_dep/1, clash/1,
- load_cached/1, start_node_with_cache/1, add_and_rehash/1,
- where_is_file_cached/1, where_is_file_no_cache/1,
+ where_is_file/1,
purge_stacktrace/1, mult_lib_roots/1, bad_erl_libs/1,
code_archive/1, code_archive2/1, on_load/1, on_load_binary/1,
on_load_embedded/1, on_load_errors/1, big_boot_embedded/1,
@@ -47,7 +46,9 @@
-export([compile_load/4]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,5}}].
all() ->
[set_path, get_path, add_path, add_paths, del_path,
@@ -56,9 +57,8 @@ all() ->
load_binary, dir_req, object_code, set_path_file,
upgrade,
sticky_dir, pa_pz_option, add_del_path, dir_disappeared,
- ext_mod_dep, clash, load_cached, start_node_with_cache,
- add_and_rehash, where_is_file_no_cache,
- where_is_file_cached, purge_stacktrace, mult_lib_roots,
+ ext_mod_dep, clash, where_is_file,
+ purge_stacktrace, mult_lib_roots,
bad_erl_libs, code_archive, code_archive2, on_load,
on_load_binary, on_load_embedded, on_load_errors,
big_boot_embedded, native_early_modules, get_mode].
@@ -94,34 +94,28 @@ init_per_testcase(big_boot_embedded, Config) ->
{skip, "Needs crypto!"}
end;
init_per_testcase(_Func, Config) ->
- Dog=?t:timetrap(?t:minutes(5)),
- P=code:get_path(),
- P=code:get_path(),
- [{watchdog, Dog}, {code_path, P}|Config].
+ P = code:get_path(),
+ [{code_path, P}|Config].
end_per_testcase(TC, Config) when TC == mult_lib_roots;
TC == big_boot_embedded ->
{ok, HostName} = inet:gethostname(),
NodeName = list_to_atom(atom_to_list(TC)++"@"++HostName),
- ?t:stop_node(NodeName),
+ test_server:stop_node(NodeName),
end_per_testcase(Config);
end_per_testcase(_Func, Config) ->
end_per_testcase(Config).
end_per_testcase(Config) ->
code:purge(code_b_test),
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
- P=?config(code_path, Config),
+ P=proplists:get_value(code_path, Config),
true=code:set_path(P),
P=code:get_path(),
ok.
-set_path(suite) -> [];
-set_path(doc) -> [];
set_path(Config) when is_list(Config) ->
P = code:get_path(),
- NonExDir = filename:join(?config(priv_dir, Config), ?t:temp_name("hej")),
+ NonExDir = filename:join(proplists:get_value(priv_dir, Config), test_server:temp_name("hej")),
{'EXIT',_} = (catch code:set_path({a})),
{error, bad_directory} = (catch code:set_path([{a}])),
{error, bad_directory} = code:set_path(NonExDir),
@@ -135,19 +129,15 @@ set_path(Config) when is_list(Config) ->
[LibDir] = code:get_path(),
ok.
-get_path(suite) -> [];
-get_path(doc) -> [];
get_path(Config) when is_list(Config) ->
P = code:get_path(),
- % test that all directories are strings (lists).
+ %% test that all directories are strings (lists).
[] = lists:filter(fun
(Dir) when is_list(Dir) -> false;
(_) -> true
end, P),
ok.
-add_path(suite) -> [];
-add_path(doc) -> [];
add_path(Config) when is_list(Config) ->
P = code:get_path(),
{'EXIT',_} = (catch code:add_path({})),
@@ -168,8 +158,6 @@ add_path(Config) when is_list(Config) ->
code:set_path(P),
ok.
-add_paths(suite) -> [];
-add_paths(doc) -> [];
add_paths(Config) when is_list(Config) ->
P = code:get_path(),
ok = code:add_paths([{}]),
@@ -215,8 +203,6 @@ add_paths(Config) when is_list(Config) ->
code:set_path(P),
ok.
-del_path(suite) -> [];
-del_path(doc) -> [];
del_path(Config) when is_list(Config) ->
P = code:get_path(),
try
@@ -226,18 +212,18 @@ del_path(Config) when is_list(Config) ->
end.
del_path_1(P) ->
- test_server:format("Initial code:get_path()=~p~n",[P]),
+ io:format("Initial code:get_path()=~p~n",[P]),
{'EXIT',_} = (catch code:del_path(3)),
false = code:del_path(my_dummy_name),
false = code:del_path("/kdlk/my_dummy_dir"),
Dir = filename:join([code:lib_dir(kernel),"ebin"]),
- test_server:format("kernel dir: ~p~n",[Dir]),
+ io:format("kernel dir: ~p~n",[Dir]),
true = code:del_path(kernel),
NewP = code:get_path(),
- test_server:format("Path after removing 'kernel':~p~n",[NewP]),
+ io:format("Path after removing 'kernel':~p~n",[NewP]),
ReferenceP = lists:delete(Dir,P),
- test_server:format("Reference path:~p~n",[ReferenceP]),
+ io:format("Reference path:~p~n",[ReferenceP]),
NewP = ReferenceP, % check that dir is deleted
code:set_path(P),
@@ -251,10 +237,8 @@ del_path_1(P) ->
NewP1 = lists:delete(Dir,P), % check that dir is deleted
ok.
-replace_path(suite) -> [];
-replace_path(doc) -> [];
replace_path(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
P = code:get_path(),
{'EXIT',_} = (catch code:replace_path(3,"")),
{error, bad_name} = code:replace_path(dummy_name,""),
@@ -289,10 +273,9 @@ replace_path(Config) when is_list(Config) ->
ok.
-dir_disappeared(suite) -> [];
-dir_disappeared(doc) -> ["OTP-3977"];
+%% OTP-3977.
dir_disappeared(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Dir = filename:join(PrivDir, "temp"),
ok = file:make_dir(Dir),
true = code:add_path(Dir),
@@ -300,8 +283,6 @@ dir_disappeared(Config) when is_list(Config) ->
non_existing = code:which(bubbelskrammel),
ok.
-load_file(suite) -> [];
-load_file(doc) -> [];
load_file(Config) when is_list(Config) ->
{error, nofile} = code:load_file(duuuumy_mod),
{error, badfile} = code:load_file(code_a_test),
@@ -316,8 +297,6 @@ load_file(Config) when is_list(Config) ->
test_dir() ->
filename:dirname(code:which(?MODULE)).
-load_abs(suite) -> [];
-load_abs(doc) -> [];
load_abs(Config) when is_list(Config) ->
TestDir = test_dir(),
{error, nofile} = code:load_abs(TestDir ++ "/duuuumy_mod"),
@@ -330,8 +309,6 @@ load_abs(Config) when is_list(Config) ->
code:unstick_dir(TestDir),
ok.
-ensure_loaded(suite) -> [];
-ensure_loaded(doc) -> [];
ensure_loaded(Config) when is_list(Config) ->
{module, lists} = code:ensure_loaded(lists),
case init:get_argument(mode) of
@@ -348,8 +325,6 @@ ensure_loaded(Config) when is_list(Config) ->
ok
end.
-delete(suite) -> [];
-delete(doc) -> [];
delete(Config) when is_list(Config) ->
OldFlag = process_flag(trap_exit, true),
code:purge(code_b_test),
@@ -366,8 +341,6 @@ delete(Config) when is_list(Config) ->
process_flag(trap_exit, OldFlag),
ok.
-purge(suite) -> [];
-purge(doc) -> [];
purge(Config) when is_list(Config) ->
OldFlag = process_flag(trap_exit, true),
code:purge(code_b_test),
@@ -383,8 +356,23 @@ purge(Config) when is_list(Config) ->
purge_many_exits(Config) when is_list(Config) ->
OldFlag = process_flag(trap_exit, true),
+
code:purge(code_b_test),
{'EXIT',_} = (catch code:purge({})),
+
+ CodePurgeF = fun(M, Exp) -> Exp = code:purge(M) end,
+ purge_many_exits_do(CodePurgeF),
+
+ %% Let's repeat test for erlang:purge_module as it does the same thing
+ %% now in erts-8.0 (except for return value).
+ ErlangPurgeF = fun(M, _Exp) -> erlang:purge_module(M) end,
+ purge_many_exits_do(ErlangPurgeF),
+
+ process_flag(trap_exit, OldFlag),
+ ok.
+
+
+purge_many_exits_do(PurgeF) ->
false = code:purge(code_b_test),
TPids = lists:map(fun (_) ->
{code_b_test:do_spawn(),
@@ -395,7 +383,7 @@ purge_many_exits(Config) when is_list(Config) ->
end)}
end,
lists:seq(1, 1000)),
- % Give them time to start...
+ %% Give them time to start...
receive after 1000 -> ok end,
true = code:delete(code_b_test),
lists:foreach(fun ({Pid1, Pid2}) ->
@@ -403,7 +391,7 @@ purge_many_exits(Config) when is_list(Config) ->
false = code_b_test:check_exit(Pid1),
true = erlang:is_process_alive(Pid2)
end, TPids),
- true = code:purge(code_b_test),
+ PurgeF(code_b_test, true),
lists:foreach(fun ({Pid1, Pid2}) ->
false = erlang:is_process_alive(Pid1),
true = code_b_test:check_exit(Pid1),
@@ -412,13 +400,9 @@ purge_many_exits(Config) when is_list(Config) ->
end, TPids),
lists:foreach(fun ({_Pid1, Pid2}) ->
receive {'EXIT', Pid2, _} -> ok end
- end, TPids),
- process_flag(trap_exit, OldFlag),
- ok.
+ end, TPids).
-soft_purge(suite) -> [];
-soft_purge(doc) -> [];
soft_purge(Config) when is_list(Config) ->
OldFlag = process_flag(trap_exit, true),
code:purge(code_b_test),
@@ -435,8 +419,6 @@ soft_purge(Config) when is_list(Config) ->
process_flag(trap_exit, OldFlag),
ok.
-is_loaded(suite) -> [];
-is_loaded(doc) -> [];
is_loaded(Config) when is_list(Config) ->
code:purge(code_b_test),
code:delete(code_b_test),
@@ -450,10 +432,8 @@ is_loaded(Config) when is_list(Config) ->
code:delete(code_b_test),
ok.
-all_loaded(suite) -> [];
-all_loaded(doc) -> [];
all_loaded(Config) when is_list(Config) ->
- case ?t:is_cover() of
+ case test_server:is_cover() of
true -> {skip,"Cover is running"};
false -> all_loaded_1()
end.
@@ -481,8 +461,6 @@ all_unique([]) -> ok;
all_unique([_]) -> ok;
all_unique([{X,_}|[{Y,_}|_]=T]) when X < Y -> all_unique(T).
-load_binary(suite) -> [];
-load_binary(doc) -> [];
load_binary(Config) when is_list(Config) ->
TestDir = test_dir(),
File = TestDir ++ "/code_b_test" ++ code:objfile_extension(),
@@ -499,7 +477,7 @@ load_binary(Config) when is_list(Config) ->
ok.
upgrade(Config) ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
%%T = [beam, hipe],
T = [beam],
@@ -531,15 +509,11 @@ compile_load(Mod, Dir, Ver, CodeType) ->
CompOpts = [binary, report] ++ Target ++ Version,
Src = filename:join(Dir, atom_to_list(Mod) ++ ".erl"),
- %io:format("compile:file(~p,~p)\n", [Src, CompOpts]),
{ok,Mod,Code} = compile:file(Src, CompOpts),
ObjFile = filename:basename(Src,".erl") ++ ".beam",
{module,Mod} = code:load_binary(Mod, ObjFile, Code),
- %IsNative = code:is_module_native(Mod),
ok.
-dir_req(suite) -> [];
-dir_req(doc) -> [];
dir_req(Config) when is_list(Config) ->
{ok,[[Root0]]} = init:get_argument(root),
Root = filename:join([Root0]), % Normalised form.
@@ -554,8 +528,6 @@ dir_req(Config) when is_list(Config) ->
{error, bad_name} = code:priv_dir(duuumy),
ok.
-object_code(suite) -> [];
-object_code(doc) -> [];
object_code(Config) when is_list(Config) ->
TestDir = test_dir(),
P = code:get_path(),
@@ -576,22 +548,20 @@ object_code(Config) when is_list(Config) ->
P=code:get_path(),
ok.
-set_path_file(suite) -> [];
-set_path_file(doc) -> ["Test that set_path does not accept ",
- "files as pathnames (known previous bug)"];
+%% Test that set_path does not accept
+%% files as pathnames (known previous bug)
set_path_file(Config) when is_list(Config) ->
- File=filename:join(?config(priv_dir, Config), "testfil"),
+ File=filename:join(proplists:get_value(priv_dir, Config), "testfil"),
ok=file:write_file(File, list_to_binary("lite data")),
{error, bad_directory}=code:set_path([File]).
-sticky_dir(suite) -> [];
-sticky_dir(doc) -> ["Test that a module with the same name as a module in ",
- "a sticky directory cannot be loaded."];
+%% Test that a module with the same name as a module in
+%% a sticky directory cannot be loaded.
sticky_dir(Config) when is_list(Config) ->
Pa = filename:dirname(code:which(?MODULE)),
- {ok,Node} = ?t:start_node(sticky_dir, slave, [{args,"-pa "++Pa}]),
+ {ok,Node} = test_server:start_node(sticky_dir, slave, [{args,"-pa "++Pa}]),
Mods = [code,lists,erlang,init],
- OutDir = filename:join(?config(priv_dir, Config), sticky_dir),
+ OutDir = filename:join(proplists:get_value(priv_dir, Config), sticky_dir),
_ = file:make_dir(OutDir),
Ret = rpc:call(Node, erlang, apply,
[fun sticky_compiler/2,[Mods,OutDir]]),
@@ -600,9 +570,9 @@ sticky_dir(Config) when is_list(Config) ->
ok;
Other ->
io:format("~p\n", [Other]),
- ?t:fail()
+ ct:fail(failed)
end,
- ?t:stop_node(Node),
+ test_server:stop_node(Node),
ok.
sticky_compiler(Files, PrivDir) ->
@@ -627,34 +597,31 @@ do_sticky_compile(Mod, Dir) ->
ok
end.
-pa_pz_option(suite) -> [];
-pa_pz_option(doc) -> ["Test that the -pa and -pz options work as expected"];
+%% Test that the -pa and -pz options work as expected.
pa_pz_option(Config) when is_list(Config) ->
- DDir = ?config(data_dir,Config),
+ DDir = proplists:get_value(data_dir,Config),
PaDir = filename:join(DDir,"pa"),
PzDir = filename:join(DDir,"pz"),
- {ok, Node}=?t:start_node(pa_pz1, slave,
+ {ok, Node}=test_server:start_node(pa_pz1, slave,
[{args,
"-pa " ++ PaDir
++ " -pz " ++ PzDir}]),
Ret=rpc:call(Node, code, get_path, []),
[PaDir|Paths] = Ret,
[PzDir|_] = lists:reverse(Paths),
- ?t:stop_node(Node),
- {ok, Node2}=?t:start_node(pa_pz2, slave,
+ test_server:stop_node(Node),
+ {ok, Node2}=test_server:start_node(pa_pz2, slave,
[{args,
"-mode embedded " ++ "-pa "
++ PaDir ++ " -pz " ++ PzDir}]),
Ret2=rpc:call(Node2, code, get_path, []),
[PaDir|Paths2] = Ret2,
[PzDir|_] = lists:reverse(Paths2),
- ?t:stop_node(Node2).
+ test_server:stop_node(Node2).
-add_del_path(suite) ->
- [];
-add_del_path(doc) -> ["add_path, del_path should not cause priv_dir(App) to fail"];
+%% add_path, del_path should not cause priv_dir(App) to fail.
add_del_path(Config) when is_list(Config) ->
- DDir = ?config(data_dir,Config),
+ DDir = proplists:get_value(data_dir,Config),
Dir1 = filename:join(DDir,"dummy_app-1.0/ebin"),
Dir2 = filename:join(DDir,"dummy_app-2.0/ebin"),
code:add_patha(Dir1),
@@ -668,43 +635,35 @@ add_del_path(Config) when is_list(Config) ->
clash(Config) when is_list(Config) ->
- DDir = ?config(data_dir,Config)++"clash/",
+ DDir = proplists:get_value(data_dir,Config)++"clash/",
P = code:get_path(),
- [TestServerPath|_] = [Path || Path <- code:get_path(),
- re:run(Path,"test_server/?$",[unicode]) /= nomatch],
%% test non-clashing entries
- %% remove TestServerPath to prevent clash with test-server path
- true = code:del_path(TestServerPath),
true = code:add_path(DDir++"foobar-0.1/ebin"),
true = code:add_path(DDir++"zork-0.8/ebin"),
- test_server:capture_start(),
+ ct:capture_start(),
ok = code:clash(),
- test_server:capture_stop(),
- [OKMsg|_] = test_server:capture_get(),
+ ct:capture_stop(),
+ [OKMsg|_] = ct:capture_get(),
true = lists:prefix("** Found 0 name clashes", OKMsg),
true = code:set_path(P),
%% test clashing entries
- %% remove TestServerPath to prevent clash with test-server path
- true = code:del_path(TestServerPath),
true = code:add_path(DDir++"foobar-0.1/ebin"),
true = code:add_path(DDir++"foobar-0.1.ez/foobar-0.1/ebin"),
- test_server:capture_start(),
+ ct:capture_start(),
ok = code:clash(),
- test_server:capture_stop(),
- [ClashMsg|_] = test_server:capture_get(),
+ ct:capture_stop(),
+ [ClashMsg|_] = ct:capture_get(),
{match, [" hides "]} = re:run(ClashMsg, "\\*\\* .*( hides ).*",
[{capture,all_but_first,list}]),
true = code:set_path(P),
%% test "Bad path can't read"
- %% remove TestServerPath to prevent clash with test-server path
- Priv = ?config(priv_dir, Config),
- true = code:del_path(TestServerPath),
+ Priv = proplists:get_value(priv_dir, Config),
TmpEzFile = Priv++"foobar-0.tmp.ez",
{ok, _} = file:copy(DDir++"foobar-0.1.ez", TmpEzFile),
true = code:add_path(TmpEzFile++"/foobar-0.1/ebin"),
@@ -716,20 +675,17 @@ clash(Config) when is_list(Config) ->
_ ->
ok = file:delete(TmpEzFile)
end,
- test_server:capture_start(),
+ ct:capture_start(),
ok = code:clash(),
- test_server:capture_stop(),
- [BadPathMsg|_] = test_server:capture_get(),
+ ct:capture_stop(),
+ [BadPathMsg|_] = ct:capture_get(),
true = lists:prefix("** Bad path can't read", BadPathMsg),
true = code:set_path(P),
file:delete(TmpEzFile++".moved"), %% Only effect on windows
ok.
-ext_mod_dep(suite) ->
- [];
-ext_mod_dep(doc) ->
- ["Every module that the code_server uses should be preloaded, "
- "this test case verifies that"];
+%% Every module that the code_server uses should be preloaded,
+%% this test case verifies that.
ext_mod_dep(Config) when is_list(Config) ->
xref:start(s),
xref:set_default(s, [{verbose,false},{warnings,false},
@@ -745,7 +701,7 @@ ext_mod_dep(Config) when is_list(Config) ->
xref:stop(s),
case Else of
ok -> ok;
- _ -> test_server:fail(Else)
+ _ -> ct:fail(Else)
end
end.
@@ -769,6 +725,7 @@ analyse([], [This={M,F,A}|Path], Visited, ErrCnt0) ->
OK = [erlang, os, prim_file, erl_prim_loader, init, ets,
code_server, lists, lists_sort, unicode, binary, filename,
gb_sets, gb_trees, hipe_unified_loader, hipe_bifs,
+ erts_code_purger,
prim_zip, zlib],
ErrCnt1 =
case lists:member(M, OK) or erlang:is_builtin(M,F,A) of
@@ -794,7 +751,7 @@ analyse2(MFA={_,_,_}, Path, Visited0) ->
analyse(FL, [MFA|Path], my_usort([MFA|Visited0]), 0).
%%%% We need to check these manually...
-% fun's are ok as long as they are defined locally.
+%% fun's are ok as long as they are defined locally.
check_funs({'$M_EXPR','$F_EXPR',_},
[{unicode,characters_to_binary_int,3},
{unicode,characters_to_binary,3},
@@ -839,18 +796,7 @@ check_funs({'$M_EXPR','$F_EXPR',1},
{code_server,start_link,1}]) -> 0;
check_funs({'$M_EXPR','$F_EXPR',1},
[{lists,filter,2},
- {code_server,try_archive_subdirs,3},
- {code_server,all_archive_subdirs,1},
- {code_server,archive_subdirs,1},
- {code_server,insert_name,3},
- {code_server,replace_name,2},
- {code_server,update,2},
- {code_server,maybe_update,2},
- {code_server,do_add,4},
- {code_server,add_path,4},
- {code_server,handle_call,3},
- {code_server,loop,1},
- {code_server,system_continue,3}]) -> 0;
+ {code_server,try_archive_subdirs,3}|_]) -> 0;
check_funs({'$M_EXPR','$F_EXPR',_},
[{erlang,apply,2},
{erlang,spawn_link,1},
@@ -877,19 +823,21 @@ check_funs({'$M_EXPR','$F_EXPR',1},
{hipe_unified_loader,get_refs_from,2}| _]) -> 0;
check_funs({'$M_EXPR',warning_msg,2},
[{code_server,finish_on_load_report,2} | _]) -> 0;
+check_funs({'$M_EXPR','$F_EXPR',1},
+ [{code_server,run,2}|_]) -> 0;
%% This is cheating! /raimo
%%
%% check_funs(This = {M,_,_}, Path) ->
%% case catch atom_to_list(M) of
%% [$h,$i,$p,$e | _] ->
-%% test_server:format("hipe_module_ignored(~p, ~p)~n", [This, Path]),
+%% io:format("hipe_module_ignored(~p, ~p)~n", [This, Path]),
%% 0;
%% _ ->
-%% test_server:format("not_verified(~p, ~p)~n", [This, Path]),
+%% io:format("not_verified(~p, ~p)~n", [This, Path]),
%% 1
%% end;
check_funs(This, Path) ->
- test_server:format("not_verified(~p, ~p)~n", [This, Path]),
+ io:format("not_verified(~p, ~p)~n", [This, Path]),
1.
my_usort(List) ->
@@ -905,140 +853,7 @@ uniq([H|T],A) ->
uniq(T,[H|A]).
-load_cached(suite) ->
- [];
-load_cached(doc) ->
- [];
-load_cached(Config) when is_list(Config) ->
- Priv = ?config(priv_dir, Config),
- WD = filename:dirname(code:which(?MODULE)),
- {ok,Node} =
- ?t:start_node(code_cache_node, peer, [{args,
- "-pa \"" ++ WD ++ "\""},
- {erl, [this]}]),
- CCTabCreated = fun(Tab) ->
- case ets:info(Tab, name) of
- code_cache -> true;
- _ -> false
- end
- end,
- Tabs = rpc:call(Node, ets, all, []),
- case rpc:call(Node, lists, any, [CCTabCreated,Tabs]) of
- true ->
- ?t:stop_node(Node),
- ?t:fail("Code cache should not be active!");
- false ->
- ok
- end,
- rpc:call(Node, code, del_path, [Priv]),
- rpc:call(Node, code, add_pathz, [Priv]),
-
- FullModName = Priv ++ "/code_cache_test",
- {ok,Dev} = file:open(FullModName ++ ".erl", [write]),
- io:format(Dev, "-module(code_cache_test). -export([a/0]). a() -> ok.~n", []),
- ok = file:close(Dev),
- {ok,code_cache_test} = compile:file(FullModName, [{outdir,Priv}]),
-
- F = fun load_loop/2,
- N = 1000,
- {T0,T1} = rpc:call(Node, erlang, apply, [F, [N,code_cache_test]]),
- TNoCache = now_diff(T1, T0),
- rpc:call(Node, code, rehash, []),
- {T2,T3} = rpc:call(Node, erlang, apply, [F, [N,code_cache_test]]),
- TCache = now_diff(T3, T2),
- AvgNoCache = TNoCache/N,
- AvgCache = TCache/N,
- io:format("Avg. load time (no_cache/cache): ~w/~w~n", [AvgNoCache,AvgCache]),
- ?t:stop_node(Node),
- if AvgNoCache =< AvgCache ->
- ?t:fail("Cache not working properly.");
- true ->
- ok
- end.
-
-load_loop(N, M) ->
- load_loop(N, M, now()).
-load_loop(0, _M, T0) ->
- {T0,now()};
-load_loop(N, M, T0) ->
- code:load_file(M),
- code:delete(M),
- code:purge(M),
- load_loop(N-1, M, T0).
-
-now_diff({A2, B2, C2}, {A1, B1, C1}) ->
- ((A2-A1)*1000000 + B2-B1)*1000000 + C2-C1.
-
-start_node_with_cache(suite) ->
- [];
-start_node_with_cache(doc) ->
- [];
-start_node_with_cache(Config) when is_list(Config) ->
- {ok,Node} =
- ?t:start_node(code_cache_node, peer, [{args,
- "-code_path_cache"},
- {erl, [this]}]),
- Tabs = rpc:call(Node, ets, all, []),
- io:format("Tabs: ~w~n", [Tabs]),
- CCTabCreated = fun(Tab) ->
- case rpc:call(Node, ets, info, [Tab,name]) of
- code_cache -> true;
- _ -> false
- end
- end,
- true = lists:any(CCTabCreated, Tabs),
- ?t:stop_node(Node),
- ok.
-
-add_and_rehash(suite) ->
- [];
-add_and_rehash(doc) ->
- [];
-add_and_rehash(Config) when is_list(Config) ->
- Priv = ?config(priv_dir, Config),
- WD = filename:dirname(code:which(?MODULE)),
- {ok,Node} =
- ?t:start_node(code_cache_node, peer, [{args,
- "-pa \"" ++ WD ++ "\""},
- {erl, [this]}]),
- CCTabCreated = fun(Tab) ->
- case ets:info(Tab, name) of
- code_cache -> true;
- _ -> false
- end
- end,
- Tabs0 = rpc:call(Node, ets, all, []),
- case rpc:call(Node, lists, any, [CCTabCreated,Tabs0]) of
- true ->
- ?t:stop_node(Node),
- ?t:fail("Code cache should not be active!");
- false ->
- ok
- end,
- ok = rpc:call(Node, code, rehash, []), % create cache
- Tabs1 = rpc:call(Node, ets, all, []),
- true = rpc:call(Node, lists, any, [CCTabCreated,Tabs1]), % cache table created
- ok = rpc:call(Node, code, rehash, []),
- OkDir = filename:join(Priv, ""),
- BadDir = filename:join(Priv, "guggemuffsussiputt"),
- CP = [OkDir | rpc:call(Node, code, get_path, [])],
- true = rpc:call(Node, code, set_path, [CP]),
- CP1 = [BadDir | CP],
- {error,_} = rpc:call(Node, code, set_path, [CP1]),
- true = rpc:call(Node, code, del_path, [OkDir]),
- true = rpc:call(Node, code, add_path, [OkDir]),
- true = rpc:call(Node, code, add_path, [OkDir]),
- {error,_} = rpc:call(Node, code, add_path, [BadDir]),
- ok = rpc:call(Node, code, rehash, []),
-
- ?t:stop_node(Node),
- ok.
-
-where_is_file_no_cache(suite) ->
- [];
-where_is_file_no_cache(doc) ->
- [];
-where_is_file_no_cache(Config) when is_list(Config) ->
+where_is_file(Config) when is_list(Config) ->
{T,KernelBeamFile} = timer:tc(code, where_is_file, ["kernel.beam"]),
io:format("Load time: ~w ms~n", [T]),
KernelEbinDir = filename:dirname(KernelBeamFile),
@@ -1047,39 +862,7 @@ where_is_file_no_cache(Config) when is_list(Config) ->
non_existing = code:where_is_file("kernel"), % no such file
ok.
-where_is_file_cached(suite) ->
- [];
-where_is_file_cached(doc) ->
- [];
-where_is_file_cached(Config) when is_list(Config) ->
- {ok,Node} =
- ?t:start_node(code_cache_node, peer, [{args,
- "-code_path_cache"},
- {erl, [this]}]),
- Tabs = rpc:call(Node, ets, all, []),
- io:format("Tabs: ~w~n", [Tabs]),
- CCTabCreated = fun(Tab) ->
- case rpc:call(Node, ets, info, [Tab,name]) of
- code_cache -> true;
- _ -> false
- end
- end,
- true = lists:any(CCTabCreated, Tabs),
- KernelBeamFile = rpc:call(Node, code, where_is_file, ["kernel.beam"]),
- {T,KernelBeamFile} = rpc:call(Node, timer, tc, [code,where_is_file,["kernel.beam"]]),
- io:format("Load time: ~w ms~n", [T]),
- KernelEbinDir = rpc:call(Node, filename, dirname, [KernelBeamFile]),
- AppFile = rpc:call(Node, filename, join, [KernelEbinDir,"kernel.app"]),
- AppFile = rpc:call(Node, code, where_is_file, ["kernel.app"]),
- non_existing = rpc:call(Node, code, where_is_file, ["kernel"]), % no such file
- ?t:stop_node(Node),
- ok.
-
-
-purge_stacktrace(suite) ->
- [];
-purge_stacktrace(doc) ->
- ["Test that stacktrace is deleted when purging a referred module"];
+%% Test that stacktrace is deleted when purging a referred module.
purge_stacktrace(Config) when is_list(Config) ->
code:purge(code_b_test),
try code_b_test:call(fun(b) -> ok end, a)
@@ -1120,7 +903,7 @@ purge_stacktrace(Config) when is_list(Config) ->
ok.
mult_lib_roots(Config) when is_list(Config) ->
- DataDir = filename:join(?config(data_dir, Config), "mult_lib_roots"),
+ DataDir = filename:join(proplists:get_value(data_dir, Config), "mult_lib_roots"),
mult_lib_compile(DataDir, "my_dummy_app-b/ebin/lists"),
mult_lib_compile(DataDir,
"my_dummy_app-c/ebin/code_SUITE_mult_root_module"),
@@ -1130,7 +913,7 @@ mult_lib_roots(Config) when is_list(Config) ->
filename:join(DataDir, "second_root"),
{ok,Node} =
- ?t:start_node(mult_lib_roots, slave,
+ test_server:start_node(mult_lib_roots, slave,
[{args,"-env ERL_LIBS "++ErlLibs}]),
Path0 = rpc:call(Node, code, get_path, []),
@@ -1178,15 +961,15 @@ mult_lib_remove_prefix([$/|T], []) -> T.
bad_erl_libs(Config) when is_list(Config) ->
{ok,Node} =
- ?t:start_node(bad_erl_libs, slave, []),
+ test_server:start_node(bad_erl_libs, slave, []),
Code = rpc:call(Node,code,get_path,[]),
- ?t:stop_node(Node),
+ test_server:stop_node(Node),
{ok,Node2} =
- ?t:start_node(bad_erl_libs, slave,
- [{args,"-env ERL_LIBS /no/such/dir"}]),
+ test_server:start_node(bad_erl_libs, slave,
+ [{args,"-env ERL_LIBS /no/such/dir"}]),
Code2 = rpc:call(Node,code,get_path,[]),
- ?t:stop_node(Node2),
+ test_server:stop_node(Node2),
%% Test that code path is not affected by the faulty ERL_LIBS
Code = Code2,
@@ -1205,8 +988,8 @@ code_archive2(Config) when is_list(Config) ->
do_code_archive(Config, Root, StripVsn) when is_list(Config) ->
%% Copy the orig files to priv_dir
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
App = code_archive_dict,
VsnBase = atom_to_list(App) ++ "-1.0",
Base =
@@ -1241,7 +1024,7 @@ do_code_archive(Config, Root, StripVsn) when is_list(Config) ->
%% Set up ERL_LIBS and start a slave node.
{ok, Node} =
- ?t:start_node(code_archive, slave,
+ test_server:start_node(code_archive, slave,
[{args,"-env ERL_LIBS " ++ RootDir}]),
CodePath = rpc:call(Node, code, get_path, []),
AppEbin = filename:join([Archive, Base, "ebin"]),
@@ -1272,7 +1055,7 @@ do_code_archive(Config, Root, StripVsn) when is_list(Config) ->
error = rpc:call(Node, App, find, [Tab, Key]),
ok = rpc:call(Node, App, erase, [Tab]),
- ?t:stop_node(Node),
+ test_server:stop_node(Node),
ok.
compile_app(TopDir, AppName) ->
@@ -1298,15 +1081,12 @@ compile_files([File | Files], SrcDir, OutDir) ->
compile_files([], _, _) ->
ok.
-big_boot_embedded(suite) ->
- [];
-big_boot_embedded(doc) ->
- ["Test that a boot file with (almost) all of OTP can be used to start an"
- " embeddedd system."];
+%% Test that a boot file with (almost) all of OTP can be used to start an
+%% embeddedd system.
big_boot_embedded(Config) when is_list(Config) ->
{BootArg,AppsInBoot} = create_big_boot(Config),
{ok, Node} =
- ?t:start_node(big_boot_embedded, slave,
+ test_server:start_node(big_boot_embedded, slave,
[{args,"-boot "++BootArg++" -mode embedded"}]),
RemoteNodeApps =
[ {X,Y} || {X,_,Y} <-
@@ -1317,7 +1097,7 @@ big_boot_embedded(Config) when is_list(Config) ->
on_load(Config) when is_list(Config) ->
Master = on_load_test_case_process,
- Data = filename:join([?config(data_dir, Config),"on_load"]),
+ Data = filename:join([proplists:get_value(data_dir, Config),"on_load"]),
ok = file:set_cwd(Data),
up_to_date = make:all([{d,'MASTER',Master}]),
@@ -1361,7 +1141,7 @@ on_load(Config) when is_list(Config) ->
on_load_wait_for_all(Refs),
receive
Any ->
- ?t:fail({unexpected,Any})
+ ct:fail({unexpected,Any})
after 10 ->
ok
end.
@@ -1429,7 +1209,7 @@ on_load_embedded(Config) when is_list(Config) ->
end.
on_load_embedded_1(Config) ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
%% Link the on_load_app application into the lib directory.
LibRoot = code:lib_dir(),
@@ -1484,7 +1264,7 @@ create_boot(Config, Options) ->
filename:join(LatestDir, LatestName).
create_script(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Name = PrivDir ++ "on_load_test",
Apps = application_controller:which_applications(),
{value,{_,_,KernelVer}} = lists:keysearch(kernel, 1, Apps),
@@ -1511,33 +1291,46 @@ create_big_boot(Config) ->
ok = file:set_cwd(OldDir),
{filename:join(LatestDir, LatestName),Apps}.
-% The following apps cannot be loaded
-% hipe .app references (or can reference) files that have no
-% corresponding beam file (if hipe is not enabled)
+%% The following apps cannot be loaded.
+%% hipe .app references (or can reference) files that have no
+%% corresponding beam file (if hipe is not enabled).
filter_app("hipe",_) -> false;
-% Dialyzer and typer depends on hipe
+
+%% Dialyzer and typer depends on hipe
filter_app("dialyzer",_) -> false;
filter_app("typer",_) -> false;
-% Orber requires explicit configuration
+
+%% Orber requires explicit configuration
filter_app("orber",_) -> false;
-% cos* depends on orber
+
+%% cos* depends on orber
filter_app("cos"++_,_) -> false;
-% ic has a mod instruction in the app file but no corresponding start function
+
+%% ic has a mod instruction in the app file but no corresponding start
+%% function
filter_app("ic",_) -> false;
-% Netconf has some dependency that I really do not understand (maybe like orber)
+
+%% Netconf has some dependency that I really do not understand (maybe
+%% like orber)
filter_app("netconf",_) -> false;
-% Safe has the same kind of error in the .app file as ic
+
+%% Safe has the same kind of error in the .app file as ic
filter_app("safe",_) -> false;
-% Comte cannot be started in the "usual" way
+
+%% Comte cannot be started in the "usual" way
filter_app("comte",_) -> false;
-% OS_mon does not find it's port program when running cerl
+
+%% OS_mon does not find its port program when running cerl
filter_app("os_mon",true) -> false;
-% erts is not a "real" app either =/
+
+%% erts is not a "real" app either =/
filter_app("erts",_) -> false;
-% Other apps should be OK.
+
+%% Other apps should be OK.
filter_app(_,_) -> true.
+
create_big_script(Config,Local) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Name = filename:join(PrivDir,"full_script_test"),
InitialApplications=application:loaded_applications(),
%% Applications left loaded by the application suite, unload them!
@@ -1571,7 +1364,7 @@ on_load_errors(Config) when is_list(Config) ->
Master = on_load_error_test_case_process,
register(Master, self()),
- Data = filename:join([?config(data_dir, Config),"on_load_errors"]),
+ Data = filename:join([proplists:get_value(data_dir, Config),"on_load_errors"]),
ok = file:set_cwd(Data),
up_to_date = make:all([{d,'MASTER',Master}]),
@@ -1597,7 +1390,7 @@ on_load_errors(Config) when is_list(Config) ->
%% There should be no more messages.
receive
Unexpected ->
- ?t:fail({unexpected,Unexpected})
+ ct:fail({unexpected,Unexpected})
after 10 ->
ok
end,
@@ -1626,8 +1419,7 @@ do_on_load_error(ReturnValue) ->
{undef,[{on_load_error,main,[],_}|_]} = Exit
end.
-native_early_modules(suite) -> [];
-native_early_modules(doc) -> ["Test that the native code of early loaded modules is loaded"];
+%% Test that the native code of early loaded modules is loaded.
native_early_modules(Config) when is_list(Config) ->
case erlang:system_info(hipe_architecture) of
undefined ->
@@ -1655,8 +1447,7 @@ native_early_modules_1(Architecture) ->
ok
end.
-get_mode(suite) -> [];
-get_mode(doc) -> ["Test that the mode of the code server is properly retrieved"];
+%% Test that the mode of the code server is properly retrieved.
get_mode(Config) when is_list(Config) ->
interactive = code:get_mode().
@@ -1686,7 +1477,7 @@ terminate(_Reason, State) ->
%%%
start_node(Name, Param) ->
- ?t:start_node(Name, slave, [{args, Param}]).
+ test_server:start_node(Name, slave, [{args, Param}]).
stop_node(Node) ->
- ?t:stop_node(Node).
+ test_server:stop_node(Node).
diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl
index 9988347581..135144bbe7 100644
--- a/lib/kernel/test/disk_log_SUITE.erl
+++ b/lib/kernel/test/disk_log_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(disk_log_SUITE).
-%-define(debug, true).
+%%-define(debug, true).
-ifdef(debug).
-define(format(S, A), io:format(S, A)).
@@ -29,10 +29,10 @@
-define(config(X,Y), foo).
-define(t,test_server).
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(format(S, A), ok).
--define(privdir(Conf), ?config(priv_dir, Conf)).
--define(datadir(Conf), ?config(data_dir, Conf)).
+-define(privdir(Conf), proplists:get_value(priv_dir, Conf)).
+-define(datadir(Conf), proplists:get_value(data_dir, Conf)).
-endif.
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -102,8 +102,6 @@
-export([client/4]).
--define(default_timeout, ?t:minutes(1)).
-
%% error_logger
-export([init/1,
handle_event/2, handle_call/2, handle_info/2,
@@ -139,7 +137,9 @@
change_size_after, default_size]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,2}}].
all() ->
[{group, halt_int}, {group, wrap_int},
@@ -194,259 +194,229 @@ end_per_group(_GroupName, Config) ->
-init_per_testcase(Case, Config) ->
- case should_skip(Case,Config) of
- true ->
- CS = check_nfs(Config),
- {skipped, lists:flatten
- (io_lib:format
- ("The test does not work "
- "with current NFS cache size (~w),"
- " to get this test to run, "
- "~s the NFS cache size~n",
- [CS, case CS of
- 0 ->
- "enlarge";
- _ ->
- "zero"
- end]))};
- _ ->
- Dog=?t:timetrap(?t:minutes(2)),
- [{watchdog, Dog}|Config]
- end.
+init_per_testcase(_Case, Config) ->
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
-halt_int_inf(suite) -> [];
-halt_int_inf(doc) -> ["Test simple halt disk log, size infinity"];
+%% Test simple halt disk log, size infinity.
halt_int_inf(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
- ?line ok = disk_log:start(),
+ ok = disk_log:start(),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
- {format,internal},
- {file, File}]),
- ?line simple_log(a),
- ?line ok = disk_log:close(a),
- ?line ok = file:delete(File).
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
+ {format,internal},
+ {file, File}]),
+ simple_log(a),
+ ok = disk_log:close(a),
+ ok = file:delete(File).
-halt_int_sz_1(suite) -> [];
-halt_int_sz_1(doc) -> ["Test simple halt disk log, size defined"];
+%% Test simple halt disk log, size defined.
halt_int_sz_1(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,18000},
- {format,internal},
- {file, File}]),
- ?line simple_log(a),
- ?line ok = disk_log:truncate(a),
- ?line [] = get_all_terms(a),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,18000},
+ {format,internal},
+ {file, File}]),
+ simple_log(a),
+ ok = disk_log:truncate(a),
+ [] = get_all_terms(a),
T1 = mk_bytes(10000),
T2 = mk_bytes(5000),
- ?line ok = disk_log:log(a, T1),
- ?line case get_all_terms(a) of
- [T1] ->
- ok;
- E1 ->
- test_server_fail({bad_terms, E1, [T1]})
- end,
- ?line ok = disk_log:log(a, T2),
- ?line {error, {full, a}} = disk_log:log(a, T1),
- ?line ok = disk_log:alog(a, T1),
- ?line case get_all_terms(a) of
- [T1, T2] ->
- ok;
- E2 ->
- test_server_fail({bad_terms, E2, [T1, T2]})
- end,
- ?line ok = disk_log:close(a),
- ?line ok = file:delete(File).
+ ok = disk_log:log(a, T1),
+ case get_all_terms(a) of
+ [T1] ->
+ ok;
+ E1 ->
+ test_server_fail({bad_terms, E1, [T1]})
+ end,
+ ok = disk_log:log(a, T2),
+ {error, {full, a}} = disk_log:log(a, T1),
+ ok = disk_log:alog(a, T1),
+ case get_all_terms(a) of
+ [T1, T2] ->
+ ok;
+ E2 ->
+ test_server_fail({bad_terms, E2, [T1, T2]})
+ end,
+ ok = disk_log:close(a),
+ ok = file:delete(File).
-halt_int_sz_2(suite) -> [];
-halt_int_sz_2(doc) -> ["Test simple halt disk log, size ~8192"];
+%% Test simple halt disk log, size ~8192.
halt_int_sz_2(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File1 = filename:join(Dir, "a.LOG"),
File2 = filename:join(Dir, "b.LOG"),
File3 = filename:join(Dir, "c.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,8191},
- {format,internal},
- {file, File1}]),
- ?line {ok, b} = disk_log:open([{name,b}, {type,halt}, {size,8192},
- {format,internal},
- {file, File2}]),
- ?line {ok, c} = disk_log:open([{name,c}, {type,halt}, {size,8193},
- {format,internal},
- {file, File3}]),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,8191},
+ {format,internal},
+ {file, File1}]),
+ {ok, b} = disk_log:open([{name,b}, {type,halt}, {size,8192},
+ {format,internal},
+ {file, File2}]),
+ {ok, c} = disk_log:open([{name,c}, {type,halt}, {size,8193},
+ {format,internal},
+ {file, File3}]),
T1 = mk_bytes(8191-16), % 16 is size of header + magics for 1 item
T2 = mk_bytes(8192-16),
T3 = mk_bytes(8193-16),
- ?line ok = disk_log:log(a, T1),
- ?line ok = disk_log:log(b, T2),
- ?line ok = disk_log:log(c, T3),
- ?line case get_all_terms(a) of
- [T1] ->
- ok;
- E1 ->
- test_server_fail({bad_terms, E1, [T1]})
- end,
- ?line case get_all_terms(b) of
- [T2] ->
- ok;
- E2 ->
- test_server_fail({bad_terms, E2, [T2]})
- end,
- ?line case get_all_terms(c) of
- [T3] ->
- ok;
- E3 ->
- test_server_fail({bad_terms, E3, [T3]})
- end,
- ?line ok = disk_log:truncate(a),
- ?line ok = disk_log:truncate(b),
- ?line {error, {full, a}} = disk_log:log(a, T2),
- ?line {error, {full, b}} = disk_log:log(b, T3),
- ?line [] = get_all_terms(a),
- ?line [] = get_all_terms(b),
- ?line ok = disk_log:close(a),
- ?line ok = disk_log:close(b),
- ?line ok = disk_log:close(c),
- ?line ok = file:delete(File1),
- ?line ok = file:delete(File2),
- ?line ok = file:delete(File3),
+ ok = disk_log:log(a, T1),
+ ok = disk_log:log(b, T2),
+ ok = disk_log:log(c, T3),
+ case get_all_terms(a) of
+ [T1] ->
+ ok;
+ E1 ->
+ test_server_fail({bad_terms, E1, [T1]})
+ end,
+ case get_all_terms(b) of
+ [T2] ->
+ ok;
+ E2 ->
+ test_server_fail({bad_terms, E2, [T2]})
+ end,
+ case get_all_terms(c) of
+ [T3] ->
+ ok;
+ E3 ->
+ test_server_fail({bad_terms, E3, [T3]})
+ end,
+ ok = disk_log:truncate(a),
+ ok = disk_log:truncate(b),
+ {error, {full, a}} = disk_log:log(a, T2),
+ {error, {full, b}} = disk_log:log(b, T3),
+ [] = get_all_terms(a),
+ [] = get_all_terms(b),
+ ok = disk_log:close(a),
+ ok = disk_log:close(b),
+ ok = disk_log:close(c),
+ ok = file:delete(File1),
+ ok = file:delete(File2),
+ ok = file:delete(File3),
ok.
-halt_int_ro(suite) -> [];
-halt_int_ro(doc) -> ["Test simple halt disk log, read only, internal"];
+%% Test simple halt disk log, read only, internal.
halt_int_ro(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
- {format,internal}, {file, File}]),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
+ {format,internal}, {file, File}]),
simple_log(a),
- ?line ok = disk_log:close(a),
+ ok = disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
- {format,internal}, {file, File},
- {mode,read_only}]),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
+ {format,internal}, {file, File},
+ {mode,read_only}]),
T1 = "not allowed to write",
- ?line {error, {read_only_mode, a}} = disk_log:log(a, T1),
- ?line ok = disk_log:close(a),
- ?line ok = file:delete(File).
+ {error, {read_only_mode, a}} = disk_log:log(a, T1),
+ ok = disk_log:close(a),
+ ok = file:delete(File).
-halt_ext_ro(suite) -> [];
-halt_ext_ro(doc) -> ["Test simple halt disk log, read only, external"];
+%% Test simple halt disk log, read only, external.
halt_ext_ro(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
- {format,external}, {file, File}]),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
+ {format,external}, {file, File}]),
xsimple_log(File, a),
- ?line ok = disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
- {format,external}, {file, File},
- {mode,read_only}]),
+ ok = disk_log:close(a),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
+ {format,external}, {file, File},
+ {mode,read_only}]),
T1 = "not allowed to write",
- ?line {error, {read_only_mode, a}} = disk_log:blog(a, T1),
- ?line ok = disk_log:close(a),
- ?line ok = file:delete(File).
+ {error, {read_only_mode, a}} = disk_log:blog(a, T1),
+ ok = disk_log:close(a),
+ ok = file:delete(File).
-wrap_int_ro(suite) -> [];
-wrap_int_ro(doc) -> ["Test simple wrap disk log, read only, internal"];
+%% Test simple wrap disk log, read only, internal.
wrap_int_ro(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}},
- {format,internal}, {file, File}]),
+ {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}},
+ {format,internal}, {file, File}]),
simple_log(a),
- ?line ok = disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}},
- {format,internal}, {file, File}, {mode,read_only}]),
+ ok = disk_log:close(a),
+ {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}},
+ {format,internal}, {file, File}, {mode,read_only}]),
T1 = "not allowed to write",
- ?line {error, {read_only_mode, a}} = disk_log:log(a, T1),
- ?line ok = disk_log:close(a),
- ?line del(File, 4).
+ {error, {read_only_mode, a}} = disk_log:log(a, T1),
+ ok = disk_log:close(a),
+ del(File, 4).
-wrap_ext_ro(suite) -> [];
-wrap_ext_ro(doc) -> ["Test simple wrap disk log, read only, external"];
+%% Test simple wrap disk log, read only, external.
wrap_ext_ro(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}},
- {format,external}, {file, File}]),
+ {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}},
+ {format,external}, {file, File}]),
x2simple_log(File ++ ".1", a),
- ?line ok = disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}},
- {format,external}, {file, File},
- {mode,read_only}]),
+ ok = disk_log:close(a),
+ {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}},
+ {format,external}, {file, File},
+ {mode,read_only}]),
T1 = "not allowed to write",
- ?line {error, {read_only_mode, a}} = disk_log:blog(a, T1),
- ?line {error, {read_only_mode, a}} = disk_log:inc_wrap_file(a),
- ?line ok = disk_log:close(a),
+ {error, {read_only_mode, a}} = disk_log:blog(a, T1),
+ {error, {read_only_mode, a}} = disk_log:inc_wrap_file(a),
+ ok = disk_log:close(a),
del(File, 4).
-halt_trunc(suite) -> [];
-halt_trunc(doc) -> ["Test truncation of halt disk log"];
+%% Test truncation of halt disk log.
halt_trunc(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
- {format,internal}, {file, File}]),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
+ {format,internal}, {file, File}]),
simple_log(a),
- ?line ok = disk_log:close(a),
- ?line {error,{badarg,repair_read_only}} =
+ ok = disk_log:close(a),
+ {error,{badarg,repair_read_only}} =
disk_log:open([{name,a}, {type,halt}, {size,infinity},
{repair, truncate}, {format,internal},
{file, File}, {mode,read_only}]),
- ?line ok = file:delete(File).
+ ok = file:delete(File).
-halt_misc(suite) -> [];
-halt_misc(doc) -> ["Test truncation of halt disk log"];
+%% Test truncation of halt disk log.
halt_misc(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
- {format,internal}, {file, File}]),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
+ {format,internal}, {file, File}]),
simple_log(a),
- ?line ok = disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
- {format,internal}, {file, File},
- {mode,read_only}]),
+ ok = disk_log:close(a),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
+ {format,internal}, {file, File},
+ {mode,read_only}]),
T1 = "not allowed to write",
- ?line {error, {read_only_mode, a}} = disk_log:log(a, T1),
- ?line {error, {read_only_mode, a}} = disk_log:sync(a),
- ?line {error, {read_only_mode, a}} = disk_log:reopen(a, "b.LOG"),
- ?line {error, {read_only_mode, a}} =
+ {error, {read_only_mode, a}} = disk_log:log(a, T1),
+ {error, {read_only_mode, a}} = disk_log:sync(a),
+ {error, {read_only_mode, a}} = disk_log:reopen(a, "b.LOG"),
+ {error, {read_only_mode, a}} =
disk_log:change_header(a, {head,header}),
- ?line {error, {read_only_mode, a}} =
+ {error, {read_only_mode, a}} =
disk_log:change_size(a, infinity),
- ?line ok = disk_log:close(a),
- ?line ok = file:delete(File).
+ ok = disk_log:close(a),
+ ok = file:delete(File).
-halt_ro_alog(suite) -> [];
-halt_ro_alog(doc) -> ["Test truncation of halt disk log, read only"];
+%% Test truncation of halt disk log, read only.
halt_ro_alog(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
- {format,internal}, {file, File}]),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
+ {format,internal}, {file, File}]),
simple_log(a),
- ?line ok = disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
- {notify,true}, {format,internal},
- {file, File}, {mode,read_only}]),
+ ok = disk_log:close(a),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
+ {notify,true}, {format,internal},
+ {file, File}, {mode,read_only}]),
T1 = "not allowed to write",
- ?line ok = disk_log:alog(a, T1),
- ?line ok = halt_ro_alog_wait_notify(a, T1),
- ?line ok = disk_log:close(a),
- ?line ok = file:delete(File).
+ ok = disk_log:alog(a, T1),
+ ok = halt_ro_alog_wait_notify(a, T1),
+ ok = disk_log:close(a),
+ ok = file:delete(File).
halt_ro_alog_wait_notify(Log, T) ->
Term = term_to_binary(T),
@@ -459,23 +429,22 @@ halt_ro_alog_wait_notify(Log, T) ->
failed
end.
-halt_ro_balog(suite) -> [];
-halt_ro_balog(doc) -> ["Test truncation of halt disk log, read only"];
+%% Test truncation of halt disk log, read only.
halt_ro_balog(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
- {format,internal}, {file, File}]),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
+ {format,internal}, {file, File}]),
simple_log(a),
- ?line ok = disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
- {notify,true}, {format,external},
- {file, File}, {mode,read_only}]),
+ ok = disk_log:close(a),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
+ {notify,true}, {format,external},
+ {file, File}, {mode,read_only}]),
T1 = "not allowed to write",
- ?line ok = disk_log:balog(a, T1),
- ?line ok = halt_ro_balog_wait_notify(a, T1),
- ?line ok = disk_log:close(a),
- ?line ok = file:delete(File).
+ ok = disk_log:balog(a, T1),
+ ok = halt_ro_balog_wait_notify(a, T1),
+ ok = disk_log:close(a),
+ ok = file:delete(File).
halt_ro_balog_wait_notify(Log, T) ->
Term = list_to_binary(T),
@@ -488,127 +457,123 @@ halt_ro_balog_wait_notify(Log, T) ->
failed
end.
-halt_ro_crash(suite) -> [];
-halt_ro_crash(doc) -> ["Test truncation of halt disk log, read only, repair"];
+%% Test truncation of halt disk log, read only, repair.
halt_ro_crash(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line file:delete(File),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
- {format,internal},{file, File}]),
+ file:delete(File),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
+ {format,internal},{file, File}]),
simple_log(a),
- ?line ok = disk_log:close(a),
+ ok = disk_log:close(a),
crash(File, 10),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
- {notify,true}, {format,internal},
- {file, File}, {mode,read_only}]),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
+ {notify,true}, {format,internal},
+ {file, File}, {mode,read_only}]),
- ?line Error1 = {error, {read_only_mode, a}} = disk_log:truncate(a),
- ?line "The disk log" ++ _ = format_error(Error1),
+ Error1 = {error, {read_only_mode, a}} = disk_log:truncate(a),
+ "The disk log" ++ _ = format_error(Error1),
%% crash/1 sets the length of the first item to something big (2.5 kb).
%% In R6B, binary_to_term accepts garbage at the end of the binary,
%% which means that the first item is recognized!
%% This is how it was before R6B:
- %% ?line {C1,T1,15} = disk_log:chunk(a,start),
- %% ?line {C2,T2} = disk_log:chunk(a,C1),
+ %% {C1,T1,15} = disk_log:chunk(a,start),
+ %% {C2,T2} = disk_log:chunk(a,C1),
{C1,_OneItem,7478} = disk_log:chunk(a,start),
{C2, [], 7} = disk_log:chunk(a,C1),
- ?line eof = disk_log:chunk(a,C2),
- ?line ok = disk_log:close(a),
- ?line ok = file:delete(File).
+ eof = disk_log:chunk(a,C2),
+ ok = disk_log:close(a),
+ ok = file:delete(File).
-wrap_int_1(suite) -> [];
-wrap_int_1(doc) -> ["Test wrap disk log, internal"];
+%% Test wrap disk log, internal.
wrap_int_1(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}},
- {format,internal},
- {file, File}]),
- ?line [_] =
+ {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}},
+ {format,internal},
+ {file, File}]),
+ [_] =
lists:filter(fun(P) -> disk_log:pid2name(P) =/= undefined end,
erlang:processes()),
simple_log(a),
- ?line ok = disk_log:close(a),
+ ok = disk_log:close(a),
del(File, 4),
- ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}},
- {format,internal},
- {file, File}]),
- ?line [] = get_all_terms(a),
+ {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}},
+ {format,internal},
+ {file, File}]),
+ [] = get_all_terms(a),
T1 = mk_bytes(10000), % file 2
T2 = mk_bytes(5000), % file 3
T3 = mk_bytes(4000), % file 4
T4 = mk_bytes(2000), % file 4
T5 = mk_bytes(5000), % file 1
T6 = mk_bytes(5000), % file 2
- ?line ok = disk_log:log(a, T1),
- ?line ok = disk_log:log(a, T2),
- ?line ok = disk_log:log(a, T3),
- ?line ok = disk_log:log_terms(a, [T4, T5, T6]),
- ?line case get_all_terms(a) of
- [T2,T3,T4,T5,T6] ->
- ok;
- E1 ->
- test_server_fail({bad_terms, E1, [T2,T3,T4,T5,T6]})
- end,
- ?line ok = disk_log:close(a),
+ ok = disk_log:log(a, T1),
+ ok = disk_log:log(a, T2),
+ ok = disk_log:log(a, T3),
+ ok = disk_log:log_terms(a, [T4, T5, T6]),
+ case get_all_terms(a) of
+ [T2,T3,T4,T5,T6] ->
+ ok;
+ E1 ->
+ test_server_fail({bad_terms, E1, [T2,T3,T4,T5,T6]})
+ end,
+ ok = disk_log:close(a),
del(File, 4).
-wrap_int_2(suite) -> [];
-wrap_int_2(doc) -> ["Test wrap disk log, internal"];
+%% Test wrap disk log, internal.
wrap_int_2(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File1 = filename:join(Dir, "a.LOG"),
File2 = filename:join(Dir, "b.LOG"),
File3 = filename:join(Dir, "c.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8191,3}},
- {format,internal},
- {file, File1}]),
- ?line {ok, b} = disk_log:open([{name,b}, {type,wrap}, {size,{8192,3}},
- {format,internal},
- {file, File2}]),
- ?line {ok, c} = disk_log:open([{name,c}, {type,wrap}, {size,{8193,3}},
- {format,internal},
- {file, File3}]),
+ {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8191,3}},
+ {format,internal},
+ {file, File1}]),
+ {ok, b} = disk_log:open([{name,b}, {type,wrap}, {size,{8192,3}},
+ {format,internal},
+ {file, File2}]),
+ {ok, c} = disk_log:open([{name,c}, {type,wrap}, {size,{8193,3}},
+ {format,internal},
+ {file, File3}]),
T1 = mk_bytes(8191-16), % 16 is size of header + magics for 1 item
T2 = mk_bytes(8192-16),
T3 = mk_bytes(8193-16),
- ?line ok = disk_log:log(a, T1),
- ?line ok = disk_log:log(b, T2),
- ?line ok = disk_log:log(c, T3),
- ?line case get_all_terms(a) of
- [T1] ->
- ok;
- E1 ->
- test_server_fail({bad_terms, E1, [T1]})
- end,
- ?line case get_all_terms(b) of
- [T2] ->
- ok;
- E2 ->
- test_server_fail({bad_terms, E2, [T2]})
- end,
- ?line case get_all_terms(c) of
- [T3] ->
- ok;
- E3 ->
- test_server_fail({bad_terms, E3, [T3]})
- end,
- ?line ok = disk_log:close(a),
- ?line ok = disk_log:close(b),
- ?line ok = disk_log:close(c),
+ ok = disk_log:log(a, T1),
+ ok = disk_log:log(b, T2),
+ ok = disk_log:log(c, T3),
+ case get_all_terms(a) of
+ [T1] ->
+ ok;
+ E1 ->
+ test_server_fail({bad_terms, E1, [T1]})
+ end,
+ case get_all_terms(b) of
+ [T2] ->
+ ok;
+ E2 ->
+ test_server_fail({bad_terms, E2, [T2]})
+ end,
+ case get_all_terms(c) of
+ [T3] ->
+ ok;
+ E3 ->
+ test_server_fail({bad_terms, E3, [T3]})
+ end,
+ ok = disk_log:close(a),
+ ok = disk_log:close(b),
+ ok = disk_log:close(c),
del(File1, 3),
del(File2, 3),
del(File3, 3).
-inc_wrap_file(suite) -> [];
-inc_wrap_file(doc) -> ["Test disk log, force a change to next file"];
+%% Test disk log, force a change to next file.
inc_wrap_file(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File1 = filename:join(Dir, "a.LOG"),
@@ -616,262 +581,257 @@ inc_wrap_file(Conf) when is_list(Conf) ->
File3 = filename:join(Dir, "c.LOG"),
%% Test that halt logs gets an error message
- ?line {ok, a} = disk_log:open([{name, a}, {type, halt},
- {format, internal},
- {file, File1}]),
- ?line ok = disk_log:log(a, "message one"),
- ?line {error, {halt_log, a}} = disk_log:inc_wrap_file(a),
+ {ok, a} = disk_log:open([{name, a}, {type, halt},
+ {format, internal},
+ {file, File1}]),
+ ok = disk_log:log(a, "message one"),
+ {error, {halt_log, a}} = disk_log:inc_wrap_file(a),
%% test an internally formatted wrap log file
- ?line {ok, b} = disk_log:open([{name, b}, {type, wrap}, {size, {100,3}},
- {format, internal}, {head, 'thisisahead'},
- {file, File2}]),
- ?line ok = disk_log:log(b, "message one"),
- ?line ok = disk_log:inc_wrap_file(b),
- ?line ok = disk_log:log(b, "message two"),
- ?line ok = disk_log:inc_wrap_file(b),
- ?line ok = disk_log:log(b, "message three"),
- ?line ok = disk_log:inc_wrap_file(b),
- ?line ok = disk_log:log(b, "message four"),
- ?line T1 = get_all_terms(b),
- ?line ['thisisahead', "message two",
- 'thisisahead', "message three",
- 'thisisahead', "message four"] = T1,
+ {ok, b} = disk_log:open([{name, b}, {type, wrap}, {size, {100,3}},
+ {format, internal}, {head, 'thisisahead'},
+ {file, File2}]),
+ ok = disk_log:log(b, "message one"),
+ ok = disk_log:inc_wrap_file(b),
+ ok = disk_log:log(b, "message two"),
+ ok = disk_log:inc_wrap_file(b),
+ ok = disk_log:log(b, "message three"),
+ ok = disk_log:inc_wrap_file(b),
+ ok = disk_log:log(b, "message four"),
+ T1 = get_all_terms(b),
+ ['thisisahead', "message two",
+ 'thisisahead', "message three",
+ 'thisisahead', "message four"] = T1,
%% test an externally formatted wrap log file
- ?line {ok, c} = disk_log:open([{name, c}, {type, wrap}, {size, {100,3}},
- {format,external}, {head,"this is a head "},
- {file, File3}]),
- ?line ok = disk_log:blog(c, "message one"),
- ?line ok = disk_log:inc_wrap_file(c),
- ?line ok = disk_log:blog(c, "message two"),
- ?line ok = disk_log:inc_wrap_file(c),
- ?line ok = disk_log:blog(c, "message three"),
- ?line ok = disk_log:inc_wrap_file(c),
- ?line ok = disk_log:blog(c, "message four"),
- ?line ok = disk_log:sync(c),
- ?line {ok, Fd31} = file:open(File3 ++ ".1", [read]),
- ?line {ok,"this is a head message four"} = file:read(Fd31, 200),
- ?line {ok, Fd32} = file:open(File3 ++ ".2", [read]),
- ?line {ok,"this is a head message two"} = file:read(Fd32, 200),
- ?line {ok, Fd33} = file:open(File3 ++ ".3", [read]),
- ?line {ok,"this is a head message three"} = file:read(Fd33, 200),
- ?line ok = file:close(Fd31),
- ?line ok = file:close(Fd32),
- ?line ok = file:close(Fd33),
-
- ?line ok = disk_log:close(a),
- ?line ok = disk_log:close(b),
- ?line ok = disk_log:close(c),
- ?line ok = file:delete(File1),
+ {ok, c} = disk_log:open([{name, c}, {type, wrap}, {size, {100,3}},
+ {format,external}, {head,"this is a head "},
+ {file, File3}]),
+ ok = disk_log:blog(c, "message one"),
+ ok = disk_log:inc_wrap_file(c),
+ ok = disk_log:blog(c, "message two"),
+ ok = disk_log:inc_wrap_file(c),
+ ok = disk_log:blog(c, "message three"),
+ ok = disk_log:inc_wrap_file(c),
+ ok = disk_log:blog(c, "message four"),
+ ok = disk_log:sync(c),
+ {ok, Fd31} = file:open(File3 ++ ".1", [read]),
+ {ok,"this is a head message four"} = file:read(Fd31, 200),
+ {ok, Fd32} = file:open(File3 ++ ".2", [read]),
+ {ok,"this is a head message two"} = file:read(Fd32, 200),
+ {ok, Fd33} = file:open(File3 ++ ".3", [read]),
+ {ok,"this is a head message three"} = file:read(Fd33, 200),
+ ok = file:close(Fd31),
+ ok = file:close(Fd32),
+ ok = file:close(Fd33),
+
+ ok = disk_log:close(a),
+ ok = disk_log:close(b),
+ ok = disk_log:close(c),
+ ok = file:delete(File1),
del(File2, 3),
del(File3, 3).
-halt_ext_inf(suite) -> [];
-halt_ext_inf(doc) -> ["Test halt disk log, external, infinity"];
+%% Test halt disk log, external, infinity.
halt_ext_inf(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
- {format,external},
- {file, File}]),
- ?line xsimple_log(File, a),
- ?line ok = disk_log:close(a),
- ?line ok = file:delete(File).
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,infinity},
+ {format,external},
+ {file, File}]),
+ xsimple_log(File, a),
+ ok = disk_log:close(a),
+ ok = file:delete(File).
-halt_ext_sz_1(suite) -> [];
-halt_ext_sz_1(doc) -> ["Test halt disk log, external, size defined"];
+%% Test halt disk log, external, size defined.
halt_ext_sz_1(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,18000},
- {format,external},
- {file, File}]),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,18000},
+ {format,external},
+ {file, File}]),
xsimple_log(File, a),
- ?line ok = disk_log:truncate(a),
- ?line [] = get_list(File, a),
+ ok = disk_log:truncate(a),
+ [] = get_list(File, a),
{B1, T1} = x_mk_bytes(10000),
{B2, T2} = x_mk_bytes(5000),
{B3, T3} = x_mk_bytes(1000),
- ?line ok = disk_log:blog(a, B1),
- ?line case get_list(File, a) of
- T1 ->
- ok;
- E1 ->
- test_server_fail({bad_terms, E1, T1})
- end,
- ?line ok = disk_log:blog(a, B2),
- ?line {error, {full, a}} = disk_log:blog_terms(a, [B3,B3,B1]),
- ?line ok = disk_log:balog(a, B1),
- ?line Tmp = T1 ++ T2 ++ T3 ++ T3,
- ?line case get_list(File, a) of
- Tmp ->
- ok;
- E2 ->
- test_server_fail({bad_terms, E2, Tmp})
- end,
- ?line ok = disk_log:close(a),
- ?line ok = file:delete(File).
+ ok = disk_log:blog(a, B1),
+ case get_list(File, a) of
+ T1 ->
+ ok;
+ E1 ->
+ test_server_fail({bad_terms, E1, T1})
+ end,
+ ok = disk_log:blog(a, B2),
+ {error, {full, a}} = disk_log:blog_terms(a, [B3,B3,B1]),
+ ok = disk_log:balog(a, B1),
+ Tmp = T1 ++ T2 ++ T3 ++ T3,
+ case get_list(File, a) of
+ Tmp ->
+ ok;
+ E2 ->
+ test_server_fail({bad_terms, E2, Tmp})
+ end,
+ ok = disk_log:close(a),
+ ok = file:delete(File).
-halt_ext_sz_2(suite) -> [];
-halt_ext_sz_2(doc) -> ["Test halt disk log, external, size defined"];
+%% Test halt disk log, external, size defined.
halt_ext_sz_2(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File1 = filename:join(Dir, "a.LOG"),
File2 = filename:join(Dir, "b.LOG"),
File3 = filename:join(Dir, "c.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,8191},
- {format,external},
- {file, File1}]),
- ?line {ok, b} = disk_log:open([{name,b}, {type,halt}, {size,8192},
- {format,external},
- {file, File2}]),
- ?line {ok, c} = disk_log:open([{name,c}, {type,halt}, {size,8193},
- {format,external},
- {file, File3}]),
+ {ok, a} = disk_log:open([{name,a}, {type,halt}, {size,8191},
+ {format,external},
+ {file, File1}]),
+ {ok, b} = disk_log:open([{name,b}, {type,halt}, {size,8192},
+ {format,external},
+ {file, File2}]),
+ {ok, c} = disk_log:open([{name,c}, {type,halt}, {size,8193},
+ {format,external},
+ {file, File3}]),
{B1, T1} = x_mk_bytes(8191),
{B2, T2} = x_mk_bytes(8192),
{B3, T3} = x_mk_bytes(8193),
- ?line ok = disk_log:blog(a, B1),
- ?line ok = disk_log:blog(b, B2),
- ?line ok = disk_log:blog(c, B3),
- ?line case get_list(File1, a) of
- T1 ->
- ok;
- E1 ->
- test_server_fail({bad_terms, E1, T1})
- end,
- ?line case get_list(File2, b) of
- T2 ->
- ok;
- E2 ->
- test_server_fail({bad_terms, E2, T2})
- end,
- ?line case get_list(File3, c) of
- T3 ->
- ok;
- E3 ->
- test_server_fail({bad_terms, E3, T3})
- end,
- ?line ok = disk_log:truncate(a),
- ?line ok = disk_log:truncate(b),
- ?line {error, {full, a}} = disk_log:blog(a, B2),
- ?line Error1 = {error, {full, b}} = disk_log:blog(b, B3),
- ?line "The halt log" ++ _ = format_error(Error1),
- ?line true = info(b, full, false),
- ?line [] = get_list(File1, a),
- ?line [] = get_list(File2, b),
- ?line ok = disk_log:close(a),
- ?line ok = disk_log:close(b),
- ?line ok = disk_log:close(c),
- ?line ok = file:delete(File1),
- ?line ok = file:delete(File2),
- ?line ok = file:delete(File3),
+ ok = disk_log:blog(a, B1),
+ ok = disk_log:blog(b, B2),
+ ok = disk_log:blog(c, B3),
+ case get_list(File1, a) of
+ T1 ->
+ ok;
+ E1 ->
+ test_server_fail({bad_terms, E1, T1})
+ end,
+ case get_list(File2, b) of
+ T2 ->
+ ok;
+ E2 ->
+ test_server_fail({bad_terms, E2, T2})
+ end,
+ case get_list(File3, c) of
+ T3 ->
+ ok;
+ E3 ->
+ test_server_fail({bad_terms, E3, T3})
+ end,
+ ok = disk_log:truncate(a),
+ ok = disk_log:truncate(b),
+ {error, {full, a}} = disk_log:blog(a, B2),
+ Error1 = {error, {full, b}} = disk_log:blog(b, B3),
+ "The halt log" ++ _ = format_error(Error1),
+ true = info(b, full, false),
+ [] = get_list(File1, a),
+ [] = get_list(File2, b),
+ ok = disk_log:close(a),
+ ok = disk_log:close(b),
+ ok = disk_log:close(c),
+ ok = file:delete(File1),
+ ok = file:delete(File2),
+ ok = file:delete(File3),
ok.
-wrap_ext_1(suite) -> [];
-wrap_ext_1(doc) -> ["Test wrap disk log, external, size defined"];
+%% Test wrap disk log, external, size defined.
wrap_ext_1(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}},
- {format,external},
- {file, File}]),
+ {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}},
+ {format,external},
+ {file, File}]),
x2simple_log(File ++ ".1", a),
- ?line ok = disk_log:close(a),
-% del(File, 4),
- ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}},
- {format,external},
- {file, File}]),
+ ok = disk_log:close(a),
+ %% del(File, 4),
+ {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8000, 4}},
+ {format,external},
+ {file, File}]),
{B1, _T1} = x_mk_bytes(10000), % file 2
{B2, T2} = x_mk_bytes(5000), % file 3
{B3, T3} = x_mk_bytes(4000), % file 4
{B4, T4} = x_mk_bytes(2000), % file 4
{B5, T5} = x_mk_bytes(5000), % file 1
{B6, T6} = x_mk_bytes(5000), % file 2
- ?line ok = disk_log:blog(a, B1),
- ?line ok = disk_log:blog(a, B2),
- ?line ok = disk_log:blog(a, B3),
- ?line ok = disk_log:blog_terms(a, [B4, B5, B6]),
- ?line case get_list(File ++ ".3", a) of
- T2 ->
- ok;
- E2 ->
- test_server_fail({bad_terms, E2, T2})
- end,
- ?line T34 = T3 ++ T4,
- ?line case get_list(File ++ ".4", a) of
- T34 ->
- ok;
- E34 ->
- test_server_fail({bad_terms, E34, T34})
- end,
- ?line case get_list(File ++ ".1", a) of
- T5 ->
- ok;
- E5 ->
- test_server_fail({bad_terms, E5, T5})
- end,
- ?line case get_list(File ++ ".2", a) of
- T6 ->
- ok;
- E6 ->
- test_server_fail({bad_terms, E6, T6})
- end,
- ?line ok = disk_log:close(a),
+ ok = disk_log:blog(a, B1),
+ ok = disk_log:blog(a, B2),
+ ok = disk_log:blog(a, B3),
+ ok = disk_log:blog_terms(a, [B4, B5, B6]),
+ case get_list(File ++ ".3", a) of
+ T2 ->
+ ok;
+ E2 ->
+ test_server_fail({bad_terms, E2, T2})
+ end,
+ T34 = T3 ++ T4,
+ case get_list(File ++ ".4", a) of
+ T34 ->
+ ok;
+ E34 ->
+ test_server_fail({bad_terms, E34, T34})
+ end,
+ case get_list(File ++ ".1", a) of
+ T5 ->
+ ok;
+ E5 ->
+ test_server_fail({bad_terms, E5, T5})
+ end,
+ case get_list(File ++ ".2", a) of
+ T6 ->
+ ok;
+ E6 ->
+ test_server_fail({bad_terms, E6, T6})
+ end,
+ ok = disk_log:close(a),
del(File, 4).
-wrap_ext_2(suite) -> [];
-wrap_ext_2(doc) -> ["Test wrap disk log, external, size defined"];
+%% Test wrap disk log, external, size defined.
wrap_ext_2(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File1 = filename:join(Dir, "a.LOG"),
File2 = filename:join(Dir, "b.LOG"),
File3 = filename:join(Dir, "c.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8191,3}},
- {format,external},
- {file, File1}]),
- ?line {ok, b} = disk_log:open([{name,b}, {type,wrap}, {size,{8192,3}},
- {format,external},
- {file, File2}]),
- ?line {ok, c} = disk_log:open([{name,c}, {type,wrap}, {size,{8193,3}},
- {format,external},
- {file, File3}]),
+ {ok, a} = disk_log:open([{name,a}, {type,wrap}, {size,{8191,3}},
+ {format,external},
+ {file, File1}]),
+ {ok, b} = disk_log:open([{name,b}, {type,wrap}, {size,{8192,3}},
+ {format,external},
+ {file, File2}]),
+ {ok, c} = disk_log:open([{name,c}, {type,wrap}, {size,{8193,3}},
+ {format,external},
+ {file, File3}]),
{B1, T1} = x_mk_bytes(8191),
{B2, T2} = x_mk_bytes(8192),
{B3, T3} = x_mk_bytes(8193),
- ?line ok = disk_log:blog(a, B1),
- ?line ok = disk_log:blog(b, B2),
- ?line ok = disk_log:blog(c, B3),
- ?line case get_list(File1 ++ ".1", a) of
- T1 ->
- ok;
- E1 ->
- test_server_fail({bad_terms, E1, T1})
- end,
- ?line case get_list(File2 ++ ".1", b) of
- T2 ->
- ok;
- E2 ->
- test_server_fail({bad_terms, E2, T2})
- end,
- ?line case get_list(File3 ++ ".1", c) of
- T3 ->
- ok;
- E3 ->
- test_server_fail({bad_terms, E3, T3})
- end,
- ?line ok = disk_log:close(a),
- ?line ok = disk_log:close(b),
- ?line ok = disk_log:close(c),
- ?line del(File1, 3),
- ?line del(File2, 3),
- ?line del(File3, 3),
+ ok = disk_log:blog(a, B1),
+ ok = disk_log:blog(b, B2),
+ ok = disk_log:blog(c, B3),
+ case get_list(File1 ++ ".1", a) of
+ T1 ->
+ ok;
+ E1 ->
+ test_server_fail({bad_terms, E1, T1})
+ end,
+ case get_list(File2 ++ ".1", b) of
+ T2 ->
+ ok;
+ E2 ->
+ test_server_fail({bad_terms, E2, T2})
+ end,
+ case get_list(File3 ++ ".1", c) of
+ T3 ->
+ ok;
+ E3 ->
+ test_server_fail({bad_terms, E3, T3})
+ end,
+ ok = disk_log:close(a),
+ ok = disk_log:close(b),
+ ok = disk_log:close(c),
+ del(File1, 3),
+ del(File2, 3),
+ del(File3, 3),
ok.
simple_log(Log) ->
@@ -879,61 +839,61 @@ simple_log(Log) ->
T2 = hopp,
T3 = {tjena, 12},
T4 = mk_bytes(10000),
- ?line ok = disk_log:log(Log, T1),
- ?line ok = disk_log:log_terms(Log, [T2, T3]),
- ?line case get_all_terms(Log) of
- [T1, T2, T3] ->
- ok;
- E1 ->
- test_server_fail({bad_terms, E1, [T1, T2, T3]})
- end,
- ?line ok = disk_log:log(a, T4),
- ?line case get_all_terms(Log) of
- [T1, T2, T3, T4] ->
- ok;
- E2 ->
- test_server_fail({bad_terms, E2, [T1, T2, T3, T4]})
- end.
+ ok = disk_log:log(Log, T1),
+ ok = disk_log:log_terms(Log, [T2, T3]),
+ case get_all_terms(Log) of
+ [T1, T2, T3] ->
+ ok;
+ E1 ->
+ test_server_fail({bad_terms, E1, [T1, T2, T3]})
+ end,
+ ok = disk_log:log(a, T4),
+ case get_all_terms(Log) of
+ [T1, T2, T3, T4] ->
+ ok;
+ E2 ->
+ test_server_fail({bad_terms, E2, [T1, T2, T3, T4]})
+ end.
xsimple_log(File, Log) ->
T1 = "hej",
T2 = list_to_binary("hopp"),
T3 = list_to_binary(["sena", list_to_binary("sejer")]),
T4 = list_to_binary(By = mk_bytes(10000)),
- ?line ok = disk_log:blog(Log, T1),
- ?line ok = disk_log:blog_terms(Log, [T2, T3]),
- ?line X = "hejhoppsenasejer",
- ?line X2 = get_list(File, Log),
- ?line case X2 of
- X -> ok;
- Z1 -> test_server_fail({bad_terms, Z1, X2})
- end,
- ?line ok = disk_log:blog(Log, T4),
- ?line Tmp = get_list(File, Log),
- ?line case X ++ By of
- Tmp -> ok;
- Z2 -> test_server_fail({bad_terms, Z2, X ++ By})
- end.
+ ok = disk_log:blog(Log, T1),
+ ok = disk_log:blog_terms(Log, [T2, T3]),
+ X = "hejhoppsenasejer",
+ X2 = get_list(File, Log),
+ case X2 of
+ X -> ok;
+ Z1 -> test_server_fail({bad_terms, Z1, X2})
+ end,
+ ok = disk_log:blog(Log, T4),
+ Tmp = get_list(File, Log),
+ case X ++ By of
+ Tmp -> ok;
+ Z2 -> test_server_fail({bad_terms, Z2, X ++ By})
+ end.
x2simple_log(File, Log) ->
T1 = "hej",
T2 = list_to_binary("hopp"),
T3 = list_to_binary(["sena", list_to_binary("sejer")]),
T4 = list_to_binary(By = mk_bytes(1000)),
- ?line ok = disk_log:blog(Log, T1),
- ?line ok = disk_log:blog_terms(Log, [T2, T3]),
- ?line X = "hejhoppsenasejer",
- ?line X2 = get_list(File, Log),
- ?line case X2 of
- X -> ok;
- Z1 -> test_server_fail({bad_terms, Z1, X2})
- end,
- ?line ok = disk_log:blog(Log, T4),
- ?line Tmp = get_list(File, Log),
- ?line case X ++ By of
- Tmp -> ok;
- Z2 -> test_server_fail({bad_terms, Z2, X ++ By})
- end.
+ ok = disk_log:blog(Log, T1),
+ ok = disk_log:blog_terms(Log, [T2, T3]),
+ X = "hejhoppsenasejer",
+ X2 = get_list(File, Log),
+ case X2 of
+ X -> ok;
+ Z1 -> test_server_fail({bad_terms, Z1, X2})
+ end,
+ ok = disk_log:blog(Log, T4),
+ Tmp = get_list(File, Log),
+ case X ++ By of
+ Tmp -> ok;
+ Z2 -> test_server_fail({bad_terms, Z2, X ++ By})
+ end.
x_mk_bytes(N) ->
X = lists:duplicate(N, $a),
@@ -947,7 +907,7 @@ mk_bytes(N) when N > 4 ->
end.
get_list(File, Log) ->
- ?t:format(0, "File ~p~n",[File]),
+ ct:pal(?HI_VERBOSITY, "File ~p~n", [File]),
ok = disk_log:sync(Log),
{ok, B} = file:read_file(File),
binary_to_list(B).
@@ -955,7 +915,7 @@ get_list(File, Log) ->
get_all_terms(Log, File, Type) ->
{ok, _Log} = disk_log:open([{name,Log}, {type,Type}, {size,infinity},
- {format,internal}, {file, File},
+ {format,internal}, {file, File},
{mode, read_only}]),
Ts = get_all_terms(Log),
ok = disk_log:close(Log),
@@ -976,14 +936,14 @@ get_all_terms1(Log, Cont, Res) ->
get_all_terms_and_bad(Log, File, Type) ->
{ok, _Log} = disk_log:open([{name,Log}, {type,Type}, {size,infinity},
- {format,internal}, {file, File},
+ {format,internal}, {file, File},
{mode, read_only}]),
Ts = get_all_terms_and_bad(Log),
ok = disk_log:close(Log),
Ts.
get_all_terms_and_bad(Log) ->
- ?line read_only = info(Log, mode, foo),
+ read_only = info(Log, mode, foo),
get_all_terms_and_bad1(Log, start, [], 0).
%%
@@ -999,7 +959,7 @@ get_all_terms_and_bad1(Log, Cont, Res, Bad0) ->
get_all_binary_terms_and_bad(Log, File, Type) ->
{ok, _Log} = disk_log:open([{name,Log}, {type,Type}, {size,infinity},
- {format,internal}, {file, File},
+ {format,internal}, {file, File},
{mode, read_only}]),
Ts = get_all_binary_terms_and_bad(Log),
ok = disk_log:close(Log),
@@ -1037,7 +997,7 @@ xx() ->
{format,internal}, {file, File}]),
W = xwr(a, 400),
disk_log:close(a),
-% file:delete(File),
+ %% file:delete(File),
W.
%% old: 6150
@@ -1186,73 +1146,72 @@ end_times({T1,W1}) ->
{T2-T1, W2-W1}.
-head_func(suite) -> [];
-head_func(doc) -> ["Test head parameter"];
+%% Test head parameter.
head_func(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
ets:new(xxx, [named_table, set, public]),
ets:insert(xxx, {wrapc, 0}),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
- {size, {100,4}},
- {head_func, {?MODULE, hf, []}}]),
- ?line B = mk_bytes(60),
- ?line disk_log:log(a, B),
- ?line disk_log:alog(a, B),
- ?line disk_log:alog(a, B),
- ?line disk_log:log(a, B),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
+ {size, {100,4}},
+ {head_func, {?MODULE, hf, []}}]),
+ B = mk_bytes(60),
+ disk_log:log(a, B),
+ disk_log:alog(a, B),
+ disk_log:alog(a, B),
+ disk_log:log(a, B),
H = [1,2,3],
- ?line [{wrapc, 4}] = ets:lookup(xxx, wrapc),
+ [{wrapc, 4}] = ets:lookup(xxx, wrapc),
ets:delete(xxx),
- ?line case get_all_terms(a) of
- [H,B,H,B,H,B,H,B] ->
- ok;
- E1 ->
- test_server_fail({bad_terms, E1,
- [H,B,H,B,H,B,H,B]})
- end,
- ?line 8 = no_written_items(a),
+ case get_all_terms(a) of
+ [H,B,H,B,H,B,H,B] ->
+ ok;
+ E1 ->
+ test_server_fail({bad_terms, E1,
+ [H,B,H,B,H,B,H,B]})
+ end,
+ 8 = no_written_items(a),
disk_log:close(a),
del(File, 4),
- % invalid header function
- ?line {error, {invalid_header, {_, {term}}}} =
+ %% invalid header function
+ {error, {invalid_header, {_, {term}}}} =
disk_log:open([{name, n}, {file, File}, {type, halt},
{format, external},
{head_func, {?MODULE, head_fun, [{term}]}}]),
file:delete(File),
- ?line {error, {invalid_header, _}} =
+ {error, {invalid_header, _}} =
disk_log:open([{name, n}, {file, File}, {type, halt},
{format, external},
{head_func, {?MODULE, head_fun, [{ok,{term}}]}}]),
file:delete(File),
- ?line {ok,n} =
+ {ok,n} =
disk_log:open([{name, n}, {file, File}, {type, halt},
{format, external},
{head_func, {?MODULE, head_fun, [{ok,<<"head">>}]}}]),
- ?line ok = disk_log:close(n),
- ?line {ok,<<"head">>} = file:read_file(File),
+ ok = disk_log:close(n),
+ {ok,<<"head">>} = file:read_file(File),
file:delete(File),
- ?line {ok,n} =
+ {ok,n} =
disk_log:open([{name, n}, {file, File}, {type, halt},
{format, external},
{head_func, {?MODULE, head_fun, [{ok,"head"}]}}]),
- ?line ok = disk_log:close(n),
- ?line {ok,<<"head">>} = file:read_file(File),
+ ok = disk_log:close(n),
+ {ok,<<"head">>} = file:read_file(File),
file:delete(File),
- ?line Error1 = {error, {badarg, _}} =
+ Error1 = {error, {badarg, _}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{head_func, {tjo,hej,san}},{size, {100, 4}}]),
- ?line "The argument " ++ _ = format_error(Error1),
-
- ?line Error2 = {error, {invalid_header, _}} =
+ "The argument " ++ _ = format_error(Error1),
+
+ Error2 = {error, {invalid_header, _}} =
disk_log:open([{name, n}, {file, File}, {type, halt},
{head_func, {tjo,hej,[san]}}]),
- ?line "The disk log header" ++ _ = format_error(Error2),
+ "The disk log header" ++ _ = format_error(Error2),
file:delete(File).
@@ -1263,194 +1222,186 @@ hf() ->
ets:update_counter(xxx, wrapc, 1),
{ok, [1,2,3]}.
-plain_head(suite) -> [];
-plain_head(doc) -> ["Test head parameter"];
+%% Test head parameter.
plain_head(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
H = [1,2,3],
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
- {size, {100,4}}, {head, H}]),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
+ {size, {100,4}}, {head, H}]),
%% This one is not "counted".
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
- {size, {100,4}}, {head, H}]),
- ?line B = mk_bytes(60),
- ?line disk_log:log(a, B),
- ?line disk_log:alog(a, B),
- ?line disk_log:alog(a, B),
- ?line disk_log:log(a, B),
- ?line case get_all_terms(a) of
- [H,B,H,B,H,B,H,B] ->
- ok;
- E1 ->
- test_server_fail({bad_terms, E1,
- [H,B,H,B,H,B,H,B]})
- end,
- ?line 8 = no_written_items(a),
- ?line ok = disk_log:close(a),
- ?line {error, no_such_log} = disk_log:close(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
+ {size, {100,4}}, {head, H}]),
+ B = mk_bytes(60),
+ disk_log:log(a, B),
+ disk_log:alog(a, B),
+ disk_log:alog(a, B),
+ disk_log:log(a, B),
+ case get_all_terms(a) of
+ [H,B,H,B,H,B,H,B] ->
+ ok;
+ E1 ->
+ test_server_fail({bad_terms, E1,
+ [H,B,H,B,H,B,H,B]})
+ end,
+ 8 = no_written_items(a),
+ ok = disk_log:close(a),
+ {error, no_such_log} = disk_log:close(a),
del(File, 4).
-one_header(suite) -> [];
-one_header(doc) -> ["Test that a header is just printed once in a log file"];
+%% Test that a header is just printed once in a log file.
one_header(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
H = [1,2,3],
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
- {size, {100,4}}, {head, H}]),
- ?line B = mk_bytes(60),
- ?line ok = disk_log:log(a, B),
- ?line ok = disk_log:alog(a, B),
- ?line ok = disk_log:alog(a, B),
- ?line ok = disk_log:log(a, B),
- ?line case get_all_terms(a) of
- [H,B,H,B,H,B,H,B] ->
- ok;
- E1 ->
- test_server_fail({bad_terms, E1,
- [H,B,H,B,H,B,H,B]})
- end,
- ?line 8 = no_written_items(a),
- ?line ok = disk_log:close(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
+ {size, {100,4}}, {head, H}]),
+ B = mk_bytes(60),
+ ok = disk_log:log(a, B),
+ ok = disk_log:alog(a, B),
+ ok = disk_log:alog(a, B),
+ ok = disk_log:log(a, B),
+ case get_all_terms(a) of
+ [H,B,H,B,H,B,H,B] ->
+ ok;
+ E1 ->
+ test_server_fail({bad_terms, E1,
+ [H,B,H,B,H,B,H,B]})
+ end,
+ 8 = no_written_items(a),
+ ok = disk_log:close(a),
del(File, 4),
Fileb = filename:join(Dir, "b.LOG"),
- ?line {ok, b} = disk_log:open([{name,b}, {file, Fileb}, {head, H}]),
- ?line ok = disk_log:close(b),
- ?line {ok, b} = disk_log:open([{name,b}, {file, Fileb}, {head, H}]),
- ?line ok = disk_log:log(b, "first log"),
- ?line ok = disk_log:alog(b, "second log"),
- ?line ok = disk_log:close(b),
- ?line {ok, b} = disk_log:open([{name,b}, {file, Fileb}, {head, H}]),
- ?line ok = disk_log:alog(b, "3rd log"),
- ?line ok = disk_log:log(b, "4th log"),
- ?line case get_all_terms(b) of
- [H, "first log", "second log", "3rd log", "4th log"] ->
- ok;
- E2 ->
- test_server_fail({bad_terms, E2,
- [H, "first log", "second log",
- "3rd log", "4th log"]})
- end,
- ?line 2 = no_written_items(b),
- ?line ok = disk_log:close(b),
- ?line ok = file:delete(Fileb),
+ {ok, b} = disk_log:open([{name,b}, {file, Fileb}, {head, H}]),
+ ok = disk_log:close(b),
+ {ok, b} = disk_log:open([{name,b}, {file, Fileb}, {head, H}]),
+ ok = disk_log:log(b, "first log"),
+ ok = disk_log:alog(b, "second log"),
+ ok = disk_log:close(b),
+ {ok, b} = disk_log:open([{name,b}, {file, Fileb}, {head, H}]),
+ ok = disk_log:alog(b, "3rd log"),
+ ok = disk_log:log(b, "4th log"),
+ case get_all_terms(b) of
+ [H, "first log", "second log", "3rd log", "4th log"] ->
+ ok;
+ E2 ->
+ test_server_fail({bad_terms, E2,
+ [H, "first log", "second log",
+ "3rd log", "4th log"]})
+ end,
+ 2 = no_written_items(b),
+ ok = disk_log:close(b),
+ ok = file:delete(Fileb),
Filec = filename:join(Dir, "c.LOG"),
H2 = "this is a header ",
- ?line {ok, c} = disk_log:open([{name,c}, {format, external},
- {file, Filec}, {head, H2}]),
- ?line ok = disk_log:close(c),
- ?line {ok, c} = disk_log:open([{name,c}, {format, external},
- {file, Filec}, {head, H2}]),
- ?line ok = disk_log:blog(c, "first log"),
- ?line ok = disk_log:balog(c, "second log"),
- ?line ok = disk_log:close(c),
- ?line {ok, c} = disk_log:open([{name,c}, {format, external},
- {file, Filec}, {head, H2}]),
- ?line ok = disk_log:balog(c, "3rd log"),
- ?line ok = disk_log:blog(c, "4th log"),
- ?line ok = disk_log:sync(c),
- ?line {ok, Fdc} = file:open(Filec, [read]),
- ?line {ok,"this is a header first logsecond log3rd log4th log"} =
+ {ok, c} = disk_log:open([{name,c}, {format, external},
+ {file, Filec}, {head, H2}]),
+ ok = disk_log:close(c),
+ {ok, c} = disk_log:open([{name,c}, {format, external},
+ {file, Filec}, {head, H2}]),
+ ok = disk_log:blog(c, "first log"),
+ ok = disk_log:balog(c, "second log"),
+ ok = disk_log:close(c),
+ {ok, c} = disk_log:open([{name,c}, {format, external},
+ {file, Filec}, {head, H2}]),
+ ok = disk_log:balog(c, "3rd log"),
+ ok = disk_log:blog(c, "4th log"),
+ ok = disk_log:sync(c),
+ {ok, Fdc} = file:open(Filec, [read]),
+ {ok,"this is a header first logsecond log3rd log4th log"} =
file:read(Fdc, 200),
- ?line ok = file:close(Fdc),
- ?line 2 = no_written_items(c),
- ?line disk_log:close(c),
- ?line ok = file:delete(Filec),
+ ok = file:close(Fdc),
+ 2 = no_written_items(c),
+ disk_log:close(c),
+ ok = file:delete(Filec),
ok.
-wrap_notif(suite) -> [];
-wrap_notif(doc) -> ["Test notify parameter, wrap"];
+%% Test notify parameter, wrap.
wrap_notif(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
- {size, {100,4}}, {notify, true}]),
- ?line B = mk_bytes(60),
- ?line disk_log:log(a, B),
- ?line disk_log:alog(a, B),
- ?line disk_log:alog(a, B),
- ?line disk_log:log(a, B),
- ?line disk_log:log(a, B),
- ?line rec(3, {disk_log, node(), a, {wrap, 0}}),
- ?line rec(1, {disk_log, node(), a, {wrap, 1}}),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
+ {size, {100,4}}, {notify, true}]),
+ B = mk_bytes(60),
+ disk_log:log(a, B),
+ disk_log:alog(a, B),
+ disk_log:alog(a, B),
+ disk_log:log(a, B),
+ disk_log:log(a, B),
+ rec(3, {disk_log, node(), a, {wrap, 0}}),
+ rec(1, {disk_log, node(), a, {wrap, 1}}),
disk_log:close(a),
del(File, 4).
-full_notif(suite) -> [];
-full_notif(doc) -> ["Test notify parameter, wrap, filled file"];
+%% Test notify parameter, wrap, filled file.
full_notif(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
file:delete(File),
- ?line {ok, a} = disk_log:open([{name, a}, {file, File}, {type, halt},
- {size, 100}, {notify, true}]),
- ?line B = mk_bytes(60),
- ?line disk_log:log(a, B),
- ?line disk_log:alog(a, B),
- ?line rec(1, {disk_log, node(), a, full}),
+ {ok, a} = disk_log:open([{name, a}, {file, File}, {type, halt},
+ {size, 100}, {notify, true}]),
+ B = mk_bytes(60),
+ disk_log:log(a, B),
+ disk_log:alog(a, B),
+ rec(1, {disk_log, node(), a, full}),
disk_log:close(a),
file:delete(File).
-trunc_notif(suite) -> [];
-trunc_notif(doc) -> ["Test notify parameter, wrap, truncated file"];
+%% Test notify parameter, wrap, truncated file.
trunc_notif(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
File2 = filename:join(Dir, "a.DUMP"),
- ?line {ok, a} = disk_log:open([{name, a}, {file, File}, {type, halt},
- {size, 100}, {notify, true}]),
- ?line B = mk_bytes(60),
- ?line disk_log:log(a, B),
- ?line disk_log:truncate(a),
- ?line rec(1, {disk_log, node(), a, {truncated, 1}}),
- ?line disk_log:log(a, B),
- ?line ok = disk_log:reopen(a, File2),
- ?line rec(1, {disk_log, node(), a, {truncated, 1}}),
+ {ok, a} = disk_log:open([{name, a}, {file, File}, {type, halt},
+ {size, 100}, {notify, true}]),
+ B = mk_bytes(60),
+ disk_log:log(a, B),
+ disk_log:truncate(a),
+ rec(1, {disk_log, node(), a, {truncated, 1}}),
+ disk_log:log(a, B),
+ ok = disk_log:reopen(a, File2),
+ rec(1, {disk_log, node(), a, {truncated, 1}}),
disk_log:close(a),
file:delete(File),
file:delete(File2).
-blocked_notif(suite) -> [];
-blocked_notif(doc) ->
- ["Test notify parameters 'format_external' and 'blocked_log"];
+%% Test notify parameters 'format_external' and 'blocked_log.
blocked_notif(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "n.LOG"),
No = 4,
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {size, {100,No}}, {notify, true},
- {format, external}]),
- ?line B = mk_bytes(60),
- ?line Error1 = {error,{format_external,n}} = disk_log:log(n, B),
- ?line "The requested operation" ++ _ = format_error(Error1),
- ?line ok = disk_log:blog(n, B),
- ?line ok = disk_log:alog(n, B),
- ?line rec(1, {disk_log, node(), n, {format_external, term_to_binary(B)}}),
- ?line ok = disk_log:alog_terms(n, [B,B,B,B]),
- ?line rec(1, {disk_log, node(), n, {format_external,
- lists:map(fun term_to_binary/1, [B,B,B,B])}}),
- ?line ok = disk_log:block(n, false),
- ?line ok = disk_log:alog(n, B),
- ?line rec(1, {disk_log, node(), n, {blocked_log, term_to_binary(B)}}),
- ?line ok = disk_log:balog(n, B),
- ?line rec(1, {disk_log, node(), n, {blocked_log, list_to_binary(B)}}),
- ?line ok = disk_log:balog_terms(n, [B,B,B,B]),
- ?line disk_log:close(n),
- ?line rec(1, {disk_log, node(), n, {blocked_log,
- lists:map(fun list_to_binary/1, [B,B,B,B])}}),
- ?line del(File, No).
-
-
-new_idx_vsn(suite) -> [];
-new_idx_vsn(doc) -> ["Test the new version of the .idx file"];
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {size, {100,No}}, {notify, true},
+ {format, external}]),
+ B = mk_bytes(60),
+ Error1 = {error,{format_external,n}} = disk_log:log(n, B),
+ "The requested operation" ++ _ = format_error(Error1),
+ ok = disk_log:blog(n, B),
+ ok = disk_log:alog(n, B),
+ rec(1, {disk_log, node(), n, {format_external, term_to_binary(B)}}),
+ ok = disk_log:alog_terms(n, [B,B,B,B]),
+ rec(1, {disk_log, node(), n, {format_external,
+ lists:map(fun term_to_binary/1, [B,B,B,B])}}),
+ ok = disk_log:block(n, false),
+ ok = disk_log:alog(n, B),
+ rec(1, {disk_log, node(), n, {blocked_log, term_to_binary(B)}}),
+ ok = disk_log:balog(n, B),
+ rec(1, {disk_log, node(), n, {blocked_log, list_to_binary(B)}}),
+ ok = disk_log:balog_terms(n, [B,B,B,B]),
+ disk_log:close(n),
+ rec(1, {disk_log, node(), n, {blocked_log,
+ lists:map(fun list_to_binary/1, [B,B,B,B])}}),
+ del(File, No).
+
+
+%% Test the new version of the .idx file.
new_idx_vsn(Conf) when is_list(Conf) ->
DataDir = ?datadir(Conf),
PrivDir = ?privdir(Conf),
@@ -1459,201 +1410,197 @@ new_idx_vsn(Conf) when is_list(Conf) ->
Kurt2 = filename:join(PrivDir, "kurt2.LOG"),
%% Test that a wrap log file can have more than 255 files
- ?line {ok, new_vsn} = disk_log:open([{file, File}, {name, new_vsn},
- {type, wrap}, {size, {40, 270}}]),
- ?line ok = log(new_vsn, 280),
- ?line {ok, Bin} = file:read_file(add_ext(File, "idx")),
- ?line <<0,0:32,2,10:32,1:64,1:64,_/binary>> = Bin,
- ?line disk_log:close(new_vsn),
- ?line del(File, 270),
+ {ok, new_vsn} = disk_log:open([{file, File}, {name, new_vsn},
+ {type, wrap}, {size, {40, 270}}]),
+ ok = log(new_vsn, 280),
+ {ok, Bin} = file:read_file(add_ext(File, "idx")),
+ <<0,0:32,2,10:32,1:64,1:64,_/binary>> = Bin,
+ disk_log:close(new_vsn),
+ del(File, 270),
%% convert a very old version (0) of wrap log file to the new format (2)
copy_wrap_log("kurt.LOG", 4, DataDir, PrivDir),
- ?line {repaired, kurt, {recovered, 1}, {badbytes, 0}} =
+ {repaired, kurt, {recovered, 1}, {badbytes, 0}} =
disk_log:open([{file, Kurt}, {name, kurt},
{type, wrap}, {size, {40, 4}}]),
- ?line ok = disk_log:log(kurt, "this is a logged message number X"),
- ?line ok = disk_log:log(kurt, "this is a logged message number Y"),
- ?line {ok, BinK} = file:read_file(add_ext(Kurt, "idx")),
- ?line <<0,0:32,2,2:32,1:64,1:64,1:64,1:64>> = BinK,
- ?line {{40,4}, 2} = disk_log_1:read_size_file_version(Kurt),
+ ok = disk_log:log(kurt, "this is a logged message number X"),
+ ok = disk_log:log(kurt, "this is a logged message number Y"),
+ {ok, BinK} = file:read_file(add_ext(Kurt, "idx")),
+ <<0,0:32,2,2:32,1:64,1:64,1:64,1:64>> = BinK,
+ {{40,4}, 2} = disk_log_1:read_size_file_version(Kurt),
disk_log:close(kurt),
- ?line del(Kurt, 4),
+ del(Kurt, 4),
%% keep the old format (1)
copy_wrap_log("kurt2.LOG", 4, DataDir, PrivDir),
- ?line {repaired, kurt2, {recovered, 1}, {badbytes, 0}} =
+ {repaired, kurt2, {recovered, 1}, {badbytes, 0}} =
disk_log:open([{file, Kurt2}, {name, kurt2},
{type, wrap}, {size, {40, 4}}]),
- ?line ok = disk_log:log(kurt2, "this is a logged message number X"),
- ?line ok = disk_log:log(kurt2, "this is a logged message number Y"),
- ?line {ok, BinK2} = file:read_file(add_ext(Kurt2, "idx")),
- ?line <<0,2:32,1:32,1:32,1:32,1:32>> = BinK2,
- ?line {{40,4}, 1} = disk_log_1:read_size_file_version(Kurt2),
+ ok = disk_log:log(kurt2, "this is a logged message number X"),
+ ok = disk_log:log(kurt2, "this is a logged message number Y"),
+ {ok, BinK2} = file:read_file(add_ext(Kurt2, "idx")),
+ <<0,2:32,1:32,1:32,1:32,1:32>> = BinK2,
+ {{40,4}, 1} = disk_log_1:read_size_file_version(Kurt2),
disk_log:close(kurt2),
- ?line del(Kurt2, 4),
+ del(Kurt2, 4),
ok.
-reopen(suite) -> [];
-reopen(doc) ->
- ["Test reopen/1 on halt and wrap logs."];
+%% Test reopen/1 on halt and wrap logs.
reopen(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
- ?line File = filename:join(Dir, "n.LOG"),
- ?line NewFile = filename:join(Dir, "nn.LOG"),
- ?line B = mk_bytes(60),
-
- ?line file:delete(File), % cleanup
- ?line file:delete(NewFile), % cleanup
- ?line Q = qlen(),
+ File = filename:join(Dir, "n.LOG"),
+ NewFile = filename:join(Dir, "nn.LOG"),
+ B = mk_bytes(60),
+
+ file:delete(File), % cleanup
+ file:delete(NewFile), % cleanup
+ Q = qlen(),
%% External halt log.
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {notify, true}, {head, "header"},
- {size, infinity},{format, external}]),
- ?line ok = disk_log:blog(n, B),
- ?line ok = disk_log:breopen(n, NewFile, "head"),
- ?line rec(1, {disk_log, node(), n, {truncated, 2}}),
- ?line ok = disk_log:blog(n, B),
- ?line ok = disk_log:blog(n, B),
- ?line ok = disk_log:breopen(n, NewFile, "head"),
- ?line rec(1, {disk_log, node(), n, {truncated, 3}}),
- ?line ok = disk_log:close(n),
- ?line {ok,BinaryFile} = file:read_file(File),
- ?line "head" = binary_to_list(BinaryFile),
- ?line file:delete(File),
- ?line file:delete(NewFile),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {notify, true}, {head, "header"},
+ {size, infinity},{format, external}]),
+ ok = disk_log:blog(n, B),
+ ok = disk_log:breopen(n, NewFile, "head"),
+ rec(1, {disk_log, node(), n, {truncated, 2}}),
+ ok = disk_log:blog(n, B),
+ ok = disk_log:blog(n, B),
+ ok = disk_log:breopen(n, NewFile, "head"),
+ rec(1, {disk_log, node(), n, {truncated, 3}}),
+ ok = disk_log:close(n),
+ {ok,BinaryFile} = file:read_file(File),
+ "head" = binary_to_list(BinaryFile),
+ file:delete(File),
+ file:delete(NewFile),
%% Internal halt log.
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {notify, true}, {head, header},
- {size, infinity}]),
- ?line ok = disk_log:log(n, B),
- ?line Error1 = {error, {same_file_name, n}} = disk_log:reopen(n, File),
- ?line "Current and new" ++ _ = format_error(Error1),
- ?line ok = disk_log:reopen(n, NewFile),
- ?line rec(1, {disk_log, node(), n, {truncated, 2}}),
- ?line ok = disk_log:log(n, B),
- ?line ok = disk_log:log(n, B),
- ?line ok = disk_log:reopen(n, NewFile),
- ?line rec(1, {disk_log, node(), n, {truncated, 3}}),
- ?line ok = disk_log:close(n),
- ?line [header, _B, _B] = get_all_terms(nn, NewFile, halt),
- ?line file:delete(File),
- ?line file:delete(NewFile),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {notify, true}, {head, header},
+ {size, infinity}]),
+ ok = disk_log:log(n, B),
+ Error1 = {error, {same_file_name, n}} = disk_log:reopen(n, File),
+ "Current and new" ++ _ = format_error(Error1),
+ ok = disk_log:reopen(n, NewFile),
+ rec(1, {disk_log, node(), n, {truncated, 2}}),
+ ok = disk_log:log(n, B),
+ ok = disk_log:log(n, B),
+ ok = disk_log:reopen(n, NewFile),
+ rec(1, {disk_log, node(), n, {truncated, 3}}),
+ ok = disk_log:close(n),
+ [header, _B, _B] = get_all_terms(nn, NewFile, halt),
+ file:delete(File),
+ file:delete(NewFile),
%% Internal wrap log.
- ?line No = 4,
- ?line del(File, No), % cleanup
- ?line del(NewFile, No), % cleanup
-
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {notify, true},
- {head, header}, {size, {100, No}}]),
- ?line ok = disk_log:log(n, B),
- ?line ok = disk_log:log_terms(n, [B,B,B]),
+ No = 4,
+ del(File, No), % cleanup
+ del(NewFile, No), % cleanup
+
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {notify, true},
+ {head, header}, {size, {100, No}}]),
+ ok = disk_log:log(n, B),
+ ok = disk_log:log_terms(n, [B,B,B]),
%% Used to be one message, but now one per wrapped file.
- ?line rec(3, {disk_log, node(), n, {wrap, 0}}),
- ?line ok = disk_log:log_terms(n, [B]),
- ?line rec(1, {disk_log, node(), n, {wrap, 2}}),
- ?line ok = disk_log:log_terms(n, [B]),
- ?line rec(1, {disk_log, node(), n, {wrap, 2}}),
- ?line ok = disk_log:reopen(n, NewFile, new_header),
- ?line rec(1, {disk_log, node(), n, {truncated, 8}}),
- ?line ok = disk_log:log_terms(n, [B,B]),
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line ok = disk_log:log_terms(n, [B]),
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line ok = disk_log:close(n),
- ?line [header, _, header, _, header, _, header, _] =
+ rec(3, {disk_log, node(), n, {wrap, 0}}),
+ ok = disk_log:log_terms(n, [B]),
+ rec(1, {disk_log, node(), n, {wrap, 2}}),
+ ok = disk_log:log_terms(n, [B]),
+ rec(1, {disk_log, node(), n, {wrap, 2}}),
+ ok = disk_log:reopen(n, NewFile, new_header),
+ rec(1, {disk_log, node(), n, {truncated, 8}}),
+ ok = disk_log:log_terms(n, [B,B]),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ ok = disk_log:log_terms(n, [B]),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ ok = disk_log:close(n),
+ [header, _, header, _, header, _, header, _] =
get_all_terms(nn, NewFile, wrap),
- ?line [new_header, _, header, _, header, _] = get_all_terms(n, File, wrap),
+ [new_header, _, header, _, header, _] = get_all_terms(n, File, wrap),
- ?line del(NewFile, No),
- ?line file:delete(File ++ ".2"),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {notify, true},
- {head, header}, {size, {100, No}}]),
+ del(NewFile, No),
+ file:delete(File ++ ".2"),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {notify, true},
+ {head, header}, {size, {100, No}}]),
%% One file is missing...
- ?line ok = disk_log:reopen(n, NewFile),
- ?line rec(1, {disk_log, node(), n, {truncated, 6}}),
- ?line ok = disk_log:close(n),
+ ok = disk_log:reopen(n, NewFile),
+ rec(1, {disk_log, node(), n, {truncated, 6}}),
+ ok = disk_log:close(n),
- ?line del(File, No),
- ?line del(NewFile, No),
- ?line Q = qlen(),
+ del(File, No),
+ del(NewFile, No),
+ Q = qlen(),
ok.
-block_blocked(suite) -> [];
-block_blocked(doc) ->
- ["Test block/1 on external and internal logs."];
+%% Test block/1 on external and internal logs.
block_blocked(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
- ?line B = mk_bytes(60),
+ B = mk_bytes(60),
Halt = join(Dir, "halt.LOG"),
- % External logs.
- ?line file:delete(Halt), % cleanup
- ?line {ok, halt} = disk_log:open([{name, halt}, {type, halt},
- {format, external}, {file, Halt}]),
- ?line ok = disk_log:sync(halt),
- ?line ok = disk_log:block(halt, false),
- ?line Error1 = {error, {blocked_log, halt}} = disk_log:block(halt),
- ?line "The blocked disk" ++ _ = format_error(Error1),
- ?line {error, {blocked_log, halt}} = disk_log:sync(halt),
- ?line {error, {blocked_log, halt}} = disk_log:truncate(halt),
- ?line {error, {blocked_log, halt}} = disk_log:change_size(halt, infinity),
- ?line {error, {blocked_log, halt}} =
+ %% External logs.
+ file:delete(Halt), % cleanup
+ {ok, halt} = disk_log:open([{name, halt}, {type, halt},
+ {format, external}, {file, Halt}]),
+ ok = disk_log:sync(halt),
+ ok = disk_log:block(halt, false),
+ Error1 = {error, {blocked_log, halt}} = disk_log:block(halt),
+ "The blocked disk" ++ _ = format_error(Error1),
+ {error, {blocked_log, halt}} = disk_log:sync(halt),
+ {error, {blocked_log, halt}} = disk_log:truncate(halt),
+ {error, {blocked_log, halt}} = disk_log:change_size(halt, infinity),
+ {error, {blocked_log, halt}} =
disk_log:change_notify(halt, self(), false),
- ?line {error, {blocked_log, halt}} =
+ {error, {blocked_log, halt}} =
disk_log:change_header(halt, {head, header}),
- ?line {error, {blocked_log, halt}} = disk_log:reopen(halt, "foo"),
- ?line ok = disk_log:close(halt),
-
- ?line {ok, halt} = disk_log:open([{name, halt}, {type, halt},
- {format, external}]),
- ?line ok = disk_log:sync(halt),
- ?line ok = disk_log:block(halt, true),
- ?line {error, {blocked_log, halt}} = disk_log:blog(halt, B),
- ?line {error, {blocked_log, halt}} = disk_log:blog(halt, B),
- ?line {error, {blocked_log, halt}} = disk_log:block(halt),
- ?line {error, {blocked_log, halt}} = disk_log:sync(halt),
- ?line {error, {blocked_log, halt}} = disk_log:truncate(halt),
- ?line {error, {blocked_log, halt}} = disk_log:change_size(halt, infinity),
- ?line {error, {blocked_log, halt}} =
+ {error, {blocked_log, halt}} = disk_log:reopen(halt, "foo"),
+ ok = disk_log:close(halt),
+
+ {ok, halt} = disk_log:open([{name, halt}, {type, halt},
+ {format, external}]),
+ ok = disk_log:sync(halt),
+ ok = disk_log:block(halt, true),
+ {error, {blocked_log, halt}} = disk_log:blog(halt, B),
+ {error, {blocked_log, halt}} = disk_log:blog(halt, B),
+ {error, {blocked_log, halt}} = disk_log:block(halt),
+ {error, {blocked_log, halt}} = disk_log:sync(halt),
+ {error, {blocked_log, halt}} = disk_log:truncate(halt),
+ {error, {blocked_log, halt}} = disk_log:change_size(halt, infinity),
+ {error, {blocked_log, halt}} =
disk_log:change_notify(halt, self(), false),
- ?line {error, {blocked_log, halt}} =
+ {error, {blocked_log, halt}} =
disk_log:change_header(halt, {head, header}),
- ?line {error, {blocked_log, halt}} = disk_log:reopen(halt, "foo"),
-
- ?line ok = disk_log:unblock(halt),
- ?line ok = disk_log:close(halt),
- ?line file:delete(Halt),
-
- % Internal logs.
- ?line File = filename:join(Dir, "n.LOG"),
- ?line No = 4,
- ?line del(File, No), % cleanup
- ?line {ok, halt} = disk_log:open([{name, halt}, {file, File}, {type, wrap},
- {size, {100, No}}]),
- ?line ok = disk_log:block(halt, true),
- ?line eof = disk_log:chunk(halt, start),
- ?line Error2 = {error, end_of_log} = disk_log:chunk_step(halt, start, 1),
- ?line "An attempt" ++ _ = format_error(Error2),
- ?line {error, {blocked_log, halt}} = disk_log:log(halt, B),
- ?line {error, {blocked_log, halt}} = disk_log:inc_wrap_file(halt),
- ?line ok = disk_log:unblock(halt),
- ?line ok = disk_log:block(halt, false),
- ?line {error, {blocked_log, halt}} = disk_log:log(halt, B),
- ?line {error, {blocked_log, halt}} = disk_log:inc_wrap_file(halt),
- ?line Parent = self(),
- ?line Pid =
+ {error, {blocked_log, halt}} = disk_log:reopen(halt, "foo"),
+
+ ok = disk_log:unblock(halt),
+ ok = disk_log:close(halt),
+ file:delete(Halt),
+
+ %% Internal logs.
+ File = filename:join(Dir, "n.LOG"),
+ No = 4,
+ del(File, No), % cleanup
+ {ok, halt} = disk_log:open([{name, halt}, {file, File}, {type, wrap},
+ {size, {100, No}}]),
+ ok = disk_log:block(halt, true),
+ eof = disk_log:chunk(halt, start),
+ Error2 = {error, end_of_log} = disk_log:chunk_step(halt, start, 1),
+ "An attempt" ++ _ = format_error(Error2),
+ {error, {blocked_log, halt}} = disk_log:log(halt, B),
+ {error, {blocked_log, halt}} = disk_log:inc_wrap_file(halt),
+ ok = disk_log:unblock(halt),
+ ok = disk_log:block(halt, false),
+ {error, {blocked_log, halt}} = disk_log:log(halt, B),
+ {error, {blocked_log, halt}} = disk_log:inc_wrap_file(halt),
+ Parent = self(),
+ Pid =
spawn_link(fun() ->
{error, {blocked_log, halt}} =
disk_log:chunk(halt, start),
@@ -1661,109 +1608,107 @@ block_blocked(Conf) when is_list(Conf) ->
disk_log:chunk_step(halt, start, 1),
Parent ! {self(), stopped}
end),
- ?line receive {Pid,stopped} -> ok end,
- ?line ok = disk_log:close(halt),
- ?line del(File, No).
+ receive {Pid,stopped} -> ok end,
+ ok = disk_log:close(halt),
+ del(File, No).
-block_queue(suite) -> [];
-block_queue(doc) ->
- ["Run commands from the queue by unblocking."];
+%% Run commands from the queue by unblocking.
block_queue(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
- ?line Q = qlen(),
- ?line File = filename:join(Dir, "n.LOG"),
- ?line No = 4,
- ?line del(File, No), % cleanup
- ?line B = mk_bytes(60),
-
- ?line Pid = spawn_link(?MODULE, lserv, [n]),
- ?line {ok, n} = sync_do(Pid, {open, File}),
-
- ?line ok = disk_log:block(n, true),
- ?line async_do(Pid, {blog, B}),
- ?line ok = disk_log:unblock(n),
- ?line ok = get_reply(),
- ?line 1 = no_written_items(n),
- ?line Error1 = {error,{not_blocked,n}} = disk_log:unblock(n),
- ?line "The disk log" ++ _ = format_error(Error1),
-
- ?line ok = disk_log:block(n, true),
- ?line async_do(Pid, {balog, "one string"}),
- ?line ok = disk_log:unblock(n),
- ?line ok = get_reply(),
- ?line 2 = no_written_items(n),
-
- ?line ok = disk_log:block(n, true),
- ?line async_do(Pid, sync),
- ?line ok = disk_log:unblock(n),
- ?line ok = get_reply(),
-
- ?line ok = disk_log:block(n, true),
- ?line async_do(Pid, truncate),
- ?line ok = disk_log:unblock(n),
- ?line ok = get_reply(),
- ?line 0 = no_items(n),
-
- ?line ok = disk_log:block(n, true),
- ?line async_do(Pid, {block, false}),
- ?line ok = disk_log:unblock(n),
- ?line ok = get_reply(),
- ?line {error, {blocked_log, _}} = disk_log:blog(n, B),
- ?line ok = sync_do(Pid, unblock),
-
- ?line ok = disk_log:block(n, true),
- ?line async_do(Pid, {change_notify, Pid, true}),
- ?line ok = disk_log:unblock(n),
- ?line ok = get_reply(),
- ?line [{_, true}] = owners(n),
-
- ?line ok = disk_log:block(n, true),
- ?line async_do(Pid, {change_notify, Pid, false}),
- ?line ok = disk_log:unblock(n),
- ?line ok = get_reply(),
- ?line [{_, false}] = owners(n),
-
- ?line ok = disk_log:block(n, true),
- ?line async_do(Pid, {change_header, {head, header}}),
- ?line ok = disk_log:unblock(n),
- ?line {error, {badarg, head}} = get_reply(),
-
- ?line ok = disk_log:block(n, true),
- ?line async_do(Pid, {change_size, 17}),
- ?line ok = disk_log:unblock(n),
- ?line {error, {badarg, size}} = get_reply(),
-
- ?line ok = disk_log:block(n, true),
- ?line async_do(Pid, inc_wrap_file),
- ?line ok = disk_log:unblock(n),
- ?line ok = get_reply(),
-
- ?line ok = sync_do(Pid, close),
- ?line del(File, No),
-
- ?line _Pid2 = spawn_link(?MODULE, lserv, [n]),
- ?line {ok, n} = sync_do(Pid, {int_open, File}),
-
- ?line ok = disk_log:block(n, true),
- ?line async_do(Pid, {chunk, start}),
- ?line ok = disk_log:unblock(n),
- ?line eof = get_reply(),
-
- ?line ok = disk_log:block(n, true),
- ?line async_do(Pid, {chunk_step, start, 100}),
- ?line ok = disk_log:unblock(n),
- ?line {ok, _Cont} = get_reply(),
-
- ?line ok = disk_log:block(n, true),
- ?line async_do(Pid, {log,a_term}),
- ?line ok = disk_log:unblock(n),
- ?line ok = get_reply(),
- ?line 1 = no_written_items(n),
-
- ?line ok = sync_do(Pid, close),
- ?line sync_do(Pid, terminate),
- ?line del(File, No),
+ Q = qlen(),
+ File = filename:join(Dir, "n.LOG"),
+ No = 4,
+ del(File, No), % cleanup
+ B = mk_bytes(60),
+
+ Pid = spawn_link(?MODULE, lserv, [n]),
+ {ok, n} = sync_do(Pid, {open, File}),
+
+ ok = disk_log:block(n, true),
+ async_do(Pid, {blog, B}),
+ ok = disk_log:unblock(n),
+ ok = get_reply(),
+ 1 = no_written_items(n),
+ Error1 = {error,{not_blocked,n}} = disk_log:unblock(n),
+ "The disk log" ++ _ = format_error(Error1),
+
+ ok = disk_log:block(n, true),
+ async_do(Pid, {balog, "one string"}),
+ ok = disk_log:unblock(n),
+ ok = get_reply(),
+ 2 = no_written_items(n),
+
+ ok = disk_log:block(n, true),
+ async_do(Pid, sync),
+ ok = disk_log:unblock(n),
+ ok = get_reply(),
+
+ ok = disk_log:block(n, true),
+ async_do(Pid, truncate),
+ ok = disk_log:unblock(n),
+ ok = get_reply(),
+ 0 = no_items(n),
+
+ ok = disk_log:block(n, true),
+ async_do(Pid, {block, false}),
+ ok = disk_log:unblock(n),
+ ok = get_reply(),
+ {error, {blocked_log, _}} = disk_log:blog(n, B),
+ ok = sync_do(Pid, unblock),
+
+ ok = disk_log:block(n, true),
+ async_do(Pid, {change_notify, Pid, true}),
+ ok = disk_log:unblock(n),
+ ok = get_reply(),
+ [{_, true}] = owners(n),
+
+ ok = disk_log:block(n, true),
+ async_do(Pid, {change_notify, Pid, false}),
+ ok = disk_log:unblock(n),
+ ok = get_reply(),
+ [{_, false}] = owners(n),
+
+ ok = disk_log:block(n, true),
+ async_do(Pid, {change_header, {head, header}}),
+ ok = disk_log:unblock(n),
+ {error, {badarg, head}} = get_reply(),
+
+ ok = disk_log:block(n, true),
+ async_do(Pid, {change_size, 17}),
+ ok = disk_log:unblock(n),
+ {error, {badarg, size}} = get_reply(),
+
+ ok = disk_log:block(n, true),
+ async_do(Pid, inc_wrap_file),
+ ok = disk_log:unblock(n),
+ ok = get_reply(),
+
+ ok = sync_do(Pid, close),
+ del(File, No),
+
+ _Pid2 = spawn_link(?MODULE, lserv, [n]),
+ {ok, n} = sync_do(Pid, {int_open, File}),
+
+ ok = disk_log:block(n, true),
+ async_do(Pid, {chunk, start}),
+ ok = disk_log:unblock(n),
+ eof = get_reply(),
+
+ ok = disk_log:block(n, true),
+ async_do(Pid, {chunk_step, start, 100}),
+ ok = disk_log:unblock(n),
+ {ok, _Cont} = get_reply(),
+
+ ok = disk_log:block(n, true),
+ async_do(Pid, {log,a_term}),
+ ok = disk_log:unblock(n),
+ ok = get_reply(),
+ 1 = no_written_items(n),
+
+ ok = sync_do(Pid, close),
+ sync_do(Pid, terminate),
+ del(File, No),
%% Test of the queue. Three processes involved here. Pid1's block
%% request is queued. Pid2's log requests are put in the queue.
@@ -1771,171 +1716,165 @@ block_queue(Conf) when is_list(Conf) ->
%% Pid2's log requests are executed when Pid1 unblocks.
%% (This example should show that the pair 'queue' and 'messages'
%% in State does the trick - one does not need a "real" queue.)
- ?line P0 = pps(),
+ P0 = pps(),
Name = n,
- ?line Pid1 = spawn_link(?MODULE, lserv, [Name]),
- ?line {ok, Name} = sync_do(Pid1, {int_open, File, {1000,2}}),
- ?line Pid2 = spawn_link(?MODULE, lserv, [Name]),
- ?line {ok, Name} = sync_do(Pid2, {int_open, File, {1000,2}}),
- ?line ok = disk_log:block(Name),
- ?line async_do(Pid1, {alog,{1,a}}),
- ?line ok = get_reply(),
- ?line async_do(Pid1, {alog,{2,b}}),
- ?line ok = get_reply(),
- ?line async_do(Pid1, {alog,{3,c}}),
- ?line ok = get_reply(),
- ?line async_do(Pid1, {alog,{4,d}}),
- ?line ok = get_reply(),
- ?line async_do(Pid1, block),
- ?line async_do(Pid2, {alog,{5,e}}),
- ?line ok = get_reply(),
- ?line async_do(Pid2, {alog,{6,f}}),
- ?line ok = get_reply(),
- ?line ok = disk_log:unblock(Name),
- ?line ok = get_reply(),
- ?line async_do(Pid2, {alog,{7,g}}),
- ?line ok = get_reply(),
- ?line async_do(Pid2, {alog,{8,h}}),
- ?line ok = get_reply(),
- ?line async_do(Pid1, unblock),
- ?line ok = get_reply(),
- ?line ok = sync_do(Pid1, close),
- ?line ok = sync_do(Pid2, close),
- ?line sync_do(Pid1, terminate),
- ?line sync_do(Pid2, terminate),
+ Pid1 = spawn_link(?MODULE, lserv, [Name]),
+ {ok, Name} = sync_do(Pid1, {int_open, File, {1000,2}}),
+ Pid2 = spawn_link(?MODULE, lserv, [Name]),
+ {ok, Name} = sync_do(Pid2, {int_open, File, {1000,2}}),
+ ok = disk_log:block(Name),
+ async_do(Pid1, {alog,{1,a}}),
+ ok = get_reply(),
+ async_do(Pid1, {alog,{2,b}}),
+ ok = get_reply(),
+ async_do(Pid1, {alog,{3,c}}),
+ ok = get_reply(),
+ async_do(Pid1, {alog,{4,d}}),
+ ok = get_reply(),
+ async_do(Pid1, block),
+ async_do(Pid2, {alog,{5,e}}),
+ ok = get_reply(),
+ async_do(Pid2, {alog,{6,f}}),
+ ok = get_reply(),
+ ok = disk_log:unblock(Name),
+ ok = get_reply(),
+ async_do(Pid2, {alog,{7,g}}),
+ ok = get_reply(),
+ async_do(Pid2, {alog,{8,h}}),
+ ok = get_reply(),
+ async_do(Pid1, unblock),
+ ok = get_reply(),
+ ok = sync_do(Pid1, close),
+ ok = sync_do(Pid2, close),
+ sync_do(Pid1, terminate),
+ sync_do(Pid2, terminate),
Terms = get_all_terms(Name, File, wrap),
- ?line true = [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g},{8,h}] == Terms,
+ true = [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g},{8,h}] == Terms,
del(File, 2),
- ?line Q = qlen(),
- ?line true = (P0 == pps()),
+ Q = qlen(),
+ true = (P0 == pps()),
ok.
-block_queue2(suite) -> [];
-block_queue2(doc) ->
- ["OTP-4880. Blocked processes did not get disk_log_stopped message."];
+%% OTP-4880. Blocked processes did not get disk_log_stopped message.
block_queue2(Conf) when is_list(Conf) ->
- ?line Q = qlen(),
- ?line P0 = pps(),
+ Q = qlen(),
+ P0 = pps(),
Dir = ?privdir(Conf),
- ?line File = filename:join(Dir, "n.LOG"),
- ?line No = 4,
+ File = filename:join(Dir, "n.LOG"),
+ No = 4,
%% log requests are queued, and processed when the log is closed
- ?line Pid = spawn_link(?MODULE, lserv, [n]),
- ?line {ok, n} = sync_do(Pid, {open, File}),
- ?line ok = sync_do(Pid, block),
+ Pid = spawn_link(?MODULE, lserv, [n]),
+ {ok, n} = sync_do(Pid, {open, File}),
+ ok = sync_do(Pid, block),
%% Asynchronous stuff is ignored.
- ?line ok = disk_log:balog_terms(n, [<<"foo">>,<<"bar">>]),
- ?line ok = disk_log:balog_terms(n, [<<"more">>,<<"terms">>]),
+ ok = disk_log:balog_terms(n, [<<"foo">>,<<"bar">>]),
+ ok = disk_log:balog_terms(n, [<<"more">>,<<"terms">>]),
Parent = self(),
- ?line Fun =
+ Fun =
fun() ->
{error,no_such_log} = disk_log:sync(n),
receive {disk_log, _, {error, disk_log_stopped}} -> ok end,
Parent ! disk_log_stopped_ok
end,
- ?line spawn(Fun),
- ?line ok = sync_do(Pid, close),
- ?line receive disk_log_stopped_ok -> ok end,
- ?line sync_do(Pid, terminate),
- ?line {ok,<<>>} = file:read_file(File ++ ".1"),
- ?line del(File, No),
- ?line Q = qlen(),
- ?line true = (P0 == pps()),
+ spawn(Fun),
+ ok = sync_do(Pid, close),
+ receive disk_log_stopped_ok -> ok end,
+ sync_do(Pid, terminate),
+ {ok,<<>>} = file:read_file(File ++ ".1"),
+ del(File, No),
+ Q = qlen(),
+ true = (P0 == pps()),
ok.
-unblock(suite) -> [];
-unblock(doc) ->
- ["Test unblock/1."];
+%% Test unblock/1.
unblock(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "n.LOG"),
No = 1,
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {size, {100,No}}, {notify, true},
- {format, external}]),
- ?line ok = disk_log:block(n),
- ?line spawn_link(?MODULE, try_unblock, [n]),
- ?line timer:sleep(100),
- ?line disk_log:close(n),
- ?line del(File, No).
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {size, {100,No}}, {notify, true},
+ {format, external}]),
+ ok = disk_log:block(n),
+ spawn_link(?MODULE, try_unblock, [n]),
+ timer:sleep(100),
+ disk_log:close(n),
+ del(File, No).
try_unblock(Log) ->
- ?line Error = {error, {not_blocked_by_pid, n}} = disk_log:unblock(Log),
- ?line "The disk log" ++ _ = format_error(Error).
+ Error = {error, {not_blocked_by_pid, n}} = disk_log:unblock(Log),
+ "The disk log" ++ _ = format_error(Error).
-open_overwrite(suite) -> [];
-open_overwrite(doc) ->
- ["Test open/1 when old files exist."];
+%% Test open/1 when old files exist.
open_overwrite(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
- ?line File = filename:join(Dir, "n.LOG"),
- ?line No = 4,
- ?line del(File, No), % cleanup
+ File = filename:join(Dir, "n.LOG"),
+ No = 4,
+ del(File, No), % cleanup
- % read write
- ?line First = "n.LOG.1",
- ?line make_file(Dir, First, 8),
+ %% read write
+ First = "n.LOG.1",
+ make_file(Dir, First, 8),
- ?line Error1 = {error, {not_a_log_file, _}} =
+ Error1 = {error, {not_a_log_file, _}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, internal}, {size, {100, No}}]),
- ?line "The file" ++ _ = format_error(Error1),
- ?line del(File, No),
+ "The file" ++ _ = format_error(Error1),
+ del(File, No),
- ?line make_file(Dir, First, 4),
+ make_file(Dir, First, 4),
- ?line {error, {not_a_log_file, _}} =
+ {error, {not_a_log_file, _}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, internal}, {size, {100, No}}]),
- ?line del(File, No),
+ del(File, No),
- ?line make_file(Dir, First, 0),
+ make_file(Dir, First, 0),
- ?line {error, {not_a_log_file, _}} =
+ {error, {not_a_log_file, _}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, internal}, {size, {100, No}}]),
- % read only
- ?line make_file(Dir, First, 6),
+ %% read only
+ make_file(Dir, First, 6),
- ?line {error, {not_a_log_file, _}} =
+ {error, {not_a_log_file, _}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},{mode, read_only},
{format, internal}, {size, {100, No}}]),
- ?line del(File, No),
+ del(File, No),
- ?line make_file(Dir, First, 0),
+ make_file(Dir, First, 0),
- ?line {error, {not_a_log_file, _}} =
+ {error, {not_a_log_file, _}} =
disk_log:open([{name, n}, {file, File},{type, wrap},
{mode, read_only}, {format, internal},
{size, {100, No}}]),
- ?line del(File, No),
-
- ?line {error, _} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {mode, read_only},
- {format, internal},{size, {100, No}}]),
+ del(File, No),
+
+ {error, _} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {mode, read_only},
+ {format, internal},{size, {100, No}}]),
file:delete(File),
- ?line {ok,n} = disk_log:open([{name,n},{file,File},
- {mode,read_write},{type,halt}]),
- ?line ok = disk_log:close(n),
- ?line ok = unwritable(File),
- ?line {error, {file_error, File, _}} =
- disk_log:open([{name,n},{file,File},{mode,read_write},{type,halt}]),
- ?line ok = writable(File),
+ {ok,n} = disk_log:open([{name,n},{file,File},
+ {mode,read_write},{type,halt}]),
+ ok = disk_log:close(n),
+ ok = unwritable(File),
+ {error, {file_error, File, _}} =
+ disk_log:open([{name,n},{file,File},{mode,read_write},{type,halt}]),
+ ok = writable(File),
file:delete(File),
- ?line {ok,n} = disk_log:open([{name,n},{file,File},{format,external},
- {mode,read_write},{type,halt}]),
- ?line ok = disk_log:close(n),
- ?line ok = unwritable(File),
- ?line {error, {file_error, File, _}} =
+ {ok,n} = disk_log:open([{name,n},{file,File},{format,external},
+ {mode,read_write},{type,halt}]),
+ ok = disk_log:close(n),
+ ok = unwritable(File),
+ {error, {file_error, File, _}} =
disk_log:open([{name,n},{file,File},{format,external},
{mode,read_write},{type,halt}]),
- ?line ok = writable(File),
+ ok = writable(File),
file:delete(File),
ok.
@@ -1953,424 +1892,412 @@ make_file(Dir, File, N) ->
end,
ok = file:close(F).
-open_size(suite) -> [];
-open_size(doc) ->
- ["Test open/1 option size."];
+%% Test open/1 option size.
open_size(Conf) when is_list(Conf) ->
- ?line Dir = ?privdir(Conf),
- ?line File = filename:join(Dir, "n.LOG"),
+ Dir = ?privdir(Conf),
+ File = filename:join(Dir, "n.LOG"),
- ?line No = 4,
- ?line file:delete(File),
- ?line del(File, No), % cleanup
+ No = 4,
+ file:delete(File),
+ del(File, No), % cleanup
%% missing size option
- ?line {error, {badarg, size}} =
+ {error, {badarg, size}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, internal}]),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, internal},{size, {100, No}}]),
- ?line B = mk_bytes(60),
- ?line ok = disk_log:log_terms(n, [B, B, B, B]),
- ?line ok = disk_log:sync(n),
- ?line ok = disk_log:block(n),
+ B = mk_bytes(60),
+ ok = disk_log:log_terms(n, [B, B, B, B]),
+ ok = disk_log:sync(n),
+ ok = disk_log:block(n),
%% size option does not match existing size file, read_only
- ?line Error1 = {error, {size_mismatch, _, _}} =
+ Error1 = {error, {size_mismatch, _, _}} =
disk_log:open([{name, nn}, {file, File}, {type, wrap},
{mode, read_only}, {format, internal},
{size, {100, No + 1}}]),
- ?line "The given size" ++ _ = format_error(Error1),
- ?line {ok, nn} = disk_log:open([{name, nn}, {file, File}, {type, wrap},
+ "The given size" ++ _ = format_error(Error1),
+ {ok, nn} = disk_log:open([{name, nn}, {file, File}, {type, wrap},
{mode, read_only},
{format, internal},{size, {100, No}}]),
- ?line [_, _, _, _] = get_all_terms1(nn, start, []),
- ?line disk_log:close(nn),
+ [_, _, _, _] = get_all_terms1(nn, start, []),
+ disk_log:close(nn),
- ?line ok = disk_log:unblock(n),
- ?line ok = disk_log:close(n),
+ ok = disk_log:unblock(n),
+ ok = disk_log:close(n),
%% size option does not match existing size file, read_write
- ?line {error, {size_mismatch, _, _}} =
+ {error, {size_mismatch, _, _}} =
disk_log:open([{name, nn}, {file, File}, {type, wrap},
{format, internal}, {size, {100, No + 1}}]),
%% size option does not match existing size file, truncating
- ?line {ok, nn} =
+ {ok, nn} =
disk_log:open([{name, nn}, {file, File}, {type, wrap},
{repair, truncate}, {format, internal},
{size, {100, No + 1}}]),
- ?line ok = disk_log:close(nn),
+ ok = disk_log:close(nn),
- ?line del(File, No),
+ del(File, No),
ok.
-open_truncate(suite) -> [];
-open_truncate(doc) ->
- ["Test open/1 with {repair, truncate}."];
+%% Test open/1 with {repair, truncate}.
open_truncate(Conf) when is_list(Conf) ->
- ?line Dir = ?privdir(Conf),
- ?line File = filename:join(Dir, "n.LOG"),
- ?line No = 4,
- ?line del(File, No), % cleanup
-
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, internal},{size, {100, No}}]),
- ?line B = mk_bytes(60),
- ?line ok = disk_log:log_terms(n, [B, B, B, B]),
- ?line ok = disk_log:close(n),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {repair,truncate},
- {format, internal},{size, {100, No}}]),
- ?line ok = disk_log:close(n),
- ?line [] = get_all_terms(n, File, wrap),
- ?line del(File, No),
+ Dir = ?privdir(Conf),
+ File = filename:join(Dir, "n.LOG"),
+ No = 4,
+ del(File, No), % cleanup
+
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, internal},{size, {100, No}}]),
+ B = mk_bytes(60),
+ ok = disk_log:log_terms(n, [B, B, B, B]),
+ ok = disk_log:close(n),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {repair,truncate},
+ {format, internal},{size, {100, No}}]),
+ ok = disk_log:close(n),
+ [] = get_all_terms(n, File, wrap),
+ del(File, No),
ok.
-
-open_error(suite) -> [];
-open_error(doc) ->
- ["Try some invalid open/1 options."];
+
+%% Try some invalid open/1 options.
open_error(Conf) when is_list(Conf) ->
- ?line Dir = ?privdir(Conf),
+ Dir = ?privdir(Conf),
- ?line File = filename:join(Dir, "n.LOG"),
- ?line No = 4,
- ?line del(File, No), % cleanup
+ File = filename:join(Dir, "n.LOG"),
+ No = 4,
+ del(File, No), % cleanup
- ?line {error, {badarg, name}} = disk_log:open([{file, File}]),
- ?line {error, {badarg, file}} = disk_log:open([{name,{foo,bar}}]),
- ?line {error, {badarg, [{foo,bar}]}} = disk_log:open([{foo,bar}]),
+ {error, {badarg, name}} = disk_log:open([{file, File}]),
+ {error, {badarg, file}} = disk_log:open([{name,{foo,bar}}]),
+ {error, {badarg, [{foo,bar}]}} = disk_log:open([{foo,bar}]),
%% external logs, read_only.
- ?line {error, {file_error, _, enoent}} =
+ {error, {file_error, _, enoent}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{size, {100,No}},
{format, external}, {mode, read_only}]),
- ?line Error5 = {error, {file_error, _, enoent}} =
+ Error5 = {error, {file_error, _, enoent}} =
disk_log:open([{name, n}, {file, File}, {type, halt},
{size, 100},
{format, external}, {mode, read_only}]),
- ?line true = lists:prefix("\"" ++ File, format_error(Error5)),
+ true = lists:prefix("\"" ++ File, format_error(Error5)),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, external},{size, {100, No}}]),
%% Already owner, ignored.
- ?line {ok, n} =
+ {ok, n} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, external}, {size, {100, No}}]),
- ?line Error2 = {error, {name_already_open, n}} =
+ Error2 = {error, {name_already_open, n}} =
disk_log:open([{name, n}, {file, another_file}, {type, wrap},
{format, external}, {size, {100, No}}]),
- ?line "The disk log" ++ _ = format_error(Error2),
- ?line Error1 = {error, {arg_mismatch, notify, false, true}} =
+ "The disk log" ++ _ = format_error(Error2),
+ Error1 = {error, {arg_mismatch, notify, false, true}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, external}, {size, {100, No}}, {notify, true}]),
- ?line "The value" ++ _ = format_error(Error1),
- ?line Error3 = {error, {open_read_write, n}} =
+ "The value" ++ _ = format_error(Error1),
+ Error3 = {error, {open_read_write, n}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{mode, read_only},
{format, external}, {size, {100, No}}]),
- ?line "The disk log" ++ _ = format_error(Error3),
- ?line {error, {badarg, size}} =
+ "The disk log" ++ _ = format_error(Error3),
+ {error, {badarg, size}} =
disk_log:open([{name, n}, {file, File}, {type, halt},
{format, external}, {size, {100, No}}]),
- ?line {error, {arg_mismatch, type, wrap, halt}} =
+ {error, {arg_mismatch, type, wrap, halt}} =
disk_log:open([{name, n}, {file, File}, {type, halt},
{format, external}]),
- ?line {error, {arg_mismatch, format, external, internal}} =
+ {error, {arg_mismatch, format, external, internal}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, internal}, {size, {100, No}}]),
- ?line {error, {arg_mismatch, repair, true, false}} =
+ {error, {arg_mismatch, repair, true, false}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, external}, {repair, false}]),
- ?line {error, {size_mismatch, {100,4}, {1000,4}}} =
+ {error, {size_mismatch, {100,4}, {1000,4}}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, external}, {size, {1000, No}}]),
- ?line {error, {arg_mismatch, head, none, _}} =
+ {error, {arg_mismatch, head, none, _}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{head, "header"},
{format, external}, {size, {100, No}}]),
- ?line {error, {badarg, size}} =
+ {error, {badarg, size}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, external}, {size, 100}]),
- ?line ok = disk_log:close(n),
+ ok = disk_log:close(n),
- ?line {ok, n} =
+ {ok, n} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{mode, read_only},
{format, external}, {size, {100, No}}]),
- ?line Error4 = {error, {open_read_only, n}} =
+ Error4 = {error, {open_read_only, n}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{mode, read_write},
{format, external}, {size, {100, No}}]),
- ?line "The disk log" ++ _ = format_error(Error4),
- ?line ok = disk_log:close(n),
+ "The disk log" ++ _ = format_error(Error4),
+ ok = disk_log:close(n),
- ?line del(File, No).
+ del(File, No).
-close_race(suite) -> [];
-close_race(doc) ->
- ["Do something quickly after close/1"];
+%% Do something quickly after close/1.
close_race(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
- ?line File = filename:join(Dir, "n.LOG"),
- ?line No = 1,
- ?line del(File, No), % cleanup
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {size, {100,No}}, {notify, true},
- {format, internal}]),
- ?line ok = disk_log:close(n),
- ?line Error1 = {error, no_such_log} = disk_log:close(n),
- ?line "There is no disk" ++ _ = format_error(Error1),
-
- % Pid1 blocks, Pid2 closes without being suspended.
- ?line Pid1 = spawn_link(?MODULE, lserv, [n]),
- ?line Pid2 = spawn_link(?MODULE, lserv, [n]),
- ?line {ok, n} = sync_do(Pid1, {open, File}),
- ?line {ok, n} = sync_do(Pid2, {open, File}),
- ?line ok = sync_do(Pid1, block),
- ?line [{_, false}, {_, false}] = sync_do(Pid1, owners),
- ?line ok = sync_do(Pid2, close),
- ?line [{_, false}] = sync_do(Pid1, owners),
- ?line ok = sync_do(Pid1, close),
- ?line sync_do(Pid1, terminate),
- ?line sync_do(Pid2, terminate),
- ?line {error, no_such_log} = disk_log:info(n),
-
- % Pid3 blocks, Pid3 closes. Pid4 should still be ablo to use log.
- ?line Pid3 = spawn_link(?MODULE, lserv, [n]),
- ?line Pid4 = spawn_link(?MODULE, lserv, [n]),
- ?line {ok, n} = sync_do(Pid3, {open, File}),
- ?line {ok, n} = sync_do(Pid4, {open, File}),
- ?line ok = sync_do(Pid3, block),
- ?line ok = sync_do(Pid3, close),
- ?line [{_Pid4, false}] = sync_do(Pid4, owners),
- ?line sync_do(Pid3, terminate),
- ?line sync_do(Pid4, terminate),
- ?line {error, no_such_log} = disk_log:info(n),
-
- % Pid5 blocks, Pid5 terminates. Pid6 should still be ablo to use log.
- ?line Pid5 = spawn_link(?MODULE, lserv, [n]),
- ?line Pid6 = spawn_link(?MODULE, lserv, [n]),
- ?line {ok, n} = sync_do(Pid5, {open, File}),
- ?line {ok, n} = sync_do(Pid6, {open, File}),
- ?line ok = sync_do(Pid5, block),
- ?line sync_do(Pid5, terminate),
- ?line [{_Pid6, false}] = sync_do(Pid6, owners),
- ?line sync_do(Pid6, terminate),
- ?line {error, no_such_log} = disk_log:info(n),
- ?line del(File, No), % cleanup
+ File = filename:join(Dir, "n.LOG"),
+ No = 1,
+ del(File, No), % cleanup
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {size, {100,No}}, {notify, true},
+ {format, internal}]),
+ ok = disk_log:close(n),
+ Error1 = {error, no_such_log} = disk_log:close(n),
+ "There is no disk" ++ _ = format_error(Error1),
+
+ %% Pid1 blocks, Pid2 closes without being suspended.
+ Pid1 = spawn_link(?MODULE, lserv, [n]),
+ Pid2 = spawn_link(?MODULE, lserv, [n]),
+ {ok, n} = sync_do(Pid1, {open, File}),
+ {ok, n} = sync_do(Pid2, {open, File}),
+ ok = sync_do(Pid1, block),
+ [{_, false}, {_, false}] = sync_do(Pid1, owners),
+ ok = sync_do(Pid2, close),
+ [{_, false}] = sync_do(Pid1, owners),
+ ok = sync_do(Pid1, close),
+ sync_do(Pid1, terminate),
+ sync_do(Pid2, terminate),
+ {error, no_such_log} = disk_log:info(n),
+
+ %% Pid3 blocks, Pid3 closes. Pid4 should still be ablo to use log.
+ Pid3 = spawn_link(?MODULE, lserv, [n]),
+ Pid4 = spawn_link(?MODULE, lserv, [n]),
+ {ok, n} = sync_do(Pid3, {open, File}),
+ {ok, n} = sync_do(Pid4, {open, File}),
+ ok = sync_do(Pid3, block),
+ ok = sync_do(Pid3, close),
+ [{_Pid4, false}] = sync_do(Pid4, owners),
+ sync_do(Pid3, terminate),
+ sync_do(Pid4, terminate),
+ {error, no_such_log} = disk_log:info(n),
+
+ %% Pid5 blocks, Pid5 terminates. Pid6 should still be ablo to use log.
+ Pid5 = spawn_link(?MODULE, lserv, [n]),
+ Pid6 = spawn_link(?MODULE, lserv, [n]),
+ {ok, n} = sync_do(Pid5, {open, File}),
+ {ok, n} = sync_do(Pid6, {open, File}),
+ ok = sync_do(Pid5, block),
+ sync_do(Pid5, terminate),
+ [{_Pid6, false}] = sync_do(Pid6, owners),
+ sync_do(Pid6, terminate),
+ {error, no_such_log} = disk_log:info(n),
+ del(File, No), % cleanup
ok.
-close_block(suite) -> [];
-close_block(doc) ->
- ["Block, unblock, close, terminate."];
+%% Block, unblock, close, terminate.
close_block(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
- ?line File = filename:join(Dir, "n.LOG"),
+ File = filename:join(Dir, "n.LOG"),
No = 1,
del(File, No), % cleanup
P0 = pps(),
%% One of two owners terminates.
- ?line Pid1 = spawn_link(?MODULE, lserv, [n]),
- ?line Pid2 = spawn_link(?MODULE, lserv, [n]),
- ?line {ok, n} = sync_do(Pid1, {open, File}),
- ?line {ok, n} = sync_do(Pid2, {open, File}),
- ?line [_, _] = sync_do(Pid1, owners),
- ?line [_, _] = sync_do(Pid2, owners),
- ?line 0 = sync_do(Pid1, users),
- ?line 0 = sync_do(Pid2, users),
- ?line sync_do(Pid1, terminate),
- ?line [_] = sync_do(Pid2, owners),
- ?line 0 = sync_do(Pid2, users),
- ?line sync_do(Pid2, terminate),
- ?line {error, no_such_log} = disk_log:info(n),
- ?line true = (P0 == pps()),
+ Pid1 = spawn_link(?MODULE, lserv, [n]),
+ Pid2 = spawn_link(?MODULE, lserv, [n]),
+ {ok, n} = sync_do(Pid1, {open, File}),
+ {ok, n} = sync_do(Pid2, {open, File}),
+ [_, _] = sync_do(Pid1, owners),
+ [_, _] = sync_do(Pid2, owners),
+ 0 = sync_do(Pid1, users),
+ 0 = sync_do(Pid2, users),
+ sync_do(Pid1, terminate),
+ [_] = sync_do(Pid2, owners),
+ 0 = sync_do(Pid2, users),
+ sync_do(Pid2, terminate),
+ {error, no_such_log} = disk_log:info(n),
+ true = (P0 == pps()),
%% Users terminate (no link...).
- ?line Pid3 = spawn_link(?MODULE, lserv, [n]),
- ?line Pid4 = spawn_link(?MODULE, lserv, [n]),
- ?line {ok, n} = sync_do(Pid3, {open, File, none}),
- ?line {ok, n} = sync_do(Pid4, {open, File, none}),
- ?line [] = sync_do(Pid3, owners),
- ?line [] = sync_do(Pid4, owners),
- ?line 2 = sync_do(Pid3, users),
- ?line 2 = sync_do(Pid4, users),
- ?line sync_do(Pid3, terminate),
- ?line [] = sync_do(Pid4, owners),
- ?line 2 = sync_do(Pid4, users),
- ?line sync_do(Pid4, terminate),
- ?line disk_log:close(n),
- ?line disk_log:close(n),
- ?line {error, no_such_log} = disk_log:info(n),
- ?line true = (P0 == pps()),
-
- % Blocking owner terminates.
- ?line Pid5 = spawn_link(?MODULE, lserv, [n]),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {linkto, none},{size, {100,No}},
- {format, external}]),
- ?line {ok, n} = sync_do(Pid5, {open, File}),
- ?line ok = sync_do(Pid5, block),
- ?line {blocked, true} = status(n),
- ?line [_] = owners(n),
- ?line sync_do(Pid5, terminate),
- ?line ok = status(n),
- ?line [] = owners(n),
- ?line 1 = users(n),
- ?line ok = disk_log:close(n),
- ?line {error, no_such_log} = disk_log:info(n),
- ?line true = (P0 == pps()),
-
- % Blocking user terminates.
- ?line Pid6 = spawn_link(?MODULE, lserv, [n]),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {size, {100,No}}, {format, external}]),
- ?line {ok, n} = sync_do(Pid6, {open, File, none}),
- ?line ok = sync_do(Pid6, block),
- ?line {blocked, true} = status(n),
- ?line [_] = owners(n),
- ?line 1 = users(n),
- ?line sync_do(Pid6, terminate), % very silently...
- ?line ok = status(n),
- ?line [_] = owners(n),
- ?line 1 = users(n),
- ?line ok = disk_log:close(n),
- ?line [] = owners(n),
- ?line 1 = users(n),
- ?line ok = disk_log:close(n),
- ?line {error, no_such_log} = disk_log:info(n),
- ?line true = (P0 == pps()),
-
- % Blocking owner terminates.
- ?line Pid7 = spawn_link(?MODULE, lserv, [n]),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {linkto, none},
- {size, {100,No}}, {format, external}]),
- ?line {ok, n} = sync_do(Pid7, {open, File}),
- ?line ok = sync_do(Pid7, block),
- ?line {blocked, true} = status(n),
- ?line [_] = owners(n),
- ?line 1 = users(n),
- ?line sync_do(Pid7, terminate),
- ?line ok = status(n),
- ?line [] = owners(n),
- ?line 1 = users(n),
- ?line ok = disk_log:close(n),
- ?line {error, no_such_log} = disk_log:info(n),
- ?line true = (P0 == pps()),
+ Pid3 = spawn_link(?MODULE, lserv, [n]),
+ Pid4 = spawn_link(?MODULE, lserv, [n]),
+ {ok, n} = sync_do(Pid3, {open, File, none}),
+ {ok, n} = sync_do(Pid4, {open, File, none}),
+ [] = sync_do(Pid3, owners),
+ [] = sync_do(Pid4, owners),
+ 2 = sync_do(Pid3, users),
+ 2 = sync_do(Pid4, users),
+ sync_do(Pid3, terminate),
+ [] = sync_do(Pid4, owners),
+ 2 = sync_do(Pid4, users),
+ sync_do(Pid4, terminate),
+ disk_log:close(n),
+ disk_log:close(n),
+ {error, no_such_log} = disk_log:info(n),
+ true = (P0 == pps()),
+
+ %% Blocking owner terminates.
+ Pid5 = spawn_link(?MODULE, lserv, [n]),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {linkto, none},{size, {100,No}},
+ {format, external}]),
+ {ok, n} = sync_do(Pid5, {open, File}),
+ ok = sync_do(Pid5, block),
+ {blocked, true} = status(n),
+ [_] = owners(n),
+ sync_do(Pid5, terminate),
+ ok = status(n),
+ [] = owners(n),
+ 1 = users(n),
+ ok = disk_log:close(n),
+ {error, no_such_log} = disk_log:info(n),
+ true = (P0 == pps()),
+
+ %% Blocking user terminates.
+ Pid6 = spawn_link(?MODULE, lserv, [n]),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {size, {100,No}}, {format, external}]),
+ {ok, n} = sync_do(Pid6, {open, File, none}),
+ ok = sync_do(Pid6, block),
+ {blocked, true} = status(n),
+ [_] = owners(n),
+ 1 = users(n),
+ sync_do(Pid6, terminate), % very silently...
+ ok = status(n),
+ [_] = owners(n),
+ 1 = users(n),
+ ok = disk_log:close(n),
+ [] = owners(n),
+ 1 = users(n),
+ ok = disk_log:close(n),
+ {error, no_such_log} = disk_log:info(n),
+ true = (P0 == pps()),
+
+ %% Blocking owner terminates.
+ Pid7 = spawn_link(?MODULE, lserv, [n]),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {linkto, none},
+ {size, {100,No}}, {format, external}]),
+ {ok, n} = sync_do(Pid7, {open, File}),
+ ok = sync_do(Pid7, block),
+ {blocked, true} = status(n),
+ [_] = owners(n),
+ 1 = users(n),
+ sync_do(Pid7, terminate),
+ ok = status(n),
+ [] = owners(n),
+ 1 = users(n),
+ ok = disk_log:close(n),
+ {error, no_such_log} = disk_log:info(n),
+ true = (P0 == pps()),
%% Two owners, the blocking one terminates.
- ?line Pid8 = spawn_link(?MODULE, lserv, [n]),
- ?line Pid9 = spawn_link(?MODULE, lserv, [n]),
- ?line {ok, n} = sync_do(Pid8, {open, File}),
- ?line {ok, n} = sync_do(Pid9, {open, File}),
- ?line ok = sync_do(Pid8, block),
- ?line {blocked, true} = status(n),
- ?line sync_do(Pid8, terminate),
- ?line ok = status(n),
- ?line [_] = sync_do(Pid9, owners),
- ?line 0 = sync_do(Pid9, users),
- ?line sync_do(Pid9, terminate),
- ?line {error, no_such_log} = disk_log:info(n),
- ?line true = (P0 == pps()),
-
- % Blocking user closes.
- ?line Pid10 = spawn_link(?MODULE, lserv, [n]),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {size, {100,No}}, {format, external}]),
- ?line {ok, n} = sync_do(Pid10, {open, File, none}),
- ?line ok = sync_do(Pid10, block),
- ?line {blocked, true} = status(n),
- ?line [_] = owners(n),
- ?line 1 = users(n),
- ?line ok = sync_do(Pid10, close),
- ?line ok = status(n),
- ?line [_] = owners(n),
- ?line 0 = users(n),
- ?line ok = disk_log:close(n),
- ?line sync_do(Pid10, terminate),
- ?line {error, no_such_log} = disk_log:info(n),
- ?line true = (P0 == pps()),
-
- % Blocking user unblocks and closes.
- ?line Pid11 = spawn_link(?MODULE, lserv, [n]),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {size, {100,No}}, {format, external}]),
- ?line {ok, n} = sync_do(Pid11, {open, File, none}),
- ?line ok = sync_do(Pid11, block),
- ?line {blocked, true} = status(n),
- ?line [_] = owners(n),
- ?line 1 = users(n),
- ?line ok = sync_do(Pid11, unblock),
- ?line ok = sync_do(Pid11, close),
- ?line ok = status(n),
- ?line [_] = owners(n),
- ?line 0 = users(n),
- ?line ok = disk_log:close(n),
- ?line {error, no_such_log} = disk_log:info(n),
- ?line sync_do(Pid11, terminate),
- ?line true = (P0 == pps()),
-
- % Blocking owner closes.
- ?line Pid12 = spawn_link(?MODULE, lserv, [n]),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {linkto, none},
- {size, {100,No}}, {format, external}]),
- ?line {ok, n} = sync_do(Pid12, {open, File}),
- ?line ok = sync_do(Pid12, block),
- ?line {blocked, true} = status(n),
- ?line [_] = owners(n),
- ?line 1 = users(n),
- ?line ok = sync_do(Pid12, close),
- ?line ok = status(n),
- ?line [] = owners(n),
- ?line 1 = users(n),
- ?line ok = disk_log:close(n),
- ?line {error, no_such_log} = disk_log:info(n),
- ?line sync_do(Pid12, terminate),
- ?line true = (P0 == pps()),
-
- % Blocking owner unblocks and closes.
- ?line Pid13 = spawn_link(?MODULE, lserv, [n]),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {linkto, none},
- {size, {100,No}}, {format, external}]),
- ?line {ok, n} = sync_do(Pid13, {open, File}),
- ?line ok = sync_do(Pid13, block),
- ?line {blocked, true} = status(n),
- ?line [_] = owners(n),
- ?line 1 = users(n),
- ?line ok = sync_do(Pid13, unblock),
- ?line ok = sync_do(Pid13, close),
- ?line ok = status(n),
- ?line [] = owners(n),
- ?line 1 = users(n),
- ?line ok = disk_log:close(n),
- ?line {error, no_such_log} = disk_log:info(n),
- ?line sync_do(Pid13, terminate),
- ?line true = (P0 == pps()),
+ Pid8 = spawn_link(?MODULE, lserv, [n]),
+ Pid9 = spawn_link(?MODULE, lserv, [n]),
+ {ok, n} = sync_do(Pid8, {open, File}),
+ {ok, n} = sync_do(Pid9, {open, File}),
+ ok = sync_do(Pid8, block),
+ {blocked, true} = status(n),
+ sync_do(Pid8, terminate),
+ ok = status(n),
+ [_] = sync_do(Pid9, owners),
+ 0 = sync_do(Pid9, users),
+ sync_do(Pid9, terminate),
+ {error, no_such_log} = disk_log:info(n),
+ true = (P0 == pps()),
+
+ %% Blocking user closes.
+ Pid10 = spawn_link(?MODULE, lserv, [n]),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {size, {100,No}}, {format, external}]),
+ {ok, n} = sync_do(Pid10, {open, File, none}),
+ ok = sync_do(Pid10, block),
+ {blocked, true} = status(n),
+ [_] = owners(n),
+ 1 = users(n),
+ ok = sync_do(Pid10, close),
+ ok = status(n),
+ [_] = owners(n),
+ 0 = users(n),
+ ok = disk_log:close(n),
+ sync_do(Pid10, terminate),
+ {error, no_such_log} = disk_log:info(n),
+ true = (P0 == pps()),
+
+ %% Blocking user unblocks and closes.
+ Pid11 = spawn_link(?MODULE, lserv, [n]),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {size, {100,No}}, {format, external}]),
+ {ok, n} = sync_do(Pid11, {open, File, none}),
+ ok = sync_do(Pid11, block),
+ {blocked, true} = status(n),
+ [_] = owners(n),
+ 1 = users(n),
+ ok = sync_do(Pid11, unblock),
+ ok = sync_do(Pid11, close),
+ ok = status(n),
+ [_] = owners(n),
+ 0 = users(n),
+ ok = disk_log:close(n),
+ {error, no_such_log} = disk_log:info(n),
+ sync_do(Pid11, terminate),
+ true = (P0 == pps()),
+
+ %% Blocking owner closes.
+ Pid12 = spawn_link(?MODULE, lserv, [n]),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {linkto, none},
+ {size, {100,No}}, {format, external}]),
+ {ok, n} = sync_do(Pid12, {open, File}),
+ ok = sync_do(Pid12, block),
+ {blocked, true} = status(n),
+ [_] = owners(n),
+ 1 = users(n),
+ ok = sync_do(Pid12, close),
+ ok = status(n),
+ [] = owners(n),
+ 1 = users(n),
+ ok = disk_log:close(n),
+ {error, no_such_log} = disk_log:info(n),
+ sync_do(Pid12, terminate),
+ true = (P0 == pps()),
+
+ %% Blocking owner unblocks and closes.
+ Pid13 = spawn_link(?MODULE, lserv, [n]),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {linkto, none},
+ {size, {100,No}}, {format, external}]),
+ {ok, n} = sync_do(Pid13, {open, File}),
+ ok = sync_do(Pid13, block),
+ {blocked, true} = status(n),
+ [_] = owners(n),
+ 1 = users(n),
+ ok = sync_do(Pid13, unblock),
+ ok = sync_do(Pid13, close),
+ ok = status(n),
+ [] = owners(n),
+ 1 = users(n),
+ ok = disk_log:close(n),
+ {error, no_such_log} = disk_log:info(n),
+ sync_do(Pid13, terminate),
+ true = (P0 == pps()),
del(File, No), % cleanup
ok.
-close_deadlock(suite) -> [];
-close_deadlock(doc) ->
- ["OTP-4745. Deadlock with just an ordinary log could happen."];
+%% OTP-4745. Deadlock with just an ordinary log could happen.
close_deadlock(Conf) when is_list(Conf) ->
- ?line true = is_alive(),
+ true = is_alive(),
- ?line PrivDir = ?privdir(Conf),
+ PrivDir = ?privdir(Conf),
- ?line F1 = filename:join(PrivDir, "a.LOG"),
- ?line file:delete(F1),
+ F1 = filename:join(PrivDir, "a.LOG"),
+ file:delete(F1),
Self = self(),
%% One process opens the log at the same time as another process
@@ -2378,11 +2305,11 @@ close_deadlock(Conf) when is_list(Conf) ->
Name = a,
Fun = fun() -> open_close(Self, Name, F1) end,
P = spawn(Fun),
- ?line receive {P, Name} -> ok end,
- ?line {ok, L} = disk_log:open([{name,Name},{file,F1}]),
- ?line ok = disk_log:close(L),
- ?line receive {P, done} -> ok end,
- ?line file:delete(F1),
+ receive {P, Name} -> ok end,
+ {ok, L} = disk_log:open([{name,Name},{file,F1}]),
+ ok = disk_log:close(L),
+ receive {P, done} -> ok end,
+ file:delete(F1),
%% One process opens the log at the same time as another process
%% closes the log due to file error while truncating.
@@ -2390,38 +2317,38 @@ close_deadlock(Conf) when is_list(Conf) ->
%% "work". When it works, as it seems to do right now :), the
%% disk_log_server gets {error, no_such_log}, receives the EXIT
%% message caused by truncate, and tries to open the log again.
- ?line No = 4,
- ?line LDir = F1 ++ ".2",
- ?line file:del_dir(LDir),
- ?line del(F1, No),
- ?line ok = file:make_dir(LDir),
+ No = 4,
+ LDir = F1 ++ ".2",
+ file:del_dir(LDir),
+ del(F1, No),
+ ok = file:make_dir(LDir),
Fun2 = fun() -> open_truncate(Self, Name, F1, No) end,
P2 = spawn(Fun2),
- ?line receive {P2, Name} -> ok end,
- ?line {ok, L} = disk_log:open([{name, Name}, {file, F1}, {type, wrap},
- {format, external}]),
+ receive {P2, Name} -> ok end,
+ {ok, L} = disk_log:open([{name, Name}, {file, F1}, {type, wrap},
+ {format, external}]),
%% Note: truncate causes the disk log process to terminate. One
%% cannot say if open above happened before, after, or during the
%% termination. The link to the owner is removed before termination.
- ?line case disk_log:close(L) of
- ok -> ok;
- {error,no_such_log} ->
- ok
- end,
- ?line receive {P2, done} -> ok end,
- ?line del(F1, No),
- ?line file:del_dir(LDir),
+ case disk_log:close(L) of
+ ok -> ok;
+ {error,no_such_log} ->
+ ok
+ end,
+ receive {P2, done} -> ok end,
+ del(F1, No),
+ file:del_dir(LDir),
%% To the same thing, this time using distributed logs.
%% (Does not seem to work very well, unfortunately.)
FunD = fun() -> open_close_dist(Self, Name, F1) end,
PD = spawn(FunD),
receive {PD, Name} -> ok end,
- ?line {[_], []} = disk_log:open([{name,Name},{file,F1},
- {distributed,[node()]}]),
- ?line ok = disk_log:close(L),
+ {[_], []} = disk_log:open([{name,Name},{file,F1},
+ {distributed,[node()]}]),
+ ok = disk_log:close(L),
receive {PD, done} -> ok end,
- ?line file:delete(F1),
+ file:delete(F1),
ok.
@@ -2467,7 +2394,7 @@ sync_do(Pid, Req) ->
end.
lserv(Log) ->
- ?line receive
+ receive
{From, {open, File}} ->
From ! disk_log:open([{name, Log}, {file, File}, {type, wrap},
{size, {100,1}}, {format, external}]);
@@ -2534,664 +2461,652 @@ lserv(Log) ->
lserv(Log).
-error_repair(suite) -> [];
-error_repair(doc) ->
- ["Error while repairing."];
+%% Error while repairing.
error_repair(Conf) when is_list(Conf) ->
- % not all error situations are covered by this test
+ %% not all error situations are covered by this test
DataDir = ?datadir(Conf),
PrivDir = ?privdir(Conf),
- ?line File = filename:join(PrivDir, "n.LOG"),
- ?line No = 4,
- ?line file:delete(File),
- ?line del(File, No), % cleanup
+ File = filename:join(PrivDir, "n.LOG"),
+ No = 4,
+ file:delete(File),
+ del(File, No), % cleanup
- % kurt.LOG is not closed and has four logged items, one is recovered
- ?line copy_wrap_log("kurt.LOG", "n.LOG", No, DataDir, PrivDir),
- ?line {repaired,n,{recovered,1},{badbytes,0}} =
+ %% kurt.LOG is not closed and has four logged items, one is recovered
+ copy_wrap_log("kurt.LOG", "n.LOG", No, DataDir, PrivDir),
+ {repaired,n,{recovered,1},{badbytes,0}} =
disk_log:open([{name, n}, {file, File}, {type, wrap}, {size,{40,No}}]),
- ?line 1 = cur_cnt(n),
- ?line 53 = curb(n),
- ?line 4 = no_items(n),
- ?line ok = disk_log:close(n),
-
- % temporary repair file cannot be created
- ?line copy_wrap_log("kurt.LOG", "n.LOG", No, DataDir, PrivDir),
- ?line Dir = File ++ ".4" ++ ".TMP",
- ?line ok = file:make_dir(Dir),
- ?line P0 = pps(),
- ?line {error, {file_error, _, _}} =
+ 1 = cur_cnt(n),
+ 53 = curb(n),
+ 4 = no_items(n),
+ ok = disk_log:close(n),
+
+ %% temporary repair file cannot be created
+ copy_wrap_log("kurt.LOG", "n.LOG", No, DataDir, PrivDir),
+ Dir = File ++ ".4" ++ ".TMP",
+ ok = file:make_dir(Dir),
+ P0 = pps(),
+ {error, {file_error, _, _}} =
disk_log:open([{name, n}, {file, File}, {type, wrap}, {size,{40,4}}]),
- ?line true = (P0 == pps()),
- ?line del(File, No),
- ?line ok = file:del_dir(Dir),
+ true = (P0 == pps()),
+ del(File, No),
+ ok = file:del_dir(Dir),
%% repair a file
- ?line P1 = pps(),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, internal}, {size, {40,No}}]),
- ?line ok = disk_log:log_terms(n, [{this,is}]), % first file full
- ?line ok = disk_log:log_terms(n, [{some,terms}]), % second file full
- ?line ok = disk_log:close(n),
- ?line BadFile = add_ext(File, 2), % current file
- ?line set_opened(BadFile),
- ?line crash(BadFile, 28), % the binary is now invalid
- ?line {repaired,n,{recovered,0},{badbytes,26}} =
- disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, internal}, {size, {40,No}}]),
- ?line ok = disk_log:close(n),
- ?line true = (P1 == pps()),
- ?line del(File, No),
+ P1 = pps(),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, internal}, {size, {40,No}}]),
+ ok = disk_log:log_terms(n, [{this,is}]), % first file full
+ ok = disk_log:log_terms(n, [{some,terms}]), % second file full
+ ok = disk_log:close(n),
+ BadFile = add_ext(File, 2), % current file
+ set_opened(BadFile),
+ crash(BadFile, 28), % the binary is now invalid
+ {repaired,n,{recovered,0},{badbytes,26}} =
+ disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, internal}, {size, {40,No}}]),
+ ok = disk_log:close(n),
+ true = (P1 == pps()),
+ del(File, No),
%% yet another repair
- ?line P2 = pps(),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, internal}, {size, {4000,No}}]),
- ?line ok = disk_log:log_terms(n, [{this,is},{some,terms}]),
- ?line ok = disk_log:close(n),
- ?line BadFile2 = add_ext(File, 1), % current file
- ?line set_opened(BadFile2),
- ?line crash(BadFile2, 51), % the second binary is now invalid
- ?line {repaired,n,{recovered,1},{badbytes,26}} =
+ P2 = pps(),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, internal}, {size, {4000,No}}]),
+ ok = disk_log:log_terms(n, [{this,is},{some,terms}]),
+ ok = disk_log:close(n),
+ BadFile2 = add_ext(File, 1), % current file
+ set_opened(BadFile2),
+ crash(BadFile2, 51), % the second binary is now invalid
+ {repaired,n,{recovered,1},{badbytes,26}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, internal}, {size, {4000,No}}]),
- ?line ok = disk_log:close(n),
- ?line true = (P2 == pps()),
- ?line del(File, No),
+ ok = disk_log:close(n),
+ true = (P2 == pps()),
+ del(File, No),
%% Repair, large term
- ?line Big = term_to_binary(lists:duplicate(66000,$a)),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, internal}, {size, {40,No}}]),
- ?line ok = disk_log:log_terms(n, [Big]),
- ?line ok = disk_log:close(n),
- ?line set_opened(add_ext(File, 1)),
- ?line {repaired,n,{recovered,1},{badbytes,0}} =
+ Big = term_to_binary(lists:duplicate(66000,$a)),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, internal}, {size, {40,No}}]),
+ ok = disk_log:log_terms(n, [Big]),
+ ok = disk_log:close(n),
+ set_opened(add_ext(File, 1)),
+ {repaired,n,{recovered,1},{badbytes,0}} =
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, internal}, {size, {40,No}}]),
- ?line {_, [Got]} = disk_log:chunk(n, start),
- ?line ok = disk_log:close(n),
- ?line Got = Big,
- ?line del(File, No),
+ {_, [Got]} = disk_log:chunk(n, start),
+ ok = disk_log:close(n),
+ Got = Big,
+ del(File, No),
%% A term a little smaller than a chunk, then big terms.
- ?line BigSmall = mk_bytes(1024*64-8-12),
- ?line file:delete(File),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal}]),
- ?line ok = disk_log:log_terms(n, [BigSmall, Big, Big]),
- ?line ok = disk_log:close(n),
- ?line set_opened(File),
- ?line FileSize = file_size(File),
- ?line crash(File, FileSize-byte_size(Big)-4),
- ?line Error1 = {error, {need_repair, _}} =
+ BigSmall = mk_bytes(1024*64-8-12),
+ file:delete(File),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal}]),
+ ok = disk_log:log_terms(n, [BigSmall, Big, Big]),
+ ok = disk_log:close(n),
+ set_opened(File),
+ FileSize = file_size(File),
+ crash(File, FileSize-byte_size(Big)-4),
+ Error1 = {error, {need_repair, _}} =
disk_log:open([{name, n}, {file, File}, {repair, false},
{type, halt}, {format, internal}]),
- ?line "The disk log" ++ _ = format_error(Error1),
- ?line {repaired,n,{recovered,2},{badbytes,132013}} =
+ "The disk log" ++ _ = format_error(Error1),
+ {repaired,n,{recovered,2},{badbytes,132013}} =
disk_log:open([{name, n}, {file, File}, {repair, true},
{type, halt}, {format, internal}]),
- ?line ok = disk_log:close(n),
- ?line file:delete(File),
+ ok = disk_log:close(n),
+ file:delete(File),
%% The header is recovered.
- ?line {ok,n} =
+ {ok,n} =
disk_log:open([{name, n}, {file, File}, {type, halt},
{format, internal},
{head_func, {?MODULE, head_fun, [{ok,"head"}]}}]),
- ?line ok = disk_log:log_terms(n, [list,'of',terms]),
- ?line ["head",list,'of',terms] = get_all_terms(n),
- ?line ok = disk_log:close(n),
- ?line set_opened(File),
- ?line crash(File, 30),
- ?line {repaired,n,{recovered,3},{badbytes,16}} =
+ ok = disk_log:log_terms(n, [list,'of',terms]),
+ ["head",list,'of',terms] = get_all_terms(n),
+ ok = disk_log:close(n),
+ set_opened(File),
+ crash(File, 30),
+ {repaired,n,{recovered,3},{badbytes,16}} =
disk_log:open([{name, n}, {file, File}, {type, halt},
{format, internal},{repair,true},
{head_func, {?MODULE, head_fun, [{ok,"head"}]}}]),
- ?line ["head",'of',terms] = get_all_terms(n),
- ?line ok = disk_log:close(n),
+ ["head",'of',terms] = get_all_terms(n),
+ ok = disk_log:close(n),
file:delete(File),
ok.
-
+
set_opened(File) ->
{ok, Fd} = file:open(File, [raw, binary, read, write]),
ok = file:write(Fd, [?LOGMAGIC, ?OPENED]),
ok = file:close(Fd).
-error_log(suite) -> [];
-error_log(doc) ->
- ["Error while repairing."];
+%% Error while repairing.
error_log(Conf) when is_list(Conf) ->
- ?line Dir = ?privdir(Conf),
-
- ?line File = filename:join(Dir, "n.LOG"),
- ?line No = 4,
- ?line file:delete(File),
- ?line del(File, No), % cleanup
- ?line LDir = File ++ ".2",
-
- ?line Q = qlen(),
- % dummy just to get all processes "above" disk_log going
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, external},{size, {100, No}}]),
- ?line ok = disk_log:close(n),
- ?line del(File, No),
-
- % inc_wrap_file fails, the external log is not terminated
- ?line P0 = pps(),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, external},{size, {100, No}}]),
- ?line ok = file:make_dir(LDir),
- ?line {error, {file_error, _, _}} = disk_log:inc_wrap_file(n),
- ?line timer:sleep(500),
- ?line ok = disk_log:close(n),
- ?line del(File, No),
-
- % inc_wrap_file fails, the internal log is not terminated, ./File.2/ exists
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, internal},{size, {100, No}}]),
- ?line {error, {file_error, _, _}} = disk_log:inc_wrap_file(n),
- ?line ok = disk_log:close(n),
- ?line del(File, No),
-
- % truncate fails, the log is terminated, ./File.2/ exists
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, external},{size, {100, No}}]),
- ?line {error, {file_error, _, _}} = disk_log:truncate(n),
- ?line true = (P0 == pps()),
- ?line del(File, No),
+ Dir = ?privdir(Conf),
+
+ File = filename:join(Dir, "n.LOG"),
+ No = 4,
+ file:delete(File),
+ del(File, No), % cleanup
+ LDir = File ++ ".2",
+
+ Q = qlen(),
+ %% dummy just to get all processes "above" disk_log going
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, external},{size, {100, No}}]),
+ ok = disk_log:close(n),
+ del(File, No),
+
+ %% inc_wrap_file fails, the external log is not terminated
+ P0 = pps(),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, external},{size, {100, No}}]),
+ ok = file:make_dir(LDir),
+ {error, {file_error, _, _}} = disk_log:inc_wrap_file(n),
+ timer:sleep(500),
+ ok = disk_log:close(n),
+ del(File, No),
+
+ %% inc_wrap_file fails, the internal log is not terminated, ./File.2/ exists
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, internal},{size, {100, No}}]),
+ {error, {file_error, _, _}} = disk_log:inc_wrap_file(n),
+ ok = disk_log:close(n),
+ del(File, No),
+
+ %% truncate fails, the log is terminated, ./File.2/ exists
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, external},{size, {100, No}}]),
+ {error, {file_error, _, _}} = disk_log:truncate(n),
+ true = (P0 == pps()),
+ del(File, No),
%% OTP-4880.
- % reopen (rename) fails, the log is terminated, ./File.2/ exists
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, external},{size, 100000}]),
- ?line {error, {file_error, _, eisdir}} = disk_log:reopen(n, LDir),
- ?line true = (P0 == pps()),
- ?line file:delete(File),
+ %% reopen (rename) fails, the log is terminated, ./File.2/ exists
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, external},{size, 100000}]),
+ {error, {file_error, _, eisdir}} = disk_log:reopen(n, LDir),
+ true = (P0 == pps()),
+ file:delete(File),
- ?line B = mk_bytes(60),
+ B = mk_bytes(60),
%% OTP-4880. reopen a wrap log, rename fails
- ?line File2 = filename:join(Dir, "n.LOG2"),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File2}, {type, wrap},
- {format, external},{size, {100, No}}]),
- ?line ok = disk_log:blog_terms(n, [B,B,B]),
- ?line {error, {file_error, _, eisdir}} = disk_log:reopen(n, File),
- ?line {error, no_such_log} = disk_log:close(n),
- ?line del(File2, No),
- ?line del(File, No),
-
- % log, external wrap log, ./File.2/ exists
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, external},{size, {100, No}}]),
- ?line {error, {file_error, _, _}} = disk_log:blog_terms(n, [B,B,B]),
- ?line ok = disk_log:close(n),
- ?line del(File, No),
-
- % log, internal wrap log, ./File.2/ exists
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, internal},{size, {100, No}}]),
- ?line {error, {file_error, _, _}} = disk_log:log_terms(n, [B,B,B]),
- ?line ok = disk_log:close(n),
- ?line del(File, No),
-
- ?line ok = file:del_dir(LDir),
-
- % can't remove file when changing size
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, internal},{size, {100, No}}]),
- ?line ok = disk_log:log_terms(n, [B,B,B,B]),
- ?line ok = disk_log:change_size(n, {100, No-2}),
- ?line Three = File ++ ".3",
- ?line ok = file:delete(Three),
- ?line ok = file:make_dir(Three),
- ?line {error, {file_error, _, _}} = disk_log:log_terms(n, [B,B,B]),
- ?line timer:sleep(500),
- ?line ok = disk_log:close(n),
- ?line ok = file:del_dir(Three),
- ?line del(File, No),
- ?line Q = qlen(),
+ File2 = filename:join(Dir, "n.LOG2"),
+ {ok, n} = disk_log:open([{name, n}, {file, File2}, {type, wrap},
+ {format, external},{size, {100, No}}]),
+ ok = disk_log:blog_terms(n, [B,B,B]),
+ {error, {file_error, _, eisdir}} = disk_log:reopen(n, File),
+ {error, no_such_log} = disk_log:close(n),
+ del(File2, No),
+ del(File, No),
+
+ %% log, external wrap log, ./File.2/ exists
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, external},{size, {100, No}}]),
+ {error, {file_error, _, _}} = disk_log:blog_terms(n, [B,B,B]),
+ ok = disk_log:close(n),
+ del(File, No),
+
+ %% log, internal wrap log, ./File.2/ exists
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, internal},{size, {100, No}}]),
+ {error, {file_error, _, _}} = disk_log:log_terms(n, [B,B,B]),
+ ok = disk_log:close(n),
+ del(File, No),
+
+ ok = file:del_dir(LDir),
+
+ %% can't remove file when changing size
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, internal},{size, {100, No}}]),
+ ok = disk_log:log_terms(n, [B,B,B,B]),
+ ok = disk_log:change_size(n, {100, No-2}),
+ Three = File ++ ".3",
+ ok = file:delete(Three),
+ ok = file:make_dir(Three),
+ {error, {file_error, _, _}} = disk_log:log_terms(n, [B,B,B]),
+ timer:sleep(500),
+ ok = disk_log:close(n),
+ ok = file:del_dir(Three),
+ del(File, No),
+ Q = qlen(),
ok.
-
-chunk(suite) -> [];
-chunk(doc) ->
- ["Test chunk and chunk_step."];
+
+%% Test chunk and chunk_step.
chunk(Conf) when is_list(Conf) ->
%% See also halt_ro_crash/1 above.
Dir = ?privdir(Conf),
- ?line File = filename:join(Dir, "n.LOG"),
+ File = filename:join(Dir, "n.LOG"),
No = 4,
- ?line B = mk_bytes(60),
- ?line BB = mk_bytes(64000), % 64 kB chunks
- ?line del(File, No),% cleanup
+ B = mk_bytes(60),
+ BB = mk_bytes(64000), % 64 kB chunks
+ del(File, No),% cleanup
%% Make sure chunk_step skips the rest of the binary.
%% OTP-3716. This was a bug...
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, internal}, {size, {50,No}}]),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, internal}, {size, {50,No}}]),
%% 1, 2 and 3 on file one, 4 on file two.
- ?line ok = disk_log:log_terms(n, [1,2,3,4]),
- ?line {I1, [1]} = disk_log:chunk(n, start, 1),
- ?line [{node,Node}] = disk_log:chunk_info(I1),
- ?line Node = node(),
- ?line Error1 = {error, {no_continuation, foobar}} =
+ ok = disk_log:log_terms(n, [1,2,3,4]),
+ {I1, [1]} = disk_log:chunk(n, start, 1),
+ [{node,Node}] = disk_log:chunk_info(I1),
+ Node = node(),
+ Error1 = {error, {no_continuation, foobar}} =
disk_log:chunk_info(foobar),
- ?line "The term" ++ _ = format_error(Error1),
- ?line {ok, I2} = disk_log:chunk_step(n, I1, 1),
- ?line {error, {badarg, continuation}} = disk_log:chunk_step(n, foobar, 1),
- ?line {I3, [4]} = disk_log:chunk(n, I2, 1),
- ?line {ok, I4} = disk_log:chunk_step(n, I3, -1),
- ?line {_, [1]} = disk_log:chunk(n, I4, 1),
- ?line {error, {badarg, continuation}} = disk_log:bchunk(n, 'begin'),
- ?line {Ib1, [Bin1,Bin2]} = disk_log:bchunk(n, start, 2),
- ?line 1 = binary_to_term(Bin1),
- ?line 2 = binary_to_term(Bin2),
- ?line {ok, Ib2} = disk_log:chunk_step(n, Ib1, 1),
- ?line {Ib3, [Bin3]} = disk_log:bchunk(n, Ib2, 1),
- ?line 4 = binary_to_term(Bin3),
- ?line {ok, Ib4} = disk_log:chunk_step(n, Ib3, -1),
- ?line {_, [Bin4]} = disk_log:bchunk(n, Ib4, 1),
- ?line 1 = binary_to_term(Bin4),
- ?line {Ib5, [Bin1, Bin2, Bin17]} = disk_log:bchunk(n, start),
- ?line 3 = binary_to_term(Bin17),
- ?line {Ib6, [Bin3]} = disk_log:bchunk(n, Ib5, infinity),
- ?line eof = disk_log:bchunk(n, Ib6, infinity),
- ?line ok = disk_log:close(n),
- ?line del(File, No), % cleanup
+ "The term" ++ _ = format_error(Error1),
+ {ok, I2} = disk_log:chunk_step(n, I1, 1),
+ {error, {badarg, continuation}} = disk_log:chunk_step(n, foobar, 1),
+ {I3, [4]} = disk_log:chunk(n, I2, 1),
+ {ok, I4} = disk_log:chunk_step(n, I3, -1),
+ {_, [1]} = disk_log:chunk(n, I4, 1),
+ {error, {badarg, continuation}} = disk_log:bchunk(n, 'begin'),
+ {Ib1, [Bin1,Bin2]} = disk_log:bchunk(n, start, 2),
+ 1 = binary_to_term(Bin1),
+ 2 = binary_to_term(Bin2),
+ {ok, Ib2} = disk_log:chunk_step(n, Ib1, 1),
+ {Ib3, [Bin3]} = disk_log:bchunk(n, Ib2, 1),
+ 4 = binary_to_term(Bin3),
+ {ok, Ib4} = disk_log:chunk_step(n, Ib3, -1),
+ {_, [Bin4]} = disk_log:bchunk(n, Ib4, 1),
+ 1 = binary_to_term(Bin4),
+ {Ib5, [Bin1, Bin2, Bin17]} = disk_log:bchunk(n, start),
+ 3 = binary_to_term(Bin17),
+ {Ib6, [Bin3]} = disk_log:bchunk(n, Ib5, infinity),
+ eof = disk_log:bchunk(n, Ib6, infinity),
+ ok = disk_log:close(n),
+ del(File, No), % cleanup
%% external log, cannot read chunks
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, external}, {size, {100,No}}]),
- ?line {error, {badarg, continuation}} = disk_log:chunk(n, 'begin'),
- ?line {error, {format_external, n}} = disk_log:chunk(n, start),
- ?line Error2 = {error, {not_internal_wrap, n}} =
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, external}, {size, {100,No}}]),
+ {error, {badarg, continuation}} = disk_log:chunk(n, 'begin'),
+ {error, {format_external, n}} = disk_log:chunk(n, start),
+ Error2 = {error, {not_internal_wrap, n}} =
disk_log:chunk_step(n, start, 1),
- ?line "The requested" ++ _ = format_error(Error2),
- ?line ok = disk_log:close(n),
- ?line del(File, No),
+ "The requested" ++ _ = format_error(Error2),
+ ok = disk_log:close(n),
+ del(File, No),
%% wrap, read_write
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, internal}, {size, {100,No}}]),
- ?line ok = disk_log:log_terms(n, [B,B,B,B]),
- ?line {C1, [_]} = disk_log:chunk(n, start),
- ?line {C2, [_]} = disk_log:chunk(n, C1),
- ?line {C3, [_]} = disk_log:chunk(n, C2),
- ?line {C4, [_]} = disk_log:chunk(n, C3, 1),
- ?line eof = disk_log:chunk(n, C4),
- ?line {C5, [_]} = disk_log:chunk(n, start),
- ?line {ok, C6} = disk_log:chunk_step(n, C5, 1),
- ?line {C7, [_]} = disk_log:chunk(n, C6),
- ?line {ok, C8} = disk_log:chunk_step(n, C7, 1),
- ?line {_, [_]} = disk_log:chunk(n, C8),
- ?line ok = disk_log:close(n),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, internal}, {size, {100,No}}]),
+ ok = disk_log:log_terms(n, [B,B,B,B]),
+ {C1, [_]} = disk_log:chunk(n, start),
+ {C2, [_]} = disk_log:chunk(n, C1),
+ {C3, [_]} = disk_log:chunk(n, C2),
+ {C4, [_]} = disk_log:chunk(n, C3, 1),
+ eof = disk_log:chunk(n, C4),
+ {C5, [_]} = disk_log:chunk(n, start),
+ {ok, C6} = disk_log:chunk_step(n, C5, 1),
+ {C7, [_]} = disk_log:chunk(n, C6),
+ {ok, C8} = disk_log:chunk_step(n, C7, 1),
+ {_, [_]} = disk_log:chunk(n, C8),
+ ok = disk_log:close(n),
%% wrap, read_only
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {mode, read_only},
- {format, internal}, {size, {100,No}}]),
- ?line {CC1, [_]} = disk_log:chunk(n, start),
- ?line {CC2, [_]} = disk_log:chunk(n, CC1),
- ?line {CC3, [_]} = disk_log:chunk(n, CC2),
- ?line {CC4, [_]} = disk_log:chunk(n, CC3, 1),
- ?line eof = disk_log:chunk(n, CC4),
- ?line {CC5, [_]} = disk_log:chunk(n, start),
- ?line {ok, CC6} = disk_log:chunk_step(n, CC5, 1),
- ?line {CC7, [_]} = disk_log:chunk(n, CC6),
- ?line {ok, CC8} = disk_log:chunk_step(n, CC7, 1),
- ?line {_, [_]} = disk_log:chunk(n, CC8),
- ?line ok = disk_log:close(n),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {mode, read_only},
+ {format, internal}, {size, {100,No}}]),
+ {CC1, [_]} = disk_log:chunk(n, start),
+ {CC2, [_]} = disk_log:chunk(n, CC1),
+ {CC3, [_]} = disk_log:chunk(n, CC2),
+ {CC4, [_]} = disk_log:chunk(n, CC3, 1),
+ eof = disk_log:chunk(n, CC4),
+ {CC5, [_]} = disk_log:chunk(n, start),
+ {ok, CC6} = disk_log:chunk_step(n, CC5, 1),
+ {CC7, [_]} = disk_log:chunk(n, CC6),
+ {ok, CC8} = disk_log:chunk_step(n, CC7, 1),
+ {_, [_]} = disk_log:chunk(n, CC8),
+ ok = disk_log:close(n),
%% OTP-3716. A bug: {Error, List} and {Error, List, Bad} could be
%% returned from chunk/2.
%% Magic bytes not OK.
%% File header (8 bytes) OK, item header not OK.
- ?line InvalidFile = add_ext(File, 1),
- ?line crash(InvalidFile, 15),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {mode, read_only},
- {format, internal}, {size, {100,No}}]),
- ?line {_, [], 61} = disk_log:chunk(n, start),
- ?line ok = disk_log:close(n),
+ InvalidFile = add_ext(File, 1),
+ crash(InvalidFile, 15),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {mode, read_only},
+ {format, internal}, {size, {100,No}}]),
+ {_, [], 61} = disk_log:chunk(n, start),
+ ok = disk_log:close(n),
%% read_write...
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, internal}, {size, {100,No}}]),
- ?line Error3 = {error, {corrupt_log_file, Culprit}} =
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, internal}, {size, {100,No}}]),
+ Error3 = {error, {corrupt_log_file, Culprit}} =
disk_log:chunk(n, start),
- ?line "The disk log file" ++ _ = format_error(Error3),
- ?line Culprit = InvalidFile,
- ?line ok = disk_log:close(n),
- ?line del(File, No),
+ "The disk log file" ++ _ = format_error(Error3),
+ Culprit = InvalidFile,
+ ok = disk_log:close(n),
+ del(File, No),
%% Two wrap log files, writing the second one, then reading the first
%% one, where a bogus term resides.
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, internal}, {size, {40,No}}]),
- ?line ok = disk_log:log_terms(n, [{this,is}]), % first file full
- ?line ok = disk_log:log_terms(n, [{some,terms}]), % second file full
- ?line 2 = curf(n),
- ?line BadFile = add_ext(File, 1),
- ?line crash(BadFile, 28), % the _binary_ is now invalid
- ?line {error, {corrupt_log_file, BFile}} = disk_log:chunk(n, start, 1),
- ?line BadFile = BFile,
- ?line ok = disk_log:close(n),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, internal}, {size, {40,No}}]),
+ ok = disk_log:log_terms(n, [{this,is}]), % first file full
+ ok = disk_log:log_terms(n, [{some,terms}]), % second file full
+ 2 = curf(n),
+ BadFile = add_ext(File, 1),
+ crash(BadFile, 28), % the _binary_ is now invalid
+ {error, {corrupt_log_file, BFile}} = disk_log:chunk(n, start, 1),
+ BadFile = BFile,
+ ok = disk_log:close(n),
%% The same, with a halt log.
- ?line file:delete(File), % cleanup
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal}]),
- ?line ok = disk_log:log_terms(n, [{this,is}]),
- ?line ok = disk_log:sync(n),
- ?line crash(File, 28), % the _binary_ is now invalid
- ?line {error, {corrupt_log_file, File2}} = disk_log:chunk(n, start, 1),
- ?line crash(File, 10),
- ?line {error,{corrupt_log_file,_}} = disk_log:bchunk(n, start, 1),
- ?line true = File == File2,
- ?line ok = disk_log:close(n),
- ?line del(File, No),
+ file:delete(File), % cleanup
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal}]),
+ ok = disk_log:log_terms(n, [{this,is}]),
+ ok = disk_log:sync(n),
+ crash(File, 28), % the _binary_ is now invalid
+ {error, {corrupt_log_file, File2}} = disk_log:chunk(n, start, 1),
+ crash(File, 10),
+ {error,{corrupt_log_file,_}} = disk_log:bchunk(n, start, 1),
+ true = File == File2,
+ ok = disk_log:close(n),
+ del(File, No),
%% halt, read_write
- ?line file:delete(File), % cleanup
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal}]),
- ?line ok = disk_log:log_terms(n, [BB,BB,BB,BB]),
- ?line {D1, [Ch1]} = disk_log:chunk(n, start, 1),
- ?line Ch1 = BB,
- ?line {D2, [Ch2]} = disk_log:chunk(n, D1, 1),
- ?line Ch2 = BB,
- ?line {D3, [Ch3]} = disk_log:chunk(n, D2, 1),
- ?line Ch3 = BB,
- ?line {D4, [Ch4]} = disk_log:chunk(n, D3, 1),
- ?line Ch4 = BB,
- ?line eof = disk_log:chunk(n, D4),
- ?line ok = disk_log:close(n),
+ file:delete(File), % cleanup
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal}]),
+ ok = disk_log:log_terms(n, [BB,BB,BB,BB]),
+ {D1, [Ch1]} = disk_log:chunk(n, start, 1),
+ Ch1 = BB,
+ {D2, [Ch2]} = disk_log:chunk(n, D1, 1),
+ Ch2 = BB,
+ {D3, [Ch3]} = disk_log:chunk(n, D2, 1),
+ Ch3 = BB,
+ {D4, [Ch4]} = disk_log:chunk(n, D3, 1),
+ Ch4 = BB,
+ eof = disk_log:chunk(n, D4),
+ ok = disk_log:close(n),
%% halt, read_only
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal},{mode,read_only}]),
- ?line {E1, [Ch5]} = disk_log:chunk(n, start, 1),
- ?line Ch5 = BB,
- ?line {E2, [Ch6]} = disk_log:chunk(n, E1, 1),
- ?line Ch6 = BB,
- ?line {E3, [Ch7]} = disk_log:chunk(n, E2, 1),
- ?line Ch7 = BB,
- ?line {E4, [Ch8]} = disk_log:chunk(n, E3, 1),
- ?line Ch8 = BB,
- ?line eof = disk_log:chunk(n, E4),
- ?line ok = disk_log:close(n),
- ?line file:delete(File), % cleanup
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal},{mode,read_only}]),
+ {E1, [Ch5]} = disk_log:chunk(n, start, 1),
+ Ch5 = BB,
+ {E2, [Ch6]} = disk_log:chunk(n, E1, 1),
+ Ch6 = BB,
+ {E3, [Ch7]} = disk_log:chunk(n, E2, 1),
+ Ch7 = BB,
+ {E4, [Ch8]} = disk_log:chunk(n, E3, 1),
+ Ch8 = BB,
+ eof = disk_log:chunk(n, E4),
+ ok = disk_log:close(n),
+ file:delete(File), % cleanup
%% More than 64 kB term.
- ?line BBB = term_to_binary(lists:duplicate(66000,$a)),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal}]),
- ?line ok = disk_log:log_terms(n, [BBB]),
- ?line {F1, [BBB1]} = disk_log:chunk(n, start),
- ?line BBB1 = BBB,
- ?line eof = disk_log:chunk(n, F1),
- ?line ok = disk_log:close(n),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal}, {mode, read_only}]),
- ?line {F1r, [BBB2]} = disk_log:chunk(n, start),
- ?line BBB2 = BBB,
- ?line eof = disk_log:chunk(n, F1r),
- ?line ok = disk_log:close(n),
-
- ?line truncate(File, 8192),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal}]),
- ?line {error, {corrupt_log_file, _}} = disk_log:chunk(n, start),
- ?line ok = disk_log:close(n),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal}, {mode, read_only}]),
- ?line {K1, [], 8176} = disk_log:chunk(n, start),
- ?line eof = disk_log:chunk(n, K1),
- ?line ok = disk_log:close(n),
- ?line file:delete(File), % cleanup
+ BBB = term_to_binary(lists:duplicate(66000,$a)),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal}]),
+ ok = disk_log:log_terms(n, [BBB]),
+ {F1, [BBB1]} = disk_log:chunk(n, start),
+ BBB1 = BBB,
+ eof = disk_log:chunk(n, F1),
+ ok = disk_log:close(n),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal}, {mode, read_only}]),
+ {F1r, [BBB2]} = disk_log:chunk(n, start),
+ BBB2 = BBB,
+ eof = disk_log:chunk(n, F1r),
+ ok = disk_log:close(n),
+
+ truncate(File, 8192),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal}]),
+ {error, {corrupt_log_file, _}} = disk_log:chunk(n, start),
+ ok = disk_log:close(n),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal}, {mode, read_only}]),
+ {K1, [], 8176} = disk_log:chunk(n, start),
+ eof = disk_log:chunk(n, K1),
+ ok = disk_log:close(n),
+ file:delete(File), % cleanup
%% OTP-3716. A bug: eof in the middle of the last element is not ok.
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal}]),
- ?line ok = disk_log:log_terms(n, [B,BB]),
- ?line ok = disk_log:close(n),
- ?line truncate(File, 80),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal}]),
- ?line {G1, [_]} = disk_log:chunk(n, start, 1),
- ?line {error, {corrupt_log_file, _}} = disk_log:chunk(n, G1, 1),
- ?line ok = disk_log:close(n),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal}, {mode, read_only}]),
- ?line {G1r, [_]} = disk_log:chunk(n, start, 1),
- ?line {_, [], 4} = disk_log:chunk(n, G1r, 1),
- ?line ok = disk_log:close(n),
- ?line file:delete(File), % cleanup
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal}]),
+ ok = disk_log:log_terms(n, [B,BB]),
+ ok = disk_log:close(n),
+ truncate(File, 80),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal}]),
+ {G1, [_]} = disk_log:chunk(n, start, 1),
+ {error, {corrupt_log_file, _}} = disk_log:chunk(n, G1, 1),
+ ok = disk_log:close(n),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal}, {mode, read_only}]),
+ {G1r, [_]} = disk_log:chunk(n, start, 1),
+ {_, [], 4} = disk_log:chunk(n, G1r, 1),
+ ok = disk_log:close(n),
+ file:delete(File), % cleanup
%% Opening a wrap log read-only. The second of four terms is destroyed.
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, internal}, {size, {4000,No}}]),
- ?line ok = disk_log:log_terms(n,
- [{this,is},{some,terms},{on,a},{wrap,file}]),
- ?line ok = disk_log:close(n),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, internal}, {mode, read_only}]),
- ?line CrashFile = add_ext(File, 1),
- ?line crash(CrashFile, 51), % the binary term {some,terms} is now bad
- ?line {H1, [{this,is}], 18} = disk_log:chunk(n, start, 10),
- ?line {H2, [{on,a},{wrap,file}]} = disk_log:chunk(n, H1),
- ?line eof = disk_log:chunk(n, H2),
- ?line ok = disk_log:close(n),
- ?line del(File, No),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, internal}, {size, {4000,No}}]),
+ ok = disk_log:log_terms(n,
+ [{this,is},{some,terms},{on,a},{wrap,file}]),
+ ok = disk_log:close(n),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, internal}, {mode, read_only}]),
+ CrashFile = add_ext(File, 1),
+ crash(CrashFile, 51), % the binary term {some,terms} is now bad
+ {H1, [{this,is}], 18} = disk_log:chunk(n, start, 10),
+ {H2, [{on,a},{wrap,file}]} = disk_log:chunk(n, H1),
+ eof = disk_log:chunk(n, H2),
+ ok = disk_log:close(n),
+ del(File, No),
%% The same as last, but with a halt log.
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal}, {mode, read_write}]),
- ?line ok = disk_log:alog_terms(n, [{this,is},{some,terms}]),
- ?line ok = disk_log:log_terms(n, [{on,a},{halt,file}]),
- ?line ok = disk_log:close(n),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal}, {mode, read_only}]),
- ?line crash(File, 51), % the binary term {some,terms} is now bad
- ?line {J1, [{this,is}], 18} = disk_log:chunk(n, start, 10),
- ?line {J2, [{on,a},{halt,file}]} = disk_log:chunk(n, J1),
- ?line eof = disk_log:chunk(n, J2),
- ?line ok = disk_log:close(n),
- ?line file:delete(File),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal}, {mode, read_write}]),
+ ok = disk_log:alog_terms(n, [{this,is},{some,terms}]),
+ ok = disk_log:log_terms(n, [{on,a},{halt,file}]),
+ ok = disk_log:close(n),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal}, {mode, read_only}]),
+ crash(File, 51), % the binary term {some,terms} is now bad
+ {J1, [{this,is}], 18} = disk_log:chunk(n, start, 10),
+ {J2, [{on,a},{halt,file}]} = disk_log:chunk(n, J1),
+ eof = disk_log:chunk(n, J2),
+ ok = disk_log:close(n),
+ file:delete(File),
%% OTP-7641. Same as last one, but the size of the bad term is
%% less than ?HEADERSz (8) bytes.
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal}, {mode, read_write}]),
- ?line ok = disk_log:alog_terms(n, [{this,is},{s}]),
- ?line ok = disk_log:log_terms(n, [{on,a},{halt,file}]),
- ?line ok = disk_log:close(n),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal}, {mode, read_only}]),
- ?line crash(File, 44), % the binary term {s} is now bad
- ?line {J11, [{this,is}], 7} = disk_log:chunk(n, start, 10),
- ?line {J21, [{on,a},{halt,file}]} = disk_log:chunk(n, J11),
- ?line eof = disk_log:chunk(n, J21),
- ?line ok = disk_log:close(n),
- ?line file:delete(File),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal}, {mode, read_write}]),
+ ok = disk_log:alog_terms(n, [{this,is},{s}]),
+ ok = disk_log:log_terms(n, [{on,a},{halt,file}]),
+ ok = disk_log:close(n),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal}, {mode, read_only}]),
+ crash(File, 44), % the binary term {s} is now bad
+ {J11, [{this,is}], 7} = disk_log:chunk(n, start, 10),
+ {J21, [{on,a},{halt,file}]} = disk_log:chunk(n, J11),
+ eof = disk_log:chunk(n, J21),
+ ok = disk_log:close(n),
+ file:delete(File),
%% Minimal MD5-proctected term, and maximal unprotected term.
%% A chunk ends in the middle of the MD5-sum.
- ?line MD5term = mk_bytes(64*1024-8),
- ?line NotMD5term = mk_bytes((64*1024-8)-1),
- ?line Term2 = mk_bytes((64*1024-8)-16),
- ?line MD5L = [MD5term,NotMD5term,Term2,MD5term,MD5term,NotMD5term],
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal}]),
- ?line ok = disk_log:log_terms(n, MD5L),
- ?line true = MD5L == get_all_terms(n),
- ?line ok = disk_log:close(n),
- ?line true = MD5L == get_all_terms(n, File, halt),
- ?line crash(File, 21), % the MD5-sum of the first term is now bad
- ?line true = {tl(MD5L),64*1024-8} == get_all_terms_and_bad(n, File, halt),
- ?line {_,64*1024-8} = get_all_binary_terms_and_bad(n, File, halt),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal}]),
- ?line {error, {corrupt_log_file, _}} = disk_log:chunk(n, start),
- ?line ok = disk_log:close(n),
- ?line file:delete(File),
+ MD5term = mk_bytes(64*1024-8),
+ NotMD5term = mk_bytes((64*1024-8)-1),
+ Term2 = mk_bytes((64*1024-8)-16),
+ MD5L = [MD5term,NotMD5term,Term2,MD5term,MD5term,NotMD5term],
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal}]),
+ ok = disk_log:log_terms(n, MD5L),
+ true = MD5L == get_all_terms(n),
+ ok = disk_log:close(n),
+ true = MD5L == get_all_terms(n, File, halt),
+ crash(File, 21), % the MD5-sum of the first term is now bad
+ true = {tl(MD5L),64*1024-8} == get_all_terms_and_bad(n, File, halt),
+ {_,64*1024-8} = get_all_binary_terms_and_bad(n, File, halt),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {format, internal}]),
+ {error, {corrupt_log_file, _}} = disk_log:chunk(n, start),
+ ok = disk_log:close(n),
+ file:delete(File),
%% A file with "old" terms (magic word is MAGICINT).
DataDir = ?datadir(Conf),
OldTermsFileOrig = filename:join(DataDir, "old_terms.LOG"),
OldTermsFile = filename:join(Dir, "old_terms.LOG"),
- ?line copy_file(OldTermsFileOrig, OldTermsFile),
- ?line {[_,_,_,_],0} = get_all_terms_and_bad(n, OldTermsFile, halt),
- ?line {ok, n} = disk_log:open([{name, n}, {file, OldTermsFile},
- {type, halt}, {format, internal}]),
- ?line [_,_,_,_] = get_all_terms(n),
- ?line ok = disk_log:close(n),
- ?line file:delete(OldTermsFile),
+ copy_file(OldTermsFileOrig, OldTermsFile),
+ {[_,_,_,_],0} = get_all_terms_and_bad(n, OldTermsFile, halt),
+ {ok, n} = disk_log:open([{name, n}, {file, OldTermsFile},
+ {type, halt}, {format, internal}]),
+ [_,_,_,_] = get_all_terms(n),
+ ok = disk_log:close(n),
+ file:delete(OldTermsFile),
ok.
-error_index(suite) -> [];
-error_index(doc) ->
- ["OTP-5558. Keep the contents of index files after disk crash."];
+%% OTP-5558. Keep the contents of index files after disk crash.
error_index(Conf) when is_list(Conf) ->
- ?line Dir = ?privdir(Conf),
+ Dir = ?privdir(Conf),
- ?line File = filename:join(Dir, "n.LOG"),
- ?line IdxFile = File ++ ".idx",
- ?line No = 4,
- ?line file:delete(File),
- ?line del(File, No), % cleanup
+ File = filename:join(Dir, "n.LOG"),
+ IdxFile = File ++ ".idx",
+ No = 4,
+ file:delete(File),
+ del(File, No), % cleanup
Args = [{name,n},{type,wrap},{size,{100,No}},{file,File}],
- ?line {ok, n} = disk_log:open(Args),
- ?line ok = disk_log:close(n),
- ?line Q = qlen(),
+ {ok, n} = disk_log:open(Args),
+ ok = disk_log:close(n),
+ Q = qlen(),
P0 = pps(),
- ?line ok = file:write_file(IdxFile, <<"abc">>),
- ?line {error, {invalid_index_file, _}} = disk_log:open(Args),
- ?line {error, {invalid_index_file, _}} = disk_log:open(Args),
- ?line {error, {invalid_index_file, _}} = disk_log:open(Args),
-
- ?line del(File, No),
- ?line true = (P0 == pps()),
- ?line true = (Q == qlen()),
+ ok = file:write_file(IdxFile, <<"abc">>),
+ {error, {invalid_index_file, _}} = disk_log:open(Args),
+ {error, {invalid_index_file, _}} = disk_log:open(Args),
+ {error, {invalid_index_file, _}} = disk_log:open(Args),
+
+ del(File, No),
+ true = (P0 == pps()),
+ true = (Q == qlen()),
ok.
-
-truncate(suite) -> [];
-truncate(doc) ->
- ["Test truncate/1 on halt and wrap logs."];
+
+%% Test truncate/1 on halt and wrap logs.
truncate(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
- ?line Q = qlen(),
+ Q = qlen(),
Halt = join(Dir, "halt.LOG"),
- % Halt logs.
-
- ?line file:delete(Halt), % cleanup
- ?line {ok, halt} = disk_log:open([{name, halt}, {type, halt}, {file, Halt},
- {head, header}, {notify, true}]),
- ?line infinity = sz(halt),
- ?line ok = disk_log:truncate(halt, tjohej),
- ?line rec(1, {disk_log, node(), halt, {truncated, 1}}),
- ?line ok = disk_log:change_size(halt, 10000),
- ?line 10000 = sz(halt),
- ?line disk_log:close(halt),
- ?line [tjohej] = get_all_terms(halt, Halt, halt),
- ?line file:delete(Halt),
-
- ?line {ok, halt} = disk_log:open([{name, halt}, {type, halt}, {file, Halt},
- {head, header}, {notify, true}]),
- ?line ok = disk_log:truncate(halt),
- ?line rec(1, {disk_log, node(), halt, {truncated, 1}}),
- ?line disk_log:close(halt),
- ?line [header] = get_all_terms(halt, Halt, halt),
- ?line file:delete(Halt),
-
- ?line {ok, halt} = disk_log:open([{name, halt}, {type, halt},
- {file, Halt}, {format, external},
- {head, "header"}, {notify, false}]),
- ?line ok = disk_log:btruncate(halt, "apa"),
- ?line disk_log:close(halt),
- ?line 3 = file_size(Halt),
- ?line file:delete(Halt),
-
+ %% Halt logs.
+
+ file:delete(Halt), % cleanup
+ {ok, halt} = disk_log:open([{name, halt}, {type, halt}, {file, Halt},
+ {head, header}, {notify, true}]),
+ infinity = sz(halt),
+ ok = disk_log:truncate(halt, tjohej),
+ rec(1, {disk_log, node(), halt, {truncated, 1}}),
+ ok = disk_log:change_size(halt, 10000),
+ 10000 = sz(halt),
+ disk_log:close(halt),
+ [tjohej] = get_all_terms(halt, Halt, halt),
+ file:delete(Halt),
+
+ {ok, halt} = disk_log:open([{name, halt}, {type, halt}, {file, Halt},
+ {head, header}, {notify, true}]),
+ ok = disk_log:truncate(halt),
+ rec(1, {disk_log, node(), halt, {truncated, 1}}),
+ disk_log:close(halt),
+ [header] = get_all_terms(halt, Halt, halt),
+ file:delete(Halt),
+
+ {ok, halt} = disk_log:open([{name, halt}, {type, halt},
+ {file, Halt}, {format, external},
+ {head, "header"}, {notify, false}]),
+ ok = disk_log:btruncate(halt, "apa"),
+ disk_log:close(halt),
+ 3 = file_size(Halt),
+ file:delete(Halt),
+
%% Wrap logs.
- ?line File = filename:join(Dir, "n.LOG"),
- ?line No = 4,
- ?line B = mk_bytes(60),
- ?line del(File, No), % cleanup
+ File = filename:join(Dir, "n.LOG"),
+ No = 4,
+ B = mk_bytes(60),
+ del(File, No), % cleanup
%% Internal with header.
- ?line Size = {100, No},
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {head, header}, {notify, true},
- {size, Size}]),
- ?line ok = disk_log:log_terms(n, [B,B,B]),
+ Size = {100, No},
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {head, header}, {notify, true},
+ {size, Size}]),
+ ok = disk_log:log_terms(n, [B,B,B]),
%% Used to be one message, but now one per wrapped file.
- ?line rec(2, {disk_log, node(), n, {wrap, 0}}),
- ?line ok = disk_log:truncate(n, apa),
- ?line rec(1, {disk_log, node(), n, {truncated, 6}}),
- ?line {0, 0} = no_overflows(n),
- ?line 23 = curb(n),
- ?line 1 = curf(n),
- ?line 1 = cur_cnt(n),
- ?line true = (Size == sz(n)),
-
- ?line ok = disk_log:log_terms(n, [B, B]),
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line ok = disk_log:close(n),
- ?line [apa, _, header, _] = get_all_terms(n, File, wrap),
- ?line del(File, No),
-
+ rec(2, {disk_log, node(), n, {wrap, 0}}),
+ ok = disk_log:truncate(n, apa),
+ rec(1, {disk_log, node(), n, {truncated, 6}}),
+ {0, 0} = no_overflows(n),
+ 23 = curb(n),
+ 1 = curf(n),
+ 1 = cur_cnt(n),
+ true = (Size == sz(n)),
+
+ ok = disk_log:log_terms(n, [B, B]),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ ok = disk_log:close(n),
+ [apa, _, header, _] = get_all_terms(n, File, wrap),
+ del(File, No),
+
%% Internal without general header.
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {notify, true},
- {size, {100, No}}]),
- ?line ok = disk_log:log_terms(n, [B,B,B]),
- ?line rec(2, {disk_log, node(), n, {wrap, 0}}),
- ?line ok = disk_log:truncate(n, apa),
- ?line rec(1, {disk_log, node(), n, {truncated, 3}}),
- ?line {0, 0} = no_overflows(n),
- ?line 23 = curb(n),
- ?line 1 = curf(n),
- ?line 1 = cur_cnt(n),
- ?line true = (Size == sz(n)),
-
- ?line ok = disk_log:log_terms(n, [B, B]),
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line ok = disk_log:close(n),
- ?line [apa, _, _] = get_all_terms(n, File, wrap),
- ?line del(File, No),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {notify, true},
+ {size, {100, No}}]),
+ ok = disk_log:log_terms(n, [B,B,B]),
+ rec(2, {disk_log, node(), n, {wrap, 0}}),
+ ok = disk_log:truncate(n, apa),
+ rec(1, {disk_log, node(), n, {truncated, 3}}),
+ {0, 0} = no_overflows(n),
+ 23 = curb(n),
+ 1 = curf(n),
+ 1 = cur_cnt(n),
+ true = (Size == sz(n)),
+
+ ok = disk_log:log_terms(n, [B, B]),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ ok = disk_log:close(n),
+ [apa, _, _] = get_all_terms(n, File, wrap),
+ del(File, No),
%% Internal without any header.
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {notify, true},
- {size, {100, No}}]),
- ?line ok = disk_log:log_terms(n, [B,B,B]),
- ?line rec(2, {disk_log, node(), n, {wrap, 0}}),
- ?line ok = disk_log:truncate(n),
- ?line rec(1, {disk_log, node(), n, {truncated, 3}}),
- ?line {0, 0} = no_overflows(n),
- ?line 8 = curb(n),
- ?line 1 = curf(n),
- ?line 0 = cur_cnt(n),
- ?line true = (Size == sz(n)),
-
- ?line ok = disk_log:log_terms(n, [B, B]),
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line ok = disk_log:close(n),
- ?line [_, _] = get_all_terms(n, File, wrap),
- ?line del(File, No),
- ?line Q = qlen(),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {notify, true},
+ {size, {100, No}}]),
+ ok = disk_log:log_terms(n, [B,B,B]),
+ rec(2, {disk_log, node(), n, {wrap, 0}}),
+ ok = disk_log:truncate(n),
+ rec(1, {disk_log, node(), n, {truncated, 3}}),
+ {0, 0} = no_overflows(n),
+ 8 = curb(n),
+ 1 = curf(n),
+ 0 = cur_cnt(n),
+ true = (Size == sz(n)),
+
+ ok = disk_log:log_terms(n, [B, B]),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ ok = disk_log:close(n),
+ [_, _] = get_all_terms(n, File, wrap),
+ del(File, No),
+ Q = qlen(),
ok.
-many_users(suite) -> [];
-many_users(doc) ->
- ["Test many users logging and sync:ing at the same time."];
+%% Test many users logging and sync:ing at the same time.
many_users(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
N = 100,
@@ -3199,32 +3114,32 @@ many_users(Conf) when is_list(Conf) ->
Fun1 = fun(Name, Pid, I) -> disk_log:log(Name, {Pid, I}) end,
Fun2 = fun(Name, Pid, I) -> ok = disk_log:log(Name, {Pid, I}),
disk_log:sync(Name) end,
- ?line {C1, T1} = many(Fun2, NoClients, N, halt, internal, infinity, Dir),
- ?line true = lists:duplicate(NoClients, ok) == C1,
- ?line true = length(T1) == N*NoClients,
- ?line {C2, T2} = many(Fun1, NoClients, N, halt, internal, 1000, Dir),
- ?line true = lists:duplicate(NoClients, {error, {full,"log.LOG"}}) == C2,
- ?line true = length(T2) > 0,
- ?line {C3, T3} = many(Fun2, NoClients, N, wrap, internal,
- {300*NoClients,200}, Dir),
- ?line true = lists:duplicate(NoClients, ok) == C3,
- ?line true = length(T3) == N*NoClients,
+ {C1, T1} = many(Fun2, NoClients, N, halt, internal, infinity, Dir),
+ true = lists:duplicate(NoClients, ok) == C1,
+ true = length(T1) == N*NoClients,
+ {C2, T2} = many(Fun1, NoClients, N, halt, internal, 1000, Dir),
+ true = lists:duplicate(NoClients, {error, {full,"log.LOG"}}) == C2,
+ true = length(T2) > 0,
+ {C3, T3} = many(Fun2, NoClients, N, wrap, internal,
+ {300*NoClients,200}, Dir),
+ true = lists:duplicate(NoClients, ok) == C3,
+ true = length(T3) == N*NoClients,
ok.
many(Fun, NoClients, N, Type, Format, Size, Dir) ->
Name = "log.LOG",
File = filename:join(Dir, Name),
del_files(Size, File),
- ?line Q = qlen(),
- ?line {ok, _} = disk_log:open([{name,Name}, {type,Type}, {size,Size},
- {format,Format}, {file,File}]),
- ?line Pids = spawn_clients(NoClients, client, [self(), Name, N, Fun]),
- ?line Checked = check_clients(Pids),
- ?line ok = disk_log:close(Name),
- ?line Terms = get_all_terms(Name, File, Type),
- ?line del_files(Size, File),
- ?line Q = qlen(),
- ?line {Checked, Terms}.
+ Q = qlen(),
+ {ok, _} = disk_log:open([{name,Name}, {type,Type}, {size,Size},
+ {format,Format}, {file,File}]),
+ Pids = spawn_clients(NoClients, client, [self(), Name, N, Fun]),
+ Checked = check_clients(Pids),
+ ok = disk_log:close(Name),
+ Terms = get_all_terms(Name, File, Type),
+ del_files(Size, File),
+ Q = qlen(),
+ {Checked, Terms}.
spawn_clients(0, _F, _A) ->
[];
@@ -3251,211 +3166,208 @@ del_files(_Size, File) ->
-info_current(suite) -> [];
-info_current(doc) ->
- ["Test no_current_{bytes, items} as returned by info/0."];
+%% Test no_current_{bytes, items} as returned by info/0.
info_current(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
- ?line File = filename:join(Dir, "n.LOG"),
+ File = filename:join(Dir, "n.LOG"),
No = 4,
B = mk_bytes(60),
BB = mk_bytes(160), % bigger than a single wrap log file
SB = mk_bytes(10), % much smaller than a single wrap log file
- ?line del(File, No),% cleanup
+ del(File, No),% cleanup
- ?line Q = qlen(),
+ Q = qlen(),
%% Internal with header.
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {head, header}, {size, {100,No}}]),
- ?line {26, 1} = {curb(n), cur_cnt(n)},
- ?line {1, 1} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:log(n, B),
- ?line {94, 2} = {curb(n), cur_cnt(n)},
- ?line {2, 2} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:close(n),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {notify, true},
- {head, header}, {size, {100,No}}]),
- ?line {94, 2} = {curb(n), cur_cnt(n)},
- ?line {0, 2} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:log(n, B),
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line {94, 2} = {curb(n), cur_cnt(n)},
- ?line {2, 4} = {no_written_items(n), no_items(n)},
- ?line disk_log:inc_wrap_file(n),
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line {26, 1} = {curb(n), cur_cnt(n)},
- ?line {3, 4} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:log_terms(n, [B,B,B]),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {head, header}, {size, {100,No}}]),
+ {26, 1} = {curb(n), cur_cnt(n)},
+ {1, 1} = {no_written_items(n), no_items(n)},
+ ok = disk_log:log(n, B),
+ {94, 2} = {curb(n), cur_cnt(n)},
+ {2, 2} = {no_written_items(n), no_items(n)},
+ ok = disk_log:close(n),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {notify, true},
+ {head, header}, {size, {100,No}}]),
+ {94, 2} = {curb(n), cur_cnt(n)},
+ {0, 2} = {no_written_items(n), no_items(n)},
+ ok = disk_log:log(n, B),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ {94, 2} = {curb(n), cur_cnt(n)},
+ {2, 4} = {no_written_items(n), no_items(n)},
+ disk_log:inc_wrap_file(n),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ {26, 1} = {curb(n), cur_cnt(n)},
+ {3, 4} = {no_written_items(n), no_items(n)},
+ ok = disk_log:log_terms(n, [B,B,B]),
%% Used to be one message, but now one per wrapped file.
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line rec(1, {disk_log, node(), n, {wrap, 2}}),
- ?line {94, 2} = {curb(n), cur_cnt(n)},
- ?line {8, 7} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:log_terms(n, [B]),
- ?line rec(1, {disk_log, node(), n, {wrap, 2}}),
- ?line ok = disk_log:log_terms(n, [B]),
- ?line rec(1, {disk_log, node(), n, {wrap, 2}}),
- ?line {94, 2} = {curb(n), cur_cnt(n)},
- ?line {12, 7} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:log_terms(n, [BB,BB]),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ rec(1, {disk_log, node(), n, {wrap, 2}}),
+ {94, 2} = {curb(n), cur_cnt(n)},
+ {8, 7} = {no_written_items(n), no_items(n)},
+ ok = disk_log:log_terms(n, [B]),
+ rec(1, {disk_log, node(), n, {wrap, 2}}),
+ ok = disk_log:log_terms(n, [B]),
+ rec(1, {disk_log, node(), n, {wrap, 2}}),
+ {94, 2} = {curb(n), cur_cnt(n)},
+ {12, 7} = {no_written_items(n), no_items(n)},
+ ok = disk_log:log_terms(n, [BB,BB]),
%% Used to be one message, but now one per wrapped file.
- ?line rec(2, {disk_log, node(), n, {wrap, 2}}),
- ?line {194, 2} = {curb(n), cur_cnt(n)},
- ?line {16, 7} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:log_terms(n, [SB,SB,SB]),
- ?line rec(1, {disk_log, node(), n, {wrap, 2}}),
- ?line {80, 4} = {curb(n), cur_cnt(n)},
- ?line {20, 9} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:close(n),
- ?line del(File, No),
+ rec(2, {disk_log, node(), n, {wrap, 2}}),
+ {194, 2} = {curb(n), cur_cnt(n)},
+ {16, 7} = {no_written_items(n), no_items(n)},
+ ok = disk_log:log_terms(n, [SB,SB,SB]),
+ rec(1, {disk_log, node(), n, {wrap, 2}}),
+ {80, 4} = {curb(n), cur_cnt(n)},
+ {20, 9} = {no_written_items(n), no_items(n)},
+ ok = disk_log:close(n),
+ del(File, No),
%% Internal without header.
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {size, {100,No}}]),
- ?line {8, 0} = {curb(n), cur_cnt(n)},
- ?line {0, 0} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:log(n, B),
- ?line {76, 1} = {curb(n), cur_cnt(n)},
- ?line {1, 1} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:close(n),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {notify, true}, {size, {100,No}}]),
- ?line {76, 1} = {curb(n), cur_cnt(n)},
- ?line {0, 1} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:log(n, B),
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line {76, 1} = {curb(n), cur_cnt(n)},
- ?line {1, 2} = {no_written_items(n), no_items(n)},
- ?line disk_log:inc_wrap_file(n),
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line {8, 0} = {curb(n), cur_cnt(n)},
- ?line {1, 2} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:log_terms(n, [B,B,B]),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {size, {100,No}}]),
+ {8, 0} = {curb(n), cur_cnt(n)},
+ {0, 0} = {no_written_items(n), no_items(n)},
+ ok = disk_log:log(n, B),
+ {76, 1} = {curb(n), cur_cnt(n)},
+ {1, 1} = {no_written_items(n), no_items(n)},
+ ok = disk_log:close(n),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {notify, true}, {size, {100,No}}]),
+ {76, 1} = {curb(n), cur_cnt(n)},
+ {0, 1} = {no_written_items(n), no_items(n)},
+ ok = disk_log:log(n, B),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ {76, 1} = {curb(n), cur_cnt(n)},
+ {1, 2} = {no_written_items(n), no_items(n)},
+ disk_log:inc_wrap_file(n),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ {8, 0} = {curb(n), cur_cnt(n)},
+ {1, 2} = {no_written_items(n), no_items(n)},
+ ok = disk_log:log_terms(n, [B,B,B]),
%% Used to be one message, but now one per wrapped file.
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line rec(1, {disk_log, node(), n, {wrap, 1}}),
- ?line {76, 1} = {curb(n), cur_cnt(n)},
- ?line {4, 4} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:log_terms(n, [B]),
- ?line rec(1, {disk_log, node(), n, {wrap, 1}}),
- ?line ok = disk_log:log_terms(n, [B]),
- ?line rec(1, {disk_log, node(), n, {wrap, 1}}),
- ?line {76, 1} = {curb(n), cur_cnt(n)},
- ?line {6, 4} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:log_terms(n, [BB,BB]),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ rec(1, {disk_log, node(), n, {wrap, 1}}),
+ {76, 1} = {curb(n), cur_cnt(n)},
+ {4, 4} = {no_written_items(n), no_items(n)},
+ ok = disk_log:log_terms(n, [B]),
+ rec(1, {disk_log, node(), n, {wrap, 1}}),
+ ok = disk_log:log_terms(n, [B]),
+ rec(1, {disk_log, node(), n, {wrap, 1}}),
+ {76, 1} = {curb(n), cur_cnt(n)},
+ {6, 4} = {no_written_items(n), no_items(n)},
+ ok = disk_log:log_terms(n, [BB,BB]),
%% Used to be one message, but now one per wrapped file.
- ?line rec(2, {disk_log, node(), n, {wrap, 1}}),
- ?line {176, 1} = {curb(n), cur_cnt(n)},
- ?line {8, 4} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:log_terms(n, [SB,SB,SB]),
- ?line rec(1, {disk_log, node(), n, {wrap, 1}}),
- ?line {62, 3} = {curb(n), cur_cnt(n)},
- ?line {11, 6} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:close(n),
- ?line del(File, No),
+ rec(2, {disk_log, node(), n, {wrap, 1}}),
+ {176, 1} = {curb(n), cur_cnt(n)},
+ {8, 4} = {no_written_items(n), no_items(n)},
+ ok = disk_log:log_terms(n, [SB,SB,SB]),
+ rec(1, {disk_log, node(), n, {wrap, 1}}),
+ {62, 3} = {curb(n), cur_cnt(n)},
+ {11, 6} = {no_written_items(n), no_items(n)},
+ ok = disk_log:close(n),
+ del(File, No),
%% External with header.
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, external}, {head, "header"},
- {size, {100,No}}]),
- ?line {6, 1} = {curb(n), cur_cnt(n)},
- ?line {1, 1} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:blog(n, B),
- ?line {62, 2} = {curb(n), cur_cnt(n)},
- ?line {2, 2} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:close(n),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, external}, {head, "header"},
- {notify, true}, {size, {100,No}}]),
- ?line {62, 2} = {curb(n), cur_cnt(n)},
- ?line {0, 2} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:blog(n, B),
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line {62, 2} = {curb(n), cur_cnt(n)},
- ?line {2, 4} = {no_written_items(n), no_items(n)},
- ?line disk_log:inc_wrap_file(n),
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line {6, 1} = {curb(n), cur_cnt(n)},
- ?line {3, 4} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:blog_terms(n, [B,B,B]),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, external}, {head, "header"},
+ {size, {100,No}}]),
+ {6, 1} = {curb(n), cur_cnt(n)},
+ {1, 1} = {no_written_items(n), no_items(n)},
+ ok = disk_log:blog(n, B),
+ {62, 2} = {curb(n), cur_cnt(n)},
+ {2, 2} = {no_written_items(n), no_items(n)},
+ ok = disk_log:close(n),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, external}, {head, "header"},
+ {notify, true}, {size, {100,No}}]),
+ {62, 2} = {curb(n), cur_cnt(n)},
+ {0, 2} = {no_written_items(n), no_items(n)},
+ ok = disk_log:blog(n, B),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ {62, 2} = {curb(n), cur_cnt(n)},
+ {2, 4} = {no_written_items(n), no_items(n)},
+ disk_log:inc_wrap_file(n),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ {6, 1} = {curb(n), cur_cnt(n)},
+ {3, 4} = {no_written_items(n), no_items(n)},
+ ok = disk_log:blog_terms(n, [B,B,B]),
%% Used to be one message, but now one per wrapped file.
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line rec(1, {disk_log, node(), n, {wrap, 2}}),
- ?line {62, 2} = {curb(n), cur_cnt(n)},
- ?line {8, 7} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:blog_terms(n, [B]),
- ?line rec(1, {disk_log, node(), n, {wrap, 2}}),
- ?line ok = disk_log:blog_terms(n, [B]),
- ?line rec(1, {disk_log, node(), n, {wrap, 2}}),
- ?line {62, 2} = {curb(n), cur_cnt(n)},
- ?line {12, 7} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:blog_terms(n, [BB,BB]),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ rec(1, {disk_log, node(), n, {wrap, 2}}),
+ {62, 2} = {curb(n), cur_cnt(n)},
+ {8, 7} = {no_written_items(n), no_items(n)},
+ ok = disk_log:blog_terms(n, [B]),
+ rec(1, {disk_log, node(), n, {wrap, 2}}),
+ ok = disk_log:blog_terms(n, [B]),
+ rec(1, {disk_log, node(), n, {wrap, 2}}),
+ {62, 2} = {curb(n), cur_cnt(n)},
+ {12, 7} = {no_written_items(n), no_items(n)},
+ ok = disk_log:blog_terms(n, [BB,BB]),
%% Used to be one message, but now one per wrapped file.
- ?line rec(2, {disk_log, node(), n, {wrap, 2}}),
- ?line {162, 2} = {curb(n), cur_cnt(n)},
- ?line {16, 7} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:blog_terms(n, [SB,SB,SB]),
-
- ?line rec(1, {disk_log, node(), n, {wrap, 2}}),
- ?line {24, 4} = {curb(n), cur_cnt(n)},
- ?line {20, 9} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:close(n),
- ?line del(File, No),
+ rec(2, {disk_log, node(), n, {wrap, 2}}),
+ {162, 2} = {curb(n), cur_cnt(n)},
+ {16, 7} = {no_written_items(n), no_items(n)},
+ ok = disk_log:blog_terms(n, [SB,SB,SB]),
+
+ rec(1, {disk_log, node(), n, {wrap, 2}}),
+ {24, 4} = {curb(n), cur_cnt(n)},
+ {20, 9} = {no_written_items(n), no_items(n)},
+ ok = disk_log:close(n),
+ del(File, No),
%% External without header.
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {format, external}, {size, {100,No}}]),
- ?line {0, 0} = {curb(n), cur_cnt(n)},
- ?line {0, 0} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:blog(n, B),
- ?line {56, 1} = {curb(n), cur_cnt(n)},
- ?line {1, 1} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:close(n),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
- {notify, true},
- {format, external}, {size, {100,No}}]),
- ?line {56, 1} = {curb(n), cur_cnt(n)},
- ?line {0, 1} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:blog(n, B),
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line {56, 1} = {curb(n), cur_cnt(n)},
- ?line {1, 2} = {no_written_items(n), no_items(n)},
- ?line disk_log:inc_wrap_file(n),
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line {0, 0} = {curb(n), cur_cnt(n)},
- ?line {1, 2} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:blog_terms(n, [B,B,B]),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {format, external}, {size, {100,No}}]),
+ {0, 0} = {curb(n), cur_cnt(n)},
+ {0, 0} = {no_written_items(n), no_items(n)},
+ ok = disk_log:blog(n, B),
+ {56, 1} = {curb(n), cur_cnt(n)},
+ {1, 1} = {no_written_items(n), no_items(n)},
+ ok = disk_log:close(n),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {notify, true},
+ {format, external}, {size, {100,No}}]),
+ {56, 1} = {curb(n), cur_cnt(n)},
+ {0, 1} = {no_written_items(n), no_items(n)},
+ ok = disk_log:blog(n, B),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ {56, 1} = {curb(n), cur_cnt(n)},
+ {1, 2} = {no_written_items(n), no_items(n)},
+ disk_log:inc_wrap_file(n),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ {0, 0} = {curb(n), cur_cnt(n)},
+ {1, 2} = {no_written_items(n), no_items(n)},
+ ok = disk_log:blog_terms(n, [B,B,B]),
%% Used to be one message, but now one per wrapped file.
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line rec(1, {disk_log, node(), n, {wrap, 1}}),
- ?line {56, 1} = {curb(n), cur_cnt(n)},
- ?line {4, 4} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:blog_terms(n, [B]),
- ?line rec(1, {disk_log, node(), n, {wrap, 1}}),
- ?line ok = disk_log:blog_terms(n, [B]),
- ?line rec(1, {disk_log, node(), n, {wrap, 1}}),
- ?line {56, 1} = {curb(n), cur_cnt(n)},
- ?line {6, 4} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:blog_terms(n, [BB,BB]),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ rec(1, {disk_log, node(), n, {wrap, 1}}),
+ {56, 1} = {curb(n), cur_cnt(n)},
+ {4, 4} = {no_written_items(n), no_items(n)},
+ ok = disk_log:blog_terms(n, [B]),
+ rec(1, {disk_log, node(), n, {wrap, 1}}),
+ ok = disk_log:blog_terms(n, [B]),
+ rec(1, {disk_log, node(), n, {wrap, 1}}),
+ {56, 1} = {curb(n), cur_cnt(n)},
+ {6, 4} = {no_written_items(n), no_items(n)},
+ ok = disk_log:blog_terms(n, [BB,BB]),
%% Used to be one message, but now one per wrapped file.
- ?line rec(2, {disk_log, node(), n, {wrap, 1}}),
- ?line {156, 1} = {curb(n), cur_cnt(n)},
- ?line {8, 4} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:blog_terms(n, [SB,SB,SB]),
- ?line rec(1, {disk_log, node(), n, {wrap, 1}}),
- ?line {18, 3} = {curb(n), cur_cnt(n)},
- ?line {11, 6} = {no_written_items(n), no_items(n)},
- ?line ok = disk_log:close(n),
- ?line del(File, No),
-
- ?line Q = qlen(),
+ rec(2, {disk_log, node(), n, {wrap, 1}}),
+ {156, 1} = {curb(n), cur_cnt(n)},
+ {8, 4} = {no_written_items(n), no_items(n)},
+ ok = disk_log:blog_terms(n, [SB,SB,SB]),
+ rec(1, {disk_log, node(), n, {wrap, 1}}),
+ {18, 3} = {curb(n), cur_cnt(n)},
+ {11, 6} = {no_written_items(n), no_items(n)},
+ ok = disk_log:close(n),
+ del(File, No),
+
+ Q = qlen(),
ok.
-change_size_before(suite) -> [];
change_size_before(doc) ->
["Change size of a wrap log file before we have reached "
"to the file index corresponding to the new size"];
@@ -3478,138 +3390,136 @@ change_size_before(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
del(File, 5),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File},
- {type, wrap}, {size, {100,5}}]),
- ?line disk_log:log(a, Log_1_1),
- ?line disk_log:log(a, Log_1_2),
- ?line disk_log:log(a, Log_2_1),
- ?line disk_log:log(a, Log_2_2),
- ?line disk_log:change_size(a, {100, 3}),
- ?line [Log_1_1, Log_1_2,
- Log_2_1, Log_2_2] = get_all_terms(a),
- ?line disk_log:log(a, Log_3_1),
- ?line disk_log:log(a, Log_3_2),
- ?line disk_log:log(a, Log_1_2_1),
- ?line disk_log:log(a, Log_1_2_2),
- ?line [Log_2_1, Log_2_2,
- Log_3_1, Log_3_2,
- Log_1_2_1, Log_1_2_2] = get_all_terms(a),
-
- ?line disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
- {size, {100,3}}]),
- ?line [Log_2_1, Log_2_2,
- Log_3_1, Log_3_2,
- Log_1_2_1, Log_1_2_2] = get_all_terms(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File},
+ {type, wrap}, {size, {100,5}}]),
+ disk_log:log(a, Log_1_1),
+ disk_log:log(a, Log_1_2),
+ disk_log:log(a, Log_2_1),
+ disk_log:log(a, Log_2_2),
+ disk_log:change_size(a, {100, 3}),
+ [Log_1_1, Log_1_2,
+ Log_2_1, Log_2_2] = get_all_terms(a),
+ disk_log:log(a, Log_3_1),
+ disk_log:log(a, Log_3_2),
+ disk_log:log(a, Log_1_2_1),
+ disk_log:log(a, Log_1_2_2),
+ [Log_2_1, Log_2_2,
+ Log_3_1, Log_3_2,
+ Log_1_2_1, Log_1_2_2] = get_all_terms(a),
+
+ disk_log:close(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
+ {size, {100,3}}]),
+ [Log_2_1, Log_2_2,
+ Log_3_1, Log_3_2,
+ Log_1_2_1, Log_1_2_2] = get_all_terms(a),
disk_log:close(a),
del(File, 5),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
- {size, {60,5}}, {format, external}]),
- ?line disk_log:blog(a, Log_1_1),
- ?line disk_log:blog(a, Log_1_2),
- ?line disk_log:blog(a, Log_2_1),
- ?line disk_log:blog(a, Log_2_2),
- ?line disk_log:change_size(a, {60, 3}),
- ?line ok = disk_log:sync(a),
- ?line {ok, Fd1} = file:open(File ++ ".1", [read]),
- ?line Log11_12 = Log_1_1 ++ Log_1_2,
- ?line {ok,Log11_12} = file:read(Fd1, 200),
- ?line ok = file:close(Fd1),
- ?line {ok, Fd2} = file:open(File ++ ".2", [read]),
-% ?t:format(0, "~p~n",[file:read(Fd2, 200)]),
- ?line Log21_22 = Log_2_1 ++ Log_2_2,
- ?line {ok,Log21_22} = file:read(Fd2, 200),
- ?line ok = file:close(Fd2),
- ?line disk_log:blog(a, Log_3_1),
- ?line disk_log:blog(a, Log_3_2),
- ?line disk_log:blog(a, Log_1_2_1),
- ?line disk_log:blog(a, Log_1_2_2),
- ?line ok = disk_log:sync(a),
- ?line {ok, Fd2a} = file:open(File ++ ".2", [read]),
- ?line {ok,Log21_22} = file:read(Fd2a, 200),
- ?line ok = file:close(Fd2a),
- ?line {ok, Fd3a} = file:open(File ++ ".3", [read]),
- ?line Log31_32 = Log_3_1 ++ Log_3_2,
- ?line {ok,Log31_32} = file:read(Fd3a, 200),
- ?line ok = file:close(Fd3a),
- ?line {ok, Fd1a} = file:open(File ++ ".1", [read]),
- ?line Log121_122 = Log_1_2_1 ++ Log_1_2_2,
- ?line {ok,Log121_122} = file:read(Fd1a, 200),
- ?line ok = file:close(Fd1a),
-
- ?line disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
- {size, {60,3}}, {format, external}]),
- ?line {ok, Fd2b} = file:open(File ++ ".2", [read]),
- ?line {ok,Log21_22} = file:read(Fd2b, 200),
- ?line ok = file:close(Fd2b),
- ?line {ok, Fd3b} = file:open(File ++ ".3", [read]),
- ?line {ok,Log31_32} = file:read(Fd3b, 200),
- ?line ok = file:close(Fd3b),
- ?line {ok, Fd1b} = file:open(File ++ ".1", [read]),
- ?line {ok,Log121_122} = file:read(Fd1b, 200),
- ?line ok = file:close(Fd1b),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
+ {size, {60,5}}, {format, external}]),
+ disk_log:blog(a, Log_1_1),
+ disk_log:blog(a, Log_1_2),
+ disk_log:blog(a, Log_2_1),
+ disk_log:blog(a, Log_2_2),
+ disk_log:change_size(a, {60, 3}),
+ ok = disk_log:sync(a),
+ {ok, Fd1} = file:open(File ++ ".1", [read]),
+ Log11_12 = Log_1_1 ++ Log_1_2,
+ {ok,Log11_12} = file:read(Fd1, 200),
+ ok = file:close(Fd1),
+ {ok, Fd2} = file:open(File ++ ".2", [read]),
+ Log21_22 = Log_2_1 ++ Log_2_2,
+ {ok,Log21_22} = file:read(Fd2, 200),
+ ok = file:close(Fd2),
+ disk_log:blog(a, Log_3_1),
+ disk_log:blog(a, Log_3_2),
+ disk_log:blog(a, Log_1_2_1),
+ disk_log:blog(a, Log_1_2_2),
+ ok = disk_log:sync(a),
+ {ok, Fd2a} = file:open(File ++ ".2", [read]),
+ {ok,Log21_22} = file:read(Fd2a, 200),
+ ok = file:close(Fd2a),
+ {ok, Fd3a} = file:open(File ++ ".3", [read]),
+ Log31_32 = Log_3_1 ++ Log_3_2,
+ {ok,Log31_32} = file:read(Fd3a, 200),
+ ok = file:close(Fd3a),
+ {ok, Fd1a} = file:open(File ++ ".1", [read]),
+ Log121_122 = Log_1_2_1 ++ Log_1_2_2,
+ {ok,Log121_122} = file:read(Fd1a, 200),
+ ok = file:close(Fd1a),
+
+ disk_log:close(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
+ {size, {60,3}}, {format, external}]),
+ {ok, Fd2b} = file:open(File ++ ".2", [read]),
+ {ok,Log21_22} = file:read(Fd2b, 200),
+ ok = file:close(Fd2b),
+ {ok, Fd3b} = file:open(File ++ ".3", [read]),
+ {ok,Log31_32} = file:read(Fd3b, 200),
+ ok = file:close(Fd3b),
+ {ok, Fd1b} = file:open(File ++ ".1", [read]),
+ {ok,Log121_122} = file:read(Fd1b, 200),
+ ok = file:close(Fd1b),
disk_log:close(a),
del(File, 5),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,5}}]),
- ?line disk_log:log(a, Log_1_1),
- ?line disk_log:log(a, Log_1_2),
- ?line disk_log:log(a, Log_2_1),
- ?line disk_log:log(a, Log_2_2),
- ?line disk_log:change_size(a, {60, 3}),
- ?line [Log_1_1, Log_1_2,
- Log_2_1, Log_2_2] = get_all_terms(a),
- ?line disk_log:log(a, Log_3_1),
- ?line disk_log:log(a, Log_1_2_1),
- ?line [Log_2_1, Log_2_2,
- Log_3_1,
- Log_1_2_1] = get_all_terms(a),
-
- ?line disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {60,3}}]),
- ?line [Log_2_1, Log_2_2,
- Log_3_1,
- Log_1_2_1] = get_all_terms(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,5}}]),
+ disk_log:log(a, Log_1_1),
+ disk_log:log(a, Log_1_2),
+ disk_log:log(a, Log_2_1),
+ disk_log:log(a, Log_2_2),
+ disk_log:change_size(a, {60, 3}),
+ [Log_1_1, Log_1_2,
+ Log_2_1, Log_2_2] = get_all_terms(a),
+ disk_log:log(a, Log_3_1),
+ disk_log:log(a, Log_1_2_1),
+ [Log_2_1, Log_2_2,
+ Log_3_1,
+ Log_1_2_1] = get_all_terms(a),
+
+ disk_log:close(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {60,3}}]),
+ [Log_2_1, Log_2_2,
+ Log_3_1,
+ Log_1_2_1] = get_all_terms(a),
disk_log:close(a),
del(File, 5),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {60, 3}}]),
- ?line disk_log:log(a, Log_1_1),
- ?line disk_log:log(a, Log_2_1),
- ?line disk_log:change_size(a, {100, 5}),
- ?line [Log_1_1,
- Log_2_1] = get_all_terms(a),
- ?line disk_log:log(a, Log_2_2),
- ?line disk_log:log(a, Log_3_1),
- ?line disk_log:log(a, Log_3_2),
- ?line disk_log:log(a, Log_4_1),
- ?line disk_log:log(a, Log_4_2),
- ?line disk_log:log(a, Log_5_1),
- ?line disk_log:log(a, Log_5_2),
- ?line disk_log:log(a, Log_1_2_1),
- ?line [Log_2_1, Log_2_2,
- Log_3_1, Log_3_2,
- Log_4_1, Log_4_2,
- Log_5_1, Log_5_2,
- Log_1_2_1] = get_all_terms(a),
-
- ?line disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100, 5}}]),
- ?line [Log_2_1, Log_2_2,
- Log_3_1, Log_3_2,
- Log_4_1, Log_4_2,
- Log_5_1, Log_5_2,
- Log_1_2_1] = get_all_terms(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {60, 3}}]),
+ disk_log:log(a, Log_1_1),
+ disk_log:log(a, Log_2_1),
+ disk_log:change_size(a, {100, 5}),
+ [Log_1_1,
+ Log_2_1] = get_all_terms(a),
+ disk_log:log(a, Log_2_2),
+ disk_log:log(a, Log_3_1),
+ disk_log:log(a, Log_3_2),
+ disk_log:log(a, Log_4_1),
+ disk_log:log(a, Log_4_2),
+ disk_log:log(a, Log_5_1),
+ disk_log:log(a, Log_5_2),
+ disk_log:log(a, Log_1_2_1),
+ [Log_2_1, Log_2_2,
+ Log_3_1, Log_3_2,
+ Log_4_1, Log_4_2,
+ Log_5_1, Log_5_2,
+ Log_1_2_1] = get_all_terms(a),
+
+ disk_log:close(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100, 5}}]),
+ [Log_2_1, Log_2_2,
+ Log_3_1, Log_3_2,
+ Log_4_1, Log_4_2,
+ Log_5_1, Log_5_2,
+ Log_1_2_1] = get_all_terms(a),
disk_log:close(a),
del(File, 5).
-change_size_during(suite) -> [];
-change_size_during(doc) -> ["Change size of a wrap log file while logging "
- "to a file index between the old and the new size"];
+%% Change size of a wrap log file while logging to a file index
+%% between the old and the new size.
change_size_during(Conf) when is_list(Conf) ->
Log_1_1 = "first log first message",
@@ -3633,114 +3543,111 @@ change_size_during(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,5}}]),
- ?line disk_log:log(a, Log_1_1),
- ?line disk_log:log(a, Log_1_2),
- ?line disk_log:log(a, Log_2_1),
- ?line disk_log:log(a, Log_2_2),
- ?line disk_log:log(a, Log_3_1),
- ?line disk_log:log(a, Log_3_2),
- ?line disk_log:log(a, Log_4_1),
- ?line disk_log:log(a, Log_4_2),
- ?line disk_log:log(a, Log_5_1),
- ?line disk_log:log(a, Log_5_2),
- ?line disk_log:log(a, Log_1_1),
- ?line disk_log:log(a, Log_1_2),
- ?line disk_log:log(a, Log_2_1),
- ?line disk_log:log(a, Log_2_2),
- ?line disk_log:log(a, Log_3_1),
- ?line disk_log:log(a, Log_3_2),
- ?line disk_log:log(a, Log_4_1),
- ?line disk_log:log(a, Log_4_2),
- ?line disk_log:change_size(a, {100, 3}),
- ?line [Log_5_1, Log_5_2,
- Log_1_1, Log_1_2,
- Log_2_1, Log_2_2,
- Log_3_1, Log_3_2,
- Log_4_1, Log_4_2] = get_all_terms(a),
- ?line disk_log:log(a, Log_1_2_1),
- ?line disk_log:log(a, Log_1_2_2),
- ?line [Log_2_1, Log_2_2,
- Log_3_1, Log_3_2,
- Log_4_1, Log_4_2,
- Log_1_2_1, Log_1_2_2] = get_all_terms(a),
-
- ?line disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,3}}]),
- ?line [Log_2_1, Log_2_2,
- Log_3_1, Log_3_2,
- Log_4_1, Log_4_2,
- Log_1_2_1, Log_1_2_2] = get_all_terms(a),
- ?line disk_log:log(a, Log_2_2_1),
- ?line disk_log:log(a, Log_2_2_2),
- ?line disk_log:log(a, Log_3_2_1),
- ?line disk_log:log(a, Log_3_2_2),
- ?line disk_log:log(a, Log_1_3_1),
- ?line disk_log:log(a, Log_1_3_2),
- ?line [Log_2_2_1, Log_2_2_2,
- Log_3_2_1, Log_3_2_2,
- Log_1_3_1, Log_1_3_2] = get_all_terms(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,5}}]),
+ disk_log:log(a, Log_1_1),
+ disk_log:log(a, Log_1_2),
+ disk_log:log(a, Log_2_1),
+ disk_log:log(a, Log_2_2),
+ disk_log:log(a, Log_3_1),
+ disk_log:log(a, Log_3_2),
+ disk_log:log(a, Log_4_1),
+ disk_log:log(a, Log_4_2),
+ disk_log:log(a, Log_5_1),
+ disk_log:log(a, Log_5_2),
+ disk_log:log(a, Log_1_1),
+ disk_log:log(a, Log_1_2),
+ disk_log:log(a, Log_2_1),
+ disk_log:log(a, Log_2_2),
+ disk_log:log(a, Log_3_1),
+ disk_log:log(a, Log_3_2),
+ disk_log:log(a, Log_4_1),
+ disk_log:log(a, Log_4_2),
+ disk_log:change_size(a, {100, 3}),
+ [Log_5_1, Log_5_2,
+ Log_1_1, Log_1_2,
+ Log_2_1, Log_2_2,
+ Log_3_1, Log_3_2,
+ Log_4_1, Log_4_2] = get_all_terms(a),
+ disk_log:log(a, Log_1_2_1),
+ disk_log:log(a, Log_1_2_2),
+ [Log_2_1, Log_2_2,
+ Log_3_1, Log_3_2,
+ Log_4_1, Log_4_2,
+ Log_1_2_1, Log_1_2_2] = get_all_terms(a),
+
disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,3}}]),
- ?line [Log_2_2_1, Log_2_2_2,
- Log_3_2_1, Log_3_2_2,
- Log_1_3_1, Log_1_3_2] = get_all_terms(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,3}}]),
+ [Log_2_1, Log_2_2,
+ Log_3_1, Log_3_2,
+ Log_4_1, Log_4_2,
+ Log_1_2_1, Log_1_2_2] = get_all_terms(a),
+ disk_log:log(a, Log_2_2_1),
+ disk_log:log(a, Log_2_2_2),
+ disk_log:log(a, Log_3_2_1),
+ disk_log:log(a, Log_3_2_2),
+ disk_log:log(a, Log_1_3_1),
+ disk_log:log(a, Log_1_3_2),
+ [Log_2_2_1, Log_2_2_2,
+ Log_3_2_1, Log_3_2_2,
+ Log_1_3_1, Log_1_3_2] = get_all_terms(a),
+ disk_log:close(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,3}}]),
+ [Log_2_2_1, Log_2_2_2,
+ Log_3_2_1, Log_3_2_2,
+ Log_1_3_1, Log_1_3_2] = get_all_terms(a),
disk_log:close(a),
del(File, 5),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,5}}]),
- ?line disk_log:log(a, Log_1_1),
- ?line disk_log:log(a, Log_1_2),
- ?line disk_log:log(a, Log_2_1),
- ?line disk_log:log(a, Log_2_2),
- ?line disk_log:log(a, Log_3_1),
- ?line disk_log:log(a, Log_3_2),
- ?line disk_log:log(a, Log_4_1),
- ?line disk_log:log(a, Log_4_2),
- ?line disk_log:log(a, Log_5_1),
- ?line disk_log:log(a, Log_5_2),
- ?line disk_log:log(a, Log_1_1),
- ?line disk_log:log(a, Log_1_2),
- ?line disk_log:log(a, Log_2_1),
- ?line disk_log:log(a, Log_2_2),
- ?line disk_log:log(a, Log_3_1),
- ?line disk_log:log(a, Log_3_2),
- ?line disk_log:log(a, Log_4_1),
- ?line disk_log:log(a, Log_4_2),
- ?line disk_log:log(a, Log_5_1),
- ?line disk_log:log(a, Log_5_2),
- ?line disk_log:change_size(a, {100, 3}),
- ?line [Log_1_1, Log_1_2,
- Log_2_1, Log_2_2,
- Log_3_1, Log_3_2,
- Log_4_1, Log_4_2,
- Log_5_1, Log_5_2] = get_all_terms(a),
- ?line disk_log:log(a, Log_1_2_1),
- ?line disk_log:log(a, Log_1_2_2),
- ?line disk_log:log(a, Log_2_2_1),
- ?line disk_log:log(a, Log_2_2_2),
- ?line disk_log:log(a, Log_3_2_1),
- ?line disk_log:log(a, Log_3_2_2),
- ?line disk_log:log(a, Log_1_3_1),
- ?line disk_log:log(a, Log_1_3_2),
- ?line [Log_2_2_1, Log_2_2_2,
- Log_3_2_1, Log_3_2_2,
- Log_1_3_1, Log_1_3_2] = get_all_terms(a),
-
- ?line disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,3}}]),
- ?line [Log_2_2_1, Log_2_2_2,
- Log_3_2_1, Log_3_2_2,
- Log_1_3_1, Log_1_3_2] = get_all_terms(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,5}}]),
+ disk_log:log(a, Log_1_1),
+ disk_log:log(a, Log_1_2),
+ disk_log:log(a, Log_2_1),
+ disk_log:log(a, Log_2_2),
+ disk_log:log(a, Log_3_1),
+ disk_log:log(a, Log_3_2),
+ disk_log:log(a, Log_4_1),
+ disk_log:log(a, Log_4_2),
+ disk_log:log(a, Log_5_1),
+ disk_log:log(a, Log_5_2),
+ disk_log:log(a, Log_1_1),
+ disk_log:log(a, Log_1_2),
+ disk_log:log(a, Log_2_1),
+ disk_log:log(a, Log_2_2),
+ disk_log:log(a, Log_3_1),
+ disk_log:log(a, Log_3_2),
+ disk_log:log(a, Log_4_1),
+ disk_log:log(a, Log_4_2),
+ disk_log:log(a, Log_5_1),
+ disk_log:log(a, Log_5_2),
+ disk_log:change_size(a, {100, 3}),
+ [Log_1_1, Log_1_2,
+ Log_2_1, Log_2_2,
+ Log_3_1, Log_3_2,
+ Log_4_1, Log_4_2,
+ Log_5_1, Log_5_2] = get_all_terms(a),
+ disk_log:log(a, Log_1_2_1),
+ disk_log:log(a, Log_1_2_2),
+ disk_log:log(a, Log_2_2_1),
+ disk_log:log(a, Log_2_2_2),
+ disk_log:log(a, Log_3_2_1),
+ disk_log:log(a, Log_3_2_2),
+ disk_log:log(a, Log_1_3_1),
+ disk_log:log(a, Log_1_3_2),
+ [Log_2_2_1, Log_2_2_2,
+ Log_3_2_1, Log_3_2_2,
+ Log_1_3_1, Log_1_3_2] = get_all_terms(a),
+
+ disk_log:close(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}, {size, {100,3}}]),
+ [Log_2_2_1, Log_2_2_2,
+ Log_3_2_1, Log_3_2_2,
+ Log_1_3_1, Log_1_3_2] = get_all_terms(a),
disk_log:close(a),
del(File, 5).
-change_size_after(suite) -> [];
-change_size_after(doc) ->
- ["Change size of a wrap log file before we have reached "
- "(on the second round) "
- "to the file index corresponding to the new size"];
+%% Change size of a wrap log file before we have reached (on the
+%% second round) to the file index corresponding to the new size.
change_size_after(Conf) when is_list(Conf) ->
Log_1_1 = "first log first message",
@@ -3758,172 +3665,169 @@ change_size_after(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "a.LOG"),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
- {size, {100,5}}]),
- ?line disk_log:log(a, Log_1_1),
- ?line disk_log:log(a, Log_1_2),
- ?line disk_log:log(a, Log_2_1),
- ?line disk_log:log(a, Log_2_2),
- ?line disk_log:log(a, Log_3_1),
- ?line disk_log:log(a, Log_3_2),
- ?line disk_log:log(a, Log_4_1),
- ?line disk_log:log(a, Log_4_2),
- ?line disk_log:log(a, Log_5_1),
- ?line disk_log:log(a, Log_5_2),
- ?line disk_log:log(a, Log_1_1),
- ?line disk_log:log(a, Log_1_2),
- ?line disk_log:log(a, Log_2_1),
- ?line disk_log:log(a, Log_2_2),
- ?line disk_log:change_size(a, {100, 3}),
- ?line [Log_3_1,Log_3_2,
- Log_4_1, Log_4_2,
- Log_5_1, Log_5_2,
- Log_1_1, Log_1_2,
- Log_2_1, Log_2_2] = get_all_terms(a),
- ?line disk_log:log(a, Log_3_1),
- ?line disk_log:log(a, Log_3_2),
- ?line disk_log:log(a, Log_1_2_1),
- ?line disk_log:log(a, Log_1_2_2),
- ?line [Log_2_1, Log_2_2,
- Log_3_1, Log_3_2,
- Log_1_2_1, Log_1_2_2] = get_all_terms(a),
-
- ?line disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
- {size, {100,3}}]),
- ?line [Log_2_1, Log_2_2,
- Log_3_1, Log_3_2,
- Log_1_2_1, Log_1_2_2] = get_all_terms(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
+ {size, {100,5}}]),
+ disk_log:log(a, Log_1_1),
+ disk_log:log(a, Log_1_2),
+ disk_log:log(a, Log_2_1),
+ disk_log:log(a, Log_2_2),
+ disk_log:log(a, Log_3_1),
+ disk_log:log(a, Log_3_2),
+ disk_log:log(a, Log_4_1),
+ disk_log:log(a, Log_4_2),
+ disk_log:log(a, Log_5_1),
+ disk_log:log(a, Log_5_2),
+ disk_log:log(a, Log_1_1),
+ disk_log:log(a, Log_1_2),
+ disk_log:log(a, Log_2_1),
+ disk_log:log(a, Log_2_2),
+ disk_log:change_size(a, {100, 3}),
+ [Log_3_1,Log_3_2,
+ Log_4_1, Log_4_2,
+ Log_5_1, Log_5_2,
+ Log_1_1, Log_1_2,
+ Log_2_1, Log_2_2] = get_all_terms(a),
+ disk_log:log(a, Log_3_1),
+ disk_log:log(a, Log_3_2),
+ disk_log:log(a, Log_1_2_1),
+ disk_log:log(a, Log_1_2_2),
+ [Log_2_1, Log_2_2,
+ Log_3_1, Log_3_2,
+ Log_1_2_1, Log_1_2_2] = get_all_terms(a),
+
+ disk_log:close(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
+ {size, {100,3}}]),
+ [Log_2_1, Log_2_2,
+ Log_3_1, Log_3_2,
+ Log_1_2_1, Log_1_2_2] = get_all_terms(a),
disk_log:close(a),
del(File, 5),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
- {size, {100,5}}]),
- ?line disk_log:log(a, Log_1_1),
- ?line disk_log:log(a, Log_1_2),
- ?line disk_log:log(a, Log_2_1),
- ?line disk_log:log(a, Log_2_2),
- ?line disk_log:log(a, Log_3_1),
- ?line disk_log:log(a, Log_3_2),
- ?line disk_log:log(a, Log_4_1),
- ?line disk_log:log(a, Log_4_2),
- ?line disk_log:log(a, Log_5_1),
- ?line disk_log:log(a, Log_5_2),
- ?line disk_log:log(a, Log_1_1),
- ?line disk_log:log(a, Log_1_2),
- ?line disk_log:log(a, Log_2_1),
- ?line disk_log:log(a, Log_2_2),
- ?line disk_log:change_size(a, {60, 3}),
- ?line [Log_3_1,Log_3_2,
- Log_4_1, Log_4_2,
- Log_5_1, Log_5_2,
- Log_1_1, Log_1_2,
- Log_2_1, Log_2_2] = get_all_terms(a),
- ?line disk_log:log(a, Log_3_1),
- ?line disk_log:log(a, Log_1_2_1),
- ?line [Log_2_1, Log_2_2,
- Log_3_1,
- Log_1_2_1] = get_all_terms(a),
-
- ?line disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
- {size, {60,3}}]),
- ?line [Log_2_1, Log_2_2,
- Log_3_1,
- Log_1_2_1] = get_all_terms(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
+ {size, {100,5}}]),
+ disk_log:log(a, Log_1_1),
+ disk_log:log(a, Log_1_2),
+ disk_log:log(a, Log_2_1),
+ disk_log:log(a, Log_2_2),
+ disk_log:log(a, Log_3_1),
+ disk_log:log(a, Log_3_2),
+ disk_log:log(a, Log_4_1),
+ disk_log:log(a, Log_4_2),
+ disk_log:log(a, Log_5_1),
+ disk_log:log(a, Log_5_2),
+ disk_log:log(a, Log_1_1),
+ disk_log:log(a, Log_1_2),
+ disk_log:log(a, Log_2_1),
+ disk_log:log(a, Log_2_2),
+ disk_log:change_size(a, {60, 3}),
+ [Log_3_1,Log_3_2,
+ Log_4_1, Log_4_2,
+ Log_5_1, Log_5_2,
+ Log_1_1, Log_1_2,
+ Log_2_1, Log_2_2] = get_all_terms(a),
+ disk_log:log(a, Log_3_1),
+ disk_log:log(a, Log_1_2_1),
+ [Log_2_1, Log_2_2,
+ Log_3_1,
+ Log_1_2_1] = get_all_terms(a),
+
+ disk_log:close(a),
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
+ {size, {60,3}}]),
+ [Log_2_1, Log_2_2,
+ Log_3_1,
+ Log_1_2_1] = get_all_terms(a),
disk_log:close(a),
del(File, 5).
-default_size(suite) -> [];
-default_size(doc) -> ["Open an existing wrap log without size option "];
+%% Open an existing wrap log without size option .
default_size(Conf) when is_list(Conf) ->
- ?line Dir = ?privdir(Conf),
- ?line File = filename:join(Dir, "a.LOG"),
- ?line {error, {badarg, size}} = disk_log:open([{name,a}, {file, File},
+ Dir = ?privdir(Conf),
+ File = filename:join(Dir, "a.LOG"),
+ {error, {badarg, size}} = disk_log:open([{name,a}, {file, File},
{type, wrap}]),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap},
{size, {100,5}}]),
- ?line disk_log:close(a),
+ disk_log:close(a),
- ?line {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}]),
- ?line {100, 5} = disk_log_1:read_size_file(File),
- ?line ok = disk_log:close(a),
- ?line del(File, 5).
+ {ok, a} = disk_log:open([{name,a}, {file, File}, {type, wrap}]),
+ {100, 5} = disk_log_1:read_size_file(File),
+ ok = disk_log:close(a),
+ del(File, 5).
-change_size2(suite) -> [];
-change_size2(doc) -> ["Testing change_size/2 a bit more..."];
+%% Testing change_size/2 a bit more...
change_size2(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
- ?line File = filename:join(Dir, "n.LOG"),
- ?line No = 4,
- ?line del(File, No), % cleanup
+ File = filename:join(Dir, "n.LOG"),
+ No = 4,
+ del(File, No), % cleanup
%% External halt.
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {size, 100000},
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {size, 100000},
{format, external}, {type, halt}]),
- ?line B = mk_bytes(60), % 56 actually...
- ?line ok = disk_log:blog_terms(n, [B,list_to_binary(B),B]),
- ?line Error1 = {error, {new_size_too_small,n,168}} =
+ B = mk_bytes(60), % 56 actually...
+ ok = disk_log:blog_terms(n, [B,list_to_binary(B),B]),
+ Error1 = {error, {new_size_too_small,n,168}} =
disk_log:change_size(n, 167),
- ?line "The current size" ++ _ = format_error(Error1),
- ?line ok = disk_log:change_size(n, infinity),
- ?line ok = disk_log:change_size(n, 168),
- ?line ok = disk_log:close(n),
- ?line file:delete(File), % cleanup
+ "The current size" ++ _ = format_error(Error1),
+ ok = disk_log:change_size(n, infinity),
+ ok = disk_log:change_size(n, 168),
+ ok = disk_log:close(n),
+ file:delete(File), % cleanup
%% External wrap.
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
{size, {100,No}}, {notify, true},
{format, external}]),
- ?line BB = mk_bytes(160),
- ?line ok = disk_log:blog_terms(n, [BB, BB, BB, BB]), % create all files
+ BB = mk_bytes(160),
+ ok = disk_log:blog_terms(n, [BB, BB, BB, BB]), % create all files
%% Used to be one message, but now one per wrapped file.
- ?line rec(3, {disk_log, node(), n, {wrap, 0}}),
- ?line ok = disk_log:blog_terms(n, [BB, BB]),
+ rec(3, {disk_log, node(), n, {wrap, 0}}),
+ ok = disk_log:blog_terms(n, [BB, BB]),
%% Used to be one message, but now one per wrapped file.
- ?line rec(2, {disk_log, node(), n, {wrap, 1}}),
- ?line ok = disk_log:change_size(n, {100, 2}),
- ?line ok = disk_log:change_size(n, {100, 2}),
- ?line {100, 2} = sz(n),
- ?line ok = disk_log:balog_terms(n, [BB, BB]),
- ?line ok = disk_log:balog_terms(n, [BB]),
- ?line ok = disk_log:blog_terms(n, [BB]),
+ rec(2, {disk_log, node(), n, {wrap, 1}}),
+ ok = disk_log:change_size(n, {100, 2}),
+ ok = disk_log:change_size(n, {100, 2}),
+ {100, 2} = sz(n),
+ ok = disk_log:balog_terms(n, [BB, BB]),
+ ok = disk_log:balog_terms(n, [BB]),
+ ok = disk_log:blog_terms(n, [BB]),
%% Used to be one message, but now one per wrapped file.
- ?line rec(4, {disk_log, node(), n, {wrap, 1}}),
- ?line ok = disk_log:change_size(n, {100, 4}),
- ?line ok = disk_log:close(n),
- ?line del(File, No),
+ rec(4, {disk_log, node(), n, {wrap, 1}}),
+ ok = disk_log:change_size(n, {100, 4}),
+ ok = disk_log:close(n),
+ del(File, No),
%% Internal wrap.
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
{size, {100,No}}, {notify, true},
{format, internal}]),
- ?line ok = disk_log:blog_terms(n, [BB, BB, BB, BB]), % create all files
+ ok = disk_log:blog_terms(n, [BB, BB, BB, BB]), % create all files
%% Used to be one message, but now one per wrapped file.
- ?line rec(3, {disk_log, node(), n, {wrap, 0}}),
- ?line ok = disk_log:blog_terms(n, [BB, BB]),
+ rec(3, {disk_log, node(), n, {wrap, 0}}),
+ ok = disk_log:blog_terms(n, [BB, BB]),
%% Used to be one message, but now one per wrapped file.
- ?line rec(2, {disk_log, node(), n, {wrap, 1}}),
- ?line ok = disk_log:change_size(n, {100, 2}),
- ?line {100, 2} = sz(n),
- ?line ok = disk_log:blog_terms(n, [BB, BB, BB, BB]),
+ rec(2, {disk_log, node(), n, {wrap, 1}}),
+ ok = disk_log:change_size(n, {100, 2}),
+ {100, 2} = sz(n),
+ ok = disk_log:blog_terms(n, [BB, BB, BB, BB]),
%% Used to be one message, but now one per wrapped file.
- ?line rec(4, {disk_log, node(), n, {wrap, 1}}),
- ?line ok = disk_log:close(n),
- ?line del(File, No).
+ rec(4, {disk_log, node(), n, {wrap, 1}}),
+ ok = disk_log:close(n),
+ del(File, No).
-change_size_truncate(suite) -> [];
-change_size_truncate(doc) -> ["OTP-3484: truncating index file"];
+%% OTP-3484: truncating index file.
change_size_truncate(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
- ?line File = filename:join(Dir, "bert.LOG"),
- ?line No = 3,
- ?line B = mk_bytes(60),
+ File = filename:join(Dir, "bert.LOG"),
+ No = 3,
+ B = mk_bytes(60),
%% The problem here is truncation of the index file. One cannot easily
%% check that the index file is correctly updated, but print_index_file()
@@ -3933,541 +3837,527 @@ change_size_truncate(Conf) when is_list(Conf) ->
%% Change the size immediately after creating the log, while there
%% are no log files. This used to write stuff a negative offset
%% from the beginning of the file.
- ?line del(File, No+1),
- ?line {ok, bert} = disk_log:open([{name,bert}, {type,wrap}, {file, File},
+ del(File, No+1),
+ {ok, bert} = disk_log:open([{name,bert}, {type,wrap}, {file, File},
{notify, true}, {size,{1000,255}}]),
- ?line ok = disk_log:change_size(bert,{100,No}),
- ?line ok = disk_log:blog(bert, B),
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 0}}),
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 0}}),
- ?line 3 = curf(bert),
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 1}}),
- ?line 1 = curf(bert),
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 1}}),
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 1}}),
-
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 1}}),
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 1}}),
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 1}}),
-
- % Three items expected.
- % disk_log_1:print_index_file("bert.LOG.idx"),
- ?line 3 = curf(bert),
- ?line ok = disk_log:change_size(bert,{100,1}),
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 1}}),
- % Three items expected.
- % disk_log_1:print_index_file("bert.LOG.idx"),
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 1}}),
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 1}}),
- % One item expected.
- % disk_log_1:print_index_file("bert.LOG.idx"),
-
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 1}}),
- ?line ok = disk_log:close(bert),
- ?line del(File, No),
+ ok = disk_log:change_size(bert,{100,No}),
+ ok = disk_log:blog(bert, B),
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 0}}),
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 0}}),
+ 3 = curf(bert),
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 1}}),
+ 1 = curf(bert),
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 1}}),
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 1}}),
+
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 1}}),
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 1}}),
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 1}}),
+
+ %% Three items expected.
+ %% disk_log_1:print_index_file("bert.LOG.idx"),
+ 3 = curf(bert),
+ ok = disk_log:change_size(bert,{100,1}),
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 1}}),
+ %% Three items expected.
+ %% disk_log_1:print_index_file("bert.LOG.idx"),
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 1}}),
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 1}}),
+ %% One item expected.
+ %% disk_log_1:print_index_file("bert.LOG.idx"),
+
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 1}}),
+ ok = disk_log:close(bert),
+ del(File, No),
%% Part 2.
%% Change the size twice, the second time while the the effects of
%% the first changed have not yet been handled. Finally close before
%% the index file has been truncated.
- ?line del(File, No),
- ?line {ok, bert} = disk_log:open([{name,bert}, {type,wrap}, {file, File},
+ del(File, No),
+ {ok, bert} = disk_log:open([{name,bert}, {type,wrap}, {file, File},
{notify, true}, {size,{100,No}}]),
- ?line ok = disk_log:blog(bert, B),
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 0}}),
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 0}}),
+ ok = disk_log:blog(bert, B),
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 0}}),
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 0}}),
- ?line 3 = curf(bert),
- ?line ok = disk_log:change_size(bert,{100,No-1}),
+ 3 = curf(bert),
+ ok = disk_log:change_size(bert,{100,No-1}),
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 1}}),
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 1}}),
- ?line 1 = curf(bert),
- ?line ok = disk_log:change_size(bert,{100,No+1}),
+ 1 = curf(bert),
+ ok = disk_log:change_size(bert,{100,No+1}),
- % Three items expected.
- % disk_log_1:print_index_file("bert.LOG.idx"),
+ %% Three items expected.
+ %% disk_log_1:print_index_file("bert.LOG.idx"),
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 1}}),
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 1}}),
- % Three items expected.
- % disk_log_1:print_index_file("bert.LOG.idx"),
+ %% Three items expected.
+ %% disk_log_1:print_index_file("bert.LOG.idx"),
- ?line 2 = curf(bert),
- ?line ok = disk_log:change_size(bert,{100,1}),
+ 2 = curf(bert),
+ ok = disk_log:change_size(bert,{100,1}),
- % Three items expected.
- % disk_log_1:print_index_file("bert.LOG.idx"),
+ %% Three items expected.
+ %% disk_log_1:print_index_file("bert.LOG.idx"),
- ?line ok = disk_log:close(bert),
+ ok = disk_log:close(bert),
- % State: .siz is 1, current file is 2, index file size is 3...
+ %% State: .siz is 1, current file is 2, index file size is 3...
- ?line {ok, bert} = disk_log:open([{name,bert}, {file, File},
+ {ok, bert} = disk_log:open([{name,bert}, {file, File},
{type,wrap}, {notify, true}]),
- % Three items expected.
- % disk_log_1:print_index_file("bert.LOG.idx"),
+ %% Three items expected.
+ %% disk_log_1:print_index_file("bert.LOG.idx"),
- ?line 2 = curf(bert),
- ?line ok = disk_log:blog(bert, B),
- ?line rec(1, {disk_log, node(), bert, {wrap, 1}}),
- ?line ok = disk_log:close(bert),
+ 2 = curf(bert),
+ ok = disk_log:blog(bert, B),
+ rec(1, {disk_log, node(), bert, {wrap, 1}}),
+ ok = disk_log:close(bert),
- ?line {ok, bert} = disk_log:open([{name,bert}, {file, File},
+ {ok, bert} = disk_log:open([{name,bert}, {file, File},
{type,wrap}, {notify, true}]),
- % Two items expected.
- % disk_log_1:print_index_file("bert.LOG.idx"),
+ %% Two items expected.
+ %% disk_log_1:print_index_file("bert.LOG.idx"),
- ?line 1 = curf(bert),
- ?line ok = disk_log:blog(bert, B),
+ 1 = curf(bert),
+ ok = disk_log:blog(bert, B),
%% Expect {wrap 0}. Nothing lost now, last wrap notification
%% reported one lost item.
- ?line rec(1, {disk_log, node(), bert, {wrap, 0}}),
+ rec(1, {disk_log, node(), bert, {wrap, 0}}),
- % One item expected.
- % disk_log_1:print_index_file("bert.LOG.idx"),
- ?line ok = disk_log:close(bert),
+ %% One item expected.
+ %% disk_log_1:print_index_file("bert.LOG.idx"),
+ ok = disk_log:close(bert),
- ?line del(File, No),
+ del(File, No),
ok.
-change_attribute(suite) -> [];
-change_attribute(doc) ->
- ["Change notify and head"];
+%% Change notify and head.
change_attribute(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
- ?line File = filename:join(Dir, "n.LOG"),
- ?line No = 4,
- ?line del(File, No), % cleanup
- ?line B = mk_bytes(60),
+ File = filename:join(Dir, "n.LOG"),
+ No = 4,
+ del(File, No), % cleanup
+ B = mk_bytes(60),
- ?line Q = qlen(),
+ Q = qlen(),
- % test change_notify
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ %% test change_notify
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
{size, {100,No}}]),
- ?line {ok, n} = disk_log:open([{name, n}]), % ignored...
- ?line ok = disk_log:log_terms(n, [B,B]),
- ?line {error, {badarg, notify}} = disk_log:change_notify(n, self(), wrong),
- ?line ok = disk_log:change_notify(n, self(), false),
- ?line ok = disk_log:change_notify(n, self(), true),
- ?line Error1 = {error, {not_owner, _}} =
+ {ok, n} = disk_log:open([{name, n}]), % ignored...
+ ok = disk_log:log_terms(n, [B,B]),
+ {error, {badarg, notify}} = disk_log:change_notify(n, self(), wrong),
+ ok = disk_log:change_notify(n, self(), false),
+ ok = disk_log:change_notify(n, self(), true),
+ Error1 = {error, {not_owner, _}} =
disk_log:change_notify(n, none, true),
- ?line "The pid" ++ _ = format_error(Error1),
- ?line 2 = no_written_items(n),
- ?line 0 = users(n),
- ?line Parent = self(),
- ?line Pid = spawn(fun() -> disk_log:close(n), Parent ! {self(),done} end),
- ?line receive {Pid, done} -> ok end,
- ?line 0 = users(n),
- ?line 1 = length(owners(n)),
-
- % test change_header
- ?line {error, {badarg, head}} = disk_log:change_header(n, none),
- ?line {error, {badarg, head}} =
+ "The pid" ++ _ = format_error(Error1),
+ 2 = no_written_items(n),
+ 0 = users(n),
+ Parent = self(),
+ Pid = spawn(fun() -> disk_log:close(n), Parent ! {self(),done} end),
+ receive {Pid, done} -> ok end,
+ 0 = users(n),
+ 1 = length(owners(n)),
+
+ %% test change_header
+ {error, {badarg, head}} = disk_log:change_header(n, none),
+ {error, {badarg, head}} =
disk_log:change_header(n, {head_func, {1,2,3}}),
- ?line ok = disk_log:change_header(n, {head, header}),
- ?line ok = disk_log:log(n, B),
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line 4 = no_written_items(n),
- ?line ok = disk_log:change_header(n, {head, none}),
- ?line ok = disk_log:log(n, B),
- ?line rec(1, {disk_log, node(), n, {wrap, 0}}),
- ?line 5 = no_written_items(n),
- ?line ok = disk_log:change_header(n,
+ ok = disk_log:change_header(n, {head, header}),
+ ok = disk_log:log(n, B),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ 4 = no_written_items(n),
+ ok = disk_log:change_header(n, {head, none}),
+ ok = disk_log:log(n, B),
+ rec(1, {disk_log, node(), n, {wrap, 0}}),
+ 5 = no_written_items(n),
+ ok = disk_log:change_header(n,
{head_func, {?MODULE, head_fun, [{ok,header}]}}),
- ?line ok = disk_log:log(n, B),
- ?line rec(1, {disk_log, node(), n, {wrap, 1}}),
- ?line 7 = no_written_items(n),
- ?line ok = disk_log:close(n),
- ?line {error, no_such_log} = disk_log:close(n),
- ?line del(File, No),
- ?line file:delete(File), % cleanup
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {format, external},
+ ok = disk_log:log(n, B),
+ rec(1, {disk_log, node(), n, {wrap, 1}}),
+ 7 = no_written_items(n),
+ ok = disk_log:close(n),
+ {error, no_such_log} = disk_log:close(n),
+ del(File, No),
+ file:delete(File), % cleanup
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {format, external},
{type, halt}]),
- ?line {error, {badarg, head}} = disk_log:change_header(n, {head, header}),
- ?line ok = disk_log:change_header(n, {head, "header"}),
- ?line ok = disk_log:close(n),
- ?line file:delete(File),
+ {error, {badarg, head}} = disk_log:change_header(n, {head, header}),
+ ok = disk_log:change_header(n, {head, "header"}),
+ ok = disk_log:close(n),
+ file:delete(File),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
{size, {100,No}}]),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
{size, {100,No}}]),
- ?line ok = disk_log:change_notify(n, self(), true),
- ?line ok = disk_log:change_header(n, {head, tjolahopp}),
- ?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
+ ok = disk_log:change_notify(n, self(), true),
+ ok = disk_log:change_header(n, {head, tjolahopp}),
+ {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
{size, {100,No}}, {notify, true}]),
- ?line ok = disk_log:close(n),
- ?line {error, no_such_log} = disk_log:info(n),
- ?line Q = qlen(),
- ?line del(File, No).
+ ok = disk_log:close(n),
+ {error, no_such_log} = disk_log:info(n),
+ Q = qlen(),
+ del(File, No).
-dist_open(suite) -> [];
-dist_open(doc) ->
- ["Open a distributed log"];
+%% Open a distributed log.
dist_open(Conf) when is_list(Conf) ->
- ?line PrivDir = ?privdir(Conf),
- ?line true = is_alive(),
-
- ?line Q = qlen(),
- ?line File = filename:join(PrivDir, "n.LOG"),
- ?line File1 = filename:join(PrivDir, "n1.LOG"),
- ?line No = 3,
- ?line file:delete(File),
- ?line del(File, No), % cleanup
- ?line del(File1, No), % cleanup
- ?line B = mk_bytes(60),
-
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?line {ok, Node} = start_node(disk_log, "-pa " ++ PA),
- ?line wait_for_ready_net(),
+ PrivDir = ?privdir(Conf),
+ true = is_alive(),
+
+ Q = qlen(),
+ File = filename:join(PrivDir, "n.LOG"),
+ File1 = filename:join(PrivDir, "n1.LOG"),
+ No = 3,
+ file:delete(File),
+ del(File, No), % cleanup
+ del(File1, No), % cleanup
+ B = mk_bytes(60),
+
+ PA = filename:dirname(code:which(?MODULE)),
+ {ok, Node} = start_node(disk_log, "-pa " ++ PA),
+ wait_for_ready_net(),
%% open non-distributed on this node:
- ?line {ok,n} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {ok,n} = disk_log:open([{name, n}, {file, File}, {type, halt},
{distributed, []}]),
- ?line Error1 = {error, {halt_log, n}} = disk_log:inc_wrap_file(n),
- ?line "The halt log" ++ _ = format_error(Error1),
- ?line ok = disk_log:lclose(n),
- ?line file:delete(File),
+ Error1 = {error, {halt_log, n}} = disk_log:inc_wrap_file(n),
+ "The halt log" ++ _ = format_error(Error1),
+ ok = disk_log:lclose(n),
+ file:delete(File),
%% open distributed on this node:
- ?line {[_],[]} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {[_],[]} = disk_log:open([{name, n}, {file, File}, {type, halt},
{distributed, [node()]}]),
%% the error message is ignored:
- ?line ok = disk_log:inc_wrap_file(n),
- ?line ok = disk_log:close(n),
- ?line file:delete(File),
+ ok = disk_log:inc_wrap_file(n),
+ ok = disk_log:close(n),
+ file:delete(File),
%% open a wrap log on this node, write something on this node
- ?line {[_],[]} = disk_log:open([{name, n}, {file, File},
+ {[_],[]} = disk_log:open([{name, n}, {file, File},
{type, wrap}, {size, {50, No}},
{distributed, [node()]}]),
- ?line ok = disk_log:log(n, B),
- ?line ok = disk_log:close(n),
+ ok = disk_log:log(n, B),
+ ok = disk_log:close(n),
%% open a wrap log on this node and aother node, write something
- ?line {[_],[]} = disk_log:open([{name, n}, {file, File},
+ {[_],[]} = disk_log:open([{name, n}, {file, File},
{type, wrap}, {size, {50, No}},
{distributed, [node()]}]),
- ?line {[_],[]} = disk_log:open([{name, n}, {file, File1},
+ {[_],[]} = disk_log:open([{name, n}, {file, File1},
{type, wrap}, {size, {50, No}},
{distributed, [Node]}]),
- ?line ok = disk_log:log(n, B),
- ?line ok = rpc:call(Node, disk_log, log, [n, B]),
- ?line ok = disk_log:close(n),
- ?line del(File, No),
- ?line del(File1, No),
- ?line file:delete(File),
+ ok = disk_log:log(n, B),
+ ok = rpc:call(Node, disk_log, log, [n, B]),
+ ok = disk_log:close(n),
+ del(File, No),
+ del(File1, No),
+ file:delete(File),
%% open a wrap log on this node and another node, use lclose
- ?line {[_],[]} = disk_log:open([{name, n}, {file, File},
+ {[_],[]} = disk_log:open([{name, n}, {file, File},
{type, wrap}, {size, {50, No}},
{distributed, [node()]}]),
- ?line {[_],[]} = disk_log:open([{name, n}, {file, File},
+ {[_],[]} = disk_log:open([{name, n}, {file, File},
{type, wrap}, {size, {50, No}},
{distributed, [node()]},
{linkto,none}]),
- ?line {[_],[]} = disk_log:open([{name, n}, {file, File1},
+ {[_],[]} = disk_log:open([{name, n}, {file, File1},
{type, wrap}, {size, {50, No}},
{distributed, [Node]}]),
- ?line [_, _] = distributed(n),
- ?line ok = disk_log:lclose(n, Node),
- ?line [_] = distributed(n),
- ?line ok = disk_log:lclose(n),
- ?line ok = disk_log:lclose(n),
- ?line {error, no_such_log} = disk_log:info(n),
- ?line del(File, No),
- ?line del(File1, No),
- ?line file:delete(File),
-
- % open an invalid log file, and see how error are handled
- ?line First = "n.LOG.1",
- ?line make_file(PrivDir, First, 8),
-
- ?line {[], [_,_]} = disk_log:open([{name, n}, {file, File},
+ [_, _] = distributed(n),
+ ok = disk_log:lclose(n, Node),
+ [_] = distributed(n),
+ ok = disk_log:lclose(n),
+ ok = disk_log:lclose(n),
+ {error, no_such_log} = disk_log:info(n),
+ del(File, No),
+ del(File1, No),
+ file:delete(File),
+
+ %% open an invalid log file, and see how error are handled
+ First = "n.LOG.1",
+ make_file(PrivDir, First, 8),
+
+ {[], [_,_]} = disk_log:open([{name, n}, {file, File},
{type, wrap}, {size, {50, No}},
{distributed, [Node,node()]}]),
- ?line del(File, No),
- ?line file:delete(File),
+ del(File, No),
+ file:delete(File),
- % open a wrap on one other node (not on this node)
- ?line {[_],[]} = disk_log:open([{name, n}, {file, File},
+ %% open a wrap on one other node (not on this node)
+ {[_],[]} = disk_log:open([{name, n}, {file, File},
{type, wrap}, {size, {50, No}},
{distributed, [Node]}]),
- ?line ok = rpc:call(Node, disk_log, log, [n, B]),
- ?line {error, no_such_log} = disk_log:lclose(n),
- ?line ok = disk_log:close(n),
+ ok = rpc:call(Node, disk_log, log, [n, B]),
+ {error, no_such_log} = disk_log:lclose(n),
+ ok = disk_log:close(n),
- ?line Q = qlen(),
+ Q = qlen(),
- ?line {error, no_such_log} = disk_log:info(n),
- ?line del(File, No),
- ?line file:delete(File),
- ?line stop_node(Node),
+ {error, no_such_log} = disk_log:info(n),
+ del(File, No),
+ file:delete(File),
+ stop_node(Node),
ok.
-dist_error_open(suite) -> [];
-dist_error_open(doc) ->
- ["Open a log distributed and not distributed"];
+%% Open a log distributed and not distributed.
dist_error_open(Conf) when is_list(Conf) ->
- ?line PrivDir = ?privdir(Conf),
- ?line true = is_alive(),
-
- ?line Q = qlen(),
- ?line File = filename:join(PrivDir, "bert.LOG"),
- ?line File1 = filename:join(PrivDir, "bert1.LOG"),
- ?line No = 3,
- ?line file:delete(File),
- ?line del(File, No), % cleanup
- ?line del(File1, No), % cleanup
-
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?line {ok, Node} = start_node(disk_log, "-pa " ++ PA),
- ?line wait_for_ready_net(),
-
- % open non-distributed on this node:
- ?line {ok,n} = disk_log:open([{name, n}, {file, File},
+ PrivDir = ?privdir(Conf),
+ true = is_alive(),
+
+ Q = qlen(),
+ File = filename:join(PrivDir, "bert.LOG"),
+ File1 = filename:join(PrivDir, "bert1.LOG"),
+ No = 3,
+ file:delete(File),
+ del(File, No), % cleanup
+ del(File1, No), % cleanup
+
+ PA = filename:dirname(code:which(?MODULE)),
+ {ok, Node} = start_node(disk_log, "-pa " ++ PA),
+ wait_for_ready_net(),
+
+ %% open non-distributed on this node:
+ {ok,n} = disk_log:open([{name, n}, {file, File},
{type, wrap}, {size, {50, No}}]),
- % trying to open distributed on this node (error):
- ?line {[],[Error1={ENode,{error,{node_already_open,n}}}]} =
+ %% trying to open distributed on this node (error):
+ {[],[Error1={ENode,{error,{node_already_open,n}}}]} =
disk_log:open([{name, n}, {file, File},
{type, wrap}, {size, {50, No}},
{distributed, [node()]}]),
- ?line true =
+ true =
lists:prefix(lists:flatten(io_lib:format("~p: The distribution",
[ENode])),
format_error(Error1)),
- ?line ok = disk_log:lclose(n),
+ ok = disk_log:lclose(n),
- % open distributed on this node:
- ?line {[_],[]} = disk_log:open([{name, n}, {file, File},
+ %% open distributed on this node:
+ {[_],[]} = disk_log:open([{name, n}, {file, File},
{type, wrap}, {size, {50, No}},
{distributed, [node()]}]),
- % trying to open non-distributed on this node (error):
- ?line {_,{node_already_open,n}} =
+ %% trying to open non-distributed on this node (error):
+ {_,{node_already_open,n}} =
disk_log:open([{name, n}, {file, File},
{type, wrap}, {size, {50, No}}]),
- ?line ok = disk_log:close(n),
- ?line Q = qlen(),
+ ok = disk_log:close(n),
+ Q = qlen(),
- ?line del(File, No),
- ?line del(File1, No),
- ?line file:delete(File),
- ?line stop_node(Node),
+ del(File, No),
+ del(File1, No),
+ file:delete(File),
+ stop_node(Node),
ok.
-dist_notify(suite) -> [];
-dist_notify(doc) ->
- ["Notification from other node"];
+%% Notification from other node.
dist_notify(Conf) when is_list(Conf) ->
- ?line PrivDir = ?privdir(Conf),
- ?line true = is_alive(),
+ PrivDir = ?privdir(Conf),
+ true = is_alive(),
- ?line File = filename:join(PrivDir, "bert.LOG"),
- ?line File1 = filename:join(PrivDir, "bert1.LOG"),
- ?line No = 3,
- ?line B = mk_bytes(60),
- ?line file:delete(File),
- ?line file:delete(File1),
- ?line del(File, No), % cleanup
- ?line del(File1, No),
-
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?line {ok, Node} = start_node(disk_log, "-pa " ++ PA),
- ?line wait_for_ready_net(),
-
- % opening distributed on this node:
- ?line {[_],[]} = disk_log:open([{name, n}, {file, File}, {notify, false},
+ File = filename:join(PrivDir, "bert.LOG"),
+ File1 = filename:join(PrivDir, "bert1.LOG"),
+ No = 3,
+ B = mk_bytes(60),
+ file:delete(File),
+ file:delete(File1),
+ del(File, No), % cleanup
+ del(File1, No),
+
+ PA = filename:dirname(code:which(?MODULE)),
+ {ok, Node} = start_node(disk_log, "-pa " ++ PA),
+ wait_for_ready_net(),
+
+ %% opening distributed on this node:
+ {[_],[]} = disk_log:open([{name, n}, {file, File}, {notify, false},
{type, wrap}, {size, {50, No}},
{distributed, [node()]}]),
- % opening distributed on other node:
- ?line {[_],[]} = disk_log:open([{name, n}, {file, File1},
+ %% opening distributed on other node:
+ {[_],[]} = disk_log:open([{name, n}, {file, File1},
{notify, true}, {linkto, self()},
{type, wrap}, {size, {50, No}},
{distributed, [Node]}]),
- ?line disk_log:alog(n, B),
- ?line disk_log:alog(n, B),
- ?line ok = disk_log:sync(n),
- ?line rec(1, {disk_log, Node, n, {wrap, 0}}),
- ?line ok = disk_log:close(n),
-
- ?line del(File, No),
- ?line del(File1, No),
- ?line file:delete(File),
- ?line stop_node(Node),
+ disk_log:alog(n, B),
+ disk_log:alog(n, B),
+ ok = disk_log:sync(n),
+ rec(1, {disk_log, Node, n, {wrap, 0}}),
+ ok = disk_log:close(n),
+
+ del(File, No),
+ del(File1, No),
+ file:delete(File),
+ stop_node(Node),
ok.
-dist_terminate(suite) -> [];
-dist_terminate(doc) ->
- ["Terminating nodes with distributed logs"];
+%% Terminating nodes with distributed logs.
dist_terminate(Conf) when is_list(Conf) ->
- ?line Dir = ?privdir(Conf),
- ?line true = is_alive(),
+ Dir = ?privdir(Conf),
+ true = is_alive(),
- ?line File = filename:join(Dir, "n.LOG"),
- ?line File1 = filename:join(Dir, "n1.LOG"),
+ File = filename:join(Dir, "n.LOG"),
+ File1 = filename:join(Dir, "n1.LOG"),
No = 1,
del(File, No), % cleanup
del(File1, No), % cleanup
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?line {ok, Node} = start_node(disk_log, "-pa " ++ PA),
- ?line wait_for_ready_net(),
+ PA = filename:dirname(code:which(?MODULE)),
+ {ok, Node} = start_node(disk_log, "-pa " ++ PA),
+ wait_for_ready_net(),
%% Distributed versions of two of the situations in close_block(/1.
%% One of two owners terminates.
- ?line Pid1 = spawn_link(?MODULE, lserv, [n]),
- ?line Pid2 = spawn_link(?MODULE, lserv, [n]),
- ?line {[{_, {ok, n}}], []} = sync_do(Pid1, {dist_open, File, node()}),
- ?line {[{_, {ok, n}}], []} = sync_do(Pid2, {dist_open, File1, Node}),
- ?line [_] = sync_do(Pid1, owners),
- ?line [_] = sync_do(Pid2, owners),
- ?line 0 = sync_do(Pid1, users),
- ?line 0 = sync_do(Pid2, users),
- ?line sync_do(Pid1, terminate),
- ?line [_] = sync_do(Pid2, owners),
- ?line 0 = sync_do(Pid2, users),
- ?line sync_do(Pid2, terminate),
- ?line {error, no_such_log} = disk_log:info(n),
+ Pid1 = spawn_link(?MODULE, lserv, [n]),
+ Pid2 = spawn_link(?MODULE, lserv, [n]),
+ {[{_, {ok, n}}], []} = sync_do(Pid1, {dist_open, File, node()}),
+ {[{_, {ok, n}}], []} = sync_do(Pid2, {dist_open, File1, Node}),
+ [_] = sync_do(Pid1, owners),
+ [_] = sync_do(Pid2, owners),
+ 0 = sync_do(Pid1, users),
+ 0 = sync_do(Pid2, users),
+ sync_do(Pid1, terminate),
+ [_] = sync_do(Pid2, owners),
+ 0 = sync_do(Pid2, users),
+ sync_do(Pid2, terminate),
+ {error, no_such_log} = disk_log:info(n),
%% Users terminate (no link...).
- ?line Pid3 = spawn_link(?MODULE, lserv, [n]),
- ?line Pid4 = spawn_link(?MODULE, lserv, [n]),
- ?line {[{_, {ok, n}}], []} =
+ Pid3 = spawn_link(?MODULE, lserv, [n]),
+ Pid4 = spawn_link(?MODULE, lserv, [n]),
+ {[{_, {ok, n}}], []} =
sync_do(Pid3, {dist_open, File, none, node()}),
- ?line {[{_, {ok, n}}], []} =
+ {[{_, {ok, n}}], []} =
sync_do(Pid4, {dist_open, File1, none, Node}),
- ?line [] = sync_do(Pid3, owners),
- ?line [] = sync_do(Pid4, owners),
- ?line 1 = sync_do(Pid3, users),
- ?line 1 = sync_do(Pid4, users),
- ?line sync_do(Pid3, terminate),
- ?line [] = sync_do(Pid4, owners),
- ?line 1 = sync_do(Pid4, users),
- ?line sync_do(Pid4, terminate),
- ?line ok = disk_log:close(n), % closing all nodes
- ?line {error, no_such_log} = disk_log:info(n),
+ [] = sync_do(Pid3, owners),
+ [] = sync_do(Pid4, owners),
+ 1 = sync_do(Pid3, users),
+ 1 = sync_do(Pid4, users),
+ sync_do(Pid3, terminate),
+ [] = sync_do(Pid4, owners),
+ 1 = sync_do(Pid4, users),
+ sync_do(Pid4, terminate),
+ ok = disk_log:close(n), % closing all nodes
+ {error, no_such_log} = disk_log:info(n),
- ?line del(File, No),
- ?line del(File1, No),
- ?line stop_node(Node),
+ del(File, No),
+ del(File1, No),
+ stop_node(Node),
ok.
-dist_accessible(suite) -> [];
-dist_accessible(doc) ->
- ["Accessible logs on nodes"];
+%% Accessible logs on nodes.
dist_accessible(Conf) when is_list(Conf) ->
- ?line PrivDir = ?privdir(Conf),
-
- ?line true = is_alive(),
-
- ?line F1 = filename:join(PrivDir, "a.LOG"),
- ?line file:delete(F1),
- ?line F2 = filename:join(PrivDir, "b.LOG"),
- ?line file:delete(F2),
- ?line F3 = filename:join(PrivDir, "c.LOG"),
- ?line file:delete(F3),
- ?line F4 = filename:join(PrivDir, "d.LOG"),
- ?line file:delete(F1),
- ?line F5 = filename:join(PrivDir, "e.LOG"),
- ?line file:delete(F2),
- ?line F6 = filename:join(PrivDir, "f.LOG"),
- ?line file:delete(F3),
-
- ?line {[],[]} = disk_log:accessible_logs(),
- ?line {ok, a} = disk_log:open([{name, a}, {type, halt}, {file, F1}]),
- ?line {[a],[]} = disk_log:accessible_logs(),
- ?line {ok, b} = disk_log:open([{name, b}, {type, halt}, {file, F2}]),
- ?line {[a,b],[]} = disk_log:accessible_logs(),
- ?line {ok, c} = disk_log:open([{name, c}, {type, halt}, {file, F3}]),
- ?line {[a,b,c],[]} = disk_log:accessible_logs(),
-
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?line {ok, Node} = start_node(disk_log, "-pa " ++ PA),
- ?line wait_for_ready_net(),
-
- ?line {[_],[]} = disk_log:open([{name, a}, {file, F4}, {type, halt},
+ PrivDir = ?privdir(Conf),
+
+ true = is_alive(),
+
+ F1 = filename:join(PrivDir, "a.LOG"),
+ file:delete(F1),
+ F2 = filename:join(PrivDir, "b.LOG"),
+ file:delete(F2),
+ F3 = filename:join(PrivDir, "c.LOG"),
+ file:delete(F3),
+ F4 = filename:join(PrivDir, "d.LOG"),
+ file:delete(F1),
+ F5 = filename:join(PrivDir, "e.LOG"),
+ file:delete(F2),
+ F6 = filename:join(PrivDir, "f.LOG"),
+ file:delete(F3),
+
+ {[],[]} = disk_log:accessible_logs(),
+ {ok, a} = disk_log:open([{name, a}, {type, halt}, {file, F1}]),
+ {[a],[]} = disk_log:accessible_logs(),
+ {ok, b} = disk_log:open([{name, b}, {type, halt}, {file, F2}]),
+ {[a,b],[]} = disk_log:accessible_logs(),
+ {ok, c} = disk_log:open([{name, c}, {type, halt}, {file, F3}]),
+ {[a,b,c],[]} = disk_log:accessible_logs(),
+
+ PA = filename:dirname(code:which(?MODULE)),
+ {ok, Node} = start_node(disk_log, "-pa " ++ PA),
+ wait_for_ready_net(),
+
+ {[_],[]} = disk_log:open([{name, a}, {file, F4}, {type, halt},
{distributed, [Node]}]),
- ?line {[a,b,c],[]} = disk_log:accessible_logs(),
- ?line {[],[a]} = rpc:call(Node, disk_log, accessible_logs, []),
- ?line {[_],[]} = disk_log:open([{name, b}, {file, F5}, {type, halt},
+ {[a,b,c],[]} = disk_log:accessible_logs(),
+ {[],[a]} = rpc:call(Node, disk_log, accessible_logs, []),
+ {[_],[]} = disk_log:open([{name, b}, {file, F5}, {type, halt},
{distributed, [Node]}]),
- ?line {[],[a,b]} = rpc:call(Node, disk_log, accessible_logs, []),
- ?line {[_],[]} = disk_log:open([{name, c}, {file, F6}, {type, halt},
+ {[],[a,b]} = rpc:call(Node, disk_log, accessible_logs, []),
+ {[_],[]} = disk_log:open([{name, c}, {file, F6}, {type, halt},
{distributed, [Node]}]),
- ?line {[],[a,b,c]} = rpc:call(Node, disk_log, accessible_logs, []),
- ?line {[a,b,c],[]} = disk_log:accessible_logs(),
- ?line ok = disk_log:close(a),
- ?line {[b,c],[a]} = disk_log:accessible_logs(),
- ?line ok = disk_log:close(b),
- ?line {[c],[a,b]} = disk_log:accessible_logs(),
- ?line ok = disk_log:close(b),
- ?line {[c],[a]} = disk_log:accessible_logs(),
- ?line {[],[a,c]} = rpc:call(Node, disk_log, accessible_logs, []),
- ?line ok = disk_log:close(c),
- ?line {[],[a,c]} = disk_log:accessible_logs(),
- ?line ok = disk_log:close(c),
- ?line {[],[a]} = disk_log:accessible_logs(),
- ?line {[],[a]} = rpc:call(Node, disk_log, accessible_logs, []),
- ?line ok = disk_log:close(a),
- ?line {[],[]} = disk_log:accessible_logs(),
- ?line {[],[]} = rpc:call(Node, disk_log, accessible_logs, []),
-
- ?line file:delete(F1),
- ?line file:delete(F2),
- ?line file:delete(F3),
- ?line file:delete(F4),
- ?line file:delete(F5),
- ?line file:delete(F6),
-
- ?line stop_node(Node),
+ {[],[a,b,c]} = rpc:call(Node, disk_log, accessible_logs, []),
+ {[a,b,c],[]} = disk_log:accessible_logs(),
+ ok = disk_log:close(a),
+ {[b,c],[a]} = disk_log:accessible_logs(),
+ ok = disk_log:close(b),
+ {[c],[a,b]} = disk_log:accessible_logs(),
+ ok = disk_log:close(b),
+ {[c],[a]} = disk_log:accessible_logs(),
+ {[],[a,c]} = rpc:call(Node, disk_log, accessible_logs, []),
+ ok = disk_log:close(c),
+ {[],[a,c]} = disk_log:accessible_logs(),
+ ok = disk_log:close(c),
+ {[],[a]} = disk_log:accessible_logs(),
+ {[],[a]} = rpc:call(Node, disk_log, accessible_logs, []),
+ ok = disk_log:close(a),
+ {[],[]} = disk_log:accessible_logs(),
+ {[],[]} = rpc:call(Node, disk_log, accessible_logs, []),
+
+ file:delete(F1),
+ file:delete(F2),
+ file:delete(F3),
+ file:delete(F4),
+ file:delete(F5),
+ file:delete(F6),
+
+ stop_node(Node),
ok.
-dist_deadlock(suite) -> [];
-dist_deadlock(doc) ->
- ["OTP-4405. Deadlock between two nodes could happen."];
+%% OTP-4405. Deadlock between two nodes could happen.
dist_deadlock(Conf) when is_list(Conf) ->
- ?line PrivDir = ?privdir(Conf),
+ PrivDir = ?privdir(Conf),
- ?line true = is_alive(),
+ true = is_alive(),
- ?line F1 = filename:join(PrivDir, "a.LOG"),
- ?line file:delete(F1),
- ?line F2 = filename:join(PrivDir, "b.LOG"),
- ?line file:delete(F2),
+ F1 = filename:join(PrivDir, "a.LOG"),
+ file:delete(F1),
+ F2 = filename:join(PrivDir, "b.LOG"),
+ file:delete(F2),
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?line {ok, Node1} = start_node(disk_log_node1, "-pa " ++ PA),
- ?line {ok, Node2} = start_node(disk_log_node2, "-pa " ++ PA),
- ?line wait_for_ready_net(),
+ PA = filename:dirname(code:which(?MODULE)),
+ {ok, Node1} = start_node(disk_log_node1, "-pa " ++ PA),
+ {ok, Node2} = start_node(disk_log_node2, "-pa " ++ PA),
+ wait_for_ready_net(),
Self = self(),
Fun1 = fun() -> dist_dl(Node2, a, F1, Self) end,
@@ -4477,11 +4367,11 @@ dist_deadlock(Conf) when is_list(Conf) ->
receive {P1, a} -> ok end,
receive {P2, b} -> ok end,
- ?line stop_node(Node1),
- ?line stop_node(Node2),
+ stop_node(Node1),
+ stop_node(Node2),
- ?line file:delete(F1),
- ?line file:delete(F2),
+ file:delete(F1),
+ file:delete(F2),
ok.
dist_dl(Node, Name, File, Pid) ->
@@ -4492,12 +4382,10 @@ dist_dl(Node, Name, File, Pid) ->
Pid ! {self(), Name},
ok.
-dist_open2(suite) -> [];
-dist_open2(doc) ->
- ["OTP-4480. Opening several logs simultaneously."];
+%% OTP-4480. Opening several logs simultaneously.
dist_open2(Conf) when is_list(Conf) ->
- ?line true = is_alive(),
- ?line {ok, _Pg2} = pg2:start(),
+ true = is_alive(),
+ {ok, _Pg2} = pg2:start(),
dist_open2_1(Conf, 0),
dist_open2_1(Conf, 100),
@@ -4513,9 +4401,9 @@ dist_open2(Conf) when is_list(Conf) ->
%% to open the log. The second one succeeds, and the third one is
%% attached.
P0 = pps(),
- ?line File0 = "n.LOG",
- ?line File = filename:join(PrivDir, File0),
- ?line make_file(PrivDir, File0, 8),
+ File0 = "n.LOG",
+ File = filename:join(PrivDir, File0),
+ make_file(PrivDir, File0, 8),
Parent = self(),
F1 = fun() -> R = disk_log:open([{name, Log}, {file, File},
@@ -4529,18 +4417,18 @@ dist_open2(Conf) when is_list(Conf) ->
Parent ! {self(), R},
timer:sleep(300)
end,
- ?line Pid1 = spawn(F1),
+ Pid1 = spawn(F1),
timer:sleep(10),
- ?line Pid2 = spawn(F2),
- ?line Pid3 = spawn(F2),
+ Pid2 = spawn(F2),
+ Pid3 = spawn(F2),
- ?line receive {Pid1,R1} -> {[],[_]} = R1 end,
- ?line receive {Pid2,R2} -> {[_],[]} = R2 end,
- ?line receive {Pid3,R3} -> {[_],[]} = R3 end,
+ receive {Pid1,R1} -> {[],[_]} = R1 end,
+ receive {Pid2,R2} -> {[_],[]} = R2 end,
+ receive {Pid3,R3} -> {[_],[]} = R3 end,
timer:sleep(500),
- ?line file:delete(File),
- ?line true = (P0 == pps()),
+ file:delete(File),
+ true = (P0 == pps()),
%% This time the first process has a naughty head_func. This test
%% does not add very much. Perhaps it should be removed. However,
@@ -4561,15 +4449,15 @@ dist_open2(Conf) when is_list(Conf) ->
{type,halt}]),
Parent ! {self(), R}
end,
- ?line Pid4 = spawn(F3),
+ Pid4 = spawn(F3),
timer:sleep(10),
- ?line Pid5 = spawn(F4),
- ?line Pid6 = spawn(F4),
+ Pid5 = spawn(F4),
+ Pid6 = spawn(F4),
%% The timing is crucial here.
- ?line R = case receive {Pid4,R4} -> R4 end of
+ R = case receive {Pid4,R4} -> R4 end of
{error, no_such_log} ->
- ?line R5 = receive {Pid5, R5a} -> R5a end,
- ?line R6 = receive {Pid6, R6a} -> R6a end,
+ R5 = receive {Pid5, R5a} -> R5a end,
+ R6 = receive {Pid6, R6a} -> R6a end,
case {R5, R6} of
{{repaired, _, _, _}, {ok, Log}} -> ok;
{{ok, Log}, {repaired, _, _, _}} -> ok;
@@ -4577,16 +4465,16 @@ dist_open2(Conf) when is_list(Conf) ->
end,
ok;
{ok, Log} -> % uninteresting case
- ?line receive {Pid5,_R5} -> ok end,
- ?line receive {Pid6,_R6} -> ok end,
+ receive {Pid5,_R5} -> ok end,
+ receive {Pid6,_R6} -> ok end,
{comment,
"Timing dependent test did not check anything."}
end,
timer:sleep(100),
- ?line {error, no_such_log} = disk_log:close(Log),
+ {error, no_such_log} = disk_log:close(Log),
file:delete(File),
- ?line true = (P0 == pps()),
+ true = (P0 == pps()),
No = 2,
Log2 = n2,
@@ -4598,7 +4486,7 @@ dist_open2(Conf) when is_list(Conf) ->
%% processes should be able to attach to other log without having to
%% wait.
- ?line {ok,Log} =
+ {ok,Log} =
disk_log:open([{name,Log},{file,File},{type,wrap},{size,{100,No}}]),
Pid = spawn(fun() ->
receive {HeadPid, start} -> ok end,
@@ -4607,15 +4495,15 @@ dist_open2(Conf) when is_list(Conf) ->
HeadPid ! {self(), done}
end),
HeadFunc = {?MODULE, slow_header, [Pid]},
- ?line ok = disk_log:change_header(Log, {head_func, HeadFunc}),
- ?line ok = disk_log:inc_wrap_file(Log), % header is written
+ ok = disk_log:change_header(Log, {head_func, HeadFunc}),
+ ok = disk_log:inc_wrap_file(Log), % header is written
timer:sleep(100),
- ?line ok = disk_log:close(Log),
+ ok = disk_log:close(Log),
file:delete(File2),
del(File, No),
- ?line true = (P0 == pps()),
+ true = (P0 == pps()),
R.
@@ -4625,13 +4513,13 @@ dist_open2_1(Conf, Delay) ->
Log = n,
A0 = [{name,Log},{file,File},{type,halt}],
- ?line create_opened_log(File, A0),
+ create_opened_log(File, A0),
P0 = pps(),
Log2 = log2,
File2 = "log2.LOG",
- ?line file:delete(File2),
- ?line {ok,Log2} = disk_log:open([{name,Log2},{file,File2},{type,halt}]),
+ file:delete(File2),
+ {ok,Log2} = disk_log:open([{name,Log2},{file,File2},{type,halt}]),
Parent = self(),
F = fun() ->
@@ -4639,28 +4527,28 @@ dist_open2_1(Conf, Delay) ->
timer:sleep(Delay),
Parent ! {self(), R}
end,
- ?line Pid1 = spawn(F),
+ Pid1 = spawn(F),
timer:sleep(10),
- ?line Pid2 = spawn(F),
- ?line Pid3 = spawn(F),
- ?line {error, no_such_log} = disk_log:log(Log, term), % is repairing now
- ?line 0 = qlen(),
+ Pid2 = spawn(F),
+ Pid3 = spawn(F),
+ {error, no_such_log} = disk_log:log(Log, term), % is repairing now
+ 0 = qlen(),
%% The file is already open, so this will not take long.
- ?line {ok,Log2} = disk_log:open([{name,Log2},{file,File2},{type,halt}]),
- ?line 0 = qlen(), % still repairing
- ?line ok = disk_log:close(Log2),
- ?line {error, no_such_log} = disk_log:close(Log2),
- ?line file:delete(File2),
-
- ?line receive {Pid1,R1} -> {repaired,_,_,_} = R1 end,
- ?line receive {Pid2,R2} -> {ok,_} = R2 end,
- ?line receive {Pid3,R3} -> {ok,_} = R3 end,
+ {ok,Log2} = disk_log:open([{name,Log2},{file,File2},{type,halt}]),
+ 0 = qlen(), % still repairing
+ ok = disk_log:close(Log2),
+ {error, no_such_log} = disk_log:close(Log2),
+ file:delete(File2),
+
+ receive {Pid1,R1} -> {repaired,_,_,_} = R1 end,
+ receive {Pid2,R2} -> {ok,_} = R2 end,
+ receive {Pid3,R3} -> {ok,_} = R3 end,
timer:sleep(500),
- ?line {error, no_such_log} = disk_log:info(Log),
+ {error, no_such_log} = disk_log:info(Log),
file:delete(File),
- ?line true = (P0 == pps()),
+ true = (P0 == pps()),
ok.
@@ -4669,18 +4557,18 @@ dist_open2_2(Conf, Delay) ->
File = filename:join(Dir, "n.LOG"),
Log = n,
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?line {ok, Node1} = start_node(disk_log_node2, "-pa " ++ PA),
- ?line wait_for_ready_net(),
+ PA = filename:dirname(code:which(?MODULE)),
+ {ok, Node1} = start_node(disk_log_node2, "-pa " ++ PA),
+ wait_for_ready_net(),
P0 = pps(),
A0 = [{name,Log},{file,File},{type,halt}],
- ?line create_opened_log(File, A0),
+ create_opened_log(File, A0),
Log2 = log2,
File2 = "log2.LOG",
- ?line file:delete(File2),
- ?line {[{Node1,{ok,Log2}}],[]} =
+ file:delete(File2),
+ {[{Node1,{ok,Log2}}],[]} =
disk_log:open([{name,Log2},{file,File2},{type,halt},
{distributed,[Node1]}]),
@@ -4693,32 +4581,32 @@ dist_open2_2(Conf, Delay) ->
Parent ! {self(), R}
end,
%% And {priority, ...} probably has no effect either.
- ?line Pid1 = spawn_opt(F, [{priority, low}]),
- % timer:sleep(1), % no guarantee that Pid1 will return {repaired, ...}
- ?line Pid2 = spawn_opt(F, [{priority, low}]),
- ?line {error, no_such_log} =
+ Pid1 = spawn_opt(F, [{priority, low}]),
+ %% timer:sleep(1), % no guarantee that Pid1 will return {repaired, ...}
+ Pid2 = spawn_opt(F, [{priority, low}]),
+ {error, no_such_log} =
disk_log:log(Log, term), % maybe repairing now
- ?line 0 = qlen(),
+ 0 = qlen(),
%% The file is already open, so this will not take long.
- ?line {[{Node1,{ok,Log2}}],[]} =
+ {[{Node1,{ok,Log2}}],[]} =
disk_log:open([{name,Log2},{file,File2},{type,halt},
{distributed,[Node1]}]),
- ?line 0 = qlen(), % probably still repairing
- ?line ok = disk_log:close(Log2),
- ?line file:delete(File2),
+ 0 = qlen(), % probably still repairing
+ ok = disk_log:close(Log2),
+ file:delete(File2),
- ?line receive {Pid1,R1} -> R1 end,
- ?line receive {Pid2,R2} -> R2 end,
- ?line case {R1, R2} of
+ receive {Pid1,R1} -> R1 end,
+ receive {Pid2,R2} -> R2 end,
+ case {R1, R2} of
{{[{Node1,{repaired,_,_,_}}],[]},
{[{Node1,{ok,Log}}],[]}} -> ok;
{{[{Node1,{ok,Log}}],[]},
{[{Node1,{repaired,_,_,_}}],[]}} -> ok
end,
- ?line true = (P0 == pps()),
- ?line stop_node(Node1),
+ true = (P0 == pps()),
+ stop_node(Node1),
file:delete(File),
ok.
@@ -4751,38 +4639,35 @@ log_terms(Log, N) ->
ok = disk_log:log(Log, {term, N}),
log_terms(Log, N-1).
-other_groups(suite) -> [];
-other_groups(doc) ->
- ["OTP-5810. Cope with pg2 groups that are not disk logs."];
+%% OTP-5810. Cope with pg2 groups that are not disk logs.
other_groups(Conf) when is_list(Conf) ->
- ?line true = is_alive(),
- ?line PrivDir = ?privdir(Conf),
+ true = is_alive(),
+ PrivDir = ?privdir(Conf),
- ?line File = filename:join(PrivDir, "n.LOG"),
- ?line file:delete(File),
+ File = filename:join(PrivDir, "n.LOG"),
+ file:delete(File),
- ?line {[],[]} = disk_log:accessible_logs(),
- ?line {[_],[]} = disk_log:open([{name, n}, {file, File}, {type, halt},
+ {[],[]} = disk_log:accessible_logs(),
+ {[_],[]} = disk_log:open([{name, n}, {file, File}, {type, halt},
{distributed, [node()]}]),
- ?line {[],[n]} = disk_log:accessible_logs(),
+ {[],[n]} = disk_log:accessible_logs(),
Group = grupp,
- ?line pg2:create(Group),
- ?line ok = pg2:join(Group, self()),
- ?line {[],[n]} = disk_log:accessible_logs(),
- ?line [_] =
+ pg2:create(Group),
+ ok = pg2:join(Group, self()),
+ {[],[n]} = disk_log:accessible_logs(),
+ [_] =
lists:filter(fun(P) -> disk_log:pid2name(P) =/= undefined end,
erlang:processes()),
- ?line pg2:delete(Group),
- ?line {[],[n]} = disk_log:accessible_logs(),
- ?line ok = disk_log:close(n),
- ?line {[],[]} = disk_log:accessible_logs(),
- ?line file:delete(File),
+ pg2:delete(Group),
+ {[],[n]} = disk_log:accessible_logs(),
+ ok = disk_log:close(n),
+ {[],[]} = disk_log:accessible_logs(),
+ file:delete(File),
ok.
-define(MAX, 16384). % MAX in disk_log_1.erl
-evil(suite) -> [];
-evil(doc) -> ["Evil cases such as closed file descriptor port."];
+%% Evil cases such as closed file descriptor port.
evil(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "n.LOG"),
@@ -4790,62 +4675,62 @@ evil(Conf) when is_list(Conf) ->
%% Not a very thorough test.
- ?line ok = setup_evil_filled_cache_wrap(Log, Dir),
- ?line {error, {file_error,_,einval}} = disk_log:log(Log, apa),
- ?line ok = disk_log:close(Log),
+ ok = setup_evil_filled_cache_wrap(Log, Dir),
+ {error, {file_error,_,einval}} = disk_log:log(Log, apa),
+ ok = disk_log:close(Log),
- ?line ok = setup_evil_filled_cache_halt(Log, Dir),
- ?line {error, {file_error,_,einval}} = disk_log:truncate(Log, apa),
- ?line ok = stop_evil(Log),
+ ok = setup_evil_filled_cache_halt(Log, Dir),
+ {error, {file_error,_,einval}} = disk_log:truncate(Log, apa),
+ ok = stop_evil(Log),
%% White box test.
file:delete(File),
- ?line Ports0 = erlang:ports(),
- ?line {ok, Log} = disk_log:open([{name,Log},{file,File},{type,halt},
+ Ports0 = erlang:ports(),
+ {ok, Log} = disk_log:open([{name,Log},{file,File},{type,halt},
{size,?MAX+50},{format,external}]),
- ?line [Fd] = erlang:ports() -- Ports0,
- ?line {B,_} = x_mk_bytes(30),
- ?line ok = disk_log:blog(Log, <<0:(?MAX+1)/unit:8>>),
- ?line exit(Fd, kill),
- ?line {error, {file_error,_,einval}} = disk_log:blog_terms(Log, [B,B]),
- ?line ok= disk_log:close(Log),
+ [Fd] = erlang:ports() -- Ports0,
+ {B,_} = x_mk_bytes(30),
+ ok = disk_log:blog(Log, <<0:(?MAX+1)/unit:8>>),
+ exit(Fd, kill),
+ {error, {file_error,_,einval}} = disk_log:blog_terms(Log, [B,B]),
+ ok= disk_log:close(Log),
file:delete(File),
- ?line ok = setup_evil_wrap(Log, Dir),
- ?line {error, {file_error,_,einval}} = disk_log:close(Log),
+ ok = setup_evil_wrap(Log, Dir),
+ {error, {file_error,_,einval}} = disk_log:close(Log),
- ?line ok = setup_evil_wrap(Log, Dir),
- ?line {error, {file_error,_,einval}} = disk_log:log(Log, apa),
- ?line ok = stop_evil(Log),
+ ok = setup_evil_wrap(Log, Dir),
+ {error, {file_error,_,einval}} = disk_log:log(Log, apa),
+ ok = stop_evil(Log),
- ?line ok = setup_evil_halt(Log, Dir),
- ?line {error, {file_error,_,einval}} = disk_log:log(Log, apa),
- ?line ok = stop_evil(Log),
+ ok = setup_evil_halt(Log, Dir),
+ {error, {file_error,_,einval}} = disk_log:log(Log, apa),
+ ok = stop_evil(Log),
- ?line ok = setup_evil_wrap(Log, Dir),
- ?line {error, {file_error,_,einval}} = disk_log:reopen(Log, apa),
- ?line {error, {file_error,_,einval}} = disk_log:reopen(Log, apa),
- ?line ok = stop_evil(Log),
+ ok = setup_evil_wrap(Log, Dir),
+ {error, {file_error,_,einval}} = disk_log:reopen(Log, apa),
+ {error, {file_error,_,einval}} = disk_log:reopen(Log, apa),
+ ok = stop_evil(Log),
- ?line ok = setup_evil_wrap(Log, Dir),
- ?line {error, {file_error,_,einval}} = disk_log:reopen(Log, apa),
- ?line ok = stop_evil(Log),
+ ok = setup_evil_wrap(Log, Dir),
+ {error, {file_error,_,einval}} = disk_log:reopen(Log, apa),
+ ok = stop_evil(Log),
- ?line ok = setup_evil_wrap(Log, Dir),
- ?line {error, {file_error,_,einval}} = disk_log:inc_wrap_file(Log),
- ?line ok = stop_evil(Log),
+ ok = setup_evil_wrap(Log, Dir),
+ {error, {file_error,_,einval}} = disk_log:inc_wrap_file(Log),
+ ok = stop_evil(Log),
- ?line ok = setup_evil_wrap(Log, Dir),
- ?line {error, {file_error,_,einval}} = disk_log:chunk(Log, start),
- ?line ok = stop_evil(Log),
+ ok = setup_evil_wrap(Log, Dir),
+ {error, {file_error,_,einval}} = disk_log:chunk(Log, start),
+ ok = stop_evil(Log),
- ?line ok = setup_evil_wrap(Log, Dir),
- ?line {error, {file_error,_,einval}} = disk_log:truncate(Log),
- ?line ok = stop_evil(Log),
+ ok = setup_evil_wrap(Log, Dir),
+ {error, {file_error,_,einval}} = disk_log:truncate(Log),
+ ok = stop_evil(Log),
- ?line ok = setup_evil_wrap(Log, Dir),
- ?line {error, {file_error,_,einval}} = disk_log:chunk_step(Log, start, 1),
- ?line ok = stop_evil(Log),
+ ok = setup_evil_wrap(Log, Dir),
+ {error, {file_error,_,einval}} = disk_log:chunk_step(Log, start, 1),
+ ok = stop_evil(Log),
io:format("messages: ~p~n", [erlang:process_info(self(), messages)]),
del(File, 2),
@@ -4894,25 +4779,23 @@ setup_evil_filled_cache(Log, Args, Dir) ->
exit(Fd, kill),
ok.
-otp_6278(suite) -> [];
-otp_6278(doc) -> ["OTP-6278. open/1 creates no status or crash report."];
+%% OTP-6278. open/1 creates no status or crash report.
otp_6278(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = filename:join(Dir, "no_such_dir/no_such_file"),
- ?line error_logger:add_report_handler(?MODULE, self()),
- ?line {error, {file_error, _, _}} =
+ error_logger:add_report_handler(?MODULE, self()),
+ {error, {file_error, _, _}} =
disk_log:open([{name,n},{file,File}]),
receive
{crash_report,_Pid,Report} ->
- ?line io:format("Unexpected: ~p\n", [Report]),
- ?line ?t:fail()
+ io:format("Unexpected: ~p\n", [Report]),
+ ct:fail(failed)
after 1000 ->
ok
end,
- ?line error_logger:delete_report_handler(?MODULE).
+ error_logger:delete_report_handler(?MODULE).
-otp_10131(suite) -> [];
-otp_10131(doc) -> ["OTP-10131. head_func type."];
+%% OTP-10131. head_func type.
otp_10131(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
Log = otp_10131,
@@ -4979,7 +4862,7 @@ copy_wrap_log(FromName, ToName, N, FromDir, ToDir) ->
-define(BUFSIZE, 8192).
copy_file(Src, Dest) ->
- % ?t:format("copying from ~p to ~p~n", [Src, Dest]),
+ %% io:format("copying from ~p to ~p~n", [Src, Dest]),
{ok, InFd} = file:open(Src, [raw, binary, read]),
{ok, OutFd} = file:open(Dest, [raw, binary, write]),
ok = copy_file1(InFd, OutFd),
@@ -5104,50 +4987,15 @@ get_known(Node) ->
%% Copied from erl_distribution_SUITE.erl:
start_node(Name, Param) ->
- ?t:start_node(Name, slave, [{args, Param}]).
+ test_server:start_node(Name, slave, [{args, Param}]).
stop_node(Node) ->
- ?t:stop_node(Node).
-
-%from(H, [H | T]) -> T;
-%from(H, [_ | T]) -> from(H, T);
-%from(_H, []) -> [].
-
-
-%% Check for NFS cache size, this is called from init_per_testcase() and
-%% makes different tests run depending on the size of the NFS cache on
-%% VxWorks. Possibly this could be adopted to Windows too, but we seldom use
-%% NFS when testing on windows, so I can find better things to do.
-%% The port program used simply reads the nfsCacheSize variable on the board.
-%% If the board is configured without NFS, the port program will fail to load
-%% and this will return 0, which may or may not be the wrong thing to do.
-
-check_nfs(_Config) ->
- 0.
+ test_server:stop_node(Node).
-skip_expand([]) ->
- [];
-skip_expand([Case | T]) ->
- case (catch apply(?MODULE, Case, [suite])) of
- {'EXIT', _} ->
- [Case | skip_expand(T)];
- [] ->
- [Case | skip_expand(T)];
- Res ->
- skip_expand(Res) ++ skip_expand(T)
- end.
-
-
-skip_list(Config) ->
- case check_nfs(Config) of
- 0 ->
- skip_expand(?SKIP_NO_CACHE);
- _ ->
- skip_expand(?SKIP_LARGE_CACHE)
- end.
+%% from(H, [H | T]) -> T;
+%% from(H, [_ | T]) -> from(H, T);
+%% from(_H, []) -> [].
-should_skip(_Test,_Config) ->
- false.
%%-----------------------------------------------------------------
%% The error_logger handler used.
diff --git a/lib/kernel/test/erl_boot_server_SUITE.erl b/lib/kernel/test/erl_boot_server_SUITE.erl
index 954880e252..aef1d69f62 100644
--- a/lib/kernel/test/erl_boot_server_SUITE.erl
+++ b/lib/kernel/test/erl_boot_server_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(erl_boot_server_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2]).
@@ -34,7 +34,9 @@
%% Changed for the new erl_boot_server for R3A by Bjorn Gustavsson.
%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[start, start_link, stop, add, delete, responses].
@@ -57,274 +59,262 @@ end_per_group(_GroupName, Config) ->
-define(all_ones, {255, 255, 255, 255}).
-start(doc) -> "Tests the erl_boot_server:start/1 function.";
+%% Tests the erl_boot_server:start/1 function.
start(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(50)),
- ?line [Host1, Host2|_] = good_hosts(Config),
+ [Host1, Host2|_] = good_hosts(Config),
%% Bad arguments.
BadHost = "bad__host",
- ?line {error, {badarg, {}}} = erl_boot_server:start({}),
- ?line {error, {badarg, atom}} = erl_boot_server:start(atom),
- ?line {error, {badarg, [atom, BadHost]}} =
+ {error, {badarg, {}}} = erl_boot_server:start({}),
+ {error, {badarg, atom}} = erl_boot_server:start(atom),
+ {error, {badarg, [atom, BadHost]}} =
erl_boot_server:start([atom, BadHost]),
- ?line {error, {badarg, [Host1, BadHost]}} =
+ {error, {badarg, [Host1, BadHost]}} =
erl_boot_server:start([Host1, BadHost]),
%% Test once.
- ?line {ok, Pid1} = erl_boot_server:start([Host1]),
- ?line {error, {already_started, Pid1}} =
+ {ok, Pid1} = erl_boot_server:start([Host1]),
+ {error, {already_started, Pid1}} =
erl_boot_server:start([Host1]),
- ?line exit(Pid1, kill),
+ exit(Pid1, kill),
%% Test again.
- test_server:sleep(1),
- ?line {ok, Pid2} = erl_boot_server:start([Host1, Host2]),
- ?line {error, {already_started, Pid2}} =
+ ct:sleep(1),
+ {ok, Pid2} = erl_boot_server:start([Host1, Host2]),
+ {error, {already_started, Pid2}} =
erl_boot_server:start([Host1, Host2]),
- ?line exit(Pid2, kill),
- test_server:sleep(1),
+ exit(Pid2, kill),
+ ct:sleep(1),
- ?line test_server:timetrap_cancel(Dog),
ok.
-start_link(doc) -> "Tests the erl_boot_server:start_link/1 function.";
+%% Tests the erl_boot_server:start_link/1 function.
start_link(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line [Host1, Host2|_] = good_hosts(Config),
+ [Host1, Host2|_] = good_hosts(Config),
OldFlag = process_flag(trap_exit, true),
- ?line {error, {badarg, {}}} = erl_boot_server:start_link({}),
- ?line {error, {badarg, atom}} = erl_boot_server:start_link(atom),
- ?line BadHost = "bad__host",
- ?line {error, {badarg, [atom, BadHost]}} =
+ {error, {badarg, {}}} = erl_boot_server:start_link({}),
+ {error, {badarg, atom}} = erl_boot_server:start_link(atom),
+ BadHost = "bad__host",
+ {error, {badarg, [atom, BadHost]}} =
erl_boot_server:start_link([atom, BadHost]),
- ?line {ok, Pid1} = erl_boot_server:start_link([Host1]),
- ?line {error, {already_started, Pid1}} =
+ {ok, Pid1} = erl_boot_server:start_link([Host1]),
+ {error, {already_started, Pid1}} =
erl_boot_server:start_link([Host1]),
- ?line shutdown(Pid1),
+ shutdown(Pid1),
- ?line {ok, Pid2} = erl_boot_server:start_link([Host1, Host2]),
- ?line {error, {already_started, Pid2}} =
+ {ok, Pid2} = erl_boot_server:start_link([Host1, Host2]),
+ {error, {already_started, Pid2}} =
erl_boot_server:start_link([Host1, Host2]),
- ?line shutdown(Pid2),
+ shutdown(Pid2),
process_flag(trap_exit, OldFlag),
- ?line test_server:timetrap_cancel(Dog),
ok.
-stop(doc) -> "Tests that no processes are left if a boot server is killed.";
+%% Tests that no processes are left if a boot server is killed.
stop(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(50)),
- ?line [Host1|_] = good_hosts(Config),
+ [Host1|_] = good_hosts(Config),
%% Start a boot server and kill it. Make sure that any helper processes
%% dies.
- % Make sure the inet_gethost_native server is already started,
- % otherwise it will make this test fail:
- ?line inet:getaddr(localhost, inet),
- ?line Before = processes(),
- ?line {ok, Pid} = erl_boot_server:start([Host1]),
- ?line New = processes() -- [Pid|Before],
- ?line exit(Pid, kill),
- ?line receive after 100 -> ok end,
- ?line case [P || P <- New, is_process_alive(P)] of
- [] ->
- ok;
- NotKilled ->
- test_server:fail({not_killed, NotKilled})
- end,
- ?line test_server:timetrap_cancel(Dog),
+ %% Make sure the inet_gethost_native server is already started,
+ %% otherwise it will make this test fail:
+ inet:getaddr(localhost, inet),
+ Before = processes(),
+ {ok, Pid} = erl_boot_server:start([Host1]),
+ New = processes() -- [Pid|Before],
+ exit(Pid, kill),
+ receive after 100 -> ok end,
+ case [P || P <- New, is_process_alive(P)] of
+ [] ->
+ ok;
+ NotKilled ->
+ ct:fail({not_killed, NotKilled})
+ end,
ok.
-add(doc) -> "Tests the erl_boot_server:add/1 function.";
+%% Tests the erl_boot_server:add/1 function.
add(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line OldFlag = process_flag(trap_exit, true),
- ?line {ok, Pid1} = erl_boot_server:start_link([]),
- ?line [] = erl_boot_server:which_slaves(),
- ?line [Host1, Host2, Host3|_] = good_hosts(Config),
+ OldFlag = process_flag(trap_exit, true),
+ {ok, Pid1} = erl_boot_server:start_link([]),
+ [] = erl_boot_server:which_slaves(),
+ [Host1, Host2, Host3|_] = good_hosts(Config),
%% Try bad values.
- ?line {error, {badarg, {}}} = erl_boot_server:add_slave({}),
- ?line {error, {badarg, [atom]}} = erl_boot_server:add_slave([atom]),
- ?line BadHost = "bad__host",
- ?line {error, {badarg, BadHost}} = erl_boot_server:add_slave(BadHost),
- ?line [] = erl_boot_server:which_slaves(),
+ {error, {badarg, {}}} = erl_boot_server:add_slave({}),
+ {error, {badarg, [atom]}} = erl_boot_server:add_slave([atom]),
+ BadHost = "bad__host",
+ {error, {badarg, BadHost}} = erl_boot_server:add_slave(BadHost),
+ [] = erl_boot_server:which_slaves(),
%% Add good host names.
- ?line {ok, Ip1} = inet:getaddr(Host1, inet),
- ?line {ok, Ip2} = inet:getaddr(Host2, inet),
- ?line {ok, Ip3} = inet:getaddr(Host3, inet),
- ?line MIp1 = {?all_ones, Ip1},
- ?line MIp2 = {?all_ones, Ip2},
- ?line MIp3 = {?all_ones, Ip3},
- ?line ok = erl_boot_server:add_slave(Host1),
- ?line [MIp1] = erl_boot_server:which_slaves(),
- ?line ok = erl_boot_server:add_slave(Host2),
- ?line M_Ip1_Ip2 = lists:sort([MIp1, MIp2]),
- ?line M_Ip1_Ip2 = lists:sort(erl_boot_server:which_slaves()),
- ?line ok = erl_boot_server:add_slave(Host3),
- ?line M_Ip1_Ip2_Ip3 = lists:sort([MIp3|M_Ip1_Ip2]),
- ?line M_Ip1_Ip2_Ip3 = erl_boot_server:which_slaves(),
+ {ok, Ip1} = inet:getaddr(Host1, inet),
+ {ok, Ip2} = inet:getaddr(Host2, inet),
+ {ok, Ip3} = inet:getaddr(Host3, inet),
+ MIp1 = {?all_ones, Ip1},
+ MIp2 = {?all_ones, Ip2},
+ MIp3 = {?all_ones, Ip3},
+ ok = erl_boot_server:add_slave(Host1),
+ [MIp1] = erl_boot_server:which_slaves(),
+ ok = erl_boot_server:add_slave(Host2),
+ M_Ip1_Ip2 = lists:sort([MIp1, MIp2]),
+ M_Ip1_Ip2 = lists:sort(erl_boot_server:which_slaves()),
+ ok = erl_boot_server:add_slave(Host3),
+ M_Ip1_Ip2_Ip3 = lists:sort([MIp3|M_Ip1_Ip2]),
+ M_Ip1_Ip2_Ip3 = erl_boot_server:which_slaves(),
%% Add duplicate names.
- ?line ok = erl_boot_server:add_slave(Host3),
- ?line M_Ip1_Ip2_Ip3 = erl_boot_server:which_slaves(),
+ ok = erl_boot_server:add_slave(Host3),
+ M_Ip1_Ip2_Ip3 = erl_boot_server:which_slaves(),
%% More bad names.
- ?line {error, {badarg, BadHost}} = erl_boot_server:add_slave(BadHost),
- ?line M_Ip1_Ip2_Ip3 = erl_boot_server:which_slaves(),
+ {error, {badarg, BadHost}} = erl_boot_server:add_slave(BadHost),
+ M_Ip1_Ip2_Ip3 = erl_boot_server:which_slaves(),
%% Cleanup.
- ?line shutdown(Pid1),
- ?line process_flag(trap_exit, OldFlag),
- ?line test_server:timetrap_cancel(Dog),
+ shutdown(Pid1),
+ process_flag(trap_exit, OldFlag),
ok.
-delete(doc) -> "Tests the erl_boot_server:delete/1 function.";
+%% Tests the erl_boot_server:delete/1 function.
delete(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line OldFlag = process_flag(trap_exit, true),
+ OldFlag = process_flag(trap_exit, true),
- ?line [Host1, Host2, Host3|_] = good_hosts(Config),
- ?line {ok, Ip1} = inet:getaddr(Host1, inet),
- ?line {ok, Ip2} = inet:getaddr(Host2, inet),
- ?line {ok, Ip3} = inet:getaddr(Host3, inet),
- ?line MIp1 = {?all_ones, Ip1},
- ?line MIp2 = {?all_ones, Ip2},
- ?line MIp3 = {?all_ones, Ip3},
+ [Host1, Host2, Host3|_] = good_hosts(Config),
+ {ok, Ip1} = inet:getaddr(Host1, inet),
+ {ok, Ip2} = inet:getaddr(Host2, inet),
+ {ok, Ip3} = inet:getaddr(Host3, inet),
+ MIp1 = {?all_ones, Ip1},
+ MIp2 = {?all_ones, Ip2},
+ MIp3 = {?all_ones, Ip3},
- ?line {ok, Pid1} = erl_boot_server:start_link([Host1, Host2, Host3]),
- ?line M_Ip123 = lists:sort([MIp1, MIp2, MIp3]),
- ?line M_Ip123 = erl_boot_server:which_slaves(),
+ {ok, Pid1} = erl_boot_server:start_link([Host1, Host2, Host3]),
+ M_Ip123 = lists:sort([MIp1, MIp2, MIp3]),
+ M_Ip123 = erl_boot_server:which_slaves(),
%% Do some bad attempts and check that the list of slaves is intact.
- ?line {error, {badarg, {}}} = erl_boot_server:delete_slave({}),
- ?line {error, {badarg, [atom]}} = erl_boot_server:delete_slave([atom]),
- ?line BadHost = "bad__host",
- ?line {error, {badarg, BadHost}} = erl_boot_server:delete_slave(BadHost),
- ?line M_Ip123 = erl_boot_server:which_slaves(),
+ {error, {badarg, {}}} = erl_boot_server:delete_slave({}),
+ {error, {badarg, [atom]}} = erl_boot_server:delete_slave([atom]),
+ BadHost = "bad__host",
+ {error, {badarg, BadHost}} = erl_boot_server:delete_slave(BadHost),
+ M_Ip123 = erl_boot_server:which_slaves(),
%% Delete Host2 and make sure it's gone.
- ?line ok = erl_boot_server:delete_slave(Host2),
- ?line M_Ip13 = lists:sort([MIp1, MIp3]),
- ?line M_Ip13 = erl_boot_server:which_slaves(),
-
- ?line ok = erl_boot_server:delete_slave(Host1),
- ?line [MIp3] = erl_boot_server:which_slaves(),
- ?line ok = erl_boot_server:delete_slave(Host1),
- ?line [MIp3] = erl_boot_server:which_slaves(),
-
- ?line {error, {badarg, BadHost}} = erl_boot_server:delete_slave(BadHost),
- ?line [MIp3] = erl_boot_server:which_slaves(),
-
- ?line ok = erl_boot_server:delete_slave(Ip3),
- ?line [] = erl_boot_server:which_slaves(),
- ?line ok = erl_boot_server:delete_slave(Ip3),
- ?line [] = erl_boot_server:which_slaves(),
-
- ?line shutdown(Pid1),
- ?line process_flag(trap_exit, OldFlag),
- ?line test_server:timetrap_cancel(Dog),
+ ok = erl_boot_server:delete_slave(Host2),
+ M_Ip13 = lists:sort([MIp1, MIp3]),
+ M_Ip13 = erl_boot_server:which_slaves(),
+
+ ok = erl_boot_server:delete_slave(Host1),
+ [MIp3] = erl_boot_server:which_slaves(),
+ ok = erl_boot_server:delete_slave(Host1),
+ [MIp3] = erl_boot_server:which_slaves(),
+
+ {error, {badarg, BadHost}} = erl_boot_server:delete_slave(BadHost),
+ [MIp3] = erl_boot_server:which_slaves(),
+
+ ok = erl_boot_server:delete_slave(Ip3),
+ [] = erl_boot_server:which_slaves(),
+ ok = erl_boot_server:delete_slave(Ip3),
+ [] = erl_boot_server:which_slaves(),
+
+ shutdown(Pid1),
+ process_flag(trap_exit, OldFlag),
ok.
-responses(doc) -> "Tests erl_boot_server responses to slave requests.";
+%% Tests erl_boot_server responses to slave requests.
responses(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(30)),
- ?line process_flag(trap_exit, true),
+ process_flag(trap_exit, true),
%% Copy from inet_boot.hrl
EBOOT_PORT = 4368,
EBOOT_REQUEST = "EBOOTQ",
EBOOT_REPLY = "EBOOTR",
- ?line {ok,Host} = inet:gethostname(),
- ?line {ok,Ip} = inet:getaddr(Host, inet),
+ {ok,Host} = inet:gethostname(),
+ {ok,Ip} = inet:getaddr(Host, inet),
ThisVer = erlang:system_info(version),
- ?line {ok,BootPid} = erl_boot_server:start_link([Host]),
+ {ok,BootPid} = erl_boot_server:start_link([Host]),
%% Send junk
- ?line S1 = open_udp(),
- ?line prim_inet:sendto(S1, Ip, EBOOT_PORT, ["0"]),
+ S1 = open_udp(),
+ prim_inet:sendto(S1, Ip, EBOOT_PORT, ["0"]),
receive
What ->
- ?line close_udp(S1),
- ?line ?t:fail({"got unexpected response",What})
+ close_udp(S1),
+ ct:fail({"got unexpected response",What})
after 100 ->
ok
end,
%% Req from a slave with same erlang vsn.
- ?line S2 = open_udp(),
- ?line prim_inet:sendto(S2, Ip, EBOOT_PORT, [EBOOT_REQUEST,ThisVer]),
+ S2 = open_udp(),
+ prim_inet:sendto(S2, Ip, EBOOT_PORT, [EBOOT_REQUEST,ThisVer]),
receive
{udp,S2,Ip,_Port1,Resp1} ->
- ?line close_udp(S2),
- ?line EBOOT_REPLY = string:substr(Resp1, 1, length(EBOOT_REPLY)),
- ?line Rest1 = string:substr(Resp1, length(EBOOT_REPLY)+1, length(Resp1)),
- ?line [_,_,_ | ThisVer] = Rest1
+ close_udp(S2),
+ EBOOT_REPLY = string:substr(Resp1, 1, length(EBOOT_REPLY)),
+ Rest1 = string:substr(Resp1, length(EBOOT_REPLY)+1, length(Resp1)),
+ [_,_,_ | ThisVer] = Rest1
after 2000 ->
- ?line close_udp(S2),
- ?line ?t:fail("no boot server response; same vsn")
+ close_udp(S2),
+ ct:fail("no boot server response; same vsn")
end,
-
+
%% Req from a slave with other erlang vsn.
- ?line S3 = open_udp(),
- ?line prim_inet:sendto(S3, Ip, EBOOT_PORT, [EBOOT_REQUEST,"1.0"]),
+ S3 = open_udp(),
+ prim_inet:sendto(S3, Ip, EBOOT_PORT, [EBOOT_REQUEST,"1.0"]),
receive
Anything ->
- ?line close_udp(S3),
- ?line ?t:fail({"got unexpected response",Anything})
+ close_udp(S3),
+ ct:fail({"got unexpected response",Anything})
after 100 ->
ok
end,
%% Kill the boot server and wait for it to disappear.
- ?line unlink(BootPid),
- ?line BootPidMref = erlang:monitor(process, BootPid),
- ?line exit(BootPid, kill),
+ unlink(BootPid),
+ BootPidMref = erlang:monitor(process, BootPid),
+ exit(BootPid, kill),
receive
{'DOWN',BootPidMref,_,_,_} -> ok
end,
- ?line {ok,BootPid2} = erl_boot_server:start_link(["127.0.0.1"]),
+ {ok,BootPid2} = erl_boot_server:start_link(["127.0.0.1"]),
%% Req from slave with invalid ip address.
- ?line S4 = open_udp(),
+ S4 = open_udp(),
Ret =
case Ip of
{127,0,0,1} ->
{comment,"IP address for this host is 127.0.0.1"};
_ ->
- ?line prim_inet:sendto(S4, Ip, EBOOT_PORT,
- [EBOOT_REQUEST,ThisVer]),
+ prim_inet:sendto(S4, Ip, EBOOT_PORT,
+ [EBOOT_REQUEST,ThisVer]),
receive
Huh ->
- ?line close_udp(S4),
- ?line ?t:fail({"got unexpected response",Huh})
+ close_udp(S4),
+ ct:fail({"got unexpected response",Huh})
after 100 ->
ok
end
end,
- ?line unlink(BootPid2),
- ?line exit(BootPid2, kill),
+ unlink(BootPid2),
+ exit(BootPid2, kill),
%% Now wait for any late unexpected messages.
receive
Whatever ->
- ?line ?t:fail({unexpected_message,Whatever})
+ ct:fail({unexpected_message,Whatever})
after 4000 ->
- ?line close_udp(S1),
- ?line close_udp(S3),
- ?line close_udp(S4),
+ close_udp(S1),
+ close_udp(S3),
+ close_udp(S4),
ok
end,
- ?line test_server:timetrap_cancel(Dog),
Ret.
shutdown(Pid) ->
@@ -335,7 +325,7 @@ shutdown(Pid) ->
after 1000 ->
%% The timeout used to be 1 ms, which could be too short time for the
%% SMP emulator on a slow computer with one CPU.
- test_server:fail(shutdown)
+ ct:fail(shutdown)
end.
good_hosts(_Config) ->
@@ -347,10 +337,10 @@ good_hosts(_Config) ->
[GoodHost1, GoodHost2, GoodHost3].
open_udp() ->
- ?line {ok, S} = prim_inet:open(udp, inet, dgram),
- ?line ok = prim_inet:setopts(S, [{mode,list},{active,true},
- {deliver,term},{broadcast,true}]),
- ?line {ok,_} = prim_inet:bind(S, {0,0,0,0}, 0),
+ {ok, S} = prim_inet:open(udp, inet, dgram),
+ ok = prim_inet:setopts(S, [{mode,list},{active,true},
+ {deliver,term},{broadcast,true}]),
+ {ok,_} = prim_inet:bind(S, {0,0,0,0}, 0),
S.
close_udp(S) ->
diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl
index 2f73ab170a..9951ac17e9 100644
--- a/lib/kernel/test/erl_distribution_SUITE.erl
+++ b/lib/kernel/test/erl_distribution_SUITE.erl
@@ -19,8 +19,7 @@
%%
-module(erl_distribution_SUITE).
-%-define(line_trace, 1).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
@@ -61,7 +60,9 @@
%% erl -sname master -rsh ctrsh
%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,4}}].
all() ->
[tick, tick_change, illegal_nodenames, hidden_node,
@@ -91,27 +92,22 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?t:timetrap(?t:minutes(4)),
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
+end_per_testcase(_Func, _Config) ->
+ ok.
-tick(suite) -> [];
-tick(doc) -> [];
tick(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(120)),
PaDir = filename:dirname(code:which(erl_distribution_SUITE)),
-
+
%% First check that the normal case is OK!
- ?line {ok, Node} = start_node(dist_test, "-pa " ++ PaDir),
+ {ok, Node} = start_node(dist_test, "-pa " ++ PaDir),
rpc:call(Node, erl_distribution_SUITE, tick_cli_test, [node()]),
-
+
erlang:monitor_node(Node, true),
receive
{nodedown, Node} ->
- test_server:fail("nodedown from other node")
+ ct:fail("nodedown from other node")
after 30000 ->
erlang:monitor_node(Node, false),
stop_node(Node)
@@ -129,20 +125,20 @@ tick(Config) when is_list(Config) ->
%% Set the ticktime on the server node to 100 secs so the server
%% node doesn't tick the client node within the interval ...
- ?line {ok, ServNode} = start_node(dist_test_server,
- "-kernel net_ticktime 100 "
- "-pa " ++ PaDir),
+ {ok, ServNode} = start_node(dist_test_server,
+ "-kernel net_ticktime 100 "
+ "-pa " ++ PaDir),
rpc:call(ServNode, erl_distribution_SUITE, tick_serv_test, [Node, node()]),
- ?line {ok, _} = start_node(dist_test,
- "-kernel net_ticktime 12 "
- "-pa " ++ PaDir),
+ {ok, _} = start_node(dist_test,
+ "-kernel net_ticktime 12 "
+ "-pa " ++ PaDir),
rpc:call(Node, erl_distribution_SUITE, tick_cli_test, [ServNode]),
-
+
spawn_link(erl_distribution_SUITE, keep_conn, [Node]),
{tick_serv, ServNode} ! {i_want_the_result, self()},
-
+
monitor_node(ServNode, true),
monitor_node(Node, true),
@@ -154,56 +150,47 @@ tick(Config) when is_list(Config) ->
{tick_test, Error} ->
stop_node(ServNode),
stop_node(Node),
- test_server:fail(Error);
+ ct:fail(Error);
{nodedown, Node} ->
stop_node(ServNode),
- test_server:fail("client node died");
+ ct:fail("client node died");
{nodedown, ServNode} ->
stop_node(Node),
- test_server:fail("server node died")
+ ct:fail("server node died")
end,
- ?line test_server:timetrap_cancel(Dog),
ok.
-table_waste(doc) ->
- ["Checks that pinging nonexistyent nodes does not waste space in distribution table"];
-table_waste(suite) ->
- [];
+%% Checks that pinging nonexistyent nodes does not waste space in distribution table.
table_waste(Config) when is_list(Config) ->
- ?line {ok, HName} = inet:gethostname(),
+ {ok, HName} = inet:gethostname(),
F = fun(0,_F) -> [];
(N,F) ->
- ?line Name = list_to_atom("erl_distribution_"++integer_to_list(N)++
- "@"++HName),
- ?line pang = net_adm:ping(Name),
- ?line F(N-1,F)
+ Name = list_to_atom("erl_distribution_"++integer_to_list(N)++
+ "@"++HName),
+ pang = net_adm:ping(Name),
+ F(N-1,F)
end,
- ?line F(256,F),
- ?line {ok, N} = start_node(erl_distribution_300,""),
- ?line stop_node(N),
+ F(256,F),
+ {ok, N} = start_node(erl_distribution_300,""),
+ stop_node(N),
ok.
-
-
-illegal_nodenames(doc) ->
- ["Test that pinging an illegal nodename does not kill the node"];
-illegal_nodenames(suite) ->
- [];
+
+
+%% Test that pinging an illegal nodename does not kill the node.
illegal_nodenames(Config) when is_list(Config) ->
- ?line Dog=?t:timetrap(?t:minutes(2)),
PaDir = filename:dirname(code:which(erl_distribution_SUITE)),
- ?line {ok, Node}=start_node(illegal_nodenames, "-pa " ++ PaDir),
+ {ok, Node}=start_node(illegal_nodenames, "-pa " ++ PaDir),
monitor_node(Node, true),
- ?line RPid=rpc:call(Node, erlang, spawn,
- [?MODULE, pinger, [self()]]),
+ RPid=rpc:call(Node, erlang, spawn,
+ [?MODULE, pinger, [self()]]),
receive
{RPid, pinged} ->
ok;
{nodedown, Node} ->
- ?t:fail("Remote node died.")
+ ct:fail("Remote node died.")
end,
stop_node(Node),
- ?t:timetrap_cancel(Dog),
ok.
pinger(Starter) ->
@@ -213,7 +200,7 @@ pinger(Starter) ->
ok.
-net_setuptime(doc) -> ["Test that you can set the net_setuptime properly"];
+%% Test that you can set the net_setuptime properly.
net_setuptime(Config) when is_list(Config) ->
%% In this test case, we reluctantly accept shorter times than the given
%% setup time, because the connection attempt can end in a
@@ -221,18 +208,18 @@ net_setuptime(Config) when is_list(Config) ->
Res0 = do_test_setuptime("2"),
io:format("Res0 = ~p", [Res0]),
- ?line true = (Res0 =< 4000),
+ true = (Res0 =< 4000),
Res1 = do_test_setuptime("0.3"),
io:format("Res1 = ~p", [Res1]),
- ?line true = (Res1 =< 500),
+ true = (Res1 =< 500),
ok.
do_test_setuptime(Setuptime) when is_list(Setuptime) ->
- ?line PaDir = filename:dirname(code:which(?MODULE)),
- ?line {ok, Node} = start_node(dist_setuptime_test, "-pa " ++ PaDir ++
- " -kernel net_setuptime " ++ Setuptime),
- ?line Res = rpc:call(Node,?MODULE,time_ping,[?DUMMY_NODE]),
- ?line stop_node(Node),
+ PaDir = filename:dirname(code:which(?MODULE)),
+ {ok, Node} = start_node(dist_setuptime_test, "-pa " ++ PaDir ++
+ " -kernel net_setuptime " ++ Setuptime),
+ Res = rpc:call(Node,?MODULE,time_ping,[?DUMMY_NODE]),
+ stop_node(Node),
Res.
time_ping(Node) ->
@@ -296,160 +283,159 @@ tick_cli_test1(Node) ->
end.
-tick_change(doc) -> ["OTP-4255"];
-tick_change(suite) -> [];
+%% OTP-4255.
tick_change(Config) when is_list(Config) ->
- ?line PaDir = filename:dirname(code:which(?MODULE)),
- ?line [BN, CN] = get_nodenames(2, tick_change),
- ?line DefaultTT = net_kernel:get_net_ticktime(),
- ?line unchanged = net_kernel:set_net_ticktime(DefaultTT, 60),
- ?line case DefaultTT of
- I when is_integer(I) -> ?line ok;
- _ -> ?line ?t:fail(DefaultTT)
- end,
-
- % In case other nodes are connected
+ PaDir = filename:dirname(code:which(?MODULE)),
+ [BN, CN] = get_nodenames(2, tick_change),
+ DefaultTT = net_kernel:get_net_ticktime(),
+ unchanged = net_kernel:set_net_ticktime(DefaultTT, 60),
+ case DefaultTT of
+ I when is_integer(I) -> ok;
+ _ -> ct:fail(DefaultTT)
+ end,
+
+ %% In case other nodes are connected
case nodes(connected) of
- [] -> ?line net_kernel:set_net_ticktime(10, 0);
- _ -> ?line rpc:multicall(nodes([this, connected]), net_kernel,
- set_net_ticktime, [10, 5])
+ [] -> net_kernel:set_net_ticktime(10, 0);
+ _ -> rpc:multicall(nodes([this, connected]), net_kernel,
+ set_net_ticktime, [10, 5])
end,
- ?line wait_until(fun () -> 10 == net_kernel:get_net_ticktime() end),
- ?line {ok, B} = start_node(BN, "-kernel net_ticktime 10 -pa " ++ PaDir),
- ?line {ok, C} = start_node(CN, "-kernel net_ticktime 10 -hidden -pa "
- ++ PaDir),
+ wait_until(fun () -> 10 == net_kernel:get_net_ticktime() end),
+ {ok, B} = start_node(BN, "-kernel net_ticktime 10 -pa " ++ PaDir),
+ {ok, C} = start_node(CN, "-kernel net_ticktime 10 -hidden -pa "
+ ++ PaDir),
- ?line OTE = process_flag(trap_exit, true),
+ OTE = process_flag(trap_exit, true),
case catch begin
- ?line run_tick_change_test(B, C, 10, 1, PaDir),
- ?line run_tick_change_test(B, C, 1, 10, PaDir)
+ run_tick_change_test(B, C, 10, 1, PaDir),
+ run_tick_change_test(B, C, 1, 10, PaDir)
end of
{'EXIT', Reason} ->
- ?line stop_node(B),
- ?line stop_node(C),
+ stop_node(B),
+ stop_node(C),
%% In case other nodes are connected
case nodes(connected) of
- [] -> ?line net_kernel:set_net_ticktime(DefaultTT, 0);
- _ -> ?line rpc:multicall(nodes([this, connected]), net_kernel,
- set_net_ticktime, [DefaultTT, 10])
+ [] -> net_kernel:set_net_ticktime(DefaultTT, 0);
+ _ -> rpc:multicall(nodes([this, connected]), net_kernel,
+ set_net_ticktime, [DefaultTT, 10])
end,
- ?line wait_until(fun () ->
- DefaultTT == net_kernel:get_net_ticktime()
- end),
- ?line process_flag(trap_exit, OTE),
- ?t:fail(Reason);
+ wait_until(fun () ->
+ DefaultTT == net_kernel:get_net_ticktime()
+ end),
+ process_flag(trap_exit, OTE),
+ ct:fail(Reason);
_ ->
ok
end,
- ?line process_flag(trap_exit, OTE),
- ?line stop_node(B),
- ?line stop_node(C),
+ process_flag(trap_exit, OTE),
+ stop_node(B),
+ stop_node(C),
- % In case other nodes are connected
+ %% In case other nodes are connected
case nodes(connected) of
- [] -> ?line net_kernel:set_net_ticktime(DefaultTT, 0);
- _ -> ?line rpc:multicall(nodes([this, connected]), net_kernel,
- set_net_ticktime, [DefaultTT, 5])
+ [] -> net_kernel:set_net_ticktime(DefaultTT, 0);
+ _ -> rpc:multicall(nodes([this, connected]), net_kernel,
+ set_net_ticktime, [DefaultTT, 5])
end,
- ?line wait_until(fun () -> DefaultTT == net_kernel:get_net_ticktime() end),
- ?line ok.
+ wait_until(fun () -> DefaultTT == net_kernel:get_net_ticktime() end),
+ ok.
wait_for_nodedowns(Tester, Ref) ->
receive
{nodedown, Node} ->
- ?t:format("~p~n", [{node(), {nodedown, Node}}]),
- ?line Tester ! {Ref, {node(), {nodedown, Node}}}
+ io:format("~p~n", [{node(), {nodedown, Node}}]),
+ Tester ! {Ref, {node(), {nodedown, Node}}}
end,
wait_for_nodedowns(Tester, Ref).
run_tick_change_test(B, C, PrevTT, TT, PaDir) ->
- ?line [DN, EN] = get_nodenames(2, tick_change),
-
- ?line Tester = self(),
- ?line Ref = make_ref(),
- ?line MonitorNodes = fun (Nodes) ->
- ?line lists:foreach(
- fun (N) ->
- ?line monitor_node(N,true)
- end,
- Nodes),
- wait_for_nodedowns(Tester, Ref)
- end,
-
- ?line {ok, D} = start_node(DN, "-kernel net_ticktime "
- ++ integer_to_list(PrevTT) ++ " -pa " ++ PaDir),
-
- ?line NMA = spawn_link(fun () -> MonitorNodes([B, C, D]) end),
- ?line NMB = spawn_link(B, fun () -> MonitorNodes([node(), C, D]) end),
- ?line NMC = spawn_link(C, fun () -> MonitorNodes([node(), B, D]) end),
-
- ?line MaxTT = case PrevTT > TT of
- true -> ?line PrevTT;
- false -> ?line TT
- end,
+ [DN, EN] = get_nodenames(2, tick_change),
- ?line CheckResult = make_ref(),
- ?line spawn_link(fun () ->
- receive
- after (25 + MaxTT)*1000 ->
- Tester ! CheckResult
- end
- end),
+ Tester = self(),
+ Ref = make_ref(),
+ MonitorNodes = fun (Nodes) ->
+ lists:foreach(
+ fun (N) ->
+ monitor_node(N,true)
+ end,
+ Nodes),
+ wait_for_nodedowns(Tester, Ref)
+ end,
+
+ {ok, D} = start_node(DN, "-kernel net_ticktime "
+ ++ integer_to_list(PrevTT) ++ " -pa " ++ PaDir),
+
+ NMA = spawn_link(fun () -> MonitorNodes([B, C, D]) end),
+ NMB = spawn_link(B, fun () -> MonitorNodes([node(), C, D]) end),
+ NMC = spawn_link(C, fun () -> MonitorNodes([node(), B, D]) end),
+
+ MaxTT = case PrevTT > TT of
+ true -> PrevTT;
+ false -> TT
+ end,
- % In case other nodes than these are connected
+ CheckResult = make_ref(),
+ spawn_link(fun () ->
+ receive
+ after (25 + MaxTT)*1000 ->
+ Tester ! CheckResult
+ end
+ end),
+
+ %% In case other nodes than these are connected
case nodes(connected) -- [B, C, D] of
- [] -> ?line ok;
- OtherNodes -> ?line rpc:multicall(OtherNodes, net_kernel,
- set_net_ticktime, [TT, 20])
+ [] -> ok;
+ OtherNodes -> rpc:multicall(OtherNodes, net_kernel,
+ set_net_ticktime, [TT, 20])
end,
- ?line change_initiated = net_kernel:set_net_ticktime(TT,20),
- ?line {ongoing_change_to,_} = net_kernel:set_net_ticktime(TT,20),
- ?line sleep(3),
- ?line change_initiated = rpc:call(B,net_kernel,set_net_ticktime,[TT,15]),
- ?line sleep(7),
- ?line change_initiated = rpc:call(C,net_kernel,set_net_ticktime,[TT,10]),
-
- ?line {ok, E} = start_node(EN, "-kernel net_ticktime "
- ++ integer_to_list(TT) ++ " -pa " ++ PaDir),
- ?line NME = spawn_link(E, fun () -> MonitorNodes([node(), B, C, D]) end),
- ?line NMA2 = spawn_link(fun () -> MonitorNodes([E]) end),
- ?line NMB2 = spawn_link(B, fun () -> MonitorNodes([E]) end),
- ?line NMC2 = spawn_link(C, fun () -> MonitorNodes([E]) end),
-
- receive CheckResult -> ?line ok end,
-
- ?line unlink(NMA), exit(NMA, kill),
- ?line unlink(NMB), exit(NMB, kill),
- ?line unlink(NMC), exit(NMC, kill),
- ?line unlink(NME), exit(NME, kill),
- ?line unlink(NMA2), exit(NMA2, kill),
- ?line unlink(NMB2), exit(NMB2, kill),
- ?line unlink(NMC2), exit(NMC2, kill),
+ change_initiated = net_kernel:set_net_ticktime(TT,20),
+ {ongoing_change_to,_} = net_kernel:set_net_ticktime(TT,20),
+ sleep(3),
+ change_initiated = rpc:call(B,net_kernel,set_net_ticktime,[TT,15]),
+ sleep(7),
+ change_initiated = rpc:call(C,net_kernel,set_net_ticktime,[TT,10]),
+
+ {ok, E} = start_node(EN, "-kernel net_ticktime "
+ ++ integer_to_list(TT) ++ " -pa " ++ PaDir),
+ NME = spawn_link(E, fun () -> MonitorNodes([node(), B, C, D]) end),
+ NMA2 = spawn_link(fun () -> MonitorNodes([E]) end),
+ NMB2 = spawn_link(B, fun () -> MonitorNodes([E]) end),
+ NMC2 = spawn_link(C, fun () -> MonitorNodes([E]) end),
+
+ receive CheckResult -> ok end,
+
+ unlink(NMA), exit(NMA, kill),
+ unlink(NMB), exit(NMB, kill),
+ unlink(NMC), exit(NMC, kill),
+ unlink(NME), exit(NME, kill),
+ unlink(NMA2), exit(NMA2, kill),
+ unlink(NMB2), exit(NMB2, kill),
+ unlink(NMC2), exit(NMC2, kill),
%% The node not changing ticktime should have been disconnected from the
%% other nodes
- receive {Ref, {Node, {nodedown, D}}} when Node == node() -> ?line ok
- after 0 -> ?line exit({?LINE, no_nodedown})
+ receive {Ref, {Node, {nodedown, D}}} when Node == node() -> ok
+ after 0 -> exit({?LINE, no_nodedown})
end,
- receive {Ref, {B, {nodedown, D}}} -> ?line ok
- after 0 -> ?line exit({?LINE, no_nodedown})
+ receive {Ref, {B, {nodedown, D}}} -> ok
+ after 0 -> exit({?LINE, no_nodedown})
end,
- receive {Ref, {C, {nodedown, D}}} -> ?line ok
- after 0 -> ?line exit({?LINE, no_nodedown})
+ receive {Ref, {C, {nodedown, D}}} -> ok
+ after 0 -> exit({?LINE, no_nodedown})
end,
- receive {Ref, {E, {nodedown, D}}} -> ?line ok
- after 0 -> ?line exit({?LINE, no_nodedown})
+ receive {Ref, {E, {nodedown, D}}} -> ok
+ after 0 -> exit({?LINE, no_nodedown})
end,
%% No other connections should have been broken
receive
{Ref, Reason} ->
- ?line stop_node(E),
- ?line exit({?LINE, Reason});
+ stop_node(E),
+ exit({?LINE, Reason});
{'EXIT', Pid, Reason} when Pid == NMA;
Pid == NMB;
Pid == NMC;
@@ -457,70 +443,65 @@ run_tick_change_test(B, C, PrevTT, TT, PaDir) ->
Pid == NMA2;
Pid == NMB2;
Pid == NMC2 ->
- ?line stop_node(E),
+ stop_node(E),
- ?line exit({?LINE, {node(Pid), Reason}})
+ exit({?LINE, {node(Pid), Reason}})
after 0 ->
- ?line TT = net_kernel:get_net_ticktime(),
- ?line TT = rpc:call(B, net_kernel, get_net_ticktime, []),
- ?line TT = rpc:call(C, net_kernel, get_net_ticktime, []),
- ?line TT = rpc:call(E, net_kernel, get_net_ticktime, []),
- ?line stop_node(E),
- ?line ok
+ TT = net_kernel:get_net_ticktime(),
+ TT = rpc:call(B, net_kernel, get_net_ticktime, []),
+ TT = rpc:call(C, net_kernel, get_net_ticktime, []),
+ TT = rpc:call(E, net_kernel, get_net_ticktime, []),
+ stop_node(E),
+ ok
end.
%%
%% Basic tests of hidden node.
%%
-hidden_node(doc) ->
- ["Basic test of hidden node"];
-hidden_node(suite) ->
- [];
+%% Basic test of hidden node.
hidden_node(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(40)),
PaDir = filename:dirname(code:which(?MODULE)),
VArgs = "-pa " ++ PaDir,
HArgs = "-hidden -pa " ++ PaDir,
- ?line {ok, V} = start_node(visible_node, VArgs),
+ {ok, V} = start_node(visible_node, VArgs),
VMN = start_monitor_nodes_proc(V),
- ?line {ok, H} = start_node(hidden_node, HArgs),
- % Connect visible_node -> hidden_node
+ {ok, H} = start_node(hidden_node, HArgs),
+ %% Connect visible_node -> hidden_node
connect_nodes(V, H),
test_nodes(V, H),
stop_node(H),
sleep(5),
check_monitor_nodes_res(VMN, H),
stop_node(V),
- ?line {ok, H} = start_node(hidden_node, HArgs),
+ {ok, H} = start_node(hidden_node, HArgs),
HMN = start_monitor_nodes_proc(H),
- ?line {ok, V} = start_node(visible_node, VArgs),
- % Connect hidden_node -> visible_node
+ {ok, V} = start_node(visible_node, VArgs),
+ %% Connect hidden_node -> visible_node
connect_nodes(H, V),
test_nodes(V, H),
stop_node(V),
sleep(5),
check_monitor_nodes_res(HMN, V),
stop_node(H),
- ?line ?t:timetrap_cancel(Dog),
ok.
connect_nodes(A, B) ->
- % Check that they haven't already connected.
- ?line false = lists:member(A, rpc:call(B, erlang, nodes, [connected])),
- ?line false = lists:member(B, rpc:call(A, erlang, nodes, [connected])),
- % Connect them.
- ?line pong = rpc:call(A, net_adm, ping, [B]).
-
+ %% Check that they haven't already connected.
+ false = lists:member(A, rpc:call(B, erlang, nodes, [connected])),
+ false = lists:member(B, rpc:call(A, erlang, nodes, [connected])),
+ %% Connect them.
+ pong = rpc:call(A, net_adm, ping, [B]).
+
test_nodes(V, H) ->
- % No nodes should be visible on hidden_node
- ?line [] = rpc:call(H, erlang, nodes, []),
- % visible_node should be hidden on hidden_node
- ?line true = lists:member(V, rpc:call(H, erlang, nodes, [hidden])),
- % hidden_node node shouldn't be visible on visible_node
- ?line false = lists:member(H, rpc:call(V, erlang, nodes, [])),
- % hidden_node should be hidden on visible_node
- ?line true = lists:member(H, rpc:call(V, erlang, nodes, [hidden])).
+ %% No nodes should be visible on hidden_node
+ [] = rpc:call(H, erlang, nodes, []),
+ %% visible_node should be hidden on hidden_node
+ true = lists:member(V, rpc:call(H, erlang, nodes, [hidden])),
+ %% hidden_node node shouldn't be visible on visible_node
+ false = lists:member(H, rpc:call(V, erlang, nodes, [])),
+ %% hidden_node should be hidden on visible_node
+ true = lists:member(H, rpc:call(V, erlang, nodes, [hidden])).
mn_loop(MNs) ->
receive
@@ -548,21 +529,19 @@ start_monitor_nodes_proc(Node) ->
ok
end,
Pid.
-
+
check_monitor_nodes_res(Pid, Node) ->
Ref = make_ref(),
Pid ! {monitor_nodes_result, Ref, self()},
receive
{Ref, MNs} ->
- ?line false = lists:keysearch(Node, 2, MNs)
+ false = lists:keysearch(Node, 2, MNs)
end.
-inet_dist_options_options(suite) -> [];
-inet_dist_options_options(doc) ->
- ["Check the kernel inet_dist_{listen,connect}_options options"];
+%% Check the kernel inet_dist_{listen,connect}_options options.
inet_dist_options_options(Config) when is_list(Config) ->
Prio = 1,
case gen_udp:open(0, [{priority,Prio}]) of
@@ -571,7 +550,7 @@ inet_dist_options_options(Config) when is_list(Config) ->
{ok,[{priority,Prio}]} ->
ok = gen_udp:close(Socket),
do_inet_dist_options_options(Prio);
- _ ->
+ _ ->
ok = gen_udp:close(Socket),
{skip,
"Can not set priority "++integer_to_list(Prio)++
@@ -595,25 +574,25 @@ do_inet_dist_options_options(Prio) ->
"-hidden "
"-kernel inet_dist_connect_options "++PriorityString++" "
"-kernel inet_dist_listen_options "++PriorityString,
- ?line {ok,Node1} =
+ {ok,Node1} =
start_node(inet_dist_options_1, InetDistOptions),
- ?line {ok,Node2} =
+ {ok,Node2} =
start_node(inet_dist_options_2, InetDistOptions),
%%
- ?line pong =
+ pong =
rpc:call(Node1, net_adm, ping, [Node2]),
- ?line PrioritiesNode1 =
+ PrioritiesNode1 =
rpc:call(Node1, ?MODULE, get_socket_priorities, []),
- ?line PrioritiesNode2 =
+ PrioritiesNode2 =
rpc:call(Node2, ?MODULE, get_socket_priorities, []),
- ?line ?t:format("PrioritiesNode1 = ~p", [PrioritiesNode1]),
- ?line ?t:format("PrioritiesNode2 = ~p", [PrioritiesNode2]),
- ?line Elevated = [P || P <- PrioritiesNode1, P =:= Prio],
- ?line Elevated = [P || P <- PrioritiesNode2, P =:= Prio],
- ?line [_|_] = Elevated,
+ io:format("PrioritiesNode1 = ~p", [PrioritiesNode1]),
+ io:format("PrioritiesNode2 = ~p", [PrioritiesNode2]),
+ Elevated = [P || P <- PrioritiesNode1, P =:= Prio],
+ Elevated = [P || P <- PrioritiesNode2, P =:= Prio],
+ [_|_] = Elevated,
%%
- ?line stop_node(Node2),
- ?line stop_node(Node1),
+ stop_node(Node2),
+ stop_node(Node1),
ok.
get_socket_priorities() ->
@@ -624,185 +603,178 @@ get_socket_priorities() ->
element(2, erlang:port_info(Port, name)) =:= "tcp_inet"]].
-
+
%%
%% Testcase:
%% monitor_nodes_nodedown_reason
%%
-monitor_nodes_nodedown_reason(doc) -> [];
-monitor_nodes_nodedown_reason(suite) -> [];
monitor_nodes_nodedown_reason(Config) when is_list(Config) ->
- ?line MonNodeState = monitor_node_state(),
- ?line ok = net_kernel:monitor_nodes(true),
- ?line ok = net_kernel:monitor_nodes(true, [nodedown_reason]),
-
- ?line Names = get_numbered_nodenames(5, node),
- ?line [NN1, NN2, NN3, NN4, NN5] = Names,
-
- ?line {ok, N1} = start_node(NN1),
- ?line {ok, N2} = start_node(NN2),
- ?line {ok, N3} = start_node(NN3),
- ?line {ok, N4} = start_node(NN4, "-hidden"),
-
- ?line receive {nodeup, N1} -> ok end,
- ?line receive {nodeup, N2} -> ok end,
- ?line receive {nodeup, N3} -> ok end,
-
- ?line receive {nodeup, N1, []} -> ok end,
- ?line receive {nodeup, N2, []} -> ok end,
- ?line receive {nodeup, N3, []} -> ok end,
-
- ?line stop_node(N1),
- ?line stop_node(N4),
- ?line true = net_kernel:disconnect(N2),
- ?line TickTime = net_kernel:get_net_ticktime(),
- ?line SleepTime = TickTime + (TickTime div 4),
- ?line spawn(N3, fun () ->
- block_emu(SleepTime*1000),
- halt()
- end),
-
- ?line receive {nodedown, N1} -> ok end,
- ?line receive {nodedown, N2} -> ok end,
- ?line receive {nodedown, N3} -> ok end,
-
- ?line receive {nodedown, N1, [{nodedown_reason, R1}]} -> connection_closed = R1 end,
- ?line receive {nodedown, N2, [{nodedown_reason, R2}]} -> disconnect = R2 end,
- ?line receive {nodedown, N3, [{nodedown_reason, R3}]} -> net_tick_timeout = R3 end,
-
- ?line ok = net_kernel:monitor_nodes(false, [nodedown_reason]),
-
- ?line {ok, N5} = start_node(NN5),
- ?line stop_node(N5),
-
- ?line receive {nodeup, N5} -> ok end,
- ?line receive {nodedown, N5} -> ok end,
- ?line print_my_messages(),
- ?line ok = check_no_nodedown_nodeup(1000),
- ?line ok = net_kernel:monitor_nodes(false),
- ?line MonNodeState = monitor_node_state(),
- ?line ok.
-
-
-monitor_nodes_complex_nodedown_reason(doc) -> [];
-monitor_nodes_complex_nodedown_reason(suite) -> [];
+ MonNodeState = monitor_node_state(),
+ ok = net_kernel:monitor_nodes(true),
+ ok = net_kernel:monitor_nodes(true, [nodedown_reason]),
+
+ Names = get_numbered_nodenames(5, node),
+ [NN1, NN2, NN3, NN4, NN5] = Names,
+
+ {ok, N1} = start_node(NN1),
+ {ok, N2} = start_node(NN2),
+ {ok, N3} = start_node(NN3),
+ {ok, N4} = start_node(NN4, "-hidden"),
+
+ receive {nodeup, N1} -> ok end,
+ receive {nodeup, N2} -> ok end,
+ receive {nodeup, N3} -> ok end,
+
+ receive {nodeup, N1, []} -> ok end,
+ receive {nodeup, N2, []} -> ok end,
+ receive {nodeup, N3, []} -> ok end,
+
+ stop_node(N1),
+ stop_node(N4),
+ true = net_kernel:disconnect(N2),
+ TickTime = net_kernel:get_net_ticktime(),
+ SleepTime = TickTime + (TickTime div 4),
+ spawn(N3, fun () ->
+ block_emu(SleepTime*1000),
+ halt()
+ end),
+
+ receive {nodedown, N1} -> ok end,
+ receive {nodedown, N2} -> ok end,
+ receive {nodedown, N3} -> ok end,
+
+ receive {nodedown, N1, [{nodedown_reason, R1}]} -> connection_closed = R1 end,
+ receive {nodedown, N2, [{nodedown_reason, R2}]} -> disconnect = R2 end,
+ receive {nodedown, N3, [{nodedown_reason, R3}]} -> net_tick_timeout = R3 end,
+
+ ok = net_kernel:monitor_nodes(false, [nodedown_reason]),
+
+ {ok, N5} = start_node(NN5),
+ stop_node(N5),
+
+ receive {nodeup, N5} -> ok end,
+ receive {nodedown, N5} -> ok end,
+ print_my_messages(),
+ ok = check_no_nodedown_nodeup(1000),
+ ok = net_kernel:monitor_nodes(false),
+ MonNodeState = monitor_node_state(),
+ ok.
+
+
monitor_nodes_complex_nodedown_reason(Config) when is_list(Config) ->
- ?line MonNodeState = monitor_node_state(),
- ?line Me = self(),
- ?line ok = net_kernel:monitor_nodes(true, [nodedown_reason]),
- ?line [Name] = get_nodenames(1, monitor_nodes_complex_nodedown_reason),
- ?line {ok, Node} = start_node(Name, ""),
- ?line Pid = spawn(Node,
- fun() ->
- Me ! {stuff,
- self(),
- [make_ref(),
- {processes(), erlang:ports()}]}
- end),
- ?line receive {nodeup, Node, []} -> ok end,
- ?line {ok, NodeInfo} = net_kernel:node_info(Node),
- ?line {value,{owner, Owner}} = lists:keysearch(owner, 1, NodeInfo),
- ?line ComplexTerm = receive {stuff, Pid, _} = Msg ->
- {Msg, term_to_binary(Msg)}
- end,
- ?line exit(Owner, ComplexTerm),
- ?line receive
- {nodedown, Node, [{nodedown_reason, NodeDownReason}]} ->
- ?line ok
- end,
+ MonNodeState = monitor_node_state(),
+ Me = self(),
+ ok = net_kernel:monitor_nodes(true, [nodedown_reason]),
+ [Name] = get_nodenames(1, monitor_nodes_complex_nodedown_reason),
+ {ok, Node} = start_node(Name, ""),
+ Pid = spawn(Node,
+ fun() ->
+ Me ! {stuff,
+ self(),
+ [make_ref(),
+ {processes(), erlang:ports()}]}
+ end),
+ receive {nodeup, Node, []} -> ok end,
+ {ok, NodeInfo} = net_kernel:node_info(Node),
+ {value,{owner, Owner}} = lists:keysearch(owner, 1, NodeInfo),
+ ComplexTerm = receive {stuff, Pid, _} = Msg ->
+ {Msg, term_to_binary(Msg)}
+ end,
+ exit(Owner, ComplexTerm),
+ receive
+ {nodedown, Node, [{nodedown_reason, NodeDownReason}]} ->
+ ok
+ end,
%% If the complex nodedown_reason messed something up garbage collections
%% are likely to dump core
- ?line garbage_collect(),
- ?line garbage_collect(),
- ?line garbage_collect(),
- ?line ComplexTerm = NodeDownReason,
- ?line ok = net_kernel:monitor_nodes(false, [nodedown_reason]),
- ?line no_msgs(),
- ?line MonNodeState = monitor_node_state(),
- ?line ok.
-
-
-
+ garbage_collect(),
+ garbage_collect(),
+ garbage_collect(),
+ ComplexTerm = NodeDownReason,
+ ok = net_kernel:monitor_nodes(false, [nodedown_reason]),
+ no_msgs(),
+ MonNodeState = monitor_node_state(),
+ ok.
+
+
+
%%
%% Testcase:
%% monitor_nodes_node_type
%%
-monitor_nodes_node_type(doc) -> [];
-monitor_nodes_node_type(suite) -> [];
monitor_nodes_node_type(Config) when is_list(Config) ->
- ?line MonNodeState = monitor_node_state(),
- ?line ok = net_kernel:monitor_nodes(true),
- ?line ok = net_kernel:monitor_nodes(true, [{node_type, all}]),
- ?line Names = get_numbered_nodenames(9, node),
-% ?line ?t:format("Names: ~p~n", [Names]),
- ?line [NN1, NN2, NN3, NN4, NN5, NN6, NN7, NN8, NN9] = Names,
-
- ?line {ok, N1} = start_node(NN1),
- ?line {ok, N2} = start_node(NN2),
- ?line {ok, N3} = start_node(NN3, "-hidden"),
- ?line {ok, N4} = start_node(NN4, "-hidden"),
-
- ?line receive {nodeup, N1} -> ok end,
- ?line receive {nodeup, N2} -> ok end,
-
- ?line receive {nodeup, N1, [{node_type, visible}]} -> ok end,
- ?line receive {nodeup, N2, [{node_type, visible}]} -> ok end,
- ?line receive {nodeup, N3, [{node_type, hidden}]} -> ok end,
- ?line receive {nodeup, N4, [{node_type, hidden}]} -> ok end,
-
- ?line stop_node(N1),
- ?line stop_node(N2),
- ?line stop_node(N3),
- ?line stop_node(N4),
-
- ?line receive {nodedown, N1} -> ok end,
- ?line receive {nodedown, N2} -> ok end,
-
- ?line receive {nodedown, N1, [{node_type, visible}]} -> ok end,
- ?line receive {nodedown, N2, [{node_type, visible}]} -> ok end,
- ?line receive {nodedown, N3, [{node_type, hidden}]} -> ok end,
- ?line receive {nodedown, N4, [{node_type, hidden}]} -> ok end,
-
- ?line ok = net_kernel:monitor_nodes(false, [{node_type, all}]),
- ?line {ok, N5} = start_node(NN5),
-
- ?line receive {nodeup, N5} -> ok end,
- ?line stop_node(N5),
- ?line receive {nodedown, N5} -> ok end,
-
- ?line ok = net_kernel:monitor_nodes(true, [{node_type, hidden}]),
- ?line {ok, N6} = start_node(NN6),
- ?line {ok, N7} = start_node(NN7, "-hidden"),
-
-
- ?line receive {nodeup, N6} -> ok end,
- ?line receive {nodeup, N7, [{node_type, hidden}]} -> ok end,
- ?line stop_node(N6),
- ?line stop_node(N7),
-
- ?line receive {nodedown, N6} -> ok end,
- ?line receive {nodedown, N7, [{node_type, hidden}]} -> ok end,
-
- ?line ok = net_kernel:monitor_nodes(true, [{node_type, visible}]),
- ?line ok = net_kernel:monitor_nodes(false, [{node_type, hidden}]),
- ?line ok = net_kernel:monitor_nodes(false),
-
- ?line {ok, N8} = start_node(NN8),
- ?line {ok, N9} = start_node(NN9, "-hidden"),
-
- ?line receive {nodeup, N8, [{node_type, visible}]} -> ok end,
- ?line stop_node(N8),
- ?line stop_node(N9),
-
- ?line receive {nodedown, N8, [{node_type, visible}]} -> ok end,
- ?line print_my_messages(),
- ?line ok = check_no_nodedown_nodeup(1000),
- ?line ok = net_kernel:monitor_nodes(false, [{node_type, visible}]),
- ?line MonNodeState = monitor_node_state(),
- ?line ok.
+ MonNodeState = monitor_node_state(),
+ ok = net_kernel:monitor_nodes(true),
+ ok = net_kernel:monitor_nodes(true, [{node_type, all}]),
+ Names = get_numbered_nodenames(9, node),
+ [NN1, NN2, NN3, NN4, NN5, NN6, NN7, NN8, NN9] = Names,
+
+ {ok, N1} = start_node(NN1),
+ {ok, N2} = start_node(NN2),
+ {ok, N3} = start_node(NN3, "-hidden"),
+ {ok, N4} = start_node(NN4, "-hidden"),
+
+ receive {nodeup, N1} -> ok end,
+ receive {nodeup, N2} -> ok end,
+
+ receive {nodeup, N1, [{node_type, visible}]} -> ok end,
+ receive {nodeup, N2, [{node_type, visible}]} -> ok end,
+ receive {nodeup, N3, [{node_type, hidden}]} -> ok end,
+ receive {nodeup, N4, [{node_type, hidden}]} -> ok end,
+
+ stop_node(N1),
+ stop_node(N2),
+ stop_node(N3),
+ stop_node(N4),
+
+ receive {nodedown, N1} -> ok end,
+ receive {nodedown, N2} -> ok end,
+
+ receive {nodedown, N1, [{node_type, visible}]} -> ok end,
+ receive {nodedown, N2, [{node_type, visible}]} -> ok end,
+ receive {nodedown, N3, [{node_type, hidden}]} -> ok end,
+ receive {nodedown, N4, [{node_type, hidden}]} -> ok end,
+
+ ok = net_kernel:monitor_nodes(false, [{node_type, all}]),
+ {ok, N5} = start_node(NN5),
+
+ receive {nodeup, N5} -> ok end,
+ stop_node(N5),
+ receive {nodedown, N5} -> ok end,
+
+ ok = net_kernel:monitor_nodes(true, [{node_type, hidden}]),
+ {ok, N6} = start_node(NN6),
+ {ok, N7} = start_node(NN7, "-hidden"),
+
+
+ receive {nodeup, N6} -> ok end,
+ receive {nodeup, N7, [{node_type, hidden}]} -> ok end,
+ stop_node(N6),
+ stop_node(N7),
+
+ receive {nodedown, N6} -> ok end,
+ receive {nodedown, N7, [{node_type, hidden}]} -> ok end,
+
+ ok = net_kernel:monitor_nodes(true, [{node_type, visible}]),
+ ok = net_kernel:monitor_nodes(false, [{node_type, hidden}]),
+ ok = net_kernel:monitor_nodes(false),
+
+ {ok, N8} = start_node(NN8),
+ {ok, N9} = start_node(NN9, "-hidden"),
+
+ receive {nodeup, N8, [{node_type, visible}]} -> ok end,
+ stop_node(N8),
+ stop_node(N9),
+
+ receive {nodedown, N8, [{node_type, visible}]} -> ok end,
+ print_my_messages(),
+ ok = check_no_nodedown_nodeup(1000),
+ ok = net_kernel:monitor_nodes(false, [{node_type, visible}]),
+ MonNodeState = monitor_node_state(),
+ ok.
%%
@@ -810,95 +782,89 @@ monitor_nodes_node_type(Config) when is_list(Config) ->
%% monitor_nodes
%%
-monitor_nodes_misc(doc) -> [];
-monitor_nodes_misc(suite) -> [];
monitor_nodes_misc(Config) when is_list(Config) ->
- ?line MonNodeState = monitor_node_state(),
- ?line ok = net_kernel:monitor_nodes(true),
- ?line ok = net_kernel:monitor_nodes(true, [{node_type, all}, nodedown_reason]),
- ?line ok = net_kernel:monitor_nodes(true, [nodedown_reason, {node_type, all}]),
- ?line Names = get_numbered_nodenames(3, node),
-% ?line ?t:format("Names: ~p~n", [Names]),
- ?line [NN1, NN2, NN3] = Names,
-
- ?line {ok, N1} = start_node(NN1),
- ?line {ok, N2} = start_node(NN2, "-hidden"),
-
- ?line receive {nodeup, N1} -> ok end,
-
- ?line receive {nodeup, N1, [{node_type, visible}]} -> ok end,
- ?line receive {nodeup, N1, [{node_type, visible}]} -> ok end,
- ?line receive {nodeup, N2, [{node_type, hidden}]} -> ok end,
- ?line receive {nodeup, N2, [{node_type, hidden}]} -> ok end,
-
- ?line stop_node(N1),
- ?line stop_node(N2),
-
- ?line VisbleDownInfo = lists:sort([{node_type, visible},
- {nodedown_reason, connection_closed}]),
- ?line HiddenDownInfo = lists:sort([{node_type, hidden},
- {nodedown_reason, connection_closed}]),
-
- ?line receive {nodedown, N1} -> ok end,
-
- ?line receive {nodedown, N1, Info1A} -> VisbleDownInfo = lists:sort(Info1A) end,
- ?line receive {nodedown, N1, Info1B} -> VisbleDownInfo = lists:sort(Info1B) end,
- ?line receive {nodedown, N2, Info2A} -> HiddenDownInfo = lists:sort(Info2A) end,
- ?line receive {nodedown, N2, Info2B} -> HiddenDownInfo = lists:sort(Info2B) end,
-
- ?line ok = net_kernel:monitor_nodes(false, [{node_type, all}, nodedown_reason]),
-
- ?line {ok, N3} = start_node(NN3),
- ?line receive {nodeup, N3} -> ok end,
- ?line stop_node(N3),
- ?line receive {nodedown, N3} -> ok end,
- ?line print_my_messages(),
- ?line ok = check_no_nodedown_nodeup(1000),
- ?line ok = net_kernel:monitor_nodes(false),
- ?line MonNodeState = monitor_node_state(),
- ?line ok.
-
-
-monitor_nodes_otp_6481(doc) ->
- ["Tests that {nodeup, Node} messages are received before "
- "messages from Node and that {nodedown, Node} messages are"
- "received after messages from Node"];
-monitor_nodes_otp_6481(suite) ->
- [];
+ MonNodeState = monitor_node_state(),
+ ok = net_kernel:monitor_nodes(true),
+ ok = net_kernel:monitor_nodes(true, [{node_type, all}, nodedown_reason]),
+ ok = net_kernel:monitor_nodes(true, [nodedown_reason, {node_type, all}]),
+ Names = get_numbered_nodenames(3, node),
+ [NN1, NN2, NN3] = Names,
+
+ {ok, N1} = start_node(NN1),
+ {ok, N2} = start_node(NN2, "-hidden"),
+
+ receive {nodeup, N1} -> ok end,
+
+ receive {nodeup, N1, [{node_type, visible}]} -> ok end,
+ receive {nodeup, N1, [{node_type, visible}]} -> ok end,
+ receive {nodeup, N2, [{node_type, hidden}]} -> ok end,
+ receive {nodeup, N2, [{node_type, hidden}]} -> ok end,
+
+ stop_node(N1),
+ stop_node(N2),
+
+ VisbleDownInfo = lists:sort([{node_type, visible},
+ {nodedown_reason, connection_closed}]),
+ HiddenDownInfo = lists:sort([{node_type, hidden},
+ {nodedown_reason, connection_closed}]),
+
+ receive {nodedown, N1} -> ok end,
+
+ receive {nodedown, N1, Info1A} -> VisbleDownInfo = lists:sort(Info1A) end,
+ receive {nodedown, N1, Info1B} -> VisbleDownInfo = lists:sort(Info1B) end,
+ receive {nodedown, N2, Info2A} -> HiddenDownInfo = lists:sort(Info2A) end,
+ receive {nodedown, N2, Info2B} -> HiddenDownInfo = lists:sort(Info2B) end,
+
+ ok = net_kernel:monitor_nodes(false, [{node_type, all}, nodedown_reason]),
+
+ {ok, N3} = start_node(NN3),
+ receive {nodeup, N3} -> ok end,
+ stop_node(N3),
+ receive {nodedown, N3} -> ok end,
+ print_my_messages(),
+ ok = check_no_nodedown_nodeup(1000),
+ ok = net_kernel:monitor_nodes(false),
+ MonNodeState = monitor_node_state(),
+ ok.
+
+
+%% Tests that {nodeup, Node} messages are received before
+%% messages from Node and that {nodedown, Node} messages are
+%% received after messages from Node.
monitor_nodes_otp_6481(Config) when is_list(Config) ->
- ?line ?t:format("Testing nodedown...~n"),
- ?line monitor_nodes_otp_6481_test(Config, nodedown),
- ?line ?t:format("ok~n"),
- ?line ?t:format("Testing nodeup...~n"),
- ?line monitor_nodes_otp_6481_test(Config, nodeup),
- ?line ?t:format("ok~n"),
- ?line ok.
+ io:format("Testing nodedown...~n"),
+ monitor_nodes_otp_6481_test(Config, nodedown),
+ io:format("ok~n"),
+ io:format("Testing nodeup...~n"),
+ monitor_nodes_otp_6481_test(Config, nodeup),
+ io:format("ok~n"),
+ ok.
monitor_nodes_otp_6481_test(Config, TestType) when is_list(Config) ->
- ?line MonNodeState = monitor_node_state(),
- ?line NodeMsg = make_ref(),
- ?line Me = self(),
- ?line [Name] = get_nodenames(1, monitor_nodes_otp_6481),
- ?line case TestType of
- nodedown -> ?line ok = net_kernel:monitor_nodes(true);
- nodeup -> ?line ok
- end,
- ?line Seq = lists:seq(1,10000),
- ?line MN = spawn_link(
- fun () ->
- ?line lists:foreach(
- fun (_) ->
- ?line ok = net_kernel:monitor_nodes(true)
- end,
- Seq),
- ?line Me ! {mon_set, self()},
- ?line receive after infinity -> ok end
- end),
- ?line receive {mon_set, MN} -> ok end,
- ?line case TestType of
- nodedown -> ?line ok;
- nodeup -> ?line ok = net_kernel:monitor_nodes(true)
- end,
+ MonNodeState = monitor_node_state(),
+ NodeMsg = make_ref(),
+ Me = self(),
+ [Name] = get_nodenames(1, monitor_nodes_otp_6481),
+ case TestType of
+ nodedown -> ok = net_kernel:monitor_nodes(true);
+ nodeup -> ok
+ end,
+ Seq = lists:seq(1,10000),
+ MN = spawn_link(
+ fun () ->
+ lists:foreach(
+ fun (_) ->
+ ok = net_kernel:monitor_nodes(true)
+ end,
+ Seq),
+ Me ! {mon_set, self()},
+ receive after infinity -> ok end
+ end),
+ receive {mon_set, MN} -> ok end,
+ case TestType of
+ nodedown -> ok;
+ nodeup -> ok = net_kernel:monitor_nodes(true)
+ end,
%% Whitebox:
%% nodedown test: Since this process was the first one monitoring
@@ -909,60 +875,60 @@ monitor_nodes_otp_6481_test(Config, TestType) when is_list(Config) ->
%% on nodeup
%% Verify the monitor_nodes order expected
- ?line TestMonNodeState = monitor_node_state(),
- %?line ?t:format("~p~n", [TestMonNodeState]),
- ?line TestMonNodeState =
+ TestMonNodeState = monitor_node_state(),
+ %% io:format("~p~n", [TestMonNodeState]),
+ TestMonNodeState =
MonNodeState
++ case TestType of
- nodedown -> [{self(), []}];
- nodeup -> []
+ nodedown -> [{self(), []}];
+ nodeup -> []
end
++ lists:map(fun (_) -> {MN, []} end, Seq)
++ case TestType of
- nodedown -> [];
- nodeup -> [{self(), []}]
+ nodedown -> [];
+ nodeup -> [{self(), []}]
end,
- ?line {ok, Node} = start_node(Name, "", this),
- ?line receive {nodeup, Node} -> ok end,
-
- ?line RemotePid = spawn(Node,
- fun () ->
- receive after 1500 -> ok end,
- % infinit loop of msgs
- % we want an endless stream of messages and the kill
- % the node mercilessly.
- % We then want to ensure that the nodedown message arrives
- % last ... without garbage after it.
- _ = spawn(fun() -> node_loop_send(Me, NodeMsg, 1) end),
- receive {Me, kill_it} -> ok end,
- halt()
- end),
+ {ok, Node} = start_node(Name, "", this),
+ receive {nodeup, Node} -> ok end,
+
+ RemotePid = spawn(Node,
+ fun () ->
+ receive after 1500 -> ok end,
+ %% infinit loop of msgs
+ %% we want an endless stream of messages and the kill
+ %% the node mercilessly.
+ %% We then want to ensure that the nodedown message arrives
+ %% last ... without garbage after it.
+ _ = spawn(fun() -> node_loop_send(Me, NodeMsg, 1) end),
+ receive {Me, kill_it} -> ok end,
+ halt()
+ end),
- ?line net_kernel:disconnect(Node),
- ?line receive {nodedown, Node} -> ok end,
+ net_kernel:disconnect(Node),
+ receive {nodedown, Node} -> ok end,
%% Verify that '{nodeup, Node}' comes before '{NodeMsg, 1}' (the message
%% bringing up the connection).
- ?line no_msgs(500),
- ?line {nodeup, Node} = receive Msg1 -> Msg1 end,
- ?line {NodeMsg, 1} = receive Msg2 -> Msg2 end,
- % msg stream has begun, kill the node
- ?line RemotePid ! {self(), kill_it},
+ no_msgs(500),
+ {nodeup, Node} = receive Msg1 -> Msg1 end,
+ {NodeMsg, 1} = receive Msg2 -> Msg2 end,
+ %% msg stream has begun, kill the node
+ RemotePid ! {self(), kill_it},
%% Verify that '{nodedown, Node}' comes after the last '{NodeMsg, N}'
%% message.
- ?line {nodedown, Node} = flush_node_msgs(NodeMsg, 2),
- ?line no_msgs(500),
-
- ?line Mon = erlang:monitor(process, MN),
- ?line unlink(MN),
- ?line exit(MN, bang),
- ?line receive {'DOWN', Mon, process, MN, bang} -> ok end,
- ?line ok = net_kernel:monitor_nodes(false),
- ?line MonNodeState = monitor_node_state(),
- ?line ok.
+ {nodedown, Node} = flush_node_msgs(NodeMsg, 2),
+ no_msgs(500),
+
+ Mon = erlang:monitor(process, MN),
+ unlink(MN),
+ exit(MN, bang),
+ receive {'DOWN', Mon, process, MN, bang} -> ok end,
+ ok = net_kernel:monitor_nodes(false),
+ MonNodeState = monitor_node_state(),
+ ok.
flush_node_msgs(NodeMsg, No) ->
case receive Msg -> Msg end of
@@ -974,105 +940,97 @@ node_loop_send(Pid, Msg, No) ->
Pid ! {Msg, No},
node_loop_send(Pid, Msg, No + 1).
-monitor_nodes_errors(doc) ->
- [];
-monitor_nodes_errors(suite) ->
- [];
monitor_nodes_errors(Config) when is_list(Config) ->
- ?line MonNodeState = monitor_node_state(),
- ?line error = net_kernel:monitor_nodes(asdf),
- ?line {error,
- {unknown_options,
- [gurka]}} = net_kernel:monitor_nodes(true,
- [gurka]),
- ?line {error,
- {options_not_a_list,
- gurka}} = net_kernel:monitor_nodes(true,
- gurka),
- ?line {error,
- {option_value_mismatch,
- [{node_type,visible},
- {node_type,hidden}]}}
+ MonNodeState = monitor_node_state(),
+ error = net_kernel:monitor_nodes(asdf),
+ {error,
+ {unknown_options,
+ [gurka]}} = net_kernel:monitor_nodes(true,
+ [gurka]),
+ {error,
+ {options_not_a_list,
+ gurka}} = net_kernel:monitor_nodes(true,
+ gurka),
+ {error,
+ {option_value_mismatch,
+ [{node_type,visible},
+ {node_type,hidden}]}}
= net_kernel:monitor_nodes(true,
[{node_type,hidden},
{node_type,visible}]),
- ?line {error,
- {option_value_mismatch,
- [{node_type,visible},
- {node_type,all}]}}
+ {error,
+ {option_value_mismatch,
+ [{node_type,visible},
+ {node_type,all}]}}
= net_kernel:monitor_nodes(true,
[{node_type,all},
{node_type,visible}]),
- ?line {error,
- {bad_option_value,
- {node_type,
- blaha}}}
+ {error,
+ {bad_option_value,
+ {node_type,
+ blaha}}}
= net_kernel:monitor_nodes(true, [{node_type, blaha}]),
- ?line MonNodeState = monitor_node_state(),
- ?line ok.
+ MonNodeState = monitor_node_state(),
+ ok.
-monitor_nodes_combinations(doc) ->
- [];
-monitor_nodes_combinations(suite) ->
- [];
monitor_nodes_combinations(Config) when is_list(Config) ->
- ?line MonNodeState = monitor_node_state(),
- ?line monitor_nodes_all_comb(true),
- ?line [VisibleName, HiddenName] = get_nodenames(2,
- monitor_nodes_combinations),
- ?line {ok, Visible} = start_node(VisibleName, ""),
- ?line receive_all_comb_nodeup_msgs(visible, Visible),
- ?line no_msgs(),
- ?line stop_node(Visible),
- ?line receive_all_comb_nodedown_msgs(visible, Visible, connection_closed),
- ?line no_msgs(),
- ?line {ok, Hidden} = start_node(HiddenName, "-hidden"),
- ?line receive_all_comb_nodeup_msgs(hidden, Hidden),
- ?line no_msgs(),
- ?line stop_node(Hidden),
- ?line receive_all_comb_nodedown_msgs(hidden, Hidden, connection_closed),
- ?line no_msgs(),
- ?line monitor_nodes_all_comb(false),
- ?line MonNodeState = monitor_node_state(),
- ?line no_msgs(),
- ?line ok.
+ MonNodeState = monitor_node_state(),
+ monitor_nodes_all_comb(true),
+ [VisibleName, HiddenName] = get_nodenames(2,
+ monitor_nodes_combinations),
+ {ok, Visible} = start_node(VisibleName, ""),
+ receive_all_comb_nodeup_msgs(visible, Visible),
+ no_msgs(),
+ stop_node(Visible),
+ receive_all_comb_nodedown_msgs(visible, Visible, connection_closed),
+ no_msgs(),
+ {ok, Hidden} = start_node(HiddenName, "-hidden"),
+ receive_all_comb_nodeup_msgs(hidden, Hidden),
+ no_msgs(),
+ stop_node(Hidden),
+ receive_all_comb_nodedown_msgs(hidden, Hidden, connection_closed),
+ no_msgs(),
+ monitor_nodes_all_comb(false),
+ MonNodeState = monitor_node_state(),
+ no_msgs(),
+ ok.
monitor_nodes_all_comb(Flag) ->
- ?line ok = net_kernel:monitor_nodes(Flag),
- ?line ok = net_kernel:monitor_nodes(Flag,
- [nodedown_reason]),
- ?line ok = net_kernel:monitor_nodes(Flag,
- [{node_type, hidden}]),
- ?line ok = net_kernel:monitor_nodes(Flag,
- [{node_type, visible}]),
- ?line ok = net_kernel:monitor_nodes(Flag,
- [{node_type, all}]),
- ?line ok = net_kernel:monitor_nodes(Flag,
- [nodedown_reason,
- {node_type, hidden}]),
- ?line ok = net_kernel:monitor_nodes(Flag,
- [nodedown_reason,
- {node_type, visible}]),
- ?line ok = net_kernel:monitor_nodes(Flag,
- [nodedown_reason,
- {node_type, all}]),
+ ok = net_kernel:monitor_nodes(Flag),
+ ok = net_kernel:monitor_nodes(Flag,
+ [nodedown_reason]),
+ ok = net_kernel:monitor_nodes(Flag,
+ [{node_type, hidden}]),
+ ok = net_kernel:monitor_nodes(Flag,
+ [{node_type, visible}]),
+ ok = net_kernel:monitor_nodes(Flag,
+ [{node_type, all}]),
+ ok = net_kernel:monitor_nodes(Flag,
+ [nodedown_reason,
+ {node_type, hidden}]),
+ ok = net_kernel:monitor_nodes(Flag,
+ [nodedown_reason,
+ {node_type, visible}]),
+ ok = net_kernel:monitor_nodes(Flag,
+ [nodedown_reason,
+ {node_type, all}]),
%% There currently are 8 different combinations
- ?line 8.
+ 8.
receive_all_comb_nodeup_msgs(visible, Node) ->
- ?t:format("Receive nodeup visible...~n"),
+ io:format("Receive nodeup visible...~n"),
Exp = [{nodeup, Node},
{nodeup, Node, []}]
++ mk_exp_mn_all_comb_nodeup_msgs_common(visible, Node),
receive_mn_msgs(Exp),
- ?t:format("ok~n"),
+ io:format("ok~n"),
ok;
receive_all_comb_nodeup_msgs(hidden, Node) ->
- ?t:format("Receive nodeup hidden...~n"),
+ io:format("Receive nodeup hidden...~n"),
Exp = mk_exp_mn_all_comb_nodeup_msgs_common(hidden, Node),
receive_mn_msgs(Exp),
- ?t:format("ok~n"),
+ io:format("ok~n"),
ok.
mk_exp_mn_all_comb_nodeup_msgs_common(Type, Node) ->
@@ -1083,20 +1041,20 @@ mk_exp_mn_all_comb_nodeup_msgs_common(Type, Node) ->
{nodeup, Node, InfoNt}].
receive_all_comb_nodedown_msgs(visible, Node, Reason) ->
- ?t:format("Receive nodedown visible...~n"),
+ io:format("Receive nodedown visible...~n"),
Exp = [{nodedown, Node},
{nodedown, Node, [{nodedown_reason, Reason}]}]
++ mk_exp_mn_all_comb_nodedown_msgs_common(visible,
Node,
Reason),
receive_mn_msgs(Exp),
- ?t:format("ok~n"),
+ io:format("ok~n"),
ok;
receive_all_comb_nodedown_msgs(hidden, Node, Reason) ->
- ?t:format("Receive nodedown hidden...~n"),
+ io:format("Receive nodedown hidden...~n"),
Exp = mk_exp_mn_all_comb_nodedown_msgs_common(hidden, Node, Reason),
receive_mn_msgs(Exp),
- ?t:format("ok~n"),
+ io:format("ok~n"),
ok.
mk_exp_mn_all_comb_nodedown_msgs_common(Type, Node, Reason) ->
@@ -1110,81 +1068,73 @@ mk_exp_mn_all_comb_nodedown_msgs_common(Type, Node, Reason) ->
receive_mn_msgs([]) ->
ok;
receive_mn_msgs(Msgs) ->
- ?t:format("Expecting msgs: ~p~n", [Msgs]),
+ io:format("Expecting msgs: ~p~n", [Msgs]),
receive
{_Dir, _Node} = Msg ->
- ?t:format("received ~p~n", [Msg]),
+ io:format("received ~p~n", [Msg]),
case lists:member(Msg, Msgs) of
true -> receive_mn_msgs(lists:delete(Msg, Msgs));
- false -> ?t:fail({unexpected_message, Msg,
+ false -> ct:fail({unexpected_message, Msg,
expected_messages, Msgs})
end;
{Dir, Node, Info} ->
Msg = {Dir, Node, lists:sort(Info)},
- ?t:format("received ~p~n", [Msg]),
+ io:format("received ~p~n", [Msg]),
case lists:member(Msg, Msgs) of
true -> receive_mn_msgs(lists:delete(Msg, Msgs));
- false -> ?t:fail({unexpected_message, Msg,
+ false -> ct:fail({unexpected_message, Msg,
expected_messages, Msgs})
end;
Msg ->
- ?t:format("received ~p~n", [Msg]),
- ?t:fail({unexpected_message, Msg,
+ io:format("received ~p~n", [Msg]),
+ ct:fail({unexpected_message, Msg,
expected_messages, Msgs})
end.
-monitor_nodes_cleanup(doc) ->
- [];
-monitor_nodes_cleanup(suite) ->
- [];
monitor_nodes_cleanup(Config) when is_list(Config) ->
- ?line MonNodeState = monitor_node_state(),
- ?line Me = self(),
- ?line No = monitor_nodes_all_comb(true),
- ?line Inf = spawn(fun () ->
- monitor_nodes_all_comb(true),
- Me ! {mons_set, self()},
- receive after infinity -> ok end
- end),
- ?line TO = spawn(fun () ->
- monitor_nodes_all_comb(true),
- Me ! {mons_set, self()},
- receive after 500 -> ok end
- end),
- ?line receive {mons_set, Inf} -> ok end,
- ?line receive {mons_set, TO} -> ok end,
- ?line MNLen = length(MonNodeState) + No*3,
- ?line MNLen = length(monitor_node_state()),
- ?line MonInf = erlang:monitor(process, Inf),
- ?line MonTO = erlang:monitor(process, TO),
- ?line exit(Inf, bang),
- ?line No = monitor_nodes_all_comb(false),
- ?line receive {'DOWN', MonInf, process, Inf, bang} -> ok end,
- ?line receive {'DOWN', MonTO, process, TO, normal} -> ok end,
- ?line MonNodeState = monitor_node_state(),
- ?line no_msgs(),
- ?line ok.
-
-monitor_nodes_many(doc) ->
- [];
-monitor_nodes_many(suite) ->
- [];
+ MonNodeState = monitor_node_state(),
+ Me = self(),
+ No = monitor_nodes_all_comb(true),
+ Inf = spawn(fun () ->
+ monitor_nodes_all_comb(true),
+ Me ! {mons_set, self()},
+ receive after infinity -> ok end
+ end),
+ TO = spawn(fun () ->
+ monitor_nodes_all_comb(true),
+ Me ! {mons_set, self()},
+ receive after 500 -> ok end
+ end),
+ receive {mons_set, Inf} -> ok end,
+ receive {mons_set, TO} -> ok end,
+ MNLen = length(MonNodeState) + No*3,
+ MNLen = length(monitor_node_state()),
+ MonInf = erlang:monitor(process, Inf),
+ MonTO = erlang:monitor(process, TO),
+ exit(Inf, bang),
+ No = monitor_nodes_all_comb(false),
+ receive {'DOWN', MonInf, process, Inf, bang} -> ok end,
+ receive {'DOWN', MonTO, process, TO, normal} -> ok end,
+ MonNodeState = monitor_node_state(),
+ no_msgs(),
+ ok.
+
monitor_nodes_many(Config) when is_list(Config) ->
- ?line MonNodeState = monitor_node_state(),
- ?line [Name] = get_nodenames(1, monitor_nodes_many),
+ MonNodeState = monitor_node_state(),
+ [Name] = get_nodenames(1, monitor_nodes_many),
%% We want to perform more than 2^16 net_kernel:monitor_nodes
%% since this will wrap an internal counter
- ?line No = (1 bsl 16) + 17,
- ?line repeat(fun () -> ok = net_kernel:monitor_nodes(true) end, No),
- ?line No = length(monitor_node_state()) - length(MonNodeState),
- ?line {ok, Node} = start_node(Name),
- ?line repeat(fun () -> receive {nodeup, Node} -> ok end end, No),
- ?line stop_node(Node),
- ?line repeat(fun () -> receive {nodedown, Node} -> ok end end, No),
- ?line ok = net_kernel:monitor_nodes(false),
- ?line no_msgs(10),
- ?line MonNodeState = monitor_node_state(),
- ?line ok.
+ No = (1 bsl 16) + 17,
+ repeat(fun () -> ok = net_kernel:monitor_nodes(true) end, No),
+ No = length(monitor_node_state()) - length(MonNodeState),
+ {ok, Node} = start_node(Name),
+ repeat(fun () -> receive {nodeup, Node} -> ok end end, No),
+ stop_node(Node),
+ repeat(fun () -> receive {nodedown, Node} -> ok end end, No),
+ ok = net_kernel:monitor_nodes(false),
+ no_msgs(10),
+ MonNodeState = monitor_node_state(),
+ ok.
%% Misc. functions
@@ -1196,59 +1146,45 @@ monitor_node_state() ->
check_no_nodedown_nodeup(TimeOut) ->
- ?line receive
- {nodeup, _, _} = Msg -> ?line ?t:fail({unexpected_nodeup, Msg});
- {nodeup, _} = Msg -> ?line ?t:fail({unexpected_nodeup, Msg});
- {nodedown, _, _} = Msg -> ?line ?t:fail({unexpected_nodedown, Msg});
- {nodedown, _} = Msg -> ?line ?t:fail({unexpected_nodedown, Msg})
- after TimeOut ->
- ok
- end.
+ receive
+ {nodeup, _, _} = Msg -> ct:fail({unexpected_nodeup, Msg});
+ {nodeup, _} = Msg -> ct:fail({unexpected_nodeup, Msg});
+ {nodedown, _, _} = Msg -> ct:fail({unexpected_nodedown, Msg});
+ {nodedown, _} = Msg -> ct:fail({unexpected_nodedown, Msg})
+ after TimeOut ->
+ ok
+ end.
print_my_messages() ->
- ?line {messages, Messages} = process_info(self(), messages),
- ?line ?t:format("Messages: ~p~n", [Messages]),
- ?line ok.
+ {messages, Messages} = process_info(self(), messages),
+ io:format("Messages: ~p~n", [Messages]),
+ ok.
sleep(T) -> receive after T * 1000 -> ok end.
start_node(Name, Param, this) ->
NewParam = Param ++ " -pa " ++ filename:dirname(code:which(?MODULE)),
- ?t:start_node(Name, peer, [{args, NewParam}, {erl, [this]}]);
+ test_server:start_node(Name, peer, [{args, NewParam}, {erl, [this]}]);
start_node(Name, Param, "this") ->
NewParam = Param ++ " -pa " ++ filename:dirname(code:which(?MODULE)),
- ?t:start_node(Name, peer, [{args, NewParam}, {erl, [this]}]);
+ test_server:start_node(Name, peer, [{args, NewParam}, {erl, [this]}]);
start_node(Name, Param, Rel) when is_atom(Rel) ->
NewParam = Param ++ " -pa " ++ filename:dirname(code:which(?MODULE)),
- ?t:start_node(Name, peer, [{args, NewParam}, {erl, [{release, atom_to_list(Rel)}]}]);
+ test_server:start_node(Name, peer, [{args, NewParam}, {erl, [{release, atom_to_list(Rel)}]}]);
start_node(Name, Param, Rel) when is_list(Rel) ->
NewParam = Param ++ " -pa " ++ filename:dirname(code:which(?MODULE)),
- ?t:start_node(Name, peer, [{args, NewParam}, {erl, [{release, Rel}]}]).
+ test_server:start_node(Name, peer, [{args, NewParam}, {erl, [{release, Rel}]}]).
start_node(Name, Param) ->
NewParam = Param ++ " -pa " ++ filename:dirname(code:which(?MODULE)),
- ?t:start_node(Name, slave, [{args, NewParam}]).
-% M = list_to_atom(from($@, atom_to_list(node()))),
-% slave:start_link(M, Name, Param).
+ test_server:start_node(Name, slave, [{args, NewParam}]).
start_node(Name) ->
start_node(Name, "").
stop_node(Node) ->
- ?t:stop_node(Node).
-% erlang:monitor_node(Node, true),
-% rpc:cast(Node, init, stop, []),
-% receive
-% {nodedown, Node} ->
-% ok
-% after 10000 ->
-% test_server:fail({stop_node, Node})
-% end.
-
-% from(H, [H | T]) -> T;
-% from(H, [_ | T]) -> from(H, T);
-% from(H, []) -> [].
+ test_server:stop_node(Node).
get_nodenames(N, T) ->
get_nodenames(N, T, []).
diff --git a/lib/kernel/test/erl_distribution_wb_SUITE.erl b/lib/kernel/test/erl_distribution_wb_SUITE.erl
index c107e92fae..dc60b8b9e9 100644
--- a/lib/kernel/test/erl_distribution_wb_SUITE.erl
+++ b/lib/kernel/test/erl_distribution_wb_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(erl_distribution_wb_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/inet.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -71,7 +71,7 @@
-define(i16(X1,X0),
(?u16(X1,X0) -
- (if (X1) > 127 -> 16#10000; true -> 0 end))).
+ (if (X1) > 127 -> 16#10000; true -> 0 end))).
-define(u16(X1,X0),
(((X1) bsl 8) bor (X0))).
@@ -79,7 +79,9 @@
-define(u32(X3,X2,X1,X0),
(((X3) bsl 24) bor ((X2) bsl 16) bor ((X1) bsl 8) bor (X0))).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[whitebox, switch_options, missing_compulsory_dflags].
@@ -101,39 +103,33 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?t:timetrap(?t:minutes(1)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
-
-switch_options(doc) ->
- ["Tests switching of options for the tcp port, as this is done"
- " when the distribution port is to be shortcut into the emulator."
- " Maybe this should be in the inet test suite, but only the distribution"
- " does such horrible things..."];
+ Config.
+
+end_per_testcase(_Func, _Config) ->
+ ok.
+
+%% Tests switching of options for the tcp port, as this is done
+%% when the distribution port is to be shortcut into the emulator.
+%% Maybe this should be in the inet test suite, but only the distribution
+%% does such horrible things...
switch_options(Config) when is_list(Config) ->
ok = test_switch_active(),
ok = test_switch_active_partial() ,
ok = test_switch_active_and_packet(),
ok.
-
-whitebox(doc) ->
- ["Whitebox testing of distribution handshakes. Tests both BC with R5 and "
- "the md5 version. Note that after R6B, this should be revised to "
- "remove BC code."];
+
+%% Whitebox testing of distribution handshakes.
whitebox(Config) when is_list(Config) ->
- ?line {ok, Node} = start_node(?MODULE,""),
- ?line Cookie = erlang:get_cookie(),
- ?line {_,Host} = split(node()),
- ?line ok = pending_up_md5(Node, join(ccc,Host), Cookie),
- ?line ok = simultaneous_md5(Node, join('A',Host), Cookie),
- ?line ok = simultaneous_md5(Node, join(zzzzzzzzzzzzzz,Host), Cookie),
- ?line stop_node(Node),
+ {ok, Node} = start_node(?MODULE,""),
+ Cookie = erlang:get_cookie(),
+ {_,Host} = split(node()),
+ ok = pending_up_md5(Node, join(ccc,Host), Cookie),
+ ok = simultaneous_md5(Node, join('A',Host), Cookie),
+ ok = simultaneous_md5(Node, join(zzzzzzzzzzzzzz,Host), Cookie),
+ stop_node(Node),
ok.
-
+
%%
%% The actual tests
%%
@@ -143,56 +139,56 @@ whitebox(Config) when is_list(Config) ->
%%
test_switch_active() ->
- ?line {Client, Server} = socket_pair(0, 4),
- ?line ok = write_packets_32(Client, 1, 5),
+ {Client, Server} = socket_pair(0, 4),
+ ok = write_packets_32(Client, 1, 5),
receive after 2000 -> ok end,
- ?line ok = read_packets(Server, 1, 1),
+ ok = read_packets(Server, 1, 1),
receive after 2000 -> ok end,
- ?line ok = read_packets(Server, 2, 2),
- ?line inet:setopts(Server, [{active, true}]),
- ?line ok = receive_packets(Server, 3, 5),
+ ok = read_packets(Server, 2, 2),
+ inet:setopts(Server, [{active, true}]),
+ ok = receive_packets(Server, 3, 5),
close_pair({Client, Server}),
ok.
-
+
test_switch_active_partial() ->
- ?line {Client, Server} = socket_pair(0, 4),
- ?line ok = write_packets_32(Client, 1, 2),
- ?line ok = gen_tcp:send(Client,[?int32(4), [0,0,0]]),
+ {Client, Server} = socket_pair(0, 4),
+ ok = write_packets_32(Client, 1, 2),
+ ok = gen_tcp:send(Client,[?int32(4), [0,0,0]]),
receive after 2000 -> ok end,
- ?line ok = read_packets(Server, 1, 1),
+ ok = read_packets(Server, 1, 1),
receive after 2000 -> ok end,
- ?line ok = read_packets(Server, 2, 2),
- ?line inet:setopts(Server, [{active, true}]),
- ?line ok = gen_tcp:send(Client,[3]),
- ?line ok = write_packets_32(Client, 4, 5),
- ?line ok = receive_packets(Server, 3, 5),
+ ok = read_packets(Server, 2, 2),
+ inet:setopts(Server, [{active, true}]),
+ ok = gen_tcp:send(Client,[3]),
+ ok = write_packets_32(Client, 4, 5),
+ ok = receive_packets(Server, 3, 5),
close_pair({Client, Server}),
ok.
-
+
do_test_switch_active_and_packet(SendBefore, SendAfter) ->
- ?line {Client, Server} = socket_pair(0, 2),
- ?line ok = write_packets_16(Client, 1, 2),
- ?line ok = gen_tcp:send(Client,SendBefore),
+ {Client, Server} = socket_pair(0, 2),
+ ok = write_packets_16(Client, 1, 2),
+ ok = gen_tcp:send(Client,SendBefore),
receive after 2000 -> ok end,
- ?line ok = read_packets(Server, 1, 1),
+ ok = read_packets(Server, 1, 1),
receive after 2000 -> ok end,
- ?line ok = read_packets(Server, 2, 2),
- ?line inet:setopts(Server, [{packet,4}, {active, true}]),
- ?line ok = gen_tcp:send(Client,SendAfter),
- ?line ok = write_packets_32(Client, 4, 5),
- ?line ok = receive_packets(Server, 3, 5),
+ ok = read_packets(Server, 2, 2),
+ inet:setopts(Server, [{packet,4}, {active, true}]),
+ ok = gen_tcp:send(Client,SendAfter),
+ ok = write_packets_32(Client, 4, 5),
+ ok = receive_packets(Server, 3, 5),
close_pair({Client, Server}),
ok.
test_switch_active_and_packet() ->
- ?line ok = do_test_switch_active_and_packet([0],[0,0,4,0,0,0,3]),
- ?line ok = do_test_switch_active_and_packet([0,0],[0,4,0,0,0,3]),
- ?line ok = do_test_switch_active_and_packet([0,0,0],[4,0,0,0,3]),
- ?line ok = do_test_switch_active_and_packet([0,0,0,4],[0,0,0,3]),
- ?line ok = do_test_switch_active_and_packet([0,0,0,4,0],[0,0,3]),
- ?line ok = do_test_switch_active_and_packet([0,0,0,4,0,0],[0,3]),
- ?line ok = do_test_switch_active_and_packet([0,0,0,4,0,0,0],[3]),
- ?line ok = do_test_switch_active_and_packet([0,0,0,4,0,0,0,3],[]),
+ ok = do_test_switch_active_and_packet([0],[0,0,4,0,0,0,3]),
+ ok = do_test_switch_active_and_packet([0,0],[0,4,0,0,0,3]),
+ ok = do_test_switch_active_and_packet([0,0,0],[4,0,0,0,3]),
+ ok = do_test_switch_active_and_packet([0,0,0,4],[0,0,0,3]),
+ ok = do_test_switch_active_and_packet([0,0,0,4,0],[0,0,3]),
+ ok = do_test_switch_active_and_packet([0,0,0,4,0,0],[0,3]),
+ ok = do_test_switch_active_and_packet([0,0,0,4,0,0,0],[3]),
+ ok = do_test_switch_active_and_packet([0,0,0,4,0,0,0,3],[]),
ok.
@@ -200,181 +196,180 @@ test_switch_active_and_packet() ->
%% Handshake tests
%%
pending_up_md5(Node,OurName,Cookie) ->
- ?line {NA,NB} = split(Node),
- ?line {port,PortNo,_} = erl_epmd:port_please(NA,NB),
- ?line {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo,
- [{active,false},
- {packet,2}]),
- ?line send_name(SocketA,OurName,5),
- ?line ok = recv_status(SocketA),
- ?line {hidden,Node,5,HisChallengeA} = recv_challenge(SocketA), % See 1)
- ?line OurChallengeA = gen_challenge(),
- ?line OurDigestA = gen_digest(HisChallengeA, Cookie),
- ?line send_challenge_reply(SocketA, OurChallengeA, OurDigestA),
- ?line ok = recv_challenge_ack(SocketA, OurChallengeA, Cookie),
- %%%
- %%% OK, one connection is up, now lets be nasty and try another up:
- %%%
- %%% But wait for a while, the other node might not have done setnode
- %%% just yet...
- ?line receive after 1000 -> ok end,
- ?line {ok, SocketB} = gen_tcp:connect(atom_to_list(NB),PortNo,
- [{active,false},
- {packet,2}]),
- ?line send_name(SocketB,OurName,5),
- ?line alive = recv_status(SocketB),
- ?line send_status(SocketB, true),
- ?line gen_tcp:close(SocketA),
- ?line {hidden,Node,5,HisChallengeB} = recv_challenge(SocketB), % See 1)
- ?line OurChallengeB = gen_challenge(),
- ?line OurDigestB = gen_digest(HisChallengeB, Cookie),
- ?line send_challenge_reply(SocketB, OurChallengeB, OurDigestB),
- ?line ok = recv_challenge_ack(SocketB, OurChallengeB, Cookie),
- %%%
- %%% Well, are we happy?
- %%%
-
- ?line inet:setopts(SocketB, [{active, false},
- {packet, 4}]),
- ?line gen_tcp:send(SocketB,build_rex_message('',OurName)),
- ?line {Header, Message} = recv_message(SocketB),
- ?line io:format("Received header ~p, data ~p.~n",
+ {NA,NB} = split(Node),
+ {port,PortNo,_} = erl_epmd:port_please(NA,NB),
+ {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo,
+ [{active,false},
+ {packet,2}]),
+ send_name(SocketA,OurName,5),
+ ok = recv_status(SocketA),
+ {hidden,Node,5,HisChallengeA} = recv_challenge(SocketA), % See 1)
+ OurChallengeA = gen_challenge(),
+ OurDigestA = gen_digest(HisChallengeA, Cookie),
+ send_challenge_reply(SocketA, OurChallengeA, OurDigestA),
+ ok = recv_challenge_ack(SocketA, OurChallengeA, Cookie),
+%%%
+%%% OK, one connection is up, now lets be nasty and try another up:
+%%%
+%%% But wait for a while, the other node might not have done setnode
+%%% just yet...
+ receive after 1000 -> ok end,
+ {ok, SocketB} = gen_tcp:connect(atom_to_list(NB),PortNo,
+ [{active,false},
+ {packet,2}]),
+ send_name(SocketB,OurName,5),
+ alive = recv_status(SocketB),
+ send_status(SocketB, true),
+ gen_tcp:close(SocketA),
+ {hidden,Node,5,HisChallengeB} = recv_challenge(SocketB), % See 1)
+ OurChallengeB = gen_challenge(),
+ OurDigestB = gen_digest(HisChallengeB, Cookie),
+ send_challenge_reply(SocketB, OurChallengeB, OurDigestB),
+ ok = recv_challenge_ack(SocketB, OurChallengeB, Cookie),
+%%%
+%%% Well, are we happy?
+%%%
+
+ inet:setopts(SocketB, [{active, false},
+ {packet, 4}]),
+ gen_tcp:send(SocketB,build_rex_message('',OurName)),
+ {Header, Message} = recv_message(SocketB),
+ io:format("Received header ~p, data ~p.~n",
[Header, Message]),
- ?line gen_tcp:close(SocketB),
+ gen_tcp:close(SocketB),
ok.
simultaneous_md5(Node, OurName, Cookie) when OurName < Node ->
- ?line pong = net_adm:ping(Node),
- ?line LSocket = case gen_tcp:listen(0, [{active, false}, {packet,2}]) of
+ pong = net_adm:ping(Node),
+ LSocket = case gen_tcp:listen(0, [{active, false}, {packet,2}]) of
{ok, Socket} ->
Socket;
Else ->
exit(Else)
end,
- ?line EpmdSocket = register(OurName, LSocket, 1, 5),
- ?line {NA, NB} = split(Node),
- ?line rpc:cast(Node, net_adm, ping, [OurName]),
- ?line receive after 1000 -> ok end,
- ?line {port, PortNo, _} = erl_epmd:port_please(NA,NB),
- ?line {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo,
- [{active,false},
- {packet,2}]),
- ?line send_name(SocketA,OurName,5),
+ EpmdSocket = register(OurName, LSocket, 1, 5),
+ {NA, NB} = split(Node),
+ rpc:cast(Node, net_adm, ping, [OurName]),
+ receive after 1000 -> ok end,
+ {port, PortNo, _} = erl_epmd:port_please(NA,NB),
+ {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo,
+ [{active,false},
+ {packet,2}]),
+ send_name(SocketA,OurName,5),
%% We are still not marked up on the other side, as our first message
%% is not sent.
- ?line SocketB = case gen_tcp:accept(LSocket) of
+ SocketB = case gen_tcp:accept(LSocket) of
{ok, Socket1} ->
- ?line Socket1;
+ Socket1;
Else2 ->
- ?line exit(Else2)
+ exit(Else2)
end,
- ?line nok = recv_status(SocketA),
- % Now we are expected to close A
- ?line gen_tcp:close(SocketA),
- % But still Socket B will continue
- ?line {normal,Node,5} = recv_name(SocketB), % See 1)
- ?line send_status(SocketB, ok_simultaneous),
- ?line MyChallengeB = gen_challenge(),
- ?line send_challenge(SocketB, OurName, MyChallengeB,5),
- ?line HisChallengeB = recv_challenge_reply(SocketB, MyChallengeB, Cookie),
- ?line DigestB = gen_digest(HisChallengeB,Cookie),
- ?line send_challenge_ack(SocketB, DigestB),
- ?line inet:setopts(SocketB, [{active, false},
- {packet, 4}]),
- % This should be the ping message.
- ?line {Header, Message} = recv_message(SocketB),
- ?line io:format("Received header ~p, data ~p.~n",
+ nok = recv_status(SocketA),
+ %% Now we are expected to close A
+ gen_tcp:close(SocketA),
+ %% But still Socket B will continue
+ {normal,Node,5} = recv_name(SocketB), % See 1)
+ send_status(SocketB, ok_simultaneous),
+ MyChallengeB = gen_challenge(),
+ send_challenge(SocketB, OurName, MyChallengeB,5),
+ HisChallengeB = recv_challenge_reply(SocketB, MyChallengeB, Cookie),
+ DigestB = gen_digest(HisChallengeB,Cookie),
+ send_challenge_ack(SocketB, DigestB),
+ inet:setopts(SocketB, [{active, false},
+ {packet, 4}]),
+ %% This should be the ping message.
+ {Header, Message} = recv_message(SocketB),
+ io:format("Received header ~p, data ~p.~n",
[Header, Message]),
- ?line gen_tcp:close(SocketB),
- ?line gen_tcp:close(LSocket),
- ?line gen_tcp:close(EpmdSocket),
+ gen_tcp:close(SocketB),
+ gen_tcp:close(LSocket),
+ gen_tcp:close(EpmdSocket),
ok;
-
+
simultaneous_md5(Node, OurName, Cookie) when OurName > Node ->
- ?line pong = net_adm:ping(Node),
- ?line LSocket = case gen_tcp:listen(0, [{active, false}, {packet,2}]) of
- {ok, Socket} ->
- ?line Socket;
- Else ->
- ?line exit(Else)
- end,
- ?line EpmdSocket = register(OurName, LSocket, 1, 5),
- ?line {NA, NB} = split(Node),
- ?line rpc:cast(Node, net_adm, ping, [OurName]),
- ?line receive after 1000 -> ok end,
- ?line {port, PortNo, _} = erl_epmd:port_please(NA,NB),
- ?line {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo,
- [{active,false},
- {packet,2}]),
- ?line SocketB = case gen_tcp:accept(LSocket) of
+ pong = net_adm:ping(Node),
+ LSocket = case gen_tcp:listen(0, [{active, false}, {packet,2}]) of
+ {ok, Socket} ->
+ Socket;
+ Else ->
+ exit(Else)
+ end,
+ EpmdSocket = register(OurName, LSocket, 1, 5),
+ {NA, NB} = split(Node),
+ rpc:cast(Node, net_adm, ping, [OurName]),
+ receive after 1000 -> ok end,
+ {port, PortNo, _} = erl_epmd:port_please(NA,NB),
+ {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo,
+ [{active,false},
+ {packet,2}]),
+ SocketB = case gen_tcp:accept(LSocket) of
{ok, Socket1} ->
- ?line Socket1;
+ Socket1;
Else2 ->
- ?line exit(Else2)
+ exit(Else2)
end,
- ?line send_name(SocketA,OurName,5),
- ?line ok_simultaneous = recv_status(SocketA),
+ send_name(SocketA,OurName,5),
+ ok_simultaneous = recv_status(SocketA),
%% Socket B should die during this
- ?line case catch begin
- ?line {normal,Node,5} = recv_name(SocketB), % See 1)
- ?line send_status(SocketB, ok_simultaneous),
- ?line MyChallengeB = gen_challenge(),
- ?line send_challenge(SocketB, OurName, MyChallengeB,
- 5),
- ?line HisChallengeB = recv_challenge_reply(
- SocketB,
- MyChallengeB,
- Cookie),
- ?line DigestB = gen_digest(HisChallengeB,Cookie),
- ?line send_challenge_ack(SocketB, DigestB),
- ?line inet:setopts(SocketB, [{active, false},
- {packet, 4}]),
- ?line {HeaderB, MessageB} = recv_message(SocketB),
- ?line io:format("Received header ~p, data ~p.~n",
- [HeaderB, MessageB])
- end of
- {'EXIT', Exitcode} ->
- ?line io:format("Expected exitsignal caught: ~p.~n",
- [Exitcode]);
- Success ->
- ?line io:format("Unexpected success: ~p~n",
- [Success]),
- ?line exit(unexpected_success)
- end,
- ?line gen_tcp:close(SocketB),
+ case catch begin
+ {normal,Node,5} = recv_name(SocketB), % See 1)
+ send_status(SocketB, ok_simultaneous),
+ MyChallengeB = gen_challenge(),
+ send_challenge(SocketB, OurName, MyChallengeB,
+ 5),
+ HisChallengeB = recv_challenge_reply(
+ SocketB,
+ MyChallengeB,
+ Cookie),
+ DigestB = gen_digest(HisChallengeB,Cookie),
+ send_challenge_ack(SocketB, DigestB),
+ inet:setopts(SocketB, [{active, false},
+ {packet, 4}]),
+ {HeaderB, MessageB} = recv_message(SocketB),
+ io:format("Received header ~p, data ~p.~n",
+ [HeaderB, MessageB])
+ end of
+ {'EXIT', Exitcode} ->
+ io:format("Expected exitsignal caught: ~p.~n",
+ [Exitcode]);
+ Success ->
+ io:format("Unexpected success: ~p~n",
+ [Success]),
+ exit(unexpected_success)
+ end,
+ gen_tcp:close(SocketB),
%% But still Socket A will continue
- ?line {hidden,Node,5,HisChallengeA} = recv_challenge(SocketA), % See 1)
- ?line OurChallengeA = gen_challenge(),
- ?line OurDigestA = gen_digest(HisChallengeA, Cookie),
- ?line send_challenge_reply(SocketA, OurChallengeA, OurDigestA),
- ?line ok = recv_challenge_ack(SocketA, OurChallengeA, Cookie),
-
- ?line inet:setopts(SocketA, [{active, false},
- {packet, 4}]),
- ?line gen_tcp:send(SocketA,build_rex_message('',OurName)),
- ?line {Header, Message} = recv_message(SocketA),
- ?line io:format("Received header ~p, data ~p.~n",
+ {hidden,Node,5,HisChallengeA} = recv_challenge(SocketA), % See 1)
+ OurChallengeA = gen_challenge(),
+ OurDigestA = gen_digest(HisChallengeA, Cookie),
+ send_challenge_reply(SocketA, OurChallengeA, OurDigestA),
+ ok = recv_challenge_ack(SocketA, OurChallengeA, Cookie),
+
+ inet:setopts(SocketA, [{active, false},
+ {packet, 4}]),
+ gen_tcp:send(SocketA,build_rex_message('',OurName)),
+ {Header, Message} = recv_message(SocketA),
+ io:format("Received header ~p, data ~p.~n",
[Header, Message]),
- ?line gen_tcp:close(SocketA),
- ?line gen_tcp:close(LSocket),
- ?line gen_tcp:close(EpmdSocket),
+ gen_tcp:close(SocketA),
+ gen_tcp:close(LSocket),
+ gen_tcp:close(EpmdSocket),
ok.
-missing_compulsory_dflags(doc) -> [];
missing_compulsory_dflags(Config) when is_list(Config) ->
- ?line [Name1, Name2] = get_nodenames(2, missing_compulsory_dflags),
- ?line {ok, Node} = start_node(Name1,""),
- ?line {NA,NB} = split(Node),
- ?line {port,PortNo,_} = erl_epmd:port_please(NA,NB),
- ?line {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo,
- [{active,false},
- {packet,2}]),
- ?line BadNode = list_to_atom(atom_to_list(Name2)++"@"++atom_to_list(NB)),
- ?line send_name(SocketA,BadNode,5,0),
- ?line not_allowed = recv_status(SocketA),
- ?line gen_tcp:close(SocketA),
- ?line stop_node(Node),
- ?line ok.
+ [Name1, Name2] = get_nodenames(2, missing_compulsory_dflags),
+ {ok, Node} = start_node(Name1,""),
+ {NA,NB} = split(Node),
+ {port,PortNo,_} = erl_epmd:port_please(NA,NB),
+ {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo,
+ [{active,false},
+ {packet,2}]),
+ BadNode = list_to_atom(atom_to_list(Name2)++"@"++atom_to_list(NB)),
+ send_name(SocketA,BadNode,5,0),
+ not_allowed = recv_status(SocketA),
+ gen_tcp:close(SocketA),
+ stop_node(Node),
+ ok.
%%
%% Here comes the utilities
@@ -437,7 +432,7 @@ socket_pair(ClientPack, ServerPack) ->
{ok, Server} = gen_tcp:accept(Listen),
gen_tcp:close(Listen),
{Client, Server}.
-
+
close_pair({Client, Server}) ->
gen_tcp:close(Client),
gen_tcp:close(Server),
@@ -454,7 +449,7 @@ close_pair({Client, Server}) ->
gen_challenge() ->
rand:uniform(1000000).
-
+
%% Generate a message digest from Challenge number and Cookie
gen_digest(Challenge, Cookie) when is_integer(Challenge), is_atom(Cookie) ->
C0 = erlang:md5_init(),
@@ -595,15 +590,15 @@ do_register_node(NodeName, TcpPort, VLow, VHigh) ->
Elen = length(Extra),
Len = 1+2+1+1+2+2+2+length(Name)+2+Elen,
gen_tcp:send(Socket, [?int16(Len), $x,
- ?int16(TcpPort),
- $M,
- 0,
- ?int16(VHigh),
- ?int16(VLow),
- ?int16(length(Name)),
- Name,
- ?int16(Elen),
- Extra]),
+ ?int16(TcpPort),
+ $M,
+ 0,
+ ?int16(VHigh),
+ ?int16(VLow),
+ ?int16(length(Name)),
+ Name,
+ ?int16(Elen),
+ Extra]),
case wait_for_reg_reply(Socket, []) of
{error, epmd_close} ->
exit(epmd_broken);
@@ -666,11 +661,11 @@ split(Atom) ->
build_rex_message(Cookie,OurName) ->
[$?,term_to_binary({6,self(),Cookie,rex}),
term_to_binary({'$gen_cast',
- {cast,
- rpc,
- cast,
- [OurName, hello, world, []],
- self()} })].
+ {cast,
+ rpc,
+ cast,
+ [OurName, hello, world, []],
+ self()} })].
%% Receive a distribution message
recv_message(Socket) ->
@@ -698,10 +693,10 @@ join(Name,Host) ->
%% start/stop slave.
start_node(Name, Param) ->
- ?t:start_node(Name, slave, [{args, Param}]).
+ test_server:start_node(Name, slave, [{args, Param}]).
stop_node(Node) ->
- ?t:stop_node(Node).
+ test_server:stop_node(Node).
get_nodenames(N, T) ->
diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl
index 0803cf428f..3ea925ee9a 100644
--- a/lib/kernel/test/erl_prim_loader_SUITE.erl
+++ b/lib/kernel/test/erl_prim_loader_SUITE.erl
@@ -20,31 +20,35 @@
-module(erl_prim_loader_SUITE).
-include_lib("kernel/include/file.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2,end_per_testcase/2,
init_per_group/2,end_per_group/2]).
-export([get_path/1, set_path/1, get_file/1, normalize_and_backslash/1,
inet_existing/1, inet_coming_up/1, inet_disconnects/1,
multiple_slaves/1, file_requests/1,
local_archive/1, remote_archive/1,
- primary_archive/1, virtual_dir_in_archive/1]).
+ primary_archive/1, virtual_dir_in_archive/1,
+ get_modules/1]).
--export([init_per_testcase/2, end_per_testcase/2]).
%%-----------------------------------------------------------------
%% Test suite for erl_prim_loader. (Most code is run during system start/stop.)
%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,3}}].
all() ->
[get_path, set_path, get_file,
normalize_and_backslash, inet_existing,
inet_coming_up, inet_disconnects, multiple_slaves,
file_requests, local_archive, remote_archive,
- primary_archive, virtual_dir_in_archive].
+ primary_archive, virtual_dir_in_archive,
+ get_modules].
groups() ->
[].
@@ -62,53 +66,88 @@ end_per_group(_GroupName, Config) ->
Config.
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?t:timetrap(?t:minutes(3)),
- [{watchdog, Dog}|Config].
+init_per_testcase(_Func, Config) ->
+ Config.
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
+end_per_testcase(_Func, _Config) ->
+ ok.
-get_path(doc) -> [];
get_path(Config) when is_list(Config) ->
- ?line case erl_prim_loader:get_path() of
- {ok, Path} when is_list(Path) ->
- ok;
- _ ->
- test_server:fail(get_path)
- end,
+ case erl_prim_loader:get_path() of
+ {ok, Path} when is_list(Path) ->
+ ok;
+ _ ->
+ ct:fail(get_path)
+ end,
ok.
-set_path(doc) -> [];
set_path(Config) when is_list(Config) ->
- ?line {ok, Path} = erl_prim_loader:get_path(),
- ?line ok = erl_prim_loader:set_path(Path),
- ?line {ok, Path} = erl_prim_loader:get_path(),
+ {ok, Path} = erl_prim_loader:get_path(),
+ ok = erl_prim_loader:set_path(Path),
+ {ok, Path} = erl_prim_loader:get_path(),
NewPath = Path ++ ["dummy_dir","/dummy_dir/dummy_dir"],
- ?line ok = erl_prim_loader:set_path(NewPath),
- ?line {ok, NewPath} = erl_prim_loader:get_path(),
+ ok = erl_prim_loader:set_path(NewPath),
+ {ok, NewPath} = erl_prim_loader:get_path(),
- ?line ok = erl_prim_loader:set_path(Path), % Reset path.
- ?line {ok, Path} = erl_prim_loader:get_path(),
+ ok = erl_prim_loader:set_path(Path), % Reset path.
+ {ok, Path} = erl_prim_loader:get_path(),
- ?line {'EXIT',_} = (catch erl_prim_loader:set_path(not_a_list)),
- ?line {ok, Path} = erl_prim_loader:get_path(),
+ {'EXIT',_} = (catch erl_prim_loader:set_path(not_a_list)),
+ {ok, Path} = erl_prim_loader:get_path(),
ok.
-get_file(doc) -> [];
get_file(Config) when is_list(Config) ->
- ?line case erl_prim_loader:get_file("lists" ++ code:objfile_extension()) of
- {ok,Bin,File} when is_binary(Bin), is_list(File) ->
- ok;
- _ ->
- test_server:fail(get_valid_file)
- end,
- ?line error = erl_prim_loader:get_file("duuuuuuummmy_file"),
- ?line error = erl_prim_loader:get_file(duuuuuuummmy_file),
- ?line error = erl_prim_loader:get_file({dummy}),
+ case erl_prim_loader:get_file("lists" ++ code:objfile_extension()) of
+ {ok,Bin,File} when is_binary(Bin), is_list(File) ->
+ ok;
+ _ ->
+ ct:fail(get_valid_file)
+ end,
+ error = erl_prim_loader:get_file("duuuuuuummmy_file"),
+ error = erl_prim_loader:get_file(duuuuuuummmy_file),
+ error = erl_prim_loader:get_file({dummy}),
+ ok.
+
+get_modules(_Config) ->
+ case test_server:is_cover() of
+ false -> do_get_modules();
+ true -> {skip,"Cover"}
+ end.
+
+do_get_modules() ->
+ MsGood = lists:sort([lists,gen_server,gb_trees,code_server]),
+ Ms = [certainly_not_existing|MsGood],
+ SuccExp = [begin
+ F = code:which(M),
+ {ok,Code} = file:read_file(F),
+ {M,{F,erlang:md5(Code)}}
+ end || M <- MsGood],
+ FailExp = [{certainly_not_existing,enoent}],
+
+ io:format("SuccExp = ~p\n", [SuccExp]),
+ io:format("FailExp = ~p\n", [FailExp]),
+
+ Path = code:get_path(),
+ Process = fun(_, F, Code) -> {ok,{F,erlang:md5(Code)}} end,
+ {ok,{Succ,FailExp}} = erl_prim_loader:get_modules(Ms, Process, Path),
+ SuccExp = lists:sort(Succ),
+
+ Name = inet_get_modules,
+ {ok, Node, BootPid} = complete_start_node(Name),
+ ThisDir = filename:dirname(code:which(?MODULE)),
+ true = rpc:call(Node, code, add_patha, [ThisDir]),
+ _ = rpc:call(Node, code, ensure_loaded, [?MODULE]),
+ {ok,{InetSucc,FailExp}} = rpc:call(Node, erl_prim_loader,
+ get_modules, [Ms,Process,Path]),
+ SuccExp = lists:sort(InetSucc),
+
+ stop_node(Node),
+ unlink(BootPid),
+ exit(BootPid, kill),
+
ok.
+
normalize_and_backslash(Config) ->
%% Test OTP-11170
case os:type() of
@@ -118,7 +157,7 @@ normalize_and_backslash(Config) ->
test_normalize_and_backslash(Config)
end.
test_normalize_and_backslash(Config) ->
- PrivDir = ?config(priv_dir,Config),
+ PrivDir = proplists:get_value(priv_dir,Config),
Dir = filename:join(PrivDir,"\\"),
File = filename:join(Dir,"file-OTP-11170"),
ok = file:make_dir(Dir),
@@ -129,41 +168,27 @@ test_normalize_and_backslash(Config) ->
ok = file:del_dir(Dir),
ok.
-inet_existing(doc) -> ["Start a node using the 'inet' loading method, ",
- "from an already started boot server."];
+%% Start a node using the 'inet' loading method,
+%% from an already started boot server.
inet_existing(Config) when is_list(Config) ->
Name = erl_prim_test_inet_existing,
- Host = host(),
- Cookie = atom_to_list(erlang:get_cookie()),
- IpStr = ip_str(Host),
- LFlag = get_loader_flag(os:type()),
- Args = LFlag ++ " -hosts " ++ IpStr ++
- " -setcookie " ++ Cookie,
- {ok, BootPid} = erl_boot_server:start_link([Host]),
- {ok, Node} = start_node(Name, Args),
+ BootPid = start_boot_server(),
+ Node = start_node_using_inet(Name),
{ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]),
stop_node(Node),
unlink(BootPid),
exit(BootPid, kill),
ok.
-inet_coming_up(doc) -> ["Start a node using the 'inet' loading method, ",
- "but start the boot server afterwards."];
+%% Start a node using the 'inet' loading method,
+%% but start the boot server afterwards.
inet_coming_up(Config) when is_list(Config) ->
Name = erl_prim_test_inet_coming_up,
- Cookie = atom_to_list(erlang:get_cookie()),
- Host = host(),
- IpStr = ip_str(Host),
- LFlag = get_loader_flag(os:type()),
- Args = LFlag ++
- " -hosts " ++ IpStr ++
- " -setcookie " ++ Cookie,
- {ok, Node} = start_node(Name, Args, [{wait, false}]),
+ Node = start_node_using_inet(Name, [{wait,false}]),
%% Wait a while, then start boot server, and wait for node to start.
- test_server:sleep(test_server:seconds(6)),
- io:format("erl_boot_server:start_link([~p]).", [Host]),
- {ok, BootPid} = erl_boot_server:start_link([Host]),
+ ct:sleep({seconds,6}),
+ BootPid = start_boot_server(),
wait_really_started(Node, 25),
%% Check loader argument, then cleanup.
@@ -174,41 +199,36 @@ inet_coming_up(Config) when is_list(Config) ->
ok.
wait_really_started(Node, 0) ->
- test_server:fail({not_booted,Node});
+ ct:fail({not_booted,Node});
wait_really_started(Node, N) ->
case rpc:call(Node, init, get_status, []) of
{started, _} ->
ok;
_ ->
- test_server:sleep(1000),
+ ct:sleep(1000),
wait_really_started(Node, N - 1)
end.
-inet_disconnects(doc) -> ["Start a node using the 'inet' loading method, ",
- "then lose the connection."];
+%% Start a node using the 'inet' loading method,
+%% then lose the connection.
inet_disconnects(Config) when is_list(Config) ->
case test_server:is_native(erl_boot_server) of
true ->
{skip,"erl_boot_server is native"};
false ->
- ?line Name = erl_prim_test_inet_disconnects,
- ?line Host = host(),
- ?line Cookie = atom_to_list(erlang:get_cookie()),
- ?line IpStr = ip_str(Host),
- ?line LFlag = get_loader_flag(os:type()),
- ?line Args = LFlag ++ " -hosts " ++ IpStr ++
- " -setcookie " ++ Cookie,
-
- ?line {ok, BootPid} = erl_boot_server:start([Host]),
+ Name = erl_prim_test_inet_disconnects,
+
+ BootPid = start_boot_server(),
+ unlink(BootPid),
Self = self(),
%% This process shuts down the boot server during loading.
- ?line Stopper = spawn_link(fun() -> stop_boot(BootPid, Self) end),
- ?line receive
- {Stopper,ready} -> ok
- end,
+ Stopper = spawn_link(fun() -> stop_boot(BootPid, Self) end),
+ receive
+ {Stopper,ready} -> ok
+ end,
%% Let the loading begin...
- ?line {ok, Node} = start_node(Name, Args, [{wait, false}]),
+ Node = start_node_using_inet(Name, [{wait,false}]),
%% When the stopper is ready, the slave node should be
%% looking for a boot server again.
@@ -216,18 +236,18 @@ inet_disconnects(Config) when is_list(Config) ->
{Stopper,ok} ->
ok;
{Stopper,{error,Reason}} ->
- ?line ?t:fail(Reason)
+ ct:fail(Reason)
after 60000 ->
- ?line ?t:fail(stopper_died)
+ ct:fail(stopper_died)
end,
%% Start new boot server to see that loading is continued.
- ?line {ok, BootPid2} = erl_boot_server:start_link([Host]),
- ?line wait_really_started(Node, 25),
- ?line {ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]),
- ?line stop_node(Node),
- ?line unlink(BootPid2),
- ?line exit(BootPid2, kill),
+ BootPid2 = start_boot_server(),
+ wait_really_started(Node, 25),
+ {ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]),
+ stop_node(Node),
+ unlink(BootPid2),
+ exit(BootPid2, kill),
ok
end.
@@ -256,81 +276,72 @@ get_calls(Count, Pid) ->
{error,{trace_msg_timeout,Count}}
end.
-multiple_slaves(doc) ->
- ["Start nodes in parallell, all using the 'inet' loading method, ",
- "verify that the boot server manages"];
+%% Start nodes in parallel, all using the 'inet' loading method;
+%% verify that the boot server manages.
multiple_slaves(Config) when is_list(Config) ->
- case os:type() of
- {ose,_} ->
- {comment, "OSE: multiple nodes not supported"};
- _ ->
- ?line Name = erl_prim_test_multiple_slaves,
- ?line Host = host(),
- ?line Cookie = atom_to_list(erlang:get_cookie()),
- ?line IpStr = ip_str(Host),
- ?line LFlag = get_loader_flag(os:type()),
- ?line Args = LFlag ++ " -hosts " ++ IpStr ++
- " -setcookie " ++ Cookie,
-
- NoOfNodes = 10, % no of slave nodes to be started
-
- NamesAndNodes =
- lists:map(fun(N) ->
- NameN = atom_to_list(Name) ++
- integer_to_list(N),
- NodeN = NameN ++ "@" ++ Host,
- {list_to_atom(NameN),list_to_atom(NodeN)}
- end, lists:seq(1, NoOfNodes)),
-
- ?line Nodes = start_multiple_nodes(NamesAndNodes, Args, []),
-
- %% "queue up" the nodes to wait for the boot server to respond
- %% (note: test_server supervises each node start by accept()
- %% on a socket, the timeout value for the accept has to be quite
- %% long for this test to work).
- ?line test_server:sleep(test_server:seconds(5)),
- %% start the code loading circus!
- ?line {ok,BootPid} = erl_boot_server:start_link([Host]),
- %% give the nodes a chance to boot up before attempting to stop them
- ?line test_server:sleep(test_server:seconds(10)),
-
- ?line wait_and_shutdown(lists:reverse(Nodes), 30),
-
- ?line unlink(BootPid),
- ?line exit(BootPid, kill),
- ok
- end.
+ Name = erl_prim_test_multiple_slaves,
+ Host = host(),
+ IpStr = ip_str(Host),
+ Args = " -loader inet -hosts " ++ IpStr,
+
+ NoOfNodes = 10, % no of slave nodes to be started
+
+ NamesAndNodes =
+ lists:map(fun(N) ->
+ NameN = atom_to_list(Name) ++
+ integer_to_list(N),
+ NodeN = NameN ++ "@" ++ Host,
+ {list_to_atom(NameN),list_to_atom(NodeN)}
+ end, lists:seq(1, NoOfNodes)),
+
+ Nodes = start_multiple_nodes(NamesAndNodes, Args, []),
+
+ %% "queue up" the nodes to wait for the boot server to respond
+ %% (note: test_server supervises each node start by accept()
+ %% on a socket, the timeout value for the accept has to be quite
+ %% long for this test to work).
+ ct:sleep({seconds,5}),
+ %% start the code loading circus!
+ BootPid = start_boot_server(),
+ %% give the nodes a chance to boot up before attempting to stop them
+ ct:sleep({seconds,10}),
+
+ wait_and_shutdown(lists:reverse(Nodes), 30),
+
+ unlink(BootPid),
+ exit(BootPid, kill),
+ ok.
start_multiple_nodes([{Name,Node} | NNs], Args, Started) ->
- ?line {ok,Node} = start_node(Name, Args, [{wait, false}]),
+ {ok,Node} = start_node(Name, Args, [{wait, false}]),
start_multiple_nodes(NNs, Args, [Node | Started]);
start_multiple_nodes([], _, Nodes) ->
Nodes.
wait_and_shutdown([Node | Nodes], Tries) ->
- ?line wait_really_started(Node, Tries),
- ?line {ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]),
- ?line stop_node(Node),
+ wait_really_started(Node, Tries),
+ {ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]),
+ stop_node(Node),
wait_and_shutdown(Nodes, Tries);
wait_and_shutdown([], _) ->
ok.
-file_requests(doc) -> ["Start a node using the 'inet' loading method, ",
- "verify that the boot server responds to file requests."];
+%% Start a node using the 'inet' loading method,
+%% verify that the boot server responds to file requests.
file_requests(Config) when is_list(Config) ->
- ?line {ok, Node, BootPid} = complete_start_node(erl_prim_test_file_req),
+ {ok, Node, BootPid} = complete_start_node(erl_prim_test_file_req),
%% compare with results from file server calls (the
%% boot server uses the same file sys and cwd)
{ok,Files} = file:list_dir("."),
io:format("Files: ~p~n",[Files]),
- ?line {ok,Files} = rpc:call(Node, erl_prim_loader, list_dir, ["."]),
+ {ok,Files} = rpc:call(Node, erl_prim_loader, list_dir, ["."]),
{ok,Info} = file:read_file_info(code:which(test_server)),
- ?line {ok,Info} = rpc:call(Node, erl_prim_loader, read_file_info,
- [code:which(test_server)]),
+ {ok,Info} = rpc:call(Node, erl_prim_loader, read_file_info,
+ [code:which(test_server)]),
- PrivDir = ?config(priv_dir,Config),
+ PrivDir = proplists:get_value(priv_dir,Config),
Dir = filename:join(PrivDir,?MODULE_STRING++"_file_requests"),
ok = file:make_dir(Dir),
Alias = filename:join(Dir,"symlink"),
@@ -354,163 +365,140 @@ file_requests(Config) when is_list(Config) ->
end,
{ok,Cwd} = file:get_cwd(),
- ?line {ok,Cwd} = rpc:call(Node, erl_prim_loader, get_cwd, []),
+ {ok,Cwd} = rpc:call(Node, erl_prim_loader, get_cwd, []),
case file:get_cwd("C:") of
{error,enotsup} ->
ok;
{ok,DCwd} ->
- ?line {ok,DCwd} = rpc:call(Node, erl_prim_loader, get_cwd, ["C:"])
+ {ok,DCwd} = rpc:call(Node, erl_prim_loader, get_cwd, ["C:"])
end,
- ?line stop_node(Node),
- ?line unlink(BootPid),
- ?line exit(BootPid, kill),
+ stop_node(Node),
+ unlink(BootPid),
+ exit(BootPid, kill),
ok.
-complete_start_node(Name) ->
- ?line Host = host(),
- ?line Cookie = atom_to_list(erlang:get_cookie()),
- ?line IpStr = ip_str(Host),
- ?line LFlag = get_loader_flag(os:type()),
- ?line Args = LFlag ++ " -hosts " ++ IpStr ++
- " -setcookie " ++ Cookie,
-
- ?line {ok,BootPid} = erl_boot_server:start_link([Host]),
-
- ?line {ok,Node} = start_node(Name, Args),
- ?line wait_really_started(Node, 25),
- {ok, Node, BootPid}.
-
-local_archive(suite) ->
- [];
-local_archive(doc) ->
- ["Read files from local archive."];
+%% Read files from local archive.
local_archive(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
KernelDir = filename:basename(code:lib_dir(kernel)),
Archive = filename:join([PrivDir, KernelDir ++ init:archive_extension()]),
file:delete(Archive),
- ?line {ok, Archive} = create_archive(Archive, [KernelDir]),
+ {ok, Archive} = create_archive(Archive, [KernelDir]),
Node = node(),
BeamName = "inet.beam",
- ?line ok = test_archive(Node, Archive, KernelDir, BeamName),
+ ok = test_archive(Node, Archive, KernelDir, BeamName),
%% Cleanup
- ?line ok = rpc:call(Node, erl_prim_loader, release_archives, []),
- ?line ok = file:delete(Archive),
+ ok = rpc:call(Node, erl_prim_loader, purge_archive_cache, []),
+ ok = file:delete(Archive),
ok.
-remote_archive(suite) ->
- {req, [{local_slave_nodes, 1}, {time, 10}]};
-remote_archive(doc) ->
- ["Read files from remote archive."];
+%% Read files from remote archive.
remote_archive(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
KernelDir = filename:basename(code:lib_dir(kernel)),
Archive = filename:join([PrivDir, KernelDir ++ init:archive_extension()]),
file:delete(Archive),
- ?line {ok, Archive} = create_archive(Archive, [KernelDir]),
+ {ok, Archive} = create_archive(Archive, [KernelDir]),
- ?line {ok, Node, BootPid} = complete_start_node(remote_archive),
+ {ok, Node, BootPid} = complete_start_node(remote_archive),
BeamName = "inet.beam",
- ?line ok = test_archive(Node, Archive, KernelDir, BeamName),
+ ok = test_archive(Node, Archive, KernelDir, BeamName),
%% Cleanup
- ?line stop_node(Node),
- ?line unlink(BootPid),
- ?line exit(BootPid, kill),
+ stop_node(Node),
+ unlink(BootPid),
+ exit(BootPid, kill),
ok.
-primary_archive(suite) ->
- {req, [{local_slave_nodes, 1}, {time, 10}]};
-primary_archive(doc) ->
- ["Read files from primary archive."];
+%% Read files from primary archive.
primary_archive(Config) when is_list(Config) ->
%% Copy the orig files to priv_dir
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Archive = filename:join([PrivDir, "primary_archive.zip"]),
file:delete(Archive),
- DataDir = ?config(data_dir, Config),
- ?line {ok, _} = zip:create(Archive, ["primary_archive"],
- [{compress, []}, {cwd, DataDir}]),
- ?line {ok, _} = zip:extract(Archive, [{cwd, PrivDir}]),
+ DataDir = proplists:get_value(data_dir, Config),
+ {ok, _} = zip:create(Archive, ["primary_archive"],
+ [{compress, []}, {cwd, DataDir}]),
+ {ok, _} = zip:extract(Archive, [{cwd, PrivDir}]),
TopDir = filename:join([PrivDir, "primary_archive"]),
%% Compile the code
DictDir = "primary_archive_dict-1.0",
DummyDir = "primary_archive_dummy",
- ?line ok = compile_app(TopDir, DictDir),
- ?line ok = compile_app(TopDir, DummyDir),
-
+ ok = compile_app(TopDir, DictDir),
+ ok = compile_app(TopDir, DummyDir),
+
%% Create the archive
{ok, TopFiles} = file:list_dir(TopDir),
- ?line {ok, {_, ArchiveBin}} = zip:create(Archive, TopFiles,
- [memory, {compress, []}, {cwd, TopDir}]),
-
+ {ok, {_, ArchiveBin}} = zip:create(Archive, TopFiles,
+ [memory, {compress, []}, {cwd, TopDir}]),
+
%% Use temporary node to simplify cleanup
- ?line Cookie = atom_to_list(erlang:get_cookie()),
- ?line Args = " -setcookie " ++ Cookie,
- ?line {ok,Node} = start_node(primary_archive, Args),
- ?line wait_really_started(Node, 25),
- ?line {_,_,_} = rpc:call(Node, erlang, date, []),
+ Cookie = atom_to_list(erlang:get_cookie()),
+ Args = " -setcookie " ++ Cookie,
+ {ok,Node} = start_node(primary_archive, Args),
+ wait_really_started(Node, 25),
+ {_,_,_} = rpc:call(Node, erlang, date, []),
%% Set primary archive
ExpectedEbins = [Archive, DictDir ++ "/ebin", DummyDir ++ "/ebin"],
io:format("ExpectedEbins: ~p\n", [ExpectedEbins]),
- ?line {ok, FileInfo} = prim_file:read_file_info(Archive),
- ?line {ok, Ebins} = rpc:call(Node, erl_prim_loader, set_primary_archive,
- [Archive, ArchiveBin, FileInfo,
- fun escript:parse_file/1]),
- ?line ExpectedEbins = lists:sort(Ebins), % assert
-
- ?line {ok, TopFiles2} = rpc:call(Node, erl_prim_loader, list_dir, [Archive]),
- ?line [DictDir, DummyDir] = lists:sort(TopFiles2),
+ {ok, FileInfo} = prim_file:read_file_info(Archive),
+ {ok, Ebins} = rpc:call(Node, erl_prim_loader, set_primary_archive,
+ [Archive, ArchiveBin, FileInfo,
+ fun escript:parse_file/1]),
+ ExpectedEbins = lists:sort(Ebins), % assert
+
+ {ok, TopFiles2} = rpc:call(Node, erl_prim_loader, list_dir, [Archive]),
+ [DictDir, DummyDir] = lists:sort(TopFiles2),
BeamName = "primary_archive_dict_app.beam",
- ?line ok = test_archive(Node, Archive, DictDir, BeamName),
-
+ ok = test_archive(Node, Archive, DictDir, BeamName),
+
%% Cleanup
- ?line {ok, []} = rpc:call(Node, erl_prim_loader, set_primary_archive,
- [undefined, undefined, undefined,
- fun escript:parse_file/1]),
- ?line stop_node(Node),
- ?line ok = file:delete(Archive),
+ {ok, []} = rpc:call(Node, erl_prim_loader, set_primary_archive,
+ [undefined, undefined, undefined,
+ fun escript:parse_file/1]),
+ stop_node(Node),
+ ok = file:delete(Archive),
ok.
test_archive(Node, TopDir, AppDir, BeamName) ->
%% List dir
io:format("test_archive: ~p\n", [rpc:call(Node, erl_prim_loader, list_dir, [TopDir])]),
- ?line {ok, TopFiles} = rpc:call(Node, erl_prim_loader, list_dir, [TopDir]),
- ?line true = lists:member(AppDir, TopFiles),
+ {ok, TopFiles} = rpc:call(Node, erl_prim_loader, list_dir, [TopDir]),
+ true = lists:member(AppDir, TopFiles),
AbsAppDir = TopDir ++ "/" ++ AppDir,
- ?line {ok, AppFiles} = rpc:call(Node, erl_prim_loader, list_dir, [AbsAppDir]),
- ?line true = lists:member("ebin", AppFiles),
+ {ok, AppFiles} = rpc:call(Node, erl_prim_loader, list_dir, [AbsAppDir]),
+ true = lists:member("ebin", AppFiles),
Ebin = AbsAppDir ++ "/ebin",
- ?line {ok, EbinFiles} = rpc:call(Node, erl_prim_loader, list_dir, [Ebin]),
+ {ok, EbinFiles} = rpc:call(Node, erl_prim_loader, list_dir, [Ebin]),
Beam = Ebin ++ "/" ++ BeamName,
- ?line true = lists:member(BeamName, EbinFiles),
- ?line error = rpc:call(Node, erl_prim_loader, list_dir, [TopDir ++ "/no_such_file"]),
- ?line error = rpc:call(Node, erl_prim_loader, list_dir, [TopDir ++ "/ebin/no_such_file"]),
-
+ true = lists:member(BeamName, EbinFiles),
+ error = rpc:call(Node, erl_prim_loader, list_dir, [TopDir ++ "/no_such_file"]),
+ error = rpc:call(Node, erl_prim_loader, list_dir, [TopDir ++ "/ebin/no_such_file"]),
+
%% File info
- ?line {ok, #file_info{type = directory}} =
+ {ok, #file_info{type = directory}} =
rpc:call(Node, erl_prim_loader, read_file_info, [TopDir]),
- ?line {ok, #file_info{type = directory}} =
+ {ok, #file_info{type = directory}} =
rpc:call(Node, erl_prim_loader, read_file_info, [Ebin]),
- ?line {ok, #file_info{type = regular} = FI} =
+ {ok, #file_info{type = regular} = FI} =
rpc:call(Node, erl_prim_loader, read_file_info, [Beam]),
- ?line error = rpc:call(Node, erl_prim_loader, read_file_info, [TopDir ++ "/no_such_file"]),
- ?line error = rpc:call(Node, erl_prim_loader, read_file_info, [TopDir ++ "/ebin/no_such_file"]),
-
+ error = rpc:call(Node, erl_prim_loader, read_file_info, [TopDir ++ "/no_such_file"]),
+ error = rpc:call(Node, erl_prim_loader, read_file_info, [TopDir ++ "/ebin/no_such_file"]),
+
%% Get file
- ?line {ok, Bin, Beam} = rpc:call(Node, erl_prim_loader, get_file, [Beam]),
- ?line if
- FI#file_info.size =:= byte_size(Bin) -> ok;
- true -> exit({FI#file_info.size, byte_size(Bin)})
- end,
- ?line error = rpc:call(Node, erl_prim_loader, get_file, ["/no_such_file"]),
- ?line error = rpc:call(Node, erl_prim_loader, get_file, ["/ebin/no_such_file"]),
+ {ok, Bin, Beam} = rpc:call(Node, erl_prim_loader, get_file, [Beam]),
+ if
+ FI#file_info.size =:= byte_size(Bin) -> ok;
+ true -> exit({FI#file_info.size, byte_size(Bin)})
+ end,
+ error = rpc:call(Node, erl_prim_loader, get_file, ["/no_such_file"]),
+ error = rpc:call(Node, erl_prim_loader, get_file, ["/ebin/no_such_file"]),
ok.
create_archive(Archive, AppDirs) ->
@@ -520,12 +508,9 @@ create_archive(Archive, AppDirs) ->
zip:create(Archive, AppDirs, Opts).
-virtual_dir_in_archive(suite) ->
- [];
-virtual_dir_in_archive(doc) ->
- ["Read virtual directories from archive."];
+%% Read virtual directories from archive.
virtual_dir_in_archive(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Data = <<"A little piece of data.">>,
ArchiveBase = "archive_with_virtual_dirs",
Archive = filename:join([PrivDir, ArchiveBase ++ init:archive_extension()]),
@@ -534,32 +519,62 @@ virtual_dir_in_archive(Config) when is_list(Config) ->
FileInArchive = filename:join([ArchiveBase, EbinBase, FileBase]),
BinFiles = [{FileInArchive, Data}],
Opts = [{compress, []}],
- ?line file:delete(Archive),
+ file:delete(Archive),
io:format("zip:create(~p,\n\t~p,\n\t~p).\n", [Archive, BinFiles, Opts]),
- ?line {ok, Archive} = zip:create(Archive, BinFiles, Opts),
+ {ok, Archive} = zip:create(Archive, BinFiles, Opts),
%% Verify that there is no directories
- ?line {ok, BinFiles} = zip:unzip(Archive, [memory]),
+ {ok, BinFiles} = zip:unzip(Archive, [memory]),
FullPath = filename:join([Archive, FileInArchive]),
- ?line {ok, _} = erl_prim_loader:read_file_info(FullPath),
+ {ok, _} = erl_prim_loader:read_file_info(FullPath),
%% Read one virtual dir
EbinDir = filename:dirname(FullPath),
- ?line {ok, _} = erl_prim_loader:read_file_info(EbinDir),
- ?line {ok, [FileBase]} = erl_prim_loader:list_dir(EbinDir),
+ {ok, _} = erl_prim_loader:read_file_info(EbinDir),
+ {ok, [FileBase]} = erl_prim_loader:list_dir(EbinDir),
%% Read another virtual dir
AppDir = filename:dirname(EbinDir),
- ?line {ok, _} = erl_prim_loader:read_file_info(AppDir),
- ?line {ok, [EbinBase]} = erl_prim_loader:list_dir(AppDir),
-
+ {ok, _} = erl_prim_loader:read_file_info(AppDir),
+ {ok, [EbinBase]} = erl_prim_loader:list_dir(AppDir),
+
%% Cleanup
- ?line ok = erl_prim_loader:release_archives(),
- ?line ok = file:delete(Archive),
+ ok = erl_prim_loader:purge_archive_cache(),
+ ok = file:delete(Archive),
ok.
-%% Misc. functions
+%%%
+%%% Helper functions.
+%%%
+
+complete_start_node(Name) ->
+ BootPid = start_boot_server(),
+ Node = start_node_using_inet(Name),
+ wait_really_started(Node, 25),
+ {ok, Node, BootPid}.
+
+start_boot_server() ->
+ %% Many linux systems define:
+ %% 127.0.0.1 localhost
+ %% 127.0.1.1 somehostname
+ %% Therefore, to allow the tests to work on those kind of systems,
+ %% also include "localhost" in the list of allowed hosts.
+
+ Hosts = [host(),ip_str("localhost")],
+ {ok,BootPid} = erl_boot_server:start_link(Hosts),
+ BootPid.
+
+start_node_using_inet(Name) ->
+ start_node_using_inet(Name, []).
+
+start_node_using_inet(Name, Opts) ->
+ Host = host(),
+ IpStr = ip_str(Host),
+ Args = " -loader inet -hosts " ++ IpStr,
+ {ok,Node} = start_node(Name, Args, Opts),
+ Node.
+
ip_str({A, B, C, D}) ->
lists:concat([A, ".", B, ".", C, ".", D]);
@@ -585,14 +600,11 @@ host() ->
stop_node(Node) ->
test_server:stop_node(Node).
-get_loader_flag(_) ->
- " -loader inet ".
-
compile_app(TopDir, AppName) ->
AppDir = filename:join([TopDir, AppName]),
SrcDir = filename:join([AppDir, "src"]),
OutDir = filename:join([AppDir, "ebin"]),
- ?line {ok, Files} = file:list_dir(SrcDir),
+ {ok, Files} = file:list_dir(SrcDir),
compile_files(Files, SrcDir, OutDir).
compile_files([File | Files], SrcDir, OutDir) ->
diff --git a/lib/kernel/test/error_handler_SUITE.erl b/lib/kernel/test/error_handler_SUITE.erl
index d93ec643ce..6092eebb62 100644
--- a/lib/kernel/test/error_handler_SUITE.erl
+++ b/lib/kernel/test/error_handler_SUITE.erl
@@ -26,7 +26,9 @@
%% Callback from error_handler.
-export(['$handle_undefined_function'/2]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[undefined_function_handler].
diff --git a/lib/kernel/test/error_logger_SUITE.erl b/lib/kernel/test/error_logger_SUITE.erl
index f1988b68d9..07d039349c 100644
--- a/lib/kernel/test/error_logger_SUITE.erl
+++ b/lib/kernel/test/error_logger_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(error_logger_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%%-----------------------------------------------------------------
%% We don't have to test the normal behaviour here, i.e. the tty
@@ -40,7 +40,9 @@
terminate/2]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[error_report, info_report, error, info, emulator, tty,
@@ -64,159 +66,149 @@ end_per_group(_GroupName, Config) ->
%%-----------------------------------------------------------------
-error_report(suite) -> [];
-error_report(doc) -> [];
error_report(Config) when is_list(Config) ->
- ?line error_logger:add_report_handler(?MODULE, self()),
+ error_logger:add_report_handler(?MODULE, self()),
Rep1 = [{tag1,"data1"},{tag2,data2},{tag3,3}],
Rep2 = [testing,"testing",{tag1,"tag1"}],
Rep3 = "This is a string !",
Rep4 = {this,is,a,tuple},
- ?line ok = error_logger:error_report(Rep1),
+ ok = error_logger:error_report(Rep1),
reported(error_report, std_error, Rep1),
- ?line ok = error_logger:error_report(Rep2),
+ ok = error_logger:error_report(Rep2),
reported(error_report, std_error, Rep2),
- ?line ok = error_logger:error_report(Rep3),
+ ok = error_logger:error_report(Rep3),
reported(error_report, std_error, Rep3),
- ?line ok = error_logger:error_report(Rep4),
+ ok = error_logger:error_report(Rep4),
reported(error_report, std_error, Rep4),
- ?line ok = error_logger:error_report(test_type, Rep1),
+ ok = error_logger:error_report(test_type, Rep1),
reported(error_report, test_type, Rep1),
- ?line ok = error_logger:error_report(test_type, Rep2),
+ ok = error_logger:error_report(test_type, Rep2),
reported(error_report, test_type, Rep2),
- ?line ok = error_logger:error_report(test_type, Rep3),
+ ok = error_logger:error_report(test_type, Rep3),
reported(error_report, test_type, Rep3),
- ?line ok = error_logger:error_report(test_type, Rep4),
+ ok = error_logger:error_report(test_type, Rep4),
reported(error_report, test_type, Rep4),
- ?line ok = error_logger:error_report("test_type", Rep1),
+ ok = error_logger:error_report("test_type", Rep1),
reported(error_report, "test_type", Rep1),
- ?line ok = error_logger:error_report({test,type}, Rep2),
+ ok = error_logger:error_report({test,type}, Rep2),
reported(error_report, {test,type}, Rep2),
- ?line ok = error_logger:error_report([test,type], Rep3),
+ ok = error_logger:error_report([test,type], Rep3),
reported(error_report, [test,type], Rep3),
- ?line ok = error_logger:error_report(1, Rep4),
+ ok = error_logger:error_report(1, Rep4),
reported(error_report, 1, Rep4),
- ?line my_yes = error_logger:delete_report_handler(?MODULE),
+ my_yes = error_logger:delete_report_handler(?MODULE),
ok.
%%-----------------------------------------------------------------
-info_report(suite) -> [];
-info_report(doc) -> [];
info_report(Config) when is_list(Config) ->
- ?line error_logger:add_report_handler(?MODULE, self()),
+ error_logger:add_report_handler(?MODULE, self()),
Rep1 = [{tag1,"data1"},{tag2,data2},{tag3,3}],
Rep2 = [testing,"testing",{tag1,"tag1"}],
Rep3 = "This is a string !",
Rep4 = {this,is,a,tuple},
- ?line ok = error_logger:info_report(Rep1),
+ ok = error_logger:info_report(Rep1),
reported(info_report, std_info, Rep1),
- ?line ok = error_logger:info_report(Rep2),
+ ok = error_logger:info_report(Rep2),
reported(info_report, std_info, Rep2),
- ?line ok = error_logger:info_report(Rep3),
+ ok = error_logger:info_report(Rep3),
reported(info_report, std_info, Rep3),
- ?line ok = error_logger:info_report(Rep4),
+ ok = error_logger:info_report(Rep4),
reported(info_report, std_info, Rep4),
- ?line ok = error_logger:info_report(test_type, Rep1),
+ ok = error_logger:info_report(test_type, Rep1),
reported(info_report, test_type, Rep1),
- ?line ok = error_logger:info_report(test_type, Rep2),
+ ok = error_logger:info_report(test_type, Rep2),
reported(info_report, test_type, Rep2),
- ?line ok = error_logger:info_report(test_type, Rep3),
+ ok = error_logger:info_report(test_type, Rep3),
reported(info_report, test_type, Rep3),
- ?line ok = error_logger:info_report(test_type, Rep4),
+ ok = error_logger:info_report(test_type, Rep4),
reported(info_report, test_type, Rep4),
- ?line ok = error_logger:info_report("test_type", Rep1),
+ ok = error_logger:info_report("test_type", Rep1),
reported(info_report, "test_type", Rep1),
- ?line ok = error_logger:info_report({test,type}, Rep2),
+ ok = error_logger:info_report({test,type}, Rep2),
reported(info_report, {test,type}, Rep2),
- ?line ok = error_logger:info_report([test,type], Rep3),
+ ok = error_logger:info_report([test,type], Rep3),
reported(info_report, [test,type], Rep3),
- ?line ok = error_logger:info_report(1, Rep4),
+ ok = error_logger:info_report(1, Rep4),
reported(info_report, 1, Rep4),
- ?line my_yes = error_logger:delete_report_handler(?MODULE),
+ my_yes = error_logger:delete_report_handler(?MODULE),
ok.
%%-----------------------------------------------------------------
-error(suite) -> [];
-error(doc) -> [];
error(Config) when is_list(Config) ->
- ?line error_logger:add_report_handler(?MODULE, self()),
+ error_logger:add_report_handler(?MODULE, self()),
Msg1 = "This is a plain text string~n",
Msg2 = "This is a text with arguments ~p~n",
Arg2 = "This is the argument",
Msg3 = {erroneous,msg},
- ?line ok = error_logger:error_msg(Msg1),
+ ok = error_logger:error_msg(Msg1),
reported(error, Msg1, []),
- ?line ok = error_logger:error_msg(Msg2, Arg2),
+ ok = error_logger:error_msg(Msg2, Arg2),
reported(error, Msg2, Arg2),
- ?line ok = error_logger:error_msg(Msg3),
+ ok = error_logger:error_msg(Msg3),
reported(error, Msg3, []),
- ?line ok = error_logger:error_msg(Msg1, []),
+ ok = error_logger:error_msg(Msg1, []),
reported(error, Msg1, []),
- ?line ok = error_logger:error_msg(Msg2, Arg2),
+ ok = error_logger:error_msg(Msg2, Arg2),
reported(error, Msg2, Arg2),
- ?line ok = error_logger:error_msg(Msg3, []),
+ ok = error_logger:error_msg(Msg3, []),
reported(error, Msg3, []),
- ?line ok = error_logger:format(Msg1, []),
+ ok = error_logger:format(Msg1, []),
reported(error, Msg1, []),
- ?line ok = error_logger:format(Msg2, Arg2),
+ ok = error_logger:format(Msg2, Arg2),
reported(error, Msg2, Arg2),
- ?line ok = error_logger:format(Msg3, []),
+ ok = error_logger:format(Msg3, []),
reported(error, Msg3, []),
- ?line my_yes = error_logger:delete_report_handler(?MODULE),
+ my_yes = error_logger:delete_report_handler(?MODULE),
ok.
%%-----------------------------------------------------------------
-info(suite) -> [];
-info(doc) -> [];
info(Config) when is_list(Config) ->
- ?line error_logger:add_report_handler(?MODULE, self()),
+ error_logger:add_report_handler(?MODULE, self()),
Msg1 = "This is a plain text string~n",
Msg2 = "This is a text with arguments ~p~n",
Arg2 = "This is the argument",
Msg3 = {erroneous,msg},
- ?line ok = error_logger:info_msg(Msg1),
+ ok = error_logger:info_msg(Msg1),
reported(info_msg, Msg1, []),
- ?line ok = error_logger:info_msg(Msg2, Arg2),
+ ok = error_logger:info_msg(Msg2, Arg2),
reported(info_msg, Msg2, Arg2),
- ?line ok = error_logger:info_msg(Msg3),
+ ok = error_logger:info_msg(Msg3),
reported(info_msg, Msg3, []),
- ?line ok = error_logger:info_msg(Msg1, []),
+ ok = error_logger:info_msg(Msg1, []),
reported(info_msg, Msg1, []),
- ?line ok = error_logger:info_msg(Msg2, Arg2),
+ ok = error_logger:info_msg(Msg2, Arg2),
reported(info_msg, Msg2, Arg2),
- ?line ok = error_logger:info_msg(Msg3, []),
+ ok = error_logger:info_msg(Msg3, []),
reported(info_msg, Msg3, []),
- ?line my_yes = error_logger:delete_report_handler(?MODULE),
+ my_yes = error_logger:delete_report_handler(?MODULE),
ok.
%%-----------------------------------------------------------------
-emulator(suite) -> [];
-emulator(doc) -> [];
emulator(Config) when is_list(Config) ->
- ?line error_logger:add_report_handler(?MODULE, self()),
+ error_logger:add_report_handler(?MODULE, self()),
Msg = "Error in process ~p on node ~p with exit value:~n~p~n",
Error = {badmatch,4},
Stack = [{module, function, 2, []}],
Pid = spawn(?MODULE, generate_error, [Error, Stack]),
reported(error, Msg, [Pid, node(), {Error, Stack}]),
- ?line my_yes = error_logger:delete_report_handler(?MODULE),
+ my_yes = error_logger:delete_report_handler(?MODULE),
ok.
generate_error(Error, Stack) ->
@@ -227,52 +219,44 @@ generate_error(Error, Stack) ->
%% want to interact with the test run.
%%-----------------------------------------------------------------
-tty(suite) -> [];
-tty(doc) -> [];
tty(Config) when is_list(Config) ->
- ?line {'EXIT', _Reason} = (catch error_logger:tty(dummy)),
+ {'EXIT', _Reason} = (catch error_logger:tty(dummy)),
ok.
%%-----------------------------------------------------------------
%% If where already exists a logfile we skip this test case !!
%%-----------------------------------------------------------------
-logfile(suite) -> [];
-logfile(doc) -> [];
logfile(Config) when is_list(Config) ->
- ?line case error_logger:logfile(filename) of
- {error, no_log_file} -> % Ok, we continues.
- do_logfile();
- _ ->
- ok
- end.
+ case error_logger:logfile(filename) of
+ {error, no_log_file} -> % Ok, we continues.
+ do_logfile();
+ _ ->
+ ok
+ end.
do_logfile() ->
- ?line {error, _} = error_logger:logfile(close),
- ?line {error, _} = error_logger:logfile({open,{error}}),
- ?line ok = error_logger:logfile({open, "dummy_logfile.log"}),
- ?line "dummy_logfile.log" = error_logger:logfile(filename),
- ?line ok = error_logger:logfile(close),
- ?line {'EXIT',_} = (catch error_logger:logfile(dummy)),
+ {error, _} = error_logger:logfile(close),
+ {error, _} = error_logger:logfile({open,{error}}),
+ ok = error_logger:logfile({open, "dummy_logfile.log"}),
+ "dummy_logfile.log" = error_logger:logfile(filename),
+ ok = error_logger:logfile(close),
+ {'EXIT',_} = (catch error_logger:logfile(dummy)),
ok.
%%-----------------------------------------------------------------
-add(suite) -> [];
-add(doc) -> [];
add(Config) when is_list(Config) ->
- ?line {'EXIT',_} = (catch error_logger:add_report_handler("dummy")),
- ?line {'EXIT',_} = error_logger:add_report_handler(non_existing),
- ?line my_error = error_logger:add_report_handler(?MODULE, [error]),
+ {'EXIT',_} = (catch error_logger:add_report_handler("dummy")),
+ {'EXIT',_} = error_logger:add_report_handler(non_existing),
+ my_error = error_logger:add_report_handler(?MODULE, [error]),
ok.
%%-----------------------------------------------------------------
-delete(suite) -> [];
-delete(doc) -> [];
delete(Config) when is_list(Config) ->
- ?line {'EXIT',_} = (catch error_logger:delete_report_handler("dummy")),
- ?line {error,_} = error_logger:delete_report_handler(non_existing),
+ {'EXIT',_} = (catch error_logger:delete_report_handler("dummy")),
+ {error,_} = error_logger:delete_report_handler(non_existing),
ok.
%%-----------------------------------------------------------------
@@ -284,7 +268,7 @@ reported(Tag, Type, Report) ->
test_server:messages_get(),
ok
after 1000 ->
- test_server:fail(no_report_received)
+ ct:fail(no_report_received)
end.
%%-----------------------------------------------------------------
diff --git a/lib/kernel/test/error_logger_warn_SUITE.erl b/lib/kernel/test/error_logger_warn_SUITE.erl
index a3a3b2f8c6..d8bbd42517 100644
--- a/lib/kernel/test/error_logger_warn_SUITE.erl
+++ b/lib/kernel/test/error_logger_warn_SUITE.erl
@@ -29,7 +29,7 @@
%% Internal exports.
-export([init/1,handle_event/2,handle_info/2,handle_call/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(EXPECT(Pattern),
(fun() ->
@@ -42,11 +42,10 @@
end
end)()).
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[basic, warnings_info, warnings_errors, rb_basic,
@@ -70,69 +69,58 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_Case, Config) ->
- Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+ Config.
+
+end_per_testcase(_Case, _Config) ->
ok.
-basic(doc) ->
- ["Tests basic error logger functionality"];
+%% Tests basic error logger functionality.
basic(Config) when is_list(Config) ->
put(elw_config,Config),
basic().
-warnings_info(doc) ->
- ["Tests mapping warnings to info functionality"];
+%% Tests mapping warnings to info functionality.
warnings_info(Config) when is_list(Config) ->
put(elw_config,Config),
warnings_info().
-warnings_errors(doc) ->
- ["Tests mapping warnings to errors functionality"];
+%% Tests mapping warnings to errors functionality.
warnings_errors(Config) when is_list(Config) ->
put(elw_config,Config),
warnings_errors().
-rb_basic(doc) ->
- ["Tests basic rb functionality"];
+%% Tests basic rb functionality.
rb_basic(Config) when is_list(Config) ->
put(elw_config,Config),
rb_basic().
-rb_warnings_info(doc) ->
- ["Tests warnings as info rb functionality"];
+%% Tests warnings as info rb functionality.
rb_warnings_info(Config) when is_list(Config) ->
put(elw_config,Config),
rb_warnings_info().
-rb_warnings_errors(doc) ->
- ["Tests warnings as errors rb functionality"];
+%% Tests warnings as errors rb functionality.
rb_warnings_errors(Config) when is_list(Config) ->
put(elw_config,Config),
rb_warnings_errors().
-rb_trunc(doc) ->
- ["Tests rb functionality on truncated data"];
+%% Tests rb functionality on truncated data.
rb_trunc(Config) when is_list(Config) ->
put(elw_config,Config),
rb_trunc().
-rb_utc(doc) ->
- ["Tests UTC mapping in rb (-sasl utc_log true)"];
+%% Tests UTC mapping in rb (-sasl utc_log true).
rb_utc(Config) when is_list(Config) ->
put(elw_config,Config),
rb_utc().
-file_utc(doc) ->
- ["Tests UTC mapping in file logger (-stdlib utc_log true)"];
+%% Tests UTC mapping in file logger (-stdlib utc_log true).
file_utc(Config) when is_list(Config) ->
put(elw_config,Config),
file_utc().
-% a small gen_event
+%% a small gen_event
init([Pid]) ->
{ok, Pid}.
@@ -236,7 +224,7 @@ warnings_errors() ->
stop_node(Node),
ok.
-% RB...
+%% RB...
quote(String) ->
case os:type() of
@@ -283,7 +271,7 @@ findstrc(String,File) ->
0
end.
-% Doesn't count empty lines
+%% Doesn't count empty lines
lines(File) ->
length(
string:tokens(
@@ -291,17 +279,17 @@ lines(File) ->
element(2,file:read_file(File))),
"\n")).
-%directories anf filenames
+%% Directories and filenames
ld() ->
Config = get(elw_config),
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
filename:absname(PrivDir).
lf() ->
filename:join([ld(),"logfile.txt"]).
rd() ->
Config = get(elw_config),
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
LogDir = filename:join(PrivDir,"log"),
file:make_dir(LogDir),
filename:absname(LogDir).
@@ -315,7 +303,7 @@ nice_stop_node(Name) ->
{nodedown,Name} -> ok
end.
-%clean out rd() before each report test in order to get only one file...
+%% Clean out rd() before each report test in order to get only one file...
clean_rd() ->
{ok,L} = file:list_dir(rd()),
lists:foreach(fun(F) ->
@@ -352,10 +340,10 @@ one_rb_findstr(Param,String) ->
rb:stop_log(),
findstr(String,lf()).
-% Tests
+%% Tests
rb_basic() ->
clean_rd(),
- % Behold, the magic parameters to activate rb logging...
+ %% Behold, the magic parameters to activate rb logging...
Node = start_node(nn(),"-boot start_sasl -sasl error_logger_mf_dir "++
quote(rd())++" error_logger_mf_maxbytes 5000 "
"error_logger_mf_maxfiles 5"),
@@ -513,9 +501,7 @@ rb_utc() ->
file_utc() ->
file:delete(lf()),
SS="-stdlib utc_log true -kernel error_logger "++ oquote("{file,"++iquote(lf())++"}"),
- %erlang:display(SS),
Node = start_node(nn(),SS),
- %erlang:display(rpc:call(Node,application,get_env,[kernel,error_logger])),
Self = self(),
GL = group_leader(),
fake_gl(Node,error_msg,"~p~n",[Self]),
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 09d9a45197..74db2970af 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -51,20 +51,20 @@
pos1/1, pos2/1, pos3/1]).
-export([close/1, consult1/1, path_consult/1, delete/1]).
-export([ eval1/1, path_eval/1, script1/1, path_script/1,
- open1/1,
- old_modes/1, new_modes/1, path_open/1, open_errors/1]).
+ open1/1,
+ old_modes/1, new_modes/1, path_open/1, open_errors/1]).
-export([ file_info_basic_file/1, file_info_basic_directory/1,
- file_info_bad/1, file_info_times/1, file_write_file_info/1]).
+ file_info_bad/1, file_info_times/1, file_write_file_info/1]).
-export([rename/1, access/1, truncate/1, datasync/1, sync/1,
read_write/1, pread_write/1, append/1, exclusive/1]).
-export([ e_delete/1, e_rename/1, e_make_dir/1, e_del_dir/1]).
-export([otp_5814/1, otp_10852/1]).
-export([ read_not_really_compressed/1,
- read_compressed_cooked/1, read_compressed_cooked_binary/1,
- read_cooked_tar_problem/1,
- write_compressed/1, compress_errors/1, catenated_gzips/1,
- compress_async_crash/1]).
+ read_compressed_cooked/1, read_compressed_cooked_binary/1,
+ read_cooked_tar_problem/1,
+ write_compressed/1, compress_errors/1, catenated_gzips/1,
+ compress_async_crash/1]).
-export([ make_link/1, read_link_info_for_non_link/1, symlinks/1]).
@@ -83,7 +83,7 @@
-export([unicode/1]).
-export([altname/1]).
--export([large_file/1, large_write/1]).
+-export([large_file/0, large_file/1, large_write/1]).
-export([read_line_1/1, read_line_2/1, read_line_3/1,read_line_4/1]).
@@ -106,13 +106,15 @@
%% System probe functions that might be handy to check from the shell
-export([disc_free/1, memsize/0]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
-define(THROW_ERROR(RES), throw({fail, ?LINE, RES})).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[unicode, altname, read_write_file, {group, dirs},
@@ -168,16 +170,11 @@ init_per_suite(Config) when is_list(Config) ->
ok ->
[{sasl,started}]
end,
- ok = case os:type() of
- {ose,_} ->
- ok;
- _ ->
- application:start(os_mon)
- end,
+ application:start(os_mon),
case os:type() of
{win32, _} ->
- Priv = ?config(priv_dir, Config),
+ Priv = proplists:get_value(priv_dir, Config),
HasAccessTime =
case ?FILE_MODULE:read_file_info(Priv) of
{ok, #file_info{atime={_, {0, 0, 0}}}} ->
@@ -199,12 +196,7 @@ end_per_suite(Config) when is_list(Config) ->
ok
end,
- case os:type() of
- {ose,_} ->
- ok;
- _ ->
- application:stop(os_mon)
- end,
+ application:stop(os_mon),
case proplists:get_value(sasl, Config) of
started ->
application:stop(sasl);
@@ -271,73 +263,66 @@ mini_server(Parent) ->
mini_server(Parent)
end.
-standard_io(suite) ->
- [];
-standard_io(doc) ->
- ["Test that standard i/o-servers work with file module"];
+%% Test that standard i/o-servers work with file module.
standard_io(Config) when is_list(Config) ->
%% Really just a smoke test
- ?line Pid = spawn(?MODULE,mini_server,[self()]),
- ?line register(mini_server,Pid),
- ?line ok = file:write(mini_server,<<"hej\n">>),
- ?line receive
- {io_request,_,_,{put_chars,<<"hej\n">>}} ->
- ok
- after 1000 ->
- exit(noreply)
- end,
- ?line {ok,"aaaaa"} = file:read(mini_server,5),
- ?line receive
- {io_request,_,_,{get_chars,'',5}} ->
- ok
- after 1000 ->
- exit(noreply)
- end,
- ?line {ok,"hej\n"} = file:read_line(mini_server),
- ?line receive
- {io_request,_,_,{get_line,''}} ->
- ok
- after 1000 ->
- exit(noreply)
- end,
- ?line OldGL = group_leader(),
- ?line group_leader(Pid,self()),
- ?line ok = file:write(standard_io,<<"hej\n">>),
- ?line group_leader(OldGL,self()),
- ?line receive
- {io_request,_,_,{put_chars,<<"hej\n">>}} ->
- ok
- after 1000 ->
- exit(noreply)
- end,
- ?line group_leader(Pid,self()),
- ?line {ok,"aaaaa"} = file:read(standard_io,5),
- ?line group_leader(OldGL,self()),
- ?line receive
- {io_request,_,_,{get_chars,'',5}} ->
- ok
- after 1000 ->
- exit(noreply)
- end,
- ?line group_leader(Pid,self()),
- ?line {ok,"hej\n"} = file:read_line(standard_io),
- ?line group_leader(OldGL,self()),
- ?line receive
- {io_request,_,_,{get_line,''}} ->
- ok
- after 1000 ->
- exit(noreply)
- end,
+ Pid = spawn(?MODULE,mini_server,[self()]),
+ register(mini_server,Pid),
+ ok = file:write(mini_server,<<"hej\n">>),
+ receive
+ {io_request,_,_,{put_chars,<<"hej\n">>}} ->
+ ok
+ after 1000 ->
+ exit(noreply)
+ end,
+ {ok,"aaaaa"} = file:read(mini_server,5),
+ receive
+ {io_request,_,_,{get_chars,'',5}} ->
+ ok
+ after 1000 ->
+ exit(noreply)
+ end,
+ {ok,"hej\n"} = file:read_line(mini_server),
+ receive
+ {io_request,_,_,{get_line,''}} ->
+ ok
+ after 1000 ->
+ exit(noreply)
+ end,
+ OldGL = group_leader(),
+ group_leader(Pid,self()),
+ ok = file:write(standard_io,<<"hej\n">>),
+ group_leader(OldGL,self()),
+ receive
+ {io_request,_,_,{put_chars,<<"hej\n">>}} ->
+ ok
+ after 1000 ->
+ exit(noreply)
+ end,
+ group_leader(Pid,self()),
+ {ok,"aaaaa"} = file:read(standard_io,5),
+ group_leader(OldGL,self()),
+ receive
+ {io_request,_,_,{get_chars,'',5}} ->
+ ok
+ after 1000 ->
+ exit(noreply)
+ end,
+ group_leader(Pid,self()),
+ {ok,"hej\n"} = file:read_line(standard_io),
+ group_leader(OldGL,self()),
+ receive
+ {io_request,_,_,{get_line,''}} ->
+ ok
+ after 1000 ->
+ exit(noreply)
+ end,
Pid ! die,
receive after 1000 -> ok end.
-old_io_protocol(suite) ->
- [];
-old_io_protocol(doc) ->
- ["Test that the old file IO protocol =< R16B still works"];
+%% Test that the old file IO protocol =< R16B still works.
old_io_protocol(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(5)),
- RootDir = ?config(priv_dir,Config),
+ RootDir = proplists:get_value(priv_dir,Config),
Name = filename:join(RootDir,
atom_to_list(?MODULE)
++"old_io_protocol.fil"),
@@ -350,14 +335,11 @@ old_io_protocol(Config) when is_list(Config) ->
end,
ok = ?FILE_MODULE:close(Fd),
{ok, <<>>} = ?FILE_MODULE:read_file(Name),
- test_server:timetrap_cancel(Dog),
[] = flush(),
ok.
-unicode_mode(suite) -> [];
-unicode_mode(doc) -> [""];
unicode_mode(Config) ->
- Dir = {dir, ?config(priv_dir,Config)},
+ Dir = {dir, proplists:get_value(priv_dir,Config)},
OptVariants = [[Dir],
[Dir, {encoding, utf8}],
[Dir, binary],
@@ -503,105 +485,98 @@ um_filename(Str = [_|_], Dir, Options) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-read_write_file(suite) -> [];
-read_write_file(doc) -> [];
read_write_file(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_read_write_file"),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_read_write_file"),
%% Try writing and reading back some term
- ?line SomeTerm = {"This term",{will,be},[written,$t,$o],1,file,[]},
- ?line ok = ?FILE_MODULE:write_file(Name,term_to_binary(SomeTerm)),
- ?line {ok,Bin1} = ?FILE_MODULE:read_file(Name),
- ?line SomeTerm = binary_to_term(Bin1),
-
+ SomeTerm = {"This term",{will,be},[written,$t,$o],1,file,[]},
+ ok = ?FILE_MODULE:write_file(Name,term_to_binary(SomeTerm)),
+ {ok,Bin1} = ?FILE_MODULE:read_file(Name),
+ SomeTerm = binary_to_term(Bin1),
+
%% Try a "null" term
- ?line NullTerm = [],
- ?line ok = ?FILE_MODULE:write_file(Name,term_to_binary(NullTerm)),
- ?line {ok,Bin2} = ?FILE_MODULE:read_file(Name),
- ?line NullTerm = binary_to_term(Bin2),
+ NullTerm = [],
+ ok = ?FILE_MODULE:write_file(Name,term_to_binary(NullTerm)),
+ {ok,Bin2} = ?FILE_MODULE:read_file(Name),
+ NullTerm = binary_to_term(Bin2),
%% Try some "complicated" types
- ?line BigNum = 123456789012345678901234567890,
- ?line ComplTerm = {self(),make_ref(),BigNum,3.14159},
- ?line ok = ?FILE_MODULE:write_file(Name,term_to_binary(ComplTerm)),
- ?line {ok,Bin3} = ?FILE_MODULE:read_file(Name),
- ?line ComplTerm = binary_to_term(Bin3),
+ BigNum = 123456789012345678901234567890,
+ ComplTerm = {self(),make_ref(),BigNum,3.14159},
+ ok = ?FILE_MODULE:write_file(Name,term_to_binary(ComplTerm)),
+ {ok,Bin3} = ?FILE_MODULE:read_file(Name),
+ ComplTerm = binary_to_term(Bin3),
%% Try reading a nonexistent file
- ?line Name2 = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_nonexistent_file"),
- ?line {error, enoent} = ?FILE_MODULE:read_file(Name2),
- ?line {error, enoent} = ?FILE_MODULE:read_file(""),
- ?line {error, enoent} = ?FILE_MODULE:read_file(''),
-
- % Try writing to a bad filename
- ?line {error, enoent} =
+ Name2 = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_nonexistent_file"),
+ {error, enoent} = ?FILE_MODULE:read_file(Name2),
+ {error, enoent} = ?FILE_MODULE:read_file(""),
+ {error, enoent} = ?FILE_MODULE:read_file(''),
+
+ %% Try writing to a bad filename
+ {error, enoent} =
?FILE_MODULE:write_file("",term_to_binary(NullTerm)),
- % Try writing something else than a binary
- ?line {error, badarg} = ?FILE_MODULE:write_file(Name,{1,2,3}),
- ?line {error, badarg} = ?FILE_MODULE:write_file(Name,self()),
+ %% Try writing something else than a binary
+ {error, badarg} = ?FILE_MODULE:write_file(Name,{1,2,3}),
+ {error, badarg} = ?FILE_MODULE:write_file(Name,self()),
%% Some non-term binaries
- ?line ok = ?FILE_MODULE:write_file(Name,[]),
- ?line {ok,Bin4} = ?FILE_MODULE:read_file(Name),
- ?line 0 = byte_size(Bin4),
+ ok = ?FILE_MODULE:write_file(Name,[]),
+ {ok,Bin4} = ?FILE_MODULE:read_file(Name),
+ 0 = byte_size(Bin4),
- ?line ok = ?FILE_MODULE:write_file(Name,[Bin1,[],[[Bin2]]]),
- ?line {ok,Bin5} = ?FILE_MODULE:read_file(Name),
- ?line {Bin1,Bin2} = split_binary(Bin5,byte_size(Bin1)),
+ ok = ?FILE_MODULE:write_file(Name,[Bin1,[],[[Bin2]]]),
+ {ok,Bin5} = ?FILE_MODULE:read_file(Name),
+ {Bin1,Bin2} = split_binary(Bin5,byte_size(Bin1)),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-make_del_dir(suite) -> [];
-make_del_dir(doc) -> [];
make_del_dir(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_mk-dir"),
- ?line ok = ?FILE_MODULE:make_dir(NewDir),
- ?line {error, eexist} = ?FILE_MODULE:make_dir(NewDir),
- ?line ok = ?FILE_MODULE:del_dir(NewDir),
- ?line {error, enoent} = ?FILE_MODULE:del_dir(NewDir),
- % Make sure we are not in a directory directly under test_server
- % as that would result in eacces errors when trying to delete '..',
- % because there are processes having that directory as current.
- ?line ok = ?FILE_MODULE:make_dir(NewDir),
- ?line {ok,CurrentDir} = file:get_cwd(),
+ RootDir = proplists:get_value(priv_dir,Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_mk-dir"),
+ ok = ?FILE_MODULE:make_dir(NewDir),
+ {error, eexist} = ?FILE_MODULE:make_dir(NewDir),
+ ok = ?FILE_MODULE:del_dir(NewDir),
+ {error, enoent} = ?FILE_MODULE:del_dir(NewDir),
+ %% Make sure we are not in a directory directly under test_server
+ %% as that would result in eacces errors when trying to delete '..',
+ %% because there are processes having that directory as current.
+ ok = ?FILE_MODULE:make_dir(NewDir),
+ {ok,CurrentDir} = file:get_cwd(),
case {os:type(), length(NewDir) >= 260 } of
{{win32,_}, true} ->
io:format("Skip set_cwd for windows path longer than 260 (MAX_PATH)\n", []),
io:format("\nNewDir = ~p\n", [NewDir]);
_ ->
- ?line ok = ?FILE_MODULE:set_cwd(NewDir)
+ ok = ?FILE_MODULE:set_cwd(NewDir)
end,
try
%% Check that we get an error when trying to create...
%% a deep directory
- ?line NewDir2 = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_mk-dir-noexist/foo"),
- ?line {error, enoent} = ?FILE_MODULE:make_dir(NewDir2),
+ NewDir2 = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_mk-dir-noexist/foo"),
+ {error, enoent} = ?FILE_MODULE:make_dir(NewDir2),
%% a nameless directory
- ?line {error, enoent} = ?FILE_MODULE:make_dir(""),
+ {error, enoent} = ?FILE_MODULE:make_dir(""),
%% a directory with illegal name
- ?line {error, badarg} = ?FILE_MODULE:make_dir({1,2,3}),
-
+ {error, badarg} = ?FILE_MODULE:make_dir({1,2,3}),
+
%% a directory with illegal name, even if it's a (bad) list
- ?line {error, badarg} = ?FILE_MODULE:make_dir([1,2,3,{}]),
-
+ {error, badarg} = ?FILE_MODULE:make_dir([1,2,3,{}]),
+
%% Maybe this isn't an error, exactly, but worth mentioning anyway:
%% ok = ?FILE_MODULE:make_dir([$f,$o,$o,0,$b,$a,$r])),
%% The above line works, and created a directory "./foo"
@@ -609,40 +584,36 @@ make_del_dir(Config) when is_list(Config) ->
%% a directory, but with a name that incorporates the "bar" part of
%% the list, so that [$f,$o,$o,0,$f,$o,$o] wouldn't refer to the same
%% dir. But this would slow it down.
-
+
%% Try deleting some bad directories
%% Deleting the parent directory to the current, sounds dangerous, huh?
%% Don't worry ;-) the parent directory should never be empty, right?
- ?line case ?FILE_MODULE:del_dir('..') of
- {error, eexist} -> ok;
- {error, eacces} -> ok; %OpenBSD
- {error, einval} -> ok %FreeBSD
- end,
- ?line {error, enoent} = ?FILE_MODULE:del_dir(""),
- ?line {error, badarg} = ?FILE_MODULE:del_dir([3,2,1,{}]),
-
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog)
+ case ?FILE_MODULE:del_dir('..') of
+ {error, eexist} -> ok;
+ {error, eacces} -> ok; %OpenBSD
+ {error, einval} -> ok %FreeBSD
+ end,
+ {error, enoent} = ?FILE_MODULE:del_dir(""),
+ {error, badarg} = ?FILE_MODULE:del_dir([3,2,1,{}]),
+
+ [] = flush()
after
- ?FILE_MODULE:set_cwd(CurrentDir)
+ ?FILE_MODULE:set_cwd(CurrentDir)
end,
ok.
-cur_dir_0(suite) -> [];
-cur_dir_0(doc) -> [];
cur_dir_0(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
%% Find out the current dir, and cd to it ;-)
- ?line {ok,BaseDir} = ?FILE_MODULE:get_cwd(),
- ?line Dir1 = BaseDir ++ "", %% Check that it's a string
- ?line ok = ?FILE_MODULE:set_cwd(Dir1),
+ {ok,BaseDir} = ?FILE_MODULE:get_cwd(),
+ Dir1 = BaseDir ++ "", %% Check that it's a string
+ ok = ?FILE_MODULE:set_cwd(Dir1),
%% Make a new dir, and cd to that
- ?line RootDir = ?config(priv_dir,Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_curdir"),
- ?line ok = ?FILE_MODULE:make_dir(NewDir),
+ RootDir = proplists:get_value(priv_dir,Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_curdir"),
+ ok = ?FILE_MODULE:make_dir(NewDir),
case {os:type(), length(NewDir) >= 260} of
{{win32,_}, true} ->
io:format("Skip set_cwd for windows path longer than 260 (MAX_PATH):\n"),
@@ -675,50 +646,44 @@ cur_dir_0(Config) when is_list(Config) ->
{ok,OldDirFiles} = ?FILE_MODULE:list_dir("."),
false = lists:member(UncommonName,OldDirFiles)
end,
-
+
%% Try doing some bad things
- ?line {error, badarg} = ?FILE_MODULE:set_cwd({foo,bar}),
- ?line {error, enoent} = ?FILE_MODULE:set_cwd(""),
- ?line {error, enoent} = ?FILE_MODULE:set_cwd(".......a......"),
- ?line {ok,BaseDir} = ?FILE_MODULE:get_cwd(), %% Still there?
+ {error, badarg} = ?FILE_MODULE:set_cwd({foo,bar}),
+ {error, enoent} = ?FILE_MODULE:set_cwd(""),
+ {error, enoent} = ?FILE_MODULE:set_cwd(".......a......"),
+ {ok,BaseDir} = ?FILE_MODULE:get_cwd(), %% Still there?
%% On Windows, there should only be slashes, no backslashes,
%% in the return value of get_cwd().
%% (The test is harmless on Unix, because filenames usually
%% don't contain backslashes.)
- ?line {ok, BaseDir} = ?FILE_MODULE:get_cwd(),
- ?line false = lists:member($\\, BaseDir),
+ {ok, BaseDir} = ?FILE_MODULE:get_cwd(),
+ false = lists:member($\\, BaseDir),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
%% Tests ?FILE_MODULE:get_cwd/1.
-cur_dir_1(suite) -> [];
-cur_dir_1(doc) -> [];
cur_dir_1(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
-
- ?line case os:type() of
- {win32, _} ->
- win_cur_dir_1(Config);
- _ ->
- ?line {error, enotsup} = ?FILE_MODULE:get_cwd("d:")
- end,
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ case os:type() of
+ {win32, _} ->
+ win_cur_dir_1(Config);
+ _ ->
+ {error, enotsup} = ?FILE_MODULE:get_cwd("d:")
+ end,
+ [] = flush(),
ok.
-
+
win_cur_dir_1(_Config) ->
- ?line {ok,BaseDir} = ?FILE_MODULE:get_cwd(),
+ {ok,BaseDir} = ?FILE_MODULE:get_cwd(),
%% Get the drive letter from the current directory,
%% and try to get current directory for that drive.
- ?line [Drive,$:|_] = BaseDir,
- ?line {ok,BaseDir} = ?FILE_MODULE:get_cwd([Drive,$:]),
+ [Drive,$:|_] = BaseDir,
+ {ok,BaseDir} = ?FILE_MODULE:get_cwd([Drive,$:]),
io:format("BaseDir = ~s\n", [BaseDir]),
%% Unfortunately, there is no way to move away from the
@@ -733,7 +698,7 @@ win_cur_dir_1(_Config) ->
%%%
list_dir_error(Config) ->
- Priv = ?config(priv_dir, Config),
+ Priv = proplists:get_value(priv_dir, Config),
NonExisting = filename:join(Priv, "non-existing-dir"),
{error,enoent} = ?FILE_MODULE:list_dir(NonExisting),
ok.
@@ -743,7 +708,7 @@ list_dir_error(Config) ->
%%%
list_dir(Config) ->
- RootDir = ?config(priv_dir, Config),
+ RootDir = proplists:get_value(priv_dir, Config),
TestDir = filename:join(RootDir, ?MODULE_STRING++"_list_dir"),
?FILE_MODULE:make_dir(TestDir),
list_dir_1(TestDir, 42, []).
@@ -773,7 +738,7 @@ untranslatable_names(Config) ->
untranslatable_names_1(Config) ->
{ok,OldCwd} = file:get_cwd(),
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Dir = filename:join(PrivDir, "untranslatable_names"),
ok = file:make_dir(Dir),
Node = start_node(untranslatable_names, "+fnu"),
@@ -814,7 +779,7 @@ untranslatable_names_error(Config) ->
untranslatable_names_error_1(Config) ->
{ok,OldCwd} = file:get_cwd(),
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Dir = filename:join(PrivDir, "untranslatable_names_error"),
ok = file:make_dir(Dir),
Node = start_node(untranslatable_names, "+fnue"),
@@ -862,7 +827,7 @@ start_node(Name, Args) ->
ct:log("Trying to start ~w@~s~n", [Name,Host]),
case test_server:start_node(Name, peer, [{args,Args}]) of
{error,Reason} ->
- test_server:fail(Reason);
+ ct:fail(Reason);
{ok,Node} ->
ct:log("Node ~p started~n", [Node]),
Node
@@ -873,568 +838,504 @@ start_node(Name, Args) ->
-open1(suite) -> [];
-open1(doc) -> [];
open1(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_files"),
- ?line ok = ?FILE_MODULE:make_dir(NewDir),
- ?line Name = filename:join(NewDir, "foo1.fil"),
- ?line {ok,Fd1} = ?FILE_MODULE:open(Name,read_write),
- ?line {ok,Fd2} = ?FILE_MODULE:open(Name,read),
- ?line Str = "{a,tuple}.\n",
- ?line io:format(Fd1,Str,[]),
- ?line {ok,0} = ?FILE_MODULE:position(Fd1,bof),
- ?line Str = io:get_line(Fd1,''),
- ?line case io:get_line(Fd2,'') of
- Str -> Str;
- eof -> Str
- end,
- ?line ok = ?FILE_MODULE:close(Fd2),
- ?line {ok,0} = ?FILE_MODULE:position(Fd1,bof),
- ?line ok = ?FILE_MODULE:truncate(Fd1),
- ?line eof = io:get_line(Fd1,''),
- ?line ok = ?FILE_MODULE:close(Fd1),
- ?line {ok,Fd3} = ?FILE_MODULE:open(Name,read),
- ?line eof = io:get_line(Fd3,''),
- ?line ok = ?FILE_MODULE:close(Fd3),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ RootDir = proplists:get_value(priv_dir,Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_files"),
+ ok = ?FILE_MODULE:make_dir(NewDir),
+ Name = filename:join(NewDir, "foo1.fil"),
+ {ok,Fd1} = ?FILE_MODULE:open(Name,read_write),
+ {ok,Fd2} = ?FILE_MODULE:open(Name,read),
+ Str = "{a,tuple}.\n",
+ io:format(Fd1,Str,[]),
+ {ok,0} = ?FILE_MODULE:position(Fd1,bof),
+ Str = io:get_line(Fd1,''),
+ Str = io:get_line(Fd2,''),
+ ok = ?FILE_MODULE:close(Fd2),
+ {ok,0} = ?FILE_MODULE:position(Fd1,bof),
+ ok = ?FILE_MODULE:truncate(Fd1),
+ eof = io:get_line(Fd1,''),
+ ok = ?FILE_MODULE:close(Fd1),
+ {ok,Fd3} = ?FILE_MODULE:open(Name,read),
+ eof = io:get_line(Fd3,''),
+ ok = ?FILE_MODULE:close(Fd3),
+ [] = flush(),
ok.
%% Tests all open modes.
-old_modes(suite) -> [];
-old_modes(doc) -> [];
old_modes(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_old_open_modes"),
- ?line ok = ?FILE_MODULE:make_dir(NewDir),
- ?line Name1 = filename:join(NewDir, "foo1.fil"),
- ?line Marker = "hello, world",
+ RootDir = proplists:get_value(priv_dir, Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_old_open_modes"),
+ ok = ?FILE_MODULE:make_dir(NewDir),
+ Name1 = filename:join(NewDir, "foo1.fil"),
+ Marker = "hello, world",
%% write
- ?line {ok, Fd1} = ?FILE_MODULE:open(Name1, write),
- ?line ok = io:write(Fd1, Marker),
- ?line ok = io:put_chars(Fd1, ".\n"),
- ?line ok = ?FILE_MODULE:close(Fd1),
+ {ok, Fd1} = ?FILE_MODULE:open(Name1, write),
+ ok = io:write(Fd1, Marker),
+ ok = io:put_chars(Fd1, ".\n"),
+ ok = ?FILE_MODULE:close(Fd1),
%% read
- ?line {ok, Fd2} = ?FILE_MODULE:open(Name1, read),
- ?line {ok, Marker} = io:read(Fd2, prompt),
- ?line ok = ?FILE_MODULE:close(Fd2),
+ {ok, Fd2} = ?FILE_MODULE:open(Name1, read),
+ {ok, Marker} = io:read(Fd2, prompt),
+ ok = ?FILE_MODULE:close(Fd2),
%% read_write
- ?line {ok, Fd3} = ?FILE_MODULE:open(Name1, read_write),
- ?line {ok, Marker} = io:read(Fd3, prompt),
- ?line ok = io:write(Fd3, Marker),
- ?line ok = ?FILE_MODULE:close(Fd3),
+ {ok, Fd3} = ?FILE_MODULE:open(Name1, read_write),
+ {ok, Marker} = io:read(Fd3, prompt),
+ ok = io:write(Fd3, Marker),
+ ok = ?FILE_MODULE:close(Fd3),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
-new_modes(suite) -> [];
-new_modes(doc) -> [];
new_modes(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_new_open_modes"),
- ?line ok = ?FILE_MODULE:make_dir(NewDir),
- ?line Name1 = filename:join(NewDir, "foo1.fil"),
- ?line Marker = "hello, world",
+ RootDir = proplists:get_value(priv_dir, Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_new_open_modes"),
+ ok = ?FILE_MODULE:make_dir(NewDir),
+ Name1 = filename:join(NewDir, "foo1.fil"),
+ Marker = "hello, world",
%% write
- ?line {ok, Fd1} = ?FILE_MODULE:open(Name1, [write]),
- ?line ok = io:write(Fd1, Marker),
- ?line ok = io:put_chars(Fd1, ".\n"),
- ?line ok = ?FILE_MODULE:close(Fd1),
+ {ok, Fd1} = ?FILE_MODULE:open(Name1, [write]),
+ ok = io:write(Fd1, Marker),
+ ok = io:put_chars(Fd1, ".\n"),
+ ok = ?FILE_MODULE:close(Fd1),
%% read
- ?line {ok, Fd2} = ?FILE_MODULE:open(Name1, [read]),
- ?line {ok, Marker} = io:read(Fd2, prompt),
- ?line ok = ?FILE_MODULE:close(Fd2),
+ {ok, Fd2} = ?FILE_MODULE:open(Name1, [read]),
+ {ok, Marker} = io:read(Fd2, prompt),
+ ok = ?FILE_MODULE:close(Fd2),
%% read and write
- ?line {ok, Fd3} = ?FILE_MODULE:open(Name1, [read, write]),
- ?line {ok, Marker} = io:read(Fd3, prompt),
- ?line ok = io:write(Fd3, Marker),
- ?line ok = ?FILE_MODULE:close(Fd3),
+ {ok, Fd3} = ?FILE_MODULE:open(Name1, [read, write]),
+ {ok, Marker} = io:read(Fd3, prompt),
+ ok = io:write(Fd3, Marker),
+ ok = ?FILE_MODULE:close(Fd3),
%% read by default
- ?line {ok, Fd4} = ?FILE_MODULE:open(Name1, []),
- ?line {ok, Marker} = io:read(Fd4, prompt),
- ?line ok = ?FILE_MODULE:close(Fd4),
+ {ok, Fd4} = ?FILE_MODULE:open(Name1, []),
+ {ok, Marker} = io:read(Fd4, prompt),
+ ok = ?FILE_MODULE:close(Fd4),
%% read and binary
- ?line {ok, Fd5} = ?FILE_MODULE:open(Name1, [read, binary]),
- ?line {ok, Marker} = io:read(Fd5, prompt),
- ?line ok = ?FILE_MODULE:close(Fd5),
+ {ok, Fd5} = ?FILE_MODULE:open(Name1, [read, binary]),
+ {ok, Marker} = io:read(Fd5, prompt),
+ ok = ?FILE_MODULE:close(Fd5),
%% read, raw
- ?line {ok, Fd6} = ?FILE_MODULE:open(Name1, [read, raw]),
- ?line {ok, [$\[]} = ?FILE_MODULE:read(Fd6, 1),
- ?line ok = ?FILE_MODULE:close(Fd6),
-
- %% write and sync
- case ?FILE_MODULE:open(Name1, [write, sync]) of
- {ok, Fd7} ->
- ok = io:write(Fd7, Marker),
- ok = io:put_chars(Fd7, ".\n"),
- ok = ?FILE_MODULE:close(Fd7),
- {ok, Fd8} = ?FILE_MODULE:open(Name1, [read]),
- {ok, Marker} = io:read(Fd8, prompt),
- ok = ?FILE_MODULE:close(Fd8);
- {error, enotsup} ->
- %% for platforms that don't support the sync option
- ok
- end,
-
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
- ok.
+ {ok, Fd6} = ?FILE_MODULE:open(Name1, [read, raw]),
+ {ok, [$\[]} = ?FILE_MODULE:read(Fd6, 1),
+ ok = ?FILE_MODULE:close(Fd6),
+
+ %% write and sync
+ case ?FILE_MODULE:open(Name1, [write, sync]) of
+ {ok, Fd7} ->
+ ok = io:write(Fd7, Marker),
+ ok = io:put_chars(Fd7, ".\n"),
+ ok = ?FILE_MODULE:close(Fd7),
+ {ok, Fd8} = ?FILE_MODULE:open(Name1, [read]),
+ {ok, Marker} = io:read(Fd8, prompt),
+ ok = ?FILE_MODULE:close(Fd8);
+ {error, enotsup} ->
+ %% for platforms that don't support the sync option
+ ok
+ end,
+
+ [] = flush(),
+ ok.
-path_open(suite) -> [];
-path_open(doc) -> [];
path_open(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_path_open"),
- ?line ok = ?FILE_MODULE:make_dir(NewDir),
- ?line FileName = "path_open.fil",
- ?line Name = filename:join(RootDir, FileName),
- ?line {ok,Fd1,_FullName1} =
+ RootDir = proplists:get_value(priv_dir,Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_path_open"),
+ ok = ?FILE_MODULE:make_dir(NewDir),
+ FileName = "path_open.fil",
+ Name = filename:join(RootDir, FileName),
+ {ok,Fd1,_FullName1} =
?FILE_MODULE:path_open(
- [RootDir,
- "nosuch1",
- NewDir],FileName,write),
- ?line io:format(Fd1,"ABCDEFGH",[]),
- ?line ok = ?FILE_MODULE:close(Fd1),
+ [RootDir,
+ "nosuch1",
+ NewDir],FileName,write),
+ io:format(Fd1,"ABCDEFGH",[]),
+ ok = ?FILE_MODULE:close(Fd1),
%% locate it in the last dir
- ?line {ok,Fd2,_FullName2} =
+ {ok,Fd2,_FullName2} =
?FILE_MODULE:path_open(
- ["nosuch1",
- NewDir,
- RootDir],FileName,read),
- ?line {ok,2} =
+ ["nosuch1",
+ NewDir,
+ RootDir],FileName,read),
+ {ok,2} =
?FILE_MODULE:position(Fd2,2), "C" = io:get_chars(Fd2,'',1),
- ?line ok = ?FILE_MODULE:close(Fd2),
+ ok = ?FILE_MODULE:close(Fd2),
%% Try a failing path
- ?line {error, enoent} = ?FILE_MODULE:path_open(
- ["nosuch1",
- NewDir],FileName,read),
+ {error, enoent} = ?FILE_MODULE:path_open(
+ ["nosuch1",
+ NewDir],FileName,read),
%% Check that it's found regardless of path, if an absolute name given
- ?line {ok,Fd3,_FullPath3} =
+ {ok,Fd3,_FullPath3} =
?FILE_MODULE:path_open(
- ["nosuch1",
- NewDir],Name,read),
- ?line {ok,2} =
+ ["nosuch1",
+ NewDir],Name,read),
+ {ok,2} =
?FILE_MODULE:position(Fd3,2), "C" = io:get_chars(Fd3,'',1),
- ?line ok = ?FILE_MODULE:close(Fd3),
+ ok = ?FILE_MODULE:close(Fd3),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
-close(suite) -> [];
-close(doc) -> [];
close(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_close.fil"),
- ?line {ok,Fd1} = ?FILE_MODULE:open(Name,read_write),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_close.fil"),
+ {ok,Fd1} = ?FILE_MODULE:open(Name,read_write),
%% Just closing it is no fun, we did that a million times already
%% This is a common error, for code written before Erlang 4.3
%% bacause then ?FILE_MODULE:open just returned a Pid, and not everyone
%% really checked what they got.
- ?line {'EXIT',_Msg} = (catch ok = ?FILE_MODULE:close({ok,Fd1})),
- ?line ok = ?FILE_MODULE:close(Fd1),
+ {'EXIT',_Msg} = (catch ok = ?FILE_MODULE:close({ok,Fd1})),
+ ok = ?FILE_MODULE:close(Fd1),
%% Try closing one more time
- ?line Val = ?FILE_MODULE:close(Fd1),
- ?line io:format("Second close gave: ~p",[Val]),
+ Val = ?FILE_MODULE:close(Fd1),
+ io:format("Second close gave: ~p",[Val]),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
-access(suite) -> [];
-access(doc) -> [];
access(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_access.fil"),
- ?line Str = "ABCDEFGH",
- ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write),
- ?line io:format(Fd1,Str,[]),
- ?line ok = ?FILE_MODULE:close(Fd1),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_access.fil"),
+ Str = "ABCDEFGH",
+ {ok,Fd1} = ?FILE_MODULE:open(Name,write),
+ io:format(Fd1,Str,[]),
+ ok = ?FILE_MODULE:close(Fd1),
%% Check that we can't write when in read only mode
- ?line {ok,Fd2} = ?FILE_MODULE:open(Name,read),
- ?line case catch io:format(Fd2,"XXXX",[]) of
- ok ->
- test_server:fail({format,write});
- _ ->
- ok
- end,
- ?line ok = ?FILE_MODULE:close(Fd2),
- ?line {ok,Fd3} = ?FILE_MODULE:open(Name,read),
- ?line Str = io:get_line(Fd3,''),
- ?line ok = ?FILE_MODULE:close(Fd3),
+ {ok,Fd2} = ?FILE_MODULE:open(Name,read),
+ case catch io:format(Fd2,"XXXX",[]) of
+ ok ->
+ ct:fail({format,write});
+ _ ->
+ ok
+ end,
+ ok = ?FILE_MODULE:close(Fd2),
+ {ok,Fd3} = ?FILE_MODULE:open(Name,read),
+ Str = io:get_line(Fd3,''),
+ ok = ?FILE_MODULE:close(Fd3),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
%% Tests ?FILE_MODULE:read/2 and ?FILE_MODULE:write/2.
-read_write(suite) -> [];
-read_write(doc) -> [];
read_write(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_read_write"),
- ?line ok = ?FILE_MODULE:make_dir(NewDir),
- ?line Marker = "hello, world",
- ?line MarkerB = list_to_binary(Marker),
+ RootDir = proplists:get_value(priv_dir, Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_read_write"),
+ ok = ?FILE_MODULE:make_dir(NewDir),
+ Marker = "hello, world",
+ MarkerB = list_to_binary(Marker),
%% Plain file.
- ?line Name1 = filename:join(NewDir, "plain.fil"),
- ?line {ok, Fd1} = ?FILE_MODULE:open(Name1, [read, write]),
- ?line read_write_test(Fd1, Marker, []),
+ Name1 = filename:join(NewDir, "plain.fil"),
+ {ok, Fd1} = ?FILE_MODULE:open(Name1, [read, write]),
+ read_write_test(Fd1, Marker, []),
%% Raw file.
- ?line Name2 = filename:join(NewDir, "raw.fil"),
- ?line {ok, Fd2} = ?FILE_MODULE:open(Name2, [read, write, raw]),
- ?line read_write_test(Fd2, Marker, []),
+ Name2 = filename:join(NewDir, "raw.fil"),
+ {ok, Fd2} = ?FILE_MODULE:open(Name2, [read, write, raw]),
+ read_write_test(Fd2, Marker, []),
%% Plain binary file.
- ?line Name3 = filename:join(NewDir, "plain-b.fil"),
- ?line {ok, Fd3} = ?FILE_MODULE:open(Name3, [read, write, binary]),
- ?line read_write_test(Fd3, MarkerB, <<>>),
+ Name3 = filename:join(NewDir, "plain-b.fil"),
+ {ok, Fd3} = ?FILE_MODULE:open(Name3, [read, write, binary]),
+ read_write_test(Fd3, MarkerB, <<>>),
%% Raw binary file.
- ?line Name4 = filename:join(NewDir, "raw-b.fil"),
- ?line {ok, Fd4} = ?FILE_MODULE:open(Name4, [read, write, raw, binary]),
- ?line read_write_test(Fd4, MarkerB, <<>>),
+ Name4 = filename:join(NewDir, "raw-b.fil"),
+ {ok, Fd4} = ?FILE_MODULE:open(Name4, [read, write, raw, binary]),
+ read_write_test(Fd4, MarkerB, <<>>),
- ?line test_server:timetrap_cancel(Dog),
ok.
read_write_test(File, Marker, Empty) ->
- ?line ok = ?FILE_MODULE:write(File, Marker),
- ?line {ok, 0} = ?FILE_MODULE:position(File, 0),
- ?line {ok, Empty} = ?FILE_MODULE:read(File, 0),
- ?line {ok, Marker} = ?FILE_MODULE:read(File, 100),
- ?line eof = ?FILE_MODULE:read(File, 100),
- ?line {ok, Empty} = ?FILE_MODULE:read(File, 0),
- ?line ok = ?FILE_MODULE:close(File),
- ?line [] = flush(),
+ ok = ?FILE_MODULE:write(File, Marker),
+ {ok, 0} = ?FILE_MODULE:position(File, 0),
+ {ok, Empty} = ?FILE_MODULE:read(File, 0),
+ {ok, Marker} = ?FILE_MODULE:read(File, 100),
+ eof = ?FILE_MODULE:read(File, 100),
+ {ok, Empty} = ?FILE_MODULE:read(File, 0),
+ ok = ?FILE_MODULE:close(File),
+ [] = flush(),
ok.
%% Tests ?FILE_MODULE:pread/2 and ?FILE_MODULE:pwrite/2.
-pread_write(suite) -> [];
-pread_write(doc) -> [];
pread_write(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_pread_write"),
- ?line ok = ?FILE_MODULE:make_dir(NewDir),
- ?line List = "hello, world",
- ?line Bin = list_to_binary(List),
+ RootDir = proplists:get_value(priv_dir, Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_pread_write"),
+ ok = ?FILE_MODULE:make_dir(NewDir),
+ List = "hello, world",
+ Bin = list_to_binary(List),
%% Plain file.
- ?line Name1 = filename:join(NewDir, "plain.fil"),
- ?line {ok, Fd1} = ?FILE_MODULE:open(Name1, [read, write]),
- ?line pread_write_test(Fd1, List),
+ Name1 = filename:join(NewDir, "plain.fil"),
+ {ok, Fd1} = ?FILE_MODULE:open(Name1, [read, write]),
+ pread_write_test(Fd1, List),
%% Raw file.
- ?line Name2 = filename:join(NewDir, "raw.fil"),
- ?line {ok, Fd2} = ?FILE_MODULE:open(Name2, [read, write, raw]),
- ?line pread_write_test(Fd2, List),
+ Name2 = filename:join(NewDir, "raw.fil"),
+ {ok, Fd2} = ?FILE_MODULE:open(Name2, [read, write, raw]),
+ pread_write_test(Fd2, List),
%% Plain file. Binary mode.
- ?line Name3 = filename:join(NewDir, "plain-binary.fil"),
- ?line {ok, Fd3} = ?FILE_MODULE:open(Name3, [binary, read, write]),
- ?line pread_write_test(Fd3, Bin),
+ Name3 = filename:join(NewDir, "plain-binary.fil"),
+ {ok, Fd3} = ?FILE_MODULE:open(Name3, [binary, read, write]),
+ pread_write_test(Fd3, Bin),
%% Raw file. Binary mode.
- ?line Name4 = filename:join(NewDir, "raw-binary.fil"),
- ?line {ok, Fd4} = ?FILE_MODULE:open(Name4, [binary, read, write, raw]),
- ?line pread_write_test(Fd4, Bin),
+ Name4 = filename:join(NewDir, "raw-binary.fil"),
+ {ok, Fd4} = ?FILE_MODULE:open(Name4, [binary, read, write, raw]),
+ pread_write_test(Fd4, Bin),
- ?line test_server:timetrap_cancel(Dog),
ok.
pread_write_test(File, Data) ->
- ?line io:format("~p:pread_write_test(~p,~p)~n", [?MODULE, File, Data]),
- ?line Size = if is_binary(Data) -> byte_size(Data);
- is_list(Data) -> length(Data)
- end,
- ?line I = Size + 17,
- ?line ok = ?FILE_MODULE:pwrite(File, 0, Data),
+ io:format("~p:pread_write_test(~p,~p)~n", [?MODULE, File, Data]),
+ Size = if is_binary(Data) -> byte_size(Data);
+ is_list(Data) -> length(Data)
+ end,
+ I = Size + 17,
+ ok = ?FILE_MODULE:pwrite(File, 0, Data),
Res = ?FILE_MODULE:pread(File, 0, I),
- ?line {ok, Data} = Res,
- ?line eof = ?FILE_MODULE:pread(File, I, 1),
- ?line ok = ?FILE_MODULE:pwrite(File, [{0, Data}, {I, Data}]),
- ?line {ok, [Data, eof, Data]} =
+ {ok, Data} = Res,
+ eof = ?FILE_MODULE:pread(File, I, 1),
+ ok = ?FILE_MODULE:pwrite(File, [{0, Data}, {I, Data}]),
+ {ok, [Data, eof, Data]} =
?FILE_MODULE:pread(File, [{0, Size}, {2*I, 1}, {I, Size}]),
- ?line Plist = lists:seq(21*I, 0, -I),
- ?line Pwrite = lists:map(fun(P)->{P,Data}end, Plist),
- ?line Pread = [{22*I,Size} | lists:map(fun(P)->{P,Size}end, Plist)],
- ?line Presult = [eof | lists:map(fun(_)->Data end, Plist)],
- ?line ok = ?FILE_MODULE:pwrite(File, Pwrite),
- ?line {ok, Presult} = ?FILE_MODULE:pread(File, Pread),
- ?line ok = ?FILE_MODULE:close(File),
- ?line [] = flush(),
+ Plist = lists:seq(21*I, 0, -I),
+ Pwrite = lists:map(fun(P)->{P,Data}end, Plist),
+ Pread = [{22*I,Size} | lists:map(fun(P)->{P,Size}end, Plist)],
+ Presult = [eof | lists:map(fun(_)->Data end, Plist)],
+ ok = ?FILE_MODULE:pwrite(File, Pwrite),
+ {ok, Presult} = ?FILE_MODULE:pread(File, Pread),
+ ok = ?FILE_MODULE:close(File),
+ [] = flush(),
ok.
-append(doc) -> "Test appending to a file.";
-append(suite) -> [];
+%% Test appending to a file.
append(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_append"),
- ?line ok = ?FILE_MODULE:make_dir(NewDir),
+ RootDir = proplists:get_value(priv_dir, Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_append"),
+ ok = ?FILE_MODULE:make_dir(NewDir),
- ?line First = "First line\n",
- ?line Second = "Seond lines comes here\n",
- ?line Third = "And here is the third line\n",
+ First = "First line\n",
+ Second = "Seond lines comes here\n",
+ Third = "And here is the third line\n",
%% Write a small text file.
- ?line Name1 = filename:join(NewDir, "a_file.txt"),
- ?line {ok, Fd1} = ?FILE_MODULE:open(Name1, [write]),
- ?line ok = io:format(Fd1, First, []),
- ?line ok = io:format(Fd1, Second, []),
- ?line ok = ?FILE_MODULE:close(Fd1),
+ Name1 = filename:join(NewDir, "a_file.txt"),
+ {ok, Fd1} = ?FILE_MODULE:open(Name1, [write]),
+ ok = io:format(Fd1, First, []),
+ ok = io:format(Fd1, Second, []),
+ ok = ?FILE_MODULE:close(Fd1),
%% Open it a again and a append a line to it.
- ?line {ok, Fd2} = ?FILE_MODULE:open(Name1, [append]),
- ?line ok = io:format(Fd2, Third, []),
- ?line ok = ?FILE_MODULE:close(Fd2),
+ {ok, Fd2} = ?FILE_MODULE:open(Name1, [append]),
+ ok = io:format(Fd2, Third, []),
+ ok = ?FILE_MODULE:close(Fd2),
%% Read it back and verify.
- ?line Expected = list_to_binary([First, Second, Third]),
- ?line {ok, Expected} = ?FILE_MODULE:read_file(Name1),
+ Expected = list_to_binary([First, Second, Third]),
+ {ok, Expected} = ?FILE_MODULE:read_file(Name1),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
-open_errors(suite) -> [];
-open_errors(doc) -> [];
open_errors(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line DataDir =
+ DataDir =
filename:dirname(
- filename:join(?config(data_dir, Config), "x")),
- ?line DataDirSlash = DataDir++"/",
- ?line {error, E1} = ?FILE_MODULE:open(DataDir, [read]),
- ?line {error, E2} = ?FILE_MODULE:open(DataDirSlash, [read]),
- ?line {error, E3} = ?FILE_MODULE:open(DataDir, [write]),
- ?line {error, E4} = ?FILE_MODULE:open(DataDirSlash, [write]),
- ?line {eisdir,eisdir,eisdir,eisdir} = {E1,E2,E3,E4},
-
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ filename:join(proplists:get_value(data_dir, Config), "x")),
+ DataDirSlash = DataDir++"/",
+ {error, E1} = ?FILE_MODULE:open(DataDir, [read]),
+ {error, E2} = ?FILE_MODULE:open(DataDirSlash, [read]),
+ {error, E3} = ?FILE_MODULE:open(DataDir, [write]),
+ {error, E4} = ?FILE_MODULE:open(DataDirSlash, [write]),
+ {eisdir,eisdir,eisdir,eisdir} = {E1,E2,E3,E4},
+
+ [] = flush(),
ok.
-exclusive(suite) -> [];
-exclusive(doc) -> "Test exclusive access to a file.";
+%% Test exclusive access to a file.
exclusive(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_exclusive"),
- ?line ok = ?FILE_MODULE:make_dir(NewDir),
- ?line Name = filename:join(NewDir, "ex_file.txt"),
- ?line {ok, Fd} = ?FILE_MODULE:open(Name, [write, exclusive]),
- ?line {error, eexist} = ?FILE_MODULE:open(Name, [write, exclusive]),
- ?line ok = ?FILE_MODULE:close(Fd),
- ?line test_server:timetrap_cancel(Dog),
+ RootDir = proplists:get_value(priv_dir,Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_exclusive"),
+ ok = ?FILE_MODULE:make_dir(NewDir),
+ Name = filename:join(NewDir, "ex_file.txt"),
+ {ok, Fd} = ?FILE_MODULE:open(Name, [write, exclusive]),
+ {error, eexist} = ?FILE_MODULE:open(Name, [write, exclusive]),
+ ok = ?FILE_MODULE:close(Fd),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-pos1(suite) -> [];
-pos1(doc) -> [];
pos1(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_pos1.fil"),
- ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write),
- ?line io:format(Fd1,"ABCDEFGH",[]),
- ?line ok = ?FILE_MODULE:close(Fd1),
- ?line {ok,Fd2} = ?FILE_MODULE:open(Name,read),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_pos1.fil"),
+ {ok,Fd1} = ?FILE_MODULE:open(Name,write),
+ io:format(Fd1,"ABCDEFGH",[]),
+ ok = ?FILE_MODULE:close(Fd1),
+ {ok,Fd2} = ?FILE_MODULE:open(Name,read),
%% Start pos is first char
- ?line io:format("Relative positions"),
- ?line "A" = io:get_chars(Fd2,'',1),
- ?line {ok,2} = ?FILE_MODULE:position(Fd2,{cur,1}),
- ?line "C" = io:get_chars(Fd2,'',1),
- ?line {ok,0} = ?FILE_MODULE:position(Fd2,{cur,-3}),
- ?line "A" = io:get_chars(Fd2,'',1),
+ io:format("Relative positions"),
+ "A" = io:get_chars(Fd2,'',1),
+ {ok,2} = ?FILE_MODULE:position(Fd2,{cur,1}),
+ "C" = io:get_chars(Fd2,'',1),
+ {ok,0} = ?FILE_MODULE:position(Fd2,{cur,-3}),
+ "A" = io:get_chars(Fd2,'',1),
%% Backwards from first char should be an error
- ?line {ok,0} = ?FILE_MODULE:position(Fd2,{cur,-1}),
- ?line {error, einval} = ?FILE_MODULE:position(Fd2,{cur,-1}),
+ {ok,0} = ?FILE_MODULE:position(Fd2,{cur,-1}),
+ {error, einval} = ?FILE_MODULE:position(Fd2,{cur,-1}),
%% Reset position and move again
- ?line {ok,0} = ?FILE_MODULE:position(Fd2,0),
- ?line {ok,2} = ?FILE_MODULE:position(Fd2,{cur,2}),
- ?line "C" = io:get_chars(Fd2,'',1),
+ {ok,0} = ?FILE_MODULE:position(Fd2,0),
+ {ok,2} = ?FILE_MODULE:position(Fd2,{cur,2}),
+ "C" = io:get_chars(Fd2,'',1),
%% Go a lot forwards
- ?line {ok,13} = ?FILE_MODULE:position(Fd2,{cur,10}),
- ?line eof = io:get_chars(Fd2,'',1),
+ {ok,13} = ?FILE_MODULE:position(Fd2,{cur,10}),
+ eof = io:get_chars(Fd2,'',1),
%% Try some fixed positions
- ?line io:format("Fixed positions"),
- ?line {ok,8} =
+ io:format("Fixed positions"),
+ {ok,8} =
?FILE_MODULE:position(Fd2,8), eof = io:get_chars(Fd2,'',1),
- ?line {ok,8} =
+ {ok,8} =
?FILE_MODULE:position(Fd2,cur), eof = io:get_chars(Fd2,'',1),
- ?line {ok,7} =
+ {ok,7} =
?FILE_MODULE:position(Fd2,7), "H" = io:get_chars(Fd2,'',1),
- ?line {ok,0} =
+ {ok,0} =
?FILE_MODULE:position(Fd2,0), "A" = io:get_chars(Fd2,'',1),
- ?line {ok,3} =
+ {ok,3} =
?FILE_MODULE:position(Fd2,3), "D" = io:get_chars(Fd2,'',1),
- ?line {ok,12} =
+ {ok,12} =
?FILE_MODULE:position(Fd2,12), eof = io:get_chars(Fd2,'',1),
- ?line {ok,3} =
+ {ok,3} =
?FILE_MODULE:position(Fd2,3), "D" = io:get_chars(Fd2,'',1),
%% Try the {bof,X} notation
- ?line {ok,3} = ?FILE_MODULE:position(Fd2,{bof,3}),
- ?line "D" = io:get_chars(Fd2,'',1),
+ {ok,3} = ?FILE_MODULE:position(Fd2,{bof,3}),
+ "D" = io:get_chars(Fd2,'',1),
%% Try eof positions
- ?line io:format("EOF positions"),
- ?line {ok,8} =
+ io:format("EOF positions"),
+ {ok,8} =
?FILE_MODULE:position(Fd2,{eof,0}), eof=io:get_chars(Fd2,'',1),
- ?line {ok,7} =
+ {ok,7} =
?FILE_MODULE:position(Fd2,{eof,-1}),
- ?line "H" = io:get_chars(Fd2,'',1),
- ?line {ok,0} =
+ "H" = io:get_chars(Fd2,'',1),
+ {ok,0} =
?FILE_MODULE:position(Fd2,{eof,-8}), "A"=io:get_chars(Fd2,'',1),
- ?line {error, einval} = ?FILE_MODULE:position(Fd2,{eof,-9}),
+ {error, einval} = ?FILE_MODULE:position(Fd2,{eof,-9}),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
-pos2(suite) -> [];
-pos2(doc) -> [];
pos2(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_pos2.fil"),
- ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write),
- ?line io:format(Fd1,"ABCDEFGH",[]),
- ?line ok = ?FILE_MODULE:close(Fd1),
- ?line {ok,Fd2} = ?FILE_MODULE:open(Name,read),
- ?line {error, einval} = ?FILE_MODULE:position(Fd2,-1),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_pos2.fil"),
+ {ok,Fd1} = ?FILE_MODULE:open(Name,write),
+ io:format(Fd1,"ABCDEFGH",[]),
+ ok = ?FILE_MODULE:close(Fd1),
+ {ok,Fd2} = ?FILE_MODULE:open(Name,read),
+ {error, einval} = ?FILE_MODULE:position(Fd2,-1),
%% Make sure that we still can search after an error.
- ?line {ok,0} = ?FILE_MODULE:position(Fd2, 0),
- ?line {ok,3} = ?FILE_MODULE:position(Fd2, {bof,3}),
- ?line "D" = io:get_chars(Fd2,'',1),
+ {ok,0} = ?FILE_MODULE:position(Fd2, 0),
+ {ok,3} = ?FILE_MODULE:position(Fd2, {bof,3}),
+ "D" = io:get_chars(Fd2,'',1),
- ?line [] = flush(),
- ?line io:format("DONE"),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
+ io:format("DONE"),
ok.
-pos3(suite) -> [];
-pos3(doc) -> ["When it does not use raw mode, file:position had a bug."];
+%% When it does not use raw mode, file:position had a bug.
pos3(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(data_dir, Config),
- ?line Name = filename:join(RootDir, "realmen.html.gz"),
+ RootDir = proplists:get_value(data_dir, Config),
+ Name = filename:join(RootDir, "realmen.html.gz"),
- ?line {ok, Fd} = ?FILE_MODULE:open(Name, [read, binary]),
- ?line {ok, _} = ?FILE_MODULE:read(Fd, 5),
- ?line {error, einval} = ?FILE_MODULE:position(Fd, {bof, -1}),
+ {ok, Fd} = ?FILE_MODULE:open(Name, [read, binary]),
+ {ok, _} = ?FILE_MODULE:read(Fd, 5),
+ {error, einval} = ?FILE_MODULE:position(Fd, {bof, -1}),
%% Here ok had returned =(
- ?line {error, einval} = ?FILE_MODULE:position(Fd, {cur, -10}),
+ {error, einval} = ?FILE_MODULE:position(Fd, {cur, -10}),
%% That test is actually questionable since file:position/2
%% is documented to leave the file position undefined after
%% it has returned an error. But on Posix systems the position
%% is guaranteed to be unchanged after an error return. On e.g
%% Windows there is nothing stated about this in the documentation.
- ?line test_server:timetrap_cancel(Dog),
ok.
-file_info_basic_file(suite) -> [];
-file_info_basic_file(doc) -> [];
file_info_basic_file(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir, Config),
+ RootDir = proplists:get_value(priv_dir, Config),
%% Create a short file.
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_basic_test.fil"),
- ?line {ok,Fd1} = ?FILE_MODULE:open(Name, write),
- ?line io:put_chars(Fd1, "foo bar"),
- ?line ok = ?FILE_MODULE:close(Fd1),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_basic_test.fil"),
+ {ok,Fd1} = ?FILE_MODULE:open(Name, write),
+ io:put_chars(Fd1, "foo bar"),
+ ok = ?FILE_MODULE:close(Fd1),
%% Test that the file has the expected attributes.
%% The times are tricky, so we will save them to a separate test case.
{ok,FileInfo} = ?FILE_MODULE:read_file_info(Name),
{ok,FileInfo} = ?FILE_MODULE:read_file_info(Name, [raw]),
#file_info{size=Size,type=Type,access=Access,
- atime=AccessTime,mtime=ModifyTime} = FileInfo,
- ?line io:format("Access ~p, Modify ~p", [AccessTime, ModifyTime]),
- ?line Size = 7,
- ?line Type = regular,
- ?line read_write = Access,
- ?line true = abs(time_dist(filter_atime(AccessTime, Config),
- filter_atime(ModifyTime,
- Config))) < 2,
- ?line all_integers(tuple_to_list(AccessTime) ++ tuple_to_list(ModifyTime)),
-
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ atime=AccessTime,mtime=ModifyTime} = FileInfo,
+ io:format("Access ~p, Modify ~p", [AccessTime, ModifyTime]),
+ Size = 7,
+ Type = regular,
+ read_write = Access,
+ true = abs(time_dist(filter_atime(AccessTime, Config),
+ filter_atime(ModifyTime,
+ Config))) < 2,
+ all_integers(tuple_to_list(AccessTime) ++ tuple_to_list(ModifyTime)),
+
+ [] = flush(),
ok.
-file_info_basic_directory(suite) -> [];
-file_info_basic_directory(doc) -> [];
file_info_basic_directory(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(5)),
-
%% Note: filename:join/1 removes any trailing slash,
%% which is essential for ?FILE_MODULE:file_info/1 to work on
%% platforms such as Windows95.
- RootDir = filename:join([?config(priv_dir, Config)]),
+ RootDir = filename:join([proplists:get_value(priv_dir, Config)]),
%% Test that the RootDir directory has the expected attributes.
test_directory(RootDir, read_write),
@@ -1445,65 +1346,57 @@ file_info_basic_directory(Config) when is_list(Config) ->
%% directories.
case os:type() of
{win32, _} ->
- ?line test_directory("/", read_write),
- ?line test_directory("c:/", read_write),
- ?line test_directory("c:\\", read_write);
+ test_directory("/", read_write),
+ test_directory("c:/", read_write),
+ test_directory("c:\\", read_write);
_ ->
- ?line test_directory("/", read)
+ test_directory("/", read)
end,
- test_server:timetrap_cancel(Dog).
+ ok.
test_directory(Name, ExpectedAccess) ->
{ok,FileInfo} = ?FILE_MODULE:read_file_info(Name),
{ok,FileInfo} = ?FILE_MODULE:read_file_info(Name, [raw]),
#file_info{size=Size,type=Type,access=Access,
atime=AccessTime,mtime=ModifyTime} = FileInfo,
- ?line io:format("Testing directory ~s", [Name]),
- ?line io:format("Directory size is ~p", [Size]),
- ?line io:format("Access ~p", [Access]),
- ?line io:format("Access time ~p; Modify time~p",
- [AccessTime, ModifyTime]),
- ?line Type = directory,
- ?line Access = ExpectedAccess,
- ?line all_integers(tuple_to_list(AccessTime) ++ tuple_to_list(ModifyTime)),
- ?line [] = flush(),
+ io:format("Testing directory ~s", [Name]),
+ io:format("Directory size is ~p", [Size]),
+ io:format("Access ~p", [Access]),
+ io:format("Access time ~p; Modify time~p",
+ [AccessTime, ModifyTime]),
+ Type = directory,
+ Access = ExpectedAccess,
+ all_integers(tuple_to_list(AccessTime) ++ tuple_to_list(ModifyTime)),
+ [] = flush(),
ok.
all_integers([{A,B,C}|T]) ->
all_integers([A,B,C|T]);
all_integers([Int|Rest]) when is_integer(Int) ->
- ?line all_integers(Rest);
+ all_integers(Rest);
all_integers([]) -> ok.
%% Try something nonexistent.
-file_info_bad(suite) -> [];
-file_info_bad(doc) -> [];
file_info_bad(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = filename:join([?config(priv_dir, Config)]),
+ RootDir = filename:join([proplists:get_value(priv_dir, Config)]),
FileName = filename:join(RootDir, atom_to_list(?MODULE) ++ "_nonexistent"),
{error,enoent} = ?FILE_MODULE:read_file_info(FileName),
{error,enoent} = ?FILE_MODULE:read_file_info(FileName, [raw]),
- ?line {error, enoent} = ?FILE_MODULE:read_file_info(""),
+ {error, enoent} = ?FILE_MODULE:read_file_info(""),
{error, enoent} = ?FILE_MODULE:read_file_info("", [raw]),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
%% Test that the file times behave as they should.
-file_info_times(suite) -> [];
-file_info_times(doc) -> [];
file_info_times(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(60)),
%% We have to try this twice, since if the test runs across the change
%% of a month the time diff calculations will fail. But it won't happen
%% if you run it twice in succession.
- ?line test_server:m_out_of_n(
- 1,2,
- fun() -> ?line file_info_int(Config) end),
- ?line test_server:timetrap_cancel(Dog),
+ test_server:m_out_of_n(
+ 1,2,
+ fun() -> file_info_int(Config) end),
ok.
file_info_int(Config) ->
@@ -1511,14 +1404,14 @@ file_info_int(Config) ->
%% which is essential for ?FILE_MODULE:file_info/1 to work on
%% platforms such as Windows95.
- ?line RootDir = filename:join([?config(priv_dir, Config)]),
- ?line test_server:format("RootDir = ~p", [RootDir]),
+ RootDir = filename:join([proplists:get_value(priv_dir, Config)]),
+ io:format("RootDir = ~p", [RootDir]),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_file_info.fil"),
- ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write),
- ?line io:put_chars(Fd1,"foo"),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_file_info.fil"),
+ {ok,Fd1} = ?FILE_MODULE:open(Name,write),
+ io:put_chars(Fd1,"foo"),
%% check that the file got a modify date max a few seconds away from now
{ok,FileInfo1} = ?FILE_MODULE:read_file_info(Name),
@@ -1531,31 +1424,31 @@ file_info_int(Config) ->
#file_info{type=regular,atime=AccTime1,mtime=ModTime1} = FileInfo1,
- ?line Now = erlang:localtime(), %???
- ?line io:format("Now ~p",[Now]),
- ?line io:format("Open file Acc ~p Mod ~p",[AccTime1,ModTime1]),
- ?line true = abs(time_dist(filter_atime(Now, Config),
- filter_atime(AccTime1,
- Config))) < 8,
- ?line true = abs(time_dist(Now,ModTime1)) < 8,
+ Now = erlang:localtime(), %???
+ io:format("Now ~p",[Now]),
+ io:format("Open file Acc ~p Mod ~p",[AccTime1,ModTime1]),
+ true = abs(time_dist(filter_atime(Now, Config),
+ filter_atime(AccTime1,
+ Config))) < 8,
+ true = abs(time_dist(Now,ModTime1)) < 8,
%% Sleep until we can be sure the seconds value has changed.
%% Note: FAT-based filesystem (like on Windows 95) have
%% a resolution of 2 seconds.
- ?line test_server:sleep(test_server:seconds(2.2)),
+ timer:sleep(2200),
%% close the file, and watch the modify date change
- ?line ok = ?FILE_MODULE:close(Fd1),
+ ok = ?FILE_MODULE:close(Fd1),
{ok,FileInfo2} = ?FILE_MODULE:read_file_info(Name),
{ok,FileInfo2} = ?FILE_MODULE:read_file_info(Name, [raw]),
#file_info{size=Size,type=regular,access=Access,
atime=AccTime2,mtime=ModTime2} = FileInfo2,
- ?line io:format("Closed file Acc ~p Mod ~p",[AccTime2,ModTime2]),
- ?line true = time_dist(ModTime1,ModTime2) >= 0,
+ io:format("Closed file Acc ~p Mod ~p",[AccTime2,ModTime2]),
+ true = time_dist(ModTime1,ModTime2) >= 0,
%% this file is supposed to be binary, so it'd better keep it's size
- ?line Size = 3,
- ?line Access = read_write,
+ Size = 3,
+ Access = read_write,
%% Do some directory checking
{ok,FileInfo3} = ?FILE_MODULE:read_file_info(RootDir),
@@ -1563,12 +1456,12 @@ file_info_int(Config) ->
#file_info{size=DSize,type=directory,access=DAccess,
atime=AccTime3,mtime=ModTime3} = FileInfo3,
%% this dir was modified only a few secs ago
- ?line io:format("Dir Acc ~p; Mod ~p; Now ~p", [AccTime3, ModTime3, Now]),
- ?line true = abs(time_dist(Now,ModTime3)) < 5,
- ?line DAccess = read_write,
- ?line io:format("Dir size is ~p",[DSize]),
+ io:format("Dir Acc ~p; Mod ~p; Now ~p", [AccTime3, ModTime3, Now]),
+ true = abs(time_dist(Now,ModTime3)) < 5,
+ DAccess = read_write,
+ io:format("Dir size is ~p",[DSize]),
- ?line [] = flush(),
+ [] = flush(),
ok.
%% Filter access times, to copy with a deficiency of FAT file systems
@@ -1579,9 +1472,9 @@ filter_atime(Atime, Config) ->
true ->
case Atime of
{Date, _} ->
- {Date, {0, 0, 0}};
+ {Date, {0, 0, 0}};
{Y, M, D, _, _, _} ->
- {Y, M, D, 0, 0, 0}
+ {Y, M, D, 0, 0, 0}
end;
false ->
Atime
@@ -1589,50 +1482,47 @@ filter_atime(Atime, Config) ->
%% Test the write_file_info/2 function.
-file_write_file_info(suite) -> [];
-file_write_file_info(doc) -> [];
file_write_file_info(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line RootDir = get_good_directory(Config),
- ?line test_server:format("RootDir = ~p", [RootDir]),
+ RootDir = get_good_directory(Config),
+ io:format("RootDir = ~p", [RootDir]),
%% Set the file to read only AND update the file times at the same time.
%% (This used to fail on Windows NT/95 for a local filesystem.)
%% Note: Seconds must be even; see note in file_info_times/1.
- ?line Name1 = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_write_file_info_ro"),
- ?line ok = ?FILE_MODULE:write_file(Name1, "hello"),
- ?line Time = {{1997, 01, 02}, {12, 35, 42}},
- ?line Info = #file_info{mode=8#400, atime=Time, mtime=Time, ctime=Time},
- ?line ok = ?FILE_MODULE:write_file_info(Name1, Info),
+ Name1 = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_write_file_info_ro"),
+ ok = ?FILE_MODULE:write_file(Name1, "hello"),
+ Time = {{1997, 01, 02}, {12, 35, 42}},
+ Info = #file_info{mode=8#400, atime=Time, mtime=Time, ctime=Time},
+ ok = ?FILE_MODULE:write_file_info(Name1, Info),
%% Read back the times.
- ?line {ok, ActualInfo} = ?FILE_MODULE:read_file_info(Name1),
- ?line #file_info{mode=_Mode, atime=ActAtime, mtime=Time,
- ctime=ActCtime} = ActualInfo,
- ?line FilteredAtime = filter_atime(Time, Config),
- ?line FilteredAtime = filter_atime(ActAtime, Config),
- ?line case os:type() of
- {win32, _} ->
- %% On Windows, "ctime" means creation time and it can
- %% be set.
- ActCtime = Time;
- _ ->
- ok
- end,
- ?line {error, eacces} = ?FILE_MODULE:write_file(Name1, "hello again"),
+ {ok, ActualInfo} = ?FILE_MODULE:read_file_info(Name1),
+ #file_info{mode=_Mode, atime=ActAtime, mtime=Time,
+ ctime=ActCtime} = ActualInfo,
+ FilteredAtime = filter_atime(Time, Config),
+ FilteredAtime = filter_atime(ActAtime, Config),
+ case os:type() of
+ {win32, _} ->
+ %% On Windows, "ctime" means creation time and it can
+ %% be set.
+ ActCtime = Time;
+ _ ->
+ ok
+ end,
+ {error, eacces} = ?FILE_MODULE:write_file(Name1, "hello again"),
%% Make the file writable again.
- ?line ?FILE_MODULE:write_file_info(Name1, #file_info{mode=8#600}),
- ?line ok = ?FILE_MODULE:write_file(Name1, "hello again"),
+ ?FILE_MODULE:write_file_info(Name1, #file_info{mode=8#600}),
+ ok = ?FILE_MODULE:write_file(Name1, "hello again"),
%% And unwritable.
- ?line ?FILE_MODULE:write_file_info(Name1, #file_info{mode=8#400}),
- ?line {error, eacces} = ?FILE_MODULE:write_file(Name1, "hello again"),
+ ?FILE_MODULE:write_file_info(Name1, #file_info{mode=8#400}),
+ {error, eacces} = ?FILE_MODULE:write_file(Name1, "hello again"),
%% Same with raw.
?FILE_MODULE:write_file_info(Name1, #file_info{mode=8#600}, [raw]),
@@ -1643,634 +1533,577 @@ file_write_file_info(Config) when is_list(Config) ->
%% Write the times again.
%% Note: Seconds must be even; see note in file_info_times/1.
- ?line NewTime = {{1997, 02, 15}, {13, 18, 20}},
- ?line NewInfo = #file_info{atime=NewTime, mtime=NewTime, ctime=NewTime},
- ?line ok = ?FILE_MODULE:write_file_info(Name1, NewInfo),
- ?line {ok, ActualInfo2} = ?FILE_MODULE:read_file_info(Name1),
- ?line #file_info{atime=NewActAtime, mtime=NewTime,
- ctime=NewActCtime} = ActualInfo2,
- ?line NewFilteredAtime = filter_atime(NewTime, Config),
- ?line NewFilteredAtime = filter_atime(NewActAtime, Config),
- ?line case os:type() of
- {win32, _} -> NewActCtime = NewTime;
- _ -> ok
- end,
+ NewTime = {{1997, 02, 15}, {13, 18, 20}},
+ NewInfo = #file_info{atime=NewTime, mtime=NewTime, ctime=NewTime},
+ ok = ?FILE_MODULE:write_file_info(Name1, NewInfo),
+ {ok, ActualInfo2} = ?FILE_MODULE:read_file_info(Name1),
+ #file_info{atime=NewActAtime, mtime=NewTime,
+ ctime=NewActCtime} = ActualInfo2,
+ NewFilteredAtime = filter_atime(NewTime, Config),
+ NewFilteredAtime = filter_atime(NewActAtime, Config),
+ case os:type() of
+ {win32, _} -> NewActCtime = NewTime;
+ _ -> ok
+ end,
%% The file should still be unwritable.
- ?line {error, eacces} = ?FILE_MODULE:write_file(Name1, "hello again"),
+ {error, eacces} = ?FILE_MODULE:write_file(Name1, "hello again"),
%% Make the file writeable again, so that we can remove the
%% test suites ... :-)
- ?line ?FILE_MODULE:write_file_info(Name1, #file_info{mode=8#600}),
+ ?FILE_MODULE:write_file_info(Name1, #file_info{mode=8#600}),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
%% Returns a directory on a file system that has correct file times.
get_good_directory(Config) ->
- ?line ?config(priv_dir, Config).
+ proplists:get_value(priv_dir, Config).
-consult1(suite) -> [];
-consult1(doc) -> [];
consult1(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_consult.fil"),
- ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_consult.fil"),
+ {ok,Fd1} = ?FILE_MODULE:open(Name,write),
%% note that there is no final \n (only a space)
- ?line io:format(Fd1,
- "{this,[is,1.0],'journey'}.\n\"into\". (sound). ",
- []),
- ?line ok = ?FILE_MODULE:close(Fd1),
- ?line {ok,[{this,[is,1.0],journey},"into",sound]} =
+ io:format(Fd1,
+ "{this,[is,1.0],'journey'}.\n\"into\". (sound). ",
+ []),
+ ok = ?FILE_MODULE:close(Fd1),
+ {ok,[{this,[is,1.0],journey},"into",sound]} =
?FILE_MODULE:consult(Name),
- ?line {ok,Fd2} = ?FILE_MODULE:open(Name,write),
+ {ok,Fd2} = ?FILE_MODULE:open(Name,write),
%% note the missing double quote
- ?line io:format(
- Fd2,"{this,[is,1.0],'journey'}.\n \"into. (sound). ",[]),
- ?line ok = ?FILE_MODULE:close(Fd2),
- ?line {error, {_, _, _} = Msg} = ?FILE_MODULE:consult(Name),
- ?line io:format("Errmsg: ~p",[Msg]),
+ io:format(
+ Fd2,"{this,[is,1.0],'journey'}.\n \"into. (sound). ",[]),
+ ok = ?FILE_MODULE:close(Fd2),
+ {error, {_, _, _} = Msg} = ?FILE_MODULE:consult(Name),
+ io:format("Errmsg: ~p",[Msg]),
- ?line {error, enoent} = ?FILE_MODULE:consult(Name ++ ".nonexistent"),
+ {error, enoent} = ?FILE_MODULE:consult(Name ++ ".nonexistent"),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
-path_consult(suite) -> [];
-path_consult(doc) -> [];
path_consult(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line FileName = atom_to_list(?MODULE)++"_path_consult.fil",
- ?line Name = filename:join(RootDir, FileName),
- ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write),
- ?line io:format(Fd1,"{this,is,a,journey,into,sound}.\n",[]),
- ?line ok = ?FILE_MODULE:close(Fd1),
+ RootDir = proplists:get_value(priv_dir,Config),
+ FileName = atom_to_list(?MODULE)++"_path_consult.fil",
+ Name = filename:join(RootDir, FileName),
+ {ok,Fd1} = ?FILE_MODULE:open(Name,write),
+ io:format(Fd1,"{this,is,a,journey,into,sound}.\n",[]),
+ ok = ?FILE_MODULE:close(Fd1),
%% File last in path
- ?line {ok,[{this,is,a,journey,into,sound}],Dir} =
+ {ok,[{this,is,a,journey,into,sound}],Dir} =
?FILE_MODULE:path_consult(
- [filename:join(RootDir, "dir1"),
- filename:join(RootDir, ".."),
- filename:join(RootDir, "dir2"),
- RootDir], FileName),
- ?line true = lists:prefix(RootDir,Dir),
+ [filename:join(RootDir, "dir1"),
+ filename:join(RootDir, ".."),
+ filename:join(RootDir, "dir2"),
+ RootDir], FileName),
+ true = lists:prefix(RootDir,Dir),
%% While maybe not an error, it may be worth noting that
%% when the full path to a file is given, it's always found
%% regardless of the contents of the path
- ?line {ok,_,_} = ?FILE_MODULE:path_consult(["nosuch1","nosuch2"],Name),
+ {ok,_,_} = ?FILE_MODULE:path_consult(["nosuch1","nosuch2"],Name),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
-eval1(suite) -> [];
-eval1(doc) -> [];
eval1(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)++"_eval.fil"),
- ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)++"_eval.fil"),
+ {ok,Fd1} = ?FILE_MODULE:open(Name,write),
%% note that there is no final \n (only a space)
- ?line io:format(Fd1,"put(evaluated_ok,\ntrue). ",[]),
- ?line ok = ?FILE_MODULE:close(Fd1),
- ?line ok = ?FILE_MODULE:eval(Name),
- ?line true = get(evaluated_ok),
-
- ?line {ok,Fd2} = ?FILE_MODULE:open(Name,write),
+ io:format(Fd1,"put(evaluated_ok,\ntrue). ",[]),
+ ok = ?FILE_MODULE:close(Fd1),
+ ok = ?FILE_MODULE:eval(Name),
+ true = get(evaluated_ok),
+
+ {ok,Fd2} = ?FILE_MODULE:open(Name,write),
%% note that there is no final \n (only a space)
- ?line io:format(Fd2,"put(evaluated_ok,\nR). ",[]),
- ?line ok = ?FILE_MODULE:close(Fd2),
- ?line ok = ?FILE_MODULE:eval(
- Name,
- erl_eval:add_binding('R', true, erl_eval:new_bindings())),
- ?line true = get(evaluated_ok),
-
- ?line {ok,Fd3} = ?FILE_MODULE:open(Name,write),
+ io:format(Fd2,"put(evaluated_ok,\nR). ",[]),
+ ok = ?FILE_MODULE:close(Fd2),
+ ok = ?FILE_MODULE:eval(
+ Name,
+ erl_eval:add_binding('R', true, erl_eval:new_bindings())),
+ true = get(evaluated_ok),
+
+ {ok,Fd3} = ?FILE_MODULE:open(Name,write),
%% garbled
- ?line io:format(Fd3,"puGARBLED-GARBLED\ntrue). ",[]),
- ?line ok = ?FILE_MODULE:close(Fd3),
- ?line {error, {_, _, _} = Msg} = ?FILE_MODULE:eval(Name),
- ?line io:format("Errmsg1: ~p",[Msg]),
-
- ?line {error, enoent} = ?FILE_MODULE:eval(Name ++ ".nonexistent"),
-
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ io:format(Fd3,"puGARBLED-GARBLED\ntrue). ",[]),
+ ok = ?FILE_MODULE:close(Fd3),
+ {error, {_, _, _} = Msg} = ?FILE_MODULE:eval(Name),
+ io:format("Errmsg1: ~p",[Msg]),
+
+ {error, enoent} = ?FILE_MODULE:eval(Name ++ ".nonexistent"),
+
+ [] = flush(),
ok.
-path_eval(suite) -> [];
-path_eval(doc) -> [];
path_eval(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line FileName = atom_to_list(?MODULE)++"_path_eval.fil",
- ?line Name = filename:join(RootDir, FileName),
- ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write),
- ?line io:format(Fd1,"put(evaluated_ok,true).\n",[]),
- ?line ok = ?FILE_MODULE:close(Fd1),
+ RootDir = proplists:get_value(priv_dir,Config),
+ FileName = atom_to_list(?MODULE)++"_path_eval.fil",
+ Name = filename:join(RootDir, FileName),
+ {ok,Fd1} = ?FILE_MODULE:open(Name,write),
+ io:format(Fd1,"put(evaluated_ok,true).\n",[]),
+ ok = ?FILE_MODULE:close(Fd1),
%% File last in path
- ?line {ok,Dir} =
+ {ok,Dir} =
?FILE_MODULE:path_eval(
- [filename:join(RootDir, "dir1"),
- filename:join(RootDir, ".."),
- filename:join(RootDir, "dir2"),
- RootDir],FileName),
- ?line true = get(evaluated_ok),
- ?line true = lists:prefix(RootDir,Dir),
-
+ [filename:join(RootDir, "dir1"),
+ filename:join(RootDir, ".."),
+ filename:join(RootDir, "dir2"),
+ RootDir],FileName),
+ true = get(evaluated_ok),
+ true = lists:prefix(RootDir,Dir),
+
%% While maybe not an error, it may be worth noting that
%% when the full path to a file is given, it's always found
%% regardless of the contents of the path
- ?line {ok,Fd2} = ?FILE_MODULE:open(Name,write),
- ?line io:format(Fd2,"put(evaluated_ok,R).\n",[]),
- ?line ok = ?FILE_MODULE:close(Fd2),
- ?line {ok,_} = ?FILE_MODULE:path_eval(
- ["nosuch1","nosuch2"],
- Name,
- erl_eval:add_binding('R', true, erl_eval:new_bindings())),
-
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ {ok,Fd2} = ?FILE_MODULE:open(Name,write),
+ io:format(Fd2,"put(evaluated_ok,R).\n",[]),
+ ok = ?FILE_MODULE:close(Fd2),
+ {ok,_} = ?FILE_MODULE:path_eval(
+ ["nosuch1","nosuch2"],
+ Name,
+ erl_eval:add_binding('R', true, erl_eval:new_bindings())),
+
+ [] = flush(),
ok.
-script1(suite) -> [];
-script1(doc) -> "";
script1(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)++"_script.fil"),
- ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)++"_script.fil"),
+ {ok,Fd1} = ?FILE_MODULE:open(Name,write),
%% note that there is no final \n (only a space)
- ?line io:format(Fd1,"A = 11,\nB = 6,\nA+B. ",[]),
- ?line ok = ?FILE_MODULE:close(Fd1),
- ?line {ok,17} = ?FILE_MODULE:script(Name),
-
- ?line {ok,Fd2} = ?FILE_MODULE:open(Name,write),
+ io:format(Fd1,"A = 11,\nB = 6,\nA+B. ",[]),
+ ok = ?FILE_MODULE:close(Fd1),
+ {ok,17} = ?FILE_MODULE:script(Name),
+
+ {ok,Fd2} = ?FILE_MODULE:open(Name,write),
%% note that there is no final \n (only a space)
- ?line io:format(Fd2,"A = 11,\nA+B. ",[]),
- ?line ok = ?FILE_MODULE:close(Fd2),
- ?line {ok,17} = ?FILE_MODULE:script(
- Name,
- erl_eval:add_binding('B', 6, erl_eval:new_bindings())),
-
- ?line {ok,Fd3} = ?FILE_MODULE:open(Name,write),
- ?line io:format(Fd3,"A = 11,\nB = six,\nA+B. ",[]),
- ?line ok = ?FILE_MODULE:close(Fd3),
- ?line {error, {_, _, _} = Msg} = ?FILE_MODULE:script(Name),
- ?line io:format("Errmsg1: ~p",[Msg]),
-
- ?line {error, enoent} = ?FILE_MODULE:script(Name ++ ".nonexistent"),
-
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ io:format(Fd2,"A = 11,\nA+B. ",[]),
+ ok = ?FILE_MODULE:close(Fd2),
+ {ok,17} = ?FILE_MODULE:script(
+ Name,
+ erl_eval:add_binding('B', 6, erl_eval:new_bindings())),
+
+ {ok,Fd3} = ?FILE_MODULE:open(Name,write),
+ io:format(Fd3,"A = 11,\nB = six,\nA+B. ",[]),
+ ok = ?FILE_MODULE:close(Fd3),
+ {error, {_, _, _} = Msg} = ?FILE_MODULE:script(Name),
+ io:format("Errmsg1: ~p",[Msg]),
+
+ {error, enoent} = ?FILE_MODULE:script(Name ++ ".nonexistent"),
+
+ [] = flush(),
ok.
-
-path_script(suite) -> [];
-path_script(doc) -> [];
+
path_script(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line FileName = atom_to_list(?MODULE)++"_path_script.fil",
- ?line Name = filename:join(RootDir, FileName),
- ?line {ok,Fd1} = ?FILE_MODULE:open(Name,write),
- ?line io:format(Fd1,"A = 11,\nB = 6,\nA+B.\n",[]),
- ?line ok = ?FILE_MODULE:close(Fd1),
+ RootDir = proplists:get_value(priv_dir,Config),
+ FileName = atom_to_list(?MODULE)++"_path_script.fil",
+ Name = filename:join(RootDir, FileName),
+ {ok,Fd1} = ?FILE_MODULE:open(Name,write),
+ io:format(Fd1,"A = 11,\nB = 6,\nA+B.\n",[]),
+ ok = ?FILE_MODULE:close(Fd1),
%% File last in path
- ?line {ok, 17, Dir} =
+ {ok, 17, Dir} =
?FILE_MODULE:path_script(
[filename:join(RootDir, "dir1"),
filename:join(RootDir, ".."),
filename:join(RootDir, "dir2"),
RootDir],FileName),
- ?line true = lists:prefix(RootDir,Dir),
-
+ true = lists:prefix(RootDir,Dir),
+
%% While maybe not an error, it may be worth noting that
%% when the full path to a file is given, it's always found
%% regardless of the contents of the path
- ?line {ok,Fd2} = ?FILE_MODULE:open(Name,write),
- ?line io:format(Fd2,"A = 11,\nA+B.",[]),
- ?line ok = ?FILE_MODULE:close(Fd2),
- ?line {ok, 17, Dir} =
+ {ok,Fd2} = ?FILE_MODULE:open(Name,write),
+ io:format(Fd2,"A = 11,\nA+B.",[]),
+ ok = ?FILE_MODULE:close(Fd2),
+ {ok, 17, Dir} =
?FILE_MODULE:path_script(
["nosuch1","nosuch2"],
Name,
erl_eval:add_binding('B', 6, erl_eval:new_bindings())),
-
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+
+ [] = flush(),
ok.
-
-truncate(suite) -> [];
-truncate(doc) -> [];
+
truncate(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_truncate.fil"),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_truncate.fil"),
%% Create a file with some data.
- ?line MyData = "0123456789abcdefghijklmnopqrstuvxyz",
- ?line ok = ?FILE_MODULE:write_file(Name, MyData),
+ MyData = "0123456789abcdefghijklmnopqrstuvxyz",
+ ok = ?FILE_MODULE:write_file(Name, MyData),
%% Truncate the file to 10 characters.
- ?line {ok, Fd} = ?FILE_MODULE:open(Name, read_write),
- ?line {ok, 10} = ?FILE_MODULE:position(Fd, 10),
- ?line ok = ?FILE_MODULE:truncate(Fd),
- ?line ok = ?FILE_MODULE:close(Fd),
+ {ok, Fd} = ?FILE_MODULE:open(Name, read_write),
+ {ok, 10} = ?FILE_MODULE:position(Fd, 10),
+ ok = ?FILE_MODULE:truncate(Fd),
+ ok = ?FILE_MODULE:close(Fd),
%% Read back the file and check that it has been truncated.
- ?line Expected = list_to_binary("0123456789"),
- ?line {ok, Expected} = ?FILE_MODULE:read_file(Name),
+ Expected = list_to_binary("0123456789"),
+ {ok, Expected} = ?FILE_MODULE:read_file(Name),
%% Open the file read only and verify that it is not possible to
%% truncate it, OTP-1960
- ?line {ok, Fd2} = ?FILE_MODULE:open(Name, read),
- ?line {ok, 5} = ?FILE_MODULE:position(Fd2, 5),
- ?line {error, _} = ?FILE_MODULE:truncate(Fd2),
+ {ok, Fd2} = ?FILE_MODULE:open(Name, read),
+ {ok, 5} = ?FILE_MODULE:position(Fd2, 5),
+ {error, _} = ?FILE_MODULE:truncate(Fd2),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
-datasync(suite) -> [];
-datasync(doc) -> "Tests that ?FILE_MODULE:datasync/1 at least doesn't crash.";
+%% Tests that ?FILE_MODULE:datasync/1 at least doesn't crash.
datasync(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Sync = filename:join(PrivDir,
- atom_to_list(?MODULE)
- ++"_sync.fil"),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Sync = filename:join(PrivDir,
+ atom_to_list(?MODULE)
+ ++"_sync.fil"),
%% Raw open.
- ?line {ok, Fd} = ?FILE_MODULE:open(Sync, [write, raw]),
- ?line ok = ?FILE_MODULE:datasync(Fd),
- ?line ok = ?FILE_MODULE:close(Fd),
+ {ok, Fd} = ?FILE_MODULE:open(Sync, [write, raw]),
+ ok = ?FILE_MODULE:datasync(Fd),
+ ok = ?FILE_MODULE:close(Fd),
%% Ordinary open.
- ?line {ok, Fd2} = ?FILE_MODULE:open(Sync, [write]),
- ?line ok = ?FILE_MODULE:datasync(Fd2),
- ?line ok = ?FILE_MODULE:close(Fd2),
+ {ok, Fd2} = ?FILE_MODULE:open(Sync, [write]),
+ ok = ?FILE_MODULE:datasync(Fd2),
+ ok = ?FILE_MODULE:close(Fd2),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
-sync(suite) -> [];
-sync(doc) -> "Tests that ?FILE_MODULE:sync/1 at least doesn't crash.";
+%% Tests that ?FILE_MODULE:sync/1 at least doesn't crash.
sync(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Sync = filename:join(PrivDir,
- atom_to_list(?MODULE)
- ++"_sync.fil"),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Sync = filename:join(PrivDir,
+ atom_to_list(?MODULE)
+ ++"_sync.fil"),
%% Raw open.
- ?line {ok, Fd} = ?FILE_MODULE:open(Sync, [write, raw]),
- ?line ok = ?FILE_MODULE:sync(Fd),
- ?line ok = ?FILE_MODULE:close(Fd),
+ {ok, Fd} = ?FILE_MODULE:open(Sync, [write, raw]),
+ ok = ?FILE_MODULE:sync(Fd),
+ ok = ?FILE_MODULE:close(Fd),
%% Ordinary open.
- ?line {ok, Fd2} = ?FILE_MODULE:open(Sync, [write]),
- ?line ok = ?FILE_MODULE:sync(Fd2),
- ?line ok = ?FILE_MODULE:close(Fd2),
+ {ok, Fd2} = ?FILE_MODULE:open(Sync, [write]),
+ ok = ?FILE_MODULE:sync(Fd2),
+ ok = ?FILE_MODULE:close(Fd2),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
-advise(suite) -> [];
-advise(doc) -> "Tests that ?FILE_MODULE:advise/4 at least doesn't crash.";
+%% Tests that ?FILE_MODULE:advise/4 at least doesn't crash.
advise(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Advise = filename:join(PrivDir,
- atom_to_list(?MODULE)
- ++"_advise.fil"),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Advise = filename:join(PrivDir,
+ atom_to_list(?MODULE)
+ ++"_advise.fil"),
Line1 = "Hello\n",
Line2 = "World!\n",
- ?line {ok, Fd} = ?FILE_MODULE:open(Advise, [write]),
- ?line ok = ?FILE_MODULE:advise(Fd, 0, 0, normal),
- ?line ok = io:format(Fd, "~s", [Line1]),
- ?line ok = io:format(Fd, "~s", [Line2]),
- ?line ok = ?FILE_MODULE:close(Fd),
-
- ?line {ok, Fd2} = ?FILE_MODULE:open(Advise, [write]),
- ?line ok = ?FILE_MODULE:advise(Fd2, 0, 0, random),
- ?line ok = io:format(Fd2, "~s", [Line1]),
- ?line ok = io:format(Fd2, "~s", [Line2]),
- ?line ok = ?FILE_MODULE:close(Fd2),
-
- ?line {ok, Fd3} = ?FILE_MODULE:open(Advise, [write]),
- ?line ok = ?FILE_MODULE:advise(Fd3, 0, 0, sequential),
- ?line ok = io:format(Fd3, "~s", [Line1]),
- ?line ok = io:format(Fd3, "~s", [Line2]),
- ?line ok = ?FILE_MODULE:close(Fd3),
-
- ?line {ok, Fd4} = ?FILE_MODULE:open(Advise, [write]),
- ?line ok = ?FILE_MODULE:advise(Fd4, 0, 0, will_need),
- ?line ok = io:format(Fd4, "~s", [Line1]),
- ?line ok = io:format(Fd4, "~s", [Line2]),
- ?line ok = ?FILE_MODULE:close(Fd4),
-
- ?line {ok, Fd5} = ?FILE_MODULE:open(Advise, [write]),
- ?line ok = ?FILE_MODULE:advise(Fd5, 0, 0, dont_need),
- ?line ok = io:format(Fd5, "~s", [Line1]),
- ?line ok = io:format(Fd5, "~s", [Line2]),
- ?line ok = ?FILE_MODULE:close(Fd5),
-
- ?line {ok, Fd6} = ?FILE_MODULE:open(Advise, [write]),
- ?line ok = ?FILE_MODULE:advise(Fd6, 0, 0, no_reuse),
- ?line ok = io:format(Fd6, "~s", [Line1]),
- ?line ok = io:format(Fd6, "~s", [Line2]),
- ?line ok = ?FILE_MODULE:close(Fd6),
-
- ?line {ok, Fd7} = ?FILE_MODULE:open(Advise, [write]),
- ?line {error, einval} = ?FILE_MODULE:advise(Fd7, 0, 0, bad_advise),
- ?line ok = ?FILE_MODULE:close(Fd7),
+ {ok, Fd} = ?FILE_MODULE:open(Advise, [write]),
+ ok = ?FILE_MODULE:advise(Fd, 0, 0, normal),
+ ok = io:format(Fd, "~s", [Line1]),
+ ok = io:format(Fd, "~s", [Line2]),
+ ok = ?FILE_MODULE:close(Fd),
+
+ {ok, Fd2} = ?FILE_MODULE:open(Advise, [write]),
+ ok = ?FILE_MODULE:advise(Fd2, 0, 0, random),
+ ok = io:format(Fd2, "~s", [Line1]),
+ ok = io:format(Fd2, "~s", [Line2]),
+ ok = ?FILE_MODULE:close(Fd2),
+
+ {ok, Fd3} = ?FILE_MODULE:open(Advise, [write]),
+ ok = ?FILE_MODULE:advise(Fd3, 0, 0, sequential),
+ ok = io:format(Fd3, "~s", [Line1]),
+ ok = io:format(Fd3, "~s", [Line2]),
+ ok = ?FILE_MODULE:close(Fd3),
+
+ {ok, Fd4} = ?FILE_MODULE:open(Advise, [write]),
+ ok = ?FILE_MODULE:advise(Fd4, 0, 0, will_need),
+ ok = io:format(Fd4, "~s", [Line1]),
+ ok = io:format(Fd4, "~s", [Line2]),
+ ok = ?FILE_MODULE:close(Fd4),
+
+ {ok, Fd5} = ?FILE_MODULE:open(Advise, [write]),
+ ok = ?FILE_MODULE:advise(Fd5, 0, 0, dont_need),
+ ok = io:format(Fd5, "~s", [Line1]),
+ ok = io:format(Fd5, "~s", [Line2]),
+ ok = ?FILE_MODULE:close(Fd5),
+
+ {ok, Fd6} = ?FILE_MODULE:open(Advise, [write]),
+ ok = ?FILE_MODULE:advise(Fd6, 0, 0, no_reuse),
+ ok = io:format(Fd6, "~s", [Line1]),
+ ok = io:format(Fd6, "~s", [Line2]),
+ ok = ?FILE_MODULE:close(Fd6),
+
+ {ok, Fd7} = ?FILE_MODULE:open(Advise, [write]),
+ {error, einval} = ?FILE_MODULE:advise(Fd7, 0, 0, bad_advise),
+ ok = ?FILE_MODULE:close(Fd7),
%% test write without advise, then a read after an advise
- ?line {ok, Fd8} = ?FILE_MODULE:open(Advise, [write]),
- ?line ok = io:format(Fd8, "~s", [Line1]),
- ?line ok = io:format(Fd8, "~s", [Line2]),
- ?line ok = ?FILE_MODULE:close(Fd8),
- ?line {ok, Fd9} = ?FILE_MODULE:open(Advise, [read]),
+ {ok, Fd8} = ?FILE_MODULE:open(Advise, [write]),
+ ok = io:format(Fd8, "~s", [Line1]),
+ ok = io:format(Fd8, "~s", [Line2]),
+ ok = ?FILE_MODULE:close(Fd8),
+ {ok, Fd9} = ?FILE_MODULE:open(Advise, [read]),
Offset = 0,
%% same as a 0 length in some implementations
Length = length(Line1) + length(Line2),
- ?line ok = ?FILE_MODULE:advise(Fd9, Offset, Length, sequential),
- ?line {ok, Line1} = ?FILE_MODULE:read_line(Fd9),
- ?line {ok, Line2} = ?FILE_MODULE:read_line(Fd9),
- ?line eof = ?FILE_MODULE:read_line(Fd9),
- ?line ok = ?FILE_MODULE:close(Fd9),
-
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ ok = ?FILE_MODULE:advise(Fd9, Offset, Length, sequential),
+ {ok, Line1} = ?FILE_MODULE:read_line(Fd9),
+ {ok, Line2} = ?FILE_MODULE:read_line(Fd9),
+ eof = ?FILE_MODULE:read_line(Fd9),
+ ok = ?FILE_MODULE:close(Fd9),
+
+ [] = flush(),
ok.
-allocate(suite) -> [];
-allocate(doc) -> "Tests that ?FILE_MODULE:allocate/3 at least doesn't crash.";
+%% Tests that ?FILE_MODULE:allocate/3 at least doesn't crash.
allocate(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Allocate = filename:join(PrivDir,
- atom_to_list(?MODULE)
- ++"_allocate.fil"),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Allocate = filename:join(PrivDir,
+ atom_to_list(?MODULE)
+ ++"_allocate.fil"),
Line1 = "Hello\n",
Line2 = "World!\n",
- ?line {ok, Fd} = ?FILE_MODULE:open(Allocate, [write, binary]),
+ {ok, Fd} = ?FILE_MODULE:open(Allocate, [write, binary]),
allocate_and_assert(Fd, 1, iolist_size([Line1, Line2])),
- ?line ok = io:format(Fd, "~s", [Line1]),
- ?line ok = io:format(Fd, "~s", [Line2]),
- ?line ok = ?FILE_MODULE:close(Fd),
+ ok = io:format(Fd, "~s", [Line1]),
+ ok = io:format(Fd, "~s", [Line2]),
+ ok = ?FILE_MODULE:close(Fd),
- ?line {ok, Fd2} = ?FILE_MODULE:open(Allocate, [write, binary]),
+ {ok, Fd2} = ?FILE_MODULE:open(Allocate, [write, binary]),
allocate_and_assert(Fd2, 1, iolist_size(Line1)),
- ?line ok = io:format(Fd2, "~s", [Line1]),
- ?line ok = io:format(Fd2, "~s", [Line2]),
- ?line ok = ?FILE_MODULE:close(Fd2),
+ ok = io:format(Fd2, "~s", [Line1]),
+ ok = io:format(Fd2, "~s", [Line2]),
+ ok = ?FILE_MODULE:close(Fd2),
- ?line {ok, Fd3} = ?FILE_MODULE:open(Allocate, [write, binary]),
+ {ok, Fd3} = ?FILE_MODULE:open(Allocate, [write, binary]),
allocate_and_assert(Fd3, 1, iolist_size(Line1) + 1),
- ?line ok = io:format(Fd3, "~s", [Line1]),
- ?line ok = io:format(Fd3, "~s", [Line2]),
- ?line ok = ?FILE_MODULE:close(Fd3),
+ ok = io:format(Fd3, "~s", [Line1]),
+ ok = io:format(Fd3, "~s", [Line2]),
+ ok = ?FILE_MODULE:close(Fd3),
- ?line {ok, Fd4} = ?FILE_MODULE:open(Allocate, [write, binary]),
+ {ok, Fd4} = ?FILE_MODULE:open(Allocate, [write, binary]),
allocate_and_assert(Fd4, 1, 4 * iolist_size([Line1, Line2])),
- ?line ok = io:format(Fd4, "~s", [Line1]),
- ?line ok = io:format(Fd4, "~s", [Line2]),
- ?line ok = ?FILE_MODULE:close(Fd4),
+ ok = io:format(Fd4, "~s", [Line1]),
+ ok = io:format(Fd4, "~s", [Line2]),
+ ok = ?FILE_MODULE:close(Fd4),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
allocate_and_assert(Fd, Offset, Length) ->
- % Just verify that calls to ?PRIM_FILE:allocate/3 don't crash or have
- % any other negative side effect. We can't really asssert against a
- % specific return value, because support for file space pre-allocation
- % depends on the OS, OS version and underlying filesystem.
- %
- % The Linux kernel added support for fallocate() in version 2.6.23,
- % which currently works only for the ext4, ocfs2, xfs and btrfs file
- % systems. posix_fallocate() is available in glibc as of version
- % 2.1.94, but it was buggy until glibc version 2.7.
- %
- % Mac OS X, as of version 10.3, supports the fcntl operation F_PREALLOCATE.
- %
- % Solaris supports posix_fallocate() but only for the UFS file system
- % apparently (not supported for ZFS).
- %
- % FreeBSD 9.0 is the first FreeBSD release supporting posix_fallocate().
- %
- % For Windows there's apparently no way to pre-allocate file space, at
- % least with same semantics as posix_fallocate(), fallocate() and
- % fcntl F_PREALLOCATE.
+ %% Just verify that calls to ?PRIM_FILE:allocate/3 don't crash or have
+ %% any other negative side effect. We can't really asssert against a
+ %% specific return value, because support for file space pre-allocation
+ %% depends on the OS, OS version and underlying filesystem.
+ %%
+ %% The Linux kernel added support for fallocate() in version 2.6.23,
+ %% which currently works only for the ext4, ocfs2, xfs and btrfs file
+ %% systems. posix_fallocate() is available in glibc as of version
+ %% 2.1.94, but it was buggy until glibc version 2.7.
+ %%
+ %% Mac OS X, as of version 10.3, supports the fcntl operation F_PREALLOCATE.
+ %%
+ %% Solaris supports posix_fallocate() but only for the UFS file system
+ %% apparently (not supported for ZFS).
+ %%
+ %% FreeBSD 9.0 is the first FreeBSD release supporting posix_fallocate().
+ %%
+ %% For Windows there's apparently no way to pre-allocate file space, at
+ %% least with same semantics as posix_fallocate(), fallocate() and
+ %% fcntl F_PREALLOCATE.
Result = ?FILE_MODULE:allocate(Fd, Offset, Length),
case os:type() of
{win32, _} ->
- ?line {error, enotsup} = Result;
+ {error, enotsup} = Result;
_ ->
- ?line _ = Result
+ _ = Result
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-delete(suite) -> [];
-delete(doc) -> [];
delete(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_delete.fil"),
- ?line {ok, Fd1} = ?FILE_MODULE:open(Name, write),
- ?line io:format(Fd1,"ok.\n",[]),
- ?line ok = ?FILE_MODULE:close(Fd1),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_delete.fil"),
+ {ok, Fd1} = ?FILE_MODULE:open(Name, write),
+ io:format(Fd1,"ok.\n",[]),
+ ok = ?FILE_MODULE:close(Fd1),
%% Check that the file is readable
- ?line {ok, Fd2} = ?FILE_MODULE:open(Name, read),
- ?line ok = ?FILE_MODULE:close(Fd2),
- ?line ok = ?FILE_MODULE:delete(Name),
+ {ok, Fd2} = ?FILE_MODULE:open(Name, read),
+ ok = ?FILE_MODULE:close(Fd2),
+ ok = ?FILE_MODULE:delete(Name),
%% Check that the file is not readable anymore
- ?line {error, _} = ?FILE_MODULE:open(Name, read),
+ {error, _} = ?FILE_MODULE:open(Name, read),
%% Try deleting a nonexistent file
- ?line {error, enoent} = ?FILE_MODULE:delete(Name),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ {error, enoent} = ?FILE_MODULE:delete(Name),
+ [] = flush(),
ok.
-rename(suite) ->[];
-rename(doc) ->[];
rename(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line FileName1 = atom_to_list(?MODULE)++"_rename.fil",
- ?line FileName2 = atom_to_list(?MODULE)++"_rename.ful",
- ?line Name1 = filename:join(RootDir, FileName1),
- ?line Name2 = filename:join(RootDir, FileName2),
- ?line {ok,Fd1} = ?FILE_MODULE:open(Name1,write),
- ?line ok = ?FILE_MODULE:close(Fd1),
+ RootDir = proplists:get_value(priv_dir,Config),
+ FileName1 = atom_to_list(?MODULE)++"_rename.fil",
+ FileName2 = atom_to_list(?MODULE)++"_rename.ful",
+ Name1 = filename:join(RootDir, FileName1),
+ Name2 = filename:join(RootDir, FileName2),
+ {ok,Fd1} = ?FILE_MODULE:open(Name1,write),
+ ok = ?FILE_MODULE:close(Fd1),
%% Rename, and check that id really changed name
- ?line ok = ?FILE_MODULE:rename(Name1,Name2),
- ?line {error, _} = ?FILE_MODULE:open(Name1,read),
- ?line {ok,Fd2} = ?FILE_MODULE:open(Name2,read),
- ?line ok = ?FILE_MODULE:close(Fd2),
+ ok = ?FILE_MODULE:rename(Name1,Name2),
+ {error, _} = ?FILE_MODULE:open(Name1,read),
+ {ok,Fd2} = ?FILE_MODULE:open(Name2,read),
+ ok = ?FILE_MODULE:close(Fd2),
%% Try renaming something to itself
- ?line ok = ?FILE_MODULE:rename(Name2,Name2),
+ ok = ?FILE_MODULE:rename(Name2,Name2),
%% Try renaming something that doesn't exist
- ?line {error, enoent} = ?FILE_MODULE:rename(Name1,Name2),
+ {error, enoent} = ?FILE_MODULE:rename(Name1,Name2),
%% Try renaming to something else than a string
- ?line {error, badarg} = ?FILE_MODULE:rename(Name1,{foo,bar}),
-
+ {error, badarg} = ?FILE_MODULE:rename(Name1,{foo,bar}),
+
%% Move between directories
- ?line DirName1 = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_rename_dir"),
- ?line DirName2 = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_second_rename_dir"),
- ?line Name1foo = filename:join(DirName1, "foo.fil"),
- ?line Name2foo = filename:join(DirName2, "foo.fil"),
- ?line Name2bar = filename:join(DirName2, "bar.dir"),
- ?line ok = ?FILE_MODULE:make_dir(DirName1),
+ DirName1 = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_rename_dir"),
+ DirName2 = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_second_rename_dir"),
+ Name1foo = filename:join(DirName1, "foo.fil"),
+ Name2foo = filename:join(DirName2, "foo.fil"),
+ Name2bar = filename:join(DirName2, "bar.dir"),
+ ok = ?FILE_MODULE:make_dir(DirName1),
%% The name has to include the full file name, path in not enough
- ?line expect({error, eisdir}, {error, eexist},
- ?FILE_MODULE:rename(Name2,DirName1)),
- ?line ok = ?FILE_MODULE:rename(Name2, Name1foo),
+ expect({error, eisdir}, {error, eexist},
+ ?FILE_MODULE:rename(Name2,DirName1)),
+ ok = ?FILE_MODULE:rename(Name2, Name1foo),
%% Now rename the directory
- ?line ok = ?FILE_MODULE:rename(DirName1,DirName2),
+ ok = ?FILE_MODULE:rename(DirName1,DirName2),
%% And check that the file is there now
- ?line {ok,Fd3} = ?FILE_MODULE:open(Name2foo, read),
- ?line ok = ?FILE_MODULE:close(Fd3),
+ {ok,Fd3} = ?FILE_MODULE:open(Name2foo, read),
+ ok = ?FILE_MODULE:close(Fd3),
%% Try some dirty things now: move the directory into itself
- ?line {error, Msg1} = ?FILE_MODULE:rename(DirName2, Name2bar),
- ?line io:format("Errmsg1: ~p",[Msg1]),
+ {error, Msg1} = ?FILE_MODULE:rename(DirName2, Name2bar),
+ io:format("Errmsg1: ~p",[Msg1]),
%% move dir into a file in itself
- ?line {error, Msg2} = ?FILE_MODULE:rename(DirName2, Name2foo),
- ?line io:format("Errmsg2: ~p",[Msg2]),
+ {error, Msg2} = ?FILE_MODULE:rename(DirName2, Name2foo),
+ io:format("Errmsg2: ~p",[Msg2]),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-names(suite) -> [];
-names(doc) -> [];
names(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(5)),
- ?line RootDir = ?config(priv_dir,Config),
- ?line FileName = "foo1.fil",
- ?line Name1 = filename:join(RootDir, FileName),
- ?line Name2 = [RootDir,"/","foo1",".","fil"],
- ?line Name3 = [RootDir,"/",foo,$1,[[[],[],'.']],"f",il],
- ?line {ok,Fd0} = ?FILE_MODULE:open(Name1,write),
- ?line ok = ?FILE_MODULE:close(Fd0),
+ RootDir = proplists:get_value(priv_dir,Config),
+ FileName = "foo1.fil",
+ Name1 = filename:join(RootDir, FileName),
+ Name2 = [RootDir,"/","foo1",".","fil"],
+ Name3 = [RootDir,"/",foo,$1,[[[],[],'.']],"f",il],
+ {ok,Fd0} = ?FILE_MODULE:open(Name1,write),
+ ok = ?FILE_MODULE:close(Fd0),
%% Try some file names
- ?line {ok,Fd1} = ?FILE_MODULE:open(Name1,read),
- ?line ok = ?FILE_MODULE:close(Fd1),
- ?line {ok,Fd2f} = ?FILE_MODULE:open(lists:flatten(Name2),read),
- ?line ok = ?FILE_MODULE:close(Fd2f),
- ?line {ok,Fd2} = ?FILE_MODULE:open(Name2,read),
- ?line ok = ?FILE_MODULE:close(Fd2),
- ?line {ok,Fd3} = ?FILE_MODULE:open(Name3,read),
- ?line ok = ?FILE_MODULE:close(Fd3),
- case length(Name1) > 255 of
- true ->
- io:format("Path too long for an atom:\n\n~p\n", [Name1]);
- false ->
- Name4 = list_to_atom(Name1),
- {ok,Fd4} = ?FILE_MODULE:open(Name4,read),
- ok = ?FILE_MODULE:close(Fd4)
- end,
+ {ok,Fd1} = ?FILE_MODULE:open(Name1,read),
+ ok = ?FILE_MODULE:close(Fd1),
+ {ok,Fd2f} = ?FILE_MODULE:open(lists:flatten(Name2),read),
+ ok = ?FILE_MODULE:close(Fd2f),
+ {ok,Fd2} = ?FILE_MODULE:open(Name2,read),
+ ok = ?FILE_MODULE:close(Fd2),
+ {ok,Fd3} = ?FILE_MODULE:open(Name3,read),
+ ok = ?FILE_MODULE:close(Fd3),
+ case length(Name1) > 255 of
+ true ->
+ io:format("Path too long for an atom:\n\n~p\n", [Name1]);
+ false ->
+ Name4 = list_to_atom(Name1),
+ {ok,Fd4} = ?FILE_MODULE:open(Name4,read),
+ ok = ?FILE_MODULE:close(Fd4)
+ end,
%% Try some path names
- ?line Path1 = RootDir,
- ?line Path2 = [RootDir],
- ?line Path3 = ['',[],[RootDir,[[]]]],
- ?line {ok,Fd11,_} = ?FILE_MODULE:path_open([Path1],FileName,read),
- ?line ok = ?FILE_MODULE:close(Fd11),
- ?line {ok,Fd12,_} = ?FILE_MODULE:path_open([Path2],FileName,read),
- ?line ok = ?FILE_MODULE:close(Fd12),
- ?line {ok,Fd13,_} = ?FILE_MODULE:path_open([Path3],FileName,read),
- ?line ok = ?FILE_MODULE:close(Fd13),
- case length(Path1) > 255 of
- true->
- io:format("Path too long for an atom:\n\n~p\n", [Path1]);
- false ->
- Path4 = list_to_atom(Path1),
- {ok,Fd14,_} = ?FILE_MODULE:path_open([Path4],FileName,read),
- ok = ?FILE_MODULE:close(Fd14)
- end,
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ Path1 = RootDir,
+ Path2 = [RootDir],
+ Path3 = ['',[],[RootDir,[[]]]],
+ {ok,Fd11,_} = ?FILE_MODULE:path_open([Path1],FileName,read),
+ ok = ?FILE_MODULE:close(Fd11),
+ {ok,Fd12,_} = ?FILE_MODULE:path_open([Path2],FileName,read),
+ ok = ?FILE_MODULE:close(Fd12),
+ {ok,Fd13,_} = ?FILE_MODULE:path_open([Path3],FileName,read),
+ ok = ?FILE_MODULE:close(Fd13),
+ case length(Path1) > 255 of
+ true->
+ io:format("Path too long for an atom:\n\n~p\n", [Path1]);
+ false ->
+ Path4 = list_to_atom(Path1),
+ {ok,Fd14,_} = ?FILE_MODULE:path_open([Path4],FileName,read),
+ ok = ?FILE_MODULE:close(Fd14)
+ end,
+ [] = flush(),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-e_delete(suite) -> [];
-e_delete(doc) -> [];
e_delete(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line Base = filename:join(RootDir,
- atom_to_list(?MODULE)++"_e_delete"),
- ?line ok = ?FILE_MODULE:make_dir(Base),
+ RootDir = proplists:get_value(priv_dir, Config),
+ Base = filename:join(RootDir,
+ atom_to_list(?MODULE)++"_e_delete"),
+ ok = ?FILE_MODULE:make_dir(Base),
%% Delete a non-existing file.
- ?line {error, enoent} =
+ {error, enoent} =
?FILE_MODULE:delete(filename:join(Base, "non_existing")),
%% Delete a directory.
- ?line {error, eperm} = ?FILE_MODULE:delete(Base),
+ {error, eperm} = ?FILE_MODULE:delete(Base),
%% Use a path-name with a non-directory component.
- ?line Afile = filename:join(Base, "a_file"),
- ?line ok = ?FILE_MODULE:write_file(Afile, "hello\n"),
- ?line {error, E} =
+ Afile = filename:join(Base, "a_file"),
+ ok = ?FILE_MODULE:write_file(Afile, "hello\n"),
+ {error, E} =
expect({error, enotdir}, {error, enoent},
?FILE_MODULE:delete(filename:join(Afile, "another_file"))),
- ?line io:format("Result: ~p~n", [E]),
+ io:format("Result: ~p~n", [E]),
%% No permission.
- ?line case os:type() of
- {win32, _} ->
- %% Remove a character device.
- ?line {error, eacces} = ?FILE_MODULE:delete("nul");
- _ ->
- ?line ?FILE_MODULE:write_file_info(
- Base, #file_info {mode=0}),
- ?line {error, eacces} = ?FILE_MODULE:delete(Afile),
- ?line ?FILE_MODULE:write_file_info(
- Base, #file_info {mode=8#600})
- end,
+ case os:type() of
+ {win32, _} ->
+ %% Remove a character device.
+ {error, eacces} = ?FILE_MODULE:delete("nul");
+ _ ->
+ ?FILE_MODULE:write_file_info(
+ Base, #file_info {mode=0}),
+ {error, eacces} = ?FILE_MODULE:delete(Afile),
+ ?FILE_MODULE:write_file_info(
+ Base, #file_info {mode=8#600})
+ end,
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
%%% FreeBSD gives EEXIST when renaming a file to an empty dir, although the
@@ -2278,13 +2111,10 @@ e_delete(Config) when is_list(Config) ->
%%% (What about FreeBSD? We store our nightly build results on a FreeBSD
%%% file system, that's what.)
-e_rename(suite) -> [];
-e_rename(doc) -> [];
e_rename(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
- RootDir = ?config(priv_dir, Config),
+ RootDir = proplists:get_value(priv_dir, Config),
Base = filename:join(RootDir,
- atom_to_list(?MODULE)++"_e_rename"),
+ atom_to_list(?MODULE)++"_e_rename"),
ok = ?FILE_MODULE:make_dir(Base),
%% Create an empty directory.
@@ -2295,15 +2125,15 @@ e_rename(Config) when is_list(Config) ->
NonEmptyDir = filename:join(Base, "non_empty_dir"),
ok = ?FILE_MODULE:make_dir(NonEmptyDir),
ok = ?FILE_MODULE:write_file(
- filename:join(NonEmptyDir, "a_file"),
- "hello\n"),
+ filename:join(NonEmptyDir, "a_file"),
+ "hello\n"),
%% Create another non-empty directory.
ADirectory = filename:join(Base, "a_directory"),
ok = ?FILE_MODULE:make_dir(ADirectory),
ok = ?FILE_MODULE:write_file(
- filename:join(ADirectory, "a_file"),
- "howdy\n\n"),
+ filename:join(ADirectory, "a_file"),
+ "howdy\n\n"),
%% Create a data file.
File = filename:join(Base, "just_a_file"),
@@ -2317,15 +2147,15 @@ e_rename(Config) when is_list(Config) ->
%% Move Base into Base/new_name.
{error, einval} =
- ?FILE_MODULE:rename(Base, filename:join(Base, "new_name")),
+ ?FILE_MODULE:rename(Base, filename:join(Base, "new_name")),
%% Overwrite a directory with a file.
expect({error, eexist}, %FreeBSD (?)
- {error, eisdir},
- ?FILE_MODULE:rename(File, EmptyDir)),
+ {error, eisdir},
+ ?FILE_MODULE:rename(File, EmptyDir)),
expect({error, eexist}, %FreeBSD (?)
- {error, eisdir},
- ?FILE_MODULE:rename(File, NonEmptyDir)),
+ {error, eisdir},
+ ?FILE_MODULE:rename(File, NonEmptyDir)),
%% Move a non-existing file.
NonExistingFile = filename:join(Base, "non_existing_file"),
@@ -2333,8 +2163,8 @@ e_rename(Config) when is_list(Config) ->
%% Overwrite a file with a directory.
expect({error, eexist}, %FreeBSD (?)
- {error, enotdir},
- ?FILE_MODULE:rename(ADirectory, File)),
+ {error, enotdir},
+ ?FILE_MODULE:rename(ADirectory, File)),
%% Move a file to another filesystem.
%% XXX - This test case is bogus. We cannot be guaranteed that
@@ -2343,49 +2173,42 @@ e_rename(Config) when is_list(Config) ->
%%
%% XXX - Gross hack!
Comment = case os:type() of
- {unix, _} ->
- OtherFs = "/tmp",
- NameOnOtherFs = filename:join(OtherFs, filename:basename(File)),
- {ok, Com} = case ?FILE_MODULE:rename(File, NameOnOtherFs) of
- {error, exdev} ->
- %% The file could be in
- %% the same filesystem!
- {ok, ok};
- ok ->
- {ok, {comment,
- "Moving between filesystems "
- "suceeded, files are probably "
- "in the same filesystem!"}};
- {error, eperm} ->
- {ok, {comment, "SBS! You don't "
- "have the permission to do "
- "this test!"}};
- Else ->
- Else
- end,
- Com;
- {win32, _} ->
- %% At least Windows NT can
- %% successfully move a file to
- %% another drive.
- ok;
- {ose, _} ->
- %% disabled for now
- ok
- end,
+ {unix, _} ->
+ OtherFs = "/tmp",
+ NameOnOtherFs = filename:join(OtherFs, filename:basename(File)),
+ {ok, Com} = case ?FILE_MODULE:rename(File, NameOnOtherFs) of
+ {error, exdev} ->
+ %% The file could be in
+ %% the same filesystem!
+ {ok, ok};
+ ok ->
+ {ok, {comment,
+ "Moving between filesystems "
+ "suceeded, files are probably "
+ "in the same filesystem!"}};
+ {error, eperm} ->
+ {ok, {comment, "SBS! You don't "
+ "have the permission to do "
+ "this test!"}};
+ Else ->
+ Else
+ end,
+ Com;
+ {win32, _} ->
+ %% At least Windows NT can
+ %% successfully move a file to
+ %% another drive.
+ ok
+ end,
[] = flush(),
- test_server:timetrap_cancel(Dog),
Comment.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-e_make_dir(suite) -> [];
-e_make_dir(doc) -> [];
e_make_dir(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
- RootDir = ?config(priv_dir, Config),
+ RootDir = proplists:get_value(priv_dir, Config),
Base = filename:join(RootDir,
- atom_to_list(?MODULE)++"_e_make_dir"),
+ atom_to_list(?MODULE)++"_e_make_dir"),
ok = ?FILE_MODULE:make_dir(Base),
%% A component of the path does not exist.
@@ -2408,18 +2231,14 @@ e_make_dir(Config) when is_list(Config) ->
?FILE_MODULE:write_file_info(Base, #file_info {mode=0}),
{error, eacces} = ?FILE_MODULE:make_dir(filename:join(Base, "xxxx")),
?FILE_MODULE:write_file_info(
- Base, #file_info {mode=8#600})
+ Base, #file_info {mode=8#600})
end,
- test_server:timetrap_cancel(Dog),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-e_del_dir(suite) -> [];
-e_del_dir(doc) -> [];
e_del_dir(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
- RootDir = ?config(priv_dir, Config),
+ RootDir = proplists:get_value(priv_dir, Config),
Base = test_server:temp_name(filename:join(RootDir, "e_del_dir")),
io:format("Base: ~p", [Base]),
ok = ?FILE_MODULE:make_dir(Base),
@@ -2432,21 +2251,21 @@ e_del_dir(Config) when is_list(Config) ->
Afile = filename:join(Base, "a_directory"),
ok = ?FILE_MODULE:write_file(Afile, "hello\n"),
{error, E1} = expect({error, enotdir}, {error, enoent},
- ?FILE_MODULE:del_dir(
- filename:join(Afile, "another_directory"))),
+ ?FILE_MODULE:del_dir(
+ filename:join(Afile, "another_directory"))),
io:format("Result: ~p", [E1]),
%% Delete a non-empty directory.
{error, E2} = expect({error, enotempty}, {error, eexist}, {error, eacces},
- ?FILE_MODULE:del_dir(Base)),
+ ?FILE_MODULE:del_dir(Base)),
io:format("Result: ~p", [E2]),
%% Remove the current directory.
{error, E3} = expect({error, einval},
- {error, eperm}, % Linux and DUX
- {error, eacces},
- {error, ebusy},
- ?FILE_MODULE:del_dir(".")),
+ {error, eperm}, % Linux and DUX
+ {error, eacces},
+ {error, ebusy},
+ ?FILE_MODULE:del_dir(".")),
io:format("Result: ~p", [E3]),
%% No permission.
@@ -2461,7 +2280,6 @@ e_del_dir(Config) when is_list(Config) ->
?FILE_MODULE:write_file_info( Base, #file_info {mode=8#600})
end,
[] = flush(),
- test_server:timetrap_cancel(Dog),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2470,35 +2288,35 @@ e_del_dir(Config) when is_list(Config) ->
%% Trying reading and positioning from a compressed file.
read_compressed_cooked(Config) when is_list(Config) ->
- ?line Data = ?config(data_dir, Config),
- ?line Real = filename:join(Data, "realmen.html.gz"),
- ?line {ok, Fd} = ?FILE_MODULE:open(Real, [read,compressed]),
- ?line try_read_file_list(Fd).
+ Data = proplists:get_value(data_dir, Config),
+ Real = filename:join(Data, "realmen.html.gz"),
+ {ok, Fd} = ?FILE_MODULE:open(Real, [read,compressed]),
+ try_read_file_list(Fd).
read_compressed_cooked_binary(Config) when is_list(Config) ->
- ?line Data = ?config(data_dir, Config),
- ?line Real = filename:join(Data, "realmen.html.gz"),
- ?line {ok, Fd} = ?FILE_MODULE:open(Real, [read,compressed,binary]),
- ?line try_read_file_binary(Fd).
+ Data = proplists:get_value(data_dir, Config),
+ Real = filename:join(Data, "realmen.html.gz"),
+ {ok, Fd} = ?FILE_MODULE:open(Real, [read,compressed,binary]),
+ try_read_file_binary(Fd).
%% Trying reading and positioning from an uncompressed file,
%% but with the compressed flag given.
read_not_really_compressed(Config) when is_list(Config) ->
- ?line Data = ?config(data_dir, Config),
- ?line Priv = ?config(priv_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
+ Priv = proplists:get_value(priv_dir, Config),
%% The file realmen.html might have got CRs added (by WinZip).
%% Remove them, or the file positions will not be correct.
- ?line Real = filename:join(Data, "realmen.html"),
- ?line RealPriv = filename:join(Priv,
- atom_to_list(?MODULE)++"_realmen.html"),
- ?line {ok, RealDataBin} = ?FILE_MODULE:read_file(Real),
- ?line RealData = remove_crs(binary_to_list(RealDataBin), []),
- ?line ok = ?FILE_MODULE:write_file(RealPriv, RealData),
- ?line {ok, Fd} = ?FILE_MODULE:open(RealPriv, [read, compressed]),
- ?line try_read_file_list(Fd).
+ Real = filename:join(Data, "realmen.html"),
+ RealPriv = filename:join(Priv,
+ atom_to_list(?MODULE)++"_realmen.html"),
+ {ok, RealDataBin} = ?FILE_MODULE:read_file(Real),
+ RealData = remove_crs(binary_to_list(RealDataBin), []),
+ ok = ?FILE_MODULE:write_file(RealPriv, RealData),
+ {ok, Fd} = ?FILE_MODULE:open(RealPriv, [read, compressed]),
+ try_read_file_list(Fd).
remove_crs([$\r|Rest], Result) ->
remove_crs(Rest, Result);
@@ -2508,146 +2326,134 @@ remove_crs([], Result) ->
lists:reverse(Result).
try_read_file_list(Fd) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
-
%% Seek to the current position (nothing should happen).
- ?line {ok, 0} = ?FILE_MODULE:position(Fd, 0),
- ?line {ok, 0} = ?FILE_MODULE:position(Fd, {cur, 0}),
+ {ok, 0} = ?FILE_MODULE:position(Fd, 0),
+ {ok, 0} = ?FILE_MODULE:position(Fd, {cur, 0}),
%% Read a few lines from a compressed file.
- ?line ShouldBe = "<TITLE>Real Programmers Don't Use PASCAL</TITLE>\n",
- ?line ShouldBe = io:get_line(Fd, ''),
+ ShouldBe = "<TITLE>Real Programmers Don't Use PASCAL</TITLE>\n",
+ ShouldBe = io:get_line(Fd, ''),
%% Now seek forward.
- ?line {ok, 381} = ?FILE_MODULE:position(Fd, 381),
- ?line Back = "Back in the good old days -- the \"Golden Era\" " ++
+ {ok, 381} = ?FILE_MODULE:position(Fd, 381),
+ Back = "Back in the good old days -- the \"Golden Era\" " ++
"of computers, it was\n",
- ?line Back = io:get_line(Fd, ''),
+ Back = io:get_line(Fd, ''),
%% Try to search forward relative to the current position.
- ?line {ok, CurPos} = ?FILE_MODULE:position(Fd, {cur, 0}),
- ?line RealPos = 4273,
- ?line {ok, RealPos} = ?FILE_MODULE:position(Fd, {cur, RealPos-CurPos}),
- ?line RealProg = "<LI> Real Programmers aren't afraid to use GOTOs.\n",
- ?line RealProg = io:get_line(Fd, ''),
+ {ok, CurPos} = ?FILE_MODULE:position(Fd, {cur, 0}),
+ RealPos = 4273,
+ {ok, RealPos} = ?FILE_MODULE:position(Fd, {cur, RealPos-CurPos}),
+ RealProg = "<LI> Real Programmers aren't afraid to use GOTOs.\n",
+ RealProg = io:get_line(Fd, ''),
%% Seek backward.
- ?line AfterTitle = length("<TITLE>"),
- ?line {ok, AfterTitle} = ?FILE_MODULE:position(Fd, AfterTitle),
- ?line Title = "Real Programmers Don't Use PASCAL</TITLE>\n",
- ?line Title = io:get_line(Fd, ''),
+ AfterTitle = length("<TITLE>"),
+ {ok, AfterTitle} = ?FILE_MODULE:position(Fd, AfterTitle),
+ Title = "Real Programmers Don't Use PASCAL</TITLE>\n",
+ Title = io:get_line(Fd, ''),
%% Seek past the end of the file.
- ?line {ok, _} = ?FILE_MODULE:position(Fd, 25000),
+ {ok, _} = ?FILE_MODULE:position(Fd, 25000),
%% Done.
- ?line ?FILE_MODULE:close(Fd),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ ?FILE_MODULE:close(Fd),
+ [] = flush(),
ok.
try_read_file_binary(Fd) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
-
%% Seek to the current position (nothing should happen).
- ?line {ok, 0} = ?FILE_MODULE:position(Fd, 0),
- ?line {ok, 0} = ?FILE_MODULE:position(Fd, {cur, 0}),
+ {ok, 0} = ?FILE_MODULE:position(Fd, 0),
+ {ok, 0} = ?FILE_MODULE:position(Fd, {cur, 0}),
%% Read a few lines from a compressed file.
- ?line ShouldBe = <<"<TITLE>Real Programmers Don't Use PASCAL</TITLE>\n">>,
- ?line ShouldBe = io:get_line(Fd, ''),
+ ShouldBe = <<"<TITLE>Real Programmers Don't Use PASCAL</TITLE>\n">>,
+ ShouldBe = io:get_line(Fd, ''),
%% Now seek forward.
- ?line {ok, 381} = ?FILE_MODULE:position(Fd, 381),
- ?line Back = <<"Back in the good old days -- the \"Golden Era\" "
- "of computers, it was\n">>,
- ?line Back = io:get_line(Fd, ''),
+ {ok, 381} = ?FILE_MODULE:position(Fd, 381),
+ Back = <<"Back in the good old days -- the \"Golden Era\" "
+ "of computers, it was\n">>,
+ Back = io:get_line(Fd, ''),
%% Try to search forward relative to the current position.
- ?line {ok, CurPos} = ?FILE_MODULE:position(Fd, {cur, 0}),
- ?line RealPos = 4273,
- ?line {ok, RealPos} = ?FILE_MODULE:position(Fd, {cur, RealPos-CurPos}),
- ?line RealProg = <<"<LI> Real Programmers aren't afraid to use GOTOs.\n">>,
- ?line RealProg = io:get_line(Fd, ''),
+ {ok, CurPos} = ?FILE_MODULE:position(Fd, {cur, 0}),
+ RealPos = 4273,
+ {ok, RealPos} = ?FILE_MODULE:position(Fd, {cur, RealPos-CurPos}),
+ RealProg = <<"<LI> Real Programmers aren't afraid to use GOTOs.\n">>,
+ RealProg = io:get_line(Fd, ''),
%% Seek backward.
- ?line AfterTitle = length("<TITLE>"),
- ?line {ok, AfterTitle} = ?FILE_MODULE:position(Fd, AfterTitle),
- ?line Title = <<"Real Programmers Don't Use PASCAL</TITLE>\n">>,
- ?line Title = io:get_line(Fd, ''),
+ AfterTitle = length("<TITLE>"),
+ {ok, AfterTitle} = ?FILE_MODULE:position(Fd, AfterTitle),
+ Title = <<"Real Programmers Don't Use PASCAL</TITLE>\n">>,
+ Title = io:get_line(Fd, ''),
%% Done.
- ?line ?FILE_MODULE:close(Fd),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ ?FILE_MODULE:close(Fd),
+ [] = flush(),
ok.
read_cooked_tar_problem(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
+ Data = proplists:get_value(data_dir, Config),
+ ProblemFile = filename:join(Data, "cooked_tar_problem.tar.gz"),
+ {ok,Fd} = ?FILE_MODULE:open(ProblemFile, [read,compressed,binary]),
- ?line Data = ?config(data_dir, Config),
- ?line ProblemFile = filename:join(Data, "cooked_tar_problem.tar.gz"),
- ?line {ok,Fd} = ?FILE_MODULE:open(ProblemFile, [read,compressed,binary]),
+ {ok,34304} = file:position(Fd, 34304),
+ {ok,Bin} = file:read(Fd, 512),
+ 512 = byte_size(Bin),
- ?line {ok,34304} = file:position(Fd, 34304),
- ?line {ok,Bin} = file:read(Fd, 512),
- ?line 512 = byte_size(Bin),
-
- ?line {ok,34304+512+1024} = file:position(Fd, {cur,1024}),
-
- ?line ok = file:close(Fd),
+ {ok,34304+512+1024} = file:position(Fd, {cur,1024}),
+
+ ok = file:close(Fd),
- ?line test_server:timetrap_cancel(Dog),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-write_compressed(suite) -> [];
-write_compressed(doc) -> [];
write_compressed(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Priv = ?config(priv_dir, Config),
- ?line MyFile = filename:join(Priv,
- atom_to_list(?MODULE)++"_test.gz"),
+ Priv = proplists:get_value(priv_dir, Config),
+ MyFile = filename:join(Priv,
+ atom_to_list(?MODULE)++"_test.gz"),
%% Write a file.
- ?line {ok, Fd} = ?FILE_MODULE:open(MyFile, [write, compressed]),
- ?line {ok, 0} = ?FILE_MODULE:position(Fd, 0),
- ?line Prefix = "hello\n",
- ?line End = "end\n",
- ?line ok = io:put_chars(Fd, Prefix),
- ?line {ok, 143} = ?FILE_MODULE:position(Fd, 143),
- ?line ok = io:put_chars(Fd, End),
- ?line ok = ?FILE_MODULE:close(Fd),
+ {ok, Fd} = ?FILE_MODULE:open(MyFile, [write, compressed]),
+ {ok, 0} = ?FILE_MODULE:position(Fd, 0),
+ Prefix = "hello\n",
+ End = "end\n",
+ ok = io:put_chars(Fd, Prefix),
+ {ok, 143} = ?FILE_MODULE:position(Fd, 143),
+ ok = io:put_chars(Fd, End),
+ ok = ?FILE_MODULE:close(Fd),
%% Read the file and verify the contents.
- ?line {ok, Fd1} = ?FILE_MODULE:open(MyFile, [read, compressed]),
- ?line Prefix = io:get_line(Fd1, ''),
- ?line Second = lists:duplicate(143-length(Prefix), 0) ++ End,
- ?line Second = io:get_line(Fd1, ''),
- ?line ok = ?FILE_MODULE:close(Fd1),
+ {ok, Fd1} = ?FILE_MODULE:open(MyFile, [read, compressed]),
+ Prefix = io:get_line(Fd1, ''),
+ Second = lists:duplicate(143-length(Prefix), 0) ++ End,
+ Second = io:get_line(Fd1, ''),
+ ok = ?FILE_MODULE:close(Fd1),
%% Verify successful compression by uncompressing the file
%% using zlib:gunzip/1.
- ?line {ok,Contents} = file:read_file(MyFile),
- ?line <<"hello\n",0:137/unit:8,"end\n">> = zlib:gunzip(Contents),
+ {ok,Contents} = file:read_file(MyFile),
+ <<"hello\n",0:137/unit:8,"end\n">> = zlib:gunzip(Contents),
%% Ensure that the file is compressed.
@@ -2656,99 +2462,92 @@ write_compressed(Config) when is_list(Config) ->
{ok, #file_info{size=Size}} when Size < TotalSize ->
ok;
{ok, #file_info{size=Size}} when Size == TotalSize ->
- test_server:fail(file_not_compressed)
+ ct:fail(file_not_compressed)
end,
%% Write again to ensure that the file is truncated.
- ?line {ok, Fd2} = ?FILE_MODULE:open(MyFile, [write, compressed]),
- ?line NewString = "aaaaaaaaaaa",
- ?line ok = io:put_chars(Fd2, NewString),
- ?line ok = ?FILE_MODULE:close(Fd2),
- ?line {ok, Fd3} = ?FILE_MODULE:open(MyFile, [read, compressed]),
- ?line {ok, NewString} = ?FILE_MODULE:read(Fd3, 1024),
- ?line ok = ?FILE_MODULE:close(Fd3),
+ {ok, Fd2} = ?FILE_MODULE:open(MyFile, [write, compressed]),
+ NewString = "aaaaaaaaaaa",
+ ok = io:put_chars(Fd2, NewString),
+ ok = ?FILE_MODULE:close(Fd2),
+ {ok, Fd3} = ?FILE_MODULE:open(MyFile, [read, compressed]),
+ {ok, NewString} = ?FILE_MODULE:read(Fd3, 1024),
+ ok = ?FILE_MODULE:close(Fd3),
%% Done.
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
catenated_gzips(Config) when is_list(Config) ->
- ?line Priv = ?config(priv_dir, Config),
- ?line MyFile = filename:join(Priv, ?MODULE_STRING++"_test.gz"),
+ Priv = proplists:get_value(priv_dir, Config),
+ MyFile = filename:join(Priv, ?MODULE_STRING++"_test.gz"),
First = "Hello, all good men going to search parties. ",
Second = "Now I really need your help.",
All = iolist_to_binary([First|Second]),
- ?line Cat = [zlib:gzip(First),zlib:gzip(Second)],
-
- ?line ok = file:write_file(MyFile, Cat),
+ Cat = [zlib:gzip(First),zlib:gzip(Second)],
+
+ ok = file:write_file(MyFile, Cat),
- ?line {ok,Fd} = file:open(MyFile, [read,compressed,binary]),
- ?line {ok,All} = file:read(Fd, 100000),
- ?line ok = file:close(Fd),
+ {ok,Fd} = file:open(MyFile, [read,compressed,binary]),
+ {ok,All} = file:read(Fd, 100000),
+ ok = file:close(Fd),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-compress_errors(suite) -> [];
-compress_errors(doc) -> [];
compress_errors(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line DataDir =
+ DataDir =
filename:dirname(
- filename:join(?config(data_dir, Config), "x")),
- ?line DataDirSlash = DataDir++"/",
- ?line {error, enoent} = ?FILE_MODULE:open("non_existing__",
- [compressed, read]),
- ?line {error, einval} = ?FILE_MODULE:open("non_existing__",
- [compressed, read, write]),
- ?line {error, einval} = ?FILE_MODULE:open("non_existing__",
- [compressed, read, append]),
- ?line {error, einval} = ?FILE_MODULE:open("non_existing__",
- [compressed, write, append]),
- ?line {error, E1} = ?FILE_MODULE:open(DataDir, [compressed, read]),
- ?line {error, E2} = ?FILE_MODULE:open(DataDirSlash, [compressed, read]),
- ?line {error, E3} = ?FILE_MODULE:open(DataDir, [compressed, write]),
- ?line {error, E4} = ?FILE_MODULE:open(DataDirSlash, [compressed, write]),
- ?line {eisdir,eisdir,eisdir,eisdir} = {E1,E2,E3,E4},
+ filename:join(proplists:get_value(data_dir, Config), "x")),
+ DataDirSlash = DataDir++"/",
+ {error, enoent} = ?FILE_MODULE:open("non_existing__",
+ [compressed, read]),
+ {error, einval} = ?FILE_MODULE:open("non_existing__",
+ [compressed, read, write]),
+ {error, einval} = ?FILE_MODULE:open("non_existing__",
+ [compressed, read, append]),
+ {error, einval} = ?FILE_MODULE:open("non_existing__",
+ [compressed, write, append]),
+ {error, E1} = ?FILE_MODULE:open(DataDir, [compressed, read]),
+ {error, E2} = ?FILE_MODULE:open(DataDirSlash, [compressed, read]),
+ {error, E3} = ?FILE_MODULE:open(DataDir, [compressed, write]),
+ {error, E4} = ?FILE_MODULE:open(DataDirSlash, [compressed, write]),
+ {eisdir,eisdir,eisdir,eisdir} = {E1,E2,E3,E4},
%% Read a corrupted .gz file.
- ?line Corrupted = filename:join(DataDir, "corrupted.gz"),
- ?line {ok, Fd} = ?FILE_MODULE:open(Corrupted, [read, compressed]),
- ?line {error, eio} = ?FILE_MODULE:read(Fd, 100),
- ?line ?FILE_MODULE:close(Fd),
+ Corrupted = filename:join(DataDir, "corrupted.gz"),
+ {ok, Fd} = ?FILE_MODULE:open(Corrupted, [read, compressed]),
+ {error, eio} = ?FILE_MODULE:read(Fd, 100),
+ ?FILE_MODULE:close(Fd),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-compress_async_crash(suite) -> [];
-compress_async_crash(doc) -> [];
compress_async_crash(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line Path = filename:join(DataDir, "test.gz"),
+ DataDir = proplists:get_value(data_dir, Config),
+ Path = filename:join(DataDir, "test.gz"),
ExpectedData = <<"qwerty">>,
- ?line _ = ?FILE_MODULE:delete(Path),
- ?line {ok, Fd} = ?FILE_MODULE:open(Path, [write, binary, compressed]),
- ?line ok = ?FILE_MODULE:write(Fd, ExpectedData),
- ?line ok = ?FILE_MODULE:close(Fd),
+ _ = ?FILE_MODULE:delete(Path),
+ {ok, Fd} = ?FILE_MODULE:open(Path, [write, binary, compressed]),
+ ok = ?FILE_MODULE:write(Fd, ExpectedData),
+ ok = ?FILE_MODULE:close(Fd),
- % Test that when using async thread pool, the emulator doesn't crash
- % when the efile port driver is stopped while a compressed file operation
- % is in progress (being carried by an async thread).
- ?line ok = compress_async_crash_loop(10000, Path, ExpectedData),
- ?line ok = ?FILE_MODULE:delete(Path),
+ %% Test that when using async thread pool, the emulator doesn't crash
+ %% when the efile port driver is stopped while a compressed file operation
+ %% is in progress (being carried by an async thread).
+ ok = compress_async_crash_loop(10000, Path, ExpectedData),
+ ok = ?FILE_MODULE:delete(Path),
ok.
compress_async_crash_loop(0, _Path, _ExpectedData) ->
@@ -2756,35 +2555,35 @@ compress_async_crash_loop(0, _Path, _ExpectedData) ->
compress_async_crash_loop(N, Path, ExpectedData) ->
Parent = self(),
{Pid, Ref} = spawn_monitor(
- fun() ->
- ?line {ok, Fd} = ?FILE_MODULE:open(
- Path, [read, compressed, raw, binary]),
- Len = byte_size(ExpectedData),
- Parent ! {self(), continue},
- ?line {ok, ExpectedData} = ?FILE_MODULE:read(Fd, Len),
- ?line ok = ?FILE_MODULE:close(Fd),
- receive foobar -> ok end
- end),
+ fun() ->
+ {ok, Fd} = ?FILE_MODULE:open(
+ Path, [read, compressed, raw, binary]),
+ Len = byte_size(ExpectedData),
+ Parent ! {self(), continue},
+ {ok, ExpectedData} = ?FILE_MODULE:read(Fd, Len),
+ ok = ?FILE_MODULE:close(Fd),
+ receive foobar -> ok end
+ end),
receive
{Pid, continue} ->
exit(Pid, shutdown),
receive
{'DOWN', Ref, _, _, Reason} ->
- ?line shutdown = Reason
+ shutdown = Reason
end;
{'DOWN', Ref, _, _, Reason2} ->
- test_server:fail({worker_exited, Reason2})
+ ct:fail({worker_exited, Reason2})
after 60000 ->
exit(Pid, shutdown),
erlang:demonitor(Ref, [flush]),
- test_server:fail(worker_timeout)
+ ct:fail(worker_timeout)
end,
compress_async_crash_loop(N - 1, Path, ExpectedData).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
unicode(Config) when is_list(Config) ->
- Dir = ?config(priv_dir, Config),
+ Dir = proplists:get_value(priv_dir, Config),
Name = filename:join(Dir, "data-utf8.txt"),
Txt = lists:seq(128, 255),
D = unicode:characters_to_binary(Txt, latin1, latin1),
@@ -2817,53 +2616,46 @@ unicode(Config) when is_list(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-altname(doc) ->
- "Test the file:altname/1 function";
-altname(suite) ->
- [];
+%% Test the file:altname/1 function.
altname(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line NewDir = filename:join(RootDir,
- "long alternative path name with spaces"),
- ?line ok = ?FILE_MODULE:make_dir(NewDir),
- ?line Name = filename:join(NewDir, "a_file_with_long_name"),
- ?line ShortName = filename:join(NewDir, "short"),
- ?line NonexName = filename:join(NewDir, "nonexistent"),
- ?line ok = ?FILE_MODULE:write_file(Name, "some contents\n"),
- ?line ok = ?FILE_MODULE:write_file(ShortName, "some contents\n"),
- ?line Result =
+ RootDir = proplists:get_value(priv_dir, Config),
+ NewDir = filename:join(RootDir,
+ "long alternative path name with spaces"),
+ ok = ?FILE_MODULE:make_dir(NewDir),
+ Name = filename:join(NewDir, "a_file_with_long_name"),
+ ShortName = filename:join(NewDir, "short"),
+ NonexName = filename:join(NewDir, "nonexistent"),
+ ok = ?FILE_MODULE:write_file(Name, "some contents\n"),
+ ok = ?FILE_MODULE:write_file(ShortName, "some contents\n"),
+ Result =
case ?FILE_MODULE:altname(NewDir) of
{error, enotsup} ->
{skipped, "Altname not supported on this platform"};
{ok, "LONGAL~1"} ->
- ?line {ok, "A_FILE~1"} = ?FILE_MODULE:altname(Name),
- ?line {ok, "C:/"} = ?FILE_MODULE:altname("C:/"),
- ?line {ok, "C:\\"} = ?FILE_MODULE:altname("C:\\"),
- ?line {error,enoent} = ?FILE_MODULE:altname(NonexName),
- ?line {ok, "short"} = ?FILE_MODULE:altname(ShortName),
+ {ok, "A_FILE~1"} = ?FILE_MODULE:altname(Name),
+ {ok, "C:/"} = ?FILE_MODULE:altname("C:/"),
+ {ok, "C:\\"} = ?FILE_MODULE:altname("C:\\"),
+ {error,enoent} = ?FILE_MODULE:altname(NonexName),
+ {ok, "short"} = ?FILE_MODULE:altname(ShortName),
ok
end,
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ [] = flush(),
Result.
-make_link(doc) -> "Test creating a hard link.";
-make_link(suite) -> [];
+%% Test creating a hard link.
make_link(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_make_link"),
- ?line ok = ?FILE_MODULE:make_dir(NewDir),
-
- ?line Name = filename:join(NewDir, "a_file"),
- ?line ok = ?FILE_MODULE:write_file(Name, "some contents\n"),
-
- ?line Alias = filename:join(NewDir, "an_alias"),
- ?line Result =
+ RootDir = proplists:get_value(priv_dir, Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_make_link"),
+ ok = ?FILE_MODULE:make_dir(NewDir),
+
+ Name = filename:join(NewDir, "a_file"),
+ ok = ?FILE_MODULE:write_file(Name, "some contents\n"),
+
+ Alias = filename:join(NewDir, "an_alias"),
+ Result =
case ?FILE_MODULE:make_link(Name, Alias) of
{error, enotsup} ->
{skipped, "Links not supported on this platform"};
@@ -2873,53 +2665,45 @@ make_link(Config) when is_list(Config) ->
%% which should in behave exactly as
%% ?FILE_MODULE:read_file_info/1
%% since they are not used on symbolic links.
-
- ?line {ok, Info} = ?FILE_MODULE:read_link_info(Name),
+
+ {ok, Info} = ?FILE_MODULE:read_link_info(Name),
{ok,Info} = ?FILE_MODULE:read_link_info(Name, [raw]),
- ?line {ok, Info} = ?FILE_MODULE:read_link_info(Alias),
+ {ok, Info} = ?FILE_MODULE:read_link_info(Alias),
{ok,Info} = ?FILE_MODULE:read_link_info(Alias, [raw]),
- ?line #file_info{links = 2, type = regular} = Info,
- ?line {error, eexist} =
+ #file_info{links = 2, type = regular} = Info,
+ {error, eexist} =
?FILE_MODULE:make_link(Name, Alias),
ok
end,
-
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+
+ [] = flush(),
Result.
-read_link_info_for_non_link(doc) ->
- "Test that reading link info for an ordinary file or directory works "
- "(on all platforms).";
-read_link_info_for_non_link(suite) -> [];
+%% Test that reading link info for an ordinary file or directory works
+%% (on all platforms).
read_link_info_for_non_link(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
-
- ?line {ok, #file_info{type=directory}} =
+ {ok, #file_info{type=directory}} =
?FILE_MODULE:read_link_info("."),
{ok, #file_info{type=directory}} = ?FILE_MODULE:read_link_info(".", [raw]),
-
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+
+ [] = flush(),
ok.
-symlinks(doc) -> "Test operations on symbolic links (for Unix).";
-symlinks(suite) -> [];
+%% Test operations on symbolic links (for Unix).
symlinks(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line {error, _} = ?FILE_MODULE:read_link(lists:duplicate(10000,$a)),
+ {error, _} = ?FILE_MODULE:read_link(lists:duplicate(10000,$a)),
{error, _} = ?FILE_MODULE:read_link_all(lists:duplicate(10000,$a)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_symlinks"),
- ?line ok = ?FILE_MODULE:make_dir(NewDir),
-
- ?line Name = filename:join(NewDir, "a_plain_file"),
- ?line ok = ?FILE_MODULE:write_file(Name, "some stupid content\n"),
-
- ?line Alias = filename:join(NewDir, "a_symlink_alias"),
- ?line Result =
+ RootDir = proplists:get_value(priv_dir, Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_symlinks"),
+ ok = ?FILE_MODULE:make_dir(NewDir),
+
+ Name = filename:join(NewDir, "a_plain_file"),
+ ok = ?FILE_MODULE:write_file(Name, "some stupid content\n"),
+
+ Alias = filename:join(NewDir, "a_symlink_alias"),
+ Result =
case ?FILE_MODULE:make_symlink(Name, Alias) of
{error, enotsup} ->
{skipped, "Links not supported on this platform"};
@@ -2927,41 +2711,37 @@ symlinks(Config) when is_list(Config) ->
{win32,_} = os:type(),
{skipped, "Windows user not privileged to create symlinks"};
ok ->
- ?line {ok, Info1} = ?FILE_MODULE:read_file_info(Name),
+ {ok, Info1} = ?FILE_MODULE:read_file_info(Name),
{ok,Info1} = ?FILE_MODULE:read_file_info(Name, [raw]),
- ?line {ok, Info1} = ?FILE_MODULE:read_file_info(Alias),
+ {ok, Info1} = ?FILE_MODULE:read_file_info(Alias),
{ok,Info1} = ?FILE_MODULE:read_file_info(Alias, [raw]),
- ?line {ok, Info1} = ?FILE_MODULE:read_link_info(Name),
+ {ok, Info1} = ?FILE_MODULE:read_link_info(Name),
{ok,Info1} = ?FILE_MODULE:read_link_info(Name, [raw]),
- ?line #file_info{links = 1, type = regular} = Info1,
-
- ?line {ok, Info2} = ?FILE_MODULE:read_link_info(Alias),
+ #file_info{links = 1, type = regular} = Info1,
+
+ {ok, Info2} = ?FILE_MODULE:read_link_info(Alias),
{ok,Info2} = ?FILE_MODULE:read_link_info(Alias, [raw]),
- ?line #file_info{links=1, type=symlink} = Info2,
- ?line {ok, Name} = ?FILE_MODULE:read_link(Alias),
+ #file_info{links=1, type=symlink} = Info2,
+ {ok, Name} = ?FILE_MODULE:read_link(Alias),
{ok, Name} = ?FILE_MODULE:read_link_all(Alias),
%% If all is good, delete dir again (avoid hanging dir on windows)
rm_rf(?FILE_MODULE,NewDir),
ok
- end,
-
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ end,
+
+ [] = flush(),
Result.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-copy(doc) -> [];
-copy(suite) -> [];
copy(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line RootDir = ?config(priv_dir, Config),
+ RootDir = proplists:get_value(priv_dir, Config),
%% Create a text file.
- ?line Name1 = filename:join(RootDir, atom_to_list(?MODULE)++"_copy_1.txt"),
- ?line Line = "The quick brown fox jumps over a lazy dog. 0123456789\n",
- ?line Len = length(Line),
- ?line {ok, Handle1} = ?FILE_MODULE:open(Name1, [write]),
- ?line {_, Size1} =
+ Name1 = filename:join(RootDir, atom_to_list(?MODULE)++"_copy_1.txt"),
+ Line = "The quick brown fox jumps over a lazy dog. 0123456789\n",
+ Len = length(Line),
+ {ok, Handle1} = ?FILE_MODULE:open(Name1, [write]),
+ {_, Size1} =
iterate({0, 0},
done,
fun({_, S}) when S >= 128*1024 ->
@@ -2971,45 +2751,44 @@ copy(Config) when is_list(Config) ->
ok = ?FILE_MODULE:write(Handle1, [H, " ", Line]),
{N + 1, S + length(H) + 1 + Len}
end),
- ?line ?FILE_MODULE:close(Handle1),
+ ?FILE_MODULE:close(Handle1),
%% Make a copy
- ?line Name2 = filename:join(RootDir, atom_to_list(?MODULE)++"_copy_2.txt"),
- ?line {ok, Size1} = ?FILE_MODULE:copy(Name1, Name2),
+ Name2 = filename:join(RootDir, atom_to_list(?MODULE)++"_copy_2.txt"),
+ {ok, Size1} = ?FILE_MODULE:copy(Name1, Name2),
%% Concatenate 1
- ?line Name3 = filename:join(RootDir, atom_to_list(?MODULE)++"_copy_3.txt"),
- ?line {ok, Handle3} = ?FILE_MODULE:open(Name3, [raw, write, binary]),
- ?line {ok, Size1} = ?FILE_MODULE:copy(Name1, Handle3),
- ?line {ok, Handle2} = ?FILE_MODULE:open(Name2, [read, binary]),
- ?line {ok, Size1} = ?FILE_MODULE:copy(Handle2, Handle3),
- ?line ok = ?FILE_MODULE:close(Handle3),
- ?line ok = ?FILE_MODULE:close(Handle2),
+ Name3 = filename:join(RootDir, atom_to_list(?MODULE)++"_copy_3.txt"),
+ {ok, Handle3} = ?FILE_MODULE:open(Name3, [raw, write, binary]),
+ {ok, Size1} = ?FILE_MODULE:copy(Name1, Handle3),
+ {ok, Handle2} = ?FILE_MODULE:open(Name2, [read, binary]),
+ {ok, Size1} = ?FILE_MODULE:copy(Handle2, Handle3),
+ ok = ?FILE_MODULE:close(Handle3),
+ ok = ?FILE_MODULE:close(Handle2),
%% Concatenate 2
- ?line Name4 = filename:join(RootDir, atom_to_list(?MODULE)++"_copy_4.txt"),
- ?line {ok, Handle4} = ?FILE_MODULE:open(Name4, [write, binary]),
- ?line {ok, Size1} = ?FILE_MODULE:copy(Name1, Handle4),
- ?line {ok, Handle5} = ?FILE_MODULE:open(Name2, [raw, read, binary]),
- ?line {ok, Size1} = ?FILE_MODULE:copy(Handle5, Handle4),
- ?line ok = ?FILE_MODULE:close(Handle5),
- ?line ok = ?FILE_MODULE:close(Handle4),
+ Name4 = filename:join(RootDir, atom_to_list(?MODULE)++"_copy_4.txt"),
+ {ok, Handle4} = ?FILE_MODULE:open(Name4, [write, binary]),
+ {ok, Size1} = ?FILE_MODULE:copy(Name1, Handle4),
+ {ok, Handle5} = ?FILE_MODULE:open(Name2, [raw, read, binary]),
+ {ok, Size1} = ?FILE_MODULE:copy(Handle5, Handle4),
+ ok = ?FILE_MODULE:close(Handle5),
+ ok = ?FILE_MODULE:close(Handle4),
%% %% Just for test of the test
- %% ?line {ok, Handle2q} = ?FILE_MODULE:open(Name2, [write, append]),
- %% ?line ok = ?FILE_MODULE:write(Handle2q, "q"),
- %% ?line ok = ?FILE_MODULE:close(Handle2q),
+ %% {ok, Handle2q} = ?FILE_MODULE:open(Name2, [write, append]),
+ %% ok = ?FILE_MODULE:write(Handle2q, "q"),
+ %% ok = ?FILE_MODULE:close(Handle2q),
%% Compare the files
- ?line {ok, Handle1a} = ?FILE_MODULE:open(Name1, [raw, read]),
- ?line {ok, Handle2a} = ?FILE_MODULE:open(Name2, [raw, read]),
- ?line true = stream_cmp(fd_stream_factory([Handle1a]),
- fd_stream_factory([Handle2a])),
- ?line {ok, 0} = ?FILE_MODULE:position(Handle1a, 0),
- ?line {ok, 0} = ?FILE_MODULE:position(Handle2a, 0),
- ?line {ok, Handle3a} = ?FILE_MODULE:open(Name3, [raw, read]),
- ?line true = stream_cmp(fd_stream_factory([Handle1a, Handle2a]),
- fd_stream_factory([Handle2a])),
- ?line ok = ?FILE_MODULE:close(Handle1a),
- ?line ok = ?FILE_MODULE:close(Handle2a),
- ?line ok = ?FILE_MODULE:close(Handle3a),
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
+ {ok, Handle1a} = ?FILE_MODULE:open(Name1, [raw, read]),
+ {ok, Handle2a} = ?FILE_MODULE:open(Name2, [raw, read]),
+ true = stream_cmp(fd_stream_factory([Handle1a]),
+ fd_stream_factory([Handle2a])),
+ {ok, 0} = ?FILE_MODULE:position(Handle1a, 0),
+ {ok, 0} = ?FILE_MODULE:position(Handle2a, 0),
+ {ok, Handle3a} = ?FILE_MODULE:open(Name3, [raw, read]),
+ true = stream_cmp(fd_stream_factory([Handle1a, Handle2a]),
+ fd_stream_factory([Handle2a])),
+ ok = ?FILE_MODULE:close(Handle1a),
+ ok = ?FILE_MODULE:close(Handle2a),
+ ok = ?FILE_MODULE:close(Handle3a),
+ [] = flush(),
ok.
@@ -3030,7 +2809,7 @@ fd_stream_factory([Fd | T] = L) ->
end
end.
-
+
stream_cmp(F1, F2) when is_function(F1), is_function(F2) ->
stream_cmp(F1(), F2());
@@ -3055,80 +2834,75 @@ stream_cmp([H | T1], [H | T2]) ->
%% Test the get_cwd(), open(), and copy() file server calls.
new_slave(_RootDir, Cwd) ->
- ?line L = "qwertyuiopasdfghjklzxcvbnm",
- ?line N = length(L),
- ?line {ok, Cwd} = ?FILE_MODULE:get_cwd(),
- ?line {error, enotsup} = ?FILE_MODULE:get_cwd("C:"), % Unix only testcase
- ?line {ok, FD1} = ?FILE_MODULE:open("file1.txt", write),
- ?line ok = ?FILE_MODULE:close(FD1),
- ?line {ok, FD2} = ?FILE_MODULE:open("file1.txt",
- [write, append,
- binary, compressed,
- delayed_write,
- {delayed_write, 0, 0},
- read_ahead,
- {read_ahead, 0}]),
- ?line ok = ?FILE_MODULE:write(FD2, L),
- ?line ok = ?FILE_MODULE:close(FD2),
- ?line {ok, N2} = ?FILE_MODULE:copy("file1.txt", "file2.txt"),
- ?line io:format("Size ~p, compressed ~p.~n", [N, N2]),
- ?line {ok, FD3} = ?FILE_MODULE:open("file2.txt",
- [binary, compressed]),
+ L = "qwertyuiopasdfghjklzxcvbnm",
+ N = length(L),
+ {ok, Cwd} = ?FILE_MODULE:get_cwd(),
+ {error, enotsup} = ?FILE_MODULE:get_cwd("C:"), % Unix only testcase
+ {ok, FD1} = ?FILE_MODULE:open("file1.txt", write),
+ ok = ?FILE_MODULE:close(FD1),
+ {ok, FD2} = ?FILE_MODULE:open("file1.txt",
+ [write, append,
+ binary, compressed,
+ delayed_write,
+ {delayed_write, 0, 0},
+ read_ahead,
+ {read_ahead, 0}]),
+ ok = ?FILE_MODULE:write(FD2, L),
+ ok = ?FILE_MODULE:close(FD2),
+ {ok, N2} = ?FILE_MODULE:copy("file1.txt", "file2.txt"),
+ io:format("Size ~p, compressed ~p.~n", [N, N2]),
+ {ok, FD3} = ?FILE_MODULE:open("file2.txt",
+ [binary, compressed]),
%% The file_io_server will translate the binary into a list
- ?line {ok, L} = ?FILE_MODULE:read(FD3, N+1),
- ?line ok = ?FILE_MODULE:close(FD3),
+ {ok, L} = ?FILE_MODULE:read(FD3, N+1),
+ ok = ?FILE_MODULE:close(FD3),
%%
- ?line ok = ?FILE_MODULE:delete("file1.txt"),
- ?line ok = ?FILE_MODULE:delete("file2.txt"),
- ?line [] = flush(),
+ ok = ?FILE_MODULE:delete("file1.txt"),
+ ok = ?FILE_MODULE:delete("file2.txt"),
+ [] = flush(),
ok.
%% Test the get_cwd() and open() file server calls.
old_slave(_RootDir, Cwd) ->
- ?line L = "qwertyuiopasdfghjklzxcvbnm",
- ?line N = length(L),
- ?line {ok, Cwd} = ?FILE_MODULE:get_cwd(),
- ?line {error, enotsup} = ?FILE_MODULE:get_cwd("C:"), % Unix only testcase
- ?line {ok, FD1} = ?FILE_MODULE:open("file1.txt", write),
- ?line ok = ?FILE_MODULE:close(FD1),
- ?line {ok, FD2} = ?FILE_MODULE:open("file1.txt",
- [write, binary, compressed]),
- ?line ok = ?FILE_MODULE:write(FD2, L),
- ?line ok = ?FILE_MODULE:close(FD2),
- ?line {ok, FD3} = ?FILE_MODULE:open("file1.txt", [write, append]),
- ?line ok = ?FILE_MODULE:close(FD3),
- ?line {ok, FD4} = ?FILE_MODULE:open("file1.txt",
- [binary, compressed]),
+ L = "qwertyuiopasdfghjklzxcvbnm",
+ N = length(L),
+ {ok, Cwd} = ?FILE_MODULE:get_cwd(),
+ {error, enotsup} = ?FILE_MODULE:get_cwd("C:"), % Unix only testcase
+ {ok, FD1} = ?FILE_MODULE:open("file1.txt", write),
+ ok = ?FILE_MODULE:close(FD1),
+ {ok, FD2} = ?FILE_MODULE:open("file1.txt",
+ [write, binary, compressed]),
+ ok = ?FILE_MODULE:write(FD2, L),
+ ok = ?FILE_MODULE:close(FD2),
+ {ok, FD3} = ?FILE_MODULE:open("file1.txt", [write, append]),
+ ok = ?FILE_MODULE:close(FD3),
+ {ok, FD4} = ?FILE_MODULE:open("file1.txt",
+ [binary, compressed]),
%% The file_io_server will translate the binary into a list
- ?line {ok, L} = ?FILE_MODULE:read(FD4, N+1),
- ?line ok = ?FILE_MODULE:close(FD4),
+ {ok, L} = ?FILE_MODULE:read(FD4, N+1),
+ ok = ?FILE_MODULE:close(FD4),
%%
- ?line ok = ?FILE_MODULE:delete("file1.txt"),
- ?line [] = flush(),
+ ok = ?FILE_MODULE:delete("file1.txt"),
+ [] = flush(),
ok.
run_test(Test, Args) ->
- ?line case (catch apply(?MODULE, Test, Args)) of
- {'EXIT', _} = Exit ->
- {done, Exit, get(test_server_loc)};
- Result ->
- {done, Result}
- end.
+ case (catch apply(?MODULE, Test, Args)) of
+ {'EXIT', _} = Exit ->
+ {done, Exit, get(test_server_loc)};
+ Result ->
+ {done, Result}
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-delayed_write(suite) ->
- [];
-delayed_write(doc) ->
- ["Tests the file open option {delayed_write, Size, Delay}"];
+%% Tests the file open option {delayed_write, Size, Delay}.
delayed_write(Config) when is_list(Config) ->
- Dog = ?t:timetrap(?t:seconds(20)),
-
- RootDir = ?config(priv_dir, Config),
+ RootDir = proplists:get_value(priv_dir, Config),
File = filename:join(RootDir,
- atom_to_list(?MODULE)++"_delayed_write.txt"),
+ atom_to_list(?MODULE)++"_delayed_write.txt"),
Data1 = "asdfghjkl",
Data2 = "qwertyuio",
Data3 = "zxcvbnm,.",
@@ -3143,18 +2917,18 @@ delayed_write(Config) when is_list(Config) ->
{ok, Fd1} =
?FILE_MODULE:open(File, [write, {delayed_write, Size+1, 2000}]),
ok = ?FILE_MODULE:write(Fd1, Data1),
- ?t:sleep(1000), % Just in case the file system is slow
+ timer:sleep(1000), % Just in case the file system is slow
{ok, Fd2} = ?FILE_MODULE:open(File, [read]),
eof = ?FILE_MODULE:read(Fd2, 1),
ok = ?FILE_MODULE:write(Fd1, Data1), % Data flush on size
- ?t:sleep(1000), % Just in case the file system is slow
+ timer:sleep(1000), % Just in case the file system is slow
{ok, Data1Data1} = ?FILE_MODULE:pread(Fd2, bof, 2*Size+1),
ok = ?FILE_MODULE:write(Fd1, Data1),
- ?t:sleep(3000), % Wait until data flush on timeout
+ timer:sleep(3000), % Wait until data flush on timeout
{ok, Data1Data1Data1} = ?FILE_MODULE:pread(Fd2, bof, 3*Size+1),
ok = ?FILE_MODULE:write(Fd1, Data1),
ok = ?FILE_MODULE:close(Fd1), % Data flush on close
- ?t:sleep(1000), % Just in case the file system is slow
+ timer:sleep(1000), % Just in case the file system is slow
{ok, Data1Data1Data1Data1} = ?FILE_MODULE:pread(Fd2, bof, 4*Size+1),
ok = ?FILE_MODULE:close(Fd2),
%%
@@ -3162,33 +2936,33 @@ delayed_write(Config) when is_list(Config) ->
%% raw file, default parameters.
Parent = self(),
Fun = fun() ->
- Child = self(),
- Test =
- fun () ->
- {ok, Fd} = ?FILE_MODULE:open(File,
- [raw, write, delayed_write]),
- ok = ?FILE_MODULE:write(Fd, Data1),
- Parent ! {Child, wrote},
- receive
- {Parent, continue, Reason} ->
- {ok, Reason}
- end
- end,
- case (catch Test()) of
- {ok, Reason} -> exit(Reason);
- Unknown ->
- exit({Unknown, get(test_server_loc)})
- end
- end,
+ Child = self(),
+ Test =
+ fun () ->
+ {ok, Fd} = ?FILE_MODULE:open(File,
+ [raw, write, delayed_write]),
+ ok = ?FILE_MODULE:write(Fd, Data1),
+ Parent ! {Child, wrote},
+ receive
+ {Parent, continue, Reason} ->
+ {ok, Reason}
+ end
+ end,
+ case (catch Test()) of
+ {ok, Reason} -> exit(Reason);
+ Unknown ->
+ exit({Unknown, get(test_server_loc)})
+ end
+ end,
Child1 = spawn(Fun),
Mref1 = erlang:monitor(process, Child1),
receive
{Child1, wrote} ->
ok;
{'DOWN', Mref1, _, _, _} = Down1a ->
- ?t:fail(Down1a)
+ ct:fail(Down1a)
end,
- ?t:sleep(1000), % Just in case the file system is slow
+ timer:sleep(1000), % Just in case the file system is slow
{ok, Fd3} = ?FILE_MODULE:open(File, [read]),
eof = ?FILE_MODULE:read(Fd3, 1),
Child1 ! {Parent, continue, normal},
@@ -3196,9 +2970,9 @@ delayed_write(Config) when is_list(Config) ->
{'DOWN', Mref1, process, Child1, normal} ->
ok;
{'DOWN', Mref1, _, _, _} = Down1b ->
- ?t:fail(Down1b)
+ ct:fail(Down1b)
end,
- ?t:sleep(1000), % Just in case the file system is slow
+ timer:sleep(1000), % Just in case the file system is slow
{ok, Data1} = ?FILE_MODULE:pread(Fd3, bof, Size+1),
ok = ?FILE_MODULE:close(Fd3),
%%
@@ -3209,9 +2983,9 @@ delayed_write(Config) when is_list(Config) ->
{Child2, wrote} ->
ok;
{'DOWN', Mref2, _, _, _} = Down2a ->
- ?t:fail(Down2a)
+ ct:fail(Down2a)
end,
- ?t:sleep(1000), % Just in case the file system is slow
+ timer:sleep(1000), % Just in case the file system is slow
{ok, Fd4} = ?FILE_MODULE:open(File, [read]),
eof = ?FILE_MODULE:read(Fd4, 1),
Child2 ! {Parent, continue, kill},
@@ -3219,15 +2993,15 @@ delayed_write(Config) when is_list(Config) ->
{'DOWN', Mref2, process, Child2, kill} ->
ok;
{'DOWN', Mref2, _, _, _} = Down2b ->
- ?t:fail(Down2b)
+ ct:fail(Down2b)
end,
- ?t:sleep(1000), % Just in case the file system is slow
+ timer:sleep(1000), % Just in case the file system is slow
eof = ?FILE_MODULE:pread(Fd4, bof, 1),
ok = ?FILE_MODULE:close(Fd4),
%%
%% Test if file position works with delayed_write
{ok, Fd5} = ?FILE_MODULE:open(File, [raw, read, write,
- delayed_write]),
+ delayed_write]),
ok = ?FILE_MODULE:truncate(Fd5),
ok = ?FILE_MODULE:write(Fd5, [Data1|Data2]),
{ok, 0} = ?FILE_MODULE:position(Fd5, bof),
@@ -3239,93 +3013,82 @@ delayed_write(Config) when is_list(Config) ->
ok = ?FILE_MODULE:close(Fd5),
%%
[] = flush(),
- ?t:timetrap_cancel(Dog),
ok.
-pid2name(doc) -> "Tests file:pid2name/1.";
-pid2name(suite) -> [];
+%% Tests file:pid2name/1.
pid2name(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line Base = test_server:temp_name(
- filename:join(RootDir, "pid2name_")),
- ?line Name1 = [Base, '.txt'],
- ?line Name2 = Base ++ ".txt",
- %%
- ?line {ok, Pid} = file:open(Name1, [write]),
- ?line {ok, Name2} = file:pid2name(Pid),
- ?line undefined = file:pid2name(self()),
- ?line ok = file:close(Pid),
- ?line test_server:sleep(1000),
- ?line false = is_process_alive(Pid),
- ?line undefined = file:pid2name(Pid),
+ RootDir = proplists:get_value(priv_dir, Config),
+ Base = test_server:temp_name(
+ filename:join(RootDir, "pid2name_")),
+ Name1 = [Base, '.txt'],
+ Name2 = Base ++ ".txt",
%%
- ?line test_server:timetrap_cancel(Dog),
+ {ok, Pid} = file:open(Name1, [write]),
+ {ok, Name2} = file:pid2name(Pid),
+ undefined = file:pid2name(self()),
+ ok = file:close(Pid),
+ ct:sleep(1000),
+ false = is_process_alive(Pid),
+ undefined = file:pid2name(Pid),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-read_ahead(suite) ->
- [];
-read_ahead(doc) ->
- ["Tests the file open option {read_ahead, Size}"];
+%% Tests the file open option {read_ahead, Size}.
read_ahead(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(20)),
- %%
- ?line RootDir = ?config(priv_dir, Config),
- ?line File = filename:join(RootDir,
- atom_to_list(?MODULE)++"_read_ahead.txt"),
- ?line Data1 = "asdfghjkl", % Must be
- ?line Data2 = "qwertyuio", % same
- ?line Data3 = "zxcvbnm,.", % length
- ?line Size = length(Data1),
- ?line Size = length(Data2),
- ?line Size = length(Data3),
+ RootDir = proplists:get_value(priv_dir, Config),
+ File = filename:join(RootDir,
+ atom_to_list(?MODULE)++"_read_ahead.txt"),
+ Data1 = "asdfghjkl", % Must be
+ Data2 = "qwertyuio", % same
+ Data3 = "zxcvbnm,.", % length
+ Size = length(Data1),
+ Size = length(Data2),
+ Size = length(Data3),
%%
%% Test caching of normal non-raw file
- ?line {ok, Fd1} = ?FILE_MODULE:open(File, [write]),
- ?line ok = ?FILE_MODULE:write(Fd1, [Data1|Data1]),
- ?line ?t:sleep(1000), % Just in case the file system is slow
- ?line {ok, Fd2} = ?FILE_MODULE:open(File, [read, {read_ahead, 2*Size}]),
- ?line {ok, Data1} = ?FILE_MODULE:read(Fd2, Size),
- ?line ok = ?FILE_MODULE:pwrite(Fd1, Size, Data2),
- ?line ?t:sleep(1000), % Just in case the file system is slow
- ?line {ok, Data1} = ?FILE_MODULE:read(Fd2, Size), % Will read cached data
- ?line Data2Data2Data2 = Data2++Data2++Data2,
- ?line ok = ?FILE_MODULE:pwrite(Fd1, eof, Data2Data2Data2),
- ?line ?t:sleep(1000), % Just in case the file system is slow
- ?line {ok, Data2Data2Data2} =
+ {ok, Fd1} = ?FILE_MODULE:open(File, [write]),
+ ok = ?FILE_MODULE:write(Fd1, [Data1|Data1]),
+ timer:sleep(1000), % Just in case the file system is slow
+ {ok, Fd2} = ?FILE_MODULE:open(File, [read, {read_ahead, 2*Size}]),
+ {ok, Data1} = ?FILE_MODULE:read(Fd2, Size),
+ ok = ?FILE_MODULE:pwrite(Fd1, Size, Data2),
+ timer:sleep(1000), % Just in case the file system is slow
+ {ok, Data1} = ?FILE_MODULE:read(Fd2, Size), % Will read cached data
+ Data2Data2Data2 = Data2++Data2++Data2,
+ ok = ?FILE_MODULE:pwrite(Fd1, eof, Data2Data2Data2),
+ timer:sleep(1000), % Just in case the file system is slow
+ {ok, Data2Data2Data2} =
?FILE_MODULE:read(Fd2, 3*Size), % Read more than cache buffer
- ?line ok = ?FILE_MODULE:close(Fd1),
- ?line ok = ?FILE_MODULE:close(Fd2),
+ ok = ?FILE_MODULE:close(Fd1),
+ ok = ?FILE_MODULE:close(Fd2),
%% Test caching of raw file and default parameters
- ?line {ok, Fd3} = ?FILE_MODULE:open(File, [raw, write]),
- ?line ok = ?FILE_MODULE:write(Fd3, [Data1|Data1]),
- ?line ?t:sleep(1000), % Just in case the file system is slow
- ?line {ok, Fd4} = ?FILE_MODULE:open(File, [raw, read, read_ahead]),
- ?line {ok, Data1} = ?FILE_MODULE:read(Fd4, Size),
- ?line ok = ?FILE_MODULE:pwrite(Fd3, Size, Data2),
- ?line ?t:sleep(1000), % Just in case the file system is slow
- ?line {ok, Data1} = ?FILE_MODULE:read(Fd4, Size), % Will read cached data
- ?line ok = ?FILE_MODULE:close(Fd3),
- ?line ok = ?FILE_MODULE:close(Fd4),
+ {ok, Fd3} = ?FILE_MODULE:open(File, [raw, write]),
+ ok = ?FILE_MODULE:write(Fd3, [Data1|Data1]),
+ timer:sleep(1000), % Just in case the file system is slow
+ {ok, Fd4} = ?FILE_MODULE:open(File, [raw, read, read_ahead]),
+ {ok, Data1} = ?FILE_MODULE:read(Fd4, Size),
+ ok = ?FILE_MODULE:pwrite(Fd3, Size, Data2),
+ timer:sleep(1000), % Just in case the file system is slow
+ {ok, Data1} = ?FILE_MODULE:read(Fd4, Size), % Will read cached data
+ ok = ?FILE_MODULE:close(Fd3),
+ ok = ?FILE_MODULE:close(Fd4),
%% Test if the file position works in combination with read_ahead
- ?line {ok, Fd5} = ?FILE_MODULE:open(File, [raw, read, write, read_ahead]),
- ?line ok = ?FILE_MODULE:truncate(Fd5),
- ?line ok = ?FILE_MODULE:write(Fd5, [Data1,Data1|Data3]),
- ?line {ok, 0} = ?FILE_MODULE:position(Fd5, bof),
- ?line {ok, Data1} = ?FILE_MODULE:read(Fd5, Size),
- ?line ok = ?FILE_MODULE:write(Fd5, Data2),
- ?line {ok, 0} = ?FILE_MODULE:position(Fd5, bof),
- ?line Data1Data2Data3 = Data1++Data2++Data3,
- ?line {ok, Data1Data2Data3} = ?FILE_MODULE:read(Fd5, 3*Size+1),
- ?line ok = ?FILE_MODULE:close(Fd5),
+ {ok, Fd5} = ?FILE_MODULE:open(File, [raw, read, write, read_ahead]),
+ ok = ?FILE_MODULE:truncate(Fd5),
+ ok = ?FILE_MODULE:write(Fd5, [Data1,Data1|Data3]),
+ {ok, 0} = ?FILE_MODULE:position(Fd5, bof),
+ {ok, Data1} = ?FILE_MODULE:read(Fd5, Size),
+ ok = ?FILE_MODULE:write(Fd5, Data2),
+ {ok, 0} = ?FILE_MODULE:position(Fd5, bof),
+ Data1Data2Data3 = Data1++Data2++Data3,
+ {ok, Data1Data2Data3} = ?FILE_MODULE:read(Fd5, 3*Size+1),
+ ok = ?FILE_MODULE:close(Fd5),
%%
- ?line [] = flush(),
- ?line ?t:timetrap_cancel(Dog),
+ [] = flush(),
ok.
@@ -3334,137 +3097,131 @@ read_ahead(Config) when is_list(Config) ->
-segment_read(suite) ->
- [];
-segment_read(doc) ->
- ["Tests the segmenting of large reads"];
+%% Tests the segmenting of large reads.
segment_read(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(60)),
- %%
- ?line Name = filename:join(?config(priv_dir, Config),
- ?MODULE_STRING ++ "_segment_read"),
- ?line SegSize = 256*1024,
- ?line SegCnt = SegSize div 4,
- ?line Cnt = 4 * SegCnt,
- ?line ok = create_file(Name, Cnt),
+ Name = filename:join(proplists:get_value(priv_dir, Config),
+ ?MODULE_STRING ++ "_segment_read"),
+ SegSize = 256*1024,
+ SegCnt = SegSize div 4,
+ Cnt = 4 * SegCnt,
+ ok = create_file(Name, Cnt),
%%
%% read_file/1
%%
- ?line {ok, Bin} = ?FILE_MODULE:read_file(Name),
- ?line true = verify_bin(Bin, 0, Cnt),
+ {ok, Bin} = ?FILE_MODULE:read_file(Name),
+ true = verify_bin(Bin, 0, Cnt),
%%
%% read/2
%%
%% Not segmented
- ?line {ok, FD1} = ?FILE_MODULE:open(Name, [read, raw, binary]),
- ?line {ok, B1a} = ?FILE_MODULE:read(FD1, SegSize),
- ?line {ok, B1b} = ?FILE_MODULE:read(FD1, SegSize),
- ?line {ok, B1c} = ?FILE_MODULE:read(FD1, SegSize),
- ?line {ok, B1d} = ?FILE_MODULE:read(FD1, SegSize),
- ?line ok = ?FILE_MODULE:close(FD1),
- ?line true = verify_bin(B1a, 0*SegCnt, SegCnt),
- ?line true = verify_bin(B1b, 1*SegCnt, SegCnt),
- ?line true = verify_bin(B1c, 2*SegCnt, SegCnt),
- ?line true = verify_bin(B1d, 3*SegCnt, SegCnt),
+ {ok, FD1} = ?FILE_MODULE:open(Name, [read, raw, binary]),
+ {ok, B1a} = ?FILE_MODULE:read(FD1, SegSize),
+ {ok, B1b} = ?FILE_MODULE:read(FD1, SegSize),
+ {ok, B1c} = ?FILE_MODULE:read(FD1, SegSize),
+ {ok, B1d} = ?FILE_MODULE:read(FD1, SegSize),
+ ok = ?FILE_MODULE:close(FD1),
+ true = verify_bin(B1a, 0*SegCnt, SegCnt),
+ true = verify_bin(B1b, 1*SegCnt, SegCnt),
+ true = verify_bin(B1c, 2*SegCnt, SegCnt),
+ true = verify_bin(B1d, 3*SegCnt, SegCnt),
%%
%% Segmented
- ?line {ok, FD2} = ?FILE_MODULE:open(Name, [read, raw, binary]),
- ?line {ok, B2a} = ?FILE_MODULE:read(FD2, 1*SegSize),
- ?line {ok, B2b} = ?FILE_MODULE:read(FD2, 2*SegSize),
- ?line {ok, B2c} = ?FILE_MODULE:read(FD2, 2*SegSize),
- ?line ok = ?FILE_MODULE:close(FD2),
- ?line true = verify_bin(B2a, 0*SegCnt, 1*SegCnt),
- ?line true = verify_bin(B2b, 1*SegCnt, 2*SegCnt),
- ?line true = verify_bin(B2c, 3*SegCnt, 1*SegCnt),
+ {ok, FD2} = ?FILE_MODULE:open(Name, [read, raw, binary]),
+ {ok, B2a} = ?FILE_MODULE:read(FD2, 1*SegSize),
+ {ok, B2b} = ?FILE_MODULE:read(FD2, 2*SegSize),
+ {ok, B2c} = ?FILE_MODULE:read(FD2, 2*SegSize),
+ ok = ?FILE_MODULE:close(FD2),
+ true = verify_bin(B2a, 0*SegCnt, 1*SegCnt),
+ true = verify_bin(B2b, 1*SegCnt, 2*SegCnt),
+ true = verify_bin(B2c, 3*SegCnt, 1*SegCnt),
%%
%% pread/3
%%
- ?line {ok, FD3} = ?FILE_MODULE:open(Name, [read, raw, binary]),
+ {ok, FD3} = ?FILE_MODULE:open(Name, [read, raw, binary]),
%%
%% Not segmented
- ?line {ok, B3d} = ?FILE_MODULE:pread(FD3, 3*SegSize, SegSize),
- ?line {ok, B3c} = ?FILE_MODULE:pread(FD3, 2*SegSize, SegSize),
- ?line {ok, B3b} = ?FILE_MODULE:pread(FD3, 1*SegSize, SegSize),
- ?line {ok, B3a} = ?FILE_MODULE:pread(FD3, 0*SegSize, SegSize),
- ?line true = verify_bin(B3a, 0*SegCnt, SegCnt),
- ?line true = verify_bin(B3b, 1*SegCnt, SegCnt),
- ?line true = verify_bin(B3c, 2*SegCnt, SegCnt),
- ?line true = verify_bin(B3d, 3*SegCnt, SegCnt),
+ {ok, B3d} = ?FILE_MODULE:pread(FD3, 3*SegSize, SegSize),
+ {ok, B3c} = ?FILE_MODULE:pread(FD3, 2*SegSize, SegSize),
+ {ok, B3b} = ?FILE_MODULE:pread(FD3, 1*SegSize, SegSize),
+ {ok, B3a} = ?FILE_MODULE:pread(FD3, 0*SegSize, SegSize),
+ true = verify_bin(B3a, 0*SegCnt, SegCnt),
+ true = verify_bin(B3b, 1*SegCnt, SegCnt),
+ true = verify_bin(B3c, 2*SegCnt, SegCnt),
+ true = verify_bin(B3d, 3*SegCnt, SegCnt),
%%
%% Segmented
- ?line {ok, B3g} = ?FILE_MODULE:pread(FD3, 3*SegSize, 2*SegSize),
- ?line {ok, B3f} = ?FILE_MODULE:pread(FD3, 1*SegSize, 2*SegSize),
- ?line {ok, B3e} = ?FILE_MODULE:pread(FD3, 0*SegSize, 1*SegSize),
- ?line true = verify_bin(B3e, 0*SegCnt, 1*SegCnt),
- ?line true = verify_bin(B3f, 1*SegCnt, 2*SegCnt),
- ?line true = verify_bin(B3g, 3*SegCnt, 1*SegCnt),
+ {ok, B3g} = ?FILE_MODULE:pread(FD3, 3*SegSize, 2*SegSize),
+ {ok, B3f} = ?FILE_MODULE:pread(FD3, 1*SegSize, 2*SegSize),
+ {ok, B3e} = ?FILE_MODULE:pread(FD3, 0*SegSize, 1*SegSize),
+ true = verify_bin(B3e, 0*SegCnt, 1*SegCnt),
+ true = verify_bin(B3f, 1*SegCnt, 2*SegCnt),
+ true = verify_bin(B3g, 3*SegCnt, 1*SegCnt),
%%
- ?line ok = ?FILE_MODULE:close(FD3),
+ ok = ?FILE_MODULE:close(FD3),
%%
%% pread/2
%%
- ?line {ok, FD5} = ?FILE_MODULE:open(Name, [read, raw, binary]),
+ {ok, FD5} = ?FILE_MODULE:open(Name, [read, raw, binary]),
%%
%% +---+---+---+---+
%% | 4 | 3 | 2 | 1 |
%% +---+---+---+---+
%% < ^ >
- ?line {ok, [B5d, B5c, B5b, B5a]} =
+ {ok, [B5d, B5c, B5b, B5a]} =
?FILE_MODULE:pread(FD5, [{3*SegSize, SegSize},
{2*SegSize, SegSize},
{1*SegSize, SegSize},
{0*SegSize, SegSize}]),
- ?line true = verify_bin(B5a, 0*SegCnt, SegCnt),
- ?line true = verify_bin(B5b, 1*SegCnt, SegCnt),
- ?line true = verify_bin(B5c, 2*SegCnt, SegCnt),
- ?line true = verify_bin(B5d, 3*SegCnt, SegCnt),
+ true = verify_bin(B5a, 0*SegCnt, SegCnt),
+ true = verify_bin(B5b, 1*SegCnt, SegCnt),
+ true = verify_bin(B5c, 2*SegCnt, SegCnt),
+ true = verify_bin(B5d, 3*SegCnt, SegCnt),
%%
%% +---+-------+-------+
%% | 3 | 2 | 1 |
%% +---+-------+-------+
%% < ^ ^ >
- ?line {ok, [B5g, B5f, B5e]} =
+ {ok, [B5g, B5f, B5e]} =
?FILE_MODULE:pread(FD5, [{3*SegSize, 2*SegSize},
{1*SegSize, 2*SegSize},
{0*SegSize, 1*SegSize}]),
- ?line true = verify_bin(B5e, 0*SegCnt, 1*SegCnt),
- ?line true = verify_bin(B5f, 1*SegCnt, 2*SegCnt),
- ?line true = verify_bin(B5g, 3*SegCnt, 1*SegCnt),
+ true = verify_bin(B5e, 0*SegCnt, 1*SegCnt),
+ true = verify_bin(B5f, 1*SegCnt, 2*SegCnt),
+ true = verify_bin(B5g, 3*SegCnt, 1*SegCnt),
%%
%%
%% +-------+-----------+
%% | 2 | 1 |
%% +-------+-----------+
%% < ^ ^ >
- ?line {ok, [B5i, B5h]} =
+ {ok, [B5i, B5h]} =
?FILE_MODULE:pread(FD5, [{2*SegSize, 3*SegSize},
{0*SegSize, 2*SegSize}]),
- ?line true = verify_bin(B5h, 0*SegCnt, 2*SegCnt),
- ?line true = verify_bin(B5i, 2*SegCnt, 2*SegCnt),
+ true = verify_bin(B5h, 0*SegCnt, 2*SegCnt),
+ true = verify_bin(B5i, 2*SegCnt, 2*SegCnt),
%%
%% +-------+---+---+
%% | 3 | 2 | 1 |
%% +-------+---+---+
%% < ^ ^ >
- ?line {ok, [B5l, B5k, B5j]} =
+ {ok, [B5l, B5k, B5j]} =
?FILE_MODULE:pread(FD5, [{3*SegSize, 1*SegSize},
{2*SegSize, 1*SegSize},
{0*SegSize, 2*SegSize}]),
- ?line true = verify_bin(B5j, 0*SegCnt, 2*SegCnt),
- ?line true = verify_bin(B5k, 2*SegCnt, 1*SegCnt),
- ?line true = verify_bin(B5l, 3*SegCnt, 1*SegCnt),
+ true = verify_bin(B5j, 0*SegCnt, 2*SegCnt),
+ true = verify_bin(B5k, 2*SegCnt, 1*SegCnt),
+ true = verify_bin(B5l, 3*SegCnt, 1*SegCnt),
%%
%% Real time response time test.
%%
Req = lists:flatten(lists:duplicate(17,
[{2*SegSize, 2*SegSize},
{0*SegSize, 2*SegSize}])),
- ?line {{ok, _}, Comment} =
+ {{ok, _}, Comment} =
response_analysis(?FILE_MODULE, pread, [FD5, Req]),
- ?line ok = ?FILE_MODULE:close(FD5),
+ ok = ?FILE_MODULE:close(FD5),
%%
- ?line [] = flush(),
- ?line ?t:timetrap_cancel(Dog),
+ [] = flush(),
{comment, Comment}.
@@ -3473,100 +3230,95 @@ segment_read(Config) when is_list(Config) ->
-segment_write(suite) ->
- [];
-segment_write(doc) ->
- ["Tests the segmenting of large writes"];
+%% Tests the segmenting of large writes.
segment_write(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(60)),
- %%
- ?line Name = filename:join(?config(priv_dir, Config),
- ?MODULE_STRING ++ "_segment_write"),
- ?line SegSize = 256*1024,
- ?line SegCnt = SegSize div 4,
- ?line Cnt = 4 * SegCnt,
- ?line Bin = create_bin(0, Cnt),
+ Name = filename:join(proplists:get_value(priv_dir, Config),
+ ?MODULE_STRING ++ "_segment_write"),
+ SegSize = 256*1024,
+ SegCnt = SegSize div 4,
+ Cnt = 4 * SegCnt,
+ Bin = create_bin(0, Cnt),
%%
%% write/2
%%
%% Not segmented
- ?line {ok, FD1} = ?FILE_MODULE:open(Name, [write, raw, binary]),
- ?line ok = ?FILE_MODULE:write(FD1, subbin(Bin, 0*SegSize, 1*SegSize)),
- ?line ok = ?FILE_MODULE:write(FD1, subbin(Bin, 1*SegSize, 1*SegSize)),
- ?line ok = ?FILE_MODULE:write(FD1, subbin(Bin, 2*SegSize, 1*SegSize)),
- ?line ok = ?FILE_MODULE:write(FD1, subbin(Bin, 3*SegSize, 1*SegSize)),
- ?line ok = ?FILE_MODULE:close(FD1),
- ?line true = verify_file(Name, Cnt),
+ {ok, FD1} = ?FILE_MODULE:open(Name, [write, raw, binary]),
+ ok = ?FILE_MODULE:write(FD1, subbin(Bin, 0*SegSize, 1*SegSize)),
+ ok = ?FILE_MODULE:write(FD1, subbin(Bin, 1*SegSize, 1*SegSize)),
+ ok = ?FILE_MODULE:write(FD1, subbin(Bin, 2*SegSize, 1*SegSize)),
+ ok = ?FILE_MODULE:write(FD1, subbin(Bin, 3*SegSize, 1*SegSize)),
+ ok = ?FILE_MODULE:close(FD1),
+ true = verify_file(Name, Cnt),
%%
%% Segmented
- ?line {ok, FD2} = ?FILE_MODULE:open(Name, [write, raw, binary]),
- ?line ok = ?FILE_MODULE:write(FD2, subbin(Bin, 0*SegSize, 1*SegSize)),
- ?line ok = ?FILE_MODULE:write(FD2, subbin(Bin, 1*SegSize, 2*SegSize)),
- ?line ok = ?FILE_MODULE:write(FD2, subbin(Bin, 3*SegSize, 1*SegSize)),
- ?line ok = ?FILE_MODULE:close(FD2),
- ?line true = verify_file(Name, Cnt),
+ {ok, FD2} = ?FILE_MODULE:open(Name, [write, raw, binary]),
+ ok = ?FILE_MODULE:write(FD2, subbin(Bin, 0*SegSize, 1*SegSize)),
+ ok = ?FILE_MODULE:write(FD2, subbin(Bin, 1*SegSize, 2*SegSize)),
+ ok = ?FILE_MODULE:write(FD2, subbin(Bin, 3*SegSize, 1*SegSize)),
+ ok = ?FILE_MODULE:close(FD2),
+ true = verify_file(Name, Cnt),
%%
%% +---+---+---+---+
%% | | | | |
%% +---+---+---+---+
%% < ^ >
- ?line ok = write_file(Name, [subbin(Bin, 0*SegSize, 1*SegSize),
- subbin(Bin, 1*SegSize, 1*SegSize),
- subbin(Bin, 2*SegSize, 1*SegSize),
- subbin(Bin, 3*SegSize, 1*SegSize)]),
- ?line true = verify_file(Name, Cnt),
+ ok = write_file(Name, [subbin(Bin, 0*SegSize, 1*SegSize),
+ subbin(Bin, 1*SegSize, 1*SegSize),
+ subbin(Bin, 2*SegSize, 1*SegSize),
+ subbin(Bin, 3*SegSize, 1*SegSize)]),
+ true = verify_file(Name, Cnt),
%%
%% +---+-------+---+
%% | | | |
%% +---+-------+---+
%% < ^ ^ >
- ?line ok = write_file(Name, [subbin(Bin, 0*SegSize, 1*SegSize),
- subbin(Bin, 1*SegSize, 2*SegSize),
- subbin(Bin, 3*SegSize, 1*SegSize)]),
- ?line true = verify_file(Name, Cnt),
+ ok = write_file(Name, [subbin(Bin, 0*SegSize, 1*SegSize),
+ subbin(Bin, 1*SegSize, 2*SegSize),
+ subbin(Bin, 3*SegSize, 1*SegSize)]),
+ true = verify_file(Name, Cnt),
%%
%% +-------+-------+
%% | | |
%% +-------+-------+
%% < ^ ^ >
- ?line ok = write_file(Name, [subbin(Bin, 0*SegSize, 2*SegSize),
- subbin(Bin, 2*SegSize, 2*SegSize)]),
- ?line true = verify_file(Name, Cnt),
+ ok = write_file(Name, [subbin(Bin, 0*SegSize, 2*SegSize),
+ subbin(Bin, 2*SegSize, 2*SegSize)]),
+ true = verify_file(Name, Cnt),
%%
%% +-------+---+---+
%% | | | |
%% +-------+---+---+
%% < ^ ^ >
- ?line ok = write_file(Name, [subbin(Bin, 0*SegSize, 2*SegSize),
- subbin(Bin, 2*SegSize, 1*SegSize),
- subbin(Bin, 3*SegSize, 1*SegSize)]),
- ?line true = verify_file(Name, Cnt),
+ ok = write_file(Name, [subbin(Bin, 0*SegSize, 2*SegSize),
+ subbin(Bin, 2*SegSize, 1*SegSize),
+ subbin(Bin, 3*SegSize, 1*SegSize)]),
+ true = verify_file(Name, Cnt),
%%
%% pwrite/3
%%
%% Not segmented
- ?line {ok, FD3} = ?FILE_MODULE:open(Name, [write, raw, binary]),
- ?line ok = ?FILE_MODULE:pwrite(FD3, 3*SegSize,
- subbin(Bin, 3*SegSize, 1*SegSize)),
- ?line ok = ?FILE_MODULE:pwrite(FD3, 2*SegSize,
- subbin(Bin, 2*SegSize, 1*SegSize)),
- ?line ok = ?FILE_MODULE:pwrite(FD3, 1*SegSize,
- subbin(Bin, 1*SegSize, 1*SegSize)),
- ?line ok = ?FILE_MODULE:pwrite(FD3, 0*SegSize,
- subbin(Bin, 0*SegSize, 1*SegSize)),
- ?line ok = ?FILE_MODULE:close(FD3),
- ?line true = verify_file(Name, Cnt),
+ {ok, FD3} = ?FILE_MODULE:open(Name, [write, raw, binary]),
+ ok = ?FILE_MODULE:pwrite(FD3, 3*SegSize,
+ subbin(Bin, 3*SegSize, 1*SegSize)),
+ ok = ?FILE_MODULE:pwrite(FD3, 2*SegSize,
+ subbin(Bin, 2*SegSize, 1*SegSize)),
+ ok = ?FILE_MODULE:pwrite(FD3, 1*SegSize,
+ subbin(Bin, 1*SegSize, 1*SegSize)),
+ ok = ?FILE_MODULE:pwrite(FD3, 0*SegSize,
+ subbin(Bin, 0*SegSize, 1*SegSize)),
+ ok = ?FILE_MODULE:close(FD3),
+ true = verify_file(Name, Cnt),
%%
%% Segmented
- ?line {ok, FD4} = ?FILE_MODULE:open(Name, [write, raw, binary]),
- ?line ok = ?FILE_MODULE:pwrite(FD4, 3*SegSize,
- subbin(Bin, 3*SegSize, 1*SegSize)),
- ?line ok = ?FILE_MODULE:pwrite(FD4, 1*SegSize,
- subbin(Bin, 1*SegSize, 2*SegSize)),
- ?line ok = ?FILE_MODULE:pwrite(FD4, 0*SegSize,
- subbin(Bin, 0*SegSize, 1*SegSize)),
- ?line ok = ?FILE_MODULE:close(FD4),
- ?line true = verify_file(Name, Cnt),
+ {ok, FD4} = ?FILE_MODULE:open(Name, [write, raw, binary]),
+ ok = ?FILE_MODULE:pwrite(FD4, 3*SegSize,
+ subbin(Bin, 3*SegSize, 1*SegSize)),
+ ok = ?FILE_MODULE:pwrite(FD4, 1*SegSize,
+ subbin(Bin, 1*SegSize, 2*SegSize)),
+ ok = ?FILE_MODULE:pwrite(FD4, 0*SegSize,
+ subbin(Bin, 0*SegSize, 1*SegSize)),
+ ok = ?FILE_MODULE:close(FD4),
+ true = verify_file(Name, Cnt),
@@ -3574,125 +3326,118 @@ segment_write(Config) when is_list(Config) ->
%% pwrite/2
%%
%% Not segmented
- ?line {ok, FD5} = ?FILE_MODULE:open(Name, [write, raw, binary]),
- ?line ok = ?FILE_MODULE:pwrite(FD5, [{3*SegSize,
- subbin(Bin, 3*SegSize, 1*SegSize)}]),
- ?line ok = ?FILE_MODULE:pwrite(FD5, [{2*SegSize,
- subbin(Bin, 2*SegSize, 1*SegSize)}]),
- ?line ok = ?FILE_MODULE:pwrite(FD5, [{1*SegSize,
- subbin(Bin, 1*SegSize, 1*SegSize)}]),
- ?line ok = ?FILE_MODULE:pwrite(FD5, [{0*SegSize,
- subbin(Bin, 0*SegSize, 1*SegSize)}]),
- ?line ok = ?FILE_MODULE:close(FD5),
- ?line true = verify_file(Name, Cnt),
+ {ok, FD5} = ?FILE_MODULE:open(Name, [write, raw, binary]),
+ ok = ?FILE_MODULE:pwrite(FD5, [{3*SegSize,
+ subbin(Bin, 3*SegSize, 1*SegSize)}]),
+ ok = ?FILE_MODULE:pwrite(FD5, [{2*SegSize,
+ subbin(Bin, 2*SegSize, 1*SegSize)}]),
+ ok = ?FILE_MODULE:pwrite(FD5, [{1*SegSize,
+ subbin(Bin, 1*SegSize, 1*SegSize)}]),
+ ok = ?FILE_MODULE:pwrite(FD5, [{0*SegSize,
+ subbin(Bin, 0*SegSize, 1*SegSize)}]),
+ ok = ?FILE_MODULE:close(FD5),
+ true = verify_file(Name, Cnt),
%%
%% Segmented
- ?line {ok, FD6} = ?FILE_MODULE:open(Name, [write, raw, binary]),
- ?line ok = ?FILE_MODULE:pwrite(FD6, [{3*SegSize,
- subbin(Bin, 3*SegSize, 1*SegSize)}]),
- ?line ok = ?FILE_MODULE:pwrite(FD6, [{1*SegSize,
- subbin(Bin, 1*SegSize, 2*SegSize)}]),
- ?line ok = ?FILE_MODULE:pwrite(FD6, [{0*SegSize,
- subbin(Bin, 0*SegSize, 1*SegSize)}]),
- ?line ok = ?FILE_MODULE:close(FD6),
- ?line true = verify_file(Name, Cnt),
+ {ok, FD6} = ?FILE_MODULE:open(Name, [write, raw, binary]),
+ ok = ?FILE_MODULE:pwrite(FD6, [{3*SegSize,
+ subbin(Bin, 3*SegSize, 1*SegSize)}]),
+ ok = ?FILE_MODULE:pwrite(FD6, [{1*SegSize,
+ subbin(Bin, 1*SegSize, 2*SegSize)}]),
+ ok = ?FILE_MODULE:pwrite(FD6, [{0*SegSize,
+ subbin(Bin, 0*SegSize, 1*SegSize)}]),
+ ok = ?FILE_MODULE:close(FD6),
+ true = verify_file(Name, Cnt),
%%
%% +---+---+---+---+
%% | 4 | 3 | 2 | 1 |
%% +---+---+---+---+
%% < ^ >
- ?line ok = pwrite_file(Name, [{3*SegSize,
- subbin(Bin, 3*SegSize, 1*SegSize)},
- {2*SegSize,
- subbin(Bin, 2*SegSize, 1*SegSize)},
- {1*SegSize,
- subbin(Bin, 1*SegSize, 1*SegSize)},
- {0*SegSize,
- subbin(Bin, 0*SegSize, 1*SegSize)}]),
- ?line true = verify_file(Name, Cnt),
+ ok = pwrite_file(Name, [{3*SegSize,
+ subbin(Bin, 3*SegSize, 1*SegSize)},
+ {2*SegSize,
+ subbin(Bin, 2*SegSize, 1*SegSize)},
+ {1*SegSize,
+ subbin(Bin, 1*SegSize, 1*SegSize)},
+ {0*SegSize,
+ subbin(Bin, 0*SegSize, 1*SegSize)}]),
+ true = verify_file(Name, Cnt),
%%
%% +---+-------+---+
%% | 3 | 2 | 1 |
%% +---+-------+---+
%% < ^ ^ >
- ?line ok = pwrite_file(Name, [{3*SegSize,
- subbin(Bin, 3*SegSize, 1*SegSize)},
- {1*SegSize,
- subbin(Bin, 1*SegSize, 2*SegSize)},
- {0*SegSize,
- subbin(Bin, 0*SegSize, 1*SegSize)}]),
- ?line true = verify_file(Name, Cnt),
+ ok = pwrite_file(Name, [{3*SegSize,
+ subbin(Bin, 3*SegSize, 1*SegSize)},
+ {1*SegSize,
+ subbin(Bin, 1*SegSize, 2*SegSize)},
+ {0*SegSize,
+ subbin(Bin, 0*SegSize, 1*SegSize)}]),
+ true = verify_file(Name, Cnt),
%%
%% +-------+-------+
%% | 2 | 1 |
%% +-------+-------+
%% < ^ ^ >
- ?line ok = pwrite_file(Name, [{2*SegSize,
- subbin(Bin, 2*SegSize, 2*SegSize)},
- {0*SegSize,
- subbin(Bin, 0*SegSize, 2*SegSize)}]),
- ?line true = verify_file(Name, Cnt),
+ ok = pwrite_file(Name, [{2*SegSize,
+ subbin(Bin, 2*SegSize, 2*SegSize)},
+ {0*SegSize,
+ subbin(Bin, 0*SegSize, 2*SegSize)}]),
+ true = verify_file(Name, Cnt),
%%
%% +-------+---+---+
%% | 3 | 2 | 1 |
%% +-------+---+---+
%% < ^ ^ >
- ?line ok = pwrite_file(Name, [{3*SegSize,
- subbin(Bin, 3*SegSize, 1*SegSize)},
- {2*SegSize,
- subbin(Bin, 2*SegSize, 1*SegSize)},
- {0*SegSize,
- subbin(Bin, 0*SegSize, 2*SegSize)}]),
- ?line true = verify_file(Name, Cnt),
+ ok = pwrite_file(Name, [{3*SegSize,
+ subbin(Bin, 3*SegSize, 1*SegSize)},
+ {2*SegSize,
+ subbin(Bin, 2*SegSize, 1*SegSize)},
+ {0*SegSize,
+ subbin(Bin, 0*SegSize, 2*SegSize)}]),
+ true = verify_file(Name, Cnt),
%%
%% Real time response time test.
%%
- ?line {ok, FD7} = ?FILE_MODULE:open(Name, [write, raw, binary]),
+ {ok, FD7} = ?FILE_MODULE:open(Name, [write, raw, binary]),
Req = lists:flatten(lists:duplicate(17,
[{2*SegSize,
subbin(Bin, 2*SegSize, 2*SegSize)},
- {0*SegSize,
- subbin(Bin, 0*SegSize, 2*SegSize)}])),
- ?line {ok, Comment} =
+ {0*SegSize,
+ subbin(Bin, 0*SegSize, 2*SegSize)}])),
+ {ok, Comment} =
response_analysis(?FILE_MODULE, pwrite, [FD7, Req]),
- ?line ok = ?FILE_MODULE:close(FD7),
+ ok = ?FILE_MODULE:close(FD7),
%%
- ?line [] = flush(),
- ?line ?t:timetrap_cancel(Dog),
+ [] = flush(),
{comment, Comment}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-ipread(suite) ->
- [];
-ipread(doc) ->
- ["Test Dets special indirect pread"];
+%% Test Dets special indirect pread.
ipread(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(30)),
- %%
- ?line Dir = ?config(priv_dir, Config),
- ?line ok = ipread_int(Dir, [raw, binary]),
- ?line ok = ipread_int(Dir, [raw]),
- ?line ok = ipread_int(Dir, [binary]),
- ?line ok = ipread_int(Dir, []),
- ?line ok = ipread_int(Dir, [ram, binary]),
- ?line ok = ipread_int(Dir, [ram]),
+ Dir = proplists:get_value(priv_dir, Config),
+ ok = ipread_int(Dir, [raw, binary]),
+ ok = ipread_int(Dir, [raw]),
+ ok = ipread_int(Dir, [binary]),
+ ok = ipread_int(Dir, []),
+ ok = ipread_int(Dir, [ram, binary]),
+ ok = ipread_int(Dir, [ram]),
%%
- ?line [] = flush(),
- ?line ?t:timetrap_cancel(Dog),
+ [] = flush(),
ok.
ipread_int(Dir, ModeList) ->
- ?line Name =
+ Name =
filename:join(Dir,
lists:flatten([?MODULE_STRING, "_ipread",
- lists:map(fun (X) ->
- ["_", atom_to_list(X)]
- end,
- ModeList)])),
- ?line io:format("ipread_int<~p, ~p>~n", [Name, ModeList]),
- ?line {Conv, Sizeof} =
+ lists:map(fun (X) ->
+ ["_", atom_to_list(X)]
+ end,
+ ModeList)])),
+ io:format("ipread_int<~p, ~p>~n", [Name, ModeList]),
+ {Conv, Sizeof} =
case lists:member(binary, ModeList) of
true ->
{fun (Bin) when is_binary(Bin) -> Bin;
@@ -3705,144 +3450,130 @@ ipread_int(Dir, ModeList) ->
end,
fun erlang:length/1}
end,
- ?line Pos = 4711,
- ?line Data = Conv("THE QUICK BROWN FOX JUMPS OVER A LAZY DOG"),
- ?line Size = Sizeof(Data),
- ?line Init = Conv(" "),
- ?line SizeInit = Sizeof(Init),
- ?line Head = Conv(<<Size:32/big-unsigned, Pos:32/big-unsigned>>),
- ?line Filler = Conv(bytes($ , Pos-SizeInit-Sizeof(Head))),
- ?line Size1 = Size+1,
- ?line SizePos = Size+Pos,
+ Pos = 4711,
+ Data = Conv("THE QUICK BROWN FOX JUMPS OVER A LAZY DOG"),
+ Size = Sizeof(Data),
+ Init = Conv(" "),
+ SizeInit = Sizeof(Init),
+ Head = Conv(<<Size:32/big-unsigned, Pos:32/big-unsigned>>),
+ Filler = Conv(bytes($ , Pos-SizeInit-Sizeof(Head))),
+ Size1 = Size+1,
+ SizePos = Size+Pos,
%%
- ?line {ok, FD} = ?FILE_MODULE:open(Name, [write, read | ModeList]),
- ?line ok = ?FILE_MODULE:truncate(FD),
- ?line ok = ?FILE_MODULE:write(FD, Init),
- ?line ok = ?FILE_MODULE:write(FD, Head),
- ?line ok = ?FILE_MODULE:write(FD, Filler),
- ?line ok = ?FILE_MODULE:write(FD, Data),
+ {ok, FD} = ?FILE_MODULE:open(Name, [write, read | ModeList]),
+ ok = ?FILE_MODULE:truncate(FD),
+ ok = ?FILE_MODULE:write(FD, Init),
+ ok = ?FILE_MODULE:write(FD, Head),
+ ok = ?FILE_MODULE:write(FD, Filler),
+ ok = ?FILE_MODULE:write(FD, Data),
%% Correct read
- ?line {ok, {Size, Pos, Data}} =
+ {ok, {Size, Pos, Data}} =
?FILE_MODULE:ipread_s32bu_p32bu(FD, SizeInit, infinity),
%% Invalid header - size > max
- ?line eof =
+ eof =
?FILE_MODULE:ipread_s32bu_p32bu(FD, SizeInit, Size-1),
%% Data block protudes over eof
- ?line ok =
+ ok =
?FILE_MODULE:pwrite(FD, SizeInit,
<<Size1:32/big-unsigned,
- Pos:32/big-unsigned>>),
- ?line {ok, {Size1, Pos, Data}} =
+ Pos:32/big-unsigned>>),
+ {ok, {Size1, Pos, Data}} =
?FILE_MODULE:ipread_s32bu_p32bu(FD, SizeInit, Size1),
%% Data block outside file
- ?line ok =
+ ok =
?FILE_MODULE:pwrite(FD, SizeInit,
<<Size:32/big-unsigned,
- SizePos:32/big-unsigned>>),
- ?line {ok, {Size, SizePos, eof}} =
+ SizePos:32/big-unsigned>>),
+ {ok, {Size, SizePos, eof}} =
?FILE_MODULE:ipread_s32bu_p32bu(FD, SizeInit, Size),
%% Zero size
- ?line ok =
+ ok =
?FILE_MODULE:pwrite(FD, SizeInit,
<<0:32/big-unsigned,
- Pos:32/big-unsigned>>),
- ?line {ok, {0, Pos, eof}} =
+ Pos:32/big-unsigned>>),
+ {ok, {0, Pos, eof}} =
?FILE_MODULE:ipread_s32bu_p32bu(FD, SizeInit, Size),
%% Invalid header - protudes over eof
- ?line eof =
+ eof =
?FILE_MODULE:ipread_s32bu_p32bu(FD,
Pos+Size-(Sizeof(Head)-1),
infinity),
%% Header not even in file
- ?line eof =
+ eof =
?FILE_MODULE:ipread_s32bu_p32bu(FD, Pos+Size, infinity),
%%
- ?line ok = ?FILE_MODULE:close(FD),
+ ok = ?FILE_MODULE:close(FD),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-interleaved_read_write(suite) ->
- [];
-interleaved_read_write(doc) ->
- ["Tests interleaved read and writes"];
+%% Tests interleaved read and writes.
interleaved_read_write(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(30)),
- %%
- ?line Dir = ?config(priv_dir, Config),
- ?line File =
+ Dir = proplists:get_value(priv_dir, Config),
+ File =
filename:join(Dir, ?MODULE_STRING++"interleaved_read_write.txt"),
- ?line {ok,F1} = ?FILE_MODULE:open(File, [write]),
- ?line ok = ?FILE_MODULE:write(F1, "data---r1."), % 10 chars each
- ?line ok = ?FILE_MODULE:write(F1, "data---r2."),
- ?line ok = ?FILE_MODULE:write(F1, "data---r3."),
- ?line ok = ?FILE_MODULE:close(F1),
- ?line {ok,F2} = ?FILE_MODULE:open(File, [read, write]),
- ?line {ok, "data---r1."} = ?FILE_MODULE:read(F2, 10),
- ?line ok = ?FILE_MODULE:write(F2, "data---w2."),
- ?line ok = ?FILE_MODULE:close(F2),
- ?line {ok,F3} = ?FILE_MODULE:open(File, [read]),
- ?line {ok, "data---r1."} = ?FILE_MODULE:read(F3, 10),
- ?line {ok, "data---w2."} = ?FILE_MODULE:read(F3, 10),
- ?line {ok, "data---r3."} = ?FILE_MODULE:read(F3, 10),
- ?line eof = ?FILE_MODULE:read(F3, 1),
- ?line ok = ?FILE_MODULE:close(F2),
+ {ok,F1} = ?FILE_MODULE:open(File, [write]),
+ ok = ?FILE_MODULE:write(F1, "data---r1."), % 10 chars each
+ ok = ?FILE_MODULE:write(F1, "data---r2."),
+ ok = ?FILE_MODULE:write(F1, "data---r3."),
+ ok = ?FILE_MODULE:close(F1),
+ {ok,F2} = ?FILE_MODULE:open(File, [read, write]),
+ {ok, "data---r1."} = ?FILE_MODULE:read(F2, 10),
+ ok = ?FILE_MODULE:write(F2, "data---w2."),
+ ok = ?FILE_MODULE:close(F2),
+ {ok,F3} = ?FILE_MODULE:open(File, [read]),
+ {ok, "data---r1."} = ?FILE_MODULE:read(F3, 10),
+ {ok, "data---w2."} = ?FILE_MODULE:read(F3, 10),
+ {ok, "data---r3."} = ?FILE_MODULE:read(F3, 10),
+ eof = ?FILE_MODULE:read(F3, 1),
+ ok = ?FILE_MODULE:close(F2),
%%
- ?line [] = flush(),
- ?line ?t:timetrap_cancel(Dog),
+ [] = flush(),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-otp_5814(suite) ->
- [];
-otp_5814(doc) ->
- ["OTP-5814. eval/consult/script return correct line numbers"];
+%% OTP-5814. eval/consult/script return correct line numbers.
otp_5814(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(10)),
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
File = filename:join(PrivDir, "otp_5814"),
Path = [PrivDir],
- ?line ok = file:write_file(File, <<"{a,b,c}.
+ ok = file:write_file(File, <<"{a,b,c}.
a.
- b.
- c.
- {d,e,
- [}.">>),
- ?line {error, {6,erl_parse,_}} = file:eval(File),
- ?line {error, {6,erl_parse,_}} = file:consult(File),
- ?line {error, {6,erl_parse,_}} = file:path_consult(Path, File),
- ?line {error, {6,erl_parse,_}} = file:path_eval(Path, File),
- ?line {error, {6,erl_parse,_}} = file:script(File),
- ?line {error, {6,erl_parse,_}} = file:path_script(Path, File),
-
- ?line ok = file:write_file(File, <<>>),
- ?line {error, {1,file,undefined_script}} = file:path_script(Path, File),
+b.
+c.
+{d,e,
+ [}.">>),
+ {error, {6,erl_parse,_}} = file:eval(File),
+ {error, {6,erl_parse,_}} = file:consult(File),
+ {error, {6,erl_parse,_}} = file:path_consult(Path, File),
+ {error, {6,erl_parse,_}} = file:path_eval(Path, File),
+ {error, {6,erl_parse,_}} = file:script(File),
+ {error, {6,erl_parse,_}} = file:path_script(Path, File),
+
+ ok = file:write_file(File, <<>>),
+ {error, {1,file,undefined_script}} = file:path_script(Path, File),
%% The error is not propagated...
- ?line ok = file:write_file(File, <<"a.
+ ok = file:write_file(File, <<"a.
b.
- 1/0.">>),
- ?line {error, {3, file, {error, badarith, _}}} = file:eval(File),
-
- ?line ok = file:write_file(File, <<"erlang:raise(throw, apa, []).">>),
- ?line {error, {1, file, {throw, apa, _}}} = file:eval(File),
+1/0.">>),
+ {error, {3, file, {error, badarith, _}}} = file:eval(File),
- file:delete(File),
- ?line ?t:timetrap_cancel(Dog),
- ok.
+ok = file:write_file(File, <<"erlang:raise(throw, apa, []).">>),
+{error, {1, file, {throw, apa, _}}} = file:eval(File),
+
+file:delete(File),
+ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-otp_10852(suite) ->
- [];
-otp_10852(doc) ->
- ["OTP-10852. +fnu and latin1 filenames"];
+%% OTP-10852. +fnu and latin1 filenames.
otp_10852(Config) when is_list(Config) ->
Node = start_node(erl_pp_helper, "+fnu"),
- Dir = ?config(priv_dir, Config),
+ Dir = proplists:get_value(priv_dir, Config),
B = filename:join(Dir, <<"\xE4">>),
ok = rpc_call(Node, get_cwd, [B]),
{error, no_translation} = rpc_call(Node, set_cwd, [B]),
@@ -3857,10 +3588,10 @@ otp_10852(Config) when is_list(Config) ->
ok = rpc_call(Node, read_file, [B]),
ok = rpc_call(Node, make_link, [B,B]),
case rpc_call(Node, make_symlink, [B,B]) of
- ok -> ok;
- {error, E} when (E =:= enotsup) or (E =:= eperm) ->
- {win32,_} = os:type()
- end,
+ ok -> ok;
+ {error, E} when (E =:= enotsup) or (E =:= eperm) ->
+ {win32,_} = os:type()
+ end,
ok = rpc_call(Node, delete, [B]),
ok = rpc_call(Node, make_dir, [B]),
ok = rpc_call(Node, del_dir, [B]),
@@ -3883,54 +3614,51 @@ rpc_call(N, F, As) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-large_file(suite) ->
- [];
-large_file(doc) ->
- ["Tests positioning in large files (> 4G)"];
+large_file() ->
+ [{timetrap,{minutes,20}}].
+
+%% Tests positioning in large files (> 4G).
large_file(Config) when is_list(Config) ->
run_large_file_test(Config,
fun(Name) -> do_large_file(Name) end,
"_large_file").
do_large_file(Name) ->
- ?line Watchdog = ?t:timetrap(?t:minutes(20)),
-
- ?line S = "1234567890",
+ S = "1234567890",
L = length(S),
R = lists:reverse(S),
P = 1 bsl 32,
Ss = lists:sort(S),
Rs = lists:reverse(Ss),
- ?line {ok,F} = ?FILE_MODULE:open(Name, [raw,read,write]),
- ?line ok = ?FILE_MODULE:write(F, S),
- ?line {ok,P} = ?FILE_MODULE:position(F, P),
- ?line ok = ?FILE_MODULE:write(F, R),
- ?line {ok,0} = ?FILE_MODULE:position(F, bof),
- ?line {ok,S} = ?FILE_MODULE:read(F, L),
- ?line {ok,P} = ?FILE_MODULE:position(F, {eof,-L}),
- ?line {ok,R} = ?FILE_MODULE:read(F, L+1),
- ?line {ok,S} = ?FILE_MODULE:pread(F, 0, L),
- ?line {ok,R} = ?FILE_MODULE:pread(F, P, L+1),
- ?line ok = ?FILE_MODULE:pwrite(F, 0, Ss),
- ?line ok = ?FILE_MODULE:pwrite(F, P, Rs),
- ?line {ok,0} = ?FILE_MODULE:position(F, bof),
- ?line {ok,Ss} = ?FILE_MODULE:read(F, L),
- ?line {ok,P} = ?FILE_MODULE:position(F, {eof,-L}),
- ?line {ok,Rs} = ?FILE_MODULE:read(F, L+1),
- ?line ok = ?FILE_MODULE:close(F),
+ {ok,F} = ?FILE_MODULE:open(Name, [raw,read,write]),
+ ok = ?FILE_MODULE:write(F, S),
+ {ok,P} = ?FILE_MODULE:position(F, P),
+ ok = ?FILE_MODULE:write(F, R),
+ {ok,0} = ?FILE_MODULE:position(F, bof),
+ {ok,S} = ?FILE_MODULE:read(F, L),
+ {ok,P} = ?FILE_MODULE:position(F, {eof,-L}),
+ {ok,R} = ?FILE_MODULE:read(F, L+1),
+ {ok,S} = ?FILE_MODULE:pread(F, 0, L),
+ {ok,R} = ?FILE_MODULE:pread(F, P, L+1),
+ ok = ?FILE_MODULE:pwrite(F, 0, Ss),
+ ok = ?FILE_MODULE:pwrite(F, P, Rs),
+ {ok,0} = ?FILE_MODULE:position(F, bof),
+ {ok,Ss} = ?FILE_MODULE:read(F, L),
+ {ok,P} = ?FILE_MODULE:position(F, {eof,-L}),
+ {ok,Rs} = ?FILE_MODULE:read(F, L+1),
+ ok = ?FILE_MODULE:close(F),
%% Reopen the file with 'append'; used to fail on Windows causing
%% writes to go to the beginning of the file for files > 4GB.
- ?line PL = P + L,
- ?line PLL = PL + L,
- ?line {ok,F1} = ?FILE_MODULE:open(Name, [raw,read,write,append]),
- ?line ok = ?FILE_MODULE:write(F1, R),
- ?line {ok,PLL} = ?FILE_MODULE:position(F1, {cur,0}),
- ?line {ok,Rs} = ?FILE_MODULE:pread(F1, P, L),
- ?line {ok,PL} = ?FILE_MODULE:position(F1, {eof,-L}),
- ?line {ok,R} = ?FILE_MODULE:read(F1, L+1),
- ?line ok = ?FILE_MODULE:close(F1),
- %%
- ?line ?t:timetrap_cancel(Watchdog),
+ PL = P + L,
+ PLL = PL + L,
+ {ok,F1} = ?FILE_MODULE:open(Name, [raw,read,write,append]),
+ ok = ?FILE_MODULE:write(F1, R),
+ {ok,PLL} = ?FILE_MODULE:position(F1, {cur,0}),
+ {ok,Rs} = ?FILE_MODULE:pread(F1, P, L),
+ {ok,PL} = ?FILE_MODULE:position(F1, {eof,-L}),
+ {ok,R} = ?FILE_MODULE:read(F1, L+1),
+ ok = ?FILE_MODULE:close(F1),
+
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -3964,8 +3692,8 @@ do_large_write(Name) ->
response_analysis(Module, Function, Arguments) ->
Parent = self(),
- ?line erlang:yield(), % Schedule out before test
- ?line Child =
+ erlang:yield(), % Schedule out before test
+ Child =
spawn_link(
fun () ->
receive {Parent, start, Ts} -> ok end,
@@ -3985,19 +3713,19 @@ response_analysis(Module, Function, Arguments) ->
Parent ! {self(), stopped, response_stat(Stat, micro_ts())}
end),
Child ! {Parent, start, micro_ts()},
- ?line Result = apply(Module, Function, Arguments),
- ?line Child ! {Parent, stop},
- ?line {N, Sum, _, M, Max} = receive {Child, stopped, X} -> X end,
- ?line Mean_ms = (0.001*Sum) / (N-1),
- ?line Max_ms = 0.001 * Max,
- ?line Comment =
+ Result = apply(Module, Function, Arguments),
+ Child ! {Parent, stop},
+ {N, Sum, _, M, Max} = receive {Child, stopped, X} -> X end,
+ Mean_ms = (0.001*Sum) / (N-1),
+ Max_ms = 0.001 * Max,
+ Comment =
lists:flatten(
io_lib:format(
"Scheduling interval: Mean = ~.3f ms, "
++"Max = ~.3f ms for no ~p of ~p.~n",
[Mean_ms, Max_ms, M, (N-1)])),
- ?line {Result, Comment}.
-
+ {Result, Comment}.
+
micro_ts() ->
erlang:monotonic_time(micro_seconds).
@@ -4021,10 +3749,10 @@ response_stat({N, Sum, Ts0, M, Max}, Ts) ->
%% create_file/2 below is some 44 times faster.
create_file_slow(Name, N) when is_integer(N), N >= 0 ->
- ?line {ok, FD} =
+ {ok, FD} =
?FILE_MODULE:open(Name, [raw, write, delayed_write, binary]),
- ?line ok = create_file_slow(FD, 0, N),
- ?line ok = ?FILE_MODULE:close(FD),
+ ok = create_file_slow(FD, 0, N),
+ ok = ?FILE_MODULE:close(FD),
ok.
create_file_slow(_FD, M, M) ->
@@ -4039,10 +3767,10 @@ create_file_slow(FD, M, N) ->
%% from 0 to N-1.
create_file(Name, N) when is_integer(N), N >= 0 ->
- ?line {ok, FD} =
+ {ok, FD} =
?FILE_MODULE:open(Name, [raw, write, delayed_write, binary]),
- ?line ok = create_file(FD, 0, N),
- ?line ok = ?FILE_MODULE:close(FD),
+ ok = create_file(FD, 0, N),
+ ok = ?FILE_MODULE:close(FD),
ok.
create_file(_FD, M, M) ->
@@ -4059,10 +3787,10 @@ create_file(FD, M, N0, R) when M + 8 =< N0 ->
N1 = N0-1, N2 = N0-2, N3 = N0-3, N4 = N0-4,
N5 = N0-5, N6 = N0-6, N7 = N0-7, N8 = N0-8,
create_file(FD, M, N8,
- [<<N8:32/unsigned, N7:32/unsigned,
- N6:32/unsigned, N5:32/unsigned,
- N4:32/unsigned, N3:32/unsigned,
- N2:32/unsigned, N1:32/unsigned>> | R]);
+ [<<N8:32/unsigned, N7:32/unsigned,
+ N6:32/unsigned, N5:32/unsigned,
+ N4:32/unsigned, N3:32/unsigned,
+ N2:32/unsigned, N1:32/unsigned>> | R]);
create_file(FD, M, N0, R) ->
N1 = N0-1,
create_file(FD, M, N1, [<<N1:32/unsigned>> | R]).
@@ -4079,14 +3807,14 @@ create_bin(M, N0, R) when M+8 =< N0 ->
N5 = N0-5, N6 = N0-6, N7 = N0-7, N8 = N0-8,
create_bin(M, N8,
[<<N8:32/unsigned, N7:32/unsigned,
- N6:32/unsigned, N5:32/unsigned,
- N4:32/unsigned, N3:32/unsigned,
- N2:32/unsigned, N1:32/unsigned>> | R]);
+ N6:32/unsigned, N5:32/unsigned,
+ N4:32/unsigned, N3:32/unsigned,
+ N2:32/unsigned, N1:32/unsigned>> | R]);
create_bin(M, N0, R) ->
N1 = N0-1,
create_bin(M, N1, [<<N1:32/unsigned>> | R]).
-
-
+
+
verify_bin(<<>>, _, 0) ->
@@ -4098,8 +3826,8 @@ verify_bin(Bin, N, Cnt) ->
N4 = N + 4, N5 = N + 5, N6 = N + 6, N7 = N + 7,
case Bin of
<<N0:32/unsigned, N1:32/unsigned, N2:32/unsigned, N3:32/unsigned,
- N4:32/unsigned, N5:32/unsigned, N6:32/unsigned, N7:32/unsigned,
- B/binary>> ->
+ N4:32/unsigned, N5:32/unsigned, N6:32/unsigned, N7:32/unsigned,
+ B/binary>> ->
verify_bin(B, N+8, Cnt-8);
<<N:32/unsigned, B/binary>> ->
verify_bin(B, N+1, Cnt-1);
@@ -4180,13 +3908,13 @@ pwrite_file(Name, Data) ->
read_line_testdata(PrivDir) ->
All0 = [{fun read_line_create0/1,"Testdata1.txt",5,10},
- {fun read_line_create1/1,"Testdata2.txt",401,802},
- {fun read_line_create2/1,"Testdata3.txt",1,2},
- {fun read_line_create3/1,"Testdata4.txt",601,fail},
- {fun read_line_create4/1,"Testdata5.txt",601,1002},
- {fun read_line_create5/1,"Testdata6.txt",601,1202},
- {fun read_line_create6/1,"Testdata7.txt",601,1202},
- {fun read_line_create7/1,"Testdata8.txt",4001,8002}],
+ {fun read_line_create1/1,"Testdata2.txt",401,802},
+ {fun read_line_create2/1,"Testdata3.txt",1,2},
+ {fun read_line_create3/1,"Testdata4.txt",601,fail},
+ {fun read_line_create4/1,"Testdata5.txt",601,1002},
+ {fun read_line_create5/1,"Testdata6.txt",601,1202},
+ {fun read_line_create6/1,"Testdata7.txt",601,1202},
+ {fun read_line_create7/1,"Testdata8.txt",4001,8002}],
[ {A,filename:join([PrivDir,B]),C,D} || {A,B,C,D} <- All0 ].
read_line_create_files(TestData) ->
@@ -4195,105 +3923,93 @@ read_line_create_files(TestData) ->
read_line_remove_files(TestData) ->
[ file:delete(File) || {_Function,File,_,_} <- TestData ].
-read_line_1(suite) ->
- [];
-read_line_1(doc) ->
- ["read_line with prim_file"];
+%% read_line with prim_file.
read_line_1(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line All = read_line_testdata(PrivDir),
- ?line read_line_create_files(All),
- ?line [ begin
- io:format("read_line_all: ~s~n",[File]),
- {X,_} = read_line_all(File),
- true
- end || {_,File,X,_} <- All ],
- ?line [ begin
- io:format("read_line_all_alternating: ~s~n",[File]),
- {Y,_} = read_line_all_alternating(File),
- true
- end || {_,File,_,Y} <- All , Y =/= fail],
- ?line [ begin
- io:format("read_line_all_alternating (failing as should): ~s~n",[File]),
- {'EXIT',_} = (catch read_line_all_alternating(File)),
- true
- end || {_,File,_,Y} <- All , Y =:= fail],
- ?line read_line_remove_files(All),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ All = read_line_testdata(PrivDir),
+ read_line_create_files(All),
+ [ begin
+ io:format("read_line_all: ~s~n",[File]),
+ {X,_} = read_line_all(File),
+ true
+ end || {_,File,X,_} <- All ],
+ [ begin
+ io:format("read_line_all_alternating: ~s~n",[File]),
+ {Y,_} = read_line_all_alternating(File),
+ true
+ end || {_,File,_,Y} <- All , Y =/= fail],
+ [ begin
+ io:format("read_line_all_alternating (failing as should): ~s~n",[File]),
+ {'EXIT',_} = (catch read_line_all_alternating(File)),
+ true
+ end || {_,File,_,Y} <- All , Y =:= fail],
+ read_line_remove_files(All),
ok.
-read_line_2(suite) ->
- [];
-read_line_2(doc) ->
- ["read_line with file"];
+%% read_line with file.
read_line_2(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line All = read_line_testdata(PrivDir),
- ?line read_line_create_files(All),
- ?line [ begin
- io:format("read_line_all: ~s~n",[File]),
- {X,_} = read_line_all2(File),
- true
- end || {_,File,X,_} <- All ],
- ?line [ begin
- io:format("read_line_all_alternating: ~s~n",[File]),
- {Y,_} = read_line_all_alternating2(File),
- true
- end || {_,File,_,Y} <- All , Y =/= fail],
- ?line [ begin
- io:format("read_line_all_alternating (failing as should): ~s~n",[File]),
- {'EXIT',_} = (catch read_line_all_alternating2(File)),
- true
- end || {_,File,_,Y} <- All , Y =:= fail],
- ?line read_line_remove_files(All),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ All = read_line_testdata(PrivDir),
+ read_line_create_files(All),
+ [ begin
+ io:format("read_line_all: ~s~n",[File]),
+ {X,_} = read_line_all2(File),
+ true
+ end || {_,File,X,_} <- All ],
+ [ begin
+ io:format("read_line_all_alternating: ~s~n",[File]),
+ {Y,_} = read_line_all_alternating2(File),
+ true
+ end || {_,File,_,Y} <- All , Y =/= fail],
+ [ begin
+ io:format("read_line_all_alternating (failing as should): ~s~n",[File]),
+ {'EXIT',_} = (catch read_line_all_alternating2(File)),
+ true
+ end || {_,File,_,Y} <- All , Y =:= fail],
+ read_line_remove_files(All),
ok.
-read_line_3(suite) ->
- [];
-read_line_3(doc) ->
- ["read_line with raw file"];
+%% read_line with raw file.
read_line_3(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line All = read_line_testdata(PrivDir),
- ?line read_line_create_files(All),
- ?line [ begin
- io:format("read_line_all: ~s~n",[File]),
- {X,_} = read_line_all3(File),
- true
- end || {_,File,X,_} <- All ],
- ?line [ begin
- io:format("read_line_all_alternating: ~s~n",[File]),
- {Y,_} = read_line_all_alternating3(File),
- true
- end || {_,File,_,Y} <- All , Y =/= fail],
- ?line [ begin
- io:format("read_line_all_alternating (failing as should): ~s~n",[File]),
- {'EXIT',_} = (catch read_line_all_alternating3(File)),
- true
- end || {_,File,_,Y} <- All , Y =:= fail],
- ?line read_line_remove_files(All),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ All = read_line_testdata(PrivDir),
+ read_line_create_files(All),
+ [ begin
+ io:format("read_line_all: ~s~n",[File]),
+ {X,_} = read_line_all3(File),
+ true
+ end || {_,File,X,_} <- All ],
+ [ begin
+ io:format("read_line_all_alternating: ~s~n",[File]),
+ {Y,_} = read_line_all_alternating3(File),
+ true
+ end || {_,File,_,Y} <- All , Y =/= fail],
+ [ begin
+ io:format("read_line_all_alternating (failing as should): ~s~n",[File]),
+ {'EXIT',_} = (catch read_line_all_alternating3(File)),
+ true
+ end || {_,File,_,Y} <- All , Y =:= fail],
+ read_line_remove_files(All),
ok.
-read_line_4(suite) ->
- [];
-read_line_4(doc) ->
- ["read_line with raw buffered file"];
+%% read_line with raw buffered file.
read_line_4(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line All = read_line_testdata(PrivDir),
- ?line read_line_create_files(All),
- ?line [ begin
- io:format("read_line_all: ~s~n",[File]),
- {X,_} = read_line_all4(File),
- true
- end || {_,File,X,_} <- All ],
- ?line [ begin
- io:format("read_line_all_alternating: ~s~n",[File]),
- {Y,_} = read_line_all_alternating4(File),
- true
- end || {_,File,_,Y} <- All , Y =/= fail],
- ?line [ begin
- io:format("read_line_all_alternating (failing as should): ~s~n",[File]),
- {'EXIT',_} = (catch read_line_all_alternating4(File)),
- true
- end || {_,File,_,Y} <- All , Y =:= fail],
- ?line read_line_remove_files(All),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ All = read_line_testdata(PrivDir),
+ read_line_create_files(All),
+ [ begin
+ io:format("read_line_all: ~s~n",[File]),
+ {X,_} = read_line_all4(File),
+ true
+ end || {_,File,X,_} <- All ],
+ [ begin
+ io:format("read_line_all_alternating: ~s~n",[File]),
+ {Y,_} = read_line_all_alternating4(File),
+ true
+ end || {_,File,_,Y} <- All , Y =/= fail],
+ [ begin
+ io:format("read_line_all_alternating (failing as should): ~s~n",[File]),
+ {'EXIT',_} = (catch read_line_all_alternating4(File)),
+ true
+ end || {_,File,_,Y} <- All , Y =:= fail],
+ read_line_remove_files(All),
ok.
rl_lines() ->
@@ -4548,7 +4264,7 @@ run_large_file_test(Config, Run, Name) ->
{{unix,sunos},OsVersion} when OsVersion < {5,5,1} ->
{skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"};
{{unix,_},_} ->
- N = disc_free(?config(priv_dir, Config)),
+ N = disc_free(proplists:get_value(priv_dir, Config)),
io:format("Free disk: ~w KByte~n", [N]),
if N < 5 * (1 bsl 20) ->
%% Less than 5 GByte free
@@ -4562,9 +4278,9 @@ run_large_file_test(Config, Run, Name) ->
do_run_large_file_test(Config, Run, Name0) ->
- Name = filename:join(?config(priv_dir, Config),
+ Name = filename:join(proplists:get_value(priv_dir, Config),
?MODULE_STRING ++ Name0),
-
+
%% Set up a process that will delete this file.
Tester = self(),
Deleter =
@@ -4577,7 +4293,7 @@ do_run_large_file_test(Config, Run, Name0) ->
end,
?FILE_MODULE:delete(Name)
end),
-
+
%% Run the test case.
Res = Run(Name),
diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl
index 32006d893e..be4ef9c394 100644
--- a/lib/kernel/test/file_name_SUITE.erl
+++ b/lib/kernel/test/file_name_SUITE.erl
@@ -19,7 +19,7 @@
%% %CopyrightEnd%
%%
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
%%
@@ -79,14 +79,14 @@
init_per_testcase(_Func, Config) ->
- Dog = test_server:timetrap(test_server:seconds(60)),
- [{watchdog,Dog}|Config].
+ Config.
-end_per_testcase(_Func, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog).
+end_per_testcase(_Func, _Config) ->
+ ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[normal, icky, very_icky, normalize, home_dir].
@@ -101,19 +101,16 @@ end_per_suite(_Config) ->
ok.
init_per_group(_GroupName, Config) ->
- Config.
+ Config.
end_per_group(_GroupName, Config) ->
- Config.
+ Config.
-home_dir(suite) ->
- [];
-home_dir(doc) ->
- ["Check that Erlang can be started with unicode named home directory"];
+%% Check that Erlang can be started with unicode named home directory.
home_dir(Config) when is_list(Config) ->
try
Name=[960,945,964,961,953,954],
- Priv = ?config(priv_dir, Config),
+ Priv = proplists:get_value(priv_dir, Config),
UniMode = file:native_name_encoding() =/= latin1,
if
not UniMode ->
@@ -154,45 +151,39 @@ home_dir(Config) when is_list(Config) ->
{skipped,"Runs only on Unix/Windows"}
end.
-normalize(suite) ->
- [];
-normalize(doc) ->
- ["Check that filename normalization works"];
+%% Check that filename normalization works.
normalize(Config) when is_list(Config) ->
- random:seed({1290,431421,830412}),
+ rand:seed(exsplus, {1290,431421,830412}),
try
- ?line UniMode = file:native_name_encoding() =/= latin1,
+ UniMode = file:native_name_encoding() =/= latin1,
if
not UniMode ->
throw(need_unicode_mode);
true ->
ok
end,
- ?line Pairs = [rand_comp_decomp(200) || _ <- lists:seq(1,1000)],
+ Pairs = [rand_comp_decomp(200) || _ <- lists:seq(1,1000)],
case os:type() of
{unix,darwin} ->
- ?line [ true = (A =:= prim_file:internal_native2name(B)) ||
+ [ true = (A =:= prim_file:internal_native2name(B)) ||
{A,B} <- Pairs ];
_ ->
ok
end,
- ?line [ true = (A =:= prim_file:internal_normalize_utf8(B)) ||
- {A,B} <- Pairs ]
-
+ [ true = (A =:= prim_file:internal_normalize_utf8(B)) ||
+ {A,B} <- Pairs ]
+
catch
throw:need_unicode_mode ->
io:format("Sorry, can only run in unicode mode.~n"),
{skipped,"VM needs to be started in Unicode filename mode"}
end.
-
-normal(suite) ->
- [];
-normal(doc) ->
- "Check file operations on normal file names regardless of unicode mode";
+
+%% Check file operations on normal file names regardless of unicode mode.
normal(Config) when is_list(Config) ->
{ok,Dir} = file:get_cwd(),
try
- Priv = ?config(priv_dir, Config),
+ Priv = proplists:get_value(priv_dir, Config),
file:set_cwd(Priv),
put(file_module,prim_file),
ok = check_normal(prim_file),
@@ -204,12 +195,9 @@ normal(Config) when is_list(Config) ->
after
file:set_cwd(Dir)
end.
-
-icky(suite) ->
- [];
-icky(doc) ->
- "Check file operations on normal file names regardless of unicode mode";
+
+%% Check file operations on normal file names regardless of unicode mode.
icky(Config) when is_list(Config) ->
case hopeless_darwin() of
true ->
@@ -217,7 +205,7 @@ icky(Config) when is_list(Config) ->
false ->
{ok,Dir} = file:get_cwd(),
try
- Priv = ?config(priv_dir, Config),
+ Priv = proplists:get_value(priv_dir, Config),
file:set_cwd(Priv),
put(file_module,prim_file),
ok = check_icky(prim_file),
@@ -230,10 +218,7 @@ icky(Config) when is_list(Config) ->
file:set_cwd(Dir)
end
end.
-very_icky(suite) ->
- [];
-very_icky(doc) ->
- "Check file operations on normal file names regardless of unicode mode";
+%% Check file operations on normal file names regardless of unicode mode.
very_icky(Config) when is_list(Config) ->
case hopeless_darwin() of
true ->
@@ -241,7 +226,7 @@ very_icky(Config) when is_list(Config) ->
false ->
{ok,Dir} = file:get_cwd(),
try
- Priv = ?config(priv_dir, Config),
+ Priv = proplists:get_value(priv_dir, Config),
file:set_cwd(Priv),
put(file_module,prim_file),
case check_very_icky(prim_file) of
@@ -259,78 +244,77 @@ very_icky(Config) when is_list(Config) ->
file:set_cwd(Dir)
end
end.
-
+
check_normal(Mod) ->
{ok,Dir} = Mod:get_cwd(),
try
- ?line make_normal_dir(Mod),
- ?line {ok, L0} = Mod:list_dir("."),
- ?line L1 = lists:sort(L0),
- %erlang:display(L1),
- ?line L1 = lists:sort(list(normal_dir())),
- ?line {ok,D2} = Mod:get_cwd(),
- ?line true = is_list(D2),
- ?line case Mod:altname("fil1") of
+ make_normal_dir(Mod),
+ {ok, L0} = Mod:list_dir("."),
+ L1 = lists:sort(L0),
+ L1 = lists:sort(list(normal_dir())),
+ {ok,D2} = Mod:get_cwd(),
+ true = is_list(D2),
+ case Mod:altname("fil1") of
{error,enotsup} ->
ok;
{ok,LLL} when is_list(LLL) ->
ok
end,
- ?line [ true = is_list(El) || El <- L1],
- ?line Syms = [ {S,Targ,list_to_binary(get_data(Targ,normal_dir()))}
+ [ true = is_list(El) || El <- L1],
+ Syms = [ {S,Targ,list_to_binary(get_data(Targ,normal_dir()))}
|| {T,S,Targ} <- normal_dir(), T =:= symlink ],
- ?line [ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ],
- ?line [ {ok, Targ} = fixlink(Mod:read_link(SymL)) || {SymL,Targ,_} <- Syms ],
- ?line chk_cre_dir(Mod,[{directory,"temp_dir",normal_dir()}]),
- ?line {ok,BeginAt} = Mod:get_cwd(),
- ?line true = is_list(BeginAt),
- ?line {error,enoent} = Mod:set_cwd("tmp_dir"),
- ?line ok = Mod:set_cwd("temp_dir"),
- ?line {ok, NowAt} = Mod:get_cwd(),
- ?line true = BeginAt =/= NowAt,
- ?line ok = Mod:set_cwd(".."),
- ?line {ok,BeginAt} = Mod:get_cwd(),
- ?line rm_r(Mod,"temp_dir"),
- ?line true = is_list(Dir),
- ?line [ true = is_list(FN) || FN <- L0 ],
+ [ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ],
+ [ {ok, Targ} = fixlink(Mod:read_link(SymL)) || {SymL,Targ,_} <- Syms ],
+ chk_cre_dir(Mod,[{directory,"temp_dir",normal_dir()}]),
+ {ok,BeginAt} = Mod:get_cwd(),
+ true = is_list(BeginAt),
+ {error,enoent} = Mod:set_cwd("tmp_dir"),
+ ok = Mod:set_cwd("temp_dir"),
+ {ok, NowAt} = Mod:get_cwd(),
+ true = BeginAt =/= NowAt,
+ ok = Mod:set_cwd(".."),
+ {ok,BeginAt} = Mod:get_cwd(),
+ rm_r(Mod,"temp_dir"),
+ true = is_list(Dir),
+ [ true = is_list(FN) || FN <- L0 ],
case has_links() of
true ->
- ?line ok = Mod:make_link("fil1","nisse"),
- ?line {ok, <<"fil1">>} = Mod:read_file("nisse"),
- ?line {ok, #file_info{type = regular}} = Mod:read_link_info("nisse"),
- ?line ok = Mod:delete("nisse"),
- ?line {ok, <<"fil1">>} = Mod:read_file("fil1"),
- ?line {error,enoent} = Mod:read_file("nisse"),
- ?line {error,enoent} = Mod:read_link_info("nisse");
+ ok = Mod:make_link("fil1","nisse"),
+ {ok, <<"fil1">>} = Mod:read_file("nisse"),
+ {ok, #file_info{type = regular}} = Mod:read_link_info("nisse"),
+ ok = Mod:delete("nisse"),
+ {ok, <<"fil1">>} = Mod:read_file("fil1"),
+ {error,enoent} = Mod:read_file("nisse"),
+ {error,enoent} = Mod:read_link_info("nisse");
false ->
ok
end,
- ?line [ begin
- ?line {ok, FD} = Mod:open(Name,[read]),
- ?line {ok, Content} = Mod:read(FD,1024),
- ?line ok = file:close(FD)
+ [ begin
+ {ok, FD} = Mod:open(Name,[read]),
+ {ok, Content} = Mod:read(FD,1024),
+ ok = file:close(FD)
end || {regular,Name,Content} <- normal_dir() ],
- ?line [ begin
- ?line {ok, FD} = Mod:open(Name,[read,binary]),
- ?line BC = list_to_binary(Content),
- ?line {ok, BC} = Mod:read(FD,1024),
- ?line ok = file:close(FD)
+ [ begin
+ {ok, FD} = Mod:open(Name,[read,binary]),
+ BC = list_to_binary(Content),
+ {ok, BC} = Mod:read(FD,1024),
+ ok = file:close(FD)
end || {regular,Name,Content} <- normal_dir() ],
- ?line Mod:rename("fil1","tmp_fil1"),
- ?line {ok, <<"fil1">>} = Mod:read_file("tmp_fil1"),
- ?line {error,enoent} = Mod:read_file("fil1"),
- ?line Mod:rename("tmp_fil1","fil1"),
- ?line {ok, <<"fil1">>} = Mod:read_file("fil1"),
- ?line {error,enoent} = Mod:read_file("tmp_fil1"),
- ?line {ok,FI} = Mod:read_file_info("fil1"),
- ?line NewMode = FI#file_info.mode band (bnot 8#333),
- ?line NewMode2 = NewMode bor 8#222,
- ?line true = NewMode2 =/= NewMode,
- ?line ok = Mod:write_file_info("fil1",FI#file_info{mode = NewMode}),
- ?line {ok,#file_info{mode = NewMode}} = Mod:read_file_info("fil1"),
- ?line ok = Mod:write_file_info("fil1",FI#file_info{mode = NewMode2}),
- ?line {ok,#file_info{mode = NewMode2}} = Mod:read_file_info("fil1"),
+ Mod:rename("fil1","tmp_fil1"),
+ {ok, <<"fil1">>} = Mod:read_file("tmp_fil1"),
+ {error,enoent} = Mod:read_file("fil1"),
+ Mod:rename("tmp_fil1","fil1"),
+ {ok, <<"fil1">>} = Mod:read_file("fil1"),
+ {error,enoent} = Mod:read_file("tmp_fil1"),
+ {ok,FI} = Mod:read_file_info("fil1"),
+ NewMode = FI#file_info.mode band (bnot 8#333),
+ NewMode2 = NewMode bor 8#222,
+ true = NewMode2 =/= NewMode,
+ ok = Mod:write_file_info("fil1",FI#file_info{mode = NewMode}),
+ {ok,#file_info{mode = NewMode}} = Mod:read_file_info("fil1"),
+ ok = Mod:write_file_info("fil1",FI#file_info{mode = NewMode2}),
+ {ok,#file_info{mode = NewMode2}} = Mod:read_file_info("fil1"),
ok
after
case Mod:read_file_info("fil1") of
@@ -347,129 +331,129 @@ check_normal(Mod) ->
check_icky(Mod) ->
{ok,Dir} = Mod:get_cwd(),
try
- ?line true=(length("åäö") =:= 3),
- ?line UniMode = file:native_name_encoding() =/= latin1,
- ?line make_icky_dir(Mod),
+ true=(length("åäö") =:= 3),
+ UniMode = file:native_name_encoding() =/= latin1,
+ make_icky_dir(Mod),
{ok, L0} = Mod:list_dir_all("."),
- ?line L1 = lists:sort(L0),
+ L1 = lists:sort(L0),
io:format("~p~n~p~n~n",[L1,lists:sort(list(icky_dir()))]),
- ?line L1 = lists:sort(convlist(list(icky_dir()))),
- ?line {ok,D2} = Mod:get_cwd(),
- ?line true = is_list(D2),
-%% Altname only on windows, and there are no non native filenames there
-%% ?line case Mod:altname("fil1") of
-%% {error,enotsup} ->
-%% ok;
-%% {ok,LLL} when is_list(LLL) ->
-%% ok
-%% end,
- ?line [ true = ((is_list(El) or (UniMode and is_binary(El)))) || El <- L1],
- ?line Syms = [ {S,conv(Targ),list_to_binary(get_data(Targ,icky_dir()))}
+ L1 = lists:sort(convlist(list(icky_dir()))),
+ {ok,D2} = Mod:get_cwd(),
+ true = is_list(D2),
+ %% Altname only on windows, and there are no non native filenames there
+ %% case Mod:altname("fil1") of
+ %% {error,enotsup} ->
+ %% ok;
+ %% {ok,LLL} when is_list(LLL) ->
+ %% ok
+ %% end,
+ [ true = ((is_list(El) or (UniMode and is_binary(El)))) || El <- L1],
+ Syms = [ {S,conv(Targ),list_to_binary(get_data(Targ,icky_dir()))}
|| {T,S,Targ} <- icky_dir(), T =:= symlink ],
- ?line [ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ],
+ [ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ],
[ {ok, Targ} = fixlink(Mod:read_link_all(SymL)) ||
{SymL,Targ,_} <- Syms ],
- ?line chk_cre_dir(Mod,[{directory,"åäö_dir",icky_dir()}]),
- ?line {ok,BeginAt} = Mod:get_cwd(),
- ?line true = is_list(BeginAt),
- ?line {error,enoent} = Mod:set_cwd("åä_dir"),
- ?line ok = Mod:set_cwd("åäö_dir"),
- ?line {ok, NowAt} = Mod:get_cwd(),
- ?line true = is_list(NowAt),
- ?line true = BeginAt =/= NowAt,
- ?line ok = Mod:set_cwd(".."),
- ?line {ok,BeginAt} = Mod:get_cwd(),
- ?line rm_r2(Mod,"åäö_dir"),
+ chk_cre_dir(Mod,[{directory,"åäö_dir",icky_dir()}]),
+ {ok,BeginAt} = Mod:get_cwd(),
+ true = is_list(BeginAt),
+ {error,enoent} = Mod:set_cwd("åä_dir"),
+ ok = Mod:set_cwd("åäö_dir"),
+ {ok, NowAt} = Mod:get_cwd(),
+ true = is_list(NowAt),
+ true = BeginAt =/= NowAt,
+ ok = Mod:set_cwd(".."),
+ {ok,BeginAt} = Mod:get_cwd(),
+ rm_r2(Mod,"åäö_dir"),
{OS,_} = os:type(),
- % Check that treat_icky really converts to the same as the OS
+ %% Check that treat_icky really converts to the same as the OS
case UniMode of
true ->
- ?line chk_cre_dir(Mod,[{directory,"åäö_dir",[]}]),
- ?line ok = Mod:set_cwd("åäö_dir"),
- ?line ok = Mod:write_file(<<"ååå">>,<<"hello">>),
- ?line Treated = treat_icky(<<"ååå">>),
+ chk_cre_dir(Mod,[{directory,"åäö_dir",[]}]),
+ ok = Mod:set_cwd("åäö_dir"),
+ ok = Mod:write_file(<<"ååå">>,<<"hello">>),
+ Treated = treat_icky(<<"ååå">>),
{ok,[Treated]} = Mod:list_dir_all("."),
- ?line ok = Mod:delete(<<"ååå">>),
- ?line {ok,[]} = Mod:list_dir("."),
- ?line ok = Mod:set_cwd(".."),
- ?line rm_r2(Mod,"åäö_dir");
+ ok = Mod:delete(<<"ååå">>),
+ {ok,[]} = Mod:list_dir("."),
+ ok = Mod:set_cwd(".."),
+ rm_r2(Mod,"åäö_dir");
false ->
ok
end,
- ?line chk_cre_dir(Mod,[{directory,treat_icky(<<"åäö_dir">>),icky_dir()}]),
+ chk_cre_dir(Mod,[{directory,treat_icky(<<"åäö_dir">>),icky_dir()}]),
if
UniMode and (OS =/= win32) ->
- ?line {error,enoent} = Mod:set_cwd("åäö_dir");
+ {error,enoent} = Mod:set_cwd("åäö_dir");
true ->
ok
end,
- ?line {ok,BeginAt} = Mod:get_cwd(),
+ {ok,BeginAt} = Mod:get_cwd(),
case has_links() of
true ->
- ?line ok = Mod:make_link("fil1","nisseö"),
- ?line {ok, <<"fil1">>} = Mod:read_file("nisseö"),
- ?line {ok, #file_info{type = regular}} = Mod:read_link_info("nisseö"),
- ?line ok = Mod:delete("nisseö"),
- ?line ok = Mod:make_link("fil1",treat_icky(<<"nisseö">>)),
- ?line {ok, <<"fil1">>} = Mod:read_file(treat_icky(<<"nisseö">>)),
- ?line {ok, #file_info{type = regular}} = Mod:read_link_info(treat_icky(<<"nisseö">>)),
- ?line ok = Mod:delete(treat_icky(<<"nisseö">>)),
- ?line {ok, <<"fil1">>} = Mod:read_file("fil1"),
- ?line {error,enoent} = Mod:read_file("nisseö"),
- ?line {error,enoent} = Mod:read_link_info("nisseö"),
- ?line {error,enoent} = Mod:read_file(treat_icky(<<"nisseö">>)),
- ?line {error,enoent} = Mod:read_link_info(treat_icky(<<"nisseö">>));
+ ok = Mod:make_link("fil1","nisseö"),
+ {ok, <<"fil1">>} = Mod:read_file("nisseö"),
+ {ok, #file_info{type = regular}} = Mod:read_link_info("nisseö"),
+ ok = Mod:delete("nisseö"),
+ ok = Mod:make_link("fil1",treat_icky(<<"nisseö">>)),
+ {ok, <<"fil1">>} = Mod:read_file(treat_icky(<<"nisseö">>)),
+ {ok, #file_info{type = regular}} = Mod:read_link_info(treat_icky(<<"nisseö">>)),
+ ok = Mod:delete(treat_icky(<<"nisseö">>)),
+ {ok, <<"fil1">>} = Mod:read_file("fil1"),
+ {error,enoent} = Mod:read_file("nisseö"),
+ {error,enoent} = Mod:read_link_info("nisseö"),
+ {error,enoent} = Mod:read_file(treat_icky(<<"nisseö">>)),
+ {error,enoent} = Mod:read_link_info(treat_icky(<<"nisseö">>));
false ->
ok
end,
- ?line [ begin
- ?line {ok, FD} = Mod:open(Name,[read]),
- ?line {ok, Content} = Mod:read(FD,1024),
- ?line ok = file:close(FD)
+ [ begin
+ {ok, FD} = Mod:open(Name,[read]),
+ {ok, Content} = Mod:read(FD,1024),
+ ok = file:close(FD)
end || {regular,Name,Content} <- icky_dir() ],
- ?line [ begin
- ?line {ok, FD} = Mod:open(Name,[read,binary]),
- ?line BC = list_to_binary([Content]),
- ?line {ok, BC} = Mod:read(FD,1024),
- ?line ok = file:close(FD)
+ [ begin
+ {ok, FD} = Mod:open(Name,[read,binary]),
+ BC = list_to_binary([Content]),
+ {ok, BC} = Mod:read(FD,1024),
+ ok = file:close(FD)
end || {regular,Name,Content} <- icky_dir() ],
- ?line Mod:rename("åäö2","åäö_fil1"),
- ?line {ok, <<"åäö2">>} = Mod:read_file("åäö_fil1"),
- ?line {error,enoent} = Mod:read_file("åäö2"),
- ?line Mod:rename("åäö_fil1","åäö2"),
- ?line {ok, <<"åäö2">>} = Mod:read_file("åäö2"),
- ?line {error,enoent} = Mod:read_file("åäö_fil1"),
+ Mod:rename("åäö2","åäö_fil1"),
+ {ok, <<"åäö2">>} = Mod:read_file("åäö_fil1"),
+ {error,enoent} = Mod:read_file("åäö2"),
+ Mod:rename("åäö_fil1","åäö2"),
+ {ok, <<"åäö2">>} = Mod:read_file("åäö2"),
+ {error,enoent} = Mod:read_file("åäö_fil1"),
- ?line Mod:rename("åäö2",treat_icky(<<"åäö_fil1">>)),
- ?line {ok, <<"åäö2">>} = Mod:read_file(treat_icky(<<"åäö_fil1">>)),
+ Mod:rename("åäö2",treat_icky(<<"åäö_fil1">>)),
+ {ok, <<"åäö2">>} = Mod:read_file(treat_icky(<<"åäö_fil1">>)),
if
UniMode and (OS =/= win32) ->
{error,enoent} = Mod:read_file("åäö_fil1");
true ->
ok
end,
- ?line {error,enoent} = Mod:read_file("åäö2"),
- ?line Mod:rename(treat_icky(<<"åäö_fil1">>),"åäö2"),
- ?line {ok, <<"åäö2">>} = Mod:read_file("åäö2"),
- ?line {error,enoent} = Mod:read_file("åäö_fil1"),
- ?line {error,enoent} = Mod:read_file(treat_icky(<<"åäö_fil1">>)),
+ {error,enoent} = Mod:read_file("åäö2"),
+ Mod:rename(treat_icky(<<"åäö_fil1">>),"åäö2"),
+ {ok, <<"åäö2">>} = Mod:read_file("åäö2"),
+ {error,enoent} = Mod:read_file("åäö_fil1"),
+ {error,enoent} = Mod:read_file(treat_icky(<<"åäö_fil1">>)),
- ?line {ok,FI} = Mod:read_file_info("åäö2"),
- ?line NewMode = FI#file_info.mode band (bnot 8#333),
- ?line NewMode2 = NewMode bor 8#222,
- ?line true = NewMode2 =/= NewMode,
- ?line ok = Mod:write_file_info("åäö2",FI#file_info{mode = NewMode}),
- ?line {ok,#file_info{mode = NewMode}} = Mod:read_file_info("åäö2"),
- ?line ok = Mod:write_file_info("åäö2",FI#file_info{mode = NewMode2}),
- ?line {ok,#file_info{mode = NewMode2}} = Mod:read_file_info("åäö2"),
+ {ok,FI} = Mod:read_file_info("åäö2"),
+ NewMode = FI#file_info.mode band (bnot 8#333),
+ NewMode2 = NewMode bor 8#222,
+ true = NewMode2 =/= NewMode,
+ ok = Mod:write_file_info("åäö2",FI#file_info{mode = NewMode}),
+ {ok,#file_info{mode = NewMode}} = Mod:read_file_info("åäö2"),
+ ok = Mod:write_file_info("åäö2",FI#file_info{mode = NewMode2}),
+ {ok,#file_info{mode = NewMode2}} = Mod:read_file_info("åäö2"),
- ?line {ok,FII} = Mod:read_file_info(treat_icky(<<"åäö5">>)),
- ?line true = NewMode2 =/= NewMode,
- ?line ok = Mod:write_file_info(treat_icky(<<"åäö5">>),FII#file_info{mode = NewMode}),
- ?line {ok,#file_info{mode = NewMode}} = Mod:read_file_info(treat_icky(<<"åäö5">>)),
- ?line ok = Mod:write_file_info(<<"åäö5">>,FII#file_info{mode = NewMode2}),
- ?line {ok,#file_info{mode = NewMode2}} = Mod:read_file_info(treat_icky(<<"åäö5">>)),
+ {ok,FII} = Mod:read_file_info(treat_icky(<<"åäö5">>)),
+ true = NewMode2 =/= NewMode,
+ ok = Mod:write_file_info(treat_icky(<<"åäö5">>),FII#file_info{mode = NewMode}),
+ {ok,#file_info{mode = NewMode}} = Mod:read_file_info(treat_icky(<<"åäö5">>)),
+ ok = Mod:write_file_info(<<"åäö5">>,FII#file_info{mode = NewMode2}),
+ {ok,#file_info{mode = NewMode2}} = Mod:read_file_info(treat_icky(<<"åäö5">>)),
ok
after
Mod:set_cwd(Dir),
@@ -479,90 +463,90 @@ check_icky(Mod) ->
check_very_icky(Mod) ->
{ok,Dir} = Mod:get_cwd(),
try
- ?line true=(length("åäö") =:= 3),
- ?line UniMode = file:native_name_encoding() =/= latin1,
+ true=(length("åäö") =:= 3),
+ UniMode = file:native_name_encoding() =/= latin1,
if
not UniMode ->
throw(need_unicode_mode);
true ->
ok
end,
- ?line make_very_icky_dir(Mod),
+ make_very_icky_dir(Mod),
{ok, L0} = Mod:list_dir_all("."),
- ?line L1 = lists:sort(L0),
- ?line L1 = lists:sort(convlist(list(very_icky_dir()))),
- ?line {ok,D2} = Mod:get_cwd(),
- ?line true = is_list(D2),
- ?line [ true = ((is_list(El) or is_binary(El))) || El <- L1],
- ?line Syms = [ {S,conv(Targ),list_to_binary(get_data(Targ,very_icky_dir()))}
+ L1 = lists:sort(L0),
+ L1 = lists:sort(convlist(list(very_icky_dir()))),
+ {ok,D2} = Mod:get_cwd(),
+ true = is_list(D2),
+ [ true = ((is_list(El) or is_binary(El))) || El <- L1],
+ Syms = [ {S,conv(Targ),list_to_binary(get_data(Targ,very_icky_dir()))}
|| {T,S,Targ} <- very_icky_dir(), T =:= symlink ],
- ?line [ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ],
- ?line [ {ok, Targ} = fixlink(Mod:read_link_all(SymL)) ||
- {SymL,Targ,_} <- Syms ],
- ?line chk_cre_dir(Mod,[{directory,[1088,1079,1091]++"_dir",very_icky_dir()}]),
- ?line {ok,BeginAt} = Mod:get_cwd(),
- ?line true = is_list(BeginAt),
- ?line {error,enoent} = Mod:set_cwd("åä_dir"),
- ?line ok = Mod:set_cwd([1088,1079,1091]++"_dir"),
- ?line {ok, NowAt} = Mod:get_cwd(),
- ?line true = is_list(NowAt),
- ?line true = BeginAt =/= NowAt,
- ?line ok = Mod:set_cwd(".."),
- ?line {ok,BeginAt} = Mod:get_cwd(),
- ?line rm_r2(Mod,[1088,1079,1091]++"_dir"),
+ [ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ],
+ [ {ok, Targ} = fixlink(Mod:read_link_all(SymL)) ||
+ {SymL,Targ,_} <- Syms ],
+ chk_cre_dir(Mod,[{directory,[1088,1079,1091]++"_dir",very_icky_dir()}]),
+ {ok,BeginAt} = Mod:get_cwd(),
+ true = is_list(BeginAt),
+ {error,enoent} = Mod:set_cwd("åä_dir"),
+ ok = Mod:set_cwd([1088,1079,1091]++"_dir"),
+ {ok, NowAt} = Mod:get_cwd(),
+ true = is_list(NowAt),
+ true = BeginAt =/= NowAt,
+ ok = Mod:set_cwd(".."),
+ {ok,BeginAt} = Mod:get_cwd(),
+ rm_r2(Mod,[1088,1079,1091]++"_dir"),
case has_links() of
true ->
- ?line ok = Mod:make_link("fil1","nisse"++[1088,1079,1091]),
- ?line {ok, <<"fil1">>} =
+ ok = Mod:make_link("fil1","nisse"++[1088,1079,1091]),
+ {ok, <<"fil1">>} =
Mod:read_file("nisse"++[1088,1079,1091]),
- ?line {ok, #file_info{type = regular}} =
+ {ok, #file_info{type = regular}} =
Mod:read_link_info("nisse"++[1088,1079,1091]),
- ?line ok = Mod:delete("nisse"++[1088,1079,1091]),
- ?line ok = Mod:make_link("fil1",<<"nisseö">>),
- ?line {ok, <<"fil1">>} = Mod:read_file(<<"nisseö">>),
- ?line {ok, #file_info{type = regular}} =
+ ok = Mod:delete("nisse"++[1088,1079,1091]),
+ ok = Mod:make_link("fil1",<<"nisseö">>),
+ {ok, <<"fil1">>} = Mod:read_file(<<"nisseö">>),
+ {ok, #file_info{type = regular}} =
Mod:read_link_info(<<"nisseö">>),
- ?line ok = Mod:delete(<<"nisseö">>),
- ?line {ok, <<"fil1">>} = Mod:read_file("fil1"),
- ?line {error,enoent} = Mod:read_file("nisse"++[1088,1079,1091]),
- ?line {error,enoent} = Mod:read_link_info("nisse"++[1088,1079,1091]),
- ?line {error,enoent} = Mod:read_file(<<"nisseö">>),
- ?line {error,enoent} = Mod:read_link_info(<<"nisseö">>);
+ ok = Mod:delete(<<"nisseö">>),
+ {ok, <<"fil1">>} = Mod:read_file("fil1"),
+ {error,enoent} = Mod:read_file("nisse"++[1088,1079,1091]),
+ {error,enoent} = Mod:read_link_info("nisse"++[1088,1079,1091]),
+ {error,enoent} = Mod:read_file(<<"nisseö">>),
+ {error,enoent} = Mod:read_link_info(<<"nisseö">>);
false ->
ok
end,
- ?line [ begin
- ?line {ok, FD} = Mod:open(Name,[read]),
- ?line {ok, Content} = Mod:read(FD,1024),
- ?line ok = file:close(FD)
+ [ begin
+ {ok, FD} = Mod:open(Name,[read]),
+ {ok, Content} = Mod:read(FD,1024),
+ ok = file:close(FD)
end || {regular,Name,Content} <- very_icky_dir() ],
- ?line [ begin
- ?line {ok, FD} = Mod:open(Name,[read,binary]),
- ?line BC = list_to_binary([Content]),
- ?line {ok, BC} = Mod:read(FD,1024),
- ?line ok = file:close(FD)
+ [ begin
+ {ok, FD} = Mod:open(Name,[read,binary]),
+ BC = list_to_binary([Content]),
+ {ok, BC} = Mod:read(FD,1024),
+ ok = file:close(FD)
end || {regular,Name,Content} <- very_icky_dir() ],
- ?line Mod:rename([956,965,963,954,959,49],
- [956,965,963,954,959]++"_fil1"),
- ?line {ok, <<"åäö2">>} = Mod:read_file([956,965,963,954,959]++"_fil1"),
- ?line {error,enoent} = Mod:read_file([956,965,963,954,959,49]),
- ?line Mod:rename([956,965,963,954,959]++"_fil1",[956,965,963,954,959,49]),
- ?line {ok, <<"åäö2">>} = Mod:read_file([956,965,963,954,959,49]),
- ?line {error,enoent} = Mod:read_file([956,965,963,954,959]++"_fil1"),
+ Mod:rename([956,965,963,954,959,49],
+ [956,965,963,954,959]++"_fil1"),
+ {ok, <<"åäö2">>} = Mod:read_file([956,965,963,954,959]++"_fil1"),
+ {error,enoent} = Mod:read_file([956,965,963,954,959,49]),
+ Mod:rename([956,965,963,954,959]++"_fil1",[956,965,963,954,959,49]),
+ {ok, <<"åäö2">>} = Mod:read_file([956,965,963,954,959,49]),
+ {error,enoent} = Mod:read_file([956,965,963,954,959]++"_fil1"),
- ?line {ok,FI} = Mod:read_file_info([956,965,963,954,959,49]),
- ?line NewMode = FI#file_info.mode band (bnot 8#333),
- ?line NewMode2 = NewMode bor 8#222,
- ?line true = NewMode2 =/= NewMode,
- ?line ok = Mod:write_file_info([956,965,963,954,959,49],
- FI#file_info{mode = NewMode}),
- ?line {ok,#file_info{mode = NewMode}} =
- Mod:read_file_info([956,965,963,954,959,49]),
- ?line ok = Mod:write_file_info([956,965,963,954,959,49],
- FI#file_info{mode = NewMode2}),
- ?line {ok,#file_info{mode = NewMode2}} =
- Mod:read_file_info([956,965,963,954,959,49]),
+ {ok,FI} = Mod:read_file_info([956,965,963,954,959,49]),
+ NewMode = FI#file_info.mode band (bnot 8#333),
+ NewMode2 = NewMode bor 8#222,
+ true = NewMode2 =/= NewMode,
+ ok = Mod:write_file_info([956,965,963,954,959,49],
+ FI#file_info{mode = NewMode}),
+ {ok,#file_info{mode = NewMode}} =
+ Mod:read_file_info([956,965,963,954,959,49]),
+ ok = Mod:write_file_info([956,965,963,954,959,49],
+ FI#file_info{mode = NewMode2}),
+ {ok,#file_info{mode = NewMode2}} =
+ Mod:read_file_info([956,965,963,954,959,49]),
ok
catch
throw:need_unicode_mode ->
@@ -592,7 +576,6 @@ rm_rf(Mod,Dir) ->
end.
rm_r(Mod,Dir) ->
- %erlang:display({rm_r,Dir}),
case Mod:read_link_info(Dir) of
{ok, #file_info{type = directory}} ->
{ok,#file_info{type = directory}} = Mod:read_file_info(Dir),
@@ -610,7 +593,7 @@ rm_r(Mod,Dir) ->
end.
%% For icky test, allow binaries sometimes
rm_r2(Mod,Dir) ->
- %erlang:display({rm_r2,Dir}),
+ %% erlang:display({rm_r2,Dir}),
case Mod:read_link_info(Dir) of
{ok, #file_info{type = directory}} ->
{ok,#file_info{type = directory}} = Mod:read_file_info(Dir),
@@ -630,7 +613,7 @@ rm_r2(Mod,Dir) ->
chk_cre_dir(_,[]) ->
ok;
chk_cre_dir(Mod,[{regular,Name,Content}|T]) ->
- %io:format("~p~n",[Name]),
+ %% io:format("~p~n",[Name]),
ok = Mod:write_file(Name,Content),
chk_cre_dir(Mod,T);
chk_cre_dir(Mod,[{link,Name,Target}|T]) ->
@@ -641,12 +624,12 @@ chk_cre_dir(Mod,[{symlink,Name,Target}|T]) ->
chk_cre_dir(Mod,T);
chk_cre_dir(Mod,[{directory,Name,Content}|T]) ->
ok = Mod:make_dir(Name),
- %io:format("Content = ~p~n",[Content]),
+ %% io:format("Content = ~p~n",[Content]),
Content2 = [{Ty,filename:join(Name,N),case Ty of link -> filename:join(Name,C); _ -> C end} || {Ty,N,C} <- Content ],
- %io:format("Content2 = ~p~n",[Content2]),
+ %% io:format("Content2 = ~p~n",[Content2]),
chk_cre_dir(Mod,Content2),
chk_cre_dir(Mod,T).
-
+
has_links() ->
case os:type() of
{win32,_} ->
@@ -676,7 +659,7 @@ make_normal_dir(Mod) ->
Mod:make_dir("subdir"),
Mod:write_file(filename:join("subdir","subfil1"),"subfil1"),
ok.
-
+
normal_dir() ->
[{regular,"fil1","fil1"},
{regular,"fil2","fil2"}] ++
@@ -731,12 +714,12 @@ icky_dir() ->
[]
end ++
[{regular,treat_icky(<<"åäö5">>),"åäö5"}] ++
- case has_links() of
- true ->
- [{symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)}];
- false ->
- []
- end ++
+ case has_links() of
+ true ->
+ [{symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)}];
+ false ->
+ []
+ end ++
[{directory,treat_icky(<<"åäösubdir2">>),
[{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"},
{regular,"åäösubfil3","åäösubfil13"}]},
@@ -760,18 +743,18 @@ very_icky_dir() ->
false ->
[]
end ++
- [{regular,treat_icky(<<"åäö5">>),"åäö5"}] ++
+ [{regular,treat_icky(<<"åäö5">>),"åäö5"}] ++
case has_links() of
true ->
[{symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)}];
false ->
[]
end ++
- [{directory,treat_icky(<<"åäösubdir2">>),
- [{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"},
- {regular,"åäösubfil3","åäösubfil13"}]},
- {directory,[956,965,963,954,959]++"subdir1",
- [{regular,[956,965,963,954,959]++"subfil1","åäösubfil1"}]}].
+ [{directory,treat_icky(<<"åäösubdir2">>),
+ [{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"},
+ {regular,"åäösubfil3","åäösubfil13"}]},
+ {directory,[956,965,963,954,959]++"subdir1",
+ [{regular,[956,965,963,954,959]++"subfil1","åäösubfil1"}]}].
%% Some OS'es simply do not allow non UTF8 filenames
treat_icky(Bin) ->
@@ -784,7 +767,7 @@ treat_icky(Bin) ->
Bin
end.
-% Handle windows having absolute soft link targets.
+%% Handle windows having absolute soft link targets.
fixlink({ok,Link}) ->
case os:type() of
{win32,_} ->
@@ -811,7 +794,7 @@ list([]) ->
[];
list([{_,Name,_} | T]) ->
[Name | list(T)].
-
+
get_data(FN,List) ->
case lists:keysearch(FN,2,List) of
@@ -827,7 +810,7 @@ get_data(FN,List) ->
convlist(L) ->
convlist(file:native_name_encoding(),L).
convlist(latin1,[Bin|T]) when is_binary(Bin) ->
- %erlang:display('Convert...'),
+ %% erlang:display('Convert...'),
[binary_to_list(Bin)| convlist(latin1,T)];
convlist(Any,[H|T]) ->
[H|convlist(Any,T)];
@@ -845,17 +828,17 @@ conv(L) ->
rand_comp_decomp(Max) ->
- N = random:uniform(Max),
+ N = rand:uniform(Max),
L = [ rand_decomp() || _ <- lists:seq(1,N) ],
LC = [ A || {A,_} <- L],
LD = lists:flatten([B || {_,B} <- L]),
LB = unicode:characters_to_binary(LD,unicode,utf8),
{LC,LB}.
-
+
rand_decomp() ->
BT = bigtup(),
SZ = tuple_size(BT),
- element(random:uniform(SZ),BT).
+ element(rand:uniform(SZ),BT).
bigtup() ->
{{192,[65,768]},
{200,[69,768]},
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index 91a57d3290..8e53da210e 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(gen_sctp_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/inet_sctp.hrl").
%%-compile(export_all).
@@ -42,7 +42,9 @@
names_unihoming_ipv4/1, names_unihoming_ipv6/1,
names_multihoming_ipv4/1, names_multihoming_ipv6/1]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[basic, api_open_close, api_listen, api_connect_init,
@@ -81,48 +83,40 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_Func, Config) ->
- Dog = test_server:timetrap(test_server:seconds(15)),
- [{watchdog, Dog}|Config].
-end_per_testcase(_Func, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog).
+ Config.
+end_per_testcase(_Func, _Config) ->
+ ok.
-define(LOGVAR(Var), begin io:format(??Var" = ~p~n", [Var]) end).
-basic(doc) ->
- "Hello world";
-basic(suite) ->
- [];
+%% Hello world.
basic(Config) when is_list(Config) ->
- ?line {ok,S} = gen_sctp:open(),
- ?line ok = gen_sctp:close(S),
+ {ok,S} = gen_sctp:open(),
+ ok = gen_sctp:close(S),
ok.
-xfer_min(doc) ->
- "Minimal data transfer";
-xfer_min(suite) ->
- [];
+%% Minimal data transfer.
xfer_min(Config) when is_list(Config) ->
- ?line Stream = 0,
- ?line Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>,
- ?line Loopback = {127,0,0,1},
- ?line {ok,Sb} = gen_sctp:open([{type,seqpacket}]),
- ?line {ok,Pb} = inet:port(Sb),
- ?line ok = gen_sctp:listen(Sb, true),
-
- ?line {ok,Sa} = gen_sctp:open(),
- ?line {ok,Pa} = inet:port(Sa),
- ?line {ok,#sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=SaOutboundStreams,
- inbound_streams=SaInboundStreams,
- assoc_id=SaAssocId}=SaAssocChange} =
+ Stream = 0,
+ Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>,
+ Loopback = {127,0,0,1},
+ {ok,Sb} = gen_sctp:open([{type,seqpacket}]),
+ {ok,Pb} = inet:port(Sb),
+ ok = gen_sctp:listen(Sb, true),
+
+ {ok,Sa} = gen_sctp:open(),
+ {ok,Pa} = inet:port(Sa),
+ {ok,#sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SaOutboundStreams,
+ inbound_streams=SaInboundStreams,
+ assoc_id=SaAssocId}=SaAssocChange} =
gen_sctp:connect(Sa, Loopback, Pb, []),
- ?line {SbAssocId,SaOutboundStreams,SaInboundStreams} =
+ {SbAssocId,SaOutboundStreams,SaInboundStreams} =
case recv_event(log_ok(gen_sctp:recv(Sb, infinity))) of
{Loopback,Pa,
#sctp_assoc_change{state=comm_up,
@@ -142,184 +136,181 @@ xfer_min(Config) when is_list(Config) ->
outbound_streams=SbOutboundStreams,
inbound_streams=SbInboundStreams,
assoc_id=AssocId}} =
- ?line recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
+ recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
{AssocId,SbInboundStreams,SbOutboundStreams}
end,
- ?line ok = gen_sctp:send(Sa, SaAssocId, 0, Data),
- ?line case log_ok(gen_sctp:recv(Sb, infinity)) of
- {Loopback,
- Pa,
- [#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SbAssocId}],
- Data} -> ok;
- Event1 ->
- case recv_event(Event1) of
- {Loopback,Pa,
- #sctp_paddr_change{addr = {Loopback,_},
- state = State,
- error = 0,
- assoc_id = SbAssocId}}
- when State =:= addr_available;
- State =:= addr_confirmed ->
- {Loopback,
- Pa,
- [#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SbAssocId}],
- Data} = log_ok(gen_sctp:recv(Sb, infinity))
- end
- end,
- ?line ok = gen_sctp:send(Sb, SbAssocId, 0, Data),
- ?line case log_ok(gen_sctp:recv(Sa, infinity)) of
- {Loopback,Pb,
- [#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SaAssocId}],
- Data} ->
- ok;
- Event2 ->
- {Loopback,Pb,
- #sctp_paddr_change{addr={_,Pb},
- state=addr_confirmed,
- error=0,
- assoc_id=SaAssocId}} =
- ?line recv_event(Event2),
- ?line {Loopback,
- Pb,
- [#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SaAssocId}],
- Data} =
- log_ok(gen_sctp:recv(Sa, infinity))
- end,
+ ok = gen_sctp:send(Sa, SaAssocId, 0, Data),
+ case log_ok(gen_sctp:recv(Sb, infinity)) of
+ {Loopback,
+ Pa,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SbAssocId}],
+ Data} -> ok;
+ Event1 ->
+ case recv_event(Event1) of
+ {Loopback,Pa,
+ #sctp_paddr_change{addr = {Loopback,_},
+ state = State,
+ error = 0,
+ assoc_id = SbAssocId}}
+ when State =:= addr_available;
+ State =:= addr_confirmed ->
+ {Loopback,
+ Pa,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SbAssocId}],
+ Data} = log_ok(gen_sctp:recv(Sb, infinity))
+ end
+ end,
+ ok = gen_sctp:send(Sb, SbAssocId, 0, Data),
+ case log_ok(gen_sctp:recv(Sa, infinity)) of
+ {Loopback,Pb,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SaAssocId}],
+ Data} ->
+ ok;
+ Event2 ->
+ {Loopback,Pb,
+ #sctp_paddr_change{addr={_,Pb},
+ state=addr_confirmed,
+ error=0,
+ assoc_id=SaAssocId}} =
+ recv_event(Event2),
+ {Loopback,
+ Pb,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SaAssocId}],
+ Data} =
+ log_ok(gen_sctp:recv(Sa, infinity))
+ end,
%%
- ?line ok = gen_sctp:eof(Sa, SaAssocChange),
- ?line {Loopback,Pa,#sctp_shutdown_event{assoc_id=SbAssocId}} =
+ ok = gen_sctp:eof(Sa, SaAssocChange),
+ {Loopback,Pa,#sctp_shutdown_event{assoc_id=SbAssocId}} =
recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
- ?line {Loopback,Pb,
- #sctp_assoc_change{state=shutdown_comp,
- error=0,
- assoc_id=SaAssocId}} =
+ {Loopback,Pb,
+ #sctp_assoc_change{state=shutdown_comp,
+ error=0,
+ assoc_id=SaAssocId}} =
recv_event(log_ok(gen_sctp:recv(Sa, infinity))),
- ?line {Loopback,Pa,
- #sctp_assoc_change{state=shutdown_comp,
- error=0,
- assoc_id=SbAssocId}} =
+ {Loopback,Pa,
+ #sctp_assoc_change{state=shutdown_comp,
+ error=0,
+ assoc_id=SbAssocId}} =
recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
- ?line ok = gen_sctp:close(Sa),
- ?line ok = gen_sctp:close(Sb),
+ ok = gen_sctp:close(Sa),
+ ok = gen_sctp:close(Sb),
- ?line receive
- Msg -> test_server:fail({received,Msg})
- after 17 -> ok
- end,
+ receive
+ Msg -> ct:fail({received,Msg})
+ after 17 -> ok
+ end,
ok.
-xfer_active(doc) ->
- "Minimal data transfer in active mode";
-xfer_active(suite) ->
- [];
+%% Minimal data transfer in active mode.
xfer_active(Config) when is_list(Config) ->
- ?line Timeout = 2000,
- ?line Stream = 0,
- ?line Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>,
- ?line Loopback = {127,0,0,1},
- ?line {ok,Sb} = gen_sctp:open([{active,true}]),
- ?line {ok,Pb} = inet:port(Sb),
- ?line ok = gen_sctp:listen(Sb, true),
-
- ?line {ok,Sa} = gen_sctp:open([{active,true}]),
- ?line {ok,Pa} = inet:port(Sa),
- ?line ok = gen_sctp:connect_init(Sa, Loopback, Pb, []),
- ?line #sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=SaOutboundStreams,
- inbound_streams=SaInboundStreams,
- assoc_id=SaAssocId} = SaAssocChange =
+ Timeout = 2000,
+ Stream = 0,
+ Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>,
+ Loopback = {127,0,0,1},
+ {ok,Sb} = gen_sctp:open([{active,true}]),
+ {ok,Pb} = inet:port(Sb),
+ ok = gen_sctp:listen(Sb, true),
+
+ {ok,Sa} = gen_sctp:open([{active,true}]),
+ {ok,Pa} = inet:port(Sa),
+ ok = gen_sctp:connect_init(Sa, Loopback, Pb, []),
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SaOutboundStreams,
+ inbound_streams=SaInboundStreams,
+ assoc_id=SaAssocId} = SaAssocChange =
recv_assoc_change(Sa, Loopback, Pb, Timeout),
- ?line io:format("Sa=~p, Pa=~p, Sb=~p, Pb=~p, SaAssocId=~p, "
- "SaOutboundStreams=~p, SaInboundStreams=~p~n",
- [Sa,Pa,Sb,Pb,SaAssocId,
- SaOutboundStreams,SaInboundStreams]),
- ?line #sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=SbOutboundStreams,
- inbound_streams=SbInboundStreams,
- assoc_id=SbAssocId} =
+ io:format("Sa=~p, Pa=~p, Sb=~p, Pb=~p, SaAssocId=~p, "
+ "SaOutboundStreams=~p, SaInboundStreams=~p~n",
+ [Sa,Pa,Sb,Pb,SaAssocId,
+ SaOutboundStreams,SaInboundStreams]),
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SbOutboundStreams,
+ inbound_streams=SbInboundStreams,
+ assoc_id=SbAssocId} =
recv_assoc_change(Sb, Loopback, Pa, Timeout),
- ?line SbOutboundStreams = SaInboundStreams,
- ?line SbInboundStreams = SaOutboundStreams,
- ?line io:format("SbAssocId=~p~n", [SbAssocId]),
-
- ?line case recv_paddr_change(Sa, Loopback, Pb, 314) of
- #sctp_paddr_change{state=addr_confirmed,
- addr={_,Pb},
- error=0,
- assoc_id=SaAssocId} -> ok;
- #sctp_paddr_change{state=addr_available,
- addr={_,Pb},
- error=0,
- assoc_id=SaAssocId} -> ok;
- timeout -> ok
- end,
- ?line case recv_paddr_change(Sb, Loopback, Pa, 314) of
- #sctp_paddr_change{state=addr_confirmed,
- addr={Loopback,Pa},
- error=0,
- assoc_id=SbAssocId} -> ok;
- #sctp_paddr_change{state=addr_available,
- addr={Loopback,P},
- error=0,
- assoc_id=SbAssocId} ->
- ?line match_unless_solaris(Pa, P);
- timeout -> ok
- end,
- ?line [] = flush(),
-
- ?line ok =
+ SbOutboundStreams = SaInboundStreams,
+ SbInboundStreams = SaOutboundStreams,
+ io:format("SbAssocId=~p~n", [SbAssocId]),
+
+ case recv_paddr_change(Sa, Loopback, Pb, 314) of
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={_,Pb},
+ error=0,
+ assoc_id=SaAssocId} -> ok;
+ #sctp_paddr_change{state=addr_available,
+ addr={_,Pb},
+ error=0,
+ assoc_id=SaAssocId} -> ok;
+ timeout -> ok
+ end,
+ case recv_paddr_change(Sb, Loopback, Pa, 314) of
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={Loopback,Pa},
+ error=0,
+ assoc_id=SbAssocId} -> ok;
+ #sctp_paddr_change{state=addr_available,
+ addr={Loopback,P},
+ error=0,
+ assoc_id=SbAssocId} ->
+ match_unless_solaris(Pa, P);
+ timeout -> ok
+ end,
+ [] = flush(),
+
+ ok =
do_from_other_process(
fun () -> gen_sctp:send(Sa, SaAssocId, 0, Data) end),
- ?line receive
- {sctp,Sb,Loopback,Pa,
- {[#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SbAssocId}],
- Data}} -> ok
- after Timeout ->
- ?line test_server:fail({timeout,flush()})
- end,
- ?line ok = gen_sctp:send(Sb, SbAssocId, 0, Data),
- ?line receive
- {sctp,Sa,Loopback,Pb,
- {[#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SaAssocId}],
- Data}} -> ok
- after Timeout ->
- ?line test_server:fail({timeout,flush()})
- end,
+ receive
+ {sctp,Sb,Loopback,Pa,
+ {[#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SbAssocId}],
+ Data}} -> ok
+ after Timeout ->
+ ct:fail({timeout,flush()})
+ end,
+ ok = gen_sctp:send(Sb, SbAssocId, 0, Data),
+ receive
+ {sctp,Sa,Loopback,Pb,
+ {[#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SaAssocId}],
+ Data}} -> ok
+ after Timeout ->
+ ct:fail({timeout,flush()})
+ end,
%%
- ?line ok = gen_sctp:abort(Sa, SaAssocChange),
- ?line case recv_assoc_change(Sb, Loopback, Pa, Timeout) of
- #sctp_assoc_change{state=comm_lost,
- assoc_id=SbAssocId} -> ok;
- timeout ->
- ?line test_server:fail({timeout,flush()})
- end,
- ?line ok = gen_sctp:close(Sb),
- ?line case recv_assoc_change(Sa, Loopback, Pb, Timeout) of
- #sctp_assoc_change{state=comm_lost,
- assoc_id=SaAssocId} -> ok;
- timeout ->
- ?line io:format("timeout waiting for comm_lost on Sa~n"),
- ?line match_unless_solaris(ok, {timeout,flush()})
- end,
- ?line receive
- {sctp_error,Sa,enotconn} -> ok % Solaris
- after 17 -> ok
- end,
- ?line ok = gen_sctp:close(Sa),
+ ok = gen_sctp:abort(Sa, SaAssocChange),
+ case recv_assoc_change(Sb, Loopback, Pa, Timeout) of
+ #sctp_assoc_change{state=comm_lost,
+ assoc_id=SbAssocId} -> ok;
+ timeout ->
+ ct:fail({timeout,flush()})
+ end,
+ ok = gen_sctp:close(Sb),
+ case recv_assoc_change(Sa, Loopback, Pb, Timeout) of
+ #sctp_assoc_change{state=comm_lost,
+ assoc_id=SaAssocId} -> ok;
+ timeout ->
+ io:format("timeout waiting for comm_lost on Sa~n"),
+ match_unless_solaris(ok, {timeout,flush()})
+ end,
+ receive
+ {sctp_error,Sa,enotconn} -> ok % Solaris
+ after 17 -> ok
+ end,
+ ok = gen_sctp:close(Sa),
%%
- ?line receive
- Msg -> test_server:fail({unexpected,[Msg]++flush()})
- after 17 -> ok
- end,
+ receive
+ Msg -> ct:fail({unexpected,[Msg]++flush()})
+ after 17 -> ok
+ end,
ok.
recv_assoc_change(S, Addr, Port, Timeout) ->
@@ -346,142 +337,139 @@ recv_paddr_change(S, Addr, Port, Timeout) ->
timeout
end.
-def_sndrcvinfo(doc) ->
- "Test that #sctp_sndrcvinfo{} parameters set on a socket "
- "are used by gen_sctp:send/4";
-def_sndrcvinfo(suite) ->
- [];
+%% Test that #sctp_sndrcvinfo{} parameters set on a socket
+%% are used by gen_sctp:send/4.
def_sndrcvinfo(Config) when is_list(Config) ->
- ?line Loopback = {127,0,0,1},
- ?line Data = <<"What goes up, must come down.">>,
+ Loopback = {127,0,0,1},
+ Data = <<"What goes up, must come down.">>,
%%
- ?line S1 =
+ S1 =
log_ok(gen_sctp:open(
0, [{sctp_default_send_param,#sctp_sndrcvinfo{ppid=17}}])),
?LOGVAR(S1),
- ?line P1 =
+ P1 =
log_ok(inet:port(S1)),
?LOGVAR(P1),
- ?line #sctp_sndrcvinfo{ppid=17, context=0, timetolive=0, assoc_id=0} =
+ #sctp_sndrcvinfo{ppid=17, context=0, timetolive=0, assoc_id=0} =
getopt(S1, sctp_default_send_param),
- ?line ok =
+ ok =
gen_sctp:listen(S1, true),
%%
- ?line S2 =
+ S2 =
log_ok(gen_sctp:open()),
?LOGVAR(S2),
- ?line P2 =
+ P2 =
log_ok(inet:port(S2)),
?LOGVAR(P2),
- ?line #sctp_sndrcvinfo{ppid=0, context=0, timetolive=0, assoc_id=0} =
+ #sctp_sndrcvinfo{ppid=0, context=0, timetolive=0, assoc_id=0} =
getopt(S2, sctp_default_send_param),
%%
- ?line #sctp_assoc_change{
+ #sctp_assoc_change{
state=comm_up,
error=0,
assoc_id=S2AssocId} = S2AssocChange =
log_ok(gen_sctp:connect(S2, Loopback, P1, [])),
?LOGVAR(S2AssocChange),
- ?line case recv_event(log_ok(gen_sctp:recv(S1))) of
- {Loopback,P2,
- #sctp_assoc_change{
- state=comm_up,
- error=0,
- assoc_id=S1AssocId}} ->
- ?LOGVAR(S1AssocId);
- {Loopback,P2,
- #sctp_paddr_change{
- state=addr_confirmed,
- error=0,
- assoc_id=S1AssocId}} ->
- ?LOGVAR(S1AssocId),
- {Loopback,P2,
- #sctp_assoc_change{
- state=comm_up,
- error=0,
- assoc_id=S1AssocId}} =
- recv_event(log_ok(gen_sctp:recv(S1)))
- end,
-
- ?line #sctp_sndrcvinfo{
+ case recv_event(log_ok(gen_sctp:recv(S1))) of
+ {Loopback,P2,
+ #sctp_assoc_change{
+ state=comm_up,
+ error=0,
+ assoc_id=S1AssocId}} ->
+ ?LOGVAR(S1AssocId);
+ {Loopback,P2,
+ #sctp_paddr_change{
+ state=addr_confirmed,
+ error=0,
+ assoc_id=S1AssocId}} ->
+ ?LOGVAR(S1AssocId),
+ {Loopback,P2,
+ #sctp_assoc_change{
+ state=comm_up,
+ error=0,
+ assoc_id=S1AssocId}} =
+ recv_event(log_ok(gen_sctp:recv(S1)))
+ end,
+
+ #sctp_sndrcvinfo{
ppid=17, context=0, timetolive=0} = %, assoc_id=S1AssocId} =
getopt(
S1, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S1AssocId}),
- ?line #sctp_sndrcvinfo{
+ #sctp_sndrcvinfo{
ppid=0, context=0, timetolive=0} = %, assoc_id=S2AssocId} =
getopt(
S2, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S2AssocId}),
%%
- ?line ok =
+ ok =
gen_sctp:send(S1, S1AssocId, 1, <<"1: ",Data/binary>>),
- ?line case log_ok(gen_sctp:recv(S2)) of
- {Loopback,P1,
- [#sctp_sndrcvinfo{
- stream=1, ppid=17, context=0, assoc_id=S2AssocId}],
- <<"1: ",Data/binary>>} -> ok;
- Event1 ->
- ?line {Loopback,P1,
- #sctp_paddr_change{state=addr_confirmed,
- addr={_,P1},
- error=0,
- assoc_id=S2AssocId}} =
- recv_event(Event1),
- ?line {Loopback,P1,
- [#sctp_sndrcvinfo{
- stream=1, ppid=17, context=0, assoc_id=S2AssocId}],
- <<"1: ",Data/binary>>} =
- log_ok(gen_sctp:recv(S2))
- end,
+ case log_ok(gen_sctp:recv(S2)) of
+ {Loopback,P1,
+ [#sctp_sndrcvinfo{
+ stream=1, ppid=17, context=0, assoc_id=S2AssocId}],
+ <<"1: ",Data/binary>>} -> ok;
+ Event1 ->
+ {Loopback,P1,
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={_,P1},
+ error=0,
+ assoc_id=S2AssocId}} =
+ recv_event(Event1),
+ {Loopback,P1,
+ [#sctp_sndrcvinfo{
+ stream=1, ppid=17, context=0, assoc_id=S2AssocId}],
+ <<"1: ",Data/binary>>} =
+ log_ok(gen_sctp:recv(S2))
+ end,
%%
- ?line ok =
+ ok =
setopt(
S1, sctp_default_send_param, #sctp_sndrcvinfo{ppid=18}),
- ?line ok =
+ ok =
setopt(
S1, sctp_default_send_param,
#sctp_sndrcvinfo{ppid=19, assoc_id=S1AssocId}),
- ?line #sctp_sndrcvinfo{
+ #sctp_sndrcvinfo{
ppid=18, context=0, timetolive=0, assoc_id=0} =
getopt(S1, sctp_default_send_param),
- ?line #sctp_sndrcvinfo{
+ #sctp_sndrcvinfo{
ppid=19, context=0, timetolive=0, assoc_id=S1AssocId} =
getopt(
S1, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S1AssocId}),
%%
- ?line ok =
+ ok =
gen_sctp:send(S1, S1AssocId, 0, <<"2: ",Data/binary>>),
- ?line case log_ok(gen_sctp:recv(S2)) of
- {Loopback,P1,
- [#sctp_sndrcvinfo{
- stream=0, ppid=19, context=0, assoc_id=S2AssocId}],
- <<"2: ",Data/binary>>} -> ok
- end,
- ?line ok =
+ case log_ok(gen_sctp:recv(S2)) of
+ {Loopback,P1,
+ [#sctp_sndrcvinfo{
+ stream=0, ppid=19, context=0, assoc_id=S2AssocId}],
+ <<"2: ",Data/binary>>} -> ok
+ end,
+ ok =
gen_sctp:send(S2, S2AssocChange, 1, <<"3: ",Data/binary>>),
- ?line case log_ok(gen_sctp:recv(S1)) of
- {Loopback,P2,
- [#sctp_sndrcvinfo{
- stream=1, ppid=0, context=0, assoc_id=S1AssocId}],
- <<"3: ",Data/binary>>} -> ok;
- Event2 ->
- case recv_event(Event2) of
- {Loopback,P2,
- #sctp_paddr_change{
- addr={Loopback,_},
- state=State,
- error=0, assoc_id=S1AssocId}}
- when State =:= addr_available;
- State =:= addr_confirmed ->
- ?line case log_ok(gen_sctp:recv(S1)) of
- {Loopback,P2,
- [#sctp_sndrcvinfo{
- stream=1, ppid=0, context=0,
- assoc_id=S1AssocId}],
- <<"3: ",Data/binary>>} -> ok
- end
- end
- end,
- ?line ok =
+ case log_ok(gen_sctp:recv(S1)) of
+ {Loopback,P2,
+ [#sctp_sndrcvinfo{
+ stream=1, ppid=0, context=0, assoc_id=S1AssocId}],
+ <<"3: ",Data/binary>>} -> ok;
+ Event2 ->
+ case recv_event(Event2) of
+ {Loopback,P2,
+ #sctp_paddr_change{
+ addr={Loopback,_},
+ state=State,
+ error=0, assoc_id=S1AssocId}}
+ when State =:= addr_available;
+ State =:= addr_confirmed ->
+ case log_ok(gen_sctp:recv(S1)) of
+ {Loopback,P2,
+ [#sctp_sndrcvinfo{
+ stream=1, ppid=0, context=0,
+ assoc_id=S1AssocId}],
+ <<"3: ",Data/binary>>} -> ok
+ end
+ end
+ end,
+ ok =
do_from_other_process(
fun () ->
gen_sctp:send(
@@ -489,22 +477,22 @@ def_sndrcvinfo(Config) when is_list(Config) ->
#sctp_sndrcvinfo{stream=0, ppid=20, assoc_id=S2AssocId},
<<"4: ",Data/binary>>)
end),
- ?line case log_ok(do_from_other_process(fun() -> gen_sctp:recv(S1) end)) of
- {Loopback,P2,
- [#sctp_sndrcvinfo{
- stream=0, ppid=20, context=0, assoc_id=S1AssocId}],
- <<"4: ",Data/binary>>} -> ok
- end,
+ case log_ok(do_from_other_process(fun() -> gen_sctp:recv(S1) end)) of
+ {Loopback,P2,
+ [#sctp_sndrcvinfo{
+ stream=0, ppid=20, context=0, assoc_id=S1AssocId}],
+ <<"4: ",Data/binary>>} -> ok
+ end,
%%
- ?line ok =
+ ok =
gen_sctp:close(S1),
- ?line ok =
+ ok =
gen_sctp:close(S2),
- ?line receive
- Msg ->
- test_server:fail({received,Msg})
- after 17 -> ok
- end,
+ receive
+ Msg ->
+ ct:fail({received,Msg})
+ after 17 -> ok
+ end,
ok.
getopt(S, Opt) ->
@@ -541,147 +529,138 @@ flush() ->
[]
end.
-api_open_close(doc) ->
- "Test the API function open/1,2 and close/1";
-api_open_close(suite) ->
- [];
+%% Test the API function open/1,2 and close/1.
api_open_close(Config) when is_list(Config) ->
- ?line {ok,S1} = gen_sctp:open(0),
- ?line {ok,P} = inet:port(S1),
- ?line ok = gen_sctp:close(S1),
+ {ok,S1} = gen_sctp:open(0),
+ {ok,P} = inet:port(S1),
+ ok = gen_sctp:close(S1),
- ?line {ok,S2} = gen_sctp:open(P),
- ?line {ok,P} = inet:port(S2),
- ?line ok = gen_sctp:close(S2),
+ {ok,S2} = gen_sctp:open(P),
+ {ok,P} = inet:port(S2),
+ ok = gen_sctp:close(S2),
- ?line {ok,S3} = gen_sctp:open([{port,P}]),
- ?line {ok,P} = inet:port(S3),
- ?line ok = gen_sctp:close(S3),
+ {ok,S3} = gen_sctp:open([{port,P}]),
+ {ok,P} = inet:port(S3),
+ ok = gen_sctp:close(S3),
- ?line {ok,S4} = gen_sctp:open(P, []),
- ?line {ok,P} = inet:port(S4),
- ?line ok = gen_sctp:close(S4),
+ {ok,S4} = gen_sctp:open(P, []),
+ {ok,P} = inet:port(S4),
+ ok = gen_sctp:close(S4),
- ?line {ok,S5} = gen_sctp:open(P, [{ifaddr,any}]),
- ?line {ok,P} = inet:port(S5),
- ?line ok = gen_sctp:close(S5),
+ {ok,S5} = gen_sctp:open(P, [{ifaddr,any}]),
+ {ok,P} = inet:port(S5),
+ ok = gen_sctp:close(S5),
- ?line ok = gen_sctp:close(S5),
+ ok = gen_sctp:close(S5),
- ?line try gen_sctp:close(0)
- catch error:badarg -> ok
- end,
+ try gen_sctp:close(0)
+ catch error:badarg -> ok
+ end,
- ?line try gen_sctp:open({})
- catch error:badarg -> ok
- end,
+ try gen_sctp:open({})
+ catch error:badarg -> ok
+ end,
- ?line try gen_sctp:open(-1)
- catch error:badarg -> ok
- end,
+ try gen_sctp:open(-1)
+ catch error:badarg -> ok
+ end,
- ?line try gen_sctp:open(65536)
- catch error:badarg -> ok
- end,
+ try gen_sctp:open(65536)
+ catch error:badarg -> ok
+ end,
- ?line try gen_sctp:open(make_ref(), [])
- catch error:badarg -> ok
- end,
+ try gen_sctp:open(make_ref(), [])
+ catch error:badarg -> ok
+ end,
- ?line try gen_sctp:open(0, {})
- catch error:badarg -> ok
- end,
+ try gen_sctp:open(0, {})
+ catch error:badarg -> ok
+ end,
- ?line try gen_sctp:open(0, [make_ref()])
- catch error:badarg -> ok
- end,
+ try gen_sctp:open(0, [make_ref()])
+ catch error:badarg -> ok
+ end,
- ?line try gen_sctp:open([{invalid_option,0}])
- catch error:badarg -> ok
- end,
+ try gen_sctp:open([{invalid_option,0}])
+ catch error:badarg -> ok
+ end,
- ?line try gen_sctp:open(0, [{mode,invalid_mode}])
- catch error:badarg -> ok
- end,
+ try gen_sctp:open(0, [{mode,invalid_mode}])
+ catch error:badarg -> ok
+ end,
ok.
-api_listen(doc) ->
- "Test the API function listen/2";
-api_listen(suite) ->
- [];
+%% Test the API function listen/2.
api_listen(Config) when is_list(Config) ->
- ?line Localhost = {127,0,0,1},
-
- ?line try gen_sctp:listen(0, true)
- catch error:badarg -> ok
- end,
-
- ?line {ok,S} = gen_sctp:open(),
- ?line {ok,Pb} = inet:port(S),
- ?line try gen_sctp:listen(S, not_allowed_for_listen)
- catch error:badarg -> ok
- end,
- ?line ok = gen_sctp:close(S),
- ?line {error,closed} = gen_sctp:listen(S, true),
-
- ?line {ok,Sb} = gen_sctp:open(Pb),
- ?line {ok,Sa} = gen_sctp:open(),
- ?line case gen_sctp:connect(Sa, localhost, Pb, []) of
- {error,econnrefused} ->
- ?line {ok,{Localhost,
- Pb,[],
- #sctp_assoc_change{
- state=comm_lost}}} =
- gen_sctp:recv(Sa, infinity);
- {error,#sctp_assoc_change{state=cant_assoc}} ->
- ok%;
- %% {error,{Localhost,Pb,_,#sctp_assoc_change{state=cant_assoc}}} ->
- %% ok
- end,
- ?line ok = gen_sctp:listen(Sb, true),
- ?line {ok,#sctp_assoc_change{state=comm_up,
- error=0}} =
+ Localhost = {127,0,0,1},
+
+ try gen_sctp:listen(0, true)
+ catch error:badarg -> ok
+ end,
+
+ {ok,S} = gen_sctp:open(),
+ {ok,Pb} = inet:port(S),
+ try gen_sctp:listen(S, not_allowed_for_listen)
+ catch error:badarg -> ok
+ end,
+ ok = gen_sctp:close(S),
+ {error,closed} = gen_sctp:listen(S, true),
+
+ {ok,Sb} = gen_sctp:open(Pb),
+ {ok,Sa} = gen_sctp:open(),
+ case gen_sctp:connect(Sa, localhost, Pb, []) of
+ {error,econnrefused} ->
+ {ok,{Localhost,
+ Pb,[],
+ #sctp_assoc_change{
+ state=comm_lost}}} =
+ gen_sctp:recv(Sa, infinity);
+ {error,#sctp_assoc_change{state=cant_assoc}} ->
+ ok%;
+ %% {error,{Localhost,Pb,_,#sctp_assoc_change{state=cant_assoc}}} ->
+ %% ok
+ end,
+ ok = gen_sctp:listen(Sb, true),
+ {ok,#sctp_assoc_change{state=comm_up,
+ error=0}} =
gen_sctp:connect(Sa, localhost, Pb, []),
- ?line ok = gen_sctp:close(Sa),
- ?line ok = gen_sctp:close(Sb),
+ ok = gen_sctp:close(Sa),
+ ok = gen_sctp:close(Sb),
ok.
-api_connect_init(doc) ->
- "Test the API function connect_init/4";
-api_connect_init(suite) ->
- [];
+%% Test the API function connect_init/4.
api_connect_init(Config) when is_list(Config) ->
- ?line Localhost = {127,0,0,1},
-
- ?line {ok,S} = gen_sctp:open(),
- ?line {ok,Pb} = inet:port(S),
- ?line try gen_sctp:connect_init(S, Localhost, not_allowed_for_port, [])
- catch error:badarg -> ok
- end,
- ?line try gen_sctp:connect_init(S, Localhost, 12345, not_allowed_for_opts)
- catch error:badarg -> ok
- end,
- ?line ok = gen_sctp:close(S),
- ?line {error,closed} = gen_sctp:connect_init(S, Localhost, 12345, []),
-
- ?line {ok,Sb} = gen_sctp:open(Pb),
- ?line {ok,Sa} = gen_sctp:open(),
- ?line case gen_sctp:connect_init(Sa, localhost, Pb, []) of
- {error,econnrefused} ->
- ?line {Localhost,Pb,#sctp_assoc_change{state=comm_lost}} =
- recv_event(log_ok(gen_sctp:recv(Sa, infinity)));
- ok ->
- ?line {Localhost,Pb,#sctp_assoc_change{state=cant_assoc}} =
- recv_event(log_ok(gen_sctp:recv(Sa, infinity)))
- end,
- ?line ok = gen_sctp:listen(Sb, true),
- ?line case gen_sctp:connect_init(Sa, localhost, Pb, []) of
- ok ->
- ?line {Localhost,Pb,#sctp_assoc_change{state=comm_up}} =
- recv_event(log_ok(gen_sctp:recv(Sa, infinity)))
- end,
- ?line ok = gen_sctp:close(Sa),
- ?line ok = gen_sctp:close(Sb),
+ Localhost = {127,0,0,1},
+
+ {ok,S} = gen_sctp:open(),
+ {ok,Pb} = inet:port(S),
+ try gen_sctp:connect_init(S, Localhost, not_allowed_for_port, [])
+ catch error:badarg -> ok
+ end,
+ try gen_sctp:connect_init(S, Localhost, 12345, not_allowed_for_opts)
+ catch error:badarg -> ok
+ end,
+ ok = gen_sctp:close(S),
+ {error,closed} = gen_sctp:connect_init(S, Localhost, 12345, []),
+
+ {ok,Sb} = gen_sctp:open(Pb),
+ {ok,Sa} = gen_sctp:open(),
+ case gen_sctp:connect_init(Sa, localhost, Pb, []) of
+ {error,econnrefused} ->
+ {Localhost,Pb,#sctp_assoc_change{state=comm_lost}} =
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity)));
+ ok ->
+ {Localhost,Pb,#sctp_assoc_change{state=cant_assoc}} =
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity)))
+ end,
+ ok = gen_sctp:listen(Sb, true),
+ case gen_sctp:connect_init(Sa, localhost, Pb, []) of
+ ok ->
+ {Localhost,Pb,#sctp_assoc_change{state=comm_up}} =
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity)))
+ end,
+ ok = gen_sctp:close(Sa),
+ ok = gen_sctp:close(Sb),
ok.
recv_event({Addr,Port,[],#sctp_assoc_change{}=AssocChange}) ->
@@ -703,94 +682,86 @@ recv_event({Addr,Port,
#sctp_shutdown_event{assoc_id=Assoc}=ShutdownEvent}) ->
{Addr,Port,ShutdownEvent}.
-api_opts(doc) ->
- "Test socket options";
-api_opts(suite) ->
- [];
+%% Test socket options.
api_opts(Config) when is_list(Config) ->
- ?line Sndbuf = 32768,
- ?line Recbuf = 65536,
- ?line {ok,S} = gen_sctp:open(0),
- ?line OSType = os:type(),
- ?line case {inet:setopts(S, [{linger,{true,2}}]),OSType} of
- {ok,_} ->
- ok;
- {{error,einval},{unix,sunos}} ->
- ok
- end,
- ?line ok = inet:setopts(S, [{sndbuf,Sndbuf}]),
- ?line ok = inet:setopts(S, [{recbuf,Recbuf}]),
- ?line case inet:getopts(S, [sndbuf]) of
- {ok,[{sndbuf,SB}]} when SB >= Sndbuf -> ok
- end,
- ?line case inet:getopts(S, [recbuf]) of
- {ok,[{recbuf,RB}]} when RB >= Recbuf -> ok
- end.
+ Sndbuf = 32768,
+ Recbuf = 65536,
+ {ok,S} = gen_sctp:open(0),
+ OSType = os:type(),
+ case {inet:setopts(S, [{linger,{true,2}}]),OSType} of
+ {ok,_} ->
+ ok;
+ {{error,einval},{unix,sunos}} ->
+ ok
+ end,
+ ok = inet:setopts(S, [{sndbuf,Sndbuf}]),
+ ok = inet:setopts(S, [{recbuf,Recbuf}]),
+ case inet:getopts(S, [sndbuf]) of
+ {ok,[{sndbuf,SB}]} when SB >= Sndbuf -> ok
+ end,
+ case inet:getopts(S, [recbuf]) of
+ {ok,[{recbuf,RB}]} when RB >= Recbuf -> ok
+ end.
implicit_inet6(Config) when is_list(Config) ->
- ?line Hostname = log_ok(inet:gethostname()),
- ?line
- case gen_sctp:open(0, [inet6]) of
- {ok,S1} ->
- ?line
- case inet:getaddr(Hostname, inet6) of
- {ok,Host} ->
- ?line Loopback = {0,0,0,0,0,0,0,1},
- ?line io:format("~s ~p~n", ["Loopback",Loopback]),
- ?line implicit_inet6(S1, Loopback),
- ?line ok = gen_sctp:close(S1),
- %%
- ?line Localhost =
- log_ok(inet:getaddr("localhost", inet6)),
- ?line io:format("~s ~p~n", ["localhost",Localhost]),
- ?line S2 =
- log_ok(gen_sctp:open(0, [{ip,Localhost}])),
- ?line implicit_inet6(S2, Localhost),
- ?line ok = gen_sctp:close(S2),
- %%
- ?line io:format("~s ~p~n", [Hostname,Host]),
- ?line S3 =
- log_ok(gen_sctp:open(0, [{ifaddr,Host}])),
- ?line implicit_inet6(S3, Host),
- ?line ok = gen_sctp:close(S1);
- {error,eafnosupport} ->
- ?line ok = gen_sctp:close(S1),
- {skip,"Can not look up IPv6 address"}
- end;
- _ ->
- {skip,"IPv6 not supported"}
- end.
+ Hostname = log_ok(inet:gethostname()),
+ case gen_sctp:open(0, [inet6]) of
+ {ok,S1} ->
+ case inet:getaddr(Hostname, inet6) of
+ {ok,Host} ->
+ Loopback = {0,0,0,0,0,0,0,1},
+ io:format("~s ~p~n", ["Loopback",Loopback]),
+ implicit_inet6(S1, Loopback),
+ ok = gen_sctp:close(S1),
+ %%
+ Localhost =
+ log_ok(inet:getaddr("localhost", inet6)),
+ io:format("~s ~p~n", ["localhost",Localhost]),
+ S2 =
+ log_ok(gen_sctp:open(0, [{ip,Localhost}])),
+ implicit_inet6(S2, Localhost),
+ ok = gen_sctp:close(S2),
+ %%
+ io:format("~s ~p~n", [Hostname,Host]),
+ S3 =
+ log_ok(gen_sctp:open(0, [{ifaddr,Host}])),
+ implicit_inet6(S3, Host),
+ ok = gen_sctp:close(S1);
+ {error,eafnosupport} ->
+ ok = gen_sctp:close(S1),
+ {skip,"Can not look up IPv6 address"}
+ end;
+ _ ->
+ {skip,"IPv6 not supported"}
+ end.
implicit_inet6(S1, Addr) ->
- ?line ok = gen_sctp:listen(S1, true),
- ?line P1 = log_ok(inet:port(S1)),
- ?line S2 = log_ok(gen_sctp:open(0, [inet6])),
- ?line P2 = log_ok(inet:port(S2)),
- ?line #sctp_assoc_change{state=comm_up} =
+ ok = gen_sctp:listen(S1, true),
+ P1 = log_ok(inet:port(S1)),
+ S2 = log_ok(gen_sctp:open(0, [inet6])),
+ P2 = log_ok(inet:port(S2)),
+ #sctp_assoc_change{state=comm_up} =
log_ok(gen_sctp:connect(S2, Addr, P1, [])),
- ?line case recv_event(log_ok(gen_sctp:recv(S1))) of
- {Addr,P2,#sctp_assoc_change{state=comm_up}} ->
- ok;
- {Addr,P2,#sctp_paddr_change{state=addr_confirmed,
- addr={Addr,P2},
- error=0}} ->
- {Addr,P2,#sctp_assoc_change{state=comm_up}} =
- recv_event(log_ok(gen_sctp:recv(S1)))
- end,
- ?line case log_ok(inet:sockname(S1)) of
- {Addr,P1} -> ok;
- {{0,0,0,0,0,0,0,0},P1} -> ok
- end,
- ?line case log_ok(inet:sockname(S2)) of
- {Addr,P2} -> ok;
- {{0,0,0,0,0,0,0,0},P2} -> ok
- end,
- ?line ok = gen_sctp:close(S2).
-
-active_n(doc) ->
- "Verify {active,N} socket management";
-active_n(suite) ->
- [];
+ case recv_event(log_ok(gen_sctp:recv(S1))) of
+ {Addr,P2,#sctp_assoc_change{state=comm_up}} ->
+ ok;
+ {Addr,P2,#sctp_paddr_change{state=addr_confirmed,
+ addr={Addr,P2},
+ error=0}} ->
+ {Addr,P2,#sctp_assoc_change{state=comm_up}} =
+ recv_event(log_ok(gen_sctp:recv(S1)))
+ end,
+ case log_ok(inet:sockname(S1)) of
+ {Addr,P1} -> ok;
+ {{0,0,0,0,0,0,0,0},P1} -> ok
+ end,
+ case log_ok(inet:sockname(S2)) of
+ {Addr,P2} -> ok;
+ {{0,0,0,0,0,0,0,0},P2} -> ok
+ end,
+ ok = gen_sctp:close(S2).
+
+%% Verify {active,N} socket management.
active_n(Config) when is_list(Config) ->
N = 3,
S1 = ok(gen_sctp:open([{active,N}])),
@@ -887,51 +858,45 @@ active_n(Config) when is_list(Config) ->
ok = gen_sctp:close(S1),
ok.
-basic_stream(doc) ->
- "Hello world stream socket";
-basic_stream(suite) ->
- [];
+%% Hello world stream socket.
basic_stream(Config) when is_list(Config) ->
- ?line {ok,S} = gen_sctp:open([{type,stream}]),
- ?line ok = gen_sctp:listen(S, true),
- ?line ok =
+ {ok,S} = gen_sctp:open([{type,stream}]),
+ ok = gen_sctp:listen(S, true),
+ ok =
do_from_other_process(
fun () -> gen_sctp:listen(S, 10) end),
- ?line ok = gen_sctp:close(S),
+ ok = gen_sctp:close(S),
ok.
-xfer_stream_min(doc) ->
- "Minimal data transfer";
-xfer_stream_min(suite) ->
- [];
+%% Minimal data transfer.
xfer_stream_min(Config) when is_list(Config) ->
- ?line Stream = 0,
- ?line Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>,
- ?line Loopback = {127,0,0,1},
- ?line {ok,Sb} = gen_sctp:open([{type,seqpacket}]),
- ?line ?LOGVAR(Sb),
- ?line {ok,Pb} = inet:port(Sb),
- ?line ?LOGVAR(Pb),
- ?line ok = gen_sctp:listen(Sb, true),
-
- ?line {ok,Sa} = gen_sctp:open([{type,stream}]),
- ?line ?LOGVAR(Sa),
- ?line {ok,Pa} = inet:port(Sa),
- ?line ?LOGVAR(Pa),
- ?line #sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=SaOutboundStreams,
- inbound_streams=SaInboundStreams,
- assoc_id=SaAssocId_X} =
+ Stream = 0,
+ Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>,
+ Loopback = {127,0,0,1},
+ {ok,Sb} = gen_sctp:open([{type,seqpacket}]),
+ ?LOGVAR(Sb),
+ {ok,Pb} = inet:port(Sb),
+ ?LOGVAR(Pb),
+ ok = gen_sctp:listen(Sb, true),
+
+ {ok,Sa} = gen_sctp:open([{type,stream}]),
+ ?LOGVAR(Sa),
+ {ok,Pa} = inet:port(Sa),
+ ?LOGVAR(Pa),
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SaOutboundStreams,
+ inbound_streams=SaInboundStreams,
+ assoc_id=SaAssocId_X} =
log_ok(gen_sctp:connect(Sa, Loopback, Pb, [])),
- ?line ?LOGVAR(SaAssocId_X),
- ?line [{_,#sctp_paddrinfo{assoc_id=SaAssocId,state=active}}] =
+ ?LOGVAR(SaAssocId_X),
+ [{_,#sctp_paddrinfo{assoc_id=SaAssocId,state=active}}] =
log_ok(inet:getopts(Sa, [{sctp_get_peer_addr_info,
#sctp_paddrinfo{address={Loopback,Pb}}}])),
- ?line ?LOGVAR(SaAssocId),
- ?line match_unless_solaris(SaAssocId_X, SaAssocId),
+ ?LOGVAR(SaAssocId),
+ match_unless_solaris(SaAssocId_X, SaAssocId),
- ?line {SbOutboundStreams,SbInboundStreams,SbAssocId} =
+ {SbOutboundStreams,SbInboundStreams,SbAssocId} =
case recv_event(log_ok(gen_sctp:recv(Sb, infinity))) of
{Loopback,Pa,
#sctp_assoc_change{state=comm_up,
@@ -946,87 +911,87 @@ xfer_stream_min(Config) when is_list(Config) ->
error=0,
assoc_id=AI}} ->
{Loopback,Pa,
- ?line #sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=OS,
- inbound_streams=IS,
- assoc_id=AI}} =
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=OS,
+ inbound_streams=IS,
+ assoc_id=AI}} =
recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
{OS,IS,AI}
end,
- ?line ?LOGVAR(SbAssocId),
- ?line SaOutboundStreams = SbInboundStreams,
- ?line ?LOGVAR(SaOutboundStreams),
- ?line SbOutboundStreams = SaInboundStreams,
- ?line ?LOGVAR(SbOutboundStreams),
- ?line ok = gen_sctp:send(Sa, SaAssocId, 0, Data),
- ?line case log_ok(gen_sctp:recv(Sb, infinity)) of
- {Loopback,
- Pa,
- [#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SbAssocId}],
- Data} -> ok;
- {Loopback,
- Pa,[],
- #sctp_paddr_change{addr = {Loopback,_},
- state = addr_available,
- error = 0,
- assoc_id = SbAssocId}} ->
- {Loopback,
- Pa,
- [#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SbAssocId}],
- Data} = log_ok(gen_sctp:recv(Sb, infinity));
- {Loopback,
- Pa,
- [#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SbAssocId}],
- #sctp_paddr_change{addr = {Loopback,_},
- state = addr_confirmed,
- error = 0,
- assoc_id = SbAssocId}} ->
- {Loopback,
- Pa,
- [#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SbAssocId}],
- Data} = log_ok(gen_sctp:recv(Sb, infinity))
- end,
- ?line ok =
+ ?LOGVAR(SbAssocId),
+ SaOutboundStreams = SbInboundStreams,
+ ?LOGVAR(SaOutboundStreams),
+ SbOutboundStreams = SaInboundStreams,
+ ?LOGVAR(SbOutboundStreams),
+ ok = gen_sctp:send(Sa, SaAssocId, 0, Data),
+ case log_ok(gen_sctp:recv(Sb, infinity)) of
+ {Loopback,
+ Pa,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SbAssocId}],
+ Data} -> ok;
+ {Loopback,
+ Pa,[],
+ #sctp_paddr_change{addr = {Loopback,_},
+ state = addr_available,
+ error = 0,
+ assoc_id = SbAssocId}} ->
+ {Loopback,
+ Pa,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SbAssocId}],
+ Data} = log_ok(gen_sctp:recv(Sb, infinity));
+ {Loopback,
+ Pa,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SbAssocId}],
+ #sctp_paddr_change{addr = {Loopback,_},
+ state = addr_confirmed,
+ error = 0,
+ assoc_id = SbAssocId}} ->
+ {Loopback,
+ Pa,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SbAssocId}],
+ Data} = log_ok(gen_sctp:recv(Sb, infinity))
+ end,
+ ok =
do_from_other_process(
fun () -> gen_sctp:send(Sb, SbAssocId, 0, Data) end),
- ?line case log_ok(gen_sctp:recv(Sa, infinity)) of
- {Loopback,Pb,
- [#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SaAssocId}],
- Data} -> ok;
- Event1 ->
- ?line {Loopback,Pb,
- #sctp_paddr_change{state=addr_confirmed,
- addr={_,Pb},
- error=0,
- assoc_id=SaAssocId}} =
- recv_event(Event1),
- ?line {Loopback,Pb,
- [#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SaAssocId}],
- Data} =
- log_ok(gen_sctp:recv(Sa, infinity))
- end,
- ?line ok = gen_sctp:close(Sa),
- ?line {Loopback,Pa,
- #sctp_shutdown_event{assoc_id=SbAssocId}} =
+ case log_ok(gen_sctp:recv(Sa, infinity)) of
+ {Loopback,Pb,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SaAssocId}],
+ Data} -> ok;
+ Event1 ->
+ {Loopback,Pb,
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={_,Pb},
+ error=0,
+ assoc_id=SaAssocId}} =
+ recv_event(Event1),
+ {Loopback,Pb,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SaAssocId}],
+ Data} =
+ log_ok(gen_sctp:recv(Sa, infinity))
+ end,
+ ok = gen_sctp:close(Sa),
+ {Loopback,Pa,
+ #sctp_shutdown_event{assoc_id=SbAssocId}} =
recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
- ?line {Loopback,Pa,
- #sctp_assoc_change{state=shutdown_comp,
- error=0,
- assoc_id=SbAssocId}} =
+ {Loopback,Pa,
+ #sctp_assoc_change{state=shutdown_comp,
+ error=0,
+ assoc_id=SbAssocId}} =
recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
- ?line ok = gen_sctp:close(Sb),
+ ok = gen_sctp:close(Sb),
- ?line receive
- Msg -> test_server:fail({received,Msg})
- after 17 -> ok
- end,
+ receive
+ Msg -> ct:fail({received,Msg})
+ after 17 -> ok
+ end,
ok.
@@ -1058,205 +1023,184 @@ do_from_other_process(Fun) ->
end.
-peeloff_active_once(doc) ->
- "Peel off an SCTP stream socket ({active,once})";
-peeloff_active_once(suite) ->
- [];
+%% Peel off an SCTP stream socket ({active,once}).
peeloff_active_once(Config) ->
peeloff(Config, [{active,once}]).
-peeloff_active_true(doc) ->
- "Peel off an SCTP stream socket ({active,true})";
-peeloff_active_true(suite) ->
- [];
+%% Peel off an SCTP stream socket ({active,true}).
peeloff_active_true(Config) ->
peeloff(Config, [{active,true}]).
-peeloff_active_n(doc) ->
- "Peel off an SCTP stream socket ({active,N})";
-peeloff_active_n(suite) ->
- [];
+%% Peel off an SCTP stream socket ({active,N}).
peeloff_active_n(Config) ->
peeloff(Config, [{active,1}]).
peeloff(Config, SockOpts) when is_list(Config) ->
- ?line Addr = {127,0,0,1},
- ?line Stream = 0,
- ?line Timeout = 333,
- ?line S1 = socket_open([{ifaddr,Addr}|SockOpts], Timeout),
- ?line ?LOGVAR(S1),
- ?line P1 = socket_call(S1, get_port),
- ?line ?LOGVAR(P1),
- ?line Socket1 = socket_call(S1, get_socket),
- ?line ?LOGVAR(Socket1),
- ?line socket_call(S1, {listen,true}),
- ?line S2 = socket_open([{ifaddr,Addr}|SockOpts], Timeout),
- ?line ?LOGVAR(S2),
- ?line P2 = socket_call(S2, get_port),
- ?line ?LOGVAR(P2),
- ?line Socket2 = socket_call(S2, get_socket),
- ?line ?LOGVAR(Socket2),
+ Addr = {127,0,0,1},
+ Stream = 0,
+ Timeout = 333,
+ S1 = socket_open([{ifaddr,Addr}|SockOpts], Timeout),
+ ?LOGVAR(S1),
+ P1 = socket_call(S1, get_port),
+ ?LOGVAR(P1),
+ Socket1 = socket_call(S1, get_socket),
+ ?LOGVAR(Socket1),
+ socket_call(S1, {listen,true}),
+ S2 = socket_open([{ifaddr,Addr}|SockOpts], Timeout),
+ ?LOGVAR(S2),
+ P2 = socket_call(S2, get_port),
+ ?LOGVAR(P2),
+ Socket2 = socket_call(S2, get_socket),
+ ?LOGVAR(Socket2),
%%
- ?line socket_call(S2, {connect_init,Addr,P1,[]}),
- ?line S2Ai =
+ socket_call(S2, {connect_init,Addr,P1,[]}),
+ S2Ai =
receive
{S2,{Addr,P1,
#sctp_assoc_change{
- state=comm_up,
- assoc_id=AssocId2}}} -> AssocId2
+ state=comm_up,
+ assoc_id=AssocId2}}} -> AssocId2
after Timeout ->
socket_bailout([S1,S2])
end,
- ?line ?LOGVAR(S2Ai),
- ?line S1Ai =
+ ?LOGVAR(S2Ai),
+ S1Ai =
receive
{S1,{Addr,P2,
#sctp_assoc_change{
- state=comm_up,
- assoc_id=AssocId1}}} -> AssocId1
+ state=comm_up,
+ assoc_id=AssocId1}}} -> AssocId1
after Timeout ->
socket_bailout([S1,S2])
end,
- ?line ?LOGVAR(S1Ai),
+ ?LOGVAR(S1Ai),
%%
- ?line socket_call(S2, {send,S2Ai,Stream,<<"Number one">>}),
- ?line
- receive
- {S1,{Addr,P2,S1Ai,Stream,<<"Number one">>}} -> ok
- after Timeout ->
- socket_bailout([S1,S2])
- end,
- ?line socket_call(S2, {send,Socket1,S1Ai,Stream,<<"Number two">>}),
- ?line
- receive
- {S2,{Addr,P1,S2Ai,Stream,<<"Number two">>}} -> ok
- after Timeout ->
- socket_bailout([S1,S2])
- end,
+ socket_call(S2, {send,S2Ai,Stream,<<"Number one">>}),
+ receive
+ {S1,{Addr,P2,S1Ai,Stream,<<"Number one">>}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ socket_call(S2, {send,Socket1,S1Ai,Stream,<<"Number two">>}),
+ receive
+ {S2,{Addr,P1,S2Ai,Stream,<<"Number two">>}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
%%
- ?line S3 = socket_peeloff(Socket1, S1Ai, SockOpts, Timeout),
- ?line ?LOGVAR(S3),
- ?line P3_X = socket_call(S3, get_port),
- ?line ?LOGVAR(P3_X),
- ?line P3 = case P3_X of 0 -> P1; _ -> P3_X end,
- ?line [{_,#sctp_paddrinfo{assoc_id=S3Ai,state=active}}] =
+ S3 = socket_peeloff(Socket1, S1Ai, SockOpts, Timeout),
+ ?LOGVAR(S3),
+ P3_X = socket_call(S3, get_port),
+ ?LOGVAR(P3_X),
+ P3 = case P3_X of 0 -> P1; _ -> P3_X end,
+ [{_,#sctp_paddrinfo{assoc_id=S3Ai,state=active}}] =
socket_call(S3,
{getopts,[{sctp_get_peer_addr_info,
#sctp_paddrinfo{address={Addr,P2}}}]}),
- %%?line S3Ai = S1Ai,
- ?line ?LOGVAR(S3Ai),
+ %%S3Ai = S1Ai,
+ ?LOGVAR(S3Ai),
%%
- ?line socket_call(S3, {send,S3Ai,Stream,<<"Number three">>}),
- ?line
- receive
- {S2,{Addr,P3,S2Ai,Stream,<<"Number three">>}} -> ok
- after Timeout ->
- socket_bailout([S1,S2,S3])
- end,
- ?line socket_call(S3, {send,Socket2,S2Ai,Stream,<<"Number four">>}),
- ?line
- receive
- {S3,{Addr,P2,S3Ai,Stream,<<"Number four">>}} -> ok
- after Timeout ->
- socket_bailout([S1,S2,S3])
- end,
+ socket_call(S3, {send,S3Ai,Stream,<<"Number three">>}),
+ receive
+ {S2,{Addr,P3,S2Ai,Stream,<<"Number three">>}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2,S3])
+ end,
+ socket_call(S3, {send,Socket2,S2Ai,Stream,<<"Number four">>}),
+ receive
+ {S3,{Addr,P2,S3Ai,Stream,<<"Number four">>}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2,S3])
+ end,
%%
- ?line inet:i(sctp),
- ?line socket_close_verbose(S1),
- ?line socket_close_verbose(S2),
- ?line
- receive
- {S3,{Addr,P2,#sctp_shutdown_event{assoc_id=S3Ai_X}}} ->
- ?line match_unless_solaris(S3Ai, S3Ai_X)
- after Timeout ->
- socket_bailout([S3])
- end,
- ?line
- receive
- {S3,{Addr,P2,#sctp_assoc_change{state=shutdown_comp,
- assoc_id=S3Ai}}} -> ok
- after Timeout ->
- socket_bailout([S3])
- end,
- ?line socket_close_verbose(S3),
- ?line [] = flush(),
+ inet:i(sctp),
+ socket_close_verbose(S1),
+ socket_close_verbose(S2),
+ receive
+ {S3,{Addr,P2,#sctp_shutdown_event{assoc_id=S3Ai_X}}} ->
+ match_unless_solaris(S3Ai, S3Ai_X)
+ after Timeout ->
+ socket_bailout([S3])
+ end,
+ receive
+ {S3,{Addr,P2,#sctp_assoc_change{state=shutdown_comp,
+ assoc_id=S3Ai}}} -> ok
+ after Timeout ->
+ socket_bailout([S3])
+ end,
+ socket_close_verbose(S3),
+ [] = flush(),
ok.
-buffers(doc) ->
- ["Check sndbuf and recbuf behaviour"];
-buffers(suite) ->
- [];
+%% Check sndbuf and recbuf behaviour.
buffers(Config) when is_list(Config) ->
- ?line Limit = 4096,
- ?line Addr = {127,0,0,1},
- ?line Stream = 1,
- ?line Timeout = 3333,
- ?line S1 = socket_open([{ip,Addr}], Timeout),
- ?line ?LOGVAR(S1),
- ?line P1 = socket_call(S1, get_port),
- ?line ?LOGVAR(P1),
- ?line ok = socket_call(S1, {listen,true}),
- ?line S2 = socket_open([{ip,Addr}], Timeout),
- ?line ?LOGVAR(S2),
- ?line P2 = socket_call(S2, get_port),
- ?line ?LOGVAR(P2),
+ Limit = 4096,
+ Addr = {127,0,0,1},
+ Stream = 1,
+ Timeout = 3333,
+ S1 = socket_open([{ip,Addr}], Timeout),
+ ?LOGVAR(S1),
+ P1 = socket_call(S1, get_port),
+ ?LOGVAR(P1),
+ ok = socket_call(S1, {listen,true}),
+ S2 = socket_open([{ip,Addr}], Timeout),
+ ?LOGVAR(S2),
+ P2 = socket_call(S2, get_port),
+ ?LOGVAR(P2),
%%
- ?line socket_call(S2, {connect_init,Addr,P1,[]}),
- ?line S2Ai =
+ socket_call(S2, {connect_init,Addr,P1,[]}),
+ S2Ai =
receive
{S2,{Addr,P1,
#sctp_assoc_change{
- state=comm_up,
- assoc_id=AssocId2}}} -> AssocId2
+ state=comm_up,
+ assoc_id=AssocId2}}} -> AssocId2
after Timeout ->
socket_bailout([S1,S2])
end,
- ?line S1Ai =
+ S1Ai =
receive
{S1,{Addr,P2,
#sctp_assoc_change{
- state=comm_up,
- assoc_id=AssocId1}}} -> AssocId1
+ state=comm_up,
+ assoc_id=AssocId1}}} -> AssocId1
after Timeout ->
socket_bailout([S1,S2])
end,
%%
- ?line socket_call(S1, {setopts,[{recbuf,Limit}]}),
- ?line Recbuf =
+ socket_call(S1, {setopts,[{recbuf,Limit}]}),
+ Recbuf =
case socket_call(S1, {getopts,[recbuf]}) of
[{recbuf,RB1}] when RB1 >= Limit -> RB1
end,
- ?line Data = mk_data(Recbuf+Limit),
- ?line socket_call(S2, {setopts,[{sndbuf,Recbuf+Limit}]}),
- ?line socket_call(S2, {send,S2Ai,Stream,Data}),
- ?line
- receive
- {S1,{Addr,P2,S1Ai,Stream,Data}} -> ok
- after Timeout ->
- socket_bailout([S1,S2])
- end,
+ Data = mk_data(Recbuf+Limit),
+ socket_call(S2, {setopts,[{sndbuf,Recbuf+Limit}]}),
+ socket_call(S2, {send,S2Ai,Stream,Data}),
+ receive
+ {S1,{Addr,P2,S1Ai,Stream,Data}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
%%
- ?line socket_close_verbose(S1),
- ?line
- receive
- {S2,{Addr,P1,#sctp_shutdown_event{assoc_id=S2Ai}}} -> ok
- after Timeout ->
- socket_bailout([S2])
- end,
- ?line
- receive
- {S2,{Addr,P1,#sctp_assoc_change{state=shutdown_comp,
- assoc_id=S2Ai}}} -> ok
- after Timeout ->
- socket_bailout([S2])
- end,
- ?line socket_close_verbose(S2),
- ?line [] = flush(),
+ socket_close_verbose(S1),
+ receive
+ {S2,{Addr,P1,#sctp_shutdown_event{assoc_id=S2Ai}}} -> ok
+ after Timeout ->
+ socket_bailout([S2])
+ end,
+ receive
+ {S2,{Addr,P1,#sctp_assoc_change{state=shutdown_comp,
+ assoc_id=S2Ai}}} -> ok
+ after Timeout ->
+ socket_bailout([S2])
+ end,
+ socket_close_verbose(S2),
+ [] = flush(),
ok.
mk_data(Bytes) ->
@@ -1269,153 +1213,129 @@ mk_data(_, _, Bin) ->
-open_multihoming_ipv4_socket(doc) ->
- "Test opening a multihoming ipv4 socket";
-open_multihoming_ipv4_socket(suite) ->
- [];
+%% Test opening a multihoming ipv4 socket.
open_multihoming_ipv4_socket(Config) when is_list(Config) ->
- ?line case get_addrs_by_family(inet, 2) of
- {ok, [Addr1, Addr2]} ->
- ?line do_open_and_connect([Addr1, Addr2], Addr1);
- {error, Reason} ->
- {skip, Reason}
- end.
-
-open_unihoming_ipv6_socket(doc) ->
- %% This test is mostly aimed to indicate
- %% whether host has a non-working ipv6 setup
- "Test opening a unihoming (non-multihoming) ipv6 socket";
-open_unihoming_ipv6_socket(suite) ->
- [];
+ case get_addrs_by_family(inet, 2) of
+ {ok, [Addr1, Addr2]} ->
+ do_open_and_connect([Addr1, Addr2], Addr1);
+ {error, Reason} ->
+ {skip, Reason}
+ end.
+
+%% This test is mostly aimed to indicate whether host has a
+%% non-working ipv6 setup. Test opening a unihoming (non-multihoming)
+%% ipv6 socket.
open_unihoming_ipv6_socket(Config) when is_list(Config) ->
- ?line case get_addrs_by_family(inet6, 1) of
- {ok, [Addr]} ->
- ?line do_open_and_connect([Addr], Addr);
- {error, Reason} ->
- {skip, Reason}
- end.
-
-
-open_multihoming_ipv6_socket(doc) ->
- "Test opening a multihoming ipv6 socket";
-open_multihoming_ipv6_socket(suite) ->
- [];
+ case get_addrs_by_family(inet6, 1) of
+ {ok, [Addr]} ->
+ do_open_and_connect([Addr], Addr);
+ {error, Reason} ->
+ {skip, Reason}
+ end.
+
+
+%% Test opening a multihoming ipv6 socket.
open_multihoming_ipv6_socket(Config) when is_list(Config) ->
- ?line case get_addrs_by_family(inet6, 2) of
- {ok, [Addr1, Addr2]} ->
- ?line do_open_and_connect([Addr1, Addr2], Addr1);
- {error, Reason} ->
- {skip, Reason}
- end.
-
-open_multihoming_ipv4_and_ipv6_socket(doc) ->
- "Test opening a multihoming ipv6 socket with ipv4 and ipv6 addresses";
-open_multihoming_ipv4_and_ipv6_socket(suite) ->
- [];
+ case get_addrs_by_family(inet6, 2) of
+ {ok, [Addr1, Addr2]} ->
+ do_open_and_connect([Addr1, Addr2], Addr1);
+ {error, Reason} ->
+ {skip, Reason}
+ end.
+
+%% Test opening a multihoming ipv6 socket with ipv4 and ipv6 addresses.
open_multihoming_ipv4_and_ipv6_socket(Config) when is_list(Config) ->
- ?line case get_addrs_by_family(inet_and_inet6, 2) of
- {ok, [[InetAddr1, InetAddr2], [Inet6Addr1, Inet6Addr2]]} ->
- %% Connect to the first address to test bind
- ?line do_open_and_connect([InetAddr1, Inet6Addr1, InetAddr2],
- InetAddr1),
- ?line do_open_and_connect([Inet6Addr1, InetAddr1],
- Inet6Addr1),
-
- %% Connect an address, not the first,
- %% to test sctp_bindx
- ?line do_open_and_connect([Inet6Addr1, Inet6Addr2, InetAddr1],
- Inet6Addr2),
- ?line do_open_and_connect([Inet6Addr1, Inet6Addr2, InetAddr1],
- InetAddr1);
- {error, Reason} ->
- {skip, Reason}
- end.
-
-names_unihoming_ipv4(doc) ->
- "Test inet:socknames/peernames on unihoming IPv4 sockets";
-names_unihoming_ipv4(suite) ->
- [];
+ case get_addrs_by_family(inet_and_inet6, 2) of
+ {ok, [[InetAddr1, InetAddr2], [Inet6Addr1, Inet6Addr2]]} ->
+ %% Connect to the first address to test bind
+ do_open_and_connect([InetAddr1, Inet6Addr1, InetAddr2],
+ InetAddr1),
+ do_open_and_connect([Inet6Addr1, InetAddr1],
+ Inet6Addr1),
+
+ %% Connect an address, not the first,
+ %% to test sctp_bindx
+ do_open_and_connect([Inet6Addr1, Inet6Addr2, InetAddr1],
+ Inet6Addr2),
+ do_open_and_connect([Inet6Addr1, Inet6Addr2, InetAddr1],
+ InetAddr1);
+ {error, Reason} ->
+ {skip, Reason}
+ end.
+
+%% Test inet:socknames/peernames on unihoming IPv4 sockets.
names_unihoming_ipv4(Config) when is_list(Config) ->
- ?line do_names(Config, inet, 1).
+ do_names(Config, inet, 1).
-names_unihoming_ipv6(doc) ->
- "Test inet:socknames/peernames on unihoming IPv6 sockets";
-names_unihoming_ipv6(suite) ->
- [];
+%% Test inet:socknames/peernames on unihoming IPv6 sockets.
names_unihoming_ipv6(Config) when is_list(Config) ->
- ?line do_names(Config, inet6, 1).
+ do_names(Config, inet6, 1).
-names_multihoming_ipv4(doc) ->
- "Test inet:socknames/peernames on multihoming IPv4 sockets";
-names_multihoming_ipv4(suite) ->
- [];
+%% Test inet:socknames/peernames on multihoming IPv4 sockets.
names_multihoming_ipv4(Config) when is_list(Config) ->
- ?line do_names(Config, inet, 2).
+ do_names(Config, inet, 2).
-names_multihoming_ipv6(doc) ->
- "Test inet:socknames/peernames on multihoming IPv6 sockets";
-names_multihoming_ipv6(suite) ->
- [];
+%% Test inet:socknames/peernames on multihoming IPv6 sockets.
names_multihoming_ipv6(Config) when is_list(Config) ->
- ?line do_names(Config, inet6, 2).
+ do_names(Config, inet6, 2).
do_names(_, FamilySpec, AddressCount) ->
Fun =
fun (ServerSocket, _, ServerAssoc, ClientSocket, _, ClientAssoc) ->
- ?line ServerSocknamesNoassoc =
+ ServerSocknamesNoassoc =
lists:sort(ok(inet:socknames(ServerSocket))),
- ?line ?LOGVAR(ServerSocknamesNoassoc),
- ?line ServerSocknames =
+ ?LOGVAR(ServerSocknamesNoassoc),
+ ServerSocknames =
lists:sort(ok(inet:socknames(ServerSocket, ServerAssoc))),
- ?line ?LOGVAR(ServerSocknames),
- ?line [_|_] =
+ ?LOGVAR(ServerSocknames),
+ [_|_] =
ordsets:intersection
(ServerSocknamesNoassoc, ServerSocknames),
- ?line ClientSocknamesNoassoc =
+ ClientSocknamesNoassoc =
lists:sort(ok(inet:socknames(ClientSocket))),
- ?line ?LOGVAR(ClientSocknamesNoassoc),
- ?line ClientSocknames =
+ ?LOGVAR(ClientSocknamesNoassoc),
+ ClientSocknames =
lists:sort(ok(inet:socknames(ClientSocket, ClientAssoc))),
- ?line ?LOGVAR(ClientSocknames),
- ?line [_|_] =
+ ?LOGVAR(ClientSocknames),
+ [_|_] =
ordsets:intersection
(ClientSocknamesNoassoc, ClientSocknames),
- ?line err([einval,enotconn], inet:peernames(ServerSocket)),
- ?line ServerPeernames =
+ err([einval,enotconn], inet:peernames(ServerSocket)),
+ ServerPeernames =
lists:sort(ok(inet:peernames(ServerSocket, ServerAssoc))),
- ?line ?LOGVAR(ServerPeernames),
- ?line err([einval,enotconn], inet:peernames(ClientSocket)),
- ?line ClientPeernames =
+ ?LOGVAR(ServerPeernames),
+ err([einval,enotconn], inet:peernames(ClientSocket)),
+ ClientPeernames =
lists:sort(ok(inet:peernames(ClientSocket, ClientAssoc))),
- ?line ?LOGVAR(ClientPeernames),
- ?line ServerSocknames = ClientPeernames,
- ?line ClientSocknames = ServerPeernames,
- ?line {ok,Socket} =
+ ?LOGVAR(ClientPeernames),
+ ServerSocknames = ClientPeernames,
+ ClientSocknames = ServerPeernames,
+ {ok,Socket} =
gen_sctp:peeloff(ServerSocket, ServerAssoc),
- ?line SocknamesNoassoc =
+ SocknamesNoassoc =
lists:sort(ok(inet:socknames(Socket))),
- ?line ?LOGVAR(SocknamesNoassoc),
- ?line Socknames =
+ ?LOGVAR(SocknamesNoassoc),
+ Socknames =
lists:sort(ok(inet:socknames(Socket, ServerAssoc))),
- ?line ?LOGVAR(Socknames),
- ?line true =
+ ?LOGVAR(Socknames),
+ true =
ordsets:is_subset(SocknamesNoassoc, Socknames),
- ?line Peernames =
+ Peernames =
lists:sort(ok(inet:peernames(Socket, ServerAssoc))),
- ?line ?LOGVAR(Peernames),
- ?line ok = gen_sctp:close(Socket),
- ?line Socknames = ClientPeernames,
- ?line ClientSocknames = Peernames,
+ ?LOGVAR(Peernames),
+ ok = gen_sctp:close(Socket),
+ Socknames = ClientPeernames,
+ ClientSocknames = Peernames,
ok
end,
- ?line case get_addrs_by_family(FamilySpec, AddressCount) of
- {ok, Addresses} when length(Addresses) =:= AddressCount ->
- ?line do_open_and_connect(Addresses, hd(Addresses), Fun);
- {error, Reason} ->
- {skip, Reason}
- end.
+ case get_addrs_by_family(FamilySpec, AddressCount) of
+ {ok, Addresses} when length(Addresses) =:= AddressCount ->
+ do_open_and_connect(Addresses, hd(Addresses), Fun);
+ {error, Reason} ->
+ {skip, Reason}
+ end.
@@ -1451,29 +1371,28 @@ get_addrs_by_family(Family, NumAddrs) ->
get_addrs_by_family_aux(Family, NumAddrs) when Family =:= inet;
Family =:= inet6 ->
- ?line
- case inet:getaddr(localhost, Family) of
- {error,eafnosupport} ->
- {skip, f("No support for ~p", Family)};
- {ok, _} ->
- ?line IfAddrs = ok(inet:getifaddrs()),
- ?line case filter_addrs_by_family(IfAddrs, Family) of
- Addrs when length(Addrs) >= NumAddrs ->
- {ok, lists:sublist(Addrs, NumAddrs)};
- [] ->
- {error, f("Need ~p ~p address(es) found none~n",
- [NumAddrs, Family])};
- Addrs ->
- {error,
- f("Need ~p ~p address(es) found only ~p: ~p~n",
- [NumAddrs, Family, length(Addrs), Addrs])}
- end
- end;
+ case inet:getaddr(localhost, Family) of
+ {error,eafnosupport} ->
+ {skip, f("No support for ~p", Family)};
+ {ok, _} ->
+ IfAddrs = ok(inet:getifaddrs()),
+ case filter_addrs_by_family(IfAddrs, Family) of
+ Addrs when length(Addrs) >= NumAddrs ->
+ {ok, lists:sublist(Addrs, NumAddrs)};
+ [] ->
+ {error, f("Need ~p ~p address(es) found none~n",
+ [NumAddrs, Family])};
+ Addrs ->
+ {error,
+ f("Need ~p ~p address(es) found only ~p: ~p~n",
+ [NumAddrs, Family, length(Addrs), Addrs])}
+ end
+ end;
get_addrs_by_family_aux(inet_and_inet6, NumAddrs) ->
- ?line catch {ok, [case get_addrs_by_family_aux(Family, NumAddrs) of
- {ok, Addrs} -> Addrs;
- {error, Reason} -> throw({error, Reason})
- end || Family <- [inet, inet6]]}.
+ catch {ok, [case get_addrs_by_family_aux(Family, NumAddrs) of
+ {ok, Addrs} -> Addrs;
+ {error, Reason} -> throw({error, Reason})
+ end || Family <- [inet, inet6]]}.
filter_addrs_by_family(IfAddrs, Family) ->
lists:flatten([[Addr || {addr, Addr} <- Info,
@@ -1502,21 +1421,21 @@ f(F, A) ->
lists:flatten(io_lib:format(F, A)).
do_open_and_connect(ServerAddresses, AddressToConnectTo) ->
- ?line Fun = fun (_, _, _, _, _, _) -> ok end,
- ?line do_open_and_connect(ServerAddresses, AddressToConnectTo, Fun).
+ Fun = fun (_, _, _, _, _, _) -> ok end,
+ do_open_and_connect(ServerAddresses, AddressToConnectTo, Fun).
%%
do_open_and_connect(ServerAddresses, AddressToConnectTo, Fun) ->
- ?line ServerFamily = get_family_by_addrs(ServerAddresses),
- ?line io:format("Serving ~p addresses: ~p~n",
- [ServerFamily, ServerAddresses]),
- ?line S1 = ok(gen_sctp:open(0, [{ip,Addr} || Addr <- ServerAddresses] ++
- [ServerFamily])),
- ?line ok = gen_sctp:listen(S1, true),
- ?line P1 = ok(inet:port(S1)),
- ?line ClientFamily = get_family_by_addr(AddressToConnectTo),
- ?line io:format("Connecting to ~p ~p~n",
- [ClientFamily, AddressToConnectTo]),
- ?line ClientOpts =
+ ServerFamily = get_family_by_addrs(ServerAddresses),
+ io:format("Serving ~p addresses: ~p~n",
+ [ServerFamily, ServerAddresses]),
+ S1 = ok(gen_sctp:open(0, [{ip,Addr} || Addr <- ServerAddresses] ++
+ [ServerFamily])),
+ ok = gen_sctp:listen(S1, true),
+ P1 = ok(inet:port(S1)),
+ ClientFamily = get_family_by_addr(AddressToConnectTo),
+ io:format("Connecting to ~p ~p~n",
+ [ClientFamily, AddressToConnectTo]),
+ ClientOpts =
[ClientFamily |
case ClientFamily of
inet6 ->
@@ -1524,39 +1443,39 @@ do_open_and_connect(ServerAddresses, AddressToConnectTo, Fun) ->
_ ->
[]
end],
- ?line S2 = ok(gen_sctp:open(0, ClientOpts)),
+ S2 = ok(gen_sctp:open(0, ClientOpts)),
log(open),
%% Verify client can connect
- ?line #sctp_assoc_change{state=comm_up} = S2Assoc =
+ #sctp_assoc_change{state=comm_up} = S2Assoc =
ok(gen_sctp:connect(S2, AddressToConnectTo, P1, [])),
log(comm_up),
%% verify server side also receives comm_up from client
- ?line S1Assoc = recv_comm_up_eventually(S1),
- ?line Result = Fun(S1, ServerFamily, S1Assoc, S2, ClientFamily, S2Assoc),
- ?line ok = gen_sctp:close(S2),
- ?line ok = gen_sctp:close(S1),
+ S1Assoc = recv_comm_up_eventually(S1),
+ Result = Fun(S1, ServerFamily, S1Assoc, S2, ClientFamily, S2Assoc),
+ ok = gen_sctp:close(S2),
+ ok = gen_sctp:close(S1),
Result.
%% If at least one of the addresses is an ipv6 address, return inet6, else inet.
get_family_by_addrs(Addresses) ->
- ?line case lists:usort([get_family_by_addr(Addr) || Addr <- Addresses]) of
- [inet, inet6] -> inet6;
- [inet] -> inet;
- [inet6] -> inet6
- end.
+ case lists:usort([get_family_by_addr(Addr) || Addr <- Addresses]) of
+ [inet, inet6] -> inet6;
+ [inet] -> inet;
+ [inet6] -> inet6
+ end.
get_family_by_addr(Addr) when tuple_size(Addr) =:= 4 -> inet;
get_family_by_addr(Addr) when tuple_size(Addr) =:= 8 -> inet6.
recv_comm_up_eventually(S) ->
- ?line case ok(gen_sctp:recv(S)) of
- {_Addr, _Port, _Info,
- #sctp_assoc_change{state=comm_up} = Assoc} ->
- Assoc;
- {_Addr, _Port, _Info, _OtherSctpMsg} = Msg ->
- ?line log({unexpected,Msg}),
- ?line recv_comm_up_eventually(S)
- end.
+ case ok(gen_sctp:recv(S)) of
+ {_Addr, _Port, _Info,
+ #sctp_assoc_change{state=comm_up} = Assoc} ->
+ Assoc;
+ {_Addr, _Port, _Info, _OtherSctpMsg} = Msg ->
+ log({unexpected,Msg}),
+ recv_comm_up_eventually(S)
+ end.
%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% socket gen_server ultra light
@@ -1609,7 +1528,7 @@ socket_bailout([S|Ss]) ->
socket_bailout(Ss);
socket_bailout([]) ->
io:format("flush: ~p.~n", [flush()]),
- test_server:fail(socket_bailout).
+ ct:fail(socket_bailout).
socket_history({State,Flush}) ->
{lists:keysort(
@@ -1697,8 +1616,8 @@ s_loop(Socket, Timeout, Parent, Handler, State) ->
case gb_get({assoc_change,AssocId}, State) of
[{_,{Addr,Port,
#sctp_assoc_change{
- state=comm_up,
- inbound_streams=Is}}}|_]
+ state=comm_up,
+ inbound_streams=Is}}}|_]
when 0 =< Stream, Stream < Is-> ok;
[] -> ok
end,
diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl
index 962471c20c..4d829bcac6 100644
--- a/lib/kernel/test/gen_tcp_api_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_api_SUITE.erl
@@ -38,7 +38,9 @@
-export([getsockfd/0,closesockfd/1]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[{group, t_accept}, {group, t_connect}, {group, t_recv},
@@ -65,74 +67,67 @@ end_per_group(_,_Config) ->
ok.
init_per_testcase(_Func, Config) ->
- Dog = test_server:timetrap(test_server:seconds(60)),
- [{watchdog, Dog}|Config].
-end_per_testcase(_Func, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog).
+ Config.
+
+end_per_testcase(_Func, _Config) ->
+ ok.
%%% gen_tcp:accept/1,2
-t_accept_timeout(doc) -> "Test that gen_tcp:accept/2 (with timeout) works.";
-t_accept_timeout(suite) -> [];
+%% Test that gen_tcp:accept/2 (with timeout) works.
t_accept_timeout(Config) when is_list(Config) ->
- ?line {ok, L} = gen_tcp:listen(0, []),
- ?line timeout({gen_tcp, accept, [L, 200]}, 0.2, 1.0).
+ {ok, L} = gen_tcp:listen(0, []),
+ timeout({gen_tcp, accept, [L, 200]}, 0.2, 1.0).
%%% gen_tcp:connect/X
-t_connect_timeout(doc) -> "Test that gen_tcp:connect/4 (with timeout) works.";
+%% Test that gen_tcp:connect/4 (with timeout) works.
t_connect_timeout(Config) when is_list(Config) ->
- %%?line BadAddr = {134,138,177,16},
- %%?line TcpPort = 80,
- ?line {ok, BadAddr} = unused_ip(),
- ?line TcpPort = 45638,
- ?line ok = io:format("Connecting to ~p, port ~p", [BadAddr, TcpPort]),
- ?line connect_timeout({gen_tcp,connect,[BadAddr,TcpPort,[],200]}, 0.2, 5.0).
-
-t_connect_bad(doc) ->
- ["Test that gen_tcp:connect/3 handles non-existings hosts, and other ",
- "invalid things."];
-t_connect_bad(suite) -> [];
+ %%BadAddr = {134,138,177,16},
+ %%TcpPort = 80,
+ {ok, BadAddr} = unused_ip(),
+ TcpPort = 45638,
+ ok = io:format("Connecting to ~p, port ~p", [BadAddr, TcpPort]),
+ connect_timeout({gen_tcp,connect,[BadAddr,TcpPort,[],200]}, 0.2, 5.0).
+
+%% Test that gen_tcp:connect/3 handles non-existings hosts, and other
+%% invalid things.
t_connect_bad(Config) when is_list(Config) ->
- ?line NonExistingPort = 45638, % Not in use, I hope.
- ?line {error, Reason1} = gen_tcp:connect(localhost, NonExistingPort, []),
- ?line io:format("Error for connection attempt to port not in use: ~p",
- [Reason1]),
-
- ?line {error, Reason2} = gen_tcp:connect("non-existing-host-xxx", 7, []),
- ?line io:format("Error for connection attempt to non-existing host: ~p",
- [Reason2]),
+ NonExistingPort = 45638, % Not in use, I hope.
+ {error, Reason1} = gen_tcp:connect(localhost, NonExistingPort, []),
+ io:format("Error for connection attempt to port not in use: ~p",
+ [Reason1]),
+
+ {error, Reason2} = gen_tcp:connect("non-existing-host-xxx", 7, []),
+ io:format("Error for connection attempt to non-existing host: ~p",
+ [Reason2]),
ok.
%%% gen_tcp:recv/X
-t_recv_timeout(doc) -> "Test that gen_tcp:recv/3 (with timeout works).";
-t_recv_timeout(suite) -> [];
+%% Test that gen_tcp:recv/3 (with timeout works).
t_recv_timeout(Config) when is_list(Config) ->
- ?line {ok, L} = gen_tcp:listen(0, []),
- ?line {ok, Port} = inet:port(L),
- ?line {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]),
- ?line {ok, _A} = gen_tcp:accept(L),
- ?line timeout({gen_tcp, recv, [Client, 0, 200]}, 0.2, 5.0).
-
-t_recv_eof(doc) -> "Test that end of file on a socket is reported correctly.";
-t_recv_eof(suite) -> [];
+ {ok, L} = gen_tcp:listen(0, []),
+ {ok, Port} = inet:port(L),
+ {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]),
+ {ok, _A} = gen_tcp:accept(L),
+ timeout({gen_tcp, recv, [Client, 0, 200]}, 0.2, 5.0).
+
+%% Test that end of file on a socket is reported correctly.
t_recv_eof(Config) when is_list(Config) ->
- ?line {ok, L} = gen_tcp:listen(0, []),
- ?line {ok, Port} = inet:port(L),
- ?line {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]),
- ?line {ok, A} = gen_tcp:accept(L),
- ?line ok = gen_tcp:close(A),
- ?line {error, closed} = gen_tcp:recv(Client, 0),
+ {ok, L} = gen_tcp:listen(0, []),
+ {ok, Port} = inet:port(L),
+ {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]),
+ {ok, A} = gen_tcp:accept(L),
+ ok = gen_tcp:close(A),
+ {error, closed} = gen_tcp:recv(Client, 0),
ok.
-t_recv_delim(doc) -> "Test using message delimiter $X";
-t_recv_delim(suite) -> [];
+%% Test using message delimiter $X.
t_recv_delim(Config) when is_list(Config) ->
{ok, L} = gen_tcp:listen(0, []),
{ok, Port} = inet:port(L),
@@ -149,96 +144,96 @@ t_recv_delim(Config) when is_list(Config) ->
%%% gen_tcp:shutdown/2
t_shutdown_write(Config) when is_list(Config) ->
- ?line {ok, L} = gen_tcp:listen(0, []),
- ?line {ok, Port} = inet:port(L),
- ?line {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]),
- ?line {ok, A} = gen_tcp:accept(L),
- ?line ok = gen_tcp:shutdown(A, write),
- ?line {error, closed} = gen_tcp:recv(Client, 0),
+ {ok, L} = gen_tcp:listen(0, []),
+ {ok, Port} = inet:port(L),
+ {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]),
+ {ok, A} = gen_tcp:accept(L),
+ ok = gen_tcp:shutdown(A, write),
+ {error, closed} = gen_tcp:recv(Client, 0),
ok.
t_shutdown_both(Config) when is_list(Config) ->
- ?line {ok, L} = gen_tcp:listen(0, []),
- ?line {ok, Port} = inet:port(L),
- ?line {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]),
- ?line {ok, A} = gen_tcp:accept(L),
- ?line ok = gen_tcp:shutdown(A, read_write),
- ?line {error, closed} = gen_tcp:recv(Client, 0),
+ {ok, L} = gen_tcp:listen(0, []),
+ {ok, Port} = inet:port(L),
+ {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]),
+ {ok, A} = gen_tcp:accept(L),
+ ok = gen_tcp:shutdown(A, read_write),
+ {error, closed} = gen_tcp:recv(Client, 0),
ok.
t_shutdown_error(Config) when is_list(Config) ->
- ?line {ok, L} = gen_tcp:listen(0, []),
- ?line {error, enotconn} = gen_tcp:shutdown(L, read_write),
- ?line ok = gen_tcp:close(L),
- ?line {error, closed} = gen_tcp:shutdown(L, read_write),
+ {ok, L} = gen_tcp:listen(0, []),
+ {error, enotconn} = gen_tcp:shutdown(L, read_write),
+ ok = gen_tcp:close(L),
+ {error, closed} = gen_tcp:shutdown(L, read_write),
ok.
t_shutdown_async(Config) when is_list(Config) ->
- ?line {OS, _} = os:type(),
- ?line {ok, L} = gen_tcp:listen(0, [{sndbuf, 4096}]),
- ?line {ok, Port} = inet:port(L),
- ?line {ok, Client} = gen_tcp:connect(localhost, Port,
- [{recbuf, 4096},
- {active, false}]),
- ?line {ok, S} = gen_tcp:accept(L),
- ?line PayloadSize = 1024 * 1024,
- ?line Payload = lists:duplicate(PayloadSize, $.),
- ?line ok = gen_tcp:send(S, Payload),
- ?line case erlang:port_info(S, queue_size) of
- {queue_size, N} when N > 0 -> ok;
- {queue_size, 0} when OS =:= win32 -> ok;
- {queue_size, 0} = T -> ?t:fail({unexpected, T})
- end,
-
- ?line ok = gen_tcp:shutdown(S, write),
- ?line {ok, Buf} = gen_tcp:recv(Client, PayloadSize),
- ?line {error, closed} = gen_tcp:recv(Client, 0),
- ?line case length(Buf) of
- PayloadSize -> ok;
- Sz -> ?t:fail({payload_size,
- {expected, PayloadSize},
- {received, Sz}})
- end.
+ {OS, _} = os:type(),
+ {ok, L} = gen_tcp:listen(0, [{sndbuf, 4096}]),
+ {ok, Port} = inet:port(L),
+ {ok, Client} = gen_tcp:connect(localhost, Port,
+ [{recbuf, 4096},
+ {active, false}]),
+ {ok, S} = gen_tcp:accept(L),
+ PayloadSize = 1024 * 1024,
+ Payload = lists:duplicate(PayloadSize, $.),
+ ok = gen_tcp:send(S, Payload),
+ case erlang:port_info(S, queue_size) of
+ {queue_size, N} when N > 0 -> ok;
+ {queue_size, 0} when OS =:= win32 -> ok;
+ {queue_size, 0} = T -> ct:fail({unexpected, T})
+ end,
+
+ ok = gen_tcp:shutdown(S, write),
+ {ok, Buf} = gen_tcp:recv(Client, PayloadSize),
+ {error, closed} = gen_tcp:recv(Client, 0),
+ case length(Buf) of
+ PayloadSize -> ok;
+ Sz -> ct:fail({payload_size,
+ {expected, PayloadSize},
+ {received, Sz}})
+ end.
%%% gen_tcp:fdopen/2
t_fdopen(Config) when is_list(Config) ->
- ?line Question = "Aaaa... Long time ago in a small town in Germany,",
- ?line Question1 = list_to_binary(Question),
- ?line Question2 = [<<"Aaaa">>, "... ", $L, <<>>, $o, "ng time ago ",
- ["in ", [], <<"a small town">>, [" in Germany,", <<>>]]],
- ?line Question1 = iolist_to_binary(Question2),
- ?line Answer = "there was a shoemaker, Schumacher was his name.",
- ?line {ok, L} = gen_tcp:listen(0, [{active, false}]),
- ?line {ok, Port} = inet:port(L),
- ?line {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]),
- ?line {ok, A} = gen_tcp:accept(L),
- ?line {ok, FD} = prim_inet:getfd(A),
- ?line {ok, Server} = gen_tcp:fdopen(FD, []),
- ?line ok = gen_tcp:send(Client, Question),
- ?line {ok, Question} = gen_tcp:recv(Server, length(Question), 2000),
- ?line ok = gen_tcp:send(Client, Question1),
- ?line {ok, Question} = gen_tcp:recv(Server, length(Question), 2000),
- ?line ok = gen_tcp:send(Client, Question2),
- ?line {ok, Question} = gen_tcp:recv(Server, length(Question), 2000),
- ?line ok = gen_tcp:send(Server, Answer),
- ?line {ok, Answer} = gen_tcp:recv(Client, length(Answer), 2000),
- ?line ok = gen_tcp:close(Client),
- ?line {error,closed} = gen_tcp:recv(A, 1, 2000),
- ?line ok = gen_tcp:close(Server),
- ?line ok = gen_tcp:close(A),
- ?line ok = gen_tcp:close(L),
+ Question = "Aaaa... Long time ago in a small town in Germany,",
+ Question1 = list_to_binary(Question),
+ Question2 = [<<"Aaaa">>, "... ", $L, <<>>, $o, "ng time ago ",
+ ["in ", [], <<"a small town">>, [" in Germany,", <<>>]]],
+ Question1 = iolist_to_binary(Question2),
+ Answer = "there was a shoemaker, Schumacher was his name.",
+ {ok, L} = gen_tcp:listen(0, [{active, false}]),
+ {ok, Port} = inet:port(L),
+ {ok, Client} = gen_tcp:connect(localhost, Port, [{active, false}]),
+ {ok, A} = gen_tcp:accept(L),
+ {ok, FD} = prim_inet:getfd(A),
+ {ok, Server} = gen_tcp:fdopen(FD, []),
+ ok = gen_tcp:send(Client, Question),
+ {ok, Question} = gen_tcp:recv(Server, length(Question), 2000),
+ ok = gen_tcp:send(Client, Question1),
+ {ok, Question} = gen_tcp:recv(Server, length(Question), 2000),
+ ok = gen_tcp:send(Client, Question2),
+ {ok, Question} = gen_tcp:recv(Server, length(Question), 2000),
+ ok = gen_tcp:send(Server, Answer),
+ {ok, Answer} = gen_tcp:recv(Client, length(Answer), 2000),
+ ok = gen_tcp:close(Client),
+ {error,closed} = gen_tcp:recv(A, 1, 2000),
+ ok = gen_tcp:close(Server),
+ ok = gen_tcp:close(A),
+ ok = gen_tcp:close(L),
ok.
t_fdconnect(Config) when is_list(Config) ->
Question = "Aaaa... Long time ago in a small town in Germany,",
Question1 = list_to_binary(Question),
Question2 = [<<"Aaaa">>, "... ", $L, <<>>, $o, "ng time ago ",
- ["in ", [], <<"a small town">>, [" in Germany,", <<>>]]],
+ ["in ", [], <<"a small town">>, [" in Germany,", <<>>]]],
Question1 = iolist_to_binary(Question2),
Answer = "there was a shoemaker, Schumacher was his name.",
- Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
Lib = "gen_tcp_api_SUITE",
ok = erlang:load_nif(filename:join(Path,Lib), []),
{ok, L} = gen_tcp:listen(0, [{active, false}]),
@@ -266,53 +261,51 @@ t_fdconnect(Config) when is_list(Config) ->
%%% implicit inet6 option to api functions
t_implicit_inet6(Config) when is_list(Config) ->
- ?line Host = ok(inet:gethostname()),
- ?line
- case inet:getaddr(Host, inet6) of
- {ok,Addr} ->
- ?line t_implicit_inet6(Host, Addr);
- {error,Reason} ->
- {skip,
- "Can not look up IPv6 address: "
- ++atom_to_list(Reason)}
- end.
+ Host = ok(inet:gethostname()),
+ case inet:getaddr(Host, inet6) of
+ {ok,Addr} ->
+ t_implicit_inet6(Host, Addr);
+ {error,Reason} ->
+ {skip,
+ "Can not look up IPv6 address: "
+ ++atom_to_list(Reason)}
+ end.
t_implicit_inet6(Host, Addr) ->
- ?line
- case gen_tcp:listen(0, [inet6]) of
- {ok,S1} ->
- ?line Loopback = {0,0,0,0,0,0,0,1},
- ?line io:format("~s ~p~n", ["::1",Loopback]),
- ?line implicit_inet6(S1, Loopback),
- ?line ok = gen_tcp:close(S1),
- %%
- ?line Localhost = "localhost",
- ?line Localaddr = ok(inet:getaddr(Localhost, inet6)),
- ?line io:format("~s ~p~n", [Localhost,Localaddr]),
- ?line S2 = ok(gen_tcp:listen(0, [{ip,Localaddr}])),
- ?line implicit_inet6(S2, Localaddr),
- ?line ok = gen_tcp:close(S2),
- %%
- ?line io:format("~s ~p~n", [Host,Addr]),
- ?line S3 = ok(gen_tcp:listen(0, [{ifaddr,Addr}])),
- ?line implicit_inet6(S3, Addr),
- ?line ok = gen_tcp:close(S3);
- {error,_} ->
- {skip,"IPv6 not supported"}
- end.
+ case gen_tcp:listen(0, [inet6]) of
+ {ok,S1} ->
+ Loopback = {0,0,0,0,0,0,0,1},
+ io:format("~s ~p~n", ["::1",Loopback]),
+ implicit_inet6(S1, Loopback),
+ ok = gen_tcp:close(S1),
+ %%
+ Localhost = "localhost",
+ Localaddr = ok(inet:getaddr(Localhost, inet6)),
+ io:format("~s ~p~n", [Localhost,Localaddr]),
+ S2 = ok(gen_tcp:listen(0, [{ip,Localaddr}])),
+ implicit_inet6(S2, Localaddr),
+ ok = gen_tcp:close(S2),
+ %%
+ io:format("~s ~p~n", [Host,Addr]),
+ S3 = ok(gen_tcp:listen(0, [{ifaddr,Addr}])),
+ implicit_inet6(S3, Addr),
+ ok = gen_tcp:close(S3);
+ {error,_} ->
+ {skip,"IPv6 not supported"}
+ end.
implicit_inet6(S, Addr) ->
- ?line P = ok(inet:port(S)),
- ?line S2 = ok(gen_tcp:connect(Addr, P, [])),
- ?line P2 = ok(inet:port(S2)),
- ?line S1 = ok(gen_tcp:accept(S)),
- ?line P1 = P = ok(inet:port(S1)),
- ?line {Addr,P2} = ok(inet:peername(S1)),
- ?line {Addr,P1} = ok(inet:peername(S2)),
- ?line {Addr,P1} = ok(inet:sockname(S1)),
- ?line {Addr,P2} = ok(inet:sockname(S2)),
- ?line ok = gen_tcp:close(S2),
- ?line ok = gen_tcp:close(S1).
+ P = ok(inet:port(S)),
+ S2 = ok(gen_tcp:connect(Addr, P, [])),
+ P2 = ok(inet:port(S2)),
+ S1 = ok(gen_tcp:accept(S)),
+ P1 = P = ok(inet:port(S1)),
+ {Addr,P2} = ok(inet:peername(S1)),
+ {Addr,P1} = ok(inet:peername(S2)),
+ {Addr,P1} = ok(inet:sockname(S1)),
+ {Addr,P2} = ok(inet:sockname(S2)),
+ ok = gen_tcp:close(S2),
+ ok = gen_tcp:close(S1).
%%% Utilities
@@ -323,13 +316,13 @@ implicit_inet6(S, Addr) ->
timeout({M,F,A}, Lower, Upper) ->
case test_server:timecall(M, F, A) of
{Time, Result} when Time < Lower ->
- test_server:fail({too_short_time, Time, Result});
+ ct:fail({too_short_time, Time, Result});
{Time, Result} when Time > Upper ->
- test_server:fail({too_long_time, Time, Result});
+ ct:fail({too_long_time, Time, Result});
{_, {error, timeout}} ->
ok;
{_, Result} ->
- test_server:fail({unexpected_result, Result})
+ ct:fail({unexpected_result, Result})
end.
connect_timeout({M,F,A}, Lower, Upper) ->
@@ -344,28 +337,28 @@ connect_timeout({M,F,A}, Lower, Upper) ->
Pinfo = erlang:port_info(Socket),
Db = inet_db:lookup_socket(Socket),
Peer = inet:peername(Socket),
- test_server:fail({too_short_time, Time,
- [Result,Pinfo,Db,Peer]});
+ ct:fail({too_short_time, Time,
+ [Result,Pinfo,Db,Peer]});
_ ->
- test_server:fail({too_short_time, Time, Result})
+ ct:fail({too_short_time, Time, Result})
end;
{Time, Result} when Time > Upper ->
- test_server:fail({too_long_time, Time, Result});
+ ct:fail({too_long_time, Time, Result});
{_, {error, timeout}} ->
ok;
{_, Result} ->
- test_server:fail({unexpected_result, Result})
+ ct:fail({unexpected_result, Result})
end.
%% Try to obtain an unused IP address in the local network.
unused_ip() ->
- ?line {ok, Host} = inet:gethostname(),
- ?line {ok, Hent} = inet:gethostbyname(Host),
- ?line #hostent{h_addr_list=[{A, B, C, _D}|_]} = Hent,
+ {ok, Host} = inet:gethostname(),
+ {ok, Hent} = inet:gethostbyname(Host),
+ #hostent{h_addr_list=[{A, B, C, _D}|_]} = Hent,
%% Note: In our net, addresses below 16 are reserved for routers and
%% other strange creatures.
- ?line IP = unused_ip(A, B, C, 16),
+ IP = unused_ip(A, B, C, 16),
io:format("we = ~p, unused_ip = ~p~n", [Hent, IP]),
IP.
diff --git a/lib/kernel/test/gen_tcp_echo_SUITE.erl b/lib/kernel/test/gen_tcp_echo_SUITE.erl
index 6dcb21758b..f4b67af8c8 100644
--- a/lib/kernel/test/gen_tcp_echo_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_echo_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(gen_tcp_echo_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%%-compile(export_all).
@@ -34,7 +34,9 @@
-define(TPKT_VRSN, 3).
-define(LINE_LENGTH, 1023). % (default value of gen_tcp option 'recbuf') - 1
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,5}}].
all() ->
[active_echo, passive_echo, active_once_echo,
@@ -59,94 +61,75 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_Func, Config) ->
- Dog = test_server:timetrap(test_server:minutes(5)),
- [{watchdog, Dog}|Config].
-end_per_testcase(_Func, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog).
-
-active_echo(doc) ->
- ["Test sending packets of various sizes and various packet types ",
- "to the echo port and receiving them again (socket in active mode)."];
-active_echo(suite) -> [];
+ Config.
+
+end_per_testcase(_Func, _Config) ->
+ ok.
+
+%% Test sending packets of various sizes and various packet types
+%% to the echo port and receiving them again (socket in active mode).
active_echo(Config) when is_list(Config) ->
- ?line echo_test([], fun active_echo/4, [{echo, fun echo_server/0}]).
+ echo_test([], fun active_echo/4, [{echo, fun echo_server/0}]).
-passive_echo(doc) ->
- ["Test sending packets of various sizes and various packet types ",
- "to the echo port and receiving them again (socket in passive mode)."];
-passive_echo(suite) -> [];
+%% Test sending packets of various sizes and various packet types
+%% to the echo port and receiving them again (socket in passive mode).
passive_echo(Config) when is_list(Config) ->
- ?line echo_test([{active, false}], fun passive_echo/4,
- [{echo, fun echo_server/0}]).
+ echo_test([{active, false}], fun passive_echo/4,
+ [{echo, fun echo_server/0}]).
-active_once_echo(doc) ->
- ["Test sending packets of various sizes and various packet types ",
- "to the echo port and receiving them again (socket in active once mode)."];
-active_once_echo(suite) -> [];
+%% Test sending packets of various sizes and various packet types
+%% to the echo port and receiving them again (socket in active once mode).
active_once_echo(Config) when is_list(Config) ->
- ?line echo_test([{active, once}], fun active_once_echo/4,
- [{echo, fun echo_server/0}]).
-
-slow_active_echo(doc) ->
- ["Test sending packets of various sizes and various packet types ",
- "to the echo port and receiving them again (socket in active mode). ",
- "The echo server is a special one that delays between every character."];
-slow_active_echo(suite) -> [];
+ echo_test([{active, once}], fun active_once_echo/4,
+ [{echo, fun echo_server/0}]).
+
+%% Test sending packets of various sizes and various packet types
+%% to the echo port and receiving them again (socket in active mode).
+%% The echo server is a special one that delays between every character.
slow_active_echo(Config) when is_list(Config) ->
- ?line echo_test([], fun active_echo/4,
- [slow_echo, {echo, fun slow_echo_server/0}]).
-
-slow_passive_echo(doc) ->
- ["Test sending packets of various sizes and various packet types ",
- "to an echo server and receiving them again (socket in passive mode).",
- "The echo server is a special one that delays between every character."];
-slow_passive_echo(suite) -> [];
+ echo_test([], fun active_echo/4,
+ [slow_echo, {echo, fun slow_echo_server/0}]).
+
+%% Test sending packets of various sizes and various packet types
+%% to an echo server and receiving them again (socket in passive mode).
+%% The echo server is a special one that delays between every character.
slow_passive_echo(Config) when is_list(Config) ->
- ?line echo_test([{active, false}], fun passive_echo/4,
- [slow_echo, {echo, fun slow_echo_server/0}]).
-
-limit_active_echo(doc) ->
- ["Test sending packets of various sizes and various packet types ",
- "to the echo port and receiving them again (socket in active mode) "
- "with packet_size limitation."];
-limit_active_echo(suite) -> [];
+ echo_test([{active, false}], fun passive_echo/4,
+ [slow_echo, {echo, fun slow_echo_server/0}]).
+
+%% Test sending packets of various sizes and various packet types
+%% to the echo port and receiving them again (socket in active mode)
+%% with packet_size limitation.
limit_active_echo(Config) when is_list(Config) ->
- ?line echo_test([{packet_size, 10}],
- fun active_echo/4,
- [{packet_size, 10}, {echo, fun echo_server/0}]).
-
-limit_passive_echo(doc) ->
- ["Test sending packets of various sizes and various packet types ",
- "to the echo port and receiving them again (socket in passive mode) ",
- "with packet_size limitation."];
-limit_passive_echo(suite) -> [];
+ echo_test([{packet_size, 10}],
+ fun active_echo/4,
+ [{packet_size, 10}, {echo, fun echo_server/0}]).
+
+%% Test sending packets of various sizes and various packet types
+%% to the echo port and receiving them again (socket in passive mode)
+%% with packet_size limitation.
limit_passive_echo(Config) when is_list(Config) ->
- ?line echo_test([{packet_size, 10},{active, false}],
- fun passive_echo/4,
- [{packet_size, 10}, {echo, fun echo_server/0}]).
-
-large_limit_active_echo(doc) ->
- ["Test sending packets of various sizes and various packet types ",
- "to the echo port and receiving them again (socket in active mode) "
- "with large packet_size limitation."];
-large_limit_active_echo(suite) -> [];
+ echo_test([{packet_size, 10},{active, false}],
+ fun passive_echo/4,
+ [{packet_size, 10}, {echo, fun echo_server/0}]).
+
+%% Test sending packets of various sizes and various packet types
+%% to the echo port and receiving them again (socket in active mode)
+%% with large packet_size limitation.
large_limit_active_echo(Config) when is_list(Config) ->
- ?line echo_test([{packet_size, 10}],
- fun active_echo/4,
- [{packet_size, (1 bsl 32)-1},
- {echo, fun echo_server/0}]).
-
-large_limit_passive_echo(doc) ->
- ["Test sending packets of various sizes and various packet types ",
- "to the echo port and receiving them again (socket in passive mode) ",
- "with large packet_size limitation."];
-large_limit_passive_echo(suite) -> [];
+ echo_test([{packet_size, 10}],
+ fun active_echo/4,
+ [{packet_size, (1 bsl 32)-1},
+ {echo, fun echo_server/0}]).
+
+%% Test sending packets of various sizes and various packet types
+%% to the echo port and receiving them again (socket in passive mode)
+%% with large packet_size limitation.
large_limit_passive_echo(Config) when is_list(Config) ->
- ?line echo_test([{packet_size, 10},{active, false}],
- fun passive_echo/4,
- [{packet_size, (1 bsl 32) -1},
- {echo, fun echo_server/0}]).
+ echo_test([{packet_size, 10},{active, false}],
+ fun passive_echo/4,
+ [{packet_size, (1 bsl 32) -1},
+ {echo, fun echo_server/0}]).
echo_test(SockOpts, EchoFun, Config0) ->
echo_test_1(SockOpts, EchoFun, Config0),
@@ -154,53 +137,53 @@ echo_test(SockOpts, EchoFun, Config0) ->
echo_test_1([{delay_send,true}|SockOpts], EchoFun, Config0).
echo_test_1(SockOpts, EchoFun, Config0) ->
- ?line EchoSrvFun = ?config(echo, Config0),
- ?line {ok, EchoPort} = EchoSrvFun(),
- ?line Config = [{echo_port, EchoPort}|Config0],
-
- ?line echo_packet([{packet, 1}|SockOpts], EchoFun, Config),
- ?line echo_packet([{packet, 2}|SockOpts], EchoFun, Config),
- ?line echo_packet([{packet, 4}|SockOpts], EchoFun, Config),
- ?line echo_packet([{packet, sunrm}|SockOpts], EchoFun, Config),
- ?line echo_packet([{packet, cdr}|SockOpts], EchoFun,
- [{type, {cdr, big}}|Config]),
- ?line echo_packet([{packet, cdr}|SockOpts], EchoFun,
- [{type, {cdr, little}}|Config]),
- ?line case lists:keymember(packet_size, 1, SockOpts) of
- false ->
- % This is cheating, we should test that packet_size
- % also works for line and http.
- echo_packet([{packet, line}|SockOpts], EchoFun, Config),
- echo_packet([{packet, http}|SockOpts], EchoFun, Config),
- echo_packet([{packet, http_bin}|SockOpts], EchoFun, Config);
-
- true -> ok
- end,
- ?line echo_packet([{packet, tpkt}|SockOpts], EchoFun, Config),
-
- ?line ShortTag = [16#E0],
- ?line LongTag = [16#1F, 16#83, 16#27],
- ?line echo_packet([{packet, asn1}|SockOpts], EchoFun,
- [{type, {asn1, short, ShortTag}}|Config]),
- ?line echo_packet([{packet, asn1}|SockOpts], EchoFun,
- [{type, {asn1, long, ShortTag}}|Config]),
- ?line echo_packet([{packet, asn1}|SockOpts], EchoFun,
- [{type, {asn1, short, LongTag}}|Config]),
- ?line echo_packet([{packet, asn1}|SockOpts], EchoFun,
- [{type, {asn1, long, LongTag}}|Config]),
+ EchoSrvFun = proplists:get_value(echo, Config0),
+ {ok, EchoPort} = EchoSrvFun(),
+ Config = [{echo_port, EchoPort}|Config0],
+
+ echo_packet([{packet, 1}|SockOpts], EchoFun, Config),
+ echo_packet([{packet, 2}|SockOpts], EchoFun, Config),
+ echo_packet([{packet, 4}|SockOpts], EchoFun, Config),
+ echo_packet([{packet, sunrm}|SockOpts], EchoFun, Config),
+ echo_packet([{packet, cdr}|SockOpts], EchoFun,
+ [{type, {cdr, big}}|Config]),
+ echo_packet([{packet, cdr}|SockOpts], EchoFun,
+ [{type, {cdr, little}}|Config]),
+ case lists:keymember(packet_size, 1, SockOpts) of
+ false ->
+ %% This is cheating, we should test that packet_size
+ %% also works for line and http.
+ echo_packet([{packet, line}|SockOpts], EchoFun, Config),
+ echo_packet([{packet, http}|SockOpts], EchoFun, Config),
+ echo_packet([{packet, http_bin}|SockOpts], EchoFun, Config);
+
+ true -> ok
+ end,
+ echo_packet([{packet, tpkt}|SockOpts], EchoFun, Config),
+
+ ShortTag = [16#E0],
+ LongTag = [16#1F, 16#83, 16#27],
+ echo_packet([{packet, asn1}|SockOpts], EchoFun,
+ [{type, {asn1, short, ShortTag}}|Config]),
+ echo_packet([{packet, asn1}|SockOpts], EchoFun,
+ [{type, {asn1, long, ShortTag}}|Config]),
+ echo_packet([{packet, asn1}|SockOpts], EchoFun,
+ [{type, {asn1, short, LongTag}}|Config]),
+ echo_packet([{packet, asn1}|SockOpts], EchoFun,
+ [{type, {asn1, long, LongTag}}|Config]),
ok.
echo_packet(SockOpts, EchoFun, Opts) ->
Type = case lists:keysearch(type, 1, Opts) of
- {value, {type, T}} ->
- T;
- _ ->
- {value, {packet, T}} = lists:keysearch(packet, 1, SockOpts),
- T
- end,
+ {value, {type, T}} ->
+ T;
+ _ ->
+ {value, {packet, T}} = lists:keysearch(packet, 1, SockOpts),
+ T
+ end,
%% Connect to the echo server.
- EchoPort = ?config(echo_port, Opts),
+ EchoPort = proplists:get_value(echo_port, Opts),
{ok, Echo} = gen_tcp:connect(localhost, EchoPort, SockOpts),
SlowEcho = lists:member(slow_echo, Opts),
@@ -223,83 +206,78 @@ echo_packet_http(Echo, Type, EchoFun) ->
EchoFun(Echo, Type, P2, http_reply(P2, Type)).
echo_packet0(Echo, Type, EchoFun, SlowEcho, Opts) ->
- ?line PacketSize =
+ PacketSize =
case lists:keysearch(packet_size, 1, Opts) of
{value,{packet_size,Sz}} when Sz < 10 -> Sz;
{value,{packet_size,_}} -> 10;
false -> 0
end,
%% Echo small packets first.
- ?line echo_packet1(Echo, Type, EchoFun, 0),
- ?line echo_packet1(Echo, Type, EchoFun, 1),
- ?line echo_packet1(Echo, Type, EchoFun, 2),
- ?line echo_packet1(Echo, Type, EchoFun, 3),
- ?line echo_packet1(Echo, Type, EchoFun, 4),
- ?line echo_packet1(Echo, Type, EchoFun, 7),
+ echo_packet1(Echo, Type, EchoFun, 0),
+ echo_packet1(Echo, Type, EchoFun, 1),
+ echo_packet1(Echo, Type, EchoFun, 2),
+ echo_packet1(Echo, Type, EchoFun, 3),
+ echo_packet1(Echo, Type, EchoFun, 4),
+ echo_packet1(Echo, Type, EchoFun, 7),
if PacketSize =/= 0 ->
- ?line echo_packet1(Echo, Type, EchoFun,
- {PacketSize-1, PacketSize}),
- ?line echo_packet1(Echo, Type, EchoFun,
- {PacketSize, PacketSize}),
- ?line echo_packet1(Echo, Type, EchoFun,
- {PacketSize+1, PacketSize});
+ echo_packet1(Echo, Type, EchoFun,
+ {PacketSize-1, PacketSize}),
+ echo_packet1(Echo, Type, EchoFun,
+ {PacketSize, PacketSize}),
+ echo_packet1(Echo, Type, EchoFun,
+ {PacketSize+1, PacketSize});
not SlowEcho -> % Go on with bigger packets if not slow echo server.
- ?line echo_packet1(Echo, Type, EchoFun, 10),
- ?line echo_packet1(Echo, Type, EchoFun, 13),
- ?line echo_packet1(Echo, Type, EchoFun, 126),
- ?line echo_packet1(Echo, Type, EchoFun, 127),
- ?line echo_packet1(Echo, Type, EchoFun, 128),
- ?line echo_packet1(Echo, Type, EchoFun, 255),
- ?line echo_packet1(Echo, Type, EchoFun, 256),
- ?line echo_packet1(Echo, Type, EchoFun, 1023),
- ?line echo_packet1(Echo, Type, EchoFun, 3747),
- ?line echo_packet1(Echo, Type, EchoFun, 32767),
- ?line echo_packet1(Echo, Type, EchoFun, 32768),
- ?line echo_packet1(Echo, Type, EchoFun, 65531),
- ?line echo_packet1(Echo, Type, EchoFun, 65535),
- ?line echo_packet1(Echo, Type, EchoFun, 65536),
- ?line echo_packet1(Echo, Type, EchoFun, 70000),
- ?line echo_packet1(Echo, Type, EchoFun, infinite);
+ echo_packet1(Echo, Type, EchoFun, 10),
+ echo_packet1(Echo, Type, EchoFun, 13),
+ echo_packet1(Echo, Type, EchoFun, 126),
+ echo_packet1(Echo, Type, EchoFun, 127),
+ echo_packet1(Echo, Type, EchoFun, 128),
+ echo_packet1(Echo, Type, EchoFun, 255),
+ echo_packet1(Echo, Type, EchoFun, 256),
+ echo_packet1(Echo, Type, EchoFun, 1023),
+ echo_packet1(Echo, Type, EchoFun, 3747),
+ echo_packet1(Echo, Type, EchoFun, 32767),
+ echo_packet1(Echo, Type, EchoFun, 32768),
+ echo_packet1(Echo, Type, EchoFun, 65531),
+ echo_packet1(Echo, Type, EchoFun, 65535),
+ echo_packet1(Echo, Type, EchoFun, 65536),
+ echo_packet1(Echo, Type, EchoFun, 70000),
+ echo_packet1(Echo, Type, EchoFun, infinite);
true -> ok
end,
- ?line gen_tcp:close(Echo),
+ gen_tcp:close(Echo),
ok.
echo_packet1(EchoSock, Type, EchoFun, Size) ->
- ?line case packet(Size, Type) of
- false ->
- ok;
- Packet ->
- ?line io:format("Type ~p, size ~p, time ~p",
- [Type, Size, time()]),
- ?line
- case EchoFun(EchoSock, Type, Packet, [Packet]) of
- ok ->
- ?line
- case Size of
- {N, Max} when N > Max ->
- ?line
- test_server:fail(
- {packet_through, {N, Max}});
- _ -> ok
- end;
- {error, emsgsize} ->
- ?line
- case Size of
- {N, Max} when N > Max ->
- io:format(" Blocked!");
- _ ->
- ?line
- test_server:fail(
- {packet_blocked, Size})
- end;
- Error ->
- ?line test_server:fail(Error)
- end
- end.
+ case packet(Size, Type) of
+ false ->
+ ok;
+ Packet ->
+ io:format("Type ~p, size ~p, time ~p",
+ [Type, Size, time()]),
+ case EchoFun(EchoSock, Type, Packet, [Packet]) of
+ ok ->
+ case Size of
+ {N, Max} when N > Max ->
+ ct:fail(
+ {packet_through, {N, Max}});
+ _ -> ok
+ end;
+ {error, emsgsize} ->
+ case Size of
+ {N, Max} when N > Max ->
+ io:format(" Blocked!");
+ _ ->
+ ct:fail(
+ {packet_blocked, Size})
+ end;
+ Error ->
+ ct:fail(Error)
+ end
+ end.
active_echo(Sock, Type, Packet, PacketEchos) ->
- ?line ok = gen_tcp:send(Sock, Packet),
+ ok = gen_tcp:send(Sock, Packet),
active_recv(Sock, Type, PacketEchos).
active_recv(_, _, []) ->
@@ -310,21 +288,21 @@ active_recv(Sock, Type, [PacketEcho|Tail]) ->
http_bin -> http;
_ -> tcp
end,
- ?line receive Recv->Recv end,
+ receive Recv->Recv end,
%%io:format("Active received: ~p\n",[Recv]),
- ?line case Recv of
- {Tag, Sock, PacketEcho} ->
- active_recv(Sock, Type, Tail);
- {Tag, Sock, Bad} ->
- ?line test_server:fail({wrong_data, Bad, expected, PacketEcho});
- {tcp_error, Sock, Reason} ->
- {error, Reason};
- Other ->
- ?line test_server:fail({unexpected_message, Other, Tag})
- end.
+ case Recv of
+ {Tag, Sock, PacketEcho} ->
+ active_recv(Sock, Type, Tail);
+ {Tag, Sock, Bad} ->
+ ct:fail({wrong_data, Bad, expected, PacketEcho});
+ {tcp_error, Sock, Reason} ->
+ {error, Reason};
+ Other ->
+ ct:fail({unexpected_message, Other, Tag})
+ end.
passive_echo(Sock, _Type, Packet, PacketEchos) ->
- ?line ok = gen_tcp:send(Sock, Packet),
+ ok = gen_tcp:send(Sock, Packet),
passive_recv(Sock, PacketEchos).
passive_recv(_, []) ->
@@ -332,22 +310,22 @@ passive_recv(_, []) ->
passive_recv(Sock, [PacketEcho | Tail]) ->
Recv = gen_tcp:recv(Sock, 0),
%%io:format("Passive received: ~p\n",[Recv]),
- ?line case Recv of
- {ok, PacketEcho} ->
- passive_recv(Sock, Tail);
- {ok, Bad} ->
- io:format("Expected: ~p\nGot: ~p\n",[PacketEcho,Bad]),
- ?line test_server:fail({wrong_data, Bad});
- {error,PacketEcho} ->
- passive_recv(Sock, Tail); % expected error
- {error, _}=Error ->
- Error;
- Other ->
- ?line test_server:fail({unexpected_message, Other})
- end.
+ case Recv of
+ {ok, PacketEcho} ->
+ passive_recv(Sock, Tail);
+ {ok, Bad} ->
+ io:format("Expected: ~p\nGot: ~p\n",[PacketEcho,Bad]),
+ ct:fail({wrong_data, Bad});
+ {error,PacketEcho} ->
+ passive_recv(Sock, Tail); % expected error
+ {error, _}=Error ->
+ Error;
+ Other ->
+ ct:fail({unexpected_message, Other})
+ end.
active_once_echo(Sock, Type, Packet, PacketEchos) ->
- ?line ok = gen_tcp:send(Sock, Packet),
+ ok = gen_tcp:send(Sock, Packet),
active_once_recv(Sock, Type, PacketEchos).
active_once_recv(_, _, []) ->
@@ -358,17 +336,17 @@ active_once_recv(Sock, Type, [PacketEcho | Tail]) ->
http_bin -> http;
_ -> tcp
end,
- ?line receive
- {Tag, Sock, PacketEcho} ->
- inet:setopts(Sock, [{active, once}]),
- active_once_recv(Sock, Type, Tail);
- {Tag, Sock, Bad} ->
- ?line test_server:fail({wrong_data, Bad});
- {tcp_error, Sock, Reason} ->
- {error, Reason};
- Other ->
- ?line test_server:fail({unexpected_message, Other, expected, {Tag, Sock, PacketEcho}})
- end.
+ receive
+ {Tag, Sock, PacketEcho} ->
+ inet:setopts(Sock, [{active, once}]),
+ active_once_recv(Sock, Type, Tail);
+ {Tag, Sock, Bad} ->
+ ct:fail({wrong_data, Bad});
+ {tcp_error, Sock, Reason} ->
+ {error, Reason};
+ Other ->
+ ct:fail({unexpected_message, Other, expected, {Tag, Sock, PacketEcho}})
+ end.
%%% Building of random packets.
@@ -442,14 +420,7 @@ random_char(Chars) ->
lists:nth(uniform(length(Chars)), Chars).
uniform(N) ->
- case get(random_seed) of
- undefined ->
- {X, Y, Z} = time(),
- random:seed(X, Y, Z);
- _ ->
- ok
- end,
- random:uniform(N).
+ rand:uniform(N).
put_int32(X, big, List) ->
[ (X bsr 24) band 16#ff,
@@ -458,9 +429,9 @@ put_int32(X, big, List) ->
(X) band 16#ff | List ];
put_int32(X, little, List) ->
[ (X) band 16#ff,
- (X bsr 8) band 16#ff,
- (X bsr 16) band 16#ff,
- (X bsr 24) band 16#ff | List].
+ (X bsr 8) band 16#ff,
+ (X bsr 16) band 16#ff,
+ (X bsr 24) band 16#ff | List].
put_int16(X, ByteOrder) ->
put_int16(X, ByteOrder, []).
@@ -470,16 +441,16 @@ put_int16(X, big, List) ->
(X) band 16#ff | List ];
put_int16(X, little, List) ->
[ (X) band 16#ff,
- (X bsr 8) band 16#ff | List ].
+ (X bsr 8) band 16#ff | List ].
%%% A normal echo server, for systems that don't have one.
echo_server() ->
Self = self(),
- ?line spawn_link(fun() -> echo_server(Self) end),
- ?line receive
- {echo_port, Port} ->
- {ok, Port}
+ spawn_link(fun() -> echo_server(Self) end),
+ receive
+ {echo_port, Port} ->
+ {ok, Port}
end.
echo_server(ReplyTo) ->
@@ -512,11 +483,11 @@ echoer_loop(Sock) ->
slow_echo_server() ->
Self = self(),
- ?line spawn_link(fun() -> slow_echo_server(Self) end),
- ?line receive
- {echo_port, Port} ->
- {ok, Port}
- end.
+ spawn_link(fun() -> slow_echo_server(Self) end),
+ receive
+ {echo_port, Port} ->
+ {ok, Port}
+ end.
slow_echo_server(ReplyTo) ->
{ok, S} = gen_tcp:listen(0, [{active, false}, {nodelay, true}]),
@@ -552,17 +523,17 @@ slow_send(_, []) ->
http_request(Uri) ->
list_to_binary(["POST ", Uri, <<" HTTP/1.1\r\n"
- "Connection: close\r\n"
- "Host: localhost:8000\r\n"
- "User-Agent: perl post\r\n"
- "Content-Length: 4\r\n"
- "Content-Type: text/xml; charset=utf-8\r\n"
- "Other-Field: with some text\r\n"
- "Multi-Line: Once upon a time in a land far far away,\r\n"
- " there lived a princess imprisoned in the highest tower\r\n"
- " of the most haunted castle.\r\n"
- "Invalid line without a colon\r\n"
- "\r\n">>]).
+ "Connection: close\r\n"
+ "Host: localhost:8000\r\n"
+ "User-Agent: perl post\r\n"
+ "Content-Length: 4\r\n"
+ "Content-Type: text/xml; charset=utf-8\r\n"
+ "Other-Field: with some text\r\n"
+ "Multi-Line: Once upon a time in a land far far away,\r\n"
+ " there lived a princess imprisoned in the highest tower\r\n"
+ " of the most haunted castle.\r\n"
+ "Invalid line without a colon\r\n"
+ "\r\n">>]).
http_uri_variants() ->
["*",
@@ -575,11 +546,11 @@ http_uri_variants() ->
http_response() ->
<<"HTTP/1.0 404 Object Not Found\r\n"
- "Server: inets/4.7.16\r\n"
- "Date: Fri, 04 Jul 2008 17:16:22 GMT\r\n"
- "Content-Type: text/html\r\n"
- "Content-Length: 207\r\n"
- "\r\n">>.
+ "Server: inets/4.7.16\r\n"
+ "Date: Fri, 04 Jul 2008 17:16:22 GMT\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 207\r\n"
+ "\r\n">>.
http_reply(Bin, Type) ->
{ok, Line, Rest} = erlang:decode_packet(Type,Bin,[]),
@@ -596,7 +567,3 @@ http_reply(<<>>, Acc, _) ->
http_reply(Bin, Acc, HType) ->
{ok, Line, Rest} = erlang:decode_packet(HType,Bin,[]),
http_reply(Rest, [Line | Acc], HType).
-
-
-
-
diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl
index 81c6dcd0fd..7c3b011eb9 100644
--- a/lib/kernel/test/gen_tcp_misc_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl
@@ -19,15 +19,15 @@
%%
-module(gen_tcp_misc_SUITE).
--include_lib("test_server/include/test_server.hrl").
-
-%-compile(export_all).
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
controlling_process/1, controlling_process_self/1,
no_accept/1, close_with_pending_output/1, active_n/1,
- data_before_close/1, iter_max_socks/1, get_status/1,
+ data_before_close/1,
+ iter_max_socks/0, iter_max_socks/1,
+ get_status/1,
passive_sockets/1, accept_closed_by_other_process/1,
init_per_testcase/2, end_per_testcase/2,
otp_3924/1, otp_3924_sender/4, closed_socket/1,
@@ -41,7 +41,7 @@
busy_send/1, busy_disconnect_passive/1, busy_disconnect_active/1,
fill_sendq/1, partial_recv_and_close/1,
partial_recv_and_close_2/1,partial_recv_and_close_3/1,so_priority/1,
- % Accept tests
+ %% Accept tests
primitive_accept/1,multi_accept_close_listen/1,accept_timeout/1,
accept_timeouts_in_order/1,accept_timeouts_in_order2/1,
accept_timeouts_in_order3/1,accept_timeouts_in_order4/1,
@@ -50,7 +50,8 @@
killing_acceptor/1,killing_multi_acceptors/1,killing_multi_acceptors2/1,
several_accepts_in_one_go/1, accept_system_limit/1,
active_once_closed/1, send_timeout/1, send_timeout_active/1,
- otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1, wrapping_oct/1,
+ otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1,
+ wrapping_oct/0, wrapping_oct/1,
otp_9389/1]).
%% Internal exports.
@@ -58,41 +59,15 @@
oct_acceptor/1,
otp_7731_server/1, zombie_server/2, do_iter_max_socks/2]).
-init_per_testcase(wrapping_oct, Config) when is_list(Config) ->
- Dog = case os:type() of
- {ose,_} ->
- test_server:timetrap(test_server:minutes(20));
- _Else ->
- test_server:timetrap(test_server:seconds(600))
- end,
- [{watchdog, Dog}|Config];
-init_per_testcase(iter_max_socks, Config) when is_list(Config) ->
- Dog = case os:type() of
- {win32,_} ->
- test_server:timetrap(test_server:minutes(30));
- _Else ->
- test_server:timetrap(test_server:seconds(240))
- end,
- [{watchdog, Dog}|Config];
-init_per_testcase(accept_system_limit, Config) when is_list(Config) ->
- case os:type() of
- {ose,_} ->
- {skip,"Skip in OSE"};
- _ ->
- Dog = test_server:timetrap(test_server:seconds(240)),
- [{watchdog,Dog}|Config]
- end;
-init_per_testcase(wrapping_oct, Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(600)),
- [{watchdog, Dog}|Config];
-init_per_testcase(_Func, Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(240)),
- [{watchdog, Dog}|Config].
-end_per_testcase(_Func, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+init_per_testcase(_Func, Config) ->
+ Config.
+
+end_per_testcase(_Func, _Config) ->
+ ok.
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,4}}].
all() ->
[controlling_process, controlling_process_self, no_accept,
@@ -136,11 +111,13 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-default_options(doc) ->
- ["Tests kernel application variables inet_default_listen_options and "
- "inet_default_connect_options"];
-default_options(suite) ->
- [];
+-define(UNIQ_NODE_NAME,
+ list_to_atom(?MODULE_STRING ++ "__" ++
+ atom_to_list(?FUNCTION_NAME) ++ "_" ++
+ integer_to_list(erlang:unique_integer([positive])))).
+
+%% Tests kernel application variables inet_default_listen_options and
+%% inet_default_connect_options.
default_options(Config) when is_list(Config) ->
%% First check the delay_send option
{true,true,true}=do_delay_send_1(),
@@ -215,7 +192,7 @@ default_options(Config) when is_list(Config) ->
do_delay_on_other_node(XArgs, Function) ->
Dir = filename:dirname(code:which(?MODULE)),
- {ok,Node} = test_server:start_node(test_default_options_slave,slave,
+ {ok,Node} = test_server:start_node(?UNIQ_NODE_NAME, slave,
[{args,"-pa " ++ Dir ++ " " ++ XArgs}]),
Res = rpc:call(Node,erlang,apply,[Function,[]]),
test_server:stop_node(Node),
@@ -312,11 +289,9 @@ do_delay_send_7() ->
gen_tcp:close(LS),
{B1,B2,B3}.
-controlling_process(doc) ->
- ["Open a listen port and change controlling_process for it",
- "The result should be ok of done by the owner process,"
- "Otherwise is should return {error,not_owner} or similar"];
-controlling_process(suite) -> [];
+%% Open a listen port and change controlling_process for it
+%% The result should be ok of done by the owner process,
+%% Otherwise is should return {error,not_owner} or similar.
controlling_process(Config) when is_list(Config) ->
{ok,S} = gen_tcp:listen(0,[]),
Pid2 = spawn(?MODULE,not_owner,[S]),
@@ -345,9 +320,8 @@ not_owner(S) ->
ok
end.
-controlling_process_self(doc) ->
- ["Open a listen port and assign the controlling process to "
- "it self, then exit and make sure the port is closed properly."];
+%% Open a listen port and assign the controlling process to
+%% it self, then exit and make sure the port is closed properly.
controlling_process_self(Config) when is_list(Config) ->
S = self(),
process_flag(trap_exit,true),
@@ -371,11 +345,9 @@ controlling_process_self(Config) when is_list(Config) ->
end.
-no_accept(doc) ->
- ["Open a listen port and connect to it, then close the listen port ",
- "without doing any accept. The connected socket should receive ",
- "a tcp_closed message."];
-no_accept(suite) -> [];
+%% Open a listen port and connect to it, then close the listen port
+%% without doing any accept. The connected socket should receive
+%% a tcp_closed message.
no_accept(Config) when is_list(Config) ->
{ok, L} = gen_tcp:listen(0, []),
{ok, {_, Port}} = inet:sockname(L),
@@ -385,14 +357,12 @@ no_accept(Config) when is_list(Config) ->
{tcp_closed, Client} ->
ok
after 5000 ->
- test_server:fail(never_closed)
+ ct:fail(never_closed)
end.
-close_with_pending_output(doc) ->
- ["Send several packets to a socket and close it. All packets should arrive ",
- "to the other end."];
-close_with_pending_output(suite) -> [];
+%% Send several packets to a socket and close it. All packets should
+%% arrive to the other end.
close_with_pending_output(Config) when is_list(Config) ->
{ok, L} = gen_tcp:listen(0, [binary, {active, false}]),
{ok, {_, Port}} = inet:sockname(L),
@@ -408,16 +378,16 @@ close_with_pending_output(Config) when is_list(Config) ->
gen_tcp:close(A),
gen_tcp:close(L);
{ok, Bin} ->
- test_server:fail({small_packet,
+ ct:fail({small_packet,
byte_size(Bin)});
Error ->
- test_server:fail({unexpected, Error})
+ ct:fail({unexpected, Error})
end,
ok;
{error, no_remote_hosts} ->
{skipped,"No remote hosts"};
{error, Other} ->
- ?t:fail({failed_to_start_slave_node, Other})
+ ct:fail({failed_to_start_slave_node, Other})
end.
sender(Port, Packets, Host) ->
@@ -435,9 +405,7 @@ send_loop(Sock, Data, Left) ->
send_loop(Sock, Data, Left-1).
%% Test {active,N} option
-active_n(doc) ->
- ["Verify operation of the {active,N} option."];
-active_n(suite) -> [];
+%% Verify operation of the {active,N} option.
active_n(Config) when is_list(Config) ->
N = 3,
LS = ok(gen_tcp:listen(0, [{active,N}])),
@@ -547,9 +515,7 @@ active_n(Config) when is_list(Config) ->
%% I expect propagation of a close to be quite fast
%% so 100 ms seems reasonable.
-otp_3924(doc) ->
- ["Tests that a socket can be closed fast enough."];
-otp_3924(suite) -> [];
+%% Tests that a socket can be closed fast enough.
otp_3924(Config) when is_list(Config) ->
MaxDelay = (case has_superfluous_schedulers() of
true -> 4;
@@ -567,8 +533,8 @@ otp_3924_1(MaxDelay) ->
{ok, Node} = start_node(otp_3924),
DataLen = 100*1024,
Data = otp_3924_data(DataLen),
- % Repeat the test a couple of times to prevent the test from passing
- % by chance.
+ %% Repeat the test a couple of times to prevent the test from passing
+ %% by chance.
repeat(10, fun(N) ->
ok = otp_3924(MaxDelay, Node, Data, DataLen, N)
end),
@@ -607,17 +573,17 @@ otp_3924_receive_data(LSock, Sender, MaxDelay, Len, N) ->
process_flag(priority, OP),
receive
{'EXIT', _, TimeoutRef} ->
- test_server:fail({close_not_fast_enough,MaxDelay,N});
+ ct:fail({close_not_fast_enough,MaxDelay,N});
{'EXIT', Sender, Reason} ->
- test_server:fail({sender_exited, Reason});
+ ct:fail({sender_exited, Reason});
{'EXIT', _Other, Reason} ->
- test_server:fail({linked_process_exited, Reason})
+ ct:fail({linked_process_exited, Reason})
after 0 ->
case Data of
{'EXIT', {A,B}} ->
- test_server:fail({A,B,N});
+ ct:fail({A,B,N});
{'EXIT', Failure} ->
- test_server:fail(Failure);
+ ct:fail(Failure);
_ ->
Data
end
@@ -676,8 +642,7 @@ otp_3924_sender(Receiver, Host, Port, Data) ->
end.
-data_before_close(doc) ->
- ["Tests that a huge amount of data can be received before a close."];
+%% Tests that a huge amount of data can be received before a close.
data_before_close(Config) when is_list(Config) ->
{ok, L} = gen_tcp:listen(0, [binary]),
{ok, {_, TcpPort}} = inet:sockname(L),
@@ -689,7 +654,7 @@ data_before_close(Config) when is_list(Config) ->
io:format("Result: ~p", [Result]);
{Wrong, Result} ->
io:format("Result: ~p", [Result]),
- test_server:fail({wrong_count, Wrong})
+ ct:fail({wrong_count, Wrong})
end,
ok.
@@ -714,11 +679,9 @@ make_zero_packet(N) when N rem 2 == 0 ->
make_zero_packet(N) ->
P = make_zero_packet(N div 2),
[0, P|P].
-get_status(doc) ->
- ["OTP-2924",
- "test that the socket process does not crash when sys:get_status(Pid)",
- "is called."];
-get_status(suite) -> [];
+
+%% OTP-2924. Test that the socket process does not crash when
+%% sys:get_status(Pid) is called.
get_status(Config) when is_list(Config) ->
{ok,{socket,Pid,_,_}} = gen_tcp:listen(5678,[]),
{status,Pid,_,_} = sys:get_status(Pid).
@@ -726,9 +689,11 @@ get_status(Config) when is_list(Config) ->
-define(RECOVER_SLEEP, 60000).
-define(RETRY_SLEEP, 15000).
-iter_max_socks(doc) ->
- ["Open as many sockets as possible. Do this several times and check ",
- "that we get the same number of sockets every time."];
+iter_max_socks() ->
+ [{timetrap,{minutes,30}}].
+
+%% Open as many sockets as possible. Do this several times and check
+%% that we get the same number of sockets every time.
iter_max_socks(Config) when is_list(Config) ->
N = case os:type() of {win32,_} -> 10; _ -> 20 end,
%% Run on a different node in order to limit the effect if this test fails.
@@ -757,7 +722,7 @@ do_iter_max_socks(N, First) when is_integer(First) ->
true ->
io:format("Sleeping for ~p seconds...~n",
[?RETRY_SLEEP/1000]),
- ?t:sleep(?RETRY_SLEEP),
+ ct:sleep(?RETRY_SLEEP),
io:format("Trying again...~n", []),
RetryMS = max_socks(),
if RetryMS == First ->
@@ -775,10 +740,10 @@ all_equal([Rule | T]) ->
all_equal(Rule, [Rule | T]) ->
all_equal(Rule, T);
all_equal(_, [_ | _]) ->
- ?t:sleep(?RECOVER_SLEEP), % Wait a while and *hope* that we'll
- % recover so other tests won't be
- % affected.
- ?t:fail(max_socket_mismatch);
+ ct:sleep(?RECOVER_SLEEP), % Wait a while and *hope* that we'll
+ %% recover so other tests won't be
+ %% affected.
+ ct:fail(max_socket_mismatch);
all_equal(_Rule, []) ->
ok.
@@ -820,21 +785,20 @@ start_remote(Name) ->
Pa = filename:dirname(code:which(?MODULE)),
test_server:start_node(Name, slave, [{remote, true}, {args, "-pa " ++ Pa}]).
-passive_sockets(doc) ->
- ["Tests that when 'the other side' on a passive socket closes, the connecting",
- "side still can read until the end of data."];
+%% Tests that when 'the other side' on a passive socket closes, the
+%% connecting, side still can read until the end of data.
passive_sockets(Config) when is_list(Config) ->
spawn_link(?MODULE, passive_sockets_server,
[[{active,false}],self()]),
receive
{socket,Port} -> ok
end,
- ?t:sleep(500),
+ ct:sleep(500),
case gen_tcp:connect("localhost", Port, [{active, false}]) of
{ok, Sock} ->
passive_sockets_read(Sock);
Error ->
- ?t:fail({"Could not connect to server", Error})
+ ct:fail({"Could not connect to server", Error})
end.
%%
@@ -850,7 +814,7 @@ passive_sockets_read(Sock) ->
gen_tcp:close(Sock);
Error ->
gen_tcp:close(Sock),
- ?t:fail({"Did not get {error, closed} before other error", Error})
+ ct:fail({"Did not get {error, closed} before other error", Error})
end.
passive_sockets_server(Opts, Parent) ->
@@ -860,17 +824,17 @@ passive_sockets_server(Opts, Parent) ->
Parent ! {socket,Port},
passive_sockets_server_accept(LSock);
Error ->
- ?t:fail({"Could not create listen socket", Error})
+ ct:fail({"Could not create listen socket", Error})
end.
passive_sockets_server_accept(Sock) ->
case gen_tcp:accept(Sock) of
{ok, Socket} ->
- ?t:sleep(500), % Simulate latency
+ timer:sleep(500), % Simulate latency
passive_sockets_server_send(Socket, 5),
passive_sockets_server_accept(Sock);
Error ->
- ?t:fail({"Could not accept connection", Error})
+ ct:fail({"Could not accept connection", Error})
end.
passive_sockets_server_send(Socket, 0) ->
@@ -880,16 +844,15 @@ passive_sockets_server_send(Socket, X) ->
Data = lists:duplicate(1024*X, $a),
case gen_tcp:send(Socket, Data) of
ok ->
- ?t:sleep(50), % Simulate some processing.
+ ct:sleep(50), % Simulate some processing.
passive_sockets_server_send(Socket, X-1);
{error, _Reason} ->
- ?t:fail("Failed to send data")
+ ct:fail("Failed to send data")
end.
-accept_closed_by_other_process(doc) ->
- ["Tests the return value from gen_tcp:accept when ",
- "the socket is closed from another process. (OTP-3817)"];
+%% Tests the return value from gen_tcp:accept when
+%% the socket is closed from another process. (OTP-3817)
accept_closed_by_other_process(Config) when is_list(Config) ->
Parent = self(),
{ok, ListenSocket} = gen_tcp:listen(0, []),
@@ -904,7 +867,7 @@ accept_closed_by_other_process(Config) when is_list(Config) ->
{Child, {error, closed}} ->
ok;
{Child, Other} ->
- ?t:fail({"Wrong result of gen_tcp:accept", Other})
+ ct:fail({"Wrong result of gen_tcp:accept", Other})
end.
repeat(N, Fun) ->
@@ -917,10 +880,7 @@ repeat(_, _, _) ->
ok.
-closed_socket(suite) ->
- [];
-closed_socket(doc) ->
- ["Tests the response when using a closed socket as argument"];
+%% Tests the response when using a closed socket as argument.
closed_socket(Config) when is_list(Config) ->
{ok, LS1} = gen_tcp:listen(0, []),
erlang:yield(),
@@ -932,7 +892,7 @@ closed_socket(Config) when is_list(Config) ->
%% in inet_db processes the 'EXIT' message from the port,
%% the socket is unregistered.
%%
- %% test_server:sleep(test_server:seconds(2)),
+ %% ct:sleep({seconds,2})
%%
{error, R_send} = gen_tcp:send(LS1, "data"),
{error, R_recv} = gen_tcp:recv(LS1, 17),
@@ -974,7 +934,7 @@ shutdown_common(Active) ->
do_sort(P, []),
receive
Any ->
- ?t:fail({unexpected_message,Any})
+ ct:fail({unexpected_message,Any})
after 0 -> ok
end.
@@ -1055,7 +1015,7 @@ shutdown_pending(Config) when is_list(Config) ->
io:format("~p\n", [Msg]),
N = list_to_integer(Msg) - 5;
Other ->
- ?t:fail({unexpected,Other})
+ ct:fail({unexpected,Other})
end,
ok.
@@ -1107,9 +1067,9 @@ show_econnreset_active(Config) when is_list(Config) ->
{tcp_closed, S} ->
ok;
Other ->
- ?t:fail({unexpected1, Other})
+ ct:fail({unexpected1, Other})
after 1000 ->
- ?t:fail({timeout, {server, no_tcp_closed}})
+ ct:fail({timeout, {server, no_tcp_closed}})
end,
%% Now test with option switched on.
@@ -1128,14 +1088,14 @@ show_econnreset_active(Config) when is_list(Config) ->
{tcp_closed, S1} ->
ok;
Other1 ->
- ?t:fail({unexpected2, Other1})
+ ct:fail({unexpected2, Other1})
after 1 ->
- ?t:fail({timeout, {server, no_tcp_closed}})
+ ct:fail({timeout, {server, no_tcp_closed}})
end;
Other2 ->
- ?t:fail({unexpected3, Other2})
+ ct:fail({unexpected3, Other2})
after 1000 ->
- ?t:fail({timeout, {server, no_tcp_error}})
+ ct:fail({timeout, {server, no_tcp_error}})
end.
show_econnreset_active_once(Config) when is_list(Config) ->
@@ -1149,7 +1109,7 @@ show_econnreset_active_once(Config) when is_list(Config) ->
ok = gen_tcp:close(L),
ok = inet:setopts(Client, [{linger, {true, 0}}]),
ok = gen_tcp:close(Client),
- ok = ?t:sleep(20),
+ ok = ct:sleep(20),
ok = receive Msg -> {unexpected_msg, Msg} after 0 -> ok end,
ok = inet:setopts(S, [{active, once}]),
receive
@@ -1158,14 +1118,14 @@ show_econnreset_active_once(Config) when is_list(Config) ->
{tcp_closed, S} ->
ok;
Other1 ->
- ?t:fail({unexpected1, Other1})
+ ct:fail({unexpected1, Other1})
after 1 ->
- ?t:fail({timeout, {server, no_tcp_closed}})
+ ct:fail({timeout, {server, no_tcp_closed}})
end;
Other2 ->
- ?t:fail({unexpected2, Other2})
+ ct:fail({unexpected2, Other2})
after 1000 ->
- ?t:fail({timeout, {server, no_tcp_error}})
+ ct:fail({timeout, {server, no_tcp_error}})
end.
show_econnreset_passive(Config) when is_list(Config) ->
@@ -1177,7 +1137,7 @@ show_econnreset_passive(Config) when is_list(Config) ->
ok = gen_tcp:close(L),
ok = inet:setopts(S, [{linger, {true, 0}}]),
ok = gen_tcp:close(S),
- ok = ?t:sleep(1),
+ ok = ct:sleep(1),
{error, closed} = gen_tcp:recv(Client, 0),
%% Now test with option switched on.
@@ -1190,7 +1150,7 @@ show_econnreset_passive(Config) when is_list(Config) ->
ok = gen_tcp:close(L1),
ok = inet:setopts(S1, [{linger, {true, 0}}]),
ok = gen_tcp:close(S1),
- ok = ?t:sleep(1),
+ ok = ct:sleep(1),
{error, econnreset} = gen_tcp:recv(Client1, 0).
econnreset_after_sync_send(Config) when is_list(Config) ->
@@ -1202,7 +1162,7 @@ econnreset_after_sync_send(Config) when is_list(Config) ->
ok = gen_tcp:close(L),
ok = inet:setopts(S, [{linger, {true, 0}}]),
ok = gen_tcp:close(S),
- ok = ?t:sleep(20),
+ ok = ct:sleep(20),
{error, closed} = gen_tcp:send(Client, "Whatever"),
%% Now test with option switched on.
@@ -1215,7 +1175,7 @@ econnreset_after_sync_send(Config) when is_list(Config) ->
ok = gen_tcp:close(L1),
ok = inet:setopts(S1, [{linger, {true, 0}}]),
ok = gen_tcp:close(S1),
- ok = ?t:sleep(20),
+ ok = ct:sleep(20),
{error, econnreset} = gen_tcp:send(Client1, "Whatever").
econnreset_after_async_send_active(Config) when is_list(Config) ->
@@ -1232,23 +1192,23 @@ econnreset_after_async_send_active(Config) when is_list(Config) ->
case erlang:port_info(Client, queue_size) of
{queue_size, N} when N > 0 -> ok;
{queue_size, 0} when OS =:= win32 -> ok;
- {queue_size, 0} = T -> ?t:fail(T)
+ {queue_size, 0} = T -> ct:fail(T)
end,
ok = gen_tcp:send(S, "Whatever"),
- ok = ?t:sleep(20),
+ ok = ct:sleep(20),
ok = inet:setopts(S, [{linger, {true, 0}}]),
ok = gen_tcp:close(S),
- ok = ?t:sleep(20),
+ ok = ct:sleep(20),
receive
{tcp, Client, "Whatever"} ->
receive
{tcp_closed, Client} ->
ok;
Other1 ->
- ?t:fail({unexpected1, Other1})
+ ct:fail({unexpected1, Other1})
end;
Other2 ->
- ?t:fail({unexpected2, Other2})
+ ct:fail({unexpected2, Other2})
end,
%% Now test with option switched on.
@@ -1263,13 +1223,13 @@ econnreset_after_async_send_active(Config) when is_list(Config) ->
case erlang:port_info(Client1, queue_size) of
{queue_size, N1} when N1 > 0 -> ok;
{queue_size, 0} when OS =:= win32 -> ok;
- {queue_size, 0} = T1 -> ?t:fail(T1)
+ {queue_size, 0} = T1 -> ct:fail(T1)
end,
ok = gen_tcp:send(S1, "Whatever"),
- ok = ?t:sleep(20),
+ ok = ct:sleep(20),
ok = inet:setopts(S1, [{linger, {true, 0}}]),
ok = gen_tcp:close(S1),
- ok = ?t:sleep(20),
+ ok = ct:sleep(20),
receive
{tcp, Client1, "Whatever"} ->
receive
@@ -1278,13 +1238,13 @@ econnreset_after_async_send_active(Config) when is_list(Config) ->
{tcp_closed, Client1} ->
ok;
Other3 ->
- ?t:fail({unexpected3, Other3})
+ ct:fail({unexpected3, Other3})
end;
Other4 ->
- ?t:fail({unexpected4, Other4})
+ ct:fail({unexpected4, Other4})
end;
Other5 ->
- ?t:fail({unexpected5, Other5})
+ ct:fail({unexpected5, Other5})
end.
econnreset_after_async_send_active_once(Config) when is_list(Config) ->
@@ -1302,13 +1262,13 @@ econnreset_after_async_send_active_once(Config) when is_list(Config) ->
case erlang:port_info(Client, queue_size) of
{queue_size, N} when N > 0 -> ok;
{queue_size, 0} when OS =:= win32 -> ok;
- {queue_size, 0} = T -> ?t:fail(T)
+ {queue_size, 0} = T -> ct:fail(T)
end,
ok = gen_tcp:send(S, "Whatever"),
- ok = ?t:sleep(20),
+ ok = ct:sleep(20),
ok = inet:setopts(S, [{linger, {true, 0}}]),
ok = gen_tcp:close(S),
- ok = ?t:sleep(20),
+ ok = ct:sleep(20),
ok = receive Msg -> {unexpected_msg, Msg} after 0 -> ok end,
ok = inet:setopts(Client, [{active, once}]),
receive
@@ -1317,10 +1277,10 @@ econnreset_after_async_send_active_once(Config) when is_list(Config) ->
{tcp_closed, Client} ->
ok;
Other ->
- ?t:fail({unexpected1, Other})
+ ct:fail({unexpected1, Other})
end;
Other ->
- ?t:fail({unexpected2, Other})
+ ct:fail({unexpected2, Other})
end.
econnreset_after_async_send_passive(Config) when is_list(Config) ->
@@ -1341,10 +1301,10 @@ econnreset_after_async_send_passive(Config) when is_list(Config) ->
case erlang:port_info(Client, queue_size) of
{queue_size, N} when N > 0 -> ok;
{queue_size, 0} when OS =:= win32 -> ok;
- {queue_size, 0} = T -> ?t:fail(T)
+ {queue_size, 0} = T -> ct:fail(T)
end,
ok = gen_tcp:close(S),
- ok = ?t:sleep(20),
+ ok = ct:sleep(20),
{error, closed} = gen_tcp:recv(Client, 0),
%% Now test with option switched on.
@@ -1360,7 +1320,7 @@ econnreset_after_async_send_passive(Config) when is_list(Config) ->
ok = gen_tcp:send(S1, "Whatever"),
ok = gen_tcp:send(Client1, Payload),
ok = gen_tcp:close(S1),
- ok = ?t:sleep(20),
+ ok = ct:sleep(20),
{error, econnreset} = gen_tcp:recv(Client1, 0).
%%
@@ -1387,11 +1347,11 @@ linger_zero(Config) when is_list(Config) ->
case erlang:port_info(Client, queue_size) of
{queue_size, N} when N > 0 -> ok;
{queue_size, 0} when OS =:= win32 -> ok;
- {queue_size, 0} = T -> ?t:fail(T)
+ {queue_size, 0} = T -> ct:fail(T)
end,
ok = inet:setopts(Client, [{linger, {true, 0}}]),
ok = gen_tcp:close(Client),
- ok = ?t:sleep(1),
+ ok = ct:sleep(1),
undefined = erlang:port_info(Client, connected),
{error, econnreset} = gen_tcp:recv(S, PayloadSize).
@@ -1466,7 +1426,7 @@ busy_send_loop(Server, Client, N) ->
busy_send_2(Server, Client, N+1)
after 10000 ->
%% If this happens, see busy_send_srv
- ?t:fail({timeout,{server,not_send,flush([])}})
+ ct:fail({timeout,{server,not_send,flush([])}})
end
end.
@@ -1477,7 +1437,7 @@ busy_send_2(Server, Client, _N) ->
{Server,[closed]} ->
receive {Client,[0,{error,closed}]} -> ok end
after 10000 ->
- ?t:fail({timeout,{server,not_closed,flush([])}})
+ ct:fail({timeout,{server,not_closed,flush([])}})
end.
busy_send_srv(L, Master, Msg) ->
@@ -1567,7 +1527,7 @@ busy_disconnect_active_send(S, Data) ->
{error,closed} ->
receive
{tcp_closed,S} -> ok;
- _Other -> ?t:fail()
+ _Other -> ct:fail(failed)
end
end.
@@ -1646,7 +1606,7 @@ fill_sendq_loop(Server, Client, Reader) ->
("Got reader closed.~n"),
ok
after 3000 ->
- ?t:fail({timeout,{closed,reader}})
+ ct:fail({timeout,{closed,reader}})
end;
{Reader,[{error,closed}]} ->
io:format("Got reader closed.~n"),
@@ -1654,10 +1614,10 @@ fill_sendq_loop(Server, Client, Reader) ->
io:format("Got server closed~n"),
ok
after 3000 ->
- ?t:fail({timeout,{closed,server}})
+ ct:fail({timeout,{closed,server}})
end
after 3000 ->
- ?t:fail({timeout,{closed,[server,reader]}})
+ ct:fail({timeout,{closed,[server,reader]}})
end
end.
@@ -1865,7 +1825,7 @@ test_prio_accept_async() ->
spawn(?MODULE,priority_server,[{self(),Ref}]),
Port = receive
{Ref,P} -> P
- after 5000 -> ?t:fail({error,"helper process timeout"})
+ after 5000 -> ct:fail({error,"helper process timeout"})
end,
receive
after 3000 -> ok
@@ -1879,15 +1839,15 @@ test_prio_accept_async() ->
{Ref,{ok,[{priority,4},{tos,Tos1}]}} ->
ok;
{Ref,Error} ->
- ?t:fail({missmatch,Error})
- after 5000 -> ?t:fail({error,"helper process timeout"})
+ ct:fail({missmatch,Error})
+ after 5000 -> ct:fail({error,"helper process timeout"})
end,
receive
{Ref,{ok,[{priority,4},{tos,Tos1}]}} ->
ok;
{Ref,Error2} ->
- ?t:fail({missmatch,Error2})
- after 5000 -> ?t:fail({error,"helper process timeout"})
+ ct:fail({missmatch,Error2})
+ after 5000 -> ct:fail({error,"helper process timeout"})
end,
{ok,[{priority,4},{tos,Tos2}]} = inet:getopts(Sock2,[priority,tos]),
@@ -1909,10 +1869,6 @@ priority_server({Parent,Ref}) ->
test_prio_fail() ->
{ok,L} = gen_tcp:listen(0, [{active,false}]),
{error,_} = inet:setopts(L,[{priority,1000}]),
-% This error could only happen in linux kernels earlier than 2.6.24.4
-% Privilege check is now disabled and IP_TOS can never fail (only silently
-% be masked).
-% {error,_} = inet:setopts(L,[{tos,6 bsl 5}]),
gen_tcp:close(L),
ok.
@@ -1924,10 +1880,7 @@ test_prio_udp() ->
gen_udp:close(S),
ok.
-so_priority(doc) ->
- ["Tests the so_priority and ip_tos options on sockets when applicable."];
-so_priority(suite) ->
- [];
+%% Tests the so_priority and ip_tos options on sockets when applicable.
so_priority(Config) when is_list(Config) ->
{ok,L} = gen_tcp:listen(0, [{active,false}]),
ok = inet:setopts(L,[{priority,1}]),
@@ -1947,7 +1900,7 @@ so_priority(Config) when is_list(Config) ->
{unix,linux} ->
case os:version() of
{X,Y,_} when (X > 2) or ((X =:= 2) and (Y >= 4)) ->
- ?t:fail({error,
+ ct:fail({error,
"so_priority should work on this "
"OS, but does not"});
_ ->
@@ -2006,10 +1959,7 @@ mktmofun(Tmo,Parent,LS) ->
fun() -> Parent ! {accepted,self(), catch gen_tcp:accept(LS,Tmo)} end.
%% Accept tests
-primitive_accept(suite) ->
- [];
-primitive_accept(doc) ->
- ["Test singular accept"];
+%% Test singular accept.
primitive_accept(Config) when is_list(Config) ->
{ok,LS}=gen_tcp:listen(0,[]),
{ok,PortNo}=inet:port(LS),
@@ -2027,10 +1977,7 @@ primitive_accept(Config) when is_list(Config) ->
end.
-multi_accept_close_listen(suite) ->
- [];
-multi_accept_close_listen(doc) ->
- ["Closing listen socket when multi-accepting"];
+%% Closing listen socket when multi-accepting.
multi_accept_close_listen(Config) when is_list(Config) ->
{ok,LS}=gen_tcp:listen(0,[]),
Parent = self(),
@@ -2043,10 +1990,7 @@ multi_accept_close_listen(Config) when is_list(Config) ->
ok = ?EXPECT_ACCEPTS([{_,{error,closed}},{_,{error,closed}},
{_,{error,closed}},{_,{error,closed}}],4,500).
-accept_timeout(suite) ->
- [];
-accept_timeout(doc) ->
- ["Single accept with timeout"];
+%% Single accept with timeout.
accept_timeout(Config) when is_list(Config) ->
{ok,LS}=gen_tcp:listen(0,[]),
Parent = self(),
@@ -2054,10 +1998,7 @@ accept_timeout(Config) when is_list(Config) ->
P = spawn(F),
ok = ?EXPECT_ACCEPTS([{P,{error,timeout}}],1,2000).
-accept_timeouts_in_order(suite) ->
- [];
-accept_timeouts_in_order(doc) ->
- ["Check that multi-accept timeouts happen in the correct order"];
+%% Check that multi-accept timeouts happen in the correct order.
accept_timeouts_in_order(Config) when is_list(Config) ->
{ok,LS}=gen_tcp:listen(0,[]),
Parent = self(),
@@ -2068,10 +2009,7 @@ accept_timeouts_in_order(Config) when is_list(Config) ->
ok = ?EXPECT_ACCEPTS([{P1,{error,timeout}},{P2,{error,timeout}},
{P3,{error,timeout}},{P4,{error,timeout}}],infinity,2000).
-accept_timeouts_in_order2(suite) ->
- [];
-accept_timeouts_in_order2(doc) ->
- ["Check that multi-accept timeouts happen in the correct order (more)"];
+%% Check that multi-accept timeouts happen in the correct order (more).
accept_timeouts_in_order2(Config) when is_list(Config) ->
{ok,LS}=gen_tcp:listen(0,[]),
Parent = self(),
@@ -2082,10 +2020,7 @@ accept_timeouts_in_order2(Config) when is_list(Config) ->
ok = ?EXPECT_ACCEPTS([{P4,{error,timeout}},{P3,{error,timeout}},
{P2,{error,timeout}},{P1,{error,timeout}}],infinity,2000).
-accept_timeouts_in_order3(suite) ->
- [];
-accept_timeouts_in_order3(doc) ->
- ["Check that multi-accept timeouts happen in the correct order (even more)"];
+%% Check that multi-accept timeouts happen in the correct order (even more).
accept_timeouts_in_order3(Config) when is_list(Config) ->
{ok,LS}=gen_tcp:listen(0,[]),
Parent = self(),
@@ -2096,11 +2031,8 @@ accept_timeouts_in_order3(Config) when is_list(Config) ->
ok = ?EXPECT_ACCEPTS([{P4,{error,timeout}},{P1,{error,timeout}},
{P3,{error,timeout}},{P2,{error,timeout}}],infinity,2000).
-accept_timeouts_in_order4(suite) ->
- [];
-accept_timeouts_in_order4(doc) ->
- ["Check that multi-accept timeouts happen in the correct order after "
- "mixing millsec and sec timeouts"];
+%% Check that multi-accept timeouts happen in the correct order after
+%% mixing millsec and sec timeouts.
accept_timeouts_in_order4(Config) when is_list(Config) ->
{ok,LS}=gen_tcp:listen(0,[]),
Parent = self(),
@@ -2111,11 +2043,8 @@ accept_timeouts_in_order4(Config) when is_list(Config) ->
ok = ?EXPECT_ACCEPTS([{P1,{error,timeout}},{P2,{error,timeout}},
{P4,{error,timeout}},{P3,{error,timeout}}],infinity,2000).
-accept_timeouts_in_order5(suite) ->
- [];
-accept_timeouts_in_order5(doc) ->
- ["Check that multi-accept timeouts happen in the correct order after "
- "mixing millsec and sec timeouts (more)"];
+%% Check that multi-accept timeouts happen in the correct order after
+%% mixing millsec and sec timeouts (more).
accept_timeouts_in_order5(Config) when is_list(Config) ->
{ok,LS}=gen_tcp:listen(0,[]),
Parent = self(),
@@ -2126,11 +2055,8 @@ accept_timeouts_in_order5(Config) when is_list(Config) ->
ok = ?EXPECT_ACCEPTS([{P4,{error,timeout}},{P1,{error,timeout}},
{P3,{error,timeout}},{P2,{error,timeout}}],infinity,2000).
-accept_timeouts_in_order6(suite) ->
- [];
-accept_timeouts_in_order6(doc) ->
- ["Check that multi-accept timeouts happen in the correct order after "
- "mixing millsec and sec timeouts (even more)"];
+%% Check that multi-accept timeouts happen in the correct order after
+%% mixing millsec and sec timeouts (even more).
accept_timeouts_in_order6(Config) when is_list(Config) ->
{ok,LS}=gen_tcp:listen(0,[]),
Parent = self(),
@@ -2141,11 +2067,8 @@ accept_timeouts_in_order6(Config) when is_list(Config) ->
ok = ?EXPECT_ACCEPTS([{P4,{error,timeout}},{P2,{error,timeout}},
{P3,{error,timeout}},{P1,{error,timeout}}],infinity,2000).
-accept_timeouts_in_order7(suite) ->
- [];
-accept_timeouts_in_order7(doc) ->
- ["Check that multi-accept timeouts happen in the correct order after "
- "mixing millsec and sec timeouts (even more++)"];
+%% Check that multi-accept timeouts happen in the correct order after
+%% mixing millsec and sec timeouts (even more++).
accept_timeouts_in_order7(Config) when is_list(Config) ->
{ok,LS}=gen_tcp:listen(0,[]),
Parent = self(),
@@ -2162,10 +2085,7 @@ accept_timeouts_in_order7(Config) when is_list(Config) ->
{P1,{error,timeout}},{P3,{error,timeout}},
{P8,{error,timeout}},{P7,{error,timeout}}],infinity,2000).
-accept_timeouts_mixed(suite) ->
- [];
-accept_timeouts_mixed(doc) ->
- ["Check that multi-accept timeouts behave correctly when mixed with successful timeouts"];
+%% Check that multi-accept timeouts behave correctly when mixed with successful timeouts.
accept_timeouts_mixed(Config) when is_list(Config) ->
{ok,LS}=gen_tcp:listen(0,[]),
Parent = self(),
@@ -2185,10 +2105,7 @@ accept_timeouts_mixed(Config) when is_list(Config) ->
gen_tcp:connect("localhost",PortNo,[]),
ok = ?EXPECT_ACCEPTS([{P4,{ok,Port1}}] when is_port(Port1),infinity,100).
-killing_acceptor(suite) ->
- [];
-killing_acceptor(doc) ->
- ["Check that single acceptor behaves as expected when killed"];
+%% Check that single acceptor behaves as expected when killed.
killing_acceptor(Config) when is_list(Config) ->
{ok,LS}=gen_tcp:listen(0,[]),
Pid = spawn(fun() -> erlang:display({accepted,self(),gen_tcp:accept(LS)}) end),
@@ -2203,10 +2120,7 @@ killing_acceptor(Config) when is_list(Config) ->
false = lists:member(accepting, L2),
ok.
-killing_multi_acceptors(suite) ->
- [];
-killing_multi_acceptors(doc) ->
- ["Check that multi acceptors behaves as expected when killed"];
+%% Check that multi acceptors behaves as expected when killed.
killing_multi_acceptors(Config) when is_list(Config) ->
{ok,LS}=gen_tcp:listen(0,[]),
Parent = self(),
@@ -2228,10 +2142,7 @@ killing_multi_acceptors(Config) when is_list(Config) ->
false = lists:member(accepting, L3),
ok.
-killing_multi_acceptors2(suite) ->
- [];
-killing_multi_acceptors2(doc) ->
- ["Check that multi acceptors behaves as expected when killed (more)"];
+%% Check that multi acceptors behaves as expected when killed (more).
killing_multi_acceptors2(Config) when is_list(Config) ->
{ok,LS}=gen_tcp:listen(0,[]),
Parent = self(),
@@ -2265,11 +2176,8 @@ killing_multi_acceptors2(Config) when is_list(Config) ->
false = lists:member(accepting, L5),
ok.
-several_accepts_in_one_go(suite) ->
- [];
-several_accepts_in_one_go(doc) ->
- ["checks that multi-accept works when more than one accept can be "
- "done at once (wb test of inet_driver)"];
+%% Checks that multi-accept works when more than one accept can be
+%% done at once (wb test of inet_driver).
several_accepts_in_one_go(Config) when is_list(Config) ->
{ok,LS}=gen_tcp:listen(0,[]),
Parent = self(),
@@ -2312,11 +2220,8 @@ wait_until_accepting(Proc,N) ->
end.
-accept_system_limit(suite) ->
- [];
-accept_system_limit(doc) ->
- ["Check that accept returns {error, system_limit} "
- "(and not {error, enfile}) when running out of ports"];
+%% Check that accept returns {error, system_limit}
+%% (and not {error, enfile}) when running out of ports.
accept_system_limit(Config) when is_list(Config) ->
{ok, LS} = gen_tcp:listen(0, []),
{ok, TcpPort} = inet:port(LS),
@@ -2365,10 +2270,7 @@ open_ports(L) ->
end.
-active_once_closed(suite) ->
- [];
-active_once_closed(doc) ->
- ["Check that active once and tcp_close messages behave as expected"];
+%% Check that active once and tcp_close messages behave as expected.
active_once_closed(Config) when is_list(Config) ->
(fun() ->
{Loop,A} = setup_closed_ao(),
@@ -2416,10 +2318,7 @@ active_once_closed(Config) when is_list(Config) ->
ok = receive {tcp_closed, A} -> ok after 1000 -> error end
end)().
-send_timeout(suite) ->
- [];
-send_timeout(doc) ->
- ["Test the send_timeout socket option"];
+%% Test the send_timeout socket option.
send_timeout(Config) when is_list(Config) ->
%% Basic
BasicFun =
@@ -2500,18 +2399,13 @@ mad_sender(S) ->
flush() ->
receive
_X ->
- %erlang:display(_X),
flush()
after 0 ->
ok
end.
-send_timeout_active(suite) ->
- [];
-send_timeout_active(doc) ->
- ["Test the send_timeout socket option for active sockets"];
+%% Test the send_timeout socket option for active sockets.
send_timeout_active(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(20)),
%% Basic
BasicFun =
fun(AutoClose) ->
@@ -2524,7 +2418,6 @@ send_timeout_active(Config) when is_list(Config) ->
{tcp, _Sock, _Data} ->
inet:setopts(A, [{active, once}]),
Res = gen_tcp:send(A,lists:duplicate(1000, $a)),
- %erlang:display(Res),
Res;
Err ->
io:format("sock closed: ~p~n", [Err]),
@@ -2539,7 +2432,6 @@ send_timeout_active(Config) when is_list(Config) ->
flush(),
BasicFun(true),
flush(),
- test_server:timetrap_cancel(Dog),
ok.
after_send_timeout(AutoClose) ->
@@ -2581,7 +2473,7 @@ get_max_diff(Max) ->
setup_closed_ao() ->
Dir = filename:dirname(code:which(?MODULE)),
- {ok,R} = test_server:start_node(test_default_options_slave,slave,
+ {ok,R} = test_server:start_node(?UNIQ_NODE_NAME, slave,
[{args,"-pa " ++ Dir}]),
Host = list_to_atom(lists:nth(2,string:tokens(atom_to_list(node()),"@"))),
{ok, L} = gen_tcp:listen(0, [{active,false},{packet,2}]),
@@ -2624,7 +2516,7 @@ setup_closed_ao() ->
setup_timeout_sink(Timeout, AutoClose) ->
Dir = filename:dirname(code:which(?MODULE)),
- {ok,R} = test_server:start_node(test_default_options_slave,slave,
+ {ok,R} = test_server:start_node(?UNIQ_NODE_NAME, slave,
[{args,"-pa " ++ Dir}]),
Host = list_to_atom(lists:nth(2,string:tokens(atom_to_list(node()),"@"))),
{ok, L} = gen_tcp:listen(0, [{active,false},{packet,2},
@@ -2667,7 +2559,7 @@ setup_timeout_sink(Timeout, AutoClose) ->
setup_active_timeout_sink(Timeout, AutoClose) ->
Dir = filename:dirname(code:which(?MODULE)),
- {ok,R} = test_server:start_node(test_default_options_slave,slave,
+ {ok,R} = test_server:start_node(?UNIQ_NODE_NAME, slave,
[{args,"-pa " ++ Dir}]),
Host = list_to_atom(lists:nth(2,string:tokens(atom_to_list(node()),"@"))),
{ok, L} = gen_tcp:listen(0, [binary,{active,false},{packet,0},{nodelay, true},{keepalive, true},
@@ -2718,10 +2610,8 @@ has_superfluous_schedulers() ->
end.
-otp_7731(suite) -> [];
-otp_7731(doc) ->
- "Leaking message from inet_drv {inet_reply,P,ok} "
- "when a socket sending resumes working after a send_timeout";
+%% Leaking message from inet_drv {inet_reply,P,ok}
+%% when a socket sending resumes working after a send_timeout.
otp_7731(Config) when is_list(Config) ->
ServerPid = spawn_link(?MODULE, otp_7731_server, [self()]),
receive {ServerPid, ready, PortNum} -> ok end,
@@ -2738,7 +2628,7 @@ otp_7731(Config) when is_list(Config) ->
%% Now make sure inet_drv does not leak any internal messages.
receive Msg ->
- test_server:fail({unexpected, Msg})
+ ct:fail({unexpected, Msg})
after 1000 ->
ok
end,
@@ -2791,8 +2681,7 @@ otp_7731_recv(Socket) ->
%% OTP-7615: TCP-ports hanging in CLOSING state when sending large
%% buffer followed by a recv() that returns error due to closed
%% connection.
-zombie_sockets(suite) -> [];
-zombie_sockets(doc) -> ["OTP-7615 Leaking closed ports."];
+%% OTP-7615 Leaking closed ports.
zombie_sockets(Config) when is_list(Config) ->
register(zombie_collector,self()),
Calls = 10,
@@ -2872,9 +2761,7 @@ zombie_serve_client(Socket, Bin) ->
gen_tcp:close(Socket),
zombie_collector ! {closed, Socket}.
-otp_7816(suite) -> [];
-otp_7816(doc) ->
- "Hanging send on windows when sending iolist with more than 16 binaries.";
+%% Hanging send on windows when sending iolist with more than 16 binaries.
otp_7816(Config) when is_list(Config) ->
Client = self(),
Server = spawn_link(fun()-> otp_7816_server(Client) end),
@@ -2963,8 +2850,7 @@ otp_7816_recv(CSocket, BytesLeft) ->
error
end.
-otp_8102(doc) -> ["Receive a packet with a faulty packet header"];
-otp_8102(suite) -> [];
+%% Receive a packet with a faulty packet header.
otp_8102(Config) when is_list(Config) ->
{ok, LSocket} = gen_tcp:listen(0, []),
{ok, {_, PortNum}} = inet:sockname(LSocket),
@@ -3004,8 +2890,7 @@ otp_8102_do(LSocket, PortNum, {Bin,PType}) ->
gen_tcp:close(SSocket),
gen_tcp:close(RSocket).
-otp_9389(doc) -> ["Verify packet_size handles long HTTP header lines"];
-otp_9389(suite) -> [];
+%% Verify packet_size handles long HTTP header lines.
otp_9389(Config) when is_list(Config) ->
{ok, LS} = gen_tcp:listen(0, [{active,false}]),
{ok, {_, PortNum}} = inet:sockname(LS),
@@ -3064,10 +2949,10 @@ otp_9389_loop(S, OrigLinkHdr, State) ->
error({timeout,header})
end.
-wrapping_oct(doc) ->
- "Check that 64bit octet counters work.";
-wrapping_oct(suite) ->
- [];
+wrapping_oct() ->
+ [{timetrap,{minutes,10}}].
+
+%% Check that 64bit octet counters work.
wrapping_oct(Config) when is_list(Config) ->
{ok,Sock} = gen_tcp:listen(0,[{active,false},{mode,binary}]),
{ok,Port} = inet:port(Sock),
diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl
index 8d8c953303..19cdc03603 100644
--- a/lib/kernel/test/gen_udp_SUITE.erl
+++ b/lib/kernel/test/gen_udp_SUITE.erl
@@ -17,17 +17,16 @@
%%
%% %CopyrightEnd%
%%
-%
-% test the behavior of gen_udp. Testing udp is really a very unfunny task,
-% because udp is not deterministic.
-%
--module(gen_udp_SUITE).
--include_lib("test_server/include/test_server.hrl").
+%%
+%% Test the behavior of gen_udp. Testing udp is really a very unfunny task,
+%% because udp is not deterministic.
+%%
+-module(gen_udp_SUITE).
+-include_lib("common_test/include/ct.hrl").
--define(default_timeout, ?t:minutes(1)).
-% XXX - we should pick a port that we _know_ is closed. That's pretty hard.
+%% XXX - we should pick a port that we _know_ is closed. That's pretty hard.
-define(CLOSED_PORT, 6666).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -38,7 +37,9 @@
buffer_size/1, binary_passive_recv/1, bad_address/1,
read_packets/1, open_fd/1, connect/1, implicit_inet6/1]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[send_to_closed, buffer_size, binary_passive_recv,
@@ -62,28 +63,22 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_Case, Config) ->
- ?line Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
+ Config.
end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
ok.
%%-------------------------------------------------------------
%% Send two packets to a closed port (on some systems this causes the socket
%% to be closed).
-send_to_closed(doc) ->
- ["Tests core functionality."];
-send_to_closed(suite) ->
- [];
+%% Tests core functionality.
send_to_closed(Config) when is_list(Config) ->
- ?line {ok, Sock} = gen_udp:open(0),
- ?line ok = gen_udp:send(Sock, {127,0,0,1}, ?CLOSED_PORT, "foo"),
+ {ok, Sock} = gen_udp:open(0),
+ ok = gen_udp:send(Sock, {127,0,0,1}, ?CLOSED_PORT, "foo"),
timer:sleep(2),
- ?line ok = gen_udp:send(Sock, {127,0,0,1}, ?CLOSED_PORT, "foo"),
- ?line ok = gen_udp:close(Sock),
+ ok = gen_udp:send(Sock, {127,0,0,1}, ?CLOSED_PORT, "foo"),
+ ok = gen_udp:close(Sock),
ok.
@@ -91,19 +86,16 @@ send_to_closed(Config) when is_list(Config) ->
%%-------------------------------------------------------------
%% Test that the UDP socket buffer sizes are settable
-buffer_size(suite) ->
- [];
-buffer_size(doc) ->
- ["Test UDP buffer size setting."];
+%% Test UDP buffer size setting.
buffer_size(Config) when is_list(Config) ->
- ?line Len = 256,
- ?line Bin = list_to_binary(lists:seq(0, Len-1)),
- ?line M = 8192 div Len,
- ?line Spec0 =
+ Len = 256,
+ Bin = list_to_binary(lists:seq(0, Len-1)),
+ M = 8192 div Len,
+ Spec0 =
[{opt,M},{safe,M-3},{long,M+1},
{opt,2*M},{safe,2*M-3},{long,2*M+1},
{opt,4*M},{safe,4*M-3},{long,4*M+1}],
- ?line Spec =
+ Spec =
[case Tag of
opt ->
[{recbuf,Val*Len},{sndbuf,(Val + 2)*Len}];
@@ -115,12 +107,12 @@ buffer_size(Config) when is_list(Config) ->
[truncated,emsgsize,timeout]}
end || {Tag,Val} <- Spec0],
%%
- ?line {ok, ClientSocket} = gen_udp:open(0, [binary]),
- ?line {ok, ClientPort} = inet:port(ClientSocket),
- ?line Client = self(),
- ?line ClientIP = {127,0,0,1},
- ?line ServerIP = {127,0,0,1},
- ?line Server =
+ {ok, ClientSocket} = gen_udp:open(0, [binary]),
+ {ok, ClientPort} = inet:port(ClientSocket),
+ Client = self(),
+ ClientIP = {127,0,0,1},
+ ServerIP = {127,0,0,1},
+ Server =
spawn_link(
fun () ->
{ok, ServerSocket} = gen_udp:open(0, [binary]),
@@ -130,78 +122,77 @@ buffer_size(Config) when is_list(Config) ->
ServerSocket, 1, Spec),
ok = gen_udp:close(ServerSocket)
end),
- ?line Mref = erlang:monitor(process, Server),
- ?line receive
- {Server,port,ServerPort} ->
- ?line buffer_size_client(Server, ServerIP, ServerPort,
- ClientSocket, 1, Spec)
- end,
- ?line ok = gen_udp:close(ClientSocket),
- ?line receive
- {'DOWN',Mref,_,_,normal} ->
- ?line ok
- end.
+ Mref = erlang:monitor(process, Server),
+ receive
+ {Server,port,ServerPort} ->
+ buffer_size_client(Server, ServerIP, ServerPort,
+ ClientSocket, 1, Spec)
+ end,
+ ok = gen_udp:close(ClientSocket),
+ receive
+ {'DOWN',Mref,_,_,normal} ->
+ ok
+ end.
buffer_size_client(_, _, _, _, _, []) ->
- ?line ok;
+ ok;
buffer_size_client(Server, IP, Port,
Socket, Cnt, [Opts|T]) when is_list(Opts) ->
- ?line io:format("buffer_size_client Cnt=~w setopts ~p.~n", [Cnt,Opts]),
- ?line ok = inet:setopts(Socket, Opts),
- ?line Server ! {self(),setopts,Cnt},
- ?line receive {Server,setopts,Cnt} -> ok end,
- ?line buffer_size_client(Server, IP, Port, Socket, Cnt+1, T);
+ io:format("buffer_size_client Cnt=~w setopts ~p.~n", [Cnt,Opts]),
+ ok = inet:setopts(Socket, Opts),
+ Server ! {self(),setopts,Cnt},
+ receive {Server,setopts,Cnt} -> ok end,
+ buffer_size_client(Server, IP, Port, Socket, Cnt+1, T);
buffer_size_client(Server, IP, Port,
Socket, Cnt, [{B,Replies}|T]=Opts) when is_binary(B) ->
- ?line io:format(
- "buffer_size_client Cnt=~w send size ~w expecting ~p.~n",
- [Cnt,size(B),Replies]),
- ?line ok = gen_udp:send(Socket, IP, Port, <<Cnt,B/binary>>),
- ?line receive
- {Server,Cnt,Reply} ->
- ?line Tag =
- if
- is_tuple(Reply) ->
- element(1, Reply);
- is_atom(Reply) ->
- Reply
- end,
- ?line case lists:member(Tag, Replies) of
- true -> ok;
- false ->
- ?line
- ?t:fail({reply_mismatch,Cnt,Reply,Replies,
- byte_size(B),
- inet:getopts(Socket,
- [sndbuf,recbuf])})
- end,
- ?line buffer_size_client(Server, IP, Port, Socket, Cnt+1, T)
- after 1313 ->
- ?line buffer_size_client(Server, IP, Port, Socket, Cnt, Opts)
- end.
+ io:format(
+ "buffer_size_client Cnt=~w send size ~w expecting ~p.~n",
+ [Cnt,size(B),Replies]),
+ ok = gen_udp:send(Socket, IP, Port, <<Cnt,B/binary>>),
+ receive
+ {Server,Cnt,Reply} ->
+ Tag =
+ if
+ is_tuple(Reply) ->
+ element(1, Reply);
+ is_atom(Reply) ->
+ Reply
+ end,
+ case lists:member(Tag, Replies) of
+ true -> ok;
+ false ->
+ ct:fail({reply_mismatch,Cnt,Reply,Replies,
+ byte_size(B),
+ inet:getopts(Socket,
+ [sndbuf,recbuf])})
+ end,
+ buffer_size_client(Server, IP, Port, Socket, Cnt+1, T)
+ after 1313 ->
+ buffer_size_client(Server, IP, Port, Socket, Cnt, Opts)
+ end.
buffer_size_server(_, _, _, _, _, []) ->
ok;
buffer_size_server(Client, IP, Port,
Socket, Cnt, [Opts|T]) when is_list(Opts) ->
receive {Client,setopts,Cnt} -> ok end,
- ?line io:format("buffer_size_server Cnt=~w setopts ~p.~n", [Cnt,Opts]),
+ io:format("buffer_size_server Cnt=~w setopts ~p.~n", [Cnt,Opts]),
ok = inet:setopts(Socket, Opts),
Client ! {self(),setopts,Cnt},
buffer_size_server(Client, IP, Port, Socket, Cnt+1, T);
buffer_size_server(Client, IP, Port,
Socket, Cnt, [{B,_}|T]) when is_binary(B) ->
- ?line io:format(
- "buffer_size_server Cnt=~w expecting size ~w.~n",
- [Cnt,size(B)]),
+ io:format(
+ "buffer_size_server Cnt=~w expecting size ~w.~n",
+ [Cnt,size(B)]),
Client !
{self(),Cnt,
case buffer_size_server_recv(Socket, IP, Port, Cnt) of
D when is_binary(D) ->
SizeD = byte_size(D),
- ?line io:format(
- "buffer_size_server Cnt=~w received size ~w.~n",
- [Cnt,SizeD]),
+ io:format(
+ "buffer_size_server Cnt=~w received size ~w.~n",
+ [Cnt,SizeD]),
case B of
D ->
correct;
@@ -211,9 +202,9 @@ buffer_size_server(Client, IP, Port,
{unexpected,D}
end;
Error ->
- ?line io:format(
- "buffer_size_server Cnt=~w received error ~w.~n",
- [Cnt,Error]),
+ io:format(
+ "buffer_size_server Cnt=~w received error ~w.~n",
+ [Cnt,Error]),
Error
end},
buffer_size_server(Client, IP, Port, Socket, Cnt+1, T).
@@ -236,50 +227,44 @@ buffer_size_server_recv(Socket, IP, Port, Cnt) ->
%% OTP-3823 gen_udp:recv does not return address in binary mode
%%
-binary_passive_recv(suite) ->
- [];
-binary_passive_recv(doc) ->
- ["OTP-3823 gen_udp:recv does not return address in binary mode"];
+%% OTP-3823 gen_udp:recv does not return address in binary mode.
binary_passive_recv(Config) when is_list(Config) ->
- ?line D1 = "The quick brown fox jumps over a lazy dog",
- ?line D2 = list_to_binary(D1),
- ?line D3 = ["The quick", <<" brown ">>, "fox jumps ", <<"over ">>,
- <<>>, $a, [[], " lazy ", <<"dog">>]],
- ?line D2 = iolist_to_binary(D3),
- ?line B = D2,
- ?line {ok, R} = gen_udp:open(0, [binary, {active, false}]),
- ?line {ok, RP} = inet:port(R),
- ?line {ok, S} = gen_udp:open(0),
- ?line {ok, SP} = inet:port(S),
- ?line ok = gen_udp:send(S, localhost, RP, D1),
- ?line {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1),
- ?line ok = gen_udp:send(S, localhost, RP, D2),
- ?line {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1),
- ?line ok = gen_udp:send(S, localhost, RP, D3),
- ?line {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1),
- ?line ok = gen_udp:close(S),
- ?line ok = gen_udp:close(R),
+ D1 = "The quick brown fox jumps over a lazy dog",
+ D2 = list_to_binary(D1),
+ D3 = ["The quick", <<" brown ">>, "fox jumps ", <<"over ">>,
+ <<>>, $a, [[], " lazy ", <<"dog">>]],
+ D2 = iolist_to_binary(D3),
+ B = D2,
+ {ok, R} = gen_udp:open(0, [binary, {active, false}]),
+ {ok, RP} = inet:port(R),
+ {ok, S} = gen_udp:open(0),
+ {ok, SP} = inet:port(S),
+ ok = gen_udp:send(S, localhost, RP, D1),
+ {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1),
+ ok = gen_udp:send(S, localhost, RP, D2),
+ {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1),
+ ok = gen_udp:send(S, localhost, RP, D3),
+ {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1),
+ ok = gen_udp:close(S),
+ ok = gen_udp:close(R),
ok.
%%-------------------------------------------------------------
%% OTP-3836 inet_udp crashes when IP-address is larger than 255.
-bad_address(suite) ->
- [];
-bad_address(doc) ->
- ["OTP-3836 inet_udp crashes when IP-address is larger than 255."];
+%% OTP-3836 inet_udp crashes when IP-address is larger than 255.
bad_address(Config) when is_list(Config) ->
- ?line {ok, R} = gen_udp:open(0),
- ?line {ok, RP} = inet:port(R),
- ?line {ok, S} = gen_udp:open(0),
- ?line {ok, _SP} = inet:port(S),
- ?line {'EXIT', badarg} =
+ {ok, R} = gen_udp:open(0),
+ {ok, RP} = inet:port(R),
+ {ok, S} = gen_udp:open(0),
+ {ok, _SP} = inet:port(S),
+ {'EXIT', badarg} =
(catch gen_udp:send(S, {127,0,0,1,0}, RP, "void")),
- ?line {'EXIT', badarg} =
+ {'EXIT', badarg} =
(catch gen_udp:send(S, {127,0,0,256}, RP, "void")),
- ?line ok = gen_udp:close(S),
- ?line ok = gen_udp:close(R),
+ ok = gen_udp:close(S),
+ ok = gen_udp:close(R),
ok.
@@ -298,8 +283,7 @@ bad_address(Config) when is_list(Config) ->
%% What happens on the SMP emulator remains to be seen...
%%
-read_packets(doc) ->
- ["OTP-6249 UDP option for number of packet reads."];
+%% OTP-6249 UDP option for number of packet reads.
read_packets(Config) when is_list(Config) ->
case erlang:system_info(smp_support) of
false ->
@@ -311,35 +295,35 @@ read_packets(Config) when is_list(Config) ->
end.
read_packets_1() ->
- ?line N1 = 5,
- ?line N2 = 7,
- ?line {ok,R} = gen_udp:open(0, [{read_packets,N1}]),
- ?line {ok,RP} = inet:port(R),
- ?line {ok,Node} = start_node(gen_udp_SUITE_read_packets),
- ?line Die = make_ref(),
- ?line Loop = erlang:spawn_link(fun () -> infinite_loop(Die) end),
+ N1 = 5,
+ N2 = 7,
+ {ok,R} = gen_udp:open(0, [{read_packets,N1}]),
+ {ok,RP} = inet:port(R),
+ {ok,Node} = start_node(gen_udp_SUITE_read_packets),
+ Die = make_ref(),
+ Loop = erlang:spawn_link(fun () -> infinite_loop(Die) end),
%%
- ?line Msgs1 = [erlang:integer_to_list(M) || M <- lists:seq(1, N1*3)],
- ?line [V1|_] = read_packets_test(R, RP, Msgs1, Node),
- ?line {ok,[{read_packets,N1}]} = inet:getopts(R, [read_packets]),
+ Msgs1 = [erlang:integer_to_list(M) || M <- lists:seq(1, N1*3)],
+ [V1|_] = read_packets_test(R, RP, Msgs1, Node),
+ {ok,[{read_packets,N1}]} = inet:getopts(R, [read_packets]),
%%
- ?line ok = inet:setopts(R, [{read_packets,N2}]),
- ?line Msgs2 = [erlang:integer_to_list(M) || M <- lists:seq(1, N2*3)],
- ?line [V2|_] = read_packets_test(R, RP, Msgs2, Node),
- ?line {ok,[{read_packets,N2}]} = inet:getopts(R, [read_packets]),
+ ok = inet:setopts(R, [{read_packets,N2}]),
+ Msgs2 = [erlang:integer_to_list(M) || M <- lists:seq(1, N2*3)],
+ [V2|_] = read_packets_test(R, RP, Msgs2, Node),
+ {ok,[{read_packets,N2}]} = inet:getopts(R, [read_packets]),
%%
- ?line stop_node(Node),
- ?line Mref = erlang:monitor(process, Loop),
- ?line Loop ! Die,
- ?line receive
- {'DOWN',Mref,_,_, normal} ->
- case {V1,V2} of
- {N1,N2} ->
- ok;
- _ when V1 =/= N1, V2 =/= N2 ->
- ok
- end
- end.
+ stop_node(Node),
+ Mref = erlang:monitor(process, Loop),
+ Loop ! Die,
+ receive
+ {'DOWN',Mref,_,_, normal} ->
+ case {V1,V2} of
+ {N1,N2} ->
+ ok;
+ _ when V1 =/= N1, V2 =/= N2 ->
+ ok
+ end
+ end.
infinite_loop(Die) ->
receive
@@ -407,21 +391,21 @@ read_packets_recv(N) ->
read_packets_verify(R, SP, Msg, Trace) ->
lists:reverse(
- lists:sort(read_packets_verify(R, SP, Msg, Trace, 0))).
-
+ lists:sort(read_packets_verify(R, SP, Msg, Trace, 0))).
+
read_packets_verify(R, SP, Msgs, [{trace,Self,OutIn,_}|Trace], M)
when Self =:= self(), OutIn =:= out;
Self =:= self(), OutIn =:= in ->
push(M, read_packets_verify(R, SP, Msgs, Trace, 0));
read_packets_verify(R, SP, [Msg|Msgs],
- [{trace,Self,'receive',{udp,R,{127,0,0,1},SP,Msg}}
- |Trace], M)
+ [{trace,Self,'receive',{udp,R,{127,0,0,1},SP,Msg}}
+ |Trace], M)
when Self =:= self() ->
read_packets_verify(R, SP, Msgs, Trace, M+1);
read_packets_verify(_R, _SP, [], [], M) ->
push(M, []);
read_packets_verify(_R, _SP, Msgs, Trace, M) ->
- ?t:fail({read_packets_verify,mismatch,Msgs,Trace,M}).
+ ct:fail({read_packets_verify,mismatch,Msgs,Trace,M}).
push(0, Vs) ->
Vs;
@@ -438,10 +422,7 @@ flush() ->
-open_fd(suite) ->
- [];
-open_fd(doc) ->
- ["Test that the 'fd' option works"];
+%% Test that the 'fd' option works.
open_fd(Config) when is_list(Config) ->
Msg = "Det gör ont när knoppar brista. Varför skulle annars våren tveka?",
Addr = {127,0,0,1},
@@ -460,10 +441,10 @@ open_fd(Config) when is_list(Config) ->
{udp,S3,Addr,P2,Msg} ->
ok
after 1000 ->
- ?t:fail(io_lib:format("~w", [flush()]))
+ ct:fail(io_lib:format("~w", [flush()]))
end
after 1000 ->
- ?t:fail(io_lib:format("~w", [flush()]))
+ ct:fail(io_lib:format("~w", [flush()]))
end.
active_n(Config) when is_list(Config) ->
@@ -569,88 +550,84 @@ active_n(Config) when is_list(Config) ->
ok = gen_udp:close(S1),
ok.
-%
-% Utils
-%
+%%
+%% Utils
+%%
+
start_node(Name) ->
Pa = filename:dirname(code:which(?MODULE)),
- ?t:start_node(Name, slave, [{args, "-pa " ++ Pa}]).
+ test_server:start_node(Name, slave, [{args, "-pa " ++ Pa}]).
stop_node(Node) ->
- ?t:stop_node(Node).
+ test_server:stop_node(Node).
-connect(suite) ->
- [];
-connect(doc) ->
- ["Test that connect/3 has effect"];
+%% Test that connect/3 has effect.
connect(Config) when is_list(Config) ->
- ?line Addr = {127,0,0,1},
- ?line {ok,S1} = gen_udp:open(0),
- ?line {ok,P1} = inet:port(S1),
- ?line {ok,S2} = gen_udp:open(0),
- ?line ok = inet:setopts(S2, [{active,false}]),
- ?line ok = gen_udp:close(S1),
- ?line ok = gen_udp:connect(S2, Addr, P1),
- ?line ok = gen_udp:send(S2, <<16#deadbeef:32>>),
- ?line ok = case gen_udp:recv(S2, 0, 5) of
- {error,econnrefused} -> ok;
- {error,econnreset} -> ok;
- Other -> Other
- end,
+ Addr = {127,0,0,1},
+ {ok,S1} = gen_udp:open(0),
+ {ok,P1} = inet:port(S1),
+ {ok,S2} = gen_udp:open(0),
+ ok = inet:setopts(S2, [{active,false}]),
+ ok = gen_udp:close(S1),
+ ok = gen_udp:connect(S2, Addr, P1),
+ ok = gen_udp:send(S2, <<16#deadbeef:32>>),
+ ok = case gen_udp:recv(S2, 0, 5) of
+ {error,econnrefused} -> ok;
+ {error,econnreset} -> ok;
+ Other -> Other
+ end,
ok.
implicit_inet6(Config) when is_list(Config) ->
- ?line Host = ok(inet:gethostname()),
- ?line
- case inet:getaddr(Host, inet6) of
- {ok,Addr} ->
- ?line implicit_inet6(Host, Addr);
- {error,Reason} ->
- {skip,
- "Can not look up IPv6 address: "
- ++atom_to_list(Reason)}
- end.
+ Host = ok(inet:gethostname()),
+ case inet:getaddr(Host, inet6) of
+ {ok,Addr} ->
+ implicit_inet6(Host, Addr);
+ {error,Reason} ->
+ {skip,
+ "Can not look up IPv6 address: "
+ ++atom_to_list(Reason)}
+ end.
implicit_inet6(Host, Addr) ->
- ?line Active = {active,false},
- ?line
- case gen_udp:open(0, [inet6,Active]) of
- {ok,S1} ->
- ?line Loopback = {0,0,0,0,0,0,0,1},
- ?line io:format("~s ~p~n", ["::1",Loopback]),
- ?line implicit_inet6(S1, Active, Loopback),
- ?line ok = gen_udp:close(S1),
- %%
- ?line Localhost = "localhost",
- ?line Localaddr = ok(inet:getaddr(Localhost, inet6)),
- ?line io:format("~s ~p~n", [Localhost,Localaddr]),
- ?line S2 = ok(gen_udp:open(0, [{ip,Localaddr},Active])),
- ?line implicit_inet6(S2, Active, Localaddr),
- ?line ok = gen_udp:close(S2),
- %%
- ?line io:format("~s ~p~n", [Host,Addr]),
- ?line S3 = ok(gen_udp:open(0, [{ifaddr,Addr},Active])),
- ?line implicit_inet6(S3, Active, Addr),
- ?line ok = gen_udp:close(S3);
- _ ->
- {skip,"IPv6 not supported"}
- end.
+ Active = {active,false},
+ case gen_udp:open(0, [inet6,Active]) of
+ {ok,S1} ->
+ Loopback = {0,0,0,0,0,0,0,1},
+ io:format("~s ~p~n", ["::1",Loopback]),
+ implicit_inet6(S1, Active, Loopback),
+ ok = gen_udp:close(S1),
+ %%
+ Localhost = "localhost",
+ Localaddr = ok(inet:getaddr(Localhost, inet6)),
+ io:format("~s ~p~n", [Localhost,Localaddr]),
+ S2 = ok(gen_udp:open(0, [{ip,Localaddr},Active])),
+ implicit_inet6(S2, Active, Localaddr),
+ ok = gen_udp:close(S2),
+ %%
+ io:format("~s ~p~n", [Host,Addr]),
+ S3 = ok(gen_udp:open(0, [{ifaddr,Addr},Active])),
+ implicit_inet6(S3, Active, Addr),
+ ok = gen_udp:close(S3);
+ _ ->
+ {skip,"IPv6 not supported"}
+ end.
implicit_inet6(S1, Active, Addr) ->
- ?line P1 = ok(inet:port(S1)),
- ?line S2 = ok(gen_udp:open(0, [inet6,Active])),
- ?line P2 = ok(inet:port(S2)),
- ?line ok = gen_udp:connect(S2, Addr, P1),
- ?line ok = gen_udp:connect(S1, Addr, P2),
- ?line {Addr,P2} = ok(inet:peername(S1)),
- ?line {Addr,P1} = ok(inet:peername(S2)),
- ?line {Addr,P1} = ok(inet:sockname(S1)),
- ?line {Addr,P2} = ok(inet:sockname(S2)),
- ?line ok = gen_udp:send(S1, Addr, P2, "ping"),
- ?line {Addr,P1,"ping"} = ok(gen_udp:recv(S2, 1024, 1000)),
- ?line ok = gen_udp:send(S2, Addr, P1, "pong"),
- ?line {Addr,P2,"pong"} = ok(gen_udp:recv(S1, 1024)),
- ?line ok = gen_udp:close(S2).
+ P1 = ok(inet:port(S1)),
+ S2 = ok(gen_udp:open(0, [inet6,Active])),
+ P2 = ok(inet:port(S2)),
+ ok = gen_udp:connect(S2, Addr, P1),
+ ok = gen_udp:connect(S1, Addr, P2),
+ {Addr,P2} = ok(inet:peername(S1)),
+ {Addr,P1} = ok(inet:peername(S2)),
+ {Addr,P1} = ok(inet:sockname(S1)),
+ {Addr,P2} = ok(inet:sockname(S2)),
+ ok = gen_udp:send(S1, Addr, P2, "ping"),
+ {Addr,P1,"ping"} = ok(gen_udp:recv(S2, 1024, 1000)),
+ ok = gen_udp:send(S2, Addr, P1, "pong"),
+ {Addr,P2,"pong"} = ok(gen_udp:recv(S1, 1024)),
+ ok = gen_udp:close(S2).
ok({ok,V}) -> V.
diff --git a/lib/kernel/test/global_SUITE.erl b/lib/kernel/test/global_SUITE.erl
index 73ee86eba4..dd4cf82d4a 100644
--- a/lib/kernel/test/global_SUITE.erl
+++ b/lib/kernel/test/global_SUITE.erl
@@ -19,8 +19,6 @@
%%
-module(global_SUITE).
-%-define(line_trace, 1).
-
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
init_per_suite/1, end_per_suite/1,
names/1, names_hidden/1, locks/1, locks_hidden/1,
@@ -51,7 +49,7 @@
-compile(export_all).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(NODES, [node()|nodes()]).
@@ -61,7 +59,8 @@
-define(GLOBAL_LOCK, global).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]}].
all() ->
case init:get_argument(ring_line) of
@@ -86,10 +85,10 @@ groups() ->
ring]}].
init_per_group(_GroupName, Config) ->
- Config.
+ Config.
end_per_group(_GroupName, Config) ->
- Config.
+ Config.
init_per_suite(Config) ->
Config.
@@ -99,9 +98,9 @@ end_per_suite(_Config) ->
-define(TESTCASE, testcase_name).
--define(testcase, ?config(?TESTCASE, Config)).
+-define(testcase, proplists:get_value(?TESTCASE, Config)).
-define(nodes_tag, '$global_nodes').
--define(registered, ?config(registered, Config)).
+-define(registered, proplists:get_value(registered, Config)).
init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
ok = gen_server:call(global_name_server, high_level_trace_start,infinity),
@@ -115,16 +114,16 @@ init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
end_per_testcase(_Case, Config) ->
ct:log("Calling end_per_testcase!",[]),
- ?line write_high_level_trace(Config),
- ?line _ =
+ write_high_level_trace(Config),
+ _ =
gen_server:call(global_name_server, high_level_trace_stop, infinity),
[global:unregister_name(N) || N <- global:registered_names()],
- ?line InitRegistered = ?registered,
- ?line Registered = registered(),
- ?line [io:format("~s local names: ~p~n", [What, N]) ||
- {What, N} <- [{"Added", Registered -- InitRegistered},
- {"Removed", InitRegistered -- Registered}],
- N =/= []],
+ InitRegistered = ?registered,
+ Registered = registered(),
+ [io:format("~s local names: ~p~n", [What, N]) ||
+ {What, N} <- [{"Added", Registered -- InitRegistered},
+ {"Removed", InitRegistered -- Registered}],
+ N =/= []],
ok.
@@ -147,12 +146,11 @@ end_per_testcase(_Case, Config) ->
%%% and releases the lock. Now the name should exist on both our own node
%%% and on the slave node (we wait until that is true; it seems that we
%%% can do rpc calls to another node before the connection is really up).
-register_1(suite) -> [];
register_1(Config) when is_list(Config) ->
Timeout = 15,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
+ init_condition(Config),
P = spawn_link(?MODULE, lock_global, [self(), Config]),
receive
{P, ok} ->
@@ -161,7 +159,7 @@ register_1(Config) when is_list(Config) ->
end,
P ! step2,
io:format("p1: sent step2~n"),
- ?line yes = global:register_name(foo, self()),
+ yes = global:register_name(foo, self()),
io:format("p1: registered~n"),
P ! step3,
receive
@@ -172,11 +170,11 @@ register_1(Config) when is_list(Config) ->
I =:= I2 ->
ok;
true ->
- test_server:fail({notsync, I, I2})
+ ct:fail({notsync, I, I2})
end,
- ?line _ = global:unregister_name(foo),
+ _ = global:unregister_name(foo),
write_high_level_trace(Config),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
lock_global(Parent, Config) ->
@@ -203,7 +201,7 @@ lock_global(Parent, Config) ->
io:format("p2: received step3~n"),
I = global:whereis_name(foo),
io:format("p2: name ~p~n", [I]),
- ?line ?UNTIL(I =:= rpc:call(N1, global, whereis_name, [foo])),
+ ?UNTIL(I =:= rpc:call(N1, global, whereis_name, [foo])),
I2 = I,
slave:stop(N1),
io:format("p2: name2 ~p~n", [I2]),
@@ -216,75 +214,73 @@ lock_global(Parent, Config) ->
%%% 'try_again_locker' would be called, and this time cause both 1 and 2
%%% to obtain a lock for 'global' on node 3, which would keep the
%%% name registry from ever becoming consistent again.
-both_known_1(suite) -> [];
both_known_1(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
+ init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ OrigNames = global:registered_names(),
- ?line [Cp1, Cp2, Cp3] = start_nodes([cp1, cp2, cp3], slave, Config),
+ [Cp1, Cp2, Cp3] = start_nodes([cp1, cp2, cp3], slave, Config),
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
- ?line rpc_disconnect_node(Cp1, Cp2, Config),
+ rpc_disconnect_node(Cp1, Cp2, Config),
- ?line {_Pid1, yes} = rpc:call(Cp1, ?MODULE, start_proc, [p1]),
- ?line {_Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [p2]),
+ {_Pid1, yes} = rpc:call(Cp1, ?MODULE, start_proc, [p1]),
+ {_Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [p2]),
- ?line Names10 = rpc:call(Cp1, global, registered_names, []),
- ?line Names20 = rpc:call(Cp2, global, registered_names, []),
- ?line Names30 = rpc:call(Cp3, global, registered_names, []),
+ Names10 = rpc:call(Cp1, global, registered_names, []),
+ Names20 = rpc:call(Cp2, global, registered_names, []),
+ Names30 = rpc:call(Cp3, global, registered_names, []),
Names1 = Names10 -- OrigNames,
Names2 = Names20 -- OrigNames,
Names3 = Names30 -- OrigNames,
- ?line [p1] = lists:sort(Names1),
- ?line [p2] = lists:sort(Names2),
- ?line [p1, p2] = lists:sort(Names3),
+ [p1] = lists:sort(Names1),
+ [p2] = lists:sort(Names2),
+ [p1, p2] = lists:sort(Names3),
- ?line Locker = spawn(Cp3, ?MODULE, lock_global2, [{global, l3},
- self()]),
+ Locker = spawn(Cp3, ?MODULE, lock_global2, [{global, l3},
+ self()]),
- ?line receive
- {locked, S} ->
- true = S
- end,
+ receive
+ {locked, S} ->
+ true = S
+ end,
- ?line pong = rpc:call(Cp1, net_adm, ping, [Cp2]),
+ pong = rpc:call(Cp1, net_adm, ping, [Cp2]),
%% Bring cp1 and cp2 together, while someone has locked global.
%% They will now loop in 'loop_locker'.
- ?line Names10_2 = rpc:call(Cp1, global, registered_names, []),
- ?line Names20_2 = rpc:call(Cp2, global, registered_names, []),
- ?line Names30_2 = rpc:call(Cp3, global, registered_names, []),
+ Names10_2 = rpc:call(Cp1, global, registered_names, []),
+ Names20_2 = rpc:call(Cp2, global, registered_names, []),
+ Names30_2 = rpc:call(Cp3, global, registered_names, []),
Names1_2 = Names10_2 -- OrigNames,
Names2_2 = Names20_2 -- OrigNames,
Names3_2 = Names30_2 -- OrigNames,
- ?line [p1] = lists:sort(Names1_2),
- ?line [p2] = lists:sort(Names2_2),
- ?line [p1, p2] = lists:sort(Names3_2),
+ [p1] = lists:sort(Names1_2),
+ [p2] = lists:sort(Names2_2),
+ [p1, p2] = lists:sort(Names3_2),
%% Let go of the lock, and expect the lockers to resolve the name
%% registry.
Locker ! {ok, self()},
- ?line
?UNTIL(begin
- ?line Names10_3 = rpc:call(Cp1, global, registered_names, []),
- ?line Names20_3 = rpc:call(Cp2, global, registered_names, []),
- ?line Names30_3 = rpc:call(Cp3, global, registered_names, []),
-
+ Names10_3 = rpc:call(Cp1, global, registered_names, []),
+ Names20_3 = rpc:call(Cp2, global, registered_names, []),
+ Names30_3 = rpc:call(Cp3, global, registered_names, []),
+
Names1_3 = Names10_3 -- OrigNames,
Names2_3 = Names20_3 -- OrigNames,
Names3_3 = Names30_3 -- OrigNames,
-
+
N1 = lists:sort(Names1_3),
N2 = lists:sort(Names2_3),
N3 = lists:sort(Names3_3),
@@ -296,51 +292,49 @@ both_known_1(Config) when is_list(Config) ->
stop_node(Cp2),
stop_node(Cp3),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-lost_unregister(suite) -> [];
-lost_unregister(doc) ->
- ["OTP-6428. An unregistered name reappears."];
+%% OTP-6428. An unregistered name reappears.
lost_unregister(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
+ init_condition(Config),
- ?line {ok, B} = start_node(b, Config),
- ?line {ok, C} = start_node(c, Config),
+ {ok, B} = start_node(b, Config),
+ {ok, C} = start_node(c, Config),
Nodes = [node(), B, C],
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
- % start a proc and register it
- ?line {Pid, yes} = start_proc(test),
+ %% start a proc and register it
+ {Pid, yes} = start_proc(test),
- ?line ?UNTIL(Pid =:= global:whereis_name(test)),
- ?line check_everywhere(Nodes, test, Config),
+ ?UNTIL(Pid =:= global:whereis_name(test)),
+ check_everywhere(Nodes, test, Config),
- ?line rpc_disconnect_node(B, C, Config),
- ?line check_everywhere(Nodes, test, Config),
- ?line _ = rpc:call(B, global, unregister_name, [test]),
- ?line ?UNTIL(undefined =:= global:whereis_name(test)),
- ?line Pid = rpc:call(C, global, whereis_name, [test]),
- ?line check_everywhere(Nodes--[C], test, Config),
- ?line pong = rpc:call(B, net_adm, ping, [C]),
+ rpc_disconnect_node(B, C, Config),
+ check_everywhere(Nodes, test, Config),
+ _ = rpc:call(B, global, unregister_name, [test]),
+ ?UNTIL(undefined =:= global:whereis_name(test)),
+ Pid = rpc:call(C, global, whereis_name, [test]),
+ check_everywhere(Nodes--[C], test, Config),
+ pong = rpc:call(B, net_adm, ping, [C]),
%% Now the name has reappeared on node B.
- ?line ?UNTIL(Pid =:= global:whereis_name(test)),
- ?line check_everywhere(Nodes, test, Config),
+ ?UNTIL(Pid =:= global:whereis_name(test)),
+ check_everywhere(Nodes, test, Config),
exit_p(Pid),
- ?line ?UNTIL(undefined =:= global:whereis_name(test)),
- ?line check_everywhere(Nodes, test, Config),
+ ?UNTIL(undefined =:= global:whereis_name(test)),
+ check_everywhere(Nodes, test, Config),
write_high_level_trace(Config),
stop_node(B),
stop_node(C),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-define(UNTIL_LOOP, 300).
@@ -350,7 +344,7 @@ lost_unregister(Config) when is_list(Config) ->
init_high_level_trace(Time) ->
Mul = try
test_server:timetrap_scale_factor()
- catch _:_ -> 1
+ catch _:_ -> 1
end,
put(?end_tag, msec() + Time * Mul * 1000),
%% Assures that started nodes start the high level trace automatically.
@@ -395,7 +389,7 @@ write_high_level_trace(Nodes, Config) ->
%% 'info' returns more than the trace, which is nice.
Data = [{Node, {info, rpc:call(Node, global, info, [])}} ||
Node <- Nodes],
- Dir = ?config(priv_dir, Config),
+ Dir = proplists:get_value(priv_dir, Config),
DataFile = filename:join([Dir, lists:concat(["global_", ?testcase])]),
file:write_file(DataFile, term_to_binary({high_level_trace, When, Data})).
@@ -413,37 +407,35 @@ lock_global2(Id, Parent) ->
%% erl -sname XXX -rsh ctrsh where XX not in [cp1, cp2, cp3]
%%-----------------------------------------------------------------
-%cp1 - cp3 are started, and the name 'test' registered for a process on
-%test_server. Then it is checked that the name is registered on all
-%nodes, using whereis_name. Check that the same
-%name can't be registered with another value. Exit the registered
-%process and check that the name disappears. Register a new process
-%(Pid2) under the name 'test'. Let another new process (Pid3)
-%reregister itself under the same name. Test global:send/2. Test
-%unregister. Kill Pid3. Start a process (Pid6) on cp3,
-%register it as 'test', stop cp1 - cp3 and check that 'test' disappeared.
-%Kill Pid2 and check that 'test' isn't registered.
-
-names(suite) -> [];
+%% cp1 - cp3 are started, and the name 'test' registered for a process on
+%% test_server. Then it is checked that the name is registered on all
+%% nodes, using whereis_name. Check that the same
+%% name can't be registered with another value. Exit the registered
+%% process and check that the name disappears. Register a new process
+%% (Pid2) under the name 'test'. Let another new process (Pid3)
+%% reregister itself under the same name. Test global:send/2. Test
+%% unregister. Kill Pid3. Start a process (Pid6) on cp3,
+%% register it as 'test', stop cp1 - cp3 and check that 'test' disappeared.
+%% Kill Pid2 and check that 'test' isn't registered.
+
names(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
- ?line {ok, Cp1} = start_node(cp1, Config),
- ?line {ok, Cp2} = start_node(cp2, Config),
- ?line {ok, Cp3} = start_node(cp3, Config),
+ {ok, Cp1} = start_node(cp1, Config),
+ {ok, Cp2} = start_node(cp2, Config),
+ {ok, Cp3} = start_node(cp3, Config),
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
- % start a proc and register it
- ?line {Pid, yes} = start_proc(test),
+ %% start a proc and register it
+ {Pid, yes} = start_proc(test),
- % test that it is registered at all nodes
- ?line
- ?UNTIL(begin
+ %% test that it is registered at all nodes
+ ?UNTIL(begin
(Pid =:= global:whereis_name(test)) and
(Pid =:= rpc:call(Cp1, global, whereis_name, [test])) and
(Pid =:= rpc:call(Cp2, global, whereis_name, [test])) and
@@ -451,156 +443,148 @@ names(Config) when is_list(Config) ->
([test] =:= global:registered_names() -- OrigNames)
end),
- % try to register the same name
- ?line no = global:register_name(test, self()),
- ?line no = rpc:call(Cp1, global, register_name, [test, self()]),
+ %% try to register the same name
+ no = global:register_name(test, self()),
+ no = rpc:call(Cp1, global, register_name, [test, self()]),
- % let process exit, check that it is unregistered automatically
+ %% let process exit, check that it is unregistered automatically
exit_p(Pid),
- ?line
- ?UNTIL((undefined =:= global:whereis_name(test)) and
+ ?UNTIL((undefined =:= global:whereis_name(test)) and
(undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and
(undefined =:= rpc:call(Cp2, global, whereis_name, [test])) and
(undefined =:= rpc:call(Cp3, global, whereis_name, [test]))),
- % test re_register
- ?line {Pid2, yes} = start_proc(test),
- ?line ?UNTIL(Pid2 =:= rpc:call(Cp3, global, whereis_name, [test])),
+ %% test re_register
+ {Pid2, yes} = start_proc(test),
+ ?UNTIL(Pid2 =:= rpc:call(Cp3, global, whereis_name, [test])),
Pid3 = rpc:call(Cp3, ?MODULE, start_proc2, [test]),
- ?line ?UNTIL(Pid3 =:= rpc:call(Cp3, global, whereis_name, [test])),
+ ?UNTIL(Pid3 =:= rpc:call(Cp3, global, whereis_name, [test])),
Pid3 = global:whereis_name(test),
- % test sending
+ %% test sending
global:send(test, {ping, self()}),
receive
{pong, Cp3} -> ok
after
- 2000 -> test_server:fail(timeout1)
+ 2000 -> ct:fail(timeout1)
end,
rpc:call(Cp1, global, send, [test, {ping, self()}]),
receive
{pong, Cp3} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
- ?line _ = global:unregister_name(test),
- ?line
- ?UNTIL((undefined =:= global:whereis_name(test)) and
+ _ = global:unregister_name(test),
+ ?UNTIL((undefined =:= global:whereis_name(test)) and
(undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and
(undefined =:= rpc:call(Cp2, global, whereis_name, [test])) and
(undefined =:= rpc:call(Cp3, global, whereis_name, [test]))),
exit_p(Pid3),
- ?line ?UNTIL(undefined =:= global:whereis_name(test)),
+ ?UNTIL(undefined =:= global:whereis_name(test)),
- % register a proc
- ?line {_Pid6, yes} = rpc:call(Cp3, ?MODULE, start_proc, [test]),
+ %% register a proc
+ {_Pid6, yes} = rpc:call(Cp3, ?MODULE, start_proc, [test]),
write_high_level_trace(Config),
- % stop the nodes, and make sure names are released.
+
+ %% stop the nodes, and make sure names are released.
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
- ?line ?UNTIL(undefined =:= global:whereis_name(test)),
+ ?UNTIL(undefined =:= global:whereis_name(test)),
exit_p(Pid2),
- ?line ?UNTIL(undefined =:= global:whereis_name(test)),
- ?line init_condition(Config),
+ ?UNTIL(undefined =:= global:whereis_name(test)),
+ init_condition(Config),
ok.
-names_hidden(suite) -> [];
-names_hidden(doc) ->
- ["Tests that names on a hidden node doesn't interfere with names on "
- "visible nodes."];
+%% Tests that names on a hidden node doesn't interfere with names on
+%% visible nodes.
names_hidden(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
- ?line OrigNodes = nodes(),
-
- ?line {ok, Cp1} = start_node(cp1, Config),
- ?line {ok, Cp2} = start_node(cp2, Config),
- ?line {ok, Cp3} = start_hidden_node(cp3, Config),
- ?line pong = rpc:call(Cp1, net_adm, ping, [Cp3]),
- ?line pong = rpc:call(Cp3, net_adm, ping, [Cp2]),
- ?line pong = rpc:call(Cp3, net_adm, ping, [node()]),
-
- ?line [] = [Cp1, Cp2 | OrigNodes] -- nodes(),
-
- % start a proc on hidden node and register it
- ?line {HPid, yes} = rpc:call(Cp3, ?MODULE, start_proc, [test]),
- ?line Cp3 = node(HPid),
-
- % Check that it didn't get registered on visible nodes
- ?line
- ?UNTIL((undefined =:= global:whereis_name(test)) and
+ init_condition(Config),
+ OrigNames = global:registered_names(),
+ OrigNodes = nodes(),
+
+ {ok, Cp1} = start_node(cp1, Config),
+ {ok, Cp2} = start_node(cp2, Config),
+ {ok, Cp3} = start_hidden_node(cp3, Config),
+ pong = rpc:call(Cp1, net_adm, ping, [Cp3]),
+ pong = rpc:call(Cp3, net_adm, ping, [Cp2]),
+ pong = rpc:call(Cp3, net_adm, ping, [node()]),
+
+ [] = [Cp1, Cp2 | OrigNodes] -- nodes(),
+
+ %% start a proc on hidden node and register it
+ {HPid, yes} = rpc:call(Cp3, ?MODULE, start_proc, [test]),
+ Cp3 = node(HPid),
+
+ %% Check that it didn't get registered on visible nodes
+ ?UNTIL((undefined =:= global:whereis_name(test)) and
(undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and
(undefined =:= rpc:call(Cp2, global, whereis_name, [test]))),
- % start a proc on visible node and register it
- ?line {Pid, yes} = start_proc(test),
- ?line true = (Pid =/= HPid),
+ %% start a proc on visible node and register it
+ {Pid, yes} = start_proc(test),
+ true = (Pid =/= HPid),
- % test that it is registered at all nodes
- ?line
- ?UNTIL((Pid =:= global:whereis_name(test)) and
+ %% test that it is registered at all nodes
+ ?UNTIL((Pid =:= global:whereis_name(test)) and
(Pid =:= rpc:call(Cp1, global, whereis_name, [test])) and
(Pid =:= rpc:call(Cp2, global, whereis_name, [test])) and
(HPid =:= rpc:call(Cp3, global, whereis_name, [test])) and
([test] =:= global:registered_names() -- OrigNames)),
- % try to register the same name
- ?line no = global:register_name(test, self()),
- ?line no = rpc:call(Cp1, global, register_name, [test, self()]),
+ %% try to register the same name
+ no = global:register_name(test, self()),
+ no = rpc:call(Cp1, global, register_name, [test, self()]),
- % let process exit, check that it is unregistered automatically
+ %% let process exit, check that it is unregistered automatically
exit_p(Pid),
- ?line
- ?UNTIL((undefined =:= global:whereis_name(test)) and
+ ?UNTIL((undefined =:= global:whereis_name(test)) and
(undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and
(undefined =:= rpc:call(Cp2, global, whereis_name, [test])) and
(HPid =:= rpc:call(Cp3, global, whereis_name, [test]))),
- % test re_register
- ?line {Pid2, yes} = start_proc(test),
- ?line ?UNTIL(Pid2 =:= rpc:call(Cp2, global, whereis_name, [test])),
+ %% test re_register
+ {Pid2, yes} = start_proc(test),
+ ?UNTIL(Pid2 =:= rpc:call(Cp2, global, whereis_name, [test])),
Pid3 = rpc:call(Cp2, ?MODULE, start_proc2, [test]),
- ?line ?UNTIL(Pid3 =:= rpc:call(Cp2, global, whereis_name, [test])),
- ?line Pid3 = global:whereis_name(test),
+ ?UNTIL(Pid3 =:= rpc:call(Cp2, global, whereis_name, [test])),
+ Pid3 = global:whereis_name(test),
- % test sending
- ?line Pid3 = global:send(test, {ping, self()}),
+ %% test sending
+ Pid3 = global:send(test, {ping, self()}),
receive
{pong, Cp2} -> ok
after
- 2000 -> test_server:fail(timeout1)
+ 2000 -> ct:fail(timeout1)
end,
rpc:call(Cp1, global, send, [test, {ping, self()}]),
receive
{pong, Cp2} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
- ?line _ = rpc:call(Cp3, global, unregister_name, [test]),
- ?line
- ?UNTIL((Pid3 =:= global:whereis_name(test)) and
+ _ = rpc:call(Cp3, global, unregister_name, [test]),
+ ?UNTIL((Pid3 =:= global:whereis_name(test)) and
(Pid3 =:= rpc:call(Cp1, global, whereis_name, [test])) and
(Pid3 =:= rpc:call(Cp2, global, whereis_name, [test])) and
(undefined =:= rpc:call(Cp3, global, whereis_name, [test]))),
- ?line _ = global:unregister_name(test),
- ?line
- ?UNTIL((undefined =:= global:whereis_name(test)) and
+ _ = global:unregister_name(test),
+ ?UNTIL((undefined =:= global:whereis_name(test)) and
(undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and
(undefined =:= rpc:call(Cp2, global, whereis_name, [test])) and
(undefined =:= rpc:call(Cp3, global, whereis_name, [test]))),
@@ -608,277 +592,297 @@ names_hidden(Config) when is_list(Config) ->
exit_p(Pid3),
exit_p(HPid),
- ?line ?UNTIL(undefined =:= global:whereis_name(test)),
+ ?UNTIL(undefined =:= global:whereis_name(test)),
write_high_level_trace(Config),
- % stop the nodes, and make sure names are released.
+
+ %% stop the nodes, and make sure names are released.
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-locks(suite) -> [];
locks(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line {ok, Cp1} = start_node(cp1, Config),
- ?line {ok, Cp2} = start_node(cp2, Config),
- ?line {ok, Cp3} = start_node(cp3, Config),
-
- ?line wait_for_ready_net(Config),
-
- % start two procs
- ?line Pid = start_proc(),
- ?line Pid2 = rpc:call(Cp1, ?MODULE, start_proc, []),
- % set a lock, and make sure noone else can set the same lock
- ?line true = global:set_lock({test_lock, self()}, ?NODES, 1),
- ?line false = req(Pid, {set_lock, test_lock, self()}),
- ?line false = req(Pid2, {set_lock, test_lock, self()}),
- % delete, and let another proc set the lock
+ init_condition(Config),
+ {ok, Cp1} = start_node(cp1, Config),
+ {ok, Cp2} = start_node(cp2, Config),
+ {ok, Cp3} = start_node(cp3, Config),
+
+ wait_for_ready_net(Config),
+
+ %% start two procs
+ Pid = start_proc(),
+ Pid2 = rpc:call(Cp1, ?MODULE, start_proc, []),
+
+ %% set a lock, and make sure noone else can set the same lock
+ true = global:set_lock({test_lock, self()}, ?NODES, 1),
+ false = req(Pid, {set_lock, test_lock, self()}),
+ false = req(Pid2, {set_lock, test_lock, self()}),
+
+ %% delete, and let another proc set the lock
global:del_lock({test_lock, self()}),
- ?line true = req(Pid, {set_lock, test_lock, self()}),
- ?line false = req(Pid2, {set_lock, test_lock, self()}),
- ?line false = global:set_lock({test_lock, self()}, ?NODES,1),
- % kill lock-holding proc, make sure the lock is released
+ true = req(Pid, {set_lock, test_lock, self()}),
+ false = req(Pid2, {set_lock, test_lock, self()}),
+ false = global:set_lock({test_lock, self()}, ?NODES,1),
+
+ %% kill lock-holding proc, make sure the lock is released
exit_p(Pid),
?UNTIL(true =:= global:set_lock({test_lock, self()}, ?NODES,1)),
Pid2 ! {set_lock_loop, test_lock, self()},
- % make sure we don't have the msg
+
+ %% make sure we don't have the msg
receive
- {got_lock, Pid2} -> test_server:fail(got_lock)
+ {got_lock, Pid2} -> ct:fail(got_lock)
after
1000 -> ok
end,
global:del_lock({test_lock, self()}),
- % make sure pid2 got the lock
+
+ %% make sure pid2 got the lock
receive
{got_lock, Pid2} -> ok
after
- % 12000 >> 5000, which is the max time before a new retry for
- % set_lock
- 12000 -> test_server:fail(got_lock2)
+ %% 12000 >> 5000, which is the max time before a new retry for
+ %% set_lock
+ 12000 -> ct:fail(got_lock2)
end,
- % let proc set the same lock
- ?line true = req(Pid2, {set_lock, test_lock, self()}),
- % let proc set new lock
- ?line true = req(Pid2, {set_lock, test_lock2, self()}),
- ?line false = global:set_lock({test_lock, self()},?NODES,1),
- ?line false = global:set_lock({test_lock2, self()}, ?NODES,1),
+ %% let proc set the same lock
+ true = req(Pid2, {set_lock, test_lock, self()}),
+
+ %% let proc set new lock
+ true = req(Pid2, {set_lock, test_lock2, self()}),
+ false = global:set_lock({test_lock, self()},?NODES,1),
+ false = global:set_lock({test_lock2, self()}, ?NODES,1),
exit_p(Pid2),
-% erlang:display({locks1, ets:tab2list(global_locks)}),
?UNTIL(true =:= global:set_lock({test_lock, self()}, ?NODES, 1)),
?UNTIL(true =:= global:set_lock({test_lock2, self()}, ?NODES, 1)),
- ?line global:del_lock({test_lock, self()}),
- ?line global:del_lock({test_lock2, self()}),
-
- % let proc set two locks
- ?line Pid3 = rpc:call(Cp1, ?MODULE, start_proc, []),
- ?line true = req(Pid3, {set_lock, test_lock, self()}),
- ?line true = req(Pid3, {set_lock, test_lock2, self()}),
- % del one lock
- ?line Pid3 ! {del_lock, test_lock2},
- ?line test_server:sleep(100),
- % check that one lock is still set, but not the other
- ?line false = global:set_lock({test_lock, self()}, ?NODES, 1),
- ?line true = global:set_lock({test_lock2, self()}, ?NODES, 1),
- ?line global:del_lock({test_lock2, self()}),
- % kill lock-holder
+ global:del_lock({test_lock, self()}),
+ global:del_lock({test_lock2, self()}),
+
+ %% let proc set two locks
+ Pid3 = rpc:call(Cp1, ?MODULE, start_proc, []),
+ true = req(Pid3, {set_lock, test_lock, self()}),
+ true = req(Pid3, {set_lock, test_lock2, self()}),
+
+ %% del one lock
+ Pid3 ! {del_lock, test_lock2},
+ ct:sleep(100),
+
+ %% check that one lock is still set, but not the other
+ false = global:set_lock({test_lock, self()}, ?NODES, 1),
+ true = global:set_lock({test_lock2, self()}, ?NODES, 1),
+ global:del_lock({test_lock2, self()}),
+
+ %% kill lock-holder
exit_p(Pid3),
-% erlang:display({locks2, ets:tab2list(global_locks)}),
+
?UNTIL(true =:= global:set_lock({test_lock, self()}, ?NODES, 1)),
- ?line global:del_lock({test_lock, self()}),
+ global:del_lock({test_lock, self()}),
?UNTIL(true =:= global:set_lock({test_lock2, self()}, ?NODES, 1)),
- ?line global:del_lock({test_lock2, self()}),
-
- % start one proc on each node
- ?line Pid4 = start_proc(),
- ?line Pid5 = rpc:call(Cp1, ?MODULE, start_proc, []),
- ?line Pid6 = rpc:call(Cp2, ?MODULE, start_proc, []),
- ?line Pid7 = rpc:call(Cp3, ?MODULE, start_proc, []),
- % set lock on two nodes
- ?line true = req(Pid4, {set_lock, test_lock, self(), [node(), Cp1]}),
- ?line false = req(Pid5, {set_lock, test_lock, self(), [node(), Cp1]}),
- % set same lock on other two nodes
- ?line true = req(Pid6, {set_lock, test_lock, self(), [Cp2, Cp3]}),
- ?line false = req(Pid7, {set_lock, test_lock, self(), [Cp2, Cp3]}),
- % release lock
+ global:del_lock({test_lock2, self()}),
+
+ %% start one proc on each node
+ Pid4 = start_proc(),
+ Pid5 = rpc:call(Cp1, ?MODULE, start_proc, []),
+ Pid6 = rpc:call(Cp2, ?MODULE, start_proc, []),
+ Pid7 = rpc:call(Cp3, ?MODULE, start_proc, []),
+
+ %% set lock on two nodes
+ true = req(Pid4, {set_lock, test_lock, self(), [node(), Cp1]}),
+ false = req(Pid5, {set_lock, test_lock, self(), [node(), Cp1]}),
+
+ %% set same lock on other two nodes
+ true = req(Pid6, {set_lock, test_lock, self(), [Cp2, Cp3]}),
+ false = req(Pid7, {set_lock, test_lock, self(), [Cp2, Cp3]}),
+
+ %% release lock
Pid6 ! {del_lock, test_lock, [Cp2, Cp3]},
- % try to set lock on a node that already has the lock
- ?line false = req(Pid6, {set_lock, test_lock, self(), [Cp1, Cp2, Cp3]}),
- % set lock on a node
+ %% try to set lock on a node that already has the lock
+ false = req(Pid6, {set_lock, test_lock, self(), [Cp1, Cp2, Cp3]}),
+
+ %% set lock on a node
exit_p(Pid4),
?UNTIL(true =:= req(Pid5, {set_lock, test_lock, self(), [node(), Cp1]})),
- ?line Pid8 = start_proc(),
- ?line false = req(Pid8, {set_lock, test_lock, self()}),
+ Pid8 = start_proc(),
+ false = req(Pid8, {set_lock, test_lock, self()}),
write_high_level_trace(Config),
- % stop the nodes, and make sure locks are released.
+
+ %% stop the nodes, and make sure locks are released.
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
- ?line test_server:sleep(100),
- ?line true = req(Pid8, {set_lock, test_lock, self()}),
+ ct:sleep(100),
+ true = req(Pid8, {set_lock, test_lock, self()}),
exit_p(Pid8),
- ?line test_server:sleep(10),
+ ct:sleep(10),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-
-locks_hidden(suite) -> [];
-locks_hidden(doc) ->
- ["Tests that locks on a hidden node doesn't interere with locks on "
- "visible nodes."];
+
+%% Tests that locks on a hidden node doesn't interere with locks on
+%% visible nodes.
locks_hidden(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNodes = nodes(),
- ?line {ok, Cp1} = start_node(cp1, Config),
- ?line {ok, Cp2} = start_node(cp2, Config),
- ?line {ok, Cp3} = start_hidden_node(cp3, Config),
- ?line pong = rpc:call(Cp1, net_adm, ping, [Cp3]),
- ?line pong = rpc:call(Cp3, net_adm, ping, [Cp2]),
- ?line pong = rpc:call(Cp3, net_adm, ping, [node()]),
-
- ?line [] = [Cp1, Cp2 | OrigNodes] -- nodes(),
-
- % start two procs
- ?line Pid = start_proc(),
- ?line Pid2 = rpc:call(Cp1, ?MODULE, start_proc, []),
- ?line HPid = rpc:call(Cp3, ?MODULE, start_proc, []),
- % Make sure hidden node doesn't interfere with visible nodes lock
- ?line true = req(HPid, {set_lock, test_lock, self()}),
- ?line true = global:set_lock({test_lock, self()}, ?NODES, 1),
- ?line false = req(Pid, {set_lock, test_lock, self()}),
- ?line true = req(HPid, {del_lock_sync, test_lock, self()}),
- ?line false = req(Pid2, {set_lock, test_lock, self()}),
- % delete, and let another proc set the lock
+ init_condition(Config),
+ OrigNodes = nodes(),
+ {ok, Cp1} = start_node(cp1, Config),
+ {ok, Cp2} = start_node(cp2, Config),
+ {ok, Cp3} = start_hidden_node(cp3, Config),
+ pong = rpc:call(Cp1, net_adm, ping, [Cp3]),
+ pong = rpc:call(Cp3, net_adm, ping, [Cp2]),
+ pong = rpc:call(Cp3, net_adm, ping, [node()]),
+
+ [] = [Cp1, Cp2 | OrigNodes] -- nodes(),
+
+ %% start two procs
+ Pid = start_proc(),
+ Pid2 = rpc:call(Cp1, ?MODULE, start_proc, []),
+ HPid = rpc:call(Cp3, ?MODULE, start_proc, []),
+
+ %% Make sure hidden node doesn't interfere with visible nodes lock
+ true = req(HPid, {set_lock, test_lock, self()}),
+ true = global:set_lock({test_lock, self()}, ?NODES, 1),
+ false = req(Pid, {set_lock, test_lock, self()}),
+ true = req(HPid, {del_lock_sync, test_lock, self()}),
+ false = req(Pid2, {set_lock, test_lock, self()}),
+
+ %% delete, and let another proc set the lock
global:del_lock({test_lock, self()}),
- ?line true = req(Pid, {set_lock, test_lock, self()}),
- ?line false = req(Pid2, {set_lock, test_lock, self()}),
- ?line false = global:set_lock({test_lock, self()}, ?NODES,1),
- % kill lock-holding proc, make sure the lock is released
+ true = req(Pid, {set_lock, test_lock, self()}),
+ false = req(Pid2, {set_lock, test_lock, self()}),
+ false = global:set_lock({test_lock, self()}, ?NODES,1),
+
+ %% kill lock-holding proc, make sure the lock is released
exit_p(Pid),
?UNTIL(true =:= global:set_lock({test_lock, self()}, ?NODES, 1)),
?UNTIL(true =:= req(HPid, {set_lock, test_lock, self()})),
Pid2 ! {set_lock_loop, test_lock, self()},
- % make sure we don't have the msg
+
+ %% make sure we don't have the msg
receive
- {got_lock, Pid2} -> test_server:fail(got_lock)
+ {got_lock, Pid2} -> ct:fail(got_lock)
after
1000 -> ok
end,
global:del_lock({test_lock, self()}),
- % make sure pid2 got the lock
+
+ %% make sure pid2 got the lock
receive
{got_lock, Pid2} -> ok
after
- % 12000 >> 5000, which is the max time before a new retry for
- % set_lock
- 12000 -> test_server:fail(got_lock2)
+ %% 12000 >> 5000, which is the max time before a new retry for
+ %% set_lock
+ 12000 -> ct:fail(got_lock2)
end,
- ?line true = req(HPid, {del_lock_sync, test_lock, self()}),
-
- % let proc set the same lock
- ?line true = req(Pid2, {set_lock, test_lock, self()}),
- % let proc set new lock
- ?line true = req(Pid2, {set_lock, test_lock2, self()}),
- ?line true = req(HPid, {set_lock, test_lock, self()}),
- ?line true = req(HPid, {set_lock, test_lock2, self()}),
+ true = req(HPid, {del_lock_sync, test_lock, self()}),
+
+ %% let proc set the same lock
+ true = req(Pid2, {set_lock, test_lock, self()}),
+
+ %% let proc set new lock
+ true = req(Pid2, {set_lock, test_lock2, self()}),
+ true = req(HPid, {set_lock, test_lock, self()}),
+ true = req(HPid, {set_lock, test_lock2, self()}),
exit_p(HPid),
- ?line false = global:set_lock({test_lock, self()},?NODES,1),
- ?line false = global:set_lock({test_lock2, self()}, ?NODES,1),
+ false = global:set_lock({test_lock, self()},?NODES,1),
+ false = global:set_lock({test_lock2, self()}, ?NODES,1),
+
exit_p(Pid2),
-% erlang:display({locks1, ets:tab2list(global_locks)}),
?UNTIL(true =:= global:set_lock({test_lock, self()}, ?NODES, 1)),
?UNTIL(true =:= global:set_lock({test_lock2, self()}, ?NODES, 1)),
- ?line global:del_lock({test_lock, self()}),
- ?line global:del_lock({test_lock2, self()}),
+ global:del_lock({test_lock, self()}),
+ global:del_lock({test_lock2, self()}),
write_high_level_trace(Config),
- % stop the nodes, and make sure locks are released.
+
+ %% stop the nodes, and make sure locks are released.
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-
-bad_input(suite) -> [];
+
bad_input(Config) when is_list(Config) ->
Timeout = 15,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
+ init_condition(Config),
Pid = whereis(global_name_server),
- ?line {'EXIT', _} = (catch global:set_lock(bad_id)),
- ?line {'EXIT', _} = (catch global:set_lock({id, self()}, bad_nodes)),
- ?line {'EXIT', _} = (catch global:del_lock(bad_id)),
- ?line {'EXIT', _} = (catch global:del_lock({id, self()}, bad_nodes)),
- ?line {'EXIT', _} = (catch global:register_name(name, bad_pid)),
- ?line {'EXIT', _} = (catch global:reregister_name(name, bad_pid)),
- ?line {'EXIT', _} = (catch global:trans(bad_id, {m,f})),
- ?line {'EXIT', _} = (catch global:trans({id, self()}, {m,f}, [node()], -1)),
- ?line Pid = whereis(global_name_server),
- ?line init_condition(Config),
+ {'EXIT', _} = (catch global:set_lock(bad_id)),
+ {'EXIT', _} = (catch global:set_lock({id, self()}, bad_nodes)),
+ {'EXIT', _} = (catch global:del_lock(bad_id)),
+ {'EXIT', _} = (catch global:del_lock({id, self()}, bad_nodes)),
+ {'EXIT', _} = (catch global:register_name(name, bad_pid)),
+ {'EXIT', _} = (catch global:reregister_name(name, bad_pid)),
+ {'EXIT', _} = (catch global:trans(bad_id, {m,f})),
+ {'EXIT', _} = (catch global:trans({id, self()}, {m,f}, [node()], -1)),
+ Pid = whereis(global_name_server),
+ init_condition(Config),
ok.
-names_and_locks(suite) -> [];
names_and_locks(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
-
- ?line {ok, Cp1} = start_node(cp1, Config),
- ?line {ok, Cp2} = start_node(cp2, Config),
- ?line {ok, Cp3} = start_node(cp3, Config),
-
- % start one proc on each node
- ?line PidTS = start_proc(),
- ?line Pid1 = rpc:call(Cp1, ?MODULE, start_proc, []),
- ?line Pid2 = rpc:call(Cp2, ?MODULE, start_proc, []),
- ?line Pid3 = rpc:call(Cp3, ?MODULE, start_proc, []),
- % register some of them
- ?line yes = global:register_name(test1, Pid1),
- ?line yes = global:register_name(test2, Pid2),
- ?line yes = global:register_name(test3, Pid3),
- ?line no = global:register_name(test3, PidTS),
- ?line yes = global:register_name(test4, PidTS),
-
- % set lock on two nodes
- ?line true = req(PidTS, {set_lock, test_lock, self(), [node(), Cp1]}),
- ?line false = req(Pid1, {set_lock, test_lock, self(), [node(), Cp1]}),
- % set same lock on other two nodes
- ?line true = req(Pid2, {set_lock, test_lock, self(), [Cp2, Cp3]}),
- ?line false = req(Pid3, {set_lock, test_lock, self(), [Cp2, Cp3]}),
- % release lock
+ init_condition(Config),
+ OrigNames = global:registered_names(),
+
+ {ok, Cp1} = start_node(cp1, Config),
+ {ok, Cp2} = start_node(cp2, Config),
+ {ok, Cp3} = start_node(cp3, Config),
+
+ %% start one proc on each node
+ PidTS = start_proc(),
+ Pid1 = rpc:call(Cp1, ?MODULE, start_proc, []),
+ Pid2 = rpc:call(Cp2, ?MODULE, start_proc, []),
+ Pid3 = rpc:call(Cp3, ?MODULE, start_proc, []),
+
+ %% register some of them
+ yes = global:register_name(test1, Pid1),
+ yes = global:register_name(test2, Pid2),
+ yes = global:register_name(test3, Pid3),
+ no = global:register_name(test3, PidTS),
+ yes = global:register_name(test4, PidTS),
+
+ %% set lock on two nodes
+ true = req(PidTS, {set_lock, test_lock, self(), [node(), Cp1]}),
+ false = req(Pid1, {set_lock, test_lock, self(), [node(), Cp1]}),
+
+ %% set same lock on other two nodes
+ true = req(Pid2, {set_lock, test_lock, self(), [Cp2, Cp3]}),
+ false = req(Pid3, {set_lock, test_lock, self(), [Cp2, Cp3]}),
+
+ %% release lock
Pid2 ! {del_lock, test_lock, [Cp2, Cp3]},
- ?line test_server:sleep(100),
- % try to set lock on a node that already has the lock
- ?line false = req(Pid2, {set_lock, test_lock, self(), [Cp1, Cp2, Cp3]}),
- % set two locks
- ?line true = req(Pid2, {set_lock, test_lock, self(), [Cp2, Cp3]}),
- ?line true = req(Pid2, {set_lock, test_lock2, self(), [Cp2, Cp3]}),
-
- % kill some processes, make sure all locks/names are released
+ ct:sleep(100),
+
+ %% try to set lock on a node that already has the lock
+ false = req(Pid2, {set_lock, test_lock, self(), [Cp1, Cp2, Cp3]}),
+
+ %% set two locks
+ true = req(Pid2, {set_lock, test_lock, self(), [Cp2, Cp3]}),
+ true = req(Pid2, {set_lock, test_lock2, self(), [Cp2, Cp3]}),
+
+ %% kill some processes, make sure all locks/names are released
exit_p(PidTS),
- ?line ?UNTIL(undefined =:= global:whereis_name(test4)),
- ?line true = global:set_lock({test_lock, self()}, [node(), Cp1], 1),
+ ?UNTIL(undefined =:= global:whereis_name(test4)),
+ true = global:set_lock({test_lock, self()}, [node(), Cp1], 1),
global:del_lock({test_lock, self()}, [node(), Cp1]),
exit_p(Pid2),
- ?line
- ?UNTIL((undefined =:= global:whereis_name(test2)) and
+ ?UNTIL((undefined =:= global:whereis_name(test2)) and
(true =:= global:set_lock({test_lock, self()}, [Cp2, Cp3], 1)) and
(true =:= global:set_lock({test_lock2, self()}, [Cp2, Cp3], 1))),
@@ -888,117 +892,113 @@ names_and_locks(Config) when is_list(Config) ->
exit_p(Pid1),
exit_p(Pid3),
- ?line ?UNTIL(OrigNames =:= global:registered_names()),
+ ?UNTIL(OrigNames =:= global:registered_names()),
write_high_level_trace(Config),
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-
-lock_die(suite) -> [];
-lock_die(doc) ->
- ["OTP-6341. Remove locks using monitors."];
+
+%% OTP-6341. Remove locks using monitors.
lock_die(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
- ?line {ok, Cp1} = start_node(cp1, Config),
- ?line {ok, Cp2} = start_node(cp2, Config),
+ {ok, Cp1} = start_node(cp1, Config),
+ {ok, Cp2} = start_node(cp2, Config),
%% First test.
LockId = {id, self()},
- ?line Pid2 = start_proc(),
- ?line true = req(Pid2, {set_lock2, LockId, self()}),
+ Pid2 = start_proc(),
+ true = req(Pid2, {set_lock2, LockId, self()}),
- ?line true = global:set_lock(LockId, [Cp1]),
+ true = global:set_lock(LockId, [Cp1]),
%% Id is locked on Cp1 and Cp2 (by Pid2) but not by self():
%% (there is no mon. ref)
- ?line _ = global:del_lock(LockId, [node(), Cp1, Cp2]),
+ _ = global:del_lock(LockId, [node(), Cp1, Cp2]),
+
+ exit_p(Pid2),
- ?line exit_p(Pid2),
-
%% Second test.
- ?line Pid3 = start_proc(),
- ?line true = req(Pid3, {set_lock, id, self(), [Cp1]}),
+ Pid3 = start_proc(),
+ true = req(Pid3, {set_lock, id, self(), [Cp1]}),
%% The lock is removed from Cp1 thanks to monitors.
- ?line exit_p(Pid3),
-
- ?line true = global:set_lock(LockId, [node(), Cp1]),
- ?line _ = global:del_lock(LockId, [node(), Cp1]),
+ exit_p(Pid3),
+
+ true = global:set_lock(LockId, [node(), Cp1]),
+ _ = global:del_lock(LockId, [node(), Cp1]),
- ?line ?UNTIL(OrigNames =:= global:registered_names()),
+ ?UNTIL(OrigNames =:= global:registered_names()),
write_high_level_trace(Config),
stop_node(Cp1),
stop_node(Cp2),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-name_die(suite) -> [];
-name_die(doc) ->
- ["OTP-6341. Remove names using monitors."];
+%% OTP-6341. Remove names using monitors.
name_die(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
- ?line [Cp1] = Cps = start_nodes([z], peer, Config), % z > test_server
+ init_condition(Config),
+ OrigNames = global:registered_names(),
+ [Cp1] = Cps = start_nodes([z], peer, Config), % z > test_server
Nodes = lists:sort([node() | Cps]),
- ?line wait_for_ready_net(Config),
-
+ wait_for_ready_net(Config),
+
Name = name_die,
- ?line Pid = rpc:call(Cp1, ?MODULE, start_proc, []),
+ Pid = rpc:call(Cp1, ?MODULE, start_proc, []),
%% Test 1. No resolver is called if the same pid is registered on
%% both partitions.
T1 = node(),
Part1 = [T1],
Part2 = [Cp1],
- ?line rpc_cast(Cp1,
- ?MODULE, part_2_2, [Config,
- Part1,
- Part2,
- []]),
- ?line ?UNTIL(is_ready_partition(Config)),
- ?line ?UNTIL(undefined =:= global:whereis_name(Name)),
- ?line yes = global:register_name(Name, Pid),
-
- ?line pong = net_adm:ping(Cp1),
- ?line wait_for_ready_net(Nodes, Config),
- ?line assert_pid(global:whereis_name(Name)),
+ rpc_cast(Cp1,
+ ?MODULE, part_2_2, [Config,
+ Part1,
+ Part2,
+ []]),
+ ?UNTIL(is_ready_partition(Config)),
+ ?UNTIL(undefined =:= global:whereis_name(Name)),
+ yes = global:register_name(Name, Pid),
+
+ pong = net_adm:ping(Cp1),
+ wait_for_ready_net(Nodes, Config),
+ assert_pid(global:whereis_name(Name)),
exit_p(Pid),
- ?line ?UNTIL(OrigNames =:= global:registered_names()),
+ ?UNTIL(OrigNames =:= global:registered_names()),
%% Test 2. Register a name running outside the current partition.
%% Killing the pid will not remove the name from the current
%% partition, unless monitors are used.
- ?line Pid2 = rpc:call(Cp1, ?MODULE, start_proc, []),
- Dir = ?config(priv_dir, Config),
+ Pid2 = rpc:call(Cp1, ?MODULE, start_proc, []),
+ Dir = proplists:get_value(priv_dir, Config),
KillFile = filename:join([Dir, "kill.txt"]),
file:delete(KillFile),
- ?line erlang:spawn(Cp1, fun() -> kill_pid(Pid2, KillFile, Config) end),
- ?line rpc_cast(Cp1,
- ?MODULE, part_2_2, [Config,
- Part1,
- Part2,
- []]),
- ?line ?UNTIL(is_ready_partition(Config)),
- ?line ?UNTIL(undefined =:= global:whereis_name(Name)),
- ?line yes = global:register_name(Name, Pid2),
- ?line touch(KillFile, "kill"),
- ?line file_contents(KillFile, "done", Config),
+ erlang:spawn(Cp1, fun() -> kill_pid(Pid2, KillFile, Config) end),
+ rpc_cast(Cp1,
+ ?MODULE, part_2_2, [Config,
+ Part1,
+ Part2,
+ []]),
+ ?UNTIL(is_ready_partition(Config)),
+ ?UNTIL(undefined =:= global:whereis_name(Name)),
+ yes = global:register_name(Name, Pid2),
+ touch(KillFile, "kill"),
+ file_contents(KillFile, "done", Config),
file:delete(KillFile),
- ?line ?UNTIL(OrigNames =:= global:registered_names()),
+ ?UNTIL(OrigNames =:= global:registered_names()),
write_high_level_trace(Config),
stop_nodes(Cps),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
kill_pid(Pid, File, Config) ->
@@ -1006,186 +1006,178 @@ kill_pid(Pid, File, Config) ->
exit_p(Pid),
touch(File, "done").
-basic_partition(suite) -> [];
-basic_partition(doc) ->
- ["Tests that two partitioned networks exchange correct info."];
+%% Tests that two partitioned networks exchange correct info.
basic_partition(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
-
- ?line [Cp1, Cp2, Cp3] = start_nodes([cp1, cp2, cp3], peer, Config),
- ?line [Cp1, Cp2, Cp3] = lists:sort(nodes()),
-
- ?line wait_for_ready_net(Config),
-
- % make cp2 and cp3 connected, partitioned from us and cp1
- ?line rpc_cast(Cp2, ?MODULE, part1, [Config, node(), Cp1, Cp3]),
- ?line ?UNTIL(is_ready_partition(Config)),
-
- % start different processes in both partitions
- ?line {Pid, yes} = start_proc(test),
-
- % connect to other partition
- ?line pong = net_adm:ping(Cp2),
- ?line pong = net_adm:ping(Cp3),
- ?line [Cp1, Cp2, Cp3] = lists:sort(nodes()),
-
- % check names
- ?line ?UNTIL(Pid =:= rpc:call(Cp2, global, whereis_name, [test])),
- ?line ?UNTIL(undefined =/= global:whereis_name(test2)),
- ?line Pid2 = global:whereis_name(test2),
- ?line Pid2 = rpc:call(Cp2, global, whereis_name, [test2]),
- ?line assert_pid(Pid2),
- ?line Pid3 = global:whereis_name(test4),
- ?line ?UNTIL(Pid3 =:= rpc:call(Cp1, global, whereis_name, [test4])),
- ?line assert_pid(Pid3),
-
- % kill all procs
- ?line Pid3 = global:send(test4, die),
- % sleep to let the proc die
+ init_condition(Config),
+ OrigNames = global:registered_names(),
+
+ [Cp1, Cp2, Cp3] = start_nodes([cp1, cp2, cp3], peer, Config),
+ [Cp1, Cp2, Cp3] = lists:sort(nodes()),
+
+ wait_for_ready_net(Config),
+
+ %% make cp2 and cp3 connected, partitioned from us and cp1
+ rpc_cast(Cp2, ?MODULE, part1, [Config, node(), Cp1, Cp3]),
+ ?UNTIL(is_ready_partition(Config)),
+
+ %% start different processes in both partitions
+ {Pid, yes} = start_proc(test),
+
+ %% connect to other partition
+ pong = net_adm:ping(Cp2),
+ pong = net_adm:ping(Cp3),
+ [Cp1, Cp2, Cp3] = lists:sort(nodes()),
+
+ %% check names
+ ?UNTIL(Pid =:= rpc:call(Cp2, global, whereis_name, [test])),
+ ?UNTIL(undefined =/= global:whereis_name(test2)),
+ Pid2 = global:whereis_name(test2),
+ Pid2 = rpc:call(Cp2, global, whereis_name, [test2]),
+ assert_pid(Pid2),
+ Pid3 = global:whereis_name(test4),
+ ?UNTIL(Pid3 =:= rpc:call(Cp1, global, whereis_name, [test4])),
+ assert_pid(Pid3),
+
+ %% kill all procs
+ Pid3 = global:send(test4, die),
+ %% sleep to let the proc die
wait_for_exit(Pid3),
- ?line ?UNTIL(undefined =:= global:whereis_name(test4)),
-
+ ?UNTIL(undefined =:= global:whereis_name(test4)),
+
exit_p(Pid),
exit_p(Pid2),
- ?line ?UNTIL(OrigNames =:= global:registered_names()),
+ ?UNTIL(OrigNames =:= global:registered_names()),
write_high_level_trace(Config),
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-basic_name_partition(suite) ->
- [];
-basic_name_partition(doc) ->
- ["Creates two partitions with two nodes in each partition.",
- "Tests that names are exchanged correctly, and that EXITs",
- "during connect phase are handled correctly."];
+%% Creates two partitions with two nodes in each partition.
+%% Tests that names are exchanged correctly, and that EXITs
+%% during connect phase are handled correctly.
basic_name_partition(Config) when is_list(Config) ->
Timeout = 60,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
- ?line [Cp1, Cp2, Cp3] = start_nodes([cp1, cp2, cp3], peer, Config),
- ?line [Cp1, Cp2, Cp3] = lists:sort(nodes()),
+ [Cp1, Cp2, Cp3] = start_nodes([cp1, cp2, cp3], peer, Config),
+ [Cp1, Cp2, Cp3] = lists:sort(nodes()),
Nodes = ?NODES,
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
- % There used to be more than one name registered for some
- % processes. That was a mistake; there is no support for more than
- % one name per process, and the manual is quite clear about that
- % ("equivalent to the register/2 and whereis/1 BIFs"). The
- % resolver procedure did not take care of such "duplicated" names,
- % which caused this testcase to fail every now and then.
+ %% There used to be more than one name registered for some
+ %% processes. That was a mistake; there is no support for more than
+ %% one name per process, and the manual is quite clear about that
+ %% ("equivalent to the register/2 and whereis/1 BIFs"). The
+ %% resolver procedure did not take care of such "duplicated" names,
+ %% which caused this testcase to fail every now and then.
- % make cp2 and cp3 connected, partitioned from us and cp1
- % us: register name03
- % cp1: register name12
- % cp2: register name12
- % cp3: register name03
-
- ?line rpc_cast(Cp2, ?MODULE, part1_5, [Config, node(), Cp1, Cp3]),
- ?line ?UNTIL(is_ready_partition(Config)),
-
- % start different processes in both partitions
- ?line {_, yes} = start_proc_basic(name03),
- ?line {_, yes} = rpc:call(Cp1, ?MODULE, start_proc_basic, [name12]),
- test_server:sleep(1000),
+ %% make cp2 and cp3 connected, partitioned from us and cp1
+ %% us: register name03
+ %% cp1: register name12
+ %% cp2: register name12
+ %% cp3: register name03
- % connect to other partition
- ?line pong = net_adm:ping(Cp3),
-
- ?line ?UNTIL([Cp1, Cp2, Cp3] =:= lists:sort(nodes())),
- ?line wait_for_ready_net(Config),
- % check names
- ?line Pid03 = global:whereis_name(name03),
- ?line assert_pid(Pid03),
- ?line true = lists:member(node(Pid03), [node(), Cp3]),
- ?line check_everywhere(Nodes, name03, Config),
-
- ?line Pid12 = global:whereis_name(name12),
- ?line assert_pid(Pid12),
- ?line true = lists:member(node(Pid12), [Cp1, Cp2]),
- ?line check_everywhere(Nodes, name12, Config),
-
- % kill all procs
- ?line Pid12 = global:send(name12, die),
- ?line Pid03 = global:send(name03, die),
- % sleep to let the procs die
+ rpc_cast(Cp2, ?MODULE, part1_5, [Config, node(), Cp1, Cp3]),
+ ?UNTIL(is_ready_partition(Config)),
+
+ %% start different processes in both partitions
+ {_, yes} = start_proc_basic(name03),
+ {_, yes} = rpc:call(Cp1, ?MODULE, start_proc_basic, [name12]),
+ ct:sleep(1000),
+
+ %% connect to other partition
+ pong = net_adm:ping(Cp3),
+
+ ?UNTIL([Cp1, Cp2, Cp3] =:= lists:sort(nodes())),
+ wait_for_ready_net(Config),
+
+ %% check names
+ Pid03 = global:whereis_name(name03),
+ assert_pid(Pid03),
+ true = lists:member(node(Pid03), [node(), Cp3]),
+ check_everywhere(Nodes, name03, Config),
+
+ Pid12 = global:whereis_name(name12),
+ assert_pid(Pid12),
+ true = lists:member(node(Pid12), [Cp1, Cp2]),
+ check_everywhere(Nodes, name12, Config),
+
+ %% kill all procs
+ Pid12 = global:send(name12, die),
+ Pid03 = global:send(name03, die),
+
+ %% sleep to let the procs die
wait_for_exit(Pid12),
wait_for_exit(Pid03),
- ?line
?UNTIL(begin
Names = [name03, name12],
lists:duplicate(length(Names), undefined)
=:= [global:whereis_name(Name) || Name <- Names]
end),
-
- ?line ?UNTIL(OrigNames =:= global:registered_names()),
+
+ ?UNTIL(OrigNames =:= global:registered_names()),
write_high_level_trace(Config),
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-%Peer nodes cp0 - cp6 are started. Break apart the connections from
-%cp3-cp6 to cp0-cp2 and test_server so we get two partitions.
-%In the cp3-cp6 partition, start one process on each node and register
-%using both erlang:register, and global:register (test1 on cp3, test2 on
-%cp4, test3 on cp5, test4 on cp6), using different resolution functions:
-%default for test1, notify_all_name for test2, random_notify_name for test3
-%and one for test4 that sends a message to test_server and keeps the
-%process which is greater in the standard ordering. In the other partition,
-%do the same (test1 on test_server, test2 on cp0, test3 on cp1, test4 on cp2).
-%Sleep a little, then from test_server, connect to cp3-cp6 in order.
-%Check that the values for the registered names are the expected ones, and
-%that the messages from test4 arrive.
-
-advanced_partition(suite) ->
- [];
-advanced_partition(doc) ->
- ["Test that names are resolved correctly when two",
- "partitioned networks connect."];
+%% Peer nodes cp0 - cp6 are started. Break apart the connections from
+%% cp3-cp6 to cp0-cp2 and test_server so we get two partitions.
+%% In the cp3-cp6 partition, start one process on each node and register
+%% using both erlang:register, and global:register (test1 on cp3, test2 on
+%% cp4, test3 on cp5, test4 on cp6), using different resolution functions:
+%% default for test1, notify_all_name for test2, random_notify_name for test3
+%% and one for test4 that sends a message to test_server and keeps the
+%% process which is greater in the standard ordering. In the other partition,
+%% do the same (test1 on test_server, test2 on cp0, test3 on cp1, test4 on cp2).
+%% Sleep a little, then from test_server, connect to cp3-cp6 in order.
+%% Check that the values for the registered names are the expected ones, and
+%% that the messages from test4 arrive.
+
+%% Test that names are resolved correctly when two
+%% partitioned networks connect.
advanced_partition(Config) when is_list(Config) ->
Timeout = 60,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
- ?line [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6]
+ [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6]
= start_nodes([cp0, cp1, cp2, cp3, cp4, cp5, cp6], peer, Config),
Nodes = lists:sort([node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6]),
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
- % make cp3-cp6 connected, partitioned from us and cp0-cp2
- ?line rpc_cast(Cp3, ?MODULE, part2,
- [Config, self(), node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5,Cp6]),
- ?line ?UNTIL(is_ready_partition(Config)),
-
- % start different processes in this partition
- ?line start_procs(self(), Cp0, Cp1, Cp2, Config),
-
- % connect to other partition
- ?line pong = net_adm:ping(Cp3),
- ?line pong = net_adm:ping(Cp4),
- ?line pong = net_adm:ping(Cp5),
- ?line pong = net_adm:ping(Cp6),
-
- ?line wait_for_ready_net(Config),
+ %% make cp3-cp6 connected, partitioned from us and cp0-cp2
+ rpc_cast(Cp3, ?MODULE, part2,
+ [Config, self(), node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5,Cp6]),
+ ?UNTIL(is_ready_partition(Config)),
+
+ %% start different processes in this partition
+ start_procs(self(), Cp0, Cp1, Cp2, Config),
+
+ %% connect to other partition
+ pong = net_adm:ping(Cp3),
+ pong = net_adm:ping(Cp4),
+ pong = net_adm:ping(Cp5),
+ pong = net_adm:ping(Cp6),
+
+ wait_for_ready_net(Config),
- ?line
?UNTIL(lists:member(undefined,
[rpc:call(Cp3, erlang, whereis, [test1]),
rpc:call(node(), erlang, whereis, [test1])])),
@@ -1200,43 +1192,42 @@ advanced_partition(Config) when is_list(Config) ->
Mt3 = rpc:call(Cp1, erlang, whereis, [test3]),
_Mt4 = rpc:call(Cp2, erlang, whereis, [test4]),
- % check names
- ?line Pid1 = global:whereis_name(test1),
- ?line Pid1 = rpc:call(Cp3, global, whereis_name, [test1]),
- ?line assert_pid(Pid1),
- ?line true = lists:member(Pid1, [Nt1, Mt1]),
- ?line true = lists:member(undefined, [Nt1, Mt1]),
- ?line check_everywhere(Nodes, test1, Config),
-
- ?line undefined = global:whereis_name(test2),
- ?line undefined = rpc:call(Cp3, global, whereis_name, [test2]),
- ?line yes = sreq(Nt2, {got_notify, self()}),
- ?line yes = sreq(Mt2, {got_notify, self()}),
- ?line check_everywhere(Nodes, test2, Config),
-
- ?line Pid3 = global:whereis_name(test3),
- ?line Pid3 = rpc:call(Cp3, global, whereis_name, [test3]),
- ?line assert_pid(Pid3),
- ?line true = lists:member(Pid3, [Nt3, Mt3]),
- ?line no = sreq(Pid3, {got_notify, self()}),
- ?line yes = sreq(other(Pid3, [Nt2, Nt3]), {got_notify, self()}),
- ?line check_everywhere(Nodes, test3, Config),
-
- ?line Pid4 = global:whereis_name(test4),
- ?line Pid4 = rpc:call(Cp3, global, whereis_name, [test4]),
- ?line assert_pid(Pid4),
-% ?line true = lists:member(Pid4, [Nt4, Mt4]),
- ?line Pid4 = Nt4,
- ?line check_everywhere(Nodes, test4, Config),
-
- ?line 1 = collect_resolves(),
-
- ?line Pid1 = global:send(test1, die),
+ %% check names
+ Pid1 = global:whereis_name(test1),
+ Pid1 = rpc:call(Cp3, global, whereis_name, [test1]),
+ assert_pid(Pid1),
+ true = lists:member(Pid1, [Nt1, Mt1]),
+ true = lists:member(undefined, [Nt1, Mt1]),
+ check_everywhere(Nodes, test1, Config),
+
+ undefined = global:whereis_name(test2),
+ undefined = rpc:call(Cp3, global, whereis_name, [test2]),
+ yes = sreq(Nt2, {got_notify, self()}),
+ yes = sreq(Mt2, {got_notify, self()}),
+ check_everywhere(Nodes, test2, Config),
+
+ Pid3 = global:whereis_name(test3),
+ Pid3 = rpc:call(Cp3, global, whereis_name, [test3]),
+ assert_pid(Pid3),
+ true = lists:member(Pid3, [Nt3, Mt3]),
+ no = sreq(Pid3, {got_notify, self()}),
+ yes = sreq(other(Pid3, [Nt2, Nt3]), {got_notify, self()}),
+ check_everywhere(Nodes, test3, Config),
+
+ Pid4 = global:whereis_name(test4),
+ Pid4 = rpc:call(Cp3, global, whereis_name, [test4]),
+ assert_pid(Pid4),
+ Pid4 = Nt4,
+ check_everywhere(Nodes, test4, Config),
+
+ 1 = collect_resolves(),
+
+ Pid1 = global:send(test1, die),
exit_p(Pid3),
exit_p(Pid4),
wait_for_exit(Pid1),
wait_for_exit(Pid3),
- ?line ?UNTIL(OrigNames =:= global:registered_names()),
+ ?UNTIL(OrigNames =:= global:registered_names()),
write_high_level_trace(Config),
stop_node(Cp0),
@@ -1246,93 +1237,90 @@ advanced_partition(Config) when is_list(Config) ->
stop_node(Cp4),
stop_node(Cp5),
stop_node(Cp6),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-
-%Peer nodes cp0 - cp6 are started, and partitioned just like in
-%advanced_partition. Start cp8, only connected to test_server. Let cp6
-%break apart from the rest, and 12 s later, ping cp0 and cp3, and
-%register the name test5. After the same 12 s, let cp5 halt.
-%Wait for the death of cp5. Ping cp3 (at the same time as cp6 does).
-%Take down cp2. Start cp7, restart cp2. Ping cp4, cp6 and cp8.
-%Now, expect all nodes to be connected and have the same picture of all
-%registered names.
-
-stress_partition(suite) ->
- [];
-stress_partition(doc) ->
- ["Stress global, make a partitioned net, make some nodes",
- "go up/down a bit."];
+
+%% Peer nodes cp0 - cp6 are started, and partitioned just like in
+%% advanced_partition. Start cp8, only connected to test_server. Let cp6
+%% break apart from the rest, and 12 s later, ping cp0 and cp3, and
+%% register the name test5. After the same 12 s, let cp5 halt.
+%% Wait for the death of cp5. Ping cp3 (at the same time as cp6 does).
+%% Take down cp2. Start cp7, restart cp2. Ping cp4, cp6 and cp8.
+%% Now, expect all nodes to be connected and have the same picture of all
+%% registered names.
+
+%% Stress global, make a partitioned net, make some nodes
+%% go up/down a bit.
stress_partition(Config) when is_list(Config) ->
Timeout = 90,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
- ?line [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6]
+ [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6]
= start_nodes([cp0, cp1, cp2, cp3, cp4, cp5, cp6], peer, Config),
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
- % make cp3-cp5 connected, partitioned from us and cp0-cp2
- % cp6 is alone (single node). cp6 pings cp0 and cp3 in 12 secs...
- ?line rpc_cast(Cp3, ?MODULE, part3,
- [Config, self(), node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5,Cp6]),
- ?line ?UNTIL(is_ready_partition(Config)),
-
- % start different processes in this partition
- ?line start_procs(self(), Cp0, Cp1, Cp2, Config),
+ %% make cp3-cp5 connected, partitioned from us and cp0-cp2
+ %% cp6 is alone (single node). cp6 pings cp0 and cp3 in 12 secs...
+ rpc_cast(Cp3, ?MODULE, part3,
+ [Config, self(), node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5,Cp6]),
+ ?UNTIL(is_ready_partition(Config)),
+
+ %% start different processes in this partition
+ start_procs(self(), Cp0, Cp1, Cp2, Config),
+
+ {ok, Cp8} = start_peer_node(cp8, Config),
- ?line {ok, Cp8} = start_peer_node(cp8, Config),
-
monitor_node(Cp5, true),
receive
{nodedown, Cp5} -> ok
after
- 20000 -> test_server:fail({no_nodedown, Cp5})
+ 20000 -> ct:fail({no_nodedown, Cp5})
end,
monitor_node(Cp5, false),
- % Ok, now cp6 pings us, and cp5 will go down.
-
- % connect to other partition
- ?line pong = net_adm:ping(Cp3),
- ?line rpc_cast(Cp2, ?MODULE, crash, [0]),
-
- % Start new nodes
- ?line {ok, Cp7} = start_peer_node(cp7, Config),
- ?line {ok, Cp2_2} = start_peer_node(cp2, Config),
+ %% Ok, now cp6 pings us, and cp5 will go down.
+
+ %% connect to other partition
+ pong = net_adm:ping(Cp3),
+ rpc_cast(Cp2, ?MODULE, crash, [0]),
+
+ %% Start new nodes
+ {ok, Cp7} = start_peer_node(cp7, Config),
+ {ok, Cp2_2} = start_peer_node(cp2, Config),
Nodes = lists:sort([node(), Cp0, Cp1, Cp2_2, Cp3, Cp4, Cp6, Cp7, Cp8]),
put(?nodes_tag, Nodes),
- ?line pong = net_adm:ping(Cp4),
- ?line pong = net_adm:ping(Cp6),
- ?line pong = net_adm:ping(Cp8),
+ pong = net_adm:ping(Cp4),
+ pong = net_adm:ping(Cp6),
+ pong = net_adm:ping(Cp8),
- ?line wait_for_ready_net(Nodes, Config),
+ wait_for_ready_net(Nodes, Config),
- % Make sure that all nodes have the same picture of all names
- ?line check_everywhere(Nodes, test1, Config),
- ?line assert_pid(global:whereis_name(test1)),
-
- ?line check_everywhere(Nodes, test2, Config),
- ?line undefined = global:whereis_name(test2),
+ %% Make sure that all nodes have the same picture of all names
+ check_everywhere(Nodes, test1, Config),
+ assert_pid(global:whereis_name(test1)),
- ?line check_everywhere(Nodes, test3, Config),
- ?line assert_pid(global:whereis_name(test3)),
+ check_everywhere(Nodes, test2, Config),
+ undefined = global:whereis_name(test2),
- ?line check_everywhere(Nodes, test4, Config),
- ?line assert_pid(global:whereis_name(test4)),
+ check_everywhere(Nodes, test3, Config),
+ assert_pid(global:whereis_name(test3)),
- ?line check_everywhere(Nodes, test5, Config),
- ?line ?UNTIL(undefined =:= global:whereis_name(test5)),
-
- ?line assert_pid(global:send(test1, die)),
- ?line assert_pid(global:send(test3, die)),
- ?line assert_pid(global:send(test4, die)),
+ check_everywhere(Nodes, test4, Config),
+ assert_pid(global:whereis_name(test4)),
+
+ check_everywhere(Nodes, test5, Config),
+ ?UNTIL(undefined =:= global:whereis_name(test5)),
+
+ assert_pid(global:send(test1, die)),
+ assert_pid(global:send(test3, die)),
+ assert_pid(global:send(test4, die)),
- ?line ?UNTIL(OrigNames =:= global:registered_names()),
+ ?UNTIL(OrigNames =:= global:registered_names()),
write_high_level_trace(Config),
stop_node(Cp0),
@@ -1344,15 +1332,13 @@ stress_partition(Config) when is_list(Config) ->
stop_node(Cp6),
stop_node(Cp7),
stop_node(Cp8),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
%% Use this one to test alot of connection tests
-%% erl -sname ts -rsh ctrsh -pa /clearcase/otp/internal_tools/test_server/ebin/ -ring_line 10000 -s test_server run_test global_SUITE
+%% erl -sname ts -ring_line 10000 -s test_server run_test global_SUITE
-ring_line(suite) -> [];
-ring_line(doc) -> [""];
ring_line(Config) when is_list(Config) ->
{ok, [[N]]} = init:get_argument(ring_line),
loop_it(list_to_integer(N), Config).
@@ -1361,74 +1347,70 @@ loop_it(N, Config) -> loop_it(N,N, Config).
loop_it(0,_, _Config) -> ok;
loop_it(N,M, Config) ->
- test_server:format(1, "Round: ~w", [M-N]),
+ ct:pal(?HI_VERBOSITY, "Round: ~w", [M-N]),
ring(Config),
line(Config),
loop_it(N-1,M, Config).
-ring(suite) ->
- [];
-ring(doc) ->
- ["Make 10 single nodes, all having the same name.",
- "Make all ping its predecessor, pinging in a ring.",
- "Make sure that there's just one winner."];
+%% Make 10 single nodes, all having the same name.
+%% Make all ping its predecessor, pinging in a ring.
+%% Make sure that there's just one winner.
ring(Config) when is_list(Config) ->
Timeout = 60,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
- ?line [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6, Cp7, Cp8]
+ [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6, Cp7, Cp8]
= start_nodes([cp0, cp1, cp2, cp3, cp4, cp5, cp6, cp7, cp8],
peer, Config),
Nodes = lists:sort([node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6, Cp7, Cp8]),
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
Time = msec() + 7000,
- ?line rpc_cast(Cp0, ?MODULE, single_node, [Time, Cp8, Config]),
- ?line rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]),
- ?line rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]),
- ?line rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]),
- ?line rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]),
- ?line rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
- ?line rpc_cast(Cp6, ?MODULE, single_node, [Time, Cp5, Config]),
- ?line rpc_cast(Cp7, ?MODULE, single_node, [Time, Cp6, Config]),
- ?line rpc_cast(Cp8, ?MODULE, single_node, [Time, Cp7, Config]),
-
- % sleep to make the partitioned net ready
- test_server:sleep(Time - msec()),
-
- ?line pong = net_adm:ping(Cp0),
- ?line pong = net_adm:ping(Cp1),
- ?line pong = net_adm:ping(Cp2),
- ?line pong = net_adm:ping(Cp3),
- ?line pong = net_adm:ping(Cp4),
- ?line pong = net_adm:ping(Cp5),
- ?line pong = net_adm:ping(Cp6),
- ?line pong = net_adm:ping(Cp7),
- ?line pong = net_adm:ping(Cp8),
-
- ?line pong = net_adm:ping(Cp0),
- ?line pong = net_adm:ping(Cp1),
- ?line pong = net_adm:ping(Cp2),
- ?line pong = net_adm:ping(Cp3),
- ?line pong = net_adm:ping(Cp4),
- ?line pong = net_adm:ping(Cp5),
- ?line pong = net_adm:ping(Cp6),
- ?line pong = net_adm:ping(Cp7),
- ?line pong = net_adm:ping(Cp8),
-
- ?line wait_for_ready_net(Nodes, Config),
-
- % Just make sure that all nodes have the same picture of all names
- ?line check_everywhere(Nodes, single_name, Config),
- ?line assert_pid(global:whereis_name(single_name)),
-
- ?line
+ rpc_cast(Cp0, ?MODULE, single_node, [Time, Cp8, Config]),
+ rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]),
+ rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]),
+ rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]),
+ rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]),
+ rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
+ rpc_cast(Cp6, ?MODULE, single_node, [Time, Cp5, Config]),
+ rpc_cast(Cp7, ?MODULE, single_node, [Time, Cp6, Config]),
+ rpc_cast(Cp8, ?MODULE, single_node, [Time, Cp7, Config]),
+
+ %% sleep to make the partitioned net ready
+ ct:sleep(Time - msec()),
+
+ pong = net_adm:ping(Cp0),
+ pong = net_adm:ping(Cp1),
+ pong = net_adm:ping(Cp2),
+ pong = net_adm:ping(Cp3),
+ pong = net_adm:ping(Cp4),
+ pong = net_adm:ping(Cp5),
+ pong = net_adm:ping(Cp6),
+ pong = net_adm:ping(Cp7),
+ pong = net_adm:ping(Cp8),
+
+ pong = net_adm:ping(Cp0),
+ pong = net_adm:ping(Cp1),
+ pong = net_adm:ping(Cp2),
+ pong = net_adm:ping(Cp3),
+ pong = net_adm:ping(Cp4),
+ pong = net_adm:ping(Cp5),
+ pong = net_adm:ping(Cp6),
+ pong = net_adm:ping(Cp7),
+ pong = net_adm:ping(Cp8),
+
+ wait_for_ready_net(Nodes, Config),
+
+ %% Just make sure that all nodes have the same picture of all names
+ check_everywhere(Nodes, single_name, Config),
+ assert_pid(global:whereis_name(single_name)),
+
?UNTIL(begin
{Ns2, []} = rpc:multicall(Nodes, erlang, whereis,
[single_name]),
@@ -1437,10 +1419,10 @@ ring(Config) when is_list(Config) ->
end,
0, Ns2)
end),
-
- ?line assert_pid(global:send(single_name, die)),
- ?line ?UNTIL(OrigNames =:= global:registered_names()),
+ assert_pid(global:send(single_name, die)),
+
+ ?UNTIL(OrigNames =:= global:registered_names()),
write_high_level_trace(Config),
stop_node(Cp0),
@@ -1452,64 +1434,60 @@ ring(Config) when is_list(Config) ->
stop_node(Cp6),
stop_node(Cp7),
stop_node(Cp8),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-simple_ring(suite) ->
- [];
-simple_ring(doc) ->
- ["Simpler version of the ring case. Used because there are some",
- "distribution problems with many nodes.",
- "Make 6 single nodes, all having the same name.",
- "Make all ping its predecessor, pinging in a ring.",
- "Make sure that there's just one winner."];
+%% Simpler version of the ring case. Used because there are some
+%% distribution problems with many nodes.
+%% Make 6 single nodes, all having the same name.
+%% Make all ping its predecessor, pinging in a ring.
+%% Make sure that there's just one winner.
simple_ring(Config) when is_list(Config) ->
Timeout = 60,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
Names = [cp0, cp1, cp2, cp3, cp4, cp5],
- ?line [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5]
+ [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5]
= start_nodes(Names, peer, Config),
Nodes = lists:sort([node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5]),
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
Time = msec() + 5000,
- ?line rpc_cast(Cp0, ?MODULE, single_node, [Time, Cp5, Config]),
- ?line rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]),
- ?line rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]),
- ?line rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]),
- ?line rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]),
- ?line rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
-
- % sleep to make the partitioned net ready
- test_server:sleep(Time - msec()),
-
- ?line pong = net_adm:ping(Cp0),
- ?line pong = net_adm:ping(Cp1),
- ?line pong = net_adm:ping(Cp2),
- ?line pong = net_adm:ping(Cp3),
- ?line pong = net_adm:ping(Cp4),
- ?line pong = net_adm:ping(Cp5),
-
- ?line pong = net_adm:ping(Cp0),
- ?line pong = net_adm:ping(Cp1),
- ?line pong = net_adm:ping(Cp2),
- ?line pong = net_adm:ping(Cp3),
- ?line pong = net_adm:ping(Cp4),
- ?line pong = net_adm:ping(Cp5),
-
- ?line wait_for_ready_net(Nodes, Config),
-
- % Just make sure that all nodes have the same picture of all names
- ?line check_everywhere(Nodes, single_name, Config),
- ?line assert_pid(global:whereis_name(single_name)),
-
- ?line
+ rpc_cast(Cp0, ?MODULE, single_node, [Time, Cp5, Config]),
+ rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]),
+ rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]),
+ rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]),
+ rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]),
+ rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
+
+ %% sleep to make the partitioned net ready
+ ct:sleep(Time - msec()),
+
+ pong = net_adm:ping(Cp0),
+ pong = net_adm:ping(Cp1),
+ pong = net_adm:ping(Cp2),
+ pong = net_adm:ping(Cp3),
+ pong = net_adm:ping(Cp4),
+ pong = net_adm:ping(Cp5),
+
+ pong = net_adm:ping(Cp0),
+ pong = net_adm:ping(Cp1),
+ pong = net_adm:ping(Cp2),
+ pong = net_adm:ping(Cp3),
+ pong = net_adm:ping(Cp4),
+ pong = net_adm:ping(Cp5),
+
+ wait_for_ready_net(Nodes, Config),
+
+ %% Just make sure that all nodes have the same picture of all names
+ check_everywhere(Nodes, single_name, Config),
+ assert_pid(global:whereis_name(single_name)),
+
?UNTIL(begin
{Ns2, []} = rpc:multicall(Nodes, erlang, whereis,
[single_name]),
@@ -1518,10 +1496,10 @@ simple_ring(Config) when is_list(Config) ->
end,
0, Ns2)
end),
-
- ?line assert_pid(global:send(single_name, die)),
- ?line ?UNTIL(OrigNames =:= global:registered_names()),
+ assert_pid(global:send(single_name, die)),
+
+ ?UNTIL(OrigNames =:= global:registered_names()),
write_high_level_trace(Config),
stop_node(Cp0),
@@ -1530,72 +1508,68 @@ simple_ring(Config) when is_list(Config) ->
stop_node(Cp3),
stop_node(Cp4),
stop_node(Cp5),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-line(suite) ->
- [];
-line(doc) ->
- ["Make 6 single nodes, all having the same name.",
- "Make all ping its predecessor, pinging in a line.",
- "Make sure that there's just one winner."];
+%% Make 6 single nodes, all having the same name.
+%% Make all ping its predecessor, pinging in a line.
+%% Make sure that there's just one winner.
line(Config) when is_list(Config) ->
Timeout = 60,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
- ?line [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6, Cp7, Cp8]
+ [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6, Cp7, Cp8]
= start_nodes([cp0, cp1, cp2, cp3, cp4, cp5, cp6, cp7, cp8],
peer, Config),
Nodes = lists:sort([node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6, Cp7, Cp8]),
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
Time = msec() + 7000,
- ?line rpc_cast(Cp0, ?MODULE, single_node,
- [Time, Cp0, Config]), % ping ourself!
- ?line rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]),
- ?line rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]),
- ?line rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]),
- ?line rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]),
- ?line rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
- ?line rpc_cast(Cp6, ?MODULE, single_node, [Time, Cp5, Config]),
- ?line rpc_cast(Cp7, ?MODULE, single_node, [Time, Cp6, Config]),
- ?line rpc_cast(Cp8, ?MODULE, single_node, [Time, Cp7, Config]),
-
- % sleep to make the partitioned net ready
- test_server:sleep(Time - msec()),
-
- ?line pong = net_adm:ping(Cp0),
- ?line pong = net_adm:ping(Cp1),
- ?line pong = net_adm:ping(Cp2),
- ?line pong = net_adm:ping(Cp3),
- ?line pong = net_adm:ping(Cp4),
- ?line pong = net_adm:ping(Cp5),
- ?line pong = net_adm:ping(Cp6),
- ?line pong = net_adm:ping(Cp7),
- ?line pong = net_adm:ping(Cp8),
-
- ?line pong = net_adm:ping(Cp0),
- ?line pong = net_adm:ping(Cp1),
- ?line pong = net_adm:ping(Cp2),
- ?line pong = net_adm:ping(Cp3),
- ?line pong = net_adm:ping(Cp4),
- ?line pong = net_adm:ping(Cp5),
- ?line pong = net_adm:ping(Cp6),
- ?line pong = net_adm:ping(Cp7),
- ?line pong = net_adm:ping(Cp8),
-
- ?line wait_for_ready_net(Nodes, Config),
-
- % Just make sure that all nodes have the same picture of all names
- ?line check_everywhere(Nodes, single_name, Config),
- ?line assert_pid(global:whereis_name(single_name)),
-
- ?line
+ rpc_cast(Cp0, ?MODULE, single_node,
+ [Time, Cp0, Config]), % ping ourself!
+ rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]),
+ rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]),
+ rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]),
+ rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]),
+ rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
+ rpc_cast(Cp6, ?MODULE, single_node, [Time, Cp5, Config]),
+ rpc_cast(Cp7, ?MODULE, single_node, [Time, Cp6, Config]),
+ rpc_cast(Cp8, ?MODULE, single_node, [Time, Cp7, Config]),
+
+ %% Sleep to make the partitioned net ready
+ ct:sleep(Time - msec()),
+
+ pong = net_adm:ping(Cp0),
+ pong = net_adm:ping(Cp1),
+ pong = net_adm:ping(Cp2),
+ pong = net_adm:ping(Cp3),
+ pong = net_adm:ping(Cp4),
+ pong = net_adm:ping(Cp5),
+ pong = net_adm:ping(Cp6),
+ pong = net_adm:ping(Cp7),
+ pong = net_adm:ping(Cp8),
+
+ pong = net_adm:ping(Cp0),
+ pong = net_adm:ping(Cp1),
+ pong = net_adm:ping(Cp2),
+ pong = net_adm:ping(Cp3),
+ pong = net_adm:ping(Cp4),
+ pong = net_adm:ping(Cp5),
+ pong = net_adm:ping(Cp6),
+ pong = net_adm:ping(Cp7),
+ pong = net_adm:ping(Cp8),
+
+ wait_for_ready_net(Nodes, Config),
+
+ %% Just make sure that all nodes have the same picture of all names
+ check_everywhere(Nodes, single_name, Config),
+ assert_pid(global:whereis_name(single_name)),
+
?UNTIL(begin
{Ns2, []} = rpc:multicall(Nodes, erlang, whereis,
[single_name]),
@@ -1604,10 +1578,10 @@ line(Config) when is_list(Config) ->
end,
0, Ns2)
end),
-
- ?line assert_pid(global:send(single_name, die)),
- ?line ?UNTIL(OrigNames =:= global:registered_names()),
+ assert_pid(global:send(single_name, die)),
+
+ ?UNTIL(OrigNames =:= global:registered_names()),
write_high_level_trace(Config),
stop_node(Cp0),
@@ -1619,65 +1593,61 @@ line(Config) when is_list(Config) ->
stop_node(Cp6),
stop_node(Cp7),
stop_node(Cp8),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-simple_line(suite) ->
- [];
-simple_line(doc) ->
- ["Simpler version of the line case. Used because there are some",
- "distribution problems with many nodes.",
- "Make 6 single nodes, all having the same name.",
- "Make all ping its predecessor, pinging in a line.",
- "Make sure that there's just one winner."];
+%% Simpler version of the line case. Used because there are some
+%% distribution problems with many nodes.
+%% Make 6 single nodes, all having the same name.
+%% Make all ping its predecessor, pinging in a line.
+%% Make sure that there's just one winner.
simple_line(Config) when is_list(Config) ->
Timeout = 60,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
- ?line [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5]
+ [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5]
= start_nodes([cp0, cp1, cp2, cp3, cp4, cp5], peer, Config),
Nodes = lists:sort([node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5]),
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
Time = msec() + 5000,
- ?line rpc_cast(Cp0, ?MODULE, single_node,
- [Time, Cp0, Config]), % ping ourself!
- ?line rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]),
- ?line rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]),
- ?line rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]),
- ?line rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]),
- ?line rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
-
- % sleep to make the partitioned net ready
- test_server:sleep(Time - msec()),
-
- ?line pong = net_adm:ping(Cp0),
- ?line pong = net_adm:ping(Cp1),
- ?line pong = net_adm:ping(Cp2),
- ?line pong = net_adm:ping(Cp3),
- ?line pong = net_adm:ping(Cp4),
- ?line pong = net_adm:ping(Cp5),
-
- ?line pong = net_adm:ping(Cp0),
- ?line pong = net_adm:ping(Cp1),
- ?line pong = net_adm:ping(Cp2),
- ?line pong = net_adm:ping(Cp3),
- ?line pong = net_adm:ping(Cp4),
- ?line pong = net_adm:ping(Cp5),
-
- ?line wait_for_ready_net(Nodes, Config),
-
- % Just make sure that all nodes have the same picture of all names
- ?line check_everywhere(Nodes, single_name, Config),
- ?line assert_pid(global:whereis_name(single_name)),
-
- ?line
+ rpc_cast(Cp0, ?MODULE, single_node,
+ [Time, Cp0, Config]), % ping ourself!
+ rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]),
+ rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]),
+ rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]),
+ rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]),
+ rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
+
+ %% sleep to make the partitioned net ready
+ ct:sleep(Time - msec()),
+
+ pong = net_adm:ping(Cp0),
+ pong = net_adm:ping(Cp1),
+ pong = net_adm:ping(Cp2),
+ pong = net_adm:ping(Cp3),
+ pong = net_adm:ping(Cp4),
+ pong = net_adm:ping(Cp5),
+
+ pong = net_adm:ping(Cp0),
+ pong = net_adm:ping(Cp1),
+ pong = net_adm:ping(Cp2),
+ pong = net_adm:ping(Cp3),
+ pong = net_adm:ping(Cp4),
+ pong = net_adm:ping(Cp5),
+
+ wait_for_ready_net(Nodes, Config),
+
+ %% Just make sure that all nodes have the same picture of all names
+ check_everywhere(Nodes, single_name, Config),
+ assert_pid(global:whereis_name(single_name)),
+
?UNTIL(begin
{Ns2, []} = rpc:multicall(Nodes, erlang, whereis,
[single_name]),
@@ -1686,10 +1656,10 @@ simple_line(Config) when is_list(Config) ->
end,
0, Ns2)
end),
-
- ?line assert_pid(global:send(single_name, die)),
- ?line ?UNTIL(OrigNames =:= global:registered_names()),
+ assert_pid(global:send(single_name, die)),
+
+ ?UNTIL(OrigNames =:= global:registered_names()),
write_high_level_trace(Config),
stop_node(Cp0),
@@ -1698,82 +1668,74 @@ simple_line(Config) when is_list(Config) ->
stop_node(Cp3),
stop_node(Cp4),
stop_node(Cp5),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-
-otp_1849(suite) -> [];
-otp_1849(doc) ->
- ["Test ticket: Global should keep track of all pids that set the same lock."];
+
+%% Test ticket: Global should keep track of all pids that set the same lock.
otp_1849(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line {ok, Cp1} = start_node(cp1, Config),
- ?line {ok, Cp2} = start_node(cp2, Config),
- ?line {ok, Cp3} = start_node(cp3, Config),
-
- ?line wait_for_ready_net(Config),
-
- % start procs on each node
- ?line Pid1 = rpc:call(Cp1, ?MODULE, start_proc, []),
- ?line assert_pid(Pid1),
- ?line Pid2 = rpc:call(Cp2, ?MODULE, start_proc, []),
- ?line assert_pid(Pid2),
- ?line Pid3 = rpc:call(Cp3, ?MODULE, start_proc, []),
- ?line assert_pid(Pid3),
-
- % set a lock on every node
- ?line true = req(Pid1, {set_lock2, {test_lock, ?MODULE}, self()}),
- ?line true = req(Pid2, {set_lock2, {test_lock, ?MODULE}, self()}),
- ?line true = req(Pid3, {set_lock2, {test_lock, ?MODULE}, self()}),
-
- ?line
- ?UNTIL(begin
+ init_condition(Config),
+ {ok, Cp1} = start_node(cp1, Config),
+ {ok, Cp2} = start_node(cp2, Config),
+ {ok, Cp3} = start_node(cp3, Config),
+
+ wait_for_ready_net(Config),
+
+ %% start procs on each node
+ Pid1 = rpc:call(Cp1, ?MODULE, start_proc, []),
+ assert_pid(Pid1),
+ Pid2 = rpc:call(Cp2, ?MODULE, start_proc, []),
+ assert_pid(Pid2),
+ Pid3 = rpc:call(Cp3, ?MODULE, start_proc, []),
+ assert_pid(Pid3),
+
+ %% set a lock on every node
+ true = req(Pid1, {set_lock2, {test_lock, ?MODULE}, self()}),
+ true = req(Pid2, {set_lock2, {test_lock, ?MODULE}, self()}),
+ true = req(Pid3, {set_lock2, {test_lock, ?MODULE}, self()}),
+
+ ?UNTIL(begin
[{test_lock, ?MODULE, Lock1}] =
rpc:call(Cp1, ets, tab2list, [global_locks]),
3 =:= length(Lock1)
end),
- ?line true = req(Pid3, {del_lock2, {test_lock, ?MODULE}, self()}),
- ?line
+ true = req(Pid3, {del_lock2, {test_lock, ?MODULE}, self()}),
?UNTIL(begin
[{test_lock, ?MODULE, Lock2}] =
rpc:call(Cp1, ets, tab2list, [global_locks]),
2 =:= length(Lock2)
end),
- ?line true = req(Pid2, {del_lock2, {test_lock, ?MODULE}, self()}),
- ?line
+ true = req(Pid2, {del_lock2, {test_lock, ?MODULE}, self()}),
?UNTIL(begin
[{test_lock, ?MODULE, Lock3}] =
rpc:call(Cp1, ets, tab2list, [global_locks]),
1 =:= length(Lock3)
end),
- ?line true = req(Pid1, {del_lock2, {test_lock, ?MODULE}, self()}),
- ?line ?UNTIL([] =:= rpc:call(Cp1, ets, tab2list, [global_locks])),
+ true = req(Pid1, {del_lock2, {test_lock, ?MODULE}, self()}),
+ ?UNTIL([] =:= rpc:call(Cp1, ets, tab2list, [global_locks])),
- ?line true = req(Pid1, {set_lock2, {test_lock, ?MODULE}, self()}),
- ?line true = req(Pid2, {set_lock2, {test_lock, ?MODULE}, self()}),
- ?line true = req(Pid3, {set_lock2, {test_lock, ?MODULE}, self()}),
- ?line false = req(Pid2, {set_lock2, {test_lock, not_valid}, self()}),
+ true = req(Pid1, {set_lock2, {test_lock, ?MODULE}, self()}),
+ true = req(Pid2, {set_lock2, {test_lock, ?MODULE}, self()}),
+ true = req(Pid3, {set_lock2, {test_lock, ?MODULE}, self()}),
+ false = req(Pid2, {set_lock2, {test_lock, not_valid}, self()}),
exit_p(Pid1),
- ?line
?UNTIL(begin
[{test_lock, ?MODULE, Lock10}] =
rpc:call(Cp1, ets, tab2list, [global_locks]),
2 =:= length(Lock10)
end),
- ?line
?UNTIL(begin
[{test_lock, ?MODULE, Lock11}] =
rpc:call(Cp2, ets, tab2list, [global_locks]),
2 =:= length(Lock11)
end),
- ?line
?UNTIL(begin
[{test_lock, ?MODULE, Lock12}] =
rpc:call(Cp3, ets, tab2list, [global_locks]),
@@ -1784,13 +1746,11 @@ otp_1849(Config) when is_list(Config) ->
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-
-otp_3162(suite) -> [];
-otp_3162(doc) ->
- ["Test ticket: Deadlock in global"];
+
+%% Test ticket: Deadlock in global.
otp_3162(Config) when is_list(Config) ->
StartFun = fun() ->
{ok, Cp1} = start_node(cp1, Config),
@@ -1804,77 +1764,74 @@ do_otp_3162(StartFun, Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line [Cp1, Cp2, Cp3] = StartFun(),
+ init_condition(Config),
+ [Cp1, Cp2, Cp3] = StartFun(),
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
- % start procs on each node
- ?line Pid1 = rpc:call(Cp1, ?MODULE, start_proc4, [kalle]),
- ?line assert_pid(Pid1),
- ?line Pid2 = rpc:call(Cp2, ?MODULE, start_proc4, [stina]),
- ?line assert_pid(Pid2),
- ?line Pid3 = rpc:call(Cp3, ?MODULE, start_proc4, [vera]),
- ?line assert_pid(Pid3),
+ %% start procs on each node
+ Pid1 = rpc:call(Cp1, ?MODULE, start_proc4, [kalle]),
+ assert_pid(Pid1),
+ Pid2 = rpc:call(Cp2, ?MODULE, start_proc4, [stina]),
+ assert_pid(Pid2),
+ Pid3 = rpc:call(Cp3, ?MODULE, start_proc4, [vera]),
+ assert_pid(Pid3),
- ?line rpc_disconnect_node(Cp1, Cp2, Config),
+ rpc_disconnect_node(Cp1, Cp2, Config),
- ?line ?UNTIL
+ ?UNTIL
([Cp3] =:= lists:sort(rpc:call(Cp1, erlang, nodes, [])) -- [node()]),
?UNTIL([kalle, vera] =:=
- lists:sort(rpc:call(Cp1, global, registered_names, []))),
- ?line ?UNTIL
+ lists:sort(rpc:call(Cp1, global, registered_names, []))),
+ ?UNTIL
([Cp3] =:= lists:sort(rpc:call(Cp2, erlang, nodes, [])) -- [node()]),
?UNTIL([stina, vera] =:=
- lists:sort(rpc:call(Cp2, global, registered_names, []))),
- ?line ?UNTIL
+ lists:sort(rpc:call(Cp2, global, registered_names, []))),
+ ?UNTIL
([Cp1, Cp2] =:=
- lists:sort(rpc:call(Cp3, erlang, nodes, [])) -- [node()]),
+ lists:sort(rpc:call(Cp3, erlang, nodes, [])) -- [node()]),
?UNTIL([kalle, stina, vera] =:=
- lists:sort(rpc:call(Cp3, global, registered_names, []))),
+ lists:sort(rpc:call(Cp3, global, registered_names, []))),
- ?line pong = rpc:call(Cp2, net_adm, ping, [Cp1]),
+ pong = rpc:call(Cp2, net_adm, ping, [Cp1]),
- ?line ?UNTIL
+ ?UNTIL
([Cp2, Cp3] =:=
- lists:sort(rpc:call(Cp1, erlang, nodes, [])) -- [node()]),
- ?line
+ lists:sort(rpc:call(Cp1, erlang, nodes, [])) -- [node()]),
?UNTIL(begin
NN = lists:sort(rpc:call(Cp1, global, registered_names, [])),
[kalle, stina, vera] =:= NN
end),
- ?line ?UNTIL
+ ?UNTIL
([Cp1, Cp3] =:=
- lists:sort(rpc:call(Cp2, erlang, nodes, [])) -- [node()]),
+ lists:sort(rpc:call(Cp2, erlang, nodes, [])) -- [node()]),
?UNTIL([kalle, stina, vera] =:=
- lists:sort(rpc:call(Cp2, global, registered_names, []))),
- ?line ?UNTIL
+ lists:sort(rpc:call(Cp2, global, registered_names, []))),
+ ?UNTIL
([Cp1, Cp2] =:=
- lists:sort(rpc:call(Cp3, erlang, nodes, [])) -- [node()]),
+ lists:sort(rpc:call(Cp3, erlang, nodes, [])) -- [node()]),
?UNTIL([kalle, stina, vera] =:=
- lists:sort(rpc:call(Cp3, global, registered_names, []))),
+ lists:sort(rpc:call(Cp3, global, registered_names, []))),
write_high_level_trace(Config),
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-
-otp_5640(suite) -> [];
-otp_5640(doc) ->
- ["OTP-5640. 'allow' multiple names for registered processes."];
+
+%% OTP-5640. 'allow' multiple names for registered processes.
otp_5640(Config) when is_list(Config) ->
Timeout = 25,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
init_condition(Config),
- ?line {ok, B} = start_node(b, Config),
+ {ok, B} = start_node(b, Config),
- ?line Nodes = lists:sort([node(), B]),
- ?line wait_for_ready_net(Nodes, Config),
+ Nodes = lists:sort([node(), B]),
+ wait_for_ready_net(Nodes, Config),
Server = whereis(global_name_server),
ServerB = rpc:call(B, erlang, whereis, [global_name_server]),
@@ -1882,50 +1839,50 @@ otp_5640(Config) when is_list(Config) ->
Me = self(),
Proc = spawn(fun() -> otp_5640_proc(Me) end),
- ?line yes = global:register_name(name1, Proc),
- ?line no = global:register_name(name2, Proc),
+ yes = global:register_name(name1, Proc),
+ no = global:register_name(name2, Proc),
- ?line ok = application:set_env(kernel, global_multi_name_action, allow),
- ?line yes = global:register_name(name2, Proc),
+ ok = application:set_env(kernel, global_multi_name_action, allow),
+ yes = global:register_name(name2, Proc),
- test_server:sleep(100),
- ?line Proc = global:whereis_name(name1),
- ?line Proc = global:whereis_name(name2),
- ?line check_everywhere(Nodes, name1, Config),
- ?line check_everywhere(Nodes, name2, Config),
+ ct:sleep(100),
+ Proc = global:whereis_name(name1),
+ Proc = global:whereis_name(name2),
+ check_everywhere(Nodes, name1, Config),
+ check_everywhere(Nodes, name2, Config),
- ?line {monitors_2levels, MonBy1} = mon_by_servers(Proc),
- ?line [] = ([Server,Server,ServerB,ServerB] -- MonBy1),
- ?line {links,[]} = process_info(Proc, links),
- ?line _ = global:unregister_name(name1),
+ {monitors_2levels, MonBy1} = mon_by_servers(Proc),
+ [] = ([Server,Server,ServerB,ServerB] -- MonBy1),
+ {links,[]} = process_info(Proc, links),
+ _ = global:unregister_name(name1),
- test_server:sleep(100),
- ?line undefined = global:whereis_name(name1),
- ?line Proc = global:whereis_name(name2),
- ?line check_everywhere(Nodes, name1, Config),
- ?line check_everywhere(Nodes, name2, Config),
+ ct:sleep(100),
+ undefined = global:whereis_name(name1),
+ Proc = global:whereis_name(name2),
+ check_everywhere(Nodes, name1, Config),
+ check_everywhere(Nodes, name2, Config),
- ?line {monitors_2levels, MonBy2} = mon_by_servers(Proc),
- ?line [] = ([Server,ServerB] -- MonBy2),
+ {monitors_2levels, MonBy2} = mon_by_servers(Proc),
+ [] = ([Server,ServerB] -- MonBy2),
TmpMonBy2 = MonBy2 -- [Server,ServerB],
- ?line TmpMonBy2 = TmpMonBy2 -- [Server,ServerB],
- ?line {links,[]} = process_info(Proc, links),
+ TmpMonBy2 = TmpMonBy2 -- [Server,ServerB],
+ {links,[]} = process_info(Proc, links),
- ?line yes = global:register_name(name1, Proc),
+ yes = global:register_name(name1, Proc),
Proc ! die,
- test_server:sleep(100),
- ?line undefined = global:whereis_name(name1),
- ?line undefined = global:whereis_name(name2),
- ?line check_everywhere(Nodes, name1, Config),
- ?line check_everywhere(Nodes, name2, Config),
- ?line {monitors, GMonitors} = process_info(Server, monitors),
- ?line false = lists:member({process, Proc}, GMonitors),
+ ct:sleep(100),
+ undefined = global:whereis_name(name1),
+ undefined = global:whereis_name(name2),
+ check_everywhere(Nodes, name1, Config),
+ check_everywhere(Nodes, name2, Config),
+ {monitors, GMonitors} = process_info(Server, monitors),
+ false = lists:member({process, Proc}, GMonitors),
write_high_level_trace(Config),
stop_node(B),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
otp_5640_proc(_Parent) ->
@@ -1934,45 +1891,42 @@ otp_5640_proc(_Parent) ->
exit(normal)
end.
-otp_5737(suite) -> [];
-otp_5737(doc) ->
- ["OTP-5737. set_lock/3 and trans/4 accept Retries = 0."];
+%% OTP-5737. set_lock/3 and trans/4 accept Retries = 0.
otp_5737(Config) when is_list(Config) ->
Timeout = 25,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
+ init_condition(Config),
LockId = {?MODULE,self()},
Nodes = [node()],
- ?line {'EXIT', _} = (catch global:set_lock(LockId, Nodes, -1)),
- ?line {'EXIT', _} = (catch global:set_lock(LockId, Nodes, a)),
- ?line true = global:set_lock(LockId, Nodes, 0),
+ {'EXIT', _} = (catch global:set_lock(LockId, Nodes, -1)),
+ {'EXIT', _} = (catch global:set_lock(LockId, Nodes, a)),
+ true = global:set_lock(LockId, Nodes, 0),
Time1 = now(),
- ?line false = global:set_lock({?MODULE,not_me}, Nodes, 0),
- ?line true = timer:now_diff(now(), Time1) < 5000,
- ?line _ = global:del_lock(LockId, Nodes),
+ false = global:set_lock({?MODULE,not_me}, Nodes, 0),
+ true = timer:now_diff(now(), Time1) < 5000,
+ _ = global:del_lock(LockId, Nodes),
Fun = fun() -> ok end,
- ?line {'EXIT', _} = (catch global:trans(LockId, Fun, Nodes, -1)),
- ?line {'EXIT', _} = (catch global:trans(LockId, Fun, Nodes, a)),
- ?line ok = global:trans(LockId, Fun, Nodes, 0),
+ {'EXIT', _} = (catch global:trans(LockId, Fun, Nodes, -1)),
+ {'EXIT', _} = (catch global:trans(LockId, Fun, Nodes, a)),
+ ok = global:trans(LockId, Fun, Nodes, 0),
write_high_level_trace(Config),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-otp_6931(suite) -> [];
-otp_6931(doc) -> ["OTP-6931. Ignore nodeup when connect_all=false."];
+%% OTP-6931. Ignore nodeup when connect_all=false.
otp_6931(Config) when is_list(Config) ->
Me = self(),
- ?line {ok, CAf} = start_non_connecting_node(ca_false, Config),
- ?line ok = rpc:call(CAf, error_logger, add_report_handler, [?MODULE, Me]),
- ?line info = rpc:call(CAf, error_logger, warning_map, []),
- ?line {global_name_server,CAf} ! {nodeup, fake_node},
+ {ok, CAf} = start_non_connecting_node(ca_false, Config),
+ ok = rpc:call(CAf, error_logger, add_report_handler, [?MODULE, Me]),
+ info = rpc:call(CAf, error_logger, warning_map, []),
+ {global_name_server,CAf} ! {nodeup, fake_node},
timer:sleep(100),
stop_node(CAf),
- receive {nodeup,fake_node} -> test_server:fail({info_report, was, sent})
+ receive {nodeup,fake_node} -> ct:fail({info_report, was, sent})
after 1000 -> ok
end,
ok.
@@ -1980,18 +1934,17 @@ otp_6931(Config) when is_list(Config) ->
%%%-----------------------------------------------------------------
%%% Testing a disconnected node. Not two partitions.
%%%-----------------------------------------------------------------
-simple_disconnect(suite) -> [];
-simple_disconnect(doc) -> ["OTP-5563. Disconnected nodes (not partitions)"];
+%% OTP-5563. Disconnected nodes (not partitions).
simple_disconnect(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
%% Three nodes (test_server, n_1, n_2).
- ?line [Cp1, Cp2] = Cps = start_nodes([n_1, n_2], peer, Config),
- ?line wait_for_ready_net(Config),
+ [Cp1, Cp2] = Cps = start_nodes([n_1, n_2], peer, Config),
+ wait_for_ready_net(Config),
Nodes = lists:sort([node() | Cps]),
@@ -2001,39 +1954,39 @@ simple_disconnect(Config) when is_list(Config) ->
Resolver = {no_module, resolve_none}, % will never be called
PingNode = Cp2,
- ?line {_Pid1, yes} =
+ {_Pid1, yes} =
rpc:call(Cp1, ?MODULE, start_resolver, [Name, Resolver]),
- test_server:sleep(100),
+ ct:sleep(100),
%% Disconnect test_server and Cp2.
- ?line true = erlang:disconnect_node(Cp2),
- test_server:sleep(500),
+ true = erlang:disconnect_node(Cp2),
+ ct:sleep(500),
%% _Pid is registered on Cp1. The exchange of names between Cp2 and
%% test_server sees two identical pids.
- ?line pong = net_adm:ping(PingNode),
- ?line ?UNTIL(Cps =:= lists:sort(nodes())),
+ pong = net_adm:ping(PingNode),
+ ?UNTIL(Cps =:= lists:sort(nodes())),
- ?line {_, Trace0} = collect_tracers(Nodes),
- ?line Resolvers = [P || {_Node,new_resolver,{pid,P}} <- Trace0],
- ?line lists:foreach(fun(P) -> P ! die end, Resolvers),
- ?line lists:foreach(fun(P) -> wait_for_exit(P) end, Resolvers),
- ?line check_everywhere(Nodes, Name, Config),
- ?line undefined = global:whereis_name(Name),
+ {_, Trace0} = collect_tracers(Nodes),
+ Resolvers = [P || {_Node,new_resolver,{pid,P}} <- Trace0],
+ lists:foreach(fun(P) -> P ! die end, Resolvers),
+ lists:foreach(fun(P) -> wait_for_exit(P) end, Resolvers),
+ check_everywhere(Nodes, Name, Config),
+ undefined = global:whereis_name(Name),
- ?line {_, Trace1} = collect_tracers(Nodes),
+ {_, Trace1} = collect_tracers(Nodes),
Trace = Trace0 ++ Trace1,
- ?line [] = [foo || {_, resolve_none, _, _} <- Trace],
+ [] = [foo || {_, resolve_none, _, _} <- Trace],
- ?line Gs = name_servers(Nodes),
- ?line [_, _, _] = monitored_by_node(Trace, Gs),
+ Gs = name_servers(Nodes),
+ [_, _, _] = monitored_by_node(Trace, Gs),
lists:foreach(fun(N) -> rpc:call(N, ?MODULE, stop_tracer, []) end, Nodes),
- ?line OrigNames = global:registered_names(),
+ OrigNames = global:registered_names(),
write_high_level_trace(Config),
stop_nodes(Cps),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
%% Not used right now.
@@ -2052,7 +2005,7 @@ simple_dis(Nodes0, Name, Resolver, Config) ->
simple_dis_node(_Node, DisNodes, _Name, _Resolver, Config) ->
lists:foreach(
fun(OtherNode) -> _ = erlang:disconnect_node(OtherNode) end, DisNodes),
- ?line ?UNTIL(DisNodes -- nodes() =:= DisNodes),
+ ?UNTIL(DisNodes -- nodes() =:= DisNodes),
ok.
@@ -2072,19 +2025,18 @@ simple_dis_node(_Node, DisNodes, _Name, _Resolver, Config) ->
-define(RES(F), {F, fun ?MODULE:F/3}).
-simple_resolve(suite) -> [];
-simple_resolve(doc) -> ["OTP-5563. Partitions and names."];
+%% OTP-5563. Partitions and names.
simple_resolve(Config) when is_list(Config) ->
Timeout = 360,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
- ?line [N1, A2, Z2] = Cps = start_nodes([n_1, a_2, z_2], peer, Config),
+ [N1, A2, Z2] = Cps = start_nodes([n_1, a_2, z_2], peer, Config),
Nodes = lists:sort([node() | Cps]),
- ?line wait_for_ready_net(Config),
-
+ wait_for_ready_net(Config),
+
lists:foreach(fun(N) ->
rpc:call(N, ?MODULE, start_tracer, [])
end, Nodes),
@@ -2193,20 +2145,19 @@ simple_resolve(Config) when is_list(Config) ->
%% then a new attempt (nodeup etc.) is made. This time the
%% resolver does not disconnect any node.
res(?RES(disconnect_first), Cps, Cf#cf{link = Z2, n2 = Z2,
- nodes = [node(), N1, A2, Z2]}),
+ nodes = [node(), N1, A2, Z2]}),
- ?line lists:foreach(fun(N) ->
- rpc:call(N, ?MODULE, stop_tracer, [])
- end, Nodes),
+ lists:foreach(fun(N) ->
+ rpc:call(N, ?MODULE, stop_tracer, [])
+ end, Nodes),
- ?line OrigNames = global:registered_names(),
+ OrigNames = global:registered_names(),
write_high_level_trace(Config),
stop_nodes(Cps),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-simple_resolve2(suite) -> [];
-simple_resolve2(doc) -> ["OTP-5563. Partitions and names."];
+%% OTP-5563. Partitions and names.
simple_resolve2(Config) when is_list(Config) ->
%% Continuation of simple_resolve. Of some reason it did not
%% always work to re-start z_2. "Cannot be a global bug."
@@ -2214,13 +2165,13 @@ simple_resolve2(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
- ?line [N1, A2, Z2] = Cps = start_nodes([n_1, a_2, z_2], peer, Config),
- ?line wait_for_ready_net(Config),
+ [N1, A2, Z2] = Cps = start_nodes([n_1, a_2, z_2], peer, Config),
+ wait_for_ready_net(Config),
Nodes = lists:sort([node() | Cps]),
-
+
lists:foreach(fun(N) ->
rpc:call(N, ?MODULE, start_tracer, [])
end, Nodes),
@@ -2230,33 +2181,32 @@ simple_resolve2(Config) when is_list(Config) ->
%% Halt z_2.
res(?RES(halt_second), Cps, Cf#cf{link = N1, n1 = N1, n2 = Z2, ping = A2,
- nodes = [node(), N1, A2], n_res = 1}),
+ nodes = [node(), N1, A2], n_res = 1}),
- ?line lists:foreach(fun(N) ->
- rpc:call(N, ?MODULE, stop_tracer, [])
- end, Nodes),
+ lists:foreach(fun(N) ->
+ rpc:call(N, ?MODULE, stop_tracer, [])
+ end, Nodes),
- ?line OrigNames = global:registered_names(),
+ OrigNames = global:registered_names(),
write_high_level_trace(Config),
stop_nodes(Cps), % Not all nodes may be present, but it works anyway.
- ?line init_condition(Config),
+ init_condition(Config),
ok.
-simple_resolve3(suite) -> [];
-simple_resolve3(doc) -> ["OTP-5563. Partitions and names."];
+%% OTP-5563. Partitions and names.
simple_resolve3(Config) when is_list(Config) ->
%% Continuation of simple_resolve.
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
- ?line [N1, A2, Z2] = Cps = start_nodes([n_1, a_2, z_2], peer, Config),
- ?line wait_for_ready_net(Config),
+ [N1, A2, Z2] = Cps = start_nodes([n_1, a_2, z_2], peer, Config),
+ wait_for_ready_net(Config),
Nodes = lists:sort([node() | Cps]),
-
+
lists:foreach(fun(N) ->
rpc:call(N, ?MODULE, start_tracer, [])
end, Nodes),
@@ -2267,27 +2217,27 @@ simple_resolve3(Config) when is_list(Config) ->
%% Halt a_2.
res(?RES(halt_second), Cps, Cf#cf{link = node(), n2 = A2,
nodes = [node(), N1], n_res = 1}),
-
- ?line lists:foreach(fun(N) ->
- rpc:call(N, ?MODULE, stop_tracer, [])
- end, Nodes),
- ?line OrigNames = global:registered_names(),
+ lists:foreach(fun(N) ->
+ rpc:call(N, ?MODULE, stop_tracer, [])
+ end, Nodes),
+
+ OrigNames = global:registered_names(),
write_high_level_trace(Config),
stop_nodes(Cps), % Not all nodes may be present, but it works anyway.
- ?line init_condition(Config),
+ init_condition(Config),
ok.
res({Res,Resolver}, [N1, A2, Z2], Cf) ->
%% Note: there are no links anymore, but monitors.
#cf{link = LinkedNode, ping = PingNode, n1 = Res1, n2 = OtherNode,
nodes = Nodes0, n_res = NRes, config = Config} = Cf,
- ?t:format("~n~nResolver: ~p", [Res]),
- ?t:format(" Registered on partition 1: ~p", [Res1]),
- ?t:format(" Registered on partition 2: ~p", [OtherNode]),
- ?t:format(" Pinged node: ~p", [PingNode]),
- ?t:format(" Linked node: ~p", [LinkedNode]),
- ?t:format(" Expected # resolvers: ~p", [NRes]),
+ io:format("~n~nResolver: ~p", [Res]),
+ io:format(" Registered on partition 1: ~p", [Res1]),
+ io:format(" Registered on partition 2: ~p", [OtherNode]),
+ io:format(" Pinged node: ~p", [PingNode]),
+ io:format(" Linked node: ~p", [LinkedNode]),
+ io:format(" Expected # resolvers: ~p", [NRes]),
Nodes = lists:sort(Nodes0),
T1 = node(),
Part1 = [T1, N1],
@@ -2299,67 +2249,67 @@ res({Res,Resolver}, [N1, A2, Z2], Cf) ->
%% expected monitors remain between registered processes and the
%% global_name_server.
- ?line rpc_cast(OtherNode,
- ?MODULE,
- part_2_2,
- [Config, Part1, Part2, [{Name, Resolver}]]),
- ?line ?UNTIL(is_ready_partition(Config)),
- ?line {_Pid1, yes} =
+ rpc_cast(OtherNode,
+ ?MODULE,
+ part_2_2,
+ [Config, Part1, Part2, [{Name, Resolver}]]),
+ ?UNTIL(is_ready_partition(Config)),
+ {_Pid1, yes} =
rpc:call(Res1, ?MODULE, start_resolver, [Name, Resolver]),
- ?line pong = net_adm:ping(PingNode),
- ?line wait_for_ready_net(Nodes, Config),
+ pong = net_adm:ping(PingNode),
+ wait_for_ready_net(Nodes, Config),
- ?line check_everywhere(Nodes, Name, Config),
- ?line case global:whereis_name(Name) of
- undefined when LinkedNode =:= none -> ok;
- Pid -> assert_pid(Pid)
- end,
+ check_everywhere(Nodes, Name, Config),
+ case global:whereis_name(Name) of
+ undefined when LinkedNode =:= none -> ok;
+ Pid -> assert_pid(Pid)
+ end,
- ?line {_, Trace0} = collect_tracers(Nodes),
- ?line Resolvers = [P || {_Node,new_resolver,{pid,P}} <- Trace0],
+ {_, Trace0} = collect_tracers(Nodes),
+ Resolvers = [P || {_Node,new_resolver,{pid,P}} <- Trace0],
- ?line NRes = length(Resolvers),
+ NRes = length(Resolvers),
%% Wait for extra monitor processes to be created.
%% This applies as long as global:do_monitor/1 spawns processes.
%% (Some day monitor() will be truly synchronous.)
- test_server:sleep(100),
+ ct:sleep(100),
- ?line lists:foreach(fun(P) -> P ! die end, Resolvers),
- ?line lists:foreach(fun(P) -> wait_for_exit(P) end, Resolvers),
+ lists:foreach(fun(P) -> P ! die end, Resolvers),
+ lists:foreach(fun(P) -> wait_for_exit(P) end, Resolvers),
- ?line check_everywhere(Nodes, Name, Config),
- ?line undefined = global:whereis_name(Name),
+ check_everywhere(Nodes, Name, Config),
+ undefined = global:whereis_name(Name),
%% Wait for monitors to remove names.
- test_server:sleep(100),
+ ct:sleep(100),
- ?line {_, Trace1} = collect_tracers(Nodes),
+ {_, Trace1} = collect_tracers(Nodes),
Trace = Trace0 ++ Trace1,
- ?line Gs = name_servers([T1, N1, A2, Z2]),
- ?line MonitoredByNode = monitored_by_node(Trace, Gs),
- ?line MonitoredBy = [M || {_N,M} <- MonitoredByNode],
-
+ Gs = name_servers([T1, N1, A2, Z2]),
+ MonitoredByNode = monitored_by_node(Trace, Gs),
+ MonitoredBy = [M || {_N,M} <- MonitoredByNode],
+
X = MonitoredBy -- Gs,
LengthGs = length(Gs),
- ?line case MonitoredBy of
- [] when LinkedNode =:= none -> ok;
- Gs -> ok;
- _ when LengthGs < 4, X =:= [] -> ok;
- _ -> ?t:format("ERROR:~nMonitoredBy ~p~n"
- "global_name_servers ~p~n",
- [MonitoredByNode, Gs]),
- ?t:fail(monitor_mismatch)
- end,
+ case MonitoredBy of
+ [] when LinkedNode =:= none -> ok;
+ Gs -> ok;
+ _ when LengthGs < 4, X =:= [] -> ok;
+ _ -> io:format("ERROR:~nMonitoredBy ~p~n"
+ "global_name_servers ~p~n",
+ [MonitoredByNode, Gs]),
+ ct:fail(monitor_mismatch)
+ end,
ok.
name_servers(Nodes) ->
lists:sort([rpc:call(N, erlang, whereis, [global_name_server]) ||
N <- Nodes,
pong =:= net_adm:ping(N)]).
-
+
monitored_by_node(Trace, Servers) ->
lists:sort([{node(M),M} ||
{_Node,_P,died,{monitors_2levels,ML}} <- Trace,
@@ -2371,7 +2321,7 @@ part_2_2(Config, Part1, Part2, NameResolvers) ->
make_partition(Config, Part1, Part2),
lists:foreach
(fun({Name, Resolver}) ->
- ?line {Pid2, yes} = start_resolver(Name, Resolver),
+ {Pid2, yes} = start_resolver(Name, Resolver),
trace_message({node(), part_2_2, nodes(), {pid2,Pid2}})
end, NameResolvers).
@@ -2396,7 +2346,7 @@ exit_resolver(name, _Pid1, _Pid2) ->
lock_resolver(name, Pid1, _Pid2) ->
Id = {?MODULE, self()},
Nodes = [node()],
- ?line true = global:set_lock(Id, Nodes),
+ true = global:set_lock(Id, Nodes),
_ = global:del_lock(Id, Nodes),
Pid1.
@@ -2426,7 +2376,7 @@ start_resolver(Name, Resolver) ->
receive
{Pid, Res} -> {Pid, Res}
end.
-
+
init_resolver(Parent, Name, Resolver) ->
X = global:register_name(Name, self(), Resolver),
Parent ! {self(), X},
@@ -2455,18 +2405,17 @@ mon_by_servers(Proc) ->
-define(REGNAME, contact_a_2).
-leftover_name(suite) -> [];
-leftover_name(doc) -> ["OTP-5563. Bug: nodedown while synching."];
+%% OTP-5563. Bug: nodedown while synching.
leftover_name(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
- ?line [N1, A2, Z2] = Cps = start_nodes([n_1, a_2, z_2], peer, Config),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
+ [N1, A2, Z2] = Cps = start_nodes([n_1, a_2, z_2], peer, Config),
Nodes = lists:sort([node() | Cps]),
- ?line wait_for_ready_net(Config),
-
+ wait_for_ready_net(Config),
+
lists:foreach(fun(N) ->
rpc:call(N, ?MODULE, start_tracer, [])
end, Nodes),
@@ -2474,20 +2423,20 @@ leftover_name(Config) when is_list(Config) ->
Name = name, % registered on a_2
ResName = resolved_name, % registered on n_1 and a_2
%%
- ?line _Pid = ping_a_2_fun(?REGNAME, N1, A2),
+ _Pid = ping_a_2_fun(?REGNAME, N1, A2),
T1 = node(),
Part1 = [T1, N1],
Part2 = [A2, Z2],
NoResolver = {no_module, resolve_none},
Resolver = fun contact_a_2/3,
- ?line rpc_cast(A2,
- ?MODULE, part_2_2, [Config,
- Part1,
- Part2,
- [{Name, NoResolver},
- {ResName, Resolver}]]),
- ?line ?UNTIL(is_ready_partition(Config)),
+ rpc_cast(A2,
+ ?MODULE, part_2_2, [Config,
+ Part1,
+ Part2,
+ [{Name, NoResolver},
+ {ResName, Resolver}]]),
+ ?UNTIL(is_ready_partition(Config)),
%% resolved_name is resolved to run on a_2, an insert operation is
%% sent to n_1. The resolver function halts a_2, but the nodedown
@@ -2496,36 +2445,36 @@ leftover_name(Config) when is_list(Config) ->
%% delayed). Unless "artificial" nodedown messages are sent the
%% name would linger on indefinitely. [There is no test case for
%% the situation that no nodedown message at all is sent.]
- ?line {_Pid1, yes} =
+ {_Pid1, yes} =
rpc:call(N1, ?MODULE, start_resolver,
[ResName, fun contact_a_2/3]),
- test_server:sleep(1000),
+ ct:sleep(1000),
- ?line trace_message({node(), pinging, z_2}),
- ?line pong = net_adm:ping(Z2),
- ?line ?UNTIL((Nodes -- [A2]) =:= lists:sort(?NODES)),
- ?t:sleep(1000),
+ trace_message({node(), pinging, z_2}),
+ pong = net_adm:ping(Z2),
+ ?UNTIL((Nodes -- [A2]) =:= lists:sort(?NODES)),
+ ct:sleep(1000),
- ?line {_,Trace0} = collect_tracers(Nodes),
+ {_,Trace0} = collect_tracers(Nodes),
- ?line Resolvers = [P || {_Node,new_resolver,{pid,P}} <- Trace0],
- ?line lists:foreach(fun(P) -> P ! die end, Resolvers),
- ?line lists:foreach(fun(P) -> wait_for_exit(P) end, Resolvers),
+ Resolvers = [P || {_Node,new_resolver,{pid,P}} <- Trace0],
+ lists:foreach(fun(P) -> P ! die end, Resolvers),
+ lists:foreach(fun(P) -> wait_for_exit(P) end, Resolvers),
- ?line lists:foreach(fun(N) ->
- rpc:call(N, ?MODULE, stop_tracer, [])
- end, Nodes),
+ lists:foreach(fun(N) ->
+ rpc:call(N, ?MODULE, stop_tracer, [])
+ end, Nodes),
- ?line ?UNTIL(OrigNames =:= global:registered_names()),
+ ?UNTIL(OrigNames =:= global:registered_names()),
write_high_level_trace(Config),
stop_nodes(Cps),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
%% Runs on n_1
contact_a_2(resolved_name, Pid1, Pid2) ->
trace_message({node(), ?REGNAME, {pid1,Pid1}, {pid2,Pid2},
- {node1,node(Pid1)}, {node2,node(Pid2)}}),
+ {node1,node(Pid1)}, {node2,node(Pid2)}}),
?REGNAME ! doit,
Pid2.
@@ -2543,15 +2492,14 @@ ping_a_2(RegName, N1, A2) ->
{nodedown, A2} -> ok
end
end.
-
+
halt_node(Node) ->
rpc:call(Node, erlang, halt, []).
%%%-----------------------------------------------------------------
%%% Testing re-registration of a name.
%%%-----------------------------------------------------------------
-re_register_name(suite) -> [];
-re_register_name(doc) -> ["OTP-5563. Name is re-registered."];
+%% OTP-5563. Name is re-registered.
re_register_name(Config) when is_list(Config) ->
%% When re-registering a name the link to the old pid used to
%% linger on. Don't think is was a serious bug though--some memory
@@ -2560,18 +2508,18 @@ re_register_name(Config) when is_list(Config) ->
Timeout = 15,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
+ init_condition(Config),
Me = self(),
Pid1 = spawn(fun() -> proc(Me) end),
- ?line yes = global:register_name(name, Pid1),
+ yes = global:register_name(name, Pid1),
Pid2 = spawn(fun() -> proc(Me) end),
- ?line _ = global:re_register_name(name, Pid2),
+ _ = global:re_register_name(name, Pid2),
Pid2 ! die,
Pid1 ! die,
receive {Pid1, MonitoredBy1} -> [] = MonitoredBy1 end,
receive {Pid2, MonitoredBy2} -> [_] = MonitoredBy2 end,
- ?line _ = global:unregister_name(name),
- ?line init_condition(Config),
+ _ = global:unregister_name(name),
+ init_condition(Config),
ok.
proc(Parent) ->
@@ -2583,15 +2531,14 @@ proc(Parent) ->
%%%-----------------------------------------------------------------
%%%
%%%-----------------------------------------------------------------
-name_exit(suite) -> [];
-name_exit(doc) -> ["OTP-5563. Registered process dies."];
+%% OTP-5563. Registered process dies.
name_exit(Config) when is_list(Config) ->
StartFun = fun() ->
{ok, N1} = start_node_rel(n_1, this, Config),
{ok, N2} = start_node_rel(n_2, this, Config),
[N1, N2]
end,
- ?t:format("Test of current release~n"),
+ io:format("Test of current release~n"),
do_name_exit(StartFun, current, Config).
do_name_exit(StartFun, Version, Config) ->
@@ -2607,17 +2554,17 @@ do_name_exit(StartFun, Version, Config) ->
Timeout = 60,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
%% Three nodes (test_server, n_1, n_2).
- ?line Cps = StartFun(),
+ Cps = StartFun(),
Nodes = lists:sort([node() | Cps]),
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
lists:foreach(fun(N) -> rpc:call(N, ?MODULE, start_tracer, []) end,Nodes),
Name = name,
- ?line {Pid, yes} = start_proc(Name),
+ {Pid, yes} = start_proc(Name),
Me = self(),
LL = spawn(fun() -> long_lock(Me) end),
@@ -2628,23 +2575,23 @@ do_name_exit(StartFun, Version, Config) ->
Pid ! die,
wait_for_exit_fast(Pid),
- ?t:sleep(100),
+ ct:sleep(100),
%% Name has been removed from node()'s table, but nowhere else
%% since there is a lock on 'global'.
{R1,[]} = rpc:multicall(Nodes, global, whereis_name, [Name]),
- ?line case Version of
- old -> [_,_] = lists:usort(R1);
- current -> [undefined, undefined, undefined] = R1
- end,
- ?t:sleep(3000),
- ?line check_everywhere(Nodes, Name, Config),
+ case Version of
+ old -> [_,_] = lists:usort(R1);
+ current -> [undefined, undefined, undefined] = R1
+ end,
+ ct:sleep(3000),
+ check_everywhere(Nodes, Name, Config),
lists:foreach(fun(N) -> rpc:call(N, ?MODULE, stop_tracer, []) end, Nodes),
- ?line OrigNames = global:registered_names(),
+ OrigNames = global:registered_names(),
exit(LL, kill),
write_high_level_trace(Config),
stop_nodes(Cps),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
long_lock(Parent) ->
@@ -2657,17 +2604,16 @@ long_lock(Parent) ->
%%%-----------------------------------------------------------------
%%% Testing the support for external nodes (cnodes)
%%%-----------------------------------------------------------------
-external_nodes(suite) -> [];
-external_nodes(doc) -> ["OTP-5563. External nodes (cnodes)."];
+%% OTP-5563. External nodes (cnodes).
external_nodes(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
- ?line [NodeB, NodeC] = start_nodes([b, c], peer, Config),
- ?line wait_for_ready_net(Config),
+ [NodeB, NodeC] = start_nodes([b, c], peer, Config),
+ wait_for_ready_net(Config),
%% Nodes = ?NODES,
%% lists:foreach(fun(N) -> rpc:call(N, ?MODULE, start_tracer, []) end,
@@ -2676,75 +2622,75 @@ external_nodes(Config) when is_list(Config) ->
%% Two partitions: [test_server] and [b, c].
%% c registers an external name on b
- ?line rpc_cast(NodeB, ?MODULE, part_ext,
- [Config, node(), NodeC, Name]),
- ?line ?UNTIL(is_ready_partition(Config)),
+ rpc_cast(NodeB, ?MODULE, part_ext,
+ [Config, node(), NodeC, Name]),
+ ?UNTIL(is_ready_partition(Config)),
- ?line pong = net_adm:ping(NodeB),
- ?line ?UNTIL([NodeB, NodeC] =:= lists:sort(nodes())),
- ?line wait_for_ready_net(Config),
+ pong = net_adm:ping(NodeB),
+ ?UNTIL([NodeB, NodeC] =:= lists:sort(nodes())),
+ wait_for_ready_net(Config),
- ?line Cpid = rpc:call(NodeC, erlang, whereis, [Name]),
+ Cpid = rpc:call(NodeC, erlang, whereis, [Name]),
ExternalName = [{name,Cpid,NodeB}],
- ?line ExternalName = get_ext_names(),
- ?line ExternalName = rpc:call(NodeB, gen_server, call,
- [global_name_server, get_names_ext]),
- ?line ExternalName = rpc:call(NodeC, gen_server, call,
- [global_name_server, get_names_ext]),
-
- ?line [_] = cnode_links(Cpid),
- ?line [_,_,_] = cnode_monitored_by(Cpid),
- ?line no = global:register_name(Name, self()),
- ?line yes = global:re_register_name(Name, self()),
- ?line ?UNTIL([] =:= cnode_monitored_by(Cpid)),
- ?line ?UNTIL([] =:= cnode_links(Cpid)),
- ?line [] = gen_server:call(global_name_server, get_names_ext, infinity),
-
- ?line Cpid ! {register, self(), Name},
- ?line receive {Cpid, Reply1} -> no = Reply1 end,
- ?line _ = global:unregister_name(Name),
- test_server:sleep(1000),
- ?line Cpid ! {register, self(), Name},
- ?line ?UNTIL(length(get_ext_names()) =:= 1),
- ?line receive {Cpid, Reply2} -> yes = Reply2 end,
-
- ?line Cpid ! {unregister, self(), Name},
- ?line ?UNTIL(length(get_ext_names()) =:= 0),
- ?line receive {Cpid, Reply3} -> ok = Reply3 end,
+ ExternalName = get_ext_names(),
+ ExternalName = rpc:call(NodeB, gen_server, call,
+ [global_name_server, get_names_ext]),
+ ExternalName = rpc:call(NodeC, gen_server, call,
+ [global_name_server, get_names_ext]),
+
+ [_] = cnode_links(Cpid),
+ [_,_,_] = cnode_monitored_by(Cpid),
+ no = global:register_name(Name, self()),
+ yes = global:re_register_name(Name, self()),
+ ?UNTIL([] =:= cnode_monitored_by(Cpid)),
+ ?UNTIL([] =:= cnode_links(Cpid)),
+ [] = gen_server:call(global_name_server, get_names_ext, infinity),
+
+ Cpid ! {register, self(), Name},
+ receive {Cpid, Reply1} -> no = Reply1 end,
+ _ = global:unregister_name(Name),
+ ct:sleep(1000),
+ Cpid ! {register, self(), Name},
+ ?UNTIL(length(get_ext_names()) =:= 1),
+ receive {Cpid, Reply2} -> yes = Reply2 end,
+
+ Cpid ! {unregister, self(), Name},
+ ?UNTIL(length(get_ext_names()) =:= 0),
+ receive {Cpid, Reply3} -> ok = Reply3 end,
Cpid ! die,
- ?line ?UNTIL(OrigNames =:= global:registered_names()),
- ?line [] = get_ext_names(),
- ?line [] = rpc:call(NodeB, gen_server, call,
- [global_name_server, get_names_ext]),
- ?line [] = rpc:call(NodeC, gen_server, call,
- [global_name_server, get_names_ext]),
+ ?UNTIL(OrigNames =:= global:registered_names()),
+ [] = get_ext_names(),
+ [] = rpc:call(NodeB, gen_server, call,
+ [global_name_server, get_names_ext]),
+ [] = rpc:call(NodeC, gen_server, call,
+ [global_name_server, get_names_ext]),
- ?line Cpid2 = erlang:spawn(NodeC, fun() -> cnode_proc(NodeB) end),
- ?line Cpid2 ! {register, self(), Name},
- ?line receive {Cpid2, Reply4} -> yes = Reply4 end,
+ Cpid2 = erlang:spawn(NodeC, fun() -> cnode_proc(NodeB) end),
+ Cpid2 ! {register, self(), Name},
+ receive {Cpid2, Reply4} -> yes = Reply4 end,
%% It could be a bug that Cpid2 is linked to 'global_name_server'
%% at node 'b'. The effect: Cpid2 dies when node 'b' crashes.
stop_node(NodeB),
- ?line ?UNTIL(OrigNames =:= global:registered_names()),
- ?line [] = get_ext_names(),
- ?line [] = rpc:call(NodeC, gen_server, call,
- [global_name_server, get_names_ext]),
+ ?UNTIL(OrigNames =:= global:registered_names()),
+ [] = get_ext_names(),
+ [] = rpc:call(NodeC, gen_server, call,
+ [global_name_server, get_names_ext]),
- %% ?line {_, Trace} = collect_tracers(Nodes),
+ %% {_, Trace} = collect_tracers(Nodes),
%% lists:foreach(fun(M) -> erlang:display(M) end, Trace),
ThisNode = node(),
- ?line Cpid3 = erlang:spawn(NodeC, fun() -> cnode_proc(ThisNode) end),
- ?line Cpid3 ! {register, self(), Name},
- ?line receive {Cpid3, Reply5} -> yes = Reply5 end,
+ Cpid3 = erlang:spawn(NodeC, fun() -> cnode_proc(ThisNode) end),
+ Cpid3 ! {register, self(), Name},
+ receive {Cpid3, Reply5} -> yes = Reply5 end,
- ?line ?UNTIL(length(get_ext_names()) =:= 1),
+ ?UNTIL(length(get_ext_names()) =:= 1),
stop_node(NodeC),
- ?line ?UNTIL(length(get_ext_names()) =:= 0),
+ ?UNTIL(length(get_ext_names()) =:= 0),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
get_ext_names() ->
@@ -2791,19 +2737,16 @@ cnode_proc(E) ->
cnode_proc(E).
-many_nodes(suite) ->
- [];
-many_nodes(doc) ->
- ["OTP-5770. Start many nodes. Make them connect at the same time."];
+%% OTP-5770. Start many nodes. Make them connect at the same time.
many_nodes(Config) when is_list(Config) ->
Timeout = 240,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
{Rels, N_cps} =
- case ?t:os_type() of
+ case test_server:os_type() of
{unix, Osname} when Osname =:= linux;
Osname =:= openbsd;
Osname =:= darwin ->
@@ -2814,12 +2757,12 @@ many_nodes(Config) when is_list(Config) ->
_ ->
{node_rel(1, 32, this), 32}
end,
- ?line Cps = [begin {ok, Cp} = start_node_rel(Name, Rel, Config), Cp end ||
- {Name,Rel} <- Rels],
+ Cps = [begin {ok, Cp} = start_node_rel(Name, Rel, Config), Cp end ||
+ {Name,Rel} <- Rels],
Nodes = lists:sort(?NODES),
- ?line wait_for_ready_net(Nodes, Config),
+ wait_for_ready_net(Nodes, Config),
- ?line Dir = ?config(priv_dir, Config),
+ Dir = proplists:get_value(priv_dir, Config),
GoFile = filename:join([Dir, "go.txt"]),
file:delete(GoFile),
@@ -2830,34 +2773,34 @@ many_nodes(Config) when is_list(Config) ->
file:delete(File),
rpc_cast(N, ?MODULE, isolated_node, [File, GoFile, Cps, Config])
end,
- ?line lists:foreach(IsoFun, CpsFiles),
-
- ?line all_nodes_files(CpsFiles, "isolated", Config),
- ?line Time = msec(),
- ?line sync_until(),
+ lists:foreach(IsoFun, CpsFiles),
+
+ all_nodes_files(CpsFiles, "isolated", Config),
+ Time = msec(),
+ sync_until(),
erlang:display(ready_to_go),
- ?line touch(GoFile, "go"),
- ?line all_nodes_files(CpsFiles, "done", Config),
- ?line Time2 = msec(),
+ touch(GoFile, "go"),
+ all_nodes_files(CpsFiles, "done", Config),
+ Time2 = msec(),
- ?line lists:foreach(fun(N) -> pong = net_adm:ping(N) end, Cps),
+ lists:foreach(fun(N) -> pong = net_adm:ping(N) end, Cps),
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
write_high_level_trace(Config), % The test succeeded, but was it slow?
- ?line lists:foreach(fun({_N, File}) -> file:delete(File) end, CpsFiles),
- ?line file:delete(GoFile),
+ lists:foreach(fun({_N, File}) -> file:delete(File) end, CpsFiles),
+ file:delete(GoFile),
- ?line ?UNTIL(OrigNames =:= global:registered_names()),
+ ?UNTIL(OrigNames =:= global:registered_names()),
write_high_level_trace(Config),
- ?line stop_nodes(Cps),
- ?line init_condition(Config),
+ stop_nodes(Cps),
+ init_condition(Config),
Diff = Time2 - Time,
Return = lists:flatten(io_lib:format("~w nodes took ~w ms",
[N_cps, Diff])),
erlang:display({{nodes,N_cps},{time,Diff}}),
- ?t:format("~s~n", [Return]),
+ io:format("~s~n", [Return]),
{comment, Return}.
node_rel(From, To, Rel) ->
@@ -2883,7 +2826,7 @@ isolated_node(File, GoFile, Nodes, Config) ->
touch(File, "got_go"),
lists:foreach(fun(N) -> _ = net_adm:ping(N) end, shuffle(Nodes)),
touch(File, "pinged"),
- ?line ?UNTIL((Ns -- get_known(node())) =:= []),
+ ?UNTIL((Ns -- get_known(node())) =:= []),
touch(File, "done").
touch(File, List) ->
@@ -2931,19 +2874,17 @@ sync_until(LogFile) ->
timer:sleep(Time).
shuffle(L) ->
- [E || {_, E} <- lists:keysort(1, [{random:uniform(), E} || E <- L])].
+ [E || {_, E} <- lists:keysort(1, [{rand:uniform(), E} || E <- L])].
-sync_0(suite) -> [];
-sync_0(doc) ->
- ["OTP-5770. sync/0."];
+%% OTP-5770. sync/0.
sync_0(Config) when is_list(Config) ->
Timeout = 180,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
+ init_condition(Config),
N_cps =
- case ?t:os_type() of
+ case test_server:os_type() of
{unix, Osname} when Osname =:= linux;
Osname =:= openbsd;
Osname =:= darwin ->
@@ -2958,82 +2899,80 @@ sync_0(Config) when is_list(Config) ->
Names = [lists:concat([cp,N]) || N <- lists:seq(1, N_cps)],
Cps = start_and_sync(Names),
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
write_high_level_trace(Config),
stop_nodes(Cps),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
start_and_sync([]) ->
[];
start_and_sync([Name | Names]) ->
- ?line {ok, N} = start_node(Name, slave, []),
- ?line {Time, _Void} = rpc:call(N, timer, tc, [global, sync, []]),
- ?t:format("~p: ~p~n", [Name, Time]),
+ {ok, N} = start_node(Name, slave, []),
+ {Time, _Void} = rpc:call(N, timer, tc, [global, sync, []]),
+ io:format("~p: ~p~n", [Name, Time]),
[N | start_and_sync(Names)].
%%%-----------------------------------------------------------------
%%% Testing of change of global_groups parameter.
%%%-----------------------------------------------------------------
-global_groups_change(suite) -> [];
-global_groups_change(doc) -> ["Test change of global_groups parameter."];
+%% Test change of global_groups parameter.
global_groups_change(Config) ->
Timeout = 90,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line M = from($@, atom_to_list(node())),
-
- % Create the .app files and the boot script
- ?line {KernelVer, StdlibVer} = create_script_dc("dc"),
- ?line case is_real_system(KernelVer, StdlibVer) of
- true ->
- Options = [];
- false ->
- Options = [local]
- end,
+ init_condition(Config),
+ M = from($@, atom_to_list(node())),
+
+ %% Create the .app files and the boot script
+ {KernelVer, StdlibVer} = create_script_dc("dc"),
+ case is_real_system(KernelVer, StdlibVer) of
+ true ->
+ Options = [];
+ false ->
+ Options = [local]
+ end,
+
+ ok = systools:make_script("dc", Options),
- ?line ok = systools:make_script("dc", Options),
-
[Ncp1,Ncp2,Ncp3,Ncp4,Ncp5,NcpA,NcpB,NcpC,NcpD,NcpE] =
node_names([cp1,cp2,cp3,cp4,cp5,cpA,cpB,cpC,cpD,cpE], Config),
- % Write config files
- ?line Dir = ?config(priv_dir,Config),
- ?line {ok, Fd_dc} = file:open(filename:join(Dir, "sys.config"), [write]),
- ?line config_dc1(Fd_dc, Ncp1, Ncp2, Ncp3, NcpA, NcpB, NcpC, NcpD, NcpE),
- ?line file:close(Fd_dc),
- ?line Config1 = filename:join(Dir, "sys"),
-
- % Test [cp1, cp2, cp3]
- ?line {ok, Cp1} = start_node_boot(Ncp1, Config1, dc),
- ?line {ok, Cp2} = start_node_boot(Ncp2, Config1, dc),
- ?line {ok, Cp3} = start_node_boot(Ncp3, Config1, dc),
- ?line {ok, CpA} = start_node_boot(NcpA, Config1, dc),
- ?line {ok, CpB} = start_node_boot(NcpB, Config1, dc),
- ?line {ok, CpC} = start_node_boot(NcpC, Config1, dc),
- ?line {ok, CpD} = start_node_boot(NcpD, Config1, dc),
- ?line {ok, CpE} = start_node_boot(NcpE, Config1, dc),
-
- ?line pong = rpc:call(Cp1, net_adm, ping, [Cp2]),
- ?line pong = rpc:call(Cp1, net_adm, ping, [Cp3]),
- ?line pang = rpc:call(Cp1, net_adm, ping,
- [list_to_atom(lists:concat(["cp5@", M]))]),
- ?line pong = rpc:call(Cp2, net_adm, ping, [Cp3]),
- ?line pang = rpc:call(Cp2, net_adm, ping,
- [list_to_atom(lists:concat(["cp5@", M]))]),
-
- ?line {TestGG4, yes} = rpc:call(CpB, ?MODULE, start_proc, [test]),
- ?line {TestGG5, yes} = rpc:call(CpE, ?MODULE, start_proc, [test]),
-
-
- ?line pong = rpc:call(CpA, net_adm, ping, [CpC]),
- ?line pong = rpc:call(CpC, net_adm, ping, [CpB]),
- ?line pong = rpc:call(CpD, net_adm, ping, [CpC]),
- ?line pong = rpc:call(CpE, net_adm, ping, [CpD]),
-
- ?line
+ %% Write config files
+ Dir = proplists:get_value(priv_dir,Config),
+ {ok, Fd_dc} = file:open(filename:join(Dir, "sys.config"), [write]),
+ config_dc1(Fd_dc, Ncp1, Ncp2, Ncp3, NcpA, NcpB, NcpC, NcpD, NcpE),
+ file:close(Fd_dc),
+ Config1 = filename:join(Dir, "sys"),
+
+ %% Test [cp1, cp2, cp3]
+ {ok, Cp1} = start_node_boot(Ncp1, Config1, dc),
+ {ok, Cp2} = start_node_boot(Ncp2, Config1, dc),
+ {ok, Cp3} = start_node_boot(Ncp3, Config1, dc),
+ {ok, CpA} = start_node_boot(NcpA, Config1, dc),
+ {ok, CpB} = start_node_boot(NcpB, Config1, dc),
+ {ok, CpC} = start_node_boot(NcpC, Config1, dc),
+ {ok, CpD} = start_node_boot(NcpD, Config1, dc),
+ {ok, CpE} = start_node_boot(NcpE, Config1, dc),
+
+ pong = rpc:call(Cp1, net_adm, ping, [Cp2]),
+ pong = rpc:call(Cp1, net_adm, ping, [Cp3]),
+ pang = rpc:call(Cp1, net_adm, ping,
+ [list_to_atom(lists:concat(["cp5@", M]))]),
+ pong = rpc:call(Cp2, net_adm, ping, [Cp3]),
+ pang = rpc:call(Cp2, net_adm, ping,
+ [list_to_atom(lists:concat(["cp5@", M]))]),
+
+ {TestGG4, yes} = rpc:call(CpB, ?MODULE, start_proc, [test]),
+ {TestGG5, yes} = rpc:call(CpE, ?MODULE, start_proc, [test]),
+
+
+ pong = rpc:call(CpA, net_adm, ping, [CpC]),
+ pong = rpc:call(CpC, net_adm, ping, [CpB]),
+ pong = rpc:call(CpD, net_adm, ping, [CpC]),
+ pong = rpc:call(CpE, net_adm, ping, [CpD]),
+
?UNTIL(begin
TestGG4_1 = rpc:call(CpA, global, whereis_name, [test]),
TestGG4_2 = rpc:call(CpB, global, whereis_name, [test]),
@@ -3050,88 +2989,87 @@ global_groups_change(Config) ->
(TestGG5_2 =:= TestGG5)
end),
- ?line ?t:format( "#### nodes() ~p~n",[nodes()]),
+ io:format( "#### nodes() ~p~n",[nodes()]),
- ?line XDcWa1 = rpc:call(Cp1, global_group, info, []),
- ?line XDcWa2 = rpc:call(Cp2, global_group, info, []),
- ?line XDcWa3 = rpc:call(Cp3, global_group, info, []),
- ?line ?t:format( "#### XDcWa1 ~p~n",[XDcWa1]),
- ?line ?t:format( "#### XDcWa2 ~p~n",[XDcWa2]),
- ?line ?t:format( "#### XDcWa3 ~p~n",[XDcWa3]),
+ XDcWa1 = rpc:call(Cp1, global_group, info, []),
+ XDcWa2 = rpc:call(Cp2, global_group, info, []),
+ XDcWa3 = rpc:call(Cp3, global_group, info, []),
+ io:format( "#### XDcWa1 ~p~n",[XDcWa1]),
+ io:format( "#### XDcWa2 ~p~n",[XDcWa2]),
+ io:format( "#### XDcWa3 ~p~n",[XDcWa3]),
+
+ stop_node(CpC),
- ?line stop_node(CpC),
-
%% Read the current configuration parameters, and change them
- ?line OldEnv =
+ OldEnv =
rpc:call(Cp1, application_controller, prep_config_change, []),
- ?line {value, {kernel, OldKernel}} = lists:keysearch(kernel, 1, OldEnv),
+ {value, {kernel, OldKernel}} = lists:keysearch(kernel, 1, OldEnv),
- ?line GG1 =
+ GG1 =
lists:sort([mk_node(Ncp1, M), mk_node(Ncp2, M), mk_node(Ncp5, M)]),
- ?line GG2 = lists:sort([mk_node(Ncp3, M)]),
- ?line GG3 = lists:sort([mk_node(Ncp4, M)]),
- ?line GG4 = lists:sort([mk_node(NcpA, M), mk_node(NcpB, M)]),
- ?line GG5 =
+ GG2 = lists:sort([mk_node(Ncp3, M)]),
+ GG3 = lists:sort([mk_node(Ncp4, M)]),
+ GG4 = lists:sort([mk_node(NcpA, M), mk_node(NcpB, M)]),
+ GG5 =
lists:sort([mk_node(NcpC, M), mk_node(NcpD, M), mk_node(NcpE, M)]),
- ?line NewNG = {global_groups,[{gg1, normal, GG1},
- {gg2, normal, GG2},
- {gg3, normal, GG3},
- {gg4, normal, GG4},
- {gg5, hidden, GG5}]},
-
- ?line NewKernel =
+ NewNG = {global_groups,[{gg1, normal, GG1},
+ {gg2, normal, GG2},
+ {gg3, normal, GG3},
+ {gg4, normal, GG4},
+ {gg5, hidden, GG5}]},
+
+ NewKernel =
[{kernel, lists:keyreplace(global_groups, 1, OldKernel, NewNG)}],
- ?line ok = rpc:call(Cp1, application_controller, test_change_apps,
- [[kernel], [NewKernel]]),
- ?line ok = rpc:call(Cp2, application_controller, test_change_apps,
- [[kernel], [NewKernel]]),
- ?line ok = rpc:call(Cp3, application_controller, test_change_apps,
- [[kernel], [NewKernel]]),
- ?line ok = rpc:call(CpA, application_controller, test_change_apps,
- [[kernel], [NewKernel]]),
- ?line ok = rpc:call(CpB, application_controller, test_change_apps,
- [[kernel], [NewKernel]]),
- ?line ok = rpc:call(CpD, application_controller, test_change_apps,
- [[kernel], [NewKernel]]),
- ?line ok = rpc:call(CpE, application_controller, test_change_apps,
- [[kernel], [NewKernel]]),
-
- ?line ?t:format("#### ~p~n",[multicall]),
- ?line ?t:format( "#### ~p~n",[multicall]),
+ ok = rpc:call(Cp1, application_controller, test_change_apps,
+ [[kernel], [NewKernel]]),
+ ok = rpc:call(Cp2, application_controller, test_change_apps,
+ [[kernel], [NewKernel]]),
+ ok = rpc:call(Cp3, application_controller, test_change_apps,
+ [[kernel], [NewKernel]]),
+ ok = rpc:call(CpA, application_controller, test_change_apps,
+ [[kernel], [NewKernel]]),
+ ok = rpc:call(CpB, application_controller, test_change_apps,
+ [[kernel], [NewKernel]]),
+ ok = rpc:call(CpD, application_controller, test_change_apps,
+ [[kernel], [NewKernel]]),
+ ok = rpc:call(CpE, application_controller, test_change_apps,
+ [[kernel], [NewKernel]]),
+
+ io:format("#### ~p~n",[multicall]),
+ io:format( "#### ~p~n",[multicall]),
%% no idea to check the result from the rpc because the other
%% nodes will disconnect test server, and thus the result will
%% always be {badrpc, nodedown}
- ?line rpc:multicall([Cp1, Cp2, Cp3, CpA, CpB, CpD, CpE],
- application_controller, config_change, [OldEnv]),
+ rpc:multicall([Cp1, Cp2, Cp3, CpA, CpB, CpD, CpE],
+ application_controller, config_change, [OldEnv]),
- ?line {ok, Fd_dc2} = file:open(filename:join(Dir, "sys2.config"), [write]),
- ?line config_dc2(Fd_dc2, NewNG, Ncp1, Ncp2, Ncp3),
- ?line file:close(Fd_dc2),
- ?line Config2 = filename:join(Dir, "sys2"),
- ?line {ok, CpC} = start_node_boot(NcpC, Config2, dc),
+ {ok, Fd_dc2} = file:open(filename:join(Dir, "sys2.config"), [write]),
+ config_dc2(Fd_dc2, NewNG, Ncp1, Ncp2, Ncp3),
+ file:close(Fd_dc2),
+ Config2 = filename:join(Dir, "sys2"),
+ {ok, CpC} = start_node_boot(NcpC, Config2, dc),
- ?line sync_and_wait(CpA),
- ?line sync_and_wait(CpD),
-
- ?line pong = rpc:call(CpA, net_adm, ping, [CpC]),
- ?line pong = rpc:call(CpC, net_adm, ping, [CpB]),
- ?line pong = rpc:call(CpD, net_adm, ping, [CpC]),
- ?line pong = rpc:call(CpE, net_adm, ping, [CpD]),
-
- ?line GG5 =
+ sync_and_wait(CpA),
+ sync_and_wait(CpD),
+
+ pong = rpc:call(CpA, net_adm, ping, [CpC]),
+ pong = rpc:call(CpC, net_adm, ping, [CpB]),
+ pong = rpc:call(CpD, net_adm, ping, [CpC]),
+ pong = rpc:call(CpE, net_adm, ping, [CpD]),
+
+ GG5 =
lists:sort([mk_node(NcpC, M)|rpc:call(CpC, erlang, nodes, [])]),
- ?line GG5 =
+ GG5 =
lists:sort([mk_node(NcpD, M)|rpc:call(CpD, erlang, nodes, [])]),
- ?line GG5 =
+ GG5 =
lists:sort([mk_node(NcpE, M)|rpc:call(CpE, erlang, nodes, [])]),
- ?line false =
+ false =
lists:member(mk_node(NcpC, M), rpc:call(CpA, erlang, nodes, [])),
- ?line false =
+ false =
lists:member(mk_node(NcpC, M), rpc:call(CpB, erlang, nodes, [])),
- ?line
?UNTIL(begin
TestGG4a = rpc:call(CpA, global, whereis_name, [test]),
TestGG4b = rpc:call(CpB, global, whereis_name, [test]),
@@ -3148,171 +3086,171 @@ global_groups_change(Config) ->
(TestGG5 =:= TestGG5e)
end),
- ?line Info1 = rpc:call(Cp1, global_group, info, []),
- ?line Info2 = rpc:call(Cp2, global_group, info, []),
- ?line Info3 = rpc:call(Cp3, global_group, info, []),
- ?line InfoA = rpc:call(CpA, global_group, info, []),
- ?line InfoB = rpc:call(CpB, global_group, info, []),
- ?line InfoC = rpc:call(CpC, global_group, info, []),
- ?line InfoD = rpc:call(CpD, global_group, info, []),
- ?line InfoE = rpc:call(CpE, global_group, info, []),
- ?line ?t:format( "#### Info1 ~p~n",[Info1]),
- ?line ?t:format( "#### Info2 ~p~n",[Info2]),
- ?line ?t:format( "#### Info3 ~p~n",[Info3]),
- ?line ?t:format( "#### InfoA ~p~n",[InfoA]),
- ?line ?t:format( "#### InfoB ~p~n",[InfoB]),
- ?line ?t:format( "#### InfoC ~p~n",[InfoC]),
- ?line ?t:format( "#### InfoD ~p~n",[InfoD]),
- ?line ?t:format( "#### InfoE ~p~n",[InfoE]),
-
- ?line {global_groups, GGNodes} = NewNG,
-
- ?line Info1ok = [{state, synced},
- {own_group_name, gg1},
- {own_group_nodes, GG1},
- {synced_nodes, [mk_node(Ncp2, M)]},
- {sync_error, []},
- {no_contact, [mk_node(Ncp5, M)]},
- {other_groups, remove_gg_pub_type(lists:keydelete
- (gg1, 1, GGNodes))},
- {monitoring, []}],
-
-
- ?line Info2ok = [{state, synced},
- {own_group_name, gg1},
- {own_group_nodes, GG1},
- {synced_nodes, [mk_node(Ncp1, M)]},
- {sync_error, []},
- {no_contact, [mk_node(Ncp5, M)]},
- {other_groups, remove_gg_pub_type(lists:keydelete
- (gg1, 1, GGNodes))},
- {monitoring, []}],
-
- ?line Info3ok = [{state, synced},
- {own_group_name, gg2},
- {own_group_nodes, GG2},
- {synced_nodes, []},
- {sync_error, []},
- {no_contact, []},
- {other_groups, remove_gg_pub_type(lists:keydelete
- (gg2, 1, GGNodes))},
- {monitoring, []}],
-
- ?line InfoAok = [{state, synced},
- {own_group_name, gg4},
- {own_group_nodes, GG4},
- {synced_nodes, lists:delete(mk_node(NcpA, M), GG4)},
- {sync_error, []},
- {no_contact, []},
- {other_groups, remove_gg_pub_type(lists:keydelete
- (gg4, 1, GGNodes))},
- {monitoring, []}],
-
- ?line InfoBok = [{state, synced},
- {own_group_name, gg4},
- {own_group_nodes, GG4},
- {synced_nodes, lists:delete(mk_node(NcpB, M), GG4)},
- {sync_error, []},
- {no_contact, []},
- {other_groups, remove_gg_pub_type(lists:keydelete
- (gg4, 1, GGNodes))},
- {monitoring, []}],
-
- ?line InfoCok = [{state, synced},
- {own_group_name, gg5},
- {own_group_nodes, GG5},
- {synced_nodes, lists:delete(mk_node(NcpC, M), GG5)},
- {sync_error, []},
- {no_contact, []},
- {other_groups, remove_gg_pub_type(lists:keydelete
- (gg5, 1, GGNodes))},
- {monitoring, []}],
-
- ?line InfoDok = [{state, synced},
- {own_group_name, gg5},
- {own_group_nodes, GG5},
- {synced_nodes, lists:delete(mk_node(NcpD, M), GG5)},
- {sync_error, []},
- {no_contact, []},
- {other_groups, remove_gg_pub_type(lists:keydelete
- (gg5, 1, GGNodes))},
- {monitoring, []}],
-
- ?line InfoEok = [{state, synced},
- {own_group_name, gg5},
- {own_group_nodes, GG5},
- {synced_nodes, lists:delete(mk_node(NcpE, M), GG5)},
- {sync_error, []},
- {no_contact, []},
- {other_groups, remove_gg_pub_type(lists:keydelete
- (gg5, 1, GGNodes))},
- {monitoring, []}],
-
-
- ?line case Info1 of
- Info1ok ->
- ok;
- _ ->
- test_server:fail({{"could not change the global groups"
- " in node", Cp1}, {Info1, Info1ok}})
- end,
+ Info1 = rpc:call(Cp1, global_group, info, []),
+ Info2 = rpc:call(Cp2, global_group, info, []),
+ Info3 = rpc:call(Cp3, global_group, info, []),
+ InfoA = rpc:call(CpA, global_group, info, []),
+ InfoB = rpc:call(CpB, global_group, info, []),
+ InfoC = rpc:call(CpC, global_group, info, []),
+ InfoD = rpc:call(CpD, global_group, info, []),
+ InfoE = rpc:call(CpE, global_group, info, []),
+ io:format( "#### Info1 ~p~n",[Info1]),
+ io:format( "#### Info2 ~p~n",[Info2]),
+ io:format( "#### Info3 ~p~n",[Info3]),
+ io:format( "#### InfoA ~p~n",[InfoA]),
+ io:format( "#### InfoB ~p~n",[InfoB]),
+ io:format( "#### InfoC ~p~n",[InfoC]),
+ io:format( "#### InfoD ~p~n",[InfoD]),
+ io:format( "#### InfoE ~p~n",[InfoE]),
+
+ {global_groups, GGNodes} = NewNG,
+
+ Info1ok = [{state, synced},
+ {own_group_name, gg1},
+ {own_group_nodes, GG1},
+ {synced_nodes, [mk_node(Ncp2, M)]},
+ {sync_error, []},
+ {no_contact, [mk_node(Ncp5, M)]},
+ {other_groups, remove_gg_pub_type(lists:keydelete
+ (gg1, 1, GGNodes))},
+ {monitoring, []}],
+
+
+ Info2ok = [{state, synced},
+ {own_group_name, gg1},
+ {own_group_nodes, GG1},
+ {synced_nodes, [mk_node(Ncp1, M)]},
+ {sync_error, []},
+ {no_contact, [mk_node(Ncp5, M)]},
+ {other_groups, remove_gg_pub_type(lists:keydelete
+ (gg1, 1, GGNodes))},
+ {monitoring, []}],
+
+ Info3ok = [{state, synced},
+ {own_group_name, gg2},
+ {own_group_nodes, GG2},
+ {synced_nodes, []},
+ {sync_error, []},
+ {no_contact, []},
+ {other_groups, remove_gg_pub_type(lists:keydelete
+ (gg2, 1, GGNodes))},
+ {monitoring, []}],
+
+ InfoAok = [{state, synced},
+ {own_group_name, gg4},
+ {own_group_nodes, GG4},
+ {synced_nodes, lists:delete(mk_node(NcpA, M), GG4)},
+ {sync_error, []},
+ {no_contact, []},
+ {other_groups, remove_gg_pub_type(lists:keydelete
+ (gg4, 1, GGNodes))},
+ {monitoring, []}],
+
+ InfoBok = [{state, synced},
+ {own_group_name, gg4},
+ {own_group_nodes, GG4},
+ {synced_nodes, lists:delete(mk_node(NcpB, M), GG4)},
+ {sync_error, []},
+ {no_contact, []},
+ {other_groups, remove_gg_pub_type(lists:keydelete
+ (gg4, 1, GGNodes))},
+ {monitoring, []}],
+
+ InfoCok = [{state, synced},
+ {own_group_name, gg5},
+ {own_group_nodes, GG5},
+ {synced_nodes, lists:delete(mk_node(NcpC, M), GG5)},
+ {sync_error, []},
+ {no_contact, []},
+ {other_groups, remove_gg_pub_type(lists:keydelete
+ (gg5, 1, GGNodes))},
+ {monitoring, []}],
+
+ InfoDok = [{state, synced},
+ {own_group_name, gg5},
+ {own_group_nodes, GG5},
+ {synced_nodes, lists:delete(mk_node(NcpD, M), GG5)},
+ {sync_error, []},
+ {no_contact, []},
+ {other_groups, remove_gg_pub_type(lists:keydelete
+ (gg5, 1, GGNodes))},
+ {monitoring, []}],
+
+ InfoEok = [{state, synced},
+ {own_group_name, gg5},
+ {own_group_nodes, GG5},
+ {synced_nodes, lists:delete(mk_node(NcpE, M), GG5)},
+ {sync_error, []},
+ {no_contact, []},
+ {other_groups, remove_gg_pub_type(lists:keydelete
+ (gg5, 1, GGNodes))},
+ {monitoring, []}],
+
+
+ case Info1 of
+ Info1ok ->
+ ok;
+ _ ->
+ ct:fail({{"could not change the global groups"
+ " in node", Cp1}, {Info1, Info1ok}})
+ end,
- ?line case Info2 of
- Info2ok ->
- ok;
- _ ->
- test_server:fail({{"could not change the global groups"
- " in node", Cp2}, {Info2, Info2ok}})
- end,
+ case Info2 of
+ Info2ok ->
+ ok;
+ _ ->
+ ct:fail({{"could not change the global groups"
+ " in node", Cp2}, {Info2, Info2ok}})
+ end,
- ?line case Info3 of
- Info3ok ->
- ok;
- _ ->
- test_server:fail({{"could not change the global groups"
- " in node", Cp3}, {Info3, Info3ok}})
- end,
+ case Info3 of
+ Info3ok ->
+ ok;
+ _ ->
+ ct:fail({{"could not change the global groups"
+ " in node", Cp3}, {Info3, Info3ok}})
+ end,
- ?line case InfoA of
- InfoAok ->
- ok;
- _ ->
- test_server:fail({{"could not change the global groups"
- " in node", CpA}, {InfoA, InfoAok}})
- end,
+ case InfoA of
+ InfoAok ->
+ ok;
+ _ ->
+ ct:fail({{"could not change the global groups"
+ " in node", CpA}, {InfoA, InfoAok}})
+ end,
- ?line case InfoB of
- InfoBok ->
- ok;
- _ ->
- test_server:fail({{"could not change the global groups"
- " in node", CpB}, {InfoB, InfoBok}})
- end,
+ case InfoB of
+ InfoBok ->
+ ok;
+ _ ->
+ ct:fail({{"could not change the global groups"
+ " in node", CpB}, {InfoB, InfoBok}})
+ end,
- ?line case InfoC of
- InfoCok ->
- ok;
- _ ->
- test_server:fail({{"could not change the global groups"
- " in node", CpC}, {InfoC, InfoCok}})
- end,
+ case InfoC of
+ InfoCok ->
+ ok;
+ _ ->
+ ct:fail({{"could not change the global groups"
+ " in node", CpC}, {InfoC, InfoCok}})
+ end,
- ?line case InfoD of
- InfoDok ->
- ok;
- _ ->
- test_server:fail({{"could not change the global groups"
- " in node", CpD}, {InfoD, InfoDok}})
- end,
+ case InfoD of
+ InfoDok ->
+ ok;
+ _ ->
+ ct:fail({{"could not change the global groups"
+ " in node", CpD}, {InfoD, InfoDok}})
+ end,
- ?line case InfoE of
- InfoEok ->
- ok;
- _ ->
- test_server:fail({{"could not change the global groups"
- " in node", CpE}, {InfoE, InfoEok}})
- end,
+ case InfoE of
+ InfoEok ->
+ ok;
+ _ ->
+ ct:fail({{"could not change the global groups"
+ " in node", CpE}, {InfoE, InfoEok}})
+ end,
write_high_level_trace(Config), % no good since CpC was restarted
stop_node(Cp1),
@@ -3324,7 +3262,7 @@ global_groups_change(Config) ->
stop_node(CpD),
stop_node(CpE),
- ?line init_condition(Config),
+ init_condition(Config),
ok.
sync_and_wait(Node) ->
@@ -3354,43 +3292,43 @@ sync_and_wait(Node) ->
is_real_system(KernelVsn, StdlibVsn) ->
LibDir = code:lib_dir(),
filelib:is_dir(filename:join(LibDir, "kernel-" ++ KernelVsn))
- andalso
- filelib:is_dir(filename:join(LibDir, "stdlib-" ++ StdlibVsn)).
+ andalso
+ filelib:is_dir(filename:join(LibDir, "stdlib-" ++ StdlibVsn)).
create_script_dc(ScriptName) ->
- ?line Name = filename:join(".", ScriptName),
- ?line Apps = application_controller:which_applications(),
- ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
- ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
- ?line {ok,Fd} = file:open(Name ++ ".rel", [write]),
- ?line {_, Version} = init:script_id(),
- ?line io:format(Fd,
- "{release, {\"Test release 3\", \"~s\"}, \n"
- " {erts, \"4.4\"}, \n"
- " [{kernel, \"~s\"}, {stdlib, \"~s\"}]}.\n",
- [Version, KernelVer, StdlibVer]),
- ?line file:close(Fd),
+ Name = filename:join(".", ScriptName),
+ Apps = application_controller:which_applications(),
+ {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+ {ok,Fd} = file:open(Name ++ ".rel", [write]),
+ {_, Version} = init:script_id(),
+ io:format(Fd,
+ "{release, {\"Test release 3\", \"~s\"}, \n"
+ " {erts, \"4.4\"}, \n"
+ " [{kernel, \"~s\"}, {stdlib, \"~s\"}]}.\n",
+ [Version, KernelVer, StdlibVer]),
+ file:close(Fd),
{KernelVer, StdlibVer}.
%% Not used?
config_dc(Fd, Ncp1, Ncp2, Ncp3) ->
M = from($@, atom_to_list(node())),
io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s']},"
- "{sync_nodes_timeout, 1000},"
- "{global_groups, [{gg1, ['~s@~s', '~s@~s']},"
- " {gg2, ['~s@~s']}]}"
- " ]}].~n",
+ "{sync_nodes_timeout, 1000},"
+ "{global_groups, [{gg1, ['~s@~s', '~s@~s']},"
+ " {gg2, ['~s@~s']}]}"
+ " ]}].~n",
[Ncp1, M, Ncp2, M, Ncp3, M, Ncp1, M, Ncp2, M, Ncp3, M]).
config_dc1(Fd, Ncp1, Ncp2, Ncp3, NcpA, NcpB, NcpC, NcpD, NcpE) ->
M = from($@, atom_to_list(node())),
io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s','~s@~s','~s@~s','~s@~s','~s@~s','~s@~s']},"
- "{sync_nodes_timeout, 1000},"
- "{global_groups, [{gg1, ['~s@~s', '~s@~s']},"
- " {gg2, ['~s@~s']},"
- " {gg4, normal, ['~s@~s','~s@~s','~s@~s']},"
- " {gg5, hidden, ['~s@~s','~s@~s']}]}]}].~n",
+ "{sync_nodes_timeout, 1000},"
+ "{global_groups, [{gg1, ['~s@~s', '~s@~s']},"
+ " {gg2, ['~s@~s']},"
+ " {gg4, normal, ['~s@~s','~s@~s','~s@~s']},"
+ " {gg5, hidden, ['~s@~s','~s@~s']}]}]}].~n",
[Ncp1, M, Ncp2, M, Ncp3, M,
NcpA, M, NcpB, M, NcpC, M, NcpD, M, NcpE, M,
Ncp1, M, Ncp2, M,
@@ -3401,8 +3339,8 @@ config_dc1(Fd, Ncp1, Ncp2, Ncp3, NcpA, NcpB, NcpC, NcpD, NcpE) ->
config_dc2(Fd, NewGG, Ncp1, Ncp2, Ncp3) ->
M = from($@, atom_to_list(node())),
io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s']},"
- "{sync_nodes_timeout, 1000},"
- "~p]}].~n",
+ "{sync_nodes_timeout, 1000},"
+ "~p]}].~n",
[Ncp1, M, Ncp2, M, Ncp3, M, NewGG]).
@@ -3414,33 +3352,33 @@ from(_H, []) -> [].
other(A, [A, _B]) -> A;
other(_, [_A, B]) -> B.
-
+
%% this one runs at cp2
part1(Config, Main, Cp1, Cp3) ->
case catch begin
make_partition(Config, [Main, Cp1], [node(), Cp3]),
- ?line {_Pid, yes} = start_proc(test2),
- ?line {_Pid2, yes} = start_proc(test4)
+ {_Pid, yes} = start_proc(test2),
+ {_Pid2, yes} = start_proc(test4)
end of
{_, yes} -> ok; % w("ok", []);
{'EXIT', _R} ->
ok
- % w("global_SUITE line:~w: ~p", [?LINE, _R])
+ %% w("global_SUITE line:~w: ~p", [?LINE, _R])
end.
%% Runs at Cp2
part1_5(Config, Main, Cp1, Cp3) ->
case catch begin
make_partition(Config, [Main, Cp1], [node(), Cp3]),
- ?line {_Pid1, yes} = start_proc_basic(name12),
- ?line {_Pid2, yes} =
+ {_Pid1, yes} = start_proc_basic(name12),
+ {_Pid2, yes} =
rpc:call(Cp3, ?MODULE, start_proc_basic, [name03])
end of
{_, yes} -> ok; % w("ok", []);
{'EXIT', _R} ->
ok
- % w("global_SUITE line:~w: ~p", [?LINE, _R])
+ %% w("global_SUITE line:~w: ~p", [?LINE, _R])
end.
w(X,Y) ->
@@ -3451,7 +3389,7 @@ w(X,Y) ->
%% this one runs on one node in Part2
%% The partition is ready when is_ready_partition(Config) returns (true).
make_partition(Config, Part1, Part2) ->
- Dir = ?config(priv_dir, Config),
+ Dir = proplists:get_value(priv_dir, Config),
Ns = [begin
Name = lists:concat([atom_to_list(N),"_",msec(),".part"]),
File = filename:join([Dir, Name]),
@@ -3503,7 +3441,7 @@ is_ready_partition(Config) ->
true.
make_partition_file(Config) ->
- Dir = ?config(priv_dir, Config),
+ Dir = proplists:get_value(priv_dir, Config),
filename:join([Dir, atom_to_list(make_partition_done)]).
%% this one runs at cp3
@@ -3514,37 +3452,36 @@ part2(Config, Parent, Main, Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6) ->
part3(Config, Parent, Main, Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6) ->
make_partition(Config, [Main, Cp0, Cp1, Cp2], [Cp3, Cp4, Cp5, Cp6]),
start_procs(Parent, Cp4, Cp5, Cp6, Config),
- % Make Cp6 alone
- ?line rpc_cast(Cp5, ?MODULE, crash, [12000]),
- ?line rpc_cast(Cp6, ?MODULE, alone, [Cp0, Cp3]).
+ %% Make Cp6 alone
+ rpc_cast(Cp5, ?MODULE, crash, [12000]),
+ rpc_cast(Cp6, ?MODULE, alone, [Cp0, Cp3]).
start_procs(Parent, N1, N2, N3, Config) ->
S1 = lists:sort([N1, N2, N3]),
- ?line
?UNTIL(begin
NN = lists:sort(nodes()),
S1 =:= NN
end),
- ?line Pid3 = start_proc3(test1),
- ?line Pid4 = rpc:call(N1, ?MODULE, start_proc3, [test2]),
- ?line assert_pid(Pid4),
- ?line Pid5 = rpc:call(N2, ?MODULE, start_proc3, [test3]),
- ?line assert_pid(Pid5),
- ?line Pid6 = rpc:call(N3, ?MODULE, start_proc3, [test4]),
- ?line assert_pid(Pid6),
- ?line yes = global:register_name(test1, Pid3),
- ?line yes = global:register_name(test2, Pid4, {global, notify_all_name}),
- ?line yes = global:register_name(test3, Pid5, {global, random_notify_name}),
+ Pid3 = start_proc3(test1),
+ Pid4 = rpc:call(N1, ?MODULE, start_proc3, [test2]),
+ assert_pid(Pid4),
+ Pid5 = rpc:call(N2, ?MODULE, start_proc3, [test3]),
+ assert_pid(Pid5),
+ Pid6 = rpc:call(N3, ?MODULE, start_proc3, [test4]),
+ assert_pid(Pid6),
+ yes = global:register_name(test1, Pid3),
+ yes = global:register_name(test2, Pid4, {global, notify_all_name}),
+ yes = global:register_name(test3, Pid5, {global, random_notify_name}),
Resolve = fun(Name, Pid1, Pid2) ->
Parent ! {resolve_called, Name, node()},
{Min, Max} = minmax(Pid1, Pid2),
exit(Min, kill),
Max
end,
- ?line yes = global:register_name(test4, Pid6, Resolve).
+ yes = global:register_name(test4, Pid6, Resolve).
+
-
collect_resolves() -> cr(0).
cr(Res) ->
receive
@@ -3574,7 +3511,7 @@ start_proc() ->
receive
Pid -> Pid
end.
-
+
start_proc(Name) ->
Pid = spawn(?MODULE, p_init, [self(), Name]),
@@ -3618,7 +3555,7 @@ single_node(Time, Node, Config) ->
lists:foreach(fun(N) -> _ = erlang:disconnect_node(N) end, nodes()),
?UNTIL(get_known(node()) =:= [node()]),
spawn(?MODULE, init_2, []),
- test_server:sleep(Time - msec()),
+ ct:sleep(Time - msec()),
net_adm:ping(Node).
init_2() ->
@@ -3630,12 +3567,12 @@ loop_2() ->
receive
die -> ok
end.
-
+
msec() ->
msec(now()).
msec(T) ->
- element(1,T)*1000000000 + element(2,T)*1000 + element(3,T) div 1000.
+ element(1,T)*1000000000 + element(2,T)*1000 + element(3,T) div 1000.
assert_pid(Pid) ->
if
@@ -3680,13 +3617,15 @@ sreq(Pid, Msg) ->
alone(N1, N2) ->
lists:foreach(fun(Node) -> true = erlang:disconnect_node(Node) end,
nodes()),
- test_server:sleep(12000),
+ ct:sleep(12000),
net_adm:ping(N1),
net_adm:ping(N2),
yes = global:register_name(test5, self()).
crash(Time) ->
- test_server:sleep(Time),
+ %% ct:sleep/1 will not work because it calls a server process
+ %% that does not run on other nodes.
+ timer:sleep(Time),
erlang:halt().
loop() ->
@@ -3748,23 +3687,23 @@ pr_diff(Str, T0, T1) ->
{_, {H,M,S}} = calendar:time_difference(T0, T1),
((H*60+M)*60)+S
end,
- test_server:format(1,"~13s: ~w (diff: ~w)",[Str, T1, Diff]),
+ ct:pal(?HI_VERBOSITY,"~13s: ~w (diff: ~w)",[Str, T1, Diff]),
if
Diff > 100 ->
- test_server:format(1,"~s: ** LARGE DIFF ~w~n", [Str, Diff]);
+ io:format(1,"~s: ** LARGE DIFF ~w~n", [Str, Diff]);
true ->
ok
end.
-endif.
now_diff({A1,B1,C1},{A2,B2,C2}) ->
- C1-C2 + 1000000*((B1-B2) + 1000000*(A1-A2)).
+ C1-C2 + 1000000*((B1-B2) + 1000000*(A1-A2)).
start_node_boot(Name, Config, Boot) ->
Pa = filename:dirname(code:which(?MODULE)),
Res = test_server:start_node(Name, peer, [{args, " -pa " ++ Pa ++
- " -config " ++ Config ++
- " -boot " ++ atom_to_list(Boot)}]),
+ " -config " ++ Config ++
+ " -boot " ++ atom_to_list(Boot)}]),
record_started_node(Res).
%% Increase the timeout for when an upcoming connection is teared down
@@ -3790,13 +3729,13 @@ start_node(Name0, How, Args, Config) ->
Pa = filename:dirname(code:which(?MODULE)),
R = test_server:start_node(Name, How, [{args,
Args ++ " " ++
- "-kernel net_setuptime 100 "
-% "-noshell "
+ "-kernel net_setuptime 100 "
+ %% "-noshell "
"-pa " ++ Pa},
{linked, false}
-]),
+ ]),
%% {linked,false} only seems to work for slave nodes.
-% test_server:sleep(1000),
+ %% ct:sleep(1000),
record_started_node(R).
start_node_rel(Name0, Rel, Config) ->
@@ -3807,14 +3746,14 @@ start_node_rel(Name0, Rel, Config) ->
Rel when is_atom(Rel) ->
{[{release, atom_to_list(Rel)}], ""};
RelList ->
- {RelList, ""}
- end,
+ {RelList, ""}
+ end,
Env = [],
Pa = filename:dirname(code:which(?MODULE)),
Res = test_server:start_node(Name, peer,
[{args,
Compat ++
- " -kernel net_setuptime 100 "
+ " -kernel net_setuptime 100 "
" -pa " ++ Pa},
{erl, Release}] ++ Env),
record_started_node(Res).
@@ -3844,12 +3783,12 @@ stop_nodes(Nodes) ->
lists:foreach(fun(Node) -> stop_node(Node) end, Nodes).
stop_node(Node) ->
- ?line ?t:stop_node(Node).
+ test_server:stop_node(Node).
stop() ->
lists:foreach(fun(Node) ->
- ?t:stop_node(Node)
+ test_server:stop_node(Node)
end, nodes()).
dbg_logs(Name) -> dbg_logs(Name, ?NODES).
@@ -3857,44 +3796,41 @@ dbg_logs(Name) -> dbg_logs(Name, ?NODES).
dbg_logs(Name, Nodes) ->
lists:foreach(fun(N) ->
F = lists:concat([Name, ".log.", N, ".txt"]),
- ?line ok = sys:log_to_file({global_name_server, N}, F)
+ ok = sys:log_to_file({global_name_server, N}, F)
end, Nodes).
-global_lost_nodes(suite) ->
- [];
-global_lost_nodes(doc) ->
- ["Tests that locally loaded nodes do not loose contact with other nodes."];
+%% Tests that locally loaded nodes do not loose contact with other nodes.
global_lost_nodes(Config) when is_list(Config) ->
Timeout = 60,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
-
- ?line {ok, Node1} = start_node(node1, Config),
- ?line {ok, Node2} = start_node(node2, Config),
+ init_condition(Config),
+
+ {ok, Node1} = start_node(node1, Config),
+ {ok, Node2} = start_node(node2, Config),
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
- ?line io:format("Nodes: ~p", [nodes()]),
- ?line io:format("Nodes at node1: ~p",
- [rpc:call(Node1, erlang, nodes, [])]),
- ?line io:format("Nodes at node2: ~p",
- [rpc:call(Node2, erlang, nodes, [])]),
+ io:format("Nodes: ~p", [nodes()]),
+ io:format("Nodes at node1: ~p",
+ [rpc:call(Node1, erlang, nodes, [])]),
+ io:format("Nodes at node2: ~p",
+ [rpc:call(Node2, erlang, nodes, [])]),
- ?line rpc_cast(Node1, ?MODULE, global_load, [node_1,Node2,node_2]),
- ?line rpc_cast(Node2, ?MODULE, global_load, [node_2,Node1,node_1]),
+ rpc_cast(Node1, ?MODULE, global_load, [node_1,Node2,node_2]),
+ rpc_cast(Node2, ?MODULE, global_load, [node_2,Node1,node_1]),
lost_nodes_waiter(Node1, Node2),
write_high_level_trace(Config),
- ?line stop_node(Node1),
- ?line stop_node(Node2),
- ?line init_condition(Config),
+ stop_node(Node1),
+ stop_node(Node2),
+ init_condition(Config),
ok.
global_load(MyName, OtherNode, OtherName) ->
- ?line yes = global:register_name(MyName, self()),
+ yes = global:register_name(MyName, self()),
io:format("Registered ~p",[MyName]),
global_load1(OtherNode, OtherName, 0).
@@ -3902,32 +3838,32 @@ global_load1(_OtherNode, _OtherName, 2) ->
io:format("*** ~p giving up. No use.", [node()]),
init:stop();
global_load1(OtherNode, OtherName, Fails) ->
- test_server:sleep(1000),
- ?line case catch global:whereis_name(OtherName) of
- Pid when is_pid(Pid) ->
- io:format("~p says: ~p is still there.",
- [node(),OtherName]),
- global_load1(OtherNode, OtherName, Fails);
- Other ->
- io:format("~p says: ~p is lost (~p) Pinging.",
- [ node(), OtherName, Other]),
- case net_adm:ping(OtherNode) of
- pong ->
- io:format("Re-established contact to ~p",
- [OtherName]);
- pang ->
- io:format("PANIC! Other node is DEAD.", []),
- init:stop()
- end,
- global_load1(OtherNode, OtherName, Fails+1)
- end.
+ ct:sleep(1000),
+ case catch global:whereis_name(OtherName) of
+ Pid when is_pid(Pid) ->
+ io:format("~p says: ~p is still there.",
+ [node(),OtherName]),
+ global_load1(OtherNode, OtherName, Fails);
+ Other ->
+ io:format("~p says: ~p is lost (~p) Pinging.",
+ [ node(), OtherName, Other]),
+ case net_adm:ping(OtherNode) of
+ pong ->
+ io:format("Re-established contact to ~p",
+ [OtherName]);
+ pang ->
+ io:format("PANIC! Other node is DEAD.", []),
+ init:stop()
+ end,
+ global_load1(OtherNode, OtherName, Fails+1)
+ end.
lost_nodes_waiter(N1, N2) ->
- ?line net_kernel:monitor_nodes(true),
+ net_kernel:monitor_nodes(true),
receive
{nodedown, Node} when Node =:= N1 ; Node =:= N2 ->
io:format("~p went down!",[Node]),
- ?line ?t:fail("Node went down.")
+ ct:fail("Node went down.")
after 10000 ->
ok
end,
@@ -3935,36 +3871,33 @@ lost_nodes_waiter(N1, N2) ->
-mass_death(suite) ->
- [];
-mass_death(doc) ->
- ["Tests the simultaneous death of many processes with registered names"];
+%% Tests the simultaneous death of many processes with registered names.
mass_death(Config) when is_list(Config) ->
Timeout = 90,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line OrigNames = global:registered_names(),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
%% Start nodes
- ?line Cps = [cp1,cp2,cp3,cp4,cp5],
- ?line Nodes = [begin {ok, Node} = start_node(Cp, Config), Node end ||
- Cp <- Cps],
- ?line io:format("Nodes: ~p~n", [Nodes]),
- ?line Ns = lists:seq(1, 40),
+ Cps = [cp1,cp2,cp3,cp4,cp5],
+ Nodes = [begin {ok, Node} = start_node(Cp, Config), Node end ||
+ Cp <- Cps],
+ io:format("Nodes: ~p~n", [Nodes]),
+ Ns = lists:seq(1, 40),
%% Start processes with globally registered names on the nodes
- ?line {Pids,[]} = rpc:multicall(Nodes, ?MODULE, mass_spawn, [Ns]),
- ?line io:format("Pids: ~p~n", [Pids]),
+ {Pids,[]} = rpc:multicall(Nodes, ?MODULE, mass_spawn, [Ns]),
+ io:format("Pids: ~p~n", [Pids]),
%% Wait...
- ?line test_server:sleep(10000),
+ ct:sleep(10000),
%% Check the globally registered names
- ?line NewNames = global:registered_names(),
- ?line io:format("NewNames: ~p~n", [NewNames]),
- ?line Ndiff = lists:sort(NewNames--OrigNames),
- ?line io:format("Ndiff: ~p~n", [Ndiff]),
- ?line Ndiff = lists:sort(mass_names(Nodes, Ns)),
+ NewNames = global:registered_names(),
+ io:format("NewNames: ~p~n", [NewNames]),
+ Ndiff = lists:sort(NewNames--OrigNames),
+ io:format("Ndiff: ~p~n", [Ndiff]),
+ Ndiff = lists:sort(mass_names(Nodes, Ns)),
%%
%% Kill the root pids
- ?line lists:foreach(fun (Pid) -> Pid ! drop_dead end, Pids),
+ lists:foreach(fun (Pid) -> Pid ! drop_dead end, Pids),
%% Start probing and wait for all registered names to disappear
{YYYY,MM,DD} = date(),
{H,M,S} = time(),
@@ -3973,22 +3906,21 @@ mass_death(Config) when is_list(Config) ->
wait_mass_death(Nodes, OrigNames, erlang:now(), Config).
wait_mass_death(Nodes, OrigNames, Then, Config) ->
- ?line Names = global:registered_names(),
- ?line
- case Names--OrigNames of
- [] ->
- ?line T = now_diff(erlang:now(), Then) div 1000,
- ?line lists:foreach(
- fun (Node) ->
- stop_node(Node)
- end, Nodes),
- ?line init_condition(Config),
- {comment,lists:flatten(io_lib:format("~.3f s~n", [T/1000.0]))};
- Ndiff ->
- ?line io:format("Ndiff: ~p~n", [Ndiff]),
- ?line test_server:sleep(1000),
- ?line wait_mass_death(Nodes, OrigNames, Then, Config)
- end.
+ Names = global:registered_names(),
+ case Names--OrigNames of
+ [] ->
+ T = now_diff(erlang:now(), Then) div 1000,
+ lists:foreach(
+ fun (Node) ->
+ stop_node(Node)
+ end, Nodes),
+ init_condition(Config),
+ {comment,lists:flatten(io_lib:format("~.3f s~n", [T/1000.0]))};
+ Ndiff ->
+ io:format("Ndiff: ~p~n", [Ndiff]),
+ ct:sleep(1000),
+ wait_mass_death(Nodes, OrigNames, Then, Config)
+ end.
mass_spawn([]) ->
ok;
@@ -4018,7 +3950,7 @@ mass_name(Node, N) ->
start_nodes(L, How, Config) ->
start_nodes2(L, How, 0, Config),
Nodes = collect_nodes(0, length(L)),
- ?line ?UNTIL([] =:= Nodes -- nodes()),
+ ?UNTIL([] =:= Nodes -- nodes()),
put(?nodes_tag, Nodes),
%% Pinging doesn't help, we have to wait too, for nodes() to become
%% correct on the other node.
@@ -4042,7 +3974,7 @@ verify_nodes(Nodes, Config) ->
verify_nodes([], _N, _Config) ->
[];
verify_nodes([Node | Rest], N, Config) ->
- ?line ?UNTIL(
+ ?UNTIL(
case rpc:call(Node, erlang, nodes, []) of
Nodes when is_list(Nodes) ->
case N =:= lists:sort([Node | Nodes]) of
@@ -4074,7 +4006,7 @@ start_nodes2([Name | Rest], How, N, Config) ->
Self ! {N, R},
%% sleeping is necessary, or with peer nodes, they will
%% go down again, despite {linked, false}.
- test_server:sleep(100000)
+ ct:sleep(100000)
end),
start_nodes2(Rest, How, N+1, Config).
@@ -4155,14 +4087,12 @@ remove_gg_pub_type([{GG, _, Nodes}|Rest]) ->
%% Better do this in a slave node.
%% (The transition from links to monitors does not affect this case.)
-garbage_messages(suite) ->
- [];
garbage_messages(Config) when is_list(Config) ->
Timeout = 25,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
- ?line init_condition(Config),
- ?line [Slave] = start_nodes([garbage_messages], slave, Config),
+ init_condition(Config),
+ [Slave] = start_nodes([garbage_messages], slave, Config),
Fun = fun() ->
{links,L} = process_info(whereis(global_name_server), links),
lists:foreach(fun(Pid) -> Pid ! {garbage,to,you} end, L),
@@ -4170,15 +4100,15 @@ garbage_messages(Config) when is_list(Config) ->
_Any -> ok
end
end,
- ?line Pid = spawn_link(Slave, erlang, apply, [Fun,[]]),
- ?t:sleep(2000),
- ?line Global = rpc:call(Slave, erlang, whereis, [global_name_server]),
- ?line {registered_name,global_name_server} =
+ Pid = spawn_link(Slave, erlang, apply, [Fun,[]]),
+ ct:sleep(2000),
+ Global = rpc:call(Slave, erlang, whereis, [global_name_server]),
+ {registered_name,global_name_server} =
rpc:call(Slave, erlang, process_info, [Global,registered_name]),
- ?line true = unlink(Pid),
+ true = unlink(Pid),
write_high_level_trace(Config),
- ?line stop_node(Slave),
- ?line init_condition(Config),
+ stop_node(Slave),
+ init_condition(Config),
ok.
wait_for_ready_net(Config) ->
@@ -4186,13 +4116,13 @@ wait_for_ready_net(Config) ->
wait_for_ready_net(Nodes0, Config) ->
Nodes = lists:sort(Nodes0),
- ?t:format("wait_for_ready_net ~p~n", [Nodes]),
+ io:format("wait_for_ready_net ~p~n", [Nodes]),
?UNTIL(begin
lists:all(fun(N) -> Nodes =:= get_known(N) end, Nodes) and
- lists:all(fun(N) ->
- LNs = rpc:call(N, erlang, nodes, []),
- Nodes =:= lists:sort([N | LNs])
- end, Nodes)
+ lists:all(fun(N) ->
+ LNs = rpc:call(N, erlang, nodes, []),
+ Nodes =:= lists:sort([N | LNs])
+ end, Nodes)
end).
get_known(Node) ->
@@ -4207,7 +4137,7 @@ quite_a_few_nodes(Max) ->
N = try
ulimit("ulimit -u")
catch _:_ ->
- ulimit("ulimit -p") % can fail...
+ ulimit("ulimit -p") % can fail...
end,
lists:min([(N - 40) div 3, Max]).
@@ -4264,15 +4194,15 @@ start_tracer() ->
Pid = spawn(fun() -> tracer([]) end),
case catch register(my_tracer, Pid) of
{'EXIT', _} ->
- ?t:fail(re_register_my_tracer);
+ ct:fail(re_register_my_tracer);
_ ->
ok
end.
tracer(L) ->
receive
- % {save, Term} ->
- % tracer([{now(),Term} | L]);
+ %% {save, Term} ->
+ %% tracer([{now(),Term} | L]);
{get, From} ->
From ! {trace, lists:reverse(L)},
tracer([]);
@@ -4305,7 +4235,7 @@ collect_tracers(Nodes) ->
trace_message(M) ->
case catch my_tracer ! M of
{'EXIT', _} ->
- ?t:fail(my_tracer_not_registered);
+ ct:fail(my_tracer_not_registered);
_ ->
ok
end.
diff --git a/lib/kernel/test/global_group_SUITE.erl b/lib/kernel/test/global_group_SUITE.erl
index 0a994c3bf0..8b9e1c5ae8 100644
--- a/lib/kernel/test/global_group_SUITE.erl
+++ b/lib/kernel/test/global_group_SUITE.erl
@@ -28,15 +28,17 @@
-export([init_per_testcase/2, end_per_testcase/2]).
-%-compile(export_all).
+%%-compile(export_all).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(NODES, [node()|nodes()]).
-define(UNTIL(Seq), loop_until_true(fun() -> Seq end)).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,5}}].
all() ->
[start_gg_proc, no_gg_proc, no_gg_proc_sync, compatible,
@@ -46,10 +48,10 @@ groups() ->
[].
init_per_group(_GroupName, Config) ->
- Config.
+ Config.
end_per_group(_GroupName, Config) ->
- Config.
+ Config.
init_per_suite(Config) ->
@@ -77,15 +79,13 @@ end_per_suite(_Config) ->
ok.
-define(TESTCASE, testcase_name).
--define(testcase, ?config(?TESTCASE, Config)).
+-define(testcase, proplists:get_value(?TESTCASE, Config)).
-init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog=?t:timetrap(?t:minutes(5)),
- [{?TESTCASE, Case}, {watchdog, Dog}|Config].
+init_per_testcase(Case, Config) ->
+ Config.
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
+end_per_testcase(_Func, _Config) ->
+ ok.
%%-----------------------------------------------------------------
%% Test suites for global groups.
@@ -94,198 +94,191 @@ end_per_testcase(_Func, Config) ->
%%-----------------------------------------------------------------
-start_gg_proc(suite) -> [];
-start_gg_proc(doc) -> ["Check that the global_group processes are started automatically. "];
+%% Check that the global_group processes are started automatically. .
start_gg_proc(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(120)),
-
- ?line Dir = ?config(priv_dir, Config),
- ?line File = filename:join(Dir, "global_group.config"),
- ?line {ok, Fd}=file:open(File, [write]),
+ Dir = proplists:get_value(priv_dir, Config),
+ File = filename:join(Dir, "global_group.config"),
+ {ok, Fd}=file:open(File, [write]),
[Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config),
- ?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"),
+ config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"),
- ?line Cp1nn = node_at(Ncp1),
- ?line Cp2nn = node_at(Ncp2),
- ?line Cp3nn = node_at(Ncp3),
+ Cp1nn = node_at(Ncp1),
+ Cp2nn = node_at(Ncp2),
+ Cp3nn = node_at(Ncp3),
- ?line {ok, Cp1} = start_node(Ncp1, Config),
- ?line {ok, Cp2} = start_node(Ncp2, Config),
- ?line {ok, Cp3} = start_node(Ncp3, Config),
+ {ok, Cp1} = start_node(Ncp1, Config),
+ {ok, Cp2} = start_node(Ncp2, Config),
+ {ok, Cp3} = start_node(Ncp3, Config),
- ?line [] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]),
- ?line [] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]),
- ?line [] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]),
+ [] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]),
+ [] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]),
+ [] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]),
- % stop the nodes, and make sure names are released.
+ %% stop the nodes, and make sure names are released.
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
- ?line ?UNTIL(undefined =:= global:whereis_name(test)),
- ?line test_server:timetrap_cancel(Dog),
+ ?UNTIL(undefined =:= global:whereis_name(test)),
ok.
-
-no_gg_proc(suite) -> [];
-no_gg_proc(doc) -> ["Start a system without global groups. Nodes are not "
- "synced at start (sync_nodes_optional is not defined)"];
+
+%% Start a system without global groups. Nodes are not
+%% synced at start (sync_nodes_optional is not defined).
no_gg_proc(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(200)),
-
- ?line Dir = ?config(priv_dir, Config),
- ?line File = filename:join(Dir, "no_global_group.config"),
- ?line {ok, Fd} = file:open(File, [write]),
- ?line config_no(Fd),
-
- ?line NN = node_name(atom_to_list(node())),
- ?line Cp1nn = list_to_atom("cp1@" ++ NN),
- ?line Cp2nn = list_to_atom("cp2@" ++ NN),
- ?line Cp3nn = list_to_atom("cp3@" ++ NN),
- ?line Cpxnn = list_to_atom("cpx@" ++ NN),
- ?line Cpynn = list_to_atom("cpy@" ++ NN),
- ?line Cpznn = list_to_atom("cpz@" ++ NN),
-
- ?line {ok, Cp1} = start_node_no(cp1, Config),
- ?line {ok, Cp2} = start_node_no(cp2, Config),
- ?line {ok, Cp3} = start_node_no(cp3, Config),
- ?line {ok, Cpx} = start_node_no(cpx, Config),
- ?line {ok, Cpy} = start_node_no(cpy, Config),
- ?line {ok, Cpz} = start_node_no(cpz, Config),
+ Dir = proplists:get_value(priv_dir, Config),
+ File = filename:join(Dir, "no_global_group.config"),
+ {ok, Fd} = file:open(File, [write]),
+ config_no(Fd),
+
+ NN = node_name(atom_to_list(node())),
+ Cp1nn = list_to_atom("cp1@" ++ NN),
+ Cp2nn = list_to_atom("cp2@" ++ NN),
+ Cp3nn = list_to_atom("cp3@" ++ NN),
+ Cpxnn = list_to_atom("cpx@" ++ NN),
+ Cpynn = list_to_atom("cpy@" ++ NN),
+ Cpznn = list_to_atom("cpz@" ++ NN),
+
+ {ok, Cp1} = start_node_no(cp1, Config),
+ {ok, Cp2} = start_node_no(cp2, Config),
+ {ok, Cp3} = start_node_no(cp3, Config),
+ {ok, Cpx} = start_node_no(cpx, Config),
+ {ok, Cpy} = start_node_no(cpy, Config),
+ {ok, Cpz} = start_node_no(cpz, Config),
%% let the nodes know of each other
- ?line pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]),
- ?line pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]),
- ?line pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]),
- ?line pong = rpc:call(Cpx, net_adm, ping, [Cpynn]),
- ?line pong = rpc:call(Cpy, net_adm, ping, [Cpznn]),
+ pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]),
+ pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]),
+ pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cpynn]),
+ pong = rpc:call(Cpy, net_adm, ping, [Cpznn]),
- ?line wait_for_ready_net(),
+ wait_for_ready_net(),
- ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]),
- ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]),
- ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]),
- ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]),
- ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]),
- ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]),
+ [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]),
+ [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]),
+ [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]),
+ [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]),
+ [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]),
+ [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]),
- % start a proc and register it
- ?line {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]),
+ %% start a proc and register it
+ {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]),
- ?line RegNames = lists:sort([test2,test_server]),
+ RegNames = lists:sort([test2,test_server]),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}])),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}])),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}])),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}])),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}])),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}])),
- ?line undefined = rpc:call(Cp3, global_group, global_groups, []),
+ undefined = rpc:call(Cp3, global_group, global_groups, []),
+
+ Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn,
+ Cpxnn, Cpynn, Cpznn],
+ Own_nodes = rpc:call(Cp3, global_group, own_nodes, []),
+ [] = (Own_nodes -- Own_nodes_should),
+ [] = (Own_nodes_should -- Own_nodes),
+
+ Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]),
+ receive
+ {pong, Cp2} -> ok
+ after
+ 2000 -> ct:fail(timeout2)
+ end,
+ Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]),
+ receive
+ {pong, Cp2} -> ok
+ after
+ 2000 -> ct:fail(timeout3)
+ end,
+ Pid2 = rpc:call(Cpz, global_group, send, [test2, {ping, self()}]),
+ receive
+ {pong, Cp2} -> ok
+ after
+ 2000 -> ct:fail(timeout4)
+ end,
- ?line Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn,
- Cpxnn, Cpynn, Cpznn],
- ?line Own_nodes = rpc:call(Cp3, global_group, own_nodes, []),
- ?line [] = (Own_nodes -- Own_nodes_should),
- ?line [] = (Own_nodes_should -- Own_nodes),
-
- ?line Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]),
- ?line receive
- {pong, Cp2} -> ok
- after
- 2000 -> test_server:fail(timeout2)
- end,
- ?line Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]),
- ?line receive
- {pong, Cp2} -> ok
- after
- 2000 -> test_server:fail(timeout3)
- end,
- ?line Pid2 = rpc:call(Cpz, global_group, send, [test2, {ping, self()}]),
- ?line receive
- {pong, Cp2} -> ok
- after
- 2000 -> test_server:fail(timeout4)
- end,
-
-
- % start a proc and register it
- ?line {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]),
+
+ %% start a proc and register it
+ {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]),
%%------------------------------------
%% Test monitor nodes
%%------------------------------------
- ?line Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]),
- ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]),
+ Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]),
+ PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]),
- % Kill node Cp1
- ?line Pid2 =
+ %% Kill node Cp1
+ Pid2 =
rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cp1}]),
- ?line PidX =
+ PidX =
rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cp1}]),
- ?line test_server:sleep(100),
- ?line stop_node(Cp1),
- ?line test_server:sleep(1000),
-
- ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ct:sleep(100),
+ stop_node(Cp1),
+ ct:sleep(1000),
+
+ ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
- % Kill node Cpz
- ?line Pid2 =
+ %% Kill node Cpz
+ Pid2 =
rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cpz}]),
- ?line PidX =
+ PidX =
rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cpz}]),
- ?line test_server:sleep(100),
- ?line stop_node(Cpz),
- ?line test_server:sleep(1000),
-
- ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ct:sleep(100),
+ stop_node(Cpz),
+ ct:sleep(1000),
- % Restart node Cp1
- ?line Pid2 =
+ ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+
+ %% Restart node Cp1
+ Pid2 =
rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cp1}]),
- ?line PidX =
+ PidX =
rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cp1}]),
- ?line {ok, Cp1} = start_node_no(cp1, Config),
- ?line pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]),
- ?line pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]),
- ?line wait_for_ready_net(),
-
- ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ {ok, Cp1} = start_node_no(cp1, Config),
+ pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]),
+ wait_for_ready_net(),
- % Restart node Cpz
- ?line Pid2 =
+ ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+
+ %% Restart node Cpz
+ Pid2 =
rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cpz}]),
- ?line PidX =
+ PidX =
rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cpz}]),
- ?line {ok, Cpz} = start_node_no(cpz, Config),
- ?line pong = rpc:call(Cp2, net_adm, ping, [Cpznn]),
- ?line pong = rpc:call(Cpx, net_adm, ping, [Cpznn]),
- ?line wait_for_ready_net(),
-
- ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ {ok, Cpz} = start_node_no(cpz, Config),
+ pong = rpc:call(Cp2, net_adm, ping, [Cpznn]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cpznn]),
+ wait_for_ready_net(),
- % stop the nodes, and make sure names are released.
+ ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+
+ %% stop the nodes, and make sure names are released.
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
@@ -293,174 +286,169 @@ no_gg_proc(Config) when is_list(Config) ->
stop_node(Cpy),
stop_node(Cpz),
- ?line ?UNTIL(undefined =:= global:whereis_name(test)),
- ?line test_server:timetrap_cancel(Dog),
+ ?UNTIL(undefined =:= global:whereis_name(test)),
ok.
-
-no_gg_proc_sync(suite) -> [];
-no_gg_proc_sync(doc) ->
- ["Start a system without global groups, but syncing the nodes by using "
- "sync_nodes_optional."];
-no_gg_proc_sync(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(200)),
- ?line Dir = ?config(priv_dir, Config),
- ?line File = filename:join(Dir, "no_global_group_sync.config"),
- ?line {ok, Fd} = file:open(File, [write]),
+%% Start a system without global groups, but syncing the nodes by using
+%% sync_nodes_optional.
+no_gg_proc_sync(Config) when is_list(Config) ->
+ Dir = proplists:get_value(priv_dir, Config),
+ File = filename:join(Dir, "no_global_group_sync.config"),
+ {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz] =
node_names([cp1,cp2,cp3,cpx,cpy,cpz], Config),
- ?line config_sync(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz),
-
- ?line Cp1nn = node_at(Ncp1),
- ?line Cp2nn = node_at(Ncp2),
- ?line Cp3nn = node_at(Ncp3),
- ?line Cpxnn = node_at(Ncpx),
- ?line Cpynn = node_at(Ncpy),
- ?line Cpznn = node_at(Ncpz),
-
- ?line {ok, Cp1} = start_node_no2(Ncp1, Config),
- ?line {ok, Cp2} = start_node_no2(Ncp2, Config),
- ?line {ok, Cp3} = start_node_no2(Ncp3, Config),
- ?line {ok, Cpx} = start_node_no2(Ncpx, Config),
- ?line {ok, Cpy} = start_node_no2(Ncpy, Config),
- ?line {ok, Cpz} = start_node_no2(Ncpz, Config),
+ config_sync(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz),
+
+ Cp1nn = node_at(Ncp1),
+ Cp2nn = node_at(Ncp2),
+ Cp3nn = node_at(Ncp3),
+ Cpxnn = node_at(Ncpx),
+ Cpynn = node_at(Ncpy),
+ Cpznn = node_at(Ncpz),
+
+ {ok, Cp1} = start_node_no2(Ncp1, Config),
+ {ok, Cp2} = start_node_no2(Ncp2, Config),
+ {ok, Cp3} = start_node_no2(Ncp3, Config),
+ {ok, Cpx} = start_node_no2(Ncpx, Config),
+ {ok, Cpy} = start_node_no2(Ncpy, Config),
+ {ok, Cpz} = start_node_no2(Ncpz, Config),
%% let the nodes know of each other
- ?line pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]),
- ?line pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]),
- ?line pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]),
- ?line pong = rpc:call(Cpx, net_adm, ping, [Cpynn]),
- ?line pong = rpc:call(Cpy, net_adm, ping, [Cpznn]),
+ pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]),
+ pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]),
+ pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cpynn]),
+ pong = rpc:call(Cpy, net_adm, ping, [Cpznn]),
- ?line wait_for_ready_net(),
+ wait_for_ready_net(),
- ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]),
- ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]),
- ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]),
- ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]),
- ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]),
- ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]),
+ [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]),
+ [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]),
+ [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]),
+ [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]),
+ [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]),
+ [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]),
- % start a proc and register it
- ?line {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]),
+ %% start a proc and register it
+ {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]),
- ?line RegNames = lists:sort([test2,test_server]),
+ RegNames = lists:sort([test2,test_server]),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}])),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}])),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}])),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}])),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}])),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}])),
- ?line undefined = rpc:call(Cp3, global_group, global_groups, []),
+ undefined = rpc:call(Cp3, global_group, global_groups, []),
- ?line Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn,
- Cpxnn, Cpynn, Cpznn],
- ?line Own_nodes = rpc:call(Cp3, global_group, own_nodes, []),
- ?line [] = (Own_nodes -- Own_nodes_should),
- ?line [] = (Own_nodes_should -- Own_nodes),
-
- ?line Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]),
- ?line receive
- {pong, Cp2} -> ok
- after
- 2000 -> test_server:fail(timeout2)
- end,
- ?line Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]),
- ?line receive
- {pong, Cp2} -> ok
- after
- 2000 -> test_server:fail(timeout3)
- end,
- ?line Pid2 = rpc:call(Cpz, global_group, send, [test2, {ping, self()}]),
- ?line receive
- {pong, Cp2} -> ok
- after
- 2000 -> test_server:fail(timeout4)
- end,
-
-
- % start a proc and register it
- ?line {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]),
+ Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn,
+ Cpxnn, Cpynn, Cpznn],
+ Own_nodes = rpc:call(Cp3, global_group, own_nodes, []),
+ [] = (Own_nodes -- Own_nodes_should),
+ [] = (Own_nodes_should -- Own_nodes),
+
+ Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]),
+ receive
+ {pong, Cp2} -> ok
+ after
+ 2000 -> ct:fail(timeout2)
+ end,
+ Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]),
+ receive
+ {pong, Cp2} -> ok
+ after
+ 2000 -> ct:fail(timeout3)
+ end,
+ Pid2 = rpc:call(Cpz, global_group, send, [test2, {ping, self()}]),
+ receive
+ {pong, Cp2} -> ok
+ after
+ 2000 -> ct:fail(timeout4)
+ end,
+
+
+ %% start a proc and register it
+ {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]),
%%------------------------------------
%% Test monitor nodes
%%------------------------------------
- ?line Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]),
- ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]),
+ Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]),
+ PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]),
- % Kill node Cp1
- ?line Pid2 =
+ %% Kill node Cp1
+ Pid2 =
rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cp1}]),
- ?line PidX =
+ PidX =
rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cp1}]),
- ?line test_server:sleep(100),
- ?line stop_node(Cp1),
- ?line test_server:sleep(1000),
-
- ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ct:sleep(100),
+ stop_node(Cp1),
+ ct:sleep(1000),
+
+ ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
- % Kill node Cpz
- ?line Pid2 =
+ %% Kill node Cpz
+ Pid2 =
rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cpz}]),
- ?line PidX =
+ PidX =
rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cpz}]),
- ?line test_server:sleep(100),
- ?line stop_node(Cpz),
- ?line test_server:sleep(1000),
-
- ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ct:sleep(100),
+ stop_node(Cpz),
+ ct:sleep(1000),
- % Restart node Cp1
- ?line Pid2 =
+ ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+
+ %% Restart node Cp1
+ Pid2 =
rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cp1}]),
- ?line PidX =
+ PidX =
rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cp1}]),
- ?line {ok, Cp1} = start_node_no2(Ncp1, Config),
- ?line pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]),
- ?line pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]),
- ?line wait_for_ready_net(),
-
- ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ {ok, Cp1} = start_node_no2(Ncp1, Config),
+ pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]),
+ wait_for_ready_net(),
- % Restart node Cpz
- ?line Pid2 =
+ ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+
+ %% Restart node Cpz
+ Pid2 =
rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cpz}]),
- ?line PidX =
+ PidX =
rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cpz}]),
- ?line {ok, Cpz} = start_node_no2(Ncpz, Config),
- ?line pong = rpc:call(Cp2, net_adm, ping, [Cpznn]),
- ?line pong = rpc:call(Cpx, net_adm, ping, [Cpznn]),
- ?line wait_for_ready_net(),
-
- ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ {ok, Cpz} = start_node_no2(Ncpz, Config),
+ pong = rpc:call(Cp2, net_adm, ping, [Cpznn]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cpznn]),
+ wait_for_ready_net(),
- % stop the nodes, and make sure names are released.
+ ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+
+ %% stop the nodes, and make sure names are released.
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
@@ -468,173 +456,168 @@ no_gg_proc_sync(Config) when is_list(Config) ->
stop_node(Cpy),
stop_node(Cpz),
- ?line ?UNTIL(undefined =:= global:whereis_name(test)),
- ?line test_server:timetrap_cancel(Dog),
+ ?UNTIL(undefined =:= global:whereis_name(test)),
ok.
-
-compatible(suite) -> [];
-compatible(doc) ->
- ["Check that a system without global groups is compatible with the old R4 system."];
-compatible(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(200)),
- ?line Dir = ?config(priv_dir, Config),
- ?line File = filename:join(Dir, "global_group_comp.config"),
- ?line {ok, Fd} = file:open(File, [write]),
+%% Check that a system without global groups is compatible with the old R4 system.
+compatible(Config) when is_list(Config) ->
+ Dir = proplists:get_value(priv_dir, Config),
+ File = filename:join(Dir, "global_group_comp.config"),
+ {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz] =
node_names([cp1,cp2,cp3,cpx,cpy,cpz], Config),
- ?line config_comp(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz),
-
- ?line Cp1nn = node_at(Ncp1),
- ?line Cp2nn = node_at(Ncp2),
- ?line Cp3nn = node_at(Ncp3),
- ?line Cpxnn = node_at(Ncpx),
- ?line Cpynn = node_at(Ncpy),
- ?line Cpznn = node_at(Ncpz),
-
- ?line {ok, Cp1} = start_node_comp(Ncp1, Config),
- ?line {ok, Cp2} = start_node_comp(Ncp2, Config),
- ?line {ok, Cp3} = start_node_comp(Ncp3, Config),
- ?line {ok, Cpx} = start_node_comp(Ncpx, Config),
- ?line {ok, Cpy} = start_node_comp(Ncpy, Config),
- ?line {ok, Cpz} = start_node_comp(Ncpz, Config),
+ config_comp(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz),
+
+ Cp1nn = node_at(Ncp1),
+ Cp2nn = node_at(Ncp2),
+ Cp3nn = node_at(Ncp3),
+ Cpxnn = node_at(Ncpx),
+ Cpynn = node_at(Ncpy),
+ Cpznn = node_at(Ncpz),
+
+ {ok, Cp1} = start_node_comp(Ncp1, Config),
+ {ok, Cp2} = start_node_comp(Ncp2, Config),
+ {ok, Cp3} = start_node_comp(Ncp3, Config),
+ {ok, Cpx} = start_node_comp(Ncpx, Config),
+ {ok, Cpy} = start_node_comp(Ncpy, Config),
+ {ok, Cpz} = start_node_comp(Ncpz, Config),
%% let the nodes know of each other
- ?line pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]),
- ?line pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]),
- ?line pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]),
- ?line pong = rpc:call(Cpx, net_adm, ping, [Cpynn]),
- ?line pong = rpc:call(Cpy, net_adm, ping, [Cpznn]),
+ pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]),
+ pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]),
+ pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cpynn]),
+ pong = rpc:call(Cpy, net_adm, ping, [Cpznn]),
- ?line wait_for_ready_net(),
+ wait_for_ready_net(),
- ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]),
- ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]),
- ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]),
- ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]),
- ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]),
- ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]),
+ [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]),
+ [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]),
+ [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]),
+ [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]),
+ [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]),
+ [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]),
- % start a proc and register it
- ?line {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]),
+ %% start a proc and register it
+ {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]),
- ?line RegNames = lists:sort([test2,test_server]),
+ RegNames = lists:sort([test2,test_server]),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}])),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}])),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}])),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}])),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}])),
- ?line RegNames =
+ RegNames =
lists:sort(
rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}])),
- ?line undefined = rpc:call(Cp3, global_group, global_groups, []),
+ undefined = rpc:call(Cp3, global_group, global_groups, []),
- ?line Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn,
- Cpxnn, Cpynn, Cpznn],
- ?line Own_nodes = rpc:call(Cp3, global_group, own_nodes, []),
- ?line [] = (Own_nodes -- Own_nodes_should),
- ?line [] = (Own_nodes_should -- Own_nodes),
-
- ?line Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]),
- ?line receive
- {pong, Cp2} -> ok
- after
- 2000 -> test_server:fail(timeout2)
- end,
- ?line Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]),
- ?line receive
- {pong, Cp2} -> ok
- after
- 2000 -> test_server:fail(timeout3)
- end,
- ?line Pid2 = rpc:call(Cpz, global_group, send, [test2, {ping, self()}]),
- ?line receive
- {pong, Cp2} -> ok
- after
- 2000 -> test_server:fail(timeout4)
- end,
-
-
- % start a proc and register it
- ?line {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]),
+ Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn,
+ Cpxnn, Cpynn, Cpznn],
+ Own_nodes = rpc:call(Cp3, global_group, own_nodes, []),
+ [] = (Own_nodes -- Own_nodes_should),
+ [] = (Own_nodes_should -- Own_nodes),
+
+ Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]),
+ receive
+ {pong, Cp2} -> ok
+ after
+ 2000 -> ct:fail(timeout2)
+ end,
+ Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]),
+ receive
+ {pong, Cp2} -> ok
+ after
+ 2000 -> ct:fail(timeout3)
+ end,
+ Pid2 = rpc:call(Cpz, global_group, send, [test2, {ping, self()}]),
+ receive
+ {pong, Cp2} -> ok
+ after
+ 2000 -> ct:fail(timeout4)
+ end,
+
+
+ %% start a proc and register it
+ {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]),
%%------------------------------------
%% Test monitor nodes
%%------------------------------------
- ?line Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]),
- ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]),
+ Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]),
+ PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]),
- % Kill node Cp1
- ?line Pid2 =
+ %% Kill node Cp1
+ Pid2 =
rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cp1}]),
- ?line PidX =
+ PidX =
rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cp1}]),
- ?line test_server:sleep(100),
- ?line stop_node(Cp1),
- ?line test_server:sleep(1000),
-
- ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ct:sleep(100),
+ stop_node(Cp1),
+ ct:sleep(1000),
+
+ ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
- % Kill node Cpz
- ?line Pid2 =
+ %% Kill node Cpz
+ Pid2 =
rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cpz}]),
- ?line PidX =
+ PidX =
rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cpz}]),
- ?line test_server:sleep(100),
- ?line stop_node(Cpz),
- ?line test_server:sleep(1000),
-
- ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ct:sleep(100),
+ stop_node(Cpz),
+ ct:sleep(1000),
+
+ ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
- % Restart node Cp1
- ?line Pid2 =
+ %% Restart node Cp1
+ Pid2 =
rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cp1}]),
- ?line PidX =
+ PidX =
rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cp1}]),
- ?line {ok, Cp1} = start_node_comp(Ncp1, Config),
- ?line pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]),
- ?line pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]),
- ?line wait_for_ready_net(),
-
- ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ {ok, Cp1} = start_node_comp(Ncp1, Config),
+ pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]),
+ wait_for_ready_net(),
+
+ ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
- % Restart node Cpz
- ?line Pid2 =
+ %% Restart node Cpz
+ Pid2 =
rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cpz}]),
- ?line PidX =
+ PidX =
rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cpz}]),
- ?line {ok, Cpz} = start_node_comp(Ncpz, Config),
- ?line pong = rpc:call(Cp2, net_adm, ping, [Cpznn]),
- ?line pong = rpc:call(Cpx, net_adm, ping, [Cpznn]),
- ?line wait_for_ready_net(),
-
- ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ {ok, Cpz} = start_node_comp(Ncpz, Config),
+ pong = rpc:call(Cp2, net_adm, ping, [Cpznn]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cpznn]),
+ wait_for_ready_net(),
+
+ ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
- % stop the nodes, and make sure names are released.
+ %% stop the nodes, and make sure names are released.
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
@@ -642,147 +625,137 @@ compatible(Config) when is_list(Config) ->
stop_node(Cpy),
stop_node(Cpz),
- ?line ?UNTIL(undefined =:= global:whereis_name(test)),
- ?line test_server:timetrap_cancel(Dog),
+ ?UNTIL(undefined =:= global:whereis_name(test)),
ok.
-
-one_grp(suite) -> [];
-one_grp(doc) -> ["Test a system with only one global group. "];
-one_grp(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(120)),
- ?line Dir = ?config(priv_dir, Config),
- ?line File = filename:join(Dir, "global_group.config"),
- ?line {ok, Fd} = file:open(File, [write]),
+%% Test a system with only one global group. .
+one_grp(Config) when is_list(Config) ->
+ Dir = proplists:get_value(priv_dir, Config),
+ File = filename:join(Dir, "global_group.config"),
+ {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config),
- ?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"),
+ config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"),
- ?line {ok, Cp1} = start_node(Ncp1, Config),
- ?line {ok, Cp2} = start_node(Ncp2, Config),
- ?line {ok, Cp3} = start_node(Ncp3, Config),
+ {ok, Cp1} = start_node(Ncp1, Config),
+ {ok, Cp2} = start_node(Ncp2, Config),
+ {ok, Cp3} = start_node(Ncp3, Config),
- % sleep a while to make the global_group to sync...
- test_server:sleep(1000),
+ %% sleep a while to make the global_group to sync...
+ ct:sleep(1000),
- % start a proc and register it
- ?line {Pid, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]),
+ %% start a proc and register it
+ {Pid, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]),
- % test that it is registered at all nodes
- ?line Pid = rpc:call(Cp1, global, whereis_name, [test]),
- ?line Pid = rpc:call(Cp2, global, whereis_name, [test]),
- ?line Pid = rpc:call(Cp3, global, whereis_name, [test]),
+ %% test that it is registered at all nodes
+ Pid = rpc:call(Cp1, global, whereis_name, [test]),
+ Pid = rpc:call(Cp2, global, whereis_name, [test]),
+ Pid = rpc:call(Cp3, global, whereis_name, [test]),
- % try to register the same name
- ?line no = rpc:call(Cp1, global, register_name, [test, self()]),
+ %% try to register the same name
+ no = rpc:call(Cp1, global, register_name, [test, self()]),
- % let process exit, check that it is unregistered automatically
+ %% let process exit, check that it is unregistered automatically
Pid ! die,
- ?line
- ?UNTIL(begin
+ ?UNTIL(begin
(undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and
(undefined =:= rpc:call(Cp2, global, whereis_name, [test])) and
(undefined =:= rpc:call(Cp3, global, whereis_name, [test]))
end),
- % test re_register
- ?line {Pid2, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]),
- ?line Pid2 = rpc:call(Cp3, global, whereis_name, [test]),
+ %% test re_register
+ {Pid2, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]),
+ Pid2 = rpc:call(Cp3, global, whereis_name, [test]),
Pid3 = rpc:call(Cp3, ?MODULE, start_proc_rereg, [test]),
- ?line Pid3 = rpc:call(Cp3, global, whereis_name, [test]),
+ Pid3 = rpc:call(Cp3, global, whereis_name, [test]),
- % test sending
+ %% test sending
rpc:call(Cp1, global, send, [test, {ping, self()}]),
receive
{pong, Cp3} -> ok
after
- 2000 -> test_server:fail(timeout1)
+ 2000 -> ct:fail(timeout1)
end,
rpc:call(Cp3, global, send, [test, {ping, self()}]),
receive
{pong, Cp3} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
- ?line rpc:call(Cp3, global, unregister_name, [test]),
- ?line undefined = rpc:call(Cp1, global, whereis_name, [test]),
- ?line undefined = rpc:call(Cp2, global, whereis_name, [test]),
- ?line undefined = rpc:call(Cp3, global, whereis_name, [test]),
+ rpc:call(Cp3, global, unregister_name, [test]),
+ undefined = rpc:call(Cp1, global, whereis_name, [test]),
+ undefined = rpc:call(Cp2, global, whereis_name, [test]),
+ undefined = rpc:call(Cp3, global, whereis_name, [test]),
Pid3 ! die,
- ?line ?UNTIL(undefined =:= rpc:call(Cp3, global, whereis_name, [test])),
+ ?UNTIL(undefined =:= rpc:call(Cp3, global, whereis_name, [test])),
- % register a proc
- ?line {_, yes} = rpc:call(Cp3, ?MODULE, start_proc, [test]),
+ %% register a proc
+ {_, yes} = rpc:call(Cp3, ?MODULE, start_proc, [test]),
- % stop the nodes, and make sure names are released.
+ %% stop the nodes, and make sure names are released.
stop_node(Cp3),
- ?line ?UNTIL(undefined =:= rpc:call(Cp1, global, whereis_name, [test])),
+ ?UNTIL(undefined =:= rpc:call(Cp1, global, whereis_name, [test])),
Pid2 ! die,
stop_node(Cp1),
stop_node(Cp2),
- ?line test_server:timetrap_cancel(Dog),
ok.
-
-one_grp_x(suite) -> [];
-one_grp_x(doc) -> ["Check a system with only one global group. "
- "Start the nodes with different time intervals. "];
-one_grp_x(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(120)),
- ?line Dir = ?config(priv_dir, Config),
- ?line File = filename:join(Dir, "global_group.config"),
- ?line {ok, Fd} = file:open(File, [write]),
+%% Check a system with only one global group.
+%% Start the nodes with different time intervals.
+one_grp_x(Config) when is_list(Config) ->
+ Dir = proplists:get_value(priv_dir, Config),
+ File = filename:join(Dir, "global_group.config"),
+ {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config),
- ?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"),
+ config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"),
- ?line {ok, Cp1} = start_node(Ncp1, Config),
- % sleep a while to make the global_group to sync...
- test_server:sleep(1000),
+ {ok, Cp1} = start_node(Ncp1, Config),
+ %% sleep a while to make the global_group to sync...
+ ct:sleep(1000),
- % start a proc and register it
- ?line {Pid, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]),
+ %% start a proc and register it
+ {Pid, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]),
- ?line {ok, Cp2} = start_node(Ncp2, Config),
- % sleep a while to make the global_group to sync...
- test_server:sleep(1000),
+ {ok, Cp2} = start_node(Ncp2, Config),
+ %% sleep a while to make the global_group to sync...
+ ct:sleep(1000),
- % test that it is registered at all nodes
- ?line Pid = rpc:call(Cp1, global, whereis_name, [test]),
- ?line Pid = rpc:call(Cp2, global, whereis_name, [test]),
+ %% test that it is registered at all nodes
+ Pid = rpc:call(Cp1, global, whereis_name, [test]),
+ Pid = rpc:call(Cp2, global, whereis_name, [test]),
- ?line {ok, Cp3} = start_node(Ncp3, Config),
- % sleep a while to make the global_group to sync...
- test_server:sleep(1000),
+ {ok, Cp3} = start_node(Ncp3, Config),
+ %% sleep a while to make the global_group to sync...
+ ct:sleep(1000),
- ?line Pid = rpc:call(Cp3, global, whereis_name, [test]),
+ Pid = rpc:call(Cp3, global, whereis_name, [test]),
- % try to register the same name
- ?line no = rpc:call(Cp1, global, register_name, [test, self()]),
+ %% try to register the same name
+ no = rpc:call(Cp1, global, register_name, [test, self()]),
- % let process exit, check that it is unregistered automatically
+ %% let process exit, check that it is unregistered automatically
Pid ! die,
- ?line
- ?UNTIL(begin
+ ?UNTIL(begin
(undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and
(undefined =:= rpc:call(Cp2, global, whereis_name, [test])) and
(undefined =:= rpc:call(Cp3, global, whereis_name, [test]))
end),
- % test re_register
- ?line {Pid2, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]),
- ?line Pid2 = rpc:call(Cp3, global, whereis_name, [test]),
+ %% test re_register
+ {Pid2, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]),
+ Pid2 = rpc:call(Cp3, global, whereis_name, [test]),
Pid2 ! die,
@@ -790,296 +763,291 @@ one_grp_x(Config) when is_list(Config) ->
stop_node(Cp2),
stop_node(Cp3),
- ?line test_server:timetrap_cancel(Dog),
ok.
-
-two_grp(suite) -> [];
-two_grp(doc) -> ["Test a two global group system. "];
-two_grp(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(200)),
- ?line Dir = ?config(priv_dir, Config),
- ?line File = filename:join(Dir, "global_group.config"),
- ?line {ok, Fd} = file:open(File, [write]),
+%% Test a two global group system. .
+two_grp(Config) when is_list(Config) ->
+ Dir = proplists:get_value(priv_dir, Config),
+ File = filename:join(Dir, "global_group.config"),
+ {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Ncpq] =
node_names([cp1,cp2,cp3,cpx,cpy,cpz,cpq], Config),
- ?line config(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq),
-
- ?line Cp1nn = node_at(Ncp1),
- ?line Cp2nn = node_at(Ncp2),
- ?line Cp3nn = node_at(Ncp3),
- ?line Cpxnn = node_at(Ncpx),
- ?line Cpynn = node_at(Ncpy),
- ?line Cpznn = node_at(Ncpz),
-
- ?line {ok, Cp1} = start_node(Ncp1, Config),
- ?line {ok, Cp2} = start_node(Ncp2, Config),
- ?line {ok, Cp3} = start_node(Ncp3, Config),
- ?line {ok, Cpx} = start_node(Ncpx, Config),
- ?line {ok, Cpy} = start_node(Ncpy, Config),
- ?line {ok, Cpz} = start_node(Ncpz, Config),
+ config(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq),
+
+ Cp1nn = node_at(Ncp1),
+ Cp2nn = node_at(Ncp2),
+ Cp3nn = node_at(Ncp3),
+ Cpxnn = node_at(Ncpx),
+ Cpynn = node_at(Ncpy),
+ Cpznn = node_at(Ncpz),
+
+ {ok, Cp1} = start_node(Ncp1, Config),
+ {ok, Cp2} = start_node(Ncp2, Config),
+ {ok, Cp3} = start_node(Ncp3, Config),
+ {ok, Cpx} = start_node(Ncpx, Config),
+ {ok, Cpy} = start_node(Ncpy, Config),
+ {ok, Cpz} = start_node(Ncpz, Config),
%% The groups (cpq not started):
%% [{nc1, [cp1,cp2,cp3]}, {nc2, [cpx,cpy,cpz]}, {nc3, [cpq]}]
- % sleep a while to make the global_groups to sync...
- test_server:sleep(1000),
-
- % check the global group names
- ?line {nc1, [nc2, nc3]} = rpc:call(Cp1, global_group, global_groups, []),
- ?line {nc1, [nc2, nc3]} = rpc:call(Cp2, global_group, global_groups, []),
- ?line {nc1, [nc2, nc3]} = rpc:call(Cp3, global_group, global_groups, []),
- ?line {nc2, [nc1, nc3]} = rpc:call(Cpx, global_group, global_groups, []),
- ?line {nc2, [nc1, nc3]} = rpc:call(Cpy, global_group, global_groups, []),
- ?line {nc2, [nc1, nc3]} = rpc:call(Cpz, global_group, global_groups, []),
-
- % check the global group nodes
- ?line [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp1, global_group, own_nodes, []),
- ?line [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp2, global_group, own_nodes, []),
- ?line [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp3, global_group, own_nodes, []),
- ?line [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpx, global_group, own_nodes, []),
- ?line [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpy, global_group, own_nodes, []),
- ?line [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpz, global_group, own_nodes, []),
-
-
- % start a proc and register it
- ?line {Pid1, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]),
-
- ?line Pid1 = rpc:call(Cp1, global_group, send, [test, {io, from_cp1}]),
- ?line Pid1 = rpc:call(Cpx, global_group, send, [test, {io, from_cpx}]),
- ?line Pid1 = rpc:call(Cp1, global_group, send, [{group,nc1}, test,
- {io, from_cp1}]),
- ?line [test] =
+ %% sleep a while to make the global_groups to sync...
+ ct:sleep(1000),
+
+ %% check the global group names
+ {nc1, [nc2, nc3]} = rpc:call(Cp1, global_group, global_groups, []),
+ {nc1, [nc2, nc3]} = rpc:call(Cp2, global_group, global_groups, []),
+ {nc1, [nc2, nc3]} = rpc:call(Cp3, global_group, global_groups, []),
+ {nc2, [nc1, nc3]} = rpc:call(Cpx, global_group, global_groups, []),
+ {nc2, [nc1, nc3]} = rpc:call(Cpy, global_group, global_groups, []),
+ {nc2, [nc1, nc3]} = rpc:call(Cpz, global_group, global_groups, []),
+
+ %% check the global group nodes
+ [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp1, global_group, own_nodes, []),
+ [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp2, global_group, own_nodes, []),
+ [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp3, global_group, own_nodes, []),
+ [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpx, global_group, own_nodes, []),
+ [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpy, global_group, own_nodes, []),
+ [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpz, global_group, own_nodes, []),
+
+
+ %% start a proc and register it
+ {Pid1, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]),
+
+ Pid1 = rpc:call(Cp1, global_group, send, [test, {io, from_cp1}]),
+ Pid1 = rpc:call(Cpx, global_group, send, [test, {io, from_cpx}]),
+ Pid1 = rpc:call(Cp1, global_group, send, [{group,nc1}, test,
+ {io, from_cp1}]),
+ [test] =
rpc:call(Cpx, global_group, registered_names, [{node, Cp1nn}]),
- ?line [test] =
+ [test] =
rpc:call(Cpx, global_group, registered_names, [{group, nc1}]),
- ?line [] = rpc:call(Cpx, global_group, registered_names, [{node, Cpxnn}]),
- ?line [] = rpc:call(Cpx, global_group, registered_names, [{group, nc2}]),
- ?line Pid1 = rpc:call(Cpx, global_group, send, [{group,nc1}, test,
- {io, from_cp1}]),
- ?line {badarg,{test,{io,from_cpx}}} =
+ [] = rpc:call(Cpx, global_group, registered_names, [{node, Cpxnn}]),
+ [] = rpc:call(Cpx, global_group, registered_names, [{group, nc2}]),
+ Pid1 = rpc:call(Cpx, global_group, send, [{group,nc1}, test,
+ {io, from_cp1}]),
+ {badarg,{test,{io,from_cpx}}} =
rpc:call(Cp1, global_group, send, [{group,nc2}, test, {io, from_cpx}]),
- ?line {badarg,{test,{io,from_cpx}}} =
+ {badarg,{test,{io,from_cpx}}} =
rpc:call(Cpx, global_group, send, [{group,nc2}, test, {io, from_cpx}]),
- % test that it is registered at all nodes
- ?line Pid1 = rpc:call(Cp1, global, whereis_name, [test]),
- ?line Pid1 = rpc:call(Cp2, global, whereis_name, [test]),
- ?line Pid1 = rpc:call(Cp3, global, whereis_name, [test]),
- ?line undefined = rpc:call(Cpx, global, whereis_name, [test]),
- ?line undefined = rpc:call(Cpy, global, whereis_name, [test]),
- ?line undefined = rpc:call(Cpz, global, whereis_name, [test]),
-
- % start a proc and register it
- ?line {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]),
-
- % test that it is registered at all nodes
- ?line Pid1 = rpc:call(Cp1, global, whereis_name, [test]),
- ?line Pid1 = rpc:call(Cp2, global, whereis_name, [test]),
- ?line Pid1 = rpc:call(Cp3, global, whereis_name, [test]),
- ?line PidX = rpc:call(Cpx, global, whereis_name, [test]),
- ?line PidX = rpc:call(Cpy, global, whereis_name, [test]),
- ?line PidX = rpc:call(Cpz, global, whereis_name, [test]),
-
+ %% test that it is registered at all nodes
+ Pid1 = rpc:call(Cp1, global, whereis_name, [test]),
+ Pid1 = rpc:call(Cp2, global, whereis_name, [test]),
+ Pid1 = rpc:call(Cp3, global, whereis_name, [test]),
+ undefined = rpc:call(Cpx, global, whereis_name, [test]),
+ undefined = rpc:call(Cpy, global, whereis_name, [test]),
+ undefined = rpc:call(Cpz, global, whereis_name, [test]),
+
+ %% start a proc and register it
+ {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]),
+
+ %% test that it is registered at all nodes
+ Pid1 = rpc:call(Cp1, global, whereis_name, [test]),
+ Pid1 = rpc:call(Cp2, global, whereis_name, [test]),
+ Pid1 = rpc:call(Cp3, global, whereis_name, [test]),
+ PidX = rpc:call(Cpx, global, whereis_name, [test]),
+ PidX = rpc:call(Cpy, global, whereis_name, [test]),
+ PidX = rpc:call(Cpz, global, whereis_name, [test]),
+
Pid1 ! die,
%% If we don't wait for global on other nodes to have updated its
%% tables, 'test' may still be defined at the point when it is
%% tested a few lines below.
- ?line
- ?UNTIL(begin
+ ?UNTIL(begin
Pid = rpc:call(Cp2, global, whereis_name, [test]),
undefined =:= Pid
end),
- % start a proc and register it
- ?line {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]),
+ %% start a proc and register it
+ {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]),
+
+ %% test that it is registered at all nodes
+ Pid2 = rpc:call(Cp1, global, whereis_name, [test2]),
+ Pid2 = rpc:call(Cp2, global, whereis_name, [test2]),
+ Pid2 = rpc:call(Cp3, global, whereis_name, [test2]),
+ PidX = rpc:call(Cpx, global, whereis_name, [test]),
+ PidX = rpc:call(Cpy, global, whereis_name, [test]),
+ PidX = rpc:call(Cpz, global, whereis_name, [test]),
+
+ undefined = rpc:call(Cp1, global, whereis_name, [test]),
+ undefined = rpc:call(Cp2, global, whereis_name, [test]),
+ undefined = rpc:call(Cp3, global, whereis_name, [test]),
+ undefined = rpc:call(Cpx, global, whereis_name, [test2]),
+ undefined = rpc:call(Cpy, global, whereis_name, [test2]),
+ undefined = rpc:call(Cpz, global, whereis_name, [test2]),
- % test that it is registered at all nodes
- ?line Pid2 = rpc:call(Cp1, global, whereis_name, [test2]),
- ?line Pid2 = rpc:call(Cp2, global, whereis_name, [test2]),
- ?line Pid2 = rpc:call(Cp3, global, whereis_name, [test2]),
- ?line PidX = rpc:call(Cpx, global, whereis_name, [test]),
- ?line PidX = rpc:call(Cpy, global, whereis_name, [test]),
- ?line PidX = rpc:call(Cpz, global, whereis_name, [test]),
-
- ?line undefined = rpc:call(Cp1, global, whereis_name, [test]),
- ?line undefined = rpc:call(Cp2, global, whereis_name, [test]),
- ?line undefined = rpc:call(Cp3, global, whereis_name, [test]),
- ?line undefined = rpc:call(Cpx, global, whereis_name, [test2]),
- ?line undefined = rpc:call(Cpy, global, whereis_name, [test2]),
- ?line undefined = rpc:call(Cpz, global, whereis_name, [test2]),
-
- ?line Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]),
+ Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]),
receive
{pong, Cp2} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
- ?line Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]),
+ Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]),
receive
{pong, Cp2} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
- ?line Pid2 = rpc:call(Cp3, global_group, send, [test2, {ping, self()}]),
+ Pid2 = rpc:call(Cp3, global_group, send, [test2, {ping, self()}]),
receive
{pong, Cp2} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
- ?line PidX = rpc:call(Cpx, global_group, send, [test, {ping, self()}]),
+ PidX = rpc:call(Cpx, global_group, send, [test, {ping, self()}]),
receive
{pong, Cpx} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
- ?line PidX = rpc:call(Cpy, global_group, send, [test, {ping, self()}]),
+ PidX = rpc:call(Cpy, global_group, send, [test, {ping, self()}]),
receive
{pong, Cpx} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
- ?line PidX = rpc:call(Cpz, global_group, send, [test, {ping, self()}]),
+ PidX = rpc:call(Cpz, global_group, send, [test, {ping, self()}]),
receive
{pong, Cpx} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
- ?line Pid2 = rpc:call(Cpx, global_group, send, [{node, Cp1nn}, test2,
- {ping, self()}]),
+ Pid2 = rpc:call(Cpx, global_group, send, [{node, Cp1nn}, test2,
+ {ping, self()}]),
receive
{pong, Cp2} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
- ?line Pid2 = rpc:call(Cpy, global_group, send, [{node, Cp2nn}, test2,
- {ping, self()}]),
+ Pid2 = rpc:call(Cpy, global_group, send, [{node, Cp2nn}, test2,
+ {ping, self()}]),
receive
{pong, Cp2} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
- ?line Pid2 = rpc:call(Cpz, global_group, send, [{node, Cp3nn}, test2,
- {ping, self()}]),
+ Pid2 = rpc:call(Cpz, global_group, send, [{node, Cp3nn}, test2,
+ {ping, self()}]),
receive
{pong, Cp2} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
- ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpznn}, test,
- {ping, self()}]),
+ PidX = rpc:call(Cpx, global_group, send, [{node, Cpznn}, test,
+ {ping, self()}]),
receive
{pong, Cpx} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
- ?line PidX = rpc:call(Cpy, global_group, send, [{node, Cpxnn}, test,
- {ping, self()}]),
+ PidX = rpc:call(Cpy, global_group, send, [{node, Cpxnn}, test,
+ {ping, self()}]),
receive
{pong, Cpx} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
- ?line PidX = rpc:call(Cpz, global_group, send, [{node, Cpynn}, test,
- {ping, self()}]),
+ PidX = rpc:call(Cpz, global_group, send, [{node, Cpynn}, test,
+ {ping, self()}]),
receive
{pong, Cpx} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
- ?line Pid2 = rpc:call(Cpx, global_group, send, [{group, nc1}, test2,
- {ping, self()}]),
+ Pid2 = rpc:call(Cpx, global_group, send, [{group, nc1}, test2,
+ {ping, self()}]),
receive
{pong, Cp2} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
- ?line PidX = rpc:call(Cpy, global_group, send, [{group, nc2}, test,
- {ping, self()}]),
+ PidX = rpc:call(Cpy, global_group, send, [{group, nc2}, test,
+ {ping, self()}]),
receive
{pong, Cpx} -> ok
after
- 2000 -> test_server:fail(timeout2)
+ 2000 -> ct:fail(timeout2)
end,
%%------------------------------------
%% Test monitor nodes
%%------------------------------------
- ?line Pid2 =
+ Pid2 =
rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]),
- ?line PidX =
+ PidX =
rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]),
- % Kill node Cp1
- ?line Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2,
- {wait_nodedown, Cp1}]),
- ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test,
- {wait_nodedown, Cp1}]),
- ?line test_server:sleep(100),
- ?line stop_node(Cp1),
- ?line test_server:sleep(1000),
-
- ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop_nodedown),
- ?line PidX =
+ %% Kill node Cp1
+ Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2,
+ {wait_nodedown, Cp1}]),
+ PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test,
+ {wait_nodedown, Cp1}]),
+ ct:sleep(100),
+ stop_node(Cp1),
+ ct:sleep(1000),
+
+ ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpxnn, test, PidX, loop_nodedown),
+ PidX =
rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, to_loop]),
- % Kill node Cpz
- ?line Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2,
- {wait_nodedown, Cpz}]),
- ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test,
- {wait_nodedown, Cpz}]),
- ?line test_server:sleep(100),
- ?line stop_node(Cpz),
- ?line test_server:sleep(1000),
-
- ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop_nodedown),
- ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
- ?line Pid2 =
+ %% Kill node Cpz
+ Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2,
+ {wait_nodedown, Cpz}]),
+ PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test,
+ {wait_nodedown, Cpz}]),
+ ct:sleep(100),
+ stop_node(Cpz),
+ ct:sleep(1000),
+
+ ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop_nodedown),
+ ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ Pid2 =
rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, to_loop]),
- % Restart node Cp1
- ?line [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp2, global_group, own_nodes, []),
- ?line Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2,
- {wait_nodeup, Cp1}]),
- ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test,
- {wait_nodeup, Cp1}]),
- ?line test_server:sleep(100),
- ?line {ok, Cp1} = start_node(Ncp1, Config),
- ?line test_server:sleep(5000),
-
- ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop_nodeup),
- ?line PidX =
+ %% Restart node Cp1
+ [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp2, global_group, own_nodes, []),
+ Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2,
+ {wait_nodeup, Cp1}]),
+ PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test,
+ {wait_nodeup, Cp1}]),
+ ct:sleep(100),
+ {ok, Cp1} = start_node(Ncp1, Config),
+ ct:sleep(5000),
+
+ ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpxnn, test, PidX, loop_nodeup),
+ PidX =
rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, to_loop]),
- % Restart node Cpz
- ?line Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2,
- {wait_nodeup, Cpz}]),
- ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test,
- {wait_nodeup, Cpz}]),
- ?line test_server:sleep(100),
- ?line {ok, Cpz} = start_node(Ncpz, Config),
- ?line test_server:sleep(5000),
-
- ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop_nodeup),
- ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
- ?line Pid2 =
+ %% Restart node Cpz
+ Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2,
+ {wait_nodeup, Cpz}]),
+ PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test,
+ {wait_nodeup, Cpz}]),
+ ct:sleep(100),
+ {ok, Cpz} = start_node(Ncpz, Config),
+ ct:sleep(5000),
+
+ ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop_nodeup),
+ ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ Pid2 =
rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, to_loop]),
@@ -1093,72 +1061,68 @@ two_grp(Config) when is_list(Config) ->
stop_node(Cpy),
stop_node(Cpz),
- ?line test_server:timetrap_cancel(Dog),
ok.
-
-hidden_groups(suite) -> [];
-hidden_groups(doc) -> ["Test hidden global groups."];
-hidden_groups(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(200)),
- ?line Dir = ?config(priv_dir, Config),
- ?line File = filename:join(Dir, "global_group.config"),
- ?line {ok, Fd} = file:open(File, [write]),
+%% Test hidden global groups.
+hidden_groups(Config) when is_list(Config) ->
+ Dir = proplists:get_value(priv_dir, Config),
+ File = filename:join(Dir, "global_group.config"),
+ {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Ncpq] =
node_names([cp1,cp2,cp3,cpx,cpy,cpz,cpq], Config),
- ?line config_hidden(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq),
-
- ?line {ok, Cp1} = start_node(Ncp1, Config),
- ?line {ok, Cp2} = start_node(Ncp2, Config),
- ?line {ok, Cp3} = start_node(Ncp3, Config),
- ?line {ok, Cpx} = start_node(Ncpx, Config),
- ?line {ok, Cpy} = start_node(Ncpy, Config),
- ?line {ok, Cpz} = start_node(Ncpz, Config),
- ?line {ok, Cpq} = start_node(Ncpq, Config),
-
- % sleep a while to make the global_groups to sync...
- test_server:sleep(1000),
-
- % check the global group names
- ?line {nc1, [nc2, nc3]} = rpc:call(Cp1, global_group, global_groups, []),
- ?line {nc1, [nc2, nc3]} = rpc:call(Cp2, global_group, global_groups, []),
- ?line {nc1, [nc2, nc3]} = rpc:call(Cp3, global_group, global_groups, []),
- ?line {nc2, [nc1, nc3]} = rpc:call(Cpx, global_group, global_groups, []),
- ?line {nc2, [nc1, nc3]} = rpc:call(Cpy, global_group, global_groups, []),
- ?line {nc2, [nc1, nc3]} = rpc:call(Cpz, global_group, global_groups, []),
-
- % check the global group nodes
- ?line [Cp1, Cp2, Cp3] = rpc:call(Cp1, global_group, own_nodes, []),
- ?line [Cp1, Cp2, Cp3] = rpc:call(Cp2, global_group, own_nodes, []),
- ?line [Cp1, Cp2, Cp3] = rpc:call(Cp3, global_group, own_nodes, []),
- ?line [Cpx, Cpy, Cpz] = rpc:call(Cpx, global_group, own_nodes, []),
- ?line [Cpx, Cpy, Cpz] = rpc:call(Cpy, global_group, own_nodes, []),
- ?line [Cpx, Cpy, Cpz] = rpc:call(Cpz, global_group, own_nodes, []),
- ?line [Cpq] = rpc:call(Cpq, global_group, own_nodes, []),
-
- % Make some inter group connections
- ?line pong = rpc:call(Cp1, net_adm, ping, [Cpx]),
- ?line pong = rpc:call(Cpy, net_adm, ping, [Cp2]),
- ?line pong = rpc:call(Cp3, net_adm, ping, [Cpx]),
- ?line pong = rpc:call(Cpz, net_adm, ping, [Cp3]),
- ?line pong = rpc:call(Cpq, net_adm, ping, [Cp1]),
- ?line pong = rpc:call(Cpz, net_adm, ping, [Cpq]),
-
- % Check that no inter group connections are visible
+ config_hidden(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq),
+
+ {ok, Cp1} = start_node(Ncp1, Config),
+ {ok, Cp2} = start_node(Ncp2, Config),
+ {ok, Cp3} = start_node(Ncp3, Config),
+ {ok, Cpx} = start_node(Ncpx, Config),
+ {ok, Cpy} = start_node(Ncpy, Config),
+ {ok, Cpz} = start_node(Ncpz, Config),
+ {ok, Cpq} = start_node(Ncpq, Config),
+
+ %% sleep a while to make the global_groups to sync...
+ ct:sleep(1000),
+
+ %% check the global group names
+ {nc1, [nc2, nc3]} = rpc:call(Cp1, global_group, global_groups, []),
+ {nc1, [nc2, nc3]} = rpc:call(Cp2, global_group, global_groups, []),
+ {nc1, [nc2, nc3]} = rpc:call(Cp3, global_group, global_groups, []),
+ {nc2, [nc1, nc3]} = rpc:call(Cpx, global_group, global_groups, []),
+ {nc2, [nc1, nc3]} = rpc:call(Cpy, global_group, global_groups, []),
+ {nc2, [nc1, nc3]} = rpc:call(Cpz, global_group, global_groups, []),
+
+ %% check the global group nodes
+ [Cp1, Cp2, Cp3] = rpc:call(Cp1, global_group, own_nodes, []),
+ [Cp1, Cp2, Cp3] = rpc:call(Cp2, global_group, own_nodes, []),
+ [Cp1, Cp2, Cp3] = rpc:call(Cp3, global_group, own_nodes, []),
+ [Cpx, Cpy, Cpz] = rpc:call(Cpx, global_group, own_nodes, []),
+ [Cpx, Cpy, Cpz] = rpc:call(Cpy, global_group, own_nodes, []),
+ [Cpx, Cpy, Cpz] = rpc:call(Cpz, global_group, own_nodes, []),
+ [Cpq] = rpc:call(Cpq, global_group, own_nodes, []),
+
+ %% Make some inter group connections
+ pong = rpc:call(Cp1, net_adm, ping, [Cpx]),
+ pong = rpc:call(Cpy, net_adm, ping, [Cp2]),
+ pong = rpc:call(Cp3, net_adm, ping, [Cpx]),
+ pong = rpc:call(Cpz, net_adm, ping, [Cp3]),
+ pong = rpc:call(Cpq, net_adm, ping, [Cp1]),
+ pong = rpc:call(Cpz, net_adm, ping, [Cpq]),
+
+ %% Check that no inter group connections are visible
NC1Nodes = lists:sort([Cp1, Cp2, Cp3]),
NC2Nodes = lists:sort([Cpx, Cpy, Cpz]),
- ?line NC1Nodes = lists:sort([Cp1|rpc:call(Cp1, erlang, nodes, [])]),
- ?line NC1Nodes = lists:sort([Cp2|rpc:call(Cp2, erlang, nodes, [])]),
- ?line NC1Nodes = lists:sort([Cp3|rpc:call(Cp3, erlang, nodes, [])]),
- ?line NC2Nodes = lists:sort([Cpx|rpc:call(Cpx, erlang, nodes, [])]),
- ?line NC2Nodes = lists:sort([Cpy|rpc:call(Cpy, erlang, nodes, [])]),
- ?line NC2Nodes = lists:sort([Cpz|rpc:call(Cpz, erlang, nodes, [])]),
+ NC1Nodes = lists:sort([Cp1|rpc:call(Cp1, erlang, nodes, [])]),
+ NC1Nodes = lists:sort([Cp2|rpc:call(Cp2, erlang, nodes, [])]),
+ NC1Nodes = lists:sort([Cp3|rpc:call(Cp3, erlang, nodes, [])]),
+ NC2Nodes = lists:sort([Cpx|rpc:call(Cpx, erlang, nodes, [])]),
+ NC2Nodes = lists:sort([Cpy|rpc:call(Cpy, erlang, nodes, [])]),
+ NC2Nodes = lists:sort([Cpz|rpc:call(Cpz, erlang, nodes, [])]),
NC12Nodes = lists:append(NC1Nodes, NC2Nodes),
- ?line false = lists:any(fun(N) -> lists:member(N, NC12Nodes) end,
- rpc:call(Cpq, erlang, nodes, [])),
+ false = lists:any(fun(N) -> lists:member(N, NC12Nodes) end,
+ rpc:call(Cpq, erlang, nodes, [])),
stop_node(Cp1),
@@ -1169,63 +1133,58 @@ hidden_groups(Config) when is_list(Config) ->
stop_node(Cpz),
stop_node(Cpq),
- ?line test_server:timetrap_cancel(Dog),
ok.
-
-test_exit(suite) -> [];
-test_exit(doc) -> ["Checks when the search process exits. "];
-test_exit(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(120)),
- ?line NN = node_name(atom_to_list(node())),
- ?line Cp1nn = list_to_atom("cp1@" ++ NN),
+%% Checks when the search process exits. .
+test_exit(Config) when is_list(Config) ->
+ NN = node_name(atom_to_list(node())),
+ Cp1nn = list_to_atom("cp1@" ++ NN),
- ?line {ok, Cp1} = start_node(cp1, Config),
- ?line {ok, Cp2} = start_node(cp2, Config),
- ?line {ok, Cp3} = start_node(cp3, Config),
+ {ok, Cp1} = start_node(cp1, Config),
+ {ok, Cp2} = start_node(cp2, Config),
+ {ok, Cp3} = start_node(cp3, Config),
- test_server:sleep(1000),
+ ct:sleep(1000),
- ?line {error, illegal_function_call} =
+ {error, illegal_function_call} =
rpc:call(Cp1, global_group, registered_names_test, [{node, Cp1nn}]),
- ?line {badarg,_} =
+ {badarg,_} =
rpc:call(Cp1, global_group, send, [king, "The message"]),
- ?line undefined = rpc:call(Cp1, global_group, whereis_name, [king]),
+ undefined = rpc:call(Cp1, global_group, whereis_name, [king]),
- % stop the nodes, and make sure names are released.
+ %% stop the nodes, and make sure names are released.
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
- % sleep to let the nodes die
- test_server:sleep(1000),
+ %% sleep to let the nodes die
+ ct:sleep(1000),
- ?line test_server:timetrap_cancel(Dog),
ok.
-
+
start_node(Name, Config) ->
Pa=filename:dirname(code:which(?MODULE)),
- Dir=?config(priv_dir, Config),
+ Dir=proplists:get_value(priv_dir, Config),
ConfFile = " -config " ++ filename:join(Dir, "global_group"),
test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ ConfFile}]).
start_node_no(Name, Config) ->
Pa=filename:dirname(code:which(?MODULE)),
- Dir=?config(priv_dir, Config),
+ Dir=proplists:get_value(priv_dir, Config),
ConfFile = " -config " ++ filename:join(Dir, "no_global_group"),
test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ ConfFile}]).
start_node_no2(Name, Config) ->
Pa=filename:dirname(code:which(?MODULE)),
- Dir=?config(priv_dir, Config),
+ Dir=proplists:get_value(priv_dir, Config),
ConfFile = " -config " ++ filename:join(Dir, "no_global_group_sync"),
test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ ConfFile}]).
start_node_comp(Name, Config) ->
Pa=filename:dirname(code:which(?MODULE)),
- Dir=?config(priv_dir, Config),
+ Dir=proplists:get_value(priv_dir, Config),
ConfFile = " -config " ++ filename:join(Dir, "global_group_comp"),
test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ ConfFile}]).
@@ -1242,17 +1201,17 @@ node_name(Name, Config) ->
lists:concat([Name,U,?testcase,U,Pid,U,U,L]).
stop_node(Node) ->
- ?t:stop_node(Node).
+ test_server:stop_node(Node).
wait_for_ready_net() ->
Nodes = lists:sort(?NODES),
?UNTIL(begin
lists:all(fun(N) -> Nodes =:= get_known(N) end, Nodes) and
- lists:all(fun(N) ->
- LNs = rpc:call(N, erlang, nodes, []),
- Nodes =:= lists:sort([N | LNs])
- end, Nodes)
+ lists:all(fun(N) ->
+ LNs = rpc:call(N, erlang, nodes, []),
+ Nodes =:= lists:sort([N | LNs])
+ end, Nodes)
end).
get_known(Node) ->
@@ -1262,11 +1221,11 @@ get_known(Node) ->
config_hidden(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq) ->
M = from($@, atom_to_list(node())),
io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s', "
- " '~s@~s','~s@~s','~s@~s']},"
- "{sync_nodes_timeout, 1000},"
- "{global_groups, [{nc1, hidden, ['~s@~s','~s@~s','~s@~s']}, "
- "{nc2, hidden, ['~s@~s','~s@~s','~s@~s']}, "
- "{nc3, normal, ['~s@~s']}]} ] }]. ~n",
+ " '~s@~s','~s@~s','~s@~s']},"
+ "{sync_nodes_timeout, 1000},"
+ "{global_groups, [{nc1, hidden, ['~s@~s','~s@~s','~s@~s']}, "
+ "{nc2, hidden, ['~s@~s','~s@~s','~s@~s']}, "
+ "{nc3, normal, ['~s@~s']}]} ] }]. ~n",
[Ncp1, M, Ncp2, M, Ncp3, M,
Ncpx, M, Ncpy, M, Ncpz, M,
Ncp1, M, Ncp2, M, Ncp3, M,
@@ -1276,11 +1235,11 @@ config_hidden(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq) ->
config(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq) ->
M = from($@, atom_to_list(node())),
io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s', "
- " '~s@~s','~s@~s','~s@~s']},"
- "{sync_nodes_timeout, 1000},"
- "{global_groups, [{nc1, ['~s@~s','~s@~s','~s@~s']}, "
- " {nc2, ['~s@~s','~s@~s','~s@~s']}, "
- "{nc3, ['~s@~s']}]} ] }]. ~n",
+ " '~s@~s','~s@~s','~s@~s']},"
+ "{sync_nodes_timeout, 1000},"
+ "{global_groups, [{nc1, ['~s@~s','~s@~s','~s@~s']}, "
+ " {nc2, ['~s@~s','~s@~s','~s@~s']}, "
+ "{nc3, ['~s@~s']}]} ] }]. ~n",
[Ncp1, M, Ncp2, M, Ncp3, M,
Ncpx, M, Ncpy, M, Ncpz, M,
Ncp1, M, Ncp2, M, Ncp3, M,
@@ -1293,9 +1252,9 @@ config_no(Fd) ->
config_sync(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz) ->
M = from($@, atom_to_list(node())),
io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s', "
- " '~s@~s','~s@~s','~s@~s']},"
- "{sync_nodes_timeout, 1000},"
- "{global_groups, []} ] }] .~n",
+ " '~s@~s','~s@~s','~s@~s']},"
+ "{sync_nodes_timeout, 1000},"
+ "{global_groups, []} ] }] .~n",
[Ncp1, M, Ncp2, M, Ncp3, M,
Ncpx, M, Ncpy, M, Ncpz, M]).
@@ -1303,8 +1262,8 @@ config_sync(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz) ->
config_comp(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz) ->
M = from($@, atom_to_list(node())),
io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s', "
- " '~s@~s','~s@~s','~s@~s']},"
- "{sync_nodes_timeout, 1000} ] }] .~n",
+ " '~s@~s','~s@~s','~s@~s']},"
+ "{sync_nodes_timeout, 1000} ] }] .~n",
[Ncp1, M, Ncp2, M, Ncp3, M,
Ncpx, M, Ncpy, M, Ncpz, M]).
@@ -1325,7 +1284,7 @@ start_proc(Name) ->
receive
{Pid, Res} -> {Pid, Res}
end.
-
+
start_proc_rereg(Name) ->
Pid = spawn(?MODULE, init2, [self(), Name]),
receive
@@ -1437,9 +1396,9 @@ assert_loop(Cp, CpName, Name, NamePid, Loop) ->
Loop ->
ok;
Other1 ->
- test_server:fail(Other1)
+ ct:fail(Other1)
after 5000 ->
- test_server:fail(timeout)
+ ct:fail(timeout)
end.
loop_until_true(Fun) ->
diff --git a/lib/kernel/test/heart_SUITE.erl b/lib/kernel/test/heart_SUITE.erl
index 39cd29cea0..dd6348c610 100644
--- a/lib/kernel/test/heart_SUITE.erl
+++ b/lib/kernel/test/heart_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(heart_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2, start/1, restart/1,
@@ -38,30 +38,29 @@
-define(DEFAULT_TIMEOUT_SECS, 120).
init_per_testcase(_Func, Config) ->
- Dog=test_server:timetrap(test_server:seconds(?DEFAULT_TIMEOUT_SECS)),
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Func, Config) ->
+end_per_testcase(_Func, _Config) ->
Nodes = nodes(),
lists:foreach(fun(X) ->
NNam = list_to_atom(hd(string:tokens(atom_to_list(X),"@"))),
case NNam of
heart_test ->
- ?t:format(1, "WARNING: Killed ~p~n", [X]),
+ ct:pal(?HI_VERBOSITY, "WARNING: Killed ~p~n", [X]),
rpc:cast(X, erlang, halt, []);
_ ->
ok
end
- end, Nodes),
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog).
+ end, Nodes).
%%-----------------------------------------------------------------
%% Test suite for heart.
%% Should be started in a CC view with:
%% erl -sname master -rsh ctrsh
%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,2}}].
all() -> [
start, restart, reboot,
@@ -97,7 +96,7 @@ end_per_suite(Config) when is_list(Config) ->
start_check(Type, Name) ->
start_check(Type, Name, []).
start_check(Type, Name, Envs) ->
- Args = case ?t:os_type() of
+ Args = case test_server:os_type() of
{win32,_} ->
"+t50000 -heart " ++ env_encode([{"HEART_COMMAND", no_reboot}|Envs]);
_ ->
@@ -107,32 +106,30 @@ start_check(Type, Name, Envs) ->
loose ->
loose_node:start(Name, Args, ?DEFAULT_TIMEOUT_SECS);
_ ->
- ?t:start_node(Name, Type, [{args, Args}])
+ test_server:start_node(Name, Type, [{args, Args}])
end,
erlang:monitor_node(Node, true),
case rpc:call(Node, erlang, whereis, [heart]) of
Pid when is_pid(Pid) ->
ok;
_ ->
- test_server:fail(heart_not_started)
+ ct:fail(heart_not_started)
end,
{ok, Node}.
-start(doc) -> [];
-start(suite) -> {req, [{time, 10}]};
start(Config) when is_list(Config) ->
{ok, Node} = start_check(slave, heart_test),
rpc:call(Node, init, reboot, []),
receive
{nodedown, Node} -> ok
- after 2000 -> test_server:fail(node_not_closed)
+ after 2000 -> ct:fail(node_not_closed)
end,
- test_server:sleep(5000),
+ timer:sleep(5000),
case net_adm:ping(Node) of
pang ->
ok;
_ ->
- test_server:fail(node_rebooted)
+ ct:fail(node_rebooted)
end,
test_server:stop_node(Node).
@@ -145,14 +142,6 @@ start(Config) when is_list(Config) ->
%% restart
%% Purpose:
%% Check that a node is up and running after a init:restart/0
-restart(doc) -> [];
-restart(suite) ->
- case ?t:os_type() of
- {Fam, _} when Fam == unix; Fam == win32 ->
- {req, [{time,10}]};
- _ ->
- {skip, "Only run on unix and win32"}
- end;
restart(Config) when is_list(Config) ->
{ok, Node} = start_check(loose, heart_test),
rpc:call(Node, init, restart, []),
@@ -160,17 +149,15 @@ restart(Config) when is_list(Config) ->
{nodedown, Node} ->
ok
after 2000 ->
- test_server:fail(node_not_closed)
+ ct:fail(node_not_closed)
end,
- test_server:sleep(5000),
+ timer:sleep(5000),
node_check_up_down(Node, 2000),
loose_node:stop(Node).
%% reboot
%% Purpose:
%% Check that a node is up and running after a init:reboot/0
-reboot(doc) -> [];
-reboot(suite) -> {req, [{time, 10}]};
reboot(Config) when is_list(Config) ->
{ok, Node} = start_check(slave, heart_test),
@@ -182,9 +169,9 @@ reboot(Config) when is_list(Config) ->
{nodedown, Node} ->
ok
after 2000 ->
- test_server:fail(node_not_closed)
+ ct:fail(node_not_closed)
end,
- test_server:sleep(5000),
+ timer:sleep(5000),
node_check_up_down(Node, 2000),
ok.
@@ -196,7 +183,6 @@ reboot(Config) when is_list(Config) ->
%% May currently dump core in beam debug build due to lock-order violation
%% This should be removed when a non-lockad information retriever is implemented
%% for crash dumps
-node_start_immediately_after_crash(suite) -> {req, [{time, 10}]};
node_start_immediately_after_crash(Config) when is_list(Config) ->
Config2 = ignore_cores:setup(?MODULE, node_start_immediately_after_crash, Config, true),
try
@@ -229,13 +215,13 @@ node_start_immediately_after_crash_test(Config) when is_list(Config) ->
T0 = now(),
receive {nodedown, Node} ->
- test_server:format("Took ~.2f s. for node to go down~n", [timer:now_diff(now(), T0)/1000000]),
+ io:format("Took ~.2f s. for node to go down~n", [timer:now_diff(now(), T0)/1000000]),
ok
%% timeout is very liberal here. nodedown is received in about 1 s. on linux (palantir)
%% and in about 10 s. on solaris (carcharoth)
- after (15000*test_server:timetrap_scale_factor()) -> test_server:fail(node_not_closed)
+ after (15000*test_server:timetrap_scale_factor()) -> ct:fail(node_not_closed)
end,
- test_server:sleep(3000),
+ timer:sleep(3000),
node_check_up_down(Node, 2000),
loose_node:stop(Node).
@@ -248,7 +234,6 @@ node_start_immediately_after_crash_test(Config) when is_list(Config) ->
%% May currently dump core in beam debug build due to lock-order violation
%% This should be removed when a non-lockad information retriever is implemented
%% for crash dumps
-node_start_soon_after_crash(suite) -> {req, [{time, 10}]};
node_start_soon_after_crash(Config) when is_list(Config) ->
Config2 = ignore_cores:setup(?MODULE, node_start_soon_after_crash, Config, true),
try
@@ -278,9 +263,9 @@ node_start_soon_after_crash_test(Config) when is_list(Config) ->
rpc:cast(Node, Mod, do, []),
receive {nodedown, Node} -> ok
- after (15000*test_server:timetrap_scale_factor()) -> test_server:fail(node_not_closed)
+ after (15000*test_server:timetrap_scale_factor()) -> ct:fail(node_not_closed)
end,
- test_server:sleep(20000),
+ timer:sleep(20000),
node_check_up_down(Node, 15000),
loose_node:stop(Node).
@@ -293,14 +278,13 @@ node_check_up_down(Node, Tmo) ->
receive
{nodedown, Node} -> ok
after Tmo ->
- test_server:fail(node_not_closed2)
+ ct:fail(node_not_closed2)
end;
_ ->
- test_server:fail(node_not_rebooted)
+ ct:fail(node_not_rebooted)
end.
%% Only tests bad command, correct behaviour is tested in reboot/1.
-set_cmd(suite) -> [];
set_cmd(Config) when is_list(Config) ->
{ok, Node} = start_check(slave, heart_test),
Cmd = wrong_atom,
@@ -314,7 +298,6 @@ set_cmd(Config) when is_list(Config) ->
stop_node(Node),
ok.
-clear_cmd(suite) -> {req,[{time,15}]};
clear_cmd(Config) when is_list(Config) ->
{ok, Node} = start_check(slave, heart_test),
ok = rpc:call(Node, heart, set_cmd,
@@ -325,14 +308,14 @@ clear_cmd(Config) when is_list(Config) ->
{nodedown, Node} ->
ok
after 2000 ->
- test_server:fail(node_not_closed)
+ ct:fail(node_not_closed)
end,
- test_server:sleep(5000),
+ timer:sleep(5000),
case net_adm:ping(Node) of
pong ->
erlang:monitor_node(Node, true);
_ ->
- test_server:fail(node_not_rebooted)
+ ct:fail(node_not_rebooted)
end,
ok = rpc:call(Node, heart, set_cmd,
["erl -noshell -heart " ++ name(Node) ++ "&"]),
@@ -342,18 +325,17 @@ clear_cmd(Config) when is_list(Config) ->
{nodedown, Node} ->
ok
after 2000 ->
- test_server:fail(node_not_closed)
+ ct:fail(node_not_closed)
end,
- test_server:sleep(5000),
+ timer:sleep(5000),
case net_adm:ping(Node) of
pang ->
ok;
_ ->
- test_server:fail(node_rebooted)
+ ct:fail(node_rebooted)
end,
ok.
-get_cmd(suite) -> [];
get_cmd(Config) when is_list(Config) ->
{ok, Node} = start_check(slave, heart_test),
Cmd = "test",
@@ -391,7 +373,7 @@ callback_api(Config) when is_list(Config) ->
{ok, {M2,F2}} = rpc:call(Node, heart, get_callback, []),
ok = rpc:call(Node, heart, set_callback, [M2,F3]),
receive {nodedown, Node} -> ok
- after 5000 -> test_server:fail(node_not_killed)
+ after 5000 -> ct:fail(node_not_killed)
end,
stop_node(Node),
ok.
@@ -425,15 +407,13 @@ options_api(Config) when is_list(Config) ->
ok.
-dont_drop(suite) ->
%%% Removed as it may crash epmd/distribution in colourful
%%% ways. While we ARE finding out WHY, it would
%%% be nice for others to be able to run the kernel test suite
-%%% without "exploding machines", so thats why I removed it for now.
- [];
-dont_drop(doc) ->
- ["Tests that the heart command does not get dropped when ",
- "set just before halt on very high I/O load."];
+%%% without "exploding machines", so that's why I removed it for now.
+
+%% Tests that the heart command does not get dropped when
+%% set just before halt on very high I/O load..
dont_drop(Config) when is_list(Config) ->
%%% Have to do it some times to make it happen...
[ok,ok,ok,ok,ok,ok,ok,ok,ok,ok] = do_dont_drop(Config,10),
@@ -455,7 +435,7 @@ do_dont_drop(Config,N) ->
Env = [{"HEART_COMMAND", FirstCmd}],
Func = "start_heart_stress",
Arg = NN3 ++ "@" ++ Host ++ " " ++
- filename:join(?config(data_dir, Config), "simple_echo"),
+ filename:join(proplists:get_value(data_dir, Config), "simple_echo"),
start_node_run(Name,Env,Func,Arg),
case wait_for_any_of(list_to_atom(NN2 ++ "@" ++ Host),
list_to_atom(NN3 ++ "@" ++ Host)) of
@@ -488,11 +468,8 @@ wait_for_any_of(N1,N2,Times) ->
end.
-kill_pid(suite) ->
- [];
-kill_pid(doc) ->
- ["Tests that heart kills the old erlang node before executing ",
- "heart command."];
+%% Tests that heart kills the old erlang node before executing
+%% heart command.
kill_pid(Config) when is_list(Config) ->
ok = do_kill_pid(Config).
diff --git a/lib/kernel/test/ignore_cores.erl b/lib/kernel/test/ignore_cores.erl
index db61c4003b..24b95e273c 100644
--- a/lib/kernel/test/ignore_cores.erl
+++ b/lib/kernel/test/ignore_cores.erl
@@ -28,7 +28,7 @@
-module(ignore_cores).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([init/1, fini/1, setup/3, setup/4, restore/1, dir/1]).
@@ -53,7 +53,7 @@ init(Config) ->
fini(Config) ->
#ignore_cores{org_cwd = OrgCWD,
org_path = OrgPath,
- org_pwd_env = OrgPWD} = ?config(ignore_cores, Config),
+ org_pwd_env = OrgPWD} = proplists:get_value(ignore_cores, Config),
ok = file:set_cwd(OrgCWD),
true = code:set_path(OrgPath),
case OrgPWD of
@@ -70,10 +70,10 @@ setup(Suite, Testcase, Config, SetCwd) when is_atom(Suite),
is_list(Config) ->
#ignore_cores{org_cwd = OrgCWD,
org_path = OrgPath,
- org_pwd_env = OrgPWD} = ?config(ignore_cores, Config),
+ org_pwd_env = OrgPWD} = proplists:get_value(ignore_cores, Config),
Path = lists:map(fun (".") -> OrgCWD; (Dir) -> Dir end, OrgPath),
true = code:set_path(Path),
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
IgnDir = filename:join([PrivDir,
atom_to_list(Suite)
++ "_"
@@ -94,7 +94,7 @@ setup(Suite, Testcase, Config, SetCwd) when is_atom(Suite),
end,
ok = file:write_file(filename:join([IgnDir, "ignore_core_files"]), <<>>),
%% cores are dumped in /cores on MacOS X
- CoresDir = case {?t:os_type(), filelib:is_dir("/cores")} of
+ CoresDir = case {test_server:os_type(), filelib:is_dir("/cores")} of
{{unix,darwin}, true} ->
filelib:fold_files("/cores",
"^core.*$",
@@ -119,7 +119,7 @@ restore(Config) ->
org_path = OrgPath,
org_pwd_env = OrgPWD,
ign_dir = IgnDir,
- cores_dir = CoresDir} = ?config(ignore_cores, Config),
+ cores_dir = CoresDir} = proplists:get_value(ignore_cores, Config),
try
case CoresDir of
false ->
@@ -155,5 +155,5 @@ restore(Config) ->
dir(Config) ->
- #ignore_cores{ign_dir = Dir} = ?config(ignore_cores, Config),
+ #ignore_cores{ign_dir = Dir} = proplists:get_value(ignore_cores, Config),
Dir.
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index 5ba06bb032..ee10747b0a 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(inet_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/inet.hrl").
-include_lib("kernel/src/inet_dns.hrl").
@@ -46,7 +46,9 @@
kill_gethost/0, parallell_gethost/0, test_netns/0]).
-export([init_per_testcase/2, end_per_testcase/2]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[t_gethostbyaddr, t_gethostbyname, t_getaddr,
@@ -97,35 +99,30 @@ init_per_testcase(lookup_bad_search_option, Config) ->
Prev = ets:lookup(Db, Key),
ets:delete(Db, Key),
ets:insert(Db, {Key,[lookup_bad_search_option]}),
- ?t:format("Misconfigured resolver lookup order", []),
- Dog = test_server:timetrap(test_server:seconds(60)),
- [{Key,Prev},{watchdog,Dog}|Config];
+ io:format("Misconfigured resolver lookup order", []),
+ [{Key,Prev}|Config];
init_per_testcase(_Func, Config) ->
- Dog = test_server:timetrap(test_server:seconds(60)),
- [{watchdog,Dog}|Config].
+ Config.
end_per_testcase(lookup_bad_search_option, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
Db = inet_db,
Key = res_lookup,
- Prev = ?config(Key, Config),
+ Prev = proplists:get_value(Key, Config),
ets:delete(Db, Key),
ets:insert(Db, Prev),
- ?t:format("Restored resolver lookup order", []);
-end_per_testcase(_Func, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog).
+ io:format("Restored resolver lookup order", []);
+end_per_testcase(_Func, _Config) ->
+ ok.
t_gethostbyaddr() ->
required(v4).
-t_gethostbyaddr(doc) -> "Test the inet:gethostbyaddr/1 function.";
+%% Test the inet:gethostbyaddr/1 function.
t_gethostbyaddr(Config) when is_list(Config) ->
{Name,FullName,IPStr,{A,B,C,D}=IP,Aliases,_,_} = ct:get_config(test_host_ipv4_only),
Rname = integer_to_list(D) ++ "." ++
- integer_to_list(C) ++ "." ++
- integer_to_list(B) ++ "." ++
- integer_to_list(A) ++ ".in-addr.arpa",
+ integer_to_list(C) ++ "." ++
+ integer_to_list(B) ++ "." ++
+ integer_to_list(A) ++ ".in-addr.arpa",
{ok,HEnt} = inet:gethostbyaddr(IPStr),
{ok,HEnt} = inet:gethostbyaddr(IP),
{error,Error} = inet:gethostbyaddr(Name),
@@ -155,79 +152,77 @@ t_gethostbyaddr(Config) when is_list(Config) ->
ok.
t_gethostbyaddr_v6() -> required(v6).
-t_gethostbyaddr_v6(doc) -> "Test the inet:gethostbyaddr/1 inet6 function.";
+%% Test the inet:gethostbyaddr/1 inet6 function.
t_gethostbyaddr_v6(Config) when is_list(Config) ->
- ?line {Name6, FullName6, IPStr6, IP6, Aliases6} =
+ {Name6, FullName6, IPStr6, IP6, Aliases6} =
ct:get_config(test_host_ipv6_only),
- ?line case inet:gethostbyaddr(IPStr6) of
+ case inet:gethostbyaddr(IPStr6) of
%% Even if IPv6 is not supported, the native resolver may succeed
%% looking up the host. DNS lookup will probably fail.
{error,nxdomain} ->
{skip, "IPv6 test fails! IPv6 not supported on this host!?"};
{ok,HEnt6} ->
- ?line {ok,HEnt6} = inet:gethostbyaddr(IP6),
- ?line {error,Error6} = inet:gethostbyaddr(Name6),
- ?line ok = io:format("Failure reason: ~p: ~s",
- [Error6, inet:format_error(Error6)]),
- ?line HEnt6_ = HEnt6#hostent{h_addrtype = inet6,
- h_length = 16,
- h_addr_list = [IP6]},
- ?line HEnt6_ = HEnt6,
- ?line check_elems([{HEnt6#hostent.h_name,[Name6,FullName6]},
- {HEnt6#hostent.h_aliases,[[],Aliases6]}]),
-
- ?line {_DName6, _DFullName6, DIPStr6, DIP6, _} =
- ct:get_config(test_dummy_ipv6_host),
- ?line {error,nxdomain} = inet:gethostbyaddr(DIPStr6),
- ?line {error,nxdomain} = inet:gethostbyaddr(DIP6),
+ {ok,HEnt6} = inet:gethostbyaddr(IP6),
+ {error,Error6} = inet:gethostbyaddr(Name6),
+ ok = io:format("Failure reason: ~p: ~s",
+ [Error6, inet:format_error(Error6)]),
+ HEnt6_ = HEnt6#hostent{h_addrtype = inet6,
+ h_length = 16,
+ h_addr_list = [IP6]},
+ HEnt6_ = HEnt6,
+ check_elems([{HEnt6#hostent.h_name,[Name6,FullName6]},
+ {HEnt6#hostent.h_aliases,[[],Aliases6]}]),
+
+ {_DName6, _DFullName6, DIPStr6, DIP6, _} =
+ ct:get_config(test_dummy_ipv6_host),
+ {error,nxdomain} = inet:gethostbyaddr(DIPStr6),
+ {error,nxdomain} = inet:gethostbyaddr(DIP6),
ok
end.
t_gethostbyname() -> required(v4).
-t_gethostbyname(doc) -> "Test the inet:gethostbyname/1 function.";
-t_gethostbyname(suite) -> [];
+%% Test the inet:gethostbyname/1 function.
t_gethostbyname(Config) when is_list(Config) ->
- ?line {Name,FullName,IPStr,IP,Aliases,IP_46_Str,_} =
+ {Name,FullName,IPStr,IP,Aliases,IP_46_Str,_} =
ct:get_config(test_host_ipv4_only),
- ?line {ok,_} = inet:gethostbyname(IPStr),
- ?line {ok,HEnt} = inet:gethostbyname(Name),
- ?line {ok,HEnt} = inet:gethostbyname(list_to_atom(Name)),
- ?line HEnt_ = HEnt#hostent{h_addrtype = inet,
- h_length = 4,
- h_addr_list = [IP]},
-
- ?line HEnt_ = HEnt,
- ?line check_elems([{HEnt#hostent.h_name,[Name,FullName]},
- {HEnt#hostent.h_aliases,[[],Aliases]}]),
- ?line {ok,HEntF} = inet:gethostbyname(FullName),
- ?line HEntF_ = HEntF#hostent{h_name = FullName,
- h_addrtype = inet,
- h_length = 4,
- h_addr_list = [IP]},
- ?line HEntF_ = HEntF,
- ?line check_elems([{HEnt#hostent.h_aliases,[[],Aliases]}]),
+ {ok,_} = inet:gethostbyname(IPStr),
+ {ok,HEnt} = inet:gethostbyname(Name),
+ {ok,HEnt} = inet:gethostbyname(list_to_atom(Name)),
+ HEnt_ = HEnt#hostent{h_addrtype = inet,
+ h_length = 4,
+ h_addr_list = [IP]},
+
+ HEnt_ = HEnt,
+ check_elems([{HEnt#hostent.h_name,[Name,FullName]},
+ {HEnt#hostent.h_aliases,[[],Aliases]}]),
+ {ok,HEntF} = inet:gethostbyname(FullName),
+ HEntF_ = HEntF#hostent{h_name = FullName,
+ h_addrtype = inet,
+ h_length = 4,
+ h_addr_list = [IP]},
+ HEntF_ = HEntF,
+ check_elems([{HEnt#hostent.h_aliases,[[],Aliases]}]),
%%
- ?line FullNameU = toupper(FullName),
- ?line {ok,HEntU} = inet:gethostbyname(FullNameU),
- ?line FullNameU = toupper(HEntU#hostent.h_name),
- ?line #hostent{
+ FullNameU = toupper(FullName),
+ {ok,HEntU} = inet:gethostbyname(FullNameU),
+ FullNameU = toupper(HEntU#hostent.h_name),
+ #hostent{
h_addrtype = inet,
h_length = 4,
h_addr_list = [IP]} = HEntU,
- ?line check_elems(
- [{[toupper(H) || H <- HEntU#hostent.h_aliases],
- [[],[toupper(A) || A <- Aliases]]}]),
+ check_elems(
+ [{[toupper(H) || H <- HEntU#hostent.h_aliases],
+ [[],[toupper(A) || A <- Aliases]]}]),
- ?line {DName, _DFullName, _DIPStr, _DIP, _, _, _} =
+ {DName, _DFullName, _DIPStr, _DIP, _, _, _} =
ct:get_config(test_dummy_host),
- ?line {error,nxdomain} = inet:gethostbyname(DName),
- ?line {error,nxdomain} = inet:gethostbyname(IP_46_Str),
+ {error,nxdomain} = inet:gethostbyname(DName),
+ {error,nxdomain} = inet:gethostbyname(IP_46_Str),
ok.
t_gethostbyname_v6() -> required(v6).
-t_gethostbyname_v6(doc) -> "Test the inet:gethostbyname/1 inet6 function.";
-t_gethostbyname_v6(suite) -> [];
+%% Test the inet:gethostbyname/1 inet6 function.
t_gethostbyname_v6(Config) when is_list(Config) ->
{Name, FullName, IPStr, IP, Aliases} =
ct:get_config(test_host_ipv6_only),
@@ -287,33 +282,31 @@ check_elem(Val, [Val|_], _) -> ok;
check_elem(Val, [_|Tests], Tests0) ->
check_elem(Val, Tests, Tests0);
check_elem(Val, [], Tests0) ->
- ?t:fail({no_match,Val,Tests0}).
+ ct:fail({no_match,Val,Tests0}).
t_getaddr() -> required(v4).
-t_getaddr(doc) -> "Test the inet:getaddr/2 function.";
-t_getaddr(suite) -> [];
+%% Test the inet:getaddr/2 function.
t_getaddr(Config) when is_list(Config) ->
- ?line {Name,FullName,IPStr,IP,_,IP_46_Str,IP46} =
+ {Name,FullName,IPStr,IP,_,IP_46_Str,IP46} =
ct:get_config(test_host_ipv4_only),
- ?line {ok,IP} = inet:getaddr(list_to_atom(Name), inet),
- ?line {ok,IP} = inet:getaddr(Name, inet),
- ?line {ok,IP} = inet:getaddr(FullName, inet),
- ?line {ok,IP} = inet:getaddr(IP, inet),
- ?line {ok,IP} = inet:getaddr(IPStr, inet),
- ?line {error,nxdomain} = inet:getaddr(IP_46_Str, inet),
- ?line {error,eafnosupport} = inet:getaddr(IP46, inet),
-
- ?line {DName, DFullName, DIPStr, DIP, _, _, _} = ct:get_config(test_dummy_host),
- ?line {error,nxdomain} = inet:getaddr(DName, inet),
- ?line {error,nxdomain} = inet:getaddr(DFullName, inet),
- ?line {ok,DIP} = inet:getaddr(DIPStr, inet),
- ?line {ok,DIP} = inet:getaddr(DIP, inet),
+ {ok,IP} = inet:getaddr(list_to_atom(Name), inet),
+ {ok,IP} = inet:getaddr(Name, inet),
+ {ok,IP} = inet:getaddr(FullName, inet),
+ {ok,IP} = inet:getaddr(IP, inet),
+ {ok,IP} = inet:getaddr(IPStr, inet),
+ {error,nxdomain} = inet:getaddr(IP_46_Str, inet),
+ {error,eafnosupport} = inet:getaddr(IP46, inet),
+
+ {DName, DFullName, DIPStr, DIP, _, _, _} = ct:get_config(test_dummy_host),
+ {error,nxdomain} = inet:getaddr(DName, inet),
+ {error,nxdomain} = inet:getaddr(DFullName, inet),
+ {ok,DIP} = inet:getaddr(DIPStr, inet),
+ {ok,DIP} = inet:getaddr(DIP, inet),
ok.
t_getaddr_v6() -> required(v4) ++ required(v6).
-t_getaddr_v6(doc) -> "Test the inet:getaddr/2 function.";
-t_getaddr_v6(suite) -> [];
+%% Test the inet:getaddr/2 function.
t_getaddr_v6(Config) when is_list(Config) ->
{Name,FullName,IPStr,IP,_} =
ct:get_config(test_host_ipv6_only),
@@ -341,16 +334,15 @@ t_getaddr_v6(Config) when is_list(Config) ->
end.
ipv4_to_ipv6() -> required(v4).
-ipv4_to_ipv6(doc) -> "Test if IPv4 address is converted to IPv6 address.";
-ipv4_to_ipv6(suite) -> [];
+%% Test if IPv4 address is converted to IPv6 address.
ipv4_to_ipv6(Config) when is_list(Config) ->
%% Test what happens if an IPv4 address is looked up in an IPv6 context.
%% If the native resolver succeeds to look it up, an IPv4 compatible
%% address should be returned. If no IPv6 support on this host, an
%% error should beturned.
- ?line {_Name,_FullName,IPStr,_IP,Aliases,IP_46_Str,IP_46} =
+ {_Name,_FullName,IPStr,_IP,Aliases,IP_46_Str,IP_46} =
ct:get_config(test_host_ipv4_only),
- ?line IP4to6Res =
+ IP4to6Res =
case inet:getaddr(IPStr, inet6) of
{ok,IP_46} ->
io:format("IPv4->IPv6: success~n"),
@@ -362,36 +354,34 @@ ipv4_to_ipv6(Config) when is_list(Config) ->
io:format("IPv6->IPv4: eafnosupport~n"),
E;
Other ->
- ?line ?t:fail({ipv4_to_ipv6_lookup_failed,Other})
+ ct:fail({ipv4_to_ipv6_lookup_failed,Other})
end,
- ?line case {IP4to6Res,inet:gethostbyname(IPStr, inet6)} of
- {true,{ok,HEnt}} ->
- ?line HEnt_ = HEnt#hostent{h_addrtype = inet6,
- h_length = 16,
- h_addr_list = [IP_46]},
- ?line HEnt_ = HEnt,
- ?line check_elems([{HEnt#hostent.h_name,[IP_46_Str,IPStr]},
- {HEnt#hostent.h_aliases,[[],Aliases]}]);
- {_,IP4to6Res} -> ok
- end,
+ case {IP4to6Res,inet:gethostbyname(IPStr, inet6)} of
+ {true,{ok,HEnt}} ->
+ HEnt_ = HEnt#hostent{h_addrtype = inet6,
+ h_length = 16,
+ h_addr_list = [IP_46]},
+ HEnt_ = HEnt,
+ check_elems([{HEnt#hostent.h_name,[IP_46_Str,IPStr]},
+ {HEnt#hostent.h_aliases,[[],Aliases]}]);
+ {_,IP4to6Res} -> ok
+ end,
ok.
-host_and_addr() -> required(hosts).
-host_and_addr(doc) -> ["Test looking up hosts and addresses. Use 'ypcat hosts' ",
- "or the local eqivalent to find all hosts."];
-host_and_addr(suite) -> [];
-host_and_addr(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(5)),
+host_and_addr() ->
+ [{timetrap,{minutes,5}}|required(hosts)].
- ?line lists:foreach(fun try_host/1, get_hosts(Config)),
- ?line test_server:timetrap_cancel(Dog),
+%% Test looking up hosts and addresses. Use 'ypcat hosts'
+%% or the local eqivalent to find all hosts.
+host_and_addr(Config) when is_list(Config) ->
+ lists:foreach(fun try_host/1, get_hosts(Config)),
ok.
try_host({Ip0, Host}) ->
- ?line {ok,Ip} = inet:getaddr(Ip0, inet),
- ?line {ok,{hostent, _, _, inet, _, Ips1}} = inet:gethostbyaddr(Ip),
- ?line {ok,{hostent, _, _, inet, _, _Ips2}} = inet:gethostbyname(Host),
- ?line true = lists:member(Ip, Ips1),
+ {ok,Ip} = inet:getaddr(Ip0, inet),
+ {ok,{hostent, _, _, inet, _, Ips1}} = inet:gethostbyaddr(Ip),
+ {ok,{hostent, _, _, inet, _, _Ips2}} = inet:gethostbyname(Host),
+ true = lists:member(Ip, Ips1),
ok.
%% Get all hosts from the system using 'ypcat hosts' or the local
@@ -438,18 +428,18 @@ get_hosts([C|Rest], Cur, Ip, Result) ->
get_hosts(Rest, [C|Cur], Ip, Result);
get_hosts([], _, _, Result) ->
Result.
-
+
parse_hosts(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line HostFile = filename:join(DataDir, "hosts"),
- ?line inet_parse:hosts(HostFile),
- ?line HostFileErr1 = filename:join(DataDir, "hosts_err1"),
- ?line inet_parse:hosts(HostFileErr1),
- ?line Resolv = filename:join(DataDir,"resolv.conf"),
- ?line inet_parse:resolv(Resolv),
- ?line ResolvErr1 = filename:join(DataDir,"resolv.conf.err1"),
- ?line inet_parse:resolv(ResolvErr1).
+ DataDir = proplists:get_value(data_dir,Config),
+ HostFile = filename:join(DataDir, "hosts"),
+ inet_parse:hosts(HostFile),
+ HostFileErr1 = filename:join(DataDir, "hosts_err1"),
+ inet_parse:hosts(HostFileErr1),
+ Resolv = filename:join(DataDir,"resolv.conf"),
+ inet_parse:resolv(Resolv),
+ ResolvErr1 = filename:join(DataDir,"resolv.conf.err1"),
+ inet_parse:resolv(ResolvErr1).
parse_address(Config) when is_list(Config) ->
V4Strict =
@@ -521,10 +511,10 @@ parse_address(Config) when is_list(Config) ->
{{0,0,0,0,0,65535,258,65534},"::FFFF:1.2.255.254"},
{{16#ffff,16#ffff,16#ffff,16#ffff,16#ffff,16#ffff,16#ffff,16#ffff},
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"}
- |[{{D2,0,0,0,0,P,(D1 bsl 8) bor D2,(D3 bsl 8) bor D4},
- erlang:integer_to_list(D2, 16)++"::"++Q++S}
- || {{D1,D2,D3,D4},S} <- V4Strict,
- {P,Q} <- [{0,""},{16#17,"17:"},{16#ff0,"0ff0:"}]]],
+ |[{{D2,0,0,0,0,P,(D1 bsl 8) bor D2,(D3 bsl 8) bor D4},
+ erlang:integer_to_list(D2, 16)++"::"++Q++S}
+ || {{D1,D2,D3,D4},S} <- V4Strict,
+ {P,Q} <- [{0,""},{16#17,"17:"},{16#ff0,"0ff0:"}]]],
V4Sloppy =
[{{10,1,16#98,16#76},"10.0x019876"},
{{8#12,1,8#130,8#321},"012.01.054321"},
@@ -624,42 +614,37 @@ parse_strict_address(Config) when is_list(Config) ->
{ok, {3089,3106,23603,50240,0,0,119,136}} =
inet:parse_strict_address("c11:0c22:5c33:c440::077:0088").
-t_gethostnative(suite) ->[];
-t_gethostnative(doc) ->[];
t_gethostnative(Config) when is_list(Config) ->
-%% this will result in 26 bytes sent which causes problem in Windows
-%% if the port-program has not assured stdin to be read in BINARY mode
-%% OTP-2555
- ?line case inet_gethost_native:gethostbyname(
- "a23456789012345678901234") of
+ %% this will result in 26 bytes sent which causes problem in Windows
+ %% if the port-program has not assured stdin to be read in BINARY mode
+ %% OTP-2555
+ case inet_gethost_native:gethostbyname(
+ "a23456789012345678901234") of
{error,notfound} ->
- ?line ok;
+ ok;
{error,no_data} ->
- ?line ok
+ ok
end.
-gethostnative_parallell(suite) ->
- [];
-gethostnative_parallell(doc) ->
- ["Check that the emulator survives crashes in gethost_native"];
+%% Check that the emulator survives crashes in gethost_native.
gethostnative_parallell(Config) when is_list(Config) ->
- ?line {ok,Hostname} = inet:gethostname(),
- ?line {ok,_} = inet:gethostbyname(Hostname),
+ {ok,Hostname} = inet:gethostname(),
+ {ok,_} = inet:gethostbyname(Hostname),
case whereis(inet_gethost_native) of
Pid when is_pid(Pid) ->
- ?line do_gethostnative_parallell();
+ do_gethostnative_parallell();
_ ->
- ?line {skipped, "Not running native gethostbyname"}
+ {skipped, "Not running native gethostbyname"}
end.
do_gethostnative_parallell() ->
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?line {ok,Node} = ?t:start_node(gethost_parallell, slave,
- [{args, "-pa " ++ PA}]),
- ?line ok = rpc:call(Node, ?MODULE, parallell_gethost, []),
- ?line receive after 10000 -> ok end,
- ?line pong = net_adm:ping(Node),
- ?line ?t:stop_node(Node),
+ PA = filename:dirname(code:which(?MODULE)),
+ {ok,Node} = test_server:start_node(gethost_parallell, slave,
+ [{args, "-pa " ++ PA}]),
+ ok = rpc:call(Node, ?MODULE, parallell_gethost, []),
+ receive after 10000 -> ok end,
+ pong = net_adm:ping(Node),
+ test_server:stop_node(Node),
ok.
parallell_gethost() ->
@@ -752,7 +737,7 @@ wait_for_gethost(N) ->
%% This is what I call an exit tuple :)
exit({inet,gethostbyname, returned, Otherwise, 'when',
'N','=',N,'and','hostname','=',Hostname,'and',
- kill_gethost_n,'=',get(kill_gethost_n)})
+ kill_gethost_n,'=',get(kill_gethost_n)})
end,
case whereis(inet_gethost_native) of
Pid when is_pid(Pid) ->
@@ -764,23 +749,20 @@ wait_for_gethost(N) ->
end,
wait_for_gethost(N-1)
end.
-
-cname_loop(suite) ->
- [];
-cname_loop(doc) ->
- ["Check that the resolver handles a CNAME loop"];
+
+%% Check that the resolver handles a CNAME loop.
cname_loop(Config) when is_list(Config) ->
%% getbyname (hostent_by_domain)
- ?line ok = inet_db:add_rr("mydomain.com", in, ?S_CNAME, ttl, "mydomain.com"),
- ?line {error,nxdomain} = inet_db:getbyname("mydomain.com", ?S_A),
- ?line ok = inet_db:del_rr("mydomain.com", in, ?S_CNAME, "mydomain.com"),
+ ok = inet_db:add_rr("mydomain.com", in, ?S_CNAME, ttl, "mydomain.com"),
+ {error,nxdomain} = inet_db:getbyname("mydomain.com", ?S_A),
+ ok = inet_db:del_rr("mydomain.com", in, ?S_CNAME, "mydomain.com"),
%% res_hostent_by_domain
RR = #dns_rr{domain = "mydomain.com",
class = in,
type = ?S_CNAME,
data = "mydomain.com"},
Rec = #dns_rec{anlist = [RR]},
- ?line {error,nxdomain} = inet_db:res_hostent_by_domain("mydomain.com", ?S_A, Rec),
+ {error,nxdomain} = inet_db:res_hostent_by_domain("mydomain.com", ?S_A, Rec),
ok.
@@ -795,80 +777,75 @@ cname_loop(Config) when is_list(Config) ->
lookup_processes=20}).
gethostnative_soft_restart() -> required(hosts).
-gethostnative_soft_restart(suite) ->
- [];
-gethostnative_soft_restart(doc) ->
- ["Check that no name lookups fails during soft restart "
- "of inet_gethost_native"];
+
+%% Check that no name lookups fails during soft restart
+%% of inet_gethost_native.
gethostnative_soft_restart(Config) when is_list(Config) ->
- ?line gethostnative_control(Config,
- #gethostnative_control{
- control_seq=[soft_restart]}).
+ gethostnative_control(Config,
+ #gethostnative_control{
+ control_seq=[soft_restart]}).
gethostnative_debug_level() -> required(hosts).
-gethostnative_debug_level(suite) ->
- [];
-gethostnative_debug_level(doc) ->
- ["Check that no name lookups fails during debug level change "
- "of inet_gethost_native"];
+
+%% Check that no name lookups fails during debug level change
+%% of inet_gethost_native.
gethostnative_debug_level(Config) when is_list(Config) ->
- ?line gethostnative_control(Config,
- #gethostnative_control{
- control_seq=[{debug_level,1},
- {debug_level,0}]}).
+ gethostnative_control(Config,
+ #gethostnative_control{
+ control_seq=[{debug_level,1},
+ {debug_level,0}]}).
gethostnative_control(Config, Optrec) ->
- ?line case inet_db:res_option(lookup) of
- [native] ->
- case whereis(inet_gethost_native) of
- Pid when is_pid(Pid) ->
- ?line gethostnative_control_1(Config, Optrec);
- _ ->
- ?line {skipped, "Not running native gethostbyname"}
- end;
- _ ->
- ?line {skipped, "Native not only lookup metod"}
- end.
+ case inet_db:res_option(lookup) of
+ [native] ->
+ case whereis(inet_gethost_native) of
+ Pid when is_pid(Pid) ->
+ gethostnative_control_1(Config, Optrec);
+ _ ->
+ {skipped, "Not running native gethostbyname"}
+ end;
+ _ ->
+ {skipped, "Native not only lookup metod"}
+ end.
gethostnative_control_1(Config,
#gethostnative_control{
- control_seq=Seq,
- control_interval=Interval,
- lookup_delay=Delay,
- lookup_count=Cnt,
- lookup_processes=N}) ->
- ?line {ok, Hostname} = inet:gethostname(),
- ?line {ok, _} = inet:gethostbyname(Hostname),
- ?line Hosts =
+ control_seq=Seq,
+ control_interval=Interval,
+ lookup_delay=Delay,
+ lookup_count=Cnt,
+ lookup_processes=N}) ->
+ {ok, Hostname} = inet:gethostname(),
+ {ok, _} = inet:gethostbyname(Hostname),
+ Hosts =
[Hostname|[H || {_,H} <- get_hosts(Config)]
++[H++D || H <- ["www.","www1.","www2.",""],
D <- ["erlang.org","erlang.se"]]
++[H++"cslab.ericsson.net" || H <- ["morgoth.","hades.","styx."]]],
%% Spawn some processes to do parallel lookups while
%% I repeatedly do inet_gethost_native:control/1.
- ?line TrapExit = process_flag(trap_exit, true),
- ?line gethostnative_control_2([undefined], Interval, Delay, Cnt, N, Hosts),
- ?line test_server:format(
- "First intermission: now starting control sequence ~w\n",
- [Seq]),
- ?line erlang:display(first_intermission),
- ?line gethostnative_control_2(Seq, Interval, Delay, Cnt, N, Hosts),
- ?line erlang:display(second_intermission),
- ?line test_server:format(
- "Second intermission: now stopping control sequence ~w\n",
- [Seq]),
- ?line gethostnative_control_2([undefined], Interval, Delay, Cnt, N, Hosts),
- ?line true = process_flag(trap_exit, TrapExit),
- ?line ok.
+ TrapExit = process_flag(trap_exit, true),
+ gethostnative_control_2([undefined], Interval, Delay, Cnt, N, Hosts),
+ io:format(
+ "First intermission: now starting control sequence ~w\n",
+ [Seq]),
+ erlang:display(first_intermission),
+ gethostnative_control_2(Seq, Interval, Delay, Cnt, N, Hosts),
+ erlang:display(second_intermission),
+ io:format(
+ "Second intermission: now stopping control sequence ~w\n",
+ [Seq]),
+ gethostnative_control_2([undefined], Interval, Delay, Cnt, N, Hosts),
+ true = process_flag(trap_exit, TrapExit),
+ ok.
gethostnative_control_2(Seq, Interval, Delay, Cnt, N, Hosts) ->
- ?line Tag = make_ref(),
- ?line Parent = self(),
- ?line Lookupers =
+ Tag = make_ref(),
+ Parent = self(),
+ Lookupers =
[spawn_link(
fun () ->
- random:seed(),
lookup_loop(Hosts, Delay, Tag, Parent, Cnt, Hosts)
end)
|| _ <- lists:seq(1, N)],
@@ -878,7 +855,7 @@ gethostnative_control_2(Seq, Interval, Delay, Cnt, N, Hosts) ->
gethostnative_control_3(Tag, Reason) ->
receive
{Tag,Error} ->
- ?line gethostnative_control_3(Tag, Error)
+ gethostnative_control_3(Tag, Error)
after 0 ->
Reason
end.
@@ -893,27 +870,26 @@ control_loop([Op|Ops], Interval, Tag, Lookupers, Seq) ->
Seq).
control_loop_1(Op, Interval, Tag, Lookupers) ->
- ?line
- receive
- {'EXIT',Pid,Reason} ->
- ?line case Reason of
- Tag -> % Done
- ?line control_loop_1
- (Op, Interval, Tag,
- lists:delete(Pid, Lookupers));
- _ ->
- ?line io:format("Lookuper ~p died: ~p",
- [Pid,Reason]),
- ?line test_server:fail("Lookuper died")
- end
- after Interval ->
- ?line if Op =/= undefined ->
- ?line ok = inet_gethost_native:control(Op);
- true ->
- ?line ok
- end,
- ?line Lookupers
- end.
+ receive
+ {'EXIT',Pid,Reason} ->
+ case Reason of
+ Tag -> % Done
+ control_loop_1
+ (Op, Interval, Tag,
+ lists:delete(Pid, Lookupers));
+ _ ->
+ io:format("Lookuper ~p died: ~p",
+ [Pid,Reason]),
+ ct:fail("Lookuper died")
+ end
+ after Interval ->
+ if Op =/= undefined ->
+ ok = inet_gethost_native:control(Op);
+ true ->
+ ok
+ end,
+ Lookupers
+ end.
lookup_loop(_, _Delay, Tag, _Parent, 0, _Hosts) ->
exit(Tag);
@@ -924,21 +900,18 @@ lookup_loop([H|Hs], Delay, Tag, Parent, Cnt, Hosts) ->
{ok,_Hent} -> ok;
{error,nxdomain} -> ok;
Error ->
- ?line io:format("Name lookup error for ~p for ~p: ~p",
- [self(),H,Error]),
+ io:format("Name lookup error for ~p for ~p: ~p",
+ [self(),H,Error]),
Parent ! {Tag,Error}
end,
receive
- after random:uniform(Delay) ->
+ after rand:uniform(Delay) ->
lookup_loop(Hs, Delay, Tag, Parent, Cnt-1, Hosts)
end.
-lookup_bad_search_option(suite) ->
- [];
-lookup_bad_search_option(doc) ->
- ["Test lookup with erroneously configured lookup option (OTP-12133)"];
+%% Test lookup with erroneously configured lookup option (OTP-12133).
lookup_bad_search_option(Config) when is_list(Config) ->
%% Manipulation of resolver config is done in init_per_testcase
%% and end_per_testcase to ensure cleanup.
@@ -948,24 +921,21 @@ lookup_bad_search_option(Config) when is_list(Config) ->
-getif(suite) ->
- [];
-getif(doc) ->
- ["Tests basic functionality of getiflist, getif, and ifget"];
+%% Tests basic functionality of getiflist, getif, and ifget.
getif(Config) when is_list(Config) ->
- ?line case os:type() of
- {unix,Osname} ->
- ?line do_getif(Osname);
- {_,_} ->
- {skip,"inet:getif/0 probably not supported"}
- end.
+ case os:type() of
+ {unix,Osname} ->
+ do_getif(Osname);
+ {_,_} ->
+ {skip,"inet:getif/0 probably not supported"}
+ end.
do_getif(Osname) ->
- ?line {ok,Hostname} = inet:gethostname(),
- ?line {ok,Address} = inet:getaddr(Hostname, inet),
- ?line {ok,Loopback} = inet:getaddr("localhost", inet),
- ?line {ok,Interfaces} = inet:getiflist(),
- ?line HWAs =
+ {ok,Hostname} = inet:gethostname(),
+ {ok,Address} = inet:getaddr(Hostname, inet),
+ {ok,Loopback} = inet:getaddr("localhost", inet),
+ {ok,Interfaces} = inet:getiflist(),
+ HWAs =
lists:sort(
lists:foldl(
fun (I, Acc) ->
@@ -974,10 +944,10 @@ do_getif(Osname) ->
{ok,[]} -> Acc
end
end, [], Interfaces)),
- ?line io:format("HWAs = ~p~n", [HWAs]),
- ?line (Osname =/= sunos)
- andalso ((length(HWAs) > 0) orelse (?t:fail(no_HWAs))),
- ?line Addresses =
+ io:format("HWAs = ~p~n", [HWAs]),
+ (Osname =/= sunos)
+ andalso ((length(HWAs) > 0) orelse (ct:fail(no_HWAs))),
+ Addresses =
lists:sort(
lists:foldl(
fun (I, Acc) ->
@@ -986,99 +956,95 @@ do_getif(Osname) ->
{ok,[]} -> Acc
end
end, [], Interfaces)),
- ?line {ok,Getif} = inet:getif(),
- ?line Addresses = lists:sort([A || {A,_,_} <- Getif]),
- ?line true = ip_member(Address, Addresses),
- ?line true = ip_member(Loopback, Addresses),
- ?line ok.
-
-getif_ifr_name_overflow(doc) ->
- "Test long interface names do not overrun buffer";
+ {ok,Getif} = inet:getif(),
+ Addresses = lists:sort([A || {A,_,_} <- Getif]),
+ true = ip_member(Address, Addresses),
+ true = ip_member(Loopback, Addresses),
+ ok.
+
+%% Test long interface names do not overrun buffer.
getif_ifr_name_overflow(Config) when is_list(Config) ->
- ?line case os:type() of
- {unix,Osname} ->
- ?line do_getif_ifr_name_overflow(Osname);
- {_,_} ->
- {skip,"inet:ifget/2 probably not supported"}
- end.
+ case os:type() of
+ {unix,Osname} ->
+ do_getif_ifr_name_overflow(Osname);
+ {_,_} ->
+ {skip,"inet:ifget/2 probably not supported"}
+ end.
do_getif_ifr_name_overflow(_) ->
%% emulator should not crash
- ?line {ok,[]} = inet:ifget(lists:duplicate(128, "x"), [addr]),
+ {ok,[]} = inet:ifget(lists:duplicate(128, "x"), [addr]),
ok.
-getservbyname_overflow(doc) ->
- "Test long service names do not overrun buffer";
+%% Test long service names do not overrun buffer.
getservbyname_overflow(Config) when is_list(Config) ->
%% emulator should not crash
- ?line {error,einval} = inet:getservbyname(list_to_atom(lists:flatten(lists:duplicate(128, "x"))), tcp),
+ {error,einval} = inet:getservbyname(list_to_atom(lists:flatten(lists:duplicate(128, "x"))), tcp),
ok.
-getifaddrs(doc) ->
- "Test inet:gifaddrs/0";
+%% Test inet:gifaddrs/0.
getifaddrs(Config) when is_list (Config) ->
- ?line {ok,IfAddrs} = inet:getifaddrs(),
- ?line ?t:format("IfAddrs = ~p.~n", [IfAddrs]),
- ?line
- case
- {os:type(),
- [If ||
- {If,Opts} <- IfAddrs,
- lists:keymember(hwaddr, 1, Opts)]} of
- {{unix,sunos},[]} -> ok;
- {OT,[]} ->
- ?t:fail({should_have_hwaddr,OT});
- _ -> ok
- end,
- ?line Addrs =
+ {ok,IfAddrs} = inet:getifaddrs(),
+ io:format("IfAddrs = ~p.~n", [IfAddrs]),
+ case
+ {os:type(),
+ [If ||
+ {If,Opts} <- IfAddrs,
+ lists:keymember(hwaddr, 1, Opts)]} of
+ {{unix,sunos},[]} -> ok;
+ {OT,[]} ->
+ ct:fail({should_have_hwaddr,OT});
+ _ -> ok
+ end,
+ Addrs =
[element(1, A) || A <- ifaddrs(IfAddrs)],
- ?line ?t:format("Addrs = ~p.~n", [Addrs]),
- ?line [check_addr(Addr) || Addr <- Addrs],
+ io:format("Addrs = ~p.~n", [Addrs]),
+ [check_addr(Addr) || Addr <- Addrs],
ok.
check_addr(Addr)
when tuple_size(Addr) =:= 8,
element(1, Addr) band 16#FFC0 =:= 16#FE80 ->
- ?line ?t:format("Addr: ~p link local; SKIPPED!~n", [Addr]),
+ io:format("Addr: ~p link local; SKIPPED!~n", [Addr]),
ok;
check_addr(Addr) ->
- ?line ?t:format("Addr: ~p.~n", [Addr]),
- ?line Ping = "ping",
- ?line Pong = "pong",
- ?line {ok,L} = gen_tcp:listen(0, [{ip,Addr},{active,false}]),
- ?line {ok,P} = inet:port(L),
- ?line {ok,S1} = gen_tcp:connect(Addr, P, [{active,false}]),
- ?line {ok,S2} = gen_tcp:accept(L),
- ?line ok = gen_tcp:send(S2, Ping),
- ?line {ok,Ping} = gen_tcp:recv(S1, length(Ping)),
- ?line ok = gen_tcp:send(S1, Pong),
- ?line ok = gen_tcp:close(S1),
- ?line {ok,Pong} = gen_tcp:recv(S2, length(Pong)),
- ?line ok = gen_tcp:close(S2),
- ?line ok = gen_tcp:close(L),
+ io:format("Addr: ~p.~n", [Addr]),
+ Ping = "ping",
+ Pong = "pong",
+ {ok,L} = gen_tcp:listen(0, [{ip,Addr},{active,false}]),
+ {ok,P} = inet:port(L),
+ {ok,S1} = gen_tcp:connect(Addr, P, [{active,false}]),
+ {ok,S2} = gen_tcp:accept(L),
+ ok = gen_tcp:send(S2, Ping),
+ {ok,Ping} = gen_tcp:recv(S1, length(Ping)),
+ ok = gen_tcp:send(S1, Pong),
+ ok = gen_tcp:close(S1),
+ {ok,Pong} = gen_tcp:recv(S2, length(Pong)),
+ ok = gen_tcp:close(S2),
+ ok = gen_tcp:close(L),
ok.
-record(ifopts, {name,flags,addrs=[],hwaddr}).
ifaddrs([]) -> [];
ifaddrs([{If,Opts}|IOs]) ->
- ?line #ifopts{flags=Flags} = Ifopts =
+ #ifopts{flags=Flags} = Ifopts =
check_ifopts(Opts, #ifopts{name=If}),
- ?line case Flags =/= undefined andalso lists:member(up, Flags) of
- true ->
- Ifopts#ifopts.addrs;
- false ->
- []
- end++ifaddrs(IOs).
+ case Flags =/= undefined andalso lists:member(up, Flags) of
+ true ->
+ Ifopts#ifopts.addrs;
+ false ->
+ []
+ end++ifaddrs(IOs).
check_ifopts([], #ifopts{name=If,flags=Flags,addrs=Raddrs}=Ifopts) ->
Addrs = lists:reverse(Raddrs),
R = Ifopts#ifopts{addrs=Addrs},
- ?t:format("~p.~n", [R]),
+ io:format("~p.~n", [R]),
%% See how we did...
if is_list(Flags) -> ok;
true ->
- ?t:fail({flags_undefined,If})
+ ct:fail({flags_undefined,If})
end,
case lists:member(broadcast, Flags) of
true ->
@@ -1086,12 +1052,12 @@ check_ifopts([], #ifopts{name=If,flags=Flags,addrs=Raddrs}=Ifopts) ->
{_,_,_} -> A;
{T,_} when tuple_size(T) =:= 8 -> A;
_ ->
- ?t:fail({broaddr_missing,If,A})
+ ct:fail({broaddr_missing,If,A})
end || A <- Addrs];
false ->
[case A of {_,_} -> A;
_ ->
- ?t:fail({should_have_netmask,If,A})
+ ct:fail({should_have_netmask,If,A})
end || A <- Addrs]
end,
R;
@@ -1102,7 +1068,7 @@ check_ifopts([{flags,Fs}|Opts], #ifopts{flags=Flags}=Ifopts) ->
Flags ->
check_ifopts(Opts, Ifopts#ifopts{});
_ ->
- ?t:fail({multiple_flags,Fs,Ifopts})
+ ct:fail({multiple_flags,Fs,Ifopts})
end;
check_ifopts(
[{addr,Addr},{netmask,Netmask},{broadaddr,Broadaddr}|Opts],
@@ -1118,7 +1084,7 @@ check_ifopts([{hwaddr,Hwaddr}|Opts], #ifopts{hwaddr=undefined}=Ifopts)
when is_list(Hwaddr) ->
check_ifopts(Opts, Ifopts#ifopts{hwaddr=Hwaddr});
check_ifopts([{hwaddr,HwAddr}|_], #ifopts{}=Ifopts) ->
- ?t:fail({multiple_hwaddrs,HwAddr,Ifopts}).
+ ct:fail({multiple_hwaddrs,HwAddr,Ifopts}).
%% Works just like lists:member/2, except that any {127,_,_,_} tuple
%% matches any other {127,_,_,_}. We do this to handle Linux systems
diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl
index ace4ccb8bd..a82849b2d3 100644
--- a/lib/kernel/test/inet_res_SUITE.erl
+++ b/lib/kernel/test/inet_res_SUITE.erl
@@ -20,7 +20,6 @@
-module(inet_res_SUITE).
-include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-include_lib("kernel/include/inet.hrl").
-include_lib("kernel/src/inet_dns.hrl").
@@ -43,7 +42,9 @@
-define(RUN_NAMED, "run-named").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[basic, resolve, edns0, txt_record, files_monitor,
@@ -78,8 +79,8 @@ zone_dir(TC) ->
end.
init_per_testcase(Func, Config) ->
- PrivDir = ?config(priv_dir, Config),
- DataDir = ?config(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
try ns_init(zone_dir(Func), PrivDir, DataDir) of
NsSpec ->
Lookup = inet_db:res_option(lookup),
@@ -89,29 +90,27 @@ init_per_testcase(Func, Config) ->
inet_db:ins_alt_ns(IP, Port);
_ -> ok
end,
- Dog = test_server:timetrap(test_server:seconds(20)),
- [{nameserver,NsSpec},{res_lookup,Lookup},{watchdog,Dog}|Config]
+ [{nameserver,NsSpec},{res_lookup,Lookup}|Config]
catch
SkipReason ->
{skip,SkipReason}
end.
end_per_testcase(_Func, Config) ->
- test_server:timetrap_cancel(?config(watchdog, Config)),
- inet_db:set_lookup(?config(res_lookup, Config)),
- NsSpec = ?config(nameserver, Config),
+ inet_db:set_lookup(proplists:get_value(res_lookup, Config)),
+ NsSpec = proplists:get_value(nameserver, Config),
case NsSpec of
{_,{IP,Port},_} ->
inet_db:del_alt_ns(IP, Port);
_ -> ok
end,
- ns_end(NsSpec, ?config(priv_dir, Config)).
+ ns_end(NsSpec, proplists:get_value(priv_dir, Config)).
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Nameserver control
ns(Config) ->
- {_ZoneDir,NS,_P} = ?config(nameserver, Config),
+ {_ZoneDir,NS,_P} = proplists:get_value(nameserver, Config),
NS.
ns_init(ZoneDir, PrivDir, DataDir) ->
@@ -120,7 +119,7 @@ ns_init(ZoneDir, PrivDir, DataDir) ->
{unix,_} ->
PortNum = case {os:type(),os:version()} of
{{unix,solaris},{M,V,_}} when M =< 5, V < 10 ->
- 11895 + random:uniform(100);
+ 11895 + rand:uniform(100);
_ ->
{ok,S} = gen_udp:open(0, [{reuseaddr,true}]),
{ok,PNum} = inet:port(S),
@@ -278,8 +277,7 @@ proxy_ns({proxy,_,_,ProxyNS}) -> ProxyNS.
%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-basic(doc) ->
- ["Lookup an A record with different API functions"];
+%% Lookup an A record with different API functions.
basic(Config) when is_list(Config) ->
NS = ns(Config),
Name = "ns.otptest",
@@ -341,8 +339,7 @@ basic(Config) when is_list(Config) ->
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-resolve(doc) ->
- ["Lookup different records using resolve/2..4"];
+%% Lookup different records using resolve/2..4.
resolve(Config) when is_list(Config) ->
Class = in,
NS = ns(Config),
@@ -472,8 +469,7 @@ check_msg(Class, Type, Msg, AnList, NsList) ->
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-edns0(doc) ->
- ["Test EDNS and truncation"];
+%% Test EDNS and truncation.
edns0(Config) when is_list(Config) ->
NS = ns(Config),
Domain = "otptest",
@@ -534,10 +530,7 @@ inet_res_filter(Anlist, Class, Type) ->
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-txt_record(suite) ->
- [];
-txt_record(doc) ->
- ["Tests TXT records"];
+%% Tests TXT records.
txt_record(Config) when is_list(Config) ->
D1 = "cslab.ericsson.net",
D2 = "mail1.cslab.ericsson.net",
@@ -556,10 +549,7 @@ txt_record(Config) when is_list(Config) ->
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-files_monitor(suite) ->
- [];
-files_monitor(doc) ->
- ["Tests monitoring of /etc/hosts and /etc/resolv.conf, but not them"];
+%% Tests monitoring of /etc/hosts and /etc/resolv.conf, but not them.
files_monitor(Config) when is_list(Config) ->
Search = inet_db:res_option(search),
HostsFile = inet_db:res_option(hosts_file),
@@ -574,7 +564,7 @@ files_monitor(Config) when is_list(Config) ->
end.
do_files_monitor(Config) ->
- Dir = ?config(priv_dir, Config),
+ Dir = proplists:get_value(priv_dir, Config),
{ok,Hostname} = inet:gethostname(),
io:format("Hostname = ~p.~n", [Hostname]),
FQDN =
@@ -648,8 +638,7 @@ do_files_monitor(Config) ->
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-last_ms_answer(doc) ->
- ["Answer just when timeout is triggered (OTP-9221)"];
+%% Answer just when timeout is triggered (OTP-9221).
last_ms_answer(Config) when is_list(Config) ->
NS = ns(Config),
Name = "ns.otptest",
diff --git a/lib/kernel/test/inet_sockopt_SUITE.erl b/lib/kernel/test/inet_sockopt_SUITE.erl
index cb522c8abe..d682398ba8 100644
--- a/lib/kernel/test/inet_sockopt_SUITE.erl
+++ b/lib/kernel/test/inet_sockopt_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(inet_sockopt_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(C_GET_IPPROTO_TCP,1).
@@ -62,7 +62,9 @@
-export([init_per_testcase/2, end_per_testcase/2]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[simple, loop_all, simple_raw, simple_raw_getbin,
@@ -90,97 +92,91 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_Func, Config) ->
- Dog = test_server:timetrap(test_server:seconds(60)),
- [{watchdog,Dog}|Config].
+ Config.
-end_per_testcase(_Func, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog).
+end_per_testcase(_Func, _Config) ->
+ ok.
-simple(suite) -> [];
-simple(doc) -> "Test inet:setopt/getopt simple functionality.";
+%% Test inet:setopt/getopt simple functionality.
simple(Config) when is_list(Config) ->
- ?line XOpt = case os:type() of
- {unix,_} -> [{reuseaddr,true}];
- _ -> []
- end,
- ?line Opt = [{nodelay,true},
- {keepalive,true},{packet,4},
- {active,false}|XOpt],
- ?line OptTags = [X || {X,_} <- Opt],
- ?line {S1,S2} = create_socketpair(Opt, Opt),
- ?line {ok,Opt} = inet:getopts(S1,OptTags),
- ?line {ok,Opt} = inet:getopts(S2,OptTags),
- ?line COpt = [{X,case X of nodelay -> false;_ -> Y end} || {X,Y} <- Opt],
- ?line inet:setopts(S1,COpt),
- ?line {ok,COpt} = inet:getopts(S1,OptTags),
- ?line {ok,Opt} = inet:getopts(S2,OptTags),
- ?line gen_tcp:close(S1),
- ?line gen_tcp:close(S2),
+ XOpt = case os:type() of
+ {unix,_} -> [{reuseaddr,true}];
+ _ -> []
+ end,
+ Opt = [{nodelay,true},
+ {keepalive,true},{packet,4},
+ {active,false}|XOpt],
+ OptTags = [X || {X,_} <- Opt],
+ {S1,S2} = create_socketpair(Opt, Opt),
+ {ok,Opt} = inet:getopts(S1,OptTags),
+ {ok,Opt} = inet:getopts(S2,OptTags),
+ COpt = [{X,case X of nodelay -> false;_ -> Y end} || {X,Y} <- Opt],
+ inet:setopts(S1,COpt),
+ {ok,COpt} = inet:getopts(S1,OptTags),
+ {ok,Opt} = inet:getopts(S2,OptTags),
+ gen_tcp:close(S1),
+ gen_tcp:close(S2),
ok.
-loop_all(suite) -> [];
-loop_all(doc) -> "Loop through all socket options and check that they work";
+%% Loop through all socket options and check that they work.
loop_all(Config) when is_list(Config) ->
- ?line ListenFailures =
+ ListenFailures =
lists:foldr(make_check_fun(listen,1),[],all_listen_options()),
- ?line ConnectFailures =
+ ConnectFailures =
lists:foldr(make_check_fun(connect,2),[],all_connect_options()),
- ?line case ListenFailures++ConnectFailures of
- [] ->
- ?line ok;
- Failed ->
- ?line {comment,lists:flatten(
- io_lib:format("Non mandatory failed:~w",
- [Failed]))}
- end.
+ case ListenFailures++ConnectFailures of
+ [] ->
+ ok;
+ Failed ->
+ {comment,lists:flatten(
+ io_lib:format("Non mandatory failed:~w",
+ [Failed]))}
+ end.
-simple_raw(suite) -> [];
-simple_raw(doc) -> "Test simple setopt/getopt of raw options.";
+%% Test simple setopt/getopt of raw options.
simple_raw(Config) when is_list(Config) ->
do_simple_raw(Config,false).
-simple_raw_getbin(suite) -> [];
-simple_raw_getbin(doc) -> "Test simple setopt/getopt of raw options, "
- "with binaries in getopt.";
+
+%% Test simple setopt/getopt of raw options, with binaries in getopt.
simple_raw_getbin(Config) when is_list(Config) ->
do_simple_raw(Config,true).
do_simple_raw(Config,Binary) when is_list(Config) ->
- ?line Port = start_helper(Config),
- ?line SolSocket = ask_helper(Port,?C_GET_SOL_SOCKET),
- ?line SoKeepAlive = ask_helper(Port,?C_GET_SO_KEEPALIVE),
- ?line OptionTrue = {raw,SolSocket,SoKeepAlive,<<1:32/native>>},
- ?line OptionFalse = {raw,SolSocket,SoKeepAlive,<<0:32/native>>},
- ?line {S1,S2} = create_socketpair([OptionTrue],[{keepalive,true}]),
- ?line {ok,[{keepalive,true}]} = inet:getopts(S1,[keepalive]),
- ?line {ok,[{keepalive,true}]} = inet:getopts(S2,[keepalive]),
- ?line {ok,[{raw,SolSocket,SoKeepAlive,X1B}]} =
+ Port = start_helper(Config),
+ SolSocket = ask_helper(Port,?C_GET_SOL_SOCKET),
+ SoKeepAlive = ask_helper(Port,?C_GET_SO_KEEPALIVE),
+ OptionTrue = {raw,SolSocket,SoKeepAlive,<<1:32/native>>},
+ OptionFalse = {raw,SolSocket,SoKeepAlive,<<0:32/native>>},
+ {S1,S2} = create_socketpair([OptionTrue],[{keepalive,true}]),
+ {ok,[{keepalive,true}]} = inet:getopts(S1,[keepalive]),
+ {ok,[{keepalive,true}]} = inet:getopts(S2,[keepalive]),
+ {ok,[{raw,SolSocket,SoKeepAlive,X1B}]} =
inet:getopts(S1,[{raw,SolSocket,SoKeepAlive,binarify(4,Binary)}]),
- ?line X1 = nintbin2int(X1B),
- ?line {ok,[{raw,SolSocket,SoKeepAlive,X2B}]} =
+ X1 = nintbin2int(X1B),
+ {ok,[{raw,SolSocket,SoKeepAlive,X2B}]} =
inet:getopts(S2,[{raw,SolSocket,SoKeepAlive,binarify(4,Binary)}]),
- ?line X2 = nintbin2int(X2B),
- ?line true = X1 > 0,
- ?line true = X2 > 0,
- ?line inet:setopts(S1,[{keepalive,false}]),
- ?line inet:setopts(S2,[OptionFalse]),
- ?line {ok,[{keepalive,false}]} = inet:getopts(S1,[keepalive]),
- ?line {ok,[{keepalive,false}]} = inet:getopts(S2,[keepalive]),
- ?line {ok,[{raw,SolSocket,SoKeepAlive,Y1B}]} =
+ X2 = nintbin2int(X2B),
+ true = X1 > 0,
+ true = X2 > 0,
+ inet:setopts(S1,[{keepalive,false}]),
+ inet:setopts(S2,[OptionFalse]),
+ {ok,[{keepalive,false}]} = inet:getopts(S1,[keepalive]),
+ {ok,[{keepalive,false}]} = inet:getopts(S2,[keepalive]),
+ {ok,[{raw,SolSocket,SoKeepAlive,Y1B}]} =
inet:getopts(S1,[{raw,SolSocket,SoKeepAlive,binarify(4,Binary)}]),
- ?line Y1 = nintbin2int(Y1B),
- ?line {ok,[{raw,SolSocket,SoKeepAlive,Y2B}]} =
+ Y1 = nintbin2int(Y1B),
+ {ok,[{raw,SolSocket,SoKeepAlive,Y2B}]} =
inet:getopts(S2,[{raw,SolSocket,SoKeepAlive,binarify(4,Binary)}]),
- ?line Y2 = nintbin2int(Y2B),
- ?line true = Y1 == 0,
- ?line true = Y2 == 0,
- ?line gen_tcp:close(S1),
- ?line gen_tcp:close(S2),
- ?line stop_helper(Port),
+ Y2 = nintbin2int(Y2B),
+ true = Y1 == 0,
+ true = Y2 == 0,
+ gen_tcp:close(S1),
+ gen_tcp:close(S2),
+ stop_helper(Port),
ok.
-
+
nintbin2int(<<Int:32/native>>) -> Int;
nintbin2int(<<Int:24/native>>) -> Int;
nintbin2int(<<Int:16/native>>) -> Int;
@@ -189,13 +185,12 @@ nintbin2int(<<>>) -> 0.
-multiple_raw(suite) -> [];
-multiple_raw(doc) -> "Test setopt/getopt of multiple raw options.";
+%% Test setopt/getopt of multiple raw options.
multiple_raw(Config) when is_list(Config) ->
do_multiple_raw(Config,false).
-multiple_raw_getbin(suite) -> [];
-multiple_raw_getbin(doc) -> "Test setopt/getopt of multiple raw options, "
- "with binaries in getopt.";
+
+%% Test setopt/getopt of multiple raw options, with binaries in
+%% getopt.
multiple_raw_getbin(Config) when is_list(Config) ->
do_multiple_raw(Config,true).
@@ -265,145 +260,143 @@ do_multiple_raw(Config, Binary) ->
-doc_examples_raw(suite) -> [];
-doc_examples_raw(doc) -> "Test that the example code from the documentation "
- "works";
+%% Test that the example code from the documentation works.
doc_examples_raw(Config) when is_list(Config) ->
do_doc_examples_raw(Config,false).
-doc_examples_raw_getbin(suite) -> [];
-doc_examples_raw_getbin(doc) -> "Test that the example code from the "
- "documentation works when getopt uses "
- "binaries";
+
+%% Test that the example code from the documentation works when getopt
+%% uses binaries.
doc_examples_raw_getbin(Config) when is_list(Config) ->
do_doc_examples_raw(Config,true).
+
do_doc_examples_raw(Config,Binary) when is_list(Config) ->
- ?line Port = start_helper(Config),
- ?line Proto = ask_helper(Port,?C_GET_IPPROTO_TCP),
- ?line TcpInfo = ask_helper(Port,?C_GET_TCP_INFO),
- ?line TcpInfoSize = ask_helper(Port,?C_GET_TCP_INFO_SIZE),
- ?line TcpiSackedOffset = ask_helper(Port,?C_GET_OFF_TCPI_SACKED),
- ?line TcpiOptionsOffset = ask_helper(Port,?C_GET_OFF_TCPI_OPTIONS),
- ?line TcpiSackedSize = ask_helper(Port,?C_GET_SIZ_TCPI_SACKED),
- ?line TcpiOptionsSize = ask_helper(Port,?C_GET_SIZ_TCPI_OPTIONS),
- ?line TcpLinger2 = ask_helper(Port,?C_GET_TCP_LINGER2),
- ?line stop_helper(Port),
+ Port = start_helper(Config),
+ Proto = ask_helper(Port,?C_GET_IPPROTO_TCP),
+ TcpInfo = ask_helper(Port,?C_GET_TCP_INFO),
+ TcpInfoSize = ask_helper(Port,?C_GET_TCP_INFO_SIZE),
+ TcpiSackedOffset = ask_helper(Port,?C_GET_OFF_TCPI_SACKED),
+ TcpiOptionsOffset = ask_helper(Port,?C_GET_OFF_TCPI_OPTIONS),
+ TcpiSackedSize = ask_helper(Port,?C_GET_SIZ_TCPI_SACKED),
+ TcpiOptionsSize = ask_helper(Port,?C_GET_SIZ_TCPI_OPTIONS),
+ TcpLinger2 = ask_helper(Port,?C_GET_TCP_LINGER2),
+ stop_helper(Port),
case all_ok([Proto,TcpInfo,TcpInfoSize,TcpiSackedOffset,
TcpiOptionsOffset,TcpiSackedSize,TcpiOptionsSize,
TcpLinger2]) of
false ->
{skipped,"Does not run on this OS."};
true ->
- ?line {Sock,I} = create_socketpair([],[]),
- ?line {ok,[{raw,Proto,TcpLinger2,<<OrigLinger:32/native>>}]} =
+ {Sock,I} = create_socketpair([],[]),
+ {ok,[{raw,Proto,TcpLinger2,<<OrigLinger:32/native>>}]} =
inet:getopts(Sock,[{raw,Proto,TcpLinger2,binarify(4,Binary)}]),
- ?line NewLinger = OrigLinger div 2,
- ?line ok = inet:setopts(Sock,[{raw,Proto,TcpLinger2,
- <<NewLinger:32/native>>}]),
- ?line {ok,[{raw,Proto,TcpLinger2,<<NewLinger:32/native>>}]} =
+ NewLinger = OrigLinger div 2,
+ ok = inet:setopts(Sock,[{raw,Proto,TcpLinger2,
+ <<NewLinger:32/native>>}]),
+ {ok,[{raw,Proto,TcpLinger2,<<NewLinger:32/native>>}]} =
inet:getopts(Sock,[{raw,Proto,TcpLinger2,binarify(4,Binary)}]),
- ?line ok = inet:setopts(Sock,[{raw,Proto,TcpLinger2,
- <<OrigLinger:32/native>>}]),
- ?line {ok,[{raw,Proto,TcpLinger2,<<OrigLinger:32/native>>}]} =
+ ok = inet:setopts(Sock,[{raw,Proto,TcpLinger2,
+ <<OrigLinger:32/native>>}]),
+ {ok,[{raw,Proto,TcpLinger2,<<OrigLinger:32/native>>}]} =
inet:getopts(Sock,[{raw,Proto,TcpLinger2,binarify(4,Binary)}]),
- ?line {ok,[{raw,_,_,Info}]} =
+ {ok,[{raw,_,_,Info}]} =
inet:getopts(Sock,[{raw,Proto,TcpInfo,
binarify(TcpInfoSize,Binary)}]),
- ?line Bit1 = TcpiSackedSize * 8,
- ?line <<_:TcpiSackedOffset/binary,
- TcpiSacked:Bit1/native,_/binary>> =
+ Bit1 = TcpiSackedSize * 8,
+ <<_:TcpiSackedOffset/binary,
+ TcpiSacked:Bit1/native,_/binary>> =
Info,
- ?line 0 = TcpiSacked,
- ?line Bit2 = TcpiOptionsSize * 8,
- ?line <<_:TcpiOptionsOffset/binary,
- TcpiOptions:Bit2/native,_/binary>> =
+ 0 = TcpiSacked,
+ Bit2 = TcpiOptionsSize * 8,
+ <<_:TcpiOptionsOffset/binary,
+ TcpiOptions:Bit2/native,_/binary>> =
Info,
- ?line true = TcpiOptions =/= 0,
- ?line gen_tcp:close(Sock),
- ?line gen_tcp:close(I),
+ true = TcpiOptions =/= 0,
+ gen_tcp:close(Sock),
+ gen_tcp:close(I),
ok
end.
-
-large_raw(suite) -> [];
-large_raw(doc) -> "Test structs and large/too large buffers when raw";
+
+%% Test structs and large/too large buffers when raw.
large_raw(Config) when is_list(Config) ->
do_large_raw(Config,false).
-large_raw_getbin(suite) -> [];
-large_raw_getbin(doc) -> "Test structs and large/too large buffers when raw"
- "using binaries to getopts";
+
+%% Test structs and large/too large buffers when raw
+%% using binaries to getopts.
large_raw_getbin(Config) when is_list(Config) ->
do_large_raw(Config,true).
+
do_large_raw(Config,Binary) when is_list(Config) ->
- ?line Port = start_helper(Config),
- ?line Proto = ask_helper(Port,?C_GET_SOL_SOCKET),
- ?line Linger = ask_helper(Port,?C_GET_SO_LINGER),
- ?line LingerSize = ask_helper(Port,?C_GET_LINGER_SIZE),
- ?line LingerOnOffOffset = ask_helper(Port,?C_GET_OFF_LINGER_L_ONOFF),
- ?line LingerLingerOffset = ask_helper(Port,?C_GET_OFF_LINGER_L_LINGER),
- ?line LingerOnOffSize = ask_helper(Port,?C_GET_SIZ_LINGER_L_ONOFF),
- ?line LingerLingerSize = ask_helper(Port,?C_GET_SIZ_LINGER_L_LINGER),
- ?line stop_helper(Port),
+ Port = start_helper(Config),
+ Proto = ask_helper(Port,?C_GET_SOL_SOCKET),
+ Linger = ask_helper(Port,?C_GET_SO_LINGER),
+ LingerSize = ask_helper(Port,?C_GET_LINGER_SIZE),
+ LingerOnOffOffset = ask_helper(Port,?C_GET_OFF_LINGER_L_ONOFF),
+ LingerLingerOffset = ask_helper(Port,?C_GET_OFF_LINGER_L_LINGER),
+ LingerOnOffSize = ask_helper(Port,?C_GET_SIZ_LINGER_L_ONOFF),
+ LingerLingerSize = ask_helper(Port,?C_GET_SIZ_LINGER_L_LINGER),
+ stop_helper(Port),
case all_ok([Proto,Linger,LingerSize,LingerOnOffOffset,
LingerLingerOffset,LingerOnOffSize,LingerLingerSize]) of
false ->
{skipped,"Does not run on this OS."};
true ->
- ?line {Sock1,Sock2} = create_socketpair([{linger,{true,10}}],
- [{linger,{false,0}}]),
- ?line LargeSize = 1024, % Solaris can take up to 1024*9,
- % linux 1024*63...
- ?line TooLargeSize = 1024*64,
- ?line {ok,[{raw,Proto,Linger,Linger1}]} =
+ {Sock1,Sock2} = create_socketpair([{linger,{true,10}}],
+ [{linger,{false,0}}]),
+ LargeSize = 1024, % Solaris can take up to 1024*9,
+ % linux 1024*63...
+ TooLargeSize = 1024*64,
+ {ok,[{raw,Proto,Linger,Linger1}]} =
inet:getopts(Sock1,[{raw,Proto,Linger,
binarify(LargeSize,Binary)}]),
- ?line {ok,[{raw,Proto,Linger,Linger2}]} =
+ {ok,[{raw,Proto,Linger,Linger2}]} =
inet:getopts(Sock2,[{raw,Proto,Linger,
binarify(LingerSize,Binary)}]),
- ?line true = byte_size(Linger1) =:= LingerSize,
- ?line LingerLingerBits = LingerLingerSize * 8,
- ?line LingerOnOffBits = LingerOnOffSize * 8,
- ?line <<_:LingerLingerOffset/binary,
- Ling1:LingerLingerBits/native,_/binary>> = Linger1,
- ?line <<_:LingerOnOffOffset/binary,
- Off1:LingerOnOffBits/native,_/binary>> = Linger1,
- ?line <<_:LingerOnOffOffset/binary,
- Off2:LingerOnOffBits/native,_/binary>> = Linger2,
- ?line true = Off1 =/= 0,
- ?line true = Off2 == 0,
- ?line true = Ling1 == 10,
- ?line {error,einval} =
+ true = byte_size(Linger1) =:= LingerSize,
+ LingerLingerBits = LingerLingerSize * 8,
+ LingerOnOffBits = LingerOnOffSize * 8,
+ <<_:LingerLingerOffset/binary,
+ Ling1:LingerLingerBits/native,_/binary>> = Linger1,
+ <<_:LingerOnOffOffset/binary,
+ Off1:LingerOnOffBits/native,_/binary>> = Linger1,
+ <<_:LingerOnOffOffset/binary,
+ Off2:LingerOnOffBits/native,_/binary>> = Linger2,
+ true = Off1 =/= 0,
+ true = Off2 == 0,
+ true = Ling1 == 10,
+ {error,einval} =
inet:getopts(Sock1,[{raw,Proto,Linger,TooLargeSize}]),
- ?line gen_tcp:close(Sock1),
- ?line gen_tcp:close(Sock2),
+ gen_tcp:close(Sock1),
+ gen_tcp:close(Sock2),
ok
end.
-combined(suite) -> [];
-combined(doc) -> "Test raw structs combined w/ other options ";
+%% Test raw structs combined w/ other options .
combined(Config) when is_list(Config) ->
do_combined(Config,false).
-combined_getbin(suite) -> [];
-combined_getbin(doc) -> "Test raw structs combined w/ other options and "
- "binarise in getopts";
+
+%% Test raw structs combined w/ other options and
+%% binarise in getopts.
combined_getbin(Config) when is_list(Config) ->
do_combined(Config,true).
+
do_combined(Config,Binary) when is_list(Config) ->
- ?line Port = start_helper(Config),
- ?line Proto = ask_helper(Port,?C_GET_SOL_SOCKET),
- ?line Linger = ask_helper(Port,?C_GET_SO_LINGER),
- ?line LingerSize = ask_helper(Port,?C_GET_LINGER_SIZE),
- ?line LingerOnOffOffset = ask_helper(Port,?C_GET_OFF_LINGER_L_ONOFF),
- ?line LingerLingerOffset = ask_helper(Port,?C_GET_OFF_LINGER_L_LINGER),
- ?line LingerOnOffSize = ask_helper(Port,?C_GET_SIZ_LINGER_L_ONOFF),
- ?line LingerLingerSize = ask_helper(Port,?C_GET_SIZ_LINGER_L_LINGER),
- ?line stop_helper(Port),
+ Port = start_helper(Config),
+ Proto = ask_helper(Port,?C_GET_SOL_SOCKET),
+ Linger = ask_helper(Port,?C_GET_SO_LINGER),
+ LingerSize = ask_helper(Port,?C_GET_LINGER_SIZE),
+ LingerOnOffOffset = ask_helper(Port,?C_GET_OFF_LINGER_L_ONOFF),
+ LingerLingerOffset = ask_helper(Port,?C_GET_OFF_LINGER_L_LINGER),
+ LingerOnOffSize = ask_helper(Port,?C_GET_SIZ_LINGER_L_ONOFF),
+ LingerLingerSize = ask_helper(Port,?C_GET_SIZ_LINGER_L_LINGER),
+ stop_helper(Port),
case all_ok([Proto,Linger,LingerSize,LingerOnOffOffset,
LingerLingerOffset,LingerOnOffSize,LingerLingerSize]) of
false ->
{skipped,"Does not run on this OS."};
true ->
- ?line LingerLingerBits = LingerLingerSize * 8,
- ?line LingerOnOffBits = LingerOnOffSize * 8,
- ?line {LingerOn,LingerOff} =
+ LingerLingerBits = LingerLingerSize * 8,
+ LingerOnOffBits = LingerOnOffSize * 8,
+ {LingerOn,LingerOff} =
case LingerOnOffOffset < LingerLingerOffset of
true ->
Pad1 =
@@ -423,11 +416,11 @@ do_combined(Config,Binary) when is_list(Config) ->
lists:duplicate(Pad3Siz,
0)),
{<<Pad1/binary,1:LingerOnOffBits/native,
- Pad2/binary,10:LingerLingerBits/native,
- Pad3/binary>>,
+ Pad2/binary,10:LingerLingerBits/native,
+ Pad3/binary>>,
<<Pad1/binary,0:LingerOnOffBits/native,
- Pad2/binary,0:LingerLingerBits/native,
- Pad3/binary>>};
+ Pad2/binary,0:LingerLingerBits/native,
+ Pad3/binary>>};
false ->
Pad1 =
list_to_binary(
@@ -446,177 +439,174 @@ do_combined(Config,Binary) when is_list(Config) ->
lists:duplicate(Pad3Siz,
0)),
{<<Pad1/binary,1:LingerLingerBits/native,
- Pad2/binary,10:LingerOnOffBits/native,
- Pad3/binary>>,
+ Pad2/binary,10:LingerOnOffBits/native,
+ Pad3/binary>>,
<<Pad1/binary,0:LingerLingerBits/native,
- Pad2/binary,0:LingerOnOffBits/native,
- Pad3/binary>>}
+ Pad2/binary,0:LingerOnOffBits/native,
+ Pad3/binary>>}
end,
- ?line RawLingerOn = {raw,Proto,Linger,LingerOn},
- ?line RawLingerOff = {raw,Proto,Linger,LingerOff},
- ?line {Sock1,Sock2} =
+ RawLingerOn = {raw,Proto,Linger,LingerOn},
+ RawLingerOff = {raw,Proto,Linger,LingerOff},
+ {Sock1,Sock2} =
create_socketpair([{keepalive,true},
RawLingerOn],
[{keepalive,false},
RawLingerOff]),
- ?line {ok,[{raw,Proto,Linger,Linger1},{keepalive,Keep1}]} =
+ {ok,[{raw,Proto,Linger,Linger1},{keepalive,Keep1}]} =
inet:getopts(Sock1,[{raw,Proto,Linger,
binarify(LingerSize,Binary)},keepalive]),
- ?line {ok,[{raw,Proto,Linger,Linger2},{keepalive,Keep2}]} =
+ {ok,[{raw,Proto,Linger,Linger2},{keepalive,Keep2}]} =
inet:getopts(Sock2,[{raw,Proto,Linger,
binarify(LingerSize,Binary)},keepalive]),
- ?line true = byte_size(Linger1) =:= LingerSize,
- ?line <<_:LingerLingerOffset/binary,
- Ling1:LingerLingerBits/native,_/binary>> = Linger1,
- ?line <<_:LingerOnOffOffset/binary,
- Off1:LingerOnOffBits/native,_/binary>> = Linger1,
- ?line <<_:LingerOnOffOffset/binary,
- Off2:LingerOnOffBits/native,_/binary>> = Linger2,
- ?line true = Off1 =/= 0,
- ?line true = Off2 == 0,
- ?line true = Ling1 == 10,
- ?line true = Keep1 =:= true,
- ?line true = Keep2 =:= false,
- ?line {Sock3,Sock4} =
+ true = byte_size(Linger1) =:= LingerSize,
+ <<_:LingerLingerOffset/binary,
+ Ling1:LingerLingerBits/native,_/binary>> = Linger1,
+ <<_:LingerOnOffOffset/binary,
+ Off1:LingerOnOffBits/native,_/binary>> = Linger1,
+ <<_:LingerOnOffOffset/binary,
+ Off2:LingerOnOffBits/native,_/binary>> = Linger2,
+ true = Off1 =/= 0,
+ true = Off2 == 0,
+ true = Ling1 == 10,
+ true = Keep1 =:= true,
+ true = Keep2 =:= false,
+ {Sock3,Sock4} =
create_socketpair([RawLingerOn,{keepalive,true}],
[RawLingerOff,{keepalive,false}]),
- ?line {ok,[{raw,Proto,Linger,Linger3},{keepalive,Keep3}]} =
+ {ok,[{raw,Proto,Linger,Linger3},{keepalive,Keep3}]} =
inet:getopts(Sock3,[{raw,Proto,Linger,
binarify(LingerSize,Binary)},keepalive]),
- ?line {ok,[{raw,Proto,Linger,Linger4},{keepalive,Keep4}]} =
+ {ok,[{raw,Proto,Linger,Linger4},{keepalive,Keep4}]} =
inet:getopts(Sock4,[{raw,Proto,Linger,
binarify(LingerSize,Binary)},keepalive]),
- ?line true = byte_size(Linger3) =:= LingerSize,
- ?line <<_:LingerLingerOffset/binary,
- Ling3:LingerLingerBits/native,_/binary>> = Linger3,
- ?line <<_:LingerOnOffOffset/binary,
- Off3:LingerOnOffBits/native,_/binary>> = Linger3,
- ?line <<_:LingerOnOffOffset/binary,
- Off4:LingerOnOffBits/native,_/binary>> = Linger4,
- ?line true = Off3 =/= 0,
- ?line true = Off4 == 0,
- ?line true = Ling3 == 10,
- ?line true = Keep3 =:= true,
- ?line true = Keep4 =:= false,
- ?line {Sock5,Sock6} =
+ true = byte_size(Linger3) =:= LingerSize,
+ <<_:LingerLingerOffset/binary,
+ Ling3:LingerLingerBits/native,_/binary>> = Linger3,
+ <<_:LingerOnOffOffset/binary,
+ Off3:LingerOnOffBits/native,_/binary>> = Linger3,
+ <<_:LingerOnOffOffset/binary,
+ Off4:LingerOnOffBits/native,_/binary>> = Linger4,
+ true = Off3 =/= 0,
+ true = Off4 == 0,
+ true = Ling3 == 10,
+ true = Keep3 =:= true,
+ true = Keep4 =:= false,
+ {Sock5,Sock6} =
create_socketpair([{packet,4},RawLingerOn,{keepalive,true}],
[{packet,2},RawLingerOff,{keepalive,false}]),
- ?line {ok,[{packet,Pack5},{raw,Proto,Linger,Linger5},
- {keepalive,Keep5}]} =
+ {ok,[{packet,Pack5},{raw,Proto,Linger,Linger5},
+ {keepalive,Keep5}]} =
inet:getopts(Sock5,[packet,{raw,Proto,Linger,
binarify(LingerSize,Binary)},
keepalive]),
- ?line {ok,[{packet,Pack6},{raw,Proto,Linger,Linger6},
- {keepalive,Keep6}]} =
+ {ok,[{packet,Pack6},{raw,Proto,Linger,Linger6},
+ {keepalive,Keep6}]} =
inet:getopts(Sock6,[packet,{raw,Proto,Linger,
binarify(LingerSize,Binary)},
keepalive]),
- ?line true = byte_size(Linger5) =:= LingerSize,
- ?line <<_:LingerLingerOffset/binary,
- Ling5:LingerLingerBits/native,_/binary>> = Linger5,
- ?line <<_:LingerOnOffOffset/binary,
- Off5:LingerOnOffBits/native,_/binary>> = Linger5,
- ?line <<_:LingerOnOffOffset/binary,
- Off6:LingerOnOffBits/native,_/binary>> = Linger6,
- ?line true = Off5 =/= 0,
- ?line true = Off6 == 0,
- ?line true = Ling5 == 10,
- ?line true = Keep5 =:= true,
- ?line true = Keep6 =:= false,
- ?line true = Pack5 =:= 4,
- ?line true = Pack6 =:= 2,
- ?line inet:setopts(Sock6,[{packet,4},RawLingerOn,
- {keepalive,true}]),
- ?line {ok,[{packet,Pack7},{raw,Proto,Linger,Linger7},
- {keepalive,Keep7}]} =
+ true = byte_size(Linger5) =:= LingerSize,
+ <<_:LingerLingerOffset/binary,
+ Ling5:LingerLingerBits/native,_/binary>> = Linger5,
+ <<_:LingerOnOffOffset/binary,
+ Off5:LingerOnOffBits/native,_/binary>> = Linger5,
+ <<_:LingerOnOffOffset/binary,
+ Off6:LingerOnOffBits/native,_/binary>> = Linger6,
+ true = Off5 =/= 0,
+ true = Off6 == 0,
+ true = Ling5 == 10,
+ true = Keep5 =:= true,
+ true = Keep6 =:= false,
+ true = Pack5 =:= 4,
+ true = Pack6 =:= 2,
+ inet:setopts(Sock6,[{packet,4},RawLingerOn,
+ {keepalive,true}]),
+ {ok,[{packet,Pack7},{raw,Proto,Linger,Linger7},
+ {keepalive,Keep7}]} =
inet:getopts(Sock6,[packet,{raw,Proto,Linger,
binarify(LingerSize,Binary)},
keepalive]),
- ?line <<_:LingerOnOffOffset/binary,
- Off7:LingerOnOffBits/native,_/binary>> = Linger7,
- ?line true = Off7 =/= 0,
- ?line true = Keep7 =:= true,
- ?line true = Pack7 =:= 4,
- ?line gen_tcp:close(Sock1),
- ?line gen_tcp:close(Sock2),
- ?line gen_tcp:close(Sock3),
- ?line gen_tcp:close(Sock4),
- ?line gen_tcp:close(Sock5),
- ?line gen_tcp:close(Sock6),
+ <<_:LingerOnOffOffset/binary,
+ Off7:LingerOnOffBits/native,_/binary>> = Linger7,
+ true = Off7 =/= 0,
+ true = Keep7 =:= true,
+ true = Pack7 =:= 4,
+ gen_tcp:close(Sock1),
+ gen_tcp:close(Sock2),
+ gen_tcp:close(Sock3),
+ gen_tcp:close(Sock4),
+ gen_tcp:close(Sock5),
+ gen_tcp:close(Sock6),
ok
end.
-ipv6_v6only_udp(suite) -> [];
-ipv6_v6only_udp(doc) -> "Test socket option ipv6_v6only for UDP";
+%% Test socket option ipv6_v6only for UDP.
ipv6_v6only_udp(Config) when is_list(Config) ->
ipv6_v6only(Config, gen_udp).
-ipv6_v6only_tcp(suite) -> [];
-ipv6_v6only_tcp(doc) -> "Test socket option ipv6_v6only for TCP";
+%% Test socket option ipv6_v6only for TCP.
ipv6_v6only_tcp(Config) when is_list(Config) ->
ipv6_v6only(Config, gen_tcp).
-ipv6_v6only_sctp(suite) -> [];
-ipv6_v6only_sctp(doc) -> "Test socket option ipv6_v6only for SCTP";
+%% Test socket option ipv6_v6only for SCTP.
ipv6_v6only_sctp(Config) when is_list(Config) ->
ipv6_v6only(Config, gen_sctp).
ipv6_v6only(Config, Module) when is_list(Config) ->
- ?line case ipv6_v6only_open(Module, []) of
- {ok,S1} ->
- ?line case inet:getopts(S1, [ipv6_v6only]) of
- {ok,[{ipv6_v6only,Default}]}
- when is_boolean(Default) ->
- ?line ok =
- ipv6_v6only_close(Module, S1),
- ?line ipv6_v6only(Config, Module, Default);
- {ok,[]} ->
- ?line io:format("Not implemented.~n", []),
- %% This list of OS:es where the option is
- %% supposed to be not implemented is just
- %% a guess, and may grow with time.
- ?line case {os:type(),os:version()} of
- {{unix,linux},{2,M,_}}
- when M =< 4 -> ok
- end,
- %% At least this should work
- ?line {ok,S2} =
- ipv6_v6only_open(
- Module,
- [{ipv6_v6only,true}]),
- ?line ok =
- ipv6_v6only_close(Module, S2)
- end;
- {error,_} ->
- {skipped,"Socket type not supported"}
- end.
+ case ipv6_v6only_open(Module, []) of
+ {ok,S1} ->
+ case inet:getopts(S1, [ipv6_v6only]) of
+ {ok,[{ipv6_v6only,Default}]}
+ when is_boolean(Default) ->
+ ok =
+ ipv6_v6only_close(Module, S1),
+ ipv6_v6only(Config, Module, Default);
+ {ok,[]} ->
+ io:format("Not implemented.~n", []),
+ %% This list of OS:es where the option is
+ %% supposed to be not implemented is just
+ %% a guess, and may grow with time.
+ case {os:type(),os:version()} of
+ {{unix,linux},{2,M,_}}
+ when M =< 4 -> ok
+ end,
+ %% At least this should work
+ {ok,S2} =
+ ipv6_v6only_open(
+ Module,
+ [{ipv6_v6only,true}]),
+ ok =
+ ipv6_v6only_close(Module, S2)
+ end;
+ {error,_} ->
+ {skipped,"Socket type not supported"}
+ end.
ipv6_v6only(Config, Module, Default) when is_list(Config) ->
- ?line io:format("Default ~w.~n", [Default]),
- ?line {ok,S1} =
+ io:format("Default ~w.~n", [Default]),
+ {ok,S1} =
ipv6_v6only_open(Module, [{ipv6_v6only,Default}]),
- ?line {ok,[{ipv6_v6only,Default}]} =
+ {ok,[{ipv6_v6only,Default}]} =
inet:getopts(S1, [ipv6_v6only]),
- ?line ok =
+ ok =
ipv6_v6only_close(Module, S1),
- ?line NotDefault = not Default,
- ?line case ipv6_v6only_open(Module, [{ipv6_v6only,NotDefault}]) of
- {ok,S2} ->
- ?line io:format("Read-write.~n", []),
- ?line {ok,[{ipv6_v6only,NotDefault}]} =
- inet:getopts(S2, [ipv6_v6only]),
- ok;
- {error,einval} ->
- ?line io:format("Read-only.~n", []),
- %% This option is known to be read-only and true
- %% on Windows and OpenBSD
- ?line case os:type() of
- {unix,openbsd} when Default =:= true -> ok;
- {win32,_} when Default =:= true -> ok
- end
- end.
+ NotDefault = not Default,
+ case ipv6_v6only_open(Module, [{ipv6_v6only,NotDefault}]) of
+ {ok,S2} ->
+ io:format("Read-write.~n", []),
+ {ok,[{ipv6_v6only,NotDefault}]} =
+ inet:getopts(S2, [ipv6_v6only]),
+ ok;
+ {error,einval} ->
+ io:format("Read-only.~n", []),
+ %% This option is known to be read-only and true
+ %% on Windows and OpenBSD
+ case os:type() of
+ {unix,openbsd} when Default =:= true -> ok;
+ {win32,_} when Default =:= true -> ok
+ end
+ end.
ipv6_v6only_open(Module, Opts) ->
Module:case Module of
@@ -628,47 +618,46 @@ ipv6_v6only_close(Module, Socket) ->
Module:close(Socket).
-use_ipv6_v6only_udp(suite) -> [];
-use_ipv6_v6only_udp(doc) -> "Test using socket option ipv6_v6only for UDP";
+%% Test using socket option ipv6_v6only for UDP.
use_ipv6_v6only_udp(Config) when is_list(Config) ->
- ?line case gen_udp:open(0, [inet6,{ipv6_v6only,true}]) of
- {ok,S6} ->
- ?line case inet:getopts(S6, [ipv6_v6only]) of
- {ok,[{ipv6_v6only,true}]} ->
- use_ipv6_v6only_udp(Config, S6);
- {ok,Other} ->
- {skipped,{getopts,Other}}
- end;
- {error,_} ->
- {skipped,"Socket type not supported"}
- end.
+ case gen_udp:open(0, [inet6,{ipv6_v6only,true}]) of
+ {ok,S6} ->
+ case inet:getopts(S6, [ipv6_v6only]) of
+ {ok,[{ipv6_v6only,true}]} ->
+ use_ipv6_v6only_udp(Config, S6);
+ {ok,Other} ->
+ {skipped,{getopts,Other}}
+ end;
+ {error,_} ->
+ {skipped,"Socket type not supported"}
+ end.
use_ipv6_v6only_udp(_Config, S6) ->
- ?line {ok,Port} = inet:port(S6),
- ?line {ok,S4} = gen_udp:open(Port, [inet]),
- ?line E6 = " IPv6-echo.",
- ?line E4 = " IPv4-echo.",
- ?line Sender =
+ {ok,Port} = inet:port(S6),
+ {ok,S4} = gen_udp:open(Port, [inet]),
+ E6 = " IPv6-echo.",
+ E4 = " IPv4-echo.",
+ Sender =
spawn_link(fun () -> use_ipv6_v6only_udp_sender(Port, E6, E4) end),
- ?line use_ipv6_v6only_udp_listener(
- S6, S4, E6, E4, monitor(process, Sender)).
+ use_ipv6_v6only_udp_listener(
+ S6, S4, E6, E4, monitor(process, Sender)).
use_ipv6_v6only_udp_listener(S6, S4, E6, E4, Mref) ->
- ?line receive
- {udp,S6,IP,P,Data} ->
- ?line ok = gen_udp:send(S6, IP, P, [Data|E6]),
- ?line use_ipv6_v6only_udp_listener(S6, S4, E6, E4, Mref);
- {udp,S4,IP,P,Data} ->
- ?line ok = gen_udp:send(S4, IP, P, [Data|E4]),
- ?line use_ipv6_v6only_udp_listener(S6, S4, E6, E4, Mref);
- {'DOWN',Mref,_,_,normal} ->
- ok;
- {'DOWN',Mref,_,_,Result} ->
- %% Since we are linked we will never arrive here
- Result;
- Other ->
- ?line exit({failed,{listener_unexpected,Other}})
- end.
+ receive
+ {udp,S6,IP,P,Data} ->
+ ok = gen_udp:send(S6, IP, P, [Data|E6]),
+ use_ipv6_v6only_udp_listener(S6, S4, E6, E4, Mref);
+ {udp,S4,IP,P,Data} ->
+ ok = gen_udp:send(S4, IP, P, [Data|E4]),
+ use_ipv6_v6only_udp_listener(S6, S4, E6, E4, Mref);
+ {'DOWN',Mref,_,_,normal} ->
+ ok;
+ {'DOWN',Mref,_,_,Result} ->
+ %% Since we are linked we will never arrive here
+ Result;
+ Other ->
+ exit({failed,{listener_unexpected,Other}})
+ end.
use_ipv6_v6only_udp_sender(Port, E6, E4) ->
D6 = "IPv6-send.",
@@ -693,12 +682,9 @@ sndrcv(Ip, Port, Opts, Data) ->
-type_errors(suite) ->
- [];
-type_errors(doc) ->
- "Test that raw data requests are not executed for bad types";
+%% Test that raw data requests are not executed for bad types.
type_errors(Config) when is_list(Config) ->
- ?line BadSetOptions =
+ BadSetOptions =
[
{raw,x,3,<<1:32>>},
{raw,1,tre,<<1:32>>},
@@ -716,7 +702,7 @@ type_errors(Config) when is_list(Config) ->
rav,
{linger,banan}
],
- ?line BadGetOptions =
+ BadGetOptions =
[
{raw,x,3,<<1:32>>},
{raw,1,tre,<<1:32>>},
@@ -735,46 +721,46 @@ type_errors(Config) when is_list(Config) ->
rav,
{linger,banan}
],
- ?line lists:foreach(fun(Option) ->
- ?line case
- catch create_socketpair([Option],[]) of
- {'EXIT',badarg} ->
- ?line ok;
- Unexpected1 ->
- ?line exit({unexpected,
- Unexpected1})
- end,
- ?line case
- catch create_socketpair([],[Option]) of
- {'EXIT',badarg} ->
- ?line ok;
- Unexpected2 ->
- ?line exit({unexpected,
- Unexpected2})
- end,
- ?line {Sock1,Sock2} = create_socketpair([],[]),
- ?line case inet:setopts(Sock1, [Option]) of
- {error,einval} ->
- ?line ok;
- Unexpected3 ->
- ?line exit({unexpected,
- Unexpected3})
- end,
- ?line gen_tcp:close(Sock1),
- ?line gen_tcp:close(Sock2)
- end,BadSetOptions),
- ?line {Sock1,Sock2} = create_socketpair([],[]),
- ?line lists:foreach(fun(Option) ->
- ?line case inet:getopts(Sock1, [Option]) of
- {error,einval} ->
- ?line ok;
- Unexpected ->
- ?line exit({unexpected,
- Unexpected})
- end
- end,BadGetOptions),
- ?line gen_tcp:close(Sock1),
- ?line gen_tcp:close(Sock2),
+ lists:foreach(fun(Option) ->
+ case
+ catch create_socketpair([Option],[]) of
+ {'EXIT',badarg} ->
+ ok;
+ Unexpected1 ->
+ exit({unexpected,
+ Unexpected1})
+ end,
+ case
+ catch create_socketpair([],[Option]) of
+ {'EXIT',badarg} ->
+ ok;
+ Unexpected2 ->
+ exit({unexpected,
+ Unexpected2})
+ end,
+ {Sock1,Sock2} = create_socketpair([],[]),
+ case inet:setopts(Sock1, [Option]) of
+ {error,einval} ->
+ ok;
+ Unexpected3 ->
+ exit({unexpected,
+ Unexpected3})
+ end,
+ gen_tcp:close(Sock1),
+ gen_tcp:close(Sock2)
+ end,BadSetOptions),
+ {Sock1,Sock2} = create_socketpair([],[]),
+ lists:foreach(fun(Option) ->
+ case inet:getopts(Sock1, [Option]) of
+ {error,einval} ->
+ ok;
+ Unexpected ->
+ exit({unexpected,
+ Unexpected})
+ end
+ end,BadGetOptions),
+ gen_tcp:close(Sock1),
+ gen_tcp:close(Sock2),
ok.
all_ok([]) ->
@@ -784,59 +770,59 @@ all_ok([H|T]) when H >= 0 ->
all_ok(_) ->
false.
-
+
make_check_fun(Type,Element) ->
fun({Name,V1,V2,Mand,Chang},Acc) ->
- ?line {LO1,CO1} = setelement(Element,{[],[]}, [{Name,V1}]),
- ?line {LO2,CO2} = setelement(Element,{[],[]}, [{Name,V2}]),
- ?line {X1,Y1} = create_socketpair(LO1,CO1),
- ?line {X2,Y2} = create_socketpair(LO2,CO2),
- ?line S1 = element(Element,{X1,Y1}),
- ?line S2 = element(Element,{X2,Y2}),
- ?line {ok,[{Name,R1}]} = inet:getopts(S1,[Name]),
- ?line {ok,[{Name,R2}]} = inet:getopts(S2,[Name]),
+ {LO1,CO1} = setelement(Element,{[],[]}, [{Name,V1}]),
+ {LO2,CO2} = setelement(Element,{[],[]}, [{Name,V2}]),
+ {X1,Y1} = create_socketpair(LO1,CO1),
+ {X2,Y2} = create_socketpair(LO2,CO2),
+ S1 = element(Element,{X1,Y1}),
+ S2 = element(Element,{X2,Y2}),
+ {ok,[{Name,R1}]} = inet:getopts(S1,[Name]),
+ {ok,[{Name,R2}]} = inet:getopts(S2,[Name]),
NewAcc =
case R1 =/= R2 of
true ->
case Chang of
true ->
- ?line inet:setopts(S1,[{Name,V2}]),
- ?line {ok,[{Name,R3}]} =
+ inet:setopts(S1,[{Name,V2}]),
+ {ok,[{Name,R3}]} =
inet:getopts(S1,[Name]),
case {R3 =/= R1, R3 =:= R2} of
{true,true} ->
- ?line Acc;
+ Acc;
_ ->
case Mand of
true ->
- ?line exit
- ({failed_sockopt,
- {change,
- Name}});
+ exit
+ ({failed_sockopt,
+ {change,
+ Name}});
false ->
- ?line [{change,Name}|Acc]
+ [{change,Name}|Acc]
end
end;
false ->
- ?line Acc
+ Acc
end;
false ->
case Mand of
true ->
- ?line exit({failed_sockopt,
- {Type,Name}});
+ exit({failed_sockopt,
+ {Type,Name}});
false ->
- ?line [{Type,Name}|Acc]
+ [{Type,Name}|Acc]
end
end,
- ?line gen_tcp:close(X1),
- ?line gen_tcp:close(Y1),
- ?line gen_tcp:close(X2),
- ?line gen_tcp:close(Y2),
+ gen_tcp:close(X1),
+ gen_tcp:close(Y1),
+ gen_tcp:close(X2),
+ gen_tcp:close(Y2),
NewAcc
- end.
+ end.
-% {OptionName,Value1,Value2,Mandatory,Changeable}
+%% {OptionName,Value1,Value2,Mandatory,Changeable}
all_listen_options() ->
[{tos,0,1,false,true},
{priority,0,1,false,true},
@@ -887,19 +873,19 @@ all_connect_options() ->
{delay_send,false,true,true,true},
{packet_size,0,4,true,true}
].
-
+
create_socketpair(ListenOptions,ConnectOptions) ->
- ?line {ok,LS}=gen_tcp:listen(0,ListenOptions),
- ?line {ok,Port}=inet:port(LS),
- ?line {ok,CS}=gen_tcp:connect(localhost,Port,ConnectOptions),
- ?line {ok,AS}=gen_tcp:accept(LS),
- ?line gen_tcp:close(LS),
+ {ok,LS}=gen_tcp:listen(0,ListenOptions),
+ {ok,Port}=inet:port(LS),
+ {ok,CS}=gen_tcp:connect(localhost,Port,ConnectOptions),
+ {ok,AS}=gen_tcp:accept(LS),
+ gen_tcp:close(LS),
{AS,CS}.
start_helper(Config) ->
- Progname = filename:join(?config(data_dir, Config), "sockopt_helper"),
+ Progname = filename:join(proplists:get_value(data_dir, Config), "sockopt_helper"),
Port = open_port({spawn,Progname},[eof,line]),
Port.
diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl
index 54ab5aa566..0fa97b585c 100644
--- a/lib/kernel/test/init_SUITE.erl
+++ b/lib/kernel/test/init_SUITE.erl
@@ -19,13 +19,13 @@
%%
-module(init_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
-export([get_arguments/1, get_argument/1, boot_var/1, restart/1,
- many_restarts/1,
+ many_restarts/0, many_restarts/1,
get_plain_arguments/1,
reboot/1, stop/1, get_status/1, script_id/1]).
-export([boot1/1, boot2/1]).
@@ -41,7 +41,9 @@
%% Should be started in a CC view with:
%% erl -sname master -rsh ctrsh
%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,2}}].
all() ->
[get_arguments, get_argument, boot_var,
@@ -65,46 +67,35 @@ end_per_group(_GroupName, Config) ->
Config.
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?t:timetrap(?t:seconds(?DEFAULT_TIMEOUT_SEC)),
- [{watchdog, Dog}|Config].
+init_per_testcase(Func, Config) ->
+ Config.
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
+end_per_testcase(_Func, _Config) ->
+ ok.
-init(doc) -> [];
-init(suite) -> [];
init(Config) when is_list(Config) ->
Config.
-fini(doc) -> [];
-fini(suite) -> [];
fini(Config) when is_list(Config) ->
Host = list_to_atom(from($@, atom_to_list(node()))),
Node = list_to_atom(lists:concat([init_test, "@", Host])),
stop_node(Node),
Config.
-get_arguments(doc) ->[];
-get_arguments(suite) -> {req, [distribution, {local_slave_nodes, 1}]};
get_arguments(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(10)),
-
Args = args(),
- ?line {ok, Node} = start_node(init_test, Args),
- ?line case rpc:call(Node, init, get_arguments, []) of
- Arguments when is_list(Arguments) ->
- stop_node(Node),
- check_a(Arguments),
- check_b(Arguments),
- check_c(Arguments),
- check_d(Arguments);
- _ ->
- stop_node(Node),
- ?t:fail(get_arguments)
- end,
- ?line ?t:timetrap_cancel(Dog),
+ {ok, Node} = start_node(init_test, Args),
+ case rpc:call(Node, init, get_arguments, []) of
+ Arguments when is_list(Arguments) ->
+ stop_node(Node),
+ check_a(Arguments),
+ check_b(Arguments),
+ check_c(Arguments),
+ check_d(Arguments);
+ _ ->
+ stop_node(Node),
+ ct:fail(get_arguments)
+ end,
ok.
check_a(Args) ->
@@ -115,10 +106,10 @@ check_a(Args) ->
false ->
ok;
_ ->
- ?t:fail(check_a1)
+ ct:fail(check_a1)
end;
_ ->
- ?t:fail(check_a2)
+ ct:fail(check_a2)
end.
check_b(Args) ->
@@ -132,13 +123,13 @@ check_b(Args) ->
false ->
ok;
_ ->
- ?t:fail(check_b1)
+ ct:fail(check_b1)
end;
_ ->
- ?t:fail(check_b2)
+ ct:fail(check_b2)
end;
_ ->
- ?t:fail(check_b3)
+ ct:fail(check_b3)
end.
check_c(Args) ->
@@ -152,13 +143,13 @@ check_c(Args) ->
false ->
ok;
_ ->
- ?t:fail(check_c1)
+ ct:fail(check_c1)
end;
_ ->
- ?t:fail(check_c2)
+ ct:fail(check_c2)
end;
_ ->
- ?t:fail(check_c3)
+ ct:fail(check_c3)
end.
check_d(Args) ->
@@ -169,62 +160,54 @@ check_d(Args) ->
false ->
ok;
_ ->
- ?t:fail(check_d1)
+ ct:fail(check_d1)
end;
_ ->
- ?t:fail(check_d2)
+ ct:fail(check_d2)
end.
-get_argument(doc) ->[];
-get_argument(suite) -> {req, [distribution, {local_slave_nodes, 1}]};
get_argument(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(10)),
-
Args = args(),
- ?line {ok, Node} = start_node(init_test, Args),
- ?line case rpc:call(Node, init, get_argument, [b]) of
- {ok, [["hej", "hopp"],["san", "sa"]]} ->
- ok;
- _ ->
- stop_node(Node),
- ?t:fail({get_argument, b})
- end,
- ?line case rpc:call(Node, init, get_argument, [a]) of
- {ok, [["kalle"]]} ->
- ok;
- _ ->
- stop_node(Node),
- ?t:fail({get_argument, a})
- end,
- ?line case rpc:call(Node, init, get_argument, [c]) of
- {ok, [["4", "5", "6"], ["7", "8", "9"]]} ->
- ok;
- _ ->
- stop_node(Node),
- ?t:fail({get_argument, c})
- end,
- ?line case rpc:call(Node, init, get_argument, [d]) of
- {ok, [[]]} ->
- ok;
- _ ->
- stop_node(Node),
- ?t:fail({get_argument, d})
- end,
- ?line case rpc:call(Node, init, get_argument, [e]) of
- error ->
- ok;
- _ ->
- stop_node(Node),
- ?t:fail({get_argument, e})
- end,
+ {ok, Node} = start_node(init_test, Args),
+ case rpc:call(Node, init, get_argument, [b]) of
+ {ok, [["hej", "hopp"],["san", "sa"]]} ->
+ ok;
+ _ ->
+ stop_node(Node),
+ ct:fail({get_argument, b})
+ end,
+ case rpc:call(Node, init, get_argument, [a]) of
+ {ok, [["kalle"]]} ->
+ ok;
+ _ ->
+ stop_node(Node),
+ ct:fail({get_argument, a})
+ end,
+ case rpc:call(Node, init, get_argument, [c]) of
+ {ok, [["4", "5", "6"], ["7", "8", "9"]]} ->
+ ok;
+ _ ->
+ stop_node(Node),
+ ct:fail({get_argument, c})
+ end,
+ case rpc:call(Node, init, get_argument, [d]) of
+ {ok, [[]]} ->
+ ok;
+ _ ->
+ stop_node(Node),
+ ct:fail({get_argument, d})
+ end,
+ case rpc:call(Node, init, get_argument, [e]) of
+ error ->
+ ok;
+ _ ->
+ stop_node(Node),
+ ct:fail({get_argument, e})
+ end,
stop_node(Node),
- ?line ?t:timetrap_cancel(Dog),
ok.
-get_plain_arguments(doc) ->[];
-get_plain_arguments(suite) -> {req, [distribution, {local_slave_nodes, 1}]};
get_plain_arguments(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(10)),
Longstring =
"fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2"
"fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2"
@@ -235,18 +218,17 @@ get_plain_arguments(Config) when is_list(Config) ->
"fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2"
"fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2"
"fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2",
- ?line true = (length(Longstring) > 255),
+ true = (length(Longstring) > 255),
Args = long_args(Longstring),
- ?line {ok, Node} = start_node(init_test, Args),
- ?line case rpc:call(Node, init, get_plain_arguments, []) of
- ["a", "b", "c", Longstring] ->
- ok;
- As ->
- stop_node(Node),
- ?t:fail({get_argument, As})
- end,
+ {ok, Node} = start_node(init_test, Args),
+ case rpc:call(Node, init, get_plain_arguments, []) of
+ ["a", "b", "c", Longstring] ->
+ ok;
+ As ->
+ stop_node(Node),
+ ct:fail({get_argument, As})
+ end,
stop_node(Node),
- ?line ?t:timetrap_cancel(Dog),
ok.
@@ -254,199 +236,182 @@ get_plain_arguments(Config) when is_list(Config) ->
%% ------------------------------------------------
%% Use -boot_var flag to set $TEST_VAR in boot script.
%% ------------------------------------------------
-boot_var(doc) -> [];
-boot_var(suite) -> {req, [distribution, {local_slave_nodes, 1}]};
boot_var(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(100)),
-
{BootScript, TEST_VAR, KernelVsn, StdlibVsn} = create_boot(Config),
%% Should fail as we have not given -boot_var TEST_VAR
- ?line {error, timeout} =
- start_node(init_test, "-boot " ++ BootScript),
+ {error, timeout} =
+ start_node(init_test, "-boot " ++ BootScript),
case is_real_system(KernelVsn, StdlibVsn) of
true ->
%% Now it should work !!
- ?line {ok, Node} =
- start_node(init_test,
- "-boot " ++ BootScript ++
- " -boot_var TEST_VAR " ++ TEST_VAR),
+ {ok, Node} =
+ start_node(init_test,
+ "-boot " ++ BootScript ++
+ " -boot_var TEST_VAR " ++ TEST_VAR),
stop_node(Node),
Res = ok;
_ ->
%% What we need is not so much version numbers on the directories, but
%% for the boot var TEST_VAR to appear in the boot script, and it doesn't
%% if we give the 'local' option to systools:make_script.
- ?t:format(
- "Test case not complete as we are not~n"
- "running in a real system!~n"
- "Probably this test is performed in a "
- "clearcase view or source tree.~n"
- "Need version numbers on the kernel and "
- "stdlib directories!~n",
- []),
+ io:format(
+ "Test case not complete as we are not~n"
+ "running in a real system!~n"
+ "Probably this test is performed in a "
+ "clearcase view or source tree.~n"
+ "Need version numbers on the kernel and "
+ "stdlib directories!~n",
+ []),
Res = {skip,
- "Test case only partially run since it is run "
- "in a clearcase view or in a source tree. "
- "Need an installed system to complete this test."}
+ "Test case only partially run since it is run "
+ "in a clearcase view or in a source tree. "
+ "Need an installed system to complete this test."}
end,
- ?line ?t:timetrap_cancel(Dog),
Res.
create_boot(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
- ?line {LatestDir, LatestName, KernelVsn, StdlibVsn} =
+ {ok, OldDir} = file:get_cwd(),
+ {LatestDir, LatestName, KernelVsn, StdlibVsn} =
create_script(Config),
LibDir = code:lib_dir(),
- ?line ok = file:set_cwd(LatestDir),
- ?line ok = systools:make_script(LatestName,
- [{variables, [{"TEST_VAR", LibDir}]}]),
- ?line ok = file:set_cwd(OldDir),
+ ok = file:set_cwd(LatestDir),
+ ok = systools:make_script(LatestName,
+ [{variables, [{"TEST_VAR", LibDir}]}]),
+ ok = file:set_cwd(OldDir),
{LatestDir ++ "/" ++ LatestName, LibDir, KernelVsn, StdlibVsn}.
is_real_system(KernelVsn, StdlibVsn) ->
LibDir = code:lib_dir(),
- filelib:is_dir(filename:join(LibDir, "kernel"++KernelVsn)) andalso
- filelib:is_dir(filename:join(LibDir, "stdlib"++StdlibVsn)).
-
+ filelib:is_dir(filename:join(LibDir, "kernel-"++KernelVsn)) andalso
+ filelib:is_dir(filename:join(LibDir, "stdlib-"++StdlibVsn)).
+
%% ------------------------------------------------
%% Slave executes erlang:halt() on master nodedown.
%% Therefore the slave process must be killed
%% before restart.
%% ------------------------------------------------
-many_restarts(doc) -> [];
-many_restarts(suite) ->
- case ?t:os_type() of
- {Fam, _} when Fam == unix; Fam == win32 ->
- {req, [distribution, {local_slave_nodes, 1}, {time, 5}]};
- _ ->
- {skip, "Only run on unix and win32"}
- end;
+many_restarts() ->
+ [{timetrap,{minutes,8}}].
many_restarts(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(480)),
- ?line {ok, Node} = loose_node:start(init_test, "", ?DEFAULT_TIMEOUT_SEC),
- ?line loop_restart(30,Node,rpc:call(Node,erlang,whereis,[error_logger])),
- ?line loose_node:stop(Node),
- ?line ?t:timetrap_cancel(Dog),
+ {ok, Node} = loose_node:start(init_test, "", ?DEFAULT_TIMEOUT_SEC),
+ loop_restart(30,Node,rpc:call(Node,erlang,whereis,[error_logger])),
+ loose_node:stop(Node),
ok.
loop_restart(0,_,_) ->
ok;
loop_restart(N,Node,EHPid) ->
- ?line erlang:monitor_node(Node, true),
- ?line ok = rpc:call(Node, init, restart, []),
- ?line receive
- {nodedown, Node} ->
- ok
- after 10000 ->
- loose_node:stop(Node),
- ?t:fail(not_stopping)
- end,
- ?line ok = wait_for(30, Node, EHPid),
- ?line loop_restart(N-1,Node,rpc:call(Node,erlang,whereis,[error_logger])).
+ erlang:monitor_node(Node, true),
+ ok = rpc:call(Node, init, restart, []),
+ receive
+ {nodedown, Node} ->
+ ok
+ after 10000 ->
+ loose_node:stop(Node),
+ ct:fail(not_stopping)
+ end,
+ ok = wait_for(30, Node, EHPid),
+ loop_restart(N-1,Node,rpc:call(Node,erlang,whereis,[error_logger])).
wait_for(0,Node,_) ->
loose_node:stop(Node),
error;
wait_for(N,Node,EHPid) ->
- ?line case rpc:call(Node, erlang, whereis, [error_logger]) of
+ case rpc:call(Node, erlang, whereis, [error_logger]) of
Pid when is_pid(Pid), Pid =/= EHPid ->
- %% ?line erlang:display(ok),
- ?line ok;
+ %% erlang:display(ok),
+ ok;
_X ->
- %% ?line erlang:display(_X),
- %% ?line Procs = rpc:call(Node, erlang, processes, []),
- %% ?line erlang:display(Procs),
- %% case is_list(Procs) of
- %% true ->
- %% ?line [(catch erlang:display(
- %% rpc:call(Node,
- %% erlang,
- %% process_info,
- %% [Y,registered_name])))
- %% || Y <- Procs];
- %% _ ->
- %% ok
- %% end,
- receive
- after 100 ->
- ok
- end,
- ?line wait_for(N-1,Node,EHPid)
- end.
+ %% erlang:display(_X),
+ %% Procs = rpc:call(Node, erlang, processes, []),
+ %% erlang:display(Procs),
+ %% case is_list(Procs) of
+ %% true ->
+ %% [(catch erlang:display(
+ %% rpc:call(Node,
+ %% erlang,
+ %% process_info,
+ %% [Y,registered_name])))
+ %% || Y <- Procs];
+ %% _ ->
+ %% ok
+ %% end,
+ receive
+ after 100 ->
+ ok
+ end,
+ wait_for(N-1,Node,EHPid)
+ end.
%% ------------------------------------------------
%% Slave executes erlang:halt() on master nodedown.
%% Therefore the slave process must be killed
%% before restart.
%% ------------------------------------------------
-restart(doc) -> [];
-restart(suite) ->
- case ?t:os_type() of
- {Fam, _} when Fam == unix; Fam == win32 ->
- {req, [distribution, {local_slave_nodes, 1}, {time, 5}]};
- _ ->
- {skip, "Only run on unix and win32"}
- end;
restart(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(40)),
- ?line Args = args(),
+ Args = args(),
%% Currently test_server:start_node cannot be used. The restarted
%% node immediately halts due to the implementation of
%% test_server:start_node.
- ?line {ok, Node} = loose_node:start(init_test, Args, ?DEFAULT_TIMEOUT_SEC),
+ {ok, Node} = loose_node:start(init_test, Args, ?DEFAULT_TIMEOUT_SEC),
%% Ok, the node is up, now the real test test begins.
- ?line erlang:monitor_node(Node, true),
- ?line InitPid = rpc:call(Node, erlang, whereis, [init]),
- ?line Procs = rpc:call(Node, erlang, processes, []),
- ?line MaxPid = lists:last(Procs),
- ?line ok = rpc:call(Node, init, restart, []),
- ?line receive
- {nodedown, Node} ->
- ok
- after 10000 ->
- loose_node:stop(Node),
- ?t:fail(not_stopping)
- end,
- ?line ok = wait_restart(30, Node),
+ erlang:monitor_node(Node, true),
+ InitPid = rpc:call(Node, erlang, whereis, [init]),
+ PurgerPid = rpc:call(Node, erlang, whereis, [erts_code_purger]),
+ Procs = rpc:call(Node, erlang, processes, []),
+ MaxPid = lists:last(Procs),
+ ok = rpc:call(Node, init, restart, []),
+ receive
+ {nodedown, Node} ->
+ ok
+ after 10000 ->
+ loose_node:stop(Node),
+ ct:fail(not_stopping)
+ end,
+ ok = wait_restart(30, Node),
%% Still the same init process!
- ?line InitPid1 = rpc:call(Node, erlang, whereis, [init]),
+ InitPid1 = rpc:call(Node, erlang, whereis, [init]),
InitP = pid_to_list(InitPid),
- ?line InitP = pid_to_list(InitPid1),
-
- ?line NewProcs0 = rpc:call(Node, erlang, processes, []),
- NewProcs = lists:delete(InitPid1, NewProcs0),
- ?line case check_processes(NewProcs, MaxPid) of
- true ->
- ok;
- _ ->
- loose_node:stop(Node),
- ?t:fail(processes_not_greater)
- end,
+ InitP = pid_to_list(InitPid1),
+
+ %% and same purger process!
+ PurgerPid1 = rpc:call(Node, erlang, whereis, [erts_code_purger]),
+ PurgerP = pid_to_list(PurgerPid),
+ PurgerP = pid_to_list(PurgerPid1),
+
+ NewProcs0 = rpc:call(Node, erlang, processes, []),
+ NewProcs = NewProcs0 -- [InitPid1, PurgerPid1],
+ case check_processes(NewProcs, MaxPid) of
+ true ->
+ ok;
+ _ ->
+ loose_node:stop(Node),
+ ct:fail(processes_not_greater)
+ end,
%% Test that, for instance, the same argument still exists.
- ?line case rpc:call(Node, init, get_argument, [c]) of
- {ok, [["4", "5", "6"], ["7", "8", "9"]]} ->
- ok;
- _ ->
- loose_node:stop(Node),
- ?t:fail({get_argument, restart_fail})
- end,
+ case rpc:call(Node, init, get_argument, [c]) of
+ {ok, [["4", "5", "6"], ["7", "8", "9"]]} ->
+ ok;
+ _ ->
+ loose_node:stop(Node),
+ ct:fail({get_argument, restart_fail})
+ end,
loose_node:stop(Node),
- ?line ?t:timetrap_cancel(Dog),
ok.
wait_restart(0, _Node) ->
- ?t:fail(not_restarted);
+ ct:fail(not_restarted);
wait_restart(N, Node) ->
case net_adm:ping(Node) of
pong -> ok;
_ ->
- ?t:sleep(1000),
+ ct:sleep(1000),
wait_restart(N - 1, Node)
end.
@@ -474,124 +439,98 @@ apid(Pid) ->
%% The reboot facility using heart is tested
%% in the heart_SUITE.
%% ------------------------------------------------
-reboot(doc) -> [];
-reboot(suite) -> {req, [distribution, {local_slave_nodes, 1}]};
reboot(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(40)),
-
Args = args(),
- ?line {ok, Node} = start_node(init_test, Args),
+ {ok, Node} = start_node(init_test, Args),
erlang:monitor_node(Node, true),
- ?line ok = rpc:call(Node, init, reboot, []),
- ?line receive
- {nodedown, Node} ->
- ok
- after 10000 ->
- stop_node(Node),
- ?t:fail(not_stopping)
- end,
- ?t:sleep(5000),
- ?line case net_adm:ping(Node) of
- pang ->
- ok;
- _ ->
- stop_node(Node),
- ?t:fail(system_rebooted)
- end,
- ?line ?t:timetrap_cancel(Dog),
+ ok = rpc:call(Node, init, reboot, []),
+ receive
+ {nodedown, Node} ->
+ ok
+ after 10000 ->
+ stop_node(Node),
+ ct:fail(not_stopping)
+ end,
+ ct:sleep(5000),
+ case net_adm:ping(Node) of
+ pang ->
+ ok;
+ _ ->
+ stop_node(Node),
+ ct:fail(system_rebooted)
+ end,
ok.
%% ------------------------------------------------
%%
%% ------------------------------------------------
-stop(doc) -> [];
-stop(suite) -> [];
stop(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(20)),
Args = args(),
- ?line {ok, Node} = start_node(init_test, Args),
+ {ok, Node} = start_node(init_test, Args),
erlang:monitor_node(Node, true),
- ?line ok = rpc:call(Node, init, reboot, []),
- ?line receive
- {nodedown, Node} ->
- ok
- after 10000 ->
- stop_node(Node),
- ?t:fail(not_stopping)
- end,
- ?t:sleep(5000),
- ?line case net_adm:ping(Node) of
- pang ->
- ok;
- _ ->
- stop_node(Node),
- ?t:fail(system_rebooted)
- end,
- ?line ?t:timetrap_cancel(Dog),
+ ok = rpc:call(Node, init, reboot, []),
+ receive
+ {nodedown, Node} ->
+ ok
+ after 10000 ->
+ stop_node(Node),
+ ct:fail(not_stopping)
+ end,
+ ct:sleep(5000),
+ case net_adm:ping(Node) of
+ pang ->
+ ok;
+ _ ->
+ stop_node(Node),
+ ct:fail(system_rebooted)
+ end,
ok.
%% ------------------------------------------------
%%
%% ------------------------------------------------
-get_status(doc) -> [];
-get_status(suite) -> [];
get_status(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(10)),
- ?line ?t:timetrap_cancel(Dog),
+ {Start, _} = init:get_status(),
- ?line {Start, _} = init:get_status(),
%% Depending on how the test_server is started Start has
%% different values. staring if test_server started with
%% -s flag.
- ?line case lists:member(Start, [started, starting]) of
- true ->
- ok;
- _ ->
- ?t:fail(get_status)
- end.
+ case lists:member(Start, [started, starting]) of
+ true ->
+ ok;
+ _ ->
+ ct:fail(get_status)
+ end.
%% ------------------------------------------------
%%
%% ------------------------------------------------
-script_id(doc) -> [];
-script_id(suite) -> [];
script_id(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(10)),
-
- ?line {Name, Vsn} = init:script_id(),
- ?line if
- is_list(Name), is_list(Vsn) ->
- ok;
- true ->
- ?t:fail(not_standard_script)
- end,
- ?line ?t:timetrap_cancel(Dog),
+ {Name, Vsn} = init:script_id(),
+ if
+ is_list(Name), is_list(Vsn) ->
+ ok;
+ true ->
+ ct:fail(not_standard_script)
+ end,
ok.
%% ------------------------------------------------
%% Start the slave system with -boot flag.
%% ------------------------------------------------
-boot1(doc) -> [];
-boot1(suite) -> {req, [distribution, {local_slave_nodes, 1}, {time, 35}]};
boot1(Config) when is_list(Config) ->
- ?line Dog = ?t:timetrap(?t:seconds(80)),
Args = args() ++ " -boot start_sasl",
- ?line {ok, Node} = start_node(init_test, Args),
- ?line stop_node(Node),
+ {ok, Node} = start_node(init_test, Args),
+ stop_node(Node),
%% Try to start with non existing boot file.
Args1 = args() ++ " -boot dummy_script",
- ?line {error, timeout} = start_node(init_test, Args1),
+ {error, timeout} = start_node(init_test, Args1),
- ?line ?t:timetrap_cancel(Dog),
ok.
-boot2(doc) -> [];
-boot2(suite) -> {req, [distribution, {local_slave_nodes, 1}, {time, 35}]};
boot2(Config) when is_list(Config) ->
- Dog = ?t:timetrap(?t:seconds(80)),
-
%% Absolute boot file name
Boot = filename:join([code:root_dir(), "bin", "start_sasl"]),
@@ -604,9 +543,9 @@ boot2(Config) when is_list(Config) ->
%% Absolute boot file name for Windows -- all slashes are
%% converted to backslashes.
Win_boot = lists:map(fun
- ($/) -> $\\;
- (C) -> C
- end, Boot),
+ ($/) -> $\\;
+ (C) -> C
+ end, Boot),
Args2 = args() ++ " -boot \"" ++ Win_boot ++ "\"",
{ok, Node2} = start_node(init_test, Args2),
stop_node(Node2);
@@ -614,16 +553,15 @@ boot2(Config) when is_list(Config) ->
ok
end,
- ?t:timetrap_cancel(Dog),
ok.
%% Misc. functions
start_node(Name, Param) ->
- ?t:start_node(Name, slave, [{args, Param}]).
+ test_server:start_node(Name, slave, [{args, Param}]).
stop_node(Node) ->
- ?t:stop_node(Node).
+ test_server:stop_node(Node).
from(H, [H | T]) -> T;
from(H, [_ | T]) -> from(H, T);
@@ -639,18 +577,18 @@ long_args(A) ->
[A])).
create_script(Config) ->
- ?line PrivDir = ?config(priv_dir,Config),
- ?line Name = PrivDir ++ "boot_var_test",
- ?line Apps = application_controller:which_applications(),
- ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
- ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
- ?line {ok,Fd} = file:open(Name ++ ".rel", [write]),
- ?line io:format(Fd,
- "{release, {\"Test release 3\", \"P2A\"}, \n"
- " {erts, \"4.4\"}, \n"
- " [{kernel, \"~s\"}, {stdlib, \"~s\"}]}.\n",
- [KernelVer,StdlibVer]),
- ?line file:close(Fd),
+ PrivDir = proplists:get_value(priv_dir,Config),
+ Name = PrivDir ++ "boot_var_test",
+ Apps = application_controller:which_applications(),
+ {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+ {ok,Fd} = file:open(Name ++ ".rel", [write]),
+ io:format(Fd,
+ "{release, {\"Test release 3\", \"P2A\"}, \n"
+ " {erts, \"4.4\"}, \n"
+ " [{kernel, \"~s\"}, {stdlib, \"~s\"}]}.\n",
+ [KernelVer,StdlibVer]),
+ file:close(Fd),
{filename:dirname(Name), filename:basename(Name),
- KernelVer, StdlibVer}.
+ KernelVer, StdlibVer}.
diff --git a/lib/kernel/test/interactive_shell_SUITE.erl b/lib/kernel/test/interactive_shell_SUITE.erl
index 8adae1f606..414504e257 100644
--- a/lib/kernel/test/interactive_shell_SUITE.erl
+++ b/lib/kernel/test/interactive_shell_SUITE.erl
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
%%
-module(interactive_shell_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
get_columns_and_rows/1, exit_initial/1, job_control_local/1,
@@ -30,15 +30,14 @@
-export([toerl_server/3]).
init_per_testcase(_Func, Config) ->
- Dog = test_server:timetrap(test_server:minutes(3)),
- [{watchdog,Dog}|Config].
-
-end_per_testcase(_Func, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog).
+ Config.
+end_per_testcase(_Func, _Config) ->
+ ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,3}}].
all() ->
[get_columns_and_rows, exit_initial, job_control_local,
@@ -55,7 +54,7 @@ init_per_suite(Config) ->
[{default_shell,DefShell},{term,Term}|Config].
end_per_suite(Config) ->
- Term = ?config(term,Config),
+ Term = proplists:get_value(term,Config),
os:putenv("TERM",Term),
ok.
@@ -66,68 +65,66 @@ end_per_group(_GroupName, Config) ->
Config.
-%-define(DEBUG,1).
+%%-define(DEBUG,1).
-ifdef(DEBUG).
-define(dbg(Data),erlang:display(Data)).
-else.
-define(dbg(Data),noop).
-endif.
-get_columns_and_rows(suite) -> [];
-get_columns_and_rows(doc) -> ["Test that the shell can access columns and rows"];
+%% Test that the shell can access columns and rows.
get_columns_and_rows(Config) when is_list(Config) ->
case proplists:get_value(default_shell,Config) of
old ->
%% Old shell tests
?dbg(old_shell),
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline,"io:columns()."},
- {getline_re,".*{error,enotsup}"},
- {putline,"io:rows()."},
- {getline_re,".*{error,enotsup}"}
-
- ],[]),
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline,"io:columns()."},
- {getline_re,".*{ok,90}"},
- {putline,"io:rows()."},
- {getline_re,".*{ok,40}"}],
- [],
- "stty rows 40; stty columns 90; ");
+ rtnode([{putline,""},
+ {putline, "2."},
+ {getline, "2"},
+ {putline,"io:columns()."},
+ {getline_re,".*{error,enotsup}"},
+ {putline,"io:rows()."},
+ {getline_re,".*{error,enotsup}"}
+
+ ],[]),
+ rtnode([{putline,""},
+ {putline, "2."},
+ {getline, "2"},
+ {putline,"io:columns()."},
+ {getline_re,".*{ok,90}"},
+ {putline,"io:rows()."},
+ {getline_re,".*{ok,40}"}],
+ [],
+ "stty rows 40; stty columns 90; ");
new ->
- % New shell tests
+ %% New shell tests
?dbg(new_shell),
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline,"io:columns()."},
- %% Behaviour change in R12B-5, returns 80
- %% {getline,"{error,enotsup}"},
- {getline,"{ok,80}"},
- {putline,"io:rows()."},
- %% Behaviour change in R12B-5, returns 24
- %% {getline,"{error,enotsup}"}
- {getline,"{ok,24}"}
- ],[]),
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline,"io:columns()."},
- {getline,"{ok,90}"},
- {putline,"io:rows()."},
- {getline,"{ok,40}"}],
- [],
- "stty rows 40; stty columns 90; ")
+ rtnode([{putline,""},
+ {putline, "2."},
+ {getline, "2"},
+ {putline,"io:columns()."},
+ %% Behaviour change in R12B-5, returns 80
+ %% {getline,"{error,enotsup}"},
+ {getline,"{ok,80}"},
+ {putline,"io:rows()."},
+ %% Behaviour change in R12B-5, returns 24
+ %% {getline,"{error,enotsup}"}
+ {getline,"{ok,24}"}
+ ],[]),
+ rtnode([{putline,""},
+ {putline, "2."},
+ {getline, "2"},
+ {putline,"io:columns()."},
+ {getline,"{ok,90}"},
+ {putline,"io:rows()."},
+ {getline,"{ok,40}"}],
+ [],
+ "stty rows 40; stty columns 90; ")
end.
-
-
-exit_initial(suite) -> [];
-exit_initial(doc) -> ["Tests that exit of initial shell restarts shell"];
+
+
+%% Tests that exit of initial shell restarts shell.
exit_initial(Config) when is_list(Config) ->
case proplists:get_value(default_shell,Config) of
old ->
@@ -152,9 +149,7 @@ exit_initial(Config) when is_list(Config) ->
{getline_re,"35"}],[])
end.
-job_control_local(suite) -> [];
-job_control_local(doc) -> [ "Tests that local shell can be "
- "started by means of job control" ];
+%% Tests that local shell can be started by means of job control.
job_control_local(Config) when is_list(Config) ->
case proplists:get_value(default_shell,Config) of
old ->
@@ -162,133 +157,130 @@ job_control_local(Config) when is_list(Config) ->
{skip,"No new shell found"};
new ->
%% New shell tests
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline,[7]},
- {sleep,timeout(short)},
- {putline,""},
- {getline," -->"},
- {putline,"s"},
- {putline,"c"},
- {putline_raw,""},
- {getline,"Eshell"},
- {putline_raw,""},
- {getline,"1>"},
- {putline,"35."},
- {getline,"35"}],[])
+ rtnode([{putline,""},
+ {putline, "2."},
+ {getline, "2"},
+ {putline,[7]},
+ {sleep,timeout(short)},
+ {putline,""},
+ {getline," -->"},
+ {putline,"s"},
+ {putline,"c"},
+ {putline_raw,""},
+ {getline,"Eshell"},
+ {putline_raw,""},
+ {getline,"1>"},
+ {putline,"35."},
+ {getline,"35"}],[])
end.
-job_control_remote(suite) -> [];
job_control_remote(doc) -> [ "Tests that remote shell can be "
"started by means of job control" ];
job_control_remote(Config) when is_list(Config) ->
case {node(),proplists:get_value(default_shell,Config)} of
{nonode@nohost,_} ->
- ?line exit(not_distributed);
+ exit(not_distributed);
{_,old} ->
{skip,"No new shell found"};
_ ->
- ?line RNode = create_nodename(),
- ?line MyNode = atom2list(node()),
- ?line Pid = spawn_link(fun() ->
- receive die ->
- ok
- end
- end),
- ?line PidStr = pid_to_list(Pid),
- ?line register(kalaskula,Pid),
- ?line CookieString = lists:flatten(
- io_lib:format("~w",
- [erlang:get_cookie()])),
- ?line Res = rtnode([{putline,""},
- {putline, "erlang:get_cookie()."},
- {getline, CookieString},
- {putline,[7]},
- {sleep,timeout(short)},
- {putline,""},
- {getline," -->"},
- {putline,"r '"++MyNode++"'"},
- {putline,"c"},
- {putline_raw,""},
- {getline,"Eshell"},
- {sleep,timeout(short)},
- {putline_raw,""},
- {getline,"("++MyNode++")1>"},
- {putline,"whereis(kalaskula)."},
- {getline,PidStr},
- {sleep,timeout(short)}, % Race, known bug.
- {putline_raw,"exit()."},
- {getline,"***"},
- {putline,[7]},
- {putline,""},
- {getline," -->"},
- {putline,"c 1"},
- {putline,""},
- {sleep,timeout(short)},
- {putline_raw,""},
- {getline,"("++RNode++")"}],RNode),
- ?line Pid ! die,
- ?line Res
+ RNode = create_nodename(),
+ MyNode = atom2list(node()),
+ Pid = spawn_link(fun() ->
+ receive die ->
+ ok
+ end
+ end),
+ PidStr = pid_to_list(Pid),
+ register(kalaskula,Pid),
+ CookieString = lists:flatten(
+ io_lib:format("~w",
+ [erlang:get_cookie()])),
+ Res = rtnode([{putline,""},
+ {putline, "erlang:get_cookie()."},
+ {getline, CookieString},
+ {putline,[7]},
+ {sleep,timeout(short)},
+ {putline,""},
+ {getline," -->"},
+ {putline,"r '"++MyNode++"'"},
+ {putline,"c"},
+ {putline_raw,""},
+ {getline,"Eshell"},
+ {sleep,timeout(short)},
+ {putline_raw,""},
+ {getline,"("++MyNode++")1>"},
+ {putline,"whereis(kalaskula)."},
+ {getline,PidStr},
+ {sleep,timeout(short)}, % Race, known bug.
+ {putline_raw,"exit()."},
+ {getline,"***"},
+ {putline,[7]},
+ {putline,""},
+ {getline," -->"},
+ {putline,"c 1"},
+ {putline,""},
+ {sleep,timeout(short)},
+ {putline_raw,""},
+ {getline,"("++RNode++")"}],RNode),
+ Pid ! die,
+ Res
end.
-job_control_remote_noshell(suite) -> [];
-job_control_remote_noshell(doc) ->
- [ "Tests that remote shell can be "
- "started by means of job control to -noshell node" ];
+
+%% Tests that remote shell can be
+%% started by means of job control to -noshell node.
job_control_remote_noshell(Config) when is_list(Config) ->
case {node(),proplists:get_value(default_shell,Config)} of
{nonode@nohost,_} ->
- ?line exit(not_distributed);
+ exit(not_distributed);
{_,old} ->
{skip,"No new shell found"};
_ ->
- ?line RNode = create_nodename(),
- ?line NSNode = start_noshell_node(interactive_shell_noshell),
- ?line Pid = spawn_link(NSNode, fun() ->
- receive die ->
- ok
- end
- end),
- ?line PidStr = rpc:call(NSNode,erlang,pid_to_list,[Pid]),
- ?line true = rpc:call(NSNode,erlang,register,[kalaskula,Pid]),
- ?line NSNodeStr = atom2list(NSNode),
- ?line CookieString = lists:flatten(
- io_lib:format("~w",
- [erlang:get_cookie()])),
- ?line Res = rtnode([{putline,""},
- {putline, "erlang:get_cookie()."},
- {getline, CookieString},
- {putline,[7]},
- {sleep,timeout(short)},
- {putline,""},
- {getline," -->"},
- {putline,"r '"++NSNodeStr++"'"},
- {putline,"c"},
- {putline_raw,""},
- {getline,"Eshell"},
- {sleep,timeout(short)},
- {putline_raw,""},
- {getline,"("++NSNodeStr++")1>"},
- {putline,"whereis(kalaskula)."},
- {getline,PidStr},
- {sleep,timeout(short)}, % Race, known bug.
- {putline_raw,"exit()."},
- {getline,"***"},
- {putline,[7]},
- {putline,""},
- {getline," -->"},
- {putline,"c 1"},
- {putline,""},
- {sleep,timeout(short)},
- {putline_raw,""},
- {getline,"("++RNode++")"}],RNode),
- ?line Pid ! die,
- ?line stop_noshell_node(NSNode),
- ?line Res
+ RNode = create_nodename(),
+ NSNode = start_noshell_node(interactive_shell_noshell),
+ Pid = spawn_link(NSNode, fun() ->
+ receive die ->
+ ok
+ end
+ end),
+ PidStr = rpc:call(NSNode,erlang,pid_to_list,[Pid]),
+ true = rpc:call(NSNode,erlang,register,[kalaskula,Pid]),
+ NSNodeStr = atom2list(NSNode),
+ CookieString = lists:flatten(
+ io_lib:format("~w",
+ [erlang:get_cookie()])),
+ Res = rtnode([{putline,""},
+ {putline, "erlang:get_cookie()."},
+ {getline, CookieString},
+ {putline,[7]},
+ {sleep,timeout(short)},
+ {putline,""},
+ {getline," -->"},
+ {putline,"r '"++NSNodeStr++"'"},
+ {putline,"c"},
+ {putline_raw,""},
+ {getline,"Eshell"},
+ {sleep,timeout(short)},
+ {putline_raw,""},
+ {getline,"("++NSNodeStr++")1>"},
+ {putline,"whereis(kalaskula)."},
+ {getline,PidStr},
+ {sleep,timeout(short)}, % Race, known bug.
+ {putline_raw,"exit()."},
+ {getline,"***"},
+ {putline,[7]},
+ {putline,""},
+ {getline," -->"},
+ {putline,"c 1"},
+ {putline,""},
+ {sleep,timeout(short)},
+ {putline_raw,""},
+ {getline,"("++RNode++")"}],RNode),
+ Pid ! die,
+ stop_noshell_node(NSNode),
+ Res
end.
-ctrl_keys(suite) -> [];
-ctrl_keys(doc) -> ["Tests various control keys"];
+%% Tests various control keys.
ctrl_keys(_Conf) when is_list(_Conf) ->
Cu=[$\^u],
Cw=[$\^w],
@@ -308,7 +300,7 @@ ctrl_keys(_Conf) when is_list(_Conf) ->
{getline,"\"hello world\""},
{putline,"\"hello world\""++Cu++Cy++"."},
{getline,"\"hello world\""}]
- ++wordLeft()++wordRight(),[]).
+ ++wordLeft()++wordRight(),[]).
wordLeft() ->
@@ -337,46 +329,46 @@ wordRight(Chars) ->
rtnode(C,N) ->
rtnode(C,N,[]).
rtnode(Commands,Nodename,ErlPrefix) ->
- ?line case get_progs() of
- {error,_Reason} ->
- ?line {skip,"No runerl present"};
- {RunErl,ToErl,Erl} ->
- ?line case create_tempdir() of
- {error, Reason2} ->
- ?line {skip, Reason2};
- Tempdir ->
- ?line SPid =
- start_runerl_node(RunErl,ErlPrefix++"\\\""++Erl++"\\\"",
- Tempdir,Nodename),
- ?line CPid = start_toerl_server(ToErl,Tempdir),
- ?line erase(getline_skipped),
- ?line Res =
- (catch get_and_put(CPid, Commands,1)),
- ?line case stop_runerl_node(CPid) of
- {error,_} ->
- ?line CPid2 =
- start_toerl_server
- (ToErl,Tempdir),
- ?line erase(getline_skipped),
- ?line ok = get_and_put
- (CPid2,
- [{putline,[7]},
- {sleep,
- timeout(short)},
- {putline,""},
- {getline," -->"},
- {putline,"s"},
- {putline,"c"},
- {putline,""}],1),
- ?line stop_runerl_node(CPid2);
- _ ->
- ?line ok
- end,
- ?line wait_for_runerl_server(SPid),
- ?line ok = rm_rf(Tempdir),
- ?line ok = Res
- end
- end.
+ case get_progs() of
+ {error,_Reason} ->
+ {skip,"No runerl present"};
+ {RunErl,ToErl,Erl} ->
+ case create_tempdir() of
+ {error, Reason2} ->
+ {skip, Reason2};
+ Tempdir ->
+ SPid =
+ start_runerl_node(RunErl,ErlPrefix++"\\\""++Erl++"\\\"",
+ Tempdir,Nodename),
+ CPid = start_toerl_server(ToErl,Tempdir),
+ erase(getline_skipped),
+ Res =
+ (catch get_and_put(CPid, Commands,1)),
+ case stop_runerl_node(CPid) of
+ {error,_} ->
+ CPid2 =
+ start_toerl_server
+ (ToErl,Tempdir),
+ erase(getline_skipped),
+ ok = get_and_put
+ (CPid2,
+ [{putline,[7]},
+ {sleep,
+ timeout(short)},
+ {putline,""},
+ {getline," -->"},
+ {putline,"s"},
+ {putline,"c"},
+ {putline,""}],1),
+ stop_runerl_node(CPid2);
+ _ ->
+ ok
+ end,
+ wait_for_runerl_server(SPid),
+ ok = rm_rf(Tempdir),
+ ok = Res
+ end
+ end.
timeout(long) ->
2 * timeout(normal);
@@ -389,7 +381,7 @@ timeout(normal) ->
start_noshell_node(Name) ->
PADir = filename:dirname(code:which(?MODULE)),
{ok, Node} = test_server:start_node(Name,slave,[{args," -noshell -pa "++
- PADir++" "}]),
+ PADir++" "}]),
Node.
stop_noshell_node(Node) ->
test_server:stop_node(Node).
@@ -397,20 +389,20 @@ stop_noshell_node(Node) ->
rm_rf(Dir) ->
try
- {ok,List} = file:list_dir(Dir),
- Files = [filename:join([Dir,X]) || X <- List],
- [case file:list_dir(Y) of
- {error, enotdir} ->
- ok = file:delete(Y);
- _ ->
- ok = rm_rf(Y)
- end || Y <- Files],
- ok = file:del_dir(Dir),
- ok
+ {ok,List} = file:list_dir(Dir),
+ Files = [filename:join([Dir,X]) || X <- List],
+ [case file:list_dir(Y) of
+ {error, enotdir} ->
+ ok = file:delete(Y);
+ _ ->
+ ok = rm_rf(Y)
+ end || Y <- Files],
+ ok = file:del_dir(Dir),
+ ok
catch
_:Exception -> {error, {Exception,Dir}}
end.
-
+
get_and_put(_CPid,[],_) ->
ok;
@@ -479,7 +471,7 @@ get_and_put(CPid, [{putline_raw, Line}|T],N) ->
Timeout = timeout(normal),
receive
{send_line, ok} ->
- get_and_put(CPid, T,N+1)
+ get_and_put(CPid, T,N+1)
after Timeout ->
error_logger:error_msg("~p: putline_raw timeout (~p) sending "
"\"~s\" (command number ~p)~n",
@@ -493,7 +485,7 @@ get_and_put(CPid, [{putline, Line}|T],N) ->
Timeout = timeout(normal),
receive
{send_line, ok} ->
- get_and_put(CPid, [{getline, []}|T],N)
+ get_and_put(CPid, [{getline, []}|T],N)
after Timeout ->
error_logger:error_msg("~p: putline timeout (~p) sending "
"\"~s\" (command number ~p)~n[~p]~n",
@@ -510,8 +502,8 @@ wait_for_runerl_server(SPid) ->
after Timeout ->
{error, timeout}
end.
-
-
+
+
stop_runerl_node(CPid) ->
Ref = erlang:monitor(process, CPid),
@@ -562,11 +554,11 @@ create_tempdir(Dir,X) when X > $Z, X < $a ->
create_tempdir(Dir,$a);
create_tempdir(Dir,X) when X > $z ->
Estr = lists:flatten(
- io_lib:format("Unable to create ~s, reason eexist",
- [Dir++[$z]])),
+ io_lib:format("Unable to create ~s, reason eexist",
+ [Dir++[$z]])),
{error, Estr};
create_tempdir(Dir0, Ch) ->
- % Expect fairly standard unix.
+ %% Expect fairly standard unix.
Dir = Dir0++[Ch],
case file:make_dir(Dir) of
{error, eexist} ->
@@ -604,13 +596,13 @@ start_runerl_node(RunErl,Erl,Tempdir,Nodename) ->
[];
_ ->
" -sname "++(if is_atom(Nodename) -> atom_to_list(Nodename);
- true -> Nodename
- end)++
+ true -> Nodename
+ end)++
" -setcookie "++atom_to_list(erlang:get_cookie())
end,
spawn(fun() ->
os:cmd("\""++RunErl++"\" "++Tempdir++"/ "++Tempdir++" \""++
- Erl++XArg++"\"")
+ Erl++XArg++"\"")
end).
start_toerl_server(ToErl,Tempdir) ->
@@ -668,7 +660,7 @@ toerl_loop(Port,Acc) ->
_ ->
toerl_loop(Port,[{Tag0,Data}|Acc])
end;
- {Pid,{get_line,Timeout}} ->
+ {Pid,{get_line,Timeout}} ->
case Acc of
[] ->
case get_data_within(Port,Timeout,[]) of
@@ -717,10 +709,10 @@ toerl_loop(Port,Acc) ->
Other ->
{error, {unexpected, Other}}
end.
-
+
millistamp() ->
erlang:monotonic_time(milli_seconds).
-
+
get_data_within(Port, X, Acc) when X =< 0 ->
?dbg({get_data_within, X, Acc, ?LINE}),
receive
@@ -751,7 +743,7 @@ get_data_within(Port, Timeout, Acc) ->
after Timeout ->
timeout
end.
-
+
get_default_shell() ->
try
rtnode([{putline,""},
diff --git a/lib/kernel/test/kernel_SUITE.erl b/lib/kernel/test/kernel_SUITE.erl
index 8ae2e4b23b..e02aa2aa8d 100644
--- a/lib/kernel/test/kernel_SUITE.erl
+++ b/lib/kernel/test/kernel_SUITE.erl
@@ -21,21 +21,20 @@
%%% Kernel application test suite.
%%%-----------------------------------------------------------------
-module(kernel_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-% Test server specific exports
+%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
-export([init_per_testcase/2, end_per_testcase/2]).
-% Test cases must be exported.
+%% Test cases must be exported.
-export([app_test/1, appup_test/1]).
-%%
-%% all/1
-%%
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,2}}].
all() ->
[app_test, appup_test].
@@ -61,15 +60,12 @@ init_per_testcase(_Case, Config) ->
end_per_testcase(_Case, _Config) ->
ok.
-%
-% Test cases starts here.
-%
-app_test(doc) ->
- ["Tests the applications consistency."];
-app_test(suite) ->
- [];
+%%
+%% Test cases starts here.
+%%
+%% Tests the applications consistency.
app_test(Config) when is_list(Config) ->
- ?line ok=?t:app_test(kernel),
+ ok=test_server:app_test(kernel),
ok.
diff --git a/lib/kernel/test/kernel_config_SUITE.erl b/lib/kernel/test/kernel_config_SUITE.erl
index 4be44015c9..5f36ad995c 100644
--- a/lib/kernel/test/kernel_config_SUITE.erl
+++ b/lib/kernel/test/kernel_config_SUITE.erl
@@ -19,13 +19,15 @@
%%
-module(kernel_config_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, sync/1]).
-export([init_per_suite/1, end_per_suite/1]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,2}}].
all() ->
[sync].
@@ -40,13 +42,9 @@ end_per_group(_GroupName, Config) ->
Config.
-init_per_suite(doc) -> [];
-init_per_suite(suite) -> [];
init_per_suite(Config) when is_list(Config) ->
Config.
-end_per_suite(doc) -> [];
-end_per_suite(suite) -> [];
end_per_suite(Config) when is_list(Config) ->
stop_node(init_test),
Config.
@@ -54,7 +52,7 @@ end_per_suite(Config) when is_list(Config) ->
config(Fd) ->
M = from($@, atom_to_list(node())),
io:format(Fd, "[{kernel, [{sync_nodes_optional, ['cp1@~s','cp2@~s']},"
- "{sync_nodes_timeout, 15000}]}].~n",
+ "{sync_nodes_timeout, 15000}]}].~n",
[M, M]).
from(H, [H | T]) -> T;
@@ -67,12 +65,9 @@ from(_, []) -> [].
%% Should be started in a CC view with:
%% erl -sname XXX where XX not in [cp1, cp2]
%%-----------------------------------------------------------------
-sync(doc) -> [];
-sync(suite) -> [];
sync(Conf) when is_list(Conf) ->
- ?line Dog = ?t:timetrap(?t:seconds(120)),
- % Write a config file
- Dir = ?config(priv_dir,Conf),
+ %% Write a config file
+ Dir = proplists:get_value(priv_dir,Conf),
{ok, Fd} = file:open(Dir ++ "sys.config", [write]),
config(Fd),
file:close(Fd),
@@ -81,34 +76,33 @@ sync(Conf) when is_list(Conf) ->
%% Reset wall_clock
{T1,_} = erlang:statistics(wall_clock),
io:format("~p~n", [{t1, T1}]),
- ?line Command = lists:concat([lib:progname(),
- " -detached -sname cp1 ",
- "-config ", Config,
- " -env ERL_CRASH_DUMP erl_crash_dump.cp1"]),
+ Command = lists:concat([lib:progname(),
+ " -detached -sname cp1 ",
+ "-config ", Config,
+ " -env ERL_CRASH_DUMP erl_crash_dump.cp1"]),
io:format("Command: ~s", [Command]),
- ?line open_port({spawn, Command}, [stream]),
+ open_port({spawn, Command}, [stream]),
io:format("started~n"),
- ?line ?t:sleep(12000),
+ ct:sleep(12000),
io:format("waited12~n"),
- ?line Host = from($@, atom_to_list(node())),
- ?line Cp1 = list_to_atom("cp1@"++Host),
- ?line wait_for_node(Cp1),
+ Host = from($@, atom_to_list(node())),
+ Cp1 = list_to_atom("cp1@"++Host),
+ wait_for_node(Cp1),
io:format("waitednode~n"),
%% Check time since last call
- ?line {TT, T} = erlang:statistics(wall_clock),
+ {TT, T} = erlang:statistics(wall_clock),
io:format("~p~n", [{t2, {TT, T}}]),
- ?line stop_node(cp1),
+ stop_node(cp1),
if
- TT-T1 < 15000 -> ?line ?t:fail({too_short_time, TT-T1});
+ TT-T1 < 15000 -> ct:fail({too_short_time, TT-T1});
true -> ok
end,
- ?line ?t:timetrap_cancel(Dog),
ok.
wait_for_node(Node) ->
case rpc:call(Node, init, get_status, []) of
{started,_} -> ok;
- {badrpc, R} -> ?line ?t:fail({rpc_failed, R});
+ {badrpc, R} -> ct:fail({rpc_failed, R});
_Other -> wait_for_node(Node)
end.
diff --git a/lib/kernel/test/multi_load_SUITE.erl b/lib/kernel/test/multi_load_SUITE.erl
new file mode 100644
index 0000000000..9cba6fc06e
--- /dev/null
+++ b/lib/kernel/test/multi_load_SUITE.erl
@@ -0,0 +1,419 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-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(multi_load_SUITE).
+-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
+ init_per_group/2,end_per_group/2,
+ basic_atomic_load/1,basic_errors/1,sticky_dir/1,
+ on_load_failing/1,ensure_modules_loaded/1,
+ native_code/1]).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("syntax_tools/include/merl.hrl").
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
+
+all() ->
+ [basic_atomic_load,basic_errors,sticky_dir,on_load_failing,
+ ensure_modules_loaded,native_code].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+basic_atomic_load(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Dir = filename:join(PrivDir, multi_load_sticky_dir),
+ _ = file:make_dir(Dir),
+
+ OldPath = code:get_path(),
+ try
+ code:add_patha(Dir),
+ do_basic(Dir)
+ after
+ code:set_path(OldPath)
+ end,
+
+ ok.
+
+do_basic(Dir) ->
+ MsVer1_0 = make_modules(5, versioned_module(1)),
+ MsVer1 = [{M,filename:absname(F, Dir),Bin} || {M,F,Bin} <- MsVer1_0],
+ _ = [ok = file:write_file(F, Bin) || {_,F,Bin} <- MsVer1],
+
+ Ms = [M || {M,_,_} <- MsVer1],
+ [] = [loaded || M <- Ms, is_loaded(M)],
+
+ ok = code:atomic_load(Ms),
+ _ = [1 = M:M() || M <- Ms],
+ _ = [F = code:which(M) || {M,F,_} <- MsVer1],
+ [] = [not_loaded || M <- Ms, not is_loaded(M)],
+
+ MsVer2 = update_modules(Ms, versioned_module(2)),
+ {ok,Prepared} = code:prepare_loading(MsVer2),
+ ok = code:finish_loading(Prepared),
+ _ = [2 = M:M() || M <- Ms],
+ _ = [F = code:which(M) || {M,F,_} <- MsVer2],
+ [] = [not_loaded || M <- Ms, not is_loaded(M)],
+
+ MsVer3 = update_modules(Ms, versioned_module(2)),
+ NotPurged = lists:sort([{M,not_purged} || M <- Ms]),
+ NotPurged = atomic_load_error(MsVer3, true),
+
+ ok.
+
+versioned_module(Ver) ->
+ fun(Mod) ->
+ ?Q(["-module('@Mod@').\n",
+ "-export(['@Mod@'/0]).\n",
+ "'@Mod@'() -> _@Ver@.\n"])
+ end.
+
+basic_errors(_Config) ->
+ atomic_load_fc([42]),
+ atomic_load_fc([{"mod","file","bin"}]),
+
+ finish_loading_fc(atom),
+ {ok,{PrepTag,_}} = code:prepare_loading([code]),
+ finish_loading_fc({PrepTag,[x]}),
+ finish_loading_fc({PrepTag,[{m,{<<>>,"",<<>>}}]}),
+ Prep = prepared_with_wrong_magic_bin(),
+ finish_loading_fc(Prep),
+
+ [{x,badfile}] = atomic_load_error([{x,"x",<<"bad">>}], false),
+ [{a,badfile},{some_nonexistent_file,nofile}] =
+ atomic_load_error([some_nonexistent_file,{a,"a",<<>>}],
+ false),
+
+ %% Modules mentioned more than once.
+ Mods = make_modules(2, fun basic_module/1),
+ Ms = [M || {M,_,_} <- Mods],
+ DupMods = Mods ++ [mnesia] ++ Mods ++ [mnesia],
+ DupErrors0 = lists:sort([mnesia|Ms]),
+ DupErrors = [{M,duplicated} || M <- DupErrors0],
+ DupErrors = atomic_load_error(DupMods, false),
+
+ ok.
+
+atomic_load_fc(L) ->
+ {'EXIT',{function_clause,[{code,atomic_load,[L],_}|_]}} =
+ (catch code:atomic_load(L)),
+ {'EXIT',{function_clause,[{code,prepare_loading,[L],_}|_]}} =
+ (catch code:prepare_loading(L)).
+
+finish_loading_fc(Term) ->
+ {'EXIT',{function_clause,[{code,finish_loading,[Term],_}|_]}} =
+ (catch code:finish_loading(Term)).
+
+prepared_with_wrong_magic_bin() ->
+ {ok,Prep} = code:prepare_loading([?MODULE]),
+ prep_magic(Prep).
+
+prep_magic([H|T]) ->
+ [prep_magic(H)|prep_magic(T)];
+prep_magic(Tuple) when is_tuple(Tuple) ->
+ L = prep_magic(tuple_to_list(Tuple)),
+ list_to_tuple(L);
+prep_magic(Bin) when is_binary(Bin) ->
+ try erlang:has_prepared_code_on_load(Bin) of
+ false ->
+ %% Create a different kind of magic binary.
+ ets:match_spec_compile([{'_',[true],['$_']}])
+ catch
+ _:_ ->
+ Bin
+ end;
+prep_magic(Other) ->
+ Other.
+
+sticky_dir(_Config) ->
+ Mod0 = make_module(lists, fun basic_module/1),
+ Mod1 = make_module(gen_server, fun basic_module/1),
+ Ms = [Mod0,Mod1],
+ SD = sticky_directory,
+ StickyErrors = [{gen_server,SD},{lists,SD}],
+ StickyErrors = atomic_load_error(Ms, true),
+
+ ok.
+
+on_load_failing(_Config) ->
+ OnLoad = make_modules(1, fun on_load_module/1),
+ [{OnLoadMod,_,_}] = OnLoad,
+ Ms = make_modules(10, fun basic_module/1) ++ OnLoad,
+
+ %% Fail because there is a module with on_load in the list.
+ on_load_failure(OnLoadMod, Ms),
+ on_load_failure(OnLoadMod, [lists:last(Ms)]),
+
+ %% Fail because there already is a pending on_load.
+ [{HangingOnLoad,_,_}|_] = Ms,
+ spawn_hanging_on_load(HangingOnLoad),
+ NoOnLoadMs = lists:droplast(Ms),
+ {error,[{HangingOnLoad,pending_on_load}]} =
+ code:atomic_load(NoOnLoadMs),
+ hanging_on_load ! stop_hanging_and_unload,
+
+ ok.
+
+on_load_failure(OnLoadMod, Ms) ->
+ [{OnLoadMod,on_load_not_allowed}] = atomic_load_error(Ms, false).
+
+spawn_hanging_on_load(Mod) ->
+ {Mod,Name,Bin} = make_module(Mod, "unknown",
+ fun(_) ->
+ hanging_on_load_module(Mod)
+ end),
+ spawn_link(fun() ->
+ {error,on_load_failure} =
+ code:load_binary(Mod, Name, Bin)
+ end).
+
+hanging_on_load_module(Mod) ->
+ ?Q(["-module('@Mod@').\n",
+ "-on_load(hang/0).\n",
+ "hang() ->\n"
+ " register(hanging_on_load, self()),\n"
+ " receive _ -> unload end.\n"]).
+
+ensure_modules_loaded(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Dir = filename:join(PrivDir, multi_load_ensure_modules_loaded),
+ _ = file:make_dir(Dir),
+
+ OldPath = code:get_path(),
+ try
+ code:add_patha(Dir),
+ do_ensure_modules_loaded(Dir)
+ after
+ code:set_path(OldPath)
+ end,
+
+ ok.
+
+do_ensure_modules_loaded(Dir) ->
+ %% Create a dummy "lists" module and place it in our code path.
+ {lists,ListsFile,ListsCode} = make_module(lists, fun basic_module/1),
+ ok = file:write_file(filename:absname(ListsFile, Dir), ListsCode),
+ {error,sticky_directory} = code:load_file(lists),
+
+ %% Make a new module that we can load.
+ Mod = make_module_file(Dir, fun basic_module/1),
+ false = is_loaded(Mod),
+
+ %% Make a new module with an on_load function.
+ OLMod = make_module_file(Dir, fun on_load_module/1),
+ false = is_loaded(OLMod),
+
+ %% lists should not be loaded again; Mod and OLMod should be
+ %% loaded. ?MODULE should not be reloaded, but there is no easy
+ %% way to test that. Repeating modules is OK.
+ ok = code:ensure_modules_loaded([?MODULE,lists,Mod,OLMod,
+ Mod,OLMod,Mod,lists]),
+ last = lists:last([last]),
+ true = is_loaded(Mod),
+ ok = Mod:Mod(),
+ true = is_loaded(OLMod),
+ _ = OLMod:module_info(),
+
+ %% Unload the modules that were loaded.
+ [begin
+ code:purge(M),
+ code:delete(M),
+ code:purge(M),
+ false = is_loaded(M)
+ end || M <- [Mod,OLMod]],
+
+ %% If there are some errors, all other modules should be loaded
+ %% anyway.
+ [{BadMod,BadFile,_}] = make_modules(1, fun basic_module/1),
+ ok = file:write_file(filename:absname(BadFile, Dir), <<"bad_code">>),
+ BadOLMod = make_module_file(Dir, fun failing_on_load_module/1),
+ BadEgg = bad__egg,
+ NativeMod = a_native_module,
+ NativeModFile = atom_to_list(NativeMod) ++ ".beam",
+ {NativeMod,_,NativeCode} = make_module(NativeMod, NativeModFile,
+ fun basic_module/1, [native]),
+ ok = file:write_file(filename:absname(NativeModFile, Dir), NativeCode),
+ ModulesToLoad = [OLMod,?MODULE,Mod,BadOLMod,NativeMod,
+ BadEgg,BadMod,lists],
+ {error,Error0} = code:ensure_modules_loaded(ModulesToLoad),
+ Error = lists:sort([{BadEgg,nofile},
+ {BadMod,badfile},
+ {BadOLMod,on_load_failure}]),
+ Error = lists:sort(Error0),
+ true = is_loaded(Mod),
+ true = is_loaded(OLMod),
+ true = is_loaded(NativeMod),
+
+ ModuleNative = case erlang:system_info(hipe_architecture) of
+ undefined -> false;
+ _ -> true
+ end,
+ ModuleNative = NativeMod:module_info(native),
+
+ ok.
+
+failing_on_load_module(Mod) ->
+ ?Q(["-module('@Mod@').\n",
+ "-on_load(f/0).\n",
+ "f() -> fail.\n"]).
+
+native_code(_Config) ->
+ case erlang:system_info(hipe_architecture) of
+ undefined ->
+ {skip,"No native support"};
+ _ ->
+ do_native_code()
+ end.
+
+do_native_code() ->
+ CalledMod = native_called_module,
+ CallingMod = native_calling_module,
+
+ %% Create a module in native code that calls another module.
+ CallingMod = make_and_load(CallingMod,
+ calling_module_fun(CalledMod),
+ [native]),
+
+ %% Create a threaded-code module.
+ _ = make_and_load(CalledMod, called_module_fun(42), []),
+ 42 = CallingMod:call(),
+
+ %% Now replace it with a changed module in native code.
+ code:purge(CalledMod),
+ make_and_load(CalledMod, called_module_fun(43), [native]),
+ true = test_server:is_native(CalledMod),
+ 43 = CallingMod:call(),
+
+ %% Reload the called module and call it.
+ code:purge(CalledMod),
+ ModVer3 = make_module(CalledMod, "", called_module_fun(changed)),
+ ok = code:atomic_load([ModVer3]),
+ false = test_server:is_native(CalledMod),
+ changed = CallingMod:call(),
+ code:purge(CalledMod),
+
+ ok.
+
+make_and_load(Mod, Fun, Opts) ->
+ {Mod,_,Code} = make_module(Mod, "", Fun, Opts),
+ {module,Mod} = code:load_binary(Mod, "", Code),
+ Mod.
+
+calling_module_fun(Called) ->
+ fun(Mod) ->
+ ?Q(["-module('@Mod@').\n",
+ "-export([call/0]).\n",
+ "call() -> _@Called@:f().\n"])
+ end.
+
+called_module_fun(Ret) ->
+ fun(Mod) ->
+ ?Q(["-module('@Mod@').\n",
+ "-export([f/0]).\n",
+ "f() -> _@Ret@.\n"])
+ end.
+
+%%%
+%%% Common utilities
+%%%
+
+atomic_load_error(Modules, ErrorInFinishLoading) ->
+ {error,Errors0} = code:atomic_load(Modules),
+ {Errors1,Bool} =
+ case code:prepare_loading(Modules) of
+ {ok,Prepared} ->
+ {error,Es0} = code:finish_loading(Prepared),
+ {Es0,true};
+ {error,Es0} ->
+ {Es0,false}
+ end,
+ Errors = lists:sort(Errors0),
+ Errors = lists:sort(Errors1),
+ case {ErrorInFinishLoading,Bool} of
+ {B,B} ->
+ Errors;
+ {false,true} ->
+ ct:fail("code:prepare_loading/1 should have failed");
+ {true,false} ->
+ ct:fail("code:prepare_loading/1 should have succeeded")
+ end.
+
+is_loaded(Mod) ->
+ case erlang:module_loaded(Mod) of
+ false ->
+ false = code:is_loaded(Mod);
+ true ->
+ {file,_} = code:is_loaded(Mod),
+ true
+ end.
+
+basic_module(Mod) ->
+ ?Q(["-module('@Mod@').\n"
+ "-export(['@Mod@'/0]).\n",
+ "'@Mod@'() -> ok."]).
+
+on_load_module(Mod) ->
+ ?Q(["-module('@Mod@').\n",
+ "-on_load(f/0).\n",
+ "f() -> ok.\n"]).
+
+make_module_file(Dir, Fun) ->
+ [{Mod,File,Code}] = make_modules(1, Fun),
+ ok = file:write_file(filename:absname(File, Dir), Code),
+ Mod.
+
+make_modules(0, _) ->
+ [];
+make_modules(N, Fun) ->
+ U = erlang:unique_integer([positive]),
+ ModName = "m__" ++ integer_to_list(N) ++ "_" ++ integer_to_list(U),
+ Mod = list_to_atom(ModName),
+ ModItem = make_module(Mod, Fun),
+ [ModItem|make_modules(N-1, Fun)].
+
+update_modules(Ms, Fun) ->
+ [make_module(M, Fun) || M <- Ms].
+
+make_module(Mod, Fun) ->
+ Filename = atom_to_list(Mod) ++ ".beam",
+ make_module(Mod, Filename, Fun).
+
+make_module(Mod, Filename, Fun) ->
+ make_module(Mod, Filename, Fun, []).
+
+make_module(Mod, Filename, Fun, Opts) ->
+ Tree = Fun(Mod),
+ merl:print(Tree),
+ {ok,Mod,Code} = merl:compile(Tree, Opts),
+ {Mod,Filename,Code}.
diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl
index 29d8d10262..782d34416b 100644
--- a/lib/kernel/test/os_SUITE.erl
+++ b/lib/kernel/test/os_SUITE.erl
@@ -20,17 +20,22 @@
-module(os_SUITE).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
+ init_per_group/2,end_per_group/2,
+ init_per_testcase/2,end_per_testcase/2]).
-export([space_in_cwd/1, quoting/1, cmd_unicode/1, space_in_name/1, bad_command/1,
- find_executable/1, unix_comment_in_command/1, deep_list_command/1, evil/1]).
+ find_executable/1, unix_comment_in_command/1, deep_list_command/1,
+ large_output_command/1, perf_counter_api/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[space_in_cwd, quoting, cmd_unicode, space_in_name, bad_command,
- find_executable, unix_comment_in_command, deep_list_command, evil].
+ find_executable, unix_comment_in_command, deep_list_command,
+ large_output_command, perf_counter_api].
groups() ->
[].
@@ -47,16 +52,19 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+init_per_testcase(_TC,Config) ->
+ Config.
+
+end_per_testcase(_,_Config) ->
+ ok.
-space_in_cwd(doc) ->
- "Test that executing a command in a current working directory "
- "with space in its name works.";
-space_in_cwd(suite) -> [];
+%% Test that executing a command in a current working directory
+%% with space in its name works.
space_in_cwd(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Dirname = filename:join(PrivDir, "cwd with space"),
- ?line ok = file:make_dir(Dirname),
- ?line ok = file:set_cwd(Dirname),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Dirname = filename:join(PrivDir, "cwd with space"),
+ ok = file:make_dir(Dirname),
+ ok = file:set_cwd(Dirname),
%% Using `more' gives the almost the same result on both Unix and Windows.
@@ -67,70 +75,66 @@ space_in_cwd(Config) when is_list(Config) ->
"more </dev/null"
end,
- ?line case os:cmd(Cmd) of
- [] -> ok; % Unix.
- "\r\n" -> ok; % Windows.
- Other ->
- ?line test_server:fail({unexpected, Other})
- end,
+ case os:cmd(Cmd) of
+ [] -> ok; % Unix.
+ "\r\n" -> ok; % Windows.
+ Other ->
+ ct:fail({unexpected, Other})
+ end,
- ?t:sleep(5),
- ?line [] = receive_all(),
+ ct:sleep(5),
+ [] = receive_all(),
ok.
-quoting(doc) -> "Test that various ways of quoting arguments work.";
-quoting(suite) -> [];
+%% Test that various ways of quoting arguments work.
quoting(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line Echo = filename:join(DataDir, "my_echo"),
-
- ?line comp("one", os:cmd(Echo ++ " one")),
- ?line comp("one::two", os:cmd(Echo ++ " one two")),
- ?line comp("one two", os:cmd(Echo ++ " \"one two\"")),
- ?line comp("x::one two::y", os:cmd(Echo ++ " x \"one two\" y")),
- ?line comp("x::one two", os:cmd(Echo ++ " x \"one two\"")),
- ?line comp("one two::y", os:cmd(Echo ++ " \"one two\" y")),
- ?line comp("x::::y", os:cmd(Echo ++ " x \"\" y")),
- ?t:sleep(5),
- ?line [] = receive_all(),
+ DataDir = proplists:get_value(data_dir, Config),
+ Echo = filename:join(DataDir, "my_echo"),
+
+ comp("one", os:cmd(Echo ++ " one")),
+ comp("one::two", os:cmd(Echo ++ " one two")),
+ comp("one two", os:cmd(Echo ++ " \"one two\"")),
+ comp("x::one two::y", os:cmd(Echo ++ " x \"one two\" y")),
+ comp("x::one two", os:cmd(Echo ++ " x \"one two\"")),
+ comp("one two::y", os:cmd(Echo ++ " \"one two\" y")),
+ comp("x::::y", os:cmd(Echo ++ " x \"\" y")),
+ ct:sleep(5),
+ [] = receive_all(),
ok.
-cmd_unicode(doc) -> "Test that unicode arguments work.";
-cmd_unicode(suite) -> [];
+%% Test that unicode arguments work.
cmd_unicode(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line Echo = filename:join(DataDir, "my_echo"),
-
- ?line comp("one", os:cmd(Echo ++ " one")),
- ?line comp("one::two", os:cmd(Echo ++ " one two")),
- ?line comp("åäö::ϼΩ", os:cmd(Echo ++ " åäö " ++ [1020, 937])),
- ?t:sleep(5),
- ?line [] = receive_all(),
+ DataDir = proplists:get_value(data_dir, Config),
+ Echo = filename:join(DataDir, "my_echo"),
+
+ comp("one", os:cmd(Echo ++ " one")),
+ comp("one::two", os:cmd(Echo ++ " one two")),
+ comp("åäö::ϼΩ", os:cmd(Echo ++ " åäö " ++ [1020, 937])),
+ ct:sleep(5),
+ [] = receive_all(),
ok.
-space_in_name(doc) ->
- "Test that program with a space in its name can be executed.";
-space_in_name(suite) -> [];
+%% Test that program with a space in its name can be executed.
space_in_name(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line DataDir = ?config(data_dir, Config),
- ?line Spacedir = filename:join(PrivDir, "program files"),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ Spacedir = filename:join(PrivDir, "program files"),
Ext = case os:type() of
{win32,_} -> ".exe";
_ -> ""
end,
- ?line OrigEcho = filename:join(DataDir, "my_echo" ++ Ext),
- ?line Echo0 = filename:join(Spacedir, "my_echo" ++ Ext),
+ OrigEcho = filename:join(DataDir, "my_echo" ++ Ext),
+ Echo0 = filename:join(Spacedir, "my_echo" ++ Ext),
%% Copy the `my_echo' program to a directory whose name contains a space.
- ?line ok = file:make_dir(Spacedir),
- ?line {ok, Bin} = file:read_file(OrigEcho),
- ?line ok = file:write_file(Echo0, Bin),
- ?line Echo = filename:nativename(Echo0),
- ?line ok = file:change_mode(Echo, 8#777), % Make it executable on Unix.
+ ok = file:make_dir(Spacedir),
+ {ok, Bin} = file:read_file(OrigEcho),
+ ok = file:write_file(Echo0, Bin),
+ Echo = filename:nativename(Echo0),
+ ok = file:change_mode(Echo, 8#777), % Make it executable on Unix.
%% Run the echo program.
%% Quoting on windows depends on if the full path of the executable
@@ -146,78 +150,74 @@ space_in_name(Config) when is_list(Config) ->
_ ->
"\""
end,
- ?line comp("", os:cmd(Quote ++ Echo ++ Quote)),
- ?line comp("a::b::c", os:cmd(Quote ++ Echo ++ Quote ++ " a b c")),
- ?t:sleep(5),
- ?line [] = receive_all(),
+ comp("", os:cmd(Quote ++ Echo ++ Quote)),
+ comp("a::b::c", os:cmd(Quote ++ Echo ++ Quote ++ " a b c")),
+ ct:sleep(5),
+ [] = receive_all(),
ok.
-bad_command(doc) ->
- "Check that a bad command doesn't crasch the server or the emulator (it used to).";
-bad_command(suite) -> [];
+%% Check that a bad command doesn't crasch the server or the emulator (it used to).
bad_command(Config) when is_list(Config) ->
- ?line catch os:cmd([a|b]),
- ?line catch os:cmd({bad, thing}),
+ catch os:cmd([a|b]),
+ catch os:cmd({bad, thing}),
%% This should at least not crash (on Unix it typically returns
%% a message from the shell).
- ?line os:cmd("xxxxx"),
+ os:cmd("xxxxx"),
ok.
-find_executable(suite) -> [];
-find_executable(doc) -> [];
find_executable(Config) when is_list(Config) ->
case os:type() of
{win32, _} ->
- ?line DataDir = filename:join(?config(data_dir, Config), "win32"),
- ?line ok = file:set_cwd(filename:join([DataDir, "current"])),
- ?line Bin = filename:join(DataDir, "bin"),
- ?line Abin = filename:join(DataDir, "abin"),
- ?line UsrBin = filename:join([DataDir, "usr", "bin"]),
- ?line {ok, Current} = file:get_cwd(),
+ DataDir = filename:join(proplists:get_value(data_dir, Config), "win32"),
+ ok = file:set_cwd(filename:join([DataDir, "current"])),
+ Bin = filename:join(DataDir, "bin"),
+ Abin = filename:join(DataDir, "abin"),
+ UsrBin = filename:join([DataDir, "usr", "bin"]),
+ {ok, Current} = file:get_cwd(),
- ?line Path = lists:concat([Bin, ";", Abin, ";", UsrBin]),
- ?line io:format("Path = ~s", [Path]),
+ Path = lists:concat([Bin, ";", Abin, ";", UsrBin]),
+ io:format("Path = ~s", [Path]),
%% Search for programs in Bin (second element in PATH).
- ?line find_exe(Abin, "my_ar", ".exe", Path),
- ?line find_exe(Abin, "my_ascii", ".com", Path),
- ?line find_exe(Abin, "my_adb", ".bat", Path),
+ find_exe(Abin, "my_ar", ".exe", Path),
+ find_exe(Abin, "my_ascii", ".com", Path),
+ find_exe(Abin, "my_adb", ".bat", Path),
%% OTP-3626 find names of executables given with extension
- ?line find_exe(Abin, "my_ar.exe", "", Path),
- ?line find_exe(Abin, "my_ascii.com", "", Path),
- ?line find_exe(Abin, "my_adb.bat", "", Path),
- ?line find_exe(Abin, "my_ar.EXE", "", Path),
- ?line find_exe(Abin, "my_ascii.COM", "", Path),
- ?line find_exe(Abin, "MY_ADB.BAT", "", Path),
+ find_exe(Abin, "my_ar.exe", "", Path),
+ find_exe(Abin, "my_ascii.com", "", Path),
+ find_exe(Abin, "my_adb.bat", "", Path),
+ find_exe(Abin, "my_ar.EXE", "", Path),
+ find_exe(Abin, "my_ascii.COM", "", Path),
+ find_exe(Abin, "MY_ADB.BAT", "", Path),
%% Search for programs in Abin (second element in PATH).
- ?line find_exe(Abin, "my_ar", ".exe", Path),
- ?line find_exe(Abin, "my_ascii", ".com", Path),
- ?line find_exe(Abin, "my_adb", ".bat", Path),
+ find_exe(Abin, "my_ar", ".exe", Path),
+ find_exe(Abin, "my_ascii", ".com", Path),
+ find_exe(Abin, "my_adb", ".bat", Path),
%% Search for programs in the current working directory.
- ?line find_exe(Current, "my_program", ".exe", Path),
- ?line find_exe(Current, "my_command", ".com", Path),
- ?line find_exe(Current, "my_batch", ".bat", Path),
+ find_exe(Current, "my_program", ".exe", Path),
+ find_exe(Current, "my_command", ".com", Path),
+ find_exe(Current, "my_batch", ".bat", Path),
ok;
{unix, _} ->
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
%% Smoke test.
case lib:progname() of
erl ->
- ?line ErlPath = os:find_executable("erl"),
- ?line true = is_list(ErlPath),
- ?line true = filelib:is_regular(ErlPath);
+ ErlPath = os:find_executable("erl"),
+ true = is_list(ErlPath),
+ true = filelib:is_regular(ErlPath);
_ ->
%% Don't bother -- the progname could include options.
ok
end,
%% Never return a directory name.
- ?line false = os:find_executable("unix", [DataDir]),
+ false = os:find_executable("unix", [DataDir]),
ok
end.
@@ -233,29 +233,23 @@ find_exe(Where, Name, Ext, Path) ->
Other ->
io:format("Expected ~p; got (converted to absolute) ~p",
[Expected, Other]),
- test_server:fail()
+ ct:fail(failed)
end;
Other ->
io:format("Expected ~p; got ~p", [Expected, Other]),
- test_server:fail()
+ ct:fail(failed)
end.
-unix_comment_in_command(doc) ->
- "OTP-1805: Test that os:cmd(\"ls #\") works correctly (used to hang).";
-unix_comment_in_command(suite) -> [];
+%% OTP-1805: Test that os:cmd(\ls #\) works correctly (used to hang).
unix_comment_in_command(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(20)),
- ?line Priv = ?config(priv_dir, Config),
- ?line ok = file:set_cwd(Priv),
- ?line _ = os:cmd("ls #"), % Any result is ok.
- ?t:sleep(5),
- ?line [] = receive_all(),
- ?line test_server:timetrap_cancel(Dog),
+ Priv = proplists:get_value(priv_dir, Config),
+ ok = file:set_cwd(Priv),
+ _ = os:cmd("ls #"), % Any result is ok.
+ ct:sleep(5),
+ [] = receive_all(),
ok.
-deep_list_command(doc) ->
- "Check that a deep list in command works equally on unix and on windows.";
-deep_list_command(suite) -> [];
+%% Check that a deep list in command works equally on unix and on windows.
deep_list_command(Config) when is_list(Config) ->
%% As a 'io_lib' module description says: "There is no guarantee that the
%% character lists returned from some of the functions are flat, they can
@@ -267,50 +261,46 @@ deep_list_command(Config) when is_list(Config) ->
%% FYI: [$e, $c, "ho"] =:= io_lib:format("ec~s", ["ho"])
ok.
-
--define(EVIL_PROCS, 100).
--define(EVIL_LOOPS, 100).
--define(PORT_CREATOR, os_cmd_port_creator).
-evil(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:minutes(5)),
- Parent = self(),
- Ps = lists:map(fun (N) ->
- spawn_link(fun () ->
- evil_loop(Parent, ?EVIL_LOOPS,N)
- end)
- end, lists:seq(1, ?EVIL_PROCS)),
- Devil = spawn_link(fun () -> devil(hd(Ps), hd(lists:reverse(Ps))) end),
- lists:foreach(fun (P) -> receive {P, done} -> ok end end, Ps),
- unlink(Devil),
- exit(Devil, kill),
- test_server:timetrap_cancel(Dog),
- ok.
-
-devil(P1, P2) ->
- erlang:display({?PORT_CREATOR, whereis(?PORT_CREATOR)}),
- (catch ?PORT_CREATOR ! lists:seq(1,1000000)),
- (catch ?PORT_CREATOR ! lists:seq(1,666)),
- (catch ?PORT_CREATOR ! grrrrrrrrrrrrrrrr),
- (catch ?PORT_CREATOR ! {'EXIT', P1, buhuuu}),
- (catch ?PORT_CREATOR ! {'EXIT', hd(erlang:ports()), buhuuu}),
- (catch ?PORT_CREATOR ! {'EXIT', P2, arggggggg}),
- receive after 500 -> ok end,
- (catch exit(whereis(?PORT_CREATOR), kill)),
- (catch ?PORT_CREATOR ! ">8|"),
- receive after 500 -> ok end,
- (catch exit(whereis(?PORT_CREATOR), diiiiiiiiiiiiiiiiiiiie)),
- receive after 100 -> ok end,
- devil(P1, P2).
-
-evil_loop(Parent, Loops, N) ->
- Res = integer_to_list(N),
- evil_loop(Parent, Loops, Res, "echo " ++ Res).
-
-evil_loop(Parent, 0, _Res, _Cmd) ->
- Parent ! {self(), done};
-evil_loop(Parent, Loops, Res, Cmd) ->
- comp(Res, os:cmd(Cmd)),
- evil_loop(Parent, Loops-1, Res, Cmd).
+%% Test to take sure that the correct data is
+%% received when doing large commands.
+large_output_command(Config) when is_list(Config) ->
+ %% Maximum allowed on windows is 8192, so we test well below that
+ AAA = lists:duplicate(7000, $a),
+ comp(AAA,os:cmd("echo " ++ AAA)).
+
+%% Test that the os:perf_counter api works as expected
+perf_counter_api(_Config) ->
+
+ true = is_integer(os:perf_counter()),
+ true = os:perf_counter() > 0,
+
+ T1 = os:perf_counter(),
+ timer:sleep(100),
+ T2 = os:perf_counter(),
+ TsDiff = erlang:convert_time_unit(T2 - T1, perf_counter, nano_seconds),
+ ct:pal("T1: ~p~n"
+ "T2: ~p~n"
+ "TsDiff: ~p~n",
+ [T1,T2,TsDiff]),
+
+ %% We allow a 15% diff
+ true = TsDiff < 115000000,
+ true = TsDiff > 85000000,
+
+ T1Ms = os:perf_counter(1000),
+ timer:sleep(100),
+ T2Ms = os:perf_counter(1000),
+ MsDiff = T2Ms - T1Ms,
+ ct:pal("T1Ms: ~p~n"
+ "T2Ms: ~p~n"
+ "MsDiff: ~p~n",
+ [T1Ms,T2Ms,MsDiff]),
+
+ %% We allow a 15% diff
+ true = MsDiff < 115,
+ true = MsDiff > 85.
+
+%% Util functions
comp(Expected, Got) ->
case strip_nl(Got) of
@@ -319,7 +309,7 @@ comp(Expected, Got) ->
Other ->
ok = io:format("Expected: ~ts\n", [Expected]),
ok = io:format("Got: ~ts\n", [Other]),
- test_server:fail()
+ ct:fail(failed)
end.
%% Like lib:nonl/1, but strips \r as well as \n.
diff --git a/lib/kernel/test/pdict_SUITE.erl b/lib/kernel/test/pdict_SUITE.erl
index 6de4ff9f77..a89fdf4797 100644
--- a/lib/kernel/test/pdict_SUITE.erl
+++ b/lib/kernel/test/pdict_SUITE.erl
@@ -18,10 +18,9 @@
%% %CopyrightEnd%
%%
-module(pdict_SUITE).
-%% NB: The ?line macro cannot be used when testing the dictionary.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(M(A,B),m(A,B,?MODULE,?LINE)).
-ifdef(DEBUG).
@@ -32,22 +31,24 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
+ mixed/1,
simple/1, complicated/1, heavy/1, simple_all_keys/1, info/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
-export([other_process/2]).
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(test_server:minutes(10)),
- [{watchdog, Dog} | Config].
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+ Config.
+
+end_per_testcase(_Case, _Config) ->
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
- [simple, complicated, heavy, simple_all_keys, info].
+ [simple, complicated, heavy, simple_all_keys, info,
+ mixed].
groups() ->
[].
@@ -65,10 +66,7 @@ end_per_group(_GroupName, Config) ->
Config.
-simple(doc) ->
- ["Tests simple functionality in process dictionary."];
-simple(suite) ->
- [];
+%% Tests simple functionality in process dictionary.
simple(Config) when is_list(Config) ->
XX = get(),
ok = match_keys(XX),
@@ -109,7 +107,7 @@ complicated(Config) when is_list(Config) ->
Previous = get(),
ok = match_keys(Previous),
Previous = erase(),
- N = case ?t:is_debug() of
+ N = case test_server:is_debug() of
false -> 500000;
true -> 5000
end,
@@ -143,10 +141,7 @@ comp_4([{{key,_}=K,{value,_}=Val}|T]) ->
comp_4(T);
comp_4([]) -> ok.
-heavy(doc) ->
- ["Tests heavy usage of the process dictionary"];
-heavy(suite) ->
- [];
+%% Tests heavy usage of the process dictionary.
heavy(Config) when is_list(Config) ->
XX = get(),
erase(),
@@ -156,7 +151,7 @@ heavy(Config) when is_list(Config) ->
?M([],get()),
time(5000),
?M([],get()),
- case {os:type(),?t:is_debug()} of
+ case {os:type(),test_server:is_debug()} of
{_,true} -> ok;
_ ->
time(50000),
@@ -185,10 +180,7 @@ simple_all_keys_del_loop([K|Ks]) ->
ok = match_keys(get()),
simple_all_keys_del_loop(Ks).
-info(doc) ->
- ["Tests process_info(Pid, dictionary)"];
-info(suite) ->
- [];
+%% Tests process_info(Pid, dictionary).
info(Config) when is_list(Config) ->
L = [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,
q,r,s,t,u,v,x,y,z,'A','B','C','D'],
@@ -369,3 +361,60 @@ match_keys(All) ->
Ks = lists:sort([K||{K,_}<-All]),
Ks = lists:sort(erlang:get_keys()),
ok.
+
+
+%% Do random mixed put/erase to test grow/shrink
+%% Written for a temporary bug in gc during shrink
+mixed(_Config) ->
+ Rand0 = rand:seed_s(exsplus),
+ io:format("Random seed = ~p\n\n", [rand:export_seed_s(Rand0)]),
+
+ erts_debug:set_internal_state(available_internal_state, true),
+ try
+ C = do_mixed([10,0,100,50,1000,500,600,100,150,1,11,2,30,0],
+ 0,
+ array:new(),
+ 1,
+ Rand0),
+ io:format("\nDid total of ~p operations\n", [C])
+ after
+ erts_debug:set_internal_state(available_internal_state, false)
+ end.
+
+do_mixed([], _, _, C, _) ->
+ C;
+do_mixed([GoalN | Tail], GoalN, Array, C, Rand0) ->
+ io:format("Reached goal of ~p keys in dict after ~p mixed ops\n",[GoalN, C]),
+ GoalN = array:size(Array),
+ do_mixed(Tail, GoalN, Array, C, Rand0);
+do_mixed([GoalN | _]=Goals, CurrN, Array0, C, Rand0) ->
+ CurrN = array:size(Array0),
+ GrowPercent = case GoalN > CurrN of
+ true when CurrN == 0 -> 100;
+ true -> 75;
+ false -> 25
+ end,
+ {R, Rand1} = rand:uniform_s(100, Rand0),
+ case R of
+ _ when R =< GrowPercent -> %%%%%%%%%%%%% GROW
+ {Key, Rand2} = rand:uniform_s(10000, Rand1),
+ case put(Key, {Key,C}) of
+ undefined ->
+ Array1 = array:set(CurrN, Key, Array0),
+ do_mixed(Goals, CurrN+1, Array1, C+1, Rand2);
+ _ ->
+ do_mixed(Goals, CurrN, Array0, C+1, Rand2)
+ end;
+
+ _ -> %%%%%%%%%% SHRINK
+ {Kix, Rand2} = rand:uniform_s(CurrN, Rand1),
+ Key = array:get(Kix-1, Array0),
+
+ %% provoke GC during shrink
+ erts_debug:set_internal_state(fill_heap, true),
+
+ {Key, _} = erase(Key),
+ Array1 = array:set(Kix-1, array:get(CurrN-1, Array0), Array0),
+ Array2 = array:resize(CurrN-1, Array1),
+ do_mixed(Goals, CurrN-1, Array2, C+1, Rand2)
+ end.
diff --git a/lib/kernel/test/pg2_SUITE.erl b/lib/kernel/test/pg2_SUITE.erl
index 832d2d1c27..53544be763 100644
--- a/lib/kernel/test/pg2_SUITE.erl
+++ b/lib/kernel/test/pg2_SUITE.erl
@@ -21,9 +21,9 @@
%%-----------------------------------------------------------------
-module(pg2_SUITE).
--include_lib("test_server/include/test_server.hrl").
--define(datadir, ?config(data_dir, Config)).
--define(privdir, ?config(priv_dir, Config)).
+-include_lib("common_test/include/ct.hrl").
+-define(datadir, proplists:get_value(data_dir, Config)).
+-define(privdir, proplists:get_value(priv_dir, Config)).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
@@ -33,27 +33,23 @@
otp_7277/1, otp_8259/1, otp_8653/1,
compat/1, basic/1]).
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
-
-define(TESTCASE, testcase_name).
--define(testcase, ?config(?TESTCASE, Config)).
+-define(testcase, proplists:get_value(?TESTCASE, Config)).
%% Internal export.
-export([mk_part_node_and_group/3, part2/4,
mk_part_node/3, part1/5, p_init/3, start_proc/1, sane/0]).
init_per_testcase(Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- [{?TESTCASE, Case}, {watchdog, Dog} | Config].
+ [{?TESTCASE, Case}| Config].
end_per_testcase(_Case, _Config) ->
test_server_ctrl:kill_slavenodes(),
- Dog = ?config(watchdog, _Config),
- test_server:timetrap_cancel(Dog),
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[{group, tickets}].
@@ -76,67 +72,59 @@ end_per_group(_GroupName, Config) ->
-otp_7277(doc) ->
- "OTP-7277. Bugfix leave().";
-otp_7277(suite) -> [];
+%% OTP-7277. Bugfix leave().
otp_7277(Config) when is_list(Config) ->
- ?line ok = pg2:create(a),
- ?line ok = pg2:create(b),
+ ok = pg2:create(a),
+ ok = pg2:create(b),
P = spawn(forever()),
- ?line ok = pg2:join(a, P),
- ?line ok = pg2:leave(b, P),
- ?line true = exit(P, kill),
+ ok = pg2:join(a, P),
+ ok = pg2:leave(b, P),
+ true = exit(P, kill),
case {pg2:get_members(a), pg2:get_local_members(a)} of
{[], []} ->
ok;
_ ->
timer:sleep(100),
- ?line [] = pg2:get_members(a),
- ?line [] = pg2:get_local_members(a)
+ [] = pg2:get_members(a),
+ [] = pg2:get_local_members(a)
end,
- ?line _ = pg2:delete(a),
- ?line _ = pg2:delete(b),
+ _ = pg2:delete(a),
+ _ = pg2:delete(b),
ok.
-define(UNTIL(Seq), loop_until_true(fun() -> Seq end, Config)).
-define(UNTIL_LOOP, 300).
-otp_8653(suite) -> [];
-otp_8653(doc) ->
- ["OTP-8259. Member was not removed after being killed."];
+%% OTP-8259. Member was not removed after being killed.
otp_8653(Config) when is_list(Config) ->
- Timeout = 15,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
-
- ?line [A, B, C] = start_nodes([a, b, c], peer, Config),
+ [A, B, C] = start_nodes([a, b, c], peer, Config),
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
- % make b and c connected, partitioned from node() and a
- ?line rpc_cast(B, ?MODULE, part2, [Config, node(), A, C]),
- ?line ?UNTIL(is_ready_partition(Config)),
+ %% make b and c connected, partitioned from node() and a
+ rpc_cast(B, ?MODULE, part2, [Config, node(), A, C]),
+ ?UNTIL(is_ready_partition(Config)),
- % Connect to the other partition.
- ?line pong = net_adm:ping(B),
+ %% Connect to the other partition.
+ pong = net_adm:ping(B),
timer:sleep(100),
- ?line pong = net_adm:ping(C),
- ?line _ = global:sync(),
- ?line [A, B, C] = lists:sort(nodes()),
+ pong = net_adm:ping(C),
+ _ = global:sync(),
+ [A, B, C] = lists:sort(nodes()),
G = pg2_otp_8653,
- ?line ?UNTIL(begin
- GA = lists:sort(rpc:call(A, pg2, get_members, [G])),
- GB = lists:sort(rpc:call(B, pg2, get_members, [G])),
- GC = lists:sort(rpc:call(C, pg2, get_members, [G])),
- GT = lists:sort(pg2:get_members(G)),
- GA =:= GB andalso
- GB =:= GC andalso
- GC =:= GT andalso
- 8 =:= length(GA)
- end),
- ?line ok = pg2:delete(G),
- ?line stop_nodes([A,B,C]),
- ?line test_server:timetrap_cancel(Dog),
+ ?UNTIL(begin
+ GA = lists:sort(rpc:call(A, pg2, get_members, [G])),
+ GB = lists:sort(rpc:call(B, pg2, get_members, [G])),
+ GC = lists:sort(rpc:call(C, pg2, get_members, [G])),
+ GT = lists:sort(pg2:get_members(G)),
+ GA =:= GB andalso
+ GB =:= GC andalso
+ GC =:= GT andalso
+ 8 =:= length(GA)
+ end),
+ ok = pg2:delete(G),
+ stop_nodes([A,B,C]),
ok.
part2(Config, Main, A, C) ->
@@ -158,54 +146,48 @@ mk_part_node_and_group(File, MyPart0, Config) ->
_ = [ok = pg2:join(G, Pid) || _ <- [1,1]],
touch(File, "done").
-otp_8259(suite) -> [];
-otp_8259(doc) ->
- ["OTP-8259. Member was not removed after being killed."];
+%% OTP-8259. Member was not removed after being killed.
otp_8259(Config) when is_list(Config) ->
- Timeout = 15,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
-
- ?line [A, B, C] = start_nodes([a, b, c], peer, Config),
+ [A, B, C] = start_nodes([a, b, c], peer, Config),
- ?line wait_for_ready_net(Config),
+ wait_for_ready_net(Config),
G = pg2_otp_8259,
Name = otp_8259_a_global_name,
- % start different processes in both partitions
- ?line {Pid, yes} = rpc:call(A, ?MODULE, start_proc, [Name]),
+ %% start different processes in both partitions
+ {Pid, yes} = rpc:call(A, ?MODULE, start_proc, [Name]),
- ?line ok = pg2:create(G),
- ?line ok = pg2:join(G, Pid),
+ ok = pg2:create(G),
+ ok = pg2:join(G, Pid),
- % make b and c connected, partitioned from node() and a
- ?line rpc_cast(B, ?MODULE, part1, [Config, node(), A, C, Name]),
- ?line ?UNTIL(is_ready_partition(Config)),
+ %% make b and c connected, partitioned from node() and a
+ rpc_cast(B, ?MODULE, part1, [Config, node(), A, C, Name]),
+ ?UNTIL(is_ready_partition(Config)),
- % Connect to the other partition.
- % The resolver on node b will be called.
- ?line pong = net_adm:ping(B),
+ %% Connect to the other partition.
+ %% The resolver on node b will be called.
+ pong = net_adm:ping(B),
timer:sleep(100),
- ?line pong = net_adm:ping(C),
- ?line _ = global:sync(),
- ?line [A, B, C] = lists:sort(nodes()),
+ pong = net_adm:ping(C),
+ _ = global:sync(),
+ [A, B, C] = lists:sort(nodes()),
%% Pid has been killed by the resolver.
%% Pid has been removed from pg2 on all nodes, in particular node B.
- ?line ?UNTIL([] =:= rpc:call(B, pg2, get_members, [G])),
- ?line ?UNTIL([] =:= pg2:get_members(G)),
- ?line ?UNTIL([] =:= rpc:call(A, pg2, get_members, [G])),
- ?line ?UNTIL([] =:= rpc:call(C, pg2, get_members, [G])),
-
- ?line ok = pg2:delete(G),
- ?line stop_nodes([A,B,C]),
- ?line test_server:timetrap_cancel(Dog),
+ ?UNTIL([] =:= rpc:call(B, pg2, get_members, [G])),
+ ?UNTIL([] =:= pg2:get_members(G)),
+ ?UNTIL([] =:= rpc:call(A, pg2, get_members, [G])),
+ ?UNTIL([] =:= rpc:call(C, pg2, get_members, [G])),
+
+ ok = pg2:delete(G),
+ stop_nodes([A,B,C]),
ok.
part1(Config, Main, A, C, Name) ->
case catch begin
make_partition(Config, [Main, A], [node(), C]),
- ?line {_Pid, yes} = start_proc(Name)
+ {_Pid, yes} = start_proc(Name)
end of
{_, yes} -> ok
end.
@@ -236,39 +218,33 @@ loop() ->
exit(normal)
end.
-compat(suite) -> [];
-compat(doc) ->
- ["OTP-8259. Check that 'exchange' and 'del_member' work."];
+%% OTP-8259. Check that 'exchange' and 'del_member' work.
compat(Config) when is_list(Config) ->
- case ?t:is_release_available("r13b") of
+ case test_server:is_release_available("r13b") of
true ->
- Timeout = 15,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
Pid = spawn(forever()),
G = a,
- ?line ok = pg2:create(G),
- ?line ok = pg2:join(G, Pid),
- ?line ok = pg2:join(G, Pid),
- ?line {ok, A} = start_node_rel(r13, r13b, slave),
- ?line pong = net_adm:ping(A),
- ?line wait_for_ready_net(Config),
- ?line {ok, _} = rpc:call(A, pg2, start, []),
- ?line ?UNTIL([Pid,Pid] =:= rpc:call(A, pg2, get_members, [a])),
- ?line true = exit(Pid, kill),
- ?line ?UNTIL([] =:= pg2:get_members(a)),
- ?line ?UNTIL([] =:= rpc:call(A, pg2, get_members, [a])),
- ?t:stop_node(A),
- ?line test_server:timetrap_cancel(Dog);
+ ok = pg2:create(G),
+ ok = pg2:join(G, Pid),
+ ok = pg2:join(G, Pid),
+ {ok, A} = start_node_rel(r13, r13b, slave),
+ pong = net_adm:ping(A),
+ wait_for_ready_net(Config),
+ {ok, _} = rpc:call(A, pg2, start, []),
+ ?UNTIL([Pid,Pid] =:= rpc:call(A, pg2, get_members, [a])),
+ true = exit(Pid, kill),
+ ?UNTIL([] =:= pg2:get_members(a)),
+ ?UNTIL([] =:= rpc:call(A, pg2, get_members, [a])),
+ test_server:stop_node(A),
+ ok;
false ->
{skipped, "No support for old node"}
end.
-basic(suite) -> [];
-basic(doc) ->
- ["OTP-8259. Some basic tests."];
+%% OTP-8259. Some basic tests.
basic(Config) when is_list(Config) ->
_ = [pg2:delete(G) || G <- pg2:which_groups()],
- ?line _ = [do(Cs, T, Config) || {T,Cs} <- ts()],
+ _ = [do(Cs, T, Config) || {T,Cs} <- ts()],
ok.
ts() ->
@@ -373,7 +349,7 @@ ts() ->
].
do(Cs, T, Config) ->
- ?t:format("*** Test ~p ***~n", [T]),
+ io:format("*** Test ~p ***~n", [T]),
{ok,T} = (catch {do(Cs, [], [], Config),T}).
do([{nodeup,N} | Cs], Ps, Ns, Config) ->
@@ -425,7 +401,7 @@ doit(N, C, Ps, Ns) ->
Result when Result =:= R orelse R =:= ignore ->
sane(Ns);
Else ->
- ?t:format("~p and ~p: expected ~p, but got ~p~n",
+ io:format("~p and ~p: expected ~p, but got ~p~n",
[F, As, R, Else]),
throw({error,{F, As, R, Else}})
end.
@@ -446,8 +422,8 @@ killit(N, P, Ps, Ns) ->
lists:keydelete(P, 1, Ps).
pr(Node, C) ->
- _ = [?t:format("~p: ", [Node]) || Node =/= node()],
- ?t:format("do ~p~n", [C]).
+ _ = [io:format("~p: ", [Node]) || Node =/= node()],
+ io:format("do ~p~n", [C]).
get_node(N, Ns) ->
if
@@ -475,7 +451,7 @@ replace_pids(A, Ps) ->
sane(Ns) ->
Nodes = [node()] ++ [NN || {_,NN} <- Ns],
- _ = [?t:format("~p, pg2_table:~n ~p~n", % debug
+ _ = [io:format("~p, pg2_table:~n ~p~n", % debug
[N, rpc:call(N, ets, tab2list, [pg2_table])]) ||
N <- Nodes],
R = [case rpc:call(Node, ?MODULE, sane, []) of
@@ -509,7 +485,7 @@ wsane(Ns) ->
Pid when is_pid(Pid), node(Pid) =:= N ->
true =
lists:member(Pid, rpc:call(N, pg2, get_local_members, [G]));
-%% FIXME. Om annan nod: member, local = [].
+ %% FIXME. Om annan nod: member, local = [].
_ -> [] = rpc:call(N, pg2, get_local_members, [G])
end || N <- Ns]
|| G <- pg2:which_groups()].
@@ -558,21 +534,21 @@ start_node_rel(Name, Rel, How) ->
Rel when is_atom(Rel) ->
{[{release, atom_to_list(Rel)}], ""};
RelList ->
- {RelList, ""}
- end,
- ?line Pa = filename:dirname(code:which(?MODULE)),
- ?line Res = test_server:start_node(Name, How,
- [{args,
- Compat ++
- " -kernel net_setuptime 100 "
- " -pa " ++ Pa},
- {erl, Release}]),
+ {RelList, ""}
+ end,
+ Pa = filename:dirname(code:which(?MODULE)),
+ Res = test_server:start_node(Name, How,
+ [{args,
+ Compat ++
+ " -kernel net_setuptime 100 "
+ " -pa " ++ Pa},
+ {erl, Release}]),
Res.
start_nodes(L, How, Config) ->
start_nodes2(L, How, 0, Config),
Nodes = collect_nodes(0, length(L)),
- ?line ?UNTIL([] =:= Nodes -- nodes()),
+ ?UNTIL([] =:= Nodes -- nodes()),
%% Pinging doesn't help, we have to wait too, for nodes() to become
%% correct on the other node.
lists:foreach(fun(E) ->
@@ -588,7 +564,7 @@ verify_nodes(Nodes, Config) ->
verify_nodes([], _N, _Config) ->
[];
verify_nodes([Node | Rest], N, Config) ->
- ?line ?UNTIL(
+ ?UNTIL(
case rpc:call(Node, erlang, nodes, []) of
Nodes when is_list(Nodes) ->
case N =:= lists:sort([Node | Nodes]) of
@@ -620,7 +596,7 @@ start_nodes2([Name | Rest], How, N, Config) ->
Self ! {N, R},
%% sleeping is necessary, or with peer nodes, they will
%% go down again, despite {linked, false}.
- test_server:sleep(100000)
+ ct:sleep(100000)
end),
start_nodes2(Rest, How, N+1, Config).
@@ -640,7 +616,7 @@ start_node(Name0, How, Args, Config) ->
Pa = filename:dirname(code:which(?MODULE)),
test_server:start_node(Name, How, [{args,
Args ++ " " ++
- "-kernel net_setuptime 100 "
+ "-kernel net_setuptime 100 "
"-noshell "
"-pa " ++ Pa},
{linked, false}]).
@@ -648,7 +624,7 @@ stop_nodes(Nodes) ->
lists:foreach(fun(Node) -> stop_node(Node) end, Nodes).
stop_node(Node) ->
- ?t:stop_node(Node).
+ test_server:stop_node(Node).
get_known(Node) ->
case catch gen_server:call({global_name_server,Node},get_known,infinity) of
@@ -672,7 +648,7 @@ make_partition(Config, Part1, Part2) ->
make_partition(Config, Part1, Part2, mk_part_node).
make_partition(Config, Part1, Part2, Function) ->
- Dir = ?config(priv_dir, Config),
+ Dir = proplists:get_value(priv_dir, Config),
Ns = [begin
Name = lists:concat([atom_to_list(N),"_",msec(),".part"]),
File = filename:join([Dir, Name]),
@@ -726,13 +702,13 @@ wait_for_ready_net(Config) ->
wait_for_ready_net(Nodes0, Config) ->
Nodes = lists:sort(Nodes0),
- ?t:format("wait_for_ready_net ~p~n", [Nodes]),
+ io:format("wait_for_ready_net ~p~n", [Nodes]),
?UNTIL(begin
lists:all(fun(N) -> Nodes =:= get_known(N) end, Nodes) and
- lists:all(fun(N) ->
- LNs = rpc:call(N, erlang, nodes, []),
- Nodes =:= lists:sort([N | LNs])
- end, Nodes)
+ lists:all(fun(N) ->
+ LNs = rpc:call(N, erlang, nodes, []),
+ Nodes =:= lists:sort([N | LNs])
+ end, Nodes)
end).
%% To make it less probable that some low-level problem causes
@@ -788,11 +764,11 @@ file_contents(File, ContentsList, Config, LogFile) ->
end).
make_partition_file(Config) ->
- Dir = ?config(priv_dir, Config),
+ Dir = proplists:get_value(priv_dir, Config),
filename:join([Dir, atom_to_list(make_partition_done)]).
msec() ->
msec(now()).
msec(T) ->
- element(1,T)*1000000000 + element(2,T)*1000 + element(3,T) div 1000.
+ element(1,T)*1000000000 + element(2,T)*1000 + element(3,T) div 1000.
diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl
index 3e6d8492f7..149cc6c816 100644
--- a/lib/kernel/test/prim_file_SUITE.erl
+++ b/lib/kernel/test/prim_file_SUITE.erl
@@ -36,7 +36,7 @@
file_write_file_info_a/1, file_write_file_info_b/1,
file_read_file_info_opts/1, file_write_file_info_opts/1,
file_write_read_file_info_opts/1
- ]).
+ ]).
-export([rename_a/1, rename_b/1,
access/1, truncate/1, datasync/1, sync/1,
read_write/1, pread_write/1, append/1, exclusive/1]).
@@ -62,7 +62,7 @@
-export([allocate/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
-define(PRIM_FILE, prim_file).
@@ -105,7 +105,7 @@ groups() ->
file_write_file_info_a, file_write_file_info_b,
file_read_file_info_opts, file_write_file_info_opts,
file_write_read_file_info_opts
- ]},
+ ]},
{errors, [],
[e_delete, e_rename, e_make_dir, e_del_dir]},
{compression, [],
@@ -125,7 +125,7 @@ end_per_group(_GroupName, Config) ->
init_per_suite(Config) when is_list(Config) ->
case os:type() of
{win32, _} ->
- Priv = ?config(priv_dir, Config),
+ Priv = proplists:get_value(priv_dir, Config),
HasAccessTime =
case file:read_file_info(Priv) of
{ok, #file_info{atime={_, {0, 0, 0}}}} ->
@@ -181,92 +181,86 @@ time_dist({_D1, _T1} = DT1, {_D2, _T2} = DT2) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-read_write_file(suite) -> [];
-read_write_file(doc) -> [];
read_write_file(Config) when is_list(Config) ->
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_read_write_file"),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_read_write_file"),
%% Try writing and reading back some term
- ?line SomeTerm = {"This term",{will,be},[written,$t,$o],1,file,[]},
- ?line ok = ?PRIM_FILE:write_file(Name,term_to_binary(SomeTerm)),
- ?line {ok,Bin1} = ?PRIM_FILE:read_file(Name),
- ?line SomeTerm = binary_to_term(Bin1),
-
+ SomeTerm = {"This term",{will,be},[written,$t,$o],1,file,[]},
+ ok = ?PRIM_FILE:write_file(Name,term_to_binary(SomeTerm)),
+ {ok,Bin1} = ?PRIM_FILE:read_file(Name),
+ SomeTerm = binary_to_term(Bin1),
+
%% Try a "null" term
- ?line NullTerm = [],
- ?line ok = ?PRIM_FILE:write_file(Name,term_to_binary(NullTerm)),
- ?line {ok,Bin2} = ?PRIM_FILE:read_file(Name),
- ?line NullTerm = binary_to_term(Bin2),
+ NullTerm = [],
+ ok = ?PRIM_FILE:write_file(Name,term_to_binary(NullTerm)),
+ {ok,Bin2} = ?PRIM_FILE:read_file(Name),
+ NullTerm = binary_to_term(Bin2),
%% Try some "complicated" types
- ?line BigNum = 123456789012345678901234567890,
- ?line ComplTerm = {self(),make_ref(),BigNum,3.14159},
- ?line ok = ?PRIM_FILE:write_file(Name,term_to_binary(ComplTerm)),
- ?line {ok,Bin3} = ?PRIM_FILE:read_file(Name),
- ?line ComplTerm = binary_to_term(Bin3),
+ BigNum = 123456789012345678901234567890,
+ ComplTerm = {self(),make_ref(),BigNum,3.14159},
+ ok = ?PRIM_FILE:write_file(Name,term_to_binary(ComplTerm)),
+ {ok,Bin3} = ?PRIM_FILE:read_file(Name),
+ ComplTerm = binary_to_term(Bin3),
%% Try reading a nonexistent file
- ?line Name2 = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_nonexistent_file"),
- ?line {error, enoent} = ?PRIM_FILE:read_file(Name2),
- ?line {error, enoent} = ?PRIM_FILE:read_file(""),
-
- % Try writing to a bad filename
- ?line {error, enoent} =
+ Name2 = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_nonexistent_file"),
+ {error, enoent} = ?PRIM_FILE:read_file(Name2),
+ {error, enoent} = ?PRIM_FILE:read_file(""),
+
+ %% Try writing to a bad filename
+ {error, enoent} =
?PRIM_FILE:write_file("",term_to_binary(NullTerm)),
- % Try writing something else than a binary
- ?line {error, badarg} = ?PRIM_FILE:write_file(Name,{1,2,3}),
- ?line {error, badarg} = ?PRIM_FILE:write_file(Name,self()),
+ %% Try writing something else than a binary
+ {error, badarg} = ?PRIM_FILE:write_file(Name,{1,2,3}),
+ {error, badarg} = ?PRIM_FILE:write_file(Name,self()),
%% Some non-term binaries
- ?line ok = ?PRIM_FILE:write_file(Name,[]),
- ?line {ok,Bin4} = ?PRIM_FILE:read_file(Name),
- ?line 0 = byte_size(Bin4),
+ ok = ?PRIM_FILE:write_file(Name,[]),
+ {ok,Bin4} = ?PRIM_FILE:read_file(Name),
+ 0 = byte_size(Bin4),
- ?line ok = ?PRIM_FILE:write_file(Name,[Bin1,[],[[Bin2]]]),
- ?line {ok,Bin5} = ?PRIM_FILE:read_file(Name),
- ?line {Bin1,Bin2} = split_binary(Bin5,byte_size(Bin1)),
+ ok = ?PRIM_FILE:write_file(Name,[Bin1,[],[[Bin2]]]),
+ {ok,Bin5} = ?PRIM_FILE:read_file(Name),
+ {Bin1,Bin2} = split_binary(Bin5,byte_size(Bin1)),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-make_del_dir_a(suite) -> [];
-make_del_dir_a(doc) -> [];
make_del_dir_a(Config) when is_list(Config) ->
make_del_dir(Config, [], "_a").
-make_del_dir_b(suite) -> [];
-make_del_dir_b(doc) -> [];
make_del_dir_b(Config) when is_list(Config) ->
- ?line {ok, Handle} = ?PRIM_FILE:start(),
+ {ok, Handle} = ?PRIM_FILE:start(),
Result = make_del_dir(Config, Handle, "_b"),
- ?line ok = ?PRIM_FILE:stop(Handle),
+ ok = ?PRIM_FILE:stop(Handle),
%% Just to make sure the state of the server makes a difference
- ?line {error, einval} = ?PRIM_FILE_call(get_cwd, Handle, []),
+ {error, einval} = ?PRIM_FILE_call(get_cwd, Handle, []),
Result.
make_del_dir(Config, Handle, Suffix) ->
- ?line RootDir = ?config(priv_dir,Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_mk-dir"++Suffix),
- ?line ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
- ?line {error, eexist} = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
- ?line ok = ?PRIM_FILE_call(del_dir, Handle, [NewDir]),
- ?line {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [NewDir]),
-
- % Make sure we are not in a directory directly under test_server
- % as that would result in eacces errors when trying to delete '..',
- % because there are processes having that directory as current.
- ?line ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
- ?line {ok, CurrentDir} = ?PRIM_FILE_call(get_cwd, Handle, []),
+ RootDir = proplists:get_value(priv_dir,Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_mk-dir"++Suffix),
+ ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
+ {error, eexist} = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
+ ok = ?PRIM_FILE_call(del_dir, Handle, [NewDir]),
+ {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [NewDir]),
+
+ %% Make sure we are not in a directory directly under test_server
+ %% as that would result in eacces errors when trying to delete '..',
+ %% because there are processes having that directory as current.
+ ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
+ {ok, CurrentDir} = ?PRIM_FILE_call(get_cwd, Handle, []),
case {os:type(), length(NewDir) >= 260 } of
{{win32,_}, true} ->
io:format("Skip set_cwd for windows path longer than 260 (MAX_PATH)\n", []),
@@ -277,18 +271,18 @@ make_del_dir(Config, Handle, Suffix) ->
try
%% Check that we get an error when trying to create...
%% a deep directory
- ?line NewDir2 = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_mk-dir-noexist/foo"),
- ?line {error, enoent} = ?PRIM_FILE_call(make_dir, Handle, [NewDir2]),
+ NewDir2 = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_mk-dir-noexist/foo"),
+ {error, enoent} = ?PRIM_FILE_call(make_dir, Handle, [NewDir2]),
%% a nameless directory
- ?line {error, enoent} = ?PRIM_FILE_call(make_dir, Handle, [""]),
+ {error, enoent} = ?PRIM_FILE_call(make_dir, Handle, [""]),
%% a directory with illegal name
- ?line {error, badarg} = ?PRIM_FILE_call(make_dir, Handle, ['mk-dir']),
-
+ {error, badarg} = ?PRIM_FILE_call(make_dir, Handle, ['mk-dir']),
+
%% a directory with illegal name, even if it's a (bad) list
- ?line {error, badarg} = ?PRIM_FILE_call(make_dir, Handle, [[1,2,3,{}]]),
-
+ {error, badarg} = ?PRIM_FILE_call(make_dir, Handle, [[1,2,3,{}]]),
+
%% Maybe this isn't an error, exactly, but worth mentioning anyway:
%% ok = ?PRIM_FILE:make_dir([$f,$o,$o,0,$b,$a,$r])),
%% The above line works, and created a directory "./foo"
@@ -296,41 +290,37 @@ make_del_dir(Config, Handle, Suffix) ->
%% a directory, but with a name that incorporates the "bar" part of
%% the list, so that [$f,$o,$o,0,$f,$o,$o] wouldn't refer to the same
%% dir. But this would slow it down.
-
+
%% Try deleting some bad directories
%% Deleting the parent directory to the current, sounds dangerous, huh?
%% Don't worry ;-) the parent directory should never be empty, right?
- ?line case ?PRIM_FILE_call(del_dir, Handle, [".."]) of
- {error, eexist} -> ok;
- {error, eacces} -> ok; %OpenBSD
- {error, einval} -> ok %FreeBSD
- end,
- ?line {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [""]),
- ?line {error, badarg} = ?PRIM_FILE_call(del_dir, Handle, [[3,2,1,{}]])
+ case ?PRIM_FILE_call(del_dir, Handle, [".."]) of
+ {error, eexist} -> ok;
+ {error, eacces} -> ok; %OpenBSD
+ {error, einval} -> ok %FreeBSD
+ end,
+ {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [""]),
+ {error, badarg} = ?PRIM_FILE_call(del_dir, Handle, [[3,2,1,{}]])
after
- ?line ok = ?PRIM_FILE_call(set_cwd, Handle, [CurrentDir])
+ ok = ?PRIM_FILE_call(set_cwd, Handle, [CurrentDir])
end,
ok.
-cur_dir_0a(suite) -> [];
-cur_dir_0a(doc) -> [];
cur_dir_0a(Config) when is_list(Config) ->
cur_dir_0(Config, []).
-cur_dir_0b(suite) -> [];
-cur_dir_0b(doc) -> [];
cur_dir_0b(Config) when is_list(Config) ->
- ?line {ok, Handle} = ?PRIM_FILE:start(),
+ {ok, Handle} = ?PRIM_FILE:start(),
Result = cur_dir_0(Config, Handle),
- ?line ok = ?PRIM_FILE:stop(Handle),
+ ok = ?PRIM_FILE:stop(Handle),
Result.
cur_dir_0(Config, Handle) ->
%% Find out the current dir, and cd to it ;-)
- ?line {ok,BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, []),
- ?line Dir1 = BaseDir ++ "", %% Check that it's a string
- ?line ok = ?PRIM_FILE_call(set_cwd, Handle, [Dir1]),
- ?line DirName = atom_to_list(?MODULE) ++
+ {ok,BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, []),
+ Dir1 = BaseDir ++ "", %% Check that it's a string
+ ok = ?PRIM_FILE_call(set_cwd, Handle, [Dir1]),
+ DirName = atom_to_list(?MODULE) ++
case Handle of
[] ->
"_curdir";
@@ -339,9 +329,9 @@ cur_dir_0(Config, Handle) ->
end,
%% Make a new dir, and cd to that
- ?line RootDir = ?config(priv_dir,Config),
- ?line NewDir = filename:join(RootDir, DirName),
- ?line ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
+ RootDir = proplists:get_value(priv_dir,Config),
+ NewDir = filename:join(RootDir, DirName),
+ ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
case {os:type(), length(NewDir) >= 260} of
{{win32,_}, true} ->
io:format("Skip set_cwd for windows path longer than 260 (MAX_PATH):\n"),
@@ -361,7 +351,7 @@ cur_dir_0(Config, Handle) ->
%% Delete the directory and return to the old current directory
%% and check that the created file isn't there (too!)
expect({error, einval}, {error, eacces}, {error, eexist},
- ?PRIM_FILE_call(del_dir, Handle, [NewDir])),
+ ?PRIM_FILE_call(del_dir, Handle, [NewDir])),
?PRIM_FILE_call(delete, Handle, [UncommonName]),
{ok,[]} = ?PRIM_FILE_call(list_dir, Handle, ["."]),
ok = ?PRIM_FILE_call(set_cwd, Handle, [Dir1]),
@@ -375,13 +365,13 @@ cur_dir_0(Config, Handle) ->
end,
%% Try doing some bad things
- ?line {error, badarg} =
+ {error, badarg} =
?PRIM_FILE_call(set_cwd, Handle, [{foo,bar}]),
- ?line {error, enoent} =
+ {error, enoent} =
?PRIM_FILE_call(set_cwd, Handle, [""]),
- ?line {error, enoent} =
+ {error, enoent} =
?PRIM_FILE_call(set_cwd, Handle, [".......a......"]),
- ?line {ok,BaseDir} =
+ {ok,BaseDir} =
?PRIM_FILE_call(get_cwd, Handle, []), %% Still there?
%% On Windows, there should only be slashes, no backslashes,
@@ -389,44 +379,40 @@ cur_dir_0(Config, Handle) ->
%% (The test is harmless on Unix, because filenames usually
%% don't contain backslashes.)
- ?line {ok, BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, []),
- ?line false = lists:member($\\, BaseDir),
+ {ok, BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, []),
+ false = lists:member($\\, BaseDir),
ok.
%% Tests ?PRIM_FILE:get_cwd/1.
-cur_dir_1a(suite) -> [];
-cur_dir_1a(doc) -> [];
cur_dir_1a(Config) when is_list(Config) ->
cur_dir_1(Config, []).
-cur_dir_1b(suite) -> [];
-cur_dir_1b(doc) -> [];
cur_dir_1b(Config) when is_list(Config) ->
- ?line {ok, Handle} = ?PRIM_FILE:start(),
+ {ok, Handle} = ?PRIM_FILE:start(),
Result = cur_dir_1(Config, Handle),
- ?line ok = ?PRIM_FILE:stop(Handle),
+ ok = ?PRIM_FILE:stop(Handle),
Result.
cur_dir_1(Config, Handle) ->
- ?line case os:type() of
- {win32, _} ->
- win_cur_dir_1(Config, Handle);
- _ ->
- ?line {error, enotsup} =
- ?PRIM_FILE_call(get_cwd, Handle, ["d:"])
- end,
+ case os:type() of
+ {win32, _} ->
+ win_cur_dir_1(Config, Handle);
+ _ ->
+ {error, enotsup} =
+ ?PRIM_FILE_call(get_cwd, Handle, ["d:"])
+ end,
ok.
-
+
win_cur_dir_1(_Config, Handle) ->
- ?line {ok, BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, []),
+ {ok, BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, []),
%% Get the drive letter from the current directory,
%% and try to get current directory for that drive.
- ?line [Drive, $:|_] = BaseDir,
- ?line {ok, BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, [[Drive, $:]]),
+ [Drive, $:|_] = BaseDir,
+ {ok, BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, [[Drive, $:]]),
io:format("BaseDir = ~s\n", [BaseDir]),
%% Unfortunately, there is no way to move away from the
@@ -439,440 +425,405 @@ win_cur_dir_1(_Config, Handle) ->
-open1(suite) -> [];
-open1(doc) -> [];
open1(Config) when is_list(Config) ->
- ?line RootDir = ?config(priv_dir,Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_files"),
- ?line ok = ?PRIM_FILE:make_dir(NewDir),
- ?line Name = filename:join(NewDir, "foo1.fil"),
- ?line {ok,Fd1} = ?PRIM_FILE:open(Name, [read, write]),
- ?line {ok,Fd2} = ?PRIM_FILE:open(Name, [read]),
- ?line Str = "{a,tuple}.\n",
- ?line Length = length(Str),
- ?line ?PRIM_FILE:write(Fd1,Str),
- ?line {ok,0} = ?PRIM_FILE:position(Fd1,bof),
- ?line {ok, Str} = ?PRIM_FILE:read(Fd1,Length),
- ?line case ?PRIM_FILE:read(Fd2,Length) of
- {ok,Str} -> Str;
- eof -> Str
- end,
- ?line ok = ?PRIM_FILE:close(Fd2),
- ?line {ok,0} = ?PRIM_FILE:position(Fd1,bof),
- ?line ok = ?PRIM_FILE:truncate(Fd1),
- ?line eof = ?PRIM_FILE:read(Fd1,Length),
- ?line ok = ?PRIM_FILE:close(Fd1),
- ?line {ok,Fd3} = ?PRIM_FILE:open(Name, [read]),
- ?line eof = ?PRIM_FILE:read(Fd3,Length),
- ?line ok = ?PRIM_FILE:close(Fd3),
+ RootDir = proplists:get_value(priv_dir,Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_files"),
+ ok = ?PRIM_FILE:make_dir(NewDir),
+ Name = filename:join(NewDir, "foo1.fil"),
+ {ok,Fd1} = ?PRIM_FILE:open(Name, [read, write]),
+ {ok,Fd2} = ?PRIM_FILE:open(Name, [read]),
+ Str = "{a,tuple}.\n",
+ Length = length(Str),
+ ?PRIM_FILE:write(Fd1,Str),
+ {ok,0} = ?PRIM_FILE:position(Fd1,bof),
+ {ok, Str} = ?PRIM_FILE:read(Fd1,Length),
+ {ok, Str} = ?PRIM_FILE:read(Fd2,Length),
+ ok = ?PRIM_FILE:close(Fd2),
+ {ok,0} = ?PRIM_FILE:position(Fd1,bof),
+ ok = ?PRIM_FILE:truncate(Fd1),
+ eof = ?PRIM_FILE:read(Fd1,Length),
+ ok = ?PRIM_FILE:close(Fd1),
+ {ok,Fd3} = ?PRIM_FILE:open(Name, [read]),
+ eof = ?PRIM_FILE:read(Fd3,Length),
+ ok = ?PRIM_FILE:close(Fd3),
ok.
%% Tests all open modes.
-modes(suite) -> [];
-modes(doc) -> [];
modes(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_open_modes"),
- ?line ok = ?PRIM_FILE:make_dir(NewDir),
- ?line Name1 = filename:join(NewDir, "foo1.fil"),
- ?line Marker = "hello, world",
- ?line Length = length(Marker),
+ RootDir = proplists:get_value(priv_dir, Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_open_modes"),
+ ok = ?PRIM_FILE:make_dir(NewDir),
+ Name1 = filename:join(NewDir, "foo1.fil"),
+ Marker = "hello, world",
+ Length = length(Marker),
%% write
- ?line {ok, Fd1} = ?PRIM_FILE:open(Name1, [write]),
- ?line ok = ?PRIM_FILE:write(Fd1, Marker),
- ?line ok = ?PRIM_FILE:write(Fd1, ".\n"),
- ?line ok = ?PRIM_FILE:close(Fd1),
+ {ok, Fd1} = ?PRIM_FILE:open(Name1, [write]),
+ ok = ?PRIM_FILE:write(Fd1, Marker),
+ ok = ?PRIM_FILE:write(Fd1, ".\n"),
+ ok = ?PRIM_FILE:close(Fd1),
%% read
- ?line {ok, Fd2} = ?PRIM_FILE:open(Name1, [read]),
- ?line {ok, Marker} = ?PRIM_FILE:read(Fd2, Length),
- ?line ok = ?PRIM_FILE:close(Fd2),
+ {ok, Fd2} = ?PRIM_FILE:open(Name1, [read]),
+ {ok, Marker} = ?PRIM_FILE:read(Fd2, Length),
+ ok = ?PRIM_FILE:close(Fd2),
%% read and write
- ?line {ok, Fd3} = ?PRIM_FILE:open(Name1, [read, write]),
- ?line {ok, Marker} = ?PRIM_FILE:read(Fd3, Length),
- ?line ok = ?PRIM_FILE:write(Fd3, Marker),
- ?line ok = ?PRIM_FILE:close(Fd3),
+ {ok, Fd3} = ?PRIM_FILE:open(Name1, [read, write]),
+ {ok, Marker} = ?PRIM_FILE:read(Fd3, Length),
+ ok = ?PRIM_FILE:write(Fd3, Marker),
+ ok = ?PRIM_FILE:close(Fd3),
%% read by default
- ?line {ok, Fd4} = ?PRIM_FILE:open(Name1, []),
- ?line {ok, Marker} = ?PRIM_FILE:read(Fd4, Length),
- ?line ok = ?PRIM_FILE:close(Fd4),
+ {ok, Fd4} = ?PRIM_FILE:open(Name1, []),
+ {ok, Marker} = ?PRIM_FILE:read(Fd4, Length),
+ ok = ?PRIM_FILE:close(Fd4),
%% read and binary
- ?line BinaryMarker = list_to_binary(Marker),
- ?line {ok, Fd5} = ?PRIM_FILE:open(Name1, [read, binary]),
- ?line {ok, BinaryMarker} = ?PRIM_FILE:read(Fd5, Length),
- ?line ok = ?PRIM_FILE:close(Fd5),
+ BinaryMarker = list_to_binary(Marker),
+ {ok, Fd5} = ?PRIM_FILE:open(Name1, [read, binary]),
+ {ok, BinaryMarker} = ?PRIM_FILE:read(Fd5, Length),
+ ok = ?PRIM_FILE:close(Fd5),
- ?line test_server:timetrap_cancel(Dog),
ok.
-close(suite) -> [];
-close(doc) -> [];
close(Config) when is_list(Config) ->
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_close.fil"),
- ?line {ok,Fd1} = ?PRIM_FILE:open(Name, [read, write]),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_close.fil"),
+ {ok,Fd1} = ?PRIM_FILE:open(Name, [read, write]),
%% Just closing it is no fun, we did that a million times already
%% This is a common error, for code written before Erlang 4.3
%% bacause then ?PRIM_FILE:open just returned a Pid, and not everyone
%% really checked what they got.
- ?line {'EXIT',_Msg} = (catch ok = ?PRIM_FILE:close({ok,Fd1})),
- ?line ok = ?PRIM_FILE:close(Fd1),
+ {'EXIT',_Msg} = (catch ok = ?PRIM_FILE:close({ok,Fd1})),
+ ok = ?PRIM_FILE:close(Fd1),
%% Try closing one more time
- ?line Val = ?PRIM_FILE:close(Fd1),
- ?line io:format("Second close gave: ~p", [Val]),
+ Val = ?PRIM_FILE:close(Fd1),
+ io:format("Second close gave: ~p", [Val]),
ok.
-access(suite) -> [];
-access(doc) -> [];
access(Config) when is_list(Config) ->
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_access.fil"),
- ?line Str = "ABCDEFGH",
- ?line {ok,Fd1} = ?PRIM_FILE:open(Name, [write]),
- ?line ?PRIM_FILE:write(Fd1,Str),
- ?line ok = ?PRIM_FILE:close(Fd1),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_access.fil"),
+ Str = "ABCDEFGH",
+ {ok,Fd1} = ?PRIM_FILE:open(Name, [write]),
+ ?PRIM_FILE:write(Fd1,Str),
+ ok = ?PRIM_FILE:close(Fd1),
%% Check that we can't write when in read only mode
- ?line {ok,Fd2} = ?PRIM_FILE:open(Name, [read]),
- ?line case catch ?PRIM_FILE:write(Fd2,"XXXX") of
- ok ->
- test_server:fail({access,write});
- _ ->
- ok
- end,
- ?line ok = ?PRIM_FILE:close(Fd2),
- ?line {ok, Fd3} = ?PRIM_FILE:open(Name, [read]),
- ?line {ok, Str} = ?PRIM_FILE:read(Fd3,length(Str)),
- ?line ok = ?PRIM_FILE:close(Fd3),
+ {ok,Fd2} = ?PRIM_FILE:open(Name, [read]),
+ case catch ?PRIM_FILE:write(Fd2,"XXXX") of
+ ok ->
+ ct:fail({access,write});
+ _ ->
+ ok
+ end,
+ ok = ?PRIM_FILE:close(Fd2),
+ {ok, Fd3} = ?PRIM_FILE:open(Name, [read]),
+ {ok, Str} = ?PRIM_FILE:read(Fd3,length(Str)),
+ ok = ?PRIM_FILE:close(Fd3),
ok.
%% Tests ?PRIM_FILE:read/2 and ?PRIM_FILE:write/2.
-read_write(suite) -> [];
-read_write(doc) -> [];
read_write(Config) when is_list(Config) ->
- ?line RootDir = ?config(priv_dir, Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_read_write"),
- ?line ok = ?PRIM_FILE:make_dir(NewDir),
+ RootDir = proplists:get_value(priv_dir, Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_read_write"),
+ ok = ?PRIM_FILE:make_dir(NewDir),
%% Raw file.
- ?line Name = filename:join(NewDir, "raw.fil"),
- ?line {ok, Fd} = ?PRIM_FILE:open(Name, [read, write]),
- ?line read_write_test(Fd),
+ Name = filename:join(NewDir, "raw.fil"),
+ {ok, Fd} = ?PRIM_FILE:open(Name, [read, write]),
+ read_write_test(Fd),
ok.
read_write_test(File) ->
- ?line Marker = "hello, world",
- ?line ok = ?PRIM_FILE:write(File, Marker),
- ?line {ok, 0} = ?PRIM_FILE:position(File, 0),
- ?line {ok, Marker} = ?PRIM_FILE:read(File, 100),
- ?line eof = ?PRIM_FILE:read(File, 100),
- ?line ok = ?PRIM_FILE:close(File),
+ Marker = "hello, world",
+ ok = ?PRIM_FILE:write(File, Marker),
+ {ok, 0} = ?PRIM_FILE:position(File, 0),
+ {ok, Marker} = ?PRIM_FILE:read(File, 100),
+ eof = ?PRIM_FILE:read(File, 100),
+ ok = ?PRIM_FILE:close(File),
ok.
%% Tests ?PRIM_FILE:pread/2 and ?PRIM_FILE:pwrite/2.
-pread_write(suite) -> [];
-pread_write(doc) -> [];
pread_write(Config) when is_list(Config) ->
- ?line RootDir = ?config(priv_dir, Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_pread_write"),
- ?line ok = ?PRIM_FILE:make_dir(NewDir),
+ RootDir = proplists:get_value(priv_dir, Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_pread_write"),
+ ok = ?PRIM_FILE:make_dir(NewDir),
%% Raw file.
- ?line Name = filename:join(NewDir, "raw.fil"),
- ?line {ok, Fd} = ?PRIM_FILE:open(Name, [read, write]),
- ?line pread_write_test(Fd),
+ Name = filename:join(NewDir, "raw.fil"),
+ {ok, Fd} = ?PRIM_FILE:open(Name, [read, write]),
+ pread_write_test(Fd),
ok.
pread_write_test(File) ->
- ?line Marker = "hello, world",
- ?line Len = length(Marker),
- ?line ok = ?PRIM_FILE:write(File, Marker),
- ?line {ok, Marker} = ?PRIM_FILE:pread(File, 0, 100),
- ?line eof = ?PRIM_FILE:pread(File, 100, 1),
- ?line ok = ?PRIM_FILE:pwrite(File, Len, Marker),
- ?line {ok, Marker} = ?PRIM_FILE:pread(File, Len, 100),
- ?line eof = ?PRIM_FILE:pread(File, 100, 1),
- ?line MM = Marker ++ Marker,
- ?line {ok, MM} = ?PRIM_FILE:pread(File, 0, 100),
- ?line ok = ?PRIM_FILE:close(File),
+ Marker = "hello, world",
+ Len = length(Marker),
+ ok = ?PRIM_FILE:write(File, Marker),
+ {ok, Marker} = ?PRIM_FILE:pread(File, 0, 100),
+ eof = ?PRIM_FILE:pread(File, 100, 1),
+ ok = ?PRIM_FILE:pwrite(File, Len, Marker),
+ {ok, Marker} = ?PRIM_FILE:pread(File, Len, 100),
+ eof = ?PRIM_FILE:pread(File, 100, 1),
+ MM = Marker ++ Marker,
+ {ok, MM} = ?PRIM_FILE:pread(File, 0, 100),
+ ok = ?PRIM_FILE:close(File),
ok.
-append(doc) -> "Test appending to a file.";
-append(suite) -> [];
+%% Test appending to a file.
append(Config) when is_list(Config) ->
- ?line RootDir = ?config(priv_dir, Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_append"),
- ?line ok = ?PRIM_FILE:make_dir(NewDir),
+ RootDir = proplists:get_value(priv_dir, Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_append"),
+ ok = ?PRIM_FILE:make_dir(NewDir),
- ?line First = "First line\n",
- ?line Second = "Seond lines comes here\n",
- ?line Third = "And here is the third line\n",
+ First = "First line\n",
+ Second = "Seond lines comes here\n",
+ Third = "And here is the third line\n",
%% Write a small text file.
- ?line Name1 = filename:join(NewDir, "a_file.txt"),
- ?line {ok, Fd1} = ?PRIM_FILE:open(Name1, [write]),
- ?line ok = ?PRIM_FILE:write(Fd1, First),
- ?line ok = ?PRIM_FILE:write(Fd1, Second),
- ?line ok = ?PRIM_FILE:close(Fd1),
+ Name1 = filename:join(NewDir, "a_file.txt"),
+ {ok, Fd1} = ?PRIM_FILE:open(Name1, [write]),
+ ok = ?PRIM_FILE:write(Fd1, First),
+ ok = ?PRIM_FILE:write(Fd1, Second),
+ ok = ?PRIM_FILE:close(Fd1),
%% Open it a again and a append a line to it.
- ?line {ok, Fd2} = ?PRIM_FILE:open(Name1, [append]),
- ?line ok = ?PRIM_FILE:write(Fd2, Third),
- ?line ok = ?PRIM_FILE:close(Fd2),
+ {ok, Fd2} = ?PRIM_FILE:open(Name1, [append]),
+ ok = ?PRIM_FILE:write(Fd2, Third),
+ ok = ?PRIM_FILE:close(Fd2),
%% Read it back and verify.
- ?line Expected = list_to_binary([First, Second, Third]),
- ?line {ok, Expected} = ?PRIM_FILE:read_file(Name1),
+ Expected = list_to_binary([First, Second, Third]),
+ {ok, Expected} = ?PRIM_FILE:read_file(Name1),
ok.
-exclusive(suite) -> [];
-exclusive(doc) -> "Test exclusive access to a file.";
+%% Test exclusive access to a file.
exclusive(Config) when is_list(Config) ->
- ?line RootDir = ?config(priv_dir,Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_exclusive"),
- ?line ok = ?PRIM_FILE:make_dir(NewDir),
- ?line Name = filename:join(NewDir, "ex_file.txt"),
- ?line {ok,Fd} = ?PRIM_FILE:open(Name, [write, exclusive]),
- ?line {error, eexist} = ?PRIM_FILE:open(Name, [write, exclusive]),
- ?line ok = ?PRIM_FILE:close(Fd),
+ RootDir = proplists:get_value(priv_dir,Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_exclusive"),
+ ok = ?PRIM_FILE:make_dir(NewDir),
+ Name = filename:join(NewDir, "ex_file.txt"),
+ {ok,Fd} = ?PRIM_FILE:open(Name, [write, exclusive]),
+ {error, eexist} = ?PRIM_FILE:open(Name, [write, exclusive]),
+ ok = ?PRIM_FILE:close(Fd),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-pos1(suite) -> [];
-pos1(doc) -> [];
pos1(Config) when is_list(Config) ->
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_pos1.fil"),
- ?line {ok, Fd1} = ?PRIM_FILE:open(Name, [write]),
- ?line ?PRIM_FILE:write(Fd1,"ABCDEFGH"),
- ?line ok = ?PRIM_FILE:close(Fd1),
- ?line {ok, Fd2} = ?PRIM_FILE:open(Name, [read]),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_pos1.fil"),
+ {ok, Fd1} = ?PRIM_FILE:open(Name, [write]),
+ ?PRIM_FILE:write(Fd1,"ABCDEFGH"),
+ ok = ?PRIM_FILE:close(Fd1),
+ {ok, Fd2} = ?PRIM_FILE:open(Name, [read]),
%% Start pos is first char
- ?line io:format("Relative positions"),
- ?line {ok, "A"} = ?PRIM_FILE:read(Fd2,1),
- ?line {ok, 2} = ?PRIM_FILE:position(Fd2,{cur,1}),
- ?line {ok, "C"} = ?PRIM_FILE:read(Fd2,1),
- ?line {ok, 0} = ?PRIM_FILE:position(Fd2,{cur,-3}),
- ?line {ok, "A"} = ?PRIM_FILE:read(Fd2,1),
+ io:format("Relative positions"),
+ {ok, "A"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, 2} = ?PRIM_FILE:position(Fd2,{cur,1}),
+ {ok, "C"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, 0} = ?PRIM_FILE:position(Fd2,{cur,-3}),
+ {ok, "A"} = ?PRIM_FILE:read(Fd2,1),
%% Backwards from first char should be an error
- ?line {ok,0} = ?PRIM_FILE:position(Fd2,{cur,-1}),
- ?line {error, einval} = ?PRIM_FILE:position(Fd2,{cur,-1}),
+ {ok,0} = ?PRIM_FILE:position(Fd2,{cur,-1}),
+ {error, einval} = ?PRIM_FILE:position(Fd2,{cur,-1}),
%% Reset position and move again
- ?line {ok, 0} = ?PRIM_FILE:position(Fd2,0),
- ?line {ok, 2} = ?PRIM_FILE:position(Fd2,{cur,2}),
- ?line {ok, "C"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, 0} = ?PRIM_FILE:position(Fd2,0),
+ {ok, 2} = ?PRIM_FILE:position(Fd2,{cur,2}),
+ {ok, "C"} = ?PRIM_FILE:read(Fd2,1),
%% Go a lot forwards
- ?line {ok, 13} = ?PRIM_FILE:position(Fd2,{cur,10}),
- ?line eof = ?PRIM_FILE:read(Fd2,1),
+ {ok, 13} = ?PRIM_FILE:position(Fd2,{cur,10}),
+ eof = ?PRIM_FILE:read(Fd2,1),
%% Try some fixed positions
- ?line io:format("Fixed positions"),
- ?line {ok, 8} = ?PRIM_FILE:position(Fd2,8),
- ?line eof = ?PRIM_FILE:read(Fd2,1),
- ?line {ok, 8} = ?PRIM_FILE:position(Fd2,cur),
- ?line eof = ?PRIM_FILE:read(Fd2,1),
- ?line {ok, 7} = ?PRIM_FILE:position(Fd2,7),
- ?line {ok, "H"} = ?PRIM_FILE:read(Fd2,1),
- ?line {ok, 0} = ?PRIM_FILE:position(Fd2,0),
- ?line {ok, "A"} = ?PRIM_FILE:read(Fd2,1),
- ?line {ok, 3} = ?PRIM_FILE:position(Fd2,3),
- ?line {ok, "D"} = ?PRIM_FILE:read(Fd2,1),
- ?line {ok, 12} = ?PRIM_FILE:position(Fd2,12),
- ?line eof = ?PRIM_FILE:read(Fd2,1),
- ?line {ok, 3} = ?PRIM_FILE:position(Fd2,3),
- ?line {ok, "D"} = ?PRIM_FILE:read(Fd2,1),
+ io:format("Fixed positions"),
+ {ok, 8} = ?PRIM_FILE:position(Fd2,8),
+ eof = ?PRIM_FILE:read(Fd2,1),
+ {ok, 8} = ?PRIM_FILE:position(Fd2,cur),
+ eof = ?PRIM_FILE:read(Fd2,1),
+ {ok, 7} = ?PRIM_FILE:position(Fd2,7),
+ {ok, "H"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, 0} = ?PRIM_FILE:position(Fd2,0),
+ {ok, "A"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, 3} = ?PRIM_FILE:position(Fd2,3),
+ {ok, "D"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, 12} = ?PRIM_FILE:position(Fd2,12),
+ eof = ?PRIM_FILE:read(Fd2,1),
+ {ok, 3} = ?PRIM_FILE:position(Fd2,3),
+ {ok, "D"} = ?PRIM_FILE:read(Fd2,1),
%% Try the {bof,X} notation
- ?line {ok, 3} = ?PRIM_FILE:position(Fd2,{bof,3}),
- ?line {ok, "D"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, 3} = ?PRIM_FILE:position(Fd2,{bof,3}),
+ {ok, "D"} = ?PRIM_FILE:read(Fd2,1),
%% Try eof positions
- ?line io:format("EOF positions"),
- ?line {ok, 8} = ?PRIM_FILE:position(Fd2,{eof,0}),
- ?line eof = ?PRIM_FILE:read(Fd2,1),
- ?line {ok, 7} = ?PRIM_FILE:position(Fd2,{eof,-1}),
- ?line {ok, "H"} = ?PRIM_FILE:read(Fd2,1),
- ?line {ok, 0} = ?PRIM_FILE:position(Fd2,{eof,-8}),
- ?line {ok, "A"} = ?PRIM_FILE:read(Fd2,1),
- ?line {error, einval} = ?PRIM_FILE:position(Fd2,{eof,-9}),
+ io:format("EOF positions"),
+ {ok, 8} = ?PRIM_FILE:position(Fd2,{eof,0}),
+ eof = ?PRIM_FILE:read(Fd2,1),
+ {ok, 7} = ?PRIM_FILE:position(Fd2,{eof,-1}),
+ {ok, "H"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, 0} = ?PRIM_FILE:position(Fd2,{eof,-8}),
+ {ok, "A"} = ?PRIM_FILE:read(Fd2,1),
+ {error, einval} = ?PRIM_FILE:position(Fd2,{eof,-9}),
ok.
-pos2(suite) -> [];
-pos2(doc) -> [];
pos2(Config) when is_list(Config) ->
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_pos2.fil"),
- ?line {ok,Fd1} = ?PRIM_FILE:open(Name, [write]),
- ?line ?PRIM_FILE:write(Fd1,"ABCDEFGH"),
- ?line ok = ?PRIM_FILE:close(Fd1),
- ?line {ok, Fd2} = ?PRIM_FILE:open(Name, [read]),
- ?line {error, einval} = ?PRIM_FILE:position(Fd2,-1),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_pos2.fil"),
+ {ok,Fd1} = ?PRIM_FILE:open(Name, [write]),
+ ?PRIM_FILE:write(Fd1,"ABCDEFGH"),
+ ok = ?PRIM_FILE:close(Fd1),
+ {ok, Fd2} = ?PRIM_FILE:open(Name, [read]),
+ {error, einval} = ?PRIM_FILE:position(Fd2,-1),
%% Make sure that we still can search after an error.
- ?line {ok, 0} = ?PRIM_FILE:position(Fd2, 0),
- ?line {ok, 3} = ?PRIM_FILE:position(Fd2, {bof,3}),
- ?line {ok, "D"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, 0} = ?PRIM_FILE:position(Fd2, 0),
+ {ok, 3} = ?PRIM_FILE:position(Fd2, {bof,3}),
+ {ok, "D"} = ?PRIM_FILE:read(Fd2,1),
- ?line io:format("DONE"),
+ io:format("DONE"),
ok.
-file_info_basic_file_a(suite) -> [];
-file_info_basic_file_a(doc) -> [];
file_info_basic_file_a(Config) when is_list(Config) ->
file_info_basic_file(Config, [], "_a").
-file_info_basic_file_b(suite) -> [];
-file_info_basic_file_b(doc) -> [];
file_info_basic_file_b(Config) when is_list(Config) ->
- ?line {ok, Handle} = ?PRIM_FILE:start(),
+ {ok, Handle} = ?PRIM_FILE:start(),
Result = file_info_basic_file(Config, Handle, "_b"),
- ?line ok = ?PRIM_FILE:stop(Handle),
+ ok = ?PRIM_FILE:stop(Handle),
Result.
file_info_basic_file(Config, Handle, Suffix) ->
- ?line RootDir = ?config(priv_dir, Config),
+ RootDir = proplists:get_value(priv_dir, Config),
%% Create a short file.
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_basic_test"++Suffix++".fil"),
- ?line {ok,Fd1} = ?PRIM_FILE:open(Name, [write]),
- ?line ?PRIM_FILE:write(Fd1, "foo bar"),
- ?line ok = ?PRIM_FILE:close(Fd1),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_basic_test"++Suffix++".fil"),
+ {ok,Fd1} = ?PRIM_FILE:open(Name, [write]),
+ ?PRIM_FILE:write(Fd1, "foo bar"),
+ ok = ?PRIM_FILE:close(Fd1),
%% Test that the file has the expected attributes.
%% The times are tricky, so we will save them to a separate test case.
- ?line {ok, FileInfo} = ?PRIM_FILE_call(read_file_info, Handle, [Name]),
- ?line #file_info{size = Size, type = Type, access = Access,
- atime = AccessTime, mtime = ModifyTime} =
+ {ok, FileInfo} = ?PRIM_FILE_call(read_file_info, Handle, [Name]),
+ #file_info{size = Size, type = Type, access = Access,
+ atime = AccessTime, mtime = ModifyTime} =
FileInfo,
- ?line io:format("Access ~p, Modify ~p", [AccessTime, ModifyTime]),
- ?line Size = 7,
- ?line Type = regular,
- ?line Access = read_write,
- ?line true = abs(time_dist(filter_atime(AccessTime, Config),
- filter_atime(ModifyTime,
- Config))) < 2,
- ?line {AD, AT} = AccessTime,
- ?line all_integers(tuple_to_list(AD) ++ tuple_to_list(AT)),
- ?line {MD, MT} = ModifyTime,
- ?line all_integers(tuple_to_list(MD) ++ tuple_to_list(MT)),
+ io:format("Access ~p, Modify ~p", [AccessTime, ModifyTime]),
+ Size = 7,
+ Type = regular,
+ Access = read_write,
+ true = abs(time_dist(filter_atime(AccessTime, Config),
+ filter_atime(ModifyTime,
+ Config))) < 2,
+ {AD, AT} = AccessTime,
+ all_integers(tuple_to_list(AD) ++ tuple_to_list(AT)),
+ {MD, MT} = ModifyTime,
+ all_integers(tuple_to_list(MD) ++ tuple_to_list(MT)),
ok.
-file_info_basic_directory_a(suite) -> [];
-file_info_basic_directory_a(doc) -> [];
file_info_basic_directory_a(Config) when is_list(Config) ->
file_info_basic_directory(Config, []).
-file_info_basic_directory_b(suite) -> [];
-file_info_basic_directory_b(doc) -> [];
file_info_basic_directory_b(Config) when is_list(Config) ->
- ?line {ok, Handle} = ?PRIM_FILE:start(),
+ {ok, Handle} = ?PRIM_FILE:start(),
Result = file_info_basic_directory(Config, Handle),
- ?line ok = ?PRIM_FILE:stop(Handle),
+ ok = ?PRIM_FILE:stop(Handle),
Result.
file_info_basic_directory(Config, Handle) ->
%% Note: filename:join/1 removes any trailing slash,
%% which is essential for ?PRIM_FILE:read_file_info/1 to work on
%% platforms such as Windows95.
- ?line RootDir = filename:join([?config(priv_dir, Config)]),
+ RootDir = filename:join([proplists:get_value(priv_dir, Config)]),
%% Test that the RootDir directory has the expected attributes.
- ?line test_directory(RootDir, read_write, Handle),
+ test_directory(RootDir, read_write, Handle),
%% Note that on Windows file systems, "/" or "c:/" are *NOT* directories.
%% Therefore, test that ?PRIM_FILE:read_file_info/1 behaves
%% as if they were directories.
- ?line case os:type() of
- {win32, _} ->
- ?line test_directory("/", read_write, Handle),
- ?line test_directory("c:/", read_write, Handle),
- ?line test_directory("c:\\", read_write, Handle);
- _ ->
- ?line test_directory("/", read, Handle)
- end,
+ case os:type() of
+ {win32, _} ->
+ test_directory("/", read_write, Handle),
+ test_directory("c:/", read_write, Handle),
+ test_directory("c:\\", read_write, Handle);
+ _ ->
+ test_directory("/", read, Handle)
+ end,
ok.
test_directory(Name, ExpectedAccess, Handle) ->
- ?line {ok, FileInfo} = ?PRIM_FILE_call(read_file_info, Handle, [Name]),
- ?line #file_info{size = Size, type = Type, access = Access,
- atime = AccessTime, mtime = ModifyTime} =
+ {ok, FileInfo} = ?PRIM_FILE_call(read_file_info, Handle, [Name]),
+ #file_info{size = Size, type = Type, access = Access,
+ atime = AccessTime, mtime = ModifyTime} =
FileInfo,
- ?line io:format("Testing directory ~s", [Name]),
- ?line io:format("Directory size is ~p", [Size]),
- ?line io:format("Access ~p", [Access]),
- ?line io:format("Access time ~p; Modify time~p",
- [AccessTime, ModifyTime]),
- ?line Type = directory,
- ?line Access = ExpectedAccess,
- ?line {AD, AT} = AccessTime,
- ?line all_integers(tuple_to_list(AD) ++ tuple_to_list(AT)),
- ?line {MD, MT} = ModifyTime,
- ?line all_integers(tuple_to_list(MD) ++ tuple_to_list(MT)),
+ io:format("Testing directory ~s", [Name]),
+ io:format("Directory size is ~p", [Size]),
+ io:format("Access ~p", [Access]),
+ io:format("Access time ~p; Modify time~p",
+ [AccessTime, ModifyTime]),
+ Type = directory,
+ Access = ExpectedAccess,
+ {AD, AT} = AccessTime,
+ all_integers(tuple_to_list(AD) ++ tuple_to_list(AT)),
+ {MD, MT} = ModifyTime,
+ all_integers(tuple_to_list(MD) ++ tuple_to_list(MT)),
ok.
all_integers([Int|Rest]) when is_integer(Int) ->
- ?line all_integers(Rest);
+ all_integers(Rest);
all_integers([]) ->
ok.
%% Try something nonexistent.
-file_info_bad_a(suite) -> [];
-file_info_bad_a(doc) -> [];
file_info_bad_a(Config) when is_list(Config) ->
file_info_bad(Config, []).
-file_info_bad_b(suite) -> [];
-file_info_bad_b(doc) -> [];
file_info_bad_b(Config) when is_list(Config) ->
- ?line {ok, Handle} = ?PRIM_FILE:start(),
+ {ok, Handle} = ?PRIM_FILE:start(),
Result = file_info_bad(Config, Handle),
- ?line ok = ?PRIM_FILE:stop(Handle),
+ ok = ?PRIM_FILE:stop(Handle),
Result.
file_info_bad(Config, Handle) ->
- ?line RootDir = filename:join([?config(priv_dir, Config)]),
- ?line {error, enoent} =
+ RootDir = filename:join([proplists:get_value(priv_dir, Config)]),
+ {error, enoent} =
?PRIM_FILE_call(
read_file_info, Handle,
[filename:join(RootDir,
@@ -881,28 +832,22 @@ file_info_bad(Config, Handle) ->
%% Test that the file times behave as they should.
-file_info_times_a(suite) -> [];
-file_info_times_a(doc) -> [];
file_info_times_a(Config) when is_list(Config) ->
file_info_times(Config, [], "_a").
-file_info_times_b(suite) -> [];
-file_info_times_b(doc) -> [];
file_info_times_b(Config) when is_list(Config) ->
- ?line {ok, Handle} = ?PRIM_FILE:start(),
+ {ok, Handle} = ?PRIM_FILE:start(),
Result = file_info_times(Config, Handle, "_b"),
- ?line ok = ?PRIM_FILE:stop(Handle),
+ ok = ?PRIM_FILE:stop(Handle),
Result.
file_info_times(Config, Handle, Suffix) ->
- ?line Dog = test_server:timetrap(test_server:seconds(60)),
%% We have to try this twice, since if the test runs across the change
%% of a month the time diff calculations will fail. But it won't happen
%% if you run it twice in succession.
- ?line test_server:m_out_of_n(
- 1,2,
- fun() -> ?line file_info_int(Config, Handle, Suffix) end),
- ?line test_server:timetrap_cancel(Dog),
+ test_server:m_out_of_n(
+ 1,2,
+ fun() -> file_info_int(Config, Handle, Suffix) end),
ok.
file_info_int(Config, Handle, Suffix) ->
@@ -910,55 +855,55 @@ file_info_int(Config, Handle, Suffix) ->
%% which is essential for ?PRIM_FILE:read_file_info/1 to work on
%% platforms such as Windows95.
- ?line RootDir = filename:join([?config(priv_dir, Config)]),
- ?line test_server:format("RootDir = ~p", [RootDir]),
+ RootDir = filename:join([proplists:get_value(priv_dir, Config)]),
+ io:format("RootDir = ~p", [RootDir]),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_file_info"++Suffix++".fil"),
- ?line {ok,Fd1} = ?PRIM_FILE:open(Name, [write]),
- ?line ?PRIM_FILE:write(Fd1,"foo"),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_file_info"++Suffix++".fil"),
+ {ok,Fd1} = ?PRIM_FILE:open(Name, [write]),
+ ?PRIM_FILE:write(Fd1,"foo"),
%% check that the file got a modify date max a few seconds away from now
- ?line {ok, #file_info{type = regular,
- atime = AccTime1, mtime = ModTime1}} =
+ {ok, #file_info{type = regular,
+ atime = AccTime1, mtime = ModTime1}} =
?PRIM_FILE_call(read_file_info, Handle, [Name]),
- ?line Now = erlang:localtime(),
- ?line io:format("Now ~p",[Now]),
- ?line io:format("Open file Acc ~p Mod ~p",[AccTime1,ModTime1]),
- ?line true = abs(time_dist(filter_atime(Now, Config),
- filter_atime(AccTime1,
- Config))) < 8,
- ?line true = abs(time_dist(Now, ModTime1)) < 8,
-
+ Now = erlang:localtime(),
+ io:format("Now ~p",[Now]),
+ io:format("Open file Acc ~p Mod ~p",[AccTime1,ModTime1]),
+ true = abs(time_dist(filter_atime(Now, Config),
+ filter_atime(AccTime1,
+ Config))) < 8,
+ true = abs(time_dist(Now, ModTime1)) < 8,
+
%% Sleep until we can be sure the seconds value has changed.
%% Note: FAT-based filesystem (like on Windows 95) have
%% a resolution of 2 seconds.
- ?line test_server:sleep(test_server:seconds(2.2)),
+ ct:sleep({seconds,2.2}),
%% close the file, and watch the modify date change
- ?line ok = ?PRIM_FILE:close(Fd1),
- ?line {ok, #file_info{size = Size, type = regular, access = Access,
- atime = AccTime2, mtime = ModTime2}} =
+ ok = ?PRIM_FILE:close(Fd1),
+ {ok, #file_info{size = Size, type = regular, access = Access,
+ atime = AccTime2, mtime = ModTime2}} =
?PRIM_FILE_call(read_file_info, Handle, [Name]),
- ?line io:format("Closed file Acc ~p Mod ~p",[AccTime2,ModTime2]),
- ?line true = time_dist(ModTime1, ModTime2) >= 0,
+ io:format("Closed file Acc ~p Mod ~p",[AccTime2,ModTime2]),
+ true = time_dist(ModTime1, ModTime2) >= 0,
%% this file is supposed to be binary, so it'd better keep it's size
- ?line Size = 3,
- ?line Access = read_write,
+ Size = 3,
+ Access = read_write,
%% Do some directory checking
- ?line {ok, #file_info{size = DSize, type = directory,
- access = DAccess,
- atime = AccTime3, mtime = ModTime3}} =
+ {ok, #file_info{size = DSize, type = directory,
+ access = DAccess,
+ atime = AccTime3, mtime = ModTime3}} =
?PRIM_FILE_call(read_file_info, Handle, [RootDir]),
%% this dir was modified only a few secs ago
- ?line io:format("Dir Acc ~p; Mod ~p; Now ~p",
- [AccTime3, ModTime3, Now]),
- ?line true = abs(time_dist(Now, ModTime3)) < 5,
- ?line DAccess = read_write,
- ?line io:format("Dir size is ~p",[DSize]),
+ io:format("Dir Acc ~p; Mod ~p; Now ~p",
+ [AccTime3, ModTime3, Now]),
+ true = abs(time_dist(Now, ModTime3)) < 5,
+ DAccess = read_write,
+ io:format("Dir size is ~p",[DSize]),
ok.
%% Filter access times, to cope with a deficiency of FAT file systems
@@ -969,9 +914,9 @@ filter_atime(Atime, Config) ->
true ->
case Atime of
{Date, _} ->
- {Date, {0, 0, 0}};
+ {Date, {0, 0, 0}};
{Y, M, D, _, _, _} ->
- {Y, M, D, 0, 0, 0}
+ {Y, M, D, 0, 0, 0}
end;
false ->
Atime
@@ -979,163 +924,146 @@ filter_atime(Atime, Config) ->
%% Test the write_file_info/2 function.
-file_write_file_info_a(suite) -> [];
-file_write_file_info_a(doc) -> [];
file_write_file_info_a(Config) when is_list(Config) ->
file_write_file_info(Config, [], "_a").
-file_write_file_info_b(suite) -> [];
-file_write_file_info_b(doc) -> [];
file_write_file_info_b(Config) when is_list(Config) ->
- ?line {ok, Handle} = ?PRIM_FILE:start(),
+ {ok, Handle} = ?PRIM_FILE:start(),
Result = file_write_file_info(Config, Handle, "_b"),
- ?line ok = ?PRIM_FILE:stop(Handle),
+ ok = ?PRIM_FILE:stop(Handle),
Result.
file_write_file_info(Config, Handle, Suffix) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line RootDir = get_good_directory(Config),
- ?line test_server:format("RootDir = ~p", [RootDir]),
+ RootDir = get_good_directory(Config),
+ io:format("RootDir = ~p", [RootDir]),
%% Set the file to read only AND update the file times at the same time.
%% (This used to fail on Windows NT/95 for a local filesystem.)
%% Note: Seconds must be even; see note in file_info_times/1.
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_write_file_info_ro"++Suffix),
- ?line ok = ?PRIM_FILE:write_file(Name, "hello"),
- ?line Time = {{1997, 01, 02}, {12, 35, 42}},
- ?line Info = #file_info{mode=8#400, atime=Time, mtime=Time, ctime=Time},
- ?line ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, Info]),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_write_file_info_ro"++Suffix),
+ ok = ?PRIM_FILE:write_file(Name, "hello"),
+ Time = {{1997, 01, 02}, {12, 35, 42}},
+ Info = #file_info{mode=8#400, atime=Time, mtime=Time, ctime=Time},
+ ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, Info]),
%% Read back the times.
- ?line {ok, ActualInfo} =
+ {ok, ActualInfo} =
?PRIM_FILE_call(read_file_info, Handle, [Name]),
- ?line #file_info{mode=_Mode, atime=ActAtime, mtime=Time,
- ctime=ActCtime} = ActualInfo,
- ?line FilteredAtime = filter_atime(Time, Config),
- ?line FilteredAtime = filter_atime(ActAtime, Config),
- ?line case os:type() of
- {win32, _} ->
- %% On Windows, "ctime" means creation time and it can
- %% be set.
- ActCtime = Time;
- _ ->
- ok
- end,
- ?line {error, eacces} = ?PRIM_FILE:write_file(Name, "hello again"),
+ #file_info{mode=_Mode, atime=ActAtime, mtime=Time,
+ ctime=ActCtime} = ActualInfo,
+ FilteredAtime = filter_atime(Time, Config),
+ FilteredAtime = filter_atime(ActAtime, Config),
+ case os:type() of
+ {win32, _} ->
+ %% On Windows, "ctime" means creation time and it can
+ %% be set.
+ ActCtime = Time;
+ _ ->
+ ok
+ end,
+ {error, eacces} = ?PRIM_FILE:write_file(Name, "hello again"),
%% Make the file writable again.
- ?line ?PRIM_FILE_call(write_file_info, Handle,
- [Name, #file_info{mode=8#600}]),
- ?line ok = ?PRIM_FILE:write_file(Name, "hello again"),
+ ?PRIM_FILE_call(write_file_info, Handle,
+ [Name, #file_info{mode=8#600}]),
+ ok = ?PRIM_FILE:write_file(Name, "hello again"),
%% And unwritable.
- ?line ?PRIM_FILE_call(write_file_info, Handle,
- [Name, #file_info{mode=8#400}]),
- ?line {error, eacces} = ?PRIM_FILE:write_file(Name, "hello again"),
+ ?PRIM_FILE_call(write_file_info, Handle,
+ [Name, #file_info{mode=8#400}]),
+ {error, eacces} = ?PRIM_FILE:write_file(Name, "hello again"),
%% Write the times again.
%% Note: Seconds must be even; see note in file_info_times/1.
- ?line NewTime = {{1997, 02, 15}, {13, 18, 20}},
- ?line NewInfo = #file_info{atime=NewTime, mtime=NewTime, ctime=NewTime},
- ?line ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, NewInfo]),
- ?line {ok, ActualInfo2} =
+ NewTime = {{1997, 02, 15}, {13, 18, 20}},
+ NewInfo = #file_info{atime=NewTime, mtime=NewTime, ctime=NewTime},
+ ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, NewInfo]),
+ {ok, ActualInfo2} =
?PRIM_FILE_call(read_file_info, Handle, [Name]),
- ?line #file_info{atime=NewActAtime, mtime=NewTime,
- ctime=NewActCtime} = ActualInfo2,
- ?line NewFilteredAtime = filter_atime(NewTime, Config),
- ?line NewFilteredAtime = filter_atime(NewActAtime, Config),
- ?line case os:type() of
- {win32, _} -> NewActCtime = NewTime;
- _ -> ok
- end,
+ #file_info{atime=NewActAtime, mtime=NewTime,
+ ctime=NewActCtime} = ActualInfo2,
+ NewFilteredAtime = filter_atime(NewTime, Config),
+ NewFilteredAtime = filter_atime(NewActAtime, Config),
+ case os:type() of
+ {win32, _} -> NewActCtime = NewTime;
+ _ -> ok
+ end,
%% The file should still be unwritable.
- ?line {error, eacces} = ?PRIM_FILE:write_file(Name, "hello again"),
+ {error, eacces} = ?PRIM_FILE:write_file(Name, "hello again"),
%% Make the file writeable again, so that we can remove the
%% test suites ... :-)
- ?line ?PRIM_FILE_call(write_file_info, Handle,
- [Name, #file_info{mode=8#600}]),
- ?line test_server:timetrap_cancel(Dog),
+ ?PRIM_FILE_call(write_file_info, Handle,
+ [Name, #file_info{mode=8#600}]),
ok.
%% Test the write_file_info/3 function.
-file_write_file_info_opts(suite) -> [];
-file_write_file_info_opts(doc) -> [];
file_write_file_info_opts(Config) when is_list(Config) ->
{ok, Handle} = ?PRIM_FILE:start(),
- Dog = test_server:timetrap(test_server:seconds(10)),
RootDir = get_good_directory(Config),
- test_server:format("RootDir = ~p", [RootDir]),
+ io:format("RootDir = ~p", [RootDir]),
Name = filename:join(RootDir, atom_to_list(?MODULE) ++"_write_file_info_opts"),
ok = ?PRIM_FILE:write_file(Name, "hello_opts"),
lists:foreach(fun
- ({FI, Opts}) ->
- ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts])
- end, [
- {#file_info{ mode=8#600, atime = Time, mtime = Time, ctime = Time}, Opts} ||
- Opts <- [[{time, posix}]],
- Time <- [ 0,1,-1,100,-100,1000,-1000,10000,-10000 ]
- ]),
-
- % REM: determine date range dependent on time_t = Uint32 | Sint32 | Sint64
- % Determine time_t on os:type()?
+ ({FI, Opts}) ->
+ ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts])
+ end, [
+ {#file_info{ mode=8#600, atime = Time, mtime = Time, ctime = Time}, Opts} ||
+ Opts <- [[{time, posix}]],
+ Time <- [ 0,1,-1,100,-100,1000,-1000,10000,-10000 ]
+ ]),
+
+ %% REM: determine date range dependent on time_t = Uint32 | Sint32 | Sint64
+ %% Determine time_t on os:type()?
lists:foreach(fun
- ({FI, Opts}) ->
- ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts])
- end, [
- {#file_info{ mode=8#400, atime = Time, mtime = Time, ctime = Time}, Opts} ||
- Opts <- [[{time, universal}],[{time, local}]],
- Time <- [
- {{1970,1,1},{0,0,0}},
- {{1970,1,1},{0,0,1}},
- {{1969,12,31},{23,59,59}},
- {{1908,2,3},{23,59,59}},
- {{2012,2,3},{23,59,59}},
- {{2037,2,3},{23,59,59}},
- erlang:localtime()
- ]]),
+ ({FI, Opts}) ->
+ ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts])
+ end, [
+ {#file_info{ mode=8#400, atime = Time, mtime = Time, ctime = Time}, Opts} ||
+ Opts <- [[{time, universal}],[{time, local}]],
+ Time <- [
+ {{1970,1,1},{0,0,0}},
+ {{1970,1,1},{0,0,1}},
+ {{1969,12,31},{23,59,59}},
+ {{1908,2,3},{23,59,59}},
+ {{2012,2,3},{23,59,59}},
+ {{2037,2,3},{23,59,59}},
+ erlang:localtime()
+ ]]),
ok = ?PRIM_FILE:stop(Handle),
- test_server:timetrap_cancel(Dog),
ok.
-file_read_file_info_opts(suite) -> [];
-file_read_file_info_opts(doc) -> [];
file_read_file_info_opts(Config) when is_list(Config) ->
{ok, Handle} = ?PRIM_FILE:start(),
- Dog = test_server:timetrap(test_server:seconds(10)),
RootDir = get_good_directory(Config),
- test_server:format("RootDir = ~p", [RootDir]),
+ io:format("RootDir = ~p", [RootDir]),
Name = filename:join(RootDir, atom_to_list(?MODULE) ++"_read_file_info_opts"),
ok = ?PRIM_FILE:write_file(Name, "hello_opts"),
lists:foreach(fun
- (Opts) ->
- {ok,_} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts])
- end, [[{time, Type}] || Type <- [local, universal, posix]]),
+ (Opts) ->
+ {ok,_} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts])
+ end, [[{time, Type}] || Type <- [local, universal, posix]]),
ok = ?PRIM_FILE:stop(Handle),
- test_server:timetrap_cancel(Dog),
ok.
%% Test the write and read back *_file_info/3 functions.
-file_write_read_file_info_opts(suite) -> [];
-file_write_read_file_info_opts(doc) -> [];
file_write_read_file_info_opts(Config) when is_list(Config) ->
{ok, Handle} = ?PRIM_FILE:start(),
- Dog = test_server:timetrap(test_server:seconds(10)),
RootDir = get_good_directory(Config),
- test_server:format("RootDir = ~p", [RootDir]),
+ io:format("RootDir = ~p", [RootDir]),
Name = filename:join(RootDir, atom_to_list(?MODULE) ++"_read_write_file_info_opts"),
ok = ?PRIM_FILE:write_file(Name, "hello_opts2"),
@@ -1151,7 +1079,6 @@ file_write_read_file_info_opts(Config) when is_list(Config) ->
ok = file_write_read_file_info_opts(Handle, Name, 0, [{time, posix}]),
ok = ?PRIM_FILE:stop(Handle),
- test_server:timetrap_cancel(Dog),
ok.
file_write_read_file_info_opts(Handle, Name, Mtime, Opts) ->
@@ -1166,136 +1093,131 @@ file_write_read_file_info_opts(Handle, Name, Mtime, Opts) ->
%% Returns a directory on a file system that has correct file times.
get_good_directory(Config) ->
- ?line ?config(priv_dir, Config).
+ proplists:get_value(priv_dir, Config).
-truncate(suite) -> [];
-truncate(doc) -> [];
truncate(Config) when is_list(Config) ->
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_truncate.fil"),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_truncate.fil"),
%% Create a file with some data.
- ?line MyData = "0123456789abcdefghijklmnopqrstuvxyz",
- ?line ok = ?PRIM_FILE:write_file(Name, MyData),
+ MyData = "0123456789abcdefghijklmnopqrstuvxyz",
+ ok = ?PRIM_FILE:write_file(Name, MyData),
%% Truncate the file to 10 characters.
- ?line {ok, Fd} = ?PRIM_FILE:open(Name, [read, write]),
- ?line {ok, 10} = ?PRIM_FILE:position(Fd, 10),
- ?line ok = ?PRIM_FILE:truncate(Fd),
- ?line ok = ?PRIM_FILE:close(Fd),
+ {ok, Fd} = ?PRIM_FILE:open(Name, [read, write]),
+ {ok, 10} = ?PRIM_FILE:position(Fd, 10),
+ ok = ?PRIM_FILE:truncate(Fd),
+ ok = ?PRIM_FILE:close(Fd),
%% Read back the file and check that it has been truncated.
- ?line Expected = list_to_binary("0123456789"),
- ?line {ok, Expected} = ?PRIM_FILE:read_file(Name),
+ Expected = list_to_binary("0123456789"),
+ {ok, Expected} = ?PRIM_FILE:read_file(Name),
%% Open the file read only and verify that it is not possible to
%% truncate it, OTP-1960
- ?line {ok, Fd2} = ?PRIM_FILE:open(Name, [read]),
- ?line {ok, 5} = ?PRIM_FILE:position(Fd2, 5),
- ?line {error, _} = ?PRIM_FILE:truncate(Fd2),
+ {ok, Fd2} = ?PRIM_FILE:open(Name, [read]),
+ {ok, 5} = ?PRIM_FILE:position(Fd2, 5),
+ {error, _} = ?PRIM_FILE:truncate(Fd2),
ok.
-datasync(suite) -> [];
-datasync(doc) -> "Tests that ?PRIM_FILE:datasync/1 at least doesn't crash.";
+%% Tests that ?PRIM_FILE:datasync/1 at least doesn't crash.
datasync(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Sync = filename:join(PrivDir,
- atom_to_list(?MODULE)
- ++"_sync.fil"),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Sync = filename:join(PrivDir,
+ atom_to_list(?MODULE)
+ ++"_sync.fil"),
%% Raw open.
- ?line {ok, Fd} = ?PRIM_FILE:open(Sync, [write]),
- ?line ok = ?PRIM_FILE:datasync(Fd),
- ?line ok = ?PRIM_FILE:close(Fd),
+ {ok, Fd} = ?PRIM_FILE:open(Sync, [write]),
+ ok = ?PRIM_FILE:datasync(Fd),
+ ok = ?PRIM_FILE:close(Fd),
ok.
-sync(suite) -> [];
-sync(doc) -> "Tests that ?PRIM_FILE:sync/1 at least doesn't crash.";
+%% Tests that ?PRIM_FILE:sync/1 at least doesn't crash.
sync(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Sync = filename:join(PrivDir,
- atom_to_list(?MODULE)
- ++"_sync.fil"),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Sync = filename:join(PrivDir,
+ atom_to_list(?MODULE)
+ ++"_sync.fil"),
%% Raw open.
- ?line {ok, Fd} = ?PRIM_FILE:open(Sync, [write]),
- ?line ok = ?PRIM_FILE:sync(Fd),
- ?line ok = ?PRIM_FILE:close(Fd),
+ {ok, Fd} = ?PRIM_FILE:open(Sync, [write]),
+ ok = ?PRIM_FILE:sync(Fd),
+ ok = ?PRIM_FILE:close(Fd),
ok.
-advise(suite) -> [];
-advise(doc) -> "Tests that ?PRIM_FILE:advise/4 at least doesn't crash.";
+%% Tests that ?PRIM_FILE:advise/4 at least doesn't crash.
advise(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Advise = filename:join(PrivDir,
- atom_to_list(?MODULE)
- ++"_advise.fil"),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Advise = filename:join(PrivDir,
+ atom_to_list(?MODULE)
+ ++"_advise.fil"),
Line1 = "Hello\n",
Line2 = "World!\n",
- ?line {ok, Fd} = ?PRIM_FILE:open(Advise, [write]),
- ?line ok = ?PRIM_FILE:advise(Fd, 0, 0, normal),
- ?line ok = ?PRIM_FILE:write(Fd, Line1),
- ?line ok = ?PRIM_FILE:write(Fd, Line2),
- ?line ok = ?PRIM_FILE:close(Fd),
-
- ?line {ok, Fd2} = ?PRIM_FILE:open(Advise, [write]),
- ?line ok = ?PRIM_FILE:advise(Fd2, 0, 0, random),
- ?line ok = ?PRIM_FILE:write(Fd2, Line1),
- ?line ok = ?PRIM_FILE:write(Fd2, Line2),
- ?line ok = ?PRIM_FILE:close(Fd2),
-
- ?line {ok, Fd3} = ?PRIM_FILE:open(Advise, [write]),
- ?line ok = ?PRIM_FILE:advise(Fd3, 0, 0, sequential),
- ?line ok = ?PRIM_FILE:write(Fd3, Line1),
- ?line ok = ?PRIM_FILE:write(Fd3, Line2),
- ?line ok = ?PRIM_FILE:close(Fd3),
-
- ?line {ok, Fd4} = ?PRIM_FILE:open(Advise, [write]),
- ?line ok = ?PRIM_FILE:advise(Fd4, 0, 0, will_need),
- ?line ok = ?PRIM_FILE:write(Fd4, Line1),
- ?line ok = ?PRIM_FILE:write(Fd4, Line2),
- ?line ok = ?PRIM_FILE:close(Fd4),
-
- ?line {ok, Fd5} = ?PRIM_FILE:open(Advise, [write]),
- ?line ok = ?PRIM_FILE:advise(Fd5, 0, 0, dont_need),
- ?line ok = ?PRIM_FILE:write(Fd5, Line1),
- ?line ok = ?PRIM_FILE:write(Fd5, Line2),
- ?line ok = ?PRIM_FILE:close(Fd5),
-
- ?line {ok, Fd6} = ?PRIM_FILE:open(Advise, [write]),
- ?line ok = ?PRIM_FILE:advise(Fd6, 0, 0, no_reuse),
- ?line ok = ?PRIM_FILE:write(Fd6, Line1),
- ?line ok = ?PRIM_FILE:write(Fd6, Line2),
- ?line ok = ?PRIM_FILE:close(Fd6),
-
- ?line {ok, Fd7} = ?PRIM_FILE:open(Advise, [write]),
- ?line {error, einval} = ?PRIM_FILE:advise(Fd7, 0, 0, bad_advise),
- ?line ok = ?PRIM_FILE:close(Fd7),
+ {ok, Fd} = ?PRIM_FILE:open(Advise, [write]),
+ ok = ?PRIM_FILE:advise(Fd, 0, 0, normal),
+ ok = ?PRIM_FILE:write(Fd, Line1),
+ ok = ?PRIM_FILE:write(Fd, Line2),
+ ok = ?PRIM_FILE:close(Fd),
+
+ {ok, Fd2} = ?PRIM_FILE:open(Advise, [write]),
+ ok = ?PRIM_FILE:advise(Fd2, 0, 0, random),
+ ok = ?PRIM_FILE:write(Fd2, Line1),
+ ok = ?PRIM_FILE:write(Fd2, Line2),
+ ok = ?PRIM_FILE:close(Fd2),
+
+ {ok, Fd3} = ?PRIM_FILE:open(Advise, [write]),
+ ok = ?PRIM_FILE:advise(Fd3, 0, 0, sequential),
+ ok = ?PRIM_FILE:write(Fd3, Line1),
+ ok = ?PRIM_FILE:write(Fd3, Line2),
+ ok = ?PRIM_FILE:close(Fd3),
+
+ {ok, Fd4} = ?PRIM_FILE:open(Advise, [write]),
+ ok = ?PRIM_FILE:advise(Fd4, 0, 0, will_need),
+ ok = ?PRIM_FILE:write(Fd4, Line1),
+ ok = ?PRIM_FILE:write(Fd4, Line2),
+ ok = ?PRIM_FILE:close(Fd4),
+
+ {ok, Fd5} = ?PRIM_FILE:open(Advise, [write]),
+ ok = ?PRIM_FILE:advise(Fd5, 0, 0, dont_need),
+ ok = ?PRIM_FILE:write(Fd5, Line1),
+ ok = ?PRIM_FILE:write(Fd5, Line2),
+ ok = ?PRIM_FILE:close(Fd5),
+
+ {ok, Fd6} = ?PRIM_FILE:open(Advise, [write]),
+ ok = ?PRIM_FILE:advise(Fd6, 0, 0, no_reuse),
+ ok = ?PRIM_FILE:write(Fd6, Line1),
+ ok = ?PRIM_FILE:write(Fd6, Line2),
+ ok = ?PRIM_FILE:close(Fd6),
+
+ {ok, Fd7} = ?PRIM_FILE:open(Advise, [write]),
+ {error, einval} = ?PRIM_FILE:advise(Fd7, 0, 0, bad_advise),
+ ok = ?PRIM_FILE:close(Fd7),
%% test write without advise, then a read after an advise
- ?line {ok, Fd8} = ?PRIM_FILE:open(Advise, [write]),
- ?line ok = ?PRIM_FILE:write(Fd8, Line1),
- ?line ok = ?PRIM_FILE:write(Fd8, Line2),
- ?line ok = ?PRIM_FILE:close(Fd8),
- ?line {ok, Fd9} = ?PRIM_FILE:open(Advise, [read]),
+ {ok, Fd8} = ?PRIM_FILE:open(Advise, [write]),
+ ok = ?PRIM_FILE:write(Fd8, Line1),
+ ok = ?PRIM_FILE:write(Fd8, Line2),
+ ok = ?PRIM_FILE:close(Fd8),
+ {ok, Fd9} = ?PRIM_FILE:open(Advise, [read]),
Offset = 0,
%% same as a 0 length in some implementations
Length = length(Line1) + length(Line2),
- ?line ok = ?PRIM_FILE:advise(Fd9, Offset, Length, sequential),
- ?line {ok, Line1} = ?PRIM_FILE:read_line(Fd9),
- ?line {ok, Line2} = ?PRIM_FILE:read_line(Fd9),
- ?line eof = ?PRIM_FILE:read_line(Fd9),
- ?line ok = ?PRIM_FILE:close(Fd9),
+ ok = ?PRIM_FILE:advise(Fd9, Offset, Length, sequential),
+ {ok, Line1} = ?PRIM_FILE:read_line(Fd9),
+ {ok, Line2} = ?PRIM_FILE:read_line(Fd9),
+ eof = ?PRIM_FILE:read_line(Fd9),
+ ok = ?PRIM_FILE:close(Fd9),
ok.
@@ -1307,7 +1229,6 @@ large_write(Config) when is_list(Config) ->
"_large_write").
do_large_write(Name) ->
- Dog = test_server:timetrap(test_server:minutes(60)),
ChunkSize = (256 bsl 20) + 1, % 256 M + 1
Chunks = 16, % times 16 -> 4 G + 16
Base = 100,
@@ -1320,187 +1241,177 @@ do_large_write(Name) ->
ok when Wordsize =:= 8 ->
{ok,#file_info{size=Size}} = file:read_file_info(Name),
{ok,Fd} = prim_file:open(Name, [read]),
- check_large_write(Dog, Fd, ChunkSize, 0, Interleave);
+ check_large_write(Fd, ChunkSize, 0, Interleave);
{error,einval} when Wordsize =:= 4 ->
ok
end.
-check_large_write(Dog, Fd, ChunkSize, Pos, [X|Interleave]) ->
+check_large_write(Fd, ChunkSize, Pos, [X|Interleave]) ->
Pos1 = Pos + ChunkSize,
{ok,Pos1} = prim_file:position(Fd, {cur,ChunkSize}),
{ok,[X]} = prim_file:read(Fd, 1),
- check_large_write(Dog, Fd, ChunkSize, Pos1+1, Interleave);
-check_large_write(Dog, Fd, _, _, []) ->
+ check_large_write(Fd, ChunkSize, Pos1+1, Interleave);
+check_large_write(Fd, _, _, []) ->
eof = prim_file:read(Fd, 1),
- test_server:timetrap_cancel(Dog),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-allocate(suite) -> [];
-allocate(doc) -> "Tests that ?PRIM_FILE:allocate/3 at least doesn't crash.";
+%% Tests that ?PRIM_FILE:allocate/3 at least doesn't crash.
allocate(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Allocate = filename:join(PrivDir,
- atom_to_list(?MODULE)
- ++"_allocate.fil"),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Allocate = filename:join(PrivDir,
+ atom_to_list(?MODULE)
+ ++"_allocate.fil"),
Line1 = "Hello\n",
Line2 = "World!\n",
- ?line {ok, Fd} = ?PRIM_FILE:open(Allocate, [write, binary]),
+ {ok, Fd} = ?PRIM_FILE:open(Allocate, [write, binary]),
allocate_and_assert(Fd, 1, iolist_size([Line1, Line2])),
- ?line ok = ?PRIM_FILE:write(Fd, Line1),
- ?line ok = ?PRIM_FILE:write(Fd, Line2),
- ?line ok = ?PRIM_FILE:close(Fd),
+ ok = ?PRIM_FILE:write(Fd, Line1),
+ ok = ?PRIM_FILE:write(Fd, Line2),
+ ok = ?PRIM_FILE:close(Fd),
- ?line {ok, Fd2} = ?PRIM_FILE:open(Allocate, [write, binary]),
+ {ok, Fd2} = ?PRIM_FILE:open(Allocate, [write, binary]),
allocate_and_assert(Fd2, 1, iolist_size(Line1)),
- ?line ok = ?PRIM_FILE:write(Fd2, Line1),
- ?line ok = ?PRIM_FILE:write(Fd2, Line2),
- ?line ok = ?PRIM_FILE:close(Fd2),
+ ok = ?PRIM_FILE:write(Fd2, Line1),
+ ok = ?PRIM_FILE:write(Fd2, Line2),
+ ok = ?PRIM_FILE:close(Fd2),
- ?line {ok, Fd3} = ?PRIM_FILE:open(Allocate, [write, binary]),
+ {ok, Fd3} = ?PRIM_FILE:open(Allocate, [write, binary]),
allocate_and_assert(Fd3, 1, iolist_size(Line1) + 1),
- ?line ok = ?PRIM_FILE:write(Fd3, Line1),
- ?line ok = ?PRIM_FILE:write(Fd3, Line2),
- ?line ok = ?PRIM_FILE:close(Fd3),
+ ok = ?PRIM_FILE:write(Fd3, Line1),
+ ok = ?PRIM_FILE:write(Fd3, Line2),
+ ok = ?PRIM_FILE:close(Fd3),
- ?line {ok, Fd4} = ?PRIM_FILE:open(Allocate, [write, binary]),
+ {ok, Fd4} = ?PRIM_FILE:open(Allocate, [write, binary]),
allocate_and_assert(Fd4, 1, 4 * iolist_size([Line1, Line2])),
- ?line ok = ?PRIM_FILE:write(Fd4, Line1),
- ?line ok = ?PRIM_FILE:write(Fd4, Line2),
- ?line ok = ?PRIM_FILE:close(Fd4),
+ ok = ?PRIM_FILE:write(Fd4, Line1),
+ ok = ?PRIM_FILE:write(Fd4, Line2),
+ ok = ?PRIM_FILE:close(Fd4),
ok.
allocate_and_assert(Fd, Offset, Length) ->
- % Just verify that calls to ?PRIM_FILE:allocate/3 don't crash or have
- % any other negative side effect. We can't really asssert against a
- % specific return value, because support for file space pre-allocation
- % depends on the OS, OS version and underlying filesystem.
- %
- % The Linux kernel added support for fallocate() in version 2.6.23,
- % which currently works only for the ext4, ocfs2, xfs and btrfs file
- % systems. posix_fallocate() is available in glibc as of version
- % 2.1.94, but it was buggy until glibc version 2.7.
- %
- % Mac OS X, as of version 10.3, supports the fcntl operation F_PREALLOCATE.
- %
- % Solaris supports posix_fallocate() but only for the UFS file system
- % apparently (not supported for ZFS).
- %
- % FreeBSD 9.0 is the first FreeBSD release supporting posix_fallocate().
- %
- % For Windows there's apparently no way to pre-allocate file space, at
- % least with similar API/semantics as posix_fallocate(), fallocate() or
- % fcntl F_PREALLOCATE.
+ %% Just verify that calls to ?PRIM_FILE:allocate/3 don't crash or have
+ %% any other negative side effect. We can't really asssert against a
+ %% specific return value, because support for file space pre-allocation
+ %% depends on the OS, OS version and underlying filesystem.
+ %%
+ %% The Linux kernel added support for fallocate() in version 2.6.23,
+ %% which currently works only for the ext4, ocfs2, xfs and btrfs file
+ %% systems. posix_fallocate() is available in glibc as of version
+ %% 2.1.94, but it was buggy until glibc version 2.7.
+ %%
+ %% Mac OS X, as of version 10.3, supports the fcntl operation F_PREALLOCATE.
+ %%
+ %% Solaris supports posix_fallocate() but only for the UFS file system
+ %% apparently (not supported for ZFS).
+ %%
+ %% FreeBSD 9.0 is the first FreeBSD release supporting posix_fallocate().
+ %%
+ %% For Windows there's apparently no way to pre-allocate file space, at
+ %% least with similar API/semantics as posix_fallocate(), fallocate() or
+ %% fcntl F_PREALLOCATE.
Result = ?PRIM_FILE:allocate(Fd, Offset, Length),
case os:type() of
{win32, _} ->
- ?line {error, enotsup} = Result;
+ {error, enotsup} = Result;
_ ->
- ?line _ = Result
+ _ = Result
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-delete_a(suite) -> [];
-delete_a(doc) -> [];
delete_a(Config) when is_list(Config) ->
delete(Config, [], "_a").
-delete_b(suite) -> [];
-delete_b(doc) -> [];
delete_b(Config) when is_list(Config) ->
- ?line {ok, Handle} = ?PRIM_FILE:start(),
+ {ok, Handle} = ?PRIM_FILE:start(),
Result = delete(Config, Handle, "_b"),
- ?line ok = ?PRIM_FILE:stop(Handle),
+ ok = ?PRIM_FILE:stop(Handle),
Result.
delete(Config, Handle, Suffix) ->
- ?line RootDir = ?config(priv_dir,Config),
- ?line Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_delete"++Suffix++".fil"),
- ?line {ok, Fd1} = ?PRIM_FILE:open(Name, [write]),
- ?line ?PRIM_FILE:write(Fd1,"ok.\n"),
- ?line ok = ?PRIM_FILE:close(Fd1),
+ RootDir = proplists:get_value(priv_dir,Config),
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_delete"++Suffix++".fil"),
+ {ok, Fd1} = ?PRIM_FILE:open(Name, [write]),
+ ?PRIM_FILE:write(Fd1,"ok.\n"),
+ ok = ?PRIM_FILE:close(Fd1),
%% Check that the file is readable
- ?line {ok, Fd2} = ?PRIM_FILE:open(Name, [read]),
- ?line ok = ?PRIM_FILE:close(Fd2),
- ?line ok = ?PRIM_FILE_call(delete, Handle, [Name]),
+ {ok, Fd2} = ?PRIM_FILE:open(Name, [read]),
+ ok = ?PRIM_FILE:close(Fd2),
+ ok = ?PRIM_FILE_call(delete, Handle, [Name]),
%% Check that the file is not readable anymore
- ?line {error, _} = ?PRIM_FILE:open(Name, [read]),
+ {error, _} = ?PRIM_FILE:open(Name, [read]),
%% Try deleting a nonexistent file
- ?line {error, enoent} = ?PRIM_FILE_call(delete, Handle, [Name]),
+ {error, enoent} = ?PRIM_FILE_call(delete, Handle, [Name]),
ok.
-rename_a(suite) ->[];
-rename_a(doc) ->[];
rename_a(Config) when is_list(Config) ->
rename(Config, [], "_a").
-rename_b(suite) ->[];
-rename_b(doc) ->[];
rename_b(Config) when is_list(Config) ->
- ?line {ok, Handle} = ?PRIM_FILE:start(),
+ {ok, Handle} = ?PRIM_FILE:start(),
Result = rename(Config, Handle, "_b"),
- ?line ok = ?PRIM_FILE:stop(Handle),
+ ok = ?PRIM_FILE:stop(Handle),
Result.
rename(Config, Handle, Suffix) ->
- ?line RootDir = ?config(priv_dir,Config),
- ?line FileName1 = atom_to_list(?MODULE)++"_rename"++Suffix++".fil",
- ?line FileName2 = atom_to_list(?MODULE)++"_rename"++Suffix++".ful",
- ?line Name1 = filename:join(RootDir, FileName1),
- ?line Name2 = filename:join(RootDir, FileName2),
- ?line {ok,Fd1} = ?PRIM_FILE:open(Name1, [write]),
- ?line ok = ?PRIM_FILE:close(Fd1),
+ RootDir = proplists:get_value(priv_dir,Config),
+ FileName1 = atom_to_list(?MODULE)++"_rename"++Suffix++".fil",
+ FileName2 = atom_to_list(?MODULE)++"_rename"++Suffix++".ful",
+ Name1 = filename:join(RootDir, FileName1),
+ Name2 = filename:join(RootDir, FileName2),
+ {ok,Fd1} = ?PRIM_FILE:open(Name1, [write]),
+ ok = ?PRIM_FILE:close(Fd1),
%% Rename, and check that it really changed name
- ?line ok = ?PRIM_FILE_call(rename, Handle, [Name1, Name2]),
- ?line {error, _} = ?PRIM_FILE:open(Name1, [read]),
- ?line {ok, Fd2} = ?PRIM_FILE:open(Name2, [read]),
- ?line ok = ?PRIM_FILE:close(Fd2),
+ ok = ?PRIM_FILE_call(rename, Handle, [Name1, Name2]),
+ {error, _} = ?PRIM_FILE:open(Name1, [read]),
+ {ok, Fd2} = ?PRIM_FILE:open(Name2, [read]),
+ ok = ?PRIM_FILE:close(Fd2),
%% Try renaming something to itself
- ?line ok = ?PRIM_FILE_call(rename, Handle, [Name2, Name2]),
+ ok = ?PRIM_FILE_call(rename, Handle, [Name2, Name2]),
%% Try renaming something that doesn't exist
- ?line {error, enoent} =
+ {error, enoent} =
?PRIM_FILE_call(rename, Handle, [Name1, Name2]),
%% Try renaming to something else than a string
- ?line {error, badarg} =
+ {error, badarg} =
?PRIM_FILE_call(rename, Handle, [Name1, foobar]),
-
+
%% Move between directories
- ?line DirName1 = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_rename_dir"++Suffix),
- ?line DirName2 = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_second_rename_dir"++Suffix),
- ?line Name1foo = filename:join(DirName1, "foo.fil"),
- ?line Name2foo = filename:join(DirName2, "foo.fil"),
- ?line Name2bar = filename:join(DirName2, "bar.dir"),
- ?line ok = ?PRIM_FILE:make_dir(DirName1),
+ DirName1 = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_rename_dir"++Suffix),
+ DirName2 = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_second_rename_dir"++Suffix),
+ Name1foo = filename:join(DirName1, "foo.fil"),
+ Name2foo = filename:join(DirName2, "foo.fil"),
+ Name2bar = filename:join(DirName2, "bar.dir"),
+ ok = ?PRIM_FILE:make_dir(DirName1),
%% The name has to include the full file name, path is not enough
- ?line expect(
- {error, eexist}, {error, eisdir},
- ?PRIM_FILE_call(rename, Handle, [Name2, DirName1])),
- ?line ok =
+ expect(
+ {error, eexist}, {error, eisdir},
+ ?PRIM_FILE_call(rename, Handle, [Name2, DirName1])),
+ ok =
?PRIM_FILE_call(rename, Handle, [Name2, Name1foo]),
%% Now rename the directory
- ?line ok = ?PRIM_FILE_call(rename, Handle, [DirName1, DirName2]),
+ ok = ?PRIM_FILE_call(rename, Handle, [DirName1, DirName2]),
%% And check that the file is there now
- ?line {ok,Fd3} = ?PRIM_FILE:open(Name2foo, [read]),
- ?line ok = ?PRIM_FILE:close(Fd3),
+ {ok,Fd3} = ?PRIM_FILE:open(Name2foo, [read]),
+ ok = ?PRIM_FILE:close(Fd3),
%% Try some dirty things now: move the directory into itself
- ?line {error, Msg1} =
+ {error, Msg1} =
?PRIM_FILE_call(rename, Handle, [DirName2, Name2bar]),
- ?line io:format("Errmsg1: ~p",[Msg1]),
+ io:format("Errmsg1: ~p",[Msg1]),
%% move dir into a file in itself
- ?line {error, Msg2} =
+ {error, Msg2} =
?PRIM_FILE_call(rename, Handle, [DirName2, Name2foo]),
- ?line io:format("Errmsg2: ~p",[Msg2]),
+ io:format("Errmsg2: ~p",[Msg2]),
ok.
@@ -1509,45 +1420,41 @@ rename(Config, Handle, Suffix) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-e_delete(suite) -> [];
-e_delete(doc) -> [];
e_delete(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line Base = filename:join(RootDir,
- atom_to_list(?MODULE)++"_e_delete"),
- ?line ok = ?PRIM_FILE:make_dir(Base),
+ RootDir = proplists:get_value(priv_dir, Config),
+ Base = filename:join(RootDir,
+ atom_to_list(?MODULE)++"_e_delete"),
+ ok = ?PRIM_FILE:make_dir(Base),
%% Delete a non-existing file.
- ?line {error, enoent} =
+ {error, enoent} =
?PRIM_FILE:delete(filename:join(Base, "non_existing")),
%% Delete a directory.
- ?line {error, eperm} = ?PRIM_FILE:delete(Base),
+ {error, eperm} = ?PRIM_FILE:delete(Base),
%% Use a path-name with a non-directory component.
- ?line Afile = filename:join(Base, "a_file"),
- ?line ok = ?PRIM_FILE:write_file(Afile, "hello\n"),
- ?line {error, E} =
+ Afile = filename:join(Base, "a_file"),
+ ok = ?PRIM_FILE:write_file(Afile, "hello\n"),
+ {error, E} =
expect(
{error, enotdir}, {error, enoent},
?PRIM_FILE:delete(filename:join(Afile, "another_file"))),
- ?line io:format("Result: ~p~n", [E]),
+ io:format("Result: ~p~n", [E]),
%% No permission.
- ?line case os:type() of
- {win32, _} ->
- %% Remove a character device.
- ?line {error, eacces} = ?PRIM_FILE:delete("nul");
- _ ->
- ?line ?PRIM_FILE:write_file_info(
- Base, #file_info {mode=0}),
- ?line {error, eacces} = ?PRIM_FILE:delete(Afile),
- ?line ?PRIM_FILE:write_file_info(
- Base, #file_info {mode=8#600})
- end,
-
- ?line test_server:timetrap_cancel(Dog),
+ case os:type() of
+ {win32, _} ->
+ %% Remove a character device.
+ {error, eacces} = ?PRIM_FILE:delete("nul");
+ _ ->
+ ?PRIM_FILE:write_file_info(
+ Base, #file_info {mode=0}),
+ {error, eacces} = ?PRIM_FILE:delete(Afile),
+ ?PRIM_FILE:write_file_info(
+ Base, #file_info {mode=8#600})
+ end,
+
ok.
%%% FreeBSD gives EEXIST when renaming a file to an empty dir, although the
@@ -1555,66 +1462,63 @@ e_delete(Config) when is_list(Config) ->
%%% (What about FreeBSD? We store our nightly build results on a FreeBSD
%%% file system, that's what.)
-e_rename(suite) -> [];
-e_rename(doc) -> [];
e_rename(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line Base = filename:join(RootDir,
- atom_to_list(?MODULE)++"_e_rename"),
- ?line ok = ?PRIM_FILE:make_dir(Base),
+ RootDir = proplists:get_value(priv_dir, Config),
+ Base = filename:join(RootDir,
+ atom_to_list(?MODULE)++"_e_rename"),
+ ok = ?PRIM_FILE:make_dir(Base),
%% Create an empty directory.
- ?line EmptyDir = filename:join(Base, "empty_dir"),
- ?line ok = ?PRIM_FILE:make_dir(EmptyDir),
+ EmptyDir = filename:join(Base, "empty_dir"),
+ ok = ?PRIM_FILE:make_dir(EmptyDir),
%% Create a non-empty directory.
- ?line NonEmptyDir = filename:join(Base, "non_empty_dir"),
- ?line ok = ?PRIM_FILE:make_dir(NonEmptyDir),
- ?line ok = ?PRIM_FILE:write_file(
- filename:join(NonEmptyDir, "a_file"),
- "hello\n"),
+ NonEmptyDir = filename:join(Base, "non_empty_dir"),
+ ok = ?PRIM_FILE:make_dir(NonEmptyDir),
+ ok = ?PRIM_FILE:write_file(
+ filename:join(NonEmptyDir, "a_file"),
+ "hello\n"),
%% Create another non-empty directory.
- ?line ADirectory = filename:join(Base, "a_directory"),
- ?line ok = ?PRIM_FILE:make_dir(ADirectory),
- ?line ok = ?PRIM_FILE:write_file(
- filename:join(ADirectory, "a_file"),
- "howdy\n\n"),
+ ADirectory = filename:join(Base, "a_directory"),
+ ok = ?PRIM_FILE:make_dir(ADirectory),
+ ok = ?PRIM_FILE:write_file(
+ filename:join(ADirectory, "a_file"),
+ "howdy\n\n"),
%% Create a data file.
- ?line File = filename:join(Base, "just_a_file"),
- ?line ok = ?PRIM_FILE:write_file(File, "anything goes\n\n"),
+ File = filename:join(Base, "just_a_file"),
+ ok = ?PRIM_FILE:write_file(File, "anything goes\n\n"),
%% Move an existing directory to a non-empty directory.
- ?line {error, eexist} =
- ?PRIM_FILE:rename(ADirectory, NonEmptyDir),
+ {error, eexist} =
+ ?PRIM_FILE:rename(ADirectory, NonEmptyDir),
%% Move a root directory.
- ?line {error, einval} = ?PRIM_FILE:rename("/", "arne"),
+ {error, einval} = ?PRIM_FILE:rename("/", "arne"),
%% Move Base into Base/new_name.
- ?line {error, einval} =
- ?PRIM_FILE:rename(Base, filename:join(Base, "new_name")),
+ {error, einval} =
+ ?PRIM_FILE:rename(Base, filename:join(Base, "new_name")),
%% Overwrite a directory with a file.
- ?line expect({error, eexist}, % FreeBSD (?)
- {error, eisdir},
- ?PRIM_FILE:rename(File, EmptyDir)),
- ?line expect({error, eexist}, % FreeBSD (?)
- {error, eisdir},
- ?PRIM_FILE:rename(File, NonEmptyDir)),
+ expect({error, eexist}, % FreeBSD (?)
+ {error, eisdir},
+ ?PRIM_FILE:rename(File, EmptyDir)),
+ expect({error, eexist}, % FreeBSD (?)
+ {error, eisdir},
+ ?PRIM_FILE:rename(File, NonEmptyDir)),
%% Move a non-existing file.
- ?line NonExistingFile = filename:join(
- Base, "non_existing_file"),
- ?line {error, enoent} =
- ?PRIM_FILE:rename(NonExistingFile, NonEmptyDir),
+ NonExistingFile = filename:join(
+ Base, "non_existing_file"),
+ {error, enoent} =
+ ?PRIM_FILE:rename(NonExistingFile, NonEmptyDir),
%% Overwrite a file with a directory.
- ?line expect({error, eexist}, % FreeBSD (?)
- {error, enotdir},
- ?PRIM_FILE:rename(ADirectory, File)),
+ expect({error, eexist}, % FreeBSD (?)
+ {error, enotdir},
+ ?PRIM_FILE:rename(ADirectory, File)),
%% Move a file to another filesystem.
%% XXX - This test case is bogus. We cannot be guaranteed that
@@ -1622,166 +1526,149 @@ e_rename(Config) when is_list(Config) ->
%% different filesystems.
%%
%% XXX - Gross hack!
- ?line Comment =
- case os:type() of
- {win32, _} ->
- %% At least Windows NT can
- %% successfully move a file to
- %% another drive.
- ok;
- {unix, _ } ->
- OtherFs = "/tmp",
- ?line NameOnOtherFs =
- filename:join(OtherFs,
- filename:basename(File)),
- ?line {ok, Com} =
- case ?PRIM_FILE:rename(
- File, NameOnOtherFs) of
- {error, exdev} ->
- %% The file could be in
- %% the same filesystem!
- {ok, ok};
- ok ->
- {ok, {comment,
- "Moving between filesystems "
- "suceeded, files are probably "
- "in the same filesystem!"}};
- {error, eperm} ->
- {ok, {comment, "SBS! You don't "
- "have the permission to do "
- "this test!"}};
- Else ->
- Else
- end,
- Com;
- {ose, _} ->
- %% disabled for now
- ok
- end,
- ?line test_server:timetrap_cancel(Dog),
+ Comment =
+ case os:type() of
+ {win32, _} ->
+ %% At least Windows NT can
+ %% successfully move a file to
+ %% another drive.
+ ok;
+ _ ->
+ OtherFs = "/tmp",
+ NameOnOtherFs =
+ filename:join(OtherFs,
+ filename:basename(File)),
+ {ok, Com} =
+ case ?PRIM_FILE:rename(
+ File, NameOnOtherFs) of
+ {error, exdev} ->
+ %% The file could be in
+ %% the same filesystem!
+ {ok, ok};
+ ok ->
+ {ok, {comment,
+ "Moving between filesystems "
+ "suceeded, files are probably "
+ "in the same filesystem!"}};
+ {error, eperm} ->
+ {ok, {comment, "SBS! You don't "
+ "have the permission to do "
+ "this test!"}};
+ Else ->
+ Else
+ end,
+ Com
+ end,
Comment.
-e_make_dir(suite) -> [];
-e_make_dir(doc) -> [];
e_make_dir(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line Base = filename:join(RootDir,
- atom_to_list(?MODULE)++"_e_make_dir"),
- ?line ok = ?PRIM_FILE:make_dir(Base),
+ RootDir = proplists:get_value(priv_dir, Config),
+ Base = filename:join(RootDir,
+ atom_to_list(?MODULE)++"_e_make_dir"),
+ ok = ?PRIM_FILE:make_dir(Base),
%% A component of the path does not exist.
- ?line {error, enoent} =
+ {error, enoent} =
?PRIM_FILE:make_dir(filename:join([Base, "a", "b"])),
%% Use a path-name with a non-directory component.
- ?line Afile = filename:join(Base, "a_directory"),
- ?line ok = ?PRIM_FILE:write_file(Afile, "hello\n"),
- ?line case ?PRIM_FILE:make_dir(
- filename:join(Afile, "another_directory")) of
- {error, enotdir} -> io:format("Result: enotdir");
- {error, enoent} -> io:format("Result: enoent")
- end,
+ Afile = filename:join(Base, "a_directory"),
+ ok = ?PRIM_FILE:write_file(Afile, "hello\n"),
+ case ?PRIM_FILE:make_dir(
+ filename:join(Afile, "another_directory")) of
+ {error, enotdir} -> io:format("Result: enotdir");
+ {error, enoent} -> io:format("Result: enoent")
+ end,
%% No permission (on Unix only).
case os:type() of
{win32, _} ->
ok;
_ ->
- ?line ?PRIM_FILE:write_file_info(Base, #file_info {mode=0}),
- ?line {error, eacces} =
+ ?PRIM_FILE:write_file_info(Base, #file_info {mode=0}),
+ {error, eacces} =
?PRIM_FILE:make_dir(filename:join(Base, "xxxx")),
- ?line
- ?PRIM_FILE:write_file_info(Base, #file_info {mode=8#600})
+ ?PRIM_FILE:write_file_info(Base, #file_info {mode=8#600})
end,
- ?line test_server:timetrap_cancel(Dog),
ok.
-e_del_dir(suite) -> [];
-e_del_dir(doc) -> [];
e_del_dir(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line Base = filename:join(RootDir,
- atom_to_list(?MODULE)++"_e_del_dir"),
- ?line io:format("Base: ~p", [Base]),
- ?line ok = ?PRIM_FILE:make_dir(Base),
+ RootDir = proplists:get_value(priv_dir, Config),
+ Base = filename:join(RootDir,
+ atom_to_list(?MODULE)++"_e_del_dir"),
+ io:format("Base: ~p", [Base]),
+ ok = ?PRIM_FILE:make_dir(Base),
%% Delete a non-existent directory.
- ?line {error, enoent} =
+ {error, enoent} =
?PRIM_FILE:del_dir(filename:join(Base, "non_existing")),
%% Use a path-name with a non-directory component.
- ?line Afile = filename:join(Base, "a_directory"),
- ?line ok = ?PRIM_FILE:write_file(Afile, "hello\n"),
- ?line {error, E1} =
+ Afile = filename:join(Base, "a_directory"),
+ ok = ?PRIM_FILE:write_file(Afile, "hello\n"),
+ {error, E1} =
expect({error, enotdir}, {error, enoent},
?PRIM_FILE:del_dir(
filename:join(Afile, "another_directory"))),
- ?line io:format("Result: ~p", [E1]),
+ io:format("Result: ~p", [E1]),
%% Delete a non-empty directory.
%% Delete a non-empty directory.
- ?line {error, E2} =
+ {error, E2} =
expect({error, enotempty}, {error, eexist}, {error, eacces},
?PRIM_FILE:del_dir(Base)),
- ?line io:format("Result: ~p", [E2]),
+ io:format("Result: ~p", [E2]),
%% Remove the current directory.
- ?line {error, E3} =
+ {error, E3} =
expect({error, einval},
{error, eperm}, % Linux and DUX
{error, eacces},
{error, ebusy},
?PRIM_FILE:del_dir(".")),
- ?line io:format("Result: ~p", [E3]),
+ io:format("Result: ~p", [E3]),
%% No permission.
case os:type() of
{win32, _} ->
ok;
_ ->
- ?line ADirectory = filename:join(Base, "no_perm"),
- ?line ok = ?PRIM_FILE:make_dir(ADirectory),
- ?line ?PRIM_FILE:write_file_info(Base, #file_info {mode=0}),
- ?line {error, eacces} = ?PRIM_FILE:del_dir(ADirectory),
- ?line ?PRIM_FILE:write_file_info(
- Base, #file_info {mode=8#600})
+ ADirectory = filename:join(Base, "no_perm"),
+ ok = ?PRIM_FILE:make_dir(ADirectory),
+ ?PRIM_FILE:write_file_info(Base, #file_info {mode=0}),
+ {error, eacces} = ?PRIM_FILE:del_dir(ADirectory),
+ ?PRIM_FILE:write_file_info(
+ Base, #file_info {mode=8#600})
end,
- ?line test_server:timetrap_cancel(Dog),
ok.
%% Trying reading and positioning from a compressed file.
-read_compressed(suite) -> [];
-read_compressed(doc) -> [];
read_compressed(Config) when is_list(Config) ->
- ?line Data = ?config(data_dir, Config),
- ?line Real = filename:join(Data, "realmen.html.gz"),
- ?line {ok, Fd} = ?PRIM_FILE:open(Real, [read, compressed]),
- ?line try_read_file(Fd).
+ Data = proplists:get_value(data_dir, Config),
+ Real = filename:join(Data, "realmen.html.gz"),
+ {ok, Fd} = ?PRIM_FILE:open(Real, [read, compressed]),
+ try_read_file(Fd).
%% Trying reading and positioning from an uncompressed file,
%% but with the compressed flag given.
-read_not_really_compressed(suite) -> [];
-read_not_really_compressed(doc) -> [];
read_not_really_compressed(Config) when is_list(Config) ->
- ?line Data = ?config(data_dir, Config),
- ?line Priv = ?config(priv_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
+ Priv = proplists:get_value(priv_dir, Config),
%% The file realmen.html might have got CRs added (by WinZip).
%% Remove them, or the file positions will not be correct.
- ?line Real = filename:join(Data, "realmen.html"),
- ?line RealPriv = filename:join(Priv,
- atom_to_list(?MODULE)++"_realmen.html"),
- ?line {ok, RealDataBin} = ?PRIM_FILE:read_file(Real),
- ?line RealData = remove_crs(binary_to_list(RealDataBin), []),
- ?line ok = ?PRIM_FILE:write_file(RealPriv, RealData),
- ?line {ok, Fd} = ?PRIM_FILE:open(RealPriv, [read, compressed]),
- ?line try_read_file(Fd).
+ Real = filename:join(Data, "realmen.html"),
+ RealPriv = filename:join(Priv,
+ atom_to_list(?MODULE)++"_realmen.html"),
+ {ok, RealDataBin} = ?PRIM_FILE:read_file(Real),
+ RealData = remove_crs(binary_to_list(RealDataBin), []),
+ ok = ?PRIM_FILE:write_file(RealPriv, RealData),
+ {ok, Fd} = ?PRIM_FILE:open(RealPriv, [read, compressed]),
+ try_read_file(Fd).
remove_crs([$\r|Rest], Result) ->
remove_crs(Rest, Result);
@@ -1791,72 +1678,66 @@ remove_crs([], Result) ->
lists:reverse(Result).
try_read_file(Fd) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
-
%% Seek to the current position (nothing should happen).
- ?line {ok, 0} = ?PRIM_FILE:position(Fd, 0),
- ?line {ok, 0} = ?PRIM_FILE:position(Fd, {cur, 0}),
+ {ok, 0} = ?PRIM_FILE:position(Fd, 0),
+ {ok, 0} = ?PRIM_FILE:position(Fd, {cur, 0}),
%% Read a few lines from a compressed file.
- ?line ShouldBe = "<TITLE>Real Programmers Don't Use PASCAL</TITLE>\n",
- ?line {ok, ShouldBe} = ?PRIM_FILE:read(Fd, length(ShouldBe)),
+ ShouldBe = "<TITLE>Real Programmers Don't Use PASCAL</TITLE>\n",
+ {ok, ShouldBe} = ?PRIM_FILE:read(Fd, length(ShouldBe)),
%% Now seek forward.
- ?line {ok, 381} = ?PRIM_FILE:position(Fd, 381),
- ?line Back = "Back in the good old days -- the \"Golden Era\" " ++
+ {ok, 381} = ?PRIM_FILE:position(Fd, 381),
+ Back = "Back in the good old days -- the \"Golden Era\" " ++
"of computers, it was\n",
- ?line {ok, Back} = ?PRIM_FILE:read(Fd, length(Back)),
+ {ok, Back} = ?PRIM_FILE:read(Fd, length(Back)),
%% Try to search forward relative to the current position.
- ?line {ok, CurPos} = ?PRIM_FILE:position(Fd, {cur, 0}),
- ?line RealPos = 4273,
- ?line {ok, RealPos} = ?PRIM_FILE:position(Fd, {cur, RealPos-CurPos}),
- ?line RealProg = "<LI> Real Programmers aren't afraid to use GOTOs.\n",
- ?line {ok, RealProg} = ?PRIM_FILE:read(Fd, length(RealProg)),
+ {ok, CurPos} = ?PRIM_FILE:position(Fd, {cur, 0}),
+ RealPos = 4273,
+ {ok, RealPos} = ?PRIM_FILE:position(Fd, {cur, RealPos-CurPos}),
+ RealProg = "<LI> Real Programmers aren't afraid to use GOTOs.\n",
+ {ok, RealProg} = ?PRIM_FILE:read(Fd, length(RealProg)),
%% Seek backward.
- ?line AfterTitle = length("<TITLE>"),
- ?line {ok, AfterTitle} = ?PRIM_FILE:position(Fd, AfterTitle),
- ?line Title = "Real Programmers Don't Use PASCAL</TITLE>\n",
- ?line {ok, Title} = ?PRIM_FILE:read(Fd, length(Title)),
+ AfterTitle = length("<TITLE>"),
+ {ok, AfterTitle} = ?PRIM_FILE:position(Fd, AfterTitle),
+ Title = "Real Programmers Don't Use PASCAL</TITLE>\n",
+ {ok, Title} = ?PRIM_FILE:read(Fd, length(Title)),
%% Done.
- ?line ?PRIM_FILE:close(Fd),
- ?line test_server:timetrap_cancel(Dog),
+ ?PRIM_FILE:close(Fd),
ok.
-write_compressed(suite) -> [];
-write_compressed(doc) -> [];
write_compressed(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Priv = ?config(priv_dir, Config),
- ?line MyFile = filename:join(Priv,
- atom_to_list(?MODULE)++"_test.gz"),
+ Priv = proplists:get_value(priv_dir, Config),
+ MyFile = filename:join(Priv,
+ atom_to_list(?MODULE)++"_test.gz"),
%% Write a file.
- ?line {ok, Fd} = ?PRIM_FILE:open(MyFile, [write, compressed]),
- ?line {ok, 0} = ?PRIM_FILE:position(Fd, 0),
- ?line Prefix = "hello\n",
- ?line End = "end\n",
- ?line ok = ?PRIM_FILE:write(Fd, Prefix),
- ?line {ok, 143} = ?PRIM_FILE:position(Fd, 143),
- ?line ok = ?PRIM_FILE:write(Fd, End),
- ?line ok = ?PRIM_FILE:close(Fd),
+ {ok, Fd} = ?PRIM_FILE:open(MyFile, [write, compressed]),
+ {ok, 0} = ?PRIM_FILE:position(Fd, 0),
+ Prefix = "hello\n",
+ End = "end\n",
+ ok = ?PRIM_FILE:write(Fd, Prefix),
+ {ok, 143} = ?PRIM_FILE:position(Fd, 143),
+ ok = ?PRIM_FILE:write(Fd, End),
+ ok = ?PRIM_FILE:close(Fd),
%% Read the file and verify the contents.
- ?line {ok, Fd1} = ?PRIM_FILE:open(MyFile, [read, compressed]),
- ?line {ok, Prefix} = ?PRIM_FILE:read(Fd1, length(Prefix)),
- ?line Second = lists:duplicate(143-length(Prefix), 0) ++ End,
- ?line {ok, Second} = ?PRIM_FILE:read(Fd1, length(Second)),
- ?line ok = ?PRIM_FILE:close(Fd1),
+ {ok, Fd1} = ?PRIM_FILE:open(MyFile, [read, compressed]),
+ {ok, Prefix} = ?PRIM_FILE:read(Fd1, length(Prefix)),
+ Second = lists:duplicate(143-length(Prefix), 0) ++ End,
+ {ok, Second} = ?PRIM_FILE:read(Fd1, length(Second)),
+ ok = ?PRIM_FILE:close(Fd1),
%% Ensure that the file is compressed.
@@ -1865,71 +1746,61 @@ write_compressed(Config) when is_list(Config) ->
{ok, #file_info{size=Size}} when Size < TotalSize ->
ok;
{ok, #file_info{size=Size}} when Size == TotalSize ->
- test_server:fail(file_not_compressed)
+ ct:fail(file_not_compressed)
end,
%% Write again to ensure that the file is truncated.
- ?line {ok, Fd2} = ?PRIM_FILE:open(MyFile, [write, compressed]),
- ?line NewString = "aaaaaaaaaaa",
- ?line ok = ?PRIM_FILE:write(Fd2, NewString),
- ?line ok = ?PRIM_FILE:close(Fd2),
- ?line {ok, Fd3} = ?PRIM_FILE:open(MyFile, [read, compressed]),
- ?line {ok, NewString} = ?PRIM_FILE:read(Fd3, 1024),
- ?line ok = ?PRIM_FILE:close(Fd3),
+ {ok, Fd2} = ?PRIM_FILE:open(MyFile, [write, compressed]),
+ NewString = "aaaaaaaaaaa",
+ ok = ?PRIM_FILE:write(Fd2, NewString),
+ ok = ?PRIM_FILE:close(Fd2),
+ {ok, Fd3} = ?PRIM_FILE:open(MyFile, [read, compressed]),
+ {ok, NewString} = ?PRIM_FILE:read(Fd3, 1024),
+ ok = ?PRIM_FILE:close(Fd3),
- %% Done.
-
- ?line test_server:timetrap_cancel(Dog),
ok.
-compress_errors(suite) -> [];
-compress_errors(doc) -> [];
compress_errors(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line Data = ?config(data_dir, Config),
- ?line {error, enoent} = ?PRIM_FILE:open("non_existing__",
+ Data = proplists:get_value(data_dir, Config),
+ {error, enoent} = ?PRIM_FILE:open("non_existing__",
[compressed, read]),
- ?line {error, einval} = ?PRIM_FILE:open("non_existing__",
+ {error, einval} = ?PRIM_FILE:open("non_existing__",
[compressed, read, write]),
%% Read a corrupted .gz file.
- ?line Corrupted = filename:join(Data, "corrupted.gz"),
- ?line {ok, Fd} = ?PRIM_FILE:open(Corrupted, [read, compressed]),
- ?line {error, eio} = ?PRIM_FILE:read(Fd, 100),
- ?line ?PRIM_FILE:close(Fd),
+ Corrupted = filename:join(Data, "corrupted.gz"),
+ {ok, Fd} = ?PRIM_FILE:open(Corrupted, [read, compressed]),
+ {error, eio} = ?PRIM_FILE:read(Fd, 100),
+ ?PRIM_FILE:close(Fd),
- ?line test_server:timetrap_cancel(Dog),
ok.
-make_link_a(doc) -> "Test creating a hard link.";
-make_link_a(suite) -> [];
+%% Test creating a hard link.
make_link_a(Config) when is_list(Config) ->
make_link(Config, [], "_a").
-make_link_b(doc) -> "Test creating a hard link.";
-make_link_b(suite) -> [];
+%% Test creating a hard link.
make_link_b(Config) when is_list(Config) ->
- ?line {ok, Handle} = ?PRIM_FILE:start(),
+ {ok, Handle} = ?PRIM_FILE:start(),
Result = make_link(Config, Handle, "_b"),
- ?line ok = ?PRIM_FILE:stop(Handle),
+ ok = ?PRIM_FILE:stop(Handle),
Result.
make_link(Config, Handle, Suffix) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_make_link"++Suffix),
- ?line ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
-
- ?line Name = filename:join(NewDir, "a_file"),
- ?line ok = ?PRIM_FILE:write_file(Name, "some contents\n"),
-
- ?line Alias = filename:join(NewDir, "an_alias"),
- ?line Result =
+ RootDir = proplists:get_value(priv_dir, Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_make_link"++Suffix),
+ ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
+
+ Name = filename:join(NewDir, "a_file"),
+ ok = ?PRIM_FILE:write_file(Name, "some contents\n"),
+
+ Alias = filename:join(NewDir, "an_alias"),
+ Result =
case ?PRIM_FILE_call(make_link, Handle, [Name, Alias]) of
{error, enotsup} ->
{skipped, "Links not supported on this platform"};
@@ -1939,58 +1810,48 @@ make_link(Config, Handle, Suffix) ->
%% which should in behave exactly as
%% ?PRIM_FILE:read_file_info/1
%% since they are not used on symbolic links.
-
- ?line {ok, Info} =
+
+ {ok, Info} =
?PRIM_FILE_call(read_link_info, Handle, [Name]),
- ?line {ok, Info} =
+ {ok, Info} =
?PRIM_FILE_call(read_link_info, Handle, [Alias]),
- ?line #file_info{links = 2, type = regular} = Info,
- ?line {error, eexist} =
+ #file_info{links = 2, type = regular} = Info,
+ {error, eexist} =
?PRIM_FILE_call(make_link, Handle, [Name, Alias]),
ok
end,
-
- ?line test_server:timetrap_cancel(Dog),
+
Result.
-read_link_info_for_non_link(doc) ->
- "Test that reading link info for an ordinary file or directory works "
- "(on all platforms).";
-read_link_info_for_non_link(suite) -> [];
+%% Test that reading link info for an ordinary file or directory works
+%% (on all platforms).
read_link_info_for_non_link(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
-
- ?line {ok, #file_info{type=directory}} = ?PRIM_FILE:read_link_info("."),
-
- ?line test_server:timetrap_cancel(Dog),
+ {ok, #file_info{type=directory}} = ?PRIM_FILE:read_link_info("."),
ok.
-
-symlinks_a(doc) -> "Test operations on symbolic links (for Unix).";
-symlinks_a(suite) -> [];
+
+%% Test operations on symbolic links (for Unix).
symlinks_a(Config) when is_list(Config) ->
symlinks(Config, [], "_a").
-symlinks_b(doc) -> "Test operations on symbolic links (for Unix).";
-symlinks_b(suite) -> [];
+%% Test operations on symbolic links (for Unix).
symlinks_b(Config) when is_list(Config) ->
- ?line {ok, Handle} = ?PRIM_FILE:start(),
+ {ok, Handle} = ?PRIM_FILE:start(),
Result = symlinks(Config, Handle, "_b"),
- ?line ok = ?PRIM_FILE:stop(Handle),
+ ok = ?PRIM_FILE:stop(Handle),
Result.
symlinks(Config, Handle, Suffix) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_make_symlink"++Suffix),
- ?line ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
-
- ?line Name = filename:join(NewDir, "a_plain_file"),
- ?line ok = ?PRIM_FILE:write_file(Name, "some stupid content\n"),
-
- ?line Alias = filename:join(NewDir, "a_symlink_alias"),
- ?line Result =
+ RootDir = proplists:get_value(priv_dir, Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_make_symlink"++Suffix),
+ ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
+
+ Name = filename:join(NewDir, "a_plain_file"),
+ ok = ?PRIM_FILE:write_file(Name, "some stupid content\n"),
+
+ Alias = filename:join(NewDir, "a_symlink_alias"),
+ Result =
case ?PRIM_FILE_call(make_symlink, Handle, [Name, Alias]) of
{error, enotsup} ->
{skipped, "Links not supported on this platform"};
@@ -1998,18 +1859,18 @@ symlinks(Config, Handle, Suffix) ->
{win32,_} = os:type(),
{skipped, "Windows user not privileged to create links"};
ok ->
- ?line {ok, Info1} =
+ {ok, Info1} =
?PRIM_FILE_call(read_file_info, Handle, [Name]),
- ?line {ok, Info1} =
+ {ok, Info1} =
?PRIM_FILE_call(read_file_info, Handle, [Alias]),
- ?line {ok, Info1} =
+ {ok, Info1} =
?PRIM_FILE_call(read_link_info, Handle, [Name]),
- ?line #file_info{links = 1, type = regular} = Info1,
-
- ?line {ok, Info2} =
+ #file_info{links = 1, type = regular} = Info1,
+
+ {ok, Info2} =
?PRIM_FILE_call(read_link_info, Handle, [Alias]),
- ?line #file_info{links=1, type=symlink} = Info2,
- ?line {ok, Name} =
+ #file_info{links=1, type=symlink} = Info2,
+ {ok, Name} =
?PRIM_FILE_call(read_link, Handle, [Alias]),
{ok, Name} =
?PRIM_FILE_call(read_link_all, Handle, [Alias]),
@@ -2017,45 +1878,39 @@ symlinks(Config, Handle, Suffix) ->
rm_rf(?PRIM_FILE,NewDir),
ok
end,
-
- ?line test_server:timetrap_cancel(Dog),
+
Result.
%% Creates as many files as possible during a certain time,
%% periodically calls list_dir/2 to check if it works,
%% then deletes all files.
-list_dir_limit(doc) ->
- "Tests if large directories can be read";
-list_dir_limit(suite) ->
- [];
+%% Tests if large directories can be read.
list_dir_limit(Config) when is_list(Config) ->
- ?line MaxTime = 120,
- ?line MaxNumber = 20000,
- ?line Dog = test_server:timetrap(
- test_server:seconds(2*MaxTime + MaxTime)),
- ?line RootDir = ?config(priv_dir, Config),
- ?line NewDir = filename:join(RootDir,
- atom_to_list(?MODULE)++"_list_dir_limit"),
- ?line {ok, Handle1} = ?PRIM_FILE:start(),
- ?line ok = ?PRIM_FILE_call(make_dir, Handle1, [NewDir]),
+ MaxTime = 120,
+ MaxNumber = 20000,
+ ct:timetrap({seconds,2*MaxTime + MaxTime}),
+ RootDir = proplists:get_value(priv_dir, Config),
+ NewDir = filename:join(RootDir,
+ atom_to_list(?MODULE)++"_list_dir_limit"),
+ {ok, Handle1} = ?PRIM_FILE:start(),
+ ok = ?PRIM_FILE_call(make_dir, Handle1, [NewDir]),
Ref = erlang:start_timer(MaxTime*1000, self(), []),
- ?line Result = list_dir_limit_loop(NewDir, Handle1, Ref, MaxNumber, 0),
- ?line Time = case erlang:cancel_timer(Ref) of
- false -> MaxTime;
- T -> MaxTime - (T div 1000)
- end,
- ?line Number = case Result of
- {ok, N} -> N;
- {error, _Reason, N} -> N;
- _ -> 0
- end,
- ?line {ok, Handle2} = ?PRIM_FILE:start(),
- ?line list_dir_limit_cleanup(NewDir, Handle2, Number, 0),
- ?line ok = ?PRIM_FILE:stop(Handle1),
- ?line ok = ?PRIM_FILE:stop(Handle2),
- ?line {ok, Number} = Result,
- ?line test_server:timetrap_cancel(Dog),
+ Result = list_dir_limit_loop(NewDir, Handle1, Ref, MaxNumber, 0),
+ Time = case erlang:cancel_timer(Ref) of
+ false -> MaxTime;
+ T -> MaxTime - (T div 1000)
+ end,
+ Number = case Result of
+ {ok, N} -> N;
+ {error, _Reason, N} -> N;
+ _ -> 0
+ end,
+ {ok, Handle2} = ?PRIM_FILE:start(),
+ list_dir_limit_cleanup(NewDir, Handle2, Number, 0),
+ ok = ?PRIM_FILE:stop(Handle1),
+ ok = ?PRIM_FILE:stop(Handle2),
+ {ok, Number} = Result,
{comment,
"Created " ++ integer_to_list(Number) ++ " files in "
++ integer_to_list(Time) ++ " seconds."}.
@@ -2124,7 +1979,7 @@ list_dir_limit_cleanup(Dir, Handle, N, Cnt) ->
%%%
list_dir_error(Config) ->
- Priv = ?config(priv_dir, Config),
+ Priv = proplists:get_value(priv_dir, Config),
NonExisting = filename:join(Priv, "non-existing-dir"),
{error,enoent} = prim_file:list_dir(NonExisting),
ok.
@@ -2134,7 +1989,7 @@ list_dir_error(Config) ->
%%%
list_dir(Config) ->
- RootDir = ?config(priv_dir, Config),
+ RootDir = proplists:get_value(priv_dir, Config),
TestDir = filename:join(RootDir, ?MODULE_STRING++"_list_dir"),
?PRIM_FILE:make_dir(TestDir),
list_dir_1(TestDir, 42, []).
@@ -2165,7 +2020,7 @@ run_large_file_test(Config, Run, Name) ->
{{unix,sunos},OsVersion} when OsVersion < {5,5,1} ->
{skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"};
{{unix,_},_} ->
- N = unix_free(?config(priv_dir, Config)),
+ N = unix_free(proplists:get_value(priv_dir, Config)),
io:format("Free disk: ~w KByte~n", [N]),
if N < 5 bsl 20 ->
%% Less than 5 GByte free
@@ -2179,9 +2034,9 @@ run_large_file_test(Config, Run, Name) ->
do_run_large_file_test(Config, Run, Name0) ->
- Name = filename:join(?config(priv_dir, Config),
+ Name = filename:join(proplists:get_value(priv_dir, Config),
?MODULE_STRING ++ Name0),
-
+
%% Set up a process that will delete this file.
Tester = self(),
Deleter =
@@ -2194,7 +2049,7 @@ do_run_large_file_test(Config, Run, Name0) ->
end,
prim_file:delete(Name)
end),
-
+
%% Run the test case.
Res = Run(Name),
diff --git a/lib/kernel/test/ram_file_SUITE.erl b/lib/kernel/test/ram_file_SUITE.erl
index 933dc88d21..d90995923a 100644
--- a/lib/kernel/test/ram_file_SUITE.erl
+++ b/lib/kernel/test/ram_file_SUITE.erl
@@ -26,9 +26,10 @@
init_per_testcase/2, end_per_testcase/2]).
-export([open_modes/1, open_old_modes/1, pread_pwrite/1, position/1,
truncate/1, sync/1, get_set_file/1, compress/1, uuencode/1,
- large_file_errors/1, large_file_light/1, large_file_heavy/1]).
+ large_file_errors/1, large_file_light/1,
+ large_file_heavy/0, large_file_heavy/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
-define(FILE_MODULE, file). % Name of module to test
@@ -36,7 +37,9 @@
%%--------------------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[open_modes, open_old_modes, pread_pwrite, position,
@@ -59,37 +62,23 @@ end_per_group(_GroupName, Config) ->
Config.
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Time =
- case Func of
- large_file_heavy ->
- ?t:minutes(5);
- _ ->
- ?t:seconds(10)
- end,
- Dog = ?t:timetrap(Time),
- %% error_logger:info_msg("~p:~p *****~n", [?MODULE, Func]),
- [{watchdog, Dog} | Config].
+init_per_testcase(Func, Config) ->
+ Config.
end_per_testcase(_Func, Config) ->
- %% error_logger:info_msg("~p:~p END *****~n", [?MODULE, Func]),
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
+ Config.
%%--------------------------------------------------------------------------
%% Test suites
-open_modes(suite) ->
- [];
-open_modes(doc) ->
- ["Test that the basic read, write and binary options works for open/2."];
+%% Test that the basic read, write and binary options works for open/2.
open_modes(Config) when is_list(Config) ->
- ?line Str1 = "The quick brown fox ",
- ?line Str2 = "jumps over a lazy dog ",
- ?line Str = Str1 ++ Str2,
- ?line Bin1 = list_to_binary(Str1),
- ?line Bin2 = list_to_binary(Str2),
- ?line Bin = list_to_binary(Str),
+ Str1 = "The quick brown fox ",
+ Str2 = "jumps over a lazy dog ",
+ Str = Str1 ++ Str2,
+ Bin1 = list_to_binary(Str1),
+ Bin2 = list_to_binary(Str2),
+ Bin = list_to_binary(Str),
%%
open_read_write(?FILE_MODULE, Str1, [ram, read, write], Str2),
open_read(?FILE_MODULE, Str, [ram]),
@@ -98,18 +87,15 @@ open_modes(Config) when is_list(Config) ->
%%
ok.
-open_old_modes(suite) ->
- [];
-open_old_modes(doc) ->
- ["Test that the old style read, write and binary options ",
- "works for open/2."];
+%% Test that the old style read, write and binary options
+%% works for open/2.
open_old_modes(Config) when is_list(Config) ->
- ?line Str1 = "The quick brown fox ",
- ?line Str2 = "jumps over a lazy dog ",
- ?line Str = Str1 ++ Str2,
- ?line Bin1 = list_to_binary(Str1),
- ?line Bin2 = list_to_binary(Str2),
- ?line Bin = list_to_binary(Str),
+ Str1 = "The quick brown fox ",
+ Str2 = "jumps over a lazy dog ",
+ Str = Str1 ++ Str2,
+ Bin1 = list_to_binary(Str1),
+ Bin2 = list_to_binary(Str2),
+ Bin = list_to_binary(Str),
%%
open_read_write(?RAM_FILE_MODULE, Str1, read_write, Str2),
open_read(?RAM_FILE_MODULE, Str, read),
@@ -119,57 +105,54 @@ open_old_modes(Config) when is_list(Config) ->
ok.
open_read_write(Module, Data1, Options, Data2) ->
- ?line io:format("~p:open_read_write(~p, ~p, ~p, ~p)~n",
- [?MODULE, Module, Data1, Options, Data2]),
- %%
- ?line Size1 = sizeof(Data1),
- ?line Size2 = sizeof(Data2),
- ?line Data = append(Data1, Data2),
- ?line Size = Size1 + Size2,
- %%
- ?line {ok, Fd} = Module:open(Data1, Options),
- ?line {ok, Data1} = Module:read(Fd, Size1),
- ?line eof = Module:read(Fd, 1),
- ?line {ok, Zero} = Module:read(Fd, 0),
- ?line 0 = sizeof(Zero),
- ?line ok = Module:write(Fd, Data2),
- ?line {ok, 0} = Module:position(Fd, bof),
- ?line {ok, Data} = Module:read(Fd, Size),
- ?line eof = Module:read(Fd, 1),
- ?line {ok, Zero} = Module:read(Fd, 0),
- ?line ok = Module:close(Fd),
- %%
- ?line ok.
+ io:format("~p:open_read_write(~p, ~p, ~p, ~p)~n",
+ [?MODULE, Module, Data1, Options, Data2]),
+ %%
+ Size1 = sizeof(Data1),
+ Size2 = sizeof(Data2),
+ Data = append(Data1, Data2),
+ Size = Size1 + Size2,
+ %%
+ {ok, Fd} = Module:open(Data1, Options),
+ {ok, Data1} = Module:read(Fd, Size1),
+ eof = Module:read(Fd, 1),
+ {ok, Zero} = Module:read(Fd, 0),
+ 0 = sizeof(Zero),
+ ok = Module:write(Fd, Data2),
+ {ok, 0} = Module:position(Fd, bof),
+ {ok, Data} = Module:read(Fd, Size),
+ eof = Module:read(Fd, 1),
+ {ok, Zero} = Module:read(Fd, 0),
+ ok = Module:close(Fd),
+ %%
+ ok.
open_read(Module, Data, Options) ->
- ?line io:format("~p:open_read(~p, ~p, ~p)~n",
- [?MODULE, Module, Data, Options]),
- %%
- ?line Size = sizeof(Data),
- %%
- ?line {ok, Fd} = Module:open(Data, Options),
- ?line {ok, Data} = Module:read(Fd, Size),
- ?line eof = Module:read(Fd, 1),
- ?line {ok, Zero} = Module:read(Fd, 0),
- ?line 0 = sizeof(Zero),
- ?line {error, ebadf} = Module:write(Fd, Data),
- ?line {ok, 0} = Module:position(Fd, bof),
- ?line {ok, Data} = Module:read(Fd, Size),
- ?line eof = Module:read(Fd, 1),
- ?line {ok, Zero} = Module:read(Fd, 0),
- ?line ok = Module:close(Fd),
+ io:format("~p:open_read(~p, ~p, ~p)~n",
+ [?MODULE, Module, Data, Options]),
+ %%
+ Size = sizeof(Data),
+ %%
+ {ok, Fd} = Module:open(Data, Options),
+ {ok, Data} = Module:read(Fd, Size),
+ eof = Module:read(Fd, 1),
+ {ok, Zero} = Module:read(Fd, 0),
+ 0 = sizeof(Zero),
+ {error, ebadf} = Module:write(Fd, Data),
+ {ok, 0} = Module:position(Fd, bof),
+ {ok, Data} = Module:read(Fd, Size),
+ eof = Module:read(Fd, 1),
+ {ok, Zero} = Module:read(Fd, 0),
+ ok = Module:close(Fd),
%%
- ?line ok.
+ ok.
-pread_pwrite(suite) ->
- [];
-pread_pwrite(doc) ->
- ["Test that pread/2,3 and pwrite/2,3 works."];
+%% Test that pread/2,3 and pwrite/2,3 works.
pread_pwrite(Config) when is_list(Config) ->
- ?line Str = "Flygande bäckaziner söka hwila på mjuqa tuvor x",
- ?line Bin = list_to_binary(Str),
+ Str = "Flygande bäckaziner söka hwila på mjuqa tuvor x",
+ Bin = list_to_binary(Str),
%%
pread_pwrite_test(?FILE_MODULE, Str, [ram, read, write]),
pread_pwrite_test(?FILE_MODULE, Bin, [ram, binary, read, write]),
@@ -179,36 +162,33 @@ pread_pwrite(Config) when is_list(Config) ->
ok.
pread_pwrite_test(Module, Data, Options) ->
- ?line io:format("~p:pread_pwrite_test(~p, ~p, ~p)~n",
- [?MODULE, Module, Data, Options]),
- %%
- ?line Size = sizeof(Data),
- %%
- ?line {ok, Fd} = Module:open([], Options),
- ?line ok = Module:pwrite(Fd, 0, Data),
- ?line {ok, Data} = Module:pread(Fd, 0, Size+1),
- ?line eof = Module:pread(Fd, Size+1, 1),
- ?line {ok, Zero} = Module:pread(Fd, Size+1, 0),
- ?line 0 = sizeof(Zero),
- ?line ok = Module:pwrite(Fd, [{0, Data}, {Size+17, Data}]),
- ?line {ok, [Data,
- eof,
- Data,
- Zero]} = Module:pread(Fd, [{Size+17, Size+1},
- {2*Size+17+1, 1},
- {0, Size},
- {2*Size+17+1, 0}]),
- ?line ok = Module:close(Fd),
- %%
- ?line ok.
-
-position(suite) ->
- [];
-position(doc) ->
- ["Test that position/2 works."];
+ io:format("~p:pread_pwrite_test(~p, ~p, ~p)~n",
+ [?MODULE, Module, Data, Options]),
+ %%
+ Size = sizeof(Data),
+ %%
+ {ok, Fd} = Module:open([], Options),
+ ok = Module:pwrite(Fd, 0, Data),
+ {ok, Data} = Module:pread(Fd, 0, Size+1),
+ eof = Module:pread(Fd, Size+1, 1),
+ {ok, Zero} = Module:pread(Fd, Size+1, 0),
+ 0 = sizeof(Zero),
+ ok = Module:pwrite(Fd, [{0, Data}, {Size+17, Data}]),
+ {ok, [Data,
+ eof,
+ Data,
+ Zero]} = Module:pread(Fd, [{Size+17, Size+1},
+ {2*Size+17+1, 1},
+ {0, Size},
+ {2*Size+17+1, 0}]),
+ ok = Module:close(Fd),
+ %%
+ ok.
+
+%% Test that position/2 works.
position(Config) when is_list(Config) ->
- ?line Str = "Att vara eller icke vara, det är frågan. ",
- ?line Bin = list_to_binary(Str),
+ Str = "Att vara eller icke vara, det är frågan. ",
+ Bin = list_to_binary(Str),
%%
position_test(?FILE_MODULE, Str, [ram, read]),
position_test(?FILE_MODULE, Bin, [ram, binary]),
@@ -218,79 +198,76 @@ position(Config) when is_list(Config) ->
ok.
position_test(Module, Data, Options) ->
- ?line io:format("~p:position_test(~p, ~p, ~p)~n",
- [?MODULE, Module, Data, Options]),
- %%
- ?line Size = sizeof(Data),
- ?line Size_7 = Size+7,
- %%
- ?line Slice_0_2 = slice(Data, 0, 2),
- ?line Slice_0_3 = slice(Data, 0, 3),
- ?line Slice_2_5 = slice(Data, 2, 5),
- ?line Slice_3_4 = slice(Data, 3, 4),
- ?line Slice_5 = slice(Data, 5, Size),
- %%
- ?line {ok, Fd} = Module:open(Data, Options),
- %%
- ?line io:format("CUR positions"),
- ?line {ok, Slice_0_2} = Module:read(Fd, 2),
- ?line {ok, 2} = Module:position(Fd, cur),
- ?line {ok, Slice_2_5} = Module:read(Fd, 5),
- ?line {ok, 3} = Module:position(Fd, {cur, -4}),
- ?line {ok, Slice_3_4} = Module:read(Fd, 4),
- ?line {ok, 0} = Module:position(Fd, {cur, -7}),
- ?line {ok, Slice_0_3} = Module:read(Fd, 3),
- ?line {ok, 0} = Module:position(Fd, {cur, -3}),
- ?line {error, einval} = Module:position(Fd, {cur, -1}),
- ?line {ok, 0} = Module:position(Fd, 0),
- ?line {ok, 2} = Module:position(Fd, {cur, 2}),
- ?line {ok, Slice_2_5} = Module:read(Fd, 5),
- ?line {ok, Size_7} = Module:position(Fd, {cur, Size}),
- ?line {ok, Zero} = Module:read(Fd, 0),
- ?line 0 = sizeof(Zero),
- ?line eof = Module:read(Fd, 1),
- %%
- ?line io:format("Absolute and BOF positions"),
- ?line {ok, Size} = Module:position(Fd, Size),
- ?line eof = Module:read(Fd, 1),
- ?line {ok, 5} = Module:position(Fd, 5),
- ?line {ok, Slice_5} = Module:read(Fd, Size),
- ?line {ok, 2} = Module:position(Fd, {bof, 2}),
- ?line {ok, Slice_2_5} = Module:read(Fd, 5),
- ?line {ok, 3} = Module:position(Fd, 3),
- ?line {ok, Slice_3_4} = Module:read(Fd, 4),
- ?line {ok, 0} = Module:position(Fd, bof),
- ?line {ok, Slice_0_2} = Module:read(Fd, 2),
- ?line {ok, Size_7} = Module:position(Fd, {bof, Size_7}),
- ?line {ok, Zero} = Module:read(Fd, 0),
- %%
- ?line io:format("EOF positions"),
- ?line {ok, Size} = Module:position(Fd, eof),
- ?line eof = Module:read(Fd, 1),
- ?line {ok, 5} = Module:position(Fd, {eof, -Size+5}),
- ?line {ok, Slice_5} = Module:read(Fd, Size),
- ?line {ok, 2} = Module:position(Fd, {eof, -Size+2}),
- ?line {ok, Slice_2_5} = Module:read(Fd, 5),
- ?line {ok, 3} = Module:position(Fd, {eof, -Size+3}),
- ?line {ok, Slice_3_4} = Module:read(Fd, 4),
- ?line {ok, 0} = Module:position(Fd, {eof, -Size}),
- ?line {ok, Slice_0_2} = Module:read(Fd, 2),
- ?line {ok, Size_7} = Module:position(Fd, {eof, 7}),
- ?line {ok, Zero} = Module:read(Fd, 0),
- ?line eof = Module:read(Fd, 1),
- %%
- ?line ok.
-
-
-
-truncate(suite) ->
- [];
-truncate(doc) ->
- ["Test that truncate/1 works."];
+ io:format("~p:position_test(~p, ~p, ~p)~n",
+ [?MODULE, Module, Data, Options]),
+ %%
+ Size = sizeof(Data),
+ Size_7 = Size+7,
+ %%
+ Slice_0_2 = slice(Data, 0, 2),
+ Slice_0_3 = slice(Data, 0, 3),
+ Slice_2_5 = slice(Data, 2, 5),
+ Slice_3_4 = slice(Data, 3, 4),
+ Slice_5 = slice(Data, 5, Size),
+ %%
+ {ok, Fd} = Module:open(Data, Options),
+ %%
+ io:format("CUR positions"),
+ {ok, Slice_0_2} = Module:read(Fd, 2),
+ {ok, 2} = Module:position(Fd, cur),
+ {ok, Slice_2_5} = Module:read(Fd, 5),
+ {ok, 3} = Module:position(Fd, {cur, -4}),
+ {ok, Slice_3_4} = Module:read(Fd, 4),
+ {ok, 0} = Module:position(Fd, {cur, -7}),
+ {ok, Slice_0_3} = Module:read(Fd, 3),
+ {ok, 0} = Module:position(Fd, {cur, -3}),
+ {error, einval} = Module:position(Fd, {cur, -1}),
+ {ok, 0} = Module:position(Fd, 0),
+ {ok, 2} = Module:position(Fd, {cur, 2}),
+ {ok, Slice_2_5} = Module:read(Fd, 5),
+ {ok, Size_7} = Module:position(Fd, {cur, Size}),
+ {ok, Zero} = Module:read(Fd, 0),
+ 0 = sizeof(Zero),
+ eof = Module:read(Fd, 1),
+ %%
+ io:format("Absolute and BOF positions"),
+ {ok, Size} = Module:position(Fd, Size),
+ eof = Module:read(Fd, 1),
+ {ok, 5} = Module:position(Fd, 5),
+ {ok, Slice_5} = Module:read(Fd, Size),
+ {ok, 2} = Module:position(Fd, {bof, 2}),
+ {ok, Slice_2_5} = Module:read(Fd, 5),
+ {ok, 3} = Module:position(Fd, 3),
+ {ok, Slice_3_4} = Module:read(Fd, 4),
+ {ok, 0} = Module:position(Fd, bof),
+ {ok, Slice_0_2} = Module:read(Fd, 2),
+ {ok, Size_7} = Module:position(Fd, {bof, Size_7}),
+ {ok, Zero} = Module:read(Fd, 0),
+ %%
+ io:format("EOF positions"),
+ {ok, Size} = Module:position(Fd, eof),
+ eof = Module:read(Fd, 1),
+ {ok, 5} = Module:position(Fd, {eof, -Size+5}),
+ {ok, Slice_5} = Module:read(Fd, Size),
+ {ok, 2} = Module:position(Fd, {eof, -Size+2}),
+ {ok, Slice_2_5} = Module:read(Fd, 5),
+ {ok, 3} = Module:position(Fd, {eof, -Size+3}),
+ {ok, Slice_3_4} = Module:read(Fd, 4),
+ {ok, 0} = Module:position(Fd, {eof, -Size}),
+ {ok, Slice_0_2} = Module:read(Fd, 2),
+ {ok, Size_7} = Module:position(Fd, {eof, 7}),
+ {ok, Zero} = Module:read(Fd, 0),
+ eof = Module:read(Fd, 1),
+ %%
+ ok.
+
+
+
+%% Test that truncate/1 works.
truncate(Config) when is_list(Config) ->
- ?line Str = "Mån ädlare att lida och fördraga "
+ Str = "Mån ädlare att lida och fördraga "
++ "ett bittert ödes stygn av pilar, ",
- ?line Bin = list_to_binary(Str),
+ Bin = list_to_binary(Str),
%%
ok = truncate_test(?FILE_MODULE, Str, [ram, read, write]),
ok = truncate_test(?FILE_MODULE, Bin, [ram, binary, read, write]),
@@ -305,35 +282,32 @@ truncate(Config) when is_list(Config) ->
ok.
truncate_test(Module, Data, Options) ->
- ?line io:format("~p:truncate_test(~p, ~p, ~p)~n",
- [?MODULE, Module, Data, Options]),
- %%
- ?line Size = sizeof(Data),
- ?line Size1 = Size-2,
- ?line Data1 = slice(Data, 0, Size1),
- %%
- ?line {ok, Fd} = Module:open(Data, Options),
- ?line {ok, Size1} = Module:position(Fd, Size1),
- ?line case Module:truncate(Fd) of
- ok ->
- ?line {ok, 0} = Module:position(Fd, 0),
- ?line {ok, Data1} = Module:read(Fd, Size),
- ?line ok = Module:close(Fd),
- ?line ok;
- Error ->
- ?line ok = Module:close(Fd),
- ?line Error
- end.
-
-
-
-sync(suite) ->
- [];
-sync(doc) ->
- ["Test that sync/1 at least does not crash."];
+ io:format("~p:truncate_test(~p, ~p, ~p)~n",
+ [?MODULE, Module, Data, Options]),
+ %%
+ Size = sizeof(Data),
+ Size1 = Size-2,
+ Data1 = slice(Data, 0, Size1),
+ %%
+ {ok, Fd} = Module:open(Data, Options),
+ {ok, Size1} = Module:position(Fd, Size1),
+ case Module:truncate(Fd) of
+ ok ->
+ {ok, 0} = Module:position(Fd, 0),
+ {ok, Data1} = Module:read(Fd, Size),
+ ok = Module:close(Fd),
+ ok;
+ Error ->
+ ok = Module:close(Fd),
+ Error
+ end.
+
+
+
+%% Test that sync/1 at least does not crash.
sync(Config) when is_list(Config) ->
- ?line Str = "än att ta till vapen mot ett hav av kval. ",
- ?line Bin = list_to_binary(Str),
+ Str = "än att ta till vapen mot ett hav av kval. ",
+ Bin = list_to_binary(Str),
%%
sync_test(?FILE_MODULE, Str, [ram, read, write]),
sync_test(?FILE_MODULE, Bin, [ram, binary, read, write]),
@@ -348,28 +322,25 @@ sync(Config) when is_list(Config) ->
ok.
sync_test(Module, Data, Options) ->
- ?line io:format("~p:sync_test(~p, ~p, ~p)~n",
- [?MODULE, Module, Data, Options]),
+ io:format("~p:sync_test(~p, ~p, ~p)~n",
+ [?MODULE, Module, Data, Options]),
%%
- ?line Size = sizeof(Data),
+ Size = sizeof(Data),
%%
- ?line {ok, Fd} = Module:open(Data, Options),
- ?line ok = Module:sync(Fd),
- ?line {ok, Data} = Module:read(Fd, Size+1),
- ?line ok.
+ {ok, Fd} = Module:open(Data, Options),
+ ok = Module:sync(Fd),
+ {ok, Data} = Module:read(Fd, Size+1),
+ ok.
-get_set_file(suite) ->
- [];
-get_set_file(doc) ->
- ["Tests get_file/1, set_file/2, get_file_close/1 and get_size/1."];
+%% Tests get_file/1, set_file/2, get_file_close/1 and get_size/1.
get_set_file(Config) when is_list(Config) ->
%% These two strings should not be of equal length.
- ?line Str = "När högan nord blir snöbetäckt, ",
- ?line Str2 = "får alla harar byta dräkt. ",
- ?line Bin = list_to_binary(Str),
- ?line Bin2 = list_to_binary(Str2),
+ Str = "När högan nord blir snöbetäckt, ",
+ Str2 = "får alla harar byta dräkt. ",
+ Bin = list_to_binary(Str),
+ Bin2 = list_to_binary(Str2),
%%
ok = get_set_file_test(Str, read_write, Str2),
ok = get_set_file_test(Bin, [binary, read, write], Bin2),
@@ -379,87 +350,84 @@ get_set_file(Config) when is_list(Config) ->
ok.
get_set_file_test(Data, Options, Data2) ->
- ?line io:format("~p:get_set_file_test(~p, ~p, ~p)~n",
- [?MODULE, Data, Options, Data2]),
- %%
- ?line Size = sizeof(Data),
- ?line Size2 = sizeof(Data2),
- %%
- ?line {ok, Fd} = ?RAM_FILE_MODULE:open(Data, Options),
- ?line {ok, Size} = ?RAM_FILE_MODULE:get_size(Fd),
- ?line {ok, Data} = ?RAM_FILE_MODULE:get_file(Fd),
- ?line {ok, Data} = ?RAM_FILE_MODULE:get_file_close(Fd),
- ?line {error, einval} = ?RAM_FILE_MODULE:get_size(Fd),
- ?line {ok, Fd2} = ?RAM_FILE_MODULE:open(Data, Options),
- ?line case ?RAM_FILE_MODULE:set_file(Fd2, Data2) of
- {ok, Size2} ->
- ?line {ok, Size2} = ?RAM_FILE_MODULE:get_size(Fd2),
- ?line {ok, Data2} = ?RAM_FILE_MODULE:get_file(Fd2),
- ?line {ok, Data2} = ?RAM_FILE_MODULE:get_file_close(Fd2),
- ?line ok;
- {error, _} = Error ->
- ?line {ok, Data} = ?RAM_FILE_MODULE:get_file_close(Fd2),
- ?line Error
- end.
-
-
-
-compress(suite) ->
- [];
-compress(doc) ->
- ["Test that compress/1 and uncompress/1 works."];
+ io:format("~p:get_set_file_test(~p, ~p, ~p)~n",
+ [?MODULE, Data, Options, Data2]),
+ %%
+ Size = sizeof(Data),
+ Size2 = sizeof(Data2),
+ %%
+ {ok, Fd} = ?RAM_FILE_MODULE:open(Data, Options),
+ {ok, Size} = ?RAM_FILE_MODULE:get_size(Fd),
+ {ok, Data} = ?RAM_FILE_MODULE:get_file(Fd),
+ {ok, Data} = ?RAM_FILE_MODULE:get_file_close(Fd),
+ {error, einval} = ?RAM_FILE_MODULE:get_size(Fd),
+ {ok, Fd2} = ?RAM_FILE_MODULE:open(Data, Options),
+ case ?RAM_FILE_MODULE:set_file(Fd2, Data2) of
+ {ok, Size2} ->
+ {ok, Size2} = ?RAM_FILE_MODULE:get_size(Fd2),
+ {ok, Data2} = ?RAM_FILE_MODULE:get_file(Fd2),
+ {ok, Data2} = ?RAM_FILE_MODULE:get_file_close(Fd2),
+ ok;
+ {error, _} = Error ->
+ {ok, Data} = ?RAM_FILE_MODULE:get_file_close(Fd2),
+ Error
+ end.
+
+
+
+%% Test that compress/1 and uncompress/1 works.
compress(Config) when is_list(Config) ->
- ?line Data = ?config(data_dir, Config),
- ?line Real = filename:join(Data, "realmen.html"),
- ?line RealGz = filename:join(Data, "realmen.html.gz"),
+ Data = proplists:get_value(data_dir, Config),
+ Real = filename:join(Data, "realmen.html"),
+ RealGz = filename:join(Data, "realmen.html.gz"),
%%
%% Uncompress test
%%
- ?line {ok, FdReal} = ?FILE_MODULE:open(Real, []),
- ?line {ok, Fd} = ?FILE_MODULE:open([], [ram, read, write]),
- ?line {ok, FdRealGz} = ?FILE_MODULE:open(RealGz, []),
+ {ok, FdReal} = ?FILE_MODULE:open(Real, []),
+ {ok, Fd} = ?FILE_MODULE:open([], [ram, read, write]),
+ {ok, FdRealGz} = ?FILE_MODULE:open(RealGz, []),
%%
- ?line {ok, SzGz} = ?FILE_MODULE:copy(FdRealGz, Fd),
- ?line {ok, Sz} = ?RAM_FILE_MODULE:uncompress(Fd),
- ?line {ok, 0} = ?FILE_MODULE:position(Fd, bof),
- ?line true = compare(FdReal, Fd),
+ {ok, SzGz} = ?FILE_MODULE:copy(FdRealGz, Fd),
+ {ok, Sz} = ?RAM_FILE_MODULE:uncompress(Fd),
+ {ok, 0} = ?FILE_MODULE:position(Fd, bof),
+ true = compare(FdReal, Fd),
%%
- ?line true = (SzGz =< Sz),
+ true = (SzGz =< Sz),
%%
%% Compress and uncompress test
%%
- ?line {ok, 0} = ?FILE_MODULE:position(FdReal, bof),
- ?line {ok, 0} = ?FILE_MODULE:position(Fd, bof),
- ?line ok = ?FILE_MODULE:truncate(Fd),
- ?line {ok, Sz} = ?FILE_MODULE:copy(FdReal, Fd),
- ?line {ok, SzGz} = ?RAM_FILE_MODULE:compress(Fd),
- ?line {ok, Sz} = ?RAM_FILE_MODULE:uncompress(Fd),
- ?line {ok, 0} = ?FILE_MODULE:position(Fd, bof),
- ?line {ok, 0} = ?FILE_MODULE:position(FdReal, bof),
- ?line true = compare(FdReal, Fd),
+ {ok, 0} = ?FILE_MODULE:position(FdReal, bof),
+ {ok, 0} = ?FILE_MODULE:position(Fd, bof),
+ ok = ?FILE_MODULE:truncate(Fd),
+ {ok, Sz} = ?FILE_MODULE:copy(FdReal, Fd),
+ {ok, SzGz} = ?RAM_FILE_MODULE:compress(Fd),
+ {ok, Sz} = ?RAM_FILE_MODULE:uncompress(Fd),
+ {ok, 0} = ?FILE_MODULE:position(Fd, bof),
+ {ok, 0} = ?FILE_MODULE:position(FdReal, bof),
+ true = compare(FdReal, Fd),
%%
- ?line ok = ?FILE_MODULE:close(FdReal),
- ?line ok = ?FILE_MODULE:close(Fd),
- ?line ok = ?FILE_MODULE:close(FdRealGz),
+ ok = ?FILE_MODULE:close(FdReal),
+ ok = ?FILE_MODULE:close(Fd),
+ ok = ?FILE_MODULE:close(FdRealGz),
%% Test uncompressing data that will be expanded many times.
- ?line Huge = iolist_to_binary(mk_42(18)),
- ?line HugeSize = byte_size(Huge),
- ?line HugeGz = zlib:gzip(Huge),
+ Huge = iolist_to_binary(mk_42(18)),
+ HugeSize = byte_size(Huge),
+ HugeGz = zlib:gzip(Huge),
- ?line {ok,HugeFd} = ?FILE_MODULE:open([], [ram,read,write,binary]),
- ?line ok = ?FILE_MODULE:write(HugeFd, HugeGz),
- ?line {ok,HugeSize} = ?RAM_FILE_MODULE:uncompress(HugeFd),
- ?line {ok,0} = ?FILE_MODULE:position(HugeFd, bof),
- ?line {ok,Huge} = ?FILE_MODULE:read(HugeFd, HugeSize),
+ {ok,HugeFd} = ?FILE_MODULE:open([], [ram,read,write,binary]),
+ ok = ?FILE_MODULE:write(HugeFd, HugeGz),
+ {ok,HugeSize} = ?RAM_FILE_MODULE:uncompress(HugeFd),
+ {ok,0} = ?FILE_MODULE:position(HugeFd, bof),
+ {ok,Huge} = ?FILE_MODULE:read(HugeFd, HugeSize),
%% Uncompressing again should do nothing.
- ?line {ok,HugeSize} = ?RAM_FILE_MODULE:uncompress(HugeFd),
- ?line {ok,0} = ?FILE_MODULE:position(HugeFd, bof),
- ?line {ok,Huge} = ?FILE_MODULE:read(HugeFd, HugeSize),
+ {ok,HugeSize} = ?RAM_FILE_MODULE:uncompress(HugeFd),
+ {ok,0} = ?FILE_MODULE:position(HugeFd, bof),
+ {ok,Huge} = ?FILE_MODULE:read(HugeFd, HugeSize),
- ?line ok = ?FILE_MODULE:close(HugeFd),
+ ok = ?FILE_MODULE:close(HugeFd),
ok.
@@ -469,118 +437,108 @@ mk_42(N) ->
B = mk_42(N-1),
[B|B].
-uuencode(suite) ->
- [];
-uuencode(doc) ->
- ["Test that uuencode/1 and uudecode/1 works."];
+%% Test that uuencode/1 and uudecode/1 works.
uuencode(Config) when is_list(Config) ->
- ?line Data = ?config(data_dir, Config),
- ?line Real = filename:join(Data, "realmen.html"),
- ?line RealUu = filename:join(Data, "realmen.html.uu"),
+ Data = proplists:get_value(data_dir, Config),
+ Real = filename:join(Data, "realmen.html"),
+ RealUu = filename:join(Data, "realmen.html.uu"),
%%
%% Uudecode test
%%
- ?line {ok, FdReal} = ?FILE_MODULE:open(Real, []),
- ?line {ok, Fd} = ?FILE_MODULE:open([], [ram, read, write]),
- ?line {ok, FdRealUu} = ?FILE_MODULE:open(RealUu, []),
+ {ok, FdReal} = ?FILE_MODULE:open(Real, []),
+ {ok, Fd} = ?FILE_MODULE:open([], [ram, read, write]),
+ {ok, FdRealUu} = ?FILE_MODULE:open(RealUu, []),
%%
- ?line {ok, SzUu} = ?FILE_MODULE:copy(FdRealUu, Fd),
- ?line {ok, Sz} = ?RAM_FILE_MODULE:uudecode(Fd),
- ?line true = (Sz =< SzUu),
- ?line {ok, 0} = ?FILE_MODULE:position(Fd, bof),
- ?line true = compare(FdReal, Fd),
+ {ok, SzUu} = ?FILE_MODULE:copy(FdRealUu, Fd),
+ {ok, Sz} = ?RAM_FILE_MODULE:uudecode(Fd),
+ true = (Sz =< SzUu),
+ {ok, 0} = ?FILE_MODULE:position(Fd, bof),
+ true = compare(FdReal, Fd),
%%
%% Uuencode and decode test
%%
F = fun(Offs) ->
Size = Sz - Offs,
- ?line {ok, Offs} = ?FILE_MODULE:position(FdReal, {bof,Offs}),
- ?line {ok, 0} = ?FILE_MODULE:position(Fd, bof),
- ?line ok = ?FILE_MODULE:truncate(Fd),
- ?line {ok, Size} = ?FILE_MODULE:copy(FdReal, Fd),
- ?line {ok, SizeUu} = ?RAM_FILE_MODULE:uuencode(Fd),
- ?line true = (Size =< SizeUu),
- ?line {ok, Size} = ?RAM_FILE_MODULE:uudecode(Fd),
- ?line {ok, Offs} = ?FILE_MODULE:position(FdReal, {bof,Offs}),
- ?line {ok, 0} = ?FILE_MODULE:position(Fd, bof),
- ?line true = compare(FdReal, Fd)
+ {ok, Offs} = ?FILE_MODULE:position(FdReal, {bof,Offs}),
+ {ok, 0} = ?FILE_MODULE:position(Fd, bof),
+ ok = ?FILE_MODULE:truncate(Fd),
+ {ok, Size} = ?FILE_MODULE:copy(FdReal, Fd),
+ {ok, SizeUu} = ?RAM_FILE_MODULE:uuencode(Fd),
+ true = (Size =< SizeUu),
+ {ok, Size} = ?RAM_FILE_MODULE:uudecode(Fd),
+ {ok, Offs} = ?FILE_MODULE:position(FdReal, {bof,Offs}),
+ {ok, 0} = ?FILE_MODULE:position(Fd, bof),
+ true = compare(FdReal, Fd)
end,
lists:foreach(F, lists:seq(0,Sz-1, 43)),
- ?line ok = ?FILE_MODULE:close(FdReal),
- ?line ok = ?FILE_MODULE:close(Fd),
- ?line ok = ?FILE_MODULE:close(FdRealUu),
+ ok = ?FILE_MODULE:close(FdReal),
+ ok = ?FILE_MODULE:close(Fd),
+ ok = ?FILE_MODULE:close(FdRealUu),
%%
ok.
-
-large_file_errors(suite) ->
- [];
-large_file_errors(doc) ->
- ["Test error checking of large file offsets."];
+%% Test error checking of large file offsets.
large_file_errors(Config) when is_list(Config) ->
- ?line TwoGig = 1 bsl 31,
- ?line {ok,Fd} = ?RAM_FILE_MODULE:open("1234567890", [read,write]),
- ?line {error, einval} = ?FILE_MODULE:read(Fd, TwoGig),
- ?line {error, badarg} = ?FILE_MODULE:read(Fd, -1),
- ?line {error, einval} = ?FILE_MODULE:position(Fd, {bof,TwoGig}),
- ?line {error, einval} = ?FILE_MODULE:position(Fd, {bof,-TwoGig-1}),
- ?line {error, einval} = ?FILE_MODULE:position(Fd, {bof,-1}),
- ?line {error, einval} = ?FILE_MODULE:position(Fd, {cur,TwoGig}),
- ?line {error, einval} = ?FILE_MODULE:position(Fd, {cur,-TwoGig-1}),
- ?line {error, einval} = ?FILE_MODULE:position(Fd, {eof,TwoGig}),
- ?line {error, einval} = ?FILE_MODULE:position(Fd, {eof,-TwoGig-1}),
- ?line {error, einval} = ?FILE_MODULE:pread(Fd, TwoGig, 1),
- ?line {error, einval} = ?FILE_MODULE:pread(Fd, -TwoGig-1, 1),
- ?line {error, einval} = ?FILE_MODULE:pread(Fd, -1, 1),
- ?line {error, einval} = ?FILE_MODULE:pwrite(Fd, TwoGig, "@"),
- ?line {error, einval} = ?FILE_MODULE:pwrite(Fd, -TwoGig-1, "@"),
- ?line {error, einval} = ?FILE_MODULE:pwrite(Fd, -1, "@"),
- ?line {error, einval} = ?FILE_MODULE:pread(Fd, TwoGig, 0),
- ?line {error, einval} = ?FILE_MODULE:pread(Fd, -TwoGig-1, 0),
- ?line {error, einval} = ?FILE_MODULE:pread(Fd, -1, 0),
- ?line ok = ?FILE_MODULE:close(Fd),
+ TwoGig = 1 bsl 31,
+ {ok,Fd} = ?RAM_FILE_MODULE:open("1234567890", [read,write]),
+ {error, einval} = ?FILE_MODULE:read(Fd, TwoGig),
+ {error, badarg} = ?FILE_MODULE:read(Fd, -1),
+ {error, einval} = ?FILE_MODULE:position(Fd, {bof,TwoGig}),
+ {error, einval} = ?FILE_MODULE:position(Fd, {bof,-TwoGig-1}),
+ {error, einval} = ?FILE_MODULE:position(Fd, {bof,-1}),
+ {error, einval} = ?FILE_MODULE:position(Fd, {cur,TwoGig}),
+ {error, einval} = ?FILE_MODULE:position(Fd, {cur,-TwoGig-1}),
+ {error, einval} = ?FILE_MODULE:position(Fd, {eof,TwoGig}),
+ {error, einval} = ?FILE_MODULE:position(Fd, {eof,-TwoGig-1}),
+ {error, einval} = ?FILE_MODULE:pread(Fd, TwoGig, 1),
+ {error, einval} = ?FILE_MODULE:pread(Fd, -TwoGig-1, 1),
+ {error, einval} = ?FILE_MODULE:pread(Fd, -1, 1),
+ {error, einval} = ?FILE_MODULE:pwrite(Fd, TwoGig, "@"),
+ {error, einval} = ?FILE_MODULE:pwrite(Fd, -TwoGig-1, "@"),
+ {error, einval} = ?FILE_MODULE:pwrite(Fd, -1, "@"),
+ {error, einval} = ?FILE_MODULE:pread(Fd, TwoGig, 0),
+ {error, einval} = ?FILE_MODULE:pread(Fd, -TwoGig-1, 0),
+ {error, einval} = ?FILE_MODULE:pread(Fd, -1, 0),
+ ok = ?FILE_MODULE:close(Fd),
ok.
-large_file_light(suite) ->
- [];
-large_file_light(doc) ->
- ["Test light operations on a \"large\" ram_file."];
+%% Test light operations on a \large\ ram_file.
large_file_light(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
%% Marker for next test case that is to heavy to run in a suite.
- ?line ok = ?FILE_MODULE:write_file(
- filename:join(PrivDir, "large_file_light"),
- <<"TAG">>),
- %%
- ?line Data = "abcdefghijklmnopqrstuvwzyz",
- ?line Size = sizeof(Data),
- ?line Max = (1 bsl 31) - 1,
- ?line Max__1 = Max - 1,
- ?line {ok, Fd} = ?RAM_FILE_MODULE:open(Data, [read]),
- ?line {ok, Data} = ?FILE_MODULE:read(Fd, Size+1),
- ?line {ok, Max__1} = ?FILE_MODULE:position(Fd, {eof, Max-Size-1}),
- ?line eof = ?FILE_MODULE:read(Fd, 1),
- ?line {ok, Max} = ?FILE_MODULE:position(Fd, {bof, Max}),
- ?line {ok, Zero} = ?FILE_MODULE:read(Fd, 0),
- ?line 0 = sizeof(Zero),
- ?line eof = ?FILE_MODULE:read(Fd, 1),
- ?line eof = ?FILE_MODULE:pread(Fd, Max__1, 1),
- ?line {ok, Zero} = ?FILE_MODULE:pread(Fd, Max, 0),
- ?line eof = ?FILE_MODULE:pread(Fd, Max, 1),
+ ok = ?FILE_MODULE:write_file(
+ filename:join(PrivDir, "large_file_light"),
+ <<"TAG">>),
+ %%
+ Data = "abcdefghijklmnopqrstuvwzyz",
+ Size = sizeof(Data),
+ Max = (1 bsl 31) - 1,
+ Max__1 = Max - 1,
+ {ok, Fd} = ?RAM_FILE_MODULE:open(Data, [read]),
+ {ok, Data} = ?FILE_MODULE:read(Fd, Size+1),
+ {ok, Max__1} = ?FILE_MODULE:position(Fd, {eof, Max-Size-1}),
+ eof = ?FILE_MODULE:read(Fd, 1),
+ {ok, Max} = ?FILE_MODULE:position(Fd, {bof, Max}),
+ {ok, Zero} = ?FILE_MODULE:read(Fd, 0),
+ 0 = sizeof(Zero),
+ eof = ?FILE_MODULE:read(Fd, 1),
+ eof = ?FILE_MODULE:pread(Fd, Max__1, 1),
+ {ok, Zero} = ?FILE_MODULE:pread(Fd, Max, 0),
+ eof = ?FILE_MODULE:pread(Fd, Max, 1),
ok.
-large_file_heavy(suite) ->
- [];
-large_file_heavy(doc) ->
- ["Test operations on a maximum size (2 GByte - 1) ram_file."];
+large_file_heavy() ->
+ [{timetrap,{minutes,5}}].
+
+%% Test operations on a maximum size (2 GByte - 1) ram_file.
large_file_heavy(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
%% Check previous test case marker.
case ?FILE_MODULE:read_file_info(
filename:join(PrivDir, "large_file_light")) of
@@ -591,33 +549,33 @@ large_file_heavy(Config) when is_list(Config) ->
end.
do_large_file_heavy(_Config) ->
- ?line Data = "qwertyuiopasdfghjklzxcvbnm",
- ?line Size = sizeof(Data),
- ?line Max = (1 bsl 31) - 1,
- ?line Max__1 = Max - 1,
- ?line Max__3 = Max - 3,
- ?line {ok, Fd} = ?RAM_FILE_MODULE:open(Data, [read,write]),
- ?line {ok, Data} = ?FILE_MODULE:read(Fd, Size+1),
- ?line {ok, Max} = ?FILE_MODULE:position(Fd, {eof, Max-Size}),
- ?line eof = ?FILE_MODULE:read(Fd, 1),
- ?line erlang:display({allocating,2,'GByte',please,be,patient,'...'}),
- ?line ok = ?FILE_MODULE:write(Fd, ""),
- ?line erlang:display({allocating,2,'GByte',succeeded}),
- ?line {ok, Max__1} = ?FILE_MODULE:position(Fd, {eof, -1}),
- ?line {ok, [0]} = ?FILE_MODULE:read(Fd, 1),
- ?line {ok, []} = ?FILE_MODULE:read(Fd, 0),
- ?line eof = ?FILE_MODULE:read(Fd, 1),
- ?line ok = ?FILE_MODULE:pwrite(Fd, Max-3, "TAG"),
- ?line {ok, Max} = ?FILE_MODULE:position(Fd, cur),
- ?line {ok, Max__3} = ?FILE_MODULE:position(Fd, {eof, -3}),
- ?line {ok, "TAG"} = ?FILE_MODULE:read(Fd, 3+1),
- ?line {ok, Max__3} = ?FILE_MODULE:position(Fd, {cur, -3}),
- ?line ok = ?FILE_MODULE:write(Fd, "tag"),
- ?line {ok, Max} = ?FILE_MODULE:position(Fd, cur),
- ?line {ok, 0} = ?FILE_MODULE:position(Fd, bof),
- ?line {ok, "tag"} = ?FILE_MODULE:pread(Fd, Max__3, 3+1),
- ?line {ok, 0} = ?FILE_MODULE:position(Fd, cur),
- ?line ok = ?FILE_MODULE:close(Fd),
+ Data = "qwertyuiopasdfghjklzxcvbnm",
+ Size = sizeof(Data),
+ Max = (1 bsl 31) - 1,
+ Max__1 = Max - 1,
+ Max__3 = Max - 3,
+ {ok, Fd} = ?RAM_FILE_MODULE:open(Data, [read,write]),
+ {ok, Data} = ?FILE_MODULE:read(Fd, Size+1),
+ {ok, Max} = ?FILE_MODULE:position(Fd, {eof, Max-Size}),
+ eof = ?FILE_MODULE:read(Fd, 1),
+ erlang:display({allocating,2,'GByte',please,be,patient,'...'}),
+ ok = ?FILE_MODULE:write(Fd, ""),
+ erlang:display({allocating,2,'GByte',succeeded}),
+ {ok, Max__1} = ?FILE_MODULE:position(Fd, {eof, -1}),
+ {ok, [0]} = ?FILE_MODULE:read(Fd, 1),
+ {ok, []} = ?FILE_MODULE:read(Fd, 0),
+ eof = ?FILE_MODULE:read(Fd, 1),
+ ok = ?FILE_MODULE:pwrite(Fd, Max-3, "TAG"),
+ {ok, Max} = ?FILE_MODULE:position(Fd, cur),
+ {ok, Max__3} = ?FILE_MODULE:position(Fd, {eof, -3}),
+ {ok, "TAG"} = ?FILE_MODULE:read(Fd, 3+1),
+ {ok, Max__3} = ?FILE_MODULE:position(Fd, {cur, -3}),
+ ok = ?FILE_MODULE:write(Fd, "tag"),
+ {ok, Max} = ?FILE_MODULE:position(Fd, cur),
+ {ok, 0} = ?FILE_MODULE:position(Fd, bof),
+ {ok, "tag"} = ?FILE_MODULE:pread(Fd, Max__3, 3+1),
+ {ok, 0} = ?FILE_MODULE:position(Fd, cur),
+ ok = ?FILE_MODULE:close(Fd),
ok.
%%--------------------------------------------------------------------------
@@ -651,7 +609,7 @@ compare_data(A, B) when is_binary(A), is_list(B) ->
A == list_to_binary(B);
compare_data(A, B) when is_binary(A), is_binary(B) ->
A == B.
-
+
sizeof(Data) when is_list(Data) ->
length(Data);
sizeof(Data) when is_binary(Data) ->
diff --git a/lib/kernel/test/rpc_SUITE.erl b/lib/kernel/test/rpc_SUITE.erl
index ed30c2dffa..101cff7ed2 100644
--- a/lib/kernel/test/rpc_SUITE.erl
+++ b/lib/kernel/test/rpc_SUITE.erl
@@ -28,9 +28,11 @@
-export([suicide/2, suicide/3, f/0, f2/0]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,2}}].
all() ->
[call, block_call, multicall, multicall_timeout,
@@ -55,272 +57,252 @@ end_per_group(_GroupName, Config) ->
-call(doc) -> "Test different rpc calls";
+%% Test different rpc calls.
call(Config) when is_list(Config) ->
- Timetrap = ?t:timetrap(?t:seconds(30)),
- ?line PA = filename:dirname(code:which(?MODULE)),
+ PA = filename:dirname(code:which(?MODULE)),
%% Note. First part of nodename sets response delay in seconds
- ?line {ok, N1} = ?t:start_node('3_rpc_SUITE_call', slave,
- [{args, "-pa " ++ PA}]),
- ?line {ok, N2} = ?t:start_node('1_rcp_SUITE_call', slave,
- [{args, "-pa " ++ PA}]),
- ?line {ok, N3} = ?t:start_node('4_rcp_SUITE_call', slave,
- [{args, "-pa " ++ PA}]),
- ?line {ok, N4} = ?t:start_node('8_rcp_SUITE_call', slave,
- [{args, "-pa " ++ PA}]),
- ?line ok = io:format("~p~n", [[N1, N2, N3]]),
- ?line {hej,_,N1} = rpc:call(N1, ?MODULE, f, []),
- ?line {hej,_,N2} = rpc:call(N2, ?MODULE, f, [], 2000),
- ?line {badrpc,timeout} = rpc:call(N3, ?MODULE, f, [], 2000),
- ?line receive after 6000 -> ok end,
- ?line [] = flush([]),
- ?line {hej,_,N4} = rpc:call(N4, ?MODULE, f, []),
- ?line ?t:stop_node(N1),
- ?line ?t:stop_node(N2),
- ?line ?t:stop_node(N3),
- ?line ?t:stop_node(N4),
- ?t:timetrap_cancel(Timetrap),
+ {ok, N1} = test_server:start_node('3_rpc_SUITE_call', slave,
+ [{args, "-pa " ++ PA}]),
+ {ok, N2} = test_server:start_node('1_rcp_SUITE_call', slave,
+ [{args, "-pa " ++ PA}]),
+ {ok, N3} = test_server:start_node('4_rcp_SUITE_call', slave,
+ [{args, "-pa " ++ PA}]),
+ {ok, N4} = test_server:start_node('8_rcp_SUITE_call', slave,
+ [{args, "-pa " ++ PA}]),
+ ok = io:format("~p~n", [[N1, N2, N3]]),
+ {hej,_,N1} = rpc:call(N1, ?MODULE, f, []),
+ {hej,_,N2} = rpc:call(N2, ?MODULE, f, [], 2000),
+ {badrpc,timeout} = rpc:call(N3, ?MODULE, f, [], 2000),
+ receive after 6000 -> ok end,
+ [] = flush([]),
+ {hej,_,N4} = rpc:call(N4, ?MODULE, f, []),
+ test_server:stop_node(N1),
+ test_server:stop_node(N2),
+ test_server:stop_node(N3),
+ test_server:stop_node(N4),
ok.
-block_call(doc) -> "Test different rpc calls";
+%% Test different rpc calls.
block_call(Config) when is_list(Config) ->
- Timetrap = ?t:timetrap(?t:seconds(30)),
- ?line PA = filename:dirname(code:which(?MODULE)),
+ PA = filename:dirname(code:which(?MODULE)),
%% Note. First part of nodename sets response delay in seconds
- ?line {ok, N1} = ?t:start_node('3_rpc_SUITE_block_call', slave,
- [{args, "-pa " ++ PA}]),
- ?line {ok, N2} = ?t:start_node('1_rcp_SUITE_block_call', slave,
- [{args, "-pa " ++ PA}]),
- ?line {ok, N3} = ?t:start_node('4_rcp_SUITE_block_call', slave,
- [{args, "-pa " ++ PA}]),
- ?line {ok, N4} = ?t:start_node('8_rcp_SUITE_block_call', slave,
- [{args, "-pa " ++ PA}]),
- ?line ok = io:format("~p~n", [[N1, N2, N3]]),
- ?line {hej,_,N1} = rpc:block_call(N1, ?MODULE, f, []),
- ?line {hej,_,N2} = rpc:block_call(N2, ?MODULE, f, [], 2000),
- ?line {badrpc,timeout} = rpc:block_call(N3, ?MODULE, f, [], 2000),
- ?line receive after 6000 -> ok end,
- ?line [] = flush([]),
- ?line {hej,_,N4} = rpc:block_call(N4, ?MODULE, f, []),
- ?line ?t:stop_node(N1),
- ?line ?t:stop_node(N2),
- ?line ?t:stop_node(N3),
- ?line ?t:stop_node(N4),
- ?t:timetrap_cancel(Timetrap),
+ {ok, N1} = test_server:start_node('3_rpc_SUITE_block_call', slave,
+ [{args, "-pa " ++ PA}]),
+ {ok, N2} = test_server:start_node('1_rcp_SUITE_block_call', slave,
+ [{args, "-pa " ++ PA}]),
+ {ok, N3} = test_server:start_node('4_rcp_SUITE_block_call', slave,
+ [{args, "-pa " ++ PA}]),
+ {ok, N4} = test_server:start_node('8_rcp_SUITE_block_call', slave,
+ [{args, "-pa " ++ PA}]),
+ ok = io:format("~p~n", [[N1, N2, N3]]),
+ {hej,_,N1} = rpc:block_call(N1, ?MODULE, f, []),
+ {hej,_,N2} = rpc:block_call(N2, ?MODULE, f, [], 2000),
+ {badrpc,timeout} = rpc:block_call(N3, ?MODULE, f, [], 2000),
+ receive after 6000 -> ok end,
+ [] = flush([]),
+ {hej,_,N4} = rpc:block_call(N4, ?MODULE, f, []),
+ test_server:stop_node(N1),
+ test_server:stop_node(N2),
+ test_server:stop_node(N3),
+ test_server:stop_node(N4),
ok.
-multicall(doc) ->
- "OTP-3449";
+%% OTP-3449.
multicall(Config) when is_list(Config) ->
- Timetrap = ?t:timetrap(?t:seconds(20)),
- ?line PA = filename:dirname(code:which(?MODULE)),
+ PA = filename:dirname(code:which(?MODULE)),
%% Note. First part of nodename sets response delay in seconds
- ?line {ok, N1} = ?t:start_node('3_rpc_SUITE_multicall', slave,
- [{args, "-pa " ++ PA}]),
- ?line {ok, N2} = ?t:start_node('1_rcp_SUITE_multicall', slave,
- [{args, "-pa " ++ PA}]),
- ?line ok = io:format("~p~n", [[N1, N2]]),
- ?line {[{hej,_,N1},{hej,_,N2}],[]} =
- rpc:multicall([N1, N2], ?MODULE, f, []),
- ?line Msgs = flush([]),
- ?line [] = Msgs,
- ?line ?t:stop_node(N1),
- ?line ?t:stop_node(N2),
- ?t:timetrap_cancel(Timetrap),
+ {ok, N1} = test_server:start_node('3_rpc_SUITE_multicall', slave,
+ [{args, "-pa " ++ PA}]),
+ {ok, N2} = test_server:start_node('1_rcp_SUITE_multicall', slave,
+ [{args, "-pa " ++ PA}]),
+ ok = io:format("~p~n", [[N1, N2]]),
+ {[{hej,_,N1},{hej,_,N2}],[]} =
+ rpc:multicall([N1, N2], ?MODULE, f, []),
+ Msgs = flush([]),
+ [] = Msgs,
+ test_server:stop_node(N1),
+ test_server:stop_node(N2),
ok.
multicall_timeout(Config) when is_list(Config) ->
- Timetrap = ?t:timetrap(?t:seconds(30)),
- ?line PA = filename:dirname(code:which(?MODULE)),
+ PA = filename:dirname(code:which(?MODULE)),
%% Note. First part of nodename sets response delay in seconds
- ?line {ok, N1} = ?t:start_node('11_rpc_SUITE_multicall', slave,
- [{args, "-pa " ++ PA}]),
- ?line {ok, N2} = ?t:start_node('8_rpc_SUITE_multicall', slave,
- [{args, "-pa " ++ PA}]),
- ?line {ok, N3} = ?t:start_node('5_rpc_SUITE_multicall', slave,
- [{args, "-pa " ++ PA}]),
- ?line {ok, N4} = ?t:start_node('2_rcp_SUITE_multicall', slave,
- [{args, "-pa " ++ PA}]),
- ?line ok = io:format("~p~n", [[N1, N2]]),
- ?line {[{hej,_,N3},{hej,_,N4}],[N1, N2]} =
- rpc:multicall([N3, N1, N2, N4], ?MODULE, f, [], ?t:seconds(6)),
- ?t:sleep(?t:seconds(8)), %% Wait for late answers
- ?line Msgs = flush([]),
- ?line [] = Msgs,
- ?line ?t:stop_node(N1),
- ?line ?t:stop_node(N2),
- ?line ?t:stop_node(N3),
- ?line ?t:stop_node(N4),
- ?t:timetrap_cancel(Timetrap),
+ {ok, N1} = test_server:start_node('11_rpc_SUITE_multicall', slave,
+ [{args, "-pa " ++ PA}]),
+ {ok, N2} = test_server:start_node('8_rpc_SUITE_multicall', slave,
+ [{args, "-pa " ++ PA}]),
+ {ok, N3} = test_server:start_node('5_rpc_SUITE_multicall', slave,
+ [{args, "-pa " ++ PA}]),
+ {ok, N4} = test_server:start_node('2_rcp_SUITE_multicall', slave,
+ [{args, "-pa " ++ PA}]),
+ ok = io:format("~p~n", [[N1, N2]]),
+ {[{hej,_,N3},{hej,_,N4}],[N1, N2]} =
+ rpc:multicall([N3, N1, N2, N4], ?MODULE, f, [], 6000),
+ ct:sleep({seconds,8}), %Wait for late answers
+ Msgs = flush([]),
+ [] = Msgs,
+ test_server:stop_node(N1),
+ test_server:stop_node(N2),
+ test_server:stop_node(N3),
+ test_server:stop_node(N4),
ok.
multicall_dies(Config) when is_list(Config) ->
- Timetrap = ?t:timetrap(?t:seconds(30)),
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?line {ok, N1} = ?t:start_node('rpc_SUITE_multicall_dies_1', slave,
- [{args, "-pa " ++ PA}]),
- ?line {ok, N2} = ?t:start_node('rcp_SUITE_multicall_dies_2', slave,
- [{args, "-pa " ++ PA}]),
- ?line Nodes = [N1, N2],
+ PA = filename:dirname(code:which(?MODULE)),
+ {ok, N1} = test_server:start_node('rpc_SUITE_multicall_dies_1', slave,
+ [{args, "-pa " ++ PA}]),
+ {ok, N2} = test_server:start_node('rcp_SUITE_multicall_dies_2', slave,
+ [{args, "-pa " ++ PA}]),
+ Nodes = [N1, N2],
%%
- ?line {[{badrpc, {'EXIT', normal}}, {badrpc, {'EXIT', normal}}], []} =
+ {[{badrpc, {'EXIT', normal}}, {badrpc, {'EXIT', normal}}], []} =
do_multicall(Nodes, erlang, exit, [normal]),
- ?line {[{badrpc, {'EXIT', abnormal}}, {badrpc, {'EXIT', abnormal}}], []} =
+ {[{badrpc, {'EXIT', abnormal}}, {badrpc, {'EXIT', abnormal}}], []} =
do_multicall(Nodes, erlang, exit, [abnormal]),
- ?line {[{badrpc, {'EXIT', {badarith, _}}},
- {badrpc, {'EXIT', {badarith, _}}}],
- []} =
+ {[{badrpc, {'EXIT', {badarith, _}}},
+ {badrpc, {'EXIT', {badarith, _}}}],
+ []} =
do_multicall(Nodes, erlang, 'div', [1, 0]),
- ?line {[{badrpc, {'EXIT', {badarg, _}}},
- {badrpc, {'EXIT', {badarg, _}}}],
- []} =
+ {[{badrpc, {'EXIT', {badarg, _}}},
+ {badrpc, {'EXIT', {badarg, _}}}],
+ []} =
do_multicall(Nodes, erlang, atom_to_list, [1]),
- ?line {[{badrpc, {'EXIT', {undef, _}}},
- {badrpc, {'EXIT', {undef, _}}}],
- []} =
+ {[{badrpc, {'EXIT', {undef, _}}},
+ {badrpc, {'EXIT', {undef, _}}}],
+ []} =
do_multicall(Nodes, ?MODULE, suicide, []),
- ?line {[timeout, timeout], []} =
+ {[timeout, timeout], []} =
do_multicall(Nodes, ?MODULE, suicide, [link, normal]),
- ?line {[{badrpc, {'EXIT', abnormal}}, {badrpc, {'EXIT', abnormal}}], []} =
+ {[{badrpc, {'EXIT', abnormal}}, {badrpc, {'EXIT', abnormal}}], []} =
do_multicall(Nodes, ?MODULE, suicide, [link, abnormal]),
- ?line {[timeout, timeout], []} =
+ {[timeout, timeout], []} =
do_multicall(Nodes, ?MODULE, suicide, [exit, normal]),
- ?line {[{badrpc, {'EXIT', abnormal}}, {badrpc, {'EXIT', abnormal}}], []} =
+ {[{badrpc, {'EXIT', abnormal}}, {badrpc, {'EXIT', abnormal}}], []} =
do_multicall(Nodes, ?MODULE, suicide, [exit, abnormal]),
- ?line {[{badrpc, {'EXIT', killed}}, {badrpc, {'EXIT', killed}}], []} =
+ {[{badrpc, {'EXIT', killed}}, {badrpc, {'EXIT', killed}}], []} =
do_multicall(Nodes, ?MODULE, suicide, [exit, kill]),
%%
- ?line ?t:stop_node(N1),
- ?line ?t:stop_node(N2),
- ?t:timetrap_cancel(Timetrap),
+ test_server:stop_node(N1),
+ test_server:stop_node(N2),
ok.
do_multicall(Nodes, Mod, Func, Args) ->
- ?line ok = io:format("~p:~p~p~n", [Mod, Func, Args]),
- ?line Result = rpc:multicall(Nodes, Mod, Func, Args),
- ?line Msgs = flush([]),
- ?line [] = Msgs,
+ ok = io:format("~p:~p~p~n", [Mod, Func, Args]),
+ Result = rpc:multicall(Nodes, Mod, Func, Args),
+ Msgs = flush([]),
+ [] = Msgs,
Result.
-multicall_node_dies(doc) ->
- "";
multicall_node_dies(Config) when is_list(Config) ->
- Timetrap = ?t:timetrap(?t:seconds(60)),
- %%
do_multicall_2_nodes_dies(?MODULE, suicide, [erlang, halt, []]),
do_multicall_2_nodes_dies(?MODULE, suicide, [init, stop, []]),
do_multicall_2_nodes_dies(?MODULE, suicide, [rpc, stop, []]),
- %%
- ?t:timetrap_cancel(Timetrap),
ok.
do_multicall_2_nodes_dies(Mod, Func, Args) ->
- ?line ok = io:format("~p:~p~p~n", [Mod, Func, Args]),
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?line {ok, N1} = ?t:start_node('rpc_SUITE_multicall_node_dies_1', slave,
- [{args, "-pa " ++ PA}]),
- ?line {ok, N2} = ?t:start_node('rcp_SUITE_multicall_node_dies_2', slave,
- [{args, "-pa " ++ PA}]),
- ?line Nodes = [N1, N2],
- ?line {[], Nodes} = rpc:multicall(Nodes, Mod, Func, Args),
- ?line Msgs = flush([]),
- ?line [] = Msgs,
+ ok = io:format("~p:~p~p~n", [Mod, Func, Args]),
+ PA = filename:dirname(code:which(?MODULE)),
+ {ok, N1} = test_server:start_node('rpc_SUITE_multicall_node_dies_1', slave,
+ [{args, "-pa " ++ PA}]),
+ {ok, N2} = test_server:start_node('rcp_SUITE_multicall_node_dies_2', slave,
+ [{args, "-pa " ++ PA}]),
+ Nodes = [N1, N2],
+ {[], Nodes} = rpc:multicall(Nodes, Mod, Func, Args),
+ Msgs = flush([]),
+ [] = Msgs,
ok.
-called_dies(doc) ->
- "OTP-3766";
+%% OTP-3766.
called_dies(Config) when is_list(Config) ->
- Timetrap = ?t:timetrap(?t:seconds(210)),
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?line {ok, N} = ?t:start_node(rpc_SUITE_called_dies, slave,
- [{args, "-pa " ++ PA}]),
+ PA = filename:dirname(code:which(?MODULE)),
+ {ok, N} = test_server:start_node(rpc_SUITE_called_dies, slave,
+ [{args, "-pa " ++ PA}]),
%%
- ?line rep(fun (Tag, Call, Args) ->
- {Tag,{badrpc,{'EXIT',normal}}} =
- {Tag,apply(rpc, Call, Args)}
- end, N, erlang, exit, [normal]),
- ?line rep(fun (Tag, Call, Args) ->
- {Tag,{badrpc,{'EXIT',abnormal}}} =
- {Tag,apply(rpc, Call, Args)}
- end, N, erlang, exit, [abnormal]),
- ?line rep(fun (Tag, Call, Args) ->
- {Tag,{badrpc,{'EXIT',{badarith,_}}}} =
- {Tag,apply(rpc, Call, Args)}
- end, N, erlang, 'div', [1,0]),
- ?line rep(fun (Tag, Call, Args) ->
- {Tag,{badrpc,{'EXIT',{badarg,_}}}} =
- {Tag,apply(rpc, Call, Args)}
- end, N, erlang, atom_to_list, [1]),
- ?line rep(fun (Tag, Call, Args) ->
- {Tag,{badrpc,{'EXIT',{undef,_}}}} =
- {Tag,apply(rpc, Call, Args)}
- end, N, ?MODULE, suicide, []),
+ rep(fun (Tag, Call, Args) ->
+ {Tag,{badrpc,{'EXIT',normal}}} =
+ {Tag,apply(rpc, Call, Args)}
+ end, N, erlang, exit, [normal]),
+ rep(fun (Tag, Call, Args) ->
+ {Tag,{badrpc,{'EXIT',abnormal}}} =
+ {Tag,apply(rpc, Call, Args)}
+ end, N, erlang, exit, [abnormal]),
+ rep(fun (Tag, Call, Args) ->
+ {Tag,{badrpc,{'EXIT',{badarith,_}}}} =
+ {Tag,apply(rpc, Call, Args)}
+ end, N, erlang, 'div', [1,0]),
+ rep(fun (Tag, Call, Args) ->
+ {Tag,{badrpc,{'EXIT',{badarg,_}}}} =
+ {Tag,apply(rpc, Call, Args)}
+ end, N, erlang, atom_to_list, [1]),
+ rep(fun (Tag, Call, Args) ->
+ {Tag,{badrpc,{'EXIT',{undef,_}}}} =
+ {Tag,apply(rpc, Call, Args)}
+ end, N, ?MODULE, suicide, []),
%%
TrapExit = process_flag(trap_exit, true),
%%
- ?line rep(fun (Tag, Call, Args=[Node|_]) when Node == node() ->
- {Tag,timeout} =
- {Tag,apply(rpc, Call, Args)},
- {Tag,flush,[{'EXIT',_,normal}]} =
- {Tag,flush,flush([])};
- (Tag, Call, Args) ->
- {Tag,timeout} =
- {Tag,apply(rpc, Call, Args)}
- end, N, ?MODULE, suicide, [link,normal]),
- ?line rep(fun (Tag, Call, Args=[Node|_]) when Node == node() ->
- {Tag,timeout} =
- {Tag,apply(rpc, Call, Args)},
- {Tag,flush,[{'EXIT',_,abnormal}]} =
- {Tag,flush,flush([])};
- (Tag, block_call, Args) ->
- {Tag,timeout} =
- {Tag,apply(rpc, block_call, Args)};
- (Tag, Call, Args) ->
- {Tag,{badrpc,{'EXIT',abnormal}}} =
- {Tag,apply(rpc, Call, Args)}
- end, N, ?MODULE, suicide, [link,abnormal]),
- ?line rep(fun (Tag, Call, Args=[Node|_]) when Node == node() ->
- {Tag,timeout} =
- {Tag,apply(rpc, Call, Args)},
- {Tag,flush,[{'EXIT',_,normal}]} =
- {Tag,flush,flush([])};
- (Tag, Call, Args) ->
- {Tag,timeout} =
- {Tag,apply(rpc, Call, Args)}
- end, N, ?MODULE, suicide, [exit,normal]),
- ?line rep(fun (Tag, Call, Args=[Node|_]) when Node == node() ->
- {Tag,timeout} =
- {Tag,apply(rpc, Call, Args)},
- {Tag,flush,[{'EXIT',_,abnormal}]} =
- {Tag,flush,flush([])};
- (Tag, block_call, Args) ->
- {Tag,timeout} =
- {Tag,apply(rpc, block_call, Args)};
- (Tag, Call, Args) ->
- {Tag,{badrpc,{'EXIT',abnormal}}} =
- {Tag,apply(rpc, Call, Args)}
- end, N, ?MODULE, suicide, [exit,abnormal]),
+ rep(fun (Tag, Call, Args=[Node|_]) when Node == node() ->
+ {Tag,timeout} =
+ {Tag,apply(rpc, Call, Args)},
+ {Tag,flush,[{'EXIT',_,normal}]} =
+ {Tag,flush,flush([])};
+ (Tag, Call, Args) ->
+ {Tag,timeout} =
+ {Tag,apply(rpc, Call, Args)}
+ end, N, ?MODULE, suicide, [link,normal]),
+ rep(fun (Tag, Call, Args=[Node|_]) when Node == node() ->
+ {Tag,timeout} =
+ {Tag,apply(rpc, Call, Args)},
+ {Tag,flush,[{'EXIT',_,abnormal}]} =
+ {Tag,flush,flush([])};
+ (Tag, block_call, Args) ->
+ {Tag,timeout} =
+ {Tag,apply(rpc, block_call, Args)};
+ (Tag, Call, Args) ->
+ {Tag,{badrpc,{'EXIT',abnormal}}} =
+ {Tag,apply(rpc, Call, Args)}
+ end, N, ?MODULE, suicide, [link,abnormal]),
+ rep(fun (Tag, Call, Args=[Node|_]) when Node == node() ->
+ {Tag,timeout} =
+ {Tag,apply(rpc, Call, Args)},
+ {Tag,flush,[{'EXIT',_,normal}]} =
+ {Tag,flush,flush([])};
+ (Tag, Call, Args) ->
+ {Tag,timeout} =
+ {Tag,apply(rpc, Call, Args)}
+ end, N, ?MODULE, suicide, [exit,normal]),
+ rep(fun (Tag, Call, Args=[Node|_]) when Node == node() ->
+ {Tag,timeout} =
+ {Tag,apply(rpc, Call, Args)},
+ {Tag,flush,[{'EXIT',_,abnormal}]} =
+ {Tag,flush,flush([])};
+ (Tag, block_call, Args) ->
+ {Tag,timeout} =
+ {Tag,apply(rpc, block_call, Args)};
+ (Tag, Call, Args) ->
+ {Tag,{badrpc,{'EXIT',abnormal}}} =
+ {Tag,apply(rpc, Call, Args)}
+ end, N, ?MODULE, suicide, [exit,abnormal]),
%%
process_flag(trap_exit, TrapExit),
%%
- ?line rep(fun %% A local [exit,kill] would kill the test case process
- (_Tag, _Call, [Node|_]) when Node == node() ->
- ok;
- %% A block_call [exit,kill] would kill the rpc server
- (_Tag, block_call, _Args) -> ok;
- (Tag, Call, Args) ->
- {Tag,{badrpc,{'EXIT',killed}}} =
- {Tag,apply(rpc, Call, Args)}
- end, N, ?MODULE, suicide, [exit,kill]),
+ rep(fun %% A local [exit,kill] would kill the test case process
+ (_Tag, _Call, [Node|_]) when Node == node() ->
+ ok;
+ %% A block_call [exit,kill] would kill the rpc server
+ (_Tag, block_call, _Args) -> ok;
+ (Tag, Call, Args) ->
+ {Tag,{badrpc,{'EXIT',killed}}} =
+ {Tag,apply(rpc, Call, Args)}
+ end, N, ?MODULE, suicide, [exit,kill]),
%%
- ?line [] = flush([]),
- ?line ?t:stop_node(N),
- ?t:timetrap_cancel(Timetrap),
+ [] = flush([]),
+ test_server:stop_node(N),
ok.
rep(Fun, N, M, F, A) ->
@@ -335,7 +317,7 @@ rep(Fun, N, M, F, A) ->
Fun(9, block_call, [N, M, F, A, infinity]),
Fun(10, block_call, [N, M, F, A, 3000]),
ok.
-
+
suicide(link, Reason) ->
spawn_link(
@@ -364,109 +346,83 @@ suicide(Mod, Func, Args) ->
-called_node_dies(doc) ->
- "";
-called_node_dies(suite) -> [];
called_node_dies(Config) when is_list(Config) ->
- Timetrap = ?t:timetrap(?t:minutes(2)),
- ?line PA = filename:dirname(code:which(?MODULE)),
- %%
- ?line node_rep(
- fun (Tag, Call, Args) ->
- {Tag,{badrpc,nodedown}} =
- {Tag,apply(rpc, Call, Args)}
- end, "rpc_SUITE_called_node_dies_1",
- PA, ?MODULE, suicide, [erlang,halt,[]]),
- ?line node_rep(
- fun (Tag, Call, Args) ->
- {Tag,{badrpc,nodedown}} =
- {Tag,apply(rpc, Call, Args)}
- end, "rpc_SUITE_called_node_dies_2",
- PA, ?MODULE, suicide, [init,stop,[]]),
- ?line node_rep(
- fun (Tag, Call, Args=[_|_]) ->
- {Tag,{'EXIT',{killed,_}}} =
- {Tag,catch {noexit,apply(rpc, Call, Args)}}
- end, "rpc_SUITE_called_node_dies_3",
- PA, ?MODULE, suicide, [erlang,exit,[rex,kill]]),
- ?line node_rep(
- fun %% Cannot block call rpc - will hang
- (_Tag, block_call, _Args) -> ok;
- (Tag, Call, Args=[_|_]) ->
- {Tag,{'EXIT',{normal,_}}} =
- {Tag,catch {noexit,apply(rpc, Call, Args)}}
- end, "rpc_SUITE_called_node_dies_4",
- PA, ?MODULE, suicide, [rpc,stop,[]]),
- %%
- ?t:timetrap_cancel(Timetrap),
+ PA = filename:dirname(code:which(?MODULE)),
+
+ node_rep(
+ fun (Call, Args) ->
+ {badrpc,nodedown} = apply(rpc, Call, Args)
+ end, "rpc_SUITE_called_node_dies_1",
+ PA, ?MODULE, suicide, [erlang,halt,[]]),
+
+ node_rep(
+ fun (Call, Args) ->
+ {badrpc,nodedown} = apply(rpc, Call, Args)
+ end, "rpc_SUITE_called_node_dies_2",
+ PA, ?MODULE, suicide, [init,stop,[]]),
+
+ node_rep(
+ fun (Call, Args=[_|_]) ->
+ {badrpc,{'EXIT',{killed,_}}} = apply(rpc, Call, Args)
+ end, "rpc_SUITE_called_node_dies_3",
+ PA, ?MODULE, suicide, [erlang,exit,[rex,kill]]),
+
+ node_rep(
+ fun (block_call, _Args) ->
+ %% Cannot block call rpc - will hang
+ ok;
+ (Call, Args=[_|_]) ->
+ {badrpc,{'EXIT',{normal,_}}} = apply(rpc, Call, Args)
+ end, "rpc_SUITE_called_node_dies_4",
+ PA, ?MODULE, suicide, [rpc,stop,[]]),
+
ok.
node_rep(Fun, Name, PA, M, F, A) ->
- {ok, Na} = ?t:start_node(list_to_atom(Name++"_a"), slave,
- [{args, "-pa " ++ PA}]),
- Fun(a, call, [Na, M, F, A]),
- catch ?t:stop_node(Na),
- {ok, Nb} = ?t:start_node(list_to_atom(Name++"_b"), slave,
- [{args, "-pa " ++ PA}]),
- Fun(b, call, [Nb, M, F, A, infinity]),
- catch ?t:stop_node(Nb),
- {ok, Nc} = ?t:start_node(list_to_atom(Name++"_c"), slave,
- [{args, "-pa " ++ PA}]),
- Fun(c, call, [Nc, M, F, A, infinity]),
- catch ?t:stop_node(Nc),
- %%
- {ok, Nd} = ?t:start_node(list_to_atom(Name++"_d"), slave,
- [{args, "-pa " ++ PA}]),
- Fun(d, block_call, [Nd, M, F, A]),
- catch ?t:stop_node(Nd),
- {ok, Ne} = ?t:start_node(list_to_atom(Name++"_e"), slave,
- [{args, "-pa " ++ PA}]),
- Fun(e, block_call, [Ne, M, F, A, infinity]),
- catch ?t:stop_node(Ne),
- {ok, Nf} = ?t:start_node(list_to_atom(Name++"_f"), slave,
- [{args, "-pa " ++ PA}]),
- Fun(f, block_call, [Nf, M, F, A, infinity]),
- catch ?t:stop_node(Nf),
+ node_rep_call(a, call, [M,F,A], Fun, Name, PA),
+ node_rep_call(b, call, [M,F,A,infinity], Fun, Name, PA),
+ node_rep_call(c, block_call, [M,F,A], Fun, Name, PA),
+ node_rep_call(d, block_call, [M,F,A,infinity], Fun, Name, PA).
+
+node_rep_call(Tag, Call, Args, Fun, Name0, PA) ->
+ Name = list_to_atom(Name0 ++ "_" ++ atom_to_list(Tag)),
+ {ok, N} = test_server:start_node(Name, slave,
+ [{args, "-pa " ++ PA}]),
+ Fun(Call, [N|Args]),
+ catch test_server:stop_node(N),
ok.
-
-
-called_throws(doc) ->
- "OTP-3766";
+%% OTP-3766.
called_throws(Config) when is_list(Config) ->
- Timetrap = ?t:timetrap(?t:seconds(10)),
- ?line PA = filename:dirname(code:which(?MODULE)),
+ PA = filename:dirname(code:which(?MODULE)),
%%
- ?line {ok, N} = ?t:start_node(rpc_SUITE_called_throws, slave,
- [{args, "-pa " ++ PA}]),
+ {ok, N} = test_server:start_node(rpc_SUITE_called_throws, slave,
+ [{args, "-pa " ++ PA}]),
%%
- ?line rep(fun (Tag, Call, Args) ->
- {Tag,up} =
- {Tag,apply(rpc, Call, Args)}
- end, N, erlang, throw, [up]),
- ?line rep(fun (Tag, Call, Args) ->
- {Tag,{badrpc,{'EXIT',reason}}} =
- {Tag,apply(rpc, Call, Args)}
- end, N, erlang, throw, [{'EXIT',reason}]),
+ rep(fun (Tag, Call, Args) ->
+ {Tag,up} =
+ {Tag,apply(rpc, Call, Args)}
+ end, N, erlang, throw, [up]),
+ rep(fun (Tag, Call, Args) ->
+ {Tag,{badrpc,{'EXIT',reason}}} =
+ {Tag,apply(rpc, Call, Args)}
+ end, N, erlang, throw, [{'EXIT',reason}]),
%%
- ?line ?t:stop_node(N),
- ?t:timetrap_cancel(Timetrap),
+ test_server:stop_node(N),
ok.
call_benchmark(Config) when is_list(Config) ->
- Timetrap = ?t:timetrap(?t:seconds(120)),
PA = filename:dirname(code:which(?MODULE)),
- {ok, Node} = ?t:start_node(rpc_SUITE_call_benchmark, slave,
- [{args, "-pa " ++ PA}]),
+ {ok, Node} = test_server:start_node(rpc_SUITE_call_benchmark, slave,
+ [{args, "-pa " ++ PA}]),
Iter = case erlang:system_info(modified_timing_level) of
undefined -> 10000;
_ -> 500 %Modified timing - spawn is slower
end,
Res = do_call_benchmark(Node, Iter),
- ?t:stop_node(Node),
- ?t:timetrap_cancel(Timetrap),
+ test_server:stop_node(Node),
Res.
do_call_benchmark(Node, M) when is_integer(M), M > 0 ->
@@ -486,31 +442,28 @@ do_call_benchmark(Node, I, M) ->
do_call_benchmark(Node, I+1, M).
async_call(Config) when is_list(Config) ->
- Dog = ?t:timetrap(?t:seconds(120)),
-
%% Note: First part of nodename sets response delay in seconds.
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?line NodeArgs = [{args,"-pa "++ PA}],
- ?line {ok,Node1} = ?t:start_node('1_rpc_SUITE_call', slave, NodeArgs),
- ?line {ok,Node2} = ?t:start_node('10_rpc_SUITE_call', slave, NodeArgs),
- ?line {ok,Node3} = ?t:start_node('20_rpc_SUITE_call', slave, NodeArgs),
- ?line Promise1 = rpc:async_call(Node1, ?MODULE, f, []),
- ?line Promise2 = rpc:async_call(Node2, ?MODULE, f, []),
- ?line Promise3 = rpc:async_call(Node3, ?MODULE, f, []),
+ PA = filename:dirname(code:which(?MODULE)),
+ NodeArgs = [{args,"-pa "++ PA}],
+ {ok,Node1} = test_server:start_node('1_rpc_SUITE_call', slave, NodeArgs),
+ {ok,Node2} = test_server:start_node('10_rpc_SUITE_call', slave, NodeArgs),
+ {ok,Node3} = test_server:start_node('20_rpc_SUITE_call', slave, NodeArgs),
+ Promise1 = rpc:async_call(Node1, ?MODULE, f, []),
+ Promise2 = rpc:async_call(Node2, ?MODULE, f, []),
+ Promise3 = rpc:async_call(Node3, ?MODULE, f, []),
%% Test fast timeouts.
- ?line timeout = rpc:nb_yield(Promise2),
- ?line timeout = rpc:nb_yield(Promise2, 10),
+ timeout = rpc:nb_yield(Promise2),
+ timeout = rpc:nb_yield(Promise2, 10),
%% Let Node1 finish its work before yielding.
- ?t:sleep(?t:seconds(2)),
- ?line {hej,_,Node1} = rpc:yield(Promise1),
+ ct:sleep({seconds,2}),
+ {hej,_,Node1} = rpc:yield(Promise1),
%% Wait for the Node2 and Node3.
- ?line {value,{hej,_,Node2}} = rpc:nb_yield(Promise2, infinity),
- ?line {hej,_,Node3} = rpc:yield(Promise3),
+ {value,{hej,_,Node2}} = rpc:nb_yield(Promise2, infinity),
+ {hej,_,Node3} = rpc:yield(Promise3),
- ?t:timetrap_cancel(Dog),
ok.
%%%
diff --git a/lib/kernel/test/sendfile_SUITE.erl b/lib/kernel/test/sendfile_SUITE.erl
index a82b9c5fcd..775689a6bc 100644
--- a/lib/kernel/test/sendfile_SUITE.erl
+++ b/lib/kernel/test/sendfile_SUITE.erl
@@ -53,7 +53,7 @@ init_per_suite(Config) ->
{{unix,sunos}, {5,8,_}} ->
{skip, "Solaris 8 not supported for now"};
_ ->
- Priv = ?config(priv_dir, Config),
+ Priv = proplists:get_value(priv_dir, Config),
SFilename = filename:join(Priv, "sendfile_small.html"),
{ok, DS} = file:open(SFilename,[write,raw]),
file:write(DS,"yo baby yo"),
diff --git a/lib/kernel/test/seq_trace_SUITE.erl b/lib/kernel/test/seq_trace_SUITE.erl
index 6a63f7bc9c..15128ab69c 100644
--- a/lib/kernel/test/seq_trace_SUITE.erl
+++ b/lib/kernel/test/seq_trace_SUITE.erl
@@ -27,22 +27,21 @@
trace_exit/1, distributed_exit/1, call/1, port/1,
match_set_seq_token/1, gc_seq_token/1]).
-% internal exports
+%% internal exports
-export([simple_tracer/2, one_time_receiver/0, one_time_receiver/1,
start_tracer/0, stop_tracer/1,
do_match_set_seq_token/1, do_gc_seq_token/1, countdown_start/2]).
- %-define(line_trace, 1).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(TIMESTAMP_MODES, [no_timestamp,
timestamp,
monotonic_timestamp,
strict_monotonic_timestamp]).
--define(default_timeout, ?t:minutes(1)).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[token_set_get, tracer_set_get, print, send,
@@ -67,18 +66,13 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_Case, Config) ->
- ?line Dog = test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
%% Verifies that the set_token and get_token functions work as expected
-token_set_get(doc) -> [];
-token_set_get(suite) -> [];
token_set_get(Config) when is_list(Config) ->
do_token_set_get(timestamp),
do_token_set_get(monotonic_timestamp),
@@ -91,371 +85,351 @@ do_token_set_get(TsType) ->
strict_monotonic_timestamp -> 23;
monotonic_timestamp -> 39
end,
- ?line Self = self(),
- ?line seq_trace:reset_trace(),
+ Self = self(),
+ seq_trace:reset_trace(),
%% Test that initial seq_trace is disabled
- ?line [] = seq_trace:get_token(),
+ [] = seq_trace:get_token(),
%% Test setting and reading the different fields
- ?line 0 = seq_trace:set_token(label,17),
- ?line {label,17} = seq_trace:get_token(label),
- ?line false = seq_trace:set_token(print,true),
- ?line {print,true} = seq_trace:get_token(print),
- ?line false = seq_trace:set_token(send,true),
- ?line {send,true} = seq_trace:get_token(send),
- ?line false = seq_trace:set_token('receive',true),
- ?line {'receive',true} = seq_trace:get_token('receive'),
- ?line false = seq_trace:set_token(TsType,true),
- ?line {TsType,true} = seq_trace:get_token(TsType),
+ 0 = seq_trace:set_token(label,17),
+ {label,17} = seq_trace:get_token(label),
+ false = seq_trace:set_token(print,true),
+ {print,true} = seq_trace:get_token(print),
+ false = seq_trace:set_token(send,true),
+ {send,true} = seq_trace:get_token(send),
+ false = seq_trace:set_token('receive',true),
+ {'receive',true} = seq_trace:get_token('receive'),
+ false = seq_trace:set_token(TsType,true),
+ {TsType,true} = seq_trace:get_token(TsType),
%% Check the whole token
- ?line {Flags,17,0,Self,0} = seq_trace:get_token(), % all flags are set
+ {Flags,17,0,Self,0} = seq_trace:get_token(), % all flags are set
%% Test setting and reading the 'serial' field
- ?line {0,0} = seq_trace:set_token(serial,{3,5}),
- ?line {serial,{3,5}} = seq_trace:get_token(serial),
+ {0,0} = seq_trace:set_token(serial,{3,5}),
+ {serial,{3,5}} = seq_trace:get_token(serial),
%% Check the whole token, test that a whole token can be set and get
- ?line {Flags,17,5,Self,3} = seq_trace:get_token(),
- ?line seq_trace:set_token({Flags,19,7,Self,5}),
- ?line {Flags,19,7,Self,5} = seq_trace:get_token(),
+ {Flags,17,5,Self,3} = seq_trace:get_token(),
+ seq_trace:set_token({Flags,19,7,Self,5}),
+ {Flags,19,7,Self,5} = seq_trace:get_token(),
%% Check that receive timeout does not reset token
- ?line receive after 0 -> ok end,
- ?line {Flags,19,7,Self,5} = seq_trace:get_token(),
+ receive after 0 -> ok end,
+ {Flags,19,7,Self,5} = seq_trace:get_token(),
%% Check that token can be unset
- ?line {Flags,19,7,Self,5} = seq_trace:set_token([]),
- ?line [] = seq_trace:get_token(),
+ {Flags,19,7,Self,5} = seq_trace:set_token([]),
+ [] = seq_trace:get_token(),
%% Check that Previous serial counter survived unset token
- ?line 0 = seq_trace:set_token(label, 17),
- ?line {0,17,0,Self,5} = seq_trace:get_token(),
+ 0 = seq_trace:set_token(label, 17),
+ {0,17,0,Self,5} = seq_trace:get_token(),
%% Check that reset_trace resets the token and clears
%% the Previous serial counter
- ?line seq_trace:reset_trace(),
- ?line [] = seq_trace:get_token(),
- ?line 0 = seq_trace:set_token(label, 19),
- ?line {0,19,0,Self,0} = seq_trace:get_token(),
+ seq_trace:reset_trace(),
+ [] = seq_trace:get_token(),
+ 0 = seq_trace:set_token(label, 19),
+ {0,19,0,Self,0} = seq_trace:get_token(),
%% Cleanup
- ?line seq_trace:reset_trace(),
+ seq_trace:reset_trace(),
ok.
-tracer_set_get(doc) -> [];
-tracer_set_get(suite) -> [];
tracer_set_get(Config) when is_list(Config) ->
- ?line Self = self(),
- ?line seq_trace:set_system_tracer(self()),
- ?line Self = seq_trace:get_system_tracer(),
- ?line Self = seq_trace:set_system_tracer(false),
- ?line false = seq_trace:get_system_tracer(),
+ Self = self(),
+ seq_trace:set_system_tracer(self()),
+ Self = seq_trace:get_system_tracer(),
+ Self = seq_trace:set_system_tracer(false),
+ false = seq_trace:get_system_tracer(),
%% Set the system tracer to a port.
- ?line Port = load_tracer(Config),
- ?line seq_trace:set_system_tracer(Port),
- ?line Port = seq_trace:get_system_tracer(),
- ?line Port = seq_trace:set_system_tracer(false),
- ?line false = seq_trace:get_system_tracer(),
+ Port = load_tracer(Config),
+ seq_trace:set_system_tracer(Port),
+ Port = seq_trace:get_system_tracer(),
+ Port = seq_trace:set_system_tracer(false),
+ false = seq_trace:get_system_tracer(),
ok.
-print(doc) -> [];
-print(suite) -> [];
print(Config) when is_list(Config) ->
lists:foreach(fun do_print/1, ?TIMESTAMP_MODES).
do_print(TsType) ->
- ?line start_tracer(),
- ?line set_token_flags([print, TsType]),
- ?line seq_trace:print(0,print1),
- ?line seq_trace:print(1,print2),
- ?line seq_trace:print(print3),
- ?line seq_trace:reset_trace(),
- ?line [{0,{print,_,_,[],print1}, Ts0},
+ start_tracer(),
+ set_token_flags([print, TsType]),
+ seq_trace:print(0,print1),
+ seq_trace:print(1,print2),
+ seq_trace:print(print3),
+ seq_trace:reset_trace(),
+ [{0,{print,_,_,[],print1}, Ts0},
{0,{print,_,_,[],print3}, Ts1}] = stop_tracer(2),
check_ts(TsType, Ts0),
check_ts(TsType, Ts1).
-send(doc) -> [];
-send(suite) -> [];
send(Config) when is_list(Config) ->
lists:foreach(fun do_send/1, ?TIMESTAMP_MODES).
do_send(TsType) ->
- ?line seq_trace:reset_trace(),
- ?line start_tracer(),
- ?line Receiver = spawn(?MODULE,one_time_receiver,[]),
- ?line set_token_flags([send, TsType]),
- ?line Receiver ! send,
- ?line Self = self(),
- ?line seq_trace:reset_trace(),
- ?line [{0,{send,_,Self,Receiver,send}, Ts}] = stop_tracer(1),
+ seq_trace:reset_trace(),
+ start_tracer(),
+ Receiver = spawn(?MODULE,one_time_receiver,[]),
+ set_token_flags([send, TsType]),
+ Receiver ! send,
+ Self = self(),
+ seq_trace:reset_trace(),
+ [{0,{send,_,Self,Receiver,send}, Ts}] = stop_tracer(1),
check_ts(TsType, Ts).
-distributed_send(doc) -> [];
-distributed_send(suite) -> [];
distributed_send(Config) when is_list(Config) ->
lists:foreach(fun do_distributed_send/1, ?TIMESTAMP_MODES).
do_distributed_send(TsType) ->
- ?line {ok,Node} = start_node(seq_trace_other,[]),
- ?line {_,Dir} = code:is_loaded(?MODULE),
- ?line Mdir = filename:dirname(Dir),
- ?line true = rpc:call(Node,code,add_patha,[Mdir]),
- ?line seq_trace:reset_trace(),
- ?line start_tracer(),
- ?line Receiver = spawn(Node,?MODULE,one_time_receiver,[]),
- ?line set_token_flags([send,TsType]),
- ?line Receiver ! send,
- ?line Self = self(),
- ?line seq_trace:reset_trace(),
- ?line stop_node(Node),
- ?line [{0,{send,_,Self,Receiver,send}, Ts}] = stop_tracer(1),
+ {ok,Node} = start_node(seq_trace_other,[]),
+ {_,Dir} = code:is_loaded(?MODULE),
+ Mdir = filename:dirname(Dir),
+ true = rpc:call(Node,code,add_patha,[Mdir]),
+ seq_trace:reset_trace(),
+ start_tracer(),
+ Receiver = spawn(Node,?MODULE,one_time_receiver,[]),
+ set_token_flags([send,TsType]),
+ Receiver ! send,
+ Self = self(),
+ seq_trace:reset_trace(),
+ stop_node(Node),
+ [{0,{send,_,Self,Receiver,send}, Ts}] = stop_tracer(1),
check_ts(TsType, Ts).
-recv(doc) -> [];
-recv(suite) -> [];
recv(Config) when is_list(Config) ->
lists:foreach(fun do_recv/1, ?TIMESTAMP_MODES).
do_recv(TsType) ->
- ?line seq_trace:reset_trace(),
- ?line start_tracer(),
- ?line Receiver = spawn(?MODULE,one_time_receiver,[]),
- ?line set_token_flags(['receive',TsType]),
- ?line Receiver ! 'receive',
+ seq_trace:reset_trace(),
+ start_tracer(),
+ Receiver = spawn(?MODULE,one_time_receiver,[]),
+ set_token_flags(['receive',TsType]),
+ Receiver ! 'receive',
%% let the other process receive the message:
- ?line receive after 1 -> ok end,
- ?line Self = self(),
- ?line seq_trace:reset_trace(),
- ?line [{0,{'receive',_,Self,Receiver,'receive'}, Ts}] = stop_tracer(1),
+ receive after 1 -> ok end,
+ Self = self(),
+ seq_trace:reset_trace(),
+ [{0,{'receive',_,Self,Receiver,'receive'}, Ts}] = stop_tracer(1),
check_ts(TsType, Ts).
-distributed_recv(doc) -> [];
-distributed_recv(suite) -> [];
distributed_recv(Config) when is_list(Config) ->
lists:foreach(fun do_distributed_recv/1, ?TIMESTAMP_MODES).
do_distributed_recv(TsType) ->
- ?line {ok,Node} = start_node(seq_trace_other,[]),
- ?line {_,Dir} = code:is_loaded(?MODULE),
- ?line Mdir = filename:dirname(Dir),
- ?line true = rpc:call(Node,code,add_patha,[Mdir]),
- ?line seq_trace:reset_trace(),
- ?line rpc:call(Node,?MODULE,start_tracer,[]),
- ?line Receiver = spawn(Node,?MODULE,one_time_receiver,[]),
- ?line set_token_flags(['receive',TsType]),
- ?line Receiver ! 'receive',
+ {ok,Node} = start_node(seq_trace_other,[]),
+ {_,Dir} = code:is_loaded(?MODULE),
+ Mdir = filename:dirname(Dir),
+ true = rpc:call(Node,code,add_patha,[Mdir]),
+ seq_trace:reset_trace(),
+ rpc:call(Node,?MODULE,start_tracer,[]),
+ Receiver = spawn(Node,?MODULE,one_time_receiver,[]),
+ set_token_flags(['receive',TsType]),
+ Receiver ! 'receive',
%% let the other process receive the message:
- ?line receive after 1 -> ok end,
- ?line Self = self(),
- ?line seq_trace:reset_trace(),
- ?line Result = rpc:call(Node,?MODULE,stop_tracer,[1]),
- ?line stop_node(Node),
- ?line ok = io:format("~p~n",[Result]),
- ?line [{0,{'receive',_,Self,Receiver,'receive'}, Ts}] = Result,
+ receive after 1 -> ok end,
+ Self = self(),
+ seq_trace:reset_trace(),
+ Result = rpc:call(Node,?MODULE,stop_tracer,[1]),
+ stop_node(Node),
+ ok = io:format("~p~n",[Result]),
+ [{0,{'receive',_,Self,Receiver,'receive'}, Ts}] = Result,
check_ts(TsType, Ts).
-trace_exit(doc) -> [];
-trace_exit(suite) -> [];
trace_exit(Config) when is_list(Config) ->
lists:foreach(fun do_trace_exit/1, ?TIMESTAMP_MODES).
do_trace_exit(TsType) ->
- ?line seq_trace:reset_trace(),
- ?line start_tracer(),
- ?line Receiver = spawn_link(?MODULE, one_time_receiver, [exit]),
- ?line process_flag(trap_exit, true),
- ?line set_token_flags([send, TsType]),
- ?line Receiver ! {before, exit},
+ seq_trace:reset_trace(),
+ start_tracer(),
+ Receiver = spawn_link(?MODULE, one_time_receiver, [exit]),
+ process_flag(trap_exit, true),
+ set_token_flags([send, TsType]),
+ Receiver ! {before, exit},
%% let the other process receive the message:
- ?line receive
+ receive
{'EXIT', Receiver, {exit, {before, exit}}} ->
seq_trace:set_token([]);
Other ->
seq_trace:set_token([]),
- ?t:fail({received, Other})
+ ct:fail({received, Other})
end,
- ?line Self = self(),
- ?line Result = stop_tracer(2),
- ?line seq_trace:reset_trace(),
- ?line ok = io:format("~p~n", [Result]),
- ?line [{0, {send, {0,1}, Self, Receiver, {before, exit}}, Ts0},
+ Self = self(),
+ Result = stop_tracer(2),
+ seq_trace:reset_trace(),
+ ok = io:format("~p~n", [Result]),
+ [{0, {send, {0,1}, Self, Receiver, {before, exit}}, Ts0},
{0, {send, {1,2}, Receiver, Self,
{'EXIT', Receiver, {exit, {before, exit}}}}, Ts1}] = Result,
check_ts(TsType, Ts0),
check_ts(TsType, Ts1).
-distributed_exit(doc) -> [];
-distributed_exit(suite) -> [];
distributed_exit(Config) when is_list(Config) ->
lists:foreach(fun do_distributed_exit/1, ?TIMESTAMP_MODES).
do_distributed_exit(TsType) ->
- ?line {ok, Node} = start_node(seq_trace_other, []),
- ?line {_, Dir} = code:is_loaded(?MODULE),
- ?line Mdir = filename:dirname(Dir),
- ?line true = rpc:call(Node, code, add_patha, [Mdir]),
- ?line seq_trace:reset_trace(),
- ?line rpc:call(Node, ?MODULE, start_tracer,[]),
- ?line Receiver = spawn_link(Node, ?MODULE, one_time_receiver, [exit]),
- ?line process_flag(trap_exit, true),
- ?line set_token_flags([send, TsType]),
- ?line Receiver ! {before, exit},
+ {ok, Node} = start_node(seq_trace_other, []),
+ {_, Dir} = code:is_loaded(?MODULE),
+ Mdir = filename:dirname(Dir),
+ true = rpc:call(Node, code, add_patha, [Mdir]),
+ seq_trace:reset_trace(),
+ rpc:call(Node, ?MODULE, start_tracer,[]),
+ Receiver = spawn_link(Node, ?MODULE, one_time_receiver, [exit]),
+ process_flag(trap_exit, true),
+ set_token_flags([send, TsType]),
+ Receiver ! {before, exit},
%% let the other process receive the message:
- ?line receive
+ receive
{'EXIT', Receiver, {exit, {before, exit}}} ->
seq_trace:set_token([]);
Other ->
seq_trace:set_token([]),
- ?t:fail({received, Other})
+ ct:fail({received, Other})
end,
- ?line Self = self(),
- ?line Result = rpc:call(Node, ?MODULE, stop_tracer, [1]),
- ?line seq_trace:reset_trace(),
- ?line stop_node(Node),
- ?line ok = io:format("~p~n", [Result]),
- ?line [{0, {send, {1, 2}, Receiver, Self,
+ Self = self(),
+ Result = rpc:call(Node, ?MODULE, stop_tracer, [1]),
+ seq_trace:reset_trace(),
+ stop_node(Node),
+ ok = io:format("~p~n", [Result]),
+ [{0, {send, {1, 2}, Receiver, Self,
{'EXIT', Receiver, {exit, {before, exit}}}}, Ts}] = Result,
check_ts(TsType, Ts).
call(doc) ->
"Tests special forms {is_seq_trace} and {get_seq_token} "
"in trace match specs.";
-call(suite) ->
- [];
call(Config) when is_list(Config) ->
- ?line Self = self(),
- ?line seq_trace:reset_trace(),
- ?line TrA = transparent_tracer(),
- ?line 1 =
+ Self = self(),
+ seq_trace:reset_trace(),
+ TrA = transparent_tracer(),
+ 1 =
erlang:trace(Self, true,
[call, set_on_spawn, {tracer, TrA(pid)}]),
- ?line 1 =
+ 1 =
erlang:trace_pattern({?MODULE, call_tracee_1, 1},
[{'_',
[],
[{message, {{{self}, {get_seq_token}}}}]}],
[local]),
- ?line 1 =
+ 1 =
erlang:trace_pattern({?MODULE, call_tracee_2, 1},
[{'_',
[{is_seq_trace}],
[{message, {{{self}, {get_seq_token}}}}]}],
[local]),
- ?line RefA = make_ref(),
- ?line Pid2A = spawn_link(
+ RefA = make_ref(),
+ Pid2A = spawn_link(
fun() ->
receive {_, msg, RefA} -> ok end,
RefA = call_tracee_2(RefA),
Self ! {self(), msg, RefA}
end),
- ?line Pid1A = spawn_link(
+ Pid1A = spawn_link(
fun() ->
receive {_, msg, RefA} -> ok end,
RefA = call_tracee_1(RefA),
Pid2A ! {self(), msg, RefA}
end),
- ?line Pid1A ! {Self, msg, RefA},
+ Pid1A ! {Self, msg, RefA},
%% The message is passed Self -> Pid1B -> Pid2B -> Self.
%% Traced functions are called in Pid1B and Pid2B.
- ?line receive {Pid2A, msg, RefA} -> ok end,
+ receive {Pid2A, msg, RefA} -> ok end,
%% Only call_tracee1 will be traced since the guard for
%% call_tracee2 requires a sequential trace. The trace
%% token is undefined.
- ?line Token2A = [],
- ?line {ok, [{trace, Pid1A, call,
+ Token2A = [],
+ {ok, [{trace, Pid1A, call,
{?MODULE, call_tracee_1, [RefA]},
{Pid1A, Token2A}}]} =
TrA({stop, 1}),
- ?line seq_trace:reset_trace(),
+ seq_trace:reset_trace(),
- ?line TrB = transparent_tracer(),
- ?line 1 =
+ TrB = transparent_tracer(),
+ 1 =
erlang:trace(Self, true,
[call, set_on_spawn, {tracer, TrB(pid)}]),
- ?line Label = 17,
- ?line seq_trace:set_token(label, Label), % Token enters here!!
- ?line RefB = make_ref(),
- ?line Pid2B = spawn_link(
+ Label = 17,
+ seq_trace:set_token(label, Label), % Token enters here!!
+ RefB = make_ref(),
+ Pid2B = spawn_link(
fun() ->
receive {_, msg, RefB} -> ok end,
RefB = call_tracee_2(RefB),
Self ! {self(), msg, RefB}
end),
- ?line Pid1B = spawn_link(
+ Pid1B = spawn_link(
fun() ->
receive {_, msg, RefB} -> ok end,
RefB = call_tracee_1(RefB),
Pid2B ! {self(), msg, RefB}
end),
- ?line Pid1B ! {Self, msg, RefB},
+ Pid1B ! {Self, msg, RefB},
%% The message is passed Self -> Pid1B -> Pid2B -> Self, and the
%% seq_trace token follows invisibly. Traced functions are
%% called in Pid1B and Pid2B. Seq_trace flags == 0 so no
%% seq_trace messages are generated.
- ?line receive {Pid2B, msg, RefB} -> ok end,
+ receive {Pid2B, msg, RefB} -> ok end,
%% The values of these counters {.., 1, _, 0}, {.., 2, _, 1}
%% depend on that seq_trace has been reset just before this test.
- ?line Token1B = {0, Label, 1, Self, 0},
- ?line Token2B = {0, Label, 2, Pid1B, 1},
- ?line {ok, [{trace, Pid1B, call,
+ Token1B = {0, Label, 1, Self, 0},
+ Token2B = {0, Label, 2, Pid1B, 1},
+ {ok, [{trace, Pid1B, call,
{?MODULE, call_tracee_1, [RefB]},
{Pid1B, Token1B}},
{trace, Pid2B, call,
{?MODULE, call_tracee_2, [RefB]},
{Pid2B, Token2B}}]} =
TrB({stop,2}),
- ?line seq_trace:reset_trace(),
+ seq_trace:reset_trace(),
ok.
-port(doc) ->
- "Send trace messages to a port.";
-port(suite) -> [];
+%% Send trace messages to a port.
port(Config) when is_list(Config) ->
lists:foreach(fun (TsType) -> do_port(TsType, Config) end,
?TIMESTAMP_MODES).
do_port(TsType, Config) ->
io:format("Testing ~p~n",[TsType]),
- ?line Port = load_tracer(Config),
- ?line seq_trace:set_system_tracer(Port),
+ Port = load_tracer(Config),
+ seq_trace:set_system_tracer(Port),
- ?line set_token_flags([print, TsType]),
- ?line Small = [small,term],
- ?line seq_trace:print(0, Small),
- ?line case get_port_message(Port) of
+ set_token_flags([print, TsType]),
+ Small = [small,term],
+ seq_trace:print(0, Small),
+ case get_port_message(Port) of
{seq_trace,0,{print,_,_,[],Small}} when TsType == no_timestamp ->
ok;
{seq_trace,0,{print,_,_,[],Small},Ts0} when TsType /= no_timestamp ->
check_ts(TsType, Ts0),
ok;
Other ->
- ?line seq_trace:reset_trace(),
- ?line ?t:fail({unexpected,Other})
+ seq_trace:reset_trace(),
+ ct:fail({unexpected,Other})
end,
%% OTP-4218 Messages from ports should not affect seq trace token.
%%
%% Check if trace token still is active on this process after
%% the get_port_message/1 above that receives from a port.
- ?line OtherSmall = [other | Small],
- ?line seq_trace:print(0, OtherSmall),
- ?line seq_trace:reset_trace(),
- ?line case get_port_message(Port) of
+ OtherSmall = [other | Small],
+ seq_trace:print(0, OtherSmall),
+ seq_trace:reset_trace(),
+ case get_port_message(Port) of
{seq_trace,0,{print,_,_,[],OtherSmall}} when TsType == no_timestamp ->
ok;
{seq_trace,0,{print,_,_,[],OtherSmall}, Ts1} when TsType /= no_timestamp ->
check_ts(TsType, Ts1),
ok;
Other1 ->
- ?line ?t:fail({unexpected,Other1})
+ ct:fail({unexpected,Other1})
end,
- ?line seq_trace:set_token(print, true),
- ?line Huge = huge_data(),
- ?line seq_trace:print(0, Huge),
- ?line seq_trace:reset_trace(),
- ?line case get_port_message(Port) of
+ seq_trace:set_token(print, true),
+ Huge = huge_data(),
+ seq_trace:print(0, Huge),
+ seq_trace:reset_trace(),
+ case get_port_message(Port) of
{seq_trace,0,{print,_,_,[],Huge}} ->
ok;
Other2 ->
- ?line ?t:fail({unexpected,Other2})
+ ct:fail({unexpected,Other2})
end,
unlink(Port),
exit(Port,kill),
@@ -466,21 +440,19 @@ get_port_message(Port) ->
{Port,{data,Bin}} when is_binary(Bin) ->
binary_to_term(Bin);
Other ->
- ?t:fail({unexpected,Other})
+ ct:fail({unexpected,Other})
after 5000 ->
- ?t:fail(timeout)
+ ct:fail(timeout)
end.
-match_set_seq_token(suite) ->
- [];
match_set_seq_token(doc) ->
["Tests that match spec function set_seq_token does not "
"corrupt the heap"];
match_set_seq_token(Config) when is_list(Config) ->
- ?line Parent = self(),
- ?line Timetrap = test_server:timetrap(test_server:seconds(20)),
+ Parent = self(),
+
%% OTP-4222 Match spec 'set_seq_token' corrupts heap
%%
%% This test crashes the emulator if the bug in question is present,
@@ -488,13 +460,13 @@ match_set_seq_token(Config) when is_list(Config) ->
%%
%% All the timeout stuff is here to get decent accuracy of the error
%% return value, instead of just 'timeout'.
- %
- ?line {ok, Sandbox} = start_node(seq_trace_other, []),
- ?line true = rpc:call(Sandbox, code, add_patha,
+ %%
+ {ok, Sandbox} = start_node(seq_trace_other, []),
+ true = rpc:call(Sandbox, code, add_patha,
[filename:dirname(code:which(?MODULE))]),
- ?line Lbl = 4711,
+ Lbl = 4711,
%% Do the possibly crashing test
- ?line P1 =
+ P1 =
spawn(
fun () ->
Parent ! {self(),
@@ -502,16 +474,16 @@ match_set_seq_token(Config) when is_list(Config) ->
?MODULE, do_match_set_seq_token, [Lbl])}
end),
%% Probe the node with a simple rpc request, to see if it is alive.
- ?line P2 =
+ P2 =
spawn(
fun () ->
receive after 4000 -> ok end,
Parent ! {self(), rpc:call(Sandbox, erlang, abs, [-1])}
end),
%% If the test node hangs completely, this timer expires.
- ?line R3 = erlang:start_timer(8000, self(), void),
+ R3 = erlang:start_timer(8000, self(), void),
%%
- ?line {ok, Log} =
+ {ok, Log} =
receive
{P1, Result} ->
exit(P2, done),
@@ -526,10 +498,9 @@ match_set_seq_token(Config) when is_list(Config) ->
exit(P2, timeout),
{error, "Test node hung"}
end,
- ?line ok = check_match_set_seq_token_log(Lbl, Log),
+ ok = check_match_set_seq_token_log(Lbl, Log),
%%
- ?line stop_node(Sandbox),
- ?line test_server:timetrap_cancel(Timetrap),
+ stop_node(Sandbox),
ok.
%% OTP-4222 Match spec 'set_seq_token' corrupts heap
@@ -621,14 +592,12 @@ bounce(Ref) ->
-gc_seq_token(suite) ->
- [];
gc_seq_token(doc) ->
["Tests that a seq_trace token on a message in the inqueue ",
"can be garbage collected."];
gc_seq_token(Config) when is_list(Config) ->
- ?line Parent = self(),
- ?line Timetrap = test_server:timetrap(test_server:seconds(20)),
+ Parent = self(),
+
%% OTP-4555 Seq trace token causes free mem read in gc
%%
%% This test crashes the emulator if the bug in question is present,
@@ -636,13 +605,13 @@ gc_seq_token(Config) when is_list(Config) ->
%%
%% All the timeout stuff is here to get decent accuracy of the error
%% return value, instead of just 'timeout'.
- %
- ?line {ok, Sandbox} = start_node(seq_trace_other, []),
- ?line true = rpc:call(Sandbox, code, add_patha,
+ %%
+ {ok, Sandbox} = start_node(seq_trace_other, []),
+ true = rpc:call(Sandbox, code, add_patha,
[filename:dirname(code:which(?MODULE))]),
- ?line Label = 4711,
+ Label = 4711,
%% Do the possibly crashing test
- ?line P1 =
+ P1 =
spawn(
fun () ->
Parent ! {self(),
@@ -650,16 +619,16 @@ gc_seq_token(Config) when is_list(Config) ->
?MODULE, do_gc_seq_token, [Label])}
end),
%% Probe the node with a simple rpc request, to see if it is alive.
- ?line P2 =
+ P2 =
spawn(
fun () ->
receive after 4000 -> ok end,
Parent ! {self(), rpc:call(Sandbox, erlang, abs, [-1])}
end),
%% If the test node hangs completely, this timer expires.
- ?line R3 = erlang:start_timer(8000, self(), void),
+ R3 = erlang:start_timer(8000, self(), void),
%%
- ?line ok =
+ ok =
receive
{P1, Result} ->
exit(P2, done),
@@ -675,8 +644,7 @@ gc_seq_token(Config) when is_list(Config) ->
{error, "Test node hung"}
end,
%%
- ?line stop_node(Sandbox),
- ?line test_server:timetrap_cancel(Timetrap),
+ stop_node(Sandbox),
ok.
do_gc_seq_token(Label) ->
@@ -836,7 +804,7 @@ check_ts(no_timestamp, Ts) ->
no_timestamp = Ts
catch
_ : _ ->
- ?t:fail({unexpected_timestamp, Ts})
+ ct:fail({unexpected_timestamp, Ts})
end,
ok;
check_ts(timestamp, Ts) ->
@@ -847,7 +815,7 @@ check_ts(timestamp, Ts) ->
true = is_integer(Us)
catch
_ : _ ->
- ?t:fail({unexpected_timestamp, Ts})
+ ct:fail({unexpected_timestamp, Ts})
end,
ok;
check_ts(monotonic_timestamp, Ts) ->
@@ -855,7 +823,7 @@ check_ts(monotonic_timestamp, Ts) ->
true = is_integer(Ts)
catch
_ : _ ->
- ?t:fail({unexpected_timestamp, Ts})
+ ct:fail({unexpected_timestamp, Ts})
end,
ok;
check_ts(strict_monotonic_timestamp, Ts) ->
@@ -865,7 +833,7 @@ check_ts(strict_monotonic_timestamp, Ts) ->
true = is_integer(UMI)
catch
_ : _ ->
- ?t:fail({unexpected_timestamp, Ts})
+ ct:fail({unexpected_timestamp, Ts})
end,
ok.
@@ -876,7 +844,7 @@ stop_node(Node) ->
test_server:stop_node(Node).
load_tracer(Config) ->
- Path = ?config(data_dir, Config),
+ Path = proplists:get_value(data_dir, Config),
ok = erl_ddll:load_driver(Path, echo_drv),
open_port({spawn,echo_drv}, [eof,binary]).
diff --git a/lib/kernel/test/wrap_log_reader_SUITE.erl b/lib/kernel/test/wrap_log_reader_SUITE.erl
index 9a93b9037f..c797354a3e 100644
--- a/lib/kernel/test/wrap_log_reader_SUITE.erl
+++ b/lib/kernel/test/wrap_log_reader_SUITE.erl
@@ -20,7 +20,7 @@
-module(wrap_log_reader_SUITE).
-%-define(debug, true).
+%%-define(debug, true).
-ifdef(debug).
-define(format(S, A), io:format(S, A)).
@@ -29,9 +29,9 @@
-define(config(X,Y), foo).
-define(t,test_server).
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(format(S, A), ok).
--define(privdir(Conf), ?config(priv_dir, Conf)).
+-define(privdir(Conf), proplists:get_value(priv_dir, Conf)).
-endif.
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -47,7 +47,9 @@
-export([init_per_testcase/2, end_per_testcase/2]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[no_file, {group, one}, {group, two}, {group, four},
@@ -71,75 +73,70 @@ end_per_group(_GroupName, Config) ->
Config.
-init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Dog=?t:timetrap(?t:seconds(60)),
- [{watchdog, Dog} | Config].
+init_per_testcase(Func, Config) ->
+ Config.
end_per_testcase(_Func, _Config) ->
- Dog=?config(watchdog, _Config),
- ?t:timetrap_cancel(Dog).
+ ok.
-no_file(suite) -> [];
-no_file(doc) -> ["No log file exists"];
+%% No log file exists.
no_file(Conf) when is_list(Conf) ->
- ?line code:add_path(?config(data_dir,Conf)),
+ code:add_path(proplists:get_value(data_dir,Conf)),
Dir = ?privdir(Conf),
File = join(Dir, "sune.LOG"),
delete_files(File),
start(),
wlt ! {open, self(), File},
- ?line rec({error, {index_file_not_found, File}}, ?LINE),
+ rec({error, {index_file_not_found, File}}, ?LINE),
wlt ! {open, self(), File, 1},
- ?line rec({error, {index_file_not_found, File}}, ?LINE),
+ rec({error, {index_file_not_found, File}}, ?LINE),
wlt ! {open, self(), File, 4},
- ?line rec({error, {index_file_not_found, File}}, ?LINE),
+ rec({error, {index_file_not_found, File}}, ?LINE),
stop(),
delete_files(File),
ok.
-one_empty(suite) -> [];
-one_empty(doc) -> ["One empty index file"];
+%% One empty index file.
one_empty(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = join(Dir, "sune.LOG"),
delete_files(File),
start(),
- ?line open(sune, File, ?LINE),
+ open(sune, File, ?LINE),
%% open
- ?line do_chunk([{open,File}, eof], wlt, ?LINE),
- ?line do_chunk([{open,File,1}, eof], wlt, ?LINE),
+ do_chunk([{open,File}, eof], wlt, ?LINE),
+ do_chunk([{open,File,1}, eof], wlt, ?LINE),
wlt ! {open, self(), File, 2},
- ?line rec({error, {file_not_found, add_ext(File, 2)}}, ?LINE),
- ?line close(sune),
+ rec({error, {file_not_found, add_ext(File, 2)}}, ?LINE),
+ close(sune),
%% closed
- ?line do_chunk([{open,File}, eof], wlt, ?LINE),
- ?line do_chunk([{open,File,1}, eof], wlt, ?LINE),
+ do_chunk([{open,File}, eof], wlt, ?LINE),
+ do_chunk([{open,File,1}, eof], wlt, ?LINE),
wlt ! {open, self(), File, 2},
- ?line rec({error, {file_not_found, add_ext(File, 2)}}, ?LINE),
+ rec({error, {file_not_found, add_ext(File, 2)}}, ?LINE),
stop(),
delete_files(File),
ok.
-one_filled(suite) -> [];
-one_filled(doc) -> ["One filled index file"];
+%% One filled index file.
one_filled(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = join(Dir, "sune.LOG"),
delete_files(File),
start(),
- ?line open(sune, File, ?LINE),
- ?line log_terms(sune, ["first round, one", "first round, two"]),
- ?line sync(sune),
+ open(sune, File, ?LINE),
+ log_terms(sune, ["first round, one", "first round, two"]),
+ sync(sune),
%% open
test_one(File),
- ?line close(sune),
+ close(sune),
%% closed
test_one(File),
@@ -148,34 +145,33 @@ one_filled(Conf) when is_list(Conf) ->
ok.
test_one(File) ->
- ?line do_chunk([{open,File},
- {chunk, ["first round, one", "first round, two"]},
- eof], wlt, ?LINE),
- ?line do_chunk([{open,File,1},
- {chunk, ["first round, one", "first round, two"]},
- eof], wlt, ?LINE),
+ do_chunk([{open,File},
+ {chunk, ["first round, one", "first round, two"]},
+ eof], wlt, ?LINE),
+ do_chunk([{open,File,1},
+ {chunk, ["first round, one", "first round, two"]},
+ eof], wlt, ?LINE),
wlt ! {open, self(), File, 2},
- ?line rec({error, {file_not_found, add_ext(File, 2)}}, ?LINE),
- ?line do_chunk([{open,File,1}, {chunk, 1, ["first round, one"]},
- {chunk, 1, ["first round, two"]}, eof], wlt, ?LINE),
+ rec({error, {file_not_found, add_ext(File, 2)}}, ?LINE),
+ do_chunk([{open,File,1}, {chunk, 1, ["first round, one"]},
+ {chunk, 1, ["first round, two"]}, eof], wlt, ?LINE),
ok.
-two_filled(suite) -> [];
-two_filled(doc) -> ["Two filled index files"];
+%% Two filled index files.
two_filled(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = list_to_atom(join(Dir, "sune.LOG")),
delete_files(File),
start(),
- ?line open(sune, File, ?LINE),
- ?line log_terms(sune, ["first round, 11", "first round, 12"]),
- ?line log_terms(sune, ["first round, 21", "first round, 22"]),
- ?line sync(sune),
+ open(sune, File, ?LINE),
+ log_terms(sune, ["first round, 11", "first round, 12"]),
+ log_terms(sune, ["first round, 21", "first round, 22"]),
+ sync(sune),
%% open
test_two(File),
- ?line close(sune),
+ close(sune),
%% closed
test_two(File),
@@ -184,37 +180,36 @@ two_filled(Conf) when is_list(Conf) ->
ok.
test_two(File) ->
- ?line do_chunk([{open,File},
- {chunk, infinity, ["first round, 11", "first round, 12"]},
- {chunk, ["first round, 21", "first round, 22"]},
- eof], wlt, ?LINE),
- ?line do_chunk([{open,File,1},
- {chunk, ["first round, 11", "first round, 12"]},
- eof], wlt, ?LINE),
- ?line do_chunk([{open,File,2},
- {chunk, ["first round, 21", "first round, 22"]},
- eof], wlt, ?LINE),
+ do_chunk([{open,File},
+ {chunk, infinity, ["first round, 11", "first round, 12"]},
+ {chunk, ["first round, 21", "first round, 22"]},
+ eof], wlt, ?LINE),
+ do_chunk([{open,File,1},
+ {chunk, ["first round, 11", "first round, 12"]},
+ eof], wlt, ?LINE),
+ do_chunk([{open,File,2},
+ {chunk, ["first round, 21", "first round, 22"]},
+ eof], wlt, ?LINE),
wlt ! {open, self(), File, 3},
- ?line rec({error, {file_not_found, add_ext(File, 3)}}, ?LINE),
- ?line do_chunk([{open,File,1}, {chunk, 1, ["first round, 11"]},
- {chunk, 2, ["first round, 12"]}, eof], wlt, ?LINE),
+ rec({error, {file_not_found, add_ext(File, 3)}}, ?LINE),
+ do_chunk([{open,File,1}, {chunk, 1, ["first round, 11"]},
+ {chunk, 2, ["first round, 12"]}, eof], wlt, ?LINE),
ok.
-four_filled(suite) -> [];
-four_filled(doc) -> ["Four filled index files"];
+%% Four filled index files.
four_filled(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = join(Dir, "sune.LOG"),
delete_files(File),
start(),
- ?line open(sune, File, ?LINE),
- ?line init_files(0),
- ?line sync(sune),
+ open(sune, File, ?LINE),
+ init_files(0),
+ sync(sune),
%% open
test_four(File),
- ?line close(sune),
+ close(sune),
%% closed
test_four(File),
@@ -223,42 +218,41 @@ four_filled(Conf) when is_list(Conf) ->
ok.
test_four(File) ->
- ?line do_chunk([{open,File},
- {chunk, ["first round, 11", "first round, 12"]},
- {chunk, ["first round, 21", "first round, 22"]},
- {chunk, ["first round, 31", "first round, 32"]},
- {chunk, ["first round, 41", "first round, 42"]},
- eof], wlt, ?LINE),
- ?line do_chunk([{open,File,1},
- {chunk, ["first round, 11", "first round, 12"]},
- eof], wlt, ?LINE),
- ?line do_chunk([{open,File,4},
- {chunk, ["first round, 41", "first round, 42"]},
- eof], wlt, ?LINE),
+ do_chunk([{open,File},
+ {chunk, ["first round, 11", "first round, 12"]},
+ {chunk, ["first round, 21", "first round, 22"]},
+ {chunk, ["first round, 31", "first round, 32"]},
+ {chunk, ["first round, 41", "first round, 42"]},
+ eof], wlt, ?LINE),
+ do_chunk([{open,File,1},
+ {chunk, ["first round, 11", "first round, 12"]},
+ eof], wlt, ?LINE),
+ do_chunk([{open,File,4},
+ {chunk, ["first round, 41", "first round, 42"]},
+ eof], wlt, ?LINE),
wlt ! {open, self(), File, 5},
- ?line rec({error, {file_not_found, add_ext(File, 5)}}, ?LINE),
- ?line do_chunk([{open,File,1}, {chunk, 1, ["first round, 11"]},
- {chunk, 2, ["first round, 12"]}, eof], wlt, ?LINE),
- ?line do_chunk([{open,File,4}, {chunk, 1, ["first round, 41"]},
- {chunk, 2, ["first round, 42"]}, eof], wlt, ?LINE),
+ rec({error, {file_not_found, add_ext(File, 5)}}, ?LINE),
+ do_chunk([{open,File,1}, {chunk, 1, ["first round, 11"]},
+ {chunk, 2, ["first round, 12"]}, eof], wlt, ?LINE),
+ do_chunk([{open,File,4}, {chunk, 1, ["first round, 41"]},
+ {chunk, 2, ["first round, 42"]}, eof], wlt, ?LINE),
ok.
-wrap_filled(suite) -> [];
-wrap_filled(doc) -> ["First wrap, open, filled index file"];
+%% First wrap, open, filled index file.
wrap_filled(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = join(Dir, "sune.LOG"),
delete_files(File),
start(),
- ?line open(sune, File, ?LINE),
- ?line init_files(0),
- ?line log_terms(sune, ["second round, 11", "second round, 12"]),
- ?line sync(sune),
+ open(sune, File, ?LINE),
+ init_files(0),
+ log_terms(sune, ["second round, 11", "second round, 12"]),
+ sync(sune),
%% open
test_wrap(File),
- ?line close(sune),
+ close(sune),
%% closed
test_wrap(File),
@@ -267,103 +261,100 @@ wrap_filled(Conf) when is_list(Conf) ->
ok.
test_wrap(File) ->
- ?line do_chunk([{open,File},
- {chunk, ["first round, 21", "first round, 22"]},
- {chunk, ["first round, 31", "first round, 32"]},
- {chunk, ["first round, 41", "first round, 42"]},
- {chunk, ["second round, 11", "second round, 12"]},
- eof], wlt, ?LINE),
- ?line do_chunk([{open,File,1},
- {chunk, ["second round, 11", "second round, 12"]},
- eof], wlt, ?LINE),
- ?line do_chunk([{open,File,2},
- {chunk, ["first round, 21", "first round, 22"]},
- eof], wlt, ?LINE),
+ do_chunk([{open,File},
+ {chunk, ["first round, 21", "first round, 22"]},
+ {chunk, ["first round, 31", "first round, 32"]},
+ {chunk, ["first round, 41", "first round, 42"]},
+ {chunk, ["second round, 11", "second round, 12"]},
+ eof], wlt, ?LINE),
+ do_chunk([{open,File,1},
+ {chunk, ["second round, 11", "second round, 12"]},
+ eof], wlt, ?LINE),
+ do_chunk([{open,File,2},
+ {chunk, ["first round, 21", "first round, 22"]},
+ eof], wlt, ?LINE),
wlt ! {open, self(), File, 5},
- ?line rec({error, {file_not_found, add_ext(File, 5)}}, ?LINE),
- ?line do_chunk([{open,File,1}, {chunk, 1, ["second round, 11"]},
- {chunk, 2, ["second round, 12"]}, eof], wlt, ?LINE),
- ?line do_chunk([{open,File,4}, {chunk, 1, ["first round, 41"]},
- {chunk, 2, ["first round, 42"]}, eof], wlt, ?LINE),
+ rec({error, {file_not_found, add_ext(File, 5)}}, ?LINE),
+ do_chunk([{open,File,1}, {chunk, 1, ["second round, 11"]},
+ {chunk, 2, ["second round, 12"]}, eof], wlt, ?LINE),
+ do_chunk([{open,File,4}, {chunk, 1, ["first round, 41"]},
+ {chunk, 2, ["first round, 42"]}, eof], wlt, ?LINE),
ok.
-wrapping(suite) -> [];
-wrapping(doc) -> ["Wrapping at the same time as reading"];
+%% Wrapping at the same time as reading.
wrapping(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = join(Dir, "sune.LOG"),
delete_files(File),
start(),
- ?line open(sune, File, ?LINE),
- ?line init_files(1100),
- ?line sync(sune),
- ?line C1 =
+ open(sune, File, ?LINE),
+ init_files(1100),
+ sync(sune),
+ C1 =
do_chunk([{open,File}, {chunk, 1, ["first round, 11"]}], wlt, ?LINE),
- ?line log_terms(sune, ["second round, 11", "second round, 12"]),
- ?line sync(sune),
- ?line do_chunk([{chunk, 1, ["first round, 12"]},
- %% Here two bad bytes are found.
- {chunk, ["first round, 21", "first round, 22"]},
- {chunk, ["first round, 31", "first round, 32"]},
- {chunk, ["first round, 41", "first round, 42"]}, eof],
- wlt, ?LINE, C1),
+ log_terms(sune, ["second round, 11", "second round, 12"]),
+ sync(sune),
+ do_chunk([{chunk, 1, ["first round, 12"]},
+ %% Here two bad bytes are found.
+ {chunk, ["first round, 21", "first round, 22"]},
+ {chunk, ["first round, 31", "first round, 32"]},
+ {chunk, ["first round, 41", "first round, 42"]}, eof],
+ wlt, ?LINE, C1),
start(),
delete_files(File),
- ?line open(sune, File, ?LINE),
- ?line init_files(1100),
- ?line sync(sune),
- ?line C2 =
+ open(sune, File, ?LINE),
+ init_files(1100),
+ sync(sune),
+ C2 =
do_chunk([{open,File}, {chunk, 1, ["first round, 11"]}], wlt, ?LINE),
- ?line log_terms(sune, ["second round, 11", "second round, 12"]),
- ?line close(sune),
- ?line do_chunk([{chunk, 1, ["first round, 12"]},
- %% Here two bad bytes are found.
- {chunk, ["first round, 21", "first round, 22"]},
- {chunk, ["first round, 31", "first round, 32"]},
- {chunk, ["first round, 41", "first round, 42"]}, eof],
- wlt, ?LINE, C2),
+ log_terms(sune, ["second round, 11", "second round, 12"]),
+ close(sune),
+ do_chunk([{chunk, 1, ["first round, 12"]},
+ %% Here two bad bytes are found.
+ {chunk, ["first round, 21", "first round, 22"]},
+ {chunk, ["first round, 31", "first round, 32"]},
+ {chunk, ["first round, 41", "first round, 42"]}, eof],
+ wlt, ?LINE, C2),
start(),
delete_files(File),
- ?line open(sune, File, ?LINE),
- ?line init_files(1100),
- ?line sync(sune),
- ?line C3 = do_chunk([{open,File}], wlt, ?LINE),
- ?line log_terms(sune, ["second round, 11"]),
- ?line sync(sune),
- ?line do_chunk([{chunk, 1, ["second round, 11"]},
- {chunk, 1, ["first round, 21"]},
- {chunk, 1, ["first round, 22"]},
- {chunk, ["first round, 31", "first round, 32"]},
- {chunk, ["first round, 41", "first round, 42"]}, eof],
- wlt, ?LINE, C3),
+ open(sune, File, ?LINE),
+ init_files(1100),
+ sync(sune),
+ C3 = do_chunk([{open,File}], wlt, ?LINE),
+ log_terms(sune, ["second round, 11"]),
+ sync(sune),
+ do_chunk([{chunk, 1, ["second round, 11"]},
+ {chunk, 1, ["first round, 21"]},
+ {chunk, 1, ["first round, 22"]},
+ {chunk, ["first round, 31", "first round, 32"]},
+ {chunk, ["first round, 41", "first round, 42"]}, eof],
+ wlt, ?LINE, C3),
stop(),
delete_files(File),
ok.
-external(suite) -> [];
-external(doc) -> ["External format"];
+%% External format.
external(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = join(Dir, "sune.LOG"),
delete_files(File),
start(),
- ?line open_ext(sune, File, ?FILE),
- ?line init_files_ext(0),
- ?line close(sune),
+ open_ext(sune, File, ?FILE),
+ init_files_ext(0),
+ close(sune),
P0 = pps(),
wlt ! {open, self(), File},
- ?line rec({error, {not_a_log_file, add_ext(File, 1)}}, ?LINE),
- ?line true = (P0 == pps()),
+ rec({error, {not_a_log_file, add_ext(File, 1)}}, ?LINE),
+ true = (P0 == pps()),
stop(),
delete_files(File),
ok.
-error(suite) -> [];
-error(doc) -> ["Error situations"];
+%% Error situations.
error(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
File = join(Dir, "sune.LOG"),
@@ -372,69 +363,69 @@ error(Conf) when is_list(Conf) ->
P0 = pps(),
wlt ! {open, self(), File, 1},
- ?line rec({error, {index_file_not_found, File}}, ?LINE),
+ rec({error, {index_file_not_found, File}}, ?LINE),
wlt ! {open, self(), File},
- ?line rec({error, {index_file_not_found, File}}, ?LINE),
- ?line true = (P0 == pps()),
+ rec({error, {index_file_not_found, File}}, ?LINE),
+ true = (P0 == pps()),
- ?line open(sune, File, ?LINE),
- ?line close(sune),
+ open(sune, File, ?LINE),
+ close(sune),
P1 = pps(),
- ?line First = add_ext(File, 1),
- ?line ok = file:delete(First),
+ First = add_ext(File, 1),
+ ok = file:delete(First),
wlt ! {open, self(), File},
- ?line rec({error, {not_a_log_file, First}}, ?LINE),
- ?line true = (P1 == pps()),
+ rec({error, {not_a_log_file, First}}, ?LINE),
+ true = (P1 == pps()),
delete_files(File),
- ?line open(sune, File, ?LINE),
- ?line init_files(0),
- ?line close(sune),
+ open(sune, File, ?LINE),
+ init_files(0),
+ close(sune),
P2 = pps(),
- ?line C = do_chunk([{open,File},
- {chunk, ["first round, 11", "first round, 12"]}],
- wlt, ?LINE),
- ?line Second = add_ext(File, 2),
- ?line ok = file:delete(Second),
+ C = do_chunk([{open,File},
+ {chunk, ["first round, 11", "first round, 12"]}],
+ wlt, ?LINE),
+ Second = add_ext(File, 2),
+ ok = file:delete(Second),
wlt ! {chunk, self(), C},
- ?line rec({error, {file_error, Second, {error, enoent}}}, ?LINE),
- ?line ok = file:write_file(Second, <<17:(3*8)>>), % three bytes
+ rec({error, {file_error, Second, {error, enoent}}}, ?LINE),
+ ok = file:write_file(Second, <<17:(3*8)>>), % three bytes
wlt ! {chunk, self(), C},
- ?line rec({error, {not_a_log_file, Second}}, ?LINE),
- ?line do_chunk([close], wlt, ?LINE, C),
- ?line true = (P2 == pps()),
+ rec({error, {not_a_log_file, Second}}, ?LINE),
+ do_chunk([close], wlt, ?LINE, C),
+ true = (P2 == pps()),
delete_files(File),
- ?line open(sune, File, ?LINE),
- ?line init_files(0),
- ?line close(sune),
+ open(sune, File, ?LINE),
+ init_files(0),
+ close(sune),
P3 = pps(),
timer:sleep(1100),
Now = calendar:local_time(),
- ?line ok = file:change_time(First, Now),
- ?line C2 = do_chunk([{open,File},
- {chunk, ["first round, 11", "first round, 12"]}],
- wlt, ?LINE),
+ ok = file:change_time(First, Now),
+ C2 = do_chunk([{open,File},
+ {chunk, ["first round, 11", "first round, 12"]}],
+ wlt, ?LINE),
wlt ! {chunk, self(), C2},
- ?line rec({error,{is_wrapped,First}}, ?LINE),
- ?line do_chunk([close], wlt, ?LINE, C2),
+ rec({error,{is_wrapped,First}}, ?LINE),
+ do_chunk([close], wlt, ?LINE, C2),
IndexFile = add_ext(File, idx),
- ?line ok = file:write_file(IndexFile, <<17:(3*8)>>),
+ ok = file:write_file(IndexFile, <<17:(3*8)>>),
wlt ! {open, self(), File, 1},
- ?line rec({error, {index_file_not_found, File}}, ?LINE),
- ?line true = (P3 == pps()),
+ rec({error, {index_file_not_found, File}}, ?LINE),
+ true = (P3 == pps()),
stop(),
delete_files(File),
ok.
start() ->
- ?line ok = wrap_log_test:stop(),
+ ok = wrap_log_test:stop(),
dl_wait(),
- ?line ok = wrap_log_test:init().
+ ok = wrap_log_test:init().
stop() ->
- ?line ok = wrap_log_test:stop(),
+ ok = wrap_log_test:stop(),
dl_wait().
%% Give disk logs opened by 'logger' and 'wlt' time to close after
@@ -458,24 +449,24 @@ delete_files(File) ->
ok.
init_files(Delay) ->
- ?line log_terms(sune, ["first round, 11", "first round, 12"]),
+ log_terms(sune, ["first round, 11", "first round, 12"]),
timer:sleep(Delay),
- ?line log_terms(sune, ["first round, 21", "first round, 22"]),
+ log_terms(sune, ["first round, 21", "first round, 22"]),
timer:sleep(Delay),
- ?line log_terms(sune, ["first round, 31", "first round, 32"]),
+ log_terms(sune, ["first round, 31", "first round, 32"]),
timer:sleep(Delay),
- ?line log_terms(sune, ["first round, 41", "first round, 42"]),
+ log_terms(sune, ["first round, 41", "first round, 42"]),
timer:sleep(Delay),
ok.
init_files_ext(Delay) ->
- ?line blog_terms(sune, ["first round, 11", "first round, 12"]),
+ blog_terms(sune, ["first round, 11", "first round, 12"]),
timer:sleep(Delay),
- ?line blog_terms(sune, ["first round, 21", "first round, 22"]),
+ blog_terms(sune, ["first round, 21", "first round, 22"]),
timer:sleep(Delay),
- ?line blog_terms(sune, ["first round, 31", "first round, 32"]),
+ blog_terms(sune, ["first round, 31", "first round, 32"]),
timer:sleep(Delay),
- ?line blog_terms(sune, ["first round, 41", "first round, 42"]),
+ blog_terms(sune, ["first round, 41", "first round, 42"]),
timer:sleep(Delay),
ok.
@@ -487,27 +478,27 @@ do_chunk(Commands, Server, Where) ->
do_chunk([{open, File, One} | Cs], S, W, _C) ->
S ! {open, self(), File, One},
- ?line NC = rec1(ok, {W,?LINE}),
+ NC = rec1(ok, {W,?LINE}),
do_chunk(Cs, S, W, NC);
do_chunk([{open, File} | Cs], S, W, _C) ->
S ! {open, self(), File},
- ?line NC = rec1(ok, {W,?LINE}),
+ NC = rec1(ok, {W,?LINE}),
do_chunk(Cs, S, W, NC);
do_chunk([{chunk, Terms} | Cs], S, W, C) ->
S ! {chunk, self(), C},
- ?line NC = rec2(Terms, {W,?LINE}),
+ NC = rec2(Terms, {W,?LINE}),
do_chunk(Cs, S, W, NC);
do_chunk([{chunk, N, Terms} | Cs], S, W, C) ->
S ! {chunk, self(), C, N},
- ?line NC = rec2(Terms, {W,?LINE}),
+ NC = rec2(Terms, {W,?LINE}),
do_chunk(Cs, S, W, NC);
do_chunk([eof], S, W, C) ->
S ! {chunk, self(), C},
- ?line C1 = rec2(eof, {W,?LINE}),
+ C1 = rec2(eof, {W,?LINE}),
do_chunk([close], S, W, C1);
do_chunk([close], S, W, C) ->
S ! {close, self(), C},
- ?line rec(ok, {W,?LINE});
+ rec(ok, {W,?LINE});
do_chunk([], _S, _W, C) ->
C.
@@ -542,24 +533,24 @@ blog_terms(File, Terms) ->
rec1(M, Where) ->
receive
{M, C} -> C;
- Else -> test_server:fail({error, {Where, Else}})
- after 1000 -> test_server:fail({error, {Where, time_out}})
+ Else -> ct:fail({error, {Where, Else}})
+ after 1000 -> ct:fail({error, {Where, time_out}})
end.
rec2(M, Where) ->
receive
{C, M} -> C;
- Else -> test_server:fail({error, {Where, Else}})
- after 1000 -> test_server:fail({error, {Where, time_out}})
+ Else -> ct:fail({error, {Where, Else}})
+ after 1000 -> ct:fail({error, {Where, time_out}})
end.
rec(M, Where) ->
receive
M ->
ok;
- Else -> ?t:fail({error, {Where, Else}})
- after 5000 -> ?t:fail({error, {Where, time_out}})
+ Else -> ct:fail({error, {Where, Else}})
+ after 5000 -> ct:fail({error, {Where, time_out}})
end.
-
+
pps() ->
{erlang:ports(), lists:filter(fun erlang:is_process_alive/1, processes())}.
diff --git a/lib/kernel/test/zlib_SUITE.erl b/lib/kernel/test/zlib_SUITE.erl
index 6aaa024a82..97e1e2caa5 100644
--- a/lib/kernel/test/zlib_SUITE.erl
+++ b/lib/kernel/test/zlib_SUITE.erl
@@ -20,7 +20,7 @@
-module(zlib_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-compile(export_all).
@@ -47,11 +47,10 @@
-define(DATA_ERROR, {'EXIT',{data_error,[{zlib,_,_,_}|_]}}).
init_per_testcase(_Func, Config) ->
- Dog = test_server:timetrap(test_server:seconds(60)),
- [{watchdog, Dog}|Config].
-end_per_testcase(_Func, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog).
+ Config.
+
+end_per_testcase(_Func, _Config) ->
+ ok.
error(Format, Args, File, Line) ->
io:format("~p:~p: ERROR: " ++ Format, [File,Line|Args]),
@@ -70,7 +69,9 @@ error(Format, Args, File, Line) ->
%% end,
%% log("<>ERROR<>~n" ++ Format, Args, File, Line).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[{group, api}, {group, examples}, {group, func}, smp,
@@ -106,80 +107,78 @@ end_per_group(_GroupName, Config) ->
-api_open_close(doc) -> "Test open/0 and close/1";
-api_open_close(suite) -> [];
+%% Test open/0 and close/1.
api_open_close(Config) when is_list(Config) ->
- ?line Fd1 = zlib:open(),
- ?line Fd2 = zlib:open(),
+ Fd1 = zlib:open(),
+ Fd2 = zlib:open(),
?m(false,Fd1 == Fd2),
?m(ok,zlib:close(Fd1)),
?m(?BARG, zlib:close(Fd1)),
?m(ok,zlib:close(Fd2)),
-
+
%% Make sure that we don't get any EXIT messages if trap_exit is enabled.
- ?line process_flag(trap_exit, true),
- ?line Fd3 = zlib:open(),
+ process_flag(trap_exit, true),
+ Fd3 = zlib:open(),
?m(ok,zlib:close(Fd3)),
receive
- Any -> ?line ?t:fail({unexpected_message,Any})
+ Any -> ct:fail({unexpected_message,Any})
after 10 -> ok
end.
-api_deflateInit(doc) -> "Test deflateInit/2 and /6";
-api_deflateInit(suite) -> [];
+%% Test deflateInit/2 and /6.
api_deflateInit(Config) when is_list(Config) ->
- ?line Z1 = zlib:open(),
+ Z1 = zlib:open(),
?m(?BARG, zlib:deflateInit(gurka, none)),
?m(?BARG, zlib:deflateInit(gurka, gurka)),
?m(?BARG, zlib:deflateInit(Z1, gurka)),
Levels = [none, default, best_speed, best_compression] ++ lists:seq(0,9),
lists:foreach(fun(Level) ->
- ?line Z = zlib:open(),
+ Z = zlib:open(),
?m(ok, zlib:deflateInit(Z, Level)),
?m(ok,zlib:close(Z))
end, Levels),
%% /6
?m(?BARG, zlib:deflateInit(Z1,gurka,deflated,-15,8,default)),
-
+
?m(?BARG, zlib:deflateInit(Z1,default,undefined,-15,8,default)),
-
+
?m(?BARG, zlib:deflateInit(Z1,default,deflated,48,8,default)),
?m(?BARG, zlib:deflateInit(Z1,default,deflated,-20,8,default)),
?m(?BARG, zlib:deflateInit(Z1,default,deflated,-7,8,default)),
?m(?BARG, zlib:deflateInit(Z1,default,deflated,7,8,default)),
-
+
?m(?BARG, zlib:deflateInit(Z1,default,deflated,-15,0,default)),
?m(?BARG, zlib:deflateInit(Z1,default,deflated,-15,10,default)),
-
+
?m(?BARG, zlib:deflateInit(Z1,default,deflated,-15,8,0)),
?m(?BARG, zlib:deflateInit(Z1,default,deflated,-15,8,undefined)),
-
+
lists:foreach(fun(Level) ->
- ?line Z = zlib:open(),
+ Z = zlib:open(),
?m(ok, zlib:deflateInit(Z, Level, deflated, -15, 8, default)),
?m(ok,zlib:close(Z))
end, Levels),
-
+
lists:foreach(fun(Wbits) ->
- ?line Z11 = zlib:open(),
+ Z11 = zlib:open(),
?m(ok, zlib:deflateInit(Z11,best_compression,deflated,
Wbits,8,default)),
- ?line Z12 = zlib:open(),
+ Z12 = zlib:open(),
?m(ok, zlib:deflateInit(Z12,default,deflated,-Wbits,8,default)),
?m(ok,zlib:close(Z11)),
?m(ok,zlib:close(Z12))
end, lists:seq(8, 15)),
-
+
lists:foreach(fun(MemLevel) ->
- ?line Z = zlib:open(),
+ Z = zlib:open(),
?m(ok, zlib:deflateInit(Z,default,deflated,-15,
MemLevel,default)),
?m(ok,zlib:close(Z))
end, lists:seq(1,8)),
-
+
Strategies = [filtered,huffman_only,rle,default],
lists:foreach(fun(Strategy) ->
- ?line Z = zlib:open(),
+ Z = zlib:open(),
?m(ok, zlib:deflateInit(Z,best_speed,deflated,-15,8,Strategy)),
?m(ok,zlib:close(Z))
end, Strategies),
@@ -187,10 +186,9 @@ api_deflateInit(Config) when is_list(Config) ->
?m({'EXIT',_}, zlib:deflateInit(Z1,none,deflated,-15,8,default)), %% ??
?m(ok, zlib:close(Z1)).
-api_deflateSetDictionary(doc) -> "Test deflateSetDictionary";
-api_deflateSetDictionary(suite) -> [];
+%% Test deflateSetDictionary.
api_deflateSetDictionary(Config) when is_list(Config) ->
- ?line Z1 = zlib:open(),
+ Z1 = zlib:open(),
?m(ok, zlib:deflateInit(Z1, default)),
?m(Id when is_integer(Id), zlib:deflateSetDictionary(Z1, <<1,1,2,3,4,5,1>>)),
?m(Id when is_integer(Id), zlib:deflateSetDictionary(Z1, [1,1,2,3,4,5,1])),
@@ -200,10 +198,9 @@ api_deflateSetDictionary(Config) when is_list(Config) ->
?m({'EXIT',{stream_error,_}},zlib:deflateSetDictionary(Z1,<<1,1,2,3,4,5,1>>)),
?m(ok, zlib:close(Z1)).
-api_deflateReset(doc) -> "Test deflateReset";
-api_deflateReset(suite) -> [];
+%% Test deflateReset.
api_deflateReset(Config) when is_list(Config) ->
- ?line Z1 = zlib:open(),
+ Z1 = zlib:open(),
?m(ok, zlib:deflateInit(Z1, default)),
?m(_, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)),
?m(ok, zlib:deflateReset(Z1)),
@@ -211,20 +208,18 @@ api_deflateReset(Config) when is_list(Config) ->
%% FIXME how do I make this go wrong??
?m(ok, zlib:close(Z1)).
-api_deflateParams(doc) -> "Test deflateParams";
-api_deflateParams(suite) -> [];
+%% Test deflateParams.
api_deflateParams(Config) when is_list(Config) ->
- ?line Z1 = zlib:open(),
+ Z1 = zlib:open(),
?m(ok, zlib:deflateInit(Z1, default)),
?m(_, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)),
?m(ok, zlib:deflateParams(Z1, best_compression, huffman_only)),
?m(_, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, sync)),
?m(ok, zlib:close(Z1)).
-api_deflate(doc) -> "Test deflate";
-api_deflate(suite) -> [];
+%% Test deflate.
api_deflate(Config) when is_list(Config) ->
- ?line Z1 = zlib:open(),
+ Z1 = zlib:open(),
?m(ok, zlib:deflateInit(Z1, default)),
?m([B] when is_binary(B), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, finish)),
?m(ok, zlib:deflateReset(Z1)),
@@ -235,19 +230,18 @@ api_deflate(Config) when is_list(Config) ->
?m(B when is_list(B), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, sync)),
?m(B when is_list(B), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, full)),
?m(B when is_list(B), zlib:deflate(Z1, <<>>, finish)),
-
+
?m(?BARG, zlib:deflate(gurka, <<1,1,1,1,1,1,1,1,1>>, full)),
?m(?BARG, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, asdj)),
?m(?BARG, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, 198)),
%% Causes problems ERROR REPORT
?m(?BARG, zlib:deflate(Z1, [asdj,asd], none)),
-
+
?m(ok, zlib:close(Z1)).
-api_deflateEnd(doc) -> "Test deflateEnd";
-api_deflateEnd(suite) -> [];
+%% Test deflateEnd.
api_deflateEnd(Config) when is_list(Config) ->
- ?line Z1 = zlib:open(),
+ Z1 = zlib:open(),
?m(ok, zlib:deflateInit(Z1, default)),
?m(ok, zlib:deflateEnd(Z1)),
?m({'EXIT', {einval,_}}, zlib:deflateEnd(Z1)), %% ??
@@ -259,20 +253,19 @@ api_deflateEnd(Config) when is_list(Config) ->
?m(B when is_list(B), zlib:deflate(Z1, <<"Kilroy was here">>)),
?m(B when is_list(B), zlib:deflate(Z1, <<"Kilroy was here">>, finish)),
?m(ok, zlib:deflateEnd(Z1)),
-
+
?m(ok, zlib:close(Z1)).
-api_inflateInit(doc) -> "Test inflateInit /1 and /2";
-api_inflateInit(suite) -> [];
+%% Test inflateInit /1 and /2.
api_inflateInit(Config) when is_list(Config) ->
- ?line Z1 = zlib:open(),
+ Z1 = zlib:open(),
?m(?BARG, zlib:inflateInit(gurka)),
?m(ok, zlib:inflateInit(Z1)),
?m({'EXIT',{einval,_}}, zlib:inflateInit(Z1, 15)), %% ??
lists:foreach(fun(Wbits) ->
- ?line Z11 = zlib:open(),
+ Z11 = zlib:open(),
?m(ok, zlib:inflateInit(Z11,Wbits)),
- ?line Z12 = zlib:open(),
+ Z12 = zlib:open(),
?m(ok, zlib:inflateInit(Z12,-Wbits)),
?m(ok,zlib:close(Z11)),
?m(ok,zlib:close(Z12))
@@ -284,10 +277,9 @@ api_inflateInit(Config) when is_list(Config) ->
?m(?BARG, zlib:inflateInit(Z1, -16)),
?m(ok, zlib:close(Z1)).
-api_inflateSetDictionary(doc) -> "Test inflateSetDictionary";
-api_inflateSetDictionary(suite) -> [];
+%% Test inflateSetDictionary.
api_inflateSetDictionary(Config) when is_list(Config) ->
- ?line Z1 = zlib:open(),
+ Z1 = zlib:open(),
?m(ok, zlib:inflateInit(Z1)),
?m(?BARG, zlib:inflateSetDictionary(gurka,<<1,1,1,1,1>>)),
?m(?BARG, zlib:inflateSetDictionary(Z1,102)),
@@ -296,27 +288,26 @@ api_inflateSetDictionary(Config) when is_list(Config) ->
?m({'EXIT',{stream_error,_}}, zlib:inflateSetDictionary(Z1,Dict)),
?m(ok, zlib:close(Z1)).
-api_inflateSync(doc) -> "Test inflateSync";
-api_inflateSync(suite) -> [];
+%% Test inflateSync.
api_inflateSync(Config) when is_list(Config) ->
{skip,"inflateSync/1 sucks"}.
-%% ?line Z1 = zlib:open(),
+%% Z1 = zlib:open(),
%% ?m(ok, zlib:deflateInit(Z1)),
-%% ?line B1list0 = zlib:deflate(Z1, "gurkan gurra ger galna tunnor", full),
-%% ?line B2 = zlib:deflate(Z1, "grodan boll", finish),
+%% B1list0 = zlib:deflate(Z1, "gurkan gurra ger galna tunnor", full),
+%% B2 = zlib:deflate(Z1, "grodan boll", finish),
%% io:format("~p\n", [B1list0]),
%% io:format("~p\n", [B2]),
%% ?m(ok, zlib:deflateEnd(Z1)),
-%% ?line B1 = clobber(14, list_to_binary(B1list0)),
-%% ?line Compressed = list_to_binary([B1,B2]),
-%% ?line io:format("~p\n", [Compressed]),
+%% B1 = clobber(14, list_to_binary(B1list0)),
+%% Compressed = list_to_binary([B1,B2]),
+%% io:format("~p\n", [Compressed]),
%% ?m(ok, zlib:inflateInit(Z1)),
%% ?m(?BARG, zlib:inflateSync(gurka)),
%% ?m({'EXIT',{data_error,_}}, zlib:inflate(Z1, Compressed)),
%% ?m(ok, zlib:inflateSync(Z1)),
-%% ?line Ubs = zlib:inflate(Z1, []),
-%% ?line <<"grodan boll">> = list_to_binary(Ubs),
+%% Ubs = zlib:inflate(Z1, []),
+%% <<"grodan boll">> = list_to_binary(Ubs),
%% ?m(ok, zlib:close(Z1)).
clobber(N, Bin) when is_binary(Bin) ->
@@ -327,21 +318,19 @@ clobber(N, Bin) when is_binary(Bin) ->
end,
list_to_binary(tuple_to_list(setelement(N, T, Byte))).
-api_inflateReset(doc) -> "Test inflateReset";
-api_inflateReset(suite) -> [];
+%% Test inflateReset.
api_inflateReset(Config) when is_list(Config) ->
- ?line Z1 = zlib:open(),
+ Z1 = zlib:open(),
?m(ok, zlib:inflateInit(Z1)),
?m(?BARG, zlib:inflateReset(gurka)),
?m(ok, zlib:inflateReset(Z1)),
?m(ok, zlib:close(Z1)).
-api_inflate(doc) -> "Test inflate";
-api_inflate(suite) -> [];
+%% Test inflate.
api_inflate(Config) when is_list(Config) ->
Data = [<<1,2,2,3,3,3,4,4,4,4>>],
- ?line Compressed = zlib:compress(Data),
- ?line Z1 = zlib:open(),
+ Compressed = zlib:compress(Data),
+ Z1 = zlib:open(),
?m(ok, zlib:inflateInit(Z1)),
?m([], zlib:inflate(Z1, <<>>)),
?m(Data, zlib:inflate(Z1, Compressed)),
@@ -356,17 +345,16 @@ api_inflate(Config) when is_list(Config) ->
?m({'EXIT',{data_error,_}}, zlib:inflate(Z1, <<2,1,2,1,2>>)),
?m(ok, zlib:close(Z1)).
-api_inflateChunk(doc) -> "Test inflateChunk";
-api_inflateChunk(suite) -> [];
+%% Test inflateChunk.
api_inflateChunk(Config) when is_list(Config) ->
ChunkSize = 1024,
Data = << <<(I rem 150)>> || I <- lists:seq(1, 3 * ChunkSize) >>,
Part1 = binary:part(Data, 0, ChunkSize),
Part2 = binary:part(Data, ChunkSize, ChunkSize),
Part3 = binary:part(Data, ChunkSize * 2, ChunkSize),
- ?line Compressed = zlib:compress(Data),
- ?line Z1 = zlib:open(),
- ?line zlib:setBufSize(Z1, ChunkSize),
+ Compressed = zlib:compress(Data),
+ Z1 = zlib:open(),
+ zlib:setBufSize(Z1, ChunkSize),
?m(ok, zlib:inflateInit(Z1)),
?m([], zlib:inflateChunk(Z1, <<>>)),
?m({more, Part1}, zlib:inflateChunk(Z1, Compressed)),
@@ -379,7 +367,7 @@ api_inflateChunk(Config) when is_list(Config) ->
?m(ok, zlib:inflateReset(Z1)),
- ?line zlib:setBufSize(Z1, size(Data)),
+ zlib:setBufSize(Z1, size(Data)),
?m(Data, zlib:inflateChunk(Z1, Compressed)),
?m(ok, zlib:inflateEnd(Z1)),
@@ -389,10 +377,9 @@ api_inflateChunk(Config) when is_list(Config) ->
?m({'EXIT',{data_error,_}}, zlib:inflateEnd(Z1)),
?m(ok, zlib:close(Z1)).
-api_inflateEnd(doc) -> "Test inflateEnd";
-api_inflateEnd(suite) -> [];
+%% Test inflateEnd.
api_inflateEnd(Config) when is_list(Config) ->
- ?line Z1 = zlib:open(),
+ Z1 = zlib:open(),
?m({'EXIT',{einval,_}}, zlib:inflateEnd(Z1)),
?m(ok, zlib:inflateInit(Z1)),
?m(?BARG, zlib:inflateEnd(gurka)),
@@ -403,18 +390,16 @@ api_inflateEnd(Config) when is_list(Config) ->
?m(ok, zlib:inflateEnd(Z1)),
?m(ok, zlib:close(Z1)).
-api_getBufsz(doc) -> "Test getBufsz";
-api_getBufsz(suite) -> [];
+%% Test getBufsz.
api_getBufsz(Config) when is_list(Config) ->
- ?line Z1 = zlib:open(),
+ Z1 = zlib:open(),
?m(Val when is_integer(Val), zlib:getBufSize(Z1)),
?m(?BARG, zlib:getBufSize(gurka)),
?m(ok, zlib:close(Z1)).
-api_setBufsz(doc) -> "Test setBufsz";
-api_setBufsz(suite) -> [];
+%% Test setBufsz.
api_setBufsz(Config) when is_list(Config) ->
- ?line Z1 = zlib:open(),
+ Z1 = zlib:open(),
?m(?BARG, zlib:setBufSize(Z1, gurka)),
?m(?BARG, zlib:setBufSize(gurka, 1232330)),
Sz = ?m( Val when is_integer(Val), zlib:getBufSize(Z1)),
@@ -424,25 +409,23 @@ api_setBufsz(Config) when is_list(Config) ->
?m(ok, zlib:close(Z1)).
%%% Debug function ??
-api_getQSize(doc) -> "Test getQSize";
-api_getQSize(suite) -> [];
+%% Test getQSize.
api_getQSize(Config) when is_list(Config) ->
- ?line Z1 = zlib:open(),
+ Z1 = zlib:open(),
Q = ?m(Val when is_integer(Val), zlib:getQSize(Z1)),
io:format("QSize ~p ~n", [Q]),
?m(?BARG, zlib:getQSize(gurka)),
?m(ok, zlib:close(Z1)).
-api_crc32(doc) -> "Test crc32";
-api_crc32(suite) -> [];
+%% Test crc32.
api_crc32(Config) when is_list(Config) ->
- ?line Z1 = zlib:open(),
+ Z1 = zlib:open(),
?m(ok, zlib:deflateInit(Z1,best_speed,deflated,-15,8,default)),
Bin = <<1,1,1,1,1,1,1,1,1>>,
Compressed1 = ?m(_, zlib:deflate(Z1, Bin, none)),
Compressed2 = ?m(_, zlib:deflate(Z1, <<>>, finish)),
Compressed = list_to_binary(Compressed1 ++ Compressed2),
- CRC1 = ?m( CRC1 when is_integer(CRC1), zlib:crc32(Z1)),
+ CRC1 = ?m( CRC1 when is_integer(CRC1), zlib:crc32(Z1)),
?m(CRC1 when is_integer(CRC1), zlib:crc32(Z1,Bin)),
?m(CRC1 when is_integer(CRC1), zlib:crc32(Z1,binary_to_list(Bin))),
?m(CRC2 when is_integer(CRC2), zlib:crc32(Z1,Compressed)),
@@ -460,10 +443,9 @@ api_crc32(Config) when is_list(Config) ->
?m(ok, zlib:deflateEnd(Z1)),
?m(ok, zlib:close(Z1)).
-api_adler32(doc) -> "Test adler32";
-api_adler32(suite) -> [];
+%% Test adler32.
api_adler32(Config) when is_list(Config) ->
- ?line Z1 = zlib:open(),
+ Z1 = zlib:open(),
?m(ok, zlib:deflateInit(Z1,best_speed,deflated,-15,8,default)),
Bin = <<1,1,1,1,1,1,1,1,1>>,
Compressed1 = ?m(_, zlib:deflate(Z1, Bin, none)),
@@ -484,12 +466,11 @@ api_adler32(Config) when is_list(Config) ->
?m(ok, zlib:deflateEnd(Z1)),
?m(ok, zlib:close(Z1)).
-api_un_compress(doc) -> "Test compress";
-api_un_compress(suite) -> [];
+%% Test compress.
api_un_compress(Config) when is_list(Config) ->
?m(?BARG,zlib:compress(not_a_binary)),
Bin = <<1,11,1,23,45>>,
- ?line Comp = zlib:compress(Bin),
+ Comp = zlib:compress(Bin),
?m(?BARG,zlib:uncompress(not_a_binary)),
?m({'EXIT',{data_error,_}}, zlib:uncompress(<<171,171,171,171,171>>)),
?m({'EXIT',{data_error,_}}, zlib:uncompress(<<>>)),
@@ -501,58 +482,40 @@ api_un_compress(Config) when is_list(Config) ->
?m(Bin, zlib:uncompress(binary_to_list(Comp))),
?m(Bin, zlib:uncompress(Comp)).
-api_un_zip(doc) -> "Test zip";
-api_un_zip(suite) -> [];
+%% Test zip.
api_un_zip(Config) when is_list(Config) ->
?m(?BARG,zlib:zip(not_a_binary)),
Bin = <<1,11,1,23,45>>,
- ?line Comp = zlib:zip(Bin),
+ Comp = zlib:zip(Bin),
?m(Comp, zlib:zip(binary_to_list(Bin))),
?m(?BARG,zlib:unzip(not_a_binary)),
?m({'EXIT',{data_error,_}}, zlib:unzip(<<171,171,171,171,171>>)),
?m({'EXIT',{data_error,_}}, zlib:unzip(<<>>)),
?m(Bin, zlib:unzip(Comp)),
?m(Bin, zlib:unzip(binary_to_list(Comp))),
-
+
%% OTP-6396
B = <<131,104,19,100,0,13,99,95,99,105,100,95,99,115,103,115,110,95,50,97,1,107,0,4,208,161,246,29,107,0,3,237,166,224,107,0,6,66,240,153,0,2,10,1,0,8,97,116,116,97,99,104,101,100,104,2,100,0,22,117,112,100,97,116,101,95,112,100,112,95,99,111,110,116,101,120,116,95,114,101,113,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,197,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,5,0,33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,1,114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4,103,112,114,115,8,0,104,2,104,2,100,0,8,97,99,116,105,118,97,116,101,104,23,100,0,11,112,100,112,95,99,111,110,116,1,120,116,100,0,7,112,114,105,109,97,114,121,97,1,100,0,9,117,110,100,101,102,105,110,101,100,97,1,97,4,97,4,97,7,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,10100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,5,102,97,108,115,101,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,1,101,100,97,0,100,0,9,117,110,100,101,102,105,110,101,100,107,0,4,16,0,1,144,107,0,4,61,139,186,181,107,0,4,10,8,201,49,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,0,101,100,100,0,9,117,110,100,101,102,105,110,101,100,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,21,106,108,0,0,0,3,104,2,97,1,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,167,20,104,2,97,4,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,21,104,2,97,10,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,26,106,100,0,5,118,101,114,57,57,100,0,9,117,110,0,101,102,105,110,101,100,107,0,2,0,244,107,0,4,10,6,102,195,107,0,4,10,6,102,195,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,107,0,125,248,143,0,203,25115,157,116,65,185,65,172,55,87,164,88,225,50,203,251,115,157,116,65,185,65,172,55,87,164,88,225,50,0,0,82,153,50,0,200,98,87,148,237,193,185,65,149,167,69,144,14,16,153,50,3,81,70,94,13,109,193,1,120,5,181,113,198,118,50,3,81,70,94,13,109,193,185,120,5,181,113,198,118,153,3,81,70,94,13,109,193,185,120,5,181,113,198,118,153,50,16,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,113,92,2,119,128,0,0,108,0,0,1,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,11,97,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,0,33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,101,114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4,103,112,114,115,8,0,106>>,
Z = zlib:zip(B),
?m(B, zlib:unzip(Z)).
-%% api_g_un_zip_file(doc) -> "Test gunzip_file";
-%% api_g_un_zip_file(suite) -> [];
-%% api_g_un_zip_file(Config) when is_list(Config) ->
-%% ?line Out = conf(data_dir,Config),
-%% io:format("Using OutDir ~p ~n", [Out]),
-%% F = filename:join(Out,"testing1"),
-%% Data = <<1,1,255,255,255,1,1>>,
-%% ?m(ok, file:write_file(F,Data)),
-%% ?line Compressed = zlib:gzip_file(F),
-%% ?m(ok, file:write_file(F++".gz",Compressed)),
-%% ?m(Data, zlib:gunzip_file(F++".gz")),
-%% ?m({error,enoent}, zlib:gunzip_file(gurka)),
-%% ?m({error,enoent}, zlib:gzip_file(gurka)),
-%% ?m({error,what}, zlib:gunzip_file(F)),
-%% ?line ok.
-
-api_g_un_zip(doc) -> "Test gunzip";
-api_g_un_zip(suite) -> [];
+%% Test gunzip.
api_g_un_zip(Config) when is_list(Config) ->
?m(?BARG,zlib:gzip(not_a_binary)),
Bin = <<1,11,1,23,45>>,
- ?line Comp = zlib:gzip(Bin),
+ Comp = zlib:gzip(Bin),
?m(Comp, zlib:gzip(binary_to_list(Bin))),
?m(?BARG, zlib:gunzip(not_a_binary)),
?m(?DATA_ERROR, zlib:gunzip(<<171,171,171,171,171>>)),
?m(?DATA_ERROR, zlib:gunzip(<<>>)),
?m(Bin, zlib:gunzip(Comp)),
?m(Bin, zlib:gunzip(binary_to_list(Comp))),
-
+
%% Bad CRC; bad length.
BadCrc = bad_crc_data(),
- ?line ?m({'EXIT',{data_error,_}},(catch zlib:gunzip(BadCrc))),
+ ?m({'EXIT',{data_error,_}},(catch zlib:gunzip(BadCrc))),
BadLen = bad_len_data(),
- ?line ?m({'EXIT',{data_error,_}},(catch zlib:gunzip(BadLen))),
+ ?m({'EXIT',{data_error,_}},(catch zlib:gunzip(BadLen))),
ok.
bad_crc_data() ->
@@ -564,45 +527,42 @@ bad_len_data() ->
<<31,139,8,0,0,0,0,0,0,3,211,2,0,91,38,185,9,2,0,0,0>>.
-intro(suite) -> [];
-intro(doc) -> "";
intro(Config) when is_list(Config) ->
D = <<"This is a binary">>,
[put({ex, N}, <<"This is a binary">>) || N <- [0,1,2,3,4]],
put({ex, 5}, end_of_data),
put(ex,0),
- ?line Read = fun() ->
- N = get(ex),
- put(ex,N+1),
- get({ex,N})
- end,
-
- ?line Z = zlib:open(),
- ?line ok = zlib:deflateInit(Z,default),
-
- ?line Compress = fun(end_of_data, _Cont) -> [];
- (Data, Cont) ->
- [zlib:deflate(Z, Data)|Cont(Read(),Cont)]
- end,
- ?line Compressed = Compress(Read(),Compress),
- ?line Last = zlib:deflate(Z, [], finish),
- ?line ok = zlib:deflateEnd(Z),
- ?line zlib:close(Z),
- ?line Res = list_to_binary([Compressed|Last]),
+ Read = fun() ->
+ N = get(ex),
+ put(ex,N+1),
+ get({ex,N})
+ end,
+
+ Z = zlib:open(),
+ ok = zlib:deflateInit(Z,default),
+
+ Compress = fun(end_of_data, _Cont) -> [];
+ (Data, Cont) ->
+ [zlib:deflate(Z, Data)|Cont(Read(),Cont)]
+ end,
+ Compressed = Compress(Read(),Compress),
+ Last = zlib:deflate(Z, [], finish),
+ ok = zlib:deflateEnd(Z),
+ zlib:close(Z),
+ Res = list_to_binary([Compressed|Last]),
Orig = list_to_binary(lists:duplicate(5, D)),
?m(Orig, zlib:uncompress(Res)).
-large_deflate(doc) -> "Test deflate large file, which had a bug reported on erlang-bugs";
-large_deflate(suite) -> [];
+%% Test deflate large file, which had a bug reported on erlang-bugs.
large_deflate(Config) when is_list(Config) ->
large_deflate_do().
large_deflate_do() ->
- ?line Z = zlib:open(),
- ?line Plain = rand_bytes(zlib:getBufSize(Z)*5),
- ?line ok = zlib:deflateInit(Z),
- ?line _ZlibHeader = zlib:deflate(Z, [], full),
- ?line Deflated = zlib:deflate(Z, Plain, full),
+ Z = zlib:open(),
+ Plain = rand_bytes(zlib:getBufSize(Z)*5),
+ ok = zlib:deflateInit(Z),
+ _ZlibHeader = zlib:deflate(Z, [], full),
+ Deflated = zlib:deflate(Z, Plain, full),
?m(ok, zlib:close(Z)),
?m(Plain, zlib:unzip(list_to_binary([Deflated, 3, 0]))).
@@ -617,23 +577,22 @@ rand_bytes(Bin, Sz) ->
rand_bytes(<<(erlang:md5(Bin))/binary, Bin/binary>>, Sz).
-zip_usage(doc) -> "Test a standard compressed zip file";
-zip_usage(suite) -> [];
+%% Test a standard compressed zip file.
zip_usage(Config) when is_list(Config) ->
zip_usage(zip_usage({get_arg,Config}));
zip_usage({get_arg,Config}) ->
- ?line Out = conf(data_dir,Config),
- ?line {ok,ZIP} = file:read_file(filename:join(Out,"zipdoc.zip")),
- ?line {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")),
+ Out = conf(data_dir,Config),
+ {ok,ZIP} = file:read_file(filename:join(Out,"zipdoc.zip")),
+ {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")),
{run,ZIP,ORIG};
zip_usage({run,ZIP,ORIG}) ->
- ?line <<_:14/binary, CRC:32/little,
- CompSz:32/little, UnCompSz:32/little,_:31/binary,
- Compressed:CompSz/binary, _/binary>> = ZIP,
-
+ <<_:14/binary, CRC:32/little,
+ CompSz:32/little, UnCompSz:32/little,_:31/binary,
+ Compressed:CompSz/binary, _/binary>> = ZIP,
+
%%io:format("CRC ~p CSz ~p UnCSz ~p ~n", [CRC,CompSz,UnCompSz]),
- ?line Split = split_bin(Compressed,[]),
- ?line Z = zlib:open(),
+ Split = split_bin(Compressed,[]),
+ Z = zlib:open(),
?m(ok, zlib:inflateInit(Z, -15)),
Bs = [zlib:inflate(Z, Part) || Part <- Split],
@@ -643,86 +602,84 @@ zip_usage({run,ZIP,ORIG}) ->
?m(true, zlib:crc32(Z,UC0) == zlib:crc32(Z,ORIG)),
?m(ok, zlib:inflateEnd(Z)),
- ?line UC1 = zlib:unzip(Compressed),
+ UC1 = zlib:unzip(Compressed),
?m(UnCompSz, byte_size(UC1)),
?m(true, zlib:crc32(Z,UC1) == zlib:crc32(Z,ORIG)),
-
+
?m(ok, zlib:inflateInit(Z, -15)),
- ?line UC2 = zlib:inflate(Z, Compressed),
+ UC2 = zlib:inflate(Z, Compressed),
?m(UnCompSz, byte_size(list_to_binary(UC2))),
?m(CRC, zlib:crc32(Z)),
?m(true, zlib:crc32(Z,UC2) == zlib:crc32(Z,ORIG)),
?m(ok, zlib:inflateEnd(Z)),
-
+
?m(ok, zlib:inflateInit(Z, -15)),
- ?line UC3 = zlib:inflate(Z, Split), % Test multivec.
+ UC3 = zlib:inflate(Z, Split), % Test multivec.
?m(UnCompSz, byte_size(list_to_binary(UC3))),
?m(true, zlib:crc32(Z,UC3) == zlib:crc32(Z,ORIG)),
?m(CRC, zlib:crc32(Z)),
?m(ok, zlib:inflateEnd(Z)),
-
+
?m(ok, zlib:inflateInit(Z, -15)),
?m(ok, zlib:setBufSize(Z, UnCompSz *2)),
- ?line UC4 = zlib:inflate(Z, Compressed),
+ UC4 = zlib:inflate(Z, Compressed),
?m(UnCompSz, byte_size(list_to_binary(UC4))),
?m(CRC, zlib:crc32(Z)),
?m(CRC, zlib:crc32(Z,UC4)),
?m(true, zlib:crc32(Z,UC4) == zlib:crc32(Z,ORIG)),
?m(ok, zlib:inflateEnd(Z)),
-
- ?line C1 = zlib:zip(ORIG),
- ?line UC5 = zlib:unzip(C1),
+
+ C1 = zlib:zip(ORIG),
+ UC5 = zlib:unzip(C1),
?m(CRC, zlib:crc32(Z,UC5)),
?m(true,zlib:crc32(Z,UC5) == zlib:crc32(Z,ORIG)),
-
+
?m(ok, zlib:deflateInit(Z, default, deflated, -15, 8, default)),
- ?line C2 = zlib:deflate(Z, ORIG, finish),
+ C2 = zlib:deflate(Z, ORIG, finish),
?m(true, C1 == list_to_binary(C2)),
?m(ok, zlib:deflateEnd(Z)),
-
+
?m(ok, zlib:deflateInit(Z, none, deflated, -15, 8, filtered)),
?m(ok, zlib:deflateParams(Z, default, default)),
- ?line C3 = zlib:deflate(Z, ORIG, finish),
+ C3 = zlib:deflate(Z, ORIG, finish),
?m(true, C1 == list_to_binary(C3)),
?m(ok, zlib:deflateEnd(Z)),
- ?line ok = zlib:close(Z),
- ?line ok.
+ ok = zlib:close(Z),
+ ok.
-gz_usage(doc) -> "Test a standard compressed gzipped file";
-gz_usage(suite) -> [];
+%% Test a standard compressed gzipped file.
gz_usage(Config) when is_list(Config) ->
gz_usage(gz_usage({get_arg,Config}));
gz_usage({get_arg,Config}) ->
- ?line Out = conf(data_dir,Config),
- ?line {ok,GZIP} = file:read_file(filename:join(Out,"zipdoc.1.gz")),
- ?line {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")),
- ?line {ok,GZIP2} = file:read_file(filename:join(Out,"zipdoc.txt.gz")),
+ Out = conf(data_dir,Config),
+ {ok,GZIP} = file:read_file(filename:join(Out,"zipdoc.1.gz")),
+ {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")),
+ {ok,GZIP2} = file:read_file(filename:join(Out,"zipdoc.txt.gz")),
{run,GZIP,ORIG,GZIP2};
gz_usage({run,GZIP,ORIG,GZIP2}) ->
- ?line Z = zlib:open(),
- ?line UC1 = zlib:gunzip(GZIP),
+ Z = zlib:open(),
+ UC1 = zlib:gunzip(GZIP),
?m(true,zlib:crc32(Z,UC1) == zlib:crc32(Z,ORIG)),
- ?line UC3 = zlib:gunzip(GZIP2),
+ UC3 = zlib:gunzip(GZIP2),
?m(true,zlib:crc32(Z,UC3) == zlib:crc32(Z,ORIG)),
- ?line Compressed = zlib:gzip(ORIG),
- ?line UC5 = zlib:gunzip(Compressed),
+ Compressed = zlib:gzip(ORIG),
+ UC5 = zlib:gunzip(Compressed),
?m(true,zlib:crc32(Z,UC5) == zlib:crc32(Z,ORIG)),
- ?line ok = zlib:close(Z).
+ ok = zlib:close(Z).
-gz_usage2(doc) -> "Test more of a standard compressed gzipped file";
-gz_usage2(suite) -> [];
+%% Test more of a standard compressed gzipped file.
gz_usage2(Config) ->
case os:find_executable("gzip") of
Name when is_list(Name) ->
- ?line Z = zlib:open(),
- ?line Out = conf(data_dir,Config),
- ?line {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")),
- ?line Compressed = zlib:gzip(ORIG),
+ Z = zlib:open(),
+ Out = conf(data_dir,Config),
+ {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")),
+ Compressed = zlib:gzip(ORIG),
GzOutFile = filename:join(Out,"out.gz"),
OutFile = filename:join(Out,"out.txt"),
?m(ok, file:write_file(GzOutFile,Compressed)),
- ?line os:cmd("gzip -c -d " ++ GzOutFile ++ " > " ++ OutFile),
+ os:cmd("gzip -c -d " ++ GzOutFile ++ " > " ++ OutFile),
case file:read_file(OutFile) of
{ok,ExtDecompressed} ->
?m(true,
@@ -731,83 +688,80 @@ gz_usage2(Config) ->
io:format("Couldn't test external decompressor ~p\n",
[Error])
end,
- ?line ok = zlib:close(Z),
+ ok = zlib:close(Z),
ok;
false ->
{skipped,"No gzip in path"}
end.
-
-compress_usage(doc) ->
- "Test that (de)compress funcs work with"
- " standard tools, for example a chunk from a png file";
-compress_usage(suite) -> [];
+
+%% Test that (de)compress funcs work with standard tools, for example
+%% a chunk from a png file.
compress_usage(Config) when is_list(Config) ->
compress_usage(compress_usage({get_arg,Config}));
compress_usage({get_arg,Config}) ->
- ?line Out = conf(data_dir,Config),
- ?line {ok,C1} = file:read_file(filename:join(Out,"png-compressed.zlib")),
+ Out = conf(data_dir,Config),
+ {ok,C1} = file:read_file(filename:join(Out,"png-compressed.zlib")),
{run,C1};
compress_usage({run,C1}) ->
- ?line Z = zlib:open(),
+ Z = zlib:open(),
%% See that we can uncompress a file generated with external prog.
- ?line UC1 = zlib:uncompress(C1),
+ UC1 = zlib:uncompress(C1),
%% Check that the crc are correct.
?m(4125865008,zlib:crc32(Z,UC1)),
- ?line C2 = zlib:compress(UC1),
- ?line UC2 = zlib:uncompress(C2),
+ C2 = zlib:compress(UC1),
+ UC2 = zlib:uncompress(C2),
%% Check that the crc are correct.
?m(4125865008,zlib:crc32(Z,UC2)),
-
- ?line ok = zlib:close(Z),
+
+ ok = zlib:close(Z),
D = [<<"We tests some partial">>,
<<"data, sent over">>,
<<"the stream">>,
<<"we check that we can unpack">>,
<<"every message we get">>],
-
- ?line ZC = zlib:open(),
- ?line ZU = zlib:open(),
+
+ ZC = zlib:open(),
+ ZU = zlib:open(),
Test = fun(finish, {_,Tot}) ->
- ?line Compressed = zlib:deflate(ZC, <<>>, finish),
+ Compressed = zlib:deflate(ZC, <<>>, finish),
Data = zlib:inflate(ZU, Compressed),
[Tot|Data];
(Data, {Op,Tot}) ->
- ?line Compressed = zlib:deflate(ZC, Data, Op),
+ Compressed = zlib:deflate(ZC, Data, Op),
Res1 = ?m([Data],zlib:inflate(ZU, Compressed)),
{Op, [Tot|Res1]}
end,
- ?line zlib:deflateInit(ZC),
- ?line zlib:inflateInit(ZU),
- ?line T1 = lists:foldl(Test,{sync,[]},D++[finish]),
+ zlib:deflateInit(ZC),
+ zlib:inflateInit(ZU),
+ T1 = lists:foldl(Test,{sync,[]},D++[finish]),
?m(true, list_to_binary(D) == list_to_binary(T1)),
- ?line zlib:deflateEnd(ZC),
- ?line zlib:inflateEnd(ZU),
-
- ?line zlib:deflateInit(ZC),
- ?line zlib:inflateInit(ZU),
- ?line T2 = lists:foldl(Test,{full,[]},D++[finish]),
+ zlib:deflateEnd(ZC),
+ zlib:inflateEnd(ZU),
+
+ zlib:deflateInit(ZC),
+ zlib:inflateInit(ZU),
+ T2 = lists:foldl(Test,{full,[]},D++[finish]),
?m(true, list_to_binary(D) == list_to_binary(T2)),
- ?line zlib:deflateEnd(ZC),
- ?line zlib:inflateEnd(ZU),
-
- ?line ok = zlib:close(ZC),
- ?line ok = zlib:close(ZU).
+ zlib:deflateEnd(ZC),
+ zlib:inflateEnd(ZU),
+ ok = zlib:close(ZC),
+ ok = zlib:close(ZU).
-crc(doc) -> "Check that crc works as expected";
-crc(suite) -> [];
+
+%% Check that crc works as expected.
crc(Config) when is_list(Config) ->
crc(crc({get_arg,Config}));
crc({get_arg,Config}) ->
- ?line Out = conf(data_dir,Config),
- ?line {ok,C1} = file:read_file(filename:join(Out,"zipdoc")),
+ Out = conf(data_dir,Config),
+ {ok,C1} = file:read_file(filename:join(Out,"zipdoc")),
{run,C1};
crc({run,C1}) ->
- ?line Z = zlib:open(),
- ?line Crc = zlib:crc32(Z, C1),
+ Z = zlib:open(),
+ Crc = zlib:crc32(Z, C1),
Bins = split_bin(C1,[]),
%%io:format("Length ~p ~p ~n", [length(Bins), [size(Bin) || Bin <- Bins]]),
Last = lists:last(Bins),
@@ -817,29 +771,28 @@ crc({run,C1}) ->
Crc1
end, 0, Bins),
?m(Crc,SCrc),
- ?line [First|Rest] = Bins,
+ [First|Rest] = Bins,
Combine = fun(Bin, CS1) ->
CS2 = zlib:crc32(Z, Bin),
S2 = byte_size(Bin),
zlib:crc32_combine(Z,CS1,CS2,S2)
end,
- ?line Comb = lists:foldl(Combine, zlib:crc32(Z, First), Rest),
+ Comb = lists:foldl(Combine, zlib:crc32(Z, First), Rest),
?m(Crc,Comb),
- ?line ok = zlib:close(Z).
+ ok = zlib:close(Z).
-adler(doc) -> "Check that adler works as expected";
-adler(suite) -> [];
+%% Check that adler works as expected.
adler(Config) when is_list(Config) ->
adler(adler({get_arg,Config}));
adler({get_arg,Config}) ->
- ?line Out = conf(data_dir,Config),
+ Out = conf(data_dir,Config),
File1 = filename:join(Out,"zipdoc"),
- ?line {ok,C1} = file:read_file(File1),
+ {ok,C1} = file:read_file(File1),
{run,C1};
adler({run,C1}) ->
- ?line Z = zlib:open(),
+ Z = zlib:open(),
?m(1, zlib:adler32(Z,<<>>)),
- ?line Crc = zlib:adler32(Z, C1),
+ Crc = zlib:adler32(Z, C1),
Bins = split_bin(C1,[]),
Last = lists:last(Bins),
SCrc = lists:foldl(fun(Bin,Crc0) ->
@@ -848,43 +801,42 @@ adler({run,C1}) ->
Crc1
end, zlib:adler32(Z,<<>>), Bins),
?m(Crc,SCrc),
- ?line [First|Rest] = Bins,
+ [First|Rest] = Bins,
Combine = fun(Bin, CS1) ->
CS2 = zlib:adler32(Z, Bin),
S2 = byte_size(Bin),
zlib:adler32_combine(Z,CS1,CS2,S2)
end,
- ?line Comb = lists:foldl(Combine, zlib:adler32(Z, First), Rest),
+ Comb = lists:foldl(Combine, zlib:adler32(Z, First), Rest),
?m(Crc,Comb),
- ?line ok = zlib:close(Z).
+ ok = zlib:close(Z).
-dictionary_usage(doc) -> "Test dictionary usage";
-dictionary_usage(suite) -> [];
+%% Test dictionary usage.
dictionary_usage(Config) when is_list(Config) ->
dictionary_usage(dictionary_usage({get_arg,Config}));
dictionary_usage({get_arg,_Config}) ->
{run}; % no args
dictionary_usage({run}) ->
- ?line Z1 = zlib:open(),
+ Z1 = zlib:open(),
Dict = <<"Anka">>,
Data = <<"Kalle Anka">>,
?m(ok, zlib:deflateInit(Z1)),
- ?line DictID = zlib:deflateSetDictionary(Z1, Dict),
- %% ?line io:format("DictID = ~p\n", [DictID]),
- ?line B1 = zlib:deflate(Z1, Data),
- ?line B2 = zlib:deflate(Z1, <<>>, finish),
+ DictID = zlib:deflateSetDictionary(Z1, Dict),
+ %% io:format("DictID = ~p\n", [DictID]),
+ B1 = zlib:deflate(Z1, Data),
+ B2 = zlib:deflate(Z1, <<>>, finish),
?m(ok, zlib:deflateEnd(Z1)),
?m(ok, zlib:close(Z1)),
Compressed = list_to_binary([B1,B2]),
%% io:format("~p\n", [Compressed]),
%% Now uncompress.
- ?line Z2 = zlib:open(),
+ Z2 = zlib:open(),
?m(ok, zlib:inflateInit(Z2)),
- ?line {'EXIT',{{need_dictionary,DictID},_}} = (catch zlib:inflate(Z2, Compressed)),
+ {'EXIT',{{need_dictionary,DictID},_}} = (catch zlib:inflate(Z2, Compressed)),
?m(ok, zlib:inflateSetDictionary(Z2, Dict)),
?m(ok, zlib:inflateSetDictionary(Z2, binary_to_list(Dict))),
- ?line Uncompressed = ?m(B when is_list(B), zlib:inflate(Z2, [])),
+ Uncompressed = ?m(B when is_list(B), zlib:inflate(Z2, [])),
?m(ok, zlib:inflateEnd(Z2)),
?m(ok, zlib:close(Z2)),
?m(Data, list_to_binary(Uncompressed)).
@@ -895,8 +847,7 @@ split_bin(Last,Acc) ->
lists:reverse([Last|Acc]).
-smp(doc) -> "Check concurrent access to zlib driver";
-smp(suite) -> [];
+%% Check concurrent access to zlib driver.
smp(Config) ->
case erlang:system_info(smp_support) of
true ->
@@ -912,7 +863,7 @@ smp(Config) ->
FnAList = lists:map(fun(F) -> {F,?MODULE:F({get_arg,Config})}
end, Funcs),
- Pids = [spawn_link(?MODULE, worker, [random:uniform(9999),
+ Pids = [spawn_link(?MODULE, worker, [rand:uniform(9999),
list_to_tuple(FnAList),
self()])
|| _ <- lists:seq(1,NumOfProcs)],
@@ -921,11 +872,11 @@ smp(Config) ->
false ->
{skipped,"No smp support"}
end.
-
+
worker(Seed, FnATpl, Parent) ->
io:format("smp worker ~p, seed=~p~n",[self(),Seed]),
- random:seed(Seed,Seed,Seed),
+ rand:seed(exsplus, {Seed,Seed,Seed}),
worker_loop(100, FnATpl),
Parent ! self().
@@ -933,33 +884,32 @@ worker_loop(0, _FnATpl) ->
large_deflate_do(), % the time consuming one as finale
ok;
worker_loop(N, FnATpl) ->
- {F,A} = element(random:uniform(size(FnATpl)),FnATpl),
+ {F,A} = element(rand:uniform(tuple_size(FnATpl)), FnATpl),
?MODULE:F(A),
worker_loop(N-1, FnATpl).
-
+
wait_pids([]) ->
ok;
wait_pids(Pids) ->
receive
Pid ->
- ?line true = lists:member(Pid,Pids),
+ true = lists:member(Pid,Pids),
Others = lists:delete(Pid,Pids),
io:format("wait_pid got ~p, still waiting for ~p\n",[Pid,Others]),
wait_pids(Others)
end.
-otp_7359(doc) -> "Deflate/inflate data with size close to multiple of internal buffer size";
-otp_7359(suite) -> [];
+%% Deflate/inflate data with size close to multiple of internal buffer size.
otp_7359(_Config) ->
%% Find compressed size
ZTry = zlib:open(),
ok = zlib:deflateInit(ZTry),
ISize = zlib:getBufSize(ZTry),
IData = list_to_binary([Byte band 255 || Byte <- lists:seq(1,ISize)]),
- ?line ISize = byte_size(IData),
+ ISize = byte_size(IData),
- ?line DSize = iolist_size(zlib:deflate(ZTry, IData, sync)),
+ DSize = iolist_size(zlib:deflate(ZTry, IData, sync)),
zlib:close(ZTry),
io:format("Deflated try ~p -> ~p bytes~n", [ISize, DSize]),
@@ -981,19 +931,19 @@ otp_7359(_Config) ->
otp_7359_def_inf(Data,{DefSize,InfSize}) ->
%%io:format("Try: DefSize=~p InfSize=~p~n", [DefSize,InfSize]),
- ?line ZDef = zlib:open(),
- ?line ok = zlib:deflateInit(ZDef),
- ?line ok = zlib:setBufSize(ZDef,DefSize),
- ?line DefData = iolist_to_binary(zlib:deflate(ZDef, Data, sync)),
+ ZDef = zlib:open(),
+ ok = zlib:deflateInit(ZDef),
+ ok = zlib:setBufSize(ZDef,DefSize),
+ DefData = iolist_to_binary(zlib:deflate(ZDef, Data, sync)),
%%io:format("Deflated ~p(~p) -> ~p(~p) bytes~n",
%% [byte_size(Data), InfSize, byte_size(DefData), DefSize]),
- ?line ok = zlib:close(ZDef),
+ ok = zlib:close(ZDef),
- ?line ZInf = zlib:open(),
- ?line ok = zlib:inflateInit(ZInf),
- ?line ok = zlib:setBufSize(ZInf,InfSize),
- ?line Data = iolist_to_binary(zlib:inflate(ZInf, DefData)),
- ?line ok = zlib:close(ZInf),
+ ZInf = zlib:open(),
+ ok = zlib:inflateInit(ZInf),
+ ok = zlib:setBufSize(ZInf,InfSize),
+ Data = iolist_to_binary(zlib:inflate(ZInf, DefData)),
+ ok = zlib:close(ZInf),
ok.
otp_9981(Config) when is_list(Config) ->
@@ -1013,13 +963,13 @@ otp_9981(Config) when is_list(Config) ->
Ports = lists:sort(erlang:ports()),
ok.
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Helps with testing directly %%%%%%%%%%%%%
conf(What,Config) ->
- try ?config(What,Config) of
+ try proplists:get_value(What,Config) of
undefined ->
"./zlib_SUITE_data";
Dir ->
diff --git a/lib/megaco/test/Makefile b/lib/megaco/test/Makefile
index 06ecc06d20..d621b0f16d 100644
--- a/lib/megaco/test/Makefile
+++ b/lib/megaco/test/Makefile
@@ -100,10 +100,7 @@ ifeq ($(USE_MEGACO_HIPE),true)
ERL_COMPILE_FLAGS += +native -Dmegaco_hipe_special=true
endif
-ERL_COMPILE_FLAGS += \
- $(MEGACO_ERL_COMPILE_FLAGS) \
- -pa $(ERL_TOP)/lib/test_server/ebin \
- -I$(ERL_TOP)/lib/test_server/include
+ERL_COMPILE_FLAGS += $(MEGACO_ERL_COMPILE_FLAGS)
ERL_PATH = -pa ../../megaco/examples/simple \
-pa ../../megaco/ebin \
diff --git a/lib/mnesia/src/mnesia_lib.erl b/lib/mnesia/src/mnesia_lib.erl
index 0f1354f43e..a5eded4f0f 100644
--- a/lib/mnesia/src/mnesia_lib.erl
+++ b/lib/mnesia/src/mnesia_lib.erl
@@ -922,20 +922,7 @@ random_time(Retries, _Counter0) ->
UpperLimit = 500,
Dup = Retries * Retries,
MaxIntv = trunc(UpperLimit * (1-(50/((Dup)+50)))),
-
- case get(random_seed) of
- undefined ->
- _ = random:seed(erlang:unique_integer(),
- erlang:monotonic_time(),
- erlang:unique_integer()),
- Time = Dup + random:uniform(MaxIntv),
- %% dbg_out("---random_test rs ~w max ~w val ~w---~n", [Retries, MaxIntv, Time]),
- Time;
- _ ->
- Time = Dup + random:uniform(MaxIntv),
- %% dbg_out("---random_test rs ~w max ~w val ~w---~n", [Retries, MaxIntv, Time]),
- Time
- end.
+ Dup + rand:uniform(MaxIntv).
report_system_event(Event0) ->
Event = {mnesia_system_event, Event0},
diff --git a/lib/mnesia/test/mnesia_consistency_test.erl b/lib/mnesia/test/mnesia_consistency_test.erl
index 087aef86c9..279e7bc1ec 100644
--- a/lib/mnesia/test/mnesia_consistency_test.erl
+++ b/lib/mnesia/test/mnesia_consistency_test.erl
@@ -696,7 +696,7 @@ consistency_after_restore(ReplicaType, Op, Config) ->
?verify_mnesia(Nodes, []).
change_tab(Father, Tab, Test) ->
- Key = random:uniform(20),
+ Key = rand:uniform(20),
Update = fun() ->
case mnesia:read({Tab, Key}) of
[{Tab, Key, 1}] ->
diff --git a/lib/observer/src/observer_alloc_wx.erl b/lib/observer/src/observer_alloc_wx.erl
index 8d5c8a9037..d37623d1cc 100644
--- a/lib/observer/src/observer_alloc_wx.erl
+++ b/lib/observer/src/observer_alloc_wx.erl
@@ -30,19 +30,23 @@
-record(state,
{
- offset = 0.0,
+ time = #ti{},
active = false,
parent,
- windows,
- data = {0, queue:new()},
+ wins,
+ mem,
+ samples,
panel,
paint,
appmon,
async
}).
--define(ALLOC_W, 1).
--define(UTIL_W, 2).
+-define(ID_REFRESH_INTERVAL, 102).
+
+-import(observer_perf_wx,
+ [make_win/4, setup_graph_drawing/1, refresh_panel/4, interval_dialog/2,
+ add_data/5, precalc/4]).
start_link(Notebook, Parent) ->
wx_object:start_link(?MODULE, [Notebook, Parent], []).
@@ -51,34 +55,44 @@ init([Notebook, Parent]) ->
try
Panel = wxPanel:new(Notebook),
Main = wxBoxSizer:new(?wxVERTICAL),
- Style = ?wxFULL_REPAINT_ON_RESIZE bor ?wxCLIP_CHILDREN,
- Carrier = wxPanel:new(Panel, [{winid, ?ALLOC_W}, {style,Style}]),
- Utilz = wxPanel:new(Panel, [{winid, ?UTIL_W}, {style,Style}]),
BorderFlags = ?wxLEFT bor ?wxRIGHT,
- wxSizer:add(Main, Carrier, [{flag, ?wxEXPAND bor BorderFlags bor ?wxTOP},
- {proportion, 1}, {border, 5}]),
-
- wxSizer:add(Main, Utilz, [{flag, ?wxEXPAND bor BorderFlags},
- {proportion, 1}, {border, 5}]),
+ Carrier = make_win(alloc, Panel, Main, BorderFlags bor ?wxTOP),
+ Utilz = make_win(utilz, Panel, Main, BorderFlags),
MemWin = {MemPanel,_} = create_mem_info(Panel),
wxSizer:add(Main, MemPanel, [{flag, ?wxEXPAND bor BorderFlags bor ?wxBOTTOM},
{proportion, 1}, {border, 5}]),
wxWindow:setSizer(Panel, Main),
-
- PaintInfo = observer_perf_wx:setup_graph_drawing([Carrier, Utilz]),
- {Panel, #state{parent=Parent,
- panel =Panel,
- windows = {Carrier, Utilz, MemWin},
- paint=PaintInfo}
+ Windows = [Carrier, Utilz],
+ PaintInfo = setup_graph_drawing(Windows),
+ {Panel, #state{parent= Parent,
+ panel = Panel,
+ wins = Windows,
+ mem = MemWin,
+ paint = PaintInfo,
+ time = setup_time()
+ }
}
catch _:Err ->
io:format("~p crashed ~p: ~p~n",[?MODULE, Err, erlang:get_stacktrace()]),
{stop, Err}
end.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+setup_time() ->
+ Freq = 1,
+ #ti{fetch=Freq, disp=?DISP_FREQ/Freq}.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+handle_event(#wx{id=?ID_REFRESH_INTERVAL, event=#wxCommand{type=command_menu_selected}},
+ #state{panel=Panel, appmon=Old, wins=Wins0, time=#ti{fetch=F0} = Ti0} = State) ->
+ case interval_dialog(Panel, Ti0) of
+ Ti0 -> {noreply, State};
+ #ti{fetch=F0} = Ti -> %% Same fetch interval force refresh
+ Wins = [W#win{max=undefined} || W <- Wins0],
+ {noreply, precalc(State#state{time=Ti, wins=Wins})};
+ Ti -> %% Changed fetch interval, drop all data
+ {noreply, restart_fetcher(Old, State#state{time=Ti})}
+ end;
handle_event(#wx{event=#wxCommand{type=command_menu_selected}},
State = #state{}) ->
{noreply, State};
@@ -88,13 +102,11 @@ handle_event(Event, _State) ->
%%%%%%%%%%
handle_sync_event(#wx{obj=Panel, event = #wxPaint{}},_,
- #state{active=Active, offset=Offset, paint=Paint,
- windows=Windows, data=Data}) ->
+ #state{active=Active, time=Ti, paint=Paint,
+ wins = Windows}) ->
%% Sigh workaround bug on MacOSX (Id in paint event is always 0)
- Id = if Panel =:= element(?ALLOC_W, Windows) -> alloc;
- Panel =:= element(?UTIL_W, Windows) -> utilz
- end,
- observer_perf_wx:refresh_panel(Panel, Id, Offset, Data, Active, Paint),
+ Win = lists:keyfind(Panel, #win.panel, Windows),
+ refresh_panel(Active, Win, Ti, Paint),
ok.
%%%%%%%%%%
handle_call(Event, From, _State) ->
@@ -107,24 +119,37 @@ handle_cast(Event, _State) ->
handle_info({Key, {promise_reply, {badrpc, _}}}, #state{async=Key} = State) ->
{noreply, State#state{active=false, appmon=undefined}};
-handle_info({Key, {promise_reply, SysInfo}}, #state{async=Key, data=Data} = State) ->
+handle_info({Key, {promise_reply, SysInfo}},
+ #state{async=Key, panel=Panel, samples=Data, active=Active, wins=Wins0,
+ time=#ti{tick=Tick, disp=Disp0}=Ti} = S0) ->
+ Disp = trunc(Disp0),
+ Next = max(Tick - Disp, 0),
+ erlang:send_after(1000 div ?DISP_FREQ, self(), {refresh, Next}),
Info = alloc_info(SysInfo),
- update_alloc(State, Info),
- {noreply, State#state{offset=0.0, data = add_data(Info, Data), async=undefined}};
+ {Wins, Samples} = add_data(Info, Data, Wins0, Ti, Active),
+ S1 = S0#state{time=Ti#ti{tick=Next}, wins=Wins, samples=Samples, async=undefined},
+ if Active ->
+ update_alloc(S0, Info),
+ State = precalc(S1),
+ catch wxWindow:refresh(Panel),
+ {noreply, State};
+ true ->
+ {noreply, S1}
+ end;
-handle_info({refresh, Seq, Freq, Node}, #state{panel=Panel, appmon=Node, async=Key} = State) ->
- wxWindow:refresh(Panel),
+handle_info({refresh, Seq},
+ State = #state{panel=Panel, appmon=Node, time=#ti{tick=Seq, disp=DispF}=Ti})
+ when (Seq+1) < (DispF*1.5) ->
Next = Seq+1,
- if
- Next > Freq, Key =:= undefined ->
- erlang:send_after(trunc(1000 / Freq), self(), {refresh, 1, Freq, Node}),
+ State#state.active andalso (catch wxWindow:refresh(Panel)),
+ erlang:send_after(1000 div ?DISP_FREQ, self(), {refresh, Next}),
+ if Seq =:= (trunc(DispF)-1) ->
Req = rpc:async_call(Node, observer_backend, sys_info, []),
- {noreply, State#state{offset=Seq/Freq, async=Req}};
+ {noreply, State#state{time=Ti#ti{tick=Next}, async=Req}};
true ->
- erlang:send_after(trunc(1000 / Freq), self(), {refresh, Next, Freq, Node}),
- {noreply, State#state{offset=Seq/Freq}}
+ {noreply, State#state{time=Ti#ti{tick=Next}}}
end;
-handle_info({refresh, _Seq, _Freq, _Node}, State) ->
+handle_info({refresh, _S}, #state{}=State) ->
{noreply, State};
handle_info({active, Node}, State = #state{parent=Parent, panel=Panel, appmon=Old}) ->
@@ -132,15 +157,9 @@ handle_info({active, Node}, State = #state{parent=Parent, panel=Panel, appmon=Ol
try
Node = Old,
wxWindow:refresh(Panel),
- {noreply, State#state{active=true}}
+ {noreply, precalc(State#state{active=true})}
catch _:_ ->
- SysInfo = observer_wx:try_rpc(Node, observer_backend, sys_info, []),
- Info = alloc_info(SysInfo),
- Freq = 6,
- erlang:send_after(trunc(1000 / Freq), self(), {refresh, 1, Freq, Node}),
- wxWindow:refresh(Panel),
- {noreply, State#state{active=true, appmon=Node, offset=0.0,
- data = add_data(Info, {0, queue:new()})}}
+ {noreply, restart_fetcher(Node, State)}
end;
handle_info(not_active, State = #state{appmon=_Pid}) ->
@@ -160,12 +179,21 @@ code_change(_, _, State) ->
%%%%%%%%%%
-add_data(Stats, {N, Q}) when N > 60 ->
- {N, queue:drop(queue:in(Stats, Q))};
-add_data(Stats, {N, Q}) ->
- {N+1, queue:in(Stats, Q)}.
+restart_fetcher(Node, #state{panel=Panel, wins=Wins0, time=Ti} = State) ->
+ SysInfo = observer_wx:try_rpc(Node, observer_backend, sys_info, []),
+ Info = alloc_info(SysInfo),
+ {Wins, Samples} = add_data(Info, {0, queue:new()}, Wins0, Ti, true),
+ erlang:send_after(1000 div ?DISP_FREQ, self(), {refresh, 0}),
+ wxWindow:refresh(Panel),
+ precalc(State#state{active=true, appmon=Node, time=Ti#ti{tick=0},
+ wins=Wins, samples=Samples}).
+
+precalc(#state{samples=Data0, paint=Paint, time=Ti, wins=Wins0}=State) ->
+ Wins = [precalc(Ti, Data0, Paint, Win) || Win <- Wins0],
+ State#state{wins=Wins}.
+
-update_alloc(#state{windows={_, _, {_, Grid}}}, Fields) ->
+update_alloc(#state{mem={_, Grid}}, Fields) ->
Max = wxListCtrl:getItemCount(Grid),
Update = fun({Name, BS, CS}, Row) ->
(Row >= Max) andalso wxListCtrl:insertItem(Grid, Row, ""),
@@ -174,7 +202,7 @@ update_alloc(#state{windows={_, _, {_, Grid}}}, Fields) ->
wxListCtrl:setItem(Grid, Row, 2, observer_lib:to_str(CS div 1024)),
Row + 1
end,
- lists:foldl(Update, 0, Fields),
+ wx:foldl(Update, 0, Fields),
Fields.
alloc_info(SysInfo) ->
@@ -247,11 +275,7 @@ create_mem_info(Parent) ->
create_menus(Parent, _) ->
- MenuEntries =
- [{"File",
- [
- ]}
- ],
- observer_wx:create_menus(Parent, MenuEntries).
+ View = {"View", [#create_menu{id = ?ID_REFRESH_INTERVAL, text = "Graph Settings"}]},
+ observer_wx:create_menus(Parent, [{"File", []}, View]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/observer/src/observer_app_wx.erl b/lib/observer/src/observer_app_wx.erl
index a2b7c21993..40e117357c 100644
--- a/lib/observer/src/observer_app_wx.erl
+++ b/lib/observer/src/observer_app_wx.erl
@@ -29,7 +29,7 @@
-include("observer_defs.hrl").
%% Import drawing wrappers
--import(observer_perf_wx, [haveGC/0,
+-import(observer_perf_wx, [haveGC/0, make_gc/2, destroy_gc/1,
setPen/2, setFont/3, setBrush/2,
strokeLine/5, strokeLines/2, drawRoundedRectangle/6,
drawText/4, getTextExtent/2]).
@@ -244,28 +244,18 @@ handle_event(Event, _State) ->
%%%%%%%%%%
handle_sync_event(#wx{event = #wxPaint{}},_,
#state{app_w=DA, app=App, sel=Sel, paint=Paint, usegc=UseGC}) ->
- %% PaintDC must be created in a callback to work on windows.
- IsWindows = element(1, os:type()) =:= win32,
- %% Avoid Windows flickering hack
- DC = if IsWindows -> wx:typeCast(wxBufferedPaintDC:new(DA), wxPaintDC);
- true -> wxPaintDC:new(DA)
- end,
- IsWindows andalso wxDC:clear(DC),
- GC = case UseGC of
- true ->
- GC0 = ?wxGC:create(DC),
- %% Argh must handle scrolling when using ?wxGC
- {Sx,Sy} = wxScrolledWindow:calcScrolledPosition(DA, {0,0}),
- ?wxGC:translate(GC0, Sx,Sy),
- GC0;
- false ->
- wxScrolledWindow:doPrepareDC(DA,DC),
- DC
- end,
+ GC = {GC0, DC} = make_gc(DA, UseGC),
+ case UseGC of
+ false ->
+ wxScrolledWindow:doPrepareDC(DA,DC);
+ true ->
+ %% Argh must handle scrolling when using ?wxGC
+ {Sx,Sy} = wxScrolledWindow:calcScrolledPosition(DA, {0,0}),
+ ?wxGC:translate(GC0, Sx,Sy)
+ end,
%% Nothing is drawn until wxPaintDC is destroyed.
- draw({UseGC, GC}, App, Sel, Paint),
- UseGC andalso ?wxGC:destroy(GC),
- wxPaintDC:destroy(DC),
+ draw(GC, App, Sel, Paint),
+ destroy_gc(GC),
ok.
%%%%%%%%%%
handle_call(Event, From, _State) ->
@@ -312,15 +302,10 @@ handle_info({delivery, _Pid, app, _Curr, {[], [], [], []}},
handle_info({delivery, Pid, app, Curr, AppData},
State = #state{panel=Panel, appmon=Pid, current=Curr, usegc=UseGC,
app_w=AppWin, paint=#paint{font=Font}}) ->
- GC = if UseGC -> ?wxGC:create(AppWin);
- true -> wxWindowDC:new(AppWin)
- end,
- FontW = {UseGC, GC},
- setFont(FontW, Font, {0,0,0}),
- App = build_tree(AppData, FontW),
- if UseGC -> ?wxGC:destroy(GC);
- true -> wxWindowDC:destroy(GC)
- end,
+ GC = make_gc(AppWin, UseGC),
+ setFont(GC, Font, {0,0,0}),
+ App = build_tree(AppData, GC),
+ destroy_gc(GC),
setup_scrollbar(AppWin, App),
wxWindow:refresh(Panel),
wxWindow:layout(Panel),
diff --git a/lib/observer/src/observer_defs.hrl b/lib/observer/src/observer_defs.hrl
index 1c2fe520b7..c4ba84a8c4 100644
--- a/lib/observer/src/observer_defs.hrl
+++ b/lib/observer/src/observer_defs.hrl
@@ -49,3 +49,14 @@
-define(LCTRL_WDECR, 4). %% Remove some pixels in column width to avoid creating unnecessary scrollbar
-define(SASH_STYLE, ?wxSP_LIVE_UPDATE bor ?wxSP_NOBORDER bor ?wxSP_3DSASH).
+
+-define(DISP_FREQ, 10). %% per second
+-define(FETCH_DATA, 2). %% per second
+-define(DISP_SECONDS, 60).
+
+-record(ti, {tick=0, disp=?DISP_FREQ/?FETCH_DATA, fetch=?FETCH_DATA, secs=?DISP_SECONDS}).
+
+-record(win, {name, panel, size, geom,
+ graphs=[], no_samples=0,
+ max, state,
+ info=[]}).
diff --git a/lib/observer/src/observer_perf_wx.erl b/lib/observer/src/observer_perf_wx.erl
index ace0b62c1d..56da5a862a 100644
--- a/lib/observer/src/observer_perf_wx.erl
+++ b/lib/observer/src/observer_perf_wx.erl
@@ -25,8 +25,9 @@
handle_event/2, handle_sync_event/3, handle_cast/2]).
%% Drawing wrappers for DC and GC areas
--export([setup_graph_drawing/1, refresh_panel/6,
- haveGC/0,
+-export([make_win/4, setup_graph_drawing/1,
+ refresh_panel/4, precalc/4, add_data/5, interval_dialog/2,
+ haveGC/0, make_gc/2, destroy_gc/1,
setPen/2, setFont/3, setBrush/2,
strokeLine/5, strokeLines/2, drawRoundedRectangle/6,
drawText/4, getTextExtent/2]).
@@ -35,13 +36,18 @@
-include_lib("wx/include/wx.hrl").
-include("observer_defs.hrl").
+-define(ID_REFRESH_INTERVAL, 102).
+
+-define(BW, 5).
+-define(BH, 5).
+
-record(state,
{
- offset = 0.0,
+ time = #ti{},
active = false,
parent,
- windows,
- data = {0, queue:new()},
+ samples, %% Orig data store
+ wins=[], %% per window content
panel,
paint,
appmon
@@ -51,49 +57,49 @@
-record(paint, {font, small, pen, pen2, pens, usegc = false}).
--define(RQ_W, 1).
--define(MEM_W, 2).
--define(IO_W, 3).
-
start_link(Notebook, Parent) ->
wx_object:start_link(?MODULE, [Notebook, Parent], []).
init([Notebook, Parent]) ->
- try
- Panel = wxPanel:new(Notebook),
- Main = wxBoxSizer:new(?wxVERTICAL),
+ try
+ Panel = wxPanel:new(Notebook),
+ Main = wxBoxSizer:new(?wxVERTICAL),
+ MemIO = wxBoxSizer:new(?wxHORIZONTAL),
+
+ CPU = make_win(runq, Panel, Main, ?wxALL),
+ MEM = make_win(memory, Panel, MemIO, ?wxLEFT),
+ IO = make_win(io, Panel, MemIO, ?wxLEFT bor ?wxRIGHT),
+
+ wxSizer:add(Main, MemIO, [{flag, ?wxEXPAND bor ?wxDOWN},
+ {proportion, 1}, {border, 5}]),
+ wxWindow:setSizer(Panel, Main),
+ Windows = [CPU, MEM, IO],
+ PaintInfo = setup_graph_drawing(Windows),
+
+ process_flag(trap_exit, true),
+ State0 = #state{parent=Parent,
+ panel =Panel,
+ wins = Windows,
+ paint=PaintInfo,
+ samples=reset_data()
+ },
+ {Panel, State0}
+ catch _:Err ->
+ io:format("~p crashed ~p: ~p~n",[?MODULE, Err, erlang:get_stacktrace()]),
+ {stop, Err}
+ end.
+
+make_win(Name, Parent, Sizer, Border) ->
Style = ?wxFULL_REPAINT_ON_RESIZE bor ?wxCLIP_CHILDREN,
- CPU = wxPanel:new(Panel, [{winid, ?RQ_W}, {style,Style}]),
- wxSizer:add(Main, CPU, [{flag, ?wxEXPAND bor ?wxALL},
- {proportion, 1}, {border, 5}]),
- MemIO = wxBoxSizer:new(?wxHORIZONTAL),
- MEM = wxPanel:new(Panel, [{winid, ?MEM_W}, {style,Style}]),
- IO = wxPanel:new(Panel, [{winid, ?IO_W}, {style,Style}]),
- wxSizer:add(MemIO, MEM, [{flag, ?wxEXPAND bor ?wxLEFT},
- {proportion, 1}, {border, 5}]),
- wxSizer:add(MemIO, IO, [{flag, ?wxEXPAND bor ?wxLEFT bor ?wxRIGHT},
- {proportion, 1}, {border, 5}]),
- wxSizer:add(Main, MemIO, [{flag, ?wxEXPAND bor ?wxDOWN},
- {proportion, 1}, {border, 5}]),
- wxWindow:setSizer(Panel, Main),
-
- PaintInfo = setup_graph_drawing([CPU, MEM, IO]),
-
- process_flag(trap_exit, true),
- {Panel, #state{parent=Parent,
- panel =Panel,
- windows = {CPU, MEM, IO},
- paint=PaintInfo
- }}
- catch _:Err ->
- io:format("~p crashed ~p: ~p~n",[?MODULE, Err, erlang:get_stacktrace()]),
- {stop, Err}
- end.
+ Panel = wxPanel:new(Parent, [{style,Style}]),
+ Opts = [{flag, ?wxEXPAND bor Border}, {proportion, 1}, {border, 5}],
+ wxSizer:add(Sizer, Panel, Opts),
+ #win{name=Name, panel=Panel}.
setup_graph_drawing(Panels) ->
IsWindows = element(1, os:type()) =:= win32,
IgnoreCB = {callback, fun(_,_) -> ok end},
- Do = fun(Panel) ->
+ Do = fun(#win{panel=Panel}) ->
wxWindow:setBackgroundColour(Panel, ?wxWHITE),
wxPanel:connect(Panel, paint, [callback]),
IsWindows andalso
@@ -117,8 +123,8 @@ setup_graph_drawing(Panels) ->
SF = wxFont:new(DefSize-2, DefFamily, ?wxFONTSTYLE_NORMAL, ?wxFONTWEIGHT_NORMAL),
{F, SF}
end,
- BlackPen = wxPen:new({0,0,0}, [{width, 2}]),
- Pens = [wxPen:new(Col, [{width, 3}]) || Col <- tuple_to_list(colors())],
+ BlackPen = wxPen:new({0,0,0}, [{width, 1}]),
+ Pens = [wxPen:new(Col, [{width, 1}]) || Col <- tuple_to_list(colors())],
#paint{usegc = UseGC,
font = Font,
small = SmallFont,
@@ -129,7 +135,16 @@ setup_graph_drawing(Panels) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
+handle_event(#wx{id=?ID_REFRESH_INTERVAL, event=#wxCommand{type=command_menu_selected}},
+ #state{panel=Panel, appmon=Old, wins=Wins0, time=#ti{fetch=F0} = Ti0} = State) ->
+ case interval_dialog(Panel, Ti0) of
+ Ti0 -> {noreply, State};
+ #ti{fetch=F0} = Ti -> %% Same fetch interval force refresh
+ Wins = [W#win{max=undefined} || W <- Wins0],
+ {noreply, precalc(State#state{time=Ti, wins=Wins})};
+ Ti -> %% Changed fetch interval, drop all data
+ {noreply, restart_fetcher(node(Old), State#state{time=Ti})}
+ end;
handle_event(#wx{event=#wxCommand{type=command_menu_selected}},
State = #state{}) ->
{noreply, State};
@@ -139,41 +154,21 @@ handle_event(Event, _State) ->
%%%%%%%%%%
handle_sync_event(#wx{obj=Panel, event = #wxPaint{}},_,
- #state{active=Active, offset=Offset, paint=Paint,
- windows=Windows, data=Data}) ->
+ #state{active=Active, time=Ti, paint=Paint, wins=Windows}) ->
%% Sigh workaround bug on MacOSX (Id in paint event is always 0)
%% Panel = element(Id, Windows),
- Id = if Panel =:= element(?RQ_W, Windows) -> runq;
- Panel =:= element(?MEM_W, Windows) -> memory;
- Panel =:= element(?IO_W, Windows) -> io
- end,
-
- refresh_panel(Panel, Id, Offset, Data, Active, Paint),
+ Win = lists:keyfind(Panel, #win.panel, Windows),
+ refresh_panel(Active, Win, Ti, Paint),
ok.
-refresh_panel(Panel, Id, Offset, Data, Active, #paint{usegc=UseGC} = Paint) ->
+refresh_panel(Active, #win{name=_Id, panel=Panel}=Win, Ti, #paint{usegc=UseGC}=Paint) ->
%% PaintDC must be created in a callback to work on windows.
- IsWindows = element(1, os:type()) =:= win32,
- DC = if IsWindows ->
- %% Ugly hack to aviod flickering on windows, works on windows only
- %% But the other platforms are doublebuffered by default
- wx:typeCast(wxBufferedPaintDC:new(Panel), wxPaintDC);
- true ->
- wxPaintDC:new(Panel)
- end,
- IsWindows andalso wxDC:clear(DC),
- GC = if UseGC -> ?wxGC:create(DC);
- true -> DC
- end,
%% Nothing is drawn until wxPaintDC is destroyed.
- try
- draw(Offset, Id, {UseGC, GC}, Panel, Paint, Data, Active)
- catch _:Err ->
- io:format("Internal error ~p ~p~n",[Err, erlang:get_stacktrace()])
+ GC = make_gc(Panel, UseGC),
+ if Active -> draw_win(GC, Win, Ti, Paint);
+ true -> ignore
end,
- UseGC andalso ?wxGC:destroy(GC),
- wxPaintDC:destroy(DC).
-
+ destroy_gc(GC).
%%%%%%%%%%
handle_call(Event, From, _State) ->
@@ -182,41 +177,42 @@ handle_call(Event, From, _State) ->
handle_cast(Event, _State) ->
error({unhandled_cast, Event}).
%%%%%%%%%%
-handle_info(Stats = {stats, 1, _, _, _},
- State = #state{panel=Panel, data=Data, active=Active}) ->
+handle_info({stats, 1, _, _, _} = Stats,
+ #state{panel=Panel, samples=Data, active=Active, wins=Wins0,
+ time=#ti{tick=Tick, disp=Disp0}=Ti} = State0) ->
if Active ->
+ Disp = trunc(Disp0),
+ Next = max(Tick - Disp, 0),
+ erlang:send_after(1000 div ?DISP_FREQ, self(), {refresh, Next}),
+ {Wins, Samples} = add_data(Stats, Data, Wins0, Ti, Active),
+ State = precalc(State0#state{time=Ti#ti{tick=Next}, wins=Wins, samples=Samples}),
wxWindow:refresh(Panel),
- Freq = 6,
- erlang:send_after(trunc(1000 / Freq), self(), {refresh, 1, Freq});
- true -> ignore
- end,
- {noreply, State#state{offset=0.0, data = add_data(Stats, Data)}};
-
-handle_info({refresh, Seq, Freq}, State = #state{panel=Panel, offset=Prev}) ->
- wxWindow:refresh(Panel),
- Next = Seq+1,
- if Seq > 1, Prev =:= 0.0 ->
- %% We didn't have time to handle the refresh
{noreply, State};
- Next < Freq ->
- erlang:send_after(trunc(1000 / Freq), self(), {refresh, Next, Freq}),
- {noreply, State#state{offset=Seq/Freq}};
true ->
- {noreply, State#state{offset=Seq/Freq}}
+ {Wins1, Samples} = add_data(Stats, Data, Wins0, Ti, Active),
+ Wins = [W#win{max=undefined} || W <- Wins1],
+ {noreply, State0#state{samples=Samples, wins=Wins, time=Ti#ti{tick=0}}}
end;
-handle_info({active, Node}, State = #state{parent=Parent, panel=Panel, appmon=Old}) ->
+handle_info({refresh, Seq}, #state{panel=Panel, time=#ti{tick=Seq, disp=DispF}=Ti} = State0)
+ when (Seq+1) < (DispF*1.5) ->
+ Next = Seq+1,
+ erlang:send_after(1000 div ?DISP_FREQ, self(), {refresh, Next}),
+ State = precalc(State0#state{time=Ti#ti{tick=Next}}),
+ catch wxWindow:refresh(Panel),
+ {noreply, State};
+handle_info({refresh, _}, State) ->
+ {noreply, State};
+
+handle_info({active, Node}, #state{parent=Parent, panel=Panel, appmon=Old, time=_Ti} = State) ->
create_menus(Parent, []),
try
Node = node(Old),
wxWindow:refresh(Panel),
+ erlang:send_after(1000 div ?DISP_FREQ, self(), {refresh, 0}),
{noreply, State#state{active=true}}
catch _:_ ->
- catch Old ! exit,
- Me = self(),
- Pid = spawn_link(Node, observer_backend, fetch_stats, [Me, 1000]),
- wxWindow:refresh(Panel),
- {noreply, State#state{active=true, appmon=Pid, data={0, queue:new()}}}
+ {noreply,restart_fetcher(Node, State)}
end;
handle_info(not_active, State = #state{appmon=_Pid}) ->
@@ -237,173 +233,337 @@ terminate(_Event, #state{appmon=Pid}) ->
code_change(_, _, State) ->
State.
-add_data(Stats, {N, Q}) when N > 60 ->
- {N, queue:drop(queue:in(Stats, Q))};
-add_data(Stats, {N, Q}) ->
- {N+1, queue:in(Stats, Q)}.
+restart_fetcher(Node, #state{appmon=Old, panel=Panel, time=#ti{fetch=Freq}=Ti}=State) ->
+ catch Old ! exit,
+ Me = self(),
+ Pid = spawn_link(Node, observer_backend, fetch_stats, [Me, round(1000/Freq)]),
+ wxWindow:refresh(Panel),
+ precalc(State#state{active=true, appmon=Pid, samples=reset_data(), time=Ti#ti{tick=0}}).
+
+reset_data() ->
+ {0, queue:new()}.
+
+add_data(Stats, {N, Q0}, Wins, #ti{fetch=Fetch, secs=Secs}, Active) when N > (Secs*Fetch+1) ->
+ {{value, Drop}, Q} = queue:out(Q0),
+ add_data_1(Wins, Stats, N, {Drop,Q}, Active);
+add_data(Stats, {N, Q}, Wins, _, Active) ->
+ add_data_1(Wins, Stats, N+1, {empty, Q}, Active).
+
+add_data_1([#win{state={_,St}}|_]=Wins0, Last, N, {Drop, Q}, Active)
+ when St /= undefined ->
+ {Wins, Stat} =
+ lists:mapfoldl(fun(Win0, Entry) ->
+ {Win1,Stat} = add_data_2(Win0, Last, Entry),
+ case Active of
+ true ->
+ Win = add_data_3(Win1, N, Drop, Stat, Q),
+ {Win, Stat};
+ false ->
+ {Win1, Stat}
+ end
+ end, #{}, Wins0),
+ {Wins, {N,queue:in(Stat#{}, Q)}};
+add_data_1(Wins, Stats, 1, {_, Q}, _) ->
+ {[Win#win{state=init_data(Id, Stats),
+ info = info(Id, Stats)}
+ || #win{name=Id}=Win <- Wins], {0,Q}}.
+
+add_data_2(#win{name=Id, state=S0}=Win, Stats, Map) ->
+ {V1, S1} = collect_data(Id, Stats, S0),
+ {Win#win{state=S1}, Map#{Id=>V1}}.
+
+add_data_3(#win{name=Id, max={{OldMax, OldEntry},_,_,_},
+ geom=#{scale:={WS,HS}}, state={Max,_},
+ graphs=Graphs}=Win,
+ N, Drop0, Last, Q1)
+ when N > 3 ->
+ Drop = case Drop0 of
+ #{Id:=D} -> D;
+ _ -> Drop0
+ end,
+ case {max_value(Max), Drop =:= OldEntry} of
+ {OldMax, false} ->
+ #{Id:=V4} = Last,
+ {{value, #{Id:=V3}},Q2} = queue:out_r(Q1),
+ {{value, #{Id:=V2}},Q3} = queue:out_r(Q2),
+ {{value, #{Id:=V1}},_} = queue:out_r(Q3),
+ Vals = [V1,V2,V3,V4],
+ Gs = tuple_size(V1),
+ Info = lists:zip(lists:seq(Gs, 1, -1), Graphs),
+ Lines = [add_lines(Vals, Drop, Prev, I, WS, HS) || {I, Prev} <- Info],
+ Win#win{graphs=Lines, no_samples=N};
+ _W -> %% Max changed Trigger complete recalc
+ Win#win{max=undefined}
+ end;
+add_data_3(Win, _, _, _,_) ->
+ %% Trigger complete recalc
+ Win#win{max=undefined}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
create_menus(Parent, _) ->
- MenuEntries =
- [{"File",
- [
- ]}
- ],
- observer_wx:create_menus(Parent, MenuEntries).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-collect_data(runq, {N, Q}) ->
- case queue:to_list(Q) of
- [] -> {0, 0, [], []};
- [_] -> {0, 0, [], []};
- [{stats, _Ver, Init0, _IO, _Mem}|Data0] ->
- Init = lists:sort(Init0),
- [_|Data=[First|_]] = lists:foldl(fun({stats, _, T0, _, _}, [Prev|Acc]) ->
- TN = lists:sort(T0),
- Delta = calc_delta(TN, Prev),
- [TN, list_to_tuple(Delta)|Acc]
- end, [Init], Data0),
- NoGraphs = tuple_size(First),
- {N, lmax(Data), lists:reverse([First|Data]), lists:seq(1, NoGraphs)}
- end;
-collect_data(memory, {N, Q}) ->
- MemT = mem_types(),
- Data = [list_to_tuple([Value || {Type,Value} <- MemInfo,
- lists:member(Type, MemT)])
- || {stats, _Ver, _RQ, _IO, MemInfo} <- queue:to_list(Q)],
- {N, lmax(Data), Data, MemT};
-collect_data(io, {N, Q}) ->
- case queue:to_list(Q) of
- [] -> {0, 0, [], []};
- [_] -> {0, 0, [], []};
- [{stats, _Ver, _RQ, {{_,In0}, {_,Out0}}, _Mem}|Data0] ->
- [_,_|Data=[First|_]] =
- lists:foldl(fun({stats, _, _, {{_,In}, {_,Out}}, _}, [PIn,Pout|Acc]) ->
- [In,Out,{In-PIn,Out-Pout}|Acc]
- end, [In0,Out0], Data0),
- {N, lmax(Data), lists:reverse([First|Data]), [input, output]}
- end;
-collect_data(alloc, {N, Q}) ->
- List = queue:to_list(Q),
- Data = [list_to_tuple([Carrier || {_Type,_Block,Carrier} <- MemInfo])
- || MemInfo <- List],
- Info = case List of %% Varies depending on erlang build config/platform
- [MInfo|_] -> [Type || {Type, _, _} <- MInfo];
- _ -> []
- end,
- {N, lmax(Data), Data, Info};
-
-collect_data(utilz, {N, Q}) ->
- List = queue:to_list(Q),
- Data = [list_to_tuple([round(100*Block/Carrier) || {_Type,Block,Carrier} <- MemInfo])
- || MemInfo <- List],
- Info = case List of %% Varies depending on erlang build config/platform
- [MInfo|_] -> [Type || {Type, _, _} <- MInfo];
- _ -> []
- end,
- {N, lmax(Data), Data, Info}.
+ View = {"View", [#create_menu{id = ?ID_REFRESH_INTERVAL, text = "Graph Settings"}]},
+ observer_wx:create_menus(Parent, [{"File", []}, View]).
+
+interval_dialog(Parent0, #ti{fetch=Fetch0, secs=Secs0}=Ti) ->
+ Parent = observer_lib:get_wx_parent(Parent0),
+ Dialog = wxDialog:new(Parent, ?wxID_ANY, "Load Chart Settings",
+ [{style, ?wxDEFAULT_DIALOG_STYLE bor
+ ?wxRESIZE_BORDER}]),
+ {Sl1,FetchSl} = slider(Dialog, "Sample (ms)", trunc(1000 / Fetch0), 100, 10000),
+ {Sl2, SecsSl} = slider(Dialog, "Length (min)", Secs0 div 60, 1, 10),
+ TopSizer = wxBoxSizer:new(?wxVERTICAL),
+ Flags = [{flag, ?wxEXPAND bor ?wxTOP bor ?wxLEFT bor ?wxRIGHT},
+ {border, 5}, {proportion, 1}],
+ wxSizer:add(TopSizer, Sl1, Flags),
+ wxSizer:add(TopSizer, Sl2, Flags),
+ wxSizer:add(TopSizer, wxDialog:createButtonSizer(Dialog, ?wxOK bor ?wxCANCEL), Flags),
+ wxWindow:setSizerAndFit(Dialog, TopSizer),
+ wxSizer:setSizeHints(TopSizer, Dialog),
+ Res = case wxDialog:showModal(Dialog) of
+ ?wxID_OK ->
+ Fetch = 1000 / wxSlider:getValue(FetchSl),
+ Secs = wxSlider:getValue(SecsSl) * 60,
+ Ti#ti{fetch=Fetch, secs=Secs, disp=?DISP_FREQ/Fetch};
+ ?wxID_CANCEL ->
+ Ti
+ end,
+ wxDialog:destroy(Dialog),
+ Res.
+
+slider(Parent, Str, Value, Min, Max) ->
+ Sz = wxBoxSizer:new(?wxHORIZONTAL),
+ Center = [{flag, ?wxALIGN_CENTER_VERTICAL}],
+ wxSizer:add(Sz, wxStaticText:new(Parent, ?wxID_ANY, Str), [{proportion, 1}|Center]),
+ Opt = [{style, ?wxSL_HORIZONTAL bor ?wxSL_LABELS}],
+ Slider = wxSlider:new(Parent, ?wxID_ANY, Value, Min, Max, Opt),
+ wxSizer:add(Sz, Slider, [{proportion, 2}|Center]),
+ case Min > 1 of
+ false ->
+ {Sz, Slider};
+ true ->
+ CB = fun(#wx{event=Ev},_) -> step(Ev, Slider, Min) end,
+ wxSlider:connect(Slider, scroll_thumbtrack, [{callback, CB}]),
+ wxSlider:connect(Slider, scroll_changed, [{callback, CB}]),
+ {Sz, Slider}
+ end.
+step(_Ev = #wxScroll{commandInt=Value}, Slider, Min) ->
+ Val = Min * round(Value / Min),
+ wxSlider:setValue(Slider, Val),
+ ok.
-mem_types() ->
- [total, processes, atom, binary, code, ets].
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-lmax([]) -> 0;
-lmax(List) ->
- Max = [lists:max(tuple_to_list(T)) || T <- List,
- tuple_size(T) > 0],
- case Max of
- [] -> 0;
- _ -> lists:max(Max)
+mk_max() -> {0, undefined}.
+max_value({Max,_}) -> Max.
+%% max_data({_,Data}) -> Data. matched in function head
+
+lmax(MState, Tuple, Tuple) when is_tuple(Tuple) ->
+ lmax(MState, tuple_to_list(Tuple), Tuple);
+lmax(MState, Values, State) ->
+ Max = max_value(MState),
+ New = lists:max([Max|Values]),
+ case New >= Max of
+ false -> MState;
+ true -> {New, State}
end.
+init_data(runq, {stats, _, T0, _, _}) -> {mk_max(),lists:sort(T0)};
+init_data(io, {stats, _, _, {{_,In0}, {_,Out0}}, _}) -> {mk_max(), {In0,Out0}};
+init_data(memory, _) -> {mk_max(), info(memory, undefined)};
+init_data(alloc, _) -> {mk_max(), ok};
+init_data(utilz, _) -> {mk_max(), ok}.
+
+info(runq, {stats, _, T0, _, _}) -> lists:seq(1, length(T0));
+info(memory, _) -> [total, processes, atom, binary, code, ets];
+info(io, _) -> [input, output];
+info(alloc, First) -> [Type || {Type, _, _} <- First];
+info(utilz, First) -> [Type || {Type, _, _} <- First];
+info(_, []) -> [].
+
+collect_data(runq, {stats, _, T0, _, _}, {Max,S0}) ->
+ S1 = lists:sort(T0),
+ Delta = calc_delta(S1, S0),
+ Sample = list_to_tuple(Delta),
+ {Sample, {lmax(Max,Delta,Sample), S1}};
+collect_data(io, {stats, _, _, {{_,In0}, {_,Out0}}, _}, {Max,{PIn,POut}}) ->
+ In = In0-PIn,
+ Out = Out0-POut,
+ Sample = {In, Out},
+ {Sample, {lmax(Max, [In,Out], Sample), {In0, Out0}}};
+collect_data(memory, {stats, _, _, _, MemInfo}, {Max, MemTypes}) ->
+ Vs = [Value || {Type,Value} <- MemInfo, lists:member(Type, MemTypes)],
+ Sample = list_to_tuple(Vs),
+ {Sample, {lmax(Max, Vs, Sample),MemTypes}};
+collect_data(alloc, MemInfo, Max) ->
+ Vs = [Carrier || {_Type,_Block,Carrier} <- MemInfo],
+ Sample = list_to_tuple(Vs),
+ {Sample, lmax(Max, Vs, Sample)};
+collect_data(utilz, MemInfo, Max) ->
+ Vs = [round(100*Block/Carrier) || {_Type,Block,Carrier} <- MemInfo],
+ Sample = list_to_tuple(Vs),
+ {Sample, lmax(Max,Vs,Sample)}.
+
calc_delta([{Id, WN, TN}|Ss], [{Id, WP, TP}|Ps]) ->
[100*(WN-WP) div (TN-TP)|calc_delta(Ss, Ps)];
calc_delta([], []) -> [].
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-draw(Offset, Id, DC, Panel, Paint=#paint{pens=Pens, small=Small}, Data, Active) ->
- %% This can be optimized a lot by collecting data once
- %% and draw to memory and then blit memory and only draw new entries in new memory
- %% area. Hmm now rewritten to use ?wxGC I don't now if it is feasable.
- {Len, Max0, Hs, Info} = collect_data(Id, Data),
- {Max,_,_} = MaxDisp = calc_max(Id, Max0),
+precalc(#state{samples=Data0, paint=Paint, time=Ti, wins=Wins0}=State) ->
+ Wins = [precalc(Ti, Data0, Paint, Win) || Win <- Wins0],
+ State#state{wins=Wins}.
+
+precalc(Ti, {NoSamples,Q}, Paint, #win{name=Id, panel=Panel}=Win) ->
Size = wxWindow:getClientSize(Panel),
- {X0,Y0,WS,HS, DrawBs} = draw_borders(Id, Info, DC, Size, MaxDisp, Paint),
- Last = 60*WS+X0-1,
- Start = max(61-Len, 0)*WS+X0 - Offset*WS,
- Samples = length(Hs),
- NoGraphs = try tuple_size(hd(Hs)) catch _:_ -> 0 end,
- case Active andalso Samples > 1 andalso NoGraphs > 0 of
- true ->
- Draw = fun(N) ->
- Lines = make_lines(Hs, Start, N, {X0,Max*HS,Last}, Y0, WS, HS),
- setPen(DC, element(1+ ((N-1) rem tuple_size(Pens)), Pens)),
- strokeLines(DC, Lines),
- N+1
- end,
- [Draw(I) || I <- lists:seq(NoGraphs, 1, -1)],
- DrawBs();
- false ->
- DrawBs(),
- Text = case Active andalso Samples =< 1 of
+ case Win of
+ #win{max=Max, no_samples=NoSamples, size=Size} when is_tuple(Max) ->
+ Win;
+ _SomeThingChanged ->
+ Hs = [Vals || #{Id:=Vals} <- queue:to_list(Q)],
+ Max = lists:foldl(fun(Vals,Max) -> lmax(Max, Vals, Vals) end,
+ mk_max(), Hs),
+ MaxDisp = calc_max(Id, Max),
+ #{scale:={WS,HS}} = Props = window_geom(Size, MaxDisp, Ti, Panel, Paint),
+ NoGraphs = try tuple_size(hd(Hs)) catch _:_ -> 0 end,
+ Graphs = [make_lines(Hs, I, WS, HS) || I <- lists:seq(NoGraphs, 1, -1)],
+ State = case Win#win.state of
+ undefined -> {Max, undefined};
+ {_, St} -> {Max, St}
+ end,
+ Win#win{geom=Props, size=Size,
+ max=MaxDisp,
+ graphs=Graphs,
+ no_samples=NoSamples,
+ state=State}
+ end.
+
+window_geom({W,H}, {_, Max, _Unit, MaxUnit},
+ #ti{secs=Secs, fetch=FetchFreq},
+ Panel, #paint{font=Font}) ->
+ Str1 = observer_lib:to_str(MaxUnit),
+ Str2 = observer_lib:to_str(MaxUnit div 2),
+ Str3 = observer_lib:to_str(0),
+ {TW,TH,_,_} = wxWindow:getTextExtent(Panel, Str1, [{theFont, Font}]),
+ {SpaceW, _,_,_} = wxWindow:getTextExtent(Panel, "W", [{theFont, Font}]),
+ X0 = ?BW+TW+?BW,
+ X1 = W-?BW*4,
+ MaxTextY = TH+?BH,
+ BottomTextY = H-?BH-TH,
+ Y0 = MaxTextY + (TH / 2),
+ Y1 = BottomTextY - TH - ?BH,
+
+ ScaleW = (X1-X0-1)/(Secs*FetchFreq),
+ ScaleH = (Y1-Y0-1) / Max,
+ #{p0=>{X0,Y0}, p1=>{X1,Y1}, scale=>{ScaleW, ScaleH},
+ txsz=>{TW,TH,SpaceW}, txt=>{BottomTextY, MaxTextY}, strs=>{Str1,Str2,Str3}}.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+draw_win(DC, #win{no_samples=Samples, geom=#{scale:={WS,HS}}, graphs=Graphs, max={_,Max,_,_}}=Win,
+ #ti{tick=Tick, fetch=FetchFreq, secs=Secs, disp=DispFreq}=Ti,
+ Paint=#paint{pens=Pens}) when Samples >= 2, Graphs =/= [] ->
+ %% Draw graphs
+ {X0,Y0,DrawBs} = draw_borders(DC, Ti, Win, Paint),
+ Offset = Tick / DispFreq,
+ Full = case Samples > (1+Secs*FetchFreq) of
+ true -> 1;
+ false -> 2
+ end,
+ Start = X0 + (max(Secs*FetchFreq+Full-Samples, 0) - Offset)*WS,
+ Last = Secs*FetchFreq*WS+X0,
+ Draw = fun(Lines0, N) ->
+ setPen(DC, element(1+ ((N-1) rem tuple_size(Pens)), Pens)),
+ Order = lists:reverse(Lines0),
+ [{_,Y}|Lines] = translate(Order, {Start, Y0}, 0, WS, {X0,Max*HS,Last}, []),
+ strokeLines(DC, [{Last,Y}|Lines]),
+ N-1
+ end,
+ lists:foldl(Draw, length(Graphs), Graphs),
+ DrawBs(),
+ ok;
+
+draw_win(DC, #win{no_samples=Samples} = Win,Ti, #paint{small=Small}=Paint) ->
+ %% Draw Error Msg
+ try draw_borders(DC, Ti, Win, Paint) of
+ {X0,_Y0,DrawBs} ->
+ Text = case Samples =< 1 of
true -> "Waiting for data";
false -> "Information not available"
end,
setFont(DC, Small, {0,0,0}),
- drawText(DC, Text, X0 + 100, element(2,Size) div 2)
- end,
- ok.
+ {_,WW} = getSize(DC),
+ drawText(DC, Text, X0 + 100, WW div 2),
+ DrawBs(),
+ ok
+ catch _:_ -> %% Early redraws fail
+ ok
+ end.
-make_lines(Ds = [Data|_], PX, N, Clip, ZeroY, WS, HS) ->
+translate([{X0,Y}|Rest], {Sx,Sy}=Start, N, WS, {Cx,Cy,Cw}=Clip, Acc) ->
+ X = min((N-X0)*WS+Sx,Cw),
+ Next = if X0 > 0 -> N; true -> N+1 end,
+ case X =< Cx of
+ true ->
+ translate(Rest, Start, Next, WS, Clip, [{Cx,Sy-min(Cy,Y)}]);
+ false ->
+ translate(Rest, Start, Next, WS, Clip, [{X,Sy-min(Cy,Y)}|Acc])
+ end;
+translate([], _, _, _, _, Acc) ->
+ Acc.
+
+add_lines(Vals, Drop, OldLines, I, WS, HS) ->
+ Lines = strip(OldLines, Drop, 2),
+ New = make_lines(Vals, I, WS, HS),
+ New ++ Lines.
+
+strip([{X,_}|Rest], Drop, N) when X > 0.0001, N > 0 ->
+ strip(Rest, Drop, N);
+strip([_|Rest], Drop, N) when N > 0 ->
+ strip(Rest, Drop, N-1);
+strip(List, empty, _) -> List;
+strip(List, _, _) ->
+ lists:reverse(strip(lists:reverse(List), empty, 1)).
+
+make_lines(Ds = [Data|_], N, WS, HS) ->
Y = element(N,Data),
- make_lines(Ds, PX, N, Clip, ZeroY, WS, HS, Y, []).
+ make_lines(Ds, N, WS, HS, Y, []).
-make_lines([D1 | Ds = [D2|Rest]], PX, N, Clip={Cx,Cy, _}, ZeroY, WS, HS, Y0, Acc0) ->
+make_lines([D1 | Ds = [D2|Rest]], N, WS, HS, Y0, Acc0) ->
Y1 = element(N,D1),
Y2 = element(N,D2),
Y3 = case Rest of
[D3|_] -> element(N,D3);
[] -> Y2
end,
- This = {max(Cx, PX),ZeroY-min(Cy,Y1*HS)},
+ This = {0, Y1*HS},
Acc = if (abs(Y1-Y2) * HS) < 3.0 -> [This|Acc0];
WS < 3.0 -> [This|Acc0];
- PX < Cx ->
- make_splines(Y0,Y1,Y2,Y3,PX,Clip,ZeroY,WS,HS,Acc0);
- true ->
- make_splines(Y0,Y1,Y2,Y3,PX,Clip,ZeroY,WS,HS,[This|Acc0])
+ true -> make_splines(Y0,Y1,Y2,Y3,WS,HS,[This|Acc0])
end,
- make_lines(Ds, PX+WS, N, Clip, ZeroY, WS, HS, Y1, Acc);
-make_lines([D1], _PX, N, {_,Cy,Last}, ZeroY, _WS, HS, _Y0, Acc) ->
- Y1 = element(N,D1),
- [{Last,ZeroY-min(Cy, Y1*HS)}|Acc].
+ make_lines(Ds, N, WS, HS, Y1, Acc);
+make_lines([_D1], _N, _WS, _HS, _Y0, Acc) ->
+ Acc.
-make_splines(Y00,Y10,Y20,Y30,PX,Clip,ZeroY,WS,HS,Acc) ->
+make_splines(Y00,Y10,Y20,Y30,WS,HS,Acc) ->
Y1 = Y10*HS,
Y2 = Y20*HS,
- Steps = min(abs(Y1-Y2), WS),
+ Steps = min(abs(Y1-Y2), WS/2),
if Steps > 2 ->
Y0 = Y00*HS,
Y3 = Y30*HS,
Tan = spline_tan(Y0,Y1,Y2,Y3),
Delta = 1/Steps,
- splines(Steps-1, 0.0, Delta, Tan, Y1,Y2, PX, Clip,ZeroY, Delta*WS, Acc);
+ splines(Steps-1, 0.0, Delta, Tan, Y1,Y2, Acc);
true ->
Acc
end.
-splines(N, XD, XD0, Tan, Y1,Y2, PX0, Clip={Cx,Cy,_},ZeroY, WS, Acc) when N > 0 ->
- PX = PX0+WS,
+splines(N, XD, XD0, Tan, Y1,Y2, Acc) when N > 0 ->
Delta = XD+XD0,
- if PX < Cx ->
- splines(N-1, Delta, XD0, Tan, Y1, Y2, PX, Clip,ZeroY, WS, Acc);
- true ->
- Y = min(Cy, max(0,spline(Delta, Tan, Y1,Y2))),
- splines(N-1, Delta, XD0, Tan, Y1, Y2, PX, Clip,ZeroY, WS,
- [{PX, ZeroY-Y}|Acc])
- end;
-splines(_N, _XD, _XD0, _Tan, _Y1,_Y2, _PX, _Clip,_ZeroY, _WS, Acc) -> Acc.
+ Y = max(0, spline(Delta, Tan, Y1,Y2)),
+ splines(N-1, Delta, XD0, Tan, Y1, Y2, [{1.0-Delta, Y}|Acc]);
+splines(_N, _XD, _XD0, _Tan, _Y1,_Y2, Acc) ->
+ Acc.
spline(T, {M1, M2}, Y1, Y2) ->
%% Hermite Basis Funcs
@@ -423,34 +583,19 @@ spline_tan(Y0, Y1, Y2, Y3) ->
M2 = S*C*(Y3-Y1),
{M1,M2}.
--define(BW, 5).
--define(BH, 5).
-
-draw_borders(Type, Info, DC, {W,H}, {Max, Unit, MaxUnit},
+draw_borders(DC, #ti{secs=Secs, fetch=FetchFreq},
+ #win{name=Type, geom=Geom, info=Info, max={_,_,Unit,_}},
#paint{pen=Pen, pen2=Pen2, font=Font, small=Small}) ->
- Str1 = observer_lib:to_str(MaxUnit),
- Str2 = observer_lib:to_str(MaxUnit div 2),
- Str3 = observer_lib:to_str(0),
-
- setFont(DC, Font, {0,0,0}),
- {TW,TH} = getTextExtent(DC, Str1),
- {SpaceW, _} = getTextExtent(DC, "W"),
+ #{p0:={GraphX0, GraphY0}, p1:={GraphX1,GraphY1}, scale:={ScaleW0,_},
+ txsz:={TW,TH,SpaceW}, txt:={BottomTextY, MaxTextY}, strs:={Str1,Str2,Str3}} = Geom,
- GraphX0 = ?BW+TW+?BW,
- GraphX1 = W-?BW*4,
+ ScaleW = ScaleW0*FetchFreq,
TopTextX = ?BW*3+TW,
- MaxTextY = TH+?BH,
- BottomTextY = H-?BH-TH,
SecondsY = BottomTextY - TH,
- GraphY0 = MaxTextY + (TH / 2),
- GraphY1 = SecondsY - ?BH,
- GraphW = GraphX1-GraphX0-1,
- GraphH = GraphY1-GraphY0-1,
+
GraphY25 = GraphY0 + (GraphY1 - GraphY0) / 4,
GraphY50 = GraphY0 + (GraphY1 - GraphY0) / 2,
GraphY75 = GraphY0 + 3*(GraphY1 - GraphY0) / 4,
- ScaleW = GraphW / 60,
- ScaleH = GraphH / Max,
setFont(DC, Small, {0,0,0}),
Align = fun(Str, Y) ->
@@ -462,14 +607,21 @@ draw_borders(Type, Info, DC, {W,H}, {Max, Unit, MaxUnit},
Align(Str3, GraphY1 - (TH / 2) + 1),
setPen(DC, Pen),
- DrawSecs = fun(Secs, Pos) ->
- Str = [observer_lib:to_str(Secs)|" s"],
+ DrawSecs = fun(Sec, {Pos, Prev}) ->
+ Str = observer_lib:to_str(Sec) ++ "s",
X = GraphX0+Pos,
- drawText(DC, Str, X-SpaceW, SecondsY),
strokeLine(DC, X, GraphY0, X, GraphY1+5),
- Pos + 10*ScaleW
+ TxtX = X-SpaceW,
+ case TxtX > Prev of
+ true ->
+ drawText(DC, Str, TxtX, SecondsY),
+ TxtW = SpaceW*length(Str),
+ {Pos + 10*ScaleW, TxtX+TxtW};
+ false ->
+ {Pos + 10*ScaleW, Prev}
+ end
end,
- lists:foldl(DrawSecs, 0, lists:seq(60,0, -10)),
+ lists:foldl(DrawSecs, {0, 0}, lists:seq(Secs,0, -10)),
strokeLine(DC, GraphX0-3, GraphY25, GraphX1, GraphY25),
strokeLine(DC, GraphX0-3, GraphY50, GraphX1, GraphY50),
@@ -526,7 +678,7 @@ draw_borders(Type, Info, DC, {W,H}, {Max, Unit, MaxUnit},
{GraphX1, GraphY1+1}, {GraphX1, GraphY0-1},
{GraphX0, GraphY0-1}])
end,
- {GraphX0+1, GraphY1, ScaleW, ScaleH, DrawBorder}.
+ {GraphX0+1, GraphY1, DrawBorder}.
to_string(Atom) ->
Name = atom_to_list(Atom),
@@ -543,43 +695,44 @@ uppercase([C|Rest]) ->
calc_max(Type, Max) ->
bytes(Type, Max).
-calc_max1(Max) when Max < 10 ->
- 10;
-calc_max1(Max) ->
- case Max div 10 of
- X when X < 10 ->
- case Max rem 10 of
- 0 -> Max;
- _ ->
- (X+1)*10
- end;
- X ->
- 10*calc_max1(X)
- end.
-
-bytes(runq, Val) ->
- Upper = calc_max1(Val),
- {Upper, "", Upper};
-bytes(utilz, Val) ->
- Upper = calc_max1(Val),
- {Upper, "", Upper};
-bytes(_, B) ->
+bytes(runq, Max) ->
+ Upper = calc_max1(max_value(Max)),
+ {Max, Upper, "", Upper};
+bytes(utilz, Max) ->
+ Upper = calc_max1(max_value(Max)),
+ {Max, Upper, "", Upper};
+bytes(_, Max) ->
+ B = max_value(Max),
KB = B div 1024,
MB = KB div 1024,
GB = MB div 1024,
if
GB > 10 ->
Upper = calc_max1(GB),
- {Upper*1024*1024*1024, "(GB)", Upper};
+ {Max, Upper*1024*1024*1024, "(GB)", Upper};
MB > 10 ->
Upper = calc_max1(MB),
- {Upper*1024*1024, "(MB)", Upper};
+ {Max, Upper*1024*1024, "(MB)", Upper};
KB > 0 ->
Upper = calc_max1(KB),
- {Upper*1024, "(KB)", Upper};
+ {Max, Upper*1024, "(KB)", Upper};
true ->
Upper = calc_max1(B),
- {Upper, "(B)", Upper}
+ {Max, Upper, "(B)", Upper}
+ end.
+
+calc_max1(Max) when Max < 10 ->
+ 10;
+calc_max1(Max) ->
+ case Max div 10 of
+ X when X < 10 ->
+ case Max rem 10 of
+ 0 -> Max;
+ _ ->
+ (X+1)*10
+ end;
+ X ->
+ 10*calc_max1(X)
end.
colors() ->
@@ -592,6 +745,25 @@ colors() ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% wxDC and ?wxGC wrappers
+make_gc(Panel,UseGC) ->
+ DC = case os:type() of
+ {win32, _} ->
+ %% Ugly hack to avoid flickering on windows, works on windows only
+ %% But the other platforms are doublebuffered by default
+ DC0 = wx:typeCast(wxBufferedPaintDC:new(Panel), wxPaintDC),
+ wxDC:clear(DC0),
+ DC0;
+ _ ->
+ wxPaintDC:new(Panel)
+ end,
+ if UseGC -> {?wxGC:create(DC), DC};
+ true -> {false, DC}
+ end.
+
+destroy_gc({GC, DC}) ->
+ (GC =/= false) andalso ?wxGC:destroy(GC),
+ wxPaintDC:destroy(DC).
+
haveGC() ->
try
wxGraphicsRenderer:getDefaultRenderer(),
@@ -599,44 +771,48 @@ haveGC() ->
catch _:_ -> false
end.
+getSize({_, DC}) ->
+ wxDC:getSize(DC).
+
setPen({false, DC}, Pen) ->
wxDC:setPen(DC, Pen);
-setPen({true, GC}, Pen) ->
+setPen({GC, _}, Pen) ->
?wxGC:setPen(GC, Pen).
setFont({false, DC}, Font, Color) ->
wxDC:setTextForeground(DC, Color),
wxDC:setFont(DC, Font);
-setFont({true, GC}, Font, Color) ->
+setFont({GC, _}, Font, Color) ->
?wxGC:setFont(GC, Font, Color).
setBrush({false, DC}, Brush) ->
wxDC:setBrush(DC, Brush);
-setBrush({true, GC}, Brush) ->
+setBrush({GC, _}, Brush) ->
?wxGC:setBrush(GC, Brush).
strokeLine({false, DC}, X0, Y0, X1, Y1) ->
wxDC:drawLine(DC, {round(X0), round(Y0)}, {round(X1), round(Y1)});
-strokeLine({true, GC}, X0, Y0, X1, Y1) ->
+strokeLine({GC, _}, X0, Y0, X1, Y1) ->
?wxGC:strokeLine(GC, X0, Y0, X1, Y1).
+strokeLines(_, [_]) -> ok;
strokeLines({false, DC}, Lines) ->
wxDC:drawLines(DC, [{round(X), round(Y)} || {X,Y} <- Lines]);
-strokeLines({true, GC}, Lines) ->
+strokeLines({GC, _}, Lines) ->
?wxGC:strokeLines(GC, Lines).
drawRoundedRectangle({false, DC}, X0, Y0, X1, Y1, R) ->
wxDC:drawRoundedRectangle(DC, {round(X0), round(Y0)}, {round(X1), round(Y1)}, round(R));
-drawRoundedRectangle({true, GC}, X0, Y0, X1, Y1, R) ->
+drawRoundedRectangle({GC, _}, X0, Y0, X1, Y1, R) ->
?wxGC:drawRoundedRectangle(GC, X0, Y0, X1, Y1, R).
drawText({false, DC}, Str, X, Y) ->
wxDC:drawText(DC, Str, {round(X),round(Y)});
-drawText({true, GC}, Str, X, Y) ->
+drawText({GC, _}, Str, X, Y) ->
?wxGC:drawText(GC, Str, X, Y).
getTextExtent({false, DC}, Str) ->
wxDC:getTextExtent(DC, Str);
-getTextExtent({true, GC}, Str) ->
+getTextExtent({GC, _}, Str) ->
{W,H,_,_} = ?wxGC:getTextExtent(GC, Str),
{W,H}.
diff --git a/lib/observer/test/Makefile b/lib/observer/test/Makefile
index e8bb7d0a52..6100af5e17 100644
--- a/lib/observer/test/Makefile
+++ b/lib/observer/test/Makefile
@@ -45,8 +45,8 @@ RELSYSDIR = $(RELEASE_PATH)/observer_test
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-ERL_MAKE_FLAGS += -pa $(ERL_TOP)/lib/test_server/ebin
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_MAKE_FLAGS +=
+ERL_COMPILE_FLAGS +=
EBIN = .
@@ -60,8 +60,6 @@ make_emakefile:
$(MODULES) > $(EMAKEFILE)
tests debug opt: make_emakefile
- cd $(ERL_TOP)/lib/test_server/src && \
- $(MAKE) ../ebin/test_server_line.beam
erl $(ERL_MAKE_FLAGS) -make
clean:
diff --git a/lib/observer/test/crashdump_helper.erl b/lib/observer/test/crashdump_helper.erl
index eea82d8c3c..e9a3ba0369 100644
--- a/lib/observer/test/crashdump_helper.erl
+++ b/lib/observer/test/crashdump_helper.erl
@@ -21,7 +21,7 @@
-module(crashdump_helper).
-export([n1_proc/2,remote_proc/2]).
-compile(r13).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
n1_proc(N2,Creator) ->
spawn(fun() -> n1_proc(Creator,N2,x,y,[]) end).
diff --git a/lib/observer/test/crashdump_viewer_SUITE.erl b/lib/observer/test/crashdump_viewer_SUITE.erl
index eae4ee01b9..a2b96ecb88 100644
--- a/lib/observer/test/crashdump_viewer_SUITE.erl
+++ b/lib/observer/test/crashdump_viewer_SUITE.erl
@@ -30,7 +30,6 @@
-export([init_per_testcase/2, end_per_testcase/2]).
-include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-include_lib("kernel/include/file.hrl").
-define(failed_file,"failed-cases.txt").
diff --git a/lib/observer/test/etop_SUITE.erl b/lib/observer/test/etop_SUITE.erl
index d4857c5e2f..4b05e4c2a0 100644
--- a/lib/observer/test/etop_SUITE.erl
+++ b/lib/observer/test/etop_SUITE.erl
@@ -26,7 +26,7 @@
-export([text/1,text/2,text_tracing_off/1,text_tracing_off/2]).
-export([init_per_testcase/2, end_per_testcase/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(default_timeout, ?t:minutes(1)).
diff --git a/lib/observer/test/observer_SUITE.erl b/lib/observer/test/observer_SUITE.erl
index 7f96d72e59..a33df61b98 100644
--- a/lib/observer/test/observer_SUITE.erl
+++ b/lib/observer/test/observer_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(observer_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("wx/include/wx.hrl").
-include_lib("observer/src/observer_tv.hrl").
diff --git a/lib/observer/test/ttb_SUITE.erl b/lib/observer/test/ttb_SUITE.erl
index bdf10f507d..f1649e6cb9 100644
--- a/lib/observer/test/ttb_SUITE.erl
+++ b/lib/observer/test/ttb_SUITE.erl
@@ -32,7 +32,7 @@
-export([init_per_testcase/2, end_per_testcase/2]).
-export([foo/0]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(default_timeout, ?t:minutes(1)).
-define(OUTPUT, "handler_output").
diff --git a/lib/odbc/test/Makefile b/lib/odbc/test/Makefile
index 114eb5373d..4fecea3aae 100644
--- a/lib/odbc/test/Makefile
+++ b/lib/odbc/test/Makefile
@@ -21,7 +21,7 @@ include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
-INCLUDES= -I. -I$(ERL_TOP)/lib/test_server/include/ -I$(ERL_TOP)/lib/odbc/src
+INCLUDES= -I. -I$(ERL_TOP)/lib/odbc/src
# ----------------------------------------------------
# Target Specs
diff --git a/lib/odbc/test/odbc_connect_SUITE.erl b/lib/odbc/test/odbc_connect_SUITE.erl
index 2d4173a008..41601a2750 100644
--- a/lib/odbc/test/odbc_connect_SUITE.erl
+++ b/lib/odbc/test/odbc_connect_SUITE.erl
@@ -26,7 +26,6 @@
-compile(export_all).
-include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-include("odbc_test.hrl").
-define(MAX_SEQ_TIMEOUTS, 10).
diff --git a/lib/odbc/test/odbc_data_type_SUITE.erl b/lib/odbc/test/odbc_data_type_SUITE.erl
index a56af650c2..25988bef2a 100644
--- a/lib/odbc/test/odbc_data_type_SUITE.erl
+++ b/lib/odbc/test/odbc_data_type_SUITE.erl
@@ -27,7 +27,6 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
--include("test_server_line.hrl").
-include("odbc_test.hrl").
%%--------------------------------------------------------------------
diff --git a/lib/odbc/test/odbc_query_SUITE.erl b/lib/odbc/test/odbc_query_SUITE.erl
index e8c2df7c31..79c756e956 100644
--- a/lib/odbc/test/odbc_query_SUITE.erl
+++ b/lib/odbc/test/odbc_query_SUITE.erl
@@ -26,7 +26,6 @@
-compile(export_all).
-include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-include("odbc_test.hrl").
%%--------------------------------------------------------------------
diff --git a/lib/odbc/test/odbc_start_SUITE.erl b/lib/odbc/test/odbc_start_SUITE.erl
index 8fb564d1f9..e16b4cfb7f 100644
--- a/lib/odbc/test/odbc_start_SUITE.erl
+++ b/lib/odbc/test/odbc_start_SUITE.erl
@@ -26,7 +26,6 @@
-compile(export_all).
-include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-include("odbc_test.hrl").
%% Test server callback functions
diff --git a/lib/odbc/test/odbc_test_lib.erl b/lib/odbc/test/odbc_test_lib.erl
index 6f49c019e3..88d772467c 100644
--- a/lib/odbc/test/odbc_test_lib.erl
+++ b/lib/odbc/test/odbc_test_lib.erl
@@ -26,7 +26,7 @@
-compile(export_all).
-include("odbc_test.hrl").
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
unique_table_name() ->
lists:reverse(lists:foldl(fun($@, Acc) -> [$t, $A |Acc] ;
diff --git a/lib/orber/test/Makefile b/lib/orber/test/Makefile
index b9be48c790..1d4e3c70f0 100644
--- a/lib/orber/test/Makefile
+++ b/lib/orber/test/Makefile
@@ -162,12 +162,10 @@ TARGET_FILES = \
ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/orber/ebin -pa $(ERL_TOP)/lib/ic/ebin
ERL_COMPILE_FLAGS += $(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/test_server/ebin \
-pa $(ERL_TOP)/lib/ic/ebin \
-pa $(ERL_TOP)/lib/orber/ebin \
-I$(ERL_TOP)/lib/orber \
- -I$(ERL_TOP)/lib/orber/test/$(IDLOUTDIR) \
- -I$(ERL_TOP)/lib/test_server/include
+ -I$(ERL_TOP)/lib/orber/test/$(IDLOUTDIR)
# ----------------------------------------------------
# Targets
diff --git a/lib/orber/test/cdrcoding_10_SUITE.erl b/lib/orber/test/cdrcoding_10_SUITE.erl
index 1fec91dca3..dac6e78ddd 100644
--- a/lib/orber/test/cdrcoding_10_SUITE.erl
+++ b/lib/orber/test/cdrcoding_10_SUITE.erl
@@ -28,7 +28,7 @@
-include("idl_output/Module.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/src/orber_iiop.hrl").
diff --git a/lib/orber/test/cdrcoding_11_SUITE.erl b/lib/orber/test/cdrcoding_11_SUITE.erl
index 324b9b2b17..f4fe3d06e3 100644
--- a/lib/orber/test/cdrcoding_11_SUITE.erl
+++ b/lib/orber/test/cdrcoding_11_SUITE.erl
@@ -28,7 +28,7 @@
-include("idl_output/Module.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/src/orber_iiop.hrl").
diff --git a/lib/orber/test/cdrcoding_12_SUITE.erl b/lib/orber/test/cdrcoding_12_SUITE.erl
index f0a8fe4d7f..8843233d35 100644
--- a/lib/orber/test/cdrcoding_12_SUITE.erl
+++ b/lib/orber/test/cdrcoding_12_SUITE.erl
@@ -29,7 +29,7 @@
-module(cdrcoding_12_SUITE).
-include("idl_output/Module.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/src/orber_iiop.hrl").
diff --git a/lib/orber/test/cdrlib_SUITE.erl b/lib/orber/test/cdrlib_SUITE.erl
index dd1f975d9e..8fc9c655ce 100644
--- a/lib/orber/test/cdrlib_SUITE.erl
+++ b/lib/orber/test/cdrlib_SUITE.erl
@@ -26,7 +26,7 @@
%%-----------------------------------------------------------------
-module(cdrlib_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(default_timeout, ?t:minutes(3)).
diff --git a/lib/orber/test/corba_SUITE.erl b/lib/orber/test/corba_SUITE.erl
index 914856f370..018d8b5f12 100644
--- a/lib/orber/test/corba_SUITE.erl
+++ b/lib/orber/test/corba_SUITE.erl
@@ -26,7 +26,7 @@
%%-----------------------------------------------------------------
-module(corba_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming.hrl").
-include_lib("orber/src/orber_iiop.hrl").
diff --git a/lib/orber/test/csiv2_SUITE.erl b/lib/orber/test/csiv2_SUITE.erl
index 7f45f16ef7..cf4dbec073 100644
--- a/lib/orber/test/csiv2_SUITE.erl
+++ b/lib/orber/test/csiv2_SUITE.erl
@@ -21,7 +21,7 @@
-module(csiv2_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming.hrl").
-include_lib("orber/src/orber_iiop.hrl").
diff --git a/lib/orber/test/data_types_SUITE.erl b/lib/orber/test/data_types_SUITE.erl
index d0e0eacad1..f910eecae7 100644
--- a/lib/orber/test/data_types_SUITE.erl
+++ b/lib/orber/test/data_types_SUITE.erl
@@ -26,7 +26,7 @@
-module(data_types_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-define(default_timeout, ?t:minutes(3)).
diff --git a/lib/orber/test/generated_SUITE.erl b/lib/orber/test/generated_SUITE.erl
index cc14b4ebc0..7af355620e 100644
--- a/lib/orber/test/generated_SUITE.erl
+++ b/lib/orber/test/generated_SUITE.erl
@@ -26,7 +26,7 @@
-module(generated_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-define(default_timeout, ?t:minutes(3)).
diff --git a/lib/orber/test/interceptors_SUITE.erl b/lib/orber/test/interceptors_SUITE.erl
index 57d5a5f831..ec30187aca 100644
--- a/lib/orber/test/interceptors_SUITE.erl
+++ b/lib/orber/test/interceptors_SUITE.erl
@@ -26,7 +26,7 @@
-module(interceptors_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/src/orber_iiop.hrl").
diff --git a/lib/orber/test/iop_ior_10_SUITE.erl b/lib/orber/test/iop_ior_10_SUITE.erl
index 5705a95710..edfe566dcd 100644
--- a/lib/orber/test/iop_ior_10_SUITE.erl
+++ b/lib/orber/test/iop_ior_10_SUITE.erl
@@ -26,7 +26,7 @@
%%-----------------------------------------------------------------
-module(iop_ior_10_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/src/orber_iiop.hrl").
-define(default_timeout, ?t:minutes(3)).
diff --git a/lib/orber/test/iop_ior_11_SUITE.erl b/lib/orber/test/iop_ior_11_SUITE.erl
index b32da44c68..d24e3fb882 100644
--- a/lib/orber/test/iop_ior_11_SUITE.erl
+++ b/lib/orber/test/iop_ior_11_SUITE.erl
@@ -26,7 +26,7 @@
%%-----------------------------------------------------------------
-module(iop_ior_11_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/src/orber_iiop.hrl").
-define(default_timeout, ?t:minutes(3)).
diff --git a/lib/orber/test/iop_ior_12_SUITE.erl b/lib/orber/test/iop_ior_12_SUITE.erl
index a12f341f04..725118b609 100644
--- a/lib/orber/test/iop_ior_12_SUITE.erl
+++ b/lib/orber/test/iop_ior_12_SUITE.erl
@@ -27,7 +27,7 @@
-module(iop_ior_12_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/src/orber_iiop.hrl").
-define(default_timeout, ?t:minutes(3)).
diff --git a/lib/orber/test/ip_v4v6_interop_SUITE.erl b/lib/orber/test/ip_v4v6_interop_SUITE.erl
index 995a11ae1e..4840501418 100644
--- a/lib/orber/test/ip_v4v6_interop_SUITE.erl
+++ b/lib/orber/test/ip_v4v6_interop_SUITE.erl
@@ -47,7 +47,7 @@
%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming.hrl").
-include_lib("orber/src/orber_iiop.hrl").
diff --git a/lib/orber/test/lname_SUITE.erl b/lib/orber/test/lname_SUITE.erl
index 2200ff6ed1..1fb4d7bbb9 100644
--- a/lib/orber/test/lname_SUITE.erl
+++ b/lib/orber/test/lname_SUITE.erl
@@ -26,7 +26,7 @@
%%-----------------------------------------------------------------
-module(lname_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming.hrl").
-include_lib("orber/COSS/CosNaming/lname.hrl").
diff --git a/lib/orber/test/multi_ORB_SUITE.erl b/lib/orber/test/multi_ORB_SUITE.erl
index 6b523229cc..abedcec407 100644
--- a/lib/orber/test/multi_ORB_SUITE.erl
+++ b/lib/orber/test/multi_ORB_SUITE.erl
@@ -21,7 +21,7 @@
-module(multi_ORB_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming.hrl").
-include_lib("orber/src/orber_iiop.hrl").
diff --git a/lib/orber/test/naming_context_SUITE.erl b/lib/orber/test/naming_context_SUITE.erl
index f99820fa24..626b9237b5 100644
--- a/lib/orber/test/naming_context_SUITE.erl
+++ b/lib/orber/test/naming_context_SUITE.erl
@@ -26,7 +26,7 @@
%%-----------------------------------------------------------------
-module(naming_context_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming.hrl").
-include_lib("orber/src/orber_iiop.hrl").
-include_lib("orber/include/corba.hrl").
diff --git a/lib/orber/test/orber_SUITE.erl b/lib/orber/test/orber_SUITE.erl
index 914705adb9..1ca22cd60b 100644
--- a/lib/orber/test/orber_SUITE.erl
+++ b/lib/orber/test/orber_SUITE.erl
@@ -19,7 +19,7 @@
%%
%%
-module(orber_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(default_timeout, ?t:minutes(15)).
-define(application, orber).
diff --git a/lib/orber/test/orber_acl_SUITE.erl b/lib/orber/test/orber_acl_SUITE.erl
index 8d1f9ebb6d..0d8f79de5c 100644
--- a/lib/orber/test/orber_acl_SUITE.erl
+++ b/lib/orber/test/orber_acl_SUITE.erl
@@ -26,7 +26,7 @@
%%-----------------------------------------------------------------
-module(orber_acl_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(default_timeout, ?t:minutes(5)).
diff --git a/lib/orber/test/orber_firewall_ipv4_in_SUITE.erl b/lib/orber/test/orber_firewall_ipv4_in_SUITE.erl
index 220029ec72..efa4f120c7 100644
--- a/lib/orber/test/orber_firewall_ipv4_in_SUITE.erl
+++ b/lib/orber/test/orber_firewall_ipv4_in_SUITE.erl
@@ -21,7 +21,7 @@
-module(orber_firewall_ipv4_in_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming.hrl").
-include_lib("orber/src/orber_iiop.hrl").
diff --git a/lib/orber/test/orber_firewall_ipv4_out_SUITE.erl b/lib/orber/test/orber_firewall_ipv4_out_SUITE.erl
index 270b166fe9..cfe1ab2d95 100644
--- a/lib/orber/test/orber_firewall_ipv4_out_SUITE.erl
+++ b/lib/orber/test/orber_firewall_ipv4_out_SUITE.erl
@@ -21,7 +21,7 @@
-module(orber_firewall_ipv4_out_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming.hrl").
-include_lib("orber/src/orber_iiop.hrl").
diff --git a/lib/orber/test/orber_firewall_ipv6_in_SUITE.erl b/lib/orber/test/orber_firewall_ipv6_in_SUITE.erl
index b0e28118f7..514504716f 100644
--- a/lib/orber/test/orber_firewall_ipv6_in_SUITE.erl
+++ b/lib/orber/test/orber_firewall_ipv6_in_SUITE.erl
@@ -21,7 +21,7 @@
-module(orber_firewall_ipv6_in_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming.hrl").
-include_lib("orber/src/orber_iiop.hrl").
diff --git a/lib/orber/test/orber_firewall_ipv6_out_SUITE.erl b/lib/orber/test/orber_firewall_ipv6_out_SUITE.erl
index 96884f3339..9ff57a0294 100644
--- a/lib/orber/test/orber_firewall_ipv6_out_SUITE.erl
+++ b/lib/orber/test/orber_firewall_ipv6_out_SUITE.erl
@@ -21,7 +21,7 @@
-module(orber_firewall_ipv6_out_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming.hrl").
-include_lib("orber/src/orber_iiop.hrl").
diff --git a/lib/orber/test/orber_nat_SUITE.erl b/lib/orber/test/orber_nat_SUITE.erl
index 1294f96681..0751cdf89c 100644
--- a/lib/orber/test/orber_nat_SUITE.erl
+++ b/lib/orber/test/orber_nat_SUITE.erl
@@ -21,7 +21,7 @@
-module(orber_nat_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming.hrl").
-include_lib("orber/src/orber_iiop.hrl").
diff --git a/lib/orber/test/orber_test_lib.erl b/lib/orber/test/orber_test_lib.erl
index 51025927ee..796ed21489 100644
--- a/lib/orber/test/orber_test_lib.erl
+++ b/lib/orber/test/orber_test_lib.erl
@@ -20,7 +20,7 @@
%%
-module(orber_test_lib).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/include/ifr_types.hrl").
-include_lib("orber/src/orber_iiop.hrl").
diff --git a/lib/orber/test/orber_web_SUITE.erl b/lib/orber/test/orber_web_SUITE.erl
index a88e0373bd..31c67be9d8 100644
--- a/lib/orber/test/orber_web_SUITE.erl
+++ b/lib/orber/test/orber_web_SUITE.erl
@@ -26,7 +26,7 @@
-module(orber_web_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/src/orber_iiop.hrl").
diff --git a/lib/orber/test/tc_SUITE.erl b/lib/orber/test/tc_SUITE.erl
index a1a5c74ae3..c670ebdea2 100644
--- a/lib/orber/test/tc_SUITE.erl
+++ b/lib/orber/test/tc_SUITE.erl
@@ -26,7 +26,7 @@
%%-----------------------------------------------------------------
-module(tc_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("orber/src/orber_iiop.hrl").
-define(default_timeout, ?t:minutes(3)).
diff --git a/lib/os_mon/test/Makefile b/lib/os_mon/test/Makefile
index cdfc13a4c1..aace77a3f0 100644
--- a/lib/os_mon/test/Makefile
+++ b/lib/os_mon/test/Makefile
@@ -55,8 +55,7 @@ RELSYSDIR = $(RELEASE_PATH)/os_mon_test
# FLAGS
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \
- -I$(ERL_TOP)/lib/snmp/include
+ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/snmp/include
# ----------------------------------------------------
# Targets
diff --git a/lib/os_mon/test/cpu_sup_SUITE.erl b/lib/os_mon/test/cpu_sup_SUITE.erl
index e96b54d3fe..13d47c6a89 100644
--- a/lib/os_mon/test/cpu_sup_SUITE.erl
+++ b/lib/os_mon/test/cpu_sup_SUITE.erl
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
%%
-module(cpu_sup_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
diff --git a/lib/os_mon/test/disksup_SUITE.erl b/lib/os_mon/test/disksup_SUITE.erl
index e41fc73ab2..8e2825ec26 100644
--- a/lib/os_mon/test/disksup_SUITE.erl
+++ b/lib/os_mon/test/disksup_SUITE.erl
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
%%
-module(disksup_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
diff --git a/lib/os_mon/test/memsup_SUITE.erl b/lib/os_mon/test/memsup_SUITE.erl
index 8ab61e9581..904c9b95b0 100644
--- a/lib/os_mon/test/memsup_SUITE.erl
+++ b/lib/os_mon/test/memsup_SUITE.erl
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
%%
-module(memsup_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
diff --git a/lib/os_mon/test/os_mon_SUITE.erl b/lib/os_mon/test/os_mon_SUITE.erl
index 5c484ef2a6..0f7ae3a508 100644
--- a/lib/os_mon/test/os_mon_SUITE.erl
+++ b/lib/os_mon/test/os_mon_SUITE.erl
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
%%
-module(os_mon_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
diff --git a/lib/os_mon/test/os_mon_mib_SUITE.erl b/lib/os_mon/test/os_mon_mib_SUITE.erl
index e68a139a74..f8fb9e20fc 100644
--- a/lib/os_mon/test/os_mon_mib_SUITE.erl
+++ b/lib/os_mon/test/os_mon_mib_SUITE.erl
@@ -30,7 +30,7 @@
%% > ct_run -suite os_mon_mib_SUITE -config os_mon_mib_SUITE.cfg
%%-----------------------------------------------------------------
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("os_mon/include/OTP-OS-MON-MIB.hrl").
-include_lib("snmp/include/snmp_types.hrl").
diff --git a/lib/os_mon/test/os_sup_SUITE.erl b/lib/os_mon/test/os_sup_SUITE.erl
index 768d95aebc..5857faa0a6 100644
--- a/lib/os_mon/test/os_sup_SUITE.erl
+++ b/lib/os_mon/test/os_sup_SUITE.erl
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
%%
-module(os_sup_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
diff --git a/lib/ose/Makefile b/lib/ose/Makefile
deleted file mode 100644
index 6119b75c3f..0000000000
--- a/lib/ose/Makefile
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-2009. 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
-
-#
-# Macros
-#
-
-SUB_DIRECTORIES = src doc/src
-
-include vsn.mk
-VSN = $(OSE_VSN)
-
-SPECIAL_TARGETS =
-
-#
-# Default Subdir Targets
-#
-include $(ERL_TOP)/make/otp_subdir.mk
diff --git a/lib/ose/doc/html/.gitignore b/lib/ose/doc/html/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ose/doc/html/.gitignore
+++ /dev/null
diff --git a/lib/ose/doc/man3/.gitignore b/lib/ose/doc/man3/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ose/doc/man3/.gitignore
+++ /dev/null
diff --git a/lib/ose/doc/man6/.gitignore b/lib/ose/doc/man6/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ose/doc/man6/.gitignore
+++ /dev/null
diff --git a/lib/ose/doc/pdf/.gitignore b/lib/ose/doc/pdf/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ose/doc/pdf/.gitignore
+++ /dev/null
diff --git a/lib/ose/doc/src/.gitignore b/lib/ose/doc/src/.gitignore
deleted file mode 100644
index 860e9e703e..0000000000
--- a/lib/ose/doc/src/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-ose.xml
diff --git a/lib/ose/doc/src/Makefile b/lib/ose/doc/src/Makefile
deleted file mode 100644
index 7ebd4125ba..0000000000
--- a/lib/ose/doc/src/Makefile
+++ /dev/null
@@ -1,133 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-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%
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(OSE_VSN)
-APPLICATION=ose
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
-
-# ----------------------------------------------------
-# Help application directory specification
-# ----------------------------------------------------
-EDOC_DIR = $(ERL_TOP)/lib/edoc
-SYNTAX_TOOLS_DIR = $(ERL_TOP)/lib/syntax_tools
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-XML_APPLICATION_FILES = ref_man.xml
-
-XML_REF3_FILES = \
- ose.xml \
- ose_erl_driver.xml
-
-XML_REF6_FILES = ose_app.xml
-
-XML_PART_FILES = part.xml
-XML_CHAPTER_FILES = notes.xml ose_intro.xml ose_signals_chapter.xml
-
-BOOK_FILES = book.xml
-
-XML_FILES = \
- $(BOOK_FILES) $(XML_CHAPTER_FILES) \
- $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_REF6_FILES) \
- $(XML_APPLICATION_FILES)
-
-# ----------------------------------------------------
-
-HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
-
-INFO_FILE = ../../info
-
-MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-MAN6_FILES = $(XML_REF6_FILES:%_app.xml=$(MAN6DIR)/%.6)
-
-HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
-
-TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-
-SPECS_FILES =
-
-TOP_SPECS_FILE =
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-XML_FLAGS +=
-
-SPECS_FLAGS = -I../../include -I../../../kernel/include
-
-OSE_SRC_DIR = ../../src
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-docs: man pdf html
-
-$(TOP_PDF_FILE): $(XML_FILES)
-
-pdf: $(TOP_PDF_FILE)
-
-html: $(HTML_REF_MAN_FILE)
-
-man: $(MAN3_FILES) $(MAN6_FILES)
-
-ose.xml: $(OSE_SRC_DIR)/ose.erl
- escript $(DOCGEN)/priv/bin/xml_from_edoc.escript\
- $(OSE_SRC_DIR)/$(@:%.xml=%.erl)
-
-debug opt:
-
-clean clean_docs:
- rm -rf $(HTMLDIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(MAN6DIR)/*
- rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f $(SPECDIR)/*
- rm -f errs core *~
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_docs_spec: docs
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(HTMLDIR)/* \
- "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
- $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
- $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6"
- $(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6"
-
-release_spec:
diff --git a/lib/ose/doc/src/book.xml b/lib/ose/doc/src/book.xml
deleted file mode 100644
index d62e0d32f4..0000000000
--- a/lib/ose/doc/src/book.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book xmlns:xi="http://www.w3.org/2001/XInclude">
- <header titlestyle="normal">
- <copyright>
- <year>2014</year><year>2014</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>OSE</title>
- <prepared>Lukas Larsson</prepared>
- <docno></docno>
- <date>2014-01-08</date>
- <rev>1.0</rev>
- <file>book.xml</file>
- </header>
- <insidecover>
- </insidecover>
- <pagetext>OSE</pagetext>
- <preamble>
- <contents level="2"></contents>
- </preamble>
- <parts>
- <xi:include href="part.xml"/>
- </parts>
- <applications>
- <xi:include href="ref_man.xml"/>
- </applications>
- <releasenotes>
- <xi:include href="notes.xml"/>
- </releasenotes>
- <listofterms></listofterms>
- <index></index>
-</book>
diff --git a/lib/ose/doc/src/notes.xml b/lib/ose/doc/src/notes.xml
deleted file mode 100644
index 06881b6c99..0000000000
--- a/lib/ose/doc/src/notes.xml
+++ /dev/null
@@ -1,109 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2014</year><year>2014</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>OSE Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>notes.xml</file>
- </header>
- <p>This document describes the changes made to the OSE application.</p>
-
-<section><title>Ose 1.1</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Change license text from Erlang Public License to Apache
- Public License v2</p>
- <p>
- Own Id: OTP-12845</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Ose 1.0.2</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Add missing release notes for the OSE application.</p>
- <p>
- Own Id: OTP-12177</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Ose 1.0.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Fix some spelling mistakes in documentation</p>
- <p>
- Own Id: OTP-12152</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Ose 1.0</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Erlang/OTP has been ported to the realtime operating
- system OSE. The port supports both smp and non-smp
- emulator. For details around the port and how to started
- see the User's Guide in the <seealso
- marker="ose:ose_intro">ose</seealso> application. </p>
- <p>
- Note that not all parts of Erlang/OTP has been ported. </p>
- <p>
- Notable things that work are: non-smp and smp emulators,
- OSE signal interaction, crypto, asn1, run_erl/to_erl,
- tcp, epmd, distribution and most if not all non-os
- specific functionality of Erlang.</p>
- <p>
- Notable things that does not work are: udp/sctp, os_mon,
- erl_interface, binding of schedulers.</p>
- <p>
- Own Id: OTP-11334</p>
- </item>
- </list>
- </section>
-
-</section>
-
-</chapter>
diff --git a/lib/ose/doc/src/ose_app.xml b/lib/ose/doc/src/ose_app.xml
deleted file mode 100644
index d555f0ec4f..0000000000
--- a/lib/ose/doc/src/ose_app.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE appref SYSTEM "appref.dtd">
-
-<appref>
- <header>
- <copyright>
- <year>2014</year><year>2014</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Enea OSE</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <app>ose</app>
- <appsummary>The OSE Application</appsummary>
- <description>
- <p>The OSE application contains modules and documentation that only
- applies when running Erlang/OTP on Enea OSE.</p>
- </description>
-
-</appref>
diff --git a/lib/ose/doc/src/ose_erl_driver.xml b/lib/ose/doc/src/ose_erl_driver.xml
deleted file mode 100644
index b804c29d2d..0000000000
--- a/lib/ose/doc/src/ose_erl_driver.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE cref SYSTEM "cref.dtd">
-
-<cref>
- <header>
- <copyright>
- <year>2013</year><year>2014</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>erl_driver for Enea OSE</title>
- <prepared>Lukas Larsson</prepared>
- <docno></docno>
- <date>2014-01-08</date>
- <rev>A</rev>
- <file>ose_erl_driver.xml</file>
- </header>
- <lib>ose_erl_driver</lib>
- <libsummary>Linked-in drivers in Enea OSE</libsummary>
- <description>
- <p>Writing Linked-in drivers that also work on Enea OSE is very similar for
- how you would do it for Unix. The difference from Unix is that
- driver_select, ready_input and ready_output all work with signals
- instead of file descriptors. This means that the driver_select is
- used to specify which type of signal should trigger calls to
- ready_input/ready_output. The functions described below are available
- to driver programmers on Enea OSE to facilitate this.
- </p>
- </description>
- <section>
- <title>DATA TYPES</title>
-
- <taglist>
- <tag><marker id="union_SIGNAL"/>union SIGNAL</tag>
- <item>See the Enea OSE SPI documentation for a description.</item>
- <tag><marker id="SIGSELECT"/>SIGSELECT</tag>
- <item>See the Enea OSE SPI documentation for a description.</item>
- <tag><marker id="ErlDrvEvent"/>ErlDrvEvent</tag>
- <item>The <c>ErlDrvEvent</c> is a handle to a signal number and id combination. It is passed to <seealso marker="erts:erl_driver#driver_select">driver_select(3)</seealso>.</item>
- <tag><marker id="ErlDrvOseEventId"/>ErlDrvOseEventId</tag>
- <item>This is the id used to associate a specific signal to a
- certain driver instance. </item>
- </taglist>
- </section>
- <funcs>
- <func>
- <name><ret>union SIGNAL *</ret><nametext>erl_drv_ose_get_signal(ErlDrvEvent drv_event)</nametext></name>
- <desc>
- <marker id="erl_drv_ose_get_signal"></marker>
- <p>Fetch the next signal associated with <c>drv_event</c>.
- Signals will be returned in the order which they were received and
- when no more signals are available <c>NULL</c> will be returned.
- Use this function in the ready_input/ready_output callbacks
- to get signals.</p>
- </desc>
- </func>
- <func>
- <name><ret>ErlDrvEvent</ret><nametext>erl_drv_ose_event_alloc(SIGSELECT signo, ErlDrvOseEventId id, ErlDrvOseEventId (*resolve_signal)(union SIGNAL* sig), void *extra)</nametext></name>
- <desc>
- <marker id="erl_drv_ose_event_alloc"></marker>
- <p>Create a new <c>ErlDrvEvent</c> associated with <c>signo</c>,
- <c>id</c> and uses the <c>resolve_signal</c> function to extract
- the <c>id</c> from a signal with <c>signo</c>. The <c>extra</c>
- parameter can be used for additional data. See
- <seealso marker="ose_signals_chapter#driver">
- Signals in a Linked-in driver</seealso> in the OSE User's Guide.
- </p>
- </desc>
- </func>
- <func>
- <name><ret>void</ret><nametext>erl_drv_ose_event_free(ErlDrvEvent drv_event)</nametext></name>
- <desc>
- <marker id="erl_drv_ose_event_free"></marker>
- <p>Free a <c>ErlDrvEvent</c>. This should always be done in the
- <seealso marker="erts:driver_entry#stop_select">stop_select</seealso>
- callback when the event is no longer being used.</p>
- </desc>
- </func>
- <func>
- <name><ret>void</ret><nametext>erl_drv_ose_event_fetch(ErlDrvEvent drv_event, SIGSELECT *signo, ErlDrvOseEventId *id, void **extra)</nametext></name>
- <desc>
- <marker id="erl_drv_ose_event_fetch"></marker>
- <p>Write the signal number, id and any extra data associated with <c>drv_event</c>
- into <c>*signo</c> and <c>*id</c> respectively. <c>NULL</c> can be
- also passed as <c>signo</c> or <c>id</c> in order to ignore that field.
- </p>
- </desc>
- </func>
- </funcs>
- <section>
- <title>SEE ALSO</title>
- <p>
- <seealso marker="erts:driver_entry">driver_entry(3)</seealso>,
- <seealso marker="erts:erl_driver">erl_driver(3)</seealso>
- </p>
- </section>
-</cref>
diff --git a/lib/ose/doc/src/ose_intro.xml b/lib/ose/doc/src/ose_intro.xml
deleted file mode 100644
index 982516c8bd..0000000000
--- a/lib/ose/doc/src/ose_intro.xml
+++ /dev/null
@@ -1,154 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2013</year><year>2014</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Introduction</title>
- <prepared>Lukas Larsson</prepared>
- <docno></docno>
- <date>2014-01-08</date>
- <rev>A</rev>
- <file>ose_intro.xml</file>
- </header>
-
- <section>
- <title>Features</title>
- </section>
-
- <section>
- <title>Starting Erlang/OTP</title>
- <p>
- Starting Erlang/OTP on OSE is not as simple as on Unix/Windows (yet).
- First of all you have to explicitly use the beam (or beam.smp) executables
- found in erts-X.Y.Z/bin as the load module that you run. This in turn
- means that you have to supply the raw beam arguments to the emulator
- when starting. Fortunately <c>erl</c> on Unix/Windows has a
- undocumented flag called <c>-emu_args_exit</c> that can be used to
- figure out what the arguments to beam look like. For example:</p>
- <code># erl +Mut false +A 10 +S 4:4 +Muycs256 +P 2096 +Q 2096 -emu_args_exit
--Mut
-false
--A
-10
--S
-4:4
--Muycs256
--P
-2096
--Q
-2096
---
--root
-/usr/local/lib/erlang
--progname
-erl
---
--home
-/home/erlang
---</code>
- <p>
- The arguments are printed on separate lines to make it possible to know
- what has to be quoted with &quot;. Each line is one quotable unit.
- So taking the arguments above you can supply them to pm_create or
- just execute directly on the command line. For example:</p>
- <code>rtose@acp3400> pm_install erlang /mst/erlang/erts-6.0/bin/beam.smp
-rtose@acp3400> pm_create -c ARGV="-Mut false -A 10 -S 4:4 -Muycs256 -P 2096 -Q 2099 -- -root /mst/erlang -progname erl -- -home /mst/erlang --" erlang
-pid: 0x110059
-rtose@acp3400> pm_start 0x110059</code>
- <p>
- Also note that since we are running erl to figure out the arguments on a
- separate machine the paths have to be updated. In the example above
- <c>/usr/local/lib/erlang</c> was replaced by <c>/mst/erlang/</c>. The
- goal is to in future releases not have to do the special argument handling
- but for now (OTP 17.0) you have to do it.
- </p>
- <note>
- Because of a limitation in the way the OSE handles stdio when starting
- load modules using pm_install/create the Erlang shell only reads every
- other command from stdin. However if you start Erlang using run_erl
- you do not have this problem. So it is highly recommended that you
- start Erlang using run_erl.
- </note>
- </section>
-
- <section>
- <title>run_erl and to_erl</title>
- <p>
- In OSE run_erl and to_erl are combined into a single load module called
- run_erl_lm. Installing and starting the load module will add two new
- shell commands called run_erl and to_erl. They work in exactly the same
- way as the unix variants of run_erl and to_erl, except that the read
- and write pipes have to be placed under the /pipe vm. One additional
- option also exists to run_erl on ose:
- <taglist>
- <tag><c>-block Name</c></tag>
- <item>The name of the install handle and block that will be created/used by
- installing and exectuting the first part of the command. If nothing
- if given the basename of the load module will be used for this value.
- Example:
- <code>pm_install erlang /path/to/erlang/vm/beam.smp
-run_erl -daemon -block erlang /pipe/ /mst/erlang_logs/ "beam.smp -A 1 -- -root /mst/erlang -- -home /mst --"</code>
- </item>
- </taglist>
- The same argument munching as when starting Erlang/OTP without run_erl
- has to be done. If <c>-daemon</c> is given then all error printouts
- are sent to the ramlog.
- See also
- <seealso marker="erts:run_erl">run_erl</seealso> for more details.
- </p>
- <p>
- Below is an example of how to get started with <c>run_erl_lm</c>.
- <code>rtose@acp3400> pm_install run_erl_lm /mst/erlang/erts-6.0/bin/run_erl_lm
-rtose@acp3400> pm_create run_erl_lm
-pid: 0x1c005d
-rtose@acp3400> pm_start 0x1c005d
-rtose@acp3400> mkdir /mst/erlang_log
-rtose@acp3400> run_erl -daemon /pipe/ /mst/erlang_log/ "/mst/erlang/erts-6.0/bin/beam.smp -A 1 -- -root /mst/erlang -- -home /mst --"
-rtose@acp3400> to_erl
-Attaching to /pipe/erlang.pipe.1 (^C to exit)
-os:type().
-{ose,release}
-2>
-'to_erl' terminated.</code>
- Note that Ctrl-C is used instead of Ctrl-D to exit the to_erl shell.
- </p>
- </section>
-
- <section>
- <title>epmd</title>
- <p>
- In OSE epmd will not be started automatically so if you want to use
- Erlang distribution you have to manually start epmd.
- </p>
- </section>
-
- <section>
- <title>VM Process Priorities</title>
- <p>
- It is possible to set the priorities you want for the OSE processes that
- thr emulator creates in the lmconf. An example of how to do it can be
- found in the default lmconf file in
- $ERL_TOP/erts/emulator/sys/ose/beam.lmconf.
- </p>
- </section>
-
-</chapter>
diff --git a/lib/ose/doc/src/ose_signals_chapter.xml b/lib/ose/doc/src/ose_signals_chapter.xml
deleted file mode 100644
index bcf2259577..0000000000
--- a/lib/ose/doc/src/ose_signals_chapter.xml
+++ /dev/null
@@ -1,240 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2013</year><year>2014</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Interacting with Enea OSE</title>
- <prepared>Lukas Larsson</prepared>
- <docno></docno>
- <date>2014-01-08</date>
- <rev>A</rev>
- <file>ose_signals_chapter.xml</file>
- </header>
-
- <marker id="introduction"></marker>
- <section>
- <title>Introduction</title>
- <p>The main way which programs on Enea OSE interact is through the
- usage of message passing, much the same way as Erlang processes
- communicate. There are two ways in which an Erlang programmer can
- interact with the signals sent from other Enea OSE processes; either
- through the provided <c>ose</c> module, or by writing a custom linked-in
- driver. This User's Guide describes and provides examples for both
- approaches.
- </p>
- </section>
-
- <marker id="erlang"></marker>
- <section>
- <title>Signals in Erlang</title>
- <p>Erlang/OTP on OSE provides a erlang module called
- <seealso marker="ose:ose">ose</seealso> that can be used to interact
- with other OSE processes using message passing. The api in the module
- is very similar to the native OSE api, so for details of how the
- functions work please refer to the official OSE documenation. Below
- is an example usage of the API.
- </p>
- <code>1> P1 = ose:open("p1").
-#Port&gt;0.344>
-2> ose:hunt(P1,"p2").
-{#Port&gt;0.344>,1}
-3> P2 = ose:open("p2").
-#Port&gt;0.355>
-4> flush().
-Shell got {mailbox_up,#Port&gt;0.344>,{#Port&gt;0.344>,1},852189}
-ok
-5> ose:listen(P1,[1234]).
-ok
-6> ose:send(P2,ose:get_id(P1),1234,&gt;&gt;"hello">>).
-ok
-7> flush().
-Shell got {message,#Port&gt;0.344>,{852189,1245316,1234,&gt;&gt;"hello">>}}
-ok</code>
- </section>
-
- <marker id="driver"></marker>
- <section>
- <title>Signals in a Linked-in driver</title>
- <p>
- Writing Linked-in drivers for OSE is very similar to how it is done
- for Unix/Windows. It is only the way in which the driver subscribes
- and consumed external events that is different. In Unix (and Windows)
- file descriptiors (and Event Objects) are used to select on. On OSE
- we use signals to deliver the same functionality. There are two large
- differences between a signal and an fd.
- </p>
- <p>
- In OSE it is not possible for a signal number to be a unique identifier
- for a resource in the same way as an fd is. For example; let's say we
- implement a driver that does an asynchronous hunt that uses signal
- number 1234 as the hunt_sig. If we want to be able to have multiple
- hunt ports running at the same time we have to have someway of routing
- the signal to the correct port. This is achieved by supplying a secondary
- id that can be retrieved through the meta-data or payload of the signal,
- e.g:
- <code>ErlDrvEvent event = erl_drv_ose_event_alloc(1234,port,resolver);</code>
- The event you get back from
- <seealso marker="ose_erl_driver#erl_drv_ose_event_alloc">
- erl_drv_ose_event_alloc</seealso> can then be used by
- <seealso marker="erts:erl_driver#driver_select">driver_select</seealso>
- to subscribe to signals. The first argument is just the signal number
- that we are interested in. The second is the id that we choose to use,
- in this case the port id that we got in the
- <seealso marker="erts:driver_entry#start">start</seealso> callback is
- used. The third argument is a function pointer to a function that can
- be used to figure out the id from a given signal. The fourth argument can
- point to any additional data you might want to associate with the event.
- There is a complete. You can examine the data contained in the event with
- <seealso marker="ose_erl_driver#erl_drv_ose_event_fetch">erl_drv_ose_event_fetch</seealso>
- , eg:
- <code>erl_drv_ose_event_fetch(event, &amp;signal, &amp;port, (void **)&amp;extra);</code>
- example of what this could look like in
- <seealso marker="#example">the next section</seealso>.
- <note>It is very important to issue the driver_select call before
- any of the signals you are interested in are sent. If driver_select
- is called after the signal is sent, there is a high probability that it
- will be lost.</note>
- </p>
- <p>
- The other difference from unix is that in OSE the payload of the event
- (i.e. the signal data) is already received when the ready_output/input
- callbacks are called. This means that you access the data of a signal
- by calling <seealso marker="ose_erl_driver#erl_drv_ose_get_signal">
- erl_drv_ose_get_signal</seealso>. Additionally multiple signals might be
- associated with the event, so you should call
- <seealso marker="ose_erl_driver#erl_drv_ose_get_signal">
- erl_drv_ose_get_signal</seealso> until <c>NULL</c> is returned.
- </p>
- </section>
-
- <marker id="example"></marker>
- <section>
- <title>Example Linked-in driver</title>
-<code>#include "erl_driver.h"
-#include "ose.h"
-
-struct huntsig {
- SIGSELECT signo;
- ErlDrvPort port;
-};
-
-union SIGNAL {
- SIGSELECT signo;
- struct huntsig;
-}
-
-/* Here we have to get the id from the signal. In this case we use the
- port id since we have control over the data structure of the signal.
- It is however possible to use anything in here. The only restriction
- is that the same id has to be used for all signals of the same number.*/
-ErlDrvOseEventId resolver(union SIGNAL *sig) {
- return (ErlDrvOseEventId)sig->huntsig.port;
-}
-
-static int drv_init(void) { return 0; };
-
-static ErlDrvData drv_start(ErlDrvPort port, char *command) {
- return (ErlDrvData)port;
-}
-
-static ErlDrvSSizeT control(ErlDrvData driver_data, unsigned int cmd,
- char *buf, ErlDrvSizeT len,
- char **rbuf, ErlDrvSizeT rlen) {
- ErlDrvPort port = (ErlDrvPort)driver_data;
-
- /* An example of extra data to associate with the event */
- char *extra_data = driver_alloc(80);
- snprintf("extra_data, "Event, sig_no: 1234, and port: %d", port);
-
- /* Create a new event to select on */
- ErlDrvOseEvent evt = erl_drv_ose_event_alloc(1234,port,resolver, extra_data);
-
- /* Make sure to do the select call _BEFORE_ the signal arrives.
- The signal might get lost if the hunt call is done before the
- select. */
- driver_select(port,evt,ERL_DRV_READ|ERL_DRV_USE,1);
-
- union SIGNAL *sig = alloc(sizeof(union SIGNAL),1234);
- sig->huntsig.port = port;
- hunt("testprocess",0,NULL,&amp;sig);
- return 0;
-}
-
-static void ready_input(ErlDrvData driver_data, ErlDrvEvent evt) {
- char *extra_data;
- /* Get the first signal payload from the event */
- union SIGNAL *sig = erl_drv_ose_get_signal(evt);
- ErlDrvPort port = (ErlDrvPort)driver_data;
- while (sig != NULL) {
- if (sig->signo == 1234) {
- /* Print out the string we added as the extra parameter */
- erl_drv_ose_event_fetch(evt, NULL, NULL, (void **)&amp;extra_data);
- printf("We've received: %s\n", extra_data);
-
- /* If it is our signal we send a message with the sender of the signal
- to the controlling erlang process */
- ErlDrvTermData reply[] = { ERL_DRV_UINT, (ErlDrvUInt)sender(&amp;sig) };
- erl_drv_send_term(port,reply,sizeof(reply) / sizeof(reply[0]));
- }
-
- /* Cleanup the signal and deselect on the event.
- Note that the event itself has to be free'd in the stop_select
- callback. */
- free_buf(&amp;sig);
- driver_select(port,evt,ERL_DRV_READ|ERL_DRV_USE,0);
-
- /* There could be more than one signal waiting in this event, so
- we have to loop until sig == NULL */
- sig = erl_drv_ose_get_signal(evt);
- }
-}
-
-static void stop_select(ErlDrvEvent event, void *reserved)
-{
- /* Free the extra_data */
- erl_drv_ose_event_fetch(evt, NULL, NULL, (void **)&amp;extra_data);
- driver_free(extra_data);
-
- /* Free the event itself */
- erl_drv_ose_event_free(event);
-}
-
-/**
- * Setup the driver entry for the Erlang runtime
- **/
-ErlDrvEntry ose_signal_driver_entry = {
- .init = drv_init,
- .start = drv_start,
- .stop = drv_stop,
- .ready_input = ready_input,
- .driver_name = DRIVER_NAME,
- .control = control,
- .extended_marker = ERL_DRV_EXTENDED_MARKER,
- .major_version = ERL_DRV_EXTENDED_MAJOR_VERSION,
- .minor_version = ERL_DRV_EXTENDED_MINOR_VERSION,
- .driver_flags = ERL_DRV_FLAG_USE_PORT_LOCKING,
- .stop_select = stop_select
-};
-</code>
- </section>
-
-</chapter>
diff --git a/lib/ose/doc/src/part.xml b/lib/ose/doc/src/part.xml
deleted file mode 100644
index 0c9ebd16c0..0000000000
--- a/lib/ose/doc/src/part.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2014</year>
- <year>2014</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- 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.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>OSE User's Guide</title>
- <prepared>Lukas Larsson</prepared>
- <docno></docno>
- <date>2014-01-08</date>
- <rev>1.0</rev>
- <file>part.xml</file>
- </header>
- <description>
- <p><em>OSE</em>.</p>
- </description>
- <xi:include href="ose_intro.xml"/>
- <xi:include href="ose_signals_chapter.xml"/>
-</part>
diff --git a/lib/ose/doc/src/ref_man.xml b/lib/ose/doc/src/ref_man.xml
deleted file mode 100644
index 964e5ab8ff..0000000000
--- a/lib/ose/doc/src/ref_man.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE application SYSTEM "application.dtd">
-
-<application xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2014</year><year>2014</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>OSE Reference Manual</title>
- <prepared>Lukas Larsson</prepared>
- <docno></docno>
- <date>2014-01-08</date>
- <rev>1.0</rev>
- <file>ref_man.xml</file>
- </header>
- <description>
- <p>The Standard Erlang Libraries application, <em>STDLIB</em>,
- contains modules for manipulating lists, strings and files etc.</p>
- <br></br>
- </description>
- <xi:include href="ose_app.xml"/>
- <xi:include href="ose.xml"/>
- <xi:include href="ose_erl_driver.xml"/>
-</application>
diff --git a/lib/ose/ebin/.gitignore b/lib/ose/ebin/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ose/ebin/.gitignore
+++ /dev/null
diff --git a/lib/ose/include/.gitignore b/lib/ose/include/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ose/include/.gitignore
+++ /dev/null
diff --git a/lib/ose/info b/lib/ose/info
deleted file mode 100644
index 85c07dbe82..0000000000
--- a/lib/ose/info
+++ /dev/null
@@ -1,2 +0,0 @@
-group: misc Miscellaneous Applications
-short: Description of Enea OSE specific functionality
diff --git a/lib/ose/src/Makefile b/lib/ose/src/Makefile
deleted file mode 100644
index a89e9392e9..0000000000
--- a/lib/ose/src/Makefile
+++ /dev/null
@@ -1,107 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-2013. 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=$(OSE_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/ose-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-MODULES= \
- ose
-
-HRL_FILES=
-
-INTERNAL_HRL_FILES=
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
-
-APP_FILE= ose.app
-
-APP_SRC= $(APP_FILE).src
-APP_TARGET= $(EBIN)/$(APP_FILE)
-
-APPUP_FILE= ose.appup
-
-APPUP_SRC= $(APPUP_FILE).src
-APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-ifeq ($(NATIVE_LIBS_ENABLED),yes)
-ERL_COMPILE_FLAGS += +native
-endif
-ERL_COMPILE_FLAGS += -I../include -I../../kernel/include -Werror
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(TARGET_FILES)
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f core
- rm -f erl_parse.erl
-
-docs:
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-$(APP_TARGET): $(APP_SRC) ../vsn.mk
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
-
-$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/include"
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
-
-release_docs_spec:
-
-# ----------------------------------------------------
-# Dependencies -- alphabetically, please
-# ----------------------------------------------------
diff --git a/lib/ose/src/ose.app.src b/lib/ose/src/ose.app.src
deleted file mode 100644
index 036779eb16..0000000000
--- a/lib/ose/src/ose.app.src
+++ /dev/null
@@ -1,28 +0,0 @@
-%% This is an -*- erlang -*- file.
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2011. 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%
-%%
-{application, ose,
- [{description, "Enea OSE specific modules"},
- {vsn, "%VSN%"},
- {modules, [ose]},
- {registered,[]},
- {applications, [stdlib,kernel]},
- {env, []},
- {runtime_dependencies, ["stdlib-2.0","erts-6.0"]}]}.
diff --git a/lib/ose/src/ose.appup.src b/lib/ose/src/ose.appup.src
deleted file mode 100644
index 28b6da3439..0000000000
--- a/lib/ose/src/ose.appup.src
+++ /dev/null
@@ -1,23 +0,0 @@
-%% -*- erlang -*-
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2013. 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%
-{"%VSN%",
- [
- ],
- [
- ]}.
diff --git a/lib/ose/src/ose.erl b/lib/ose/src/ose.erl
deleted file mode 100644
index 5534dba4d4..0000000000
--- a/lib/ose/src/ose.erl
+++ /dev/null
@@ -1,453 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2013. 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%
-%%
-%% @doc Interface module for OSE messaging and process monitoring from Erlang
-%%
-%% For each mailbox created through {@link open/1} a OSE phantom process with
-%% that name is started. Since phantom processes are used the memory footprint
-%% of each mailbox is quite small.
-%%
-%% To receive messages you first have to subscribe to the specific message
-%% numbers that you are interested in with {@link listen/2}. The messages
-%% will be sent to the Erlang process that created the mailbox.
-%%
-%% @end
-%%
--module(ose).
-
-%%==============================================================================
-%% Exported API
-%%==============================================================================
--export([open/1,
- close/1,
- get_id/1,
- get_name/2,
- hunt/2,
- dehunt/2,
- attach/2,
- detach/2,
- send/4,
- send/5,
- listen/2
- ]).
-
-%%==============================================================================
-%% Types
-%%==============================================================================
--opaque mailbox() :: port().
-%% Mailbox handle. Implemented as an erlang port.
-
--opaque mailbox_id() :: integer().
-%% Mailbox ID, this is the same as the process id of an OSE process.
-%% An integer.
-
--type message_number() :: 0..4294967295.
-%% OSE Signal number
-
--opaque hunt_ref() :: {mailbox(),integer()}.
-%% Reference from a hunt request. This term will be included
-%% in a successful hunt response.
-
--opaque attach_ref() :: {mailbox(),integer()}.
-%% Reference from an attach request. This term will be included
-%% in the term returned when the attached mailbox disappears.
-
--export_type([mailbox_id/0,
- message_number/0,
- mailbox/0,
- hunt_ref/0,
- attach_ref/0]).
-
-%%==============================================================================
-%% Defines
-%%==============================================================================
--define(DRIVER_NAME, "ose_signal_drv").
--define(GET_SPID, 1).
--define(GET_NAME, 2).
--define(HUNT, 100).
--define(DEHUNT, 101).
--define(ATTACH, 102).
--define(DETACH, 103).
--define(SEND, 104).
--define(SEND_W_S, 105).
--define(LISTEN, 106).
--define(OPEN, 200).
-
--define(INT_32BIT(Int),(is_integer(Int) andalso (Int >= 0) andalso (Int < (1 bsl 32)))).
-
-%%==============================================================================
-%% API functions
-%%==============================================================================
-
-%%------------------------------------------------------------------------------
-%% @doc Create a mailbox with the given name and return a port that handles
-%% the mailbox.
-%%
-%% An OSE phantom process with the given name will be created that will send any
-%% messages sent through this mailbox. Any messages sent to the new OSE process
-%% will automatically be converted to an Erlang message and sent to the Erlang
-%% process that calls this function. See {@link listen/2} for details about the
-%% format of the message sent.
-%%
-%% The caller gets linked to the created mailbox.
-%%
-%% raises: `badarg' | `system_limit'
-%%
-%% @see listen/2
-%% @end
-%%------------------------------------------------------------------------------
--spec open(Name) -> Port when
- Name :: iodata(),
- Port :: mailbox().
-open(Name) ->
- try open_port({spawn_driver,?DRIVER_NAME}, [binary]) of
- Port ->
- try port_command(Port,[?OPEN,Name]) of
- true ->
- receive
- {ose_drv_reply,Port,{error,Error}} ->
- close(Port),
- erlang:error(Error,[Name]);
- {ose_drv_reply,Port,ok} ->
- Port
- end
- catch
- error:badarg -> close(Port),erlang:error(badarg,[Name])
- end
- catch
- error:badarg -> erlang:error(badarg,[Name])
- end.
-
-%%------------------------------------------------------------------------------
-%% @doc Close a mailbox
-%%
-%% This kills the OSE phantom process associated with this mailbox.
-%%
-%% Will also consume any ``{'EXIT',Port,_}'' message from the port that comes
-%% due to the port closing when the calling process traps exits.
-%%
-%% raises: `badarg'
-%% @end
-%%------------------------------------------------------------------------------
--spec close(Port) -> ok when
- Port :: mailbox().
-close(Port) when is_port(Port) ->
- %% Copied from prim_inet
- case erlang:process_info(self(), trap_exit) of
- {trap_exit,true} ->
- link(Port),
- catch erlang:port_close(Port),
- receive {'EXIT',Port,_} -> ok end;
- {trap_exit,false} ->
- catch erlang:port_close(Port),
- ok
- end;
-close(NotPort) ->
- erlang:error(badarg,[NotPort]).
-
-%%------------------------------------------------------------------------------
-%% @doc Get the mailbox id for the given port.
-%%
-%% The mailbox id is the same as the OSE process id of the OSE phantom process
-%% that this mailbox represents.
-%%
-%% raises: `badarg'
-%% @end
-%%------------------------------------------------------------------------------
--spec get_id(Port) -> Pid when
- Port :: mailbox(),
- Pid :: mailbox_id().
-get_id(Port) ->
- try port_control(Port, ?GET_SPID, <<>>) of
- <<Spid:32>> -> Spid
- catch error:_Error ->
- erlang:error(badarg,[Port])
- end.
-
-%%------------------------------------------------------------------------------
-%% @doc Get the mailbox name for the given mailbox id.
-%%
-%% The mailbox name is the name of the OSE process with process id Pid.
-%%
-%% This call will fail with badarg if the underlying system does not support
-%% getting the name from a process id.
-%%
-%% raises: `badarg'
-%% @end
-%%------------------------------------------------------------------------------
--spec get_name(Port, Pid) -> Name | undefined when
- Port :: mailbox(),
- Pid :: mailbox_id(),
- Name :: binary().
-get_name(Port, Pid) when ?INT_32BIT(Pid) ->
- try port_control(Port, ?GET_NAME, <<Pid:32>>) of
- [] -> undefined;
- Res -> Res
- catch error:_Error ->
- erlang:error(badarg,[Port,Pid])
- end;
-get_name(Port, Pid) ->
- erlang:error(badarg,[Port,Pid]).
-
-
-%%------------------------------------------------------------------------------
-%% @doc Hunt for OSE process by name.
-%%
-%% Will send `{mailbox_up, Port, Ref, MboxId}'
-%% to the calling process when the OSE process becomes available.
-%%
-%% Returns a reference term that can be used to cancel the hunt
-%% using {@link dehunt/2}.
-%%
-%% raises: `badarg'
-%%
-%% @end
-%%------------------------------------------------------------------------------
--spec hunt(Port, HuntPath) -> Ref when
- Port :: mailbox(),
- HuntPath :: iodata(),
- Ref :: hunt_ref().
-hunt(Port, HuntPath) ->
- try port_command(Port, [?HUNT,HuntPath]) of
- true ->
- receive
- {ose_drv_reply,Port,{error,Error}} ->
- erlang:error(Error,[Port,HuntPath]);
- {ose_drv_reply,Port,Ref} ->
- Ref
- end
- catch error:_Error ->
- erlang:error(badarg,[Port,HuntPath])
- end.
-
-%%------------------------------------------------------------------------------
-%% @doc Stop hunting for OSE process.
-%%
-%% If a message for this hunt has been sent but not received
-%% by the calling process, it is removed from the message queue.
-%% Note that this only works if the same process that did
-%% the hunt does the dehunt.
-%%
-%% raises: `badarg'
-%%
-%% @see hunt/2
-%% @end
-%%------------------------------------------------------------------------------
--spec dehunt(Port, Ref) -> ok when
- Port :: mailbox(),
- Ref :: hunt_ref().
-dehunt(Port, {Port,Ref}) when ?INT_32BIT(Ref) ->
- try port_command(Port, <<?DEHUNT:8, Ref:32>>) of
- true ->
- receive
- {ose_drv_reply,Port,{error,enoent}} ->
- %% enoent could mean that it is in the message queue
- receive
- {mailbox_up, Port, {Port,Ref}, _} ->
- ok
- after 0 ->
- ok
- end;
- {ose_drv_reply,Port,ok} ->
- ok
- end
- catch error:_Error ->
- erlang:error(badarg,[Port,{Port,Ref}])
- end;
-dehunt(Port,Ref) ->
- erlang:error(badarg,[Port,Ref]).
-
-%%------------------------------------------------------------------------------
-%% @doc Attach to an OSE process.
-%%
-%% Will send `{mailbox_down, Port, Ref, MboxId}'
-%% to the calling process if the OSE process exits.
-%%
-%% Returns a reference that can be used to cancel the attachment
-%% using {@link detach/2}.
-%%
-%% raises: `badarg' | `enomem'
-%%
-%% @end
-%%------------------------------------------------------------------------------
--spec attach(Port,Pid) -> Ref when
- Port :: mailbox(),
- Pid :: mailbox_id(),
- Ref :: attach_ref().
-attach(Port, Spid) when ?INT_32BIT(Spid) ->
- try port_command(Port, <<?ATTACH:8, Spid:32>>) of
- true ->
- receive
- {ose_drv_reply,Port,{error,Error}} ->
- erlang:error(Error,[Port,Spid]);
- {ose_drv_reply,Port,Ref} ->
- Ref
- end
- catch error:_Error ->
- erlang:error(badarg,[Port,Spid])
- end;
-attach(Port,Spid) ->
- erlang:error(badarg,[Port,Spid]).
-
-
-%%------------------------------------------------------------------------------
-%% @doc Remove attachment to an OSE process.
-%%
-%% If a message for this monitor has been sent but not received
-%% by the calling process, it is removed from the message queue.
-%% Note that this only works of the same process
-%% that did the attach does the detach.
-%%
-%% raises: `badarg'
-%%
-%% @see attach/2
-%% @end
-%%------------------------------------------------------------------------------
--spec detach(Port,Ref) -> ok when
- Port :: mailbox(),
- Ref :: attach_ref().
-detach(Port, {Port,Ref} ) when ?INT_32BIT(Ref) ->
- try port_command(Port, <<?DETACH:8, Ref:32>>) of
- true ->
- receive
- {ose_drv_reply,Port,{error,enoent}} ->
- %% enoent could mean that it is in the message queue
- receive
- {mailbox_down,Port,{Port,Ref},_} ->
- ok
- after 0 ->
- ok
- end;
- {ose_drv_reply,Port,ok} ->
- ok
- end
- catch error:_Error ->
- erlang:error(badarg,[Port,{Port,Ref}])
- end;
-detach(Port,Ref) ->
- erlang:error(badarg,[Port,Ref]).
-
-%%------------------------------------------------------------------------------
-%% @doc Send an OSE message.
-%%
-%% The message is sent from the OSE process' own ID that is: `get_id(Port)'.
-%%
-%% raises: `badarg'
-%%
-%% @see send/5
-%% @end
-%%------------------------------------------------------------------------------
--spec send(Port,Pid,SigNo,SigData) -> ok when
- Port :: mailbox(),
- Pid :: mailbox_id(),
- SigNo :: message_number(),
- SigData :: iodata().
-send(Port, Spid, SigNo, SigData) when ?INT_32BIT(Spid), ?INT_32BIT(SigNo) ->
- try erlang:port_command(Port, [<<?SEND:8, Spid:32, SigNo:32>>, SigData]) of
- true -> ok
- catch error:_Error ->
- erlang:error(badarg,[Port,Spid,SigNo,SigData])
- end;
-send(Port,Spid,SigNo,SigData) ->
- erlang:error(badarg,[Port,Spid,SigNo,SigData]).
-
-
-%%------------------------------------------------------------------------------
-%% @doc Send an OSE message with different sender.
-%%
-%% As {@link send/4} but the sender will be `SenderPid'.
-%%
-%% raises: `badarg'
-%%
-%% @see send/4
-%% @end
-%%------------------------------------------------------------------------------
--spec send(Port,Pid,SenderPid,SigNo,SigData) -> ok when
- Port :: mailbox(),
- Pid :: mailbox_id(),
- SenderPid :: mailbox_id(),
- SigNo :: message_number(),
- SigData :: iodata().
-send(Port, Spid, SenderPid, SigNo, SigData)
- when ?INT_32BIT(Spid), ?INT_32BIT(SenderPid), ?INT_32BIT(SigNo) ->
- try erlang:port_command(Port, [<<?SEND_W_S:8, Spid:32, SenderPid:32,
- SigNo:32>>, SigData]) of
- true -> ok
- catch error:_Error ->
- erlang:error(badarg,[Port,Spid,SenderPid,SigNo,SigData])
- end;
-send(Port,Spid,SenderPid,SigNo,SigData) ->
- erlang:error(badarg,[Port,Spid,SenderPid,SigNo,SigData]).
-
-%%------------------------------------------------------------------------------
-%% @doc Start listening for specified OSE signal numbers.
-%%
-%% The mailbox will send `{message,Port,{FromMboxId,ToMboxId,MsgNo,MsgData}}'
-%% to the process that created the mailbox when an OSE message with any
-%% of the specified `SigNos' arrives.
-%%
-%% Repeated calls to listen will replace the current set of signal numbers to
-%% listen to. i.e
-%%
-%% ```1>ose:listen(MsgB,[1234,12345]).
-%% ok
-%% 2> ose:listen(MsgB,[1234,123456]).
-%% ok.'''
-%%
-%% The above will first listen for signals with numbers 1234 and 12345, and then
-%% replace that with only listening to 1234 and 123456.
-%%
-%% With the current implementation it is not possible to listen to all signal
-%% numbers.
-%%
-%% raises: `badarg' | `enomem'
-%%
-%% @end
-%%------------------------------------------------------------------------------
--spec listen(Port, SigNos) -> ok when
- Port :: mailbox(),
- SigNos :: list(message_number()).
-listen(Port, SigNos) when is_list(SigNos) ->
- USSigNos = lists:usort(SigNos),
- BinSigNos = try
- << <<SigNo:32>> ||
- SigNo <- USSigNos,
- ?INT_32BIT(SigNo) orelse erlang:error(badarg)
- >>
- catch _:_ ->
- erlang:error(badarg,[Port,SigNos])
- end,
- try port_command(Port, [?LISTEN, BinSigNos]) of
- true ->
- receive
- {ose_drv_reply,Port,{error,Error}} ->
- erlang:error(Error,[Port,SigNos]);
- {ose_drv_reply,Port,Else} ->
- Else
- end
- catch error:_Error ->
- erlang:error(badarg,[Port,SigNos])
- end;
-listen(Port, SigNos) ->
- erlang:error(badarg,[Port,SigNos]).
-
-
-%%%=============================================================================
-%%% Internal functions
-%%%=============================================================================
diff --git a/lib/ose/test/Makefile b/lib/ose/test/Makefile
deleted file mode 100644
index 7e2080ba38..0000000000
--- a/lib/ose/test/Makefile
+++ /dev/null
@@ -1,67 +0,0 @@
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES= \
- ose_SUITE
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-INSTALL_PROGS= $(TARGET_FILES)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/ose_test
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \
- -I$(ERL_TOP)/lib/kernel/include
-
-EBIN = .
-
-EMAKEFILE=Emakefile
-COVERFILE=ose.cover
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-make_emakefile:
- $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \
- > $(EMAKEFILE)
-
-tests debug opt: make_emakefile
- erl $(ERL_MAKE_FLAGS) -make
-
-clean:
- rm -f $(EMAKEFILE)
- rm -f $(TARGET_FILES)
- rm -f core
-
-docs:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
-
-release_tests_spec: make_emakefile
- $(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) ose.spec $(EMAKEFILE) \
- $(ERL_FILES) $(COVERFILE) "$(RELSYSDIR)"
- chmod -R u+w "$(RELSYSDIR)"
- @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
-
-release_docs_spec:
diff --git a/lib/ose/test/ose.cover b/lib/ose/test/ose.cover
deleted file mode 100644
index 7b846cfaf6..0000000000
--- a/lib/ose/test/ose.cover
+++ /dev/null
@@ -1,2 +0,0 @@
-%% -*- erlang -*-
-{incl_app,ose,details}.
diff --git a/lib/ose/test/ose.spec b/lib/ose/test/ose.spec
deleted file mode 100644
index c897e8cd16..0000000000
--- a/lib/ose/test/ose.spec
+++ /dev/null
@@ -1 +0,0 @@
-{suites,"../ose_test",all}.
diff --git a/lib/ose/test/ose_SUITE.erl b/lib/ose/test/ose_SUITE.erl
deleted file mode 100644
index 31d950bd03..0000000000
--- a/lib/ose/test/ose_SUITE.erl
+++ /dev/null
@@ -1,766 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2013. 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(ose_SUITE).
-
-%-compile(export_all).
-
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,init_per_testcase/2,
- end_per_testcase/2]).
--export([
- basic/1,stress/1,multi_msg_numbers/1,multi_mailboxes/1,
- hunt/1,multi_hunt/1,dehunt/1,multi_dehunt/1,
- attach/1,multi_attach/1,detach/1,multi_detach/1,
- open_errors/1,close_errors/1,get_id_errors/1,get_name_errors/1,
- hunt_errors/1,dehunt_errors/1,attach_errors/1,detach_errors/1,
- send_errors/1,send_w_s_errors/1,listen_errors/1
- ]).
-
--define(INTERFACE,ose).
-
-
-init_per_testcase(_Func, Config) ->
- Config.
-end_per_testcase(_Func, _Config) ->
- ok.
-
-suite() -> [{timeout,{30,seconds}}].
-
-all() ->
- [
- basic,stress,multi_msg_numbers,multi_mailboxes,
- hunt,multi_hunt,dehunt,multi_dehunt,
- attach,multi_attach,detach,multi_detach,
-
- open_errors,close_errors,get_id_errors,get_name_errors,
- hunt_errors,dehunt_errors,attach_errors,detach_errors,
- send_errors,send_w_s_errors,listen_errors
- ].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- case os:type() of
- {ose,_} ->
- Config;
- _Else ->
- {skip,"Only run on OSE"}
- end.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-basic(_Config) ->
-
- [P1,P2] = multi_open(2,[42]),
- P1Id = ?INTERFACE:get_id(P1),
- P2Id = ?INTERFACE:get_id(P2),
-
- ok = ?INTERFACE:send(P2,P1Id,42,<<"ping">>),
- receive
- {message,P1,V1} ->
- {P2Id,P1Id,42,<<"ping">>} = V1,
- ?INTERFACE:send(P1,P2Id,42,<<"pong">>);
- Else1 ->
- ct:fail({got_wrong_message,Else1})
- end,
-
- receive
- {message,P2,V2} ->
- {P1Id,P2Id,42,<<"pong">>} = V2;
- Else2 ->
- ct:fail({got_wrong_message,Else2})
- end,
-
- ?INTERFACE:close(P1),
- ?INTERFACE:close(P2).
-
-%% Send 1000 messages and see if we can cope and that msg order is preserved
-stress(_Config) ->
-
- Iterations = 1000,
-
- [P1,P2] = multi_open(2,[42]),
- P1Id = ?INTERFACE:get_id(P1),
- P2Id = ?INTERFACE:get_id(P2),
-
- spawn(fun() ->
- n(fun(N) ->
- Msg = [<<"ping">>|integer_to_list(N)],
- ?INTERFACE:send(P2,P1Id,42,Msg)
- end,Iterations)
- end),
- timer:sleep(100),
- n(fun(N) ->
- receive
- {message,P1,Value} ->
- Int = integer_to_binary(N),
- {P2Id,P1Id,42,<<"ping",Int/binary>>} = Value,
- ok;
- Else ->
- ct:fail({got_wrong_message,Else})
- end
- end,Iterations),
-
- ?INTERFACE:close(P1),
- ?INTERFACE:close(P2).
-
-%% Listen to 1000 different message numbers and send some random messages
-multi_msg_numbers(_Config) ->
-
- Iterations = 100,
-
- [P1,P2] = multi_open(2,lists:seq(2000,3000)),
- P1Id = ?INTERFACE:get_id(P1),
-
- n(fun(_) ->
- Num = random:uniform(1000)+2000,
- ?INTERFACE:send(P2,P1Id,Num,<<"ping",(integer_to_binary(Num))/binary>>)
- end,Iterations),
-
- n(fun(_) ->
- receive
- {message,P1,{_,_,Id,<<"ping",Num/binary>>}} when Id > 2000;
- Id =< 3000 ->
- Id = binary_to_integer(Num),
- ok;
- Else ->
- ct:fail({got_wrong_message,Else})
- end
- end,Iterations),
-
- ?INTERFACE:close(P1),
- ?INTERFACE:close(P2).
-
-
-%% Create 100 mailboxes and send messages to them
-multi_mailboxes(_Config) ->
-
- Mailboxes = 100,
-
- [P1|MBs] = multi_open(Mailboxes,[42]),
-
- [?INTERFACE:send(P1,?INTERFACE:get_id(P),42,[<<"ping">>,?INTERFACE:get_name(P,?INTERFACE:get_id(P))]) || P <- MBs],
-
- [receive
- {message,P,Value} ->
- Name = ?INTERFACE:get_name(P,?INTERFACE:get_id(P)),
- {_,_,42,<<"ping",Name/binary>>} = Value,
- ok
- end || P <- MBs],
-
- [?INTERFACE:close(P) || P <- [P1|MBs]],
- ok.
-
-hunt(_Config) ->
- [P1,P2] = multi_open(2,[]),
-
- Ref = ?INTERFACE:hunt(P1,"p2"),
- receive
- {mailbox_up,P1,Ref,Pid} ->
- Pid = ?INTERFACE:get_id(P2),
- ?INTERFACE:close(P1),
- ?INTERFACE:close(P2);
- Else ->
- ct:fail({got_wrong_message,Else,Ref})
- end.
-
-multi_hunt(_Config) ->
-
- Iterations = 100,
-
- P = ?INTERFACE:open("p"),
-
- Refs = [?INTERFACE:hunt(P,"p"++integer_to_list(N))|| N <- lists:seq(1,Iterations)],
-
- Pids = [begin
- Prt = ?INTERFACE:open("p"++integer_to_list(N)),
- Pid = ?INTERFACE:get_id(Prt),
- ?INTERFACE:close(Prt),
- Pid
- end || N <- lists:seq(1,Iterations)],
-
- [receive
- {mailbox_up,P,Ref,Pid} ->
- ok
- after 10 ->
- ct:fail({did_not_get,Pid,Ref})
- end || {Pid,Ref} <- lists:zip(Pids,Refs)],
- ?INTERFACE:close(P).
-
-
-dehunt(_Config) ->
- [P1] = multi_open(1,[]),
- Ref = ?INTERFACE:hunt(P1,"p2"),
- receive
- _Else -> ct:fail({got,_Else})
- after 1000 ->
- ok
- end,
- P2 = ?INTERFACE:open("p2"),
-
- % Make sure any messages are sent
- receive after 10 -> ok end,
-
- ok = ?INTERFACE:dehunt(P1,Ref),
-
- % Make sure no messages are received
- receive
- _Else2 -> ct:fail({got,_Else2})
- after 1000 ->
- ?INTERFACE:close(P1),
- ?INTERFACE:close(P2)
- end.
-
-%%%
-%%% This testcase basically:
-%%% spawn 10 processes that in parallel
-%%% adds some hunts for different OSE processes
-%%% maybe create hunted OSE process
-%%% dehunt half of the hunts
-%%% create more hunts
-%%% if not created create hunted OSE process
-%%% veryify that all expected hunt messages are received
-%%% verify that all processes exited correctly
-%%%
-%%% This complex test is done to make sure that the internal handling
-%%% of dehunt works as expected.
-%%%
-multi_dehunt(_Config) ->
- [P1] = multi_open(1,[]),
-
- Scenario =
- fun(Iterations) ->
-
- Hunted = "p"++integer_to_list(Iterations),
- %% Start a couple of hunts
- Refs = [?INTERFACE:hunt(P1,Hunted) || _ <- lists:seq(1,Iterations)],
-
- %% We alternate if the process is opened before or after the dehunt
- P2O = if Iterations rem 2 == 0 ->
- ?INTERFACE:open(Hunted);
- true ->
- undefined
- end,
-
- %% Remove half of them
- {RemRefs,_} = lists:mapfoldl(fun(Ref,Acc) when Acc rem 2 == 0 ->
- ok = ?INTERFACE:dehunt(P1,Ref),
- {[],Acc+1};
- (Ref,Acc) ->
- {Ref,Acc+1}
- end,0,Refs),
-
- %% Add some new ones
- NewRefs = [?INTERFACE:hunt(P1,Hunted)
- || _ <- lists:seq(1,Iterations div 4)]
- ++ lists:flatten(RemRefs),
-
- P2 = if P2O == undefined ->
- ?INTERFACE:open(Hunted);
- true ->
- P2O
- end,
- P2Id = ?INTERFACE:get_id(P2),
-
- %% Receive all the expected ones
- lists:foreach(fun(Ref) ->
- receive
- {mailbox_up,P1,Ref,P2Id} ->
- ok
- after 1000 ->
- io:format("Flush: ~p~n",[flush()]),
- io:format("~p~n",[{Iterations,{did_not_get, Ref}}]),
- ok = Ref
- end
- end,NewRefs),
-
- %% Check that no other have arrived
- receive
- _Else ->
- io:format("Flush: ~p~n",[flush()]),
- io:format("~p~n",[{Iterations,{got, _Else}}]),
- ok = _Else
- after 100 ->
- ok
- end,
- ?INTERFACE:close(P2)
- end,
-
- Self = self(),
-
- n(fun(N) ->
- spawn(fun() -> Self !
- Scenario(N*25)
- end),
- ok
- end,10),
-
- n(fun(_N) ->
- receive ok -> ok
- after 60000 -> ct:fail(failed)
- end
- end,10),
- ?INTERFACE:close(P1).
-
-attach(_Config) ->
- [P1,P2] = multi_open(2,[]),
-
- P2Id = ?INTERFACE:get_id(P2),
- Ref = ?INTERFACE:attach(P1,P2Id),
- ?INTERFACE:close(P2),
- receive
- {mailbox_down,P1,Ref,P2Id} ->
- ?INTERFACE:close(P1);
- _Else ->
- ct:fail({got,_Else, {P1,Ref,P2Id}})
- after 1000 ->
- ct:fail({did_not_get,P1,Ref,P2Id})
- end.
-
-multi_attach(_Config) ->
-
- Iterations = 100,
-
- [P1|Pids] = multi_open(Iterations,[]),
-
- Refs = [{?INTERFACE:get_id(Pid),?INTERFACE:attach(P1,?INTERFACE:get_id(Pid))} || Pid <- Pids],
-
- [?INTERFACE:close(Pid) || Pid <- Pids],
-
- [receive
- {mailbox_down,P1,Ref,Pid} ->
- ok
- after 10000 ->
- ct:fail({did_not_get,Pid,Ref})
- end || {Pid,Ref} <- Refs],
- ?INTERFACE:close(P1).
-
-detach(_Config) ->
- [P1,P2] = multi_open(2,[]),
- P2Id = ?INTERFACE:get_id(P2),
- Ref = ?INTERFACE:attach(P1,P2Id),
- receive
- _Else -> ct:fail({got,_Else})
- after 100 ->
- ok
- end,
-
- ?INTERFACE:close(P2),
-
- % Make sure any messages are sent
- receive after 10 -> ok end,
-
- ?INTERFACE:detach(P1,Ref),
-
- % Make sure no messages are received
- receive
- _Else2 -> ct:fail({got,_Else2})
- after 1000 ->
- ?INTERFACE:close(P1)
- end.
-
-%%%
-%%% This testcase basically:
-%%% spawn 10 processes that in parallel
-%%% adds some attach for different OSE processes
-%%% maybe close OSE process
-%%% dehunt half of the hunts
-%%% create more hunts
-%%% if not closed close attached OSE process
-%%% veryify that all expected attach messages are received
-%%% verify that all processes exited correctly
-%%%
-%%% This complex test is done to make sure that the internal handling
-%%% of dehunt works as expected.
-%%%
-multi_detach(_Config) ->
- [P1] = multi_open(1,[]),
-
- Scenario =
- fun(Iterations) ->
-
- Attached = ?INTERFACE:open("p"++integer_to_list(Iterations)),
- AttachedId = ?INTERFACE:get_id(Attached),
- %% Start a couple of attachs
- Refs = [?INTERFACE:attach(P1,AttachedId) || _ <- lists:seq(1,Iterations)],
-
- %% We alternate if the process is closed before or after the detach
- P2O = if Iterations rem 2 == 0 ->
- ?INTERFACE:close(Attached);
- true ->
- undefined
- end,
-
- %% Remove half of them
- {RemRefs,_} = lists:mapfoldl(fun(Ref,Acc) when Acc rem 2 == 0 ->
- ok = ?INTERFACE:detach(P1,Ref),
- {[],Acc+1};
- (Ref,Acc) ->
- {Ref,Acc+1}
- end,0,Refs),
-
- %% Add some new ones
- NewRefs = [?INTERFACE:attach(P1,AttachedId)
- || _ <- lists:seq(1,Iterations div 4)]
- ++ lists:flatten(RemRefs),
-
- if P2O == undefined ->
- ?INTERFACE:close(Attached);
- true ->
- P2O
- end,
-
- %% Receive all the expected ones
- lists:foreach(fun(Ref) ->
- receive
- {mailbox_down,P1,Ref,AttachedId} ->
- ok
- after 1000 ->
- io:format("Flush: ~p~n",[flush()]),
- io:format("~p~n",[{Iterations,{did_not_get, Ref}}]),
- ok = Ref
- end
- end,NewRefs),
-
- %% Check that no other have arrived
- receive
- _Else ->
- io:format("Flush: ~p~n",[flush()]),
- io:format("~p~n",[{Iterations,{got, _Else}}]),
- ok = _Else
- after 100 ->
- ok
- end
- end,
-
- Self = self(),
-
- n(fun(N) ->
- spawn(fun() -> Self !
- Scenario(N*5)
- end),
- ok
- end,10),
-
- n(fun(_N) ->
- receive ok -> ok
- after 60000 -> ct:fail(failed)
- end
- end,10),
- ?INTERFACE:close(P1).
-
-
-open_errors(_Config) ->
- {'EXIT',{badarg,[{?INTERFACE,open,[inval],_}|_]}} =
- (catch ?INTERFACE:open(inval)),
- {'EXIT',{badarg,[{?INTERFACE,open,[["p"|1]],_}|_]}} =
- (catch ?INTERFACE:open(["p"|1])),
- {'EXIT',{badarg,[{?INTERFACE,open,[["p",1234]],_}|_]}} =
- (catch ?INTERFACE:open(["p",1234])),
-
- ok.
-
-close_errors(_Config) ->
- {'EXIT',{badarg,[{?INTERFACE,close,[inval],_}|_]}} =
- (catch ?INTERFACE:close(inval)),
-
- P1 = ?INTERFACE:open("p1"),
- ok = ?INTERFACE:close(P1),
- ok = ?INTERFACE:close(P1).
-
-
-get_id_errors(_Config) ->
- {'EXIT',{badarg,[{?INTERFACE,get_id,[inval],_}|_]}} =
- (catch ?INTERFACE:get_id(inval)),
-
- P1 = ?INTERFACE:open("p1"),
- ok = ?INTERFACE:close(P1),
- {'EXIT',{badarg,[{?INTERFACE,get_id,[P1],_}|_]}} =
- (catch ?INTERFACE:get_id(P1)),
-
- ok.
-
-get_name_errors(_Config) ->
- P1 = ?INTERFACE:open("p1"),
- {'EXIT',{badarg,[{?INTERFACE,get_name,[P1,inval],_}|_]}} =
- (catch ?INTERFACE:get_name(P1,inval)),
-
- undefined = ?INTERFACE:get_name(P1,1234),
-
- P2 = ?INTERFACE:open("p2"),
- P2Id = ?INTERFACE:get_id(P2),
- ok = ?INTERFACE:close(P1),
- {'EXIT',{badarg,[{?INTERFACE,get_name,[P1,P2Id],_}|_]}} =
- (catch ?INTERFACE:get_name(P1,P2Id)),
- ?INTERFACE:close(P2),
-
- P3 = ?INTERFACE:open([255]),
- <<255>> = ?INTERFACE:get_name(P3, ?INTERFACE:get_id(P3)),
- ?INTERFACE:close(P3),
-
- ok.
-
-hunt_errors(_Config) ->
-
- {'EXIT',{badarg,[{?INTERFACE,hunt,[inval,"hello"],_}|_]}} =
- (catch ?INTERFACE:hunt(inval,"hello")),
-
- P1 = ?INTERFACE:open("p1"),
- {'EXIT',{badarg,[{?INTERFACE,hunt,[P1,["hello",12345]],_}|_]}} =
- (catch ?INTERFACE:hunt(P1,["hello",12345])),
-
- P2 = ?INTERFACE:open(<<255>>),
- P2Pid = ?INTERFACE:get_id(P2),
- Ref = ?INTERFACE:hunt(P1,[255]),
- receive
- {mailbox_up,P1,Ref,P2Pid} ->
- ok;
- Else ->
- ct:fail({got,Else,{mailbox_up,P1,Ref,P2Pid}})
- after 150 ->
- ct:fail({did_not_get,{mailbox_up,P1,Ref,P2Pid}})
- end,
-
- ok = ?INTERFACE:close(P1),
- ok = ?INTERFACE:close(P2),
- {'EXIT',{badarg,[{?INTERFACE,hunt,[P1,["hello"]],_}|_]}} =
- (catch ?INTERFACE:hunt(P1,["hello"])),
-
- ok.
-
-dehunt_errors(_Config) ->
- P1 = ?INTERFACE:open("p1"),
- Ref = ?INTERFACE:hunt(P1,"p2"),
-
- {'EXIT',{badarg,[{?INTERFACE,dehunt,[inval,Ref],_}|_]}} =
- (catch ?INTERFACE:dehunt(inval,Ref)),
-
- {'EXIT',{badarg,[{?INTERFACE,dehunt,[P1,inval],_}|_]}} =
- (catch ?INTERFACE:dehunt(P1,inval)),
-
- ok = ?INTERFACE:dehunt(P1,Ref),
- ok = ?INTERFACE:dehunt(P1,Ref),
-
- ok = ?INTERFACE:close(P1),
-
- {'EXIT',{badarg,[{?INTERFACE,dehunt,[P1,Ref],_}|_]}} =
- (catch ?INTERFACE:dehunt(P1,Ref)),
-
- case ?INTERFACE of
- ose -> ok;
- _ ->
- P2 = ?INTERFACE:open("p2"),
- ok = ?INTERFACE:close(P2)
- end,
-
- receive
- Else -> ct:fail({got,Else})
- after 100 ->
- ok
- end.
-
-attach_errors(_Config) ->
- P1 = ?INTERFACE:open("p1"),
- P2 = ?INTERFACE:open("p2"),
- P2Id = ?INTERFACE:get_id(P2),
-
- {'EXIT',{badarg,[{?INTERFACE,attach,[inval,P2Id],_}|_]}} =
- (catch ?INTERFACE:attach(inval,P2Id)),
-
- {'EXIT',{badarg,[{?INTERFACE,attach,[P1,[12345]],_}|_]}} =
- (catch ?INTERFACE:attach(P1,[12345])),
-
- ok = ?INTERFACE:close(P1),
- ok = ?INTERFACE:close(P2),
- {'EXIT',{badarg,[{?INTERFACE,attach,[P1,P2Id],_}|_]}} =
- (catch ?INTERFACE:attach(P1,P2Id)),
-
- ok.
-
-detach_errors(_Config) ->
- P1 = ?INTERFACE:open("p1"),
- P2 = ?INTERFACE:open("p2"),
- P2Id = ?INTERFACE:get_id(P2),
-
- Ref = ?INTERFACE:attach(P1,P2Id),
-
- {'EXIT',{badarg,[{?INTERFACE,detach,[inval,Ref],_}|_]}} =
- (catch ?INTERFACE:detach(inval,Ref)),
-
- {'EXIT',{badarg,[{?INTERFACE,detach,[P1,inval],_}|_]}} =
- (catch ?INTERFACE:detach(P1,inval)),
-
- ok = ?INTERFACE:detach(P1,Ref),
- ok = ?INTERFACE:detach(P1,Ref),
-
- case ?INTERFACE of
- ose -> ok;
- _ ->
- ok = ?INTERFACE:close(P1)
- end,
-
- ok = ?INTERFACE:close(P2),
- ok = ?INTERFACE:close(P1),
-
- {'EXIT',{badarg,[{?INTERFACE,detach,[P1,Ref],_}|_]}} =
- (catch ?INTERFACE:detach(P1,Ref)),
-
- receive
- Else -> ct:fail({got,Else})
- after 100 ->
- ok
- end.
-
-send_errors(_Config) ->
- P1 = ?INTERFACE:open("p1"),
- P2 = ?INTERFACE:open("p2"),
- P2Id = ?INTERFACE:get_id(P2),
-
- {'EXIT',{badarg,[{?INTERFACE,send,[inval,P2Id,42,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(inval,P2Id,42,"hello")),
- {'EXIT',{badarg,[{?INTERFACE,send,[P1,inval,42,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(P1,inval,42,"hello")),
- {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,inval,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(P1,P2Id,inval,"hello")),
- {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,42,inval],_}|_]}} =
- (catch ?INTERFACE:send(P1,P2Id,42,inval)),
-
- ok = ?INTERFACE:close(P2),
- ok = ?INTERFACE:send(P1,P2Id,42,"hello"),
- ok = ?INTERFACE:close(P1),
-
- {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,42,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(P1,P2Id,42,"hello")),
-
- receive
- Else -> ct:fail({got,Else})
- after 100 ->
- ok
- end.
-
-send_w_s_errors(_Config) ->
- P1 = ?INTERFACE:open("p1"),
- P1Id = ?INTERFACE:get_id(P1),
- P2 = ?INTERFACE:open("p2"),
- P2Id = ?INTERFACE:get_id(P2),
- P3 = ?INTERFACE:open("p3"),
- P3Id = ?INTERFACE:get_id(P3),
-
- {'EXIT',{badarg,[{?INTERFACE,send,[inval,P2Id,P1Id,42,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(inval,P2Id,P1Id,42,"hello")),
- {'EXIT',{badarg,[{?INTERFACE,send,[P2,-1,P1Id,42,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(P2,-1,P1Id,42,"hello")),
- {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,1 bsl 32,42,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(P2,P2Id,1 bsl 32,42,"hello")),
- {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,P1Id,inval,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(P2,P2Id,P1Id,inval,"hello")),
- {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,P1Id,42,inval],_}|_]}} =
- (catch ?INTERFACE:send(P2,P2Id,P1Id,42,inval)),
-
- ok = ?INTERFACE:close(P3),
- ok = ?INTERFACE:send(P2,P3Id,P1Id,42,"hello"),
-
- ok = ?INTERFACE:close(P1),
- ok = ?INTERFACE:send(P2,P2Id,P1Id,42,"hello"),
- ok = ?INTERFACE:close(P2),
-
- {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,P1Id,42,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(P1,P2Id,P1Id,42,"hello")),
-
- receive
- Else -> ct:fail({got,Else})
- after 100 ->
- ok
- end.
-
-listen_errors(_Config) ->
-
- P1 = ?INTERFACE:open("p1"),
- P1Id = ?INTERFACE:get_id(P1),
-
- {'EXIT',{badarg,[{?INTERFACE,listen,[inval,[42]],_}|_]}} =
- (catch ?INTERFACE:listen(inval,[42])),
- {'EXIT',{badarg,[{?INTERFACE,listen,[P1,inval],_}|_]}} =
- (catch ?INTERFACE:listen(P1,inval)),
- {'EXIT',{badarg,[{?INTERFACE,listen,[P1,[1 bsl 33]],_}|_]}} =
- (catch ?INTERFACE:listen(P1,[1 bsl 33])),
-
- ok = ?INTERFACE:listen(P1,[42,42,42,42,42,42,42,42,42,42,42,42,42]),
-
- case ?INTERFACE of
- ose -> ok;
- _ ->
- ?INTERFACE:send(P1,P1Id,42,"hello"),
- timer:sleep(50),
- ?INTERFACE:listen(P1,[]),
- ?INTERFACE:send(P1,P1Id,42,"hello2"),
-
- receive
- {message,P1,42,"hello"} -> ok
- end,
-
- receive
- Else -> ct:fail({got,Else})
- after 100 ->
- ok
- end
- end,
-
- ok = ?INTERFACE:close(P1),
- {'EXIT',{badarg,[{?INTERFACE,listen,[P1,[42]],_}|_]}} =
- (catch ?INTERFACE:listen(P1,[42])),
-
- ok.
-
-%%
-%% Internal functions
-%%
-multi_open(N,ListenNums) ->
- multi_open(N,ListenNums,[]).
-
-multi_open(0,_,Acc) ->
- Acc;
-multi_open(N,ListenNums,Acc) ->
- P = ?INTERFACE:open("p"++integer_to_list(N)),
- ok = ?INTERFACE:listen(P,ListenNums),
- multi_open(N-1,ListenNums,[P|Acc]).
-
-n(_F,0) ->
- ok;
-n(F,N) ->
- ok = F(N),
- n(F,N-1).
-
-
-flush() ->
- receive
- Msg ->
- [Msg|flush()]
- after 0 ->
- []
- end.
diff --git a/lib/ose/vsn.mk b/lib/ose/vsn.mk
deleted file mode 100644
index fb1cf8219f..0000000000
--- a/lib/ose/vsn.mk
+++ /dev/null
@@ -1 +0,0 @@
-OSE_VSN = 1.1
diff --git a/lib/otp_mibs/test/Makefile b/lib/otp_mibs/test/Makefile
index e1cfbb347d..18d7e915db 100644
--- a/lib/otp_mibs/test/Makefile
+++ b/lib/otp_mibs/test/Makefile
@@ -49,7 +49,6 @@ RELSYSDIR = $(RELEASE_PATH)/otp_mibs_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS += \
- -I$(ERL_TOP)/lib/test_server/include \
-I$(ERL_TOP)/lib/snmp/include
# ----------------------------------------------------
diff --git a/lib/otp_mibs/test/otp_mibs_SUITE.erl b/lib/otp_mibs/test/otp_mibs_SUITE.erl
index abb5aa8194..4d1eb155cd 100644
--- a/lib/otp_mibs/test/otp_mibs_SUITE.erl
+++ b/lib/otp_mibs/test/otp_mibs_SUITE.erl
@@ -30,7 +30,7 @@
%% > ct_run -suite otp_mibs_SUITE -config otp_mibs_SUITE.cfg
%%-----------------------------------------------------------------
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("otp_mibs/include/OTP-MIB.hrl").
-include_lib("snmp/include/snmp_types.hrl").
diff --git a/lib/parsetools/test/Makefile b/lib/parsetools/test/Makefile
index f84bb0e75e..75f9624fd5 100644
--- a/lib/parsetools/test/Makefile
+++ b/lib/parsetools/test/Makefile
@@ -41,7 +41,7 @@ RELSYSDIR = $(RELEASE_PATH)/parsetools_test
# FLAGS
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_COMPILE_FLAGS +=
EBIN = .
diff --git a/lib/parsetools/test/leex_SUITE.erl b/lib/parsetools/test/leex_SUITE.erl
index 1e3738de85..f5ff32c358 100644
--- a/lib/parsetools/test/leex_SUITE.erl
+++ b/lib/parsetools/test/leex_SUITE.erl
@@ -31,7 +31,7 @@
-define(privdir, "leex_SUITE_priv").
-define(t, test_server).
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(datadir, ?config(data_dir, Config)).
-define(privdir, ?config(priv_dir, Config)).
-endif.
diff --git a/lib/parsetools/test/yecc_SUITE.erl b/lib/parsetools/test/yecc_SUITE.erl
index 6603a5a07d..a1bb5eb16c 100644
--- a/lib/parsetools/test/yecc_SUITE.erl
+++ b/lib/parsetools/test/yecc_SUITE.erl
@@ -30,7 +30,7 @@
-define(privdir, "yecc_SUITE_priv").
-define(t, test_server).
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(datadir, ?config(data_dir, Config)).
-define(privdir, ?config(priv_dir, Config)).
-endif.
diff --git a/lib/percept/test/Makefile b/lib/percept/test/Makefile
index 4ba0b80fc8..6891de832d 100644
--- a/lib/percept/test/Makefile
+++ b/lib/percept/test/Makefile
@@ -52,8 +52,7 @@ RELSYSDIR = $(RELEASE_PATH)/percept_test
# FLAGS
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \
- -I$(ERL_TOP)/lib/percept/include
+ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/percept/include
# ----------------------------------------------------
# Targets
diff --git a/lib/percept/test/egd_SUITE.erl b/lib/percept/test/egd_SUITE.erl
index 41e8999e17..0b1149e1f1 100644
--- a/lib/percept/test/egd_SUITE.erl
+++ b/lib/percept/test/egd_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(egd_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
@@ -40,7 +40,7 @@
-define(default_timeout, ?t:minutes(1)).
init_per_suite(Config) when is_list(Config) ->
- random:seed(now()),
+ rand:seed(exsplus),
Config.
end_per_suite(Config) when is_list(Config) ->
@@ -348,4 +348,4 @@ get_points(0, Out) ->
get_points(N, Out) ->
get_points(N - 1, [get_point() | Out]).
-random(N) -> trunc(random:uniform(trunc(N + 1)) - 1).
+random(N) -> trunc(rand:uniform(trunc(N + 1)) - 1).
diff --git a/lib/percept/test/percept_SUITE.erl b/lib/percept/test/percept_SUITE.erl
index fd96c2b97a..06d62630ba 100644
--- a/lib/percept/test/percept_SUITE.erl
+++ b/lib/percept/test/percept_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(percept_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
diff --git a/lib/percept/test/percept_db_SUITE.erl b/lib/percept/test/percept_db_SUITE.erl
index e2775aabc0..5b878e8462 100644
--- a/lib/percept/test/percept_db_SUITE.erl
+++ b/lib/percept/test/percept_db_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(percept_db_SUITE).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Test server specific exports
-export([all/1]).
diff --git a/lib/reltool/src/reltool.hrl b/lib/reltool/src/reltool.hrl
index 4c3f76bdc6..9ac22b9450 100644
--- a/lib/reltool/src/reltool.hrl
+++ b/lib/reltool/src/reltool.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2009-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.
@@ -141,15 +141,15 @@
app_name :: '_' | app_name(),
incl_cond :: '_' | incl_cond() | undefined,
debug_info :: '_' | debug_info() | undefined,
- is_app_mod :: '_' | boolean(),
- is_ebin_mod :: '_' | boolean(),
- uses_mods :: '$2' | [mod_name()],
- exists :: '_' | boolean(),
+ is_app_mod :: '_' | boolean() | undefined,
+ is_ebin_mod :: '_' | boolean() | undefined,
+ uses_mods :: '$2' | [mod_name()] | undefined,
+ exists :: '_' | boolean() | undefined,
%% Dynamic
- status :: '_' | status(),
- used_by_mods :: '_' | [mod_name()],
- is_pre_included :: '_' | boolean() | undefined,
- is_included :: '_' | boolean() | undefined
+ status = ok :: '_' | status(),
+ used_by_mods = [] :: '_' | [mod_name()],
+ is_pre_included :: '_' | boolean() | undefined,
+ is_included :: '_' | boolean() | undefined
}).
-record(app_info,
@@ -177,10 +177,10 @@
name :: '_' | app_name(),
is_escript :: '_' | boolean() | {inlined, escript_app_name()},
use_selected_vsn :: '_' | vsn | dir | undefined,
- active_dir :: '_' | dir(),
+ active_dir :: '_' | dir() | undefined,
sorted_dirs :: '_' | [dir()],
- vsn :: '_' | app_vsn(),
- label :: '_' | app_label(),
+ vsn :: '_' | app_vsn() | undefined,
+ label :: '_' | app_label() | undefined,
info :: '_' | #app_info{} | undefined,
mods :: '_' | [#mod{}],
@@ -192,21 +192,21 @@
debug_info :: '_' | debug_info() | undefined,
app_file :: '_' | app_file() | undefined,
app_type :: '_' | app_type() | undefined,
- incl_app_filters :: '_' | [#regexp{}],
- excl_app_filters :: '_' | [#regexp{}],
- incl_archive_filters :: '_' | [#regexp{}],
- excl_archive_filters :: '_' | [#regexp{}],
- archive_opts :: '_' | [archive_opt()],
+ incl_app_filters :: '_' | [#regexp{}] | undefined,
+ excl_app_filters :: '_' | [#regexp{}] | undefined,
+ incl_archive_filters :: '_' | [#regexp{}] | undefined,
+ excl_archive_filters :: '_' | [#regexp{}] | undefined,
+ archive_opts :: '_' | [archive_opt()] | undefined,
%% Dynamic
status :: '_' | status(),
- uses_mods :: '_' | [mod_name()],
- used_by_mods :: '_' | [mod_name()],
- uses_apps :: '_' | [app_name()],
- used_by_apps :: '_' | [app_name()],
+ uses_mods :: '_' | [mod_name()] | undefined,
+ used_by_mods :: '_' | [mod_name()] | undefined,
+ uses_apps :: '_' | [app_name()] | undefined,
+ used_by_apps :: '_' | [app_name()] | undefined,
is_pre_included :: '_' | '$2' | boolean() | undefined,
is_included :: '_' | '$1' | boolean() | undefined,
- rels :: '_' | [rel_name()]
+ rels :: '_' | [rel_name()] | undefined
}).
-record(rel_app,
@@ -237,7 +237,7 @@
rels :: [#rel{}],
emu_name :: emu_name(),
profile :: profile(),
- excl_lib :: excl_lib(),
+ excl_lib :: excl_lib() | undefined,
incl_sys_filters :: [#regexp{}],
excl_sys_filters :: [#regexp{}],
incl_app_filters :: [#regexp{}],
diff --git a/lib/reltool/src/reltool_fgraph_win.erl b/lib/reltool/src/reltool_fgraph_win.erl
index 6b58cae187..deab502bfe 100644
--- a/lib/reltool/src/reltool_fgraph_win.erl
+++ b/lib/reltool/src/reltool_fgraph_win.erl
@@ -220,8 +220,8 @@ graph_add_node_unsure(Key, State, G = #graph{ vs = Vs }) ->
graph_add_node(Key, Color, G = #graph{ vs = Vs}) ->
Q = 20.0, % repulsive force
M = 0.5, % mass
- P = {float(450 + random:uniform(100)),
- float(450 + random:uniform(100))},
+ P = {float(450 + rand:uniform(100)),
+ float(450 + rand:uniform(100))},
G#graph{ vs = reltool_fgraph:add(Key,
#fg_v{ p = P, m = M, q = Q, color = Color},
Vs)}.
diff --git a/lib/runtime_tools/c_src/Makefile.in b/lib/runtime_tools/c_src/Makefile.in
index 448b8c62c2..aeacee0655 100644
--- a/lib/runtime_tools/c_src/Makefile.in
+++ b/lib/runtime_tools/c_src/Makefile.in
@@ -102,12 +102,7 @@ endif
_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
-ifneq ($(findstring ose,$(TARGET)),ose)
debug opt valgrind: $(SOLIBS) $(OBJDIR) $(LIBDIR) $(NIF_LIB)
-else
-# We do not build this on OSE
-debug opt valgrind:
-endif
DYNTRACE_OBJS = $(before_DTrace_OBJS)
@@ -159,10 +154,8 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/priv/obj"
$(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
-ifneq ($(findstring ose,$(TARGET)),ose)
$(INSTALL_PROGRAM) $(DYNTRACE_OBJS) "$(RELSYSDIR)/priv/obj"
$(INSTALL_PROGRAM) $(NIF_LIB) $(SOLIBS) "$(RELSYSDIR)/priv/lib"
-endif
release_docs_spec:
diff --git a/lib/runtime_tools/doc/src/Makefile b/lib/runtime_tools/doc/src/Makefile
index 0292333f0a..38725807ae 100644
--- a/lib/runtime_tools/doc/src/Makefile
+++ b/lib/runtime_tools/doc/src/Makefile
@@ -41,7 +41,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = dbg.xml dyntrace.xml erts_alloc_config.xml system_information.xml
+XML_REF3_FILES = dbg.xml dyntrace.xml erts_alloc_config.xml system_information.xml msacc.xml
XML_REF6_FILES = runtime_tools_app.xml
XML_PART_FILES = part_notes.xml part_notes_history.xml part.xml
diff --git a/lib/runtime_tools/doc/src/msacc.xml b/lib/runtime_tools/doc/src/msacc.xml
new file mode 100644
index 0000000000..129da3d230
--- /dev/null
+++ b/lib/runtime_tools/doc/src/msacc.xml
@@ -0,0 +1,305 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2014</year><year>2014</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ 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.
+ </legalnotice>
+
+ <title>Microstate Accounting</title>
+ <prepared>Lukas Larsson</prepared>
+ <responsible></responsible>
+ <docno>1</docno>
+ <approved></approved>
+ <checked></checked>
+ <date>14-09-30</date>
+ <rev>A</rev>
+ <file>msacc.xml</file>
+ </header>
+ <module>msacc</module>
+ <modulesummary>Convenience functions for microstate accounting</modulesummary>
+ <description>
+ <p>This module implements some convenience functions for analyzing
+ microstate accounting data. For details about how to use the basic api and
+ what the different states represent see
+ <seealso marker="erts:erlang#statistics_microstate_accounting"><c>
+ erlang:statistics(microstate_accounting)</c></seealso>.</p>
+ <marker id="msacc_print_example"></marker>
+ <p><em>Basic Scenario</em></p>
+ <pre>1> <input>msacc:start(1000).</input>
+ok
+2> <input>msacc:print().</input>
+Average thread real-time : 1000513 us
+Accumulated system run-time : 2213 us
+Average scheduler run-time : 1076 us
+
+ Thread aux check_io emulator gc other port sleep
+
+Stats per thread:
+ async( 0) 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 100.00%
+ async( 1) 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 100.00%
+ aux( 1) 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 99.99%
+ scheduler( 1) 0.00% 0.03% 0.13% 0.00% 0.01% 0.00% 99.82%
+ scheduler( 2) 0.00% 0.00% 0.00% 0.00% 0.03% 0.00% 99.97%
+
+Stats per type:
+ async 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 100.00%
+ aux 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 99.99%
+ scheduler 0.00% 0.02% 0.06% 0.00% 0.02% 0.00% 99.89%
+ok
+</pre>
+ <p>This first command enables microstate accounting for 1000 milliseconds.
+ See <seealso marker="#start-0"><c>start/0</c></seealso>,
+ <seealso marker="#stop-0"><c>stop/0</c></seealso>,
+ <seealso marker="#reset-0"><c>reset/0</c></seealso> and
+ <seealso marker="#start-1"><c>start/1</c></seealso> for more details.
+ The second command prints the statistics gathered during that time.
+ First three general statistics are printed.</p>
+ <taglist>
+ <tag>Average real-time</tag>
+ <item>The average time spent collecting data in the threads.
+ This should be close to the time which data was collected.
+ </item>
+ <tag>System run-time</tag>
+ <item>The total run-time of all threads in the system.
+ This is what you get if you call <c>msacc:stats(total_runtime,Stats).</c>
+ </item>
+ <tag>Average scheduler run-time</tag>
+ <item>The average run-time for the schedulers.
+ This is the average amount of time the schedulers did not sleep.</item>
+ </taglist>
+ <p>Then one column per state is printed with a the percentage of time this
+ thread spent in the state out of it's own real-time. After the thread
+ specific time, the accumulated time for each type of thread is printed in
+ a similar format.</p>
+ <p>Since we have the average real-time and the percentage spent in each
+ state we can easily calculate the time spent in each state by multiplying
+ <c>Average thread real-time</c> with <c>Thread state %</c>, i.e. to
+ get the time Scheduler 1 spent in the emulator state we do
+ <c>1000513us * 0.13% = 1300us</c>.</p>
+ </description>
+ <datatypes>
+ <datatype>
+ <name name="msacc_data"/>
+ </datatype>
+ <datatype>
+ <name name="msacc_data_thread"/>
+ </datatype>
+ <datatype>
+ <name name="msacc_data_counters"/>
+ <desc><p>A map containing the different microstate accounting states and
+ the number of microseconds spent in it.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="msacc_stats"/>
+ </datatype>
+ <datatype>
+ <name name="msacc_stats_thread"/>
+ <desc><p>A map containing information about a specific thread. The
+ percentages in the map can be either run-time or real-time depending
+ on if <c>runtime</c> or <c>realtime</c> was requested from
+ <seealso marker="#stats-2">stats/2</seealso>. <c>system</c> is the
+ percentage of total system time for this specific thread.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="msacc_stats_counters"/>
+ <desc><p>A map containing the different microstate accounting states. Each
+ value in the map contains another map with the percentage of time that
+ this thread has spent in the specific state. Both the percentage of
+ <c>system</c> time and the time for that specific <c>thread</c> is part of
+ the map.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="msacc_type"/>
+ </datatype>
+ <datatype>
+ <name name="msacc_id"/>
+ </datatype>
+ <datatype>
+ <name name="msacc_state"/>
+ <desc><p>The different states that a thread can be in. See
+ <seealso marker="erts:erlang#statistics_microstate_accounting">
+ erlang:statistics(microstate_accounting)</seealso> for details.
+ </p></desc>
+ </datatype>
+ <datatype>
+ <name name="msacc_print_options"/>
+ <desc><p>The different options that can be given to
+ <seealso marker="#print-2"><c>print/2</c></seealso>.
+ </p></desc>
+ </datatype>
+ </datatypes>
+ <funcs>
+ <func>
+ <name name="available" arity="0"/>
+ <fsummary>Check if microstate accounting is available</fsummary>
+ <desc>
+ <p>This function checks whether microstate accounting
+ is available or not.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="start" arity="0"/>
+ <fsummary>Start microstate accounting.</fsummary>
+ <desc>
+ <p>Start microstate accounting. Returns whether it was
+ previously enabled or disabled.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="start" arity="1"/>
+ <fsummary>Start microstate accounting for a time.</fsummary>
+ <desc>
+ <p>Resets all counters and then starts microstate accounting
+ for the given milliseconds.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="stop" arity="0"/>
+ <fsummary>Stop microstate accounting.</fsummary>
+ <desc>
+ <p>Stop microstate accounting.
+ Returns whether is was previously enabled or disabled.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="reset" arity="0"/>
+ <fsummary>Reset microstate accounting counters</fsummary>
+ <desc>
+ <p>Reset microstate accounting counters.
+ Returns whether is was enabled or disabled.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="print" arity="0"/>
+ <fsummary>Print microstate statistics</fsummary>
+ <desc>
+ <p>
+ Prints the current microstate accounting to standard out.
+ Same as
+ <seealso marker="#print-1">
+ <c>msacc:print(msacc:stats(),#{}).</c>
+ </seealso>
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="print" arity="1"/>
+ <fsummary>Print microstate statistics</fsummary>
+ <desc>
+ <p>Print the given microstate statistics values to stdout.
+ Same as
+ <seealso marker="#print-1">
+ <c>msacc:print(DataOrStats,#{}).</c>
+ </seealso>
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="print" arity="2"/>
+ <fsummary>Print microstate statistics</fsummary>
+ <desc>
+ <p>Print the given microstate statistics values to standard out.
+ With many states this can be quite verbose. See the top of this
+ reference manual for a brief description of what the fields mean.</p>
+ <p>It is possible to print more specific types of statistics by
+ first manipulating the <c>DataOrStats</c> using
+ <seealso marker="#stats-2"><c>stats/2</c></seealso>.
+ For instance if you want to print the percentage of run-time for each
+ thread you can do:</p>
+ <pre><input>msacc:print(msacc:stats(runtime,msacc:stats())).</input></pre>
+ <p>If you want to only print run-time per thread type you can do:</p>
+ <pre><input>msacc:print(msacc:stats(type,msacc:stats(runtime,msacc:stats()))).</input></pre>
+ <p><em>Options</em></p>
+ <taglist>
+ <tag><c>system</c></tag><item>Print percentage of time spent in each
+ state out of system time as well as thread time.
+ Default: false.</item>
+ </taglist>
+ </desc>
+ </func>
+ <func>
+ <name name="print" arity="3"/>
+ <fsummary>Print microstate statistics</fsummary>
+ <desc>
+ <p>Print the given microstate statistics values to the given file
+ or device. The other arguments behave the same way as for
+ <seealso marker="#print-2"><c>print/2</c></seealso>.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="stats" arity="0"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>Returns a runtime system independent version of the microstate
+ statistics data presented by
+ <seealso marker="erts:erlang#statistics_microstate_accounting">
+ <c>erlang:statistics(microstate_accounting)</c></seealso>.
+ All counters have been normalized to be in microsecond resolution.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="stats" arity="2" clause_i="1"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>Returns the system time for the given microstate statistics values.
+ System time is the accumulated time of all threads.</p>
+ <taglist>
+ <tag><c>realtime</c></tag>
+ <item>Returns all time recorded for all threads.</item>
+ <tag><c>runtime</c></tag>
+ <item>Returns all time spent doing work for all threads, i.e.
+ all time not spent in the <c>sleep</c> state.</item>
+ </taglist>
+ </desc>
+ </func>
+ <func>
+ <name name="stats" arity="2" clause_i="2"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>Returns fractions of real-time or run-time spent in the various
+ threads from the given microstate statistics values.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="stats" arity="2" clause_i="3"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>Returns a list of microstate statistics values where the values
+ for all threads of the same type has been merged.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="to_file" arity="1"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>Dumps the current microstate statistics counters to a file that can
+ be parsed with <seealso marker="kernel:file#consult/1">
+ file:consult/1</seealso>.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="from_file" arity="1"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>Read a file dump produced by <seealso marker="#to_file/1">
+ to_file(Filename)</seealso>.</p>
+ </desc>
+ </func>
+ </funcs>
+</erlref>
diff --git a/lib/runtime_tools/doc/src/ref_man.xml b/lib/runtime_tools/doc/src/ref_man.xml
index ea0c0832a4..8657a07a30 100644
--- a/lib/runtime_tools/doc/src/ref_man.xml
+++ b/lib/runtime_tools/doc/src/ref_man.xml
@@ -36,6 +36,7 @@
<xi:include href="dbg.xml"/>
<xi:include href="dyntrace.xml"/>
<xi:include href="erts_alloc_config.xml"/>
+ <xi:include href="msacc.xml"/>
<xi:include href="system_information.xml"/>
</application>
diff --git a/lib/runtime_tools/doc/src/specs.xml b/lib/runtime_tools/doc/src/specs.xml
index d4c3c9dfe6..978bd39e55 100644
--- a/lib/runtime_tools/doc/src/specs.xml
+++ b/lib/runtime_tools/doc/src/specs.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<specs xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="../specs/specs_system_information.xml"/>
+ <xi:include href="../specs/specs_msacc.xml"/>
</specs>
diff --git a/lib/runtime_tools/src/Makefile b/lib/runtime_tools/src/Makefile
index 99b90f9ec5..3b41184f4e 100644
--- a/lib/runtime_tools/src/Makefile
+++ b/lib/runtime_tools/src/Makefile
@@ -45,7 +45,9 @@ MODULES= \
percept_profile \
system_information \
observer_backend \
- ttb_autostart
+ ttb_autostart\
+ msacc
+
HRL_FILES= ../include/observer_backend.hrl
ERL_FILES= $(MODULES:%=%.erl)
diff --git a/lib/runtime_tools/src/msacc.erl b/lib/runtime_tools/src/msacc.erl
new file mode 100644
index 0000000000..612effa5aa
--- /dev/null
+++ b/lib/runtime_tools/src/msacc.erl
@@ -0,0 +1,355 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2014-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%
+%%
+
+%%
+%% @doc Microstate accounting utility function
+%%
+%% This module provides a user interface for analysing
+%% erlang:statistics(microstate_accounting) data.
+%%
+
+-module(msacc).
+-export([available/0, start/0, start/1, stop/0, reset/0, to_file/1,
+ from_file/1, stats/0, stats/2, print/0, print/1, print/2,
+ print/3]).
+
+-type msacc_data() :: [msacc_data_thread()].
+
+-type msacc_data_thread() :: #{ '$type' => msacc_data,
+ type => msacc_type(), id => msacc_id(),
+ counters => msacc_data_counters() }.
+-type msacc_data_counters() :: #{ msacc_state() => non_neg_integer()}.
+
+-type msacc_stats() :: [msacc_stats_thread()].
+-type msacc_stats_thread() :: #{ '$type' => msacc_stats,
+ type => msacc_type(), id => msacc_id(),
+ system => float(),
+ counters => msacc_stats_counters()}.
+-type msacc_stats_counters() :: #{ msacc_state() => #{ thread => float(),
+ system => float()}}.
+
+
+-type msacc_type() :: scheduler | aux | async.
+-type msacc_id() :: non_neg_integer().
+-type msacc_state() :: alloc | aux | bif | busy_wait | check_io |
+ emulator | ets | gc | gc_fullsweep | nif |
+ other | port | send | sleep | timers.
+
+-type msacc_print_options() :: #{ system => boolean() }.
+
+-spec available() -> boolean().
+available() ->
+ try
+ [_|_] = erlang:statistics(microstate_accounting),
+ true
+ catch _:_ ->
+ false
+ end.
+
+-spec start() -> boolean().
+start() ->
+ erlang:system_flag(microstate_accounting, true).
+
+-spec stop() -> boolean().
+stop() ->
+ erlang:system_flag(microstate_accounting, false).
+
+-spec reset() -> boolean().
+reset() ->
+ erlang:system_flag(microstate_accounting, reset).
+
+-spec start(Time) -> true when
+ Time :: timeout().
+start(Tmo) ->
+ stop(), reset(), start(),
+ timer:sleep(Tmo),
+ stop().
+
+-spec to_file(Filename) -> ok | {error, file:posix()} when
+ Filename :: file:name_all().
+to_file(Filename) ->
+ file:write_file(Filename, io_lib:format("~p.~n",[stats()])).
+
+-spec from_file(Filename) -> msacc_data() when
+ Filename :: file:name_all().
+from_file(Filename) ->
+ {ok, [Stats]} = file:consult(Filename),
+ Stats.
+
+-spec print() -> ok.
+print() ->
+ print(stats()).
+
+-spec print(DataOrStats) -> ok when
+ DataOrStats :: msacc_data() | msacc_stats().
+print(Stats) ->
+ print(Stats, #{}).
+
+-spec print(DataOrStats, Options) -> ok when
+ DataOrStats :: msacc_data() | msacc_stats(),
+ Options :: msacc_print_options().
+print(Stats, Options) ->
+ print(group_leader(), Stats, Options).
+
+-spec print(FileOrDevice, DataOrStats, Options) -> ok when
+ FileOrDevice :: file:filename() | io:device(),
+ DataOrStats :: msacc_data() | msacc_stats(),
+ Options :: msacc_print_options().
+print(Filename, Stats, Options) when is_list(Filename) ->
+ case file:open(Filename,[write]) of
+ {ok, D} -> print(D, Stats, Options),file:close(D);
+ Error -> Error
+ end;
+print(Device, Stats, Options) ->
+ DefaultOpts = #{ system => false },
+ print_int(Device, Stats, maps:merge(DefaultOpts, Options)).
+print_int(Device, [#{ '$type' := msacc_data, id := _Id }|_] = Stats, Options) ->
+ TypeStats = stats(type, Stats),
+ io:format(Device, "~s", [print_stats_overview(Stats, Options)]),
+ io:format(Device, "~s", [print_stats_header(Stats, Options)]),
+ io:format(Device, "~s", [print_stats_threads(
+ stats(realtime, Stats), Options)]),
+ io:format(Device, "~s", [print_stats_type(
+ stats(realtime, TypeStats), Options)]);
+print_int(Device, [#{ '$type' := msacc_data }|_] = Stats, Options) ->
+ io:format(Device, "~s", [print_stats_header(Stats, Options)]),
+ io:format(Device, "~s", [print_stats_type(
+ stats(realtime, Stats), Options)]);
+print_int(Device, [#{ '$type' := msacc_stats, id := _Id }|_] = Stats,Options) ->
+ io:format(Device, "~s", [print_stats_header(Stats, Options)]),
+ io:format(Device, "~s", [print_stats_threads(Stats, Options)]),
+ io:format(Device, "~s", [print_stats_type(
+ msacc:stats(type, Stats), Options)]);
+print_int(Device, [#{ '$type' := msacc_stats }|_] = Stats, Options) ->
+ io:format(Device, "~s", [print_stats_header(Stats, Options)]),
+ io:format(Device, "~s", [print_stats_type(Stats, Options)]).
+
+
+-spec stats() -> msacc_data().
+stats() ->
+ Fun = fun F(K,{PerfCount,StateCount}) ->
+ %% Need to handle ERTS_MSACC_STATE_COUNTERS
+ {F(K,PerfCount),StateCount};
+ F(_K,PerfCount) ->
+ erlang:convert_time_unit(PerfCount, perf_counter, 1000000)
+ end,
+ UsStats = lists:map(
+ fun(#{ counters := Cnt } = M) ->
+ UsCnt = maps:map(Fun,Cnt),
+ M#{ '$type' => msacc_data, counters := UsCnt }
+ end, erlang:statistics(microstate_accounting)),
+ statssort(UsStats).
+
+-spec stats(Analysis, Stats) -> non_neg_integer() when
+ Analysis :: system_realtime | system_runtime,
+ Stats :: msacc_data();
+ (Analysis, Stats) -> msacc_stats() when
+ Analysis :: realtime | runtime,
+ Stats :: msacc_data();
+ (Analysis, StatsOrData) -> msacc_data() | msacc_stats() when
+ Analysis :: type,
+ StatsOrData :: msacc_data() | msacc_stats().
+stats(system_realtime, Stats) ->
+ lists:foldl(fun(#{ counters := Cnt }, Acc) ->
+ get_total(Cnt, Acc)
+ end, 0, Stats);
+stats(system_runtime, Stats) ->
+ lists:foldl(fun(#{ counters := Cnt }, Acc) ->
+ get_total(maps:remove(sleep, Cnt), Acc)
+ end, 0, Stats);
+stats(realtime, Stats) ->
+ RealTime = stats(system_realtime, Stats),
+ statssort([get_thread_perc(Thread, RealTime) || Thread <- Stats]);
+stats(runtime, Stats) ->
+ RunTime = stats(system_runtime, Stats),
+ statssort([get_thread_perc(T#{ counters := maps:remove(sleep,Cnt)}, RunTime)
+ || T = #{ counters := Cnt } <- Stats]);
+stats(type, Stats) ->
+ statssort(merge_threads(Stats, [])).
+
+print_stats_overview(Stats, _Options) ->
+ RunTime = stats(system_runtime, Stats),
+ RealTime = stats(system_realtime, Stats) div length(Stats),
+ SchedStats = [S || #{ type := scheduler } = S <- Stats],
+ AvgSchedRunTime = stats(system_runtime, SchedStats) div length(SchedStats),
+ NumSize = if
+ RealTime > RunTime -> length(integer_to_list(RealTime));
+ true -> length(integer_to_list(RunTime))
+ end,
+ [io_lib:format("Average thread real-time : ~*B us~n",
+ [NumSize, RealTime]),
+ io_lib:format("Accumulated system run-time : ~*B us~n",
+ [NumSize, RunTime]),
+ io_lib:format("Average scheduler run-time : ~*B us~n",
+ [NumSize, AvgSchedRunTime]),
+ io_lib:format("~n",[])].
+
+print_stats_threads(Stats, Options) ->
+ [io_lib:format("~nStats per thread:~n", []),
+ [print_thread_info(Thread, Options) || Thread <- Stats]].
+
+print_stats_type(Stats, Options) ->
+ [io_lib:format("~nStats per type:~n", []),
+ [print_thread_info(Thread, Options) || Thread <- Stats]].
+
+
+print_stats_header([#{ counters := Cnt }|_], #{ system := PrintSys }) ->
+ [io_lib:format("~14s", ["Thread"]),
+ map(fun(Counter, _) when PrintSys->
+ io_lib:format("~9s ", [atom_to_list(Counter)]);
+ (Counter, _) ->
+ io_lib:format("~9s", [atom_to_list(Counter)])
+ end, Cnt),
+ io_lib:format("~n",[])].
+
+print_thread_info(#{ '$type' := msacc_stats,
+ counters := Cnt } = Thread, #{ system := PrintSys }) ->
+ [case maps:find(id, Thread) of
+ error ->
+ io_lib:format("~14s", [atom_to_list(maps:get(type, Thread))]);
+ {ok, Id} ->
+ io_lib:format("~10s(~2B)", [atom_to_list(maps:get(type,Thread)),Id])
+ end,
+ map(fun(_Key, #{ thread := ThreadPerc, system := SystemPerc }) when PrintSys ->
+ io_lib:format("~6.2f%(~4.1f%)", [ThreadPerc, SystemPerc]);
+ (_Key, #{ thread := ThreadPerc }) ->
+ io_lib:format("~8.2f%", [ThreadPerc])
+ end, Cnt),
+ io_lib:format("~n",[])].
+
+get_total(Cnt, Base) ->
+ maps:fold(fun(_, {Val,_}, Time) ->
+ %% Have to handle ERTS_MSACC_STATE_COUNTERS
+ Time + Val;
+ (_, Val, Time) -> Time + Val
+ end, Base, Cnt).
+
+get_thread_perc(#{ '$type' := msacc_data, counters := Cnt } = Thread,
+ SystemTime) ->
+ ThreadTime = get_total(Cnt, 0),
+ Thread#{ '$type' := msacc_stats,
+ system => percentage(ThreadTime,SystemTime),
+ counters => get_thread_perc(Cnt, ThreadTime, SystemTime)}.
+get_thread_perc(Cnt, ThreadTime, SystemTime) ->
+ maps:map(fun F(Key, {Val, C}) ->
+ M = F(Key, Val),
+ M#{ cnt => C };
+ F(_Key, Val) ->
+ #{ thread => percentage(Val, ThreadTime),
+ system => percentage(Val, SystemTime) }
+ end, Cnt).
+
+%% This code is a little bit messy as it has to be able to deal with
+%% both [msacc_data()] and [msacc_stats()].
+merge_threads([#{ '$type' := msacc_stats,
+ type := Type,
+ counters := Cnt } = M0|R], Acc) ->
+ case keyfind(type, Type, Acc) of
+ false ->
+ merge_threads(R, [maps:remove(id,M0#{ threads => 1 })|Acc]);
+ #{ '$type' := msacc_stats, counters := Cnt0,
+ threads := Threads, system := System } = M ->
+ NewMap = M#{ counters := add_counters(Cnt, Cnt0),
+ system := System + maps:get(system, M0),
+ threads := Threads + 1},
+ NewAcc = keyreplace(type, Type, NewMap, Acc),
+ merge_threads(R, NewAcc)
+ end;
+merge_threads([], [#{ '$type' := msacc_stats,
+ system := System,
+ threads := Threads,
+ counters := Cnt} = M0|R]) ->
+ Counters = maps:map(fun(_,#{ thread := Thr } = Map) ->
+ Map#{ thread := Thr / Threads }
+ end, Cnt),
+ M = maps:remove(threads, M0),
+ [M#{ system := System, counters := Counters} | merge_threads([],R)];
+merge_threads([], []) ->
+ [];
+%% The clauses below deal with msacc_data()
+merge_threads([#{ '$type' := msacc_data,
+ type := Type,
+ counters := Cnt } = M0|R], Acc) ->
+ case keyfind(type, Type, Acc) of
+ false ->
+ merge_threads(R, [maps:remove(id,M0)|Acc]);
+ #{ '$type' := msacc_data, counters := Cnt0 } = M ->
+ NewMap = M#{ counters := add_counters(Cnt, Cnt0) },
+ NewAcc = keyreplace(type, Type, NewMap, Acc),
+ merge_threads(R, NewAcc)
+ end;
+merge_threads([], Acc) ->
+ Acc.
+
+add_counters(M1, M2) ->
+ maps:map(
+ fun(Key, #{ thread := Thr1, system := Sys1, cnt := Cnt1}) ->
+ %% Have to handle ERTS_MSACC_STATE_COUNTERS
+ #{ thread := Thr2, system := Sys2, cnt := Cnt2} = maps:get(Key, M2),
+ #{ thread => Thr1 + Thr2, system => Sys1 + Sys2,
+ cnt => Cnt1 + Cnt2 };
+ (Key, #{ thread := Thr1, system := Sys1}) ->
+ #{ thread := Thr2, system := Sys2} = maps:get(Key, M2),
+ #{ thread => Thr1 + Thr2, system => Sys1 + Sys2};
+ (Key, {V1,C1}) ->
+ %% Have to handle ERTS_MSACC_STATE_COUNTERS
+ {V2,C2} = maps:get(Key, M2),{V1+V2,C1+C2};
+ (Key, V1) -> maps:get(Key, M2) + V1
+ end, M1).
+
+percentage(Divident, Divisor) ->
+ if Divisor == 0 andalso Divident /= 0 ->
+ 100.0;
+ Divisor == 0 ->
+ 0.0;
+ true ->
+ Divident / Divisor * 100
+ end.
+
+keyfind(Key, Value, [H|T]) ->
+ case maps:find(Key, H) of
+ {ok, Value} ->
+ H;
+ _ ->
+ keyfind(Key, Value, T)
+ end;
+keyfind(_, _, []) ->
+ false.
+
+keyreplace(Key, Value, NewMap, [H|T]) ->
+ case maps:find(Key, H) of
+ {ok, Value} ->
+ [NewMap|T];
+ _ ->
+ [H|keyreplace(Key, Value, NewMap, T)]
+ end;
+keyreplace(_, _, _, []) ->
+ [].
+
+statssort(Stats) ->
+ lists:sort(fun(#{ type := Type1, id := Id1},
+ #{ type := Type2, id := Id2}) ->
+ {Type1, Id1} < {Type2, Id2};
+ (#{ type := Type1}, #{ type := Type2}) ->
+ Type1 < Type2
+ end, Stats).
+
+map(Fun,Map) ->
+ [ Fun(K,V) || {K,V} <- maps:to_list(Map) ].
diff --git a/lib/runtime_tools/src/runtime_tools.app.src b/lib/runtime_tools/src/runtime_tools.app.src
index ad10655aa0..aeda103e72 100644
--- a/lib/runtime_tools/src/runtime_tools.app.src
+++ b/lib/runtime_tools/src/runtime_tools.app.src
@@ -22,7 +22,8 @@
{vsn, "%VSN%"},
{modules, [appmon_info, dbg,observer_backend,percept_profile,
runtime_tools,runtime_tools_sup,erts_alloc_config,
- ttb_autostart,dyntrace,system_information]},
+ ttb_autostart,dyntrace,system_information,
+ msacc]},
{registered, [runtime_tools_sup]},
{applications, [kernel, stdlib]},
{env, []},
diff --git a/lib/runtime_tools/test/Makefile b/lib/runtime_tools/test/Makefile
index dcb9082231..432a361468 100644
--- a/lib/runtime_tools/test/Makefile
+++ b/lib/runtime_tools/test/Makefile
@@ -7,7 +7,8 @@ MODULES = \
runtime_tools_SUITE \
system_information_SUITE \
dbg_SUITE \
- erts_alloc_config_SUITE
+ erts_alloc_config_SUITE \
+ msacc_SUITE
ERL_FILES= $(MODULES:%=%.erl)
@@ -26,7 +27,7 @@ RELSYSDIR = $(RELEASE_PATH)/runtime_tools_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_COMPILE_FLAGS +=
EBIN = .
diff --git a/lib/runtime_tools/test/dbg_SUITE.erl b/lib/runtime_tools/test/dbg_SUITE.erl
index 11dd753eed..fd9b8f23bd 100644
--- a/lib/runtime_tools/test/dbg_SUITE.erl
+++ b/lib/runtime_tools/test/dbg_SUITE.erl
@@ -31,7 +31,7 @@
-export([tracee1/1, tracee2/1]).
-export([dummy/0, exported/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(default_timeout, ?t:minutes(1)).
init_per_testcase(_Case, Config) ->
diff --git a/lib/runtime_tools/test/dyntrace_SUITE.erl b/lib/runtime_tools/test/dyntrace_SUITE.erl
index 03242784dd..6d39bc54f4 100644
--- a/lib/runtime_tools/test/dyntrace_SUITE.erl
+++ b/lib/runtime_tools/test/dyntrace_SUITE.erl
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
%%
-module(dyntrace_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
diff --git a/lib/runtime_tools/test/erts_alloc_config_SUITE.erl b/lib/runtime_tools/test/erts_alloc_config_SUITE.erl
index 9c0a643e91..a5c4801af9 100644
--- a/lib/runtime_tools/test/erts_alloc_config_SUITE.erl
+++ b/lib/runtime_tools/test/erts_alloc_config_SUITE.erl
@@ -22,7 +22,7 @@
%-define(line_trace, 1).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%-compile(export_all).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
diff --git a/lib/runtime_tools/test/msacc_SUITE.erl b/lib/runtime_tools/test/msacc_SUITE.erl
new file mode 100644
index 0000000000..145a6d07fb
--- /dev/null
+++ b/lib/runtime_tools/test/msacc_SUITE.erl
@@ -0,0 +1,132 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2014-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(msacc_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+%% Test server callbacks
+-export([suite/0, all/0]).
+
+%% Test cases
+-export([
+ %% API-test
+ api_file/1,
+ api_start_stop/1,
+ api_timer/1,
+ api_print/1
+ ]).
+
+%%--------------------------------------------------------------------
+%% COMMON TEST CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+all() ->
+ [
+ api_start_stop,
+ api_file,
+ api_timer,
+ api_print
+ ].
+
+suite() -> [
+ {timetrap,{minutes,1}},
+ {ct_hooks,[ts_install_cth]}
+ ].
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+api_timer(_Config) ->
+
+ %% Run msacc for about 100ms
+ msacc:start(100),
+
+ %% Verify that scheduler 1 executed+slept for about 100ms
+ [Sched1] = [S || S = #{ type := scheduler, id := 1 } <- msacc:stats()],
+
+ #{ counters := Cnt } = Sched1,
+
+ %% Time should be in us
+ Time = maps:fold(fun(_,V,Acc) -> V + Acc end, 0, Cnt),
+
+ if Time < 120000 andalso Time > 80000 -> ok;
+ true -> ct:fail({inaccurate_time, Time, msacc:stats()})
+ end.
+
+%% We just do a basic check that none of the apis crash
+api_start_stop(_Config) ->
+ msacc:start(),
+ timer:sleep(100),
+ msacc:stop(),
+ Runtime = msacc:stats(system_runtime, msacc:stats()),
+ Realtime = msacc:stats(system_realtime, msacc:stats()),
+ true = Runtime < Realtime,
+
+ RuntimeCnt = msacc:stats(runtime, msacc:stats()),
+ RealtimeCnt = msacc:stats(realtime, msacc:stats()),
+ TypeCnt = msacc:stats(type, msacc:stats()),
+
+ %% These should be very similar
+ RuntimeTypeCnt = msacc:stats(type, RuntimeCnt),
+ TypeRuntimeCnt = msacc:stats(runtime, TypeCnt),
+ lists:map(fun({#{ system := T1 },#{ system := T2}}) ->
+ if T1-0.5 < T2 orelse T1+0.5 > T2 -> ok;
+ true -> ct:fail({inaccurate_stats, RuntimeTypeCnt,
+ TypeRuntimeCnt})
+ end
+ end, lists:zip(RuntimeTypeCnt, TypeRuntimeCnt)),
+
+ %% These should be very similar
+ RealtimeTypeCnt = msacc:stats(type, RealtimeCnt),
+ TypeRealtimeCnt = msacc:stats(realtime, TypeCnt),
+ lists:map(fun({#{ system := T1 },#{ system := T2}}) ->
+ if T1-0.5 < T2 orelse T1+0.5 > T2 -> ok;
+ true -> ct:fail({inaccurate_stats, RealtimeTypeCnt,
+ TypeRealtimeCnt})
+ end
+ end,lists:zip(RealtimeTypeCnt, TypeRealtimeCnt)),
+
+ msacc:reset().
+
+api_file(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ File = filename:join(PrivDir, "msacc.stats"),
+ Stats = msacc:stats(),
+ ok = msacc:to_file(File),
+ Stats = msacc:from_file(File),
+
+ PrintFile = filename:join(PrivDir, "msacc.txt"),
+ msacc:print(PrintFile, Stats, #{}).
+
+%% We just check that it is possible to print in a couple of different ways
+api_print(_Config) ->
+ msacc:start(100),
+ io:format("msacc:print(msacc:stats()).~n"),
+ msacc:print(msacc:stats()),
+ io:format("msacc:print(msacc:stats(),#{ system => true }).~n"),
+ msacc:print(msacc:stats(), #{ system => true }),
+ io:format("msacc:print(msacc:stats(runtime,msacc:stats())).~n"),
+ msacc:print(msacc:stats(runtime, msacc:stats())),
+ io:format("msacc:print(msacc:stats(type,msacc:stats())).~n"),
+ msacc:print(msacc:stats(type, msacc:stats())),
+ io:format("msacc:print(msacc:stats(realtime,msacc:stats())).~n"),
+ msacc:print(msacc:stats(realtime, msacc:stats())),
+ io:format("msacc:stats(type,msacc:stats(runtime,msacc:stats())).~n"),
+ msacc:print(msacc:stats(type, msacc:stats(runtime, msacc:stats()))).
diff --git a/lib/runtime_tools/test/runtime_tools_SUITE.erl b/lib/runtime_tools/test/runtime_tools_SUITE.erl
index 7599026e7e..2a79f0a8f9 100644
--- a/lib/runtime_tools/test/runtime_tools_SUITE.erl
+++ b/lib/runtime_tools/test/runtime_tools_SUITE.erl
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
%%
-module(runtime_tools_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
diff --git a/lib/sasl/doc/src/Makefile b/lib/sasl/doc/src/Makefile
index 1ee48af338..a66b1f8bcb 100644
--- a/lib/sasl/doc/src/Makefile
+++ b/lib/sasl/doc/src/Makefile
@@ -36,7 +36,6 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# ----------------------------------------------------
XML_APPLICATION_FILES = ref_man.xml
XML_REF3_FILES = alarm_handler.xml \
- overload.xml \
rb.xml \
release_handler.xml \
systools.xml
diff --git a/lib/sasl/doc/src/overload.xml b/lib/sasl/doc/src/overload.xml
deleted file mode 100644
index 2f19cd9088..0000000000
--- a/lib/sasl/doc/src/overload.xml
+++ /dev/null
@@ -1,152 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1996</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>overload</title>
- <prepared>Peter H&ouml;gfeldt</prepared>
- <responsible>Peter H&ouml;gfeldt</responsible>
- <docno></docno>
- <approved>(Joe Armstrong)</approved>
- <checked></checked>
- <date>1996-10-29</date>
- <rev>A</rev>
- <file>overload.sgml</file>
- </header>
- <module>overload</module>
- <modulesummary>An Overload Regulation Process</modulesummary>
- <description>
- <warning>
- <p>
- All functions in this module are deprecated and will be
- removed in a future release.
- </p>
- </warning>
- <p><c>overload</c> is a process that indirectly regulates the CPU
- usage in the system. The idea is that a main application calls
- function
- <seealso marker="#request/0"><c>request/0</c></seealso>
- before starting a major job and
- proceeds with the job if the return value is positive; otherwise
- the job must not be started.</p>
- <p><c>overload</c> is part of the <c>SASL</c> application and all
- configuration parameters are defined there.</p>
- <p>A set of two intensities are maintained, the <c>total intensity</c>
- and the <c>accept intensity</c>. For that purpose,
- there are two configuration parameters, <c>MaxIntensity</c>
- and <c>Weight</c>; both are measured in 1/second.</p>
- <p>Then total and accept intensities are calculated as
- follows. Assume that the time of the current call to
- <c>request/0</c> is <c>T(n)</c> and that the time of the
- previous call was <c>T(n-1)</c>.</p>
- <list type="bulleted">
- <item>
- <p>The current <c>total intensity</c>, denoted
- <c>TI(n)</c>, is calculated according to the formula</p>
- <p><c>TI(n) = exp(-Weight*(T(n) - T(n-1)) * TI(n-1) + Weight</c>,</p>
- <p>where <c>TI(n-1)</c> is the previous <c>total intensity</c>.</p>
- </item>
- <item>
- <p>The current <c>accept intensity</c>, denoted
- <c>AI(n)</c>, is determined by the formula</p>
- <p><c>AI(n) = exp(-Weight*(T(n) - T(n-1)) * AI(n-1) + Weight</c>,</p>
- <p>where <c>AI(n-1)</c> is the previous <c>accept intensity</c>,
- if the value of <c>exp(-Weight*(T(n) - T(n-1)) * AI(n-1)</c>
- is less than <c>MaxIntensity</c>. Otherwise the value is</p>
- <p><c>AI(n) = exp(-Weight*(T(n) - T(n-1)) * AI(n-1)</c></p>
- </item>
- </list>
- <p>The value of configuration parameter <c>Weight</c> controls the
- speed with which the calculations of intensities react to
- changes in the underlying input intensity. The inverted value of
- <c>Weight</c>, <c>T = 1/Weight</c>, can be thought of as the
- "time constant" of the intensity calculation formulas. For example,
- if <c>Weight = 0.1</c>, a change in the underlying input intensity is
- reflected in <c>total intensity</c> and <c>accept intensity</c> within
- about 10 seconds.</p>
- <p>The overload process defines one alarm, which it sets using
- <c>alarm_handler:set_alarm(Alarm)</c>. <c>Alarm</c> is defined
- as follows:</p>
- <taglist>
- <tag><c>{overload, []}</c></tag>
- <item>
- <p>This alarm is set when the current <c>accept intensity</c> exceeds
- <c>MaxIntensity</c>.</p>
- </item>
- </taglist>
- <p>A new request is not accepted until the current <c>accept
- intensity</c> has fallen below <c>MaxIntensity</c>. To prevent the
- overload process from generating many set/reset alarms, the
- alarm is not reset until the current <c>accept intensity</c> has fallen
- below 75% of <c>MaxIntensity</c>; it is not until then that
- the alarm can be set again.</p>
- </description>
-
- <funcs>
- <func>
- <name>request() -> accept | reject</name>
- <fsummary>Requests to proceed with current job.</fsummary>
- <desc>
- <p>Returns <c>accept</c> or <c>reject</c> depending on the
- current value of the <c>accept intensity</c>.</p>
- <p>The application
- calling this function is to proceed with the job in
- question if the return value is <c>accept</c>; otherwise it
- is not to continue with that job.</p>
- </desc>
- </func>
-
- <func>
- <name>get_overload_info() -> OverloadInfo</name>
- <fsummary>Returns current overload information data.</fsummary>
- <type>
- <v>OverloadInfo = [{total_intensity, TotalIntensity},
- {accept_intensity, AcceptIntensity}, {max_intensity,
- MaxIntensity}, {weight, Weight}, {total_requests,
- TotalRequests}, {accepted_requests, AcceptedRequests}].</v>
- <v>TotalIntensity = float() > 0</v>
- <v>AcceptIntensity = float() > 0</v>
- <v>MaxIntensity = float() > 0</v>
- <v>Weight = float() > 0</v>
- <v>TotalRequests = integer()</v>
- <v>AcceptedRequests = integer()</v>
- </type>
- <desc>
- <p>Returns:</p>
- <list type="bulleted">
- <item>Current total and accept intensities</item>
- <item>Configuration parameters</item>
- <item>Absolute counts of the total number of requests</item>
- <item>Accepted number of requests (since the overload
- process was started)</item>
- </list>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>See Also</title>
- <p><seealso marker="alarm_handler"><c>alarm_handler(3)</c></seealso>,
- <seealso marker="sasl_app"><c>sasl(6)</c></seealso></p>
- </section>
-</erlref>
-
diff --git a/lib/sasl/doc/src/ref_man.xml b/lib/sasl/doc/src/ref_man.xml
index a80e5a2a00..74cd92a9b0 100644
--- a/lib/sasl/doc/src/ref_man.xml
+++ b/lib/sasl/doc/src/ref_man.xml
@@ -35,7 +35,6 @@
</description>
<xi:include href="sasl_app.xml"/>
<xi:include href="alarm_handler.xml"/>
- <xi:include href="overload.xml"/>
<xi:include href="rb.xml"/>
<xi:include href="release_handler.xml"/>
<xi:include href="systools.xml"/>
diff --git a/lib/sasl/doc/src/sasl_app.xml b/lib/sasl/doc/src/sasl_app.xml
index bcd446a868..044c016302 100644
--- a/lib/sasl/doc/src/sasl_app.xml
+++ b/lib/sasl/doc/src/sasl_app.xml
@@ -34,7 +34,6 @@
<p>The <c>SASL</c> application provides the following services:</p>
<list type="bulleted">
<item><c>alarm_handler</c></item>
- <item><c>overload</c> (deprecated)</item>
<item><c>rb</c></item>
<item><c>release_handler</c></item>
<item><c>systools</c></item>
@@ -140,21 +139,6 @@
this parameter is undefined, the <c>log_mf_h</c> handler is
not installed.</p>
</item>
- <tag><c><![CDATA[overload_max_intensity = float() > 0 ]]></c></tag>
- <item>
- <p>Specifies the maximum intensity
- for <seealso marker="overload"><c>overload</c></seealso>. Default
- is <c>0.8</c>.</p>
- <p>Note that the <c>overload</c> module is deprected and
- will be removed in a future release.</p>
- </item>
- <tag><c><![CDATA[overload_weight = float() > 0 ]]></c></tag>
- <item>
- <p>Specifies the <seealso marker="overload"><c>overload</c></seealso>
- weight. Default is <c>0.1</c>.</p>
- <p>Note that the <c>overload</c> module is deprected and
- will be removed in a future release.</p>
- </item>
<tag><c><![CDATA[start_prg = string() ]]></c></tag>
<item>
<p>Specifies the program to be used when restarting the system
@@ -205,7 +189,6 @@
<p><seealso marker="alarm_handler"><c>alarm_handler(3)</c></seealso>,
<seealso marker="kernel:error_logger"><c>error_logger(3)</c></seealso>,
<seealso marker="stdlib:log_mf_h"><c>log_mf_h(3)</c></seealso>,
- <seealso marker="overload"><c>overload(3)</c></seealso>,
<seealso marker="rb"><c>rb(3)</c></seealso>,
<seealso marker="release_handler"><c>release_handler(3)</c></seealso>,
<seealso marker="systools"><c>systools(3)</c></seealso></p>
diff --git a/lib/sasl/doc/src/sasl_intro.xml b/lib/sasl/doc/src/sasl_intro.xml
index bbc9457103..237580977c 100644
--- a/lib/sasl/doc/src/sasl_intro.xml
+++ b/lib/sasl/doc/src/sasl_intro.xml
@@ -36,7 +36,6 @@
<list type="bulleted">
<item>Error logging</item>
<item>Alarm handling</item>
- <item>Overload regulation</item>
<item>Release handling</item>
<item>Report browsing</item>
</list>
diff --git a/lib/sasl/src/Makefile b/lib/sasl/src/Makefile
index 7ff6a03a50..92d4818f2e 100644
--- a/lib/sasl/src/Makefile
+++ b/lib/sasl/src/Makefile
@@ -36,7 +36,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/sasl-$(VSN)
# ----------------------------------------------------
MODULES= alarm_handler sasl sasl_report \
sasl_report_file_h sasl_report_tty_h format_lib_supp \
- misc_supp overload rb rb_format_supp release_handler \
+ misc_supp rb rb_format_supp release_handler \
release_handler_1 si si_sasl_supp systools \
systools_make systools_rc systools_relup systools_lib \
erlsrv
diff --git a/lib/sasl/src/misc_supp.erl b/lib/sasl/src/misc_supp.erl
index 42de7eedec..39656f6e65 100644
--- a/lib/sasl/src/misc_supp.erl
+++ b/lib/sasl/src/misc_supp.erl
@@ -27,7 +27,7 @@
%%% 2) Very generic functions such as, multi_map, is_string...
%%%
%%% This module is a part of the BOS. (format_pdict is called from
-%%% init, memsup, disksup, overload (but not the fileserver since it
+%%% init, memsup, disksup (but not the fileserver since it
%%% formats its pdict its own way).)
%%%---------------------------------------------------------------------
diff --git a/lib/sasl/src/overload.erl b/lib/sasl/src/overload.erl
deleted file mode 100644
index bc8ab7d5e4..0000000000
--- a/lib/sasl/src/overload.erl
+++ /dev/null
@@ -1,233 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2013. 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(overload).
-
--deprecated(module).
-
--export([start_link/0, request/0, set_config_data/2,
- get_overload_info/0]).
-
--export([init/1, handle_call/3, handle_info/2, terminate/2,
- format_status/2]).
-
-%%%-----------------------------------------------------------------
-%%% This is a rewrite of overload from BS.3, by Peter Högfeldt.
-%%%
-%%% DESCRIPTION
-%%%
-%%% This module implements a server process that keeps record of the
-%%% intensity of calls of the request/0 function, and answers accept or
-%%% reject depending on if the current average intensity is not greater
-%%% than a specified maximum intensity.
-%%%
-%%% The intensity i is calculated according to the formula:
-%%% i(n) = exp(-K*(T(n) - T(n-1)))*i(n-1) + Kappa
-%%% where i(n) is the intensity at event n, Kappa is a constant, and
-%%% T(n) is the time at event n.
-%%%
-%%% The constant Kappa can be thought of as 1 / T, where T is the time
-%%% constant. Kappa is externally referred to as Weight.
-%%%
-%%% We keep track of two intensities: the total call intensity and the
-%%% intensity of accepted calls.
-%%%-----------------------------------------------------------------
-%%% TODO
-%%%
-%%% 3. Hysteresis.
-%%%
-%%%-----------------------------------------------------------------
-
--record(state, {total = 0, accept = 0, max, prev_t = get_now(),
- kappa, call_counts = {0, 0}, alarm = clear}).
-
--define(clear_timeout, 30000).
-
-start_link() ->
- gen_server:start_link({local, overload}, overload, [], []).
-
-init([]) ->
- process_flag(priority, high),
- MaxIntensity = fetch_config_data(overload_max_intensity),
- Kappa = fetch_config_data(overload_weight),
- {ok, #state{max = MaxIntensity, kappa = Kappa}}.
-
-%%-----------------------------------------------------------------
-%% Func: request/0
-%% Purpose: This is a request to proceed, e.g. a request to
-%% establish a call.
-%% Returns: accept | reject
-%%-----------------------------------------------------------------
-request() -> call(request).
-
-%%-----------------------------------------------------------------
-%% Func: set_config_data/2
-%% Purpose: Set configuration data, and reset intensities.
-%% Arguments: MaxIntensity (real > 0), Weight (real > 0).
-%% Returns: ok | {error, What}
-%% This function is for debugging purposes and is therefore not
-%% documented at all.
-%%-----------------------------------------------------------------
-set_config_data(MaxIntensity, Weight) ->
- call({set_config_data, MaxIntensity, Weight}).
-%%-----------------------------------------------------------------
-%% Func: get_overload_info/0
-%% Returns: A list of tagged items: TotalIntensity, AcceptIntensity,
-%% MaxIntensity, Weight, TotalRequests, AcceptedRequests.
-%%-----------------------------------------------------------------
-get_overload_info() -> call(get_overload_info).
-
-%%-----------------------------------------------------------------
-%% call(Request) -> Term
-%%-----------------------------------------------------------------
-call(Req) ->
- gen_server:call(overload, Req, infinity).
-
-%%%-----------------------------------------------------------------
-%%% Callback functions from gen_server
-%%%-----------------------------------------------------------------
-handle_call(request, _From, State) ->
- #state{total = TI, accept = AI, kappa = Kappa, prev_t = PrevT,
- alarm = Alarm} = State,
- {TR, AR} = State#state.call_counts,
- T = get_now(),
- CurI = new_intensity(AI, T, PrevT, Kappa),
- NewTI = new_intensity(TI, T, PrevT, Kappa) + Kappa,
- if
- CurI =< State#state.max ->
- %% Hysteresis: If alarm is set, and current intensity has
- %% fallen below 75% of max intensity, clear alarm.
- NewAlarm = if
- CurI =< 0.75*State#state.max ->
- clear_alarm(Alarm);
- true ->
- Alarm
- end,
- {reply, accept, State#state{call_counts = {TR+1, AR+1},
- prev_t = T, total = NewTI,
- accept = CurI + Kappa,
- alarm = NewAlarm},
- ?clear_timeout};
- true ->
- %% Set alarm if not already set.
- NewAlarm = set_alarm(Alarm),
- {reply, reject,
- State#state{call_counts = {TR+1, AR}, prev_t = T,
- total = NewTI, accept = CurI,
- alarm = NewAlarm},
- ?clear_timeout}
- end;
-handle_call({set_config_data, MaxIntensity, Weight}, _From, _State) ->
- {reply, ok, #state{max = MaxIntensity, kappa = Weight},
- ?clear_timeout};
-handle_call(get_overload_info, _From, State) ->
- #state{max = MI, total = TI, accept = AI, kappa = Kappa,
- prev_t = PrevT, call_counts = {TR, AR}} = State,
- T = get_now(),
- CurI = new_intensity(AI, T, PrevT, Kappa),
- NewTI = new_intensity(TI, T, PrevT, Kappa),
- Reply = [{total_intensity, NewTI}, {accept_intensity, CurI},
- {max_intensity, MI}, {weight, Kappa},
- {total_requests, TR}, {accepted_requests, AR}],
- {reply, Reply, State#state{total = NewTI, accept = CurI},
- ?clear_timeout}.
-
-handle_info(timeout, State) ->
- #state{total = TI, accept = AI, kappa = Kappa, prev_t = PrevT,
- alarm = Alarm} = State,
- T = get_now(),
- CurI = new_intensity(AI, T, PrevT, Kappa),
- NewTI = new_intensity(TI, T, PrevT, Kappa),
- if
- CurI < 0.75* State#state.max ->
- NewAlarm = clear_alarm(Alarm),
- {noreply, State#state{total = NewTI, accept = CurI,
- alarm = NewAlarm}};
-
- true ->
- {noreply, State#state{total = NewTI, accept = CurI},
- ?clear_timeout}
- end;
-
-handle_info(_, State) ->
- {noreply, State, ?clear_timeout}.
-
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-fetch_config_data(Tag) ->
- case application:get_env(sasl, Tag) of
- {ok, Value} -> Value;
- _ -> fetch_default_data(Tag)
- end.
-
-fetch_default_data(overload_max_intensity) -> 0.8;
-fetch_default_data(overload_weight) -> 0.1.
-
-set_alarm(clear) ->
- alarm_handler:set_alarm({overload, []}),
- set;
-set_alarm(Alarm) ->
- Alarm.
-
-clear_alarm(set) ->
- alarm_handler:clear_alarm(overload),
- clear;
-clear_alarm(Alarm) ->
- Alarm.
-
-%%-----------------------------------------------------------------
-%% The catch protects against floating-point exception.
-%%
-new_intensity(I, T, PrevT, K) ->
- Diff = sub(T, PrevT)/1000,
- case catch (I*math:exp(-K*Diff)) of
- {'EXIT', _} -> % Assume zero.
- 0.0;
- Res ->
- Res
- end.
-
-%% Mask equal to 2^27 - 1, used below.
--define(mask27, 16#7ffffff).
-
-%% Returns number of milliseconds in the range [0, 2^27 - 1]. Must have
-%% this since statistics(wall_clock) wraps. Having 2^27 -1 as the max
-%% assures that we always get non-negative integers. 2^27 milliseconds
-%% are approx. 37.28 hours.
-get_now() ->
- element(1, statistics(wall_clock)) band ?mask27.
-
-%% Returns (X - Y) mod 2^27 (which is in the range [0, 2^27 - 1]).
-sub(X, Y) ->
- (X + (bnot Y) + 1) band ?mask27.
-
-format_status(Opt, [PDict, #state{max = MI, total = TI, accept = AI,
- kappa = K,
- call_counts = {TR, AR}}]) ->
- [{data, [{"Total Intensity", TI},
- {"Accept Intensity", AI},
- {"Max Intensity", MI},
- {"Weight", K},
- {"Total requests", TR},
- {"Accepted requests", AR}]} |
- misc_supp:format_pdict(Opt, PDict, [])].
diff --git a/lib/sasl/src/sasl.app.src b/lib/sasl/src/sasl.app.src
index 507e2dc229..16e8e44ba2 100644
--- a/lib/sasl/src/sasl.app.src
+++ b/lib/sasl/src/sasl.app.src
@@ -24,7 +24,6 @@
alarm_handler,
format_lib_supp,
misc_supp,
- overload,
rb,
rb_format_supp,
release_handler,
@@ -41,7 +40,7 @@
systools_relup,
systools_lib
]},
- {registered, [sasl_sup, alarm_handler, overload, release_handler]},
+ {registered, [sasl_sup, alarm_handler, release_handler]},
{applications, [kernel, stdlib]},
{env, [{sasl_error_logger, tty},
{errlog_type, all}]},
diff --git a/lib/sasl/src/sasl.appup.src b/lib/sasl/src/sasl.appup.src
index e08ae369b8..ca5122dab4 100644
--- a/lib/sasl/src/sasl.appup.src
+++ b/lib/sasl/src/sasl.appup.src
@@ -18,9 +18,9 @@
%% %CopyrightEnd%
{"%VSN%",
%% Up from - max one major revision back
- [{<<"2\\.[5-7](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.*
- {<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17
+ [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.*
+ {<<"2\\.[5-7](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-18.*
%% Down to - max one major revision back
- [{<<"2\\.[5-7](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.*
- {<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17
+ [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.*
+ {<<"2\\.[5-7](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-18.*
}.
diff --git a/lib/sasl/src/sasl.erl b/lib/sasl/src/sasl.erl
index fc49fc2465..0fb85682c6 100644
--- a/lib/sasl/src/sasl.erl
+++ b/lib/sasl/src/sasl.erl
@@ -170,7 +170,4 @@ init(safe) ->
AlarmH = {alarm_handler,
{alarm_handler, start_link, []},
permanent, 2000, worker, dynamic},
- Overload = {overload,
- {overload, start_link, []},
- permanent, 2000, worker, [overload]},
- {ok, {SupFlags, [AlarmH, Overload]}}.
+ {ok, {SupFlags, [AlarmH]}}.
diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl
index 8132034172..d207dc15bb 100644
--- a/lib/sasl/src/systools_make.erl
+++ b/lib/sasl/src/systools_make.erl
@@ -1469,7 +1469,9 @@ mandatory_modules() ->
preloaded() ->
%% Sorted
- [erl_prim_loader,erlang,erts_internal,init,otp_ring0,prim_eval,prim_file,
+ [erl_prim_loader,erlang,
+ erts_code_purger,
+ erts_internal,init,otp_ring0,prim_eval,prim_file,
prim_inet,prim_zip,zlib].
%%______________________________________________________________________
diff --git a/lib/sasl/test/Makefile b/lib/sasl/test/Makefile
index 86976def6a..2e9e107efd 100644
--- a/lib/sasl/test/Makefile
+++ b/lib/sasl/test/Makefile
@@ -33,7 +33,6 @@ MODULES= \
sasl_report_suite_supervisor \
systools_SUITE \
systools_rc_SUITE \
- overload_SUITE \
rb_SUITE \
rh_test_lib \
@@ -55,8 +54,7 @@ RELSYSDIR = $(RELEASE_PATH)/sasl_test
# FLAGS
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \
- -I$(ERL_TOP)/lib/sasl/src
+ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/sasl/src
EBIN = .
diff --git a/lib/sasl/test/overload_SUITE.erl b/lib/sasl/test/overload_SUITE.erl
deleted file mode 100644
index 02d1056698..0000000000
--- a/lib/sasl/test/overload_SUITE.erl
+++ /dev/null
@@ -1,168 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2011. 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(overload_SUITE).
--include_lib("common_test/include/ct.hrl").
-
--compile(export_all).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all() -> [info, set_config_data, set_env_vars, request, timeout].
-
-init_per_testcase(_Case,Config) ->
- restart_sasl(),
- Config.
-
-end_per_testcase(Case,Config) ->
- try apply(?MODULE,Case,[cleanup,Config])
- catch error:undef -> ok
- end,
- ok.
-
-%%%-----------------------------------------------------------------
-info(_Config) ->
- Info = overload:get_overload_info(),
- [{total_intensity,0.0},
- {accept_intensity,0.0},
- {max_intensity,0.8},
- {weight,0.1},
- {total_requests,0},
- {accepted_requests,0}] = Info.
-
-%%%-----------------------------------------------------------------
-set_config_data(_Config) ->
- InfoDefault = overload:get_overload_info(),
- ok = check_info(0.8,0.1,InfoDefault),
- ok = overload:set_config_data(0.5,0.4),
- Info1 = overload:get_overload_info(),
- ok = check_info(0.5,0.4,Info1),
- ok.
-
-%%%-----------------------------------------------------------------
-set_env_vars(_Config) ->
- InfoDefault = overload:get_overload_info(),
- ok = check_info(0.8,0.1,InfoDefault),
- ok = application:set_env(sasl,overload_max_intensity,0.5),
- ok = application:set_env(sasl,overload_weight,0.4),
- ok = application:stop(sasl),
- ok = application:start(sasl),
- Info1 = overload:get_overload_info(),
- ok = check_info(0.5,0.4,Info1),
- ok.
-set_env_vars(cleanup,_Config) ->
- application:unset_env(sasl,overload_max_intensity),
- application:unset_env(sasl,overload_weight),
- ok.
-
-%%%-----------------------------------------------------------------
-request(_Config) ->
- %% Find number of request that can be done with default settings
- %% and no delay
- overload:set_config_data(0.8, 0.1),
- NDefault = do_many_requests(0),
- restart_sasl(),
- ?t:format("NDefault: ~p",[NDefault]),
-
- %% Check that the number of requests increases when max_intensity
- %% increases
- overload:set_config_data(2, 0.1),
- NLargeMI = do_many_requests(0),
- restart_sasl(),
- ?t:format("NLargeMI: ~p",[NLargeMI]),
- true = NLargeMI > NDefault,
-
- %% Check that the number of requests decreases when weight
- %% increases
- overload:set_config_data(0.8, 1),
- NLargeWeight = do_many_requests(0),
- restart_sasl(),
- ?t:format("NLargeWeight: ~p",[NLargeWeight]),
- true = NLargeWeight < NDefault,
-
- %% Check that number of requests increases when delay between
- %% requests increases.
- %% (Keeping same config and comparing to large weight in order to
- %% minimize the time needed for this case.)
- overload:set_config_data(0.8, 1),
- NLargeTime = do_many_requests(500),
- restart_sasl(),
- ?t:format("NLargeTime: ~p",[NLargeTime]),
- true = NLargeTime > NLargeWeight,
- ok.
-
-%%%-----------------------------------------------------------------
-timeout(_Config) ->
- overload:set_config_data(0.8, 1),
- _N = do_many_requests(0),
-
- %% Check that the overload alarm is raised
- [{overload,_}] = alarm_handler:get_alarms(),
-
- %% Fake a clear timeout in overload.erl and check that, since it
- %% came very soon after the overload situation, the alarm is not
- %% cleared
- overload ! timeout,
- timer:sleep(1000),
- [{overload,_}] = alarm_handler:get_alarms(),
-
- %% A bit later, try again and check that this time the alarm is
- %% cleared
- overload ! timeout,
- timer:sleep(1000),
- [] = alarm_handler:get_alarms(),
-
- ok.
-
-
-%%%-----------------------------------------------------------------
-%%% INTERNAL FUNCTIONS
-
-%%%-----------------------------------------------------------------
-%%% Call overload:request/0 up to 30 times with the given time delay
-%%% between. Stop when 'reject' is returned.
-do_many_requests(T) ->
- 30 - do_requests(30,T).
-
-do_requests(0,_) ->
- ?t:fail(never_rejected);
-do_requests(N,T) ->
- case overload:request() of
- accept ->
- timer:sleep(T),
- do_requests(N-1,T);
- reject ->
- N
- end.
-
-%%%-----------------------------------------------------------------
-%%% Restart the sasl application
-restart_sasl() ->
- application:stop(sasl),
- application:start(sasl),
- ok.
-
-%%%-----------------------------------------------------------------
-%%% Check that max_intensity and weight is set as expected
-check_info(MI,W,Info) ->
- case {lists:keyfind(max_intensity,1,Info), lists:keyfind(weight,1,Info)} of
- {{_,MI},{_,W}} -> ok;
- _ -> ?t:fail({unexpected_info,MI,W,Info})
- end.
diff --git a/lib/sasl/test/sasl_report_SUITE.erl b/lib/sasl/test/sasl_report_SUITE.erl
index 940234f152..7469ec4d46 100644
--- a/lib/sasl/test/sasl_report_SUITE.erl
+++ b/lib/sasl/test/sasl_report_SUITE.erl
@@ -24,7 +24,7 @@
-export([crash_me/0,start_link/0,init/1,handle_cast/2,terminate/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl
index cf0ed5fcfc..825a7f6e86 100644
--- a/lib/sasl/test/systools_SUITE.erl
+++ b/lib/sasl/test/systools_SUITE.erl
@@ -1640,25 +1640,21 @@ app_start_type_relup(Dir2,Name2,Config) ->
%% ?t:format("Dn: ~p",[DownInstructions]),
[{load_object_code, {mnesia, _, _}},
{load_object_code, {runtime_tools, _, _}},
- {load_object_code, {webtool, _, _}},
{load_object_code, {snmp, _, _}},
{load_object_code, {xmerl, _, _}},
point_of_no_return
| UpInstructionsT] = UpInstructions,
true = lists:member({apply,{application,start,[mnesia,permanent]}}, UpInstructionsT),
true = lists:member({apply,{application,start,[runtime_tools,transient]}}, UpInstructionsT),
- true = lists:member({apply,{application,start,[webtool,temporary]}}, UpInstructionsT),
true = lists:member({apply,{application,load,[snmp]}}, UpInstructionsT),
false = lists:any(fun({apply,{application,_,[xmerl|_]}}) -> true; (_) -> false end, UpInstructionsT),
[point_of_no_return | DownInstructionsT] = DownInstructions,
true = lists:member({apply,{application,stop,[mnesia]}}, DownInstructionsT),
true = lists:member({apply,{application,stop,[runtime_tools]}}, DownInstructionsT),
- true = lists:member({apply,{application,stop,[webtool]}}, DownInstructionsT),
true = lists:member({apply,{application,stop,[snmp]}}, DownInstructionsT),
true = lists:member({apply,{application,stop,[xmerl]}}, DownInstructionsT),
true = lists:member({apply,{application,unload,[mnesia]}}, DownInstructionsT),
true = lists:member({apply,{application,unload,[runtime_tools]}}, DownInstructionsT),
- true = lists:member({apply,{application,unload,[webtool]}}, DownInstructionsT),
true = lists:member({apply,{application,unload,[snmp]}}, DownInstructionsT),
true = lists:member({apply,{application,unload,[xmerl]}}, DownInstructionsT),
ok.
@@ -2207,7 +2203,6 @@ create_script(latest_app_start_type1,Config) ->
create_script(latest_app_start_type2,Config) ->
OtherApps = [{mnesia,current,permanent},
{runtime_tools,current,transient},
- {webtool,current,temporary},
{snmp,current,load},
{xmerl,current,none}],
Apps = core_apps(current) ++ OtherApps,
diff --git a/lib/sasl/test/systools_rc_SUITE.erl b/lib/sasl/test/systools_rc_SUITE.erl
index 3754ed99f2..2ecb6f107a 100644
--- a/lib/sasl/test/systools_rc_SUITE.erl
+++ b/lib/sasl/test/systools_rc_SUITE.erl
@@ -26,10 +26,6 @@
translate_emulator_restarts/1,
translate_add_delete_module/1]).
-%%-----------------------------------------------------------------
-%% erl -compile systools_rc_SUITE @i ../src/ @i ../../test_server/include/
-%% c(systools_rc_SUITE, [{i, "../src"}, {i, "../../test_server/include"}]).
-%%-----------------------------------------------------------------
all() ->
[syntax_check, translate, translate_app, translate_emulator_restarts,
translate_add_delete_module].
diff --git a/lib/snmp/test/Makefile b/lib/snmp/test/Makefile
index 3261982a32..8e895bc5b1 100644
--- a/lib/snmp/test/Makefile
+++ b/lib/snmp/test/Makefile
@@ -150,7 +150,6 @@ ERL_COMPILE_FLAGS += -I../../snmp/src/app \
-I../../snmp/src/misc \
-I../../snmp/src/agent \
-I../../snmp/src/manager \
- -I$(ERL_TOP)/lib/test_server/include \
-I../../snmp/include \
-Dsnmp_test_data=snmp_test_data \
-Dversion=\"$(VSN)$(PRE_VSN)\" \
diff --git a/lib/snmp/test/exp/snmp_agent_ms_test.erl b/lib/snmp/test/exp/snmp_agent_ms_test.erl
index 3415fcc8e6..3010de0619 100644
--- a/lib/snmp/test/exp/snmp_agent_ms_test.erl
+++ b/lib/snmp/test/exp/snmp_agent_ms_test.erl
@@ -29,7 +29,7 @@
-define(application, snmp).
-include_lib("kernel/include/file.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
-define(SNMP_USE_V3, true).
-include_lib("snmp/include/snmp_types.hrl").
diff --git a/lib/snmp/test/exp/snmp_agent_mt_test.erl b/lib/snmp/test/exp/snmp_agent_mt_test.erl
index 89815e1044..71ae58baca 100644
--- a/lib/snmp/test/exp/snmp_agent_mt_test.erl
+++ b/lib/snmp/test/exp/snmp_agent_mt_test.erl
@@ -29,7 +29,7 @@
-define(application, snmp).
-include_lib("kernel/include/file.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
-define(SNMP_USE_V3, true).
-include_lib("snmp/include/snmp_types.hrl").
diff --git a/lib/snmp/test/exp/snmp_agent_v1_test.erl b/lib/snmp/test/exp/snmp_agent_v1_test.erl
index ec243747df..55045d536e 100644
--- a/lib/snmp/test/exp/snmp_agent_v1_test.erl
+++ b/lib/snmp/test/exp/snmp_agent_v1_test.erl
@@ -29,7 +29,7 @@
-define(application, snmp).
-include_lib("kernel/include/file.hrl").
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
-define(SNMP_USE_V3, true).
-include_lib("snmp/include/snmp_types.hrl").
diff --git a/lib/snmp/test/exp/snmp_agent_v2_test.erl b/lib/snmp/test/exp/snmp_agent_v2_test.erl
index ce95d0b5cd..6238a6c4bd 100644
--- a/lib/snmp/test/exp/snmp_agent_v2_test.erl
+++ b/lib/snmp/test/exp/snmp_agent_v2_test.erl
@@ -29,7 +29,7 @@
-define(application, snmp).
-include_lib("kernel/include/file.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
-define(SNMP_USE_V3, true).
-include_lib("snmp/include/snmp_types.hrl").
diff --git a/lib/snmp/test/exp/snmp_agent_v3_test.erl b/lib/snmp/test/exp/snmp_agent_v3_test.erl
index 1ba06209b2..af7cee9b96 100644
--- a/lib/snmp/test/exp/snmp_agent_v3_test.erl
+++ b/lib/snmp/test/exp/snmp_agent_v3_test.erl
@@ -29,7 +29,7 @@
-define(application, snmp).
-include_lib("kernel/include/file.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
-define(SNMP_USE_V3, true).
-include_lib("snmp/include/snmp_types.hrl").
diff --git a/lib/snmp/test/snmp_agent_mibs_test.erl b/lib/snmp/test/snmp_agent_mibs_test.erl
index a03c2b8534..2cbba14c74 100644
--- a/lib/snmp/test/snmp_agent_mibs_test.erl
+++ b/lib/snmp/test/snmp_agent_mibs_test.erl
@@ -31,7 +31,7 @@
%% Include files
%%----------------------------------------------------------------------
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
-include_lib("snmp/include/snmp_types.hrl").
-include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl").
diff --git a/lib/snmp/test/snmp_agent_nfilter_test.erl b/lib/snmp/test/snmp_agent_nfilter_test.erl
index 16a9903198..8aeef81333 100644
--- a/lib/snmp/test/snmp_agent_nfilter_test.erl
+++ b/lib/snmp/test/snmp_agent_nfilter_test.erl
@@ -26,7 +26,7 @@
%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl
index 412d62c6a1..93968ede2e 100644
--- a/lib/snmp/test/snmp_agent_test.erl
+++ b/lib/snmp/test/snmp_agent_test.erl
@@ -421,7 +421,7 @@
-define(application, snmp).
-include_lib("kernel/include/file.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
-define(SNMP_USE_V3, true).
-include_lib("snmp/include/snmp_types.hrl").
diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl
index 8ea7b2e081..6f20254fcb 100644
--- a/lib/snmp/test/snmp_agent_test_lib.erl
+++ b/lib/snmp/test/snmp_agent_test_lib.erl
@@ -69,7 +69,7 @@
-export([wait/5, run/4]).
-include_lib("kernel/include/file.hrl").
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
-define(SNMP_USE_V3, true).
-include_lib("snmp/include/snmp_types.hrl").
diff --git a/lib/snmp/test/snmp_app_test.erl b/lib/snmp/test/snmp_app_test.erl
index 3b5b196ad6..6892d4aa93 100644
--- a/lib/snmp/test/snmp_app_test.erl
+++ b/lib/snmp/test/snmp_app_test.erl
@@ -45,7 +45,7 @@
-include_lib("kernel/include/file.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
diff --git a/lib/snmp/test/snmp_compiler_test.erl b/lib/snmp/test/snmp_compiler_test.erl
index c83c4e0fed..b08181191f 100644
--- a/lib/snmp/test/snmp_compiler_test.erl
+++ b/lib/snmp/test/snmp_compiler_test.erl
@@ -29,7 +29,7 @@
%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
-include_lib("snmp/include/snmp_types.hrl").
diff --git a/lib/snmp/test/snmp_conf_test.erl b/lib/snmp/test/snmp_conf_test.erl
index 1d514cd1d2..73b471b107 100644
--- a/lib/snmp/test/snmp_conf_test.erl
+++ b/lib/snmp/test/snmp_conf_test.erl
@@ -27,7 +27,7 @@
%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
-include_lib("snmp/include/STANDARD-MIB.hrl").
diff --git a/lib/snmp/test/snmp_log_test.erl b/lib/snmp/test/snmp_log_test.erl
index b204522ee0..ae2581fb69 100644
--- a/lib/snmp/test/snmp_log_test.erl
+++ b/lib/snmp/test/snmp_log_test.erl
@@ -30,7 +30,7 @@
%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
-define(SNMP_USE_V3, true).
-include_lib("snmp/include/snmp_types.hrl").
diff --git a/lib/snmp/test/snmp_manager_config_test.erl b/lib/snmp/test/snmp_manager_config_test.erl
index 47e150e8e8..8428b61e8a 100644
--- a/lib/snmp/test/snmp_manager_config_test.erl
+++ b/lib/snmp/test/snmp_manager_config_test.erl
@@ -32,7 +32,7 @@
%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
-include_lib("snmp/src/manager/snmpm_usm.hrl").
diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl
index 3d05e5791f..a343dfdca7 100644
--- a/lib/snmp/test/snmp_manager_test.erl
+++ b/lib/snmp/test/snmp_manager_test.erl
@@ -32,7 +32,7 @@
%% Include files
%%----------------------------------------------------------------------
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
-include("snmp_test_data/Test2.hrl").
diff --git a/lib/snmp/test/snmp_manager_user.erl b/lib/snmp/test/snmp_manager_user.erl
index 256ea6a834..55b1e23b2e 100644
--- a/lib/snmp/test/snmp_manager_user.erl
+++ b/lib/snmp/test/snmp_manager_user.erl
@@ -31,7 +31,7 @@
%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
diff --git a/lib/snmp/test/snmp_manager_user_old.erl b/lib/snmp/test/snmp_manager_user_old.erl
index 0f0f026eca..f317fa831c 100644
--- a/lib/snmp/test/snmp_manager_user_old.erl
+++ b/lib/snmp/test/snmp_manager_user_old.erl
@@ -30,7 +30,7 @@
%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
diff --git a/lib/snmp/test/snmp_manager_user_test.erl b/lib/snmp/test/snmp_manager_user_test.erl
index a0cdcdef4d..64edfef4d5 100644
--- a/lib/snmp/test/snmp_manager_user_test.erl
+++ b/lib/snmp/test/snmp_manager_user_test.erl
@@ -27,7 +27,7 @@
%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
diff --git a/lib/snmp/test/snmp_manager_user_test_lib.erl b/lib/snmp/test/snmp_manager_user_test_lib.erl
index a547f78efb..ea2c83a0da 100644
--- a/lib/snmp/test/snmp_manager_user_test_lib.erl
+++ b/lib/snmp/test/snmp_manager_user_test_lib.erl
@@ -30,7 +30,7 @@
%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("snmp_test_lib.hrl").
diff --git a/lib/ssh/src/ssh_bits.erl b/lib/ssh/src/ssh_bits.erl
index 4da3a6018b..101bf76cd3 100644
--- a/lib/ssh/src/ssh_bits.erl
+++ b/lib/ssh/src/ssh_bits.erl
@@ -26,52 +26,30 @@
-include("ssh.hrl").
--export([encode/2]).
--export([mpint/1, string/1, name_list/1]).
+-export([mpint/1, name_list/1]).
-export([random/1]).
--define(name_list(X),
- (fun(B) -> ?binary(B) end)(list_to_binary(name_concat(X)))).
-
-
-name_concat([Name]) when is_atom(Name) -> atom_to_list(Name);
-name_concat([Name]) when is_list(Name) -> Name;
-name_concat([Name|Ns]) ->
- if is_atom(Name) ->
- [atom_to_list(Name),"," | name_concat(Ns)];
- is_list(Name) ->
- [Name,"," | name_concat(Ns)]
- end;
-name_concat([]) -> [].
-
-
-name_list(Ns) ->
- ?name_list(Ns).
+%%%----------------------------------------------------------------
+name_list([Name]) -> to_bin(Name);
+name_list([Name|Ns]) -> <<(to_bin(Name))/binary, ",", (name_list(Ns))/binary>>;
+name_list([]) -> <<>>.
+
+to_bin(A) when is_atom(A) -> list_to_binary(atom_to_list(A));
+to_bin(S) when is_list(S) -> list_to_binary(S);
+to_bin(B) when is_binary(B) -> B.
+
+%%%----------------------------------------------------------------
+%%% Multi Precision Integer encoding
+mpint(-1) -> <<0,0,0,1,16#ff>>;
+mpint(0) -> <<0,0,0,0>>;
+mpint(X) when X < 0 -> mpint_neg(X,0,[]);
+mpint(X) -> mpint_pos(X,0,[]).
-
-string(Str) ->
- ?string(Str).
-
-
-%% MP representaion (SSH2)
-mpint(X) when X < 0 ->
- if X == -1 ->
- <<0,0,0,1,16#ff>>;
- true ->
- mpint_neg(X,0,[])
- end;
-mpint(X) ->
- if X == 0 ->
- <<0,0,0,0>>;
- true ->
- mpint_pos(X,0,[])
- end.
-
mpint_neg(-1,I,Ds=[MSB|_]) ->
if MSB band 16#80 =/= 16#80 ->
<<?UINT32((I+1)), (list_to_binary([255|Ds]))/binary>>;
true ->
- (<<?UINT32(I), (list_to_binary(Ds))/binary>>)
+ <<?UINT32(I), (list_to_binary(Ds))/binary>>
end;
mpint_neg(X,I,Ds) ->
mpint_neg(X bsr 8,I+1,[(X band 255)|Ds]).
@@ -80,96 +58,17 @@ mpint_pos(0,I,Ds=[MSB|_]) ->
if MSB band 16#80 == 16#80 ->
<<?UINT32((I+1)), (list_to_binary([0|Ds]))/binary>>;
true ->
- (<<?UINT32(I), (list_to_binary(Ds))/binary>>)
+ <<?UINT32(I), (list_to_binary(Ds))/binary>>
end;
mpint_pos(X,I,Ds) ->
mpint_pos(X bsr 8,I+1,[(X band 255)|Ds]).
-encode(List, Types) ->
- list_to_binary(enc(List, Types)).
-
-%%
-%% Encode record element
-%%
-enc(Xs, Ts) ->
- enc(Xs, Ts, 0).
-
-enc(Xs, [boolean|Ts], Offset) ->
- X = hd(Xs),
- [?boolean(X) | enc(tl(Xs), Ts, Offset+1)];
-enc(Xs, [byte|Ts], Offset) ->
- X = hd(Xs),
- [?byte(X) | enc(tl(Xs), Ts,Offset+1)];
-enc(Xs, [uint16|Ts], Offset) ->
- X = hd(Xs),
- [?uint16(X) | enc(tl(Xs), Ts,Offset+2)];
-enc(Xs, [uint32 |Ts], Offset) ->
- X = hd(Xs),
- [?uint32(X) | enc(tl(Xs), Ts,Offset+4)];
-enc(Xs, [uint64|Ts], Offset) ->
- X = hd(Xs),
- [?uint64(X) | enc(tl(Xs), Ts,Offset+8)];
-enc(Xs, [mpint|Ts], Offset) ->
- Y = mpint(hd(Xs)),
- [Y | enc(tl(Xs), Ts,Offset+size(Y))];
-enc(Xs, [string|Ts], Offset) ->
- X0 = hd(Xs),
- Y = ?string(X0),
- [Y | enc(tl(Xs),Ts,Offset+size(Y))];
-enc(Xs, [string_utf8|Ts], Offset) ->
- X0 = hd(Xs),
- Y = ?string_utf8(X0),
- [Y | enc(tl(Xs),Ts,Offset+size(Y))];
-enc(Xs, [binary|Ts], Offset) ->
- X0 = hd(Xs),
- Y = ?binary(X0),
- [Y | enc(tl(Xs), Ts,Offset+size(Y))];
-enc(Xs, [name_list|Ts], Offset) ->
- X0 = hd(Xs),
- Y = ?name_list(X0),
- [Y | enc(tl(Xs), Ts, Offset+size(Y))];
-enc(Xs, [cookie|Ts], Offset) ->
- [random(16) | enc(tl(Xs), Ts, Offset+16)];
-enc(Xs, [{pad,N}|Ts], Offset) ->
- K = (N - (Offset rem N)) rem N,
- [fill_bits(K,0) | enc(Xs, Ts, Offset+K)];
-enc(Xs, ['...'| []], _Offset) ->
- X = hd(Xs),
- if is_binary(X) ->
- [X];
- is_list(X) ->
- [list_to_binary(X)];
- X==undefined ->
- []
- end;
-enc([], [],_) ->
- [].
-
-
-%%
-%% Create a binary with constant bytes
-%%
-fill_bits(N,C) ->
- list_to_binary(fill(N,C)).
-
-fill(0,_C) -> [];
-fill(1,C) -> [C];
-fill(N,C) ->
- Cs = fill(N div 2, C),
- Cs1 = [Cs,Cs],
- if N band 1 == 0 ->
- Cs1;
- true ->
- [C,Cs,Cs]
- end.
-
-
+%%%----------------------------------------------------------------
%% random/1
%% Generate N random bytes
%%
-random(N) ->
- crypto:strong_rand_bytes(N).
+random(N) -> crypto:strong_rand_bytes(N).
diff --git a/lib/ssh/src/ssh_connect.hrl b/lib/ssh/src/ssh_connect.hrl
index 9f9f3de8fa..0c9ddad641 100644
--- a/lib/ssh/src/ssh_connect.hrl
+++ b/lib/ssh/src/ssh_connect.hrl
@@ -24,8 +24,9 @@
-type channel_id() :: integer().
--define(DEFAULT_PACKET_SIZE, 32768).
--define(DEFAULT_WINDOW_SIZE, 2*?DEFAULT_PACKET_SIZE).
+-define(DEFAULT_PACKET_SIZE, 65536).
+-define(DEFAULT_WINDOW_SIZE, 10*?DEFAULT_PACKET_SIZE).
+
-define(DEFAULT_TIMEOUT, 5000).
-define(MAX_PROTO_VERSION, 255).
diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl
index b6c4496be2..a0e9a4961c 100644
--- a/lib/ssh/src/ssh_message.erl
+++ b/lib/ssh/src/ssh_message.erl
@@ -32,16 +32,44 @@
-export([encode/1, decode/1, decode_keyboard_interactive_prompts/2]).
+-define('2bin'(X), (if is_binary(X) -> X;
+ is_list(X) -> list_to_binary(X);
+ X==undefined -> <<>>
+ end) ).
+
+-define('E...'(X), ?'2bin'(X)/binary ).
+-define(Eboolean(X), ?BOOLEAN(case X of
+ true -> ?TRUE;
+ false -> ?FALSE
+ end) ).
+-define(Ebyte(X), ?BYTE(X) ).
+-define(Euint32(X), ?UINT32(X) ).
+-define(Estring(X), ?STRING(?'2bin'(X)) ).
+-define(Estring_utf8(X), ?string_utf8(X)/binary ).
+-define(Ename_list(X), ?STRING(ssh_bits:name_list(X)) ).
+-define(Empint(X), (ssh_bits:mpint(X))/binary ).
+-define(Ebinary(X), ?STRING(X) ).
+
+%% encode(Msg) ->
+%% try encode1(Msg)
+%% catch
+%% C:E ->
+%% io:format('***********************~n~p:~p ~p~n',[C,E,Msg]),
+%% error(E)
+%% end.
+
encode(#ssh_msg_global_request{
name = Name,
want_reply = Bool,
data = Data}) ->
- ssh_bits:encode([?SSH_MSG_GLOBAL_REQUEST,
- Name, Bool, Data], [byte, string, boolean, '...']);
+ <<?Ebyte(?SSH_MSG_GLOBAL_REQUEST), ?Estring(Name), ?Eboolean(Bool), ?'E...'(Data)>>;
+
encode(#ssh_msg_request_success{data = Data}) ->
- <<?BYTE(?SSH_MSG_REQUEST_SUCCESS), Data/binary>>;
+ <<?Ebyte(?SSH_MSG_REQUEST_SUCCESS), Data/binary>>;
+
encode(#ssh_msg_request_failure{}) ->
- <<?BYTE(?SSH_MSG_REQUEST_FAILURE)>>;
+ <<?Ebyte(?SSH_MSG_REQUEST_FAILURE)>>;
+
encode(#ssh_msg_channel_open{
channel_type = Type,
sender_channel = Sender,
@@ -49,9 +77,8 @@ encode(#ssh_msg_channel_open{
maximum_packet_size = Max,
data = Data
}) ->
- ssh_bits:encode([?SSH_MSG_CHANNEL_OPEN,
- Type, Sender, Window, Max, Data], [byte, string, uint32,
- uint32, uint32, '...']);
+ <<?Ebyte(?SSH_MSG_CHANNEL_OPEN), ?Estring(Type), ?Euint32(Sender), ?Euint32(Window), ?Euint32(Max), ?'E...'(Data)>>;
+
encode(#ssh_msg_channel_open_confirmation{
recipient_channel = Recipient,
sender_channel = Sender,
@@ -59,60 +86,63 @@ encode(#ssh_msg_channel_open_confirmation{
maximum_packet_size = MaxPacketSize,
data = Data
}) ->
- ssh_bits:encode([?SSH_MSG_CHANNEL_OPEN_CONFIRMATION, Recipient,
- Sender, InitWindowSize, MaxPacketSize, Data],
- [byte, uint32, uint32, uint32, uint32, '...']);
+ <<?Ebyte(?SSH_MSG_CHANNEL_OPEN_CONFIRMATION),
+ ?Euint32(Recipient), ?Euint32(Sender), ?Euint32(InitWindowSize), ?Euint32(MaxPacketSize),
+ ?'E...'(Data)>>;
+
encode(#ssh_msg_channel_open_failure{
recipient_channel = Recipient,
reason = Reason,
description = Desc,
lang = Lang
}) ->
- ssh_bits:encode([?SSH_MSG_CHANNEL_OPEN_FAILURE, Recipient,
- Reason, Desc, Lang], [byte, uint32, uint32, string, string]);
+ <<?Ebyte(?SSH_MSG_CHANNEL_OPEN_FAILURE), ?Euint32(Recipient),?Euint32(Reason), ?Estring(Desc), ?Estring(Lang)>>;
+
encode(#ssh_msg_channel_window_adjust{
recipient_channel = Recipient,
bytes_to_add = Bytes
}) ->
- ssh_bits:encode([?SSH_MSG_CHANNEL_WINDOW_ADJUST, Recipient, Bytes],
- [byte, uint32, uint32]);
+ <<?Ebyte(?SSH_MSG_CHANNEL_WINDOW_ADJUST), ?Euint32(Recipient), ?Euint32(Bytes)>>;
+
encode(#ssh_msg_channel_data{
recipient_channel = Recipient,
data = Data
}) ->
- ssh_bits:encode([?SSH_MSG_CHANNEL_DATA, Recipient, Data], [byte, uint32, binary]);
+ <<?Ebyte(?SSH_MSG_CHANNEL_DATA), ?Euint32(Recipient), ?Ebinary(Data)>>;
encode(#ssh_msg_channel_extended_data{
recipient_channel = Recipient,
data_type_code = DataType,
data = Data
}) ->
- ssh_bits:encode([?SSH_MSG_CHANNEL_EXTENDED_DATA, Recipient,
- DataType, Data], [byte, uint32, uint32, binary]);
+ <<?Ebyte(?SSH_MSG_CHANNEL_EXTENDED_DATA), ?Euint32(Recipient), ?Euint32(DataType), ?Ebinary(Data)>>;
encode(#ssh_msg_channel_eof{recipient_channel = Recipient
}) ->
- <<?BYTE(?SSH_MSG_CHANNEL_EOF), ?UINT32(Recipient)>>;
+ <<?Ebyte(?SSH_MSG_CHANNEL_EOF), ?Euint32(Recipient)>>;
+
encode(#ssh_msg_channel_close{
recipient_channel = Recipient
}) ->
- <<?BYTE(?SSH_MSG_CHANNEL_CLOSE), ?UINT32(Recipient)>>;
+ <<?Ebyte(?SSH_MSG_CHANNEL_CLOSE), ?Euint32(Recipient)>>;
+
encode(#ssh_msg_channel_request{
recipient_channel = Recipient,
request_type = Type,
want_reply = Bool,
data = Data
}) ->
- ssh_bits:encode([?SSH_MSG_CHANNEL_REQUEST, Recipient, Type, Bool, Data],
- [byte, uint32, string, boolean, '...']);
+ <<?Ebyte(?SSH_MSG_CHANNEL_REQUEST), ?Euint32(Recipient), ?Estring(Type), ?Eboolean(Bool), ?'E...'(Data)>>;
+
encode(#ssh_msg_channel_success{
recipient_channel = Recipient
}) ->
- <<?BYTE(?SSH_MSG_CHANNEL_SUCCESS), ?UINT32(Recipient)>>;
+ <<?Ebyte(?SSH_MSG_CHANNEL_SUCCESS), ?Euint32(Recipient)>>;
+
encode(#ssh_msg_channel_failure{
recipient_channel = Recipient
}) ->
- <<?BYTE(?SSH_MSG_CHANNEL_FAILURE), ?UINT32(Recipient)>>;
+ <<?Ebyte(?SSH_MSG_CHANNEL_FAILURE), ?Euint32(Recipient)>>;
encode(#ssh_msg_userauth_request{
user = User,
@@ -120,36 +150,33 @@ encode(#ssh_msg_userauth_request{
method = Method,
data = Data
}) ->
- ssh_bits:encode([?SSH_MSG_USERAUTH_REQUEST, User, Service, Method, Data],
- [byte, string_utf8, string, string, '...']);
+ <<?Ebyte(?SSH_MSG_USERAUTH_REQUEST), ?Estring_utf8(User), ?Estring(Service), ?Estring(Method), ?'E...'(Data)>>;
+
encode(#ssh_msg_userauth_failure{
authentications = Auths,
partial_success = Bool
}) ->
- ssh_bits:encode([?SSH_MSG_USERAUTH_FAILURE, Auths, Bool],
- [byte, string, boolean]);
+ <<?Ebyte(?SSH_MSG_USERAUTH_FAILURE), ?Estring(Auths), ?Eboolean(Bool)>>;
+
encode(#ssh_msg_userauth_success{}) ->
- <<?BYTE(?SSH_MSG_USERAUTH_SUCCESS)>>;
+ <<?Ebyte(?SSH_MSG_USERAUTH_SUCCESS)>>;
encode(#ssh_msg_userauth_banner{
message = Banner,
language = Lang
}) ->
- ssh_bits:encode([?SSH_MSG_USERAUTH_BANNER, Banner, Lang],
- [byte, string_utf8, string]);
+ <<?Ebyte(?SSH_MSG_USERAUTH_BANNER), ?Estring_utf8(Banner), ?Estring(Lang)>>;
encode(#ssh_msg_userauth_pk_ok{
algorithm_name = Alg,
key_blob = KeyBlob
}) ->
- ssh_bits:encode([?SSH_MSG_USERAUTH_PK_OK, Alg, KeyBlob],
- [byte, string, binary]);
+ <<?Ebyte(?SSH_MSG_USERAUTH_PK_OK), ?Estring(Alg), ?Ebinary(KeyBlob)>>;
encode(#ssh_msg_userauth_passwd_changereq{prompt = Prompt,
languge = Lang
})->
- ssh_bits:encode([?SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, Prompt, Lang],
- [byte, string, string]);
+ <<?Ebyte(?SSH_MSG_USERAUTH_PASSWD_CHANGEREQ), ?Estring(Prompt), ?Estring(Lang)>>;
encode(#ssh_msg_userauth_info_request{
name = Name,
@@ -157,41 +184,37 @@ encode(#ssh_msg_userauth_info_request{
language_tag = Lang,
num_prompts = NumPromtps,
data = Data}) ->
- ssh_bits:encode([?SSH_MSG_USERAUTH_INFO_REQUEST, Name, Inst, Lang, NumPromtps, Data],
- [byte, string, string, string, uint32, '...']);
+ <<?Ebyte(?SSH_MSG_USERAUTH_INFO_REQUEST), ?Estring(Name), ?Estring(Inst), ?Estring(Lang),
+ ?Euint32(NumPromtps), ?'E...'(Data)>>;
encode(#ssh_msg_userauth_info_response{
num_responses = Num,
data = Data}) ->
- Responses = lists:map(fun("") ->
- <<>>;
- (Response) ->
- ssh_bits:encode([Response], [string])
- end, Data),
- Start = ssh_bits:encode([?SSH_MSG_USERAUTH_INFO_RESPONSE, Num],
- [byte, uint32]),
- iolist_to_binary([Start, Responses]);
+ lists:foldl(fun %%("", Acc) -> Acc; % commented out since it seem wrong
+ (Response, Acc) -> <<Acc/binary, ?Estring(Response)>>
+ end,
+ <<?Ebyte(?SSH_MSG_USERAUTH_INFO_RESPONSE), ?Euint32(Num)>>,
+ Data);
encode(#ssh_msg_disconnect{
code = Code,
description = Desc,
language = Lang
}) ->
- ssh_bits:encode([?SSH_MSG_DISCONNECT, Code, Desc, Lang],
- [byte, uint32, string, string]);
+ <<?Ebyte(?SSH_MSG_DISCONNECT), ?Euint32(Code), ?Estring(Desc), ?Estring(Lang)>>;
encode(#ssh_msg_service_request{
name = Service
}) ->
- ssh_bits:encode([?SSH_MSG_SERVICE_REQUEST, Service], [byte, string]);
+ <<?Ebyte(?SSH_MSG_SERVICE_REQUEST), ?Estring(Service)>>;
encode(#ssh_msg_service_accept{
name = Service
}) ->
- ssh_bits:encode([?SSH_MSG_SERVICE_ACCEPT, Service], [byte, string]);
+ <<?Ebyte(?SSH_MSG_SERVICE_ACCEPT), ?Estring(Service)>>;
encode(#ssh_msg_newkeys{}) ->
- <<?BYTE(?SSH_MSG_NEWKEYS)>>;
+ <<?Ebyte(?SSH_MSG_NEWKEYS)>>;
encode(#ssh_msg_kexinit{
cookie = Cookie,
@@ -208,19 +231,13 @@ encode(#ssh_msg_kexinit{
first_kex_packet_follows = Bool,
reserved = Reserved
}) ->
- ssh_bits:encode([?SSH_MSG_KEXINIT, Cookie, KeyAlgs, HostKeyAlgs, EncAlgC2S, EncAlgS2C,
- MacAlgC2S, MacAlgS2C, CompAlgS2C, CompAlgC2S, LangC2S, LangS2C, Bool,
- Reserved],
- [byte, cookie,
- name_list, name_list,
- name_list, name_list,
- name_list, name_list,
- name_list, name_list,
- name_list, name_list,
- boolean, uint32]);
+ <<?Ebyte(?SSH_MSG_KEXINIT), Cookie/binary,
+ ?Ename_list(KeyAlgs), ?Ename_list(HostKeyAlgs), ?Ename_list(EncAlgC2S), ?Ename_list(EncAlgS2C), ?Ename_list(MacAlgC2S),
+ ?Ename_list(MacAlgS2C), ?Ename_list(CompAlgS2C), ?Ename_list(CompAlgC2S), ?Ename_list(LangC2S), ?Ename_list(LangS2C),
+ ?Eboolean(Bool), ?Euint32(Reserved)>>;
encode(#ssh_msg_kexdh_init{e = E}) ->
- ssh_bits:encode([?SSH_MSG_KEXDH_INIT, E], [byte, mpint]);
+ <<?Ebyte(?SSH_MSG_KEXDH_INIT), ?Empint(E)>>;
encode(#ssh_msg_kexdh_reply{
public_host_key = Key,
@@ -229,25 +246,23 @@ encode(#ssh_msg_kexdh_reply{
}) ->
EncKey = public_key:ssh_encode(Key, ssh2_pubkey),
EncSign = encode_signature(Key, Signature),
- ssh_bits:encode([?SSH_MSG_KEXDH_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]);
+ <<?Ebyte(?SSH_MSG_KEXDH_REPLY), ?Ebinary(EncKey), ?Empint(F), ?Ebinary(EncSign)>>;
encode(#ssh_msg_kex_dh_gex_request{
min = Min,
n = N,
max = Max
}) ->
- ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REQUEST, Min, N, Max],
- [byte, uint32, uint32, uint32]);
+ <<?Ebyte(?SSH_MSG_KEX_DH_GEX_REQUEST), ?Euint32(Min), ?Euint32(N), ?Euint32(Max)>>;
+
encode(#ssh_msg_kex_dh_gex_request_old{n = N}) ->
- ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REQUEST_OLD, N],
- [byte, uint32]);
+ <<?Ebyte(?SSH_MSG_KEX_DH_GEX_REQUEST_OLD), ?Euint32(N)>>;
encode(#ssh_msg_kex_dh_gex_group{p = Prime, g = Generator}) ->
- ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_GROUP, Prime, Generator],
- [byte, mpint, mpint]);
+ <<?Ebyte(?SSH_MSG_KEX_DH_GEX_GROUP), ?Empint(Prime), ?Empint(Generator)>>;
encode(#ssh_msg_kex_dh_gex_init{e = Public}) ->
- ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_INIT, Public], [byte, mpint]);
+ <<?Ebyte(?SSH_MSG_KEX_DH_GEX_INIT), ?Empint(Public)>>;
encode(#ssh_msg_kex_dh_gex_reply{
%% Will be private key encode_host_key extracts only the public part!
@@ -257,26 +272,26 @@ encode(#ssh_msg_kex_dh_gex_reply{
}) ->
EncKey = public_key:ssh_encode(Key, ssh2_pubkey),
EncSign = encode_signature(Key, Signature),
- ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]);
+ <<?Ebyte(?SSH_MSG_KEX_DH_GEX_REPLY), ?Ebinary(EncKey), ?Empint(F), ?Ebinary(EncSign)>>;
encode(#ssh_msg_kex_ecdh_init{q_c = Q_c}) ->
- ssh_bits:encode([?SSH_MSG_KEX_ECDH_INIT, Q_c], [byte, mpint]);
+ <<?Ebyte(?SSH_MSG_KEX_ECDH_INIT), ?Empint(Q_c)>>;
encode(#ssh_msg_kex_ecdh_reply{public_host_key = Key, q_s = Q_s, h_sig = Sign}) ->
EncKey = public_key:ssh_encode(Key, ssh2_pubkey),
EncSign = encode_signature(Key, Sign),
- ssh_bits:encode([?SSH_MSG_KEX_ECDH_REPLY, EncKey, Q_s, EncSign], [byte, binary, mpint, binary]);
+ <<?Ebyte(?SSH_MSG_KEX_ECDH_REPLY), ?Ebinary(EncKey), ?Empint(Q_s), ?Ebinary(EncSign)>>;
encode(#ssh_msg_ignore{data = Data}) ->
- ssh_bits:encode([?SSH_MSG_IGNORE, Data], [byte, string]);
+ <<?Ebyte(?SSH_MSG_IGNORE), ?Estring(Data)>>;
encode(#ssh_msg_unimplemented{sequence = Seq}) ->
- ssh_bits:encode([?SSH_MSG_UNIMPLEMENTED, Seq], [byte, uint32]);
+ <<?Ebyte(?SSH_MSG_UNIMPLEMENTED), ?Euint32(Seq)>>;
encode(#ssh_msg_debug{always_display = Bool,
message = Msg,
language = Lang}) ->
- ssh_bits:encode([?SSH_MSG_DEBUG, Bool, Msg, Lang], [byte, boolean, string, string]).
+ <<?Ebyte(?SSH_MSG_DEBUG), ?Eboolean(Bool), ?Estring(Msg), ?Estring(Lang)>>.
%% Connection Messages
@@ -553,10 +568,10 @@ decode_signature(<<?DEC_BIN(_Alg,__0), ?UINT32(_), Signature/binary>>) ->
encode_signature(#'RSAPublicKey'{}, Signature) ->
- ssh_bits:encode(["ssh-rsa", Signature],[string, binary]);
+ <<?Ebinary(<<"ssh-rsa">>), ?Ebinary(Signature)>>;
encode_signature({_, #'Dss-Parms'{}}, Signature) ->
- ssh_bits:encode(["ssh-dss", Signature],[string, binary]);
+ <<?Ebinary(<<"ssh-dss">>), ?Ebinary(Signature)>>;
encode_signature({#'ECPoint'{}, {namedCurve,OID}}, Signature) ->
CurveName = public_key:oid2ssh_curvename(OID),
- ssh_bits:encode([<<"ecdsa-sha2-",CurveName/binary>>, Signature], [binary,binary]).
+ <<?Ebinary(<<"ecdsa-sha2-",CurveName/binary>>), ?Ebinary(Signature)>>.
diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl
index dbacf730cc..eb99406626 100644
--- a/lib/ssh/src/ssh_sftp.erl
+++ b/lib/ssh/src/ssh_sftp.erl
@@ -99,8 +99,8 @@ start_channel(Host) when is_list(Host) ->
start_channel(Host, []).
start_channel(Cm, Opts) when is_pid(Cm) ->
Timeout = proplists:get_value(timeout, Opts, infinity),
- {_, SftpOpts} = handle_options(Opts, [], []),
- case ssh_xfer:attach(Cm, []) of
+ {_, ChanOpts, SftpOpts} = handle_options(Opts, [], [], []),
+ case ssh_xfer:attach(Cm, [], ChanOpts) of
{ok, ChannelId, Cm} ->
case ssh_channel:start(Cm, ChannelId,
?MODULE, [Cm, ChannelId, SftpOpts]) of
@@ -123,9 +123,9 @@ start_channel(Cm, Opts) when is_pid(Cm) ->
start_channel(Host, Opts) ->
start_channel(Host, 22, Opts).
start_channel(Host, Port, Opts) ->
- {SshOpts, SftpOpts} = handle_options(Opts, [], []),
+ {SshOpts, ChanOpts, SftpOpts} = handle_options(Opts, [], [], []),
Timeout = proplists:get_value(timeout, SftpOpts, infinity),
- case ssh_xfer:connect(Host, Port, SshOpts, Timeout) of
+ case ssh_xfer:connect(Host, Port, SshOpts, ChanOpts, Timeout) of
{ok, ChannelId, Cm} ->
case ssh_channel:start(Cm, ChannelId, ?MODULE, [Cm,
ChannelId, SftpOpts]) of
@@ -842,14 +842,18 @@ terminate(_Reason, State) ->
%%====================================================================
%% Internal functions
%%====================================================================
-handle_options([], Sftp, Ssh) ->
- {Ssh, Sftp};
-handle_options([{timeout, _} = Opt | Rest], Sftp, Ssh) ->
- handle_options(Rest, [Opt | Sftp], Ssh);
-handle_options([{sftp_vsn, _} = Opt| Rest], Sftp, Ssh) ->
- handle_options(Rest, [Opt | Sftp], Ssh);
-handle_options([Opt | Rest], Sftp, Ssh) ->
- handle_options(Rest, Sftp, [Opt | Ssh]).
+handle_options([], Sftp, Chan, Ssh) ->
+ {Ssh, Chan, Sftp};
+handle_options([{timeout, _} = Opt | Rest], Sftp, Chan, Ssh) ->
+ handle_options(Rest, [Opt|Sftp], Chan, Ssh);
+handle_options([{sftp_vsn, _} = Opt| Rest], Sftp, Chan, Ssh) ->
+ handle_options(Rest, [Opt|Sftp], Chan, Ssh);
+handle_options([{window_size, _} = Opt| Rest], Sftp, Chan, Ssh) ->
+ handle_options(Rest, Sftp, [Opt|Chan], Ssh);
+handle_options([{packet_size, _} = Opt| Rest], Sftp, Chan, Ssh) ->
+ handle_options(Rest, Sftp, [Opt|Chan], Ssh);
+handle_options([Opt|Rest], Sftp, Chan, Ssh) ->
+ handle_options(Rest, Sftp, Chan, [Opt|Ssh]).
call(Pid, Msg, TimeOut) ->
ssh_channel:call(Pid, {{timeout, TimeOut}, Msg}, infinity).
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index 18037b8461..a648c7af3d 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -52,6 +52,14 @@
-export([pack/3]).
-export([decompress/2, decrypt_blocks/3, is_valid_mac/3 ]). % FIXME: remove
+-define(Estring(X), ?STRING((if is_binary(X) -> X;
+ is_list(X) -> list_to_binary(X);
+ X==undefined -> <<>>
+ end))).
+-define(Empint(X), (ssh_bits:mpint(X))/binary ).
+-define(Ebinary(X), ?STRING(X) ).
+-define(Euint32(X), ?UINT32(X) ).
+
%%%----------------------------------------------------------------------------
%%%
%%% There is a difference between supported and default algorithms. The
@@ -1084,7 +1092,7 @@ sign(SigData, Hash, #'DSAPrivateKey'{} = Key) ->
sign(SigData, Hash, Key = #'ECPrivateKey'{}) ->
DerEncodedSign = public_key:sign(SigData, Hash, Key),
#'ECDSA-Sig-Value'{r=R, s=S} = public_key:der_decode('ECDSA-Sig-Value', DerEncodedSign),
- ssh_bits:encode([R,S], [mpint,mpint]);
+ <<?Empint(R),?Empint(S)>>;
sign(SigData, Hash, Key) ->
public_key:sign(SigData, Hash, Key).
@@ -1584,21 +1592,16 @@ hash(K, H, Ki, N, HASH) ->
kex_h(SSH, Key, E, F, K) ->
KeyBin = public_key:ssh_encode(Key, ssh2_pubkey),
- L = ssh_bits:encode([SSH#ssh.c_version, SSH#ssh.s_version,
- SSH#ssh.c_keyinit, SSH#ssh.s_keyinit,
- KeyBin, E,F,K],
- [string,string,binary,binary,binary,
- mpint,mpint,mpint]),
+ L = <<?Estring(SSH#ssh.c_version), ?Estring(SSH#ssh.s_version),
+ ?Ebinary(SSH#ssh.c_keyinit), ?Ebinary(SSH#ssh.s_keyinit), ?Ebinary(KeyBin),
+ ?Empint(E), ?Empint(F), ?Empint(K)>>,
crypto:hash(sha((SSH#ssh.algorithms)#alg.kex), L).
-%% crypto:hash(sha,L).
kex_h(SSH, Curve, Key, Q_c, Q_s, K) ->
KeyBin = public_key:ssh_encode(Key, ssh2_pubkey),
- L = ssh_bits:encode([SSH#ssh.c_version, SSH#ssh.s_version,
- SSH#ssh.c_keyinit, SSH#ssh.s_keyinit,
- KeyBin, Q_c, Q_s, K],
- [string,string,binary,binary,binary,
- mpint,mpint,mpint]),
+ L = <<?Estring(SSH#ssh.c_version), ?Estring(SSH#ssh.s_version),
+ ?Ebinary(SSH#ssh.c_keyinit), ?Ebinary(SSH#ssh.s_keyinit), ?Ebinary(KeyBin),
+ ?Empint(Q_c), ?Empint(Q_s), ?Empint(K)>>,
crypto:hash(sha(Curve), L).
kex_h(SSH, Key, Min, NBits, Max, Prime, Gen, E, F, K) ->
@@ -1607,21 +1610,14 @@ kex_h(SSH, Key, Min, NBits, Max, Prime, Gen, E, F, K) ->
%% flag from 'ssh_msg_kex_dh_gex_request_old'
%% It was like this before that message was supported,
%% why?
- Ts = [string,string,binary,binary,binary,
- uint32,
- mpint,mpint,mpint,mpint,mpint],
- ssh_bits:encode([SSH#ssh.c_version,SSH#ssh.s_version,
- SSH#ssh.c_keyinit,SSH#ssh.s_keyinit,
- KeyBin, NBits, Prime, Gen, E,F,K],
- Ts);
+ <<?Estring(SSH#ssh.c_version), ?Estring(SSH#ssh.s_version),
+ ?Ebinary(SSH#ssh.c_keyinit), ?Ebinary(SSH#ssh.s_keyinit), ?Ebinary(KeyBin),
+ ?Empint(E), ?Empint(F), ?Empint(K)>>;
true ->
- Ts = [string,string,binary,binary,binary,
- uint32,uint32,uint32,
- mpint,mpint,mpint,mpint,mpint],
- ssh_bits:encode([SSH#ssh.c_version,SSH#ssh.s_version,
- SSH#ssh.c_keyinit,SSH#ssh.s_keyinit,
- KeyBin, Min, NBits, Max,
- Prime, Gen, E,F,K], Ts)
+ <<?Estring(SSH#ssh.c_version), ?Estring(SSH#ssh.s_version),
+ ?Ebinary(SSH#ssh.c_keyinit), ?Ebinary(SSH#ssh.s_keyinit), ?Ebinary(KeyBin),
+ ?Euint32(Min), ?Euint32(NBits), ?Euint32(Max),
+ ?Empint(Prime), ?Empint(Gen), ?Empint(E), ?Empint(F), ?Empint(K)>>
end,
crypto:hash(sha((SSH#ssh.algorithms)#alg.kex), L).
diff --git a/lib/ssh/src/ssh_xfer.erl b/lib/ssh/src/ssh_xfer.erl
index b8dff1c533..259dc71aa5 100644
--- a/lib/ssh/src/ssh_xfer.erl
+++ b/lib/ssh/src/ssh_xfer.erl
@@ -24,7 +24,7 @@
-module(ssh_xfer).
--export([attach/2, connect/3, connect/4]).
+-export([attach/2, attach/3, connect/3, connect/4, connect/5]).
-export([open/6, opendir/3, readdir/3, close/3, read/5, write/5,
rename/5, remove/3, mkdir/4, rmdir/3, realpath/3, extended/4,
stat/4, fstat/4, lstat/4, setstat/4,
@@ -47,28 +47,38 @@
-define(is_set(F, Bits),
((F) band (Bits)) == (F)).
--define(XFER_PACKET_SIZE, 32768).
--define(XFER_WINDOW_SIZE, 4*?XFER_PACKET_SIZE).
+-define(XFER_PACKET_SIZE, 65536).
+-define(XFER_WINDOW_SIZE, 20*?XFER_PACKET_SIZE).
attach(CM, Opts) ->
- open_xfer(CM, Opts).
+ open_xfer(CM, Opts, []).
+
+attach(CM, Opts, ChanOpts) ->
+ open_xfer(CM, Opts, ChanOpts).
+
connect(Host, Port, Opts) ->
case ssh:connect(Host, Port, Opts) of
- {ok, CM} -> open_xfer(CM, Opts);
+ {ok, CM} -> open_xfer(CM, Opts, []);
Error -> Error
end.
connect(Host, Port, Opts, Timeout) ->
+ connect(Host, Port, Opts, [], Timeout).
+
+connect(Host, Port, Opts, ChanOpts, Timeout) ->
case ssh:connect(Host, Port, Opts, Timeout) of
- {ok, CM} -> open_xfer(CM, [{timeout, Timeout}|Opts]);
+ {ok, CM} -> open_xfer(CM, [{timeout, Timeout}|Opts], ChanOpts);
{error, Timeout} -> {error, timeout};
Error -> Error
end.
-open_xfer(CM, Opts) ->
+
+open_xfer(CM, Opts, ChanOpts) ->
TMO = proplists:get_value(timeout, Opts, infinity),
- case ssh_connection:session_channel(CM, ?XFER_WINDOW_SIZE, ?XFER_PACKET_SIZE, TMO) of
+ WindowSize = proplists:get_value(window_size, ChanOpts, ?XFER_WINDOW_SIZE),
+ PacketSize = proplists:get_value(packet_size, ChanOpts, ?XFER_PACKET_SIZE),
+ case ssh_connection:session_channel(CM, WindowSize, PacketSize, TMO) of
{ok, ChannelId} ->
{ok, ChannelId, CM};
Error ->
diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile
index 9cd98f069f..fb539f98fa 100644
--- a/lib/ssh/test/Makefile
+++ b/lib/ssh/test/Makefile
@@ -64,8 +64,7 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
DATA_DIRS = $(MODULES:%=%_data)
-INCLUDES = -I$(ERL_TOP)/lib/test_server/include \
- -I$(ERL_TOP)/lib/ssh/src \
+INCLUDES = -I$(ERL_TOP)/lib/ssh/src
EMAKEFILE=Emakefile
MAKE_EMAKE = $(wildcard $(ERL_TOP)/make/make_emakefile)
@@ -88,8 +87,7 @@ RELSYSDIR = $(RELEASE_PATH)/ssh_test
# The path to the test_server ebin dir is needed when
# running the target "targets".
# ----------------------------------------------------
-ERL_COMPILE_FLAGS += -pa ../../../internal_tools/test_server/ebin \
- $(INCLUDES)
+ERL_COMPILE_FLAGS += $(INCLUDES)
EBIN = .
diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl
index 44da0f4d6f..dbba48c726 100644
--- a/lib/ssh/test/ssh_protocol_SUITE.erl
+++ b/lib/ssh/test/ssh_protocol_SUITE.erl
@@ -308,7 +308,7 @@ no_common_alg_client_disconnects(Config) ->
{send, hello},
{match, #ssh_msg_kexinit{_='_'}, receive_msg},
{send, #ssh_msg_kexinit{ % with unsupported "SOME-UNSUPPORTED"
- cookie = 247381486335508958743193106082599558706,
+ cookie = <<80,158,95,51,174,35,73,130,246,141,200,49,180,190,82,234>>,
kex_algorithms = ["diffie-hellman-group1-sha1"],
server_host_key_algorithms = ["SOME-UNSUPPORTED"], % SIC!
encryption_algorithms_client_to_server = ["aes128-ctr"],
diff --git a/lib/ssl/doc/src/ssl_app.xml b/lib/ssl/doc/src/ssl_app.xml
index 6c82e32a74..d05ece3971 100644
--- a/lib/ssl/doc/src/ssl_app.xml
+++ b/lib/ssl/doc/src/ssl_app.xml
@@ -43,6 +43,8 @@
<item>For security reasons SSL-2.0 is not supported.</item>
<item>For security reasons SSL-3.0 is no longer supported by default,
but can be configured.</item>
+ <item>For security reasons DES cipher suites are no longer supported by default,
+ but can be configured.</item>
<item>Ephemeral Diffie-Hellman cipher suites are supported,
but not Diffie Hellman Certificates cipher suites.</item>
<item>Elliptic Curve cipher suites are supported if the Crypto
@@ -55,8 +57,8 @@
motivated to implement them.</item>
<item>CRL validation is supported.</item>
<item>Policy certificate extensions are not supported.</item>
- <item>'Server Name Indication' extension client side
- (RFC 6066, Section 3) is supported.</item>
+ <item>'Server Name Indication' extension
+ (<url href="http://www.ietf.org/rfc/rfc6066.txt">RFC 6066</url>) is supported.</item>
</list>
</description>
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index 974a6ec6b5..d737f74aa3 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -38,7 +38,7 @@
cipher_init/3, decipher/6, cipher/5, decipher_aead/6, cipher_aead/6,
suite/1, suites/1, all_suites/1,
ec_keyed_suites/0, anonymous_suites/1, psk_suites/1, srp_suites/0,
- rc4_suites/1, openssl_suite/1, openssl_suite_name/1, filter/2, filter_suites/1,
+ rc4_suites/1, des_suites/1, openssl_suite/1, openssl_suite_name/1, filter/2, filter_suites/1,
hash_algorithm/1, sign_algorithm/1, is_acceptable_hash/2, is_fallback/1]).
-export_type([cipher_suite/0,
@@ -315,7 +315,8 @@ all_suites(Version) ->
++ anonymous_suites(Version)
++ psk_suites(Version)
++ srp_suites()
- ++ rc4_suites(Version).
+ ++ rc4_suites(Version)
+ ++ des_suites(Version).
%%--------------------------------------------------------------------
-spec anonymous_suites(ssl_record:ssl_version() | integer()) -> [cipher_suite()].
%%
@@ -419,6 +420,16 @@ rc4_suites({3, N}) when N =< 3 ->
?TLS_RSA_WITH_RC4_128_MD5,
?TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
?TLS_ECDH_RSA_WITH_RC4_128_SHA].
+%%--------------------------------------------------------------------
+-spec des_suites(Version::ssl_record:ssl_version()) -> [cipher_suite()].
+%%
+%% Description: Returns a list of the cipher suites
+%% with DES cipher, only supported if explicitly set by user.
+%% Are not considered secure any more.
+%%--------------------------------------------------------------------
+des_suites(_)->
+ [?TLS_DHE_RSA_WITH_DES_CBC_SHA,
+ ?TLS_RSA_WITH_DES_CBC_SHA].
%%--------------------------------------------------------------------
-spec suite_definition(cipher_suite()) -> erl_cipher_suite().
@@ -1728,7 +1739,8 @@ dhe_rsa_suites() ->
?TLS_DHE_RSA_WITH_DES_CBC_SHA,
?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
- ?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256].
+ ?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+ ].
psk_rsa_suites() ->
[?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl
index 9a58f2b8f7..bb41ef2b62 100644
--- a/lib/ssl/src/ssl_connection.hrl
+++ b/lib/ssl/src/ssl_connection.hrl
@@ -48,27 +48,28 @@
socket_options :: #socket_options{},
connection_states :: #connection_states{} | secret_printout(),
protocol_buffers :: term() | secret_printout() , %% #protocol_buffers{} from tls_record.hrl or dtls_recor.hrl
- tls_handshake_history :: ssl_handshake:ssl_handshake_history() | secret_printout(),
- cert_db :: reference(),
+ tls_handshake_history :: ssl_handshake:ssl_handshake_history() | secret_printout()
+ | 'undefined',
+ cert_db :: reference() | 'undefined',
session :: #session{} | secret_printout(),
session_cache :: db_handle(),
session_cache_cb :: atom(),
crl_db :: term(),
- negotiated_version :: ssl_record:ssl_version(),
+ negotiated_version :: ssl_record:ssl_version() | 'undefined',
client_certificate_requested = false :: boolean(),
key_algorithm :: ssl_cipher:key_algo(),
hashsign_algorithm = {undefined, undefined},
cert_hashsign_algorithm,
- public_key_info :: ssl_handshake:public_key_info(),
- private_key :: public_key:private_key() | secret_printout(),
+ public_key_info :: ssl_handshake:public_key_info() | 'undefined',
+ private_key :: public_key:private_key() | secret_printout() | 'undefined',
diffie_hellman_params:: #'DHParameter'{} | undefined | secret_printout(),
diffie_hellman_keys :: {PublicKey :: binary(), PrivateKey :: binary()} | #'ECPrivateKey'{} | undefined | secret_printout(),
- psk_identity :: binary(), % server psk identity hint
- srp_params :: #srp_user{} | secret_printout(),
- srp_keys ::{PublicKey :: binary(), PrivateKey :: binary()} | secret_printout(),
- premaster_secret :: binary() | secret_printout() ,
+ psk_identity :: binary() | 'undefined', % server psk identity hint
+ srp_params :: #srp_user{} | secret_printout() | 'undefined',
+ srp_keys ::{PublicKey :: binary(), PrivateKey :: binary()} | secret_printout() | 'undefined',
+ premaster_secret :: binary() | secret_printout() | 'undefined',
file_ref_db :: db_handle(),
- cert_db_ref :: certdb_ref(),
+ cert_db_ref :: certdb_ref() | 'undefined',
bytes_to_read :: undefined | integer(), %% bytes to read in passive mode
user_data_buffer :: undefined | binary() | secret_printout(),
renegotiation :: undefined | {boolean(), From::term() | internal | peer},
@@ -81,7 +82,7 @@
expecting_finished = false ::boolean(),
negotiated_protocol = undefined :: undefined | binary(),
client_ecc, % {Curves, PointFmt}
- tracker :: pid(), %% Tracker process for listen socket
+ tracker :: pid() | 'undefined', %% Tracker process for listen socket
sni_hostname = undefined
}).
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index 8c7ed9c0d1..913746598f 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -93,16 +93,16 @@
validate_extensions_fun,
depth :: integer(),
certfile :: binary(),
- cert :: public_key:der_encoded() | secret_printout(),
+ cert :: public_key:der_encoded() | secret_printout() | 'undefined',
keyfile :: binary(),
- key :: {'RSAPrivateKey' | 'DSAPrivateKey' | 'ECPrivateKey' | 'PrivateKeyInfo', public_key:der_encoded()} | secret_printout(),
- password :: string() | secret_printout(),
- cacerts :: [public_key:der_encoded()] | secret_printout(),
+ key :: {'RSAPrivateKey' | 'DSAPrivateKey' | 'ECPrivateKey' | 'PrivateKeyInfo', public_key:der_encoded()} | secret_printout() | 'undefined',
+ password :: string() | secret_printout() | 'undefined',
+ cacerts :: [public_key:der_encoded()] | secret_printout() | 'undefined',
cacertfile :: binary(),
dh :: public_key:der_encoded() | secret_printout(),
- dhfile :: binary() | secret_printout(),
+ dhfile :: binary() | secret_printout() | 'undefined',
user_lookup_fun, % server option, fun to lookup the user
- psk_identity :: binary() | secret_printout() ,
+ psk_identity :: binary() | secret_printout() | 'undefined',
srp_identity, % client option {User, Password}
ciphers, %
%% Local policy for the server if it want's to reuse the session
@@ -118,7 +118,7 @@
%% undefined if not hibernating, or number of ms of
%% inactivity after which ssl_connection will go into
%% hibernation
- hibernate_after :: boolean(),
+ hibernate_after :: boolean() | 'undefined',
%% This option should only be set to true by inet_tls_dist
erl_dist = false :: boolean(),
alpn_advertised_protocols = undefined :: [binary()] | undefined ,
diff --git a/lib/ssl/src/ssl_v3.erl b/lib/ssl/src/ssl_v3.erl
index f169059a75..f98ea83771 100644
--- a/lib/ssl/src/ssl_v3.erl
+++ b/lib/ssl/src/ssl_v3.erl
@@ -143,9 +143,7 @@ suites() ->
?TLS_RSA_WITH_3DES_EDE_CBC_SHA,
?TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
?TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
- ?TLS_RSA_WITH_AES_128_CBC_SHA,
- ?TLS_DHE_RSA_WITH_DES_CBC_SHA,
- ?TLS_RSA_WITH_DES_CBC_SHA
+ ?TLS_RSA_WITH_AES_128_CBC_SHA
].
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl
index 71e5f349dd..09e378cfeb 100644
--- a/lib/ssl/src/tls_v1.erl
+++ b/lib/ssl/src/tls_v1.erl
@@ -208,9 +208,7 @@ suites(Minor) when Minor == 1; Minor == 2 ->
?TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
- ?TLS_RSA_WITH_AES_128_CBC_SHA,
- ?TLS_DHE_RSA_WITH_DES_CBC_SHA,
- ?TLS_RSA_WITH_DES_CBC_SHA
+ ?TLS_RSA_WITH_AES_128_CBC_SHA
];
suites(3) ->
[
diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile
index 999df320a3..89a62c3a4b 100644
--- a/lib/ssl/test/Makefile
+++ b/lib/ssl/test/Makefile
@@ -81,7 +81,7 @@ HRL_FILES_NEEDED_IN_TEST = \
TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-INCLUDES = -I. -I$(ERL_TOP)/lib/test_server/include/
+INCLUDES = -I.
DATADIRS = ssl_basic_SUITE_data
@@ -100,8 +100,7 @@ RELSYSDIR = $(RELEASE_PATH)/ssl_test
# The path to the test_server ebin dir is needed when
# running the target "targets".
# ----------------------------------------------------
-ERL_COMPILE_FLAGS += -pa ../../../internal_tools/test_server/ebin \
- $(INCLUDES)
+ERL_COMPILE_FLAGS += $(INCLUDES)
# ----------------------------------------------------
# Targets
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 1a864edb8b..847a9f19de 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -183,6 +183,8 @@ cipher_tests() ->
rc4_rsa_cipher_suites,
rc4_ecdh_rsa_cipher_suites,
rc4_ecdsa_cipher_suites,
+ des_rsa_cipher_suites,
+ des_ecdh_rsa_cipher_suites,
default_reject_anonymous].
cipher_tests_ec() ->
@@ -445,7 +447,7 @@ connection_info(Config) when is_list(Config) ->
{from, self()},
{mfa, {?MODULE, connection_info_result, []}},
{options,
- [{ciphers,[{rsa,des_cbc,sha,no_export}]} |
+ [{ciphers,[{rsa, aes_128_cbc, sha}]} |
ClientOpts]}]),
ct:log("Testcase ~p, Client ~p Server ~p ~n",
@@ -454,7 +456,7 @@ connection_info(Config) when is_list(Config) ->
Version =
tls_record:protocol_version(tls_record:highest_protocol_version([])),
- ServerMsg = ClientMsg = {ok, {Version, {rsa, des_cbc, sha}}},
+ ServerMsg = ClientMsg = {ok, {Version, {rsa, aes_128_cbc, sha}}},
ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
@@ -1982,6 +1984,23 @@ rc4_ecdsa_cipher_suites(Config) when is_list(Config) ->
Ciphers = ssl_test_lib:rc4_suites(NVersion),
run_suites(Ciphers, Version, Config, rc4_ecdsa).
+%%-------------------------------------------------------------------
+des_rsa_cipher_suites()->
+ [{doc, "Test the RC4 ciphersuites"}].
+des_rsa_cipher_suites(Config) when is_list(Config) ->
+ NVersion = tls_record:highest_protocol_version([]),
+ Version = tls_record:protocol_version(NVersion),
+ Ciphers = ssl_test_lib:des_suites(NVersion),
+ run_suites(Ciphers, Version, Config, des_rsa).
+%-------------------------------------------------------------------
+des_ecdh_rsa_cipher_suites()->
+ [{doc, "Test the RC4 ciphersuites"}].
+des_ecdh_rsa_cipher_suites(Config) when is_list(Config) ->
+ NVersion = tls_record:highest_protocol_version([]),
+ Version = tls_record:protocol_version(NVersion),
+ Ciphers = ssl_test_lib:des_suites(NVersion),
+ run_suites(Ciphers, Version, Config, des_dhe_rsa).
+
%%--------------------------------------------------------------------
default_reject_anonymous()->
[{doc,"Test that by default anonymous cipher suites are rejected "}].
@@ -2718,7 +2737,12 @@ defaults(Config) when is_list(Config)->
true = lists:member(sslv3, Available),
false = lists:member(sslv3, Supported),
false = lists:member({rsa,rc4_128,sha}, ssl:cipher_suites()),
- true = lists:member({rsa,rc4_128,sha}, ssl:cipher_suites(all)).
+ true = lists:member({rsa,rc4_128,sha}, ssl:cipher_suites(all)),
+ false = lists:member({rsa,des_cbc,sha}, ssl:cipher_suites()),
+ true = lists:member({rsa,des_cbc,sha}, ssl:cipher_suites(all)),
+ false = lists:member({dhe_rsa,des_cbc,sha}, ssl:cipher_suites()),
+ true = lists:member({dhe_rsa,des_cbc,sha}, ssl:cipher_suites(all)).
+
%%--------------------------------------------------------------------
reuseaddr() ->
[{doc,"Test reuseaddr option"}].
@@ -4006,7 +4030,15 @@ run_suites(Ciphers, Version, Config, Type) ->
rc4_ecdsa ->
{?config(client_opts, Config),
[{ciphers, Ciphers} |
- ?config(server_ecdsa_opts, Config)]}
+ ?config(server_ecdsa_opts, Config)]};
+ des_dhe_rsa ->
+ {?config(client_opts, Config),
+ [{ciphers, Ciphers} |
+ ?config(server_rsa_opts, Config)]};
+ des_rsa ->
+ {?config(client_opts, Config),
+ [{ciphers, Ciphers} |
+ ?config(server_opts, Config)]}
end,
Result = lists:map(fun(Cipher) ->
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index 90fcd193cc..b0495cb5ac 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -981,6 +981,10 @@ rc4_suites(Version) ->
Suites = ssl_cipher:rc4_suites(Version),
ssl_cipher:filter_suites(Suites).
+des_suites(Version) ->
+ Suites = ssl_cipher:des_suites(Version),
+ ssl_cipher:filter_suites(Suites).
+
pem_to_der(File) ->
{ok, PemBin} = file:read_file(File),
public_key:pem_decode(PemBin).
diff --git a/lib/ssl/test/ssl_upgrade_SUITE.erl b/lib/ssl/test/ssl_upgrade_SUITE.erl
index d65bdf6983..f5f4b25b23 100644
--- a/lib/ssl/test/ssl_upgrade_SUITE.erl
+++ b/lib/ssl/test/ssl_upgrade_SUITE.erl
@@ -40,20 +40,19 @@ all() ->
init_per_suite(Config0) ->
catch crypto:stop(),
- try {crypto:start(), erlang:system_info({wordsize, internal}) == erlang:system_info({wordsize, external})} of
- {ok, true} ->
- case ct_release_test:init(Config0) of
- {skip, Reason} ->
- {skip, Reason};
- Config ->
- {ok, _} = make_certs:all(?config(data_dir, Config),
- ?config(priv_dir, Config)),
- ssl_test_lib:cert_options(Config)
- end;
- {ok, false} ->
- {skip, "Test server will not handle halfwordemulator correctly. Skip as halfwordemulator is deprecated"}
+ try crypto:start() of
+ ok ->
+ case ct_release_test:init(Config0) of
+ {skip, Reason} ->
+ {skip, Reason};
+ Config ->
+ Result =
+ {ok, _} = make_certs:all(?config(data_dir, Config),
+ ?config(priv_dir, Config)),
+ ssl_test_lib:cert_options(Config)
+ end
catch _:_ ->
- {skip, "Crypto did not start"}
+ {skip, "Crypto did not start"}
end.
end_per_suite(Config) ->
diff --git a/lib/stdlib/doc/src/erl_parse.xml b/lib/stdlib/doc/src/erl_parse.xml
index 0938b5dec3..13be488c33 100644
--- a/lib/stdlib/doc/src/erl_parse.xml
+++ b/lib/stdlib/doc/src/erl_parse.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2015</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -44,21 +44,33 @@
</description>
<datatypes>
<datatype>
- <name name="abstract_clause"></name>
- <desc><p>Parse tree for Erlang clause.</p>
+ <name>abstract_clause()</name>
+ <desc><p><marker id="type-abstract_clause"/>
+ Abstract form of an Erlang clause.</p>
</desc>
</datatype>
<datatype>
- <name name="abstract_expr"></name>
- <desc><p>Parse tree for Erlang expression.</p>
+ <name>abstract_expr()</name>
+ <desc><p><marker id="type-abstract_expr"/>
+ Abstract form of an Erlang expression.</p>
</desc>
</datatype>
<datatype>
- <name name="abstract_form"></name>
- <desc><p>Parse tree for Erlang form.</p>
+ <name>abstract_form()</name>
+ <desc><p><marker id="type-abstract_form"/>
+ Abstract form of an Erlang form.</p>
</desc>
</datatype>
<datatype>
+ <name>abstract_type()</name>
+ <desc><p><marker id="type-abstract_type"/>
+ Abstract form of an Erlang type.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="erl_parse_tree"></name>
+ </datatype>
+ <datatype>
<name name="error_description"></name>
</datatype>
<datatype>
@@ -180,7 +192,7 @@
<p>Converts the Erlang data structure <c><anno>Data</anno></c> into an
abstract form of type <c><anno>AbsTerm</anno></c>.</p>
<p>The <c><anno>Line</anno></c> option is the line that will
- be assigned to each node of the abstract form.</p>
+ be assigned to each node of <c><anno>AbsTerm</anno></c>.</p>
<p>The <c><anno>Encoding</anno></c> option is used for
selecting which integer lists will be considered
as strings. The default is to use the encoding returned by
@@ -196,47 +208,53 @@
<func>
<name name="map_anno" arity="2"/>
<fsummary>
- Map a function over the annotations of an abstract form
+ Map a function over the annotations of a <c>erl_parse</c> tree
</fsummary>
<desc>
- <p>Modifies the abstract form <anno>Abstr</anno> by applying
- <anno>Fun</anno> on every collection of annotations of the
- abstract form. The abstract form is traversed in a
- depth-first, left-to-right, fashion.
+ <p>Modifies the <c>erl_parse</c> tree <c><anno>Abstr</anno></c>
+ by applying <c><anno>Fun</anno></c> on each collection of
+ annotations of the nodes of the <c>erl_parse</c> tree. The
+ <c>erl_parse</c> tree is traversed in a depth-first,
+ left-to-right, fashion.
</p>
</desc>
</func>
<func>
<name name="fold_anno" arity="3"/>
<fsummary>
- Fold a function over the annotations of an abstract form
+ Fold a function over the annotations of a <c>erl_parse</c> tree
</fsummary>
<desc>
- <p>Updates an accumulator by applying <anno>Fun</anno> on
- every collection of annotations of the abstract form
- <anno>Abstr</anno>. The first call to <anno>Fun</anno> has
- <anno>AccIn</anno> as argument, and the returned accumulator
- <anno>AccOut</anno> is passed to the next call, and so on.
- The final value of the accumulator is returned. The abstract
- form is traversed in a depth-first, left-to-right, fashion.
+ <p>Updates an accumulator by applying <c><anno>Fun</anno></c> on
+ each collection of annotations of the <c>erl_parse</c> tree
+ <c><anno>Abstr</anno></c>. The first call to
+ <c><anno>Fun</anno></c> has <c><anno>AccIn</anno></c> as
+ argument, and the returned accumulator
+ <c><anno>AccOut</anno></c> is passed to the next call, and
+ so on. The final value of the accumulator is returned. The
+ <c>erl_parse</c> tree is traversed in a depth-first, left-to-right,
+ fashion.
</p>
</desc>
</func>
<func>
<name name="mapfold_anno" arity="3"/>
<fsummary>
- Map and fold a function over the annotations of an abstract form
+ Map and fold a function over the annotations of a
+ <c>erl_parse</c> tree
</fsummary>
<desc>
- <p>Modifies the abstract form <anno>Abstr</anno> by applying
- <anno>Fun</anno> on every collection of annotations of the
- abstract form, while at the same time updating an
- accumulator. The first call to <anno>Fun</anno> has
- <anno>AccIn</anno> as second argument, and the returned
- accumulator <anno>AccOut</anno> is passed to the next call,
- and so on. The modified abstract form as well as the the
- final value of the accumulator is returned. The abstract
- form is traversed in a depth-first, left-to-right, fashion.
+ <p>Modifies the <c>erl_parse</c> tree <c><anno>Abstr</anno></c>
+ by applying <c><anno>Fun</anno></c> on each collection of
+ annotations of the nodes of the <c>erl_parse</c> tree, while
+ at the same time updating an accumulator. The first call to
+ <c><anno>Fun</anno></c> has <c><anno>AccIn</anno></c> as
+ second argument, and the returned accumulator
+ <c><anno>AccOut</anno></c> is passed to the next call, and
+ so on. The modified <c>erl_parse</c> tree as well as the the
+ final value of the accumulator are returned. The
+ <c>erl_parse</c> tree is traversed in a depth-first,
+ left-to-right, fashion.
</p>
</desc>
</func>
@@ -246,12 +264,15 @@
Create new annotations
</fsummary>
<desc>
- <p>Creates an abstract form from a term which has the same
- structure as an abstract form, but <seealso
- marker="erl_anno#type-location">locations</seealso> where the
- abstract form has annotations. For each location, <seealso
- marker="erl_anno#new/1"><c>erl_anno:new/1</c></seealso> is
- called, and the annotations replace the location.
+ <p>Assumes that <c><anno>Term</anno></c> is a term with the same
+ structure as a <c>erl_parse</c> tree, but with <seealso
+ marker="erl_anno#type-location">locations</seealso> where a
+ <c>erl_parse</c> tree has collections of annotations.
+ Returns a <c>erl_parse</c> tree where each location <c>L</c>
+ has been replaced by the value returned by <seealso
+ marker="erl_anno#new/1"><c>erl_anno:new(L)</c></seealso>.
+ The term <c><anno>Term</anno></c> is traversed in a
+ depth-first, left-to-right, fashion.
</p>
</desc>
</func>
@@ -261,12 +282,14 @@
Return annotations as terms
</fsummary>
<desc>
- <p>Assumes that <anno>Term</anno> is a term with the same
- structure as an abstract form, but with terms, T say, on
- those places where an abstract form has annotations. Returns
- an abstract form where every term T has been replaced by the
- value returned by calling <c>erl_anno:from_term(T)</c>. The
- term <anno>Term</anno> is traversed in a depth-first,
+ <p>Assumes that <c><anno>Term</anno></c> is a term with the same
+ structure as a <c>erl_parse</c> tree, but with terms,
+ <c>T</c> say, where a <c>erl_parse</c> tree has collections
+ of annotations. Returns a <c>erl_parse</c> tree where each
+ term <c>T</c> has been replaced by the value returned by
+ <seealso marker="erl_anno#from_term/1">
+ <c>erl_anno:from_term(T)</c></seealso>. The term
+ <c><anno>Term</anno></c> is traversed in a depth-first,
left-to-right, fashion.
</p>
</desc>
@@ -277,10 +300,13 @@
Return the representation of annotations
</fsummary>
<desc>
- <p>Returns a term where every collection of annotations Anno of
- <anno>Abstr</anno> has been replaced by the term returned by
- calling <c>erl_anno:to_term(Anno)</c>. The abstract form is
- traversed in a depth-first, left-to-right, fashion.
+ <p>Returns a term where each collection of annotations
+ <c>Anno</c> of the nodes of the <c>erl_parse</c> tree
+ <c><anno>Abstr</anno></c> has been replaced by the term
+ returned by <seealso marker="erl_anno#to_term/1">
+ <c>erl_anno:to_term(Anno)</c></seealso>. The
+ <c>erl_parse</c> tree is traversed in a depth-first,
+ left-to-right, fashion.
</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/erl_scan.xml b/lib/stdlib/doc/src/erl_scan.xml
index 342f491dd0..ee0d6b6033 100644
--- a/lib/stdlib/doc/src/erl_scan.xml
+++ b/lib/stdlib/doc/src/erl_scan.xml
@@ -40,39 +40,15 @@
</description>
<datatypes>
<datatype>
- <name name="attribute_info"></name>
- </datatype>
- <datatype>
- <name name="attributes"></name>
- </datatype>
- <datatype>
- <name name="attributes_data"></name>
- </datatype>
- <datatype>
<name name="category"></name>
</datatype>
<datatype>
- <name name="column"></name>
- </datatype>
- <datatype>
<name name="error_description"></name>
</datatype>
<datatype>
<name name="error_info"></name>
</datatype>
<datatype>
- <name name="info_line"></name>
- </datatype>
- <datatype>
- <name name="info_location"></name>
- </datatype>
- <datatype>
- <name name="line"></name>
- </datatype>
- <datatype>
- <name name="location"></name>
- </datatype>
- <datatype>
<name name="option"></name>
</datatype>
<datatype>
@@ -88,9 +64,6 @@
<name name="token"></name>
</datatype>
<datatype>
- <name name="token_info"></name>
- </datatype>
- <datatype>
<name name="tokens"></name>
</datatype>
<datatype>
@@ -122,25 +95,23 @@
<anno>StartLocation</anno>, [])</c>.</p>
<p><c><anno>StartLocation</anno></c> indicates the initial location
when scanning starts. If <c><anno>StartLocation</anno></c> is a line,
- <c>attributes()</c> as well as <c><anno>EndLocation</anno></c> and
+ <c>Anno</c> as well as <c><anno>EndLocation</anno></c> and
<c><anno>ErrorLocation</anno></c> will be lines. If
<c><anno>StartLocation</anno></c> is a pair of a line and a column
- <c>attributes()</c> takes the form of an opaque compound
+ <c>Anno</c> takes the form of an opaque compound
data type, and <c><anno>EndLocation</anno></c> and
<c><anno>ErrorLocation</anno></c>
will be pairs of a line and a column. The <em>token
- attributes</em> contain information about the column and the
+ annotations</em> contain information about the column and the
line where the token begins, as well as the text of the
token (if the <c>text</c> option is given), all of which can
- be accessed by calling <seealso
- marker="#token_info/1">token_info/1,2</seealso>, <seealso
- marker="#attributes_info/1">attributes_info/1,2</seealso>,
+ be accessed by calling
<seealso marker="#column/1">column/1</seealso>,
<seealso marker="#line/1">line/1</seealso>,
<seealso marker="#location/1">location/1</seealso>, and
<seealso marker="#text/1">text/1</seealso>.</p>
<p>A <em>token</em> is a tuple containing information about
- syntactic category, the token attributes, and the actual
+ syntactic category, the token annotations, and the actual
terminal symbol. For punctuation characters (e.g. <c>;</c>,
<c>|</c>) and reserved words, the category and the symbol
coincide, and the token is represented by a two-tuple.
@@ -172,7 +143,7 @@
<item><p>Short for <c>[return_comments, return_white_spaces]</c>.</p>
</item>
<tag><c>text</c></tag>
- <item><p>Include the token's text in the token attributes. The
+ <item><p>Include the token's text in the token annotation. The
text is the part of the input corresponding to the token.</p>
</item>
</taglist>
@@ -306,150 +277,6 @@
</desc>
</func>
<func>
- <name name="token_info" arity="1"/>
- <fsummary>Return information about a token</fsummary>
- <desc>
- <p>Returns a list containing information about the token
- <c><anno>Token</anno></c>. The order of the
- <c><anno>TokenInfoTuple</anno></c>s is not
- defined. See <seealso
- marker="#token_info/2">token_info/2</seealso> for
- information about specific
- <c><anno>TokenInfoTuple</anno></c>s.</p>
- <p>Note that if <c>token_info(Token, TokenItem)</c> returns
- <c>undefined</c> for some <c>TokenItem</c>, the
- item is not included in <c><anno>TokenInfo</anno></c>.</p>
- </desc>
- </func>
- <func>
- <name name="token_info" arity="2" clause_i="1"/>
- <name name="token_info" arity="2" clause_i="2"/>
- <fsummary>Return information about a token</fsummary>
- <type name="token_item"/>
- <type name="attribute_item"/>
- <desc>
- <p>Returns a list containing information about the token
- <c><anno>Token</anno></c>. If one single
- <c><anno>TokenItem</anno></c> is given the returned value is
- the corresponding
- <c>TokenInfoTuple</c>, or <c>undefined</c> if the
- <c>TokenItem</c> has no value. If a list of
- <c><anno>TokenItem</anno></c>s is given the result is a list of
- <c><anno>TokenInfoTuple</anno></c>. The
- <c><anno>TokenInfoTuple</anno></c>s will
- appear with the corresponding <c><anno>TokenItem</anno></c>s in
- the same order as the <c><anno>TokenItem</anno></c>s
- appear in the list of <c>TokenItem</c>s.
- <c><anno>TokenItem</anno></c>s with no value are not included
- in the list of <c><anno>TokenInfoTuple</anno></c>.</p>
- <p>The following <c><anno>TokenInfoTuple</anno></c>s with corresponding
- <c><anno>TokenItem</anno></c>s are valid:</p>
- <taglist>
- <tag><c>{category, </c><seealso marker="#type-category">
- category()</seealso><c>}</c></tag>
- <item><p>The category of the token.</p>
- </item>
- <tag><c>{column, </c><seealso marker="#type-column">
- column()</seealso><c>}</c></tag>
- <item><p>The column where the token begins.</p>
- </item>
- <tag><c>{length, integer() > 0}</c></tag>
- <item><p>The length of the token's text.</p>
- </item>
- <tag><c>{line, </c><seealso marker="#type-line">
- line()</seealso><c>}</c></tag>
- <item><p>The line where the token begins.</p>
- </item>
- <tag><c>{location, </c><seealso marker="#type-location">
- location()</seealso><c>}</c></tag>
- <item><p>The line and column where the token begins, or
- just the line if the column unknown.</p>
- </item>
- <tag><c>{symbol, </c><seealso marker="#type-symbol">
- symbol()</seealso><c>}</c></tag>
- <item><p>The token's symbol.</p>
- </item>
- <tag><c>{text, string()}</c></tag>
- <item><p>The token's text.</p>
- </item>
- </taglist>
- </desc>
- </func>
- <func>
- <name name="attributes_info" arity="1"/>
- <fsummary>Return information about token attributes</fsummary>
- <desc>
- <p>Returns a list containing information about the token
- attributes <c><anno>Attributes</anno></c>. The order of the
- <c><anno>AttributeInfoTuple</anno></c>s is not defined.
- See <seealso
- marker="#attributes_info/2">attributes_info/2</seealso> for
- information about specific
- <c><anno>AttributeInfoTuple</anno></c>s.</p>
- <p>Note that if <c>attributes_info(Token, AttributeItem)</c>
- returns <c>undefined</c> for some <c>AttributeItem</c> in
- the list above, the item is not included in
- <c><anno>AttributesInfo</anno></c>.</p>
- </desc>
- </func>
- <func>
- <name name="attributes_info" arity="2" clause_i="1"/>
- <name name="attributes_info" arity="2" clause_i="2"/>
- <fsummary>Return information about a token attributes</fsummary>
- <type name="attribute_item"/>
- <desc>
- <p>Returns a list containing information about the token
- attributes <c><anno>Attributes</anno></c>. If one single
- <c><anno>AttributeItem</anno></c> is given the returned value is the
- corresponding <c><anno>AttributeInfoTuple</anno></c>,
- or <c>undefined</c> if the <c><anno>AttributeItem</anno></c>
- has no value. If a list of <c><anno>AttributeItem</anno></c>
- is given the result is a list of
- <c><anno>AttributeInfoTuple</anno></c>.
- The <c><anno>AttributeInfoTuple</anno></c>s
- will appear with the corresponding <c><anno>AttributeItem</anno></c>s
- in the same order as the <c><anno>AttributeItem</anno></c>s
- appear in the list of <c><anno>AttributeItem</anno></c>s.
- <c><anno>AttributeItem</anno></c>s with no
- value are not included in the list of
- <c><anno>AttributeInfoTuple</anno></c>.</p>
- <p>The following <c><anno>AttributeInfoTuple</anno></c>s with
- corresponding <c><anno>AttributeItem</anno></c>s are valid:</p>
- <taglist>
- <tag><c>{column, </c><seealso marker="#type-column">
- column()</seealso><c>}</c></tag>
- <item><p>The column where the token begins.</p>
- </item>
- <tag><c>{length, integer() > 0}</c></tag>
- <item><p>The length of the token's text.</p>
- </item>
- <tag><c>{line, </c><seealso marker="#type-line">
- line()</seealso><c>}</c></tag>
- <item><p>The line where the token begins.</p>
- </item>
- <tag><c>{location, </c><seealso marker="#type-location">
- location()</seealso><c>}</c></tag>
- <item><p>The line and column where the token begins, or
- just the line if the column unknown.</p>
- </item>
- <tag><c>{text, string()}</c></tag>
- <item><p>The token's text.</p>
- </item>
- </taglist>
- </desc>
- </func>
- <func>
- <name name="set_attribute" arity="3"/>
- <fsummary>Set a token attribute value</fsummary>
- <desc>
- <p>Sets the value of the <c>line</c> attribute of the token
- attributes <c><anno>Attributes</anno></c>.</p>
- <p>The <c><anno>SetAttributeFun</anno></c> is called with the value of
- the <c>line</c> attribute, and is to return the new value of
- the <c>line</c> attribute.</p>
- </desc>
- </func>
- <func>
<name name="format_error" arity="1"/>
<fsummary>Format an error descriptor</fsummary>
<desc>
diff --git a/lib/stdlib/doc/src/filename.xml b/lib/stdlib/doc/src/filename.xml
index 1d4ffc10f9..ce6aba3657 100644
--- a/lib/stdlib/doc/src/filename.xml
+++ b/lib/stdlib/doc/src/filename.xml
@@ -47,7 +47,12 @@
<p>The module supports raw file names in the way that if a binary is present, or the file name cannot be interpreted according to the return value of
<seealso marker="kernel:file#native_name_encoding/0">file:native_name_encoding/0</seealso>, a raw file name will also be returned. For example filename:join/1 provided with a path component being a binary (and also not being possible to interpret under the current native file name encoding) will result in a raw file name being returned (the join operation will have been performed of course). For more information about raw file names, see the <seealso marker="kernel:file">file</seealso> module.</p>
</description>
-
+ <datatypes>
+ <datatype>
+ <name name="basedir_type"/>
+ </datatype>
+ </datatypes>
+
<funcs>
<func>
<name name="absname" arity="1"/>
@@ -102,6 +107,155 @@
</desc>
</func>
<func>
+ <name name="basedir" arity="2"/>
+ <fsummary>Equivalent to <c>basedir(<anno>Type</anno>,<anno>Application</anno>,#{})</c>.</fsummary>
+ <desc>
+ <p>
+ Equivalent to <seealso marker="#basedir-3">
+ basedir(<anno>Type</anno>, <anno>Application</anno>, #{})</seealso>.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="basedir" arity="3"/>
+ <fsummary></fsummary>
+ <desc><marker id="basedir-3"/>
+ <p>
+ Returns a suitable path, or paths, for a given type.
+ If <c>os</c> is not set in <c><anno>Opts</anno></c> the function will default to
+ the native option, i.e. <c>'linux'</c>, <c>'darwin'</c> or <c>'windows'</c>, as understood
+ by <c>os:type/0</c>. Anything not recognized as <c>'darwin'</c> or <c>'windows'</c> is
+ interpreted as <c>'linux'</c>.</p>
+ <p>
+ The options <c>'author'</c> and <c>'version'</c> are only used with <c>'windows'</c> option mode.
+ </p>
+ <list type="bulleted">
+ <item><c>user_cache</c>
+ <p>The path location is intended for transient data files on a local machine.</p>
+ <p>
+ On Linux:
+ Respects the os environment variable <c>XDG_CACHE_HOME</c>.
+ </p>
+ <pre>
+1> <input>filename:basedir(user_cache, "my_application", #{os=>linux}).</input>
+"/home/otptest/.cache/my_application"</pre>
+ On Darwin: <pre>
+1> <input>filename:basedir(user_cache, "my_application", #{os=>darwin}).</input>
+"/home/otptest/Library/Caches/my_application"</pre>
+ On Windows: <pre>
+1> <input>filename:basedir(user_cache, "My App").</input>
+"c:/Users/otptest/AppData/Local/My App/Cache"
+2> <input>filename:basedir(user_cache, "My App").</input>
+"c:/Users/otptest/AppData/Local/My App/Cache"
+3> <input>filename:basedir(user_cache, "My App", #{author=>"Erlang"}).</input>
+"c:/Users/otptest/AppData/Local/Erlang/My App/Cache"
+4> <input>filename:basedir(user_cache, "My App", #{version=>"1.2"}).</input>
+"c:/Users/otptest/AppData/Local/My App/1.2/Cache"
+5> <input>filename:basedir(user_cache, "My App", #{author=>"Erlang",version=>"1.2"}).</input>
+"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Cache"</pre>
+ </item>
+ <item><c>user_config</c>
+ <p>
+ The path location is intended for persistent configuration files.
+ </p>
+ <p>
+ On Linux:
+ Respects the os environment variable <c>XDG_CONFIG_HOME</c>.
+ </p>
+ <pre>
+2> <input>filename:basedir(user_config, "my_application", #{os=>linux}).</input>
+"/home/otptest/.config/my_application"</pre>
+ On Darwin:<pre>
+2> <input>filename:basedir(user_config, "my_application", #{os=>darwin}).</input>
+"/home/otptest/Library/Application Support/my_application"</pre>
+ On Windows:<pre>
+1> <input>filename:basedir(user_config, "My App").</input>
+"c:/Users/otptest/AppData/Roaming/My App"
+2> <input>filename:basedir(user_config, "My App", #{author=>"Erlang", version=>"1.2"}).</input>
+"c:/Users/otptest/AppData/Roaming/Erlang/My App/1.2"</pre>
+ </item>
+ <item><c>user_data</c>
+ <p>
+ The path location is intended for persistent data files.
+ </p>
+ <p>
+ On Linux:
+ Respects the os environment variable <c>XDG_DATA_HOME</c>.
+ </p>
+ <pre>
+3> <input>filename:basedir(user_data, "my_application", #{os=>linux}).</input>
+"/home/otptest/.local/my_application"</pre>
+ On Darwin:<pre>
+3> <input>filename:basedir(user_data, "my_application", #{os=>darwin}).</input>
+"/home/otptest/Library/Application Support/my_application"</pre>
+ On Windows:<pre>
+8> <input>filename:basedir(user_data, "My App").</input>
+"c:/Users/otptest/AppData/Local/My App"
+9> <input>filename:basedir(user_data, "My App",#{author=>"Erlang",version=>"1.2"}).</input>
+"c:/Users/otptest/AppData/Local/Erlang/My App/1.2"</pre>
+ </item>
+ <item><c>user_log</c>
+ <p>The path location is intended for transient log files on a local machine.</p>
+ <p>
+ On Linux:
+ Respects the os environment variable <c>XDG_CACHE_HOME</c>.</p>
+ <pre>
+4> <input>filename:basedir(user_log, "my_application", #{os=>linux}).</input>
+"/home/otptest/.cache/my_application/log"</pre>
+ On Darwin:<pre>
+4> <input>filename:basedir(user_log, "my_application", #{os=>darwin}).</input>
+"/home/otptest/Library/Caches/my_application"</pre>
+ On Windows:<pre>
+12> <input>filename:basedir(user_log, "My App").</input>
+"c:/Users/otptest/AppData/Local/My App/Logs"
+13> <input>filename:basedir(user_log, "My App",#{author=>"Erlang",version=>"1.2"}).</input>
+"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Logs"</pre>
+ </item>
+ <item><c>site_config</c><p>
+ On Linux:
+ Respects the os environment variable <c>XDG_CONFIG_DIRS</c>.</p>
+<pre>
+5> <input>filename:basedir(site_data, "my_application", #{os=>linux}).</input>
+["/usr/local/share/my_application",
+ "/usr/share/my_application"]
+6> <input>os:getenv("XDG_CONFIG_DIRS").</input>
+"/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg"
+7> <input>filename:basedir(site_config, "my_application", #{os=>linux}).</input>
+["/etc/xdg/xdg-ubuntu/my_application",
+ "/usr/share/upstart/xdg/my_application",
+ "/etc/xdg/my_application"]
+8> <input>os:unsetenv("XDG_CONFIG_DIRS").</input>
+true
+9> <input>filename:basedir(site_config, "my_application", #{os=>linux}).</input>
+["/etc/xdg/my_application"]</pre>
+ On Darwin:<pre>
+5> <input>filename:basedir(site_config, "my_application", #{os=>darwin}).</input>
+["/Library/Application Support/my_application"]</pre>
+ </item>
+ <item><c>site_data</c><p>
+ On Linux:
+ Respects the os environment variable <c>XDG_DATA_DIRS</c>.</p>
+ <pre>
+10> <input>os:getenv("XDG_DATA_DIRS").</input>
+"/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/"
+11> <input>filename:basedir(site_data, "my_application", #{os=>linux}).</input>
+["/usr/share/ubuntu/my_application",
+ "/usr/share/gnome/my_application",
+ "/usr/local/share/my_application",
+ "/usr/share/my_application"]
+12> <input>os:unsetenv("XDG_DATA_DIRS").</input>
+true
+13> <input>filename:basedir(site_data, "my_application", #{os=>linux}).</input>
+["/usr/local/share/my_application",
+ "/usr/share/my_application"]</pre>
+ On Darwin:<pre>
+5> <input>filename:basedir(site_data, "my_application", #{os=>darwin}).</input>
+["/Library/Application Support/my_application"]</pre>
+ </item>
+ </list>
+ </desc>
+ </func>
+ <func>
<name name="basename" arity="1"/>
<fsummary>Return the last component of a filename</fsummary>
<desc>
diff --git a/lib/stdlib/examples/erl_id_trans.erl b/lib/stdlib/examples/erl_id_trans.erl
index 529ae30862..c2e345763a 100644
--- a/lib/stdlib/examples/erl_id_trans.erl
+++ b/lib/stdlib/examples/erl_id_trans.erl
@@ -18,11 +18,11 @@
%%
-module(erl_id_trans).
-%% A identity transformer of Erlang abstract syntax.
+%% An identity transformer of Erlang abstract syntax.
%% This module only traverses legal Erlang code. This is most noticeable
%% in guards where only a limited number of expressions are allowed.
-%% N.B. if this module is to be used as a basis for tranforms then
+%% N.B. if this module is to be used as a basis for transforms then
%% all the error cases must be handled otherwise this module just crashes!
-export([parse_transform/2]).
@@ -53,6 +53,17 @@ form({attribute,Line,export,Es0}) ->
form({attribute,Line,import,{Mod,Is0}}) ->
Is1 = farity_list(Is0),
{attribute,Line,import,{Mod,Is1}};
+form({attribute,Line,export_type,Es0}) ->
+ Es1 = farity_list(Es0),
+ {attribute,Line,export_type,Es1};
+form({attribute,Line,optional_callbacks,Es0}) ->
+ try farity_list(Es0) of
+ Es1 ->
+ {attribute,Line,optional_callbacks,Es1}
+ catch
+ _:_ ->
+ {attribute,Line,optional_callbacks,Es0}
+ end;
form({attribute,Line,compile,C}) ->
{attribute,Line,compile,C};
form({attribute,Line,record,{Name,Defs0}}) ->
@@ -60,14 +71,28 @@ form({attribute,Line,record,{Name,Defs0}}) ->
{attribute,Line,record,{Name,Defs1}};
form({attribute,Line,asm,{function,N,A,Code}}) ->
{attribute,Line,asm,{function,N,A,Code}};
+form({attribute,Line,type,{N,T,Vs}}) ->
+ T1 = type(T),
+ Vs1 = variable_list(Vs),
+ {attribute,Line,type,{N,T1,Vs1}};
+form({attribute,Line,opaque,{N,T,Vs}}) ->
+ T1 = type(T),
+ Vs1 = variable_list(Vs),
+ {attribute,Line,opaque,{N,T1,Vs1}};
+form({attribute,Line,spec,{{N,A},FTs}}) ->
+ FTs1 = function_type_list(FTs),
+ {attribute,Line,spec,{{N,A},FTs1}};
+form({attribute,Line,spec,{{M,N,A},FTs}}) ->
+ FTs1 = function_type_list(FTs),
+ {attribute,Line,spec,{{M,N,A},FTs1}};
+form({attribute,Line,callback,{{N,A},FTs}}) ->
+ FTs1 = function_type_list(FTs),
+ {attribute,Line,callback,{{N,A},FTs1}};
form({attribute,Line,Attr,Val}) -> %The general attribute.
{attribute,Line,Attr,Val};
form({function,Line,Name0,Arity0,Clauses0}) ->
{Name,Arity,Clauses} = function(Name0, Arity0, Clauses0),
{function,Line,Name,Arity,Clauses};
-% Mnemosyne, ignore...
-form({rule,Line,Name,Arity,Body}) ->
- {rule,Line,Name,Arity,Body}; % Dont dig into this
%% Extra forms from the parser.
form({error,E}) -> {error,E};
form({warning,W}) -> {warning,W};
@@ -79,6 +104,12 @@ farity_list([{Name,Arity}|Fas]) ->
[{Name,Arity}|farity_list(Fas)];
farity_list([]) -> [].
+%% -type variable_list([Var]) -> [Var]
+
+variable_list([{var,Line,Var}|Vs]) ->
+ [{var,Line,Var}|variable_list(Vs)];
+variable_list([]) -> [].
+
%% -type record_defs([RecDef]) -> [RecDef].
%% N.B. Field names are full expressions here but only atoms are allowed
%% by the *parser*!
@@ -88,6 +119,16 @@ record_defs([{record_field,Line,{atom,La,A},Val0}|Is]) ->
[{record_field,Line,{atom,La,A},Val1}|record_defs(Is)];
record_defs([{record_field,Line,{atom,La,A}}|Is]) ->
[{record_field,Line,{atom,La,A}}|record_defs(Is)];
+record_defs([{typed_record_field,{record_field,Line,{atom,La,A},Val0},Type}|
+ Is]) ->
+ Val1 = expr(Val0),
+ Type1 = type(Type),
+ [{typed_record_field,{record_field,Line,{atom,La,A},Val1},Type1}|
+ record_defs(Is)];
+record_defs([{typed_record_field,{record_field,Line,{atom,La,A}},Type}|Is]) ->
+ Type1 = type(Type),
+ [{typed_record_field,{record_field,Line,{atom,La,A}},Type1}|
+ record_defs(Is)];
record_defs([]) -> [].
%% -type function(atom(), integer(), [Clause]) -> {atom(),integer(),[Clause]}.
@@ -196,9 +237,9 @@ pattern_grp([]) ->
bit_types([]) ->
[];
-bit_types([Atom | Rest]) when atom(Atom) ->
+bit_types([Atom | Rest]) when is_atom(Atom) ->
[Atom | bit_types(Rest)];
-bit_types([{Atom, Integer} | Rest]) when atom(Atom), integer(Integer) ->
+bit_types([{Atom, Integer} | Rest]) when is_atom(Atom), is_integer(Integer) ->
[{Atom, Integer} | bit_types(Rest)].
@@ -226,7 +267,7 @@ pattern_fields([]) -> [].
%% -type guard([GuardTest]) -> [GuardTest].
-guard([G0|Gs]) when list(G0) ->
+guard([G0|Gs]) when is_list(G0) ->
[guard0(G0) | guard(Gs)];
guard(L) ->
guard0(L).
@@ -547,3 +588,97 @@ fun_clauses([C0|Cs]) ->
C1 = clause(C0),
[C1|fun_clauses(Cs)];
fun_clauses([]) -> [].
+
+function_type_list([{type,Line,bounded_fun,[Ft,Fc]}|Fts]) ->
+ Ft1 = function_type(Ft),
+ Fc1 = function_constraint(Fc),
+ [{type,Line,bounded_fun,[Ft1,Fc1]}|function_type_list(Fts)];
+function_type_list([Ft|Fts]) ->
+ [function_type(Ft)|function_type_list(Fts)];
+function_type_list([]) -> [].
+
+function_type({type,Line,'fun',[{type,Lt,product,As},B]}) ->
+ As1 = type_list(As),
+ B1 = type(B),
+ {type,Line,'fun',[{type,Lt,product,As1},B1]}.
+
+function_constraint([C|Cs]) ->
+ C1 = constraint(C),
+ [C1|function_constraint(Cs)];
+function_constraint([]) -> [].
+
+constraint({type,Line,constraint,[{atom,L,A},[V,T]]}) ->
+ V1 = type(V),
+ T1 = type(T),
+ {type,Line,constraint,[{atom,L,A},[V1,T1]]}.
+
+type({ann_type,Line,[{var,Lv,V},T]}) ->
+ T1 = type(T),
+ {ann_type,Line,[{var,Lv,V},T1]};
+type({atom,Line,A}) ->
+ {atom,Line,A};
+type({integer,Line,I}) ->
+ {integer,Line,I};
+type({op,Line,Op,T}) ->
+ T1 = type(T),
+ {op,Line,Op,T1};
+type({op,Line,Op,L,R}) ->
+ L1 = type(L),
+ R1 = type(R),
+ {op,Line,Op,L1,R1};
+type({type,Line,binary,[M,N]}) ->
+ M1 = type(M),
+ N1 = type(N),
+ {type,Line,binary,[M1,N1]};
+type({type,Line,'fun',[]}) ->
+ {type,Line,'fun',[]};
+type({type,Line,'fun',[{type,Lt,any},B]}) ->
+ B1 = type(B),
+ {type,Line,'fun',[{type,Lt,any},B1]};
+type({type,Line,range,[L,H]}) ->
+ L1 = type(L),
+ H1 = type(H),
+ {type,Line,range,[L1,H1]};
+type({type,Line,map,any}) ->
+ {type,Line,map,any};
+type({type,Line,map,Ps}) ->
+ Ps1 = map_pair_types(Ps),
+ {type,Line,map,Ps1};
+type({type,Line,record,[{atom,La,N}|Fs]}) ->
+ Fs1 = field_types(Fs),
+ {type,Line,record,[{atom,La,N}|Fs1]};
+type({remote_type,Line,[{atom,Lm,M},{atom,Ln,N},As]}) ->
+ As1 = type_list(As),
+ {remote_type,Line,[{atom,Lm,M},{atom,Ln,N},As1]};
+type({type,Line,tuple,any}) ->
+ {type,Line,tuple,any};
+type({type,Line,tuple,Ts}) ->
+ Ts1 = type_list(Ts),
+ {type,Line,tuple,Ts1};
+type({type,Line,union,Ts}) ->
+ Ts1 = type_list(Ts),
+ {type,Line,union,Ts1};
+type({var,Line,V}) ->
+ {var,Line,V};
+type({user_type,Line,N,As}) ->
+ As1 = type_list(As),
+ {user_type,Line,N,As1};
+type({type,Line,N,As}) ->
+ As1 = type_list(As),
+ {type,Line,N,As1}.
+
+map_pair_types([{type,Line,map_field_assoc,[K,V]}|Ps]) ->
+ K1 = type(K),
+ V1 = type(V),
+ [{type,Line,map_field_assoc,[K1,V1]}|map_pair_types(Ps)];
+map_pair_types([]) -> [].
+
+field_types([{type,Line,field_type,[{atom,La,A},T]}|Fs]) ->
+ T1 = type(T),
+ [{type,Line,field_type,[{atom,La,A},T1]}|field_types(Fs)];
+field_types([]) -> [].
+
+type_list([T|Ts]) ->
+ T1 = type(T),
+ [T1|type_list(Ts)];
+type_list([]) -> [].
diff --git a/lib/stdlib/include/erl_bits.hrl b/lib/stdlib/include/erl_bits.hrl
index 8405a55d55..2a54587a17 100644
--- a/lib/stdlib/include/erl_bits.hrl
+++ b/lib/stdlib/include/erl_bits.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-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.
@@ -26,10 +26,10 @@
-type bt_unit() :: 1..256.
-record(bittype, {
- type :: bt_type(),
- unit :: bt_unit(), %% element unit
- sign :: bt_sign(),
- endian :: bt_endian()
+ type :: bt_type() | 'undefined',
+ unit :: bt_unit() | 'undefined', %% element unit
+ sign :: bt_sign() | 'undefined',
+ endian :: bt_endian() | 'undefined'
}).
-record(bitdefault, {
diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl
index 503a2b416f..7a17226e46 100644
--- a/lib/stdlib/src/beam_lib.erl
+++ b/lib/stdlib/src/beam_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2000-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.
@@ -872,7 +872,7 @@ mandatory_chunks() ->
%%% can use it.
%%% ====================================================================
--record(state, {crypto_key_f :: crypto_fun()}).
+-record(state, {crypto_key_f :: crypto_fun() | 'undefined'}).
-define(CRYPTO_KEY_SERVER, beam_lib__crypto_key_server).
@@ -904,7 +904,11 @@ anno_from_term({Tag, Forms}) when Tag =:= abstract_v1; Tag =:= abstract_v2 ->
anno_from_term(T) ->
T.
-anno_from_forms(Forms) ->
+anno_from_forms(Forms0) ->
+ %% Forms with record field types created before OTP 19.0 are
+ %% replaced by well-formed record forms holding the type
+ %% information.
+ Forms = epp:restore_typed_record_fields(Forms0),
[erl_parse:anno_from_term(Form) || Form <- Forms].
start_crypto() ->
@@ -975,9 +979,7 @@ handle_call({get_crypto_key, What}, From, #state{crypto_key_f=F}=S) ->
handle_call({crypto_key_fun, F}, {_,_} = From, S) ->
case S#state.crypto_key_f of
undefined ->
- %% Don't allow tuple funs here. (They weren't allowed before,
- %% so there is no reason to allow them now.)
- if is_function(F), is_function(F, 1) ->
+ if is_function(F, 1) ->
{Result, Fun, Reply} =
case catch F(init) of
ok ->
diff --git a/lib/stdlib/src/binary.erl b/lib/stdlib/src/binary.erl
index af00410572..fb0c395d70 100644
--- a/lib/stdlib/src/binary.erl
+++ b/lib/stdlib/src/binary.erl
@@ -20,7 +20,7 @@
-module(binary).
%%
%% Implemented in this module:
--export([split/2,split/3,replace/3,replace/4]).
+-export([replace/3,replace/4]).
-export_type([cp/0]).
@@ -34,7 +34,8 @@
decode_unsigned/2, encode_unsigned/1, encode_unsigned/2,
first/1, last/1, list_to_bin/1, longest_common_prefix/1,
longest_common_suffix/1, match/2, match/3, matches/2,
- matches/3, part/2, part/3, referenced_byte_size/1]).
+ matches/3, part/2, part/3, referenced_byte_size/1,
+ split/2, split/3]).
-spec at(Subject, Pos) -> byte() when
Subject :: binary(),
@@ -198,19 +199,13 @@ part(_, _, _) ->
referenced_byte_size(_) ->
erlang:nif_error(undef).
-%%% End of BIFs.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% split
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-spec split(Subject, Pattern) -> Parts when
Subject :: binary(),
Pattern :: binary() | [binary()] | cp(),
Parts :: [binary()].
-split(H,N) ->
- split(H,N,[]).
+split(_, _) ->
+ erlang:nif_error(undef).
-spec split(Subject, Pattern, Options) -> Parts when
Subject :: binary(),
@@ -219,53 +214,10 @@ split(H,N) ->
Option :: {scope, part()} | trim | global | trim_all,
Parts :: [binary()].
-split(Haystack,Needles,Options) ->
- try
- {Part,Global,Trim,TrimAll} =
- get_opts_split(Options,{no,false,false,false}),
- Moptlist = case Part of
- no ->
- [];
- {A,B} ->
- [{scope,{A,B}}]
- end,
- MList = if
- Global ->
- binary:matches(Haystack,Needles,Moptlist);
- true ->
- case binary:match(Haystack,Needles,Moptlist) of
- nomatch -> [];
- Match -> [Match]
- end
- end,
- do_split(Haystack,MList,0,Trim,TrimAll)
- catch
- _:_ ->
- erlang:error(badarg)
- end.
-
-do_split(H,[],N,true,_) when N >= byte_size(H) ->
- [];
-do_split(H,[],N,_,true) when N >= byte_size(H) ->
- [];
-do_split(H,[],N,_,_) ->
- [binary:part(H,{N,byte_size(H)-N})];
-do_split(H,[{A,B}|T],N,Trim,TrimAll) ->
- case binary:part(H,{N,A-N}) of
- <<>> when TrimAll == true ->
- do_split(H,T,A+B,Trim,TrimAll);
- <<>> ->
- Rest = do_split(H,T,A+B,Trim,TrimAll),
- case {Trim, Rest} of
- {true,[]} ->
- [];
- _ ->
- [<<>> | Rest]
- end;
- Oth ->
- [Oth | do_split(H,T,A+B,Trim,TrimAll)]
- end.
+split(_, _, _) ->
+ erlang:nif_error(undef).
+%%% End of BIFs.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% replace
@@ -352,19 +304,6 @@ splitat(H,N,[I|T]) ->
%% Simple helper functions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-get_opts_split([],{Part,Global,Trim,TrimAll}) ->
- {Part,Global,Trim,TrimAll};
-get_opts_split([{scope,{A,B}} | T],{_Part,Global,Trim,TrimAll}) ->
- get_opts_split(T,{{A,B},Global,Trim,TrimAll});
-get_opts_split([global | T],{Part,_Global,Trim,TrimAll}) ->
- get_opts_split(T,{Part,true,Trim,TrimAll});
-get_opts_split([trim | T],{Part,Global,_Trim,TrimAll}) ->
- get_opts_split(T,{Part,Global,true,TrimAll});
-get_opts_split([trim_all | T],{Part,Global,Trim,_TrimAll}) ->
- get_opts_split(T,{Part,Global,Trim,true});
-get_opts_split(_,_) ->
- throw(badopt).
-
get_opts_replace([],{Part,Global,Insert}) ->
{Part,Global,Insert};
get_opts_replace([{scope,{A,B}} | T],{_Part,Global,Insert}) ->
diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl
index 2d037ff795..bf22949870 100644
--- a/lib/stdlib/src/dets.erl
+++ b/lib/stdlib/src/dets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-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.
@@ -1124,7 +1124,9 @@ repl({delayed_write, {Delay,Size} = C}, Defs)
Defs#open_args{delayed_write = C};
repl({estimated_no_objects, I}, Defs) ->
repl({min_no_slots, I}, Defs);
-repl({file, File}, Defs) ->
+repl({file, File}, Defs) when is_list(File) ->
+ Defs#open_args{file = File};
+repl({file, File}, Defs) when is_atom(File) ->
Defs#open_args{file = to_list(File)};
repl({keypos, P}, Defs) when is_integer(P), P > 0 ->
Defs#open_args{keypos =P};
@@ -1289,7 +1291,15 @@ init(Parent, Server) ->
open_file_loop(#head{parent = Parent, server = Server}).
open_file_loop(Head) ->
- open_file_loop(Head, 0).
+ %% The Dets server pretends the file is open before
+ %% internal_open() has been called, which means that unless the
+ %% internal_open message is applied first, other processes can
+ %% find the pid by calling dets_server:get_pid() and do things
+ %% before Head has been initialized properly.
+ receive
+ ?DETS_CALL(From, {internal_open, _Ref, _Args}=Op) ->
+ do_apply_op(Op, From, Head, 0)
+ end.
open_file_loop(Head, N) when element(1, Head#head.update_mode) =:= error ->
open_file_loop2(Head, N);
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index d3124ac593..936c095aef 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -40,16 +40,21 @@
-type ifdef() :: 'ifdef' | 'ifndef' | 'else'.
--type name() :: {'atom', atom()}.
+-type name() :: atom().
-type argspec() :: 'none' %No arguments
| non_neg_integer(). %Number of arguments
-type tokens() :: [erl_scan:token()].
-type used() :: {name(), argspec()}.
+-type function_name_type() :: 'undefined'
+ | {atom(),non_neg_integer()}
+ | tokens().
+
-define(DEFAULT_ENCODING, utf8).
%% Epp state record.
--record(epp, {file :: file:io_device(), %Current file
+-record(epp, {file :: file:io_device()
+ | 'undefined', %Current file
location=1, %Current location
delta=0 :: non_neg_integer(), %Offset from Location (-file)
name="" :: file:name(), %Current file name
@@ -57,21 +62,15 @@
istk=[] :: [ifdef()], %Ifdef stack
sstk=[] :: [#epp{}], %State stack
path=[] :: [file:name()], %Include-path
- macs = dict:new() %Macros (don't care locations)
- :: dict:dict(name(), {argspec(), tokens()}),
- uses = dict:new() %Macro use structure
- :: dict:dict(name(), [{argspec(), [used()]}]),
+ macs = #{} %Macros (don't care locations)
+ :: #{name() => {argspec(), tokens()}},
+ uses = #{} %Macro use structure
+ :: #{name() => [{argspec(), [used()]}]},
default_encoding = ?DEFAULT_ENCODING :: source_encoding(),
- pre_opened = false :: boolean()
+ pre_opened = false :: boolean(),
+ fname = [] :: function_name_type()
}).
-%%% Note on representation: as tokens, both {var, Location, Name} and
-%%% {atom, Location, Name} can occur as macro identifiers. However, keeping
-%%% this distinction here is done for historical reasons only: previously,
-%%% ?FOO and ?'FOO' were not the same, but now they are. Removing the
-%%% distinction in the internal representation would simplify the code
-%%% a little.
-
%% open(Options)
%% open(FileName, IncludePath)
%% open(FileName, IncludePath, PreDefMacros)
@@ -211,6 +210,10 @@ format_error({include,W,F}) ->
io_lib:format("can't find include ~s \"~s\"", [W,F]);
format_error({illegal,How,What}) ->
io_lib:format("~s '-~s'", [How,What]);
+format_error({illegal_function,Macro}) ->
+ io_lib:format("?~s can only be used within a function", [Macro]);
+format_error({illegal_function_usage,Macro}) ->
+ io_lib:format("?~s must not begin a form", [Macro]);
format_error({'NYI',What}) ->
io_lib:format("not yet implemented '~s'", [What]);
format_error(E) -> file:format_error(E).
@@ -264,20 +267,7 @@ parse_file(Ifile, Options) ->
parse_file(Epp) ->
case parse_erl_form(Epp) of
{ok,Form} ->
- case Form of
- {attribute,La,record,{Record, Fields}} ->
- case normalize_typed_record_fields(Fields) of
- {typed, NewFields} ->
- [{attribute, La, record, {Record, NewFields}},
- {attribute, La, type,
- {{record, Record}, Fields, []}}
- |parse_file(Epp)];
- not_typed ->
- [Form|parse_file(Epp)]
- end;
- _ ->
- [Form|parse_file(Epp)]
- end;
+ [Form|parse_file(Epp)];
{error,E} ->
[{error,E}|parse_file(Epp)];
{eof,Location} ->
@@ -549,7 +539,8 @@ init_server(Pid, Name, Options, St0) ->
default_encoding=DefEncoding},
From = wait_request(St),
Anno = erl_anno:new(AtLocation),
- enter_file_reply(From, Name, Anno, AtLocation, code),
+ enter_file_reply(From, file_name(Name), Anno,
+ AtLocation, code),
wait_req_scan(St);
{error,E} ->
epp_reply(Pid, {error,E})
@@ -560,18 +551,20 @@ init_server(Pid, Name, Options, St0) ->
%% FILE, LINE, MODULE as undefined, MACHINE and MACHINE value.
predef_macros(File) ->
- Machine = list_to_atom(erlang:system_info(machine)),
- Anno = line1(),
- dict:from_list([
- {{atom,'FILE'}, {none,[{string,Anno,File}]}},
- {{atom,'LINE'}, {none,[{integer,Anno,1}]}},
- {{atom,'MODULE'}, undefined},
- {{atom,'MODULE_STRING'}, undefined},
- {{atom,'BASE_MODULE'}, undefined},
- {{atom,'BASE_MODULE_STRING'}, undefined},
- {{atom,'MACHINE'}, {none,[{atom,Anno,Machine}]}},
- {{atom,Machine}, {none,[{atom,Anno,true}]}}
- ]).
+ Machine = list_to_atom(erlang:system_info(machine)),
+ Anno = line1(),
+ Defs = [{'FILE', {none,[{string,Anno,File}]}},
+ {'FUNCTION_NAME', undefined},
+ {'FUNCTION_ARITY', undefined},
+ {'LINE', {none,[{integer,Anno,1}]}},
+ {'MODULE', undefined},
+ {'MODULE_STRING', undefined},
+ {'BASE_MODULE', undefined},
+ {'BASE_MODULE_STRING', undefined},
+ {'MACHINE', {none,[{atom,Anno,Machine}]}},
+ {Machine, {none,[{atom,Anno,true}]}}
+ ],
+ maps:from_list(Defs).
%% user_predef(PreDefMacros, Macros) ->
%% {ok,MacroDict} | {error,E}
@@ -580,28 +573,21 @@ predef_macros(File) ->
user_predef([{M,Val,redefine}|Pdm], Ms) when is_atom(M) ->
Exp = erl_parse:tokens(erl_parse:abstract(Val)),
- user_predef(Pdm, dict:store({atom,M}, {none,Exp}, Ms));
+ user_predef(Pdm, Ms#{M=>{none,Exp}});
user_predef([{M,Val}|Pdm], Ms) when is_atom(M) ->
- case dict:find({atom,M}, Ms) of
- {ok,_Defs} when is_list(_Defs) -> %% User defined macros
+ case Ms of
+ #{M:=Defs} when is_list(Defs) ->
+ %% User defined macros.
{error,{redefine,M}};
- {ok,_Def} -> %% Predefined macros
+ #{M:=_Defs} ->
+ %% Predefined macros.
{error,{redefine_predef,M}};
- error ->
+ _ ->
Exp = erl_parse:tokens(erl_parse:abstract(Val)),
- user_predef(Pdm, dict:store({atom,M}, [{none, {none,Exp}}], Ms))
+ user_predef(Pdm, Ms#{M=>[{none,{none,Exp}}]})
end;
user_predef([M|Pdm], Ms) when is_atom(M) ->
- case dict:find({atom,M}, Ms) of
- {ok,_Defs} when is_list(_Defs) -> %% User defined macros
- {error,{redefine,M}};
- {ok,_Def} -> %% Predefined macros
- {error,{redefine_predef,M}};
- error ->
- A = line1(),
- user_predef(Pdm,
- dict:store({atom,M}, [{none, {none,[{atom,A,true}]}}], Ms))
- end;
+ user_predef([{M,true}|Pdm], Ms);
user_predef([Md|_Pdm], _Ms) -> {error,{bad,Md}};
user_predef([], Ms) -> {ok,Ms}.
@@ -615,7 +601,9 @@ wait_request(St) ->
receive
{epp_request,From,scan_erl_form} -> From;
{epp_request,From,macro_defs} ->
- epp_reply(From, dict:to_list(St#epp.macs)),
+ %% Return the old format to avoid any incompability issues.
+ Defs = [{{atom,K},V} || {K,V} <- maps:to_list(St#epp.macs)],
+ epp_reply(From, Defs),
wait_request(St);
{epp_request,From,close} ->
close_file(St),
@@ -667,7 +655,8 @@ enter_file(NewName, Inc, From, St) ->
enter_file2(NewF, Pname, From, St0, AtLocation) ->
Anno = erl_anno:new(AtLocation),
enter_file_reply(From, Pname, Anno, AtLocation, code),
- Ms = dict:store({atom,'FILE'}, {none,[{string,Anno,Pname}]}, St0#epp.macs),
+ Ms0 = St0#epp.macs,
+ Ms = Ms0#{'FILE':={none,[{string,Anno,Pname}]}},
%% update the head of the include path to be the directory of the new
%% source file, so that an included file can always include other files
%% relative to its current location (this is also how C does it); note
@@ -688,7 +677,7 @@ enter_file_reply(From, Name, LocationAnno, AtLocation, Where) ->
generated -> erl_anno:set_generated(true, Anno0)
end,
Rep = {ok, [{'-',Anno},{atom,Anno,file},{'(',Anno},
- {string,Anno,file_name(Name)},{',',Anno},
+ {string,Anno,Name},{',',Anno},
{integer,Anno,get_line(LocationAnno)},{')',LocationAnno},
{dot,Anno}]},
epp_reply(From, Rep).
@@ -719,9 +708,8 @@ leave_file(From, St) ->
name2=OldName2} = OldSt,
CurrLoc = add_line(OldLoc, Delta),
Anno = erl_anno:new(CurrLoc),
- Ms = dict:store({atom,'FILE'},
- {none,[{string,Anno,OldName2}]},
- St#epp.macs),
+ Ms0 = St#epp.macs,
+ Ms = Ms0#{'FILE':={none,[{string,Anno,OldName2}]}},
NextSt = OldSt#epp{sstk=Sts,macs=Ms,uses=St#epp.uses},
enter_file_reply(From, OldName, Anno, CurrLoc, code),
case OldName2 =:= OldName of
@@ -778,7 +766,7 @@ scan_toks([{'-',_Lh},{atom,_Le,elif}=Elif|Toks], From, St) ->
scan_toks([{'-',_Lh},{atom,_Le,endif}=Endif|Toks], From, St) ->
scan_endif(Toks, Endif, From, St);
scan_toks([{'-',_Lh},{atom,_Lf,file}=FileToken|Toks0], From, St) ->
- case catch expand_macros(Toks0, {St#epp.macs, St#epp.uses}) of
+ case catch expand_macros(Toks0, St) of
Toks1 when is_list(Toks1) ->
scan_file(Toks1, FileToken, From, St);
{error,ErrL,What} ->
@@ -786,7 +774,7 @@ scan_toks([{'-',_Lh},{atom,_Lf,file}=FileToken|Toks0], From, St) ->
wait_req_scan(St)
end;
scan_toks(Toks0, From, St) ->
- case catch expand_macros(Toks0, {St#epp.macs, St#epp.uses}) of
+ case catch expand_macros(Toks0, St#epp{fname=Toks0}) of
Toks1 when is_list(Toks1) ->
epp_reply(From, {ok,Toks1}),
wait_req_scan(St#epp{macs=scan_module(Toks1, St#epp.macs)});
@@ -796,91 +784,48 @@ scan_toks(Toks0, From, St) ->
end.
scan_module([{'-',_Lh},{atom,_Lm,module},{'(',_Ll}|Ts], Ms) ->
- scan_module_1(Ts, [], Ms);
+ scan_module_1(Ts, Ms);
scan_module([{'-',_Lh},{atom,_Lm,extends},{'(',_Ll}|Ts], Ms) ->
- scan_extends(Ts, [], Ms);
+ scan_extends(Ts, Ms);
scan_module(_Ts, Ms) -> Ms.
-scan_module_1([{atom,_,_}=A,{',',L}|Ts], As, Ms) ->
+scan_module_1([{atom,_,_}=A,{',',L}|Ts], Ms) ->
%% Parameterized modules.
- scan_module_1([A,{')',L}|Ts], As, Ms);
-scan_module_1([{atom,Ln,A},{')',_Lr}|_Ts], As, Ms0) ->
- Mod = lists:concat(lists:reverse([A|As])),
- Ms = dict:store({atom,'MODULE'},
- {none,[{atom,Ln,list_to_atom(Mod)}]}, Ms0),
- dict:store({atom,'MODULE_STRING'}, {none,[{string,Ln,Mod}]}, Ms);
-scan_module_1([{atom,_Ln,A},{'.',_Lr}|Ts], As, Ms) ->
- scan_module_1(Ts, [".",A|As], Ms);
-scan_module_1([{'.',_Lr}|Ts], As, Ms) ->
- scan_module_1(Ts, As, Ms);
-scan_module_1(_Ts, _As, Ms) -> Ms.
-
-scan_extends([{atom,Ln,A},{')',_Lr}|_Ts], As, Ms0) ->
- Mod = lists:concat(lists:reverse([A|As])),
- Ms = dict:store({atom,'BASE_MODULE'},
- {none,[{atom,Ln,list_to_atom(Mod)}]}, Ms0),
- dict:store({atom,'BASE_MODULE_STRING'}, {none,[{string,Ln,Mod}]}, Ms);
-scan_extends([{atom,_Ln,A},{'.',_Lr}|Ts], As, Ms) ->
- scan_extends(Ts, [".",A|As], Ms);
-scan_extends([{'.',_Lr}|Ts], As, Ms) ->
- scan_extends(Ts, As, Ms);
-scan_extends(_Ts, _As, Ms) -> Ms.
+ scan_module_1([A,{')',L}|Ts], Ms);
+scan_module_1([{atom,Ln,A}=ModAtom,{')',_Lr}|_Ts], Ms0) ->
+ ModString = atom_to_list(A),
+ Ms = Ms0#{'MODULE':={none,[ModAtom]}},
+ Ms#{'MODULE_STRING':={none,[{string,Ln,ModString}]}};
+scan_module_1(_Ts, Ms) -> Ms.
+
+scan_extends([{atom,Ln,A}=ModAtom,{')',_Lr}|_Ts], Ms0) ->
+ ModString = atom_to_list(A),
+ Ms = Ms0#{'BASE_MODULE':={none,[ModAtom]}},
+ Ms#{'BASE_MODULE_STRING':={none,[{string,Ln,ModString}]}};
+scan_extends(_Ts, Ms) -> Ms.
%% scan_define(Tokens, DefineToken, From, EppState)
-scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{',',_}=Comma|Toks], _Def, From, St)
+scan_define([{'(',_Lp},{Type,_Lm,_}=Mac|Toks], Def, From, St)
when Type =:= atom; Type =:= var ->
+ scan_define_1(Toks, Mac, Def, From, St);
+scan_define(_Toks, Def, From, St) ->
+ epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
+ wait_req_scan(St).
+
+scan_define_1([{',',_}=Comma|Toks], Mac,_Def, From, St) ->
case catch macro_expansion(Toks, Comma) of
Expansion when is_list(Expansion) ->
- case dict:find({atom,M}, St#epp.macs) of
- {ok, Defs} when is_list(Defs) ->
- %% User defined macros: can be overloaded
- case proplists:is_defined(none, Defs) of
- true ->
- epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
- wait_req_scan(St);
- false ->
- scan_define_cont(From, St,
- {atom, M},
- {none, {none,Expansion}})
- end;
- {ok, _PreDef} ->
- %% Predefined macros: cannot be overloaded
- epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,M}}}),
- wait_req_scan(St);
- error ->
- scan_define_cont(From, St,
- {atom, M},
- {none, {none,Expansion}})
- end;
+ scan_define_2(none, {none,Expansion}, Mac, From, St);
{error,ErrL,What} ->
epp_reply(From, {error,{ErrL,epp,What}}),
wait_req_scan(St)
end;
-scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St)
- when Type =:= atom; Type =:= var ->
+scan_define_1([{'(',_Lc}|Toks], Mac, Def, From, St) ->
case catch macro_pars(Toks, []) of
- {ok, {As,Me}} ->
+ {ok,{As,_}=MacroDef} ->
Len = length(As),
- case dict:find({atom,M}, St#epp.macs) of
- {ok, Defs} when is_list(Defs) ->
- %% User defined macros: can be overloaded
- case proplists:is_defined(Len, Defs) of
- true ->
- epp_reply(From,{error,{loc(Mac),epp,{redefine,M}}}),
- wait_req_scan(St);
- false ->
- scan_define_cont(From, St, {atom, M},
- {Len, {As, Me}})
- end;
- {ok, _PreDef} ->
- %% Predefined macros: cannot be overloaded
- %% (There are currently no predefined F(...) macros.)
- epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,M}}}),
- wait_req_scan(St);
- error ->
- scan_define_cont(From, St, {atom, M}, {Len, {As, Me}})
- end;
+ scan_define_2(Len, MacroDef, Mac, From, St);
{error,ErrL,What} ->
epp_reply(From, {error,{ErrL,epp,What}}),
wait_req_scan(St);
@@ -888,10 +833,29 @@ scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St)
epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
wait_req_scan(St)
end;
-scan_define(_Toks, Def, From, St) ->
+scan_define_1(_Toks, _Mac, Def, From, St) ->
epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
wait_req_scan(St).
+scan_define_2(Arity, Def, {_,_,Key}=Mac, From, #epp{macs=Ms}=St) ->
+ case Ms of
+ #{Key:=Defs} when is_list(Defs) ->
+ %% User defined macros: can be overloaded
+ case proplists:is_defined(Arity, Defs) of
+ true ->
+ epp_reply(From, {error,{loc(Mac),epp,{redefine,Key}}}),
+ wait_req_scan(St);
+ false ->
+ scan_define_cont(From, St, Key, Defs, Arity, Def)
+ end;
+ #{Key:=_} ->
+ %% Predefined macros: cannot be overloaded
+ epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,Key}}}),
+ wait_req_scan(St);
+ _ ->
+ scan_define_cont(From, St, Key, [], Arity, Def)
+ end.
+
%%% Detection of circular macro expansions (which would either keep
%%% the compiler looping forever, or run out of memory):
%%% When a macro is defined, we store the names of other macros it
@@ -901,11 +865,17 @@ scan_define(_Toks, Def, From, St) ->
%%% the information from St#epp.uses is traversed, and if a circularity
%%% is detected, an error message is thrown.
-scan_define_cont(F, St, M, {Arity, Def}) ->
- Ms = dict:append_list(M, [{Arity, Def}], St#epp.macs),
- try dict:append_list(M, [{Arity, macro_uses(Def)}], St#epp.uses) of
+scan_define_cont(F, #epp{macs=Ms0}=St, M, Defs, Arity, Def) ->
+ Ms = Ms0#{M=>[{Arity,Def}|Defs]},
+ try macro_uses(Def) of
U ->
- scan_toks(F, St#epp{uses=U, macs=Ms})
+ Uses0 = St#epp.uses,
+ Val = [{Arity,U}|case Uses0 of
+ #{M:=UseList} -> UseList;
+ _ -> []
+ end],
+ Uses = Uses0#{M=>Val},
+ scan_toks(F, St#epp{uses=Uses,macs=Ms})
catch
{error, Line, Reason} ->
epp_reply(F, {error,{Line,epp,Reason}}),
@@ -923,23 +893,23 @@ macro_ref([{'?', _}, {'?', _} | Rest]) ->
macro_ref([{'?', _}, {atom, _, A}=Atom | Rest]) ->
Lm = loc(Atom),
Arity = count_args(Rest, Lm, A),
- [{{atom, A}, Arity} | macro_ref(Rest)];
+ [{A,Arity} | macro_ref(Rest)];
macro_ref([{'?', _}, {var, _, A}=Var | Rest]) ->
Lm = loc(Var),
Arity = count_args(Rest, Lm, A),
- [{{atom, A}, Arity} | macro_ref(Rest)];
+ [{A,Arity} | macro_ref(Rest)];
macro_ref([_Token | Rest]) ->
macro_ref(Rest).
%% scan_undef(Tokens, UndefToken, From, EppState)
scan_undef([{'(',_Llp},{atom,_Lm,M},{')',_Lrp},{dot,_Ld}], _Undef, From, St) ->
- Macs = dict:erase({atom,M}, St#epp.macs),
- Uses = dict:erase({atom,M}, St#epp.uses),
+ Macs = maps:remove(M, St#epp.macs),
+ Uses = maps:remove(M, St#epp.uses),
scan_toks(From, St#epp{macs=Macs, uses=Uses});
scan_undef([{'(',_Llp},{var,_Lm,M},{')',_Lrp},{dot,_Ld}], _Undef, From,St) ->
- Macs = dict:erase({atom,M}, St#epp.macs),
- Uses = dict:erase({atom,M}, St#epp.uses),
+ Macs = maps:remove(M, St#epp.macs),
+ Uses = maps:remove(M, St#epp.uses),
scan_toks(From, St#epp{macs=Macs, uses=Uses});
scan_undef(_Toks, Undef, From, St) ->
epp_reply(From, {error,{loc(Undef),epp,{bad,undef}}}),
@@ -1006,17 +976,17 @@ scan_include_lib(_Toks, Inc, From, St) ->
%% Report a badly formed if[n]def test and then treat as undefined macro.
scan_ifdef([{'(',_Llp},{atom,_Lm,M},{')',_Lrp},{dot,_Ld}], _IfD, From, St) ->
- case dict:find({atom,M}, St#epp.macs) of
- {ok,_Def} ->
+ case St#epp.macs of
+ #{M:=_Def} ->
scan_toks(From, St#epp{istk=[ifdef|St#epp.istk]});
- error ->
+ _ ->
skip_toks(From, St, [ifdef])
end;
scan_ifdef([{'(',_Llp},{var,_Lm,M},{')',_Lrp},{dot,_Ld}], _IfD, From, St) ->
- case dict:find({atom,M}, St#epp.macs) of
- {ok,_Def} ->
+ case St#epp.macs of
+ #{M:=_Def} ->
scan_toks(From, St#epp{istk=[ifdef|St#epp.istk]});
- error ->
+ _ ->
skip_toks(From, St, [ifdef])
end;
scan_ifdef(_Toks, IfDef, From, St) ->
@@ -1024,17 +994,17 @@ scan_ifdef(_Toks, IfDef, From, St) ->
wait_req_skip(St, [ifdef]).
scan_ifndef([{'(',_Llp},{atom,_Lm,M},{')',_Lrp},{dot,_Ld}], _IfnD, From, St) ->
- case dict:find({atom,M}, St#epp.macs) of
- {ok,_Def} ->
+ case St#epp.macs of
+ #{M:=_Def} ->
skip_toks(From, St, [ifndef]);
- error ->
+ _ ->
scan_toks(From, St#epp{istk=[ifndef|St#epp.istk]})
end;
scan_ifndef([{'(',_Llp},{var,_Lm,M},{')',_Lrp},{dot,_Ld}], _IfnD, From, St) ->
- case dict:find({atom,M}, St#epp.macs) of
- {ok,_Def} ->
+ case St#epp.macs of
+ #{M:=_Def} ->
skip_toks(From, St, [ifndef]);
- error ->
+ _ ->
scan_toks(From, St#epp{istk=[ifndef|St#epp.istk]})
end;
scan_ifndef(_Toks, IfnDef, From, St) ->
@@ -1102,7 +1072,8 @@ scan_file([{'(',_Llp},{string,_Ls,Name},{',',_Lc},{integer,_Li,Ln},{')',_Lrp},
{dot,_Ld}], Tf, From, St) ->
Anno = erl_anno:new(Ln),
enter_file_reply(From, Name, Anno, loc(Tf), generated),
- Ms = dict:store({atom,'FILE'}, {none,[{string,line1(),Name}]}, St#epp.macs),
+ Ms0 = St#epp.macs,
+ Ms = Ms0#{'FILE':={none,[{string,line1(),Name}]}},
Locf = loc(Tf),
NewLoc = new_location(Ln, St#epp.location, Locf),
Delta = get_line(element(2, Tf))-Ln + St#epp.delta,
@@ -1185,45 +1156,47 @@ macro_expansion([T|Ts], _Anno0) ->
[T|macro_expansion(Ts, T)];
macro_expansion([], Anno0) -> throw({error,loc(Anno0),premature_end}).
-%% expand_macros(Tokens, Macros)
+%% expand_macros(Tokens, St)
%% expand_macro(Tokens, MacroToken, RestTokens)
%% Expand the macros in a list of tokens, making sure that an expansion
%% gets the same location as the macro call.
-expand_macros(Type, MacT, M, Toks, Ms0) ->
- %% (Type will always be 'atom')
- {Ms, U} = Ms0,
+expand_macros(MacT, M, Toks, St) ->
+ #epp{macs=Ms,uses=U} = St,
Lm = loc(MacT),
Tinfo = element(2, MacT),
- case expand_macro1(Type, Lm, M, Toks, Ms) of
+ case expand_macro1(Lm, M, Toks, Ms) of
{ok,{none,Exp}} ->
- check_uses([{{Type,M}, none}], [], U, Lm),
- Toks1 = expand_macros(expand_macro(Exp, Tinfo, [], dict:new()), Ms0),
- expand_macros(Toks1++Toks, Ms0);
+ check_uses([{M,none}], [], U, Lm),
+ Toks1 = expand_macros(expand_macro(Exp, Tinfo, [], #{}), St),
+ expand_macros(Toks1++Toks, St);
{ok,{As,Exp}} ->
- check_uses([{{Type,M}, length(As)}], [], U, Lm),
- {Bs,Toks1} = bind_args(Toks, Lm, M, As, dict:new()),
- expand_macros(expand_macro(Exp, Tinfo, Toks1, Bs), Ms0)
+ check_uses([{M,length(As)}], [], U, Lm),
+ {Bs,Toks1} = bind_args(Toks, Lm, M, As, #{}),
+ expand_macros(expand_macro(Exp, Tinfo, Toks1, Bs), St)
end.
-expand_macro1(Type, Lm, M, Toks, Ms) ->
+expand_macro1(Lm, M, Toks, Ms) ->
Arity = count_args(Toks, Lm, M),
- case dict:find({Type,M}, Ms) of
- error -> %% macro not found
+ case Ms of
+ #{M:=undefined} ->
+ %% Predefined macro without definition.
throw({error,Lm,{undefined,M,Arity}});
- {ok, undefined} -> %% Predefined macro without definition
- throw({error,Lm,{undefined,M,Arity}});
- {ok, [{none, Def}]} ->
- {ok, Def};
- {ok, Defs} when is_list(Defs) ->
- case proplists:get_value(Arity, Defs) of
+ #{M:=[{none,Def}]} ->
+ {ok,Def};
+ #{M:=Defs} when is_list(Defs) ->
+ case proplists:get_value(Arity, Defs) of
undefined ->
throw({error,Lm,{mismatch,M}});
Def ->
- {ok, Def}
+ {ok,Def}
end;
- {ok, PreDef} -> %% Predefined macro
- {ok, PreDef}
+ #{M:=PreDef} ->
+ %% Predefined macro.
+ {ok,PreDef};
+ _ ->
+ %% Macro not found.
+ throw({error,Lm,{undefined,M,Arity}})
end.
check_uses([], _Anc, _U, _Lm) ->
@@ -1231,7 +1204,7 @@ check_uses([], _Anc, _U, _Lm) ->
check_uses([M|Rest], Anc, U, Lm) ->
case lists:member(M, Anc) of
true ->
- {{_, Name},Arity} = M,
+ {Name,Arity} = M,
throw({error,Lm,{circular,Name,Arity}});
false ->
L = get_macro_uses(M, U),
@@ -1240,25 +1213,41 @@ check_uses([M|Rest], Anc, U, Lm) ->
end.
get_macro_uses({M,Arity}, U) ->
- case dict:find(M, U) of
- error ->
- [];
- {ok, L} ->
- proplists:get_value(Arity, L, proplists:get_value(none, L, []))
+ case U of
+ #{M:=L} ->
+ proplists:get_value(Arity, L, proplists:get_value(none, L, []));
+ _ ->
+ []
end.
%% Macro expansion
%% Note: io:scan_erl_form() does not return comments or white spaces.
-expand_macros([{'?',_Lq},{atom,_Lm,M}=MacT|Toks], Ms) ->
- expand_macros(atom, MacT, M, Toks, Ms);
+expand_macros([{'?',_Lq},{atom,_Lm,M}=MacT|Toks], St) ->
+ expand_macros(MacT, M, Toks, St);
%% Special macros
-expand_macros([{'?',_Lq},{var,Lm,'LINE'}=Tok|Toks], Ms) ->
+expand_macros([{'?',_Lq},{var,Lm,'FUNCTION_NAME'}=Token|Toks], St0) ->
+ St = update_fun_name(Token, St0),
+ case St#epp.fname of
+ undefined ->
+ [{'?',_Lq},Token];
+ {Name,_} ->
+ [{atom,Lm,Name}]
+ end ++ expand_macros(Toks, St);
+expand_macros([{'?',_Lq},{var,Lm,'FUNCTION_ARITY'}=Token|Toks], St0) ->
+ St = update_fun_name(Token, St0),
+ case St#epp.fname of
+ undefined ->
+ [{'?',_Lq},Token];
+ {_,Arity} ->
+ [{integer,Lm,Arity}]
+ end ++ expand_macros(Toks, St);
+expand_macros([{'?',_Lq},{var,Lm,'LINE'}=Tok|Toks], St) ->
Line = erl_scan:line(Tok),
- [{integer,Lm,Line}|expand_macros(Toks, Ms)];
-expand_macros([{'?',_Lq},{var,_Lm,M}=MacT|Toks], Ms) ->
- expand_macros(atom, MacT, M, Toks, Ms);
+ [{integer,Lm,Line}|expand_macros(Toks, St)];
+expand_macros([{'?',_Lq},{var,_Lm,M}=MacT|Toks], St) ->
+ expand_macros(MacT, M, Toks, St);
%% Illegal macros
-expand_macros([{'?',_Lq},Token|_Toks], _Ms) ->
+expand_macros([{'?',_Lq},Token|_Toks], _St) ->
T = case erl_scan:text(Token) of
Text when is_list(Text) ->
Text;
@@ -1267,9 +1256,9 @@ expand_macros([{'?',_Lq},Token|_Toks], _Ms) ->
io_lib:write(Symbol)
end,
throw({error,loc(Token),{call,[$?|T]}});
-expand_macros([T|Ts], Ms) ->
- [T|expand_macros(Ts, Ms)];
-expand_macros([], _Ms) -> [].
+expand_macros([T|Ts], St) ->
+ [T|expand_macros(Ts, St)];
+expand_macros([], _St) -> [].
%% bind_args(Tokens, MacroLocation, MacroName, ArgumentVars, Bindings)
%% Collect the arguments to a macro call.
@@ -1295,7 +1284,7 @@ macro_args(_Toks, Lm, M, _As, _Bs) ->
store_arg(L, M, _A, [], _Bs) ->
throw({error,L,{mismatch,M}});
store_arg(_L, _M, A, Arg, Bs) ->
- dict:store(A, Arg, Bs).
+ Bs#{A=>Arg}.
%% count_args(Tokens, MacroLine, MacroName)
%% Count the number of arguments in a macro call.
@@ -1368,19 +1357,17 @@ macro_arg([], _E, Arg) ->
%% and then the macro arguments, i.e. simulate textual expansion.
expand_macro([{var,_Lv,V}|Ts], L, Rest, Bs) ->
- case dict:find(V, Bs) of
- {ok,Val} ->
- %% lists:append(Val, expand_macro(Ts, L, Rest, Bs));
+ case Bs of
+ #{V:=Val} ->
expand_arg(Val, Ts, L, Rest, Bs);
- error ->
+ _ ->
[{var,L,V}|expand_macro(Ts, L, Rest, Bs)]
end;
expand_macro([{'?', _}, {'?', _}, {var,_Lv,V}|Ts], L, Rest, Bs) ->
- case dict:find(V, Bs) of
- {ok,Val} ->
- %% lists:append(Val, expand_macro(Ts, L, Rest, Bs));
+ case Bs of
+ #{V:=Val} ->
expand_arg(stringify(Val, L), Ts, L, Rest, Bs);
- error ->
+ _ ->
[{var,L,V}|expand_macro(Ts, L, Rest, Bs)]
end;
expand_macro([T|Ts], L, Rest, Bs) ->
@@ -1394,6 +1381,93 @@ expand_arg([A|As], Ts, _L, Rest, Bs) ->
expand_arg([], Ts, L, Rest, Bs) ->
expand_macro(Ts, L, Rest, Bs).
+%%%
+%%% Here follows support for the ?FUNCTION_NAME and ?FUNCTION_ARITY
+%%% macros. Since the parser has not been run yet, we don't know the
+%%% name and arity of the current function. Therefore, we will need to
+%%% scan the beginning of the current form to extract the name and
+%%% arity of the function.
+%%%
+
+update_fun_name(Token, #epp{fname=Toks0}=St) when is_list(Toks0) ->
+ %% ?FUNCTION_NAME or ?FUNCTION_ARITY is used for the first time in
+ %% a function. First expand macros (except ?FUNCTION_NAME and
+ %% ?FUNCTION_ARITY) in the form.
+
+ Toks1 = (catch expand_macros(Toks0, St#epp{fname=undefined})),
+
+ %% Now extract the name and arity from the stream of tokens, and store
+ %% the result in the #epp{} record so we don't have to do it
+ %% again.
+
+ case Toks1 of
+ [{atom,_,Name},{'(',_}|Toks] ->
+ %% This is the beginning of a function definition.
+ %% Scan the token stream up to the matching right
+ %% parenthesis and count the number of arguments.
+ FA = update_fun_name_1(Toks, 1, {Name,0}, St),
+ St#epp{fname=FA};
+ [{'?',_}|_] ->
+ %% ?FUNCTION_NAME/?FUNCTION_ARITY used at the beginning
+ %% of a form. Does not make sense.
+ {var,_,Macro} = Token,
+ throw({error,loc(Token),{illegal_function_usage,Macro}});
+ _ when is_list(Toks1) ->
+ %% Not the beginning of a function (an attribute or a
+ %% syntax error).
+ {var,_,Macro} = Token,
+ throw({error,loc(Token),{illegal_function,Macro}});
+ _ ->
+ %% A macro expansion error. Return a dummy value and
+ %% let the caller notice and handle the error.
+ St#epp{fname={'_',0}}
+ end;
+update_fun_name(_Token, St) ->
+ St.
+
+update_fun_name_1([Tok|Toks], L, FA, St) ->
+ case classify_token(Tok) of
+ comma ->
+ if
+ L =:= 1 ->
+ {Name,Arity} = FA,
+ update_fun_name_1(Toks, L, {Name,Arity+1}, St);
+ true ->
+ update_fun_name_1(Toks, L, FA, St)
+ end;
+ left ->
+ update_fun_name_1(Toks, L+1, FA, St);
+ right when L =:= 1 ->
+ FA;
+ right ->
+ update_fun_name_1(Toks, L-1, FA, St);
+ other ->
+ case FA of
+ {Name,0} ->
+ update_fun_name_1(Toks, L, {Name,1}, St);
+ {_,_} ->
+ update_fun_name_1(Toks, L, FA, St)
+ end
+ end;
+update_fun_name_1([], _, FA, _) ->
+ %% Syntax error, but never mind.
+ FA.
+
+classify_token({C,_}) -> classify_token_1(C);
+classify_token(_) -> other.
+
+classify_token_1(',') -> comma;
+classify_token_1('(') -> left;
+classify_token_1('{') -> left;
+classify_token_1('[') -> left;
+classify_token_1('<<') -> left;
+classify_token_1(')') -> right;
+classify_token_1('}') -> right;
+classify_token_1(']') -> right;
+classify_token_1('>>') -> right;
+classify_token_1(_) -> other.
+
+
%%% stringify(Ts, L) returns a list of one token: a string which when
%%% tokenized would yield the token list Ts.
diff --git a/lib/stdlib/src/erl_anno.erl b/lib/stdlib/src/erl_anno.erl
index 143318aa55..d32c34dabd 100644
--- a/lib/stdlib/src/erl_anno.erl
+++ b/lib/stdlib/src/erl_anno.erl
@@ -33,7 +33,7 @@
-export_type([anno_term/0]).
--define(LN(L), is_integer(L)).
+-define(LN(L), is_integer(L), L >= 0).
-define(COL(C), (is_integer(C) andalso C >= 1)).
%% Location.
@@ -52,13 +52,13 @@
| {'record', record()}
| {'text', string()}.
--type anno() :: location() | [annotation(), ...].
+-opaque anno() :: location() | [annotation(), ...].
-type anno_term() :: term().
-type column() :: pos_integer().
-type generated() :: boolean().
-type filename() :: file:filename_all().
--type line() :: integer().
+-type line() :: non_neg_integer().
-type location() :: line() | {line(), column()}.
-type record() :: boolean().
-type text() :: string().
@@ -90,9 +90,13 @@ to_term(Anno) ->
-ifdef(DEBUG).
from_term(Term) when is_list(Term) ->
Term;
+from_term(Line) when is_integer(Line), Line < 0 -> % Before OTP 19
+ set_generated(true, new(-Line));
from_term(Term) ->
[{location, Term}].
-else.
+from_term(Line) when is_integer(Line), Line < 0 -> % Before OTP 19
+ set_generated(true, new(-Line));
from_term(Term) ->
Term.
-endif.
@@ -198,18 +202,11 @@ file(Anno) ->
Anno :: anno().
generated(Line) when ?ALINE(Line) ->
- Line =< 0;
+ false;
generated({Line, Column}) when ?ALINE(Line), ?ACOLUMN(Column) ->
- Line =< 0;
+ false;
generated(Anno) ->
- _ = anno_info(Anno, generated, false),
- {location, Location} = lists:keyfind(location, 1, Anno),
- case Location of
- {Line, _Column} ->
- Line =< 0;
- Line ->
- Line =< 0
- end.
+ anno_info(Anno, generated, false).
-spec line(Anno) -> line() when
Anno :: anno().
@@ -226,18 +223,11 @@ line(Anno) ->
Anno :: anno().
location(Line) when ?ALINE(Line) ->
- abs(Line);
-location({Line, Column}) when ?ALINE(Line), ?ACOLUMN(Column) ->
- {abs(Line), Column};
+ Line;
+location({Line, Column}=Location) when ?ALINE(Line), ?ACOLUMN(Column) ->
+ Location;
location(Anno) ->
- case anno_info(Anno, location) of
- Line when Line < 0 ->
- -Line;
- {Line, Column} when Line < 0 ->
- {-Line, Column};
- Location ->
- Location
- end.
+ anno_info(Anno, location).
-spec record(Anno) -> record() when
Anno :: anno().
@@ -270,31 +260,8 @@ set_file(File, Anno) ->
Generated :: generated(),
Anno :: anno().
-set_generated(true, Line) when ?ALINE(Line) ->
- -abs(Line);
-set_generated(false, Line) when ?ALINE(Line) ->
- abs(Line);
-set_generated(true, {Line, Column}) when ?ALINE(Line),
- ?ACOLUMN(Column) ->
- {-abs(Line),Column};
-set_generated(false, {Line, Column}) when ?ALINE(Line),
- ?ACOLUMN(Column) ->
- {abs(Line),Column};
set_generated(Generated, Anno) ->
- _ = set(generated, Generated, Anno),
- {location, Location} = lists:keyfind(location, 1, Anno),
- NewLocation =
- case Location of
- {Line, Column} when Generated ->
- {-abs(Line), Column};
- {Line, Column} when not Generated ->
- {abs(Line), Column};
- Line when Generated ->
- -abs(Line);
- Line when not Generated ->
- abs(Line)
- end,
- lists:keyreplace(location, 1, Anno, {location, NewLocation}).
+ set(generated, Generated, Anno).
-spec set_line(Line, Anno) -> Anno when
Line :: line(),
@@ -313,38 +280,17 @@ set_line(Line, Anno) ->
Anno :: anno().
set_location(Line, L) when ?ALINE(L), ?LLINE(Line) ->
- new_location(fix_line(Line, L));
+ new_location(Line);
set_location(Line, {L, Column}) when ?ALINE(L), ?ACOLUMN(Column),
?LLINE(Line) ->
- new_location(fix_line(Line, L));
+ new_location(Line);
set_location({L, C}=Loc, Line) when ?ALINE(Line), ?LLINE(L), ?LCOLUMN(C) ->
- new_location(fix_location(Loc, Line));
+ new_location(Loc);
set_location({L, C}=Loc, {Line, Column}) when ?ALINE(Line), ?ACOLUMN(Column),
?LLINE(L), ?LCOLUMN(C) ->
- new_location(fix_location(Loc, Line));
+ new_location(Loc);
set_location(Location, Anno) ->
- _ = set(location, Location, Anno),
- {location, OldLocation} = lists:keyfind(location, 1, Anno),
- NewLocation =
- case {Location, OldLocation} of
- {{_Line, _Column}=Loc, {L, _C}} ->
- fix_location(Loc, L);
- {Line, {L, _C}} ->
- fix_line(Line, L);
- {{_Line, _Column}=Loc, L} ->
- fix_location(Loc, L);
- {Line, L} ->
- fix_line(Line, L)
- end,
- lists:keyreplace(location, 1, Anno, {location, NewLocation}).
-
-fix_location({Line, Column}, OldLine) ->
- {fix_line(Line, OldLine), Column}.
-
-fix_line(Line, OldLine) when OldLine < 0, Line > 0 ->
- -Line;
-fix_line(Line, _OldLine) ->
- Line.
+ set(location, Location, Anno).
-spec set_record(Record, Anno) -> Anno when
Record :: record(),
@@ -383,7 +329,7 @@ set_anno(Item, Value, Anno) ->
_ ->
lists:keyreplace(Item, 1, Anno, {Item, Value})
end,
- simplify(R)
+ reset_simplify(R)
end.
reset(Anno, Item) ->
diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl
index bcfeef7321..9c0a7fb7d5 100644
--- a/lib/stdlib/src/erl_expand_records.erl
+++ b/lib/stdlib/src/erl_expand_records.erl
@@ -33,8 +33,6 @@
vcount=0, % Variable counter
imports=[], % Imports
records=dict:new(), % Record definitions
- trecords=sets:new(), % Typed records
- uses_types=false, % Are there -spec or -type in the module
strict_ra=[], % strict record accesses
checked_ra=[] % successfully accessed records
}).
@@ -47,45 +45,18 @@
%% erl_lint without errors.
module(Fs0, Opts0) ->
Opts = compiler_options(Fs0) ++ Opts0,
- TRecs = typed_records(Fs0),
- UsesTypes = uses_types(Fs0),
- St0 = #exprec{compile = Opts, trecords = TRecs, uses_types = UsesTypes},
+ St0 = #exprec{compile = Opts},
{Fs,_St} = forms(Fs0, St0),
Fs.
compiler_options(Forms) ->
lists:flatten([C || {attribute,_,compile,C} <- Forms]).
-typed_records(Fs) ->
- typed_records(Fs, sets:new()).
-
-typed_records([{attribute,_L,type,{{record, Name},_Defs,[]}} | Fs], Trecs) ->
- typed_records(Fs, sets:add_element(Name, Trecs));
-typed_records([_|Fs], Trecs) ->
- typed_records(Fs, Trecs);
-typed_records([], Trecs) ->
- Trecs.
-
-uses_types([{attribute,_L,spec,_}|_]) -> true;
-uses_types([{attribute,_L,type,_}|_]) -> true;
-uses_types([{attribute,_L,opaque,_}|_]) -> true;
-uses_types([_|Fs]) -> uses_types(Fs);
-uses_types([]) -> false.
-
-forms([{attribute,L,record,{Name,Defs}} | Fs], St0) ->
+forms([{attribute,_,record,{Name,Defs}}=Attr | Fs], St0) ->
NDefs = normalise_fields(Defs),
St = St0#exprec{records=dict:store(Name, NDefs, St0#exprec.records)},
{Fs1, St1} = forms(Fs, St),
- %% Check if we need to keep the record information for usage in types.
- case St#exprec.uses_types of
- true ->
- case sets:is_element(Name, St#exprec.trecords) of
- true -> {Fs1, St1};
- false -> {[{attribute,L,type,{{record,Name},Defs,[]}}|Fs1], St1}
- end;
- false ->
- {Fs1, St1}
- end;
+ {[Attr | Fs1], St1};
forms([{attribute,L,import,Is} | Fs0], St0) ->
St1 = import(Is, St0),
{Fs,St2} = forms(Fs0, St1),
@@ -513,7 +484,6 @@ lc_tq(Line, [F0 | Qs0], St0) ->
lc_tq(_Line, [], St0) ->
{[],St0#exprec{checked_ra = []}}.
-
%% normalise_fields([RecDef]) -> [Field].
%% Normalise the field definitions to always have a default value. If
%% none has been given then use 'undefined'.
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index 62b3169a6c..4ca9a609a8 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -31,12 +31,8 @@
-export([is_guard_expr/1]).
-export([bool_option/4,value_option/3,value_option/7]).
--export([modify_line/2]).
-
-import(lists, [member/2,map/2,foldl/3,foldr/3,mapfoldl/3,all/2,reverse/1]).
--deprecated([{modify_line, 2, next_major_release}]).
-
%% bool_option(OnOpt, OffOpt, Default, Options) -> boolean().
%% value_option(Flag, Default, Options) -> Value.
%% value_option(Flag, Default, OnOpt, OnVal, OffOpt, OffVal, Options) ->
@@ -79,7 +75,7 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
%%-define(DEBUGF(X,Y), io:format(X, Y)).
-define(DEBUGF(X,Y), void).
--type line() :: erl_anno:line(). % a convenient alias
+-type line() :: erl_anno:anno(). % a convenient alias
-type fa() :: {atom(), arity()}. % function+arity
-type ta() :: {atom(), arity()}. % type+arity
@@ -238,6 +234,9 @@ format_error({removed, MFA, ReplacementMFA, Rel}) ->
"use ~s", [format_mfa(MFA), Rel, format_mfa(ReplacementMFA)]);
format_error({removed, MFA, String}) when is_list(String) ->
io_lib:format("~s: ~s", [format_mfa(MFA), String]);
+format_error({removed_type, MNA, ReplacementMNA, Rel}) ->
+ io_lib:format("the type ~s was removed in ~s; use ~s instead",
+ [format_mna(MNA), Rel, format_mna(ReplacementMNA)]);
format_error({obsolete_guard, {F, A}}) ->
io_lib:format("~p/~p obsolete", [F, A]);
format_error({too_many_arguments,Arity}) ->
@@ -361,6 +360,9 @@ format_error({redefine_type, {TypeName, Arity}}) ->
[TypeName, gen_type_paren(Arity)]);
format_error({type_syntax, Constr}) ->
io_lib:format("bad ~w type", [Constr]);
+format_error(old_abstract_code) ->
+ io_lib:format("abstract code generated before Erlang/OTP 19.0 and "
+ "having typed record fields cannot be compiled", []);
format_error({redefine_spec, {M, F, A}}) ->
io_lib:format("spec for ~w:~w/~w already defined", [M, F, A]);
format_error({redefine_spec, {F, A}}) ->
@@ -374,9 +376,9 @@ format_error({spec_fun_undefined, {F, A}}) ->
format_error({missing_spec, {F,A}}) ->
io_lib:format("missing specification for function ~w/~w", [F, A]);
format_error(spec_wrong_arity) ->
- "spec has the wrong arity";
+ "spec has wrong arity";
format_error(callback_wrong_arity) ->
- "callback has the wrong arity";
+ "callback has wrong arity";
format_error({deprecated_builtin_type, {Name, Arity},
Replacement, Rel}) ->
UseS = case Replacement of
@@ -416,6 +418,9 @@ format_mfa({M, F, A}) when is_integer(A) ->
format_mf(M, F, ArityString) when is_atom(M), is_atom(F) ->
atom_to_list(M) ++ ":" ++ atom_to_list(F) ++ "/" ++ ArityString.
+format_mna({M, N, A}) when is_integer(A) ->
+ atom_to_list(M) ++ ":" ++ atom_to_list(N) ++ gen_type_paren(A).
+
format_where(L) when is_integer(L) ->
io_lib:format("(line ~p)", [L]);
format_where({L,C}) when is_integer(L), is_integer(C) ->
@@ -694,7 +699,12 @@ set_form_file({function,L,N,A,C}, File) ->
set_form_file(Form, _File) ->
Form.
+set_file(Ts, File) when is_list(Ts) ->
+ [anno_set_file(T, File) || T <- Ts];
set_file(T, File) ->
+ anno_set_file(T, File).
+
+anno_set_file(T, File) ->
F = fun(Anno) -> erl_anno:set_file(File, Anno) end,
erl_parse:map_anno(F, T).
@@ -1136,7 +1146,7 @@ check_untyped_records(Forms, St0) ->
RecNames = dict:fetch_keys(St0#lint.records),
%% these are the records with field(s) containing type info
TRecNames = [Name ||
- {attribute,_,type,{{record,Name},Fields,_}} <- Forms,
+ {attribute,_,record,{Name,Fields}} <- Forms,
lists:all(fun ({typed_record_field,_,_}) -> true;
(_) -> false
end, Fields)],
@@ -1146,7 +1156,8 @@ check_untyped_records(Forms, St0) ->
[] -> St; % exclude records with no fields
[_|_] -> add_warning(L, {untyped_record, N}, St)
end
- end, St0, RecNames -- TRecNames);
+ end, St0, ordsets:subtract(ordsets:from_list(RecNames),
+ ordsets:from_list(TRecNames)));
false ->
St0
end.
@@ -2436,7 +2447,10 @@ record_def(Line, Name, Fs0, St0) ->
true -> add_error(Line, {redefine_record,Name}, St0);
false ->
{Fs1,St1} = def_fields(normalise_fields(Fs0), Name, St0),
- St1#lint{records=dict:store(Name, {Line,Fs1}, St1#lint.records)}
+ St2 = St1#lint{records=dict:store(Name, {Line,Fs1},
+ St1#lint.records)},
+ Types = [T || {typed_record_field, _, T} <- Fs0],
+ check_type({type, nowarn(), product, Types}, St2)
end.
%% def_fields([RecDef], RecordName, State) -> {[DefField],State}.
@@ -2639,11 +2653,6 @@ find_field(_F, []) -> error.
%% Attr :: 'type' | 'opaque'
%% Checks that a type definition is valid.
-type_def(_Attr, _Line, {record, _RecName}, Fields, [], St0) ->
- %% The record field names and such are checked in the record format.
- %% We only need to check the types.
- Types = [T || {typed_record_field, _, T} <- Fields],
- check_type({type, nowarn(), product, Types}, St0);
type_def(Attr, Line, TypeName, ProtoType, Args, St0) ->
TypeDefs = St0#lint.types,
Arity = length(Args),
@@ -2806,6 +2815,8 @@ check_type({user_type, L, TypeName, Args}, SeenVars, St) ->
lists:foldl(fun(T, {AccSeenVars, AccSt}) ->
check_type(T, AccSeenVars, AccSt)
end, {SeenVars, St1}, Args);
+check_type([{typed_record_field,Field,_T}|_], SeenVars, St) ->
+ {SeenVars, add_error(element(2, Field), old_abstract_code, St)};
check_type(I, SeenVars, St) ->
case erl_eval:partial_eval(I) of
{integer,_ILn,_Integer} -> {SeenVars, St};
@@ -2876,7 +2887,7 @@ spec_decl(Line, MFA0, TypeSpecs, St0 = #lint{specs = Specs, module = Mod}) ->
St1 = St0#lint{specs = dict:store(MFA, Line, Specs)},
case dict:is_key(MFA, Specs) of
true -> add_error(Line, {redefine_spec, MFA0}, St1);
- false -> check_specs(TypeSpecs, Arity, St1)
+ false -> check_specs(TypeSpecs, spec_wrong_arity, Arity, St1)
end.
%% callback_decl(Line, Fun, Types, State) -> State.
@@ -2890,7 +2901,8 @@ callback_decl(Line, MFA0, TypeSpecs,
St1 = St0#lint{callbacks = dict:store(MFA, Line, Callbacks)},
case dict:is_key(MFA, Callbacks) of
true -> add_error(Line, {redefine_callback, MFA0}, St1);
- false -> check_specs(TypeSpecs, Arity, St1)
+ false -> check_specs(TypeSpecs, callback_wrong_arity,
+ Arity, St1)
end
end.
@@ -2927,7 +2939,7 @@ is_fa({FuncName, Arity})
when is_atom(FuncName), is_integer(Arity), Arity >= 0 -> true;
is_fa(_) -> false.
-check_specs([FunType|Left], Arity, St0) ->
+check_specs([FunType|Left], ETag, Arity, St0) ->
{FunType1, CTypes} =
case FunType of
{type, _, bounded_fun, [FT = {type, _, 'fun', _}, Cs]} ->
@@ -2935,18 +2947,16 @@ check_specs([FunType|Left], Arity, St0) ->
{FT, lists:append(Types0)};
{type, _, 'fun', _} = FT -> {FT, []}
end,
- SpecArity =
- case FunType1 of
- {type, L, 'fun', [any, _]} -> any;
- {type, L, 'fun', [{type, _, product, D}, _]} -> length(D)
- end,
+ {type, L, 'fun', [{type, _, product, D}, _]} = FunType1,
+ SpecArity = length(D),
St1 = case Arity =:= SpecArity of
true -> St0;
- false -> add_error(L, spec_wrong_arity, St0)
+ false -> %% Cannot happen if called from the compiler.
+ add_error(L, ETag, St0)
end,
St2 = check_type({type, nowarn(), product, [FunType1|CTypes]}, St1),
- check_specs(Left, Arity, St2);
-check_specs([], _Arity, St) ->
+ check_specs(Left, ETag, Arity, St2);
+check_specs([], _ETag, _Arity, St) ->
St.
nowarn() ->
@@ -2988,9 +2998,10 @@ add_missing_spec_warnings(Forms, St0, Type) ->
[{FA,L} || {function,L,F,A,_} <- Forms,
not lists:member(FA = {F,A}, Specs)];
exported ->
- Exps = gb_sets:to_list(St0#lint.exports) -- pseudolocals(),
+ Exps0 = gb_sets:to_list(St0#lint.exports) -- pseudolocals(),
+ Exps = Exps0 -- Specs,
[{FA,L} || {function,L,F,A,_} <- Forms,
- member(FA = {F,A}, Exps -- Specs)]
+ member(FA = {F,A}, Exps)]
end,
foldl(fun ({FA,L}, St) ->
add_warning(L, {missing_spec,FA}, St)
@@ -3003,7 +3014,9 @@ check_unused_types(Forms, #lint{usage=Usage, types=Ts, exp_types=ExpTs}=St) ->
L = gb_sets:to_list(ExpTs) ++ dict:fetch_keys(D),
UsedTypes = gb_sets:from_list(L),
FoldFun =
- fun(Type, #typeinfo{line = FileLine}, AccSt) ->
+ fun({{record, _}=_Type, 0}, _, AccSt) ->
+ AccSt; % Before Erlang/OTP 19.0
+ (Type, #typeinfo{line = FileLine}, AccSt) ->
case loc(FileLine, AccSt) of
{FirstFile, _} ->
case gb_sets:is_member(Type, UsedTypes) of
@@ -3190,8 +3203,8 @@ handle_generator(P,E,Vt,Uvt,St0) ->
handle_bitstring_gen_pat({bin,_,Segments=[_|_]},St) ->
case lists:last(Segments) of
{bin_element,Line,{var,_,_},default,Flags} when is_list(Flags) ->
- case member(binary, Flags) orelse member(bits, Flags)
- orelse member(bitstring, Flags) of
+ case member(binary, Flags) orelse member(bytes, Flags)
+ orelse member(bits, Flags) orelse member(bitstring, Flags) of
true ->
add_error(Line, unsized_binary_in_bin_gen_pattern, St);
false ->
@@ -3485,13 +3498,6 @@ vt_no_unused(Vt) -> [V || {_,{_,U,_L}}=V <- Vt, U =/= unused].
copy_expr(Expr, Anno) ->
erl_parse:map_anno(fun(_A) -> Anno end, Expr).
-%% modify_line(Form, Fun) -> Form
-%% modify_line(Expression, Fun) -> Expression
-%% Applies Fun to each line number occurrence.
-
-modify_line(T, F0) ->
- erl_parse:map_anno(F0, T).
-
%% Check a record_info call. We have already checked that it is not
%% shadowed by an import.
@@ -3574,6 +3580,8 @@ deprecated_type(L, M, N, As, St) ->
false ->
St
end;
+ {removed, Replacement, Rel} ->
+ add_warning(L, {removed_type, {M,N,NAs}, Replacement, Rel}, St);
no ->
St
end.
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index e82282421e..6f8e5e8449 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1996-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.
@@ -85,10 +85,6 @@ type_spec -> '(' spec_fun type_sigs ')' : {'$2', '$3'}.
spec_fun -> atom : '$1'.
spec_fun -> atom ':' atom : {'$1', '$3'}.
-%% The following two are retained only for backwards compatibility;
-%% they are not part of the EEP syntax and should be removed.
-spec_fun -> atom '/' integer '::' : {'$1', '$3'}.
-spec_fun -> atom ':' atom '/' integer '::' : {'$1', '$3', '$5'}.
typed_attr_val -> expr ',' typed_record_fields : {typed_record, '$1', '$3'}.
typed_attr_val -> expr '::' top_type : {type_def, '$1', '$3'}.
@@ -315,7 +311,7 @@ bit_size_expr -> expr_max : '$1'.
list_comprehension -> '[' expr '||' lc_exprs ']' :
{lc,?anno('$1'),'$2','$4'}.
-binary_comprehension -> '<<' binary '||' lc_exprs '>>' :
+binary_comprehension -> '<<' expr_max '||' lc_exprs '>>' :
{bc,?anno('$1'),'$2','$4'}.
lc_exprs -> lc_expr : ['$1'].
lc_exprs -> lc_expr ',' lc_exprs : ['$1'|'$3'].
@@ -525,23 +521,424 @@ Erlang code.
-export([type_inop_prec/1,type_preop_prec/1]).
-export([map_anno/2, fold_anno/3, mapfold_anno/3,
new_anno/1, anno_to_term/1, anno_from_term/1]).
--export([set_line/2,get_attribute/2,get_attributes/1]).
-
--deprecated([{set_line, 2, next_major_release},
- {get_attribute, 2, next_major_release},
- {get_attributes, 1, next_major_release}]).
%% The following directive is needed for (significantly) faster compilation
%% of the generated .erl file by the HiPE compiler. Please do not remove.
-compile([{hipe,[{regalloc,linear_scan}]}]).
-export_type([abstract_clause/0, abstract_expr/0, abstract_form/0,
- error_info/0]).
+ abstract_type/0, error_info/0]).
+
+%% Start of Abstract Format
+
+-type anno() :: erl_anno:anno().
+
+-type abstract_form() :: af_module()
+ | af_behavior()
+ | af_behaviour()
+ | af_export()
+ | af_import()
+ | af_export_type()
+ | af_optional_callbacks()
+ | af_compile()
+ | af_file()
+ | af_record_decl()
+ | af_type_decl()
+ | af_function_spec()
+ | af_wild_attribute()
+ | af_function_decl().
+
+-type af_module() :: {'attribute', anno(), 'module', module()}.
+
+-type af_behavior() :: {'attribute', anno(), 'behavior', behaviour()}.
+
+-type af_behaviour() :: {'attribute', anno(), 'behaviour', behaviour()}.
+
+-type behaviour() :: atom().
+
+-type af_export() :: {'attribute', anno(), 'export', af_fa_list()}.
+
+-type af_import() :: {'attribute', anno(), 'import', af_fa_list()}.
+
+-type af_fa_list() :: [{function_name(), arity()}].
+
+-type af_export_type() :: {'attribute', anno(), 'export_type', af_ta_list()}.
+
+-type af_ta_list() :: [{type_name(), arity()}].
+
+-type af_optional_callbacks() ::
+ {'attribute', anno(), 'optional_callbacks', af_fa_list()}.
+
+-type af_compile() :: {'attribute', anno(), 'compile', any()}.
+
+-type af_file() :: {'attribute', anno(), 'file', {string(), anno()}}.
+
+-type af_record_decl() ::
+ {'attribute', anno(), 'record', {record_name(), [af_field_decl()]}}.
+
+-type af_field_decl() :: af_typed_field() | af_field().
+
+-type af_typed_field() ::
+ {'typed_record_field', af_field(), abstract_type()}.
+
+-type af_field() :: {'record_field', anno(), af_field_name()}
+ | {'record_field', anno(), af_field_name(), abstract_expr()}.
+
+-type af_type_decl() :: {'attribute', anno(), type_attr(),
+ {type_name(), abstract_type(), [af_variable()]}}.
+
+-type type_attr() :: 'opaque' | 'type'.
+
+-type af_function_spec() :: {'attribute', anno(), spec_attr(),
+ {{function_name(), arity()},
+ af_function_type_list()}}
+ | {'attribute', anno(), 'spec',
+ {{module(), function_name(), arity()},
+ af_function_type_list()}}.
+
+-type spec_attr() :: 'callback' | 'spec'.
+
+-type af_wild_attribute() :: {'attribute', anno(), atom(), any()}.
+
+-type af_function_decl() ::
+ {'function', anno(), function_name(), arity(), af_clause_seq()}.
+
+-type abstract_expr() :: af_literal()
+ | af_match(abstract_expr())
+ | af_variable()
+ | af_tuple(abstract_expr())
+ | af_nil()
+ | af_cons(abstract_expr())
+ | af_bin(abstract_expr())
+ | af_binary_op(abstract_expr())
+ | af_unary_op(abstract_expr())
+ | af_record_access(abstract_expr())
+ | af_record_update(abstract_expr())
+ | af_record_index()
+ | af_record_field_access(abstract_expr())
+ | af_map_access(abstract_expr())
+ | af_map_update(abstract_expr())
+ | af_catch()
+ | af_local_call()
+ | af_remote_call()
+ | af_list_comprehension()
+ | af_binary_comprehension()
+ | af_block()
+ | af_if()
+ | af_case()
+ | af_try()
+ | af_receive()
+ | af_local_fun()
+ | af_remote_fun()
+ | af_fun()
+ | af_named_fun().
+
+-type af_record_update(T) :: {'record',
+ anno(),
+ abstract_expr(),
+ record_name(),
+ [af_record_field(T)]}.
+
+-type af_catch() :: {'catch', anno(), abstract_expr()}.
+
+-type af_local_call() :: {'call', anno(), af_local_function(), af_args()}.
+
+-type af_remote_call() :: {'call', anno(), af_remote_function(), af_args()}.
+
+-type af_args() :: [abstract_expr()].
+
+-type af_local_function() :: abstract_expr().
+
+-type af_remote_function() ::
+ {'remote', anno(), abstract_expr(), abstract_expr()}.
+
+-type af_list_comprehension() ::
+ {'lc', anno(), af_template(), af_qualifier_seq()}.
+
+-type af_binary_comprehension() ::
+ {'bc', anno(), af_template(), af_qualifier_seq()}.
+
+-type af_template() :: abstract_expr().
+
+-type af_qualifier_seq() :: [af_qualifier()].
+
+-type af_qualifier() :: af_generator() | af_filter().
+
+-type af_generator() :: {'generate', anno(), af_pattern(), abstract_expr()}
+ | {'b_generate', anno(), af_pattern(), abstract_expr()}.
+
+-type af_filter() :: abstract_expr().
+
+-type af_block() :: {'block', anno(), af_body()}.
+
+-type af_if() :: {'if', anno(), af_clause_seq()}.
+
+-type af_case() :: {'case', anno(), abstract_expr(), af_clause_seq()}.
+
+-type af_try() :: {'try',
+ anno(),
+ af_body() | [],
+ af_clause_seq() | [],
+ af_clause_seq() | [],
+ af_body() | []}.
+
+-type af_clause_seq() :: [af_clause(), ...].
+
+-type af_receive() ::
+ {'receive', anno(), af_clause_seq()}
+ | {'receive', anno(), af_clause_seq(), abstract_expr(), af_body()}.
+
+-type af_local_fun() ::
+ {'fun', anno(), {'function', function_name(), arity()}}.
+
+-type af_remote_fun() ::
+ {'fun', anno(), {'function', module(), function_name(), arity()}}
+ | {'fun', anno(), {'function', af_atom(), af_atom(), af_integer()}}.
+
+-type af_fun() :: {'fun', anno(), {'clauses', af_clause_seq()}}.
+
+-type af_named_fun() :: {'named_fun', anno(), fun_name(), af_clause_seq()}.
+
+-type fun_name() :: atom().
+
+-type abstract_clause() :: af_clause().
+
+-type af_clause() ::
+ {'clause', anno(), [af_pattern()], af_guard_seq(), af_body()}.
+
+-type af_body() :: [abstract_expr(), ...].
+
+-type af_guard_seq() :: [af_guard()].
+
+-type af_guard() :: [af_guard_test(), ...].
+
+-type af_guard_test() :: af_literal()
+ | af_variable()
+ | af_tuple(af_guard_test())
+ | af_nil()
+ | af_cons(af_guard_test())
+ | af_bin(af_guard_test())
+ | af_binary_op(af_guard_test())
+ | af_unary_op(af_guard_test())
+ | af_record_access(af_guard_test())
+ | af_record_index()
+ | af_record_field_access(af_guard_test())
+ | af_map_access(abstract_expr()) % FIXME
+ | af_map_update(abstract_expr()) % FIXME
+ | af_guard_call()
+ | af_remote_guard_call().
+
+-type af_record_field_access(T) ::
+ {'record_field', anno(), T, record_name(), af_field_name()}.
+
+-type af_map_access(T) :: {'map', anno(), [af_map_field(T)]}.
+
+-type af_map_update(T) :: {'map', anno(), T, [af_map_field(T)]}.
+
+-type af_map_field(T) :: af_map_field_assoc(T) | af_map_field_exact(T).
+
+-type af_map_field_assoc(T) :: {'map_field_assoc', anno(), T, T}.
+
+-type af_map_field_exact(T) :: {'map_field_exact', anno(), T, T}.
+
+-type af_guard_call() :: {'call', anno(), function_name(), [af_guard_test()]}.
+
+-type af_remote_guard_call() ::
+ {'call', anno(),
+ {'remote', anno(), af_lit_atom('erlang'), af_atom()},
+ [af_guard_test()]}.
+
+-type af_pattern() :: af_literal()
+ | af_match(af_pattern())
+ | af_variable()
+ | af_tuple(af_pattern())
+ | af_nil()
+ | af_cons(af_pattern())
+ | af_bin(af_pattern())
+ | af_binary_op(af_pattern())
+ | af_unary_op(af_pattern())
+ | af_record_access(af_pattern())
+ | af_record_index()
+ | af_map_pattern().
+
+-type af_record_index() ::
+ {'record_index', anno(), record_name(), af_field_name()}.
+
+-type af_record_access(T) ::
+ {'record', anno(), record_name(), [af_record_field(T)]}.
+
+-type af_record_field(T) :: {'record_field', anno(), af_field_name(), T}.
+
+-type af_map_pattern() ::
+ {'map', anno(), [af_map_field_exact(abstract_expr)]}. % FIXME?
+
+-type abstract_type() :: af_annotated_type()
+ | af_atom()
+ | af_bitstring_type()
+ | af_empty_list_type()
+ | af_fun_type()
+ | af_integer_range_type()
+ | af_map_type()
+ | af_predefined_type()
+ | af_record_type()
+ | af_remote_type()
+ | af_singleton_integer_type()
+ | af_tuple_type()
+ | af_type_union()
+ | af_type_variable()
+ | af_user_defined_type().
+
+-type af_annotated_type() ::
+ {'ann_type', anno(), [af_anno() | abstract_type()]}. % [Var, Type]
+
+-type af_anno() :: af_variable().
+
+-type af_bitstring_type() ::
+ {'type', anno(), 'binary', [af_singleton_integer_type()]}.
+
+-type af_empty_list_type() :: {'type', anno(), 'nil', []}.
+
+-type af_fun_type() :: {'type', anno(), 'fun', []}
+ | {'type', anno(), 'fun', [{'type', anno(), 'any'} |
+ abstract_type()]}
+ | {'type', anno(), 'fun', af_function_type()}.
+
+-type af_integer_range_type() ::
+ {'type', anno(), 'range', [af_singleton_integer_type()]}.
+
+-type af_map_type() :: {'type', anno(), 'map', 'any'}
+ | {'type', anno(), 'map', [af_map_pair_type()]}.
+
+-type af_map_pair_type() ::
+ {'type', anno(), 'map_field_assoc', [abstract_type()]}.
+
+-type af_predefined_type() ::
+ {'type', anno(), type_name(), [abstract_type()]}.
+
+-type af_record_type() ::
+ {'type', anno(), 'record', [(Name :: af_atom()) % [Name, T1, ... Tk]
+ | af_record_field_type()]}.
+
+-type af_record_field_type() ::
+ {'type', anno(), 'field_type', [(Name :: af_atom()) |
+ abstract_type()]}. % [Name, Type]
+
+-type af_remote_type() ::
+ {'remote_type', anno(), [(Module :: af_atom()) |
+ (TypeName :: af_atom()) |
+ [abstract_type()]]}. % [Module, Name, [T]]
+
+-type af_tuple_type() :: {'type', anno(), 'tuple', 'any'}
+ | {'type', anno(), 'tuple', [abstract_type()]}.
+
+-type af_type_union() :: {'type', anno(), 'union', [abstract_type()]}.
+
+-type af_type_variable() :: {'var', anno(), atom()}. % except '_'
+
+-type af_user_defined_type() ::
+ {'user_type', anno(), type_name(), [abstract_type()]}.
+
+-type af_function_type_list() :: [af_constrained_function_type() |
+ af_function_type()].
+
+-type af_constrained_function_type() ::
+ {'type', anno(), 'bounded_fun', [af_function_type() | % [Ft, Fc]
+ af_function_constraint()]}.
+
+-type af_function_type() ::
+ {'type', anno(), 'fun',
+ [{'type', anno(), 'product', [abstract_type()]} | abstract_type()]}.
+
+-type af_function_constraint() :: [af_constraint()].
+
+-type af_constraint() :: {'type', anno(), 'constraint',
+ af_lit_atom('is_subtype'),
+ [af_type_variable() | abstract_type()]}. % [V, T]
+
+-type af_singleton_integer_type() :: af_integer()
+ | af_unary_op(af_singleton_integer_type())
+ | af_binary_op(af_singleton_integer_type()).
+
+-type af_literal() :: af_atom() | af_integer() | af_float() | af_string().
+
+-type af_atom() :: af_lit_atom(atom()).
+
+-type af_lit_atom(A) :: {'atom', anno(), A}.
+
+-type af_integer() :: {'integer', anno(), non_neg_integer()}.
+
+-type af_float() :: {'float', anno(), float()}.
+
+-type af_string() :: {'string', anno(), string()}.
+
+-type af_match(T) :: {'match', anno(), af_pattern(), T}.
+
+-type af_variable() :: {'var', anno(), atom()}. % | af_anon_variable()
+
+%-type af_anon_variable() :: {'var', anno(), '_'}.
+
+-type af_tuple(T) :: {'tuple', anno(), [T]}.
+
+-type af_nil() :: {'nil', anno()}.
+
+-type af_cons(T) :: {'cons', anno(), T, T}.
+
+-type af_bin(T) :: {'bin', anno(), [af_binelement(T)]}.
+
+-type af_binelement(T) :: {'bin_element',
+ anno(),
+ T,
+ af_binelement_size(),
+ type_specifier_list()}.
+
+-type af_binelement_size() :: 'default' | abstract_expr().
+
+-type af_binary_op(T) :: {'op', anno(), binary_op(), T, T}.
+
+-type binary_op() :: '/' | '*' | 'div' | 'rem' | 'band' | 'and' | '+' | '-'
+ | 'bor' | 'bxor' | 'bsl' | 'bsr' | 'or' | 'xor' | '++'
+ | '--' | '==' | '/=' | '=<' | '<' | '>=' | '>' | '=:='
+ | '=/='.
+
+-type af_unary_op(T) :: {'op', anno(), unary_op(), T}.
+
+-type unary_op() :: '+' | '*' | 'bnot' | 'not'.
+
+%% See also lib/stdlib/{src/erl_bits.erl,include/erl_bits.hrl}.
+-type type_specifier_list() :: 'default' | [type_specifier(), ...].
+
+-type type_specifier() :: type()
+ | signedness()
+ | endianness()
+ | unit().
+
+-type type() :: 'integer'
+ | 'float'
+ | 'binary'
+ | 'bytes'
+ | 'bitstring'
+ | 'bits'
+ | 'utf8'
+ | 'utf16'
+ | 'utf32'.
+
+-type signedness() :: 'signed' | 'unsigned'.
+
+-type endianness() :: 'big' | 'little' | 'native'.
+
+-type unit() :: {'unit', 1..256}.
+
+-type record_name() :: atom().
+
+-type af_field_name() :: af_atom().
+
+-type function_name() :: atom().
+
+-type type_name() :: atom().
+
+%% End of Abstract Format
%% XXX. To be refined.
--type abstract_clause() :: term().
--type abstract_expr() :: term().
--type abstract_form() :: term().
-type error_description() :: term().
-type error_info() :: {erl_anno:line(), module(), error_description()}.
-type token() :: erl_scan:token().
@@ -639,14 +1036,8 @@ build_type_spec({Kind,Aa}, {SpecFun, TypeSpecs})
{atom, _, Fun} ->
{Fun, find_arity_from_specs(TypeSpecs)};
{{atom,_, Mod}, {atom,_, Fun}} ->
- {Mod,Fun,find_arity_from_specs(TypeSpecs)};
- {{atom, _, Fun}, {integer, _, Arity}} ->
- %% Old style spec. Allow this for now.
- {Fun,Arity};
- {{atom,_, Mod}, {atom, _, Fun}, {integer, _, Arity}} ->
- %% Old style spec. Allow this for now.
- {Mod,Fun,Arity}
- end,
+ {Mod,Fun,find_arity_from_specs(TypeSpecs)}
+ end,
{attribute,Aa,Kind,{NewSpecFun, TypeSpecs}}.
find_arity_from_specs([Spec|_]) ->
@@ -795,31 +1186,11 @@ record_fields([{match,_Am,{atom,Aa,A},Expr}|Fields]) ->
[{record_field,Aa,{atom,Aa,A},Expr}|record_fields(Fields)];
record_fields([{typed,Expr,TypeInfo}|Fields]) ->
[Field] = record_fields([Expr]),
- TypeInfo1 =
- case Expr of
- {match, _, _, _} -> TypeInfo; %% If we have an initializer.
- {atom, Aa, _} ->
- case has_undefined(TypeInfo) of
- false ->
- lift_unions(abstract2(undefined, Aa), TypeInfo);
- true ->
- TypeInfo
- end
- end,
- [{typed_record_field,Field,TypeInfo1}|record_fields(Fields)];
+ [{typed_record_field,Field,TypeInfo}|record_fields(Fields)];
record_fields([Other|_Fields]) ->
ret_err(?anno(Other), "bad record field");
record_fields([]) -> [].
-has_undefined({atom,_,undefined}) ->
- true;
-has_undefined({ann_type,_,[_,T]}) ->
- has_undefined(T);
-has_undefined({type,_,union,Ts}) ->
- lists:any(fun has_undefined/1, Ts);
-has_undefined(_) ->
- false.
-
term(Expr) ->
try normalise(Expr)
catch _:_R -> ret_err(?anno(Expr), "bad attribute")
@@ -1118,33 +1489,16 @@ type_preop_prec('-') -> {600,700};
type_preop_prec('bnot') -> {600,700};
type_preop_prec('#') -> {700,800}.
-%%% [Experimental]. The parser just copies the attributes of the
-%%% scanner tokens to the abstract format. This design decision has
-%%% been hidden to some extent: use set_line() and get_attribute() to
-%%% access the second element of (almost all) of the abstract format
-%%% tuples. A typical use is to negate line numbers to prevent the
-%%% compiler from emitting warnings and errors. The second element can
-%%% (of course) be set to any value, but then these functions no
-%%% longer apply. To get all present attributes as a property list
-%%% get_attributes() should be used.
-
--compile({nowarn_deprecated_function,{erl_scan,set_attribute,3}}).
-set_line(L, F) ->
- erl_scan:set_attribute(line, L, F).
-
--compile({nowarn_deprecated_function,{erl_scan,attributes_info,2}}).
-get_attribute(L, Name) ->
- erl_scan:attributes_info(L, Name).
-
--compile({nowarn_deprecated_function,{erl_scan,attributes_info,1}}).
-get_attributes(L) ->
- erl_scan:attributes_info(L).
+-type erl_parse_tree() :: abstract_clause()
+ | abstract_expr()
+ | abstract_form()
+ | abstract_type().
-spec map_anno(Fun, Abstr) -> NewAbstr when
Fun :: fun((Anno) -> Anno),
Anno :: erl_anno:anno(),
- Abstr :: abstract_form() | abstract_expr(),
- NewAbstr :: abstract_form() | abstract_expr().
+ Abstr :: erl_parse_tree(),
+ NewAbstr :: erl_parse_tree().
map_anno(F0, Abstr) ->
F = fun(A, Acc) -> {F0(A), Acc} end,
@@ -1157,8 +1511,8 @@ map_anno(F0, Abstr) ->
Acc0 :: term(),
AccIn :: term(),
AccOut :: term(),
- Abstr :: abstract_form() | abstract_expr(),
- NewAbstr :: abstract_form() | abstract_expr().
+ Abstr :: erl_parse_tree(),
+ NewAbstr :: erl_parse_tree().
fold_anno(F0, Acc0, Abstr) ->
F = fun(A, Acc) -> {A, F0(A, Acc)} end,
@@ -1172,26 +1526,26 @@ fold_anno(F0, Acc0, Abstr) ->
Acc1 :: term(),
AccIn :: term(),
AccOut :: term(),
- Abstr :: abstract_form() | abstract_expr(),
- NewAbstr :: abstract_form() | abstract_expr().
+ Abstr :: erl_parse_tree(),
+ NewAbstr :: erl_parse_tree().
mapfold_anno(F, Acc0, Abstr) ->
modify_anno1(Abstr, Acc0, F).
-spec new_anno(Term) -> Abstr when
Term :: term(),
- Abstr :: abstract_form() | abstract_expr().
+ Abstr :: erl_parse_tree().
new_anno(Term) ->
map_anno(fun erl_anno:new/1, Term).
-spec anno_to_term(Abstr) -> term() when
- Abstr :: abstract_form() | abstract_expr().
+ Abstr :: erl_parse_tree().
anno_to_term(Abstract) ->
map_anno(fun erl_anno:to_term/1, Abstract).
--spec anno_from_term(Term) -> abstract_form() | abstract_expr() when
+-spec anno_from_term(Term) -> erl_parse_tree() when
Term :: term().
anno_from_term(Term) ->
diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl
index d2f53816b8..47223b129c 100644
--- a/lib/stdlib/src/erl_scan.erl
+++ b/lib/stdlib/src/erl_scan.erl
@@ -52,25 +52,15 @@
%%% External exports
-export([string/1,string/2,string/3,tokens/3,tokens/4,
- format_error/1,reserved_word/1,
- token_info/1,token_info/2,
- attributes_info/1,attributes_info/2,set_attribute/3]).
+ format_error/1,reserved_word/1]).
-export([column/1,end_location/1,line/1,location/1,text/1,
category/1,symbol/1]).
--deprecated([{attributes_info, 1, next_major_release},
- {attributes_info, 2, next_major_release},
- {set_attribute, 3, next_major_release},
- {token_info, 1, next_major_release},
- {token_info, 2, next_major_release}]).
-
%%% Private
-export([continuation_location/1]).
-export_type([error_info/0,
- line/0,
- location/0,
options/0,
return_cont/0,
token/0,
@@ -85,29 +75,18 @@
-define(ALINE(L), is_integer(L)).
-define(STRING(S), is_list(S)).
-define(RESWORDFUN(F), is_function(F, 1)).
--define(SETATTRFUN(F), is_function(F, 1)).
-type category() :: atom().
--type column() :: pos_integer(). % Deprecated
--type line() :: integer(). % Deprecated
--type location() :: line() | {line(),column()}. % Deprecated
-type resword_fun() :: fun((atom()) -> boolean()).
-type option() :: 'return' | 'return_white_spaces' | 'return_comments'
| 'text' | {'reserved_word_fun', resword_fun()}.
-type options() :: option() | [option()].
-type symbol() :: atom() | float() | integer() | string().
--type info_line() :: integer() | term().
--type attributes_data()
- :: [{'column', column()} | {'line', info_line()} | {'text', string()}]
- | {line(), column()}.
-%% The fact that {line(),column()} is a possible attributes() type
-%% is hidden.
--type attributes() :: line() | attributes_data().
--type token() :: {category(), attributes(), symbol()}
- | {category(), attributes()}.
+-type token() :: {category(), Anno :: erl_anno:anno(), symbol()}
+ | {category(), Anno :: erl_anno:anno()}.
-type tokens() :: [token()].
-type error_description() :: term().
--type error_info() :: {location(), module(), error_description()}.
+-type error_info() :: {erl_anno:location(), module(), error_description()}.
%%% Local record.
-record(erl_scan,
@@ -136,8 +115,8 @@ format_error(Other) ->
String :: string(),
Return :: {'ok', Tokens :: tokens(), EndLocation}
| {'error', ErrorInfo :: error_info(), ErrorLocation},
- EndLocation :: location(),
- ErrorLocation :: location().
+ EndLocation :: erl_anno:location(),
+ ErrorLocation :: erl_anno:location().
string(String) ->
string(String, 1, []).
@@ -145,9 +124,9 @@ string(String) ->
String :: string(),
Return :: {'ok', Tokens :: tokens(), EndLocation}
| {'error', ErrorInfo :: error_info(), ErrorLocation},
- StartLocation :: location(),
- EndLocation :: location(),
- ErrorLocation :: location().
+ StartLocation :: erl_anno:location(),
+ EndLocation :: erl_anno:location(),
+ ErrorLocation :: erl_anno:location().
string(String, StartLocation) ->
string(String, StartLocation, []).
@@ -156,9 +135,9 @@ string(String, StartLocation) ->
Options :: options(),
Return :: {'ok', Tokens :: tokens(), EndLocation}
| {'error', ErrorInfo :: error_info(), ErrorLocation},
- StartLocation :: location(),
- EndLocation :: location(),
- ErrorLocation :: location().
+ StartLocation :: erl_anno:location(),
+ EndLocation :: erl_anno:location(),
+ ErrorLocation :: erl_anno:location().
string(String, Line, Options) when ?STRING(String), ?ALINE(Line) ->
string1(String, options(Options), Line, no_col, []);
string(String, {Line,Column}, Options) when ?STRING(String),
@@ -167,20 +146,23 @@ string(String, {Line,Column}, Options) when ?STRING(String),
string1(String, options(Options), Line, Column, []).
-type char_spec() :: string() | 'eof'.
--type cont_fun() :: fun((char_spec(), #erl_scan{}, line(), column(),
+-type cont_fun() :: fun((char_spec(), #erl_scan{},
+ erl_anno:line(), erl_anno:column(),
tokens(), any()) -> any()).
-opaque return_cont() :: {erl_scan_continuation,
- string(), column(), tokens(), line(),
+ string(), erl_anno:column(), tokens(),
+ erl_anno:line(),
#erl_scan{}, any(), cont_fun()}.
--type tokens_result() :: {'ok', Tokens :: tokens(), EndLocation :: location()}
- | {'eof', EndLocation :: location()}
+-type tokens_result() :: {'ok', Tokens :: tokens(),
+ EndLocation :: erl_anno:location()}
+ | {'eof', EndLocation :: erl_anno:location()}
| {'error', ErrorInfo :: error_info(),
- EndLocation :: location()}.
+ EndLocation :: erl_anno:location()}.
-spec tokens(Continuation, CharSpec, StartLocation) -> Return when
Continuation :: return_cont() | [],
CharSpec :: char_spec(),
- StartLocation :: location(),
+ StartLocation :: erl_anno:location(),
Return :: {'done',Result :: tokens_result(),LeftOverChars :: char_spec()}
| {'more', Continuation1 :: return_cont()}.
tokens(Cont, CharSpec, StartLocation) ->
@@ -189,7 +171,7 @@ tokens(Cont, CharSpec, StartLocation) ->
-spec tokens(Continuation, CharSpec, StartLocation, Options) -> Return when
Continuation :: return_cont() | [],
CharSpec :: char_spec(),
- StartLocation :: location(),
+ StartLocation :: erl_anno:location(),
Options :: options(),
Return :: {'done',Result :: tokens_result(),LeftOverChars :: char_spec()}
| {'more', Continuation1 :: return_cont()}.
@@ -257,155 +239,6 @@ symbol({_Category,_Anno,Symbol}) ->
symbol(T) ->
erlang:error(badarg, [T]).
--type attribute_item() :: 'column' | 'length' | 'line'
- | 'location' | 'text'.
--type info_location() :: location() | term().
--type attribute_info() :: {'column', column()}| {'length', pos_integer()}
- | {'line', info_line()}
- | {'location', info_location()}
- | {'text', string()}.
--type token_item() :: 'category' | 'symbol' | attribute_item().
--type token_info() :: {'category', category()} | {'symbol', symbol()}
- | attribute_info().
-
--spec token_info(Token) -> TokenInfo when
- Token :: token(),
- TokenInfo :: [TokenInfoTuple :: token_info()].
-token_info(Token) ->
- Items = [category,column,length,line,symbol,text], % undefined order
- token_info(Token, Items).
-
--spec token_info(Token, TokenItem) -> TokenInfoTuple | 'undefined' when
- Token :: token(),
- TokenItem :: token_item(),
- TokenInfoTuple :: token_info();
- (Token, TokenItems) -> TokenInfo when
- Token :: token(),
- TokenItems :: [TokenItem :: token_item()],
- TokenInfo :: [TokenInfoTuple :: token_info()].
-token_info(_Token, []) ->
- [];
-token_info(Token, [Item|Items]) when is_atom(Item) ->
- case token_info(Token, Item) of
- undefined ->
- token_info(Token, Items);
- TokenInfo when is_tuple(TokenInfo) ->
- [TokenInfo|token_info(Token, Items)]
- end;
-token_info({Category,_Attrs}, category=Item) ->
- {Item,Category};
-token_info({Category,_Attrs,_Symbol}, category=Item) ->
- {Item,Category};
-token_info({Category,_Attrs}, symbol=Item) ->
- {Item,Category};
-token_info({_Category,_Attrs,Symbol}, symbol=Item) ->
- {Item,Symbol};
-token_info({_Category,Attrs}, Item) ->
- attributes_info(Attrs, Item);
-token_info({_Category,Attrs,_Symbol}, Item) ->
- attributes_info(Attrs, Item).
-
--spec attributes_info(Attributes) -> AttributesInfo when
- Attributes :: attributes(),
- AttributesInfo :: [AttributeInfoTuple :: attribute_info()].
-attributes_info(Attributes) ->
- Items = [column,length,line,text], % undefined order
- attributes_info(Attributes, Items).
-
--spec attributes_info
- (Attributes, AttributeItem) -> AttributeInfoTuple | 'undefined' when
- Attributes :: attributes(),
- AttributeItem :: attribute_item(),
- AttributeInfoTuple :: attribute_info();
- (Attributes, AttributeItems) -> AttributeInfo when
- Attributes :: attributes(),
- AttributeItems :: [AttributeItem :: attribute_item()],
- AttributeInfo :: [AttributeInfoTuple :: attribute_info()].
-attributes_info(_Attrs, []) ->
- [];
-attributes_info(Attrs, [A|As]) when is_atom(A) ->
- case attributes_info(Attrs, A) of
- undefined ->
- attributes_info(Attrs, As);
- AttributeInfo when is_tuple(AttributeInfo) ->
- [AttributeInfo|attributes_info(Attrs, As)]
- end;
-attributes_info({Line,Column}, column=Item) when ?ALINE(Line),
- ?COLUMN(Column) ->
- {Item,Column};
-attributes_info(Line, column) when ?ALINE(Line) ->
- undefined;
-attributes_info(Attrs, column=Item) ->
- case attr_info(Attrs, Item) of
- undefined ->
- case erl_anno:column(Attrs) of
- undefined ->
- undefined;
- Column ->
- {Item,Column}
- end;
- T ->
- T
- end;
-attributes_info(Attrs, length=Item) ->
- case attributes_info(Attrs, text) of
- undefined ->
- undefined;
- {text,Text} ->
- {Item,length(Text)}
- end;
-attributes_info(Line, line=Item) when ?ALINE(Line) ->
- {Item,Line};
-attributes_info({Line,Column}, line=Item) when ?ALINE(Line),
- ?COLUMN(Column) ->
- {Item,Line};
-attributes_info(Attrs, line=Item) ->
- case attr_info(Attrs, Item) of
- undefined ->
- case attr_info(Attrs, location) of
- {location,{Line,_Column}} ->
- {Item,Line};
- {location,Line} ->
- {Item,Line};
- undefined ->
- undefined
- end;
- T ->
- T
- end;
-attributes_info({Line,Column}=Location, location=Item) when ?ALINE(Line),
- ?COLUMN(Column) ->
- {Item,Location};
-attributes_info(Line, location=Item) when ?ALINE(Line) ->
- {Item,Line};
-attributes_info(Attrs, location=Item) ->
- {line,Line} = attributes_info(Attrs, line),
- case attributes_info(Attrs, column) of
- undefined ->
- %% If set_attribute() has assigned a term such as {17,42}
- %% to 'line', then Line will look like {Line,Column}. One
- %% should not use 'location' but 'line' and 'column' in
- %% such special cases.
- {Item,Line};
- {column,Column} ->
- {Item,{Line,Column}}
- end;
-attributes_info({Line,Column}, text) when ?ALINE(Line), ?COLUMN(Column) ->
- undefined;
-attributes_info(Line, text) when ?ALINE(Line) ->
- undefined;
-attributes_info(Attrs, text=Item) ->
- attr_info(Attrs, Item);
-attributes_info(T1, T2) ->
- erlang:error(badarg, [T1,T2]).
-
--spec set_attribute(AttributeItem, Attributes, SetAttributeFun) -> Attributes when
- AttributeItem :: 'line',
- Attributes :: attributes(),
- SetAttributeFun :: fun((info_line()) -> info_line()).
-set_attribute(Tag, Attributes, Fun) when ?SETATTRFUN(Fun) ->
- set_attr(Tag, Attributes, Fun).
-
%%%
%%% Local functions
%%%
@@ -471,62 +304,6 @@ expand_opt(return, Os) ->
expand_opt(O, Os) ->
[O|Os].
-attr_info(Attrs, Item) ->
- try lists:keyfind(Item, 1, Attrs) of
- {_Item, _Value} = T ->
- T;
- false ->
- undefined
- catch
- _:_ ->
- erlang:error(badarg, [Attrs, Item])
- end.
-
--spec set_attr('line', attributes(), fun((line()) -> line())) -> attributes().
-
-set_attr(line, Line, Fun) when ?ALINE(Line) ->
- Ln = Fun(Line),
- if
- ?ALINE(Ln) ->
- Ln;
- true ->
- [{line,Ln}]
- end;
-set_attr(line, {Line,Column}, Fun) when ?ALINE(Line), ?COLUMN(Column) ->
- Ln = Fun(Line),
- if
- ?ALINE(Ln) ->
- {Ln,Column};
- true ->
- [{line,Ln},{column,Column}]
- end;
-set_attr(line=Tag, Attrs, Fun) when is_list(Attrs) ->
- case lists:keyfind(Tag, 1, Attrs) of
- {line,Line} ->
- case lists:keyreplace(Tag, 1, Attrs, {line,Fun(Line)}) of
- [{line,Ln}] when ?ALINE(Ln) ->
- Ln;
- As ->
- As
- end;
- false ->
- {location, Location} = lists:keyfind(location, 1, Attrs),
- Ln = case Location of
- {Line,Column} when ?ALINE(Line), ?COLUMN(Column) ->
- {Fun(Line),Column};
- _ ->
- Fun(Location)
- end,
- case lists:keyreplace(location, 1, Attrs, {location,Ln}) of
- [{location,Ln}] when ?ALINE(Ln) ->
- Ln;
- As ->
- As
- end
- end;
-set_attr(T1, T2, T3) ->
- erlang:error(badarg, [T1,T2,T3]).
-
tokens1(Cs, St, Line, Col, Toks, Fun, Any) when ?STRING(Cs); Cs =:= eof ->
case Fun(Cs, St, Line, Col, Toks, Any) of
{more,{Cs0,Ncol,Ntoks,Nline,Nany,Nfun}} ->
diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl
index 41b49f4a86..b8ce311c35 100644
--- a/lib/stdlib/src/escript.erl
+++ b/lib/stdlib/src/escript.erl
@@ -38,7 +38,7 @@
-record(state, {file :: file:filename(),
module :: module(),
forms_or_bin,
- source :: source(),
+ source :: source() | 'undefined',
n_errors :: non_neg_integer(),
mode :: mode(),
exports_main :: boolean(),
@@ -49,9 +49,9 @@
-type emu_args() :: string().
-record(sections, {type,
- shebang :: shebang(),
- comment :: comment(),
- emu_args :: emu_args(),
+ shebang :: shebang() | 'undefined',
+ comment :: comment() | 'undefined',
+ emu_args :: emu_args() | 'undefined',
body}).
-record(extract_options, {compile_source}).
diff --git a/lib/stdlib/src/file_sorter.erl b/lib/stdlib/src/file_sorter.erl
index 0d50392b96..3aeaff8dc4 100644
--- a/lib/stdlib/src/file_sorter.erl
+++ b/lib/stdlib/src/file_sorter.erl
@@ -307,7 +307,6 @@ options(Option) ->
options([{format, Format} | L], Opts) when Format =:= binary;
Format =:= term;
- is_function(Format),
is_function(Format, 1) ->
options(L, Opts#opts{format = Format});
options([{format, binary_term} | L], Opts) ->
@@ -326,7 +325,7 @@ options([{tmpdir, Dir} | L], Opts) ->
FileName ->
options(L, Opts#opts{tmpdir = {dir, FileName}})
end;
-options([{order, Fun} | L], Opts) when is_function(Fun), is_function(Fun, 2) ->
+options([{order, Fun} | L], Opts) when is_function(Fun, 2) ->
options(L, Opts#opts{order = Fun});
options([{order, Order} | L], Opts) when Order =:= ascending;
Order =:= descending ->
@@ -411,7 +410,7 @@ merge_terms_fun(RFun) ->
case RFun(read) of
end_of_input ->
eof;
- {Objs, NRFun} when is_function(NRFun), is_function(NRFun, 1) ->
+ {Objs, NRFun} when is_function(NRFun, 1) ->
{_, [], Ts, _} = fun_objs(Objs, [], 0, ?MAXSIZE, I, W),
{{I, Ts, ?CHUNKSIZE}, merge_terms_fun(NRFun)};
Error ->
@@ -427,13 +426,12 @@ merge_bins_fun(FileName) ->
Fun(A)
end.
-wrap_output_terms(term, OutFun, _Z) when is_function(OutFun),
- is_function(OutFun, 1) ->
+wrap_output_terms(term, OutFun, _Z) when is_function(OutFun, 1) ->
{fun_wterms(OutFun), true};
wrap_output_terms(term, File, Z) when File =/= undefined ->
{file_wterms(name, File, Z++[write]), false};
wrap_output_terms(_Format, Output, _Z) ->
- {Output, is_function(Output) and is_function(Output, 1)}.
+ {Output, is_function(Output, 1)}.
binary_term_fun() ->
fun binary_to_term/1.
@@ -1311,8 +1309,7 @@ infun(W) ->
{end_of_input, W1};
{end_of_input, Value} ->
{end_of_input, W1#w{inout_value = {value, Value}}};
- {Objs, NFun} when is_function(NFun),
- is_function(NFun, 1),
+ {Objs, NFun} when is_function(NFun, 1),
is_list(Objs) ->
{cont, W#w{in = NFun}, Objs};
Error ->
@@ -1335,7 +1332,7 @@ outfun(A, W) ->
try (W#w.out)(A) of
Reply when A =:= close ->
Reply;
- NF when is_function(NF), is_function(NF, 1) ->
+ NF when is_function(NF, 1) ->
W#w{out = NF};
Error ->
error(Error, W1)
@@ -1360,7 +1357,7 @@ is_keyposs([Bad | _]) ->
is_keyposs(Bad) ->
{badarg, Bad}.
-is_input(Fun) when is_function(Fun), is_function(Fun, 1) ->
+is_input(Fun) when is_function(Fun, 1) ->
{true, Fun};
is_input(Files) ->
is_files(Files).
@@ -1380,7 +1377,7 @@ is_files([], L) ->
is_files(Bad, _L) ->
{badarg, Bad}.
-maybe_output(Fun) when is_function(Fun), is_function(Fun, 1) ->
+maybe_output(Fun) when is_function(Fun, 1) ->
{true, Fun};
maybe_output(File) ->
case read_file_info(File) of
@@ -1589,7 +1586,6 @@ fun_rterms(InFun) ->
(read) ->
case InFun(read) of
{Ts, NInFun} when is_list(Ts),
- is_function(NInFun),
is_function(NInFun, 1) ->
{to_bin(Ts, []), fun_rterms(NInFun)};
Else ->
@@ -1602,7 +1598,7 @@ fun_wterms(OutFun) ->
OutFun(close);
(L) ->
case OutFun(wterms_arg(L)) of
- NOutFun when is_function(NOutFun), is_function(NOutFun, 1) ->
+ NOutFun when is_function(NOutFun, 1) ->
fun_wterms(NOutFun);
Else ->
Else
diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl
index 008beb8b67..d921a69108 100644
--- a/lib/stdlib/src/filename.erl
+++ b/lib/stdlib/src/filename.erl
@@ -36,6 +36,7 @@
extension/1, join/1, join/2, pathtype/1,
rootname/1, rootname/2, split/1, nativename/1]).
-export([find_src/1, find_src/2, flatten/1]).
+-export([basedir/2, basedir/3]).
%% Undocumented and unsupported exports.
-export([append/2]).
@@ -139,6 +140,7 @@ absname_join(AbsBase, Name) ->
-spec basename(Filename) -> file:filename_all() when
Filename :: file:name_all().
+
basename(Name) when is_binary(Name) ->
case os:type() of
{win32,_} ->
@@ -954,3 +956,161 @@ filename_string_to_binary(List) ->
Bin
end.
+%% Application Base Directories
+%% basedir
+%% http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
+
+-type basedir_type() :: 'user_cache' | 'user_config' | 'user_data'
+ | 'user_log'
+ | 'site_config' | 'site_data'.
+
+-spec basedir(Type,Application) -> file:filename_all() when
+ Type :: basedir_type(),
+ Application :: string() | binary().
+
+basedir(Type,Application) when is_atom(Type), is_list(Application) orelse
+ is_binary(Application) ->
+ basedir(Type, Application, #{}).
+
+-spec basedir(Type,Application,Opts) -> file:filename_all() when
+ Type :: basedir_type(),
+ Application :: string() | binary(),
+ Opts :: #{author => string() | binary(),
+ os => 'windows' | 'darwin' | 'linux',
+ version => string() | binary()}.
+
+basedir(Type,Application,Opts) when is_atom(Type), is_map(Opts),
+ is_list(Application) orelse
+ is_binary(Application) ->
+ Os = basedir_os_from_opts(Opts),
+ Name = basedir_name_from_opts(Os,Application,Opts),
+ Base = basedir_from_os(Type,Os),
+ case {Type,Os} of
+ {user_log,linux} ->
+ filename:join([Base,Name,"log"]);
+ {user_log,windows} ->
+ filename:join([Base,Name,"Logs"]);
+ {user_cache,windows} ->
+ filename:join([Base,Name,"Cache"]);
+ {Type,_} when Type =:= site_config orelse Type =:= site_data ->
+ [filename:join([B,Name]) || B <- Base];
+ _ ->
+ filename:join([Base,Name])
+ end.
+
+basedir_os_from_opts(#{os := linux}) -> linux;
+basedir_os_from_opts(#{os := windows}) -> windows;
+basedir_os_from_opts(#{os := darwin}) -> darwin;
+basedir_os_from_opts(#{}) -> basedir_os_type().
+
+basedir_name_from_opts(windows,App,#{author:=Author,version:=Vsn}) ->
+ filename:join([Author,App,Vsn]);
+basedir_name_from_opts(windows,App,#{author:=Author}) ->
+ filename:join([Author,App]);
+basedir_name_from_opts(_,App,#{version:=Vsn}) ->
+ filename:join([App,Vsn]);
+basedir_name_from_opts(_,App,_) ->
+ App.
+
+basedir_from_os(Type,Os) ->
+ case Os of
+ linux -> basedir_linux(Type);
+ darwin -> basedir_darwin(Type);
+ windows -> basedir_windows(Type)
+ end.
+
+-define(basedir_linux_user_data, ".local/share").
+-define(basedir_linux_user_config, ".config").
+-define(basedir_linux_user_cache, ".cache").
+-define(basedir_linux_user_log, ".cache"). %% .cache/App/log
+-define(basedir_linux_site_data, "/usr/local/share/:/usr/share/").
+-define(basedir_linux_site_config, "/etc/xdg").
+
+basedir_linux(Type) ->
+ case Type of
+ user_data -> getenv("XDG_DATA_HOME", ?basedir_linux_user_data, true);
+ user_config -> getenv("XDG_CONFIG_HOME",?basedir_linux_user_config,true);
+ user_cache -> getenv("XDG_CACHE_HOME", ?basedir_linux_user_cache, true);
+ user_log -> getenv("XDG_CACHE_HOME", ?basedir_linux_user_log, true);
+ site_data ->
+ Base = getenv("XDG_DATA_DIRS",?basedir_linux_site_data,false),
+ string:tokens(Base,":");
+ site_config ->
+ Base = getenv("XDG_CONFIG_DIRS",?basedir_linux_site_config,false),
+ string:tokens(Base,":")
+ end.
+
+-define(basedir_darwin_user_data, "Library/Application Support").
+-define(basedir_darwin_user_config, "Library/Application Support").
+-define(basedir_darwin_user_cache, "Library/Caches").
+-define(basedir_darwin_user_log, "Library/Logs").
+-define(basedir_darwin_site_data, "/Library/Application Support").
+-define(basedir_darwin_site_config, "/Library/Application Support").
+
+basedir_darwin(Type) ->
+ case Type of
+ user_data -> basedir_join_home(?basedir_darwin_user_data);
+ user_config -> basedir_join_home(?basedir_darwin_user_config);
+ user_cache -> basedir_join_home(?basedir_darwin_user_cache);
+ user_log -> basedir_join_home(?basedir_darwin_user_log);
+ site_data -> [?basedir_darwin_site_data];
+ site_config -> [?basedir_darwin_site_config]
+ end.
+
+%% On Windows:
+%% ex. C:\Users\egil\AppData\Local\Ericsson\Erlang
+%% %LOCALAPPDATA% is defined on Windows 7 and onwards
+%% %APPDATA% is used instead of %LOCALAPPDATA% if it's not defined.
+%% %APPDATA% is used for roaming, i.e. for user_config on Windows 7 and beyond.
+%%
+%% user_data %LOCALAPPDATA%[/$author]/$appname[/$version]
+%% user_config %APPDATA%[/$author]/$appname[/$version]
+%% user_cache %LOCALAPPDATA%[/$author]/$appname[/$version]/Cache
+%% user_log %LOCALAPPDATA%[/$author]/$appname[/$version]/Logs
+
+basedir_windows(Type) ->
+ %% If LOCALAPPDATA is not defined we are likely on an
+ %% XP machine. Use APPDATA instead.
+ AppData = basedir_windows_appdata(),
+ case Type of
+ user_data -> getenv("LOCALAPPDATA", AppData);
+ user_config -> AppData;
+ user_cache -> getenv("LOCALAPPDATA", AppData);
+ user_log -> getenv("LOCALAPPDATA", AppData);
+ site_data -> [];
+ site_config -> []
+ end.
+
+basedir_windows_appdata() ->
+ case os:getenv("APPDATA") of
+ Invalid when Invalid =:= false orelse Invalid =:= [] ->
+ erlang:error(noappdata);
+ Val -> Val
+ end.
+
+%% basedir aux
+
+getenv(K,Def,false) -> getenv(K,Def);
+getenv(K,Def,true) -> getenv(K,basedir_join_home(Def)).
+
+getenv(K,Def) ->
+ case os:getenv(K) of
+ [] -> Def;
+ false -> Def;
+ Val -> Val
+ end.
+
+basedir_join_home(Dir) ->
+ case os:getenv("HOME") of
+ false ->
+ {ok,[[Home]]} = init:get_argument(home),
+ filename:join(Home,Dir);
+ Home -> filename:join(Home,Dir)
+ end.
+
+basedir_os_type() ->
+ case os:type() of
+ {unix,darwin} -> darwin;
+ {win32,_} -> windows;
+ _ -> linux
+ end.
diff --git a/lib/stdlib/src/io.erl b/lib/stdlib/src/io.erl
index 284f2e5a2b..f510f61e9f 100644
--- a/lib/stdlib/src/io.erl
+++ b/lib/stdlib/src/io.erl
@@ -444,7 +444,7 @@ scan_erl_form(Io, Prompt, Pos0, Options) ->
%% Parsing Erlang code.
-type parse_ret() :: {'ok',
- ExprList :: erl_parse:abstract_expr(),
+ ExprList :: [erl_parse:abstract_expr()],
EndLocation :: location()}
| {'eof', EndLocation :: location()}
| {'error',
@@ -631,41 +631,20 @@ io_requests(Pid, [], [Rs|Cont], Tail) ->
io_requests(_Pid, [], [], _Tail) ->
{false,[]}.
-
-bc_req(Pid,{Op,Enc,Param},MaybeConvert) ->
- case net_kernel:dflag_unicode_io(Pid) of
- true ->
- {false,{Op,Enc,Param}};
- false ->
- {MaybeConvert,{Op,Param}}
- end;
-bc_req(Pid,{Op,Enc,P,F},MaybeConvert) ->
- case net_kernel:dflag_unicode_io(Pid) of
- true ->
- {false,{Op,Enc,P,F}};
- false ->
- {MaybeConvert,{Op,P,F}}
- end;
-bc_req(Pid, {Op,Enc,M,F,A},MaybeConvert) ->
+bc_req(Pid, Req0, MaybeConvert) ->
case net_kernel:dflag_unicode_io(Pid) of
true ->
- {false,{Op,Enc,M,F,A}};
+ %% The most common case. A modern i/o server.
+ {false,Req0};
false ->
- {MaybeConvert,{Op,M,F,A}}
- end;
-bc_req(Pid, {Op,Enc,P,M,F,A},MaybeConvert) ->
- case net_kernel:dflag_unicode_io(Pid) of
- true ->
- {false,{Op,Enc,P,M,F,A}};
- false ->
- {MaybeConvert,{Op,P,M,F,A}}
- end;
-bc_req(Pid,{Op,Enc},MaybeConvert) ->
- case net_kernel:dflag_unicode_io(Pid) of
- true ->
- {false,{Op, Enc}};
- false ->
- {MaybeConvert,Op}
+ %% Backward compatibility only. Unlikely to ever happen.
+ case tuple_to_list(Req0) of
+ [Op,_Enc] ->
+ {MaybeConvert,Op};
+ [Op,_Enc|T] ->
+ Req = list_to_tuple([Op|T]),
+ {MaybeConvert,Req}
+ end
end.
io_request(Pid, {write,Term}) ->
diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl
index b67b6f75d7..24b5fde1db 100644
--- a/lib/stdlib/src/ms_transform.erl
+++ b/lib/stdlib/src/ms_transform.erl
@@ -307,15 +307,18 @@ cleanup_filename({Old,OldRec,OldWarnings}) ->
add_record_definition({Name,FieldList}) ->
{KeyList,_} = lists:foldl(
- fun({record_field,_,{atom,Line0,FieldName}},{L,C}) ->
- {[{FieldName,C,{atom,Line0,undefined}}|L],C+1};
- ({record_field,_,{atom,_,FieldName},Def},{L,C}) ->
- {[{FieldName,C,Def}|L],C+1}
- end,
+ fun(F, {L,C}) -> {[record_field(F, C)|L],C+1} end,
{[],2},
FieldList),
put_records([{Name,KeyList}|get_records()]).
+record_field({record_field,_,{atom,Line0,FieldName}}, C) ->
+ {FieldName,C,{atom,Line0,undefined}};
+record_field({record_field,_,{atom,_,FieldName},Def}, C) ->
+ {FieldName,C,Def};
+record_field({typed_record_field,Field,_Type}, C) ->
+ record_field(Field, C).
+
forms([F0|Fs0]) ->
F1 = form(F0),
Fs1 = forms(Fs0),
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index 9d394e19d7..6f546da7b8 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -588,49 +588,40 @@ obsolete_1(asn1rt, utf8_list_to_binary, 1) ->
%% Added in OTP 18.
obsolete_1(core_lib, get_anno, 1) ->
- {deprecated,{cerl,get_ann,1}};
+ {removed,{cerl,get_ann,1},"19"};
obsolete_1(core_lib, set_anno, 2) ->
- {deprecated,{cerl,set_ann,2}};
+ {removed,{cerl,set_ann,2},"19"};
obsolete_1(core_lib, is_literal, 1) ->
- {deprecated,{cerl,is_literal,1}};
+ {removed,{cerl,is_literal,1},"19"};
obsolete_1(core_lib, is_literal_list, 1) ->
- {deprecated,"deprecated; use lists:all(fun cerl:is_literal/1, L)"
+ {removed,"removed; use lists:all(fun cerl:is_literal/1, L)"
" instead"};
obsolete_1(core_lib, literal_value, 1) ->
- {deprecated,{core_lib,concrete,1}};
+ {removed,{core_lib,concrete,1},"19"};
obsolete_1(erl_scan, set_attribute, 3) ->
- {deprecated,
- "deprecated (will be removed in OTP 19); use erl_anno:set_line/2 instead"};
+ {removed,{erl_anno,set_line,2},"19.0"};
obsolete_1(erl_scan, attributes_info, 1) ->
- {deprecated,
- "deprecated (will be removed in OTP 19); use "
+ {removed,"removed in 19.0; use "
"erl_anno:{column,line,location,text}/1 instead"};
obsolete_1(erl_scan, attributes_info, 2) ->
- {deprecated,
- "deprecated (will be removed in OTP 19); use "
+ {removed,"removed in 19.0; use "
"erl_anno:{column,line,location,text}/1 instead"};
obsolete_1(erl_scan, token_info, 1) ->
- {deprecated,
- "deprecated (will be removed in OTP 19); use "
+ {removed,"removed in 19.0; use "
"erl_scan:{category,column,line,location,symbol,text}/1 instead"};
obsolete_1(erl_scan, token_info, 2) ->
- {deprecated,
- "deprecated (will be removed in OTP 19); use "
+ {removed,"removed in 19.0; use "
"erl_scan:{category,column,line,location,symbol,text}/1 instead"};
obsolete_1(erl_parse, set_line, 2) ->
- {deprecated,
- "deprecated (will be removed in OTP 19); use erl_anno:set_line/2 instead"};
+ {removed,{erl_anno,set_line,2},"19.0"};
obsolete_1(erl_parse, get_attributes, 1) ->
- {deprecated,
- "deprecated (will be removed in OTP 19); use "
+ {removed,"removed in 19.0; use "
"erl_anno:{column,line,location,text}/1 instead"};
obsolete_1(erl_parse, get_attribute, 2) ->
- {deprecated,
- "deprecated (will be removed in OTP 19); use "
+ {removed,"removed in 19.0; use "
"erl_anno:{column,line,location,text}/1 instead"};
obsolete_1(erl_lint, modify_line, 2) ->
- {deprecated,
- "deprecated (will be removed in OTP 19); use erl_parse:map_anno/2 instead"};
+ {removed,{erl_parse,map_anno,2},"19.0"};
obsolete_1(ssl, negotiated_next_protocol, 1) ->
{deprecated,{ssl,negotiated_protocol,1}};
@@ -650,8 +641,16 @@ obsolete_1(httpd_conf, is_file, 1) ->
obsolete_1(httpd_conf, make_integer, 1) ->
{deprecated, "deprecated; use erlang:list_to_integer/1 instead"};
+%% Added in OTP 19.
+
+obsolete_1(random, _, _) ->
+ {deprecated, "the 'random' module is deprecated; "
+ "use the 'rand' module instead"};
+obsolete_1(code, rehash, 0) ->
+ {deprecated, "deprecated because the code path cache feature has been removed"};
+
obsolete_1(overload, _, _) ->
- {deprecated, "deprecated; will be removed in OTP 19"};
+ {removed, "removed in OTP 19"};
obsolete_1(_, _, _) ->
no.
@@ -705,6 +704,7 @@ is_snmp_agent_function(_, _) -> false.
-spec obsolete_type(module(), atom(), arity()) ->
'no' | {tag(), string()} | {tag(), mfas(), release()}.
+-dialyzer({no_match, obsolete_type/3}).
obsolete_type(Module, Name, NumberOfVariables) ->
case obsolete_type_1(Module, Name, NumberOfVariables) of
{deprecated=Tag,{_,_,_}=Replacement} ->
@@ -718,13 +718,10 @@ obsolete_type(Module, Name, NumberOfVariables) ->
end.
obsolete_type_1(erl_scan,column,0) ->
- {deprecated,
- "deprecated (will be removed in OTP 19); use erl_anno:column() instead"};
+ {removed,{erl_anno,column,0},"19.0"};
obsolete_type_1(erl_scan,line,0) ->
- {deprecated,
- "deprecated (will be removed in OTP 19); use erl_anno:line() instead"};
+ {removed,{erl_anno,line,0},"19.0"};
obsolete_type_1(erl_scan,location,0) ->
- {deprecated,
- "deprecated (will be removed in OTP 19); use erl_anno:location() instead"};
+ {removed,{erl_anno,location,0},"19.0"};
obsolete_type_1(_,_,_) ->
no.
diff --git a/lib/stdlib/src/qlc.erl b/lib/stdlib/src/qlc.erl
index 1ae7c6cc25..b396ba7057 100644
--- a/lib/stdlib/src/qlc.erl
+++ b/lib/stdlib/src/qlc.erl
@@ -810,21 +810,21 @@ options(Options0, [Key | Keys], L) when is_list(Options0) ->
{ok, U};
{pre_fun, U=undefined} ->
{ok, U};
- {info_fun, Fun} when is_function(Fun), is_function(Fun, 1) ->
+ {info_fun, Fun} when is_function(Fun, 1) ->
{ok, Fun};
- {pre_fun, Fun} when is_function(Fun), is_function(Fun, 1) ->
+ {pre_fun, Fun} when is_function(Fun, 1) ->
{ok, Fun};
- {post_fun, Fun} when is_function(Fun), is_function(Fun, 0) ->
+ {post_fun, Fun} when is_function(Fun, 0) ->
{ok, Fun};
- {lookup_fun, Fun} when is_function(Fun), is_function(Fun, 2) ->
+ {lookup_fun, Fun} when is_function(Fun, 2) ->
{ok, Fun};
{max_lookup, Max} when is_integer(Max), Max >= 0 ->
{ok, Max};
{max_lookup, infinity} ->
{ok, -1};
- {format_fun, Fun} when is_function(Fun), is_function(Fun, 1) ->
+ {format_fun, Fun} when is_function(Fun, 1) ->
{ok, Fun};
- {parent_fun, Fun} when is_function(Fun), is_function(Fun, 0) ->
+ {parent_fun, Fun} when is_function(Fun, 0) ->
{ok, Fun};
{key_equality, KE='=='} ->
{ok, KE};
@@ -887,7 +887,7 @@ options(Options0, [Key | Keys], L) when is_list(Options0) ->
{depth, Depth} when Depth =:= infinity;
is_integer(Depth), Depth >= 0 ->
{ok, Depth};
- {order, Order} when is_function(Order), is_function(Order, 2);
+ {order, Order} when is_function(Order, 2);
(Order =:= ascending);
(Order =:= descending) ->
{ok, Order};
diff --git a/lib/stdlib/src/qlc_pt.erl b/lib/stdlib/src/qlc_pt.erl
index 9577d17a85..e4b9768b12 100644
--- a/lib/stdlib/src/qlc_pt.erl
+++ b/lib/stdlib/src/qlc_pt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2004-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.
@@ -200,7 +200,7 @@ exclude_integers_from_unique_line_numbers(Forms, NodeInfo) ->
find_integers(Forms) ->
F = fun(A) ->
- Fs1 = erl_parse:map_anno(fun(_) -> A end, Forms),
+ Fs1 = map_anno(fun(_) -> A end, Forms),
ordsets:from_list(integers(Fs1, []))
end,
ordsets:to_list(ordsets:intersection(F(anno0()), F(anno1()))).
@@ -319,13 +319,13 @@ badarg(Forms, State) ->
E0.
lc_nodes(E, NodeInfo) ->
- erl_parse:map_anno(fun(Anno) ->
- N = erl_anno:line(Anno),
- [{N, Data}] = ets:lookup(NodeInfo, N),
- NData = Data#{inside_lc => true},
- true = ets:insert(NodeInfo, {N, NData}),
- Anno
- end, E).
+ map_anno(fun(Anno) ->
+ N = erl_anno:line(Anno),
+ [{N, Data}] = ets:lookup(NodeInfo, N),
+ NData = Data#{inside_lc => true},
+ true = ets:insert(NodeInfo, {N, NData}),
+ Anno
+ end, E).
used_genvar_messages(MsL, S) ->
[{File,[{Loc,?APIMOD,{used_generator_variable,V}}]}
@@ -416,7 +416,7 @@ intro_anno(LC, Where, QId, NodeInfo) ->
true = ets:insert(NodeInfo, {Location,Data}),
Anno
end,
- erl_parse:map_anno(Fun, save_anno(LC, NodeInfo)).
+ map_anno(Fun, save_anno(LC, NodeInfo)).
compile_errors(FormsNoShadows) ->
case compile_forms(FormsNoShadows, []) of
@@ -1650,7 +1650,7 @@ reset_anno(T) ->
set_anno(T, anno0()).
set_anno(T, A) ->
- erl_parse:map_anno(fun(_L) -> A end, T).
+ map_anno(fun(_L) -> A end, T).
-record(fstate, {state, bind_fun, imported}).
@@ -1914,9 +1914,9 @@ expand_pattern_records(P, State) ->
expand_expr_records(E, State) ->
RecordDefs = State#state.records,
A = anno1(),
- Forms = RecordDefs ++ [{function,A,foo,0,[{clause,A,[],[],[pe(E)]}]}],
- [{function,_,foo,0,[{clause,_,[],[],[NE]}]}] =
- erl_expand_records:module(Forms, [no_strict_record_tests]),
+ Forms0 = RecordDefs ++ [{function,A,foo,0,[{clause,A,[],[],[pe(E)]}]}],
+ Forms = erl_expand_records:module(Forms0, [no_strict_record_tests]),
+ {function,_,foo,0,[{clause,_,[],[],[NE]}]} = lists:last(Forms),
NE.
%% Partial evaluation.
@@ -2609,7 +2609,7 @@ save_anno(Abstr, NodeInfo) ->
true = ets:insert(NodeInfo, Data),
erl_anno:new(N)
end,
- erl_parse:map_anno(F, Abstr).
+ map_anno(F, Abstr).
next_slot(T) ->
I = ets:update_counter(T, var_n, 1),
@@ -2633,7 +2633,7 @@ restore_anno(Abstr, NodeInfo) ->
Anno
end
end,
- erl_parse:map_anno(F, Abstr).
+ map_anno(F, Abstr).
restore_loc(Location, #state{node_info = NodeInfo}) ->
case ets:lookup(NodeInfo, Location) of
@@ -2872,6 +2872,14 @@ var_mapfold(F, A0, [E0 | Es0]) ->
var_mapfold(_F, A, E) ->
{E, A}.
+map_anno(F, AbstrList) when is_list(AbstrList) ->
+ [map_anno1(F, Abstr) || Abstr <- AbstrList];
+map_anno(F, Abstr) ->
+ map_anno1(F, Abstr).
+
+map_anno1(F, Abstr) ->
+ erl_parse:map_anno(F, Abstr).
+
family_list(L) ->
sofs:to_external(family(L)).
diff --git a/lib/stdlib/src/random.erl b/lib/stdlib/src/random.erl
index 8b67cde56c..8b639dd0a7 100644
--- a/lib/stdlib/src/random.erl
+++ b/lib/stdlib/src/random.erl
@@ -18,6 +18,7 @@
%% %CopyrightEnd%
%%
-module(random).
+-deprecated(module).
%% Reasonable random number generator.
%% The method is attributed to B. A. Wichmann and I. D. Hill
diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl
index ce1d9eb0ff..82a3a2be4f 100644
--- a/lib/stdlib/src/shell.erl
+++ b/lib/stdlib/src/shell.erl
@@ -917,9 +917,9 @@ expand_records(UsedRecords, E0) ->
RecordDefs = [Def || {_Name,Def} <- UsedRecords],
L = erl_anno:new(1),
E = prep_rec(E0),
- Forms = RecordDefs ++ [{function,L,foo,0,[{clause,L,[],[],[E]}]}],
- [{function,L,foo,0,[{clause,L,[],[],[NE]}]}] =
- erl_expand_records:module(Forms, [strict_record_tests]),
+ Forms0 = RecordDefs ++ [{function,L,foo,0,[{clause,L,[],[],[E]}]}],
+ Forms = erl_expand_records:module(Forms0, [strict_record_tests]),
+ {function,L,foo,0,[{clause,L,[],[],[NE]}]} = lists:last(Forms),
prep_rec(NE).
prep_rec({value,_CommandN,_V}=Value) ->
@@ -1081,6 +1081,8 @@ record_fields([{record_field,_,{atom,_,Field}} | Fs]) ->
[Field | record_fields(Fs)];
record_fields([{record_field,_,{atom,_,Field},_} | Fs]) ->
[Field | record_fields(Fs)];
+record_fields([{typed_record_field,Field,_Type} | Fs]) ->
+ record_fields([Field | Fs]);
record_fields([]) ->
[].
diff --git a/lib/stdlib/src/slave.erl b/lib/stdlib/src/slave.erl
index 24fc8ce204..4e629a5e56 100644
--- a/lib/stdlib/src/slave.erl
+++ b/lib/stdlib/src/slave.erl
@@ -289,10 +289,7 @@ register_unique_name(Number) ->
%% no need to use rsh.
mk_cmd(Host, Name, Args, Waiter, Prog0) ->
- Prog = case os:type() of
- {ose,_} -> mk_ose_prog(Prog0);
- _ -> quote_progname(Prog0)
- end,
+ Prog = quote_progname(Prog0),
BasicCmd = lists:concat([Prog,
" -detached -noinput -master ", node(),
" ", long_or_short(), Name, "@", Host,
@@ -312,24 +309,6 @@ mk_cmd(Host, Name, Args, Waiter, Prog0) ->
end
end.
-%% On OSE we have to pass the beam arguments directory to the slave
-%% process. To find out what arguments that should be passed on we
-%% make an assumption. All arguments after the last "--" should be
-%% skipped. So given these arguments:
-%% -Muycs256 -A 1 -- -root /mst/ -progname beam.debug.smp -- -home /mst/ -- -kernel inetrc '"/mst/inetrc.conf"' -- -name test@localhost
-%% we send
-%% -Muycs256 -A 1 -- -root /mst/ -progname beam.debug.smp -- -home /mst/ -- -kernel inetrc '"/mst/inetrc.conf"' --
-%% to the slave with whatever other args that are added in mk_cmd.
-mk_ose_prog(Prog) ->
- SkipTail = fun("--",[]) ->
- ["--"];
- (_,[]) ->
- [];
- (Arg,Args) ->
- [Arg," "|Args]
- end,
- [Prog,tl(lists:foldr(SkipTail,[],erlang:system_info(emu_args)))].
-
%% This is an attempt to distinguish between spaces in the program
%% path and spaces that separate arguments. The program is quoted to
%% allow spaces in the path.
diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src
index 8a313591a7..15d8857656 100644
--- a/lib/stdlib/src/stdlib.appup.src
+++ b/lib/stdlib/src/stdlib.appup.src
@@ -18,9 +18,9 @@
%% %CopyrightEnd%
{"%VSN%",
%% Up from - max one major revision back
- [{<<"2\\.[5-8](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.*
- {<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}], % 17.0-17.5
+ [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.*
+ {<<"2\\.[5-8](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-18.*
%% Down to - max one major revision back
- [{<<"2\\.[5-8](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.*
- {<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}] % 17.0-17.5
+ [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.*
+ {<<"2\\.[5-8](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-18.*
}.
diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl
index cecdebd0c8..0400c845ab 100644
--- a/lib/stdlib/src/supervisor.erl
+++ b/lib/stdlib/src/supervisor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-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.
@@ -110,11 +110,13 @@
-define(SET, sets:set).
-record(state, {name,
- strategy :: strategy(),
+ strategy :: strategy() | 'undefined',
children = [] :: [child_rec()],
- dynamics :: ?DICT(pid(), list()) | ?SET(pid()),
- intensity :: non_neg_integer(),
- period :: pos_integer(),
+ dynamics :: {'dict', ?DICT(pid(), list())}
+ | {'set', ?SET(pid())}
+ | 'undefined',
+ intensity :: non_neg_integer() | 'undefined',
+ period :: pos_integer() | 'undefined',
restarts = [],
dynamic_restarts = 0 :: non_neg_integer(),
module,
@@ -579,7 +581,7 @@ handle_cast({try_again_restart,Pid}, #state{children=[Child]}=State)
when ?is_simple(State) ->
RT = Child#child.restart_type,
RPid = restarting(Pid),
- case dynamic_child_args(RPid, dynamics_db(RT, State#state.dynamics)) of
+ case dynamic_child_args(RPid, RT, State#state.dynamics) of
{ok, Args} ->
{M, F, _} = Child#child.mfargs,
NChild = Child#child{pid = RPid, mfargs = {M, F, Args}},
@@ -737,7 +739,7 @@ handle_start_child(Child, State) ->
restart_child(Pid, Reason, #state{children = [Child]} = State) when ?is_simple(State) ->
RestartType = Child#child.restart_type,
- case dynamic_child_args(Pid, dynamics_db(RestartType, State#state.dynamics)) of
+ case dynamic_child_args(Pid, RestartType, State#state.dynamics) of
{ok, Args} ->
{M, F, _} = Child#child.mfargs,
NChild = Child#child{pid = Pid, mfargs = {M, F, Args}},
@@ -821,16 +823,18 @@ restart(simple_one_for_one, Child, State0) ->
State#state.dynamics)),
case do_start_child_i(M, F, A) of
{ok, Pid} ->
- NState = State#state{dynamics = ?DICTS:store(Pid, A, Dynamics)},
+ DynamicsDb = {dict, ?DICTS:store(Pid, A, Dynamics)},
+ NState = State#state{dynamics = DynamicsDb},
{ok, NState};
{ok, Pid, _Extra} ->
- NState = State#state{dynamics = ?DICTS:store(Pid, A, Dynamics)},
+ DynamicsDb = {dict, ?DICTS:store(Pid, A, Dynamics)},
+ NState = State#state{dynamics = DynamicsDb},
{ok, NState};
{error, Error} ->
NRestarts = State#state.dynamic_restarts + 1,
+ DynamicsDb = {dict, ?DICTS:store(restarting(OldPid), A, Dynamics)},
NState = State#state{dynamic_restarts = NRestarts,
- dynamics = ?DICTS:store(restarting(OldPid), A,
- Dynamics)},
+ dynamics = DynamicsDb},
report_error(start_error, Error, Child, State#state.name),
{try_again, NState}
end;
@@ -1113,31 +1117,32 @@ save_child(Child, #state{children = Children} = State) ->
State#state{children = [Child |Children]}.
save_dynamic_child(temporary, Pid, _, #state{dynamics = Dynamics} = State) ->
- State#state{dynamics = ?SETS:add_element(Pid, dynamics_db(temporary, Dynamics))};
+ DynamicsDb = dynamics_db(temporary, Dynamics),
+ State#state{dynamics = {set, ?SETS:add_element(Pid, DynamicsDb)}};
save_dynamic_child(RestartType, Pid, Args, #state{dynamics = Dynamics} = State) ->
- State#state{dynamics = ?DICTS:store(Pid, Args, dynamics_db(RestartType, Dynamics))}.
+ DynamicsDb = dynamics_db(RestartType, Dynamics),
+ State#state{dynamics = {dict, ?DICTS:store(Pid, Args, DynamicsDb)}}.
dynamics_db(temporary, undefined) ->
?SETS:new();
dynamics_db(_, undefined) ->
?DICTS:new();
-dynamics_db(_,Dynamics) ->
- Dynamics.
-
-dynamic_child_args(Pid, Dynamics) ->
- case ?SETS:is_set(Dynamics) of
- true ->
- {ok, undefined};
- false ->
- ?DICTS:find(Pid, Dynamics)
- end.
+dynamics_db(_, {_Tag, DynamicsDb}) ->
+ DynamicsDb.
+
+dynamic_child_args(_Pid, temporary, _DynamicsDb) ->
+ {ok, undefined};
+dynamic_child_args(Pid, _RT, {dict, DynamicsDb}) ->
+ ?DICTS:find(Pid, DynamicsDb);
+dynamic_child_args(_Pid, _RT, undefined) ->
+ error.
state_del_child(#child{pid = Pid, restart_type = temporary}, State) when ?is_simple(State) ->
NDynamics = ?SETS:del_element(Pid, dynamics_db(temporary, State#state.dynamics)),
- State#state{dynamics = NDynamics};
+ State#state{dynamics = {set, NDynamics}};
state_del_child(#child{pid = Pid, restart_type = RType}, State) when ?is_simple(State) ->
NDynamics = ?DICTS:erase(Pid, dynamics_db(RType, State#state.dynamics)),
- State#state{dynamics = NDynamics};
+ State#state{dynamics = {dict, NDynamics}};
state_del_child(Child, State) ->
NChildren = del_child(Child#child.name, State#state.children),
State#state{children = NChildren}.
@@ -1171,19 +1176,19 @@ split_child(_, [], After) ->
get_child(Name, State) ->
get_child(Name, State, false).
+
get_child(Pid, State, AllowPid) when AllowPid, is_pid(Pid) ->
get_dynamic_child(Pid, State);
get_child(Name, State, _) ->
lists:keysearch(Name, #child.name, State#state.children).
get_dynamic_child(Pid, #state{children=[Child], dynamics=Dynamics}) ->
- DynamicsDb = dynamics_db(Child#child.restart_type, Dynamics),
- case is_dynamic_pid(Pid, DynamicsDb) of
+ case is_dynamic_pid(Pid, Dynamics) of
true ->
{value, Child#child{pid=Pid}};
false ->
RPid = restarting(Pid),
- case is_dynamic_pid(RPid, DynamicsDb) of
+ case is_dynamic_pid(RPid, Dynamics) of
true ->
{value, Child#child{pid=RPid}};
false ->
@@ -1194,13 +1199,12 @@ get_dynamic_child(Pid, #state{children=[Child], dynamics=Dynamics}) ->
end
end.
-is_dynamic_pid(Pid, Dynamics) ->
- case ?SETS:is_set(Dynamics) of
- true ->
- ?SETS:is_element(Pid, Dynamics);
- false ->
- ?DICTS:is_key(Pid, Dynamics)
- end.
+is_dynamic_pid(Pid, {dict, Dynamics}) ->
+ ?DICTS:is_key(Pid, Dynamics);
+is_dynamic_pid(Pid, {set, Dynamics}) ->
+ ?SETS:is_element(Pid, Dynamics);
+is_dynamic_pid(_Pid, undefined) ->
+ false.
replace_child(Child, State) ->
Chs = do_replace_child(Child, State#state.children),
diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile
index e366c2b755..287f63b2be 100644
--- a/lib/stdlib/test/Makefile
+++ b/lib/stdlib/test/Makefile
@@ -107,8 +107,7 @@ RELSYSDIR = $(RELEASE_PATH)/stdlib_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \
- -I$(ERL_TOP)/lib/kernel/include \
+ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/kernel/include \
-I$(ERL_TOP)/lib/stdlib/include
EBIN = .
diff --git a/lib/stdlib/test/array_SUITE.erl b/lib/stdlib/test/array_SUITE.erl
index ab4ca91f76..8d031ed490 100644
--- a/lib/stdlib/test/array_SUITE.erl
+++ b/lib/stdlib/test/array_SUITE.erl
@@ -20,12 +20,7 @@
-module(array_SUITE).
--include_lib("test_server/include/test_server.hrl").
-
-%% Default timetrap timeout (set in init_per_testcase).
-%% This should be set relatively high (10-15 times the expected
-%% max testcasetime).
--define(default_timeout, ?t:seconds(60)).
+-include_lib("common_test/include/ct.hrl").
%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -66,7 +61,9 @@
%%
%% all/1
%%
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[new_test, fix_test, relax_test, resize_test,
@@ -93,12 +90,9 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_Case, Config) ->
- ?line Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
-define(LEAFSIZE,10).
@@ -111,19 +105,19 @@ end_per_testcase(_Case, Config) ->
}).
-define(_assert(What),
- begin ?line true = What end
+ begin true = What end
).
-define(_assertNot(What),
- begin ?line false = What end
+ begin false = What end
).
-define(_assertMatch(Res,What),
begin
- ?line case What of Res -> ok end
+ case What of Res -> ok end
end
).
-define(_assertError(Reas,What),
- begin ?line fun() ->
+ begin fun() ->
try What of
A_Success -> exit({test_error, A_Success})
catch error:Reas -> ok end
@@ -131,9 +125,9 @@ end_per_testcase(_Case, Config) ->
end
).
--define(LET(Var,Expr, Test), begin ?line fun() -> Var = Expr, Test end() end).
+-define(LET(Var,Expr, Test), begin fun() -> Var = Expr, Test end() end).
--define(_test(Expr), begin ?line Expr end).
+-define(_test(Expr), begin Expr end).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Some helpers to be able to run the tests without testserver
@@ -152,18 +146,7 @@ t(What) ->
io:format("Failed ~p:~p ~p ~p~n ~p~n",
[T,Line,_E,_R, erlang:get_stacktrace()])
end
- end, expand(What)).
-
-expand(All) ->
- lists:reverse(expand(All,[])).
-expand([H|T], Acc) ->
- case ?MODULE:H(suite) of
- [] -> expand(T,[H|Acc]);
- Cs ->
- R = expand(Cs, Acc),
- expand(T, R)
- end;
-expand([], Acc) -> Acc.
+ end, What).
%%%%% extract tests
@@ -173,8 +156,6 @@ extract_tests() ->
try
Tests = extract_tests(In,Out,[]),
Call = fun(Test) ->
- io:format(Out, "~s(doc) -> [];~n", [Test]),
- io:format(Out, "~s(suite) -> [];~n", [Test]),
io:format(Out, "~s(Config) when is_list(Config) -> ~s_(), ok.~n",
[Test, Test])
end,
@@ -775,54 +756,20 @@ sparse_foldr_test_() ->
set(0,0,new())))))
].
-new_test(doc) -> [];
-new_test(suite) -> [];
new_test(Config) when is_list(Config) -> new_test_(), ok.
-fix_test(doc) -> [];
-fix_test(suite) -> [];
fix_test(Config) when is_list(Config) -> fix_test_(), ok.
-relax_test(doc) -> [];
-relax_test(suite) -> [];
relax_test(Config) when is_list(Config) -> relax_test_(), ok.
-resize_test(doc) -> [];
-resize_test(suite) -> [];
resize_test(Config) when is_list(Config) -> resize_test_(), ok.
-set_get_test(doc) -> [];
-set_get_test(suite) -> [];
set_get_test(Config) when is_list(Config) -> set_get_test_(), ok.
-to_list_test(doc) -> [];
-to_list_test(suite) -> [];
to_list_test(Config) when is_list(Config) -> to_list_test_(), ok.
-sparse_to_list_test(doc) -> [];
-sparse_to_list_test(suite) -> [];
sparse_to_list_test(Config) when is_list(Config) -> sparse_to_list_test_(), ok.
-from_list_test(doc) -> [];
-from_list_test(suite) -> [];
from_list_test(Config) when is_list(Config) -> from_list_test_(), ok.
-to_orddict_test(doc) -> [];
-to_orddict_test(suite) -> [];
to_orddict_test(Config) when is_list(Config) -> to_orddict_test_(), ok.
-sparse_to_orddict_test(doc) -> [];
-sparse_to_orddict_test(suite) -> [];
sparse_to_orddict_test(Config) when is_list(Config) -> sparse_to_orddict_test_(), ok.
-from_orddict_test(doc) -> [];
-from_orddict_test(suite) -> [];
from_orddict_test(Config) when is_list(Config) -> from_orddict_test_(), ok.
-map_test(doc) -> [];
-map_test(suite) -> [];
map_test(Config) when is_list(Config) -> map_test_(), ok.
-sparse_map_test(doc) -> [];
-sparse_map_test(suite) -> [];
sparse_map_test(Config) when is_list(Config) -> sparse_map_test_(), ok.
-foldl_test(doc) -> [];
-foldl_test(suite) -> [];
foldl_test(Config) when is_list(Config) -> foldl_test_(), ok.
-sparse_foldl_test(doc) -> [];
-sparse_foldl_test(suite) -> [];
sparse_foldl_test(Config) when is_list(Config) -> sparse_foldl_test_(), ok.
-foldr_test(doc) -> [];
-foldr_test(suite) -> [];
foldr_test(Config) when is_list(Config) -> foldr_test_(), ok.
-sparse_foldr_test(doc) -> [];
-sparse_foldr_test(suite) -> [];
sparse_foldr_test(Config) when is_list(Config) -> sparse_foldr_test_(), ok.
diff --git a/lib/stdlib/test/base64_SUITE.erl b/lib/stdlib/test/base64_SUITE.erl
index 75eebba6c6..074047c7c5 100644
--- a/lib/stdlib/test/base64_SUITE.erl
+++ b/lib/stdlib/test/base64_SUITE.erl
@@ -34,19 +34,17 @@
roundtrip_1/1, roundtrip_2/1, roundtrip_3/1, roundtrip_4/1]).
init_per_testcase(_, Config) ->
- Dog = test_server:timetrap(?t:minutes(4)),
- NewConfig = lists:keydelete(watchdog, 1, Config),
- [{watchdog, Dog} | NewConfig].
+ Config.
-end_per_testcase(_, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_, _Config) ->
ok.
%%-------------------------------------------------------------------------
%% Test cases starts here.
%%-------------------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,4}}].
all() ->
[base64_encode, base64_decode, base64_otp_5635,
@@ -72,10 +70,7 @@ end_per_group(_GroupName, Config) ->
%%-------------------------------------------------------------------------
-base64_encode(doc) ->
- ["Test base64:encode/1."];
-base64_encode(suite) ->
- [];
+%% Test base64:encode/1.
base64_encode(Config) when is_list(Config) ->
%% Two pads
<<"QWxhZGRpbjpvcGVuIHNlc2FtZQ==">> =
@@ -90,10 +85,7 @@ base64_encode(Config) when is_list(Config) ->
base64:encode_to_string(<<"0123456789!@#0^&*();:<>,. []{}">>),
ok.
%%-------------------------------------------------------------------------
-base64_decode(doc) ->
- ["Test base64:decode/1."];
-base64_decode(suite) ->
- [];
+%% Test base64:decode/1.
base64_decode(Config) when is_list(Config) ->
%% Two pads
<<"Aladdin:open sesame">> =
@@ -117,28 +109,18 @@ base64_decode(Config) when is_list(Config) ->
<<"MDEy MzQ1Njc4 \tOSFAIzBeJ \niooKTs6 PD4sLi \r\nBbXXt9">>),
ok.
%%-------------------------------------------------------------------------
-base64_otp_5635(doc) ->
- ["OTP-5635: Some data doesn't pass through base64:decode/1 "
- "correctly"];
-base64_otp_5635(suite) ->
- [];
+%% OTP-5635: Some data doesn't pass through base64:decode/1 correctly.
base64_otp_5635(Config) when is_list(Config) ->
<<"===">> = base64:decode(base64:encode("===")),
ok.
%%-------------------------------------------------------------------------
-base64_otp_6279(doc) ->
- ["OTP-6279: Guard needed so that function fails in a correct"
- "way for faulty input i.e. function_clause"];
-base64_otp_6279(suite) ->
- [];
+%% OTP-6279: Guard needed so that function fails in a correct
+%% way for faulty input, i.e. function_clause.
base64_otp_6279(Config) when is_list(Config) ->
{'EXIT',{function_clause, _}} = (catch base64:decode("dGVzda==a")),
ok.
%%-------------------------------------------------------------------------
-big(doc) ->
- ["Encode and decode big binaries."];
-big(suite) ->
- [];
+%% Encode and decode big binaries.
big(Config) when is_list(Config) ->
Big = make_big_binary(300000),
B = base64:encode(Big),
@@ -148,10 +130,7 @@ big(Config) when is_list(Config) ->
Big = base64:mime_decode(B),
ok.
%%-------------------------------------------------------------------------
-illegal(doc) ->
- ["Make sure illegal characters are rejected when decoding."];
-illegal(suite) ->
- [];
+%% Make sure illegal characters are rejected when decoding.
illegal(Config) when is_list(Config) ->
{'EXIT',{function_clause, _}} = (catch base64:decode("()")),
ok.
@@ -159,10 +138,8 @@ illegal(Config) when is_list(Config) ->
%% 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.
-mime_decode(doc) ->
- ["Test base64:mime_decode/1."];
-mime_decode(suite) ->
- [];
+%%
+%% Test base64:mime_decode/1.
mime_decode(Config) when is_list(Config) ->
%% Test correct padding
<<"one">> = base64:mime_decode(<<"b25l">>),
@@ -202,10 +179,8 @@ mime_decode(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
%% Repeat of mime_decode() tests
-mime_decode_to_string(doc) ->
- ["Test base64:mime_decode_to_string/1."];
-mime_decode_to_string(suite) ->
- [];
+
+%% Test base64:mime_decode_to_string/1.
mime_decode_to_string(Config) when is_list(Config) ->
%% Test correct padding
"one" = base64:mime_decode_to_string(<<"b25l">>),
@@ -340,7 +315,7 @@ interleaved_ws_roundtrip_1([], Base64List, Bin, List) ->
random_byte_list(0, Acc) ->
Acc;
random_byte_list(N, Acc) ->
- random_byte_list(N-1, [random:uniform(255)|Acc]).
+ random_byte_list(N-1, [rand:uniform(255)|Acc]).
make_big_binary(N) ->
list_to_binary(mbb(N, [])).
diff --git a/lib/stdlib/test/beam_lib_SUITE.erl b/lib/stdlib/test/beam_lib_SUITE.erl
index c102f6e929..bf6e30ec83 100644
--- a/lib/stdlib/test/beam_lib_SUITE.erl
+++ b/lib/stdlib/test/beam_lib_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(beam_lib_SUITE).
-%-define(debug, true).
+%%-define(debug, true).
-ifdef(debug).
-define(format(S, A), io:format(S, A)).
@@ -28,9 +28,9 @@
-define(t,test_server).
-define(privdir, "beam_lib_SUITE_priv").
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(format(S, A), ok).
--define(privdir, ?config(priv_dir, Conf)).
+-define(privdir, proplists:get_value(priv_dir, Conf)).
-endif.
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -40,7 +40,9 @@
-export([init_per_testcase/2, end_per_testcase/2]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,2}}].
all() ->
[error, normal, cmp, cmp_literals, strip, otp_6711,
@@ -63,78 +65,74 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_Case, Config) ->
- Dog=?t:timetrap(?t:minutes(2)),
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
-normal(suite) -> [];
-normal(doc) -> ["Read correct beam file"];
+%% Read correct beam file.
normal(Conf) when is_list(Conf) ->
- ?line PrivDir = ?privdir,
- ?line Simple = filename:join(PrivDir, "simple"),
- ?line Source = Simple ++ ".erl",
- ?line BeamFile = Simple ++ ".beam",
- ?line simple_file(Source),
+ PrivDir = ?privdir,
+ Simple = filename:join(PrivDir, "simple"),
+ Source = Simple ++ ".erl",
+ BeamFile = Simple ++ ".beam",
+ simple_file(Source),
- ?line NoOfTables = length(ets:all()),
- ?line P0 = pps(),
+ NoOfTables = length(ets:all()),
+ P0 = pps(),
CompileFlags = [{outdir,PrivDir}, debug_info],
- ?line {ok,_} = compile:file(Source, CompileFlags),
- ?line {ok, Binary} = file:read_file(BeamFile),
+ {ok,_} = compile:file(Source, CompileFlags),
+ {ok, Binary} = file:read_file(BeamFile),
- ?line do_normal(BeamFile),
- ?line do_normal(Binary),
+ do_normal(BeamFile),
+ do_normal(Binary),
- ?line {ok,_} = compile:file(Source, [{outdir,PrivDir}, no_debug_info]),
- ?line {ok, {simple, [{abstract_code, no_abstract_code}]}} =
+ {ok,_} = compile:file(Source, [{outdir,PrivDir}, no_debug_info]),
+ {ok, {simple, [{abstract_code, no_abstract_code}]}} =
beam_lib:chunks(BeamFile, [abstract_code]),
- %% ?line {ok,_} = compile:file(Source, [compressed | CompileFlags]),
- %% ?line do_normal(BeamFile),
+ %% {ok,_} = compile:file(Source, [compressed | CompileFlags]),
+ %% do_normal(BeamFile),
- ?line file:delete(BeamFile),
- ?line file:delete(Source),
- ?line NoOfTables = length(ets:all()),
- ?line true = (P0 == pps()),
+ file:delete(BeamFile),
+ file:delete(Source),
+ NoOfTables = length(ets:all()),
+ true = (P0 == pps()),
ok.
do_normal(BeamFile) ->
- ?line Imports = {imports, [{erlang, get_module_info, 1},
- {erlang, get_module_info, 2},
- {lists, member, 2}]},
- ?line Exports = {exports, [{module_info, 0}, {module_info, 1}, {t, 0}]},
- ?line Local = {locals, [{t, 1}]},
- ?line {ok, {simple, [Imports]}} = beam_lib:chunks(BeamFile, [imports]),
- ?line {ok, {simple, [{"ImpT",_Bin}]}} =
+ Imports = {imports, [{erlang, get_module_info, 1},
+ {erlang, get_module_info, 2},
+ {lists, member, 2}]},
+ Exports = {exports, [{module_info, 0}, {module_info, 1}, {t, 0}]},
+ Local = {locals, [{t, 1}]},
+ {ok, {simple, [Imports]}} = beam_lib:chunks(BeamFile, [imports]),
+ {ok, {simple, [{"ImpT",_Bin}]}} =
beam_lib:chunks(BeamFile, ["ImpT"]),
- ?line {ok, {simple, [Exports]}} = beam_lib:chunks(BeamFile, [exports]),
- ?line {ok, {simple, [{attributes, [{vsn, [_]}]}]}} =
+ {ok, {simple, [Exports]}} = beam_lib:chunks(BeamFile, [exports]),
+ {ok, {simple, [{attributes, [{vsn, [_]}]}]}} =
beam_lib:chunks(BeamFile, [attributes]),
- ?line {ok, {simple, [{compile_info, _}=CompileInfo]}} =
+ {ok, {simple, [{compile_info, _}=CompileInfo]}} =
beam_lib:chunks(BeamFile, [compile_info]),
- ?line {ok, {simple, [Local]}} = beam_lib:chunks(BeamFile, [locals]),
- ?line {ok, {simple, [{attributes, [{vsn, [_]}]}, CompileInfo,
- Exports, Imports, Local]}} =
+ {ok, {simple, [Local]}} = beam_lib:chunks(BeamFile, [locals]),
+ {ok, {simple, [{attributes, [{vsn, [_]}]}, CompileInfo,
+ Exports, Imports, Local]}} =
beam_lib:chunks(BeamFile, [attributes, compile_info, exports, imports, locals]),
- ?line {ok, {simple, [{atoms, _Atoms}]}} =
+ {ok, {simple, [{atoms, _Atoms}]}} =
beam_lib:chunks(BeamFile, [atoms]),
- ?line {ok, {simple, [{labeled_exports, _LExports}]}} =
+ {ok, {simple, [{labeled_exports, _LExports}]}} =
beam_lib:chunks(BeamFile, [labeled_exports]),
- ?line {ok, {simple, [{labeled_locals, _LLocals}]}} =
+ {ok, {simple, [{labeled_locals, _LLocals}]}} =
beam_lib:chunks(BeamFile, [labeled_locals]),
- ?line {ok, {simple, [_Vsn]}} = beam_lib:version(BeamFile),
- ?line {ok, {simple, [{abstract_code, _}]}} =
+ {ok, {simple, [_Vsn]}} = beam_lib:version(BeamFile),
+ {ok, {simple, [{abstract_code, _}]}} =
beam_lib:chunks(BeamFile, [abstract_code]),
-
+
%% Test reading optional chunks.
All = ["Atom", "Code", "StrT", "ImpT", "ExpT", "FunT", "LitT"],
- ?line {ok,{simple,Chunks}} = beam_lib:chunks(BeamFile, All, [allow_missing_chunks]),
- ?line verify_simple(Chunks).
+ {ok,{simple,Chunks}} = beam_lib:chunks(BeamFile, All, [allow_missing_chunks]),
+ verify_simple(Chunks).
verify_simple([{"Atom", AtomBin},
{"Code", CodeBin},
@@ -147,64 +145,61 @@ verify_simple([{"Atom", AtomBin},
is_binary(ImpBin), is_binary(ExpBin) ->
ok.
-error(suite) -> [];
-error(doc) -> ["Read invalid beam files"];
+%% Read invalid beam files.
error(Conf) when is_list(Conf) ->
- ?line PrivDir = ?privdir,
- ?line Simple = filename:join(PrivDir, "simple"),
- ?line Source = Simple ++ ".erl",
- ?line BeamFile = Simple ++ ".beam",
- ?line WrongFile = Simple ++ "foo.beam",
- ?line simple_file(Source),
-
- ?line NoOfTables = length(ets:all()),
- ?line P0 = pps(),
- ?line {ok,_} = compile:file(Source, [{outdir,PrivDir},debug_info]),
- ?line ACopy = filename:join(PrivDir, "a_copy.beam"),
- ?line copy_file(BeamFile, ACopy),
-
- ?line {ok, Binary} = file:read_file(BeamFile),
-
- ?line copy_file(ACopy, WrongFile),
- ?line verify(file_error, beam_lib:info("./does_simply_not_exist")),
-
- ?line do_error(BeamFile, ACopy),
- ?line do_error(Binary, ACopy),
-
- ?line copy_file(ACopy, BeamFile),
- ?line verify(unknown_chunk, beam_lib:chunks(BeamFile, [not_a_chunk])),
-
- ?line ok = file:write_file(BeamFile, <<>>),
- ?line verify(not_a_beam_file, beam_lib:info(BeamFile)),
- ?line verify(not_a_beam_file, beam_lib:info(<<>>)),
- ?line ok = file:write_file(BeamFile, <<"short">>),
- ?line verify(not_a_beam_file, beam_lib:info(BeamFile)),
- ?line verify(not_a_beam_file, beam_lib:info(<<"short">>)),
-
- ?line {Binary1, _} = split_binary(Binary, byte_size(Binary)-10),
+ PrivDir = ?privdir,
+ Simple = filename:join(PrivDir, "simple"),
+ Source = Simple ++ ".erl",
+ BeamFile = Simple ++ ".beam",
+ WrongFile = Simple ++ "foo.beam",
+ simple_file(Source),
+
+ NoOfTables = length(ets:all()),
+ P0 = pps(),
+ {ok,_} = compile:file(Source, [{outdir,PrivDir},debug_info]),
+ ACopy = filename:join(PrivDir, "a_copy.beam"),
+ copy_file(BeamFile, ACopy),
+
+ {ok, Binary} = file:read_file(BeamFile),
+
+ copy_file(ACopy, WrongFile),
+ verify(file_error, beam_lib:info("./does_simply_not_exist")),
+
+ do_error(BeamFile, ACopy),
+ do_error(Binary, ACopy),
+
+ copy_file(ACopy, BeamFile),
+ verify(unknown_chunk, beam_lib:chunks(BeamFile, [not_a_chunk])),
+
+ ok = file:write_file(BeamFile, <<>>),
+ verify(not_a_beam_file, beam_lib:info(BeamFile)),
+ verify(not_a_beam_file, beam_lib:info(<<>>)),
+ ok = file:write_file(BeamFile, <<"short">>),
+ verify(not_a_beam_file, beam_lib:info(BeamFile)),
+ verify(not_a_beam_file, beam_lib:info(<<"short">>)),
+
+ {Binary1, _} = split_binary(Binary, byte_size(Binary)-10),
LastChunk = last_chunk(Binary),
- ?line verify(chunk_too_big, beam_lib:chunks(Binary1, [LastChunk])),
- ?line Chunks = chunk_info(Binary),
- ?line {value, {_, AbstractStart, _}} = lists:keysearch("Abst", 1, Chunks),
- ?line {Binary2, _} = split_binary(Binary, AbstractStart),
- ?line verify(chunk_too_big, beam_lib:chunks(Binary2, ["Abst"])),
- ?line {Binary3, _} = split_binary(Binary, AbstractStart-4),
- ?line verify(invalid_beam_file, beam_lib:chunks(Binary3, ["Abst"])),
+ verify(chunk_too_big, beam_lib:chunks(Binary1, [LastChunk])),
+ Chunks = chunk_info(Binary),
+ {value, {_, AbstractStart, _}} = lists:keysearch("Abst", 1, Chunks),
+ {Binary2, _} = split_binary(Binary, AbstractStart),
+ verify(chunk_too_big, beam_lib:chunks(Binary2, ["Abst"])),
+ {Binary3, _} = split_binary(Binary, AbstractStart-4),
+ verify(invalid_beam_file, beam_lib:chunks(Binary3, ["Abst"])),
%% Instead of the 5:32 field below, there used to be control characters
%% (including zero bytes) directly in the string. Because inferior programs
%% such as sed and clearcasediff don't like zero bytes in text files,
%% we have eliminated them.
- ?line ok = file:write_file(BeamFile, <<"FOR1",5:32,"BEAMfel">>),
-% ?line verify(invalid_beam_file, beam_lib:info(BeamFile)),
-% ?line verify(invalid_beam_file, beam_lib:info(<<"FOR1",5:32,"BEAMfel">>)),
-
- ?line NoOfTables = length(ets:all()),
- ?line true = (P0 == pps()),
- ?line file:delete(Source),
- ?line file:delete(WrongFile),
- ?line file:delete(BeamFile),
- ?line file:delete(ACopy),
+ ok = file:write_file(BeamFile, <<"FOR1",5:32,"BEAMfel">>),
+
+ NoOfTables = length(ets:all()),
+ true = (P0 == pps()),
+ file:delete(Source),
+ file:delete(WrongFile),
+ file:delete(BeamFile),
+ file:delete(ACopy),
ok.
last_chunk(Bin) ->
@@ -214,213 +209,210 @@ last_chunk(Bin) ->
Last.
do_error(BeamFile, ACopy) ->
- % evil tests
- ?line Chunks = chunk_info(BeamFile),
- ?line {value, {_, AtomStart, _}} = lists:keysearch("Atom", 1, Chunks),
- ?line {value, {_, ImportStart, _}} = lists:keysearch("ImpT", 1, Chunks),
- ?line {value, {_, AbstractStart, _}} = lists:keysearch("Abst", 1, Chunks),
- ?line {value, {_, AttributesStart, _}} =
+ %% evil tests
+ Chunks = chunk_info(BeamFile),
+ {value, {_, AtomStart, _}} = lists:keysearch("Atom", 1, Chunks),
+ {value, {_, ImportStart, _}} = lists:keysearch("ImpT", 1, Chunks),
+ {value, {_, AbstractStart, _}} = lists:keysearch("Abst", 1, Chunks),
+ {value, {_, AttributesStart, _}} =
lists:keysearch("Attr", 1, Chunks),
- ?line {value, {_, CompileInfoStart, _}} =
+ {value, {_, CompileInfoStart, _}} =
lists:keysearch("CInf", 1, Chunks),
- ?line verify(missing_chunk, beam_lib:chunks(BeamFile, ["__"])),
- ?line BF2 = set_byte(ACopy, BeamFile, ImportStart+4, 17),
- ?line verify(invalid_chunk, beam_lib:chunks(BF2, [imports])),
- ?line BF3 = set_byte(ACopy, BeamFile, AtomStart-6, 17),
- ?line verify(missing_chunk, beam_lib:chunks(BF3, [imports])),
- ?line BF4 = set_byte(ACopy, BeamFile, AbstractStart+10, 17),
- ?line verify(invalid_chunk, beam_lib:chunks(BF4, [abstract_code])),
- ?line BF5 = set_byte(ACopy, BeamFile, AttributesStart+10, 17),
- ?line verify(invalid_chunk, beam_lib:chunks(BF5, [attributes])),
-
- ?line BF6 = set_byte(ACopy, BeamFile, 1, 17),
- ?line verify(not_a_beam_file, beam_lib:info(BF6)),
- ?line BF7 = set_byte(ACopy, BeamFile, 9, 17),
- ?line verify(not_a_beam_file, beam_lib:info(BF7)),
-
- ?line BF8 = set_byte(ACopy, BeamFile, 13, 17),
- ?line verify(missing_chunk, beam_lib:chunks(BF8, ["Atom"])),
-
- ?line BF9 = set_byte(ACopy, BeamFile, CompileInfoStart+10, 17),
- ?line verify(invalid_chunk, beam_lib:chunks(BF9, [compile_info])).
-
-
-cmp(suite) -> [];
-cmp(doc) -> ["Compare contents of BEAM files and directories"];
+ verify(missing_chunk, beam_lib:chunks(BeamFile, ["__"])),
+ BF2 = set_byte(ACopy, BeamFile, ImportStart+4, 17),
+ verify(invalid_chunk, beam_lib:chunks(BF2, [imports])),
+ BF3 = set_byte(ACopy, BeamFile, AtomStart-6, 17),
+ verify(missing_chunk, beam_lib:chunks(BF3, [imports])),
+ BF4 = set_byte(ACopy, BeamFile, AbstractStart+10, 17),
+ verify(invalid_chunk, beam_lib:chunks(BF4, [abstract_code])),
+ BF5 = set_byte(ACopy, BeamFile, AttributesStart+10, 17),
+ verify(invalid_chunk, beam_lib:chunks(BF5, [attributes])),
+
+ BF6 = set_byte(ACopy, BeamFile, 1, 17),
+ verify(not_a_beam_file, beam_lib:info(BF6)),
+ BF7 = set_byte(ACopy, BeamFile, 9, 17),
+ verify(not_a_beam_file, beam_lib:info(BF7)),
+
+ BF8 = set_byte(ACopy, BeamFile, 13, 17),
+ verify(missing_chunk, beam_lib:chunks(BF8, ["Atom"])),
+
+ BF9 = set_byte(ACopy, BeamFile, CompileInfoStart+10, 17),
+ verify(invalid_chunk, beam_lib:chunks(BF9, [compile_info])).
+
+
+%% Compare contents of BEAM files and directories.
cmp(Conf) when is_list(Conf) ->
- ?line PrivDir = ?privdir,
+ PrivDir = ?privdir,
- ?line Dir1 = filename:join(PrivDir, "dir1"),
- ?line Dir2 = filename:join(PrivDir, "dir2"),
+ Dir1 = filename:join(PrivDir, "dir1"),
+ Dir2 = filename:join(PrivDir, "dir2"),
ok = file:make_dir(Dir1),
ok = file:make_dir(Dir2),
- ?line {SourceD1, BeamFileD1} = make_beam(Dir1, simple, member),
- ?line {Source2D1, BeamFile2D1} = make_beam(Dir1, simple2, concat),
- ?line {SourceD2, BeamFileD2} = make_beam(Dir2, simple, concat),
+ {SourceD1, BeamFileD1} = make_beam(Dir1, simple, member),
+ {Source2D1, BeamFile2D1} = make_beam(Dir1, simple2, concat),
+ {SourceD2, BeamFileD2} = make_beam(Dir2, simple, concat),
- ?line NoOfTables = length(ets:all()),
- ?line P0 = pps(),
+ NoOfTables = length(ets:all()),
+ P0 = pps(),
%% cmp
- ?line ok = beam_lib:cmp(BeamFileD1, BeamFileD1),
- ?line ver(modules_different, beam_lib:cmp(BeamFileD1, BeamFile2D1)),
- ?line ver(chunks_different, beam_lib:cmp(BeamFileD1, BeamFileD2)),
- ?line verify(file_error, beam_lib:cmp(foo, bar)),
-
- ?line {ok, B1} = file:read_file(BeamFileD1),
- ?line ok = beam_lib:cmp(B1, BeamFileD1),
- ?line {ok, B2} = file:read_file(BeamFileD2),
- ?line ver(chunks_different, beam_lib:cmp(B1, B2)),
+ ok = beam_lib:cmp(BeamFileD1, BeamFileD1),
+ ver(modules_different, beam_lib:cmp(BeamFileD1, BeamFile2D1)),
+ ver(chunks_different, beam_lib:cmp(BeamFileD1, BeamFileD2)),
+ verify(file_error, beam_lib:cmp(foo, bar)),
+
+ {ok, B1} = file:read_file(BeamFileD1),
+ ok = beam_lib:cmp(B1, BeamFileD1),
+ {ok, B2} = file:read_file(BeamFileD2),
+ ver(chunks_different, beam_lib:cmp(B1, B2)),
%% cmp_dirs
- ?line {[],[],[]} = beam_lib:cmp_dirs(Dir1, Dir1),
- ?line true = {[BeamFile2D1], [], [{BeamFileD1,BeamFileD2}]} ==
- beam_lib:cmp_dirs(Dir1, Dir2),
- ?line true = {[], [BeamFile2D1], [{BeamFileD2,BeamFileD1}]} ==
- beam_lib:cmp_dirs(Dir2, Dir1),
- ?line ver(not_a_directory, beam_lib:cmp_dirs(foo, bar)),
-
+ {[],[],[]} = beam_lib:cmp_dirs(Dir1, Dir1),
+ true = {[BeamFile2D1], [], [{BeamFileD1,BeamFileD2}]} ==
+ beam_lib:cmp_dirs(Dir1, Dir2),
+ true = {[], [BeamFile2D1], [{BeamFileD2,BeamFileD1}]} ==
+ beam_lib:cmp_dirs(Dir2, Dir1),
+ ver(not_a_directory, beam_lib:cmp_dirs(foo, bar)),
+
%% diff_dirs
- ?line ok = beam_lib:diff_dirs(Dir1, Dir1),
- ?line ver(not_a_directory, beam_lib:diff_dirs(foo, bar)),
+ ok = beam_lib:diff_dirs(Dir1, Dir1),
+ ver(not_a_directory, beam_lib:diff_dirs(foo, bar)),
- ?line true = (P0 == pps()),
- ?line NoOfTables = length(ets:all()),
- ?line delete_files([SourceD1, BeamFileD1, Source2D1,
- BeamFile2D1, SourceD2, BeamFileD2]),
+ true = (P0 == pps()),
+ NoOfTables = length(ets:all()),
+ delete_files([SourceD1, BeamFileD1, Source2D1,
+ BeamFile2D1, SourceD2, BeamFileD2]),
file:del_dir(Dir1),
file:del_dir(Dir2),
ok.
-cmp_literals(suite) -> [];
-cmp_literals(doc) -> ["Compare contents of BEAM files having literals"];
+%% Compare contents of BEAM files having literals.
cmp_literals(Conf) when is_list(Conf) ->
- ?line PrivDir = ?privdir,
+ PrivDir = ?privdir,
- ?line Dir1 = filename:join(PrivDir, "dir1"),
- ?line Dir2 = filename:join(PrivDir, "dir2"),
+ Dir1 = filename:join(PrivDir, "dir1"),
+ Dir2 = filename:join(PrivDir, "dir2"),
ok = file:make_dir(Dir1),
ok = file:make_dir(Dir2),
- ?line {SourceD1, BeamFileD1} = make_beam(Dir1, simple, constant),
- ?line {SourceD2, BeamFileD2} = make_beam(Dir2, simple, constant2),
+ {SourceD1, BeamFileD1} = make_beam(Dir1, simple, constant),
+ {SourceD2, BeamFileD2} = make_beam(Dir2, simple, constant2),
- ?line NoOfTables = length(ets:all()),
- ?line P0 = pps(),
+ NoOfTables = length(ets:all()),
+ P0 = pps(),
%% cmp
- ?line ok = beam_lib:cmp(BeamFileD1, BeamFileD1),
- ?line ver(chunks_different, beam_lib:cmp(BeamFileD1, BeamFileD2)),
-
- ?line {ok, B1} = file:read_file(BeamFileD1),
- ?line ok = beam_lib:cmp(B1, BeamFileD1),
- ?line {ok, B2} = file:read_file(BeamFileD2),
- ?line ver(chunks_different, beam_lib:cmp(B1, B2)),
+ ok = beam_lib:cmp(BeamFileD1, BeamFileD1),
+ ver(chunks_different, beam_lib:cmp(BeamFileD1, BeamFileD2)),
+
+ {ok, B1} = file:read_file(BeamFileD1),
+ ok = beam_lib:cmp(B1, BeamFileD1),
+ {ok, B2} = file:read_file(BeamFileD2),
+ ver(chunks_different, beam_lib:cmp(B1, B2)),
- ?line true = (P0 == pps()),
- ?line NoOfTables = length(ets:all()),
+ true = (P0 == pps()),
+ NoOfTables = length(ets:all()),
- ?line delete_files([SourceD1, BeamFileD1, SourceD2, BeamFileD2]),
+ delete_files([SourceD1, BeamFileD1, SourceD2, BeamFileD2]),
file:del_dir(Dir1),
file:del_dir(Dir2),
ok.
-strip(suite) -> [];
-strip(doc) -> ["Strip BEAM files"];
+%% Strip BEAM files.
strip(Conf) when is_list(Conf) ->
- ?line PrivDir = ?privdir,
- ?line {SourceD1, BeamFileD1} = make_beam(PrivDir, simple, member),
- ?line {Source2D1, BeamFile2D1} = make_beam(PrivDir, simple2, concat),
- ?line {Source3D1, BeamFile3D1} = make_beam(PrivDir, make_fun, make_fun),
- ?line {Source4D1, BeamFile4D1} = make_beam(PrivDir, constant, constant),
- ?line {Source5D1, BeamFile5D1} = make_beam(PrivDir, lines, lines),
+ PrivDir = ?privdir,
+ {SourceD1, BeamFileD1} = make_beam(PrivDir, simple, member),
+ {Source2D1, BeamFile2D1} = make_beam(PrivDir, simple2, concat),
+ {Source3D1, BeamFile3D1} = make_beam(PrivDir, make_fun, make_fun),
+ {Source4D1, BeamFile4D1} = make_beam(PrivDir, constant, constant),
+ {Source5D1, BeamFile5D1} = make_beam(PrivDir, lines, lines),
- ?line NoOfTables = length(ets:all()),
- ?line P0 = pps(),
+ NoOfTables = length(ets:all()),
+ P0 = pps(),
%% strip binary
- ?line verify(not_a_beam_file, beam_lib:strip(<<>>)),
- ?line {ok, B1} = file:read_file(BeamFileD1),
- ?line {ok, {simple, NB1}} = beam_lib:strip(B1),
- ?line BId1 = chunk_ids(B1),
- ?line NBId1 = chunk_ids(NB1),
- ?line true = length(BId1) > length(NBId1),
- ?line compare_chunks(B1, NB1, NBId1),
+ verify(not_a_beam_file, beam_lib:strip(<<>>)),
+ {ok, B1} = file:read_file(BeamFileD1),
+ {ok, {simple, NB1}} = beam_lib:strip(B1),
+ BId1 = chunk_ids(B1),
+ NBId1 = chunk_ids(NB1),
+ true = length(BId1) > length(NBId1),
+ compare_chunks(B1, NB1, NBId1),
%% strip file
- ?line verify(file_error, beam_lib:strip(foo)),
- ?line {ok, {simple, _}} = beam_lib:strip(BeamFileD1),
- ?line compare_chunks(NB1, BeamFileD1, NBId1),
+ verify(file_error, beam_lib:strip(foo)),
+ {ok, {simple, _}} = beam_lib:strip(BeamFileD1),
+ compare_chunks(NB1, BeamFileD1, NBId1),
%% strip_files
- ?line {ok, B2} = file:read_file(BeamFile2D1),
- ?line {ok, [{simple,_},{simple2,_}]} = beam_lib:strip_files([B1, B2]),
- ?line {ok, [{simple,_},{simple2,_},{make_fun,_},{constant,_}]} =
+ {ok, B2} = file:read_file(BeamFile2D1),
+ {ok, [{simple,_},{simple2,_}]} = beam_lib:strip_files([B1, B2]),
+ {ok, [{simple,_},{simple2,_},{make_fun,_},{constant,_}]} =
beam_lib:strip_files([BeamFileD1, BeamFile2D1, BeamFile3D1, BeamFile4D1]),
%% check that each module can be loaded.
- ?line {module, simple} = code:load_abs(filename:rootname(BeamFileD1)),
- ?line {module, simple2} = code:load_abs(filename:rootname(BeamFile2D1)),
- ?line {module, make_fun} = code:load_abs(filename:rootname(BeamFile3D1)),
- ?line {module, constant} = code:load_abs(filename:rootname(BeamFile4D1)),
+ {module, simple} = code:load_abs(filename:rootname(BeamFileD1)),
+ {module, simple2} = code:load_abs(filename:rootname(BeamFile2D1)),
+ {module, make_fun} = code:load_abs(filename:rootname(BeamFile3D1)),
+ {module, constant} = code:load_abs(filename:rootname(BeamFile4D1)),
%% check that line number information is still present after stripping
- ?line {module, lines} = code:load_abs(filename:rootname(BeamFile5D1)),
- ?line {'EXIT',{badarith,[{lines,t,1,Info}|_]}} =
+ {module, lines} = code:load_abs(filename:rootname(BeamFile5D1)),
+ {'EXIT',{badarith,[{lines,t,1,Info}|_]}} =
(catch lines:t(atom)),
- ?line true = code:delete(lines),
- ?line false = code:purge(lines),
- ?line {ok, {lines,BeamFile5D1}} = beam_lib:strip(BeamFile5D1),
- ?line {module, lines} = code:load_abs(filename:rootname(BeamFile5D1)),
- ?line {'EXIT',{badarith,[{lines,t,1,Info}|_]}} =
+ true = code:delete(lines),
+ false = code:purge(lines),
+ {ok, {lines,BeamFile5D1}} = beam_lib:strip(BeamFile5D1),
+ {module, lines} = code:load_abs(filename:rootname(BeamFile5D1)),
+ {'EXIT',{badarith,[{lines,t,1,Info}|_]}} =
(catch lines:t(atom)),
- ?line true = (P0 == pps()),
- ?line NoOfTables = length(ets:all()),
+ true = (P0 == pps()),
+ NoOfTables = length(ets:all()),
- ?line delete_files([SourceD1, BeamFileD1,
- Source2D1, BeamFile2D1,
- Source3D1, BeamFile3D1,
- Source4D1, BeamFile4D1,
- Source5D1, BeamFile5D1]),
+ delete_files([SourceD1, BeamFileD1,
+ Source2D1, BeamFile2D1,
+ Source3D1, BeamFile3D1,
+ Source4D1, BeamFile4D1,
+ Source5D1, BeamFile5D1]),
ok.
otp_6711(Conf) when is_list(Conf) ->
- ?line {'EXIT',{function_clause,_}} = (catch {a, beam_lib:info(3)}),
- ?line {'EXIT',{function_clause,_}} = (catch {a, beam_lib:chunks(a, b)}),
- ?line {'EXIT',{function_clause,_}} = (catch {a, beam_lib:chunks(a,b,c)}),
- ?line {'EXIT',{function_clause,_}} = (catch {a, beam_lib:all_chunks(3)}),
- ?line {'EXIT',{function_clause,_}} = (catch {a, beam_lib:cmp(3,4)}),
- ?line {'EXIT',{function_clause,_}} = (catch {a, beam_lib:strip(3)}),
- ?line {'EXIT',{function_clause,_}} =
+ {'EXIT',{function_clause,_}} = (catch {a, beam_lib:info(3)}),
+ {'EXIT',{function_clause,_}} = (catch {a, beam_lib:chunks(a, b)}),
+ {'EXIT',{function_clause,_}} = (catch {a, beam_lib:chunks(a,b,c)}),
+ {'EXIT',{function_clause,_}} = (catch {a, beam_lib:all_chunks(3)}),
+ {'EXIT',{function_clause,_}} = (catch {a, beam_lib:cmp(3,4)}),
+ {'EXIT',{function_clause,_}} = (catch {a, beam_lib:strip(3)}),
+ {'EXIT',{function_clause,_}} =
(catch {a, beam_lib:strip_files([3])}),
- ?line PrivDir = ?privdir,
- ?line Dir = filename:join(PrivDir, "dir"),
- ?line Lib = filename:join(Dir, "lib"),
- ?line App = filename:join(Lib, "app"),
- ?line EBin = filename:join(App, "ebin"),
+ PrivDir = ?privdir,
+ Dir = filename:join(PrivDir, "dir"),
+ Lib = filename:join(Dir, "lib"),
+ App = filename:join(Lib, "app"),
+ EBin = filename:join(App, "ebin"),
ok = file:make_dir(Dir),
ok = file:make_dir(Lib),
ok = file:make_dir(App),
ok = file:make_dir(EBin),
-
- ?line {SourceD, BeamFileD} = make_beam(EBin, simple, member),
+
+ {SourceD, BeamFileD} = make_beam(EBin, simple, member),
unwritable(BeamFileD),
%% There is no way that strip_release can fail with
%% function_clause or something like that...
- ?line {error,_,{file_error,_,_}} = beam_lib:strip_release(Dir),
+ {error,_,{file_error,_,_}} = beam_lib:strip_release(Dir),
- ?line delete_files([SourceD, BeamFileD]),
+ delete_files([SourceD, BeamFileD]),
file:del_dir(EBin),
file:del_dir(App),
file:del_dir(Lib),
@@ -434,59 +426,58 @@ unwritable(Fname) ->
Mode = Info#file_info.mode - 8#00200,
file:write_file_info(Fname, Info#file_info{mode = Mode}).
-building(doc) -> "Testing building of BEAM files.";
+%% Testing building of BEAM files.
building(Conf) when is_list(Conf) ->
- ?line PrivDir = ?privdir,
+ PrivDir = ?privdir,
- ?line Dir1 = filename:join(PrivDir, "b_dir1"),
- ?line Dir2 = filename:join(PrivDir, "b_dir2"),
+ Dir1 = filename:join(PrivDir, "b_dir1"),
+ Dir2 = filename:join(PrivDir, "b_dir2"),
ok = file:make_dir(Dir1),
ok = file:make_dir(Dir2),
- ?line {SourceD1, BeamFileD1} = make_beam(Dir1, building, member),
+ {SourceD1, BeamFileD1} = make_beam(Dir1, building, member),
- ?line NoOfTables = length(ets:all()),
- ?line P0 = pps(),
+ NoOfTables = length(ets:all()),
+ P0 = pps(),
%% read all chunks
- ?line ChunkIds = chunk_ids(BeamFileD1),
- ?line {ok, _Mod, Chunks} = beam_lib:all_chunks(BeamFileD1),
- ?line ChunkIds = lists:map(fun ({Id, Data}) when is_binary(Data) -> Id
- end, Chunks),
+ ChunkIds = chunk_ids(BeamFileD1),
+ {ok, _Mod, Chunks} = beam_lib:all_chunks(BeamFileD1),
+ ChunkIds = lists:map(fun ({Id, Data}) when is_binary(Data) -> Id
+ end, Chunks),
%% write a new beam file, with reversed chunk order
- ?line BeamFileD2 = filename:join(Dir2, "building.beam"),
- ?line {ok,RevBeam} = beam_lib:build_module(lists:reverse(Chunks)),
- ?line file:write_file(BeamFileD2, RevBeam),
+ BeamFileD2 = filename:join(Dir2, "building.beam"),
+ {ok,RevBeam} = beam_lib:build_module(lists:reverse(Chunks)),
+ file:write_file(BeamFileD2, RevBeam),
%% compare files
- ?line compare_chunks(BeamFileD1, BeamFileD2, ChunkIds),
+ compare_chunks(BeamFileD1, BeamFileD2, ChunkIds),
%% test that we can retrieve a chunk before the atom table
%% (actually, try to retrieve all chunks)
- ?line lists:foreach(fun(Id) ->
- {ok, {building, [{Id, _Data}]}} =
- beam_lib:chunks(BeamFileD1, [Id])
- end, ChunkIds),
- ?line lists:foreach(fun(Id) ->
- {ok, {building, [{Id, _Data}]}} =
- beam_lib:chunks(BeamFileD2, [Id])
- end, ChunkIds),
+ lists:foreach(fun(Id) ->
+ {ok, {building, [{Id, _Data}]}} =
+ beam_lib:chunks(BeamFileD1, [Id])
+ end, ChunkIds),
+ lists:foreach(fun(Id) ->
+ {ok, {building, [{Id, _Data}]}} =
+ beam_lib:chunks(BeamFileD2, [Id])
+ end, ChunkIds),
- ?line true = (P0 == pps()),
- ?line NoOfTables = length(ets:all()),
+ true = (P0 == pps()),
+ NoOfTables = length(ets:all()),
- ?line delete_files([SourceD1, BeamFileD1, BeamFileD2]),
+ delete_files([SourceD1, BeamFileD1, BeamFileD2]),
file:del_dir(Dir1),
file:del_dir(Dir2),
ok.
-md5(suite) -> [];
-md5(doc) -> ["Compare beam_lib:md5/1 and code:module_md5/1."];
+%% Compare beam_lib:md5/1 and code:module_md5/1.
md5(Conf) when is_list(Conf) ->
- ?line Beams = collect_beams(),
+ Beams = collect_beams(),
io:format("Found ~w beam files", [length(Beams)]),
md5_1(Beams).
@@ -497,7 +488,7 @@ md5_1([N|Ns]) ->
{Mod,MD5} = {Mod,code:module_md5(Beam)},
md5_1(Ns);
md5_1([]) -> ok.
-
+
collect_beams() ->
SuperDir = filename:dirname(filename:dirname(code:which(?MODULE))),
TestDirs = filelib:wildcard(filename:join([SuperDir,"*_test"])),
@@ -511,90 +502,89 @@ collect_beams_1([]) -> [].
maybe_uncompress(<<"FOR1",_/binary>>=Beam) -> Beam;
maybe_uncompress(Beam) -> zlib:gunzip(Beam).
-encrypted_abstr(suite) -> [];
-encrypted_abstr(doc) -> ["Test encrypted abstract format"];
+%% Test encrypted abstract format.
encrypted_abstr(Conf) when is_list(Conf) ->
run_if_crypto_works(fun() -> encrypted_abstr_1(Conf) end).
encrypted_abstr_1(Conf) ->
- ?line PrivDir = ?privdir,
- ?line Simple = filename:join(PrivDir, "simple"),
- ?line Source = Simple ++ ".erl",
- ?line BeamFile = Simple ++ ".beam",
- ?line simple_file(Source),
+ PrivDir = ?privdir,
+ Simple = filename:join(PrivDir, "simple"),
+ Source = Simple ++ ".erl",
+ BeamFile = Simple ++ ".beam",
+ simple_file(Source),
%% Avoid getting an extra port when crypto starts erl_ddll.
- ?line erl_ddll:start(),
+ erl_ddll:start(),
- ?line NoOfTables = length(ets:all()),
- ?line P0 = pps(),
+ NoOfTables = length(ets:all()),
+ P0 = pps(),
Key = "#a_crypto_key",
CompileFlags = [{outdir,PrivDir}, debug_info, {debug_info_key,Key}],
- ?line {ok,_} = compile:file(Source, CompileFlags),
- ?line {ok, Binary} = file:read_file(BeamFile),
+ {ok,_} = compile:file(Source, CompileFlags),
+ {ok, Binary} = file:read_file(BeamFile),
- ?line do_encrypted_abstr(BeamFile, Key),
- ?line do_encrypted_abstr(Binary, Key),
+ do_encrypted_abstr(BeamFile, Key),
+ do_encrypted_abstr(Binary, Key),
- ?line ok = crypto:stop(), %To get rid of extra ets tables.
- ?line file:delete(BeamFile),
- ?line file:delete(Source),
- ?line NoOfTables = length(ets:all()),
- ?line true = (P0 == pps()),
+ ok = crypto:stop(), %To get rid of extra ets tables.
+ file:delete(BeamFile),
+ file:delete(Source),
+ NoOfTables = length(ets:all()),
+ true = (P0 == pps()),
ok.
do_encrypted_abstr(Beam, Key) ->
- ?line verify(key_missing_or_invalid, beam_lib:chunks(Beam, [abstract_code])),
+ verify(key_missing_or_invalid, beam_lib:chunks(Beam, [abstract_code])),
%% The raw chunk "Abst" can still be read even without a key.
- ?line {ok,{simple,[{"Abst",Abst}]}} = beam_lib:chunks(Beam, ["Abst"]),
- ?line <<0:8,8:8,"des3_cbc",_/binary>> = Abst,
+ {ok,{simple,[{"Abst",Abst}]}} = beam_lib:chunks(Beam, ["Abst"]),
+ <<0:8,8:8,"des3_cbc",_/binary>> = Abst,
%% Try som invalid funs.
- ?line bad_fun(badfun, fun() -> ok end),
- ?line bad_fun(badfun, {a,b}),
- ?line bad_fun(blurf),
- ?line {function_clause,_} = bad_fun(fun(glurf) -> ok end),
+ bad_fun(badfun, fun() -> ok end),
+ bad_fun(badfun, {a,b}),
+ bad_fun(blurf),
+ {function_clause,_} = bad_fun(fun(glurf) -> ok end),
%% Funs that return something strange.
- ?line bad_fun(badfun, fun(init) -> {ok,fun() -> ok end} end),
- ?line glurf = bad_fun(fun(init) -> {error,glurf} end),
+ bad_fun(badfun, fun(init) -> {ok,fun() -> ok end} end),
+ glurf = bad_fun(fun(init) -> {error,glurf} end),
%% Try clearing (non-existing fun).
- ?line undefined = beam_lib:clear_crypto_key_fun(),
+ undefined = beam_lib:clear_crypto_key_fun(),
%% Install a fun which cannot retrieve a key.
- ?line ok = beam_lib:crypto_key_fun(fun(init) -> ok end),
- ?line {error,beam_lib,Error} = beam_lib:chunks(Beam, [abstract_code]),
+ ok = beam_lib:crypto_key_fun(fun(init) -> ok end),
+ {error,beam_lib,Error} = beam_lib:chunks(Beam, [abstract_code]),
%% Install a fun which returns an incorrect key.
- ?line {ok,_} = beam_lib:clear_crypto_key_fun(),
- ?line ok = beam_lib:crypto_key_fun(simple_crypto_fun("wrong key...")),
- ?line {error,beam_lib,Error} = beam_lib:chunks(Beam, [abstract_code]),
-
+ {ok,_} = beam_lib:clear_crypto_key_fun(),
+ ok = beam_lib:crypto_key_fun(simple_crypto_fun("wrong key...")),
+ {error,beam_lib,Error} = beam_lib:chunks(Beam, [abstract_code]),
+
%% Installing a new key fun is not possible without clearing the old.
- ?line verify(exists, beam_lib:crypto_key_fun(simple_crypto_fun(Key))),
+ verify(exists, beam_lib:crypto_key_fun(simple_crypto_fun(Key))),
%% Install the simplest possible working key fun.
- ?line {ok,_} = beam_lib:clear_crypto_key_fun(),
- ?line ok = beam_lib:crypto_key_fun(simple_crypto_fun(Key)),
- ?line verify_abstract(Beam),
- ?line {ok,{simple,[{"Abst",Abst}]}} = beam_lib:chunks(Beam, ["Abst"]),
+ {ok,_} = beam_lib:clear_crypto_key_fun(),
+ ok = beam_lib:crypto_key_fun(simple_crypto_fun(Key)),
+ verify_abstract(Beam),
+ {ok,{simple,[{"Abst",Abst}]}} = beam_lib:chunks(Beam, ["Abst"]),
%% Installing a new key fun is not possible without clearing the old.
verify(exists, beam_lib:crypto_key_fun(ets_crypto_fun(Key))),
%% Install a key using an ets table.
- ?line {ok,_} = beam_lib:clear_crypto_key_fun(),
- ?line ok = beam_lib:crypto_key_fun(ets_crypto_fun(Key)),
- ?line verify_abstract(Beam),
- ?line {ok,{simple,[{"Abst",Abst}]}} = beam_lib:chunks(Beam, ["Abst"]),
+ {ok,_} = beam_lib:clear_crypto_key_fun(),
+ ok = beam_lib:crypto_key_fun(ets_crypto_fun(Key)),
+ verify_abstract(Beam),
+ {ok,{simple,[{"Abst",Abst}]}} = beam_lib:chunks(Beam, ["Abst"]),
- ?line {ok,cleared} = beam_lib:clear_crypto_key_fun(),
+ {ok,cleared} = beam_lib:clear_crypto_key_fun(),
%% Try to force a stop/start race.
- ?line start_stop_race(10000),
+ start_stop_race(10000),
ok.
@@ -635,69 +625,67 @@ ets_crypto_fun(Key) ->
end}
end.
-encrypted_abstr_file(suite) -> [];
-encrypted_abstr_file(doc) ->
- ["Test encrypted abstract format with the key in .erlang.crypt"];
+%% Test encrypted abstract format with the key in .erlang.crypt.
encrypted_abstr_file(Conf) when is_list(Conf) ->
run_if_crypto_works(fun() -> encrypted_abstr_file_1(Conf) end).
encrypted_abstr_file_1(Conf) ->
- ?line PrivDir = ?privdir,
- ?line Simple = filename:join(PrivDir, "simple"),
- ?line Source = Simple ++ ".erl",
- ?line BeamFile = Simple ++ ".beam",
- ?line simple_file(Source),
+ PrivDir = ?privdir,
+ Simple = filename:join(PrivDir, "simple"),
+ Source = Simple ++ ".erl",
+ BeamFile = Simple ++ ".beam",
+ simple_file(Source),
%% Avoid getting an extra port when crypto starts erl_ddll.
- ?line erl_ddll:start(),
+ erl_ddll:start(),
- ?line NoOfTables = length(ets:all()),
- ?line P0 = pps(),
+ NoOfTables = length(ets:all()),
+ P0 = pps(),
Key = "Long And niCe 99Krypto Key",
CompileFlags = [{outdir,PrivDir}, debug_info, {debug_info_key,Key}],
- ?line {ok,_} = compile:file(Source, CompileFlags),
- ?line {ok, Binary} = file:read_file(BeamFile),
-
- ?line {ok,OldCwd} = file:get_cwd(),
- ?line ok = file:set_cwd(PrivDir),
- ?line do_encrypted_abstr_file(BeamFile, Key),
- ?line do_encrypted_abstr_file(Binary, Key),
- ?line ok = file:set_cwd(OldCwd),
-
- ?line ok = crypto:stop(), %To get rid of extra ets tables.
- ?line file:delete(filename:join(PrivDir, ".erlang.crypt")),
- ?line file:delete(BeamFile),
- ?line file:delete(Source),
- ?line NoOfTables = length(ets:all()),
- ?line true = (P0 == pps()),
+ {ok,_} = compile:file(Source, CompileFlags),
+ {ok, Binary} = file:read_file(BeamFile),
+
+ {ok,OldCwd} = file:get_cwd(),
+ ok = file:set_cwd(PrivDir),
+ do_encrypted_abstr_file(BeamFile, Key),
+ do_encrypted_abstr_file(Binary, Key),
+ ok = file:set_cwd(OldCwd),
+
+ ok = crypto:stop(), %To get rid of extra ets tables.
+ file:delete(filename:join(PrivDir, ".erlang.crypt")),
+ file:delete(BeamFile),
+ file:delete(Source),
+ NoOfTables = length(ets:all()),
+ true = (P0 == pps()),
ok.
do_encrypted_abstr_file(Beam, Key) ->
%% No key.
- ?line write_crypt_file(""),
- ?line {error,beam_lib,Error} = beam_lib:chunks(Beam, [abstract_code]),
+ write_crypt_file(""),
+ {error,beam_lib,Error} = beam_lib:chunks(Beam, [abstract_code]),
%% A wrong key.
- ?line write_crypt_file(["[{debug_info,des3_cbc,simple,\"A Wrong Key\"}].\n"]),
- ?line {error,beam_lib,Error} = beam_lib:chunks(Beam, [abstract_code]),
+ write_crypt_file(["[{debug_info,des3_cbc,simple,\"A Wrong Key\"}].\n"]),
+ {error,beam_lib,Error} = beam_lib:chunks(Beam, [abstract_code]),
%% Write correct key...
- ?line write_crypt_file(["[{debug_info,des3_cbc,simple,\"",Key,"\"}].\n"]),
+ write_crypt_file(["[{debug_info,des3_cbc,simple,\"",Key,"\"}].\n"]),
%% ... but the fun with the wrong key is still there.
- ?line {error,beam_lib,Error} = beam_lib:chunks(Beam, [abstract_code]),
+ {error,beam_lib,Error} = beam_lib:chunks(Beam, [abstract_code]),
%% Clear the fun. Now it should work.
- ?line {ok,_} = beam_lib:clear_crypto_key_fun(),
- ?line verify_abstract(Beam),
- ?line verify_abstract(Beam),
- ?line ok = file:delete(".erlang.crypt"),
- ?line verify_abstract(Beam),
+ {ok,_} = beam_lib:clear_crypto_key_fun(),
+ verify_abstract(Beam),
+ verify_abstract(Beam),
+ ok = file:delete(".erlang.crypt"),
+ verify_abstract(Beam),
%% Clear, otherwise the second pass will fail.
- ?line {ok,_} = beam_lib:clear_crypto_key_fun(),
- ?line {error,beam_lib,Error} = beam_lib:chunks(Beam, [abstract_code]),
+ {ok,_} = beam_lib:clear_crypto_key_fun(),
+ {error,beam_lib,Error} = beam_lib:chunks(Beam, [abstract_code]),
ok.
write_crypt_file(Contents0) ->
@@ -706,45 +694,44 @@ write_crypt_file(Contents0) ->
ok = file:write_file(".erlang.crypt", Contents).
compare_chunks(File1, File2, ChunkIds) ->
- ?line {ok, {_, Chunks1}} = beam_lib:chunks(File1, ChunkIds),
- ?line {ok, {_, Chunks2}} = beam_lib:chunks(File2, ChunkIds),
- ?line true = Chunks1 == Chunks2.
+ {ok, {_, Chunks1}} = beam_lib:chunks(File1, ChunkIds),
+ {ok, {_, Chunks2}} = beam_lib:chunks(File2, ChunkIds),
+ true = Chunks1 == Chunks2.
chunk_ids(File) ->
- ?line lists:map(fun({Id,_Start,_Size}) -> Id end, chunk_info(File)).
-
+ lists:map(fun({Id,_Start,_Size}) -> Id end, chunk_info(File)).
+
chunk_info(File) ->
- ?line {value, {chunks, Chunks}} =
+ {value, {chunks, Chunks}} =
lists:keysearch(chunks, 1, beam_lib:info(File)),
Chunks.
-
+
make_beam(Dir, Module, F) ->
- ?line FileBase = filename:join(Dir, atom_to_list(Module)),
- ?line Source = FileBase ++ ".erl",
- ?line BeamFile = FileBase ++ ".beam",
- ?line simple_file(Source, Module, F),
- ?line {ok, _} = compile:file(Source, [{outdir,Dir}, debug_info, report]),
+ FileBase = filename:join(Dir, atom_to_list(Module)),
+ Source = FileBase ++ ".erl",
+ BeamFile = FileBase ++ ".beam",
+ simple_file(Source, Module, F),
+ {ok, _} = compile:file(Source, [{outdir,Dir}, debug_info, report]),
{Source, BeamFile}.
set_byte(_Backup, Binary, Pos, Byte) when is_binary(Binary) ->
- ?line <<B1:Pos/binary, _:1/binary, B2/binary>> = Binary,
+ <<B1:Pos/binary, _:1/binary, B2/binary>> = Binary,
NB = <<B1/binary, Byte:8, B2/binary>>,
NB;
set_byte(Backup, File, Pos, Byte) ->
- ?line copy_file(Backup, File),
- ?line set_byte(File, Pos, Byte),
+ copy_file(Backup, File),
+ set_byte(File, Pos, Byte),
File.
set_byte(File, Pos, Byte) ->
- ?line {ok, Fd} = file:open(File, [read, write]),
- ?line {ok, _} = file:position(Fd, Pos),
- ?line ok = file:write(Fd, [Byte]),
- ?line file:close(Fd).
+ {ok, Fd} = file:open(File, [read, write]),
+ {ok, _} = file:position(Fd, Pos),
+ ok = file:write(Fd, [Byte]),
+ file:close(Fd).
copy_file(Src, Dest) ->
- % ?t:format("copying from ~p to ~p~n", [Src, Dest]),
- ?line {ok, _} = file:copy(Src, Dest),
- ?line ok = file:change_mode(Dest, 8#0666).
+ {ok, _} = file:copy(Src, Dest),
+ ok = file:change_mode(Dest, 8#0666).
delete_files(Files) ->
lists:foreach(fun(F) -> file:delete(F) end, Files).
@@ -772,7 +759,7 @@ ver(S, {error, beam_lib, R}) ->
[S|_] = tuple_to_list(R),
case lists:flatten(beam_lib:format_error(R)) of
[${ | _] ->
- test_server:fail({bad_format_error, R});
+ ct:fail({bad_format_error, R});
_ ->
ok
end.
diff --git a/lib/stdlib/test/binary_module_SUITE.erl b/lib/stdlib/test/binary_module_SUITE.erl
index 70c946bdb9..285740d3e0 100644
--- a/lib/stdlib/test/binary_module_SUITE.erl
+++ b/lib/stdlib/test/binary_module_SUITE.erl
@@ -20,6 +20,7 @@
-module(binary_module_SUITE).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2,
init_per_group/2,end_per_group/2,
interesting/1,scope_return/1,random_ref_comp/1,random_ref_sr_comp/1,
random_ref_fla_comp/1,parts/1, bin_to_list/1, list_to_bin/1,
@@ -27,45 +28,17 @@
-export([random_number/1, make_unaligned/1]).
-
-
-%%-define(STANDALONE,1).
-
--ifdef(STANDALONE).
-
--define(line,erlang:display({?MODULE,?LINE}),).
-
--else.
-
--include_lib("test_server/include/test_server.hrl").
--export([init_per_testcase/2, end_per_testcase/2]).
-% Default timetrap timeout (set in init_per_testcase).
-% Some of these testcases are really heavy...
--define(default_timeout, ?t:minutes(30)).
-
--endif.
-
-
-
--ifdef(STANDALONE).
--export([run/0]).
-
-run() ->
- [ apply(?MODULE,X,[[]]) || X <- all(suite) ].
-
--else.
+-include_lib("common_test/include/ct.hrl").
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- ?line Dog = ?config(watchdog, Config),
- ?line test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
--endif.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,30}}].
all() ->
[scope_return,interesting, random_ref_fla_comp, random_ref_sr_comp,
@@ -92,300 +65,297 @@ end_per_group(_GroupName, Config) ->
-define(MASK_ERROR(EXPR),mask_error((catch (EXPR)))).
-badargs(doc) ->
- ["Tests various badarg exceptions in the module"];
+%% Test various badarg exceptions in the module.
badargs(Config) when is_list(Config) ->
- ?line badarg = ?MASK_ERROR(binary:compile_pattern([<<1,2,3:3>>])),
- ?line badarg = ?MASK_ERROR(binary:compile_pattern([<<1,2,3>>|<<1,2>>])),
- ?line badarg = ?MASK_ERROR(binary:compile_pattern(<<1,2,3:3>>)),
- ?line badarg = ?MASK_ERROR(binary:compile_pattern(<<>>)),
- ?line badarg = ?MASK_ERROR(binary:match(<<1,2,3:3>>,<<1>>)),
- ?line badarg = ?MASK_ERROR(binary:matches(<<1,2,3:3>>,<<1>>)),
- ?line badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
- [{scope,{0,1},1}])),
- ?line badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
- [{scape,{0,1}}])),
- ?line badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
- [{scope,{0,1,1}}])),
- ?line badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,[{scope,0,1}])),
- ?line badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,[{scope,[0,1]}])),
- ?line badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
- [{scope,{0.1,1}}])),
- ?line badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
- [{scope,{1,1.1}}])),
- ?line badarg =
+ badarg = ?MASK_ERROR(binary:compile_pattern([<<1,2,3:3>>])),
+ badarg = ?MASK_ERROR(binary:compile_pattern([<<1,2,3>>|<<1,2>>])),
+ badarg = ?MASK_ERROR(binary:compile_pattern(<<1,2,3:3>>)),
+ badarg = ?MASK_ERROR(binary:compile_pattern(<<>>)),
+ badarg = ?MASK_ERROR(binary:match(<<1,2,3:3>>,<<1>>)),
+ badarg = ?MASK_ERROR(binary:matches(<<1,2,3:3>>,<<1>>)),
+ badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
+ [{scope,{0,1},1}])),
+ badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
+ [{scape,{0,1}}])),
+ badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
+ [{scope,{0,1,1}}])),
+ badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,[{scope,0,1}])),
+ badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,[{scope,[0,1]}])),
+ badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
+ [{scope,{0.1,1}}])),
+ badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
+ [{scope,{1,1.1}}])),
+ badarg =
?MASK_ERROR(
binary:match(<<1,2,3>>,<<1>>,
[{scope,{16#FF,
16#FFFFFFFFFFFFFFFF}}])),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:match(<<1,2,3>>,<<1>>,
[{scope,{16#FFFFFFFFFFFFFFFF,
-16#7FFFFFFFFFFFFFFF-1}}])),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:match(<<1,2,3>>,<<1>>,
[{scope,{16#FFFFFFFFFFFFFFFF,
16#7FFFFFFFFFFFFFFF}}])),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:part(<<1,2,3>>,{16#FF,
- 16#FFFFFFFFFFFFFFFF})),
- ?line badarg =
+ 16#FFFFFFFFFFFFFFFF})),
+ badarg =
?MASK_ERROR(
binary:part(<<1,2,3>>,{16#FFFFFFFFFFFFFFFF,
- -16#7FFFFFFFFFFFFFFF-1})),
- ?line badarg =
+ -16#7FFFFFFFFFFFFFFF-1})),
+ badarg =
?MASK_ERROR(
binary:part(<<1,2,3>>,{16#FFFFFFFFFFFFFFFF,
- 16#7FFFFFFFFFFFFFFF})),
- ?line badarg =
+ 16#7FFFFFFFFFFFFFFF})),
+ badarg =
?MASK_ERROR(
binary:part(make_unaligned(<<1,2,3>>),{1,1,1})),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary_part(make_unaligned(<<1,2,3>>),{1,1,1})),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary_part(make_unaligned(<<1,2,3>>),{16#FFFFFFFFFFFFFFFF,
- -16#7FFFFFFFFFFFFFFF-1})),
- ?line badarg =
+ -16#7FFFFFFFFFFFFFFF-1})),
+ badarg =
?MASK_ERROR(
binary_part(make_unaligned(<<1,2,3>>),{16#FF,
- 16#FFFFFFFFFFFFFFFF})),
- ?line badarg =
+ 16#FFFFFFFFFFFFFFFF})),
+ badarg =
?MASK_ERROR(
binary_part(make_unaligned(<<1,2,3>>),{16#FFFFFFFFFFFFFFFF,
- 16#7FFFFFFFFFFFFFFF})),
- ?line badarg =
+ 16#7FFFFFFFFFFFFFFF})),
+ badarg =
?MASK_ERROR(
binary_part(make_unaligned(<<1,2,3>>),{16#FFFFFFFFFFFFFFFFFF,
- -16#7FFF})),
- ?line badarg =
+ -16#7FFF})),
+ badarg =
?MASK_ERROR(
binary_part(make_unaligned(<<1,2,3>>),{16#FF,
- -16#7FFF})),
- ?line badarg =
+ -16#7FFF})),
+ badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3>>,{16#FF,
- 16#FFFFFFFFFFFFFFFF})),
- ?line badarg =
+ 16#FFFFFFFFFFFFFFFF})),
+ badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3>>,{16#FFFFFFFFFFFFFFFF,
- -16#7FFFFFFFFFFFFFFF-1})),
- ?line badarg =
+ -16#7FFFFFFFFFFFFFFF-1})),
+ badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3>>,{16#FFFFFFFFFFFFFFFF,
- 16#7FFFFFFFFFFFFFFF})),
- ?line [1,2,3] =
+ 16#7FFFFFFFFFFFFFFF})),
+ [1,2,3] =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3>>)),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3>>,[])),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3>>,{1,2,3})),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3>>,{1.0,1})),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3>>,{1,1.0})),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3:3>>,{1,1})),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3:3>>)),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:bin_to_list([1,2,3])),
- ?line nomatch =
+ nomatch =
?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,[{scope,{0,0}}])),
- ?line badarg =
+ badarg =
?MASK_ERROR(binary:match(<<1,2,3>>,{bm,<<>>},[{scope,{0,1}}])),
- ?line badarg =
+ badarg =
?MASK_ERROR(binary:match(<<1,2,3>>,[],[{scope,{0,1}}])),
- ?line badarg =
+ badarg =
?MASK_ERROR(binary:match(<<1,2,3>>,{ac,<<>>},[{scope,{0,1}}])),
- ?line {bm,BMMagic} = binary:compile_pattern([<<1,2,3>>]),
- ?line {ac,ACMagic} = binary:compile_pattern([<<1,2,3>>,<<4,5>>]),
- ?line badarg =
+ {bm,BMMagic} = binary:compile_pattern([<<1,2,3>>]),
+ {ac,ACMagic} = binary:compile_pattern([<<1,2,3>>,<<4,5>>]),
+ badarg =
?MASK_ERROR(binary:match(<<1,2,3>>,{bm,ACMagic},[{scope,{0,1}}])),
- ?line badarg =
+ badarg =
?MASK_ERROR(binary:match(<<1,2,3>>,{ac,BMMagic},[{scope,{0,1}}])),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:match(<<1,2,3>>,
{bm,ets:match_spec_compile([{'_',[],['$_']}])},
[{scope,{0,1}}])),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:match(<<1,2,3>>,
{ac,ets:match_spec_compile([{'_',[],['$_']}])},
[{scope,{0,1}}])),
- ?line [] =
+ [] =
?MASK_ERROR(binary:matches(<<1,2,3>>,<<1>>,[{scope,{0,0}}])),
- ?line badarg =
+ badarg =
?MASK_ERROR(binary:matches(<<1,2,3>>,{bm,<<>>},[{scope,{0,1}}])),
- ?line badarg =
+ badarg =
?MASK_ERROR(binary:matches(<<1,2,3>>,[],[{scope,{0,1}}])),
- ?line badarg =
+ badarg =
?MASK_ERROR(binary:matches(<<1,2,3>>,{ac,<<>>},[{scope,{0,1}}])),
- ?line badarg =
+ badarg =
?MASK_ERROR(binary:matches(<<1,2,3>>,{bm,ACMagic},[{scope,{0,1}}])),
- ?line badarg =
+ badarg =
?MASK_ERROR(binary:matches(<<1,2,3>>,{ac,BMMagic},[{scope,{0,1}}])),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:matches(<<1,2,3>>,
- {bm,ets:match_spec_compile([{'_',[],['$_']}])},
- [{scope,{0,1}}])),
- ?line badarg =
+ {bm,ets:match_spec_compile([{'_',[],['$_']}])},
+ [{scope,{0,1}}])),
+ badarg =
?MASK_ERROR(
binary:matches(<<1,2,3>>,
- {ac,ets:match_spec_compile([{'_',[],['$_']}])},
- [{scope,{0,1}}])),
+ {ac,ets:match_spec_compile([{'_',[],['$_']}])},
+ [{scope,{0,1}}])),
%% OTP-11350
badarg = ?MASK_ERROR(
binary:matches(<<"foo">>,
[<<>>, <<"f">>])),
- ?line badarg =
+ badarg =
?MASK_ERROR(binary:longest_common_prefix(
[<<0:10000,1,2,4,1:3>>,
<<0:10000,1,2,3>>])),
- ?line badarg =
+ badarg =
?MASK_ERROR(binary:longest_common_suffix(
[<<0:10000,1,2,4,1:3>>,
<<0:10000,1,2,3>>])),
- ?line badarg =
+ badarg =
?MASK_ERROR(binary:encode_unsigned(-1)),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:encode_unsigned(-16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:first(<<1,2,4,1:3>>)),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:first([1,2,4])),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:last(<<1,2,4,1:3>>)),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:last([1,2,4])),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:at(<<1,2,4,1:3>>,2)),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:at(<<>>,2)),
- ?line badarg =
+ badarg =
?MASK_ERROR(
binary:at([1,2,4],2)),
ok.
-longest_common_trap(doc) ->
- ["Whitebox test to force special trap conditions in longest_common_{prefix,suffix}"];
+%% Whitebox test to force special trap conditions in
+%% longest_common_{prefix,suffix}.
longest_common_trap(Config) when is_list(Config) ->
- ?line erts_debug:set_internal_state(available_internal_state,true),
- ?line io:format("oldlimit: ~p~n",
- [erts_debug:set_internal_state(binary_loop_limit,10)]),
+ erts_debug:set_internal_state(available_internal_state,true),
+ io:format("oldlimit: ~p~n",
+ [erts_debug:set_internal_state(binary_loop_limit,10)]),
erlang:bump_reductions(10000000),
- ?line _ = binary:longest_common_prefix(
- [<<0:10000,1,2,4>>,
- <<0:10000,1,2,3>>,
- <<0:10000,1,3,3>>,
- <<0:10000,1,2,4>>,
- <<0:10000,1,2,4>>,
- <<0:10000,1,2,3>>,
- <<0:10000,1,3,3>>,
- <<0:10000,1,2,3>>,
- <<0:10000,1,3,3>>,
- <<0:10000,1,2,4>>,
- <<0:10000,1,2,4>>,
- <<0:10000,1,2,3>>,
- <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0:10000,1,3,3>>,
- <<0:10000,1,2,4>>]),
- ?line _ = binary:longest_common_prefix(
- [<<0:10000,1,2,4>>,
- <<0:10000,1,2,3>>,
- <<0:10000,1,3,3>>,
- <<0:10000,1,2,4>>,
- <<0:10000,1,2,4>>,
- <<0:10000,1,2,3>>,
- <<0:10000,1,3,3>>,
- <<0:10000,1,2,3>>,
- <<0:10000,1,3,3>>,
- <<0:10000,1,2,4>>,
- <<0:10000,1,2,4>>,
- <<0:10000,1,2,3>>,
- <<0,0,0,0,0,0,0,0,0,0,0,0,0,0>>,
- <<0:10000,1,2,4>>]),
+ _ = binary:longest_common_prefix(
+ [<<0:10000,1,2,4>>,
+ <<0:10000,1,2,3>>,
+ <<0:10000,1,3,3>>,
+ <<0:10000,1,2,4>>,
+ <<0:10000,1,2,4>>,
+ <<0:10000,1,2,3>>,
+ <<0:10000,1,3,3>>,
+ <<0:10000,1,2,3>>,
+ <<0:10000,1,3,3>>,
+ <<0:10000,1,2,4>>,
+ <<0:10000,1,2,4>>,
+ <<0:10000,1,2,3>>,
+ <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0:10000,1,3,3>>,
+ <<0:10000,1,2,4>>]),
+ _ = binary:longest_common_prefix(
+ [<<0:10000,1,2,4>>,
+ <<0:10000,1,2,3>>,
+ <<0:10000,1,3,3>>,
+ <<0:10000,1,2,4>>,
+ <<0:10000,1,2,4>>,
+ <<0:10000,1,2,3>>,
+ <<0:10000,1,3,3>>,
+ <<0:10000,1,2,3>>,
+ <<0:10000,1,3,3>>,
+ <<0:10000,1,2,4>>,
+ <<0:10000,1,2,4>>,
+ <<0:10000,1,2,3>>,
+ <<0,0,0,0,0,0,0,0,0,0,0,0,0,0>>,
+ <<0:10000,1,2,4>>]),
erlang:bump_reductions(10000000),
- ?line _ = binary:longest_common_suffix(
- [<<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,3,3,0:10000,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>,
- <<1,2,4,0:10000>>]),
- ?line _ = binary:longest_common_suffix(
- [<<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<1,2,4,0:10000>>,
- <<0,0,0,0,0,0,0,0,0,0,0,0,0,0>>,
- <<1,2,4,0:10000>>]),
+ _ = binary:longest_common_suffix(
+ [<<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,3,3,0:10000,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>,
+ <<1,2,4,0:10000>>]),
+ _ = binary:longest_common_suffix(
+ [<<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<0,0,0,0,0,0,0,0,0,0,0,0,0,0>>,
+ <<1,2,4,0:10000>>]),
Subj = subj(),
Len = byte_size(Subj),
- ?line Len = binary:longest_common_suffix(
- [Subj,Subj,Subj]),
- ?line io:format("limit was: ~p~n",
- [erts_debug:set_internal_state(binary_loop_limit,
- default)]),
- ?line erts_debug:set_internal_state(available_internal_state,false),
+ Len = binary:longest_common_suffix(
+ [Subj,Subj,Subj]),
+ io:format("limit was: ~p~n",
+ [erts_debug:set_internal_state(binary_loop_limit,
+ default)]),
+ erts_debug:set_internal_state(available_internal_state,false),
ok.
subj() ->
- Me = self(),
- spawn(fun() ->
- X0 = iolist_to_binary([
- "1234567890",
- %lists:seq(16#21, 16#7e),
- lists:duplicate(100, $x)
- ]),
- Me ! X0,
- receive X -> X end
- end),
- X0 = receive A -> A end,
- <<X1:32/binary,_/binary>> = X0,
- Subject= <<X1/binary>>,
- Subject.
-
-
-scope_return(doc) ->
- ["Test correct return values for scopes (OTP-9701)."];
+ Me = self(),
+ spawn(fun() ->
+ X0 = iolist_to_binary([
+ "1234567890",
+ lists:duplicate(100, $x)
+ ]),
+ Me ! X0,
+ receive X -> X end
+ end),
+ X0 = receive A -> A end,
+ <<X1:32/binary,_/binary>> = X0,
+ Subject= <<X1/binary>>,
+ Subject.
+
+
+%% Test correct return values for scopes (OTP-9701).
scope_return(Config) when is_list(Config) ->
N=10000,
Bin=binary:copy(<<"a">>,N),
@@ -394,358 +364,362 @@ scope_return(Config) when is_list(Config) ->
scope_loop(_,N,N) ->
ok;
scope_loop(Bin,N,M) ->
- ?line {N,1} = binary:match(Bin,<<"a">>,[{scope,{N,1}}]),
- ?line {N,1} = binary:match(Bin,[<<"a">>,<<"b">>],[{scope,{N,1}}]),
+ {N,1} = binary:match(Bin,<<"a">>,[{scope,{N,1}}]),
+ {N,1} = binary:match(Bin,[<<"a">>,<<"b">>],[{scope,{N,1}}]),
scope_loop(Bin,N+1,M).
-interesting(doc) ->
- ["Try some interesting patterns"];
+%% Try some interesting patterns.
interesting(Config) when is_list(Config) ->
X = do_interesting(binary),
X = do_interesting(binref).
do_interesting(Module) ->
- ?line {0,4} = Module:match(<<"123456">>,
+ {0,4} = Module:match(<<"123456">>,
Module:compile_pattern([<<"12">>,<<"1234">>,
<<"23">>,<<"3">>,
<<"34">>,<<"456">>,
<<"45">>,<<"6">>])),
- ?line [{0,4},{5,1}] = Module:matches(<<"123456">>,
+ [{0,4},{5,1}] = Module:matches(<<"123456">>,
Module:compile_pattern([<<"12">>,<<"1234">>,
<<"23">>,<<"3">>,
<<"34">>,<<"456">>,
<<"45">>,<<"6">>])),
- ?line [{0,4}] = Module:matches(<<"123456">>,
+ [{0,4}] = Module:matches(<<"123456">>,
Module:compile_pattern([<<"12">>,<<"1234">>,
<<"23">>,<<"3">>,
<<"34">>,<<"456">>,
<<"45">>])),
- ?line [{0,2},{2,2}] = Module:matches(<<"123456">>,
- Module:compile_pattern([<<"12">>,
- <<"23">>,<<"3">>,
- <<"34">>,<<"456">>,
- <<"45">>])),
- ?line {1,4} = Module:match(<<"123456">>,
+ [{0,2},{2,2}] = Module:matches(<<"123456">>,
+ Module:compile_pattern([<<"12">>,
+ <<"23">>,<<"3">>,
+ <<"34">>,<<"456">>,
+ <<"45">>])),
+ {1,4} = Module:match(<<"123456">>,
Module:compile_pattern([<<"34">>,<<"34">>,
<<"12347">>,<<"2345">>])),
- ?line [{1,4}] = Module:matches(<<"123456">>,
+ [{1,4}] = Module:matches(<<"123456">>,
Module:compile_pattern([<<"34">>,<<"34">>,
<<"12347">>,<<"2345">>])),
- ?line [{2,2}] = Module:matches(<<"123456">>,
+ [{2,2}] = Module:matches(<<"123456">>,
Module:compile_pattern([<<"34">>,<<"34">>,
<<"12347">>,<<"2346">>])),
- ?line {0,4} = Module:match(<<"123456">>,
+ {0,4} = Module:match(<<"123456">>,
[<<"12">>,<<"1234">>,
<<"23">>,<<"3">>,
<<"34">>,<<"456">>,
<<"45">>,<<"6">>]),
- ?line [{0,4},{5,1}] = Module:matches(<<"123456">>,
+ [{0,4},{5,1}] = Module:matches(<<"123456">>,
[<<"12">>,<<"1234">>,
<<"23">>,<<"3">>,
<<"34">>,<<"456">>,
<<"45">>,<<"6">>]),
- ?line [{0,4}] = Module:matches(<<"123456">>,
+ [{0,4}] = Module:matches(<<"123456">>,
[<<"12">>,<<"1234">>,
<<"23">>,<<"3">>,
<<"34">>,<<"456">>,
<<"45">>]),
- ?line [{0,2},{2,2}] = Module:matches(<<"123456">>,
- [<<"12">>,
- <<"23">>,<<"3">>,
- <<"34">>,<<"456">>,
- <<"45">>]),
- ?line {1,4} = Module:match(<<"123456">>,
- [<<"34">>,<<"34">>,
- <<"12347">>,<<"2345">>]),
- ?line [{1,4}] = Module:matches(<<"123456">>,
- [<<"34">>,<<"34">>,
- <<"12347">>,<<"2345">>]),
- ?line [{2,2}] = Module:matches(<<"123456">>,
- [<<"34">>,<<"34">>,
- <<"12347">>,<<"2346">>]),
- ?line nomatch = Module:match(<<1,2,3,4>>,<<2>>,[{scope,{0,1}}]),
- ?line {1,1} = Module:match(<<1,2,3,4>>,<<2>>,[{scope,{0,2}}]),
- ?line nomatch = Module:match(<<1,2,3,4>>,<<2,3>>,[{scope,{0,2}}]),
- ?line {1,2} = Module:match(<<1,2,3,4>>,<<2,3>>,[{scope,{0,3}}]),
- ?line {1,2} = Module:match(<<1,2,3,4>>,<<2,3>>,[{scope,{0,4}}]),
- ?line badarg = ?MASK_ERROR(Module:match(<<1,2,3,4>>,<<2,3>>,
- [{scope,{0,5}}])),
- ?line {1,2} = Module:match(<<1,2,3,4>>,<<2,3>>,[{scope,{4,-4}}]),
- ?line {0,3} = Module:match(<<1,2,3,4>>,<<1,2,3>>,[{scope,{4,-4}}]),
- ?line {0,4} = Module:match(<<1,2,3,4>>,<<1,2,3,4>>,[{scope,{4,-4}}]),
- ?line badarg = ?MASK_ERROR(Module:match(<<1,2,3,4>>,<<1,2,3,4>>,
- [{scope,{3,-4}}])),
- ?line [] = Module:matches(<<1,2,3,4>>,<<2>>,[{scope,{0,1}}]),
- ?line [{1,1}] = Module:matches(<<1,2,3,4>>,[<<2>>,<<3>>],[{scope,{0,2}}]),
- ?line [] = Module:matches(<<1,2,3,4>>,<<2,3>>,[{scope,{0,2}}]),
- ?line [{1,2}] = Module:matches(<<1,2,3,4>>,<<2,3>>,[{scope,{0,3}}]),
- ?line [{1,2}] = Module:matches(<<1,2,3,4>>,<<2,3>>,[{scope,{0,4}}]),
- ?line [{1,2}] = Module:matches(<<1,2,3,4>>,[<<2,3>>,<<4>>],
- [{scope,{0,3}}]),
- ?line [{1,2},{3,1}] = Module:matches(<<1,2,3,4>>,[<<2,3>>,<<4>>],
- [{scope,{0,4}}]),
- ?line badarg = ?MASK_ERROR(Module:matches(<<1,2,3,4>>,<<2,3>>,
- [{scope,{0,5}}])),
- ?line [{1,2}] = Module:matches(<<1,2,3,4>>,<<2,3>>,[{scope,{4,-4}}]),
- ?line [{1,2},{3,1}] = Module:matches(<<1,2,3,4>>,[<<2,3>>,<<4>>],
- [{scope,{4,-4}}]),
- ?line [{0,3}] = Module:matches(<<1,2,3,4>>,<<1,2,3>>,[{scope,{4,-4}}]),
- ?line [{0,4}] = Module:matches(<<1,2,3,4>>,<<1,2,3,4>>,[{scope,{4,-4}}]),
- ?line badarg = ?MASK_ERROR(Module:matches(<<1,2,3,4>>,<<1,2,3,4>>,
- [{scope,{3,-4}}])),
- ?line badarg = ?MASK_ERROR(Module:matches(<<1,2,3,4>>,[<<1,2,3,4>>],
- [{scope,{3,-4}}])),
- ?line [<<1,2,3>>,<<6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,<<4,5>>),
- ?line [<<1,2,3>>,<<6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<7>>]),
- ?line [<<1,2,3>>,<<6>>,<<8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<7>>],[global]),
- ?line [<<1,2,3>>,<<6>>,<<>>,<<>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<7>>,<<8>>],
- [global]),
- ?line [<<1,2,3>>,<<6>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<7>>,<<8>>],
- [global,trim]),
- ?line [<<1,2,3>>,<<6>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<7>>,<<8>>],
- [global,trim_all]),
- ?line [<<1,2,3,4,5,6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<7>>,<<8>>],
- [global,trim,{scope,{0,4}}]),
- ?line [<<1,2,3>>,<<6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
+ [{0,2},{2,2}] = Module:matches(<<"123456">>,
+ [<<"12">>,
+ <<"23">>,<<"3">>,
+ <<"34">>,<<"456">>,
+ <<"45">>]),
+ {1,4} = Module:match(<<"123456">>,
+ [<<"34">>,<<"34">>,
+ <<"12347">>,<<"2345">>]),
+ [{1,4}] = Module:matches(<<"123456">>,
+ [<<"34">>,<<"34">>,
+ <<"12347">>,<<"2345">>]),
+ [{2,2}] = Module:matches(<<"123456">>,
+ [<<"34">>,<<"34">>,
+ <<"12347">>,<<"2346">>]),
+ nomatch = Module:match(<<1,2,3,4>>,<<2>>,[{scope,{0,1}}]),
+ {1,1} = Module:match(<<1,2,3,4>>,<<2>>,[{scope,{0,2}}]),
+ nomatch = Module:match(<<1,2,3,4>>,<<2,3>>,[{scope,{0,2}}]),
+ {1,2} = Module:match(<<1,2,3,4>>,<<2,3>>,[{scope,{0,3}}]),
+ {1,2} = Module:match(<<1,2,3,4>>,<<2,3>>,[{scope,{0,4}}]),
+ badarg = ?MASK_ERROR(Module:match(<<1,2,3,4>>,<<2,3>>,
+ [{scope,{0,5}}])),
+ {1,2} = Module:match(<<1,2,3,4>>,<<2,3>>,[{scope,{4,-4}}]),
+ {0,3} = Module:match(<<1,2,3,4>>,<<1,2,3>>,[{scope,{4,-4}}]),
+ {0,4} = Module:match(<<1,2,3,4>>,<<1,2,3,4>>,[{scope,{4,-4}}]),
+ badarg = ?MASK_ERROR(Module:match(<<1,2,3,4>>,<<1,2,3,4>>,
+ [{scope,{3,-4}}])),
+ [] = Module:matches(<<1,2,3,4>>,<<2>>,[{scope,{0,1}}]),
+ [{1,1}] = Module:matches(<<1,2,3,4>>,[<<2>>,<<3>>],[{scope,{0,2}}]),
+ [] = Module:matches(<<1,2,3,4>>,<<2,3>>,[{scope,{0,2}}]),
+ [{1,2}] = Module:matches(<<1,2,3,4>>,<<2,3>>,[{scope,{0,3}}]),
+ [{1,2}] = Module:matches(<<1,2,3,4>>,<<2,3>>,[{scope,{0,4}}]),
+ [{1,2}] = Module:matches(<<1,2,3,4>>,[<<2,3>>,<<4>>],
+ [{scope,{0,3}}]),
+ [{1,2},{3,1}] = Module:matches(<<1,2,3,4>>,[<<2,3>>,<<4>>],
+ [{scope,{0,4}}]),
+ badarg = ?MASK_ERROR(Module:matches(<<1,2,3,4>>,<<2,3>>,
+ [{scope,{0,5}}])),
+ [{1,2}] = Module:matches(<<1,2,3,4>>,<<2,3>>,[{scope,{4,-4}}]),
+ [{1,2},{3,1}] = Module:matches(<<1,2,3,4>>,[<<2,3>>,<<4>>],
+ [{scope,{4,-4}}]),
+ [{0,3}] = Module:matches(<<1,2,3,4>>,<<1,2,3>>,[{scope,{4,-4}}]),
+ [{0,4}] = Module:matches(<<1,2,3,4>>,<<1,2,3,4>>,[{scope,{4,-4}}]),
+ badarg = ?MASK_ERROR(Module:matches(<<1,2,3,4>>,<<1,2,3,4>>,
+ [{scope,{3,-4}}])),
+ badarg = ?MASK_ERROR(Module:matches(<<1,2,3,4>>,[<<1,2,3,4>>],
+ [{scope,{3,-4}}])),
+ [<<1,2,3>>,<<6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,<<4,5>>),
+ [<<1,2,3>>,<<6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<7>>]),
+ [<<1,2,3>>,<<6>>,<<8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<7>>],[global]),
+ [<<1,2,3>>,<<6>>,<<>>,<<>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],
- [global,trim,{scope,{0,5}}]),
-
- ?line [<<>>,<<>>,<<3>>,<<6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
- [<<1>>,<<2>>,<<4,5>>],
- [global,trim]),
- ?line [<<3>>,<<6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
- [<<1>>,<<2>>,<<4,5>>],
- [global,trim_all]),
-
- ?line [<<1,2,3>>,<<>>,<<7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<6>>],
- [global,trim]),
- ?line [<<1,2,3>>,<<7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<6>>],
- [global,trim_all]),
- ?line [<<>>,<<>>,<<3>>,<<>>,<<6>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
- [<<1>>,<<2>>,<<4>>,<<5>>,<<7>>,<<8>>],
- [global,trim]),
- ?line [<<3>>,<<6>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
- [<<1>>,<<2>>,<<4>>,<<5>>,<<7>>,<<8>>],
- [global,trim_all]),
- ?line badarg = ?MASK_ERROR(
- Module:replace(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<7>>,<<8>>],<<99>>,
- [global,trim,{scope,{0,5}}])),
- ?line <<1,2,3,99,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<7>>,<<8>>],<<99>>,[]),
- ?line <<1,2,3,99,6,99,99>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<7>>,<<8>>],<<99>>,
- [global]),
- ?line <<1,2,3,99,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<7>>,<<8>>],<<99>>,
- [global,{scope,{0,5}}]),
- ?line <<1,2,3,99,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<7>>,<<8>>],<<99>>,
- [global,{scope,{0,5}}]),
- ?line <<1,2,3,99,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<7>>,<<8>>],<<99>>,
- [global,{scope,{0,5}}]),
- ?line badarg = ?MASK_ERROR(Module:replace(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<7>>,<<8>>],<<99>>,
- [global,{scope,{0,5}},
- {insert,1}])),
- ?line <<1,2,3,99,4,5,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<7>>,<<8>>],<<99>>,
- [global,{scope,{0,5}},
- {insert_replaced,1}]),
- ?line <<1,2,3,9,4,5,9,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<7>>,<<8>>],
- <<9,9>>,
- [global,{scope,{0,5}},
- {insert_replaced,1}]),
- ?line badarg = ?MASK_ERROR(Module:replace(<<1,2,3,4,5,6,7,8>>,
- [<<4,5>>,<<7>>,<<8>>],<<>>,
- [global,{scope,{0,5}},
- {insert_replaced,1}])),
- ?line 2 = Module:longest_common_prefix([<<1,2,4>>,<<1,2,3>>]),
- ?line 2 = Module:longest_common_prefix([<<1,2,4>>,<<1,2>>]),
- ?line 1 = Module:longest_common_prefix([<<1,2,4>>,<<1>>]),
- ?line 0 = Module:longest_common_prefix([<<1,2,4>>,<<>>]),
- ?line 1 = Module:longest_common_prefix([<<1,2,4>>,<<1,2,3>>,<<1,3,3>>]),
- ?line 1 = Module:longest_common_prefix([<<1,2,4>>,<<1,2,3>>,<<1,3,3>>,<<1,2,4>>]),
- ?line 1251 = Module:longest_common_prefix([<<0:10000,1,2,4>>,
- <<0:10000,1,2,3>>,
- <<0:10000,1,3,3>>,
- <<0:10000,1,2,4>>]),
- ?line 12501 = Module:longest_common_prefix([<<0:100000,1,2,4>>,
- <<0:100000,1,2,3>>,
- <<0:100000,1,3,3>>,
- <<0:100000,1,2,4>>]),
- ?line 1251 = Module:longest_common_prefix(
- [make_unaligned(<<0:10000,1,2,4>>),
- <<0:10000,1,2,3>>,
- make_unaligned(<<0:10000,1,3,3>>),
- <<0:10000,1,2,4>>]),
- ?line 12501 = Module:longest_common_prefix(
- [<<0:100000,1,2,4>>,
- make_unaligned(<<0:100000,1,2,3>>),
- <<0:100000,1,3,3>>,
- make_unaligned(<<0:100000,1,2,4>>)]),
- ?line 1250001 = Module:longest_common_prefix([<<0:10000000,1,2,4>>,
- <<0:10000000,1,2,3>>,
- <<0:10000000,1,3,3>>,
- <<0:10000000,1,2,4>>]),
+ [global]),
+ [<<1,2,3>>,<<6>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<7>>,<<8>>],
+ [global,trim]),
+ [<<1,2,3>>,<<6>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<7>>,<<8>>],
+ [global,trim_all]),
+ [<<1,2,3,4,5,6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<7>>,<<8>>],
+ [global,trim,{scope,{0,4}}]),
+ [<<1,2,3>>,<<6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<7>>,<<8>>],
+ [global,trim,{scope,{0,5}}]),
+
+ [<<>>,<<>>,<<3>>,<<6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
+ [<<1>>,<<2>>,<<4,5>>],
+ [global,trim]),
+ [<<3>>,<<6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
+ [<<1>>,<<2>>,<<4,5>>],
+ [global,trim_all]),
+
+ [<<1,2,3>>,<<>>,<<7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<6>>],
+ [global,trim]),
+ [<<1,2,3>>,<<7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<6>>],
+ [global,trim_all]),
+ [<<>>,<<>>,<<3>>,<<>>,<<6>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
+ [<<1>>,<<2>>,<<4>>,<<5>>,<<7>>,<<8>>],
+ [global,trim]),
+ [<<3>>,<<6>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
+ [<<1>>,<<2>>,<<4>>,<<5>>,<<7>>,<<8>>],
+ [global,trim_all]),
+ [<<>>] = binary:split(<<>>, <<",">>, []),
+ [] = binary:split(<<>>, <<",">>, [trim]),
+ [] = binary:split(<<>>, <<",">>, [trim_all]),
+ [] = binary:split(<<>>, <<",">>, [global,trim]),
+ [] = binary:split(<<>>, <<",">>, [global,trim_all]),
+
+ badarg = ?MASK_ERROR(
+ Module:replace(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<7>>,<<8>>],<<99>>,
+ [global,trim,{scope,{0,5}}])),
+ <<1,2,3,99,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<7>>,<<8>>],<<99>>,[]),
+ <<1,2,3,99,6,99,99>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<7>>,<<8>>],<<99>>,
+ [global]),
+ <<1,2,3,99,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<7>>,<<8>>],<<99>>,
+ [global,{scope,{0,5}}]),
+ <<1,2,3,99,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<7>>,<<8>>],<<99>>,
+ [global,{scope,{0,5}}]),
+ <<1,2,3,99,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<7>>,<<8>>],<<99>>,
+ [global,{scope,{0,5}}]),
+ badarg = ?MASK_ERROR(Module:replace(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<7>>,<<8>>],<<99>>,
+ [global,{scope,{0,5}},
+ {insert,1}])),
+ <<1,2,3,99,4,5,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<7>>,<<8>>],<<99>>,
+ [global,{scope,{0,5}},
+ {insert_replaced,1}]),
+ <<1,2,3,9,4,5,9,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<7>>,<<8>>],
+ <<9,9>>,
+ [global,{scope,{0,5}},
+ {insert_replaced,1}]),
+ badarg = ?MASK_ERROR(Module:replace(<<1,2,3,4,5,6,7,8>>,
+ [<<4,5>>,<<7>>,<<8>>],<<>>,
+ [global,{scope,{0,5}},
+ {insert_replaced,1}])),
+ 2 = Module:longest_common_prefix([<<1,2,4>>,<<1,2,3>>]),
+ 2 = Module:longest_common_prefix([<<1,2,4>>,<<1,2>>]),
+ 1 = Module:longest_common_prefix([<<1,2,4>>,<<1>>]),
+ 0 = Module:longest_common_prefix([<<1,2,4>>,<<>>]),
+ 1 = Module:longest_common_prefix([<<1,2,4>>,<<1,2,3>>,<<1,3,3>>]),
+ 1 = Module:longest_common_prefix([<<1,2,4>>,<<1,2,3>>,<<1,3,3>>,<<1,2,4>>]),
+ 1251 = Module:longest_common_prefix([<<0:10000,1,2,4>>,
+ <<0:10000,1,2,3>>,
+ <<0:10000,1,3,3>>,
+ <<0:10000,1,2,4>>]),
+ 12501 = Module:longest_common_prefix([<<0:100000,1,2,4>>,
+ <<0:100000,1,2,3>>,
+ <<0:100000,1,3,3>>,
+ <<0:100000,1,2,4>>]),
+ 1251 = Module:longest_common_prefix(
+ [make_unaligned(<<0:10000,1,2,4>>),
+ <<0:10000,1,2,3>>,
+ make_unaligned(<<0:10000,1,3,3>>),
+ <<0:10000,1,2,4>>]),
+ 12501 = Module:longest_common_prefix(
+ [<<0:100000,1,2,4>>,
+ make_unaligned(<<0:100000,1,2,3>>),
+ <<0:100000,1,3,3>>,
+ make_unaligned(<<0:100000,1,2,4>>)]),
+ 1250001 = Module:longest_common_prefix([<<0:10000000,1,2,4>>,
+ <<0:10000000,1,2,3>>,
+ <<0:10000000,1,3,3>>,
+ <<0:10000000,1,2,4>>]),
if % Too cruel for the reference implementation
Module =:= binary ->
- ?line erts_debug:set_internal_state(available_internal_state,true),
- ?line io:format("oldlimit: ~p~n",
- [erts_debug:set_internal_state(
- binary_loop_limit,100)]),
- ?line 1250001 = Module:longest_common_prefix(
- [<<0:10000000,1,2,4>>,
- <<0:10000000,1,2,3>>,
- <<0:10000000,1,3,3>>,
- <<0:10000000,1,2,4>>]),
- ?line io:format("limit was: ~p~n",
- [erts_debug:set_internal_state(binary_loop_limit,
- default)]),
- ?line erts_debug:set_internal_state(available_internal_state,
- false);
+ erts_debug:set_internal_state(available_internal_state,true),
+ io:format("oldlimit: ~p~n",
+ [erts_debug:set_internal_state(
+ binary_loop_limit,100)]),
+ 1250001 = Module:longest_common_prefix(
+ [<<0:10000000,1,2,4>>,
+ <<0:10000000,1,2,3>>,
+ <<0:10000000,1,3,3>>,
+ <<0:10000000,1,2,4>>]),
+ io:format("limit was: ~p~n",
+ [erts_debug:set_internal_state(binary_loop_limit,
+ default)]),
+ erts_debug:set_internal_state(available_internal_state,
+ false);
true ->
ok
end,
- ?line 1 = Module:longest_common_suffix([<<0:100000000,1,2,4,5>>,
- <<0:100000000,1,2,3,5>>,
- <<0:100000000,1,3,3,5>>,
- <<0:100000000,1,2,4,5>>]),
- ?line 1 = Module:longest_common_suffix([<<1,2,4,5>>,
- <<0:100000000,1,2,3,5>>,
- <<0:100000000,1,3,3,5>>,
- <<0:100000000,1,2,4,5>>]),
- ?line 1 = Module:longest_common_suffix([<<1,2,4,5,5>>,<<5,5>>,
- <<0:100000000,1,3,3,5,5>>,
- <<0:100000000,1,2,4,5>>]),
- ?line 0 = Module:longest_common_suffix([<<1,2,4,5,5>>,<<5,5>>,
- <<0:100000000,1,3,3,5,5>>,
- <<0:100000000,1,2,4>>]),
- ?line 2 = Module:longest_common_suffix([<<1,2,4,5,5>>,<<5,5>>,
- <<0:100000000,1,3,3,5,5>>,
- <<0:100000000,1,2,4,5,5>>]),
- ?line 1 = Module:longest_common_suffix([<<1,2,4,5,5>>,<<5>>,
- <<0:100000000,1,3,3,5,5>>,
- <<0:100000000,1,2,4,5,5>>]),
- ?line 0 = Module:longest_common_suffix([<<1,2,4,5,5>>,<<>>,
- <<0:100000000,1,3,3,5,5>>,
- <<0:100000000,1,2,4,5,5>>]),
- ?line 0 = Module:longest_common_suffix([<<>>,<<0:100000000,1,3,3,5,5>>,
- <<0:100000000,1,2,4,5,5>>]),
- ?line 0 = Module:longest_common_suffix([<<>>,<<0:100000000,1,3,3,5,5>>,
- <<0:100000000,1,2,4,5,5>>]),
- ?line 2 = Module:longest_common_suffix([<<5,5>>,<<0:100000000,1,3,3,5,5>>,
- <<0:100000000,1,2,4,5,5>>]),
- ?line 2 = Module:longest_common_suffix([<<5,5>>,<<5,5>>,<<4,5,5>>]),
- ?line 2 = Module:longest_common_suffix([<<5,5>>,<<5,5>>,<<5,5>>]),
- ?line 3 = Module:longest_common_suffix([<<4,5,5>>,<<4,5,5>>,<<4,5,5>>]),
- ?line 0 = Module:longest_common_suffix([<<>>]),
- ?line badarg = ?MASK_ERROR(Module:longest_common_suffix([])),
- ?line badarg = ?MASK_ERROR(Module:longest_common_suffix([apa])),
- ?line badarg = ?MASK_ERROR(Module:longest_common_suffix([[<<>>]])),
- ?line badarg = ?MASK_ERROR(Module:longest_common_suffix([[<<0>>,
- <<1:9>>]])),
- ?line 0 = Module:longest_common_prefix([<<>>]),
- ?line badarg = ?MASK_ERROR(Module:longest_common_prefix([])),
- ?line badarg = ?MASK_ERROR(Module:longest_common_prefix([apa])),
- ?line badarg = ?MASK_ERROR(Module:longest_common_prefix([[<<>>]])),
- ?line badarg = ?MASK_ERROR(Module:longest_common_prefix([[<<0>>,
- <<1:9>>]])),
-
- ?line <<1:6,Bin:3/binary,_:2>> = <<1:6,1,2,3,1:2>>,
- ?line <<1,2,3>> = Bin,
- ?line 1 = Module:first(Bin),
- ?line 1 = Module:first(<<1>>),
- ?line 1 = Module:first(<<1,2,3>>),
- ?line badarg = ?MASK_ERROR(Module:first(<<>>)),
- ?line badarg = ?MASK_ERROR(Module:first(apa)),
- ?line 3 = Module:last(Bin),
- ?line 1 = Module:last(<<1>>),
- ?line 3 = Module:last(<<1,2,3>>),
- ?line badarg = ?MASK_ERROR(Module:last(<<>>)),
- ?line badarg = ?MASK_ERROR(Module:last(apa)),
- ?line 1 = Module:at(Bin,0),
- ?line 1 = Module:at(<<1>>,0),
- ?line 1 = Module:at(<<1,2,3>>,0),
- ?line 2 = Module:at(<<1,2,3>>,1),
- ?line 3 = Module:at(<<1,2,3>>,2),
- ?line badarg = ?MASK_ERROR(Module:at(<<1,2,3>>,3)),
- ?line badarg = ?MASK_ERROR(Module:at(<<1,2,3>>,-1)),
- ?line badarg = ?MASK_ERROR(Module:at(<<1,2,3>>,apa)),
- ?line "hejsan" = [ Module:at(<<"hejsan">>,I) || I <- lists:seq(0,5) ],
-
- ?line badarg = ?MASK_ERROR(Module:bin_to_list(<<1,2,3>>,3,-4)),
- ?line [1,2,3] = ?MASK_ERROR(Module:bin_to_list(<<1,2,3>>,3,-3)),
-
- ?line badarg = ?MASK_ERROR(Module:decode_unsigned(<<1,2,1:2>>,big)),
- ?line badarg = ?MASK_ERROR(Module:decode_unsigned(<<1,2,1:2>>,little)),
- ?line badarg = ?MASK_ERROR(Module:decode_unsigned(apa)),
- ?line badarg = ?MASK_ERROR(Module:decode_unsigned(125,little)),
- ?line 0 = ?MASK_ERROR(Module:decode_unsigned(<<>>,little)),
- ?line 0 = ?MASK_ERROR(Module:decode_unsigned(<<>>,big)),
- ?line 0 = ?MASK_ERROR(Module:decode_unsigned(<<0>>,little)),
- ?line 0 = ?MASK_ERROR(Module:decode_unsigned(<<0>>,big)),
- ?line 0 = ?MASK_ERROR(Module:decode_unsigned(make_unaligned(<<0>>),
- little)),
- ?line 0 = ?MASK_ERROR(Module:decode_unsigned(make_unaligned(<<0>>),big)),
- ?line badarg = ?MASK_ERROR(Module:encode_unsigned(apa)),
- ?line badarg = ?MASK_ERROR(Module:encode_unsigned(125.3,little)),
- ?line badarg = ?MASK_ERROR(Module:encode_unsigned({1},little)),
- ?line badarg = ?MASK_ERROR(Module:encode_unsigned([1],little)),
- ?line <<0>> = ?MASK_ERROR(Module:encode_unsigned(0,little)),
- ?line <<0>> = ?MASK_ERROR(Module:encode_unsigned(0,big)),
+ 1 = Module:longest_common_suffix([<<0:100000000,1,2,4,5>>,
+ <<0:100000000,1,2,3,5>>,
+ <<0:100000000,1,3,3,5>>,
+ <<0:100000000,1,2,4,5>>]),
+ 1 = Module:longest_common_suffix([<<1,2,4,5>>,
+ <<0:100000000,1,2,3,5>>,
+ <<0:100000000,1,3,3,5>>,
+ <<0:100000000,1,2,4,5>>]),
+ 1 = Module:longest_common_suffix([<<1,2,4,5,5>>,<<5,5>>,
+ <<0:100000000,1,3,3,5,5>>,
+ <<0:100000000,1,2,4,5>>]),
+ 0 = Module:longest_common_suffix([<<1,2,4,5,5>>,<<5,5>>,
+ <<0:100000000,1,3,3,5,5>>,
+ <<0:100000000,1,2,4>>]),
+ 2 = Module:longest_common_suffix([<<1,2,4,5,5>>,<<5,5>>,
+ <<0:100000000,1,3,3,5,5>>,
+ <<0:100000000,1,2,4,5,5>>]),
+ 1 = Module:longest_common_suffix([<<1,2,4,5,5>>,<<5>>,
+ <<0:100000000,1,3,3,5,5>>,
+ <<0:100000000,1,2,4,5,5>>]),
+ 0 = Module:longest_common_suffix([<<1,2,4,5,5>>,<<>>,
+ <<0:100000000,1,3,3,5,5>>,
+ <<0:100000000,1,2,4,5,5>>]),
+ 0 = Module:longest_common_suffix([<<>>,<<0:100000000,1,3,3,5,5>>,
+ <<0:100000000,1,2,4,5,5>>]),
+ 0 = Module:longest_common_suffix([<<>>,<<0:100000000,1,3,3,5,5>>,
+ <<0:100000000,1,2,4,5,5>>]),
+ 2 = Module:longest_common_suffix([<<5,5>>,<<0:100000000,1,3,3,5,5>>,
+ <<0:100000000,1,2,4,5,5>>]),
+ 2 = Module:longest_common_suffix([<<5,5>>,<<5,5>>,<<4,5,5>>]),
+ 2 = Module:longest_common_suffix([<<5,5>>,<<5,5>>,<<5,5>>]),
+ 3 = Module:longest_common_suffix([<<4,5,5>>,<<4,5,5>>,<<4,5,5>>]),
+ 0 = Module:longest_common_suffix([<<>>]),
+ badarg = ?MASK_ERROR(Module:longest_common_suffix([])),
+ badarg = ?MASK_ERROR(Module:longest_common_suffix([apa])),
+ badarg = ?MASK_ERROR(Module:longest_common_suffix([[<<>>]])),
+ badarg = ?MASK_ERROR(Module:longest_common_suffix([[<<0>>,
+ <<1:9>>]])),
+ 0 = Module:longest_common_prefix([<<>>]),
+ badarg = ?MASK_ERROR(Module:longest_common_prefix([])),
+ badarg = ?MASK_ERROR(Module:longest_common_prefix([apa])),
+ badarg = ?MASK_ERROR(Module:longest_common_prefix([[<<>>]])),
+ badarg = ?MASK_ERROR(Module:longest_common_prefix([[<<0>>,
+ <<1:9>>]])),
+
+ <<1:6,Bin:3/binary,_:2>> = <<1:6,1,2,3,1:2>>,
+ <<1,2,3>> = Bin,
+ 1 = Module:first(Bin),
+ 1 = Module:first(<<1>>),
+ 1 = Module:first(<<1,2,3>>),
+ badarg = ?MASK_ERROR(Module:first(<<>>)),
+ badarg = ?MASK_ERROR(Module:first(apa)),
+ 3 = Module:last(Bin),
+ 1 = Module:last(<<1>>),
+ 3 = Module:last(<<1,2,3>>),
+ badarg = ?MASK_ERROR(Module:last(<<>>)),
+ badarg = ?MASK_ERROR(Module:last(apa)),
+ 1 = Module:at(Bin,0),
+ 1 = Module:at(<<1>>,0),
+ 1 = Module:at(<<1,2,3>>,0),
+ 2 = Module:at(<<1,2,3>>,1),
+ 3 = Module:at(<<1,2,3>>,2),
+ badarg = ?MASK_ERROR(Module:at(<<1,2,3>>,3)),
+ badarg = ?MASK_ERROR(Module:at(<<1,2,3>>,-1)),
+ badarg = ?MASK_ERROR(Module:at(<<1,2,3>>,apa)),
+ "hejsan" = [ Module:at(<<"hejsan">>,I) || I <- lists:seq(0,5) ],
+
+ badarg = ?MASK_ERROR(Module:bin_to_list(<<1,2,3>>,3,-4)),
+ [1,2,3] = ?MASK_ERROR(Module:bin_to_list(<<1,2,3>>,3,-3)),
+
+ badarg = ?MASK_ERROR(Module:decode_unsigned(<<1,2,1:2>>,big)),
+ badarg = ?MASK_ERROR(Module:decode_unsigned(<<1,2,1:2>>,little)),
+ badarg = ?MASK_ERROR(Module:decode_unsigned(apa)),
+ badarg = ?MASK_ERROR(Module:decode_unsigned(125,little)),
+ 0 = ?MASK_ERROR(Module:decode_unsigned(<<>>,little)),
+ 0 = ?MASK_ERROR(Module:decode_unsigned(<<>>,big)),
+ 0 = ?MASK_ERROR(Module:decode_unsigned(<<0>>,little)),
+ 0 = ?MASK_ERROR(Module:decode_unsigned(<<0>>,big)),
+ 0 = ?MASK_ERROR(Module:decode_unsigned(make_unaligned(<<0>>),
+ little)),
+ 0 = ?MASK_ERROR(Module:decode_unsigned(make_unaligned(<<0>>),big)),
+ badarg = ?MASK_ERROR(Module:encode_unsigned(apa)),
+ badarg = ?MASK_ERROR(Module:encode_unsigned(125.3,little)),
+ badarg = ?MASK_ERROR(Module:encode_unsigned({1},little)),
+ badarg = ?MASK_ERROR(Module:encode_unsigned([1],little)),
+ <<0>> = ?MASK_ERROR(Module:encode_unsigned(0,little)),
+ <<0>> = ?MASK_ERROR(Module:encode_unsigned(0,big)),
ok.
-encode_decode(doc) ->
- ["test binary:encode_unsigned/1,2 and binary:decode_unsigned/1,2"];
+%% Test binary:encode_unsigned/1,2 and binary:decode_unsigned/1,2.
encode_decode(Config) when is_list(Config) ->
- ?line random:seed({1271,769940,559934}),
- ?line ok = encode_decode_loop({1,200},1000), % Need to be long enough
- % to create offheap binaries
+ rand:seed(exsplus, {1271,769940,559934}),
+ ok = encode_decode_loop({1,200},1000), % Need to be long enough
+ % to create offheap binaries
ok.
encode_decode_loop(_Range,0) ->
ok;
encode_decode_loop(Range, X) ->
- ?line N = random_number(Range),
- ?line A = binary:encode_unsigned(N),
- ?line B = binary:encode_unsigned(N,big),
- ?line C = binref:encode_unsigned(N),
- ?line D = binref:encode_unsigned(N,big),
- ?line E = binary:encode_unsigned(N,little),
- ?line F = binref:encode_unsigned(N,little),
- ?line G = binary:decode_unsigned(A),
- ?line H = binary:decode_unsigned(A,big),
- ?line I = binref:decode_unsigned(A),
- ?line J = binary:decode_unsigned(E,little),
- ?line K = binref:decode_unsigned(E,little),
- ?line L = binary:decode_unsigned(make_unaligned(A)),
- ?line M = binary:decode_unsigned(make_unaligned(E),little),
- ?line PaddedBig = <<0:48,A/binary>>,
- ?line PaddedLittle = <<E/binary,0:48>>,
- ?line O = binary:decode_unsigned(PaddedBig),
- ?line P = binary:decode_unsigned(make_unaligned(PaddedBig)),
- ?line Q = binary:decode_unsigned(PaddedLittle,little),
- ?line R = binary:decode_unsigned(make_unaligned(PaddedLittle),little),
- ?line S = binref:decode_unsigned(PaddedLittle,little),
- ?line T = binref:decode_unsigned(PaddedBig),
+ N = random_number(Range),
+ A = binary:encode_unsigned(N),
+ B = binary:encode_unsigned(N,big),
+ C = binref:encode_unsigned(N),
+ D = binref:encode_unsigned(N,big),
+ E = binary:encode_unsigned(N,little),
+ F = binref:encode_unsigned(N,little),
+ G = binary:decode_unsigned(A),
+ H = binary:decode_unsigned(A,big),
+ I = binref:decode_unsigned(A),
+ J = binary:decode_unsigned(E,little),
+ K = binref:decode_unsigned(E,little),
+ L = binary:decode_unsigned(make_unaligned(A)),
+ M = binary:decode_unsigned(make_unaligned(E),little),
+ PaddedBig = <<0:48,A/binary>>,
+ PaddedLittle = <<E/binary,0:48>>,
+ O = binary:decode_unsigned(PaddedBig),
+ P = binary:decode_unsigned(make_unaligned(PaddedBig)),
+ Q = binary:decode_unsigned(PaddedLittle,little),
+ R = binary:decode_unsigned(make_unaligned(PaddedLittle),little),
+ S = binref:decode_unsigned(PaddedLittle,little),
+ T = binref:decode_unsigned(PaddedBig),
case (((A =:= B) and (B =:= C) and (C =:= D)) and
- ((E =:= F)) and
- ((N =:= G) and (G =:= H) and (H =:= I) and
- (I =:= J) and (J =:= K) and (K =:= L) and (L =:= M)) and
- ((M =:= O) and (O =:= P) and (P =:= Q) and (Q =:= R) and
- (R =:= S) and (S =:= T)))of
+ ((E =:= F)) and
+ ((N =:= G) and (G =:= H) and (H =:= I) and
+ (I =:= J) and (J =:= K) and (K =:= L) and (L =:= M)) and
+ ((M =:= O) and (O =:= P) and (P =:= Q) and (Q =:= R) and
+ (R =:= S) and (S =:= T)))of
true ->
encode_decode_loop(Range,X-1);
_ ->
@@ -754,90 +728,86 @@ encode_decode_loop(Range, X) ->
exit(mismatch)
end.
-guard(doc) ->
- ["Smoke test of the guard BIFs binary_part/2,3"];
+%% Smoke test of the guard BIFs binary_part/2,3.
guard(Config) when is_list(Config) ->
{comment, "Guard tests are run in emulator test suite"}.
-referenced(doc) ->
- ["Test refernced_byte_size/1 bif."];
+%% Test referenced_byte_size/1 bif.
referenced(Config) when is_list(Config) ->
- ?line badarg = ?MASK_ERROR(binary:referenced_byte_size([])),
- ?line badarg = ?MASK_ERROR(binary:referenced_byte_size(apa)),
- ?line badarg = ?MASK_ERROR(binary:referenced_byte_size({})),
- ?line badarg = ?MASK_ERROR(binary:referenced_byte_size(1)),
- ?line A = <<1,2,3>>,
- ?line B = binary:copy(A,1000),
- ?line 3 = binary:referenced_byte_size(A),
- ?line 3000 = binary:referenced_byte_size(B),
- ?line <<_:8,C:2/binary>> = A,
- ?line 3 = binary:referenced_byte_size(C),
- ?line 2 = binary:referenced_byte_size(binary:copy(C)),
- ?line <<_:7,D:2/binary,_:1>> = A,
- ?line 2 = binary:referenced_byte_size(binary:copy(D)),
- ?line 3 = binary:referenced_byte_size(D),
- ?line <<_:8,E:2/binary,_/binary>> = B,
- ?line 3000 = binary:referenced_byte_size(E),
- ?line 2 = binary:referenced_byte_size(binary:copy(E)),
- ?line <<_:7,F:2/binary,_:1,_/binary>> = B,
- ?line 2 = binary:referenced_byte_size(binary:copy(F)),
- ?line 3000 = binary:referenced_byte_size(F),
+ badarg = ?MASK_ERROR(binary:referenced_byte_size([])),
+ badarg = ?MASK_ERROR(binary:referenced_byte_size(apa)),
+ badarg = ?MASK_ERROR(binary:referenced_byte_size({})),
+ badarg = ?MASK_ERROR(binary:referenced_byte_size(1)),
+ A = <<1,2,3>>,
+ B = binary:copy(A,1000),
+ 3 = binary:referenced_byte_size(A),
+ 3000 = binary:referenced_byte_size(B),
+ <<_:8,C:2/binary>> = A,
+ 3 = binary:referenced_byte_size(C),
+ 2 = binary:referenced_byte_size(binary:copy(C)),
+ <<_:7,D:2/binary,_:1>> = A,
+ 2 = binary:referenced_byte_size(binary:copy(D)),
+ 3 = binary:referenced_byte_size(D),
+ <<_:8,E:2/binary,_/binary>> = B,
+ 3000 = binary:referenced_byte_size(E),
+ 2 = binary:referenced_byte_size(binary:copy(E)),
+ <<_:7,F:2/binary,_:1,_/binary>> = B,
+ 2 = binary:referenced_byte_size(binary:copy(F)),
+ 3000 = binary:referenced_byte_size(F),
ok.
-list_to_bin(doc) ->
- ["Test list_to_bin/1 bif"];
+%% Test list_to_bin/1 BIF.
list_to_bin(Config) when is_list(Config) ->
%% Just some smoke_tests first, then go nuts with random cases
- ?line badarg = ?MASK_ERROR(binary:list_to_bin({})),
- ?line badarg = ?MASK_ERROR(binary:list_to_bin(apa)),
- ?line badarg = ?MASK_ERROR(binary:list_to_bin(<<"apa">>)),
+ badarg = ?MASK_ERROR(binary:list_to_bin({})),
+ badarg = ?MASK_ERROR(binary:list_to_bin(apa)),
+ badarg = ?MASK_ERROR(binary:list_to_bin(<<"apa">>)),
F1 = fun(L) ->
?MASK_ERROR(binref:list_to_bin(L))
end,
F2 = fun(L) ->
?MASK_ERROR(binary:list_to_bin(L))
end,
- ?line random_iolist:run(1000,F1,F2),
+ random_iolist:run(1000,F1,F2),
ok.
-copy(doc) ->
- ["Test copy/1,2 bif's"];
+%% Test copy/1,2 BIFs.
copy(Config) when is_list(Config) ->
- ?line <<1,2,3>> = binary:copy(<<1,2,3>>),
- ?line RS = random_string({1,10000}),
- ?line RS = RS2 = binary:copy(RS),
- ?line false = erts_debug:same(RS,RS2),
- ?line <<>> = ?MASK_ERROR(binary:copy(<<1,2,3>>,0)),
- ?line badarg = ?MASK_ERROR(binary:copy(<<1,2,3:3>>,2)),
- ?line badarg = ?MASK_ERROR(binary:copy([],0)),
- ?line <<>> = ?MASK_ERROR(binary:copy(<<>>,0)),
- ?line badarg = ?MASK_ERROR(binary:copy(<<1,2,3>>,1.0)),
- ?line badarg = ?MASK_ERROR(binary:copy(<<1,2,3>>,
- 16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)),
- ?line <<>> = binary:copy(<<>>,10000),
- ?line random:seed({1271,769940,559934}),
- ?line ok = random_copy(3000),
- ?line erts_debug:set_internal_state(available_internal_state,true),
- ?line io:format("oldlimit: ~p~n",
- [erts_debug:set_internal_state(binary_loop_limit,10)]),
- ?line Subj = subj(),
- ?line XX = binary:copy(Subj,1000),
- ?line XX = binref:copy(Subj,1000),
- ?line ok = random_copy(1000),
- ?line kill_copy_loop(1000),
- ?line io:format("limit was: ~p~n",
- [erts_debug:set_internal_state(binary_loop_limit,
- default)]),
- ?line erts_debug:set_internal_state(available_internal_state,false),
+ <<1,2,3>> = binary:copy(<<1,2,3>>),
+ RS = random_string({1,10000}),
+ RS = RS2 = binary:copy(RS),
+ false = erts_debug:same(RS,RS2),
+ <<>> = ?MASK_ERROR(binary:copy(<<1,2,3>>,0)),
+ badarg = ?MASK_ERROR(binary:copy(<<1,2,3:3>>,2)),
+ badarg = ?MASK_ERROR(binary:copy([],0)),
+ <<>> = ?MASK_ERROR(binary:copy(<<>>,0)),
+ badarg = ?MASK_ERROR(binary:copy(<<1,2,3>>,1.0)),
+ badarg = ?MASK_ERROR(binary:copy(<<1,2,3>>,
+ 16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)),
+ <<>> = binary:copy(<<>>,10000),
+ rand:seed(exsplus, {1271,769940,559934}),
+ ok = random_copy(3000),
+ erts_debug:set_internal_state(available_internal_state,true),
+ io:format("oldlimit: ~p~n",
+ [erts_debug:set_internal_state(binary_loop_limit,10)]),
+ Subj = subj(),
+ XX = binary:copy(Subj,1000),
+ XX = binref:copy(Subj,1000),
+ ok = random_copy(1000),
+ kill_copy_loop(1000),
+ io:format("limit was: ~p~n",
+ [erts_debug:set_internal_state(binary_loop_limit,
+ default)]),
+ erts_debug:set_internal_state(available_internal_state,false),
ok.
kill_copy_loop(0) ->
ok;
kill_copy_loop(N) ->
{Pid,Ref} = spawn_monitor(fun() ->
- ok = random_copy(1000)
+ ok = random_copy(1000)
end),
receive
after 10 ->
@@ -855,7 +825,7 @@ random_copy(0) ->
ok;
random_copy(N) ->
Str = random_string({0,N}),
- Num = random:uniform(N div 10+1),
+ Num = rand:uniform(N div 10+1),
A = ?MASK_ERROR(binary:copy(Str,Num)),
B = ?MASK_ERROR(binref:copy(Str,Num)),
C = ?MASK_ERROR(binary:copy(make_unaligned(Str),Num)),
@@ -870,34 +840,33 @@ random_copy(N) ->
exit(mismatch)
end.
-bin_to_list(doc) ->
- ["Test bin_to_list/1,2,3 bif's"];
+%% Test bin_to_list/1,2,3 BIFs.
bin_to_list(Config) when is_list(Config) ->
%% Just some smoke_tests first, then go nuts with random cases
- ?line X = <<1,2,3,4,0:1000000,5>>,
- ?line Y = make_unaligned(X),
- ?line LX = binary:bin_to_list(X),
- ?line LX = binary:bin_to_list(X,0,byte_size(X)),
- ?line LX = binary:bin_to_list(X,byte_size(X),-byte_size(X)),
- ?line LX = binary:bin_to_list(X,{0,byte_size(X)}),
- ?line LX = binary:bin_to_list(X,{byte_size(X),-byte_size(X)}),
- ?line LY = binary:bin_to_list(Y),
- ?line LY = binary:bin_to_list(Y,0,byte_size(Y)),
- ?line LY = binary:bin_to_list(Y,byte_size(Y),-byte_size(Y)),
- ?line LY = binary:bin_to_list(Y,{0,byte_size(Y)}),
- ?line LY = binary:bin_to_list(Y,{byte_size(Y),-byte_size(Y)}),
- ?line 1 = hd(LX),
- ?line 5 = lists:last(LX),
- ?line 1 = hd(LY),
- ?line 5 = lists:last(LY),
- ?line X = list_to_binary(LY),
- ?line Y = list_to_binary(LY),
- ?line X = list_to_binary(LY),
- ?line [5] = lists:nthtail(byte_size(X)-1,LX),
- ?line [0,5] = lists:nthtail(byte_size(X)-2,LX),
- ?line [0,5] = lists:nthtail(byte_size(Y)-2,LY),
- ?line random:seed({1271,769940,559934}),
- ?line ok = random_bin_to_list(5000),
+ X = <<1,2,3,4,0:1000000,5>>,
+ Y = make_unaligned(X),
+ LX = binary:bin_to_list(X),
+ LX = binary:bin_to_list(X,0,byte_size(X)),
+ LX = binary:bin_to_list(X,byte_size(X),-byte_size(X)),
+ LX = binary:bin_to_list(X,{0,byte_size(X)}),
+ LX = binary:bin_to_list(X,{byte_size(X),-byte_size(X)}),
+ LY = binary:bin_to_list(Y),
+ LY = binary:bin_to_list(Y,0,byte_size(Y)),
+ LY = binary:bin_to_list(Y,byte_size(Y),-byte_size(Y)),
+ LY = binary:bin_to_list(Y,{0,byte_size(Y)}),
+ LY = binary:bin_to_list(Y,{byte_size(Y),-byte_size(Y)}),
+ 1 = hd(LX),
+ 5 = lists:last(LX),
+ 1 = hd(LY),
+ 5 = lists:last(LY),
+ X = list_to_binary(LY),
+ Y = list_to_binary(LY),
+ X = list_to_binary(LY),
+ [5] = lists:nthtail(byte_size(X)-1,LX),
+ [0,5] = lists:nthtail(byte_size(X)-2,LX),
+ [0,5] = lists:nthtail(byte_size(Y)-2,LY),
+ rand:seed(exsplus, {1271,769940,559934}),
+ ok = random_bin_to_list(5000),
ok.
random_bin_to_list(0) ->
@@ -908,10 +877,10 @@ random_bin_to_list(N) ->
Parts1 = Parts0 ++ [ {X+Y,-Y} || {X,Y} <- Parts0 ],
[ begin
try
- true = ?MASK_ERROR(binary:bin_to_list(Str,Z)) =:=
- ?MASK_ERROR(binref:bin_to_list(Str,Z)),
- true = ?MASK_ERROR(binary:bin_to_list(Str,Z)) =:=
- ?MASK_ERROR(binary:bin_to_list(make_unaligned(Str),Z))
+ true = ?MASK_ERROR(binary:bin_to_list(Str,Z)) =:=
+ ?MASK_ERROR(binref:bin_to_list(Str,Z)),
+ true = ?MASK_ERROR(binary:bin_to_list(Str,Z)) =:=
+ ?MASK_ERROR(binary:bin_to_list(make_unaligned(Str),Z))
catch
_:_ ->
io:format("Error, Str = <<\"~s\">>.~nZ = ~p.~n",
@@ -921,10 +890,10 @@ random_bin_to_list(N) ->
end || Z <- Parts1 ],
[ begin
try
- true = ?MASK_ERROR(binary:bin_to_list(Str,A,B)) =:=
- ?MASK_ERROR(binref:bin_to_list(Str,A,B)),
- true = ?MASK_ERROR(binary:bin_to_list(Str,A,B)) =:=
- ?MASK_ERROR(binary:bin_to_list(make_unaligned(Str),A,B))
+ true = ?MASK_ERROR(binary:bin_to_list(Str,A,B)) =:=
+ ?MASK_ERROR(binref:bin_to_list(Str,A,B)),
+ true = ?MASK_ERROR(binary:bin_to_list(Str,A,B)) =:=
+ ?MASK_ERROR(binary:bin_to_list(make_unaligned(Str),A,B))
catch
_:_ ->
io:format("Error, Str = <<\"~s\">>.~nA = ~p.~nB = ~p.~n",
@@ -934,37 +903,36 @@ random_bin_to_list(N) ->
end || {A,B} <- Parts1 ],
random_bin_to_list(N-1).
-parts(doc) ->
- ["Test the part/2,3 bif's"];
+%% Test the part/2,3 BIFs.
parts(Config) when is_list(Config) ->
%% Some simple smoke tests to begin with
- ?line Simple = <<1,2,3,4,5,6,7,8>>,
- ?line <<1,2>> = binary:part(Simple,0,2),
- ?line <<1,2>> = binary:part(Simple,{0,2}),
- ?line Simple = binary:part(Simple,0,8),
- ?line Simple = binary:part(Simple,{0,8}),
- ?line badarg = ?MASK_ERROR(binary:part(Simple,0,9)),
- ?line badarg = ?MASK_ERROR(binary:part(Simple,{0,9})),
- ?line badarg = ?MASK_ERROR(binary:part(Simple,1,8)),
- ?line badarg = ?MASK_ERROR(binary:part(Simple,{1,8})),
- ?line badarg = ?MASK_ERROR(binary:part(Simple,{3,-4})),
- ?line badarg = ?MASK_ERROR(binary:part(Simple,{3.0,1})),
- ?line badarg = ?MASK_ERROR(
- binary:part(Simple,{16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFF
- ,1})),
- ?line <<2,3,4,5,6,7,8>> = binary:part(Simple,{1,7}),
- ?line <<2,3,4,5,6,7,8>> = binary:part(Simple,{8,-7}),
- ?line Simple = binary:part(Simple,{8,-8}),
- ?line badarg = ?MASK_ERROR(binary:part(Simple,{1,-8})),
- ?line badarg = ?MASK_ERROR(binary:part(Simple,{8,-9})),
- ?line badarg = ?MASK_ERROR(binary:part(Simple,{0,-1})),
- ?line <<>> = binary:part(Simple,{8,0}),
- ?line badarg = ?MASK_ERROR(binary:part(Simple,{9,0})),
- ?line badarg = ?MASK_ERROR(binary:part(Simple,{-1,0})),
- ?line badarg = ?MASK_ERROR(binary:part(Simple,{7,2})),
- ?line <<8>> = binary:part(Simple,{7,1}),
- ?line random:seed({1271,769940,559934}),
- ?line random_parts(5000),
+ Simple = <<1,2,3,4,5,6,7,8>>,
+ <<1,2>> = binary:part(Simple,0,2),
+ <<1,2>> = binary:part(Simple,{0,2}),
+ Simple = binary:part(Simple,0,8),
+ Simple = binary:part(Simple,{0,8}),
+ badarg = ?MASK_ERROR(binary:part(Simple,0,9)),
+ badarg = ?MASK_ERROR(binary:part(Simple,{0,9})),
+ badarg = ?MASK_ERROR(binary:part(Simple,1,8)),
+ badarg = ?MASK_ERROR(binary:part(Simple,{1,8})),
+ badarg = ?MASK_ERROR(binary:part(Simple,{3,-4})),
+ badarg = ?MASK_ERROR(binary:part(Simple,{3.0,1})),
+ badarg = ?MASK_ERROR(
+ binary:part(Simple,{16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ ,1})),
+ <<2,3,4,5,6,7,8>> = binary:part(Simple,{1,7}),
+ <<2,3,4,5,6,7,8>> = binary:part(Simple,{8,-7}),
+ Simple = binary:part(Simple,{8,-8}),
+ badarg = ?MASK_ERROR(binary:part(Simple,{1,-8})),
+ badarg = ?MASK_ERROR(binary:part(Simple,{8,-9})),
+ badarg = ?MASK_ERROR(binary:part(Simple,{0,-1})),
+ <<>> = binary:part(Simple,{8,0}),
+ badarg = ?MASK_ERROR(binary:part(Simple,{9,0})),
+ badarg = ?MASK_ERROR(binary:part(Simple,{-1,0})),
+ badarg = ?MASK_ERROR(binary:part(Simple,{7,2})),
+ <<8>> = binary:part(Simple,{7,1}),
+ rand:seed(exsplus, {1271,769940,559934}),
+ random_parts(5000),
ok.
@@ -987,15 +955,14 @@ random_parts(N) ->
random_parts(0,_) ->
[];
random_parts(X,N) ->
- Pos = random:uniform(N),
- Len = random:uniform((Pos * 12) div 10),
+ Pos = rand:uniform(N),
+ Len = rand:uniform((Pos * 12) div 10),
[{Pos,Len} | random_parts(X-1,N)].
-random_ref_comp(doc) ->
- ["Test pseudorandomly generated cases against reference imlementation"];
+%% Test pseudorandomly generated cases against reference implementation.
random_ref_comp(Config) when is_list(Config) ->
put(success_counter,0),
- random:seed({1271,769940,559934}),
+ rand:seed(exsplus, {1271,769940,559934}),
Nr = {1,40},
Hr = {30,1000},
I1 = 1500,
@@ -1021,11 +988,11 @@ random_ref_comp(Config) when is_list(Config) ->
erts_debug:set_internal_state(available_internal_state,false),
ok.
-random_ref_sr_comp(doc) ->
- ["Test pseudorandomly generated cases against reference imlementation of split and replace"];
+%% Test pseudorandomly generated cases against reference implementation
+%% of split and replace.
random_ref_sr_comp(Config) when is_list(Config) ->
put(success_counter,0),
- random:seed({1271,769940,559934}),
+ rand:seed(exsplus, {1271,769940,559934}),
Nr = {1,40},
Hr = {30,1000},
I1 = 1500,
@@ -1039,14 +1006,14 @@ random_ref_sr_comp(Config) when is_list(Config) ->
io:format("Number of successes: ~p~n",[get(success_counter)]),
ok.
-random_ref_fla_comp(doc) ->
- ["Test pseudorandomly generated cases against reference imlementation of split and replace"];
+%% Test pseudorandomly generated cases against reference implementation
+%% of split and replace.
random_ref_fla_comp(Config) when is_list(Config) ->
- ?line put(success_counter,0),
- ?line random:seed({1271,769940,559934}),
- ?line do_random_first_comp(5000,{1,1000}),
- ?line do_random_last_comp(5000,{1,1000}),
- ?line do_random_at_comp(5000,{1,1000}),
+ put(success_counter,0),
+ rand:seed(exsplus, {1271,769940,559934}),
+ do_random_first_comp(5000,{1,1000}),
+ do_random_last_comp(5000,{1,1000}),
+ do_random_at_comp(5000,{1,1000}),
io:format("Number of successes: ~p~n",[get(success_counter)]),
ok.
@@ -1326,7 +1293,7 @@ do_random_replace_comp(N,NeedleRange,HaystackRange) ->
true = do_replace_comp(Needle,Haystack,Repl,[]),
true = do_replace_comp(Needle,Haystack,Repl,[global]),
true = do_replace_comp(Needle,Haystack,Repl,
- [global,{insert_replaced,Insertat}]),
+ [global,{insert_replaced,Insertat}]),
do_random_replace_comp(N-1,NeedleRange,HaystackRange).
do_random_replace_comp2(0,_,_) ->
ok;
@@ -1340,7 +1307,7 @@ do_random_replace_comp2(N,NeedleRange,HaystackRange) ->
true = do_replace_comp(Needles,Haystack,Repl,[]),
true = do_replace_comp(Needles,Haystack,Repl,[global]),
true = do_replace_comp(Needles,Haystack,Repl,
- [global,{insert_replaced,Insertat}]),
+ [global,{insert_replaced,Insertat}]),
do_random_replace_comp2(N-1,NeedleRange,HaystackRange).
do_replace_comp(N,H,R,Opts) ->
@@ -1376,25 +1343,25 @@ one_random(N) ->
$Ä,$Ö,$0,$1,$2,$3,$4,$5,$6,$7,$8,$9}).
random_number({Min,Max}) -> % Min and Max are *length* of number in
- % decimal positions
- X = random:uniform(Max - Min + 1) + Min - 1,
- list_to_integer([one_random_number(random:uniform(10)) || _ <- lists:seq(1,X)]).
+ % decimal positions
+ X = rand:uniform(Max - Min + 1) + Min - 1,
+ list_to_integer([one_random_number(rand:uniform(10)) || _ <- lists:seq(1,X)]).
random_length({Min,Max}) ->
- random:uniform(Max - Min + 1) + Min - 1.
+ rand:uniform(Max - Min + 1) + Min - 1.
random_string({Min,Max}) ->
- X = random:uniform(Max - Min + 1) + Min - 1,
- list_to_binary([one_random(random:uniform(68)) || _ <- lists:seq(1,X)]).
+ X = rand:uniform(Max - Min + 1) + Min - 1,
+ list_to_binary([one_random(rand:uniform(68)) || _ <- lists:seq(1,X)]).
random_substring({Min,Max},Hay) ->
- X = random:uniform(Max - Min + 1) + Min - 1,
+ X = rand:uniform(Max - Min + 1) + Min - 1,
Y = byte_size(Hay),
Z = if
X > Y -> Y;
true -> X
end,
PMax = Y - Z,
- Pos = random:uniform(PMax + 1) - 1,
+ Pos = rand:uniform(PMax + 1) - 1,
<<_:Pos/binary,Res:Z/binary,_/binary>> = Hay,
Res.
diff --git a/lib/stdlib/test/binref.erl b/lib/stdlib/test/binref.erl
index a52ea98e5a..deb1ede4df 100644
--- a/lib/stdlib/test/binref.erl
+++ b/lib/stdlib/test/binref.erl
@@ -89,7 +89,7 @@ mloop(_Haystack,_Needles,N,M) when N >= M ->
mloop(Haystack,Needles,N,M) ->
case mloop2(Haystack,Needles,N,nomatch) of
nomatch ->
- % Not found
+ %% Not found
<<_:8,NewStack/binary>> = Haystack,
mloop(NewStack,Needles,N+1,M);
{N,Len} ->
@@ -104,7 +104,7 @@ msloop(_Haystack,_Needles,N,M) when N >= M ->
msloop(Haystack,Needles,N,M) ->
case mloop2(Haystack,Needles,N,nomatch) of
nomatch ->
- % Not found
+ %% Not found
<<_:8,NewStack/binary>> = Haystack,
msloop(NewStack,Needles,N+1,M);
{N,Len} ->
@@ -325,7 +325,7 @@ at(Subject,X) ->
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% bin_to_list
+%% bin_to_list
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bin_to_list(Subject) ->
try
@@ -358,7 +358,7 @@ bin_to_list(Subject,A,B) ->
erlang:error(badarg)
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% list_to_bin
+%% list_to_bin
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
list_to_bin(List) ->
try
diff --git a/lib/stdlib/test/c_SUITE.erl b/lib/stdlib/test/c_SUITE.erl
index f3a713abfd..266918581b 100644
--- a/lib/stdlib/test/c_SUITE.erl
+++ b/lib/stdlib/test/c_SUITE.erl
@@ -23,7 +23,7 @@
-export([c_1/1, c_2/1, c_3/1, c_4/1, nc_1/1, nc_2/1, nc_3/1, nc_4/1,
ls/1, memory/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-import(c, [c/2, nc/2]).
@@ -50,144 +50,117 @@ end_per_group(_GroupName, Config) ->
%%% Write output to a directory other than current directory:
-c_1(doc) ->
- ["Checks that c:c works also with option 'outdir' [ticket OTP-1209]."];
-c_1(suite) ->
- [];
+%% OTP-1209: Check that c:c/2 works also with option 'outdir'.
c_1(Config) when is_list(Config) ->
- ?line R = filename:join(?config(data_dir, Config), "m.erl"),
- ?line W = ?config(priv_dir, Config),
- ?line Result = c(R,[{outdir,W}]),
- ?line {ok, m} = Result.
-
-c_2(doc) ->
- ["Checks that c:c works also with option 'outdir' [ticket OTP-1209]."];
-c_2(suite) ->
- [];
+ R = filename:join(proplists:get_value(data_dir, Config), "m.erl"),
+ W = proplists:get_value(priv_dir, Config),
+ Result = c(R,[{outdir,W}]),
+ {ok, m} = Result.
+
+%% OTP-1209: Check that c:c/2 works also with option 'outdir'.
c_2(Config) when is_list(Config) ->
- ?line R = filename:join(?config(data_dir, Config), "m"),
- ?line W = ?config(priv_dir, Config),
- ?line Result = c(R,[{outdir,W}]),
- ?line {ok, m} = Result.
+ R = filename:join(proplists:get_value(data_dir, Config), "m"),
+ W = proplists:get_value(priv_dir, Config),
+ Result = c(R,[{outdir,W}]),
+ {ok, m} = Result.
%%% Put results in current directory (or rather, change current dir
%%% to the output dir):
-c_3(doc) ->
- ["Checks that c:c works also with option 'outdir' (same as current"
- "directory). [ticket OTP-1209]."];
-c_3(suite) ->
- [];
+%% OTP-1209: Check that c:c/2 works also with option 'outdir'
+%% (same as current directory).
c_3(Config) when is_list(Config) ->
- ?line R = filename:join(?config(data_dir, Config), "m.erl"),
- ?line W = ?config(priv_dir, Config),
- ?line file:set_cwd(W),
- ?line Result = c(R,[{outdir,W}]),
- ?line {ok, m} = Result.
-
-c_4(doc) ->
- ["Checks that c:c works also with option 'outdir' (same as current"
- "directory). [ticket OTP-1209]."];
-c_4(suite) ->
- [];
+ R = filename:join(proplists:get_value(data_dir, Config), "m.erl"),
+ W = proplists:get_value(priv_dir, Config),
+ file:set_cwd(W),
+ Result = c(R,[{outdir,W}]),
+ {ok, m} = Result.
+
+%% OTP-1209: Check that c:c/2 works also with option 'outdir'
+%% (same as current directory).
c_4(Config) when is_list(Config) ->
- ?line R = filename:join(?config(data_dir, Config), "m"),
- ?line W = ?config(priv_dir, Config),
- ?line file:set_cwd(W),
- ?line Result = c(R,[{outdir,W}]),
- ?line {ok, m} = Result.
+ R = filename:join(proplists:get_value(data_dir, Config), "m"),
+ W = proplists:get_value(priv_dir, Config),
+ file:set_cwd(W),
+ Result = c(R,[{outdir,W}]),
+ {ok, m} = Result.
%%% Write output to a directory other than current directory:
-nc_1(doc) ->
- ["Checks that c:nc works also with option 'outdir'."];
-nc_1(suite) ->
- [];
+%% Check that c:nc/2 works also with option 'outdir'.
nc_1(Config) when is_list(Config) ->
- ?line R = filename:join(?config(data_dir, Config), "m.erl"),
- ?line W = ?config(priv_dir, Config),
- ?line Result = nc(R,[{outdir,W}]),
- ?line {ok, m} = Result.
-
-nc_2(doc) ->
- ["Checks that c:nc works also with option 'outdir'."];
-nc_2(suite) ->
- [];
+ R = filename:join(proplists:get_value(data_dir, Config), "m.erl"),
+ W = proplists:get_value(priv_dir, Config),
+ Result = nc(R,[{outdir,W}]),
+ {ok, m} = Result.
+
+%% Check that c:nc/2 works also with option 'outdir'.
nc_2(Config) when is_list(Config) ->
- ?line R = filename:join(?config(data_dir, Config), "m"),
- ?line W = ?config(priv_dir, Config),
- ?line Result = nc(R,[{outdir,W}]),
- ?line {ok, m} = Result.
+ R = filename:join(proplists:get_value(data_dir, Config), "m"),
+ W = proplists:get_value(priv_dir, Config),
+ Result = nc(R,[{outdir,W}]),
+ {ok, m} = Result.
%%% Put results in current directory (or rather, change current dir
%%% to the output dir):
-nc_3(doc) ->
- ["Checks that c:nc works also with option 'outdir' (same as current"
- "directory)."];
-nc_3(suite) ->
- [];
+%% Check that c:nc/2 works also with option 'outdir'
+%% (same as current directory).
nc_3(Config) when is_list(Config) ->
- ?line R = filename:join(?config(data_dir, Config), "m.erl"),
- ?line W = ?config(priv_dir, Config),
- ?line file:set_cwd(W),
- ?line Result = nc(R,[{outdir,W}]),
- ?line {ok, m} = Result.
-
-nc_4(doc) ->
- ["Checks that c:nc works also with option 'outdir' (same as current"
- "directory)."];
-nc_4(suite) ->
- [];
+ R = filename:join(proplists:get_value(data_dir, Config), "m.erl"),
+ W = proplists:get_value(priv_dir, Config),
+ file:set_cwd(W),
+ Result = nc(R,[{outdir,W}]),
+ {ok, m} = Result.
+
+%% Check that c:nc/2 works also with option 'outdir'
+%% (same as current directory).
nc_4(Config) when is_list(Config) ->
- ?line R = filename:join(?config(data_dir, Config), "m"),
- ?line W = ?config(priv_dir, Config),
- ?line file:set_cwd(W),
- ?line Result = nc(R,[{outdir,W}]),
- ?line {ok, m} = Result.
+ R = filename:join(proplists:get_value(data_dir, Config), "m"),
+ W = proplists:get_value(priv_dir, Config),
+ file:set_cwd(W),
+ Result = nc(R,[{outdir,W}]),
+ {ok, m} = Result.
ls(Config) when is_list(Config) ->
- Directory = ?config(data_dir, Config),
+ Directory = proplists:get_value(data_dir, Config),
ok = c:ls(Directory),
File = filename:join(Directory, "m.erl"),
ok = c:ls(File),
ok = c:ls("no_such_file").
-memory(doc) ->
- ["Checks that c:memory/[0,1] returns consistent results."];
-memory(suite) ->
- [];
+%% Check that c:memory/[0,1] returns consistent results.
memory(Config) when is_list(Config) ->
try
- ?line ML = c:memory(),
- ?line T = mget(total, ML),
- ?line P = mget(processes, ML),
- ?line S = mget(system, ML),
- ?line A = mget(atom, ML),
- ?line AU = mget(atom_used, ML),
- ?line B = mget(binary, ML),
- ?line C = mget(code, ML),
- ?line E = mget(ets, ML),
- ?line T = P + S,
- ?line if S >= A + B + C + E -> ok end,
- ?line if A >= AU -> ok end,
- ?line ok
+ ML = c:memory(),
+ T = mget(total, ML),
+ P = mget(processes, ML),
+ S = mget(system, ML),
+ A = mget(atom, ML),
+ AU = mget(atom_used, ML),
+ B = mget(binary, ML),
+ C = mget(code, ML),
+ E = mget(ets, ML),
+ T = P + S,
+ if S >= A + B + C + E -> ok end,
+ if A >= AU -> ok end,
+ ok
catch
error:notsup ->
- ?line {skipped,
- "erlang:memory/[0,1] and c:memory/[0,1] not supported"}
+ {skipped,
+ "erlang:memory/[0,1] and c:memory/[0,1] not supported"}
end.
-% Help function for c_SUITE:memory/1
+%% Help function for c_SUITE:memory/1
mget(K, L) ->
- ?line {value,{K,V}} = lists:keysearch(K, 1, L),
- ?line test_v(c:memory(K)), % Check that c:memory/1 also accept this
- % argument and returns an integer (usally
- % *not* the same as V).
- ?line test_v(V).
+ {value,{K,V}} = lists:keysearch(K, 1, L),
+ test_v(c:memory(K)), % Check that c:memory/1 also accept this
+ % argument and returns an integer (usally
+ % *not* the same as V).
+ test_v(V).
-% Help function for c_SUITE:memory/1
+%% Help function for c_SUITE:memory/1
test_v(V) when is_integer(V) ->
- ?line V.
+ V.
diff --git a/lib/stdlib/test/calendar_SUITE.erl b/lib/stdlib/test/calendar_SUITE.erl
index 498b1f459c..7372288492 100644
--- a/lib/stdlib/test/calendar_SUITE.erl
+++ b/lib/stdlib/test/calendar_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(calendar_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
@@ -57,69 +57,48 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-gregorian_days(doc) ->
- "Tests that date_to_gregorian_days and gregorian_days_to_date "
- "are each others inverses from ?START_YEAR-01-01 up to ?END_YEAR-01-01. "
- "At the same time valid_date is tested.";
-gregorian_days(suite) ->
- [];
+%% Tests that date_to_gregorian_days and gregorian_days_to_date
+%% are each others inverses from ?START_YEAR-01-01 up to ?END_YEAR-01-01.
+%% At the same time valid_date is tested.
gregorian_days(Config) when is_list(Config) ->
- ?line Days = calendar:date_to_gregorian_days({?START_YEAR, 1, 1}),
- ?line MaxDays = calendar:date_to_gregorian_days({?END_YEAR, 1, 1}),
- ?line check_gregorian_days(Days, MaxDays).
-
-gregorian_seconds(doc) ->
- "Tests that datetime_to_gregorian_seconds and "
- "gregorian_seconds_to_date are each others inverses for a sampled "
- "number of seconds from ?START_YEAR-01-01 up to ?END_YEAR-01-01: We check "
- "every 2 days + 1 second.";
-gregorian_seconds(suite) ->
- [];
+ Days = calendar:date_to_gregorian_days({?START_YEAR, 1, 1}),
+ MaxDays = calendar:date_to_gregorian_days({?END_YEAR, 1, 1}),
+ check_gregorian_days(Days, MaxDays).
+
+%% Tests that datetime_to_gregorian_seconds and
+%% gregorian_seconds_to_date are each others inverses for a sampled
+%% number of seconds from ?START_YEAR-01-01 up to ?END_YEAR-01-01: We check
+%% every 2 days + 1 second.
gregorian_seconds(Config) when is_list(Config) ->
- ?line Secs = calendar:datetime_to_gregorian_seconds({{?START_YEAR, 1, 1},
- {0, 0, 0}}),
- ?line MaxSecs = calendar:datetime_to_gregorian_seconds({{?END_YEAR, 1, 1},
- {0, 0, 0}}),
- ?line check_gregorian_seconds(Secs, MaxSecs).
-
-day_of_the_week(doc) ->
- "Tests that day_of_the_week reports correctly the day of the week from "
- "year ?START_YEAR up to ?END_YEAR.";
-day_of_the_week(suite) ->
- [];
+ Secs = calendar:datetime_to_gregorian_seconds({{?START_YEAR, 1, 1},
+ {0, 0, 0}}),
+ MaxSecs = calendar:datetime_to_gregorian_seconds({{?END_YEAR, 1, 1},
+ {0, 0, 0}}),
+ check_gregorian_seconds(Secs, MaxSecs).
+
+%% Tests that day_of_the_week reports correctly the day of the week from
+%% year ?START_YEAR up to ?END_YEAR.
day_of_the_week(Config) when is_list(Config) ->
- ?line Days = calendar:date_to_gregorian_days({?START_YEAR, 1, 1}),
- ?line MaxDays = calendar:date_to_gregorian_days({?END_YEAR, 1, 1}),
- ?line DayNumber = calendar:day_of_the_week({?START_YEAR, 1, 1}),
- ?line check_day_of_the_week(Days, MaxDays, DayNumber).
+ Days = calendar:date_to_gregorian_days({?START_YEAR, 1, 1}),
+ MaxDays = calendar:date_to_gregorian_days({?END_YEAR, 1, 1}),
+ DayNumber = calendar:day_of_the_week({?START_YEAR, 1, 1}),
+ check_day_of_the_week(Days, MaxDays, DayNumber).
-day_of_the_week_calibrate(doc) ->
- "Tests that day_of_the_week for 1997-11-11 is Tuesday (2)";
-day_of_the_week_calibrate(suite) ->
- [];
+%% Tests that day_of_the_week for 1997-11-11 is Tuesday (2).
day_of_the_week_calibrate(Config) when is_list(Config) ->
- ?line 2 = calendar:day_of_the_week({1997, 11, 11}).
+ 2 = calendar:day_of_the_week({1997, 11, 11}).
-leap_years(doc) ->
- "Tests that is_leap_year reports correctly the leap years from "
- "year ?START_YEAR up to ?END_YEAR.";
-leap_years(suite) ->
- [];
+%% Tests that is_leap_year reports correctly the leap years from
+%% year ?START_YEAR up to ?END_YEAR.
leap_years(Config) when is_list(Config) ->
- ?line check_leap_years(?START_YEAR, ?END_YEAR).
+ check_leap_years(?START_YEAR, ?END_YEAR).
-last_day_of_the_month(doc) ->
- "Tests that last_day_of_the_month reports correctly from "
- "year ?START_YEAR up to ?END_YEAR.";
-last_day_of_the_month(suite) ->
- [];
+%% Tests that last_day_of_the_month reports correctly from
+%% year ?START_YEAR up to ?END_YEAR.
last_day_of_the_month(Config) when is_list(Config) ->
- ?line check_last_day_of_the_month({?START_YEAR, 1}, {?END_YEAR, 1}).
+ check_last_day_of_the_month({?START_YEAR, 1}, {?END_YEAR, 1}).
-local_time_to_universal_time_dst(doc) ->
- "Tests local_time_to_universal_time_dst for MET";
-local_time_to_universal_time_dst(suite) ->
- [];
+%% Tests local_time_to_universal_time_dst for MET.
local_time_to_universal_time_dst(Config) when is_list(Config) ->
case os:type() of
{unix,_} ->
@@ -134,35 +113,35 @@ local_time_to_universal_time_dst(Config) when is_list(Config) ->
end.
local_time_to_universal_time_dst_x(Config) when is_list(Config) ->
%% Assumes MET (UTC+1 / UTC+2(dst)
- ?line LtW = {{2003,01,15},{14,00,00}}, % Winter
- ?line UtW = {{2003,01,15},{13,00,00}}, %
- ?line UtWd = {{2003,01,15},{12,00,00}}, % dst
- ?line LtS = {{2003,07,15},{14,00,00}}, % Summer
- ?line UtS = {{2003,07,15},{13,00,00}}, %
- ?line UtSd = {{2003,07,15},{12,00,00}}, % dst
- ?line LtWS = {{2003,03,30},{02,30,00}}, % Winter->Summer
- ?line UtWS = {{2003,03,30},{01,30,00}}, %
- ?line UtWSd = {{2003,03,30},{00,30,00}}, % dst
- ?line LtSW = {{2003,10,26},{02,30,00}}, % Summer->Winter
- ?line UtSW = {{2003,10,26},{01,30,00}}, %
- ?line UtSWd = {{2003,10,26},{00,30,00}}, % dst
+ LtW = {{2003,01,15},{14,00,00}}, % Winter
+ UtW = {{2003,01,15},{13,00,00}}, %
+ UtWd = {{2003,01,15},{12,00,00}}, % dst
+ LtS = {{2003,07,15},{14,00,00}}, % Summer
+ UtS = {{2003,07,15},{13,00,00}}, %
+ UtSd = {{2003,07,15},{12,00,00}}, % dst
+ LtWS = {{2003,03,30},{02,30,00}}, % Winter->Summer
+ UtWS = {{2003,03,30},{01,30,00}}, %
+ UtWSd = {{2003,03,30},{00,30,00}}, % dst
+ LtSW = {{2003,10,26},{02,30,00}}, % Summer->Winter
+ UtSW = {{2003,10,26},{01,30,00}}, %
+ UtSWd = {{2003,10,26},{00,30,00}}, % dst
%%
- ?line UtW = calendar:local_time_to_universal_time(LtW, false),
- ?line UtWd = calendar:local_time_to_universal_time(LtW, true),
- ?line UtW = calendar:local_time_to_universal_time(LtW, undefined),
+ UtW = calendar:local_time_to_universal_time(LtW, false),
+ UtWd = calendar:local_time_to_universal_time(LtW, true),
+ UtW = calendar:local_time_to_universal_time(LtW, undefined),
%%
- ?line UtS = calendar:local_time_to_universal_time(LtS, false),
- ?line UtSd = calendar:local_time_to_universal_time(LtS, true),
- ?line UtSd = calendar:local_time_to_universal_time(LtS, undefined),
+ UtS = calendar:local_time_to_universal_time(LtS, false),
+ UtSd = calendar:local_time_to_universal_time(LtS, true),
+ UtSd = calendar:local_time_to_universal_time(LtS, undefined),
%%
case calendar:local_time_to_universal_time(LtWS, false) of
UtWS ->
- ?line UtWSd = calendar:local_time_to_universal_time(LtWS, true),
- ?line [] = calendar:local_time_to_universal_time_dst(LtWS),
+ UtWSd = calendar:local_time_to_universal_time(LtWS, true),
+ [] = calendar:local_time_to_universal_time_dst(LtWS),
%%
- ?line UtSW = calendar:local_time_to_universal_time(LtSW, false),
- ?line UtSWd = calendar:local_time_to_universal_time(LtSW, true),
- ?line [UtSWd, UtSW] = calendar:local_time_to_universal_time_dst(LtSW),
+ UtSW = calendar:local_time_to_universal_time(LtSW, false),
+ UtSWd = calendar:local_time_to_universal_time(LtSW, true),
+ [UtSWd, UtSW] = calendar:local_time_to_universal_time_dst(LtSW),
ok;
{{1969,12,31},{23,59,59}} ->
%% It seems that Apple has no intention of fixing this bug in
@@ -171,15 +150,12 @@ local_time_to_universal_time_dst_x(Config) when is_list(Config) ->
{comment,"Bug in mktime() in this OS"}
end.
-iso_week_number(doc) ->
- "Test the iso week number calculation for all three possibilities."
- " When the date falls on the last week of the previous year,"
- " when the date falls on a week within the given year and finally,"
- " when the date falls on the first week of the next year.";
-iso_week_number(suite) ->
- [];
+%% Test the iso week number calculation for all three possibilities:
+%% When the date falls on the last week of the previous year,
+%% when the date falls on a week within the given year and finally,
+%% when the date falls on the first week of the next year.
iso_week_number(Config) when is_list(Config) ->
- ?line check_iso_week_number().
+ check_iso_week_number().
%%
%% LOCAL FUNCTIONS
@@ -188,10 +164,10 @@ iso_week_number(Config) when is_list(Config) ->
%% check_gregorian_days
%%
check_gregorian_days(Days, MaxDays) when Days < MaxDays ->
- ?line Date = calendar:gregorian_days_to_date(Days),
- ?line true = calendar:valid_date(Date),
- ?line Days = calendar:date_to_gregorian_days(Date),
- ?line check_gregorian_days(Days + 1, MaxDays);
+ Date = calendar:gregorian_days_to_date(Days),
+ true = calendar:valid_date(Date),
+ Days = calendar:date_to_gregorian_days(Date),
+ check_gregorian_days(Days + 1, MaxDays);
check_gregorian_days(_Days, _MaxDays) ->
ok.
@@ -200,9 +176,9 @@ check_gregorian_days(_Days, _MaxDays) ->
%% We increment with something prime (172801 = 2 days + 1 second).
%%
check_gregorian_seconds(Secs, MaxSecs) when Secs < MaxSecs ->
- ?line DateTime = calendar:gregorian_seconds_to_datetime(Secs),
- ?line Secs = calendar:datetime_to_gregorian_seconds(DateTime),
- ?line check_gregorian_seconds(Secs + 172801, MaxSecs);
+ DateTime = calendar:gregorian_seconds_to_datetime(Secs),
+ Secs = calendar:datetime_to_gregorian_seconds(DateTime),
+ check_gregorian_seconds(Secs + 172801, MaxSecs);
check_gregorian_seconds(_Secs, _MaxSecs) ->
ok.
@@ -210,10 +186,10 @@ check_gregorian_seconds(_Secs, _MaxSecs) ->
%% check_day_of_the_week
%%
check_day_of_the_week(Days, MaxDays, DayNumber) when Days < MaxDays ->
- ?line Date = calendar:gregorian_days_to_date(Days),
- ?line DayNumber = calendar:day_of_the_week(Date),
- ?line check_day_of_the_week(Days + 1, MaxDays,
- ((DayNumber rem 7) + 1));
+ Date = calendar:gregorian_days_to_date(Days),
+ DayNumber = calendar:day_of_the_week(Date),
+ check_day_of_the_week(Days + 1, MaxDays,
+ ((DayNumber rem 7) + 1));
check_day_of_the_week(_Days, _MaxDays, _DayNumber) ->
ok.
@@ -222,59 +198,56 @@ check_day_of_the_week(_Days, _MaxDays, _DayNumber) ->
%% SYr must be larger than 1800, and EYr must be less than ?END_YEAR.
%%
check_leap_years(SYr, EYr) when SYr < EYr ->
- ?line Rem = SYr rem 4,
+ Rem = SYr rem 4,
case Rem of
0 ->
case SYr of
1900 ->
- ?line false = calendar:is_leap_year(SYr);
+ false = calendar:is_leap_year(SYr);
2000 ->
- ?line true = calendar:is_leap_year(SYr);
+ true = calendar:is_leap_year(SYr);
_ ->
- ?line true = calendar:is_leap_year(SYr)
+ true = calendar:is_leap_year(SYr)
end;
_ ->
- ?line false = calendar:is_leap_year(SYr)
+ false = calendar:is_leap_year(SYr)
end,
check_leap_years(SYr + 1, EYr);
check_leap_years(_SYr, _EYr) ->
ok.
check_last_day_of_the_month({SYr, SMon}, {EYr, EMon}) when SYr < EYr ->
- ?line LastDay = calendar:last_day_of_the_month(SYr, SMon),
- ?line LastDay = case SMon of
- 1 -> 31;
- 2 ->
- case calendar:is_leap_year(SYr) of
- true -> 29;
- false -> 28
- end;
- 3 -> 31;
- 4 -> 30;
- 5 -> 31;
- 6 -> 30;
- 7 -> 31;
- 8 -> 31;
- 9 -> 30;
- 10 -> 31;
- 11 -> 30;
- 12 -> 31
- end,
- ?line NYr = case SMon of
- 12 -> SYr + 1;
- _ -> SYr
- end,
- ?line check_last_day_of_the_month({NYr, (SMon rem 12) + 1},
- {EYr, EMon});
+ LastDay = calendar:last_day_of_the_month(SYr, SMon),
+ LastDay = case SMon of
+ 1 -> 31;
+ 2 ->
+ case calendar:is_leap_year(SYr) of
+ true -> 29;
+ false -> 28
+ end;
+ 3 -> 31;
+ 4 -> 30;
+ 5 -> 31;
+ 6 -> 30;
+ 7 -> 31;
+ 8 -> 31;
+ 9 -> 30;
+ 10 -> 31;
+ 11 -> 30;
+ 12 -> 31
+ end,
+ NYr = case SMon of
+ 12 -> SYr + 1;
+ _ -> SYr
+ end,
+ check_last_day_of_the_month({NYr, (SMon rem 12) + 1},
+ {EYr, EMon});
check_last_day_of_the_month(_, _) ->
ok.
%% check_iso_week_number
%%
check_iso_week_number() ->
- ?line {2004, 53} = calendar:iso_week_number({2005, 1, 1}),
- ?line {2007, 1} = calendar:iso_week_number({2007, 1, 1}),
- ?line {2009, 1} = calendar:iso_week_number({2008, 12, 29}).
-
-
-
+ {2004, 53} = calendar:iso_week_number({2005, 1, 1}),
+ {2007, 1} = calendar:iso_week_number({2007, 1, 1}),
+ {2009, 1} = calendar:iso_week_number({2008, 12, 29}).
diff --git a/lib/stdlib/test/dets_SUITE.erl b/lib/stdlib/test/dets_SUITE.erl
index 35e587afcc..8948f496c4 100644
--- a/lib/stdlib/test/dets_SUITE.erl
+++ b/lib/stdlib/test/dets_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-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.
@@ -19,7 +19,7 @@
%%
-module(dets_SUITE).
-%-define(debug, true).
+%%-define(debug, true).
-ifdef(debug).
-define(format(S, A), io:format(S, A)).
@@ -28,10 +28,10 @@
-define(privdir(_), "./dets_SUITE_priv").
-define(datadir(_), "./dets_SUITE_data").
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(format(S, A), ok).
--define(privdir(Conf), ?config(priv_dir, Conf)).
--define(datadir(Conf), ?config(data_dir, Conf)).
+-define(privdir(Conf), proplists:get_value(priv_dir, Conf)).
+-define(datadir(Conf), proplists:get_value(data_dir, Conf)).
-endif.
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -53,7 +53,8 @@
simultaneous_open/1, insert_new/1, repair_continuation/1,
otp_5487/1, otp_6206/1, otp_6359/1, otp_4738/1, otp_7146/1,
otp_8070/1, otp_8856/1, otp_8898/1, otp_8899/1, otp_8903/1,
- otp_8923/1, otp_9282/1, otp_11245/1, otp_11709/1]).
+ otp_8923/1, otp_9282/1, otp_11245/1, otp_11709/1, otp_13229/1,
+ otp_13260/1]).
-export([dets_dirty_loop/0]).
@@ -82,15 +83,14 @@
-define(CLOSED_PROPERLY,1).
init_per_testcase(_Case, Config) ->
- Dog=?t:timetrap(?t:minutes(15)),
- [{watchdog, Dog}|Config].
+ Config.
end_per_testcase(_Case, _Config) ->
- Dog=?config(watchdog, _Config),
- test_server:timetrap_cancel(Dog),
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,15}}].
all() ->
[
@@ -110,7 +110,8 @@ all() ->
many_clients, otp_4906, otp_5402, simultaneous_open,
insert_new, repair_continuation, otp_5487, otp_6206,
otp_6359, otp_4738, otp_7146, otp_8070, otp_8856, otp_8898,
- otp_8899, otp_8903, otp_8923, otp_9282, otp_11245, otp_11709
+ otp_8899, otp_8903, otp_8923, otp_9282, otp_11245, otp_11709,
+ otp_13229, otp_13260
].
groups() ->
@@ -128,10 +129,7 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-newly_started(doc) ->
- ["OTP-3621"];
-newly_started(suite) ->
- [];
+%% OTP-3621
newly_started(Config) when is_list(Config) ->
true = is_alive(),
{ok, Node} = test_server:start_node(slave1, slave, []),
@@ -139,17 +137,11 @@ newly_started(Config) when is_list(Config) ->
test_server:stop_node(Node),
ok.
-basic_v8(doc) ->
- ["Basic test case."];
-basic_v8(suite) ->
- [];
+%% Basic test case.
basic_v8(Config) when is_list(Config) ->
basic(Config, 8).
-basic_v9(doc) ->
- ["Basic test case."];
-basic_v9(suite) ->
- [];
+%% Basic test case.
basic_v9(Config) when is_list(Config) ->
basic(Config, 9).
@@ -182,17 +174,9 @@ basic(Config, Version) ->
ok.
-open_v8(doc) ->
- [];
-open_v8(suite) ->
- [];
open_v8(Config) when is_list(Config) ->
open(Config, 8).
-open_v9(doc) ->
- [];
-open_v9(suite) ->
- [];
open_v9(Config) when is_list(Config) ->
open(Config, 9).
@@ -281,17 +265,11 @@ bad(_Tab, _Item) ->
?format("Can't find item ~p in ~p ~n", [_Item, _Tab]),
exit(badtab).
-sets_v8(doc) ->
- ["Performs traversal and match testing on set type dets tables."];
-sets_v8(suite) ->
- [];
+%% Perform traversal and match testing on set type dets tables.
sets_v8(Config) when is_list(Config) ->
sets(Config, 8).
-sets_v9(doc) ->
- ["Performs traversal and match testing on set type dets tables."];
-sets_v9(suite) ->
- [];
+%% Perform traversal and match testing on set type dets tables.
sets_v9(Config) when is_list(Config) ->
sets(Config, 9).
@@ -323,17 +301,11 @@ sets(Config, Version) ->
check_pps(P0),
ok.
-bags_v8(doc) ->
- ["Performs traversal and match testing on bag type dets tables."];
-bags_v8(suite) ->
- [];
+%% Perform traversal and match testing on bag type dets tables.
bags_v8(Config) when is_list(Config) ->
bags(Config, 8).
-bags_v9(doc) ->
- ["Performs traversal and match testing on bag type dets tables."];
-bags_v9(suite) ->
- [];
+%% Perform traversal and match testing on bag type dets tables.
bags_v9(Config) when is_list(Config) ->
bags(Config, 9).
@@ -363,17 +335,11 @@ bags(Config, Version) ->
ok.
-duplicate_bags_v8(doc) ->
- ["Performs traversal and match testing on duplicate_bag type dets tables."];
-duplicate_bags_v8(suite) ->
- [];
+%% Perform traversal and match testing on duplicate_bag type dets tables.
duplicate_bags_v8(Config) when is_list(Config) ->
duplicate_bags(Config, 8).
-duplicate_bags_v9(doc) ->
- ["Performs traversal and match testing on duplicate_bag type dets tables."];
-duplicate_bags_v9(suite) ->
- [];
+%% Perform traversal and match testing on duplicate_bag type dets tables.
duplicate_bags_v9(Config) when is_list(Config) ->
duplicate_bags(Config, 9).
@@ -403,17 +369,9 @@ duplicate_bags(Config, Version) when is_list(Config) ->
ok.
-access_v8(doc) ->
- [];
-access_v8(suite) ->
- [];
access_v8(Config) when is_list(Config) ->
access(Config, 8).
-access_v9(doc) ->
- [];
-access_v9(suite) ->
- [];
access_v9(Config) when is_list(Config) ->
access(Config, 9).
@@ -446,10 +404,7 @@ access(Config, Version) ->
ok.
-dirty_mark(doc) ->
- ["Test that the table is not marked dirty if not written"];
-dirty_mark(suite) ->
- [];
+%% Test that the table is not marked dirty if not written.
dirty_mark(Config) when is_list(Config) ->
true = is_alive(),
Tab = dets_dirty_mark_test,
@@ -498,10 +453,7 @@ dirty_mark(Config) when is_list(Config) ->
check_pps(P0),
ok.
-dirty_mark2(doc) ->
- ["Test that the table is flushed when auto_save is in effect"];
-dirty_mark2(suite) ->
- [];
+%% Test that the table is flushed when auto_save is in effect.
dirty_mark2(Config) when is_list(Config) ->
true = is_alive(),
Tab = dets_dirty_mark2_test,
@@ -569,17 +521,11 @@ dets_dirty_loop() ->
end.
-bag_next_v8(suite) ->
- [];
-bag_next_v8(doc) ->
- ["Check that bags and next work as expected."];
+%% Check that bags and next work as expected.
bag_next_v8(Config) when is_list(Config) ->
bag_next(Config, 8).
-bag_next_v9(suite) ->
- [];
-bag_next_v9(doc) ->
- ["Check that bags and next work as expected."];
+%% Check that bags and next work as expected.
bag_next_v9(Config) when is_list(Config) ->
Tab = dets_bag_next_test,
FName = filename(Tab, Config),
@@ -632,17 +578,9 @@ bag_next(Config, Version) ->
check_pps(P0),
ok.
-oldbugs_v8(doc) ->
- [];
-oldbugs_v8(suite) ->
- [];
oldbugs_v8(Config) when is_list(Config) ->
oldbugs(Config, 8).
-oldbugs_v9(doc) ->
- [];
-oldbugs_v9(suite) ->
- [];
oldbugs_v9(Config) when is_list(Config) ->
oldbugs(Config, 9).
@@ -660,9 +598,7 @@ oldbugs(Config, Version) ->
check_pps(P0),
ok.
-unsafe_assumptions(suite) -> [];
-unsafe_assumptions(doc) ->
- "Tests that shrinking an object and then expanding it works.";
+%% Test that shrinking an object and then expanding it works.
unsafe_assumptions(Config) when is_list(Config) ->
FName = filename(dets_suite_unsafe_assumptions_test, Config),
file:delete(FName),
@@ -691,17 +627,13 @@ unsafe_assumptions(Config) when is_list(Config) ->
check_pps(P0),
ok.
-truncated_segment_array_v8(suite) -> [];
-truncated_segment_array_v8(doc) ->
- "Tests that a file where the segment array has been truncated "
- "is possible to repair.";
+%% Test that a file where the segment array has been truncated
+%% is possible to repair.
truncated_segment_array_v8(Config) when is_list(Config) ->
trunc_seg_array(Config, 8).
-truncated_segment_array_v9(suite) -> [];
-truncated_segment_array_v9(doc) ->
- "Tests that a file where the segment array has been truncated "
- "is possible to repair.";
+%% Test that a file where the segment array has been truncated
+%% is possible to repair.
truncated_segment_array_v9(Config) when is_list(Config) ->
trunc_seg_array(Config, 9).
@@ -727,17 +659,11 @@ trunc_seg_array(Config, V) ->
check_pps(P0),
ok.
-open_file_v8(doc) ->
- ["open_file/1 test case."];
-open_file_v8(suite) ->
- [];
+%% Test open_file/1.
open_file_v8(Config) when is_list(Config) ->
open_1(Config, 8).
-open_file_v9(doc) ->
- ["open_file/1 test case."];
-open_file_v9(suite) ->
- [];
+%% Test open_file/1.
open_file_v9(Config) when is_list(Config) ->
T = open_v9,
Fname = filename(T, Config),
@@ -795,17 +721,11 @@ open_1(Config, V) ->
check_pps(P0),
ok.
-init_table_v8(doc) ->
- ["initialize_table/2 and from_ets/2 test case."];
-init_table_v8(suite) ->
- [];
+%% Test initialize_table/2 and from_ets/2.
init_table_v8(Config) when is_list(Config) ->
init_table(Config, 8).
-init_table_v9(doc) ->
- ["initialize_table/2 and from_ets/2 test case."];
-init_table_v9(suite) ->
- [];
+%% Test initialize_table/2 and from_ets/2.
init_table_v9(Config) when is_list(Config) ->
%% Objects are returned in "time order".
T = init_table_v9,
@@ -1268,17 +1188,11 @@ items(I, N, C, L) when I =:= N; C =:= 0 ->
items(I, N, C, L) ->
items(I+1, N, C-1, [{I, item(I)} | L]).
-repair_v8(doc) ->
- ["open_file and repair."];
-repair_v8(suite) ->
- [];
+%% Test open_file and repair.
repair_v8(Config) when is_list(Config) ->
repair(Config, 8).
-repair_v9(doc) ->
- ["open_file and repair."];
-repair_v9(suite) ->
- [];
+%% Test open_file and repair.
repair_v9(Config) when is_list(Config) ->
%% Convert from format 9 to format 8.
T = convert_98,
@@ -1615,11 +1529,9 @@ repair(Config, V) ->
check_pps(P0),
ok.
-hash_v8b_v8c(doc) ->
- ["Test the use of different hashing algorithms in v8b and v8c of the "
- "Dets file format."];
-hash_v8b_v8c(suite) ->
- [];
+
+%% Test the use of different hashing algorithms in v8b and v8c of the
+%% Dets file format.
hash_v8b_v8c(Config) when is_list(Config) ->
Source =
filename:join(?datadir(Config), "dets_test_v8b.dets"),
@@ -1694,10 +1606,7 @@ hash_v8b_v8c(Config) when is_list(Config) ->
check_pps(P0),
{comment, Mess}.
-phash(doc) ->
- ["Test version 9(b) with erlang:phash/2 as hash function."];
-phash(suite) ->
- [];
+%% Test version 9(b) with erlang:phash/2 as hash function.
phash(Config) when is_list(Config) ->
T = phash,
Phash_v9bS = filename:join(?datadir(Config), "version_9b_phash.dat"),
@@ -1755,17 +1664,11 @@ phash(Config) when is_list(Config) ->
file:delete(Fname),
ok.
-fold_v8(doc) ->
- ["foldl, foldr, to_ets"];
-fold_v8(suite) ->
- [];
+%% Test foldl, foldr, to_ets.
fold_v8(Config) when is_list(Config) ->
fold(Config, 8).
-fold_v9(doc) ->
- ["foldl, foldr, to_ets"];
-fold_v9(suite) ->
- [];
+%% Test foldl, foldr, to_ets.
fold_v9(Config) when is_list(Config) ->
fold(Config, 9).
@@ -1834,17 +1737,11 @@ fold(Config, Version) ->
check_pps(P0),
ok.
-fixtable_v8(doc) ->
- ["Add objects to a fixed table."];
-fixtable_v8(suite) ->
- [];
+%% Add objects to a fixed table.
fixtable_v8(Config) when is_list(Config) ->
fixtable(Config, 8).
-fixtable_v9(doc) ->
- ["Add objects to a fixed table."];
-fixtable_v9(suite) ->
- [];
+%% Add objects to a fixed table.
fixtable_v9(Config) when is_list(Config) ->
fixtable(Config, 9).
@@ -1934,17 +1831,11 @@ fixtable(Config, Version) when is_list(Config) ->
check_pps(P0),
ok.
-match_v8(doc) ->
- ["Matching objects of a fixed table."];
-match_v8(suite) ->
- [];
+%% Matching objects of a fixed table.
match_v8(Config) when is_list(Config) ->
match(Config, 8).
-match_v9(doc) ->
- ["Matching objects of a fixed table."];
-match_v9(suite) ->
- [];
+%% Matching objects of a fixed table.
match_v9(Config) when is_list(Config) ->
match(Config, 9).
@@ -2116,17 +2007,11 @@ match(Config, Version) ->
check_pps(P0),
ok.
-select_v8(doc) ->
- ["Selecting objects of a fixed table."];
-select_v8(suite) ->
- [];
+%% Selecting objects of a fixed table.
select_v8(Config) when is_list(Config) ->
select(Config, 8).
-select_v9(doc) ->
- ["Selecting objects of a fixed table."];
-select_v9(suite) ->
- [];
+%% Selecting objects of a fixed table.
select_v9(Config) when is_list(Config) ->
select(Config, 9).
@@ -2230,10 +2115,7 @@ select(Config, Version) ->
check_pps(P0),
ok.
-update_counter(doc) ->
- ["Test update_counter/1."];
-update_counter(suite) ->
- [];
+%% Test update_counter/1.
update_counter(Config) when is_list(Config) ->
T = update_counter,
Fname = filename(select, Config),
@@ -2267,10 +2149,7 @@ update_counter(Config) when is_list(Config) ->
ok.
-badarg(doc) ->
- ["Call some functions with bad arguments."];
-badarg(suite) ->
- [];
+%% Call some functions with bad arguments.
badarg(Config) when is_list(Config) ->
T = badarg,
Fname = filename(select, Config),
@@ -2279,7 +2158,6 @@ badarg(Config) when is_list(Config) ->
Args = [{file,Fname},{keypos,3}],
{ok, _} = dets:open_file(T, [{type,set} | Args]),
- % dets:verbose(),
%% badargs are tested in match, select and fixtable too.
@@ -2402,17 +2280,11 @@ badarg(Config) when is_list(Config) ->
check_pps(P0),
ok.
-cache_sets_v8(doc) ->
- ["Test the write cache for sets."];
-cache_sets_v8(suite) ->
- [];
+%% Test the write cache for sets.
cache_sets_v8(Config) when is_list(Config) ->
cache_sets(Config, 8).
-cache_sets_v9(doc) ->
- ["Test the write cache for sets."];
-cache_sets_v9(suite) ->
- [];
+%% Test the write cache for sets.
cache_sets_v9(Config) when is_list(Config) ->
cache_sets(Config, 9).
@@ -2546,7 +2418,7 @@ cache_sets(Config, DelayedWrite, Extra, Sz, Version) ->
{[],[]} -> ok;
{X,Y} ->
NoBad = length(X) + length(Y),
- test_server:fail({sets,DelayedWrite,Extra,Sz,NoBad})
+ ct:fail({sets,DelayedWrite,Extra,Sz,NoBad})
end;
true ->
ok
@@ -2557,17 +2429,11 @@ cache_sets(Config, DelayedWrite, Extra, Sz, Version) ->
check_pps(P0),
ok.
-cache_bags_v8(doc) ->
- ["Test the write cache for bags."];
-cache_bags_v8(suite) ->
- [];
+%% Test the write cache for bags.
cache_bags_v8(Config) when is_list(Config) ->
cache_bags(Config, 8).
-cache_bags_v9(doc) ->
- ["Test the write cache for bags."];
-cache_bags_v9(suite) ->
- [];
+%% Test the write cache for bags.
cache_bags_v9(Config) when is_list(Config) ->
cache_bags(Config, 9).
@@ -2710,7 +2576,7 @@ cache_bags(Config, DelayedWrite, Extra, Sz, Version) ->
{[],[]} -> ok;
{X,Y} ->
NoBad = length(X) + length(Y),
- test_server:fail({bags,DelayedWrite,Extra,Sz,NoBad})
+ ct:fail({bags,DelayedWrite,Extra,Sz,NoBad})
end;
true ->
ok
@@ -2739,17 +2605,11 @@ cache_bags(Config, DelayedWrite, Extra, Sz, Version) ->
check_pps(P0),
ok.
-cache_duplicate_bags_v8(doc) ->
- ["Test the write cache for duplicate bags."];
-cache_duplicate_bags_v8(suite) ->
- [];
+%% Test the write cache for duplicate bags.
cache_duplicate_bags_v8(Config) when is_list(Config) ->
cache_duplicate_bags(Config, 8).
-cache_duplicate_bags_v9(doc) ->
- ["Test the write cache for duplicate bags."];
-cache_duplicate_bags_v9(suite) ->
- [];
+%% Test the write cache for duplicate bags.
cache_duplicate_bags_v9(Config) when is_list(Config) ->
cache_duplicate_bags(Config, 9).
@@ -2868,7 +2728,7 @@ cache_dup_bags(Config, DelayedWrite, Extra, Sz, Version) ->
{[],[]} -> ok;
{X,Y} ->
NoBad = length(X) + length(Y),
- test_server:fail({dup_bags,DelayedWrite,Extra,Sz,NoBad})
+ ct:fail({dup_bags,DelayedWrite,Extra,Sz,NoBad})
end;
true ->
ok
@@ -2934,10 +2794,7 @@ symdiff(L1, L2) ->
sofs:symmetric_partition(sofs:set(L1), sofs:set(L2)),
{sofs:to_external(X), sofs:to_external(Y)}.
-otp_4208(doc) ->
- ["Read only table and traversal caused crash."];
-otp_4208(suite) ->
- [];
+%% Test read-only tables and traversal caused crashes.
otp_4208(Config) when is_list(Config) ->
Tab = otp_4208,
FName = filename(Tab, Config),
@@ -2956,10 +2813,7 @@ otp_4208(Config) when is_list(Config) ->
ok.
-otp_4989(doc) ->
- ["Read only table and growth."];
-otp_4989(suite) ->
- [];
+%% Test read-only tables and growth.
otp_4989(Config) when is_list(Config) ->
Tab = otp_4989,
FName = filename(Tab, Config),
@@ -2987,10 +2841,7 @@ ets_init(Tab, N) ->
ets:insert(Tab, {N,N}),
ets_init(Tab, N - 1).
-otp_8898(doc) ->
- ["OTP-8898. Truncated Dets file."];
-otp_8898(suite) ->
- [];
+%% OTP-8898. Truncated Dets file.
otp_8898(Config) when is_list(Config) ->
Tab = otp_8898,
FName = filename(Tab, Config),
@@ -3010,10 +2861,7 @@ otp_8898(Config) when is_list(Config) ->
ok.
-otp_8899(doc) ->
- ["OTP-8899. Several clients. Updated Head was ignored."];
-otp_8899(suite) ->
- [];
+%% OTP-8899. Several clients. Updated Head was ignored.
otp_8899(Config) when is_list(Config) ->
Tab = many_clients,
FName = filename(Tab, Config),
@@ -3038,10 +2886,7 @@ otp_8899(Config) when is_list(Config) ->
ok.
-many_clients(doc) ->
- ["Several clients accessing a table simultaneously."];
-many_clients(suite) ->
- [];
+%% Test several clients accessing a table simultaneously.
many_clients(Config) when is_list(Config) ->
Tab = many_clients,
FName = filename(Tab, Config),
@@ -3227,10 +3072,7 @@ eval([{info,Tag,Expected} | L], Tab) ->
eval(Else, _Tab) ->
{error, {bad_request,Else}}.
-otp_4906(doc) ->
- ["More than 128k keys caused crash."];
-otp_4906(suite) ->
- [];
+%% More than 128k keys caused crash.
otp_4906(Config) when is_list(Config) ->
N = 256*512 + 400,
Tab = otp_4906,
@@ -3274,10 +3116,7 @@ ins_small(T, I, N) ->
ok = dets:insert(T, {I}),
ins_small(T, I+1, N).
-otp_5402(doc) ->
- ["Unwritable ramfile caused krasch."];
-otp_5402(suite) ->
- [];
+%% Unwritable ramfile caused crash.
otp_5402(Config) when is_list(Config) ->
Tab = otp_5402,
File = filename:join(["cannot", "write", "this", "file"]),
@@ -3304,10 +3143,7 @@ otp_5402(Config) when is_list(Config) ->
{error,{file_error,_,_}} = dets:close(T),
ok.
-simultaneous_open(doc) ->
- ["Several clients open and close tables simultaneously."];
-simultaneous_open(suite) ->
- [];
+%% Several clients open and close tables simultaneously.
simultaneous_open(Config) ->
Tab = sim_open,
File = filename(Tab, Config),
@@ -3526,10 +3362,7 @@ create_opened_log(File) ->
crash(File, ?CLOSED_PROPERLY_POS+3, ?NOT_PROPERLY_CLOSED),
ok.
-insert_new(doc) ->
- ["OTP-5075. insert_new/2"];
-insert_new(suite) ->
- [];
+%% OTP-5075. insert_new/2
insert_new(Config) ->
Tab = insert_new,
File = filename(Tab, Config),
@@ -3557,10 +3390,7 @@ insert_new(Config) ->
file:delete(File),
ok.
-repair_continuation(doc) ->
- ["OTP-5126. repair_continuation/2"];
-repair_continuation(suite) ->
- [];
+%% OTP-5126. repair_continuation/2
repair_continuation(Config) ->
Tab = repair_continuation_table,
Fname = filename(repair_cont, Config),
@@ -3583,10 +3413,7 @@ repair_continuation(Config) ->
file:delete(Fname),
ok.
-otp_5487(doc) ->
- ["OTP-5487. Growth of read-only table (again)."];
-otp_5487(suite) ->
- [];
+%% OTP-5487. Growth of read-only table (again).
otp_5487(Config) ->
otp_5487(Config, 9),
otp_5487(Config, 8),
@@ -3609,10 +3436,7 @@ otp_5487(Config, Version) ->
ets:delete(Ets),
file:delete(Fname).
-otp_6206(doc) ->
- ["OTP-6206. Badly formed free lists."];
-otp_6206(suite) ->
- [];
+%% OTP-6206. Badly formed free lists.
otp_6206(Config) ->
Tab = otp_6206,
File = filename(Tab, Config),
@@ -3631,10 +3455,7 @@ otp_6206(Config) ->
file:delete(File),
ok.
-otp_6359(doc) ->
- ["OTP-6359. select and match never return the empty list."];
-otp_6359(suite) ->
- [];
+%% OTP-6359. select and match never return the empty list.
otp_6359(Config) ->
Tab = otp_6359,
File = filename(Tab, Config),
@@ -3647,10 +3468,7 @@ otp_6359(Config) ->
file:delete(File),
ok.
-otp_4738(doc) ->
- ["OTP-4738. ==/2 and =:=/2."];
-otp_4738(suite) ->
- [];
+%% OTP-4738. ==/2 and =:=/2.
otp_4738(Config) ->
%% Version 8 has not been corrected.
%% (The constant -12857447 is for version 9 only.)
@@ -3802,10 +3620,7 @@ otp_4738_set(Version, Config) ->
file:delete(File),
ok.
-otp_7146(doc) ->
- ["OTP-7146. Bugfix: missing test when re-hashing."];
-otp_7146(suite) ->
- [];
+%% OTP-7146. Bugfix: missing test when re-hashing.
otp_7146(Config) ->
Tab = otp_7146,
File = filename(Tab, Config),
@@ -3828,10 +3643,7 @@ write_dets(Tab, N, Max) ->
ok = dets:insert(Tab,{ N, {entry,N}}),
write_dets(Tab, N+1, Max).
-otp_8070(doc) ->
- ["OTP-8070. Duplicated objects with insert_new() and duplicate_bag."];
-otp_8070(suite) ->
- [];
+%% OTP-8070. Duplicated objects with insert_new() and duplicate_bag.
otp_8070(Config) when is_list(Config) ->
Tab = otp_8070,
File = filename(Tab, Config),
@@ -3844,10 +3656,7 @@ otp_8070(Config) when is_list(Config) ->
file:delete(File),
ok.
-otp_8856(doc) ->
- ["OTP-8856. insert_new() bug."];
-otp_8856(suite) ->
- [];
+%% OTP-8856. insert_new() bug.
otp_8856(Config) when is_list(Config) ->
Tab = otp_8856,
File = filename(Tab, Config),
@@ -3869,10 +3678,7 @@ otp_8856(Config) when is_list(Config) ->
file:delete(File),
ok.
-otp_8903(doc) ->
- ["OTP-8903. bchunk/match/select bug."];
-otp_8903(suite) ->
- [];
+%% OTP-8903. bchunk/match/select bug.
otp_8903(Config) when is_list(Config) ->
Tab = otp_8903,
File = filename(Tab, Config),
@@ -3892,10 +3698,7 @@ otp_8903(Config) when is_list(Config) ->
file:delete(File),
ok.
-otp_8923(doc) ->
- ["OTP-8923. rehash due to lookup after initialization."];
-otp_8923(suite) ->
- [];
+%% OTP-8923. rehash due to lookup after initialization.
otp_8923(Config) when is_list(Config) ->
Tab = otp_8923,
File = filename(Tab, Config),
@@ -3925,10 +3728,7 @@ otp_8923(Config) when is_list(Config) ->
file:delete(File),
ok.
-otp_9282(doc) ->
- ["OTP-9282. The name of a table can be an arbitrary term"];
-otp_9282(suite) ->
- [];
+%% OTP-9282. The name of a table can be an arbitrary term.
otp_9282(Config) when is_list(Config) ->
some_calls(make_ref(), Config),
some_calls({a,typical,name}, Config),
@@ -3948,10 +3748,7 @@ some_calls(Tab, Config) ->
file:delete(File).
-otp_11245(doc) ->
- ["OTP-11245. Tables remained fixed after traversal"];
-otp_11245(suite) ->
- [];
+%% OTP-11245. Tables remained fixed after traversal.
otp_11245(Config) when is_list(Config) ->
Tab = otp_11245,
File = filename(Tab, Config),
@@ -3970,10 +3767,7 @@ otp_11245(Config) when is_list(Config) ->
file:delete(File),
ok.
-otp_11709(doc) ->
- ["OTP-11709. Bugfixes."];
-otp_11709(suite) ->
- [];
+%% OTP-11709. Bugfixes.
otp_11709(Config) when is_list(Config) ->
Short = <<"foo">>,
Long = <<"a sufficiently long text">>,
@@ -4012,6 +3806,64 @@ otp_11709(Config) when is_list(Config) ->
_ = file:delete(File),
ok.
+%% OTP-13229. open_file() exits with badarg when given binary file name.
+otp_13229(_Config) ->
+ F = <<"binfile.tab">>,
+ try dets:open_file(name, [{file, F}]) of
+ R ->
+ exit({open_succeeded, R})
+ catch
+ error:badarg ->
+ ok
+ end.
+
+%% OTP-13260. Race when opening a table.
+otp_13260(Config) ->
+ [ok] = lists:usort([otp_13260_1(Config) || _ <- lists:seq(1, 3)]),
+ ok.
+
+otp_13260_1(Config) ->
+ Tab = otp_13260,
+ File = filename(Tab, Config),
+ N = 20,
+ P = self(),
+ Pids = [spawn_link(fun() -> counter(P, Tab, File) end) ||
+ _ <- lists:seq(1, N)],
+ Rs = rec(Pids),
+ true = lists:all(fun(R) -> is_integer(R) end, Rs),
+ wait_for_close(Tab).
+
+rec([]) ->
+ [];
+rec([Pid | Pids]) ->
+ receive {Pid, R} ->
+ [R | rec(Pids)]
+ end.
+
+%% One may have to run the test several times to trigger the bug.
+counter(P, Tab, File) ->
+ Key = key,
+ N = case catch dets:update_counter(Tab, Key, 1) of
+ {'EXIT', _} ->
+ {ok, Tab} = dets:open_file(Tab, [{file, File}]),
+ ok = dets:insert(Tab, {Key, 1}),
+ dets:update_counter(Tab, Key, 1);
+ N1 when is_integer(N1) ->
+ N1;
+ DetsBug ->
+ DetsBug
+ end,
+ P ! {self(), N}.
+
+wait_for_close(Tab) ->
+ case dets:info(Tab, owner) of
+ undefined ->
+ ok;
+ _ ->
+ timer:sleep(100),
+ wait_for_close(Tab)
+ end.
+
%%
%% Parts common to several test cases
%%
@@ -4428,7 +4280,7 @@ check_pps({Ports0,Procs0} = P0) ->
show("New port", PortsDiff),
show("Old proc", Procs0 -- Procs1),
show("New proc", ProcsDiff),
- ?t:fail()
+ ct:fail(failed)
end
end
end.
diff --git a/lib/stdlib/test/dict_SUITE.erl b/lib/stdlib/test/dict_SUITE.erl
index 648154ebbe..d315e6f673 100644
--- a/lib/stdlib/test/dict_SUITE.erl
+++ b/lib/stdlib/test/dict_SUITE.erl
@@ -28,11 +28,13 @@
init_per_testcase/2,end_per_testcase/2,
create/1,store/1,iterate/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-import(lists, [foldl/3]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,5}}].
all() ->
[create, store, iterate].
@@ -54,12 +56,9 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_Case, Config) ->
- Dog = ?t:timetrap(?t:minutes(5)),
- [{watchdog,Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
create(Config) when is_list(Config) ->
@@ -108,7 +107,7 @@ iterate_1(M) ->
M(empty, []).
iterate_2(M) ->
- random:seed(1, 2, 42),
+ rand:seed(exsplus, {1,2,42}),
iter_tree(M, 1000).
iter_tree(_M, 0) ->
@@ -117,7 +116,7 @@ iter_tree(M, N) ->
L = [{I, I} || I <- lists:seq(1, N)],
T = M(from_list, L),
L = lists:reverse(iterate_tree(M, T)),
- R = random:uniform(N),
+ R = rand:uniform(N),
KV = lists:reverse(iterate_tree_from(M, R, T)),
KV = [P || P={K,_} <- L, K >= R],
iter_tree(M, N-1).
@@ -156,7 +155,7 @@ test_all(Tester) ->
spawn_tester(M, Tester) ->
Parent = self(),
spawn_link(fun() ->
- random:seed(1, 2, 42),
+ rand:seed(exsplus, {1,2,42}),
S = Tester(M),
Res = {M(size, S),lists:sort(M(to_list, S))},
Parent ! {result,self(),Res}
@@ -194,12 +193,12 @@ rnd_list_1(0, Acc) ->
Acc;
rnd_list_1(N, Acc) ->
Key = atomic_rnd_term(),
- Value = random:uniform(100),
+ Value = rand:uniform(100),
rnd_list_1(N-1, [{Key,Value}|Acc]).
atomic_rnd_term() ->
- case random:uniform(3) of
- 1 -> list_to_atom(integer_to_list($\s+random:uniform(94))++"rnd");
- 2 -> random:uniform();
- 3 -> random:uniform(50)-37
+ case rand:uniform(3) of
+ 1 -> list_to_atom(integer_to_list($\s+rand:uniform(94))++"rnd");
+ 2 -> rand:uniform();
+ 3 -> rand:uniform(50)-37
end.
diff --git a/lib/stdlib/test/digraph_SUITE.erl b/lib/stdlib/test/digraph_SUITE.erl
index 9e007fe17d..8825d3fc15 100644
--- a/lib/stdlib/test/digraph_SUITE.erl
+++ b/lib/stdlib/test/digraph_SUITE.erl
@@ -19,12 +19,12 @@
%%
-module(digraph_SUITE).
-%-define(STANDALONE,1).
+%%-define(STANDALONE,1).
-ifdef(STANDALONE).
-define(line, put(line, ?LINE), ).
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-endif.
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -62,108 +62,100 @@ end_per_group(_GroupName, Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-opts(doc) -> [];
-opts(suite) -> [];
opts(Config) when is_list(Config) ->
%% OTP-5985: the 'public' option has been removed
- ?line {'EXIT',{badarg,_}} = (catch digraph:new([public])),
- ?line {P2,G2} = spawn_graph([private]),
- ?line {'EXIT',{badarg,_}} = (catch digraph:add_vertex(G2, x)),
- ?line kill_graph(P2),
- ?line {P3,G3} = spawn_graph([protected]),
- ?line {'EXIT',{badarg,_}} = (catch digraph:add_vertex(G3, x)),
- ?line kill_graph(P3),
- ?line Template = [{v1,[v2]}, {v2,[v3]}, {v3,[v4]}, {v4,[]}],
- ?line G4 = build_graph([], Template),
- ?line e = digraph:add_edge(G4, e, v4, v1, []),
- ?line digraph:delete(G4),
- ?line G5 = build_graph([cyclic], Template),
- ?line e = digraph:add_edge(G5, e, v4, v1, []),
- ?line digraph:delete(G5),
- ?line G6 = build_graph([acyclic], Template),
- ?line acyclic = info(G6, cyclicity),
- ?line {error, {bad_edge,_}} = digraph:add_edge(G6, v4, v1),
- ?line digraph:delete(G6),
+ {'EXIT',{badarg,_}} = (catch digraph:new([public])),
+ {P2,G2} = spawn_graph([private]),
+ {'EXIT',{badarg,_}} = (catch digraph:add_vertex(G2, x)),
+ kill_graph(P2),
+ {P3,G3} = spawn_graph([protected]),
+ {'EXIT',{badarg,_}} = (catch digraph:add_vertex(G3, x)),
+ kill_graph(P3),
+ Template = [{v1,[v2]}, {v2,[v3]}, {v3,[v4]}, {v4,[]}],
+ G4 = build_graph([], Template),
+ e = digraph:add_edge(G4, e, v4, v1, []),
+ digraph:delete(G4),
+ G5 = build_graph([cyclic], Template),
+ e = digraph:add_edge(G5, e, v4, v1, []),
+ digraph:delete(G5),
+ G6 = build_graph([acyclic], Template),
+ acyclic = info(G6, cyclicity),
+ {error, {bad_edge,_}} = digraph:add_edge(G6, v4, v1),
+ digraph:delete(G6),
ok.
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-degree(doc) -> [];
-degree(suite) -> [];
degree(Config) when is_list(Config) ->
- ?line G = build_graph([], [{x1,[]}, {x2,[x1]}, {x3,[x1,x2]},
- {x4,[x1,x2,x3]}, {x5,[x1,x2,x3,x4]}]),
+ G = build_graph([], [{x1,[]}, {x2,[x1]}, {x3,[x1,x2]},
+ {x4,[x1,x2,x3]}, {x5,[x1,x2,x3,x4]}]),
%% out degree
- ?line 0 = digraph:out_degree(G, x1),
- ?line 1 = digraph:out_degree(G, x2),
- ?line 2 = digraph:out_degree(G, x3),
- ?line 3 = digraph:out_degree(G, x4),
- ?line 4 = digraph:out_degree(G, x5),
+ 0 = digraph:out_degree(G, x1),
+ 1 = digraph:out_degree(G, x2),
+ 2 = digraph:out_degree(G, x3),
+ 3 = digraph:out_degree(G, x4),
+ 4 = digraph:out_degree(G, x5),
%% out neighbours
- ?line [] = check(digraph:out_neighbours(G, x1), []),
- ?line [] = check(digraph:out_neighbours(G, x2), [x1]),
- ?line [] = check(digraph:out_neighbours(G, x3), [x1,x2]),
- ?line [] = check(digraph:out_neighbours(G, x4), [x1,x2,x3]),
- ?line [] = check(digraph:out_neighbours(G, x5), [x1,x2,x3,x4]),
+ [] = check(digraph:out_neighbours(G, x1), []),
+ [] = check(digraph:out_neighbours(G, x2), [x1]),
+ [] = check(digraph:out_neighbours(G, x3), [x1,x2]),
+ [] = check(digraph:out_neighbours(G, x4), [x1,x2,x3]),
+ [] = check(digraph:out_neighbours(G, x5), [x1,x2,x3,x4]),
%% in degree
- ?line 4 = digraph:in_degree(G, x1),
- ?line 3 = digraph:in_degree(G, x2),
- ?line 2 = digraph:in_degree(G, x3),
- ?line 1 = digraph:in_degree(G, x4),
- ?line 0 = digraph:in_degree(G, x5),
+ 4 = digraph:in_degree(G, x1),
+ 3 = digraph:in_degree(G, x2),
+ 2 = digraph:in_degree(G, x3),
+ 1 = digraph:in_degree(G, x4),
+ 0 = digraph:in_degree(G, x5),
%% in neighbours
- ?line [] = check(digraph:in_neighbours(G, x1), [x2,x3,x4,x5]),
- ?line [] = check(digraph:in_neighbours(G, x2), [x3,x4,x5]),
- ?line [] = check(digraph:in_neighbours(G, x3), [x4,x5]),
- ?line [] = check(digraph:in_neighbours(G, x4), [x5]),
- ?line [] = check(digraph:in_neighbours(G, x5), []),
+ [] = check(digraph:in_neighbours(G, x1), [x2,x3,x4,x5]),
+ [] = check(digraph:in_neighbours(G, x2), [x3,x4,x5]),
+ [] = check(digraph:in_neighbours(G, x3), [x4,x5]),
+ [] = check(digraph:in_neighbours(G, x4), [x5]),
+ [] = check(digraph:in_neighbours(G, x5), []),
digraph:delete(G),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-path(doc) -> [];
-path(suite) -> [];
path(Config) when is_list(Config) ->
- ?line G = build_graph([], [{x1,[x2,x3]}, {x2,[x4]}, {x3,[x4]},
- {x4,[x5,x6]}, {x5,[x7]}, {x6,[x7]}]),
- ?line Vi = case digraph:get_path(G, x1, x7) of
- [x1,x2,x4,x5,x7] -> digraph:del_vertex(G, x5), x6;
- [x1,x2,x4,x6,x7] -> digraph:del_vertex(G, x6), x5;
- [x1,x3,x4,x5,x7] -> digraph:del_vertex(G, x5), x6;
- [x1,x3,x4,x6,x7] -> digraph:del_vertex(G, x6), x5
- end,
- ?line Vj = case digraph:get_path(G, x1, x7) of
- [x1,x2,x4,Vi,x7] -> digraph:del_vertex(G,x2), x3;
- [x1,x3,x4,Vi,x7] -> digraph:del_vertex(G,x3), x2
- end,
- ?line [x1,Vj,x4,Vi,x7] = digraph:get_path(G, x1, x7),
- ?line digraph:del_vertex(G, Vj),
- ?line false = digraph:get_path(G, x1, x7),
- ?line [] = check(digraph:vertices(G), [x1,x4,Vi,x7]),
+ G = build_graph([], [{x1,[x2,x3]}, {x2,[x4]}, {x3,[x4]},
+ {x4,[x5,x6]}, {x5,[x7]}, {x6,[x7]}]),
+ Vi = case digraph:get_path(G, x1, x7) of
+ [x1,x2,x4,x5,x7] -> digraph:del_vertex(G, x5), x6;
+ [x1,x2,x4,x6,x7] -> digraph:del_vertex(G, x6), x5;
+ [x1,x3,x4,x5,x7] -> digraph:del_vertex(G, x5), x6;
+ [x1,x3,x4,x6,x7] -> digraph:del_vertex(G, x6), x5
+ end,
+ Vj = case digraph:get_path(G, x1, x7) of
+ [x1,x2,x4,Vi,x7] -> digraph:del_vertex(G,x2), x3;
+ [x1,x3,x4,Vi,x7] -> digraph:del_vertex(G,x3), x2
+ end,
+ [x1,Vj,x4,Vi,x7] = digraph:get_path(G, x1, x7),
+ digraph:del_vertex(G, Vj),
+ false = digraph:get_path(G, x1, x7),
+ [] = check(digraph:vertices(G), [x1,x4,Vi,x7]),
digraph:delete(G),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-cycle(doc) -> [];
-cycle(suite) -> [];
cycle(Config) when is_list(Config) ->
- ?line G = build_graph([], [{x1,[x2,x3]}, {x2,[x4]}, {x3,[x4]},
- {x4,[x5,x6]}, {x5,[x7]}, {x6,[x7,x8]},
- {x8,[x3,x8]}]),
- ?line false = digraph:get_cycle(G, x1),
- ?line false = digraph:get_cycle(G, x2),
- ?line false = digraph:get_cycle(G, x5),
- ?line false = digraph:get_cycle(G, x7),
- ?line [x3,x4,x6,x8,x3] = digraph:get_cycle(G, x3),
- ?line [x4,x6,x8,x3,x4] = digraph:get_cycle(G, x4),
- ?line [x6,x8,x3,x4,x6] = digraph:get_cycle(G, x6),
- ?line [x8,x3,x4,x6,x8] = digraph:get_cycle(G, x8),
- ?line digraph:del_vertex(G, x4),
- ?line [x8] = digraph:get_cycle(G, x8),
+ G = build_graph([], [{x1,[x2,x3]}, {x2,[x4]}, {x3,[x4]},
+ {x4,[x5,x6]}, {x5,[x7]}, {x6,[x7,x8]},
+ {x8,[x3,x8]}]),
+ false = digraph:get_cycle(G, x1),
+ false = digraph:get_cycle(G, x2),
+ false = digraph:get_cycle(G, x5),
+ false = digraph:get_cycle(G, x7),
+ [x3,x4,x6,x8,x3] = digraph:get_cycle(G, x3),
+ [x4,x6,x8,x3,x4] = digraph:get_cycle(G, x4),
+ [x6,x8,x3,x4,x6] = digraph:get_cycle(G, x6),
+ [x8,x3,x4,x6,x8] = digraph:get_cycle(G, x8),
+ digraph:del_vertex(G, x4),
+ [x8] = digraph:get_cycle(G, x8),
digraph:delete(G),
ok.
@@ -171,61 +163,55 @@ cycle(Config) when is_list(Config) ->
-vertices(doc) -> [];
-vertices(suite) -> [];
vertices(Config) when is_list(Config) ->
- ?line G = build_graph([], [{x,[]}, {y,[]}]),
- ?line [] = check(digraph:vertices(G), [x,y]),
- ?line digraph:del_vertices(G, [x,y]),
- ?line [] = digraph:vertices(G),
- ?line digraph:delete(G),
+ G = build_graph([], [{x,[]}, {y,[]}]),
+ [] = check(digraph:vertices(G), [x,y]),
+ digraph:del_vertices(G, [x,y]),
+ [] = digraph:vertices(G),
+ digraph:delete(G),
ok.
-edges(doc) -> [];
-edges(suite) -> [];
edges(Config) when is_list(Config) ->
- ?line G = build_graph([], [{x, [{exy,y},{exx,x}]},
- {y, [{eyx,x}]}
- ]),
- ?line [] = check(digraph:edges(G), [exy, eyx, exx]),
- ?line [] = check(digraph:out_edges(G, x), [exy,exx]),
- ?line [] = check(digraph:in_edges(G, x), [eyx,exx]),
- ?line [] = check(digraph:out_edges(G, y), [eyx]),
- ?line [] = check(digraph:in_edges(G, y), [exy]),
- ?line true = digraph:del_edges(G, [exy, eyx, does_not_exist]),
- ?line [exx] = digraph:edges(G),
- ?line [] = check(digraph:out_edges(G, x), [exx]),
- ?line [] = check(digraph:in_edges(G, x), [exx]),
- ?line [] = check(digraph:out_edges(G, y), []),
- ?line [] = check(digraph:in_edges(G, y), []),
- ?line digraph:del_vertices(G, [x,y]),
- ?line [] = digraph:edges(G),
- ?line [] = digraph:vertices(G),
- ?line digraph:delete(G),
+ G = build_graph([], [{x, [{exy,y},{exx,x}]},
+ {y, [{eyx,x}]}
+ ]),
+ [] = check(digraph:edges(G), [exy, eyx, exx]),
+ [] = check(digraph:out_edges(G, x), [exy,exx]),
+ [] = check(digraph:in_edges(G, x), [eyx,exx]),
+ [] = check(digraph:out_edges(G, y), [eyx]),
+ [] = check(digraph:in_edges(G, y), [exy]),
+ true = digraph:del_edges(G, [exy, eyx, does_not_exist]),
+ [exx] = digraph:edges(G),
+ [] = check(digraph:out_edges(G, x), [exx]),
+ [] = check(digraph:in_edges(G, x), [exx]),
+ [] = check(digraph:out_edges(G, y), []),
+ [] = check(digraph:in_edges(G, y), []),
+ digraph:del_vertices(G, [x,y]),
+ [] = digraph:edges(G),
+ [] = digraph:vertices(G),
+ digraph:delete(G),
ok.
-data(doc) -> [];
-data(suite) -> [];
data(Config) when is_list(Config) ->
- ?line G = build_graph([], [{x, [{exy, y}]}, {y, []}]),
-
- ?line {x,[]} = digraph:vertex(G, x),
- ?line {y,[]} = digraph:vertex(G, y),
- ?line {exy,x,y,[]} = digraph:edge(G, exy),
-
- ?line digraph:add_edge(G, exy, x, y, {data,x,y}),
- ?line E = digraph:add_edge(G, x, y, {data,y,x}),
- ?line digraph:add_vertex(G, x, {any}),
- ?line digraph:add_vertex(G, y, '_'),
-
- ?line {x,{any}} = digraph:vertex(G, x),
- ?line {y,'_'} = digraph:vertex(G, y),
- ?line {exy,x,y,{data,x,y}} = digraph:edge(G, exy),
- ?line {E,x,y,{data,y,x}} = digraph:edge(G, E),
- ?line true = digraph:del_edge(G, E),
- ?line false = digraph:edge(G, E),
- ?line true = sane(G),
- ?line digraph:delete(G),
+ G = build_graph([], [{x, [{exy, y}]}, {y, []}]),
+
+ {x,[]} = digraph:vertex(G, x),
+ {y,[]} = digraph:vertex(G, y),
+ {exy,x,y,[]} = digraph:edge(G, exy),
+
+ digraph:add_edge(G, exy, x, y, {data,x,y}),
+ E = digraph:add_edge(G, x, y, {data,y,x}),
+ digraph:add_vertex(G, x, {any}),
+ digraph:add_vertex(G, y, '_'),
+
+ {x,{any}} = digraph:vertex(G, x),
+ {y,'_'} = digraph:vertex(G, y),
+ {exy,x,y,{data,x,y}} = digraph:edge(G, exy),
+ {E,x,y,{data,y,x}} = digraph:edge(G, E),
+ true = digraph:del_edge(G, E),
+ false = digraph:edge(G, E),
+ true = sane(G),
+ digraph:delete(G),
ok.
@@ -233,87 +219,81 @@ data(Config) when is_list(Config) ->
-otp_3522(doc) -> [];
-otp_3522(suite) -> [];
otp_3522(Config) when is_list(Config) ->
- ?line G1 = build_graph([acyclic], [{x, []}]),
- ?line {error, {bad_edge,_}} = digraph:add_edge(G1, x, x),
- ?line true = digraph:delete(G1),
-
- ?line G = digraph:new(),
- ?line 0 = digraph:no_vertices(G),
- ?line 0 = digraph:no_edges(G),
- ?line V1 = digraph:add_vertex(G),
- ?line '$vid' = digraph:add_vertex(G, '$vid'),
- ?line V2 = digraph:add_vertex(G),
- ?line '$eid' = digraph:add_edge(G, '$eid', V1, V2, []),
- ?line E = digraph:add_edge(G, V1, V2),
- ?line 3 = digraph:no_vertices(G),
- ?line 2 = digraph:no_edges(G),
- ?line cyclic = info(G, cyclicity),
- ?line protected = info(G, protection),
-
- ?line [] = check(digraph:in_edges(G, V2), ['$eid', E]),
- ?line [] = check(digraph:out_edges(G, V1), ['$eid', E]),
- ?line [] = check(digraph:vertices(G), [V1,V2,'$vid']),
- ?line [] = check(digraph:edges(G), [E, '$eid']),
- ?line true = sane(G),
- ?line true = digraph:delete(G),
+ G1 = build_graph([acyclic], [{x, []}]),
+ {error, {bad_edge,_}} = digraph:add_edge(G1, x, x),
+ true = digraph:delete(G1),
+
+ G = digraph:new(),
+ 0 = digraph:no_vertices(G),
+ 0 = digraph:no_edges(G),
+ V1 = digraph:add_vertex(G),
+ '$vid' = digraph:add_vertex(G, '$vid'),
+ V2 = digraph:add_vertex(G),
+ '$eid' = digraph:add_edge(G, '$eid', V1, V2, []),
+ E = digraph:add_edge(G, V1, V2),
+ 3 = digraph:no_vertices(G),
+ 2 = digraph:no_edges(G),
+ cyclic = info(G, cyclicity),
+ protected = info(G, protection),
+
+ [] = check(digraph:in_edges(G, V2), ['$eid', E]),
+ [] = check(digraph:out_edges(G, V1), ['$eid', E]),
+ [] = check(digraph:vertices(G), [V1,V2,'$vid']),
+ [] = check(digraph:edges(G), [E, '$eid']),
+ true = sane(G),
+ true = digraph:delete(G),
ok.
-otp_3630(doc) -> [];
-otp_3630(suite) -> [];
otp_3630(Config) when is_list(Config) ->
- ?line G = build_graph([], [{x, [{exy,y},{exx,x}]},
- {y, [{eyy,y},{eyx,x}]}
- ]),
- ?line [x,y] = digraph:get_path(G, x, y),
- ?line [y,x] = digraph:get_path(G, y, x),
-
- ?line [x,x] = digraph:get_short_path(G, x, x),
- ?line [y,y] = digraph:get_short_path(G, y, y),
- ?line true = digraph:delete(G),
-
- ?line G1 = build_graph([], [{1, [{12,2},{13,3},{11,1}]},
- {2, [{23,3}]},
- {3, [{34,4},{35,5}]},
- {4, [{45,5}]},
- {5, [{56,6},{57,7}]},
- {6, [{67,7}]},
- {7, [{71,1}]}
- ]),
-
- ?line [1,3,5,7] = digraph:get_short_path(G1, 1, 7),
- ?line [3,5,7,1,3] = digraph:get_short_cycle(G1, 3),
- ?line [1,1] = digraph:get_short_cycle(G1, 1),
- ?line true = digraph:delete(G1),
+ G = build_graph([], [{x, [{exy,y},{exx,x}]},
+ {y, [{eyy,y},{eyx,x}]}
+ ]),
+ [x,y] = digraph:get_path(G, x, y),
+ [y,x] = digraph:get_path(G, y, x),
+
+ [x,x] = digraph:get_short_path(G, x, x),
+ [y,y] = digraph:get_short_path(G, y, y),
+ true = digraph:delete(G),
+
+ G1 = build_graph([], [{1, [{12,2},{13,3},{11,1}]},
+ {2, [{23,3}]},
+ {3, [{34,4},{35,5}]},
+ {4, [{45,5}]},
+ {5, [{56,6},{57,7}]},
+ {6, [{67,7}]},
+ {7, [{71,1}]}
+ ]),
+
+ [1,3,5,7] = digraph:get_short_path(G1, 1, 7),
+ [3,5,7,1,3] = digraph:get_short_cycle(G1, 3),
+ [1,1] = digraph:get_short_cycle(G1, 1),
+ true = digraph:delete(G1),
F = 0.0, I = round(F),
- ?line G2 = digraph:new([acyclic]),
- ?line digraph:add_vertex(G2, F),
- ?line digraph:add_vertex(G2, I),
- ?line E = digraph:add_edge(G2, F, I),
- ?line true = not is_tuple(E),
- ?line true = sane(G2),
- ?line true = digraph:delete(G2),
+ G2 = digraph:new([acyclic]),
+ digraph:add_vertex(G2, F),
+ digraph:add_vertex(G2, I),
+ E = digraph:add_edge(G2, F, I),
+ true = not is_tuple(E),
+ true = sane(G2),
+ true = digraph:delete(G2),
ok.
-otp_8066(doc) -> [];
-otp_8066(suite) -> [];
otp_8066(Config) when is_list(Config) ->
fun() ->
D = digraph:new(),
V1 = digraph:add_vertex(D),
V2 = digraph:add_vertex(D),
_ = digraph:add_edge(D, V1, V2),
- ?line [V1, V2] = digraph:get_path(D, V1, V2),
- ?line true = sane(D),
- ?line true = digraph:del_path(D, V1, V2),
- ?line true = sane(D),
- ?line false = digraph:get_path(D, V1, V2),
- ?line true = digraph:del_path(D, V1, V2),
- ?line true = digraph:delete(D)
+ [V1, V2] = digraph:get_path(D, V1, V2),
+ true = sane(D),
+ true = digraph:del_path(D, V1, V2),
+ true = sane(D),
+ false = digraph:get_path(D, V1, V2),
+ true = digraph:del_path(D, V1, V2),
+ true = digraph:delete(D)
end(),
fun() ->
@@ -324,15 +304,15 @@ otp_8066(Config) when is_list(Config) ->
_ = digraph:add_edge(D, V1, V2),
_ = digraph:add_edge(D, V1, V1),
_ = digraph:add_edge(D, V2, V2),
- ?line [V1, V2] = digraph:get_path(D, V1, V2),
- ?line true = sane(D),
- ?line true = digraph:del_path(D, V1, V2),
- ?line false = digraph:get_short_path(D, V2, V1),
-
- ?line true = sane(D),
- ?line false = digraph:get_path(D, V1, V2),
- ?line true = digraph:del_path(D, V1, V2),
- ?line true = digraph:delete(D)
+ [V1, V2] = digraph:get_path(D, V1, V2),
+ true = sane(D),
+ true = digraph:del_path(D, V1, V2),
+ false = digraph:get_short_path(D, V2, V1),
+
+ true = sane(D),
+ false = digraph:get_path(D, V1, V2),
+ true = digraph:del_path(D, V1, V2),
+ true = digraph:delete(D)
end(),
fun() ->
@@ -342,18 +322,18 @@ otp_8066(Config) when is_list(Config) ->
W3 = digraph:add_vertex(G),
W4 = digraph:add_vertex(G),
_ = digraph:add_edge(G,['$e'|0], W1, W2, {}),
- ?line {error,{bad_vertex, bv}} =
+ {error,{bad_vertex, bv}} =
digraph:add_edge(G, edge, bv, W1, {}),
- ?line {error,{bad_vertex, bv}} =
+ {error,{bad_vertex, bv}} =
digraph:add_edge(G, edge, W1, bv, {}),
- ?line false = digraph:get_short_cycle(G, W1),
- ?line {error, {bad_edge,_}} =
+ false = digraph:get_short_cycle(G, W1),
+ {error, {bad_edge,_}} =
digraph:add_edge(G,['$e'|0], W3, W4, {}),
- ?line true = sane(G),
- ?line true = digraph:delete(G)
+ true = sane(G),
+ true = digraph:delete(G)
end(),
ok.
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -422,7 +402,7 @@ sane1(G) ->
end
end, OutEs)
end, Vs),
-
+
InEs = lists:flatmap(fun(V) -> digraph:in_edges(G, V) end, Vs),
OutEs = lists:flatmap(fun(V) -> digraph:out_edges(G, V) end, Vs),
lists:foreach(
@@ -450,7 +430,7 @@ sane1(G) ->
end,
Edges = [digraph:edge(G, E) || E <- Es],
EVs = lists:usort([V || {_, V, _, _} <- Edges] ++
- [V || {_, _, V, _} <- Edges]),
+ [V || {_, _, V, _} <- Edges]),
lists:foreach(
fun(V) ->
case digraph:vertex(G, V) of
diff --git a/lib/stdlib/test/digraph_utils_SUITE.erl b/lib/stdlib/test/digraph_utils_SUITE.erl
index 747ccf322c..23520072f8 100644
--- a/lib/stdlib/test/digraph_utils_SUITE.erl
+++ b/lib/stdlib/test/digraph_utils_SUITE.erl
@@ -19,11 +19,11 @@
%%
-module(digraph_utils_SUITE).
-%-define(debug, true).
+%%-define(debug, true).
-ifdef(debug).
-define(line, put(line, ?LINE), ).
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-endif.
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -59,205 +59,192 @@ end_per_group(_GroupName, Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-simple(doc) -> [];
-simple(suite) -> [];
simple(Config) when is_list(Config) ->
- ?line G = digraph:new(),
- ?line add_vertices(G, [a]),
- ?line add_edges(G, [{b,c},{b,d},{e,f},{f,g},{g,e},{h,h},{i,i},{i,j}]),
- ?line 10 = length(digraph_utils:postorder(G)),
- ?line 10 = length(digraph_utils:preorder(G)),
- ?line ok = evall(digraph_utils:components(G),
- [[a],[b,c,d],[e,f,g],[h],[i,j]]),
- ?line ok = evall(digraph_utils:strong_components(G),
+ G = digraph:new(),
+ add_vertices(G, [a]),
+ add_edges(G, [{b,c},{b,d},{e,f},{f,g},{g,e},{h,h},{i,i},{i,j}]),
+ 10 = length(digraph_utils:postorder(G)),
+ 10 = length(digraph_utils:preorder(G)),
+ ok = evall(digraph_utils:components(G),
+ [[a],[b,c,d],[e,f,g],[h],[i,j]]),
+ ok = evall(digraph_utils:strong_components(G),
[[a],[b],[c],[d],[e,f,g],[h],[i],[j]]),
- ?line ok = evall(digraph_utils:cyclic_strong_components(G),
- [[e,f,g],[h],[i]]),
- ?line true = path(G, e, e),
- ?line false = path(G, e, j),
- ?line false = path(G, a, a),
- ?line false = digraph_utils:topsort(G),
- ?line false = digraph_utils:is_acyclic(G),
- ?line ok = eval(digraph_utils:loop_vertices(G), [h,i]),
- ?line ok = eval(digraph_utils:reaching([e], G), [e,f,g]),
- ?line ok = eval(digraph_utils:reaching_neighbours([e], G), [e,f,g]),
- ?line ok = eval(digraph_utils:reachable([e], G), [e,f,g]),
- ?line ok = eval(digraph_utils:reachable_neighbours([e], G), [e,f,g]),
- ?line ok = eval(digraph_utils:reaching([b], G), [b]),
- ?line ok = eval(digraph_utils:reaching_neighbours([b], G), []),
- ?line ok = eval(digraph_utils:reachable([b], G), [b,c,d]),
- ?line ok = eval(digraph_utils:reachable_neighbours([b], G), [c,d]),
- ?line ok = eval(digraph_utils:reaching([h], G), [h]),
- ?line ok = eval(digraph_utils:reaching_neighbours([h], G), [h]),
- ?line ok = eval(digraph_utils:reachable([h], G), [h]),
- ?line ok = eval(digraph_utils:reachable_neighbours([h], G), [h]),
- ?line ok = eval(digraph_utils:reachable([e,f], G), [e,f,g]),
- ?line ok = eval(digraph_utils:reachable_neighbours([e,f], G), [e,f,g]),
- ?line ok = eval(digraph_utils:reachable([h,h,h], G), [h]),
- ?line true = digraph:delete(G),
+ ok = evall(digraph_utils:cyclic_strong_components(G),
+ [[e,f,g],[h],[i]]),
+ true = path(G, e, e),
+ false = path(G, e, j),
+ false = path(G, a, a),
+ false = digraph_utils:topsort(G),
+ false = digraph_utils:is_acyclic(G),
+ ok = eval(digraph_utils:loop_vertices(G), [h,i]),
+ ok = eval(digraph_utils:reaching([e], G), [e,f,g]),
+ ok = eval(digraph_utils:reaching_neighbours([e], G), [e,f,g]),
+ ok = eval(digraph_utils:reachable([e], G), [e,f,g]),
+ ok = eval(digraph_utils:reachable_neighbours([e], G), [e,f,g]),
+ ok = eval(digraph_utils:reaching([b], G), [b]),
+ ok = eval(digraph_utils:reaching_neighbours([b], G), []),
+ ok = eval(digraph_utils:reachable([b], G), [b,c,d]),
+ ok = eval(digraph_utils:reachable_neighbours([b], G), [c,d]),
+ ok = eval(digraph_utils:reaching([h], G), [h]),
+ ok = eval(digraph_utils:reaching_neighbours([h], G), [h]),
+ ok = eval(digraph_utils:reachable([h], G), [h]),
+ ok = eval(digraph_utils:reachable_neighbours([h], G), [h]),
+ ok = eval(digraph_utils:reachable([e,f], G), [e,f,g]),
+ ok = eval(digraph_utils:reachable_neighbours([e,f], G), [e,f,g]),
+ ok = eval(digraph_utils:reachable([h,h,h], G), [h]),
+ true = digraph:delete(G),
ok.
-loop(doc) -> [];
-loop(suite) -> [];
loop(Config) when is_list(Config) ->
- ?line G = digraph:new(),
- ?line add_vertices(G, [a,b]),
- ?line add_edges(G, [{a,a},{b,b}]),
- ?line ok = evall(digraph_utils:components(G), [[a],[b]]),
- ?line ok = evall(digraph_utils:strong_components(G), [[a],[b]]),
- ?line ok = evall(digraph_utils:cyclic_strong_components(G), [[a],[b]]),
- ?line [_,_] = digraph_utils:topsort(G),
- ?line false = digraph_utils:is_acyclic(G),
- ?line ok = eval(digraph_utils:loop_vertices(G), [a,b]),
- ?line [_,_] = digraph_utils:preorder(G),
- ?line [_,_] = digraph_utils:postorder(G),
- ?line ok = eval(digraph_utils:reaching([b], G), [b]),
- ?line ok = eval(digraph_utils:reaching_neighbours([b], G), [b]),
- ?line ok = eval(digraph_utils:reachable([b], G), [b]),
- ?line ok = eval(digraph_utils:reachable_neighbours([b], G), [b]),
- ?line true = path(G, a, a),
- ?line true = digraph:delete(G),
+ G = digraph:new(),
+ add_vertices(G, [a,b]),
+ add_edges(G, [{a,a},{b,b}]),
+ ok = evall(digraph_utils:components(G), [[a],[b]]),
+ ok = evall(digraph_utils:strong_components(G), [[a],[b]]),
+ ok = evall(digraph_utils:cyclic_strong_components(G), [[a],[b]]),
+ [_,_] = digraph_utils:topsort(G),
+ false = digraph_utils:is_acyclic(G),
+ ok = eval(digraph_utils:loop_vertices(G), [a,b]),
+ [_,_] = digraph_utils:preorder(G),
+ [_,_] = digraph_utils:postorder(G),
+ ok = eval(digraph_utils:reaching([b], G), [b]),
+ ok = eval(digraph_utils:reaching_neighbours([b], G), [b]),
+ ok = eval(digraph_utils:reachable([b], G), [b]),
+ ok = eval(digraph_utils:reachable_neighbours([b], G), [b]),
+ true = path(G, a, a),
+ true = digraph:delete(G),
ok.
-isolated(doc) -> [];
-isolated(suite) -> [];
isolated(Config) when is_list(Config) ->
- ?line G = digraph:new(),
- ?line add_vertices(G, [a,b]),
- ?line ok = evall(digraph_utils:components(G), [[a],[b]]),
- ?line ok = evall(digraph_utils:strong_components(G), [[a],[b]]),
- ?line ok = evall(digraph_utils:cyclic_strong_components(G), []),
- ?line [_,_] = digraph_utils:topsort(G),
- ?line true = digraph_utils:is_acyclic(G),
- ?line ok = eval(digraph_utils:loop_vertices(G), []),
- ?line [_,_] = digraph_utils:preorder(G),
- ?line [_,_] = digraph_utils:postorder(G),
- ?line ok = eval(digraph_utils:reaching([b], G), [b]),
- ?line ok = eval(digraph_utils:reaching_neighbours([b], G), []),
- ?line ok = eval(digraph_utils:reachable([b], G), [b]),
- ?line ok = eval(digraph_utils:reachable_neighbours([b], G), []),
- ?line false = path(G, a, a),
- ?line true = digraph:delete(G),
+ G = digraph:new(),
+ add_vertices(G, [a,b]),
+ ok = evall(digraph_utils:components(G), [[a],[b]]),
+ ok = evall(digraph_utils:strong_components(G), [[a],[b]]),
+ ok = evall(digraph_utils:cyclic_strong_components(G), []),
+ [_,_] = digraph_utils:topsort(G),
+ true = digraph_utils:is_acyclic(G),
+ ok = eval(digraph_utils:loop_vertices(G), []),
+ [_,_] = digraph_utils:preorder(G),
+ [_,_] = digraph_utils:postorder(G),
+ ok = eval(digraph_utils:reaching([b], G), [b]),
+ ok = eval(digraph_utils:reaching_neighbours([b], G), []),
+ ok = eval(digraph_utils:reachable([b], G), [b]),
+ ok = eval(digraph_utils:reachable_neighbours([b], G), []),
+ false = path(G, a, a),
+ true = digraph:delete(G),
ok.
-topsort(doc) -> [];
-topsort(suite) -> [];
topsort(Config) when is_list(Config) ->
- ?line G = digraph:new(),
- ?line add_edges(G, [{a,b},{b,c},{c,d},{d,e},{e,f}]),
- ?line ok = eval(digraph_utils:topsort(G), [a,b,c,d,e,f]),
- ?line true = digraph:delete(G),
+ G = digraph:new(),
+ add_edges(G, [{a,b},{b,c},{c,d},{d,e},{e,f}]),
+ ok = eval(digraph_utils:topsort(G), [a,b,c,d,e,f]),
+ true = digraph:delete(G),
ok.
-subgraph(doc) -> [];
-subgraph(suite) -> [];
subgraph(Config) when is_list(Config) ->
- ?line G = digraph:new([acyclic]),
- ?line add_edges(G, [{b,c},{b,d},{e,f},{f,fg,fgl,g},{f,fg2,fgl2,g},{g,e},
- {h,h},{i,i},{i,j}]),
- ?line add_vertices(G, [{b,bl},{f,fl}]),
- ?line SG = digraph_utils:subgraph(G, [u1,b,c,u2,f,g,i,u3]),
- ?line [b,c,f,g,i] = lists:sort(digraph:vertices(SG)),
- ?line {b,bl} = digraph:vertex(SG, b),
- ?line {c,[]} = digraph:vertex(SG, c),
- ?line {fg,f,g,fgl} = digraph:edge(SG, fg),
- ?line {fg2,f,g,fgl2} = digraph:edge(SG, fg2),
- ?line {_, {_, acyclic}} = lists:keysearch(cyclicity, 1, digraph:info(SG)),
- ?line true = digraph:delete(SG),
-
- ?line SG1 = digraph_utils:subgraph(G, [f, g, h],
- [{type, []}, {keep_labels, false}]),
- ?line [f,g,h] = lists:sort(digraph:vertices(SG1)),
- ?line {f,[]} = digraph:vertex(SG1, f),
- ?line {fg,f,g,[]} = digraph:edge(SG1, fg),
- ?line {_, {_, cyclic}} = lists:keysearch(cyclicity, 1, digraph:info(SG1)),
- ?line true = digraph:delete(SG1),
-
- ?line SG2 = digraph_utils:subgraph(G, [f, g, h],
- [{type, [acyclic]},
- {keep_labels, true}]),
- ?line [f,g,h] = lists:sort(digraph:vertices(SG2)),
- ?line {f,fl} = digraph:vertex(SG2, f),
- ?line {fg,f,g,fgl} = digraph:edge(SG2, fg),
- ?line {_, {_, acyclic}} = lists:keysearch(cyclicity, 1, digraph:info(SG2)),
- ?line true = digraph:delete(SG2),
-
- ?line {'EXIT',{badarg,_}} =
+ G = digraph:new([acyclic]),
+ add_edges(G, [{b,c},{b,d},{e,f},{f,fg,fgl,g},{f,fg2,fgl2,g},{g,e},
+ {h,h},{i,i},{i,j}]),
+ add_vertices(G, [{b,bl},{f,fl}]),
+ SG = digraph_utils:subgraph(G, [u1,b,c,u2,f,g,i,u3]),
+ [b,c,f,g,i] = lists:sort(digraph:vertices(SG)),
+ {b,bl} = digraph:vertex(SG, b),
+ {c,[]} = digraph:vertex(SG, c),
+ {fg,f,g,fgl} = digraph:edge(SG, fg),
+ {fg2,f,g,fgl2} = digraph:edge(SG, fg2),
+ {_, {_, acyclic}} = lists:keysearch(cyclicity, 1, digraph:info(SG)),
+ true = digraph:delete(SG),
+
+ SG1 = digraph_utils:subgraph(G, [f, g, h],
+ [{type, []}, {keep_labels, false}]),
+ [f,g,h] = lists:sort(digraph:vertices(SG1)),
+ {f,[]} = digraph:vertex(SG1, f),
+ {fg,f,g,[]} = digraph:edge(SG1, fg),
+ {_, {_, cyclic}} = lists:keysearch(cyclicity, 1, digraph:info(SG1)),
+ true = digraph:delete(SG1),
+
+ SG2 = digraph_utils:subgraph(G, [f, g, h],
+ [{type, [acyclic]},
+ {keep_labels, true}]),
+ [f,g,h] = lists:sort(digraph:vertices(SG2)),
+ {f,fl} = digraph:vertex(SG2, f),
+ {fg,f,g,fgl} = digraph:edge(SG2, fg),
+ {_, {_, acyclic}} = lists:keysearch(cyclicity, 1, digraph:info(SG2)),
+ true = digraph:delete(SG2),
+
+ {'EXIT',{badarg,_}} =
(catch digraph_utils:subgraph(G, [f], [{invalid, opt}])),
- ?line {'EXIT',{badarg,_}} =
+ {'EXIT',{badarg,_}} =
(catch digraph_utils:subgraph(G, [f], [{keep_labels, not_Bool}])),
- ?line {'EXIT',{badarg,_}} =
+ {'EXIT',{badarg,_}} =
(catch digraph_utils:subgraph(G, [f], [{type, not_type}])),
- ?line {'EXIT',{badarg,_}} =
+ {'EXIT',{badarg,_}} =
(catch digraph_utils:subgraph(G, [f], [{type, [not_type]}])),
- ?line {'EXIT',{badarg,_}} =
+ {'EXIT',{badarg,_}} =
(catch digraph_utils:subgraph(G, [f], not_a_list)),
- ?line true = digraph:delete(G),
+ true = digraph:delete(G),
ok.
-condensation(doc) -> [];
-condensation(suite) -> [];
condensation(Config) when is_list(Config) ->
- ?line G = digraph:new([]),
- ?line add_edges(G, [{b,c},{b,d},{e,f},{f,fg,fgl,g},{f,fg2,fgl2,g},{g,e},
- {h,h},{j,i},{i,j}]),
- ?line add_vertices(G, [q]),
- ?line CG = digraph_utils:condensation(G),
- ?line Vs = sort_2(digraph:vertices(CG)),
- ?line [[b],[c],[d],[e,f,g],[h],[i,j],[q]] = Vs,
- ?line Fun = fun(E) ->
- {_E, V1, V2, _L} = digraph:edge(CG, E),
- {lists:sort(V1), lists:sort(V2)}
- end,
- ?line Es = lists:map(Fun, digraph:edges(CG)),
- ?line [{[b],[c]},{[b],[d]}] = lists:sort(Es),
- ?line true = digraph:delete(CG),
- ?line true = digraph:delete(G),
+ G = digraph:new([]),
+ add_edges(G, [{b,c},{b,d},{e,f},{f,fg,fgl,g},{f,fg2,fgl2,g},{g,e},
+ {h,h},{j,i},{i,j}]),
+ add_vertices(G, [q]),
+ CG = digraph_utils:condensation(G),
+ Vs = sort_2(digraph:vertices(CG)),
+ [[b],[c],[d],[e,f,g],[h],[i,j],[q]] = Vs,
+ Fun = fun(E) ->
+ {_E, V1, V2, _L} = digraph:edge(CG, E),
+ {lists:sort(V1), lists:sort(V2)}
+ end,
+ Es = lists:map(Fun, digraph:edges(CG)),
+ [{[b],[c]},{[b],[d]}] = lists:sort(Es),
+ true = digraph:delete(CG),
+ true = digraph:delete(G),
ok.
-tree(doc) -> ["OTP-7081"];
-tree(suite) -> [];
+%% OTP-7081
tree(Config) when is_list(Config) ->
- ?line false = is_tree([], []),
- ?line true = is_tree([a], []),
- ?line false = is_tree([a,b], []),
- ?line true = is_tree([{a,b}]),
- ?line false = is_tree([{a,b},{b,a}]),
- ?line true = is_tree([{a,b},{a,c},{b,d},{b,e}]),
- ?line false = is_tree([{a,b},{a,c},{b,d},{b,e}, {d,e}]),
- ?line false = is_tree([{a,b},{a,c},{b,d},{b,e}, {b,e}]),
- ?line true = is_tree([{a,c},{c,b}]),
- ?line true = is_tree([{b,a},{c,a}]),
+ false = is_tree([], []),
+ true = is_tree([a], []),
+ false = is_tree([a,b], []),
+ true = is_tree([{a,b}]),
+ false = is_tree([{a,b},{b,a}]),
+ true = is_tree([{a,b},{a,c},{b,d},{b,e}]),
+ false = is_tree([{a,b},{a,c},{b,d},{b,e}, {d,e}]),
+ false = is_tree([{a,b},{a,c},{b,d},{b,e}, {b,e}]),
+ true = is_tree([{a,c},{c,b}]),
+ true = is_tree([{b,a},{c,a}]),
%% Parallel edges. Acyclic and with one componets
%% (according to the digraph module).
- ?line false = is_tree([{a,b},{a,b}]),
-
- ?line no = arborescence_root([], []),
- ?line {yes, a} = arborescence_root([a], []),
- ?line no = arborescence_root([a,b], []),
- ?line {yes, a} = arborescence_root([{a,b}]),
- ?line no = arborescence_root([{a,b},{b,a}]),
- ?line {yes, a} = arborescence_root([{a,b},{a,c},{b,d},{b,e}]),
- ?line no = arborescence_root([{a,b},{a,c},{b,d},{b,e}, {d,e}]),
- ?line no = arborescence_root([{a,b},{a,c},{b,d},{b,e}, {b,e}]),
- ?line {yes, a} = arborescence_root([{a,c},{c,b}]),
- ?line no = arborescence_root([{b,a},{c,a}]),
-
- ?line false = is_arborescence([], []),
- ?line true = is_arborescence([a], []),
- ?line false = is_arborescence([a,b], []),
- ?line true = is_arborescence([{a,b}]),
- ?line false = is_arborescence([{a,b},{b,a}]),
- ?line true = is_arborescence([{a,b},{a,c},{b,d},{b,e}]),
- ?line false = is_arborescence([{a,b},{a,c},{b,d},{b,e}, {d,e}]),
- ?line false = is_arborescence([{a,b},{a,c},{b,d},{b,e}, {b,e}]),
- ?line true = is_arborescence([{a,c},{c,b}]),
- ?line false = is_arborescence([{b,a},{c,a}]),
+ false = is_tree([{a,b},{a,b}]),
+
+ no = arborescence_root([], []),
+ {yes, a} = arborescence_root([a], []),
+ no = arborescence_root([a,b], []),
+ {yes, a} = arborescence_root([{a,b}]),
+ no = arborescence_root([{a,b},{b,a}]),
+ {yes, a} = arborescence_root([{a,b},{a,c},{b,d},{b,e}]),
+ no = arborescence_root([{a,b},{a,c},{b,d},{b,e}, {d,e}]),
+ no = arborescence_root([{a,b},{a,c},{b,d},{b,e}, {b,e}]),
+ {yes, a} = arborescence_root([{a,c},{c,b}]),
+ no = arborescence_root([{b,a},{c,a}]),
+
+ false = is_arborescence([], []),
+ true = is_arborescence([a], []),
+ false = is_arborescence([a,b], []),
+ true = is_arborescence([{a,b}]),
+ false = is_arborescence([{a,b},{b,a}]),
+ true = is_arborescence([{a,b},{a,c},{b,d},{b,e}]),
+ false = is_arborescence([{a,b},{a,c},{b,d},{b,e}, {d,e}]),
+ false = is_arborescence([{a,b},{a,c},{b,d},{b,e}, {b,e}]),
+ true = is_arborescence([{a,c},{c,b}]),
+ false = is_arborescence([{b,a},{c,a}]),
%% Parallel edges.
- ?line false = is_arborescence([{a,b},{a,b}]),
+ false = is_arborescence([{a,b},{a,b}]),
ok.
@@ -325,7 +312,7 @@ eval(L, E) ->
evall(L, E) ->
F = fun(L1) -> lists:sort(L1) end,
Fun = fun(LL) -> F(lists:map(F, LL)) end,
-
+
Expected = Fun(E),
Got = Fun(L),
if
diff --git a/lib/stdlib/test/dummy1_h.erl b/lib/stdlib/test/dummy1_h.erl
index 5db23872c4..cdf9a305e1 100644
--- a/lib/stdlib/test/dummy1_h.erl
+++ b/lib/stdlib/test/dummy1_h.erl
@@ -37,7 +37,7 @@ handle_event(delete_event, _Parent) ->
remove_handler;
handle_event(do_crash, _State) ->
erlang:error({badmatch,4});
-%Inverse of dummy_h
+%%Inverse of dummy_h
handle_event(hibernate, Parent) ->
{ok,Parent};
handle_event(wakeup, Parent) ->
diff --git a/lib/stdlib/test/dummy_via.erl b/lib/stdlib/test/dummy_via.erl
index e405811cbe..026b329688 100644
--- a/lib/stdlib/test/dummy_via.erl
+++ b/lib/stdlib/test/dummy_via.erl
@@ -50,8 +50,10 @@ call(Req) ->
{'DOWN', MRef, _, _, _} ->
erlang:error(badarg);
{MRef, badarg} ->
+ erlang:demonitor(MRef),
erlang:error(badarg);
{MRef, Reply} ->
+ erlang:demonitor(MRef),
Reply
after 5000 ->
erlang:error(timeout)
diff --git a/lib/stdlib/test/edlin_expand_SUITE.erl b/lib/stdlib/test/edlin_expand_SUITE.erl
index 6fdc4c35df..a53c5333d8 100644
--- a/lib/stdlib/test/edlin_expand_SUITE.erl
+++ b/lib/stdlib/test/edlin_expand_SUITE.erl
@@ -19,26 +19,21 @@
%%
-module(edlin_expand_SUITE).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2,
init_per_group/2,end_per_group/2]).
-
-export([normal/1, quoted_fun/1, quoted_module/1, quoted_both/1]).
--export([init_per_testcase/2, end_per_testcase/2]).
-
--include_lib("test_server/include/test_server.hrl").
-
-%% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
+-include_lib("common_test/include/ct.hrl").
init_per_testcase(_Case, Config) ->
- Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+ Config.
+
+end_per_testcase(_Case, _Config) ->
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[normal, quoted_fun, quoted_module, quoted_both].
@@ -63,10 +58,6 @@ end_per_group(_GroupName, Config) ->
Config.
-normal(doc) ->
- [""];
-normal(suite) ->
- [];
normal(Config) when is_list(Config) ->
{module,expand_test} = c:l(expand_test),
%% These tests might fail if another module with the prefix
@@ -85,10 +76,7 @@ normal(Config) when is_list(Config) ->
{yes,"arity_entirely()",[]} = do_expand("expand_test:expand0"),
ok.
-quoted_fun(doc) ->
- ["Normal module name, some function names using quoted atoms"];
-quoted_fun(suite) ->
- [];
+%% Normal module name, some function names using quoted atoms.
quoted_fun(Config) when is_list(Config) ->
{module,expand_test} = c:l(expand_test),
{module,expand_test1} = c:l(expand_test1),
@@ -121,10 +109,6 @@ quoted_fun(Config) when is_list(Config) ->
{yes,"(",[]} = do_expand("expand_test:module_info"),
ok.
-quoted_module(doc) ->
- [""];
-quoted_module(suite) ->
- [];
quoted_module(Config) when is_list(Config) ->
{module,'ExpandTestCaps'} = c:l('ExpandTestCaps'),
{yes, "Caps':", []} = do_expand("'ExpandTest"),
@@ -138,8 +122,6 @@ quoted_module(Config) when is_list(Config) ->
{"a_less_fun_name",1}]} = do_expand("'ExpandTestCaps':a_"),
ok.
-quoted_both(suite) ->
- [];
quoted_both(Config) when is_list(Config) ->
{module,'ExpandTestCaps'} = c:l('ExpandTestCaps'),
{module,'ExpandTestCaps1'} = c:l('ExpandTestCaps1'),
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index 4e5df661b3..3e1aaef378 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -25,16 +25,16 @@
upcase_mac_1/1, upcase_mac_2/1,
variable_1/1, otp_4870/1, otp_4871/1, otp_5362/1,
pmod/1, not_circular/1, skip_header/1, otp_6277/1, otp_7702/1,
- otp_8130/1, overload_mac/1, otp_8388/1, otp_8470/1, otp_8503/1,
+ otp_8130/1, overload_mac/1, otp_8388/1, otp_8470/1,
otp_8562/1, otp_8665/1, otp_8911/1, otp_10302/1, otp_10820/1,
- otp_11728/1, encoding/1]).
+ otp_11728/1, encoding/1, extends/1, function_macro/1]).
-export([epp_parse_erl_form/2]).
%%
%% Define to run outside of test server
%%
-%-define(STANDALONE,1).
+%%-define(STANDALONE,1).
-ifdef(STANDALONE).
-compile(export_all).
@@ -47,30 +47,27 @@ config(priv_dir, _) ->
config(data_dir, _) ->
filename:absname("./epp_SUITE_data").
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([init_per_testcase/2, end_per_testcase/2]).
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
-
init_per_testcase(_, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
-end_per_testcase(_, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+ Config.
+
+end_per_testcase(_, _Config) ->
ok.
-endif.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[rec_1, {group, upcase_mac}, include_local, predef_mac,
{group, variable}, otp_4870, otp_4871, otp_5362, pmod,
not_circular, skip_header, otp_6277, otp_7702, otp_8130,
- overload_mac, otp_8388, otp_8470, otp_8503, otp_8562,
+ overload_mac, otp_8388, otp_8470, otp_8562,
otp_8665, otp_8911, otp_10302, otp_10820, otp_11728,
- encoding].
+ encoding, extends, function_macro].
groups() ->
[{upcase_mac, [], [upcase_mac_1, upcase_mac_2]},
@@ -88,33 +85,26 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-rec_1(doc) ->
- ["Recursive macros hang or crash epp (OTP-1398)."];
-rec_1(suite) ->
- [];
+%% Recursive macros hang or crash epp (OTP-1398).
rec_1(Config) when is_list(Config) ->
- ?line File = filename:join(?config(data_dir, Config), "mac.erl"),
- ?line {ok, List} = epp_parse_file(File, [], []),
+ File = filename:join(proplists:get_value(data_dir, Config), "mac.erl"),
+ {ok, List} = epp_parse_file(File, [], []),
%% we should encounter errors
- ?line {value, _} = lists:keysearch(error, 1, List),
- ?line check_errors(List),
+ {value, _} = lists:keysearch(error, 1, List),
+ check_errors(List),
ok.
-include_local(doc) ->
- [];
-include_local(suite) ->
- [];
include_local(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line File = filename:join(DataDir, "include_local.erl"),
+ DataDir = proplists:get_value(data_dir, Config),
+ File = filename:join(DataDir, "include_local.erl"),
FooHrl = filename:join([DataDir,"include","foo.hrl"]),
BarHrl = filename:join([DataDir,"include","bar.hrl"]),
%% include_local.erl includes include/foo.hrl which
%% includes bar.hrl (also in include/) without requiring
%% any additional include path, and overriding any file
%% of the same name that the path points to
- ?line {ok, List} = epp:parse_file(File, [DataDir], []),
- ?line {value, {attribute,_,a,{true,true}}} =
+ {ok, List} = epp:parse_file(File, [DataDir], []),
+ {value, {attribute,_,a,{true,true}}} =
lists:keysearch(a,3,List),
[{File,1},{FooHrl,1},{BarHrl,1},{FooHrl,5},{File,5}] =
[ FileLine || {attribute,_,file,FileLine} <- List ],
@@ -170,108 +160,86 @@ epp_parse_erl_form(Epp, Parent) ->
check_errors([]) ->
ok;
check_errors([{error, Info} | Rest]) ->
- ?line {Line, Mod, Desc} = Info,
- ?line case Line of
- I when is_integer(I) -> ok;
- {L,C} when is_integer(L), is_integer(C), C >= 1 -> ok
- end,
- ?line Str = lists:flatten(Mod:format_error(Desc)),
- ?line [Str] = io_lib:format("~s", [Str]),
+ {Line, Mod, Desc} = Info,
+ case Line of
+ I when is_integer(I) -> ok;
+ {L,C} when is_integer(L), is_integer(C), C >= 1 -> ok
+ end,
+ Str = lists:flatten(Mod:format_error(Desc)),
+ [Str] = io_lib:format("~s", [Str]),
check_errors(Rest);
check_errors([_ | Rest]) ->
check_errors(Rest).
-upcase_mac_1(doc) ->
- [];
-upcase_mac_1(suite) ->
- [];
upcase_mac_1(Config) when is_list(Config) ->
- ?line File = filename:join(?config(data_dir, Config), "mac2.erl"),
- ?line {ok, List} = epp:parse_file(File, [], []),
- ?line [_, {attribute, _, plupp, Tuple} | _] = List,
- ?line Tuple = {1, 1, 3, 3},
+ File = filename:join(proplists:get_value(data_dir, Config), "mac2.erl"),
+ {ok, List} = epp:parse_file(File, [], []),
+ [_, {attribute, _, plupp, Tuple} | _] = List,
+ Tuple = {1, 1, 3, 3},
ok.
-upcase_mac_2(doc) ->
- [];
-upcase_mac_2(suite) ->
- [];
upcase_mac_2(Config) when is_list(Config) ->
- ?line File = filename:join(?config(data_dir, Config), "mac2.erl"),
- ?line {ok, List} = epp:parse_file(File, [], [{p, 5}, {'P', 6}]),
- ?line [_, {attribute, _, plupp, Tuple} | _] = List,
- ?line Tuple = {5, 5, 6, 6},
+ File = filename:join(proplists:get_value(data_dir, Config), "mac2.erl"),
+ {ok, List} = epp:parse_file(File, [], [{p, 5}, {'P', 6}]),
+ [_, {attribute, _, plupp, Tuple} | _] = List,
+ Tuple = {5, 5, 6, 6},
ok.
-predef_mac(doc) ->
- [];
-predef_mac(suite) ->
- [];
predef_mac(Config) when is_list(Config) ->
- ?line File = filename:join(?config(data_dir, Config), "mac3.erl"),
- ?line {ok, List} = epp:parse_file(File, [], []),
- ?line [_,
- {attribute, Anno, l, Line1},
- {attribute, _, f, File},
- {attribute, _, machine1, _},
- {attribute, _, module, mac3},
- {attribute, _, m, mac3},
- {attribute, _, ms, "mac3"},
- {attribute, _, machine2, _}
- | _] = List,
+ File = filename:join(proplists:get_value(data_dir, Config), "mac3.erl"),
+ {ok, List} = epp:parse_file(File, [], []),
+ [_,
+ {attribute, Anno, l, Line1},
+ {attribute, _, f, File},
+ {attribute, _, machine1, _},
+ {attribute, _, module, mac3},
+ {attribute, _, m, mac3},
+ {attribute, _, ms, "mac3"},
+ {attribute, _, machine2, _}
+ | _] = List,
Line1 = erl_anno:line(Anno),
ok.
-variable_1(doc) ->
- [];
-variable_1(suite) ->
- [];
variable_1(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line File = filename:join(DataDir, "variable_1.erl"),
- ?line true = os:putenv("VAR", DataDir),
+ DataDir = proplists:get_value(data_dir, Config),
+ File = filename:join(DataDir, "variable_1.erl"),
+ true = os:putenv("VAR", DataDir),
%% variable_1.erl includes variable_1_include.hrl and
%% variable_1_include_dir.hrl.
- ?line {ok, List} = epp:parse_file(File, [], []),
- ?line {value, {attribute,_,a,{value1,value2}}} =
+ {ok, List} = epp:parse_file(File, [], []),
+ {value, {attribute,_,a,{value1,value2}}} =
lists:keysearch(a,3,List),
ok.
-otp_4870(doc) ->
- ["undef without module declaration"];
-otp_4870(suite) ->
- [];
+%% undef without module declaration.
otp_4870(Config) when is_list(Config) ->
Ts = [{otp_4870,
<<"-undef(foo).
">>,
[]}],
- ?line [] = check(Config, Ts),
+ [] = check(Config, Ts),
ok.
-otp_4871(doc) ->
- ["crashing erl_scan"];
-otp_4871(suite) ->
- [];
+%% crashing erl_scan
otp_4871(Config) when is_list(Config) ->
- ?line Dir = ?config(priv_dir, Config),
- ?line File = filename:join(Dir, "otp_4871.erl"),
- ?line ok = file:write_file(File, "-module(otp_4871)."),
+ Dir = proplists:get_value(priv_dir, Config),
+ File = filename:join(Dir, "otp_4871.erl"),
+ ok = file:write_file(File, "-module(otp_4871)."),
%% Testing crash in erl_scan. Unfortunately there currently is
%% no known way to crash erl_scan so it is emulated by killing the
%% file io server. This assumes lots of things about how
%% the processes are started and how monitors are set up,
%% so there are some sanity checks before killing.
- ?line {ok,Epp} = epp:open(File, []),
+ {ok,Epp} = epp:open(File, []),
timer:sleep(1),
- ?line true = current_module(Epp, epp),
- ?line {monitored_by,[Io]} = process_info(Epp, monitored_by),
- ?line true = current_module(Io, file_io_server),
- ?line exit(Io, emulate_crash),
+ true = current_module(Epp, epp),
+ {monitored_by,[Io]} = process_info(Epp, monitored_by),
+ true = current_module(Io, file_io_server),
+ exit(Io, emulate_crash),
timer:sleep(1),
- ?line {error,{_Line,epp,cannot_parse}} = otp_4871_parse_file(Epp),
- ?line epp:close(Epp),
+ {error,{_Line,epp,cannot_parse}} = otp_4871_parse_file(Epp),
+ epp:close(Epp),
ok.
current_module(Pid, Mod) ->
@@ -288,12 +256,9 @@ otp_4871_parse_file(Epp) ->
Other -> Other
end.
-otp_5362(doc) ->
- ["OTP-5362. The -file attribute is recognized."];
-otp_5362(suite) ->
- [];
+%% OTP-5362. The -file attribute is recognized.
otp_5362(Config) when is_list(Config) ->
- Dir = ?config(priv_dir, Config),
+ Dir = proplists:get_value(priv_dir, Config),
Copts = [return, strong_validation,{i,Dir}],
@@ -317,12 +282,12 @@ otp_5362(Config) when is_list(Config) ->
Incl3 = <<"glurk(Foo) -> % line 1
bar.
">>,
- ?line ok = file:write_file(File_Incl, Incl),
- ?line ok = file:write_file(File_Incl2, Incl2),
- ?line ok = file:write_file(File_Incl3, Incl3),
+ ok = file:write_file(File_Incl, Incl),
+ ok = file:write_file(File_Incl2, Incl2),
+ ok = file:write_file(File_Incl3, Incl3),
- ?line {ok, incl_5362, InclWarnings} = compile:file(File_Incl, Copts),
- ?line true = message_compare(
+ {ok, incl_5362, InclWarnings} = compile:file(File_Incl, Copts),
+ true = message_compare(
[{File_Incl3,[{{1,1},erl_lint,{unused_function,{glurk,1}}},
{{1,7},erl_lint,{unused_var,'Foo'}}]},
{File_Incl,[{{7,15},erl_lint,{unused_function,{hi,1}}},
@@ -352,11 +317,11 @@ otp_5362(Config) when is_list(Config) ->
-file(\"">>,File_Back,<<"\", 2).
">>],
- ?line ok = file:write_file(File_Back, Back),
- ?line ok = file:write_file(File_Back_hrl, list_to_binary(Back_hrl)),
+ ok = file:write_file(File_Back, Back),
+ ok = file:write_file(File_Back_hrl, list_to_binary(Back_hrl)),
- ?line {ok, back_5362, BackWarnings} = compile:file(File_Back, Copts),
- ?line true = message_compare(
+ {ok, back_5362, BackWarnings} = compile:file(File_Back, Copts),
+ true = message_compare(
[{File_Back,[{{4,19},erl_lint,{unused_var,'V'}}]}],
BackWarnings),
file:delete(File_Back),
@@ -380,11 +345,11 @@ otp_5362(Config) when is_list(Config) ->
foo.
">>],
- ?line ok = file:write_file(File_Change, list_to_binary(Change)),
+ ok = file:write_file(File_Change, list_to_binary(Change)),
- ?line {ok, change_5362, ChangeWarnings} =
+ {ok, change_5362, ChangeWarnings} =
compile:file(File_Change, Copts),
- ?line true = message_compare(
+ true = message_compare(
[{File_Change,[{{1002,21},erl_lint,{unused_var,'B'}}]},
{"other.file",[{{105,21},erl_lint,{unused_var,'A'}}]}],
lists:usort(ChangeWarnings)),
@@ -412,9 +377,9 @@ otp_5362(Config) when is_list(Config) ->
-file(?FILE, ?LINE). c(C) -> % line 47
3.
">>,
- ?line ok = file:write_file(File_Blank, Blank),
- ?line {ok, blank_5362, BlankWarnings} = compile:file(File_Blank, Copts),
- ?line true = message_compare(
+ ok = file:write_file(File_Blank, Blank),
+ {ok, blank_5362, BlankWarnings} = compile:file(File_Blank, Copts),
+ true = message_compare(
[{File_Blank,[{{18,3},erl_lint,{unused_var,'Q'}},
{{20,18},erl_lint,{unused_var,'A'}},
{{44,18},erl_lint,{unused_var,'B'}},
@@ -438,16 +403,16 @@ otp_5362(Config) when is_list(Config) ->
FILE1 = <<"ii() -> ?FILE.
">>,
FILE_Mod = file_5362,
- ?line ok = file:write_file(FILE_incl, FILE),
- ?line ok = file:write_file(FILE_incl1, FILE1),
+ ok = file:write_file(FILE_incl, FILE),
+ ok = file:write_file(FILE_incl1, FILE1),
FILE_Copts = [return, {i,Dir},{outdir,Dir}],
- ?line {ok, file_5362, []} = compile:file(FILE_incl, FILE_Copts),
+ {ok, file_5362, []} = compile:file(FILE_incl, FILE_Copts),
AbsFile = filename:rootname(FILE_incl, ".erl"),
- ?line {module, FILE_Mod} = code:load_abs(AbsFile, FILE_Mod),
- ?line II = FILE_Mod:ii(),
- ?line "file_incl_5362.erl" = filename:basename(II),
- ?line FF = FILE_Mod:ff(),
- ?line "other_file" = filename:basename(FF),
+ {module, FILE_Mod} = code:load_abs(AbsFile, FILE_Mod),
+ II = FILE_Mod:ii(),
+ "file_incl_5362.erl" = filename:basename(II),
+ FF = FILE_Mod:ff(),
+ "other_file" = filename:basename(FF),
code:purge(file_5362),
file:delete(FILE_incl),
@@ -456,12 +421,12 @@ otp_5362(Config) when is_list(Config) ->
ok.
pmod(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line Pmod = filename:join(DataDir, "pmod.erl"),
- ?line case epp:parse_file([Pmod], [], []) of
+ DataDir = proplists:get_value(data_dir, Config),
+ Pmod = filename:join(DataDir, "pmod.erl"),
+ case epp:parse_file([Pmod], [], []) of
{ok,Forms} ->
- %% ?line io:format("~p\n", [Forms]),
- ?line [] = [F || {error,_}=F <- Forms],
+ %% io:format("~p\n", [Forms]),
+ [] = [F || {error,_}=F <- Forms],
ok
end,
ok.
@@ -474,17 +439,14 @@ not_circular(Config) when is_list(Config) ->
<<"-define(S(S), ??S).\n"
"t() -> \"string\" = ?S(string), ok.\n">>,
ok}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-skip_header(doc) ->
- ["Skip some bytes in the beginning of the file."];
-skip_header(suite) ->
- [];
+%% Skip some bytes in the beginning of the file.
skip_header(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line File = filename:join([PrivDir, "epp_test_skip_header.erl"]),
- ?line ok = file:write_file(File,
+ PrivDir = proplists:get_value(priv_dir, Config),
+ File = filename:join([PrivDir, "epp_test_skip_header.erl"]),
+ ok = file:write_file(File,
<<"some bytes
in the beginning of the file
that should be skipped
@@ -494,23 +456,20 @@ skip_header(Config) when is_list(Config) ->
main(_) -> ?MODULE.
">>),
- ?line {ok, Fd} = file:open(File, [read]),
- ?line io:get_line(Fd, ''),
- ?line io:get_line(Fd, ''),
- ?line io:get_line(Fd, ''),
- ?line {ok, Epp} = epp:open(list_to_atom(File), Fd, 4, [], []),
-
- ?line Forms = epp:parse_file(Epp),
- ?line [] = [Reason || {error, Reason} <- Forms],
- ?line ok = epp:close(Epp),
- ?line ok = file:close(Fd),
+ {ok, Fd} = file:open(File, [read]),
+ io:get_line(Fd, ''),
+ io:get_line(Fd, ''),
+ io:get_line(Fd, ''),
+ {ok, Epp} = epp:open(list_to_atom(File), Fd, 4, [], []),
+
+ Forms = epp:parse_file(Epp),
+ [] = [Reason || {error, Reason} <- Forms],
+ ok = epp:close(Epp),
+ ok = file:close(Fd),
ok.
-otp_6277(doc) ->
- ["?MODULE before module declaration."];
-otp_6277(suite) ->
- [];
+%% ?MODULE before module declaration.
otp_6277(Config) when is_list(Config) ->
Ts = [{otp_6277,
<<"-undef(ASSERT).
@@ -518,15 +477,12 @@ otp_6277(Config) when is_list(Config) ->
?ASSERT().">>,
[{error,{{4,16},epp,{undefined,'MODULE', none}}}]}],
- ?line [] = check(Config, Ts),
+ [] = check(Config, Ts),
ok.
-otp_7702(doc) ->
- ["OTP-7702. Wrong line number in stringifying macro expansion."];
-otp_7702(suite) ->
- [];
+%% OTP-7702. Wrong line number in stringifying macro expansion.
otp_7702(Config) when is_list(Config) ->
- Dir = ?config(priv_dir, Config),
+ Dir = proplists:get_value(priv_dir, Config),
File = filename:join(Dir, "file_7702.erl"),
Contents = <<"-module(file_7702).
@@ -542,8 +498,8 @@ otp_7702(Config) when is_list(Config) ->
end).
t() ->
?RECEIVE(foo, bar).">>,
- ?line ok = file:write_file(File, Contents),
- ?line {ok, file_7702, []} =
+ ok = file:write_file(File, Contents),
+ {ok, file_7702, []} =
compile:file(File, [debug_info,return,{outdir,Dir}]),
BeamFile = filename:join(Dir, "file_7702.beam"),
@@ -551,8 +507,7 @@ otp_7702(Config) when is_list(Config) ->
{file_7702,[{abstract_code,{_,Forms}}]} = AC,
Forms2 = unopaque_forms(Forms),
- ?line
- [{attribute,1,file,_},
+ [{attribute,1,file,_},
_,
_,
{function,_,t,0,
@@ -586,10 +541,7 @@ otp_7702(Config) when is_list(Config) ->
ok.
-otp_8130(doc) ->
- ["OTP-8130. Misc tests."];
-otp_8130(suite) ->
- [];
+%% OTP-8130. Misc tests.
otp_8130(Config) when is_list(Config) ->
true = os:putenv("epp_inc1", "stdlib"),
Ts = [{otp_8130_1,
@@ -621,6 +573,10 @@ otp_8130(Config) when is_list(Config) ->
" 2 end,\n"
" 7),\n"
" {2,7} =\n"
+ " ?M1(begin 1 = fun _Name () -> 1 end(),\n"
+ " 2 end,\n"
+ " 7),\n"
+ " {2,7} =\n"
" ?M1(begin 1 = fun t0/0(),\n"
" 2 end,\n"
" 7),\n"
@@ -645,6 +601,9 @@ otp_8130(Config) when is_list(Config) ->
" ?M1(begin yes = try 1 of 1 -> yes after foo end,\n"
" 2 end,\n"
" 7),\n"
+ " {[42],7} =\n"
+ " ?M1([42],\n"
+ " 7),\n"
"ok.\n">>,
ok},
@@ -682,7 +641,7 @@ otp_8130(Config) when is_list(Config) ->
{1,1}}
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
Cs = [{otp_8130_c1,
<<"-define(M1(A), if\n"
@@ -728,11 +687,16 @@ otp_8130(Config) when is_list(Config) ->
{errors,[{{2,2},epp,{include,lib,"$apa/foo.hrl"}}],[]}},
- {otp_8130_c9,
+ {otp_8130_c9a,
<<"-define(S, ?S).\n"
"t() -> ?S.\n">>,
{errors,[{{2,9},epp,{circular,'S', none}}],[]}},
+ {otp_8130_c9b,
+ <<"-define(S(), ?S()).\n"
+ "t() -> ?S().\n">>,
+ {errors,[{{2,9},epp,{circular,'S', 0}}],[]}},
+
{otp_8130_c10,
<<"\n-file.">>,
{errors,[{{2,2},epp,{bad,file}}],[]}},
@@ -799,6 +763,10 @@ otp_8130(Config) when is_list(Config) ->
<<"\n-include(\"no such file.erl\").\n">>,
{errors,[{{2,2},epp,{include,file,"no such file.erl"}}],[]}},
+ {otp_8130_c25,
+ <<"\n-define(A.\n">>,
+ {errors,[{{2,2},epp,{bad,define}}],[]}},
+
{otp_8130_7,
<<"-record(b, {b}).\n"
"-define(A, {{a,#b.b.\n"
@@ -807,7 +775,7 @@ otp_8130(Config) when is_list(Config) ->
{{3,19},epp,{undefined,'A',none}}],[]}}
],
- ?line [] = compile(Config, Cs),
+ [] = compile(Config, Cs),
Cks = [{otp_check_1,
<<"\n-include_lib(\"epp_test.erl\").\n">>,
@@ -817,24 +785,25 @@ otp_8130(Config) when is_list(Config) ->
<<"\n-include(\"epp_test.erl\").\n">>,
[{error,{{2,2},epp,{depth,"include"}}}]}
],
- ?line [] = check(Config, Cks),
+ [] = check(Config, Cks),
- ?line Dir = ?config(priv_dir, Config),
- ?line File = filename:join(Dir, "otp_8130.erl"),
- ?line ok = file:write_file(File,
+ Dir = proplists:get_value(priv_dir, Config),
+ File = filename:join(Dir, "otp_8130.erl"),
+ ok = file:write_file(File,
"-module(otp_8130).\n"
"-define(a, 3.14).\n"
"t() -> ?a.\n"),
- ?line {ok,Epp} = epp:open(File, []),
- ?line ['BASE_MODULE','BASE_MODULE_STRING','BEAM','FILE','LINE',
- 'MACHINE','MODULE','MODULE_STRING'] = macs(Epp),
- ?line {ok,[{'-',_},{atom,_,file}|_]} = epp:scan_erl_form(Epp),
- ?line {ok,[{'-',_},{atom,_,module}|_]} = epp:scan_erl_form(Epp),
- ?line {ok,[{atom,_,t}|_]} = epp:scan_erl_form(Epp),
- ?line {eof,_} = epp:scan_erl_form(Epp),
- ?line ['BASE_MODULE','BASE_MODULE_STRING','BEAM','FILE','LINE',
- 'MACHINE','MODULE','MODULE_STRING',a] = macs(Epp),
- ?line epp:close(Epp),
+ {ok,Epp} = epp:open(File, []),
+ PreDefMacs = macs(Epp),
+ ['BASE_MODULE','BASE_MODULE_STRING','BEAM','FILE',
+ 'FUNCTION_ARITY','FUNCTION_NAME',
+ 'LINE','MACHINE','MODULE','MODULE_STRING'] = PreDefMacs,
+ {ok,[{'-',_},{atom,_,file}|_]} = epp:scan_erl_form(Epp),
+ {ok,[{'-',_},{atom,_,module}|_]} = epp:scan_erl_form(Epp),
+ {ok,[{atom,_,t}|_]} = epp:scan_erl_form(Epp),
+ {eof,_} = epp:scan_erl_form(Epp),
+ [a] = macs(Epp) -- PreDefMacs,
+ epp:close(Epp),
%% escript
ModuleStr = "any_name",
@@ -843,27 +812,27 @@ otp_8130(Config) when is_list(Config) ->
PreDefMacros = [{'MODULE', Module, redefine},
{'MODULE_STRING', ModuleStr, redefine},
a, {b,2}],
- ?line {ok,Epp2} = epp:open(File, [], PreDefMacros),
- ?line [{atom,_,true}] = macro(Epp2, a),
- ?line [{integer,_,2}] = macro(Epp2, b),
- ?line false = macro(Epp2, c),
- ?line epp:close(Epp2)
+ {ok,Epp2} = epp:open(File, [], PreDefMacros),
+ [{atom,_,true}] = macro(Epp2, a),
+ [{integer,_,2}] = macro(Epp2, b),
+ false = macro(Epp2, c),
+ epp:close(Epp2)
end(),
fun() ->
PreDefMacros = [{a,b,c}],
- ?line {error,{bad,{a,b,c}}} = epp:open(File, [], PreDefMacros)
+ {error,{bad,{a,b,c}}} = epp:open(File, [], PreDefMacros)
end(),
fun() ->
PreDefMacros = [a, {a,1}],
- ?line {error,{redefine,a}} = epp:open(File, [], PreDefMacros)
+ {error,{redefine,a}} = epp:open(File, [], PreDefMacros)
end(),
fun() ->
PreDefMacros = [{a,1},a],
- ?line {error,{redefine,a}} = epp:open(File, [], PreDefMacros)
+ {error,{redefine,a}} = epp:open(File, [], PreDefMacros)
end(),
- ?line {error,enoent} = epp:open("no such file", []),
- ?line {error,enoent} = epp:parse_file("no such file", [], []),
+ {error,enoent} = epp:open("no such file", []),
+ {error,enoent} = epp:parse_file("no such file", [], []),
_ = ifdef(Config),
@@ -1003,7 +972,7 @@ ifdef(Config) ->
"t() -> a.\n">>,
{errors,[{{2,2},epp,{'NYI','if'}}],[]}}
],
- ?line [] = compile(Config, Cs),
+ [] = compile(Config, Cs),
Ts = [{ifdef_1,
<<"-ifdef(a).\n"
@@ -1084,14 +1053,11 @@ ifdef(Config) ->
ok}
],
- ?line [] = run(Config, Ts).
+ [] = run(Config, Ts).
-overload_mac(doc) ->
- ["Advanced test on overloading macros."];
-overload_mac(suite) ->
- [];
+%% Advanced test on overloading macros.
overload_mac(Config) when is_list(Config) ->
Cs = [
%% '-undef' removes all definitions of a macro
@@ -1122,7 +1088,7 @@ overload_mac(Config) when is_list(Config) ->
"t() -> ?A(1).">>,
{errors,[{{4,9},epp,{mismatch,'A'}}],[]}}
],
- ?line [] = compile(Config, Cs),
+ [] = compile(Config, Cs),
Ts = [
{overload_mac_r1,
@@ -1146,27 +1112,24 @@ overload_mac(Config) when is_list(Config) ->
"t() -> ?A(1).">>,
1}
],
- ?line [] = run(Config, Ts).
+ [] = run(Config, Ts).
-otp_8388(doc) ->
- ["OTP-8388. More tests on overloaded macros."];
-otp_8388(suite) ->
- [];
+%% OTP-8388. More tests on overloaded macros.
otp_8388(Config) when is_list(Config) ->
- Dir = ?config(priv_dir, Config),
- ?line File = filename:join(Dir, "otp_8388.erl"),
- ?line ok = file:write_file(File, <<"-module(otp_8388)."
+ Dir = proplists:get_value(priv_dir, Config),
+ File = filename:join(Dir, "otp_8388.erl"),
+ ok = file:write_file(File, <<"-module(otp_8388)."
"-define(LINE, a).">>),
fun() ->
PreDefMacros = [{'LINE', a}],
- ?line {error,{redefine_predef,'LINE'}} =
+ {error,{redefine_predef,'LINE'}} =
epp:open(File, [], PreDefMacros)
end(),
fun() ->
PreDefMacros = ['LINE'],
- ?line {error,{redefine_predef,'LINE'}} =
+ {error,{redefine_predef,'LINE'}} =
epp:open(File, [], PreDefMacros)
end(),
@@ -1196,43 +1159,22 @@ otp_8388(Config) when is_list(Config) ->
"test() -> ?BAR(1).\n">>,
{errors,[{{4,12},epp,{undefined,'FOO',1}}],[]}}
],
- ?line [] = compile(Config, Ts),
+ [] = compile(Config, Ts),
ok.
-otp_8470(doc) ->
- ["OTP-8470. Bugfix (one request - two replies)."];
-otp_8470(suite) ->
- [];
+%% OTP-8470. Bugfix (one request - two replies).
otp_8470(Config) when is_list(Config) ->
- Dir = ?config(priv_dir, Config),
+ Dir = proplists:get_value(priv_dir, Config),
C = <<"-file(\"erl_parse.yrl\", 486).\n"
"-file(\"erl_parse.yrl\", 488).\n">>,
- ?line File = filename:join(Dir, "otp_8470.erl"),
- ?line ok = file:write_file(File, C),
- ?line {ok, _List} = epp:parse_file(File, [], []),
- file:delete(File),
- ?line receive _ -> fail() after 0 -> ok end,
- ok.
-
-otp_8503(doc) ->
- ["OTP-8503. Record with no fields is considered typed."];
-otp_8503(suite) ->
- [];
-otp_8503(Config) when is_list(Config) ->
- Dir = ?config(priv_dir, Config),
- C = <<"-record(r, {}).">>,
- ?line File = filename:join(Dir, "otp_8503.erl"),
- ?line ok = file:write_file(File, C),
- ?line {ok, List} = epp:parse_file(File, [], []),
- ?line [_] = [F || {attribute,_,type,{{record,r},[],[]}}=F <- List],
+ File = filename:join(Dir, "otp_8470.erl"),
+ ok = file:write_file(File, C),
+ {ok, _List} = epp:parse_file(File, [], []),
file:delete(File),
- ?line receive _ -> fail() after 0 -> ok end,
+ receive _ -> fail() after 0 -> ok end,
ok.
-otp_8562(doc) ->
- ["OTP-8503. Record with no fields is considered typed."];
-otp_8562(suite) ->
- [];
+%% OTP-8562. Record with no fields is considered typed.
otp_8562(Config) when is_list(Config) ->
Cs = [{otp_8562,
<<"-define(P(), {a,b}.\n"
@@ -1240,13 +1182,10 @@ otp_8562(Config) when is_list(Config) ->
{errors,[{{1,60},epp,missing_parenthesis},
{{2,13},epp,missing_parenthesis}], []}}
],
- ?line [] = compile(Config, Cs),
+ [] = compile(Config, Cs),
ok.
-otp_8911(doc) ->
- ["OTP-8911. -file and file inclusion bug"];
-otp_8911(suite) ->
- [];
+%% OTP-8911. -file and file inclusion bug.
otp_8911(Config) when is_list(Config) ->
case test_server:is_cover() of
true ->
@@ -1255,8 +1194,8 @@ otp_8911(Config) when is_list(Config) ->
do_otp_8911(Config)
end.
do_otp_8911(Config) ->
- ?line {ok, CWD} = file:get_cwd(),
- ?line ok = file:set_cwd(?config(priv_dir, Config)),
+ {ok, CWD} = file:get_cwd(),
+ ok = file:set_cwd(proplists:get_value(priv_dir, Config)),
File = "i.erl",
Cont = <<"-module(i).
@@ -1266,40 +1205,34 @@ do_otp_8911(Config) ->
t() ->
a.
">>,
- ?line ok = file:write_file(File, Cont),
+ ok = file:write_file(File, Cont),
Incl = <<"-file(\"fil2\", 35).
t1() ->
b.
">>,
File1 = "i1.erl",
- ?line ok = file:write_file(File1, Incl),
+ ok = file:write_file(File1, Incl),
- ?line {ok, i} = cover:compile(File),
- ?line a = i:t(),
- ?line {ok,[{{i,6},1}]} = cover:analyse(i, calls, line),
- ?line cover:stop(),
+ {ok, i} = cover:compile(File),
+ a = i:t(),
+ {ok,[{{i,6},1}]} = cover:analyse(i, calls, line),
+ cover:stop(),
file:delete(File),
file:delete(File1),
- ?line file:set_cwd(CWD),
+ file:set_cwd(CWD),
ok.
-otp_8665(doc) ->
- ["OTP-8665. Bugfix premature end."];
-otp_8665(suite) ->
- [];
+%% OTP-8665. Bugfix premature end.
otp_8665(Config) when is_list(Config) ->
Cs = [{otp_8562,
<<"-define(A, a)\n">>,
{errors,[{{1,54},epp,premature_end}],[]}}
],
- ?line [] = compile(Config, Cs),
+ [] = compile(Config, Cs),
ok.
-otp_10302(doc) ->
- "OTP-10302. Unicode characters scanner/parser.";
-otp_10302(suite) ->
- [];
+%% OTP-10302. Unicode characters scanner/parser.
otp_10302(Config) when is_list(Config) ->
%% Two messages (one too many). Keeps otp_4871 happy.
Cs = [{otp_8562,
@@ -1308,7 +1241,7 @@ otp_10302(Config) when is_list(Config) ->
{3,file_io_server,invalid_unicode}],[]}}
],
[] = compile(Config, Cs),
- Dir = ?config(priv_dir, Config),
+ Dir = proplists:get_value(priv_dir, Config),
File = filename:join(Dir, "otp_10302.erl"),
utf8 = encoding("coding: utf-8", File),
utf8 = encoding("coding: UTF-8", File),
@@ -1370,13 +1303,10 @@ encoding_nocom(Enc, File) ->
ok = file:close(Fd),
E = epp:read_encoding(File, Options).
-otp_10820(doc) ->
- "OTP-10820. Unicode filenames.";
-otp_10820(suite) ->
- [];
+%% OTP-10820. Unicode filenames.
otp_10820(Config) when is_list(Config) ->
L = [915,953,959,973,957,953,954,959,957,964],
- Dir = ?config(priv_dir, Config),
+ Dir = proplists:get_value(priv_dir, Config),
File = filename:join(Dir, L++".erl"),
C1 = <<"%% coding: utf-8\n -module(any).">>,
ok = do_otp_10820(File, C1, "+pc latin1"),
@@ -1395,12 +1325,9 @@ do_otp_10820(File, C, PC) ->
true = test_server:stop_node(Node),
ok.
-otp_11728(doc) ->
- ["OTP-11728. Bugfix circular macro."];
-otp_11728(suite) ->
- [];
+%% OTP-11728. Bugfix circular macro.
otp_11728(Config) when is_list(Config) ->
- Dir = ?config(priv_dir, Config),
+ Dir = proplists:get_value(priv_dir, Config),
H = <<"-define(MACRO,[[]++?MACRO]).">>,
HrlFile = filename:join(Dir, "otp_11728.hrl"),
ok = file:write_file(HrlFile, H),
@@ -1422,7 +1349,7 @@ otp_11728(Config) when is_list(Config) ->
%% Check the new API for setting the default encoding.
encoding(Config) when is_list(Config) ->
- Dir = ?config(priv_dir, Config),
+ Dir = proplists:get_value(priv_dir, Config),
ErlFile = filename:join(Dir, "encoding.erl"),
%% Try a latin-1 file with no encoding given.
@@ -1476,6 +1403,102 @@ encoding(Config) when is_list(Config) ->
epp_parse_file(ErlFile, [{default_encoding,utf8},extra]),
ok.
+extends(Config) ->
+ Cs = [{extends_c1,
+ <<"-extends(some.other.module).\n">>,
+ {errors,[{1,erl_parse,["syntax error before: ","'.'"]}],[]}}],
+ [] = compile(Config, Cs),
+
+ Ts = [{extends_1,
+ <<"-extends(some_other_module).\n"
+ "t() -> {?BASE_MODULE,?BASE_MODULE_STRING}.\n">>,
+ {some_other_module,"some_other_module"}}],
+
+ [] = run(Config, Ts),
+ ok.
+
+function_macro(Config) ->
+ Cs = [{f_c1,
+ <<"-define(FUNCTION_NAME, a).\n"
+ "-define(FUNCTION_ARITY, a).\n"
+ "-define(FS,\n"
+ " atom_to_list(?FUNCTION_NAME) ++ \"/\" ++\n"
+ " integer_to_list(?FUNCTION_ARITY)).\n"
+ "-attr({f,?FUNCTION_NAME}).\n"
+ "-attr2(?FS).\n"
+ "-file(?FUNCTION_ARITY, 1).\n"
+ "f1() ?FUNCTION_NAME/?FUNCTION_ARITY.\n"
+ "f2(?FUNCTION_NAME.\n">>,
+ {errors,[{1,epp,{redefine_predef,'FUNCTION_NAME'}},
+ {2,epp,{redefine_predef,'FUNCTION_ARITY'}},
+ {6,epp,{illegal_function,'FUNCTION_NAME'}},
+ {7,epp,{illegal_function,'FUNCTION_NAME'}},
+ {8,epp,{illegal_function,'FUNCTION_ARITY'}},
+ {9,erl_parse,["syntax error before: ","f1"]},
+ {10,erl_parse,["syntax error before: ","'.'"]}],
+ []}},
+
+ {f_c2,
+ <<"a({a) -> ?FUNCTION_NAME.\n"
+ "b(}{) -> ?FUNCTION_ARITY.\n"
+ "c(?FUNCTION_NAME, ?not_defined) -> ok.\n">>,
+ {errors,[{1,erl_parse,["syntax error before: ","')'"]},
+ {2,erl_parse,["syntax error before: ","'}'"]},
+ {3,epp,{undefined,not_defined,none}}],
+ []}},
+
+ {f_c3,
+ <<"?FUNCTION_NAME() -> ok.\n"
+ "?FUNCTION_ARITY() -> ok.\n">>,
+ {errors,[{1,epp,{illegal_function_usage,'FUNCTION_NAME'}},
+ {2,epp,{illegal_function_usage,'FUNCTION_ARITY'}}],
+ []}}
+ ],
+
+ [] = compile(Config, Cs),
+
+ Ts = [{f_1,
+ <<"t() -> {a,0} = a(), {b,1} = b(1), {c,2} = c(1, 2),\n"
+ " {d,1} = d({d,1}), {foo,1} = foo(foo), ok.\n"
+ "a() -> {?FUNCTION_NAME,?FUNCTION_ARITY}.\n"
+ "b(_) -> {?FUNCTION_NAME,?FUNCTION_ARITY}.\n"
+ "c(_, (_)) -> {?FUNCTION_NAME,?FUNCTION_ARITY}.\n"
+ "d({?FUNCTION_NAME,?FUNCTION_ARITY}=F) -> F.\n"
+ "-define(FOO, foo).\n"
+ "?FOO(?FOO) -> {?FUNCTION_NAME,?FUNCTION_ARITY}.\n">>,
+ ok},
+
+ {f_2,
+ <<"t() ->\n"
+ " A = {a,[<<0:24>>,#{a=>1,b=>2}]},\n"
+ " 1 = a(A),\n"
+ " ok.\n"
+ "a({a,[<<_,_,_>>,#{a:=1,b:=2}]}) -> ?FUNCTION_ARITY.\n">>,
+ ok},
+
+ {f_3,
+ <<"-define(FS,\n"
+ " atom_to_list(?FUNCTION_NAME) ++ \"/\" ++\n"
+ " integer_to_list(?FUNCTION_ARITY)).\n"
+ "t() ->\n"
+ " {t,0} = {?FUNCTION_NAME,?FUNCTION_ARITY},\n"
+ " \"t/0\" = ?FS,\n"
+ " ok.\n">>,
+ ok},
+
+ {f_4,
+ <<"-define(__, _, _).\n"
+ "-define(FF, ?FUNCTION_NAME, ?FUNCTION_ARITY).\n"
+ "a(?__) -> 2 = ?FUNCTION_ARITY.\n"
+ "b(?FUNCTION_ARITY, ?__) -> ok.\n"
+ "c(?FF) -> ok.\n"
+ "t() -> a(1, 2), b(3, 1, 2), c(c, 2), ok.\n">>,
+ ok}
+ ],
+ [] = run(Config, Ts),
+
+ ok.
+
check(Config, Tests) ->
eval_tests(Config, fun check_test/2, Tests).
@@ -1494,7 +1517,7 @@ eval_tests(Config, Fun, Tests) ->
true ->
BadL;
false ->
- ?t:format("~nTest ~p failed. Expected~n ~p~n"
+ io:format("~nTest ~p failed. Expected~n ~p~n"
"but got~n ~p~n", [N, E, Return]),
fail()
end
@@ -1504,22 +1527,24 @@ eval_tests(Config, Fun, Tests) ->
check_test(Config, Test) ->
Filename = "epp_test.erl",
- ?line PrivDir = ?config(priv_dir, Config),
- ?line File = filename:join(PrivDir, Filename),
- ?line ok = file:write_file(File, Test),
- ?line case epp:parse_file(File, [PrivDir], []) of
- {ok,Forms} ->
- [E || E={error,_} <- Forms];
- {error,Error} ->
- Error
- end.
+ PrivDir = proplists:get_value(priv_dir, Config),
+ File = filename:join(PrivDir, Filename),
+ ok = file:write_file(File, Test),
+ case epp:parse_file(File, [PrivDir], []) of
+ {ok,Forms} ->
+ Errors = [E || E={error,_} <- Forms],
+ call_format_error([E || {error,E} <- Errors]),
+ Errors;
+ {error,Error} ->
+ Error
+ end.
compile_test(Config, Test0) ->
Test = [<<"-module(epp_test). -compile(export_all). ">>, Test0],
Filename = "epp_test.erl",
- ?line PrivDir = ?config(priv_dir, Config),
- ?line File = filename:join(PrivDir, Filename),
- ?line ok = file:write_file(File, Test),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ File = filename:join(PrivDir, Filename),
+ ok = file:write_file(File, Test),
Opts = [export_all,return,nowarn_unused_record,{outdir,PrivDir}],
case compile_file(File, Opts) of
{ok, Ws} -> warnings(File, Ws);
@@ -1528,8 +1553,11 @@ compile_test(Config, Test0) ->
warnings(File, Ws) ->
case lists:append([W || {F, W} <- Ws, F =:= File]) of
- [] -> [];
- L -> {warnings, L}
+ [] ->
+ [];
+ L ->
+ call_format_error(L),
+ {warnings, L}
end.
compile_file(File, Opts) ->
@@ -1540,12 +1568,20 @@ compile_file(File, Opts) ->
end.
errs([{File,Es}|L], File) ->
+ call_format_error(Es),
Es ++ errs(L, File);
errs([_|L], File) ->
errs(L, File);
errs([], _File) ->
[].
+%% Smoke test and coverage of format_error/1.
+call_format_error([{_,M,E}|T]) ->
+ _ = M:format_error(E),
+ call_format_error(T);
+call_format_error([]) ->
+ ok.
+
epp_parse_file(File, Opts) ->
case epp:parse_file(File, Opts) of
{ok, Forms} ->
@@ -1560,20 +1596,19 @@ unopaque_forms(Forms) ->
run_test(Config, Test0) ->
Test = [<<"-module(epp_test). -compile(export_all). ">>, Test0],
Filename = "epp_test.erl",
- ?line PrivDir = ?config(priv_dir, Config),
- ?line File = filename:join(PrivDir, Filename),
- ?line ok = file:write_file(File, Test),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ File = filename:join(PrivDir, Filename),
+ ok = file:write_file(File, Test),
Opts = [return, {i,PrivDir},{outdir,PrivDir}],
- ?line {ok, epp_test, []} = compile:file(File, Opts),
+ {ok, epp_test, []} = compile:file(File, Opts),
AbsFile = filename:rootname(File, ".erl"),
- ?line {module, epp_test} = code:load_abs(AbsFile, epp_test),
- ?line Reply = epp_test:t(),
+ {module, epp_test} = code:load_abs(AbsFile, epp_test),
+ Reply = epp_test:t(),
code:purge(epp_test),
Reply.
fail() ->
- io:format("failed~n"),
- test_server:fail().
+ ct:fail(failed).
message_compare(T, T) ->
true;
@@ -1607,5 +1642,5 @@ ln2(M) ->
%% +fnu means a peer node has to be started; slave will not do
start_node(Name, Xargs) ->
- ?line PA = filename:dirname(code:which(?MODULE)),
+ PA = filename:dirname(code:which(?MODULE)),
test_server:start_node(Name, peer, [{args, "-pa " ++ PA ++ " " ++ Xargs}]).
diff --git a/lib/stdlib/test/erl_anno_SUITE.erl b/lib/stdlib/test/erl_anno_SUITE.erl
index 66b02151a0..637a390c70 100644
--- a/lib/stdlib/test/erl_anno_SUITE.erl
+++ b/lib/stdlib/test/erl_anno_SUITE.erl
@@ -19,13 +19,13 @@
%%
-module(erl_anno_SUITE).
-%-define(debug, true).
+%%-define(debug, true).
-ifdef(debug).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(format(S, A), io:format(S, A)).
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(format(S, A), ok).
-endif.
@@ -34,7 +34,7 @@
init_per_testcase/2, end_per_testcase/2]).
-export([new/1, is_anno/1, generated/1, end_location/1, file/1,
- line/1, location/1, record/1, text/1, bad/1, neg_line/1]).
+ line/1, location/1, record/1, text/1, bad/1]).
-export([parse_abstract/1, mapfold_anno/1]).
@@ -43,10 +43,12 @@ all() ->
groups() ->
[{anno, [], [new, is_anno, generated, end_location, file,
- line, location, record, text, bad, neg_line]},
+ line, location, record, text, bad]},
{parse, [], [parse_abstract, mapfold_anno]}].
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
init_per_suite(Config) ->
Config.
@@ -61,26 +63,21 @@ end_per_group(_GroupName, Config) ->
Config.
init_per_testcase(_Case, Config) ->
- Dog=?t:timetrap(?t:minutes(1)),
- [{watchdog, Dog}|Config].
+ Config.
end_per_testcase(_Case, _Config) ->
- Dog=?config(watchdog, _Config),
- test_server:timetrap_cancel(Dog),
ok.
-define(INFO(T, V), {T, V}).
-dialyzer({no_fail_call, new/1}).
-new(doc) ->
- ["Test erl_anno:new/1"];
+%% Test erl_anno:new/1.
new(_Config) ->
{'EXIT', {badarg, _}} =
(catch erl_anno:new([{location,1},{text, "text"}])), % badarg
ok.
-is_anno(doc) ->
- ["Test erl_anno:is_anno/1"];
+%% Test erl_anno:is_anno/1.
is_anno(_Config) ->
false = erl_anno:is_anno(a),
false = erl_anno:is_anno({a}),
@@ -106,8 +103,7 @@ is_anno(_Config) ->
true = erl_anno:is_anno(A5),
ok.
-generated(doc) ->
- ["Test 'generated'"];
+%% Test 'generated'.
generated(_Config) ->
test(1, [{generated, true}, {generated, false}]),
test(1, [{generated, false}, {generated, true}, {generated, false}]),
@@ -127,8 +123,7 @@ generated(_Config) ->
{generated, false}]),
ok.
-end_location(doc) ->
- ["Test 'end_location'"];
+%% Test 'end_location'.
end_location(_Config) ->
test({1, 17}, [{text, "TEXT", [{end_location, {1, 21}}, {length, 4}]},
{text, "TEXT\n", [{end_location, {2, 1}}, {length, 5}]},
@@ -138,23 +133,20 @@ end_location(_Config) ->
{text, "TEXT\ntxt", [{end_location, 2}, {length, 8}]}]),
ok.
-file(doc) ->
- ["Test 'file'"];
+%% Test 'file'.
file(_Config) ->
test(1, [{file, "name"}, {file, ""}]),
test({1, 17}, [{file, "name"}, {file, ""}]),
ok.
-line(doc) ->
- ["Test 'line'"];
+%% Test 'line'.
line(_Config) ->
test(1, [{line, 17, [{location, 17}]},
{location, {9, 8}, [{line, 9}, {column, 8}]},
{line, 14, [{location, {14, 8}}]}]),
ok.
-location(doc) ->
- ["Test 'location'"];
+%% Test 'location'.
location(_Config) ->
test(1, [{location, 2, [{line,2}]},
{location, {1, 17}, [{line, 1}, {column, 17}]},
@@ -172,8 +164,7 @@ location(_Config) ->
{location, 9, [{column, undefined}]}]),
ok.
-record(doc) ->
- ["Test 'record'"];
+%% Test 'record'.
record(_Config) ->
test({1, 17}, [{record, true}, {record, false}]),
test(1, [{record, true}, {record, false}]),
@@ -193,8 +184,7 @@ record(_Config) ->
{generated, false}]),
ok.
-text(doc) ->
- ["Test 'text'"];
+%% Test 'text'.
text(_Config) ->
test(1, [{text, "text", [{end_location, 1}, {length, 4}]},
{text, "", [{end_location, 1}, {length, 0}]}]),
@@ -203,8 +193,7 @@ text(_Config) ->
ok.
-dialyzer({[no_opaque, no_fail_call], bad/1}).
-bad(doc) ->
- ["Test bad annotations"];
+%% Test bad annotations.
bad(_Config) ->
Line = erl_anno:new(1),
LineColumn = erl_anno:new({1, 17}),
@@ -229,77 +218,8 @@ bad(_Config) ->
(catch erl_anno:record(bad)), % 1st arg not opaque
ok.
-neg_line(doc) ->
- ["Test negative line numbers (OTP 18)"];
-neg_line(_Config) ->
- neg_line1(false),
- neg_line1(true),
- ok.
-
-neg_line1(TextToo) ->
- Minus8_0 = erl_anno:new(-8),
- Plus8_0 = erl_anno:new(8),
- Minus8C_0 = erl_anno:new({-8, 17}),
- Plus8C_0 = erl_anno:new({8, 17}),
-
- [Minus8, Plus8, Minus8C, Plus8C] =
- [case TextToo of
- true ->
- erl_anno:set_text("foo", A);
- false ->
- A
- end || A <- [Minus8_0, Plus8_0, Minus8C_0, Plus8C_0]],
-
- tst(-3, erl_anno:set_location(3, Minus8)),
- tst(-3, erl_anno:set_location(-3, Plus8)),
- tst(-3, erl_anno:set_location(-3, Minus8)),
- tst({-3,9}, erl_anno:set_location({3, 9}, Minus8)),
- tst({-3,9}, erl_anno:set_location({-3, 9}, Plus8)),
- tst({-3,9}, erl_anno:set_location({-3, 9}, Minus8)),
- tst(-3, erl_anno:set_location(3, Minus8C)),
- tst(-3, erl_anno:set_location(-3, Plus8C)),
- tst(-3, erl_anno:set_location(-3, Minus8C)),
- tst({-3,9}, erl_anno:set_location({3, 9}, Minus8C)),
- tst({-3,9}, erl_anno:set_location({-3, 9}, Plus8C)),
- tst({-3,9}, erl_anno:set_location({-3, 9}, Minus8C)),
-
- tst(-8, erl_anno:set_generated(true, Plus8)),
- tst(-8, erl_anno:set_generated(true, Minus8)),
- tst({-8,17}, erl_anno:set_generated(true, Plus8C)),
- tst({-8,17}, erl_anno:set_generated(true, Minus8C)),
- tst(8, erl_anno:set_generated(false, Plus8)),
- tst(8, erl_anno:set_generated(false, Minus8)),
- tst({8,17}, erl_anno:set_generated(false, Plus8C)),
- tst({8,17}, erl_anno:set_generated(false, Minus8C)),
-
- tst(-3, erl_anno:set_line(3, Minus8)),
- tst(-3, erl_anno:set_line(-3, Plus8)),
- tst(-3, erl_anno:set_line(-3, Minus8)),
- tst({-3,17}, erl_anno:set_line(3, Minus8C)),
- tst({-3,17}, erl_anno:set_line(-3, Plus8C)),
- tst({-3,17}, erl_anno:set_line(-3, Minus8C)),
- ok.
-
-tst(Term, Anno) ->
- ?format("Term: ~p\n", [Term]),
- ?format("Anno: ~p\n", [Anno]),
- case anno_to_term(Anno) of
- Term ->
- ok;
- Else ->
- case lists:keyfind(location, 1, Else) of
- {location, Term} ->
- ok;
- _Else2 ->
- ?format("Else2 ~p\n", [_Else2]),
- io:format("expected ~p\n got ~p\n", [Term, Else]),
- exit({Term, Else})
- end
- end.
-
-parse_abstract(doc) ->
- ["Test erl_parse:new_anno/1, erl_parse:anno_to_term/1"
- ", and erl_parse:anno_from_term/1"];
+%% Test erl_parse:new_anno/1, erl_parse:anno_to_term/1,
+%% and erl_parse:anno_from_term/1.
parse_abstract(_Config) ->
T = sample_term(),
A = erl_parse:abstract(T, [{line,17}]),
@@ -310,8 +230,7 @@ parse_abstract(_Config) ->
T = erl_parse:normalise(Abstr2),
ok.
-mapfold_anno(doc) ->
- ["Test erl_parse:{map_anno/2,fold_anno/3, and mapfold_anno/3}"];
+%% Test erl_parse:{map_anno/2,fold_anno/3, and mapfold_anno/3}.
mapfold_anno(_Config) ->
T = sample_term(),
Abstr = erl_parse:abstract(T),
diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl
index c21c4e61ee..c3ef4eb051 100644
--- a/lib/stdlib/test/erl_eval_SUITE.erl
+++ b/lib/stdlib/test/erl_eval_SUITE.erl
@@ -19,6 +19,7 @@
-module(erl_eval_SUITE).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2,
init_per_group/2,end_per_group/2]).
-export([guard_1/1, guard_2/1,
@@ -64,20 +65,18 @@
config(priv_dir,_) ->
".".
-else.
--include_lib("test_server/include/test_server.hrl").
--export([init_per_testcase/2, end_per_testcase/2]).
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
+-include_lib("common_test/include/ct.hrl").
+-endif.
+
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+ Config.
+
+end_per_testcase(_Case, _Config) ->
ok.
--endif.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[guard_1, guard_2, match_pattern, string_plusplus,
@@ -103,125 +102,101 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-guard_1(doc) ->
- ["(OTP-2405)"];
-guard_1(suite) ->
- [];
+%% OTP-2405
guard_1(Config) when is_list(Config) ->
- ?line {ok,Tokens ,_} =
+ {ok,Tokens ,_} =
erl_scan:string("if a+4 == 4 -> yes; true -> no end. "),
- ?line {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
- ?line no = guard_1_compiled(),
- ?line {value, no, []} = erl_eval:expr(Expr, []),
+ {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
+ no = guard_1_compiled(),
+ {value, no, []} = erl_eval:expr(Expr, []),
ok.
guard_1_compiled() ->
if a+4 == 4 -> yes; true -> no end.
-guard_2(doc) ->
- ["Similar to guard_1, but type-correct"];
-guard_2(suite) ->
- [];
+%% Similar to guard_1, but type-correct.
guard_2(Config) when is_list(Config) ->
- ?line {ok,Tokens ,_} =
+ {ok,Tokens ,_} =
erl_scan:string("if 6+4 == 4 -> yes; true -> no end. "),
- ?line {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
- ?line no = guard_2_compiled(),
- ?line {value, no, []} = erl_eval:expr(Expr, []),
+ {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
+ no = guard_2_compiled(),
+ {value, no, []} = erl_eval:expr(Expr, []),
ok.
guard_2_compiled() ->
if 6+4 == 4 -> yes; true -> no end.
-string_plusplus(doc) ->
- ["OTP-3069: syntactic sugar string ++ ..."];
-string_plusplus(suite) ->
- [];
+%% OTP-3069: syntactic sugar string ++ ...
string_plusplus(Config) when is_list(Config) ->
- ?line check(fun() -> case "abc" of "ab" ++ L -> L end end,
- "case \"abc\" of \"ab\" ++ L -> L end. ",
- "c"),
- ?line check(fun() -> case "abcde" of "ab" ++ "cd" ++ L -> L end end,
- "case \"abcde\" of \"ab\" ++ \"cd\" ++ L -> L end. ",
- "e"),
- ?line check(fun() -> case "abc" of [97, 98] ++ L -> L end end,
- "case \"abc\" of [97, 98] ++ L -> L end. ",
- "c"),
+ check(fun() -> case "abc" of "ab" ++ L -> L end end,
+ "case \"abc\" of \"ab\" ++ L -> L end. ",
+ "c"),
+ check(fun() -> case "abcde" of "ab" ++ "cd" ++ L -> L end end,
+ "case \"abcde\" of \"ab\" ++ \"cd\" ++ L -> L end. ",
+ "e"),
+ check(fun() -> case "abc" of [97, 98] ++ L -> L end end,
+ "case \"abc\" of [97, 98] ++ L -> L end. ",
+ "c"),
ok.
-match_pattern(doc) ->
- ["OTP-2983: match operator in pattern"];
-match_pattern(suite) ->
- [];
+%% OTP-2983: match operator in pattern.
match_pattern(Config) when is_list(Config) ->
- ?line check(fun() -> case {a, b} of {a, _X}=Y -> {x,Y} end end,
- "case {a, b} of {a, X}=Y -> {x,Y} end. ",
- {x, {a, b}}),
- ?line check(fun() -> case {a, b} of Y={a, _X} -> {x,Y} end end,
- "case {a, b} of Y={a, X} -> {x,Y} end. ",
- {x, {a, b}}),
- ?line check(fun() -> case {a, b} of Y={a, _X}=Z -> {Z,Y} end end,
- "case {a, b} of Y={a, X}=Z -> {Z,Y} end. ",
- {{a, b}, {a, b}}),
- ?line check(fun() -> A = 4, B = 28, <<13:(A+(X=B))>>, X end,
- "begin A = 4, B = 28, <<13:(A+(X=B))>>, X end.",
- 28),
+ check(fun() -> case {a, b} of {a, _X}=Y -> {x,Y} end end,
+ "case {a, b} of {a, X}=Y -> {x,Y} end. ",
+ {x, {a, b}}),
+ check(fun() -> case {a, b} of Y={a, _X} -> {x,Y} end end,
+ "case {a, b} of Y={a, X} -> {x,Y} end. ",
+ {x, {a, b}}),
+ check(fun() -> case {a, b} of Y={a, _X}=Z -> {Z,Y} end end,
+ "case {a, b} of Y={a, X}=Z -> {Z,Y} end. ",
+ {{a, b}, {a, b}}),
+ check(fun() -> A = 4, B = 28, <<13:(A+(X=B))>>, X end,
+ "begin A = 4, B = 28, <<13:(A+(X=B))>>, X end.",
+ 28),
ok.
-match_bin(doc) ->
- ["binary match problems"];
-match_bin(suite) ->
- [];
+%% Binary match problems.
match_bin(Config) when is_list(Config) ->
- ?line check(fun() -> <<"abc">> = <<"abc">> end,
- "<<\"abc\">> = <<\"abc\">>. ",
- <<"abc">>),
- ?line check(fun() ->
- <<Size,B:Size/binary,Rest/binary>> = <<2,"AB","CD">>,
- {Size,B,Rest}
- end,
- "begin <<Size,B:Size/binary,Rest/binary>> = <<2,\"AB\",\"CD\">>, "
- "{Size,B,Rest} end. ",
- {2,<<"AB">>,<<"CD">>}),
+ check(fun() -> <<"abc">> = <<"abc">> end,
+ "<<\"abc\">> = <<\"abc\">>. ",
+ <<"abc">>),
+ check(fun() ->
+ <<Size,B:Size/binary,Rest/binary>> = <<2,"AB","CD">>,
+ {Size,B,Rest}
+ end,
+ "begin <<Size,B:Size/binary,Rest/binary>> = <<2,\"AB\",\"CD\">>, "
+ "{Size,B,Rest} end. ",
+ {2,<<"AB">>,<<"CD">>}),
ok.
-pattern_expr(doc) ->
- ["OTP-3144: compile-time expressions in pattern"];
-pattern_expr(suite) ->
- [];
+%% OTP-3144: compile-time expressions in pattern.
pattern_expr(Config) when is_list(Config) ->
- ?line check(fun() -> case 4 of 2+2 -> ok end end,
- "case 4 of 2+2 -> ok end. ",
- ok),
- ?line check(fun() -> case 2 of +2 -> ok end end,
- "case 2 of +2 -> ok end. ",
- ok),
+ check(fun() -> case 4 of 2+2 -> ok end end,
+ "case 4 of 2+2 -> ok end. ",
+ ok),
+ check(fun() -> case 2 of +2 -> ok end end,
+ "case 2 of +2 -> ok end. ",
+ ok),
ok.
-guard_3(doc) ->
- ["OTP-4518."];
-guard_3(suite) ->
- [];
+%% OTP-4518.
guard_3(Config) when is_list(Config) ->
- ?line check(fun() -> if false -> false; true -> true end end,
- "if false -> false; true -> true end.",
- true),
- ?line check(fun() -> if <<"hej">> == <<"hopp">> -> true;
- true -> false end end,
- "begin if <<\"hej\">> == <<\"hopp\">> -> true;
+ check(fun() -> if false -> false; true -> true end end,
+ "if false -> false; true -> true end.",
+ true),
+ check(fun() -> if <<"hej">> == <<"hopp">> -> true;
+ true -> false end end,
+ "begin if <<\"hej\">> == <<\"hopp\">> -> true;
true -> false end end.",
false),
- ?line check(fun() -> if <<"hej">> == <<"hej">> -> true;
- true -> false end end,
- "begin if <<\"hej\">> == <<\"hej\">> -> true;
+ check(fun() -> if <<"hej">> == <<"hej">> -> true;
+ true -> false end end,
+ "begin if <<\"hej\">> == <<\"hej\">> -> true;
true -> false end end.",
true),
ok.
-guard_4(doc) ->
- ["OTP-4885."];
-guard_4(suite) ->
- [];
+%% OTP-4885.
guard_4(Config) when is_list(Config) ->
check(fun() -> if erlang:'+'(3,a) -> true ; true -> false end end,
"if erlang:'+'(3,a) -> true ; true -> false end.",
@@ -230,31 +205,28 @@ guard_4(Config) when is_list(Config) ->
end,
"if erlang:is_integer(3) -> true ; true -> false end.",
true),
- ?line check(fun() -> [X || X <- [1,2,3], erlang:is_integer(X)] end,
- "[X || X <- [1,2,3], erlang:is_integer(X)].",
- [1,2,3]),
- ?line check(fun() -> if is_atom(is_integer(a)) -> true ; true -> false end
- end,
- "if is_atom(is_integer(a)) -> true ; true -> false end.",
- true),
+ check(fun() -> [X || X <- [1,2,3], erlang:is_integer(X)] end,
+ "[X || X <- [1,2,3], erlang:is_integer(X)].",
+ [1,2,3]),
+ check(fun() -> if is_atom(is_integer(a)) -> true ; true -> false end
+ end,
+ "if is_atom(is_integer(a)) -> true ; true -> false end.",
+ true),
check(fun() -> if erlang:is_atom(erlang:is_integer(a)) -> true;
true -> false end end,
"if erlang:is_atom(erlang:is_integer(a)) -> true; "
"true -> false end.",
true),
- ?line check(fun() -> if is_atom(3+a) -> true ; true -> false end end,
- "if is_atom(3+a) -> true ; true -> false end.",
- false),
- ?line check(fun() -> if erlang:is_atom(3+a) -> true ; true -> false end
- end,
- "if erlang:is_atom(3+a) -> true ; true -> false end.",
- false),
+ check(fun() -> if is_atom(3+a) -> true ; true -> false end end,
+ "if is_atom(3+a) -> true ; true -> false end.",
+ false),
+ check(fun() -> if erlang:is_atom(3+a) -> true ; true -> false end
+ end,
+ "if erlang:is_atom(3+a) -> true ; true -> false end.",
+ false),
ok.
-guard_5(doc) ->
- ["Guards with erlang:'=='/2"];
-guard_5(suite) ->
- [];
+%% Guards with erlang:'=='/2.
guard_5(Config) when is_list(Config) ->
{ok,Tokens ,_} =
erl_scan:string("case 1 of A when erlang:'=='(A, 1) -> true end."),
@@ -266,293 +238,278 @@ guard_5(Config) when is_list(Config) ->
guard_5_compiled() ->
case 1 of A when erlang:'=='(A, 1) -> true end.
-lc(doc) ->
- ["OTP-4518."];
-lc(suite) ->
- [];
+%% OTP-4518.
lc(Config) when is_list(Config) ->
- ?line check(fun() -> X = 32, [X || X <- [1,2,3]] end,
- "begin X = 32, [X || X <- [1,2,3]] end.",
- [1,2,3]),
- ?line check(fun() -> X = 32,
- [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end,
- %% "binsize variable" ^
- "begin X = 32,
+ check(fun() -> X = 32, [X || X <- [1,2,3]] end,
+ "begin X = 32, [X || X <- [1,2,3]] end.",
+ [1,2,3]),
+ check(fun() -> X = 32,
+ [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end,
+ %% "binsize variable" ^
+ "begin X = 32,
[X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end.",
[1,2]),
- ?line check(fun() -> Y = 13,[X || {X,Y} <- [{1,2}]] end,
- "begin Y = 13,[X || {X,Y} <- [{1,2}]] end.",
- [1]),
- ?line error_check("begin [A || X <- [{1,2}], 1 == A] end.",
- {unbound_var,'A'}),
- ?line error_check("begin X = 32,
+ check(fun() -> Y = 13,[X || {X,Y} <- [{1,2}]] end,
+ "begin Y = 13,[X || {X,Y} <- [{1,2}]] end.",
+ [1]),
+ error_check("begin [A || X <- [{1,2}], 1 == A] end.",
+ {unbound_var,'A'}),
+ error_check("begin X = 32,
[{Y,W} || X <- [1,2,32,Y=4], Z <- [1,2,W=3]] end.",
{unbound_var,'Y'}),
- ?line error_check("begin X = 32,<<A:B>> = <<100:X>> end.",
- {unbound_var,'B'}),
- ?line check(fun() -> [X || X <- [1,2,3,4], not (X < 2)] end,
- "begin [X || X <- [1,2,3,4], not (X < 2)] end.",
- [2,3,4]),
- ?line check(fun() -> [X || X <- [true,false], X] end,
- "[X || X <- [true,false], X].", [true]),
+ error_check("begin X = 32,<<A:B>> = <<100:X>> end.",
+ {unbound_var,'B'}),
+ check(fun() -> [X || X <- [1,2,3,4], not (X < 2)] end,
+ "begin [X || X <- [1,2,3,4], not (X < 2)] end.",
+ [2,3,4]),
+ check(fun() -> [X || X <- [true,false], X] end,
+ "[X || X <- [true,false], X].", [true]),
ok.
-simple_cases(doc) ->
- ["Simple cases, just to cover some code."];
-simple_cases(suite) ->
- [];
+%% Simple cases, just to cover some code.
simple_cases(Config) when is_list(Config) ->
- ?line check(fun() -> A = $C end, "A = $C.", $C),
- %% ?line check(fun() -> A = 3.14 end, "A = 3.14.", 3.14),
- ?line check(fun() -> self() ! a, A = receive a -> true end end,
- "begin self() ! a, A = receive a -> true end end.",
- true),
- ?line check(fun() -> c:flush(), self() ! a, self() ! b, self() ! c,
- receive b -> b end,
- {messages, [a,c]} =
- erlang:process_info(self(), messages),
- c:flush() end,
- "begin c:flush(), self() ! a, self() ! b, self() ! c,"
- "receive b -> b end,"
- "{messages, [a,c]} ="
- " erlang:process_info(self(), messages), c:flush() end.",
- ok),
- ?line check(fun() -> self() ! a, A = receive a -> true
- after 0 -> false end end,
- "begin self() ! a, A = receive a -> true"
- " after 0 -> false end end.",
- true),
- ?line check(fun() -> c:flush(), self() ! a, self() ! b, self() ! c,
- receive b -> b after 0 -> true end,
- {messages, [a,c]} =
- erlang:process_info(self(), messages),
- c:flush() end,
- "begin c:flush(), self() ! a, self() ! b, self() ! c,"
- "receive b -> b after 0 -> true end,"
- "{messages, [a,c]} ="
- " erlang:process_info(self(), messages), c:flush() end.",
- ok),
- ?line check(fun() -> receive _ -> true after 10 -> false end end,
- "receive _ -> true after 10 -> false end.",
- false),
- ?line check(fun() -> F = fun(A) -> A end, true = 3 == F(3) end,
- "begin F = fun(A) -> A end, true = 3 == F(3) end.",
- true),
- ?line check(fun() -> F = fun(A) -> A end, true = 3 == apply(F, [3]) end,
- "begin F = fun(A) -> A end, true = 3 == apply(F,[3]) end.",
- true),
- ?line check(fun() -> catch throw(a) end, "catch throw(a).", a),
- ?line check(fun() -> catch a end, "catch a.", a),
- ?line check(fun() -> 4 == 3 end, "4 == 3.", false),
- ?line check(fun() -> not true end, "not true.", false),
- ?line check(fun() -> -3 end, "-3.", -3),
-
- ?line error_check("3.0 = 4.0.", {badmatch,4.0}),
- ?line check(fun() -> <<(3.0+2.0):32/float>> = <<5.0:32/float>> end,
- "<<(3.0+2.0):32/float>> = <<5.0:32/float>>.",
- <<5.0:32/float>>),
-
- ?line check(fun() -> false andalso kludd end, "false andalso kludd.",
- false),
- ?line check(fun() -> true andalso true end, "true andalso true.",
- true),
- ?line check(fun() -> true andalso false end, "true andalso false.",
- false),
- ?line check(fun() -> true andalso kludd end, "true andalso kludd.",
- kludd),
- ?line error_check("kladd andalso kludd.", {badarg,kladd}),
-
- ?line check(fun() -> if false andalso kludd -> a; true -> b end end,
- "if false andalso kludd -> a; true -> b end.",
- b),
- ?line check(fun() -> if true andalso true -> a; true -> b end end,
- "if true andalso true -> a; true -> b end.",
- a),
- ?line check(fun() -> if true andalso false -> a; true -> b end end,
- "if true andalso false -> a; true -> b end.",
- b),
-
- ?line check(fun() -> true orelse kludd end,
- "true orelse kludd.", true),
- ?line check(fun() -> false orelse false end,
- "false orelse false.", false),
- ?line check(fun() -> false orelse true end,
- "false orelse true.", true),
- ?line check(fun() -> false orelse kludd end,
- "false orelse kludd.", kludd),
- ?line error_check("kladd orelse kludd.", {badarg,kladd}),
- ?line error_check("[X || X <- [1,2,3], begin 1 end].",{bad_filter,1}),
- ?line error_check("[X || X <- a].",{bad_generator,a}),
-
- ?line check(fun() -> if true orelse kludd -> a; true -> b end end,
- "if true orelse kludd -> a; true -> b end.", a),
- ?line check(fun() -> if false orelse false -> a; true -> b end end,
- "if false orelse false -> a; true -> b end.", b),
- ?line check(fun() -> if false orelse true -> a; true -> b end end,
- "if false orelse true -> a; true -> b end.", a),
-
- ?line check(fun() -> [X || X <- [1,2,3], X+2] end,
- "[X || X <- [1,2,3], X+2].", []),
-
- ?line check(fun() -> [X || X <- [1,2,3], [X] == [X || X <- [2]]] end,
- "[X || X <- [1,2,3], [X] == [X || X <- [2]]].",
- [2]),
- ?line check(fun() -> F = fun(1) -> ett; (2) -> zwei end,
- ett = F(1), zwei = F(2) end,
- "begin F = fun(1) -> ett; (2) -> zwei end,
+ check(fun() -> A = $C end, "A = $C.", $C),
+ %% check(fun() -> A = 3.14 end, "A = 3.14.", 3.14),
+ check(fun() -> self() ! a, A = receive a -> true end end,
+ "begin self() ! a, A = receive a -> true end end.",
+ true),
+ check(fun() -> c:flush(), self() ! a, self() ! b, self() ! c,
+ receive b -> b end,
+ {messages, [a,c]} =
+ erlang:process_info(self(), messages),
+ c:flush() end,
+ "begin c:flush(), self() ! a, self() ! b, self() ! c,"
+ "receive b -> b end,"
+ "{messages, [a,c]} ="
+ " erlang:process_info(self(), messages), c:flush() end.",
+ ok),
+ check(fun() -> self() ! a, A = receive a -> true
+ after 0 -> false end end,
+ "begin self() ! a, A = receive a -> true"
+ " after 0 -> false end end.",
+ true),
+ check(fun() -> c:flush(), self() ! a, self() ! b, self() ! c,
+ receive b -> b after 0 -> true end,
+ {messages, [a,c]} =
+ erlang:process_info(self(), messages),
+ c:flush() end,
+ "begin c:flush(), self() ! a, self() ! b, self() ! c,"
+ "receive b -> b after 0 -> true end,"
+ "{messages, [a,c]} ="
+ " erlang:process_info(self(), messages), c:flush() end.",
+ ok),
+ check(fun() -> receive _ -> true after 10 -> false end end,
+ "receive _ -> true after 10 -> false end.",
+ false),
+ check(fun() -> F = fun(A) -> A end, true = 3 == F(3) end,
+ "begin F = fun(A) -> A end, true = 3 == F(3) end.",
+ true),
+ check(fun() -> F = fun(A) -> A end, true = 3 == apply(F, [3]) end,
+ "begin F = fun(A) -> A end, true = 3 == apply(F,[3]) end.",
+ true),
+ check(fun() -> catch throw(a) end, "catch throw(a).", a),
+ check(fun() -> catch a end, "catch a.", a),
+ check(fun() -> 4 == 3 end, "4 == 3.", false),
+ check(fun() -> not true end, "not true.", false),
+ check(fun() -> -3 end, "-3.", -3),
+
+ error_check("3.0 = 4.0.", {badmatch,4.0}),
+ check(fun() -> <<(3.0+2.0):32/float>> = <<5.0:32/float>> end,
+ "<<(3.0+2.0):32/float>> = <<5.0:32/float>>.",
+ <<5.0:32/float>>),
+
+ check(fun() -> false andalso kludd end, "false andalso kludd.",
+ false),
+ check(fun() -> true andalso true end, "true andalso true.",
+ true),
+ check(fun() -> true andalso false end, "true andalso false.",
+ false),
+ check(fun() -> true andalso kludd end, "true andalso kludd.",
+ kludd),
+ error_check("kladd andalso kludd.", {badarg,kladd}),
+
+ check(fun() -> if false andalso kludd -> a; true -> b end end,
+ "if false andalso kludd -> a; true -> b end.",
+ b),
+ check(fun() -> if true andalso true -> a; true -> b end end,
+ "if true andalso true -> a; true -> b end.",
+ a),
+ check(fun() -> if true andalso false -> a; true -> b end end,
+ "if true andalso false -> a; true -> b end.",
+ b),
+
+ check(fun() -> true orelse kludd end,
+ "true orelse kludd.", true),
+ check(fun() -> false orelse false end,
+ "false orelse false.", false),
+ check(fun() -> false orelse true end,
+ "false orelse true.", true),
+ check(fun() -> false orelse kludd end,
+ "false orelse kludd.", kludd),
+ error_check("kladd orelse kludd.", {badarg,kladd}),
+ error_check("[X || X <- [1,2,3], begin 1 end].",{bad_filter,1}),
+ error_check("[X || X <- a].",{bad_generator,a}),
+
+ check(fun() -> if true orelse kludd -> a; true -> b end end,
+ "if true orelse kludd -> a; true -> b end.", a),
+ check(fun() -> if false orelse false -> a; true -> b end end,
+ "if false orelse false -> a; true -> b end.", b),
+ check(fun() -> if false orelse true -> a; true -> b end end,
+ "if false orelse true -> a; true -> b end.", a),
+
+ check(fun() -> [X || X <- [1,2,3], X+2] end,
+ "[X || X <- [1,2,3], X+2].", []),
+
+ check(fun() -> [X || X <- [1,2,3], [X] == [X || X <- [2]]] end,
+ "[X || X <- [1,2,3], [X] == [X || X <- [2]]].",
+ [2]),
+ check(fun() -> F = fun(1) -> ett; (2) -> zwei end,
+ ett = F(1), zwei = F(2) end,
+ "begin F = fun(1) -> ett; (2) -> zwei end,
ett = F(1), zwei = F(2) end.",
zwei),
- ?line check(fun() -> F = fun(X) when X == 1 -> ett;
- (X) when X == 2 -> zwei end,
- ett = F(1), zwei = F(2) end,
- "begin F = fun(X) when X == 1 -> ett;
+ check(fun() -> F = fun(X) when X == 1 -> ett;
+ (X) when X == 2 -> zwei end,
+ ett = F(1), zwei = F(2) end,
+ "begin F = fun(X) when X == 1 -> ett;
(X) when X == 2 -> zwei end,
- ett = F(1), zwei = F(2) end.",
+ ett = F(1), zwei = F(2) end.",
zwei),
- ?line error_check("begin F = fun(1) -> ett end, zwei = F(2) end.",
- function_clause),
- ?line check(fun() -> if length([1]) == 1 -> yes;
- true -> no end end,
- "if length([1]) == 1 -> yes;
+ error_check("begin F = fun(1) -> ett end, zwei = F(2) end.",
+ function_clause),
+ check(fun() -> if length([1]) == 1 -> yes;
+ true -> no end end,
+ "if length([1]) == 1 -> yes;
true -> no end.",
yes),
- ?line check(fun() -> if is_integer(3) -> true; true -> false end end,
- "if is_integer(3) -> true; true -> false end.", true),
- ?line check(fun() -> if integer(3) -> true; true -> false end end,
- "if integer(3) -> true; true -> false end.", true),
- ?line check(fun() -> if is_float(3) -> true; true -> false end end,
- "if is_float(3) -> true; true -> false end.", false),
- ?line check(fun() -> if float(3) -> true; true -> false end end,
- "if float(3) -> true; true -> false end.", false),
- ?line check(fun() -> if is_number(3) -> true; true -> false end end,
- "if is_number(3) -> true; true -> false end.", true),
- ?line check(fun() -> if number(3) -> true; true -> false end end,
- "if number(3) -> true; true -> false end.", true),
- ?line check(fun() -> if is_atom(a) -> true; true -> false end end,
- "if is_atom(a) -> true; true -> false end.", true),
- ?line check(fun() -> if atom(a) -> true; true -> false end end,
- "if atom(a) -> true; true -> false end.", true),
- ?line check(fun() -> if is_list([]) -> true; true -> false end end,
- "if is_list([]) -> true; true -> false end.", true),
- ?line check(fun() -> if list([]) -> true; true -> false end end,
- "if list([]) -> true; true -> false end.", true),
- ?line check(fun() -> if is_tuple({}) -> true; true -> false end end,
- "if is_tuple({}) -> true; true -> false end.", true),
- ?line check(fun() -> if tuple({}) -> true; true -> false end end,
- "if tuple({}) -> true; true -> false end.", true),
- ?line check(fun() -> if is_pid(self()) -> true; true -> false end end,
- "if is_pid(self()) -> true; true -> false end.", true),
- ?line check(fun() -> if pid(self()) -> true; true -> false end end,
- "if pid(self()) -> true; true -> false end.", true),
- ?line check(fun() -> R = make_ref(), if is_reference(R) -> true;
- true -> false end end,
- "begin R = make_ref(), if is_reference(R) -> true;"
- "true -> false end end.", true),
- ?line check(fun() -> R = make_ref(), if reference(R) -> true;
- true -> false end end,
- "begin R = make_ref(), if reference(R) -> true;"
- "true -> false end end.", true),
- ?line check(fun() -> if is_port(a) -> true; true -> false end end,
- "if is_port(a) -> true; true -> false end.", false),
- ?line check(fun() -> if port(a) -> true; true -> false end end,
- "if port(a) -> true; true -> false end.", false),
- ?line check(fun() -> if is_function(a) -> true; true -> false end end,
- "if is_function(a) -> true; true -> false end.", false),
- ?line check(fun() -> if function(a) -> true; true -> false end end,
- "if function(a) -> true; true -> false end.", false),
- ?line check(fun() -> if is_binary(<<>>) -> true; true -> false end end,
- "if is_binary(<<>>) -> true; true -> false end.", true),
- ?line check(fun() -> if binary(<<>>) -> true; true -> false end end,
- "if binary(<<>>) -> true; true -> false end.", true),
- ?line check(fun() -> if is_integer(a) == true -> yes;
- true -> no end end,
- "if is_integer(a) == true -> yes;
+ check(fun() -> if is_integer(3) -> true; true -> false end end,
+ "if is_integer(3) -> true; true -> false end.", true),
+ check(fun() -> if integer(3) -> true; true -> false end end,
+ "if integer(3) -> true; true -> false end.", true),
+ check(fun() -> if is_float(3) -> true; true -> false end end,
+ "if is_float(3) -> true; true -> false end.", false),
+ check(fun() -> if float(3) -> true; true -> false end end,
+ "if float(3) -> true; true -> false end.", false),
+ check(fun() -> if is_number(3) -> true; true -> false end end,
+ "if is_number(3) -> true; true -> false end.", true),
+ check(fun() -> if number(3) -> true; true -> false end end,
+ "if number(3) -> true; true -> false end.", true),
+ check(fun() -> if is_atom(a) -> true; true -> false end end,
+ "if is_atom(a) -> true; true -> false end.", true),
+ check(fun() -> if atom(a) -> true; true -> false end end,
+ "if atom(a) -> true; true -> false end.", true),
+ check(fun() -> if is_list([]) -> true; true -> false end end,
+ "if is_list([]) -> true; true -> false end.", true),
+ check(fun() -> if list([]) -> true; true -> false end end,
+ "if list([]) -> true; true -> false end.", true),
+ check(fun() -> if is_tuple({}) -> true; true -> false end end,
+ "if is_tuple({}) -> true; true -> false end.", true),
+ check(fun() -> if tuple({}) -> true; true -> false end end,
+ "if tuple({}) -> true; true -> false end.", true),
+ check(fun() -> if is_pid(self()) -> true; true -> false end end,
+ "if is_pid(self()) -> true; true -> false end.", true),
+ check(fun() -> if pid(self()) -> true; true -> false end end,
+ "if pid(self()) -> true; true -> false end.", true),
+ check(fun() -> R = make_ref(), if is_reference(R) -> true;
+ true -> false end end,
+ "begin R = make_ref(), if is_reference(R) -> true;"
+ "true -> false end end.", true),
+ check(fun() -> R = make_ref(), if reference(R) -> true;
+ true -> false end end,
+ "begin R = make_ref(), if reference(R) -> true;"
+ "true -> false end end.", true),
+ check(fun() -> if is_port(a) -> true; true -> false end end,
+ "if is_port(a) -> true; true -> false end.", false),
+ check(fun() -> if port(a) -> true; true -> false end end,
+ "if port(a) -> true; true -> false end.", false),
+ check(fun() -> if is_function(a) -> true; true -> false end end,
+ "if is_function(a) -> true; true -> false end.", false),
+ check(fun() -> if function(a) -> true; true -> false end end,
+ "if function(a) -> true; true -> false end.", false),
+ check(fun() -> if is_binary(<<>>) -> true; true -> false end end,
+ "if is_binary(<<>>) -> true; true -> false end.", true),
+ check(fun() -> if binary(<<>>) -> true; true -> false end end,
+ "if binary(<<>>) -> true; true -> false end.", true),
+ check(fun() -> if is_integer(a) == true -> yes;
+ true -> no end end,
+ "if is_integer(a) == true -> yes;
true -> no end.",
no),
- ?line check(fun() -> if [] -> true; true -> false end end,
- "if [] -> true; true -> false end.", false),
- ?line error_check("if lists:member(1,[1]) -> true; true -> false end.",
- illegal_guard_expr),
- ?line error_check("if false -> true end.", if_clause),
- ?line check(fun() -> if a+b -> true; true -> false end end,
- "if a + b -> true; true -> false end.", false),
- ?line check(fun() -> if + b -> true; true -> false end end,
- "if + b -> true; true -> false end.", false),
- ?line error_check("case foo of bar -> true end.", {case_clause,foo}),
- ?line error_check("case 4 of 2+a -> true; _ -> false end.",
- illegal_pattern),
- ?line error_check("case 4 of +a -> true; _ -> false end.",
- illegal_pattern),
- ?line check(fun() -> case a of
- X when X == b -> one;
- X when X == a -> two
- end end,
- "begin case a of
+ check(fun() -> if [] -> true; true -> false end end,
+ "if [] -> true; true -> false end.", false),
+ error_check("if lists:member(1,[1]) -> true; true -> false end.",
+ illegal_guard_expr),
+ error_check("if false -> true end.", if_clause),
+ check(fun() -> if a+b -> true; true -> false end end,
+ "if a + b -> true; true -> false end.", false),
+ check(fun() -> if + b -> true; true -> false end end,
+ "if + b -> true; true -> false end.", false),
+ error_check("case foo of bar -> true end.", {case_clause,foo}),
+ error_check("case 4 of 2+a -> true; _ -> false end.",
+ illegal_pattern),
+ error_check("case 4 of +a -> true; _ -> false end.",
+ illegal_pattern),
+ check(fun() -> case a of
+ X when X == b -> one;
+ X when X == a -> two
+ end end,
+ "begin case a of
X when X == b -> one;
- X when X == a -> two
- end end.", two),
- ?line error_check("3 = 4.", {badmatch,4}),
- ?line error_check("a = 3.", {badmatch,3}),
- %% ?line error_check("3.1 = 2.7.",{badmatch,2.7}),
- ?line error_check("$c = 4.", {badmatch,4}),
- ?line check(fun() -> $c = $c end, "$c = $c.", $c),
- ?line check(fun() -> _ = bar end, "_ = bar.", bar),
- ?line check(fun() -> A = 14, A = 14 end,
+ X when X == a -> two
+ end end.", two),
+ error_check("3 = 4.", {badmatch,4}),
+ error_check("a = 3.", {badmatch,3}),
+ %% error_check("3.1 = 2.7.",{badmatch,2.7}),
+ error_check("$c = 4.", {badmatch,4}),
+ check(fun() -> $c = $c end, "$c = $c.", $c),
+ check(fun() -> _ = bar end, "_ = bar.", bar),
+ check(fun() -> A = 14, A = 14 end,
"begin A = 14, A = 14 end.", 14),
- ?line error_check("begin A = 14, A = 16 end.", {badmatch,16}),
- ?line error_check("\"hej\" = \"san\".", {badmatch,"san"}),
- ?line check(fun() -> "hej" = "hej" end,
+ error_check("begin A = 14, A = 16 end.", {badmatch,16}),
+ error_check("\"hej\" = \"san\".", {badmatch,"san"}),
+ check(fun() -> "hej" = "hej" end,
"\"hej\" = \"hej\".", "hej"),
- ?line error_check("[] = [a].", {badmatch,[a]}),
- ?line check(fun() -> [] = [] end, "[] = [].", []),
- ?line error_check("[a] = [].", {badmatch,[]}),
- ?line error_check("{a,b} = 34.", {badmatch,34}),
- ?line check(fun() -> <<X:7>> = <<8:7>>, X end,
+ error_check("[] = [a].", {badmatch,[a]}),
+ check(fun() -> [] = [] end, "[] = [].", []),
+ error_check("[a] = [].", {badmatch,[]}),
+ error_check("{a,b} = 34.", {badmatch,34}),
+ check(fun() -> <<X:7>> = <<8:7>>, X end,
"begin <<X:7>> = <<8:7>>, X end.", 8),
- ?line error_check("<<34:32>> = \"hej\".", {badmatch,"hej"}),
- ?line check(fun() -> trunc((1 * 3 div 3 + 4 - 3) / 1) rem 2 end,
+ error_check("<<34:32>> = \"hej\".", {badmatch,"hej"}),
+ check(fun() -> trunc((1 * 3 div 3 + 4 - 3) / 1) rem 2 end,
"begin trunc((1 * 3 div 3 + 4 - 3) / 1) rem 2 end.", 0),
- ?line check(fun() -> (2#101 band 2#10101) bor (2#110 bxor 2#010) end,
+ check(fun() -> (2#101 band 2#10101) bor (2#110 bxor 2#010) end,
"(2#101 band 2#10101) bor (2#110 bxor 2#010).", 5),
- ?line check(fun() -> (2#1 bsl 4) + (2#10000 bsr 3) end,
+ check(fun() -> (2#1 bsl 4) + (2#10000 bsr 3) end,
"(2#1 bsl 4) + (2#10000 bsr 3).", 18),
- ?line check(fun() -> ((1<3) and ((1 =:= 2) or (1 =/= 2))) xor (1=<2) end,
+ check(fun() -> ((1<3) and ((1 =:= 2) or (1 =/= 2))) xor (1=<2) end,
"((1<3) and ((1 =:= 2) or (1 =/= 2))) xor (1=<2).", false),
- ?line check(fun() -> (a /= b) or (2 > 4) or (3 >= 3) end,
+ check(fun() -> (a /= b) or (2 > 4) or (3 >= 3) end,
"(a /= b) or (2 > 4) or (3 >= 3).", true),
- ?line check(fun() -> "hej" ++ "san" =/= "hejsan" -- "san" end,
+ check(fun() -> "hej" ++ "san" =/= "hejsan" -- "san" end,
"\"hej\" ++ \"san\" =/= \"hejsan\" -- \"san\".", true),
- ?line check(fun() -> (bnot 1) < -0 end, "(bnot (+1)) < -0.", true),
- ok.
+ check(fun() -> (bnot 1) < -0 end, "(bnot (+1)) < -0.", true),
+ ok.
-unary_plus(doc) ->
- ["OTP-4929. Unary plus rejects non-numbers."];
-unary_plus(suite) ->
- [];
+%% OTP-4929. Unary plus rejects non-numbers.
unary_plus(Config) when is_list(Config) ->
- ?line check(fun() -> F = fun(X) -> + X end,
- true = -1 == F(-1) end,
- "begin F = fun(X) -> + X end,"
- " true = -1 == F(-1) end.", true, ['F'], none, none),
- ?line error_check("+a.", badarith),
+ check(fun() -> F = fun(X) -> + X end,
+ true = -1 == F(-1) end,
+ "begin F = fun(X) -> + X end,"
+ " true = -1 == F(-1) end.", true, ['F'], none, none),
+ error_check("+a.", badarith),
ok.
-apply_atom(doc) ->
- ["OTP-5064. Can no longer apply atoms."];
-apply_atom(suite) ->
- [];
+%% OTP-5064. Can no longer apply atoms.
apply_atom(Config) when is_list(Config) ->
- ?line error_check("[X || X <- [[1],[2]],
+ error_check("[X || X <- [[1],[2]],
begin L = length, L(X) =:= 1 end].",
{badfun,length}),
ok.
-otp_5269(doc) ->
- ["OTP-5269. Bugs in the bit syntax."];
-otp_5269(suite) ->
- [];
+%% OTP-5269. Bugs in the bit syntax.
otp_5269(Config) when is_list(Config) ->
- ?line check(fun() -> L = 8,
+ check(fun() -> L = 8,
F = fun(<<A:L,B:A>>) -> B end,
F(<<16:8, 7:16>>)
end,
@@ -560,7 +517,7 @@ otp_5269(Config) when is_list(Config) ->
L = 8, F = fun(<<A:L,B:A>>) -> B end, F(<<16:8, 7:16>>)
end.",
7),
- ?line check(fun() -> L = 8,
+ check(fun() -> L = 8,
F = fun(<<L:L,B:L>>) -> B end,
F(<<16:8, 7:16>>)
end,
@@ -568,31 +525,31 @@ otp_5269(Config) when is_list(Config) ->
L = 8, F = fun(<<L:L,B:L>>) -> B end, F(<<16:8, 7:16>>)
end.",
7),
- ?line check(fun() -> L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end,
+ check(fun() -> L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end,
"begin L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end.",
7),
- ?line error_check("begin L = 8, <<L:L,B:L>> = <<16:8, 7:16>> end.",
+ error_check("begin L = 8, <<L:L,B:L>> = <<16:8, 7:16>> end.",
{badmatch,<<16:8,7:16>>}),
- ?line error_check("begin <<L:16,L:L>> = <<16:16,8:16>>, L end.",
+ error_check("begin <<L:16,L:L>> = <<16:16,8:16>>, L end.",
{badmatch, <<16:16,8:16>>}),
- ?line check(fun() -> U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end,
+ check(fun() -> U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end,
"begin U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end.",
32),
- ?line check(fun() -> U = 8, [U || <<U:U>> <- [<<32:8>>]] end,
+ check(fun() -> U = 8, [U || <<U:U>> <- [<<32:8>>]] end,
"begin U = 8, [U || <<U:U>> <- [<<32:8>>]] end.",
[32]),
- ?line error_check("(fun({3,<<A:32,A:32>>}) -> a end)
+ error_check("(fun({3,<<A:32,A:32>>}) -> a end)
({3,<<17:32,19:32>>}).",
function_clause),
- ?line check(fun() -> [X || <<A:8,
+ check(fun() -> [X || <<A:8,
B:A>> <- [<<16:8,19:16>>],
<<X:8>> <- [<<B:8>>]] end,
"[X || <<A:8,
B:A>> <- [<<16:8,19:16>>],
<<X:8>> <- [<<B:8>>]].",
[19]),
- ?line check(fun() ->
+ check(fun() ->
(fun (<<A:1/binary, B:8/integer, _C:B/binary>>) ->
case A of
B -> wrong;
@@ -605,12 +562,9 @@ otp_5269(Config) when is_list(Config) ->
ok),
ok.
-otp_6539(doc) ->
- ["OTP-6539. try/catch bugs."];
-otp_6539(suite) ->
- [];
+%% OTP-6539. try/catch bugs.
otp_6539(Config) when is_list(Config) ->
- ?line check(fun() ->
+ check(fun() ->
F = fun(A,B) ->
try A+B
catch _:_ -> dontthinkso
@@ -629,152 +583,149 @@ otp_6539(Config) when is_list(Config) ->
[3, 5]),
ok.
-otp_6543(doc) ->
- ["OTP-6543. bitlevel binaries."];
-otp_6543(suite) ->
- [];
+%% OTP-6543. bitlevel binaries.
otp_6543(Config) when is_list(Config) ->
- ?line check(fun() ->
+ check(fun() ->
<< <<X>> || <<X>> <- [1,2,3] >>
end,
"<< <<X>> || <<X>> <- [1,2,3] >>.",
<<>>),
- ?line check(fun() ->
+ check(fun() ->
<< <<X>> || X <- [1,2,3] >>
end,
"<< <<X>> || X <- [1,2,3] >>.",
<<1,2,3>>),
- ?line check(fun() ->
+ check(fun() ->
<< <<X:8>> || <<X:2>> <= <<"hej">> >>
end,
"<< <<X:8>> || <<X:2>> <= <<\"hej\">> >>.",
<<1,2,2,0,1,2,1,1,1,2,2,2>>),
- ?line check(fun() ->
+ check(fun() ->
<< <<X:8>> ||
<<65,X:4>> <= <<65,7:4,65,3:4,66,8:4>> >>
end,
"<< <<X:8>> ||
<<65,X:4>> <= <<65,7:4,65,3:4,66,8:4>> >>.",
<<7,3>>),
- ?line check(fun() -> <<34:18/big>> end,
+ check(fun() -> <<34:18/big>> end,
"<<34:18/big>>.",
<<0,8,2:2>>),
- ?line check(fun() -> <<34:18/big-unit:2>> end,
+ check(fun() -> <<34:18/big-unit:2>> end,
"<<34:18/big-unit:2>>.",
<<0,0,0,2,2:4>>),
- ?line check(fun() -> <<34:18/little>> end,
+ check(fun() -> <<34:18/little>> end,
"<<34:18/little>>.",
<<34,0,0:2>>),
- ?line case eval_string("<<34:18/native>>.") of
+ case eval_string("<<34:18/native>>.") of
<<0,8,2:2>> -> ok;
<<34,0,0:2>> -> ok
end,
- ?line check(fun() -> <<34:18/big-signed>> end,
+ check(fun() -> <<34:18/big-signed>> end,
"<<34:18/big-signed>>.",
<<0,8,2:2>>),
- ?line check(fun() -> <<34:18/little-signed>> end,
+ check(fun() -> <<34:18/little-signed>> end,
"<<34:18/little-signed>>.",
<<34,0,0:2>>),
- ?line case eval_string("<<34:18/native-signed>>.") of
+ case eval_string("<<34:18/native-signed>>.") of
<<0,8,2:2>> -> ok;
<<34,0,0:2>> -> ok
end,
- ?line check(fun() -> <<34:18/big-unsigned>> end,
+ check(fun() -> <<34:18/big-unsigned>> end,
"<<34:18/big-unsigned>>.",
<<0,8,2:2>>),
- ?line check(fun() -> <<34:18/little-unsigned>> end,
+ check(fun() -> <<34:18/little-unsigned>> end,
"<<34:18/little-unsigned>>.",
<<34,0,0:2>>),
- ?line case eval_string("<<34:18/native-unsigned>>.") of
+ case eval_string("<<34:18/native-unsigned>>.") of
<<0,8,2:2>> -> ok;
<<34,0,0:2>> -> ok
end,
- ?line check(fun() -> <<3.14:32/float-big>> end,
+ check(fun() -> <<3.14:32/float-big>> end,
"<<3.14:32/float-big>>.",
<<64,72,245,195>>),
- ?line check(fun() -> <<3.14:32/float-little>> end,
+ check(fun() -> <<3.14:32/float-little>> end,
"<<3.14:32/float-little>>.",
<<195,245,72,64>>),
- ?line case eval_string("<<3.14:32/float-native>>.") of
+ case eval_string("<<3.14:32/float-native>>.") of
<<64,72,245,195>> -> ok;
<<195,245,72,64>> -> ok
end,
- ?line error_check("<<(<<17,3:2>>)/binary>>.", badarg),
- ?line check(fun() -> <<(<<17,3:2>>)/bitstring>> end,
+ error_check("<<(<<17,3:2>>)/binary>>.", badarg),
+ check(fun() -> <<(<<17,3:2>>)/bitstring>> end,
"<<(<<17,3:2>>)/bitstring>>.",
<<17,3:2>>),
- ?line check(fun() -> <<(<<17,3:2>>):10/bitstring>> end,
+ check(fun() -> <<(<<17,3:2>>):10/bitstring>> end,
"<<(<<17,3:2>>):10/bitstring>>.",
<<17,3:2>>),
- ?line check(fun() -> <<<<344:17>>/binary-unit:17>> end,
+ check(fun() -> <<<<344:17>>/binary-unit:17>> end,
"<<<<344:17>>/binary-unit:17>>.",
<<344:17>>),
- ?line check(fun() -> <<X:18/big>> = <<34:18/big>>, X end,
+ check(fun() -> <<X:18/big>> = <<34:18/big>>, X end,
"begin <<X:18/big>> = <<34:18/big>>, X end.",
34),
- ?line check(fun() -> <<X:18/big-unit:2>> = <<34:18/big-unit:2>>, X end,
+ check(fun() -> <<X:18/big-unit:2>> = <<34:18/big-unit:2>>, X end,
"begin <<X:18/big-unit:2>> = <<34:18/big-unit:2>>, X end.",
34),
- ?line check(fun() -> <<X:18/little>> = <<34:18/little>>, X end,
+ check(fun() -> <<X:18/little>> = <<34:18/little>>, X end,
"begin <<X:18/little>> = <<34:18/little>>, X end.",
34),
- ?line check(fun() -> <<X:18/native>> = <<34:18/native>>, X end,
+ check(fun() -> <<X:18/native>> = <<34:18/native>>, X end,
"begin <<X:18/native>> = <<34:18/native>>, X end.",
34),
- ?line check(fun() -> <<X:18/big-signed>> = <<34:18/big-signed>>, X end,
+ check(fun() -> <<X:18/big-signed>> = <<34:18/big-signed>>, X end,
"begin <<X:18/big-signed>> = <<34:18/big-signed>>, X end.",
34),
- ?line check(fun() -> <<X:18/little-signed>> = <<34:18/little-signed>>,
+ check(fun() -> <<X:18/little-signed>> = <<34:18/little-signed>>,
X end,
"begin <<X:18/little-signed>> = <<34:18/little-signed>>,
X end.",
34),
- ?line check(fun() -> <<X:18/native-signed>> = <<34:18/native-signed>>,
+ check(fun() -> <<X:18/native-signed>> = <<34:18/native-signed>>,
X end,
"begin <<X:18/native-signed>> = <<34:18/native-signed>>,
X end.",
34),
- ?line check(fun() -> <<X:18/big-unsigned>> = <<34:18/big-unsigned>>,
+ check(fun() -> <<X:18/big-unsigned>> = <<34:18/big-unsigned>>,
X end,
"begin <<X:18/big-unsigned>> = <<34:18/big-unsigned>>,
X end.",
34),
- ?line check(fun() ->
+ check(fun() ->
<<X:18/little-unsigned>> = <<34:18/little-unsigned>>,
X end,
"begin <<X:18/little-unsigned>> = <<34:18/little-unsigned>>,
X end.",
34),
- ?line check(fun() ->
+ check(fun() ->
<<X:18/native-unsigned>> = <<34:18/native-unsigned>>,
X end,
"begin <<X:18/native-unsigned>> = <<34:18/native-unsigned>>,
X end.",
34),
- ?line check(fun() -> <<X:32/float-big>> = <<2.0:32/float-big>>, X end,
+ check(fun() -> <<X:32/float-big>> = <<2.0:32/float-big>>, X end,
"begin <<X:32/float-big>> = <<2.0:32/float-big>>,
X end.",
2.0),
- ?line check(fun() -> <<X:32/float-little>> = <<2.0:32/float-little>>,
+ check(fun() -> <<X:32/float-little>> = <<2.0:32/float-little>>,
X end,
"begin <<X:32/float-little>> = <<2.0:32/float-little>>,
X end.",
2.0),
- ?line check(fun() -> <<X:32/float-native>> = <<2.0:32/float-native>>,
+ check(fun() -> <<X:32/float-native>> = <<2.0:32/float-native>>,
X end,
"begin <<X:32/float-native>> = <<2.0:32/float-native>>,
X end.",
2.0),
- ?line check(
+ check(
fun() ->
[X || <<"hej",X:8>> <= <<"hej",8,"san",9,"hej",17,"hej">>]
end,
"[X || <<\"hej\",X:8>> <=
<<\"hej\",8,\"san\",9,\"hej\",17,\"hej\">>].",
[8,17]),
- ?line check(
+ check(
fun() ->
L = 8, << <<B:32>> || <<L:L,B:L>> <= <<16:8, 7:16>> >>
end,
@@ -783,41 +734,41 @@ otp_6543(Config) when is_list(Config) ->
<<0,0,0,7>>),
%% Test the Value part of a binary segment.
%% "Old" bugs have been fixed (partial_eval is called on Value).
- ?line check(fun() -> [ 3 || <<17/float>> <= <<17.0/float>>] end,
+ check(fun() -> [ 3 || <<17/float>> <= <<17.0/float>>] end,
"[ 3 || <<17/float>> <= <<17.0/float>>].",
[3]),
- ?line check(fun() -> [ 3 || <<17/float>> <- [<<17.0/float>>]] end,
+ check(fun() -> [ 3 || <<17/float>> <- [<<17.0/float>>]] end,
"[ 3 || <<17/float>> <- [<<17.0/float>>]].",
[3]),
- ?line check(fun() -> [ X || <<17/float,X:3>> <= <<17.0/float,2:3>>] end,
+ check(fun() -> [ X || <<17/float,X:3>> <= <<17.0/float,2:3>>] end,
"[ X || <<17/float,X:3>> <= <<17.0/float,2:3>>].",
[2]),
- ?line check(fun() ->
+ check(fun() ->
[ foo || <<(1 bsl 1023)/float>> <= <<(1 bsl 1023)/float>>]
end,
"[ foo || <<(1 bsl 1023)/float>> <= <<(1 bsl 1023)/float>>].",
[foo]),
- ?line check(fun() ->
+ check(fun() ->
[ foo || <<(1 bsl 1023)/float>> <- [<<(1 bsl 1023)/float>>]]
end,
"[ foo || <<(1 bsl 1023)/float>> <- [<<(1 bsl 1023)/float>>]].",
[foo]),
- ?line error_check("[ foo || <<(1 bsl 1024)/float>> <-
+ error_check("[ foo || <<(1 bsl 1024)/float>> <-
[<<(1 bsl 1024)/float>>]].",
badarg),
- ?line check(fun() ->
+ check(fun() ->
[ foo || <<(1 bsl 1024)/float>> <- [<<(1 bsl 1023)/float>>]]
end,
"[ foo || <<(1 bsl 1024)/float>> <-
[<<(1 bsl 1023)/float>>]].",
[]),
- ?line check(fun() ->
+ check(fun() ->
[ foo || <<(1 bsl 1024)/float>> <= <<(1 bsl 1023)/float>>]
end,
"[ foo || <<(1 bsl 1024)/float>> <=
<<(1 bsl 1023)/float>>].",
[]),
- ?line check(fun() ->
+ check(fun() ->
L = 8,
[{L,B} || <<L:L,B:L/float>> <= <<32:8,7:32/float>>]
end,
@@ -825,7 +776,7 @@ otp_6543(Config) when is_list(Config) ->
[{L,B} || <<L:L,B:L/float>> <= <<32:8,7:32/float>>]
end.",
[{32,7.0}]),
- ?line check(fun() ->
+ check(fun() ->
L = 8,
[{L,B} || <<L:L,B:L/float>> <- [<<32:8,7:32/float>>]]
end,
@@ -833,127 +784,117 @@ otp_6543(Config) when is_list(Config) ->
[{L,B} || <<L:L,B:L/float>> <- [<<32:8,7:32/float>>]]
end.",
[{32,7.0}]),
- ?line check(fun() ->
+ check(fun() ->
[foo || <<"s">> <= <<"st">>]
end,
"[foo || <<\"s\">> <= <<\"st\">>].",
[foo]),
- ?line check(fun() -> <<_:32>> = <<17:32>> end,
+ check(fun() -> <<_:32>> = <<17:32>> end,
"<<_:32>> = <<17:32>>.",
<<17:32>>),
- ?line check(fun() -> [foo || <<_:32>> <= <<17:32,20:32>>] end,
+ check(fun() -> [foo || <<_:32>> <= <<17:32,20:32>>] end,
"[foo || <<_:32>> <= <<17:32,20:32>>].",
[foo,foo]),
- ?line check(fun() -> << <<X:32>> || X <- [1,2,3], X > 1 >> end,
+ check(fun() -> << <<X:32>> || X <- [1,2,3], X > 1 >> end,
"<< <<X:32>> || X <- [1,2,3], X > 1 >>.",
<<0,0,0,2,0,0,0,3>>),
- ?line error_check("[X || <<X>> <= [a,b]].",{bad_generator,[a,b]}),
+ error_check("[X || <<X>> <= [a,b]].",{bad_generator,[a,b]}),
ok.
-otp_6787(doc) ->
- ["OTP-6787. bitlevel binaries."];
-otp_6787(suite) ->
- [];
+%% OTP-6787. bitlevel binaries.
otp_6787(Config) when is_list(Config) ->
- ?line check(
+ check(
fun() -> <<16:(1024*1024)>> = <<16:(1024*1024)>> end,
"<<16:(1024*1024)>> = <<16:(1024*1024)>>.",
<<16:1048576>>),
ok.
-otp_6977(doc) ->
- ["OTP-6977. ++ bug."];
-otp_6977(suite) ->
- [];
+%% OTP-6977. ++ bug.
otp_6977(Config) when is_list(Config) ->
- ?line check(
+ check(
fun() -> (fun([$X] ++ _) -> ok end)("X") end,
"(fun([$X] ++ _) -> ok end)(\"X\").",
ok),
ok.
-otp_7550(doc) ->
- ["OTP-7550. Support for UTF-8, UTF-16, UTF-32."];
+%% OTP-7550. Support for UTF-8, UTF-16, UTF-32.
otp_7550(Config) when is_list(Config) ->
%% UTF-8.
- ?line check(
+ check(
fun() -> <<65>> = <<65/utf8>> end,
"<<65>> = <<65/utf8>>.",
<<65>>),
- ?line check(
+ check(
fun() -> <<350/utf8>> = <<197,158>> end,
"<<350/utf8>> = <<197,158>>.",
<<197,158>>),
- ?line check(
+ check(
fun() -> <<$b,$j,$\303,$\266,$r,$n>> = <<"bj\366rn"/utf8>> end,
"<<$b,$j,$\303,$\266,$r,$n>> = <<\"bj\366rn\"/utf8>>.",
<<$b,$j,$\303,$\266,$r,$n>>),
%% UTF-16.
- ?line check(
+ check(
fun() -> <<0,65>> = <<65/utf16>> end,
"<<0,65>> = <<65/utf16>>.",
<<0,65>>),
- ?line check(
+ check(
fun() -> <<16#D8,16#08,16#DF,16#45>> = <<16#12345/utf16>> end,
"<<16#D8,16#08,16#DF,16#45>> = <<16#12345/utf16>>.",
<<16#D8,16#08,16#DF,16#45>>),
- ?line check(
+ check(
fun() -> <<16#08,16#D8,16#45,16#DF>> = <<16#12345/little-utf16>> end,
"<<16#08,16#D8,16#45,16#DF>> = <<16#12345/little-utf16>>.",
<<16#08,16#D8,16#45,16#DF>>),
- ?line check(
+ check(
fun() -> <<350/utf16>> = <<1,94>> end,
"<<350/utf16>> = <<1,94>>.",
<<1,94>>),
- ?line check(
+ check(
fun() -> <<350/little-utf16>> = <<94,1>> end,
"<<350/little-utf16>> = <<94,1>>.",
<<94,1>>),
- ?line check(
+ check(
fun() -> <<16#12345/utf16>> = <<16#D8,16#08,16#DF,16#45>> end,
"<<16#12345/utf16>> = <<16#D8,16#08,16#DF,16#45>>.",
<<16#D8,16#08,16#DF,16#45>>),
- ?line check(
+ check(
fun() -> <<16#12345/little-utf16>> = <<16#08,16#D8,16#45,16#DF>> end,
"<<16#12345/little-utf16>> = <<16#08,16#D8,16#45,16#DF>>.",
<<16#08,16#D8,16#45,16#DF>>),
%% UTF-32.
- ?line check(
+ check(
fun() -> <<16#12345/utf32>> = <<16#0,16#01,16#23,16#45>> end,
"<<16#12345/utf32>> = <<16#0,16#01,16#23,16#45>>.",
<<16#0,16#01,16#23,16#45>>),
- ?line check(
+ check(
fun() -> <<16#0,16#01,16#23,16#45>> = <<16#12345/utf32>> end,
"<<16#0,16#01,16#23,16#45>> = <<16#12345/utf32>>.",
<<16#0,16#01,16#23,16#45>>),
- ?line check(
+ check(
fun() -> <<16#12345/little-utf32>> = <<16#45,16#23,16#01,16#00>> end,
"<<16#12345/little-utf32>> = <<16#45,16#23,16#01,16#00>>.",
<<16#45,16#23,16#01,16#00>>),
- ?line check(
+ check(
fun() -> <<16#12345/little-utf32>> end,
"<<16#12345/little-utf32>>.",
<<16#45,16#23,16#01,16#00>>),
%% Mixed.
- ?line check(
+ check(
fun() -> <<16#41,16#12345/utf32,16#0391:16,16#2E:8>> end,
"<<16#41,16#12345/utf32,16#0391:16,16#2E:8>>.",
<<16#41,16#00,16#01,16#23,16#45,16#03,16#91,16#2E>>),
ok.
-otp_8133(doc) ->
- ["OTP-8133. Bit comprehension bug."];
-otp_8133(suite) ->
- [];
+%% OTP-8133. Bit comprehension bug.
otp_8133(Config) when is_list(Config) ->
- ?line check(
+ check(
fun() ->
E = fun(N) ->
if
@@ -976,7 +917,7 @@ otp_8133(Config) when is_list(Config) ->
end
end.",
ok),
- ?line check(
+ check(
fun() ->
E = fun(N) ->
if
@@ -1002,10 +943,7 @@ otp_8133(Config) when is_list(Config) ->
ok),
ok.
-otp_10622(doc) ->
- ["OTP-10622. Bugs."];
-otp_10622(suite) ->
- [];
+%% OTP-10622. Bugs.
otp_10622(Config) when is_list(Config) ->
check(fun() -> <<0>> = <<"\x{400}">> end,
"<<0>> = <<\"\\x{400}\">>. ",
@@ -1044,51 +982,47 @@ otp_10622(Config) when is_list(Config) ->
ok.
-otp_13228(doc) ->
- ["OTP-13228. ERL-32: non-local function handler bug."];
+%% OTP-13228. ERL-32: non-local function handler bug.
otp_13228(_Config) ->
LFH = {value, fun(foo, [io_fwrite]) -> worked end},
EFH = {value, fun({io, fwrite}, [atom]) -> io_fwrite end},
{value, worked, []} = parse_and_run("foo(io:fwrite(atom)).", LFH, EFH).
-funs(doc) ->
- ["Simple cases, just to cover some code."];
-funs(suite) ->
- [];
+%% Simple cases, just to cover some code.
funs(Config) when is_list(Config) ->
do_funs(none, none),
do_funs(lfh(), none),
do_funs(lfh(), efh()),
- ?line error_check("nix:foo().", {access_not_allowed,nix}, lfh(), efh()),
- ?line error_check("bar().", undef, none, none),
+ error_check("nix:foo().", {access_not_allowed,nix}, lfh(), efh()),
+ error_check("bar().", undef, none, none),
- ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
+ check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
F1(F1, 1000) end,
"begin F1 = fun(F,N) -> count_down(F, N) end,"
"F1(F1,1000) end.",
0, ['F1'], lfh(), none),
- ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
+ check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
F1(F1, 1000) end,
"begin F1 = fun(F,N) -> count_down(F, N) end,"
"F1(F1,1000) end.",
0, ['F1'], lfh_value(), none),
- ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
+ check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
F1(F1, 1000) end,
"begin F1 = fun(F,N) -> count_down(F, N) end,"
"F1(F1,1000) end.",
0, ['F1'], lfh_value_extra(), none),
- ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
+ check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
F1(F1, 1000) end,
"begin F1 = fun(F,N) -> count_down(F, N) end,"
"F1(F1,1000) end.",
0, ['F1'], {?MODULE,local_func_value}, none),
%% This is not documented, and only for backward compatibility (good!).
B0 = erl_eval:new_bindings(),
- ?line check(fun() -> is_function(?MODULE:count_down_fun()) end,
+ check(fun() -> is_function(?MODULE:count_down_fun()) end,
"begin is_function(count_down_fun()) end.",
true, [], {?MODULE,local_func,[B0]},none),
@@ -1096,19 +1030,19 @@ funs(Config) when is_list(Config) ->
({M,F}, As) -> apply(M, F, As)
end,
EFH = {value, EF},
- ?line error_check("apply(timer, sleep, [1]).", got_it, none, EFH),
- ?line error_check("begin F = fun(T) -> timer:sleep(T) end,F(1) end.",
+ error_check("apply(timer, sleep, [1]).", got_it, none, EFH),
+ error_check("begin F = fun(T) -> timer:sleep(T) end,F(1) end.",
got_it, none, EFH),
- ?line error_check("fun c/1.", undef),
- ?line error_check("fun a:b/0().", undef),
+ error_check("fun c/1.", undef),
+ error_check("fun a:b/0().", undef),
MaxArgs = 20,
- ?line [true] =
+ [true] =
lists:usort([run_many_args(SAs) || SAs <- many_args(MaxArgs)]),
- ?line {'EXIT',{{argument_limit,_},_}} =
+ {'EXIT',{{argument_limit,_},_}} =
(catch run_many_args(many_args1(MaxArgs+1))),
- ?line check(fun() -> M = lists, F = fun M:reverse/1,
+ check(fun() -> M = lists, F = fun M:reverse/1,
[1,2] = F([2,1]), ok end,
"begin M = lists, F = fun M:reverse/1,"
" [1,2] = F([2,1]), ok end.",
@@ -1142,17 +1076,17 @@ do_funs(LFH, EFH) ->
%% manually with 1000 replaced by 1000000.
M = atom_to_list(?MODULE),
- ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
+ check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
F1(F1, 1000) end,
concat(["begin F1 = fun(F,N) -> ", M,
":count_down(F, N) end, F1(F1,1000) end."]),
0, ['F1'], LFH, EFH),
- ?line check(fun() -> F1 = fun(F,N) -> apply(?MODULE,count_down,[F,N])
+ check(fun() -> F1 = fun(F,N) -> apply(?MODULE,count_down,[F,N])
end, F1(F1, 1000) end,
concat(["begin F1 = fun(F,N) -> apply(", M,
",count_down,[F, N]) end, F1(F1,1000) end."]),
0, ['F1'], LFH, EFH),
- ?line check(fun() -> F = fun(F,N) when N > 0 -> apply(F,[F,N-1]);
+ check(fun() -> F = fun(F,N) when N > 0 -> apply(F,[F,N-1]);
(_F,0) -> ok end,
F(F, 1000)
end,
@@ -1160,7 +1094,7 @@ do_funs(LFH, EFH) ->
"(_F,0) -> ok end,"
"F(F, 1000) end.",
ok, ['F'], LFH, EFH),
- ?line check(fun() -> F = fun(F,N) when N > 0 ->
+ check(fun() -> F = fun(F,N) when N > 0 ->
apply(erlang,apply,[F,[F,N-1]]);
(_F,0) -> ok end,
F(F, 1000)
@@ -1170,7 +1104,7 @@ do_funs(LFH, EFH) ->
"(_F,0) -> ok end,"
"F(F, 1000) end.",
ok, ['F'], LFH, EFH),
- ?line check(fun() -> F = count_down_fun(),
+ check(fun() -> F = count_down_fun(),
SF = fun(SF, F1, N) -> F(SF, F1, N) end,
SF(SF, F, 1000) end,
concat(["begin F = ", M, ":count_down_fun(),"
@@ -1179,7 +1113,7 @@ do_funs(LFH, EFH) ->
ok, ['F','SF'], LFH, EFH),
- ?line check(fun() -> F = fun(X) -> A = 1+X, {X,A} end,
+ check(fun() -> F = fun(X) -> A = 1+X, {X,A} end,
true = {2,3} == F(2) end,
"begin F = fun(X) -> A = 1+X, {X,A} end,
true = {2,3} == F(2) end.", true, ['F'], LFH, EFH),
@@ -1188,13 +1122,13 @@ do_funs(LFH, EFH) ->
"begin F = fun(X) -> erlang:'+'(X,2) end,"
" true = 3 == F(1) end.", true, ['F'],
LFH, EFH),
- ?line check(fun() -> F = fun(X) -> byte_size(X) end,
+ check(fun() -> F = fun(X) -> byte_size(X) end,
?MODULE:do_apply(F,<<"hej">>) end,
concat(["begin F = fun(X) -> size(X) end,",
M,":do_apply(F,<<\"hej\">>) end."]),
3, ['F'], LFH, EFH),
- ?line check(fun() -> F1 = fun(X, Z) -> {X,Z} end,
+ check(fun() -> F1 = fun(X, Z) -> {X,Z} end,
Z = 5,
F2 = fun(X, Y) -> F1(Z,{X,Y}) end,
F3 = fun(X, Y) -> {a,F1(Z,{X,Y})} end,
@@ -1211,26 +1145,26 @@ do_funs(LFH, EFH) ->
{5,{5,y}} = F2(Z,y),
true = {5,{x,5}} == F2(x,Z) end.",
true, ['F1','Z','F2','F3'], LFH, EFH),
- ?line check(fun() -> F = fun(X) -> byte_size(X) end,
+ check(fun() -> F = fun(X) -> byte_size(X) end,
F2 = fun(Y) -> F(Y) end,
?MODULE:do_apply(F2,<<"hej">>) end,
concat(["begin F = fun(X) -> size(X) end,",
"F2 = fun(Y) -> F(Y) end,",
M,":do_apply(F2,<<\"hej\">>) end."]),
3, ['F','F2'], LFH, EFH),
- ?line check(fun() -> Z = 5, F = fun(X) -> {Z,X} end,
+ check(fun() -> Z = 5, F = fun(X) -> {Z,X} end,
F2 = fun(Z) -> F(Z) end, F2(3) end,
"begin Z = 5, F = fun(X) -> {Z,X} end,
F2 = fun(Z) -> F(Z) end, F2(3) end.",
{5,3},['F','F2','Z'], LFH, EFH),
- ?line check(fun() -> F = fun(Z) -> Z end,
+ check(fun() -> F = fun(Z) -> Z end,
F2 = fun(X) -> F(X), Z = {X,X}, Z end,
{1,1} = F2(1), Z = 7, Z end,
"begin F = fun(Z) -> Z end,
F2 = fun(X) -> F(X), Z = {X,X}, Z end,
{1,1} = F2(1), Z = 7, Z end.", 7, ['F','F2','Z'],
LFH, EFH),
- ?line check(fun() -> F = fun(F, N) -> [?MODULE:count_down(F,N) || X <-[1]]
+ check(fun() -> F = fun(F, N) -> [?MODULE:count_down(F,N) || X <-[1]]
end, F(F,2) end,
concat(["begin F = fun(F, N) -> [", M,
":count_down(F,N) || X <-[1]] end, F(F,2) end."]),
@@ -1289,45 +1223,42 @@ external_func({M,F}, As) ->
-try_catch(doc) ->
- ["Test try-of-catch-after-end statement"];
-try_catch(suite) ->
- [];
+%% Test try-of-catch-after-end statement.
try_catch(Config) when is_list(Config) ->
%% Match in of with catch
- ?line check(fun() -> try 1 of 1 -> 2 catch _:_ -> 3 end end,
+ check(fun() -> try 1 of 1 -> 2 catch _:_ -> 3 end end,
"try 1 of 1 -> 2 catch _:_ -> 3 end.", 2),
- ?line check(fun() -> try 1 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end end,
+ check(fun() -> try 1 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end end,
"try 1 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end.", 2),
- ?line check(fun() -> try 3 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end end,
+ check(fun() -> try 3 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end end,
"try 3 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end.", 4),
%% Just after
- ?line check(fun () -> X = try 1 after put(try_catch, 2) end,
+ check(fun () -> X = try 1 after put(try_catch, 2) end,
{X,get(try_catch)} end,
"begin X = try 1 after put(try_catch, 2) end, "
"{X,get(try_catch)} end.", {1,2}),
%% Match in of with after
- ?line check(fun() -> X = try 1 of 1 -> 2 after put(try_catch, 3) end,
+ check(fun() -> X = try 1 of 1 -> 2 after put(try_catch, 3) end,
{X,get(try_catch)} end,
"begin X = try 1 of 1 -> 2 after put(try_catch, 3) end, "
"{X,get(try_catch)} end.", {2,3}),
- ?line check(fun() -> X = try 1 of 1 -> 2; 3 -> 4
+ check(fun() -> X = try 1 of 1 -> 2; 3 -> 4
after put(try_catch, 5) end,
{X,get(try_catch)} end,
"begin X = try 1 of 1 -> 2; 3 -> 4 "
" after put(try_catch, 5) end, "
" {X,get(try_catch)} end.", {2,5}),
- ?line check(fun() -> X = try 3 of 1 -> 2; 3 -> 4
+ check(fun() -> X = try 3 of 1 -> 2; 3 -> 4
after put(try_catch, 5) end,
{X,get(try_catch)} end,
"begin X = try 3 of 1 -> 2; 3 -> 4 "
" after put(try_catch, 5) end, "
" {X,get(try_catch)} end.", {4,5}),
%% Nomatch in of
- ?line error_check("try 1 of 2 -> 3 catch _:_ -> 4 end.",
+ error_check("try 1 of 2 -> 3 catch _:_ -> 4 end.",
{try_clause,1}),
%% Nomatch in of with after
- ?line check(fun () -> {'EXIT',{{try_clause,1},_}} =
+ check(fun () -> {'EXIT',{{try_clause,1},_}} =
begin catch try 1 of 2 -> 3
after put(try_catch, 4) end end,
get(try_catch) end,
@@ -1336,14 +1267,14 @@ try_catch(Config) when is_list(Config) ->
" after put(try_catch, 4) end end, "
" get(try_catch) end. ", 4),
%% Exception in try
- ?line check(fun () -> try 1=2 catch error:{badmatch,2} -> 3 end end,
+ check(fun () -> try 1=2 catch error:{badmatch,2} -> 3 end end,
"try 1=2 catch error:{badmatch,2} -> 3 end.", 3),
- ?line check(fun () -> try 1=2 of 3 -> 4
+ check(fun () -> try 1=2 of 3 -> 4
catch error:{badmatch,2} -> 5 end end,
"try 1=2 of 3 -> 4 "
"catch error:{badmatch,2} -> 5 end.", 5),
%% Exception in try with after
- ?line check(fun () -> X = try 1=2
+ check(fun () -> X = try 1=2
catch error:{badmatch,2} -> 3
after put(try_catch, 4) end,
{X,get(try_catch)} end,
@@ -1351,7 +1282,7 @@ try_catch(Config) when is_list(Config) ->
" catch error:{badmatch,2} -> 3 "
" after put(try_catch, 4) end, "
" {X,get(try_catch)} end. ", {3,4}),
- ?line check(fun () -> X = try 1=2 of 3 -> 4
+ check(fun () -> X = try 1=2 of 3 -> 4
catch error:{badmatch,2} -> 5
after put(try_catch, 6) end,
{X,get(try_catch)} end,
@@ -1360,12 +1291,12 @@ try_catch(Config) when is_list(Config) ->
" after put(try_catch, 6) end, "
" {X,get(try_catch)} end. ", {5,6}),
%% Uncaught exception
- ?line error_check("try 1=2 catch error:undefined -> 3 end. ",
+ error_check("try 1=2 catch error:undefined -> 3 end. ",
{badmatch,2}),
- ?line error_check("try 1=2 of 3 -> 4 catch error:undefined -> 5 end. ",
+ error_check("try 1=2 of 3 -> 4 catch error:undefined -> 5 end. ",
{badmatch,2}),
%% Uncaught exception with after
- ?line check(fun () -> {'EXIT',{{badmatch,2},_}} =
+ check(fun () -> {'EXIT',{{badmatch,2},_}} =
begin catch try 1=2
after put(try_catch, 3) end end,
get(try_catch) end,
@@ -1373,7 +1304,7 @@ try_catch(Config) when is_list(Config) ->
" begin catch try 1=2 "
" after put(try_catch, 3) end end, "
" get(try_catch) end. ", 3),
- ?line check(fun () -> {'EXIT',{{badmatch,2},_}} =
+ check(fun () -> {'EXIT',{{badmatch,2},_}} =
begin catch try 1=2 of 3 -> 4
after put(try_catch, 5) end end,
get(try_catch) end,
@@ -1381,7 +1312,7 @@ try_catch(Config) when is_list(Config) ->
" begin catch try 1=2 of 3 -> 4"
" after put(try_catch, 5) end end, "
" get(try_catch) end. ", 5),
- ?line check(fun () -> {'EXIT',{{badmatch,2},_}} =
+ check(fun () -> {'EXIT',{{badmatch,2},_}} =
begin catch try 1=2 catch error:undefined -> 3
after put(try_catch, 4) end end,
get(try_catch) end,
@@ -1389,7 +1320,7 @@ try_catch(Config) when is_list(Config) ->
" begin catch try 1=2 catch error:undefined -> 3 "
" after put(try_catch, 4) end end, "
" get(try_catch) end. ", 4),
- ?line check(fun () -> {'EXIT',{{badmatch,2},_}} =
+ check(fun () -> {'EXIT',{{badmatch,2},_}} =
begin catch try 1=2 of 3 -> 4
catch error:undefined -> 5
after put(try_catch, 6) end end,
@@ -1402,26 +1333,23 @@ try_catch(Config) when is_list(Config) ->
ok.
-eval_expr_5(doc) ->
- ["(OTP-7933)"];
-eval_expr_5(suite) ->
- [];
+%% OTP-7933.
eval_expr_5(Config) when is_list(Config) ->
- ?line {ok,Tokens ,_} =
+ {ok,Tokens ,_} =
erl_scan:string("if a+4 == 4 -> yes; true -> no end. "),
- ?line {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
- ?line {value, no, []} = erl_eval:expr(Expr, [], none, none, none),
- ?line no = erl_eval:expr(Expr, [], none, none, value),
+ {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
+ {value, no, []} = erl_eval:expr(Expr, [], none, none, none),
+ no = erl_eval:expr(Expr, [], none, none, value),
try
erl_eval:expr(Expr, [], none, none, 4711),
- ?line function_clause = should_never_reach_here
+ function_clause = should_never_reach_here
catch
error:function_clause ->
ok
end.
zero_width(Config) when is_list(Config) ->
- ?line check(fun() ->
+ check(fun() ->
{'EXIT',{badarg,_}} = (catch <<not_a_number:0>>),
ok
end, "begin {'EXIT',{badarg,_}} = (catch <<not_a_number:0>>), "
@@ -1524,7 +1452,7 @@ check1(F, String, Result) ->
{value, Result, _} ->
ok;
Other ->
- test_server:fail({eval, Other, Result})
+ ct:fail({eval, Other, Result})
end.
check(F, String, Result, BoundVars, LFH, EFH) ->
@@ -1537,11 +1465,11 @@ check(F, String, Result, BoundVars, LFH, EFH) ->
true ->
ok;
false ->
- test_server:fail({check, BoundVars, Keys})
+ ct:fail({check, BoundVars, Keys})
end,
ok;
Other ->
- test_server:fail({check, Other, Result})
+ ct:fail({check, Other, Result})
end.
error_check(String, Result) ->
@@ -1549,7 +1477,7 @@ error_check(String, Result) ->
{'EXIT', {Result,_}} ->
ok;
Other ->
- test_server:fail({eval, Other, Result})
+ ct:fail({eval, Other, Result})
end.
error_check(String, Result, LFH, EFH) ->
@@ -1557,7 +1485,7 @@ error_check(String, Result, LFH, EFH) ->
{'EXIT', {Result,_}} ->
ok;
Other ->
- test_server:fail({eval, Other, Result})
+ ct:fail({eval, Other, Result})
end.
eval_string(String) ->
diff --git a/lib/stdlib/test/erl_expand_records_SUITE.erl b/lib/stdlib/test/erl_expand_records_SUITE.erl
index 8cec445cb4..7fed7fce56 100644
--- a/lib/stdlib/test/erl_expand_records_SUITE.erl
+++ b/lib/stdlib/test/erl_expand_records_SUITE.erl
@@ -20,7 +20,7 @@
-module(erl_expand_records_SUITE).
-%-define(debug, true).
+%%-define(debug, true).
-ifdef(debug).
-define(line, put(line, ?LINE), ).
@@ -28,8 +28,8 @@
-define(privdir, "erl_expand_records_SUITE_priv").
-define(t, test_server).
-else.
--include_lib("test_server/include/test_server.hrl").
--define(privdir, ?config(priv_dir, Config)).
+-include_lib("common_test/include/ct.hrl").
+-define(privdir, proplists:get_value(priv_dir, Config)).
-endif.
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -41,19 +41,15 @@
otp_5915/1, otp_7931/1, otp_5990/1,
otp_7078/1, otp_7101/1, maps/1]).
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
-
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
+ Config.
end_per_testcase(_Case, _Config) ->
- Dog = ?config(watchdog, _Config),
- test_server:timetrap_cancel(Dog),
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[attributes, expr, guard, init,
@@ -76,30 +72,26 @@ end_per_group(_GroupName, Config) ->
Config.
-attributes(doc) ->
- "Import module and functions.";
-attributes(suite) -> [];
+%% Import module and functions.
attributes(Config) when is_list(Config) ->
Ts = [
- <<"-import(lists, [append/2, reverse/1]).
+ <<"-import(lists, [append/2, reverse/1]).
-record(r, {a,b}).
- t() ->
- [2,1] = reverse(append([1],[2])),
- 3 = length([1,2,3]),
- 3 = record_info(size, r),
- [a, b] = record_info(fields, r),
- [] = erl_expand_records_SUITE:attributes(suite),
- ok.
- ">>
+t() ->
+ [2,1] = reverse(append([1],[2])),
+ 3 = length([1,2,3]),
+ 3 = record_info(size, r),
+ [a, b] = record_info(fields, r),
+ [_|_] = erl_expand_records_SUITE:all(),
+ ok.
+">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-expr(doc) ->
- "Some expressions.";
-expr(suite) -> [];
+%% Some expressions.
expr(Config) when is_list(Config) ->
Ts = [
<<"
@@ -159,14 +151,12 @@ expr(Config) when is_list(Config) ->
%% The code above should run equally well with and without
%% strict record tests.
- ?line run(Config, Ts, [no_strict_record_tests]),
- ?line run(Config, Ts, [strict_record_tests]),
+ run(Config, Ts, [no_strict_record_tests]),
+ run(Config, Ts, [strict_record_tests]),
ok.
-guard(doc) ->
- "is_record in guards.";
-guard(suite) -> [];
+%% is_record in guards.
guard(Config) when is_list(Config) ->
File = filename("guard.erl", Config),
Beam = filename("guard.beam", Config),
@@ -202,18 +192,16 @@ guard(Config) when is_list(Config) ->
12.
">>,
- ?line ok = file:write_file(File, Test),
- ?line {ok, guard, Ws} = compile:file(File, [return,{outdir,?privdir}]),
- ?line Warnings = [L || {_File,WL} <- Ws, {L,_M,nomatch_guard} <- WL],
- ?line [7,9,11,13,15,17,19,21,23,25,27] = Warnings,
+ ok = file:write_file(File, Test),
+ {ok, guard, Ws} = compile:file(File, [return,{outdir,?privdir}]),
+ Warnings = [L || {_File,WL} <- Ws, {L,_M,nomatch_guard} <- WL],
+ [7,9,11,13,15,17,19,21,23,25,27] = Warnings,
- ?line ok = file:delete(File),
- ?line ok = file:delete(Beam),
+ ok = file:delete(File),
+ ok = file:delete(Beam),
ok.
-init(doc) ->
- "Wildcard initialisation.";
-init(suite) -> [];
+%% Wildcard initialisation.
init(Config) when is_list(Config) ->
Ts = [
<<"
@@ -228,12 +216,10 @@ init(Config) when is_list(Config) ->
end.
">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-pattern(doc) ->
- "Some patterns.";
-pattern(suite) -> [];
+%% Some patterns.
pattern(Config) when is_list(Config) ->
Ts = [
<<"-import(lists, [append/2, reverse/1]).
@@ -317,12 +303,9 @@ pattern(Config) when is_list(Config) ->
16.
">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-strict(doc) ->
- "";
-strict(suite) -> [];
strict(Config) when is_list(Config) ->
Ts1 = [
<<"-record(r1, {a,b}).
@@ -345,7 +328,7 @@ strict(Config) when is_list(Config) ->
error(wrong_element).
">>
],
- ?line run(Config, Ts1, [strict_record_tests]),
+ run(Config, Ts1, [strict_record_tests]),
Ts2 = [
<<"-record(r1, {a,b}).
@@ -361,12 +344,10 @@ strict(Config) when is_list(Config) ->
error(wrong_element).
">>
],
- ?line run(Config, Ts2, [no_strict_record_tests]),
+ run(Config, Ts2, [no_strict_record_tests]),
ok.
-update(doc) ->
- "Record updates.";
-update(suite) -> [];
+%% Record updates.
update(Config) when is_list(Config) ->
Ts = [
<<"-record(r, {a,b,c,d,e,f}).
@@ -401,7 +382,7 @@ update(Config) when is_list(Config) ->
erlang:error(wrong_setelement_called).
">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
maps(Config) when is_list(Config) ->
@@ -420,9 +401,7 @@ maps(Config) when is_list(Config) ->
run(Config, Ts, [strict_record_tests]),
ok.
-otp_5915(doc) ->
- "Strict record tests in guards.";
-otp_5915(suite) -> [];
+%% Strict record tests in guards.
otp_5915(Config) when is_list(Config) ->
%% These tests are also run by the compiler's record_SUITE.
Ts = [
@@ -565,12 +544,10 @@ otp_5915(Config) when is_list(Config) ->
ok.
">>
],
- ?line run(Config, Ts, [strict_record_tests]),
+ run(Config, Ts, [strict_record_tests]),
ok.
-otp_7931(doc) ->
- "Test optimization of record accesses and is_record/3 tests in guards";
-otp_7931(suite) -> [];
+%% Test optimization of record accesses and is_record/3 tests in guards.
otp_7931(Config) when is_list(Config) ->
Ts = [
<<"-record(r, {a = 4,b}).
@@ -654,12 +631,10 @@ otp_7931(Config) when is_list(Config) ->
ok.
">>
],
- ?line run(Config, Ts, [strict_record_tests]),
+ run(Config, Ts, [strict_record_tests]),
ok.
-otp_5990(doc) ->
- "OTP-5990. {erlang,is_record}.";
-otp_5990(suite) -> [];
+%% OTP-5990. {erlang,is_record}.
otp_5990(Config) when is_list(Config) ->
Ts = [
<<"
@@ -690,13 +665,11 @@ otp_5990(Config) when is_list(Config) ->
ok.
">>
],
- ?line run(Config, Ts, [strict_record_tests]),
+ run(Config, Ts, [strict_record_tests]),
ok.
-otp_7078(doc) ->
- "OTP-7078. Record update: missing test.";
-otp_7078(suite) -> [];
+%% OTP-7078. Record update: missing test.
otp_7078(Config) when is_list(Config) ->
Ts = [
<<"
@@ -724,14 +697,12 @@ otp_7078(Config) when is_list(Config) ->
">>
],
- ?line run(Config, Ts, [strict_record_tests]),
+ run(Config, Ts, [strict_record_tests]),
ok.
-record(otp_7101, {a,b,c=[],d=[],e=[]}).
-otp_7101(doc) ->
- "OTP-7101. Record update: more than one call to setelement/3.";
-otp_7101(suite) -> [];
+%% OTP-7101. Record update: more than one call to setelement/3.
otp_7101(Config) when is_list(Config) ->
Rec = #otp_7101{},
@@ -739,28 +710,28 @@ otp_7101(Config) when is_list(Config) ->
%% The tracer will forward all trace messages to us.
Self = self(),
Tracer = spawn_link(fun() -> otp_7101_tracer(Self, 0) end),
- ?line 1 = erlang:trace_pattern({erlang,setelement,3}, true),
- ?line erlang:trace(self(), true, [{tracer,Tracer},call]),
+ 1 = erlang:trace_pattern({erlang,setelement,3}, true),
+ erlang:trace(self(), true, [{tracer,Tracer},call]),
%% Update the record.
- ?line #otp_7101{a=2,b=1,c=[],d=[],e=[]} = otp_7101_update1(Rec),
- ?line #otp_7101{a=1,b=2,c=[],d=[],e=[]} = otp_7101_update2(Rec),
- ?line #otp_7101{a=2,b=1,c=[],d=[],e=[]} = otp_7101_update3(Rec),
- ?line #otp_7101{a=1,b=2,c=[],d=[],e=[]} = otp_7101_update4(Rec),
+ #otp_7101{a=2,b=1,c=[],d=[],e=[]} = otp_7101_update1(Rec),
+ #otp_7101{a=1,b=2,c=[],d=[],e=[]} = otp_7101_update2(Rec),
+ #otp_7101{a=2,b=1,c=[],d=[],e=[]} = otp_7101_update3(Rec),
+ #otp_7101{a=1,b=2,c=[],d=[],e=[]} = otp_7101_update4(Rec),
%% Verify that setelement/3 was called the same number of times as
%% the number of record updates.
- ?line Ref = erlang:trace_delivered(Self),
+ Ref = erlang:trace_delivered(Self),
receive
{trace_delivered, Self, Ref} ->
Tracer ! done
end,
- ?line 1 = erlang:trace_pattern({erlang,setelement,3}, false),
+ 1 = erlang:trace_pattern({erlang,setelement,3}, false),
receive
4 ->
ok;
Other ->
- ?line ?t:fail({unexpected,Other})
+ ct:fail({unexpected,Other})
end.
otp_7101_tracer(Parent, N) ->
@@ -797,10 +768,9 @@ run(Config, Tests, Opts) ->
AbsFile = filename:rootname(SourceFile, ".erl"),
code:purge(Mod),
code:load_abs(AbsFile, Mod),
-%io:format("run~n"),
case catch Mod:t() of
{'EXIT', _Reason} = Error ->
- ?t:format("failed, got ~p~n", [Error]),
+ io:format("failed, got ~p~n", [Error]),
fail();
ok ->
ok
@@ -837,5 +807,4 @@ warnings(File, Ws) ->
end.
fail() ->
- io:format("failed~n"),
- ?t:fail().
+ ct:fail(failed).
diff --git a/lib/stdlib/test/erl_internal_SUITE.erl b/lib/stdlib/test/erl_internal_SUITE.erl
index 0d2f535040..45e67226b7 100644
--- a/lib/stdlib/test/erl_internal_SUITE.erl
+++ b/lib/stdlib/test/erl_internal_SUITE.erl
@@ -26,9 +26,11 @@
-export([init_per_testcase/2, end_per_testcase/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,2}}].
all() ->
[behav].
@@ -49,20 +51,13 @@ end_per_group(_GroupName, Config) ->
Config.
--define(default_timeout, ?t:minutes(2)).
-
init_per_testcase(_Case, Config) ->
- Dog = test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
-behav(suite) -> [];
-behav(doc) ->
- ["Check that the behaviour callbacks are correctly defined"];
+%% Check that the behaviour callbacks are correctly defined.
behav(_) ->
Modules = [application, gen_server, gen_fsm, gen_event,
supervisor_bridge, supervisor],
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index 375fb6bc93..29a389d4b8 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(erl_lint_SUITE).
-%-define(debug, true).
+%%-define(debug, true).
-ifdef(debug).
-define(line, put(line, ?LINE), ).
@@ -28,9 +28,9 @@
-define(privdir, "erl_lint_SUITE_priv").
-define(t, test_server).
-else.
--include_lib("test_server/include/test_server.hrl").
--define(datadir, ?config(data_dir, Conf)).
--define(privdir, ?config(priv_dir, Conf)).
+-include_lib("common_test/include/ct.hrl").
+-define(datadir, proplists:get_value(data_dir, Conf)).
+-define(privdir, proplists:get_value(priv_dir, Conf)).
-endif.
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -65,22 +65,19 @@
too_many_arguments/1,
basic_errors/1,bin_syntax_errors/1,
predef/1,
- maps/1,maps_type/1,otp_11851/1,otp_12195/1, otp_13230/1
+ maps/1,maps_type/1,otp_11851/1,otp_11879/1,otp_13230/1,
+ record_errors/1
]).
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
-
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
+ Config.
end_per_testcase(_Case, _Config) ->
- Dog = ?config(watchdog, _Config),
- test_server:timetrap_cancel(Dog),
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[{group, unused_vars_warn}, export_vars_warn,
@@ -94,7 +91,8 @@ all() ->
bif_clash, behaviour_basic, behaviour_multiple, otp_11861,
otp_7550, otp_8051, format_warn, {group, on_load},
too_many_arguments, basic_errors, bin_syntax_errors, predef,
- maps, maps_type, otp_11851, otp_12195, otp_13230].
+ maps, maps_type, otp_11851, otp_11879, otp_13230,
+ record_errors].
groups() ->
[{unused_vars_warn, [],
@@ -117,50 +115,48 @@ end_per_group(_GroupName, Config) ->
-unused_vars_warn_basic(doc) ->
- "Warnings for unused variables in some simple cases.";
-unused_vars_warn_basic(suite) -> [];
+%% Warnings for unused variables in some simple cases.
unused_vars_warn_basic(Config) when is_list(Config) ->
Ts = [{basic1,
<<"f(F) -> % F unused.
ok.
- f(F, F) ->
- ok.
+f(F, F) ->
+ ok.
- g(_X) ->
- y.
+g(_X) ->
+ y.
- h(P) ->
- P.
+h(P) ->
+ P.
- x(N) ->
- case a:b() of
- [N|Y] -> % Y unused.
- ok
- end.
+x(N) ->
+ case a:b() of
+ [N|Y] -> % Y unused.
+ ok
+ end.
- y(N, L) ->
- lists:map(fun(T) -> T*N end, L).
+y(N, L) ->
+ lists:map(fun(T) -> T*N end, L).
- z(N, L) -> % N unused
- lists:map(fun(N, T) -> T*N end, L). % N shadowed.
+z(N, L) -> % N unused
+ lists:map(fun(N, T) -> T*N end, L). % N shadowed.
- c(A) ->
- case A of
- 1 -> B = []; % B unused.
- 2 -> B = []; % B unused.
- 3 -> B = f, B
- end.
- ">>,
+c(A) ->
+ case A of
+ 1 -> B = []; % B unused.
+ 2 -> B = []; % B unused.
+ 3 -> B = f, B
+ end.
+">>,
[warn_unused_vars],
- {warnings,[{1,erl_lint,{unused_var,'F'}},
- {15,erl_lint,{unused_var,'Y'}},
- {22,erl_lint,{unused_var,'N'}},
- {23,erl_lint,{shadowed_var,'N','fun'}},
- {28,erl_lint,{unused_var,'B'}},
- {29,erl_lint,{unused_var,'B'}}]}},
+{warnings,[{1,erl_lint,{unused_var,'F'}},
+ {15,erl_lint,{unused_var,'Y'}},
+ {22,erl_lint,{unused_var,'N'}},
+ {23,erl_lint,{shadowed_var,'N','fun'}},
+ {28,erl_lint,{unused_var,'B'}},
+ {29,erl_lint,{unused_var,'B'}}]}},
{basic2,
<<"-record(r, {x,y}).
f({X,Y}) -> {Z=X,Z=Y};
@@ -170,12 +166,10 @@ unused_vars_warn_basic(Config) when is_list(Config) ->
g({M, F, Arg}) -> (Z=M):F(Z=Arg).
h(X, Y) -> (Z=X) + (Z=Y).">>,
[warn_unused_vars], []}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-unused_vars_warn_lc(doc) ->
- "Warnings for unused variables in list comprehensions.";
-unused_vars_warn_lc(suite) -> [];
+%% Warnings for unused variables in list comprehensions.
unused_vars_warn_lc(Config) when is_list(Config) ->
Ts = [{lc1,
<<"bin([X]) ->
@@ -402,9 +396,7 @@ unused_vars_warn_lc(Config) when is_list(Config) ->
{error,[{22,erl_lint,{unsafe_var,'U',{'case',2}}},
{27,erl_lint,{unsafe_var,'U',{'case',2}}}],
[{16,erl_lint,{unused_var,'Y'}},
- % {24,erl_lint,{exported_var,'X',{'case',8}}},
{24,erl_lint,{unused_var,'U'}},
- % {26,erl_lint,{exported_var,'X',{'case',8}}},
{26,erl_lint,{unused_var,'U'}}]}},
{lc17,
@@ -434,7 +426,6 @@ unused_vars_warn_lc(Config) when is_list(Config) ->
[warn_unused_vars],
{error,[{22,erl_lint,{unsafe_var,'U',{'case',3}}}],
[{17,erl_lint,{unused_var,'Y'}},
- % {21,erl_lint,{exported_var,'X',{'case',9}}},
{21,erl_lint,{unused_var,'U'}}]}},
{lc18,
@@ -459,14 +450,12 @@ unused_vars_warn_lc(Config) when is_list(Config) ->
end,
[B || <<U: % U unused
U>> <- X, <<B:Y>> <- Z]. % U unsafe. Y unsafe.
- % U shadowed. (X exported.)
+ % U shadowed. (X exported.)
">>,
[warn_unused_vars],
{error,[{21,erl_lint,{unsafe_var,'U',{'case',2}}},
{21,erl_lint,{unsafe_var,'Y',{'case',14}}}],
[{20,erl_lint,{unused_var,'U'}}
- % ,{21,erl_lint,{exported_var,'X',{'case',8}}}
- % ,{21,erl_lint,{shadowed_var,'U',generate}}
]}},
{lc19,
@@ -520,13 +509,11 @@ unused_vars_warn_lc(Config) when is_list(Config) ->
[{14,erl_lint,{unused_var,'Q'}}]}}
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-unused_vars_warn_rec(doc) ->
- "Warnings for unused variables in records.";
-unused_vars_warn_rec(suite) -> [];
+%% Warnings for unused variables in records.
unused_vars_warn_rec(Config) when is_list(Config) ->
Ts = [{rec1, % An example provided by Bjorn.
<<"-record(edge,
@@ -578,12 +565,10 @@ unused_vars_warn_rec(Config) when is_list(Config) ->
{error,[{2,erl_lint,{redefine_field,r,a}},
{2,erl_lint,{redefine_field,r,a}}],
[{2,erl_lint,{unused_var,'X'}}]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-unused_vars_warn_fun(doc) ->
- "Warnings for unused variables in funs.";
-unused_vars_warn_fun(suite) -> [];
+%% Warnings for unused variables in funs.
unused_vars_warn_fun(Config) when is_list(Config) ->
Ts = [{fun1,
<<"a({A,B}) -> % A unused.
@@ -705,12 +690,10 @@ unused_vars_warn_fun(Config) when is_list(Config) ->
{33,erl_lint,{unused_var,'U'}},
{33,erl_lint,{shadowed_var,'U','fun'}}]}}
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-unused_vars_OTP_4858(doc) ->
- "Bit syntax, binsize variable used in the same matching.";
-unused_vars_OTP_4858(suite) -> [];
+%% Bit syntax, binsize variable used in the same matching.
unused_vars_OTP_4858(Config) when is_list(Config) ->
Ts = [{otp_4858,
<<"objs(<<Size:4/unit:8, B:Size/binary>>) ->
@@ -729,7 +712,7 @@ unused_vars_OTP_4858(Config) when is_list(Config) ->
{8,erl_lint,{unused_var,'B'}},
{8,erl_lint,{unused_var,'Rest'}}]}}
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
unused_unsafe_vars_warn(Config) when is_list(Config) ->
@@ -774,9 +757,7 @@ unused_unsafe_vars_warn(Config) when is_list(Config) ->
run(Config, Ts),
ok.
-export_vars_warn(doc) ->
- "Warnings for exported variables";
-export_vars_warn(suite) -> [];
+%% Warnings for exported variables.
export_vars_warn(Config) when is_list(Config) ->
Ts = [{exp1,
<<"u() ->
@@ -866,13 +847,11 @@ export_vars_warn(Config) when is_list(Config) ->
[],
{warnings,[{7,erl_lint,{exported_var,'Z',{'if',2}}}]}}
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-shadow_vars(doc) ->
- "Shadowed variables are tested in other places, but here we test "
- "that the warning can be turned off.";
-shadow_vars(suite) -> [];
+%% Shadowed variables are tested in other places, but here we test
+%% that the warning can be turned off.
shadow_vars(Config) when is_list(Config) ->
Ts = [{shadow1,
<<"bin(A) ->
@@ -897,12 +876,10 @@ shadow_vars(Config) when is_list(Config) ->
">>,
[],
[]}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-unused_import(doc) ->
- "Test that the 'warn_unused_import' option works.";
-unused_import(suite) -> [];
+%% Test that the 'warn_unused_import' option works.
unused_import(Config) when is_list(Config) ->
Ts = [{imp1,
<<"-import(lists, [map/2,foldl/3]).
@@ -911,12 +888,10 @@ unused_import(Config) when is_list(Config) ->
">>,
[warn_unused_import],
{warnings,[{1,erl_lint,{unused_import,{{foldl,3},lists}}}]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-unused_function(doc) ->
- "Test warnings for unused functions.";
-unused_function(suite) -> [];
+%% Test warnings for unused functions.
unused_function(Config) when is_list(Config) ->
Ts = [{func1,
<<"-export([t/1]).
@@ -959,12 +934,10 @@ unused_function(Config) when is_list(Config) ->
{[]}, %Tuple indicates no 'export_all'.
[]}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-unsafe_vars(doc) ->
- "OTP-4671. Errors for unsafe variables";
-unsafe_vars(suite) -> [];
+%% OTP-4671. Errors for unsafe variables.
unsafe_vars(Config) when is_list(Config) ->
Ts = [{unsafe1,
<<"t() ->
@@ -1040,7 +1013,7 @@ unsafe_vars(Config) when is_list(Config) ->
D = 1;
2 ->
A = 2,
- % B not bound here
+ %% B not bound here
C = 2,
catch D = 2; % unsafe in two clauses
3 ->
@@ -1062,12 +1035,10 @@ unsafe_vars(Config) when is_list(Config) ->
{24,erl_lint,{unsafe_var,'D',{'case',2}}}],
[]}}
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-unsafe_vars2(doc) ->
- "OTP-4831, seq8202. No warn_unused_vars and unsafe variables";
-unsafe_vars2(suite) -> [];
+%% OTP-4831, seq8202. No warn_unused_vars and unsafe variables.
unsafe_vars2(Config) when is_list(Config) ->
Ts = [{unsafe2_1,
<<"foo(State) ->
@@ -1096,12 +1067,10 @@ unsafe_vars2(Config) when is_list(Config) ->
[],
{errors,[{9,erl_lint,{unsafe_var,'State1',{'if',4}}}],[]}}
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-unsafe_vars_try(doc) ->
- "Errors for unsafe variables in try/catch constructs.";
-unsafe_vars_try(suite) -> [];
+%% Errors for unsafe variables in try/catch constructs.
unsafe_vars_try(Config) when is_list(Config) ->
Ts = [{unsafe_try1,
<<"foo2() ->
@@ -1286,22 +1255,24 @@ unsafe_vars_try(Config) when is_list(Config) ->
">>,
[],
{errors,[{13,erl_lint,{unsafe_var,'Acc',{'try',6}}}],[]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-unsized_binary_in_bin_gen_pattern(doc) ->
- "Unsized binary fields are forbidden in patterns of bit string generators";
-unsized_binary_in_bin_gen_pattern(suite) -> [];
+%% Unsized binary fields are forbidden in patterns of bit string generators.
unsized_binary_in_bin_gen_pattern(Config) when is_list(Config) ->
Ts = [{unsized_binary_in_bin_gen_pattern,
<<"t({bc,binary,Bin}) ->
<< <<X,Tail/binary>> || <<X,Tail/binary>> <= Bin >>;
+ t({bc,bytes,Bin}) ->
+ << <<X,Tail/binary>> || <<X,Tail/bytes>> <= Bin >>;
t({bc,bits,Bin}) ->
<< <<X,Tail/bits>> || <<X,Tail/bits>> <= Bin >>;
t({bc,bitstring,Bin}) ->
<< <<X,Tail/bits>> || <<X,Tail/bitstring>> <= Bin >>;
t({lc,binary,Bin}) ->
[ {X,Tail} || <<X,Tail/binary>> <= Bin ];
+ t({lc,bytes,Bin}) ->
+ [ {X,Tail} || <<X,Tail/bytes>> <= Bin ];
t({lc,bits,Bin}) ->
[ {X,Tail} || <<X,Tail/bits>> <= Bin ];
t({lc,bitstring,Bin}) ->
@@ -1313,14 +1284,14 @@ unsized_binary_in_bin_gen_pattern(Config) when is_list(Config) ->
{6,erl_lint,unsized_binary_in_bin_gen_pattern},
{8,erl_lint,unsized_binary_in_bin_gen_pattern},
{10,erl_lint,unsized_binary_in_bin_gen_pattern},
- {12,erl_lint,unsized_binary_in_bin_gen_pattern}],
+ {12,erl_lint,unsized_binary_in_bin_gen_pattern},
+ {14,erl_lint,unsized_binary_in_bin_gen_pattern},
+ {16,erl_lint,unsized_binary_in_bin_gen_pattern}],
[]}}],
[] = run(Config, Ts),
ok.
-guard(doc) ->
- "OTP-4670. Guards, is_record in particular.";
-guard(suite) -> [];
+%% OTP-4670. Guards, is_record in particular.
guard(Config) when is_list(Config) ->
%% Well, these could be plain code...
Ts = [{guard1,
@@ -1535,7 +1506,7 @@ guard(Config) when is_list(Config) ->
">>,
[nowarn_obsolete_guard],
[]}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
Ts1 = [{guard5,
<<"-record(apa, {}).
t3(A) when record(A, {apa}) ->
@@ -1606,12 +1577,10 @@ guard(Config) when is_list(Config) ->
{2,erl_lint,illegal_guard_expr}],
[]}}
],
- ?line [] = run(Config, Ts1),
+ [] = run(Config, Ts1),
ok.
-otp_4886(doc) ->
- "OTP-4886. Calling is_record with given record name.";
-otp_4886(suite) -> [];
+%% OTP-4886. Calling is_record with given record name.
otp_4886(Config) when is_list(Config) ->
Ts = [{otp_4886,
<<"t() ->
@@ -1630,12 +1599,10 @@ otp_4886(Config) when is_list(Config) ->
{4,erl_lint,{undefined_record,foo}},
{5,erl_lint,{undefined_record,foo}}],
[]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-otp_4988(doc) ->
- "OTP-4988. Error when in-lining non-existent functions.";
-otp_4988(suite) -> [];
+%% OTP-4988. Error when in-lining non-existent functions.
otp_4988(Config) when is_list(Config) ->
Ts = [{otp_4988,
<<"-compile({inline, [{f,3},{f,4},{f,2},{f,a},{1,foo}]}).
@@ -1657,12 +1624,10 @@ otp_4988(Config) when is_list(Config) ->
{1,erl_lint,{bad_inline,{f,a}}},
{3,erl_lint,{bad_inline,{g,12}}}],
[]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-otp_5091(doc) ->
- "OTP-5091. Patterns and the bit syntax: invalid warnings.";
-otp_5091(suite) -> [];
+%% OTP-5091. Patterns and the bit syntax: invalid warnings.
otp_5091(Config) when is_list(Config) ->
Ts = [{otp_5091_1,
<<"t() ->
@@ -1875,12 +1840,10 @@ otp_5091(Config) when is_list(Config) ->
<<"-record(r, {f1,f2}).
t(#r{f1 = A, f2 = A}) -> a.">>, [], []}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-otp_5276(doc) ->
- "OTP-5276. Check the 'deprecated' attributed.";
-otp_5276(suite) -> [];
+%% OTP-5276. Check the 'deprecated' attributed.
otp_5276(Config) when is_list(Config) ->
Ts = [{otp_5276_1,
<<"-deprecated([{frutt,0,next_version}]).
@@ -1907,12 +1870,10 @@ otp_5276(Config) when is_list(Config) ->
{9,erl_lint,{invalid_deprecated,{{badly,formed},1}}},
{11,erl_lint,{bad_deprecated,{atom_to_list,1}}}],
[{13,erl_lint,{unused_function,{frutt,0}}}]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-otp_5917(doc) ->
- "OTP-5917. Check the 'deprecated' attributed.";
-otp_5917(suite) -> [];
+%% OTP-5917. Check the 'deprecated' attributed.
otp_5917(Config) when is_list(Config) ->
Ts = [{otp_5917_1,
<<"-compile(export_all).
@@ -1924,12 +1885,10 @@ otp_5917(Config) when is_list(Config) ->
">>,
{[]},
[]}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-otp_6585(doc) ->
- "OTP-6585. Check the deprecated guards list/1, pid/1, ....";
-otp_6585(suite) -> [];
+%% OTP-6585. Check the deprecated guards list/1, pid/1, ....
otp_6585(Config) when is_list(Config) ->
Ts = [{otp_6585_1,
<<"-compile(export_all).
@@ -1947,12 +1906,10 @@ otp_6585(Config) when is_list(Config) ->
{warnings,[{5,erl_lint,{obsolete_guard,{list,1}}},
{6,erl_lint,{obsolete_guard,{record,2}}},
{7,erl_lint,{obsolete_guard,{pid,1}}}]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-otp_5338(doc) ->
- "OTP-5338. Bad warning in record initialization.";
-otp_5338(suite) -> [];
+%% OTP-5338. Bad warning in record initialization.
otp_5338(Config) when is_list(Config) ->
%% OTP-5878: variables like X are no longer allowed in initialisations
Ts = [{otp_5338,
@@ -1964,13 +1921,11 @@ otp_5338(Config) when is_list(Config) ->
[],
{error,[{1,erl_lint,{unbound_var,'X'}}],
[{3,erl_lint,{unused_var,'X'}}]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-otp_5362(doc) ->
- "OTP-5362. deprecated_function, "
- "{nowarn_unused_funtion,FAs}, 'better' line numbers.";
-otp_5362(suite) -> [];
+%% OTP-5362. deprecated_function,
+%% {nowarn_unused_funtion,FAs}, 'better' line numbers.
otp_5362(Config) when is_list(Config) ->
Ts = [{otp_5362_1,
<<"-include_lib(\"stdlib/include/qlc.hrl\").
@@ -2170,12 +2125,10 @@ otp_5362(Config) when is_list(Config) ->
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-otp_5371(doc) ->
- "OTP-5371. Aliases for bit syntax expressions are no longer allowed.";
-otp_5371(suite) -> [];
+%% OTP-5371. Aliases for bit syntax expressions are no longer allowed.
otp_5371(Config) when is_list(Config) ->
Ts = [{otp_5371_1,
<<"t(<<A:8>> = <<B:8>>) ->
@@ -2229,10 +2182,10 @@ otp_5371(Config) when is_list(Config) ->
{6,v3_core,nomatch},
{8,v3_core,nomatch}]}}
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-otp_7227(doc) -> "OTP_7227. Some aliases for bit syntax expressions were still allowed.";
+%% OTP_7227. Some aliases for bit syntax expressions were still allowed.
otp_7227(Config) when is_list(Config) ->
Ts = [{otp_7227_1,
<<"t([<<A:8>> = {C,D} = <<B:8>>]) ->
@@ -2299,12 +2252,10 @@ otp_7227(Config) when is_list(Config) ->
[],
{errors,[{2,erl_lint,illegal_bin_pattern}],[]}}
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-otp_5494(doc) ->
- "OTP-5494. Warnings for functions exported more than once.";
-otp_5494(suite) -> [];
+%% OTP-5494. Warnings for functions exported more than once.
otp_5494(Config) when is_list(Config) ->
Ts = [{otp_5494_1,
<<"-export([t/0]).
@@ -2313,12 +2264,10 @@ otp_5494(Config) when is_list(Config) ->
">>,
[],
{warnings,[{2,erl_lint,{duplicated_export,{t,0}}}]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-otp_5644(doc) ->
- "OTP-5644. M:F/A in record initialization.";
-otp_5644(suite) -> [];
+%% OTP-5644. M:F/A in record initialization.
otp_5644(Config) when is_list(Config) ->
%% This test is a no-op. Although {function,mfa,i,1} was
%% transformed into {function,Line,i,1} by copy_expr, the module
@@ -2334,12 +2283,10 @@ otp_5644(Config) when is_list(Config) ->
">>,
[],
[]}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-otp_5878(doc) ->
- "OTP-5878. Record declaration: forward references, introduced variables.";
-otp_5878(suite) -> [];
+%% OTP-5878. Record declaration: forward references, introduced variables.
otp_5878(Config) when is_list(Config) ->
Ts = [{otp_5878_10,
<<"-record(rec1, {a = #rec2{}}).
@@ -2455,7 +2402,7 @@ otp_5878(Config) when is_list(Config) ->
[{1,erl_lint,{unused_record,r}}]}}
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
Abstr = <<"-module(lint_test, [A, B]).
">>,
@@ -2472,7 +2419,7 @@ otp_5878(Config) when is_list(Config) ->
X <- Z ++ [A,Y]])}).
t() -> {#r1{},#r2{},#r3{}}.
">>,
- ?line {error,[{8,qlc,{used_generator_variable,'A'}},
+ {error,[{8,qlc,{used_generator_variable,'A'}},
{8,qlc,{used_generator_variable,'Y'}},
{8,qlc,{used_generator_variable,'Z'}}],
[{6,erl_lint,{unused_var,'V'}}]} =
@@ -2513,7 +2460,7 @@ otp_5878(Config) when is_list(Config) ->
bar.
">>,
- ?line {errors,[{6,erl_lint,{unbound_var,'A'}},
+ {errors,[{6,erl_lint,{unbound_var,'A'}},
{13,erl_lint,illegal_guard_expr},
{15,erl_lint,{undefined_field,r3,q}},
{17,erl_lint,{undefined_field,r,q}},
@@ -2532,14 +2479,14 @@ otp_5878(Config) when is_list(Config) ->
foo
end.
">>,
- ?line {errors,[{4,erl_lint,{undefined_function,{x,0}}},
+ {errors,[{4,erl_lint,{undefined_function,{x,0}}},
{5,erl_lint,illegal_guard_expr},
{7,erl_lint,illegal_guard_expr}],
[]} =
run_test2(Config, Ill2, [warn_unused_record]),
Ill3 = <<"t() -> ok.">>,
- ?line {errors,[{1,erl_lint,undefined_module}],[]} =
+ {errors,[{1,erl_lint,undefined_module}],[]} =
run_test2(Config, Ill3, [warn_unused_record]),
Usage1 = <<"-module(lint_test).
@@ -2552,7 +2499,7 @@ otp_5878(Config) when is_list(Config) ->
t() ->
{#u2{}}.
">>,
- ?line {warnings,[{5,erl_lint,{unused_record,u3}},
+ {warnings,[{5,erl_lint,{unused_record,u3}},
{6,erl_lint,{unused_record,u4}}]} =
run_test2(Config, Usage1, [warn_unused_record]),
@@ -2567,7 +2514,7 @@ otp_5878(Config) when is_list(Config) ->
t() ->
{#u2{}}.
">>,
- ?line [] = run_test2(Config, Usage2, [warn_unused_record]),
+ [] = run_test2(Config, Usage2, [warn_unused_record]),
%% This a completely different story...
%% The linter checks if qlc.hrl hasn't been included
@@ -2581,7 +2528,7 @@ otp_5878(Config) when is_list(Config) ->
H3 = q([X || X <- [1,2]], []),
{H1,H2,H3}.
">>,
- ?line {warnings,[{6,erl_lint,{missing_qlc_hrl,1}},
+ {warnings,[{6,erl_lint,{missing_qlc_hrl,1}},
{7,erl_lint,{missing_qlc_hrl,2}},
{8,erl_lint,{missing_qlc_hrl,2}}]} =
run_test2(Config, QLC2, [warn_unused_record]),
@@ -2597,13 +2544,29 @@ otp_5878(Config) when is_list(Config) ->
foo(#request{}) -> ok.
">>,
- ?line [] = run_test2(Config, UsedByType, [warn_unused_record]),
+ [] = run_test2(Config, UsedByType, [warn_unused_record]),
+
+ %% Abstract code generated by OTP 18. Note that the type info for
+ %% record fields has been put in a separate form.
+ OldAbstract = [{attribute,1,file,{"rec.erl",1}},
+ {attribute,1,module,rec},
+ {attribute,3,export,[{t,0}]},
+ {attribute,7,record,{r,[{record_field,7,{atom,7,f}}]}},
+ {attribute,7,type,
+ {{record,r},
+ [{typed_record_field,
+ {record_field,7,{atom,7,f}},
+ {type,7,union,[{atom,7,undefined},{type,7,atom,[]}]}}],
+ []}},
+ {function,9,t,0,[{clause,9,[],[],[{record,10,r,[]}]}]},
+ {eof,11}],
+ {error,[{"rec.erl",[{7,erl_lint,old_abstract_code}]}],[]} =
+ compile:forms(OldAbstract, [return, report]),
ok.
-otp_6885(doc) ->
- "OTP-6885. Binary fields in bit syntax matching is now only allowed at the end.";
-otp_6885(suite) -> [];
+%% OTP-6885. Binary fields in bit syntax matching is now only
+%% allowed at the end.
otp_6885(Config) when is_list(Config) ->
Ts = <<"-module(otp_6885).
-export([t/1]).
@@ -2630,7 +2593,7 @@ otp_6885(Config) when is_list(Config) ->
ok.
">>,
- ?line {errors,[{3,erl_lint,unsized_binary_not_at_end},
+ {errors,[{3,erl_lint,unsized_binary_not_at_end},
{4,erl_lint,unsized_binary_not_at_end},
{5,erl_lint,unsized_binary_not_at_end},
{10,erl_lint,typed_literal_string},
@@ -2640,9 +2603,7 @@ otp_6885(Config) when is_list(Config) ->
[]} = run_test2(Config, Ts, []),
ok.
-otp_10436(doc) ->
- "OTP-6885. Warnings for opaque types.";
-otp_10436(suite) -> [];
+%% OTP-6885. Warnings for opaque types.
otp_10436(Config) when is_list(Config) ->
Ts = <<"-module(otp_10436).
-export_type([t1/0]).
@@ -2662,9 +2623,7 @@ otp_10436(Config) when is_list(Config) ->
run_test2(Config, Ts2, []),
ok.
-otp_11254(doc) ->
- "OTP-11254. M:F/A could crash the linter.";
-otp_11254(suite) -> [];
+%% OTP-11254. M:F/A could crash the linter.
otp_11254(Config) when is_list(Config) ->
Ts = <<"-module(p2).
-export([manifest/2]).
@@ -2676,9 +2635,7 @@ otp_11254(Config) when is_list(Config) ->
run_test2(Config, Ts, []),
ok.
-otp_11772(doc) ->
- "OTP-11772. Reintroduce errors for redefined builtin types.";
-otp_11772(suite) -> [];
+%% OTP-11772. Reintroduce errors for redefined builtin types.
otp_11772(Config) when is_list(Config) ->
Ts = <<"
-module(newly).
@@ -2703,9 +2660,7 @@ otp_11772(Config) when is_list(Config) ->
[]} = run_test2(Config, Ts, []),
ok.
-otp_11771(doc) ->
- "OTP-11771. Do not allow redefinition of the types arity(_) &c..";
-otp_11771(suite) -> [];
+%% OTP-11771. Do not allow redefinition of the types arity(_) &c..
otp_11771(Config) when is_list(Config) ->
Ts = <<"
-module(newly).
@@ -2732,9 +2687,7 @@ otp_11771(Config) when is_list(Config) ->
[]} = run_test2(Config, Ts, []),
ok.
-otp_11872(doc) ->
- "OTP-11872. The type map() undefined when exported.";
-otp_11872(suite) -> [];
+%% OTP-11872. The type map() undefined when exported.
otp_11872(Config) when is_list(Config) ->
Ts = <<"
-module(map).
@@ -2756,22 +2709,19 @@ otp_11872(Config) when is_list(Config) ->
run_test2(Config, Ts, []),
ok.
-export_all(doc) ->
- "OTP-7392. Warning for export_all.";
+%% OTP-7392. Warning for export_all.
export_all(Config) when is_list(Config) ->
Ts = <<"-module(export_all_module).
-compile([export_all]).
id(I) -> I.
">>,
- ?line [] = run_test2(Config, Ts, []),
- ?line {warnings,[{2,erl_lint,export_all}]} =
+ [] = run_test2(Config, Ts, []),
+ {warnings,[{2,erl_lint,export_all}]} =
run_test2(Config, Ts, [warn_export_all]),
ok.
-bif_clash(doc) ->
- "Test warnings for functions that clash with BIFs.";
-bif_clash(suite) -> [];
+%% Test warnings for functions that clash with BIFs.
bif_clash(Config) when is_list(Config) ->
Ts = [{clash1,
<<"t(X) ->
@@ -3038,12 +2988,10 @@ bif_clash(Config) when is_list(Config) ->
[]}
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-behaviour_basic(doc) ->
- "Basic tests with one behaviour.";
-behaviour_basic(suite) -> [];
+%% Basic tests with one behaviour.
behaviour_basic(Config) when is_list(Config) ->
Ts = [{behaviour1,
<<"-behaviour(application).
@@ -3077,12 +3025,10 @@ behaviour_basic(Config) when is_list(Config) ->
[],
{warnings,[{1,erl_lint,{undefined_behaviour_func,{start,2},application}}]}}
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-behaviour_multiple(doc) ->
- "Basic tests with multiple behaviours.";
-behaviour_multiple(suite) -> [];
+%% Basic tests with multiple behaviours.
behaviour_multiple(Config) when is_list(Config) ->
Ts = [{behaviour1,
<<"-behaviour(application).
@@ -3180,12 +3126,10 @@ behaviour_multiple(Config) when is_list(Config) ->
erl_lint,
{conflicting_behaviours,{init,1},supervisor,1,gen_server}}]}}
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-otp_11861(doc) ->
- "OTP-11861. behaviour_info() and -callback.";
-otp_11861(suite) -> [];
+%% OTP-11861. behaviour_info() and -callback.
otp_11861(Conf) when is_list(Conf) ->
CallbackFiles = [callback1, callback2, callback3,
bad_behaviour1, bad_behaviour2],
@@ -3366,12 +3310,12 @@ otp_11861(Conf) when is_list(Conf) ->
[],
[]}
],
- ?line [] = run(Conf, Ts),
+ [] = run(Conf, Ts),
true = code:set_path(CodePath),
ok.
-otp_7550(doc) ->
- "Test that the new utf8/utf16/utf32 types do not allow size or unit specifiers.";
+%% Test that the new utf8/utf16/utf32 types do not allow size or
+%% unit specifiers.
otp_7550(Config) when is_list(Config) ->
Ts = [{otp_7550,
<<"f8(A) ->
@@ -3407,12 +3351,11 @@ otp_7550(Config) when is_list(Config) ->
{20,erl_lint,utf_bittype_size_or_unit}
],
[]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-otp_8051(doc) ->
- "Bugfix: -opaque with invalid type.";
+%% Bugfix: -opaque with invalid type.
otp_8051(Config) when is_list(Config) ->
Ts = [{otp_8051,
<<"-opaque foo() :: bar().
@@ -3420,12 +3363,10 @@ otp_8051(Config) when is_list(Config) ->
">>,
[],
{errors,[{1,erl_lint,{undefined_type,{bar,0}}}],[]}}],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-format_warn(doc) ->
- "Check that format warnings are generated.";
-format_warn(suite) -> [];
+%% Check that format warnings are generated.
format_warn(Config) when is_list(Config) ->
L1 = 14,
L2 = 4,
@@ -3435,18 +3376,18 @@ format_warn(Config) when is_list(Config) ->
ok.
format_level(Level, Count, Config) ->
- ?line W = get_compilation_result(Config, "format",
+ W = get_compilation_result(Config, "format",
[{warn_format, Level}]),
%% Pick out the 'format' warnings.
- ?line FW = lists:filter(fun({_Line, erl_lint, {format_error, _}}) -> true;
+ FW = lists:filter(fun({_Line, erl_lint, {format_error, _}}) -> true;
(_) -> false
end,
W),
- ?line case length(FW) of
+ case length(FW) of
Count ->
ok;
Other ->
- ?t:format("Expected ~w warning(s); got ~w", [Count,Other]),
+ io:format("Expected ~w warning(s); got ~w", [Count,Other]),
fail()
end,
ok.
@@ -3482,7 +3423,7 @@ on_load_successful(Config) when is_list(Config) ->
{[]}, %Tuple indicates no 'export_all'.
[]}
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
on_load_failing(Config) when is_list(Config) ->
@@ -3530,12 +3471,10 @@ on_load_failing(Config) when is_list(Config) ->
{errors,
[{1,erl_lint,{undefined_on_load,{non_existing,0}}}],[]}}
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
-too_many_arguments(doc) ->
- "Test that too many arguments is not accepted.";
-too_many_arguments(suite) -> [];
+%% Test that too many arguments is not accepted.
too_many_arguments(Config) when is_list(Config) ->
Ts = [{too_many_1,
<<"f(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_) -> ok.">>,
@@ -3544,7 +3483,7 @@ too_many_arguments(Config) when is_list(Config) ->
[{1,erl_lint,{too_many_arguments,256}}],[]}}
],
- ?line [] = run(Config, Ts),
+ [] = run(Config, Ts),
ok.
@@ -3627,9 +3566,7 @@ bin_syntax_errors(Config) ->
[] = run(Config, Ts),
ok.
-predef(doc) ->
- "OTP-10342: No longer predefined types: array(), digraph(), and so on";
-predef(suite) -> [];
+%% OTP-10342: No longer predefined types: array(), digraph(), and so on.
predef(Config) when is_list(Config) ->
W = get_compilation_result(Config, "predef", []),
[] = W,
@@ -3756,8 +3693,7 @@ maps_type(Config) when is_list(Config) ->
[] = run(Config, Ts),
ok.
-otp_11851(doc) ->
- "OTP-11851: More atoms can be used as type names + bug fixes.";
+%% OTP-11851: More atoms can be used as type names + bug fixes.
otp_11851(Config) when is_list(Config) ->
Ts = [
{otp_11851_1,
@@ -3843,42 +3779,29 @@ otp_11851(Config) when is_list(Config) ->
[] = run(Config, Ts),
ok.
-otp_12195(doc) ->
- "OTP-12195: Check obsolete types (tailor made for OTP 18).";
-otp_12195(Config) when is_list(Config) ->
- Ts = [{otp_12195_1,
- <<"-export_type([r1/0]).
- -type r1() :: erl_scan:line()
- | erl_scan:column()
- | erl_scan:location()
- | erl_anno:line().">>,
- [],
- {warnings,[{2,erl_lint,
- {deprecated_type,{erl_scan,line,0},
- "deprecated (will be removed in OTP 19); "
- "use erl_anno:line() instead"}},
- {3,erl_lint,
- {deprecated_type,{erl_scan,column,0},
- "deprecated (will be removed in OTP 19); use "
- "erl_anno:column() instead"}},
- {4,erl_lint,
- {deprecated_type,{erl_scan,location,0},
- "deprecated (will be removed in OTP 19); "
- "use erl_anno:location() instead"}}]}},
- {otp_12195_2,
- <<"-export_type([r1/0]).
- -compile(nowarn_deprecated_type).
- -type r1() :: erl_scan:line()
- | erl_scan:column()
- | erl_scan:location()
- | erl_anno:line().">>,
- [],
- []}],
- [] = run(Config, Ts),
+%% OTP-11879: The -spec f/a :: (As) -> B; syntax removed,
+%% and is_subtype/2 deprecated.
+otp_11879(_Config) ->
+ Fs = [{attribute,0,file,{"file.erl",0}},
+ {attribute,0,module,m},
+ {attribute,1,spec,
+ {{f,1},
+ [{type,2,'fun',[{type,3,product,[{var,4,'V1'},
+ {var,5,'V1'}]},
+ {type,6,integer,[]}]}]}},
+ {attribute,20,callback,
+ {{cb,21},
+ [{type,22,'fun',[{type,23,product,[{var,24,'V1'},
+ {var,25,'V1'}]},
+ {type,6,integer,[]}]}]}}],
+ {error,[{"file.erl",
+ [{1,erl_lint,{spec_fun_undefined,{f,1}}},
+ {2,erl_lint,spec_wrong_arity},
+ {22,erl_lint,callback_wrong_arity}]}],
+ []} = compile:forms(Fs, [return,report]),
ok.
-otp_13230(doc) ->
- "OTP-13230: -deprecated without -module";
+%% OTP-13230: -deprecated without -module.
otp_13230(Config) when is_list(Config) ->
Abstr = <<"-deprecated([{frutt,0,next_version}]).">>,
{errors,[{1,erl_lint,undefined_module},
@@ -3886,13 +3809,24 @@ otp_13230(Config) when is_list(Config) ->
[]} = run_test2(Config, Abstr, []),
ok.
+record_errors(Config) when is_list(Config) ->
+ Ts = [{rec1,
+ <<"-record(r, {a,b}).
+ b() -> #r{a=foo,b=42,a=bar}.
+ u(R) -> R#r{a=1,b=2,a=2}.
+ ">>,
+ [],
+ {errors,[{2,erl_lint,{redefine_field,r,a}},
+ {3,erl_lint,{redefine_field,r,a}}],[]}}],
+ run(Config, Ts).
+
run(Config, Tests) ->
F = fun({N,P,Ws,E}, BadL) ->
case catch run_test(Config, P, Ws) of
E ->
BadL;
Bad ->
- ?t:format("~nTest ~p failed. Expected~n ~p~n"
+ io:format("~nTest ~p failed. Expected~n ~p~n"
"but got~n ~p~n", [N, E, Bad]),
fail()
end
@@ -3902,8 +3836,8 @@ run(Config, Tests) ->
%% Compiles a test file and returns the list of warnings/errors.
get_compilation_result(Conf, Filename, Warnings) ->
- ?line DataDir = ?datadir,
- ?line File = filename:join(DataDir, Filename),
+ DataDir = ?datadir,
+ File = filename:join(DataDir, Filename),
{ok,Bin} = file:read_file(File++".erl"),
FileS = binary_to_list(Bin),
{match,[{Start,Length}|_]} = re:run(FileS, "-module.*\\n"),
@@ -3967,5 +3901,4 @@ call_format_error(L) ->
L.
fail() ->
- io:format("failed~n"),
- ?t:fail().
+ ct:fail(failed).
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index 92e2764c65..4d44f7686a 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -22,7 +22,7 @@
%%%-----------------------------------------------------------------
-module(erl_pp_SUITE).
-%-define(debug, true).
+%%-define(debug, true).
-ifdef(debug).
-define(line, put(line, ?LINE), ).
@@ -31,9 +31,9 @@
-define(privdir, "erl_pp_SUITE_priv").
-define(t, test_server).
-else.
--include_lib("test_server/include/test_server.hrl").
--define(datadir, ?config(data_dir, Config)).
--define(privdir, ?config(priv_dir, Config)).
+-include_lib("common_test/include/ct.hrl").
+-define(datadir, proplists:get_value(data_dir, Config)).
+-define(privdir, proplists:get_value(priv_dir, Config)).
-endif.
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -55,19 +55,15 @@
%% Internal export.
-export([ehook/6]).
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(2)).
-
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
+ Config.
end_per_testcase(_Case, _Config) ->
- Dog = ?config(watchdog, _Config),
- test_server:timetrap_cancel(Dog),
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,2}}].
all() ->
[{group, expr}, {group, attributes}, hook, neg_indent,
@@ -99,8 +95,6 @@ end_per_group(_GroupName, Config) ->
-func(suite) ->
- [];
func(Config) when is_list(Config) ->
Ts = [{func_1,
<<"-record(r1, {a,b}).
@@ -154,11 +148,9 @@ func(Config) when is_list(Config) ->
true
end)().">>}
],
- ?line compile(Config, Ts),
+ compile(Config, Ts),
ok.
-call(suite) ->
- [];
call(Config) when is_list(Config) ->
Ts = [{call_1,
<<"t() ->
@@ -167,11 +159,9 @@ call(Config) when is_list(Config) ->
sfds,sdfsdf,sfds).
">>}
],
- ?line compile(Config, Ts),
+ compile(Config, Ts),
ok.
-recs(suite) ->
- [];
recs(Config) when is_list(Config) ->
%% Evolved while testing strict record tests in guards...
Ts = [{recs_1,
@@ -328,18 +318,16 @@ recs(Config) when is_list(Config) ->
R = #r2{},
R#r2{c = R, d = #r1{}}.">>}
],
- ?line compile(Config, Ts),
+ compile(Config, Ts),
- ?line ok = pp_expr(<<"case #r{a={1,2},b=#r{}} of
+ ok = pp_expr(<<"case #r{a={1,2},b=#r{}} of
X=Y=#r{a=foo,b=bar} ->
{(foooo:baaaar(X))#r{a = rep},Y,#r.b}
end">>),
- ?line ok = pp_expr(<<"R#r{a = {kljasdklf,sdkfjsdl,sdafjkllsdf,sdfkjsd,
+ ok = pp_expr(<<"R#r{a = {kljasdklf,sdkfjsdl,sdafjkllsdf,sdfkjsd,
sdafjsd,sdf,sdafsd,sdfdsf,sdfdsf,dsfds}}">>),
ok.
-try_catch(suite) ->
- [];
try_catch(Config) when is_list(Config) ->
Ts = [{try_1, % copied from erl_eval_SUITE
<<"t() -> try 1 of 1 -> 2 catch _:_ -> 3 end.">>},
@@ -381,8 +369,8 @@ try_catch(Config) when is_list(Config) ->
<<"t() -> catch begin begin foo, bar, foo:bar(kljsldkfjdls,kljsdl),
(catch bar:foo(foo)) end end.">>}
],
- ?line compile(Config, Ts),
- ?line ok = pp_expr(<<"try
+ compile(Config, Ts),
+ ok = pp_expr(<<"try
erl_internal:bif(M,F,length(Args))
of
true ->
@@ -392,8 +380,6 @@ try_catch(Config) when is_list(Config) ->
after foo end">>),
ok.
-if_then(suite) ->
- [];
if_then(Config) when is_list(Config) ->
Ts = [{if_1,
<<"t() -> if 1 > 2 -> 1; true -> b end.">>},
@@ -402,11 +388,9 @@ if_then(Config) when is_list(Config) ->
{if_3,
<<"t() -> if 1 == 2 -> a; 1 > 2 -> b; 1 < 2 -> c end.">>}
],
- ?line compile(Config, Ts),
+ compile(Config, Ts),
ok.
-receive_after(suite) ->
- [];
receive_after(Config) when is_list(Config) ->
Ts = [{rec_1,
<<"t() -> receive foo -> bar; bar -> foo end.">>},
@@ -427,11 +411,9 @@ receive_after(Config) when is_list(Config) ->
{3,4}
end.">>}
],
- ?line compile(Config, Ts),
+ compile(Config, Ts),
ok.
-bits(suite) ->
- [];
bits(Config) when is_list(Config) ->
Ts = [{bit_1, % copied from shell_SUITE
<<"t() -> <<(<<\"abc\">>):3/binary>>.">>},
@@ -452,21 +434,19 @@ bits(Config) when is_list(Config) ->
{bit_9,
<<"">>}
],
- ?line compile(Config, Ts),
- ?line ok = pp_expr(<<"<<(list_to_binary([1,2]))/binary>>">>),
- ?line ok = pp_expr(
+ compile(Config, Ts),
+ ok = pp_expr(<<"<<(list_to_binary([1,2]))/binary>>">>),
+ ok = pp_expr(
<<"<<(list_to_binary([1,2])):all/binary-unit:8-unsigned-big>>">>),
- ?line ok = pp_expr(<<"<<<<\"hej\">>/binary>>">>),
- ?line ok = pp_expr(<<"<<(foo:bar())/binary>>">>),
- ?line ok = pp_expr(<<"<<(a)/binary>>">>),
- ?line ok = pp_expr(<<"<<a/binary>>">>),
- ?line ok = pp_expr(<<"<<{a,b}/binary>>">>),
- ?line ok = pp_expr(<<"<<{foo:bar(),b}/binary>>">>),
- ?line ok = pp_expr(<<"<<(foo:bar()):(foo:bar())/binary>>">>),
+ ok = pp_expr(<<"<<<<\"hej\">>/binary>>">>),
+ ok = pp_expr(<<"<<(foo:bar())/binary>>">>),
+ ok = pp_expr(<<"<<(a)/binary>>">>),
+ ok = pp_expr(<<"<<a/binary>>">>),
+ ok = pp_expr(<<"<<{a,b}/binary>>">>),
+ ok = pp_expr(<<"<<{foo:bar(),b}/binary>>">>),
+ ok = pp_expr(<<"<<(foo:bar()):(foo:bar())/binary>>">>),
ok.
-head_tail(suite) ->
- [];
head_tail(Config) when is_list(Config) ->
Ts = [{list_1,
<<"t() -> [a | b].">>},
@@ -481,43 +461,30 @@ head_tail(Config) when is_list(Config) ->
[foo:bar(lkjljlskdfj, klsdajflds, sdafkljsdlfkjdas, kjlsdadjl),
bar:foo(kljlkjsdf, lkjsdlfj, [kljsfj, sdfdsfsad])].">>}
],
- ?line compile(Config, Ts),
+ compile(Config, Ts),
ok.
-cond1(suite) ->
- [];
cond1(Config) when is_list(Config) ->
C = {'cond',1,[{clause,2,[],[[{tuple,2,[{atom,2,foo},{atom,2,bar}]}]],
[{cons,3,{atom,3,a},{cons,3,{atom,3,b},{nil,3}}}]},
{clause,4,[],[[{atom,4,true}]],
[{tuple,5,[{atom,5,x},{atom,5,y}]}]}]},
CChars = flat_expr1(C),
-% ?line "cond {foo,bar} -> [a,b]; true -> {x,y} end" = CChars,
- ?line "cond\n"
+ "cond\n"
" {foo,bar} ->\n"
" [a,b];\n"
" true ->\n"
" {x,y}\n"
"end" = CChars,
-% ?line ok = pp_expr(<<"cond
-% {foo,bar} ->
-% [a,b];
-% true ->
-% {x,y}
-% end">>),
ok.
-block(suite) ->
- [];
block(Config) when is_list(Config) ->
Ts = [{block_1,
<<"t() -> begin a,{c,d} end.">>}
],
- ?line compile(Config, Ts),
+ compile(Config, Ts),
ok.
-case1(suite) ->
- [];
case1(Config) when is_list(Config) ->
Ts = [{case_1,
<<"t() -> case {foo,bar} of
@@ -527,8 +494,8 @@ case1(Config) when is_list(Config) ->
foo
end.">>}
],
- ?line compile(Config, Ts),
- ?line ok = pp_expr(<<"case
+ compile(Config, Ts),
+ ok = pp_expr(<<"case
erl_internal:bif(M,F,length(Args))
of
true ->
@@ -538,8 +505,6 @@ case1(Config) when is_list(Config) ->
end">>),
ok.
-ops(suite) ->
- [];
ops(Config) when is_list(Config) ->
Ts = [{ops_1,
<<"t() -> {a,b} + (3 - 2) + 4.">>},
@@ -548,21 +513,17 @@ ops(Config) when is_list(Config) ->
{ops_3,
<<"t() -> - (- (- (- (- 3)))).">>}
],
- ?line compile(Config, Ts),
+ compile(Config, Ts),
ok.
-messages(suite) ->
- [];
messages(Config) when is_list(Config) ->
- ?line true = "{error,{some,\"error\"}}\n" =:=
+ true = "{error,{some,\"error\"}}\n" =:=
lists:flatten(erl_pp:form({error,{some,"error"}})),
- ?line true = "{warning,{some,\"warning\"}}\n" =:=
+ true = "{warning,{some,\"warning\"}}\n" =:=
lists:flatten(erl_pp:form({warning,{some,"warning"}})),
"\n" = flat_form({eof,0}),
ok.
-import_export(suite) ->
- [];
import_export(Config) when is_list(Config) ->
Ts = [{import_1,
<<"-import(lists, [max/1, reverse/1]).
@@ -577,11 +538,9 @@ import_export(Config) when is_list(Config) ->
<<"-include_lib(\"stdlib/include/qlc.hrl\").
t() -> qlc:q([X || X <- []]).">>}
],
- ?line compile(Config, Ts),
+ compile(Config, Ts),
ok.
-misc_attrs(suite) ->
- [];
misc_attrs(Config) when is_list(Config) ->
ok = pp_forms(<<"-module(m). ">>),
ok = pp_forms(<<"-module(m, [Aafjlksfjdlsjflsdfjlsdjflkdsfjlk,"
@@ -599,8 +558,6 @@ misc_attrs(Config) when is_list(Config) ->
ok = pp_forms(<<"-custom1(#{test1 => init/2, test2 => [val/1, val/2]}). ">>),
ok.
-dialyzer_attrs(suite) ->
- [];
dialyzer_attrs(Config) when is_list(Config) ->
ok = pp_forms(<<"-type foo() :: #bar{}. ">>),
ok = pp_forms(<<"-opaque foo() :: {bar, fun((X, [42,...]) -> X)}. ">>),
@@ -608,8 +565,6 @@ dialyzer_attrs(Config) when is_list(Config) ->
ok = pp_forms(<<"-callback foo(<<_:32,_:_*4>>, T) -> T. ">>),
ok.
-hook(suite) ->
- [];
hook(Config) when is_list(Config) ->
F = fun(H) -> H end,
do_hook(F).
@@ -623,29 +578,29 @@ do_hook(HookFun) ->
Call = {call,A0,{atom,A0,foo},[Lc]},
Expr2 = {call,A0,{atom,A0,fff},[Call,Call,Call]},
EChars2 = erl_pp:exprs([Expr2]),
- ?line true = EChars =:= lists:flatten(EChars2),
+ true = EChars =:= lists:flatten(EChars2),
EsChars = erl_pp:exprs([Expr], H),
- ?line true = EChars =:= lists:flatten(EsChars),
+ true = EChars =:= lists:flatten(EsChars),
A1 = erl_anno:new(1),
F = {function,A1,ffff,0,[{clause,A1,[],[],[Expr]}]},
FuncChars = lists:flatten(erl_pp:function(F, H)),
F2 = {function,A1,ffff,0,[{clause,A1,[],[],[Expr2]}]},
FuncChars2 = erl_pp:function(F2),
- ?line true = FuncChars =:= lists:flatten(FuncChars2),
+ true = FuncChars =:= lists:flatten(FuncChars2),
FFormChars = erl_pp:form(F, H),
- ?line true = FuncChars =:= lists:flatten(FFormChars),
+ true = FuncChars =:= lists:flatten(FFormChars),
A = {attribute,A1,record,{r,[{record_field,A1,{atom,A1,a},Expr}]}},
AChars = lists:flatten(erl_pp:attribute(A, H)),
A2 = {attribute,A1,record,{r,[{record_field,A1,{atom,A1,a},Expr2}]}},
AChars2 = erl_pp:attribute(A2),
- ?line true = AChars =:= lists:flatten(AChars2),
+ true = AChars =:= lists:flatten(AChars2),
AFormChars = erl_pp:form(A, H),
- ?line true = AChars =:= lists:flatten(AFormChars),
+ true = AChars =:= lists:flatten(AFormChars),
- ?line "INVALID-FORM:{foo,bar}:" = lists:flatten(erl_pp:expr({foo,bar})),
+ "INVALID-FORM:{foo,bar}:" = lists:flatten(erl_pp:expr({foo,bar})),
%% A list (as before R6), not a list of lists.
G = [{op,A1,'>',{atom,A1,a},{foo,{atom,A1,b}}}], % not a proper guard
@@ -653,26 +608,26 @@ do_hook(HookFun) ->
G2 = [{op,A1,'>',{atom,A1,a},
{call,A0,{atom,A0,foo},[{atom,A1,b}]}}], % not a proper guard
GChars2 = erl_pp:guard(G2),
- ?line true = GChars =:= lists:flatten(GChars2),
+ true = GChars =:= lists:flatten(GChars2),
EH = HookFun({?MODULE, ehook, [foo,bar]}),
XEChars = erl_pp:expr(Expr, -1, EH),
- ?line true = remove_indentation(EChars) =:= lists:flatten(XEChars),
+ true = remove_indentation(EChars) =:= lists:flatten(XEChars),
XEChars2 = erl_pp:expr(Expr, EH),
- ?line true = EChars =:= lists:flatten(XEChars2),
+ true = EChars =:= lists:flatten(XEChars2),
%% Note: no leading spaces before "begin".
Block = {block,A0,[{match,A0,{var,A0,'A'},{integer,A0,3}},
{atom,A0,true}]},
- ?line "begin\n A =" ++ _ =
+ "begin\n A =" ++ _ =
lists:flatten(erl_pp:expr(Block, 17, none)),
%% Special...
- ?line true =
+ true =
"{some,value}" =:= lists:flatten(erl_pp:expr({value,A0,{some,value}})),
%% Silly...
- ?line true =
+ true =
"if true -> 0 end" =:=
flat_expr({'if',0,[{clause,0,[],[],[{atom,0,0}]}]}),
@@ -681,7 +636,7 @@ do_hook(HookFun) ->
NewIf = {'if',A0,[{clause,A0,[],[[{atom,A0,true}]],[{atom,A0,b}]}]},
OldIfChars = lists:flatten(erl_pp:expr(OldIf)),
NewIfChars = lists:flatten(erl_pp:expr(NewIf)),
- ?line true = OldIfChars =:= NewIfChars,
+ true = OldIfChars =:= NewIfChars,
ok.
@@ -697,18 +652,16 @@ hook({foo,E}, I, P, H) ->
A = erl_anno:new(0),
erl_pp:expr({call,A,{atom,A,foo},[E]}, I, P, H).
-neg_indent(suite) ->
- [];
neg_indent(Config) when is_list(Config) ->
- ?line ok = pp_expr(<<"begin a end">>),
- ?line ok = pp_expr(<<"begin a,b end">>),
- ?line ok = pp_expr(<<"try a,b,c
+ ok = pp_expr(<<"begin a end">>),
+ ok = pp_expr(<<"begin a,b end">>),
+ ok = pp_expr(<<"try a,b,c
catch exit:_ -> d;
throw:_ -> t;
error:{foo,bar} -> foo,
bar
end">>),
- ?line ok = pp_expr(
+ ok = pp_expr(
<<"fun() ->
F = fun(A, B) when ((A#r1.a) orelse (B#r2.a))
or (B#r2.b) or (A#r1.b) ->
@@ -722,43 +675,41 @@ neg_indent(Config) when is_list(Config) ->
ok
end()">>),
- ?line ok = pp_expr(<<"[X || X <- a, true]">>),
- ?line ok = pp_expr(<<"{[a,b,c],[d,e|f]}">>),
- ?line ok = pp_expr(<<"f(a,b,c)">>),
- ?line ok = pp_expr(<<"fun() when a,b;c,d -> a end">>),
- ?line ok = pp_expr(<<"fun A() when a,b;c,d -> a end">>),
- ?line ok = pp_expr(<<"<<34:32,17:32>>">>),
- ?line ok = pp_expr(<<"if a,b,c -> d; e,f,g -> h,i end">>),
- ?line ok = pp_expr(<<"if a -> d; c -> d end">>),
- ?line ok = pp_expr(<<"receive after 1 -> 2 end">>),
- ?line ok = pp_expr(<<"begin a,b,c end">>),
-
- ?line "\"\"" = flat_expr({string,0,""}),
- ?line ok = pp_expr(<<"\"abc\"">>),
- ?line ok = pp_expr(<<"\"abc\n\n\n\n\nkjsd\n\n\n\n\nkljsddf\n\n\n\n\n"
- "klafd\n\n\n\n\nkljsdf\n\n\n\n\nsdf\n\n\n\n\n\"">>),
- ?line ok = pp_expr(<<"fkjlskljklkkljlkjlkjkljlkjsljklf"
- "lsdjlfdsjlfjsdlfjdslfjdlsjfsdjfklsdkfjsdf("
- "\"abc\n\n\n\n\nkjsd\n\n\n\n\nkljsddf\n\n\n\n\n"
- "kljsafd\n\n\n\n\nkljsdf\n\n\n\n\nkjsdf"
- "\n\n\n\n\n\")">>),
+ ok = pp_expr(<<"[X || X <- a, true]">>),
+ ok = pp_expr(<<"{[a,b,c],[d,e|f]}">>),
+ ok = pp_expr(<<"f(a,b,c)">>),
+ ok = pp_expr(<<"fun() when a,b;c,d -> a end">>),
+ ok = pp_expr(<<"fun A() when a,b;c,d -> a end">>),
+ ok = pp_expr(<<"<<34:32,17:32>>">>),
+ ok = pp_expr(<<"if a,b,c -> d; e,f,g -> h,i end">>),
+ ok = pp_expr(<<"if a -> d; c -> d end">>),
+ ok = pp_expr(<<"receive after 1 -> 2 end">>),
+ ok = pp_expr(<<"begin a,b,c end">>),
+
+ "\"\"" = flat_expr({string,0,""}),
+ ok = pp_expr(<<"\"abc\"">>),
+ ok = pp_expr(<<"\"abc\n\n\n\n\nkjsd\n\n\n\n\nkljsddf\n\n\n\n\n"
+ "klafd\n\n\n\n\nkljsdf\n\n\n\n\nsdf\n\n\n\n\n\"">>),
+ ok = pp_expr(<<"fkjlskljklkkljlkjlkjkljlkjsljklf"
+ "lsdjlfdsjlfjsdlfjdslfjdlsjfsdjfklsdkfjsdf("
+ "\"abc\n\n\n\n\nkjsd\n\n\n\n\nkljsddf\n\n\n\n\n"
+ "kljsafd\n\n\n\n\nkljsdf\n\n\n\n\nkjsdf"
+ "\n\n\n\n\n\")">>),
%% fun-info is skipped when everything is to fit on one single line
Fun1 = {'fun',1,{function,t,0},{0,45353021,'-t/0-fun-0-'}},
- ?line "fun t/0" = flat_expr(Fun1),
+ "fun t/0" = flat_expr(Fun1),
Fun2 = {'fun',2,{clauses,[{clause,2,[],[],[{atom,3,true}]}]},
{0,108059557,'-t/0-fun-0-'}},
- ?line "fun() -> true end" = flat_expr(Fun2),
+ "fun() -> true end" = flat_expr(Fun2),
Fun3 = {named_fun,3,'True',[{clause,3,[],[],[{atom,3,true}]}],
{0,424242424,'-t/0-True-0-'}},
- ?line "fun True() -> true end" = flat_expr(Fun3),
+ "fun True() -> true end" = flat_expr(Fun3),
ok.
-otp_6321(doc) ->
- "OTP_6321. Bug fix of exprs().";
-otp_6321(suite) -> [];
+%% OTP_6321. Bug fix of exprs().
otp_6321(Config) when is_list(Config) ->
Str = "S = hopp, {hej, S}. ",
{done, {ok, Tokens, _EndLine}, ""} = erl_scan:tokens("", Str, _L=1),
@@ -766,9 +717,7 @@ otp_6321(Config) when is_list(Config) ->
"S = hopp, {hej,S}" = lists:flatten(erl_pp:exprs(Exprs)),
ok.
-otp_6911(doc) ->
- "OTP_6911. More newlines.";
-otp_6911(suite) -> [];
+%% OTP_6911. More newlines.
otp_6911(Config) when is_list(Config) ->
F = {function,5,thomas,1,
[{clause,5,
@@ -779,38 +728,32 @@ otp_6911(Config) when is_list(Config) ->
[{clause,7,[{atom,7,true}],[],[{integer,7,12}]},
{clause,8,[{atom,8,false}],[],[{integer,8,14}]}]}]}]},
Chars = flat_form(F),
- ?line "thomas(X) ->\n"
+ "thomas(X) ->\n"
" case X of\n"
" true ->\n"
" 12;\n"
" false ->\n"
" 14\n"
" end.\n" = Chars,
- ?line ok = pp_expr(<<"case X of true -> 12; false -> 14 end">>),
- ?line ok = pp_expr(<<"receive after 1 -> ok end">>),
+ ok = pp_expr(<<"case X of true -> 12; false -> 14 end">>),
+ ok = pp_expr(<<"receive after 1 -> ok end">>),
ok.
-otp_6914(doc) ->
- "OTP_6914. Binary comprehensions.";
-otp_6914(suite) -> [];
+%% OTP_6914. Binary comprehensions.
otp_6914(Config) when is_list(Config) ->
- ?line ok = pp_expr(<<"<< <<B:1>> || B <- [0,1,1] >>">>),
- ?line ok = pp_expr(<<"[ B || <<B:1>> <= <<\"hi\">>]">>),
- ?line ok = pp_expr(<<"<< <<1:1>> || true >>">>),
+ ok = pp_expr(<<"<< <<B:1>> || B <- [0,1,1] >>">>),
+ ok = pp_expr(<<"[ B || <<B:1>> <= <<\"hi\">>]">>),
+ ok = pp_expr(<<"<< <<1:1>> || true >>">>),
ok.
-otp_8150(doc) ->
- "OTP_8150. Types.";
-otp_8150(suite) -> [];
+%% OTP_8150. Types.
otp_8150(Config) when is_list(Config) ->
- ?line _ = [{N,ok} = {N,pp_forms(B)} ||
+ _ = [{N,ok} = {N,pp_forms(B)} ||
{N,B} <- type_examples()
],
ok.
-otp_8238(doc) ->
- "OTP_8238. Bugfix 'E'.";
-otp_8238(suite) -> [];
+%% OTP_8238. Bugfix 'E'.
otp_8238(Config) when is_list(Config) ->
Ex = [<<"-record(rec1, {}).\n"
"-record(rec2, {a, b}).\n"
@@ -825,7 +768,7 @@ otp_8238(Config) when is_list(Config) ->
"t2() ->\n"
" #r{}.\n">>
],
- ?line compile(Config, [{otp_8238,iolist_to_binary(Ex)}]),
+ compile(Config, [{otp_8238,iolist_to_binary(Ex)}]),
ok.
type_examples() ->
@@ -876,14 +819,17 @@ type_examples() ->
{ex30,<<"-type t99() ::"
"{t2(),'\\'t::4'(),t5(),t6(),t7(),t8(),t10(),t14(),"
"t15(),t20(),t21(), t22(),t25()}. ">>},
+ %% Writing constraints as is_subtype(V, T) is not supported since
+ %% Erlang/OTP 19.0, but as long as the parser recognizes the
+ %% is_subtype(V, T) syntax, we need a few examples of the syntax.
{ex31,<<"-spec t1(FooBar :: t99()) -> t99();"
- "(t2()) -> t2();"
- "('\\'t::4'()) -> '\\'t::4'() when is_subtype('\\'t::4'(), t24);"
- "(t23()) -> t23() when is_subtype(t23(), atom()),"
- " is_subtype(t23(), t14());"
- "(t24()) -> t24() when is_subtype(t24(), atom()),"
- " is_subtype(t24(), t14()),"
- " is_subtype(t24(), '\\'t::4'()).">>},
+ "(t2()) -> t2();"
+ "('\\'t::4'()) -> '\\'t::4'() when is_subtype('\\'t::4'(), t24);"
+ "(t23()) -> t23() when is_subtype(t23(), atom()),"
+ " is_subtype(t23(), t14());"
+ "(t24()) -> t24() when is_subtype(t24(), atom()),"
+ " is_subtype(t24(), t14()),"
+ " is_subtype(t24(), '\\'t::4'()).">>},
{ex32,<<"-spec mod:t2() -> any(). ">>},
{ex33,<<"-opaque attributes_data() :: "
"[{'column', column()} | {'line', info_line()} |"
@@ -903,19 +849,15 @@ type_examples() ->
"f19 = 3 :: integer()|undefined,"
"f5 = 3 :: undefined|integer()}). ">>}].
-otp_8473(doc) ->
- "OTP_8473. Bugfix abstract type 'fun'.";
-otp_8473(suite) -> [];
+%% OTP_8473. Bugfix abstract type 'fun'.
otp_8473(Config) when is_list(Config) ->
Ex = [{ex1,<<"-type 'fun'(A) :: A.\n"
"-type funkar() :: 'fun'(fun((integer()) -> atom())).\n">>}],
- ?line _ = [{N,ok} = {N,pp_forms(B)} ||
+ _ = [{N,ok} = {N,pp_forms(B)} ||
{N,B} <- Ex],
ok.
-otp_8522(doc) ->
- "OTP_8522. Avoid duplicated 'undefined' in record field types.";
-otp_8522(suite) -> [];
+%% OTP_8522. Avoid duplicated 'undefined' in record field types.
otp_8522(Config) when is_list(Config) ->
FileName = filename('otp_8522.erl', Config),
C = <<"-module(otp_8522).\n"
@@ -924,11 +866,13 @@ otp_8522(Config) when is_list(Config) ->
" f3 :: (undefined),\n"
" f4 :: x | y | undefined | z,\n"
" f5 :: a}).\n">>,
- ?line ok = file:write_file(FileName, C),
- ?line {ok, _} = compile:file(FileName, [{outdir,?privdir},debug_info]),
+ ok = file:write_file(FileName, C),
+ {ok, _} = compile:file(FileName, [{outdir,?privdir},debug_info]),
BF = filename("otp_8522", Config),
- ?line {ok, A} = beam_lib:chunks(BF, [abstract_code]),
- ?line 5 = count_atom(A, undefined),
+ {ok, A} = beam_lib:chunks(BF, [abstract_code]),
+ %% OTP-12719: Since 'undefined' is no longer added by the Erlang
+ %% Parser, the number of 'undefined' is 4. It used to be 5.
+ 4 = count_atom(A, undefined),
ok.
count_atom(A, A) ->
@@ -940,8 +884,6 @@ count_atom(L, A) when is_list(L) ->
count_atom(_, _) ->
0.
-maps_syntax(doc) -> "Maps syntax";
-maps_syntax(suite) -> [];
maps_syntax(Config) when is_list(Config) ->
Ts = [{map_fun_1,
<<"t() ->\n"
@@ -972,9 +914,7 @@ maps_syntax(Config) when is_list(Config) ->
ok.
-otp_8567(doc) ->
- "OTP_8567. Avoid duplicated 'undefined' in record field types.";
-otp_8567(suite) -> [];
+%% OTP_8567. Avoid duplicated 'undefined' in record field types.
otp_8567(Config) when is_list(Config) ->
FileName = filename('otp_8567.erl', Config),
C = <<"-module otp_8567.\n"
@@ -983,8 +923,8 @@ otp_8567(Config) when is_list(Config) ->
"-record r, {a}.\n"
"-record s, {a :: integer()}.\n"
"-type t() :: {#r{},#s{}}.\n">>,
- ?line ok = file:write_file(FileName, C),
- ?line {error,[{_,[{3,erl_parse,["syntax error before: ","')'"]}]}],_} =
+ ok = file:write_file(FileName, C),
+ {error,[{_,[{3,erl_parse,["syntax error before: ","')'"]}]}],_} =
compile:file(FileName, [return]),
F = <<"-module(otp_8567).\n"
@@ -998,28 +938,18 @@ otp_8567(Config) when is_list(Config) ->
"t() ->\n"
" 3.\n"
"\n"
- "-spec(t1/1 :: (ot()) -> ot1()).\n"
- "t1(A) ->\n"
- " A.\n"
- "\n"
"-spec(t2 (ot()) -> ot1()).\n"
"t2(A) ->\n"
" A.\n"
"\n"
- "-spec(otp_8567:t3/1 :: (ot()) -> ot1()).\n"
- "t3(A) ->\n"
- " A.\n"
- "\n"
"-spec(otp_8567:t4 (ot()) -> ot1()).\n"
"t4(A) ->\n"
" A.\n">>,
- ?line ok = pp_forms(F),
+ ok = pp_forms(F),
ok.
-otp_8664(doc) ->
- "OTP_8664. Types with integer expressions.";
-otp_8664(suite) -> [];
+%% OTP_8664. Types with integer expressions.
otp_8664(Config) when is_list(Config) ->
FileName = filename('otp_8664.erl', Config),
C1 = <<"-module(otp_8664).\n"
@@ -1036,42 +966,38 @@ otp_8664(Config) when is_list(Config) ->
"-type t() :: t1() | t2() | t3() | b1() | u().\n"
"-spec t() -> t().\n"
"t() -> 3.\n">>,
- ?line ok = file:write_file(FileName, C1),
- ?line {ok, _, []} = compile:file(FileName, [return]),
+ ok = file:write_file(FileName, C1),
+ {ok, _, []} = compile:file(FileName, [return]),
C2 = <<"-module(otp_8664).\n"
"-export([t/0]).\n"
"-spec t() -> 9 and 4.\n"
"t() -> 0.\n">>,
- ?line ok = file:write_file(FileName, C2),
- ?line {error,[{_,[{3,erl_lint,{type_syntax,integer}}]}],_} =
+ ok = file:write_file(FileName, C2),
+ {error,[{_,[{3,erl_lint,{type_syntax,integer}}]}],_} =
compile:file(FileName, [return]),
ok.
-otp_9147(doc) ->
- "OTP_9147. Create well-formed types when adding 'undefined'.";
-otp_9147(suite) -> [];
+%% OTP-9147. Create well-formed types when adding 'undefined'.
otp_9147(Config) when is_list(Config) ->
FileName = filename('otp_9147.erl', Config),
C1 = <<"-module(otp_9147).\n"
"-export_type([undef/0]).\n"
"-record(undef, {f1 :: F1 :: a | b}).\n"
"-type undef() :: #undef{}.\n">>,
- ?line ok = file:write_file(FileName, C1),
- ?line {ok, _, []} =
+ ok = file:write_file(FileName, C1),
+ {ok, _, []} =
compile:file(FileName, [return,'P',{outdir,?privdir}]),
PFileName = filename('otp_9147.P', Config),
- ?line {ok, Bin} = file:read_file(PFileName),
+ {ok, Bin} = file:read_file(PFileName),
%% The parentheses around "F1 :: a | b" are new (bugfix).
- ?line true =
- lists:member("-record(undef,{f1 :: undefined | (F1 :: a | b)}).",
+ true =
+ lists:member("-record(undef,{f1 :: F1 :: a | b}).",
string:tokens(binary_to_list(Bin), "\n")),
ok.
-otp_10302(doc) ->
- "OTP-10302. Unicode characters scanner/parser.";
-otp_10302(suite) -> [];
+%% OTP-10302. Unicode characters scanner/parser.
otp_10302(Config) when is_list(Config) ->
Ts = [{uni_1,
<<"t() -> <<(<<\"abc\\x{aaa}\">>):3/binary>>.">>}
@@ -1108,9 +1034,7 @@ unicode_hook({foo,E}, I, P, H) ->
A = erl_anno:new(0),
erl_pp:expr({call,A,{atom,A,foo},[E]}, I, P, H).
-otp_10820(doc) ->
- "OTP-10820. Unicode filenames.";
-otp_10820(suite) -> [];
+%% OTP-10820. Unicode filenames.
otp_10820(Config) when is_list(Config) ->
C1 = <<"%% coding: utf-8\n -module(any).">>,
ok = do_otp_10820(Config, C1, "+pc latin1"),
@@ -1136,9 +1060,7 @@ file_attr_is_string("-file(\"" ++ _) -> true;
file_attr_is_string([_ | L]) ->
file_attr_is_string(L).
-otp_11100(doc) ->
- "OTP-11100. Fix printing of invalid forms.";
-otp_11100(suite) -> [];
+%% OTP-11100. Fix printing of invalid forms.
otp_11100(Config) when is_list(Config) ->
%% There are a few places where the added code ("options(none)")
%% doesn't make a difference (pp:bit_elem_type/1 is an example).
@@ -1173,9 +1095,7 @@ otp_11100(Config) when is_list(Config) ->
[]}}),
ok.
-otp_11861(doc) ->
- "OTP-11861. behaviour_info() and -callback.";
-otp_11861(suite) -> [];
+%% OTP-11861. behaviour_info() and -callback.
otp_11861(Config) when is_list(Config) ->
"-optional_callbacks([bar/0]).\n" =
pf({attribute,3,optional_callbacks,[{bar,0}]}),
@@ -1196,11 +1116,11 @@ compile(Config, Tests) ->
ok ->
BadL;
not_ok ->
- ?t:format("~nTest ~p failed.~n", [N]),
+ io:format("~nTest ~p failed.~n", [N]),
fail()
end;
Bad ->
- ?t:format("~nTest ~p failed. got~n ~p~n",
+ io:format("~nTest ~p failed. got~n ~p~n",
[N, Bad]),
fail()
end
@@ -1366,10 +1286,9 @@ filename(Name, Config) ->
filename:join(?privdir, Name).
fail() ->
- io:format("failed~n"),
- ?t:fail().
+ ct:fail(failed).
%% +fnu means a peer node has to be started; slave will not do
start_node(Name, Xargs) ->
- ?line PA = filename:dirname(code:which(?MODULE)),
+ PA = filename:dirname(code:which(?MODULE)),
test_server:start_node(Name, peer, [{args, "-pa " ++ PA ++ " " ++ Xargs}]).
diff --git a/lib/stdlib/test/erl_scan_SUITE.erl b/lib/stdlib/test/erl_scan_SUITE.erl
index 12ea3d128c..9432edc00f 100644
--- a/lib/stdlib/test/erl_scan_SUITE.erl
+++ b/lib/stdlib/test/erl_scan_SUITE.erl
@@ -18,11 +18,12 @@
%% %CopyrightEnd%
-module(erl_scan_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2,
init_per_group/2,end_per_group/2]).
--export([ error_1/1, error_2/1, iso88591/1, otp_7810/1, otp_10302/1,
- otp_10990/1, otp_10992/1, otp_11807/1]).
+-export([error_1/1, error_2/1, iso88591/1, otp_7810/1, otp_10302/1,
+ otp_10990/1, otp_10992/1, otp_11807/1]).
-import(lists, [nth/2,flatten/1]).
-import(io_lib, [print/1]).
@@ -30,7 +31,7 @@
%%
%% Define to run outside of test server
%%
-%-define(STANDALONE,1).
+%%-define(STANDALONE,1).
-ifdef(STANDALONE).
-compile(export_all).
@@ -42,23 +43,18 @@
%% config(data_dir, _) ->
%% ".".
-else.
--include_lib("test_server/include/test_server.hrl").
--export([init_per_testcase/2, end_per_testcase/2]).
+-include_lib("common_test/include/ct.hrl").
+-endif.
-init_per_testcase(_Case, Config) when is_list(Config) ->
- ?line Dog=test_server:timetrap(test_server:seconds(1200)),
- [{watchdog, Dog}|Config].
+init_per_testcase(_Case, Config) ->
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
--endif.
-
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,20}}].
all() ->
[{group, error}, iso88591, otp_7810, otp_10302, otp_10990, otp_10992,
@@ -81,20 +77,14 @@ end_per_group(_GroupName, Config) ->
-error_1(doc) ->
- ["(OTP-2347)"];
-error_1(suite) ->
- [];
+%% (OTP-2347)
error_1(Config) when is_list(Config) ->
- ?line {error, _, _} = erl_scan:string("'a"),
+ {error, _, _} = erl_scan:string("'a"),
ok.
-error_2(doc) ->
- ["Checks that format_error works on the error cases."];
-error_2(suite) ->
- [];
+%% Checks that format_error works on the error cases.
error_2(Config) when is_list(Config) ->
- ?line lists:foreach(fun check/1, error_cases()),
+ lists:foreach(fun check/1, error_cases()),
ok.
error_cases() ->
@@ -107,7 +97,7 @@ error_cases() ->
"2.3e",
"2.3e-",
"91#9"
-].
+ ].
assert_type(N, integer) when is_integer(N) ->
ok;
@@ -128,71 +118,66 @@ check_error({error, Info, EndLine}, Module0) ->
String = lists:flatten(Module0:format_error(Desc)),
true = io_lib:printable_list(String).
-iso88591(doc) -> ["Tests the support for ISO-8859-1 i.e Latin-1"];
-iso88591(suite) -> [];
+%% Tests the support for ISO-8859-1 i.e Latin-1.
iso88591(Config) when is_list(Config) ->
- ?line ok =
- case catch begin
- %% Some atom and variable names
- V1s = [$Á,$á,$é,$ë],
- V2s = [$N,$ä,$r],
- A1s = [$h,$ä,$r],
- A2s = [$ö,$r,$e],
- %% Test parsing atom and variable characters.
- {ok,Ts1,_} = erl_scan_string(V1s ++ " " ++ V2s ++
- "\327" ++
- A1s ++ " " ++ A2s),
- V1s = atom_to_list(element(3, nth(1, Ts1))),
- V2s = atom_to_list(element(3, nth(2, Ts1))),
- A1s = atom_to_list(element(3, nth(4, Ts1))),
- A2s = atom_to_list(element(3, nth(5, Ts1))),
- %% Test printing atoms
- A1s = flatten(print(element(3, nth(4, Ts1)))),
- A2s = flatten(print(element(3, nth(5, Ts1)))),
- %% Test parsing and printing strings.
- S1 = V1s ++ "\327" ++ A1s ++ "\250" ++ A2s,
- S1s = "\"" ++ S1 ++ "\"",
- {ok,Ts2,_} = erl_scan_string(S1s),
- S1 = element(3, nth(1, Ts2)),
- S1s = flatten(print(element(3, nth(1, Ts2)))),
- ok %It all worked
- end of
- {'EXIT',R} -> %Something went wrong!
- {error,R};
- ok -> ok %Aok
- end.
-
-otp_7810(doc) ->
- ["OTP-7810. White spaces, comments, and more.."];
-otp_7810(suite) ->
- [];
+ ok =
+ case catch begin
+ %% Some atom and variable names
+ V1s = [$Á,$á,$é,$ë],
+ V2s = [$N,$ä,$r],
+ A1s = [$h,$ä,$r],
+ A2s = [$ö,$r,$e],
+ %% Test parsing atom and variable characters.
+ {ok,Ts1,_} = erl_scan_string(V1s ++ " " ++ V2s ++
+ "\327" ++
+ A1s ++ " " ++ A2s),
+ V1s = atom_to_list(element(3, nth(1, Ts1))),
+ V2s = atom_to_list(element(3, nth(2, Ts1))),
+ A1s = atom_to_list(element(3, nth(4, Ts1))),
+ A2s = atom_to_list(element(3, nth(5, Ts1))),
+ %% Test printing atoms
+ A1s = flatten(print(element(3, nth(4, Ts1)))),
+ A2s = flatten(print(element(3, nth(5, Ts1)))),
+ %% Test parsing and printing strings.
+ S1 = V1s ++ "\327" ++ A1s ++ "\250" ++ A2s,
+ S1s = "\"" ++ S1 ++ "\"",
+ {ok,Ts2,_} = erl_scan_string(S1s),
+ S1 = element(3, nth(1, Ts2)),
+ S1s = flatten(print(element(3, nth(1, Ts2)))),
+ ok %It all worked
+ end of
+ {'EXIT',R} -> %Something went wrong!
+ {error,R};
+ ok -> ok %Aok
+ end.
+
+%% OTP-7810. White spaces, comments, and more...
otp_7810(Config) when is_list(Config) ->
- ?line ok = reserved_words(),
- ?line ok = atoms(),
- ?line ok = punctuations(),
- ?line ok = comments(),
- ?line ok = errors(),
- ?line ok = integers(),
- ?line ok = base_integers(),
- ?line ok = floats(),
- ?line ok = dots(),
- ?line ok = chars(),
- ?line ok = variables(),
- ?line ok = eof(),
- ?line ok = illegal(),
- ?line ok = crashes(),
-
- ?line ok = options(),
- ?line ok = token_info(),
- ?line ok = column_errors(),
- ?line ok = white_spaces(),
-
- ?line ok = unicode(),
-
- ?line ok = more_chars(),
- ?line ok = more_options(),
- ?line ok = attributes_info(),
- ?line ok = set_attribute(),
+ ok = reserved_words(),
+ ok = atoms(),
+ ok = punctuations(),
+ ok = comments(),
+ ok = errors(),
+ ok = integers(),
+ ok = base_integers(),
+ ok = floats(),
+ ok = dots(),
+ ok = chars(),
+ ok = variables(),
+ ok = eof(),
+ ok = illegal(),
+ ok = crashes(),
+
+ ok = options(),
+ ok = token_info(),
+ ok = column_errors(),
+ ok = white_spaces(),
+
+ ok = unicode(),
+
+ ok = more_chars(),
+ ok = more_options(),
+ ok = anno_info(),
ok.
@@ -203,10 +188,10 @@ reserved_words() ->
'rem', 'band', 'and', 'bor', 'bxor', 'bsl', 'bsr',
'or', 'xor'],
[begin
- ?line {RW, true} = {RW, erl_scan:reserved_word(RW)},
+ {RW, true} = {RW, erl_scan:reserved_word(RW)},
S = atom_to_list(RW),
Ts = [{RW,{1,1}}],
- ?line test_string(S, Ts)
+ test_string(S, Ts)
end || RW <- L],
ok.
@@ -215,14 +200,14 @@ atoms() ->
test_string("a
b", [{atom,{1,1},a},{atom,{2,18},b}]),
test_string("'a b'", [{atom,{1,1},'a b'}]),
- test_string("a", [{atom,{1,1},a}]),
- test_string("a@2", [{atom,{1,1},a@2}]),
- test_string([39,65,200,39], [{atom,{1,1},'AÈ'}]),
- test_string("ärlig östen", [{atom,{1,1},ärlig},{atom,{1,7},östen}]),
- ?line {ok,[{atom,_,'$a'}],{1,6}} =
- erl_scan_string("'$\\a'", {1,1}),
- ?line test("'$\\a'"),
- ok.
+ test_string("a", [{atom,{1,1},a}]),
+ test_string("a@2", [{atom,{1,1},a@2}]),
+ test_string([39,65,200,39], [{atom,{1,1},'AÈ'}]),
+ test_string("ärlig östen", [{atom,{1,1},ärlig},{atom,{1,7},östen}]),
+ {ok,[{atom,_,'$a'}],{1,6}} =
+ erl_scan_string("'$\\a'", {1,1}),
+ test("'$\\a'"),
+ ok.
punctuations() ->
L = ["<<", "<-", "<=", "<", ">>", ">=", ">", "->", "--",
@@ -232,7 +217,7 @@ punctuations() ->
[begin
W = list_to_atom(S),
Ts = [{W,{1,1}}],
- ?line test_string(S, Ts)
+ test_string(S, Ts)
end || S <- L],
Three = ["/=:=", "<=:=", "==:=", ">=:="], % three tokens...
No = Three ++ L,
@@ -248,18 +233,18 @@ punctuations() ->
W1 = list_to_atom(S1),
W2 = list_to_atom(S2),
Ts = [{W1,{1,1}},{W2,{1,-L2+1}}],
- ?line test_string(S, Ts)
+ test_string(S, Ts)
end || {S,[{L2,S1,S2}|_]} <- SL],
PTs1 = [{'!',{1,1}},{'(',{1,2}},{')',{1,3}},{',',{1,4}},{';',{1,5}},
{'=',{1,6}},{'[',{1,7}},{']',{1,8}},{'{',{1,9}},{'|',{1,10}},
{'}',{1,11}}],
- ?line test_string("!(),;=[]{|}", PTs1),
+ test_string("!(),;=[]{|}", PTs1),
PTs2 = [{'#',{1,1}},{'&',{1,2}},{'*',{1,3}},{'+',{1,4}},{'/',{1,5}},
{':',{1,6}},{'<',{1,7}},{'>',{1,8}},{'?',{1,9}},{'@',{1,10}},
{'\\',{1,11}},{'^',{1,12}},{'`',{1,13}},{'~',{1,14}}],
- ?line test_string("#&*+/:<>?@\\^`~", PTs2),
+ test_string("#&*+/:<>?@\\^`~", PTs2),
test_string(".. ", [{'..',{1,1}}]),
test_string("1 .. 2",
@@ -268,9 +253,9 @@ punctuations() ->
ok.
comments() ->
- ?line test("a %%\n b"),
+ test("a %%\n b"),
{ok,[],1} = erl_scan_string("%"),
- ?line test("a %%\n b"),
+ test("a %%\n b"),
{ok,[{atom,{1,1},a},{atom,{2,2},b}],{2,3}} =
erl_scan_string("a %%\n b", {1,1}),
{ok,[{atom,{1,1},a},{comment,{1,3},"%%"},{atom,{2,2},b}],{2,3}} =
@@ -290,30 +275,30 @@ comments() ->
ok.
errors() ->
- ?line {error,{1,erl_scan,{string,$',"qa"}},1} = erl_scan:string("'qa"), %'
+ {error,{1,erl_scan,{string,$',"qa"}},1} = erl_scan:string("'qa"), %'
{error,{{1,1},erl_scan,{string,$',"qa"}},{1,4}} = %'
erl_scan:string("'qa", {1,1}, []), %'
- ?line {error,{1,erl_scan,{string,$","str"}},1} = %"
+ {error,{1,erl_scan,{string,$","str"}},1} = %"
erl_scan:string("\"str"), %"
{error,{{1,1},erl_scan,{string,$","str"}},{1,5}} = %"
erl_scan:string("\"str", {1,1}, []), %"
- ?line {error,{1,erl_scan,char},1} = erl_scan:string("$"),
+ {error,{1,erl_scan,char},1} = erl_scan:string("$"),
{error,{{1,1},erl_scan,char},{1,2}} = erl_scan:string("$", {1,1}, []),
test_string([34,65,200,34], [{string,{1,1},"AÈ"}]),
test_string("\\", [{'\\',{1,1}}]),
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch {foo, erl_scan:string('$\\a', {1,1})}), % type error
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch {foo, erl_scan:tokens([], '$\\a', {1,1})}), % type error
- ?line "{a,tuple}" = erl_scan:format_error({a,tuple}),
+ "{a,tuple}" = erl_scan:format_error({a,tuple}),
ok.
integers() ->
[begin
I = list_to_integer(S),
Ts = [{integer,{1,1},I}],
- ?line test_string(S, Ts)
+ test_string(S, Ts)
end || S <- [[N] || N <- lists:seq($0, $9)] ++ ["2323","000"] ],
ok.
@@ -322,11 +307,11 @@ base_integers() ->
B = list_to_integer(BS),
I = erlang:list_to_integer(S, B),
Ts = [{integer,{1,1},I}],
- ?line test_string(BS++"#"++S, Ts)
+ test_string(BS++"#"++S, Ts)
end || {BS,S} <- [{"2","11"}, {"5","23234"}, {"12","05a"},
{"16","abcdef"}, {"16","ABCDEF"}] ],
- ?line {error,{1,erl_scan,{base,1}},1} = erl_scan:string("1#000"),
+ {error,{1,erl_scan,{base,1}},1} = erl_scan:string("1#000"),
{error,{{1,1},erl_scan,{base,1}},{1,2}} =
erl_scan:string("1#000", {1,1}, []),
@@ -334,7 +319,7 @@ base_integers() ->
[begin
Str = BS ++ "#" ++ S,
- ?line {error,{1,erl_scan,{illegal,integer}},1} =
+ {error,{1,erl_scan,{illegal,integer}},1} =
erl_scan:string(Str)
end || {BS,S} <- [{"3","3"},{"15","f"}, {"12","c"}] ],
@@ -350,12 +335,12 @@ floats() ->
[begin
F = list_to_float(FS),
Ts = [{float,{1,1},F}],
- ?line test_string(FS, Ts)
+ test_string(FS, Ts)
end || FS <- ["1.0","001.17","3.31200","1.0e0","1.0E17",
"34.21E-18", "17.0E+14"]],
test_string("1.e2", [{integer,{1,1},1},{'.',{1,2}},{atom,{1,3},e2}]),
- ?line {error,{1,erl_scan,{illegal,float}},1} =
+ {error,{1,erl_scan,{illegal,float}},1} =
erl_scan:string("1.0e400"),
{error,{{1,1},erl_scan,{illegal,float}},{1,8}} =
erl_scan:string("1.0e400", {1,1}, []),
@@ -376,31 +361,26 @@ dots() ->
{".% öh",{ok,[{dot,1}],1}, {ok,[{dot,{1,1}}],{1,6}}},
{".%\n", {ok,[{dot,1}],2}, {ok,[{dot,{1,1}}],{2,1}}},
{".$", {error,{1,erl_scan,char},1},
- {error,{{1,2},erl_scan,char},{1,3}}},
+ {error,{{1,2},erl_scan,char},{1,3}}},
{".$\\", {error,{1,erl_scan,char},1},
{error,{{1,2},erl_scan,char},{1,4}}},
{".a", {ok,[{'.',1},{atom,1,a}],1},
- {ok,[{'.',{1,1}},{atom,{1,2},a}],{1,3}}}
+ {ok,[{'.',{1,1}},{atom,{1,2},a}],{1,3}}}
],
[begin
R = erl_scan_string(S),
R2 = erl_scan_string(S, {1,1}, [])
end || {S, R, R2} <- Dot],
- ?line {ok,[{dot,_}=T1],{1,2}} = erl_scan:string(".", {1,1}, text),
- ?line [{column,1},{length,1},{line,1},{text,"."}] =
- erl_scan:token_info(T1, [column, length, line, text]),
- ?line {ok,[{dot,_}=T2],{1,3}} = erl_scan:string(".%", {1,1}, text),
- ?line [{column,1},{length,1},{line,1},{text,"."}] =
- erl_scan:token_info(T2, [column, length, line, text]),
- ?line {ok,[{dot,_}=T3],{1,6}} =
+ {ok,[{dot,_}=T1],{1,2}} = erl_scan:string(".", {1,1}, text),
+ [1, 1, "."] = token_info(T1),
+ {ok,[{dot,_}=T2],{1,3}} = erl_scan:string(".%", {1,1}, text),
+ [1, 1, "."] = token_info(T2),
+ {ok,[{dot,_}=T3],{1,6}} =
erl_scan:string(".% öh", {1,1}, text),
- ?line [{column,1},{length,1},{line,1},{text,"."}] =
- erl_scan:token_info(T3, [column, length, line, text]),
- ?line {error,{{1,2},erl_scan,char},{1,3}} =
- erl_scan:string(".$", {1,1}),
- ?line {error,{{1,2},erl_scan,char},{1,4}} =
- erl_scan:string(".$\\", {1,1}),
+ [1, 1, "."] = token_info(T3),
+ {error,{{1,2},erl_scan,char},{1,3}} = erl_scan:string(".$", {1,1}),
+ {error,{{1,2},erl_scan,char},{1,4}} = erl_scan:string(".$\\", {1,1}),
test_string(". ", [{dot,{1,1}}]),
test_string(". ", [{dot,{1,1}}]),
@@ -413,45 +393,45 @@ dots() ->
test_string(".a", [{'.',{1,1}},{atom,{1,2},a}]),
test_string("%. \n. ", [{dot,{2,1}}]),
- ?line {more,C} = erl_scan:tokens([], "%. ",{1,1}, return),
+ {more,C} = erl_scan:tokens([], "%. ",{1,1}, return),
{done,{ok,[{comment,{1,1},"%. "},
{white_space,{1,4},"\n"},
{dot,{2,1}}],
{2,3}}, ""} =
erl_scan_tokens(C, "\n. ", {1,1}, return), % any loc, any options
- ?line [test_string(S, R) ||
- {S, R} <- [{".$\n", [{'.',{1,1}},{char,{1,2},$\n}]},
- {"$\\\n", [{char,{1,1},$\n}]},
- {"'\\\n'", [{atom,{1,1},'\n'}]},
- {"$\n", [{char,{1,1},$\n}]}] ],
+ [test_string(S, R) ||
+ {S, R} <- [{".$\n", [{'.',{1,1}},{char,{1,2},$\n}]},
+ {"$\\\n", [{char,{1,1},$\n}]},
+ {"'\\\n'", [{atom,{1,1},'\n'}]},
+ {"$\n", [{char,{1,1},$\n}]}] ],
ok.
chars() ->
[begin
L = lists:flatten(io_lib:format("$\\~.8b", [C])),
Ts = [{char,{1,1},C}],
- ?line test_string(L, Ts)
+ test_string(L, Ts)
end || C <- lists:seq(0, 255)],
%% Leading zeroes...
[begin
L = lists:flatten(io_lib:format("$\\~3.8.0b", [C])),
Ts = [{char,{1,1},C}],
- ?line test_string(L, Ts)
+ test_string(L, Ts)
end || C <- lists:seq(0, 255)],
%% $\^\n now increments the line...
[begin
L = "$\\^" ++ [C],
Ts = [{char,{1,1},C band 2#11111}],
- ?line test_string(L, Ts)
+ test_string(L, Ts)
end || C <- lists:seq(0, 255)],
[begin
L = "$\\" ++ [C],
Ts = [{char,{1,1},V}],
- ?line test_string(L, Ts)
+ test_string(L, Ts)
end || {C,V} <- [{$n,$\n}, {$r,$\r}, {$t,$\t}, {$v,$\v},
{$b,$\b}, {$f,$\f}, {$e,$\e}, {$s,$\s},
{$d,$\d}]],
@@ -464,13 +444,13 @@ chars() ->
[begin
L = "$\\" ++ [C],
Ts = [{char,{1,1},C}],
- ?line test_string(L, Ts)
+ test_string(L, Ts)
end || C <- lists:seq(0, 255) -- No],
[begin
L = "'$\\" ++ [C] ++ "'",
Ts = [{atom,{1,1},list_to_atom("$"++[C])}],
- ?line test_string(L, Ts)
+ test_string(L, Ts)
end || C <- lists:seq(0, 255) -- No],
test_string("\"\\013a\\\n\"", [{string,{1,1},"\va\n"}]),
@@ -482,17 +462,17 @@ chars() ->
[begin
L = "$" ++ [C],
Ts = [{char,{1,1},C}],
- ?line test_string(L, Ts)
+ test_string(L, Ts)
end || C <- lists:seq(0, 255) -- (No ++ [$\\])],
test_string("$\n", [{char,{1,1},$\n}]),
- ?line {error,{{1,1},erl_scan,char},{1,4}} =
+ {error,{{1,1},erl_scan,char},{1,4}} =
erl_scan:string("$\\^",{1,1}),
test_string("$\\\n", [{char,{1,1},$\n}]),
%% Robert's scanner returns line 1:
test_string("$\\\n", [{char,{1,1},$\n}]),
test_string("$\n\n", [{char,{1,1},$\n}]),
- ?line test("$\n\n"),
+ test("$\n\n"),
ok.
@@ -505,30 +485,30 @@ variables() ->
ok.
eof() ->
- ?line {done,{eof,1},eof} = erl_scan:tokens([], eof, 1),
+ {done,{eof,1},eof} = erl_scan:tokens([], eof, 1),
{more, C1} = erl_scan:tokens([]," \n", 1),
- ?line {done,{eof,2},eof} = erl_scan:tokens(C1, eof, 1),
+ {done,{eof,2},eof} = erl_scan:tokens(C1, eof, 1),
{more, C2} = erl_scan:tokens([], "abra", 1),
%% An error before R13A.
- %% ?line {done,Err={error,{1,erl_scan,scan},1},eof} =
- ?line {done,{ok,[{atom,1,abra}],1},eof} =
+ %% {done,Err={error,{1,erl_scan,scan},1},eof} =
+ {done,{ok,[{atom,1,abra}],1},eof} =
erl_scan_tokens(C2, eof, 1),
%% With column.
- ?line {more, C3} = erl_scan:tokens([]," \n",{1,1}),
- ?line {done,{eof,{2,1}},eof} = erl_scan:tokens(C3, eof, 1),
+ {more, C3} = erl_scan:tokens([]," \n",{1,1}),
+ {done,{eof,{2,1}},eof} = erl_scan:tokens(C3, eof, 1),
{more, C4} = erl_scan:tokens([], "abra", {1,1}),
%% An error before R13A.
- %% ?line {done,{error,{{1,1},erl_scan,scan},{1,5}},eof} =
- ?line {done,{ok,[{atom,_,abra}],{1,5}},eof} =
+ %% {done,{error,{{1,1},erl_scan,scan},{1,5}},eof} =
+ {done,{ok,[{atom,_,abra}],{1,5}},eof} =
erl_scan_tokens(C4, eof, 1),
%% Robert's scanner returns "" as LeftoverChars;
%% the R12B scanner returns eof as LeftoverChars: (eof is correct)
- ?line {more, C5} = erl_scan:tokens([], "a", 1),
+ {more, C5} = erl_scan:tokens([], "a", 1),
%% An error before R13A.
- %% ?line {done,{error,{1,erl_scan,scan},1},eof} =
- ?line {done,{ok,[{atom,1,a}],1},eof} =
+ %% {done,{error,{1,erl_scan,scan},1},eof} =
+ {done,{ok,[{atom,1,a}],1},eof} =
erl_scan_tokens(C5,eof,1),
%% With column.
@@ -539,7 +519,7 @@ eof() ->
erl_scan_tokens(C6,eof,1),
%% A dot followed by eof is special:
- ?line {more, C} = erl_scan:tokens([], "a.", 1),
+ {more, C} = erl_scan:tokens([], "a.", 1),
{done,{ok,[{atom,1,a},{dot,1}],1},eof} = erl_scan_tokens(C,eof,1),
{ok,[{atom,1,foo},{dot,1}],1} = erl_scan_string("foo."),
@@ -554,100 +534,100 @@ eof() ->
illegal() ->
Atom = lists:duplicate(1000, $a),
- ?line {error,{1,erl_scan,{illegal,atom}},1} = erl_scan:string(Atom),
- ?line {done,{error,{1,erl_scan,{illegal,atom}},1},". "} =
+ {error,{1,erl_scan,{illegal,atom}},1} = erl_scan:string(Atom),
+ {done,{error,{1,erl_scan,{illegal,atom}},1},". "} =
erl_scan:tokens([], Atom++". ", 1),
QAtom = "'" ++ Atom ++ "'",
- ?line {error,{1,erl_scan,{illegal,atom}},1} = erl_scan:string(QAtom),
- ?line {done,{error,{1,erl_scan,{illegal,atom}},1},". "} =
+ {error,{1,erl_scan,{illegal,atom}},1} = erl_scan:string(QAtom),
+ {done,{error,{1,erl_scan,{illegal,atom}},1},". "} =
erl_scan:tokens([], QAtom++". ", 1),
Var = lists:duplicate(1000, $A),
- ?line {error,{1,erl_scan,{illegal,var}},1} = erl_scan:string(Var),
- ?line {done,{error,{1,erl_scan,{illegal,var}},1},". "} =
+ {error,{1,erl_scan,{illegal,var}},1} = erl_scan:string(Var),
+ {done,{error,{1,erl_scan,{illegal,var}},1},". "} =
erl_scan:tokens([], Var++". ", 1),
Float = "1" ++ lists:duplicate(400, $0) ++ ".0",
- ?line {error,{1,erl_scan,{illegal,float}},1} = erl_scan:string(Float),
- ?line {done,{error,{1,erl_scan,{illegal,float}},1},". "} =
+ {error,{1,erl_scan,{illegal,float}},1} = erl_scan:string(Float),
+ {done,{error,{1,erl_scan,{illegal,float}},1},". "} =
erl_scan:tokens([], Float++". ", 1),
String = "\"43\\x{aaaaaa}34\"",
- ?line {error,{1,erl_scan,{illegal,character}},1} = erl_scan:string(String),
- ?line {done,{error,{1,erl_scan,{illegal,character}},1},"34\". "} =
+ {error,{1,erl_scan,{illegal,character}},1} = erl_scan:string(String),
+ {done,{error,{1,erl_scan,{illegal,character}},1},"34\". "} =
%% Would be nice if `34\"' were skipped...
%% Maybe, but then the LeftOverChars would not be the characters
%% immediately following the end location of the error.
erl_scan:tokens([], String++". ", 1),
- ?line {error,{{1,1},erl_scan,{illegal,atom}},{1,1001}} =
+ {error,{{1,1},erl_scan,{illegal,atom}},{1,1001}} =
erl_scan:string(Atom, {1,1}),
- ?line {done,{error,{{1,5},erl_scan,{illegal,atom}},{1,1005}},". "} =
+ {done,{error,{{1,5},erl_scan,{illegal,atom}},{1,1005}},". "} =
erl_scan:tokens([], "foo "++Atom++". ", {1,1}),
- ?line {error,{{1,1},erl_scan,{illegal,atom}},{1,1003}} =
+ {error,{{1,1},erl_scan,{illegal,atom}},{1,1003}} =
erl_scan:string(QAtom, {1,1}),
- ?line {done,{error,{{1,5},erl_scan,{illegal,atom}},{1,1007}},". "} =
+ {done,{error,{{1,5},erl_scan,{illegal,atom}},{1,1007}},". "} =
erl_scan:tokens([], "foo "++QAtom++". ", {1,1}),
- ?line {error,{{1,1},erl_scan,{illegal,var}},{1,1001}} =
+ {error,{{1,1},erl_scan,{illegal,var}},{1,1001}} =
erl_scan:string(Var, {1,1}),
- ?line {done,{error,{{1,5},erl_scan,{illegal,var}},{1,1005}},". "} =
+ {done,{error,{{1,5},erl_scan,{illegal,var}},{1,1005}},". "} =
erl_scan:tokens([], "foo "++Var++". ", {1,1}),
- ?line {error,{{1,1},erl_scan,{illegal,float}},{1,404}} =
+ {error,{{1,1},erl_scan,{illegal,float}},{1,404}} =
erl_scan:string(Float, {1,1}),
- ?line {done,{error,{{1,5},erl_scan,{illegal,float}},{1,408}},". "} =
+ {done,{error,{{1,5},erl_scan,{illegal,float}},{1,408}},". "} =
erl_scan:tokens([], "foo "++Float++". ", {1,1}),
- ?line {error,{{1,4},erl_scan,{illegal,character}},{1,14}} =
+ {error,{{1,4},erl_scan,{illegal,character}},{1,14}} =
erl_scan:string(String, {1,1}),
- ?line {done,{error,{{1,4},erl_scan,{illegal,character}},{1,14}},"34\". "} =
+ {done,{error,{{1,4},erl_scan,{illegal,character}},{1,14}},"34\". "} =
erl_scan:tokens([], String++". ", {1,1}),
ok.
crashes() ->
- ?line {'EXIT',_} = (catch {foo, erl_scan:string([-1])}), % type error
- ?line {'EXIT',_} = (catch {foo, erl_scan:string("$"++[-1])}),
- ?line {'EXIT',_} = (catch {foo, erl_scan:string("$\\"++[-1])}),
- ?line {'EXIT',_} = (catch {foo, erl_scan:string("$\\^"++[-1])}),
- ?line {'EXIT',_} = (catch {foo, erl_scan:string([$",-1,$"],{1,1})}),
- ?line {'EXIT',_} = (catch {foo, erl_scan:string("\"\\v"++[-1,$"])}), %$"
- ?line {'EXIT',_} = (catch {foo, erl_scan:string([$",-1,$"])}),
- ?line {'EXIT',_} = (catch {foo, erl_scan:string("% foo"++[-1])}),
- ?line {'EXIT',_} =
+ {'EXIT',_} = (catch {foo, erl_scan:string([-1])}), % type error
+ {'EXIT',_} = (catch {foo, erl_scan:string("$"++[-1])}),
+ {'EXIT',_} = (catch {foo, erl_scan:string("$\\"++[-1])}),
+ {'EXIT',_} = (catch {foo, erl_scan:string("$\\^"++[-1])}),
+ {'EXIT',_} = (catch {foo, erl_scan:string([$",-1,$"],{1,1})}),
+ {'EXIT',_} = (catch {foo, erl_scan:string("\"\\v"++[-1,$"])}), %$"
+ {'EXIT',_} = (catch {foo, erl_scan:string([$",-1,$"])}),
+ {'EXIT',_} = (catch {foo, erl_scan:string("% foo"++[-1])}),
+ {'EXIT',_} =
(catch {foo, erl_scan:string("% foo"++[-1],{1,1})}),
- ?line {'EXIT',_} = (catch {foo, erl_scan:string([a])}), % type error
- ?line {'EXIT',_} = (catch {foo, erl_scan:string("$"++[a])}),
- ?line {'EXIT',_} = (catch {foo, erl_scan:string("$\\"++[a])}),
- ?line {'EXIT',_} = (catch {foo, erl_scan:string("$\\^"++[a])}),
- ?line {'EXIT',_} = (catch {foo, erl_scan:string([$",a,$"],{1,1})}),
- ?line {'EXIT',_} = (catch {foo, erl_scan:string("\"\\v"++[a,$"])}), %$"
- ?line {'EXIT',_} = (catch {foo, erl_scan:string([$",a,$"])}),
- ?line {'EXIT',_} = (catch {foo, erl_scan:string("% foo"++[a])}),
- ?line {'EXIT',_} =
+ {'EXIT',_} = (catch {foo, erl_scan:string([a])}), % type error
+ {'EXIT',_} = (catch {foo, erl_scan:string("$"++[a])}),
+ {'EXIT',_} = (catch {foo, erl_scan:string("$\\"++[a])}),
+ {'EXIT',_} = (catch {foo, erl_scan:string("$\\^"++[a])}),
+ {'EXIT',_} = (catch {foo, erl_scan:string([$",a,$"],{1,1})}),
+ {'EXIT',_} = (catch {foo, erl_scan:string("\"\\v"++[a,$"])}), %$"
+ {'EXIT',_} = (catch {foo, erl_scan:string([$",a,$"])}),
+ {'EXIT',_} = (catch {foo, erl_scan:string("% foo"++[a])}),
+ {'EXIT',_} =
(catch {foo, erl_scan:string("% foo"++[a],{1,1})}),
- ?line {'EXIT',_} = (catch {foo, erl_scan:string([3.0])}), % type error
+ {'EXIT',_} = (catch {foo, erl_scan:string([3.0])}), % type error
ok.
options() ->
%% line and column are not options, but tested here
- ?line {ok,[{atom,1,foo},{white_space,1," "},{comment,1,"% bar"}], 1} =
+ {ok,[{atom,1,foo},{white_space,1," "},{comment,1,"% bar"}], 1} =
erl_scan_string("foo % bar", 1, return),
- ?line {ok,[{atom,1,foo},{white_space,1," "}],1} =
+ {ok,[{atom,1,foo},{white_space,1," "}],1} =
erl_scan_string("foo % bar", 1, return_white_spaces),
- ?line {ok,[{atom,1,foo},{comment,1,"% bar"}],1} =
+ {ok,[{atom,1,foo},{comment,1,"% bar"}],1} =
erl_scan_string("foo % bar", 1, return_comments),
- ?line {ok,[{atom,17,foo}],17} =
+ {ok,[{atom,17,foo}],17} =
erl_scan_string("foo % bar", 17),
- ?line {'EXIT',{function_clause,_}} =
+ {'EXIT',{function_clause,_}} =
(catch {foo,
erl_scan:string("foo % bar", {a,1}, [])}), % type error
- ?line {ok,[{atom,_,foo}],{17,18}} =
+ {ok,[{atom,_,foo}],{17,18}} =
erl_scan_string("foo % bar", {17,9}, []),
- ?line {'EXIT',{function_clause,_}} =
+ {'EXIT',{function_clause,_}} =
(catch {foo,
erl_scan:string("foo % bar", {1,0}, [])}), % type error
- ?line {ok,[{foo,1}],1} =
+ {ok,[{foo,1}],1} =
erl_scan_string("foo % bar",1, [{reserved_word_fun,
fun(W) -> W =:= foo end}]),
- ?line {'EXIT',{badarg,_}} =
+ {'EXIT',{badarg,_}} =
(catch {foo,
erl_scan:string("foo % bar",1, % type error
[{reserved_word_fun,
@@ -655,180 +635,107 @@ options() ->
ok.
more_options() ->
- ?line {ok,[{atom,A1,foo}],{19,20}} =
+ {ok,[{atom,_,foo}=T1],{19,20}} =
erl_scan:string("foo", {19,17},[]),
- ?line [{column,17},{line,19}] = erl_scan:attributes_info(A1),
- ?line {done,{ok,[{atom,A2,foo},{dot,_}],{19,22}},[]} =
+ {19,17} = erl_scan:location(T1),
+ {done,{ok,[{atom,_,foo}=T2,{dot,_}],{19,22}},[]} =
erl_scan:tokens([], "foo. ", {19,17}, [bad_opt]), % type error
- ?line [{column,17},{line,19}] = erl_scan:attributes_info(A2),
- ?line {ok,[{atom,A3,foo}],{19,20}} =
+ {19,17} = erl_scan:location(T2),
+ {ok,[{atom,_,foo}=T3],{19,20}} =
erl_scan:string("foo", {19,17},[text]),
- ?line [{column,17},{length,3},{line,19},{text,"foo"}] =
- erl_scan:attributes_info(A3),
+ {19,17} = erl_scan:location(T3),
+ "foo" = erl_scan:text(T3),
- ?line {ok,[{atom,A4,foo}],1} = erl_scan:string("foo", 1, [text]),
- ?line [{length,3},{line,1},{text,"foo"}] = erl_scan:attributes_info(A4),
+ {ok,[{atom,_,foo}=T4],1} = erl_scan:string("foo", 1, [text]),
+ 1 = erl_scan:line(T4),
+ 1 = erl_scan:location(T4),
+ "foo" = erl_scan:text(T4),
ok.
token_info() ->
- ?line {ok,[T1],_} = erl_scan:string("foo", {1,18}, [text]),
+ {ok,[T1],_} = erl_scan:string("foo", {1,18}, [text]),
+ {'EXIT',{badarg,_}} =
+ (catch {foo, erl_scan:category(foo)}), % type error
{'EXIT',{badarg,_}} =
- (catch {foo, erl_scan:token_info(T1, foo)}), % type error
- ?line {line,1} = erl_scan:token_info(T1, line),
- ?line {column,18} = erl_scan:token_info(T1, column),
- ?line {length,3} = erl_scan:token_info(T1, length),
- ?line {text,"foo"} = erl_scan:token_info(T1, text),
- ?line [{category,atom},{column,18},{length,3},{line,1},
- {symbol,foo},{text,"foo"}] =
- erl_scan:token_info(T1),
- ?line [{length,3},{column,18}] =
- erl_scan:token_info(T1, [length, column]),
- ?line [{location,{1,18}}] =
- erl_scan:token_info(T1, [location]),
- ?line {category,atom} = erl_scan:token_info(T1, category),
- ?line [{symbol,foo}] = erl_scan:token_info(T1, [symbol]),
-
- ?line {ok,[T2],_} = erl_scan:string("foo", 1, []),
- ?line {line,1} = erl_scan:token_info(T2, line),
- ?line undefined = erl_scan:token_info(T2, column),
- ?line undefined = erl_scan:token_info(T2, length),
- ?line undefined = erl_scan:token_info(T2, text),
- ?line {location,1} = erl_scan:token_info(T2, location),
- ?line [{category,atom},{line,1},{symbol,foo}] = erl_scan:token_info(T2),
- ?line [{line,1}] = erl_scan:token_info(T2, [length, line]),
-
- ?line {ok,[T3],_} = erl_scan:string("=", 1, []),
- ?line [{line,1}] = erl_scan:token_info(T3, [column, line]),
- ?line {category,'='} = erl_scan:token_info(T3, category),
- ?line [{symbol,'='}] = erl_scan:token_info(T3, [symbol]),
+ (catch {foo, erl_scan:symbol(foo)}), % type error
+ atom = erl_scan:category(T1),
+ foo = erl_scan:symbol(T1),
+
+ {ok,[T2],_} = erl_scan:string("foo", 1, []),
+ 1 = erl_scan:line(T2),
+ undefined = erl_scan:column(T2),
+ undefined = erl_scan:text(T2),
+ 1 = erl_scan:location(T2),
+
+ {ok,[T3],_} = erl_scan:string("=", 1, []),
+ '=' = erl_scan:category(T3),
+ '=' = erl_scan:symbol(T3),
ok.
-attributes_info() ->
- ?line {'EXIT',_} =
- (catch {foo,erl_scan:attributes_info(foo)}), % type error
- [{line,18}] = erl_scan:attributes_info(erl_anno:new(18)),
- {location,19} =
- erl_scan:attributes_info(erl_anno:new(19), location),
- ?line {ok,[{atom,A0,foo}],_} = erl_scan:string("foo", 19, [text]),
- ?line {location,19} = erl_scan:attributes_info(A0, location),
-
- ?line {ok,[{atom,A3,foo}],_} = erl_scan:string("foo", {1,3}, [text]),
- ?line {line,1} = erl_scan:attributes_info(A3, line),
- ?line {column,3} = erl_scan:attributes_info(A3, column),
- ?line {location,{1,3}} = erl_scan:attributes_info(A3, location),
- ?line {text,"foo"} = erl_scan:attributes_info(A3, text),
-
- ?line {ok,[{atom,A4,foo}],_} = erl_scan:string("foo", 2, [text]),
- ?line {line,2} = erl_scan:attributes_info(A4, line),
- ?line undefined = erl_scan:attributes_info(A4, column),
- ?line {location,2} = erl_scan:attributes_info(A4, location),
- ?line {text,"foo"} = erl_scan:attributes_info(A4, text),
-
- ?line {ok,[{atom,A5,foo}],_} = erl_scan:string("foo", {1,3}, []),
- ?line {line,1} = erl_scan:attributes_info(A5, line),
- ?line {column,3} = erl_scan:attributes_info(A5, column),
- ?line {location,{1,3}} = erl_scan:attributes_info(A5, location),
- ?line undefined = erl_scan:attributes_info(A5, text),
-
- ?line undefined = erl_scan:attributes_info([], line), % type error
+anno_info() ->
+ {'EXIT',_} =
+ (catch {foo,erl_scan:line(foo)}), % type error
+ {ok,[{atom,_,foo}=T0],_} = erl_scan:string("foo", 19, [text]),
+ 19 = erl_scan:location(T0),
+ 19 = erl_scan:end_location(T0),
+
+ {ok,[{atom,_,foo}=T3],_} = erl_scan:string("foo", {1,3}, [text]),
+ 1 = erl_scan:line(T3),
+ 3 = erl_scan:column(T3),
+ {1,3} = erl_scan:location(T3),
+ {1,6} = erl_scan:end_location(T3),
+ "foo" = erl_scan:text(T3),
+
+ {ok,[{atom,_,foo}=T4],_} = erl_scan:string("foo", 2, [text]),
+ 2 = erl_scan:line(T4),
+ undefined = erl_scan:column(T4),
+ 2 = erl_scan:location(T4),
+ "foo" = erl_scan:text(T4),
+
+ {ok,[{atom,_,foo}=T5],_} = erl_scan:string("foo", {1,3}, []),
+ 1 = erl_scan:line(T5),
+ 3 = erl_scan:column(T5),
+ {1,3} = erl_scan:location(T5),
+ undefined = erl_scan:text(T5),
ok.
-set_attribute() ->
- F = fun(Line) -> -Line end,
- Anno2 = erl_anno:new(2),
- A0 = erl_scan:set_attribute(line, Anno2, F),
- {line, -2} = erl_scan:attributes_info(A0, line),
- ?line {ok,[{atom,A1,foo}],_} = erl_scan:string("foo", {9,17}),
- ?line A2 = erl_scan:set_attribute(line, A1, F),
- ?line {line,-9} = erl_scan:attributes_info(A2, line),
- ?line {location,{-9,17}} = erl_scan:attributes_info(A2, location),
- ?line [{line,-9},{column,17}] =
- erl_scan:attributes_info(A2, [line,column,text]),
-
- F2 = fun(Line) -> {17,Line} end,
- ?line Attr1 = erl_scan:set_attribute(line, 2, F2),
- ?line {line,{17,2}} = erl_scan:attributes_info(Attr1, line),
- ?line undefined = erl_scan:attributes_info(Attr1, column),
- ?line {location,{17,2}} = % a bit mixed up
- erl_scan:attributes_info(Attr1, location),
-
- ?line A3 = erl_scan:set_attribute(line, A1, F2),
- ?line {line,{17,9}} = erl_scan:attributes_info(A3, line),
- ?line {location,{{17,9},17}} = erl_scan:attributes_info(A3, location),
- ?line [{line,{17,9}},{column,17}] =
- erl_scan:attributes_info(A3, [line,column,text]),
-
- ?line {ok,[{atom,A4,foo}],_} = erl_scan:string("foo", {9,17}, [text]),
- ?line A5 = erl_scan:set_attribute(line, A4, F),
- ?line {line,-9} = erl_scan:attributes_info(A5, line),
- ?line {location,{-9,17}} = erl_scan:attributes_info(A5, location),
- ?line [{line,-9},{column,17},{text,"foo"}] =
- erl_scan:attributes_info(A5, [line,column,text]),
-
- ?line {ok,[{atom,A6,foo}],_} = erl_scan:string("foo", 11, [text]),
- ?line A7 = erl_scan:set_attribute(line, A6, F2),
- %% Incompatible with pre 18:
- %% {line,{17,11}} = erl_scan:attributes_info(A7, line),
- {line,17} = erl_scan:attributes_info(A7, line),
- ?line {location,{17,11}} = % mixed up
- erl_scan:attributes_info(A7, location),
- %% Incompatible with pre 18:
- %% [{line,{17,11}},{text,"foo"}] =
- %% erl_scan:attributes_info(A7, [line,column,text]),
- [{line,17},{column,11},{text,"foo"}] =
- erl_scan:attributes_info(A7, [line,column,text]),
-
- ?line {'EXIT',_} =
- (catch {foo, erl_scan:set_attribute(line, [], F2)}), % type error
- ?line {'EXIT',{badarg,_}} =
- (catch {foo, erl_scan:set_attribute(column, [], F2)}), % type error
-
- Attr10 = erl_anno:new(8),
- Attr20 = erl_scan:set_attribute(line, Attr10,
- fun(L) -> {nos,'X',L} end),
- %% OTP-9412
- Attr30 = erl_scan:set_attribute(line, Attr20,
- fun({nos,_V,VL}) -> VL end),
- 8 = erl_anno:to_term(Attr30),
- ok.
-
column_errors() ->
- ?line {error,{{1,1},erl_scan,{string,$',""}},{1,3}} = % $'
+ {error,{{1,1},erl_scan,{string,$',""}},{1,3}} = % $'
erl_scan:string("'\\",{1,1}),
- ?line {error,{{1,1},erl_scan,{string,$",""}},{1,3}} = % $"
+ {error,{{1,1},erl_scan,{string,$",""}},{1,3}} = % $"
erl_scan:string("\"\\",{1,1}),
- ?line {error,{{1,1},erl_scan,{string,$',""}},{1,2}} = % $'
+ {error,{{1,1},erl_scan,{string,$',""}},{1,2}} = % $'
erl_scan:string("'",{1,1}),
- ?line {error,{{1,1},erl_scan,{string,$",""}},{1,2}} = % $"
+ {error,{{1,1},erl_scan,{string,$",""}},{1,2}} = % $"
erl_scan:string("\"",{1,1}),
- ?line {error,{{1,1},erl_scan,char},{1,2}} =
+ {error,{{1,1},erl_scan,char},{1,2}} =
erl_scan:string("$",{1,1}),
- ?line {error,{{1,2},erl_scan,{string,$',"1234567890123456"}},{1,20}} = %'
+ {error,{{1,2},erl_scan,{string,$',"1234567890123456"}},{1,20}} = %'
erl_scan:string(" '12345678901234567", {1,1}),
- ?line {error,{{1,2},erl_scan,{string,$',"123456789012345 "}}, {1,20}} = %'
+ {error,{{1,2},erl_scan,{string,$',"123456789012345 "}}, {1,20}} = %'
erl_scan:string(" '123456789012345\\s", {1,1}),
- ?line {error,{{1,2},erl_scan,{string,$","1234567890123456"}},{1,20}} = %"
+ {error,{{1,2},erl_scan,{string,$","1234567890123456"}},{1,20}} = %"
erl_scan:string(" \"12345678901234567", {1,1}),
- ?line {error,{{1,2},erl_scan,{string,$","123456789012345 "}}, {1,20}} = %"
+ {error,{{1,2},erl_scan,{string,$","123456789012345 "}}, {1,20}} = %"
erl_scan:string(" \"123456789012345\\s", {1,1}),
- ?line {error,{{1,2},erl_scan,{string,$',"1234567890123456"}},{2,1}} = %'
+ {error,{{1,2},erl_scan,{string,$',"1234567890123456"}},{2,1}} = %'
erl_scan:string(" '12345678901234567\n", {1,1}),
ok.
white_spaces() ->
- ?line {ok,[{white_space,_,"\r"},
+ {ok,[{white_space,_,"\r"},
{white_space,_," "},
{atom,_,a},
{white_space,_,"\n"}],
_} = erl_scan_string("\r a\n", {1,1}, return),
- ?line test("\r a\n"),
+ test("\r a\n"),
L = "{\"a\nb\", \"a\\nb\",\nabc\r,def}.\n\n",
- ?line {ok,[{'{',_},
+ {ok,[{'{',_},
{string,_,"a\nb"},
{',',_},
{white_space,_," "},
@@ -843,33 +750,33 @@ white_spaces() ->
{dot,_},
{white_space,_,"\n"}],
_} = erl_scan_string(L, {1,1}, return),
- ?line test(L),
- ?line test("\"\n\"\n"),
- ?line test("\n\r\n"),
- ?line test("\n\r"),
- ?line test("\r\n"),
- ?line test("\n\f"),
- ?line [test(lists:duplicate(N, $\t)) || N <- lists:seq(1, 20)],
- ?line [test([$\n|lists:duplicate(N, $\t)]) || N <- lists:seq(1, 20)],
- ?line [test(lists:duplicate(N, $\s)) || N <- lists:seq(1, 20)],
- ?line [test([$\n|lists:duplicate(N, $\s)]) || N <- lists:seq(1, 20)],
- ?line test("\v\f\n\v "),
- ?line test("\n\e\n\b\f\n\da\n"),
+ test(L),
+ test("\"\n\"\n"),
+ test("\n\r\n"),
+ test("\n\r"),
+ test("\r\n"),
+ test("\n\f"),
+ [test(lists:duplicate(N, $\t)) || N <- lists:seq(1, 20)],
+ [test([$\n|lists:duplicate(N, $\t)]) || N <- lists:seq(1, 20)],
+ [test(lists:duplicate(N, $\s)) || N <- lists:seq(1, 20)],
+ [test([$\n|lists:duplicate(N, $\s)]) || N <- lists:seq(1, 20)],
+ test("\v\f\n\v "),
+ test("\n\e\n\b\f\n\da\n"),
ok.
unicode() ->
- ?line {ok,[{char,1,83},{integer,1,45}],1} =
+ {ok,[{char,1,83},{integer,1,45}],1} =
erl_scan_string("$\\12345"), % not unicode
- ?line {error,{1,erl_scan,{illegal,character}},1} =
+ {error,{1,erl_scan,{illegal,character}},1} =
erl_scan:string([1089]),
- ?line {error,{{1,1},erl_scan,{illegal,character}},{1,2}} =
+ {error,{{1,1},erl_scan,{illegal,character}},{1,2}} =
erl_scan:string([1089], {1,1}),
{error,{1,erl_scan,{illegal,atom}},1} =
erl_scan:string("'a"++[1089]++"b'", 1),
{error,{{1,1},erl_scan,{illegal,atom}},{1,6}} =
erl_scan:string("'a"++[1089]++"b'", {1,1}),
- ?line test("\"a"++[1089]++"b\""),
+ test("\"a"++[1089]++"b\""),
{ok,[{char,1,1}],1} =
erl_scan_string([$$,$\\,$^,1089], 1),
@@ -877,7 +784,7 @@ unicode() ->
erl_scan:string("\"qa\x{aaa}", 1),
"unterminated string starting with \"qa"++[2730]++"\"" =
erl_scan:format_error(Error),
- ?line {error,{{1,1},erl_scan,_},{1,11}} =
+ {error,{{1,1},erl_scan,_},{1,11}} =
erl_scan:string("\"qa\\x{aaa}",{1,1}),
{error,{{1,1},erl_scan,{illegal,atom}},{1,12}} =
erl_scan:string("'qa\\x{aaa}'",{1,1}),
@@ -892,14 +799,13 @@ unicode() ->
erl_scan_string(Qs, 1),
{ok,[Q2],{1,9}} =
erl_scan:string("$\\x{aaa}", {1,1}, [text]),
- [{category,char},{column,1},{length,8},
- {line,1},{symbol,16#aaa},{text,Qs}] =
- erl_scan:token_info(Q2),
+ [{category,char},{column,1},{line,1},{symbol,16#aaa},{text,Qs}] =
+ token_info_long(Q2),
U1 = "\"\\x{aaa}\"",
- {ok,[{string,A1,[2730]}],{1,10}} = erl_scan:string(U1, {1,1}, [text]),
- [{line,1},{column,1},{text,"\"\\x{aaa}\""}] =
- erl_scan:attributes_info(A1, [line, column, text]),
+ {ok,[{string,_,[2730]}=T1],{1,10}} = erl_scan:string(U1, {1,1}, [text]),
+ {1,1} = erl_scan:location(T1),
+ "\"\\x{aaa}\"" = erl_scan:text(T1),
{ok,[{string,1,[2730]}],1} = erl_scan_string(U1, 1),
U2 = "\"\\x41\\x{fff}\\x42\"",
@@ -912,17 +818,17 @@ unicode() ->
{ok,[{string,1,[$\n,$\x{aaa},$\n]}],3} = erl_scan_string(U4, 1),
%% Keep these tests:
- ?line test(Qs),
- ?line test(U1),
- ?line test(U2),
- ?line test(U3),
- ?line test(U4),
+ test(Qs),
+ test(U1),
+ test(U2),
+ test(U3),
+ test(U4),
Str1 = "\"ab" ++ [1089] ++ "cd\"",
{ok,[{string,1,[$a,$b,1089,$c,$d]}],1} = erl_scan_string(Str1, 1),
{ok,[{string,{1,1},[$a,$b,1089,$c,$d]}],{1,8}} =
erl_scan_string(Str1, {1,1}),
- ?line test(Str1),
+ test(Str1),
Comment = "%% "++[1089],
{ok,[{comment,1,[$%,$%,$\s,1089]}],1} =
erl_scan_string(Comment, 1, [return]),
@@ -935,70 +841,67 @@ more_chars() ->
%% $\x{...}, $\xHH
%% All kinds of tests...
- ?line {ok,[{char,_,123}],{1,4}} =
+ {ok,[{char,_,123}],{1,4}} =
erl_scan_string("$\\{",{1,1}),
- ?line {more, C1} = erl_scan:tokens([], "$\\{", {1,1}),
- ?line {done,{ok,[{char,_,123}],{1,4}},eof} =
+ {more, C1} = erl_scan:tokens([], "$\\{", {1,1}),
+ {done,{ok,[{char,_,123}],{1,4}},eof} =
erl_scan_tokens(C1, eof, 1),
- ?line {ok,[{char,1,123},{atom,1,a},{'}',1}],1} =
+ {ok,[{char,1,123},{atom,1,a},{'}',1}],1} =
erl_scan_string("$\\{a}"),
- ?line {error,{{1,1},erl_scan,char},{1,4}} =
+ {error,{{1,1},erl_scan,char},{1,4}} =
erl_scan:string("$\\x", {1,1}),
- ?line {error,{{1,1},erl_scan,char},{1,5}} =
+ {error,{{1,1},erl_scan,char},{1,5}} =
erl_scan:string("$\\x{",{1,1}),
- ?line {more, C3} = erl_scan:tokens([], "$\\x", {1,1}),
- ?line {done,{error,{{1,1},erl_scan,char},{1,4}},eof} =
+ {more, C3} = erl_scan:tokens([], "$\\x", {1,1}),
+ {done,{error,{{1,1},erl_scan,char},{1,4}},eof} =
erl_scan:tokens(C3, eof, 1),
- ?line {error,{{1,1},erl_scan,char},{1,5}} =
+ {error,{{1,1},erl_scan,char},{1,5}} =
erl_scan:string("$\\x{",{1,1}),
- ?line {more, C2} = erl_scan:tokens([], "$\\x{", {1,1}),
- ?line {done,{error,{{1,1},erl_scan,char},{1,5}},eof} =
+ {more, C2} = erl_scan:tokens([], "$\\x{", {1,1}),
+ {done,{error,{{1,1},erl_scan,char},{1,5}},eof} =
erl_scan:tokens(C2, eof, 1),
- ?line {error,{1,erl_scan,{illegal,character}},1} =
+ {error,{1,erl_scan,{illegal,character}},1} =
erl_scan:string("$\\x{g}"),
- ?line {error,{{1,1},erl_scan,{illegal,character}},{1,5}} =
+ {error,{{1,1},erl_scan,{illegal,character}},{1,5}} =
erl_scan:string("$\\x{g}", {1,1}),
- ?line {error,{{1,1},erl_scan,{illegal,character}},{1,6}} =
+ {error,{{1,1},erl_scan,{illegal,character}},{1,6}} =
erl_scan:string("$\\x{}",{1,1}),
- ?line test("\"\\{0}\""),
- ?line test("\"\\x{0}\""),
- ?line test("\'\\{0}\'"),
- ?line test("\'\\x{0}\'"),
+ test("\"\\{0}\""),
+ test("\"\\x{0}\""),
+ test("\'\\{0}\'"),
+ test("\'\\x{0}\'"),
- ?line {error,{{2,3},erl_scan,{illegal,character}},{2,6}} =
+ {error,{{2,3},erl_scan,{illegal,character}},{2,6}} =
erl_scan:string("\"ab \n $\\x{g}\"",{1,1}),
- ?line {error,{{2,3},erl_scan,{illegal,character}},{2,6}} =
+ {error,{{2,3},erl_scan,{illegal,character}},{2,6}} =
erl_scan:string("\'ab \n $\\x{g}\'",{1,1}),
- ?line test("$\\{34}"),
- ?line test("$\\x{34}"),
- ?line test("$\\{377}"),
- ?line test("$\\x{FF}"),
- ?line test("$\\{400}"),
- ?line test("$\\x{100}"),
- ?line test("$\\x{10FFFF}"),
- ?line test("$\\x{10ffff}"),
- ?line test("\"$\n \\{1}\""),
- ?line {error,{1,erl_scan,{illegal,character}},1} =
+ test("$\\{34}"),
+ test("$\\x{34}"),
+ test("$\\{377}"),
+ test("$\\x{FF}"),
+ test("$\\{400}"),
+ test("$\\x{100}"),
+ test("$\\x{10FFFF}"),
+ test("$\\x{10ffff}"),
+ test("\"$\n \\{1}\""),
+ {error,{1,erl_scan,{illegal,character}},1} =
erl_scan:string("$\\x{110000}"),
- ?line {error,{{1,1},erl_scan,{illegal,character}},{1,12}} =
+ {error,{{1,1},erl_scan,{illegal,character}},{1,12}} =
erl_scan:string("$\\x{110000}", {1,1}),
- ?line {error,{{1,1},erl_scan,{illegal,character}},{1,4}} =
+ {error,{{1,1},erl_scan,{illegal,character}},{1,4}} =
erl_scan:string("$\\xfg", {1,1}),
- ?line test("$\\xffg"),
+ test("$\\xffg"),
- ?line {error,{{1,1},erl_scan,{illegal,character}},{1,4}} =
+ {error,{{1,1},erl_scan,{illegal,character}},{1,4}} =
erl_scan:string("$\\xg", {1,1}),
ok.
-otp_10302(doc) ->
- "OTP-10302. Unicode characters scanner/parser.";
-otp_10302(suite) ->
- [];
+%% OTP-10302. Unicode characters scanner/parser.
otp_10302(Config) when is_list(Config) ->
%% From unicode():
{error,{1,erl_scan,{illegal,atom}},1} =
@@ -1012,16 +915,13 @@ otp_10302(Config) when is_list(Config) ->
Qs = "$\\x{aaa}",
{ok,[{char,1,2730}],1} = erl_scan_string(Qs, 1),
{ok,[Q2],{1,9}} = erl_scan:string(Qs,{1,1},[text]),
- [{category,char},{column,1},{length,8},
- {line,1},{symbol,16#aaa},{text,Qs}] =
- erl_scan:token_info(Q2),
-
- Tags = [category, column, length, line, symbol, text],
+ [{category,char},{column,1},{line,1},{symbol,16#aaa},{text,Qs}] =
+ token_info_long(Q2),
U1 = "\"\\x{aaa}\"",
{ok,[T1],{1,10}} = erl_scan:string(U1, {1,1}, [text]),
- [{category,string},{column,1},{length,9},{line,1},
- {symbol,[16#aaa]},{text,U1}] = erl_scan:token_info(T1, Tags),
+ [{category,string},{column,1},{line,1},{symbol,[16#aaa]},{text,U1}] =
+ token_info_long(T1),
U2 = "\"\\x41\\x{fff}\\x42\"",
{ok,[{string,1,[65,4095,66]}],1} = erl_scan_string(U2, 1),
@@ -1171,18 +1071,12 @@ otp_10302(Config) when is_list(Config) ->
erl_parse_abstract("a"++[1024]++"c", [{encoding,latin1}]),
ok.
-otp_10990(doc) ->
- "OTP-10990. Floating point number in input string.";
-otp_10990(suite) ->
- [];
+%% OTP-10990. Floating point number in input string.
otp_10990(Config) when is_list(Config) ->
{'EXIT',_} = (catch {foo, erl_scan:string([$",42.0,$"],1)}),
ok.
-otp_10992(doc) ->
- "OTP-10992. List of floats to abstract format.";
-otp_10992(suite) ->
- [];
+%% OTP-10992. List of floats to abstract format.
otp_10992(Config) when is_list(Config) ->
{cons,0,{float,0,42.0},{nil,0}} =
erl_parse_abstract([42.0], [{encoding,unicode}]),
@@ -1194,10 +1088,7 @@ otp_10992(Config) when is_list(Config) ->
erl_parse_abstract([$A,42.0], [{encoding,utf8}]),
ok.
-otp_11807(doc) ->
- "OTP-11807. Generalize erl_parse:abstract/2.";
-otp_11807(suite) ->
- [];
+%% OTP-11807. Generalize erl_parse:abstract/2.
otp_11807(Config) when is_list(Config) ->
{cons,0,{integer,0,97},{cons,0,{integer,0,98},{nil,0}}} =
erl_parse_abstract("ab", [{encoding,none}]),
@@ -1353,9 +1244,7 @@ test_wsc([], []) ->
ok;
test_wsc([Token|Tokens], [Token2|Tokens2]) ->
[Text, Text2] = [Text ||
- {text, Text} <-
- [erl_scan:token_info(T, text) ||
- T <- [Token, Token2]]],
+ Text <- [erl_scan:text(T) || T <- [Token, Token2]]],
Sz = erts_debug:size(Text),
Sz2 = erts_debug:size({Text, Text2}),
IsCompacted = Sz2 < 2*Sz+erts_debug:size({a,a}),
@@ -1394,7 +1283,7 @@ all_same(L, Char) ->
newlines_first([]) ->
ok;
newlines_first([Token|Tokens]) ->
- {text,Text} = erl_scan:token_info(Token, text),
+ Text = erl_scan:text(Token),
Nnls = length([C || C <- Text, C =:= $\n]),
OK = case Text of
[$\n|_] ->
@@ -1414,7 +1303,7 @@ select_tokens(Tokens, Tags) ->
lists:filter(fun(T) -> lists:member(element(1, T), Tags) end, Tokens).
simplify([Token|Tokens]) ->
- {line,Line} = erl_scan:token_info(Token, line),
+ Line = erl_scan:line(Token),
[setelement(2, Token, erl_anno:new(Line)) | simplify(Tokens)];
simplify([]) ->
[].
@@ -1423,17 +1312,31 @@ get_text(Tokens) ->
lists:flatten(
[T ||
Token <- Tokens,
- ({text,T} = erl_scan:token_info(Token, text)) =/= []]).
+ (T = erl_scan:text(Token)) =/= []]).
test_decorated_tokens(String, Tokens) ->
ToksAttrs = token_attrs(Tokens),
test_strings(ToksAttrs, String, 1, 1).
token_attrs(Tokens) ->
- [{L,C,Len,T} ||
+ [{L,C,length(T),T} ||
Token <- Tokens,
- ([{line,L},{column,C},{length,Len},{text,T}] =
- erl_scan:token_info(Token, [line,column,length,text])) =/= []].
+ ([C,L,T] = token_info(Token)) =/= []].
+
+token_info(T) ->
+ Column = erl_scan:column(T),
+ Line = erl_scan:line(T),
+ Text = erl_scan:text(T),
+ [Column, Line, Text].
+
+token_info_long(T) ->
+ Column = erl_scan:column(T),
+ Line = erl_scan:line(T),
+ Text = erl_scan:text(T),
+ Category = erl_scan:category(T),
+ Symbol = erl_scan:symbol(T),
+ [{category,Category},{column,Column},{line,Line},
+ {symbol,Symbol},{text,Text}].
test_strings([], _S, Line, Column) ->
{Line,Column};
@@ -1514,8 +1417,7 @@ consistent_attributes([Ts | TsL]) ->
L = [T || T <- Ts, is_integer(element(2, T))],
case L of
[] ->
- TagsL = [[Tag || {Tag,_} <-
- erl_scan:attributes_info(element(2, T))] ||
+ TagsL = [[Tag || {Tag,_} <- defined(token_info_long(T))] ||
T <- Ts],
case lists:usort(TagsL) of
[_] ->
@@ -1531,6 +1433,9 @@ consistent_attributes([Ts | TsL]) ->
Ts
end.
+defined(L) ->
+ [{T,V} || {T,V} <- L, V =/= undefined].
+
family_list(L) ->
sofs:to_external(family(L)).
diff --git a/lib/stdlib/test/error_logger_h_SUITE.erl b/lib/stdlib/test/error_logger_h_SUITE.erl
index c82b1b62ef..30811f3fb4 100644
--- a/lib/stdlib/test/error_logger_h_SUITE.erl
+++ b/lib/stdlib/test/error_logger_h_SUITE.erl
@@ -25,7 +25,7 @@
%% Event handler exports.
-export([init/1,handle_event/2,terminate/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -48,7 +48,7 @@ end_per_group(_GroupName, Config) ->
Config.
logfile(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
LogDir = filename:join(PrivDir, ?MODULE),
Log = filename:join(LogDir, "logfile.log"),
ok = filelib:ensure_dir(Log),
@@ -77,7 +77,7 @@ logfile(Config) ->
ok.
logfile_truncated(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
LogDir = filename:join(PrivDir, ?MODULE),
Log = filename:join(LogDir, "logfile_truncated.log"),
ok = filelib:ensure_dir(Log),
@@ -102,7 +102,7 @@ do_one_logfile(Log, Ev, Depth) ->
analyse_events(Log, Ev, [], Depth).
tty(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
LogDir = filename:join(PrivDir, ?MODULE),
Log = filename:join(LogDir, "tty.log"),
ok = filelib:ensure_dir(Log),
@@ -125,7 +125,7 @@ tty(Config) ->
ok.
tty_truncated(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
LogDir = filename:join(PrivDir, ?MODULE),
Log = filename:join(LogDir, "tty_truncated.log"),
ok = filelib:ensure_dir(Log),
@@ -335,7 +335,7 @@ start_node(Name, Args) ->
{ok,Node} ->
{ok,Node};
Error ->
- test_server:fail(Error)
+ ct:fail(Error)
end.
cleanup(File) ->
diff --git a/lib/stdlib/test/escript_SUITE.erl b/lib/stdlib/test/escript_SUITE.erl
index 87ff6a68ff..30aaac70c2 100644
--- a/lib/stdlib/test/escript_SUITE.erl
+++ b/lib/stdlib/test/escript_SUITE.erl
@@ -19,7 +19,7 @@
-module(escript_SUITE).
-export([
- all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
init_per_testcase/2,
end_per_testcase/2,
@@ -40,10 +40,12 @@
unicode/1
]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,5}}].
all() ->
[basic, errors, strange_name, emulator_flags,
@@ -68,103 +70,100 @@ end_per_group(_GroupName, Config) ->
Config.
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?t:minutes(5)),
- [{watchdog,Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
basic(Config) when is_list(Config) ->
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
Dir = filename:absname(Data), %Get rid of trailing slash.
- ?line run(Dir, "factorial 5",
- <<"factorial 5 = 120\nExitCode:0">>),
- ?line run(Dir, "factorial_compile 10",
- <<"factorial 10 = 3628800\nExitCode:0">>),
- ?line run(Dir, "factorial_compile_main 7",
- <<"factorial 7 = 5040\nExitCode:0">>),
- ?line run(Dir, "factorial_warning 20",
- [data_dir,<<"factorial_warning:12: Warning: function bar/0 is unused\n"
- "factorial 20 = 2432902008176640000\nExitCode:0">>]),
- ?line run_with_opts(Dir, "-s", "factorial_warning",
- [data_dir,<<"factorial_warning:12: Warning: function bar/0 is unused\nExitCode:0">>]),
- ?line run_with_opts(Dir, "-s -i", "factorial_warning",
- [data_dir,<<"factorial_warning:12: Warning: function bar/0 is unused\nExitCode:0">>]),
- ?line run_with_opts(Dir, "-c -s", "factorial_warning",
- [data_dir,<<"factorial_warning:12: Warning: function bar/0 is unused\nExitCode:0">>]),
- ?line run(Dir, "filesize "++filename:join(?config(data_dir, Config),"filesize"),
- [data_dir,<<"filesize:11: Warning: function id/1 is unused\n324\nExitCode:0">>]),
- ?line run(Dir, "test_script_name",
- [data_dir,<<"test_script_name\nExitCode:0">>]),
- ?line run(Dir, "tail_rec 1000",
- [<<"ok\nExitCode:0">>]),
+ run(Dir, "factorial 5",
+ <<"factorial 5 = 120\nExitCode:0">>),
+ run(Dir, "factorial_compile 10",
+ <<"factorial 10 = 3628800\nExitCode:0">>),
+ run(Dir, "factorial_compile_main 7",
+ <<"factorial 7 = 5040\nExitCode:0">>),
+ run(Dir, "factorial_warning 20",
+ [data_dir,<<"factorial_warning:12: Warning: function bar/0 is unused\n"
+ "factorial 20 = 2432902008176640000\nExitCode:0">>]),
+ run_with_opts(Dir, "-s", "factorial_warning",
+ [data_dir,<<"factorial_warning:12: Warning: function bar/0 is unused\nExitCode:0">>]),
+ run_with_opts(Dir, "-s -i", "factorial_warning",
+ [data_dir,<<"factorial_warning:12: Warning: function bar/0 is unused\nExitCode:0">>]),
+ run_with_opts(Dir, "-c -s", "factorial_warning",
+ [data_dir,<<"factorial_warning:12: Warning: function bar/0 is unused\nExitCode:0">>]),
+ run(Dir, "filesize "++filename:join(proplists:get_value(data_dir, Config),"filesize"),
+ [data_dir,<<"filesize:11: Warning: function id/1 is unused\n324\nExitCode:0">>]),
+ run(Dir, "test_script_name",
+ [data_dir,<<"test_script_name\nExitCode:0">>]),
+ run(Dir, "tail_rec 1000",
+ [<<"ok\nExitCode:0">>]),
%% We expect the trap_exit flag for the process to be false,
%% since that is the default state for newly spawned processes.
- ?line run(Dir, "trap_exit",
- <<"false\nExitCode:0">>),
+ run(Dir, "trap_exit",
+ <<"false\nExitCode:0">>),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
errors(Config) when is_list(Config) ->
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
Dir = filename:absname(Data), %Get rid of trailing slash.
- ?line run(Dir, "compile_error",
- [data_dir,<<"compile_error:5: syntax error before: '*'\n">>,
- data_dir,<<"compile_error:8: syntax error before: blarf\n">>,
- <<"escript: There were compilation errors.\nExitCode:127">>]),
- ?line run(Dir, "lint_error",
- [data_dir,<<"lint_error:6: function main/1 already defined\n">>,
- data_dir,"lint_error:8: variable 'ExitCode' is unbound\n",
- <<"escript: There were compilation errors.\nExitCode:127">>]),
- ?line run_with_opts(Dir, "-s", "lint_error",
- [data_dir,<<"lint_error:6: function main/1 already defined\n">>,
- data_dir,"lint_error:8: variable 'ExitCode' is unbound\n",
- <<"escript: There were compilation errors.\nExitCode:127">>]),
+ run(Dir, "compile_error",
+ [data_dir,<<"compile_error:5: syntax error before: '*'\n">>,
+ data_dir,<<"compile_error:8: syntax error before: blarf\n">>,
+ <<"escript: There were compilation errors.\nExitCode:127">>]),
+ run(Dir, "lint_error",
+ [data_dir,<<"lint_error:6: function main/1 already defined\n">>,
+ data_dir,"lint_error:8: variable 'ExitCode' is unbound\n",
+ <<"escript: There were compilation errors.\nExitCode:127">>]),
+ run_with_opts(Dir, "-s", "lint_error",
+ [data_dir,<<"lint_error:6: function main/1 already defined\n">>,
+ data_dir,"lint_error:8: variable 'ExitCode' is unbound\n",
+ <<"escript: There were compilation errors.\nExitCode:127">>]),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
strange_name(Config) when is_list(Config) ->
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
Dir = filename:absname(Data), %Get rid of trailing slash.
- ?line run(Dir, "strange.name -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "ExitCode:0">>]),
+ run(Dir, "strange.name -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "ExitCode:0">>]),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
emulator_flags(Config) when is_list(Config) ->
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
Dir = filename:absname(Data), %Get rid of trailing slash.
- ?line run(Dir, "emulator_flags -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "nostick:[{nostick,[]}]\n"
- "mnesia:[{mnesia,[\"dir\",\"a/directory\"]},{mnesia,[\"debug\",\"verbose\"]}]\n"
- "ERL_FLAGS=false\n"
- "unknown:[]\n"
- "ExitCode:0">>]),
+ run(Dir, "emulator_flags -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "nostick:[{nostick,[]}]\n"
+ "mnesia:[{mnesia,[\"dir\",\"a/directory\"]},{mnesia,[\"debug\",\"verbose\"]}]\n"
+ "ERL_FLAGS=false\n"
+ "unknown:[]\n"
+ "ExitCode:0">>]),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
emulator_flags_no_shebang(Config) when is_list(Config) ->
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
Dir = filename:absname(Data), %Get rid of trailing slash.
%% Need run_with_opts, to always use "escript" explicitly
- ?line run_with_opts(Dir, "", "emulator_flags_no_shebang -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "nostick:[{nostick,[]}]\n"
- "mnesia:[{mnesia,[\"dir\",\"a/directory\"]},{mnesia,[\"debug\",\"verbose\"]}]\n"
- "ERL_FLAGS=false\n"
- "unknown:[]\n"
- "ExitCode:0">>]),
+ run_with_opts(Dir, "", "emulator_flags_no_shebang -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "nostick:[{nostick,[]}]\n"
+ "mnesia:[{mnesia,[\"dir\",\"a/directory\"]},{mnesia,[\"debug\",\"verbose\"]}]\n"
+ "ERL_FLAGS=false\n"
+ "unknown:[]\n"
+ "ExitCode:0">>]),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -173,14 +172,14 @@ emulator_flags_no_shebang(Config) when is_list(Config) ->
module_script(Config) when is_list(Config) ->
%% Read orig file
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
OrigFile = filename:join([Data,"emulator_flags"]),
{ok, OrigBin} = file:read_file(OrigFile),
- ?line [Shebang, Mode, Flags | Source] = string:tokens(binary_to_list(OrigBin), "\n"),
- ?line {ok, OrigFI} = file:read_file_info(OrigFile),
+ [Shebang, Mode, Flags | Source] = string:tokens(binary_to_list(OrigBin), "\n"),
+ {ok, OrigFI} = file:read_file_info(OrigFile),
%% Write source file
- Priv = ?config(priv_dir, Config),
+ Priv = proplists:get_value(priv_dir, Config),
Dir = filename:absname(Priv), % Get rid of trailing slash.
Base = "module_script",
ErlFile = filename:join([Priv, Base ++ ".erl"]),
@@ -188,85 +187,85 @@ module_script(Config) when is_list(Config) ->
"-export([main/1]).\n\n",
string:join(Source, "\n"),
"\n"],
- ?line ok = file:write_file(ErlFile, ErlCode),
+ ok = file:write_file(ErlFile, ErlCode),
- %%%%%%%
+%%%%%%%
%% Create and run scripts without emulator flags
%% With shebang
NoArgsBase = Base ++ "_no_args_with_shebang",
NoArgsFile = filename:join([Priv, NoArgsBase]),
- ?line ok = file:write_file(NoArgsFile,
- [Shebang, "\n",
- ErlCode]),
- ?line ok = file:write_file_info(NoArgsFile, OrigFI),
-
- ?line run(Dir, NoArgsBase ++ " -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "nostick:[]\n"
- "mnesia:[]\n"
- "ERL_FLAGS=false\n"
- "unknown:[]\n"
- "ExitCode:0">>]),
-
- ?line run_with_opts(Dir, "", NoArgsBase ++ " -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "nostick:[]\n"
- "mnesia:[]\n"
- "ERL_FLAGS=false\n"
- "unknown:[]\n"
- "ExitCode:0">>]),
+ ok = file:write_file(NoArgsFile,
+ [Shebang, "\n",
+ ErlCode]),
+ ok = file:write_file_info(NoArgsFile, OrigFI),
+
+ run(Dir, NoArgsBase ++ " -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "nostick:[]\n"
+ "mnesia:[]\n"
+ "ERL_FLAGS=false\n"
+ "unknown:[]\n"
+ "ExitCode:0">>]),
+
+ run_with_opts(Dir, "", NoArgsBase ++ " -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "nostick:[]\n"
+ "mnesia:[]\n"
+ "ERL_FLAGS=false\n"
+ "unknown:[]\n"
+ "ExitCode:0">>]),
%% Without shebang
NoArgsBase2 = Base ++ "_no_args_without_shebang",
NoArgsFile2 = filename:join([Priv, NoArgsBase2]),
- ?line ok = file:write_file(NoArgsFile2,
- ["Something else than shebang!!!", "\n",
- ErlCode]),
- ?line ok = file:write_file_info(NoArgsFile2, OrigFI),
-
- ?line run_with_opts(Dir, "", NoArgsBase2 ++ " -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "nostick:[]\n"
- "mnesia:[]\n"
- "ERL_FLAGS=false\n"
- "unknown:[]\n"
- "ExitCode:0">>]),
+ ok = file:write_file(NoArgsFile2,
+ ["Something else than shebang!!!", "\n",
+ ErlCode]),
+ ok = file:write_file_info(NoArgsFile2, OrigFI),
+
+ run_with_opts(Dir, "", NoArgsBase2 ++ " -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "nostick:[]\n"
+ "mnesia:[]\n"
+ "ERL_FLAGS=false\n"
+ "unknown:[]\n"
+ "ExitCode:0">>]),
%% Plain module without header
NoArgsBase3 = Base ++ "_no_args_without_header",
NoArgsFile3 = filename:join([Priv, NoArgsBase3]),
- ?line ok = file:write_file(NoArgsFile3, [ErlCode]),
- ?line ok = file:write_file_info(NoArgsFile3, OrigFI),
-
- ?line run_with_opts(Dir, "", NoArgsBase3 ++ " -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "nostick:[]\n"
- "mnesia:[]\n"
- "ERL_FLAGS=false\n"
- "unknown:[]\n"
- "ExitCode:0">>]),
-
- %%%%%%%
+ ok = file:write_file(NoArgsFile3, [ErlCode]),
+ ok = file:write_file_info(NoArgsFile3, OrigFI),
+
+ run_with_opts(Dir, "", NoArgsBase3 ++ " -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "nostick:[]\n"
+ "mnesia:[]\n"
+ "ERL_FLAGS=false\n"
+ "unknown:[]\n"
+ "ExitCode:0">>]),
+
+%%%%%%%
%% Create and run scripts with emulator flags
%% With shebang
ArgsBase = Base ++ "_args_with_shebang",
ArgsFile = filename:join([Priv, ArgsBase]),
- ?line ok = file:write_file(ArgsFile,
- [Shebang, "\n",
- Mode, "\n",
- Flags, "\n",
- ErlCode]),
- ?line ok = file:write_file_info(ArgsFile, OrigFI),
-
- ?line run(Dir, ArgsBase ++ " -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "nostick:[{nostick,[]}]\n"
- "mnesia:[{mnesia,[\"dir\",\"a/directory\"]},{mnesia,[\"debug\",\"verbose\"]}]\n"
- "ERL_FLAGS=false\n"
- "unknown:[]\n"
- "ExitCode:0">>]),
+ ok = file:write_file(ArgsFile,
+ [Shebang, "\n",
+ Mode, "\n",
+ Flags, "\n",
+ ErlCode]),
+ ok = file:write_file_info(ArgsFile, OrigFI),
+
+ run(Dir, ArgsBase ++ " -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "nostick:[{nostick,[]}]\n"
+ "mnesia:[{mnesia,[\"dir\",\"a/directory\"]},{mnesia,[\"debug\",\"verbose\"]}]\n"
+ "ERL_FLAGS=false\n"
+ "unknown:[]\n"
+ "ExitCode:0">>]),
ok.
@@ -275,103 +274,103 @@ module_script(Config) when is_list(Config) ->
%% Generate a new escript containing the beam code and the escript header
beam_script(Config) when is_list(Config) ->
%% Read orig file
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
OrigFile = filename:join([Data,"emulator_flags"]),
{ok, OrigBin} = file:read_file(OrigFile),
- ?line [Shebang, Mode, Flags | Source] = string:tokens(binary_to_list(OrigBin), "\n"),
- ?line {ok, OrigFI} = file:read_file_info(OrigFile),
+ [Shebang, Mode, Flags | Source] = string:tokens(binary_to_list(OrigBin), "\n"),
+ {ok, OrigFI} = file:read_file_info(OrigFile),
%% Write source file
- Priv = ?config(priv_dir, Config),
+ Priv = proplists:get_value(priv_dir, Config),
Dir = filename:absname(Priv), % Get rid of trailing slash.
Base = "beam_script",
ErlFile = filename:join([Priv, Base ++ ".erl"]),
- ?line ok = file:write_file(ErlFile,
- ["\n-module(", Base, ").\n",
- "-export([main/1]).\n\n",
- string:join(Source, "\n"),
- "\n"]),
+ ok = file:write_file(ErlFile,
+ ["\n-module(", Base, ").\n",
+ "-export([main/1]).\n\n",
+ string:join(Source, "\n"),
+ "\n"]),
%% Compile the code
- ?line {ok, _Mod, BeamCode} = compile:file(ErlFile, [binary]),
+ {ok, _Mod, BeamCode} = compile:file(ErlFile, [binary]),
- %%%%%%%
+%%%%%%%
%% Create and run scripts without emulator flags
%% With shebang
NoArgsBase = Base ++ "_no_args_with_shebang",
NoArgsFile = filename:join([Priv, NoArgsBase]),
- ?line ok = file:write_file(NoArgsFile,
- [Shebang, "\n",
- BeamCode]),
- ?line ok = file:write_file_info(NoArgsFile, OrigFI),
-
- ?line run(Dir, NoArgsBase ++ " -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "nostick:[]\n"
- "mnesia:[]\n"
- "ERL_FLAGS=false\n"
- "unknown:[]\n"
- "ExitCode:0">>]),
-
- ?line run_with_opts(Dir, "", NoArgsBase ++ " -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "nostick:[]\n"
- "mnesia:[]\n"
- "ERL_FLAGS=false\n"
- "unknown:[]\n"
- "ExitCode:0">>]),
+ ok = file:write_file(NoArgsFile,
+ [Shebang, "\n",
+ BeamCode]),
+ ok = file:write_file_info(NoArgsFile, OrigFI),
+
+ run(Dir, NoArgsBase ++ " -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "nostick:[]\n"
+ "mnesia:[]\n"
+ "ERL_FLAGS=false\n"
+ "unknown:[]\n"
+ "ExitCode:0">>]),
+
+ run_with_opts(Dir, "", NoArgsBase ++ " -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "nostick:[]\n"
+ "mnesia:[]\n"
+ "ERL_FLAGS=false\n"
+ "unknown:[]\n"
+ "ExitCode:0">>]),
%% Without shebang
NoArgsBase2 = Base ++ "_no_args_without_shebang",
NoArgsFile2 = filename:join([Priv, NoArgsBase2]),
- ?line ok = file:write_file(NoArgsFile2,
- ["Something else than shebang!!!", "\n",
- BeamCode]),
- ?line ok = file:write_file_info(NoArgsFile2, OrigFI),
-
- ?line run_with_opts(Dir, "", NoArgsBase2 ++ " -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "nostick:[]\n"
- "mnesia:[]\n"
- "ERL_FLAGS=false\n"
- "unknown:[]\n"
- "ExitCode:0">>]),
+ ok = file:write_file(NoArgsFile2,
+ ["Something else than shebang!!!", "\n",
+ BeamCode]),
+ ok = file:write_file_info(NoArgsFile2, OrigFI),
+
+ run_with_opts(Dir, "", NoArgsBase2 ++ " -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "nostick:[]\n"
+ "mnesia:[]\n"
+ "ERL_FLAGS=false\n"
+ "unknown:[]\n"
+ "ExitCode:0">>]),
%% Plain beam file without header
NoArgsBase3 = Base ++ "_no_args_without_header",
NoArgsFile3 = filename:join([Priv, NoArgsBase3]),
- ?line ok = file:write_file(NoArgsFile3, [BeamCode]),
- ?line ok = file:write_file_info(NoArgsFile3, OrigFI),
-
- ?line run_with_opts(Dir, "", NoArgsBase3 ++ " -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "nostick:[]\n"
- "mnesia:[]\n"
- "ERL_FLAGS=false\n"
- "unknown:[]\n"
- "ExitCode:0">>]),
-
- %%%%%%%
+ ok = file:write_file(NoArgsFile3, [BeamCode]),
+ ok = file:write_file_info(NoArgsFile3, OrigFI),
+
+ run_with_opts(Dir, "", NoArgsBase3 ++ " -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "nostick:[]\n"
+ "mnesia:[]\n"
+ "ERL_FLAGS=false\n"
+ "unknown:[]\n"
+ "ExitCode:0">>]),
+
+%%%%%%%
%% Create and run scripts with emulator flags
%% With shebang
ArgsBase = Base ++ "_args",
ArgsFile = filename:join([Priv, ArgsBase]),
- ?line ok = file:write_file(ArgsFile,
- [Shebang, "\n",
- Mode, "\n",
- Flags, "\n",
- BeamCode]),
- ?line ok = file:write_file_info(ArgsFile, OrigFI),
-
- ?line run(Dir, ArgsBase ++ " -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "nostick:[{nostick,[]}]\n"
- "mnesia:[{mnesia,[\"dir\",\"a/directory\"]},{mnesia,[\"debug\",\"verbose\"]}]\n"
- "ERL_FLAGS=false\n"
- "unknown:[]\n"
- "ExitCode:0">>]),
+ ok = file:write_file(ArgsFile,
+ [Shebang, "\n",
+ Mode, "\n",
+ Flags, "\n",
+ BeamCode]),
+ ok = file:write_file_info(ArgsFile, OrigFI),
+
+ run(Dir, ArgsBase ++ " -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "nostick:[{nostick,[]}]\n"
+ "mnesia:[{mnesia,[\"dir\",\"a/directory\"]},{mnesia,[\"debug\",\"verbose\"]}]\n"
+ "ERL_FLAGS=false\n"
+ "unknown:[]\n"
+ "ExitCode:0">>]),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -381,107 +380,107 @@ beam_script(Config) when is_list(Config) ->
archive_script(Config) when is_list(Config) ->
%% Copy the orig files to priv_dir
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Archive = filename:join([PrivDir, "archive_script.zip"]),
- ?line {ok, _} = zip:create(Archive, ["archive_script"],
- [{compress, []}, {cwd, DataDir}]),
- ?line {ok, _} = zip:extract(Archive, [{cwd, PrivDir}]),
+ {ok, _} = zip:create(Archive, ["archive_script"],
+ [{compress, []}, {cwd, DataDir}]),
+ {ok, _} = zip:extract(Archive, [{cwd, PrivDir}]),
TopDir = filename:join([PrivDir, "archive_script"]),
%% Compile the code
- ?line ok = compile_app(TopDir, "archive_script_dict"),
- ?line ok = compile_app(TopDir, "archive_script_dummy"),
- ?line {ok, MainFiles} = file:list_dir(TopDir),
- ?line ok = compile_files(MainFiles, TopDir, TopDir),
+ ok = compile_app(TopDir, "archive_script_dict"),
+ ok = compile_app(TopDir, "archive_script_dummy"),
+ {ok, MainFiles} = file:list_dir(TopDir),
+ ok = compile_files(MainFiles, TopDir, TopDir),
%% Create the archive
{ok, TopFiles} = file:list_dir(TopDir),
- ?line {ok, {_, ArchiveBin}} = zip:create(Archive, TopFiles,
- [memory, {compress, []}, {cwd, TopDir}]),
+ {ok, {_, ArchiveBin}} = zip:create(Archive, TopFiles,
+ [memory, {compress, []}, {cwd, TopDir}]),
%% Read the source script
OrigFile = filename:join([DataDir, "emulator_flags"]),
{ok, OrigBin} = file:read_file(OrigFile),
- ?line [Shebang, Mode, _Flags | _Source] =
+ [Shebang, Mode, _Flags | _Source] =
string:tokens(binary_to_list(OrigBin), "\n"),
Flags = "%%! -archive_script_dict foo bar"
" -archive_script_dict foo"
" -archive_script_dummy bar",
- ?line {ok, OrigFI} = file:read_file_info(OrigFile),
+ {ok, OrigFI} = file:read_file_info(OrigFile),
- %%%%%%%
+%%%%%%%
%% Create and run scripts without emulator flags
MainBase = "archive_script_main",
MainScript = filename:join([PrivDir, MainBase]),
%% With shebang
- ?line ok = file:write_file(MainScript,
- [Shebang, "\n",
- Flags, "\n",
- ArchiveBin]),
- ?line ok = file:write_file_info(MainScript, OrigFI),
-
- ?line run(PrivDir, MainBase ++ " -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "dict:[{archive_script_dict,[\"foo\",\"bar\"]},{archive_script_dict,[\"foo\"]}]\n"
- "dummy:[{archive_script_dummy,[\"bar\"]}]\n"
- "priv:{ok,<<\"Some private data...\\n\">>}\n"
- "ExitCode:0">>]),
-
- ?line run_with_opts(PrivDir, "", MainBase ++ " -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "dict:[{archive_script_dict,[\"foo\",\"bar\"]},{archive_script_dict,[\"foo\"]}]\n"
- "dummy:[{archive_script_dummy,[\"bar\"]}]\n"
- "priv:{ok,<<\"Some private data...\\n\">>}\n"
- "ExitCode:0">>]),
-
- ?line ok = file:rename(MainScript, MainScript ++ "_with_shebang"),
+ ok = file:write_file(MainScript,
+ [Shebang, "\n",
+ Flags, "\n",
+ ArchiveBin]),
+ ok = file:write_file_info(MainScript, OrigFI),
+
+ run(PrivDir, MainBase ++ " -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "dict:[{archive_script_dict,[\"foo\",\"bar\"]},{archive_script_dict,[\"foo\"]}]\n"
+ "dummy:[{archive_script_dummy,[\"bar\"]}]\n"
+ "priv:{ok,<<\"Some private data...\\n\">>}\n"
+ "ExitCode:0">>]),
+
+ run_with_opts(PrivDir, "", MainBase ++ " -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "dict:[{archive_script_dict,[\"foo\",\"bar\"]},{archive_script_dict,[\"foo\"]}]\n"
+ "dummy:[{archive_script_dummy,[\"bar\"]}]\n"
+ "priv:{ok,<<\"Some private data...\\n\">>}\n"
+ "ExitCode:0">>]),
+
+ ok = file:rename(MainScript, MainScript ++ "_with_shebang"),
%% Without shebang (no flags)
- ?line ok = file:write_file(MainScript,
- ["Something else than shebang!!!", "\n",
- ArchiveBin]),
- ?line ok = file:write_file_info(MainScript, OrigFI),
-
- ?line run_with_opts(PrivDir, "", MainBase ++ " -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "dict:[]\n"
- "dummy:[]\n"
- "priv:{ok,<<\"Some private data...\\n\">>}\n"
- "ExitCode:0">>]),
- ?line ok = file:rename(MainScript, MainScript ++ "_without_shebang"),
+ ok = file:write_file(MainScript,
+ ["Something else than shebang!!!", "\n",
+ ArchiveBin]),
+ ok = file:write_file_info(MainScript, OrigFI),
+
+ run_with_opts(PrivDir, "", MainBase ++ " -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "dict:[]\n"
+ "dummy:[]\n"
+ "priv:{ok,<<\"Some private data...\\n\">>}\n"
+ "ExitCode:0">>]),
+ ok = file:rename(MainScript, MainScript ++ "_without_shebang"),
%% Plain archive without header (no flags)
- ?line ok = file:write_file(MainScript, [ArchiveBin]),
- ?line ok = file:write_file_info(MainScript, OrigFI),
+ ok = file:write_file(MainScript, [ArchiveBin]),
+ ok = file:write_file_info(MainScript, OrigFI),
- ?line run_with_opts(PrivDir, "", MainBase ++ " -arg1 arg2 arg3",
- [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "dict:[]\n"
- "dummy:[]\n"
- "priv:{ok,<<\"Some private data...\\n\">>}\n"
- "ExitCode:0">>]),
- ?line ok = file:rename(MainScript, MainScript ++ "_without_header"),
+ run_with_opts(PrivDir, "", MainBase ++ " -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "dict:[]\n"
+ "dummy:[]\n"
+ "priv:{ok,<<\"Some private data...\\n\">>}\n"
+ "ExitCode:0">>]),
+ ok = file:rename(MainScript, MainScript ++ "_without_header"),
- %%%%%%%
+%%%%%%%
%% Create and run scripts with emulator flags
AltBase = "archive_script_alternate_main",
AltScript = filename:join([PrivDir, AltBase]),
- ?line ok = file:write_file(AltScript,
- [Shebang, "\n",
- Mode, "\n",
- Flags, " -escript main archive_script_main2\n",
- ArchiveBin]),
- ?line ok = file:write_file_info(AltScript, OrigFI),
-
- ?line run(PrivDir, AltBase ++ " -arg1 arg2 arg3",
- [<<"main2:[\"-arg1\",\"arg2\",\"arg3\"]\n"
- "dict:[{archive_script_dict,[\"foo\",\"bar\"]},{archive_script_dict,[\"foo\"]}]\n"
- "dummy:[{archive_script_dummy,[\"bar\"]}]\n"
- "priv:{ok,<<\"Some private data...\\n\">>}\n"
- "ExitCode:0">>]),
+ ok = file:write_file(AltScript,
+ [Shebang, "\n",
+ Mode, "\n",
+ Flags, " -escript main archive_script_main2\n",
+ ArchiveBin]),
+ ok = file:write_file_info(AltScript, OrigFI),
+
+ run(PrivDir, AltBase ++ " -arg1 arg2 arg3",
+ [<<"main2:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "dict:[{archive_script_dict,[\"foo\",\"bar\"]},{archive_script_dict,[\"foo\"]}]\n"
+ "dummy:[{archive_script_dummy,[\"bar\"]}]\n"
+ "priv:{ok,<<\"Some private data...\\n\">>}\n"
+ "ExitCode:0">>]),
ok.
@@ -508,21 +507,21 @@ archive_script(Config) when is_list(Config) ->
%%
archive_script_file_access(Config) when is_list(Config) ->
%% Copy the orig files to priv_dir
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
MainMod = "archive_script_file_access",
MainSrc = MainMod ++ ".erl",
MainBeam = MainMod ++ ".beam",
Archive = filename:join([PrivDir, "archive_script_file_access.zip"]),
- ?line {ok, _} = zip:create(Archive, ["archive_script_file_access"],
- [{compress, []}, {cwd, DataDir}]),
- ?line {ok, _} = zip:extract(Archive, [{cwd, PrivDir}]),
+ {ok, _} = zip:create(Archive, ["archive_script_file_access"],
+ [{compress, []}, {cwd, DataDir}]),
+ {ok, _} = zip:extract(Archive, [{cwd, PrivDir}]),
TopDir = filename:join([PrivDir, "archive_script_file_access"]),
%% Compile the code
- ?line ok = compile_files([MainSrc], TopDir, TopDir),
+ ok = compile_files([MainSrc], TopDir, TopDir),
%% First, create a file structure which will be included in the archive:
%%
@@ -630,7 +629,7 @@ compile_app(TopDir, AppName) ->
AppDir = filename:join([TopDir, AppName]),
SrcDir = filename:join([AppDir, "src"]),
OutDir = filename:join([AppDir, "ebin"]),
- ?line {ok, Files} = file:list_dir(SrcDir),
+ {ok, Files} = file:list_dir(SrcDir),
compile_files(Files, SrcDir, OutDir).
compile_files([File | Files], SrcDir, OutDir) ->
@@ -652,10 +651,10 @@ compile_files([], _, _) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
epp(Config) when is_list(Config) ->
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
Dir = filename:absname(Data), %Get rid of trailing slash.
- ?line run(Dir, "factorial_epp 5",
- <<"factorial 5 = 120\nExitCode:0">>),
+ run(Dir, "factorial_epp 5",
+ <<"factorial 5 = 120\nExitCode:0">>),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -695,9 +694,9 @@ create_and_extract(Config) when is_list(Config) ->
%% Verify the compile_source option
file:delete(NewFile),
- ?line ok = escript:create(NewFile, [{source, Source}]),
- ?line {ok, [_, _, _, {source, Source}]} = escript:extract(NewFile, []),
- ?line {ok, [_, _, _, {source, BeamCode2}]} =
+ ok = escript:create(NewFile, [{source, Source}]),
+ {ok, [_, _, _, {source, Source}]} = escript:extract(NewFile, []),
+ {ok, [_, _, _, {source, BeamCode2}]} =
escript:extract(NewFile, [compile_source]),
verify_sections(NewFile, FileInfo,
[{shebang, default},
@@ -709,15 +708,15 @@ create_and_extract(Config) when is_list(Config) ->
prepare_creation(Base, Config) ->
%% Read the source
- PrivDir = ?config(priv_dir, Config),
- DataDir = ?config(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
OrigFile = filename:join([DataDir,"emulator_flags"]),
- ?line {ok, FileInfo} = file:read_file_info(OrigFile),
+ {ok, FileInfo} = file:read_file_info(OrigFile),
NewFile = filename:join([PrivDir, Base]),
- ?line {ok, [{shebang, default},
- {comment, _},
- {emu_args, EmuArg},
- {source, Source}]} =
+ {ok, [{shebang, default},
+ {comment, _},
+ {emu_args, EmuArg},
+ {source, Source}]} =
escript:extract(OrigFile, []),
%% Compile the code
@@ -725,14 +724,14 @@ prepare_creation(Base, Config) ->
ErlCode = list_to_binary(["\n-module(", Base, ").\n",
"-export([main/1]).\n\n",
Source, "\n\n"]),
- ?line ok = file:write_file(ErlFile, ErlCode),
+ ok = file:write_file(ErlFile, ErlCode),
%% Compile the code
- ?line {ok, _Mod, BeamCode} =
+ {ok, _Mod, BeamCode} =
compile:file(ErlFile, [binary, debug_info]),
%% Create an archive
- ?line {ok, {_, ArchiveBin}} =
+ {ok, {_, ArchiveBin}} =
zip:create("dummy_archive_name",
[{Base ++ ".erl", ErlCode},
{Base ++ ".beam", BeamCode}],
@@ -749,8 +748,8 @@ verify_sections(File, FileInfo, Sections) ->
%% Create
file:delete(File),
- ?line ok = escript:create(File, Sections),
- ?line ok = file:write_file_info(File, FileInfo),
+ ok = escript:create(File, Sections),
+ ok = file:write_file_info(File, FileInfo),
%% Run
Dir = filename:absname(filename:dirname(File)),
@@ -780,21 +779,21 @@ verify_sections(File, FileInfo, Sections) ->
Expected = <<ExpectedMain/binary, ExpectedOutput/binary>>,
case HasArg(shebang) of
true ->
- ?line run(Dir, InputArgs, [Expected]);
+ run(Dir, InputArgs, [Expected]);
false ->
- ?line run_with_opts(Dir, [], InputArgs, [Expected])
+ run_with_opts(Dir, [], InputArgs, [Expected])
end,
%% Verify
- ?line {ok, Bin} = escript:create(binary, Sections),
- ?line {ok, Read} = file:read_file(File),
- ?line Bin = Read, % Assert
+ {ok, Bin} = escript:create(binary, Sections),
+ {ok, Read} = file:read_file(File),
+ Bin = Read, % Assert
Normalized = normalize_sections(Sections),
- ?line {ok, Extracted} = escript:extract(File, []),
+ {ok, Extracted} = escript:extract(File, []),
io:format("Normalized; ~p\n", [Normalized]),
io:format("Extracted ; ~p\n", [Extracted]),
- ?line Normalized = Extracted, % Assert
+ Normalized = Extracted, % Assert
ok.
normalize_sections(Sections) ->
@@ -806,27 +805,27 @@ normalize_sections(Sections) ->
end
end,
case lists:map(AtomToTuple, [{K, V} || {K, V} <- Sections, V =/= undefined]) of
- [{shebang, Shebang} | Rest] ->
- [{shebang, Shebang} |
- case Rest of
- [{comment, Comment} | Rest2] ->
- [{comment, Comment} |
- case Rest2 of
- [{emu_args, EmuArgs}, Body] ->
- [{emu_args, EmuArgs}, Body];
- [Body] ->
- [{emu_args, undefined}, Body]
- end
- ];
- [{emu_args, EmuArgs}, Body] ->
- [{comment, undefined}, {emu_args, EmuArgs}, Body];
- [Body] ->
- [{comment, undefined}, {emu_args, undefined}, Body]
- end
- ];
- [Body] ->
- [{shebang, undefined}, {comment, undefined}, {emu_args, undefined}, Body]
- end.
+ [{shebang, Shebang} | Rest] ->
+ [{shebang, Shebang} |
+ case Rest of
+ [{comment, Comment} | Rest2] ->
+ [{comment, Comment} |
+ case Rest2 of
+ [{emu_args, EmuArgs}, Body] ->
+ [{emu_args, EmuArgs}, Body];
+ [Body] ->
+ [{emu_args, undefined}, Body]
+ end
+ ];
+ [{emu_args, EmuArgs}, Body] ->
+ [{comment, undefined}, {emu_args, EmuArgs}, Body];
+ [Body] ->
+ [{comment, undefined}, {emu_args, undefined}, Body]
+ end
+ ];
+ [Body] ->
+ [{shebang, undefined}, {comment, undefined}, {emu_args, undefined}, Body]
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -846,36 +845,36 @@ foldl(Config) when is_list(Config) ->
%% Get line numbers and the file attribute right
SourceFile = NewFile ++ ".erl",
<<_:1/binary, ErlCode2/binary>> = ErlCode,
- ?line ok = file:write_file(SourceFile, ErlCode2),
- ?line {ok, _Mod, BeamCode} =
+ ok = file:write_file(SourceFile, ErlCode2),
+ {ok, _Mod, BeamCode} =
compile:file(SourceFile, [binary, debug_info]),
%% Verify source script
- ?line ok = escript:create(SourceFile, [{source, ErlCode}]),
- ?line {ok, [{".", _, BeamCode2}]}
+ ok = escript:create(SourceFile, [{source, ErlCode}]),
+ {ok, [{".", _, BeamCode2}]}
= escript_foldl(Collect, [], SourceFile),
- ?line {ok, Abstr} = beam_lib:chunks(BeamCode, [abstract_code]),
- ?line {ok, Abstr2} = beam_lib:chunks(BeamCode2, [abstract_code]),
+ {ok, Abstr} = beam_lib:chunks(BeamCode, [abstract_code]),
+ {ok, Abstr2} = beam_lib:chunks(BeamCode2, [abstract_code]),
%% io:format("abstr1=~p\n", [Abstr]),
%% io:format("abstr2=~p\n", [Abstr2]),
- ?line Abstr = Abstr2, % Assert
+ Abstr = Abstr2, % Assert
%% Verify beam script
- ?line ok = escript:create(NewFile, [{beam, BeamCode}]),
- ?line {ok, [{".", _, BeamCode}]}
+ ok = escript:create(NewFile, [{beam, BeamCode}]),
+ {ok, [{".", _, BeamCode}]}
= escript_foldl(Collect, [], NewFile),
%% Verify archive scripts
- ?line ok = escript:create(NewFile, [{archive, ArchiveBin}]),
- ?line {ok, [{BeamBase, #file_info{}, _},
- {ErlBase, #file_info{}, _}]}
+ ok = escript:create(NewFile, [{archive, ArchiveBin}]),
+ {ok, [{BeamBase, #file_info{}, _},
+ {ErlBase, #file_info{}, _}]}
= escript_foldl(Collect, [], NewFile),
ArchiveFiles = [{ErlBase, ErlCode}, {BeamBase, BeamCode}],
- ?line ok = escript:create(NewFile, [{archive, ArchiveFiles, []}]),
- ?line {ok, [{BeamBase, _, _},
- {ErlBase, _, _}]}
+ ok = escript:create(NewFile, [{archive, ArchiveFiles, []}]),
+ {ok, [{BeamBase, _, _},
+ {ErlBase, _, _}]}
= escript_foldl(Collect, [], NewFile),
ok.
@@ -909,7 +908,7 @@ emulate_escript_foldl(Fun, Acc, File) ->
end.
unicode(Config) when is_list(Config) ->
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
Dir = filename:absname(Data), %Get rid of trailing slash.
run(Dir, "unicode1",
[<<"escript: exception error: an error occurred when evaluating"
@@ -928,12 +927,12 @@ unicode(Config) when is_list(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
overflow(Config) when is_list(Config) ->
- Data = ?config(data_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
Dir = filename:absname(Data), %Get rid of trailing slash.
- ?line run(Dir, "arg_overflow",
- [<<"ExitCode:0">>]),
- ?line run(Dir, "linebuf_overflow",
- [<<"ExitCode:0">>]),
+ run(Dir, "arg_overflow",
+ [<<"ExitCode:0">>]),
+ run(Dir, "linebuf_overflow",
+ [<<"ExitCode:0">>]),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -968,7 +967,7 @@ do_run(Dir, Cmd, Expected0) ->
Actual ->
io:format("Expected: ~p\n", [Expected]),
io:format("Actual: ~p\n", [Actual]),
- ?t:fail()
+ ct:fail(failed)
end
end.
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 30a158d9e1..678c225d25 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -34,7 +34,7 @@
-export([ match1/1, match2/1, match_object/1, match_object2/1]).
-export([ dups/1, misc1/1, safe_fixtable/1, info/1, tab2list/1]).
-export([ tab2file/1, tab2file2/1, tabfile_ext1/1,
- tabfile_ext2/1, tabfile_ext3/1, tabfile_ext4/1, badfile/1]).
+ tabfile_ext2/1, tabfile_ext3/1, tabfile_ext4/1, badfile/1]).
-export([ heavy_lookup/1, heavy_lookup_element/1, heavy_concurrent/1]).
-export([ lookup_element_mult/1]).
-export([]).
@@ -43,8 +43,6 @@
t_delete_all_objects/1, t_insert_list/1, t_test_ms/1,
t_select_delete/1,t_ets_dets/1]).
--export([do_lookup/2, do_lookup_element/3]).
-
-export([ordered/1, ordered_match/1, interface_equality/1,
fixtable_next/1, fixtable_insert/1, rename/1, rename_unnamed/1, evil_rename/1,
update_element/1, update_counter/1, evil_update_counter/1, partly_bound/1, match_heavy/1]).
@@ -85,7 +83,7 @@
%% Convenience for manual testing
-export([random_test/0]).
-% internal exports
+%% internal exports
-export([dont_make_worse_sub/0, make_better_sub1/0, make_better_sub2/0]).
-export([t_repair_continuation_do/1, t_bucket_disappears_do/1,
select_fail_do/1, whitebox_1/1, whitebox_2/1, t_delete_all_objects_do/1,
@@ -107,29 +105,27 @@
-export([t_select_reverse/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--define(m(A,B), ?line assert_eq(A,B)).
+-define(m(A,B), assert_eq(A,B)).
init_per_testcase(Case, Config) ->
- Seed = {S1,S2,S3} = random:seed0(), %now(),
- random:seed(S1,S2,S3),
- io:format("*** SEED: ~p ***\n", [Seed]),
+ rand:seed(exsplus),
+ io:format("*** SEED: ~p ***\n", [rand:export_seed()]),
start_spawn_logger(),
wait_for_test_procs(), %% Ensure previous case cleaned up
- Dog=test_server:timetrap(test_server:minutes(20)),
put('__ETS_TEST_CASE__', Case),
- [{watchdog, Dog}, {test_case, Case} | Config].
+ [{test_case, Case} | Config].
+
+end_per_testcase(_Func, _Config) ->
+ wait_for_test_procs(true).
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- wait_for_test_procs(true),
- test_server:timetrap_cancel(Dog).
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,20}}].
all() ->
[{group, new}, {group, insert}, {group, lookup},
@@ -159,7 +155,7 @@ all() ->
otp_9423,
ets_all,
take,
-
+
memory_check_summary]. % MUST BE LAST
groups() ->
@@ -200,10 +196,10 @@ end_per_suite(_Config) ->
ok.
init_per_group(_GroupName, Config) ->
- Config.
+ Config.
end_per_group(_GroupName, Config) ->
- Config.
+ Config.
%% Test that we did not have "too many" failed verify_etsmem()'s
%% in the test suite.
@@ -213,7 +209,7 @@ end_per_group(_GroupName, Config) ->
memory_check_summary(_Config) ->
case whereis(ets_test_spawn_logger) of
undefined ->
- ?t:fail("No spawn logger exist");
+ ct:fail("No spawn logger exist");
_ ->
ets_test_spawn_logger ! {self(), get_failed_memchecks},
receive {get_failed_memchecks, FailedMemchecks} -> ok end,
@@ -229,45 +225,39 @@ memory_check_summary(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-t_bucket_disappears(suite) ->
- [];
-t_bucket_disappears(doc) ->
- ["Test that a disappearing bucket during select of a non-fixed table works."];
+%% Test that a disappearing bucket during select of a non-fixed table works.
t_bucket_disappears(Config) when is_list(Config) ->
repeat_for_opts(t_bucket_disappears_do).
t_bucket_disappears_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line ets_new(abcd, [named_table, public, {keypos, 2} | Opts]),
- ?line ets:insert(abcd, {abcd,1,2}),
- ?line ets:insert(abcd, {abcd,2,2}),
- ?line ets:insert(abcd, {abcd,3,2}),
- ?line {_, Cont} = ets:select(abcd, [{{'_', '$1', '_'},
- [{'<', '$1', {const, 10}}],
- ['$1']}], 1),
- ?line ets:delete(abcd, 2),
- ?line ets:select(Cont),
- ?line true = ets:delete(abcd),
- ?line verify_etsmem(EtsMem).
-
-
-t_match_spec_run(suite) ->
- [];
-t_match_spec_run(doc) ->
- ["Check ets:match_spec_run/2."];
+ EtsMem = etsmem(),
+ ets_new(abcd, [named_table, public, {keypos, 2} | Opts]),
+ ets:insert(abcd, {abcd,1,2}),
+ ets:insert(abcd, {abcd,2,2}),
+ ets:insert(abcd, {abcd,3,2}),
+ {_, Cont} = ets:select(abcd, [{{'_', '$1', '_'},
+ [{'<', '$1', {const, 10}}],
+ ['$1']}], 1),
+ ets:delete(abcd, 2),
+ ets:select(Cont),
+ true = ets:delete(abcd),
+ verify_etsmem(EtsMem).
+
+
+%% Check ets:match_spec_run/2.
t_match_spec_run(Config) when is_list(Config) ->
init_externals(),
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
t_match_spec_run_test([{1},{2},{3}],
[{{'$1'},[{'>','$1',1}],['$1']}],
[2,3]),
- ?line Huge = [{X} || X <- lists:seq(1,2500)],
- ?line L = lists:seq(2476,2500),
+ Huge = [{X} || X <- lists:seq(1,2500)],
+ L = lists:seq(2476,2500),
t_match_spec_run_test(Huge, [{{'$1'},[{'>','$1',2475}],['$1']}], L),
- ?line L2 = [{X*16#FFFFFFF} || X <- L],
+ L2 = [{X*16#FFFFFFF} || X <- L],
t_match_spec_run_test(Huge,
[{{'$1'}, [{'>','$1',2475}], [{{{'*','$1',16#FFFFFFF}}}]}],
L2),
@@ -344,7 +334,7 @@ t_match_spec_run(Config) when is_list(Config) ->
end,
test_terms(Fun, skip_refc_check),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
t_match_spec_run_test(List, MS, Result) ->
@@ -372,14 +362,12 @@ t_match_spec_run_test(List, MS, Result) ->
erlang:trace(Tracee, true, [call]),
Tracee ! start,
TRes = ms_tracer_collect(Tracee, MonRef, []),
- %erlang:trace(Tracee, false, [call]),
- %Tracee ! stop,
case TRes of
SRes -> ok;
_ ->
io:format("TRACE MATCH FAILED\n"),
io:format("Input = ~p\nMST = ~p\nExpected = ~p\nGot = ~p\n", [List, MST, SRes, TRes]),
- ?t:fail("TRACE MATCH FAILED")
+ ct:fail("TRACE MATCH FAILED")
end,
ok.
@@ -388,32 +376,27 @@ t_match_spec_run_test(List, MS, Result) ->
ms_tracer_collect(Tracee, Ref, Acc) ->
receive
{trace, Tracee, call, _Args, [Msg]} ->
- %io:format("trace Args=~p Msg=~p\n", [_Args, Msg]),
ms_tracer_collect(Tracee, Ref, [Msg | Acc]);
{'DOWN', Ref, process, Tracee, _} ->
- %io:format("monitor DOWN for ~p\n", [Tracee]),
TDRef = erlang:trace_delivered(Tracee),
ms_tracer_collect(Tracee, TDRef, Acc);
{trace_delivered, Tracee, Ref} ->
- %%io:format("trace delivered for ~p\n", [Tracee]),
lists:sort(Acc);
Other ->
io:format("Unexpected message = ~p\n", [Other]),
- ?t:fail("Unexpected tracer msg")
+ ct:fail("Unexpected tracer msg")
end.
ms_tracee(Parent, CallArgList) ->
- %io:format("ms_tracee ~p started with ArgList = ~p\n", [self(), CallArgList]),
Parent ! {self(), ready},
receive start -> ok end,
lists:foreach(fun(Args) ->
erlang:apply(?MODULE, ms_tracee_dummy, tuple_to_list(Args))
end, CallArgList).
- %%receive stop -> ok end.
@@ -428,189 +411,181 @@ ms_clause_ets_to_trace({Head, Guard, Body}) ->
assert_eq(A,A) -> ok;
assert_eq(A,B) ->
io:format("FAILED MATCH:\n~p\n =/=\n~p\n",[A,B]),
- ?t:fail("assert_eq failed").
+ ct:fail("assert_eq failed").
-t_repair_continuation(suite) ->
- [];
-t_repair_continuation(doc) ->
- ["Check ets:repair_continuation/2."];
+%% Test ets:repair_continuation/2.
t_repair_continuation(Config) when is_list(Config) ->
repeat_for_opts(t_repair_continuation_do).
t_repair_continuation_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line MS = [{'_',[],[true]}],
- ?line MS2 = [{{{'$1','_'},'_'},[],['$1']}],
+ EtsMem = etsmem(),
+ MS = [{'_',[],[true]}],
+ MS2 = [{{{'$1','_'},'_'},[],['$1']}],
(fun() ->
- ?line T = ets_new(x,[ordered_set|Opts]),
- ?line F = fun(0,_)->ok;(N,F) -> ets:insert(T,{N,N}), F(N-1,F) end,
- ?line F(1000,F),
- ?line {_,C} = ets:select(T,MS,5),
- ?line C2 = erlang:setelement(5,C,<<>>),
- ?line {'EXIT',{badarg,_}} = (catch ets:select(C2)),
- ?line C3 = ets:repair_continuation(C2,MS),
- ?line {[true,true,true,true,true],_} = ets:select(C3),
- ?line {[true,true,true,true,true],_} = ets:select(C),
- ?line true = ets:delete(T)
+ T = ets_new(x,[ordered_set|Opts]),
+ F = fun(0,_)->ok;(N,F) -> ets:insert(T,{N,N}), F(N-1,F) end,
+ F(1000,F),
+ {_,C} = ets:select(T,MS,5),
+ C2 = erlang:setelement(5,C,<<>>),
+ {'EXIT',{badarg,_}} = (catch ets:select(C2)),
+ C3 = ets:repair_continuation(C2,MS),
+ {[true,true,true,true,true],_} = ets:select(C3),
+ {[true,true,true,true,true],_} = ets:select(C),
+ true = ets:delete(T)
end)(),
(fun() ->
- ?line T = ets_new(x,[ordered_set|Opts]),
- ?line F = fun(0,_)->ok;(N,F) -> ets:insert(T,{N,N}), F(N-1,F) end,
- ?line F(1000,F),
- ?line {_,C} = ets:select(T,MS,1001),
- ?line C = '$end_of_table',
- ?line C3 = ets:repair_continuation(C,MS),
- ?line '$end_of_table' = ets:select(C3),
- ?line '$end_of_table' = ets:select(C),
- ?line true = ets:delete(T)
+ T = ets_new(x,[ordered_set|Opts]),
+ F = fun(0,_)->ok;(N,F) -> ets:insert(T,{N,N}), F(N-1,F) end,
+ F(1000,F),
+ {_,C} = ets:select(T,MS,1001),
+ C = '$end_of_table',
+ C3 = ets:repair_continuation(C,MS),
+ '$end_of_table' = ets:select(C3),
+ '$end_of_table' = ets:select(C),
+ true = ets:delete(T)
end)(),
-
+
(fun() ->
- ?line T = ets_new(x,[ordered_set|Opts]),
- ?line F = fun(0,_)->ok;(N,F) ->
- ets:insert(T,{integer_to_list(N),N}),
- F(N-1,F)
- end,
- ?line F(1000,F),
- ?line {_,C} = ets:select(T,MS,5),
- ?line C2 = erlang:setelement(5,C,<<>>),
- ?line {'EXIT',{badarg,_}} = (catch ets:select(C2)),
- ?line C3 = ets:repair_continuation(C2,MS),
- ?line {[true,true,true,true,true],_} = ets:select(C3),
- ?line {[true,true,true,true,true],_} = ets:select(C),
- ?line true = ets:delete(T)
+ T = ets_new(x,[ordered_set|Opts]),
+ F = fun(0,_)->ok;(N,F) ->
+ ets:insert(T,{integer_to_list(N),N}),
+ F(N-1,F)
+ end,
+ F(1000,F),
+ {_,C} = ets:select(T,MS,5),
+ C2 = erlang:setelement(5,C,<<>>),
+ {'EXIT',{badarg,_}} = (catch ets:select(C2)),
+ C3 = ets:repair_continuation(C2,MS),
+ {[true,true,true,true,true],_} = ets:select(C3),
+ {[true,true,true,true,true],_} = ets:select(C),
+ true = ets:delete(T)
end)(),
(fun() ->
- ?line T = ets_new(x,[ordered_set|Opts]),
- ?line F = fun(0,_)->ok;(N,F) ->
- ets:insert(T,{{integer_to_list(N),N},N}),
- F(N-1,F)
- end,
- ?line F(1000,F),
- ?line {_,C} = ets:select(T,MS2,5),
- ?line C2 = erlang:setelement(5,C,<<>>),
- ?line {'EXIT',{badarg,_}} = (catch ets:select(C2)),
- ?line C3 = ets:repair_continuation(C2,MS2),
- ?line {[_,_,_,_,_],_} = ets:select(C3),
- ?line {[_,_,_,_,_],_} = ets:select(C),
- ?line true = ets:delete(T)
+ T = ets_new(x,[ordered_set|Opts]),
+ F = fun(0,_)->ok;(N,F) ->
+ ets:insert(T,{{integer_to_list(N),N},N}),
+ F(N-1,F)
+ end,
+ F(1000,F),
+ {_,C} = ets:select(T,MS2,5),
+ C2 = erlang:setelement(5,C,<<>>),
+ {'EXIT',{badarg,_}} = (catch ets:select(C2)),
+ C3 = ets:repair_continuation(C2,MS2),
+ {[_,_,_,_,_],_} = ets:select(C3),
+ {[_,_,_,_,_],_} = ets:select(C),
+ true = ets:delete(T)
end)(),
-
+
(fun() ->
- ?line T = ets_new(x,[set|Opts]),
- ?line F = fun(0,_)->ok;(N,F) ->
- ets:insert(T,{N,N}),
- F(N-1,F)
- end,
- ?line F(1000,F),
- ?line {_,C} = ets:select(T,MS,5),
- ?line C2 = erlang:setelement(4,C,<<>>),
- ?line {'EXIT',{badarg,_}} = (catch ets:select(C2)),
- ?line C3 = ets:repair_continuation(C2,MS),
- ?line {[true,true,true,true,true],_} = ets:select(C3),
- ?line {[true,true,true,true,true],_} = ets:select(C),
- ?line true = ets:delete(T)
+ T = ets_new(x,[set|Opts]),
+ F = fun(0,_)->ok;(N,F) ->
+ ets:insert(T,{N,N}),
+ F(N-1,F)
+ end,
+ F(1000,F),
+ {_,C} = ets:select(T,MS,5),
+ C2 = erlang:setelement(4,C,<<>>),
+ {'EXIT',{badarg,_}} = (catch ets:select(C2)),
+ C3 = ets:repair_continuation(C2,MS),
+ {[true,true,true,true,true],_} = ets:select(C3),
+ {[true,true,true,true,true],_} = ets:select(C),
+ true = ets:delete(T)
end)(),
(fun() ->
- ?line T = ets_new(x,[set|Opts]),
- ?line F = fun(0,_)->ok;(N,F) ->
- ets:insert(T,{integer_to_list(N),N}),
- F(N-1,F)
- end,
- ?line F(1000,F),
- ?line {_,C} = ets:select(T,MS,5),
- ?line C2 = erlang:setelement(4,C,<<>>),
- ?line {'EXIT',{badarg,_}} = (catch ets:select(C2)),
- ?line C3 = ets:repair_continuation(C2,MS),
- ?line {[true,true,true,true,true],_} = ets:select(C3),
- ?line {[true,true,true,true,true],_} = ets:select(C),
- ?line true = ets:delete(T)
+ T = ets_new(x,[set|Opts]),
+ F = fun(0,_)->ok;(N,F) ->
+ ets:insert(T,{integer_to_list(N),N}),
+ F(N-1,F)
+ end,
+ F(1000,F),
+ {_,C} = ets:select(T,MS,5),
+ C2 = erlang:setelement(4,C,<<>>),
+ {'EXIT',{badarg,_}} = (catch ets:select(C2)),
+ C3 = ets:repair_continuation(C2,MS),
+ {[true,true,true,true,true],_} = ets:select(C3),
+ {[true,true,true,true,true],_} = ets:select(C),
+ true = ets:delete(T)
end)(),
(fun() ->
- ?line T = ets_new(x,[bag|Opts]),
- ?line F = fun(0,_)->ok;(N,F) ->
- ets:insert(T,{integer_to_list(N),N}),
- F(N-1,F)
- end,
- ?line F(1000,F),
- ?line {_,C} = ets:select(T,MS,5),
- ?line C2 = erlang:setelement(4,C,<<>>),
- ?line {'EXIT',{badarg,_}} = (catch ets:select(C2)),
- ?line C3 = ets:repair_continuation(C2,MS),
- ?line {[true,true,true,true,true],_} = ets:select(C3),
- ?line {[true,true,true,true,true],_} = ets:select(C),
- ?line true = ets:delete(T)
+ T = ets_new(x,[bag|Opts]),
+ F = fun(0,_)->ok;(N,F) ->
+ ets:insert(T,{integer_to_list(N),N}),
+ F(N-1,F)
+ end,
+ F(1000,F),
+ {_,C} = ets:select(T,MS,5),
+ C2 = erlang:setelement(4,C,<<>>),
+ {'EXIT',{badarg,_}} = (catch ets:select(C2)),
+ C3 = ets:repair_continuation(C2,MS),
+ {[true,true,true,true,true],_} = ets:select(C3),
+ {[true,true,true,true,true],_} = ets:select(C),
+ true = ets:delete(T)
end)(),
(fun() ->
- ?line T = ets_new(x,[duplicate_bag|Opts]),
- ?line F = fun(0,_)->ok;(N,F) ->
- ets:insert(T,{integer_to_list(N),N}),
- F(N-1,F)
- end,
- ?line F(1000,F),
- ?line {_,C} = ets:select(T,MS,5),
- ?line C2 = erlang:setelement(4,C,<<>>),
- ?line {'EXIT',{badarg,_}} = (catch ets:select(C2)),
- ?line C3 = ets:repair_continuation(C2,MS),
- ?line {[true,true,true,true,true],_} = ets:select(C3),
- ?line {[true,true,true,true,true],_} = ets:select(C),
- ?line true = ets:delete(T)
+ T = ets_new(x,[duplicate_bag|Opts]),
+ F = fun(0,_)->ok;(N,F) ->
+ ets:insert(T,{integer_to_list(N),N}),
+ F(N-1,F)
+ end,
+ F(1000,F),
+ {_,C} = ets:select(T,MS,5),
+ C2 = erlang:setelement(4,C,<<>>),
+ {'EXIT',{badarg,_}} = (catch ets:select(C2)),
+ C3 = ets:repair_continuation(C2,MS),
+ {[true,true,true,true,true],_} = ets:select(C3),
+ {[true,true,true,true,true],_} = ets:select(C),
+ true = ets:delete(T)
end)(),
- ?line false = ets:is_compiled_ms(<<>>),
- ?line true = ets:is_compiled_ms(ets:match_spec_compile(MS)),
- ?line verify_etsmem(EtsMem).
+ false = ets:is_compiled_ms(<<>>),
+ true = ets:is_compiled_ms(ets:match_spec_compile(MS)),
+ verify_etsmem(EtsMem).
-default(doc) ->
- ["Check correct default vaules of a new ets table"];
-default(suite) -> [];
+%% Test correct default vaules of a new ets table.
default(Config) when is_list(Config) ->
%% Default should be set,protected
- ?line EtsMem = etsmem(),
- ?line Def = ets_new(def,[]),
- ?line set = ets:info(Def,type),
- ?line protected = ets:info(Def,protection),
+ EtsMem = etsmem(),
+ Def = ets_new(def,[]),
+ set = ets:info(Def,type),
+ protected = ets:info(Def,protection),
Compressed = erlang:system_info(ets_always_compress),
- ?line Compressed = ets:info(Def,compressed),
+ Compressed = ets:info(Def,compressed),
Self = self(),
- ?line Self = ets:info(Def,owner),
- ?line none = ets:info(Def, heir),
- ?line false = ets:info(Def,named_table),
- ?line ets:delete(Def),
- ?line verify_etsmem(EtsMem).
-
-select_fail(doc) ->
- ["Test that select fails even if nothing can match"];
-select_fail(suite) ->
- [];
+ Self = ets:info(Def,owner),
+ none = ets:info(Def, heir),
+ false = ets:info(Def,named_table),
+ ets:delete(Def),
+ verify_etsmem(EtsMem).
+
+%% Test that select fails even if nothing can match.
select_fail(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
repeat_for_opts(select_fail_do, [all_types,write_concurrency]),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
select_fail_do(Opts) ->
- ?line T = ets_new(x,Opts),
- ?line ets:insert(T,{a,a}),
- ?line case (catch
- ets:select(T,[{{a,'_'},[],[{snuffla}]}])) of
- {'EXIT',{badarg,_}} ->
- ok;
- Else0 ->
- exit({type,ets:info(T,type),
- expected,'EXIT',got,Else0})
- end,
- ?line case (catch
- ets:select(T,[{{b,'_'},[],[{snuffla}]}])) of
- {'EXIT',{badarg,_}} ->
- ok;
- Else1 ->
- exit({type,ets:info(T,type),
- expected,'EXIT',got,Else1})
- end,
- ?line ets:delete(T).
-
+ T = ets_new(x,Opts),
+ ets:insert(T,{a,a}),
+ case (catch
+ ets:select(T,[{{a,'_'},[],[{snuffla}]}])) of
+ {'EXIT',{badarg,_}} ->
+ ok;
+ Else0 ->
+ exit({type,ets:info(T,type),
+ expected,'EXIT',got,Else0})
+ end,
+ case (catch
+ ets:select(T,[{{b,'_'},[],[{snuffla}]}])) of
+ {'EXIT',{badarg,_}} ->
+ ok;
+ Else1 ->
+ exit({type,ets:info(T,type),
+ expected,'EXIT',got,Else1})
+ end,
+ ets:delete(T).
+
-define(S(T),ets:info(T,memory)).
-define(TAB_STRUCT_SZ, erts_debug:get_internal_state('DbTable_words')).
@@ -619,218 +594,180 @@ select_fail_do(Opts) ->
%% The hardcoded expected memory sizes (in words) are the ones we expect on:
%% SunOS5.8, 32-bit, non smp, private heap
%%
-memory(doc) -> ["Whitebox test of ets:info(X,memory)"];
-memory(suite) -> [];
+
+%% Whitebox test of ets:info(X, memory).
memory(Config) when is_list(Config) ->
- ?line ok = chk_normal_tab_struct_size(),
+ ok = chk_normal_tab_struct_size(),
repeat_for_opts(memory_do,[compressed]),
- ?line catch erts_debug:set_internal_state(available_internal_state, false).
+ catch erts_debug:set_internal_state(available_internal_state, false).
memory_do(Opts) ->
- ?line L = [T1,T2,T3,T4] = fill_sets_int(1000,Opts),
+ L = [T1,T2,T3,T4] = fill_sets_int(1000,Opts),
XR1 = case mem_mode(T1) of
- {normal,_} -> {13836,13046,13046,13052}; %{13862,13072,13072,13078};
- {compressed,4} -> {11041,10251,10251,10252}; %{11067,10277,10277,10278};
- {compressed,8} -> {10050,9260,9260,9260} %{10076,9286,9286,9286}
+ {normal,_} -> {13836,13046,13046,13052}; %{13862,13072,13072,13078};
+ {compressed,4} -> {11041,10251,10251,10252}; %{11067,10277,10277,10278};
+ {compressed,8} -> {10050,9260,9260,9260} %{10076,9286,9286,9286}
end,
- ?line XRes1 = adjust_xmem(L, XR1),
- ?line Res1 = {?S(T1),?S(T2),?S(T3),?S(T4)},
- ?line lists:foreach(fun(T) ->
- Before = ets:info(T,size),
- Key = 2, %894, %%ets:first(T),
- Objs = ets:lookup(T,Key),
- ?line ets:delete(T,Key),
- io:format("deleted key ~p from ~p changed size ~p to ~p: ~p\n",
- [Key, ets:info(T,type), Before, ets:info(T,size), Objs])
+ XRes1 = adjust_xmem(L, XR1),
+ Res1 = {?S(T1),?S(T2),?S(T3),?S(T4)},
+ lists:foreach(fun(T) ->
+ Before = ets:info(T,size),
+ Key = 2, %894, %%ets:first(T),
+ Objs = ets:lookup(T,Key),
+ ets:delete(T,Key),
+ io:format("deleted key ~p from ~p changed size ~p to ~p: ~p\n",
+ [Key, ets:info(T,type), Before, ets:info(T,size), Objs])
end,
L),
XR2 = case mem_mode(T1) of
- {normal,_} -> {13826,13037,13028,13034}; %{13852,13063,13054,13060};
- {compressed,4} -> {11031,10242,10233,10234}; %{11057,10268,10259,10260};
- {compressed,8} -> {10040,9251,9242,9242} %10066,9277,9268,9268}
+ {normal,_} -> {13826,13037,13028,13034}; %{13852,13063,13054,13060};
+ {compressed,4} -> {11031,10242,10233,10234}; %{11057,10268,10259,10260};
+ {compressed,8} -> {10040,9251,9242,9242} %10066,9277,9268,9268}
end,
- ?line XRes2 = adjust_xmem(L, XR2),
- ?line Res2 = {?S(T1),?S(T2),?S(T3),?S(T4)},
- ?line lists:foreach(fun(T) ->
- Before = ets:info(T,size),
- Key = 4, %802, %ets:first(T),
- Objs = ets:lookup(T,Key),
- ?line ets:match_delete(T,{Key,'_'}),
- io:format("match_deleted key ~p from ~p changed size ~p to ~p: ~p\n",
- [Key, ets:info(T,type), Before, ets:info(T,size), Objs])
- end,
- L),
+ XRes2 = adjust_xmem(L, XR2),
+ Res2 = {?S(T1),?S(T2),?S(T3),?S(T4)},
+ lists:foreach(fun(T) ->
+ Before = ets:info(T,size),
+ Key = 4, %802, %ets:first(T),
+ Objs = ets:lookup(T,Key),
+ ets:match_delete(T,{Key,'_'}),
+ io:format("match_deleted key ~p from ~p changed size ~p to ~p: ~p\n",
+ [Key, ets:info(T,type), Before, ets:info(T,size), Objs])
+ end,
+ L),
XR3 = case mem_mode(T1) of
- {normal,_} -> {13816,13028,13010,13016}; %{13842,13054,13036,13042};
- {compressed,4} -> {11021,10233,10215,10216}; %{11047,10259,10241,10242};
- {compressed,8} -> {10030,9242,9224,9224} %{10056,9268,9250,9250}
+ {normal,_} -> {13816,13028,13010,13016}; %{13842,13054,13036,13042};
+ {compressed,4} -> {11021,10233,10215,10216}; %{11047,10259,10241,10242};
+ {compressed,8} -> {10030,9242,9224,9224} %{10056,9268,9250,9250}
end,
- ?line XRes3 = adjust_xmem(L, XR3),
- ?line Res3 = {?S(T1),?S(T2),?S(T3),?S(T4)},
- ?line lists:foreach(fun(T) ->
- ?line ets:delete_all_objects(T)
+ XRes3 = adjust_xmem(L, XR3),
+ Res3 = {?S(T1),?S(T2),?S(T3),?S(T4)},
+ lists:foreach(fun(T) ->
+ ets:delete_all_objects(T)
end,
L),
- ?line XRes4 = adjust_xmem(L, {50,260,260,260}), %{76,286,286,286}),
- ?line Res4 = {?S(T1),?S(T2),?S(T3),?S(T4)},
+ XRes4 = adjust_xmem(L, {50,260,260,260}), %{76,286,286,286}),
+ Res4 = {?S(T1),?S(T2),?S(T3),?S(T4)},
lists:foreach(fun(T) ->
- ?line ets:delete(T)
+ ets:delete(T)
end,
L),
- ?line L2 = [T11,T12,T13,T14] = fill_sets_int(1000),
- ?line lists:foreach(fun(T) ->
- ?line ets:select_delete(T,[{'_',[],[true]}])
+ L2 = [T11,T12,T13,T14] = fill_sets_int(1000),
+ lists:foreach(fun(T) ->
+ ets:select_delete(T,[{'_',[],[true]}])
end,
L2),
- ?line XRes5 = adjust_xmem(L2, {50,260,260,260}), %{76,286,286,286}),
- ?line Res5 = {?S(T11),?S(T12),?S(T13),?S(T14)},
- ?line io:format("XRes1 = ~p~n"
- " Res1 = ~p~n~n"
- "XRes2 = ~p~n"
- " Res2 = ~p~n~n"
- "XRes3 = ~p~n"
- " Res3 = ~p~n~n"
- "XRes4 = ~p~n"
- " Res4 = ~p~n~n"
- "XRes5 = ~p~n"
- " Res5 = ~p~n~n",
- [XRes1, Res1,
- XRes2, Res2,
- XRes3, Res3,
- XRes4, Res4,
- XRes5, Res5]),
- ?line XRes1 = Res1,
- ?line XRes2 = Res2,
- ?line XRes3 = Res3,
- ?line XRes4 = Res4,
- ?line XRes5 = Res5,
- ?line ok.
+ XRes5 = adjust_xmem(L2, {50,260,260,260}), %{76,286,286,286}),
+ Res5 = {?S(T11),?S(T12),?S(T13),?S(T14)},
+ io:format("XRes1 = ~p~n"
+ " Res1 = ~p~n~n"
+ "XRes2 = ~p~n"
+ " Res2 = ~p~n~n"
+ "XRes3 = ~p~n"
+ " Res3 = ~p~n~n"
+ "XRes4 = ~p~n"
+ " Res4 = ~p~n~n"
+ "XRes5 = ~p~n"
+ " Res5 = ~p~n~n",
+ [XRes1, Res1,
+ XRes2, Res2,
+ XRes3, Res3,
+ XRes4, Res4,
+ XRes5, Res5]),
+ XRes1 = Res1,
+ XRes2 = Res2,
+ XRes3 = Res3,
+ XRes4 = Res4,
+ XRes5 = Res5,
+ ok.
mem_mode(T) ->
{case ets:info(T,compressed) of
- true -> compressed;
- false -> normal
+ true -> compressed;
+ false -> normal
end,
erlang:system_info(wordsize)}.
chk_normal_tab_struct_size() ->
- ?line System = {os:type(),
- os:version(),
- erlang:system_info(wordsize),
- erlang:system_info(smp_support),
- erlang:system_info(heap_type)},
- ?line ?t:format("System = ~p~n", [System]),
- %%?line ?t:format("?NORMAL_TAB_STRUCT_SZ=~p~n", [?NORMAL_TAB_STRUCT_SZ]),
- ?line ?t:format("?TAB_STRUCT_SZ=~p~n", [?TAB_STRUCT_SZ]),
+ System = {os:type(),
+ os:version(),
+ erlang:system_info(wordsize),
+ erlang:system_info(smp_support),
+ erlang:system_info(heap_type)},
+ io:format("System = ~p~n", [System]),
+ io:format("?TAB_STRUCT_SZ=~p~n", [?TAB_STRUCT_SZ]),
ok.
-% ?line case System of
-% {{unix, sunos}, {5, 8, 0}, 4, false, private} ->
-% ?line ?NORMAL_TAB_STRUCT_SZ = ?TAB_STRUCT_SZ,
-% ?line ok;
-% _ ->
-% ?line ok
-% end.
-
--define(DB_TREE_STACK_NEED,50). % The static stack for a tree, in halfword pointers are two internal words
- % so the stack gets twice as big
--define(DB_HASH_SIZEOF_EXTSEG,260). % The segment size in words, in halfword this will be twice as large.
adjust_xmem([T1,T2,T3,T4], {A0,B0,C0,D0} = _Mem0) ->
%% Adjust for 64-bit, smp, and os:
%% Table struct size may differ.
-% Mem1 = case ?TAB_STRUCT_SZ of
-% ?NORMAL_TAB_STRUCT_SZ ->
-% Mem0;
-% TabStructSz ->
-% TabDiff = TabStructSz - ?NORMAL_TAB_STRUCT_SZ,
-% {A0+TabDiff, B0+TabDiff, C0+TabDiff, D0+TabDiff}
-% end,
-
TabDiff = ?TAB_STRUCT_SZ,
- Mem1 = {A0+TabDiff, B0+TabDiff, C0+TabDiff, D0+TabDiff},
-
- case {erlang:system_info({wordsize,internal}),erlang:system_info({wordsize,external})} of
- %% Halfword, corrections for regular pointers occupying two internal words.
- {4,8} ->
- {A1,B1,C1,D1} = Mem1,
- {A1+4*ets:info(T1, size)+?DB_TREE_STACK_NEED,
- B1+3*ets:info(T2, size)+?DB_HASH_SIZEOF_EXTSEG,
- C1+3*ets:info(T3, size)+?DB_HASH_SIZEOF_EXTSEG,
- D1+3*ets:info(T4, size)+?DB_HASH_SIZEOF_EXTSEG};
- _ ->
- Mem1
- end.
+ {A0+TabDiff, B0+TabDiff, C0+TabDiff, D0+TabDiff}.
-t_whitebox(doc) ->
- ["Diverse whitebox testes"];
-t_whitebox(suite) ->
- [];
+%% Misc. whitebox tests
t_whitebox(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
repeat_for_opts(whitebox_1),
repeat_for_opts(whitebox_1),
repeat_for_opts(whitebox_1),
repeat_for_opts(whitebox_2),
repeat_for_opts(whitebox_2),
repeat_for_opts(whitebox_2),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
whitebox_1(Opts) ->
- ?line T=ets_new(x,[bag | Opts]),
- ?line ets:insert(T,[{du,glade},{ta,en}]),
- ?line ets:insert(T,[{hej,hopp2},{du,glade2},{ta,en2}]),
- ?line {_,C}=ets:match(T,{ta,'$1'},1),
- ?line ets:select(C),
- ?line ets:match(C),
- ?line ets:delete(T),
+ T=ets_new(x,[bag | Opts]),
+ ets:insert(T,[{du,glade},{ta,en}]),
+ ets:insert(T,[{hej,hopp2},{du,glade2},{ta,en2}]),
+ {_,C}=ets:match(T,{ta,'$1'},1),
+ ets:select(C),
+ ets:match(C),
+ ets:delete(T),
ok.
whitebox_2(Opts) ->
- ?line T=ets_new(x,[ordered_set, {keypos,2} | Opts]),
- ?line T2=ets_new(x,[set, {keypos,2}| Opts]),
- ?line 0 = ets:select_delete(T,[{{hej},[],[true]}]),
- ?line 0 = ets:select_delete(T,[{{hej,hopp},[],[true]}]),
- ?line 0 = ets:select_delete(T2,[{{hej},[],[true]}]),
- ?line 0 = ets:select_delete(T2,[{{hej,hopp},[],[true]}]),
- ?line ets:delete(T),
- ?line ets:delete(T2),
+ T=ets_new(x,[ordered_set, {keypos,2} | Opts]),
+ T2=ets_new(x,[set, {keypos,2}| Opts]),
+ 0 = ets:select_delete(T,[{{hej},[],[true]}]),
+ 0 = ets:select_delete(T,[{{hej,hopp},[],[true]}]),
+ 0 = ets:select_delete(T2,[{{hej},[],[true]}]),
+ 0 = ets:select_delete(T2,[{{hej,hopp},[],[true]}]),
+ ets:delete(T),
+ ets:delete(T2),
ok.
-
-
-t_ets_dets(doc) ->
- ["Test ets:to/from_dets"];
-t_ets_dets(suite) ->
- [];
+
+
+%% Test ets:to/from_dets.
t_ets_dets(Config) when is_list(Config) ->
repeat_for_opts(fun(Opts) -> t_ets_dets(Config,Opts) end).
t_ets_dets(Config, Opts) ->
- ?line Fname = gen_dets_filename(Config,1),
- ?line (catch file:delete(Fname)),
- ?line {ok,DTab} = dets:open_file(testdets_1,
+ Fname = gen_dets_filename(Config,1),
+ (catch file:delete(Fname)),
+ {ok,DTab} = dets:open_file(testdets_1,
[{file, Fname}]),
- ?line ETab = ets_new(x,Opts),
- ?line filltabint(ETab,3000),
- ?line DTab = ets:to_dets(ETab,DTab),
- ?line ets:delete_all_objects(ETab),
- ?line 0 = ets:info(ETab,size),
- ?line true = ets:from_dets(ETab,DTab),
- ?line 3000 = ets:info(ETab,size),
- ?line ets:delete(ETab),
- ?line check_badarg(catch ets:to_dets(ETab,DTab),
- ets, to_dets, [ETab,DTab]),
- ?line check_badarg(catch ets:from_dets(ETab,DTab),
- ets, from_dets, [ETab,DTab]),
- ?line ETab2 = ets_new(x,Opts),
- ?line filltabint(ETab2,3000),
- ?line dets:close(DTab),
- ?line check_badarg(catch ets:to_dets(ETab2,DTab),
- ets, to_dets, [ETab2,DTab]),
- ?line check_badarg(catch ets:from_dets(ETab2,DTab),
- ets, from_dets, [ETab2,DTab]),
- ?line ets:delete(ETab2),
- ?line (catch file:delete(Fname)),
+ ETab = ets_new(x,Opts),
+ filltabint(ETab,3000),
+ DTab = ets:to_dets(ETab,DTab),
+ ets:delete_all_objects(ETab),
+ 0 = ets:info(ETab,size),
+ true = ets:from_dets(ETab,DTab),
+ 3000 = ets:info(ETab,size),
+ ets:delete(ETab),
+ check_badarg(catch ets:to_dets(ETab,DTab),
+ ets, to_dets, [ETab,DTab]),
+ check_badarg(catch ets:from_dets(ETab,DTab),
+ ets, from_dets, [ETab,DTab]),
+ ETab2 = ets_new(x,Opts),
+ filltabint(ETab2,3000),
+ dets:close(DTab),
+ check_badarg(catch ets:to_dets(ETab2,DTab),
+ ets, to_dets, [ETab2,DTab]),
+ check_badarg(catch ets:from_dets(ETab2,DTab),
+ ets, from_dets, [ETab2,DTab]),
+ ets:delete(ETab2),
+ (catch file:delete(Fname)),
ok.
check_badarg({'EXIT', {badarg, [{M,F,Args,_} | _]}}, M, F, Args) ->
@@ -838,14 +775,11 @@ check_badarg({'EXIT', {badarg, [{M,F,Args,_} | _]}}, M, F, Args) ->
check_badarg({'EXIT', {badarg, [{M,F,A,_} | _]}}, M, F, Args) ->
true = test_server:is_native(M) andalso length(Args) =:= A.
-t_delete_all_objects(doc) ->
- ["Test ets:delete_all_objects/1"];
-t_delete_all_objects(suite) ->
- [];
+%% Test ets:delete_all_objects/1.
t_delete_all_objects(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
repeat_for_opts(t_delete_all_objects_do),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
get_kept_objects(T) ->
case ets:info(T,stats) of
@@ -856,80 +790,77 @@ get_kept_objects(T) ->
end.
t_delete_all_objects_do(Opts) ->
- ?line T=ets_new(x,Opts),
- ?line filltabint(T,4000),
- ?line O=ets:first(T),
- ?line ets:next(T,O),
- ?line ets:safe_fixtable(T,true),
- ?line true = ets:delete_all_objects(T),
- ?line '$end_of_table' = ets:next(T,O),
- ?line 0 = ets:info(T,size),
- ?line 4000 = get_kept_objects(T),
- ?line ets:safe_fixtable(T,false),
- ?line 0 = ets:info(T,size),
- ?line 0 = get_kept_objects(T),
- ?line filltabint(T,4000),
- ?line 4000 = ets:info(T,size),
- ?line true = ets:delete_all_objects(T),
- ?line 0 = ets:info(T,size),
- ?line ets:delete(T).
-
-
-t_delete_object(doc) ->
- ["Test ets:delete_object/2"];
-t_delete_object(suite) ->
- [];
+ T=ets_new(x,Opts),
+ filltabint(T,4000),
+ O=ets:first(T),
+ ets:next(T,O),
+ ets:safe_fixtable(T,true),
+ true = ets:delete_all_objects(T),
+ '$end_of_table' = ets:next(T,O),
+ 0 = ets:info(T,size),
+ 4000 = get_kept_objects(T),
+ ets:safe_fixtable(T,false),
+ 0 = ets:info(T,size),
+ 0 = get_kept_objects(T),
+ filltabint(T,4000),
+ 4000 = ets:info(T,size),
+ true = ets:delete_all_objects(T),
+ 0 = ets:info(T,size),
+ ets:delete(T).
+
+
+%% Test ets:delete_object/2.
t_delete_object(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
repeat_for_opts(t_delete_object_do),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
t_delete_object_do(Opts) ->
- ?line T = ets_new(x,Opts),
- ?line filltabint(T,4000),
- ?line del_one_by_one_set(T,1,4001),
- ?line filltabint(T,4000),
- ?line del_one_by_one_set(T,4000,0),
- ?line filltabint(T,4000),
- ?line First = ets:first(T),
- ?line Next = ets:next(T,First),
- ?line ets:safe_fixtable(T,true),
- ?line ets:delete_object(T,{First, integer_to_list(First)}),
- ?line Next = ets:next(T,First),
- ?line 3999 = ets:info(T,size),
- ?line 1 = get_kept_objects(T),
- ?line ets:safe_fixtable(T,false),
- ?line 3999 = ets:info(T,size),
- ?line 0 = get_kept_objects(T),
- ?line ets:delete(T),
- ?line T1 = ets_new(x,[ordered_set | Opts]),
- ?line filltabint(T1,4000),
- ?line del_one_by_one_set(T1,1,4001),
- ?line filltabint(T1,4000),
- ?line del_one_by_one_set(T1,4000,0),
- ?line ets:delete(T1),
- ?line T2 = ets_new(x,[bag | Opts]),
- ?line filltabint2(T2,4000),
- ?line del_one_by_one_bag(T2,1,4001),
- ?line filltabint2(T2,4000),
- ?line del_one_by_one_bag(T2,4000,0),
- ?line ets:delete(T2),
- ?line T3 = ets_new(x,[duplicate_bag | Opts]),
- ?line filltabint3(T3,4000),
- ?line del_one_by_one_dbag_1(T3,1,4001),
- ?line filltabint3(T3,4000),
- ?line del_one_by_one_dbag_1(T3,4000,0),
- ?line filltabint(T3,4000),
- ?line filltabint3(T3,4000),
- ?line del_one_by_one_dbag_2(T3,1,4001),
- ?line filltabint(T3,4000),
- ?line filltabint3(T3,4000),
- ?line del_one_by_one_dbag_2(T3,4000,0),
-
- ?line filltabint2(T3,4000),
- ?line filltabint(T3,4000),
- ?line del_one_by_one_dbag_3(T3,4000,0),
- ?line ets:delete(T3),
+ T = ets_new(x,Opts),
+ filltabint(T,4000),
+ del_one_by_one_set(T,1,4001),
+ filltabint(T,4000),
+ del_one_by_one_set(T,4000,0),
+ filltabint(T,4000),
+ First = ets:first(T),
+ Next = ets:next(T,First),
+ ets:safe_fixtable(T,true),
+ ets:delete_object(T,{First, integer_to_list(First)}),
+ Next = ets:next(T,First),
+ 3999 = ets:info(T,size),
+ 1 = get_kept_objects(T),
+ ets:safe_fixtable(T,false),
+ 3999 = ets:info(T,size),
+ 0 = get_kept_objects(T),
+ ets:delete(T),
+ T1 = ets_new(x,[ordered_set | Opts]),
+ filltabint(T1,4000),
+ del_one_by_one_set(T1,1,4001),
+ filltabint(T1,4000),
+ del_one_by_one_set(T1,4000,0),
+ ets:delete(T1),
+ T2 = ets_new(x,[bag | Opts]),
+ filltabint2(T2,4000),
+ del_one_by_one_bag(T2,1,4001),
+ filltabint2(T2,4000),
+ del_one_by_one_bag(T2,4000,0),
+ ets:delete(T2),
+ T3 = ets_new(x,[duplicate_bag | Opts]),
+ filltabint3(T3,4000),
+ del_one_by_one_dbag_1(T3,1,4001),
+ filltabint3(T3,4000),
+ del_one_by_one_dbag_1(T3,4000,0),
+ filltabint(T3,4000),
+ filltabint3(T3,4000),
+ del_one_by_one_dbag_2(T3,1,4001),
+ filltabint(T3,4000),
+ filltabint3(T3,4000),
+ del_one_by_one_dbag_2(T3,4000,0),
+
+ filltabint2(T3,4000),
+ filltabint(T3,4000),
+ del_one_by_one_dbag_3(T3,4000,0),
+ ets:delete(T3),
ok.
make_init_fun(N) when N > 4000->
@@ -951,21 +882,18 @@ make_init_fun(N) ->
exit(close_not_expected)
end.
-t_init_table(doc) ->
- ["Test ets:init_table/2"];
-t_init_table(suite) ->
- [];
+%% Test ets:init_table/2.
t_init_table(Config) when is_list(Config)->
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
repeat_for_opts(t_init_table_do),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
t_init_table_do(Opts) ->
- ?line T = ets_new(x,[duplicate_bag | Opts]),
- ?line filltabint(T,4000),
- ?line ets:init_table(T, make_init_fun(1)),
- ?line del_one_by_one_dbag_1(T,4000,0),
- ?line ets:delete(T),
+ T = ets_new(x,[duplicate_bag | Opts]),
+ filltabint(T,4000),
+ ets:init_table(T, make_init_fun(1)),
+ del_one_by_one_dbag_1(T,4000,0),
+ ets:delete(T),
ok.
do_fill_dbag_using_lists(T,0) ->
@@ -976,132 +904,120 @@ do_fill_dbag_using_lists(T,N) ->
do_fill_dbag_using_lists(T,N - 1).
-t_insert_new(doc) ->
- ["Test the insert_new function"];
-t_insert_new(suite) ->
- [];
+%% Test the insert_new function.
t_insert_new(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
- ?line L = fill_sets_int(1000) ++ fill_sets_int(1000,[{write_concurrency,true}]),
+ EtsMem = etsmem(),
+ L = fill_sets_int(1000) ++ fill_sets_int(1000,[{write_concurrency,true}]),
lists:foreach(fun(Tab) ->
- ?line false = ets:insert_new(Tab,{2,"2"}),
- ?line true = ets:insert_new(Tab,{2002,"2002"}),
- ?line false = ets:insert_new(Tab,{2002,"2002"}),
- ?line true = ets:insert(Tab,{2002,"2002"}),
- ?line false = ets:insert_new(Tab,[{2002,"2002"}]),
- ?line false = ets:insert_new(Tab,[{2002,"2002"},
+ false = ets:insert_new(Tab,{2,"2"}),
+ true = ets:insert_new(Tab,{2002,"2002"}),
+ false = ets:insert_new(Tab,{2002,"2002"}),
+ true = ets:insert(Tab,{2002,"2002"}),
+ false = ets:insert_new(Tab,[{2002,"2002"}]),
+ false = ets:insert_new(Tab,[{2002,"2002"},
{2003,"2003"}]),
- ?line false = ets:insert_new(Tab,[{2001,"2001"},
+ false = ets:insert_new(Tab,[{2001,"2001"},
{2002,"2002"},
{2003,"2003"}]),
- ?line false = ets:insert_new(Tab,[{2001,"2001"},
+ false = ets:insert_new(Tab,[{2001,"2001"},
{2002,"2002"}]),
- ?line true = ets:insert_new(Tab,[{2001,"2001"},
+ true = ets:insert_new(Tab,[{2001,"2001"},
{2003,"2003"}]),
- ?line false = ets:insert_new(Tab,{2001,"2001"}),
- ?line false = ets:insert_new(Tab,{2002,"2002"}),
- ?line false = ets:insert_new(Tab,{2003,"2003"}),
- ?line true = ets:insert_new(Tab,{2004,"2004"}),
- ?line true = ets:insert_new(Tab,{2000,"2000"}),
- ?line true = ets:insert_new(Tab,[{2005,"2005"},
- {2006,"2006"},
- {2007,"2007"}]),
- ?line Num =
+ false = ets:insert_new(Tab,{2001,"2001"}),
+ false = ets:insert_new(Tab,{2002,"2002"}),
+ false = ets:insert_new(Tab,{2003,"2003"}),
+ true = ets:insert_new(Tab,{2004,"2004"}),
+ true = ets:insert_new(Tab,{2000,"2000"}),
+ true = ets:insert_new(Tab,[{2005,"2005"},
+ {2006,"2006"},
+ {2007,"2007"}]),
+ Num =
case ets:info(Tab,type) of
bag ->
- ?line true =
+ true =
ets:insert(Tab,{2004,"2004-2"}),
- ?line false =
+ false =
ets:insert_new(Tab,{2004,"2004-3"}),
1009;
duplicate_bag ->
- ?line true =
+ true =
ets:insert(Tab,{2004,"2004"}),
- ?line false =
+ false =
ets:insert_new(Tab,{2004,"2004"}),
1010;
_ ->
1008
end,
- ?line Num = ets:info(Tab,size),
- ?line List = ets:tab2list(Tab),
- ?line ets:delete_all_objects(Tab),
- ?line true = ets:insert_new(Tab,List),
- ?line false = ets:insert_new(Tab,List),
- ?line ets:delete(Tab)
+ Num = ets:info(Tab,size),
+ List = ets:tab2list(Tab),
+ ets:delete_all_objects(Tab),
+ true = ets:insert_new(Tab,List),
+ false = ets:insert_new(Tab,List),
+ ets:delete(Tab)
end,
L),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
-t_insert_list(doc) ->
- ["Test ets:insert/2 with list of objects."];
-t_insert_list(suite) ->
- [];
+%% Test ets:insert/2 with list of objects.
t_insert_list(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
repeat_for_opts(t_insert_list_do),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
t_insert_list_do(Opts) ->
- ?line T = ets_new(x,[duplicate_bag | Opts]),
- ?line do_fill_dbag_using_lists(T,4000),
- ?line del_one_by_one_dbag_2(T,4000,0),
- ?line ets:delete(T).
+ T = ets_new(x,[duplicate_bag | Opts]),
+ do_fill_dbag_using_lists(T,4000),
+ del_one_by_one_dbag_2(T,4000,0),
+ ets:delete(T).
-t_test_ms(doc) ->
- ["Test interface of ets:test_ms/2"];
-t_test_ms(suite) ->
- [];
+%% Test interface of ets:test_ms/2.
t_test_ms(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
- ?line {ok,[a,b]} = ets:test_ms({a,b},
- [{{'$1','$2'},[{'<','$1','$2'}],['$$']}]),
- ?line {ok,false} = ets:test_ms({a,b},
- [{{'$1','$2'},[{'>','$1','$2'}],['$$']}]),
+ EtsMem = etsmem(),
+ {ok,[a,b]} = ets:test_ms({a,b},
+ [{{'$1','$2'},[{'<','$1','$2'}],['$$']}]),
+ {ok,false} = ets:test_ms({a,b},
+ [{{'$1','$2'},[{'>','$1','$2'}],['$$']}]),
Tpl = {a,gb_sets:new()},
- ?line {ok,Tpl} = ets:test_ms(Tpl, [{{'_','_'}, [], ['$_']}]), % OTP-10190
- ?line {error,[{error,String}]} = ets:test_ms({a,b},
- [{{'$1','$2'},
- [{'flurp','$1','$2'}],
- ['$$']}]),
- ?line true = (if is_list(String) -> true; true -> false end),
- ?line verify_etsmem(EtsMem).
-
-t_select_reverse(doc) ->
- ["Test the select reverse BIF's"];
-t_select_reverse(suite) ->
- [];
+ {ok,Tpl} = ets:test_ms(Tpl, [{{'_','_'}, [], ['$_']}]), % OTP-10190
+ {error,[{error,String}]} = ets:test_ms({a,b},
+ [{{'$1','$2'},
+ [{'flurp','$1','$2'}],
+ ['$$']}]),
+ true = (if is_list(String) -> true; true -> false end),
+ verify_etsmem(EtsMem).
+
+%% Test the select reverse BIFs.
t_select_reverse(Config) when is_list(Config) ->
- ?line Table = ets_new(xxx, [ordered_set]),
- ?line filltabint(Table,1000),
- ?line A = lists:reverse(ets:select(Table,[{{'$1', '_'},
+ Table = ets_new(xxx, [ordered_set]),
+ filltabint(Table,1000),
+ A = lists:reverse(ets:select(Table,[{{'$1', '_'},
[{'>',
{'rem',
'$1', 5},
2}],
['$_']}])),
- ?line A = ets:select_reverse(Table,[{{'$1', '_'},
+ A = ets:select_reverse(Table,[{{'$1', '_'},
[{'>',
{'rem',
'$1', 5},
2}],
['$_']}]),
- ?line A = reverse_chunked(Table,[{{'$1', '_'},
- [{'>',
- {'rem',
- '$1', 5},
- 2}],
- ['$_']}],3),
- % A set/bag/duplicate_bag should get the same result regardless
- % of select or select_reverse
- ?line Table2 = ets_new(xxx, [set]),
- ?line filltabint(Table2,1000),
- ?line Table3 = ets_new(xxx, [bag]),
- ?line filltabint(Table3,1000),
- ?line Table4 = ets_new(xxx, [duplicate_bag]),
- ?line filltabint(Table4,1000),
- ?line lists:map(fun(Tab) ->
+ A = reverse_chunked(Table,[{{'$1', '_'},
+ [{'>',
+ {'rem',
+ '$1', 5},
+ 2}],
+ ['$_']}],3),
+ %% A set/bag/duplicate_bag should get the same result regardless
+ %% of select or select_reverse
+ Table2 = ets_new(xxx, [set]),
+ filltabint(Table2,1000),
+ Table3 = ets_new(xxx, [bag]),
+ filltabint(Table3,1000),
+ Table4 = ets_new(xxx, [duplicate_bag]),
+ filltabint(Table4,1000),
+ lists:map(fun(Tab) ->
B = ets:select(Tab,[{{'$1', '_'},
[{'>',
{'rem',
@@ -1129,52 +1045,49 @@ do_reverse_chunked({L,C},Acc) ->
do_reverse_chunked(ets:select_reverse(C), NewAcc).
-t_select_delete(doc) ->
- ["Test the ets:select_delete/2 and ets:select_count/2 BIF's"];
-t_select_delete(suite) ->
- [];
+%% Test the ets:select_delete/2 and ets:select_count/2 BIFs.
t_select_delete(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
- ?line Tables = fill_sets_int(10000) ++ fill_sets_int(10000,[{write_concurrency,true}]),
+ EtsMem = etsmem(),
+ Tables = fill_sets_int(10000) ++ fill_sets_int(10000,[{write_concurrency,true}]),
lists:foreach
(fun(Table) ->
- ?line 4000 = ets:select_count(Table,[{{'$1', '_'},
- [{'>',
- {'rem',
- '$1', 5},
- 2}],
- [true]}]),
- ?line 4000 = ets:select_delete(Table,[{{'$1', '_'},
- [{'>',
- {'rem',
- '$1', 5},
- 2}],
- [true]}]),
- ?line check(Table,
- fun({N,_}) when (N rem 5) =< 2 ->
- true;
- (_) ->
- false
- end,
- 6000)
+ 4000 = ets:select_count(Table,[{{'$1', '_'},
+ [{'>',
+ {'rem',
+ '$1', 5},
+ 2}],
+ [true]}]),
+ 4000 = ets:select_delete(Table,[{{'$1', '_'},
+ [{'>',
+ {'rem',
+ '$1', 5},
+ 2}],
+ [true]}]),
+ check(Table,
+ fun({N,_}) when (N rem 5) =< 2 ->
+ true;
+ (_) ->
+ false
+ end,
+ 6000)
end,
Tables),
lists:foreach
(fun(Table) ->
- ?line ets:select_delete(Table,[{'_',[],[true]}]),
- ?line xfilltabint(Table,4000),
- ?line successive_delete(Table,1,4001,bound),
- ?line 0 = ets:info(Table,size),
- ?line xfilltabint(Table,4000),
- ?line successive_delete(Table,4000,0, bound),
- ?line 0 = ets:info(Table,size),
- ?line xfilltabint(Table,4000),
- ?line successive_delete(Table,1,4001,unbound),
- ?line 0 = ets:info(Table,size),
- ?line xfilltabint(Table,4000),
- ?line successive_delete(Table,4000,0, unbound),
- ?line 0 = ets:info(Table,size)
+ ets:select_delete(Table,[{'_',[],[true]}]),
+ xfilltabint(Table,4000),
+ successive_delete(Table,1,4001,bound),
+ 0 = ets:info(Table,size),
+ xfilltabint(Table,4000),
+ successive_delete(Table,4000,0, bound),
+ 0 = ets:info(Table,size),
+ xfilltabint(Table,4000),
+ successive_delete(Table,1,4001,unbound),
+ 0 = ets:info(Table,size),
+ xfilltabint(Table,4000),
+ successive_delete(Table,4000,0, unbound),
+ 0 = ets:info(Table,size)
end,
Tables),
@@ -1186,167 +1099,157 @@ t_select_delete(Config) when is_list(Config) ->
_ ->
1
end,
- ?line xfilltabstr(Table, 4000),
- ?line 1000 = ets:select_count(Table,
- [{{[$3 | '$1'], '_'},
- [{'==',
- {'length', '$1'},
- 3}],[true]}]) div F,
- ?line 1000 = ets:select_delete(Table,
- [{{[$3 | '$1'], '_'},
- [{'==',
- {'length', '$1'},
- 3}],[true]}]) div F,
- ?line check(Table, fun({[3,_,_,_],_}) -> false;
- (_) -> true
- end, 3000*F),
- ?line 8 = ets:select_count(Table,
- [{{"7",'_'},[],[false]},
- {{['_'], '_'},
- [],[true]}]) div F,
- ?line 8 = ets:select_delete(Table,
- [{{"7",'_'},[],[false]},
- {{['_'], '_'},
- [],[true]}]) div F,
- ?line check(Table, fun({"7",_}) -> true;
- ({[_],_}) -> false;
- (_) -> true
- end, 2992*F),
- ?line xfilltabstr(Table, 4000),
+ xfilltabstr(Table, 4000),
+ 1000 = ets:select_count(Table,
+ [{{[$3 | '$1'], '_'},
+ [{'==',
+ {'length', '$1'},
+ 3}],[true]}]) div F,
+ 1000 = ets:select_delete(Table,
+ [{{[$3 | '$1'], '_'},
+ [{'==',
+ {'length', '$1'},
+ 3}],[true]}]) div F,
+ check(Table, fun({[3,_,_,_],_}) -> false;
+ (_) -> true
+ end, 3000*F),
+ 8 = ets:select_count(Table,
+ [{{"7",'_'},[],[false]},
+ {{['_'], '_'},
+ [],[true]}]) div F,
+ 8 = ets:select_delete(Table,
+ [{{"7",'_'},[],[false]},
+ {{['_'], '_'},
+ [],[true]}]) div F,
+ check(Table, fun({"7",_}) -> true;
+ ({[_],_}) -> false;
+ (_) -> true
+ end, 2992*F),
+ xfilltabstr(Table, 4000),
%% This happens to be interesting for other select types too
- ?line 200 = length(ets:select(Table,
- [{{[$3,'_','_'],'_'},
- [],[true]},
- {{[$1,'_','_'],'_'},
- [],[true]}])) div F,
- ?line 200 = ets:select_count(Table,
- [{{[$3,'_','_'],'_'},
- [],[true]},
- {{[$1,'_','_'],'_'},
- [],[true]}]) div F,
- ?line 200 = length(element(1,ets:select(Table,
- [{{[$3,'_','_'],'_'},
- [],[true]},
- {{[$1,'_','_'],'_'},
- [],[true]}],
- 1000))) div F,
- ?line 200 = length(
- ets:select_reverse(Table,
- [{{[$3,'_','_'],'_'},
- [],[true]},
- {{[$1,'_','_'],'_'},
- [],[true]}])) div F,
- ?line 200 = length(
- element(1,
- ets:select_reverse
- (Table,
+ 200 = length(ets:select(Table,
+ [{{[$3,'_','_'],'_'},
+ [],[true]},
+ {{[$1,'_','_'],'_'},
+ [],[true]}])) div F,
+ 200 = ets:select_count(Table,
[{{[$3,'_','_'],'_'},
[],[true]},
{{[$1,'_','_'],'_'},
- [],[true]}],
- 1000))) div F,
- ?line 200 = ets:select_delete(Table,
- [{{[$3,'_','_'],'_'},
- [],[true]},
- {{[$1,'_','_'],'_'},
- [],[true]}]) div F,
- ?line 0 = ets:select_count(Table,
+ [],[true]}]) div F,
+ 200 = length(element(1,ets:select(Table,
+ [{{[$3,'_','_'],'_'},
+ [],[true]},
+ {{[$1,'_','_'],'_'},
+ [],[true]}],
+ 1000))) div F,
+ 200 = length(
+ ets:select_reverse(Table,
[{{[$3,'_','_'],'_'},
[],[true]},
{{[$1,'_','_'],'_'},
- [],[true]}]) div F,
- ?line check(Table, fun({[$3,_,_],_}) -> false;
- ({[$1,_,_],_}) -> false;
- (_) -> true
- end, 3800*F)
+ [],[true]}])) div F,
+ 200 = length(
+ element(1,
+ ets:select_reverse
+ (Table,
+ [{{[$3,'_','_'],'_'},
+ [],[true]},
+ {{[$1,'_','_'],'_'},
+ [],[true]}],
+ 1000))) div F,
+ 200 = ets:select_delete(Table,
+ [{{[$3,'_','_'],'_'},
+ [],[true]},
+ {{[$1,'_','_'],'_'},
+ [],[true]}]) div F,
+ 0 = ets:select_count(Table,
+ [{{[$3,'_','_'],'_'},
+ [],[true]},
+ {{[$1,'_','_'],'_'},
+ [],[true]}]) div F,
+ check(Table, fun({[$3,_,_],_}) -> false;
+ ({[$1,_,_],_}) -> false;
+ (_) -> true
+ end, 3800*F)
end,
Tables),
lists:foreach(fun(Tab) -> ets:delete(Tab) end,Tables),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
-partly_bound(doc) ->
- ["Test that partly bound keys gives faster matches"];
-partly_bound(suite) ->
- [];
+%% Test that partly bound keys gives faster matches.
partly_bound(Config) when is_list(Config) ->
case os:type() of
{win32,_} ->
{skip,"Inaccurate measurements on Windows"};
_ ->
- ?line EtsMem = etsmem(),
- ?line dont_make_worse(),
- ?line make_better(),
- ?line verify_etsmem(EtsMem)
+ EtsMem = etsmem(),
+ dont_make_worse(),
+ make_better(),
+ verify_etsmem(EtsMem)
end.
dont_make_worse() ->
seventyfive_percent_success({?MODULE,dont_make_worse_sub,[]},0,0,10).
dont_make_worse_sub() ->
- ?line T = build_table([a,b],[a,b],15000),
- ?line T1 = time_match_object(T,{'_',a,a,1500}, [{{a,a,1500},a,a,1500}]),
- ?line T2 = time_match_object(T,{{a,a,'_'},a,a,1500},
- [{{a,a,1500},a,a,1500}]),
- ?line ets:delete(T),
- ?line true = (T1 > T2),
+ T = build_table([a,b],[a,b],15000),
+ T1 = time_match_object(T,{'_',a,a,1500}, [{{a,a,1500},a,a,1500}]),
+ T2 = time_match_object(T,{{a,a,'_'},a,a,1500},
+ [{{a,a,1500},a,a,1500}]),
+ ets:delete(T),
+ true = (T1 > T2),
ok.
-
+
make_better() ->
fifty_percent_success({?MODULE,make_better_sub2,[]},0,0,10),
fifty_percent_success({?MODULE,make_better_sub1,[]},0,0,10).
make_better_sub1() ->
- ?line T = build_table2([a,b],[a,b],15000),
- ?line T1 = time_match_object(T,{'_',1500,a,a}, [{{1500,a,a},1500,a,a}]),
- ?line T2 = time_match_object(T,{{1500,a,'_'},1500,a,a},
- [{{1500,a,a},1500,a,a}]),
- ?line ets:delete(T),
- ?line io:format("~p>~p~n",[(T1 / 100),T2]),
- ?line true = ((T1 / 100) > T2), % More marginal than needed.
+ T = build_table2([a,b],[a,b],15000),
+ T1 = time_match_object(T,{'_',1500,a,a}, [{{1500,a,a},1500,a,a}]),
+ T2 = time_match_object(T,{{1500,a,'_'},1500,a,a},
+ [{{1500,a,a},1500,a,a}]),
+ ets:delete(T),
+ io:format("~p>~p~n",[(T1 / 100),T2]),
+ true = ((T1 / 100) > T2), % More marginal than needed.
ok.
make_better_sub2() ->
- ?line T = build_table2([a,b],[a,b],15000),
- ?line T1 = time_match(T,{'$1',1500,a,a}),
- ?line T2 = time_match(T,{{1500,a,'$1'},1500,a,a}),
- ?line ets:delete(T),
- ?line io:format("~p>~p~n",[(T1 / 100),T2]),
- ?line true = ((T1 / 100) > T2), % More marginal than needed.
+ T = build_table2([a,b],[a,b],15000),
+ T1 = time_match(T,{'$1',1500,a,a}),
+ T2 = time_match(T,{{1500,a,'$1'},1500,a,a}),
+ ets:delete(T),
+ io:format("~p>~p~n",[(T1 / 100),T2]),
+ true = ((T1 / 100) > T2), % More marginal than needed.
ok.
-match_heavy(doc) ->
- ["Heavy random matching, comparing set with ordered_set."];
-match_heavy(suite) ->
- [];
+%% Heavy random matching, comparing set with ordered_set.
match_heavy(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir,Config),
- DataDir = ?config(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir,Config),
+ DataDir = proplists:get_value(data_dir, Config),
%% Easier to have in process dictionary when manually
%% running the test function.
put(where_to_read,DataDir),
put(where_to_write,PrivDir),
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- NewDog=test_server:timetrap(test_server:seconds(1000)),
- NewConfig = [{watchdog, NewDog} | lists:keydelete(watchdog,1,Config)],
random_test(),
drop_match(),
- NewConfig.
+ ok.
%%% Extra safety for the very low probability that this is not
%%% caught by the random test (Statistically impossible???)
drop_match() ->
- ?line EtsMem = etsmem(),
- ?line T = build_table([a,b],[a],1500),
- ?line [{{a,a,1},a,a,1},{{b,a,1},b,a,1}] =
+ EtsMem = etsmem(),
+ T = build_table([a,b],[a],1500),
+ [{{a,a,1},a,a,1},{{b,a,1},b,a,1}] =
ets:match_object(T, {'_','_','_',1}),
- ?line true = ets:delete(T),
- ?line verify_etsmem(EtsMem).
+ true = ets:delete(T),
+ verify_etsmem(EtsMem).
ets_match(Tab,Expr) ->
- case random:uniform(2) of
+ case rand:uniform(2) of
1 ->
ets:match(Tab,Expr);
_ ->
@@ -1355,14 +1258,14 @@ ets_match(Tab,Expr) ->
match_chunked(Tab,Expr) ->
match_chunked_collect(ets:match(Tab,Expr,
- random:uniform(1999) + 1)).
+ rand:uniform(1999) + 1)).
match_chunked_collect('$end_of_table') ->
[];
match_chunked_collect({Results, Continuation}) ->
Results ++ match_chunked_collect(ets:match(Continuation)).
ets_match_object(Tab,Expr) ->
- case random:uniform(2) of
+ case rand:uniform(2) of
1 ->
ets:match_object(Tab,Expr);
_ ->
@@ -1371,176 +1274,172 @@ ets_match_object(Tab,Expr) ->
match_object_chunked(Tab,Expr) ->
match_object_chunked_collect(ets:match_object(Tab,Expr,
- random:uniform(1999) + 1)).
+ rand:uniform(1999) + 1)).
match_object_chunked_collect('$end_of_table') ->
[];
match_object_chunked_collect({Results, Continuation}) ->
Results ++ match_object_chunked_collect(ets:match_object(Continuation)).
-
+
random_test() ->
- ?line ReadDir = get(where_to_read),
- ?line WriteDir = get(where_to_write),
- ?line (catch file:make_dir(WriteDir)),
- ?line Seed = case file:consult(filename:join([ReadDir,
- "preset_random_seed.txt"])) of
- {ok,[X]} ->
- X;
- _ ->
- {A,B,C} = erlang:timestamp(),
- random:seed(A,B,C),
- get(random_seed)
- end,
- put(random_seed,Seed),
- ?line {ok, F} = file:open(filename:join([WriteDir,
- "last_random_seed.txt"]),
- [write]),
+ ReadDir = get(where_to_read),
+ WriteDir = get(where_to_write),
+ (catch file:make_dir(WriteDir)),
+ case file:consult(filename:join([ReadDir,"preset_random_seed.txt"])) of
+ {ok,[X]} ->
+ rand:seed(X);
+ _ ->
+ rand:seed(exsplus)
+ end,
+ Seed = rand:export_seed(),
+ {ok,F} = file:open(filename:join([WriteDir,"last_random_seed.txt"]),
+ [write]),
io:format(F,"~p. ~n",[Seed]),
file:close(F),
io:format("Random seed ~p written to ~s, copy to ~s to rerun with "
"same seed.",[Seed,
filename:join([WriteDir, "last_random_seed.txt"]),
filename:join([ReadDir,
- "preset_random_seed.txt"])]),
+ "preset_random_seed.txt"])]),
do_random_test().
do_random_test() ->
- ?line EtsMem = etsmem(),
- ?line OrdSet = ets_new(xxx,[ordered_set]),
- ?line Set = ets_new(xxx,[]),
- ?line do_n_times(fun() ->
- ?line Key = create_random_string(25),
- ?line Value = create_random_tuple(25),
- ?line ets:insert(OrdSet,{Key,Value}),
- ?line ets:insert(Set,{Key,Value})
+ EtsMem = etsmem(),
+ OrdSet = ets_new(xxx,[ordered_set]),
+ Set = ets_new(xxx,[]),
+ do_n_times(fun() ->
+ Key = create_random_string(25),
+ Value = create_random_tuple(25),
+ ets:insert(OrdSet,{Key,Value}),
+ ets:insert(Set,{Key,Value})
end, 5000),
- ?line io:format("~nData inserted~n"),
- ?line do_n_times(fun() ->
- ?line I = random:uniform(25),
- ?line Key = create_random_string(I) ++ '_',
- ?line L1 = ets_match_object(OrdSet,{Key,'_'}),
- ?line L2 = lists:sort(ets_match_object(Set,{Key,'_'})),
+ io:format("~nData inserted~n"),
+ do_n_times(fun() ->
+ I = rand:uniform(25),
+ Key = create_random_string(I) ++ '_',
+ L1 = ets_match_object(OrdSet,{Key,'_'}),
+ L2 = lists:sort(ets_match_object(Set,{Key,'_'})),
case L1 == L2 of
false ->
io:format("~p != ~p~n",
[L1,L2]),
- ?line exit({not_eq, L1, L2});
+ exit({not_eq, L1, L2});
true ->
ok
end
end,
2000),
- ?line io:format("~nData matched~n"),
- ?line ets:match_delete(OrdSet,'_'),
- ?line ets:match_delete(Set,'_'),
- ?line do_n_times(fun() ->
- ?line Value = create_random_string(25),
- ?line Key = create_random_tuple(25),
- ?line ets:insert(OrdSet,{Key,Value}),
- ?line ets:insert(Set,{Key,Value})
+ io:format("~nData matched~n"),
+ ets:match_delete(OrdSet,'_'),
+ ets:match_delete(Set,'_'),
+ do_n_times(fun() ->
+ Value = create_random_string(25),
+ Key = create_random_tuple(25),
+ ets:insert(OrdSet,{Key,Value}),
+ ets:insert(Set,{Key,Value})
end, 2000),
- ?line io:format("~nData inserted~n"),
+ io:format("~nData inserted~n"),
(fun() ->
- ?line Key = list_to_tuple(lists:duplicate(25,'_')),
- ?line L1 = ets_match_object(OrdSet,{Key,'_'}),
- ?line L2 = lists:sort(ets_match_object(Set,{Key,'_'})),
- ?line 2000 = length(L1),
+ Key = list_to_tuple(lists:duplicate(25,'_')),
+ L1 = ets_match_object(OrdSet,{Key,'_'}),
+ L2 = lists:sort(ets_match_object(Set,{Key,'_'})),
+ 2000 = length(L1),
case L1 == L2 of
false ->
io:format("~p != ~p~n",
[L1,L2]),
- ?line exit({not_eq, L1, L2});
+ exit({not_eq, L1, L2});
true ->
ok
end
end)(),
(fun() ->
- ?line Key = {'$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'},
- ?line L1 = ets_match_object(OrdSet,{Key,'_'}),
- ?line L2 = lists:sort(ets_match_object(Set,{Key,'_'})),
- ?line 2000 = length(L1),
+ Key = {'$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'},
+ L1 = ets_match_object(OrdSet,{Key,'_'}),
+ L2 = lists:sort(ets_match_object(Set,{Key,'_'})),
+ 2000 = length(L1),
case L1 == L2 of
false ->
io:format("~p != ~p~n",
[L1,L2]),
- ?line exit({not_eq, L1, L2});
+ exit({not_eq, L1, L2});
true ->
ok
end
end)(),
(fun() ->
- ?line Key = {'$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'},
- ?line L1 = ets_match(OrdSet,{Key,'_'}),
- ?line L2 = lists:sort(ets_match(Set,{Key,'_'})),
- ?line 2000 = length(L1),
+ Key = {'$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'},
+ L1 = ets_match(OrdSet,{Key,'_'}),
+ L2 = lists:sort(ets_match(Set,{Key,'_'})),
+ 2000 = length(L1),
case L1 == L2 of
false ->
io:format("~p != ~p~n",
[L1,L2]),
- ?line exit({not_eq, L1, L2});
+ exit({not_eq, L1, L2});
true ->
ok
end
end)(),
- ?line ets:match_delete(OrdSet,'_'),
- ?line ets:match_delete(Set,'_'),
- ?line do_n_times(fun() ->
- ?line Value = create_random_string(25),
- ?line Key = create_random_tuple(25),
- ?line ets:insert(OrdSet,{Key,Value}),
- ?line ets:insert(Set,{Key,Value})
+ ets:match_delete(OrdSet,'_'),
+ ets:match_delete(Set,'_'),
+ do_n_times(fun() ->
+ Value = create_random_string(25),
+ Key = create_random_tuple(25),
+ ets:insert(OrdSet,{Key,Value}),
+ ets:insert(Set,{Key,Value})
end, 2000),
- ?line io:format("~nData inserted~n"),
+ io:format("~nData inserted~n"),
do_n_times(fun() ->
- ?line Key = create_partly_bound_tuple(25),
- ?line L1 = ets_match_object(OrdSet,{Key,'_'}),
- ?line L2 = lists:sort(ets_match_object(Set,{Key,'_'})),
+ Key = create_partly_bound_tuple(25),
+ L1 = ets_match_object(OrdSet,{Key,'_'}),
+ L2 = lists:sort(ets_match_object(Set,{Key,'_'})),
case L1 == L2 of
false ->
io:format("~p != ~p~n",
[L1,L2]),
- ?line exit({not_eq, L1, L2});
+ exit({not_eq, L1, L2});
true ->
ok
end
end,
2000),
- ?line do_n_times(fun() ->
- ?line Key = create_partly_bound_tuple2(25),
- ?line L1 = ets_match_object(OrdSet,{Key,'_'}),
- ?line L2 = lists:sort(ets_match_object(Set,{Key,'_'})),
+ do_n_times(fun() ->
+ Key = create_partly_bound_tuple2(25),
+ L1 = ets_match_object(OrdSet,{Key,'_'}),
+ L2 = lists:sort(ets_match_object(Set,{Key,'_'})),
case L1 == L2 of
false ->
io:format("~p != ~p~n",
[L1,L2]),
- ?line exit({not_eq, L1, L2});
+ exit({not_eq, L1, L2});
true ->
ok
end
end,
2000),
do_n_times(fun() ->
- ?line Key = create_partly_bound_tuple2(25),
- ?line L1 = ets_match(OrdSet,{Key,'_'}),
- ?line L2 = lists:sort(ets_match(Set,{Key,'_'})),
+ Key = create_partly_bound_tuple2(25),
+ L1 = ets_match(OrdSet,{Key,'_'}),
+ L2 = lists:sort(ets_match(Set,{Key,'_'})),
case L1 == L2 of
false ->
io:format("~p != ~p~n",
[L1,L2]),
- ?line exit({not_eq, L1, L2});
+ exit({not_eq, L1, L2});
true ->
ok
end
@@ -1551,15 +1450,15 @@ do_random_test() ->
ets:match_delete(Set,'_'),
do_n_times(fun() ->
do_n_times(fun() ->
- ?line Value =
+ Value =
create_random_string(25),
- ?line Key = create_random_tuple(25),
- ?line ets:insert(OrdSet,{Key,Value}),
- ?line ets:insert(Set,{Key,Value})
+ Key = create_random_tuple(25),
+ ets:insert(OrdSet,{Key,Value}),
+ ets:insert(Set,{Key,Value})
end, 500),
io:format("~nData inserted~n"),
do_n_times(fun() ->
- ?line Key =
+ Key =
create_partly_bound_tuple(25),
ets:match_delete(OrdSet,{Key,'_'}),
ets:match_delete(Set,{Key,'_'}),
@@ -1584,16 +1483,13 @@ do_random_test() ->
10),
ets:delete(OrdSet),
ets:delete(Set),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
-update_element(doc) ->
- ["test various variants of update_element"];
-update_element(suite) ->
- [];
+%% Ttest various variants of update_element.
update_element(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
repeat_for_opts(update_element_opts),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
update_element_opts(Opts) ->
TupleCases = [{{key,val}, 1 ,2},
@@ -1603,12 +1499,12 @@ update_element_opts(Opts) ->
{{val,key,val,val}, 2, [3,4,1]},
{{val,val,key,val}, 3, [1,4,1,2]}, % update pos1 twice
{{val,val,val,key}, 4, [2,1,2,3]}],% update pos2 twice
-
+
lists:foreach(fun({Tuple,KeyPos,UpdPos}) -> update_element_opts(Tuple,KeyPos,UpdPos,Opts) end,
TupleCases),
-
+
update_element_neg(Opts).
-
+
update_element_opts(Tuple,KeyPos,UpdPos,Opts) ->
@@ -1627,16 +1523,15 @@ update_element(T,Tuple,KeyPos,UpdPos) ->
update_element_do(T,TupleWithKey,Key,UpdPos)
end,
KeyList).
-
+
update_element_do(Tab,Tuple,Key,UpdPos) ->
- % Strategy: Step around in Values array and call ets:update_element for the values.
- % Take Length number of steps of size 1, then of size 2, ..., Length-1.
- % This will try all combinations of {fromValue,toValue}
- %
- % IMPORTANT: size(Values) must be a prime number for this to work!!!
+ %% Strategy: Step around in Values array and call ets:update_element for the values.
+ %% Take Length number of steps of size 1, then of size 2, ..., Length-1.
+ %% This will try all combinations of {fromValue,toValue}
+ %%
+ %% IMPORTANT: size(Values) must be a prime number for this to work!!!
- %io:format("update_element_do for key=~p\n",[Key]),
Big32 = 16#12345678,
Big64 = 16#123456789abcdef0,
Values = { 623, -27, 0, Big32, -Big32, Big64, -Big64, Big32*Big32,
@@ -1646,14 +1541,14 @@ update_element_do(Tab,Tuple,Key,UpdPos) ->
(fun(X) -> X*Big32 end),
make_ref(), make_ref(), self(), ok, update_element, 28, 29 },
Length = size(Values),
-
+
PosValArgF = fun(ToIx, ResList, [Pos | PosTail], Rand, MeF) ->
NextIx = (ToIx+Rand) rem Length,
MeF(NextIx, [{Pos,element(ToIx+1,Values)} | ResList], PosTail, Rand, MeF);
(_ToIx, ResList, [], _Rand, _MeF) ->
ResList;
-
+
(ToIx, [], Pos, _Rand, _MeF) ->
{Pos, element(ToIx+1,Values)} % single {pos,value} arg
end,
@@ -1662,10 +1557,10 @@ update_element_do(Tab,Tuple,Key,UpdPos) ->
PosValArg = PosValArgF(ToIx,[],UpdPos,Rand,PosValArgF),
%%io:format("update_element(~p)~n",[PosValArg]),
ArgHash = erlang:phash2({Tab,Key,PosValArg}),
- ?line true = ets:update_element(Tab, Key, PosValArg),
- ?line ArgHash = erlang:phash2({Tab,Key,PosValArg}),
+ true = ets:update_element(Tab, Key, PosValArg),
+ ArgHash = erlang:phash2({Tab,Key,PosValArg}),
NewTuple = update_tuple(PosValArg,Tuple),
- ?line [NewTuple] = ets:lookup(Tab,Key)
+ [NewTuple] = ets:lookup(Tab,Key)
end,
LoopF = fun(_FromIx, Incr, _Times, Checksum, _MeF) when Incr >= Length ->
@@ -1685,11 +1580,11 @@ update_element_do(Tab,Tuple,Key,UpdPos) ->
end,
FirstTuple = Tuple,
- ?line true = ets:insert(Tab,FirstTuple),
- ?line [FirstTuple] = ets:lookup(Tab,Key),
-
+ true = ets:insert(Tab,FirstTuple),
+ [FirstTuple] = ets:lookup(Tab,Key),
+
Checksum = LoopF(0, 1, Length, 0, LoopF),
- ?line Checksum = (Length-1)*Length*(Length+1) div 2, % if Length is a prime
+ Checksum = (Length-1)*Length*(Length+1) div 2, % if Length is a prime
ok.
update_tuple({Pos,Val}, Tpl) ->
@@ -1707,14 +1602,14 @@ update_element_neg(Opts) ->
update_element_neg_do(Set),
update_element_neg_do(OrdSet),
ets:delete(Set),
- ?line {'EXIT',{badarg,_}} = (catch ets:update_element(Set,key,{2,1})),
+ {'EXIT',{badarg,_}} = (catch ets:update_element(Set,key,{2,1})),
ets:delete(OrdSet),
- ?line {'EXIT',{badarg,_}} = (catch ets:update_element(OrdSet,key,{2,1})),
+ {'EXIT',{badarg,_}} = (catch ets:update_element(OrdSet,key,{2,1})),
- ?line Bag = ets_new(bag,[bag | Opts]),
- ?line DBag = ets_new(duplicate_bag,[duplicate_bag | Opts]),
- ?line {'EXIT',{badarg,_}} = (catch ets:update_element(Bag,key,{2,1})),
- ?line {'EXIT',{badarg,_}} = (catch ets:update_element(DBag,key,{2,1})),
+ Bag = ets_new(bag,[bag | Opts]),
+ DBag = ets_new(duplicate_bag,[duplicate_bag | Opts]),
+ {'EXIT',{badarg,_}} = (catch ets:update_element(Bag,key,{2,1})),
+ {'EXIT',{badarg,_}} = (catch ets:update_element(DBag,key,{2,1})),
true = ets:delete(Bag),
true = ets:delete(DBag),
ok.
@@ -1722,13 +1617,13 @@ update_element_neg(Opts) ->
update_element_neg_do(T) ->
Object = {key, 0, "Hej"},
- ?line true = ets:insert(T,Object),
+ true = ets:insert(T,Object),
UpdateF = fun(Arg3) ->
ArgHash = erlang:phash2({T,key,Arg3}),
- ?line {'EXIT',{badarg,_}} = (catch ets:update_element(T,key,Arg3)),
- ?line ArgHash = erlang:phash2({T,key,Arg3}),
- ?line [Object] = ets:lookup(T,key)
+ {'EXIT',{badarg,_}} = (catch ets:update_element(T,key,Arg3)),
+ ArgHash = erlang:phash2({T,key,Arg3}),
+ [Object] = ets:lookup(T,key)
end,
%% List of invalid {Pos,Value} tuples
@@ -1744,22 +1639,19 @@ update_element_neg_do(T) ->
UpdateF([{2,1} | {3,1}]),
lists:foreach(fun(InvTpl) -> UpdateF([{2,1} | InvTpl]) end, InvList),
- ?line true = ets:update_element(T,key,[]),
- ?line false = ets:update_element(T,false,[]),
- ?line false = ets:update_element(T,false,{2,1}),
- ?line ets:delete(T,key),
- ?line false = ets:update_element(T,key,{2,1}),
+ true = ets:update_element(T,key,[]),
+ false = ets:update_element(T,false,[]),
+ false = ets:update_element(T,false,{2,1}),
+ ets:delete(T,key),
+ false = ets:update_element(T,key,{2,1}),
ok.
-update_counter(doc) ->
- ["test various variants of update_counter"];
-update_counter(suite) ->
- [];
+%% test various variants of update_counter.
update_counter(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
repeat_for_opts(update_counter_do),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
update_counter_do(Opts) ->
Set = ets_new(set,Opts),
@@ -1779,26 +1671,26 @@ update_counter_do(Opts) ->
update_counter_neg(Opts).
update_counter_for(T) ->
- ?line ets:insert(T,{a,1,1}),
- ?line 101 = ets:update_counter(T,a,100),
- ?line [{a,101,1}] = ets:lookup(T,a),
- ?line 101 = ets:update_counter(T,a,{3,100}),
- ?line [{a,101,101}] = ets:lookup(T,a),
+ ets:insert(T,{a,1,1}),
+ 101 = ets:update_counter(T,a,100),
+ [{a,101,1}] = ets:lookup(T,a),
+ 101 = ets:update_counter(T,a,{3,100}),
+ [{a,101,101}] = ets:lookup(T,a),
LooperF = fun(Obj, 0, _, _) ->
Obj;
-
+
(Obj, Times, Arg3, Myself) ->
- ?line {NewObj, Ret} = uc_mimic(Obj,Arg3),
+ {NewObj, Ret} = uc_mimic(Obj,Arg3),
ArgHash = erlang:phash2({T,a,Arg3}),
%%io:format("update_counter(~p, ~p, ~p) expecting ~p\n",[T,a,Arg3,Ret]),
[DefaultObj] = ets:lookup(T, a),
- ?line Ret = ets:update_counter(T,a,Arg3),
+ Ret = ets:update_counter(T,a,Arg3),
Ret = ets:update_counter(T, b, Arg3, DefaultObj), % Use other key
- ?line ArgHash = erlang:phash2({T,a,Arg3}),
+ ArgHash = erlang:phash2({T,a,Arg3}),
%%io:format("NewObj=~p~n ",[NewObj]),
- ?line [NewObj] = ets:lookup(T,a),
+ [NewObj] = ets:lookup(T,a),
true = ets:lookup(T, b) =:= [setelement(1, NewObj, b)],
ets:delete(T, b),
Myself(NewObj,Times-1,Arg3,Myself)
@@ -1816,78 +1708,78 @@ update_counter_for(T) ->
Steps = 100,
Obj0 = {a,0,0,0,0},
- ?line ets:insert(T,Obj0),
- ?line Obj1 = LoopF(Obj0, Steps, {2,(SmallMax32 div Steps)*2}),
- ?line Obj2 = LoopF(Obj1, Steps, {3,(SmallMax64 div Steps)*2}),
- ?line Obj3 = LoopF(Obj2, Steps, {4,(Big1Max32 div Steps)*2}),
- ?line Obj4 = LoopF(Obj3, Steps, {5,(Big1Max64 div Steps)*2}),
-
- ?line Obj5 = LoopF(Obj4, Steps, {2,-(SmallMax32 div Steps)*4}),
- ?line Obj6 = LoopF(Obj5, Steps, {3,-(SmallMax64 div Steps)*4}),
- ?line Obj7 = LoopF(Obj6, Steps, {4,-(Big1Max32 div Steps)*4}),
- ?line Obj8 = LoopF(Obj7, Steps, {5,-(Big1Max64 div Steps)*4}),
-
- ?line Obj9 = LoopF(Obj8, Steps, {2,(SmallMax32 div Steps)*2}),
- ?line ObjA = LoopF(Obj9, Steps, {3,(SmallMax64 div Steps)*2}),
- ?line ObjB = LoopF(ObjA, Steps, {4,(Big1Max32 div Steps)*2}),
- ?line Obj0 = LoopF(ObjB, Steps, {5,(Big1Max64 div Steps)*2}),
+ ets:insert(T,Obj0),
+ Obj1 = LoopF(Obj0, Steps, {2,(SmallMax32 div Steps)*2}),
+ Obj2 = LoopF(Obj1, Steps, {3,(SmallMax64 div Steps)*2}),
+ Obj3 = LoopF(Obj2, Steps, {4,(Big1Max32 div Steps)*2}),
+ Obj4 = LoopF(Obj3, Steps, {5,(Big1Max64 div Steps)*2}),
+
+ Obj5 = LoopF(Obj4, Steps, {2,-(SmallMax32 div Steps)*4}),
+ Obj6 = LoopF(Obj5, Steps, {3,-(SmallMax64 div Steps)*4}),
+ Obj7 = LoopF(Obj6, Steps, {4,-(Big1Max32 div Steps)*4}),
+ Obj8 = LoopF(Obj7, Steps, {5,-(Big1Max64 div Steps)*4}),
+
+ Obj9 = LoopF(Obj8, Steps, {2,(SmallMax32 div Steps)*2}),
+ ObjA = LoopF(Obj9, Steps, {3,(SmallMax64 div Steps)*2}),
+ ObjB = LoopF(ObjA, Steps, {4,(Big1Max32 div Steps)*2}),
+ Obj0 = LoopF(ObjB, Steps, {5,(Big1Max64 div Steps)*2}),
%% back at zero, same trip again with lists
- ?line Obj4 = LoopF(Obj0,Steps,[{2, (SmallMax32 div Steps)*2},
- {3, (SmallMax64 div Steps)*2},
- {4, (Big1Max32 div Steps)*2},
- {5, (Big1Max64 div Steps)*2}]),
+ Obj4 = LoopF(Obj0,Steps,[{2, (SmallMax32 div Steps)*2},
+ {3, (SmallMax64 div Steps)*2},
+ {4, (Big1Max32 div Steps)*2},
+ {5, (Big1Max64 div Steps)*2}]),
- ?line Obj8 = LoopF(Obj4,Steps,[{4, -(Big1Max32 div Steps)*4},
- {2, -(SmallMax32 div Steps)*4},
- {5, -(Big1Max64 div Steps)*4},
- {3, -(SmallMax64 div Steps)*4}]),
+ Obj8 = LoopF(Obj4,Steps,[{4, -(Big1Max32 div Steps)*4},
+ {2, -(SmallMax32 div Steps)*4},
+ {5, -(Big1Max64 div Steps)*4},
+ {3, -(SmallMax64 div Steps)*4}]),
- ?line Obj0 = LoopF(Obj8,Steps,[{5, (Big1Max64 div Steps)*2},
- {2, (SmallMax32 div Steps)*2},
- {4, (Big1Max32 div Steps)*2},
- {3, (SmallMax64 div Steps)*2}]),
+ Obj0 = LoopF(Obj8,Steps,[{5, (Big1Max64 div Steps)*2},
+ {2, (SmallMax32 div Steps)*2},
+ {4, (Big1Max32 div Steps)*2},
+ {3, (SmallMax64 div Steps)*2}]),
%% make them shift size at the same time
- ?line ObjC = LoopF(Obj0,Steps,[{5, (Big1Max64 div Steps)*2},
- {3, (Big1Max64 div Steps)*2 + 1},
- {2, -(Big1Max64 div Steps)*2},
- {4, -(Big1Max64 div Steps)*2 + 1}]),
+ ObjC = LoopF(Obj0,Steps,[{5, (Big1Max64 div Steps)*2},
+ {3, (Big1Max64 div Steps)*2 + 1},
+ {2, -(Big1Max64 div Steps)*2},
+ {4, -(Big1Max64 div Steps)*2 + 1}]),
%% update twice in same list
- ?line ObjD = LoopF(ObjC,Steps,[{5, -(Big1Max64 div Steps) + 1},
- {3, -(Big1Max64 div Steps)*2 - 1},
- {5, -(Big1Max64 div Steps) - 1},
- {4, (Big1Max64 div Steps)*2 - 1}]),
+ ObjD = LoopF(ObjC,Steps,[{5, -(Big1Max64 div Steps) + 1},
+ {3, -(Big1Max64 div Steps)*2 - 1},
+ {5, -(Big1Max64 div Steps) - 1},
+ {4, (Big1Max64 div Steps)*2 - 1}]),
- ?line Obj0 = LoopF(ObjD,Steps,[{2, (Big1Max64 div Steps) - 1},
- {4, Big1Max64*2},
- {2, (Big1Max64 div Steps) + 1},
- {4, -Big1Max64*2}]),
+ Obj0 = LoopF(ObjD,Steps,[{2, (Big1Max64 div Steps) - 1},
+ {4, Big1Max64*2},
+ {2, (Big1Max64 div Steps) + 1},
+ {4, -Big1Max64*2}]),
%% warping with list
- ?line ObjE = LoopF(Obj0,1000,
- [{3,SmallMax32*4 div 5,SmallMax32*2,-SmallMax32*2},
- {5,-SmallMax64*4 div 7,-SmallMax64*2,SmallMax64*2},
- {4,-Big1Max32*4 div 11,-Big1Max32*2,Big1Max32*2},
- {2,Big1Max64*4 div 13,Big1Max64*2,-Big1Max64*2}]),
+ ObjE = LoopF(Obj0,1000,
+ [{3,SmallMax32*4 div 5,SmallMax32*2,-SmallMax32*2},
+ {5,-SmallMax64*4 div 7,-SmallMax64*2,SmallMax64*2},
+ {4,-Big1Max32*4 div 11,-Big1Max32*2,Big1Max32*2},
+ {2,Big1Max64*4 div 13,Big1Max64*2,-Big1Max64*2}]),
%% warping without list
- ?line ObjF = LoopF(ObjE,1000,{3,SmallMax32*4 div 5,SmallMax32*2,-SmallMax32*2}),
- ?line ObjG = LoopF(ObjF,1000,{5,-SmallMax64*4 div 7,-SmallMax64*2,SmallMax64*2}),
- ?line ObjH = LoopF(ObjG,1000,{4,-Big1Max32*4 div 11,-Big1Max32*2,Big1Max32*2}),
- ?line ObjI = LoopF(ObjH,1000,{2,Big1Max64*4 div 13,Big1Max64*2,-Big1Max64*2}),
+ ObjF = LoopF(ObjE,1000,{3,SmallMax32*4 div 5,SmallMax32*2,-SmallMax32*2}),
+ ObjG = LoopF(ObjF,1000,{5,-SmallMax64*4 div 7,-SmallMax64*2,SmallMax64*2}),
+ ObjH = LoopF(ObjG,1000,{4,-Big1Max32*4 div 11,-Big1Max32*2,Big1Max32*2}),
+ ObjI = LoopF(ObjH,1000,{2,Big1Max64*4 div 13,Big1Max64*2,-Big1Max64*2}),
%% mixing it up
- ?line LoopF(ObjI,1000,
- [{3,SmallMax32*4 div 5,SmallMax32*2,-SmallMax32*2},
- {5,-SmallMax64*4 div 3},
- {3,-SmallMax32*4 div 11},
- {5,0},
- {4,1},
- {5,-SmallMax64*4 div 7,-SmallMax64*2,SmallMax64*2},
- {2,Big1Max64*4 div 13,Big1Max64*2,-Big1Max64*2}]),
+ LoopF(ObjI,1000,
+ [{3,SmallMax32*4 div 5,SmallMax32*2,-SmallMax32*2},
+ {5,-SmallMax64*4 div 3},
+ {3,-SmallMax32*4 div 11},
+ {5,0},
+ {4,1},
+ {5,-SmallMax64*4 div 7,-SmallMax64*2,SmallMax64*2},
+ {2,Big1Max64*4 div 13,Big1Max64*2,-Big1Max64*2}]),
ok.
%% uc_mimic works kind of like the real ets:update_counter
@@ -1895,19 +1787,19 @@ update_counter_for(T) ->
%% Pits = {Pos,Incr} | {Pos,Incr,Thres,Warp}
%% Returns {Updated tuple in ets, Return value from update_counter}
uc_mimic(Obj, Pits) when is_tuple(Pits) ->
- ?line Pos = element(1,Pits),
- ?line NewObj = setelement(Pos, Obj, uc_adder(element(Pos,Obj),Pits)),
- ?line {NewObj, element(Pos,NewObj)};
+ Pos = element(1,Pits),
+ NewObj = setelement(Pos, Obj, uc_adder(element(Pos,Obj),Pits)),
+ {NewObj, element(Pos,NewObj)};
uc_mimic(Obj, PitsList) when is_list(PitsList) ->
- ?line {NewObj,ValList} = uc_mimic(Obj,PitsList,[]),
- ?line {NewObj,lists:reverse(ValList)}.
+ {NewObj,ValList} = uc_mimic(Obj,PitsList,[]),
+ {NewObj,lists:reverse(ValList)}.
uc_mimic(Obj, [], Acc) ->
- ?line {Obj,Acc};
+ {Obj,Acc};
uc_mimic(Obj, [Pits|Tail], Acc) ->
- ?line {NewObj,NewVal} = uc_mimic(Obj,Pits),
- ?line uc_mimic(NewObj,Tail,[NewVal|Acc]).
+ {NewObj,NewVal} = uc_mimic(Obj,Pits),
+ uc_mimic(NewObj,Tail,[NewVal|Acc]).
uc_adder(Init, {_Pos, Add}) ->
Init + Add;
@@ -1920,34 +1812,34 @@ uc_adder(Init, {_Pos, Add, Thres, Warp}) ->
Z ->
Z
end.
-
+
update_counter_neg(Opts) ->
Set = ets_new(set,Opts),
OrdSet = ets_new(ordered_set,[ordered_set | Opts]),
update_counter_neg_for(Set),
update_counter_neg_for(OrdSet),
ets:delete(Set),
- ?line {'EXIT',{badarg,_}} = (catch ets:update_counter(Set,key,1)),
+ {'EXIT',{badarg,_}} = (catch ets:update_counter(Set,key,1)),
ets:delete(OrdSet),
- ?line {'EXIT',{badarg,_}} = (catch ets:update_counter(OrdSet,key,1)),
+ {'EXIT',{badarg,_}} = (catch ets:update_counter(OrdSet,key,1)),
- ?line Bag = ets_new(bag,[bag | Opts]),
- ?line DBag = ets_new(duplicate_bag,[duplicate_bag | Opts]),
- ?line {'EXIT',{badarg,_}} = (catch ets:update_counter(Bag,key,1)),
- ?line {'EXIT',{badarg,_}} = (catch ets:update_counter(DBag,key,1)),
+ Bag = ets_new(bag,[bag | Opts]),
+ DBag = ets_new(duplicate_bag,[duplicate_bag | Opts]),
+ {'EXIT',{badarg,_}} = (catch ets:update_counter(Bag,key,1)),
+ {'EXIT',{badarg,_}} = (catch ets:update_counter(DBag,key,1)),
true = ets:delete(Bag),
true = ets:delete(DBag),
ok.
update_counter_neg_for(T) ->
Object = {key,0,false,1},
- ?line true = ets:insert(T,Object),
+ true = ets:insert(T,Object),
UpdateF = fun(Arg3) ->
ArgHash = erlang:phash2({T,key,Arg3}),
- ?line {'EXIT',{badarg,_}} = (catch ets:update_counter(T,key,Arg3)),
- ?line ArgHash = erlang:phash2({T,key,Arg3}),
- ?line [Object] = ets:lookup(T,key)
+ {'EXIT',{badarg,_}} = (catch ets:update_counter(T,key,Arg3)),
+ ArgHash = erlang:phash2({T,key,Arg3}),
+ [Object] = ets:lookup(T,key)
end,
%% List of invalid arg3-tuples
@@ -1965,28 +1857,28 @@ update_counter_neg_for(T) ->
UpdateF([{2,1} | {4,1}]),
lists:foreach(fun(Inv) -> UpdateF([{2,1} | Inv]) end, InvList),
- ?line {'EXIT',{badarg,_}} = (catch ets:update_counter(T,false,1)),
- ?line ets:delete(T,key),
- ?line {'EXIT',{badarg,_}} = (catch ets:update_counter(T,key,1)),
+ {'EXIT',{badarg,_}} = (catch ets:update_counter(T,false,1)),
+ ets:delete(T,key),
+ {'EXIT',{badarg,_}} = (catch ets:update_counter(T,key,1)),
ok.
-
+
evil_update_counter(Config) when is_list(Config) ->
%% The code server uses ets table. Pre-load modules that might not be
%% already loaded.
gb_sets:module_info(),
math:module_info(),
ordsets:module_info(),
- random:module_info(),
+ rand:module_info(),
repeat_for_opts(evil_update_counter_do).
evil_update_counter_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line process_flag(trap_exit, true),
- ?line Pids = [my_spawn_link(fun() -> evil_counter(I,Opts) end) || I <- lists:seq(1, 40)],
- ?line wait_for_all(gb_sets:from_list(Pids)),
- ?line verify_etsmem(EtsMem),
+ EtsMem = etsmem(),
+ process_flag(trap_exit, true),
+ Pids = [my_spawn_link(fun() -> evil_counter(I,Opts) end) || I <- lists:seq(1, 40)],
+ wait_for_all(gb_sets:from_list(Pids)),
+ verify_etsmem(EtsMem),
ok.
wait_for_all(Pids0) ->
@@ -1996,22 +1888,22 @@ wait_for_all(Pids0) ->
false ->
receive
{'EXIT',Pid,normal} ->
- ?line Pids = gb_sets:delete(Pid, Pids0),
+ Pids = gb_sets:delete(Pid, Pids0),
wait_for_all(Pids);
Other ->
io:format("unexpected: ~p\n", [Other]),
- ?line ?t:fail()
+ ct:fail(failed)
end
end.
evil_counter(I,Opts) ->
T = ets_new(a, Opts),
Start0 = case I rem 3 of
- 0 -> 16#12345678;
- 1 -> 16#12345678FFFFFFFF;
- 2 -> 16#7777777777FFFFFFFF863648726743
- end,
- Start = Start0 + random:uniform(100000),
+ 0 -> 16#12345678;
+ 1 -> 16#12345678FFFFFFFF;
+ 2 -> 16#7777777777FFFFFFFF863648726743
+ end,
+ Start = Start0 + rand:uniform(100000),
ets:insert(T, {dracula,Start}),
Iter = 40000,
End = Start + Iter,
@@ -2026,7 +1918,7 @@ evil_counter_1(Iter, T) ->
evil_counter_1(Iter-1, T).
update_counter_with_default(Config) when is_list(Config) ->
- repeat_for_opts(update_counter_with_default_do).
+ repeat_for_opts(update_counter_with_default_do).
update_counter_with_default_do(Opts) ->
T1 = ets_new(a, [set | Opts]),
@@ -2063,20 +1955,17 @@ update_counter_with_default_do(Opts) ->
ok.
-fixtable_next(doc) ->
- ["Check that a first-next sequence always works on a fixed table"];
-fixtable_next(suite) ->
- [];
+%% Check that a first-next sequence always works on a fixed table.
fixtable_next(Config) when is_list(Config) ->
repeat_for_opts(fixtable_next_do, [write_concurrency,all_types]).
fixtable_next_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line do_fixtable_next(ets_new(set,[public | Opts])),
- ?line verify_etsmem(EtsMem).
-
+ EtsMem = etsmem(),
+ do_fixtable_next(ets_new(set,[public | Opts])),
+ verify_etsmem(EtsMem).
+
do_fixtable_next(Tab) ->
- ?line F = fun(X,T,FF) -> case X of
+ F = fun(X,T,FF) -> case X of
0 -> true;
_ ->
ets:insert(T, {X,
@@ -2085,74 +1974,70 @@ do_fixtable_next(Tab) ->
FF(X-1,T,FF)
end
end,
- ?line F(100,Tab,F),
- ?line ets:safe_fixtable(Tab,true),
- ?line First = ets:first(Tab),
- ?line ets:delete(Tab, First),
- ?line ets:next(Tab, First),
- ?line ets:match_delete(Tab,{'_','_','_'}),
- ?line '$end_of_table' = ets:next(Tab, First),
- ?line true = ets:info(Tab, fixed),
- ?line ets:safe_fixtable(Tab, false),
- ?line false = ets:info(Tab, fixed),
- ?line ets:delete(Tab).
-
-fixtable_insert(doc) ->
- ["Check inserts of deleted keys in fixed bags"];
-fixtable_insert(suite) ->
- [];
+ F(100,Tab,F),
+ ets:safe_fixtable(Tab,true),
+ First = ets:first(Tab),
+ ets:delete(Tab, First),
+ ets:next(Tab, First),
+ ets:match_delete(Tab,{'_','_','_'}),
+ '$end_of_table' = ets:next(Tab, First),
+ true = ets:info(Tab, fixed),
+ ets:safe_fixtable(Tab, false),
+ false = ets:info(Tab, fixed),
+ ets:delete(Tab).
+
+%% Check inserts of deleted keys in fixed bags.
fixtable_insert(Config) when is_list(Config) ->
Combos = [[Type,{write_concurrency,WC}] || Type<- [bag,duplicate_bag],
WC <- [false,true]],
lists:foreach(fun(Opts) -> fixtable_insert_do(Opts) end,
Combos),
ok.
-
+
fixtable_insert_do(Opts) ->
io:format("Opts = ~p\n",[Opts]),
Ets = make_table(ets, Opts, [{a,1}, {a,2}, {b,1}, {b,2}]),
ets:safe_fixtable(Ets,true),
ets:match_delete(Ets,{b,1}),
First = ets:first(Ets),
- ?line Next = case First of
- a -> b;
- b -> a
- end,
- ?line Next = ets:next(Ets,First),
+ Next = case First of
+ a -> b;
+ b -> a
+ end,
+ Next = ets:next(Ets,First),
ets:delete(Ets,Next),
- ?line '$end_of_table' = ets:next(Ets,First),
+ '$end_of_table' = ets:next(Ets,First),
ets:insert(Ets, {Next,1}),
- ?line false = ets:insert_new(Ets, {Next,1}),
- ?line Next = ets:next(Ets,First),
- ?line '$end_of_table' = ets:next(Ets,Next),
+ false = ets:insert_new(Ets, {Next,1}),
+ Next = ets:next(Ets,First),
+ '$end_of_table' = ets:next(Ets,Next),
ets:delete(Ets,Next),
'$end_of_table' = ets:next(Ets,First),
ets:insert(Ets, {Next,2}),
- ?line false = ets:insert_new(Ets, {Next,1}),
+ false = ets:insert_new(Ets, {Next,1}),
Next = ets:next(Ets,First),
'$end_of_table' = ets:next(Ets,Next),
ets:delete(Ets,First),
- ?line Next = ets:first(Ets),
- ?line '$end_of_table' = ets:next(Ets,Next),
+ Next = ets:first(Ets),
+ '$end_of_table' = ets:next(Ets,Next),
ets:delete(Ets,Next),
- ?line '$end_of_table' = ets:next(Ets,First),
- ?line true = ets:insert_new(Ets,{Next,1}),
- ?line false = ets:insert_new(Ets,{Next,2}),
- ?line Next = ets:next(Ets,First),
+ '$end_of_table' = ets:next(Ets,First),
+ true = ets:insert_new(Ets,{Next,1}),
+ false = ets:insert_new(Ets,{Next,2}),
+ Next = ets:next(Ets,First),
ets:delete_object(Ets,{Next,1}),
- ?line '$end_of_table' = ets:next(Ets,First),
- ?line true = ets:insert_new(Ets,{Next,2}),
- ?line false = ets:insert_new(Ets,{Next,1}),
- ?line Next = ets:next(Ets,First),
+ '$end_of_table' = ets:next(Ets,First),
+ true = ets:insert_new(Ets,{Next,2}),
+ false = ets:insert_new(Ets,{Next,1}),
+ Next = ets:next(Ets,First),
ets:delete(Ets,First),
ets:safe_fixtable(Ets,false),
{'EXIT',{badarg,_}} = (catch ets:next(Ets,First)),
ok.
-write_concurrency(doc) -> ["The 'write_concurrency' option"];
-write_concurrency(suite) -> [];
+%% Test the 'write_concurrency' option.
write_concurrency(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
Yes1 = ets_new(foo,[public,{write_concurrency,true}]),
Yes2 = ets_new(foo,[protected,{write_concurrency,true}]),
No1 = ets_new(foo,[private,{write_concurrency,true}]),
@@ -2172,50 +2057,49 @@ write_concurrency(Config) when is_list(Config) ->
No7 = ets_new(foo,[public,{write_concurrency,false}]),
No8 = ets_new(foo,[protected,{write_concurrency,false}]),
- ?line YesMem = ets:info(Yes1,memory),
- ?line NoHashMem = ets:info(No1,memory),
- ?line NoTreeMem = ets:info(No4,memory),
+ YesMem = ets:info(Yes1,memory),
+ NoHashMem = ets:info(No1,memory),
+ NoTreeMem = ets:info(No4,memory),
io:format("YesMem=~p NoHashMem=~p NoTreeMem=~p\n",[YesMem,NoHashMem,NoTreeMem]),
- ?line YesMem = ets:info(Yes2,memory),
- ?line YesMem = ets:info(Yes3,memory),
- ?line YesMem = ets:info(Yes4,memory),
- ?line YesMem = ets:info(Yes5,memory),
- ?line YesMem = ets:info(Yes6,memory),
- ?line NoHashMem = ets:info(No2,memory),
- ?line NoHashMem = ets:info(No3,memory),
- ?line NoTreeMem = ets:info(No5,memory),
- ?line NoTreeMem = ets:info(No6,memory),
- ?line NoHashMem = ets:info(No7,memory),
- ?line NoHashMem = ets:info(No8,memory),
-
+ YesMem = ets:info(Yes2,memory),
+ YesMem = ets:info(Yes3,memory),
+ YesMem = ets:info(Yes4,memory),
+ YesMem = ets:info(Yes5,memory),
+ YesMem = ets:info(Yes6,memory),
+ NoHashMem = ets:info(No2,memory),
+ NoHashMem = ets:info(No3,memory),
+ NoTreeMem = ets:info(No5,memory),
+ NoTreeMem = ets:info(No6,memory),
+ NoHashMem = ets:info(No7,memory),
+ NoHashMem = ets:info(No8,memory),
+
case erlang:system_info(smp_support) of
true ->
- ?line true = YesMem > NoHashMem,
- ?line true = YesMem > NoTreeMem;
+ true = YesMem > NoHashMem,
+ true = YesMem > NoTreeMem;
false ->
- ?line true = YesMem =:= NoHashMem
+ true = YesMem =:= NoHashMem
end,
- ?line {'EXIT',{badarg,_}} = (catch ets_new(foo,[public,{write_concurrency,foo}])),
- ?line {'EXIT',{badarg,_}} = (catch ets_new(foo,[public,{write_concurrency}])),
- ?line {'EXIT',{badarg,_}} = (catch ets_new(foo,[public,{write_concurrency,true,foo}])),
- ?line {'EXIT',{badarg,_}} = (catch ets_new(foo,[public,write_concurrency])),
+ {'EXIT',{badarg,_}} = (catch ets_new(foo,[public,{write_concurrency,foo}])),
+ {'EXIT',{badarg,_}} = (catch ets_new(foo,[public,{write_concurrency}])),
+ {'EXIT',{badarg,_}} = (catch ets_new(foo,[public,{write_concurrency,true,foo}])),
+ {'EXIT',{badarg,_}} = (catch ets_new(foo,[public,write_concurrency])),
lists:foreach(fun(T) -> ets:delete(T) end,
[Yes1,Yes2,Yes3,Yes4,Yes5,Yes6,
No1,No2,No3,No4,No5,No6,No7,No8]),
- ?line verify_etsmem(EtsMem),
+ verify_etsmem(EtsMem),
ok.
-
-
-heir(doc) -> ["The 'heir' option"];
-heir(suite) -> [];
+
+
+%% The 'heir' option.
heir(Config) when is_list(Config) ->
repeat_for_opts(heir_do).
heir_do(Opts) ->
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
Master = self(),
%% Different types of heir data and link/monitor relations
@@ -2224,33 +2108,33 @@ heir_do(Opts) ->
lists:seq(1,10), {17,TestFun,self()},
"The busy heir"],
Mode<-[none,link,monitor]],
- ?line lists:foreach(fun({Data,Mode})-> heir_1(Data,Mode,Opts) end,
- Combos),
-
+ lists:foreach(fun({Data,Mode})-> heir_1(Data,Mode,Opts) end,
+ Combos),
+
%% No heir
{Founder1,MrefF1} = my_spawn_monitor(fun()->heir_founder(Master,foo_data,Opts)end),
Founder1 ! {go, none},
- ?line {"No heir",Founder1} = receive_any(),
- ?line {'DOWN', MrefF1, process, Founder1, normal} = receive_any(),
- ?line undefined = ets:info(foo),
+ {"No heir",Founder1} = receive_any(),
+ {'DOWN', MrefF1, process, Founder1, normal} = receive_any(),
+ undefined = ets:info(foo),
%% An already dead heir
{Heir2,MrefH2} = my_spawn_monitor(fun()->die end),
- ?line {'DOWN', MrefH2, process, Heir2, normal} = receive_any(),
+ {'DOWN', MrefH2, process, Heir2, normal} = receive_any(),
{Founder2,MrefF2} = my_spawn_monitor(fun()->heir_founder(Master,foo_data,Opts)end),
Founder2 ! {go, Heir2},
- ?line {"No heir",Founder2} = receive_any(),
- ?line {'DOWN', MrefF2, process, Founder2, normal} = receive_any(),
- ?line undefined = ets:info(foo),
+ {"No heir",Founder2} = receive_any(),
+ {'DOWN', MrefF2, process, Founder2, normal} = receive_any(),
+ undefined = ets:info(foo),
%% When heir dies before founder
{Founder3,MrefF3} = my_spawn_monitor(fun()->heir_founder(Master,"The dying heir",Opts)end),
{Heir3,MrefH3} = my_spawn_monitor(fun()->heir_heir(Founder3)end),
Founder3 ! {go, Heir3},
- ?line {'DOWN', MrefH3, process, Heir3, normal} = receive_any(),
+ {'DOWN', MrefH3, process, Heir3, normal} = receive_any(),
Founder3 ! die_please,
- ?line {'DOWN', MrefF3, process, Founder3, normal} = receive_any(),
- ?line undefined = ets:info(foo),
+ {'DOWN', MrefF3, process, Founder3, normal} = receive_any(),
+ undefined = ets:info(foo),
%% When heir dies and pid reused before founder dies
repeat_while(fun() ->
@@ -2258,238 +2142,235 @@ heir_do(Opts) ->
{Founder4,MrefF4} = my_spawn_monitor(fun()->heir_founder(Master,"The dying heir",Opts)end),
{Heir4,MrefH4} = my_spawn_monitor(fun()->heir_heir(Founder4)end),
Founder4 ! {go, Heir4},
- ?line {'DOWN', MrefH4, process, Heir4, normal} = receive_any(),
+ {'DOWN', MrefH4, process, Heir4, normal} = receive_any(),
erts_debug:set_internal_state(next_pid, NextPidIx),
DoppelGanger = spawn_monitor_with_pid(Heir4,
- fun()-> ?line die_please = receive_any() end),
+ fun()-> die_please = receive_any() end),
Founder4 ! die_please,
- ?line {'DOWN', MrefF4, process, Founder4, normal} = receive_any(),
+ {'DOWN', MrefF4, process, Founder4, normal} = receive_any(),
case DoppelGanger of
{Heir4,MrefH4_B} ->
Heir4 ! die_please,
- ?line {'DOWN', MrefH4_B, process, Heir4, normal} = receive_any(),
- ?line undefined = ets:info(foo),
+ {'DOWN', MrefH4_B, process, Heir4, normal} = receive_any(),
+ undefined = ets:info(foo),
false;
failed ->
io:format("Failed to spawn process with pid ~p\n", [Heir4]),
true % try again
end
end),
-
- ?line verify_etsmem(EtsMem).
+
+ verify_etsmem(EtsMem).
heir_founder(Master, HeirData, Opts) ->
- ?line {go,Heir} = receive_any(),
+ {go,Heir} = receive_any(),
HeirTpl = case Heir of
none -> {heir,none};
_ -> {heir, Heir, HeirData}
end,
- ?line T = ets_new(foo,[named_table, private, HeirTpl | Opts]),
- ?line true = ets:insert(T,{key,1}),
- ?line [{key,1}] = ets:lookup(T,key),
+ T = ets_new(foo,[named_table, private, HeirTpl | Opts]),
+ true = ets:insert(T,{key,1}),
+ [{key,1}] = ets:lookup(T,key),
Self = self(),
- ?line Self = ets:info(T,owner),
- ?line case ets:info(T,heir) of
- none ->
- ?line true = (Heir =:= none) orelse (not is_process_alive(Heir)),
- Master ! {"No heir",self()};
-
- Heir ->
- ?line true = is_process_alive(Heir),
- Heir ! {table,T,HeirData},
- die_please = receive_any()
- end.
+ Self = ets:info(T,owner),
+ case ets:info(T,heir) of
+ none ->
+ true = (Heir =:= none) orelse (not is_process_alive(Heir)),
+ Master ! {"No heir",self()};
+
+ Heir ->
+ true = is_process_alive(Heir),
+ Heir ! {table,T,HeirData},
+ die_please = receive_any()
+ end.
heir_heir(Founder) ->
heir_heir(Founder, none).
heir_heir(Founder, Mode) ->
- ?line {table,T,HeirData} = receive_any(),
- ?line {'EXIT',{badarg,_}} = (catch ets:lookup(T,key)),
- ?line case HeirData of
- "The dying heir" -> exit(normal);
- _ -> ok
- end,
+ {table,T,HeirData} = receive_any(),
+ {'EXIT',{badarg,_}} = (catch ets:lookup(T,key)),
+ case HeirData of
+ "The dying heir" -> exit(normal);
+ _ -> ok
+ end,
- ?line Mref = case Mode of
- link -> process_flag(trap_exit, true),
- link(Founder);
- monitor -> erlang:monitor(process,Founder);
- none -> ok
- end,
- ?line Founder ! die_please,
- ?line Msg = case HeirData of
- "The busy heir" -> receive_any_spinning();
- _ -> receive_any()
- end,
- ?line {'ETS-TRANSFER', T, Founder, HeirData} = Msg,
- ?line foo = T,
- ?line Self = self(),
- ?line Self = ets:info(T,owner),
- ?line Self = ets:info(T,heir),
- ?line [{key,1}] = ets:lookup(T,key),
- ?line true = ets:insert(T,{key,2}),
- ?line [{key,2}] = ets:lookup(T,key),
- ?line case Mode of % Verify that EXIT or DOWN comes after ETS-TRANSFER
- link ->
- {'EXIT',Founder,normal} = receive_any(),
- process_flag(trap_exit, false);
- monitor ->
- {'DOWN', Mref, process, Founder, normal} = receive_any();
- none -> ok
- end.
+ Mref = case Mode of
+ link -> process_flag(trap_exit, true),
+ link(Founder);
+ monitor -> erlang:monitor(process,Founder);
+ none -> ok
+ end,
+ Founder ! die_please,
+ Msg = case HeirData of
+ "The busy heir" -> receive_any_spinning();
+ _ -> receive_any()
+ end,
+ {'ETS-TRANSFER', T, Founder, HeirData} = Msg,
+ foo = T,
+ Self = self(),
+ Self = ets:info(T,owner),
+ Self = ets:info(T,heir),
+ [{key,1}] = ets:lookup(T,key),
+ true = ets:insert(T,{key,2}),
+ [{key,2}] = ets:lookup(T,key),
+ case Mode of % Verify that EXIT or DOWN comes after ETS-TRANSFER
+ link ->
+ {'EXIT',Founder,normal} = receive_any(),
+ process_flag(trap_exit, false);
+ monitor ->
+ {'DOWN', Mref, process, Founder, normal} = receive_any();
+ none -> ok
+ end.
heir_1(HeirData,Mode,Opts) ->
io:format("test with heir_data = ~p\n", [HeirData]),
Master = self(),
- ?line Founder = my_spawn_link(fun() -> heir_founder(Master,HeirData,Opts) end),
+ Founder = my_spawn_link(fun() -> heir_founder(Master,HeirData,Opts) end),
io:format("founder spawned = ~p\n", [Founder]),
- ?line {Heir,Mref} = my_spawn_monitor(fun() -> heir_heir(Founder,Mode) end),
+ {Heir,Mref} = my_spawn_monitor(fun() -> heir_heir(Founder,Mode) end),
io:format("heir spawned = ~p\n", [{Heir,Mref}]),
- ?line Founder ! {go, Heir},
- ?line {'DOWN', Mref, process, Heir, normal} = receive_any().
+ Founder ! {go, Heir},
+ {'DOWN', Mref, process, Heir, normal} = receive_any().
-give_away(doc) -> ["ets:give_way/3"];
-give_away(suite) -> [];
+%% Test ets:give_way/3.
give_away(Config) when is_list(Config) ->
repeat_for_opts(give_away_do).
give_away_do(Opts) ->
- ?line T = ets_new(foo,[named_table, private | Opts]),
- ?line true = ets:insert(T,{key,1}),
- ?line [{key,1}] = ets:lookup(T,key),
+ T = ets_new(foo,[named_table, private | Opts]),
+ true = ets:insert(T,{key,1}),
+ [{key,1}] = ets:lookup(T,key),
Parent = self(),
%% Give and then give back
- ?line {Receiver,Mref} = my_spawn_monitor(fun()-> give_away_receiver(T,Parent) end),
- ?line give_me = receive_any(),
- ?line true = ets:give_away(T,Receiver,here_you_are),
- ?line {'EXIT',{badarg,_}} = (catch ets:lookup(T,key)),
- ?line Receiver ! give_back,
- ?line {'ETS-TRANSFER',T,Receiver,"Tillbakakaka"} = receive_any(),
- ?line [{key,2}] = ets:lookup(T,key),
- ?line {'DOWN', Mref, process, Receiver, normal} = receive_any(),
+ {Receiver,Mref} = my_spawn_monitor(fun()-> give_away_receiver(T,Parent) end),
+ give_me = receive_any(),
+ true = ets:give_away(T,Receiver,here_you_are),
+ {'EXIT',{badarg,_}} = (catch ets:lookup(T,key)),
+ Receiver ! give_back,
+ {'ETS-TRANSFER',T,Receiver,"Tillbakakaka"} = receive_any(),
+ [{key,2}] = ets:lookup(T,key),
+ {'DOWN', Mref, process, Receiver, normal} = receive_any(),
%% Give and then let receiver keep it
- ?line true = ets:insert(T,{key,1}),
- ?line {Receiver3,Mref3} = my_spawn_monitor(fun()-> give_away_receiver(T,Parent) end),
- ?line give_me = receive_any(),
- ?line true = ets:give_away(T,Receiver3,here_you_are),
- ?line {'EXIT',{badarg,_}} = (catch ets:lookup(T,key)),
- ?line Receiver3 ! die_please,
- ?line {'DOWN', Mref3, process, Receiver3, normal} = receive_any(),
- ?line undefined = ets:info(T),
+ true = ets:insert(T,{key,1}),
+ {Receiver3,Mref3} = my_spawn_monitor(fun()-> give_away_receiver(T,Parent) end),
+ give_me = receive_any(),
+ true = ets:give_away(T,Receiver3,here_you_are),
+ {'EXIT',{badarg,_}} = (catch ets:lookup(T,key)),
+ Receiver3 ! die_please,
+ {'DOWN', Mref3, process, Receiver3, normal} = receive_any(),
+ undefined = ets:info(T),
%% Give and then kill receiver to get back
- ?line T2 = ets_new(foo,[private | Opts]),
- ?line true = ets:insert(T2,{key,1}),
- ?line ets:setopts(T2,{heir,self(),"Som en gummiboll..."}),
- ?line {Receiver2,Mref2} = my_spawn_monitor(fun()-> give_away_receiver(T2,Parent) end),
- ?line give_me = receive_any(),
- ?line true = ets:give_away(T2,Receiver2,here_you_are),
- ?line {'EXIT',{badarg,_}} = (catch ets:lookup(T2,key)),
- ?line Receiver2 ! die_please,
- ?line {'ETS-TRANSFER',T2,Receiver2,"Som en gummiboll..."} = receive_any(),
- ?line [{key,2}] = ets:lookup(T2,key),
- ?line {'DOWN', Mref2, process, Receiver2, normal} = receive_any(),
+ T2 = ets_new(foo,[private | Opts]),
+ true = ets:insert(T2,{key,1}),
+ ets:setopts(T2,{heir,self(),"Som en gummiboll..."}),
+ {Receiver2,Mref2} = my_spawn_monitor(fun()-> give_away_receiver(T2,Parent) end),
+ give_me = receive_any(),
+ true = ets:give_away(T2,Receiver2,here_you_are),
+ {'EXIT',{badarg,_}} = (catch ets:lookup(T2,key)),
+ Receiver2 ! die_please,
+ {'ETS-TRANSFER',T2,Receiver2,"Som en gummiboll..."} = receive_any(),
+ [{key,2}] = ets:lookup(T2,key),
+ {'DOWN', Mref2, process, Receiver2, normal} = receive_any(),
%% Some negative testing
- ?line {'EXIT',{badarg,_}} = (catch ets:give_away(T2,Receiver,"To a dead one")),
- ?line {'EXIT',{badarg,_}} = (catch ets:give_away(T2,self(),"To myself")),
- ?line {'EXIT',{badarg,_}} = (catch ets:give_away(T2,"not a pid","To wrong type")),
+ {'EXIT',{badarg,_}} = (catch ets:give_away(T2,Receiver,"To a dead one")),
+ {'EXIT',{badarg,_}} = (catch ets:give_away(T2,self(),"To myself")),
+ {'EXIT',{badarg,_}} = (catch ets:give_away(T2,"not a pid","To wrong type")),
- ?line true = ets:delete(T2),
- ?line {ReceiverNeg,MrefNeg} = my_spawn_monitor(fun()-> give_away_receiver(T2,Parent) end),
- ?line give_me = receive_any(),
- ?line {'EXIT',{badarg,_}} = (catch ets:give_away(T2,ReceiverNeg,"A deleted table")),
+ true = ets:delete(T2),
+ {ReceiverNeg,MrefNeg} = my_spawn_monitor(fun()-> give_away_receiver(T2,Parent) end),
+ give_me = receive_any(),
+ {'EXIT',{badarg,_}} = (catch ets:give_away(T2,ReceiverNeg,"A deleted table")),
- ?line T3 = ets_new(foo,[public | Opts]),
+ T3 = ets_new(foo,[public | Opts]),
my_spawn_link(fun()-> {'EXIT',{badarg,_}} = (catch ets:give_away(T3,ReceiverNeg,"From non owner")),
- Parent ! done
- end),
- ?line done = receive_any(),
- ?line ReceiverNeg ! no_soup_for_you,
- ?line {'DOWN', MrefNeg, process, ReceiverNeg, normal} = receive_any(),
+ Parent ! done
+ end),
+ done = receive_any(),
+ ReceiverNeg ! no_soup_for_you,
+ {'DOWN', MrefNeg, process, ReceiverNeg, normal} = receive_any(),
ok.
give_away_receiver(T, Giver) ->
- ?line {'EXIT',{badarg,_}} = (catch ets:lookup(T,key)),
- ?line Giver ! give_me,
- ?line case receive_any() of
- {'ETS-TRANSFER',T,Giver,here_you_are} ->
- ?line [{key,1}] = ets:lookup(T,key),
- ?line true = ets:insert(T,{key,2}),
- ?line case receive_any() of
- give_back ->
- ?line true = ets:give_away(T,Giver,"Tillbakakaka"),
- ?line {'EXIT',{badarg,_}} = (catch ets:lookup(T,key));
- die_please ->
- ok
- end;
- no_soup_for_you ->
- ok
- end.
-
-
-setopts(doc) -> ["ets:setopts/2"];
-setopts(suite) -> [];
+ {'EXIT',{badarg,_}} = (catch ets:lookup(T,key)),
+ Giver ! give_me,
+ case receive_any() of
+ {'ETS-TRANSFER',T,Giver,here_you_are} ->
+ [{key,1}] = ets:lookup(T,key),
+ true = ets:insert(T,{key,2}),
+ case receive_any() of
+ give_back ->
+ true = ets:give_away(T,Giver,"Tillbakakaka"),
+ {'EXIT',{badarg,_}} = (catch ets:lookup(T,key));
+ die_please ->
+ ok
+ end;
+ no_soup_for_you ->
+ ok
+ end.
+
+
+%% Test ets:setopts/2.
setopts(Config) when is_list(Config) ->
repeat_for_opts(setopts_do,[write_concurrency,all_types]).
setopts_do(Opts) ->
Self = self(),
- ?line T = ets_new(foo,[named_table, private | Opts]),
- ?line none = ets:info(T,heir),
+ T = ets_new(foo,[named_table, private | Opts]),
+ none = ets:info(T,heir),
Heir = my_spawn_link(fun()->heir_heir(Self) end),
- ?line ets:setopts(T,{heir,Heir,"Data"}),
- ?line Heir = ets:info(T,heir),
- ?line ets:setopts(T,{heir,self(),"Data"}),
- ?line Self = ets:info(T,heir),
- ?line ets:setopts(T,[{heir,Heir,"Data"}]),
- ?line Heir = ets:info(T,heir),
- ?line ets:setopts(T,[{heir,none}]),
- ?line none = ets:info(T,heir),
-
- ?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,[{heir,self(),"Data"},false])),
- ?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,{heir,self()})),
- ?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,{heir,false})),
- ?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,heir)),
- ?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,{heir,false,"Data"})),
- ?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,{false,self(),"Data"})),
-
- ?line ets:setopts(T,{protection,protected}),
- ?line ets:setopts(T,{protection,public}),
- ?line ets:setopts(T,{protection,private}),
- ?line ets:setopts(T,[{protection,protected}]),
- ?line ets:setopts(T,[{protection,public}]),
- ?line ets:setopts(T,[{protection,private}]),
-
- ?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,{protection})),
- ?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,{protection,false})),
- ?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,{protection,private,false})),
- ?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,protection)),
- ?line ets:delete(T),
+ ets:setopts(T,{heir,Heir,"Data"}),
+ Heir = ets:info(T,heir),
+ ets:setopts(T,{heir,self(),"Data"}),
+ Self = ets:info(T,heir),
+ ets:setopts(T,[{heir,Heir,"Data"}]),
+ Heir = ets:info(T,heir),
+ ets:setopts(T,[{heir,none}]),
+ none = ets:info(T,heir),
+
+ {'EXIT',{badarg,_}} = (catch ets:setopts(T,[{heir,self(),"Data"},false])),
+ {'EXIT',{badarg,_}} = (catch ets:setopts(T,{heir,self()})),
+ {'EXIT',{badarg,_}} = (catch ets:setopts(T,{heir,false})),
+ {'EXIT',{badarg,_}} = (catch ets:setopts(T,heir)),
+ {'EXIT',{badarg,_}} = (catch ets:setopts(T,{heir,false,"Data"})),
+ {'EXIT',{badarg,_}} = (catch ets:setopts(T,{false,self(),"Data"})),
+
+ ets:setopts(T,{protection,protected}),
+ ets:setopts(T,{protection,public}),
+ ets:setopts(T,{protection,private}),
+ ets:setopts(T,[{protection,protected}]),
+ ets:setopts(T,[{protection,public}]),
+ ets:setopts(T,[{protection,private}]),
+
+ {'EXIT',{badarg,_}} = (catch ets:setopts(T,{protection})),
+ {'EXIT',{badarg,_}} = (catch ets:setopts(T,{protection,false})),
+ {'EXIT',{badarg,_}} = (catch ets:setopts(T,{protection,private,false})),
+ {'EXIT',{badarg,_}} = (catch ets:setopts(T,protection)),
+ ets:delete(T),
unlink(Heir),
exit(Heir, bang),
ok.
-bad_table(doc) -> ["All kinds of operations with bad table argument"];
-bad_table(suite) -> [];
+%% All kinds of operations with bad table argument.
bad_table(Config) when is_list(Config) ->
%% Open and close disk_log to stabilize etsmem.
Name = make_ref(),
- ?line File = filename:join([?config(priv_dir, Config),"bad_table.dummy"]),
- ?line {ok, Name} = disk_log:open([{name, Name}, {file, File}]),
- ?line disk_log:close(Name),
+ File = filename:join([proplists:get_value(priv_dir, Config),"bad_table.dummy"]),
+ {ok, Name} = disk_log:open([{name, Name}, {file, File}]),
+ disk_log:close(Name),
file:delete(File),
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
repeat_for_opts(fun(Opts) -> bad_table_do(Opts,File) end,
[write_concurrency, all_types]),
- ?line verify_etsmem(EtsMem),
+ verify_etsmem(EtsMem),
ok.
bad_table_do(Opts, DummyFile) ->
@@ -2573,26 +2454,23 @@ bad_table_op({Opts,Priv,Prot}, Op) ->
end.
bad_table_call(T,{F,Args,_}) ->
- ?line {'EXIT',{badarg,_}} = (catch apply(ets, F, [T|Args]));
+ {'EXIT',{badarg,_}} = (catch apply(ets, F, [T|Args]));
bad_table_call(T,{F,Args,_,tabarg_last}) ->
- ?line {'EXIT',{badarg,_}} = (catch apply(ets, F, Args++[T]));
+ {'EXIT',{badarg,_}} = (catch apply(ets, F, Args++[T]));
bad_table_call(T,{F,Args,_,{return,Return}}) ->
try
- ?line Return = apply(ets, F, [T|Args])
+ Return = apply(ets, F, [T|Args])
catch
error:badarg -> ok
end.
-rename(doc) ->
- ["Check rename of ets tables"];
-rename(suite) ->
- [];
+%% Check rename of ets tables.
rename(Config) when is_list(Config) ->
repeat_for_opts(rename_do, [write_concurrency, all_types]).
rename_do(Opts) ->
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
ets_new(foobazz,[named_table, public | Opts]),
ets:insert(foobazz,{foo,bazz}),
ungermanbazz = ets:rename(foobazz,ungermanbazz),
@@ -2600,42 +2478,38 @@ rename_do(Opts) ->
[{foo,bazz}] = ets:lookup(ungermanbazz,foo),
{'EXIT',{badarg,_}} = (catch ets:rename(ungermanbazz,"no atom")),
ets:delete(ungermanbazz),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
-rename_unnamed(doc) ->
- ["Check rename of unnamed ets table"];
-rename_unnamed(suite) ->
- [];
+%% Check rename of unnamed ets table.
rename_unnamed(Config) when is_list(Config) ->
repeat_for_opts(rename_unnamed_do,[write_concurrency,all_types]).
rename_unnamed_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line Tab = ets_new(bonkz,[public | Opts]),
- ?line {'EXIT',{badarg, _}} = (catch ets:insert(bonkz,{foo,bazz})),
- ?line bonkz = ets:info(Tab, name),
- ?line Tab = ets:rename(Tab, tjabonkz),
- ?line {'EXIT',{badarg, _}} = (catch ets:insert(tjabonkz,{foo,bazz})),
- ?line tjabonkz = ets:info(Tab, name),
- ?line ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
-
-evil_rename(doc) ->
- "Rename a table with many fixations, and at the same time delete it.";
+ EtsMem = etsmem(),
+ Tab = ets_new(bonkz,[public | Opts]),
+ {'EXIT',{badarg, _}} = (catch ets:insert(bonkz,{foo,bazz})),
+ bonkz = ets:info(Tab, name),
+ Tab = ets:rename(Tab, tjabonkz),
+ {'EXIT',{badarg, _}} = (catch ets:insert(tjabonkz,{foo,bazz})),
+ tjabonkz = ets:info(Tab, name),
+ ets:delete(Tab),
+ verify_etsmem(EtsMem).
+
+%% Rename a table with many fixations, and at the same time delete it.
evil_rename(Config) when is_list(Config) ->
- ?line evil_rename_1(old_hash, new_hash, [public,named_table]),
- ?line EtsMem = etsmem(),
- ?line evil_rename_1(old_tree, new_tree, [public,ordered_set,named_table]),
- ?line verify_etsmem(EtsMem).
+ evil_rename_1(old_hash, new_hash, [public,named_table]),
+ EtsMem = etsmem(),
+ evil_rename_1(old_tree, new_tree, [public,ordered_set,named_table]),
+ verify_etsmem(EtsMem).
evil_rename_1(Old, New, Flags) ->
- ?line process_flag(trap_exit, true),
- ?line Old = ets_new(Old, Flags),
- ?line Fixer = fun() -> ets:safe_fixtable(Old, true) end,
- ?line crazy_fixtable(15000, Fixer),
- ?line erlang:yield(),
- ?line New = ets:rename(Old, New),
- ?line erlang:yield(),
+ process_flag(trap_exit, true),
+ Old = ets_new(Old, Flags),
+ Fixer = fun() -> ets:safe_fixtable(Old, true) end,
+ crazy_fixtable(15000, Fixer),
+ erlang:yield(),
+ New = ets:rename(Old, New),
+ erlang:yield(),
ets:delete(New),
ok.
@@ -2678,19 +2552,16 @@ evil_create_fixed_tab() ->
ets:safe_fixtable(T, true),
T.
-interface_equality(doc) ->
- ["Tests that the return values and errors are equal for set's and"
- " ordered_set's where applicable"];
-interface_equality(suite) ->
- [];
+%% Tests that the return values and errors are equal for set's and
+%% ordered_set's where applicable.
interface_equality(Config) when is_list(Config) ->
repeat_for_opts(interface_equality_do).
interface_equality_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line Set = ets_new(set,[set | Opts]),
- ?line OrderedSet = ets_new(ordered_set,[ordered_set | Opts]),
- ?line F = fun(X,T,FF) -> case X of
+ EtsMem = etsmem(),
+ Set = ets_new(set,[set | Opts]),
+ OrderedSet = ets_new(ordered_set,[ordered_set | Opts]),
+ F = fun(X,T,FF) -> case X of
0 -> true;
_ ->
ets:insert(T, {X,
@@ -2699,38 +2570,38 @@ interface_equality_do(Opts) ->
FF(X-1,T,FF)
end
end,
- ?line F(100,Set,F),
- ?line F(100,OrderedSet,F),
- ?line equal_results(ets, insert, Set, OrderedSet, [{a,"a"}]),
- ?line equal_results(ets, insert, Set, OrderedSet, [{1,1,"1"}]),
- ?line equal_results(ets, lookup, Set, OrderedSet, [10]),
- ?line equal_results(ets, lookup, Set, OrderedSet, [1000]),
- ?line equal_results(ets, delete, Set, OrderedSet, [10]),
- ?line equal_results(ets, delete, Set, OrderedSet, [nott]),
- ?line equal_results(ets, lookup, Set, OrderedSet, [1000]),
- ?line equal_results(ets, insert, Set, OrderedSet, [10]),
- ?line equal_results(ets, next, Set, OrderedSet, ['$end_of_table']),
- ?line equal_results(ets, prev, Set, OrderedSet, ['$end_of_table']),
- ?line equal_results(ets, match, Set, OrderedSet, [{'_','_','_'}]),
- ?line equal_results(ets, match, Set, OrderedSet, [{'_','_','_','_'}]),
- ?line equal_results(ets, match, Set, OrderedSet, [{$3,$2,2}]),
- ?line equal_results(ets, match, Set, OrderedSet, ['_']),
- ?line equal_results(ets, match, Set, OrderedSet, ['$1']),
- ?line equal_results(ets, match, Set, OrderedSet, [{'_','$50',3}]),
- ?line equal_results(ets, match, Set, OrderedSet, [['_','$50',3]]),
- ?line equal_results(ets, match_delete, Set, OrderedSet, [{'_','_',4}]),
- ?line equal_results(ets, match_delete, Set, OrderedSet, [{'_','_',4}]),
- ?line equal_results(ets, match_object, Set, OrderedSet, [{'_','_',4}]),
- ?line equal_results(ets, match_object, Set, OrderedSet, [{'_','_',5}]),
- ?line equal_results(ets, match_object, Set, OrderedSet, [{'_','_',4}]),
- ?line equal_results(ets, match_object, Set, OrderedSet, ['_']),
- ?line equal_results(ets, match_object, Set, OrderedSet, ['$5011']),
- ?line equal_results(ets, match_delete, Set, OrderedSet, ['$20']),
- ?line equal_results(ets, lookup_element, Set, OrderedSet, [13,2]),
- ?line equal_results(ets, lookup_element, Set, OrderedSet, [13,4]),
- ?line equal_results(ets, lookup_element, Set, OrderedSet, [14,2]),
- ?line equal_results(ets, delete, Set, OrderedSet, []),
- ?line verify_etsmem(EtsMem).
+ F(100,Set,F),
+ F(100,OrderedSet,F),
+ equal_results(ets, insert, Set, OrderedSet, [{a,"a"}]),
+ equal_results(ets, insert, Set, OrderedSet, [{1,1,"1"}]),
+ equal_results(ets, lookup, Set, OrderedSet, [10]),
+ equal_results(ets, lookup, Set, OrderedSet, [1000]),
+ equal_results(ets, delete, Set, OrderedSet, [10]),
+ equal_results(ets, delete, Set, OrderedSet, [nott]),
+ equal_results(ets, lookup, Set, OrderedSet, [1000]),
+ equal_results(ets, insert, Set, OrderedSet, [10]),
+ equal_results(ets, next, Set, OrderedSet, ['$end_of_table']),
+ equal_results(ets, prev, Set, OrderedSet, ['$end_of_table']),
+ equal_results(ets, match, Set, OrderedSet, [{'_','_','_'}]),
+ equal_results(ets, match, Set, OrderedSet, [{'_','_','_','_'}]),
+ equal_results(ets, match, Set, OrderedSet, [{$3,$2,2}]),
+ equal_results(ets, match, Set, OrderedSet, ['_']),
+ equal_results(ets, match, Set, OrderedSet, ['$1']),
+ equal_results(ets, match, Set, OrderedSet, [{'_','$50',3}]),
+ equal_results(ets, match, Set, OrderedSet, [['_','$50',3]]),
+ equal_results(ets, match_delete, Set, OrderedSet, [{'_','_',4}]),
+ equal_results(ets, match_delete, Set, OrderedSet, [{'_','_',4}]),
+ equal_results(ets, match_object, Set, OrderedSet, [{'_','_',4}]),
+ equal_results(ets, match_object, Set, OrderedSet, [{'_','_',5}]),
+ equal_results(ets, match_object, Set, OrderedSet, [{'_','_',4}]),
+ equal_results(ets, match_object, Set, OrderedSet, ['_']),
+ equal_results(ets, match_object, Set, OrderedSet, ['$5011']),
+ equal_results(ets, match_delete, Set, OrderedSet, ['$20']),
+ equal_results(ets, lookup_element, Set, OrderedSet, [13,2]),
+ equal_results(ets, lookup_element, Set, OrderedSet, [13,4]),
+ equal_results(ets, lookup_element, Set, OrderedSet, [14,2]),
+ equal_results(ets, delete, Set, OrderedSet, []),
+ verify_etsmem(EtsMem).
equal_results(M, F, FirstArg1, FirstArg2 ,ACommon) ->
Res = maybe_sort((catch apply(M,F, [FirstArg1 | ACommon]))),
@@ -2738,8 +2609,6 @@ equal_results(M, F, FirstArg1, FirstArg2 ,ACommon) ->
maybe_sort(L) when is_list(L) ->
lists:sort(L);
-%maybe_sort({'EXIT',{Reason, [{Module, Function, _}|_]}}) ->
-% {'EXIT',{Reason, [{Module, Function, '_'}]}};
maybe_sort({'EXIT',{Reason, List}}) when is_list(List) ->
{'EXIT',{Reason, lists:map(fun({Module, Function, _, _}) ->
{Module, Function, '_'}
@@ -2748,30 +2617,27 @@ maybe_sort({'EXIT',{Reason, List}}) when is_list(List) ->
maybe_sort(Any) ->
Any.
-ordered_match(doc) ->
- ["Test match, match_object and match_delete in ordered set's"];
-ordered_match(suite) ->
- [];
+%% Test match, match_object and match_delete in ordered set's.
ordered_match(Config) when is_list(Config)->
repeat_for_opts(ordered_match_do).
ordered_match_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line F = fun(X,T,FF) -> case X of
- 0 -> true;
- _ ->
- ets:insert(T, {X,
- integer_to_list(X),
- X rem 10,
- X rem 100,
- X rem 1000}),
- FF(X-1,T,FF)
- end
+ EtsMem = etsmem(),
+ F = fun(X,T,FF) -> case X of
+ 0 -> true;
+ _ ->
+ ets:insert(T, {X,
+ integer_to_list(X),
+ X rem 10,
+ X rem 100,
+ X rem 1000}),
+ FF(X-1,T,FF)
+ end
end,
- ?line T1 = ets_new(xxx,[ordered_set| Opts]),
- ?line F(3000,T1,F),
- ?line [[3,3],[3,3],[3,3]] = ets:match(T1, {'_','_','$1','$2',3}),
- ?line F2 = fun(X,Rem,Res,FF) -> case X of
+ T1 = ets_new(xxx,[ordered_set| Opts]),
+ F(3000,T1,F),
+ [[3,3],[3,3],[3,3]] = ets:match(T1, {'_','_','$1','$2',3}),
+ F2 = fun(X,Rem,Res,FF) -> case X of
0 -> [];
_ ->
case X rem Rem of
@@ -2787,166 +2653,153 @@ ordered_match_do(Opts) ->
end
end
end,
- ?line OL1 = F2(3000,100,2,F2),
- ?line OL1 = ets:match_object(T1, {'_','_','_',2,'_'}),
- ?line true = ets:match_delete(T1,{'_','_','_',2,'_'}),
- ?line [] = ets:match_object(T1, {'_','_','_',2,'_'}),
- ?line OL2 = F2(3000,100,3,F2),
- ?line OL2 = ets:match_object(T1, {'_','_','_',3,'_'}),
- ?line ets:delete(T1),
- ?line verify_etsmem(EtsMem).
-
-
-ordered(doc) ->
- ["Test basic functionality in ordered_set's."];
-ordered(suite) ->
- [];
+ OL1 = F2(3000,100,2,F2),
+ OL1 = ets:match_object(T1, {'_','_','_',2,'_'}),
+ true = ets:match_delete(T1,{'_','_','_',2,'_'}),
+ [] = ets:match_object(T1, {'_','_','_',2,'_'}),
+ OL2 = F2(3000,100,3,F2),
+ OL2 = ets:match_object(T1, {'_','_','_',3,'_'}),
+ ets:delete(T1),
+ verify_etsmem(EtsMem).
+
+
+%% Test basic functionality in ordered_set's.
ordered(Config) when is_list(Config) ->
repeat_for_opts(ordered_do).
ordered_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line T = ets_new(oset, [ordered_set | Opts]),
- ?line InsList = [
- 25,26,27,28,
- 5,6,7,8,
- 21,22,23,24,
- 9,10,11,12,
- 1,2,3,4,
- 17,18,19,20,
- 13,14,15,16,
- 1 bsl 33
- ],
- ?line lists:foreach(fun(X) ->
+ EtsMem = etsmem(),
+ T = ets_new(oset, [ordered_set | Opts]),
+ InsList = [
+ 25,26,27,28,
+ 5,6,7,8,
+ 21,22,23,24,
+ 9,10,11,12,
+ 1,2,3,4,
+ 17,18,19,20,
+ 13,14,15,16,
+ 1 bsl 33
+ ],
+ lists:foreach(fun(X) ->
ets:insert(T,{X,integer_to_list(X)})
end,
InsList),
- ?line IL2 = lists:map(fun(X) -> {X,integer_to_list(X)} end, InsList),
- ?line L1 = pick_all_forward(T),
- ?line L2 = pick_all_backwards(T),
- ?line S1 = lists:sort(IL2),
- ?line S2 = lists:reverse(lists:sort(IL2)),
- ?line S1 = L1,
- ?line S2 = L2,
- ?line [{1,"1"}] = ets:slot(T,0),
- ?line [{28,"28"}] = ets:slot(T,27),
- ?line [{1 bsl 33,_}] = ets:slot(T,28),
- ?line 27 = ets:prev(T,28),
- ?line [{7,"7"}] = ets:slot(T,6),
- ?line '$end_of_table' = ets:next(T,1 bsl 33),
- ?line [{12,"12"}] = ets:slot(T,11),
- ?line '$end_of_table' = ets:slot(T,29),
- ?line [{1,"1"}] = ets:slot(T,0),
- ?line 28 = ets:prev(T,1 bsl 33),
- ?line 1 = ets:next(T,0),
- ?line pick_all_forward(T),
- ?line [{7,"7"}] = ets:slot(T,6),
- ?line L2 = pick_all_backwards(T),
- ?line [{7,"7"}] = ets:slot(T,6),
- ?line ets:delete(T),
- ?line verify_etsmem(EtsMem).
+ IL2 = lists:map(fun(X) -> {X,integer_to_list(X)} end, InsList),
+ L1 = pick_all_forward(T),
+ L2 = pick_all_backwards(T),
+ S1 = lists:sort(IL2),
+ S2 = lists:reverse(lists:sort(IL2)),
+ S1 = L1,
+ S2 = L2,
+ [{1,"1"}] = ets:slot(T,0),
+ [{28,"28"}] = ets:slot(T,27),
+ [{1 bsl 33,_}] = ets:slot(T,28),
+ 27 = ets:prev(T,28),
+ [{7,"7"}] = ets:slot(T,6),
+ '$end_of_table' = ets:next(T,1 bsl 33),
+ [{12,"12"}] = ets:slot(T,11),
+ '$end_of_table' = ets:slot(T,29),
+ [{1,"1"}] = ets:slot(T,0),
+ 28 = ets:prev(T,1 bsl 33),
+ 1 = ets:next(T,0),
+ pick_all_forward(T),
+ [{7,"7"}] = ets:slot(T,6),
+ L2 = pick_all_backwards(T),
+ [{7,"7"}] = ets:slot(T,6),
+ ets:delete(T),
+ verify_etsmem(EtsMem).
pick_all(_T,'$end_of_table',_How) ->
[];
pick_all(T,Last,How) ->
- ?line This = case How of
+ This = case How of
next ->
- ?line ets:next(T,Last);
+ ets:next(T,Last);
prev ->
- ?line ets:prev(T,Last)
+ ets:prev(T,Last)
end,
- ?line [LastObj] = ets:lookup(T,Last),
- ?line [LastObj | pick_all(T,This,How)].
+ [LastObj] = ets:lookup(T,Last),
+ [LastObj | pick_all(T,This,How)].
pick_all_forward(T) ->
- ?line pick_all(T,ets:first(T),next).
+ pick_all(T,ets:first(T),next).
pick_all_backwards(T) ->
- ?line pick_all(T,ets:last(T),prev).
-
-
+ pick_all(T,ets:last(T),prev).
+
-setbag(doc) -> ["Small test case for both set and bag type ets tables."];
-setbag(suite) -> [];
+
+%% Small test case for both set and bag type ets tables.
setbag(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
- ?line Set = ets_new(set,[set]),
- ?line Bag = ets_new(bag,[bag]),
- ?line Key = {foo,bar},
-
+ EtsMem = etsmem(),
+ Set = ets_new(set,[set]),
+ Bag = ets_new(bag,[bag]),
+ Key = {foo,bar},
+
%% insert some value
- ?line ets:insert(Set,{Key,val1}),
- ?line ets:insert(Bag,{Key,val1}),
-
+ ets:insert(Set,{Key,val1}),
+ ets:insert(Bag,{Key,val1}),
+
%% insert new value for same key again
- ?line ets:insert(Set,{Key,val2}),
- ?line ets:insert(Bag,{Key,val2}),
-
+ ets:insert(Set,{Key,val2}),
+ ets:insert(Bag,{Key,val2}),
+
%% check
- ?line [{Key,val2}] = ets:lookup(Set,Key),
- ?line [{Key,val1},{Key,val2}] = ets:lookup(Bag,Key),
+ [{Key,val2}] = ets:lookup(Set,Key),
+ [{Key,val1},{Key,val2}] = ets:lookup(Bag,Key),
true = ets:delete(Set),
true = ets:delete(Bag),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
-badnew(doc) ->
- ["Test case to check proper return values for illegal ets_new() calls."];
-badnew(suite) -> [];
+%% Test case to check proper return values for illegal ets_new() calls.
badnew(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
- ?line {'EXIT',{badarg,_}} = (catch ets_new(12,[])),
- ?line {'EXIT',{badarg,_}} = (catch ets_new({a,b},[])),
- ?line {'EXIT',{badarg,_}} = (catch ets_new(name,[foo])),
- ?line {'EXIT',{badarg,_}} = (catch ets_new(name,{bag})),
- ?line {'EXIT',{badarg,_}} = (catch ets_new(name,bag)),
- ?line verify_etsmem(EtsMem).
-
-verybadnew(doc) ->
- ["Test case to check that a not well formed list does not crash the "
- "emulator. OTP-2314 "];
-verybadnew(suite) -> [];
+ EtsMem = etsmem(),
+ {'EXIT',{badarg,_}} = (catch ets_new(12,[])),
+ {'EXIT',{badarg,_}} = (catch ets_new({a,b},[])),
+ {'EXIT',{badarg,_}} = (catch ets_new(name,[foo])),
+ {'EXIT',{badarg,_}} = (catch ets_new(name,{bag})),
+ {'EXIT',{badarg,_}} = (catch ets_new(name,bag)),
+ verify_etsmem(EtsMem).
+
+%% OTP-2314. Test case to check that a non-proper list does not
+%% crash the emulator.
verybadnew(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
- ?line {'EXIT',{badarg,_}} = (catch ets_new(verybad,[set|protected])),
- ?line verify_etsmem(EtsMem).
+ EtsMem = etsmem(),
+ {'EXIT',{badarg,_}} = (catch ets_new(verybad,[set|protected])),
+ verify_etsmem(EtsMem).
-named(doc) -> ["Small check to see if named tables work."];
-named(suite) -> [];
+%% Small check to see if named tables work.
named(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
- ?line Tab = make_table(foo,
- [named_table],
- [{key,val}]),
- ?line [{key,val}] = ets:lookup(foo,key),
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
-
-keypos2(doc) -> ["Test case to check if specified keypos works."];
-keypos2(suite) -> [];
+ EtsMem = etsmem(),
+ Tab = make_table(foo,
+ [named_table],
+ [{key,val}]),
+ [{key,val}] = ets:lookup(foo,key),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
+
+%% Test case to check if specified keypos works.
keypos2(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
- ?line Tab = make_table(foo,
- [set,{keypos,2}],
- [{val,key}, {val2,key}]),
- ?line [{val2,key}] = ets:lookup(Tab,key),
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
-
-privacy(doc) ->
- ["Privacy check. Check that a named(public/private/protected) table "
- "cannot be read by",
- "the wrong process(es)."];
-privacy(suite) -> [];
+ EtsMem = etsmem(),
+ Tab = make_table(foo,
+ [set,{keypos,2}],
+ [{val,key}, {val2,key}]),
+ [{val2,key}] = ets:lookup(Tab,key),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
+
+%% Privacy check. Check that a named(public/private/protected) table
+%% cannot be read by the wrong process(es).
privacy(Config) when is_list(Config) ->
repeat_for_opts(privacy_do).
privacy_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line process_flag(trap_exit,true),
- ?line Owner = my_spawn_link(?MODULE,privacy_owner,[self(),Opts]),
+ EtsMem = etsmem(),
+ process_flag(trap_exit,true),
+ Owner = my_spawn_link(?MODULE,privacy_owner,[self(),Opts]),
receive
{'EXIT',Owner,Reason} ->
- ?line exit({privacy_test,Reason});
+ exit({privacy_test,Reason});
ok ->
ok
end,
@@ -2967,21 +2820,21 @@ privacy_do(Opts) ->
Owner ! die,
receive {'EXIT',Owner,_} -> ok end,
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
privacy_check(Pub,Prot,Priv) ->
%% check read rights
- ?line [] = ets:lookup(Pub, foo),
- ?line [] = ets:lookup(Prot,foo),
- ?line {'EXIT',{badarg,_}} = (catch ets:lookup(Priv,foo)),
+ [] = ets:lookup(Pub, foo),
+ [] = ets:lookup(Prot,foo),
+ {'EXIT',{badarg,_}} = (catch ets:lookup(Priv,foo)),
%% check write rights
- ?line true = ets:insert(Pub, {1,foo}),
- ?line {'EXIT',{badarg,_}} = (catch ets:insert(Prot,{2,foo})),
- ?line {'EXIT',{badarg,_}} = (catch ets:insert(Priv,{3,foo})),
+ true = ets:insert(Pub, {1,foo}),
+ {'EXIT',{badarg,_}} = (catch ets:insert(Prot,{2,foo})),
+ {'EXIT',{badarg,_}} = (catch ets:insert(Priv,{3,foo})),
%% check that it really wasn't written, either
- ?line [] = ets:lookup(Prot,foo).
+ [] = ets:lookup(Prot,foo).
privacy_owner(Boss, Opts) ->
ets_new(pub, [public,named_table | Opts]),
@@ -2994,7 +2847,7 @@ privacy_owner_loop(Boss) ->
receive
{shift,N,Pub_Prot_Priv} ->
{Pub,Prot,Priv} = rotate_tuple(Pub_Prot_Priv, N),
-
+
ets:setopts(Pub,{protection,public}),
ets:setopts(Prot,{protection,protected}),
ets:setopts(Priv,{protection,private}),
@@ -3014,82 +2867,81 @@ rotate_tuple(Tuple, N) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-empty(doc) ->
- ["Check lookup in an empty table and lookup of a non-existing key"];
-empty(suite) -> [];
+%% Check lookup in an empty table and lookup of a non-existing key.
empty(Config) when is_list(Config) ->
repeat_for_opts(empty_do).
empty_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line Tab = ets_new(foo,Opts),
- ?line [] = ets:lookup(Tab,key),
- ?line true = ets:insert(Tab,{key2,val}),
- ?line [] = ets:lookup(Tab,key),
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
-
-badinsert(doc) ->
- ["Check proper return values for illegal insert operations."];
-badinsert(suite) -> [];
+ EtsMem = etsmem(),
+ Tab = ets_new(foo,Opts),
+ [] = ets:lookup(Tab,key),
+ true = ets:insert(Tab,{key2,val}),
+ [] = ets:lookup(Tab,key),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
+
+%% Check proper return values for illegal insert operations.
badinsert(Config) when is_list(Config) ->
repeat_for_opts(badinsert_do).
badinsert_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line {'EXIT',{badarg,_}} = (catch ets:insert(foo,{key,val})),
-
- ?line Tab = ets_new(foo,Opts),
- ?line {'EXIT',{badarg,_}} = (catch ets:insert(Tab,{})),
+ EtsMem = etsmem(),
+ {'EXIT',{badarg,_}} = (catch ets:insert(foo,{key,val})),
- ?line Tab3 = ets_new(foo,[{keypos,3}| Opts]),
- ?line {'EXIT',{badarg,_}} = (catch ets:insert(Tab3,{a,b})),
+ Tab = ets_new(foo,Opts),
+ {'EXIT',{badarg,_}} = (catch ets:insert(Tab,{})),
+
+ Tab3 = ets_new(foo,[{keypos,3}| Opts]),
+ {'EXIT',{badarg,_}} = (catch ets:insert(Tab3,{a,b})),
- ?line {'EXIT',{badarg,_}} = (catch ets:insert(Tab,[key,val2])),
- ?line true = ets:delete(Tab),
- ?line true = ets:delete(Tab3),
- ?line verify_etsmem(EtsMem).
+ {'EXIT',{badarg,_}} = (catch ets:insert(Tab,[key,val2])),
+ true = ets:delete(Tab),
+ true = ets:delete(Tab3),
+ verify_etsmem(EtsMem).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-time_lookup(doc) -> ["Lookup timing."];
-time_lookup(suite) -> [];
+%% Test lookup timing.
time_lookup(Config) when is_list(Config) ->
%% just for timing, really
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
Values = repeat_for_opts(time_lookup_do),
- ?line verify_etsmem(EtsMem),
- ?line {comment,lists:flatten(io_lib:format(
- "~p ets lookups/s",[Values]))}.
+ verify_etsmem(EtsMem),
+ {comment,lists:flatten(io_lib:format(
+ "~p ets lookups/s",[Values]))}.
time_lookup_do(Opts) ->
Tab = ets_new(foo,Opts),
fill_tab(Tab,foo),
ets:insert(Tab,{{a,key},foo}),
- {Time,_} = ?t:timecall(test_server,do_times,
- [100000,ets,lookup,[Tab,{a,key}]]),
+ N = 100000,
+ {Time,_} = timer:tc(fun() -> time_lookup_many(N, Tab) end),
+ Seconds = Time / 1000000,
true = ets:delete(Tab),
- round(100000 / Time). % lookups/s
+ round(N / Seconds). % lookups/s
+
+time_lookup_many(0, _Tab) ->
+ ok;
+time_lookup_many(N, Tab) ->
+ ets:lookup(Tab, {a,key}),
+ time_lookup_many(N-1, Tab).
-badlookup(doc) ->
- ["Check proper return values from bad lookups in existing/non existing "
- " ets tables"];
-badlookup(suite) -> [];
+%% Check proper return values from bad lookups in existing/non existing
+%% ets tables.
badlookup(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
- ?line {'EXIT',{badarg,_}} = (catch ets:lookup(foo,key)),
- ?line Tab = ets_new(foo,[]),
- ?line ets:delete(Tab),
- ?line {'EXIT',{badarg,_}} = (catch ets:lookup(Tab,key)),
- ?line verify_etsmem(EtsMem).
-
-lookup_order(doc) -> ["Test that lookup returns objects in order of insertion for bag and dbag."];
-lookup_order(suite) -> [];
+ EtsMem = etsmem(),
+ {'EXIT',{badarg,_}} = (catch ets:lookup(foo,key)),
+ Tab = ets_new(foo,[]),
+ ets:delete(Tab),
+ {'EXIT',{badarg,_}} = (catch ets:lookup(Tab,key)),
+ verify_etsmem(EtsMem).
+
+%% Test that lookup returns objects in order of insertion for bag and dbag.
lookup_order(Config) when is_list(Config) ->
EtsMem = etsmem(),
repeat_for_opts(lookup_order_do, [write_concurrency,[bag,duplicate_bag]]),
- ?line verify_etsmem(EtsMem),
+ verify_etsmem(EtsMem),
ok.
lookup_order_do(Opts) ->
@@ -3126,7 +2978,7 @@ lookup_order_2(Opts, Fixed) ->
true = ets:delete(T)
end,
Combos).
-
+
check_insert({T,List0,Key},Val) ->
%%io:format("insert ~p into ~p\n",[Val,List0]),
@@ -3141,7 +2993,7 @@ check_insert({T,List0,Key},Val) ->
check_insert_new({T,List0,Key},Val) ->
%%io:format("insert_new ~p into ~p\n",[Val,List0]),
Ret = ets:insert_new(T,{Key,Val}),
- ?line Ret = (List0 =:= []),
+ Ret = (List0 =:= []),
List1 = case Ret of
true -> [{Key,Val}];
false -> List0
@@ -3160,40 +3012,39 @@ check_check(S={T,List,Key}) ->
case lists:reverse(ets:lookup(T,Key)) of
List -> ok;
ETS -> io:format("check failed:\nETS: ~p\nCHK: ~p\n", [ETS,List]),
- ?t:fail("Invalid return value from ets:lookup")
+ ct:fail("Invalid return value from ets:lookup")
end,
- ?line Items = ets:info(T,size),
- ?line Items = length(List),
+ Items = ets:info(T,size),
+ Items = length(List),
S.
-
+
fill_tab(Tab,Val) ->
- ?line ets:insert(Tab,{key,Val}),
- ?line ets:insert(Tab,{{a,144},Val}),
- ?line ets:insert(Tab,{{a,key2},Val}),
- ?line ets:insert(Tab,{14,Val}),
+ ets:insert(Tab,{key,Val}),
+ ets:insert(Tab,{{a,144},Val}),
+ ets:insert(Tab,{{a,key2},Val}),
+ ets:insert(Tab,{14,Val}),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-lookup_element_mult(doc) -> ["Multiple return elements (OTP-2386)"];
-lookup_element_mult(suite) -> [];
+%% OTP-2386. Multiple return elements.
lookup_element_mult(Config) when is_list(Config) ->
repeat_for_opts(lookup_element_mult_do).
lookup_element_mult_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line T = ets_new(service, [bag, {keypos, 2} | Opts]),
- ?line D = lists:reverse(lem_data()),
- ?line lists:foreach(fun(X) -> ets:insert(T, X) end, D),
- ?line ok = lem_crash_3(T),
- ?line ets:insert(T, {0, "heap_key"}),
- ?line ets:lookup_element(T, "heap_key", 2),
- ?line true = ets:delete(T),
- ?line verify_etsmem(EtsMem).
+ EtsMem = etsmem(),
+ T = ets_new(service, [bag, {keypos, 2} | Opts]),
+ D = lists:reverse(lem_data()),
+ lists:foreach(fun(X) -> ets:insert(T, X) end, D),
+ ok = lem_crash_3(T),
+ ets:insert(T, {0, "heap_key"}),
+ ets:lookup_element(T, "heap_key", 2),
+ true = ets:delete(T),
+ verify_etsmem(EtsMem).
lem_data() ->
[
@@ -3220,69 +3071,64 @@ lem_crash_3(T) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-delete_elem(doc) ->
- ["Check delete of an element inserted in a `filled' table."];
-delete_elem(suite) -> [];
+%% Check delete of an element inserted in a `filled' table.
delete_elem(Config) when is_list(Config) ->
repeat_for_opts(delete_elem_do, [write_concurrency, all_types]).
delete_elem_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line Tab = ets_new(foo,Opts),
- ?line fill_tab(Tab,foo),
- ?line ets:insert(Tab,{{b,key},foo}),
- ?line ets:insert(Tab,{{c,key},foo}),
- ?line true = ets:delete(Tab,{b,key}),
- ?line [] = ets:lookup(Tab,{b,key}),
- ?line [{{c,key},foo}] = ets:lookup(Tab,{c,key}),
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
-
-delete_tab(doc) ->
- ["Check that ets:delete() works and releases the name of the deleted "
- "table."];
-delete_tab(suite) -> [];
+ EtsMem = etsmem(),
+ Tab = ets_new(foo,Opts),
+ fill_tab(Tab,foo),
+ ets:insert(Tab,{{b,key},foo}),
+ ets:insert(Tab,{{c,key},foo}),
+ true = ets:delete(Tab,{b,key}),
+ [] = ets:lookup(Tab,{b,key}),
+ [{{c,key},foo}] = ets:lookup(Tab,{c,key}),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
+
+%% Check that ets:delete() works and releases the name of the
+%% deleted table.
delete_tab(Config) when is_list(Config) ->
repeat_for_opts(delete_tab_do,[write_concurrency,all_types]).
delete_tab_do(Opts) ->
Name = foo,
- ?line EtsMem = etsmem(),
- ?line Name = ets_new(Name, [named_table | Opts]),
- ?line true = ets:delete(foo),
+ EtsMem = etsmem(),
+ Name = ets_new(Name, [named_table | Opts]),
+ true = ets:delete(foo),
%% The name should be available again.
- ?line Name = ets_new(Name, [named_table | Opts]),
- ?line true = ets:delete(Name),
- ?line verify_etsmem(EtsMem).
+ Name = ets_new(Name, [named_table | Opts]),
+ true = ets:delete(Name),
+ verify_etsmem(EtsMem).
-delete_large_tab(doc) ->
- "Check that ets:delete/1 works and that other processes can run.";
+%% Check that ets:delete/1 works and that other processes can run.
delete_large_tab(Config) when is_list(Config) ->
- ?line Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 200000)],
- ?line EtsMem = etsmem(),
+ Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 200000)],
+ EtsMem = etsmem(),
repeat_for_opts(fun(Opts) -> delete_large_tab_do(Opts,Data) end),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
delete_large_tab_do(Opts,Data) ->
- ?line delete_large_tab_1(foo_hash, Opts, Data, false),
- ?line delete_large_tab_1(foo_tree, [ordered_set | Opts], Data, false),
- ?line delete_large_tab_1(foo_hash, Opts, Data, true).
+ delete_large_tab_1(foo_hash, Opts, Data, false),
+ delete_large_tab_1(foo_tree, [ordered_set | Opts], Data, false),
+ delete_large_tab_1(foo_hash, Opts, Data, true).
delete_large_tab_1(Name, Flags, Data, Fix) ->
- ?line Tab = ets_new(Name, Flags),
- ?line ets:insert(Tab, Data),
+ Tab = ets_new(Name, Flags),
+ ets:insert(Tab, Data),
case Fix of
false -> ok;
true ->
- ?line true = ets:safe_fixtable(Tab, true),
- ?line lists:foreach(fun({K,_}) -> ets:delete(Tab, K) end, Data)
+ true = ets:safe_fixtable(Tab, true),
+ lists:foreach(fun({K,_}) -> ets:delete(Tab, K) end, Data)
end,
{priority, Prio} = process_info(self(), priority),
- ?line Deleter = self(),
- ?line [SchedTracer]
+ Deleter = self(),
+ [SchedTracer]
= start_loopers(1,
Prio,
fun (SC) ->
@@ -3302,59 +3148,59 @@ delete_large_tab_1(Name, Flags, Data, Fix) ->
end,
0),
SchedTracerMon = monitor(process, SchedTracer),
- ?line Loopers = start_loopers(erlang:system_info(schedulers),
- Prio,
- fun (_) -> erlang:yield() end,
- ok),
- ?line erlang:yield(),
- ?line 1 = erlang:trace(self(),true,[running,procs,{tracer,SchedTracer}]),
- ?line true = ets:delete(Tab),
+ Loopers = start_loopers(erlang:system_info(schedulers),
+ Prio,
+ fun (_) -> erlang:yield() end,
+ ok),
+ erlang:yield(),
+ 1 = erlang:trace(self(),true,[running,procs,{tracer,SchedTracer}]),
+ true = ets:delete(Tab),
%% The register stuff is just a trace marker
- ?line true = register(delete_large_tab_done_marker, self()),
- ?line true = unregister(delete_large_tab_done_marker),
- ?line undefined = ets:info(Tab),
- ?line ok = stop_loopers(Loopers),
- ?line receive
- {schedule_count, N} ->
- ?line io:format("~s: context switches: ~p", [Name,N]),
- if
- N >= 5 -> ?line ok;
- true -> ?line ?t:fail()
- end
- end,
+ true = register(delete_large_tab_done_marker, self()),
+ true = unregister(delete_large_tab_done_marker),
+ undefined = ets:info(Tab),
+ ok = stop_loopers(Loopers),
+ receive
+ {schedule_count, N} ->
+ io:format("~s: context switches: ~p", [Name,N]),
+ if
+ N >= 5 -> ok;
+ true -> ct:fail(failed)
+ end
+ end,
receive {'DOWN',SchedTracerMon,process,SchedTracer,_} -> ok end,
ok.
-delete_large_named_table(doc) ->
- "Delete a large name table and try to create a new table with the same name in another process.";
+%% Delete a large name table and try to create a new table with
+%% the same name in another process.
delete_large_named_table(Config) when is_list(Config) ->
- ?line Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 200000)],
- ?line EtsMem = etsmem(),
+ Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 200000)],
+ EtsMem = etsmem(),
repeat_for_opts(fun(Opts) -> delete_large_named_table_do(Opts,Data) end),
- ?line verify_etsmem(EtsMem),
+ verify_etsmem(EtsMem),
ok.
delete_large_named_table_do(Opts,Data) ->
- ?line delete_large_named_table_1(foo_hash, [named_table | Opts], Data, false),
- ?line delete_large_named_table_1(foo_tree, [ordered_set,named_table | Opts], Data, false),
- ?line delete_large_named_table_1(foo_hash, [named_table | Opts], Data, true).
+ delete_large_named_table_1(foo_hash, [named_table | Opts], Data, false),
+ delete_large_named_table_1(foo_tree, [ordered_set,named_table | Opts], Data, false),
+ delete_large_named_table_1(foo_hash, [named_table | Opts], Data, true).
delete_large_named_table_1(Name, Flags, Data, Fix) ->
- ?line Tab = ets_new(Name, Flags),
- ?line ets:insert(Tab, Data),
+ Tab = ets_new(Name, Flags),
+ ets:insert(Tab, Data),
case Fix of
false -> ok;
true ->
- ?line true = ets:safe_fixtable(Tab, true),
- ?line lists:foreach(fun({K,_}) -> ets:delete(Tab, K) end, Data)
+ true = ets:safe_fixtable(Tab, true),
+ lists:foreach(fun({K,_}) -> ets:delete(Tab, K) end, Data)
end,
Parent = self(),
{Pid, MRef} = my_spawn_opt(fun() ->
- receive
- ets_new ->
- ets_new(Name, [named_table])
- end
+ receive
+ ets_new ->
+ ets_new(Name, [named_table])
+ end
end,
[link, monitor]),
true = ets:delete(Tab),
@@ -3362,139 +3208,128 @@ delete_large_named_table_1(Name, Flags, Data, Fix) ->
receive {'DOWN',MRef,process,Pid,_} -> ok end,
ok.
-evil_delete(doc) ->
- "Delete a large table, and kill the process during the delete.";
+%% Delete a large table, and kill the process during the delete.
evil_delete(Config) when is_list(Config) ->
- ?line Data = [{I,I*I} || I <- lists:seq(1, 100000)],
+ Data = [{I,I*I} || I <- lists:seq(1, 100000)],
repeat_for_opts(fun(Opts) -> evil_delete_do(Opts,Data) end).
evil_delete_do(Opts,Data) ->
- ?line EtsMem = etsmem(),
- ?line evil_delete_owner(foo_hash, Opts, Data, false),
- ?line verify_etsmem(EtsMem),
- ?line evil_delete_owner(foo_hash, Opts, Data, true),
- ?line verify_etsmem(EtsMem),
- ?line evil_delete_owner(foo_tree, [ordered_set | Opts], Data, false),
- ?line verify_etsmem(EtsMem),
- ?line TabA = evil_delete_not_owner(foo_hash, Opts, Data, false),
- ?line verify_etsmem(EtsMem),
- ?line TabB = evil_delete_not_owner(foo_hash, Opts, Data, true),
- ?line verify_etsmem(EtsMem),
- ?line TabC = evil_delete_not_owner(foo_tree, [ordered_set | Opts], Data, false),
- ?line verify_etsmem(EtsMem),
- ?line lists:foreach(fun(T) -> undefined = ets:info(T) end,
- [TabA,TabB,TabC]).
+ EtsMem = etsmem(),
+ evil_delete_owner(foo_hash, Opts, Data, false),
+ verify_etsmem(EtsMem),
+ evil_delete_owner(foo_hash, Opts, Data, true),
+ verify_etsmem(EtsMem),
+ evil_delete_owner(foo_tree, [ordered_set | Opts], Data, false),
+ verify_etsmem(EtsMem),
+ TabA = evil_delete_not_owner(foo_hash, Opts, Data, false),
+ verify_etsmem(EtsMem),
+ TabB = evil_delete_not_owner(foo_hash, Opts, Data, true),
+ verify_etsmem(EtsMem),
+ TabC = evil_delete_not_owner(foo_tree, [ordered_set | Opts], Data, false),
+ verify_etsmem(EtsMem),
+ lists:foreach(fun(T) -> undefined = ets:info(T) end,
+ [TabA,TabB,TabC]).
evil_delete_not_owner(Name, Flags, Data, Fix) ->
io:format("Not owner: ~p, fix = ~p", [Name,Fix]),
- ?line Tab = ets_new(Name, [public|Flags]),
- ?line ets:insert(Tab, Data),
+ Tab = ets_new(Name, [public|Flags]),
+ ets:insert(Tab, Data),
case Fix of
false -> ok;
true ->
- ?line true = ets:safe_fixtable(Tab, true),
- ?line lists:foreach(fun({K,_}) -> ets:delete(Tab, K) end, Data)
+ true = ets:safe_fixtable(Tab, true),
+ lists:foreach(fun({K,_}) -> ets:delete(Tab, K) end, Data)
end,
- ?line Pid = my_spawn(fun() ->
- P = my_spawn_link(
- fun() ->
- receive kill -> ok end,
- erlang:yield(),
- exit(kill_linked_processes_now)
- end),
- erlang:yield(),
- P ! kill,
- true = ets:delete(Tab)
- end),
- ?line Ref = erlang:monitor(process, Pid),
- ?line receive {'DOWN',Ref,_,_,_} -> ok end,
+ Pid = my_spawn(fun() ->
+ P = my_spawn_link(
+ fun() ->
+ receive kill -> ok end,
+ erlang:yield(),
+ exit(kill_linked_processes_now)
+ end),
+ erlang:yield(),
+ P ! kill,
+ true = ets:delete(Tab)
+ end),
+ Ref = erlang:monitor(process, Pid),
+ receive {'DOWN',Ref,_,_,_} -> ok end,
Tab.
evil_delete_owner(Name, Flags, Data, Fix) ->
- ?line Fun = fun() ->
- ?line Tab = ets_new(Name, [public|Flags]),
- ?line ets:insert(Tab, Data),
- case Fix of
- false -> ok;
- true ->
- ?line true = ets:safe_fixtable(Tab, true),
- ?line lists:foreach(fun({K,_}) ->
- ets:delete(Tab, K)
- end, Data)
- end,
- erlang:yield(),
- my_spawn_link(fun() ->
- erlang:yield(),
- exit(kill_linked_processes_now)
- end),
- true = ets:delete(Tab)
- end,
- ?line Pid = my_spawn(Fun),
- ?line Ref = erlang:monitor(process, Pid),
- ?line receive {'DOWN',Ref,_,_,_} -> ok end.
-
-
-exit_large_table_owner(doc) ->
- [];
-exit_large_table_owner(suite) ->
- [];
+ Fun = fun() ->
+ Tab = ets_new(Name, [public|Flags]),
+ ets:insert(Tab, Data),
+ case Fix of
+ false -> ok;
+ true ->
+ true = ets:safe_fixtable(Tab, true),
+ lists:foreach(fun({K,_}) ->
+ ets:delete(Tab, K)
+ end, Data)
+ end,
+ erlang:yield(),
+ my_spawn_link(fun() ->
+ erlang:yield(),
+ exit(kill_linked_processes_now)
+ end),
+ true = ets:delete(Tab)
+ end,
+ Pid = my_spawn(Fun),
+ Ref = erlang:monitor(process, Pid),
+ receive {'DOWN',Ref,_,_,_} -> ok end.
+
+
exit_large_table_owner(Config) when is_list(Config) ->
- %%?line Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 500000)],
- ?line FEData = fun(Do) -> repeat_while(fun(500000) -> {false,ok};
- (I) -> Do({erlang:phash2(I, 16#ffffff),I}),
- {true, I+1}
- end, 1)
- end,
- ?line EtsMem = etsmem(),
+ %%Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 500000)],
+ FEData = fun(Do) -> repeat_while(fun(500000) -> {false,ok};
+ (I) -> Do({erlang:phash2(I, 16#ffffff),I}),
+ {true, I+1}
+ end, 1)
+ end,
+ EtsMem = etsmem(),
repeat_for_opts({exit_large_table_owner_do,{FEData,Config}}),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
exit_large_table_owner_do(Opts,{FEData,Config}) ->
- ?line verify_rescheduling_exit(Config, FEData, [named_table | Opts], true, 1, 1),
- ?line verify_rescheduling_exit(Config, FEData, Opts, false, 1, 1).
+ verify_rescheduling_exit(Config, FEData, [named_table | Opts], true, 1, 1),
+ verify_rescheduling_exit(Config, FEData, Opts, false, 1, 1).
-exit_many_large_table_owner(doc) -> [];
-exit_many_large_table_owner(suite) -> [];
exit_many_large_table_owner(Config) when is_list(Config) ->
- %%?line Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 500000)],
- ?line FEData = fun(Do) -> repeat_while(fun(500000) -> {false,ok};
- (I) -> Do({erlang:phash2(I, 16#ffffff),I}),
- {true, I+1}
- end, 1)
- end,
- ?line EtsMem = etsmem(),
+ %%Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 500000)],
+ FEData = fun(Do) -> repeat_while(fun(500000) -> {false,ok};
+ (I) -> Do({erlang:phash2(I, 16#ffffff),I}),
+ {true, I+1}
+ end, 1)
+ end,
+ EtsMem = etsmem(),
repeat_for_opts(fun(Opts) -> exit_many_large_table_owner_do(Opts,FEData,Config) end),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
exit_many_large_table_owner_do(Opts,FEData,Config) ->
- ?line verify_rescheduling_exit(Config, FEData, Opts, true, 1, 4),
- ?line verify_rescheduling_exit(Config, FEData, [named_table | Opts], false, 1, 4).
+ verify_rescheduling_exit(Config, FEData, Opts, true, 1, 4),
+ verify_rescheduling_exit(Config, FEData, [named_table | Opts], false, 1, 4).
-exit_many_tables_owner(doc) -> [];
-exit_many_tables_owner(suite) -> [];
exit_many_tables_owner(Config) when is_list(Config) ->
NoData = fun(_Do) -> ok end,
- ?line EtsMem = etsmem(),
- ?line verify_rescheduling_exit(Config, NoData, [named_table], false, 1000, 1),
- ?line verify_rescheduling_exit(Config, NoData, [named_table,{write_concurrency,true}], false, 1000, 1),
- ?line verify_etsmem(EtsMem).
+ EtsMem = etsmem(),
+ verify_rescheduling_exit(Config, NoData, [named_table], false, 1000, 1),
+ verify_rescheduling_exit(Config, NoData, [named_table,{write_concurrency,true}], false, 1000, 1),
+ verify_etsmem(EtsMem).
-exit_many_many_tables_owner(doc) -> [];
-exit_many_many_tables_owner(suite) -> [];
exit_many_many_tables_owner(Config) when is_list(Config) ->
- ?line Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 50)],
- ?line FEData = fun(Do) -> lists:foreach(Do, Data) end,
+ Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 50)],
+ FEData = fun(Do) -> lists:foreach(Do, Data) end,
repeat_for_opts(fun(Opts) -> exit_many_many_tables_owner_do(Opts,FEData,Config) end).
exit_many_many_tables_owner_do(Opts,FEData,Config) ->
- ?line verify_rescheduling_exit(Config, FEData, [named_table | Opts], true, 200, 5),
- ?line verify_rescheduling_exit(Config, FEData, Opts, false, 200, 5),
- ?line wait_for_test_procs(),
- ?line EtsMem = etsmem(),
- ?line verify_rescheduling_exit(Config, FEData, Opts, true, 200, 5),
- ?line verify_rescheduling_exit(Config, FEData, [named_table | Opts], false, 200, 5),
- ?line verify_etsmem(EtsMem).
-
+ verify_rescheduling_exit(Config, FEData, [named_table | Opts], true, 200, 5),
+ verify_rescheduling_exit(Config, FEData, Opts, false, 200, 5),
+ wait_for_test_procs(),
+ EtsMem = etsmem(),
+ verify_rescheduling_exit(Config, FEData, Opts, true, 200, 5),
+ verify_rescheduling_exit(Config, FEData, [named_table | Opts], false, 200, 5),
+ verify_etsmem(EtsMem).
+
count_exit_sched(TP) ->
receive
@@ -3536,11 +3371,11 @@ vre_fix_tables(Tab) ->
ok.
verify_rescheduling_exit(Config, ForEachData, Flags, Fix, NOTabs, NOProcs) ->
- ?line NoFix = 5,
- ?line TestCase = atom_to_list(?config(test_case, Config)),
- ?line Parent = self(),
- ?line KillMe = make_ref(),
- ?line PFun =
+ NoFix = 5,
+ TestCase = atom_to_list(proplists:get_value(test_case, Config)),
+ Parent = self(),
+ KillMe = make_ref(),
+ PFun =
fun () ->
repeat(
fun () ->
@@ -3558,7 +3393,7 @@ verify_rescheduling_exit(Config, ForEachData, Flags, Fix, NOTabs, NOProcs) ->
lists:seq(1,NoFix)),
KeyPos = ets:info(Tab,keypos),
ForEachData(fun(Data) ->
- ets:delete(Tab, element(KeyPos,Data))
+ ets:delete(Tab, element(KeyPos,Data))
end)
end
end,
@@ -3566,89 +3401,82 @@ verify_rescheduling_exit(Config, ForEachData, Flags, Fix, NOTabs, NOProcs) ->
Parent ! {KillMe, self()},
receive after infinity -> ok end
end,
- ?line TPs = lists:map(fun (_) ->
- ?line TP = my_spawn_link(PFun),
- ?line 1 = erlang:trace(TP, true, [exiting]),
- TP
- end,
- lists:seq(1, NOProcs)),
- ?line lists:foreach(fun (TP) ->
- receive {KillMe, TP} -> ok end
- end,
- TPs),
- ?line LPs = start_loopers(erlang:system_info(schedulers),
- normal,
- fun (_) ->
- erlang:yield()
- end,
- ok),
- ?line lists:foreach(fun (TP) ->
- ?line unlink(TP),
- ?line exit(TP, bang)
- end,
- TPs),
- ?line lists:foreach(fun (TP) ->
- ?line XScheds = count_exit_sched(TP),
- ?line ?t:format("~p XScheds=~p~n",
- [TP, XScheds]),
- ?line true = XScheds >= 5
+ TPs = lists:map(fun (_) ->
+ TP = my_spawn_link(PFun),
+ 1 = erlang:trace(TP, true, [exiting]),
+ TP
+ end,
+ lists:seq(1, NOProcs)),
+ lists:foreach(fun (TP) ->
+ receive {KillMe, TP} -> ok end
+ end,
+ TPs),
+ LPs = start_loopers(erlang:system_info(schedulers),
+ normal,
+ fun (_) ->
+ erlang:yield()
end,
- TPs),
- ?line stop_loopers(LPs),
- ?line ok.
+ ok),
+ lists:foreach(fun (TP) ->
+ unlink(TP),
+ exit(TP, bang)
+ end,
+ TPs),
+ lists:foreach(fun (TP) ->
+ XScheds = count_exit_sched(TP),
+ io:format("~p XScheds=~p~n",
+ [TP, XScheds]),
+ true = XScheds >= 5
+ end,
+ TPs),
+ stop_loopers(LPs),
+ ok.
-
-table_leak(doc) ->
- "Make sure that slots for ets tables are cleared properly.";
+
+%% Make sure that slots for ets tables are cleared properly.
table_leak(Config) when is_list(Config) ->
repeat_for_opts(fun(Opts) -> table_leak_1(Opts,20000) end).
table_leak_1(_,0) -> ok;
table_leak_1(Opts,N) ->
- ?line T = ets_new(fooflarf, Opts),
- ?line true = ets:delete(T),
+ T = ets_new(fooflarf, Opts),
+ true = ets:delete(T),
table_leak_1(Opts,N-1).
-baddelete(doc) ->
- ["Check proper return values for illegal delete operations."];
-baddelete(suite) -> [];
+%% Check proper return values for illegal delete operations.
baddelete(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
- ?line {'EXIT',{badarg,_}} = (catch ets:delete(foo)),
- ?line Tab = ets_new(foo,[]),
- ?line true = ets:delete(Tab),
- ?line {'EXIT',{badarg,_}} = (catch ets:delete(Tab)),
- ?line verify_etsmem(EtsMem).
-
-match_delete(doc) ->
- ["Check that match_delete works. Also tests tab2list function."];
-match_delete(suite) -> [];
+ EtsMem = etsmem(),
+ {'EXIT',{badarg,_}} = (catch ets:delete(foo)),
+ Tab = ets_new(foo,[]),
+ true = ets:delete(Tab),
+ {'EXIT',{badarg,_}} = (catch ets:delete(Tab)),
+ verify_etsmem(EtsMem).
+
+%% Check that match_delete works. Also tests tab2list function.
match_delete(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
repeat_for_opts(match_delete_do,[write_concurrency,all_types]),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
match_delete_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line Tab = ets_new(kad,Opts),
- ?line fill_tab(Tab,foo),
- ?line ets:insert(Tab,{{c,key},bar}),
- ?line _ = ets:match_delete(Tab,{'_',foo}),
- ?line [{{c,key},bar}] = ets:tab2list(Tab),
- ?line _ = ets:match_delete(Tab,'_'),
- ?line [] = ets:tab2list(Tab),
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
-
-match_delete3(doc) ->
- ["OTP-3005: check match_delete with constant argument."];
-match_delete3(suite) -> [];
+ EtsMem = etsmem(),
+ Tab = ets_new(kad,Opts),
+ fill_tab(Tab,foo),
+ ets:insert(Tab,{{c,key},bar}),
+ _ = ets:match_delete(Tab,{'_',foo}),
+ [{{c,key},bar}] = ets:tab2list(Tab),
+ _ = ets:match_delete(Tab,'_'),
+ [] = ets:tab2list(Tab),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
+
+%% OTP-3005: check match_delete with constant argument.
match_delete3(Config) when is_list(Config) ->
repeat_for_opts(match_delete3_do).
match_delete3_do(Opts) ->
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
T = make_table(test,
[duplicate_bag | Opts],
[{aa,17},
@@ -3663,41 +3491,40 @@ match_delete3_do(Opts) ->
ets:match_delete(T, {cA,1000}),
[] = ets:match_object(T, {'_', 1000}),
ets:delete(T),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-firstnext(doc) -> ["Tests ets:first/1 & ets:next/2."];
-firstnext(suite) -> [];
+%% Test ets:first/1 & ets:next/2.
firstnext(Config) when is_list(Config) ->
repeat_for_opts(firstnext_do).
firstnext_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line Tab = ets_new(foo,Opts),
- ?line [] = firstnext_collect(Tab,ets:first(Tab),[]),
- ?line fill_tab(Tab,foo),
- ?line Len = length(ets:tab2list(Tab)),
- ?line Len = length(firstnext_collect(Tab,ets:first(Tab),[])),
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
+ EtsMem = etsmem(),
+ Tab = ets_new(foo,Opts),
+ [] = firstnext_collect(Tab,ets:first(Tab),[]),
+ fill_tab(Tab,foo),
+ Len = length(ets:tab2list(Tab)),
+ Len = length(firstnext_collect(Tab,ets:first(Tab),[])),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
firstnext_collect(_Tab,'$end_of_table',List) ->
- ?line List;
+ List;
firstnext_collect(Tab,Key,List) ->
- ?line firstnext_collect(Tab,ets:next(Tab,Key),[Key|List]).
+ firstnext_collect(Tab,ets:next(Tab,Key),[Key|List]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-firstnext_concurrent(doc) -> "Tests ets:first/1 & ets:next/2.";
+%% Tests ets:first/1 & ets:next/2.
firstnext_concurrent(Config) when is_list(Config) ->
register(master, self()),
ets_init(?MODULE, 20),
[dynamic_go() || _ <- lists:seq(1, 2)],
receive
- after 5000 -> ok
+ after 5000 -> ok
end.
ets_init(Tab, N) ->
@@ -3728,98 +3555,94 @@ dyn_lookup(T, K) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-slot(suite) -> [];
slot(Config) when is_list(Config) ->
repeat_for_opts(slot_do).
slot_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line Tab = ets_new(foo,Opts),
- ?line fill_tab(Tab,foo),
- ?line Elts = ets:info(Tab,size),
- ?line Elts = slot_loop(Tab,0,0),
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
+ EtsMem = etsmem(),
+ Tab = ets_new(foo,Opts),
+ fill_tab(Tab,foo),
+ Elts = ets:info(Tab,size),
+ Elts = slot_loop(Tab,0,0),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
slot_loop(Tab,SlotNo,EltsSoFar) ->
- ?line case ets:slot(Tab,SlotNo) of
- '$end_of_table' ->
- ?line {'EXIT',{badarg,_}} =
- (catch ets:slot(Tab,SlotNo+1)),
- ?line EltsSoFar;
- Elts ->
- ?line slot_loop(Tab,SlotNo+1,EltsSoFar+length(Elts))
+ case ets:slot(Tab,SlotNo) of
+ '$end_of_table' ->
+ {'EXIT',{badarg,_}} =
+ (catch ets:slot(Tab,SlotNo+1)),
+ EltsSoFar;
+ Elts ->
+ slot_loop(Tab,SlotNo+1,EltsSoFar+length(Elts))
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-match1(suite) -> [];
match1(Config) when is_list(Config) ->
repeat_for_opts(match1_do).
match1_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line Tab = ets_new(foo,Opts),
- ?line fill_tab(Tab,foo),
- ?line [] = ets:match(Tab,{}),
- ?line ets:insert(Tab,{{one,4},4}),
- ?line ets:insert(Tab,{{one,5},5}),
- ?line ets:insert(Tab,{{two,4},4}),
- ?line ets:insert(Tab,{{two,5},6}),
- ?line case ets:match(Tab,{{one,'_'},'$0'}) of
- [[4],[5]] -> ok;
- [[5],[4]] -> ok
- end,
- ?line case ets:match(Tab,{{two,'$1'},'$0'}) of
- [[4,4],[6,5]] -> ok;
- [[6,5],[4,4]] -> ok
- end,
- ?line case ets:match(Tab,{{two,'$9'},'$4'}) of
- [[4,4],[6,5]] -> ok;
- [[6,5],[4,4]] -> ok
- end,
- ?line case ets:match(Tab,{{two,'$9'},'$22'}) of
- [[4,4],[5,6]] -> ok;
- [[5,6],[4,4]] -> ok
- end,
- ?line [[4]] = ets:match(Tab,{{two,'$0'},'$0'}),
- ?line Len = length(ets:match(Tab,'$0')),
- ?line Len = length(ets:match(Tab,'_')),
- ?line if Len > 4 -> ok end,
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
-
-match2(doc) -> ["Tests match with specified keypos bag table."];
-match2(suite) -> [];
+ EtsMem = etsmem(),
+ Tab = ets_new(foo,Opts),
+ fill_tab(Tab,foo),
+ [] = ets:match(Tab,{}),
+ ets:insert(Tab,{{one,4},4}),
+ ets:insert(Tab,{{one,5},5}),
+ ets:insert(Tab,{{two,4},4}),
+ ets:insert(Tab,{{two,5},6}),
+ case ets:match(Tab,{{one,'_'},'$0'}) of
+ [[4],[5]] -> ok;
+ [[5],[4]] -> ok
+ end,
+ case ets:match(Tab,{{two,'$1'},'$0'}) of
+ [[4,4],[6,5]] -> ok;
+ [[6,5],[4,4]] -> ok
+ end,
+ case ets:match(Tab,{{two,'$9'},'$4'}) of
+ [[4,4],[6,5]] -> ok;
+ [[6,5],[4,4]] -> ok
+ end,
+ case ets:match(Tab,{{two,'$9'},'$22'}) of
+ [[4,4],[5,6]] -> ok;
+ [[5,6],[4,4]] -> ok
+ end,
+ [[4]] = ets:match(Tab,{{two,'$0'},'$0'}),
+ Len = length(ets:match(Tab,'$0')),
+ Len = length(ets:match(Tab,'_')),
+ if Len > 4 -> ok end,
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
+
+%% Test match with specified keypos bag table.
match2(Config) when is_list(Config) ->
repeat_for_opts(match2_do).
match2_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line Tab = make_table(foobar,
- [bag, named_table, {keypos, 2} | Opts],
- [{value1, key1},
- {value2_1, key2},
- {value2_2, key2},
- {value3_1, key3},
- {value3_2, key3},
- {value2_1, key2_wannabe}]),
- ?line case length(ets:match(Tab, '$1')) of
- 6 -> ok;
- _ -> ?t:fail("Length of matched list is wrong.")
- end,
- ?line [[value3_1],[value3_2]] = ets:match(Tab, {'$1', key3}),
- ?line [[key1]] = ets:match(Tab, {value1, '$1'}),
- ?line [[key2_wannabe],[key2]] = ets:match(Tab, {value2_1, '$2'}),
- ?line [] = ets:match(Tab,{'$1',nosuchkey}),
- ?line [] = ets:match(Tab,{'$1',kgY2}), % same hash as key2
- ?line [] = ets:match(Tab,{nosuchvalue,'$1'}),
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
-
-match_object(doc) -> ["Some ets:match_object test."];
-match_object(suite) -> [];
+ EtsMem = etsmem(),
+ Tab = make_table(foobar,
+ [bag, named_table, {keypos, 2} | Opts],
+ [{value1, key1},
+ {value2_1, key2},
+ {value2_2, key2},
+ {value3_1, key3},
+ {value3_2, key3},
+ {value2_1, key2_wannabe}]),
+ case length(ets:match(Tab, '$1')) of
+ 6 -> ok;
+ _ -> ct:fail("Length of matched list is wrong.")
+ end,
+ [[value3_1],[value3_2]] = ets:match(Tab, {'$1', key3}),
+ [[key1]] = ets:match(Tab, {value1, '$1'}),
+ [[key2_wannabe],[key2]] = ets:match(Tab, {value2_1, '$2'}),
+ [] = ets:match(Tab,{'$1',nosuchkey}),
+ [] = ets:match(Tab,{'$1',kgY2}), % same hash as key2
+ [] = ets:match(Tab,{nosuchvalue,'$1'}),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
+
+%% Some ets:match_object tests.
match_object(Config) when is_list(Config) ->
repeat_for_opts(match_object_do).
@@ -3844,25 +3667,25 @@ match_object_do(Opts) ->
case ets:match_object(Tab, {{one, '_'}, '$0'}) of
[{{one,5},5},{{one,4},4}] -> ok;
[{{one,4},4},{{one,5},5}] -> ok;
- _ -> ?t:fail("ets:match_object() returned something funny.")
+ _ -> ct:fail("ets:match_object() returned something funny.")
end,
case ets:match_object(Tab, {{two, '$1'}, '$0'}) of
[{{two,5},6},{{two,4},4}] -> ok;
[{{two,4},4},{{two,5},6}] -> ok;
- _ -> ?t:fail("ets:match_object() returned something funny.")
+ _ -> ct:fail("ets:match_object() returned something funny.")
end,
case ets:match_object(Tab, {{two, '$9'}, '$4'}) of
[{{two,5},6},{{two,4},4}] -> ok;
[{{two,4},4},{{two,5},6}] -> ok;
- _ -> ?t:fail("ets:match_object() returned something funny.")
+ _ -> ct:fail("ets:match_object() returned something funny.")
end,
case ets:match_object(Tab, {{two, '$9'}, '$22'}) of
[{{two,5},6},{{two,4},4}] -> ok;
[{{two,4},4},{{two,5},6}] -> ok;
- _ -> ?t:fail("ets:match_object() returned something funny.")
+ _ -> ct:fail("ets:match_object() returned something funny.")
end,
- % Check that maps are inspected for variables.
+ %% Check that maps are inspected for variables.
[{#{camembert:=cabécou},7}] = ets:match_object(Tab, {#{camembert=>'_'},7}),
[{#{"hi":="hello",#{"wazzup"=>3}:="awesome","1337":="42"},9}] =
@@ -3881,13 +3704,13 @@ match_object_do(Opts) ->
{#{"1337" := "42","hi" := "hello","wazzup" := #{"awesome" := 3}},10}] -> ok;
[{#{"1337" := "42","hi" := "hello","wazzup" := #{"awesome" := 3}},10},
{#{"1337" := "42","hi" := "hello","wazzup" := "awesome"},8}] -> ok;
- _ -> ?t:fail("ets:match_object() returned something funny.")
+ _ -> ct:fail("ets:match_object() returned something funny.")
end,
case ets:match_object(Tab, {#{"hi"=>'_'},'_'}) of
[{#{"1337":="42", "hi":="hello"},_},
{#{"1337":="42", "hi":="hello"},_},
{#{"1337":="42", "hi":="hello"},_}] -> ok;
- _ -> ?t:fail("ets:match_object() returned something funny.")
+ _ -> ct:fail("ets:match_object() returned something funny.")
end,
%% match large maps
@@ -3897,98 +3720,93 @@ match_object_do(Opts) ->
%% only match a part of the map
[{#{1:=1,5:=5,99:=99,100:=100},11},{#{1:="hi",6:="hi",99:="hi"},12}] -> ok;
[{#{1:="hi",2:="hi",59:="hi"},12},{#{1:=1,2:=2,39:=39,100:=100},11}] -> ok;
- _ -> ?t:fail("ets:match_object() returned something funny.")
+ _ -> ct:fail("ets:match_object() returned something funny.")
end,
case ets:match_object(Tab, {maps:from_list([{I,'_'}||I<-Is]),'_'}) of
%% only match a part of the map
[{#{1:=1,5:=5,99:=99,100:=100},11},{#{1:="hi",6:="hi",99:="hi"},12}] -> ok;
[{#{1:="hi",2:="hi",59:="hi"},12},{#{1:=1,2:=2,39:=39,100:=100},11}] -> ok;
- _ -> ?t:fail("ets:match_object() returned something funny.")
+ _ -> ct:fail("ets:match_object() returned something funny.")
end,
{'EXIT',{badarg,_}} = (catch ets:match_object(Tab, {#{'$1'=>'_'},7})),
Mve = maps:from_list([{list_to_atom([$$|integer_to_list(I)]),'_'}||I<-Is]),
{'EXIT',{badarg,_}} = (catch ets:match_object(Tab, {Mve,11})),
- % Check that unsuccessful match returns an empty list.
+ %% Check that unsuccessful match returns an empty list.
[] = ets:match_object(Tab, {{three,'$0'}, '$92'}),
- % Check that '$0' equals '_'.
+ %% Check that '$0' equals '_'.
Len = length(ets:match_object(Tab, '$0')),
Len = length(ets:match_object(Tab, '_')),
if Len > 4 -> ok end,
true = ets:delete(Tab),
verify_etsmem(EtsMem).
-match_object2(suite) -> [];
-match_object2(doc) -> ["Tests that db_match_object does not generate "
- "a `badarg' when resuming a search with no "
- "previous matches."];
+%% Tests that db_match_object does not generate a `badarg' when
+%% resuming a search with no previous matches.
match_object2(Config) when is_list(Config) ->
repeat_for_opts(match_object2_do).
match_object2_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line Tab = ets_new(foo, [bag, {keypos, 2} | Opts]),
- ?line fill_tab2(Tab, 0, 13005), % match_db_object does 1000
- % elements per pass, might
- % change in the future.
- ?line case catch ets:match_object(Tab, {hej, '$1'}) of
- {'EXIT', _} ->
- ets:delete(Tab),
- ?t:fail("match_object EXIT:ed");
- [] ->
- io:format("Nothing matched.");
- List ->
- io:format("Matched:~p~n",[List])
- end,
+ EtsMem = etsmem(),
+ Tab = ets_new(foo, [bag, {keypos, 2} | Opts]),
+ fill_tab2(Tab, 0, 13005), % match_db_object does 1000
+ % elements per pass, might
+ % change in the future.
+ case catch ets:match_object(Tab, {hej, '$1'}) of
+ {'EXIT', _} ->
+ ets:delete(Tab),
+ ct:fail("match_object EXIT:ed");
+ [] ->
+ io:format("Nothing matched.");
+ List ->
+ io:format("Matched:~p~n",[List])
+ end,
ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-tab2list(doc) -> ["Tests tab2list (OTP-3319)"];
-tab2list(suite) -> [];
+%% OTP-3319. Test tab2list.
tab2list(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
- ?line Tab = make_table(foo,
- [ordered_set],
- [{a,b}, {c,b}, {b,b}, {a,c}]),
- ?line [{a,c},{b,b},{c,b}] = ets:tab2list(Tab),
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
-
-misc1(doc) -> ["Simple general small test. ",
- "If this fails, ets is in really bad shape."];
-misc1(suite) -> [];
+ EtsMem = etsmem(),
+ Tab = make_table(foo,
+ [ordered_set],
+ [{a,b}, {c,b}, {b,b}, {a,c}]),
+ [{a,c},{b,b},{c,b}] = ets:tab2list(Tab),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
+
+%% Simple general small test. If this fails, ets is in really bad
+%% shape.
misc1(Config) when is_list(Config) ->
repeat_for_opts(misc1_do).
misc1_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line Tab = ets_new(foo,Opts),
- ?line true = lists:member(Tab,ets:all()),
- ?line ets:delete(Tab),
- ?line false = lists:member(Tab,ets:all()),
- ?line case catch ets:delete(Tab) of
- {'EXIT',_Reason} ->
- ?line verify_etsmem(EtsMem);
- true ->
- ?t:fail("Delete of nonexisting table returned `true'.")
- end,
+ EtsMem = etsmem(),
+ Tab = ets_new(foo,Opts),
+ true = lists:member(Tab,ets:all()),
+ ets:delete(Tab),
+ false = lists:member(Tab,ets:all()),
+ case catch ets:delete(Tab) of
+ {'EXIT',_Reason} ->
+ verify_etsmem(EtsMem);
+ true ->
+ ct:fail("Delete of nonexisting table returned `true'.")
+ end,
ok.
-safe_fixtable(doc) -> ["Check the safe_fixtable function."];
-safe_fixtable(suite) -> [];
+%% Check the safe_fixtable function.
safe_fixtable(Config) when is_list(Config) ->
repeat_for_opts(safe_fixtable_do).
safe_fixtable_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line Tab = ets_new(foo, Opts),
- ?line fill_tab(Tab, foobar),
- ?line true = ets:safe_fixtable(Tab, true),
- ?line receive after 1 -> ok end,
- ?line true = ets:safe_fixtable(Tab, false),
+ EtsMem = etsmem(),
+ Tab = ets_new(foo, Opts),
+ fill_tab(Tab, foobar),
+ true = ets:safe_fixtable(Tab, true),
+ receive after 1 -> ok end,
+ true = ets:safe_fixtable(Tab, false),
false = ets:info(Tab,safe_fixed_monotonic_time),
false = ets:info(Tab,safe_fixed),
SysBefore = erlang:timestamp(),
@@ -4021,90 +3839,86 @@ safe_fixtable_do(Opts) ->
{FixMonTime,[{Self,1}]} = ets:info(Tab,safe_fixed_monotonic_time),
{FixSysTime,[{Self,1}]} = ets:info(Tab,safe_fixed),
%% badarg's
- ?line {'EXIT', {badarg, _}} = (catch ets:safe_fixtable(Tab, foobar)),
- ?line true = ets:info(Tab,fixed),
- ?line true = ets:safe_fixtable(Tab, false),
- ?line false = ets:info(Tab,fixed),
- ?line {'EXIT', {badarg, _}} = (catch ets:safe_fixtable(Tab, foobar)),
- ?line false = ets:info(Tab,fixed),
- ?line ets:delete(Tab),
- ?line case catch ets:safe_fixtable(Tab, true) of
- {'EXIT', _Reason} ->
- ?line verify_etsmem(EtsMem);
- _ ->
- ?t:fail("Fixtable on nonexisting table returned `true'")
- end,
+ {'EXIT', {badarg, _}} = (catch ets:safe_fixtable(Tab, foobar)),
+ true = ets:info(Tab,fixed),
+ true = ets:safe_fixtable(Tab, false),
+ false = ets:info(Tab,fixed),
+ {'EXIT', {badarg, _}} = (catch ets:safe_fixtable(Tab, foobar)),
+ false = ets:info(Tab,fixed),
+ ets:delete(Tab),
+ case catch ets:safe_fixtable(Tab, true) of
+ {'EXIT', _Reason} ->
+ verify_etsmem(EtsMem);
+ _ ->
+ ct:fail("Fixtable on nonexisting table returned `true'")
+ end,
ok.
-info(doc) -> ["Tests ets:info result for required tuples."];
-info(suite) -> [];
+%% Tests ets:info result for required tuples.
info(Config) when is_list(Config) ->
repeat_for_opts(info_do).
info_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line MeMyselfI=self(),
- ?line ThisNode=node(),
- ?line Tab = ets_new(foobar, [{keypos, 2} | Opts]),
+ EtsMem = etsmem(),
+ MeMyselfI=self(),
+ ThisNode=node(),
+ Tab = ets_new(foobar, [{keypos, 2} | Opts]),
%% Note: ets:info/1 used to return a tuple, but from R11B onwards it
%% returns a list.
- ?line Res = ets:info(Tab),
- ?line {value, {memory, _Mem}} = lists:keysearch(memory, 1, Res),
- ?line {value, {owner, MeMyselfI}} = lists:keysearch(owner, 1, Res),
- ?line {value, {name, foobar}} = lists:keysearch(name, 1, Res),
- ?line {value, {size, 0}} = lists:keysearch(size, 1, Res),
- ?line {value, {node, ThisNode}} = lists:keysearch(node, 1, Res),
- ?line {value, {named_table, false}} = lists:keysearch(named_table, 1, Res),
- ?line {value, {type, set}} = lists:keysearch(type, 1, Res),
- ?line {value, {keypos, 2}} = lists:keysearch(keypos, 1, Res),
- ?line {value, {protection, protected}} =
+ Res = ets:info(Tab),
+ {value, {memory, _Mem}} = lists:keysearch(memory, 1, Res),
+ {value, {owner, MeMyselfI}} = lists:keysearch(owner, 1, Res),
+ {value, {name, foobar}} = lists:keysearch(name, 1, Res),
+ {value, {size, 0}} = lists:keysearch(size, 1, Res),
+ {value, {node, ThisNode}} = lists:keysearch(node, 1, Res),
+ {value, {named_table, false}} = lists:keysearch(named_table, 1, Res),
+ {value, {type, set}} = lists:keysearch(type, 1, Res),
+ {value, {keypos, 2}} = lists:keysearch(keypos, 1, Res),
+ {value, {protection, protected}} =
lists:keysearch(protection, 1, Res),
- ?line true = ets:delete(Tab),
- ?line undefined = ets:info(non_existing_table_xxyy),
- ?line undefined = ets:info(non_existing_table_xxyy,type),
- ?line undefined = ets:info(non_existing_table_xxyy,node),
- ?line undefined = ets:info(non_existing_table_xxyy,named_table),
- ?line undefined = ets:info(non_existing_table_xxyy,safe_fixed_monotonic_time),
- ?line undefined = ets:info(non_existing_table_xxyy,safe_fixed),
- ?line verify_etsmem(EtsMem).
-
-dups(doc) -> ["Test various duplicate_bags stuff"];
-dups(suite) -> [];
+ true = ets:delete(Tab),
+ undefined = ets:info(non_existing_table_xxyy),
+ undefined = ets:info(non_existing_table_xxyy,type),
+ undefined = ets:info(non_existing_table_xxyy,node),
+ undefined = ets:info(non_existing_table_xxyy,named_table),
+ undefined = ets:info(non_existing_table_xxyy,safe_fixed_monotonic_time),
+ undefined = ets:info(non_existing_table_xxyy,safe_fixed),
+ verify_etsmem(EtsMem).
+
+%% Test various duplicate_bags stuff.
dups(Config) when is_list(Config) ->
repeat_for_opts(dups_do).
dups_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line T = make_table(funky,
- [duplicate_bag | Opts],
- [{1, 2}, {1, 2}]),
- ?line 2 = length(ets:tab2list(T)),
- ?line ets:delete(T, 1),
- ?line [] = ets:lookup(T, 1),
-
- ?line ets:insert(T, {1, 2, 2}),
- ?line ets:insert(T, {1, 2, 4}),
- ?line ets:insert(T, {1, 2, 2}),
- ?line ets:insert(T, {1, 2, 2}),
- ?line ets:insert(T, {1, 2, 4}),
-
- ?line 5 = length(ets:tab2list(T)),
-
- ?line 5 = length(ets:match(T, {'$1', 2, '$2'})),
- ?line 3 = length(ets:match(T, {'_', '$1', '$1'})),
- ?line ets:match_delete(T, {'_', '$1', '$1'}),
- ?line 0 = length(ets:match(T, {'_', '$1', '$1'})),
- ?line ets:delete(T),
- ?line verify_etsmem(EtsMem).
+ EtsMem = etsmem(),
+ T = make_table(funky,
+ [duplicate_bag | Opts],
+ [{1, 2}, {1, 2}]),
+ 2 = length(ets:tab2list(T)),
+ ets:delete(T, 1),
+ [] = ets:lookup(T, 1),
+
+ ets:insert(T, {1, 2, 2}),
+ ets:insert(T, {1, 2, 4}),
+ ets:insert(T, {1, 2, 2}),
+ ets:insert(T, {1, 2, 2}),
+ ets:insert(T, {1, 2, 4}),
+
+ 5 = length(ets:tab2list(T)),
+
+ 5 = length(ets:match(T, {'$1', 2, '$2'})),
+ 3 = length(ets:match(T, {'_', '$1', '$1'})),
+ ets:match_delete(T, {'_', '$1', '$1'}),
+ 0 = length(ets:match(T, {'_', '$1', '$1'})),
+ ets:delete(T),
+ verify_etsmem(EtsMem).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-tab2file(doc) -> ["Check the ets:tab2file function on an empty "
- "ets table."];
-tab2file(suite) -> [];
+%% Test the ets:tab2file function on an empty ets table.
tab2file(Config) when is_list(Config) ->
- ?line FName = filename:join([?config(priv_dir, Config),"tab2file_case"]),
+ FName = filename:join([proplists:get_value(priv_dir, Config),"tab2file_case"]),
tab2file_do(FName, []),
tab2file_do(FName, [{sync,true}]),
tab2file_do(FName, [{sync,false}]),
@@ -4114,62 +3928,60 @@ tab2file(Config) when is_list(Config) ->
tab2file_do(FName, Opts) ->
%% Write an empty ets table to a file, read back and check properties.
- ?line Tab = ets_new(ets_SUITE_foo_tab, [named_table, set, public,
- {keypos, 2},
- compressed,
- {write_concurrency,true},
- {read_concurrency,true}]),
+ Tab = ets_new(ets_SUITE_foo_tab, [named_table, set, public,
+ {keypos, 2},
+ compressed,
+ {write_concurrency,true},
+ {read_concurrency,true}]),
catch file:delete(FName),
Res = ets:tab2file(Tab, FName, Opts),
true = ets:delete(Tab),
ok = Res,
- %
- ?line EtsMem = etsmem(),
- ?line {ok, Tab2} = ets:file2tab(FName),
+ %%
+ EtsMem = etsmem(),
+ {ok, Tab2} = ets:file2tab(FName),
public = ets:info(Tab2, protection),
- ?line true = ets:info(Tab2, named_table),
- ?line 2 = ets:info(Tab2, keypos),
- ?line set = ets:info(Tab2, type),
+ true = ets:info(Tab2, named_table),
+ 2 = ets:info(Tab2, keypos),
+ set = ets:info(Tab2, type),
true = ets:info(Tab2, compressed),
Smp = erlang:system_info(smp_support),
Smp = ets:info(Tab2, read_concurrency),
Smp = ets:info(Tab2, write_concurrency),
- ?line true = ets:delete(Tab2),
- ?line verify_etsmem(EtsMem).
+ true = ets:delete(Tab2),
+ verify_etsmem(EtsMem).
-
-tab2file2(doc) -> ["Check the ets:tab2file function on a ",
- "filled set/bag type ets table."];
-tab2file2(suite) -> [];
+
+%% Check the ets:tab2file function on a filled set/bag type ets table.
tab2file2(Config) when is_list(Config) ->
repeat_for_opts({tab2file2_do,Config}, [[set,bag],compressed]).
tab2file2_do(Opts, Config) ->
- ?line EtsMem = etsmem(),
- ?line Tab = ets_new(ets_SUITE_foo_tab, [named_table, private,
- {keypos, 2} | Opts]),
- ?line FName = filename:join([?config(priv_dir, Config),"tab2file2_case"]),
- ?line ok = fill_tab2(Tab, 0, 10000), % Fill up the table (grucho mucho!)
- ?line Len = length(ets:tab2list(Tab)),
- ?line Mem = ets:info(Tab, memory),
- ?line Type = ets:info(Tab, type),
+ EtsMem = etsmem(),
+ Tab = ets_new(ets_SUITE_foo_tab, [named_table, private,
+ {keypos, 2} | Opts]),
+ FName = filename:join([proplists:get_value(priv_dir, Config),"tab2file2_case"]),
+ ok = fill_tab2(Tab, 0, 10000), % Fill up the table (grucho mucho!)
+ Len = length(ets:tab2list(Tab)),
+ Mem = ets:info(Tab, memory),
+ Type = ets:info(Tab, type),
%%io:format("org tab: ~p\n",[ets:info(Tab)]),
- ?line ok = ets:tab2file(Tab, FName),
- ?line true = ets:delete(Tab),
+ ok = ets:tab2file(Tab, FName),
+ true = ets:delete(Tab),
- ?line EtsMem4 = etsmem(),
+ EtsMem4 = etsmem(),
- ?line {ok, Tab2} = ets:file2tab(FName),
+ {ok, Tab2} = ets:file2tab(FName),
%%io:format("loaded tab: ~p\n",[ets:info(Tab2)]),
- ?line private = ets:info(Tab2, protection),
- ?line true = ets:info(Tab2, named_table),
- ?line 2 = ets:info(Tab2, keypos),
- ?line Type = ets:info(Tab2, type),
- ?line Len = length(ets:tab2list(Tab2)),
- ?line Mem = ets:info(Tab2, memory),
- ?line true = ets:delete(Tab2),
+ private = ets:info(Tab2, protection),
+ true = ets:info(Tab2, named_table),
+ 2 = ets:info(Tab2, keypos),
+ Type = ets:info(Tab2, type),
+ Len = length(ets:tab2list(Tab2)),
+ Mem = ets:info(Tab2, memory),
+ true = ets:delete(Tab2),
io:format("Between = ~p\n", [EtsMem4]),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
-define(test_list, [8,5,4,1,58,125,255, 250, 245, 240, 235,
230, Num rem 255, 255, 125, 130, 135, 140, 145,
@@ -4184,33 +3996,30 @@ tab2file2_do(Opts, Config) ->
fill_tab2(_Tab, _Val, 0) ->
ok;
fill_tab2(Tab, Val, Num) ->
- ?line Item =
+ Item =
case Num rem 10 of
0 -> "String";
- 1 -> ?line ?test_atom;
- 2 -> ?line ?test_tuple;
- 3 -> ?line ?test_integer;
- 4 -> ?line ?test_float;
- 5 -> ?line list_to_binary(?test_list); %Heap binary
- 6 -> ?line list_to_binary(?big_test_list); %Refc binary
- 7 -> ?line make_sub_binary(?test_list, Num); %Sub binary
- 8 -> ?line ?test_list;
- 9 -> ?line fun(X) -> {Tab,Val,X*Num} end
+ 1 -> ?test_atom;
+ 2 -> ?test_tuple;
+ 3 -> ?test_integer;
+ 4 -> ?test_float;
+ 5 -> list_to_binary(?test_list); %Heap binary
+ 6 -> list_to_binary(?big_test_list); %Refc binary
+ 7 -> make_sub_binary(?test_list, Num); %Sub binary
+ 8 -> ?test_list;
+ 9 -> fun(X) -> {Tab,Val,X*Num} end
end,
- ?line true=ets:insert(Tab, {Item, Val}),
- ?line fill_tab2(Tab, Val+1, Num-1),
+ true=ets:insert(Tab, {Item, Val}),
+ fill_tab2(Tab, Val+1, Num-1),
ok.
-tabfile_ext1(suite) ->
- [];
-tabfile_ext1(doc) ->
- ["Tests verification of tables with object count extended_info"];
+%% Test verification of tables with object count extended_info.
tabfile_ext1(Config) when is_list(Config) ->
repeat_for_opts(fun(Opts) -> tabfile_ext1_do(Opts, Config) end).
tabfile_ext1_do(Opts,Config) ->
- ?line FName = filename:join([?config(priv_dir, Config),"nisse.dat"]),
- ?line FName2 = filename:join([?config(priv_dir, Config),"countflip.dat"]),
+ FName = filename:join([proplists:get_value(priv_dir, Config),"nisse.dat"]),
+ FName2 = filename:join([proplists:get_value(priv_dir, Config),"countflip.dat"]),
L = lists:seq(1,10),
T = ets_new(x,Opts),
Name = make_ref(),
@@ -4241,16 +4050,14 @@ tabfile_ext1_do(Opts,Config) ->
file:delete(FName2),
ok.
-tabfile_ext2(suite) ->
- [];
-tabfile_ext2(doc) ->
- ["Tests verification of tables with md5sum extended_info"];
+
+%% Test verification of tables with md5sum extended_info.
tabfile_ext2(Config) when is_list(Config) ->
repeat_for_opts(fun(Opts) -> tabfile_ext2_do(Opts,Config) end).
tabfile_ext2_do(Opts,Config) ->
- ?line FName = filename:join([?config(priv_dir, Config),"olle.dat"]),
- ?line FName2 = filename:join([?config(priv_dir, Config),"bitflip.dat"]),
+ FName = filename:join([proplists:get_value(priv_dir, Config),"olle.dat"]),
+ FName2 = filename:join([proplists:get_value(priv_dir, Config),"bitflip.dat"]),
L = lists:seq(1,10),
T = ets_new(x,Opts),
Name = make_ref(),
@@ -4281,13 +4088,10 @@ tabfile_ext2_do(Opts,Config) ->
file:delete(FName2),
ok.
-tabfile_ext3(suite) ->
- [];
-tabfile_ext3(doc) ->
- ["Tests verification of (named) tables without extended info"];
+%% Test verification of (named) tables without extended info.
tabfile_ext3(Config) when is_list(Config) ->
- ?line FName = filename:join([?config(priv_dir, Config),"namn.dat"]),
- ?line FName2 = filename:join([?config(priv_dir, Config),"ncountflip.dat"]),
+ FName = filename:join([proplists:get_value(priv_dir, Config),"namn.dat"]),
+ FName2 = filename:join([proplists:get_value(priv_dir, Config),"ncountflip.dat"]),
L = lists:seq(1,10),
Name = make_ref(),
?MODULE = ets_new(?MODULE,[named_table]),
@@ -4315,12 +4119,9 @@ tabfile_ext3(Config) when is_list(Config) ->
file:delete(FName2),
ok.
-tabfile_ext4(suite) ->
- [];
-tabfile_ext4(doc) ->
- ["Tests verification of large table with md5 sum"];
+%% Tests verification of large table with md5 sum.
tabfile_ext4(Config) when is_list(Config) ->
- ?line FName = filename:join([?config(priv_dir, Config),"bauta.dat"]),
+ FName = filename:join([proplists:get_value(priv_dir, Config),"bauta.dat"]),
LL = lists:seq(1,10000),
TL = ets_new(x,[]),
Name2 = make_ref(),
@@ -4357,12 +4158,9 @@ tabfile_ext4(Config) when is_list(Config) ->
file:delete(FName),
ok.
-badfile(suite) ->
- [];
-badfile(doc) ->
- ["Tests that no disk_log is left open when file has been corrupted"];
+%% Test that no disk_log is left open when file has been corrupted.
badfile(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir,Config),
+ PrivDir = proplists:get_value(priv_dir,Config),
File = filename:join(PrivDir, "badfile"),
_ = file:delete(File),
T = ets:new(table, []),
@@ -4418,32 +4216,31 @@ make_sub_binary(List, Num) when is_list(List) ->
%% Lookup stuff like crazy...
-heavy_lookup(doc) -> ["Performs multiple lookups for every key ",
- "in a large table."];
-heavy_lookup(suite) -> [];
+
+%% Perform multiple lookups for every key in a large table.
heavy_lookup(Config) when is_list(Config) ->
repeat_for_opts(heavy_lookup_do).
heavy_lookup_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line Tab = ets_new(foobar_table, [set, protected, {keypos, 2} | Opts]),
- ?line ok = fill_tab2(Tab, 0, 7000),
- ?line ?t:do_times(50, ?MODULE, do_lookup, [Tab, 6999]),
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
+ EtsMem = etsmem(),
+ Tab = ets_new(foobar_table, [set, protected, {keypos, 2} | Opts]),
+ ok = fill_tab2(Tab, 0, 7000),
+ _ = [do_lookup(Tab, 6999) || _ <- lists:seq(1, 50)],
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
do_lookup(_Tab, 0) -> ok;
do_lookup(Tab, N) ->
case ets:lookup(Tab, N) of
- [] -> ?t:format("Set #~p was reported as empty. Not valid.",
- [N]),
- exit('Invalid lookup');
- _ -> do_lookup(Tab, N-1)
+ [] ->
+ io:format("Set #~p was reported as empty. Not valid.",
+ [N]),
+ exit('Invalid lookup');
+ _ ->
+ do_lookup(Tab, N-1)
end.
-heavy_lookup_element(doc) -> ["Performs multiple lookups for ",
- "every element in a large table."];
-heavy_lookup_element(suite) -> [];
+%% Perform multiple lookups for every element in a large table.
heavy_lookup_element(Config) when is_list(Config) ->
repeat_for_opts(heavy_lookup_element_do).
@@ -4451,22 +4248,22 @@ heavy_lookup_element_do(Opts) ->
EtsMem = etsmem(),
Tab = ets_new(foobar_table, [set, protected, {keypos, 2} | Opts]),
ok = fill_tab2(Tab, 0, 7000),
- % lookup ALL elements 50 times
- ?t:do_times(50, ?MODULE, do_lookup_element, [Tab, 6999, 1]),
+ %% lookup ALL elements 50 times
+ _ = [do_lookup_element(Tab, 6999, 1) || _ <- lists:seq(1, 50)],
true = ets:delete(Tab),
verify_etsmem(EtsMem).
do_lookup_element(_Tab, 0, _) -> ok;
do_lookup_element(Tab, N, M) ->
- ?line case catch ets:lookup_element(Tab, N, M) of
- {'EXIT', {badarg, _}} ->
- case M of
- 1 -> ?t:fail("Set #~p reported as empty. Not valid.",
- [N]),
- exit('Invalid lookup_element');
- _ -> ?line do_lookup_element(Tab, N-1, 1)
- end;
- _ -> ?line do_lookup_element(Tab, N, M+1)
+ case catch ets:lookup_element(Tab, N, M) of
+ {'EXIT', {badarg, _}} ->
+ case M of
+ 1 -> ct:fail("Set #~p reported as empty. Not valid.",
+ [N]),
+ exit('Invalid lookup_element');
+ _ -> do_lookup_element(Tab, N-1, 1)
+ end;
+ _ -> do_lookup_element(Tab, N, M+1)
end.
@@ -4474,28 +4271,28 @@ heavy_concurrent(Config) when is_list(Config) ->
repeat_for_opts(do_heavy_concurrent).
do_heavy_concurrent(Opts) ->
- ?line Size = 10000,
- ?line EtsMem = etsmem(),
- ?line Tab = ets_new(blupp, [set, public, {keypos, 2} | Opts]),
- ?line ok = fill_tab2(Tab, 0, Size),
- ?line Procs = lists:map(
- fun (N) ->
- my_spawn_link(
- fun () ->
- do_heavy_concurrent_proc(Tab, Size, N)
- end)
- end,
- lists:seq(1, 500)),
- ?line lists:foreach(fun (P) ->
- M = erlang:monitor(process, P),
- receive
- {'DOWN', M, process, P, _} ->
- ok
- end
- end,
- Procs),
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
+ Size = 10000,
+ EtsMem = etsmem(),
+ Tab = ets_new(blupp, [set, public, {keypos, 2} | Opts]),
+ ok = fill_tab2(Tab, 0, Size),
+ Procs = lists:map(
+ fun (N) ->
+ my_spawn_link(
+ fun () ->
+ do_heavy_concurrent_proc(Tab, Size, N)
+ end)
+ end,
+ lists:seq(1, 500)),
+ lists:foreach(fun (P) ->
+ M = erlang:monitor(process, P),
+ receive
+ {'DOWN', M, process, P, _} ->
+ ok
+ end
+ end,
+ Procs),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
do_heavy_concurrent_proc(_Tab, 0, _Offs) ->
done;
@@ -4509,96 +4306,78 @@ do_heavy_concurrent_proc(Tab, N, Offs) ->
do_heavy_concurrent_proc(Tab, N-1, Offs).
-fold_empty(doc) ->
- [];
-fold_empty(suite) -> [];
fold_empty(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
- ?line Tab = make_table(a, [], []),
- ?line [] = ets:foldl(fun(_X) -> exit(hej) end, [], Tab),
- ?line [] = ets:foldr(fun(_X) -> exit(hej) end, [], Tab),
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
-
-foldl(doc) ->
- [];
-foldl(suite) -> [];
+ EtsMem = etsmem(),
+ Tab = make_table(a, [], []),
+ [] = ets:foldl(fun(_X) -> exit(hej) end, [], Tab),
+ [] = ets:foldr(fun(_X) -> exit(hej) end, [], Tab),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
+
foldl(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
- ?line L = [{a,1}, {c,3}, {b,2}],
- ?line LS = lists:sort(L),
- ?line Tab = make_table(a, [bag], L),
- ?line LS = lists:sort(ets:foldl(fun(E,A) -> [E|A] end, [], Tab)),
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
-
-foldr(doc) ->
- [];
-foldr(suite) -> [];
+ EtsMem = etsmem(),
+ L = [{a,1}, {c,3}, {b,2}],
+ LS = lists:sort(L),
+ Tab = make_table(a, [bag], L),
+ LS = lists:sort(ets:foldl(fun(E,A) -> [E|A] end, [], Tab)),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
+
foldr(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
- ?line L = [{a,1}, {c,3}, {b,2}],
- ?line LS = lists:sort(L),
- ?line Tab = make_table(a, [bag], L),
- ?line LS = lists:sort(ets:foldr(fun(E,A) -> [E|A] end, [], Tab)),
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
-
-foldl_ordered(doc) ->
- [];
-foldl_ordered(suite) -> [];
+ EtsMem = etsmem(),
+ L = [{a,1}, {c,3}, {b,2}],
+ LS = lists:sort(L),
+ Tab = make_table(a, [bag], L),
+ LS = lists:sort(ets:foldr(fun(E,A) -> [E|A] end, [], Tab)),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
+
foldl_ordered(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
- ?line L = [{a,1}, {c,3}, {b,2}],
- ?line LS = lists:sort(L),
- ?line Tab = make_table(a, [ordered_set], L),
- ?line LS = lists:reverse(ets:foldl(fun(E,A) -> [E|A] end, [], Tab)),
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
-
-foldr_ordered(doc) ->
- [];
-foldr_ordered(suite) -> [];
+ EtsMem = etsmem(),
+ L = [{a,1}, {c,3}, {b,2}],
+ LS = lists:sort(L),
+ Tab = make_table(a, [ordered_set], L),
+ LS = lists:reverse(ets:foldl(fun(E,A) -> [E|A] end, [], Tab)),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
+
foldr_ordered(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
- ?line L = [{a,1}, {c,3}, {b,2}],
- ?line LS = lists:sort(L),
- ?line Tab = make_table(a, [ordered_set], L),
- ?line LS = ets:foldr(fun(E,A) -> [E|A] end, [], Tab),
- ?line true = ets:delete(Tab),
- ?line verify_etsmem(EtsMem).
-
-member(suite) ->
- [];
-member(doc) ->
- ["Tests ets:member BIF"];
+ EtsMem = etsmem(),
+ L = [{a,1}, {c,3}, {b,2}],
+ LS = lists:sort(L),
+ Tab = make_table(a, [ordered_set], L),
+ LS = ets:foldr(fun(E,A) -> [E|A] end, [], Tab),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem).
+
+%% Test ets:member BIF.
member(Config) when is_list(Config) ->
repeat_for_opts(member_do, [write_concurrency, all_types]).
member_do(Opts) ->
- ?line EtsMem = etsmem(),
- ?line T = ets_new(xxx, Opts),
- ?line false = ets:member(T,hej),
- ?line E = fun(0,_F)->ok;
- (N,F) ->
- ?line ets:insert(T,{N,N rem 10}),
- F(N-1,F)
- end,
- ?line E(10000,E),
- ?line false = ets:member(T,hej),
- ?line true = ets:member(T,1),
- ?line false = ets:member(T,20000),
- ?line ets:delete(T,5),
- ?line false = ets:member(T,5),
- ?line ets:safe_fixtable(T,true),
- ?line ets:delete(T,6),
- ?line false = ets:member(T,6),
- ?line ets:safe_fixtable(T,false),
- ?line false = ets:member(T,6),
- ?line ets:delete(T),
- ?line {'EXIT',{badarg,_}} = (catch ets:member(finnsinte, 23)),
- ?line {'EXIT',{badarg,_}} = (catch ets:member(T, 23)),
- ?line verify_etsmem(EtsMem).
+ EtsMem = etsmem(),
+ T = ets_new(xxx, Opts),
+ false = ets:member(T,hej),
+ E = fun(0,_F)->ok;
+ (N,F) ->
+ ets:insert(T,{N,N rem 10}),
+ F(N-1,F)
+ end,
+ E(10000,E),
+ false = ets:member(T,hej),
+ true = ets:member(T,1),
+ false = ets:member(T,20000),
+ ets:delete(T,5),
+ false = ets:member(T,5),
+ ets:safe_fixtable(T,true),
+ ets:delete(T,6),
+ false = ets:member(T,6),
+ ets:safe_fixtable(T,false),
+ false = ets:member(T,6),
+ ets:delete(T),
+ {'EXIT',{badarg,_}} = (catch ets:member(finnsinte, 23)),
+ {'EXIT',{badarg,_}} = (catch ets:member(T, 23)),
+ verify_etsmem(EtsMem).
build_table(L1,L2,Num) ->
@@ -4684,11 +4463,11 @@ create_random_string(0) ->
[];
create_random_string(OfLength) ->
- C = case random:uniform(2) of
- 1 ->
- (random:uniform($Z - $A + 1) - 1) + $A;
- _ ->
- (random:uniform($z - $a + 1) - 1) + $a
+ C = case rand:uniform(2) of
+ 1 ->
+ (rand:uniform($Z - $A + 1) - 1) + $A;
+ _ ->
+ (rand:uniform($z - $a + 1) - 1) + $a
end,
[C | create_random_string(OfLength - 1)].
@@ -4699,23 +4478,23 @@ create_random_tuple(OfLength) ->
end,create_random_string(OfLength))).
create_partly_bound_tuple(OfLength) ->
- case random:uniform(2) of
+ case rand:uniform(2) of
1 ->
- create_partly_bound_tuple1(OfLength);
+ create_partly_bound_tuple1(OfLength);
_ ->
- create_partly_bound_tuple3(OfLength)
+ create_partly_bound_tuple3(OfLength)
end.
create_partly_bound_tuple1(OfLength) ->
T0 = create_random_tuple(OfLength),
- I = random:uniform(OfLength),
+ I = rand:uniform(OfLength),
setelement(I,T0,'$1').
set_n_random_elements(T0,0,_,_) ->
T0;
set_n_random_elements(T0,N,OfLength,GenFun) ->
- I = random:uniform(OfLength),
+ I = rand:uniform(OfLength),
What = GenFun(I),
case element(I,T0) of
What ->
@@ -4729,12 +4508,12 @@ make_dollar_atom(I) ->
list_to_atom([$$] ++ integer_to_list(I)).
create_partly_bound_tuple2(OfLength) ->
T0 = create_random_tuple(OfLength),
- I = random:uniform(OfLength - 1),
+ I = rand:uniform(OfLength - 1),
set_n_random_elements(T0,I,OfLength,fun make_dollar_atom/1).
create_partly_bound_tuple3(OfLength) ->
T0 = create_random_tuple(OfLength),
- I = random:uniform(OfLength - 1),
+ I = rand:uniform(OfLength - 1),
set_n_random_elements(T0,I,OfLength,fun(_) -> '_' end).
do_n_times(_,0) ->
@@ -4778,7 +4557,7 @@ xfilltabint(Tab,N) ->
_ ->
filltabint(Tab,N)
end.
-
+
filltabstr(Tab,N) ->
filltabstr(Tab,0,N).
@@ -4949,7 +4728,7 @@ successive_delete(Table,From,To,Type,TType) ->
end,
case TType of
X when X == bag; X == duplicate_bag ->
- %erlang:display(From),
+ %%erlang:display(From),
case From rem 2 of
0 ->
2 = ets:select_delete(Table,MS);
@@ -4968,19 +4747,19 @@ successive_delete(Table,From,To,Type,TType) ->
successive_delete(Table, Next, To, Type,TType).
gen_dets_filename(Config,N) ->
- filename:join(?config(priv_dir,Config),
+ filename:join(proplists:get_value(priv_dir,Config),
"testdets_" ++ integer_to_list(N) ++ ".dets").
otp_6842_select_1000(Config) when is_list(Config) ->
- ?line Tab = ets_new(xxx,[ordered_set]),
- ?line [ets:insert(Tab,{X,X}) || X <- lists:seq(1,10000)],
- ?line AllTrue = lists:duplicate(10,true),
- ?line AllTrue =
+ Tab = ets_new(xxx,[ordered_set]),
+ [ets:insert(Tab,{X,X}) || X <- lists:seq(1,10000)],
+ AllTrue = lists:duplicate(10,true),
+ AllTrue =
[ length(
element(1,
ets:select(Tab,[{'_',[],['$_']}],X*1000))) =:=
- X*1000 || X <- lists:seq(1,10) ],
- ?line Sequences = [[1000,1000,1000,1000,1000,1000,1000,1000,1000,1000],
+ X*1000 || X <- lists:seq(1,10) ],
+ Sequences = [[1000,1000,1000,1000,1000,1000,1000,1000,1000,1000],
[2000,2000,2000,2000,2000],
[3000,3000,3000,1000],
[4000,4000,2000],
@@ -4990,9 +4769,9 @@ otp_6842_select_1000(Config) when is_list(Config) ->
[8000,2000],
[9000,1000],
[10000]],
- ?line AllTrue = [ check_seq(Tab, ets:select(Tab,[{'_',[],['$_']}],hd(L)),L) ||
+ AllTrue = [ check_seq(Tab, ets:select(Tab,[{'_',[],['$_']}],hd(L)),L) ||
L <- Sequences ],
- ?line ets:delete(Tab),
+ ets:delete(Tab),
ok.
check_seq(_,'$end_of_table',[]) ->
@@ -5026,7 +4805,7 @@ w(_,0, _) -> ok;
w(T,N, Id) ->
ets:insert(T, {N, Id}),
w(T,N-1,Id).
-
+
verify(T, Ids) ->
List = my_tab_to_list(T),
Errors = lists:filter(fun(Bucket) ->
@@ -5037,7 +4816,7 @@ verify(T, Ids) ->
ok;
_ ->
io:format("Failed:\n~p\n", [Errors]),
- ?t:fail()
+ ct:fail(failed)
end.
verify2([{_N,Id}|RL], [Id|R]) ->
@@ -5046,8 +4825,7 @@ verify2([],[]) -> false;
verify2(_Err, _) ->
true.
-otp_7665(doc) -> ["delete_object followed by delete on fixed bag failed to delete objects."];
-otp_7665(suite) -> [];
+%% delete_object followed by delete on fixed bag failed to delete objects.
otp_7665(Config) when is_list(Config) ->
repeat_for_opts(otp_7665_do).
@@ -5057,30 +4835,30 @@ otp_7665_do(Opts) ->
Max = 10,
lists:foreach(fun(N)-> otp_7665_act(Tab,Min,Max,N) end,
lists:seq(Min,Max)),
- ?line true = ets:delete(Tab).
-
+ true = ets:delete(Tab).
+
otp_7665_act(Tab,Min,Max,DelNr) ->
List1 = [{key,N} || N <- lists:seq(Min,Max)],
- ?line true = ets:insert(Tab, List1),
- ?line true = ets:safe_fixtable(Tab, true),
- ?line true = ets:delete_object(Tab, {key,DelNr}),
+ true = ets:insert(Tab, List1),
+ true = ets:safe_fixtable(Tab, true),
+ true = ets:delete_object(Tab, {key,DelNr}),
List2 = lists:delete({key,DelNr}, List1),
%% Now verify that we find all remaining objects
- ?line List2 = ets:lookup(Tab,key),
- ?line EList2 = lists:map(fun({key,N})-> N end,
- List2),
- ?line EList2 = ets:lookup_element(Tab,key,2),
- ?line true = ets:delete(Tab, key),
- ?line [] = ets:lookup(Tab, key),
- ?line true = ets:safe_fixtable(Tab, false),
+ List2 = ets:lookup(Tab,key),
+ EList2 = lists:map(fun({key,N})-> N end,
+ List2),
+ EList2 = ets:lookup_element(Tab,key,2),
+ true = ets:delete(Tab, key),
+ [] = ets:lookup(Tab, key),
+ true = ets:safe_fixtable(Tab, false),
ok.
%% Whitebox testing of meta name table hashing.
meta_wb(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
repeat_for_opts(meta_wb_do),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
meta_wb_do(Opts) ->
@@ -5093,53 +4871,54 @@ meta_wb_do(Opts) ->
Len = length(Names),
OpFuns = {fun meta_wb_new/4, fun meta_wb_delete/4, fun meta_wb_rename/4},
- ?line true = (Len >= 3),
+ true = (Len >= 3),
io:format("Colliding names = ~p\n",[Names]),
F = fun(0,_,_) -> ok;
- (N,Tabs,Me) -> Name1 = lists:nth(random:uniform(Len),Names),
- Name2 = lists:nth(random:uniform(Len),Names),
- Op = element(random:uniform(3),OpFuns),
- NTabs = Op(Name1, Name2, Tabs, Opts),
- Me(N-1,NTabs,Me)
+ (N,Tabs,Me) ->
+ Name1 = lists:nth(rand:uniform(Len), Names),
+ Name2 = lists:nth(rand:uniform(Len), Names),
+ Op = element(rand:uniform(3),OpFuns),
+ NTabs = Op(Name1, Name2, Tabs, Opts),
+ Me(N-1, NTabs, Me)
end,
F(Len*100, [], F),
- % cleanup
+ %% cleanup
lists:foreach(fun(Name)->catch ets:delete(Name) end,
Names).
-
+
meta_wb_new(Name, _, Tabs, Opts) ->
case (catch ets_new(Name,[named_table|Opts])) of
Name ->
- ?line false = lists:member(Name, Tabs),
+ false = lists:member(Name, Tabs),
[Name | Tabs];
{'EXIT',{badarg,_}} ->
- ?line true = lists:member(Name, Tabs),
+ true = lists:member(Name, Tabs),
Tabs
end.
meta_wb_delete(Name, _, Tabs, _) ->
case (catch ets:delete(Name)) of
true ->
- ?line true = lists:member(Name, Tabs),
+ true = lists:member(Name, Tabs),
lists:delete(Name, Tabs);
{'EXIT',{badarg,_}} ->
- ?line false = lists:member(Name, Tabs),
+ false = lists:member(Name, Tabs),
Tabs
end.
meta_wb_rename(Old, New, Tabs, _) ->
case (catch ets:rename(Old,New)) of
New ->
- ?line true = lists:member(Old, Tabs)
+ true = lists:member(Old, Tabs)
andalso not lists:member(New, Tabs),
[New | lists:delete(Old, Tabs)];
{'EXIT',{badarg,_}} ->
- ?line true = not lists:member(Old, Tabs)
+ true = not lists:member(Old, Tabs)
orelse lists:member(New,Tabs),
Tabs
end.
-
-
+
+
colliding_names(Name) ->
erts_debug:set_internal_state(colliding_names, {Name,5}).
@@ -5147,17 +4926,13 @@ colliding_names(Name) ->
%% OTP_6913: Grow and shrink.
grow_shrink(Config) when is_list(Config) ->
- ?line EtsMem = etsmem(),
+ EtsMem = etsmem(),
Set = ets_new(a, [set]),
grow_shrink_0(0, 3071, 3000, 5000, Set),
ets:delete(Set),
- %OrdSet = ets_new(a, [ordered_set]),
- %grow_shrink_0(0, lists:seq(3071, 5000), OrdSet),
- %ets:delete(OrdSet),
-
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
grow_shrink_0(N, _, _, Max, _) when N >= Max ->
ok;
@@ -5170,21 +4945,18 @@ grow_shrink_1(N0, GrowN, ShrinkN, T) ->
grow_shrink_3(N1, N1 - ShrinkN, T).
grow_shrink_2(N, GrowTo, _) when N > GrowTo ->
- %io:format("Grown to ~p\n", [GrowTo]),
GrowTo;
grow_shrink_2(N, GrowTo, T) ->
true = ets:insert(T, {N,a}),
grow_shrink_2(N+1, GrowTo, T).
grow_shrink_3(N, ShrinkTo, _) when N =< ShrinkTo ->
- %io:format("Shrunk to ~p\n", [ShrinkTo]),
ShrinkTo;
grow_shrink_3(N, ShrinkTo, T) ->
true = ets:delete(T, N),
grow_shrink_3(N-1, ShrinkTo, T).
-
-grow_pseudo_deleted(doc) -> ["Grow a table that still contains pseudo-deleted objects"];
-grow_pseudo_deleted(suite) -> [];
+
+%% Grow a table that still contains pseudo-deleted objects.
grow_pseudo_deleted(Config) when is_list(Config) ->
only_if_smp(fun() -> grow_pseudo_deleted_do() end).
@@ -5195,17 +4967,17 @@ grow_pseudo_deleted_do() ->
grow_pseudo_deleted_do(Type) ->
process_flag(scheduler,1),
Self = self(),
- ?line T = ets_new(kalle,[Type,public,{write_concurrency,true}]),
+ T = ets_new(kalle,[Type,public,{write_concurrency,true}]),
Mod = 7, Mult = 10000,
filltabint(T,Mod*Mult),
- ?line true = ets:safe_fixtable(T,true),
- ?line Mult = ets:select_delete(T,
- [{{'$1', '_'},
- [{'=:=', {'rem', '$1', Mod}, 0}],
- [true]}]),
+ true = ets:safe_fixtable(T,true),
+ Mult = ets:select_delete(T,
+ [{{'$1', '_'},
+ [{'=:=', {'rem', '$1', Mod}, 0}],
+ [true]}]),
Left = Mult*(Mod-1),
- ?line Left = ets:info(T,size),
- ?line Mult = get_kept_objects(T),
+ Left = ets:info(T,size),
+ Mult = get_kept_objects(T),
filltabstr(T,Mult),
my_spawn_opt(
fun() ->
@@ -5221,7 +4993,7 @@ grow_pseudo_deleted_do(Type) ->
end),
Self ! done
end, [link, {scheduler,2}]),
- ?line start = receive_any(),
+ start = receive_any(),
io:format("Unfixing table... nitems=~p\n", [ets:info(T, size)]),
do_tc(fun() ->
true = ets:safe_fixtable(T, false)
@@ -5230,15 +5002,14 @@ grow_pseudo_deleted_do(Type) ->
io:format("Unfix table done in ~p ms. nitems=~p\n",
[Elapsed,ets:info(T, size)])
end),
- ?line false = ets:info(T,fixed),
- ?line 0 = get_kept_objects(T),
- ?line done = receive_any(),
+ false = ets:info(T,fixed),
+ 0 = get_kept_objects(T),
+ done = receive_any(),
%%verify_table_load(T), % may fail if concurrency is poor (genny)
ets:delete(T),
process_flag(scheduler,0).
-shrink_pseudo_deleted(doc) -> ["Shrink a table that still contains pseudo-deleted objects"];
-shrink_pseudo_deleted(suite) -> [];
+%% Shrink a table that still contains pseudo-deleted objects.
shrink_pseudo_deleted(Config) when is_list(Config) ->
only_if_smp(fun()->shrink_pseudo_deleted_do() end).
@@ -5249,16 +5020,16 @@ shrink_pseudo_deleted_do() ->
shrink_pseudo_deleted_do(Type) ->
process_flag(scheduler,1),
Self = self(),
- ?line T = ets_new(kalle,[Type,public,{write_concurrency,true}]),
+ T = ets_new(kalle,[Type,public,{write_concurrency,true}]),
Half = 10000,
filltabint(T,Half*2),
- ?line true = ets:safe_fixtable(T,true),
- ?line Half = ets:select_delete(T,
- [{{'$1', '_'},
- [{'>', '$1', Half}],
- [true]}]),
- ?line Half = ets:info(T,size),
- ?line Half = get_kept_objects(T),
+ true = ets:safe_fixtable(T,true),
+ Half = ets:select_delete(T,
+ [{{'$1', '_'},
+ [{'>', '$1', Half}],
+ [true]}]),
+ Half = ets:info(T,size),
+ Half = get_kept_objects(T),
my_spawn_opt(
fun()-> true = ets:info(T,fixed),
Self ! start,
@@ -5269,10 +5040,10 @@ shrink_pseudo_deleted_do(Type) ->
fun(Elapsed) ->
io:format("Done with delete in ~p ms.\n",
[Elapsed])
- end),
+ end),
Self ! done
end, [link, {scheduler,2}]),
- ?line start = receive_any(),
+ start = receive_any(),
io:format("Unfixing table... nitems=~p\n", [ets:info(T, size)]),
do_tc(fun() ->
true = ets:safe_fixtable(T, false)
@@ -5281,20 +5052,19 @@ shrink_pseudo_deleted_do(Type) ->
io:format("Unfix table done in ~p ms. nitems=~p\n",
[Elapsed,ets:info(T, size)])
end),
- ?line false = ets:info(T,fixed),
- ?line 0 = get_kept_objects(T),
- ?line done = receive_any(),
+ false = ets:info(T,fixed),
+ 0 = get_kept_objects(T),
+ done = receive_any(),
%%verify_table_load(T), % may fail if concurrency is poor (genny)
ets:delete(T),
process_flag(scheduler,0).
-
-meta_lookup_unnamed_read(suite) -> [];
+
meta_lookup_unnamed_read(Config) when is_list(Config) ->
InitF = fun(_) -> Tab = ets_new(unnamed,[]),
- true = ets:insert(Tab,{key,data}),
- Tab
+ true = ets:insert(Tab,{key,data}),
+ Tab
end,
ExecF = fun(Tab) -> [{key,data}] = ets:lookup(Tab,key),
Tab
@@ -5303,10 +5073,9 @@ meta_lookup_unnamed_read(Config) when is_list(Config) ->
end,
run_workers(InitF,ExecF,FiniF,10000).
-meta_lookup_unnamed_write(suite) -> [];
meta_lookup_unnamed_write(Config) when is_list(Config) ->
InitF = fun(_) -> Tab = ets_new(unnamed,[]),
- {Tab,0}
+ {Tab,0}
end,
ExecF = fun({Tab,N}) -> true = ets:insert(Tab,{key,N}),
{Tab,N+1}
@@ -5315,7 +5084,6 @@ meta_lookup_unnamed_write(Config) when is_list(Config) ->
end,
run_workers(InitF,ExecF,FiniF,10000).
-meta_lookup_named_read(suite) -> [];
meta_lookup_named_read(Config) when is_list(Config) ->
InitF = fun([ProcN|_]) -> Name = list_to_atom(integer_to_list(ProcN)),
Tab = ets_new(Name,[named_table]),
@@ -5329,11 +5097,10 @@ meta_lookup_named_read(Config) when is_list(Config) ->
end,
run_workers(InitF,ExecF,FiniF,10000).
-meta_lookup_named_write(suite) -> [];
meta_lookup_named_write(Config) when is_list(Config) ->
InitF = fun([ProcN|_]) -> Name = list_to_atom(integer_to_list(ProcN)),
- Tab = ets_new(Name,[named_table]),
- {Tab,0}
+ Tab = ets_new(Name,[named_table]),
+ {Tab,0}
end,
ExecF = fun({Tab,N}) -> true = ets:insert(Tab,{key,N}),
{Tab,N+1}
@@ -5342,7 +5109,6 @@ meta_lookup_named_write(Config) when is_list(Config) ->
end,
run_workers(InitF,ExecF,FiniF,10000).
-meta_newdel_unnamed(suite) -> [];
meta_newdel_unnamed(Config) when is_list(Config) ->
InitF = fun(_) -> ok end,
ExecF = fun(_) -> Tab = ets_new(unnamed,[]),
@@ -5351,7 +5117,6 @@ meta_newdel_unnamed(Config) when is_list(Config) ->
FiniF = fun(_) -> ok end,
run_workers(InitF,ExecF,FiniF,10000).
-meta_newdel_named(suite) -> [];
meta_newdel_named(Config) when is_list(Config) ->
InitF = fun([ProcN|_]) -> list_to_atom(integer_to_list(ProcN))
end,
@@ -5362,20 +5127,18 @@ meta_newdel_named(Config) when is_list(Config) ->
FiniF = fun(_) -> ok end,
run_workers(InitF,ExecF,FiniF,10000).
-smp_insert(doc) -> ["Concurrent insert's on same table"];
-smp_insert(suite) -> [];
+%% Concurrent insert's on same table.
smp_insert(Config) when is_list(Config) ->
ets_new(smp_insert,[named_table,public,{write_concurrency,true}]),
InitF = fun(_) -> ok end,
- ExecF = fun(_) -> true = ets:insert(smp_insert,{random:uniform(10000)})
+ ExecF = fun(_) -> true = ets:insert(smp_insert,{rand:uniform(10000)})
end,
FiniF = fun(_) -> ok end,
run_workers(InitF,ExecF,FiniF,100000),
verify_table_load(smp_insert),
ets:delete(smp_insert).
-smp_fixed_delete(doc) -> ["Concurrent delete's on same fixated table"];
-smp_fixed_delete(suite) -> [];
+%% Concurrent deletes on same fixated table.
smp_fixed_delete(Config) when is_list(Config) ->
only_if_smp(fun()->smp_fixed_delete_do() end).
@@ -5395,21 +5158,20 @@ smp_fixed_delete_do() ->
end,
FiniF = fun(_) -> ok end,
run_workers_do(InitF,ExecF,FiniF,NumOfObjs),
- ?line 0 = ets:info(T,size),
- ?line true = ets:info(T,fixed),
- ?line Buckets = num_of_buckets(T),
- ?line NumOfObjs = get_kept_objects(T),
+ 0 = ets:info(T,size),
+ true = ets:info(T,fixed),
+ Buckets = num_of_buckets(T),
+ NumOfObjs = get_kept_objects(T),
ets:safe_fixtable(T,false),
%% Will fail as unfix does not shrink the table:
- %%?line Mem = ets:info(T,memory),
+ %%Mem = ets:info(T,memory),
%%verify_table_load(T),
ets:delete(T).
num_of_buckets(T) ->
- ?line element(1,ets:info(T,stats)).
+ element(1,ets:info(T,stats)).
-smp_unfix_fix(doc) -> ["Fixate hash table while other process is busy doing unfix"];
-smp_unfix_fix(suite) -> [];
+%% Fixate hash table while other process is busy doing unfix.
smp_unfix_fix(Config) when is_list(Config) ->
only_if_smp(fun()-> smp_unfix_fix_do() end).
@@ -5423,15 +5185,15 @@ smp_unfix_fix_do() ->
filltabint(T,NumOfObjs),
ets:safe_fixtable(T,true),
Buckets = num_of_buckets(T),
- ?line Deleted = ets:select_delete(T,[{{'$1', '_'},
- [{'=<','$1', Deleted}],
- [true]}]),
- ?line Buckets = num_of_buckets(T),
+ Deleted = ets:select_delete(T,[{{'$1', '_'},
+ [{'=<','$1', Deleted}],
+ [true]}]),
+ Buckets = num_of_buckets(T),
Left = NumOfObjs - Deleted,
- ?line Left = ets:info(T,size),
- ?line true = ets:info(T,fixed),
- ?line Deleted = get_kept_objects(T),
-
+ Left = ets:info(T,size),
+ true = ets:info(T,fixed),
+ Deleted = get_kept_objects(T),
+
{Child, Mref} =
my_spawn_opt(
fun()->
@@ -5458,9 +5220,9 @@ smp_unfix_fix_do() ->
done = receive_any()
end,
[link, monitor, {scheduler,2}]),
-
- ?line start = receive_any(),
- ?line true = ets:info(T,fixed),
+
+ start = receive_any(),
+ true = ets:info(T,fixed),
io:put_chars("Parent starting to unfix... ~p\n"),
do_tc(fun() ->
ets:safe_fixtable(T, false)
@@ -5471,14 +5233,13 @@ smp_unfix_fix_do() ->
end),
Child ! done,
{'DOWN', Mref, process, Child, normal} = receive_any(),
- ?line false = ets:info(T,fixed),
- ?line 0 = get_kept_objects(T),
+ false = ets:info(T,fixed),
+ 0 = get_kept_objects(T),
%%verify_table_load(T),
ets:delete(T),
process_flag(scheduler,0).
-otp_8166(doc) -> ["Unsafe unfix was done by trapping select/match"];
-otp_8166(suite) -> [];
+%% Unsafe unfix was done by trapping select/match.
otp_8166(Config) when is_list(Config) ->
only_if_smp(3, fun()-> otp_8166_do(false),
otp_8166_do(true)
@@ -5509,8 +5270,8 @@ otp_8166_do(WC) ->
{'DOWN', ReaderMref, process, ReaderPid, normal} = receive_any(),
ZombieCrPid ! quit,
{'DOWN', ZombieCrMref, process, ZombieCrPid, normal} = receive_any(),
- ?line false = ets:info(T,fixed),
- ?line 0 = get_kept_objects(T),
+ false = ets:info(T,fixed),
+ 0 = get_kept_objects(T),
%%verify_table_load(T),
ets:delete(T),
process_flag(scheduler,0).
@@ -5551,9 +5312,9 @@ otp_8166_zombie_creator(T,Deleted) ->
{loop,Pid} ->
filltabint(T,Deleted),
ets:safe_fixtable(T,true),
- ?line Deleted = ets:select_delete(T,[{{'$1', '_'},
- [{'=<','$1', Deleted}],
- [true]}]),
+ Deleted = ets:select_delete(T,[{{'$1', '_'},
+ [{'=<','$1', Deleted}],
+ [true]}]),
Pid ! zombies_created,
repeat_while(fun() -> case ets:info(T,safe_fixed_monotonic_time) of
{_,[_P1,_P2]} ->
@@ -5571,57 +5332,55 @@ otp_8166_zombie_creator(T,Deleted) ->
io:format("ignore unfix in outer loop?\n",[]),
otp_8166_zombie_creator(T,Deleted)
end.
-
-
-
+
+
+
verify_table_load(T) ->
- ?line Stats = ets:info(T,stats),
- ?line {Buckets,AvgLen,StdDev,ExpSD,_MinLen,_MaxLen,_} = Stats,
- ?line ok = if
- AvgLen > 7 ->
- io:format("Table overloaded: Stats=~p\n~p\n",
- [Stats, ets:info(T)]),
- false;
-
- Buckets>256, AvgLen < 6 ->
- io:format("Table underloaded: Stats=~p\n~p\n",
- [Stats, ets:info(T)]),
- false;
-
- StdDev > ExpSD*2 ->
- io:format("Too large standard deviation (poor hashing?),"
- " stats=~p\n~p\n",[Stats, ets:info(T)]),
- false;
-
- true ->
- io:format("Stats = ~p\n",[Stats]),
- ok
- end.
-
-
-otp_8732(doc) -> ["ets:select on a tree with NIL key object"];
+ Stats = ets:info(T,stats),
+ {Buckets,AvgLen,StdDev,ExpSD,_MinLen,_MaxLen,_} = Stats,
+ ok = if
+ AvgLen > 7 ->
+ io:format("Table overloaded: Stats=~p\n~p\n",
+ [Stats, ets:info(T)]),
+ false;
+
+ Buckets>256, AvgLen < 6 ->
+ io:format("Table underloaded: Stats=~p\n~p\n",
+ [Stats, ets:info(T)]),
+ false;
+
+ StdDev > ExpSD*2 ->
+ io:format("Too large standard deviation (poor hashing?),"
+ " stats=~p\n~p\n",[Stats, ets:info(T)]),
+ false;
+
+ true ->
+ io:format("Stats = ~p\n",[Stats]),
+ ok
+ end.
+
+
+%% ets:select on a tree with NIL key object.
otp_8732(Config) when is_list(Config) ->
Tab = ets_new(noname,[ordered_set]),
filltabstr(Tab,999),
ets:insert(Tab,{[],"nasty NIL object"}),
- ?line [] = ets:match(Tab,{'_',nomatch}), %% Will hang if bug not fixed
+ [] = ets:match(Tab,{'_',nomatch}), %% Will hang if bug not fixed
ok.
-smp_select_delete(suite) -> [];
-smp_select_delete(doc) ->
- ["Run concurrent select_delete (and inserts) on same table."];
+%% Run concurrent select_delete (and inserts) on same table.
smp_select_delete(Config) when is_list(Config) ->
T = ets_new(smp_select_delete,[named_table,public,{write_concurrency,true}]),
Mod = 17,
Zeros = erlang:make_tuple(Mod,0),
InitF = fun(_) -> Zeros end,
ExecF = fun(Diffs0) ->
- case random:uniform(20) of
+ case rand:uniform(20) of
1 ->
Mod = 17,
- Eq = random:uniform(Mod) - 1,
+ Eq = rand:uniform(Mod) - 1,
Deleted = ets:select_delete(T,
[{{'_', '$1'},
[{'=:=', {'rem', '$1', Mod}, Eq}],
@@ -5630,67 +5389,67 @@ smp_select_delete(Config) when is_list(Config) ->
element(Eq+1,Diffs0) - Deleted),
Diffs1;
_ ->
- Key = random:uniform(10000),
+ Key = rand:uniform(10000),
Eq = Key rem Mod,
- ?line case ets:insert_new(T,{Key,Key}) of
- true ->
- Diffs1 = setelement(Eq+1, Diffs0,
- element(Eq+1,Diffs0)+1),
- Diffs1;
- false -> Diffs0
- end
+ case ets:insert_new(T,{Key,Key}) of
+ true ->
+ Diffs1 = setelement(Eq+1, Diffs0,
+ element(Eq+1,Diffs0)+1),
+ Diffs1;
+ false -> Diffs0
+ end
end
end,
FiniF = fun(Result) -> Result end,
Results = run_workers_do(InitF,ExecF,FiniF,20000),
- ?line TotCnts = lists:foldl(fun(Diffs, Sum) -> add_lists(Sum,tuple_to_list(Diffs)) end,
- lists:duplicate(Mod, 0), Results),
+ TotCnts = lists:foldl(fun(Diffs, Sum) -> add_lists(Sum,tuple_to_list(Diffs)) end,
+ lists:duplicate(Mod, 0), Results),
io:format("TotCnts = ~p\n",[TotCnts]),
- ?line LeftInTab = lists:foldl(fun(N,Sum) -> Sum+N end,
- 0, TotCnts),
+ LeftInTab = lists:foldl(fun(N,Sum) -> Sum+N end,
+ 0, TotCnts),
io:format("LeftInTab = ~p\n",[LeftInTab]),
- ?line LeftInTab = ets:info(T,size),
+ LeftInTab = ets:info(T,size),
lists:foldl(fun(Cnt,Eq) ->
WasCnt = ets:select_count(T,
[{{'_', '$1'},
[{'=:=', {'rem', '$1', Mod}, Eq}],
[true]}]),
io:format("~p: ~p =?= ~p\n",[Eq,Cnt,WasCnt]),
- ?line Cnt = WasCnt,
+ Cnt = WasCnt,
Eq+1
end,
0, TotCnts),
verify_table_load(T),
- ?line LeftInTab = ets:select_delete(T, [{{'$1','$1'}, [], [true]}]),
- ?line 0 = ets:info(T,size),
- ?line false = ets:info(T,fixed),
+ LeftInTab = ets:select_delete(T, [{{'$1','$1'}, [], [true]}]),
+ 0 = ets:info(T,size),
+ false = ets:info(T,fixed),
ets:delete(T).
-types(doc) -> ["Test different types"];
+%% Test different types.
types(Config) when is_list(Config) ->
init_externals(),
repeat_for_opts(types_do,[[set,ordered_set],compressed]).
types_do(Opts) ->
EtsMem = etsmem(),
- ?line T = ets_new(xxx,Opts),
+ T = ets_new(xxx,Opts),
Fun = fun(Term) ->
- ets:insert(T,{Term}),
- ?line [{Term}] = ets:lookup(T,Term),
- ets:insert(T,{Term,xxx}),
- ?line [{Term,xxx}] = ets:lookup(T,Term),
- ets:insert(T,{Term,"xxx"}),
- ?line [{Term,"xxx"}] = ets:lookup(T,Term),
- ets:insert(T,{xxx,Term}),
- ?line [{xxx,Term}] = ets:lookup(T,xxx),
- ets:insert(T,{"xxx",Term}),
- ?line [{"xxx",Term}] = ets:lookup(T,"xxx"),
- ets:delete_all_objects(T),
- ?line 0 = ets:info(T,size)
+ ets:insert(T,{Term}),
+ [{Term}] = ets:lookup(T,Term),
+ ets:insert(T,{Term,xxx}),
+ [{Term,xxx}] = ets:lookup(T,Term),
+ ets:insert(T,{Term,"xxx"}),
+ [{Term,"xxx"}] = ets:lookup(T,Term),
+ ets:insert(T,{xxx,Term}),
+ [{xxx,Term}] = ets:lookup(T,xxx),
+ ets:insert(T,{"xxx",Term}),
+ [{"xxx",Term}] = ets:lookup(T,"xxx"),
+ ets:delete_all_objects(T),
+ 0 = ets:info(T,size)
end,
test_terms(Fun, strict),
ets:delete(T),
- ?line verify_etsmem(EtsMem).
+ verify_etsmem(EtsMem).
%% OTP-9932: Memory overwrite when inserting large integers in compressed bag.
@@ -5707,9 +5466,10 @@ otp_9932(Config) when is_list(Config) ->
end,
lists:foreach(Fun, lists:seq(0, 16)),
ets:delete(T).
-
-otp_9423(doc) -> ["vm-deadlock caused by race between ets:delete and others on write_concurrency table"];
+
+%% vm-deadlock caused by race between ets:delete and others on
+%% write_concurrency table.
otp_9423(Config) when is_list(Config) ->
InitF = fun(_) -> {0,0} end,
ExecF = fun({S,F}) ->
@@ -5736,10 +5496,10 @@ otp_9423(Config) when is_list(Config) ->
[P ! stop || P <- Pids],
wait_pids(Pids),
ok;
-
+
Skipped -> Skipped
end.
-
+
%% Corrupted binary in compressed table
otp_10182(Config) when is_list(Config) ->
@@ -5767,7 +5527,7 @@ ets_all_run() ->
ets:delete(Table),
false = lists:member(Table, ets:all()),
ets_all_run().
-
+
take(Config) when is_list(Config) ->
%% Simple test for set tables.
@@ -5806,9 +5566,9 @@ take(Config) when is_list(Config) ->
ok.
-%
-% Utility functions:
-%
+%%
+%% Utility functions:
+%%
add_lists(L1,L2) ->
add_lists(L1,L2,[]).
@@ -5830,11 +5590,11 @@ run_workers(InitF,ExecF,FiniF,Laps, Exclude) ->
run_workers_do(InitF,ExecF,FiniF,Laps) ->
run_workers_do(InitF,ExecF,FiniF,Laps, 0).
run_workers_do(InitF,ExecF,FiniF,Laps, Exclude) ->
- ?line NumOfProcs = case erlang:system_info(schedulers) of
- N when (N > Exclude) -> N - Exclude
- end,
+ NumOfProcs = case erlang:system_info(schedulers) of
+ N when (N > Exclude) -> N - Exclude
+ end,
io:format("smp starting ~p workers\n",[NumOfProcs]),
- Seeds = [{ProcN,random:uniform(9999)} || ProcN <- lists:seq(1,NumOfProcs)],
+ Seeds = [{ProcN,rand:uniform(9999)} || ProcN <- lists:seq(1,NumOfProcs)],
Parent = self(),
Pids = [my_spawn_link(fun()-> worker(Seed,InitF,ExecF,FiniF,Laps,Parent,NumOfProcs) end)
|| Seed <- Seeds],
@@ -5842,10 +5602,10 @@ run_workers_do(InitF,ExecF,FiniF,Laps, Exclude) ->
infinite -> Pids;
_ -> wait_pids(Pids)
end.
-
+
worker({ProcN,Seed}, InitF, ExecF, FiniF, Laps, Parent, NumOfProcs) ->
io:format("smp worker ~p, seed=~p~n",[self(),Seed]),
- random:seed(Seed,Seed,Seed),
+ rand:seed(exsplus, {Seed,Seed,Seed}),
State1 = InitF([ProcN, NumOfProcs]),
State2 = worker_loop(Laps, ExecF, State1),
Result = FiniF(State2),
@@ -5860,7 +5620,7 @@ worker_loop(infinite, ExecF, State) ->
worker_loop(infinite,ExecF,ExecF(State));
worker_loop(N, ExecF, State) ->
worker_loop(N-1,ExecF,ExecF(State)).
-
+
wait_pids(Pids) ->
wait_pids(Pids,[]).
wait_pids([],Acc) ->
@@ -5868,7 +5628,7 @@ wait_pids([],Acc) ->
wait_pids(Pids, Acc) ->
receive
{Pid,Result} ->
- ?line true = lists:member(Pid,Pids),
+ true = lists:member(Pid,Pids),
Others = lists:delete(Pid,Pids),
io:format("wait_pid got ~p from ~p, still waiting for ~p\n",[Result,Pid,Others]),
wait_pids(Others,[Result | Acc])
@@ -5894,7 +5654,7 @@ wait_for_memory_deallocations() ->
erts_debug:set_internal_state(available_internal_state, true),
wait_for_memory_deallocations()
end.
-
+
etsmem() ->
wait_for_memory_deallocations(),
@@ -5907,35 +5667,35 @@ etsmem() ->
ErlangMemoryEts = try erlang:memory(ets) catch error:notsup -> notsup end,
Mem =
- {ErlangMemoryEts,
- case EtsAllocInfo of
- false -> undefined;
- MemInfo ->
- CS = lists:foldl(
- fun ({instance, _, L}, Acc) ->
- {value,{mbcs,MBCS}} = lists:keysearch(mbcs, 1, L),
- {value,{sbcs,SBCS}} = lists:keysearch(sbcs, 1, L),
- NewAcc = [MBCS, SBCS | Acc],
- case lists:keysearch(mbcs_pool, 1, L) of
- {value,{mbcs_pool, MBCS_POOL}} ->
- [MBCS_POOL|NewAcc];
- _ -> NewAcc
- end
- end,
- [],
- MemInfo),
- lists:foldl(
- fun(L, {Bl0,BlSz0}) ->
- {value,BlTup} = lists:keysearch(blocks, 1, L),
- blocks = element(1, BlTup),
- Bl = element(2, BlTup),
- {value,BlSzTup} = lists:keysearch(blocks_size, 1, L),
- blocks_size = element(1, BlSzTup),
- BlSz = element(2, BlSzTup),
- {Bl0+Bl,BlSz0+BlSz}
- end, {0,0}, CS)
- end},
- {Mem,AllTabs}.
+ {ErlangMemoryEts,
+ case EtsAllocInfo of
+ false -> undefined;
+ MemInfo ->
+ CS = lists:foldl(
+ fun ({instance, _, L}, Acc) ->
+ {value,{mbcs,MBCS}} = lists:keysearch(mbcs, 1, L),
+ {value,{sbcs,SBCS}} = lists:keysearch(sbcs, 1, L),
+ NewAcc = [MBCS, SBCS | Acc],
+ case lists:keysearch(mbcs_pool, 1, L) of
+ {value,{mbcs_pool, MBCS_POOL}} ->
+ [MBCS_POOL|NewAcc];
+ _ -> NewAcc
+ end
+ end,
+ [],
+ MemInfo),
+ lists:foldl(
+ fun(L, {Bl0,BlSz0}) ->
+ {value,BlTup} = lists:keysearch(blocks, 1, L),
+ blocks = element(1, BlTup),
+ Bl = element(2, BlTup),
+ {value,BlSzTup} = lists:keysearch(blocks_size, 1, L),
+ blocks_size = element(1, BlSzTup),
+ BlSz = element(2, BlSzTup),
+ {Bl0+Bl,BlSz0+BlSz}
+ end, {0,0}, CS)
+ end},
+ {Mem,AllTabs}.
verify_etsmem({MemInfo,AllTabs}) ->
wait_for_test_procs(),
@@ -6121,7 +5881,7 @@ receive_any_spinning(Loops,0,Tries) ->
end;
receive_any_spinning(Loops, N, Tries) when N>0 ->
receive_any_spinning(Loops, N-1, Tries).
-
+
spawn_monitor_with_pid(Pid, Fun) when is_pid(Pid) ->
@@ -6156,130 +5916,130 @@ only_if_smp(Schedulers, Func) ->
-define(heap_binary_size, 64).
test_terms(Test_Func, Mode) ->
garbage_collect(),
- ?line Pib0 = process_info(self(),binary),
-
- ?line Test_Func(atom),
- ?line Test_Func(''),
- ?line Test_Func('a'),
- ?line Test_Func('ab'),
- ?line Test_Func('abc'),
- ?line Test_Func('abcd'),
- ?line Test_Func('abcde'),
- ?line Test_Func('abcdef'),
- ?line Test_Func('abcdefg'),
- ?line Test_Func('abcdefgh'),
-
- ?line Test_Func(fun() -> ok end),
+ Pib0 = process_info(self(),binary),
+
+ Test_Func(atom),
+ Test_Func(''),
+ Test_Func('a'),
+ Test_Func('ab'),
+ Test_Func('abc'),
+ Test_Func('abcd'),
+ Test_Func('abcde'),
+ Test_Func('abcdef'),
+ Test_Func('abcdefg'),
+ Test_Func('abcdefgh'),
+
+ Test_Func(fun() -> ok end),
X = id([a,{b,c},c]),
Y = id({x,y,z}),
Z = id(1 bsl 8*257),
- ?line Test_Func(fun() -> X end),
- ?line Test_Func(fun() -> {X,Y} end),
- ?line Test_Func([fun() -> {X,Y,Z} end,
- fun() -> {Z,X,Y} end,
- fun() -> {Y,Z,X} end]),
-
- ?line Test_Func({trace_ts,{even_bigger,{some_data,fun() -> ok end}},{1,2,3}}),
- ?line Test_Func({trace_ts,{even_bigger,{some_data,<<1,2,3,4,5,6,7,8,9,10>>}},
- {1,2,3}}),
-
- ?line Test_Func(1),
- ?line Test_Func(42),
- ?line Test_Func(-23),
- ?line Test_Func(256),
- ?line Test_Func(25555),
- ?line Test_Func(-3333),
-
- ?line Test_Func(1.0),
-
- ?line Test_Func(183749783987483978498378478393874),
- ?line Test_Func(-37894183749783987483978498378478393874),
+ Test_Func(fun() -> X end),
+ Test_Func(fun() -> {X,Y} end),
+ Test_Func([fun() -> {X,Y,Z} end,
+ fun() -> {Z,X,Y} end,
+ fun() -> {Y,Z,X} end]),
+
+ Test_Func({trace_ts,{even_bigger,{some_data,fun() -> ok end}},{1,2,3}}),
+ Test_Func({trace_ts,{even_bigger,{some_data,<<1,2,3,4,5,6,7,8,9,10>>}},
+ {1,2,3}}),
+
+ Test_Func(1),
+ Test_Func(42),
+ Test_Func(-23),
+ Test_Func(256),
+ Test_Func(25555),
+ Test_Func(-3333),
+
+ Test_Func(1.0),
+
+ Test_Func(183749783987483978498378478393874),
+ Test_Func(-37894183749783987483978498378478393874),
Very_Big = very_big_num(),
- ?line Test_Func(Very_Big),
- ?line Test_Func(-Very_Big+1),
+ Test_Func(Very_Big),
+ Test_Func(-Very_Big+1),
- ?line Test_Func([]),
- ?line Test_Func("abcdef"),
- ?line Test_Func([a, b, 1, 2]),
- ?line Test_Func([a|b]),
+ Test_Func([]),
+ Test_Func("abcdef"),
+ Test_Func([a, b, 1, 2]),
+ Test_Func([a|b]),
- ?line Test_Func({}),
- ?line Test_Func({1}),
- ?line Test_Func({a, b}),
- ?line Test_Func({a, b, c}),
- ?line Test_Func(list_to_tuple(lists:seq(0, 255))),
- ?line Test_Func(list_to_tuple(lists:seq(0, 256))),
+ Test_Func({}),
+ Test_Func({1}),
+ Test_Func({a, b}),
+ Test_Func({a, b, c}),
+ Test_Func(list_to_tuple(lists:seq(0, 255))),
+ Test_Func(list_to_tuple(lists:seq(0, 256))),
- ?line Test_Func(make_ref()),
- ?line Test_Func([make_ref(), make_ref()]),
+ Test_Func(make_ref()),
+ Test_Func([make_ref(), make_ref()]),
- ?line Test_Func(make_port()),
+ Test_Func(make_port()),
- ?line Test_Func(make_pid()),
- ?line Test_Func(make_ext_pid()),
- ?line Test_Func(make_ext_port()),
- ?line Test_Func(make_ext_ref()),
+ Test_Func(make_pid()),
+ Test_Func(make_ext_pid()),
+ Test_Func(make_ext_port()),
+ Test_Func(make_ext_ref()),
Bin0 = list_to_binary(lists:seq(0, 14)),
- ?line Test_Func(Bin0),
+ Test_Func(Bin0),
Bin1 = list_to_binary(lists:seq(0, ?heap_binary_size)),
- ?line Test_Func(Bin1),
+ Test_Func(Bin1),
Bin2 = list_to_binary(lists:seq(0, ?heap_binary_size+1)),
- ?line Test_Func(Bin2),
+ Test_Func(Bin2),
Bin3 = list_to_binary(lists:seq(0, 255)),
garbage_collect(),
Pib = process_info(self(),binary),
- ?line Test_Func(Bin3),
+ Test_Func(Bin3),
garbage_collect(),
case Mode of
- strict -> ?line Pib = process_info(self(),binary);
+ strict -> Pib = process_info(self(),binary);
skip_refc_check -> ok
end,
- ?line Test_Func(make_unaligned_sub_binary(Bin0)),
- ?line Test_Func(make_unaligned_sub_binary(Bin1)),
- ?line Test_Func(make_unaligned_sub_binary(Bin2)),
- ?line Test_Func(make_unaligned_sub_binary(Bin3)),
-
- ?line Test_Func(make_sub_binary(lists:seq(42, 43))),
- ?line Test_Func(make_sub_binary([42,43,44])),
- ?line Test_Func(make_sub_binary([42,43,44,45])),
- ?line Test_Func(make_sub_binary([42,43,44,45,46])),
- ?line Test_Func(make_sub_binary([42,43,44,45,46,47])),
- ?line Test_Func(make_sub_binary([42,43,44,45,46,47,48])),
- ?line Test_Func(make_sub_binary(lists:seq(42, 49))),
- ?line Test_Func(make_sub_binary(lists:seq(0, 14))),
- ?line Test_Func(make_sub_binary(lists:seq(0, ?heap_binary_size))),
- ?line Test_Func(make_sub_binary(lists:seq(0, ?heap_binary_size+1))),
- ?line Test_Func(make_sub_binary(lists:seq(0, 255))),
-
- ?line Test_Func(make_unaligned_sub_binary(lists:seq(42, 43))),
- ?line Test_Func(make_unaligned_sub_binary([42,43,44])),
- ?line Test_Func(make_unaligned_sub_binary([42,43,44,45])),
- ?line Test_Func(make_unaligned_sub_binary([42,43,44,45,46])),
- ?line Test_Func(make_unaligned_sub_binary([42,43,44,45,46,47])),
- ?line Test_Func(make_unaligned_sub_binary([42,43,44,45,46,47,48])),
- ?line Test_Func(make_unaligned_sub_binary(lists:seq(42, 49))),
- ?line Test_Func(make_unaligned_sub_binary(lists:seq(0, 14))),
- ?line Test_Func(make_unaligned_sub_binary(lists:seq(0, ?heap_binary_size))),
- ?line Test_Func(make_unaligned_sub_binary(lists:seq(0, ?heap_binary_size+1))),
- ?line Test_Func(make_unaligned_sub_binary(lists:seq(0, 255))),
+ Test_Func(make_unaligned_sub_binary(Bin0)),
+ Test_Func(make_unaligned_sub_binary(Bin1)),
+ Test_Func(make_unaligned_sub_binary(Bin2)),
+ Test_Func(make_unaligned_sub_binary(Bin3)),
+
+ Test_Func(make_sub_binary(lists:seq(42, 43))),
+ Test_Func(make_sub_binary([42,43,44])),
+ Test_Func(make_sub_binary([42,43,44,45])),
+ Test_Func(make_sub_binary([42,43,44,45,46])),
+ Test_Func(make_sub_binary([42,43,44,45,46,47])),
+ Test_Func(make_sub_binary([42,43,44,45,46,47,48])),
+ Test_Func(make_sub_binary(lists:seq(42, 49))),
+ Test_Func(make_sub_binary(lists:seq(0, 14))),
+ Test_Func(make_sub_binary(lists:seq(0, ?heap_binary_size))),
+ Test_Func(make_sub_binary(lists:seq(0, ?heap_binary_size+1))),
+ Test_Func(make_sub_binary(lists:seq(0, 255))),
+
+ Test_Func(make_unaligned_sub_binary(lists:seq(42, 43))),
+ Test_Func(make_unaligned_sub_binary([42,43,44])),
+ Test_Func(make_unaligned_sub_binary([42,43,44,45])),
+ Test_Func(make_unaligned_sub_binary([42,43,44,45,46])),
+ Test_Func(make_unaligned_sub_binary([42,43,44,45,46,47])),
+ Test_Func(make_unaligned_sub_binary([42,43,44,45,46,47,48])),
+ Test_Func(make_unaligned_sub_binary(lists:seq(42, 49))),
+ Test_Func(make_unaligned_sub_binary(lists:seq(0, 14))),
+ Test_Func(make_unaligned_sub_binary(lists:seq(0, ?heap_binary_size))),
+ Test_Func(make_unaligned_sub_binary(lists:seq(0, ?heap_binary_size+1))),
+ Test_Func(make_unaligned_sub_binary(lists:seq(0, 255))),
%% Bit level binaries.
- ?line Test_Func(<<1:1>>),
- ?line Test_Func(<<2:2>>),
- ?line Test_Func(<<42:10>>),
- ?line Test_Func(list_to_bitstring([<<5:6>>|lists:seq(0, 255)])),
+ Test_Func(<<1:1>>),
+ Test_Func(<<2:2>>),
+ Test_Func(<<42:10>>),
+ Test_Func(list_to_bitstring([<<5:6>>|lists:seq(0, 255)])),
- ?line Test_Func(F = fun(A) -> 42*A end),
- ?line Test_Func(lists:duplicate(32, F)),
+ Test_Func(F = fun(A) -> 42*A end),
+ Test_Func(lists:duplicate(32, F)),
- ?line Test_Func(FF = fun binary_SUITE:all/1),
- ?line Test_Func(lists:duplicate(32, FF)),
+ Test_Func(FF = fun binary_SUITE:all/1),
+ Test_Func(lists:duplicate(32, FF)),
garbage_collect(),
case Mode of
- strict -> ?line Pib0 = process_info(self(),binary);
+ strict -> Pib0 = process_info(self(),binary);
skip_refc_check -> ok
end,
ok.
@@ -6291,18 +6051,18 @@ very_big_num() ->
very_big_num(33, 1).
very_big_num(Left, Result) when Left > 0 ->
- ?line very_big_num(Left-1, Result*256);
+ very_big_num(Left-1, Result*256);
very_big_num(0, Result) ->
- ?line Result.
+ Result.
make_port() ->
- ?line open_port({spawn, "efile"}, [eof]).
+ open_port({spawn, "efile"}, [eof]).
make_pid() ->
- ?line spawn_link(?MODULE, sleeper, []).
+ spawn_link(?MODULE, sleeper, []).
sleeper() ->
- ?line receive after infinity -> ok end.
+ receive after infinity -> ok end.
make_ext_pid() ->
{Pid, _, _} = get(externals),
@@ -6360,11 +6120,11 @@ mk_pid({NodeName, Creation}, Number, Serial) when is_atom(NodeName) ->
mk_pid({NodeNameExt, Creation}, Number, Serial);
mk_pid({NodeNameExt, Creation}, Number, Serial) ->
case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
- ?PID_EXT,
- NodeNameExt,
- uint32_be(Number),
- uint32_be(Serial),
- uint8(Creation)])) of
+ ?PID_EXT,
+ NodeNameExt,
+ uint32_be(Number),
+ uint32_be(Serial),
+ uint8(Creation)])) of
Pid when is_pid(Pid) ->
Pid;
{'EXIT', {badarg, _}} ->
@@ -6454,7 +6214,7 @@ repeat_for_opts(F, [], Acc) ->
_ -> [RV | RV_Acc]
end
end
- end, [], Acc);
+ end, [], Acc);
repeat_for_opts(F, [OptList | Tail], []) when is_list(OptList) ->
repeat_for_opts(F, Tail, [[Opt] || Opt <- OptList]);
repeat_for_opts(F, [OptList | Tail], AccList) when is_list(OptList) ->
@@ -6466,7 +6226,7 @@ repeat_for_opts_atom2list(all_types) -> [set,ordered_set,bag,duplicate_bag];
repeat_for_opts_atom2list(write_concurrency) -> [{write_concurrency,false},{write_concurrency,true}];
repeat_for_opts_atom2list(read_concurrency) -> [{read_concurrency,false},{read_concurrency,true}];
repeat_for_opts_atom2list(compressed) -> [compressed,void].
-
+
ets_new(Name, Opts) ->
%%ets:new(Name, [compressed | Opts]).
ets:new(Name, Opts).
diff --git a/lib/stdlib/test/ets_tough_SUITE.erl b/lib/stdlib/test/ets_tough_SUITE.erl
index c6f24fc670..c83c17217b 100644
--- a/lib/stdlib/test/ets_tough_SUITE.erl
+++ b/lib/stdlib/test/ets_tough_SUITE.erl
@@ -23,9 +23,11 @@
-export([init/1,terminate/2,handle_call/3,handle_info/2]).
-export([init_per_testcase/2, end_per_testcase/2]).
-compile([export_all]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,5}}].
all() ->
[ex1].
@@ -52,34 +54,31 @@ end_per_group(_GroupName, Config) ->
-define(GLOBAL_PARAMS,ets_tough_SUITE_global_params).
init_per_testcase(_Func, Config) ->
- Dog=test_server:timetrap(test_server:seconds(300)),
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Func, _Config) ->
ets:delete(?GLOBAL_PARAMS).
ex1(Config) when is_list(Config) ->
- ?line ets:new(?GLOBAL_PARAMS,[named_table,public]),
- ?line ets:insert(?GLOBAL_PARAMS,{a,set}),
- ?line ets:insert(?GLOBAL_PARAMS,{b,set}),
- ?line ex1_sub(Config),
- ?line ets:insert(?GLOBAL_PARAMS,{a,ordered_set}),
- ?line ets:insert(?GLOBAL_PARAMS,{b,set}),
- ?line ex1_sub(Config),
- ?line ets:insert(?GLOBAL_PARAMS,{a,ordered_set}),
- ?line ets:insert(?GLOBAL_PARAMS,{b,ordered_set}),
- ?line ex1_sub(Config).
-
-
+ ets:new(?GLOBAL_PARAMS,[named_table,public]),
+ ets:insert(?GLOBAL_PARAMS,{a,set}),
+ ets:insert(?GLOBAL_PARAMS,{b,set}),
+ ex1_sub(Config),
+ ets:insert(?GLOBAL_PARAMS,{a,ordered_set}),
+ ets:insert(?GLOBAL_PARAMS,{b,set}),
+ ex1_sub(Config),
+ ets:insert(?GLOBAL_PARAMS,{a,ordered_set}),
+ ets:insert(?GLOBAL_PARAMS,{b,ordered_set}),
+ ex1_sub(Config).
+
+
ex1_sub(Config) ->
{A,B} = prep(Config),
N =
- case ?config(ets_tough_SUITE_iters,Config) of
+ case proplists:get_value(ets_tough_SUITE_iters,Config) of
undefined ->
5000;
Other ->
@@ -92,9 +91,9 @@ ex1_sub(Config) ->
ok.
prep(Config) ->
- random:seed(),
+ rand:seed(exsplus),
put(dump_ticket,none),
- DumpDir = filename:join(?config(priv_dir,Config), "ets_tough"),
+ DumpDir = filename:join(proplists:get_value(priv_dir,Config), "ets_tough"),
file:make_dir(DumpDir),
put(dump_dir,DumpDir),
process_flag(trap_exit,true),
@@ -188,9 +187,9 @@ operate(dump,A,_B) ->
NewTicket = ddump_next(A,Units,Ticket),
put(dump_ticket,NewTicket),
_Result = case NewTicket of
- done -> done;
- _ -> dump_more
- end,
+ done -> done;
+ _ -> dump_more
+ end,
?DEBUG(io:format("dump ~w (~w)\n",[Units,_Result]));
_ ->
DumpDir = get(dump_dir),
@@ -211,7 +210,7 @@ operate(dump,A,_B) ->
ok
end
end.
-
+
random_operation() ->
Ops = {get,put,erase,dirty_get,dump},
random_element(Ops).
@@ -221,19 +220,19 @@ random_class() ->
random_element(Classes).
random_key() ->
- random:uniform(8).
+ rand:uniform(8).
random_value() ->
- case random:uniform(5) of
+ case rand:uniform(5) of
1 -> ok;
2 -> {data,random_key()};
3 -> {foo,bar,random_class()};
- 4 -> random:uniform(1000);
+ 4 -> rand:uniform(1000);
5 -> {recursive,random_value()}
end.
random_element(T) ->
- I = random:uniform(tuple_size(T)),
+ I = rand:uniform(tuple_size(T)),
element(I,T).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -246,7 +245,7 @@ show_table(N) ->
_ ->
error
end.
-
+
show_entries(Fd) ->
case phys_read_len(Fd) of
{ok,Len} ->
@@ -370,7 +369,7 @@ derase(ServerPid,Class,Key) ->
dget_class(ServerPid,Class,Condition) ->
gen_server:call(ServerPid,
- {handle_get_class,Class,Condition},infinity).
+ {handle_get_class,Class,Condition},infinity).
%%% derase_class(ServerPid,Class) -> ok
%%%
@@ -828,7 +827,7 @@ table_lookup_batch([],_Class,_Cond) ->
[];
table_lookup_batch([Table|Tables],Class,Cond) ->
table_lookup_batch([],Tables,Table,ets:first(Table),Class,Cond,[]).
-
+
table_lookup_batch(_Passed,[],_,'$end_of_table',_Class,_Cond,Ack) ->
Ack;
table_lookup_batch(Passed,[NewTable|Tables],Table,'$end_of_table',
@@ -838,7 +837,7 @@ table_lookup_batch(Passed,[NewTable|Tables],Table,'$end_of_table',
table_lookup_batch(Passed,Tables,Table,?ERASE_MARK(Key),Class,Cond,Ack) ->
table_lookup_batch(Passed,Tables,Table,?ets_next(Table,?ERASE_MARK(Key)),
Class,Cond,Ack);
-
+
table_lookup_batch(Passed,Tables,Table,Key,Class,Cond,Ack) ->
NewAck =
case table_lookup(Passed,Key) of
@@ -1069,7 +1068,7 @@ phys_load_table(DumpDir,N,Tab) ->
Other ->
{error,{open_error,Other}}
end.
-
+
phys_load_entries(Fd,Tab) ->
case phys_read_len(Fd) of
{ok,Len} ->
diff --git a/lib/stdlib/test/file_sorter_SUITE.erl b/lib/stdlib/test/file_sorter_SUITE.erl
index e0d9ec1fd7..379f4d609b 100644
--- a/lib/stdlib/test/file_sorter_SUITE.erl
+++ b/lib/stdlib/test/file_sorter_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(file_sorter_SUITE).
-%-define(debug, true).
+%%-define(debug, true).
-ifdef(debug).
-define(format(S, A), io:format(S, A)).
@@ -28,9 +28,9 @@
-define(t,test_server).
-define(privdir(_), "./file_sorter_SUITE_priv").
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(format(S, A), ok).
--define(privdir(Conf), ?config(priv_dir, Conf)).
+-define(privdir(Conf), proplists:get_value(priv_dir, Conf)).
-endif.
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -49,15 +49,14 @@
-export([init_per_testcase/2, end_per_testcase/2]).
init_per_testcase(_Case, Config) ->
- Dog=?t:timetrap(?t:minutes(2)),
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,2}}].
all() ->
[basic, badarg, term_sort, term_keysort,
@@ -83,377 +82,323 @@ end_per_group(_GroupName, Config) ->
Config.
-basic(doc) ->
- ["Basic test case."];
-basic(suite) ->
- [];
+%% Basic test case.
basic(Config) when is_list(Config) ->
Fmt = binary,
Arg = {format,Fmt},
Foo = outfile("foo", Config),
P0 = pps(),
- ?line F1s = [F1] = to_files([[]], Fmt, Config),
- ?line ok = file_sorter:sort(F1),
- ?line [] = from_files(F1, Fmt),
- ?line ok = file_sorter:keysort(17, F1),
- ?line [] = from_files(F1, Fmt),
- ?line ok = file_sorter:merge(F1s, Foo),
- ?line [] = from_files(Foo, Fmt),
- ?line delete_files(Foo),
- ?line ok = file_sorter:keymerge(17, F1s, Foo),
- ?line [] = from_files(Foo, Fmt),
- ?line delete_files([Foo | F1s]),
-
- ?line [F2] = to_files([[foo,bar]], Fmt, Config),
- ?line ok = file_sorter:sort([F2], F2, Arg),
- ?line [bar,foo] = from_files(F2, Fmt),
- ?line delete_files(F2),
-
- ?line Fs1 = to_files([[foo],[bar]], Fmt, Config),
- ?line ok = file_sorter:sort(Fs1, Foo, Arg),
- ?line [bar,foo] = from_files(Foo, Fmt),
- ?line delete_files(Foo),
- ?line ok = file_sorter:merge(Fs1, Foo, Arg),
- ?line [bar,foo] = from_files(Foo, Fmt),
- ?line delete_files([Foo | Fs1]),
-
- ?line Fmt2 = binary_term,
- ?line Arg2 = {format, Fmt2},
- ?line [F3] = to_files([[{foo,1},{bar,2}]], Fmt2, Config),
- ?line ok = file_sorter:keysort([2], [F3], F3, Arg2),
- ?line [{foo,1},{bar,2}] = from_files(F3, Fmt2),
- ?line delete_files(F3),
-
- ?line Fs2 = to_files([[{foo,1}],[{bar,2}]], Fmt2, Config),
- ?line ok = file_sorter:keysort(1, Fs2, Foo, Arg2),
- ?line [{bar,2},{foo,1}] = from_files(Foo, Fmt2),
- ?line delete_files(Foo),
- ?line ok = file_sorter:keymerge(1, Fs2, Foo, Arg2),
- ?line [{bar,2},{foo,1}] = from_files(Foo, Fmt2),
- ?line delete_files([Foo | Fs2]),
-
- ?line true = P0 =:= pps(),
+ F1s = [F1] = to_files([[]], Fmt, Config),
+ ok = file_sorter:sort(F1),
+ [] = from_files(F1, Fmt),
+ ok = file_sorter:keysort(17, F1),
+ [] = from_files(F1, Fmt),
+ ok = file_sorter:merge(F1s, Foo),
+ [] = from_files(Foo, Fmt),
+ delete_files(Foo),
+ ok = file_sorter:keymerge(17, F1s, Foo),
+ [] = from_files(Foo, Fmt),
+ delete_files([Foo | F1s]),
+
+ [F2] = to_files([[foo,bar]], Fmt, Config),
+ ok = file_sorter:sort([F2], F2, Arg),
+ [bar,foo] = from_files(F2, Fmt),
+ delete_files(F2),
+
+ Fs1 = to_files([[foo],[bar]], Fmt, Config),
+ ok = file_sorter:sort(Fs1, Foo, Arg),
+ [bar,foo] = from_files(Foo, Fmt),
+ delete_files(Foo),
+ ok = file_sorter:merge(Fs1, Foo, Arg),
+ [bar,foo] = from_files(Foo, Fmt),
+ delete_files([Foo | Fs1]),
+
+ Fmt2 = binary_term,
+ Arg2 = {format, Fmt2},
+ [F3] = to_files([[{foo,1},{bar,2}]], Fmt2, Config),
+ ok = file_sorter:keysort([2], [F3], F3, Arg2),
+ [{foo,1},{bar,2}] = from_files(F3, Fmt2),
+ delete_files(F3),
+
+ Fs2 = to_files([[{foo,1}],[{bar,2}]], Fmt2, Config),
+ ok = file_sorter:keysort(1, Fs2, Foo, Arg2),
+ [{bar,2},{foo,1}] = from_files(Foo, Fmt2),
+ delete_files(Foo),
+ ok = file_sorter:keymerge(1, Fs2, Foo, Arg2),
+ [{bar,2},{foo,1}] = from_files(Foo, Fmt2),
+ delete_files([Foo | Fs2]),
+
+ true = P0 =:= pps(),
ok.
-badarg(doc) ->
- ["Call functions with bad arguments."];
-badarg(suite) ->
- [];
+%% Call functions with bad arguments.
badarg(Config) when is_list(Config) ->
PrivDir = ?privdir(Config),
BadFile = filename:join(PrivDir, "not_a_file"),
ABadFile = filename:absname(BadFile),
- ?line file:delete(BadFile),
- ?line {error,{file_error,ABadFile,enoent}} =
+ file:delete(BadFile),
+ {error,{file_error,ABadFile,enoent}} =
file_sorter:sort(BadFile),
- ?line {'EXIT', {{badarg, {flipp}}, _}} =
+ {'EXIT', {{badarg, {flipp}}, _}} =
(catch file_sorter:sort({flipp})),
- ?line {error,{file_error,ABadFile,enoent}} =
+ {error,{file_error,ABadFile,enoent}} =
file_sorter:keysort(1, BadFile),
- ?line {'EXIT', {{badarg, {flipp}}, _}} =
+ {'EXIT', {{badarg, {flipp}}, _}} =
(catch file_sorter:keysort(1, {flipp})),
- ?line {'EXIT', {{badarg, {flipp}}, _}} =
+ {'EXIT', {{badarg, {flipp}}, _}} =
(catch file_sorter:merge([{flipp}],foo)),
- ?line {error,{file_error,ABadFile,enoent}} =
+ {error,{file_error,ABadFile,enoent}} =
file_sorter:keymerge(1,[BadFile],foo),
- ?line {'EXIT', {{badarg, {flipp}}, _}} =
+ {'EXIT', {{badarg, {flipp}}, _}} =
(catch file_sorter:keymerge(1,[{flipp}],foo)),
- ?line {'EXIT', {{badarg, _}, _}} =
+ {'EXIT', {{badarg, _}, _}} =
(catch file_sorter:merge(fun(X) -> X end, foo)),
- ?line {'EXIT', {{badarg, _}, _}} =
+ {'EXIT', {{badarg, _}, _}} =
(catch file_sorter:keymerge(1, fun(X) -> X end, foo)),
- ?line {error,{file_error,ABadFile,enoent}} =
+ {error,{file_error,ABadFile,enoent}} =
file_sorter:check(BadFile),
- ?line {'EXIT', {{badarg, {flipp}}, _}} =
+ {'EXIT', {{badarg, {flipp}}, _}} =
(catch file_sorter:check({flipp})),
- ?line {error,{file_error,ABadFile,enoent}} =
+ {error,{file_error,ABadFile,enoent}} =
file_sorter:keycheck(1, BadFile),
- ?line {'EXIT', {{badarg, {flipp}}, _}} =
+ {'EXIT', {{badarg, {flipp}}, _}} =
(catch file_sorter:keycheck(1, {flipp})),
- ?line {'EXIT', {{badarg, {flipp}}, _}} =
+ {'EXIT', {{badarg, {flipp}}, _}} =
(catch file_sorter:check([{flipp}],foo)),
- ?line {'EXIT', {{badarg, {flipp}}, _}} =
+ {'EXIT', {{badarg, {flipp}}, _}} =
(catch file_sorter:keycheck(1,[{flipp}],foo)),
- ?line {'EXIT', {{badarg, _}, _}} =
+ {'EXIT', {{badarg, _}, _}} =
(catch file_sorter:check(fun(X) -> X end, foo)),
- ?line {'EXIT', {{badarg, _}, _}} =
+ {'EXIT', {{badarg, _}, _}} =
(catch file_sorter:keycheck(1, fun(X) -> X end, foo)),
- ?line Fs1 = to_files([[1,2,3]], binary_term, Config),
- ?line {'EXIT', {{badarg, flipp}, _}} =
+ Fs1 = to_files([[1,2,3]], binary_term, Config),
+ {'EXIT', {{badarg, flipp}, _}} =
(catch file_sorter:check(Fs1 ++ flipp, [])),
[F1] = Fs1,
- ?line {error,{file_error,_,_}} =
+ {error,{file_error,_,_}} =
file_sorter:sort(Fs1, foo, [{tmpdir,F1},{size,0}]),
- ?line delete_files(Fs1),
- ?line Fs2 = to_files([[1,2,3]], binary_term, Config),
+ delete_files(Fs1),
+ Fs2 = to_files([[1,2,3]], binary_term, Config),
{error,{file_error,_,enoent}} =
file_sorter:sort(Fs2, foo, [{tmpdir,filename:absname(BadFile)},
{size,0}]),
- ?line delete_files(Fs2),
+ delete_files(Fs2),
- ?line {'EXIT', {{badarg, bad}, _}} =
+ {'EXIT', {{badarg, bad}, _}} =
(catch file_sorter:check([], [{format,term} | bad])),
- ?line {'EXIT', {{badarg, [{flipp}]}, _}} =
+ {'EXIT', {{badarg, [{flipp}]}, _}} =
(catch file_sorter:check([{flipp}])),
- ?line {'EXIT', {{badarg, {flipp}}, _}} =
+ {'EXIT', {{badarg, {flipp}}, _}} =
(catch file_sorter:keycheck(1, {flipp})),
- ?line {'EXIT', {{badarg, [{flipp}]}, _}} =
+ {'EXIT', {{badarg, [{flipp}]}, _}} =
(catch file_sorter:keycheck(2, [{flipp}])),
- ?line {error,{file_error,_,eisdir}} = file_sorter:keycheck(1, []),
- ?line {'EXIT', {{badarg, kp}, _}} = (catch file_sorter:keycheck(kp, [])),
- ?line {'EXIT', {{badarg, kp}, _}} =
+ {error,{file_error,_,eisdir}} = file_sorter:keycheck(1, []),
+ {'EXIT', {{badarg, kp}, _}} = (catch file_sorter:keycheck(kp, [])),
+ {'EXIT', {{badarg, kp}, _}} =
(catch file_sorter:keycheck([1, kp], [])),
- ?line {'EXIT', {{badarg, kp}, _}} =
+ {'EXIT', {{badarg, kp}, _}} =
(catch file_sorter:keycheck([1 | kp], [])),
- ?line {'EXIT', {{badarg, []}, _}} = (catch file_sorter:keycheck([], [])),
- ?line {'EXIT', {{badarg, {format, foo}}, _}} =
+ {'EXIT', {{badarg, []}, _}} = (catch file_sorter:keycheck([], [])),
+ {'EXIT', {{badarg, {format, foo}}, _}} =
(catch file_sorter:check([], {format,foo})),
- ?line {'EXIT', {{badarg, not_an_option}, _}} =
+ {'EXIT', {{badarg, not_an_option}, _}} =
(catch file_sorter:keycheck(7, [], [not_an_option])),
- ?line {'EXIT', {{badarg, format}, _}} =
+ {'EXIT', {{badarg, format}, _}} =
(catch file_sorter:keycheck(1, [], [{format, binary}])),
- ?line {'EXIT', {{badarg, order}, _}} =
+ {'EXIT', {{badarg, order}, _}} =
(catch file_sorter:keycheck(1, [], [{order, fun compare/2}])),
- ?line do_badarg(fun(I, O) -> file_sorter:sort(I, O) end,
- fun(Kp, I, O) -> file_sorter:keysort(Kp, I, O) end,
- BadFile),
- ?line do_badarg_opt(fun(I, O, X) -> file_sorter:sort(I, O, X) end,
- fun(Kp, I, O, X) -> file_sorter:keysort(Kp, I, O, X)
- end),
- ?line do_badarg(fun(I, O) -> file_sorter:merge(I, O) end,
- fun(Kp, I, O) -> file_sorter:keymerge(Kp, I, O) end,
- BadFile),
- ?line do_badarg_opt(fun(I, O, X) -> file_sorter:merge(I, O, X) end,
- fun(Kp, I, O, X) -> file_sorter:keymerge(Kp, I, O, X)
- end).
+ do_badarg(fun(I, O) -> file_sorter:sort(I, O) end,
+ fun(Kp, I, O) -> file_sorter:keysort(Kp, I, O) end,
+ BadFile),
+ do_badarg_opt(fun(I, O, X) -> file_sorter:sort(I, O, X) end,
+ fun(Kp, I, O, X) -> file_sorter:keysort(Kp, I, O, X)
+ end),
+ do_badarg(fun(I, O) -> file_sorter:merge(I, O) end,
+ fun(Kp, I, O) -> file_sorter:keymerge(Kp, I, O) end,
+ BadFile),
+ do_badarg_opt(fun(I, O, X) -> file_sorter:merge(I, O, X) end,
+ fun(Kp, I, O, X) -> file_sorter:keymerge(Kp, I, O, X)
+ end).
do_badarg(F, KF, BadFile) ->
[Char | _] = BadFile,
AFlipp = filename:absname(flipp),
- ?line {error,{file_error,AFlipp,enoent}} = F([flipp | flopp], foo),
- ?line {'EXIT', {{badarg, {foo,bar}}, _}} = (catch F([], {foo,bar})),
- ?line {'EXIT', {{badarg, Char}, _}} = (catch F(BadFile, [])),
- ?line {'EXIT', {{badarg, {flipp}}, _}} = (catch F({flipp}, [])),
-
- ?line {'EXIT', {{badarg, Char}, _}} = (catch KF(1, BadFile, [])),
- ?line {'EXIT', {{badarg, {flipp}}, _}} = (catch KF(1, {flipp}, [])),
- ?line {error,{file_error,AFlipp,enoent}} =
+ {error,{file_error,AFlipp,enoent}} = F([flipp | flopp], foo),
+ {'EXIT', {{badarg, {foo,bar}}, _}} = (catch F([], {foo,bar})),
+ {'EXIT', {{badarg, Char}, _}} = (catch F(BadFile, [])),
+ {'EXIT', {{badarg, {flipp}}, _}} = (catch F({flipp}, [])),
+
+ {'EXIT', {{badarg, Char}, _}} = (catch KF(1, BadFile, [])),
+ {'EXIT', {{badarg, {flipp}}, _}} = (catch KF(1, {flipp}, [])),
+ {error,{file_error,AFlipp,enoent}} =
KF(2, [flipp | flopp], foo),
- ?line {'EXIT', {{badarg, {foo,bar}}, _}} = (catch KF(1, [], {foo,bar})),
- ?line {'EXIT', {{badarg, kp}, _}} = (catch KF(kp, [], foo)),
- ?line {'EXIT', {{badarg, kp}, _}} = (catch KF([1, kp], [], foo)),
- ?line {'EXIT', {{badarg, kp}, _}} = (catch KF([1 | kp], [], foo)),
- ?line {'EXIT', {{badarg, []}, _}} = (catch KF([], [], foo)),
+ {'EXIT', {{badarg, {foo,bar}}, _}} = (catch KF(1, [], {foo,bar})),
+ {'EXIT', {{badarg, kp}, _}} = (catch KF(kp, [], foo)),
+ {'EXIT', {{badarg, kp}, _}} = (catch KF([1, kp], [], foo)),
+ {'EXIT', {{badarg, kp}, _}} = (catch KF([1 | kp], [], foo)),
+ {'EXIT', {{badarg, []}, _}} = (catch KF([], [], foo)),
ok.
do_badarg_opt(F, KF) ->
AFlipp = filename:absname(flipp),
- ?line {error,{file_error,AFlipp,enoent}} =
- F([flipp | flopp], foo, []),
- ?line {'EXIT', {{badarg, {flipp}}, _}} = (catch F([{flipp}], foo, [])),
- ?line {'EXIT', {{badarg, {out,put}}, _}} = (catch F([], {out,put}, [])),
- ?line {'EXIT', {{badarg, not_an_option}, _}} =
+ {error,{file_error,AFlipp,enoent}} =
+ F([flipp | flopp], foo, []),
+ {'EXIT', {{badarg, {flipp}}, _}} = (catch F([{flipp}], foo, [])),
+ {'EXIT', {{badarg, {out,put}}, _}} = (catch F([], {out,put}, [])),
+ {'EXIT', {{badarg, not_an_option}, _}} =
(catch F([], foo, [not_an_option])),
- ?line {'EXIT', {{badarg, {format, foo}}, _}} =
- (catch F([], foo, {format,foo})),
- ?line {'EXIT', {{badarg, {size,foo}}, _}} = (catch F([], foo, {size,foo})),
+ {'EXIT', {{badarg, {format, foo}}, _}} =
+ (catch F([], foo, {format,foo})),
+ {'EXIT', {{badarg, {size,foo}}, _}} = (catch F([], foo, {size,foo})),
- ?line {'EXIT', {{badarg, {size, -1}}, _}} = (catch F([], foo, {size,-1})),
- ?line {'EXIT', {{badarg, {no_files, foo}}, _}} =
+ {'EXIT', {{badarg, {size, -1}}, _}} = (catch F([], foo, {size,-1})),
+ {'EXIT', {{badarg, {no_files, foo}}, _}} =
(catch F([], foo, {no_files,foo})),
- ?line {'EXIT', {{badarg, {no_files, 1}}, _}} =
+ {'EXIT', {{badarg, {no_files, 1}}, _}} =
(catch F([], foo, {no_files,1})),
- ?line {'EXIT', {{badarg, 1}, _}} = (catch F([], foo, {tmpdir,1})),
- ?line {'EXIT', {{badarg, {order,1}}, _}} = (catch F([], foo, {order,1})),
- ?line {'EXIT', {{badarg, {compressed, flopp}}, _}} =
- (catch F([], foo, {compressed,flopp})),
- ?line {'EXIT', {{badarg, {unique,flopp}}, _}} =
- (catch F([], foo, {unique,flopp})),
- ?line {'EXIT', {{badarg, {header,foo}}, _}} =
+ {'EXIT', {{badarg, 1}, _}} = (catch F([], foo, {tmpdir,1})),
+ {'EXIT', {{badarg, {order,1}}, _}} = (catch F([], foo, {order,1})),
+ {'EXIT', {{badarg, {compressed, flopp}}, _}} =
+ (catch F([], foo, {compressed,flopp})),
+ {'EXIT', {{badarg, {unique,flopp}}, _}} =
+ (catch F([], foo, {unique,flopp})),
+ {'EXIT', {{badarg, {header,foo}}, _}} =
(catch F([], foo, {header,foo})),
- ?line {'EXIT', {{badarg, {header, 0}}, _}} =
+ {'EXIT', {{badarg, {header, 0}}, _}} =
(catch F([], foo, {header,0})),
- ?line {'EXIT', {{badarg, {header, 1 bsl 35}}, _}} =
+ {'EXIT', {{badarg, {header, 1 bsl 35}}, _}} =
(catch F([], foo, {header,1 bsl 35})),
- ?line {'EXIT', {{badarg, header}, _}} =
+ {'EXIT', {{badarg, header}, _}} =
(catch F([], foo, [{header,1},{format,term}])),
- ?line {'EXIT', {{badarg, not_an_option}, _}} =
+ {'EXIT', {{badarg, not_an_option}, _}} =
(catch KF(7, [], foo, [not_an_option])),
- ?line {'EXIT', {{badarg,format}, _}} =
+ {'EXIT', {{badarg,format}, _}} =
(catch KF(1, [], foo, [{format, binary}])),
- ?line {'EXIT', {{badarg, order}, _}} =
+ {'EXIT', {{badarg, order}, _}} =
(catch KF(1, [], foo, [{order, fun compare/2}])),
- ?line {'EXIT', {{badarg, {flipp}}, _}} =
+ {'EXIT', {{badarg, {flipp}}, _}} =
(catch KF(2, [{flipp}], foo,[])),
- ?line {error,{file_error,AFlipp,enoent}} =
+ {error,{file_error,AFlipp,enoent}} =
KF(2, [flipp | flopp], foo,[]),
- ?line {'EXIT', {{badarg, {out, put}}, _}} =
+ {'EXIT', {{badarg, {out, put}}, _}} =
(catch KF(1, [], {out,put}, [])),
- ?line {'EXIT', {{badarg, kp}, _}} = (catch KF(kp, [], foo, [])),
- ?line {'EXIT', {{badarg, kp}, _}} = (catch KF([1, kp], [], foo, [])),
- ?line {'EXIT', {{badarg, kp}, _}} = (catch KF([1 | kp], [], foo, [])),
+ {'EXIT', {{badarg, kp}, _}} = (catch KF(kp, [], foo, [])),
+ {'EXIT', {{badarg, kp}, _}} = (catch KF([1, kp], [], foo, [])),
+ {'EXIT', {{badarg, kp}, _}} = (catch KF([1 | kp], [], foo, [])),
ok.
-term_sort(doc) ->
- ["Sort terms on files."];
-term_sort(suite) ->
- [];
+%% Sort terms on files.
term_sort(Config) when is_list(Config) ->
- ?line sort(term, [{compressed,false}], Config),
- ?line sort(term, [{order, fun compare/2}], Config),
- ?line sort(term, [{order, ascending}, {compressed,true}], Config),
- ?line sort(term, [{order, descending}], Config),
+ sort(term, [{compressed,false}], Config),
+ sort(term, [{order, fun compare/2}], Config),
+ sort(term, [{order, ascending}, {compressed,true}], Config),
+ sort(term, [{order, descending}], Config),
ok.
-term_keysort(doc) ->
- ["Keysort terms on files."];
-term_keysort(suite) ->
- [];
+%% Keysort terms on files.
term_keysort(Config) when is_list(Config) ->
- ?line keysort(term, [{tmpdir, ""}], Config),
- ?line keysort(term, [{order,descending}], Config),
+ keysort(term, [{tmpdir, ""}], Config),
+ keysort(term, [{order,descending}], Config),
ok.
-binary_term_sort(doc) ->
- ["Sort binary terms on files."];
-binary_term_sort(suite) ->
- [];
+%% Sort binary terms on files.
binary_term_sort(Config) when is_list(Config) ->
PrivDir = ?privdir(Config),
- ?line sort({2, binary_term}, [], Config),
- ?line sort(binary_term, [{tmpdir, list_to_atom(PrivDir)}], Config),
- ?line sort(binary_term, [{tmpdir,PrivDir}], Config),
- ?line sort({3,binary_term}, [{order, fun compare/2}], Config),
- ?line sort(binary_term, [{order, fun compare/2}], Config),
- ?line sort(binary_term, [{order,descending}], Config),
+ sort({2, binary_term}, [], Config),
+ sort(binary_term, [{tmpdir, list_to_atom(PrivDir)}], Config),
+ sort(binary_term, [{tmpdir,PrivDir}], Config),
+ sort({3,binary_term}, [{order, fun compare/2}], Config),
+ sort(binary_term, [{order, fun compare/2}], Config),
+ sort(binary_term, [{order,descending}], Config),
ok.
-binary_term_keysort(doc) ->
- ["Keysort binary terms on files."];
-binary_term_keysort(suite) ->
- [];
+%% Keysort binary terms on files.
binary_term_keysort(Config) when is_list(Config) ->
- ?line keysort({3, binary_term}, [], Config),
- ?line keysort(binary_term, [], Config),
- ?line keysort(binary_term, [{order,descending}], Config),
+ keysort({3, binary_term}, [], Config),
+ keysort(binary_term, [], Config),
+ keysort(binary_term, [{order,descending}], Config),
ok.
-binary_sort(doc) ->
- ["Sort binaries on files."];
-binary_sort(suite) ->
- [];
+%% Sort binaries on files.
binary_sort(Config) when is_list(Config) ->
PrivDir = ?privdir(Config),
- ?line sort({2, binary}, [], Config),
- ?line sort(binary, [{tmpdir, list_to_atom(PrivDir)}], Config),
- ?line sort(binary, [{tmpdir,PrivDir}], Config),
- ?line sort({3,binary}, [{order, fun compare/2}], Config),
- ?line sort(binary, [{order, fun compare/2}], Config),
- ?line sort(binary, [{order,descending}], Config),
+ sort({2, binary}, [], Config),
+ sort(binary, [{tmpdir, list_to_atom(PrivDir)}], Config),
+ sort(binary, [{tmpdir,PrivDir}], Config),
+ sort({3,binary}, [{order, fun compare/2}], Config),
+ sort(binary, [{order, fun compare/2}], Config),
+ sort(binary, [{order,descending}], Config),
ok.
-term_merge(doc) ->
- ["Merge terms on files."];
-term_merge(suite) ->
- [];
+%% Merge terms on files.
term_merge(Config) when is_list(Config) ->
- ?line merge(term, [{order, fun compare/2}], Config),
- ?line merge(term, [{order, ascending}, {compressed,true}], Config),
- ?line merge(term, [{order, descending}, {compressed,false}], Config),
+ merge(term, [{order, fun compare/2}], Config),
+ merge(term, [{order, ascending}, {compressed,true}], Config),
+ merge(term, [{order, descending}, {compressed,false}], Config),
ok.
-term_keymerge(doc) ->
- ["Keymerge terms on files."];
-term_keymerge(suite) ->
- [];
+%% Keymerge terms on files.
term_keymerge(Config) when is_list(Config) ->
- ?line keymerge(term, [], Config),
- ?line keymerge(term, [{order, descending}], Config),
- ?line funmerge(term, [], Config),
+ keymerge(term, [], Config),
+ keymerge(term, [{order, descending}], Config),
+ funmerge(term, [], Config),
ok.
-binary_term_merge(doc) ->
- ["Merge binary terms on files."];
-binary_term_merge(suite) ->
- [];
+%% Merge binary terms on files.
binary_term_merge(Config) when is_list(Config) ->
- ?line merge(binary_term, [], Config),
- ?line merge({7, binary_term}, [], Config),
- ?line merge({3, binary_term}, [{order, fun compare/2}], Config),
+ merge(binary_term, [], Config),
+ merge({7, binary_term}, [], Config),
+ merge({3, binary_term}, [{order, fun compare/2}], Config),
ok.
-binary_term_keymerge(doc) ->
- ["Keymerge binary terms on files."];
-binary_term_keymerge(suite) ->
- [];
+%% Keymerge binary terms on files.
binary_term_keymerge(Config) when is_list(Config) ->
- ?line keymerge({3, binary_term}, [], Config),
- ?line keymerge(binary_term, [], Config),
- ?line funmerge({3, binary_term}, [], Config),
- ?line funmerge(binary_term, [], Config),
+ keymerge({3, binary_term}, [], Config),
+ keymerge(binary_term, [], Config),
+ funmerge({3, binary_term}, [], Config),
+ funmerge(binary_term, [], Config),
ok.
-binary_merge(doc) ->
- ["Merge binaries on files."];
-binary_merge(suite) ->
- [];
+%% Merge binaries on files.
binary_merge(Config) when is_list(Config) ->
- ?line merge(binary, [], Config),
- ?line merge({7, binary}, [], Config),
- ?line merge({3, binary}, [{order, fun compare/2}], Config),
+ merge(binary, [], Config),
+ merge({7, binary}, [], Config),
+ merge({3, binary}, [{order, fun compare/2}], Config),
ok.
-term_check(doc) ->
- ["Check terms on files."];
-term_check(suite) ->
- [];
+%% Check terms on files.
term_check(Config) when is_list(Config) ->
- ?line check(term, Config),
+ check(term, Config),
ok.
-binary_term_check(doc) ->
- ["Check binary terms on files."];
-binary_term_check(suite) ->
- [];
+%% Check binary terms on files.
binary_term_check(Config) when is_list(Config) ->
- ?line check(binary_term, Config),
+ check(binary_term, Config),
ok.
-term_keycheck(doc) ->
- ["Keycheck terms on files."];
-term_keycheck(suite) ->
- [];
+%% Keycheck terms on files.
term_keycheck(Config) when is_list(Config) ->
- ?line keycheck(term, Config),
+ keycheck(term, Config),
ok.
-binary_term_keycheck(doc) ->
- ["Keycheck binary terms on files."];
-binary_term_keycheck(suite) ->
- [];
+%% Keycheck binary terms on files.
binary_term_keycheck(Config) when is_list(Config) ->
- ?line keycheck(binary_term, Config),
+ keycheck(binary_term, Config),
ok.
-binary_check(doc) ->
- ["Check binary terms on files."];
-binary_check(suite) ->
- [];
+%% Check binary terms on files.
binary_check(Config) when is_list(Config) ->
- ?line check(binary, Config),
+ check(binary, Config),
ok.
-inout(doc) ->
- ["Funs as input or output."];
-inout(suite) ->
- [];
+%% Funs as input or output.
inout(Config) when is_list(Config) ->
BTF = {format, binary_term},
Foo = outfile("foo", Config),
@@ -462,52 +407,52 @@ inout(Config) when is_list(Config) ->
End = fun(read) -> end_of_input end,
IF1 = fun(read) -> {[1,7,5], End} end,
- ?line ok = file_sorter:sort(IF1, Foo, [{format, term}]),
+ ok = file_sorter:sort(IF1, Foo, [{format, term}]),
%% 'close' is called, but the return value is caught and ignored.
IF2 = fun(read) -> {[1,2,3], fun(close) -> throw(ignored) end} end,
- ?line {error, bad_object} = file_sorter:sort(IF2, Foo, BTF),
+ {error, bad_object} = file_sorter:sort(IF2, Foo, BTF),
IF3 = fun(no_match) -> foo end,
- ?line {'EXIT', {function_clause, _}} =
+ {'EXIT', {function_clause, _}} =
(catch file_sorter:sort(IF3, Foo)),
IF4 = fun(read) -> throw(my_message) end,
- ?line my_message = (catch file_sorter:sort(IF4, Foo)),
+ my_message = (catch file_sorter:sort(IF4, Foo)),
IF5 = fun(read) -> {error, my_error} end,
- ?line {error, my_error} = file_sorter:sort(IF5, Foo),
+ {error, my_error} = file_sorter:sort(IF5, Foo),
%% Output is fun.
- ?line {error, bad_object} =
+ {error, bad_object} =
file_sorter:sort(IF2, fun(close) -> ignored end, BTF),
Args = [{format, term}],
- ?line {error, bad_object} =
- file_sorter:keysort(1, IF2, fun(close) -> ignored end, Args),
+ {error, bad_object} =
+ file_sorter:keysort(1, IF2, fun(close) -> ignored end, Args),
OF1 = fun(close) -> fine; (L) when is_list(L) -> fun(close) -> nice end end,
- ?line nice = file_sorter:sort(IF1, OF1, Args),
+ nice = file_sorter:sort(IF1, OF1, Args),
OF2 = fun(_) -> my_return end,
- ?line my_return = file_sorter:sort(IF1, OF2, Args),
+ my_return = file_sorter:sort(IF1, OF2, Args),
OF3 = fun(_) -> throw(my_message) end,
- ?line my_message = (catch file_sorter:sort(IF1, OF3, Args)),
+ my_message = (catch file_sorter:sort(IF1, OF3, Args)),
OF4 = fun(no_match) -> foo end,
- ?line {'EXIT', {function_clause, _}} =
+ {'EXIT', {function_clause, _}} =
(catch file_sorter:sort(IF1, OF4, Args)),
- ?line P0 = pps(),
- ?line Fs1 = to_files([[3,1,2,5,4], [8,3,10]], term, Config),
- ?line error = file_sorter:sort(Fs1, fun(_) -> error end, Args),
- ?line delete_files(Fs1),
+ P0 = pps(),
+ Fs1 = to_files([[3,1,2,5,4], [8,3,10]], term, Config),
+ error = file_sorter:sort(Fs1, fun(_) -> error end, Args),
+ delete_files(Fs1),
- ?line true = P0 =:= pps(),
+ true = P0 =:= pps(),
%% Passing a value from the input functions to the output functions.
IFV1 = fun(read) -> {end_of_input, 17} end,
OFV1 = fun({value, Value}) -> ofv(Value, []) end,
- ?line {17, []} = file_sorter:sort(IFV1, OFV1, Args),
+ {17, []} = file_sorter:sort(IFV1, OFV1, Args),
%% Output is not a fun. The value returned by input funs is ignored.
%% OTP-5009.
- ?line ok = file_sorter:sort(IFV1, Foo, [{format,term}]),
- ?line [] = from_files(Foo, term),
- ?line delete_files(Foo),
+ ok = file_sorter:sort(IFV1, Foo, [{format,term}]),
+ [] = from_files(Foo, term),
+ delete_files(Foo),
ok.
@@ -518,10 +463,7 @@ ofv(Value, A) ->
ofv(Value, [L | A])
end.
-many(doc) ->
- ["Many temporary files."];
-many(suite) ->
- [];
+%% Many temporary files.
many(Config) when is_list(Config) ->
Foo = outfile("foo", Config),
PrivDir = ?privdir(Config),
@@ -530,171 +472,168 @@ many(Config) when is_list(Config) ->
Args = [{format, term}],
L1 = lists:map(fun(I) -> {one, two, three, I} end, lists:seq(1,1000)),
L2 = lists:map(fun(I) -> {four, five, six, I} end, lists:seq(1,1000)),
- ?line Fs2 = to_files([L1, L2], term, Config),
- ?line ok = file_sorter:sort(Fs2, Foo, [{size,1000} | Args]),
- ?line R = lists:sort(L1++L2),
- ?line R = from_files(Foo, term),
- ?line 2000 = length(R),
- ?line ok = file_sorter:sort(Fs2, Foo, [{no_files,4},{size,1000} | Args]),
- ?line R = from_files(Foo, term),
- ?line ok =
+ Fs2 = to_files([L1, L2], term, Config),
+ ok = file_sorter:sort(Fs2, Foo, [{size,1000} | Args]),
+ R = lists:sort(L1++L2),
+ R = from_files(Foo, term),
+ 2000 = length(R),
+ ok = file_sorter:sort(Fs2, Foo, [{no_files,4},{size,1000} | Args]),
+ R = from_files(Foo, term),
+ ok =
file_sorter:sort(Fs2, Foo,
[{no_files,4},{size,1000},{order,descending} | Args]),
- ?line true = lists:reverse(R) =:= from_files(Foo, term),
- ?line ok =
+ true = lists:reverse(R) =:= from_files(Foo, term),
+ ok =
file_sorter:sort(Fs2, Foo,
[{no_files,4},{size,1000},
{order,fun compare/2} | Args]),
- ?line R = from_files(Foo, term),
- ?line ok = file_sorter:keysort(4, Fs2, Foo,
- [{no_files,4},{size,1000} | Args]),
- ?line RK = lists:keysort(4, L1++L2),
- ?line RK = from_files(Foo, term),
- ?line delete_files(Foo),
- ?line ok =
+ R = from_files(Foo, term),
+ ok = file_sorter:keysort(4, Fs2, Foo,
+ [{no_files,4},{size,1000} | Args]),
+ RK = lists:keysort(4, L1++L2),
+ RK = from_files(Foo, term),
+ delete_files(Foo),
+ ok =
file_sorter:keysort(4, Fs2, Foo,
- [{no_files,4},{size,1000},{order,descending} | Args]),
- ?line true = lists:reverse(RK) =:= from_files(Foo, term),
- ?line delete_files(Foo),
- ?line ok = file_sorter:keysort(4, Fs2, Foo,
- [{size,500},{order,descending} | Args]),
- ?line true = lists:reverse(RK) =:= from_files(Foo, term),
- ?line delete_files(Foo),
- ?line error = file_sorter:sort(Fs2, fun(_) -> error end,
- [{tmpdir, PrivDir}, {no_files,3},
- {size,10000} | Args]),
+ [{no_files,4},{size,1000},{order,descending} | Args]),
+ true = lists:reverse(RK) =:= from_files(Foo, term),
+ delete_files(Foo),
+ ok = file_sorter:keysort(4, Fs2, Foo,
+ [{size,500},{order,descending} | Args]),
+ true = lists:reverse(RK) =:= from_files(Foo, term),
+ delete_files(Foo),
+ error = file_sorter:sort(Fs2, fun(_) -> error end,
+ [{tmpdir, PrivDir}, {no_files,3},
+ {size,10000} | Args]),
TmpDir = filename:join(PrivDir, "tmpdir"),
file:del_dir(TmpDir),
- ?line ok = file:make_dir(TmpDir),
- ?line case os:type() of
- {unix, _} ->
- ?line ok = file:change_mode(TmpDir, 8#0000),
- ?line {error, {file_error, _,_}} =
- file_sorter:sort(Fs2, fun(_M) -> foo end,
- [{no_files,3},{size,10000},
- {tmpdir,TmpDir} | Args]);
- _ ->
- true
- end,
- ?line ok = file:del_dir(TmpDir),
+ ok = file:make_dir(TmpDir),
+ case os:type() of
+ {unix, _} ->
+ ok = file:change_mode(TmpDir, 8#0000),
+ {error, {file_error, _,_}} =
+ file_sorter:sort(Fs2, fun(_M) -> foo end,
+ [{no_files,3},{size,10000},
+ {tmpdir,TmpDir} | Args]);
+ _ ->
+ true
+ end,
+ ok = file:del_dir(TmpDir),
delete_files(Fs2),
- ?line true = P0 =:= pps(),
+ true = P0 =:= pps(),
ok.
-misc(doc) ->
- ["Some other tests."];
-misc(suite) ->
- [];
+%% Some other tests.
misc(Config) when is_list(Config) ->
BTF = {format, binary_term},
Foo = outfile("foo", Config),
FFoo = filename:absname(Foo),
P0 = pps(),
- ?line [File] = Fs1 = to_files([[1,3,2]], term, Config),
- ?line ok = file:write_file(Foo,<<>>),
- ?line case os:type() of
- {unix, _} ->
- ok = file:change_mode(Foo, 8#0000),
- {error,{file_error,FFoo,eacces}} =
- file_sorter:sort(Fs1, Foo, {format,term});
- _ ->
- true
- end,
- ?line file:delete(Foo),
- ?line NoBytes = 16, % RAM memory will never get this big, or?
- ?line ALot = (1 bsl (NoBytes*8)) - 1,
- ?line ok = file:write_file(File, <<ALot:NoBytes/unit:8,"foobar">>),
+ [File] = Fs1 = to_files([[1,3,2]], term, Config),
+ ok = file:write_file(Foo,<<>>),
+ case os:type() of
+ {unix, _} ->
+ ok = file:change_mode(Foo, 8#0000),
+ {error,{file_error,FFoo,eacces}} =
+ file_sorter:sort(Fs1, Foo, {format,term});
+ _ ->
+ true
+ end,
+ file:delete(Foo),
+ NoBytes = 16, % RAM memory will never get this big, or?
+ ALot = (1 bsl (NoBytes*8)) - 1,
+ ok = file:write_file(File, <<ALot:NoBytes/unit:8,"foobar">>),
FFile = filename:absname(File),
- ?line {error, {bad_object,FFile}} =
+ {error, {bad_object,FFile}} =
file_sorter:sort(Fs1, Foo, [BTF, {header, 20}]),
- ?line ok = file:write_file(File, <<30:32,"foobar">>),
- ?line {error, {premature_eof, FFile}} = file_sorter:sort(Fs1, Foo, BTF),
- ?line ok = file:write_file(File, <<6:32,"foobar">>),
- ?line {error, {bad_object,FFile}} = file_sorter:sort(Fs1, Foo, BTF),
- ?line case os:type() of
- {unix, _} ->
- ok = file:change_mode(File, 8#0000),
- {error, {file_error,FFile,eacces}} =
- file_sorter:sort(Fs1, Foo),
- {error, {file_error,FFile,eacces}} =
- file_sorter:sort(Fs1, Foo, {format, binary_term});
- _ ->
- true
- end,
- ?line delete_files(Fs1),
- ?line true = P0 =:= pps(),
+ ok = file:write_file(File, <<30:32,"foobar">>),
+ {error, {premature_eof, FFile}} = file_sorter:sort(Fs1, Foo, BTF),
+ ok = file:write_file(File, <<6:32,"foobar">>),
+ {error, {bad_object,FFile}} = file_sorter:sort(Fs1, Foo, BTF),
+ case os:type() of
+ {unix, _} ->
+ ok = file:change_mode(File, 8#0000),
+ {error, {file_error,FFile,eacces}} =
+ file_sorter:sort(Fs1, Foo),
+ {error, {file_error,FFile,eacces}} =
+ file_sorter:sort(Fs1, Foo, {format, binary_term});
+ _ ->
+ true
+ end,
+ delete_files(Fs1),
+ true = P0 =:= pps(),
%% bigger than chunksize
- ?line E1 = <<32000:32, 10:256000>>,
- ?line E2 = <<32000:32, 5:256000>>,
- ?line E3 = <<32000:32, 8:256000>>,
- ?line ok = file:write_file(Foo, [E1, E2, E3]),
- ?line ok = file_sorter:sort([Foo], Foo, [{format,binary},{size,10000}]),
- ?line ok = file_sorter:sort([Foo], Foo, [{format,fun(X) -> X end},
- {size,10000}]),
- ?line Es = list_to_binary([E2,E3,E1]),
- ?line {ok, Es} = file:read_file(Foo),
- ?line delete_files(Foo),
- ?line true = P0 =:= pps(),
+ E1 = <<32000:32, 10:256000>>,
+ E2 = <<32000:32, 5:256000>>,
+ E3 = <<32000:32, 8:256000>>,
+ ok = file:write_file(Foo, [E1, E2, E3]),
+ ok = file_sorter:sort([Foo], Foo, [{format,binary},{size,10000}]),
+ ok = file_sorter:sort([Foo], Foo, [{format,fun(X) -> X end},
+ {size,10000}]),
+ Es = list_to_binary([E2,E3,E1]),
+ {ok, Es} = file:read_file(Foo),
+ delete_files(Foo),
+ true = P0 =:= pps(),
%% keysort more than one element
L = [{c,1,a},{c,2,b},{c,3,c},{b,1,c},{b,2,b},{b,3,a},{a,1,a},{a,2,b},
{a,3,c}],
- ?line Fs2 = to_files([L], binary_term, Config),
- ?line ok = file_sorter:keysort([2,3], Fs2, Foo, {format, binary_term}),
- ?line KS2_1 = from_files(Foo, binary_term),
- ?line KS2_2 = lists:keysort(2,lists:keysort(3, L)),
- ?line KS2_1 = KS2_2,
- ?line ok = file_sorter:keysort([2,3], Fs2, Foo,
- [{format, binary_term},{size,5}]),
- ?line KS2_3 = from_files(Foo, binary_term),
- ?line KS2_3 = KS2_2,
- ?line ok = file_sorter:keysort([2,3,1], Fs2, Foo, {format, binary_term}),
- ?line KS3_1 = from_files(Foo, binary_term),
- ?line KS3_2 = lists:keysort(2, lists:keysort(3,lists:keysort(1, L))),
- ?line KS3_1 = KS3_2,
- ?line ok = file_sorter:keysort([2,3,1], Fs2, Foo,
- [{format, binary_term},{size,5}]),
- ?line KS3_3 = from_files(Foo, binary_term),
- ?line KS3_3 = KS3_2,
- ?line delete_files([Foo | Fs2]),
- ?line true = P0 =:= pps(),
+ Fs2 = to_files([L], binary_term, Config),
+ ok = file_sorter:keysort([2,3], Fs2, Foo, {format, binary_term}),
+ KS2_1 = from_files(Foo, binary_term),
+ KS2_2 = lists:keysort(2,lists:keysort(3, L)),
+ KS2_1 = KS2_2,
+ ok = file_sorter:keysort([2,3], Fs2, Foo,
+ [{format, binary_term},{size,5}]),
+ KS2_3 = from_files(Foo, binary_term),
+ KS2_3 = KS2_2,
+ ok = file_sorter:keysort([2,3,1], Fs2, Foo, {format, binary_term}),
+ KS3_1 = from_files(Foo, binary_term),
+ KS3_2 = lists:keysort(2, lists:keysort(3,lists:keysort(1, L))),
+ KS3_1 = KS3_2,
+ ok = file_sorter:keysort([2,3,1], Fs2, Foo,
+ [{format, binary_term},{size,5}]),
+ KS3_3 = from_files(Foo, binary_term),
+ KS3_3 = KS3_2,
+ delete_files([Foo | Fs2]),
+ true = P0 =:= pps(),
%% bigger than chunksize
%% Assumes that CHUNKSIZE = 16384. Illustrates that the Last argument
%% of merge_files/5 is necessary.
- ?line EP1 = erlang:make_tuple(2728,foo),
- ?line EP2 = lists:duplicate(2729,qqq),
- ?line LL = [EP1, EP2, EP1, EP2, EP1, EP2],
- ?line Fs3 = to_files([LL], binary, Config),
- ?line ok = file_sorter:sort(Fs3, Foo, [{format,binary}, {unique,true}]),
- ?line [EP1,EP2] = from_files(Foo, binary),
- ?line delete_files(Foo),
- ?line ok = file_sorter:sort(Fs3, Foo,
- [{format,binary_term}, {unique,true},
- {size,30000}]),
- ?line [EP1,EP2] = from_files(Foo, binary_term),
- ?line delete_files([Foo | Fs3]),
-
- ?line true = P0 =:= pps(),
-
- ?line BE1 = <<20000:32, 17:160000>>,
- ?line BE2 = <<20000:32, 1717:160000>>,
- ?line ok = file:write_file(Foo, [BE1,BE2,BE1,BE2]),
- ?line ok = file_sorter:sort([Foo], Foo, [{format,binary},
- {size,10000},
- {unique,true}]),
- ?line BEs = list_to_binary([BE1, BE2]),
- ?line {ok, BEs} = file:read_file(Foo),
- ?line delete_files(Foo),
- ?line true = P0 =:= pps(),
-
- ?line Fs4 = to_files([[7,4,1]], binary_term, Config),
- ?line {error, {bad_term, _}} = file_sorter:sort(Fs4, Foo, {format, term}),
- ?line delete_files([Foo | Fs4]),
- ?line true = P0 =:= pps(),
+ EP1 = erlang:make_tuple(2728,foo),
+ EP2 = lists:duplicate(2729,qqq),
+ LL = [EP1, EP2, EP1, EP2, EP1, EP2],
+ Fs3 = to_files([LL], binary, Config),
+ ok = file_sorter:sort(Fs3, Foo, [{format,binary}, {unique,true}]),
+ [EP1,EP2] = from_files(Foo, binary),
+ delete_files(Foo),
+ ok = file_sorter:sort(Fs3, Foo,
+ [{format,binary_term}, {unique,true},
+ {size,30000}]),
+ [EP1,EP2] = from_files(Foo, binary_term),
+ delete_files([Foo | Fs3]),
+
+ true = P0 =:= pps(),
+
+ BE1 = <<20000:32, 17:160000>>,
+ BE2 = <<20000:32, 1717:160000>>,
+ ok = file:write_file(Foo, [BE1,BE2,BE1,BE2]),
+ ok = file_sorter:sort([Foo], Foo, [{format,binary},
+ {size,10000},
+ {unique,true}]),
+ BEs = list_to_binary([BE1, BE2]),
+ {ok, BEs} = file:read_file(Foo),
+ delete_files(Foo),
+ true = P0 =:= pps(),
+
+ Fs4 = to_files([[7,4,1]], binary_term, Config),
+ {error, {bad_term, _}} = file_sorter:sort(Fs4, Foo, {format, term}),
+ delete_files([Foo | Fs4]),
+ true = P0 =:= pps(),
ok.
@@ -708,71 +647,71 @@ sort(Fmt, XArgs, Config) ->
Foo = outfile("foo", Config),
%% Input is a fun. Output is a fun.
- ?line [] = file_sorter:sort(input([], 2, Fmt), output([], Fmt), Args),
- ?line L1 = [3,1,2,5,4],
- ?line S1 = file_sorter:sort(input(L1, 2, Fmt), output([], Fmt), TmpArgs),
- ?line S1 = rev(lists:sort(L1), TmpArgs),
+ [] = file_sorter:sort(input([], 2, Fmt), output([], Fmt), Args),
+ L1 = [3,1,2,5,4],
+ S1 = file_sorter:sort(input(L1, 2, Fmt), output([], Fmt), TmpArgs),
+ S1 = rev(lists:sort(L1), TmpArgs),
%% Input is a file. Output is a fun.
- ?line [] = file_sorter:sort([], output([], Fmt), Args),
- ?line L2 = [3,1,2,5,4],
- ?line Fs1 = to_files([L2], Fmt, Config),
- ?line S2 = file_sorter:sort(Fs1, output([], Fmt), TmpArgs),
- ?line S2 = rev(lists:sort(L2), TmpArgs),
- ?line delete_files(Fs1),
+ [] = file_sorter:sort([], output([], Fmt), Args),
+ L2 = [3,1,2,5,4],
+ Fs1 = to_files([L2], Fmt, Config),
+ S2 = file_sorter:sort(Fs1, output([], Fmt), TmpArgs),
+ S2 = rev(lists:sort(L2), TmpArgs),
+ delete_files(Fs1),
%% Input is a file. Output is a file
- ?line ok = file_sorter:sort([], Foo, Args),
- ?line [] = from_files(Foo, Fmt),
- ?line delete_files(Foo),
- ?line ok = file_sorter:sort([], Foo, [{unique,true} | Args]),
- ?line [] = from_files(Foo, Fmt),
- ?line delete_files(Foo),
- ?line L3 = [3,1,2,5,4,6],
- ?line Fs2 = to_files([L3], Fmt, Config),
- ?line ok = file_sorter:sort(Fs2, Foo, Args),
- ?line true = rev(lists:sort(L3), Args) =:= from_files(Foo, Fmt),
- ?line delete_files([Foo | Fs2]),
- ?line L4 = [1,3,4,1,2,5,4,5,6],
- ?line Fs3 = to_files([L4], Fmt, Config),
- ?line ok = file_sorter:sort(Fs3, Foo, Args++[{unique,true},
- {size,100000}]),
- ?line true = rev(lists:usort(L4), Args) =:= from_files(Foo, Fmt),
- ?line delete_files(Foo),
- ?line ok = file_sorter:sort(Fs3, Foo, Args++[{unique,true}]),
- ?line true = rev(lists:usort(L4), Args) =:= from_files(Foo, Fmt),
- ?line delete_files([Foo | Fs3]),
+ ok = file_sorter:sort([], Foo, Args),
+ [] = from_files(Foo, Fmt),
+ delete_files(Foo),
+ ok = file_sorter:sort([], Foo, [{unique,true} | Args]),
+ [] = from_files(Foo, Fmt),
+ delete_files(Foo),
+ L3 = [3,1,2,5,4,6],
+ Fs2 = to_files([L3], Fmt, Config),
+ ok = file_sorter:sort(Fs2, Foo, Args),
+ true = rev(lists:sort(L3), Args) =:= from_files(Foo, Fmt),
+ delete_files([Foo | Fs2]),
+ L4 = [1,3,4,1,2,5,4,5,6],
+ Fs3 = to_files([L4], Fmt, Config),
+ ok = file_sorter:sort(Fs3, Foo, Args++[{unique,true},
+ {size,100000}]),
+ true = rev(lists:usort(L4), Args) =:= from_files(Foo, Fmt),
+ delete_files(Foo),
+ ok = file_sorter:sort(Fs3, Foo, Args++[{unique,true}]),
+ true = rev(lists:usort(L4), Args) =:= from_files(Foo, Fmt),
+ delete_files([Foo | Fs3]),
%% Input is a fun. Output is a file.
- ?line ok = file_sorter:sort(input([], 2, Fmt), Foo, Args),
- ?line [] = from_files(Foo, Fmt),
- ?line delete_files(Foo),
- ?line L5 = [3,1,2,5,4,7],
- ?line ok = file_sorter:sort(input(L5, 2, Fmt), Foo, Args),
- ?line true = rev(lists:sort(L5), Args) =:= from_files(Foo, Fmt),
- ?line delete_files(Foo),
+ ok = file_sorter:sort(input([], 2, Fmt), Foo, Args),
+ [] = from_files(Foo, Fmt),
+ delete_files(Foo),
+ L5 = [3,1,2,5,4,7],
+ ok = file_sorter:sort(input(L5, 2, Fmt), Foo, Args),
+ true = rev(lists:sort(L5), Args) =:= from_files(Foo, Fmt),
+ delete_files(Foo),
%% Removing duplicate keys.
KFun = key_compare(2),
L6 = [{5,e},{2,b},{3,c},{1,a},{4,d}] ++ [{2,c},{1,b},{4,a}],
KUArgs = lists:keydelete(order, 1, Args) ++
- [{unique, true}, {order, KFun},{size,100000}],
- ?line ok = file_sorter:sort(input(L6, 2, Fmt), Foo, KUArgs),
- ?line true = rev(lists:ukeysort(2, L6), KUArgs) =:= from_files(Foo, Fmt),
+ [{unique, true}, {order, KFun},{size,100000}],
+ ok = file_sorter:sort(input(L6, 2, Fmt), Foo, KUArgs),
+ true = rev(lists:ukeysort(2, L6), KUArgs) =:= from_files(Foo, Fmt),
KArgs = lists:keydelete(unique, 1, KUArgs),
- ?line ok = file_sorter:sort(input(L6, 2, Fmt), Foo, KArgs),
- ?line true = rev(lists:keysort(2, L6), KArgs) =:= from_files(Foo, Fmt),
+ ok = file_sorter:sort(input(L6, 2, Fmt), Foo, KArgs),
+ true = rev(lists:keysort(2, L6), KArgs) =:= from_files(Foo, Fmt),
%% Removing duplicate keys. Again.
KUArgs2 = lists:keydelete(order, 1, Args) ++
- [{unique, true}, {order, KFun},{size,5}],
- ?line ok = file_sorter:sort(input(L6, 2, Fmt), Foo, KUArgs2),
- ?line true = rev(lists:ukeysort(2, L6), KUArgs2) =:= from_files(Foo, Fmt),
+ [{unique, true}, {order, KFun},{size,5}],
+ ok = file_sorter:sort(input(L6, 2, Fmt), Foo, KUArgs2),
+ true = rev(lists:ukeysort(2, L6), KUArgs2) =:= from_files(Foo, Fmt),
KArgs2 = lists:keydelete(unique, 1, KUArgs2),
- ?line ok = file_sorter:sort(input(L6, 2, Fmt), Foo, KArgs2),
- ?line true = rev(lists:keysort(2, L6), KArgs2) =:= from_files(Foo, Fmt),
- ?line delete_files(Foo),
-
+ ok = file_sorter:sort(input(L6, 2, Fmt), Foo, KArgs2),
+ true = rev(lists:keysort(2, L6), KArgs2) =:= from_files(Foo, Fmt),
+ delete_files(Foo),
+
ok.
keysort(Fmt, XArgs, Config) ->
@@ -781,58 +720,58 @@ keysort(Fmt, XArgs, Config) ->
Foo = outfile("foo", Config),
%% Input is files. Output is a file.
- ?line ok = file_sorter:keysort(2, [], Foo, Args),
- ?line [] = from_files(Foo, Fmt),
- ?line delete_files(Foo),
- ?line ok = file_sorter:keysort(2, [], Foo, [{unique,true} | Args]),
- ?line [] = from_files(Foo, Fmt),
- ?line delete_files(Foo),
- ?line L0 = [{a,2},{a,1},{a,2},{a,2},{a,1},{a,2},{a,2},{a,3}],
- ?line Fs0 = to_files([L0], Fmt, Config),
- ?line S = rev(lists:ukeysort(1, L0), Args),
- ?line ok =
+ ok = file_sorter:keysort(2, [], Foo, Args),
+ [] = from_files(Foo, Fmt),
+ delete_files(Foo),
+ ok = file_sorter:keysort(2, [], Foo, [{unique,true} | Args]),
+ [] = from_files(Foo, Fmt),
+ delete_files(Foo),
+ L0 = [{a,2},{a,1},{a,2},{a,2},{a,1},{a,2},{a,2},{a,3}],
+ Fs0 = to_files([L0], Fmt, Config),
+ S = rev(lists:ukeysort(1, L0), Args),
+ ok =
file_sorter:keysort(1, Fs0, Foo, Args ++ [{unique,true},
{size,100000}]),
- ?line S = from_files(Foo, Fmt),
- ?line ok =
+ S = from_files(Foo, Fmt),
+ ok =
file_sorter:keysort(1, Fs0, Foo, Args ++ [{unique,true},
{size,5}]),
- ?line S = from_files(Foo, Fmt),
- ?line ok = file_sorter:keysort(1, Fs0, Foo, Args ++ [{unique,true}]),
- ?line S = from_files(Foo, Fmt),
- ?line delete_files([Foo | Fs0]),
- ?line L11 = [{a,1,x4},{b,2,x4},{c,3,x4}],
- ?line L21 = [{a,1,x3},{b,2,x3},{c,3,x3}],
- ?line L31 = [{a,1,x2},{b,2,x2},{c,3,x2}],
- ?line L41 = [{a,1,x1},{b,2,x1},{c,3,x1}],
- ?line All = [L11, L21, L31, L41],
- ?line AllFlat = lists:append(All),
- ?line Sorted = rev(lists:keysort(2, AllFlat), Args),
- ?line Fs1 = to_files(All, Fmt, Config),
- ?line ok = file_sorter:keysort(2, Fs1, Foo, Args),
- ?line Sorted = from_files(Foo, Fmt),
- ?line delete_files(Foo),
+ S = from_files(Foo, Fmt),
+ ok = file_sorter:keysort(1, Fs0, Foo, Args ++ [{unique,true}]),
+ S = from_files(Foo, Fmt),
+ delete_files([Foo | Fs0]),
+ L11 = [{a,1,x4},{b,2,x4},{c,3,x4}],
+ L21 = [{a,1,x3},{b,2,x3},{c,3,x3}],
+ L31 = [{a,1,x2},{b,2,x2},{c,3,x2}],
+ L41 = [{a,1,x1},{b,2,x1},{c,3,x1}],
+ All = [L11, L21, L31, L41],
+ AllFlat = lists:append(All),
+ Sorted = rev(lists:keysort(2, AllFlat), Args),
+ Fs1 = to_files(All, Fmt, Config),
+ ok = file_sorter:keysort(2, Fs1, Foo, Args),
+ Sorted = from_files(Foo, Fmt),
+ delete_files(Foo),
%% Input is files. Output is a fun.
- ?line [] = file_sorter:keysort(2, [], output([], Fmt), Args),
- ?line KS1 = file_sorter:keysort(2, Fs1, output([], Fmt), TmpArgs),
- ?line Sorted = KS1,
- ?line delete_files(Fs1),
+ [] = file_sorter:keysort(2, [], output([], Fmt), Args),
+ KS1 = file_sorter:keysort(2, Fs1, output([], Fmt), TmpArgs),
+ Sorted = KS1,
+ delete_files(Fs1),
%% Input is a fun. Output is a file.
- ?line ok = file_sorter:keysort(2, input([], 2, Fmt), Foo, Args),
- ?line [] = from_files(Foo, Fmt),
- ?line delete_files(Foo),
- ?line ok = file_sorter:keysort(2, input(AllFlat, 4, Fmt), Foo, Args),
- ?line Sorted = from_files(Foo, Fmt),
- ?line delete_files(Foo),
+ ok = file_sorter:keysort(2, input([], 2, Fmt), Foo, Args),
+ [] = from_files(Foo, Fmt),
+ delete_files(Foo),
+ ok = file_sorter:keysort(2, input(AllFlat, 4, Fmt), Foo, Args),
+ Sorted = from_files(Foo, Fmt),
+ delete_files(Foo),
%% Input is a fun. Output is a fun.
- ?line [] = file_sorter:keysort(2, input([], 2, Fmt), output([], Fmt),Args),
- ?line KS2 =
+ [] = file_sorter:keysort(2, input([], 2, Fmt), output([], Fmt),Args),
+ KS2 =
file_sorter:keysort(2, input(AllFlat, 4, Fmt), output([], Fmt),
TmpArgs),
- ?line Sorted = KS2,
+ Sorted = KS2,
ok.
merge(Fmt, XArgs, Config) ->
@@ -840,35 +779,35 @@ merge(Fmt, XArgs, Config) ->
Foo = outfile("foo", Config),
%% Input is a file. Output is a fun.
- ?line [] = file_sorter:merge([], output([], Fmt), Args),
- ?line L2 = [[1,3,5],[2,4,5]],
- ?line Fs1 = to_files(L2, Fmt, Config),
- ?line S2 = file_sorter:sort(Fs1, output([], Fmt), Args),
- ?line S2 = rev(lists:sort(lists:append(L2)), Args),
- ?line delete_files(Fs1),
+ [] = file_sorter:merge([], output([], Fmt), Args),
+ L2 = [[1,3,5],[2,4,5]],
+ Fs1 = to_files(L2, Fmt, Config),
+ S2 = file_sorter:sort(Fs1, output([], Fmt), Args),
+ S2 = rev(lists:sort(lists:append(L2)), Args),
+ delete_files(Fs1),
%% Input is a file. Output is a file
- ?line ok = file_sorter:merge([], Foo, Args),
- ?line [] = from_files(Foo, Fmt),
- ?line delete_files(Foo),
- ?line ok = file_sorter:merge([], Foo, [{unique,true} | Args]),
- ?line [] = from_files(Foo, Fmt),
- ?line delete_files(Foo),
- ?line L31 = [1,2,3],
- ?line L32 = [2,3,4],
- ?line L33 = [4,5,6],
- ?line L3r = [L31, L32, L33],
- ?line L3 = [rev(L31,Args), rev(L32,Args), rev(L33,Args)],
- ?line Fs2 = to_files(L3, Fmt, Config),
- ?line ok = file_sorter:merge(Fs2, Foo, Args),
- ?line true = rev(lists:merge(L3r), Args) =:= from_files(Foo, Fmt),
- ?line ok = file_sorter:merge(Fs2, Foo, Args++[{unique,true},
- {size,100000}]),
- ?line true = rev(lists:umerge(L3r), Args) =:= from_files(Foo, Fmt),
- ?line delete_files(Foo),
- ?line ok = file_sorter:merge(Fs2, Foo, Args++[{unique,true}]),
- ?line true = rev(lists:umerge(L3r), Args) =:= from_files(Foo, Fmt),
- ?line delete_files([Foo | Fs2]),
+ ok = file_sorter:merge([], Foo, Args),
+ [] = from_files(Foo, Fmt),
+ delete_files(Foo),
+ ok = file_sorter:merge([], Foo, [{unique,true} | Args]),
+ [] = from_files(Foo, Fmt),
+ delete_files(Foo),
+ L31 = [1,2,3],
+ L32 = [2,3,4],
+ L33 = [4,5,6],
+ L3r = [L31, L32, L33],
+ L3 = [rev(L31,Args), rev(L32,Args), rev(L33,Args)],
+ Fs2 = to_files(L3, Fmt, Config),
+ ok = file_sorter:merge(Fs2, Foo, Args),
+ true = rev(lists:merge(L3r), Args) =:= from_files(Foo, Fmt),
+ ok = file_sorter:merge(Fs2, Foo, Args++[{unique,true},
+ {size,100000}]),
+ true = rev(lists:umerge(L3r), Args) =:= from_files(Foo, Fmt),
+ delete_files(Foo),
+ ok = file_sorter:merge(Fs2, Foo, Args++[{unique,true}]),
+ true = rev(lists:umerge(L3r), Args) =:= from_files(Foo, Fmt),
+ delete_files([Foo | Fs2]),
ok.
@@ -877,83 +816,83 @@ keymerge(Fmt, XArgs, Config) ->
Foo = outfile("foo", Config),
%% Input is files. Output is a file.
- ?line ok = file_sorter:keymerge(2, [], Foo, Args),
- ?line [] = from_files(Foo, Fmt),
- ?line delete_files(Foo),
- ?line ok = file_sorter:keymerge(2, [], Foo, [{unique,true} | Args]),
- ?line [] = from_files(Foo, Fmt),
- ?line delete_files(Foo),
- ?line L0 = [rev([{a,1},{a,2}], Args), rev([{a,2},{a,1},{a,3}], Args)],
- ?line Fs0 = to_files(L0, Fmt, Config),
- ?line delete_files(Foo),
- ?line ok = file_sorter:keymerge(1, Fs0, Foo, Args ++ [{unique,false}]),
- ?line S2 = rev([{a,1},{a,2},{a,2},{a,1},{a,3}], Args),
- ?line S2 = from_files(Foo, Fmt),
- ?line delete_files([Foo | Fs0]),
- ?line L11 = [{a,1,x4},{b,2,x4},{c,3,x4}],
- ?line L21 = [{a,1,x3},{b,2,x3},{c,3,x3}],
- ?line L31 = [{a,1,x2},{b,2,x2},{c,3,x2}],
- ?line L41 = [{a,1,x1},{b,2,x1},{c,3,x1}],
- ?line All =
+ ok = file_sorter:keymerge(2, [], Foo, Args),
+ [] = from_files(Foo, Fmt),
+ delete_files(Foo),
+ ok = file_sorter:keymerge(2, [], Foo, [{unique,true} | Args]),
+ [] = from_files(Foo, Fmt),
+ delete_files(Foo),
+ L0 = [rev([{a,1},{a,2}], Args), rev([{a,2},{a,1},{a,3}], Args)],
+ Fs0 = to_files(L0, Fmt, Config),
+ delete_files(Foo),
+ ok = file_sorter:keymerge(1, Fs0, Foo, Args ++ [{unique,false}]),
+ S2 = rev([{a,1},{a,2},{a,2},{a,1},{a,3}], Args),
+ S2 = from_files(Foo, Fmt),
+ delete_files([Foo | Fs0]),
+ L11 = [{a,1,x4},{b,2,x4},{c,3,x4}],
+ L21 = [{a,1,x3},{b,2,x3},{c,3,x3}],
+ L31 = [{a,1,x2},{b,2,x2},{c,3,x2}],
+ L41 = [{a,1,x1},{b,2,x1},{c,3,x1}],
+ All =
[rev(L11, Args), rev(L21, Args), rev(L31, Args), rev(L41, Args)],
- ?line Merged1 = lists:keymerge(2, L11, L21),
- ?line Merged2 = lists:keymerge(2, L31, L41),
- ?line Merged = rev(lists:keymerge(2, Merged1, Merged2), Args),
- ?line Fs1 = to_files(All, Fmt, Config),
- ?line ok = file_sorter:keymerge(2, Fs1, Foo, Args),
- ?line Merged = from_files(Foo, Fmt),
+ Merged1 = lists:keymerge(2, L11, L21),
+ Merged2 = lists:keymerge(2, L31, L41),
+ Merged = rev(lists:keymerge(2, Merged1, Merged2), Args),
+ Fs1 = to_files(All, Fmt, Config),
+ ok = file_sorter:keymerge(2, Fs1, Foo, Args),
+ Merged = from_files(Foo, Fmt),
fun() ->
- UArgs = [{unique,true} | Args],
- ?line UMerged1 = lists:ukeymerge(2, L11, L21),
- ?line UMerged2 = lists:ukeymerge(2, L31, L41),
- ?line UMerged = rev(lists:ukeymerge(2, UMerged1, UMerged2), Args),
- ?line ok = file_sorter:keymerge(2, Fs1, Foo, UArgs),
- ?line UMerged = from_files(Foo, Fmt),
- UArgs2 = make_args(Fmt, [{unique,true}, {size,50} | XArgs]),
- ?line ok = file_sorter:keymerge(2, Fs1, Foo, UArgs2),
- ?line UMerged = from_files(Foo, Fmt),
- ?line List = rev([{a,1,x4},{b,2,x4},{c,3,x4}], Args),
- ?line FsL = to_files([List], Fmt, Config),
- ?line ok = file_sorter:keymerge(2, FsL, Foo, UArgs),
- ?line List = from_files(Foo, Fmt),
- ?line List1 = [{a,1,x4},{b,2,x4},{c,3,x4}],
- ?line List2 = [{a,3,x4},{b,4,x4},{c,5,x4}],
- ?line FsLL = to_files([rev(List1, Args), rev(List2, Args)], Fmt, Config),
- ?line ok = file_sorter:keymerge(2, FsLL, Foo, UArgs),
- ?line List1_2 = rev(lists:ukeymerge(2, List1, List2), Args),
- ?line List1_2 = from_files(Foo, Fmt),
- ?line delete_files(Foo)
+ UArgs = [{unique,true} | Args],
+ UMerged1 = lists:ukeymerge(2, L11, L21),
+ UMerged2 = lists:ukeymerge(2, L31, L41),
+ UMerged = rev(lists:ukeymerge(2, UMerged1, UMerged2), Args),
+ ok = file_sorter:keymerge(2, Fs1, Foo, UArgs),
+ UMerged = from_files(Foo, Fmt),
+ UArgs2 = make_args(Fmt, [{unique,true}, {size,50} | XArgs]),
+ ok = file_sorter:keymerge(2, Fs1, Foo, UArgs2),
+ UMerged = from_files(Foo, Fmt),
+ List = rev([{a,1,x4},{b,2,x4},{c,3,x4}], Args),
+ FsL = to_files([List], Fmt, Config),
+ ok = file_sorter:keymerge(2, FsL, Foo, UArgs),
+ List = from_files(Foo, Fmt),
+ List1 = [{a,1,x4},{b,2,x4},{c,3,x4}],
+ List2 = [{a,3,x4},{b,4,x4},{c,5,x4}],
+ FsLL = to_files([rev(List1, Args), rev(List2, Args)], Fmt, Config),
+ ok = file_sorter:keymerge(2, FsLL, Foo, UArgs),
+ List1_2 = rev(lists:ukeymerge(2, List1, List2), Args),
+ List1_2 = from_files(Foo, Fmt),
+ delete_files(Foo)
end(),
%% Input is files. Output is a fun.
- ?line Fs3 = to_files(All, Fmt, Config),
- ?line [] = file_sorter:keysort(2, [], output([], Fmt), Args),
- ?line KS1 = file_sorter:keymerge(2, Fs3, output([], Fmt), Args),
- ?line Merged = KS1,
- ?line delete_files([Foo | Fs3]),
-
- ?line L2 = [[{a,1}],[{a,2}],[{a,3}],[{a,4}],[{a,5}],[{a,6}],[{a,7}]],
- ?line Fs2 = to_files(L2, Fmt, Config),
- ?line M = file_sorter:keymerge(1, Fs2, output([], Fmt), Args),
- ?line M = rev(lists:append(L2), Args),
- ?line delete_files(Fs2),
-
- ?line LL1 = [{d,4},{e,5},{f,6}],
- ?line LL2 = [{a,1},{b,2},{c,3}],
- ?line LL3 = [{j,10},{k,11},{l,12}],
- ?line LL4 = [{g,7},{h,8},{i,9}],
- ?line LL5 = [{p,16},{q,17},{r,18}],
- ?line LL6 = [{m,13},{n,14},{o,15}],
- ?line LLAll = [rev(LL1, Args),rev(LL2, Args),rev(LL3, Args),
- rev(LL4, Args),rev(LL5, Args),rev(LL6, Args)],
- ?line FsLL6 = to_files(LLAll, Fmt, Config),
- ?line LL = rev(lists:sort(lists:append(LLAll)), Args),
- ?line ok = file_sorter:keymerge(1, FsLL6, Foo, Args),
- ?line LL = from_files(Foo, Fmt),
- ?line ok = file_sorter:keymerge(1, FsLL6, Foo, [{unique,true} | Args]),
- ?line LL = from_files(Foo, Fmt),
- ?line delete_files([Foo | FsLL6]),
+ Fs3 = to_files(All, Fmt, Config),
+ [] = file_sorter:keysort(2, [], output([], Fmt), Args),
+ KS1 = file_sorter:keymerge(2, Fs3, output([], Fmt), Args),
+ Merged = KS1,
+ delete_files([Foo | Fs3]),
+
+ L2 = [[{a,1}],[{a,2}],[{a,3}],[{a,4}],[{a,5}],[{a,6}],[{a,7}]],
+ Fs2 = to_files(L2, Fmt, Config),
+ M = file_sorter:keymerge(1, Fs2, output([], Fmt), Args),
+ M = rev(lists:append(L2), Args),
+ delete_files(Fs2),
+
+ LL1 = [{d,4},{e,5},{f,6}],
+ LL2 = [{a,1},{b,2},{c,3}],
+ LL3 = [{j,10},{k,11},{l,12}],
+ LL4 = [{g,7},{h,8},{i,9}],
+ LL5 = [{p,16},{q,17},{r,18}],
+ LL6 = [{m,13},{n,14},{o,15}],
+ LLAll = [rev(LL1, Args),rev(LL2, Args),rev(LL3, Args),
+ rev(LL4, Args),rev(LL5, Args),rev(LL6, Args)],
+ FsLL6 = to_files(LLAll, Fmt, Config),
+ LL = rev(lists:sort(lists:append(LLAll)), Args),
+ ok = file_sorter:keymerge(1, FsLL6, Foo, Args),
+ LL = from_files(Foo, Fmt),
+ ok = file_sorter:keymerge(1, FsLL6, Foo, [{unique,true} | Args]),
+ LL = from_files(Foo, Fmt),
+ delete_files([Foo | FsLL6]),
ok.
@@ -963,84 +902,84 @@ funmerge(Fmt, XArgs, Config) ->
UArgs = [{unique,true} | Args],
Foo = outfile(foo, Config),
- ?line EFs = to_files([[]], Fmt, Config),
- ?line ok = file_sorter:merge(EFs, Foo, UArgs),
- ?line [] = from_files(Foo, Fmt),
+ EFs = to_files([[]], Fmt, Config),
+ ok = file_sorter:merge(EFs, Foo, UArgs),
+ [] = from_files(Foo, Fmt),
delete_files([Foo | EFs]),
- ?line L11 = [{a,1,x4},{b,2,x4},{c,3,x4}],
- ?line L21 = [{a,1,x3},{b,2,x3},{c,3,x3}],
- ?line L31 = [{a,1,x2},{b,2,x2},{c,3,x2}],
- ?line L41 = [{a,1,x1},{b,2,x1},{c,3,x1}],
- ?line CAll = [L11, L21, L31, L41],
- ?line CMerged1 = lists:merge(KComp, L11, L21),
- ?line CMerged2 = lists:merge(KComp, L31, L41),
- ?line CMerged = lists:merge(KComp, CMerged1, CMerged2),
- ?line CFs1 = to_files(CAll, Fmt, Config),
- ?line ok = file_sorter:merge(CFs1, Foo, Args),
- ?line CMerged = from_files(Foo, Fmt),
+ L11 = [{a,1,x4},{b,2,x4},{c,3,x4}],
+ L21 = [{a,1,x3},{b,2,x3},{c,3,x3}],
+ L31 = [{a,1,x2},{b,2,x2},{c,3,x2}],
+ L41 = [{a,1,x1},{b,2,x1},{c,3,x1}],
+ CAll = [L11, L21, L31, L41],
+ CMerged1 = lists:merge(KComp, L11, L21),
+ CMerged2 = lists:merge(KComp, L31, L41),
+ CMerged = lists:merge(KComp, CMerged1, CMerged2),
+ CFs1 = to_files(CAll, Fmt, Config),
+ ok = file_sorter:merge(CFs1, Foo, Args),
+ CMerged = from_files(Foo, Fmt),
Args4 = make_args(Fmt, [{size,50} | XArgs]),
- ?line ok = file_sorter:merge(CFs1, Foo, [{order,KComp} | Args4]),
- ?line CMerged = from_files(Foo, Fmt),
-
- ?line UMerged1 = lists:umerge(KComp, L11, L21),
- ?line UMerged2 = lists:umerge(KComp, L31, L41),
- ?line UMerged = lists:umerge(KComp, UMerged1, UMerged2),
- ?line ok = file_sorter:merge(CFs1, Foo, [{order,KComp} | UArgs]),
- ?line UMerged = from_files(Foo, Fmt),
+ ok = file_sorter:merge(CFs1, Foo, [{order,KComp} | Args4]),
+ CMerged = from_files(Foo, Fmt),
+
+ UMerged1 = lists:umerge(KComp, L11, L21),
+ UMerged2 = lists:umerge(KComp, L31, L41),
+ UMerged = lists:umerge(KComp, UMerged1, UMerged2),
+ ok = file_sorter:merge(CFs1, Foo, [{order,KComp} | UArgs]),
+ UMerged = from_files(Foo, Fmt),
UArgs2 =
lists:keydelete(order, 1,
make_args(Fmt, [{unique,true}, {size,50} | XArgs])),
- ?line ok = file_sorter:merge(CFs1, Foo, [{order,KComp} | UArgs2]),
- ?line UMerged = from_files(Foo, Fmt),
- ?line delete_files(Foo),
-
- ?line List1 = [{a,1,x4},{b,2,x4},{c,3,x4}],
- ?line List2 = [{a,3,x4},{b,4,x4},{c,5,x4}],
- ?line List3 = [{a,5,x4},{b,6,x4},{c,7,x4}],
- ?line FsLL = to_files([List1, List2, List3], Fmt, Config),
- ?line ok = file_sorter:merge(FsLL, Foo, Args),
- ?line List1_2 = lists:merge(KComp,lists:merge(KComp,List1,List2),List3),
- ?line List1_2 = from_files(Foo, Fmt),
- ?line ok = file_sorter:merge(FsLL, Foo, [{order,KComp} | UArgs]),
- ?line UList1_2 =
+ ok = file_sorter:merge(CFs1, Foo, [{order,KComp} | UArgs2]),
+ UMerged = from_files(Foo, Fmt),
+ delete_files(Foo),
+
+ List1 = [{a,1,x4},{b,2,x4},{c,3,x4}],
+ List2 = [{a,3,x4},{b,4,x4},{c,5,x4}],
+ List3 = [{a,5,x4},{b,6,x4},{c,7,x4}],
+ FsLL = to_files([List1, List2, List3], Fmt, Config),
+ ok = file_sorter:merge(FsLL, Foo, Args),
+ List1_2 = lists:merge(KComp,lists:merge(KComp,List1,List2),List3),
+ List1_2 = from_files(Foo, Fmt),
+ ok = file_sorter:merge(FsLL, Foo, [{order,KComp} | UArgs]),
+ UList1_2 =
lists:umerge(KComp,lists:umerge(KComp, List1, List2),List3),
- ?line UList1_2 = from_files(Foo, Fmt),
- ?line delete_files([Foo | CFs1]),
+ UList1_2 = from_files(Foo, Fmt),
+ delete_files([Foo | CFs1]),
fun() ->
- ?line LL1 = [{d,4},{e,5},{f,6}],
- ?line LL2 = [{a,1},{b,2},{c,3}],
- ?line LL3 = [{j,10},{k,11},{l,12}],
- ?line LL4 = [{g,7},{h,8},{i,9}],
- ?line LL5 = [{p,16},{q,17},{r,18}],
- ?line LL6 = [{m,13},{n,14},{o,15}],
- ?line LLAll = [LL1,LL2,LL3,LL4,LL5,LL6],
- ?line FsLL6 = to_files(LLAll, Fmt, Config),
- ?line LL = lists:sort(lists:append(LLAll)),
- ?line ok = file_sorter:merge(FsLL6, Foo, Args),
- ?line LL = from_files(Foo, Fmt),
- ?line ok = file_sorter:merge(FsLL6, Foo, UArgs),
- ?line LL = from_files(Foo, Fmt),
- ?line delete_files([Foo | FsLL6])
+ LL1 = [{d,4},{e,5},{f,6}],
+ LL2 = [{a,1},{b,2},{c,3}],
+ LL3 = [{j,10},{k,11},{l,12}],
+ LL4 = [{g,7},{h,8},{i,9}],
+ LL5 = [{p,16},{q,17},{r,18}],
+ LL6 = [{m,13},{n,14},{o,15}],
+ LLAll = [LL1,LL2,LL3,LL4,LL5,LL6],
+ FsLL6 = to_files(LLAll, Fmt, Config),
+ LL = lists:sort(lists:append(LLAll)),
+ ok = file_sorter:merge(FsLL6, Foo, Args),
+ LL = from_files(Foo, Fmt),
+ ok = file_sorter:merge(FsLL6, Foo, UArgs),
+ LL = from_files(Foo, Fmt),
+ delete_files([Foo | FsLL6])
end(),
fun() ->
- ?line RLL1 = [{b,2},{h,8},{n,14}],
- ?line RLL2 = [{a,1},{g,7},{m,13}],
- ?line RLL3 = [{d,4},{j,10},{p,16}],
- ?line RLL4 = [{c,3},{i,9},{o,15}],
- ?line RLL5 = [{f,6},{l,12},{r,18}],
- ?line RLL6 = [{e,5},{k,11},{q,17}],
- ?line RLLAll = [RLL1,RLL2,RLL3,RLL4,RLL5,RLL6],
- ?line RFsLL6 = to_files(RLLAll, Fmt, Config),
- ?line RLL = lists:sort(lists:append(RLLAll)),
- ?line ok = file_sorter:merge(RFsLL6, Foo, Args),
- ?line RLL = from_files(Foo, Fmt),
- ?line ok = file_sorter:merge(RFsLL6, Foo, UArgs),
- ?line RLL = from_files(Foo, Fmt),
- ?line delete_files([Foo | RFsLL6])
+ RLL1 = [{b,2},{h,8},{n,14}],
+ RLL2 = [{a,1},{g,7},{m,13}],
+ RLL3 = [{d,4},{j,10},{p,16}],
+ RLL4 = [{c,3},{i,9},{o,15}],
+ RLL5 = [{f,6},{l,12},{r,18}],
+ RLL6 = [{e,5},{k,11},{q,17}],
+ RLLAll = [RLL1,RLL2,RLL3,RLL4,RLL5,RLL6],
+ RFsLL6 = to_files(RLLAll, Fmt, Config),
+ RLL = lists:sort(lists:append(RLLAll)),
+ ok = file_sorter:merge(RFsLL6, Foo, Args),
+ RLL = from_files(Foo, Fmt),
+ ok = file_sorter:merge(RFsLL6, Foo, UArgs),
+ RLL = from_files(Foo, Fmt),
+ delete_files([Foo | RFsLL6])
end(),
ok.
@@ -1054,57 +993,57 @@ check(Fmt, Config) ->
L1 = [3,1,2,5,4],
[F1_0] = Fs1 = to_files([L1], Fmt, Config),
F1 = filename:absname(F1_0),
- ?line {ok, [{F1,2,1}]} = file_sorter:check(Fs1, Args),
- ?line {ok, [{F1,2,1}]} = file_sorter:check(Fs1, [{order,Fun} | Args]),
- ?line {ok, [{F1,2,1}]} = file_sorter:check(Fs1, [{unique,true} | Args]),
- ?line {ok, [{F1,2,1}]} =
+ {ok, [{F1,2,1}]} = file_sorter:check(Fs1, Args),
+ {ok, [{F1,2,1}]} = file_sorter:check(Fs1, [{order,Fun} | Args]),
+ {ok, [{F1,2,1}]} = file_sorter:check(Fs1, [{unique,true} | Args]),
+ {ok, [{F1,2,1}]} =
file_sorter:check(Fs1, [{order,Fun},{unique,true} | Args]),
- ?line {ok, [{F1,3,2}]} =
+ {ok, [{F1,3,2}]} =
file_sorter:check(Fs1, [{order,descending} | Args]),
- ?line {ok, [{F1,3,2}]} =
+ {ok, [{F1,3,2}]} =
file_sorter:check(Fs1, [{unique,true},{order,descending} | Args]),
- ?line delete_files(Fs1),
-
+ delete_files(Fs1),
+
L2 = [[1,2,2,3,3,4,5,5],[5,5,4,3,3,2,2,1]],
[F2_0,F3_0] = Fs2 = to_files(L2, Fmt, Config),
F2 = filename:absname(F2_0),
F3 = filename:absname(F3_0),
- ?line {ok, [{F3,3,4}]} = file_sorter:check(Fs2, Args),
- ?line {ok, [{F3,3,4}]} = file_sorter:check(Fs2, [{order,Fun} | Args]),
- ?line {ok, [{F2,3,2},{F3,2,5}]} =
+ {ok, [{F3,3,4}]} = file_sorter:check(Fs2, Args),
+ {ok, [{F3,3,4}]} = file_sorter:check(Fs2, [{order,Fun} | Args]),
+ {ok, [{F2,3,2},{F3,2,5}]} =
file_sorter:check(Fs2, [{unique, true} | Args]),
- ?line {ok, [{F2,3,2},{F3,2,5}]} =
+ {ok, [{F2,3,2},{F3,2,5}]} =
file_sorter:check(Fs2, [{order,Fun},{unique, true} | Args]),
- ?line {ok, [{F2,2,2}]} =
+ {ok, [{F2,2,2}]} =
file_sorter:check(Fs2, [{order,descending} | Args]),
- ?line {ok, [{F2,2,2},{F3,2,5}]} =
+ {ok, [{F2,2,2},{F3,2,5}]} =
file_sorter:check(Fs2, [{unique,true},{order,descending} | Args]),
- ?line delete_files(Fs2),
-
+ delete_files(Fs2),
+
L3 = [1,2,3,4],
- ?line Fs3 = to_files([L3], Fmt, Config),
- ?line {ok, []} = file_sorter:check(Fs3, [{unique,true} | Args]),
- ?line {ok, []} =
+ Fs3 = to_files([L3], Fmt, Config),
+ {ok, []} = file_sorter:check(Fs3, [{unique,true} | Args]),
+ {ok, []} =
file_sorter:check(Fs3, [{unique,true},{order,Fun} | Args]),
- ?line delete_files(Fs3),
+ delete_files(Fs3),
%% big objects
- ?line T1 = erlang:make_tuple(10000,foo),
- ?line T2 = erlang:make_tuple(10000,bar),
- ?line L4 = [T1,T2],
- ?line [FF_0] = Fs4 = to_files([L4], Fmt, Config),
+ T1 = erlang:make_tuple(10000,foo),
+ T2 = erlang:make_tuple(10000,bar),
+ L4 = [T1,T2],
+ [FF_0] = Fs4 = to_files([L4], Fmt, Config),
FF = filename:absname(FF_0),
- ?line {ok, [{FF,2,T2}]} = file_sorter:check(Fs4, [{unique,true} | Args]),
- ?line delete_files(Fs4),
+ {ok, [{FF,2,T2}]} = file_sorter:check(Fs4, [{unique,true} | Args]),
+ delete_files(Fs4),
CFun = key_compare(2),
L10 = [[{1,a},{2,b},T10_1={1,b},{3,c}], [{1,b},T10_2={2,a}]],
[F10_0,F11_0] = Fs10 = to_files(L10, Fmt, Config),
F10_1 = filename:absname(F10_0),
F11_1 = filename:absname(F11_0),
- ?line {ok, [{F10_1,3,T10_1},{F11_1,2,T10_2}]} =
+ {ok, [{F10_1,3,T10_1},{F11_1,2,T10_2}]} =
file_sorter:check(Fs10, [{unique,true},{order,CFun} | Args]),
- ?line delete_files(Fs10),
+ delete_files(Fs10),
ok.
@@ -1112,31 +1051,31 @@ keycheck(Fmt, Config) ->
Args0 = make_args(Fmt, [{size,5}]),
Args = Args0 ++ [{tmpdir,?privdir(Config)}],
- ?line L1 = [[{a,1},{b,2}], [{c,2},{b,1},{a,3}]],
- ?line [F1_0,F2_0] = Fs1 = to_files(L1, Fmt, Config),
+ L1 = [[{a,1},{b,2}], [{c,2},{b,1},{a,3}]],
+ [F1_0,F2_0] = Fs1 = to_files(L1, Fmt, Config),
F1 = filename:absname(F1_0),
F2 = filename:absname(F2_0),
- ?line {ok, [{F2,2,{b,1}}]} = file_sorter:keycheck(1, Fs1, Args),
- ?line {ok, [{F2,2,{b,1}}]} =
+ {ok, [{F2,2,{b,1}}]} = file_sorter:keycheck(1, Fs1, Args),
+ {ok, [{F2,2,{b,1}}]} =
file_sorter:keycheck(1, Fs1, [{unique,true} | Args]),
- ?line {ok, [{F1,2,{b,2}}]} =
+ {ok, [{F1,2,{b,2}}]} =
file_sorter:keycheck(1, Fs1, [{order,descending},{unique,true} | Args]),
- ?line delete_files(Fs1),
-
+ delete_files(Fs1),
+
L2 = [[{a,1},{a,2},{a,2},{b,2}], [{c,2},{b,1},{b,2},{b,2},{a,3}]],
- ?line [F3_0,F4_0] = Fs2 = to_files(L2, Fmt, Config),
+ [F3_0,F4_0] = Fs2 = to_files(L2, Fmt, Config),
F3 = filename:absname(F3_0),
F4 = filename:absname(F4_0),
- ?line {ok, [{F4,2,{b,1}}]} = file_sorter:keycheck(1, Fs2, Args),
- ?line {ok, [{F3,2,{a,2}},{F4,2,{b,1}}]} =
+ {ok, [{F4,2,{b,1}}]} = file_sorter:keycheck(1, Fs2, Args),
+ {ok, [{F3,2,{a,2}},{F4,2,{b,1}}]} =
file_sorter:keycheck(1, Fs2, [{unique,true} | Args]),
- ?line {ok, [{F3,4,{b,2}}]} =
+ {ok, [{F3,4,{b,2}}]} =
file_sorter:keycheck(1, Fs2, [{order,descending} | Args]),
- ?line {ok, [{F3,2,{a,2}},{F4,3,{b,2}}]} =
+ {ok, [{F3,2,{a,2}},{F4,3,{b,2}}]} =
file_sorter:keycheck(1, Fs2,
[{order,descending},{unique,true} | Args]),
- ?line delete_files(Fs2),
-
+ delete_files(Fs2),
+
ok.
rev(L, Args) ->
@@ -1330,9 +1269,9 @@ c(Fd, Bin0, Size0, NoBytes, HL, L) ->
eof when Size0 =:= 0 ->
lists:reverse(L);
eof ->
- test_server:fail({error, premature_eof});
+ ct:fail({error, premature_eof});
Error ->
- test_server:fail(Error)
+ ct:fail(Error)
end.
c1(Fd, B, BinSize, HL, L) ->
@@ -1347,7 +1286,7 @@ c1(Fd, B, BinSize, HL, L) ->
<<BinTerm:Size/binary, R/binary>> = Bin,
E = case catch binary_to_term(BinTerm) of
{'EXIT', _} ->
- test_server:fail({error, bad_object});
+ ct:fail({error, bad_object});
Term ->
Term
end,
diff --git a/lib/stdlib/test/filelib_SUITE.erl b/lib/stdlib/test/filelib_SUITE.erl
index 01b798faef..16616a3207 100644
--- a/lib/stdlib/test/filelib_SUITE.erl
+++ b/lib/stdlib/test/filelib_SUITE.erl
@@ -29,19 +29,18 @@
-import(lists, [foreach/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?t:minutes(5)),
- [{watchdog,Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,5}}].
all() ->
[wildcard_one, wildcard_two, wildcard_errors,
@@ -65,14 +64,14 @@ end_per_group(_GroupName, Config) ->
wildcard_one(Config) when is_list(Config) ->
- ?line {ok,OldCwd} = file:get_cwd(),
- ?line Dir = filename:join(?config(priv_dir, Config), "wildcard_one"),
- ?line ok = file:make_dir(Dir),
+ {ok,OldCwd} = file:get_cwd(),
+ Dir = filename:join(proplists:get_value(priv_dir, Config), "wildcard_one"),
+ ok = file:make_dir(Dir),
do_wildcard_1(Dir,
fun(Wc) ->
filelib:wildcard(Wc, Dir, erl_prim_loader)
end),
- ?line file:set_cwd(Dir),
+ file:set_cwd(Dir),
do_wildcard_1(Dir,
fun(Wc) ->
L = filelib:wildcard(Wc),
@@ -81,30 +80,30 @@ wildcard_one(Config) when is_list(Config) ->
L = filelib:wildcard(Wc, Dir),
L = filelib:wildcard(Wc, Dir++"/.")
end),
- ?line file:set_cwd(OldCwd),
- ?line ok = file:del_dir(Dir),
+ file:set_cwd(OldCwd),
+ ok = file:del_dir(Dir),
ok.
wildcard_two(Config) when is_list(Config) ->
- ?line Dir = filename:join(?config(priv_dir, Config), "wildcard_two"),
- ?line ok = file:make_dir(Dir),
- ?line do_wildcard_1(Dir, fun(Wc) -> io:format("~p~n",[{Wc,Dir, X = filelib:wildcard(Wc, Dir)}]),X end),
- ?line do_wildcard_1(Dir, fun(Wc) -> filelib:wildcard(Wc, Dir++"/") end),
- ?line do_wildcard_1(Dir, fun(Wc) -> filelib:wildcard(Wc, Dir++"/.") end),
+ Dir = filename:join(proplists:get_value(priv_dir, Config), "wildcard_two"),
+ ok = file:make_dir(Dir),
+ do_wildcard_1(Dir, fun(Wc) -> io:format("~p~n",[{Wc,Dir, X = filelib:wildcard(Wc, Dir)}]),X end),
+ do_wildcard_1(Dir, fun(Wc) -> filelib:wildcard(Wc, Dir++"/") end),
+ do_wildcard_1(Dir, fun(Wc) -> filelib:wildcard(Wc, Dir++"/.") end),
case os:type() of
{win32,_} ->
ok;
_ ->
- ?line do_wildcard_1(Dir, fun(Wc) -> filelib:wildcard(Wc, "//"++Dir) end)
+ do_wildcard_1(Dir, fun(Wc) -> filelib:wildcard(Wc, "//"++Dir) end)
end,
- ?line ok = file:del_dir(Dir),
+ ok = file:del_dir(Dir),
ok.
wildcard_errors(Config) when is_list(Config) ->
- ?line wcc("{", missing_delimiter),
- ?line wcc("{a", missing_delimiter),
- ?line wcc("{a,", missing_delimiter),
- ?line wcc("{a,b", missing_delimiter),
+ wcc("{", missing_delimiter),
+ wcc("{a", missing_delimiter),
+ wcc("{a,", missing_delimiter),
+ wcc("{a,b", missing_delimiter),
ok.
wcc(Wc, Error) ->
@@ -131,70 +130,70 @@ subtract_dir("/"++Cs, []) -> Cs.
do_wildcard_2(Dir, Wcf) ->
%% Basic wildcards.
All = ["abc","abcdef","glurf"],
- ?line Files = mkfiles(lists:reverse(All), Dir),
- ?line All = Wcf("*"),
- ?line ["abc","abcdef"] = Wcf("a*"),
- ?line ["abc","abcdef"] = Wcf("abc*"),
- ?line ["abcdef"] = Wcf("abc???"),
- ?line ["abcdef"] = Wcf("abcd*"),
- ?line ["abcdef"] = Wcf("*def"),
- ?line ["abcdef","glurf"] = Wcf("{*def,gl*}"),
- ?line ["abc","abcdef"] = Wcf("a*{def,}"),
- ?line ["abc","abcdef"] = Wcf("a*{,def}"),
+ Files = mkfiles(lists:reverse(All), Dir),
+ All = Wcf("*"),
+ ["abc","abcdef"] = Wcf("a*"),
+ ["abc","abcdef"] = Wcf("abc*"),
+ ["abcdef"] = Wcf("abc???"),
+ ["abcdef"] = Wcf("abcd*"),
+ ["abcdef"] = Wcf("*def"),
+ ["abcdef","glurf"] = Wcf("{*def,gl*}"),
+ ["abc","abcdef"] = Wcf("a*{def,}"),
+ ["abc","abcdef"] = Wcf("a*{,def}"),
%% Constant wildcard.
["abcdef"] = Wcf("abcdef"),
%% Negative tests.
- ?line [] = Wcf("b*"),
- ?line [] = Wcf("bufflig"),
+ [] = Wcf("b*"),
+ [] = Wcf("bufflig"),
- ?line del(Files),
+ del(Files),
do_wildcard_3(Dir, Wcf).
-
+
do_wildcard_3(Dir, Wcf) ->
%% Some character sets.
All = ["a01","a02","a03","b00","c02","d19"],
- ?line Files = mkfiles(lists:reverse(All), Dir),
- ?line All = Wcf("[a-z]*"),
- ?line All = Wcf("[a-d]*"),
- ?line All = Wcf("[adbc]*"),
- ?line All = Wcf("?[0-9][0-9]"),
- ?line All = Wcf("?[0-1][0-39]"),
- ?line All = Wcf("[abcdefgh][10][01239]"),
- ?line ["a01","a02","a03","b00","c02"] = Wcf("[a-z]0[0-3]"),
- ?line [] = Wcf("?[a-z][0-39]"),
- ?line del(Files),
+ Files = mkfiles(lists:reverse(All), Dir),
+ All = Wcf("[a-z]*"),
+ All = Wcf("[a-d]*"),
+ All = Wcf("[adbc]*"),
+ All = Wcf("?[0-9][0-9]"),
+ All = Wcf("?[0-1][0-39]"),
+ All = Wcf("[abcdefgh][10][01239]"),
+ ["a01","a02","a03","b00","c02"] = Wcf("[a-z]0[0-3]"),
+ [] = Wcf("?[a-z][0-39]"),
+ del(Files),
do_wildcard_4(Dir, Wcf).
do_wildcard_4(Dir, Wcf) ->
%% More character sets: tricky characters.
All = ["a-","aA","aB","aC","a[","a]"],
- ?line Files = mkfiles(lists:reverse(All), Dir),
- ?line All = Wcf("a[][A-C-]"),
+ Files = mkfiles(lists:reverse(All), Dir),
+ All = Wcf("a[][A-C-]"),
["a-"] = Wcf("a[-]"),
["a["] = Wcf("a["),
- ?line del(Files),
+ del(Files),
do_wildcard_5(Dir, Wcf).
do_wildcard_5(Dir, Wcf) ->
Dirs = ["xa","blurf","yyy"],
- ?line foreach(fun(D) -> ok = file:make_dir(filename:join(Dir, D)) end, Dirs),
+ foreach(fun(D) -> ok = file:make_dir(filename:join(Dir, D)) end, Dirs),
All = ["blurf/nisse","xa/arne","xa/kalle","yyy/arne"],
- ?line Files = mkfiles(lists:reverse(All), Dir),
+ Files = mkfiles(lists:reverse(All), Dir),
%% Test.
- ?line All = Wcf("*/*"),
- ?line ["blurf/nisse","xa/arne","xa/kalle"] = Wcf("{blurf,xa}/*"),
- ?line ["xa/arne","yyy/arne"] = Wcf("*/arne"),
- ?line ["blurf/nisse"] = Wcf("*/nisse"),
- ?line [] = Wcf("mountain/*"),
- ?line [] = Wcf("xa/gurka"),
+ All = Wcf("*/*"),
+ ["blurf/nisse","xa/arne","xa/kalle"] = Wcf("{blurf,xa}/*"),
+ ["xa/arne","yyy/arne"] = Wcf("*/arne"),
+ ["blurf/nisse"] = Wcf("*/nisse"),
+ [] = Wcf("mountain/*"),
+ [] = Wcf("xa/gurka"),
["blurf/nisse"] = Wcf("blurf/nisse"),
%% Cleanup
- ?line del(Files),
- ?line foreach(fun(D) -> ok = file:del_dir(filename:join(Dir, D)) end, Dirs),
+ del(Files),
+ foreach(fun(D) -> ok = file:del_dir(filename:join(Dir, D)) end, Dirs),
do_wildcard_6(Dir, Wcf).
do_wildcard_6(Dir, Wcf) ->
@@ -271,45 +270,45 @@ do_wildcard_9(Dir, Wcf) ->
fold_files(Config) when is_list(Config) ->
- ?line Dir = filename:join(?config(priv_dir, Config), "fold_files"),
- ?line ok = file:make_dir(Dir),
- ?line Dirs = [filename:join(Dir, D) || D <- ["blurf","blurf/blarf"]],
- ?line foreach(fun(D) -> ok = file:make_dir(D) end, Dirs),
+ Dir = filename:join(proplists:get_value(priv_dir, Config), "fold_files"),
+ ok = file:make_dir(Dir),
+ Dirs = [filename:join(Dir, D) || D <- ["blurf","blurf/blarf"]],
+ foreach(fun(D) -> ok = file:make_dir(D) end, Dirs),
All = ["fb.txt","ko.txt",
"blurf/nisse.text","blurf/blarf/aaa.txt","blurf/blarf/urfa.txt"],
- ?line Files = mkfiles(lists:reverse(All), Dir),
+ Files = mkfiles(lists:reverse(All), Dir),
%% Test.
- ?line Files0 = filelib:fold_files(Dir, "^", false,
- fun(H, T) -> [H|T] end, []),
- ?line same_lists(["fb.txt","ko.txt"], Files0, Dir),
+ Files0 = filelib:fold_files(Dir, "^", false,
+ fun(H, T) -> [H|T] end, []),
+ same_lists(["fb.txt","ko.txt"], Files0, Dir),
- ?line Files1 = filelib:fold_files(Dir, "^", true,
- fun(H, T) -> [H|T] end, []),
- ?line same_lists(All, Files1, Dir),
+ Files1 = filelib:fold_files(Dir, "^", true,
+ fun(H, T) -> [H|T] end, []),
+ same_lists(All, Files1, Dir),
- ?line Files2 = filelib:fold_files(Dir, "[.]text$", true,
- fun(H, T) -> [H|T] end, []),
- ?line same_lists(["blurf/nisse.text"], Files2, Dir),
+ Files2 = filelib:fold_files(Dir, "[.]text$", true,
+ fun(H, T) -> [H|T] end, []),
+ same_lists(["blurf/nisse.text"], Files2, Dir),
- ?line Files3 = filelib:fold_files(Dir, "^..[.]", true,
- fun(H, T) -> [H|T] end, []),
- ?line same_lists(["fb.txt","ko.txt"], Files3, Dir),
+ Files3 = filelib:fold_files(Dir, "^..[.]", true,
+ fun(H, T) -> [H|T] end, []),
+ same_lists(["fb.txt","ko.txt"], Files3, Dir),
- ?line Files4 = filelib:fold_files(Dir, "^ko[.]txt$", true,
- fun(H, T) -> [H|T] end, []),
- ?line same_lists(["ko.txt"], Files4, Dir),
- ?line Files4 = filelib:fold_files(Dir, "^ko[.]txt$", false,
- fun(H, T) -> [H|T] end, []),
+ Files4 = filelib:fold_files(Dir, "^ko[.]txt$", true,
+ fun(H, T) -> [H|T] end, []),
+ same_lists(["ko.txt"], Files4, Dir),
+ Files4 = filelib:fold_files(Dir, "^ko[.]txt$", false,
+ fun(H, T) -> [H|T] end, []),
- ?line [] = filelib:fold_files(Dir, "^$", true,
- fun(H, T) -> [H|T] end, []),
+ [] = filelib:fold_files(Dir, "^$", true,
+ fun(H, T) -> [H|T] end, []),
%% Cleanup
- ?line del(Files),
- ?line foreach(fun(D) -> ok = file:del_dir(D) end, lists:reverse(Dirs)),
- ?line ok = file:del_dir(Dir).
+ del(Files),
+ foreach(fun(D) -> ok = file:del_dir(D) end, lists:reverse(Dirs)),
+ ok = file:del_dir(Dir).
same_lists(Expected0, Actual0, BaseDir) ->
Expected = [filename:absname(N, BaseDir) || N <- lists:sort(Expected0)],
@@ -318,7 +317,7 @@ same_lists(Expected0, Actual0, BaseDir) ->
mkfiles([H|T], Dir) ->
Name = filename:join(Dir, H),
- Garbage = [31+random:uniform(95) || _ <- lists:seq(1, random:uniform(1024))],
+ Garbage = [31+rand:uniform(95) || _ <- lists:seq(1, rand:uniform(1024))],
file:write_file(Name, Garbage),
[Name|mkfiles(T, Dir)];
mkfiles([], _) -> [].
@@ -328,52 +327,49 @@ del([H|T]) ->
del(T);
del([]) -> ok.
-otp_5960(suite) ->
- [];
-otp_5960(doc) ->
- ["Test that filelib:ensure_dir/1 returns ok or {error,Reason}"];
+%% Test that filelib:ensure_dir/1 returns ok or {error,Reason}.
otp_5960(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Dir = filename:join(PrivDir, "otp_5960_dir"),
- ?line Name1 = filename:join(Dir, name1),
- ?line Name2 = filename:join(Dir, name2),
- ?line ok = filelib:ensure_dir(Name1), % parent is created
- ?line ok = filelib:ensure_dir(Name1), % repeating it should be OK
- ?line ok = filelib:ensure_dir(Name2), % parent already exists
- ?line ok = filelib:ensure_dir(Name2), % repeating it should be OK
- ?line Name3 = filename:join(Name1, name3),
- ?line {ok, FileInfo} = file:read_file_info(Dir),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Dir = filename:join(PrivDir, "otp_5960_dir"),
+ Name1 = filename:join(Dir, name1),
+ Name2 = filename:join(Dir, name2),
+ ok = filelib:ensure_dir(Name1), % parent is created
+ ok = filelib:ensure_dir(Name1), % repeating it should be OK
+ ok = filelib:ensure_dir(Name2), % parent already exists
+ ok = filelib:ensure_dir(Name2), % repeating it should be OK
+ Name3 = filename:join(Name1, name3),
+ {ok, FileInfo} = file:read_file_info(Dir),
case os:type() of
{win32,_} ->
%% Not possibly to write protect directories on Windows
%% (at least not using file:write_file_info/2).
ok;
_ ->
- ?line Mode = FileInfo#file_info.mode,
- ?line NoWriteMode = Mode - 8#00200 - 8#00020 - 8#00002,
- ?line ok = file:write_file_info(Dir, #file_info{mode=NoWriteMode}),
- ?line {error, _} = filelib:ensure_dir(Name3),
- ?line ok = file:write_file_info(Dir, #file_info{mode=Mode}),
+ Mode = FileInfo#file_info.mode,
+ NoWriteMode = Mode - 8#00200 - 8#00020 - 8#00002,
+ ok = file:write_file_info(Dir, #file_info{mode=NoWriteMode}),
+ {error, _} = filelib:ensure_dir(Name3),
+ ok = file:write_file_info(Dir, #file_info{mode=Mode}),
ok
end.
ensure_dir_eexist(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Dir = filename:join(PrivDir, "ensure_dir_eexist"),
- ?line Name = filename:join(Dir, "same_name_as_file_and_dir"),
- ?line ok = filelib:ensure_dir(Name),
- ?line ok = file:write_file(Name, <<"some string\n">>),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Dir = filename:join(PrivDir, "ensure_dir_eexist"),
+ Name = filename:join(Dir, "same_name_as_file_and_dir"),
+ ok = filelib:ensure_dir(Name),
+ ok = file:write_file(Name, <<"some string\n">>),
%% There already is a file with the name of the directory
%% we want to create.
- ?line NeedFile = filename:join(Name, "file"),
- ?line NeedFileB = filename:join(Name, <<"file">>),
- ?line {error, eexist} = filelib:ensure_dir(NeedFile),
- ?line {error, eexist} = filelib:ensure_dir(NeedFileB),
+ NeedFile = filename:join(Name, "file"),
+ NeedFileB = filename:join(Name, <<"file">>),
+ {error, eexist} = filelib:ensure_dir(NeedFile),
+ {error, eexist} = filelib:ensure_dir(NeedFileB),
ok.
ensure_dir_symlink(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Dir = filename:join(PrivDir, "ensure_dir_symlink"),
Name = filename:join(Dir, "same_name_as_file_and_dir"),
ok = filelib:ensure_dir(Name),
@@ -392,7 +388,7 @@ ensure_dir_symlink(Config) when is_list(Config) ->
end.
wildcard_symlink(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Dir = filename:join(PrivDir, ?MODULE_STRING++"_wildcard_symlink"),
SubDir = filename:join(Dir, "sub"),
AFile = filename:join(SubDir, "a_file"),
@@ -452,7 +448,7 @@ basenames(Dir, Files) ->
end || F <- Files].
is_file_symlink(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Dir = filename:join(PrivDir, ?MODULE_STRING++"_is_file_symlink"),
SubDir = filename:join(Dir, "sub"),
AFile = filename:join(SubDir, "a_file"),
@@ -485,7 +481,7 @@ is_file_symlink(Config) ->
end.
file_props_symlink(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Dir = filename:join(PrivDir, ?MODULE_STRING++"_file_props_symlink"),
AFile = filename:join(Dir, "a_file"),
Alias = filename:join(Dir, "symlink"),
diff --git a/lib/stdlib/test/filename_SUITE.erl b/lib/stdlib/test/filename_SUITE.erl
index fd47da8150..3d6734b790 100644
--- a/lib/stdlib/test/filename_SUITE.erl
+++ b/lib/stdlib/test/filename_SUITE.erl
@@ -28,21 +28,31 @@
basename_bin_1/1, basename_bin_2/1,
dirname_bin/1, extension_bin/1, join_bin/1, t_nativename_bin/1]).
-export([pathtype_bin/1,rootname_bin/1,split_bin/1]).
+-export([t_basedir_api/1, t_basedir_xdg/1, t_basedir_windows/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
- [absname, absname_2, basename_1, basename_2, dirname,
- extension,
- join, pathtype, rootname, split, t_nativename, find_src,
- absname_bin, absname_bin_2, basename_bin_1, basename_bin_2, dirname_bin,
- extension_bin,
- join_bin, pathtype_bin, rootname_bin, split_bin, t_nativename_bin].
+ [absname, absname_2,
+ find_src,
+ absname_bin, absname_bin_2,
+ {group,p},
+ t_basedir_xdg, t_basedir_windows].
groups() ->
- [].
+ [{p, [parallel],
+ [dirname,
+ extension, extension_bin,
+ join, pathtype, rootname, split, t_nativename,
+ basename_1, basename_2,
+ basename_bin_1, basename_bin_2, dirname_bin,
+ join_bin, pathtype_bin, rootname_bin, split_bin,
+ t_nativename_bin,
+ t_basedir_api]}].
init_per_suite(Config) ->
Config.
@@ -61,67 +71,59 @@ end_per_group(_GroupName, Config) ->
absname(Config) when is_list(Config) ->
case os:type() of
- {win32, _} ->
- ?line [Drive|_] = ?config(priv_dir, Config),
- ?line Temp = filename:join([Drive|":/"], "temp"),
- ?line case file:make_dir(Temp) of
- ok -> ok;
- {error,eexist} -> ok
- end,
- ?line {ok,Cwd} = file:get_cwd(),
- ?line ok = file:set_cwd(Temp),
- ?line [Drive|":/temp/foo"] = filename:absname(foo),
- ?line [Drive|":/temp/foo"] = filename:absname("foo"),
- ?line [Drive|":/temp/../ebin"] = filename:absname("../ebin"),
- ?line [Drive|":/erlang"] = filename:absname("/erlang"),
- ?line [Drive|":/erlang/src"] = filename:absname("/erlang/src"),
- ?line [Drive|":/erlang/src"] = filename:absname("\\erlang\\src"),
- ?line [Drive|":/temp/erlang"] = filename:absname([Drive|":erlang"]),
- ?line [Drive|":/temp/erlang/src"] =
- filename:absname([Drive|":erlang/src"]),
- ?line [Drive|":/temp/erlang/src"] =
- filename:absname([Drive|":erlang\\src\\"]),
- ?line "a:/erlang" = filename:absname("a:erlang"),
-
- ?line file:set_cwd([Drive|":/"]),
- ?line [Drive|":/foo"] = filename:absname(foo),
- ?line [Drive|":/foo"] = filename:absname("foo"),
- ?line [Drive|":/../ebin"] = filename:absname("../ebin"),
- ?line [Drive|":/erlang"] = filename:absname("/erlang"),
- ?line [Drive|":/erlang/src"] = filename:absname("/erlang/src"),
- ?line [Drive|":/erlang/src"] = filename:absname(["/erlang",'/src']),
- ?line [Drive|":/erlang/src"] = filename:absname("\\erlang\\\\src"),
- ?line [Drive|":/erlang"] = filename:absname([Drive|":erlang"]),
- ?line [Drive|":/erlang/src"] = filename:absname([Drive|":erlang/src"]),
- ?line "a:/erlang" = filename:absname("a:erlang"),
-
- ?line file:set_cwd(Cwd),
- ok;
- Type ->
- case Type of
- {unix, _} ->
- ?line ok = file:set_cwd("/usr"),
- ?line "/usr/foo" = filename:absname(foo),
- ?line "/usr/foo" = filename:absname("foo"),
- ?line "/usr/../ebin" = filename:absname("../ebin");
- {ose, _} ->
- ?line ok = file:set_cwd("/romfs"),
- ?line "/romfs/foo" = filename:absname(foo),
- ?line "/romfs/foo" = filename:absname("foo"),
- ?line "/romfs/../ebin" = filename:absname("../ebin")
- end,
-
- ?line file:set_cwd("/"),
- ?line "/foo" = filename:absname(foo),
- ?line "/foo" = filename:absname("foo"),
- ?line "/../ebin" = filename:absname("../ebin"),
- ?line "/erlang" = filename:absname("/erlang"),
- ?line "/erlang/src" = filename:absname("/erlang/src"),
- ?line "/erlang/src" = filename:absname(["/erl",'ang/s',"rc"]),
- ?line "/erlang/src" = filename:absname(["/erl",'a','ng',"/",'s',"rc"]),
- ?line "/erlang/src" = filename:absname("/erlang///src"),
- ?line "/file_sorter.erl" = filename:absname([file_sorter|'.erl']),
- ok
+ {win32, _} ->
+ [Drive|_] = proplists:get_value(priv_dir, Config),
+ Temp = filename:join([Drive|":/"], "temp"),
+ case file:make_dir(Temp) of
+ ok -> ok;
+ {error,eexist} -> ok
+ end,
+ {ok,Cwd} = file:get_cwd(),
+ ok = file:set_cwd(Temp),
+ [Drive|":/temp/foo"] = filename:absname(foo),
+ [Drive|":/temp/foo"] = filename:absname("foo"),
+ [Drive|":/temp/../ebin"] = filename:absname("../ebin"),
+ [Drive|":/erlang"] = filename:absname("/erlang"),
+ [Drive|":/erlang/src"] = filename:absname("/erlang/src"),
+ [Drive|":/erlang/src"] = filename:absname("\\erlang\\src"),
+ [Drive|":/temp/erlang"] = filename:absname([Drive|":erlang"]),
+ [Drive|":/temp/erlang/src"] =
+ filename:absname([Drive|":erlang/src"]),
+ [Drive|":/temp/erlang/src"] =
+ filename:absname([Drive|":erlang\\src\\"]),
+ "a:/erlang" = filename:absname("a:erlang"),
+
+ file:set_cwd([Drive|":/"]),
+ [Drive|":/foo"] = filename:absname(foo),
+ [Drive|":/foo"] = filename:absname("foo"),
+ [Drive|":/../ebin"] = filename:absname("../ebin"),
+ [Drive|":/erlang"] = filename:absname("/erlang"),
+ [Drive|":/erlang/src"] = filename:absname("/erlang/src"),
+ [Drive|":/erlang/src"] = filename:absname(["/erlang",'/src']),
+ [Drive|":/erlang/src"] = filename:absname("\\erlang\\\\src"),
+ [Drive|":/erlang"] = filename:absname([Drive|":erlang"]),
+ [Drive|":/erlang/src"] = filename:absname([Drive|":erlang/src"]),
+ "a:/erlang" = filename:absname("a:erlang"),
+
+ file:set_cwd(Cwd),
+ ok;
+ {unix, _} ->
+ ok = file:set_cwd("/usr"),
+ "/usr/foo" = filename:absname(foo),
+ "/usr/foo" = filename:absname("foo"),
+ "/usr/../ebin" = filename:absname("../ebin"),
+
+ file:set_cwd("/"),
+ "/foo" = filename:absname(foo),
+ "/foo" = filename:absname("foo"),
+ "/../ebin" = filename:absname("../ebin"),
+ "/erlang" = filename:absname("/erlang"),
+ "/erlang/src" = filename:absname("/erlang/src"),
+ "/erlang/src" = filename:absname(["/erl",'ang/s',"rc"]),
+ "/erlang/src" = filename:absname(["/erl",'a','ng',"/",'s',"rc"]),
+ "/erlang/src" = filename:absname("/erlang///src"),
+ "/file_sorter.erl" = filename:absname([file_sorter|'.erl']),
+ ok
end.
@@ -129,125 +131,119 @@ absname(Config) when is_list(Config) ->
absname_2(Config) when is_list(Config) ->
case os:type() of
- {win32, _} ->
- ?line [Drive|_] = ?config(priv_dir, Config),
- ?line [Drive|":/temp/foo"] = filename:absname(foo, [Drive|":/temp"]),
- ?line [Drive|":/temp/foo"] = filename:absname("foo", [Drive|":/temp"]),
- ?line [Drive|":/temp/../ebin"] = filename:absname("../ebin",
- [Drive|":/temp"]),
- ?line [Drive|":/erlang"] = filename:absname("/erlang", [Drive|":/temp"]),
- ?line [Drive|":/erlang/src"] = filename:absname("/erlang/src",
- [Drive|":/temp"]),
- ?line [Drive|":/erlang/src"] = filename:absname("\\erlang\\src",
- [Drive|":/temp"]),
- ?line [Drive|":/temp/erlang"] = filename:absname([Drive|":erlang"],
- [Drive|":/temp"]),
- ?line [Drive|":/temp/erlang/src"] = filename:absname([Drive|":erlang/src"],
- [Drive|":/temp"]),
- ?line [Drive|":/temp/erlang/src"] =
- filename:absname([Drive|":erlang\\src\\"], [Drive|":/temp"]),
- ?line "a:/erlang" = filename:absname("a:erlang", [Drive|":/temp"]),
-
- ?line file:set_cwd([Drive|":/"]),
- ?line [Drive|":/foo"] = filename:absname(foo, [Drive|":/"]),
- ?line [Drive|":/foo"] = filename:absname("foo", [Drive|":/"]),
- ?line [Drive|":/../ebin"] = filename:absname("../ebin", [Drive|":/"]),
- ?line [Drive|":/erlang"] = filename:absname("/erlang", [Drive|":/"]),
- ?line [Drive|":/erlang/src"] = filename:absname("/erlang/src",
- [Drive|":/"]),
- ?line [Drive|":/erlang/src"] = filename:absname("\\erlang\\\\src",
- [Drive|":/"]),
- ?line [Drive|":/erlang"] = filename:absname([Drive|":erlang"],
- [Drive|":/"]),
- ?line [Drive|":/erlang/src"] = filename:absname([Drive|":erlang/src"],
- [Drive|":/"]),
- ?line "a:/erlang" = filename:absname("a:erlang", [Drive|":/"]),
-
- ok;
- _ ->
- ?line "/usr/foo" = filename:absname(foo, "/usr"),
- ?line "/usr/foo" = filename:absname("foo", "/usr"),
- ?line "/usr/../ebin" = filename:absname("../ebin", "/usr"),
-
- ?line "/foo" = filename:absname(foo, "/"),
- ?line "/foo" = filename:absname("foo", "/"),
- ?line "/../ebin" = filename:absname("../ebin", "/"),
- ?line "/erlang" = filename:absname("/erlang", "/"),
- ?line "/erlang/src" = filename:absname("/erlang/src", "/"),
- ?line "/erlang/src" = filename:absname("/erlang///src", "/"),
- ok
+ {win32, _} ->
+ [Drive|_] = proplists:get_value(priv_dir, Config),
+ [Drive|":/temp/foo"] = filename:absname(foo, [Drive|":/temp"]),
+ [Drive|":/temp/foo"] = filename:absname("foo", [Drive|":/temp"]),
+ [Drive|":/temp/../ebin"] = filename:absname("../ebin",
+ [Drive|":/temp"]),
+ [Drive|":/erlang"] = filename:absname("/erlang", [Drive|":/temp"]),
+ [Drive|":/erlang/src"] = filename:absname("/erlang/src",
+ [Drive|":/temp"]),
+ [Drive|":/erlang/src"] = filename:absname("\\erlang\\src",
+ [Drive|":/temp"]),
+ [Drive|":/temp/erlang"] = filename:absname([Drive|":erlang"],
+ [Drive|":/temp"]),
+ [Drive|":/temp/erlang/src"] = filename:absname([Drive|":erlang/src"],
+ [Drive|":/temp"]),
+ [Drive|":/temp/erlang/src"] =
+ filename:absname([Drive|":erlang\\src\\"], [Drive|":/temp"]),
+ "a:/erlang" = filename:absname("a:erlang", [Drive|":/temp"]),
+
+ file:set_cwd([Drive|":/"]),
+ [Drive|":/foo"] = filename:absname(foo, [Drive|":/"]),
+ [Drive|":/foo"] = filename:absname("foo", [Drive|":/"]),
+ [Drive|":/../ebin"] = filename:absname("../ebin", [Drive|":/"]),
+ [Drive|":/erlang"] = filename:absname("/erlang", [Drive|":/"]),
+ [Drive|":/erlang/src"] = filename:absname("/erlang/src",
+ [Drive|":/"]),
+ [Drive|":/erlang/src"] = filename:absname("\\erlang\\\\src",
+ [Drive|":/"]),
+ [Drive|":/erlang"] = filename:absname([Drive|":erlang"],
+ [Drive|":/"]),
+ [Drive|":/erlang/src"] = filename:absname([Drive|":erlang/src"],
+ [Drive|":/"]),
+ "a:/erlang" = filename:absname("a:erlang", [Drive|":/"]),
+
+ ok;
+ _ ->
+ "/usr/foo" = filename:absname(foo, "/usr"),
+ "/usr/foo" = filename:absname("foo", "/usr"),
+ "/usr/../ebin" = filename:absname("../ebin", "/usr"),
+
+ "/foo" = filename:absname(foo, "/"),
+ "/foo" = filename:absname("foo", "/"),
+ "/../ebin" = filename:absname("../ebin", "/"),
+ "/erlang" = filename:absname("/erlang", "/"),
+ "/erlang/src" = filename:absname("/erlang/src", "/"),
+ "/erlang/src" = filename:absname("/erlang///src", "/"),
+ ok
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
basename_1(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line "." = filename:basename("."),
- ?line "foo" = filename:basename("foo"),
- ?line "foo" = filename:basename("/usr/foo"),
- ?line "foo.erl" = filename:basename("A:usr/foo.erl"),
- ?line "foo" = filename:basename('/usr/foo'),
- ?line "foo" = filename:basename(["/usr","/","f","o","o"]),
- ?line "foo" = filename:basename(["/usr/",foo]),
- ?line "foo" = filename:basename(["/usr/f",oo]),
- ?line "foo" = filename:basename(["usr/", "foo"]),
- ?line "foo" = filename:basename(["usr/"|foo]),
- ?line "foo" = filename:basename(["usr/foo/"]),
- ?line case os:type() of
- {win32, _} ->
- ?line "foo" = filename:basename(["usr\\foo\\"]),
- ?line "foo" = filename:basename("A:\\usr\\foo"),
- ?line "foo" = filename:basename("A:foo");
- _ ->
- ?line "strange\\but\\true" =
- filename:basename("strange\\but\\true")
- end,
- ?line test_server:timetrap_cancel(Dog),
+ "." = filename:basename("."),
+ "foo" = filename:basename("foo"),
+ "foo" = filename:basename("/usr/foo"),
+ "foo.erl" = filename:basename("A:usr/foo.erl"),
+ "foo" = filename:basename('/usr/foo'),
+ "foo" = filename:basename(["/usr","/","f","o","o"]),
+ "foo" = filename:basename(["/usr/",foo]),
+ "foo" = filename:basename(["/usr/f",oo]),
+ "foo" = filename:basename(["usr/", "foo"]),
+ "foo" = filename:basename(["usr/"|foo]),
+ "foo" = filename:basename(["usr/foo/"]),
+ case os:type() of
+ {win32, _} ->
+ "foo" = filename:basename(["usr\\foo\\"]),
+ "foo" = filename:basename("A:\\usr\\foo"),
+ "foo" = filename:basename("A:foo");
+ _ ->
+ "strange\\but\\true" =
+ filename:basename("strange\\but\\true")
+ end,
ok.
basename_2(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line "." = filename:basename(".", ".erl"),
- ?line "foo" = filename:basename("foo.erl", ".erl"),
- ?line "foo" = filename:basename('foo.erl', ".erl"),
- ?line "foo" = filename:basename("foo.erl", '.erl'),
- ?line "foo" = filename:basename(["/usr","/","f","oo"], ".erl"),
- ?line "foo.erl" = filename:basename("/usr/foo.erl", ".hrl"),
- ?line "foo.erl" = filename:basename("/usr.hrl/foo.erl", ".hrl"),
- ?line "foo" = filename:basename("/usr.hrl/foo", ".hrl"),
- ?line "foo" = filename:basename("usr/foo/", ".erl"),
- ?line "foo.erl" = filename:basename("usr/foo.erl/", ".erl"),
- ?line "foo.erl" = filename:basename("usr/foo.erl/", '.erl'),
- ?line "foo" = filename:basename(["/usr",'/','f','oo'], ".erl"),
- ?line "foo.erl" = filename:basename(["usr/foo.e",'rl/'], ".erl"),
- ?line case os:type() of
- {win32, _} ->
- ?line "foo" = filename:basename("A:foo", ".erl"),
- ?line "foo.erl" = filename:basename("a:\\usr\\foo.erl",
- ".hrl"),
- ?line "foo.erl" = filename:basename("c:\\usr.hrl\\foo.erl",
- ".hrl"),
- ?line "foo" = filename:basename("A:\\usr\\foo", ".hrl");
- _ ->
- ?line "strange\\but\\true" =
- filename:basename("strange\\but\\true.erl", ".erl"),
- ?line "strange\\but\\true" =
- filename:basename("strange\\but\\true", ".erl")
- end,
- ?line test_server:timetrap_cancel(Dog),
+ "." = filename:basename(".", ".erl"),
+ "foo" = filename:basename("foo.erl", ".erl"),
+ "foo" = filename:basename('foo.erl', ".erl"),
+ "foo" = filename:basename("foo.erl", '.erl'),
+ "foo" = filename:basename(["/usr","/","f","oo"], ".erl"),
+ "foo.erl" = filename:basename("/usr/foo.erl", ".hrl"),
+ "foo.erl" = filename:basename("/usr.hrl/foo.erl", ".hrl"),
+ "foo" = filename:basename("/usr.hrl/foo", ".hrl"),
+ "foo" = filename:basename("usr/foo/", ".erl"),
+ "foo.erl" = filename:basename("usr/foo.erl/", ".erl"),
+ "foo.erl" = filename:basename("usr/foo.erl/", '.erl'),
+ "foo" = filename:basename(["/usr",'/','f','oo'], ".erl"),
+ "foo.erl" = filename:basename(["usr/foo.e",'rl/'], ".erl"),
+ case os:type() of
+ {win32, _} ->
+ "foo" = filename:basename("A:foo", ".erl"),
+ "foo.erl" = filename:basename("a:\\usr\\foo.erl", ".hrl"),
+ "foo.erl" = filename:basename("c:\\usr.hrl\\foo.erl", ".hrl"),
+ "foo" = filename:basename("A:\\usr\\foo", ".hrl");
+ _ ->
+ "strange\\but\\true" =
+ filename:basename("strange\\but\\true.erl", ".erl"),
+ "strange\\but\\true" =
+ filename:basename("strange\\but\\true", ".erl")
+ end,
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
dirname(Config) when is_list(Config) ->
case os:type() of
- {win32,_} ->
- "A:/usr" = filename:dirname("A:/usr/foo.erl"),
- "A:usr" = filename:dirname("A:usr/foo.erl"),
- "/usr" = filename:dirname("\\usr\\foo.erl"),
- "/" = filename:dirname("\\usr"),
- "A:" = filename:dirname("A:");
- _ -> true
+ {win32,_} ->
+ "A:/usr" = filename:dirname("A:/usr/foo.erl"),
+ "A:usr" = filename:dirname("A:usr/foo.erl"),
+ "/usr" = filename:dirname("\\usr\\foo.erl"),
+ "/" = filename:dirname("\\usr"),
+ "A:" = filename:dirname("A:");
+ _ -> true
end,
"usr" = filename:dirname("usr///foo.erl"),
"." = filename:dirname("foo.erl"),
@@ -267,23 +263,22 @@ dirname(Config) when is_list(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
extension(Config) when is_list(Config) ->
- ?line ".erl" = filename:extension("A:/usr/foo.erl"),
- ?line ".erl" = filename:extension("A:/usr/foo.nisse.erl"),
- ?line ".erl" = filename:extension(["A:/usr/", 'foo.ni', "sse.erl"]),
- ?line ".erl" = filename:extension(["A:/usr/", 'foo.ni', "sse.e", 'rl']),
- ?line ".erl" = filename:extension(["A:/usr/", 'foo.ni', "sse.e"|'rl']),
- ?line ".erl" = filename:extension("A:/usr.bar/foo.nisse.erl"),
- ?line "" = filename:extension("A:/usr.bar/foo"),
- ?line "" = filename:extension("A:/usr/foo"),
- ?line case os:type() of
- {win32, _} ->
- ?line "" = filename:extension("A:\\usr\\foo"),
- ?line ".erl" =
- filename:extension("A:/usr.bar/foo.nisse.erl"),
- ?line "" = filename:extension("A:/usr.bar/foo"),
- ok;
- _ -> ok
- end.
+ ".erl" = filename:extension("A:/usr/foo.erl"),
+ ".erl" = filename:extension("A:/usr/foo.nisse.erl"),
+ ".erl" = filename:extension(["A:/usr/", 'foo.ni', "sse.erl"]),
+ ".erl" = filename:extension(["A:/usr/", 'foo.ni', "sse.e", 'rl']),
+ ".erl" = filename:extension(["A:/usr/", 'foo.ni', "sse.e"|'rl']),
+ ".erl" = filename:extension("A:/usr.bar/foo.nisse.erl"),
+ "" = filename:extension("A:/usr.bar/foo"),
+ "" = filename:extension("A:/usr/foo"),
+ case os:type() of
+ {win32, _} ->
+ "" = filename:extension("A:\\usr\\foo"),
+ ".erl" = filename:extension("A:/usr.bar/foo.nisse.erl"),
+ "" = filename:extension("A:/usr.bar/foo"),
+ ok;
+ _ -> ok
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -291,8 +286,8 @@ join(Config) when is_list(Config) ->
%% Whenever joining two elements, test the equivalence between
%% join/1 and join/2 (OTP-12158) by using help function
%% filename_join/2.
- ?line "/" = filename:join(["/"]),
- ?line "/" = filename:join(["//"]),
+ "/" = filename:join(["/"]),
+ "/" = filename:join(["//"]),
"usr/foo.erl" = filename_join("usr","foo.erl"),
"/src/foo.erl" = filename_join(usr, "/src/foo.erl"),
"/src/foo.erl" = filename_join("/src/",'foo.erl'),
@@ -300,7 +295,7 @@ join(Config) when is_list(Config) ->
"/src/foo.erl" = filename_join("usr", "/src/foo.erl"),
%% Make sure that redundant slashes work too.
- ?line "a/b/c/d/e/f/g" = filename:join(["a//b/c/////d//e/f/g"]),
+ "a/b/c/d/e/f/g" = filename:join(["a//b/c/////d//e/f/g"]),
"a/b/c/d/e/f/g" = filename_join("a//b/c/", "d//e/f/g"),
"a/b/c/d/e/f/g" = filename_join("a//b/c", "d//e/f/g"),
"/d/e/f/g" = filename_join("a//b/c", "/d//e/f/g"),
@@ -333,30 +328,25 @@ join(Config) when is_list(Config) ->
"/b" = filename_join("/a/","/b/"),
"/a/b" = filename_join("/a/","b/"),
- ?line case os:type() of
- {win32, _} ->
- ?line "d:/" = filename:join(["D:/"]),
- ?line "d:/" = filename:join(["D:\\"]),
- "d:/abc" = filename_join("D:/", "abc"),
- "d:abc" = filename_join("D:", "abc"),
- ?line "a/b/c/d/e/f/g" =
- filename:join(["a//b\\c//\\/\\d/\\e/f\\g"]),
- ?line "a:usr/foo.erl" =
- filename:join(["A:","usr","foo.erl"]),
- ?line "/usr/foo.erl" =
- filename:join(["A:","/usr","foo.erl"]),
- "c:usr" = filename_join("A:","C:usr"),
- "a:usr" = filename_join("A:","usr"),
- "c:/usr" = filename_join("A:", "C:/usr"),
- ?line "c:/usr/foo.erl" =
- filename:join(["A:","C:/usr","foo.erl"]),
- ?line "c:usr/foo.erl" =
- filename:join(["A:","C:usr","foo.erl"]),
- ?line "d:/foo" = filename:join([$D, $:, $/, []], "foo"),
- ok;
- _ ->
- ok
- end.
+ case os:type() of
+ {win32, _} ->
+ "d:/" = filename:join(["D:/"]),
+ "d:/" = filename:join(["D:\\"]),
+ "d:/abc" = filename_join("D:/", "abc"),
+ "d:abc" = filename_join("D:", "abc"),
+ "a/b/c/d/e/f/g" = filename:join(["a//b\\c//\\/\\d/\\e/f\\g"]),
+ "a:usr/foo.erl" = filename:join(["A:","usr","foo.erl"]),
+ "/usr/foo.erl" = filename:join(["A:","/usr","foo.erl"]),
+ "c:usr" = filename_join("A:","C:usr"),
+ "a:usr" = filename_join("A:","usr"),
+ "c:/usr" = filename_join("A:", "C:/usr"),
+ "c:/usr/foo.erl" = filename:join(["A:","C:/usr","foo.erl"]),
+ "c:usr/foo.erl" = filename:join(["A:","C:usr","foo.erl"]),
+ "d:/foo" = filename:join([$D, $:, $/, []], "foo"),
+ ok;
+ _ ->
+ ok
+ end.
%% Make sure join([A,B]) is equivalent to join(A,B) (OTP-12158)
filename_join(A,B) ->
@@ -364,92 +354,92 @@ filename_join(A,B) ->
Res = filename:join([A,B]).
pathtype(Config) when is_list(Config) ->
- ?line relative = filename:pathtype(".."),
- ?line relative = filename:pathtype("foo"),
- ?line relative = filename:pathtype("foo/bar"),
- ?line relative = filename:pathtype('foo/bar'),
- ?line relative = filename:pathtype(['f','oo',"/bar"]),
+ relative = filename:pathtype(".."),
+ relative = filename:pathtype("foo"),
+ relative = filename:pathtype("foo/bar"),
+ relative = filename:pathtype('foo/bar'),
+ relative = filename:pathtype(['f','oo',"/bar"]),
case os:type() of
- {win32, _} ->
- ?line volumerelative = filename:pathtype("/usr/local/bin"),
- ?line volumerelative = filename:pathtype("A:usr/local/bin"),
- ok;
- _ ->
- ?line absolute = filename:pathtype("/"),
- ?line absolute = filename:pathtype("/usr/local/bin"),
- ok
+ {win32, _} ->
+ volumerelative = filename:pathtype("/usr/local/bin"),
+ volumerelative = filename:pathtype("A:usr/local/bin"),
+ ok;
+ _ ->
+ absolute = filename:pathtype("/"),
+ absolute = filename:pathtype("/usr/local/bin"),
+ ok
end.
rootname(Config) when is_list(Config) ->
- ?line "/jam.src/kalle" = filename:rootname("/jam.src/kalle"),
- ?line "/jam.src/foo" = filename:rootname("/jam.src/foo.erl"),
- ?line "/jam.src/foo" = filename:rootname(["/ja",'m.sr',"c/foo.erl"]),
- ?line "/jam.src/foo" = filename:rootname("/jam.src/foo.erl", ".erl"),
- ?line "/jam.src/foo.jam" = filename:rootname("/jam.src/foo.jam", ".erl"),
- ?line "/jam.src/foo.jam" = filename:rootname(["/jam.sr",'c/foo.j',"am"],".erl"),
- ?line "/jam.src/foo.jam" = filename:rootname(["/jam.sr",'c/foo.j'|am],".erl"),
+ "/jam.src/kalle" = filename:rootname("/jam.src/kalle"),
+ "/jam.src/foo" = filename:rootname("/jam.src/foo.erl"),
+ "/jam.src/foo" = filename:rootname(["/ja",'m.sr',"c/foo.erl"]),
+ "/jam.src/foo" = filename:rootname("/jam.src/foo.erl", ".erl"),
+ "/jam.src/foo.jam" = filename:rootname("/jam.src/foo.jam", ".erl"),
+ "/jam.src/foo.jam" = filename:rootname(["/jam.sr",'c/foo.j',"am"],".erl"),
+ "/jam.src/foo.jam" = filename:rootname(["/jam.sr",'c/foo.j'|am],".erl"),
ok.
split(Config) when is_list(Config) ->
- ?line ["/","usr","local","bin"] = filename:split("/usr/local/bin"),
- ?line ["foo","bar"]= filename:split("foo/bar"),
- ?line ["foo", "bar", "hello"]= filename:split("foo////bar//hello"),
- ?line ["foo", "bar", "hello"]= filename:split(["foo//",'//bar//h',"ello"]),
- ?line ["foo", "bar", "hello"]= filename:split(["foo//",'//bar//h'|ello]),
+ ["/","usr","local","bin"] = filename:split("/usr/local/bin"),
+ ["foo","bar"]= filename:split("foo/bar"),
+ ["foo", "bar", "hello"]= filename:split("foo////bar//hello"),
+ ["foo", "bar", "hello"]= filename:split(["foo//",'//bar//h',"ello"]),
+ ["foo", "bar", "hello"]= filename:split(["foo//",'//bar//h'|ello]),
["/"] = filename:split("/"),
[] = filename:split(""),
case os:type() of
- {win32,_} ->
- ?line ["a:/","msdev","include"] =
- filename:split("a:/msdev/include"),
- ?line ["a:/","msdev","include"] =
- filename:split("A:/msdev/include"),
- ?line ["msdev","include"] =
- filename:split("msdev\\include"),
- ?line ["a:/","msdev","include"] =
- filename:split("a:\\msdev\\include"),
- ?line ["a:","msdev","include"] =
- filename:split("a:msdev\\include"),
- ok;
- _ ->
+ {win32,_} ->
+ ["a:/","msdev","include"] =
+ filename:split("a:/msdev/include"),
+ ["a:/","msdev","include"] =
+ filename:split("A:/msdev/include"),
+ ["msdev","include"] =
+ filename:split("msdev\\include"),
+ ["a:/","msdev","include"] =
+ filename:split("a:\\msdev\\include"),
+ ["a:","msdev","include"] =
+ filename:split("a:msdev\\include"),
+ ok;
+ _ ->
ok
end.
t_nativename(Config) when is_list(Config) ->
- ?line "abcedf" = filename:nativename(abcedf),
- ?line "abcedf" = filename:nativename(["abc", "edf"]),
- ?line "abcgluff" = filename:nativename(["abc", gluff]),
+ "abcedf" = filename:nativename(abcedf),
+ "abcedf" = filename:nativename(["abc", "edf"]),
+ "abcgluff" = filename:nativename(["abc", gluff]),
case os:type() of
- {win32, _} ->
- ?line "a:\\temp\\arne.exe" =
- filename:nativename("A:/temp//arne.exe/");
- _ ->
- ?line "/usr/tmp/arne" =
- filename:nativename("/usr/tmp//arne/")
+ {win32, _} ->
+ "a:\\temp\\arne.exe" =
+ filename:nativename("A:/temp//arne.exe/");
+ _ ->
+ "/usr/tmp/arne" =
+ filename:nativename("/usr/tmp//arne/")
end.
find_src(Config) when is_list(Config) ->
- ?line {Source,_} = filename:find_src(file),
- ?line ["file"|_] = lists:reverse(filename:split(Source)),
- ?line {_,_} = filename:find_src(init, [{".","."}, {"ebin","src"}]),
+ {Source,_} = filename:find_src(file),
+ ["file"|_] = lists:reverse(filename:split(Source)),
+ {_,_} = filename:find_src(init, [{".","."}, {"ebin","src"}]),
%% Try to find the source for a preloaded module.
- ?line {error,{preloaded,init}} = filename:find_src(init),
+ {error,{preloaded,init}} = filename:find_src(init),
%% Make sure that find_src works for a slim BEAM file.
OldPath = code:get_path(),
try
- PrivDir = ?config(priv_dir, Config),
- code:add_patha(PrivDir),
- Src = "simple",
- SrcPath = filename:join(PrivDir, Src) ++ ".erl",
- SrcContents = "-module(simple).\n",
- ok = file:write_file(SrcPath, SrcContents),
- {ok,simple} = compile:file(SrcPath, [slim,{outdir,PrivDir}]),
- BeamPath = filename:join(PrivDir, Src),
- {BeamPath,[]} = filename:find_src(simple)
+ PrivDir = proplists:get_value(priv_dir, Config),
+ code:add_patha(PrivDir),
+ Src = "simple",
+ SrcPath = filename:join(PrivDir, Src) ++ ".erl",
+ SrcContents = "-module(simple).\n",
+ ok = file:write_file(SrcPath, SrcContents),
+ {ok,simple} = compile:file(SrcPath, [slim,{outdir,PrivDir}]),
+ BeamPath = filename:join(PrivDir, Src),
+ {BeamPath,[]} = filename:find_src(simple)
after
- code:set_path(OldPath)
+ code:set_path(OldPath)
end,
ok.
@@ -461,58 +451,51 @@ find_src(Config) when is_list(Config) ->
absname_bin(Config) when is_list(Config) ->
case os:type() of
- {win32, _} ->
- ?line [Drive|_] = ?config(priv_dir, Config),
- ?line Temp = filename:join([Drive|":/"], "temp"),
- ?line case file:make_dir(Temp) of
- ok -> ok;
- {error,eexist} -> ok
- end,
- ?line {ok,Cwd} = file:get_cwd(),
- ?line ok = file:set_cwd(Temp),
- ?line <<Drive:8,":/temp/foo">> = filename:absname(<<"foo">>),
- ?line <<Drive:8,":/temp/../ebin">> = filename:absname(<<"../ebin">>),
- ?line <<Drive:8,":/erlang">> = filename:absname(<<"/erlang">>),
- ?line <<Drive:8,":/erlang/src">> = filename:absname(<<"/erlang/src">>),
- ?line <<Drive:8,":/erlang/src">> = filename:absname(<<"\\erlang\\src">>),
- ?line <<Drive:8,":/temp/erlang">> = filename:absname(<<Drive:8,":erlang">>),
- ?line <<Drive:8,":/temp/erlang/src">> =
- filename:absname(<<Drive:8,":erlang/src">>),
- ?line <<Drive:8,":/temp/erlang/src">> =
- filename:absname(<<Drive:8,":erlang\\src\\">>),
- ?line <<"a:/erlang">> = filename:absname(<<"a:erlang">>),
-
- ?line file:set_cwd(<<Drive:8,":/">>),
- ?line <<Drive:8,":/foo">> = filename:absname(<<"foo">>),
- ?line <<Drive:8,":/../ebin">> = filename:absname(<<"../ebin">>),
- ?line <<Drive:8,":/erlang">> = filename:absname(<<"/erlang">>),
- ?line <<Drive:8,":/erlang/src">> = filename:absname(<<"/erlang/src">>),
- ?line <<Drive:8,":/erlang/src">> = filename:absname(<<"\\erlang\\\\src">>),
- ?line <<Drive:8,":/erlang">> = filename:absname(<<Drive:8,":erlang">>),
- ?line <<Drive:8,":/erlang/src">> = filename:absname(<<Drive:8,":erlang/src">>),
- ?line <<"a:/erlang">> = filename:absname(<<"a:erlang">>),
-
- ?line file:set_cwd(Cwd),
- ok;
- Type ->
- case Type of
- {unix,_} ->
- ?line ok = file:set_cwd(<<"/usr">>),
- ?line <<"/usr/foo">> = filename:absname(<<"foo">>),
- ?line <<"/usr/../ebin">> = filename:absname(<<"../ebin">>);
- {ose,_} ->
- ?line ok = file:set_cwd(<<"/romfs">>),
- ?line <<"/romfs/foo">> = filename:absname(<<"foo">>),
- ?line <<"/romfs/../ebin">> = filename:absname(<<"../ebin">>)
- end,
-
- ?line file:set_cwd(<<"/">>),
- ?line <<"/foo">> = filename:absname(<<"foo">>),
- ?line <<"/../ebin">> = filename:absname(<<"../ebin">>),
- ?line <<"/erlang">> = filename:absname(<<"/erlang">>),
- ?line <<"/erlang/src">> = filename:absname(<<"/erlang/src">>),
- ?line <<"/erlang/src">> = filename:absname(<<"/erlang///src">>),
- ok
+ {win32, _} ->
+ [Drive|_] = proplists:get_value(priv_dir, Config),
+ Temp = filename:join([Drive|":/"], "temp"),
+ case file:make_dir(Temp) of
+ ok -> ok;
+ {error,eexist} -> ok
+ end,
+ {ok,Cwd} = file:get_cwd(),
+ ok = file:set_cwd(Temp),
+ <<Drive:8,":/temp/foo">> = filename:absname(<<"foo">>),
+ <<Drive:8,":/temp/../ebin">> = filename:absname(<<"../ebin">>),
+ <<Drive:8,":/erlang">> = filename:absname(<<"/erlang">>),
+ <<Drive:8,":/erlang/src">> = filename:absname(<<"/erlang/src">>),
+ <<Drive:8,":/erlang/src">> = filename:absname(<<"\\erlang\\src">>),
+ <<Drive:8,":/temp/erlang">> = filename:absname(<<Drive:8,":erlang">>),
+ <<Drive:8,":/temp/erlang/src">> =
+ filename:absname(<<Drive:8,":erlang/src">>),
+ <<Drive:8,":/temp/erlang/src">> =
+ filename:absname(<<Drive:8,":erlang\\src\\">>),
+ <<"a:/erlang">> = filename:absname(<<"a:erlang">>),
+
+ file:set_cwd(<<Drive:8,":/">>),
+ <<Drive:8,":/foo">> = filename:absname(<<"foo">>),
+ <<Drive:8,":/../ebin">> = filename:absname(<<"../ebin">>),
+ <<Drive:8,":/erlang">> = filename:absname(<<"/erlang">>),
+ <<Drive:8,":/erlang/src">> = filename:absname(<<"/erlang/src">>),
+ <<Drive:8,":/erlang/src">> = filename:absname(<<"\\erlang\\\\src">>),
+ <<Drive:8,":/erlang">> = filename:absname(<<Drive:8,":erlang">>),
+ <<Drive:8,":/erlang/src">> = filename:absname(<<Drive:8,":erlang/src">>),
+ <<"a:/erlang">> = filename:absname(<<"a:erlang">>),
+
+ file:set_cwd(Cwd),
+ ok;
+ {unix,_} ->
+ ok = file:set_cwd(<<"/usr">>),
+ <<"/usr/foo">> = filename:absname(<<"foo">>),
+ <<"/usr/../ebin">> = filename:absname(<<"../ebin">>),
+
+ file:set_cwd(<<"/">>),
+ <<"/foo">> = filename:absname(<<"foo">>),
+ <<"/../ebin">> = filename:absname(<<"../ebin">>),
+ <<"/erlang">> = filename:absname(<<"/erlang">>),
+ <<"/erlang/src">> = filename:absname(<<"/erlang/src">>),
+ <<"/erlang/src">> = filename:absname(<<"/erlang///src">>),
+ ok
end.
@@ -520,108 +503,100 @@ absname_bin(Config) when is_list(Config) ->
absname_bin_2(Config) when is_list(Config) ->
case os:type() of
- {win32, _} ->
- ?line [Drive|_] = ?config(priv_dir, Config),
- ?line <<Drive:8,":/temp/foo">> = filename:absname(<<"foo">>, <<Drive:8,":/temp">>),
- ?line <<Drive:8,":/temp/../ebin">> = filename:absname(<<"../ebin">>,
- <<Drive:8,":/temp">>),
- ?line <<Drive:8,":/erlang">> = filename:absname(<<"/erlang">>, <<Drive:8,":/temp">>),
- ?line <<Drive:8,":/erlang/src">> = filename:absname(<<"/erlang/src">>,
- <<Drive:8,":/temp">>),
- ?line <<Drive:8,":/erlang/src">> = filename:absname(<<"\\erlang\\src">>,
- <<Drive:8,":/temp">>),
- ?line <<Drive:8,":/temp/erlang">> = filename:absname(<<Drive:8,":erlang">>,
- <<Drive:8,":/temp">>),
- ?line <<Drive:8,":/temp/erlang/src">> = filename:absname(<<Drive:8,":erlang/src">>,
- <<Drive:8,":/temp">>),
- ?line <<Drive:8,":/temp/erlang/src">> =
- filename:absname(<<Drive:8,":erlang\\src\\">>, <<Drive:8,":/temp">>),
- ?line <<"a:/erlang">> = filename:absname(<<"a:erlang">>, <<Drive:8,":/temp">>),
-
- ?line file:set_cwd(<<Drive:8,":/">>),
- ?line <<Drive:8,":/foo">> = filename:absname(foo, <<Drive:8,":/">>),
- ?line <<Drive:8,":/foo">> = filename:absname(<<"foo">>, <<Drive:8,":/">>),
- ?line <<Drive:8,":/../ebin">> = filename:absname(<<"../ebin">>, <<Drive:8,":/">>),
- ?line <<Drive:8,":/erlang">> = filename:absname(<<"/erlang">>, <<Drive:8,":/">>),
- ?line <<Drive:8,":/erlang/src">> = filename:absname(<<"/erlang/src">>,
- <<Drive:8,":/">>),
- ?line <<Drive:8,":/erlang/src">> = filename:absname(<<"\\erlang\\\\src">>,
- <<Drive:8,":/">>),
- ?line <<Drive:8,":/erlang">> = filename:absname(<<Drive:8,":erlang">>,
- <<Drive:8,":/">>),
- ?line <<Drive:8,":/erlang/src">> = filename:absname(<<Drive:8,":erlang/src">>,
- <<Drive:8,":/">>),
- ?line <<"a:/erlang">> = filename:absname(<<"a:erlang">>, <<Drive:8,":/">>),
-
- ok;
- _ ->
- ?line <<"/usr/foo">> = filename:absname(<<"foo">>, <<"/usr">>),
- ?line <<"/usr/../ebin">> = filename:absname(<<"../ebin">>, <<"/usr">>),
-
- ?line <<"/foo">> = filename:absname(<<"foo">>, <<"/">>),
- ?line <<"/../ebin">> = filename:absname(<<"../ebin">>, <<"/">>),
- ?line <<"/erlang">> = filename:absname(<<"/erlang">>, <<"/">>),
- ?line <<"/erlang/src">> = filename:absname(<<"/erlang/src">>, <<"/">>),
- ?line <<"/erlang/src">> = filename:absname(<<"/erlang///src">>, <<"/">>),
- ok
+ {win32, _} ->
+ [Drive|_] = proplists:get_value(priv_dir, Config),
+ <<Drive:8,":/temp/foo">> = filename:absname(<<"foo">>, <<Drive:8,":/temp">>),
+ <<Drive:8,":/temp/../ebin">> = filename:absname(<<"../ebin">>,
+ <<Drive:8,":/temp">>),
+ <<Drive:8,":/erlang">> = filename:absname(<<"/erlang">>, <<Drive:8,":/temp">>),
+ <<Drive:8,":/erlang/src">> = filename:absname(<<"/erlang/src">>,
+ <<Drive:8,":/temp">>),
+ <<Drive:8,":/erlang/src">> = filename:absname(<<"\\erlang\\src">>,
+ <<Drive:8,":/temp">>),
+ <<Drive:8,":/temp/erlang">> = filename:absname(<<Drive:8,":erlang">>,
+ <<Drive:8,":/temp">>),
+ <<Drive:8,":/temp/erlang/src">> = filename:absname(<<Drive:8,":erlang/src">>,
+ <<Drive:8,":/temp">>),
+ <<Drive:8,":/temp/erlang/src">> =
+ filename:absname(<<Drive:8,":erlang\\src\\">>, <<Drive:8,":/temp">>),
+ <<"a:/erlang">> = filename:absname(<<"a:erlang">>, <<Drive:8,":/temp">>),
+
+ file:set_cwd(<<Drive:8,":/">>),
+ <<Drive:8,":/foo">> = filename:absname(foo, <<Drive:8,":/">>),
+ <<Drive:8,":/foo">> = filename:absname(<<"foo">>, <<Drive:8,":/">>),
+ <<Drive:8,":/../ebin">> = filename:absname(<<"../ebin">>, <<Drive:8,":/">>),
+ <<Drive:8,":/erlang">> = filename:absname(<<"/erlang">>, <<Drive:8,":/">>),
+ <<Drive:8,":/erlang/src">> = filename:absname(<<"/erlang/src">>,
+ <<Drive:8,":/">>),
+ <<Drive:8,":/erlang/src">> = filename:absname(<<"\\erlang\\\\src">>,
+ <<Drive:8,":/">>),
+ <<Drive:8,":/erlang">> = filename:absname(<<Drive:8,":erlang">>,
+ <<Drive:8,":/">>),
+ <<Drive:8,":/erlang/src">> = filename:absname(<<Drive:8,":erlang/src">>,
+ <<Drive:8,":/">>),
+ <<"a:/erlang">> = filename:absname(<<"a:erlang">>, <<Drive:8,":/">>),
+
+ ok;
+ _ ->
+ <<"/usr/foo">> = filename:absname(<<"foo">>, <<"/usr">>),
+ <<"/usr/../ebin">> = filename:absname(<<"../ebin">>, <<"/usr">>),
+ <<"/foo">> = filename:absname(<<"foo">>, <<"/">>),
+ <<"/../ebin">> = filename:absname(<<"../ebin">>, <<"/">>),
+ <<"/erlang">> = filename:absname(<<"/erlang">>, <<"/">>),
+ <<"/erlang/src">> = filename:absname(<<"/erlang/src">>, <<"/">>),
+ <<"/erlang/src">> = filename:absname(<<"/erlang///src">>, <<"/">>),
+ ok
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
basename_bin_1(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line <<".">> = filename:basename(<<".">>),
- ?line <<"foo">> = filename:basename(<<"foo">>),
- ?line <<"foo">> = filename:basename(<<"/usr/foo">>),
- ?line <<"foo.erl">> = filename:basename(<<"A:usr/foo.erl">>),
- ?line case os:type() of
- {win32, _} ->
- ?line <<"foo">> = filename:basename(<<"A:\\usr\\foo">>),
- ?line <<"foo">> = filename:basename(<<"A:foo">>);
- _ ->
- ?line <<"strange\\but\\true">> =
- filename:basename(<<"strange\\but\\true">>)
- end,
- ?line test_server:timetrap_cancel(Dog),
+ <<".">> = filename:basename(<<".">>),
+ <<"foo">> = filename:basename(<<"foo">>),
+ <<"foo">> = filename:basename(<<"/usr/foo">>),
+ <<"foo.erl">> = filename:basename(<<"A:usr/foo.erl">>),
+ case os:type() of
+ {win32, _} ->
+ <<"foo">> = filename:basename(<<"A:\\usr\\foo">>),
+ <<"foo">> = filename:basename(<<"A:foo">>);
+ _ ->
+ <<"strange\\but\\true">> = filename:basename(<<"strange\\but\\true">>)
+ end,
ok.
basename_bin_2(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(10)),
- ?line <<".">> = filename:basename(<<".">>, <<".erl">>),
- ?line <<"foo">> = filename:basename(<<"foo.erl">>, <<".erl">>),
- ?line <<"foo.erl">> = filename:basename(<<"/usr/foo.erl">>, <<".hrl">>),
- ?line <<"foo.erl">> = filename:basename(<<"/usr.hrl/foo.erl">>, <<".hrl">>),
- ?line <<"foo">> = filename:basename(<<"/usr.hrl/foo">>, <<".hrl">>),
- ?line <<"foo">> = filename:basename(<<"usr/foo/">>, <<".erl">>),
- ?line <<"foo.erl">> = filename:basename(<<"usr/foo.erl/">>, <<".erl">>),
- ?line case os:type() of
- {win32, _} ->
- ?line <<"foo">> = filename:basename(<<"A:foo">>, <<".erl">>),
- ?line <<"foo.erl">> = filename:basename(<<"a:\\usr\\foo.erl">>,
- <<".hrl">>),
- ?line <<"foo.erl">> = filename:basename(<<"c:\\usr.hrl\\foo.erl">>,
- <<".hrl">>),
- ?line <<"foo">> = filename:basename(<<"A:\\usr\\foo">>, <<".hrl">>);
- _ ->
- ?line <<"strange\\but\\true">> =
- filename:basename(<<"strange\\but\\true.erl">>, <<".erl">>),
- ?line <<"strange\\but\\true">> =
- filename:basename(<<"strange\\but\\true">>, <<".erl">>)
- end,
- ?line test_server:timetrap_cancel(Dog),
+ <<".">> = filename:basename(<<".">>, <<".erl">>),
+ <<"foo">> = filename:basename(<<"foo.erl">>, <<".erl">>),
+ <<"foo.erl">> = filename:basename(<<"/usr/foo.erl">>, <<".hrl">>),
+ <<"foo.erl">> = filename:basename(<<"/usr.hrl/foo.erl">>, <<".hrl">>),
+ <<"foo">> = filename:basename(<<"/usr.hrl/foo">>, <<".hrl">>),
+ <<"foo">> = filename:basename(<<"usr/foo/">>, <<".erl">>),
+ <<"foo.erl">> = filename:basename(<<"usr/foo.erl/">>, <<".erl">>),
+ case os:type() of
+ {win32, _} ->
+ <<"foo">> = filename:basename(<<"A:foo">>, <<".erl">>),
+ <<"foo.erl">> = filename:basename(<<"a:\\usr\\foo.erl">>, <<".hrl">>),
+ <<"foo.erl">> = filename:basename(<<"c:\\usr.hrl\\foo.erl">>, <<".hrl">>),
+ <<"foo">> = filename:basename(<<"A:\\usr\\foo">>, <<".hrl">>);
+ _ ->
+ <<"strange\\but\\true">> =
+ filename:basename(<<"strange\\but\\true.erl">>, <<".erl">>),
+ <<"strange\\but\\true">> =
+ filename:basename(<<"strange\\but\\true">>, <<".erl">>)
+ end,
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
dirname_bin(Config) when is_list(Config) ->
case os:type() of
- {win32,_} ->
- <<"A:/usr">> = filename:dirname(<<"A:/usr/foo.erl">>),
- <<"A:usr">> = filename:dirname(<<"A:usr/foo.erl">>),
- <<"/usr">> = filename:dirname(<<"\\usr\\foo.erl">>),
- <<"/">> = filename:dirname(<<"\\usr">>),
- <<"A:">> = filename:dirname(<<"A:">>);
- _ -> true
+ {win32,_} ->
+ <<"A:/usr">> = filename:dirname(<<"A:/usr/foo.erl">>),
+ <<"A:usr">> = filename:dirname(<<"A:usr/foo.erl">>),
+ <<"/usr">> = filename:dirname(<<"\\usr\\foo.erl">>),
+ <<"/">> = filename:dirname(<<"\\usr">>),
+ <<"A:">> = filename:dirname(<<"A:">>);
+ _ -> true
end,
<<"usr">> = filename:dirname(<<"usr///foo.erl">>),
<<".">> = filename:dirname(<<"foo.erl">>),
@@ -629,7 +604,6 @@ dirname_bin(Config) when is_list(Config) ->
<<"/">> = filename:dirname(<<"/">>),
<<"/">> = filename:dirname(<<"/usr">>),
ok.
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -641,10 +615,9 @@ extension_bin(Config) when is_list(Config) ->
<<"">> = filename:extension(<<"A:/usr/foo">>),
case os:type() of
{win32, _} ->
- ?line <<"">> = filename:extension(<<"A:\\usr\\foo">>),
- ?line <<".erl">> =
- filename:extension(<<"A:/usr.bar/foo.nisse.erl">>),
- ?line <<"">> = filename:extension(<<"A:/usr.bar/foo">>),
+ <<"">> = filename:extension(<<"A:\\usr\\foo">>),
+ <<".erl">> = filename:extension(<<"A:/usr.bar/foo.nisse.erl">>),
+ <<"">> = filename:extension(<<"A:/usr.bar/foo">>),
ok;
_ -> ok
end.
@@ -652,22 +625,22 @@ extension_bin(Config) when is_list(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
join_bin(Config) when is_list(Config) ->
- ?line <<"/">> = filename:join([<<"/">>]),
- ?line <<"/">> = filename:join([<<"//">>]),
- ?line <<"usr/foo.erl">> = filename:join(<<"usr">>,<<"foo.erl">>),
- ?line <<"/src/foo.erl">> = filename:join(usr, <<"/src/foo.erl">>),
- ?line <<"/src/foo.erl">> = filename:join([<<"/src/">>,'foo.erl']),
- ?line <<"/src/foo.erl">> = filename:join(<<"usr">>, ["/sr", 'c/foo.erl']),
- ?line <<"/src/foo.erl">> = filename:join(<<"usr">>, <<"/src/foo.erl">>),
+ <<"/">> = filename:join([<<"/">>]),
+ <<"/">> = filename:join([<<"//">>]),
+ <<"usr/foo.erl">> = filename:join(<<"usr">>,<<"foo.erl">>),
+ <<"/src/foo.erl">> = filename:join(usr, <<"/src/foo.erl">>),
+ <<"/src/foo.erl">> = filename:join([<<"/src/">>,'foo.erl']),
+ <<"/src/foo.erl">> = filename:join(<<"usr">>, ["/sr", 'c/foo.erl']),
+ <<"/src/foo.erl">> = filename:join(<<"usr">>, <<"/src/foo.erl">>),
%% Make sure that redundant slashes work too.
- ?line <<"a/b/c/d/e/f/g">> = filename:join([<<"a//b/c/////d//e/f/g">>]),
- ?line <<"a/b/c/d/e/f/g">> = filename:join([<<"a//b/c/">>, <<"d//e/f/g">>]),
- ?line <<"a/b/c/d/e/f/g">> = filename:join([<<"a//b/c">>, <<"d//e/f/g">>]),
- ?line <<"/d/e/f/g">> = filename:join([<<"a//b/c">>, <<"/d//e/f/g">>]),
- ?line <<"/d/e/f/g">> = filename:join([<<"a//b/c">>, <<"//d//e/f/g">>]),
+ <<"a/b/c/d/e/f/g">> = filename:join([<<"a//b/c/////d//e/f/g">>]),
+ <<"a/b/c/d/e/f/g">> = filename:join([<<"a//b/c/">>, <<"d//e/f/g">>]),
+ <<"a/b/c/d/e/f/g">> = filename:join([<<"a//b/c">>, <<"d//e/f/g">>]),
+ <<"/d/e/f/g">> = filename:join([<<"a//b/c">>, <<"/d//e/f/g">>]),
+ <<"/d/e/f/g">> = filename:join([<<"a//b/c">>, <<"//d//e/f/g">>]),
- ?line <<"foo/bar">> = filename:join([$f,$o,$o,$/,[]], <<"bar">>),
+ <<"foo/bar">> = filename:join([$f,$o,$o,$/,[]], <<"bar">>),
%% Single dots - should be removed if in the middle of the path,
%% but not at the end of the path.
@@ -716,30 +689,25 @@ join_bin(Config) when is_list(Config) ->
<<"/a/b">> = filename:join([<<"/a/">>,<<"b/">>]),
<<"/a/b">> = filename:join(<<"/a/">>,<<"b/">>),
- ?line case os:type() of
- {win32, _} ->
- ?line <<"d:/">> = filename:join([<<"D:/">>]),
- ?line <<"d:/">> = filename:join([<<"D:\\">>]),
- ?line <<"d:/abc">> = filename:join([<<"D:/">>, <<"abc">>]),
- ?line <<"d:abc">> = filename:join([<<"D:">>, <<"abc">>]),
- ?line <<"a/b/c/d/e/f/g">> =
- filename:join([<<"a//b\\c//\\/\\d/\\e/f\\g">>]),
- ?line <<"a:usr/foo.erl">> =
- filename:join([<<"A:">>,<<"usr">>,<<"foo.erl">>]),
- ?line <<"/usr/foo.erl">> =
- filename:join([<<"A:">>,<<"/usr">>,<<"foo.erl">>]),
- ?line <<"c:usr">> = filename:join(<<"A:">>,<<"C:usr">>),
- ?line <<"a:usr">> = filename:join(<<"A:">>,<<"usr">>),
- ?line <<"c:/usr">> = filename:join(<<"A:">>, <<"C:/usr">>),
- ?line <<"c:/usr/foo.erl">> =
- filename:join([<<"A:">>,<<"C:/usr">>,<<"foo.erl">>]),
- ?line <<"c:usr/foo.erl">> =
- filename:join([<<"A:">>,<<"C:usr">>,<<"foo.erl">>]),
- ?line <<"d:/foo">> = filename:join([$D, $:, $/, []], <<"foo">>),
- ok;
- _ ->
- ok
- end.
+ case os:type() of
+ {win32, _} ->
+ <<"d:/">> = filename:join([<<"D:/">>]),
+ <<"d:/">> = filename:join([<<"D:\\">>]),
+ <<"d:/abc">> = filename:join([<<"D:/">>, <<"abc">>]),
+ <<"d:abc">> = filename:join([<<"D:">>, <<"abc">>]),
+ <<"a/b/c/d/e/f/g">> = filename:join([<<"a//b\\c//\\/\\d/\\e/f\\g">>]),
+ <<"a:usr/foo.erl">> = filename:join([<<"A:">>,<<"usr">>,<<"foo.erl">>]),
+ <<"/usr/foo.erl">> = filename:join([<<"A:">>,<<"/usr">>,<<"foo.erl">>]),
+ <<"c:usr">> = filename:join(<<"A:">>,<<"C:usr">>),
+ <<"a:usr">> = filename:join(<<"A:">>,<<"usr">>),
+ <<"c:/usr">> = filename:join(<<"A:">>, <<"C:/usr">>),
+ <<"c:/usr/foo.erl">> = filename:join([<<"A:">>,<<"C:/usr">>,<<"foo.erl">>]),
+ <<"c:usr/foo.erl">> = filename:join([<<"A:">>,<<"C:usr">>,<<"foo.erl">>]),
+ <<"d:/foo">> = filename:join([$D, $:, $/, []], <<"foo">>),
+ ok;
+ _ ->
+ ok
+ end.
pathtype_bin(Config) when is_list(Config) ->
relative = filename:pathtype(<<"..">>),
@@ -747,14 +715,14 @@ pathtype_bin(Config) when is_list(Config) ->
relative = filename:pathtype(<<"foo/bar">>),
relative = filename:pathtype('foo/bar'),
case os:type() of
- {win32, _} ->
- volumerelative = filename:pathtype(<<"/usr/local/bin">>),
- volumerelative = filename:pathtype(<<"A:usr/local/bin">>),
- ok;
- _ ->
- absolute = filename:pathtype(<<"/">>),
- absolute = filename:pathtype(<<"/usr/local/bin">>),
- ok
+ {win32, _} ->
+ volumerelative = filename:pathtype(<<"/usr/local/bin">>),
+ volumerelative = filename:pathtype(<<"A:usr/local/bin">>),
+ ok;
+ _ ->
+ absolute = filename:pathtype(<<"/">>),
+ absolute = filename:pathtype(<<"/usr/local/bin">>),
+ ok
end.
rootname_bin(Config) when is_list(Config) ->
@@ -773,29 +741,204 @@ split_bin(Config) when is_list(Config) ->
[<<"/">>] = filename:split(<<"/">>),
[] = filename:split(<<"">>),
case os:type() of
- {win32,_} ->
- [<<"a:/">>,<<"msdev">>,<<"include">>] =
- filename:split(<<"a:/msdev/include">>),
- [<<"a:/">>,<<"msdev">>,<<"include">>] =
- filename:split(<<"A:/msdev/include">>),
- [<<"msdev">>,<<"include">>] =
- filename:split(<<"msdev\\include">>),
- [<<"a:/">>,<<"msdev">>,<<"include">>] =
- filename:split(<<"a:\\msdev\\include">>),
- [<<"a:">>,<<"msdev">>,<<"include">>] =
- filename:split(<<"a:msdev\\include">>),
- ok;
- _ ->
- ok
+ {win32,_} ->
+ [<<"a:/">>,<<"msdev">>,<<"include">>] =
+ filename:split(<<"a:/msdev/include">>),
+ [<<"a:/">>,<<"msdev">>,<<"include">>] =
+ filename:split(<<"A:/msdev/include">>),
+ [<<"msdev">>,<<"include">>] =
+ filename:split(<<"msdev\\include">>),
+ [<<"a:/">>,<<"msdev">>,<<"include">>] =
+ filename:split(<<"a:\\msdev\\include">>),
+ [<<"a:">>,<<"msdev">>,<<"include">>] =
+ filename:split(<<"a:msdev\\include">>),
+ ok;
+ _ ->
+ ok
end.
t_nativename_bin(Config) when is_list(Config) ->
- ?line <<"abcedf">> = filename:nativename(<<"abcedf">>),
+ <<"abcedf">> = filename:nativename(<<"abcedf">>),
+ case os:type() of
+ {win32, _} ->
+ <<"a:\\temp\\arne.exe">> =
+ filename:nativename(<<"A:/temp//arne.exe/">>);
+ _ ->
+ <<"/usr/tmp/arne">> =
+ filename:nativename(<<"/usr/tmp//arne/">>)
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% basedirs
+t_basedir_api(Config) when is_list(Config) ->
+ true = is_list(filename:basedir(site_data, "My App")),
+ true = is_list(filename:basedir(site_config, "My App")),
+ true = is_list(filename:basedir(user_data, "My App")),
+ true = is_list(filename:basedir(user_log, "My App")),
+ true = is_list(filename:basedir(user_config, "My App")),
+ true = is_list(filename:basedir(user_cache, "My App")),
+
+ true = is_list(filename:basedir(site_data, <<"My App">>)),
+ true = is_list(filename:basedir(site_config, <<"My App">>)),
+ true = is_binary(filename:basedir(user_data, <<"My App">>)),
+ true = is_binary(filename:basedir(user_log, <<"My App">>)),
+ true = is_binary(filename:basedir(user_config, <<"My App">>)),
+ true = is_binary(filename:basedir(user_cache, <<"My App">>)),
+
+ %% simulate for windows
+ case os:type() of
+ {win32,_} -> ok;
+ _ ->
+ os:putenv("APPDATA", "C:\\Documents and Settings\\otptest\\Application Data")
+ end,
+
+ true = is_list(filename:basedir(site_data, "My App", #{})),
+ true = is_list(filename:basedir(site_config, "My App", #{os=>linux})),
+ true = is_list(filename:basedir(user_data, "My App", #{os=>darwin})),
+ true = is_list(filename:basedir(user_log, "My App", #{os=>windows})),
+ true = is_list(filename:basedir(user_config, "My App",#{author=>"Erl"})),
+ true = is_list(filename:basedir(user_config, "My App",#{os=>darwin,
+ author=>"Erl"})),
+ true = is_list(filename:basedir(user_config, "My App",#{os=>linux,
+ author=>"Erl"})),
+ true = is_list(filename:basedir(user_cache, "My App",#{os=>windows,
+ author=>"Erl"})),
+ true = is_list(filename:basedir(user_config, "My App",#{os=>darwin,
+ author=>"Erla",
+ version=>"1.0"})),
+ true = is_list(filename:basedir(user_config, "My App",#{os=>linux,
+ version=>"2.0.1",
+ author=>"Erl"})),
+ true = is_list(filename:basedir(user_cache, "My App",#{os=>windows,
+ version=>"3.1.2",
+ author=>"Erl"})),
+ true = is_binary(filename:basedir(user_config, "My App",#{os=>darwin,
+ author=>"Erla",
+ version=><<"1.0">>})),
+ true = is_binary(filename:basedir(user_config, "My App",#{os=>windows,
+ version=>"2.0.1",
+ author=><<"Erl">>})),
+ true = is_binary(filename:basedir(user_cache, "My App",#{os=>linux,
+ version=><<"3.1.2">>,
+ author=>"Erl"})),
+ %% simulate for windows
+ case os:type() of
+ {win32,_} -> ok;
+ _ -> os:unsetenv("APPDATA")
+ end,
+
+ {'EXIT', _} = (catch filename:basedir(wrong_config, "My App")),
+ {'EXIT', _} = (catch filename:basedir(user_cache, {bad,name})),
+ {'EXIT', _} = (catch filename:basedir(user_cache, "My App", badopts)),
+ {'EXIT', _} = (catch filename:basedir(user_cache, "My App", [])),
+ ok.
+
+t_basedir_windows(Config) when is_list(Config) ->
+ Types = [user_data,user_log,user_config,user_cache],
case os:type() of
- {win32, _} ->
- ?line <<"a:\\temp\\arne.exe">> =
- filename:nativename(<<"A:/temp//arne.exe/">>);
- _ ->
- ?line <<"/usr/tmp/arne">> =
- filename:nativename(<<"/usr/tmp//arne/">>)
+ {win32,_} ->
+ ok = check_basedir_windows(Types, #{});
+ _ ->
+ %% Windows 7 and beyond
+ os:putenv("APPDATA", "C:\\Users\\otptest\\AppData\\Roaming"),
+ os:putenv("LOCALAPPDATA", "C:\\Users\\otptest\\AppData\\Local"),
+ io:format("APPDATA ~p~n", [os:getenv("APPDATA")]),
+ io:format("LOCALAPPDATA ~p~n", [os:getenv("LOCALAPPDATA")]),
+ ok = check_basedir_windows(Types,#{os=>windows}),
+ %% Windows XP
+ os:unsetenv("LOCALAPPDATA"),
+ os:putenv("APPDATA", "C:\\Documents and Settings\\otptest\\Application Data"),
+ io:format("APPDATA ~p~n", [os:getenv("APPDATA")]),
+ io:format("APPLOCALDATA ~p~n", [os:getenv("APPLOCALDATA")]),
+ ok = check_basedir_windows(Types,#{os=>windows}),
+ os:unsetenv("APPDATA")
+ end,
+ ok.
+
+check_basedir_windows([],_) -> ok;
+check_basedir_windows([Type|Types],Opt) ->
+ Name = "Some Application",
+ io:format("type: ~p~n", [Type]),
+ ok = check_basedir_windows_path(Type,
+ [Name],
+ filename:basedir(Type, Name, Opt)),
+ ok = check_basedir_windows_path(Type,
+ ["Erl",Name],
+ filename:basedir(Type, Name, Opt#{author=>"Erl"})),
+ ok = check_basedir_windows_path(Type,
+ [Name,"1.0"],
+ filename:basedir(Type, Name, Opt#{version=>"1.0"})),
+ ok = check_basedir_windows_path(Type,
+ ["Erl",Name,"1.0"],
+ filename:basedir(Type, Name, Opt#{author=>"Erl",
+ version=>"1.0"})),
+ check_basedir_windows(Types, Opt).
+
+check_basedir_windows_path(Type,Check0,Basedir) ->
+ BDR = lists:reverse(filename:split(Basedir)),
+ Check = lists:reverse(Check0),
+ io:format("~w: ~p ~p~n", [Type,Check,BDR]),
+ case Type of
+ user_log -> check_basedir_windows_path_split(["Logs"|Check],BDR);
+ user_cache -> check_basedir_windows_path_split(["Cache"|Check],BDR);
+ _ -> check_basedir_windows_path_split(Check,BDR)
+ end.
+
+check_basedir_windows_path_split([],_) -> ok;
+check_basedir_windows_path_split([Same|Check],[Same|BDR]) ->
+ check_basedir_windows_path_split(Check,BDR).
+
+
+t_basedir_xdg(Config) when is_list(Config) ->
+ check_basedir_xdg([user_data,user_log,user_config,user_cache,
+ site_data,site_config]),
+ ok.
+
+check_basedir_xdg([]) -> ok;
+check_basedir_xdg([Type|Types]) ->
+ Name = "some_app",
+ Opt = #{os=>linux},
+ Key = basedir_xdg_env(Type),
+ io:format("type: ~p~n", [Type]),
+ Home = os:getenv("HOME"),
+ NDir = "/some/absolute/path",
+ DefPath = basedir_xdg_def(Type,Home,Name),
+ EnvPath = case Type of
+ user_log -> filename:join([NDir,Name,"log"]);
+ site_data -> [filename:join([NDir,Name])];
+ site_config -> [filename:join([NDir,Name])];
+ _ -> filename:join([NDir,Name])
+ end,
+ os:unsetenv(Key),
+ ok = check_basedir(Type, DefPath, filename:basedir(Type, Name, Opt)),
+ os:putenv(Key, NDir),
+ ok = check_basedir(Type, EnvPath, filename:basedir(Type, Name, Opt)),
+ os:unsetenv(Key),
+ ok = check_basedir(Type, DefPath, filename:basedir(Type, Name, Opt)),
+ check_basedir_xdg(Types).
+
+check_basedir(Type, Path, Basedir) ->
+ io:format("~w: ~p = ~p~n", [Type,Path,Basedir]),
+ Path = Basedir,
+ ok.
+
+basedir_xdg_env(Type) ->
+ case Type of
+ user_data -> "XDG_DATA_HOME";
+ user_config -> "XDG_CONFIG_HOME";
+ user_cache -> "XDG_CACHE_HOME";
+ user_log -> "XDG_CACHE_HOME";
+ site_data -> "XDG_DATA_DIRS";
+ site_config -> "XDG_CONFIG_DIRS"
+ end.
+
+basedir_xdg_def(Type,Home,Name) ->
+ case Type of
+ user_data -> filename:join([Home,".local","share",Name]);
+ user_config -> filename:join([Home,".config",Name]);
+ user_cache -> filename:join([Home,".cache",Name]);
+ user_log -> filename:join([Home,".cache",Name,"log"]);
+ site_data -> [filename:join([Dir,Name]) ||
+ Dir <- ["/usr/local/share/","/usr/share/"]];
+ site_config -> [filename:join(["/etc/xdg",Name])]
end.
diff --git a/lib/stdlib/test/fixtable_SUITE.erl b/lib/stdlib/test/fixtable_SUITE.erl
index cf716032a1..de100a11d6 100644
--- a/lib/stdlib/test/fixtable_SUITE.erl
+++ b/lib/stdlib/test/fixtable_SUITE.erl
@@ -33,7 +33,9 @@
%%% Internal exports
-export([command_loop/0,start_commander/0]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[multiple_fixes, multiple_processes,
@@ -56,7 +58,7 @@ end_per_group(_GroupName, Config) ->
Config.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%%% I wrote this thinking I would use more than one temporary at a time, but
%%% I wasn't... Well, maybe in the future...
@@ -68,14 +70,11 @@ end_per_group(_GroupName, Config) ->
-define(HELPER_NODE, (atom_to_list(?MODULE) ++ "_helper1")).
init_per_testcase(_Func, Config) ->
- PrivDir = ?config(priv_dir,Config),
+ PrivDir = proplists:get_value(priv_dir,Config),
file:make_dir(PrivDir),
- Dog=test_server:timetrap(test_server:seconds(60)),
- [{watchdog, Dog}|Config].
+ Config.
end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
lists:foreach(fun(X) ->
(catch dets:close(X)),
(catch file:delete(dets_filename(X,Config)))
@@ -98,302 +97,280 @@ show(Term, Line) ->
-endif.
-fixbag(doc) ->
- ["Check for bug OTP-5087, safe_fixtable for bags could give "
- "incorrect lookups"];
-fixbag(suite) ->
- [];
+%% Check for bug OTP-5087; safe_fixtable for bags could give incorrect
+%% lookups.
fixbag(Config) when is_list(Config) ->
- ?line T = ets:new(x,[bag]),
- ?line ets:insert(T,{a,1}),
- ?line ets:insert(T,{a,2}),
- ?line ets:safe_fixtable(T,true),
- ?line ets:match_delete(T,{a,2}),
- ?line ets:insert(T,{a,3}),
- ?line Res = ets:lookup(T,a),
- ?line ets:safe_fixtable(T,false),
- ?line Res = ets:lookup(T,a),
+ T = ets:new(x,[bag]),
+ ets:insert(T,{a,1}),
+ ets:insert(T,{a,2}),
+ ets:safe_fixtable(T,true),
+ ets:match_delete(T,{a,2}),
+ ets:insert(T,{a,3}),
+ Res = ets:lookup(T,a),
+ ets:safe_fixtable(T,false),
+ Res = ets:lookup(T,a),
ok.
-insert_same_key(doc) ->
- ["Check correct behaviour if a key is deleted and reinserted during fixation."];
-insert_same_key(suite) ->
- [];
+%% Check correct behaviour if a key is deleted and reinserted during
+%% fixation.
insert_same_key(Config) when is_list(Config) ->
- ?line {ok,Dets1} = dets:open_file(?DETS_TMP1,
- [{file, dets_filename(?DETS_TMP1,Config)}]),
- ?line Ets1 = ets:new(ets,[]),
- ?line insert_same_key(Dets1,dets,Config),
- ?line insert_same_key(Ets1,ets,Config),
- ?line ets:insert(Ets1,{1,2}),
- ?line 1 = ets:info(Ets1,size),
- ?line dets:insert(Dets1,{1,2}),
- ?line 1 = dets:info(Dets1,size),
- ?line dets:close(Dets1),
- ?line (catch file:delete(dets_filename(Dets1,Config))),
- ?line ets:delete(Ets1),
- ?line {ok,Dets2} = dets:open_file(?DETS_TMP1,
- [{type,bag},{file, dets_filename(?DETS_TMP1,Config)}]),
- ?line Ets2 = ets:new(ets,[bag]),
- ?line insert_same_key(Dets2,dets,Config),
- ?line insert_same_key(Ets2,ets,Config),
- ?line ets:insert(Ets2,{1,2}),
- ?line 2 = ets:info(Ets2,size),
- ?line ets:insert(Ets2,{1,2}),
- ?line 2 = ets:info(Ets2,size),
- ?line dets:insert(Dets2,{1,2}),
- ?line 2 = dets:info(Dets2,size),
- ?line dets:insert(Dets2,{1,2}),
- ?line 2 = dets:info(Dets2,size),
- ?line dets:close(Dets2),
- ?line (catch file:delete(dets_filename(Dets2,Config))),
- ?line ets:delete(Ets2),
- ?line {ok,Dets3} = dets:open_file(?DETS_TMP1,
- [{type,duplicate_bag},
- {file, dets_filename(?DETS_TMP1,Config)}]),
- ?line Ets3 = ets:new(ets,[duplicate_bag]),
- ?line insert_same_key(Dets3,dets,Config),
- ?line insert_same_key(Ets3,ets,Config),
- ?line ets:insert(Ets3,{1,2}),
- ?line 2 = ets:info(Ets3,size),
- ?line ets:insert(Ets3,{1,2}),
- ?line 3 = ets:info(Ets3,size),
- ?line dets:insert(Dets3,{1,2}),
- ?line 2 = dets:info(Dets3,size),
- ?line dets:insert(Dets3,{1,2}),
- ?line 3 = dets:info(Dets3,size),
- ?line dets:close(Dets3),
- ?line (catch file:delete(dets_filename(Dets3,Config))),
- ?line ets:delete(Ets3),
+ {ok,Dets1} = dets:open_file(?DETS_TMP1,
+ [{file, dets_filename(?DETS_TMP1,Config)}]),
+ Ets1 = ets:new(ets,[]),
+ insert_same_key(Dets1,dets,Config),
+ insert_same_key(Ets1,ets,Config),
+ ets:insert(Ets1,{1,2}),
+ 1 = ets:info(Ets1,size),
+ dets:insert(Dets1,{1,2}),
+ 1 = dets:info(Dets1,size),
+ dets:close(Dets1),
+ (catch file:delete(dets_filename(Dets1,Config))),
+ ets:delete(Ets1),
+ {ok,Dets2} = dets:open_file(?DETS_TMP1,
+ [{type,bag},{file, dets_filename(?DETS_TMP1,Config)}]),
+ Ets2 = ets:new(ets,[bag]),
+ insert_same_key(Dets2,dets,Config),
+ insert_same_key(Ets2,ets,Config),
+ ets:insert(Ets2,{1,2}),
+ 2 = ets:info(Ets2,size),
+ ets:insert(Ets2,{1,2}),
+ 2 = ets:info(Ets2,size),
+ dets:insert(Dets2,{1,2}),
+ 2 = dets:info(Dets2,size),
+ dets:insert(Dets2,{1,2}),
+ 2 = dets:info(Dets2,size),
+ dets:close(Dets2),
+ (catch file:delete(dets_filename(Dets2,Config))),
+ ets:delete(Ets2),
+ {ok,Dets3} = dets:open_file(?DETS_TMP1,
+ [{type,duplicate_bag},
+ {file, dets_filename(?DETS_TMP1,Config)}]),
+ Ets3 = ets:new(ets,[duplicate_bag]),
+ insert_same_key(Dets3,dets,Config),
+ insert_same_key(Ets3,ets,Config),
+ ets:insert(Ets3,{1,2}),
+ 2 = ets:info(Ets3,size),
+ ets:insert(Ets3,{1,2}),
+ 3 = ets:info(Ets3,size),
+ dets:insert(Dets3,{1,2}),
+ 2 = dets:info(Dets3,size),
+ dets:insert(Dets3,{1,2}),
+ 3 = dets:info(Dets3,size),
+ dets:close(Dets3),
+ (catch file:delete(dets_filename(Dets3,Config))),
+ ets:delete(Ets3),
ok.
insert_same_key(Tab,Mod,_Config) ->
- ?line Mod:insert(Tab,{1,1}),
- ?line Mod:insert(Tab,{1,2}),
- ?line Mod:insert(Tab,{2,2}),
- ?line Mod:insert(Tab,{2,2}),
- ?line Mod:safe_fixtable(Tab,true),
- ?line Mod:delete(Tab,1),
- ?line Mod:insert(Tab,{1,1}),
- ?line Expect = case Mod:info(Tab,type) of
- bag ->
- Mod:insert(Tab,{1,2}),
- 2;
- _ ->
- 1
- end,
- ?line Mod:delete(Tab,2),
- ?line Mod:safe_fixtable(Tab,false),
- ?line case Mod:info(Tab,size) of
- Expect ->
- ok;
- _ ->
- exit({size_field_wrong,{Mod,Mod:info(Tab)}})
- end.
-
-
-
-
-owner_dies(doc) ->
- ["Check correct behaviour if the table owner dies."];
-owner_dies(suite) ->
- [];
+ Mod:insert(Tab,{1,1}),
+ Mod:insert(Tab,{1,2}),
+ Mod:insert(Tab,{2,2}),
+ Mod:insert(Tab,{2,2}),
+ Mod:safe_fixtable(Tab,true),
+ Mod:delete(Tab,1),
+ Mod:insert(Tab,{1,1}),
+ Expect = case Mod:info(Tab,type) of
+ bag ->
+ Mod:insert(Tab,{1,2}),
+ 2;
+ _ ->
+ 1
+ end,
+ Mod:delete(Tab,2),
+ Mod:safe_fixtable(Tab,false),
+ case Mod:info(Tab,size) of
+ Expect ->
+ ok;
+ _ ->
+ exit({size_field_wrong,{Mod,Mod:info(Tab)}})
+ end.
+
+
+
+
+%% Check correct behaviour if the table owner dies.
owner_dies(Config) when is_list(Config) ->
- ?line P1 = start_commander(),
- ?line Ets1 = command(P1,{ets,new,[ets,[]]}),
- ?line command(P1,{ets,safe_fixtable,[Ets1,true]}),
- ?line {_,[{P1,1}]} = ets:info(Ets1, safe_fixed),
- ?line stop_commander(P1),
- ?line undefined = ets:info(Ets1, safe_fixed),
- ?line P2 = start_commander(),
- ?line Ets2 = command(P2,{ets,new,[ets,[public]]}),
- ?line command(P2,{ets,safe_fixtable,[Ets2,true]}),
- ?line ets:safe_fixtable(Ets2,true),
- ?line true = ets:info(Ets2, fixed),
- ?line {_,[{_,1},{_,1}]} = ets:info(Ets2, safe_fixed),
- ?line stop_commander(P2),
- ?line undefined = ets:info(Ets2, safe_fixed),
- ?line undefined = ets:info(Ets2, fixed),
- ?line P3 = start_commander(),
- ?line {ok,Dets} = ?LOG(command(P3, {dets, open_file,
- [?DETS_TMP1,
- [{file,
- dets_filename(?DETS_TMP1,
- Config)}]]})),
- ?line command(P3, {dets, safe_fixtable, [Dets, true]}),
- ?line {_,[{P3,1}]} = dets:info(Dets, safe_fixed),
- ?line true = dets:info(Dets, fixed),
- ?line stop_commander(P3),
- ?line undefined = dets:info(Dets, safe_fixed),
- ?line undefined = dets:info(Dets, fixed),
- ?line P4 = start_commander(),
- ?line {ok,Dets} = command(P4, {dets, open_file,
+ P1 = start_commander(),
+ Ets1 = command(P1,{ets,new,[ets,[]]}),
+ command(P1,{ets,safe_fixtable,[Ets1,true]}),
+ {_,[{P1,1}]} = ets:info(Ets1, safe_fixed),
+ stop_commander(P1),
+ undefined = ets:info(Ets1, safe_fixed),
+ P2 = start_commander(),
+ Ets2 = command(P2,{ets,new,[ets,[public]]}),
+ command(P2,{ets,safe_fixtable,[Ets2,true]}),
+ ets:safe_fixtable(Ets2,true),
+ true = ets:info(Ets2, fixed),
+ {_,[{_,1},{_,1}]} = ets:info(Ets2, safe_fixed),
+ stop_commander(P2),
+ undefined = ets:info(Ets2, safe_fixed),
+ undefined = ets:info(Ets2, fixed),
+ P3 = start_commander(),
+ {ok,Dets} = ?LOG(command(P3, {dets, open_file,
+ [?DETS_TMP1,
+ [{file,
+ dets_filename(?DETS_TMP1,
+ Config)}]]})),
+ command(P3, {dets, safe_fixtable, [Dets, true]}),
+ {_,[{P3,1}]} = dets:info(Dets, safe_fixed),
+ true = dets:info(Dets, fixed),
+ stop_commander(P3),
+ undefined = dets:info(Dets, safe_fixed),
+ undefined = dets:info(Dets, fixed),
+ P4 = start_commander(),
+ {ok,Dets} = command(P4, {dets, open_file,
[?DETS_TMP1,
[{file, dets_filename(?DETS_TMP1,Config)}]]}),
- ?line {ok,Dets} = dets:open_file(?DETS_TMP1,
+ {ok,Dets} = dets:open_file(?DETS_TMP1,
[{file, dets_filename(?DETS_TMP1,Config)}]),
- ?line false = dets:info(Dets, safe_fixed),
- ?line command(P4, {dets, safe_fixtable, [Dets, true]}),
- ?line dets:safe_fixtable(Dets, true),
- ?line {_,[{_,1},{_,1}]} = dets:info(Dets, safe_fixed),
- ?line dets:safe_fixtable(Dets, true),
- ?line stop_commander(P4),
- ?line S = self(),
- ?line {_,[{S,2}]} = dets:info(Dets, safe_fixed),
- ?line true = dets:info(Dets, fixed),
- ?line dets:close(Dets),
- ?line undefined = dets:info(Dets, fixed),
- ?line undefined = dets:info(Dets, safe_fixed),
+ false = dets:info(Dets, safe_fixed),
+ command(P4, {dets, safe_fixtable, [Dets, true]}),
+ dets:safe_fixtable(Dets, true),
+ {_,[{_,1},{_,1}]} = dets:info(Dets, safe_fixed),
+ dets:safe_fixtable(Dets, true),
+ stop_commander(P4),
+ S = self(),
+ {_,[{S,2}]} = dets:info(Dets, safe_fixed),
+ true = dets:info(Dets, fixed),
+ dets:close(Dets),
+ undefined = dets:info(Dets, fixed),
+ undefined = dets:info(Dets, safe_fixed),
ok.
-
-
-other_process_closes(doc) ->
- ["When another process closes an dets table, different "
- "things should happen depending on if it has opened it before."];
-other_process_closes(suite) ->
- [];
+%% When another process closes an dets table, different things should
+%% happen depending on if it has opened it before.
other_process_closes(Config) when is_list(Config) ->
- ?line {ok,Dets} = dets:open_file(?DETS_TMP1,
+ {ok,Dets} = dets:open_file(?DETS_TMP1,
[{file, dets_filename(tmp1,Config)}]),
- ?line P2 = start_commander(),
- ?line dets:safe_fixtable(Dets,true),
- ?line S = self(),
- ?line {_,[{S,1}]} = dets:info(Dets, safe_fixed),
- ?line command(P2,{dets, safe_fixtable, [Dets, true]}),
- ?line {_,[_,_]} = dets:info(Dets, safe_fixed),
- ?line {error, not_owner} = command(P2,{dets, close, [Dets]}),
- ?line {_,[_,_]} = dets:info(Dets, safe_fixed),
- ?line command(P2,{dets, open_file,[?DETS_TMP1,
+ P2 = start_commander(),
+ dets:safe_fixtable(Dets,true),
+ S = self(),
+ {_,[{S,1}]} = dets:info(Dets, safe_fixed),
+ command(P2,{dets, safe_fixtable, [Dets, true]}),
+ {_,[_,_]} = dets:info(Dets, safe_fixed),
+ {error, not_owner} = command(P2,{dets, close, [Dets]}),
+ {_,[_,_]} = dets:info(Dets, safe_fixed),
+ command(P2,{dets, open_file,[?DETS_TMP1,
[{file,
dets_filename(?DETS_TMP1, Config)}]]}),
- ?line {_,[_,_]} = dets:info(Dets, safe_fixed),
- ?line command(P2,{dets, close, [Dets]}),
- ?line stop_commander(P2),
- ?line {_,[{S,1}]} = dets:info(Dets, safe_fixed),
- ?line true = dets:info(Dets,fixed),
- ?line dets:close(Dets),
- ?line undefined = dets:info(Dets,fixed),
- ?line undefined = dets:info(Dets, safe_fixed),
+ {_,[_,_]} = dets:info(Dets, safe_fixed),
+ command(P2,{dets, close, [Dets]}),
+ stop_commander(P2),
+ {_,[{S,1}]} = dets:info(Dets, safe_fixed),
+ true = dets:info(Dets,fixed),
+ dets:close(Dets),
+ undefined = dets:info(Dets,fixed),
+ undefined = dets:info(Dets, safe_fixed),
ok.
-
-other_process_deletes(doc) ->
- ["Check that fixtable structures are cleaned up if another process "
- "deletes an ets table"];
-other_process_deletes(suite) ->
- [];
+
+%% Check that fixtable structures are cleaned up if another process
+%% deletes an ets table.
other_process_deletes(Config) when is_list(Config) ->
- ?line Ets = ets:new(ets,[public]),
- ?line P = start_commander(),
- ?line ets:safe_fixtable(Ets,true),
- ?line ets:safe_fixtable(Ets,true),
- ?line true = ets:info(Ets, fixed),
- ?line {_,_} = ets:info(Ets, safe_fixed),
- ?line command(P,{ets,delete,[Ets]}),
- ?line stop_commander(P),
- ?line undefined = ets:info(Ets, fixed),
- ?line undefined = ets:info(Ets, safe_fixed),
+ Ets = ets:new(ets,[public]),
+ P = start_commander(),
+ ets:safe_fixtable(Ets,true),
+ ets:safe_fixtable(Ets,true),
+ true = ets:info(Ets, fixed),
+ {_,_} = ets:info(Ets, safe_fixed),
+ command(P,{ets,delete,[Ets]}),
+ stop_commander(P),
+ undefined = ets:info(Ets, fixed),
+ undefined = ets:info(Ets, safe_fixed),
ok.
-multiple_fixes(doc) ->
- ["Check that multiple safe_fixtable keeps the reference counter."];
-multiple_fixes(suite) ->
- [];
+%% Check that multiple safe_fixtable keeps the reference counter.
multiple_fixes(Config) when is_list(Config) ->
- ?line {ok,Dets} = dets:open_file(?DETS_TMP1,
+ {ok,Dets} = dets:open_file(?DETS_TMP1,
[{file, dets_filename(?DETS_TMP1,Config)}]),
- ?line Ets = ets:new(ets,[]),
- ?line multiple_fixes(Dets,dets),
- ?line multiple_fixes(Ets,ets),
- ?line dets:close(Dets),
+ Ets = ets:new(ets,[]),
+ multiple_fixes(Dets,dets),
+ multiple_fixes(Ets,ets),
+ dets:close(Dets),
ok.
multiple_fixes(Tab, Mod) ->
- ?line false = Mod:info(Tab,fixed),
- ?line false = Mod:info(Tab, safe_fixed),
- ?line Mod:safe_fixtable(Tab, true),
- ?line true = Mod:info(Tab,fixed),
- ?line S = self(),
- ?line {_,[{S,1}]} = Mod:info(Tab, safe_fixed),
- ?line Mod:safe_fixtable(Tab, true),
- ?line Mod:safe_fixtable(Tab, true),
- ?line {_,[{S,3}]} = Mod:info(Tab, safe_fixed),
- ?line true = Mod:info(Tab,fixed),
- ?line Mod:safe_fixtable(Tab, false),
- ?line {_,[{S,2}]} = Mod:info(Tab, safe_fixed),
- ?line true = Mod:info(Tab,fixed),
- ?line Mod:safe_fixtable(Tab, false),
- ?line {_,[{S,1}]} = Mod:info(Tab, safe_fixed),
- ?line true = Mod:info(Tab,fixed),
- ?line Mod:safe_fixtable(Tab, false),
- ?line false = Mod:info(Tab, safe_fixed),
- ?line false = Mod:info(Tab,fixed).
-
-multiple_processes(doc) ->
- ["Check that multiple safe_fixtable across processes are reference "
- "counted OK"];
-multiple_processes(suite) ->
- [];
+ false = Mod:info(Tab,fixed),
+ false = Mod:info(Tab, safe_fixed),
+ Mod:safe_fixtable(Tab, true),
+ true = Mod:info(Tab,fixed),
+ S = self(),
+ {_,[{S,1}]} = Mod:info(Tab, safe_fixed),
+ Mod:safe_fixtable(Tab, true),
+ Mod:safe_fixtable(Tab, true),
+ {_,[{S,3}]} = Mod:info(Tab, safe_fixed),
+ true = Mod:info(Tab,fixed),
+ Mod:safe_fixtable(Tab, false),
+ {_,[{S,2}]} = Mod:info(Tab, safe_fixed),
+ true = Mod:info(Tab,fixed),
+ Mod:safe_fixtable(Tab, false),
+ {_,[{S,1}]} = Mod:info(Tab, safe_fixed),
+ true = Mod:info(Tab,fixed),
+ Mod:safe_fixtable(Tab, false),
+ false = Mod:info(Tab, safe_fixed),
+ false = Mod:info(Tab,fixed).
+
+%% Check that multiple safe_fixtable across processes are reference
+%% counted OK.
multiple_processes(Config) when is_list(Config) ->
- ?line {ok,Dets} = dets:open_file(?DETS_TMP1,[{file,
+ {ok,Dets} = dets:open_file(?DETS_TMP1,[{file,
dets_filename(?DETS_TMP1,
Config)}]),
- ?line Ets = ets:new(ets,[public]),
- ?line multiple_processes(Dets,dets),
- ?line multiple_processes(Ets,ets),
+ Ets = ets:new(ets,[public]),
+ multiple_processes(Dets,dets),
+ multiple_processes(Ets,ets),
ok.
multiple_processes(Tab, Mod) ->
- ?line io:format("Mod = ~p\n", [Mod]),
- ?line P1 = start_commander(),
- ?line P2 = start_commander(),
- ?line false = Mod:info(Tab,fixed),
- ?line false = Mod:info(Tab, safe_fixed),
- ?line command(P1, {Mod, safe_fixtable, [Tab,true]}),
- ?line true = Mod:info(Tab,fixed),
- ?line {_,[{P1,1}]} = Mod:info(Tab, safe_fixed),
- ?line command(P2, {Mod, safe_fixtable, [Tab,true]}),
- ?line true = Mod:info(Tab,fixed),
- ?line {_,L} = Mod:info(Tab,safe_fixed),
- ?line true = (lists:sort(L) == lists:sort([{P1,1},{P2,1}])),
- ?line command(P2, {Mod, safe_fixtable, [Tab,true]}),
- ?line {_,L2} = Mod:info(Tab,safe_fixed),
- ?line true = (lists:sort(L2) == lists:sort([{P1,1},{P2,2}])),
- ?line command(P2, {Mod, safe_fixtable, [Tab,false]}),
- ?line true = Mod:info(Tab,fixed),
- ?line {_,L3} = Mod:info(Tab,safe_fixed),
- ?line true = (lists:sort(L3) == lists:sort([{P1,1},{P2,1}])),
- ?line command(P2, {Mod, safe_fixtable, [Tab,false]}),
- ?line true = Mod:info(Tab,fixed),
- ?line {_,[{P1,1}]} = Mod:info(Tab, safe_fixed),
- ?line stop_commander(P1),
- ?line receive after 1000 -> ok end,
- ?line false = Mod:info(Tab,fixed),
- ?line false = Mod:info(Tab, safe_fixed),
- ?line command(P2, {Mod, safe_fixtable, [Tab,true]}),
- ?line true = Mod:info(Tab,fixed),
- ?line {_,[{P2,1}]} = Mod:info(Tab, safe_fixed),
+ io:format("Mod = ~p\n", [Mod]),
+ P1 = start_commander(),
+ P2 = start_commander(),
+ false = Mod:info(Tab,fixed),
+ false = Mod:info(Tab, safe_fixed),
+ command(P1, {Mod, safe_fixtable, [Tab,true]}),
+ true = Mod:info(Tab,fixed),
+ {_,[{P1,1}]} = Mod:info(Tab, safe_fixed),
+ command(P2, {Mod, safe_fixtable, [Tab,true]}),
+ true = Mod:info(Tab,fixed),
+ {_,L} = Mod:info(Tab,safe_fixed),
+ true = (lists:sort(L) == lists:sort([{P1,1},{P2,1}])),
+ command(P2, {Mod, safe_fixtable, [Tab,true]}),
+ {_,L2} = Mod:info(Tab,safe_fixed),
+ true = (lists:sort(L2) == lists:sort([{P1,1},{P2,2}])),
+ command(P2, {Mod, safe_fixtable, [Tab,false]}),
+ true = Mod:info(Tab,fixed),
+ {_,L3} = Mod:info(Tab,safe_fixed),
+ true = (lists:sort(L3) == lists:sort([{P1,1},{P2,1}])),
+ command(P2, {Mod, safe_fixtable, [Tab,false]}),
+ true = Mod:info(Tab,fixed),
+ {_,[{P1,1}]} = Mod:info(Tab, safe_fixed),
+ stop_commander(P1),
+ receive after 1000 -> ok end,
+ false = Mod:info(Tab,fixed),
+ false = Mod:info(Tab, safe_fixed),
+ command(P2, {Mod, safe_fixtable, [Tab,true]}),
+ true = Mod:info(Tab,fixed),
+ {_,[{P2,1}]} = Mod:info(Tab, safe_fixed),
case Mod of
dets ->
- ?line dets:close(Tab);
+ dets:close(Tab);
ets ->
- ?line ets:delete(Tab)
+ ets:delete(Tab)
end,
- ?line stop_commander(P2),
- ?line receive after 1000 -> ok end,
- ?line undefined = Mod:info(Tab, safe_fixed),
+ stop_commander(P2),
+ receive after 1000 -> ok end,
+ undefined = Mod:info(Tab, safe_fixed),
ok.
-
-
+
+
%%% Helpers
dets_filename(Base, Config) when is_atom(Base) ->
dets_filename(atom_to_list(Base) ++ ".dat", Config);
dets_filename(Basename, Config) ->
- PrivDir = ?config(priv_dir,Config),
+ PrivDir = proplists:get_value(priv_dir,Config),
filename:join(PrivDir, Basename).
command_loop() ->
diff --git a/lib/stdlib/test/format_SUITE.erl b/lib/stdlib/test/format_SUITE.erl
index 77636687cd..b481d82ea6 100644
--- a/lib/stdlib/test/format_SUITE.erl
+++ b/lib/stdlib/test/format_SUITE.erl
@@ -25,20 +25,17 @@
-export([init_per_testcase/2, end_per_testcase/2]).
--include_lib("test_server/include/test_server.hrl").
-
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
+-include_lib("common_test/include/ct.hrl").
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+ Config.
+
+end_per_testcase(_Case, _Config) ->
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[hang_1].
@@ -59,11 +56,8 @@ end_per_group(_GroupName, Config) ->
Config.
-hang_1(doc) ->
- ["Bad args can hang (OTP-2400)"];
-hang_1(suite) ->
- [];
+%% OTP-2400. Bad args can hang.
hang_1(Config) when is_list(Config) ->
- ?line _ = (catch io:format(a, "", [])),
- ?line _ = (catch io:format({}, "", [])),
+ _ = (catch io:format(a, "", [])),
+ _ = (catch io:format({}, "", [])),
ok.
diff --git a/lib/stdlib/test/gen_event_SUITE.erl b/lib/stdlib/test/gen_event_SUITE.erl
index b019f98b69..4bad7801ff 100644
--- a/lib/stdlib/test/gen_event_SUITE.erl
+++ b/lib/stdlib/test/gen_event_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(gen_event_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
@@ -59,75 +59,72 @@ end_per_group(_GroupName, Config) ->
%% Start an event manager.
%% --------------------------------------
-start(doc) -> [];
-start(suite) -> [];
start(Config) when is_list(Config) ->
OldFl = process_flag(trap_exit, true),
- ?line dummy_via:reset(),
+ dummy_via:reset(),
- ?line {ok, Pid0} = gen_event:start(), %anonymous
- ?line [] = gen_event:which_handlers(Pid0),
- ?line ok = gen_event:stop(Pid0),
+ {ok, Pid0} = gen_event:start(), %anonymous
+ [] = gen_event:which_handlers(Pid0),
+ ok = gen_event:stop(Pid0),
- ?line {ok, Pid1} = gen_event:start_link(), %anonymous
- ?line [] = gen_event:which_handlers(Pid1),
- ?line ok = gen_event:stop(Pid1),
+ {ok, Pid1} = gen_event:start_link(), %anonymous
+ [] = gen_event:which_handlers(Pid1),
+ ok = gen_event:stop(Pid1),
- ?line {ok, Pid2} = gen_event:start({local, my_dummy_name}),
- ?line [] = gen_event:which_handlers(my_dummy_name),
- ?line [] = gen_event:which_handlers(Pid2),
- ?line ok = gen_event:stop(my_dummy_name),
+ {ok, Pid2} = gen_event:start({local, my_dummy_name}),
+ [] = gen_event:which_handlers(my_dummy_name),
+ [] = gen_event:which_handlers(Pid2),
+ ok = gen_event:stop(my_dummy_name),
- ?line {ok, Pid3} = gen_event:start_link({local, my_dummy_name}),
- ?line [] = gen_event:which_handlers(my_dummy_name),
- ?line [] = gen_event:which_handlers(Pid3),
- ?line ok = gen_event:stop(my_dummy_name),
+ {ok, Pid3} = gen_event:start_link({local, my_dummy_name}),
+ [] = gen_event:which_handlers(my_dummy_name),
+ [] = gen_event:which_handlers(Pid3),
+ ok = gen_event:stop(my_dummy_name),
- ?line {ok, Pid4} = gen_event:start_link({global, my_dummy_name}),
- ?line [] = gen_event:which_handlers({global, my_dummy_name}),
- ?line [] = gen_event:which_handlers(Pid4),
- ?line ok = gen_event:stop({global, my_dummy_name}),
+ {ok, Pid4} = gen_event:start_link({global, my_dummy_name}),
+ [] = gen_event:which_handlers({global, my_dummy_name}),
+ [] = gen_event:which_handlers(Pid4),
+ ok = gen_event:stop({global, my_dummy_name}),
- ?line {ok, Pid5} = gen_event:start_link({via, dummy_via, my_dummy_name}),
- ?line [] = gen_event:which_handlers({via, dummy_via, my_dummy_name}),
- ?line [] = gen_event:which_handlers(Pid5),
- ?line ok = gen_event:stop({via, dummy_via, my_dummy_name}),
+ {ok, Pid5} = gen_event:start_link({via, dummy_via, my_dummy_name}),
+ [] = gen_event:which_handlers({via, dummy_via, my_dummy_name}),
+ [] = gen_event:which_handlers(Pid5),
+ ok = gen_event:stop({via, dummy_via, my_dummy_name}),
- ?line {ok, _} = gen_event:start_link({local, my_dummy_name}),
- ?line {error, {already_started, _}} =
+ {ok, _} = gen_event:start_link({local, my_dummy_name}),
+ {error, {already_started, _}} =
gen_event:start_link({local, my_dummy_name}),
- ?line {error, {already_started, _}} =
+ {error, {already_started, _}} =
gen_event:start({local, my_dummy_name}),
- ?line ok = gen_event:stop(my_dummy_name),
+ ok = gen_event:stop(my_dummy_name),
- ?line {ok, Pid6} = gen_event:start_link({global, my_dummy_name}),
- ?line {error, {already_started, _}} =
+ {ok, Pid6} = gen_event:start_link({global, my_dummy_name}),
+ {error, {already_started, _}} =
gen_event:start_link({global, my_dummy_name}),
- ?line {error, {already_started, _}} =
+ {error, {already_started, _}} =
gen_event:start({global, my_dummy_name}),
ok = gen_event:stop({global, my_dummy_name}, shutdown, 10000),
receive
{'EXIT', Pid6, shutdown} -> ok
after 10000 ->
- ?t:fail(exit_gen_event)
+ ct:fail(exit_gen_event)
end,
- ?line {ok, Pid7} = gen_event:start_link({via, dummy_via, my_dummy_name}),
- ?line {error, {already_started, _}} =
+ {ok, Pid7} = gen_event:start_link({via, dummy_via, my_dummy_name}),
+ {error, {already_started, _}} =
gen_event:start_link({via, dummy_via, my_dummy_name}),
- ?line {error, {already_started, _}} =
+ {error, {already_started, _}} =
gen_event:start({via, dummy_via, my_dummy_name}),
exit(Pid7, shutdown),
receive
{'EXIT', Pid7, shutdown} -> ok
after 10000 ->
- ?t:fail(exit_gen_event)
+ ct:fail(exit_gen_event)
end,
- ?t:messages_get(),
process_flag(trap_exit, OldFl),
ok.
@@ -184,7 +181,7 @@ hibernate(Config) when is_list(Config) ->
{ok,Pid2} = gen_event:start({local, my_dummy_handler}),
ok = gen_event:add_handler(my_dummy_handler, dummy_h,
- [self(),hibernate]),
+ [self(),hibernate]),
is_in_erlang_hibernate(Pid2),
sys:suspend(my_dummy_handler),
is_in_erlang_hibernate(Pid2),
@@ -193,7 +190,7 @@ hibernate(Config) when is_list(Config) ->
Pid2 ! wake,
is_not_in_erlang_hibernate(Pid2),
-
+
ok = gen_event:stop(my_dummy_handler),
ok.
@@ -204,7 +201,7 @@ is_in_erlang_hibernate(Pid) ->
is_in_erlang_hibernate_1(0, Pid) ->
io:format("~p\n", [erlang:process_info(Pid, current_function)]),
- ?t:fail(not_in_erlang_hibernate_3);
+ ct:fail(not_in_erlang_hibernate_3);
is_in_erlang_hibernate_1(N, Pid) ->
{current_function,MFA} = erlang:process_info(Pid, current_function),
case MFA of
@@ -221,7 +218,7 @@ is_not_in_erlang_hibernate(Pid) ->
is_not_in_erlang_hibernate_1(0, Pid) ->
io:format("~p\n", [erlang:process_info(Pid, current_function)]),
- ?t:fail(not_in_erlang_hibernate_3);
+ ct:fail(not_in_erlang_hibernate_3);
is_not_in_erlang_hibernate_1(N, Pid) ->
{current_function,MFA} = erlang:process_info(Pid, current_function),
case MFA of
@@ -233,720 +230,694 @@ is_not_in_erlang_hibernate_1(N, Pid) ->
end.
-add_handler(doc) -> [];
-add_handler(suite) -> [];
add_handler(Config) when is_list(Config) ->
- ?line {ok,_} = gen_event:start({local, my_dummy_handler}),
- ?line {error, my_error} =
+ {ok,_} = gen_event:start({local, my_dummy_handler}),
+ {error, my_error} =
gen_event:add_handler(my_dummy_handler, dummy_h, make_error),
- ?line [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
- ?line [dummy_h] = gen_event:which_handlers(my_dummy_handler),
+ [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
+ [dummy_h] = gen_event:which_handlers(my_dummy_handler),
- ?line {error, my_error} =
+ {error, my_error} =
gen_event:add_handler(my_dummy_handler, {dummy_h, self()}, make_error),
- ?line [dummy_h] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_handler(my_dummy_handler, {dummy_h,self()},
- [self()]),
+ [dummy_h] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, {dummy_h,self()},
+ [self()]),
Self = self(),
- ?line [{dummy_h, Self}, dummy_h] =
+ [{dummy_h, Self}, dummy_h] =
gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:stop(my_dummy_handler),
+ ok = gen_event:stop(my_dummy_handler),
ok.
-add_sup_handler(doc) -> [];
-add_sup_handler(suite) -> [];
add_sup_handler(Config) when is_list(Config) ->
- ?line {ok,Pid} = gen_event:start({local, my_dummy_handler}),
- ?line {error, my_error} =
+ {ok,Pid} = gen_event:start({local, my_dummy_handler}),
+ {error, my_error} =
gen_event:add_sup_handler(my_dummy_handler, dummy_h, make_error),
- ?line [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
- ?line [dummy_h] = gen_event:which_handlers(my_dummy_handler),
- ?line exit(Pid, sup_died),
- ?t:sleep(1000),
- ?line [] = gen_event:which_handlers(my_dummy_handler),
+ [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
+ [dummy_h] = gen_event:which_handlers(my_dummy_handler),
+ exit(Pid, sup_died),
+ ct:sleep(1000),
+ [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
- ?line [dummy_h] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
+ [dummy_h] = gen_event:which_handlers(my_dummy_handler),
- ?line {error, my_error} =
+ {error, my_error} =
gen_event:add_handler(my_dummy_handler, {dummy_h, self()}, make_error),
- ?line [dummy_h] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, {dummy_h,self()},
- [self()]),
+ [dummy_h] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_sup_handler(my_dummy_handler, {dummy_h,self()},
+ [self()]),
Self = self(),
- ?line [{dummy_h, Self}, dummy_h] =
+ [{dummy_h, Self}, dummy_h] =
gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:stop(my_dummy_handler),
-
- ?line receive
- {gen_event_EXIT, dummy_h, shutdown} ->
- ok
- after 1000 ->
- ?t:fail({no,{gen_event_EXIT, dummy_h, shutdown}})
- end,
-
- ?line receive
- {gen_event_EXIT, {dummy_h,Self}, shutdown} ->
- ok
- after 1000 ->
- ?t:fail({no,{gen_event_EXIT, {dummy_h,Self},
- shutdown}})
- end,
+ ok = gen_event:stop(my_dummy_handler),
+
+ receive
+ {gen_event_EXIT, dummy_h, shutdown} ->
+ ok
+ after 1000 ->
+ ct:fail({no,{gen_event_EXIT, dummy_h, shutdown}})
+ end,
+
+ receive
+ {gen_event_EXIT, {dummy_h,Self}, shutdown} ->
+ ok
+ after 1000 ->
+ ct:fail({no,{gen_event_EXIT, {dummy_h,Self},
+ shutdown}})
+ end,
ok.
-delete_handler(doc) -> [];
-delete_handler(suite) -> [];
delete_handler(Config) when is_list(Config) ->
- ?line {ok,_} = gen_event:start({local, my_dummy_handler}),
- ?line ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
- ?line {error, module_not_found} =
+ {ok,_} = gen_event:start({local, my_dummy_handler}),
+ ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
+ {error, module_not_found} =
gen_event:delete_handler(my_dummy_handler, duuuuuuuuumy, []),
- ?line return_hej =
+ return_hej =
gen_event:delete_handler(my_dummy_handler, dummy_h, return_hej),
- ?line [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
- ?line ok =
+ [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
+ ok =
gen_event:delete_handler(my_dummy_handler, dummy_h, []),
- ?line [] = gen_event:which_handlers(my_dummy_handler),
+ [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_handler(my_dummy_handler, {dummy_h,1}, [self()]),
- ?line ok = gen_event:add_handler(my_dummy_handler, {dummy_h,2}, [self()]),
- ?line {error, module_not_found} =
+ ok = gen_event:add_handler(my_dummy_handler, {dummy_h,1}, [self()]),
+ ok = gen_event:add_handler(my_dummy_handler, {dummy_h,2}, [self()]),
+ {error, module_not_found} =
gen_event:delete_handler(my_dummy_handler, {duuuuuuuuumy,1}, []),
- ?line return_hej =
+ return_hej =
gen_event:delete_handler(my_dummy_handler, {dummy_h,1}, return_hej),
- ?line return_hej =
+ return_hej =
gen_event:delete_handler(my_dummy_handler, {dummy_h,2}, return_hej),
- ?line [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_handler(my_dummy_handler, {dummy_h,2}, [self()]),
- ?line ok =
+ [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, {dummy_h,2}, [self()]),
+ ok =
gen_event:delete_handler(my_dummy_handler, {dummy_h,2}, []),
- ?line [] = gen_event:which_handlers(my_dummy_handler),
+ [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:stop(my_dummy_handler),
+ ok = gen_event:stop(my_dummy_handler),
ok.
-swap_handler(doc) -> [];
-swap_handler(suite) -> [];
swap_handler(Config) when is_list(Config) ->
- ?line {ok,_} = gen_event:start({local, my_dummy_handler}),
- ?line ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
- ?line {error, non_existing} =
+ {ok,_} = gen_event:start({local, my_dummy_handler}),
+ ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
+ {error, non_existing} =
gen_event:swap_handler(my_dummy_handler, {faulty_h, swap},
{dummy1_h, []}),
- ?line ok =
+ ok =
gen_event:swap_handler(my_dummy_handler, {dummy_h, swap},
{dummy1_h, swap}),
- ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
+ [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:delete_handler(my_dummy_handler, dummy1_h, []),
+ ok = gen_event:delete_handler(my_dummy_handler, dummy1_h, []),
- ?line ok = gen_event:add_handler(my_dummy_handler, {dummy_h,3}, [self()]),
- ?line {error, non_existing} =
+ ok = gen_event:add_handler(my_dummy_handler, {dummy_h,3}, [self()]),
+ {error, non_existing} =
gen_event:swap_handler(my_dummy_handler, {faulty_h, swap},
{dummy1_h, []}),
- ?line ok =
+ ok =
gen_event:swap_handler(my_dummy_handler, {{dummy_h,3}, swap},
{{dummy1_h,4}, swap}),
- ?line [{dummy1_h,4}] = gen_event:which_handlers(my_dummy_handler),
+ [{dummy1_h,4}] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:delete_handler(my_dummy_handler, {dummy1_h,4}, []),
+ ok = gen_event:delete_handler(my_dummy_handler, {dummy1_h,4}, []),
- ?line ok = gen_event:stop(my_dummy_handler),
+ ok = gen_event:stop(my_dummy_handler),
ok.
-
-swap_sup_handler(doc) -> [];
-swap_sup_handler(suite) -> [];
+
swap_sup_handler(Config) when is_list(Config) ->
- ?line {ok,_} = gen_event:start({local, my_dummy_handler}),
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
- ?line {error, non_existing} =
+ {ok,_} = gen_event:start({local, my_dummy_handler}),
+ ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
+ {error, non_existing} =
gen_event:swap_handler(my_dummy_handler, {faulty_h, swap},
{dummy1_h, []}),
- ?line ok =
+ ok =
gen_event:swap_handler(my_dummy_handler, {dummy_h, swap},
{dummy1_h, swap}),
- ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
-
- ?line ok = gen_event:delete_handler(my_dummy_handler, dummy1_h, []),
- ?line receive
- {gen_event_EXIT, dummy1_h, normal} ->
- ok
- after 1000 ->
- ?t:fail({no,{gen_event_EXIT, dummy1_h, normal}})
- end,
-
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, {dummy_h,3},
- [self()]),
- ?line {error, non_existing} =
+ [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
+
+ ok = gen_event:delete_handler(my_dummy_handler, dummy1_h, []),
+ receive
+ {gen_event_EXIT, dummy1_h, normal} ->
+ ok
+ after 1000 ->
+ ct:fail({no,{gen_event_EXIT, dummy1_h, normal}})
+ end,
+
+ ok = gen_event:add_sup_handler(my_dummy_handler, {dummy_h,3},
+ [self()]),
+ {error, non_existing} =
gen_event:swap_sup_handler(my_dummy_handler, {faulty_h, swap},
{dummy1_h, []}),
- ?line ok =
+ ok =
gen_event:swap_sup_handler(my_dummy_handler, {{dummy_h,3}, swap},
{{dummy1_h,4}, swap}),
- ?line [{dummy1_h,4}] = gen_event:which_handlers(my_dummy_handler),
+ [{dummy1_h,4}] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:delete_handler(my_dummy_handler, {dummy1_h,4}, []),
- ?line receive
- {gen_event_EXIT, {dummy1_h,4}, normal} ->
- ok
- after 1000 ->
- ?t:fail({no,{gen_event_EXIT, {dummy1_h,4}, normal}})
- end,
+ ok = gen_event:delete_handler(my_dummy_handler, {dummy1_h,4}, []),
+ receive
+ {gen_event_EXIT, {dummy1_h,4}, normal} ->
+ ok
+ after 1000 ->
+ ct:fail({no,{gen_event_EXIT, {dummy1_h,4}, normal}})
+ end,
- ?line ok = gen_event:stop(my_dummy_handler),
+ ok = gen_event:stop(my_dummy_handler),
ok.
-
-notify(doc) -> [];
-notify(suite) -> [];
+
notify(Config) when is_list(Config) ->
- ?line {ok,_} = gen_event:start({local, my_dummy_handler}),
- ?line ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
+ {ok,_} = gen_event:start({local, my_dummy_handler}),
+ ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
Event = {event, self()},
- ?line [dummy_h] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:notify(my_dummy_handler, Event),
- ?line receive
- {dummy_h, Event} ->
- ok
- end,
- ?line ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}),
- ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:notify(my_dummy_handler, Event),
- ?line receive
- {dummy1_h, Event} ->
- ok
- end,
- ?line ok = gen_event:notify(my_dummy_handler, delete_event),
- ?line receive
- {dummy1_h, removed} ->
- ok
- end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
-
- ?line ok = gen_event:notify(my_dummy_handler, error_event),
- ?line receive
- {dummy_h, returned_error} ->
- ok
- end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
+ [dummy_h] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:notify(my_dummy_handler, Event),
+ receive
+ {dummy_h, Event} ->
+ ok
+ end,
+ ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}),
+ [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:notify(my_dummy_handler, Event),
+ receive
+ {dummy1_h, Event} ->
+ ok
+ end,
+ ok = gen_event:notify(my_dummy_handler, delete_event),
+ receive
+ {dummy1_h, removed} ->
+ ok
+ end,
+ [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
+
+ ok = gen_event:notify(my_dummy_handler, error_event),
+ receive
+ {dummy_h, returned_error} ->
+ ok
+ end,
+ [] = gen_event:which_handlers(my_dummy_handler),
%% Handler with id, {Mod,Id}
- ?line ok = gen_event:add_handler(my_dummy_handler, {dummy_h,5}, [self()]),
- ?line [{dummy_h,5}] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:notify(my_dummy_handler, Event),
- ?line receive
- {dummy_h, Event} ->
- ok
- end,
- ?line ok = gen_event:notify(my_dummy_handler,
- {swap_event, {dummy1_h, 9}, swap}),
- ?line [{dummy1_h,9}] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:notify(my_dummy_handler, Event),
- ?line receive
- {dummy1_h, Event} ->
- ok
- end,
- ?line ok = gen_event:notify(my_dummy_handler, delete_event),
- ?line receive
- {dummy1_h, removed} ->
- ok
- end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_handler(my_dummy_handler, {dummy_h,a}, [self()]),
-
- ?line ok = gen_event:notify(my_dummy_handler, error_event),
- ?line receive
- {dummy_h, returned_error} ->
- ok
- end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, {dummy_h,5}, [self()]),
+ [{dummy_h,5}] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:notify(my_dummy_handler, Event),
+ receive
+ {dummy_h, Event} ->
+ ok
+ end,
+ ok = gen_event:notify(my_dummy_handler,
+ {swap_event, {dummy1_h, 9}, swap}),
+ [{dummy1_h,9}] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:notify(my_dummy_handler, Event),
+ receive
+ {dummy1_h, Event} ->
+ ok
+ end,
+ ok = gen_event:notify(my_dummy_handler, delete_event),
+ receive
+ {dummy1_h, removed} ->
+ ok
+ end,
+ [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, {dummy_h,a}, [self()]),
+
+ ok = gen_event:notify(my_dummy_handler, error_event),
+ receive
+ {dummy_h, returned_error} ->
+ ok
+ end,
+ [] = gen_event:which_handlers(my_dummy_handler),
%% Supervised handler.
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
- ?line [dummy_h] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:notify(my_dummy_handler, Event),
- ?line receive
- {dummy_h, Event} ->
- ok
- end,
-
- ?line ok = gen_event:notify(my_dummy_handler, do_crash),
- ?line receive
- {gen_event_EXIT, dummy_h, {'EXIT',_}} ->
- ok
- end,
-
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
- ?line ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}),
- ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
-
- ?line ok = gen_event:notify(my_dummy_handler, do_crash),
- ?line receive
- {gen_event_EXIT, dummy1_h, {'EXIT',_}} ->
- ok
- end,
-
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
- ?line ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}),
- ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
-
- ?line ok = gen_event:notify(my_dummy_handler, delete_event),
- ?line receive
- {dummy1_h, removed} ->
- ok
- end,
-
- ?line receive
- {gen_event_EXIT, dummy1_h, normal} ->
- ok
- end,
-
- ?line [] = gen_event:which_handlers(my_dummy_handler),
-
- ?line ok = gen_event:stop(my_dummy_handler),
+ ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
+ [dummy_h] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:notify(my_dummy_handler, Event),
+ receive
+ {dummy_h, Event} ->
+ ok
+ end,
+
+ ok = gen_event:notify(my_dummy_handler, do_crash),
+ receive
+ {gen_event_EXIT, dummy_h, {'EXIT',_}} ->
+ ok
+ end,
+
+ ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
+ ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}),
+ [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
+
+ ok = gen_event:notify(my_dummy_handler, do_crash),
+ receive
+ {gen_event_EXIT, dummy1_h, {'EXIT',_}} ->
+ ok
+ end,
+
+ ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
+ ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}),
+ [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
+
+ ok = gen_event:notify(my_dummy_handler, delete_event),
+ receive
+ {dummy1_h, removed} ->
+ ok
+ end,
+
+ receive
+ {gen_event_EXIT, dummy1_h, normal} ->
+ ok
+ end,
+
+ [] = gen_event:which_handlers(my_dummy_handler),
+
+ ok = gen_event:stop(my_dummy_handler),
ok.
-sync_notify(doc) -> [];
-sync_notify(suite) -> [];
sync_notify(Config) when is_list(Config) ->
- ?line {ok,_} = gen_event:start({local, my_dummy_handler}),
- ?line ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
+ {ok,_} = gen_event:start({local, my_dummy_handler}),
+ ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
Event = {event, self()},
- ?line [dummy_h] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:sync_notify(my_dummy_handler, Event),
- ?line receive
- {dummy_h, Event} ->
- ok
- end,
- ?line ok = gen_event:sync_notify(my_dummy_handler,
- {swap_event, dummy1_h, swap}),
- ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:sync_notify(my_dummy_handler, Event),
- ?line receive
- {dummy1_h, Event} ->
- ok
- end,
- ?line ok = gen_event:sync_notify(my_dummy_handler, delete_event),
- ?line receive
- {dummy1_h, removed} ->
- ok
- end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
-
- ?line ok = gen_event:sync_notify(my_dummy_handler, error_event),
- ?line receive
- {dummy_h, returned_error} ->
- ok
- end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
+ [dummy_h] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:sync_notify(my_dummy_handler, Event),
+ receive
+ {dummy_h, Event} ->
+ ok
+ end,
+ ok = gen_event:sync_notify(my_dummy_handler,
+ {swap_event, dummy1_h, swap}),
+ [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:sync_notify(my_dummy_handler, Event),
+ receive
+ {dummy1_h, Event} ->
+ ok
+ end,
+ ok = gen_event:sync_notify(my_dummy_handler, delete_event),
+ receive
+ {dummy1_h, removed} ->
+ ok
+ end,
+ [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
+
+ ok = gen_event:sync_notify(my_dummy_handler, error_event),
+ receive
+ {dummy_h, returned_error} ->
+ ok
+ end,
+ [] = gen_event:which_handlers(my_dummy_handler),
%% Handler with id, {Mod,Id}
- ?line ok = gen_event:add_handler(my_dummy_handler, {dummy_h,5}, [self()]),
- ?line [{dummy_h,5}] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:sync_notify(my_dummy_handler, Event),
- ?line receive
- {dummy_h, Event} ->
- ok
- end,
- ?line ok = gen_event:sync_notify(my_dummy_handler,
- {swap_event, {dummy1_h, 9}, swap}),
- ?line [{dummy1_h,9}] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:sync_notify(my_dummy_handler, Event),
- ?line receive
- {dummy1_h, Event} ->
- ok
- end,
- ?line ok = gen_event:sync_notify(my_dummy_handler, delete_event),
- ?line receive
- {dummy1_h, removed} ->
- ok
- end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_handler(my_dummy_handler, {dummy_h,a}, [self()]),
-
- ?line ok = gen_event:sync_notify(my_dummy_handler, error_event),
- ?line receive
- {dummy_h, returned_error} ->
- ok
- end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, {dummy_h,5}, [self()]),
+ [{dummy_h,5}] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:sync_notify(my_dummy_handler, Event),
+ receive
+ {dummy_h, Event} ->
+ ok
+ end,
+ ok = gen_event:sync_notify(my_dummy_handler,
+ {swap_event, {dummy1_h, 9}, swap}),
+ [{dummy1_h,9}] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:sync_notify(my_dummy_handler, Event),
+ receive
+ {dummy1_h, Event} ->
+ ok
+ end,
+ ok = gen_event:sync_notify(my_dummy_handler, delete_event),
+ receive
+ {dummy1_h, removed} ->
+ ok
+ end,
+ [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, {dummy_h,a}, [self()]),
+
+ ok = gen_event:sync_notify(my_dummy_handler, error_event),
+ receive
+ {dummy_h, returned_error} ->
+ ok
+ end,
+ [] = gen_event:which_handlers(my_dummy_handler),
%% Supervised handler.
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
- ?line [dummy_h] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:sync_notify(my_dummy_handler, Event),
- ?line receive
- {dummy_h, Event} ->
- ok
- end,
-
- ?line ok = gen_event:sync_notify(my_dummy_handler, do_crash),
- ?line receive
- {gen_event_EXIT, dummy_h, {'EXIT',_}} ->
- ok
- end,
-
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
- ?line ok = gen_event:sync_notify(my_dummy_handler,
- {swap_event,dummy1_h,swap}),
- ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
-
- ?line ok = gen_event:sync_notify(my_dummy_handler, do_crash),
- ?line receive
- {gen_event_EXIT, dummy1_h, {'EXIT',_}} ->
- ok
- end,
-
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
- ?line ok = gen_event:sync_notify(my_dummy_handler,
- {swap_event,dummy1_h,swap}),
- ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
-
- ?line ok = gen_event:sync_notify(my_dummy_handler, delete_event),
- ?line receive
- {dummy1_h, removed} ->
- ok
- end,
-
- ?line receive
- {gen_event_EXIT, dummy1_h, normal} ->
- ok
- end,
-
- ?line [] = gen_event:which_handlers(my_dummy_handler),
-
- ?line ok = gen_event:stop(my_dummy_handler),
+ ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
+ [dummy_h] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:sync_notify(my_dummy_handler, Event),
+ receive
+ {dummy_h, Event} ->
+ ok
+ end,
+
+ ok = gen_event:sync_notify(my_dummy_handler, do_crash),
+ receive
+ {gen_event_EXIT, dummy_h, {'EXIT',_}} ->
+ ok
+ end,
+
+ ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
+ ok = gen_event:sync_notify(my_dummy_handler,
+ {swap_event,dummy1_h,swap}),
+ [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
+
+ ok = gen_event:sync_notify(my_dummy_handler, do_crash),
+ receive
+ {gen_event_EXIT, dummy1_h, {'EXIT',_}} ->
+ ok
+ end,
+
+ ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
+ ok = gen_event:sync_notify(my_dummy_handler,
+ {swap_event,dummy1_h,swap}),
+ [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
+
+ ok = gen_event:sync_notify(my_dummy_handler, delete_event),
+ receive
+ {dummy1_h, removed} ->
+ ok
+ end,
+
+ receive
+ {gen_event_EXIT, dummy1_h, normal} ->
+ ok
+ end,
+
+ [] = gen_event:which_handlers(my_dummy_handler),
+
+ ok = gen_event:stop(my_dummy_handler),
ok.
-call(doc) -> [];
-call(suite) -> [];
call(Config) when is_list(Config) ->
- ?line {ok,_} = gen_event:start({local, my_dummy_handler}),
- ?line ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
- ?line ok = gen_event:add_handler(my_dummy_handler, {dummy_h, 1}, [self()]),
- ?line [{dummy_h, 1}, dummy_h] = gen_event:which_handlers(my_dummy_handler),
- ?line {'EXIT',_} = (catch gen_event:call(non_exist, dummy_h, hejsan)),
- ?line {error, bad_module} =
+ {ok,_} = gen_event:start({local, my_dummy_handler}),
+ ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
+ ok = gen_event:add_handler(my_dummy_handler, {dummy_h, 1}, [self()]),
+ [{dummy_h, 1}, dummy_h] = gen_event:which_handlers(my_dummy_handler),
+ {'EXIT',_} = (catch gen_event:call(non_exist, dummy_h, hejsan)),
+ {error, bad_module} =
gen_event:call(my_dummy_handler, bad_h, hejsan),
- ?line {ok, hejhopp} = gen_event:call(my_dummy_handler, dummy_h, hejsan),
- ?line {ok, hejhopp} = gen_event:call(my_dummy_handler, {dummy_h, 1},
- hejsan),
- ?line {ok, hejhopp} = gen_event:call(my_dummy_handler, dummy_h, hejsan,
- 10000),
- ?line {'EXIT', {timeout, _}} =
+ {ok, hejhopp} = gen_event:call(my_dummy_handler, dummy_h, hejsan),
+ {ok, hejhopp} = gen_event:call(my_dummy_handler, {dummy_h, 1},
+ hejsan),
+ {ok, hejhopp} = gen_event:call(my_dummy_handler, dummy_h, hejsan,
+ 10000),
+ {'EXIT', {timeout, _}} =
(catch gen_event:call(my_dummy_handler, dummy_h, hejsan, 0)),
flush(),
- ?line ok = gen_event:delete_handler(my_dummy_handler, {dummy_h, 1}, []),
- ?line {ok, swapped} = gen_event:call(my_dummy_handler, dummy_h,
- {swap_call,dummy1_h,swap}),
- ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
- ?line {error, bad_module} =
+ ok = gen_event:delete_handler(my_dummy_handler, {dummy_h, 1}, []),
+ {ok, swapped} = gen_event:call(my_dummy_handler, dummy_h,
+ {swap_call,dummy1_h,swap}),
+ [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
+ {error, bad_module} =
gen_event:call(my_dummy_handler, dummy_h, hejsan),
- ?line ok = gen_event:call(my_dummy_handler, dummy1_h, delete_call),
- ?line receive
- {dummy1_h, removed} ->
- ok
- end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
-
- ?line {error, {return, faulty}} =
+ ok = gen_event:call(my_dummy_handler, dummy1_h, delete_call),
+ receive
+ {dummy1_h, removed} ->
+ ok
+ end,
+ [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
+
+ {error, {return, faulty}} =
gen_event:call(my_dummy_handler, dummy_h, error_call),
- ?line receive
- {dummy_h, returned_error} ->
- ok
- end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
-
- ?line {error, {'EXIT', _}} =
+ receive
+ {dummy_h, returned_error} ->
+ ok
+ end,
+ [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
+
+ {error, {'EXIT', _}} =
gen_event:call(my_dummy_handler, dummy_h, exit_call),
- ?line [] = gen_event:which_handlers(my_dummy_handler),
+ [] = gen_event:which_handlers(my_dummy_handler),
%% Handler with id, {Mod,Id}
- ?line ok = gen_event:add_handler(my_dummy_handler, {dummy_h,1}, [self()]),
- ?line [{dummy_h,1}] = gen_event:which_handlers(my_dummy_handler),
- ?line {error, bad_module} =
+ ok = gen_event:add_handler(my_dummy_handler, {dummy_h,1}, [self()]),
+ [{dummy_h,1}] = gen_event:which_handlers(my_dummy_handler),
+ {error, bad_module} =
gen_event:call(my_dummy_handler, bad_h, hejsan),
- ?line {ok, hejhopp} = gen_event:call(my_dummy_handler, {dummy_h,1},
- hejsan),
- ?line {ok, swapped} = gen_event:call(my_dummy_handler, {dummy_h,1},
- {swap_call,{dummy1_h,2},swap}),
- ?line [{dummy1_h,2}] = gen_event:which_handlers(my_dummy_handler),
- ?line {error, bad_module} =
+ {ok, hejhopp} = gen_event:call(my_dummy_handler, {dummy_h,1},
+ hejsan),
+ {ok, swapped} = gen_event:call(my_dummy_handler, {dummy_h,1},
+ {swap_call,{dummy1_h,2},swap}),
+ [{dummy1_h,2}] = gen_event:which_handlers(my_dummy_handler),
+ {error, bad_module} =
gen_event:call(my_dummy_handler, dummy_h, hejsan),
- ?line ok = gen_event:call(my_dummy_handler, {dummy1_h,2}, delete_call),
- ?line receive
- {dummy1_h, removed} ->
- ok
- end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_handler(my_dummy_handler, {dummy_h,3}, [self()]),
-
- ?line {error, {return, faulty}} =
+ ok = gen_event:call(my_dummy_handler, {dummy1_h,2}, delete_call),
+ receive
+ {dummy1_h, removed} ->
+ ok
+ end,
+ [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, {dummy_h,3}, [self()]),
+
+ {error, {return, faulty}} =
gen_event:call(my_dummy_handler, {dummy_h,3}, error_call),
- ?line receive
- {dummy_h, returned_error} ->
- ok
- end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_handler(my_dummy_handler, {dummy_h,4}, [self()]),
-
- ?line {error, {'EXIT', _}} =
+ receive
+ {dummy_h, returned_error} ->
+ ok
+ end,
+ [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, {dummy_h,4}, [self()]),
+
+ {error, {'EXIT', _}} =
gen_event:call(my_dummy_handler, {dummy_h,4}, exit_call),
- ?line [] = gen_event:which_handlers(my_dummy_handler),
+ [] = gen_event:which_handlers(my_dummy_handler),
%% Supervised handler.
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
- ?line [dummy_h] = gen_event:which_handlers(my_dummy_handler),
- ?line {error, bad_module} =
+ ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
+ [dummy_h] = gen_event:which_handlers(my_dummy_handler),
+ {error, bad_module} =
gen_event:call(my_dummy_handler, bad_h, hejsan),
- ?line {ok, hejhopp} = gen_event:call(my_dummy_handler, dummy_h, hejsan),
- ?line {ok, swapped} = gen_event:call(my_dummy_handler, dummy_h,
- {swap_call,dummy1_h,swap}),
- ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
- ?line {error, bad_module} =
+ {ok, hejhopp} = gen_event:call(my_dummy_handler, dummy_h, hejsan),
+ {ok, swapped} = gen_event:call(my_dummy_handler, dummy_h,
+ {swap_call,dummy1_h,swap}),
+ [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
+ {error, bad_module} =
gen_event:call(my_dummy_handler, dummy_h, hejsan),
- ?line ok = gen_event:call(my_dummy_handler, dummy1_h, delete_call),
- ?line receive
- {dummy1_h, removed} ->
- ok
- end,
+ ok = gen_event:call(my_dummy_handler, dummy1_h, delete_call),
+ receive
+ {dummy1_h, removed} ->
+ ok
+ end,
- ?line receive
- {gen_event_EXIT, dummy1_h, normal} ->
- ok
- end,
+ receive
+ {gen_event_EXIT, dummy1_h, normal} ->
+ ok
+ end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
+ [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
- ?line {error, {return, faulty}} =
+ {error, {return, faulty}} =
gen_event:call(my_dummy_handler, dummy_h, error_call),
- ?line receive
- {dummy_h, returned_error} ->
- ok
- end,
-
- ?line receive
- {gen_event_EXIT, dummy_h, {return,faulty}} ->
- ok
- after 1000 ->
- ?t:fail({no, {gen_event_EXIT, dummy_h, {return,faulty}}})
- end,
-
- ?line [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
-
- ?line {error, {'EXIT', _}} =
+ receive
+ {dummy_h, returned_error} ->
+ ok
+ end,
+
+ receive
+ {gen_event_EXIT, dummy_h, {return,faulty}} ->
+ ok
+ after 1000 ->
+ ct:fail({no, {gen_event_EXIT, dummy_h, {return,faulty}}})
+ end,
+
+ [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
+
+ {error, {'EXIT', _}} =
gen_event:call(my_dummy_handler, dummy_h, exit_call),
- ?line receive
- {gen_event_EXIT, dummy_h, {'EXIT',_}} ->
- ok
- after 1000 ->
- ?t:fail({no, {gen_event_EXIT, dummy_h, {'EXIT','_'}}})
- end,
+ receive
+ {gen_event_EXIT, dummy_h, {'EXIT',_}} ->
+ ok
+ after 1000 ->
+ ct:fail({no, {gen_event_EXIT, dummy_h, {'EXIT','_'}}})
+ end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
+ [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:stop(my_dummy_handler),
+ ok = gen_event:stop(my_dummy_handler),
ok.
flush() ->
receive _ -> flush() after 0 -> ok end.
-info(doc) -> [];
-info(suite) -> [];
info(Config) when is_list(Config) ->
- ?line {ok,_} = gen_event:start({local, my_dummy_handler}),
- ?line ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
+ {ok,_} = gen_event:start({local, my_dummy_handler}),
+ ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
Info = {info, self()},
- ?line [dummy_h] = gen_event:which_handlers(my_dummy_handler),
- ?line my_dummy_handler ! Info,
- ?line receive
- {dummy_h, Info} ->
- ok
- end,
- ?line my_dummy_handler ! {swap_info,dummy1_h,swap},
- ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
- ?line my_dummy_handler ! Info,
- ?line receive
- {dummy1_h, Info} ->
- ok
- end,
- ?line my_dummy_handler ! delete_info,
- ?line receive
- {dummy1_h, removed} ->
- ok
- end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
-
- ?line my_dummy_handler ! error_info,
- ?line receive
- {dummy_h, returned_error} ->
- ok
- end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
+ [dummy_h] = gen_event:which_handlers(my_dummy_handler),
+ my_dummy_handler ! Info,
+ receive
+ {dummy_h, Info} ->
+ ok
+ end,
+ my_dummy_handler ! {swap_info,dummy1_h,swap},
+ [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
+ my_dummy_handler ! Info,
+ receive
+ {dummy1_h, Info} ->
+ ok
+ end,
+ my_dummy_handler ! delete_info,
+ receive
+ {dummy1_h, removed} ->
+ ok
+ end,
+ [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]),
+
+ my_dummy_handler ! error_info,
+ receive
+ {dummy_h, returned_error} ->
+ ok
+ end,
+ [] = gen_event:which_handlers(my_dummy_handler),
%% Handler with id, {Mod,Id}
- ?line ok = gen_event:add_handler(my_dummy_handler, {dummy_h,1}, [self()]),
- ?line [{dummy_h,1}] = gen_event:which_handlers(my_dummy_handler),
- ?line my_dummy_handler ! Info,
- ?line receive
- {dummy_h, Info} ->
- ok
- end,
- ?line my_dummy_handler ! {swap_info,{dummy1_h,2},swap},
- ?line [{dummy1_h,2}] = gen_event:which_handlers(my_dummy_handler),
- ?line my_dummy_handler ! Info,
- ?line receive
- {dummy1_h, Info} ->
- ok
- end,
- ?line my_dummy_handler ! delete_info,
- ?line receive
- {dummy1_h, removed} ->
- ok
- end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
- ?line ok = gen_event:add_handler(my_dummy_handler, {dummy_h,3}, [self()]),
-
- ?line my_dummy_handler ! error_info,
- ?line receive
- {dummy_h, returned_error} ->
- ok
- end,
- ?line [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, {dummy_h,1}, [self()]),
+ [{dummy_h,1}] = gen_event:which_handlers(my_dummy_handler),
+ my_dummy_handler ! Info,
+ receive
+ {dummy_h, Info} ->
+ ok
+ end,
+ my_dummy_handler ! {swap_info,{dummy1_h,2},swap},
+ [{dummy1_h,2}] = gen_event:which_handlers(my_dummy_handler),
+ my_dummy_handler ! Info,
+ receive
+ {dummy1_h, Info} ->
+ ok
+ end,
+ my_dummy_handler ! delete_info,
+ receive
+ {dummy1_h, removed} ->
+ ok
+ end,
+ [] = gen_event:which_handlers(my_dummy_handler),
+ ok = gen_event:add_handler(my_dummy_handler, {dummy_h,3}, [self()]),
+
+ my_dummy_handler ! error_info,
+ receive
+ {dummy_h, returned_error} ->
+ ok
+ end,
+ [] = gen_event:which_handlers(my_dummy_handler),
%% Supervised handler
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
- ?line [dummy_h] = gen_event:which_handlers(my_dummy_handler),
- ?line my_dummy_handler ! Info,
- ?line receive
- {dummy_h, Info} ->
- ok
- end,
- ?line my_dummy_handler ! {swap_info,dummy1_h,swap},
- ?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
- ?line my_dummy_handler ! Info,
- ?line receive
- {dummy1_h, Info} ->
- ok
- end,
- ?line my_dummy_handler ! delete_info,
- ?line receive
- {dummy1_h, removed} ->
- ok
- end,
-
- ?line receive
- {gen_event_EXIT, dummy1_h, normal} ->
- ok
- after 1000 ->
- ?t:fail({no, {gen_event_EXIT, dummy1_h, normal}})
- end,
-
- ?line [] = gen_event:which_handlers(my_dummy_handler),
-
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
-
- ?line my_dummy_handler ! error_info,
- ?line receive
- {dummy_h, returned_error} ->
- ok
- end,
-
- ?line receive
- {gen_event_EXIT, dummy_h, {return,faulty}} ->
- ok
- after 1000 ->
- ?t:fail({no, {gen_event_EXIT, dummy_h, {return,faulty}}})
- end,
-
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
- ?line my_dummy_handler ! do_crash,
-
- ?line receive
- {gen_event_EXIT, dummy_h, {'EXIT',_}} ->
- ok
- after 1000 ->
- ?t:fail({no, {gen_event_EXIT, dummy_h, {'EXIT','_'}}})
- end,
-
- ?line [] = gen_event:which_handlers(my_dummy_handler),
-
- ?line ok = gen_event:stop(my_dummy_handler),
+ ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
+ [dummy_h] = gen_event:which_handlers(my_dummy_handler),
+ my_dummy_handler ! Info,
+ receive
+ {dummy_h, Info} ->
+ ok
+ end,
+ my_dummy_handler ! {swap_info,dummy1_h,swap},
+ [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
+ my_dummy_handler ! Info,
+ receive
+ {dummy1_h, Info} ->
+ ok
+ end,
+ my_dummy_handler ! delete_info,
+ receive
+ {dummy1_h, removed} ->
+ ok
+ end,
+
+ receive
+ {gen_event_EXIT, dummy1_h, normal} ->
+ ok
+ after 1000 ->
+ ct:fail({no, {gen_event_EXIT, dummy1_h, normal}})
+ end,
+
+ [] = gen_event:which_handlers(my_dummy_handler),
+
+ ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
+
+ my_dummy_handler ! error_info,
+ receive
+ {dummy_h, returned_error} ->
+ ok
+ end,
+
+ receive
+ {gen_event_EXIT, dummy_h, {return,faulty}} ->
+ ok
+ after 1000 ->
+ ct:fail({no, {gen_event_EXIT, dummy_h, {return,faulty}}})
+ end,
+
+ ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
+ my_dummy_handler ! do_crash,
+
+ receive
+ {gen_event_EXIT, dummy_h, {'EXIT',_}} ->
+ ok
+ after 1000 ->
+ ct:fail({no, {gen_event_EXIT, dummy_h, {'EXIT','_'}}})
+ end,
+
+ [] = gen_event:which_handlers(my_dummy_handler),
+
+ ok = gen_event:stop(my_dummy_handler),
ok.
-call_format_status(suite) ->
- [];
-call_format_status(doc) ->
- ["Test that sys:get_status/1,2 calls format_status/2"];
+%% Test that sys:get_status/1,2 calls format_status/2.
call_format_status(Config) when is_list(Config) ->
- ?line {ok, Pid} = gen_event:start({local, my_dummy_handler}),
+ {ok, Pid} = gen_event:start({local, my_dummy_handler}),
%% State here intentionally differs from what we expect from format_status
State = self(),
FmtState = "dummy1_h handler state",
- ?line ok = gen_event:add_handler(my_dummy_handler, dummy1_h, [State]),
- ?line Status1 = sys:get_status(Pid),
- ?line Status2 = sys:get_status(Pid, 5000),
- ?line ok = gen_event:stop(Pid),
- ?line {status, Pid, _, [_, _, Pid, [], Data1]} = Status1,
- ?line HandlerInfo1 = proplists:get_value(items, Data1),
- ?line {"Installed handlers", [{_,dummy1_h,_,FmtState,_}]} = HandlerInfo1,
- ?line {status, Pid, _, [_, _, Pid, [], Data2]} = Status2,
- ?line HandlerInfo2 = proplists:get_value(items, Data2),
- ?line {"Installed handlers", [{_,dummy1_h,_,FmtState,_}]} = HandlerInfo2,
+ ok = gen_event:add_handler(my_dummy_handler, dummy1_h, [State]),
+ Status1 = sys:get_status(Pid),
+ Status2 = sys:get_status(Pid, 5000),
+ ok = gen_event:stop(Pid),
+ {status, Pid, _, [_, _, Pid, [], Data1]} = Status1,
+ HandlerInfo1 = proplists:get_value(items, Data1),
+ {"Installed handlers", [{_,dummy1_h,_,FmtState,_}]} = HandlerInfo1,
+ {status, Pid, _, [_, _, Pid, [], Data2]} = Status2,
+ HandlerInfo2 = proplists:get_value(items, Data2),
+ {"Installed handlers", [{_,dummy1_h,_,FmtState,_}]} = HandlerInfo2,
ok.
-call_format_status_anon(suite) ->
- [];
-call_format_status_anon(doc) ->
- ["Test that sys:get_status/1,2 calls format_status/2 for anonymous gen_event processes"];
+%% Test that sys:get_status/1,2 calls format_status/2 for anonymous
+%% gen_event processes.
call_format_status_anon(Config) when is_list(Config) ->
- ?line {ok, Pid} = gen_event:start(),
+ {ok, Pid} = gen_event:start(),
%% The 'Name' of the gen_event process will be a pid() here, so
%% the next line will crash if format_status can't string-ify pids.
- ?line Status1 = sys:get_status(Pid),
- ?line ok = gen_event:stop(Pid),
+ Status1 = sys:get_status(Pid),
+ ok = gen_event:stop(Pid),
Header = "Status for event handler " ++ pid_to_list(Pid),
- ?line {status, Pid, _, [_, _, Pid, [], Data1]} = Status1,
- ?line Header = proplists:get_value(header, Data1),
+ {status, Pid, _, [_, _, Pid, [], Data1]} = Status1,
+ Header = proplists:get_value(header, Data1),
ok.
-error_format_status(suite) ->
- [];
-error_format_status(doc) ->
- ["Test that a handler error calls format_status/2"];
+%% Test that a handler error calls format_status/2.
error_format_status(Config) when is_list(Config) ->
- ?line error_logger_forwarder:register(),
+ error_logger_forwarder:register(),
OldFl = process_flag(trap_exit, true),
State = self(),
- ?line {ok, Pid} = gen_event:start({local, my_dummy_handler}),
- ?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy1_h, [State]),
- ?line ok = gen_event:notify(my_dummy_handler, do_crash),
- ?line receive
- {gen_event_EXIT,dummy1_h,{'EXIT',_}} -> ok
- after 5000 ->
- ?t:fail(exit_gen_event)
- end,
+ {ok, Pid} = gen_event:start({local, my_dummy_handler}),
+ ok = gen_event:add_sup_handler(my_dummy_handler, dummy1_h, [State]),
+ ok = gen_event:notify(my_dummy_handler, do_crash),
+ receive
+ {gen_event_EXIT,dummy1_h,{'EXIT',_}} -> ok
+ after 5000 ->
+ ct:fail(exit_gen_event)
+ end,
FmtState = "dummy1_h handler state",
receive
{error,_GroupLeader, {Pid,
@@ -955,18 +926,14 @@ error_format_status(Config) when is_list(Config) ->
FmtState, _]}} ->
ok;
Other ->
- ?line io:format("Unexpected: ~p", [Other]),
- ?line ?t:fail()
+ io:format("Unexpected: ~p", [Other]),
+ ct:fail(failed)
end,
- ?t:messages_get(),
- ?line ok = gen_event:stop(Pid),
+ ok = gen_event:stop(Pid),
process_flag(trap_exit, OldFl),
ok.
-get_state(suite) ->
- [];
-get_state(doc) ->
- ["Test that sys:get_state/1,2 return the gen_event state"];
+%% Test that sys:get_state/1,2 return the gen_event state.
get_state(Config) when is_list(Config) ->
{ok, Pid} = gen_event:start({local, my_dummy_handler}),
State1 = self(),
@@ -986,10 +953,7 @@ get_state(Config) when is_list(Config) ->
ok = gen_event:stop(Pid),
ok.
-replace_state(suite) ->
- [];
-replace_state(doc) ->
- ["Test that replace_state/2,3 replace the gen_event state"];
+%% Test that replace_state/2,3 replace the gen_event state.
replace_state(Config) when is_list(Config) ->
{ok, Pid} = gen_event:start({local, my_dummy_handler}),
State1 = self(),
diff --git a/lib/stdlib/test/gen_fsm_SUITE.erl b/lib/stdlib/test/gen_fsm_SUITE.erl
index e3da1a2271..f79a344c4e 100644
--- a/lib/stdlib/test/gen_fsm_SUITE.erl
+++ b/lib/stdlib/test/gen_fsm_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(gen_fsm_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Test cases
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -44,10 +44,9 @@
-export([enter_loop/1]).
%% Exports for apply
--export([do_msg/1, do_sync_msg/1]).
-export([enter_loop/2]).
-% The gen_fsm behaviour
+%% The gen_fsm behaviour
-export([init/1, handle_event/3, handle_sync_event/4, terminate/3,
handle_info/3, format_status/2]).
-export([idle/2, idle/3,
@@ -55,7 +54,7 @@
wfor_conf/2, wfor_conf/3,
connected/2, connected/3]).
-export([state0/3]).
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -93,97 +92,95 @@ end_per_group(_GroupName, Config) ->
start1(Config) when is_list(Config) ->
%%OldFl = process_flag(trap_exit, true),
- ?line {ok, Pid0} = gen_fsm:start_link(gen_fsm_SUITE, [], []),
- ?line ok = do_func_test(Pid0),
- ?line ok = do_sync_func_test(Pid0),
+ {ok, Pid0} = gen_fsm:start_link(gen_fsm_SUITE, [], []),
+ ok = do_func_test(Pid0),
+ ok = do_sync_func_test(Pid0),
stop_it(Pid0),
-%% ?line stopped = gen_fsm:sync_send_all_state_event(Pid0, stop),
-%% ?line {'EXIT', {timeout,_}} =
-%% (catch gen_fsm:sync_send_event(Pid0, hej)),
+ %% stopped = gen_fsm:sync_send_all_state_event(Pid0, stop),
+ %% {'EXIT', {timeout,_}} =
+ %% (catch gen_fsm:sync_send_event(Pid0, hej)),
- ?line test_server:messages_get(),
+ [] = get_messages(),
%%process_flag(trap_exit, OldFl),
- ok.
+ ok.
%% anonymous w. shutdown
start2(Config) when is_list(Config) ->
%% Dont link when shutdown
- ?line {ok, Pid0} = gen_fsm:start(gen_fsm_SUITE, [], []),
- ?line ok = do_func_test(Pid0),
- ?line ok = do_sync_func_test(Pid0),
- ?line shutdown_stopped =
+ {ok, Pid0} = gen_fsm:start(gen_fsm_SUITE, [], []),
+ ok = do_func_test(Pid0),
+ ok = do_sync_func_test(Pid0),
+ shutdown_stopped =
gen_fsm:sync_send_all_state_event(Pid0, stop_shutdown),
- ?line {'EXIT', {noproc,_}} =
+ {'EXIT', {noproc,_}} =
(catch gen_fsm:sync_send_event(Pid0, hej)),
- ?line test_server:messages_get(),
+ [] = get_messages(),
ok.
%% anonymous with timeout
start3(Config) when is_list(Config) ->
%%OldFl = process_flag(trap_exit, true),
- ?line {ok, Pid0} = gen_fsm:start(gen_fsm_SUITE, [], [{timeout,5}]),
- ?line ok = do_func_test(Pid0),
- ?line ok = do_sync_func_test(Pid0),
- ?line stop_it(Pid0),
-
- ?line {error, timeout} = gen_fsm:start(gen_fsm_SUITE, sleep,
- [{timeout,5}]),
+ {ok, Pid0} = gen_fsm:start(gen_fsm_SUITE, [], [{timeout,5}]),
+ ok = do_func_test(Pid0),
+ ok = do_sync_func_test(Pid0),
+ stop_it(Pid0),
- test_server:messages_get(),
+ {error, timeout} = gen_fsm:start(gen_fsm_SUITE, sleep,
+ [{timeout,5}]),
+
+ [] = get_messages(),
%%process_flag(trap_exit, OldFl),
ok.
%% anonymous with ignore
-start4(suite) -> [];
start4(Config) when is_list(Config) ->
OldFl = process_flag(trap_exit, true),
- ?line ignore = gen_fsm:start(gen_fsm_SUITE, ignore, []),
+ ignore = gen_fsm:start(gen_fsm_SUITE, ignore, []),
- test_server:messages_get(),
+ [] = get_messages(),
process_flag(trap_exit, OldFl),
ok.
%% anonymous with stop
-start5(suite) -> [];
start5(Config) when is_list(Config) ->
OldFl = process_flag(trap_exit, true),
- ?line {error, stopped} = gen_fsm:start(gen_fsm_SUITE, stop, []),
+ {error, stopped} = gen_fsm:start(gen_fsm_SUITE, stop, []),
- test_server:messages_get(),
+ [] = get_messages(),
process_flag(trap_exit, OldFl),
ok.
%% anonymous linked
start6(Config) when is_list(Config) ->
- ?line {ok, Pid} = gen_fsm:start_link(gen_fsm_SUITE, [], []),
- ?line ok = do_func_test(Pid),
- ?line ok = do_sync_func_test(Pid),
- ?line stop_it(Pid),
+ {ok, Pid} = gen_fsm:start_link(gen_fsm_SUITE, [], []),
+ ok = do_func_test(Pid),
+ ok = do_sync_func_test(Pid),
+ stop_it(Pid),
- test_server:messages_get(),
+ [] = get_messages(),
ok.
%% global register linked
start7(Config) when is_list(Config) ->
- ?line {ok, Pid} =
+ {ok, Pid} =
gen_fsm:start_link({global, my_fsm}, gen_fsm_SUITE, [], []),
- ?line {error, {already_started, Pid}} =
+ {error, {already_started, Pid}} =
gen_fsm:start_link({global, my_fsm}, gen_fsm_SUITE, [], []),
- ?line {error, {already_started, Pid}} =
+ {error, {already_started, Pid}} =
gen_fsm:start({global, my_fsm}, gen_fsm_SUITE, [], []),
-
- ?line ok = do_func_test(Pid),
- ?line ok = do_sync_func_test(Pid),
- ?line ok = do_func_test({global, my_fsm}),
- ?line ok = do_sync_func_test({global, my_fsm}),
- ?line stop_it({global, my_fsm}),
-
- test_server:messages_get(),
+
+ ok = do_func_test(Pid),
+ ok = do_sync_func_test(Pid),
+ ok = do_func_test({global, my_fsm}),
+ ok = do_sync_func_test({global, my_fsm}),
+ stop_it({global, my_fsm}),
+
+ [] = get_messages(),
ok.
@@ -191,18 +188,18 @@ start7(Config) when is_list(Config) ->
start8(Config) when is_list(Config) ->
%%OldFl = process_flag(trap_exit, true),
- ?line {ok, Pid} =
+ {ok, Pid} =
gen_fsm:start({local, my_fsm}, gen_fsm_SUITE, [], []),
- ?line {error, {already_started, Pid}} =
+ {error, {already_started, Pid}} =
gen_fsm:start({local, my_fsm}, gen_fsm_SUITE, [], []),
- ?line ok = do_func_test(Pid),
- ?line ok = do_sync_func_test(Pid),
- ?line ok = do_func_test(my_fsm),
- ?line ok = do_sync_func_test(my_fsm),
- ?line stop_it(Pid),
-
- test_server:messages_get(),
+ ok = do_func_test(Pid),
+ ok = do_sync_func_test(Pid),
+ ok = do_func_test(my_fsm),
+ ok = do_sync_func_test(my_fsm),
+ stop_it(Pid),
+
+ [] = get_messages(),
%%process_flag(trap_exit, OldFl),
ok.
@@ -210,80 +207,80 @@ start8(Config) when is_list(Config) ->
start9(Config) when is_list(Config) ->
%%OldFl = process_flag(trap_exit, true),
- ?line {ok, Pid} =
+ {ok, Pid} =
gen_fsm:start_link({local, my_fsm}, gen_fsm_SUITE, [], []),
- ?line {error, {already_started, Pid}} =
+ {error, {already_started, Pid}} =
gen_fsm:start({local, my_fsm}, gen_fsm_SUITE, [], []),
- ?line ok = do_func_test(Pid),
- ?line ok = do_sync_func_test(Pid),
- ?line ok = do_func_test(my_fsm),
- ?line ok = do_sync_func_test(my_fsm),
- ?line stop_it(Pid),
-
- test_server:messages_get(),
+ ok = do_func_test(Pid),
+ ok = do_sync_func_test(Pid),
+ ok = do_func_test(my_fsm),
+ ok = do_sync_func_test(my_fsm),
+ stop_it(Pid),
+
+ [] = get_messages(),
%%process_flag(trap_exit, OldFl),
ok.
%% global register
start10(Config) when is_list(Config) ->
- ?line {ok, Pid} =
+ {ok, Pid} =
gen_fsm:start({global, my_fsm}, gen_fsm_SUITE, [], []),
- ?line {error, {already_started, Pid}} =
+ {error, {already_started, Pid}} =
gen_fsm:start({global, my_fsm}, gen_fsm_SUITE, [], []),
- ?line {error, {already_started, Pid}} =
+ {error, {already_started, Pid}} =
gen_fsm:start_link({global, my_fsm}, gen_fsm_SUITE, [], []),
-
- ?line ok = do_func_test(Pid),
- ?line ok = do_sync_func_test(Pid),
- ?line ok = do_func_test({global, my_fsm}),
- ?line ok = do_sync_func_test({global, my_fsm}),
- ?line stop_it({global, my_fsm}),
-
- test_server:messages_get(),
+
+ ok = do_func_test(Pid),
+ ok = do_sync_func_test(Pid),
+ ok = do_func_test({global, my_fsm}),
+ ok = do_sync_func_test({global, my_fsm}),
+ stop_it({global, my_fsm}),
+
+ [] = get_messages(),
ok.
%% Stop registered processes
start11(Config) when is_list(Config) ->
- ?line {ok, Pid} =
+ {ok, Pid} =
gen_fsm:start_link({local, my_fsm}, gen_fsm_SUITE, [], []),
- ?line stop_it(Pid),
+ stop_it(Pid),
- ?line {ok, _Pid1} =
+ {ok, _Pid1} =
gen_fsm:start_link({local, my_fsm}, gen_fsm_SUITE, [], []),
- ?line stop_it(my_fsm),
-
- ?line {ok, Pid2} =
+ stop_it(my_fsm),
+
+ {ok, Pid2} =
gen_fsm:start({global, my_fsm}, gen_fsm_SUITE, [], []),
- ?line stop_it(Pid2),
+ stop_it(Pid2),
receive after 1 -> true end,
- ?line Result =
+ Result =
gen_fsm:start({global, my_fsm}, gen_fsm_SUITE, [], []),
io:format("Result = ~p~n",[Result]),
- ?line {ok, _Pid3} = Result,
- ?line stop_it({global, my_fsm}),
+ {ok, _Pid3} = Result,
+ stop_it({global, my_fsm}),
- test_server:messages_get(),
+ [] = get_messages(),
ok.
%% Via register linked
start12(Config) when is_list(Config) ->
- ?line dummy_via:reset(),
- ?line {ok, Pid} =
+ dummy_via:reset(),
+ {ok, Pid} =
gen_fsm:start_link({via, dummy_via, my_fsm}, gen_fsm_SUITE, [], []),
- ?line {error, {already_started, Pid}} =
+ {error, {already_started, Pid}} =
gen_fsm:start_link({via, dummy_via, my_fsm}, gen_fsm_SUITE, [], []),
- ?line {error, {already_started, Pid}} =
+ {error, {already_started, Pid}} =
gen_fsm:start({via, dummy_via, my_fsm}, gen_fsm_SUITE, [], []),
- ?line ok = do_func_test(Pid),
- ?line ok = do_sync_func_test(Pid),
- ?line ok = do_func_test({via, dummy_via, my_fsm}),
- ?line ok = do_sync_func_test({via, dummy_via, my_fsm}),
- ?line stop_it({via, dummy_via, my_fsm}),
+ ok = do_func_test(Pid),
+ ok = do_sync_func_test(Pid),
+ ok = do_func_test({via, dummy_via, my_fsm}),
+ ok = do_sync_func_test({via, dummy_via, my_fsm}),
+ stop_it({via, dummy_via, my_fsm}),
- test_server:messages_get(),
+ [] = get_messages(),
ok.
@@ -339,7 +336,7 @@ stop6(_Config) ->
stop7(_Config) ->
dummy_via:reset(),
{ok, Pid} = gen_fsm:start({via, dummy_via, to_stop},
- ?MODULE, [], []),
+ ?MODULE, [], []),
ok = gen_fsm:stop({via, dummy_via, to_stop}),
false = erlang:is_process_alive(Pid),
{'EXIT',noproc} = (catch gen_fsm:stop({via, dummy_via, to_stop})),
@@ -387,53 +384,51 @@ stop10(_Config) ->
ok.
%% Check that time outs in calls work
-abnormal1(suite) -> [];
abnormal1(Config) when is_list(Config) ->
{ok, _Pid} = gen_fsm:start({local, my_fsm}, gen_fsm_SUITE, [], []),
%% timeout call.
delayed = gen_fsm:sync_send_event(my_fsm, {delayed_answer,1}, 100),
{'EXIT',{timeout,_}} =
- (catch gen_fsm:sync_send_event(my_fsm, {delayed_answer,10}, 1)),
- test_server:messages_get(),
+ (catch gen_fsm:sync_send_event(my_fsm, {delayed_answer,10}, 1)),
+ [] = get_messages(),
ok.
%% Check that bad return values makes the fsm crash. Note that we must
%% trap exit since we must link to get the real bad_return_ error
-abnormal2(suite) -> [];
abnormal2(Config) when is_list(Config) ->
OldFl = process_flag(trap_exit, true),
- ?line {ok, Pid} =
+ {ok, Pid} =
gen_fsm:start_link(gen_fsm_SUITE, [], []),
%% bad return value in the gen_fsm loop
- ?line {'EXIT',{{bad_return_value, badreturn},_}} =
+ {'EXIT',{{bad_return_value, badreturn},_}} =
(catch gen_fsm:sync_send_event(Pid, badreturn)),
-
- test_server:messages_get(),
+
+ [{'EXIT',Pid,{bad_return_value,badreturn}}] = get_messages(),
process_flag(trap_exit, OldFl),
ok.
shutdown(Config) when is_list(Config) ->
- ?line error_logger_forwarder:register(),
+ error_logger_forwarder:register(),
process_flag(trap_exit, true),
- ?line {ok,Pid0} = gen_fsm:start_link(gen_fsm_SUITE, [], []),
- ?line ok = do_func_test(Pid0),
- ?line ok = do_sync_func_test(Pid0),
- ?line {shutdown,reason} =
+ {ok,Pid0} = gen_fsm:start_link(gen_fsm_SUITE, [], []),
+ ok = do_func_test(Pid0),
+ ok = do_sync_func_test(Pid0),
+ {shutdown,reason} =
gen_fsm:sync_send_all_state_event(Pid0, stop_shutdown_reason),
receive {'EXIT',Pid0,{shutdown,reason}} -> ok end,
process_flag(trap_exit, false),
- ?line {'EXIT', {noproc,_}} =
+ {'EXIT', {noproc,_}} =
(catch gen_fsm:sync_send_event(Pid0, hej)),
receive
Any ->
- ?line io:format("Unexpected: ~p", [Any]),
- ?line ?t:fail()
+ io:format("Unexpected: ~p", [Any]),
+ ct:fail(failed)
after 500 ->
ok
end,
@@ -443,70 +438,70 @@ shutdown(Config) when is_list(Config) ->
sys1(Config) when is_list(Config) ->
- ?line {ok, Pid} =
+ {ok, Pid} =
gen_fsm:start(gen_fsm_SUITE, [], []),
- ?line {status, Pid, {module,gen_fsm}, _} = sys:get_status(Pid),
- ?line sys:suspend(Pid),
- ?line {'EXIT', {timeout,_}} =
+ {status, Pid, {module,gen_fsm}, _} = sys:get_status(Pid),
+ sys:suspend(Pid),
+ {'EXIT', {timeout,_}} =
(catch gen_fsm:sync_send_event(Pid, hej)),
- ?line sys:resume(Pid),
- ?line stop_it(Pid).
+ sys:resume(Pid),
+ stop_it(Pid).
call_format_status(Config) when is_list(Config) ->
- ?line {ok, Pid} = gen_fsm:start(gen_fsm_SUITE, [], []),
- ?line Status = sys:get_status(Pid),
- ?line {status, Pid, _Mod, [_PDict, running, _, _, Data]} = Status,
- ?line [format_status_called | _] = lists:reverse(Data),
- ?line stop_it(Pid),
+ {ok, Pid} = gen_fsm:start(gen_fsm_SUITE, [], []),
+ Status = sys:get_status(Pid),
+ {status, Pid, _Mod, [_PDict, running, _, _, Data]} = Status,
+ [format_status_called | _] = lists:reverse(Data),
+ stop_it(Pid),
%% check that format_status can handle a name being an atom (pid is
%% already checked by the previous test)
- ?line {ok, Pid2} = gen_fsm:start({local, gfsm}, gen_fsm_SUITE, [], []),
- ?line Status2 = sys:get_status(gfsm),
- ?line {status, Pid2, _Mod, [_PDict2, running, _, _, Data2]} = Status2,
- ?line [format_status_called | _] = lists:reverse(Data2),
- ?line stop_it(Pid2),
+ {ok, Pid2} = gen_fsm:start({local, gfsm}, gen_fsm_SUITE, [], []),
+ Status2 = sys:get_status(gfsm),
+ {status, Pid2, _Mod, [_PDict2, running, _, _, Data2]} = Status2,
+ [format_status_called | _] = lists:reverse(Data2),
+ stop_it(Pid2),
%% check that format_status can handle a name being a term other than a
%% pid or atom
GlobalName1 = {global, "CallFormatStatus"},
- ?line {ok, Pid3} = gen_fsm:start(GlobalName1, gen_fsm_SUITE, [], []),
- ?line Status3 = sys:get_status(GlobalName1),
- ?line {status, Pid3, _Mod, [_PDict3, running, _, _, Data3]} = Status3,
- ?line [format_status_called | _] = lists:reverse(Data3),
- ?line stop_it(Pid3),
+ {ok, Pid3} = gen_fsm:start(GlobalName1, gen_fsm_SUITE, [], []),
+ Status3 = sys:get_status(GlobalName1),
+ {status, Pid3, _Mod, [_PDict3, running, _, _, Data3]} = Status3,
+ [format_status_called | _] = lists:reverse(Data3),
+ stop_it(Pid3),
GlobalName2 = {global, {name, "term"}},
- ?line {ok, Pid4} = gen_fsm:start(GlobalName2, gen_fsm_SUITE, [], []),
- ?line Status4 = sys:get_status(GlobalName2),
- ?line {status, Pid4, _Mod, [_PDict4, running, _, _, Data4]} = Status4,
- ?line [format_status_called | _] = lists:reverse(Data4),
- ?line stop_it(Pid4),
+ {ok, Pid4} = gen_fsm:start(GlobalName2, gen_fsm_SUITE, [], []),
+ Status4 = sys:get_status(GlobalName2),
+ {status, Pid4, _Mod, [_PDict4, running, _, _, Data4]} = Status4,
+ [format_status_called | _] = lists:reverse(Data4),
+ stop_it(Pid4),
%% check that format_status can handle a name being a term other than a
%% pid or atom
- ?line dummy_via:reset(),
+ dummy_via:reset(),
ViaName1 = {via, dummy_via, "CallFormatStatus"},
- ?line {ok, Pid5} = gen_fsm:start(ViaName1, gen_fsm_SUITE, [], []),
- ?line Status5 = sys:get_status(ViaName1),
- ?line {status, Pid5, _Mod, [_PDict5, running, _, _, Data5]} = Status5,
- ?line [format_status_called | _] = lists:reverse(Data5),
- ?line stop_it(Pid5),
+ {ok, Pid5} = gen_fsm:start(ViaName1, gen_fsm_SUITE, [], []),
+ Status5 = sys:get_status(ViaName1),
+ {status, Pid5, _Mod, [_PDict5, running, _, _, Data5]} = Status5,
+ [format_status_called | _] = lists:reverse(Data5),
+ stop_it(Pid5),
ViaName2 = {via, dummy_via, {name, "term"}},
- ?line {ok, Pid6} = gen_fsm:start(ViaName2, gen_fsm_SUITE, [], []),
- ?line Status6 = sys:get_status(ViaName2),
- ?line {status, Pid6, _Mod, [_PDict6, running, _, _, Data6]} = Status6,
- ?line [format_status_called | _] = lists:reverse(Data6),
- ?line stop_it(Pid6).
+ {ok, Pid6} = gen_fsm:start(ViaName2, gen_fsm_SUITE, [], []),
+ Status6 = sys:get_status(ViaName2),
+ {status, Pid6, _Mod, [_PDict6, running, _, _, Data6]} = Status6,
+ [format_status_called | _] = lists:reverse(Data6),
+ stop_it(Pid6).
error_format_status(Config) when is_list(Config) ->
- ?line error_logger_forwarder:register(),
+ error_logger_forwarder:register(),
OldFl = process_flag(trap_exit, true),
StateData = "called format_status",
- ?line {ok, Pid} = gen_fsm:start(gen_fsm_SUITE, {state_data, StateData}, []),
+ {ok, Pid} = gen_fsm:start(gen_fsm_SUITE, {state_data, StateData}, []),
%% bad return value in the gen_fsm loop
- ?line {'EXIT',{{bad_return_value, badreturn},_}} =
+ {'EXIT',{{bad_return_value, badreturn},_}} =
(catch gen_fsm:sync_send_event(Pid, badreturn)),
receive
{error,_GroupLeader,{Pid,
@@ -514,10 +509,9 @@ error_format_status(Config) when is_list(Config) ->
[Pid,{_,_,badreturn},idle,{formatted,StateData},_]}} ->
ok;
Other ->
- ?line io:format("Unexpected: ~p", [Other]),
- ?line ?t:fail()
+ io:format("Unexpected: ~p", [Other]),
+ ct:fail(failed)
end,
- ?t:messages_get(),
process_flag(trap_exit, OldFl),
ok.
@@ -534,12 +528,11 @@ terminate_crash_format(Config) when is_list(Config) ->
ok;
Other ->
io:format("Unexpected: ~p", [Other]),
- ?t:fail()
+ ct:fail(failed)
after 5000 ->
io:format("Timeout: expected error logger msg", []),
- ?t:fail()
+ ct:fail(failed)
end,
- _ = ?t:messages_get(),
process_flag(trap_exit, OldFl),
ok.
@@ -603,7 +596,9 @@ hibernate(Config) when is_list(Config) ->
{ok, Pid0} = gen_fsm:start_link(?MODULE, hiber_now, []),
is_in_erlang_hibernate(Pid0),
stop_it(Pid0),
- test_server:messages_get(),
+ receive
+ {'EXIT',Pid0,normal} -> ok
+ end,
{ok, Pid} = gen_fsm:start_link(?MODULE, hiber, []),
true = ({current_function,{erlang,hibernate,3}} =/=
@@ -677,7 +672,11 @@ hibernate(Config) when is_list(Config) ->
good_morning = gen_fsm:sync_send_all_state_event(Pid, wakeup_sync),
is_not_in_erlang_hibernate(Pid),
stop_it(Pid),
- test_server:messages_get(),
+ receive
+ {'EXIT',Pid,normal} -> ok
+ end,
+
+ [] = get_messages(),
process_flag(trap_exit, OldFl),
ok.
@@ -687,7 +686,7 @@ is_in_erlang_hibernate(Pid) ->
is_in_erlang_hibernate_1(0, Pid) ->
io:format("~p\n", [erlang:process_info(Pid, current_function)]),
- ?t:fail(not_in_erlang_hibernate_3);
+ ct:fail(not_in_erlang_hibernate_3);
is_in_erlang_hibernate_1(N, Pid) ->
{current_function,MFA} = erlang:process_info(Pid, current_function),
case MFA of
@@ -704,7 +703,7 @@ is_not_in_erlang_hibernate(Pid) ->
is_not_in_erlang_hibernate_1(0, Pid) ->
io:format("~p\n", [erlang:process_info(Pid, current_function)]),
- ?t:fail(not_in_erlang_hibernate_3);
+ ct:fail(not_in_erlang_hibernate_3);
is_not_in_erlang_hibernate_1(N, Pid) ->
{current_function,MFA} = erlang:process_info(Pid, current_function),
case MFA of
@@ -715,108 +714,102 @@ is_not_in_erlang_hibernate_1(N, Pid) ->
ok
end.
-%%sys1(suite) -> [];
-%%sys1(_) ->
-
-enter_loop(suite) ->
- [];
-enter_loop(doc) ->
- ["Test gen_fsm:enter_loop/4,5,6"];
+%% Test gen_fsm:enter_loop/4,5,6.
enter_loop(Config) when is_list(Config) ->
OldFlag = process_flag(trap_exit, true),
- ?line dummy_via:reset(),
+ dummy_via:reset(),
%% Locally registered process + {local, Name}
- ?line {ok, Pid1a} =
+ {ok, Pid1a} =
proc_lib:start_link(?MODULE, enter_loop, [local, local]),
- ?line yes = gen_fsm:sync_send_event(Pid1a, 'alive?'),
- ?line stopped = gen_fsm:sync_send_event(Pid1a, stop),
+ yes = gen_fsm:sync_send_event(Pid1a, 'alive?'),
+ stopped = gen_fsm:sync_send_event(Pid1a, stop),
receive
{'EXIT', Pid1a, normal} ->
ok
after 5000 ->
- ?line test_server:fail(gen_fsm_did_not_die)
+ ct:fail(gen_fsm_did_not_die)
end,
%% Unregistered process + {local, Name}
- ?line {ok, Pid1b} =
+ {ok, Pid1b} =
proc_lib:start_link(?MODULE, enter_loop, [anon, local]),
receive
{'EXIT', Pid1b, process_not_registered} ->
ok
after 5000 ->
- ?line test_server:fail(gen_fsm_did_not_die)
+ ct:fail(gen_fsm_did_not_die)
end,
%% Globally registered process + {global, Name}
- ?line {ok, Pid2a} =
+ {ok, Pid2a} =
proc_lib:start_link(?MODULE, enter_loop, [global, global]),
- ?line yes = gen_fsm:sync_send_event(Pid2a, 'alive?'),
- ?line stopped = gen_fsm:sync_send_event(Pid2a, stop),
+ yes = gen_fsm:sync_send_event(Pid2a, 'alive?'),
+ stopped = gen_fsm:sync_send_event(Pid2a, stop),
receive
{'EXIT', Pid2a, normal} ->
ok
after 5000 ->
- ?line test_server:fail(gen_fsm_did_not_die)
+ ct:fail(gen_fsm_did_not_die)
end,
%% Unregistered process + {global, Name}
- ?line {ok, Pid2b} =
+ {ok, Pid2b} =
proc_lib:start_link(?MODULE, enter_loop, [anon, global]),
receive
{'EXIT', Pid2b, process_not_registered_globally} ->
ok
after 5000 ->
- ?line test_server:fail(gen_fsm_did_not_die)
+ ct:fail(gen_fsm_did_not_die)
end,
%% Unregistered process + no name
- ?line {ok, Pid3} =
+ {ok, Pid3} =
proc_lib:start_link(?MODULE, enter_loop, [anon, anon]),
- ?line yes = gen_fsm:sync_send_event(Pid3, 'alive?'),
- ?line stopped = gen_fsm:sync_send_event(Pid3, stop),
+ yes = gen_fsm:sync_send_event(Pid3, 'alive?'),
+ stopped = gen_fsm:sync_send_event(Pid3, stop),
receive
{'EXIT', Pid3, normal} ->
ok
after 5000 ->
- ?line test_server:fail(gen_fsm_did_not_die)
+ ct:fail(gen_fsm_did_not_die)
end,
%% Process not started using proc_lib
- ?line Pid4 =
+ Pid4 =
spawn_link(gen_fsm, enter_loop, [?MODULE, [], state0, []]),
receive
{'EXIT', Pid4, process_was_not_started_by_proc_lib} ->
ok
after 5000 ->
- ?line test_server:fail(gen_fsm_did_not_die)
+ ct:fail(gen_fsm_did_not_die)
end,
%% Make sure I am the parent, ie that ordering a shutdown will
%% result in the process terminating with Reason==shutdown
- ?line {ok, Pid5} =
+ {ok, Pid5} =
proc_lib:start_link(?MODULE, enter_loop, [anon, anon]),
- ?line yes = gen_fsm:sync_send_event(Pid5, 'alive?'),
- ?line exit(Pid5, shutdown),
+ yes = gen_fsm:sync_send_event(Pid5, 'alive?'),
+ exit(Pid5, shutdown),
receive
{'EXIT', Pid5, shutdown} ->
ok
after 5000 ->
- ?line test_server:fail(gen_fsm_did_not_die)
+ ct:fail(gen_fsm_did_not_die)
end,
%% Make sure gen_fsm:enter_loop does not accept {local,Name}
%% when it's another process than the calling one which is
%% registered under that name
register(armitage, self()),
- ?line {ok, Pid6a} =
+ {ok, Pid6a} =
proc_lib:start_link(?MODULE, enter_loop, [anon, local]),
receive
{'EXIT', Pid6a, process_not_registered} ->
ok
after 1000 ->
- ?line test_server:fail(gen_fsm_started)
+ ct:fail(gen_fsm_started)
end,
unregister(armitage),
@@ -824,25 +817,24 @@ enter_loop(Config) when is_list(Config) ->
%% when it's another process than the calling one which is
%% registered under that name
global:register_name(armitage, self()),
- ?line {ok, Pid6b} =
+ {ok, Pid6b} =
proc_lib:start_link(?MODULE, enter_loop, [anon, global]),
receive
{'EXIT', Pid6b, process_not_registered_globally} ->
ok
after 1000 ->
- ?line test_server:fail(gen_fsm_started)
+ ct:fail(gen_fsm_started)
end,
global:unregister_name(armitage),
dummy_via:register_name(armitage, self()),
- ?line {ok, Pid6c} =
+ {ok, Pid6c} =
proc_lib:start_link(?MODULE, enter_loop, [anon, via]),
receive
{'EXIT', Pid6c, {process_not_registered_via, dummy_via}} ->
ok
after 1000 ->
- ?line test_server:fail({gen_fsm_started, process_info(self(),
- messages)})
+ ct:fail({gen_fsm_started, process_info(self(), messages)})
end,
dummy_via:unregister_name(armitage),
@@ -883,8 +875,8 @@ wfor(Msg) ->
stop_it(FSM) ->
- ?line stopped = gen_fsm:sync_send_all_state_event(FSM, stop),
- ?line {'EXIT',_} = (catch gen_fsm:sync_send_event(FSM, hej)),
+ stopped = gen_fsm:sync_send_all_state_event(FSM, stop),
+ {'EXIT',_} = (catch gen_fsm:sync_send_event(FSM, hej)),
ok.
@@ -895,7 +887,7 @@ do_func_test(FSM) ->
ok = do_connect(FSM),
ok = gen_fsm:send_all_state_event(FSM, {'alive?', self()}),
wfor(yes),
- test_server:do_times(3, ?MODULE, do_msg, [FSM]),
+ _ = [do_msg(FSM) || _ <- lists:seq(1, 3)],
ok = gen_fsm:send_all_state_event(FSM, {'alive?', self()}),
wfor(yes),
ok = do_disconnect(FSM),
@@ -933,7 +925,7 @@ do_sync_func_test(FSM) ->
yes = gen_fsm:sync_send_all_state_event(FSM, 'alive?'),
ok = do_sync_connect(FSM),
yes = gen_fsm:sync_send_all_state_event(FSM, 'alive?'),
- test_server:do_times(3, ?MODULE, do_sync_msg, [FSM]),
+ _ = [do_sync_msg(FSM) || _ <- lists:seq(1, 3)],
yes = gen_fsm:sync_send_all_state_event(FSM, 'alive?'),
ok = do_sync_disconnect(FSM),
yes = gen_fsm:sync_send_all_state_event(FSM, 'alive?'),
@@ -964,7 +956,7 @@ do_sync_disconnect(FSM) ->
yes = gen_fsm:sync_send_event(FSM, disconnect),
check_state(FSM, idle).
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
@@ -979,7 +971,7 @@ init(stop) ->
init(stop_shutdown) ->
{stop, shutdown};
init(sleep) ->
- test_server:sleep(1000),
+ ct:sleep(1000),
{ok, idle, data};
init({timeout, T}) ->
{ok, idle, state, T};
@@ -1012,7 +1004,7 @@ idle(_, Data) ->
idle({connect, _Pid}, _From, Data) ->
{reply, accept, wfor_conf, Data};
idle({delayed_answer, T}, _From, Data) ->
- test_server:sleep(T),
+ ct:sleep(T),
{reply, delayed, idle, Data};
idle(badreturn, _From, _Data) ->
badreturn;
@@ -1070,8 +1062,8 @@ hiber_idle('alive?', _From, Data) ->
{reply, 'alive!', hiber_idle, Data};
hiber_idle(hibernate_sync, _From, Data) ->
{reply, hibernating, hiber_wakeup, Data,hibernate}.
-hiber_idle(timeout, hibernate_me) -> % Arrive here from
- % handle_info(hibernate_later,...)
+hiber_idle(timeout, hibernate_me) ->
+ %% Arrive here from handle_info(hibernate_later,...)
{next_state, hiber_idle, [], hibernate};
hiber_idle(hibernate_async, Data) ->
{next_state,hiber_wakeup, Data, hibernate}.
@@ -1084,9 +1076,10 @@ hiber_wakeup(wakeup_async,Data) ->
{next_state,hiber_idle,Data};
hiber_wakeup(snooze_async,Data) ->
{next_state,hiber_wakeup,Data,hibernate}.
-
-handle_info(hibernate_now, _SName, _State) -> % Arrive here from by direct ! from testcase
+
+handle_info(hibernate_now, _SName, _State) ->
+ %% Arrive here from by direct ! from testcase
{next_state, hiber_idle, [], hibernate};
handle_info(hibernate_later, _SName, _State) ->
{next_state, hiber_idle, hibernate_me, 1000};
@@ -1134,3 +1127,9 @@ format_status(terminate, [_Pdict, StateData]) ->
{formatted, StateData};
format_status(normal, [_Pdict, _StateData]) ->
[format_status_called].
+
+get_messages() ->
+ receive
+ Msg -> [Msg|get_messages()]
+ after 1 -> []
+ end.
diff --git a/lib/stdlib/test/gen_server_SUITE.erl b/lib/stdlib/test/gen_server_SUITE.erl
index 0ae763a48d..916fbc4e84 100644
--- a/lib/stdlib/test/gen_server_SUITE.erl
+++ b/lib/stdlib/test/gen_server_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(gen_server_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/inet.hrl").
-export([init_per_testcase/2, end_per_testcase/2]).
@@ -40,7 +40,7 @@
-export([stop1/1, stop2/1, stop3/1, stop4/1, stop5/1, stop6/1, stop7/1,
stop8/1, stop9/1, stop10/1]).
-% spawn export
+%% spawn export
-export([spec_init_local/2, spec_init_global/2, spec_init_via/2,
spec_init_default_timeout/2, spec_init_global_default_timeout/2,
spec_init_anonymous/1,
@@ -48,11 +48,13 @@
spec_init_not_proc_lib/1, cast_fast_messup/0]).
-% The gen_server behaviour
+%% The gen_server behaviour
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, format_status/2]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[start, {group,stop}, crash, call, cast, cast_fast, info, abcast,
@@ -83,8 +85,6 @@ end_per_group(_GroupName, Config) ->
Config.
--define(default_timeout, ?t:minutes(1)).
-
init_per_testcase(Case, Config) when Case == call_remote1;
Case == call_remote2;
Case == call_remote3;
@@ -92,11 +92,10 @@ init_per_testcase(Case, Config) when Case == call_remote1;
Case == call_remote_n2;
Case == call_remote_n3 ->
{ok,N} = start_node(hubba),
- ?line Dog = ?t:timetrap(?default_timeout),
- [{node,N},{watchdog, Dog} | Config];
+ [{node,N} | Config];
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
+ Config.
+
end_per_testcase(_Case, Config) ->
case proplists:get_value(node, Config) of
undefined ->
@@ -104,8 +103,6 @@ end_per_testcase(_Case, Config) ->
N ->
test_server:stop_node(N)
end,
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
ok.
@@ -113,131 +110,133 @@ end_per_testcase(_Case, Config) ->
%% Start and stop a gen_server.
%% --------------------------------------
-start(suite) -> [];
start(Config) when is_list(Config) ->
OldFl = process_flag(trap_exit, true),
%% anonymous
- ?line {ok, Pid0} = gen_server:start(gen_server_SUITE, [], []),
- ?line ok = gen_server:call(Pid0, started_p),
- ?line ok = gen_server:call(Pid0, stop),
- ?line busy_wait_for_process(Pid0,600),
- ?line {'EXIT', {noproc,_}} = (catch gen_server:call(Pid0, started_p, 1)),
+ {ok, Pid0} = gen_server:start(gen_server_SUITE, [], []),
+ ok = gen_server:call(Pid0, started_p),
+ ok = gen_server:call(Pid0, stop),
+ busy_wait_for_process(Pid0,600),
+ {'EXIT', {noproc,_}} = (catch gen_server:call(Pid0, started_p, 1)),
%% anonymous with timeout
- ?line {ok, Pid00} = gen_server:start(gen_server_SUITE, [],
- [{timeout,1000}]),
- ?line ok = gen_server:call(Pid00, started_p),
- ?line ok = gen_server:call(Pid00, stop),
- ?line {error, timeout} = gen_server:start(gen_server_SUITE, sleep,
- [{timeout,100}]),
+ {ok, Pid00} = gen_server:start(gen_server_SUITE, [],
+ [{timeout,1000}]),
+ ok = gen_server:call(Pid00, started_p),
+ ok = gen_server:call(Pid00, stop),
+ {error, timeout} = gen_server:start(gen_server_SUITE, sleep,
+ [{timeout,100}]),
%% anonymous with ignore
- ?line ignore = gen_server:start(gen_server_SUITE, ignore, []),
+ ignore = gen_server:start(gen_server_SUITE, ignore, []),
%% anonymous with stop
- ?line {error, stopped} = gen_server:start(gen_server_SUITE, stop, []),
+ {error, stopped} = gen_server:start(gen_server_SUITE, stop, []),
%% anonymous linked
- ?line {ok, Pid1} =
+ {ok, Pid1} =
gen_server:start_link(gen_server_SUITE, [], []),
- ?line ok = gen_server:call(Pid1, started_p),
- ?line ok = gen_server:call(Pid1, stop),
- ?line receive
- {'EXIT', Pid1, stopped} ->
- ok
- after 5000 ->
- test_server:fail(not_stopped)
- end,
+ ok = gen_server:call(Pid1, started_p),
+ ok = gen_server:call(Pid1, stop),
+ receive
+ {'EXIT', Pid1, stopped} ->
+ ok
+ after 5000 ->
+ ct:fail(not_stopped)
+ end,
%% local register
- ?line {ok, Pid2} =
+ {ok, Pid2} =
gen_server:start({local, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call(my_test_name, started_p),
- ?line {error, {already_started, Pid2}} =
+ ok = gen_server:call(my_test_name, started_p),
+ {error, {already_started, Pid2}} =
gen_server:start({local, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call(my_test_name, stop),
+ ok = gen_server:call(my_test_name, stop),
- ?line busy_wait_for_process(Pid2,600),
+ busy_wait_for_process(Pid2,600),
- ?line {'EXIT', {noproc,_}} = (catch gen_server:call(Pid2, started_p, 10)),
+ {'EXIT', {noproc,_}} = (catch gen_server:call(Pid2, started_p, 10)),
%% local register linked
- ?line {ok, Pid3} =
+ {ok, Pid3} =
gen_server:start_link({local, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call(my_test_name, started_p),
- ?line {error, {already_started, Pid3}} =
+ ok = gen_server:call(my_test_name, started_p),
+ {error, {already_started, Pid3}} =
gen_server:start({local, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call(my_test_name, stop),
- ?line receive
- {'EXIT', Pid3, stopped} ->
- ok
- after 5000 ->
- test_server:fail(not_stopped)
- end,
+ ok = gen_server:call(my_test_name, stop),
+ receive
+ {'EXIT', Pid3, stopped} ->
+ ok
+ after 5000 ->
+ ct:fail(not_stopped)
+ end,
%% global register
- ?line {ok, Pid4} =
+ {ok, Pid4} =
gen_server:start({global, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call({global, my_test_name}, started_p),
- ?line {error, {already_started, Pid4}} =
+ ok = gen_server:call({global, my_test_name}, started_p),
+ {error, {already_started, Pid4}} =
gen_server:start({global, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call({global, my_test_name}, stop),
- test_server:sleep(1),
- ?line {'EXIT', {noproc,_}} = (catch gen_server:call(Pid4, started_p, 10)),
+ ok = gen_server:call({global, my_test_name}, stop),
+ ct:sleep(1),
+ {'EXIT', {noproc,_}} = (catch gen_server:call(Pid4, started_p, 10)),
%% global register linked
- ?line {ok, Pid5} =
+ {ok, Pid5} =
gen_server:start_link({global, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call({global, my_test_name}, started_p),
- ?line {error, {already_started, Pid5}} =
+ ok = gen_server:call({global, my_test_name}, started_p),
+ {error, {already_started, Pid5}} =
gen_server:start({global, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call({global, my_test_name}, stop),
- ?line receive
- {'EXIT', Pid5, stopped} ->
- ok
- after 5000 ->
- test_server:fail(not_stopped)
- end,
+ ok = gen_server:call({global, my_test_name}, stop),
+ receive
+ {'EXIT', Pid5, stopped} ->
+ ok
+ after 5000 ->
+ ct:fail(not_stopped)
+ end,
%% via register
- ?line dummy_via:reset(),
- ?line {ok, Pid6} =
+ dummy_via:reset(),
+ {ok, Pid6} =
gen_server:start({via, dummy_via, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call({via, dummy_via, my_test_name}, started_p),
- ?line {error, {already_started, Pid6}} =
+ ok = gen_server:call({via, dummy_via, my_test_name}, started_p),
+ {error, {already_started, Pid6}} =
gen_server:start({via, dummy_via, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call({via, dummy_via, my_test_name}, stop),
- test_server:sleep(1),
- ?line {'EXIT', {noproc,_}} = (catch gen_server:call(Pid6, started_p, 10)),
+ ok = gen_server:call({via, dummy_via, my_test_name}, stop),
+ ct:sleep(1),
+ {'EXIT', {noproc,_}} = (catch gen_server:call(Pid6, started_p, 10)),
%% via register linked
- ?line dummy_via:reset(),
- ?line {ok, Pid7} =
+ dummy_via:reset(),
+ {ok, Pid7} =
gen_server:start_link({via, dummy_via, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call({via, dummy_via, my_test_name}, started_p),
- ?line {error, {already_started, Pid7}} =
+ ok = gen_server:call({via, dummy_via, my_test_name}, started_p),
+ {error, {already_started, Pid7}} =
gen_server:start({via, dummy_via, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call({via, dummy_via, my_test_name}, stop),
- ?line receive
- {'EXIT', Pid7, stopped} ->
- ok
- after 5000 ->
- test_server:fail(not_stopped)
- end,
- test_server:messages_get(),
+ ok = gen_server:call({via, dummy_via, my_test_name}, stop),
+ receive
+ {'EXIT', Pid7, stopped} ->
+ ok
+ after 5000 ->
+ ct:fail(not_stopped)
+ end,
+ receive
+ Msg -> ct:fail({unexpected,Msg})
+ after 1 -> ok
+ end,
process_flag(trap_exit, OldFl),
ok.
@@ -294,7 +293,7 @@ stop6(_Config) ->
stop7(_Config) ->
dummy_via:reset(),
{ok, Pid} = gen_server:start({via, dummy_via, to_stop},
- ?MODULE, [], []),
+ ?MODULE, [], []),
ok = gen_server:stop({via, dummy_via, to_stop}),
false = erlang:is_process_alive(Pid),
{'EXIT',noproc} = (catch gen_server:stop({via, dummy_via, to_stop})),
@@ -342,31 +341,31 @@ stop10(_Config) ->
ok.
crash(Config) when is_list(Config) ->
- ?line error_logger_forwarder:register(),
+ error_logger_forwarder:register(),
process_flag(trap_exit, true),
%% This crash should not generate a crash report.
- ?line {ok,Pid0} = gen_server:start_link(?MODULE, [], []),
- ?line {'EXIT',{{shutdown,reason},_}} =
+ {ok,Pid0} = gen_server:start_link(?MODULE, [], []),
+ {'EXIT',{{shutdown,reason},_}} =
(catch gen_server:call(Pid0, shutdown_reason)),
receive {'EXIT',Pid0,{shutdown,reason}} -> ok end,
%% This crash should not generate a crash report.
- ?line {ok,Pid1} = gen_server:start_link(?MODULE, {state,state1}, []),
- ?line {'EXIT',{{shutdown,stop_reason},_}} =
+ {ok,Pid1} = gen_server:start_link(?MODULE, {state,state1}, []),
+ {'EXIT',{{shutdown,stop_reason},_}} =
(catch gen_server:call(Pid1, stop_shutdown_reason)),
receive {'EXIT',Pid1,{shutdown,stop_reason}} -> ok end,
%% This crash should not generate a crash report.
- ?line {ok,Pid2} = gen_server:start_link(?MODULE, [], []),
- ?line {'EXIT',{shutdown,_}} =
+ {ok,Pid2} = gen_server:start_link(?MODULE, [], []),
+ {'EXIT',{shutdown,_}} =
(catch gen_server:call(Pid2, exit_shutdown)),
receive {'EXIT',Pid2,shutdown} -> ok end,
%% This crash should not generate a crash report.
- ?line {ok,Pid3} = gen_server:start_link(?MODULE, {state,state3}, []),
- ?line {'EXIT',{shutdown,_}} =
+ {ok,Pid3} = gen_server:start_link(?MODULE, {state,state3}, []),
+ {'EXIT',{shutdown,_}} =
(catch gen_server:call(Pid3, stop_shutdown)),
receive {'EXIT',Pid3,shutdown} -> ok end,
@@ -374,8 +373,8 @@ crash(Config) when is_list(Config) ->
%% This crash should generate a crash report and a report
%% from gen_server.
- ?line {ok,Pid4} = gen_server:start(?MODULE, {state,state4}, []),
- ?line {'EXIT',{crashed,_}} = (catch gen_server:call(Pid4, crash)),
+ {ok,Pid4} = gen_server:start(?MODULE, {state,state4}, []),
+ {'EXIT',{crashed,_}} = (catch gen_server:call(Pid4, crash)),
receive
{error,_GroupLeader4,{Pid4,
"** Generic server"++_,
@@ -384,22 +383,22 @@ crash(Config) when is_list(Config) ->
|_Stacktrace]}]}} ->
ok;
Other4a ->
- ?line io:format("Unexpected: ~p", [Other4a]),
- ?line ?t:fail()
+ io:format("Unexpected: ~p", [Other4a]),
+ ct:fail(failed)
end,
receive
{error_report,_,{Pid4,crash_report,[List4|_]}} ->
{exit,crashed,_} = proplists:get_value(error_info, List4),
Pid4 = proplists:get_value(pid, List4);
Other4 ->
- ?line io:format("Unexpected: ~p", [Other4]),
- ?line ?t:fail()
+ io:format("Unexpected: ~p", [Other4]),
+ ct:fail(failed)
end,
receive
Any ->
- ?line io:format("Unexpected: ~p", [Any]),
- ?line ?t:fail()
+ io:format("Unexpected: ~p", [Any]),
+ ct:fail(failed)
after 500 ->
ok
end,
@@ -412,32 +411,31 @@ crash(Config) when is_list(Config) ->
%% handle_call.
%% --------------------------------------
-call(suite) -> [];
call(Config) when is_list(Config) ->
OldFl = process_flag(trap_exit, true),
- ?line {ok, _Pid} =
+ {ok, _Pid} =
gen_server:start_link({local, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call(my_test_name, started_p),
- ?line delayed = gen_server:call(my_test_name, {delayed_answer,1}),
+ ok = gen_server:call(my_test_name, started_p),
+ delayed = gen_server:call(my_test_name, {delayed_answer,1}),
%% two requests within a specified time.
- ?line ok = gen_server:call(my_test_name, {call_within, 1000}),
- test_server:sleep(500),
- ?line ok = gen_server:call(my_test_name, next_call),
- ?line ok = gen_server:call(my_test_name, {call_within, 1000}),
- test_server:sleep(1500),
- ?line false = gen_server:call(my_test_name, next_call),
-
+ ok = gen_server:call(my_test_name, {call_within, 1000}),
+ timer:sleep(500),
+ ok = gen_server:call(my_test_name, next_call),
+ ok = gen_server:call(my_test_name, {call_within, 1000}),
+ timer:sleep(1500),
+ false = gen_server:call(my_test_name, next_call),
+
%% timeout call.
- ?line delayed = gen_server:call(my_test_name, {delayed_answer,1}, 30),
- ?line {'EXIT',{timeout,_}} =
+ delayed = gen_server:call(my_test_name, {delayed_answer,1}, 30),
+ {'EXIT',{timeout,_}} =
(catch gen_server:call(my_test_name, {delayed_answer,30}, 1)),
%% bad return value in the gen_server loop from handle_call.
- ?line {'EXIT',{{bad_return_value, badreturn},_}} =
+ {'EXIT',{{bad_return_value, badreturn},_}} =
(catch gen_server:call(my_test_name, badreturn)),
process_flag(trap_exit, OldFl),
@@ -448,92 +446,86 @@ call(Config) when is_list(Config) ->
%% --------------------------------------
start_node(Name) ->
- ?line Pa = filename:dirname(code:which(?MODULE)),
- ?line N = test_server:start_node(Name, slave, [{args, " -pa " ++ Pa}]),
+ Pa = filename:dirname(code:which(?MODULE)),
+ N = test_server:start_node(Name, slave, [{args, " -pa " ++ Pa}]),
%% After starting a slave, it takes a little while until global knows
%% about it, even if nodes() includes it, so we make sure that global
%% knows about it before registering something on all nodes.
global:sync(),
N.
-call_remote1(suite) -> [];
call_remote1(Config) when is_list(Config) ->
N = hubba,
- ?line Node = proplists:get_value(node,Config),
- ?line {ok, Pid} = rpc:call(Node, gen_server, start,
- [{global, N}, ?MODULE, [], []]),
- ?line ok = (catch gen_server:call({global, N}, started_p, infinity)),
- ?line exit(Pid, boom),
- ?line {'EXIT', {Reason, _}} = (catch gen_server:call({global, N},
- started_p, infinity)),
- ?line true = (Reason == noproc) orelse (Reason == boom),
+ Node = proplists:get_value(node,Config),
+ {ok, Pid} = rpc:call(Node, gen_server, start,
+ [{global, N}, ?MODULE, [], []]),
+ ok = (catch gen_server:call({global, N}, started_p, infinity)),
+ exit(Pid, boom),
+ {'EXIT', {Reason, _}} = (catch gen_server:call({global, N},
+ started_p, infinity)),
+ true = (Reason == noproc) orelse (Reason == boom),
ok.
-call_remote2(suite) -> [];
call_remote2(Config) when is_list(Config) ->
- ?line N = hubba,
- ?line Node = proplists:get_value(node,Config),
-
- ?line {ok, Pid} = rpc:call(Node, gen_server, start,
- [{global, N}, ?MODULE, [], []]),
- ?line ok = (catch gen_server:call(Pid, started_p, infinity)),
- ?line exit(Pid, boom),
- ?line {'EXIT', {Reason, _}} = (catch gen_server:call(Pid,
- started_p, infinity)),
- ?line true = (Reason == noproc) orelse (Reason == boom),
+ N = hubba,
+ Node = proplists:get_value(node,Config),
+
+ {ok, Pid} = rpc:call(Node, gen_server, start,
+ [{global, N}, ?MODULE, [], []]),
+ ok = (catch gen_server:call(Pid, started_p, infinity)),
+ exit(Pid, boom),
+ {'EXIT', {Reason, _}} = (catch gen_server:call(Pid,
+ started_p, infinity)),
+ true = (Reason == noproc) orelse (Reason == boom),
ok.
-call_remote3(suite) -> [];
call_remote3(Config) when is_list(Config) ->
- ?line Node = proplists:get_value(node,Config),
-
- ?line {ok, Pid} = rpc:call(Node, gen_server, start,
- [{local, piller}, ?MODULE, [], []]),
- ?line ok = (catch gen_server:call({piller, Node}, started_p, infinity)),
- ?line exit(Pid, boom),
- ?line {'EXIT', {Reason, _}} = (catch gen_server:call({piller, Node},
- started_p, infinity)),
- ?line true = (Reason == noproc) orelse (Reason == boom),
+ Node = proplists:get_value(node,Config),
+
+ {ok, Pid} = rpc:call(Node, gen_server, start,
+ [{local, piller}, ?MODULE, [], []]),
+ ok = (catch gen_server:call({piller, Node}, started_p, infinity)),
+ exit(Pid, boom),
+ {'EXIT', {Reason, _}} = (catch gen_server:call({piller, Node},
+ started_p, infinity)),
+ true = (Reason == noproc) orelse (Reason == boom),
ok.
%% --------------------------------------
%% Test call to nonexisting node
%% --------------------------------------
-call_remote_n1(suite) -> [];
call_remote_n1(Config) when is_list(Config) ->
- ?line N = hubba,
- ?line Node = proplists:get_value(node,Config),
- ?line {ok, _Pid} = rpc:call(Node, gen_server, start,
- [{global, N}, ?MODULE, [], []]),
- ?line _ = test_server:stop_node(Node),
- ?line {'EXIT', {noproc, _}} =
+ N = hubba,
+ Node = proplists:get_value(node,Config),
+ {ok, _Pid} = rpc:call(Node, gen_server, start,
+ [{global, N}, ?MODULE, [], []]),
+ _ = test_server:stop_node(Node),
+ {'EXIT', {noproc, _}} =
(catch gen_server:call({global, N}, started_p, infinity)),
ok.
-call_remote_n2(suite) -> [];
call_remote_n2(Config) when is_list(Config) ->
- ?line N = hubba,
- ?line Node = proplists:get_value(node,Config),
+ N = hubba,
+ Node = proplists:get_value(node,Config),
- ?line {ok, Pid} = rpc:call(Node, gen_server, start,
- [{global, N}, ?MODULE, [], []]),
- ?line _ = test_server:stop_node(Node),
- ?line {'EXIT', {{nodedown, Node}, _}} = (catch gen_server:call(Pid,
- started_p, infinity)),
+ {ok, Pid} = rpc:call(Node, gen_server, start,
+ [{global, N}, ?MODULE, [], []]),
+ _ = test_server:stop_node(Node),
+ {'EXIT', {{nodedown, Node}, _}} = (catch gen_server:call(Pid,
+ started_p, infinity)),
ok.
-call_remote_n3(suite) -> [];
call_remote_n3(Config) when is_list(Config) ->
- ?line Node = proplists:get_value(node,Config),
+ Node = proplists:get_value(node,Config),
- ?line {ok, _Pid} = rpc:call(Node, gen_server, start,
- [{local, piller}, ?MODULE, [], []]),
- ?line _ = test_server:stop_node(Node),
- ?line {'EXIT', {{nodedown, Node}, _}} = (catch gen_server:call({piller, Node},
- started_p, infinity)),
+ {ok, _Pid} = rpc:call(Node, gen_server, start,
+ [{local, piller}, ?MODULE, [], []]),
+ _ = test_server:stop_node(Node),
+ {'EXIT', {{nodedown, Node}, _}} = (catch gen_server:call({piller, Node},
+ started_p, infinity)),
ok.
@@ -543,58 +535,56 @@ call_remote_n3(Config) when is_list(Config) ->
%% handle_cast.
%% --------------------------------------
-cast(suite) -> [];
cast(Config) when is_list(Config) ->
- ?line {ok, Pid} =
+ {ok, Pid} =
gen_server:start({local, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call(my_test_name, started_p),
-
- ?line ok = gen_server:cast(my_test_name, {self(),handle_cast}),
- ?line receive
- {Pid, handled_cast} ->
- ok
- after 1000 ->
- test_server:fail(handle_cast)
- end,
-
- ?line ok = gen_server:cast(my_test_name, {self(),delayed_cast,1}),
- ?line receive
- {Pid, delayed} ->
- ok
- after 1000 ->
- test_server:fail(delayed_cast)
- end,
-
- ?line ok = gen_server:cast(my_test_name, {self(),stop}),
- ?line receive
- {Pid, stopped} ->
- ok
- after 1000 ->
- test_server:fail(stop)
- end,
+ ok = gen_server:call(my_test_name, started_p),
+
+ ok = gen_server:cast(my_test_name, {self(),handle_cast}),
+ receive
+ {Pid, handled_cast} ->
+ ok
+ after 1000 ->
+ ct:fail(handle_cast)
+ end,
+
+ ok = gen_server:cast(my_test_name, {self(),delayed_cast,1}),
+ receive
+ {Pid, delayed} ->
+ ok
+ after 1000 ->
+ ct:fail(delayed_cast)
+ end,
+
+ ok = gen_server:cast(my_test_name, {self(),stop}),
+ receive
+ {Pid, stopped} ->
+ ok
+ after 1000 ->
+ ct:fail(stop)
+ end,
ok.
-cast_fast(suite) -> [];
-cast_fast(doc) -> ["Test that cast really return immediately"];
+%% Test that cast really return immediately.
cast_fast(Config) when is_list(Config) ->
- ?line {ok,Node} = start_node(hubba),
- ?line {_,"@"++Host} = lists:splitwith(fun ($@) -> false; (_) -> true end,
- atom_to_list(Node)),
- ?line FalseNode = list_to_atom("hopp@"++Host),
- ?line true = rpc:cast(Node, ?MODULE, cast_fast_messup, []),
-% ?line io:format("Nodes ~p~n", [rpc:call(N, ?MODULE, cast_fast_messup, [])]),
- ?line test_server:sleep(1000),
- ?line [Node] = nodes(),
- ?line {Time,ok} = test_server:timecall(gen_server, cast,
- [{hopp,FalseNode},hopp]),
- ?line true = test_server:stop_node(Node),
- ?line if Time > 1.0 -> % Default listen timeout is about 7.0 s
- test_server:fail(hanging_cast);
- true ->
- ok
- end.
+ {ok,Node} = start_node(hubba),
+ {_,"@"++Host} = lists:splitwith(fun ($@) -> false; (_) -> true end,
+ atom_to_list(Node)),
+ FalseNode = list_to_atom("hopp@"++Host),
+ true = rpc:cast(Node, ?MODULE, cast_fast_messup, []),
+ ct:sleep(1000),
+ [Node] = nodes(),
+ {Time,ok} = timer:tc(fun() ->
+ gen_server:cast({hopp,FalseNode}, hopp)
+ end),
+ true = test_server:stop_node(Node),
+ if Time > 1000000 -> % Default listen timeout is about 7.0 s
+ ct:fail(hanging_cast);
+ true ->
+ ok
+ end.
cast_fast_messup() ->
%% Register a false node: hopp@hostname
@@ -609,37 +599,36 @@ cast_fast_messup() ->
%% Test handle_info.
%% --------------------------------------
-info(suite) -> [];
info(Config) when is_list(Config) ->
- ?line {ok, Pid} =
+ {ok, Pid} =
gen_server:start({local, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call(my_test_name, started_p),
-
- ?line Pid ! {self(),handle_info},
- ?line receive
- {Pid, handled_info} ->
- ok
- after 1000 ->
- test_server:fail(handle_info)
- end,
-
- ?line Pid ! {self(),delayed_info,1},
- ?line receive
- {Pid, delayed_info} ->
- ok
- after 1000 ->
- test_server:fail(delayed_info)
- end,
-
- ?line Pid ! {self(),stop},
- ?line receive
- {Pid, stopped_info} ->
- ok
- after 1000 ->
- test_server:fail(stop_info)
- end,
+ ok = gen_server:call(my_test_name, started_p),
+
+ Pid ! {self(),handle_info},
+ receive
+ {Pid, handled_info} ->
+ ok
+ after 1000 ->
+ ct:fail(handle_info)
+ end,
+
+ Pid ! {self(),delayed_info,1},
+ receive
+ {Pid, delayed_info} ->
+ ok
+ after 1000 ->
+ ct:fail(delayed_info)
+ end,
+
+ Pid ! {self(),stop},
+ receive
+ {Pid, stopped_info} ->
+ ok
+ after 1000 ->
+ ct:fail(stop_info)
+ end,
ok.
hibernate(Config) when is_list(Config) ->
@@ -653,7 +642,7 @@ hibernate(Config) when is_list(Config) ->
{'EXIT', Pid0, stopped} ->
ok
after 5000 ->
- test_server:fail(gen_server_did_not_die)
+ ct:fail(gen_server_did_not_die)
end,
{ok, Pid} =
@@ -720,7 +709,7 @@ hibernate(Config) when is_list(Config) ->
{'EXIT', Pid, stopped} ->
ok
after 5000 ->
- test_server:fail(gen_server_did_not_die)
+ ct:fail(gen_server_did_not_die)
end,
process_flag(trap_exit, OldFl),
ok.
@@ -731,7 +720,7 @@ is_in_erlang_hibernate(Pid) ->
is_in_erlang_hibernate_1(0, Pid) ->
io:format("~p\n", [erlang:process_info(Pid, current_function)]),
- ?t:fail(not_in_erlang_hibernate_3);
+ ct:fail(not_in_erlang_hibernate_3);
is_in_erlang_hibernate_1(N, Pid) ->
{current_function,MFA} = erlang:process_info(Pid, current_function),
case MFA of
@@ -748,38 +737,37 @@ is_in_erlang_hibernate_1(N, Pid) ->
%% handle_cast.
%% --------------------------------------
-abcast(suite) -> [];
abcast(Config) when is_list(Config) ->
- ?line {ok, Pid} =
+ {ok, Pid} =
gen_server:start({local, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call(my_test_name, started_p),
-
- ?line abcast = gen_server:abcast(my_test_name, {self(),handle_cast}),
- ?line receive
- {Pid, handled_cast} ->
- ok
- after 1000 ->
- test_server:fail(abcast)
- end,
-
- ?line abcast = gen_server:abcast([node()], my_test_name,
- {self(),delayed_cast,1}),
- ?line receive
- {Pid, delayed} ->
- ok
- after 1000 ->
- test_server:fail(delayed_abcast)
- end,
-
- ?line abcast = gen_server:abcast(my_test_name, {self(),stop}),
- ?line receive
- {Pid, stopped} ->
- ok
- after 1000 ->
- test_server:fail(abcast_stop)
- end,
+ ok = gen_server:call(my_test_name, started_p),
+
+ abcast = gen_server:abcast(my_test_name, {self(),handle_cast}),
+ receive
+ {Pid, handled_cast} ->
+ ok
+ after 1000 ->
+ ct:fail(abcast)
+ end,
+
+ abcast = gen_server:abcast([node()], my_test_name,
+ {self(),delayed_cast,1}),
+ receive
+ {Pid, delayed} ->
+ ok
+ after 1000 ->
+ ct:fail(delayed_abcast)
+ end,
+
+ abcast = gen_server:abcast(my_test_name, {self(),stop}),
+ receive
+ {Pid, stopped} ->
+ ok
+ after 1000 ->
+ ct:fail(abcast_stop)
+ end,
ok.
%% --------------------------------------
@@ -788,58 +776,56 @@ abcast(Config) when is_list(Config) ->
%% handle_call.
%% --------------------------------------
-multicall(suite) -> [];
multicall(Config) when is_list(Config) ->
OldFl = process_flag(trap_exit, true),
- ?line {ok, Pid} =
+ {ok, Pid} =
gen_server:start_link({local, my_test_name},
gen_server_SUITE, [], []),
- ?line ok = gen_server:call(my_test_name, started_p),
+ ok = gen_server:call(my_test_name, started_p),
Nodes = nodes(),
Node = node(),
- ?line {[{Node,delayed}],Nodes} =
- gen_server:multi_call(my_test_name, {delayed_answer,1}),
+ {[{Node,delayed}],Nodes} =
+ gen_server:multi_call(my_test_name, {delayed_answer,1}),
%% two requests within a specified time.
- ?line {[{Node,ok}],[]} =
- gen_server:multi_call([Node], my_test_name, {call_within, 1000}),
- test_server:sleep(500),
- ?line {[{Node,ok}],[]} =
- gen_server:multi_call([Node], my_test_name, next_call),
- ?line {[{Node,ok}],[]} =
- gen_server:multi_call([Node], my_test_name, {call_within, 1000}),
- test_server:sleep(1500),
- ?line {[{Node,false}],[]} =
- gen_server:multi_call([Node],my_test_name, next_call),
+ {[{Node,ok}],[]} =
+ gen_server:multi_call([Node], my_test_name, {call_within, 1000}),
+ timer:sleep(500),
+ {[{Node,ok}],[]} =
+ gen_server:multi_call([Node], my_test_name, next_call),
+ {[{Node,ok}],[]} =
+ gen_server:multi_call([Node], my_test_name, {call_within, 1000}),
+ timer:sleep(1500),
+ {[{Node,false}],[]} =
+ gen_server:multi_call([Node],my_test_name, next_call),
%% Stop the server.
- ?line {[{Node,ok}],[]} =
- gen_server:multi_call([Node],my_test_name, stop),
+ {[{Node,ok}],[]} =
+ gen_server:multi_call([Node],my_test_name, stop),
receive
{'EXIT', Pid, stopped} -> ok
after 1000 ->
- test_server:fail(multicall_stop)
+ ct:fail(multicall_stop)
end,
-
+
process_flag(trap_exit, OldFl),
ok.
%% OTP-3587
-multicall_down(suite) -> [];
multicall_down(Config) when is_list(Config) ->
%% We need a named host which is inaccessible.
- ?line Name = node@test01,
+ Name = node@test01,
%% We use 'global' as a gen_server to call.
- ?line {Good, Bad} = gen_server:multi_call([Name, node()],
- global_name_server,
- info,
- 3000),
+ {Good, Bad} = gen_server:multi_call([Name, node()],
+ global_name_server,
+ info,
+ 3000),
io:format("good = ~p, bad = ~p~n", [Good, Bad]),
- ?line [Name] = Bad,
+ [Name] = Bad,
ok.
busy_wait_for_process(Pid,N) ->
@@ -854,82 +840,79 @@ busy_wait_for_process(Pid,N) ->
ok
end.
%%--------------------------------------------------------------
-spec_init(doc) ->
- ["Test gen_server:enter_loop/[3,4,5]. Used when you want to write "
- "your own special init-phase."];
-spec_init(suite) ->
- [];
+%% Test gen_server:enter_loop/[3,4,5]. Used when you want to write
+%% your own special init-phase.
spec_init(Config) when is_list(Config) ->
-
+
OldFlag = process_flag(trap_exit, true),
- ?line {ok, Pid0} = start_link(spec_init_local, [{ok, my_server}, []]),
- ?line ok = gen_server:call(Pid0, started_p),
- ?line ok = gen_server:call(Pid0, stop),
+ {ok, Pid0} = start_link(spec_init_local, [{ok, my_server}, []]),
+ ok = gen_server:call(Pid0, started_p),
+ ok = gen_server:call(Pid0, stop),
receive
{'EXIT', Pid0, stopped} ->
ok
after 5000 ->
- test_server:fail(gen_server_did_not_die)
+ ct:fail(gen_server_did_not_die)
end,
-
- ?line {ok, Pid01} = start_link(spec_init_local, [{not_ok, my_server}, []]),
+
+ {ok, Pid01} = start_link(spec_init_local, [{not_ok, my_server}, []]),
receive
{'EXIT', Pid01, process_not_registered} ->
ok
after 5000 ->
- test_server:fail(gen_server_did_not_die)
+ ct:fail(gen_server_did_not_die)
end,
-
- ?line {ok, Pid1} = start_link(spec_init_global, [{ok, my_server}, []]),
- ?line ok = gen_server:call(Pid1, started_p),
- ?line ok = gen_server:call(Pid1, stop),
+
+ {ok, Pid1} = start_link(spec_init_global, [{ok, my_server}, []]),
+ ok = gen_server:call(Pid1, started_p),
+ ok = gen_server:call(Pid1, stop),
receive
{'EXIT', Pid1, stopped} ->
ok
after 5000 ->
- test_server:fail(gen_server_did_not_die)
+ ct:fail(gen_server_did_not_die)
end,
-
- ?line {ok, Pid11} =
+
+ {ok, Pid11} =
start_link(spec_init_global, [{not_ok, my_server}, []]),
receive
{'EXIT', Pid11, process_not_registered_globally} ->
ok
after 5000 ->
- test_server:fail(gen_server_did_not_die)
+ ct:fail(gen_server_did_not_die)
end,
-
- ?line {ok, Pid2} = start_link(spec_init_anonymous, [[]]),
- ?line ok = gen_server:call(Pid2, started_p),
- ?line ok = gen_server:call(Pid2, stop),
+
+ {ok, Pid2} = start_link(spec_init_anonymous, [[]]),
+ ok = gen_server:call(Pid2, started_p),
+ ok = gen_server:call(Pid2, stop),
receive
{'EXIT', Pid2, stopped} ->
ok
after 5000 ->
- test_server:fail(gen_server_did_not_die)
+ ct:fail(gen_server_did_not_die)
end,
-
- ?line {ok, Pid3} = start_link(spec_init_anonymous_default_timeout, [[]]),
- ?line ok = gen_server:call(Pid3, started_p),
- ?line ok = gen_server:call(Pid3, stop),
+
+ {ok, Pid3} = start_link(spec_init_anonymous_default_timeout, [[]]),
+ ok = gen_server:call(Pid3, started_p),
+ ok = gen_server:call(Pid3, stop),
receive
{'EXIT', Pid3, stopped} ->
ok
after 5000 ->
- test_server:fail(gen_server_did_not_die)
+ ct:fail(gen_server_did_not_die)
end,
-
- ?line {ok, Pid4} =
+
+ {ok, Pid4} =
start_link(spec_init_default_timeout, [{ok, my_server}, []]),
- ?line ok = gen_server:call(Pid4, started_p),
- ?line ok = gen_server:call(Pid4, stop),
+ ok = gen_server:call(Pid4, started_p),
+ ok = gen_server:call(Pid4, stop),
receive
{'EXIT', Pid4, stopped} ->
ok
after 5000 ->
- test_server:fail(gen_server_did_not_die)
+ ct:fail(gen_server_did_not_die)
end,
%% Before the OTP-10130 fix this failed because a timeout message
@@ -939,83 +922,79 @@ spec_init(Config) when is_list(Config) ->
start_link(spec_init_global_default_timeout, [{ok, hurra}, []]),
timer:sleep(1000),
ok = gen_server:call(_PidHurra, started_p),
-
- ?line Pid5 =
+
+ Pid5 =
erlang:spawn_link(?MODULE, spec_init_not_proc_lib, [[]]),
receive
{'EXIT', Pid5, process_was_not_started_by_proc_lib} ->
ok
after 5000 ->
- test_server:fail(gen_server_did_not_die)
+ ct:fail(gen_server_did_not_die)
end,
process_flag(trap_exit, OldFlag),
ok.
%%--------------------------------------------------------------
-spec_init_local_registered_parent(doc) ->
- ["Test that terminate is run when the parent is a locally registered "
- "process OTP-4820"];
-spec_init_local_registered_parent(suite) -> [];
+%% OTP-4820. Test that terminate is run when the parent is a locally
+%% registered process.
spec_init_local_registered_parent(Config) when is_list(Config) ->
register(foobar, self()),
process_flag(trap_exit, true),
-
- ?line {ok, Pid} = start_link(spec_init_local, [{ok, my_server}, []]),
-
- ?line ok = gen_server:cast(my_server, {self(),stop}),
- ?line receive
- {Pid, stopped} ->
- ok
- after 1000 ->
- test_server:fail(stop)
- end,
+
+ {ok, Pid} = start_link(spec_init_local, [{ok, my_server}, []]),
+
+ ok = gen_server:cast(my_server, {self(),stop}),
+ receive
+ {Pid, stopped} ->
+ ok
+ after 1000 ->
+ ct:fail(stop)
+ end,
unregister(foobar),
ok.
+
%%--------------------------------------------------------------
-spec_init_global_registered_parent(doc) ->
- ["Test that terminate is run when the parent is a global registered "
- "process OTP-4820"];
-spec_init_global_registered_parent(suite) -> [];
+%% OTP-4820. Test that terminate is run when the parent is a global registered
+%% process.
spec_init_global_registered_parent(Config) when is_list(Config) ->
global:register_name(foobar, self()),
process_flag(trap_exit, true),
-
- ?line {ok, Pid} = start_link(spec_init_global, [{ok, my_server}, []]),
-
- ?line ok = gen_server:call(Pid, started_p),
- ?line ok = gen_server:cast(Pid, {self(),stop}),
-
- ?line receive
- {Pid, stopped} ->
- ok
- after 1000 ->
- test_server:fail(stop)
- end,
+
+ {ok, Pid} = start_link(spec_init_global, [{ok, my_server}, []]),
+
+ ok = gen_server:call(Pid, started_p),
+ ok = gen_server:cast(Pid, {self(),stop}),
+
+ receive
+ {Pid, stopped} ->
+ ok
+ after 1000 ->
+ ct:fail(stop)
+ end,
global:unregister_name(foobar),
ok.
+
%%--------------------------------------------------------------
-otp_5854(suite) ->
- [];
-otp_5854(doc) ->
- ["Test check for registered name in enter_loop/3,4,5"];
+
+%% Test check for registered name in enter_loop/3,4,5.
otp_5854(Config) when is_list(Config) ->
OldFlag = process_flag(trap_exit, true),
- ?line dummy_via:reset(),
+ dummy_via:reset(),
%% Make sure gen_server:enter_loop does not accept {local,Name}
%% when it's another process than the calling one which is
%% registered under that name
register(armitage, self()),
- ?line {ok, Pid1} =
+ {ok, Pid1} =
start_link(spec_init_local, [{not_ok, armitage}, []]),
receive
{'EXIT', Pid1, process_not_registered} ->
ok
after 1000 ->
- ?line test_server:fail(gen_server_started)
+ ct:fail(gen_server_started)
end,
unregister(armitage),
@@ -1023,25 +1002,25 @@ otp_5854(Config) when is_list(Config) ->
%% when it's another process than the calling one which is
%% registered under that name
global:register_name(armitage, self()),
- ?line {ok, Pid2} =
+ {ok, Pid2} =
start_link(spec_init_global, [{not_ok, armitage}, []]),
receive
{'EXIT', Pid2, process_not_registered_globally} ->
ok
after 1000 ->
- ?line test_server:fail(gen_server_started)
+ ct:fail(gen_server_started)
end,
global:unregister_name(armitage),
%% (same for {via, Mod, Name})
dummy_via:register_name(armitage, self()),
- ?line {ok, Pid3} =
+ {ok, Pid3} =
start_link(spec_init_via, [{not_ok, armitage}, []]),
receive
{'EXIT', Pid3, {process_not_registered_via, dummy_via}} ->
ok
after 1000 ->
- ?line test_server:fail(gen_server_started)
+ ct:fail(gen_server_started)
end,
dummy_via:unregister_name(armitage),
@@ -1053,89 +1032,85 @@ otp_5854(Config) when is_list(Config) ->
%% returns.
otp_7669(Config) when is_list(Config) ->
- ?line ?t:do_times(100, fun do_otp_7669_local_ignore/0),
- ?line ?t:do_times(100, fun do_otp_7669_global_ignore/0),
- ?line ?t:do_times(10, fun do_otp_7669_stop/0),
+ do_times(100, fun do_otp_7669_local_ignore/0),
+ do_times(100, fun do_otp_7669_global_ignore/0),
+ do_times(10, fun do_otp_7669_stop/0),
ok.
+do_times(0, _) ->
+ ok;
+do_times(N, Fun) ->
+ Fun(),
+ do_times(N-1, Fun).
+
do_otp_7669_local_ignore() ->
%% The name should never be registered after the return
%% from gen_server:start/3.
- ?line ignore = gen_server:start({local,?MODULE}, ?MODULE, ignore, []),
- ?line undefined = whereis(?MODULE),
- ?line ignore = gen_server:start({local,?MODULE}, ?MODULE, ignore, []),
- ?line undefined = whereis(?MODULE),
- ?line ignore = gen_server:start_link({local,?MODULE}, ?MODULE, ignore, []),
- ?line undefined = whereis(?MODULE).
+ ignore = gen_server:start({local,?MODULE}, ?MODULE, ignore, []),
+ undefined = whereis(?MODULE),
+ ignore = gen_server:start({local,?MODULE}, ?MODULE, ignore, []),
+ undefined = whereis(?MODULE),
+ ignore = gen_server:start_link({local,?MODULE}, ?MODULE, ignore, []),
+ undefined = whereis(?MODULE).
do_otp_7669_global_ignore() ->
- ?line ignore = gen_server:start({global,?MODULE}, ?MODULE, ignore, []),
- ?line undefined = global:whereis_name(?MODULE),
- ?line ignore = gen_server:start_link({global,?MODULE}, ?MODULE, ignore, []),
- ?line undefined = global:whereis_name(?MODULE).
+ ignore = gen_server:start({global,?MODULE}, ?MODULE, ignore, []),
+ undefined = global:whereis_name(?MODULE),
+ ignore = gen_server:start_link({global,?MODULE}, ?MODULE, ignore, []),
+ undefined = global:whereis_name(?MODULE).
do_otp_7669_stop() ->
%% The name should never be registered after the return
%% from gen_server:start/3.
- ?line {error,stopped} = gen_server:start({local,?MODULE},
- ?MODULE, stop, []),
- ?line undefined = whereis(?MODULE),
+ {error,stopped} = gen_server:start({local,?MODULE},
+ ?MODULE, stop, []),
+ undefined = whereis(?MODULE),
- ?line {error,stopped} = gen_server:start({global,?MODULE},
- ?MODULE, stop, []),
- ?line undefined = global:whereis_name(?MODULE).
+ {error,stopped} = gen_server:start({global,?MODULE},
+ ?MODULE, stop, []),
+ undefined = global:whereis_name(?MODULE).
-%% Verify that sys:get_status correctly calls our format_status/2 fun
-%%
-call_format_status(suite) ->
- [];
-call_format_status(doc) ->
- ["Test that sys:get_status/1,2 calls format_status/2"];
+%% Verify that sys:get_status correctly calls our format_status/2 fun.
call_format_status(Config) when is_list(Config) ->
- ?line {ok, Pid} = gen_server:start_link({local, call_format_status},
- ?MODULE, [], []),
- ?line Status1 = sys:get_status(call_format_status),
- ?line {status, Pid, _Mod, [_PDict, running, _Parent, _, Data1]} = Status1,
- ?line [format_status_called | _] = lists:reverse(Data1),
- ?line Status2 = sys:get_status(call_format_status, 5000),
- ?line {status, Pid, _Mod, [_PDict, running, _Parent, _, Data2]} = Status2,
- ?line [format_status_called | _] = lists:reverse(Data2),
+ {ok, Pid} = gen_server:start_link({local, call_format_status},
+ ?MODULE, [], []),
+ Status1 = sys:get_status(call_format_status),
+ {status, Pid, _Mod, [_PDict, running, _Parent, _, Data1]} = Status1,
+ [format_status_called | _] = lists:reverse(Data1),
+ Status2 = sys:get_status(call_format_status, 5000),
+ {status, Pid, _Mod, [_PDict, running, _Parent, _, Data2]} = Status2,
+ [format_status_called | _] = lists:reverse(Data2),
%% check that format_status can handle a name being a pid (atom is
%% already checked by the previous test)
- ?line {ok, Pid3} = gen_server:start_link(gen_server_SUITE, [], []),
- ?line Status3 = sys:get_status(Pid3),
- ?line {status, Pid3, _Mod, [_PDict3, running, _Parent, _, Data3]} = Status3,
- ?line [format_status_called | _] = lists:reverse(Data3),
+ {ok, Pid3} = gen_server:start_link(gen_server_SUITE, [], []),
+ Status3 = sys:get_status(Pid3),
+ {status, Pid3, _Mod, [_PDict3, running, _Parent, _, Data3]} = Status3,
+ [format_status_called | _] = lists:reverse(Data3),
%% check that format_status can handle a name being a term other than a
%% pid or atom
GlobalName1 = {global, "CallFormatStatus"},
- ?line {ok, Pid4} = gen_server:start_link(GlobalName1,
- gen_server_SUITE, [], []),
- ?line Status4 = sys:get_status(Pid4),
- ?line {status, Pid4, _Mod, [_PDict4, running, _Parent, _, Data4]} = Status4,
- ?line [format_status_called | _] = lists:reverse(Data4),
+ {ok, Pid4} = gen_server:start_link(GlobalName1,
+ gen_server_SUITE, [], []),
+ Status4 = sys:get_status(Pid4),
+ {status, Pid4, _Mod, [_PDict4, running, _Parent, _, Data4]} = Status4,
+ [format_status_called | _] = lists:reverse(Data4),
GlobalName2 = {global, {name, "term"}},
- ?line {ok, Pid5} = gen_server:start_link(GlobalName2,
- gen_server_SUITE, [], []),
- ?line Status5 = sys:get_status(GlobalName2),
- ?line {status, Pid5, _Mod, [_PDict5, running, _Parent, _, Data5]} = Status5,
- ?line [format_status_called | _] = lists:reverse(Data5),
+ {ok, Pid5} = gen_server:start_link(GlobalName2,
+ gen_server_SUITE, [], []),
+ Status5 = sys:get_status(GlobalName2),
+ {status, Pid5, _Mod, [_PDict5, running, _Parent, _, Data5]} = Status5,
+ [format_status_called | _] = lists:reverse(Data5),
ok.
-%% Verify that error termination correctly calls our format_status/2 fun
-%%
-error_format_status(suite) ->
- [];
-error_format_status(doc) ->
- ["Test that an error termination calls format_status/2"];
+%% Verify that error termination correctly calls our format_status/2 fun.
error_format_status(Config) when is_list(Config) ->
- ?line error_logger_forwarder:register(),
+ error_logger_forwarder:register(),
OldFl = process_flag(trap_exit, true),
State = "called format_status",
- ?line {ok, Pid} = gen_server:start_link(?MODULE, {state, State}, []),
- ?line {'EXIT',{crashed,_}} = (catch gen_server:call(Pid, crash)),
+ {ok, Pid} = gen_server:start_link(?MODULE, {state, State}, []),
+ {'EXIT',{crashed,_}} = (catch gen_server:call(Pid, crash)),
receive
{'EXIT', Pid, crashed} ->
ok
@@ -1148,10 +1123,9 @@ error_format_status(Config) when is_list(Config) ->
|_Stacktrace]}]}} ->
ok;
Other ->
- ?line io:format("Unexpected: ~p", [Other]),
- ?line ?t:fail()
+ io:format("Unexpected: ~p", [Other]),
+ ct:fail(failed)
end,
- ?t:messages_get(),
process_flag(trap_exit, OldFl),
ok.
@@ -1169,29 +1143,23 @@ terminate_crash_format(Config) when is_list(Config) ->
"** Generic server"++_,
[Pid,stop, {formatted, State},
{{crash, terminate},[{?MODULE,terminate,2,_}
- |_Stacktrace]}]}} ->
+ |_Stacktrace]}]}} ->
ok;
Other ->
io:format("Unexpected: ~p", [Other]),
- ?t:fail()
+ ct:fail(failed)
after 5000 ->
io:format("Timeout: expected error logger msg", []),
- ?t:fail()
+ ct:fail(failed)
end,
- ?t:messages_get(),
process_flag(trap_exit, OldFl),
ok.
%% Verify that sys:get_state correctly returns gen_server state
-%%
-get_state(suite) ->
- [];
-get_state(doc) ->
- ["Test that sys:get_state/1,2 return the gen_server state"];
get_state(Config) when is_list(Config) ->
State = self(),
{ok, _Pid} = gen_server:start_link({local, get_state},
- ?MODULE, {state,State}, []),
+ ?MODULE, {state,State}, []),
State = sys:get_state(get_state),
State = sys:get_state(get_state, 5000),
{ok, Pid} = gen_server:start_link(?MODULE, {state,State}, []),
@@ -1203,15 +1171,10 @@ get_state(Config) when is_list(Config) ->
ok.
%% Verify that sys:replace_state correctly replaces gen_server state
-%%
-replace_state(suite) ->
- [];
-replace_state(doc) ->
- ["Test that sys:replace_state/1,2 replace the gen_server state"];
replace_state(Config) when is_list(Config) ->
State = self(),
{ok, _Pid} = gen_server:start_link({local, replace_state},
- ?MODULE, {state,State}, []),
+ ?MODULE, {state,State}, []),
State = sys:get_state(replace_state),
NState1 = "replaced",
Replace1 = fun(_) -> NState1 end,
@@ -1250,16 +1213,16 @@ call_with_huge_message_queue(Config) when is_list(Config) ->
"is not implemented"};
false ->
do_call_with_huge_message_queue()
- end.
+ end.
do_call_with_huge_message_queue() ->
- ?line Pid = spawn_link(fun echo_loop/0),
+ Pid = spawn_link(fun echo_loop/0),
- ?line {Time,ok} = tc(fun() -> calls(10000, Pid) end),
+ {Time,ok} = tc(fun() -> calls(10000, Pid) end),
- ?line [self() ! {msg,N} || N <- lists:seq(1, 500000)],
+ [self() ! {msg,N} || N <- lists:seq(1, 500000)],
erlang:garbage_collect(),
- ?line {NewTime,ok} = tc(fun() -> calls(10000, Pid) end),
+ {NewTime,ok} = tc(fun() -> calls(10000, Pid) end),
io:format("Time for empty message queue: ~p", [Time]),
io:format("Time for huge message queue: ~p", [NewTime]),
@@ -1269,7 +1232,7 @@ do_call_with_huge_message_queue() ->
ok;
Q ->
io:format("Q = ~p", [Q]),
- ?line ?t:fail()
+ ct:fail(failed)
end,
ok.
@@ -1381,7 +1344,7 @@ init(stop) ->
init(hibernate) ->
{ok,[],hibernate};
init(sleep) ->
- test_server:sleep(1000),
+ ct:sleep(1000),
{ok, []};
init({state,State}) ->
{ok, State}.
@@ -1435,11 +1398,11 @@ handle_info(timeout, {reply_to, From}) ->
gen_server:reply(From, delayed),
{noreply, []};
handle_info(timeout, hibernate_me) -> % Arrive here from
- % handle_info(hibernate_later,...)
+ % handle_info(hibernate_later,...)
{noreply, [], hibernate};
handle_info(hibernate_now, _State) -> % Arrive here from
- % handle_cast({_,hibernate_later},...)
- % and by direct ! from testcase
+ % handle_cast({_,hibernate_later},...)
+ % and by direct ! from testcase
{noreply, [], hibernate};
handle_info(hibernate_later, _State) ->
{noreply, hibernate_me, 1000};
diff --git a/lib/stdlib/test/id_transform_SUITE.erl b/lib/stdlib/test/id_transform_SUITE.erl
index 1cff990697..aaa6a758d5 100644
--- a/lib/stdlib/test/id_transform_SUITE.erl
+++ b/lib/stdlib/test/id_transform_SUITE.erl
@@ -29,11 +29,12 @@
-export([check/2,check2/1,g/0,f/1,t/1,t1/1,t2/1,t3/1,t4/1,
t5/1,apa/1,new_fun/0]).
- % Serves as test...
+%% Serves as test...
-hej(hopp).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]}].
all() ->
[id_transform].
@@ -54,7 +55,7 @@ end_per_group(_GroupName, Config) ->
Config.
-id_transform(doc) -> "Test erl_id_trans.";
+%% Test erl_id_trans.
id_transform(Config) when is_list(Config) ->
File = filename:join([code:lib_dir(stdlib),"examples",
"erl_id_trans.erl"]),
@@ -62,10 +63,8 @@ id_transform(Config) when is_list(Config) ->
{module,erl_id_trans} = code:load_binary(erl_id_trans, File, Bin),
case test_server:purify_is_running() of
false ->
- Dog = ct:timetrap(?t:hours(1)),
- Res = run_in_test_suite(),
- ?t:timetrap_cancel(Dog),
- Res;
+ ct:timetrap({hours,1}),
+ run_in_test_suite();
true ->
{skip,"Valgrind (too slow)"}
end.
@@ -139,9 +138,9 @@ do_trans_1(File, Tree0) ->
{failed,{File,{transform,{unknown,Else}}}}
end.
-% From here on there's only fake code to serve as test cases
-% for the id_transform.
-% They need to be exported.
+%% From here on there's only fake code to serve as test cases
+%% for the id_transform.
+%% They need to be exported.
check(X,_Y) when X ->
true;
@@ -192,7 +191,7 @@ f(X) ->
nok
end.
-% Stolen from erl_lint_SUITE.erl
+%% Stolen from erl_lint_SUITE.erl
-record(apa, {}).
t(A) when atom(A) ->
diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl
index cb96f8b575..ddc55b1466 100644
--- a/lib/stdlib/test/io_SUITE.erl
+++ b/lib/stdlib/test/io_SUITE.erl
@@ -26,7 +26,7 @@
-export([error_1/1, float_g/1, otp_5403/1, otp_5813/1, otp_6230/1,
otp_6282/1, otp_6354/1, otp_6495/1, otp_6517/1, otp_6502/1,
- manpage/1, otp_6708/1, otp_7084/1, otp_7421/1,
+ manpage/1, otp_6708/1, otp_7084/0, otp_7084/1, otp_7421/1,
io_lib_collect_line_3_wb/1, cr_whitespace_in_string/1,
io_fread_newlines/1, otp_8989/1, io_lib_fread_literal/1,
printable_range/1, bad_printable_range/1,
@@ -37,7 +37,7 @@
-export([pretty/2]).
-%-define(debug, true).
+%%-define(debug, true).
-ifdef(debug).
-define(format(S, A), io:format(S, A)).
@@ -46,24 +46,20 @@
-define(t, test_server).
-define(privdir(_), "./io_SUITE_priv").
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(format(S, A), ok).
--define(privdir(Conf), ?config(priv_dir, Conf)).
+-define(privdir(Conf), proplists:get_value(priv_dir, Conf)).
-endif.
-
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
-
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
+ Config.
+
end_per_testcase(_Case, _Config) ->
- Dog = ?config(watchdog, _Config),
- test_server:timetrap_cancel(Dog),
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[error_1, float_g, otp_5403, otp_5813, otp_6230,
@@ -92,855 +88,588 @@ end_per_group(_GroupName, Config) ->
Config.
-error_1(doc) ->
- ["Error cases for output"];
-error_1(suite) ->
- [];
+%% Error cases for output.
error_1(Config) when is_list(Config) ->
%% We don't do erroneous output on stdout - the test server
%% seems to catch that somehow.
- ?line PrivDir = ?privdir(Config),
- ?line File = filename:join(PrivDir, "slask"),
- ?line {ok, F1} = file:open(File, [write]),
- ?line {'EXIT', _} = (catch io:format(muttru, "hej", [])),
- ?line {'EXIT', _} = (catch io:format(F1, pelle, "hej")),
- ?line {'EXIT', _} = (catch io:format(F1, 1, "hej")),
- ?line {'EXIT', _} = (catch io:format(F1, "~p~", [kaka])),
- ?line {'EXIT', _} = (catch io:format(F1, "~m~n", [kaka])),
+ PrivDir = ?privdir(Config),
+ File = filename:join(PrivDir, "slask"),
+ {ok, F1} = file:open(File, [write]),
+ {'EXIT', _} = (catch io:format(muttru, "hej", [])),
+ {'EXIT', _} = (catch io:format(F1, pelle, "hej")),
+ {'EXIT', _} = (catch io:format(F1, 1, "hej")),
+ {'EXIT', _} = (catch io:format(F1, "~p~", [kaka])),
+ {'EXIT', _} = (catch io:format(F1, "~m~n", [kaka])),
%% This causes the file process to die, and it is linked to us,
%% so we can't catch the error this easily.
-% ?line {'EXIT', _} = (catch io:put_chars(F1, 666)),
+ %% {'EXIT', _} = (catch io:put_chars(F1, 666)),
- ?line file:close(F1),
- ?line {'EXIT', _} = (catch io:format(F1, "~p", ["hej"])),
+ file:close(F1),
+ {'EXIT', _} = (catch io:format(F1, "~p", ["hej"])),
ok.
float_g(Config) when is_list(Config) ->
- ?line ["5.00000e-2",
- "0.500000",
- "5.00000",
- "50.0000",
- "500.000",
- "5000.00",
- "5.00000e+4",
- "5.00000e+5"] = float_g_1("~g", 5.0, -2, 5),
-
- ?line ["-5.0000e-2",
- "-0.50000",
- "-5.0000",
- "-50.000",
- "-500.00",
- "-5000.0",
- "-5.0000e+4",
- "-5.0000e+5"] = float_g_1("~.5g", -5.0, -2, 5),
-
- ?line ["5.000e-2",
- "0.5000",
- "5.000",
- "50.00",
- "500.0",
- "5.000e+3",
- "5.000e+4",
- "5.000e+5"] = float_g_1("~.4g", 5.0, -2, 5),
-
- ?line ["-5.00e-2",
- "-0.500",
- "-5.00",
- "-50.0",
- "-5.00e+2",
- "-5.00e+3",
- "-5.00e+4",
- "-5.00e+5"] = float_g_1("~.3g", -5.0, -2, 5),
-
- ?line ["5.0e-2",
- "0.50",
- "5.0",
- "5.0e+1",
- "5.0e+2",
- "5.0e+3",
- "5.0e+4",
- "5.0e+5"] = float_g_1("~.2g", 5.0, -2, 5),
-
- ?line
- case catch fmt("~.1g", [0.5]) of
- "0.5" ->
- ?line
- ["5.0e-2",
- "0.5",
- "5.0e+0",
- "5.0e+1",
- "5.0e+2",
- "5.0e+3",
- "5.0e+4",
- "5.0e+5"] = float_g_1("~.1g", 5.0, -2, 5);
- {'EXIT',_} -> ok
- end,
-
- ?line ["4.99999e-2",
- "0.499999",
- "4.99999",
- "49.9999",
- "499.999",
- "4999.99",
- "4.99999e+4",
- "4.99999e+5"] = float_g_1("~g", 4.9999949999, -2, 5),
-
- ?line ["-5.00000e-2",
- "-0.500000",
- "-5.00000",
- "-50.0000",
- "-500.000",
- "-5000.00",
- "-5.00000e+4",
- "-5.00000e+5"] = float_g_1("~g", -4.9999950001, -2, 5),
+ ["5.00000e-2",
+ "0.500000",
+ "5.00000",
+ "50.0000",
+ "500.000",
+ "5000.00",
+ "5.00000e+4",
+ "5.00000e+5"] = float_g_1("~g", 5.0, -2, 5),
+
+ ["-5.0000e-2",
+ "-0.50000",
+ "-5.0000",
+ "-50.000",
+ "-500.00",
+ "-5000.0",
+ "-5.0000e+4",
+ "-5.0000e+5"] = float_g_1("~.5g", -5.0, -2, 5),
+
+ ["5.000e-2",
+ "0.5000",
+ "5.000",
+ "50.00",
+ "500.0",
+ "5.000e+3",
+ "5.000e+4",
+ "5.000e+5"] = float_g_1("~.4g", 5.0, -2, 5),
+
+ ["-5.00e-2",
+ "-0.500",
+ "-5.00",
+ "-50.0",
+ "-5.00e+2",
+ "-5.00e+3",
+ "-5.00e+4",
+ "-5.00e+5"] = float_g_1("~.3g", -5.0, -2, 5),
+
+ ["5.0e-2",
+ "0.50",
+ "5.0",
+ "5.0e+1",
+ "5.0e+2",
+ "5.0e+3",
+ "5.0e+4",
+ "5.0e+5"] = float_g_1("~.2g", 5.0, -2, 5),
+
+ case catch fmt("~.1g", [0.5]) of
+ "0.5" ->
+ ["5.0e-2",
+ "0.5",
+ "5.0e+0",
+ "5.0e+1",
+ "5.0e+2",
+ "5.0e+3",
+ "5.0e+4",
+ "5.0e+5"] = float_g_1("~.1g", 5.0, -2, 5);
+ {'EXIT',_} -> ok
+ end,
+
+ ["4.99999e-2",
+ "0.499999",
+ "4.99999",
+ "49.9999",
+ "499.999",
+ "4999.99",
+ "4.99999e+4",
+ "4.99999e+5"] = float_g_1("~g", 4.9999949999, -2, 5),
+
+ ["-5.00000e-2",
+ "-0.500000",
+ "-5.00000",
+ "-50.0000",
+ "-500.000",
+ "-5000.00",
+ "-5.00000e+4",
+ "-5.00000e+5"] = float_g_1("~g", -4.9999950001, -2, 5),
ok.
float_g_1(Fmt, V, Min, Max) ->
[fmt(Fmt, [V*math:pow(10, E)]) || E <- lists:seq(Min, Max)].
-otp_5403(doc) ->
- ["OTP-5403. ~s formats I/O lists and a single binary."];
-otp_5403(suite) ->
- [];
+%% OTP-5403. ~s formats I/O lists and a single binary.
otp_5403(Config) when is_list(Config) ->
- ?line "atom" = fmt("~s", [atom]),
- ?line "binary" = fmt("~s", [<<"binary">>]),
- ?line "atail" = fmt("~s", [["a" | <<"tail">>]]),
- ?line "deepcharlist" = fmt("~s", [["deep",["char",["list"]]]]),
- ?line "somebinaries" = fmt("~s", [[<<"some">>,[<<"binaries">>]]]),
+ "atom" = fmt("~s", [atom]),
+ "binary" = fmt("~s", [<<"binary">>]),
+ "atail" = fmt("~s", [["a" | <<"tail">>]]),
+ "deepcharlist" = fmt("~s", [["deep",["char",["list"]]]]),
+ "somebinaries" = fmt("~s", [[<<"some">>,[<<"binaries">>]]]),
ok.
-otp_5813(doc) ->
- ["OTP-5813. read/3 is new."];
-otp_5813(suite) ->
- [];
+%% OTP-5813. read/3 is new.
otp_5813(Config) when is_list(Config) ->
- ?line PrivDir = ?privdir(Config),
- ?line File = filename:join(PrivDir, "test"),
+ PrivDir = ?privdir(Config),
+ File = filename:join(PrivDir, "test"),
- ?line ok = file:write_file(File, <<"a. ">>),
- ?line {ok, Fd} = file:open(File, [read]),
- ?line {ok, a, 1} = io:read(Fd, '', 1),
- ?line {eof,1} = io:read(Fd, '', 1),
+ ok = file:write_file(File, <<"a. ">>),
+ {ok, Fd} = file:open(File, [read]),
+ {ok, a, 1} = io:read(Fd, '', 1),
+ {eof,1} = io:read(Fd, '', 1),
ok = file:close(Fd),
- ?line ok = file:write_file(File, <<"[}.">>),
- ?line {ok, Fd2} = file:open(File, [read]),
- ?line {error,{1,_,_},1} = io:read(Fd2, '', 1),
- ?line ok = file:close(Fd),
+ ok = file:write_file(File, <<"[}.">>),
+ {ok, Fd2} = file:open(File, [read]),
+ {error,{1,_,_},1} = io:read(Fd2, '', 1),
+ ok = file:close(Fd),
file:delete(File),
ok.
-otp_6230(doc) ->
- ["OTP-6230. ~p and ~P with (huge) binaries."];
-otp_6230(suite) ->
- [];
+%% OTP-6230. ~p and ~P with (huge) binaries.
otp_6230(Config) when is_list(Config) ->
%% The problem is actually huge binaries, but the small tests here
%% just run through most of the modified code.
- ?line "<<>>" = fmt("~P", [<<"">>,-1]),
- ?line "<<\"hej\">>" = fmt("~P", [<<"hej">>,-1]),
- ?line "{hej,...}" = fmt("~P", [{hej,<<"hej">>},2]),
- ?line "{hej,<<...>>}" = fmt("~P", [{hej,<<"hej">>},3]),
- ?line "{hej,<<\"hejs\"...>>}" = fmt("~P", [{hej,<<"hejsan">>},4]),
- ?line "{hej,<<\"hej\">>}" = fmt("~P", [{hej,<<"hej">>},6]),
- ?line "<<...>>" = fmt("~P", [<<"hej">>,1]),
- ?line "<<\"hejs\"...>>" = fmt("~P", [<<"hejsan">>,2]),
- ?line "<<\"hej\">>" = fmt("~P", [<<"hej">>,4]),
- ?line "{hej,<<127,...>>}" =
+ "<<>>" = fmt("~P", [<<"">>,-1]),
+ "<<\"hej\">>" = fmt("~P", [<<"hej">>,-1]),
+ "{hej,...}" = fmt("~P", [{hej,<<"hej">>},2]),
+ "{hej,<<...>>}" = fmt("~P", [{hej,<<"hej">>},3]),
+ "{hej,<<\"hejs\"...>>}" = fmt("~P", [{hej,<<"hejsan">>},4]),
+ "{hej,<<\"hej\">>}" = fmt("~P", [{hej,<<"hej">>},6]),
+ "<<...>>" = fmt("~P", [<<"hej">>,1]),
+ "<<\"hejs\"...>>" = fmt("~P", [<<"hejsan">>,2]),
+ "<<\"hej\">>" = fmt("~P", [<<"hej">>,4]),
+ "{hej,<<127,...>>}" =
fmt("~P", [{hej,<<127:8,<<"hej">>/binary>>},4]),
- ?line "{hej,<<127,104,101,...>>}" =
+ "{hej,<<127,104,101,...>>}" =
fmt("~P", [{hej,<<127:8,<<"hej">>/binary>>},6]),
B = list_to_binary(lists:duplicate(30000, $a)),
- ?line "<<\"aaaa"++_ = fmt("~P", [B, 20000]),
+ "<<\"aaaa"++_ = fmt("~P", [B, 20000]),
ok.
-otp_6282(doc) ->
- ["OTP-6282. ~p truncates strings (like binaries) depending on depth."];
-otp_6282(suite) ->
- [];
+%% OTP-6282. ~p truncates strings (like binaries) depending on depth.
otp_6282(Config) when is_list(Config) ->
- ?line "[]" = p("", 1, 20, 1),
- ?line "[]" = p("", 1, 20, -1),
- ?line "[...]" = p("a", 1, 20, 1),
- ?line "\"a\"" = p("a", 1, 20, 2),
- ?line "\"aa\"" = p("aa", 1, 20, 2),
- ?line "\"aaa\"" = p("aaa", 1, 20, 2),
- ?line "\"aaaa\"" = p("aaaa", 1, 20, 2),
- % ?line "\"aaaa\"..." = p("aaaaaa", 1, 20, 2),
- ?line "\"a\"" = p("a", 1, 20, -1),
- % ?line "\"aa\"..." = p([$a,$a,1000], 1, 20, 2),
- % ?line "\"aa\"..." = p([$a,$a,1000], 1, 20, 3),
- ?line "[97,97,1000]" = p([$a,$a,1000], 1, 20, 4),
+ "[]" = p("", 1, 20, 1),
+ "[]" = p("", 1, 20, -1),
+ "[...]" = p("a", 1, 20, 1),
+ "\"a\"" = p("a", 1, 20, 2),
+ "\"aa\"" = p("aa", 1, 20, 2),
+ "\"aaa\"" = p("aaa", 1, 20, 2),
+ "\"aaaa\"" = p("aaaa", 1, 20, 2),
+ "\"a\"" = p("a", 1, 20, -1),
+ "[97,97,1000]" = p([$a,$a,1000], 1, 20, 4),
S1 = lists:duplicate(200,$a),
- ?line "[...]" = p(S1, 1, 20, 1),
- % ?line "\"aaaaaaaaaaaaaaaa\"\n \"aaaaaaaaaaaaaaaa\"\n \"aaaa\"..." =
- % ?line "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"..." =
- % p(S1, 1, 20, 10),
- ?line true = "\"" ++ S1 ++ "\"" =:= p(S1, 1, 205, -1),
- ?line "[97,97,1000|...]" = p([$a,$a,1000,1000], 1, 20, 4),
-
- ?line "[[]]" = p([""], 1, 20, 2),
- ?line "[[]]" = p([""], 1, 20, -1),
- ?line "[[...]]" = p(["a"], 1, 20, 2),
- ?line "[\"a\"]" = p(["a"], 1, 20, 3),
- ?line "[\"aa\"]" = p(["aa"], 1, 20, 3),
- ?line "[\"aaa\"]" = p(["aaa"], 1, 20, 3),
- ?line "[\"a\"]" = p(["a"], 1, 20, -1),
- % ?line "[\"aa\"...]" = p([[$a,$a,1000]], 1, 20, 3),
- % ?line "[\"aa\"...]" = p([[$a,$a,1000]], 1, 20, 4),
- ?line "[[97,97,1000]]" = p([[$a,$a,1000]], 1, 20, 5),
- ?line "[[...]]" = p([S1], 1, 20, 2),
- % ?line "[\"aaaaaaaaaaaaaa\"\n \"aaaaaaaaaaaaaa\"\n \"aaaaaaaa\"...]" =
- % ?line "[\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"...]" =
- % p([S1], 1, 20, 11),
- ?line true = "[\"" ++ S1 ++ "\"]" =:= p([S1], 1, 210, -1),
- ?line "[[97,97,1000|...]]" = p([[$a,$a,1000,1000]], 1, 20, 5),
-
- % ?line "[\"aaaa\"...]" = p(["aaaaa"], 1, 10, 3),
- ?line "[\"aaaaa\"]" = p(["aaaaa"], 1, 10, 6),
+ "[...]" = p(S1, 1, 20, 1),
+ true = "\"" ++ S1 ++ "\"" =:= p(S1, 1, 205, -1),
+ "[97,97,1000|...]" = p([$a,$a,1000,1000], 1, 20, 4),
+
+ "[[]]" = p([""], 1, 20, 2),
+ "[[]]" = p([""], 1, 20, -1),
+ "[[...]]" = p(["a"], 1, 20, 2),
+ "[\"a\"]" = p(["a"], 1, 20, 3),
+ "[\"aa\"]" = p(["aa"], 1, 20, 3),
+ "[\"aaa\"]" = p(["aaa"], 1, 20, 3),
+ "[\"a\"]" = p(["a"], 1, 20, -1),
+ "[[97,97,1000]]" = p([[$a,$a,1000]], 1, 20, 5),
+ "[[...]]" = p([S1], 1, 20, 2),
+ true = "[\"" ++ S1 ++ "\"]" =:= p([S1], 1, 210, -1),
+ "[[97,97,1000|...]]" = p([[$a,$a,1000,1000]], 1, 20, 5),
+
+ "[\"aaaaa\"]" = p(["aaaaa"], 1, 10, 6),
ok.
-otp_6354(doc) ->
- ["OTP-6354. io_lib_pretty rewritten."];
-otp_6354(suite) ->
- [];
+%% OTP-6354. io_lib_pretty rewritten.
otp_6354(Config) when is_list(Config) ->
%% A few tuples:
- ?line "{}" = p({}, 1, 20, -1),
- ?line "..." = p({}, 1, 20, 0),
- ?line "{}" = p({}, 1, 20, 1),
- ?line "{}" = p({}, 1, 20, 2),
- ?line "{a}" = p({a}, 1, 20, -1),
- ?line "..." = p({a}, 1, 20, 0),
- ?line "{...}" = p({a}, 1, 20, 1),
- ?line "{a}" = p({a}, 1, 20, 2),
- ?line "{a,b}" = p({a,b}, 1, 20, -1),
- ?line "..." = p({a,b}, 1, 20, 0),
- ?line "{...}" = p({a,b}, 1, 20, 1),
- ?line "{a,...}" = p({a,b}, 1, 20, 2),
- ?line "{a,b}" = p({a,b}, 1, 20, 3),
- ?line "{}" = p({}, 1, 1, -1),
- ?line "..." = p({}, 1, 1, 0),
- ?line "{}" = p({}, 1, 1, 1),
- ?line "{}" = p({}, 1, 1, 2),
- ?line "{a}" = p({a}, 1, 1, -1),
- ?line "..." = p({a}, 1, 1, 0),
- ?line "{...}" = p({a}, 1, 1, 1),
- ?line "{a}" = p({a}, 1, 1, 2),
- ?line "{a,\n b}" = p({a,b}, 1, 1, -1),
- ?line "{1,\n b}" = p({1,b}, 1, 1, -1),
- ?line "..." = p({a,b}, 1, 1, 0),
- ?line "{...}" = p({a,b}, 1, 1, 1),
- ?line "{a,...}" = p({a,b}, 1, 1, 2),
- ?line "{a,\n b}" = p({a,b}, 1, 1, 3),
- ?line "{{}}" = p({{}}, 1, 1, 2),
- ?line "{[]}" = p({[]}, 1, 1, 2),
- ?line bt(<<"{1,2,a,b,{sfdsf,sdfdsfs},[sfsdf,sdfsdf]}">>,
- p({1,2,a,b,{sfdsf,sdfdsfs},[sfsdf,sdfsdf]}, -1)),
- ?line bt(<<"{abcd,ddddd,\n ddddd}">>,
- p({abcd,ddddd,ddddd}, 1,16, -1)),
- ?line bt(<<"{1,2,a,b,\n {sfdsf,sdfdsfs},\n [sfsdf,sdfsdf]}">>,
- p({1,2,a,b,{sfdsf,sdfdsfs},[sfsdf,sdfsdf]}, 1, 35, 100)),
- % With other terms than atomic ones on the same line:
-% ?line bt(<<"{1,2,a,b,{sfdsf,sdfdsfs},\n [sfsdf,sdfsdf]}">>,
-% p({1,2,a,b,{sfdsf,sdfdsfs},[sfsdf,sdfsdf]}, 1, 35, 100)),
- % With line breaks:
-% ?line bt(<<"{1,\n"
-% " 2,\n"
-% " a,\n"
-% " b,\n"
-% " {sfdsf,sdfdsfs},\n"
-% " [sfsdf,sdfsdf]}">>,
-% p({1,2,a,b,{sfdsf,sdfdsfs},[sfsdf,sdfsdf]}, 1, 35, 100)),
- ?line "{1,{1,{2,3}}}" = p({1,{1,{2,3}}}, 1, 80, 100),
-
- ?line bt(<<"{wwwww,{wwwww,{wwwww,{wwwww,{wwwww,lkjsldfj,klsdjfjklds,\n"
- " sdkfjdsl,sdakfjdsklj,sdkljfsdj}}}}}">>,
- p({wwwww,{wwwww,{wwwww,{wwwww,{wwwww,lkjsldfj,klsdjfjklds,
- sdkfjdsl,sdakfjdsklj,sdkljfsdj}}}}}, -1)),
-
- % With no restriction on number of characters per line:
-% ?line bt(<<"{wwwww,{wwwww,{wwwww,{wwwww,{wwwww,lkjsldfj,klsdjfjklds,"
-% "sdkfjdsl,sdakfjdsklj,\n"
-% " sdkljfsdj}}}}}">>,
-% p({wwwww,{wwwww,{wwwww,{wwwww,{wwwww,lkjsldfj,klsdjfjklds,
-% sdkfjdsl,sdakfjdsklj,sdkljfsdj}}}}}, -1)),
-
- % With line breaks:
-% ?line bt(<<"{wwwww,{wwwww,{wwwww,{wwwww,{wwwww,lkjsldfj,\n"
-% " klsdjfjklds,\n"
-% " sdkfjdsl,\n"
-% " sdakfjdsklj,\n"
-% " sdkljfsdj}}}}}">>,
-% p({wwwww,{wwwww,{wwwww,{wwwww,{wwwww,lkjsldfj,klsdjfjklds,
-% sdkfjdsl,sdakfjdsklj,sdkljfsdj}}}}}, -1)),
- ?line bt(<<"{wwwww,\n"
- " {wwwww,\n"
- " {wwwww,\n"
- " {wwwww,\n"
- " {wwwww,\n"
- " {lkjsldfj,\n"
- " {klsdjfjklds,\n"
- " {klajsljls,\n"
- " #aaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa{}}}}}}}}}">>,
- p({wwwww,{wwwww,{wwwww,{wwwww,{wwwww,{lkjsldfj,
- {klsdjfjklds,{klajsljls,
- {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}}}}}}}}},
- -1)),
- ?line "{{...},...}" = p({{a,b},{a,b,c},{d,e,f}},1,8,2),
+ "{}" = p({}, 1, 20, -1),
+ "..." = p({}, 1, 20, 0),
+ "{}" = p({}, 1, 20, 1),
+ "{}" = p({}, 1, 20, 2),
+ "{a}" = p({a}, 1, 20, -1),
+ "..." = p({a}, 1, 20, 0),
+ "{...}" = p({a}, 1, 20, 1),
+ "{a}" = p({a}, 1, 20, 2),
+ "{a,b}" = p({a,b}, 1, 20, -1),
+ "..." = p({a,b}, 1, 20, 0),
+ "{...}" = p({a,b}, 1, 20, 1),
+ "{a,...}" = p({a,b}, 1, 20, 2),
+ "{a,b}" = p({a,b}, 1, 20, 3),
+ "{}" = p({}, 1, 1, -1),
+ "..." = p({}, 1, 1, 0),
+ "{}" = p({}, 1, 1, 1),
+ "{}" = p({}, 1, 1, 2),
+ "{a}" = p({a}, 1, 1, -1),
+ "..." = p({a}, 1, 1, 0),
+ "{...}" = p({a}, 1, 1, 1),
+ "{a}" = p({a}, 1, 1, 2),
+ "{a,\n b}" = p({a,b}, 1, 1, -1),
+ "{1,\n b}" = p({1,b}, 1, 1, -1),
+ "..." = p({a,b}, 1, 1, 0),
+ "{...}" = p({a,b}, 1, 1, 1),
+ "{a,...}" = p({a,b}, 1, 1, 2),
+ "{a,\n b}" = p({a,b}, 1, 1, 3),
+ "{{}}" = p({{}}, 1, 1, 2),
+ "{[]}" = p({[]}, 1, 1, 2),
+ bt(<<"{1,2,a,b,{sfdsf,sdfdsfs},[sfsdf,sdfsdf]}">>,
+ p({1,2,a,b,{sfdsf,sdfdsfs},[sfsdf,sdfsdf]}, -1)),
+ bt(<<"{abcd,ddddd,\n ddddd}">>,
+ p({abcd,ddddd,ddddd}, 1,16, -1)),
+ bt(<<"{1,2,a,b,\n {sfdsf,sdfdsfs},\n [sfsdf,sdfsdf]}">>,
+ p({1,2,a,b,{sfdsf,sdfdsfs},[sfsdf,sdfsdf]}, 1, 35, 100)),
+ "{1,{1,{2,3}}}" = p({1,{1,{2,3}}}, 1, 80, 100),
+
+ bt(<<"{wwwww,{wwwww,{wwwww,{wwwww,{wwwww,lkjsldfj,klsdjfjklds,\n"
+ " sdkfjdsl,sdakfjdsklj,sdkljfsdj}}}}}">>,
+ p({wwwww,{wwwww,{wwwww,{wwwww,{wwwww,lkjsldfj,klsdjfjklds,
+ sdkfjdsl,sdakfjdsklj,sdkljfsdj}}}}}, -1)),
+
+ bt(<<"{wwwww,\n"
+ " {wwwww,\n"
+ " {wwwww,\n"
+ " {wwwww,\n"
+ " {wwwww,\n"
+ " {lkjsldfj,\n"
+ " {klsdjfjklds,\n"
+ " {klajsljls,\n"
+ " #aaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa{}}}}}}}}}">>,
+ p({wwwww,{wwwww,{wwwww,{wwwww,{wwwww,{lkjsldfj,
+ {klsdjfjklds,{klajsljls,
+ {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}}}}}}}}},
+ -1)),
+ "{{...},...}" = p({{a,b},{a,b,c},{d,e,f}},1,8,2),
%% Closing brackets and parentheses count:
- ?line "{{a,b,c},\n {{1,2,\n 3}}}" = p({{a,b,c},{{1,2,3}}},1,11,-1),
- % With line breaks:
-% ?line "{{a,b,c},\n {{1,\n 2,\n 3}}}" = p({{a,b,c},{{1,2,3}}},1,11,-1),
- ?line "{{a,b,c},\n [1,2,\n 3]}" = p({{a,b,c},[1,2,3]},1,10,-1),
- % With line breaks:
-% ?line "{{a,b,c},\n [1,\n 2,\n 3]}" = p({{a,b,c},[1,2,3]},1,10,-1),
- ?line "[{{a,b,c},\n {1,2,\n 3}}]" = p([{{a,b,c},{1,2,3}}],1,12,-1),
- % With line breaks:
-% ?line "[{{a,b,c},\n {1,\n 2,\n 3}}]" = p([{{a,b,c},{1,2,3}}],1,12,-1),
+ "{{a,b,c},\n {{1,2,\n 3}}}" = p({{a,b,c},{{1,2,3}}},1,11,-1),
+ %% With line breaks:
+ "{{a,b,c},\n [1,2,\n 3]}" = p({{a,b,c},[1,2,3]},1,10,-1),
+ %% With line breaks:
+ "[{{a,b,c},\n {1,2,\n 3}}]" = p([{{a,b,c},{1,2,3}}],1,12,-1),
%% A few lists:
- ?line "[]" = p([], 1, 20, -1),
- ?line "..." = p([], 1, 20, 0),
- ?line "[]" = p([], 1, 20, 1),
- ?line "[]" = p([], 1, 20, 2),
- ?line "[a]" = p([a], 1, 20, -1),
- ?line "..." = p([a], 1, 20, 0),
- ?line "[...]" = p([a], 1, 20, 1),
- ?line "[a]" = p([a], 1, 20, 2),
- ?line "[a,b]" = p([a,b], 1, 20, -1),
- ?line "..." = p([a,b], 1, 20, 0),
- ?line "[...]" = p([a,b], 1, 20, 1),
- ?line "[a|...]" = p([a,b], 1, 20, 2),
- ?line "[a,b]" = p([a,b], 1, 20, 3),
- ?line "[a|b]" = p([a|b], 1, 20, -1),
- ?line "..." = p([a|b], 1, 20, 0),
- ?line "[...]" = p([a|b], 1, 20, 1),
- ?line "[a|...]" = p([a|b], 1, 20, 2),
- ?line "[a|b]" = p([a|b], 1, 20, 3),
- ?line "[]" = p([], 1, 1, -1),
- ?line "..." = p([], 1, 1, 0),
- ?line "[]" = p([], 1, 1, 1),
- ?line "[]" = p([], 1, 1, 2),
- ?line "[a]" = p([a], 1, 1, -1),
- ?line "..." = p([a], 1, 1, 0),
- ?line "[...]" = p([a], 1, 1, 1),
- ?line "[a]" = p([a], 1, 1, 2),
- ?line "[a,\n b]" = p([a,b], 1, 1, -1),
- ?line "..." = p([a,b], 1, 1, 0),
- ?line "[...]" = p([a,b], 1, 1, 1),
- ?line "[a|...]" = p([a,b], 1, 1, 2),
- ?line "[a,\n b]" = p([a,b], 1, 1, 3),
- ?line "[a|\n b]" = p([a|b], 1, 1, -1),
- ?line "..." = p([a|b], 1, 1, 0),
- ?line "[...]" = p([a|b], 1, 1, 1),
- ?line "[a|...]" = p([a|b], 1, 1, 2),
- ?line "[a|\n b]" = p([a|b], 1, 1, 3),
- ?line "[{}]" = p([{}], 1, 1, 2),
- ?line "[[]]" = p([[]], 1, 1, 2),
- ?line bt(<<"[1,2,a,b,{sfdsf,sdfdsfs},[sfsdf,sdfsdf]]">>,
- p([1,2,a,b,{sfdsf,sdfdsfs},[sfsdf,sdfsdf]], -1)),
- ?line bt(<<"[1,2,a,b,\n {sfdsf,sdfdsfs},\n [sfsdf,sdfsdf]]">>,
- p([1,2,a,b,{sfdsf,sdfdsfs},[sfsdf,sdfsdf]], 1, 35, 100)),
- % With other terms than atomic ones on the same line:
-% ?line bt(<<"[1,2,a,b,{sfdsf,sdfdsfs},\n [sfsdf,sdfsdf]]">>,
-% p([1,2,a,b,{sfdsf,sdfdsfs},[sfsdf,sdfsdf]], 1, 35, 100)),
- % With line breaks:
-% ?line bt(<<"[1,\n"
-% " 2,\n"
-% " a,\n"
-% " b,\n"
-% " {sfdsf,sdfdsfs},\n"
-% " [sfsdf,sdfsdf]]">>,
-% p([1,2,a,b,{sfdsf,sdfdsfs},[sfsdf,sdfsdf]], 1, 35, 100)),
+ "[]" = p([], 1, 20, -1),
+ "..." = p([], 1, 20, 0),
+ "[]" = p([], 1, 20, 1),
+ "[]" = p([], 1, 20, 2),
+ "[a]" = p([a], 1, 20, -1),
+ "..." = p([a], 1, 20, 0),
+ "[...]" = p([a], 1, 20, 1),
+ "[a]" = p([a], 1, 20, 2),
+ "[a,b]" = p([a,b], 1, 20, -1),
+ "..." = p([a,b], 1, 20, 0),
+ "[...]" = p([a,b], 1, 20, 1),
+ "[a|...]" = p([a,b], 1, 20, 2),
+ "[a,b]" = p([a,b], 1, 20, 3),
+ "[a|b]" = p([a|b], 1, 20, -1),
+ "..." = p([a|b], 1, 20, 0),
+ "[...]" = p([a|b], 1, 20, 1),
+ "[a|...]" = p([a|b], 1, 20, 2),
+ "[a|b]" = p([a|b], 1, 20, 3),
+ "[]" = p([], 1, 1, -1),
+ "..." = p([], 1, 1, 0),
+ "[]" = p([], 1, 1, 1),
+ "[]" = p([], 1, 1, 2),
+ "[a]" = p([a], 1, 1, -1),
+ "..." = p([a], 1, 1, 0),
+ "[...]" = p([a], 1, 1, 1),
+ "[a]" = p([a], 1, 1, 2),
+ "[a,\n b]" = p([a,b], 1, 1, -1),
+ "..." = p([a,b], 1, 1, 0),
+ "[...]" = p([a,b], 1, 1, 1),
+ "[a|...]" = p([a,b], 1, 1, 2),
+ "[a,\n b]" = p([a,b], 1, 1, 3),
+ "[a|\n b]" = p([a|b], 1, 1, -1),
+ "..." = p([a|b], 1, 1, 0),
+ "[...]" = p([a|b], 1, 1, 1),
+ "[a|...]" = p([a|b], 1, 1, 2),
+ "[a|\n b]" = p([a|b], 1, 1, 3),
+ "[{}]" = p([{}], 1, 1, 2),
+ "[[]]" = p([[]], 1, 1, 2),
+ bt(<<"[1,2,a,b,{sfdsf,sdfdsfs},[sfsdf,sdfsdf]]">>,
+ p([1,2,a,b,{sfdsf,sdfdsfs},[sfsdf,sdfsdf]], -1)),
+ bt(<<"[1,2,a,b,\n {sfdsf,sdfdsfs},\n [sfsdf,sdfsdf]]">>,
+ p([1,2,a,b,{sfdsf,sdfdsfs},[sfsdf,sdfsdf]], 1, 35, 100)),
%% Element #8 is not printable:
- ?line "[49," ++ _ = p("1234567"++[3,4,5,6,7], 1, 100, 9),
- % ?line "\"1234567\"..." = p("1234567"++[3,4,5,6,7], 1, 100, 8),
+ "[49," ++ _ = p("1234567"++[3,4,5,6,7], 1, 100, 9),
+ %% "\"1234567\"..." = p("1234567"++[3,4,5,6,7], 1, 100, 8),
%% A few records:
%% -record(a, {}).
%% -record(a, {}).
- ?line "..." = p({a}, 0),
- ?line "{...}" = p({a}, 1),
- ?line "#a{}" = p({a}, 2),
- ?line "#a{}" = p({a}, -1),
+ "..." = p({a}, 0),
+ "{...}" = p({a}, 1),
+ "#a{}" = p({a}, 2),
+ "#a{}" = p({a}, -1),
%% -record(b, {f}).
- ?line "{...}" = p({b}, 1),
- ?line "..." = p({b,c}, 0),
- ?line "{...}" = p({b,c}, 1),
- ?line "#b{...}" = p({b,c}, 2),
- ?line "#b{f = c}" = p({b,c}, 3),
- ?line "#b{f = c}" = p({b,c}, -1),
- ?line "..." = p({b,{c,d}}, 0),
- ?line "{...}" = p({b,{c,d}}, 1),
- ?line "#b{...}" = p({b,{c,d}}, 2),
- ?line "#b{f = {...}}" = p({b,{c,d}}, 3),
- ?line "#b{f = {c,...}}" = p({b,{c,d}}, 4),
- ?line "#b{f = {c,d}}" = p({b,{c,d}}, 5),
- ?line "#b{f = {...}}" = p({b,{b,c}}, 3),
- ?line "#b{f = #b{...}}" = p({b,{b,c}}, 4),
- ?line "#b{f = #b{f = c}}" = p({b,{b,c}}, 5),
+ "{...}" = p({b}, 1),
+ "..." = p({b,c}, 0),
+ "{...}" = p({b,c}, 1),
+ "#b{...}" = p({b,c}, 2),
+ "#b{f = c}" = p({b,c}, 3),
+ "#b{f = c}" = p({b,c}, -1),
+ "..." = p({b,{c,d}}, 0),
+ "{...}" = p({b,{c,d}}, 1),
+ "#b{...}" = p({b,{c,d}}, 2),
+ "#b{f = {...}}" = p({b,{c,d}}, 3),
+ "#b{f = {c,...}}" = p({b,{c,d}}, 4),
+ "#b{f = {c,d}}" = p({b,{c,d}}, 5),
+ "#b{f = {...}}" = p({b,{b,c}}, 3),
+ "#b{f = #b{...}}" = p({b,{b,c}}, 4),
+ "#b{f = #b{f = c}}" = p({b,{b,c}}, 5),
%% -record(c, {f1, f2}).
- ?line "#c{f1 = d,f2 = e}" = p({c,d,e}, -1),
- ?line "..." = p({c,d,e}, 0),
- ?line "{...}" = p({c,d,e}, 1),
- ?line "#c{...}" = p({c,d,e}, 2),
- ?line "#c{f1 = d,...}" = p({c,d,e}, 3),
- ?line "#c{f1 = d,f2 = e}" = p({c,d,e}, 4),
+ "#c{f1 = d,f2 = e}" = p({c,d,e}, -1),
+ "..." = p({c,d,e}, 0),
+ "{...}" = p({c,d,e}, 1),
+ "#c{...}" = p({c,d,e}, 2),
+ "#c{f1 = d,...}" = p({c,d,e}, 3),
+ "#c{f1 = d,f2 = e}" = p({c,d,e}, 4),
%% -record(d, {a..., b..., c.., d...}).
- ?line bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,bbbbbbbbbbbbbbbbbbbb = 2,\n"
- " cccccccccccccccccccc = 3,dddddddddddddddddddd = 4,\n"
- " eeeeeeeeeeeeeeeeeeee = 5}">>,
- p({d,1,2,3,4,5}, -1)),
- % With no restriction on number of characters per line:
-% ?line bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,bbbbbbbbbbbbbbbbbbbb = 2,"
-% "cccccccccccccccccccc = 3,\n dddddddddddddddddddd = 4,"
-% "eeeeeeeeeeeeeeeeeeee = 5}">>,
-% p({d,1,2,3,4,5}, -1)),
- % With line breaks:
-% ?line bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,\n"
-% " bbbbbbbbbbbbbbbbbbbb = 2,\n"
-% " cccccccccccccccccccc = 3,\n"
-% " dddddddddddddddddddd = 4,\n"
-% " eeeeeeeeeeeeeeeeeeee = 5}">>,
-% p({d,1,2,3,4,5}, -1)),
- ?line "..." = p({d,1,2,3,4,5}, 0),
- ?line "{...}" = p({d,1,2,3,4,5}, 1),
- ?line "#d{...}" = p({d,1,2,3,4,5}, 2),
- ?line "#d{aaaaaaaaaaaaaaaaaaaa = 1,...}" = p({d,1,2,3,4,5}, 3),
- ?line bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,bbbbbbbbbbbbbbbbbbbb = 2,...}">>,
- p({d,1,2,3,4,5}, 4)),
- ?line bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,bbbbbbbbbbbbbbbbbbbb = 2,\n"
- " cccccccccccccccccccc = 3,...}">>,
- p({d,1,2,3,4,5}, 5)), % longer than 80 characters...
- % With no restriction on number of characters per line:
-% ?line bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,bbbbbbbbbbbbbbbbbbbb = 2,"
-% "cccccccccccccccccccc = 3,...}">>,
-% p({d,1,2,3,4,5}, 5)), % longer than 80 characters...
- % With line breaks:
-% ?line bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,\n"
-% " bbbbbbbbbbbbbbbbbbbb = 2,\n"
-% " cccccccccccccccccccc = 3,...}">>,
-% p({d,1,2,3,4,5}, 5)),
- ?line bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,bbbbbbbbbbbbbbbbbbbb = 2,\n"
- " cccccccccccccccccccc = 3,dddddddddddddddddddd = 4,...}">>,
- p({d,1,2,3,4,5}, 6)),
- % With no restriction on number of characters per line:
-% ?line bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,bbbbbbbbbbbbbbbbbbbb = 2,"
-% "cccccccccccccccccccc = 3,\n dddddddddddddddddddd = 4,...}">>,
-% p({d,1,2,3,4,5}, 6)),
- % With line breaks:
-% ?line bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,\n"
-% " bbbbbbbbbbbbbbbbbbbb = 2,\n"
-% " cccccccccccccccccccc = 3,\n"
-% " dddddddddddddddddddd = 4,...}">>,
-% p({d,1,2,3,4,5}, 6)),
- ?line bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,bbbbbbbbbbbbbbbbbbbb = 2,\n"
- " cccccccccccccccccccc = 3,dddddddddddddddddddd = 4,\n"
- " eeeeeeeeeeeeeeeeeeee = 5}">>,
- p({d,1,2,3,4,5}, 7)),
- % With no restriction on number of characters per line:
-% ?line bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,bbbbbbbbbbbbbbbbbbbb = 2,"
-% "cccccccccccccccccccc = 3,\n dddddddddddddddddddd = 4,"
-% "eeeeeeeeeeeeeeeeeeee = 5}">>,
-% p({d,1,2,3,4,5}, 7)),
- % With line breaks:
-% ?line bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,\n"
-% " bbbbbbbbbbbbbbbbbbbb = 2,\n"
-% " cccccccccccccccccccc = 3,\n"
-% " dddddddddddddddddddd = 4,\n"
-% " eeeeeeeeeeeeeeeeeeee = 5}">>,
-% p({d,1,2,3,4,5}, 7)),
- ?line bt(<<"#rrrrr{\n"
- " f1 = 1,\n"
- " f2 = #rrrrr{f1 = a,f2 = b,f3 = c},\n"
- " f3 = \n"
- " #rrrrr{\n"
- " f1 = h,f2 = i,\n"
- " f3 = \n"
- " #rrrrr{\n"
- " f1 = aa,\n"
- " f2 = \n"
- " #rrrrr{\n"
- " f1 = #rrrrr{f1 = a,f2 = b,f3 = c},\n"
- " f2 = 2,f3 = 3},\n"
- " f3 = bb}}}">>,
- p({rrrrr,1,{rrrrr,a,b,c},{rrrrr,h,i,
- {rrrrr,aa,{rrrrr,{rrrrr,a,b,c},
- 2,3},bb}}},
- -1)),
- % With other terms than atomic ones on the same line:
-% ?line bt(<<"#rrrrr{\n"
-% " f1 = 1,f2 = #rrrrr{f1 = a,f2 = b,f3 = c},\n"
-% " f3 = \n"
-% " #rrrrr{\n"
-% " f1 = h,f2 = i,\n"
-% " f3 = \n"
-% " #rrrrr{\n"
-% " f1 = aa,\n"
-% " f2 = \n"
-% " #rrrrr{\n"
-% " f1 = #rrrrr{f1 = a,f2 = b,"
-% "f3 = c},f2 = 2,f3 = 3},\n"
-% " f3 = bb}}}">>,
-% p({rrrrr,1,{rrrrr,a,b,c},{rrrrr,h,i,
-% {rrrrr,aa,{rrrrr,{rrrrr,a,b,c},
-% 2,3},bb}}},
-% -1)),
- % With line breaks:
-% ?line bt(<<"#rrrrr{\n"
-% " f1 = 1,\n"
-% " f2 = #rrrrr{f1 = a,f2 = b,f3 = c},\n"
-% " f3 = \n"
-% " #rrrrr{\n"
-% " f1 = h,\n"
-% " f2 = i,\n"
-% " f3 = \n"
-% " #rrrrr{\n"
-% " f1 = aa,\n"
-% " f2 = \n"
-% " #rrrrr{\n"
-% " f1 = #rrrrr{f1 = a,f2 = b,"
-% "f3 = c},\n"
-% " f2 = 2,\n"
-% " f3 = 3},\n"
-% " f3 = bb}}}">>,
-% p({rrrrr,1,{rrrrr,a,b,c},{rrrrr,h,i,
-% {rrrrr,aa,{rrrrr,{rrrrr,a,b,c},
-% 2,3},bb}}},
-% -1)),
- ?line bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,\n"
- " bbbbbbbbbbbbbbbbbbbb = \n"
- " #d{aaaaaaaaaaaaaaaaaaaa = a,bbbbbbbbbbbbbbbbbbbb = b,\n"
- " cccccccccccccccccccc = c,dddddddddddddddddddd = d,\n"
- " eeeeeeeeeeeeeeeeeeee = e},\n"
- " cccccccccccccccccccc = 3,\n"
- " dddddddddddddddddddd = \n"
- " #d{aaaaaaaaaaaaaaaaaaaa = h,bbbbbbbbbbbbbbbbbbbb = i,\n"
- " cccccccccccccccccccc = \n"
- " #d{aaaaaaaaaaaaaaaaaaaa = aa,"
- "bbbbbbbbbbbbbbbbbbbb = bb,\n"
- " cccccccccccccccccccc = \n"
- " #d{aaaaaaaaaaaaaaaaaaaa = 1,"
- "bbbbbbbbbbbbbbbbbbbb = 2,\n"
- " cccccccccccccccccccc = 3,"
- "dddddddddddddddddddd = 4,\n"
- " eeeeeeeeeeeeeeeeeeee = 5},\n"
- " dddddddddddddddddddd = dd,"
- "eeeeeeeeeeeeeeeeeeee = ee},\n"
- " dddddddddddddddddddd = k,"
- "eeeeeeeeeeeeeeeeeeee = l},\n"
- " eeeeeeeeeeeeeeeeeeee = 5}">>,
- p({d,1,{d,a,b,c,d,e},3,{d,h,i,{d,aa,bb,{d,1,2,3,4,5},dd,ee},
- k,l},5}, -1)),
- % With line breaks:
-% ?line bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,\n"
-% " bbbbbbbbbbbbbbbbbbbb = \n"
-% " #d{aaaaaaaaaaaaaaaaaaaa = a,\n"
-% " bbbbbbbbbbbbbbbbbbbb = b,\n"
-% " cccccccccccccccccccc = c,\n"
-% " dddddddddddddddddddd = d,\n"
-% " eeeeeeeeeeeeeeeeeeee = e},\n"
-% " cccccccccccccccccccc = 3,\n"
-% " dddddddddddddddddddd = \n"
-% " #d{aaaaaaaaaaaaaaaaaaaa = h,\n"
-% " bbbbbbbbbbbbbbbbbbbb = i,\n"
-% " cccccccccccccccccccc = \n"
-% " #d{aaaaaaaaaaaaaaaaaaaa = aa,\n"
-% " bbbbbbbbbbbbbbbbbbbb = bb,\n"
-% " cccccccccccccccccccc = \n"
-% " #d{aaaaaaaaaaaaaaaaaaaa = 1,\n"
-% " bbbbbbbbbbbbbbbbbbbb = 2,\n"
-% " cccccccccccccccccccc = 3,\n"
-% " dddddddddddddddddddd = 4,\n"
-% " eeeeeeeeeeeeeeeeeeee = 5},\n"
-% " dddddddddddddddddddd = dd,\n"
-% " eeeeeeeeeeeeeeeeeeee = ee},\n"
-% " dddddddddddddddddddd = k,\n"
-% " eeeeeeeeeeeeeeeeeeee = l},\n"
-% " eeeeeeeeeeeeeeeeeeee = 5}">>,
-% p({d,1,{d,a,b,c,d,e},3,{d,h,i,{d,aa,bb,{d,1,2,3,4,5},dd,ee},
-% k,l},5}, -1)),
+ bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,bbbbbbbbbbbbbbbbbbbb = 2,\n"
+ " cccccccccccccccccccc = 3,dddddddddddddddddddd = 4,\n"
+ " eeeeeeeeeeeeeeeeeeee = 5}">>,
+ p({d,1,2,3,4,5}, -1)),
+ "..." = p({d,1,2,3,4,5}, 0),
+ "{...}" = p({d,1,2,3,4,5}, 1),
+ "#d{...}" = p({d,1,2,3,4,5}, 2),
+ "#d{aaaaaaaaaaaaaaaaaaaa = 1,...}" = p({d,1,2,3,4,5}, 3),
+ bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,bbbbbbbbbbbbbbbbbbbb = 2,...}">>,
+ p({d,1,2,3,4,5}, 4)),
+ bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,bbbbbbbbbbbbbbbbbbbb = 2,\n"
+ " cccccccccccccccccccc = 3,...}">>,
+ p({d,1,2,3,4,5}, 5)), % longer than 80 characters...
+ bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,bbbbbbbbbbbbbbbbbbbb = 2,\n"
+ " cccccccccccccccccccc = 3,dddddddddddddddddddd = 4,...}">>,
+ p({d,1,2,3,4,5}, 6)),
+ bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,bbbbbbbbbbbbbbbbbbbb = 2,\n"
+ " cccccccccccccccccccc = 3,dddddddddddddddddddd = 4,\n"
+ " eeeeeeeeeeeeeeeeeeee = 5}">>,
+ p({d,1,2,3,4,5}, 7)),
+ bt(<<"#rrrrr{\n"
+ " f1 = 1,\n"
+ " f2 = #rrrrr{f1 = a,f2 = b,f3 = c},\n"
+ " f3 = \n"
+ " #rrrrr{\n"
+ " f1 = h,f2 = i,\n"
+ " f3 = \n"
+ " #rrrrr{\n"
+ " f1 = aa,\n"
+ " f2 = \n"
+ " #rrrrr{\n"
+ " f1 = #rrrrr{f1 = a,f2 = b,f3 = c},\n"
+ " f2 = 2,f3 = 3},\n"
+ " f3 = bb}}}">>,
+ p({rrrrr,1,{rrrrr,a,b,c},{rrrrr,h,i,
+ {rrrrr,aa,{rrrrr,{rrrrr,a,b,c},
+ 2,3},bb}}},
+ -1)),
+ bt(<<"#d{aaaaaaaaaaaaaaaaaaaa = 1,\n"
+ " bbbbbbbbbbbbbbbbbbbb = \n"
+ " #d{aaaaaaaaaaaaaaaaaaaa = a,bbbbbbbbbbbbbbbbbbbb = b,\n"
+ " cccccccccccccccccccc = c,dddddddddddddddddddd = d,\n"
+ " eeeeeeeeeeeeeeeeeeee = e},\n"
+ " cccccccccccccccccccc = 3,\n"
+ " dddddddddddddddddddd = \n"
+ " #d{aaaaaaaaaaaaaaaaaaaa = h,bbbbbbbbbbbbbbbbbbbb = i,\n"
+ " cccccccccccccccccccc = \n"
+ " #d{aaaaaaaaaaaaaaaaaaaa = aa,"
+ "bbbbbbbbbbbbbbbbbbbb = bb,\n"
+ " cccccccccccccccccccc = \n"
+ " #d{aaaaaaaaaaaaaaaaaaaa = 1,"
+ "bbbbbbbbbbbbbbbbbbbb = 2,\n"
+ " cccccccccccccccccccc = 3,"
+ "dddddddddddddddddddd = 4,\n"
+ " eeeeeeeeeeeeeeeeeeee = 5},\n"
+ " dddddddddddddddddddd = dd,"
+ "eeeeeeeeeeeeeeeeeeee = ee},\n"
+ " dddddddddddddddddddd = k,"
+ "eeeeeeeeeeeeeeeeeeee = l},\n"
+ " eeeeeeeeeeeeeeeeeeee = 5}">>,
+ p({d,1,{d,a,b,c,d,e},3,{d,h,i,{d,aa,bb,{d,1,2,3,4,5},dd,ee},
+ k,l},5}, -1)),
A = aaaaaaaaaaaaa,
%% Print the record with dots at the end of the line (Ll = 80).
- ?line "{aaaaaaa" ++ _ =
- p({A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,
- {A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,
- {A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,
- {A,{A,{ggg,{hhh,{ii,{jj,{kk,{ll,{mm,{nn,{oo,{d,1,2,3,4,5}
- }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
- }}}}}}}}}}}}}}}}, 146),
- ?line "{aaaaaaa" ++ _ =
- p({A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,
- {A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,
- {A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,
- {A,{A,{A,{A,{A,{ggg,{hhh,{ii,{jj,{kk,{ll,{mm,{nn,{oo,{a}
- }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
- }}}}}}}}}}}}}}}}}}}, 152),
-
- ?line bt(<<"{aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {g,{h,{i,{j,{k,{l,{m,{n,{o,#"
- "d{...}}}}}}}}}}}}}}}}">>,
- p({A,{A,{A,{A,{A,{A,
- {g,{h,{i,{j,{k,{l,{m,{n,{o,{d,1,2,3,4,5}}}}}}}}}}}}}}}}, 32)),
- ?line bt(<<"{a,#b{f = {c,{d,{e,{f,...}}}}}}">>,
- p({a,{b,{c,{d,{e,{f,g}}}}}}, 12)),
- ?line bt(<<"{aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,#c{f1 = ddd,"
- "f2 = eee}}}}}}}}}}">>,
- p({A,{A,{A,{A,{A,{A,{A,{A,{A,{c,ddd,eee}}}}}}}}}}, 100)),
- ?line bt(<<"{aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,{aaaaaaaaaaaaa,{aaaaaaaaaaaaa,...}}}}">>,
- p({A,{A,{A,{A,{b}}}}}, 8)),
- % With no restriction on number of characters per line:
-% ?line bt(<<"{aaaaaaaaaaaaa,{aaaaaaaaaaaaa,{aaaaaaaaaaaaa,"
-% "{aaaaaaaaaaaaa,...}}}}">>,
-% p({A,{A,{A,{A,{b}}}}}, 8)),
- ?line bt(<<"{aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,{aaaaaaaaaaaaa,{aaaaaaaaaaaaa,...}}}}}">>,
- p({A,{A,{A,{A,{A,{b}}}}}}, 10)),
- % With no restriction on number of characters per line:
-% ?line bt(<<"{aaaaaaaaaaaaa,\n"
-% " {aaaaaaaaaaaaa,{aaaaaaaaaaaaa,{aaaaaaaaaaaaa,"
-% "{aaaaaaaaaaaaa,...}}}}}">>,
-% p({A,{A,{A,{A,{A,{b}}}}}}, 10)),
- ?line bt(<<"{aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,"
- "{aaaaaaaaaaaaa,#a{}}}}}}}}}}}">>,
- p({A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{a}}}}}}}}}}}, 23)),
- ?line bt(<<"{aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n",
- " #rrrrr{\n"
- " f1 = kljlkjlksfdgkljlsdkjf,"
- "f2 = kljkljsdaflkjlkjsdf,...}}}}">>,
- p({A,{A,{A,{rrrrr, kljlkjlksfdgkljlsdkjf,
- kljkljsdaflkjlkjsdf,
- asdfkldsjfklkljsdklfds}}}}, 10)),
- % With no restriction on number of characters per line:
-% ?line bt(<<"{aaaaaaaaaaaaa,\n"
-% " {aaaaaaaaaaaaa,\n"
-% " {aaaaaaaaaaaaa,\n",
-% " #rrrrr{f1 = kljlkjlksfdgkljlsdkjf,f2 = "
-% "kljkljsdaflkjlkjsdf,...}}}}">>,
-% p({A,{A,{A,{rrrrr, kljlkjlksfdgkljlsdkjf,
-% kljkljsdaflkjlkjsdf,
-% asdfkldsjfklkljsdklfds}}}}, 10)),
- ?line bt(<<"{aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {aaaaaaaaaaaaa,\n"
- " {g,{h,{i,{j,{k,{l,{m,{n,"
- "{o,#a{}}}}}}}}}}}}}}}}}">>,
- p({A,{A,{A,{A,{A,{A,{A,
- {g,{h,{i,{j,{k,{l,{m,{n,{o,{a}}}}}}}}}}}}}}}}}, 100)),
- ?line bt(<<"#c{\n"
- " f1 = \n"
- " #c{\n"
- " f1 = \n"
- " #c{\n"
- " f1 = \n"
- " #c{\n"
- " f1 = \n"
- " #c{\n"
- " f1 = \n"
- " #c{\n"
- " f1 = \n"
- " #c{\n"
- " f1 = \n"
- " #c{\n"
- " f1 = \n"
- " #c{\n"
- " f1 = #c{f1 = #c{f1 = #c{f1 = a,"
- "f2 = b},f2 = b},f2 = b},\n"
- " f2 = b},\n"
- " f2 = b},\n"
- " f2 = b},\n"
- " f2 = b},\n"
- " f2 = b},\n"
- " f2 = b},\n"
- " f2 = b},\n"
- " f2 = b},\n"
- " f2 = b}">>,
- p({c,{c,{c,{c,{c,{c,{c,{c,{c,{c,{c,{c,a,b},b},b},b},b},b},
- b},b},b},b},b},b}, -1)),
- ?line bt(<<"#rrrrr{\n"
- " f1 = \n"
- " #rrrrr{\n"
- " f1 = \n"
- " #rrrrr{\n"
- " f1 = \n"
- " #rrrrr{\n"
- " f1 = \n"
- " {rrrrr,{rrrrr,a,#rrrrr{f1 = {rrrrr,1,2},f2 = a,"
- "f3 = b}},b},\n"
- " f2 = {rrrrr,c,d},\n"
- " f3 = {rrrrr,1,2}},\n"
- " f2 = 1,f3 = 2},\n"
- " f2 = 3,f3 = 4},\n"
- " f2 = 5,f3 = 6}">>,
- p({rrrrr,{rrrrr,{rrrrr,{rrrrr,{rrrrr,{rrrrr,a,{rrrrr,
- {rrrrr,1,2},a,b}},b},{rrrrr,c,d},{rrrrr,1,2}},
- 1,2},3,4},5,6}, -1)),
- % With other terms than atomic ones on the same line:
-% ?line bt(<<"#rrrrr{\n"
-% " f1 = \n"
-% " #rrrrr{\n"
-% " f1 = \n"
-% " #rrrrr{\n"
-% " f1 = \n"
-% " #rrrrr{\n"
-% " f1 = \n"
-% " {rrrrr,{rrrrr,a,#rrrrr{f1 = {rrrrr,1,2},f2 = a,"
-% "f3 = b}},b},\n"
-% " f2 = {rrrrr,c,d},f3 = {rrrrr,1,2}},\n"
-% " f2 = 1,f3 = 2},\n"
-% " f2 = 3,f3 = 4},\n"
-% " f2 = 5,f3 = 6}">>,
-% p({rrrrr,{rrrrr,{rrrrr,{rrrrr,{rrrrr,{rrrrr,a,{rrrrr,
-% {rrrrr,1,2},a,b}},b},{rrrrr,c,d},{rrrrr,1,2}},
-% 1,2},3,4},5,6}, -1)),
- % With no restriction on number of characters per line:
-% ?line bt(<<"#rrrrr{\n"
-% " f1 = \n"
-% " #rrrrr{\n"
-% " f1 = \n"
-% " #rrrrr{\n"
-% " f1 = \n"
-% " #rrrrr{\n"
-% " f1 = {rrrrr,{rrrrr,a,#rrrrr{f1 = {rrrrr,1,2},f2 = a,"
-% "f3 = b}},b},\n"
-% " f2 = {rrrrr,c,d},f3 = {rrrrr,1,2}},\n"
-% " f2 = 1,f3 = 2},\n"
-% " f2 = 3,f3 = 4},\n"
-% " f2 = 5,f3 = 6}">>,
-% p({rrrrr,{rrrrr,{rrrrr,{rrrrr,{rrrrr,{rrrrr,a,{rrrrr,
-% {rrrrr,1,2},a,b}},b},{rrrrr,c,d},{rrrrr,1,2}},
-% 1,2},3,4},5,6}, -1)),
- % With line breaks:
-% ?line bt(<<"#rrrrr{\n"
-% " f1 = \n"
-% " #rrrrr{\n"
-% " f1 = \n"
-% " #rrrrr{\n"
-% " f1 = \n"
-% " #rrrrr{\n"
-% " f1 = {rrrrr,{rrrrr,a,#rrrrr{f1 = {rrrrr,1,2},f2 = a,"
-% "f3 = b}},b},\n"
-% " f2 = {rrrrr,c,d},\n"
-% " f3 = {rrrrr,1,2}},\n"
-% " f2 = 1,\n"
-% " f3 = 2},\n"
-% " f2 = 3,\n"
-% " f3 = 4},\n"
-% " f2 = 5,\n"
-% " f3 = 6}">>,
-% p({rrrrr,{rrrrr,{rrrrr,{rrrrr,{rrrrr,{rrrrr,a,{rrrrr,
-% {rrrrr,1,2},a,b}},b},{rrrrr,c,d},{rrrrr,1,2}},
-% 1,2},3,4},5,6}, -1)),
- ?line "{aaa,\n {aaa," ++ _ =
+ "{aaaaaaa" ++ _ =
+ p({A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,
+ {A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,
+ {A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,
+ {A,{A,{ggg,{hhh,{ii,{jj,{kk,{ll,{mm,{nn,{oo,{d,1,2,3,4,5}
+ }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
+ }}}}}}}}}}}}}}}}, 146),
+ "{aaaaaaa" ++ _ =
+ p({A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,
+ {A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,
+ {A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{A,
+ {A,{A,{A,{A,{A,{ggg,{hhh,{ii,{jj,{kk,{ll,{mm,{nn,{oo,{a}
+ }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
+ }}}}}}}}}}}}}}}}}}}, 152),
+
+ bt(<<"{aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {g,{h,{i,{j,{k,{l,{m,{n,{o,#"
+ "d{...}}}}}}}}}}}}}}}}">>,
+ p({A,{A,{A,{A,{A,{A,
+ {g,{h,{i,{j,{k,{l,{m,{n,{o,{d,1,2,3,4,5}}}}}}}}}}}}}}}}, 32)),
+ bt(<<"{a,#b{f = {c,{d,{e,{f,...}}}}}}">>,
+ p({a,{b,{c,{d,{e,{f,g}}}}}}, 12)),
+ bt(<<"{aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,#c{f1 = ddd,"
+ "f2 = eee}}}}}}}}}}">>,
+ p({A,{A,{A,{A,{A,{A,{A,{A,{A,{c,ddd,eee}}}}}}}}}}, 100)),
+ bt(<<"{aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,{aaaaaaaaaaaaa,{aaaaaaaaaaaaa,...}}}}">>,
+ p({A,{A,{A,{A,{b}}}}}, 8)),
+ bt(<<"{aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,{aaaaaaaaaaaaa,{aaaaaaaaaaaaa,...}}}}}">>,
+ p({A,{A,{A,{A,{A,{b}}}}}}, 10)),
+ bt(<<"{aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,"
+ "{aaaaaaaaaaaaa,#a{}}}}}}}}}}}">>,
+ p({A,{A,{A,{A,{A,{A,{A,{A,{A,{A,{a}}}}}}}}}}}, 23)),
+ bt(<<"{aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n",
+ " #rrrrr{\n"
+ " f1 = kljlkjlksfdgkljlsdkjf,"
+ "f2 = kljkljsdaflkjlkjsdf,...}}}}">>,
+ p({A,{A,{A,{rrrrr, kljlkjlksfdgkljlsdkjf,
+ kljkljsdaflkjlkjsdf,
+ asdfkldsjfklkljsdklfds}}}}, 10)),
+ bt(<<"{aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {aaaaaaaaaaaaa,\n"
+ " {g,{h,{i,{j,{k,{l,{m,{n,"
+ "{o,#a{}}}}}}}}}}}}}}}}}">>,
+ p({A,{A,{A,{A,{A,{A,{A,
+ {g,{h,{i,{j,{k,{l,{m,{n,{o,{a}}}}}}}}}}}}}}}}}, 100)),
+ bt(<<"#c{\n"
+ " f1 = \n"
+ " #c{\n"
+ " f1 = \n"
+ " #c{\n"
+ " f1 = \n"
+ " #c{\n"
+ " f1 = \n"
+ " #c{\n"
+ " f1 = \n"
+ " #c{\n"
+ " f1 = \n"
+ " #c{\n"
+ " f1 = \n"
+ " #c{\n"
+ " f1 = \n"
+ " #c{\n"
+ " f1 = #c{f1 = #c{f1 = #c{f1 = a,"
+ "f2 = b},f2 = b},f2 = b},\n"
+ " f2 = b},\n"
+ " f2 = b},\n"
+ " f2 = b},\n"
+ " f2 = b},\n"
+ " f2 = b},\n"
+ " f2 = b},\n"
+ " f2 = b},\n"
+ " f2 = b},\n"
+ " f2 = b}">>,
+ p({c,{c,{c,{c,{c,{c,{c,{c,{c,{c,{c,{c,a,b},b},b},b},b},b},
+ b},b},b},b},b},b}, -1)),
+ bt(<<"#rrrrr{\n"
+ " f1 = \n"
+ " #rrrrr{\n"
+ " f1 = \n"
+ " #rrrrr{\n"
+ " f1 = \n"
+ " #rrrrr{\n"
+ " f1 = \n"
+ " {rrrrr,{rrrrr,a,#rrrrr{f1 = {rrrrr,1,2},f2 = a,"
+ "f3 = b}},b},\n"
+ " f2 = {rrrrr,c,d},\n"
+ " f3 = {rrrrr,1,2}},\n"
+ " f2 = 1,f3 = 2},\n"
+ " f2 = 3,f3 = 4},\n"
+ " f2 = 5,f3 = 6}">>,
+ p({rrrrr,{rrrrr,{rrrrr,{rrrrr,{rrrrr,{rrrrr,a,{rrrrr,
+ {rrrrr,1,2},a,b}},b},{rrrrr,c,d},{rrrrr,1,2}},
+ 1,2},3,4},5,6}, -1)),
+ "{aaa,\n {aaa," ++ _ =
p({aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,
- {aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,
- {aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,
- {aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,
- {aaa,a}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},
+ {aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,
+ {aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,
+ {aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,{aaa,
+ {aaa,a}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},
1, 80, -1),
%% A few other cases...
- ?line "{a,#Fun<" ++ _ = lists:flatten(io_lib_pretty:print({a,fun fmt/2})),
- ?line "#Fun<" ++ _ = io_lib_pretty:print(fun() -> foo end),
- % ?line "[<<\"foobar\">>|<<\"barf\"...>>]" =
- % p([<<"foobar">>|<<"barfoo">>], 1, 30, 4),
+ "{a,#Fun<" ++ _ = lists:flatten(io_lib_pretty:print({a,fun fmt/2})),
+ "#Fun<" ++ _ = io_lib_pretty:print(fun() -> foo end),
%% No support for negative columns any more:
- ?line "[a,\n [b,\n c,\n d,\n [e,\n f]],\n c]" =
- p([a,[b,c,d,[e,f]],c], -1, 2, 10),
- ?line "[a,\n [b,\n c,\n d,\n [e,\n f]],\n c]" =
- p([a,[b,c,d,[e,f]],c], 0, 2, 10),
+ "[a,\n [b,\n c,\n d,\n [e,\n f]],\n c]" =
+ p([a,[b,c,d,[e,f]],c], -1, 2, 10),
+ "[a,\n [b,\n c,\n d,\n [e,\n f]],\n c]" =
+ p([a,[b,c,d,[e,f]],c], 0, 2, 10),
%% 20 bytes are tried first, then the rest. Try 21 bytes:
L = lists:duplicate(20, $a),
- % ?line bt(<<"<<\"aaaaaa\"\n \"aaaaaa\"\n \"aaaaaa\"\n \"aaa\">>">>,
- ?line bt(<<"<<\"aaaaaaaaaaaaaaaaaaaaa\">>">>,
- p(list_to_binary([$a | L]), 1, 10, -1)),
- ?line "<<97," ++ _ = p(list_to_binary(L ++ [3]), 1, 10, -1),
- % ?line "<<\"aaaa\"...>>" = p(list_to_binary(L ++ [3]), 1, 10, 2),
- % ?line "<<\"aaaaaa\"\n \"aa\"...>>" =
- % ?line "<<\"aaaaaaaa\"...>>" =
- % p(list_to_binary(L ++ [3]), 1, 10, 3),
- % ?line "<<\"aaaaaa\"\n \"aaaaaa\"\n \"aaaaaa\"\n \"aa\"...>>" =
- % ?line "<<\"aaaaaaaaaaaaaaaaaaaa\"...>>" =
- % p(list_to_binary(L ++ [3]), 1, 10, 21),
- ?line "<<97," ++ _ = p(list_to_binary(L ++ [3]), 1, 10, 22),
-
- ?line "\"\\b\\t\\n\\v\\f\\r\\e\250\"" =
- p([8,9,10,11,12,13,27,168], 1, 40, -1),
- % ?line "\"\\b\\t\\n\"\n \"\\v\\f\\r\"\n \"\\e\250\"" =
- ?line "\"\\b\\t\\n\\v\\f\\r\\e¨\"" =
- p([8,9,10,11,12,13,27,168], 1, 10, -1),
- ?line "\"\\b\\t\\n\\v\\f\\r\\e\250\"" =
- p([8,9,10,11,12,13,27,168], 1, 40, 100),
- % ?line "\"\\e\\t\\nab\"\n \"cd\"" =
- ?line "\"\\e\\t\\nabcd\"" =
- p("\e\t\nabcd", 1, 12, -1),
+ %% bt(<<"<<\"aaaaaa\"\n \"aaaaaa\"\n \"aaaaaa\"\n \"aaa\">>">>,
+ bt(<<"<<\"aaaaaaaaaaaaaaaaaaaaa\">>">>,
+ p(list_to_binary([$a | L]), 1, 10, -1)),
+ "<<97," ++ _ = p(list_to_binary(L ++ [3]), 1, 10, -1),
+ "<<97," ++ _ = p(list_to_binary(L ++ [3]), 1, 10, 22),
+
+ "\"\\b\\t\\n\\v\\f\\r\\e\250\"" =
+ p([8,9,10,11,12,13,27,168], 1, 40, -1),
+ %% "\"\\b\\t\\n\"\n \"\\v\\f\\r\"\n \"\\e\250\"" =
+ "\"\\b\\t\\n\\v\\f\\r\\e¨\"" =
+ p([8,9,10,11,12,13,27,168], 1, 10, -1),
+ "\"\\b\\t\\n\\v\\f\\r\\e\250\"" =
+ p([8,9,10,11,12,13,27,168], 1, 40, 100),
+ %% "\"\\e\\t\\nab\"\n \"cd\"" =
+ "\"\\e\\t\\nabcd\"" =
+ p("\e\t\nabcd", 1, 12, -1),
%% DEL (127) is special...
- ?line "[127]" = p("\d", 1, 10, -1),
- ?line "[127]" = p([127], 1, 10, 100),
+ "[127]" = p("\d", 1, 10, -1),
+ "[127]" = p([127], 1, 10, 100),
- ?line "<<\"\\b\\t\\n\\v\\f\\r\\e\250\">>" =
- p(<<8,9,10,11,12,13,27,168>>, 1, 40, -1),
- ?line "<<\"\\b\\t\\n\\v\\f\\r\\e\250\">>" =
- p(<<8,9,10,11,12,13,27,168>>, 1, 10, -1),
- ?line "<<127>>" = p(<<127>>, 1, 10, 100),
+ "<<\"\\b\\t\\n\\v\\f\\r\\e\250\">>" =
+ p(<<8,9,10,11,12,13,27,168>>, 1, 40, -1),
+ "<<\"\\b\\t\\n\\v\\f\\r\\e\250\">>" =
+ p(<<8,9,10,11,12,13,27,168>>, 1, 10, -1),
+ "<<127>>" = p(<<127>>, 1, 10, 100),
%% "Partial" string binaries:
- ?line "<<\"he\"...>>" = p(list_to_binary("he"++[3]), 1, 80, 2),
- ?line "<<\"he\"...>>" = p(list_to_binary("he"++[3]), 1, 80, 3),
- ?line "<<104,101,3>>" = p(list_to_binary("he"++[3]), 1, 80, 4),
- ?line "<<...>>" = p(list_to_binary([3] ++ "he"), 1, 80, 1),
- ?line "<<3,...>>" = p(list_to_binary([3] ++ "he"), 1, 80, 2),
- ?line "<<3,104,...>>" = p(list_to_binary([3] ++ "he"), 1, 80, 3),
-
- ?line "<<\"12345678901234567890\"...>>" =
- p(list_to_binary("12345678901234567890"++[3]), 1, 80, 8),
- ?line "<<\"12345678901234567890\"...>>" =
- p(list_to_binary("12345678901234567890"++[3]), 1, 80, 21),
- ?line "<<49," ++ _ =
- p(list_to_binary("12345678901234567890"++[3]), 1, 80, 22),
-
- ?line "{sdfsdfj,\n 23" ++ _ =
- p({sdfsdfj,23423423342.23432423}, 1, 17, -1),
-
- ?line bt(<<"kljkljlksdjjlf kljalkjlsdajafasjdfj [kjljklasdf,kjlljsfd,sdfsdkjfsd,kjjsdf,jl,
+ "<<\"he\"...>>" = p(list_to_binary("he"++[3]), 1, 80, 2),
+ "<<\"he\"...>>" = p(list_to_binary("he"++[3]), 1, 80, 3),
+ "<<104,101,3>>" = p(list_to_binary("he"++[3]), 1, 80, 4),
+ "<<...>>" = p(list_to_binary([3] ++ "he"), 1, 80, 1),
+ "<<3,...>>" = p(list_to_binary([3] ++ "he"), 1, 80, 2),
+ "<<3,104,...>>" = p(list_to_binary([3] ++ "he"), 1, 80, 3),
+
+ "<<\"12345678901234567890\"...>>" =
+ p(list_to_binary("12345678901234567890"++[3]), 1, 80, 8),
+ "<<\"12345678901234567890\"...>>" =
+ p(list_to_binary("12345678901234567890"++[3]), 1, 80, 21),
+ "<<49," ++ _ =
+ p(list_to_binary("12345678901234567890"++[3]), 1, 80, 22),
+
+ "{sdfsdfj,\n 23" ++ _ =
+ p({sdfsdfj,23423423342.23432423}, 1, 17, -1),
+
+ bt(<<"kljkljlksdjjlf kljalkjlsdajafasjdfj [kjljklasdf,kjlljsfd,sdfsdkjfsd,kjjsdf,jl,
lkjjlajsfd|jsdf]">>,
fmt("~w ~w ~p",
[kljkljlksdjjlf,
@@ -949,45 +678,36 @@ otp_6354(Config) when is_list(Config) ->
jsdf]])),
%% Binaries are split as well:
- ?line bt(<<"<<80,100,0,55,55,55,55,55,55,55,55,55,\n "
+ bt(<<"<<80,100,0,55,55,55,55,55,55,55,55,55,\n "
"55,55,55,55,55,55,55,...>>">>,
p(<<80,100,0,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,
55,55,55,55,55,55,55,55,55,55,55,55>>,1,40,20)),
- ?line bt(<<"<<80,100,0,55,55,55,55,55,55,55,55,55,\n "
+ bt(<<"<<80,100,0,55,55,55,55,55,55,55,55,55,\n "
"55,55,55,55,55,55,55,55,55,55,55,55,\n 55,55,55,55,55,55>>">>,
p(<<80,100,0,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,
55,55,55,55,55,55,55,55,55,55,55,55>>,1,40,-1)),
- ?line "<<0,0,0,\n ...>>" = p(<<0,0,0,0,0>>, 1, 10, 4),
+ "<<0,0,0,\n ...>>" = p(<<0,0,0,0,0>>, 1, 10, 4),
%% ~W now uses ",..." when printing tuples
- ?line "[a,b|...]" = fmt("~W", [[a,b,c,d,e], 3]),
- ?line "{a,b,...}" = fmt("~W", [{a,b,c,d,e}, 3]),
+ "[a,b|...]" = fmt("~W", [[a,b,c,d,e], 3]),
+ "{a,b,...}" = fmt("~W", [{a,b,c,d,e}, 3]),
ok.
-otp_6495(doc) ->
- ["OTP-6495. io_lib_pretty bugfix."];
-otp_6495(suite) ->
- [];
+%% OTP-6495. io_lib_pretty bugfix.
otp_6495(Config) when is_list(Config) ->
- ?line bt(<<"[120,120,120,120,120,120,120,120,120,120,120,120,120,120,"
+ bt(<<"[120,120,120,120,120,120,120,120,120,120,120,120,120,120,"
"120,120,120,120,120]<<1>>">>,
fmt("~w~p", ["xxxxxxxxxxxxxxxxxxx", <<1>>])),
ok.
-otp_6517(doc) ->
- ["OTP-6517. The Format argument of fwrite can be a binary."];
-otp_6517(suite) ->
- [];
+%% OTP-6517. The Format argument of fwrite can be a binary.
otp_6517(Config) when is_list(Config) ->
- ?line "string" = fmt(<<"~s">>, [<<"string">>]),
+ "string" = fmt(<<"~s">>, [<<"string">>]),
ok.
-otp_6502(doc) ->
- ["OTP-6502. Bits."];
-otp_6502(suite) ->
- [];
+%% OTP-6502. Bits.
otp_6502(Config) when is_list(Config) ->
- ?line bt(<<
+ bt(<<
"[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]"
"<<0,0,8,\n"
" "
@@ -995,10 +715,7 @@ otp_6502(Config) when is_list(Config) ->
fmt("~w~p", [lists:seq(0, 25), <<17:25>>])),
ok.
-otp_7421(doc) ->
- ["OTP-7421. Soft limit of 60 chars removed when pretty printing."];
-otp_7421(suite) ->
- [];
+%% OTP-7421. Soft limit of 60 chars removed when pretty printing.
otp_7421(Config) when is_list(Config) ->
bt(<<"{aa,bb,\n"
" c,dd,\n"
@@ -1066,31 +783,28 @@ rfd(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0) ->
rfd(_, _) ->
no.
-manpage(doc) ->
- ["The examples in io(3) and io_lib(3)."];
-manpage(suite) ->
- [];
+%% The examples in io(3) and io_lib(3).
manpage(Config) when is_list(Config) ->
%% The examples that write or print only, not the ones that read...
- ?line bt(<<"Hello world!\n">>,
+ bt(<<"Hello world!\n">>,
fmt("Hello world!~n", [])),
- ?line bt(<<"| aaaaa|bbbbb |ccccc|\n">>, % bugfix
+ bt(<<"| aaaaa|bbbbb |ccccc|\n">>, % bugfix
fmt("|~10.5c|~-10.5c|~5c|~n", [$a, $b, $c])),
- ?line bt(<<"|**********|\n">>,
+ bt(<<"|**********|\n">>,
fmt("|~10w|~n", [{hey, hey, hey}])),
- ?line bt(<<"|{hey,hey,h|\n">>,
+ bt(<<"|{hey,hey,h|\n">>,
fmt("|~10s|~n", [io_lib:write({hey, hey, hey})])),
T = [{attributes,[[{id,age,1.50000},{mode,explicit},
{typename,"INTEGER"}], [{id,cho},{mode,explicit},{typename,'Cho'}]]},
{typename,'Person'},{tag,{'PRIVATE',3}},{mode,implicit}],
- ?line bt(<<"[{attributes,[[{id,age,1.5},{mode,explicit},{typename,"
+ bt(<<"[{attributes,[[{id,age,1.5},{mode,explicit},{typename,"
"[73,78,84,69,71,69,82]}],[{id,cho},{mode,explicit},"
"{typename,'Cho'}]]},{typename,'Person'},{tag,{'PRIVATE',3}},"
"{mode,implicit}]\n">>,
fmt("~w~n", [T])),
- ?line bt(<<"[{attributes,[[{id,age,1.5},\n"
+ bt(<<"[{attributes,[[{id,age,1.5},\n"
" {mode,explicit},\n"
" {typename,\"INTEGER\"}],\n"
" [{id,cho},{mode,explicit},{typename,'Cho'}]]},\n"
@@ -1098,7 +812,7 @@ manpage(Config) when is_list(Config) ->
" {tag,{'PRIVATE',3}},\n"
" {mode,implicit}]\n">>,
fmt("~62p~n", [T])),
- ?line bt(<<"Here T = [{attributes,[[{id,age,1.5},\n"
+ bt(<<"Here T = [{attributes,[[{id,age,1.5},\n"
" {mode,explicit},\n"
" {typename,\"INTEGER\"}],\n"
" [{id,cho},\n"
@@ -1108,67 +822,64 @@ manpage(Config) when is_list(Config) ->
" {tag,{'PRIVATE',3}},\n"
" {mode,implicit}]\n">>,
fmt("Here T = ~62p~n", [T])),
- ?line bt(<<"[{attributes,[[{id,age,1.5},{mode,explicit},"
+ bt(<<"[{attributes,[[{id,age,1.5},{mode,explicit},"
"{typename,...}],[{id,cho},{mode,...},{...}]]},"
"{typename,'Person'},{tag,{'PRIVATE',3}},{mode,implicit}]\n">>,
fmt("~W~n", [T,9])),
- ?line bt(<<"[{attributes,[[{id,age,1.5},{mode,explicit},{typename,...}],"
+ bt(<<"[{attributes,[[{id,age,1.5},{mode,explicit},{typename,...}],"
"\n "
"[{id,cho},{mode,...},{...}]]},\n {typename,'Person'},\n "
"{tag,{'PRIVATE',3}},\n {mode,implicit}]\n">>,
fmt("~62P~n", [T,9])),
- ?line "1F\n" = fmt("~.16B~n", [31]),
- ?line "-10011\n" = fmt("~.2B~n", [-19]),
- ?line "5Z\n" = fmt("~.36B~n", [5*36+35]),
- ?line "10#31\n" = fmt("~X~n", [31,"10#"]),
- ?line "-0x1F\n" = fmt("~.16X~n", [-31,"0x"]),
- ?line "10#31\n" = fmt("~.10#~n", [31]),
- ?line "-16#1F\n" = fmt("~.16#~n", [-31]),
- ?line "abc def 'abc def' {foo,1} A \n" =
+ "1F\n" = fmt("~.16B~n", [31]),
+ "-10011\n" = fmt("~.2B~n", [-19]),
+ "5Z\n" = fmt("~.36B~n", [5*36+35]),
+ "10#31\n" = fmt("~X~n", [31,"10#"]),
+ "-0x1F\n" = fmt("~.16X~n", [-31,"0x"]),
+ "10#31\n" = fmt("~.10#~n", [31]),
+ "-16#1F\n" = fmt("~.16#~n", [-31]),
+ "abc def 'abc def' {foo,1} A \n" =
fmt("~s ~w ~i ~w ~c ~n",
['abc def', 'abc def', {foo, 1},{foo, 1}, 65]),
- % fmt("~s", [65]),
+ %% fmt("~s", [65]),
%% io_lib(3)
- ?line bt(<<"{1,[2],[3],[...],...}">>,
+ bt(<<"{1,[2],[3],[...],...}">>,
lists:flatten(io_lib:write({1,[2],[3],[4,5],6,7,8,9}, 5))),
ok.
-otp_6708(doc) ->
- ["OTP-6708. Fewer newlines when pretty-printing."];
-otp_6708(suite) ->
- [];
+%% OTP-6708. Fewer newlines when pretty-printing.
otp_6708(Config) when is_list(Config) ->
- ?line bt(<<"[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,\n"
+ bt(<<"[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,\n"
" 23,24,25,26,27,28,29|...]">>,
p(lists:seq(1,1000), 30)),
- ?line bt(<<"{lkjasklfjsdak,mlkasjdflksj,klasdjfklasd,jklasdfjkl,\n"
+ bt(<<"{lkjasklfjsdak,mlkasjdflksj,klasdjfklasd,jklasdfjkl,\n"
" jklsdjfklsd,masdfjkkl}">>,
p({lkjasklfjsdak,mlkasjdflksj,klasdjfklasd,jklasdfjkl,
jklsdjfklsd, masdfjkkl}, -1)),
- ?line bt(<<"#b{f = {lkjljalksdf,jklaskfjd,kljasdlf,kljasdf,kljsdlkf,\n"
+ bt(<<"#b{f = {lkjljalksdf,jklaskfjd,kljasdlf,kljasdf,kljsdlkf,\n"
" kjdd}}">>,
p({b, {lkjljalksdf,jklaskfjd,kljasdlf,kljasdf,kljsdlkf,kjdd}},
-1)),
- ?line bt(<<"#b{f = {lkjljalksdf,jklaskfjd,kljasdlf,kljasdf,kljsdlkf,\n"
+ bt(<<"#b{f = {lkjljalksdf,jklaskfjd,kljasdlf,kljasdf,kljsdlkf,\n"
" kdd}}">>,
p({b, {lkjljalksdf,jklaskfjd,kljasdlf,kljasdf,kljsdlkf,kdd}},
-1)),
- ?line bt(<<"#e{f = undefined,g = undefined,\n"
+ bt(<<"#e{f = undefined,g = undefined,\n"
" h = #e{f = 11,g = 22,h = 333}}">>,
p({e,undefined,undefined,{e,11,22,333}}, -1)),
- ?line bt(<<"[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21|\n"
+ bt(<<"[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21|\n"
" apa11]">>,
p(lists:seq(1,21) ++ apa11, -1)),
- ?line bt(<<"[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,\n"
+ bt(<<"[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,\n"
" 23,\n"
" {{abadalkjlasdjflksdajfksdklfsdjlkfdlskjflsdj"
"flsdjfldsdsdddd}}]">>,
p(lists:seq(1,23) ++
[{{abadalkjlasdjflksdajfksdklfsdjlkfdlskjflsdjflsdjfldsdsdddd}}],
-1)),
- ?line bt(<<"{lkjasdf,\n"
+ bt(<<"{lkjasdf,\n"
" {kjkjsd,\n"
" {kjsd,\n"
" {kljsdf,\n"
@@ -1180,7 +891,7 @@ otp_6708(Config) when is_list(Config) ->
{dkjsdf,{kjlds,
{kljsd,{kljs,{kljlkjsd}}}}}}}}}},
-1)),
- ?line bt(<<"{lkjasdf,\n"
+ bt(<<"{lkjasdf,\n"
" {kjkjsd,\n"
" {kjsd,{kljsdf,{kjlsd,{dkjsdf,{kjlds,"
"{kljsd,{kljs}}}}}}}}}">>,
@@ -1188,24 +899,24 @@ otp_6708(Config) when is_list(Config) ->
{kljsdf,{kjlsd,{dkjsdf,
{kjlds,{kljsd,{kljs}}}}}}}}},
-1)),
- ?line bt(<<"<<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,\n"
+ bt(<<"<<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,\n"
" 22,23>>">>,
p(list_to_binary(lists:seq(1,23)), -1)),
- ?line bt(<<"<<100,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,\n"
+ bt(<<"<<100,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,\n"
" 27>>">>,
p(list_to_binary([100|lists:seq(10,27)]), -1)),
- ?line bt(<<"<<100,101,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,\n"
+ bt(<<"<<100,101,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,\n"
" 26>>">>,
p(list_to_binary([100,101|lists:seq(10,26)]), -1)),
- ?line bt(<<"{{<<100,101,102,10,11,12,13,14,15,16,17,18,19,20,21,22,\n"
+ bt(<<"{{<<100,101,102,10,11,12,13,14,15,16,17,18,19,20,21,22,\n"
" 23>>}}">>,
p({{list_to_binary([100,101,102|lists:seq(10,23)])}}, -1)),
- ?line bt(<<"[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22|\n"
+ bt(<<"[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22|\n"
" ap]">>,
p(lists:seq(1,22) ++ ap, -1)),
- ?line bt(<<"[1,2,3,4,5,6,7,8,9,10,{},[],\n <<>>,11,12,13,14,15]">>,
+ bt(<<"[1,2,3,4,5,6,7,8,9,10,{},[],\n <<>>,11,12,13,14,15]">>,
p(lists:seq(1,10) ++ [{},[],<<>>] ++ lists:seq(11,15),1,30,-1)),
- ?line bt(<<"[ddd,ddd,\n"
+ bt(<<"[ddd,ddd,\n"
" {1},\n"
" [1,2],\n"
" ddd,kdfd,\n"
@@ -1215,7 +926,7 @@ otp_6708(Config) when is_list(Config) ->
p([ddd,ddd,{1},[1,2],ddd,kdfd,[[1,2],a,b,c],<<"foo">>,<<"bar">>,
1,{2}],1,50,-1)),
- ?line bt(<<"{dskljsadfkjsdlkjflksdjflksdjfklsdjklfjsdklfjlsdjfkl,jksd,\n"
+ bt(<<"{dskljsadfkjsdlkjflksdjflksdjfklsdjklfjsdklfjlsdjfkl,jksd,\n"
" "
"lkjsdf,kljsdf,kljsf,kljsdf,kljsdf,jkldf,jklsdf,kljsdf,\n"
" "
@@ -1226,7 +937,7 @@ otp_6708(Config) when is_list(Config) ->
lkjsdf,kljsdf,kljsf,kljsdf,kljsdf,jkldf,jklsdf,kljsdf,
kljsdf,jklsdf,lkjfd,lkjsdf,kljsdf,kljsdf,lkjsdf,kljsdf,
lkjsdfsd,kljsdf,kjsfj}, 1, 110, -1)),
- ?line bt(<<"{dskljsadfkjsdlkjflksdjflksdjfklsdjklfjsdklfjlsdjfkl,"
+ bt(<<"{dskljsadfkjsdlkjflksdjflksdjfklsdjklfjsdklfjlsdjfkl,"
"#d{aaaaaaaaaaaaaaaaaaaa = 1,\n"
" "
"bbbbbbbbbbbbbbbbbbbb = 2,cccccccccccccccccccc = 3,\n"
@@ -1239,15 +950,12 @@ otp_6708(Config) when is_list(Config) ->
-define(ONE(N), ((1 bsl N) - 1)).
-define(ALL_ONES, ((1 bsl 52) - 1)).
-otp_7084(doc) ->
- ["OTP-7084. Printing floating point numbers nicely."];
-otp_7084(suite) ->
- [];
+
+otp_7084() ->
+ [{timetrap,{minutes,3}}].
+
+%% OTP-7084. Printing floating point numbers nicely.
otp_7084(Config) when is_list(Config) ->
- OldDog=?config(watchdog, Config),
- test_server:timetrap_cancel(OldDog),
- Timeout = 180,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
L = [{g_warm_up, fun g_warm_up/0},
{g_big_pos_float, fun g_big_pos_float/0},
{g_small_neg_float, fun g_small_neg_float/0},
@@ -1263,7 +971,6 @@ otp_7084(Config) when is_list(Config) ->
catch throw:Reason ->
Reason
end,
- ?line test_server:timetrap_cancel(Dog),
R.
g_warm_up() ->
@@ -1295,7 +1002,7 @@ g_close_to_zero() ->
g_denormalized() ->
%% Denormalized floats (mantissa carry):
-% D = 5,
+%% D = 5,
%% Faster:
D = 1,
[ft({{S,0,?ONE(N)},D,D}) || S <- [0,1], N <- lists:seq(0, 52)],
@@ -1303,7 +1010,7 @@ g_denormalized() ->
g_normalized() ->
%% Normalized floats (exponent carry):
-% D = 5,
+%% D = 5,
%% Faster:
D = 1,
[ft({{S,E,?ONE(52)},D,D}) || S <- [0,1], E <- lists:seq(0, 2045)],
@@ -1322,8 +1029,7 @@ g_choice() ->
g_misc() ->
L_0_308 = lists:seq(0, 308),
L_0_307 = lists:seq(0, 307),
-% L_1_9 = lists:seq(1, 9),
-% L_0_9 = lists:seq(0, 9),
+
%% Faster:
L_1_9 = [1,5,9],
L_0_9 = [0,1,5,9],
@@ -1798,10 +1504,10 @@ pack(Sign, Exp, Frac) ->
%% Whitebox test of io_lib:collect_line/3.
io_lib_collect_line_3_wb(Config) when is_list(Config) ->
- ?line do_collect_line(binary, "\n"),
- ?line do_collect_line(binary, "\r\n"),
- ?line do_collect_line(list, "\n"),
- ?line do_collect_line(list, "\r\n"),
+ do_collect_line(binary, "\n"),
+ do_collect_line(binary, "\r\n"),
+ do_collect_line(list, "\n"),
+ do_collect_line(list, "\r\n"),
ok.
do_collect_line(Mode, Eol) ->
@@ -1860,44 +1566,44 @@ do_collect_line_adjust_rest(Rest, [List|T]) when is_list(List) ->
cr_whitespace_in_string(Config) when is_list(Config) ->
- ?line {ok,["abc"],[]} = io_lib:fread("~s", "\rabc").
+ {ok,["abc"],[]} = io_lib:fread("~s", "\rabc").
io_fread_newlines(Config) when is_list(Config) ->
- ?line PrivDir = ?privdir(Config),
- ?line Fname = filename:join(PrivDir, "io_fread_newlines.txt"),
- ?line F0 = [[0,1,2,3,4,5,6,7,8,9]],
- ?line F1 = [[0,1,2,3,4,5,6,7,8],[9]],
- ?line F2 = [[0,1,2,3,4,5,6,7],[8,9]],
- ?line F3 = [[0,1,2,3,4,5,6],[7,8,9]],
- ?line F4 = [[0,1,2,3,4,5],[6,7,8,9]],
- ?line F5 = [[0,1,2,3,4],[5,6,7,8,9]],
- ?line F6 = [[0,1,2,3],[4,5,6,7],[8,9]],
- ?line F7 = [[0,1,2],[3,4,5],[6,7,8],[9]],
- ?line F8 = [[0,1],[2,3],[4,5],[6,7],[8,9]],
- ?line F9 = [[0],[1],[2],[3],[4],[5],[6],[7],[8],[9]],
- ?line Newlines = ["\n", "\r\n", "\r"],
+ PrivDir = ?privdir(Config),
+ Fname = filename:join(PrivDir, "io_fread_newlines.txt"),
+ F0 = [[0,1,2,3,4,5,6,7,8,9]],
+ F1 = [[0,1,2,3,4,5,6,7,8],[9]],
+ F2 = [[0,1,2,3,4,5,6,7],[8,9]],
+ F3 = [[0,1,2,3,4,5,6],[7,8,9]],
+ F4 = [[0,1,2,3,4,5],[6,7,8,9]],
+ F5 = [[0,1,2,3,4],[5,6,7,8,9]],
+ F6 = [[0,1,2,3],[4,5,6,7],[8,9]],
+ F7 = [[0,1,2],[3,4,5],[6,7,8],[9]],
+ F8 = [[0,1],[2,3],[4,5],[6,7],[8,9]],
+ F9 = [[0],[1],[2],[3],[4],[5],[6],[7],[8],[9]],
+ Newlines = ["\n", "\r\n", "\r"],
try
- ?line io_fread_newlines_1([F0,F1,F2,F3,F4,F5,F6,F7,F8,F9],
+ io_fread_newlines_1([F0,F1,F2,F3,F4,F5,F6,F7,F8,F9],
Fname, Newlines)
after
file:delete(Fname)
end.
io_fread_newlines_1(Fs, Fname, [Newline|Newlines]) ->
- ?line ok = io_fread_newlines_2(Fs, Fname, Newline),
- ?line io_fread_newlines_1(Fs, Fname, Newlines);
+ ok = io_fread_newlines_2(Fs, Fname, Newline),
+ io_fread_newlines_1(Fs, Fname, Newlines);
io_fread_newlines_1(_, _, []) -> ok.
io_fread_newlines_2([F|Fs], Fname, Newline) ->
- ?line N1 = write_newlines_file(Fname, F, Newline),
- ?line {F2,N2} = read_newlines_file(Fname),
- ?line io:format("~w ~p ~w~n~n", [N1,F,N2]),
- ?line F2 = lists:flatten(F),
+ N1 = write_newlines_file(Fname, F, Newline),
+ {F2,N2} = read_newlines_file(Fname),
+ io:format("~w ~p ~w~n~n", [N1,F,N2]),
+ F2 = lists:flatten(F),
%% Intermediate newlines are not counted
- ?line N2 = N1 - (length(F) - 1)*length(Newline),
- ?line io_fread_newlines_2(Fs, Fname, Newline);
+ N2 = N1 - (length(F) - 1)*length(Newline),
+ io_fread_newlines_2(Fs, Fname, Newline);
io_fread_newlines_2([], _, _) -> ok.
@@ -1939,111 +1645,108 @@ read_newlines(Fd, Acc, N0) ->
-otp_8989(doc) ->
- "OTP-8989 io:format for ~F.Ps ignores P in some cases";
+%% OTP-8989 io:format for ~F.Ps ignores P in some cases.
otp_8989(Suite) when is_list(Suite) ->
Hello = "Hello",
- ?line " Hello" = fmt("~6.6s", [Hello]),
- ?line " Hello" = fmt("~*.6s", [6,Hello]),
- ?line " Hello" = fmt("~6.*s", [6,Hello]),
- ?line " Hello" = fmt("~*.*s", [6,6,Hello]),
+ " Hello" = fmt("~6.6s", [Hello]),
+ " Hello" = fmt("~*.6s", [6,Hello]),
+ " Hello" = fmt("~6.*s", [6,Hello]),
+ " Hello" = fmt("~*.*s", [6,6,Hello]),
%%
- ?line " Hello" = fmt("~6.5s", [Hello]),
- ?line " Hello" = fmt("~*.5s", [6,Hello]),
- ?line " Hello" = fmt("~6.*s", [5,Hello]),
- ?line " Hello" = fmt("~*.*s", [6,5,Hello]),
+ " Hello" = fmt("~6.5s", [Hello]),
+ " Hello" = fmt("~*.5s", [6,Hello]),
+ " Hello" = fmt("~6.*s", [5,Hello]),
+ " Hello" = fmt("~*.*s", [6,5,Hello]),
%%
- ?line " Hell" = fmt("~6.4s", [Hello]),
- ?line " Hell" = fmt("~*.4s", [6,Hello]),
- ?line " Hell" = fmt("~6.*s", [4,Hello]),
- ?line " Hell" = fmt("~*.*s", [6,4,Hello]),
+ " Hell" = fmt("~6.4s", [Hello]),
+ " Hell" = fmt("~*.4s", [6,Hello]),
+ " Hell" = fmt("~6.*s", [4,Hello]),
+ " Hell" = fmt("~*.*s", [6,4,Hello]),
%%
- ?line "Hello" = fmt("~5.5s", [Hello]),
- ?line "Hello" = fmt("~*.5s", [5,Hello]),
- ?line "Hello" = fmt("~5.*s", [5,Hello]),
- ?line "Hello" = fmt("~*.*s", [5,5,Hello]),
+ "Hello" = fmt("~5.5s", [Hello]),
+ "Hello" = fmt("~*.5s", [5,Hello]),
+ "Hello" = fmt("~5.*s", [5,Hello]),
+ "Hello" = fmt("~*.*s", [5,5,Hello]),
%%
- ?line " Hell" = fmt("~5.4s", [Hello]),
- ?line " Hell" = fmt("~*.4s", [5,Hello]),
- ?line " Hell" = fmt("~5.*s", [4,Hello]),
- ?line " Hell" = fmt("~*.*s", [5,4,Hello]),
+ " Hell" = fmt("~5.4s", [Hello]),
+ " Hell" = fmt("~*.4s", [5,Hello]),
+ " Hell" = fmt("~5.*s", [4,Hello]),
+ " Hell" = fmt("~*.*s", [5,4,Hello]),
%%
- ?line "Hell" = fmt("~4.4s", [Hello]),
- ?line "Hell" = fmt("~*.4s", [4,Hello]),
- ?line "Hell" = fmt("~4.*s", [4,Hello]),
- ?line "Hell" = fmt("~*.*s", [4,4,Hello]),
+ "Hell" = fmt("~4.4s", [Hello]),
+ "Hell" = fmt("~*.4s", [4,Hello]),
+ "Hell" = fmt("~4.*s", [4,Hello]),
+ "Hell" = fmt("~*.*s", [4,4,Hello]),
%%
- ?line " Hel" = fmt("~4.3s", [Hello]),
- ?line " Hel" = fmt("~*.3s", [4,Hello]),
- ?line " Hel" = fmt("~4.*s", [3,Hello]),
- ?line " Hel" = fmt("~*.*s", [4,3,Hello]),
+ " Hel" = fmt("~4.3s", [Hello]),
+ " Hel" = fmt("~*.3s", [4,Hello]),
+ " Hel" = fmt("~4.*s", [3,Hello]),
+ " Hel" = fmt("~*.*s", [4,3,Hello]),
%%
%%
- ?line "Hello " = fmt("~-6.6s", [Hello]),
- ?line "Hello " = fmt("~*.6s", [-6,Hello]),
- ?line "Hello " = fmt("~-6.*s", [6,Hello]),
- ?line "Hello " = fmt("~*.*s", [-6,6,Hello]),
+ "Hello " = fmt("~-6.6s", [Hello]),
+ "Hello " = fmt("~*.6s", [-6,Hello]),
+ "Hello " = fmt("~-6.*s", [6,Hello]),
+ "Hello " = fmt("~*.*s", [-6,6,Hello]),
%%
- ?line "Hello " = fmt("~-6.5s", [Hello]),
- ?line "Hello " = fmt("~*.5s", [-6,Hello]),
- ?line "Hello " = fmt("~-6.*s", [5,Hello]),
- ?line "Hello " = fmt("~*.*s", [-6,5,Hello]),
+ "Hello " = fmt("~-6.5s", [Hello]),
+ "Hello " = fmt("~*.5s", [-6,Hello]),
+ "Hello " = fmt("~-6.*s", [5,Hello]),
+ "Hello " = fmt("~*.*s", [-6,5,Hello]),
%%
- ?line "Hell " = fmt("~-6.4s", [Hello]),
- ?line "Hell " = fmt("~*.4s", [-6,Hello]),
- ?line "Hell " = fmt("~-6.*s", [4,Hello]),
- ?line "Hell " = fmt("~*.*s", [-6,4,Hello]),
+ "Hell " = fmt("~-6.4s", [Hello]),
+ "Hell " = fmt("~*.4s", [-6,Hello]),
+ "Hell " = fmt("~-6.*s", [4,Hello]),
+ "Hell " = fmt("~*.*s", [-6,4,Hello]),
%%
- ?line "Hello" = fmt("~-5.5s", [Hello]),
- ?line "Hello" = fmt("~*.5s", [-5,Hello]),
- ?line "Hello" = fmt("~-5.*s", [5,Hello]),
- ?line "Hello" = fmt("~*.*s", [-5,5,Hello]),
+ "Hello" = fmt("~-5.5s", [Hello]),
+ "Hello" = fmt("~*.5s", [-5,Hello]),
+ "Hello" = fmt("~-5.*s", [5,Hello]),
+ "Hello" = fmt("~*.*s", [-5,5,Hello]),
%%
- ?line "Hell " = fmt("~-5.4s", [Hello]),
- ?line "Hell " = fmt("~*.4s", [-5,Hello]),
- ?line "Hell " = fmt("~-5.*s", [4,Hello]),
- ?line "Hell " = fmt("~*.*s", [-5,4,Hello]),
+ "Hell " = fmt("~-5.4s", [Hello]),
+ "Hell " = fmt("~*.4s", [-5,Hello]),
+ "Hell " = fmt("~-5.*s", [4,Hello]),
+ "Hell " = fmt("~*.*s", [-5,4,Hello]),
%%
- ?line "Hell" = fmt("~-4.4s", [Hello]),
- ?line "Hell" = fmt("~*.4s", [-4,Hello]),
- ?line "Hell" = fmt("~-4.*s", [4,Hello]),
- ?line "Hell" = fmt("~*.*s", [-4,4,Hello]),
+ "Hell" = fmt("~-4.4s", [Hello]),
+ "Hell" = fmt("~*.4s", [-4,Hello]),
+ "Hell" = fmt("~-4.*s", [4,Hello]),
+ "Hell" = fmt("~*.*s", [-4,4,Hello]),
%%
- ?line "Hel " = fmt("~-4.3s", [Hello]),
- ?line "Hel " = fmt("~*.3s", [-4,Hello]),
- ?line "Hel " = fmt("~-4.*s", [3,Hello]),
- ?line "Hel " = fmt("~*.*s", [-4,3,Hello]),
+ "Hel " = fmt("~-4.3s", [Hello]),
+ "Hel " = fmt("~*.3s", [-4,Hello]),
+ "Hel " = fmt("~-4.*s", [3,Hello]),
+ "Hel " = fmt("~*.*s", [-4,3,Hello]),
ok.
-io_lib_fread_literal(doc) ->
- "OTP-9439 io_lib:fread bug for literate at end";
+%% OTP-9439 io_lib:fread bug for literate at end.
io_lib_fread_literal(Suite) when is_list(Suite) ->
- ?line {more,"~d",0,""} = io_lib:fread("~d", ""),
- ?line {error,{fread,integer}} = io_lib:fread("~d", " "),
- ?line {more,"~d",1,""} = io_lib:fread(" ~d", " "),
- ?line {ok,[17],"X"} = io_lib:fread(" ~d", " 17X"),
+ {more,"~d",0,""} = io_lib:fread("~d", ""),
+ {error,{fread,integer}} = io_lib:fread("~d", " "),
+ {more,"~d",1,""} = io_lib:fread(" ~d", " "),
+ {ok,[17],"X"} = io_lib:fread(" ~d", " 17X"),
%%
- ?line {more,"d",0,""} = io_lib:fread("d", ""),
- ?line {error,{fread,input}} = io_lib:fread("d", " "),
- ?line {more,"d",1,""} = io_lib:fread(" d", " "),
- ?line {ok,[],"X"} = io_lib:fread(" d", " dX"),
+ {more,"d",0,""} = io_lib:fread("d", ""),
+ {error,{fread,input}} = io_lib:fread("d", " "),
+ {more,"d",1,""} = io_lib:fread(" d", " "),
+ {ok,[],"X"} = io_lib:fread(" d", " dX"),
%%
- ?line {done,eof,_} = io_lib:fread([], eof, "~d"),
- ?line {done,eof,_} = io_lib:fread([], eof, " ~d"),
- ?line {more,C1} = io_lib:fread([], " \n", " ~d"),
- ?line {done,{error,{fread,input}},_} = io_lib:fread(C1, eof, " ~d"),
- ?line {done,{ok,[18]},""} = io_lib:fread(C1, "18\n", " ~d"),
+ {done,eof,_} = io_lib:fread([], eof, "~d"),
+ {done,eof,_} = io_lib:fread([], eof, " ~d"),
+ {more,C1} = io_lib:fread([], " \n", " ~d"),
+ {done,{error,{fread,input}},_} = io_lib:fread(C1, eof, " ~d"),
+ {done,{ok,[18]},""} = io_lib:fread(C1, "18\n", " ~d"),
%%
- ?line {done,eof,_} = io_lib:fread([], eof, "d"),
- ?line {done,eof,_} = io_lib:fread([], eof, " d"),
- ?line {more,C2} = io_lib:fread([], " \n", " d"),
- ?line {done,{error,{fread,input}},_} = io_lib:fread(C2, eof, " d"),
- ?line {done,{ok,[]},[]} = io_lib:fread(C2, "d\n", " d"),
+ {done,eof,_} = io_lib:fread([], eof, "d"),
+ {done,eof,_} = io_lib:fread([], eof, " d"),
+ {more,C2} = io_lib:fread([], " \n", " d"),
+ {done,{error,{fread,input}},_} = io_lib:fread(C2, eof, " d"),
+ {done,{ok,[]},[]} = io_lib:fread(C2, "d\n", " d"),
ok.
-printable_range(doc) ->
- "Check that the printable range set by the user actually works";
+%% Check that the printable range set by the user actually works.
printable_range(Suite) when is_list(Suite) ->
Pa = filename:dirname(code:which(?MODULE)),
{ok, UNode} = test_server:start_node(printable_range_unicode, slave,
@@ -2145,19 +1848,17 @@ flush_from_port(P) ->
ok
end.
-io_lib_print_binary_depth_one(doc) ->
- "Test binaries printed with a depth of one behave correctly";
+%% Test binaries printed with a depth of one behave correctly.
io_lib_print_binary_depth_one(Suite) when is_list(Suite) ->
- ?line "<<>>" = fmt("~W", [<<>>, 1]),
- ?line "<<>>" = fmt("~P", [<<>>, 1]),
- ?line "<<...>>" = fmt("~W", [<<1>>, 1]),
- ?line "<<...>>" = fmt("~P", [<<1>>, 1]),
- ?line "<<...>>" = fmt("~W", [<<1:7>>, 1]),
- ?line "<<...>>" = fmt("~P", [<<1:7>>, 1]),
+ "<<>>" = fmt("~W", [<<>>, 1]),
+ "<<>>" = fmt("~P", [<<>>, 1]),
+ "<<...>>" = fmt("~W", [<<1>>, 1]),
+ "<<...>>" = fmt("~P", [<<1>>, 1]),
+ "<<...>>" = fmt("~W", [<<1:7>>, 1]),
+ "<<...>>" = fmt("~P", [<<1:7>>, 1]),
ok.
-otp_10302(doc) ->
- "OTP-10302. Unicode";
+%% OTP-10302. Unicode.
otp_10302(Suite) when is_list(Suite) ->
Pa = filename:dirname(code:which(?MODULE)),
{ok, UNode} = test_server:start_node(printable_range_unicode, slave,
@@ -2213,15 +1914,13 @@ pretty(Term, Opts) when is_list(Opts) ->
is_latin1(S) ->
S >= 0 andalso S =< 255.
-otp_10836(doc) ->
- "OTP-10836. ~ts extended to latin1";
+%% OTP-10836. ~ts extended to latin1.
otp_10836(Suite) when is_list(Suite) ->
S = io_lib:format("~ts", [[<<"äpple"/utf8>>, <<"äpple">>]]),
"äppleäpple" = lists:flatten(S),
ok.
-otp_10755(doc) ->
- "OTP-10755. The 'l' modifier";
+%% OTP-10755. The 'l' modifier
otp_10755(Suite) when is_list(Suite) ->
S = "string",
"\"string\"" = fmt("~p", [S]),
@@ -2300,7 +1999,7 @@ do_io_with_huge_message_queue(Config) ->
ok;
Q ->
io:format("Q = ~p", [Q]),
- ?t:fail()
+ ct:fail(failed)
end,
ok.
@@ -2373,7 +2072,7 @@ re_fmt(Pattern, Format, Args) ->
nomatch ->
io:format("Pattern: ~s", [Pattern]),
io:format("Result: ~s", [S]),
- ?t:fail();
+ ct:fail(failed);
match ->
ok
end.
diff --git a/lib/stdlib/test/io_proto_SUITE.erl b/lib/stdlib/test/io_proto_SUITE.erl
index 811c7ed7bb..ecd0d44db9 100644
--- a/lib/stdlib/test/io_proto_SUITE.erl
+++ b/lib/stdlib/test/io_proto_SUITE.erl
@@ -39,7 +39,7 @@
-export([uprompt/1]).
-%-define(without_test_server, true).
+%%-define(without_test_server, true).
-ifdef(without_test_server).
-define(line, put(line, ?LINE), ).
@@ -47,8 +47,8 @@
-define(t, test_server).
-define(privdir(_), "./io_SUITE_priv").
-else.
--include_lib("test_server/include/test_server.hrl").
--define(privdir(Conf), ?config(priv_dir, Conf)).
+-include_lib("common_test/include/ct.hrl").
+-define(privdir(Conf), proplists:get_value(priv_dir, Conf)).
-endif.
%%-define(debug, true).
@@ -57,30 +57,25 @@
-define(format(S, A), io:format(S, A)).
-define(dbg(Data),io:format(standard_error, "DBG: ~p\r\n",[Data])).
-define(RM_RF(Dir),begin io:format(standard_error, "Not Removed: ~p\r\n",[Dir]),
- ok end).
+ ok end).
-else.
-define(format(S, A), ok).
-define(dbg(Data),noop).
-define(RM_RF(Dir),rm_rf(Dir)).
-endif.
-
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(20)).
-
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
Term = os:getenv("TERM", "dumb"),
os:putenv("TERM","vt100"),
- [{watchdog, Dog}, {term, Term} | Config].
+ [{term, Term} | Config].
end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- Term = ?config(term,Config),
+ Term = proplists:get_value(term,Config),
os:putenv("TERM",Term),
- test_server:timetrap_cancel(Dog),
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,20}}].
all() ->
[setopts_getopts, unicode_options, unicode_options_gen,
@@ -110,184 +105,175 @@ end_per_group(_GroupName, Config) ->
q = [],
nxt = eof,
mode = list
- }).
+ }).
uprompt(_L) ->
[1050,1072,1082,1074,1086,32,1077,32,85,110,105,99,111,100,101,32,63].
-unicode_prompt(suite) ->
- [];
-unicode_prompt(doc) ->
- ["Test that an Unicode prompt does not crash the shell"];
+%% Test that an Unicode prompt does not crash the shell.
unicode_prompt(Config) when is_list(Config) ->
- ?line PA = filename:dirname(code:which(?MODULE)),
+ PA = filename:dirname(code:which(?MODULE)),
case proplists:get_value(default_shell,Config) of
old ->
ok;
new ->
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline, "shell:prompt_func({io_proto_SUITE,uprompt})."},
- {getline, "default"},
- {putline, "io:get_line('')."},
- {putline, "hej"},
- {getline, "\"hej\\n\""},
- {putline, "io:setopts([{binary,true}])."},
- {getline, "ok"},
- {putline, "io:get_line('')."},
- {putline, "hej"},
- {getline, "<<\"hej\\n\">>"}
- ],[],[],"-pa \""++ PA++"\"")
+ rtnode([{putline,""},
+ {putline, "2."},
+ {getline, "2"},
+ {putline, "shell:prompt_func({io_proto_SUITE,uprompt})."},
+ {getline, "default"},
+ {putline, "io:get_line('')."},
+ {putline, "hej"},
+ {getline, "\"hej\\n\""},
+ {putline, "io:setopts([{binary,true}])."},
+ {getline, "ok"},
+ {putline, "io:get_line('')."},
+ {putline, "hej"},
+ {getline, "<<\"hej\\n\">>"}
+ ],[],[],"-pa \""++ PA++"\"")
end,
%% And one with oldshell
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline_re, ".*2$"},
- {putline, "shell:prompt_func({io_proto_SUITE,uprompt})."},
- {getline_re, ".*default"},
- {putline, "io:get_line('')."},
- {putline, "hej"},
- {getline_re, ".*\"hej\\\\n\""},
- {putline, "io:setopts([{binary,true}])."},
- {getline_re, ".*ok"},
- {putline, "io:get_line('')."},
- {putline, "hej"},
- {getline_re, ".*<<\"hej\\\\n\">>"}
- ],[],[],"-oldshell -pa \""++PA++"\""),
+ rtnode([{putline,""},
+ {putline, "2."},
+ {getline_re, ".*2$"},
+ {putline, "shell:prompt_func({io_proto_SUITE,uprompt})."},
+ {getline_re, ".*default"},
+ {putline, "io:get_line('')."},
+ {putline, "hej"},
+ {getline_re, ".*\"hej\\\\n\""},
+ {putline, "io:setopts([{binary,true}])."},
+ {getline_re, ".*ok"},
+ {putline, "io:get_line('')."},
+ {putline, "hej"},
+ {getline_re, ".*<<\"hej\\\\n\">>"}
+ ],[],[],"-oldshell -pa \""++PA++"\""),
ok.
-
-setopts_getopts(suite) ->
- [];
-setopts_getopts(doc) ->
- ["Check io:setopts and io:getopts functions"];
+
+%% Check io:setopts and io:getopts functions.
setopts_getopts(Config) when is_list(Config) ->
- ?line FileName = filename:join([?config(priv_dir,Config),
- "io_proto_SUITE_setopts_getopts.dat"]),
- ?line {ok,WFile} = file:open(FileName,[write]),
- ?line Server = start_io_server_proxy(),
- ?line [{binary, false}] = io:getopts(Server),
- ?line [getopts] = proxy_getall(Server),
- ?line [{binary,false},{encoding,latin1}] = lists:sort(io:getopts(WFile)),
- ?line proxy_setnext(Server,"Hej"),
- ?line "Hej" = io:get_line(Server,''),
- ?line proxy_setnext(Server,"Hej"++[532]),
- ?line [$H,$e,$j,532] = io:get_line(Server,''),
- ?line ok = io:setopts(Server,[{binary,true}]),
- ?line proxy_setnext(Server,"Hej"),
- ?line <<"Hej">> = io:get_line(Server,''),
- ?line proxy_setnext(Server,"Hej"++[532]),
- ?line <<72,101,106,200,148>> = io:get_line(Server,''),
- ?line [$H,$e,$j,532] = lists:flatten(io_lib:format("~ts",[<<72,101,106,200,148>>])),
- ?line file:write(WFile,<<"HejA">>),
- ?line file:write(WFile,unicode:characters_to_binary("Hej"++[532],unicode,unicode)),
- ?line file:write(WFile,unicode:characters_to_binary("Hej"++[532],unicode,{utf16,big})),
- ?line file:write(WFile,unicode:characters_to_binary("Hej"++[532],unicode,{utf16,little})),
- ?line file:write(WFile,unicode:characters_to_binary("Hej"++[532],unicode,{utf32,big})),
- ?line file:write(WFile,unicode:characters_to_binary("Hej"++[532],unicode,{utf32,little})),
- ?line file:close(WFile),
- ?line {ok,RFile} = file:open(FileName,[read]),
- ?line [{binary,false},{encoding,latin1}] = lists:sort(io:getopts(RFile)),
- ?line [$H,$e,$j,$A] = io:get_chars(RFile,'',4),
- ?line io:setopts(RFile,[{encoding,unicode}]),
- ?line [$H,$e,$j,532] = io:get_chars(RFile,'',4),
- ?line [{binary,false},{encoding,unicode}] = lists:sort(io:getopts(RFile)),
- ?line io:setopts(RFile,[{encoding,{utf16,big}}]),
- ?line [$H,$e,$j,532] = io:get_chars(RFile,'',4),
- ?line [{binary,false},{encoding,{utf16,big}}] =
+ FileName = filename:join([proplists:get_value(priv_dir,Config),
+ "io_proto_SUITE_setopts_getopts.dat"]),
+ {ok,WFile} = file:open(FileName,[write]),
+ Server = start_io_server_proxy(),
+ [{binary, false}] = io:getopts(Server),
+ [getopts] = proxy_getall(Server),
+ [{binary,false},{encoding,latin1}] = lists:sort(io:getopts(WFile)),
+ proxy_setnext(Server,"Hej"),
+ "Hej" = io:get_line(Server,''),
+ proxy_setnext(Server,"Hej"++[532]),
+ [$H,$e,$j,532] = io:get_line(Server,''),
+ ok = io:setopts(Server,[{binary,true}]),
+ proxy_setnext(Server,"Hej"),
+ <<"Hej">> = io:get_line(Server,''),
+ proxy_setnext(Server,"Hej"++[532]),
+ <<72,101,106,200,148>> = io:get_line(Server,''),
+ [$H,$e,$j,532] = lists:flatten(io_lib:format("~ts",[<<72,101,106,200,148>>])),
+ file:write(WFile,<<"HejA">>),
+ file:write(WFile,unicode:characters_to_binary("Hej"++[532],unicode,unicode)),
+ file:write(WFile,unicode:characters_to_binary("Hej"++[532],unicode,{utf16,big})),
+ file:write(WFile,unicode:characters_to_binary("Hej"++[532],unicode,{utf16,little})),
+ file:write(WFile,unicode:characters_to_binary("Hej"++[532],unicode,{utf32,big})),
+ file:write(WFile,unicode:characters_to_binary("Hej"++[532],unicode,{utf32,little})),
+ file:close(WFile),
+ {ok,RFile} = file:open(FileName,[read]),
+ [{binary,false},{encoding,latin1}] = lists:sort(io:getopts(RFile)),
+ [$H,$e,$j,$A] = io:get_chars(RFile,'',4),
+ io:setopts(RFile,[{encoding,unicode}]),
+ [$H,$e,$j,532] = io:get_chars(RFile,'',4),
+ [{binary,false},{encoding,unicode}] = lists:sort(io:getopts(RFile)),
+ io:setopts(RFile,[{encoding,{utf16,big}}]),
+ [$H,$e,$j,532] = io:get_chars(RFile,'',4),
+ [{binary,false},{encoding,{utf16,big}}] =
lists:sort(io:getopts(RFile)),
- ?line io:setopts(RFile,[{encoding,{utf16,little}}]),
- ?line [$H,$e,$j,532] = io:get_chars(RFile,'',4),
- ?line [{binary,false},{encoding,{utf16,little}}] =
+ io:setopts(RFile,[{encoding,{utf16,little}}]),
+ [$H,$e,$j,532] = io:get_chars(RFile,'',4),
+ [{binary,false},{encoding,{utf16,little}}] =
lists:sort(io:getopts(RFile)),
- ?line io:setopts(RFile,[{encoding,{utf32,big}}]),
- ?line [$H,$e,$j,532] = io:get_chars(RFile,'',4),
- ?line [{binary,false},{encoding,{utf32,big}}] =
+ io:setopts(RFile,[{encoding,{utf32,big}}]),
+ [$H,$e,$j,532] = io:get_chars(RFile,'',4),
+ [{binary,false},{encoding,{utf32,big}}] =
lists:sort(io:getopts(RFile)),
- ?line io:setopts(RFile,[{encoding,{utf32,little}}]),
- ?line [$H,$e,$j,532] = io:get_chars(RFile,'',4),
- ?line [{binary,false},{encoding,{utf32,little}}] =
+ io:setopts(RFile,[{encoding,{utf32,little}}]),
+ [$H,$e,$j,532] = io:get_chars(RFile,'',4),
+ [{binary,false},{encoding,{utf32,little}}] =
lists:sort(io:getopts(RFile)),
- ?line eof = io:get_line(RFile,''),
- ?line file:position(RFile,0),
- ?line io:setopts(RFile,[{binary,true},{encoding,latin1}]),
- ?line <<$H,$e,$j,$A>> = io:get_chars(RFile,'',4),
- ?line [{binary,true},{encoding,latin1}] = lists:sort(io:getopts(RFile)),
- ?line io:setopts(RFile,[{encoding,unicode}]),
- ?line <<$H,$e,$j,532/utf8>> = io:get_chars(RFile,'',4),
- ?line [{binary,true},{encoding,unicode}] = lists:sort(io:getopts(RFile)),
- ?line io:setopts(RFile,[{encoding,{utf16,big}}]),
- ?line <<$H,$e,$j,532/utf8>> = io:get_chars(RFile,'',4),
- ?line [{binary,true},{encoding,{utf16,big}}] =
+ eof = io:get_line(RFile,''),
+ file:position(RFile,0),
+ io:setopts(RFile,[{binary,true},{encoding,latin1}]),
+ <<$H,$e,$j,$A>> = io:get_chars(RFile,'',4),
+ [{binary,true},{encoding,latin1}] = lists:sort(io:getopts(RFile)),
+ io:setopts(RFile,[{encoding,unicode}]),
+ <<$H,$e,$j,532/utf8>> = io:get_chars(RFile,'',4),
+ [{binary,true},{encoding,unicode}] = lists:sort(io:getopts(RFile)),
+ io:setopts(RFile,[{encoding,{utf16,big}}]),
+ <<$H,$e,$j,532/utf8>> = io:get_chars(RFile,'',4),
+ [{binary,true},{encoding,{utf16,big}}] =
lists:sort(io:getopts(RFile)),
- ?line io:setopts(RFile,[{encoding,{utf16,little}}]),
- ?line <<$H,$e,$j,532/utf8>> = io:get_chars(RFile,'',4),
- ?line [{binary,true},{encoding,{utf16,little}}] =
+ io:setopts(RFile,[{encoding,{utf16,little}}]),
+ <<$H,$e,$j,532/utf8>> = io:get_chars(RFile,'',4),
+ [{binary,true},{encoding,{utf16,little}}] =
lists:sort(io:getopts(RFile)),
- ?line io:setopts(RFile,[{encoding,{utf32,big}}]),
- ?line <<$H,$e,$j,532/utf8>> = io:get_chars(RFile,'',4),
- ?line [{binary,true},{encoding,{utf32,big}}] =
+ io:setopts(RFile,[{encoding,{utf32,big}}]),
+ <<$H,$e,$j,532/utf8>> = io:get_chars(RFile,'',4),
+ [{binary,true},{encoding,{utf32,big}}] =
lists:sort(io:getopts(RFile)),
- ?line io:setopts(RFile,[{encoding,{utf32,little}}]),
- ?line <<$H,$e,$j,532/utf8>> = io:get_chars(RFile,'',4),
- ?line [{binary,true},{encoding,{utf32,little}}] =
+ io:setopts(RFile,[{encoding,{utf32,little}}]),
+ <<$H,$e,$j,532/utf8>> = io:get_chars(RFile,'',4),
+ [{binary,true},{encoding,{utf32,little}}] =
lists:sort(io:getopts(RFile)),
- ?line eof = io:get_line(RFile,''),
- ?line file:close(RFile),
+ eof = io:get_line(RFile,''),
+ file:close(RFile),
case proplists:get_value(default_shell,Config) of
old ->
ok;
new ->
%% So, lets test another node with new interactive shell
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline, "lists:keyfind(binary,1,io:getopts())."},
- {getline, "{binary,false}"},
- {putline, "io:get_line('')."},
- {putline, "hej"},
- {getline, "\"hej\\n\""},
- {putline, "io:setopts([{binary,true}])."},
- {getline, "ok"},
- {putline, "io:get_line('')."},
- {putline, "hej"},
- {getline, "<<\"hej\\n\">>"}
- ],[])
+ rtnode([{putline,""},
+ {putline, "2."},
+ {getline, "2"},
+ {putline, "lists:keyfind(binary,1,io:getopts())."},
+ {getline, "{binary,false}"},
+ {putline, "io:get_line('')."},
+ {putline, "hej"},
+ {getline, "\"hej\\n\""},
+ {putline, "io:setopts([{binary,true}])."},
+ {getline, "ok"},
+ {putline, "io:get_line('')."},
+ {putline, "hej"},
+ {getline, "<<\"hej\\n\">>"}
+ ],[])
end,
%% And one with oldshell
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline_re, ".*2$"},
- {putline, "lists:keyfind(binary,1,io:getopts())."},
- {getline_re, ".*{binary,false}"},
- {putline, "io:get_line('')."},
- {putline, "hej"},
- {getline_re, ".*\"hej\\\\n\""},
- {putline, "io:setopts([{binary,true}])."},
- {getline_re, ".*ok"},
- {putline, "io:get_line('')."},
- {putline, "hej"},
- {getline_re, ".*<<\"hej\\\\n\">>"}
- ],[],[],"-oldshell"),
+ rtnode([{putline,""},
+ {putline, "2."},
+ {getline_re, ".*2$"},
+ {putline, "lists:keyfind(binary,1,io:getopts())."},
+ {getline_re, ".*{binary,false}"},
+ {putline, "io:get_line('')."},
+ {putline, "hej"},
+ {getline_re, ".*\"hej\\\\n\""},
+ {putline, "io:setopts([{binary,true}])."},
+ {getline_re, ".*ok"},
+ {putline, "io:get_line('')."},
+ {putline, "hej"},
+ {getline_re, ".*<<\"hej\\\\n\">>"}
+ ],[],[],"-oldshell"),
ok.
get_lc_ctype() ->
- case {os:type(),os:version()} of
- {{unix,sunos},{5,N,_}} when N =< 8 ->
- "iso_8859_1";
- _ ->
- "ISO-8859-1"
- end.
-
-unicode_options(suite) ->
- [];
-unicode_options(doc) ->
- ["Tests various unicode options"];
+ case {os:type(),os:version()} of
+ {{unix,sunos},{5,N,_}} when N =< 8 ->
+ "iso_8859_1";
+ _ ->
+ "ISO-8859-1"
+ end.
+
+%% Test various unicode options.
unicode_options(Config) when is_list(Config) ->
- DataDir = ?config(data_dir,Config),
- PrivDir = ?config(priv_dir,Config),
+ DataDir = proplists:get_value(data_dir,Config),
+ PrivDir = proplists:get_value(priv_dir,Config),
%% A string in both russian and greek characters, which is present
%% in all the internal test files (but in different formats of course)...
TestData = [1090,1093,1077,32,1073,1080,1075,32,
@@ -322,13 +308,10 @@ unicode_options(Config) when is_list(Config) ->
"external_utf16_little_bom.dat",
"external_utf16_big_bom.dat"],
ReadBomFile = fun(File,Dir) ->
- %io:format(standard_error,"~s\r\n",[filename:join([Dir,File])]),
{ok,F} = file:open(filename:join([Dir,File]),
[read,binary]),
{ok,Bin} = file:read(F,4),
{Type,Bytes} = unicode:bom_to_encoding(Bin),
- %io:format(standard_error,"~p\r\n",[{Type,Bytes}]),
-
file:position(F,Bytes),
io:setopts(F,[{encoding,Type}]),
R = unicode:characters_to_list(
@@ -346,26 +329,26 @@ unicode_options(Config) when is_list(Config) ->
R
end,
ReadBomlessFileList = fun({Type,File},DataLen,Dir) ->
- {ok,F} = file:open(filename:join([Dir,File]),
- [read,
- {encoding,Type}]),
- R = io:get_chars(F,'',DataLen),
- file:close(F),
- R
- end,
+ {ok,F} = file:open(filename:join([Dir,File]),
+ [read,
+ {encoding,Type}]),
+ R = io:get_chars(F,'',DataLen),
+ file:close(F),
+ R
+ end,
ReadBomlessFileListLine = fun({Type,File},Dir) ->
- {ok,F} = file:open(filename:join([Dir,File]),
- [read,
- {encoding,Type}]),
- R = io:get_line(F,''),
- file:close(F),
- R
- end,
- ?line [TestData = ReadBomFile(F,DataDir) || F <- InternalBomFiles ],
- ?line [ExternalTestData = ReadBomFile(F,DataDir) || F <- ExternalBomFiles ],
- ?line [TestData = ReadBomlessFile(F,length(TestData),DataDir) || F <- AllNoBom ],
- ?line [TestData = ReadBomlessFileList(F,length(TestData),DataDir) || F <- AllNoBom ],
- ?line [TestData = ReadBomlessFileListLine(F,DataDir) || F <- AllNoBom ],
+ {ok,F} = file:open(filename:join([Dir,File]),
+ [read,
+ {encoding,Type}]),
+ R = io:get_line(F,''),
+ file:close(F),
+ R
+ end,
+ [TestData = ReadBomFile(F,DataDir) || F <- InternalBomFiles ],
+ [ExternalTestData = ReadBomFile(F,DataDir) || F <- ExternalBomFiles ],
+ [TestData = ReadBomlessFile(F,length(TestData),DataDir) || F <- AllNoBom ],
+ [TestData = ReadBomlessFileList(F,length(TestData),DataDir) || F <- AllNoBom ],
+ [TestData = ReadBomlessFileListLine(F,DataDir) || F <- AllNoBom ],
BomDir = filename:join([PrivDir,"BOMDATA"]),
BomlessDir = filename:join([PrivDir,"BOMLESSDATA"]),
@@ -381,8 +364,8 @@ unicode_options(Config) when is_list(Config) ->
file:close(F),
ok
end,
- ?line [ ok = WriteBomFile(F,BomDir) || F <- AllNoBom ],
- ?line [TestData = ReadBomFile(F,BomDir) || {_,F} <- AllNoBom ],
+ [ ok = WriteBomFile(F,BomDir) || F <- AllNoBom ],
+ [TestData = ReadBomFile(F,BomDir) || {_,F} <- AllNoBom ],
WriteBomlessFile = fun({Enc,File},TData,Dir) ->
{ok,F} = file:open(
filename:join([Dir,File]),
@@ -391,13 +374,13 @@ unicode_options(Config) when is_list(Config) ->
file:close(F),
ok
end,
- ?line [ ok = WriteBomlessFile(F,TestData,BomlessDir) || F <- AllNoBom ],
- ?line [TestData = ReadBomlessFile(F,length(TestData),BomlessDir) || F <- AllNoBom ],
- ?line [TestData = ReadBomlessFileList(F,length(TestData),BomlessDir) || F <- AllNoBom ],
- ?line [TestData = ReadBomlessFileListLine(F,BomlessDir) || F <- AllNoBom ],
-
+ [ ok = WriteBomlessFile(F,TestData,BomlessDir) || F <- AllNoBom ],
+ [TestData = ReadBomlessFile(F,length(TestData),BomlessDir) || F <- AllNoBom ],
+ [TestData = ReadBomlessFileList(F,length(TestData),BomlessDir) || F <- AllNoBom ],
+ [TestData = ReadBomlessFileListLine(F,BomlessDir) || F <- AllNoBom ],
+
CannotReadFile = fun({Enc,File},Dir) ->
- %io:format(standard_error,"~s\r\n",[filename:join([Dir,File])]),
+ %%io:format(standard_error,"~s\r\n",[filename:join([Dir,File])]),
{ok,F} = file:open(
filename:join([Dir,File]),
[read,binary,{encoding,Enc}]),
@@ -414,14 +397,14 @@ unicode_options(Config) when is_list(Config) ->
{error,terminated} = io:get_chars(F,'',10),
ok
end,
- ?line [ ok = CannotReadFile(F,DataDir) || F <- AllNoBom ],
- ?line [ ok = CannotReadFile(F,BomlessDir) || F <- AllNoBom ],
- ?line [ ok = CannotReadFile(F,BomDir) || F <- AllNoBom ],
+ [ ok = CannotReadFile(F,DataDir) || F <- AllNoBom ],
+ [ ok = CannotReadFile(F,BomlessDir) || F <- AllNoBom ],
+ [ ok = CannotReadFile(F,BomDir) || F <- AllNoBom ],
- ?line [ ok = WriteBomlessFile(F,TestData2,BomlessDir) || F <- AllNoBom ],
- ?line [TestData2 = ReadBomlessFile(F,length(TestData2),BomlessDir) || F <- AllNoBom ],
- ?line [TestData2 = ReadBomlessFileList(F,length(TestData2),BomlessDir) || F <- AllNoBom ],
- ?line [TestData2 = ReadBomlessFileListLine(F,BomlessDir) || F <- AllNoBom ],
+ [ ok = WriteBomlessFile(F,TestData2,BomlessDir) || F <- AllNoBom ],
+ [TestData2 = ReadBomlessFile(F,length(TestData2),BomlessDir) || F <- AllNoBom ],
+ [TestData2 = ReadBomlessFileList(F,length(TestData2),BomlessDir) || F <- AllNoBom ],
+ [TestData2 = ReadBomlessFileListLine(F,BomlessDir) || F <- AllNoBom ],
FailDir = filename:join([PrivDir,"FAIL"]),
@@ -431,56 +414,56 @@ unicode_options(Config) when is_list(Config) ->
{ok,F} = file:open(
filename:join([Dir,File]),
[write,binary]),
- ?line {'EXIT', {no_translation,_}} =
+ {'EXIT', {no_translation,_}} =
(catch io:put_chars(F,TestData)),
- ?line {'EXIT', {terminated,_}} = (catch io:put_chars(F,TestData)),
+ {'EXIT', {terminated,_}} = (catch io:put_chars(F,TestData)),
ok
end,
- ?line [ ok = CannotWriteFile(F,FailDir) || F <- AllNoBom ],
+ [ ok = CannotWriteFile(F,FailDir) || F <- AllNoBom ],
case proplists:get_value(default_shell,Config) of
old ->
ok;
new ->
%% OK, time for the group_leaders...
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline, "lists:keyfind(encoding,1,io:getopts())."},
- {getline, "{encoding,latin1}"},
- {putline, "io:format(\"~ts~n\",[[1024]])."},
- {getline, "\\x{400}"},
- {putline, "io:setopts([unicode])."},
- {getline, "ok"},
- {putline, "io:format(\"~ts~n\",[[1024]])."},
- {getline,
- binary_to_list(unicode:characters_to_binary(
- [1024],unicode,utf8))}
- ],[],"LC_CTYPE=\""++get_lc_ctype()++"\"; "
- "export LC_CTYPE; ")
+ rtnode([{putline,""},
+ {putline, "2."},
+ {getline, "2"},
+ {putline, "lists:keyfind(encoding,1,io:getopts())."},
+ {getline, "{encoding,latin1}"},
+ {putline, "io:format(\"~ts~n\",[[1024]])."},
+ {getline, "\\x{400}"},
+ {putline, "io:setopts([unicode])."},
+ {getline, "ok"},
+ {putline, "io:format(\"~ts~n\",[[1024]])."},
+ {getline,
+ binary_to_list(unicode:characters_to_binary(
+ [1024],unicode,utf8))}
+ ],[],"LC_CTYPE=\""++get_lc_ctype()++"\"; "
+ "export LC_CTYPE; ")
end,
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline_re, ".*2$"},
- {putline, "lists:keyfind(encoding,1,io:getopts())."},
- {getline_re, ".*{encoding,latin1}"},
- {putline, "io:format(\"~ts~n\",[[1024]])."},
- {getline_re, ".*\\\\x{400\\}"},
- {putline, "io:setopts([{encoding,unicode}])."},
- {getline_re, ".*ok"},
- {putline, "io:format(\"~ts~n\",[[1024]])."},
- {getline_re,
- ".*"++binary_to_list(unicode:characters_to_binary(
- [1024],unicode,utf8))}
- ],[],"LC_CTYPE=\""++get_lc_ctype()++"\"; export LC_CTYPE; ",
- " -oldshell "),
+ rtnode([{putline,""},
+ {putline, "2."},
+ {getline_re, ".*2$"},
+ {putline, "lists:keyfind(encoding,1,io:getopts())."},
+ {getline_re, ".*{encoding,latin1}"},
+ {putline, "io:format(\"~ts~n\",[[1024]])."},
+ {getline_re, ".*\\\\x{400\\}"},
+ {putline, "io:setopts([{encoding,unicode}])."},
+ {getline_re, ".*ok"},
+ {putline, "io:format(\"~ts~n\",[[1024]])."},
+ {getline_re,
+ ".*"++binary_to_list(unicode:characters_to_binary(
+ [1024],unicode,utf8))}
+ ],[],"LC_CTYPE=\""++get_lc_ctype()++"\"; export LC_CTYPE; ",
+ " -oldshell "),
ok.
-
+
%% Tests various unicode options on random generated files.
unicode_options_gen(Config) when is_list(Config) ->
random:seed(1240, 900586, 553728),
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
AllModes = [utf8,utf16,{utf16,big},{utf16,little},
utf32,{utf32,big},{utf32,little}],
FSize = 9*1024,
@@ -621,7 +604,7 @@ do_read_whole_file(Fname, Options, Fun) ->
Res = do_read_whole_file_1(Fun, F),
ok = file:close(F),
unicode:characters_to_list(Res, unicode).
-
+
do_read_whole_file_1(Fun, F) ->
case Fun(F) of
eof ->
@@ -646,7 +629,7 @@ do_write_read_file(Fname, Options, Encoding, Writer) ->
{ok,Bin} = file:read_file(Fname),
ok = file:delete(Fname),
Bin.
-
+
enc2str(Atom) when is_atom(Atom) ->
atom_to_list(Atom);
enc2str({A1,A2}) when is_atom(A1), is_atom(A2) ->
@@ -656,14 +639,14 @@ enc2str({A1,A2}) when is_atom(A1), is_atom(A2) ->
random_unicode(0) ->
[];
random_unicode(N) ->
- % Favour large unicode and make linebreaks
+ %% Favour large unicode and make linebreaks
X = case random:uniform(20) of
- A when A =< 1 -> $\n;
- A0 when A0 =< 3 -> random:uniform(16#10FFFF);
- A1 when A1 =< 6 -> random:uniform(16#10FFFF - 16#7F) + 16#7F;
- A2 when A2 =< 12 -> random:uniform(16#10FFFF - 16#7FF) + 16#7FF;
- _ -> random:uniform(16#10FFFF - 16#FFFF) + 16#FFFF
- end,
+ A when A =< 1 -> $\n;
+ A0 when A0 =< 3 -> random:uniform(16#10FFFF);
+ A1 when A1 =< 6 -> random:uniform(16#10FFFF - 16#7F) + 16#7F;
+ A2 when A2 =< 12 -> random:uniform(16#10FFFF - 16#7FF) + 16#7FF;
+ _ -> random:uniform(16#10FFFF - 16#FFFF) + 16#FFFF
+ end,
case X of
Inv1 when Inv1 >= 16#D800, Inv1 =< 16#DFFF;
Inv1 =:= 16#FFFE;
@@ -672,15 +655,12 @@ random_unicode(N) ->
_ ->
[X | random_unicode(N-1)]
end.
-
-binary_options(suite) ->
- [];
-binary_options(doc) ->
- ["Tests variants with binary option"];
+
+%% Test variants with binary option.
binary_options(Config) when is_list(Config) ->
- DataDir = ?config(data_dir,Config),
- PrivDir = ?config(priv_dir,Config),
+ DataDir = proplists:get_value(data_dir,Config),
+ PrivDir = proplists:get_value(priv_dir,Config),
TestData = unicode:characters_to_binary(
[1090,1093,1077,32,1073,1080,1075,32,
1088,1077,1076,32,1092,1086,1100,32,1093,
@@ -691,84 +671,79 @@ binary_options(Config) when is_list(Config) ->
First10List = binary_to_list(First10),
Second10List = binary_to_list(Second10),
TestFile = filename:join([DataDir, "testdata_utf8.dat"]),
- ?line {ok, F} = file:open(TestFile,[read]),
- ?line {ok, First10List} = file:read(F,10),
- ?line io:setopts(F,[binary]),
- ?line {ok, Second10} = file:read(F,10),
- ?line file:close(F),
- ?line {ok, F2} = file:open(TestFile,[read,binary]),
- ?line {ok, First10} = file:read(F2,10),
- ?line io:setopts(F2,[list]),
- ?line {ok, Second10List} = file:read(F2,10),
- ?line file:position(F2,0),
- %dbg:tracer(),dbg:p(F2,call),dbg:tpl(file_io_server,x),
- ?line First10List = io:get_chars(F2,'',10),
- ?line io:setopts(F2,[binary]),
- ?line Second10 = unicode:characters_to_binary(io:get_chars(F2,'',10),unicode,latin1),
- ?line file:close(F2),
- ?line LineBreakFileName = filename:join([PrivDir, "testdata.dat"]),
- ?line LineBreakTestData = <<TestData/binary,$\n>>,
- ?line LineBreakTestDataList = binary_to_list(LineBreakTestData),
- ?line file:write_file(LineBreakFileName,[LineBreakTestData,LineBreakTestData,LineBreakTestData,TestData]),
- ?line {ok, F3} = file:open(LineBreakFileName,[read]),
- ?line LineBreakTestDataList = io:get_line(F3,''),
- ?line io:setopts(F3,[binary]),
- ?line LineBreakTestData = unicode:characters_to_binary(io:get_line(F3,''),unicode,latin1),
- ?line io:setopts(F3,[list]),
- ?line LineBreakTestDataList = io:get_line(F3,''),
- ?line io:setopts(F3,[binary]),
- %ok = io:format(standard_error,"TestData = ~w~n",[TestData]),
- ?line TestData = unicode:characters_to_binary(io:get_line(F3,''),unicode,latin1),
- ?line eof = io:get_line(F3,''),
- ?line file:close(F3),
+ {ok, F} = file:open(TestFile,[read]),
+ {ok, First10List} = file:read(F,10),
+ io:setopts(F,[binary]),
+ {ok, Second10} = file:read(F,10),
+ file:close(F),
+ {ok, F2} = file:open(TestFile,[read,binary]),
+ {ok, First10} = file:read(F2,10),
+ io:setopts(F2,[list]),
+ {ok, Second10List} = file:read(F2,10),
+ file:position(F2,0),
+ First10List = io:get_chars(F2,'',10),
+ io:setopts(F2,[binary]),
+ Second10 = unicode:characters_to_binary(io:get_chars(F2,'',10),unicode,latin1),
+ file:close(F2),
+ LineBreakFileName = filename:join([PrivDir, "testdata.dat"]),
+ LineBreakTestData = <<TestData/binary,$\n>>,
+ LineBreakTestDataList = binary_to_list(LineBreakTestData),
+ file:write_file(LineBreakFileName,[LineBreakTestData,LineBreakTestData,LineBreakTestData,TestData]),
+ {ok, F3} = file:open(LineBreakFileName,[read]),
+ LineBreakTestDataList = io:get_line(F3,''),
+ io:setopts(F3,[binary]),
+ LineBreakTestData = unicode:characters_to_binary(io:get_line(F3,''),unicode,latin1),
+ io:setopts(F3,[list]),
+ LineBreakTestDataList = io:get_line(F3,''),
+ io:setopts(F3,[binary]),
+ TestData = unicode:characters_to_binary(io:get_line(F3,''),unicode,latin1),
+ eof = io:get_line(F3,''),
+ file:close(F3),
+
%% OK, time for the group_leaders...
- %% io:format(standard_error,"Hmmm:~w~n",["<<\""++binary_to_list(<<"\345\344\366"/utf8>>)++"\\n\">>"]),
case proplists:get_value(default_shell,Config) of
old ->
ok;
new ->
- ?line rtnode([{putline, "2."},
- {getline, "2"},
- {putline, "lists:keyfind(binary,1,io:getopts())."},
- {getline, "{binary,false}"},
- {putline, "io:get_line('')."},
- {putline, "hej"},
- {getline, "\"hej\\n\""},
- {putline, "io:setopts([{binary,true},unicode])."},
- {getline, "ok"},
- {putline, "io:get_line('')."},
- {putline, "hej"},
- {getline, "<<\"hej\\n\">>"},
- {putline, "io:get_line('')."},
- {putline, binary_to_list(<<"\345\344\366"/utf8>>)},
- {getline, "<<\""++binary_to_list(<<"\345\344\366"/utf8>>)++"\\n\"/utf8>>"}
- ],[])
+ rtnode([{putline, "2."},
+ {getline, "2"},
+ {putline, "lists:keyfind(binary,1,io:getopts())."},
+ {getline, "{binary,false}"},
+ {putline, "io:get_line('')."},
+ {putline, "hej"},
+ {getline, "\"hej\\n\""},
+ {putline, "io:setopts([{binary,true},unicode])."},
+ {getline, "ok"},
+ {putline, "io:get_line('')."},
+ {putline, "hej"},
+ {getline, "<<\"hej\\n\">>"},
+ {putline, "io:get_line('')."},
+ {putline, binary_to_list(<<"\345\344\366"/utf8>>)},
+ {getline, "<<\""++binary_to_list(<<"\345\344\366"/utf8>>)++"\\n\"/utf8>>"}
+ ],[])
end,
- %% And one with oldshell
- ?line rtnode([{putline, "2."},
- {getline_re, ".*2$"},
- {putline, "lists:keyfind(binary,1,io:getopts())."},
- {getline_re, ".*{binary,false}"},
- {putline, "io:get_line('')."},
- {putline, "hej"},
- {getline_re, ".*\"hej\\\\n\""},
- {putline, "io:setopts([{binary,true},unicode])."},
- {getline_re, ".*ok"},
- {putline, "io:get_line('')."},
- {putline, "hej"},
- {getline_re, ".*<<\"hej\\\\n\">>"},
- {putline, "io:get_line('')."},
- {putline, binary_to_list(<<"\345\344\366"/utf8>>)},
- {getline_re, ".*<<\""++binary_to_list(<<"\345\344\366"/utf8>>)++"\\\\n\"/utf8>>"}
- ],[],[],"-oldshell"),
+ %% And one with oldshell
+ rtnode([{putline, "2."},
+ {getline_re, ".*2$"},
+ {putline, "lists:keyfind(binary,1,io:getopts())."},
+ {getline_re, ".*{binary,false}"},
+ {putline, "io:get_line('')."},
+ {putline, "hej"},
+ {getline_re, ".*\"hej\\\\n\""},
+ {putline, "io:setopts([{binary,true},unicode])."},
+ {getline_re, ".*ok"},
+ {putline, "io:get_line('')."},
+ {putline, "hej"},
+ {getline_re, ".*<<\"hej\\\\n\">>"},
+ {putline, "io:get_line('')."},
+ {putline, binary_to_list(<<"\345\344\366"/utf8>>)},
+ {getline_re, ".*<<\""++binary_to_list(<<"\345\344\366"/utf8>>)++"\\\\n\"/utf8>>"}
+ ],[],[],"-oldshell"),
ok.
-bc_with_r12(suite) ->
- [];
-bc_with_r12(doc) ->
- ["Test io protocol compatibility with R12 nodes"];
+%% Test io protocol compatibility with R12 nodes.
bc_with_r12(Config) when is_list(Config) ->
- case ?t:is_release_available("r12b") of
+ case test_server:is_release_available("r12b") of
true -> bc_with_r12_1(Config);
false -> {skip,"No R12B found"}
end.
@@ -776,135 +751,134 @@ bc_with_r12(Config) when is_list(Config) ->
bc_with_r12_1(Config) ->
PA = filename:dirname(code:which(?MODULE)),
Name1 = io_proto_r12_1,
- ?line N1 = list_to_atom(atom_to_list(Name1) ++ "@" ++ hostname()),
- ?line ?t:start_node(Name1, peer, [{args, "-pz \""++PA++"\""},{erl,[{release,"r12b"}]}]),
- DataDir = ?config(data_dir,Config),
- %PrivDir = ?config(priv_dir,Config),
+ N1 = list_to_atom(atom_to_list(Name1) ++ "@" ++ hostname()),
+ test_server:start_node(Name1, peer, [{args, "-pz \""++PA++"\""},
+ {erl,[{release,"r12b"}]}]),
+ DataDir = proplists:get_value(data_dir,Config),
FileName1 = filename:join([DataDir,"testdata_latin1.dat"]),
TestDataLine1 = [229,228,246],
TestDataLine2 = [197,196,214],
- ?line SPid1 = rpc:call(N1,erlang,spawn,[?MODULE,hold_the_line,[self(),FileName1,[read]]]),
- ?line {ok,F1} = receive
- {SPid1,Res1} ->
- Res1
- after 5000 ->
- exit(timeout)
- end,
- ?line TestDataLine1 = chomp(io:get_line(F1,'')),
- ?line SPid1 ! die,
+ SPid1 = rpc:call(N1,erlang,spawn,[?MODULE,hold_the_line,[self(),FileName1,[read]]]),
+ {ok,F1} = receive
+ {SPid1,Res1} ->
+ Res1
+ after 5000 ->
+ exit(timeout)
+ end,
+ TestDataLine1 = chomp(io:get_line(F1,'')),
+ SPid1 ! die,
receive after 1000 -> ok end,
- ?line SPid2 = rpc:call(N1,erlang,spawn,[?MODULE,hold_the_line,[self(),FileName1,[read,binary]]]),
- ?line {ok,F2} = receive
- {SPid2,Res2} ->
- Res2
- after 5000 ->
- exit(timeout)
- end,
+ SPid2 = rpc:call(N1,erlang,spawn,[?MODULE,hold_the_line,[self(),FileName1,[read,binary]]]),
+ {ok,F2} = receive
+ {SPid2,Res2} ->
+ Res2
+ after 5000 ->
+ exit(timeout)
+ end,
TestDataLine1BinUtf = unicode:characters_to_binary(TestDataLine1),
TestDataLine1BinLatin = list_to_binary(TestDataLine1),
TestDataLine2BinUtf = unicode:characters_to_binary(TestDataLine2),
TestDataLine2BinLatin = list_to_binary(TestDataLine2),
- ?line TestDataLine1BinUtf = chomp(io:get_line(F2,'')),
- ?line TestDataLine2BinUtf = chomp(io:get_line(F2,'')),
- %io:format(standard_error,"Exec:~s\r\n",[rpc:call(N1,os,find_executable,["erl"])]),
- %io:format(standard_error,"Io:~s\r\n",[rpc:call(N1,code,which,[io])]),
- %io:format(standard_error,"File_io_server:~s\r\n",[rpc:call(N1,code,which,[file_io_server])]),
- ?line file:position(F2,0),
- ?line TestDataLine1BinLatin = chomp(rpc:call(N1,io,get_line,[F2,''])),
- ?line TestDataLine2BinUtf = chomp(io:get_line(F2,'')),
- ?line file:position(F2,0),
- ?line TestDataLine1BinUtf = chomp(io:get_line(F2,'')),
- ?line TestDataLine2BinLatin = chomp(rpc:call(N1,io,get_line,[F2,''])),
- ?line eof = chomp(rpc:call(N1,io,get_line,[F2,''])),
- ?line file:position(F2,0),
- ?line TestDataLine1BinLatin = rpc:call(N1,io,get_chars,[F2,'',3]),
+ TestDataLine1BinUtf = chomp(io:get_line(F2,'')),
+ TestDataLine2BinUtf = chomp(io:get_line(F2,'')),
+ %%io:format(standard_error,"Exec:~s\r\n",[rpc:call(N1,os,find_executable,["erl"])]),
+ %%io:format(standard_error,"Io:~s\r\n",[rpc:call(N1,code,which,[io])]),
+ %%io:format(standard_error,"File_io_server:~s\r\n",[rpc:call(N1,code,which,[file_io_server])]),
+ file:position(F2,0),
+ TestDataLine1BinLatin = chomp(rpc:call(N1,io,get_line,[F2,''])),
+ TestDataLine2BinUtf = chomp(io:get_line(F2,'')),
+ file:position(F2,0),
+ TestDataLine1BinUtf = chomp(io:get_line(F2,'')),
+ TestDataLine2BinLatin = chomp(rpc:call(N1,io,get_line,[F2,''])),
+ eof = chomp(rpc:call(N1,io,get_line,[F2,''])),
+ file:position(F2,0),
+ TestDataLine1BinLatin = rpc:call(N1,io,get_chars,[F2,'',3]),
io:get_chars(F2,'',1),
- ?line TestDataLine2BinLatin = chomp(rpc:call(N1,io,get_line,[F2,''])),
- ?line file:position(F2,0),
- ?line {ok,[TestDataLine1]} = io:fread(F2,'',"~s"),
- ?line {ok,[TestDataLine2]} = rpc:call(N1,io,fread,[F2,'',"~s"]),
-
- ?line DataLen1 = length(TestDataLine1),
- ?line DataLen2 = length(TestDataLine2),
-
- ?line file:position(F2,0),
- ?line {ok,TestDataLine1BinLatin} = file:read(F2,DataLen1),
- ?line {ok,_} = file:read(F2,1),
- ?line {ok,TestDataLine2BinLatin} = rpc:call(N1,file,read,[F2,DataLen2]),
- ?line {ok,_} = file:read(F2,1),
- ?line eof = rpc:call(N1,file,read,[F2,1]),
+ TestDataLine2BinLatin = chomp(rpc:call(N1,io,get_line,[F2,''])),
+ file:position(F2,0),
+ {ok,[TestDataLine1]} = io:fread(F2,'',"~s"),
+ {ok,[TestDataLine2]} = rpc:call(N1,io,fread,[F2,'',"~s"]),
+
+ DataLen1 = length(TestDataLine1),
+ DataLen2 = length(TestDataLine2),
+
+ file:position(F2,0),
+ {ok,TestDataLine1BinLatin} = file:read(F2,DataLen1),
+ {ok,_} = file:read(F2,1),
+ {ok,TestDataLine2BinLatin} = rpc:call(N1,file,read,[F2,DataLen2]),
+ {ok,_} = file:read(F2,1),
+ eof = rpc:call(N1,file,read,[F2,1]),
%% As r12 has a bug when setting options with setopts, we need
%% to reopen the file...
- ?line SPid2 ! die,
+ SPid2 ! die,
receive after 1000 -> ok end,
- ?line SPid3 = rpc:call(N1,erlang,spawn,[?MODULE,hold_the_line,[self(),FileName1,[read]]]),
- ?line {ok,F3} = receive
- {SPid3,Res3} ->
- Res3
- after 5000 ->
- exit(timeout)
- end,
-
- ?line file:position(F3,0),
- ?line {ok,[TestDataLine1]} = io:fread(F3,'',"~s"),
- ?line {ok,[TestDataLine2]} = rpc:call(N1,io,fread,[F3,'',"~s"]),
-
-
- ?line file:position(F3,0),
- ?line {ok,TestDataLine1} = file:read(F3,DataLen1),
- ?line {ok,_} = file:read(F3,1),
- ?line {ok,TestDataLine2} = rpc:call(N1,file,read,[F3,DataLen2]),
- ?line {ok,_} = file:read(F3,1),
- ?line eof = rpc:call(N1,file,read,[F3,1]),
-
+ SPid3 = rpc:call(N1,erlang,spawn,[?MODULE,hold_the_line,[self(),FileName1,[read]]]),
+ {ok,F3} = receive
+ {SPid3,Res3} ->
+ Res3
+ after 5000 ->
+ exit(timeout)
+ end,
+
+ file:position(F3,0),
+ {ok,[TestDataLine1]} = io:fread(F3,'',"~s"),
+ {ok,[TestDataLine2]} = rpc:call(N1,io,fread,[F3,'',"~s"]),
+
+
+ file:position(F3,0),
+ {ok,TestDataLine1} = file:read(F3,DataLen1),
+ {ok,_} = file:read(F3,1),
+ {ok,TestDataLine2} = rpc:call(N1,file,read,[F3,DataLen2]),
+ {ok,_} = file:read(F3,1),
+ eof = rpc:call(N1,file,read,[F3,1]),
+
%% So, lets do it all again, but the other way around
{ok,F4} = file:open(FileName1,[read]),
- ?line TestDataLine1 = chomp(io:get_line(F4,'')),
- ?line file:position(F4,0),
- ?line io:setopts(F4,[binary]),
- ?line TestDataLine1BinUtf = chomp(io:get_line(F4,'')),
- ?line TestDataLine2BinUtf = chomp(io:get_line(F4,'')),
- ?line file:position(F4,0),
- ?line TestDataLine1BinUtf = chomp(io:get_line(F4,'')),
- ?line TestDataLine2BinUtf = chomp(io:get_line(F4,'')),
- ?line file:position(F4,0),
- %dbg:tracer(),dbg:p(F4,[call,m]),dbg:tpl(file_io_server,x),dbg:tpl(io_lib,x),
- ?line TestDataLine1BinUtf = chomp(io:get_line(F4,'')),
- ?line TestDataLine2BinLatin = chomp(rpc:call(N1,io,get_line,[F4,''])),
- ?line file:position(F4,0),
- ?line TestDataLine1BinLatin = chomp(rpc:call(N1,io,get_line,[F4,''])),
- ?line TestDataLine2BinUtf = chomp(io:get_line(F4,'')),
- ?line eof = chomp(rpc:call(N1,io,get_line,[F4,''])),
- ?line file:position(F4,0),
- ?line TestDataLine1BinLatin = rpc:call(N1,io,get_chars,[F4,'',3]),
+ TestDataLine1 = chomp(io:get_line(F4,'')),
+ file:position(F4,0),
+ io:setopts(F4,[binary]),
+ TestDataLine1BinUtf = chomp(io:get_line(F4,'')),
+ TestDataLine2BinUtf = chomp(io:get_line(F4,'')),
+ file:position(F4,0),
+ TestDataLine1BinUtf = chomp(io:get_line(F4,'')),
+ TestDataLine2BinUtf = chomp(io:get_line(F4,'')),
+ file:position(F4,0),
+ TestDataLine1BinUtf = chomp(io:get_line(F4,'')),
+ TestDataLine2BinLatin = chomp(rpc:call(N1,io,get_line,[F4,''])),
+ file:position(F4,0),
+ TestDataLine1BinLatin = chomp(rpc:call(N1,io,get_line,[F4,''])),
+ TestDataLine2BinUtf = chomp(io:get_line(F4,'')),
+ eof = chomp(rpc:call(N1,io,get_line,[F4,''])),
+ file:position(F4,0),
+ TestDataLine1BinLatin = rpc:call(N1,io,get_chars,[F4,'',3]),
io:get_chars(F4,'',1),
- ?line TestDataLine2BinLatin = chomp(rpc:call(N1,io,get_line,[F4,''])),
- ?line file:position(F4,0),
- ?line {ok,[TestDataLine1]} = io:fread(F4,'',"~s"),
- ?line {ok,[TestDataLine2]} = rpc:call(N1,io,fread,[F4,'',"~s"]),
- ?line file:position(F4,0),
- ?line {ok,TestDataLine1BinLatin} = file:read(F4,DataLen1),
- ?line {ok,_} = file:read(F4,1),
- ?line {ok,TestDataLine2BinLatin} = rpc:call(N1,file,read,[F4,DataLen2]),
- ?line {ok,_} = file:read(F4,1),
- ?line eof = rpc:call(N1,file,read,[F4,1]),
- ?line io:setopts(F4,[list]),
-
- ?line file:position(F4,0),
- ?line {ok,[TestDataLine1]} = io:fread(F4,'',"~s"),
- ?line {ok,[TestDataLine2]} = rpc:call(N1,io,fread,[F4,'',"~s"]),
-
-
- ?line file:position(F4,0),
- ?line {ok,TestDataLine1} = file:read(F4,DataLen1),
- ?line {ok,_} = file:read(F4,1),
- ?line {ok,TestDataLine2} = rpc:call(N1,file,read,[F4,DataLen2]),
- ?line {ok,_} = file:read(F4,1),
- ?line eof = rpc:call(N1,file,read,[F4,1]),
-
+ TestDataLine2BinLatin = chomp(rpc:call(N1,io,get_line,[F4,''])),
+ file:position(F4,0),
+ {ok,[TestDataLine1]} = io:fread(F4,'',"~s"),
+ {ok,[TestDataLine2]} = rpc:call(N1,io,fread,[F4,'',"~s"]),
+ file:position(F4,0),
+ {ok,TestDataLine1BinLatin} = file:read(F4,DataLen1),
+ {ok,_} = file:read(F4,1),
+ {ok,TestDataLine2BinLatin} = rpc:call(N1,file,read,[F4,DataLen2]),
+ {ok,_} = file:read(F4,1),
+ eof = rpc:call(N1,file,read,[F4,1]),
+ io:setopts(F4,[list]),
+
+ file:position(F4,0),
+ {ok,[TestDataLine1]} = io:fread(F4,'',"~s"),
+ {ok,[TestDataLine2]} = rpc:call(N1,io,fread,[F4,'',"~s"]),
+
+
+ file:position(F4,0),
+ {ok,TestDataLine1} = file:read(F4,DataLen1),
+ {ok,_} = file:read(F4,1),
+ {ok,TestDataLine2} = rpc:call(N1,file,read,[F4,DataLen2]),
+ {ok,_} = file:read(F4,1),
+ eof = rpc:call(N1,file,read,[F4,1]),
+
file:close(F4),
- ?t:stop_node(N1),
+ test_server:stop_node(N1),
ok.
hold_the_line(Parent,Filename,Options) ->
@@ -913,14 +887,11 @@ hold_the_line(Parent,Filename,Options) ->
die ->
ok
end.
-
-bc_with_r12_gl(suite) ->
- [];
-bc_with_r12_gl(doc) ->
- ["Test io protocol compatibility with R12 nodes (terminals)"];
+
+%% Test io protocol compatibility with R12 nodes (terminals).
bc_with_r12_gl(Config) when is_list(Config) ->
- case ?t:is_release_available("r12b") of
+ case test_server:is_release_available("r12b") of
true ->
case get_progs() of
{error,Reason} ->
@@ -932,12 +903,9 @@ bc_with_r12_gl(Config) when is_list(Config) ->
{skip,"No R12B found"}
end.
-bc_with_r12_ogl(suite) ->
- [];
-bc_with_r12_ogl(doc) ->
- ["Test io protocol compatibility with R12 nodes (oldshell)"];
+%% Test io protocol compatibility with R12 nodes (oldshell).
bc_with_r12_ogl(Config) when is_list(Config) ->
- case ?t:is_release_available("r12b") of
+ case test_server:is_release_available("r12b") of
true ->
case get_progs() of
{error,Reason} ->
@@ -952,8 +920,9 @@ bc_with_r12_ogl(Config) when is_list(Config) ->
bc_with_r12_gl_1(_Config,Machine) ->
PA = filename:dirname(code:which(?MODULE)),
Name1 = io_proto_r12_gl_1,
- ?line N1 = list_to_atom(atom_to_list(Name1) ++ "@" ++ hostname()),
- ?line ?t:start_node(Name1, peer, [{args, "-pz \""++PA++"\""},{erl,[{release,"r12b"}]}]),
+ N1 = list_to_atom(atom_to_list(Name1) ++ "@" ++ hostname()),
+ test_server:start_node(Name1, peer, [{args, "-pz \""++PA++"\""},
+ {erl,[{release,"r12b"}]}]),
TestDataLine1 = [229,228,246],
TestDataLine1BinUtf = unicode:characters_to_binary(TestDataLine1),
TestDataLine1BinLatin = list_to_binary(TestDataLine1),
@@ -963,141 +932,141 @@ bc_with_r12_gl_1(_Config,Machine) ->
register(io_proto_suite,self()),
AM1 = spawn(?MODULE,Machine,
[MyNodeList, "io_proto_suite", N2List]),
-
- ?line GL = receive X when is_pid(X) -> X end,
+
+ GL = receive X when is_pid(X) -> X end,
%% get_line
- ?line "Hej\n" = rpc:call(N1,io,get_line,[GL,"Prompt\n"]),
- ?line io:setopts(GL,[binary]),
- ?line io:format(GL,"Okej~n",[]),
- ?line <<"Hej\n">> = rpc:call(N1,io,get_line,[GL,"Prompt\n"]),
- ?line io:setopts(GL,[{encoding,latin1}]),
- ?line io:format(GL,"Okej~n",[]),
- ?line TestDataLine1BinLatin = chomp(rpc:call(N1,io,get_line,[GL,"Prompt\n"])),
- ?line io:format(GL,"Okej~n",[]),
- ?line TestDataLine1BinUtf = chomp(io:get_line(GL,"Prompt\n")),
- ?line io:setopts(GL,[{encoding,unicode}]),
-
- ?line io:format(GL,"Okej~n",[]),
- ?line TestDataLine1BinLatin = chomp(rpc:call(N1,io,get_line,[GL,"Prompt\n"])),
- ?line io:format(GL,"Okej~n",[]),
- ?line TestDataLine1BinUtf = chomp(io:get_line(GL,"Prompt\n")),
- ?line io:setopts(GL,[list]),
- ?line io:format(GL,"Okej~n",[]),
-
+ "Hej\n" = rpc:call(N1,io,get_line,[GL,"Prompt\n"]),
+ io:setopts(GL,[binary]),
+ io:format(GL,"Okej~n",[]),
+ <<"Hej\n">> = rpc:call(N1,io,get_line,[GL,"Prompt\n"]),
+ io:setopts(GL,[{encoding,latin1}]),
+ io:format(GL,"Okej~n",[]),
+ TestDataLine1BinLatin = chomp(rpc:call(N1,io,get_line,[GL,"Prompt\n"])),
+ io:format(GL,"Okej~n",[]),
+ TestDataLine1BinUtf = chomp(io:get_line(GL,"Prompt\n")),
+ io:setopts(GL,[{encoding,unicode}]),
+
+ io:format(GL,"Okej~n",[]),
+ TestDataLine1BinLatin = chomp(rpc:call(N1,io,get_line,[GL,"Prompt\n"])),
+ io:format(GL,"Okej~n",[]),
+ TestDataLine1BinUtf = chomp(io:get_line(GL,"Prompt\n")),
+ io:setopts(GL,[list]),
+ io:format(GL,"Okej~n",[]),
+
%%get_chars
- ?line "Hej" = rpc:call(N1,io,get_chars,[GL,"Prompt\n",3]),
- ?line io:setopts(GL,[binary]),
- ?line io:format(GL,"Okej~n",[]),
- ?line <<"Hej">> = rpc:call(N1,io,get_chars,[GL,"Prompt\n",3]),
- ?line io:setopts(GL,[{encoding,latin1}]),
- ?line io:format(GL,"Okej~n",[]),
- ?line TestDataLine1BinLatin = rpc:call(N1,io,get_chars,[GL,"Prompt\n",3]),
- ?line io:format(GL,"Okej~n",[]),
- ?line TestDataLine1BinUtf = io:get_chars(GL,"Prompt\n",3),
- ?line io:setopts(GL,[{encoding,unicode}]),
-
- ?line io:format(GL,"Okej~n",[]),
- ?line TestDataLine1BinLatin = rpc:call(N1,io,get_chars,[GL,"Prompt\n",3]),
- ?line io:format(GL,"Okej~n",[]),
- ?line TestDataLine1BinUtf = io:get_chars(GL,"Prompt\n",3),
- ?line io:setopts(GL,[list]),
- ?line io:format(GL,"Okej~n",[]),
+ "Hej" = rpc:call(N1,io,get_chars,[GL,"Prompt\n",3]),
+ io:setopts(GL,[binary]),
+ io:format(GL,"Okej~n",[]),
+ <<"Hej">> = rpc:call(N1,io,get_chars,[GL,"Prompt\n",3]),
+ io:setopts(GL,[{encoding,latin1}]),
+ io:format(GL,"Okej~n",[]),
+ TestDataLine1BinLatin = rpc:call(N1,io,get_chars,[GL,"Prompt\n",3]),
+ io:format(GL,"Okej~n",[]),
+ TestDataLine1BinUtf = io:get_chars(GL,"Prompt\n",3),
+ io:setopts(GL,[{encoding,unicode}]),
+
+ io:format(GL,"Okej~n",[]),
+ TestDataLine1BinLatin = rpc:call(N1,io,get_chars,[GL,"Prompt\n",3]),
+ io:format(GL,"Okej~n",[]),
+ TestDataLine1BinUtf = io:get_chars(GL,"Prompt\n",3),
+ io:setopts(GL,[list]),
+ io:format(GL,"Okej~n",[]),
%%fread
- ?line {ok,["Hej"]} = rpc:call(N1,io,fread,[GL,"Prompt\n","~s"]),
- ?line io:setopts(GL,[binary]),
- ?line io:format(GL,"Okej~n",[]),
- ?line {ok,["Hej"]} = rpc:call(N1,io,fread,[GL,"Prompt\n","~s"]),
- ?line io:setopts(GL,[{encoding,latin1}]),
- ?line io:format(GL,"Okej~n",[]),
- ?line {ok,[TestDataLine1]} = rpc:call(N1,io,fread,[GL,"Prompt\n","~s"]),
- ?line io:format(GL,"Okej~n",[]),
- ?line {ok,[TestDataLine1]} = io:fread(GL,"Prompt\n","~s"),
- ?line io:setopts(GL,[{encoding,unicode}]),
- ?line io:format(GL,"Okej~n",[]),
- ?line {ok,[TestDataLine1]} = rpc:call(N1,io,fread,[GL,"Prompt\n","~s"]),
- ?line io:format(GL,"Okej~n",[]),
- ?line {ok,[TestDataLine1]} = io:fread(GL,"Prompt\n","~s"),
- ?line io:setopts(GL,[list]),
- ?line io:format(GL,"Okej~n",[]),
-
-
- ?line receive
- {AM1,done} ->
- ok
- after 5000 ->
- exit(timeout)
- end,
- ?t:stop_node(N1),
+ {ok,["Hej"]} = rpc:call(N1,io,fread,[GL,"Prompt\n","~s"]),
+ io:setopts(GL,[binary]),
+ io:format(GL,"Okej~n",[]),
+ {ok,["Hej"]} = rpc:call(N1,io,fread,[GL,"Prompt\n","~s"]),
+ io:setopts(GL,[{encoding,latin1}]),
+ io:format(GL,"Okej~n",[]),
+ {ok,[TestDataLine1]} = rpc:call(N1,io,fread,[GL,"Prompt\n","~s"]),
+ io:format(GL,"Okej~n",[]),
+ {ok,[TestDataLine1]} = io:fread(GL,"Prompt\n","~s"),
+ io:setopts(GL,[{encoding,unicode}]),
+ io:format(GL,"Okej~n",[]),
+ {ok,[TestDataLine1]} = rpc:call(N1,io,fread,[GL,"Prompt\n","~s"]),
+ io:format(GL,"Okej~n",[]),
+ {ok,[TestDataLine1]} = io:fread(GL,"Prompt\n","~s"),
+ io:setopts(GL,[list]),
+ io:format(GL,"Okej~n",[]),
+
+
+ receive
+ {AM1,done} ->
+ ok
+ after 5000 ->
+ exit(timeout)
+ end,
+ test_server:stop_node(N1),
ok.
-
+
answering_machine1(OthNode,OthReg,Me) ->
TestDataLine1 = [229,228,246],
TestDataUtf = binary_to_list(unicode:characters_to_binary(TestDataLine1)),
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline, "{"++OthReg++","++OthNode++"} ! group_leader()."},
- {getline, "<"},
- % get_line
- {getline_re, ".*Prompt"},
- {putline, "Hej"},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, "Hej"},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataLine1},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataLine1},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataUtf},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataUtf},
- {getline_re, ".*Okej"},
- % get_chars
- {getline_re, ".*Prompt"},
- {putline, "Hej"},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, "Hej"},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataLine1},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataLine1},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataUtf},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataUtf},
- {getline_re, ".*Okej"},
- % fread
- {getline_re, ".*Prompt"},
- {putline, "Hej"},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, "Hej"},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataLine1},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataLine1},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataUtf},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataUtf},
- {getline_re, ".*Okej"}
-
- ],Me,"LC_CTYPE=\""++get_lc_ctype()++"\"; export LC_CTYPE; "),
+ rtnode([{putline,""},
+ {putline, "2."},
+ {getline, "2"},
+ {putline, "{"++OthReg++","++OthNode++"} ! group_leader()."},
+ {getline, "<"},
+ %% get_line
+ {getline_re, ".*Prompt"},
+ {putline, "Hej"},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, "Hej"},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataLine1},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataLine1},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataUtf},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataUtf},
+ {getline_re, ".*Okej"},
+ %% get_chars
+ {getline_re, ".*Prompt"},
+ {putline, "Hej"},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, "Hej"},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataLine1},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataLine1},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataUtf},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataUtf},
+ {getline_re, ".*Okej"},
+ %% fread
+ {getline_re, ".*Prompt"},
+ {putline, "Hej"},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, "Hej"},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataLine1},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataLine1},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataUtf},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataUtf},
+ {getline_re, ".*Okej"}
+
+ ],Me,"LC_CTYPE=\""++get_lc_ctype()++"\"; export LC_CTYPE; "),
O = list_to_atom(OthReg),
O ! {self(),done},
ok.
@@ -1105,79 +1074,76 @@ answering_machine1(OthNode,OthReg,Me) ->
answering_machine2(OthNode,OthReg,Me) ->
TestDataLine1 = [229,228,246],
TestDataUtf = binary_to_list(unicode:characters_to_binary(TestDataLine1)),
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline, "{"++OthReg++","++OthNode++"} ! group_leader()."},
- {getline_re, ".*<[0-9].*"},
- % get_line
- {getline_re, ".*Prompt"},
- {putline, "Hej"},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, "Hej"},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataLine1},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataLine1},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataUtf},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataUtf},
- {getline_re, ".*Okej"},
- % get_chars
- {getline_re, ".*Prompt"},
- {putline, "Hej"},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, "Hej"},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataLine1},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataLine1},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataUtf},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataUtf},
- {getline_re, ".*Okej"},
- % fread
- {getline_re, ".*Prompt"},
- {putline, "Hej"},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, "Hej"},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataLine1},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataLine1},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataUtf},
- {getline_re, ".*Okej"},
- {getline_re, ".*Prompt"},
- {putline, TestDataUtf},
- {getline_re, ".*Okej"}
-
- ],Me,"LC_CTYPE=\""++get_lc_ctype()++"\"; export LC_CTYPE; "," -oldshell "),
+ rtnode([{putline,""},
+ {putline, "2."},
+ {getline, "2"},
+ {putline, "{"++OthReg++","++OthNode++"} ! group_leader()."},
+ {getline_re, ".*<[0-9].*"},
+ %% get_line
+ {getline_re, ".*Prompt"},
+ {putline, "Hej"},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, "Hej"},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataLine1},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataLine1},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataUtf},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataUtf},
+ {getline_re, ".*Okej"},
+ %% get_chars
+ {getline_re, ".*Prompt"},
+ {putline, "Hej"},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, "Hej"},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataLine1},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataLine1},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataUtf},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataUtf},
+ {getline_re, ".*Okej"},
+ %% fread
+ {getline_re, ".*Prompt"},
+ {putline, "Hej"},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, "Hej"},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataLine1},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataLine1},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataUtf},
+ {getline_re, ".*Okej"},
+ {getline_re, ".*Prompt"},
+ {putline, TestDataUtf},
+ {getline_re, ".*Okej"}
+
+ ],Me,"LC_CTYPE=\""++get_lc_ctype()++"\"; export LC_CTYPE; "," -oldshell "),
O = list_to_atom(OthReg),
O ! {self(),done},
ok.
-
-read_modes_ogl(suite) ->
- [];
-read_modes_ogl(doc) ->
- ["Test various modes when reading from the group leade from another machine"];
+
+%% Test various modes when reading from the group leade from another machine.
read_modes_ogl(Config) when is_list(Config) ->
case get_progs() of
{error,Reason} ->
@@ -1186,10 +1152,7 @@ read_modes_ogl(Config) when is_list(Config) ->
read_modes_gl_1(Config,answering_machine2)
end.
-read_modes_gl(suite) ->
- [];
-read_modes_gl(doc) ->
- ["Test various modes when reading from the group leade from another machine"];
+%% Test various modes when reading from the group leade from another machine.
read_modes_gl(Config) when is_list(Config) ->
case {get_progs(),proplists:get_value(default_shell,Config)} of
{{error,Reason},_} ->
@@ -1210,81 +1173,78 @@ read_modes_gl_1(_Config,Machine) ->
register(io_proto_suite,self()),
AM1 = spawn(?MODULE,Machine,
[MyNodeList, "io_proto_suite", N2List]),
-
- ?line GL = receive X when is_pid(X) -> X end,
+
+ GL = receive X when is_pid(X) -> X end,
?dbg({group_leader,X}),
%% get_line
- ?line receive after 500 -> ok end, % Dont clash with the new shell...
- ?line "Hej\n" = io:get_line(GL,"Prompt\n"),
- ?line io:setopts(GL,[binary]),
- ?line io:format(GL,"Okej~n",[]),
- ?line <<"Hej\n">> = io:get_line(GL,"Prompt\n"),
- ?line io:setopts(GL,[{encoding,latin1}]),
- ?line io:format(GL,"Okej~n",[]),
- ?line TestDataLine1BinLatin = chomp(io:request(GL,{get_line,latin1,"Prompt\n"})),
- ?line io:format(GL,"Okej~n",[]),
- ?line TestDataLine1BinUtf = chomp(io:get_line(GL,"Prompt\n")),
- ?line io:setopts(GL,[{encoding,unicode}]),
-
- ?line io:format(GL,"Okej~n",[]),
- ?line TestDataLine1BinLatin = chomp(io:request(GL,{get_line,latin1,"Prompt\n"})),
- ?line io:format(GL,"Okej~n",[]),
- ?line TestDataLine1BinUtf = chomp(io:get_line(GL,"Prompt\n")),
- ?line io:setopts(GL,[list]),
- ?line io:format(GL,"Okej~n",[]),
-
+ receive after 500 -> ok end, % Dont clash with the new shell...
+ "Hej\n" = io:get_line(GL,"Prompt\n"),
+ io:setopts(GL,[binary]),
+ io:format(GL,"Okej~n",[]),
+ <<"Hej\n">> = io:get_line(GL,"Prompt\n"),
+ io:setopts(GL,[{encoding,latin1}]),
+ io:format(GL,"Okej~n",[]),
+ TestDataLine1BinLatin = chomp(io:request(GL,{get_line,latin1,"Prompt\n"})),
+ io:format(GL,"Okej~n",[]),
+ TestDataLine1BinUtf = chomp(io:get_line(GL,"Prompt\n")),
+ io:setopts(GL,[{encoding,unicode}]),
+
+ io:format(GL,"Okej~n",[]),
+ TestDataLine1BinLatin = chomp(io:request(GL,{get_line,latin1,"Prompt\n"})),
+ io:format(GL,"Okej~n",[]),
+ TestDataLine1BinUtf = chomp(io:get_line(GL,"Prompt\n")),
+ io:setopts(GL,[list]),
+ io:format(GL,"Okej~n",[]),
+
%%get_chars
- ?line "Hej" = io:get_chars(GL,"Prompt\n",3),
- ?line io:setopts(GL,[binary]),
- ?line io:format(GL,"Okej~n",[]),
- ?line <<"Hej">> = io:get_chars(GL,"Prompt\n",3),
- ?line io:setopts(GL,[{encoding,latin1}]),
- ?line io:format(GL,"Okej~n",[]),
- ?line TestDataLine1BinLatin = io:request(GL,{get_chars,latin1,"Prompt\n",3}),
- ?line io:format(GL,"Okej~n",[]),
- ?line TestDataLine1BinUtf = io:get_chars(GL,"Prompt\n",3),
- ?line io:setopts(GL,[{encoding,unicode}]),
-
- ?line io:format(GL,"Okej~n",[]),
- ?line TestDataLine1BinLatin = io:request(GL,{get_chars,latin1,"Prompt\n",3}),
- ?line io:format(GL,"Okej~n",[]),
- ?line TestDataLine1BinUtf = io:get_chars(GL,"Prompt\n",3),
- ?line io:setopts(GL,[list]),
- ?line io:format(GL,"Okej~n",[]),
+ "Hej" = io:get_chars(GL,"Prompt\n",3),
+ io:setopts(GL,[binary]),
+ io:format(GL,"Okej~n",[]),
+ <<"Hej">> = io:get_chars(GL,"Prompt\n",3),
+ io:setopts(GL,[{encoding,latin1}]),
+ io:format(GL,"Okej~n",[]),
+ TestDataLine1BinLatin = io:request(GL,{get_chars,latin1,"Prompt\n",3}),
+ io:format(GL,"Okej~n",[]),
+ TestDataLine1BinUtf = io:get_chars(GL,"Prompt\n",3),
+ io:setopts(GL,[{encoding,unicode}]),
+
+ io:format(GL,"Okej~n",[]),
+ TestDataLine1BinLatin = io:request(GL,{get_chars,latin1,"Prompt\n",3}),
+ io:format(GL,"Okej~n",[]),
+ TestDataLine1BinUtf = io:get_chars(GL,"Prompt\n",3),
+ io:setopts(GL,[list]),
+ io:format(GL,"Okej~n",[]),
%%fread
- ?line {ok,["Hej"]} = io:fread(GL,"Prompt\n","~s"),
- ?line io:setopts(GL,[binary]),
- ?line io:format(GL,"Okej~n",[]),
- ?line {ok,["Hej"]} = io:fread(GL,"Prompt\n","~s"),
- ?line io:setopts(GL,[{encoding,latin1}]),
- ?line io:format(GL,"Okej~n",[]),
- ?line {ok,[TestDataLine1]} = io:fread(GL,"Prompt\n","~s"),
- ?line io:format(GL,"Okej~n",[]),
- ?line {ok,[TestDataLine1]} = io:fread(GL,"Prompt\n","~s"),
- ?line io:setopts(GL,[{encoding,unicode}]),
- ?line io:format(GL,"Okej~n",[]),
- ?line {ok,[TestDataLine1]} = io:fread(GL,"Prompt\n","~s"),
- ?line io:format(GL,"Okej~n",[]),
- ?line {ok,[TestDataLine1]} = io:fread(GL,"Prompt\n","~s"),
- ?line io:setopts(GL,[list]),
- ?line io:format(GL,"Okej~n",[]),
-
-
- ?line receive
- {AM1,done} ->
- ok
- after 5000 ->
- exit(timeout)
- end,
+ {ok,["Hej"]} = io:fread(GL,"Prompt\n","~s"),
+ io:setopts(GL,[binary]),
+ io:format(GL,"Okej~n",[]),
+ {ok,["Hej"]} = io:fread(GL,"Prompt\n","~s"),
+ io:setopts(GL,[{encoding,latin1}]),
+ io:format(GL,"Okej~n",[]),
+ {ok,[TestDataLine1]} = io:fread(GL,"Prompt\n","~s"),
+ io:format(GL,"Okej~n",[]),
+ {ok,[TestDataLine1]} = io:fread(GL,"Prompt\n","~s"),
+ io:setopts(GL,[{encoding,unicode}]),
+ io:format(GL,"Okej~n",[]),
+ {ok,[TestDataLine1]} = io:fread(GL,"Prompt\n","~s"),
+ io:format(GL,"Okej~n",[]),
+ {ok,[TestDataLine1]} = io:fread(GL,"Prompt\n","~s"),
+ io:setopts(GL,[list]),
+ io:format(GL,"Okej~n",[]),
+
+
+ receive
+ {AM1,done} ->
+ ok
+ after 5000 ->
+ exit(timeout)
+ end,
ok.
-broken_unicode(suite) ->
- [];
-broken_unicode(doc) ->
- ["Test behaviour when reading broken Unicode files"];
+%% Test behaviour when reading broken Unicode files
broken_unicode(Config) when is_list(Config) ->
- Dir = ?config(priv_dir,Config),
+ Dir = proplists:get_value(priv_dir,Config),
Latin1Name = filename:join([Dir,"latin1_data_file.dat"]),
Utf8Name = filename:join([Dir,"utf8_data_file.dat"]),
Latin1Data = iolist_to_binary(lists:duplicate(10,lists:seq(0,255)++[255,255,255])),
@@ -1292,10 +1252,10 @@ broken_unicode(Config) when is_list(Config) ->
lists:duplicate(10,lists:seq(0,255))),
file:write_file(Latin1Name,Latin1Data),
file:write_file(Utf8Name,Utf8Data),
- ?line [ latin1 = heuristic_encoding_file2(Latin1Name,N,utf8) || N <- lists:seq(1,100)++[1024,2048,10000]],
- ?line [ utf8 = heuristic_encoding_file2(Utf8Name,N,utf8) || N <- lists:seq(1,100)++[1024,2048,10000]],
- ?line [ latin1 = heuristic_encoding_file2(Latin1Name,N,utf16) || N <- lists:seq(1,100)++[1024,2048,10000]],
- ?line [ latin1 = heuristic_encoding_file2(Latin1Name,N,utf32) || N <- lists:seq(1,100)++[1024,2048,10000]],
+ [ latin1 = heuristic_encoding_file2(Latin1Name,N,utf8) || N <- lists:seq(1,100)++[1024,2048,10000]],
+ [ utf8 = heuristic_encoding_file2(Utf8Name,N,utf8) || N <- lists:seq(1,100)++[1024,2048,10000]],
+ [ latin1 = heuristic_encoding_file2(Latin1Name,N,utf16) || N <- lists:seq(1,100)++[1024,2048,10000]],
+ [ latin1 = heuristic_encoding_file2(Latin1Name,N,utf32) || N <- lists:seq(1,100)++[1024,2048,10000]],
ok.
@@ -1314,10 +1274,7 @@ loop_through_file2(F,Bin,Chunk,Enc) when is_binary(Bin) ->
-eof_on_pipe(suite) ->
- [];
-eof_on_pipe(doc) ->
- ["tests eof before newline on stdin when erlang is in pipe"];
+%% Test eof before newline on stdin when erlang is in pipe.
eof_on_pipe(Config) when is_list(Config) ->
case {get_progs(),os:type()} of
{{error,Reason},_} ->
@@ -1337,10 +1294,10 @@ eof_on_pipe(Config) when is_list(Config) ->
end
end,
CommandLine1 = EchoLine ++
- "\""++Erl++"\" -noshell -eval "
- "'io:format(\"~p\",[io:get_line(\"\")]),"
- "io:format(\"~p\",[io:get_line(\"\")]),"
- "io:format(\"~p\",[io:get_line(\"\")]).' -run init stop",
+ "\""++Erl++"\" -noshell -eval "
+ "'io:format(\"~p\",[io:get_line(\"\")]),"
+ "io:format(\"~p\",[io:get_line(\"\")]),"
+ "io:format(\"~p\",[io:get_line(\"\")]).' -run init stop",
case os:cmd(CommandLine1) of
"\"a\\n\"\"bu\"eof" ->
ok;
@@ -1348,10 +1305,10 @@ eof_on_pipe(Config) when is_list(Config) ->
exit({unexpected1,Other1})
end,
CommandLine2 = EchoLine ++
- "\""++Erl++"\" -noshell -eval "
- "'io:setopts([binary]),io:format(\"~p\",[io:get_line(\"\")]),"
- "io:format(\"~p\",[io:get_line(\"\")]),"
- "io:format(\"~p\",[io:get_line(\"\")]).' -run init stop",
+ "\""++Erl++"\" -noshell -eval "
+ "'io:setopts([binary]),io:format(\"~p\",[io:get_line(\"\")]),"
+ "io:format(\"~p\",[io:get_line(\"\")]),"
+ "io:format(\"~p\",[io:get_line(\"\")]).' -run init stop",
case os:cmd(CommandLine2) of
"<<\"a\\n\">><<\"bu\">>eof" ->
ok;
@@ -1360,12 +1317,12 @@ eof_on_pipe(Config) when is_list(Config) ->
end
catch
throw:skip ->
- {skipped,"unsupported echo program"}
+ {skipped,"unsupported echo program"}
end;
{_,_} ->
{skipped,"Only on linux"}
end.
-
+
%%
%% Tool for running interactive shell (stolen from the kernel
@@ -1435,16 +1392,16 @@ timeout(normal) ->
-ifndef(debug).
rm_rf(Dir) ->
try
- {ok,List} = file:list_dir(Dir),
- Files = [filename:join([Dir,X]) || X <- List],
- [case file:list_dir(Y) of
- {error, enotdir} ->
- ok = file:delete(Y);
- _ ->
- ok = rm_rf(Y)
- end || Y <- Files],
- ok = file:del_dir(Dir),
- ok
+ {ok,List} = file:list_dir(Dir),
+ Files = [filename:join([Dir,X]) || X <- List],
+ [case file:list_dir(Y) of
+ {error, enotdir} ->
+ ok = file:delete(Y);
+ _ ->
+ ok = rm_rf(Y)
+ end || Y <- Files],
+ ok = file:del_dir(Dir),
+ ok
catch
_:Exception -> {error, {Exception,Dir}}
end.
@@ -1509,7 +1466,7 @@ get_and_put(CPid, [{putline_raw, Line}|T],N) ->
Timeout = timeout(normal),
receive
{send_line, ok} ->
- get_and_put(CPid, T,N+1)
+ get_and_put(CPid, T,N+1)
after Timeout ->
error_logger:error_msg("~p: putline_raw timeout (~p) sending "
"\"~s\" (command number ~p)~n",
@@ -1523,7 +1480,7 @@ get_and_put(CPid, [{putline, Line}|T],N) ->
Timeout = timeout(normal),
receive
{send_line, ok} ->
- get_and_put(CPid, [{getline, []}|T],N)
+ get_and_put(CPid, [{getline, []}|T],N)
after Timeout ->
error_logger:error_msg("~p: putline timeout (~p) sending "
"\"~s\" (command number ~p)~n[~p]~n",
@@ -1540,8 +1497,8 @@ wait_for_runerl_server(SPid) ->
after Timeout ->
{error, timeout}
end.
-
-
+
+
stop_runerl_node(CPid) ->
Ref = erlang:monitor(process, CPid),
@@ -1592,11 +1549,11 @@ create_tempdir(Dir,X) when X > $Z, X < $a ->
create_tempdir(Dir,$a);
create_tempdir(Dir,X) when X > $z ->
Estr = lists:flatten(
- io_lib:format("Unable to create ~s, reason eexist",
- [Dir++[$z]])),
+ io_lib:format("Unable to create ~s, reason eexist",
+ [Dir++[$z]])),
{error, Estr};
create_tempdir(Dir0, Ch) ->
- % Expect fairly standard unix.
+ %% Expect fairly standard unix.
Dir = Dir0++[Ch],
case file:make_dir(Dir) of
{error, eexist} ->
@@ -1634,8 +1591,8 @@ start_runerl_node(RunErl,Erl,Tempdir,Nodename,Extra) ->
[];
_ ->
" -sname "++(if is_atom(Nodename) -> atom_to_list(Nodename);
- true -> Nodename
- end)++
+ true -> Nodename
+ end)++
" -setcookie "++atom_to_list(erlang:get_cookie())
end,
XXArg = case Extra of
@@ -1646,9 +1603,9 @@ start_runerl_node(RunErl,Erl,Tempdir,Nodename,Extra) ->
end,
spawn(fun() ->
?dbg("\""++RunErl++"\" "++Tempdir++"/ "++Tempdir++
- " \""++Erl++XArg++XXArg++"\""),
+ " \""++Erl++XArg++XXArg++"\""),
os:cmd("\""++RunErl++"\" "++Tempdir++"/ "++Tempdir++
- " \""++Erl++XArg++XXArg++"\"")
+ " \""++Erl++XArg++XXArg++"\"")
end).
start_toerl_server(ToErl,Tempdir) ->
@@ -1706,7 +1663,7 @@ toerl_loop(Port,Acc) ->
_ ->
toerl_loop(Port,[{Tag0,Data}|Acc])
end;
- {Pid,{get_line,Timeout}} ->
+ {Pid,{get_line,Timeout}} ->
case Acc of
[] ->
case get_data_within(Port,Timeout,[]) of
@@ -1755,10 +1712,10 @@ toerl_loop(Port,Acc) ->
Other ->
{error, {unexpected, Other}}
end.
-
+
millistamp() ->
erlang:monotonic_time(milli_seconds).
-
+
get_data_within(Port, X, Acc) when X =< 0 ->
?dbg({get_data_within, X, Acc, ?LINE}),
receive
@@ -1877,8 +1834,8 @@ request({get_until, Encoding, Prompt, M, F, As}, State) ->
{ok, convert(State#state.nxt, Encoding, State#state.mode), State#state{nxt = eof, q = [{get_until, Encoding, Prompt, M, F, As} | State#state.q]}};
request({get_chars, Encoding, Prompt, N}, State) ->
{ok, convert(State#state.nxt, Encoding, State#state.mode), State#state{nxt = eof,
- q = [{get_chars, Encoding, Prompt, N} |
- State#state.q]}};
+ q = [{get_chars, Encoding, Prompt, N} |
+ State#state.q]}};
request({get_line, Encoding, Prompt}, State) ->
{ok, convert(State#state.nxt, Encoding, State#state.mode),
State#state{nxt = eof,
@@ -1910,7 +1867,7 @@ request(getopts, State) ->
binary -> [{binary, true}]
end, State#state{q=[getopts | State#state.q ]}};
request({requests, Reqs}, State) ->
- multi_request(Reqs, {ok, ok, State}).
+ multi_request(Reqs, {ok, ok, State}).
multi_request([R|Rs], {ok, _Res, State}) ->
multi_request(Rs, request(R, State));
@@ -1941,7 +1898,7 @@ convert(Data, latin1, binary) ->
_ ->
{error, {cannot_convert, unicode, latin1}}
end.
-
+
hostname() ->
from($@, atom_to_list(node())).
diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl
index a0f7fd2744..b21eb37ee3 100644
--- a/lib/stdlib/test/lists_SUITE.erl
+++ b/lib/stdlib/test/lists_SUITE.erl
@@ -22,26 +22,20 @@
%%%-----------------------------------------------------------------
-module(lists_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-
-% Default timetrap timeout (set in init_per_testcase).
-% This should be set relatively high (10-15 times the expected
-% max testcasetime).
--define(default_timeout, ?t:minutes(4)).
-
-% Test server specific exports
+%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
-export([init_per_testcase/2, end_per_testcase/2]).
-% Test cases must be exported.
+%% Test cases must be exported.
-export([member/1, reverse/1,
keymember/1, keysearch_keyfind/1,
keystore/1, keytake/1, keyreplace/1,
append_1/1, append_2/1,
seq_loop/1, seq_2/1, seq_3/1, seq_2_e/1, seq_3_e/1,
-
+
sublist_2/1, sublist_3/1, sublist_2_e/1, sublist_3_e/1,
flatten_1/1, flatten_2/1, flatten_1_e/1, flatten_2_e/1,
dropwhile/1, takewhile/1,
@@ -78,7 +72,9 @@
%%
%% all/1
%%
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,4}}].
all() ->
[{group, append},
@@ -141,58 +137,48 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_Case, Config) ->
- ?line Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
-%
-% Test cases starts here.
-%
+%%
+%% Test cases starts here.
+%%
-append_1(doc) -> [];
-append_1(suite) -> [];
append_1(Config) when is_list(Config) ->
- ?line "abcdef"=lists:append(["abc","def"]),
- ?line [hej, du,[glade, [bagare]]]=
+ "abcdef"=lists:append(["abc","def"]),
+ [hej, du,[glade, [bagare]]]=
lists:append([[hej], [du], [[glade, [bagare]]]]),
- ?line [10, [elem]]=lists:append([[10], [[elem]]]),
+ [10, [elem]]=lists:append([[10], [[elem]]]),
ok.
-append_2(doc) -> [];
-append_2(suite) -> [];
append_2(Config) when is_list(Config) ->
- ?line "abcdef"=lists:append("abc", "def"),
- ?line [hej, du]=lists:append([hej], [du]),
- ?line [10, [elem]]=lists:append([10], [[elem]]),
+ "abcdef"=lists:append("abc", "def"),
+ [hej, du]=lists:append([hej], [du]),
+ [10, [elem]]=lists:append([10], [[elem]]),
ok.
-reverse(suite) ->
- [];
-reverse(doc) ->
- ["Tests the lists:reverse() implementation. The function is "
- "`non-blocking', and only processes a fixed number of elements "
- "at a time."];
+%% Tests the lists:reverse() implementation. The function is
+%% `non-blocking', and only processes a fixed number of elements at a
+%% time.
reverse(Config) when is_list(Config) ->
- ?line reverse_test(0),
- ?line reverse_test(1),
- ?line reverse_test(2),
- ?line reverse_test(128),
- ?line reverse_test(256),
- ?line reverse_test(1000),
- ?line reverse_test(1998),
- ?line reverse_test(1999),
- ?line reverse_test(2000),
- ?line reverse_test(2001),
- ?line reverse_test(3998),
- ?line reverse_test(3999),
- ?line reverse_test(4000),
- ?line reverse_test(4001),
- ?line reverse_test(60001),
- ?line reverse_test(100007),
+ reverse_test(0),
+ reverse_test(1),
+ reverse_test(2),
+ reverse_test(128),
+ reverse_test(256),
+ reverse_test(1000),
+ reverse_test(1998),
+ reverse_test(1999),
+ reverse_test(2000),
+ reverse_test(2001),
+ reverse_test(3998),
+ reverse_test(3999),
+ reverse_test(4000),
+ reverse_test(4001),
+ reverse_test(60001),
+ reverse_test(100007),
ok.
reverse_test(0) ->
@@ -210,27 +196,25 @@ reverse_test(Num) ->
List0 = lists:reverse(List),
ok.
-member(doc) ->
- ["Tests the lists:member() implementation."
- "This test case depends on lists:reverse() to work, "
- "wich is tested in a separate test case."];
+%% Test the lists:member() implementation. This test case depends on
+%% lists:reverse() to work, wich is tested in a separate test case.
member(Config) when is_list(Config) ->
- ?line {'EXIT',{badarg,_}} = (catch lists:member(45, {a,b,c})),
- ?line {'EXIT',{badarg,_}} = (catch lists:member(45, [0|non_list_tail])),
- ?line false = lists:member(4233, []),
- ?line member_test(1),
- ?line member_test(100),
- ?line member_test(256),
- ?line member_test(1000),
- ?line member_test(1998),
- ?line member_test(1999),
- ?line member_test(2000),
- ?line member_test(2001),
- ?line member_test(3998),
- ?line member_test(3999),
- ?line member_test(4000),
- ?line member_test(4001),
- ?line member_test(100008),
+ {'EXIT',{badarg,_}} = (catch lists:member(45, {a,b,c})),
+ {'EXIT',{badarg,_}} = (catch lists:member(45, [0|non_list_tail])),
+ false = lists:member(4233, []),
+ member_test(1),
+ member_test(100),
+ member_test(256),
+ member_test(1000),
+ member_test(1998),
+ member_test(1999),
+ member_test(2000),
+ member_test(2001),
+ member_test(3998),
+ member_test(3999),
+ member_test(4000),
+ member_test(4001),
+ member_test(100008),
ok.
member_test(Num) ->
@@ -246,78 +230,78 @@ member_test(Num) ->
false = lists:member({a,b,c}, List).
keymember(Config) when is_list(Config) ->
- ?line false = lists:keymember(anything_goes, 1, []),
- ?line {'EXIT',{badarg,_}} = (catch lists:keymember(anything_goes, -1, [])),
- ?line {'EXIT',{badarg,_}} = (catch lists:keymember(anything_goes, 0, [])),
- ?line {'EXIT',{badarg,_}} = (catch lists:keymember(anything_goes, 1, {1,2,3})),
+ false = lists:keymember(anything_goes, 1, []),
+ {'EXIT',{badarg,_}} = (catch lists:keymember(anything_goes, -1, [])),
+ {'EXIT',{badarg,_}} = (catch lists:keymember(anything_goes, 0, [])),
+ {'EXIT',{badarg,_}} = (catch lists:keymember(anything_goes, 1, {1,2,3})),
List = [{52.0,a},{-19,b,c},{37.5,d},an_atom,42.0,{39},{45,{x,y,z}}],
- ?line false = lists:keymember(333, 5, List),
- ?line false = lists:keymember(333, 999, List),
- ?line false = lists:keymember(37, 1, List),
-
- ?line true = lists:keymember(52.0, 1, List),
- ?line true = lists:keymember(52, 1, List),
- ?line true = lists:keymember(-19, 1, List),
- ?line true = lists:keymember(-19.0, 1, List),
- ?line true = lists:keymember(37.5, 1, List),
- ?line true = lists:keymember(39, 1, List),
- ?line true = lists:keymember(39.0, 1, List),
- ?line true = lists:keymember(45, 1, List),
- ?line true = lists:keymember(45.0, 1, List),
-
- ?line true = lists:keymember(a, 2, List),
- ?line true = lists:keymember(b, 2, List),
- ?line true = lists:keymember(c, 3, List),
- ?line true = lists:keymember(d, 2, List),
- ?line true = lists:keymember({x,y,z}, 2, List),
-
- ?line Long0 = lists:seq(1, 100007),
- ?line false = lists:keymember(kalle, 1, Long0),
- ?line Long = lists:foldl(fun(E, A) -> [{1/E,E}|A] end, [], Long0),
- ?line true = lists:keymember(1, 2, Long),
- ?line true = lists:keymember(2, 2, Long),
- ?line true = lists:keymember(1.0, 2, Long),
- ?line true = lists:keymember(2.0, 2, Long),
- ?line true = lists:keymember(100006, 2, Long),
+ false = lists:keymember(333, 5, List),
+ false = lists:keymember(333, 999, List),
+ false = lists:keymember(37, 1, List),
+
+ true = lists:keymember(52.0, 1, List),
+ true = lists:keymember(52, 1, List),
+ true = lists:keymember(-19, 1, List),
+ true = lists:keymember(-19.0, 1, List),
+ true = lists:keymember(37.5, 1, List),
+ true = lists:keymember(39, 1, List),
+ true = lists:keymember(39.0, 1, List),
+ true = lists:keymember(45, 1, List),
+ true = lists:keymember(45.0, 1, List),
+
+ true = lists:keymember(a, 2, List),
+ true = lists:keymember(b, 2, List),
+ true = lists:keymember(c, 3, List),
+ true = lists:keymember(d, 2, List),
+ true = lists:keymember({x,y,z}, 2, List),
+
+ Long0 = lists:seq(1, 100007),
+ false = lists:keymember(kalle, 1, Long0),
+ Long = lists:foldl(fun(E, A) -> [{1/E,E}|A] end, [], Long0),
+ true = lists:keymember(1, 2, Long),
+ true = lists:keymember(2, 2, Long),
+ true = lists:keymember(1.0, 2, Long),
+ true = lists:keymember(2.0, 2, Long),
+ true = lists:keymember(100006, 2, Long),
ok.
keysearch_keyfind(Config) when is_list(Config) ->
- ?line false = key_search_find(anything_goes, 1, []),
- ?line {'EXIT',{badarg,_}} = (catch key_search_find(anything_goes, -1, [])),
- ?line {'EXIT',{badarg,_}} = (catch key_search_find(anything_goes, 0, [])),
- ?line {'EXIT',{badarg,_}} = (catch key_search_find(anything_goes, 1, {1,2,3})),
+ false = key_search_find(anything_goes, 1, []),
+ {'EXIT',{badarg,_}} = (catch key_search_find(anything_goes, -1, [])),
+ {'EXIT',{badarg,_}} = (catch key_search_find(anything_goes, 0, [])),
+ {'EXIT',{badarg,_}} = (catch key_search_find(anything_goes, 1, {1,2,3})),
First = {x,42.0},
Second = {y,-77},
Third = {z,[a,b,c],{5.0}},
List = [First,Second,Third],
-
- ?line false = key_search_find(333, 1, []),
- ?line false = key_search_find(333, 5, List),
- ?line false = key_search_find(333, 999, List),
- ?line false = key_search_find(37, 1, List),
-
- ?line {value,First} = key_search_find(42, 2, List),
- ?line {value,First} = key_search_find(42.0, 2, List),
-
- ?line {value,Second} = key_search_find(-77, 2, List),
- ?line {value,Second} = key_search_find(-77.0, 2, List),
-
- ?line {value,Third} = key_search_find(z, 1, List),
- ?line {value,Third} = key_search_find([a,b,c], 2, List),
- ?line {value,Third} = key_search_find({5}, 3, List),
- ?line {value,Third} = key_search_find({5.0}, 3, List),
-
- ?line Long0 = lists:seq(1, 100007),
- ?line false = key_search_find(kalle, 1, Long0),
- ?line Long = lists:foldl(fun(E, A) -> [{1/E,float(E)}|A] end, [], Long0),
- ?line {value,{_,1.0}} = key_search_find(1, 2, Long),
- ?line {value,{_,1.0}} = key_search_find(1.0, 2, Long),
- ?line {value,{_,2.0}} = key_search_find(2, 2, Long),
- ?line {value,{_,2.0}} = key_search_find(2.0, 2, Long),
- ?line {value,{_,33988.0}} = key_search_find(33988, 2, Long),
- ?line {value,{_,33988.0}} = key_search_find(33988.0, 2, Long),
+
+ false = key_search_find(333, 1, []),
+ false = key_search_find(333, 5, List),
+ false = key_search_find(333, 999, List),
+ false = key_search_find(37, 1, List),
+
+ {value,First} = key_search_find(42, 2, List),
+ {value,First} = key_search_find(42.0, 2, List),
+
+ {value,Second} = key_search_find(-77, 2, List),
+ {value,Second} = key_search_find(-77.0, 2, List),
+
+ {value,Third} = key_search_find(z, 1, List),
+ {value,Third} = key_search_find([a,b,c], 2, List),
+ {value,Third} = key_search_find({5}, 3, List),
+ {value,Third} = key_search_find({5.0}, 3, List),
+
+ Long0 = lists:seq(1, 100007),
+ false = key_search_find(kalle, 1, Long0),
+ Long = lists:foldl(fun(E, A) -> [{1/E,float(E)}|A] end, [], Long0),
+ {value,{_,1.0}} = key_search_find(1, 2, Long),
+ {value,{_,1.0}} = key_search_find(1.0, 2, Long),
+ {value,{_,2.0}} = key_search_find(2, 2, Long),
+ {value,{_,2.0}} = key_search_find(2.0, 2, Long),
+ {value,{_,33988.0}} = key_search_find(33988, 2, Long),
+ {value,{_,33988.0}} = key_search_find(33988.0, 2, Long),
ok.
%% Test both lists:keysearch/3 and lists:keyfind/3. The only
@@ -333,29 +317,29 @@ key_search_find(Key, Pos, List) ->
end.
dropwhile(Config) when is_list(Config) ->
- ?line F = fun(C) -> C =:= $@ end,
+ F = fun(C) -> C =:= $@ end,
- ?line [] = lists:dropwhile(F, []),
- ?line [a] = lists:dropwhile(F, [a]),
- ?line [a,b] = lists:dropwhile(F, [a,b]),
- ?line [a,b,c] = lists:dropwhile(F, [a,b,c]),
+ [] = lists:dropwhile(F, []),
+ [a] = lists:dropwhile(F, [a]),
+ [a,b] = lists:dropwhile(F, [a,b]),
+ [a,b,c] = lists:dropwhile(F, [a,b,c]),
- ?line [] = lists:dropwhile(F, [$@]),
- ?line [] = lists:dropwhile(F, [$@,$@]),
- ?line [a,$@] = lists:dropwhile(F, [$@,a,$@]),
+ [] = lists:dropwhile(F, [$@]),
+ [] = lists:dropwhile(F, [$@,$@]),
+ [a,$@] = lists:dropwhile(F, [$@,a,$@]),
- ?line [$k] = lists:dropwhile(F, [$@,$k]),
- ?line [$k,$l] = lists:dropwhile(F, [$@,$@,$k,$l]),
- ?line [a] = lists:dropwhile(F, [$@,$@,$@,a]),
+ [$k] = lists:dropwhile(F, [$@,$k]),
+ [$k,$l] = lists:dropwhile(F, [$@,$@,$k,$l]),
+ [a] = lists:dropwhile(F, [$@,$@,$@,a]),
- ?line [a,$@,b] = lists:dropwhile(F, [$@,a,$@,b]),
- ?line [a,$@,b] = lists:dropwhile(F, [$@,$@,a,$@,b]),
- ?line [a,$@,b] = lists:dropwhile(F, [$@,$@,$@,a,$@,b]),
+ [a,$@,b] = lists:dropwhile(F, [$@,a,$@,b]),
+ [a,$@,b] = lists:dropwhile(F, [$@,$@,a,$@,b]),
+ [a,$@,b] = lists:dropwhile(F, [$@,$@,$@,a,$@,b]),
Long = lists:seq(1, 1024),
Shorter = lists:seq(800, 1024),
- ?line Shorter = lists:dropwhile(fun(E) -> E < 800 end, Long),
+ Shorter = lists:dropwhile(fun(E) -> E < 800 end, Long),
ok.
@@ -386,41 +370,35 @@ takewhile(Config) when is_list(Config) ->
ok.
-keystore(doc) ->
- ["OTP-XXX."];
-keystore(suite) -> [];
keystore(Config) when is_list(Config) ->
- ?line {'EXIT',_} = (catch lists:keystore(key, 0, [], {1})),
- ?line {'EXIT',_} = (catch lists:keystore(key, 1, {}, {})),
- ?line {'EXIT',_} = (catch lists:keystore(key, 1, {a,b}, {})),
- ?line {'EXIT', _} = (catch lists:keystore(a, 2, [{1,a}], b)),
+ {'EXIT',_} = (catch lists:keystore(key, 0, [], {1})),
+ {'EXIT',_} = (catch lists:keystore(key, 1, {}, {})),
+ {'EXIT',_} = (catch lists:keystore(key, 1, {a,b}, {})),
+ {'EXIT', _} = (catch lists:keystore(a, 2, [{1,a}], b)),
T = {k,17},
- ?line [T] = lists:keystore(a, 2, [], T),
- ?line [{1,a},{2,b},{k,17}] = lists:keystore(c, 2, [{1,a},{2,b}],T),
+ [T] = lists:keystore(a, 2, [], T),
+ [{1,a},{2,b},{k,17}] = lists:keystore(c, 2, [{1,a},{2,b}],T),
L = [{1,a},{2,b},{3,c}],
- ?line [{k,17},{2,b},{3,c}] = lists:keystore(a, 2, L, T),
- ?line [{1,a},{k,17},{3,c}] = lists:keystore(b, 2, L, T),
- ?line [{1,a},{2,b},{k,17}] = lists:keystore(c, 2, L, T),
- ?line [{2,b}] = lists:keystore(a, 2, [{1,a}], {2,b}),
- ?line [{1,a}] = lists:keystore(foo, 1, [], {1,a}),
+ [{k,17},{2,b},{3,c}] = lists:keystore(a, 2, L, T),
+ [{1,a},{k,17},{3,c}] = lists:keystore(b, 2, L, T),
+ [{1,a},{2,b},{k,17}] = lists:keystore(c, 2, L, T),
+ [{2,b}] = lists:keystore(a, 2, [{1,a}], {2,b}),
+ [{1,a}] = lists:keystore(foo, 1, [], {1,a}),
ok.
-keytake(doc) ->
- ["OTP-XXX."];
-keytake(suite) -> [];
keytake(Config) when is_list(Config) ->
- ?line {'EXIT',_} = (catch lists:keytake(key, 0, [])),
- ?line {'EXIT',_} = (catch lists:keytake(key, 1, {})),
- ?line {'EXIT',_} = (catch lists:keytake(key, 1, {a,b})),
- ?line false = lists:keytake(key, 2, [{a}]),
- ?line false = lists:keytake(key, 1, [a]),
- ?line false = lists:keytake(k, 1, []),
- ?line false = lists:keytake(k, 1, [{a},{b},{c}]),
+ {'EXIT',_} = (catch lists:keytake(key, 0, [])),
+ {'EXIT',_} = (catch lists:keytake(key, 1, {})),
+ {'EXIT',_} = (catch lists:keytake(key, 1, {a,b})),
+ false = lists:keytake(key, 2, [{a}]),
+ false = lists:keytake(key, 1, [a]),
+ false = lists:keytake(k, 1, []),
+ false = lists:keytake(k, 1, [{a},{b},{c}]),
L = [{a,1},{b,2},{c,3}],
- ?line {value,{a,1},[{b,2},{c,3}]} = lists:keytake(1, 2, L),
- ?line {value,{b,2},[{a,1},{c,3}]} = lists:keytake(2, 2, L),
- ?line {value,{c,3},[{a,1},{b,2}]} = lists:keytake(3, 2, L),
- ?line false = lists:keytake(4, 2, L),
+ {value,{a,1},[{b,2},{c,3}]} = lists:keytake(1, 2, L),
+ {value,{b,2},[{a,1},{c,3}]} = lists:keytake(2, 2, L),
+ {value,{c,3},[{a,1},{b,2}]} = lists:keytake(3, 2, L),
+ false = lists:keytake(4, 2, L),
ok.
%% Test lists:keyreplace/4.
@@ -434,153 +412,147 @@ keyreplace(Config) when is_list(Config) ->
{'EXIT',_} = (catch lists:keyreplace(k, 0, [], {a,b})),
ok.
-merge(doc) -> ["merge functions"];
-merge(suite) -> [];
merge(Config) when is_list(Config) ->
%% merge list of lists
- ?line [] = lists:merge([]),
- ?line [] = lists:merge([[]]),
- ?line [] = lists:merge([[],[]]),
- ?line [] = lists:merge([[],[],[]]),
- ?line [1] = lists:merge([[1]]),
- ?line [1,1,2,2] = lists:merge([[1,2],[1,2]]),
- ?line [1] = lists:merge([[1],[],[]]),
- ?line [1] = lists:merge([[],[1],[]]),
- ?line [1] = lists:merge([[],[],[1]]),
- ?line [1,2] = lists:merge([[1],[2],[]]),
- ?line [1,2] = lists:merge([[1],[],[2]]),
- ?line [1,2] = lists:merge([[],[1],[2]]),
- ?line [1,2,3,4,5,6] = lists:merge([[1,2],[],[5,6],[],[3,4],[]]),
- ?line [1,2,3,4] = lists:merge([[4],[3],[2],[1]]),
- ?line [1,2,3,4,5] = lists:merge([[1],[2],[3],[4],[5]]),
- ?line [1,2,3,4,5,6] = lists:merge([[1],[2],[3],[4],[5],[6]]),
- ?line [1,2,3,4,5,6,7,8,9] =
+ [] = lists:merge([]),
+ [] = lists:merge([[]]),
+ [] = lists:merge([[],[]]),
+ [] = lists:merge([[],[],[]]),
+ [1] = lists:merge([[1]]),
+ [1,1,2,2] = lists:merge([[1,2],[1,2]]),
+ [1] = lists:merge([[1],[],[]]),
+ [1] = lists:merge([[],[1],[]]),
+ [1] = lists:merge([[],[],[1]]),
+ [1,2] = lists:merge([[1],[2],[]]),
+ [1,2] = lists:merge([[1],[],[2]]),
+ [1,2] = lists:merge([[],[1],[2]]),
+ [1,2,3,4,5,6] = lists:merge([[1,2],[],[5,6],[],[3,4],[]]),
+ [1,2,3,4] = lists:merge([[4],[3],[2],[1]]),
+ [1,2,3,4,5] = lists:merge([[1],[2],[3],[4],[5]]),
+ [1,2,3,4,5,6] = lists:merge([[1],[2],[3],[4],[5],[6]]),
+ [1,2,3,4,5,6,7,8,9] =
lists:merge([[1],[2],[3],[4],[5],[6],[7],[8],[9]]),
Seq = lists:seq(1,100),
- ?line true = Seq == lists:merge(lists:map(fun(E) -> [E] end, Seq)),
+ true = Seq == lists:merge(lists:map(fun(E) -> [E] end, Seq)),
Two = [1,2],
Six = [1,2,3,4,5,6],
%% 2-way merge
- ?line [] = lists:merge([], []),
- ?line Two = lists:merge(Two, []),
- ?line Two = lists:merge([], Two),
- ?line Six = lists:merge([1,3,5], [2,4,6]),
- ?line Six = lists:merge([2,4,6], [1,3,5]),
- ?line Six = lists:merge([1,2,3], [4,5,6]),
- ?line Six = lists:merge([4,5,6], [1,2,3]),
- ?line Six = lists:merge([1,2,5],[3,4,6]),
- ?line [1,2,3,5,7] = lists:merge([1,3,5,7], [2]),
- ?line [1,2,3,4,5,7] = lists:merge([1,3,5,7], [2,4]),
- ?line [1,2,3,4,5,6,7] = lists:merge([1,3,5,7], [2,4,6]),
- ?line [1,2,3,5,7] = lists:merge([2], [1,3,5,7]),
- ?line [1,2,3,4,5,7] = lists:merge([2,4], [1,3,5,7]),
- ?line [1,2,3,4,5,6,7] = lists:merge([2,4,6], [1,3,5,7]),
+ [] = lists:merge([], []),
+ Two = lists:merge(Two, []),
+ Two = lists:merge([], Two),
+ Six = lists:merge([1,3,5], [2,4,6]),
+ Six = lists:merge([2,4,6], [1,3,5]),
+ Six = lists:merge([1,2,3], [4,5,6]),
+ Six = lists:merge([4,5,6], [1,2,3]),
+ Six = lists:merge([1,2,5],[3,4,6]),
+ [1,2,3,5,7] = lists:merge([1,3,5,7], [2]),
+ [1,2,3,4,5,7] = lists:merge([1,3,5,7], [2,4]),
+ [1,2,3,4,5,6,7] = lists:merge([1,3,5,7], [2,4,6]),
+ [1,2,3,5,7] = lists:merge([2], [1,3,5,7]),
+ [1,2,3,4,5,7] = lists:merge([2,4], [1,3,5,7]),
+ [1,2,3,4,5,6,7] = lists:merge([2,4,6], [1,3,5,7]),
%% 3-way merge
- ?line [] = lists:merge3([], [], []),
- ?line Two = lists:merge3([], [], Two),
- ?line Two = lists:merge3([], Two, []),
- ?line Two = lists:merge3(Two, [], []),
- ?line Six = lists:merge3([], [1,3,5], [2,4,6]),
- ?line Six = lists:merge3([1,3,5], [], [2,4,6]),
- ?line Six = lists:merge3([1,3,5], [2,4,6], []),
- ?line Nine = lists:merge3([1,4,7],[2,5,8],[3,6,9]),
- ?line Nine = lists:merge3([1,4,7],[3,6,9],[2,5,8]),
- ?line Nine = lists:merge3([3,6,9],[1,4,7],[2,5,8]),
- ?line Nine = lists:merge3([4,5,6],[1,2,3],[7,8,9]),
- ?line Nine = lists:merge3([1,2,3],[4,5,6],[7,8,9]),
- ?line Nine = lists:merge3([7,8,9],[4,5,6],[1,2,3]),
- ?line Nine = lists:merge3([4,5,6],[7,8,9],[1,2,3]),
-
- ok.
-
-rmerge(doc) -> ["reverse merge functions"];
-rmerge(suite) -> [];
+ [] = lists:merge3([], [], []),
+ Two = lists:merge3([], [], Two),
+ Two = lists:merge3([], Two, []),
+ Two = lists:merge3(Two, [], []),
+ Six = lists:merge3([], [1,3,5], [2,4,6]),
+ Six = lists:merge3([1,3,5], [], [2,4,6]),
+ Six = lists:merge3([1,3,5], [2,4,6], []),
+ Nine = lists:merge3([1,4,7],[2,5,8],[3,6,9]),
+ Nine = lists:merge3([1,4,7],[3,6,9],[2,5,8]),
+ Nine = lists:merge3([3,6,9],[1,4,7],[2,5,8]),
+ Nine = lists:merge3([4,5,6],[1,2,3],[7,8,9]),
+ Nine = lists:merge3([1,2,3],[4,5,6],[7,8,9]),
+ Nine = lists:merge3([7,8,9],[4,5,6],[1,2,3]),
+ Nine = lists:merge3([4,5,6],[7,8,9],[1,2,3]),
+
+ ok.
+
+%% reverse merge functions
rmerge(Config) when is_list(Config) ->
Two = [2,1],
Six = [6,5,4,3,2,1],
%% 2-way reversed merge
- ?line [] = lists:rmerge([], []),
- ?line Two = lists:rmerge(Two, []),
- ?line Two = lists:rmerge([], Two),
- ?line Six = lists:rmerge([5,3,1], [6,4,2]),
- ?line Six = lists:rmerge([6,4,2], [5,3,1]),
- ?line Six = lists:rmerge([3,2,1], [6,5,4]),
- ?line Six = lists:rmerge([6,5,4], [3,2,1]),
- ?line Six = lists:rmerge([4,3,2],[6,5,1]),
- ?line [7,6,5,3,1] = lists:rmerge([7,5,3,1], [6]),
- ?line [7,6,5,4,3,1] = lists:rmerge([7,5,3,1], [6,4]),
- ?line [7,6,5,4,3,2,1] = lists:rmerge([7,5,3,1], [6,4,2]),
- ?line [7,5,3,2,1] = lists:rmerge([2], [7,5,3,1]),
- ?line [7,5,4,3,2,1] = lists:rmerge([4,2], [7,5,3,1]),
- ?line [7,6,5,4,3,2,1] = lists:rmerge([6,4,2], [7,5,3,1]),
+ [] = lists:rmerge([], []),
+ Two = lists:rmerge(Two, []),
+ Two = lists:rmerge([], Two),
+ Six = lists:rmerge([5,3,1], [6,4,2]),
+ Six = lists:rmerge([6,4,2], [5,3,1]),
+ Six = lists:rmerge([3,2,1], [6,5,4]),
+ Six = lists:rmerge([6,5,4], [3,2,1]),
+ Six = lists:rmerge([4,3,2],[6,5,1]),
+ [7,6,5,3,1] = lists:rmerge([7,5,3,1], [6]),
+ [7,6,5,4,3,1] = lists:rmerge([7,5,3,1], [6,4]),
+ [7,6,5,4,3,2,1] = lists:rmerge([7,5,3,1], [6,4,2]),
+ [7,5,3,2,1] = lists:rmerge([2], [7,5,3,1]),
+ [7,5,4,3,2,1] = lists:rmerge([4,2], [7,5,3,1]),
+ [7,6,5,4,3,2,1] = lists:rmerge([6,4,2], [7,5,3,1]),
Nine = [9,8,7,6,5,4,3,2,1],
%% 3-way reversed merge
- ?line [] = lists:rmerge3([], [], []),
- ?line Two = lists:rmerge3([], [], Two),
- ?line Two = lists:rmerge3([], Two, []),
- ?line Two = lists:rmerge3(Two, [], []),
- ?line Six = lists:rmerge3([], [5,3,1], [6,4,2]),
- ?line Six = lists:rmerge3([5,3,1], [], [6,4,2]),
- ?line Six = lists:rmerge3([5,3,1], [6,4,2], []),
- ?line Nine = lists:rmerge3([7,4,1],[8,5,2],[9,6,3]),
- ?line Nine = lists:rmerge3([7,4,1],[9,6,3],[8,5,2]),
- ?line Nine = lists:rmerge3([9,6,3],[7,4,1],[8,5,2]),
- ?line Nine = lists:rmerge3([6,5,4],[3,2,1],[9,8,7]),
- ?line Nine = lists:rmerge3([3,2,1],[6,5,4],[9,8,7]),
- ?line Nine = lists:rmerge3([9,8,7],[6,5,4],[3,2,1]),
- ?line Nine = lists:rmerge3([6,5,4],[9,8,7],[3,2,1]),
-
- ok.
-
-sort_1(doc) -> ["sort/1"];
-sort_1(suite) -> [];
+ [] = lists:rmerge3([], [], []),
+ Two = lists:rmerge3([], [], Two),
+ Two = lists:rmerge3([], Two, []),
+ Two = lists:rmerge3(Two, [], []),
+ Six = lists:rmerge3([], [5,3,1], [6,4,2]),
+ Six = lists:rmerge3([5,3,1], [], [6,4,2]),
+ Six = lists:rmerge3([5,3,1], [6,4,2], []),
+ Nine = lists:rmerge3([7,4,1],[8,5,2],[9,6,3]),
+ Nine = lists:rmerge3([7,4,1],[9,6,3],[8,5,2]),
+ Nine = lists:rmerge3([9,6,3],[7,4,1],[8,5,2]),
+ Nine = lists:rmerge3([6,5,4],[3,2,1],[9,8,7]),
+ Nine = lists:rmerge3([3,2,1],[6,5,4],[9,8,7]),
+ Nine = lists:rmerge3([9,8,7],[6,5,4],[3,2,1]),
+ Nine = lists:rmerge3([6,5,4],[9,8,7],[3,2,1]),
+
+ ok.
+
sort_1(Config) when is_list(Config) ->
- ?line [] = lists:sort([]),
- ?line [a] = lists:sort([a]),
- ?line [a,a] = lists:sort([a,a]),
- ?line [a,b] = lists:sort([a,b]),
- ?line [a,b] = lists:sort([b,a]),
- ?line [1,1] = lists:sort([1,1]),
- ?line [1,1,2,3] = lists:sort([1,1,3,2]),
- ?line [1,2,3,3] = lists:sort([3,3,1,2]),
- ?line [1,1,1,1] = lists:sort([1,1,1,1]),
- ?line [1,1,1,2,2,2,3,3,3] = lists:sort([3,3,3,2,2,2,1,1,1]),
- ?line [1,1,1,2,2,2,3,3,3] = lists:sort([1,1,1,2,2,2,3,3,3]),
-
- ?line lists:foreach(fun check/1, perms([1,2,3])),
- ?line lists:foreach(fun check/1, perms([1,2,3,4,5,6,7,8])),
- ok.
-
-sort_rand(doc) -> ["sort/1 on big randomized lists"];
-sort_rand(suite) -> [];
+ [] = lists:sort([]),
+ [a] = lists:sort([a]),
+ [a,a] = lists:sort([a,a]),
+ [a,b] = lists:sort([a,b]),
+ [a,b] = lists:sort([b,a]),
+ [1,1] = lists:sort([1,1]),
+ [1,1,2,3] = lists:sort([1,1,3,2]),
+ [1,2,3,3] = lists:sort([3,3,1,2]),
+ [1,1,1,1] = lists:sort([1,1,1,1]),
+ [1,1,1,2,2,2,3,3,3] = lists:sort([3,3,3,2,2,2,1,1,1]),
+ [1,1,1,2,2,2,3,3,3] = lists:sort([1,1,1,2,2,2,3,3,3]),
+
+ lists:foreach(fun check/1, perms([1,2,3])),
+ lists:foreach(fun check/1, perms([1,2,3,4,5,6,7,8])),
+ ok.
+
+%% sort/1 on big randomized lists
sort_rand(Config) when is_list(Config) ->
- ?line ok = check(biglist(10)),
- ?line ok = check(biglist(100)),
- ?line ok = check(biglist(1000)),
- ?line ok = check(biglist(10000)),
+ ok = check(biglist(10)),
+ ok = check(biglist(100)),
+ ok = check(biglist(1000)),
+ ok = check(biglist(10000)),
ok.
%% sort/1 was really stable for a while - the order of equal elements
%% was kept - but since the performance suffered a bit, this "feature"
%% was removed.
-sort_stable(doc) -> ["sort/1 should be stable for equal terms."];
-sort_stable(suite) -> [];
+
+%% sort/1 should be stable for equal terms.
sort_stable(Config) when is_list(Config) ->
- ?line ok = check_stability(bigfunlist(10)),
- ?line ok = check_stability(bigfunlist(100)),
- ?line ok = check_stability(bigfunlist(1000)),
- ?line case erlang:system_info(modified_timing_level) of
- undefined -> ok = check_stability(bigfunlist(10000));
- _ -> ok
- end,
+ ok = check_stability(bigfunlist(10)),
+ ok = check_stability(bigfunlist(100)),
+ ok = check_stability(bigfunlist(1000)),
+ case erlang:system_info(modified_timing_level) of
+ undefined -> ok = check_stability(bigfunlist(10000));
+ _ -> ok
+ end,
ok.
check([]) ->
@@ -619,188 +591,180 @@ expl_pid([], L) ->
L.
-usort_1(suite) -> [];
-usort_1(doc) -> [""];
usort_1(Conf) when is_list(Conf) ->
- ?line [] = lists:usort([]),
- ?line [1] = lists:usort([1]),
- ?line [1] = lists:usort([1,1]),
- ?line [1] = lists:usort([1,1,1,1,1]),
- ?line [1,2] = lists:usort([1,2]),
- ?line [1,2] = lists:usort([1,2,1]),
- ?line [1,2] = lists:usort([1,2,2]),
- ?line [1,2,3] = lists:usort([1,3,2]),
- ?line [1,3] = lists:usort([3,1,3]),
- ?line [0,1,3] = lists:usort([3,1,0]),
- ?line [1,2,3] = lists:usort([3,1,2]),
- ?line [1,2] = lists:usort([2,1,1]),
- ?line [1,2] = lists:usort([2,1]),
- ?line [0,3,4,8,9] = lists:usort([3,8,9,0,9,4]),
-
- ?line lists:foreach(fun ucheck/1, perms([1,2,3])),
- ?line lists:foreach(fun ucheck/1, perms([1,2,3,4,5,6,2,1])),
-
- ok.
-
-umerge(suite) -> [];
-umerge(doc) -> [""];
+ [] = lists:usort([]),
+ [1] = lists:usort([1]),
+ [1] = lists:usort([1,1]),
+ [1] = lists:usort([1,1,1,1,1]),
+ [1,2] = lists:usort([1,2]),
+ [1,2] = lists:usort([1,2,1]),
+ [1,2] = lists:usort([1,2,2]),
+ [1,2,3] = lists:usort([1,3,2]),
+ [1,3] = lists:usort([3,1,3]),
+ [0,1,3] = lists:usort([3,1,0]),
+ [1,2,3] = lists:usort([3,1,2]),
+ [1,2] = lists:usort([2,1,1]),
+ [1,2] = lists:usort([2,1]),
+ [0,3,4,8,9] = lists:usort([3,8,9,0,9,4]),
+
+ lists:foreach(fun ucheck/1, perms([1,2,3])),
+ lists:foreach(fun ucheck/1, perms([1,2,3,4,5,6,2,1])),
+
+ ok.
+
umerge(Conf) when is_list(Conf) ->
%% merge list of lists
- ?line [] = lists:umerge([]),
- ?line [] = lists:umerge([[]]),
- ?line [] = lists:umerge([[],[]]),
- ?line [] = lists:umerge([[],[],[]]),
- ?line [1] = lists:umerge([[1]]),
- ?line [1,2] = lists:umerge([[1,2],[1,2]]),
- ?line [1] = lists:umerge([[1],[],[]]),
- ?line [1] = lists:umerge([[],[1],[]]),
- ?line [1] = lists:umerge([[],[],[1]]),
- ?line [1,2] = lists:umerge([[1],[2],[]]),
- ?line [1,2] = lists:umerge([[1],[],[2]]),
- ?line [1,2] = lists:umerge([[],[1],[2]]),
- ?line [1,2,3,4,5,6] = lists:umerge([[1,2],[],[5,6],[],[3,4],[]]),
- ?line [1,2,3,4] = lists:umerge([[4],[3],[2],[1]]),
- ?line [1,2,3,4,5] = lists:umerge([[1],[2],[3],[4],[5]]),
- ?line [1,2,3,4,5,6] = lists:umerge([[1],[2],[3],[4],[5],[6]]),
- ?line [1,2,3,4,5,6,7,8,9] =
+ [] = lists:umerge([]),
+ [] = lists:umerge([[]]),
+ [] = lists:umerge([[],[]]),
+ [] = lists:umerge([[],[],[]]),
+ [1] = lists:umerge([[1]]),
+ [1,2] = lists:umerge([[1,2],[1,2]]),
+ [1] = lists:umerge([[1],[],[]]),
+ [1] = lists:umerge([[],[1],[]]),
+ [1] = lists:umerge([[],[],[1]]),
+ [1,2] = lists:umerge([[1],[2],[]]),
+ [1,2] = lists:umerge([[1],[],[2]]),
+ [1,2] = lists:umerge([[],[1],[2]]),
+ [1,2,3,4,5,6] = lists:umerge([[1,2],[],[5,6],[],[3,4],[]]),
+ [1,2,3,4] = lists:umerge([[4],[3],[2],[1]]),
+ [1,2,3,4,5] = lists:umerge([[1],[2],[3],[4],[5]]),
+ [1,2,3,4,5,6] = lists:umerge([[1],[2],[3],[4],[5],[6]]),
+ [1,2,3,4,5,6,7,8,9] =
lists:umerge([[1],[2],[3],[4],[5],[6],[7],[8],[9]]),
- ?line [1,2,4,6,8] = lists:umerge([[1,2],[2,4,6,8]]),
+ [1,2,4,6,8] = lists:umerge([[1,2],[2,4,6,8]]),
Seq = lists:seq(1,100),
- ?line true = Seq == lists:umerge(lists:map(fun(E) -> [E] end, Seq)),
+ true = Seq == lists:umerge(lists:map(fun(E) -> [E] end, Seq)),
Two = [1,2],
Six = [1,2,3,4,5,6],
%% 2-way unique merge
- ?line [] = lists:umerge([], []),
- ?line Two = lists:umerge(Two, []),
- ?line Two = lists:umerge([], Two),
- ?line Six = lists:umerge([1,3,5], [2,4,6]),
- ?line Six = lists:umerge([2,4,6], [1,3,5]),
- ?line Six = lists:umerge([1,2,3], [4,5,6]),
- ?line Six = lists:umerge([4,5,6], [1,2,3]),
- ?line Six = lists:umerge([1,2,5],[3,4,6]),
- ?line [1,2,3,5,7] = lists:umerge([1,3,5,7], [2]),
- ?line [1,2,3,4,5,7] = lists:umerge([1,3,5,7], [2,4]),
- ?line [1,2,3,4,5,6,7] = lists:umerge([1,3,5,7], [2,4,6]),
- ?line [1,2,3,5,7] = lists:umerge([2], [1,3,5,7]),
- ?line [1,2,3,4,5,7] = lists:umerge([2,4], [1,3,5,7]),
- ?line [1,2,3,4,5,6,7] = lists:umerge([2,4,6], [1,3,5,7]),
-
- ?line [1,2,3,5,7] = lists:umerge([1,2,3,5,7], [2]),
- ?line [1,2,3,4,5,7] = lists:umerge([1,2,3,4,5,7], [2,4]),
- ?line [1,2,3,4,5,6,7] = lists:umerge([1,2,3,4,5,6,7], [2,4,6]),
- ?line [1,2,3,5,7] = lists:umerge([2], [1,2,3,5,7]),
- ?line [1,2,3,4,5,7] = lists:umerge([2,4], [1,2,3,4,5,7]),
- ?line [1,2,3,4,5,6,7] = lists:umerge([2,4,6], [1,2,3,4,5,6,7]),
+ [] = lists:umerge([], []),
+ Two = lists:umerge(Two, []),
+ Two = lists:umerge([], Two),
+ Six = lists:umerge([1,3,5], [2,4,6]),
+ Six = lists:umerge([2,4,6], [1,3,5]),
+ Six = lists:umerge([1,2,3], [4,5,6]),
+ Six = lists:umerge([4,5,6], [1,2,3]),
+ Six = lists:umerge([1,2,5],[3,4,6]),
+ [1,2,3,5,7] = lists:umerge([1,3,5,7], [2]),
+ [1,2,3,4,5,7] = lists:umerge([1,3,5,7], [2,4]),
+ [1,2,3,4,5,6,7] = lists:umerge([1,3,5,7], [2,4,6]),
+ [1,2,3,5,7] = lists:umerge([2], [1,3,5,7]),
+ [1,2,3,4,5,7] = lists:umerge([2,4], [1,3,5,7]),
+ [1,2,3,4,5,6,7] = lists:umerge([2,4,6], [1,3,5,7]),
+
+ [1,2,3,5,7] = lists:umerge([1,2,3,5,7], [2]),
+ [1,2,3,4,5,7] = lists:umerge([1,2,3,4,5,7], [2,4]),
+ [1,2,3,4,5,6,7] = lists:umerge([1,2,3,4,5,6,7], [2,4,6]),
+ [1,2,3,5,7] = lists:umerge([2], [1,2,3,5,7]),
+ [1,2,3,4,5,7] = lists:umerge([2,4], [1,2,3,4,5,7]),
+ [1,2,3,4,5,6,7] = lists:umerge([2,4,6], [1,2,3,4,5,6,7]),
%% 3-way unique merge
- ?line [] = lists:umerge3([], [], []),
- ?line Two = lists:umerge3([], [], Two),
- ?line Two = lists:umerge3([], Two, []),
- ?line Two = lists:umerge3(Two, [], []),
- ?line Six = lists:umerge3([], [1,3,5], [2,4,6]),
- ?line Six = lists:umerge3([1,3,5], [], [2,4,6]),
- ?line Six = lists:umerge3([1,3,5], [2,4,6], []),
- ?line Nine = lists:umerge3([1,4,7],[2,5,8],[3,6,9]),
- ?line Nine = lists:umerge3([1,4,7],[3,6,9],[2,5,8]),
- ?line Nine = lists:umerge3([3,6,9],[1,4,7],[2,5,8]),
- ?line Nine = lists:umerge3([4,5,6],[1,2,3],[7,8,9]),
- ?line Nine = lists:umerge3([1,2,3],[4,5,6],[7,8,9]),
- ?line Nine = lists:umerge3([7,8,9],[4,5,6],[1,2,3]),
- ?line Nine = lists:umerge3([4,5,6],[7,8,9],[1,2,3]),
-
- ?line [1,2,3] = lists:umerge3([1,2,3],[1,2,3],[1,2,3]),
- ?line [1,2,3,4] = lists:umerge3([2,3,4],[1,2,3],[2,3,4]),
- ?line [1,2,3] = lists:umerge3([1,2,3],[2,3],[1,2,3]),
- ?line [1,2,3,4] = lists:umerge3([2,3,4],[3,4],[1,2,3]),
-
- ok.
-
-rumerge(suite) -> [];
-rumerge(doc) -> [""];
+ [] = lists:umerge3([], [], []),
+ Two = lists:umerge3([], [], Two),
+ Two = lists:umerge3([], Two, []),
+ Two = lists:umerge3(Two, [], []),
+ Six = lists:umerge3([], [1,3,5], [2,4,6]),
+ Six = lists:umerge3([1,3,5], [], [2,4,6]),
+ Six = lists:umerge3([1,3,5], [2,4,6], []),
+ Nine = lists:umerge3([1,4,7],[2,5,8],[3,6,9]),
+ Nine = lists:umerge3([1,4,7],[3,6,9],[2,5,8]),
+ Nine = lists:umerge3([3,6,9],[1,4,7],[2,5,8]),
+ Nine = lists:umerge3([4,5,6],[1,2,3],[7,8,9]),
+ Nine = lists:umerge3([1,2,3],[4,5,6],[7,8,9]),
+ Nine = lists:umerge3([7,8,9],[4,5,6],[1,2,3]),
+ Nine = lists:umerge3([4,5,6],[7,8,9],[1,2,3]),
+
+ [1,2,3] = lists:umerge3([1,2,3],[1,2,3],[1,2,3]),
+ [1,2,3,4] = lists:umerge3([2,3,4],[1,2,3],[2,3,4]),
+ [1,2,3] = lists:umerge3([1,2,3],[2,3],[1,2,3]),
+ [1,2,3,4] = lists:umerge3([2,3,4],[3,4],[1,2,3]),
+
+ ok.
+
rumerge(Conf) when is_list(Conf) ->
Two = [2,1],
Six = [6,5,4,3,2,1],
%% 2-way reversed unique merge
- ?line [] = lists:rumerge([], []),
- ?line Two = lists:rumerge(Two, []),
- ?line Two = lists:rumerge([], Two),
- ?line Six = lists:rumerge([5,3,1], [6,4,2]),
- ?line Six = lists:rumerge([6,4,2], [5,3,1]),
- ?line Six = lists:rumerge([3,2,1], [6,5,4]),
- ?line Six = lists:rumerge([6,5,4], [3,2,1]),
- ?line Six = lists:rumerge([4,3,2],[6,5,1]),
- ?line [7,6,5,3,1] = lists:rumerge([7,5,3,1], [6]),
- ?line [7,6,5,4,3,1] = lists:rumerge([7,5,3,1], [6,4]),
- ?line [7,6,5,4,3,2,1] = lists:rumerge([7,5,3,1], [6,4,2]),
- ?line [7,5,3,2,1] = lists:rumerge([2], [7,5,3,1]),
- ?line [7,5,4,3,2,1] = lists:rumerge([4,2], [7,5,3,1]),
- ?line [7,6,5,4,3,2,1] = lists:rumerge([6,4,2], [7,5,3,1]),
-
- ?line [7,6,5,3,1] = lists:rumerge([7,6,5,3,1], [6]),
- ?line [7,6,5,4,3,1] = lists:rumerge([7,6,5,4,3,1], [6,4]),
- ?line [7,6,5,4,3,2,1] = lists:rumerge([7,6,5,4,3,2,1], [6,4,2]),
- ?line [7,5,3,2,1] = lists:rumerge([2], [7,5,3,2,1]),
- ?line [7,5,4,3,2,1] = lists:rumerge([4,2], [7,5,4,3,2,1]),
- ?line [7,6,5,4,3,2,1] = lists:rumerge([6,4,2], [7,6,5,4,3,2,1]),
+ [] = lists:rumerge([], []),
+ Two = lists:rumerge(Two, []),
+ Two = lists:rumerge([], Two),
+ Six = lists:rumerge([5,3,1], [6,4,2]),
+ Six = lists:rumerge([6,4,2], [5,3,1]),
+ Six = lists:rumerge([3,2,1], [6,5,4]),
+ Six = lists:rumerge([6,5,4], [3,2,1]),
+ Six = lists:rumerge([4,3,2],[6,5,1]),
+ [7,6,5,3,1] = lists:rumerge([7,5,3,1], [6]),
+ [7,6,5,4,3,1] = lists:rumerge([7,5,3,1], [6,4]),
+ [7,6,5,4,3,2,1] = lists:rumerge([7,5,3,1], [6,4,2]),
+ [7,5,3,2,1] = lists:rumerge([2], [7,5,3,1]),
+ [7,5,4,3,2,1] = lists:rumerge([4,2], [7,5,3,1]),
+ [7,6,5,4,3,2,1] = lists:rumerge([6,4,2], [7,5,3,1]),
+
+ [7,6,5,3,1] = lists:rumerge([7,6,5,3,1], [6]),
+ [7,6,5,4,3,1] = lists:rumerge([7,6,5,4,3,1], [6,4]),
+ [7,6,5,4,3,2,1] = lists:rumerge([7,6,5,4,3,2,1], [6,4,2]),
+ [7,5,3,2,1] = lists:rumerge([2], [7,5,3,2,1]),
+ [7,5,4,3,2,1] = lists:rumerge([4,2], [7,5,4,3,2,1]),
+ [7,6,5,4,3,2,1] = lists:rumerge([6,4,2], [7,6,5,4,3,2,1]),
Nine = [9,8,7,6,5,4,3,2,1],
%% 3-way reversed unique merge
- ?line [] = lists:rumerge3([], [], []),
- ?line Two = lists:rumerge3([], [], Two),
- ?line Two = lists:rumerge3([], Two, []),
- ?line Two = lists:rumerge3(Two, [], []),
- ?line Six = lists:rumerge3([], [5,3,1], [6,4,2]),
- ?line Six = lists:rumerge3([5,3,1], [], [6,4,2]),
- ?line Six = lists:rumerge3([5,3,1], [6,4,2], []),
- ?line Nine = lists:rumerge3([7,4,1],[8,5,2],[9,6,3]),
- ?line Nine = lists:rumerge3([7,4,1],[9,6,3],[8,5,2]),
- ?line Nine = lists:rumerge3([9,6,3],[7,4,1],[8,5,2]),
- ?line Nine = lists:rumerge3([6,5,4],[3,2,1],[9,8,7]),
- ?line Nine = lists:rumerge3([3,2,1],[6,5,4],[9,8,7]),
- ?line Nine = lists:rumerge3([9,8,7],[6,5,4],[3,2,1]),
- ?line Nine = lists:rumerge3([6,5,4],[9,8,7],[3,2,1]),
-
- ?line [3,2,1] = lists:rumerge3([3,2,1],[3,2,1],[3,2,1]),
- ?line [4,3,2,1] = lists:rumerge3([4,3,2],[3,2,1],[3,2,1]),
- ?line [5,4,3,2,1] = lists:rumerge3([4,3,2],[5,4,3,2],[5,4,3,2,1]),
- ?line [6,5,4,3,2] = lists:rumerge3([4,3,2],[5,4,3,2],[6,5,4,3]),
+ [] = lists:rumerge3([], [], []),
+ Two = lists:rumerge3([], [], Two),
+ Two = lists:rumerge3([], Two, []),
+ Two = lists:rumerge3(Two, [], []),
+ Six = lists:rumerge3([], [5,3,1], [6,4,2]),
+ Six = lists:rumerge3([5,3,1], [], [6,4,2]),
+ Six = lists:rumerge3([5,3,1], [6,4,2], []),
+ Nine = lists:rumerge3([7,4,1],[8,5,2],[9,6,3]),
+ Nine = lists:rumerge3([7,4,1],[9,6,3],[8,5,2]),
+ Nine = lists:rumerge3([9,6,3],[7,4,1],[8,5,2]),
+ Nine = lists:rumerge3([6,5,4],[3,2,1],[9,8,7]),
+ Nine = lists:rumerge3([3,2,1],[6,5,4],[9,8,7]),
+ Nine = lists:rumerge3([9,8,7],[6,5,4],[3,2,1]),
+ Nine = lists:rumerge3([6,5,4],[9,8,7],[3,2,1]),
+
+ [3,2,1] = lists:rumerge3([3,2,1],[3,2,1],[3,2,1]),
+ [4,3,2,1] = lists:rumerge3([4,3,2],[3,2,1],[3,2,1]),
+ [5,4,3,2,1] = lists:rumerge3([4,3,2],[5,4,3,2],[5,4,3,2,1]),
+ [6,5,4,3,2] = lists:rumerge3([4,3,2],[5,4,3,2],[6,5,4,3]),
L1 = [c,d,e],
L2 = [b,c,d],
- ?line true =
+ true =
lists:umerge(L1, L2) ==
lists:reverse(lists:rumerge(lists:reverse(L1), lists:reverse(L2))),
ok.
-usort_rand(doc) -> ["usort/1 on big randomized lists"];
-usort_rand(suite) -> [];
+%% usort/1 on big randomized lists.
usort_rand(Config) when is_list(Config) ->
- ?line ok = ucheck(biglist(10)),
- ?line ok = ucheck(biglist(100)),
- ?line ok = ucheck(biglist(1000)),
- ?line ok = ucheck(biglist(10000)),
+ ok = ucheck(biglist(10)),
+ ok = ucheck(biglist(100)),
+ ok = ucheck(biglist(1000)),
+ ok = ucheck(biglist(10000)),
- ?line ok = ucheck(ubiglist(10)),
- ?line ok = ucheck(ubiglist(100)),
- ?line ok = ucheck(ubiglist(1000)),
- ?line ok = ucheck(ubiglist(10000)),
+ ok = ucheck(ubiglist(10)),
+ ok = ucheck(ubiglist(100)),
+ ok = ucheck(ubiglist(1000)),
+ ok = ucheck(ubiglist(10000)),
ok.
-usort_stable(doc) -> ["usort/1 should keep the first duplicate."];
-usort_stable(suite) -> [];
+%% usort/1 should keep the first duplicate.
usort_stable(Config) when is_list(Config) ->
- ?line ok = ucheck_stability(bigfunlist(3)),
- ?line ok = ucheck_stability(bigfunlist(10)),
- ?line ok = ucheck_stability(bigfunlist(100)),
- ?line ok = ucheck_stability(bigfunlist(1000)),
- ?line case erlang:system_info(modified_timing_level) of
- undefined -> ok = ucheck_stability(bigfunlist(10000));
- _ -> ok
- end,
+ ok = ucheck_stability(bigfunlist(3)),
+ ok = ucheck_stability(bigfunlist(10)),
+ ok = ucheck_stability(bigfunlist(100)),
+ ok = ucheck_stability(bigfunlist(1000)),
+ case erlang:system_info(modified_timing_level) of
+ undefined -> ok = ucheck_stability(bigfunlist(10000));
+ _ -> ok
+ end,
ok.
ucheck([]) ->
@@ -829,163 +793,155 @@ ucheck_stability(L) ->
check_stab(L, U, S, "usort/1", "ukeysort/2").
-keymerge(doc) -> ["Key merge two lists."];
-keymerge(suite) -> [];
+%% Key merge two lists.
keymerge(Config) when is_list(Config) ->
Two = [{1,a},{2,b}],
Six = [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f}],
%% 2-way keymerge
- ?line [] = lists:keymerge(1, [], []),
- ?line Two = lists:keymerge(1, Two, []),
- ?line Two = lists:keymerge(1, [], Two),
- ?line Six = lists:keymerge(1, [{1,a},{3,c},{5,e}], [{2,b},{4,d},{6,f}]),
- ?line Six = lists:keymerge(1, [{2,b},{4,d},{6,f}], [{1,a},{3,c},{5,e}]),
- ?line Six = lists:keymerge(1, [{1,a},{2,b},{3,c}], [{4,d},{5,e},{6,f}]),
- ?line Six = lists:keymerge(1, [{4,d},{5,e},{6,f}], [{1,a},{2,b},{3,c}]),
- ?line Six = lists:keymerge(1, [{1,a},{2,b},{5,e}],[{3,c},{4,d},{6,f}]),
- ?line [{1,a},{2,b},{3,c},{5,e},{7,g}] =
+ [] = lists:keymerge(1, [], []),
+ Two = lists:keymerge(1, Two, []),
+ Two = lists:keymerge(1, [], Two),
+ Six = lists:keymerge(1, [{1,a},{3,c},{5,e}], [{2,b},{4,d},{6,f}]),
+ Six = lists:keymerge(1, [{2,b},{4,d},{6,f}], [{1,a},{3,c},{5,e}]),
+ Six = lists:keymerge(1, [{1,a},{2,b},{3,c}], [{4,d},{5,e},{6,f}]),
+ Six = lists:keymerge(1, [{4,d},{5,e},{6,f}], [{1,a},{2,b},{3,c}]),
+ Six = lists:keymerge(1, [{1,a},{2,b},{5,e}],[{3,c},{4,d},{6,f}]),
+ [{1,a},{2,b},{3,c},{5,e},{7,g}] =
lists:keymerge(1, [{1,a},{3,c},{5,e},{7,g}], [{2,b}]),
- ?line [{1,a},{2,b},{3,c},{4,d},{5,e},{7,g}] =
+ [{1,a},{2,b},{3,c},{4,d},{5,e},{7,g}] =
lists:keymerge(1, [{1,a},{3,c},{5,e},{7,g}], [{2,b},{4,d}]),
- ?line [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g}] =
+ [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g}] =
lists:keymerge(1, [{1,a},{3,c},{5,e},{7,g}], [{2,b},{4,d},{6,f}]),
- ?line [{1,a},{2,b},{3,c},{5,e},{7,g}] =
+ [{1,a},{2,b},{3,c},{5,e},{7,g}] =
lists:keymerge(1, [{2,b}], [{1,a},{3,c},{5,e},{7,g}]),
- ?line [{1,a},{2,b},{3,c},{4,d},{5,e},{7,g}] =
+ [{1,a},{2,b},{3,c},{4,d},{5,e},{7,g}] =
lists:keymerge(1, [{2,b},{4,d}], [{1,a},{3,c},{5,e},{7,g}]),
- ?line [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g}] =
+ [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g}] =
lists:keymerge(1, [{2,b},{4,d},{6,f}], [{1,a},{3,c},{5,e},{7,g}]),
- ?line [{b,2},{c,11},{c,12},{c,21},{c,22},{e,5}] =
+ [{b,2},{c,11},{c,12},{c,21},{c,22},{e,5}] =
lists:keymerge(1,[{c,11},{c,12},{e,5}], [{b,2},{c,21},{c,22}]),
ok.
-rkeymerge(doc) -> ["Reverse key merge two lists."];
-rkeymerge(suite) -> [];
+%% Reverse key merge two lists.
rkeymerge(Config) when is_list(Config) ->
Two = [{2,b},{1,a}],
Six = [{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}],
%% 2-way reversed keymerge
- ?line [] = lists:rkeymerge(1, [], []),
- ?line Two = lists:rkeymerge(1, Two, []),
- ?line Two = lists:rkeymerge(1, [], Two),
- ?line Six = lists:rkeymerge(1, [{5,e},{3,c},{1,a}], [{6,f},{4,d},{2,b}]),
- ?line Six = lists:rkeymerge(1, [{6,f},{4,d},{2,b}], [{5,e},{3,c},{1,a}]),
- ?line Six = lists:rkeymerge(1, [{3,c},{2,b},{1,a}], [{6,f},{5,e},{4,d}]),
- ?line Six = lists:rkeymerge(1, [{6,f},{5,e},{4,d}], [{3,c},{2,b},{1,a}]),
- ?line Six = lists:rkeymerge(1, [{4,d},{3,c},{2,b}],[{6,f},{5,e},{1,a}]),
- ?line [{7,g},{6,f},{5,e},{3,c},{1,a}] =
+ [] = lists:rkeymerge(1, [], []),
+ Two = lists:rkeymerge(1, Two, []),
+ Two = lists:rkeymerge(1, [], Two),
+ Six = lists:rkeymerge(1, [{5,e},{3,c},{1,a}], [{6,f},{4,d},{2,b}]),
+ Six = lists:rkeymerge(1, [{6,f},{4,d},{2,b}], [{5,e},{3,c},{1,a}]),
+ Six = lists:rkeymerge(1, [{3,c},{2,b},{1,a}], [{6,f},{5,e},{4,d}]),
+ Six = lists:rkeymerge(1, [{6,f},{5,e},{4,d}], [{3,c},{2,b},{1,a}]),
+ Six = lists:rkeymerge(1, [{4,d},{3,c},{2,b}],[{6,f},{5,e},{1,a}]),
+ [{7,g},{6,f},{5,e},{3,c},{1,a}] =
lists:rkeymerge(1, [{7,g},{5,e},{3,c},{1,a}], [{6,f}]),
- ?line [{7,g},{6,f},{5,e},{4,d},{3,c},{1,a}] =
+ [{7,g},{6,f},{5,e},{4,d},{3,c},{1,a}] =
lists:rkeymerge(1, [{7,g},{5,e},{3,c},{1,a}], [{6,f},{4,d}]),
- ?line [{7,g},{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}] =
+ [{7,g},{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}] =
lists:rkeymerge(1, [{7,g},{5,e},{3,c},{1,a}], [{6,f},{4,d},{2,b}]),
- ?line [{7,g},{5,e},{3,c},{2,b},{1,a}] =
+ [{7,g},{5,e},{3,c},{2,b},{1,a}] =
lists:rkeymerge(1, [{2,b}], [{7,g},{5,e},{3,c},{1,a}]),
- ?line [{7,g},{5,e},{4,d},{3,c},{2,b},{1,a}] =
+ [{7,g},{5,e},{4,d},{3,c},{2,b},{1,a}] =
lists:rkeymerge(1, [{4,d},{2,b}], [{7,g},{5,e},{3,c},{1,a}]),
- ?line [{7,g},{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}] =
+ [{7,g},{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}] =
lists:rkeymerge(1, [{6,f},{4,d},{2,b}], [{7,g},{5,e},{3,c},{1,a}]),
L1 = [{c,11},{c,12},{e,5}],
L2 = [{b,2},{c,21},{c,22}],
- ?line true =
+ true =
lists:keymerge(1, L1, L2) ==
lists:reverse(lists:rkeymerge(1,lists:reverse(L1),
lists:reverse(L2))),
ok.
-keysort_1(doc) -> ["keysort"];
-keysort_1(suite) -> [];
keysort_1(Config) when is_list(Config) ->
- ?line ok = keysort_check(1, [], []),
- ?line ok = keysort_check(1, [{a,b}], [{a,b}]),
- ?line ok = keysort_check(1, [{a,b},{a,b}], [{a,b},{a,b}]),
- ?line ok = keysort_check(1, [{a,b},{b,c}], [{a,b},{b,c}]),
- ?line ok = keysort_check(1, [{b,c},{a,b}], [{a,b},{b,c}]),
- ?line ok = keysort_check(1,
- [{1,e},{3,f},{2,y},{0,z},{x,14}],
- [{0,z},{1,e},{2,y},{3,f},{x,14}]),
- ?line ok = keysort_check(1,
- [{1,a},{1,a},{1,a},{1,a}],
- [{1,a},{1,a},{1,a},{1,a}]),
-
- ?line [{b,1},{c,1}] = lists:keysort(1, [{c,1},{b,1}]),
- ?line [{a,0},{b,2},{c,3},{d,4}] =
- lists:keysort(1, [{d,4},{c,3},{b,2},{a,0}]),
- ?line [{a,0},{b,1},{b,2},{c,1}] =
- lists:keysort(1, [{c,1},{b,1},{b,2},{a,0}]),
- ?line [{a,0},{b,1},{b,2},{c,1},{d,4}] =
- lists:keysort(1, [{c,1},{b,1},{b,2},{a,0},{d,4}]),
+ ok = keysort_check(1, [], []),
+ ok = keysort_check(1, [{a,b}], [{a,b}]),
+ ok = keysort_check(1, [{a,b},{a,b}], [{a,b},{a,b}]),
+ ok = keysort_check(1, [{a,b},{b,c}], [{a,b},{b,c}]),
+ ok = keysort_check(1, [{b,c},{a,b}], [{a,b},{b,c}]),
+ ok = keysort_check(1,
+ [{1,e},{3,f},{2,y},{0,z},{x,14}],
+ [{0,z},{1,e},{2,y},{3,f},{x,14}]),
+ ok = keysort_check(1,
+ [{1,a},{1,a},{1,a},{1,a}],
+ [{1,a},{1,a},{1,a},{1,a}]),
+
+ [{b,1},{c,1}] = lists:keysort(1, [{c,1},{b,1}]),
+ [{a,0},{b,2},{c,3},{d,4}] =
+ lists:keysort(1, [{d,4},{c,3},{b,2},{a,0}]),
+ [{a,0},{b,1},{b,2},{c,1}] =
+ lists:keysort(1, [{c,1},{b,1},{b,2},{a,0}]),
+ [{a,0},{b,1},{b,2},{c,1},{d,4}] =
+ lists:keysort(1, [{c,1},{b,1},{b,2},{a,0},{d,4}]),
SFun = fun(L) -> fun(X) -> keysort_check(1, X, L) end end,
L1 = [{1,a},{2,b},{3,c}],
- ?line lists:foreach(SFun(L1), perms(L1)),
+ lists:foreach(SFun(L1), perms(L1)),
L2 = [{1,a},{1,a},{2,b}],
- ?line lists:foreach(SFun(L2), perms(L2)),
+ lists:foreach(SFun(L2), perms(L2)),
L3 = [{1,a},{1,a},{1,a},{2,b}],
- ?line lists:foreach(SFun(L3), perms(L3)),
+ lists:foreach(SFun(L3), perms(L3)),
L4 = [{a,1},{a,1},{b,2},{b,2},{c,3},{d,4},{e,5},{f,6}],
- ?line lists:foreach(SFun(L4), perms(L4)),
+ lists:foreach(SFun(L4), perms(L4)),
ok.
-keysort_stable(doc) -> ["keysort should be stable"];
-keysort_stable(suite) -> [];
+%% keysort should be stable
keysort_stable(Config) when is_list(Config) ->
- ?line ok = keysort_check(1, [{1,b},{1,c}], [{1,b},{1,c}]),
- ?line ok = keysort_check(1, [{1,c},{1,b}], [{1,c},{1,b}]),
- ?line ok = keysort_check(1,
- [{1,c},{1,b},{2,x},{3,p},{2,a}],
- [{1,c},{1,b},{2,x},{2,a},{3,p}]),
- ?line ok = keysort_check(1,
- [{1,a},{1,b},{1,a},{1,a}],
- [{1,a},{1,b},{1,a},{1,a}]),
- ok.
-
-keysort_error(doc) -> ["keysort should exit when given bad arguments"];
-keysort_error(suite) -> [];
+ ok = keysort_check(1, [{1,b},{1,c}], [{1,b},{1,c}]),
+ ok = keysort_check(1, [{1,c},{1,b}], [{1,c},{1,b}]),
+ ok = keysort_check(1,
+ [{1,c},{1,b},{2,x},{3,p},{2,a}],
+ [{1,c},{1,b},{2,x},{2,a},{3,p}]),
+ ok = keysort_check(1,
+ [{1,a},{1,b},{1,a},{1,a}],
+ [{1,a},{1,b},{1,a},{1,a}]),
+ ok.
+
+%% keysort should exit when given bad arguments
keysort_error(Config) when is_list(Config) ->
- ?line {'EXIT', _} = (catch lists:keysort(0, [{1,b},{1,c}])),
- ?line {'EXIT', _} = (catch lists:keysort(3, [{1,b},{1,c}])),
- ?line {'EXIT', _} = (catch lists:keysort(1.5, [{1,b},{1,c}])),
- ?line {'EXIT', _} = (catch lists:keysort(x, [{1,b},{1,c}])),
- ?line {'EXIT', _} = (catch lists:keysort(x, [])),
- ?line {'EXIT', _} = (catch lists:keysort(x, [{1,b}])),
- ?line {'EXIT', _} = (catch lists:keysort(1, [a,b])),
- ?line {'EXIT', _} = (catch lists:keysort(1, [{1,b} | {1,c}])),
- ok.
-
-keysort_i(doc) -> ["keysort with other key than first element"];
-keysort_i(suite) -> [];
+ {'EXIT', _} = (catch lists:keysort(0, [{1,b},{1,c}])),
+ {'EXIT', _} = (catch lists:keysort(3, [{1,b},{1,c}])),
+ {'EXIT', _} = (catch lists:keysort(1.5, [{1,b},{1,c}])),
+ {'EXIT', _} = (catch lists:keysort(x, [{1,b},{1,c}])),
+ {'EXIT', _} = (catch lists:keysort(x, [])),
+ {'EXIT', _} = (catch lists:keysort(x, [{1,b}])),
+ {'EXIT', _} = (catch lists:keysort(1, [a,b])),
+ {'EXIT', _} = (catch lists:keysort(1, [{1,b} | {1,c}])),
+ ok.
+
+%% keysort with other key than first element
keysort_i(Config) when is_list(Config) ->
- ?line ok = keysort_check(2, [{a,2},{b,1},{c,3}], [{b,1},{a,2},{c,3}]),
+ ok = keysort_check(2, [{a,2},{b,1},{c,3}], [{b,1},{a,2},{c,3}]),
ok.
-keysort_rand(doc) -> ["keysort on big randomized lists"];
-keysort_rand(suite) -> [];
+%% keysort on big randomized lists
keysort_rand(Config) when is_list(Config) ->
- ?line ok = keysort_check3(1, biglist(10)),
- ?line ok = keysort_check3(1, biglist(100)),
- ?line ok = keysort_check3(1, biglist(1000)),
- ?line ok = keysort_check3(1, biglist(10000)),
+ ok = keysort_check3(1, biglist(10)),
+ ok = keysort_check3(1, biglist(100)),
+ ok = keysort_check3(1, biglist(1000)),
+ ok = keysort_check3(1, biglist(10000)),
- ?line ok = keysort_check3(2, biglist(10)),
- ?line ok = keysort_check3(2, biglist(100)),
- ?line ok = keysort_check3(2, biglist(1000)),
- ?line ok = keysort_check3(2, biglist(10000)),
+ ok = keysort_check3(2, biglist(10)),
+ ok = keysort_check3(2, biglist(100)),
+ ok = keysort_check3(2, biglist(1000)),
+ ok = keysort_check3(2, biglist(10000)),
ok.
%%% Keysort a list, check that the returned list is what we expected,
%%% and that it is actually sorted.
keysort_check(I, Input, Expected) ->
- ?line Expected = lists:keysort(I, Input),
+ Expected = lists:keysort(I, Input),
check_sorted(I, Input, Expected).
keysort_check3(I, Input) ->
@@ -1020,232 +976,223 @@ keycompare(I, J, A, B) when element(I, A) == element(I, B),
ok.
-ukeymerge(suite) -> [];
-ukeymerge(doc) -> ["Merge two lists while removing duplicates."];
+%% Merge two lists while removing duplicates.
ukeymerge(Conf) when is_list(Conf) ->
Two = [{1,a},{2,b}],
Six = [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f}],
%% 2-way unique keymerge
- ?line [] = lists:ukeymerge(1, [], []),
- ?line Two = lists:ukeymerge(1, Two, []),
- ?line Two = lists:ukeymerge(1, [], Two),
- ?line [] = lists:ukeymerge(1, [], []),
- ?line Two = lists:ukeymerge(1, Two, []),
- ?line Two = lists:ukeymerge(1, [], Two),
- ?line Six = lists:ukeymerge(1, [{1,a},{3,c},{5,e}], [{2,b},{4,d},{6,f}]),
- ?line Six = lists:ukeymerge(1, [{2,b},{4,d},{6,f}], [{1,a},{3,c},{5,e}]),
- ?line Six = lists:ukeymerge(1, [{1,a},{2,b},{3,c}], [{4,d},{5,e},{6,f}]),
- ?line Six = lists:ukeymerge(1, [{4,d},{5,e},{6,f}], [{1,a},{2,b},{3,c}]),
- ?line Six = lists:ukeymerge(1, [{1,a},{2,b},{5,e}],[{3,c},{4,d},{6,f}]),
- ?line [{1,a},{2,b},{3,c},{5,e},{7,g}] =
+ [] = lists:ukeymerge(1, [], []),
+ Two = lists:ukeymerge(1, Two, []),
+ Two = lists:ukeymerge(1, [], Two),
+ [] = lists:ukeymerge(1, [], []),
+ Two = lists:ukeymerge(1, Two, []),
+ Two = lists:ukeymerge(1, [], Two),
+ Six = lists:ukeymerge(1, [{1,a},{3,c},{5,e}], [{2,b},{4,d},{6,f}]),
+ Six = lists:ukeymerge(1, [{2,b},{4,d},{6,f}], [{1,a},{3,c},{5,e}]),
+ Six = lists:ukeymerge(1, [{1,a},{2,b},{3,c}], [{4,d},{5,e},{6,f}]),
+ Six = lists:ukeymerge(1, [{4,d},{5,e},{6,f}], [{1,a},{2,b},{3,c}]),
+ Six = lists:ukeymerge(1, [{1,a},{2,b},{5,e}],[{3,c},{4,d},{6,f}]),
+ [{1,a},{2,b},{3,c},{5,e},{7,g}] =
lists:ukeymerge(1, [{1,a},{3,c},{5,e},{7,g}], [{2,b}]),
- ?line [{1,a},{2,b},{3,c},{4,d},{5,e},{7,g}] =
+ [{1,a},{2,b},{3,c},{4,d},{5,e},{7,g}] =
lists:ukeymerge(1, [{1,a},{3,c},{5,e},{7,g}], [{2,b},{4,d}]),
- ?line [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g}] =
+ [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g}] =
lists:ukeymerge(1, [{1,a},{3,c},{5,e},{7,g}], [{2,b},{4,d},{6,f}]),
- ?line [{1,a},{2,b},{3,c},{5,e},{7,g}] =
+ [{1,a},{2,b},{3,c},{5,e},{7,g}] =
lists:ukeymerge(1, [{2,b}], [{1,a},{3,c},{5,e},{7,g}]),
- ?line [{1,a},{2,b},{3,c},{4,d},{5,e},{7,g}] =
+ [{1,a},{2,b},{3,c},{4,d},{5,e},{7,g}] =
lists:ukeymerge(1, [{2,b},{4,d}], [{1,a},{3,c},{5,e},{7,g}]),
- ?line [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g}] =
+ [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g}] =
lists:ukeymerge(1, [{2,b},{4,d},{6,f}], [{1,a},{3,c},{5,e},{7,g}]),
- ?line [{1,a},{2,b},{3,c},{5,e},{7,g}] =
+ [{1,a},{2,b},{3,c},{5,e},{7,g}] =
lists:ukeymerge(1, [{1,a},{2,b},{3,c},{5,e},{7,g}], [{2,b}]),
- ?line [{1,a},{2,b},{3,c},{4,d},{5,e},{7,g}] =
+ [{1,a},{2,b},{3,c},{4,d},{5,e},{7,g}] =
lists:ukeymerge(1, [{1,a},{2,b},{3,c},{4,d},{5,e},{7,g}],
[{2,b},{4,d}]),
- ?line [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g}] =
+ [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g}] =
lists:ukeymerge(1, [{1,a},{3,c},{5,e},{6,f},{7,g}],
[{2,b},{4,d},{6,f}]),
- ?line [{1,a},{2,b},{3,c},{5,e},{7,g}] =
+ [{1,a},{2,b},{3,c},{5,e},{7,g}] =
lists:ukeymerge(1, [{2,b}], [{1,a},{2,b},{3,c},{5,e},{7,g}]),
- ?line [{1,a},{2,b},{3,c},{4,d},{5,e},{7,g}] =
+ [{1,a},{2,b},{3,c},{4,d},{5,e},{7,g}] =
lists:ukeymerge(1, [{2,b},{4,d}],
[{1,a},{2,b},{3,c},{4,d},{5,e},{7,g}]),
- ?line [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g}] =
+ [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g}] =
lists:ukeymerge(1, [{2,b},{4,d},{6,f}],
- [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g}]),
+ [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g}]),
L1 = [{a,1},{a,3},{a,5},{a,7}],
L2 = [{b,1},{b,3},{b,5},{b,7}],
- ?line L1 = lists:ukeymerge(2, L1, L2),
+ L1 = lists:ukeymerge(2, L1, L2),
ok.
-rukeymerge(suite) -> [];
-rukeymerge(doc) ->
- ["Reverse merge two lists while removing duplicates."];
+%% Reverse merge two lists while removing duplicates.
rukeymerge(Conf) when is_list(Conf) ->
Two = [{2,b},{1,a}],
Six = [{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}],
%% 2-way reversed unique keymerge
- ?line [] = lists:rukeymerge(1, [], []),
- ?line Two = lists:rukeymerge(1, Two, []),
- ?line Two = lists:rukeymerge(1, [], Two),
- ?line Six = lists:rukeymerge(1, [{5,e},{3,c},{1,a}], [{6,f},{4,d},{2,b}]),
- ?line Six = lists:rukeymerge(1, [{6,f},{4,d},{2,b}], [{5,e},{3,c},{1,a}]),
- ?line Six = lists:rukeymerge(1, [{3,c},{2,b},{1,a}], [{6,f},{5,e},{4,d}]),
- ?line Six = lists:rukeymerge(1, [{6,f},{5,e},{4,d}], [{3,c},{2,b},{1,a}]),
- ?line Six = lists:rukeymerge(1, [{4,d},{3,c},{2,b}],[{6,f},{5,e},{1,a}]),
- ?line [{7,g},{6,f},{5,e},{3,c},{1,a}] =
+ [] = lists:rukeymerge(1, [], []),
+ Two = lists:rukeymerge(1, Two, []),
+ Two = lists:rukeymerge(1, [], Two),
+ Six = lists:rukeymerge(1, [{5,e},{3,c},{1,a}], [{6,f},{4,d},{2,b}]),
+ Six = lists:rukeymerge(1, [{6,f},{4,d},{2,b}], [{5,e},{3,c},{1,a}]),
+ Six = lists:rukeymerge(1, [{3,c},{2,b},{1,a}], [{6,f},{5,e},{4,d}]),
+ Six = lists:rukeymerge(1, [{6,f},{5,e},{4,d}], [{3,c},{2,b},{1,a}]),
+ Six = lists:rukeymerge(1, [{4,d},{3,c},{2,b}],[{6,f},{5,e},{1,a}]),
+ [{7,g},{6,f},{5,e},{3,c},{1,a}] =
lists:rukeymerge(1, [{7,g},{5,e},{3,c},{1,a}], [{6,f}]),
- ?line [{7,g},{6,f},{5,e},{4,d},{3,c},{1,a}] =
+ [{7,g},{6,f},{5,e},{4,d},{3,c},{1,a}] =
lists:rukeymerge(1, [{7,g},{5,e},{3,c},{1,a}], [{6,f},{4,d}]),
- ?line [{7,g},{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}] =
+ [{7,g},{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}] =
lists:rukeymerge(1, [{7,g},{5,e},{3,c},{1,a}], [{6,f},{4,d},{2,b}]),
- ?line [{7,g},{5,e},{3,c},{2,b},{1,a}] =
+ [{7,g},{5,e},{3,c},{2,b},{1,a}] =
lists:rukeymerge(1, [{2,b}], [{7,g},{5,e},{3,c},{1,a}]),
- ?line [{7,g},{5,e},{4,d},{3,c},{2,b},{1,a}] =
+ [{7,g},{5,e},{4,d},{3,c},{2,b},{1,a}] =
lists:rukeymerge(1, [{4,d},{2,b}], [{7,g},{5,e},{3,c},{1,a}]),
- ?line [{7,g},{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}] =
+ [{7,g},{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}] =
lists:rukeymerge(1, [{6,f},{4,d},{2,b}], [{7,g},{5,e},{3,c},{1,a}]),
- ?line [{7,g},{6,f},{5,e},{3,c},{1,a}] =
+ [{7,g},{6,f},{5,e},{3,c},{1,a}] =
lists:rukeymerge(1, [{7,g},{6,f},{5,e},{3,c},{1,a}], [{6,f}]),
- ?line [{7,g},{6,f},{5,e},{4,d},{3,c},{1,a}] =
+ [{7,g},{6,f},{5,e},{4,d},{3,c},{1,a}] =
lists:rukeymerge(1, [{7,g},{6,f},{5,e},{4,d},{3,c},{1,a}],
[{6,f},{4,d}]),
- ?line [{7,g},{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}] =
+ [{7,g},{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}] =
lists:rukeymerge(1, [{7,g},{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}],
- [{6,f},{4,d},{2,b}]),
- ?line [{7,g},{5,e},{3,c},{2,b},{1,a}] =
+ [{6,f},{4,d},{2,b}]),
+ [{7,g},{5,e},{3,c},{2,b},{1,a}] =
lists:rukeymerge(1, [{2,b}], [{7,g},{5,e},{3,c},{2,b},{1,a}]),
- ?line [{7,g},{5,e},{4,d},{3,c},{2,b},{1,a}] =
+ [{7,g},{5,e},{4,d},{3,c},{2,b},{1,a}] =
lists:rukeymerge(1, [{4,d},{2,b}],
[{7,g},{5,e},{4,d},{3,c},{2,b},{1,a}]),
- ?line [{7,g},{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}] =
+ [{7,g},{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}] =
lists:rukeymerge(1, [{6,f},{4,d},{2,b}],
- [{7,g},{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}]),
+ [{7,g},{6,f},{5,e},{4,d},{3,c},{2,b},{1,a}]),
L1 = [{a,1},{a,3},{a,5},{a,7}],
L2 = [{b,1},{b,3},{b,5},{b,7}],
- ?line true =
+ true =
lists:ukeymerge(2, L1, L2) ==
lists:reverse(lists:rukeymerge(2, lists:reverse(L1),
lists:reverse(L2))),
ok.
-ukeysort_1(doc) -> ["ukeysort"];
-ukeysort_1(suite) -> [];
ukeysort_1(Config) when is_list(Config) ->
- ?line ok = ukeysort_check(1, [], []),
- ?line ok = ukeysort_check(1, [{a,b}], [{a,b}]),
- ?line ok = ukeysort_check(1, [{a,b},{a,b}], [{a,b}]),
- ?line ok = ukeysort_check(1, [{a,b},{b,c}], [{a,b},{b,c}]),
- ?line ok = ukeysort_check(1, [{b,c},{a,b}], [{a,b},{b,c}]),
- ?line ok = ukeysort_check(1,
- [{1,e},{3,f},{2,y},{0,z},{x,14}],
- [{0,z},{1,e},{2,y},{3,f},{x,14}]),
- ?line ok = ukeysort_check(1, [{1,a},{1,a},{1,a},{1,a}], [{1,a}]),
+ ok = ukeysort_check(1, [], []),
+ ok = ukeysort_check(1, [{a,b}], [{a,b}]),
+ ok = ukeysort_check(1, [{a,b},{a,b}], [{a,b}]),
+ ok = ukeysort_check(1, [{a,b},{b,c}], [{a,b},{b,c}]),
+ ok = ukeysort_check(1, [{b,c},{a,b}], [{a,b},{b,c}]),
+ ok = ukeysort_check(1,
+ [{1,e},{3,f},{2,y},{0,z},{x,14}],
+ [{0,z},{1,e},{2,y},{3,f},{x,14}]),
+ ok = ukeysort_check(1, [{1,a},{1,a},{1,a},{1,a}], [{1,a}]),
L1 = [{1,a},{1,b},{1,a}],
L1u = lists:ukeysort(1, L1),
L2 = [{1,a},{1,b},{1,a}],
L2u = lists:ukeysort(1, L2),
- ?line ok = ukeysort_check(1, lists:keymerge(1, L1, L2),
- lists:ukeymerge(1, L1u, L2u)),
+ ok = ukeysort_check(1, lists:keymerge(1, L1, L2),
+ lists:ukeymerge(1, L1u, L2u)),
L3 = [{1,a},{1,b},{1,a},{2,a}],
L3u = lists:ukeysort(1, L3),
- ?line ok = ukeysort_check(1, lists:keymerge(1, L3, L2),
- lists:ukeymerge(1, L3u, L2u)),
+ ok = ukeysort_check(1, lists:keymerge(1, L3, L2),
+ lists:ukeymerge(1, L3u, L2u)),
L4 = [{1,b},{1,a}],
L4u = lists:ukeysort(1, L4),
- ?line ok = ukeysort_check(1, lists:keymerge(1, L1, L4),
- lists:ukeymerge(1, L1u, L4u)),
+ ok = ukeysort_check(1, lists:keymerge(1, L1, L4),
+ lists:ukeymerge(1, L1u, L4u)),
L5 = [{1,a},{1,b},{1,a},{2,a}],
L5u = lists:ukeysort(1, L5),
- ?line ok = ukeysort_check(1, lists:keymerge(1, [], L5),
- lists:ukeymerge(1, [], L5u)),
- ?line ok = ukeysort_check(1, lists:keymerge(1, L5, []),
- lists:ukeymerge(1, L5u, [])),
+ ok = ukeysort_check(1, lists:keymerge(1, [], L5),
+ lists:ukeymerge(1, [], L5u)),
+ ok = ukeysort_check(1, lists:keymerge(1, L5, []),
+ lists:ukeymerge(1, L5u, [])),
L6 = [{3,a}],
L6u = lists:ukeysort(1, L6),
- ?line ok = ukeysort_check(1, lists:keymerge(1, L5, L6),
- lists:ukeymerge(1, L5u, L6u)),
+ ok = ukeysort_check(1, lists:keymerge(1, L5, L6),
+ lists:ukeymerge(1, L5u, L6u)),
- ?line [{b,1},{c,1}] = lists:ukeysort(1, [{c,1},{c,1},{c,1},{c,1},{b,1}]),
- ?line [{a,0},{b,2},{c,3},{d,4}] =
- lists:ukeysort(1, [{d,4},{c,3},{b,2},{b,2},{a,0}]),
- ?line [{a,0},{b,1},{c,1}] =
- lists:ukeysort(1, [{c,1},{b,1},{b,1},{b,2},{b,2},{a,0}]),
- ?line [{a,0},{b,1},{c,1},{d,4}] =
- lists:ukeysort(1, [{c,1},{b,1},{b,2},{a,0},{a,0},{d,4},{d,4}]),
+ [{b,1},{c,1}] = lists:ukeysort(1, [{c,1},{c,1},{c,1},{c,1},{b,1}]),
+ [{a,0},{b,2},{c,3},{d,4}] =
+ lists:ukeysort(1, [{d,4},{c,3},{b,2},{b,2},{a,0}]),
+ [{a,0},{b,1},{c,1}] =
+ lists:ukeysort(1, [{c,1},{b,1},{b,1},{b,2},{b,2},{a,0}]),
+ [{a,0},{b,1},{c,1},{d,4}] =
+ lists:ukeysort(1, [{c,1},{b,1},{b,2},{a,0},{a,0},{d,4},{d,4}]),
SFun = fun(L) -> fun(X) -> ukeysort_check(2, X, L) end end,
PL = [{a,1},{b,2},{c,3},{d,4},{e,5},{f,6}],
Ps = perms([{a,1},{b,2},{c,3},{d,4},{e,5},{f,6},{b,2},{a,1}]),
- ?line lists:foreach(SFun(PL), Ps),
+ lists:foreach(SFun(PL), Ps),
M1L = [{1,a},{1,a},{2,b}],
M1s = [{1,a},{2,b}],
- ?line lists:foreach(SFun(M1s), perms(M1L)),
+ lists:foreach(SFun(M1s), perms(M1L)),
M2L = [{1,a},{2,b},{2,b}],
M2s = [{1,a},{2,b}],
- ?line lists:foreach(SFun(M2s), perms(M2L)),
+ lists:foreach(SFun(M2s), perms(M2L)),
M3 = [{1,a},{2,b},{3,c}],
- ?line lists:foreach(SFun(M3), perms(M3)),
+ lists:foreach(SFun(M3), perms(M3)),
ok.
-ukeysort_stable(doc) -> ["ukeysort should keep the first duplicate"];
-ukeysort_stable(suite) -> [];
+%% ukeysort should keep the first duplicate.
ukeysort_stable(Config) when is_list(Config) ->
- ?line ok = ukeysort_check(1, [{1,b},{1,c}], [{1,b}]),
- ?line ok = ukeysort_check(1, [{1,c},{1,b}], [{1,c}]),
- ?line ok = ukeysort_check(1,
- [{1,c},{1,b},{2,x},{3,p},{2,a}],
- [{1,c},{2,x},{3,p}]),
-
- ?line ok = ukeysort_check(1, [{1,a},{1,b},{1,b}], [{1,a}]),
- ?line ok = ukeysort_check(1, [{2,a},{1,b},{2,a}], [{1,b},{2,a}]),
-
- ?line ok = ukeysort_check_stability(bigfunlist(3)),
- ?line ok = ukeysort_check_stability(bigfunlist(10)),
- ?line ok = ukeysort_check_stability(bigfunlist(100)),
- ?line ok = ukeysort_check_stability(bigfunlist(1000)),
- ?line case erlang:system_info(modified_timing_level) of
- undefined -> ok = ukeysort_check_stability(bigfunlist(10000));
- _ -> ok
- end,
- ok.
-
-ukeysort_error(doc) -> ["ukeysort should exit when given bad arguments"];
-ukeysort_error(suite) -> [];
+ ok = ukeysort_check(1, [{1,b},{1,c}], [{1,b}]),
+ ok = ukeysort_check(1, [{1,c},{1,b}], [{1,c}]),
+ ok = ukeysort_check(1,
+ [{1,c},{1,b},{2,x},{3,p},{2,a}],
+ [{1,c},{2,x},{3,p}]),
+
+ ok = ukeysort_check(1, [{1,a},{1,b},{1,b}], [{1,a}]),
+ ok = ukeysort_check(1, [{2,a},{1,b},{2,a}], [{1,b},{2,a}]),
+
+ ok = ukeysort_check_stability(bigfunlist(3)),
+ ok = ukeysort_check_stability(bigfunlist(10)),
+ ok = ukeysort_check_stability(bigfunlist(100)),
+ ok = ukeysort_check_stability(bigfunlist(1000)),
+ case erlang:system_info(modified_timing_level) of
+ undefined -> ok = ukeysort_check_stability(bigfunlist(10000));
+ _ -> ok
+ end,
+ ok.
+
+%% ukeysort should exit when given bad arguments.
ukeysort_error(Config) when is_list(Config) ->
- ?line {'EXIT', _} = (catch lists:ukeysort(0, [{1,b},{1,c}])),
- ?line {'EXIT', _} = (catch lists:ukeysort(3, [{1,b},{1,c}])),
- ?line {'EXIT', _} = (catch lists:ukeysort(1.5, [{1,b},{1,c}])),
- ?line {'EXIT', _} = (catch lists:ukeysort(x, [{1,b},{1,c}])),
- ?line {'EXIT', _} = (catch lists:ukeysort(x, [])),
- ?line {'EXIT', _} = (catch lists:ukeysort(x, [{1,b}])),
- ?line {'EXIT', _} = (catch lists:ukeysort(1, [a,b])),
- ?line {'EXIT', _} = (catch lists:ukeysort(1, [{1,b} | {1,c}])),
- ok.
-
-ukeysort_i(doc) -> ["ukeysort with other key than first element"];
-ukeysort_i(suite) -> [];
+ {'EXIT', _} = (catch lists:ukeysort(0, [{1,b},{1,c}])),
+ {'EXIT', _} = (catch lists:ukeysort(3, [{1,b},{1,c}])),
+ {'EXIT', _} = (catch lists:ukeysort(1.5, [{1,b},{1,c}])),
+ {'EXIT', _} = (catch lists:ukeysort(x, [{1,b},{1,c}])),
+ {'EXIT', _} = (catch lists:ukeysort(x, [])),
+ {'EXIT', _} = (catch lists:ukeysort(x, [{1,b}])),
+ {'EXIT', _} = (catch lists:ukeysort(1, [a,b])),
+ {'EXIT', _} = (catch lists:ukeysort(1, [{1,b} | {1,c}])),
+ ok.
+
+%% ukeysort with other key than first element.
ukeysort_i(Config) when is_list(Config) ->
- ?line ok = ukeysort_check(2, [{a,2},{b,1},{c,3}], [{b,1},{a,2},{c,3}]),
+ ok = ukeysort_check(2, [{a,2},{b,1},{c,3}], [{b,1},{a,2},{c,3}]),
ok.
-ukeysort_rand(doc) -> ["ukeysort on big randomized lists"];
-ukeysort_rand(suite) -> [];
+%% ukeysort on big randomized lists.
ukeysort_rand(Config) when is_list(Config) ->
- ?line ok = ukeysort_check3(2, biglist(10)),
- ?line ok = ukeysort_check3(2, biglist(100)),
- ?line ok = ukeysort_check3(2, biglist(1000)),
- ?line ok = ukeysort_check3(2, biglist(10000)),
+ ok = ukeysort_check3(2, biglist(10)),
+ ok = ukeysort_check3(2, biglist(100)),
+ ok = ukeysort_check3(2, biglist(1000)),
+ ok = ukeysort_check3(2, biglist(10000)),
- ?line ok = gen_ukeysort_check(1, ubiglist(10)),
- ?line ok = gen_ukeysort_check(1, ubiglist(100)),
- ?line ok = gen_ukeysort_check(1, ubiglist(1000)),
- ?line ok = gen_ukeysort_check(1, ubiglist(10000)),
+ ok = gen_ukeysort_check(1, ubiglist(10)),
+ ok = gen_ukeysort_check(1, ubiglist(100)),
+ ok = gen_ukeysort_check(1, ubiglist(1000)),
+ ok = gen_ukeysort_check(1, ubiglist(10000)),
ok.
%% Check that ukeysort/2 is stable and correct relative keysort/2.
@@ -1272,7 +1219,7 @@ ukeysort_check_stability(L) ->
%%% Uniquely keysort a list, check that the returned list is what we
%%% expected, and that it is actually sorted.
ukeysort_check(I, Input, Expected) ->
- ?line Expected = lists:ukeysort(I, Input),
+ Expected = lists:ukeysort(I, Input),
ucheck_sorted(I, Input, Expected).
ukeysort_check3(I, Input) ->
@@ -1309,8 +1256,7 @@ ukeycompare(I, J, A, B) when A =/= B,
-funmerge(doc) -> ["Merge two lists using a fun."];
-funmerge(suite) -> [];
+%% Merge two lists using a fun.
funmerge(Config) when is_list(Config) ->
Two = [1,2],
@@ -1318,29 +1264,28 @@ funmerge(Config) when is_list(Config) ->
F = fun(X, Y) -> X =< Y end,
%% 2-way merge
- ?line [] = lists:merge(F, [], []),
- ?line Two = lists:merge(F, Two, []),
- ?line Two = lists:merge(F, [], Two),
- ?line Six = lists:merge(F, [1,3,5], [2,4,6]),
- ?line Six = lists:merge(F, [2,4,6], [1,3,5]),
- ?line Six = lists:merge(F, [1,2,3], [4,5,6]),
- ?line Six = lists:merge(F, [4,5,6], [1,2,3]),
- ?line Six = lists:merge(F, [1,2,5],[3,4,6]),
- ?line [1,2,3,5,7] = lists:merge(F, [1,3,5,7], [2]),
- ?line [1,2,3,4,5,7] = lists:merge(F, [1,3,5,7], [2,4]),
- ?line [1,2,3,4,5,6,7] = lists:merge(F, [1,3,5,7], [2,4,6]),
- ?line [1,2,3,5,7] = lists:merge(F, [2], [1,3,5,7]),
- ?line [1,2,3,4,5,7] = lists:merge(F, [2,4], [1,3,5,7]),
- ?line [1,2,3,4,5,6,7] = lists:merge(F, [2,4,6], [1,3,5,7]),
+ [] = lists:merge(F, [], []),
+ Two = lists:merge(F, Two, []),
+ Two = lists:merge(F, [], Two),
+ Six = lists:merge(F, [1,3,5], [2,4,6]),
+ Six = lists:merge(F, [2,4,6], [1,3,5]),
+ Six = lists:merge(F, [1,2,3], [4,5,6]),
+ Six = lists:merge(F, [4,5,6], [1,2,3]),
+ Six = lists:merge(F, [1,2,5],[3,4,6]),
+ [1,2,3,5,7] = lists:merge(F, [1,3,5,7], [2]),
+ [1,2,3,4,5,7] = lists:merge(F, [1,3,5,7], [2,4]),
+ [1,2,3,4,5,6,7] = lists:merge(F, [1,3,5,7], [2,4,6]),
+ [1,2,3,5,7] = lists:merge(F, [2], [1,3,5,7]),
+ [1,2,3,4,5,7] = lists:merge(F, [2,4], [1,3,5,7]),
+ [1,2,3,4,5,6,7] = lists:merge(F, [2,4,6], [1,3,5,7]),
F2 = fun(X,Y) -> element(1,X) =< element(1,Y) end,
- ?line [{b,2},{c,11},{c,12},{c,21},{c,22},{e,5}] =
+ [{b,2},{c,11},{c,12},{c,21},{c,22},{e,5}] =
lists:merge(F2,[{c,11},{c,12},{e,5}], [{b,2},{c,21},{c,22}]),
ok.
-rfunmerge(doc) -> ["Reverse merge two lists using a fun."];
-rfunmerge(suite) -> [];
+%% Reverse merge two lists using a fun.
rfunmerge(Config) when is_list(Config) ->
Two = [2,1],
@@ -1348,86 +1293,81 @@ rfunmerge(Config) when is_list(Config) ->
F = fun(X, Y) -> X =< Y end,
%% 2-way reversed merge
- ?line [] = lists:rmerge(F, [], []),
- ?line Two = lists:rmerge(F, Two, []),
- ?line Two = lists:rmerge(F, [], Two),
- ?line Six = lists:rmerge(F, [5,3,1], [6,4,2]),
- ?line Six = lists:rmerge(F, [6,4,2], [5,3,1]),
- ?line Six = lists:rmerge(F, [3,2,1], [6,5,4]),
- ?line Six = lists:rmerge(F, [6,5,4], [3,2,1]),
- ?line Six = lists:rmerge(F, [4,3,2],[6,5,1]),
- ?line [7,6,5,3,1] = lists:rmerge(F, [7,5,3,1], [6]),
- ?line [7,6,5,4,3,1] = lists:rmerge(F, [7,5,3,1], [6,4]),
- ?line [7,6,5,4,3,2,1] = lists:rmerge(F, [7,5,3,1], [6,4,2]),
- ?line [7,5,3,2,1] = lists:rmerge(F, [2], [7,5,3,1]),
- ?line [7,5,4,3,2,1] = lists:rmerge(F, [4,2], [7,5,3,1]),
- ?line [7,6,5,4,3,2,1] = lists:rmerge(F, [6,4,2], [7,5,3,1]),
+ [] = lists:rmerge(F, [], []),
+ Two = lists:rmerge(F, Two, []),
+ Two = lists:rmerge(F, [], Two),
+ Six = lists:rmerge(F, [5,3,1], [6,4,2]),
+ Six = lists:rmerge(F, [6,4,2], [5,3,1]),
+ Six = lists:rmerge(F, [3,2,1], [6,5,4]),
+ Six = lists:rmerge(F, [6,5,4], [3,2,1]),
+ Six = lists:rmerge(F, [4,3,2],[6,5,1]),
+ [7,6,5,3,1] = lists:rmerge(F, [7,5,3,1], [6]),
+ [7,6,5,4,3,1] = lists:rmerge(F, [7,5,3,1], [6,4]),
+ [7,6,5,4,3,2,1] = lists:rmerge(F, [7,5,3,1], [6,4,2]),
+ [7,5,3,2,1] = lists:rmerge(F, [2], [7,5,3,1]),
+ [7,5,4,3,2,1] = lists:rmerge(F, [4,2], [7,5,3,1]),
+ [7,6,5,4,3,2,1] = lists:rmerge(F, [6,4,2], [7,5,3,1]),
F2 = fun(X,Y) -> element(1,X) =< element(1,Y) end,
L1 = [{c,11},{c,12},{e,5}],
L2 = [{b,2},{c,21},{c,22}],
- ?line true =
+ true =
lists:merge(F2, L1, L2) ==
lists:reverse(lists:rmerge(F2,lists:reverse(L1), lists:reverse(L2))),
ok.
-funsort_1(doc) -> ["sort/2"];
-funsort_1(suite) -> [];
funsort_1(Config) when is_list(Config) ->
- ?line ok = funsort_check(1, [], []),
- ?line ok = funsort_check(1, [{a,b}], [{a,b}]),
- ?line ok = funsort_check(1, [{a,b},{a,b}], [{a,b},{a,b}]),
- ?line ok = funsort_check(1, [{a,b},{b,c}], [{a,b},{b,c}]),
- ?line ok = funsort_check(1, [{b,c},{a,b}], [{a,b},{b,c}]),
- ?line ok = funsort_check(1,
- [{1,e},{3,f},{2,y},{0,z},{x,14}],
- [{0,z},{1,e},{2,y},{3,f},{x,14}]),
+ ok = funsort_check(1, [], []),
+ ok = funsort_check(1, [{a,b}], [{a,b}]),
+ ok = funsort_check(1, [{a,b},{a,b}], [{a,b},{a,b}]),
+ ok = funsort_check(1, [{a,b},{b,c}], [{a,b},{b,c}]),
+ ok = funsort_check(1, [{b,c},{a,b}], [{a,b},{b,c}]),
+ ok = funsort_check(1,
+ [{1,e},{3,f},{2,y},{0,z},{x,14}],
+ [{0,z},{1,e},{2,y},{3,f},{x,14}]),
F = funsort_fun(1),
- ?line [{b,1},{c,1}] = lists:sort(F, [{c,1},{b,1}]),
- ?line [{a,0},{b,2},{c,3},{d,4}] =
- lists:sort(F, [{d,4},{c,3},{b,2},{a,0}]),
- ?line [{a,0},{b,1},{b,2},{c,1}] =
- lists:sort(F, [{c,1},{b,1},{b,2},{a,0}]),
- ?line [{a,0},{b,1},{b,2},{c,1},{d,4}] =
- lists:sort(F, [{c,1},{b,1},{b,2},{a,0},{d,4}]),
+ [{b,1},{c,1}] = lists:sort(F, [{c,1},{b,1}]),
+ [{a,0},{b,2},{c,3},{d,4}] =
+ lists:sort(F, [{d,4},{c,3},{b,2},{a,0}]),
+ [{a,0},{b,1},{b,2},{c,1}] =
+ lists:sort(F, [{c,1},{b,1},{b,2},{a,0}]),
+ [{a,0},{b,1},{b,2},{c,1},{d,4}] =
+ lists:sort(F, [{c,1},{b,1},{b,2},{a,0},{d,4}]),
SFun = fun(L) -> fun(X) -> funsort_check(1, X, L) end end,
L1 = [{1,a},{1,a},{2,b},{2,b},{3,c},{4,d},{5,e},{6,f}],
- ?line lists:foreach(SFun(L1), perms(L1)),
+ lists:foreach(SFun(L1), perms(L1)),
ok.
-funsort_stable(doc) -> ["sort/2 should be stable"];
-funsort_stable(suite) -> [];
+%% sort/2 should be stable.
funsort_stable(Config) when is_list(Config) ->
- ?line ok = funsort_check(1, [{1,b},{1,c}], [{1,b},{1,c}]),
- ?line ok = funsort_check(1, [{1,c},{1,b}], [{1,c},{1,b}]),
- ?line ok = funsort_check(1,
- [{1,c},{1,b},{2,x},{3,p},{2,a}],
- [{1,c},{1,b},{2,x},{2,a},{3,p}]),
+ ok = funsort_check(1, [{1,b},{1,c}], [{1,b},{1,c}]),
+ ok = funsort_check(1, [{1,c},{1,b}], [{1,c},{1,b}]),
+ ok = funsort_check(1,
+ [{1,c},{1,b},{2,x},{3,p},{2,a}],
+ [{1,c},{1,b},{2,x},{2,a},{3,p}]),
ok.
-funsort_error(doc) -> ["sort/2 should exit when given bad arguments"];
-funsort_error(suite) -> [];
+%% sort/2 should exit when given bad arguments.
funsort_error(Config) when is_list(Config) ->
- ?line {'EXIT', _} = (catch lists:sort(1, [{1,b} , {1,c}])),
- ?line {'EXIT', _} = (catch lists:sort(fun(X,Y) -> X =< Y end,
- [{1,b} | {1,c}])),
+ {'EXIT', _} = (catch lists:sort(1, [{1,b} , {1,c}])),
+ {'EXIT', _} = (catch lists:sort(fun(X,Y) -> X =< Y end,
+ [{1,b} | {1,c}])),
ok.
-funsort_rand(doc) -> ["sort/2 on big randomized lists"];
-funsort_rand(suite) -> [];
+%% sort/2 on big randomized lists.
funsort_rand(Config) when is_list(Config) ->
- ?line ok = funsort_check3(1, biglist(10)),
- ?line ok = funsort_check3(1, biglist(100)),
- ?line ok = funsort_check3(1, biglist(1000)),
- ?line ok = funsort_check3(1, biglist(10000)),
+ ok = funsort_check3(1, biglist(10)),
+ ok = funsort_check3(1, biglist(100)),
+ ok = funsort_check3(1, biglist(1000)),
+ ok = funsort_check3(1, biglist(10000)),
ok.
-% Do a keysort
+%% Do a keysort
funsort(I, L) ->
lists:sort(funsort_fun(I), L).
@@ -1437,12 +1377,11 @@ funsort_check3(I, Input) ->
%%% Keysort a list, check that the returned list is what we expected,
%%% and that it is actually sorted.
funsort_check(I, Input, Expected) ->
- ?line Expected = funsort(I, Input),
+ Expected = funsort(I, Input),
check_sorted(I, Input, Expected).
-ufunmerge(suite) -> [];
-ufunmerge(doc) -> ["Merge two lists while removing duplicates using a fun."];
+%% Merge two lists while removing duplicates using a fun.
ufunmerge(Conf) when is_list(Conf) ->
Two = [1,2],
@@ -1450,175 +1389,168 @@ ufunmerge(Conf) when is_list(Conf) ->
F = fun(X, Y) -> X =< Y end,
%% 2-way unique merge
- ?line [] = lists:umerge(F, [], []),
- ?line Two = lists:umerge(F, Two, []),
- ?line Two = lists:umerge(F, [], Two),
- ?line Six = lists:umerge(F, [1,3,5], [2,4,6]),
- ?line Six = lists:umerge(F, [2,4,6], [1,3,5]),
- ?line Six = lists:umerge(F, [1,2,3], [4,5,6]),
- ?line Six = lists:umerge(F, [4,5,6], [1,2,3]),
- ?line Six = lists:umerge(F, [1,2,5],[3,4,6]),
- ?line [1,2,3,5,7] = lists:umerge(F, [1,3,5,7], [2]),
- ?line [1,2,3,4,5,7] = lists:umerge(F, [1,3,5,7], [2,4]),
- ?line [1,2,3,4,5,6,7] = lists:umerge(F, [1,3,5,7], [2,4,6]),
- ?line [1,2,3,5,7] = lists:umerge(F, [2], [1,3,5,7]),
- ?line [1,2,3,4,5,7] = lists:umerge(F, [2,4], [1,3,5,7]),
- ?line [1,2,3,4,5,6,7] = lists:umerge(F, [2,4,6], [1,3,5,7]),
-
- ?line [1,2,3,5,7] = lists:umerge(F, [1,2,3,5,7], [2]),
- ?line [1,2,3,4,5,7] = lists:umerge(F, [1,2,3,4,5,7], [2,4]),
- ?line [1,2,3,4,5,6,7] = lists:umerge(F, [1,3,5,6,7], [2,4,6]),
- ?line [1,2,3,5,7] = lists:umerge(F, [2], [1,2,3,5,7]),
- ?line [1,2,3,4,5,7] = lists:umerge(F, [2,4], [1,2,3,4,5,7]),
- ?line [1,2,3,4,5,6,7] = lists:umerge(F, [2,4,6], [1,2,3,4,5,6,7]),
+ [] = lists:umerge(F, [], []),
+ Two = lists:umerge(F, Two, []),
+ Two = lists:umerge(F, [], Two),
+ Six = lists:umerge(F, [1,3,5], [2,4,6]),
+ Six = lists:umerge(F, [2,4,6], [1,3,5]),
+ Six = lists:umerge(F, [1,2,3], [4,5,6]),
+ Six = lists:umerge(F, [4,5,6], [1,2,3]),
+ Six = lists:umerge(F, [1,2,5],[3,4,6]),
+ [1,2,3,5,7] = lists:umerge(F, [1,3,5,7], [2]),
+ [1,2,3,4,5,7] = lists:umerge(F, [1,3,5,7], [2,4]),
+ [1,2,3,4,5,6,7] = lists:umerge(F, [1,3,5,7], [2,4,6]),
+ [1,2,3,5,7] = lists:umerge(F, [2], [1,3,5,7]),
+ [1,2,3,4,5,7] = lists:umerge(F, [2,4], [1,3,5,7]),
+ [1,2,3,4,5,6,7] = lists:umerge(F, [2,4,6], [1,3,5,7]),
+
+ [1,2,3,5,7] = lists:umerge(F, [1,2,3,5,7], [2]),
+ [1,2,3,4,5,7] = lists:umerge(F, [1,2,3,4,5,7], [2,4]),
+ [1,2,3,4,5,6,7] = lists:umerge(F, [1,3,5,6,7], [2,4,6]),
+ [1,2,3,5,7] = lists:umerge(F, [2], [1,2,3,5,7]),
+ [1,2,3,4,5,7] = lists:umerge(F, [2,4], [1,2,3,4,5,7]),
+ [1,2,3,4,5,6,7] = lists:umerge(F, [2,4,6], [1,2,3,4,5,6,7]),
L1 = [{a,1},{a,3},{a,5},{a,7}],
L2 = [{b,1},{b,3},{b,5},{b,7}],
F2 = fun(X,Y) -> element(2,X) =< element(2,Y) end,
- ?line L1 = lists:umerge(F2, L1, L2),
- ?line [{b,2},{e,5},{c,11},{c,12},{c,21},{c,22}] =
+ L1 = lists:umerge(F2, L1, L2),
+ [{b,2},{e,5},{c,11},{c,12},{c,21},{c,22}] =
lists:umerge(F2, [{e,5},{c,11},{c,12}], [{b,2},{c,21},{c,22}]),
ok.
-rufunmerge(suite) -> [];
-rufunmerge(doc) ->
- ["Reverse merge two lists while removing duplicates using a fun."];
+%% Reverse merge two lists while removing duplicates using a fun.
rufunmerge(Conf) when is_list(Conf) ->
Two = [2,1],
Six = [6,5,4,3,2,1],
F = fun(X, Y) -> X =< Y end,
%% 2-way reversed unique merge
- ?line [] = lists:rumerge(F, [], []),
- ?line Two = lists:rumerge(F, Two, []),
- ?line Two = lists:rumerge(F, [], Two),
- ?line Six = lists:rumerge(F, [5,3,1], [6,4,2]),
- ?line Six = lists:rumerge(F, [6,4,2], [5,3,1]),
- ?line Six = lists:rumerge(F, [3,2,1], [6,5,4]),
- ?line Six = lists:rumerge(F, [6,5,4], [3,2,1]),
- ?line Six = lists:rumerge(F, [4,3,2],[6,5,1]),
- ?line [7,6,5,3,1] = lists:rumerge(F, [7,5,3,1], [6]),
- ?line [7,6,5,4,3,1] = lists:rumerge(F, [7,5,3,1], [6,4]),
- ?line [7,6,5,4,3,2,1] = lists:rumerge(F, [7,5,3,1], [6,4,2]),
- ?line [7,5,3,2,1] = lists:rumerge(F, [2], [7,5,3,1]),
- ?line [7,5,4,3,2,1] = lists:rumerge(F, [4,2], [7,5,3,1]),
- ?line [7,6,5,4,3,2,1] = lists:rumerge(F, [6,4,2], [7,5,3,1]),
-
- ?line [7,6,5,3,1] = lists:rumerge(F, [7,6,5,3,1], [6]),
- ?line [7,6,5,4,3,1] = lists:rumerge(F, [7,6,5,4,3,1], [6,4]),
- ?line [7,6,5,4,3,2,1] = lists:rumerge(F, [7,6,5,4,3,2,1], [6,4,2]),
- ?line [7,5,3,2,1] = lists:rumerge(F, [2], [7,5,3,2,1]),
- ?line [7,5,4,3,2,1] = lists:rumerge(F, [4,2], [7,5,4,3,2,1]),
- ?line [7,6,5,4,3,2,1] = lists:rumerge(F, [6,4,2], [7,6,5,4,3,2,1]),
+ [] = lists:rumerge(F, [], []),
+ Two = lists:rumerge(F, Two, []),
+ Two = lists:rumerge(F, [], Two),
+ Six = lists:rumerge(F, [5,3,1], [6,4,2]),
+ Six = lists:rumerge(F, [6,4,2], [5,3,1]),
+ Six = lists:rumerge(F, [3,2,1], [6,5,4]),
+ Six = lists:rumerge(F, [6,5,4], [3,2,1]),
+ Six = lists:rumerge(F, [4,3,2],[6,5,1]),
+ [7,6,5,3,1] = lists:rumerge(F, [7,5,3,1], [6]),
+ [7,6,5,4,3,1] = lists:rumerge(F, [7,5,3,1], [6,4]),
+ [7,6,5,4,3,2,1] = lists:rumerge(F, [7,5,3,1], [6,4,2]),
+ [7,5,3,2,1] = lists:rumerge(F, [2], [7,5,3,1]),
+ [7,5,4,3,2,1] = lists:rumerge(F, [4,2], [7,5,3,1]),
+ [7,6,5,4,3,2,1] = lists:rumerge(F, [6,4,2], [7,5,3,1]),
+
+ [7,6,5,3,1] = lists:rumerge(F, [7,6,5,3,1], [6]),
+ [7,6,5,4,3,1] = lists:rumerge(F, [7,6,5,4,3,1], [6,4]),
+ [7,6,5,4,3,2,1] = lists:rumerge(F, [7,6,5,4,3,2,1], [6,4,2]),
+ [7,5,3,2,1] = lists:rumerge(F, [2], [7,5,3,2,1]),
+ [7,5,4,3,2,1] = lists:rumerge(F, [4,2], [7,5,4,3,2,1]),
+ [7,6,5,4,3,2,1] = lists:rumerge(F, [6,4,2], [7,6,5,4,3,2,1]),
F2 = fun(X,Y) -> element(1,X) =< element(1,Y) end,
L1 = [{1,a},{1,b},{1,a}],
L2 = [{1,a},{1,b},{1,a}],
- ?line true = lists:umerge(F2, L1, L2) ==
+ true = lists:umerge(F2, L1, L2) ==
lists:reverse(lists:rumerge(F, lists:reverse(L2), lists:reverse(L1))),
L3 = [{c,11},{c,12},{e,5}],
L4 = [{b,2},{c,21},{c,22}],
- ?line true =
+ true =
lists:umerge(F2, L3, L4) ==
lists:reverse(lists:rumerge(F2,lists:reverse(L3), lists:reverse(L4))),
ok.
-ufunsort_1(doc) -> ["usort/2"];
-ufunsort_1(suite) -> [];
ufunsort_1(Config) when is_list(Config) ->
- ?line ok = ufunsort_check(1, [], []),
- ?line ok = ufunsort_check(1, [{a,b}], [{a,b}]),
- ?line ok = ufunsort_check(1, [{a,b},{a,b}], [{a,b}]),
- ?line ok = ufunsort_check(1, [{a,b},{b,c}], [{a,b},{b,c}]),
- ?line ok = ufunsort_check(1, [{b,c},{a,b}], [{a,b},{b,c}]),
- ?line ok = ufunsort_check(1,
- [{1,e},{3,f},{2,y},{0,z},{x,14}],
- [{0,z},{1,e},{2,y},{3,f},{x,14}]),
- ?line ok = ufunsort_check(1,
- [{1,a},{2,b},{3,c},{2,b},{1,a},{2,b},{3,c},
- {2,b},{1,a}],
- [{1,a},{2,b},{3,c}]),
- ?line ok = ufunsort_check(1,
- [{1,a},{1,a},{1,b},{1,b},{1,a},{2,a}],
- [{1,a},{2,a}]),
+ ok = ufunsort_check(1, [], []),
+ ok = ufunsort_check(1, [{a,b}], [{a,b}]),
+ ok = ufunsort_check(1, [{a,b},{a,b}], [{a,b}]),
+ ok = ufunsort_check(1, [{a,b},{b,c}], [{a,b},{b,c}]),
+ ok = ufunsort_check(1, [{b,c},{a,b}], [{a,b},{b,c}]),
+ ok = ufunsort_check(1,
+ [{1,e},{3,f},{2,y},{0,z},{x,14}],
+ [{0,z},{1,e},{2,y},{3,f},{x,14}]),
+ ok = ufunsort_check(1,
+ [{1,a},{2,b},{3,c},{2,b},{1,a},{2,b},{3,c},
+ {2,b},{1,a}],
+ [{1,a},{2,b},{3,c}]),
+ ok = ufunsort_check(1,
+ [{1,a},{1,a},{1,b},{1,b},{1,a},{2,a}],
+ [{1,a},{2,a}]),
F = funsort_fun(1),
L1 = [{1,a},{1,b},{1,a}],
L2 = [{1,a},{1,b},{1,a}],
- ?line ok = ufunsort_check(1, lists:keymerge(1, L1, L2),
- lists:umerge(F, lists:usort(F, L1),
- lists:usort(F, L2))),
+ ok = ufunsort_check(1, lists:keymerge(1, L1, L2),
+ lists:umerge(F, lists:usort(F, L1),
+ lists:usort(F, L2))),
L3 = [{1,a},{1,b},{1,a},{2,a}],
- ?line ok = ufunsort_check(1, lists:keymerge(1, L3, L2),
- lists:umerge(F, lists:usort(F, L3),
- lists:usort(F, L2))),
+ ok = ufunsort_check(1, lists:keymerge(1, L3, L2),
+ lists:umerge(F, lists:usort(F, L3),
+ lists:usort(F, L2))),
L4 = [{1,b},{1,a}],
- ?line ok = ufunsort_check(1, lists:keymerge(1, L1, L4),
- lists:umerge(F, lists:usort(F, L1),
- lists:usort(F, L4))),
+ ok = ufunsort_check(1, lists:keymerge(1, L1, L4),
+ lists:umerge(F, lists:usort(F, L1),
+ lists:usort(F, L4))),
L5 = [{1,a},{1,b},{1,a},{2,a}],
- ?line ok = ufunsort_check(1, lists:keymerge(1, L5, []),
- lists:umerge(F, lists:usort(F, L5), [])),
+ ok = ufunsort_check(1, lists:keymerge(1, L5, []),
+ lists:umerge(F, lists:usort(F, L5), [])),
L6 = [{3,a}],
- ?line ok = ufunsort_check(1, lists:keymerge(1, L5, L6),
- lists:umerge(F, lists:usort(F, L5),
- lists:usort(F, L6))),
-
- ?line [{b,1},{c,1}] = lists:usort(F, [{c,1},{c,1},{b,1}]),
- ?line [{a,0},{b,2},{c,3},{d,4}] =
- lists:usort(F, [{d,4},{c,3},{b,2},{b,2},{a,0}]),
- ?line [{a,0},{b,1},{c,1}] =
- lists:usort(F, [{c,1},{b,1},{b,1},{b,2},{b,2},{a,0}]),
- ?line [{a,0},{b,1},{c,1},{d,4}] =
- lists:usort(F, [{c,1},{b,1},{b,2},{a,0},{a,0},{d,4},{d,4}]),
+ ok = ufunsort_check(1, lists:keymerge(1, L5, L6),
+ lists:umerge(F, lists:usort(F, L5),
+ lists:usort(F, L6))),
+
+ [{b,1},{c,1}] = lists:usort(F, [{c,1},{c,1},{b,1}]),
+ [{a,0},{b,2},{c,3},{d,4}] =
+ lists:usort(F, [{d,4},{c,3},{b,2},{b,2},{a,0}]),
+ [{a,0},{b,1},{c,1}] =
+ lists:usort(F, [{c,1},{b,1},{b,1},{b,2},{b,2},{a,0}]),
+ [{a,0},{b,1},{c,1},{d,4}] =
+ lists:usort(F, [{c,1},{b,1},{b,2},{a,0},{a,0},{d,4},{d,4}]),
SFun = fun(L) -> fun(X) -> ufunsort_check(1, X, L) end end,
PL = [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f}],
Ps = perms([{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{2,b},{1,a}]),
- ?line lists:foreach(SFun(PL), Ps),
+ lists:foreach(SFun(PL), Ps),
ok.
-ufunsort_stable(doc) -> ["usort/2 should be stable"];
-ufunsort_stable(suite) -> [];
+%% usort/2 should be stable.
ufunsort_stable(Config) when is_list(Config) ->
- ?line ok = ufunsort_check(1, [{1,b},{1,c}], [{1,b}]),
- ?line ok = ufunsort_check(1, [{1,c},{1,b}], [{1,c}]),
- ?line ok = ufunsort_check(1,
- [{1,c},{1,b},{2,x},{3,p},{2,a}],
- [{1,c},{2,x},{3,p}]),
-
- ?line ok = ufunsort_check_stability(bigfunlist(10)),
- ?line ok = ufunsort_check_stability(bigfunlist(100)),
- ?line ok = ufunsort_check_stability(bigfunlist(1000)),
- ?line case erlang:system_info(modified_timing_level) of
- undefined -> ok = ufunsort_check_stability(bigfunlist(10000));
- _ -> ok
- end,
- ok.
-
-ufunsort_error(doc) -> ["usort/2 should exit when given bad arguments"];
-ufunsort_error(suite) -> [];
+ ok = ufunsort_check(1, [{1,b},{1,c}], [{1,b}]),
+ ok = ufunsort_check(1, [{1,c},{1,b}], [{1,c}]),
+ ok = ufunsort_check(1,
+ [{1,c},{1,b},{2,x},{3,p},{2,a}],
+ [{1,c},{2,x},{3,p}]),
+
+ ok = ufunsort_check_stability(bigfunlist(10)),
+ ok = ufunsort_check_stability(bigfunlist(100)),
+ ok = ufunsort_check_stability(bigfunlist(1000)),
+ case erlang:system_info(modified_timing_level) of
+ undefined -> ok = ufunsort_check_stability(bigfunlist(10000));
+ _ -> ok
+ end,
+ ok.
+
+%% usort/2 should exit when given bad arguments.
ufunsort_error(Config) when is_list(Config) ->
- ?line {'EXIT', _} = (catch lists:usort(1, [{1,b} , {1,c}])),
- ?line {'EXIT', _} = (catch lists:usort(fun(X,Y) -> X =< Y end,
- [{1,b} | {1,c}])),
+ {'EXIT', _} = (catch lists:usort(1, [{1,b} , {1,c}])),
+ {'EXIT', _} = (catch lists:usort(fun(X,Y) -> X =< Y end,
+ [{1,b} | {1,c}])),
ok.
-ufunsort_rand(doc) -> ["usort/2 on big randomized lists"];
-ufunsort_rand(suite) -> [];
+%% usort/2 on big randomized lists.
ufunsort_rand(Config) when is_list(Config) ->
- ?line ok = ufunsort_check3(1, biglist(10)),
- ?line ok = ufunsort_check3(1, biglist(100)),
- ?line ok = ufunsort_check3(1, biglist(1000)),
- ?line ok = ufunsort_check3(1, biglist(10000)),
+ ok = ufunsort_check3(1, biglist(10)),
+ ok = ufunsort_check3(1, biglist(100)),
+ ok = ufunsort_check3(1, biglist(1000)),
+ ok = ufunsort_check3(1, biglist(10000)),
- ?line ok = gen_ufunsort_check(1, ubiglist(100)),
- ?line ok = gen_ufunsort_check(1, ubiglist(1000)),
- ?line ok = gen_ufunsort_check(1, ubiglist(10000)),
+ ok = gen_ufunsort_check(1, ubiglist(100)),
+ ok = gen_ufunsort_check(1, ubiglist(1000)),
+ ok = gen_ufunsort_check(1, ubiglist(10000)),
ok.
%% Check that usort/2 is stable and correct relative sort/2.
@@ -1646,10 +1578,10 @@ ufunsort_check3(I, Input) ->
%%% Keysort a list, check that the returned list is what we expected,
%%% and that it is actually sorted.
ufunsort_check(I, Input, Expected) ->
- ?line Expected = ufunsort(I, Input),
+ Expected = ufunsort(I, Input),
ucheck_sorted(I, Input, Expected).
-% Do a keysort
+%% Do a keysort
ufunsort(I, L) ->
lists:usort(funsort_fun(I), L).
@@ -1677,8 +1609,7 @@ check_stab(L, U, S, US, SS) ->
%%% Element 3 in the tuple is the position of the tuple in the list.
biglist(N) ->
- {A, B, C} = get_seed(),
- random:seed(A, B, C),
+ rand:seed(exsplus),
biglist(N, []).
biglist(0, L) ->
@@ -1694,8 +1625,7 @@ biglist(N, L) ->
%%% No sequence number.
ubiglist(N) ->
- {A, B, C} = get_seed(),
- random:seed(A, B, C),
+ rand:seed(exsplus),
ubiglist(N, []).
ubiglist(0, L) ->
@@ -1703,7 +1633,7 @@ ubiglist(0, L) ->
ubiglist(N, L) ->
E = urandom_tuple(11, 6),
ubiglist(N-1, [E|L]).
-
+
urandom_tuple(N, I) ->
R1 = randint(N),
R2 = randint(I),
@@ -1719,8 +1649,7 @@ urandom_tuple(N, I) ->
%%% sequence number.
bigfunlist(N) ->
- {A, B, C} = get_seed(),
- random:seed(A, B, C),
+ rand:seed(exsplus),
bigfunlist_1(N).
bigfunlist_1(N) when N < 30000 -> % Now (R8) max 32000 different pids.
@@ -1736,7 +1665,7 @@ bigfunlist(0, _P, L) ->
bigfunlist(N, P, L) ->
{E, NP} = random_funtuple(P, 11),
bigfunlist(N-1, NP, [E | L]).
-
+
random_funtuple(P, N) ->
R = randint(N),
F = make_fun(),
@@ -1747,28 +1676,20 @@ random_funtuple(P, N) ->
make_fun() ->
Pid = spawn(?MODULE, make_fun, [self()]),
receive {Pid, Fun} -> Fun end.
-
+
make_fun(Pid) ->
Pid ! {self(), fun make_fun/1}.
fun_pid(Fun) ->
erlang:fun_info(Fun, pid).
-get_seed() ->
- case random:seed() of
- undefined ->
- erlang:timestamp();
- Tuple ->
- Tuple
- end.
-
random_tuple(N, Seq) ->
R1 = randint(N),
R2 = randint(N),
{R1, R2, Seq}.
randint(N) ->
- trunc(random:uniform() * N).
+ trunc(rand:uniform() * N).
%% The first "duplicate" is kept.
no_dups([]) ->
@@ -1830,8 +1751,7 @@ sort_loop_1(Pid) ->
end.
sloop(N) ->
- {A, B, C} = get_seed(),
- random:seed(A, B, C),
+ rand:seed(exsplus),
sloop(N, #state{}).
sloop(N, S) ->
@@ -1866,7 +1786,7 @@ sloop(N, S) ->
end,
sloop(N, NS)
end.
-
+
display_state(S) ->
io:format("sort: ~p~n", [S#state.sort]),
io:format("usort: ~p~n", [S#state.usort]),
@@ -2135,85 +2055,67 @@ rkeymerge2_2(_I, T1, _E1, [], M, H1) ->
%%%------------------------------------------------------------
-seq_loop(doc) ->
- ["Test for infinite loop (OTP-2404)."];
-seq_loop(suite) ->
- [];
+%% Test for infinite loop (OTP-2404).
seq_loop(Config) when is_list(Config) ->
- ?line _ = (catch lists:seq(1, 5, -1)),
+ _ = (catch lists:seq(1, 5, -1)),
ok.
-seq_2(doc) ->
- ["Non-error cases for seq/2"];
-seq_2(suite) ->
- [];
+%% Non-error cases for seq/2.
seq_2(Config) when is_list(Config) ->
- ?line [1,2,3] = lists:seq(1,3),
- ?line [1] = lists:seq(1,1),
- ?line Big = 748274827583793785928592859,
- ?line Big1 = Big+1,
- ?line Big2 = Big+2,
- ?line [Big, Big1, Big2] = lists:seq(Big, Big+2),
+ [1,2,3] = lists:seq(1,3),
+ [1] = lists:seq(1,1),
+ Big = 748274827583793785928592859,
+ Big1 = Big+1,
+ Big2 = Big+2,
+ [Big, Big1, Big2] = lists:seq(Big, Big+2),
ok.
-seq_2_e(doc) ->
- ["Error cases for seq/2"];
-seq_2_e(suite) ->
- [];
+%% Error cases for seq/2.
seq_2_e(Config) when is_list(Config) ->
- ?line seq_error([4, 2]),
- ?line seq_error([1, a]),
- ?line seq_error([1.0, 2.0]),
+ seq_error([4, 2]),
+ seq_error([1, a]),
+ seq_error([1.0, 2.0]),
ok.
seq_error(Args) ->
{'EXIT', _} = (catch apply(lists, seq, Args)).
-seq_3(doc) ->
- ["Non-error cases for seq/3"];
-seq_3(suite) ->
- [];
+%% Non-error cases for seq/3.
seq_3(Config) when is_list(Config) ->
- ?line [1,2,3] = lists:seq(1,3,1),
- ?line [1] = lists:seq(1,1,1),
- ?line Big = 748274827583793785928592859,
- ?line Big1 = Big+1,
- ?line Big2 = Big+2,
- ?line [Big, Big1, Big2] = lists:seq(Big, Big+2,1),
+ [1,2,3] = lists:seq(1,3,1),
+ [1] = lists:seq(1,1,1),
+ Big = 748274827583793785928592859,
+ Big1 = Big+1,
+ Big2 = Big+2,
+ [Big, Big1, Big2] = lists:seq(Big, Big+2,1),
- ?line [3,2,1] = lists:seq(3,1,-1),
- ?line [1] = lists:seq(1,1,-1),
+ [3,2,1] = lists:seq(3,1,-1),
+ [1] = lists:seq(1,1,-1),
- ?line [3,1] = lists:seq(3,1,-2),
- ?line [1] = lists:seq(1, 10, 10),
- ?line [1, 4, 7, 10, 13, 16, 19] = lists:seq(1, 19, 3),
- ?line [1, 4, 7, 10, 13, 16, 19] = lists:seq(1, 20, 3),
- ?line [1, 4, 7, 10, 13, 16, 19] = lists:seq(1, 21, 3),
+ [3,1] = lists:seq(3,1,-2),
+ [1] = lists:seq(1, 10, 10),
+ [1, 4, 7, 10, 13, 16, 19] = lists:seq(1, 19, 3),
+ [1, 4, 7, 10, 13, 16, 19] = lists:seq(1, 20, 3),
+ [1, 4, 7, 10, 13, 16, 19] = lists:seq(1, 21, 3),
- ?line [1] = lists:seq(1, 1, 0), %OTP-2613
+ [1] = lists:seq(1, 1, 0), %OTP-2613
ok.
-seq_3_e(doc) ->
- ["Error cases for seq/3"];
-seq_3_e(suite) ->
- [];
+%% Error cases for seq/3.
seq_3_e(Config) when is_list(Config) ->
- ?line seq_error([4, 2, 1]),
- ?line seq_error([3, 5, -1]),
- ?line seq_error([1, a, 1]),
- ?line seq_error([1.0, 2.0, 1]),
+ seq_error([4, 2, 1]),
+ seq_error([3, 5, -1]),
+ seq_error([1, a, 1]),
+ seq_error([1.0, 2.0, 1]),
- ?line seq_error([1, 3, 1.0]),
- ?line seq_error([1, 3, a]),
- ?line seq_error([1, 3, 0]),
+ seq_error([1, 3, 1.0]),
+ seq_error([1, 3, a]),
+ seq_error([1, 3, 0]),
- ?line seq_error([a, a, 0]),
+ seq_error([a, a, 0]),
ok.
-otp_7230(doc) ->
- ["OTP-7230. seq/1,2 returns the empty list"];
-otp_7230(suite) ->
- [];
+%% OTP-7230. seq/1,2 returns the empty list.
otp_7230(Config) when is_list(Config) ->
From = -10,
To = 10,
@@ -2222,26 +2124,26 @@ otp_7230(Config) when is_list(Config) ->
L = lists:seq(From, To),
SL = lists:seq(StepFrom, StepTo),
- ?line [] =
- [{F, T, S} ||
- F <- L, T <- L, S <- SL,
- not check_seq(F, T, S, catch lists:seq(F, T, S))
- orelse
- S =:= 1 andalso not check_seq(F, T, S, catch lists:seq(F, T))
+ [] =
+ [{F, T, S} ||
+ F <- L, T <- L, S <- SL,
+ not check_seq(F, T, S, catch lists:seq(F, T, S))
+ orelse
+ S =:= 1 andalso not check_seq(F, T, S, catch lists:seq(F, T))
].
check_seq(From, To, 0, R) ->
- From =:= To andalso R =:= [From]
- orelse
- From =/= To andalso is_tuple(R) andalso element(1, R) =:= 'EXIT';
+ From =:= To andalso R =:= [From]
+ orelse
+ From =/= To andalso is_tuple(R) andalso element(1, R) =:= 'EXIT';
check_seq(From, To, Step, []) when Step =/= 0 ->
- 0 =:= property(From, To, Step)
- andalso
- (
- Step > 0 andalso To < From andalso From-To =< Step
- orelse
- Step < 0 andalso To > From andalso To-From =< -Step
- );
+ 0 =:= property(From, To, Step)
+ andalso
+ (
+ Step > 0 andalso To < From andalso From-To =< Step
+ orelse
+ Step < 0 andalso To > From andalso To-From =< -Step
+ );
check_seq(From, To, Step, R) when R =/= [], To < From, Step > 0 ->
is_tuple(R) andalso element(1, R) =:= 'EXIT';
check_seq(From, To, Step, R) when R =/= [], To > From, Step < 0 ->
@@ -2252,27 +2154,27 @@ check_seq(From, To, Step, L) when is_list(L), L =/= [], Step =/= 0 ->
Min = lists:min(L),
Max = lists:max(L),
- [] =:= [E || E <- L, not is_integer(E)]
- andalso
- %% The difference between two consecutive elements is Step:
- begin
- LS = [First-Step]++L,
- LR = L++[Last+Step],
- [Step] =:= lists:usort([B-A || {A,B} <- lists:zip(LS, LR)])
- end
- andalso
- %% The first element of L is From:
- From =:= First
- andalso
- %% No element outside the given interval:
- Min >= lists:min([From, To])
- andalso
- Max =< lists:max([From, To])
- andalso
- %% All elements are present:
- abs(To-Last) < abs(Step)
- andalso
- length(L) =:= property(From, To, Step);
+ [] =:= [E || E <- L, not is_integer(E)]
+ andalso
+ %% The difference between two consecutive elements is Step:
+ begin
+ LS = [First-Step]++L,
+ LR = L++[Last+Step],
+ [Step] =:= lists:usort([B-A || {A,B} <- lists:zip(LS, LR)])
+ end
+ andalso
+ %% The first element of L is From:
+ From =:= First
+ andalso
+ %% No element outside the given interval:
+ Min >= lists:min([From, To])
+ andalso
+ Max =< lists:max([From, To])
+ andalso
+ %% All elements are present:
+ abs(To-Last) < abs(Step)
+ andalso
+ length(L) =:= property(From, To, Step);
check_seq(_From, _To, _Step, _R) ->
false.
@@ -2282,25 +2184,22 @@ property(From, To, Step) ->
%%%------------------------------------------------------------
--define(sublist_error2(X,Y), ?line {'EXIT', _} = (catch lists:sublist(X,Y))).
--define(sublist_error3(X,Y,Z), ?line {'EXIT', _} = (catch lists:sublist(X,Y,Z))).
+-define(sublist_error2(X,Y), {'EXIT', _} = (catch lists:sublist(X,Y))).
+-define(sublist_error3(X,Y,Z), {'EXIT', _} = (catch lists:sublist(X,Y,Z))).
-sublist_2(doc) -> ["sublist/2"];
-sublist_2(suite) -> [];
sublist_2(Config) when is_list(Config) ->
- ?line [] = lists:sublist([], 0),
- ?line [] = lists:sublist([], 1),
- ?line [] = lists:sublist([a], 0),
- ?line [a] = lists:sublist([a], 1),
- ?line [a] = lists:sublist([a], 2),
- ?line [a] = lists:sublist([a|b], 1),
+ [] = lists:sublist([], 0),
+ [] = lists:sublist([], 1),
+ [] = lists:sublist([a], 0),
+ [a] = lists:sublist([a], 1),
+ [a] = lists:sublist([a], 2),
+ [a] = lists:sublist([a|b], 1),
- ?line [a,b] = lists:sublist([a,b|c], 2),
+ [a,b] = lists:sublist([a,b|c], 2),
ok.
-sublist_2_e(doc) -> ["sublist/2 error cases"];
-sublist_2_e(suite) -> [];
+%% sublist/2 error cases.
sublist_2_e(Config) when is_list(Config) ->
?sublist_error2([], -1),
?sublist_error2(a, -1),
@@ -2312,36 +2211,33 @@ sublist_2_e(Config) when is_list(Config) ->
?sublist_error2([], 1.5),
ok.
-sublist_3(doc) -> ["sublist/3"];
-sublist_3(suite) -> [];
sublist_3(Config) when is_list(Config) ->
- ?line [] = lists:sublist([], 1, 0),
- ?line [] = lists:sublist([], 1, 1),
- ?line [] = lists:sublist([a], 1, 0),
- ?line [a] = lists:sublist([a], 1, 1),
- ?line [a] = lists:sublist([a], 1, 2),
- ?line [a] = lists:sublist([a|b], 1, 1),
-
- ?line [] = lists:sublist([], 1, 0),
- ?line [] = lists:sublist([], 1, 1),
- ?line [] = lists:sublist([a], 1, 0),
- ?line [a] = lists:sublist([a], 1, 1),
- ?line [a] = lists:sublist([a], 1, 2),
- ?line [] = lists:sublist([a], 2, 1),
- ?line [] = lists:sublist([a], 2, 2),
- ?line [] = lists:sublist([a], 2, 79),
- ?line [] = lists:sublist([a,b|c], 1, 0),
- ?line [] = lists:sublist([a,b|c], 2, 0),
- ?line [a] = lists:sublist([a,b|c], 1, 1),
- ?line [b] = lists:sublist([a,b|c], 2, 1),
- ?line [a,b] = lists:sublist([a,b|c], 1, 2),
-
- ?line [] = lists:sublist([a], 2, 0),
-
- ok.
-
-sublist_3_e(doc) -> ["sublist/3 error cases"];
-sublist_3_e(suite) -> [];
+ [] = lists:sublist([], 1, 0),
+ [] = lists:sublist([], 1, 1),
+ [] = lists:sublist([a], 1, 0),
+ [a] = lists:sublist([a], 1, 1),
+ [a] = lists:sublist([a], 1, 2),
+ [a] = lists:sublist([a|b], 1, 1),
+
+ [] = lists:sublist([], 1, 0),
+ [] = lists:sublist([], 1, 1),
+ [] = lists:sublist([a], 1, 0),
+ [a] = lists:sublist([a], 1, 1),
+ [a] = lists:sublist([a], 1, 2),
+ [] = lists:sublist([a], 2, 1),
+ [] = lists:sublist([a], 2, 2),
+ [] = lists:sublist([a], 2, 79),
+ [] = lists:sublist([a,b|c], 1, 0),
+ [] = lists:sublist([a,b|c], 2, 0),
+ [a] = lists:sublist([a,b|c], 1, 1),
+ [b] = lists:sublist([a,b|c], 2, 1),
+ [a,b] = lists:sublist([a,b|c], 1, 2),
+
+ [] = lists:sublist([a], 2, 0),
+
+ ok.
+
+%% sublist/3 error cases
sublist_3_e(Config) when is_list(Config) ->
?sublist_error3([], 1, -1),
?sublist_error3(a, 1, -1),
@@ -2375,8 +2271,8 @@ sublist_3_e(Config) when is_list(Config) ->
%%%------------------------------------------------------------
--define(flatten_error1(X), ?line {'EXIT', _} = (catch lists:flatten(X))).
--define(flatten_error2(X,Y), ?line {'EXIT', _} = (catch lists:flatten(X,Y))).
+-define(flatten_error1(X), {'EXIT', _} = (catch lists:flatten(X))).
+-define(flatten_error2(X,Y), {'EXIT', _} = (catch lists:flatten(X,Y))).
%% Test lists:flatten/1,2 and lists:flatlength/1.
flatten_1(Config) when is_list(Config) ->
@@ -2397,8 +2293,7 @@ lists_flatten(List) ->
Len = length(Flat),
Flat.
-flatten_1_e(doc) -> ["flatten/1 error cases"];
-flatten_1_e(suite) -> [];
+%% flatten/1 error cases
flatten_1_e(Config) when is_list(Config) ->
?flatten_error1(a),
?flatten_error1([a|b]),
@@ -2416,60 +2311,59 @@ flatten_2(Config) when is_list(Config) ->
[a,b,c,[no,flatten]] = lists:flatten([[a,[b,c]]], [[no,flatten]]),
ok.
-flatten_2_e(doc) -> ["flatten/2 error cases"];
-flatten_2_e(suite) -> [];
+%% flatten/2 error cases.
flatten_2_e(Config) when is_list(Config) ->
ok.
%% Test lists:zip/2, lists:unzip/1.
zip_unzip(Config) when is_list(Config) ->
- ?line [] = lists:zip([], []),
- ?line [{a,b}] = lists:zip([a], [b]),
- ?line [{42.0,{kalle,nisse}},{a,b}] = lists:zip([42.0,a], [{kalle,nisse},b]),
+ [] = lists:zip([], []),
+ [{a,b}] = lists:zip([a], [b]),
+ [{42.0,{kalle,nisse}},{a,b}] = lists:zip([42.0,a], [{kalle,nisse},b]),
%% Longer lists.
- ?line SeqA = lists:seq(45, 200),
- ?line SeqB = [A*A || A <- SeqA],
- ?line AB = lists:zip(SeqA, SeqB),
- ?line SeqA = [A || {A,_} <- AB],
- ?line SeqB = [B || {_,B} <- AB],
- ?line {SeqA,SeqB} = lists:unzip(AB),
-
+ SeqA = lists:seq(45, 200),
+ SeqB = [A*A || A <- SeqA],
+ AB = lists:zip(SeqA, SeqB),
+ SeqA = [A || {A,_} <- AB],
+ SeqB = [B || {_,B} <- AB],
+ {SeqA,SeqB} = lists:unzip(AB),
+
%% Some more unzip/1.
- ?line {[],[]} = lists:unzip([]),
- ?line {[a],[b]} = lists:unzip([{a,b}]),
- ?line {[a,c],[b,d]} = lists:unzip([{a,b},{c,d}]),
+ {[],[]} = lists:unzip([]),
+ {[a],[b]} = lists:unzip([{a,b}]),
+ {[a,c],[b,d]} = lists:unzip([{a,b},{c,d}]),
%% Error cases.
- ?line {'EXIT',{function_clause,_}} = (catch lists:zip([], [b])),
- ?line {'EXIT',{function_clause,_}} = (catch lists:zip([a], [])),
- ?line {'EXIT',{function_clause,_}} = (catch lists:zip([a], [b,c])),
- ?line {'EXIT',{function_clause,_}} = (catch lists:zip([a], [b,c])),
+ {'EXIT',{function_clause,_}} = (catch lists:zip([], [b])),
+ {'EXIT',{function_clause,_}} = (catch lists:zip([a], [])),
+ {'EXIT',{function_clause,_}} = (catch lists:zip([a], [b,c])),
+ {'EXIT',{function_clause,_}} = (catch lists:zip([a], [b,c])),
ok.
%% Test lists:zip3/3, lists:unzip3/1.
zip_unzip3(Config) when is_list(Config) ->
- ?line [] = lists:zip3([], [], []),
- ?line [{a,b,c}] = lists:zip3([a], [b], [c]),
+ [] = lists:zip3([], [], []),
+ [{a,b,c}] = lists:zip3([a], [b], [c]),
%% Longer lists.
- ?line SeqA = lists:seq(45, 200),
- ?line SeqB = [2*A || A <- SeqA],
- ?line SeqC = [A*A || A <- SeqA],
- ?line ABC = lists:zip3(SeqA, SeqB, SeqC),
- ?line SeqA = [A || {A,_,_} <- ABC],
- ?line SeqB = [B || {_,B,_} <- ABC],
- ?line SeqC = [C || {_,_,C} <- ABC],
- ?line {SeqA,SeqB,SeqC} = lists:unzip3(ABC),
+ SeqA = lists:seq(45, 200),
+ SeqB = [2*A || A <- SeqA],
+ SeqC = [A*A || A <- SeqA],
+ ABC = lists:zip3(SeqA, SeqB, SeqC),
+ SeqA = [A || {A,_,_} <- ABC],
+ SeqB = [B || {_,B,_} <- ABC],
+ SeqC = [C || {_,_,C} <- ABC],
+ {SeqA,SeqB,SeqC} = lists:unzip3(ABC),
%% Some more unzip3/1.
- ?line {[],[],[]} = lists:unzip3([]),
- ?line {[a],[b],[c]} = lists:unzip3([{a,b,c}]),
+ {[],[],[]} = lists:unzip3([]),
+ {[a],[b],[c]} = lists:unzip3([{a,b,c}]),
%% Error cases.
- ?line {'EXIT',{function_clause,_}} = (catch lists:zip3([], [], [c])),
- ?line {'EXIT',{function_clause,_}} = (catch lists:zip3([], [b], [])),
- ?line {'EXIT',{function_clause,_}} = (catch lists:zip3([a], [], [])),
+ {'EXIT',{function_clause,_}} = (catch lists:zip3([], [], [c])),
+ {'EXIT',{function_clause,_}} = (catch lists:zip3([], [b], [])),
+ {'EXIT',{function_clause,_}} = (catch lists:zip3([a], [], [])),
ok.
@@ -2477,61 +2371,61 @@ zip_unzip3(Config) when is_list(Config) ->
zipwith(Config) when is_list(Config) ->
Zip = fun(A, B) -> [A|B] end,
- ?line [] = lists:zipwith(Zip, [], []),
- ?line [[a|b]] = lists:zipwith(Zip, [a], [b]),
+ [] = lists:zipwith(Zip, [], []),
+ [[a|b]] = lists:zipwith(Zip, [a], [b]),
%% Longer lists.
- ?line SeqA = lists:seq(77, 300),
- ?line SeqB = [A*A || A <- SeqA],
- ?line AB = lists:zipwith(Zip, SeqA, SeqB),
- ?line SeqA = [A || [A|_] <- AB],
- ?line SeqB = [B || [_|B] <- AB],
-
+ SeqA = lists:seq(77, 300),
+ SeqB = [A*A || A <- SeqA],
+ AB = lists:zipwith(Zip, SeqA, SeqB),
+ SeqA = [A || [A|_] <- AB],
+ SeqB = [B || [_|B] <- AB],
+
%% Error cases.
- ?line {'EXIT',{function_clause,_}} = (catch lists:zipwith(badfun, [], [])),
- ?line {'EXIT',{function_clause,_}} = (catch lists:zipwith(Zip, [], [b])),
- ?line {'EXIT',{function_clause,_}} = (catch lists:zipwith(Zip, [a], [])),
- ?line {'EXIT',{function_clause,_}} = (catch lists:zipwith(Zip, [a], [b,c])),
- ?line {'EXIT',{function_clause,_}} = (catch lists:zipwith(Zip, [a], [b,c])),
+ {'EXIT',{function_clause,_}} = (catch lists:zipwith(badfun, [], [])),
+ {'EXIT',{function_clause,_}} = (catch lists:zipwith(Zip, [], [b])),
+ {'EXIT',{function_clause,_}} = (catch lists:zipwith(Zip, [a], [])),
+ {'EXIT',{function_clause,_}} = (catch lists:zipwith(Zip, [a], [b,c])),
+ {'EXIT',{function_clause,_}} = (catch lists:zipwith(Zip, [a], [b,c])),
ok.
%% Test lists:zipwith3/4.
zipwith3(Config) when is_list(Config) ->
Zip = fun(A, B, C) -> [A,B,C] end,
- ?line [] = lists:zipwith3(Zip, [], [], []),
- ?line [[a,b,c]] = lists:zipwith3(Zip, [a], [b], [c]),
+ [] = lists:zipwith3(Zip, [], [], []),
+ [[a,b,c]] = lists:zipwith3(Zip, [a], [b], [c]),
%% Longer lists.
- ?line SeqA = lists:seq(45, 200),
- ?line SeqB = [2*A || A <- SeqA],
- ?line SeqC = [A*A || A <- SeqA],
- ?line ABC = lists:zipwith3(Zip, SeqA, SeqB, SeqC),
- ?line SeqA = [A || [A,_,_] <- ABC],
- ?line SeqB = [B || [_,B,_] <- ABC],
- ?line SeqC = [C || [_,_,C] <- ABC],
+ SeqA = lists:seq(45, 200),
+ SeqB = [2*A || A <- SeqA],
+ SeqC = [A*A || A <- SeqA],
+ ABC = lists:zipwith3(Zip, SeqA, SeqB, SeqC),
+ SeqA = [A || [A,_,_] <- ABC],
+ SeqB = [B || [_,B,_] <- ABC],
+ SeqC = [C || [_,_,C] <- ABC],
%% Error cases.
- ?line {'EXIT',{function_clause,_}} = (catch lists:zipwith3(badfun, [], [], [])),
- ?line {'EXIT',{function_clause,_}} = (catch lists:zipwith3(Zip, [], [], [c])),
- ?line {'EXIT',{function_clause,_}} = (catch lists:zipwith3(Zip, [], [b], [])),
- ?line {'EXIT',{function_clause,_}} = (catch lists:zipwith3(Zip, [a], [], [])),
+ {'EXIT',{function_clause,_}} = (catch lists:zipwith3(badfun, [], [], [])),
+ {'EXIT',{function_clause,_}} = (catch lists:zipwith3(Zip, [], [], [c])),
+ {'EXIT',{function_clause,_}} = (catch lists:zipwith3(Zip, [], [b], [])),
+ {'EXIT',{function_clause,_}} = (catch lists:zipwith3(Zip, [a], [], [])),
ok.
%% Test lists:filter/2, lists:partition/2.
filter_partition(Config) when is_list(Config) ->
F = fun(I) -> I rem 2 =:= 0 end,
- ?line filpart(F, [], []),
- ?line filpart(F, [1], []),
- ?line filpart(F, [1,3,17], []),
- ?line filpart(F, [1,2,3,17], [2]),
- ?line filpart(F, [6,8,1,2,3,17], [6,8,2]),
- ?line filpart(F, [6,8,1,2,42,3,17], [6,8,2,42]),
+ filpart(F, [], []),
+ filpart(F, [1], []),
+ filpart(F, [1,3,17], []),
+ filpart(F, [1,2,3,17], [2]),
+ filpart(F, [6,8,1,2,3,17], [6,8,2]),
+ filpart(F, [6,8,1,2,42,3,17], [6,8,2,42]),
%% Error cases.
- ?line {'EXIT',{function_clause,_}} = (catch lists:filter(badfun, [])),
- ?line {'EXIT',{function_clause,_}} = (catch lists:partition(badfun, [])),
+ {'EXIT',{function_clause,_}} = (catch lists:filter(badfun, [])),
+ {'EXIT',{function_clause,_}} = (catch lists:partition(badfun, [])),
ok.
filpart(F, All, Exp) ->
@@ -2540,8 +2434,7 @@ filpart(F, All, Exp) ->
{Exp,Other} = lists:partition(F, All).
-otp_5939(doc) -> ["OTP-5939. Guard tests added."];
-otp_5939(suite) -> [];
+%% OTP-5939. Guard tests added.
otp_5939(Config) when is_list(Config) ->
Fun1 = fun(A) -> A end,
Fun2 = fun(A, B) -> {A,B} end,
@@ -2550,163 +2443,161 @@ otp_5939(Config) when is_list(Config) ->
Fold = fun(_E, A) -> A end,
MapFold = fun(E, A) -> {E,A} end,
- ?line {'EXIT', _} = (catch lists:usort( [asd], [qwe])),
-
- ?line {'EXIT', _} = (catch lists:zipwith(func, [], [])),
- ?line [] = lists:zipwith(Fun2, [], []),
- ?line {'EXIT', _} = (catch lists:zipwith3(func, [], [], [])),
- ?line [] = lists:zipwith3(Fun3, [], [], []),
- ?line {'EXIT', _} = (catch lists:keymap(func, 1, [])),
- ?line {'EXIT', _} = (catch lists:keymap(Fun1, 0, [])),
- ?line [] = lists:keymap(Fun1, 1, []),
- ?line {'EXIT', _} = (catch lists:merge(func, [], [1])),
- ?line {'EXIT', _} = (catch lists:merge(func, [1], [])),
- ?line [] = lists:merge(Fun2, [], []),
- ?line {'EXIT', _} = (catch lists:rmerge(func, [], [1])),
- ?line {'EXIT', _} = (catch lists:rmerge(func, [1], [])),
- ?line [] = lists:rmerge(Fun2, [], []),
- ?line {'EXIT', _} = (catch lists:usort(func, [])),
- ?line {'EXIT', _} = (catch lists:usort(func, [a])),
- ?line {'EXIT', _} = (catch lists:usort(func, [a, b])),
- ?line [] = lists:usort(Fun2, []),
- ?line {'EXIT', _} = (catch lists:umerge(func, [], [1])),
- ?line {'EXIT', _} = (catch lists:merge(func, [1], [])),
- ?line [] = lists:umerge(Fun2, [], []),
- ?line {'EXIT', _} = (catch lists:rumerge(func, [], [1])),
- ?line {'EXIT', _} = (catch lists:rumerge(func, [1], [])),
- ?line [] = lists:rumerge(Fun2, [], []),
- ?line {'EXIT', _} = (catch lists:all(func, [])),
- ?line true = lists:all(Pred, []),
- ?line {'EXIT', _} = (catch lists:any(func, [])),
- ?line false = lists:any(Pred, []),
- ?line {'EXIT', _} = (catch lists:map(func, [])),
- ?line [] = lists:map(Fun1, []),
- ?line {'EXIT', _} = (catch lists:flatmap(func, [])),
- ?line [] = lists:flatmap(Fun1, []),
- ?line {'EXIT', _} = (catch lists:foldl(func, [], [])),
- ?line [] = lists:foldl(Fold, [], []),
- ?line {'EXIT', _} = (catch lists:foldr(func, [], [])),
- ?line [] = lists:foldr(Fold, [], []),
- ?line {'EXIT', _} = (catch lists:filter(func, [])),
- ?line [] = lists:filter(Pred, []),
- ?line {'EXIT', _} = (catch lists:partition(func, [])),
- ?line {[],[]} = lists:partition(Pred, []),
- ?line {'EXIT', _} = (catch lists:filtermap(func, [])),
- ?line [] = lists:filtermap(Fun1, []),
- ?line {'EXIT', _} = (catch lists:foreach(func, [])),
- ?line ok = lists:foreach(Fun1, []),
- ?line {'EXIT', _} = (catch lists:mapfoldl(func, [], [])),
- ?line {[],[]} = lists:mapfoldl(MapFold, [], []),
- ?line {'EXIT', _} = (catch lists:mapfoldr(func, [], [])),
- ?line {[],[]} = lists:mapfoldr(MapFold, [], []),
- ?line {'EXIT', _} = (catch lists:takewhile(func, [])),
- ?line [] = lists:takewhile(Pred, []),
- ?line {'EXIT', _} = (catch lists:dropwhile(func, [])),
- ?line [] = lists:dropwhile(Pred, []),
- ?line {'EXIT', _} = (catch lists:splitwith(func, [])),
- ?line {[],[]} = lists:splitwith(Pred, []),
-
- ok.
-
-otp_6023(doc) -> ["OTP-6023. lists:keyreplace/4, a typecheck."];
-otp_6023(suite) -> [];
+ {'EXIT', _} = (catch lists:usort( [asd], [qwe])),
+
+ {'EXIT', _} = (catch lists:zipwith(func, [], [])),
+ [] = lists:zipwith(Fun2, [], []),
+ {'EXIT', _} = (catch lists:zipwith3(func, [], [], [])),
+ [] = lists:zipwith3(Fun3, [], [], []),
+ {'EXIT', _} = (catch lists:keymap(func, 1, [])),
+ {'EXIT', _} = (catch lists:keymap(Fun1, 0, [])),
+ [] = lists:keymap(Fun1, 1, []),
+ {'EXIT', _} = (catch lists:merge(func, [], [1])),
+ {'EXIT', _} = (catch lists:merge(func, [1], [])),
+ [] = lists:merge(Fun2, [], []),
+ {'EXIT', _} = (catch lists:rmerge(func, [], [1])),
+ {'EXIT', _} = (catch lists:rmerge(func, [1], [])),
+ [] = lists:rmerge(Fun2, [], []),
+ {'EXIT', _} = (catch lists:usort(func, [])),
+ {'EXIT', _} = (catch lists:usort(func, [a])),
+ {'EXIT', _} = (catch lists:usort(func, [a, b])),
+ [] = lists:usort(Fun2, []),
+ {'EXIT', _} = (catch lists:umerge(func, [], [1])),
+ {'EXIT', _} = (catch lists:merge(func, [1], [])),
+ [] = lists:umerge(Fun2, [], []),
+ {'EXIT', _} = (catch lists:rumerge(func, [], [1])),
+ {'EXIT', _} = (catch lists:rumerge(func, [1], [])),
+ [] = lists:rumerge(Fun2, [], []),
+ {'EXIT', _} = (catch lists:all(func, [])),
+ true = lists:all(Pred, []),
+ {'EXIT', _} = (catch lists:any(func, [])),
+ false = lists:any(Pred, []),
+ {'EXIT', _} = (catch lists:map(func, [])),
+ [] = lists:map(Fun1, []),
+ {'EXIT', _} = (catch lists:flatmap(func, [])),
+ [] = lists:flatmap(Fun1, []),
+ {'EXIT', _} = (catch lists:foldl(func, [], [])),
+ [] = lists:foldl(Fold, [], []),
+ {'EXIT', _} = (catch lists:foldr(func, [], [])),
+ [] = lists:foldr(Fold, [], []),
+ {'EXIT', _} = (catch lists:filter(func, [])),
+ [] = lists:filter(Pred, []),
+ {'EXIT', _} = (catch lists:partition(func, [])),
+ {[],[]} = lists:partition(Pred, []),
+ {'EXIT', _} = (catch lists:filtermap(func, [])),
+ [] = lists:filtermap(Fun1, []),
+ {'EXIT', _} = (catch lists:foreach(func, [])),
+ ok = lists:foreach(Fun1, []),
+ {'EXIT', _} = (catch lists:mapfoldl(func, [], [])),
+ {[],[]} = lists:mapfoldl(MapFold, [], []),
+ {'EXIT', _} = (catch lists:mapfoldr(func, [], [])),
+ {[],[]} = lists:mapfoldr(MapFold, [], []),
+ {'EXIT', _} = (catch lists:takewhile(func, [])),
+ [] = lists:takewhile(Pred, []),
+ {'EXIT', _} = (catch lists:dropwhile(func, [])),
+ [] = lists:dropwhile(Pred, []),
+ {'EXIT', _} = (catch lists:splitwith(func, [])),
+ {[],[]} = lists:splitwith(Pred, []),
+
+ ok.
+
+%% OTP-6023. lists:keyreplace/4, a typecheck.
otp_6023(Config) when is_list(Config) ->
- ?line {'EXIT', _} = (catch lists:keyreplace(a, 2, [{1,a}], b)),
- ?line [{2,b}] = lists:keyreplace(a, 2, [{1,a}], {2,b}),
+ {'EXIT', _} = (catch lists:keyreplace(a, 2, [{1,a}], b)),
+ [{2,b}] = lists:keyreplace(a, 2, [{1,a}], {2,b}),
ok.
-otp_6606(doc) -> ["OTP-6606. sort and keysort bug"];
-otp_6606(suite) -> [];
+%% OTP-6606. sort and keysort bug.
otp_6606(Config) when is_list(Config) ->
I = 1,
F = float(1),
L1 = [{F,I},{F,F},{I,I},{I,F}],
- ?line L1 = lists:keysort(1, L1),
- ?line L1 = lists:sort(L1),
+ L1 = lists:keysort(1, L1),
+ L1 = lists:sort(L1),
L2 = [{I,I},{I,F},{F,I},{F,F}],
- ?line L2 = lists:keysort(1, L2),
- ?line L2 = lists:sort(L2),
+ L2 = lists:keysort(1, L2),
+ L2 = lists:sort(L2),
ok.
%% Test lists:suffix/2.
suffix(Config) when is_list(Config) ->
- ?line true = lists:suffix([], []),
- ?line true = lists:suffix([], [a]),
- ?line true = lists:suffix([], [a,b]),
- ?line true = lists:suffix([], [a,b,c]),
- ?line true = lists:suffix([a], lists:duplicate(200000, a)),
- ?line true = lists:suffix(lists:seq(1, 1024),
- lists:seq(2, 64000) ++ lists:seq(1, 1024)),
- ?line true = lists:suffix(lists:duplicate(20000, a),
- lists:duplicate(200000, a)),
- ?line true = lists:suffix([2.0,3.0], [1.0,2.0,3.0]),
+ true = lists:suffix([], []),
+ true = lists:suffix([], [a]),
+ true = lists:suffix([], [a,b]),
+ true = lists:suffix([], [a,b,c]),
+ true = lists:suffix([a], lists:duplicate(200000, a)),
+ true = lists:suffix(lists:seq(1, 1024),
+ lists:seq(2, 64000) ++ lists:seq(1, 1024)),
+ true = lists:suffix(lists:duplicate(20000, a),
+ lists:duplicate(200000, a)),
+ true = lists:suffix([2.0,3.0], [1.0,2.0,3.0]),
%% False cases.
- ?line false = lists:suffix([a], []),
- ?line false = lists:suffix([a,b,c], []),
- ?line false = lists:suffix([a,b,c], [b,c]),
- ?line false = lists:suffix([a,b,c], [a,b,c,a,b]),
- ?line false = lists:suffix(lists:duplicate(199999, a)++[b],
- lists:duplicate(200000, a)),
- ?line false = lists:suffix([2.0,3.0], [1,2,3]),
+ false = lists:suffix([a], []),
+ false = lists:suffix([a,b,c], []),
+ false = lists:suffix([a,b,c], [b,c]),
+ false = lists:suffix([a,b,c], [a,b,c,a,b]),
+ false = lists:suffix(lists:duplicate(199999, a)++[b],
+ lists:duplicate(200000, a)),
+ false = lists:suffix([2.0,3.0], [1,2,3]),
%% Error cases.
- ?line {'EXIT',_} = (catch lists:suffix({a,b,c}, [])),
- ?line {'EXIT',_} = (catch lists:suffix([], {a,b})),
- ?line {'EXIT',_} = (catch lists:suffix([a|b], [])),
- ?line {'EXIT',_} = (catch lists:suffix([a,b|c], [a|b])),
- ?line {'EXIT',_} = (catch lists:suffix([a|b], [a,b|c])),
- ?line {'EXIT',_} = (catch lists:suffix([a|b], [a|b])),
-
+ {'EXIT',_} = (catch lists:suffix({a,b,c}, [])),
+ {'EXIT',_} = (catch lists:suffix([], {a,b})),
+ {'EXIT',_} = (catch lists:suffix([a|b], [])),
+ {'EXIT',_} = (catch lists:suffix([a,b|c], [a|b])),
+ {'EXIT',_} = (catch lists:suffix([a|b], [a,b|c])),
+ {'EXIT',_} = (catch lists:suffix([a|b], [a|b])),
+
ok.
%% Test lists:subtract/2 and the '--' operator.
subtract(Config) when is_list(Config) ->
- ?line [] = sub([], []),
- ?line [] = sub([], [a]),
- ?line [] = sub([], lists:seq(1, 1024)),
- ?line sub_non_matching([a], []),
- ?line sub_non_matching([1,2], [make_ref()]),
- ?line sub_non_matching(lists:seq(1, 1024), [make_ref(),make_ref()]),
-
+ [] = sub([], []),
+ [] = sub([], [a]),
+ [] = sub([], lists:seq(1, 1024)),
+ sub_non_matching([a], []),
+ sub_non_matching([1,2], [make_ref()]),
+ sub_non_matching(lists:seq(1, 1024), [make_ref(),make_ref()]),
+
%% Matching subtracts.
- ?line [] = sub([a], [a]),
- ?line [a] = sub([a,b], [b]),
- ?line [a] = sub([a,b], [b,c]),
- ?line [a] = sub([a,b,c], [b,c]),
- ?line [a] = sub([a,b,c], [b,c]),
- ?line [d,a,a] = sub([a,b,c,d,a,a], [a,b,c]),
- ?line [d,x,a] = sub([a,b,c,d,a,x,a], [a,b,c,a]),
- ?line [1,2,3,4,5,6,7,8,9,9999,10000,20,21,22] =
+ [] = sub([a], [a]),
+ [a] = sub([a,b], [b]),
+ [a] = sub([a,b], [b,c]),
+ [a] = sub([a,b,c], [b,c]),
+ [a] = sub([a,b,c], [b,c]),
+ [d,a,a] = sub([a,b,c,d,a,a], [a,b,c]),
+ [d,x,a] = sub([a,b,c,d,a,x,a], [a,b,c,a]),
+ [1,2,3,4,5,6,7,8,9,9999,10000,20,21,22] =
sub(lists:seq(1, 10000)++[20,21,22], lists:seq(10, 9998)),
%% Floats/integers.
- ?line [42.0,42.0] = sub([42.0,42,42.0], [42,42,42]),
- ?line [1,2,3,4,43.0] = sub([1,2,3,4,5,42.0,43.0], [42.0,5]),
+ [42.0,42.0] = sub([42.0,42,42.0], [42,42,42]),
+ [1,2,3,4,43.0] = sub([1,2,3,4,5,42.0,43.0], [42.0,5]),
%% Crashing subtracts.
- ?line {'EXIT',_} = (catch sub([], [a|b])),
- ?line {'EXIT',_} = (catch sub([a], [a|b])),
- ?line {'EXIT',_} = (catch sub([a|b], [])),
- ?line {'EXIT',_} = (catch sub([a|b], [])),
- ?line {'EXIT',_} = (catch sub([a|b], [a])),
+ {'EXIT',_} = (catch sub([], [a|b])),
+ {'EXIT',_} = (catch sub([a], [a|b])),
+ {'EXIT',_} = (catch sub([a|b], [])),
+ {'EXIT',_} = (catch sub([a|b], [])),
+ {'EXIT',_} = (catch sub([a|b], [a])),
ok.
sub_non_matching(A, B) ->
A = sub(A, B).
-
+
sub(A, B) ->
Res = A -- B,
Res = lists:subtract(A, B).
%% Test lists:droplast/1
droplast(Config) when is_list(Config) ->
- ?line [] = lists:droplast([x]),
- ?line [x] = lists:droplast([x, y]),
- ?line {'EXIT', {function_clause, _}} = (catch lists:droplast([])),
- ?line {'EXIT', {function_clause, _}} = (catch lists:droplast(x)),
+ [] = lists:droplast([x]),
+ [x] = lists:droplast([x, y]),
+ {'EXIT', {function_clause, _}} = (catch lists:droplast([])),
+ {'EXIT', {function_clause, _}} = (catch lists:droplast(x)),
ok.
diff --git a/lib/stdlib/test/log_mf_h_SUITE.erl b/lib/stdlib/test/log_mf_h_SUITE.erl
index 86af3d4614..9b543aa37c 100644
--- a/lib/stdlib/test/log_mf_h_SUITE.erl
+++ b/lib/stdlib/test/log_mf_h_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(log_mf_h_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -53,17 +53,17 @@ end_per_group(_GroupName, Config) ->
%%-----------------------------------------------------------------
test(Config) when is_list(Config) ->
- ?line {ok, Pid} = gen_event:start_link(),
- ?line PrivDir = ?config(priv_dir, Config),
+ {ok, Pid} = gen_event:start_link(),
+ PrivDir = proplists:get_value(priv_dir, Config),
Log1 = PrivDir ++ "/log1",
- ?line ok = file:make_dir(Log1),
+ ok = file:make_dir(Log1),
Args1 = log_mf_h:init(Log1, 500, 3),
gen_event:add_handler(Pid, log_mf_h, Args1),
generate(Pid, 200),
{ok, Files} = file:list_dir(Log1),
- ?line true = lists:member("1", Files),
- ?line true = lists:member("index", Files),
- ?line false = lists:member("2", Files),
+ true = lists:member("1", Files),
+ true = lists:member("index", Files),
+ false = lists:member("2", Files),
generate(Pid, 2500),
%% The documentation doesn't guarantee that syncing one request
%% causes all previous ones to be finished too, but that seems to
@@ -71,26 +71,26 @@ test(Config) when is_list(Config) ->
%% look for them with 'list_dir'.
gen_event:sync_notify(Pid, "end"),
{ok, Files2} = file:list_dir(Log1),
- ?line true = lists:member("1", Files2),
- ?line true = lists:member("2", Files2),
- ?line true = lists:member("3", Files2),
- ?line false = lists:member("4", Files2),
- ?line true = lists:member("index", Files2),
- ?line {ok, #file_info{size=Size1,type=regular}} = file:read_file_info(Log1 ++ "/1"),
- ?line if Size1 > 500 -> test_server:fail({too_big, Size1});
- true -> ok end,
- ?line {ok, #file_info{size=Size2,type=regular}} = file:read_file_info(Log1 ++ "/2"),
- ?line if Size2 > 500 -> test_server:fail({too_big, Size2});
- true -> ok end,
- ?line {ok, #file_info{size=Size3,type=regular}} = file:read_file_info(Log1 ++ "/3"),
- ?line if Size3 > 500 -> test_server:fail({too_big, Size3});
- true -> ok end,
+ true = lists:member("1", Files2),
+ true = lists:member("2", Files2),
+ true = lists:member("3", Files2),
+ false = lists:member("4", Files2),
+ true = lists:member("index", Files2),
+ {ok, #file_info{size=Size1,type=regular}} = file:read_file_info(Log1 ++ "/1"),
+ if Size1 > 500 -> ct:fail({too_big, Size1});
+ true -> ok end,
+ {ok, #file_info{size=Size2,type=regular}} = file:read_file_info(Log1 ++ "/2"),
+ if Size2 > 500 -> ct:fail({too_big, Size2});
+ true -> ok end,
+ {ok, #file_info{size=Size3,type=regular}} = file:read_file_info(Log1 ++ "/3"),
+ if Size3 > 500 -> ct:fail({too_big, Size3});
+ true -> ok end,
gen_event:delete_handler(Pid, log_mf_h, []),
- ?line {ok, Index} = read_index_file(Log1),
+ {ok, Index} = read_index_file(Log1),
gen_event:add_handler(Pid, log_mf_h, Args1),
X = if Index == 3 -> 1; true -> Index + 1 end,
- ?line {ok, X} = read_index_file(Log1).
-
+ {ok, X} = read_index_file(Log1).
+
generate(Pid, Bytes) when Bytes > 32 ->
gen_event:notify(Pid, make_list(32, [])),
@@ -110,4 +110,3 @@ read_index_file(Dir) ->
end;
_ -> error
end.
-
diff --git a/lib/stdlib/test/maps_SUITE.erl b/lib/stdlib/test/maps_SUITE.erl
index 40a8b6ac81..7f94b7bcb1 100644
--- a/lib/stdlib/test/maps_SUITE.erl
+++ b/lib/stdlib/test/maps_SUITE.erl
@@ -23,11 +23,9 @@
-module(maps_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
--define(default_timeout, ?t:minutes(1)).
-
-% Test server specific exports
+%% Test server specific exports
-export([all/0]).
-export([suite/0]).
-export([init_per_suite/1]).
@@ -39,14 +37,15 @@
t_fold_3/1,t_map_2/1,t_size_1/1,
t_with_2/1,t_without_2/1]).
-%-define(badmap(V,F,Args), {'EXIT', {{badmap,V}, [{maps,F,Args,_}|_]}}).
-%-define(badarg(F,Args), {'EXIT', {badarg, [{maps,F,Args,_}|_]}}).
-% silly broken hipe
+%%-define(badmap(V,F,Args), {'EXIT', {{badmap,V}, [{maps,F,Args,_}|_]}}).
+%%-define(badarg(F,Args), {'EXIT', {badarg, [{maps,F,Args,_}|_]}}).
+%% silly broken hipe
-define(badmap(V,F,_Args), {'EXIT', {{badmap,V}, [{maps,F,_,_}|_]}}).
-define(badarg(F,_Args), {'EXIT', {badarg, [{maps,F,_,_}|_]}}).
suite() ->
- [{ct_hooks, [ts_install_cth]}].
+ [{ct_hooks, [ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[t_get_3,t_filter_2,
@@ -60,12 +59,9 @@ end_per_suite(_Config) ->
ok.
init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
t_get_3(Config) when is_list(Config) ->
diff --git a/lib/stdlib/test/ms_transform_SUITE.erl b/lib/stdlib/test/ms_transform_SUITE.erl
index f02e82b39c..a8bd90de84 100644
--- a/lib/stdlib/test/ms_transform_SUITE.erl
+++ b/lib/stdlib/test/ms_transform_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-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.
@@ -20,9 +20,10 @@
-module(ms_transform_SUITE).
-author('[email protected]').
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2,
init_per_group/2,end_per_group/2]).
-export([basic_ets/1]).
-export([basic_dbg/1]).
@@ -42,17 +43,16 @@
-export([warnings/1]).
-export([no_warnings/1]).
-export([eep37/1]).
--export([init_per_testcase/2, end_per_testcase/2]).
init_per_testcase(_Func, Config) ->
- Dog=test_server:timetrap(test_server:seconds(360)),
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Func, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog).
+end_per_testcase(_Func, _Config) ->
+ ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,6}}].
all() ->
[from_shell, basic_ets, basic_dbg, records,
@@ -79,94 +79,89 @@ end_per_group(_GroupName, Config) ->
%% This may be subject to change
-define(WARN_NUMBER_SHADOW,50).
-warnings(suite) ->
- [];
-warnings(doc) ->
- ["Check that shadowed variables in fun head generate warning"];
+
+%% Check that shadowed variables in fun head generate warning.
warnings(Config) when is_list(Config) ->
- ?line setup(Config),
+ setup(Config),
Prog = <<"A=5, "
- "ets:fun2ms(fun({A,B}) "
- " when is_integer(A) and (A+5 > B) -> "
- " A andalso B "
- " end)">>,
- ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'A'}}]}] =
+ "ets:fun2ms(fun({A,B}) "
+ " when is_integer(A) and (A+5 > B) -> "
+ " A andalso B "
+ " end)">>,
+ [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'A'}}]}] =
compile_ww(Prog),
Prog2 = <<"C = 5,
ets:fun2ms(fun ({A,B} =
- C) when is_integer(A) and (A+5 > B) ->
+ C) when is_integer(A) and (A+5 > B) ->
{A andalso B,C}
end)">>,
[{_,[{3,ms_transform,{?WARN_NUMBER_SHADOW,'C'}}]}] =
- compile_ww(Prog2),
- Rec3 = <<"-record(a,{a,b,c,d=foppa}).">>,
- Prog3 = <<"A = 3,
+ compile_ww(Prog2),
+ Rec3 = <<"-record(a,{a,b,c,d=foppa}).">>,
+ Prog3 = <<"A = 3,
C = 5,
- ets:fun2ms(fun (C
- = #a{a = A, b = B})
- when is_integer(A) and (A+5 > B) ->
- {A andalso B,C}
- end)">>,
+ ets:fun2ms(fun (C
+ = #a{a = A, b = B})
+ when is_integer(A) and (A+5 > B) ->
+ {A andalso B,C}
+ end)">>,
[{_,[{3,ms_transform,{?WARN_NUMBER_SHADOW,'C'}},
{4,ms_transform,{?WARN_NUMBER_SHADOW,'A'}}]}] =
- compile_ww(Rec3,Prog3),
- Rec4 = <<"-record(a,{a,b,c,d=foppa}).">>,
- Prog4 = <<"A=3,C=5, "
- "F = fun(B) -> B*3 end,"
- "erlang:display(F(A)),"
- "ets:fun2ms(fun(#a{a = A, b = B} = C) "
- " when is_integer(A) and (A+5 > B) -> "
- " {A andalso B,C} "
- " end)">>,
- ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'A'}},
- {_,ms_transform,{?WARN_NUMBER_SHADOW,'C'}}]}] =
- compile_ww(Rec4,Prog4),
- Rec5 = <<"-record(a,{a,b,c,d=foppa}).">>,
- Prog5 = <<"A=3,C=5, "
- "F = fun(B) -> B*3 end,"
- "erlang:display(F(A)),"
- "B = ets:fun2ms(fun(#a{a = A, b = B} = C) "
- " when is_integer(A) and (A+5 > B) -> "
- " {A andalso B,C} "
- " end)">>,
- ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'A'}},
- {_,ms_transform,{?WARN_NUMBER_SHADOW,'C'}}]}] =
- compile_ww(Rec5,Prog5),
- Prog6 = <<" X=bar, "
- " A = case X of"
- " foo ->"
- " foo;"
- " Y ->"
- " ets:fun2ms(fun(Y) ->" % This is a warning
- " 3*Y"
- " end)"
- " end,"
- " ets:fun2ms(fun(Y) ->" % Y out of "scope" here, so no warning
- " {3*Y,A}"
- " end)">>,
- ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'Y'}}]}] =
- compile_ww(Prog6),
- Prog7 = <<" X=bar, "
- " A = case X of"
- " foo ->"
- " Y = foo;"
- " Y ->"
- " bar"
- " end,"
- " ets:fun2ms(fun(Y) ->" % Y exported from case and safe, so warn
- " {3*Y,A}"
- " end)">>,
- ?line [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'Y'}}]}] =
- compile_ww(Prog7),
- ok.
-
-no_warnings(suite) ->
- [];
-no_warnings(doc) ->
- ["Check that variables bound in other function clauses don't generate "
- "warning"];
+ compile_ww(Rec3,Prog3),
+ Rec4 = <<"-record(a,{a,b,c,d=foppa}).">>,
+ Prog4 = <<"A=3,C=5, "
+ "F = fun(B) -> B*3 end,"
+ "erlang:display(F(A)),"
+ "ets:fun2ms(fun(#a{a = A, b = B} = C) "
+ " when is_integer(A) and (A+5 > B) -> "
+ " {A andalso B,C} "
+ " end)">>,
+ [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'A'}},
+ {_,ms_transform,{?WARN_NUMBER_SHADOW,'C'}}]}] =
+ compile_ww(Rec4,Prog4),
+ Rec5 = <<"-record(a,{a,b,c,d=foppa}).">>,
+ Prog5 = <<"A=3,C=5, "
+ "F = fun(B) -> B*3 end,"
+ "erlang:display(F(A)),"
+ "B = ets:fun2ms(fun(#a{a = A, b = B} = C) "
+ " when is_integer(A) and (A+5 > B) -> "
+ " {A andalso B,C} "
+ " end)">>,
+ [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'A'}},
+ {_,ms_transform,{?WARN_NUMBER_SHADOW,'C'}}]}] =
+ compile_ww(Rec5,Prog5),
+ Prog6 = <<" X=bar, "
+ " A = case X of"
+ " foo ->"
+ " foo;"
+ " Y ->"
+ " ets:fun2ms(fun(Y) ->" % This is a warning
+ " 3*Y"
+ " end)"
+ " end,"
+ " ets:fun2ms(fun(Y) ->" % Y out of "scope" here, so no warning
+ " {3*Y,A}"
+ " end)">>,
+ [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'Y'}}]}] =
+ compile_ww(Prog6),
+ Prog7 = <<" X=bar, "
+ " A = case X of"
+ " foo ->"
+ " Y = foo;"
+ " Y ->"
+ " bar"
+ " end,"
+ " ets:fun2ms(fun(Y) ->" % Y exported from case and safe, so warn
+ " {3*Y,A}"
+ " end)">>,
+ [{_,[{_,ms_transform,{?WARN_NUMBER_SHADOW,'Y'}}]}] =
+ compile_ww(Prog7),
+ ok.
+
+%% Check that variables bound in other function clauses don't generate
+%% warning.
no_warnings(Config) when is_list(Config) ->
- ?line setup(Config),
+ setup(Config),
Prog = <<"tmp(X) when X > 100 ->\n",
" Y=X,\n"
" Y;\n"
@@ -174,188 +169,167 @@ no_warnings(Config) when is_list(Config) ->
" ets:fun2ms(fun(Y) ->\n"
" {X, 3*Y}\n"
" end)">>,
- ?line [] = compile_no_ww(Prog),
+ [] = compile_no_ww(Prog),
Prog2 = <<"tmp(X) when X > 100 ->\n",
- " Y=X,\n"
- " Y;\n"
- "tmp(X) when X < 200 ->\n"
- " ok;\n"
- "tmp(X) ->\n"
- " ets:fun2ms(fun(Y) ->\n"
- " {X, 3*Y}\n"
- " end)">>,
- ?line [] = compile_no_ww(Prog2),
+ " Y=X,\n"
+ " Y;\n"
+ "tmp(X) when X < 200 ->\n"
+ " ok;\n"
+ "tmp(X) ->\n"
+ " ets:fun2ms(fun(Y) ->\n"
+ " {X, 3*Y}\n"
+ " end)">>,
+ [] = compile_no_ww(Prog2),
ok.
-andalso_orelse(suite) ->
- [];
-andalso_orelse(doc) ->
- ["Tests that andalso and orelse are allowed in guards."];
+%% Test that andalso and orelse are allowed in guards.
andalso_orelse(Config) when is_list(Config) ->
- ?line setup(Config),
- ?line [{{'$1','$2'},
- [{'and',{is_integer,'$1'},{'>',{'+','$1',5},'$2'}}],
- [{'andalso','$1','$2'}]}] =
+ setup(Config),
+ [{{'$1','$2'},
+ [{'and',{is_integer,'$1'},{'>',{'+','$1',5},'$2'}}],
+ [{'andalso','$1','$2'}]}] =
compile_and_run(<<"ets:fun2ms(fun({A,B}) "
- " when is_integer(A) and (A+5 > B) -> "
- " A andalso B "
- " end)">>),
- ?line [{{'$1','$2'},
- [{'or',{is_atom,'$1'},{'>',{'+','$1',5},'$2'}}],
- [{'orelse','$1','$2'}]}] =
+ " when is_integer(A) and (A+5 > B) -> "
+ " A andalso B "
+ " end)">>),
+ [{{'$1','$2'},
+ [{'or',{is_atom,'$1'},{'>',{'+','$1',5},'$2'}}],
+ [{'orelse','$1','$2'}]}] =
compile_and_run(<<"ets:fun2ms(fun({A,B}) "
- " when is_atom(A) or (A+5 > B) -> "
- " A orelse B "
- " end)">>),
- ?line [{{'$1','$2'},
- [{'andalso',{is_integer,'$1'},{'>',{'+','$1',5},'$2'}}],
- ['$1']}] =
+ " when is_atom(A) or (A+5 > B) -> "
+ " A orelse B "
+ " end)">>),
+ [{{'$1','$2'},
+ [{'andalso',{is_integer,'$1'},{'>',{'+','$1',5},'$2'}}],
+ ['$1']}] =
compile_and_run(
- <<"ets:fun2ms(fun({A,B}) when is_integer(A) andalso (A+5 > B) ->"
- " A "
- " end)">>),
- ?line [{{'$1','$2'},
- [{'orelse',{is_atom,'$1'},{'>',{'+','$1',5},'$2'}}],
- ['$1']}] =
+ <<"ets:fun2ms(fun({A,B}) when is_integer(A) andalso (A+5 > B) ->"
+ " A "
+ " end)">>),
+ [{{'$1','$2'},
+ [{'orelse',{is_atom,'$1'},{'>',{'+','$1',5},'$2'}}],
+ ['$1']}] =
compile_and_run(
- <<"ets:fun2ms(fun({A,B}) when is_atom(A) orelse (A+5 > B) -> "
- " A "
- " end)">>),
+ <<"ets:fun2ms(fun({A,B}) when is_atom(A) orelse (A+5 > B) -> "
+ " A "
+ " end)">>),
ok.
-
-
-bitsyntax(suite) ->
- [];
-bitsyntax(doc) ->
- ["Tests that bitsyntax works and does not work where appropriate"];
+
+
+%% Test that bitsyntax works and does not work where appropriate.
bitsyntax(Config) when is_list(Config) ->
- ?line setup(Config),
- ?line [{'_',[],
- [<<0,27,0,27>>]}] =
+ setup(Config),
+ [{'_',[],
+ [<<0,27,0,27>>]}] =
compile_and_run(<<"A = 27, "
"ets:fun2ms(fun(_) -> <<A:16,27:16>> end)">>),
- ?line [{{<<15,47>>,
- '$1',
- '$2'},
- [{'=:=','$1',
- <<0,27>>},
- {'=:=','$2',
- <<27,28,19>>}],
- [<<188,0,13>>]}] =
+ [{{<<15,47>>,
+ '$1',
+ '$2'},
+ [{'=:=','$1',
+ <<0,27>>},
+ {'=:=','$2',
+ <<27,28,19>>}],
+ [<<188,0,13>>]}] =
compile_and_run(<<"A = 27, "
"ets:fun2ms("
" fun({<<15,47>>,B,C}) "
" when B =:= <<A:16>>, C =:= <<27,28,19>> -> "
" <<A:4,12:4,13:16>> "
" end)">>),
- ?line expect_failure(
- <<>>,
- <<"ets:fun2ms(fun({<<15,47>>,B,C}) "
- " when B =:= <<16>>, C =:= <<27,28,19>> -> "
- " <<B:4,12:4,13:16>> "
- " end)">>),
- ?line expect_failure(
- <<>>,
- <<"ets:fun2ms(fun({<<A:15,47>>,B,C}) "
- " when B =:= <<16>>, C =:= <<27,28,19>> -> "
- " <<B:4,12:4,13:16>> "
- " end)">>),
+ expect_failure(
+ <<>>,
+ <<"ets:fun2ms(fun({<<15,47>>,B,C}) "
+ " when B =:= <<16>>, C =:= <<27,28,19>> -> "
+ " <<B:4,12:4,13:16>> "
+ " end)">>),
+ expect_failure(
+ <<>>,
+ <<"ets:fun2ms(fun({<<A:15,47>>,B,C}) "
+ " when B =:= <<16>>, C =:= <<27,28,19>> -> "
+ " <<B:4,12:4,13:16>> "
+ " end)">>),
ok.
-record_defaults(suite) ->
- [];
-record_defaults(doc) ->
- ["Tests that record defaults works"];
+%% Test that record defaults works.
record_defaults(Config) when is_list(Config) ->
- ?line setup(Config),
- ?line [{{<<27>>,{a,5,'$1',hej,hej}},
- [],
- [{{a,hej,{'*','$1',2},flurp,flurp}}]}] =
+ setup(Config),
+ [{{<<27>>,{a,5,'$1',hej,hej}},
+ [],
+ [{{a,hej,{'*','$1',2},flurp,flurp}}]}] =
compile_and_run(<<"-record(a,{a,b,c,d=foppa}).">>,
<<"ets:fun2ms(fun({<<27>>,#a{a=5, b=B,_=hej}}) -> "
- "#a{a=hej,b=B*2,_=flurp} "
- "end)">>),
+ "#a{a=hej,b=B*2,_=flurp} "
+ "end)">>),
ok.
-basic_ets(suite) ->
- [];
-basic_ets(doc) ->
- ["Tests basic ets:fun2ms"];
+%% Test basic ets:fun2ms.
basic_ets(Config) when is_list(Config) ->
- ?line setup(Config),
- ?line [{{a,b},[],[true]}] = compile_and_run(
- <<"ets:fun2ms(fun({a,b}) -> true end)">>),
- ?line [{{'$1',foo},[{is_list,'$1'}],[{{{hd,'$1'},'$_'}}]},
+ setup(Config),
+ [{{a,b},[],[true]}] = compile_and_run(
+ <<"ets:fun2ms(fun({a,b}) -> true end)">>),
+ [{{'$1',foo},[{is_list,'$1'}],[{{{hd,'$1'},'$_'}}]},
{{'$1','$1'},[{is_tuple,'$1'}],[{{{element,1,'$1'},'$*'}}]}] =
compile_and_run(<<"ets:fun2ms(fun({X,foo}) when is_list(X) -> ",
- "{hd(X),object()};",
- "({X,X}) when is_tuple(X) ->",
- "{element(1,X),bindings()}",
- "end)">>),
- ?line [{{'$1','$2'},[],[{{'$2','$1'}}]}] =
+ "{hd(X),object()};",
+ "({X,X}) when is_tuple(X) ->",
+ "{element(1,X),bindings()}",
+ "end)">>),
+ [{{'$1','$2'},[],[{{'$2','$1'}}]}] =
compile_and_run(<<"ets:fun2ms(fun({A,B}) -> {B,A} end)">>),
- ?line [{{'$1','$2'},[],[['$2','$1']]}] =
+ [{{'$1','$2'},[],[['$2','$1']]}] =
compile_and_run(<<"ets:fun2ms(fun({A,B}) -> [B,A] end)">>),
ok.
-basic_dbg(suite) ->
- [];
-basic_dbg(doc) ->
- ["Tests basic ets:fun2ms"];
+%% Tests basic ets:fun2ms.
basic_dbg(Config) when is_list(Config) ->
- ?line setup(Config),
- ?line [{[a,b],[],[{message,banan},{return_trace}]}] =
+ setup(Config),
+ [{[a,b],[],[{message,banan},{return_trace}]}] =
compile_and_run(<<"dbg:fun2ms(fun([a,b]) -> message(banan), ",
- "return_trace() end)">>),
- ?line [{['$1','$2'],[],[{{'$2','$1'}}]}] =
+ "return_trace() end)">>),
+ [{['$1','$2'],[],[{{'$2','$1'}}]}] =
compile_and_run(<<"dbg:fun2ms(fun([A,B]) -> {B,A} end)">>),
- ?line [{['$1','$2'],[],[['$2','$1']]}] =
+ [{['$1','$2'],[],[['$2','$1']]}] =
compile_and_run(<<"dbg:fun2ms(fun([A,B]) -> [B,A] end)">>),
- ?line [{['$1','$2'],[],['$*']}] =
+ [{['$1','$2'],[],['$*']}] =
compile_and_run(<<"dbg:fun2ms(fun([A,B]) -> bindings() end)">>),
- ?line [{['$1','$2'],[],['$_']}] =
+ [{['$1','$2'],[],['$_']}] =
compile_and_run(<<"dbg:fun2ms(fun([A,B]) -> object() end)">>),
ok.
-from_shell(suite) ->
- [];
-from_shell(doc) ->
- ["Test calling of ets/dbg:fun2ms from the shell"];
+%% Test calling of ets/dbg:fun2ms from the shell.
from_shell(Config) when is_list(Config) ->
- ?line setup(Config),
- ?line Fun = do_eval("fun({a,b}) -> true end"),
- ?line [{{a,b},[],[true]}] = apply(ets,fun2ms,[Fun]),
- ?line [{{a,b},[],[true]}] = do_eval("ets:fun2ms(fun({a,b}) -> true end)"),
- ?line Fun2 = do_eval("fun([a,b]) -> message(banan), return_trace() end"),
- ?line [{[a,b],[],[{message,banan},{return_trace}]}]
+ setup(Config),
+ Fun = do_eval("fun({a,b}) -> true end"),
+ [{{a,b},[],[true]}] = apply(ets,fun2ms,[Fun]),
+ [{{a,b},[],[true]}] = do_eval("ets:fun2ms(fun({a,b}) -> true end)"),
+ Fun2 = do_eval("fun([a,b]) -> message(banan), return_trace() end"),
+ [{[a,b],[],[{message,banan},{return_trace}]}]
= apply(dbg,fun2ms,[Fun2]),
- ?line [{[a,b],[],[{message,banan},{return_trace}]}] =
+ [{[a,b],[],[{message,banan},{return_trace}]}] =
do_eval(
"dbg:fun2ms(fun([a,b]) -> message(banan), return_trace() end)"),
ok.
-records(suite) ->
- [];
-records(doc) ->
- ["Tests expansion of records in fun2ms"];
+%% Tests expansion of records in fun2ms.
records(Config) when is_list(Config) ->
- ?line setup(Config),
- ?line RD = <<"-record(t, {"
- "t1 = [],"
- "t2 = foo,"
- "t3,"
- "t4"
- "}).">>,
- ?line [{{t,'$1','$2',foo,'_'},[{is_list,'$1'}],[{{{hd,'$1'},'$_'}}]},
+ setup(Config),
+ RD = <<"-record(t, {"
+ "t1 = [] :: list(),"
+ "t2 = foo :: atom(),"
+ "t3,"
+ "t4"
+ "}).">>,
+ [{{t,'$1','$2',foo,'_'},[{is_list,'$1'}],[{{{hd,'$1'},'$_'}}]},
{{t,'_','_','_','_'},[{'==',{element,2,'$_'},nisse}],[{{'$*'}}]}] =
compile_and_run(RD,<<
- "ets:fun2ms(fun(#t{t1 = X, t2 = Y, t3 = foo}) when is_list(X) ->
+ "ets:fun2ms(fun(#t{t1 = X, t2 = Y, t3 = foo}) when is_list(X) ->
{hd(X),object()};
- (#t{}) when (object())#t.t1 == nisse ->
- {bindings()}
- end)">>),
- ?line [{{t,'$1','$2','_',foo},
+ (#t{}) when (object())#t.t1 == nisse ->
+ {bindings()}
+ end)">>),
+ [{{t,'$1','$2','_',foo},
[{'==',{element,4,'$_'},7},{is_list,'$1'}],
[{{{hd,'$1'},'$_'}}]},
{'$1',[{is_record,'$1',t,5}],
@@ -373,7 +347,7 @@ records(Config) when is_list(Config) ->
}
end)"
>>),
- ?line [{[{t,'$1','$2',foo,'_'}],[{is_list,'$1'}],[{{{hd,'$1'},'$_'}}]},
+ [{[{t,'$1','$2',foo,'_'}],[{is_list,'$1'}],[{{{hd,'$1'},'$_'}}]},
{[{t,'_','_','_','_'}],[{'==',{element,2,{hd,'$_'}},nisse}],[{{'$*'}}]}]=
compile_and_run(RD,<<
"dbg:fun2ms(fun([#t{t1 = X, t2 = Y, t3 = foo}]) when is_list(X) ->
@@ -385,78 +359,66 @@ records(Config) when is_list(Config) ->
ok.
-record_index(suite) ->
- [];
-record_index(doc) ->
- ["Tests expansion of records in fun2ms, part 2"];
+%% Test expansion of records in fun2ms, part 2.
record_index(Config) when is_list(Config) ->
- ?line setup(Config),
- ?line RD = <<"-record(a,{a,b}).">>,
- ?line [{{2},[],[true]}] = compile_and_run(RD,
+ setup(Config),
+ RD = <<"-record(a,{a,b}).">>,
+ [{{2},[],[true]}] = compile_and_run(RD,
<<"ets:fun2ms(fun({#a.a}) -> true end)">>),
- ?line [{{2},[],[2]}] = compile_and_run(RD,
+ [{{2},[],[2]}] = compile_and_run(RD,
<<"ets:fun2ms(fun({#a.a}) -> #a.a end)">>),
- ?line [{{2,'$1'},[{'>','$1',2}],[2]}] = compile_and_run(RD,
+ [{{2,'$1'},[{'>','$1',2}],[2]}] = compile_and_run(RD,
<<"ets:fun2ms(fun({#a.a,A}) when A > #a.a -> #a.a end)">>),
ok.
-top_match(suite) ->
- [];
-top_match(doc) ->
- ["Tests matching on top level in head to give alias for object()"];
+%% Tests matching on top level in head to give alias for object().
top_match(Config) when is_list(Config) ->
- ?line setup(Config),
- ?line RD = <<"-record(a,{a,b}).">>,
- ?line [{{a,3,'_'},[],['$_']}] =
+ setup(Config),
+ RD = <<"-record(a,{a,b}).">>,
+ [{{a,3,'_'},[],['$_']}] =
compile_and_run(RD,
<<"ets:fun2ms(fun(A = #a{a=3}) -> A end)">>),
- ?line [{{a,3,'_'},[],['$_']}] =
+ [{{a,3,'_'},[],['$_']}] =
compile_and_run(RD,
<<"ets:fun2ms(fun(#a{a=3} = A) -> A end)">>),
- ?line [{[a,b],[],['$_']}] =
+ [{[a,b],[],['$_']}] =
compile_and_run(RD,
<<"dbg:fun2ms(fun(A = [a,b]) -> A end)">>),
- ?line [{[a,b],[],['$_']}] =
+ [{[a,b],[],['$_']}] =
compile_and_run(RD,
<<"dbg:fun2ms(fun([a,b] = A) -> A end)">>),
- ?line expect_failure(RD,
+ expect_failure(RD,
<<"ets:fun2ms(fun({a,A = {_,b}}) -> A end)">>),
- ?line expect_failure(RD,
+ expect_failure(RD,
<<"dbg:fun2ms(fun([a,A = {_,b}]) -> A end)">>),
- ?line expect_failure(RD,
+ expect_failure(RD,
<<"ets:fun2ms(fun(A#a{a = 2}) -> A end)">>),
ok.
-multipass(suite) ->
- [];
-multipass(doc) ->
- ["Tests that multi-defined fields in records give errors."];
+%% Tests that multi-defined fields in records give errors.
multipass(Config) when is_list(Config) ->
- ?line setup(Config),
- ?line RD = <<"-record(a,{a,b}).">>,
- ?line expect_failure(RD,<<"ets:fun2ms(fun(A) -> #a{a=2,a=3} end)">>),
- ?line expect_failure(RD,<<"ets:fun2ms(fun(A) -> A#a{a=2,a=3} end)">>),
- ?line expect_failure(RD,<<"ets:fun2ms(fun(A) when A =:= #a{a=2,a=3} ->",
+ setup(Config),
+ RD = <<"-record(a,{a,b}).">>,
+ expect_failure(RD,<<"ets:fun2ms(fun(A) -> #a{a=2,a=3} end)">>),
+ expect_failure(RD,<<"ets:fun2ms(fun(A) -> A#a{a=2,a=3} end)">>),
+ expect_failure(RD,<<"ets:fun2ms(fun(A) when A =:= #a{a=2,a=3} ->",
" true end)">>),
- ?line expect_failure(RD,<<"ets:fun2ms(fun({A,B})when A =:= B#a{a=2,a=3}->",
+ expect_failure(RD,<<"ets:fun2ms(fun({A,B})when A =:= B#a{a=2,a=3}->",
"true end)">>),
- ?line expect_failure(RD,<<"ets:fun2ms(fun(#a{a=3,a=3}) -> true end)">>),
- ?line compile_and_run(RD,<<"ets:fun2ms(fun(A) -> #a{a=2,b=3} end)">>),
- ?line compile_and_run(RD,<<"ets:fun2ms(fun(A) -> A#a{a=2,b=3} end)">>),
- ?line compile_and_run(RD,<<"ets:fun2ms(fun(A) when A =:= #a{a=2,b=3} ->",
+ expect_failure(RD,<<"ets:fun2ms(fun(#a{a=3,a=3}) -> true end)">>),
+ compile_and_run(RD,<<"ets:fun2ms(fun(A) -> #a{a=2,b=3} end)">>),
+ compile_and_run(RD,<<"ets:fun2ms(fun(A) -> A#a{a=2,b=3} end)">>),
+ compile_and_run(RD,<<"ets:fun2ms(fun(A) when A =:= #a{a=2,b=3} ->",
" true end)">>),
- ?line compile_and_run(RD,<<"ets:fun2ms(fun({A,B})when A=:= B#a{a=2,b=3}->",
+ compile_and_run(RD,<<"ets:fun2ms(fun({A,B})when A=:= B#a{a=2,b=3}->",
"true end)">>),
- ?line compile_and_run(RD,<<"ets:fun2ms(fun(#a{a=3,b=3}) -> true end)">>),
+ compile_and_run(RD,<<"ets:fun2ms(fun(#a{a=3,b=3}) -> true end)">>),
ok.
-old_guards(suite) ->
- [];
-old_guards(doc) ->
- ["Tests that old type tests in guards are translated"];
+%% Test that old type tests in guards are translated.
old_guards(Config) when is_list(Config) ->
- ?line setup(Config),
+ setup(Config),
Tests = [
{atom,is_atom},
{float,is_float},
@@ -469,7 +431,7 @@ old_guards(Config) when is_list(Config) ->
{tuple,is_tuple},
{binary,is_binary},
{function,is_function}],
- ?line lists:foreach(
+ lists:foreach(
fun({Old,New}) ->
Bin = list_to_binary([<<"ets:fun2ms(fun(X) when ">>,
atom_to_list(Old),
@@ -482,15 +444,15 @@ old_guards(Config) when is_list(Config) ->
end
end,
Tests),
- ?line RD = <<"-record(a,{a,b}).">>,
- ?line [{'$1',[{is_record,'$1',a,3}],[true]}] =
+ RD = <<"-record(a,{a,b}).">>,
+ [{'$1',[{is_record,'$1',a,3}],[true]}] =
compile_and_run(RD,
<<"ets:fun2ms(fun(X) when record(X,a) -> true end)">>),
- ?line expect_failure
+ expect_failure
(RD,
<<"ets:fun2ms(fun(X) when integer(X) and constant(X) -> "
"true end)">>),
- ?line [{'$1',[{is_integer,'$1'},
+ [{'$1',[{is_integer,'$1'},
{is_float,'$1'},
{is_atom,'$1'},
{is_list,'$1'},
@@ -511,13 +473,10 @@ old_guards(Config) when is_list(Config) ->
>>),
ok.
-autoimported(suite) ->
- [];
-autoimported(doc) ->
- ["Tests use of autoimported bif's used like erlang:'+'(A,B) in guards"
- " and body."];
+%% Test use of autoimported BIFs used like erlang:'+'(A,B) in guards
+%% and body.
autoimported(Config) when is_list(Config) ->
- ?line setup(Config),
+ setup(Config),
Allowed = [
{abs,1},
{element,2},
@@ -530,7 +489,7 @@ autoimported(Config) when is_list(Config) ->
{tl,1},
{trunc,1},
{self,0},
- %{float,1}, see float_1_function/1
+ %%{float,1}, see float_1_function/1
{is_atom,1},
{is_float,1},
{is_integer,1},
@@ -547,8 +506,8 @@ autoimported(Config) when is_list(Config) ->
{'or',2,infix},
{'xor',2,infix},
{'not',1},
- %{'andalso',2,infix},
- %{'orelse',2,infix},
+ %%{'andalso',2,infix},
+ %%{'orelse',2,infix},
{'+',1},
{'+',2,infix},
{'-',1},
@@ -571,8 +530,8 @@ autoimported(Config) when is_list(Config) ->
{'=:=',2,infix},
{'/=',2,infix},
{'=/=',2,infix}],
- ?line RD = <<"-record(a,{a,b}).">>,
- ?line lists:foreach(
+ RD = <<"-record(a,{a,b}).">>,
+ lists:foreach(
fun({A,0}) ->
L = atom_to_list(A),
Bin1 = list_to_binary(
@@ -687,85 +646,76 @@ autoimported(Config) when is_list(Config) ->
Allowed),
ok.
-semicolon(suite) ->
- [];
-semicolon(doc) ->
- ["Tests semicolon in guards of match_specs."];
+%% Test semicolon in guards of match_specs.
semicolon(Config) when is_list(Config) ->
- ?line setup(Config),
- ?line Res01 = compile_and_run
+ setup(Config),
+ Res01 = compile_and_run
(<<"ets:fun2ms(fun(X) when is_integer(X); "
"is_float(X) -> true end)">>),
- ?line Res02 = compile_and_run
+ Res02 = compile_and_run
(<<"ets:fun2ms(fun(X) when is_integer(X) -> true; "
"(X) when is_float(X) -> true end)">>),
- ?line Res01 = Res02,
- ?line Res11 = compile_and_run
+ Res01 = Res02,
+ Res11 = compile_and_run
(<<"ets:fun2ms(fun(X) when is_integer(X); "
"is_float(X); atom(X) -> true end)">>),
- ?line Res12 = compile_and_run
+ Res12 = compile_and_run
(<<"ets:fun2ms(fun(X) when is_integer(X) -> true; "
"(X) when is_float(X) -> true; "
"(X) when is_atom(X) -> true end)">>),
- ?line Res11 = Res12,
+ Res11 = Res12,
ok.
-float_1_function(suite) ->
- [];
-float_1_function(doc) ->
- ["OTP-5297. The function float/1."];
+%% OTP-5297. The function float/1.
float_1_function(Config) when is_list(Config) ->
- ?line setup(Config),
+ setup(Config),
RunMS = fun(L, MS) ->
ets:match_spec_run(L, ets:match_spec_compile(MS))
end,
- ?line MS1 = compile_and_run
+ MS1 = compile_and_run
(<<"ets:fun2ms(fun(X) -> float(X) end)">>),
- ?line [F1] = RunMS([3], MS1),
- ?line true = is_float(F1) and (F1 == 3),
+ [F1] = RunMS([3], MS1),
+ true = is_float(F1) and (F1 == 3),
- ?line MS1b = compile_and_run
+ MS1b = compile_and_run
(<<"dbg:fun2ms(fun(X) -> float(X) end)">>),
- ?line [F2] = RunMS([3], MS1b),
- ?line true = is_float(F2) and (F2 == 3),
+ [F2] = RunMS([3], MS1b),
+ true = is_float(F2) and (F2 == 3),
- ?line MS2 = compile_and_run
+ MS2 = compile_and_run
(<<"ets:fun2ms(fun(X) when is_pid(X) or float(X) -> true end)">>),
- ?line [] = RunMS([3.0], MS2),
+ [] = RunMS([3.0], MS2),
- ?line MS3 = compile_and_run
+ MS3 = compile_and_run
(<<"dbg:fun2ms(fun(X) when is_pid(X); float(X) -> true end)">>),
- ?line [true] = RunMS([3.0], MS3),
+ [true] = RunMS([3.0], MS3),
- ?line MS4 = compile_and_run
+ MS4 = compile_and_run
(<<"ets:fun2ms(fun(X) when erlang:float(X) > 1 -> big;"
" (_) -> small end)">>),
- ?line [small,big] = RunMS([1.0, 3.0], MS4),
+ [small,big] = RunMS([1.0, 3.0], MS4),
- ?line MS5 = compile_and_run
+ MS5 = compile_and_run
(<<"ets:fun2ms(fun(X) when float(X) > 1 -> big;"
" (_) -> small end)">>),
- ?line [small,big] = RunMS([1.0, 3.0], MS5),
+ [small,big] = RunMS([1.0, 3.0], MS5),
%% This is the test from autoimported/1.
- ?line [{'$1',[{is_float,'$1'}],[{float,'$1'}]}] =
+ [{'$1',[{is_float,'$1'}],[{float,'$1'}]}] =
compile_and_run
(<<"ets:fun2ms(fun(X) when float(X) -> float(X) end)">>),
- ?line [{'$1',[{float,'$1'}],[{float,'$1'}]}] =
+ [{'$1',[{float,'$1'}],[{float,'$1'}]}] =
compile_and_run
(<<"ets:fun2ms(fun(X) when erlang:'float'(X) -> "
"erlang:'float'(X) end)">>),
ok.
-action_function(suite) ->
- [];
-action_function(doc) ->
- ["Test all 'action functions'."];
+%% Test all 'action functions'.
action_function(Config) when is_list(Config) ->
- ?line setup(Config),
- ?line [{['$1','$2'],[],
+ setup(Config),
+ [{['$1','$2'],[],
[{set_seq_token,label,0},
{get_seq_token},
{message,'$1'},
@@ -778,7 +728,7 @@ action_function(Config) when is_list(Config) ->
"message(X), "
"return_trace(), "
"exception_trace() end)">>),
- ?line [{['$1','$2'],[],
+ [{['$1','$2'],[],
[{process_dump},
{enable_trace,send},
{enable_trace,'$2',send},
@@ -791,7 +741,7 @@ action_function(Config) when is_list(Config) ->
"enable_trace(Y, send), "
"disable_trace(procs), "
"disable_trace(Y, procs) end)">>),
- ?line [{['$1','$2'],
+ [{['$1','$2'],
[],
[{display,'$1'},
{caller},
@@ -821,7 +771,7 @@ eep37(Config) when is_list(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Helpers
+%% Helpers
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
setup(Config) ->
@@ -832,14 +782,13 @@ temp_name() ->
Conf = get(mts_config),
C = get(mts_tf_counter),
put(mts_tf_counter,C+1),
- filename:join([?config(priv_dir,Conf),
+ filename:join([proplists:get_value(priv_dir,Conf),
"tempfile"++integer_to_list(C)++".tmp"]).
expect_failure(Recs,Code) ->
case (catch compile_and_run(Recs,Code)) of
{'EXIT',_Foo} ->
- %erlang:display(_Foo),
ok;
Other ->
exit({expected,failure,got,Other})
diff --git a/lib/stdlib/test/proc_lib_SUITE.erl b/lib/stdlib/test/proc_lib_SUITE.erl
index f7a6a38138..ebce74545a 100644
--- a/lib/stdlib/test/proc_lib_SUITE.erl
+++ b/lib/stdlib/test/proc_lib_SUITE.erl
@@ -44,7 +44,7 @@
-ifdef(STANDALONE).
-define(line, noop, ).
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-endif.
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -115,7 +115,7 @@ crash(Config) when is_list(Config) ->
%% Spawn function with neighbour.
Pid4 = proc_lib:spawn(?MODULE, sp2, []),
- test_server:sleep(100),
+ ct:sleep(100),
{?MODULE,sp2,[]} = proc_lib:initial_call(Pid4),
{?MODULE,sp2,0} = proc_lib:translate_initial_call(Pid4),
Pid4 ! die,
@@ -152,9 +152,9 @@ analyse_crash(Pid, Expected0, ExpLinks) ->
analyse_links(ExpLinks, Links);
Unexpected ->
io:format("~p\n", [Unexpected]),
- test_server:fail(unexpected_message)
+ ct:fail(unexpected_message)
after 5000 ->
- test_server:fail(no_crash_report)
+ ct:fail(no_crash_report)
end.
analyse_links([H|Es], [{neighbour,N}|Links]) ->
@@ -170,7 +170,7 @@ analyse_crash_1([{Key,Pattern}|T], Report) ->
case lists:keyfind(Key, 1, Report) of
false ->
io:format("~p", [Report]),
- test_server:fail({missing_key,Key});
+ ct:fail({missing_key,Key});
{Key,Info} ->
try
match_info(Pattern, Info)
@@ -179,7 +179,7 @@ analyse_crash_1([{Key,Pattern}|T], Report) ->
io:format("key: ~p", [Key]),
io:format("pattern: ~p", [Pattern]),
io:format("actual: ~p", [Report]),
- test_server:fail(no_match)
+ ct:fail(no_match)
end,
analyse_crash_1(T, Report)
end;
@@ -203,7 +203,7 @@ sync_start_nolink(Config) when is_list(Config) ->
receive
{sync_started, F} ->
exit(F, kill),
- test_server:fail(async_start)
+ ct:fail(async_start)
after 1000 -> ok
end,
receive
@@ -214,14 +214,14 @@ sync_start_nolink(Config) when is_list(Config) ->
{sync_started, _} -> ok
after 1000 ->
exit(Pid2, kill),
- test_server:fail(no_sync_start)
+ ct:fail(no_sync_start)
end,
ok.
-
+
sync_start_link(Config) when is_list(Config) ->
_Pid = spawn_link(?MODULE, sp3, [self()]),
receive
- {sync_started, _} -> test_server:fail(async_start)
+ {sync_started, _} -> ct:fail(async_start)
after 1000 -> ok
end,
receive
@@ -230,24 +230,24 @@ sync_start_link(Config) when is_list(Config) ->
end,
receive
{sync_started, _} -> ok
- after 1000 -> test_server:fail(no_sync_start)
+ after 1000 -> ct:fail(no_sync_start)
end,
ok.
-
+
spawn_opt(Config) when is_list(Config) ->
F = fun sp1/0,
{name,Fname} = erlang:fun_info(F, name),
FunMFArgs = {?MODULE,Fname,[]},
FunMFArity = {?MODULE,Fname,0},
- ?line Pid1 = proc_lib:spawn_opt(node(), F, [{priority,low}]),
- ?line Pid = proc_lib:spawn_opt(F, [{priority,low}]),
- ?line test_server:sleep(100),
- ?line FunMFArgs = proc_lib:initial_call(Pid),
- ?line FunMFArity = proc_lib:translate_initial_call(Pid),
- ?line Pid ! die,
- ?line FunMFArgs = proc_lib:initial_call(Pid1),
- ?line FunMFArity = proc_lib:translate_initial_call(Pid1),
- ?line Pid1 ! die,
+ Pid1 = proc_lib:spawn_opt(node(), F, [{priority,low}]),
+ Pid = proc_lib:spawn_opt(F, [{priority,low}]),
+ ct:sleep(100),
+ FunMFArgs = proc_lib:initial_call(Pid),
+ FunMFArity = proc_lib:translate_initial_call(Pid),
+ Pid ! die,
+ FunMFArgs = proc_lib:initial_call(Pid1),
+ FunMFArity = proc_lib:translate_initial_call(Pid1),
+ Pid1 ! die,
ok.
@@ -283,57 +283,57 @@ hibernate(Config) when is_list(Config) ->
Ref = make_ref(),
Self = self(),
LoopData = {Ref,Self},
- ?line Pid = proc_lib:spawn_link(?MODULE, hib_loop, [LoopData]),
+ Pid = proc_lib:spawn_link(?MODULE, hib_loop, [LoopData]),
%% Just check that the child process can process and answer messages.
- ?line Pid ! {Self,loop_data},
+ Pid ! {Self,loop_data},
receive
{loop_data,LoopData} -> ok;
Unexpected0 ->
- ?line io:format("Unexpected: ~p\n", [Unexpected0]),
- ?line ?t:fail()
+ io:format("Unexpected: ~p\n", [Unexpected0]),
+ ct:fail(failed)
after 1000 ->
- ?line io:format("Timeout"),
- ?line ?t:fail()
+ io:format("Timeout"),
+ ct:fail(failed)
end,
%% Hibernate the process.
- ?line Pid ! hibernate,
+ Pid ! hibernate,
erlang:yield(),
io:format("~p\n", [process_info(Pid, heap_size)]),
%% Send a message to the process...
- ?line Pid ! {Self,loop_data},
+ Pid ! {Self,loop_data},
%% ... expect first a wake up message from the process...
receive
{awaken,LoopData} -> ok;
Unexpected1 ->
- ?line io:format("Unexpected: ~p\n", [Unexpected1]),
- ?line ?t:fail()
+ io:format("Unexpected: ~p\n", [Unexpected1]),
+ ct:fail(failed)
after 1000 ->
- ?line io:format("Timeout"),
- ?line ?t:fail()
+ io:format("Timeout"),
+ ct:fail(failed)
end,
%% ... followed by the answer to the actual request.
receive
{loop_data,LoopData} -> ok;
Unexpected2 ->
- ?line io:format("Unexpected: ~p\n", [Unexpected2]),
- ?line ?t:fail()
+ io:format("Unexpected: ~p\n", [Unexpected2]),
+ ct:fail(failed)
after 1000 ->
- ?line io:format("Timeout"),
- ?line ?t:fail()
+ io:format("Timeout"),
+ ct:fail(failed)
end,
%% Test that errors are handled correctly after wake up from hibernation...
- ?line process_flag(trap_exit, true),
- ?line error_logger:add_report_handler(?MODULE, self()),
- ?line Pid ! crash,
+ process_flag(trap_exit, true),
+ error_logger:add_report_handler(?MODULE, self()),
+ Pid ! crash,
%% We should receive two messages. Especially in the SMP emulator,
%% we can't be sure of the message order, so sort the messages before
@@ -341,10 +341,10 @@ hibernate(Config) when is_list(Config) ->
Messages = lists:sort(hib_receive_messages(2)),
io:format("~p", [Messages]),
- ?line [{'EXIT',Pid,i_crashed},{crash_report,Pid,[Report,[]]}] = Messages,
+ [{'EXIT',Pid,i_crashed},{crash_report,Pid,[Report,[]]}] = Messages,
%% Check that the initial_call has the expected format.
- ?line {value,{initial_call,{?MODULE,hib_loop,[_]}}} =
+ {value,{initial_call,{?MODULE,hib_loop,[_]}}} =
lists:keysearch(initial_call, 1, Report),
error_logger:delete_report_handler(?MODULE),
@@ -371,10 +371,7 @@ hib_receive_messages(N) ->
Any -> [Any|hib_receive_messages(N-1)]
end.
-otp_6345(suite) ->
- [];
-otp_6345(doc) ->
- ["'monitor' spawn_opt option"];
+%% 'monitor' spawn_opt option.
otp_6345(Config) when is_list(Config) ->
Opts = [link,monitor],
{'EXIT', {badarg,[{proc_lib,check_for_monitor,_,_}|_Stack]}} =
@@ -392,11 +389,8 @@ otp_6345_loop() ->
otp_6345_loop()
end.
-%% OTP-9803
-init_dont_hang(suite) ->
- [];
-init_dont_hang(doc) ->
- ["Check that proc_lib:start don't hang if spawned process crashes before proc_lib:init_ack/2"];
+%% OTP-9803. Check that proc_lib:start() doesn't hang if spawned process
+%% crashes before proc_lib:init_ack/2.
init_dont_hang(Config) when is_list(Config) ->
%% Start should behave as start_link
process_flag(trap_exit, true),
@@ -489,7 +483,7 @@ stop(_Config) ->
{'EXIT',noproc} = (catch proc_lib:stop({to_stop,Node})),
true = test_server:stop_node(Node),
-
+
%% Remote registered name, but non-existing node
{'EXIT',{{nodedown,Node},_}} = (catch proc_lib:stop({to_stop,Node})),
ok.
@@ -522,7 +516,7 @@ t_format() ->
if
Tsz >= Usz ->
- ?t:fail();
+ ct:fail(failed);
true ->
ok
end,
@@ -549,7 +543,7 @@ t_format_looper() ->
%%-----------------------------------------------------------------
init(Tester) ->
{ok, Tester}.
-
+
handle_event({error_report, _GL, {Pid, crash_report, Report}}, Tester) ->
io:format("~s\n", [proc_lib:format(Report)]),
Tester ! {crash_report, Pid, Report},
diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl
index 52fdb69b73..75971bcf11 100644
--- a/lib/stdlib/test/qlc_SUITE.erl
+++ b/lib/stdlib/test/qlc_SUITE.erl
@@ -25,7 +25,7 @@
-define(QLC, qlc).
-define(QLCs, "qlc").
-%-define(debug, true).
+%%-define(debug, true).
%% There are often many tests per testcase. Most tests are copied to a
%% module, a file. The file is compiled and the test run. Should the
@@ -43,10 +43,10 @@
-define(testcase, current_testcase). % don't know
-define(t, test_server).
-else.
--include_lib("test_server/include/test_server.hrl").
--define(datadir, ?config(data_dir, Config)).
--define(privdir, ?config(priv_dir, Config)).
--define(testcase, ?config(?TESTCASE, Config)).
+-include_lib("common_test/include/ct.hrl").
+-define(datadir, proplists:get_value(data_dir, Config)).
+-define(privdir, proplists:get_value(priv_dir, Config)).
+-define(testcase, proplists:get_value(?TESTCASE, Config)).
-endif.
-include_lib("stdlib/include/ms_transform.hrl").
@@ -80,7 +80,7 @@
backward/1, forward/1,
- eep37/1]).
+ eep37/1]).
%% Internal exports.
-export([bad_table_throw/1, bad_table_exit/1, default_table/1, bad_table/1,
@@ -107,19 +107,15 @@
handle_event/2, handle_call/2, handle_info/2,
terminate/2]).
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(5)).
-
init_per_testcase(Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- [{?TESTCASE, Case}, {watchdog, Dog} | Config].
+ [{?TESTCASE, Case} | Config].
end_per_testcase(_Case, _Config) ->
- Dog = ?config(watchdog, _Config),
- test_server:timetrap_cancel(Dog),
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,5}}].
all() ->
[{group, parse_transform}, {group, evaluation},
@@ -159,35 +155,30 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-badarg(doc) ->
- "Badarg.";
-badarg(suite) -> [];
badarg(Config) when is_list(Config) ->
Ts =
- [{badarg,
- <<"-import(qlc, [q/1, q/2]).
+ [{badarg,
+ <<"-import(qlc, [q/1, q/2]).
q(_, _, _) -> ok.
- badarg() ->
- qlc:q(foo),
- qlc:q(foo, cache_all),
- qlc:q(foo, cache_all, extra),
- q(bar),
- q(bar, cache_all),
- q(bar, cache_all, extra).
- ">>,
+badarg() ->
+ qlc:q(foo),
+ qlc:q(foo, cache_all),
+ qlc:q(foo, cache_all, extra),
+ q(bar),
+ q(bar, cache_all),
+ q(bar, cache_all, extra).
+">>,
[],
- {errors,[{5,?QLC,not_a_query_list_comprehension},
- {6,?QLC,not_a_query_list_comprehension},
- {8,?QLC,not_a_query_list_comprehension},
- {9,?QLC,not_a_query_list_comprehension}],
- []}}],
- ?line [] = compile(Config, Ts),
+{errors,[{5,?QLC,not_a_query_list_comprehension},
+ {6,?QLC,not_a_query_list_comprehension},
+ {8,?QLC,not_a_query_list_comprehension},
+ {9,?QLC,not_a_query_list_comprehension}],
+ []}}],
+ [] = compile(Config, Ts),
ok.
-nested_qlc(doc) ->
- "Nested qlc expressions.";
-nested_qlc(suite) -> [];
+%% Nested qlc expressions.
nested_qlc(Config) when is_list(Config) ->
%% Nested QLC expressions. X is bound before the first one; Z and X
%% before the second one.
@@ -227,12 +218,10 @@ nested_qlc(Config) when is_list(Config) ->
[warn_unused_vars],
{warnings,[{{6,39},erl_lint,{shadowed_var,'X',generate}}]}}
],
- ?line [] = compile(Config, Ts),
+ [] = compile(Config, Ts),
ok.
-unused_var(doc) ->
- "Unused variable with a name that should not be introduced.";
-unused_var(suite) -> [];
+%% Unused variable with a name that should not be introduced.
unused_var(Config) when is_list(Config) ->
Ts =
[{unused_var,
@@ -244,12 +233,10 @@ unused_var(Config) when is_list(Config) ->
">>,
[warn_unused_vars],
{warnings,[{{2,33},erl_lint,{unused_var,'Y1'}}]}}],
- ?line [] = compile(Config, Ts),
+ [] = compile(Config, Ts),
ok.
-lc(doc) ->
- "Ordinary LC expression.";
-lc(suite) -> [];
+%% Ordinary LC expression.
lc(Config) when is_list(Config) ->
Ts =
[{lc,
@@ -258,12 +245,10 @@ lc(Config) when is_list(Config) ->
">>,
[],
{warnings,[{{2,30},erl_lint,{shadowed_var,'X',generate}}]}}],
- ?line [] = compile(Config, Ts),
+ [] = compile(Config, Ts),
ok.
-fun_clauses(doc) ->
- "Fun with several clauses.";
-fun_clauses(suite) -> [];
+%% Fun with several clauses.
fun_clauses(Config) when is_list(Config) ->
Ts =
[{fun_clauses,
@@ -279,12 +264,10 @@ fun_clauses(Config) when is_list(Config) ->
{{3,41},erl_lint,{shadowed_var,'X',generate}},
{{4,22},erl_lint,{shadowed_var,'X','fun'}},
{{4,41},erl_lint,{shadowed_var,'X',generate}}]}}],
- ?line [] = compile(Config, Ts),
+ [] = compile(Config, Ts),
ok.
-filter_var(doc) ->
- "Variable introduced in filter.";
-filter_var(suite) -> [];
+%% Variable introduced in filter.
filter_var(Config) when is_list(Config) ->
Ts =
[{filter_var,
@@ -309,13 +292,11 @@ filter_var(Config) when is_list(Config) ->
">>,
[],
{errors,[{{2,25},erl_lint,{unsafe_var,'V',{'case',{3,19}}}}],[]}}],
- ?line [] = compile(Config, Ts),
+ [] = compile(Config, Ts),
ok.
-single(doc) ->
- "Unused pattern variable.";
-single(suite) -> [];
+%% Unused pattern variable.
single(Config) when is_list(Config) ->
Ts =
[{single,
@@ -325,12 +306,10 @@ single(Config) when is_list(Config) ->
">>,
[warn_unused_vars],
{warnings,[{{2,30},erl_lint,{unused_var,'Y'}}]}}],
- ?line [] = compile(Config, Ts),
+ [] = compile(Config, Ts),
ok.
-exported_var(doc) ->
- "Exported variable in list expression (rhs of generator).";
-exported_var(suite) -> [];
+%% Exported variable in list expression (rhs of generator).
exported_var(Config) when is_list(Config) ->
Ts =
[{exported_var,
@@ -347,12 +326,10 @@ exported_var(Config) when is_list(Config) ->
[warn_export_vars],
{warnings,[{{7,37},erl_lint,{exported_var,'Z',{'case',{3,36}}}},
{{7,44},erl_lint,{exported_var,'Z',{'case',{3,36}}}}]}}],
- ?line [] = compile(Config, Ts),
+ [] = compile(Config, Ts),
ok.
-generator_vars(doc) ->
- "Errors for generator variable used in list expression.";
-generator_vars(suite) -> [];
+%% Errors for generator variable used in list expression.
generator_vars(Config) when is_list(Config) ->
Ts =
[{generator_vars,
@@ -374,12 +351,10 @@ generator_vars(Config) when is_list(Config) ->
{{9,33},?QLC,{used_generator_variable,'Z'}},
{{9,40},?QLC,{used_generator_variable,'Z'}}],
[]}}],
- ?line [] = compile(Config, Ts),
+ [] = compile(Config, Ts),
ok.
-nomatch(doc) ->
- "Unreachable clauses also found when compiling.";
-nomatch(suite) -> [];
+%% Unreachable clauses also found when compiling.
nomatch(Config) when is_list(Config) ->
Ts =
[{unreachable1,
@@ -451,13 +426,11 @@ nomatch(Config) when is_list(Config) ->
{warnings,[{3,v3_core,nomatch}]}}
],
- ?line [] = compile(Config, Ts),
+ [] = compile(Config, Ts),
ok.
-errors(doc) ->
- "Errors within qlc expressions also found when compiling.";
-errors(suite) -> [];
+%% Errors within qlc expressions also found when compiling.
errors(Config) when is_list(Config) ->
Ts =
[{errors1,
@@ -466,12 +439,10 @@ errors(Config) when is_list(Config) ->
">>,
[],
{errors,[{{2,33},erl_lint,{unbound_var,'A'}}],[]}}],
- ?line [] = compile(Config, Ts),
+ [] = compile(Config, Ts),
ok.
-pattern(doc) ->
- "Patterns.";
-pattern(suite) -> [];
+%% Patterns.
pattern(Config) when is_list(Config) ->
Ts = [
<<"%% Records in patterns. No lookup.
@@ -493,14 +464,12 @@ pattern(Config) when is_list(Config) ->
end, [{<<\"hej\">>}])">>
],
- ?line run(Config, <<"-record(a, {k,v}).
+ run(Config, <<"-record(a, {k,v}).
-record(k, {t,v}).\n">>, Ts),
ok.
-eval(doc) ->
- "eval/2";
-eval(suite) -> [];
+%% eval/2
eval(Config) when is_list(Config) ->
ScratchDir = filename:join([?privdir, "scratch","."]),
@@ -616,12 +585,10 @@ eval(Config) when is_list(Config) ->
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-cursor(doc) ->
- "cursor/2";
-cursor(suite) -> [];
+%% cursor/2
cursor(Config) when is_list(Config) ->
ScratchDir = filename:join([?privdir, "scratch","."]),
Ts = [<<"{'EXIT',{badarg,_}} =
@@ -730,12 +697,10 @@ cursor(Config) when is_list(Config) ->
ok = qlc:delete_cursor(C2)">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-fold(doc) ->
- "fold/4";
-fold(suite) -> [];
+%% fold/4
fold(Config) when is_list(Config) ->
ScratchDir = filename:join([?privdir, "scratch","."]),
Ts = [<<"Q = qlc:q([X || X <- [1,2,1,2,1]]),
@@ -825,12 +790,10 @@ fold(Config) when is_list(Config) ->
(catch qlc:fold(F, [], Q, [{unique_all,false}]))
">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-eval_unique(doc) ->
- "Test the unique_all option of eval.";
-eval_unique(suite) -> [];
+%% Test the unique_all option of eval.
eval_unique(Config) when is_list(Config) ->
Ts = [<<"QLC1 = qlc:q([X || X <- qlc:append([[1,1,2], [1,2,3,2,3]])]),
[1,2,3] = qlc:eval(QLC1, {unique_all,true}),
@@ -922,12 +885,10 @@ eval_unique(Config) when is_list(Config) ->
{sort,{sort,{list,_},[{unique,true}]},[]} = i(Q)">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-eval_cache(doc) ->
- "Test the cache_all and unique_all options of eval.";
-eval_cache(suite) -> [];
+%% Test the cache_all and unique_all options of eval.
eval_cache(Config) when is_list(Config) ->
Ts = [
<<"E = ets:new(apa, [ordered_set]),
@@ -1056,12 +1017,10 @@ eval_cache(Config) when is_list(Config) ->
[1] = qlc:e(H, unique_all)">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-append(doc) ->
- "Test the append function.";
-append(suite) -> [];
+%% Test the append function.
append(Config) when is_list(Config) ->
Ts = [<<"C = qlc:cursor(qlc:q([X || X <- [0,1,2,3], begin 10/X > 0.0 end])),
R = (catch qlc:next_answers(C)),
@@ -1121,12 +1080,12 @@ append(Config) when is_list(Config) ->
foo() -> bar">>,
%% Used to work up to R11B.
- % <<"apa = qlc:e(qlc:q([X || X <- qlc:append([[1,2,3], ugly()])])),
- % ok.
- %
- % ugly() ->
- % [a | apa].
- % foo() -> bar">>,
+ %% <<"apa = qlc:e(qlc:q([X || X <- qlc:append([[1,2,3], ugly()])])),
+ %% ok.
+ %%
+ %% ugly() ->
+ %% [a | apa].
+ %% foo() -> bar">>,
%% Maybe this one should fail.
@@ -1179,99 +1138,93 @@ append(Config) when is_list(Config) ->
[a,b,1,2,1,2] = qlc:e(Q)">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-evaluator(doc) ->
- "Simple call from evaluator.";
-evaluator(suite) -> [];
+%% Simple call from evaluator.
evaluator(Config) when is_list(Config) ->
- ?line true = is_alive(),
+ true = is_alive(),
evaluator_2(Config, []),
- ?line {ok, Node} = start_node(qlc_SUITE_evaluator),
- ?line ok = rpc:call(Node, ?MODULE, evaluator_2, [Config, [compiler]]),
- ?line ?t:stop_node(Node),
+ {ok, Node} = start_node(qlc_SUITE_evaluator),
+ ok = rpc:call(Node, ?MODULE, evaluator_2, [Config, [compiler]]),
+ test_server:stop_node(Node),
ok.
evaluator_2(Config, Apps) ->
- ?line lists:foreach(fun(App) -> true = code:del_path(App) end, Apps),
+ lists:foreach(fun(App) -> true = code:del_path(App) end, Apps),
FileName = filename:join(?privdir, "eval"),
- ?line ok = file:write_file(FileName,
+ ok = file:write_file(FileName,
<<"H = qlc:q([X || X <- L]),
[1,2,3] = qlc:e(H).">>),
- ?line Bs = erl_eval:add_binding('L', [1,2,3], erl_eval:new_bindings()),
- ?line ok = file:eval(FileName, Bs),
+ Bs = erl_eval:add_binding('L', [1,2,3], erl_eval:new_bindings()),
+ ok = file:eval(FileName, Bs),
%% The error message is "handled" a bit too much...
%% (no trace of erl_lint left)
- ?line ok = file:write_file(FileName,
+ ok = file:write_file(FileName,
<<"H = qlc:q([X || X <- L]), qlc:e(H).">>),
- ?line {error,_} = file:eval(FileName),
+ {error,_} = file:eval(FileName),
%% Ugly error message; badarg is caught by file.erl.
- ?line ok = file:write_file(FileName,
+ ok = file:write_file(FileName,
<<"H = qlc:q([Z || {X,Y} <- [{a,2}], Z <- [Y]]), qlc:e(H).">>),
- ?line {error,_} = file:eval(FileName),
+ {error,_} = file:eval(FileName),
_ = file:delete(FileName),
ok.
start_node(Name) ->
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?t:start_node(Name, slave, [{args, "-pa " ++ PA}]).
+ PA = filename:dirname(code:which(?MODULE)),
+ test_server:start_node(Name, slave, [{args, "-pa " ++ PA}]).
-string_to_handle(doc) ->
- "string_to_handle/1,2.";
-string_to_handle(suite) -> [];
+%% string_to_handle/1,2.
string_to_handle(Config) when is_list(Config) ->
- ?line {'EXIT',{badarg,_}} = (catch qlc:string_to_handle(14)),
- ?line {'EXIT',{badarg,_}} =
+ {'EXIT',{badarg,_}} = (catch qlc:string_to_handle(14)),
+ {'EXIT',{badarg,_}} =
(catch qlc:string_to_handle("[X || X <- [a].", unique_all)),
- ?line R1 = {error, _, {_,erl_scan,_}} = qlc:string_to_handle("'"),
- ?line "1: unterminated " ++ _ = lists:flatten(qlc:format_error(R1)),
- ?line {error, _, {_,erl_parse,_}} = qlc:string_to_handle("foo"),
- ?line {'EXIT',{badarg,_}} = (catch qlc:string_to_handle("foo, bar.")),
- ?line R3 = {error, _, {_,?QLC,not_a_query_list_comprehension}} =
+ R1 = {error, _, {_,erl_scan,_}} = qlc:string_to_handle("'"),
+ "1: unterminated " ++ _ = lists:flatten(qlc:format_error(R1)),
+ {error, _, {_,erl_parse,_}} = qlc:string_to_handle("foo"),
+ {'EXIT',{badarg,_}} = (catch qlc:string_to_handle("foo, bar.")),
+ R3 = {error, _, {_,?QLC,not_a_query_list_comprehension}} =
qlc:string_to_handle("bad."),
- ?line "1: argument is not" ++ _ = lists:flatten(qlc:format_error(R3)),
- ?line R4 = {error, _, {_,?QLC,{used_generator_variable,'Y'}}} =
+ "1: argument is not" ++ _ = lists:flatten(qlc:format_error(R3)),
+ R4 = {error, _, {_,?QLC,{used_generator_variable,'Y'}}} =
qlc:string_to_handle("[X || begin Y = [1,2], true end, X <- Y]."),
- ?line "1: generated variable 'Y'" ++ _ =
+ "1: generated variable 'Y'" ++ _ =
lists:flatten(qlc:format_error(R4)),
- ?line {error, _, {_,erl_lint,_}} = qlc:string_to_handle("[X || X <- A]."),
- ?line H1 = qlc:string_to_handle("[X || X <- [1,2]]."),
- ?line [1,2] = qlc:e(H1),
- ?line H2 = qlc:string_to_handle("[X || X <- qlc:append([a,b],"
+ {error, _, {_,erl_lint,_}} = qlc:string_to_handle("[X || X <- A]."),
+ H1 = qlc:string_to_handle("[X || X <- [1,2]]."),
+ [1,2] = qlc:e(H1),
+ H2 = qlc:string_to_handle("[X || X <- qlc:append([a,b],"
"qlc:e(qlc:q([X || X <- [c,d,e]])))]."),
- ?line [a,b,c,d,e] = qlc:e(H2),
+ [a,b,c,d,e] = qlc:e(H2),
%% The generated fun has many arguments (erl_eval has a maximum of 20).
- ?line H3 = qlc:string_to_handle(
+ H3 = qlc:string_to_handle(
"[{A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W} ||"
" {A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W} <- []]."),
- ?line [] = qlc:e(H3),
- ?line Bs1 = erl_eval:add_binding('L', [1,2,3], erl_eval:new_bindings()),
- ?line H4 = qlc:string_to_handle("[X || X <- L].", [], Bs1),
- ?line [1,2,3] = qlc:e(H4),
- ?line H5 = qlc:string_to_handle("[X || X <- [1,2,1,2]].", [unique, cache]),
- ?line [1,2] = qlc:e(H5),
-
- ?line Ets = ets:new(test, []),
- ?line true = ets:insert(Ets, [{1}]),
- ?line Bs2 = erl_eval:add_binding('E', Ets, erl_eval:new_bindings()),
- ?line Q = "[X || {X} <- ets:table(E)].",
- ?line [1] = qlc:e(qlc:string_to_handle(Q, [], Bs2)),
- ?line [1] = qlc:e(qlc:string_to_handle(Q, {max_lookup,1000}, Bs2)),
- ?line [1] = qlc:e(qlc:string_to_handle(Q, {max_lookup,infinity}, Bs2)),
- ?line {'EXIT',{badarg,_}} =
+ [] = qlc:e(H3),
+ Bs1 = erl_eval:add_binding('L', [1,2,3], erl_eval:new_bindings()),
+ H4 = qlc:string_to_handle("[X || X <- L].", [], Bs1),
+ [1,2,3] = qlc:e(H4),
+ H5 = qlc:string_to_handle("[X || X <- [1,2,1,2]].", [unique, cache]),
+ [1,2] = qlc:e(H5),
+
+ Ets = ets:new(test, []),
+ true = ets:insert(Ets, [{1}]),
+ Bs2 = erl_eval:add_binding('E', Ets, erl_eval:new_bindings()),
+ Q = "[X || {X} <- ets:table(E)].",
+ [1] = qlc:e(qlc:string_to_handle(Q, [], Bs2)),
+ [1] = qlc:e(qlc:string_to_handle(Q, {max_lookup,1000}, Bs2)),
+ [1] = qlc:e(qlc:string_to_handle(Q, {max_lookup,infinity}, Bs2)),
+ {'EXIT',{badarg,_}} =
(catch qlc:string_to_handle(Q, {max_lookup,-1}, Bs2)),
- ?line {'EXIT', {no_lookup_to_carry_out, _}} =
+ {'EXIT', {no_lookup_to_carry_out, _}} =
(catch qlc:e(qlc:string_to_handle(Q, {lookup,true}, Bs2))),
- ?line ets:delete(Ets),
+ ets:delete(Ets),
ok.
-table(doc) ->
- "table";
-table(suite) -> [];
+%% table
table(Config) when is_list(Config) ->
dets:start(),
Ts = [
@@ -1353,11 +1306,11 @@ table(Config) when is_list(Config) ->
ets:delete(E)">>,
%% The info tag num_of_objects is currently not used.
-% <<"E = ets:new(test, [ordered_set]),
-% true = ets:insert(E, [{1,a},{2,b},{3,c}]),
-% H = qlc:q([X || X <- qlc_SUITE:bad_table_info_fun_n_objects(E)]),
-% {'EXIT', finito} = (catch {any_term,qlc:e(H)}),
-% ets:delete(E)">>,
+%% <<"E = ets:new(test, [ordered_set]),
+%% true = ets:insert(E, [{1,a},{2,b},{3,c}]),
+%% H = qlc:q([X || X <- qlc_SUITE:bad_table_info_fun_n_objects(E)]),
+%% {'EXIT', finito} = (catch {any_term,qlc:e(H)}),
+%% ets:delete(E)">>,
<<"E = ets:new(test, [ordered_set]),
true = ets:insert(E, [{1,a},{2,b},{3,c}]),
@@ -1473,7 +1426,7 @@ table(Config) when is_list(Config) ->
[1,2] = lookup_keys(Q)
end, [{1,1},{2,2}])">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
Ts2 = [
%% [T || P <- Table, F] turned into a match spec. Records needed.
@@ -1484,13 +1437,11 @@ table(Config) when is_list(Config) ->
[{a,1,2},{a,3,4}] = lists:sort(qlc:eval(QH)),
ets:delete(E)">>
],
- ?line run(Config, <<"-record(a, {b,c}).\n">>, Ts2),
+ run(Config, <<"-record(a, {b,c}).\n">>, Ts2),
ok.
-process_dies(doc) ->
- "Caller or cursor process dies.";
-process_dies(suite) -> [];
+%% Caller or cursor process dies.
process_dies(Config) when is_list(Config) ->
Ts = [
<<"E = ets:new(test, []),
@@ -1629,12 +1580,10 @@ process_dies(Config) when is_list(Config) ->
true = ets:delete(E), ok">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-sort(doc) ->
- "The sort option.";
-sort(suite) -> [];
+%% The sort option.
sort(Config) when is_list(Config) ->
Ts = [
<<"H = qlc:q([X || X <- qlc:sort([1,2,3,2], {unique,true})]),
@@ -1741,12 +1690,10 @@ sort(Config) when is_list(Config) ->
end
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-keysort(doc) ->
- "The sort option.";
-keysort(suite) -> [];
+%% The sort option.
keysort(Config) when is_list(Config) ->
Ts = [
@@ -1865,13 +1812,11 @@ keysort(Config) when is_list(Config) ->
100003 = length(R)">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-filesort(doc) ->
- "keysort/1,2, using a file.";
-filesort(suite) -> [];
+%% keysort/1,2, using a file.
filesort(Config) when is_list(Config) ->
Ts = [
<<"Q = qlc:q([X || X <- [{3},{1},{2}]]),
@@ -1879,13 +1824,11 @@ filesort(Config) when is_list(Config) ->
Q2 = qlc:q([{X,Y} || Y <- [1,2], X <- qlc:keysort([1],Q,Opts)]),
[{{1},1},{{2},1},{{3},1},{{1},2},{{2},2},{{3},2}] = qlc:e(Q2)">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-cache(doc) ->
- "The cache option.";
-cache(suite) -> [];
+%% The cache option.
cache(Config) when is_list(Config) ->
Ts = [
<<"{'EXIT', {badarg, _}} = (catch qlc:q([X || X <- [1,2]], badarg))">>,
@@ -2043,12 +1986,10 @@ cache(Config) when is_list(Config) ->
[]} = i(H, cache_all)">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-cache_list(doc) ->
- "OTP-6038. The {cache,list} option.";
-cache_list(suite) -> [];
+%% OTP-6038. The {cache,list} option.
cache_list(Config) when is_list(Config) ->
Ts = [
begin
@@ -2334,12 +2275,10 @@ cache_list(Config) when is_list(Config) ->
{'EXIT', {badarg, _}} = (catch qlc:e(Q, {max_list_size, foo}))">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-filter(doc) ->
- "Filters and match specs.";
-filter(suite) -> [];
+%% Filters and match specs.
filter(Config) when is_list(Config) ->
Ts = [
<<"L = [1,2,3,4,5],
@@ -2461,12 +2400,10 @@ filter(Config) when is_list(Config) ->
[{2,b},{2,c},{3,b},{3,c}] = qlc:e(H)">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-info(doc) ->
- "info/2.";
-info(suite) -> [];
+%% info/2.
info(Config) when is_list(Config) ->
Ts = [
<<"{list, [1,2]} = i(qlc:q([X || X <- [1,2]])),
@@ -2686,12 +2623,10 @@ info(Config) when is_list(Config) ->
[{4},{5},{6}] = qlc:e(F(3))">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-nested_info(doc) ->
- "Nested QLC expressions. QLC expressions in filter and template.";
-nested_info(suite) -> [];
+%% Nested QLC expressions. QLC expressions in filter and template.
nested_info(Config) when is_list(Config) ->
Ts = [
<<"L = [{1,a},{2,b},{3,c}],
@@ -2792,13 +2727,11 @@ nested_info(Config) when is_list(Config) ->
[{1,1},{1,1},{1,2},{1,2},{2,1},{2,1},{2,2},{2,2}] = qlc:e(Q)">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-lookup1(doc) ->
- "Lookup keys. Mostly test of patterns.";
-lookup1(suite) -> [];
+%% Lookup keys. Mostly test of patterns.
lookup1(Config) when is_list(Config) ->
Ts = [
<<"etsc(fun(E) ->
@@ -3003,12 +2936,10 @@ lookup1(Config) when is_list(Config) ->
[]}
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-lookup2(doc) ->
- "Lookup keys. Mostly test of filters.";
-lookup2(suite) -> [];
+%% Lookup keys. Mostly test of filters.
lookup2(Config) when is_list(Config) ->
Ts = [
<<"%% Only guards are inspected. No lookup.
@@ -3708,9 +3639,7 @@ lookup2(Config) when is_list(Config) ->
ok.
-lookup_rec(doc) ->
- "Lookup keys. With records.";
-lookup_rec(suite) -> [];
+%% Lookup keys. With records.
lookup_rec(Config) when is_list(Config) ->
Ts = [
<<"etsc(fun(E) ->
@@ -3778,12 +3707,10 @@ lookup_rec(Config) when is_list(Config) ->
[_] = lookup_keys(Q)
end, [{keypos,2}], [#r{a=foo}])">>
],
- ?line run(Config, <<"-record(r, {a}).\n">>, Ts),
+ run(Config, <<"-record(r, {a}).\n">>, Ts),
ok.
-indices(doc) ->
- "Using indices for lookup.";
-indices(suite) -> [];
+%% Using indices for lookup.
indices(Config) when is_list(Config) ->
Ts = [
<<"L = [{1,a},{2,b},{3,c}],
@@ -3845,12 +3772,10 @@ indices(Config) when is_list(Config) ->
[{c,3,z,w}] = qlc:eval(QH)">>
],
- ?line run(Config, <<"-record(r, {a}).\n">>, Ts),
+ run(Config, <<"-record(r, {a}).\n">>, Ts),
ok.
-pre_fun(doc) ->
- "Test the table/2 callback functions parent_fun and stop_fun.";
-pre_fun(suite) -> [];
+%% Test the table/2 callback functions parent_fun and stop_fun.
pre_fun(Config) when is_list(Config) ->
Ts = [
<<"PF = process_flag(trap_exit, true),
@@ -3926,12 +3851,10 @@ pre_fun(Config) when is_list(Config) ->
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-skip_filters(doc) ->
- "Lookup keys. With records.";
-skip_filters(suite) -> [];
+%% Lookup keys. With records.
skip_filters(Config) when is_list(Config) ->
%% Skipped filters
TsS = [
@@ -4051,7 +3974,7 @@ skip_filters(Config) when is_list(Config) ->
end, [{0},{1},{2},{3},{4}])">>
],
- ?line run(Config, TsS),
+ run(Config, TsS),
Ts = [
<<"etsc(fun(E) ->
@@ -4329,14 +4252,12 @@ skip_filters(Config) when is_list(Config) ->
end, [{1},{2},{3}])">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-ets(doc) ->
- "ets:table/1,2.";
-ets(suite) -> [];
+%% ets:table/1,2.
ets(Config) when is_list(Config) ->
Ts = [
<<"E = ets:new(t, [ordered_set]),
@@ -4377,12 +4298,10 @@ ets(Config) when is_list(Config) ->
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-dets(doc) ->
- "dets:table/1,2.";
-dets(suite) -> [];
+%% dets:table/1,2.
dets(Config) when is_list(Config) ->
dets:start(),
T = t,
@@ -4475,14 +4394,12 @@ dets(Config) when is_list(Config) ->
],
- ?line run(Config, Ts),
+ run(Config, Ts),
_ = file:delete(Fname),
ok.
-join_option(doc) ->
- "The 'join' option (any, lookup, merge, nested_loop). Also cache/unique.";
-join_option(suite) -> [];
+%% The 'join' option (any, lookup, merge, nested_loop). Also cache/unique.
join_option(Config) when is_list(Config) ->
Ts = [
<<"Q1 = qlc:q([X || X <- [1,2,3]],{join,merge}),
@@ -4607,7 +4524,7 @@ join_option(Config) when is_list(Config) ->
ets:delete(E1)">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
%% The 'cache' and 'unique' options of qlc/2 affects join.
CUTs = [
@@ -4655,13 +4572,11 @@ join_option(Config) when is_list(Config) ->
_],[{unique,true}]} = i(Q, Options),
[{1,1,1},{2,2,1},{1,1,2},{2,2,2}] = qlc:e(Q, Options)">>
],
- ?line run(Config, CUTs),
+ run(Config, CUTs),
ok.
-join_filter(doc) ->
- "Various aspects of filters and join.";
-join_filter(suite) -> [];
+%% Various aspects of filters and join.
join_filter(Config) when is_list(Config) ->
Ts = [
<<"E1 = create_ets(1, 10),
@@ -4698,12 +4613,10 @@ join_filter(Config) when is_list(Config) ->
end, [{a},{b},{c}])">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-join_lookup(doc) ->
- "Lookup join.";
-join_lookup(suite) -> [];
+%% Lookup join.
join_lookup(Config) when is_list(Config) ->
Ts = [
<<"E1 = create_ets(1, 10),
@@ -4793,12 +4706,10 @@ join_lookup(Config) when is_list(Config) ->
ets:delete(E)">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-join_merge(doc) ->
- "Merge join.";
-join_merge(suite) -> [];
+%% Merge join.
join_merge(Config) when is_list(Config) ->
Ts = [
<<"Q = qlc:q([{X,Y} || {X} <- [], {Y} <- [{1}], X =:= Y],
@@ -5070,7 +4981,7 @@ join_merge(Config) when is_list(Config) ->
[{2,a}] = qlc:e(Q)">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
%% Small examples. Returning an error term.
ETs = [
@@ -5249,7 +5160,7 @@ join_merge(Config) when is_list(Config) ->
err = qlc:e(Q)">>
],
- ?line run(Config, ETs),
+ run(Config, ETs),
%% Mostly examples where temporary files are needed while merging.
FTs = [
@@ -5408,13 +5319,11 @@ join_merge(Config) when is_list(Config) ->
],
- ?line run(Config, FTs),
+ run(Config, FTs),
ok.
-join_sort(doc) ->
- "Merge join optimizations (avoid unnecessary sorting).";
-join_sort(suite) -> [];
+%% Merge join optimizations (avoid unnecessary sorting).
join_sort(Config) when is_list(Config) ->
Ts = [
<<"H1_1 = qlc:keysort(1, [{1,2,3},{4,5,6}]),
@@ -5694,12 +5603,10 @@ join_sort(Config) when is_list(Config) ->
end, [{1,2},{3,4}])">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-join_complex(doc) ->
- "Join of more than two columns.";
-join_complex(suite) -> [];
+%% Join of more than two columns.
join_complex(Config) when is_list(Config) ->
Ts = [{three,
<<"three() ->
@@ -5727,7 +5634,7 @@ join_complex(Config) when is_list(Config) ->
{warnings,[{2,qlc,too_many_joins}]}}
],
- ?line compile(Config, Ts),
+ compile(Config, Ts),
Ts2 = [{three,
<<"three() ->
@@ -5756,14 +5663,12 @@ join_complex(Config) when is_list(Config) ->
{[],["cannot handle more than one join efficiently"]}}
],
- ?line compile_format(Config, Ts2),
+ compile_format(Config, Ts2),
ok.
-otp_5644(doc) ->
- "OTP-5644. Handle the new language element M:F/A.";
-otp_5644(suite) -> [];
+%% OTP-5644. Handle the new language element M:F/A.
otp_5644(Config) when is_list(Config) ->
Ts = [
<<"Q = qlc:q([fun modul:mfa/0 || _ <- [1,2],
@@ -5771,12 +5676,10 @@ otp_5644(Config) when is_list(Config) ->
[_,_] = qlc:eval(Q)">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-otp_5195(doc) ->
- "OTP-5195. Allow traverse functions returning terms.";
-otp_5195(suite) -> [];
+%% OTP-5195. Allow traverse functions returning terms.
otp_5195(Config) when is_list(Config) ->
%% Several minor improvements have been implemented in OTP-5195.
%% The test cases are spread all over... except these.
@@ -5854,7 +5757,7 @@ otp_5195(Config) when is_list(Config) ->
],
- ?line run(Config, Ts),
+ run(Config, Ts),
Ts2 = [<<"Q = qlc:q([{X,Y} || {X} <- [{1},{2},{3}],
begin
@@ -5863,13 +5766,11 @@ otp_5195(Config) when is_list(Config) ->
end,
X =:= Y]),
[{3,3}] = qlc:e(Q)">>],
- ?line run(Config, Ts2),
+ run(Config, Ts2),
ok.
-otp_6038_bug(doc) ->
- "OTP-6038. Bug fixes: unique and keysort; cache.";
-otp_6038_bug(suite) -> [];
+%% OTP-6038. Bug fixes: unique and keysort; cache.
otp_6038_bug(Config) when is_list(Config) ->
%% The 'unique' option can no longer be merged with the keysort options.
%% This used to return [{1,a},{1,c},{2,b},{2,d}], but since
@@ -5879,7 +5780,7 @@ otp_6038_bug(Config) when is_list(Config) ->
H2 = qlc:keysort(1, H1, [{unique,true}]),
[{1,a},{2,b}] = qlc:e(H2)">>],
- ?line run(Config, Ts),
+ run(Config, Ts),
%% Sometimes the cache options did not empty the correct tables.
CTs = [
@@ -5908,13 +5809,11 @@ otp_6038_bug(Config) when is_list(Config) ->
L = [{X,Y} || X <- [1,2], Y <- L4],
true = R =:= L">>
],
- ?line run(Config, CTs),
+ run(Config, CTs),
ok.
-otp_6359(doc) ->
- "OTP-6359. dets:select() never returns the empty list.";
-otp_6359(suite) -> [];
+%% OTP-6359. dets:select() never returns the empty list.
otp_6359(Config) when is_list(Config) ->
dets:start(),
T = luna,
@@ -5933,12 +5832,10 @@ otp_6359(Config) when is_list(Config) ->
ok">>]
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
-otp_6562(doc) ->
- "OTP-6562. compressed = false (should be []) when sorting before join.";
-otp_6562(suite) -> [];
+%% OTP-6562. compressed = false (should be []) when sorting before join.
otp_6562(Config) when is_list(Config) ->
Bug = [
%% This example uses a file to sort E2 on the second column. It is
@@ -5957,7 +5854,7 @@ otp_6562(Config) when is_list(Config) ->
ets:delete(E1),
ets:delete(E2)">>
],
- ?line run(Config, Bug),
+ run(Config, Bug),
Bits = [
{otp_6562_1,
@@ -5969,18 +5866,16 @@ otp_6562(Config) when is_list(Config) ->
{errors,[{2,qlc,binary_generator}],
[]}}
],
- ?line [] = compile(Config, Bits),
+ [] = compile(Config, Bits),
- ?line R1 = {error,qlc,{1,qlc,binary_generator}}
+ R1 = {error,qlc,{1,qlc,binary_generator}}
= qlc:string_to_handle("[X || <<X:8>> <= <<\"hej\">>]."),
- ?line "1: cannot handle binary generators\n" =
+ "1: cannot handle binary generators\n" =
lists:flatten(qlc:format_error(R1)),
ok.
-otp_6590(doc) ->
- "OTP-6590. Bug fix (join info).";
-otp_6590(suite) -> [];
+%% OTP-6590. Bug fix (join info).
otp_6590(Config) when is_list(Config) ->
Ts = [<<"fun(Tab1Value) ->
Q = qlc:q([T1#tab1.id || T1 <- [#tab1{id = id1,
@@ -5992,13 +5887,11 @@ otp_6590(Config) when is_list(Config) ->
[id1] = qlc:e(Q)
end(v)">>],
- ?line run(Config, <<"-record(tab1, {id, tab2_id, value}).
+ run(Config, <<"-record(tab1, {id, tab2_id, value}).
-record(tab2, {id, value}).\n">>, Ts),
ok.
-otp_6673(doc) ->
- "OTP-6673. Optimizations and fixes.";
-otp_6673(suite) -> [];
+%% OTP-6673. Optimizations and fixes.
otp_6673(Config) when is_list(Config) ->
Ts_PT =
[<<"etsc(fun(E1) ->
@@ -6054,7 +5947,7 @@ otp_6673(Config) when is_list(Config) ->
end,
[{1,x},{2,y},{3,z}])">>],
- ?line run(Config, Ts_PT),
+ run(Config, Ts_PT),
MS = ets:fun2ms(fun({X,_Y}=T) when X > 1 -> T end),
Ts_RT = [
@@ -6091,13 +5984,11 @@ otp_6673(Config) when is_list(Config) ->
end, [{x,1},{y,2},{z,3}])">>
],
- ?line run(Config, Ts_RT),
+ run(Config, Ts_RT),
ok.
-otp_6964(doc) ->
- "OTP-6964. New option 'tmpdir_usage'.";
-otp_6964(suite) -> [];
+%% OTP-6964. New option 'tmpdir_usage'.
otp_6964(Config) when is_list(Config) ->
T1 = [
<<"Q1 = qlc:q([{X} || X <- [1,2]]),
@@ -6131,7 +6022,7 @@ otp_6964(Config) when is_list(Config) ->
_ = erlang:system_flag(backtrace_depth, D)
end,
qlc_SUITE:uninstall_error_logger()">>],
- ?line run(Config, T1),
+ run(Config, T1),
T2 = [
<<"%% File sorter.
@@ -6164,7 +6055,7 @@ otp_6964(Config) when is_list(Config) ->
{info, caching} = qlc_SUITE:read_error_logger(),
qlc_SUITE:uninstall_error_logger()">>],
- ?line run(Config, T2),
+ run(Config, T2),
T3 = [
<<"%% sort/keysort
@@ -6194,7 +6085,7 @@ otp_6964(Config) when is_list(Config) ->
qlc_SUITE:uninstall_error_logger(),
ets:delete(E1),
ets:delete(E2)">>],
- ?line run(Config, T3),
+ run(Config, T3),
T4 = [
<<"%% cache list
@@ -6225,18 +6116,16 @@ otp_6964(Config) when is_list(Config) ->
lists:flatten(qlc:format_error(ErrReply))
end, [{keypos,1}], [{I,a,lists:duplicate(100000,1)} ||
I <- lists:seq(1, 10)])">>],
- ?line run(Config, T4),
+ run(Config, T4),
ok.
-otp_7238(doc) ->
- "OTP-7238. info-option 'depth', &c.";
-otp_7238(suite) -> [];
+%% OTP-7238. info-option 'depth', &c.
otp_7238(Config) when is_list(Config) ->
dets:start(),
T = otp_7238,
Fname = filename(T, Config),
- ?line ok = compile_gb_table(Config),
+ ok = compile_gb_table(Config),
%% A few more warnings.
T1 = [
@@ -6365,7 +6254,7 @@ otp_7238(Config) when is_list(Config) ->
[],
{warnings,[{2,sys_core_fold,no_clause_match}]}}
],
- ?line [] = compile(Config, T1),
+ [] = compile(Config, T1),
%% 'depth' is a new option used by info()
T2 = [
@@ -6591,7 +6480,7 @@ otp_7238(Config) when is_list(Config) ->
qlc:info(Q, [{format,abstract_code},{depth, 2}])">>
],
- ?line run(Config, T2),
+ run(Config, T2),
T3 = [
%% {nomatch_6,
@@ -6607,7 +6496,7 @@ otp_7238(Config) when is_list(Config) ->
%% [],
%% {[],["pattern cannot possibly match"]}}
],
- ?line compile_format(Config, T3),
+ compile_format(Config, T3),
%% *Very* simple test - just check that it doesn't crash.
Type = [{cres,
@@ -6615,13 +6504,11 @@ otp_7238(Config) when is_list(Config) ->
{'EXIT',{{badfun,_},_}} = (catch qlc:e(Q))">>,
[type_checker],
[]}],
- ?line run(Config, Type),
+ run(Config, Type),
ok.
-otp_7114(doc) ->
- "OTP-7114. Match spec, table and duplicated objects..";
-otp_7114(suite) -> [];
+%% OTP-7114. Match spec, table and duplicated objects...
otp_7114(Config) when is_list(Config) ->
Ts = [<<"T = ets:new(t, [bag]),
[ets:insert(T, {t, I, I div 2}) || I <- lists:seq(1,10)],
@@ -6632,11 +6519,9 @@ otp_7114(Config) when is_list(Config) ->
[0,1,2,3,4,5] = qlc:e(qlc:sort(qlc:e(Q1)), unique_all),
ets:delete(T),
ok">>],
- ?line run(Config, Ts).
+ run(Config, Ts).
-otp_7232(doc) ->
- "OTP-7232. qlc:info() bug (pids, ports, refs, funs).";
-otp_7232(suite) -> [];
+%% OTP-7232. qlc:info() bug (pids, ports, refs, funs).
otp_7232(Config) when is_list(Config) ->
Ts = [<<"L = [fun math:sqrt/1, list_to_pid(\"<0.4.1>\"),
erlang:make_ref()],
@@ -6664,11 +6549,9 @@ otp_7232(Config) when is_list(Config) ->
\"[<<8,1:1>>]\" = qlc:info(Q)">>
],
- ?line run(Config, Ts).
+ run(Config, Ts).
-otp_7552(doc) ->
- "OTP-7552. Merge join bug.";
-otp_7552(suite) -> [];
+%% OTP-7552. Merge join bug.
otp_7552(Config) when is_list(Config) ->
%% The poor performance cannot be observed unless the
%% (redundant) join filter is skipped.
@@ -6691,11 +6574,9 @@ otp_7552(Config) when is_list(Config) ->
Qn = F(nested_loop),
true = lists:sort(qlc:e(Qm, {max_list_size,20})) =:=
lists:sort(qlc:e(Qn))">>],
- ?line run(Config, Ts).
+ run(Config, Ts).
-otp_7714(doc) ->
- "OTP-7714. Merge join bug.";
-otp_7714(suite) -> [];
+%% OTP-7714. Merge join bug.
otp_7714(Config) when is_list(Config) ->
%% The original example uses Mnesia. This one does not.
Ts = [<<"E1 = ets:new(set,[]),
@@ -6710,11 +6591,9 @@ otp_7714(Config) when is_list(Config) ->
[{a,1},{a,2},{a,3}] = lists:sort(qlc:e(Q)),
ets:delete(E1),
ets:delete(E2)">>],
- ?line run(Config, Ts).
+ run(Config, Ts).
-otp_11758(doc) ->
- "OTP-11758. Bug.";
-otp_11758(suite) -> [];
+%% OTP-11758. Bug.
otp_11758(Config) when is_list(Config) ->
Ts = [<<"T = ets:new(r, [{keypos, 2}]),
L = [{rrr, xxx, aaa}, {rrr, yyy, bbb}],
@@ -6725,12 +6604,10 @@ otp_11758(Config) when is_list(Config) ->
ets:delete(T)">>],
run(Config, Ts).
-otp_6674(doc) ->
- "OTP-6674. match/comparison.";
-otp_6674(suite) -> [];
+%% OTP-6674. match/comparison.
otp_6674(Config) when is_list(Config) ->
- ?line ok = compile_gb_table(Config),
+ ok = compile_gb_table(Config),
Ts = [%% lookup join
<<"E = ets:new(join, [ordered_set]),
@@ -7153,11 +7030,9 @@ otp_6674(Config) when is_list(Config) ->
],
- ?line run(Config, Ts).
+ run(Config, Ts).
-otp_12946(doc) ->
- ["Syntax error."];
-otp_12946(suite) -> [];
+%% Syntax error.
otp_12946(Config) when is_list(Config) ->
Text =
<<"-export([init/0]).
@@ -7167,12 +7042,10 @@ otp_12946(Config) when is_list(Config) ->
{errors,[{4,erl_parse,_}],[]} = compile_file(Config, Text, []),
ok.
-manpage(doc) ->
- "Examples from qlc(3).";
-manpage(suite) -> [];
+%% Examples from qlc(3).
manpage(Config) when is_list(Config) ->
- ?line ok = compile_gb_table(Config),
+ ok = compile_gb_table(Config),
Ts = [
<<"QH = qlc:q([{X,Y} || X <- [a,b], Y <- [1,2]]),
@@ -7327,7 +7200,7 @@ manpage(Config) when is_list(Config) ->
ets:match_spec_compile([{{{'$1','$2'},'_'},[],['$1']}]))\",
L = qlc:info(QH)">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
L = [1,2,3],
Bs = erl_eval:add_binding('L', L, erl_eval:new_bindings()),
@@ -7345,7 +7218,7 @@ manpage(Config) when is_list(Config) ->
true = qlc:info(QH1) =:= qlc:info(QH2),
true = ets:delete(Tab)">>]],
- ?line run(Config, ETs),
+ run(Config, ETs),
%% dets(3)
DTs = [
@@ -7358,16 +7231,16 @@ manpage(Config) when is_list(Config) ->
true = qlc:info(QH1) =:= qlc:info(QH2),
ok = dets:close(T)">>]],
- ?line run(Config, DTs),
+ run(Config, DTs),
ok.
compile_gb_table(Config) ->
GB_table_file = filename("gb_table.erl", Config),
- ?line ok = file:write_file(GB_table_file, gb_table()),
- ?line {ok, gb_table} = compile:file(GB_table_file, [{outdir,?privdir}]),
- ?line code:purge(gb_table),
- ?line {module, gb_table} =
+ ok = file:write_file(GB_table_file, gb_table()),
+ {ok, gb_table} = compile:file(GB_table_file, [{outdir,?privdir}]),
+ code:purge(gb_table),
+ {module, gb_table} =
code:load_abs(filename:rootname(GB_table_file)),
ok.
@@ -7433,9 +7306,7 @@ gb_iter(I0, N, EFun) ->
">>.
-backward(doc) ->
- "OTP-6674. Join info and extra constants.";
-backward(suite) -> [];
+%% OTP-6674. Join info and extra constants.
backward(Config) when is_list(Config) ->
try_old_join_info(Config),
ok.
@@ -7470,9 +7341,6 @@ try_old_join_info(Config) ->
qlc:info(H2, {format,debug}),
[{1,1},{2,2}] = qlc:e(H2).
-forward(doc) ->
- "";
-forward(suite) -> [];
forward(Config) when is_list(Config) ->
Ts = [
%% LC_fun() returns something unknown.
@@ -7481,12 +7349,12 @@ forward(Config) when is_list(Config) ->
{'EXIT', {{unsupported_qlc_handle,_},_}} = (catch qlc:e(FakeH))">>,
%% 'f1' should be used for new stuff that does not interfer with old behavior
-% %% The unused element 'f1' of #qlc_table seems to be used.
-% <<"DF = fun() -> foo end,
-% FakeH = {qlc_handle,{qlc_table,DF,
-% true,DF,DF,DF,DF,DF,
-% undefined,not_undefined,undefined,no_match_spec}},
-% {'EXIT', {{unsupported_qlc_handle,_},_}} = (catch qlc:e(FakeH))">>,
+%% %% The unused element 'f1' of #qlc_table seems to be used.
+%% <<"DF = fun() -> foo end,
+%% FakeH = {qlc_handle,{qlc_table,DF,
+%% true,DF,DF,DF,DF,DF,
+%% undefined,not_undefined,undefined,no_match_spec}},
+%% {'EXIT', {{unsupported_qlc_handle,_},_}} = (catch qlc:e(FakeH))">>,
%% #qlc_opt has changed.
<<"H = qlc:q([X || X <- []]),
@@ -7495,7 +7363,7 @@ forward(Config) when is_list(Config) ->
{'EXIT', {{unsupported_qlc_handle,_},_}} = (catch qlc:e(FakeH))">>
],
- ?line run(Config, Ts),
+ run(Config, Ts),
ok.
eep37(Config) when is_list(Config) ->
@@ -7955,7 +7823,7 @@ run_test(Config, Extra, {cres, Body, Opts, ExpectedCompileReturn}) ->
R = case catch Mod:function() of
{'EXIT', _Reason} = Error ->
- ?t:format("failed, got ~p~n", [Error]),
+ io:format("failed, got ~p~n", [Error]),
fail(SourceFile);
Reply ->
Reply
@@ -7966,7 +7834,7 @@ run_test(Config, Extra, {cres, Body, Opts, ExpectedCompileReturn}) ->
{file, cover_compiled} ->
ok;
{file, _} ->
- ?t:format("qlc_pt was loaded in runtime~n", []),
+ io:format("qlc_pt was loaded in runtime~n", []),
fail(SourceFile);
false ->
ok
@@ -8167,16 +8035,15 @@ warnings(File, Ws) ->
end.
expected(Test, Expected, Got, File) ->
- ?t:format("~nTest ~p failed. ", [Test]),
+ io:format("~nTest ~p failed. ", [Test]),
expected(Expected, Got, File).
expected(Expected, Got, File) ->
- ?t:format("Expected~n ~p~n, but got~n ~p~n", [Expected, Got]),
+ io:format("Expected~n ~p~n, but got~n ~p~n", [Expected, Got]),
fail(File).
fail(Source) ->
- io:format("failed~n"),
- ?t:fail({failed,testcase,on,Source}).
+ ct:fail({failed,testcase,on,Source}).
%% Copied from global_SUITE.erl.
@@ -8197,8 +8064,8 @@ read_error_logger() ->
{error, Pid, Tuple} ->
{error, Pid, Tuple}
after 1000 ->
- ?line io:format("No reply after 1 s\n", []),
- ?line ?t:fail()
+ io:format("No reply after 1 s\n", []),
+ ct:fail(failed)
end.
%%-----------------------------------------------------------------
diff --git a/lib/stdlib/test/queue_SUITE.erl b/lib/stdlib/test/queue_SUITE.erl
index c965a8b218..cd3f8e6e2f 100644
--- a/lib/stdlib/test/queue_SUITE.erl
+++ b/lib/stdlib/test/queue_SUITE.erl
@@ -19,26 +19,23 @@
%%
-module(queue_SUITE).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2,
init_per_group/2,end_per_group/2]).
-export([do/1, to_list/1, io_test/1, op_test/1, error/1, oops/1]).
--export([init_per_testcase/2, end_per_testcase/2]).
--include_lib("test_server/include/test_server.hrl").
-
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
+-include_lib("common_test/include/ct.hrl").
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+ Config.
+
+end_per_testcase(_Case, _Config) ->
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[do, to_list, io_test, op_test, error, oops].
@@ -59,47 +56,40 @@ end_per_group(_GroupName, Config) ->
Config.
-do(doc) ->
- [""];
-do(suite) ->
- [];
do(Config) when is_list(Config) ->
- ?line L = [{in, 1},
- {in, 2},
- {out, {value, 1}},
- {in, 3},
- {out, {value, 2}},
- {out, {value, 3}},
- {out, empty}
- ],
-
- ?line E = queue:new(),
- ?line [] = queue:to_list(E),
- ?line Q = do_queue(E, L),
- ?line true = queue:is_empty(Q),
- ?line 0 = queue:len(Q),
+ L = [{in, 1},
+ {in, 2},
+ {out, {value, 1}},
+ {in, 3},
+ {out, {value, 2}},
+ {out, {value, 3}},
+ {out, empty}
+ ],
+
+ E = queue:new(),
+ [] = queue:to_list(E),
+ Q = do_queue(E, L),
+ true = queue:is_empty(Q),
+ 0 = queue:len(Q),
ok.
-to_list(doc) ->
- ["OTP-2701"];
-to_list(suite) ->
- [];
+%% OTP-2701
to_list(Config) when is_list(Config) ->
- ?line E = queue:new(),
- ?line Q = do_queue(E, [{in, 1},
- {in, 2},
- {in, 3},
- {out, {value, 1}},
- {in, 4},
- {in, 5}]),
- ?line true = queue:is_queue(Q),
- ?line 4 = queue:len(Q),
- ?line case queue:to_list(Q) of
- [2,3,4,5] ->
- ok;
- Other1 ->
- test_server:fail(Other1)
- end,
+ E = queue:new(),
+ Q = do_queue(E, [{in, 1},
+ {in, 2},
+ {in, 3},
+ {out, {value, 1}},
+ {in, 4},
+ {in, 5}]),
+ true = queue:is_queue(Q),
+ 4 = queue:len(Q),
+ case queue:to_list(Q) of
+ [2,3,4,5] ->
+ ok;
+ Other1 ->
+ ct:fail(Other1)
+ end,
ok.
do_queue(Q, []) ->
@@ -114,93 +104,86 @@ do_queue_1({out, E}, Q) ->
{E, Q1} ->
Q1;
Other ->
- test_server:fail({"out failed", E, Q, Other})
+ ct:fail({"out failed", E, Q, Other})
end.
-io_test(doc) ->
- "Test input and output";
-io_test(suite) ->
- [];
+%% Test input and output.
io_test(Config) when is_list(Config) ->
E = queue:new(),
do_io_test(E),
ok.
do_io_test(E) ->
- ?line [4,3,5] =
+ [4,3,5] =
io([snoc,snoc,head,head,head,cons,cons,snoc], E, 1),
- ?line [5,3,4] =
+ [5,3,4] =
io([cons,cons,daeh,daeh,daeh,snoc,snoc,cons], E, 1),
- ?line [4,3,5] =
+ [4,3,5] =
io([in,in,out,out,out,in_r,in_r,in], E, 1),
- ?line [5,3,4] =
+ [5,3,4] =
io([in_r,in_r,out_r,out_r,out_r,in,in,in_r], E, 1),
%%
- ?line [] =
+ [] =
io([snoc,snoc,head,snoc,snoc,head,head,snoc,head,head], E, 1),
- ?line [] =
+ [] =
io([cons,cons,daeh,cons,cons,daeh,daeh,cons,daeh,daeh], E, 1),
- ?line [] =
+ [] =
io([in,in,out,in,in,out,out,in,out,out], E, 1),
- ?line [] =
+ [] =
io([in_r,in_r,out_r,in_r,in_r,out_r,out_r,in_r,out_r,out_r],
E, 1),
%%
- ?line [5,6] =
+ [5,6] =
io([snoc,snoc,snoc,head,head,snoc,snoc,snoc,head,head], E, 1),
- ?line [6,5] =
+ [6,5] =
io([cons,cons,cons,daeh,daeh,cons,cons,cons,daeh,daeh], E, 1),
- ?line [5,6] =
+ [5,6] =
io([in,in,in,out,out,in,in,in,out,out], E, 1),
- ?line [6,5] =
+ [6,5] =
io([in_r,in_r,in_r,out_r,out_r,in_r,in_r,in_r,out_r,out_r],
E, 1),
%%
- ?line [5] =
+ [5] =
io([snoc,head,head,snoc,head,snoc,head,snoc,head,snoc], E, 1),
- ?line [5] =
+ [5] =
io([cons,daeh,daeh,cons,daeh,cons,daeh,cons,daeh,cons], E, 1),
- ?line [5] =
+ [5] =
io([in,out,out,in,out,in,out,in,out,in], E, 1),
- ?line [5] =
+ [5] =
io([in_r,out_r,out_r,in_r,out_r,in_r,out_r,in_r,out_r,in_r],
E, 1),
%%
- ?line [] =
+ [] =
io([snoc,head,snoc,snoc,head,head,snoc,snoc,snoc,head,head,head],
E, 1),
- ?line [] =
+ [] =
io([cons,daeh,cons,cons,daeh,daeh,cons,cons,cons,daeh,daeh,daeh],
- E, 1),
- ?line [] =
+ E, 1),
+ [] =
io([in,out,in,in,out,out,in,in,in,out,out,out],
E, 1),
- ?line [] =
+ [] =
io([in_r,out_r,in_r,in_r,out_r,out_r,in_r,in_r,in_r,out_r,out_r,out_r],
- E, 1),
+ E, 1),
%%
- ?line [3] = io([cons,cons,cons,snoc,daeh,daeh,daeh], E, 1),
- ?line [3] = io([snoc,snoc,snoc,cons,head,head,head], E, 1),
- ?line [3] = io([in,in,in,in_r,out,out,out], E, 1),
- ?line [3] = io([in_r,in_r,in_r,in,out_r,out_r,out_r], E, 1),
+ [3] = io([cons,cons,cons,snoc,daeh,daeh,daeh], E, 1),
+ [3] = io([snoc,snoc,snoc,cons,head,head,head], E, 1),
+ [3] = io([in,in,in,in_r,out,out,out], E, 1),
+ [3] = io([in_r,in_r,in_r,in,out_r,out_r,out_r], E, 1),
%%
- ?line Q2 = queue:join(queue:cons(1, E),queue:cons(2, E)),
- ?line Q1 = queue:reverse(Q2),
- ?line [1] = io([head], Q1, 3),
- ?line [1] = io([out], Q1, 3),
- ?line [1] = io([daeh], Q2, 3),
- ?line [1] = io([out_r], Q2, 3),
-% ?line [2] = io([cons,cons,snoc,daeh,daeh], [], 1),
-% ?line [2] = io([snoc,snoc,cons,head,head], [], 1),
-% ?line [2] = io([in,in,in_r,out,out], [], 1),
-% ?line [2] = io([in_r,in_r,in,out_r,out_r], [], 1),
+ Q2 = queue:join(queue:cons(1, E),queue:cons(2, E)),
+ Q1 = queue:reverse(Q2),
+ [1] = io([head], Q1, 3),
+ [1] = io([out], Q1, 3),
+ [1] = io([daeh], Q2, 3),
+ [1] = io([out_r], Q2, 3),
%%
- ?line [2] =
+ [2] =
io([in,peek,peek_r,drop,in_r,peek,peek_r,in,peek,peek_r,drop_r], E, 1),
%% Malformed queues UGLY-GUTS-ALL-OVER-THE-PLACE
- ?line [2,1] = io([peek], {[1,2],[]}, 1),
- ?line [1,2] = io([peek_r], {[],[1,2]}, 1),
+ [2,1] = io([peek], {[1,2],[]}, 1),
+ [1,2] = io([peek_r], {[],[1,2]}, 1),
%%
ok.
@@ -269,7 +252,7 @@ io([peek_r | Tail], Q, Q0, X) ->
io([drop | Tail], Q, [], X) ->
try queue:drop(Q) of
V ->
- test_server:fail({?MODULE,?LINE,V})
+ ct:fail({?MODULE,?LINE,V})
catch
error:empty ->
io(Tail, Q, [], X)
@@ -280,7 +263,7 @@ io([drop | Tail], Q, [_ | T], X) ->
io([drop_r | Tail], Q, [], X) ->
try queue:drop_r(Q) of
V ->
- test_server:fail({?MODULE,?LINE,V})
+ ct:fail({?MODULE,?LINE,V})
catch
error:empty ->
io(Tail, Q, [], X)
@@ -298,108 +281,102 @@ io([], Q, QQ, _X) ->
QQ.
-op_test(doc) ->
- "Test operations on whole queues";
-op_test(suite) ->
- [];
+%% Test operations on whole queues.
op_test(Config) when is_list(Config) ->
do_op_test(fun id/1),
ok.
do_op_test(F) ->
- ?line Len = 50,
- ?line Len2 = 2*Len,
- ?line L1 = lists:seq(1, Len),
- ?line L1r = lists:reverse(L1),
- ?line L2 = lists:seq(Len+1, Len2),
- ?line L2r = lists:reverse(L2),
- ?line L3 = L1++L2,
- ?line L3r = L2r++L1r,
- ?line Q0 = F(queue:new()),
- ?line [] = queue:to_list(Q0),
- ?line Q0 = F(queue:from_list([])),
- ?line Q1 = F(queue:from_list(L1)),
- ?line Q2 = F(queue:from_list(L2)),
- ?line Q3 = F(queue:from_list(L3)),
- ?line Len = queue:len(Q1),
- ?line Len = queue:len(Q2),
- ?line Len2 = queue:len(Q3),
- ?line L1 = queue:to_list(Q1),
- ?line L2 = queue:to_list(Q2),
- ?line L3 = queue:to_list(Q3),
- ?line Q3b = queue:join(Q0, queue:join(queue:join(Q1, Q2), Q0)),
- ?line L3 = queue:to_list(Q3b),
- ?line {Q0, Q3New1} = queue:split(0, Q3),
- ?line L3 = queue:to_list(Q3New1),
- ?line {Q3New2, Q0} = queue:split(Len2, Q3),
- ?line L3 = queue:to_list(Q3New2),
- ?line {Q1a, Q2a} = queue:split(Len, Q3),
- ?line L1 = queue:to_list(Q1a),
- ?line L2 = queue:to_list(Q2a),
- ?line {Q3c, Q3d} = queue:split(2, Q3),
- ?line L3 = queue:to_list(Q3c) ++ queue:to_list(Q3d),
- ?line {Q1b, Q2b} = queue:split(Len, Q3b),
- ?line L1 = queue:to_list(Q1b),
- ?line L2 = queue:to_list(Q2b),
- ?line Len = queue:len(Q1b),
- ?line Len = queue:len(Q2b),
- ?line Len2 = queue:len(Q3b),
- ?line Q1r = queue:reverse(Q1),
- ?line Q2r = queue:reverse(Q2),
- ?line Q1ar = queue:reverse(Q1a),
- ?line Q2ar = queue:reverse(Q2a),
- ?line Q1br = queue:reverse(Q1b),
- ?line Q2br = queue:reverse(Q2b),
- ?line Q3br = queue:reverse(Q3b),
- ?line L1r = queue:to_list(Q1r),
- ?line L1r = queue:to_list(Q1ar),
- ?line L1r = queue:to_list(Q1br),
- ?line L2r = queue:to_list(Q2r),
- ?line L2r = queue:to_list(Q2ar),
- ?line L2r = queue:to_list(Q2br),
- ?line L3r = queue:to_list(Q3br),
- ?line Len = queue:len(Q1br),
- ?line Len = queue:len(Q2br),
- ?line Len2 = queue:len(Q3br),
- ?line false = queue:member([], Q0),
- ?line false = queue:member(0, Q0),
- ?line false = queue:member(0, Q1),
- ?line false = queue:member([], Q1),
- ?line true = queue:member(1, Q1),
- ?line false = queue:member(1.0, Q1),
- ?line true = queue:member(Len, Q1),
+ Len = 50,
+ Len2 = 2*Len,
+ L1 = lists:seq(1, Len),
+ L1r = lists:reverse(L1),
+ L2 = lists:seq(Len+1, Len2),
+ L2r = lists:reverse(L2),
+ L3 = L1++L2,
+ L3r = L2r++L1r,
+ Q0 = F(queue:new()),
+ [] = queue:to_list(Q0),
+ Q0 = F(queue:from_list([])),
+ Q1 = F(queue:from_list(L1)),
+ Q2 = F(queue:from_list(L2)),
+ Q3 = F(queue:from_list(L3)),
+ Len = queue:len(Q1),
+ Len = queue:len(Q2),
+ Len2 = queue:len(Q3),
+ L1 = queue:to_list(Q1),
+ L2 = queue:to_list(Q2),
+ L3 = queue:to_list(Q3),
+ Q3b = queue:join(Q0, queue:join(queue:join(Q1, Q2), Q0)),
+ L3 = queue:to_list(Q3b),
+ {Q0, Q3New1} = queue:split(0, Q3),
+ L3 = queue:to_list(Q3New1),
+ {Q3New2, Q0} = queue:split(Len2, Q3),
+ L3 = queue:to_list(Q3New2),
+ {Q1a, Q2a} = queue:split(Len, Q3),
+ L1 = queue:to_list(Q1a),
+ L2 = queue:to_list(Q2a),
+ {Q3c, Q3d} = queue:split(2, Q3),
+ L3 = queue:to_list(Q3c) ++ queue:to_list(Q3d),
+ {Q1b, Q2b} = queue:split(Len, Q3b),
+ L1 = queue:to_list(Q1b),
+ L2 = queue:to_list(Q2b),
+ Len = queue:len(Q1b),
+ Len = queue:len(Q2b),
+ Len2 = queue:len(Q3b),
+ Q1r = queue:reverse(Q1),
+ Q2r = queue:reverse(Q2),
+ Q1ar = queue:reverse(Q1a),
+ Q2ar = queue:reverse(Q2a),
+ Q1br = queue:reverse(Q1b),
+ Q2br = queue:reverse(Q2b),
+ Q3br = queue:reverse(Q3b),
+ L1r = queue:to_list(Q1r),
+ L1r = queue:to_list(Q1ar),
+ L1r = queue:to_list(Q1br),
+ L2r = queue:to_list(Q2r),
+ L2r = queue:to_list(Q2ar),
+ L2r = queue:to_list(Q2br),
+ L3r = queue:to_list(Q3br),
+ Len = queue:len(Q1br),
+ Len = queue:len(Q2br),
+ Len2 = queue:len(Q3br),
+ false = queue:member([], Q0),
+ false = queue:member(0, Q0),
+ false = queue:member(0, Q1),
+ false = queue:member([], Q1),
+ true = queue:member(1, Q1),
+ false = queue:member(1.0, Q1),
+ true = queue:member(Len, Q1),
%%
%% Additional coverage.
- ?line {MyL1r,MyL2r} = lists:split(Len-2, L1r),
- ?line MyQ0r = queue:reverse(F(queue:from_list(L1))),
- ?line {MyQ1r,MyQ2r} = queue:split(Len-2, MyQ0r),
- ?line MyL1r = queue:to_list(MyQ1r),
- ?line MyL2r = queue:to_list(MyQ2r),
- ?line MyQ3r = queue:filter(
- fun (X) when X rem 4 >= 2 -> false;
- (X) when X rem 8 == 0 -> [float(X),{X}];
- (X) when X rem 2 >= 1 -> [{X}];
- (_) -> true
- end, MyQ1r),
- ?line MyL3r = lists:flatten(
- [if X rem 8 == 0 -> [float(X),{X}];
- X rem 2 >= 1 -> {X};
- true -> X
- end || X <- MyL1r,
- X rem 4 < 2]),
- ?line MyL3r = queue:to_list(MyQ3r),
- ?line MyQ4 = F(queue:from_list([11,22,33,44])),
- ?line [11,22] = queue:to_list(queue:filter(fun(X) when X < 27 -> true;
- (_) -> [] end, MyQ4)),
- ?line [33,44] = queue:to_list(queue:filter(fun(X) when X < 27 -> false;
- (X) -> [X] end, MyQ4)),
+ {MyL1r,MyL2r} = lists:split(Len-2, L1r),
+ MyQ0r = queue:reverse(F(queue:from_list(L1))),
+ {MyQ1r,MyQ2r} = queue:split(Len-2, MyQ0r),
+ MyL1r = queue:to_list(MyQ1r),
+ MyL2r = queue:to_list(MyQ2r),
+ MyQ3r = queue:filter(
+ fun (X) when X rem 4 >= 2 -> false;
+ (X) when X rem 8 == 0 -> [float(X),{X}];
+ (X) when X rem 2 >= 1 -> [{X}];
+ (_) -> true
+ end, MyQ1r),
+ MyL3r = lists:flatten(
+ [if X rem 8 == 0 -> [float(X),{X}];
+ X rem 2 >= 1 -> {X};
+ true -> X
+ end || X <- MyL1r,
+ X rem 4 < 2]),
+ MyL3r = queue:to_list(MyQ3r),
+ MyQ4 = F(queue:from_list([11,22,33,44])),
+ [11,22] = queue:to_list(queue:filter(fun(X) when X < 27 -> true;
+ (_) -> [] end, MyQ4)),
+ [33,44] = queue:to_list(queue:filter(fun(X) when X < 27 -> false;
+ (X) -> [X] end, MyQ4)),
%%
ok.
-error(doc) ->
- "Test queue errors";
-error(suite) ->
- [];
+%% Test queue errors.
error(Config) when is_list(Config) ->
do_error(fun id/1, illegal_queue),
do_error(fun id/1, {[],illegal_queue}),
@@ -417,65 +394,62 @@ trycatch(M, F, Args) ->
end.
do_error(F, IQ) ->
- ?line io:format("Illegal Queue: ~p~n", [IQ]),
+ io:format("Illegal Queue: ~p~n", [IQ]),
%%
- ?line {error,badarg} = trycatch(in, [1, IQ]),
- ?line {error,badarg} = trycatch(out, [IQ]),
- ?line {error,badarg} = trycatch(in_r ,[1, IQ]),
- ?line {error,badarg} = trycatch(out_r ,[IQ]),
- ?line {error,badarg} = trycatch(to_list ,[IQ]),
+ {error,badarg} = trycatch(in, [1, IQ]),
+ {error,badarg} = trycatch(out, [IQ]),
+ {error,badarg} = trycatch(in_r ,[1, IQ]),
+ {error,badarg} = trycatch(out_r ,[IQ]),
+ {error,badarg} = trycatch(to_list ,[IQ]),
%%
- ?line {error,badarg} = trycatch(from_list, [no_list]),
- ?line {error,badarg} = trycatch(is_empty, [IQ]),
- ?line {error,badarg} = trycatch(len, [IQ]),
+ {error,badarg} = trycatch(from_list, [no_list]),
+ {error,badarg} = trycatch(is_empty, [IQ]),
+ {error,badarg} = trycatch(len, [IQ]),
%%
- ?line {error,badarg} = trycatch(cons, [1, IQ]),
- ?line {error,badarg} = trycatch(head, [IQ]),
- ?line {error,badarg} = trycatch(tail, [IQ]),
+ {error,badarg} = trycatch(cons, [1, IQ]),
+ {error,badarg} = trycatch(head, [IQ]),
+ {error,badarg} = trycatch(tail, [IQ]),
%%
- ?line {error,badarg} = trycatch(snoc, [IQ, 1]),
- ?line {error,badarg} = trycatch(last, [IQ]),
- ?line {error,badarg} = trycatch(daeh, [IQ]),
- ?line {error,badarg} = trycatch(liat, [IQ]),
- ?line {error,badarg} = trycatch(lait, [IQ]),
- ?line {error,badarg} = trycatch(init, [IQ]),
+ {error,badarg} = trycatch(snoc, [IQ, 1]),
+ {error,badarg} = trycatch(last, [IQ]),
+ {error,badarg} = trycatch(daeh, [IQ]),
+ {error,badarg} = trycatch(liat, [IQ]),
+ {error,badarg} = trycatch(lait, [IQ]),
+ {error,badarg} = trycatch(init, [IQ]),
%%
- ?line {error,badarg} = trycatch(reverse, [IQ]),
- ?line {error,badarg} = trycatch(join, [F(queue:new()), IQ]),
- ?line {error,badarg} = trycatch(join, [IQ, F(queue:new())]),
- ?line {error,badarg} = trycatch(split, [17, IQ]),
- ?line {error,badarg} = trycatch(head, [IQ]),
+ {error,badarg} = trycatch(reverse, [IQ]),
+ {error,badarg} = trycatch(join, [F(queue:new()), IQ]),
+ {error,badarg} = trycatch(join, [IQ, F(queue:new())]),
+ {error,badarg} = trycatch(split, [17, IQ]),
+ {error,badarg} = trycatch(head, [IQ]),
%%
- ?line Q0 = F(queue:new()),
- ?line {error,badarg} = trycatch(split, [1, Q0]),
- ?line {error,badarg} = trycatch(split, [2, queue:snoc(Q0, 1)]),
+ Q0 = F(queue:new()),
+ {error,badarg} = trycatch(split, [1, Q0]),
+ {error,badarg} = trycatch(split, [2, queue:snoc(Q0, 1)]),
%%
- ?line {value,false} = trycatch(is_queue, [IQ]),
- ?line {error,badarg} = trycatch(get, [IQ]),
- ?line {error,badarg} = trycatch(peek, [IQ]),
- ?line {error,badarg} = trycatch(peek_r, [IQ]),
- ?line {error,badarg} = trycatch(filter, [fun id/1, IQ]),
- ?line {error,badarg} = trycatch(filter, [no_fun, Q0]),
+ {value,false} = trycatch(is_queue, [IQ]),
+ {error,badarg} = trycatch(get, [IQ]),
+ {error,badarg} = trycatch(peek, [IQ]),
+ {error,badarg} = trycatch(peek_r, [IQ]),
+ {error,badarg} = trycatch(filter, [fun id/1, IQ]),
+ {error,badarg} = trycatch(filter, [no_fun, Q0]),
%%
- ?line {error,badarg} = trycatch(member, [1, IQ]),
+ {error,badarg} = trycatch(member, [1, IQ]),
ok.
id(X) ->
X.
-oops(doc) ->
- "Test queue errors";
-oops(suite) ->
- [];
+%% Test queue errors.
oops(Config) when is_list(Config) ->
- ?line N = 3142,
- ?line Optab = optab(),
- ?line Seed0 = random:seed0(),
- ?line {Is,Seed} = random_list(N, tuple_size(Optab), Seed0, []),
- ?line io:format("~p ", [Is]),
- ?line QA = queue:new(),
- ?line QB = {[]},
- ?line emul([QA], [QB], Seed, [element(I, Optab) || I <- Is]).
+ N = 3142,
+ Optab = optab(),
+ Seed0 = rand:seed(exsplus, {1,2,4}),
+ {Is,Seed} = random_list(N, tuple_size(Optab), Seed0, []),
+ io:format("~p ", [Is]),
+ QA = queue:new(),
+ QB = {[]},
+ emul([QA], [QB], Seed, [element(I, Optab) || I <- Is]).
optab() ->
{{new,[], q, fun () -> {[]} end},
@@ -562,20 +536,20 @@ args([], _, Seed, R) ->
args([q|Ts], [Q|Qs]=Qss, Seed, R) ->
args(Ts, if Qs =:= [] -> Qss; true -> Qs end, Seed, [Q|R]);
args([l|Ts], Qs, Seed0, R) ->
- {N,Seed1} = random:uniform_s(17, Seed0),
+ {N,Seed1} = rand:uniform_s(17, Seed0),
{L,Seed} = random_list(N, 4711, Seed1, []),
args(Ts, Qs, Seed, [L|R]);
args([t|Ts], Qs, Seed0, R) ->
- {T,Seed} = random:uniform_s(4711, Seed0),
+ {T,Seed} = rand:uniform_s(4711, Seed0),
args(Ts, Qs, Seed, [T|R]);
args([n|Ts], Qs, Seed0, R) ->
- {N,Seed} = random:uniform_s(17, Seed0),
+ {N,Seed} = rand:uniform_s(17, Seed0),
args(Ts, Qs, Seed, [N|R]).
random_list(0, _, Seed, R) ->
{R,Seed};
random_list(N, M, Seed0, R) ->
- {X,Seed} = random:uniform_s(M, Seed0),
+ {X,Seed} = rand:uniform_s(M, Seed0),
random_list(N-1, M, Seed, [X|R]).
call(Func, As) ->
diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl
index 03b5ce1a25..6830101e96 100644
--- a/lib/stdlib/test/rand_SUITE.erl
+++ b/lib/stdlib/test/rand_SUITE.erl
@@ -33,21 +33,19 @@
-export([test/0, gen/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(3)).
-define(LOOP, 1000000).
init_per_testcase(_Case, Config) ->
- Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+ Config.
+
+end_per_testcase(_Case, _Config) ->
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,3}}].
all() ->
[seed, interval_int, interval_float,
@@ -85,16 +83,13 @@ algs() ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-seed(doc) ->
- ["Test that seed and seed_s and export_seed/0 is working."];
-seed(suite) ->
- [];
+%% Test that seed and seed_s and export_seed/0 is working.
seed(Config) when is_list(Config) ->
Algs = algs(),
Test = fun(Alg) ->
try seed_1(Alg)
catch _:Reason ->
- test_server:fail({Alg, Reason, erlang:get_stacktrace()})
+ ct:fail({Alg, Reason, erlang:get_stacktrace()})
end
end,
[Test(Alg) || Alg <- Algs],
@@ -139,10 +134,7 @@ seed_1(Alg) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-api_eq(doc) ->
- ["Check that both api's are consistent with each other."];
-api_eq(suite) ->
- [];
+%% Check that both APIs are consistent with each other.
api_eq(_Config) ->
Algs = algs(),
Small = fun(Alg) ->
@@ -188,10 +180,7 @@ api_eq_1(S00) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-interval_int(doc) ->
- ["Check that uniform/1 returns values within the proper interval."];
-interval_int(suite) ->
- [];
+%% Check that uniform/1 returns values within the proper interval.
interval_int(Config) when is_list(Config) ->
Algs = algs(),
Small = fun(Alg) ->
@@ -225,10 +214,7 @@ interval_int_1(N, Top, Max) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-interval_float(doc) ->
- ["Check that uniform/0 returns values within the proper interval."];
-interval_float(suite) ->
- [];
+%% Check that uniform/0 returns values within the proper interval.
interval_float(Config) when is_list(Config) ->
Algs = algs(),
Test = fun(Alg) ->
@@ -252,8 +238,7 @@ interval_float_1(N) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-reference(doc) -> ["Check if exs64 algorithm generates the proper sequence."];
-reference(suite) -> [];
+%% Check if exs64 algorithm generates the proper sequence.
reference(Config) when is_list(Config) ->
[reference_1(Alg) || Alg <- algs()],
ok.
@@ -267,7 +252,6 @@ reference_1(Alg) ->
io:format("Failed: ~p~n",[Alg]),
io:format("Length ~p ~p~n",[length(Refval), length(Testval)]),
io:format("Head ~p ~p~n",[hd(Refval), hd(Testval)]),
- %% test_server:fail({Alg, Refval -- Testval}),
ok
end.
@@ -330,9 +314,9 @@ basic_uniform_1(0, {#{type:=Alg}, _}, Sum, A) ->
%% Verify that the basic statistics are ok
%% be gentle we don't want to see to many failing tests
- abs(0.5 - AverN) < 0.005 orelse test_server:fail({average, Alg, AverN}),
- abs(?LOOP div 100 - Min) < 1000 orelse test_server:fail({min, Alg, Min}),
- abs(?LOOP div 100 - Max) < 1000 orelse test_server:fail({max, Alg, Max}),
+ abs(0.5 - AverN) < 0.005 orelse ct:fail({average, Alg, AverN}),
+ abs(?LOOP div 100 - Min) < 1000 orelse ct:fail({min, Alg, Min}),
+ abs(?LOOP div 100 - Max) < 1000 orelse ct:fail({max, Alg, Max}),
ok.
basic_uniform_2(N, S0, Sum, A0) when N > 0 ->
@@ -349,9 +333,9 @@ basic_uniform_2(0, {#{type:=Alg}, _}, Sum, A) ->
%% Verify that the basic statistics are ok
%% be gentle we don't want to see to many failing tests
- abs(50.5 - AverN) < 0.5 orelse test_server:fail({average, Alg, AverN}),
- abs(?LOOP div 100 - Min) < 1000 orelse test_server:fail({min, Alg, Min}),
- abs(?LOOP div 100 - Max) < 1000 orelse test_server:fail({max, Alg, Max}),
+ abs(50.5 - AverN) < 0.5 orelse ct:fail({average, Alg, AverN}),
+ abs(?LOOP div 100 - Min) < 1000 orelse ct:fail({min, Alg, Min}),
+ abs(?LOOP div 100 - Max) < 1000 orelse ct:fail({max, Alg, Max}),
ok.
basic_normal_1(N, S0, Sum, Sq) when N > 0 ->
@@ -363,14 +347,13 @@ basic_normal_1(0, {#{type:=Alg}, _}, Sum, SumSq) ->
io:format("~.10w: Average: ~7.4f StdDev ~6.4f~n", [Alg, Mean, StdDev]),
%% Verify that the basic statistics are ok
%% be gentle we don't want to see to many failing tests
- abs(Mean) < 0.005 orelse test_server:fail({average, Alg, Mean}),
- abs(StdDev - 1.0) < 0.005 orelse test_server:fail({stddev, Alg, StdDev}),
+ abs(Mean) < 0.005 orelse ct:fail({average, Alg, Mean}),
+ abs(StdDev - 1.0) < 0.005 orelse ct:fail({stddev, Alg, StdDev}),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-plugin(doc) -> ["Test that the user can write algorithms"];
-plugin(suite) -> [];
+%% Test that the user can write algorithms.
plugin(Config) when is_list(Config) ->
_ = lists:foldl(fun(_, S0) ->
{V1, S1} = rand:uniform_s(10000, S0),
diff --git a/lib/stdlib/test/random_SUITE.erl b/lib/stdlib/test/random_SUITE.erl
index 738f73ae15..34b350e132 100644
--- a/lib/stdlib/test/random_SUITE.erl
+++ b/lib/stdlib/test/random_SUITE.erl
@@ -19,26 +19,23 @@
-module(random_SUITE).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2,
init_per_group/2,end_per_group/2]).
-export([interval_1/1, seed0/1, seed/1]).
--export([init_per_testcase/2, end_per_testcase/2]).
--include_lib("test_server/include/test_server.hrl").
-
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
+-include_lib("common_test/include/ct.hrl").
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- [{watchdog, Dog} | Config].
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+ Config.
+
+end_per_testcase(_Case, _Config) ->
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[interval_1, seed0, seed].
@@ -59,59 +56,50 @@ end_per_group(_GroupName, Config) ->
Config.
-seed0(doc) ->
- ["Test that seed is set implicitly, and always the same."];
-seed0(suite) ->
- [];
+%% Test that seed is set implicitly, and always the same.
seed0(Config) when is_list(Config) ->
- ?line Self = self(),
- ?line _ = spawn(fun() -> Self ! random:uniform() end),
- ?line F1 = receive
- Fa -> Fa
- end,
- ?line _ = spawn(fun() -> random:seed(),
- Self ! random:uniform() end),
- ?line F2 = receive
- Fb -> Fb
- end,
- ?line F1 = F2,
+ Self = self(),
+ _ = spawn(fun() -> Self ! random:uniform() end),
+ F1 = receive
+ Fa -> Fa
+ end,
+ _ = spawn(fun() -> random:seed(),
+ Self ! random:uniform() end),
+ F2 = receive
+ Fb -> Fb
+ end,
+ F1 = F2,
ok.
-seed(doc) ->
- ["Test that seed/1 and seed/3 is equivalent."];
-seed(suite) ->
- [];
+%% Test that seed/1 and seed/3 are equivalent.
seed(Config) when is_list(Config) ->
- ?line Self = self(),
+ Self = self(),
Seed = {S1, S2, S3} = erlang:timestamp(),
- ?line _ = spawn(fun() ->
- random:seed(S1,S2,S3),
- Rands = lists:foldl(fun
- (_, Out) -> [random:uniform(10000)|Out]
- end, [], lists:seq(1,100)),
- Self ! {seed_test, Rands}
- end),
- ?line Rands1 = receive {seed_test, R1s} -> R1s end,
- ?line _ = spawn(fun() ->
- random:seed(Seed),
- Rands = lists:foldl(fun
- (_, Out) -> [random:uniform(10000)|Out]
- end, [], lists:seq(1,100)),
- Self ! {seed_test, Rands}
- end),
- ?line Rands2 = receive {seed_test, R2s} -> R2s end,
- ?line Rands1 = Rands2,
+ _ = spawn(fun() ->
+ random:seed(S1,S2,S3),
+ Rands = lists:foldl(fun
+ (_, Out) -> [random:uniform(10000)|Out]
+ end, [], lists:seq(1,100)),
+ Self ! {seed_test, Rands}
+ end),
+ Rands1 = receive {seed_test, R1s} -> R1s end,
+ _ = spawn(fun() ->
+ random:seed(Seed),
+ Rands = lists:foldl(fun
+ (_, Out) -> [random:uniform(10000)|Out]
+ end, [], lists:seq(1,100)),
+ Self ! {seed_test, Rands}
+ end),
+ Rands2 = receive {seed_test, R2s} -> R2s end,
+ Rands1 = Rands2,
ok.
-interval_1(doc) ->
- ["Check that uniform/1 returns values within the proper interval."];
-interval_1(suite) ->
- [];
+%% Check that uniform/1 returns values within the proper interval.
interval_1(Config) when is_list(Config) ->
- ?line Top = 7,
- ?line N = 10,
- ?line check_interval(N, Top),
+ Top = 7,
+ N = 10,
+ check_interval(N, Top),
ok.
check_interval(0, _) -> ok;
@@ -119,9 +107,9 @@ check_interval(N, Top) ->
X = random:uniform(Top),
if
X < 1 ->
- test_server:fail(too_small);
+ ct:fail(too_small);
X > Top ->
- test_server:fail(too_large);
+ ct:fail(too_large);
true ->
ok
end,
diff --git a/lib/stdlib/test/random_iolist.erl b/lib/stdlib/test/random_iolist.erl
index 9a0f034e72..6da7da04de 100644
--- a/lib/stdlib/test/random_iolist.erl
+++ b/lib/stdlib/test/random_iolist.erl
@@ -36,7 +36,7 @@ run2(Iter,Fun1,Fun2) ->
compare2(Iter,Fun1,Fun2).
random_byte() ->
- random:uniform(256) - 1.
+ rand:uniform(256) - 1.
random_list(0,Acc) ->
Acc;
@@ -45,7 +45,7 @@ random_list(N,Acc) ->
random_binary(N) ->
B = list_to_binary(random_list(N,[])),
- case {random:uniform(2),size(B)} of
+ case {rand:uniform(2),size(B)} of
{2,M} when M > 1 ->
S = M-1,
<<_:3,C:S/binary,_:5>> = B,
@@ -57,7 +57,7 @@ random_list(N) ->
random_list(N,[]).
front() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
10 ->
false;
_ ->
@@ -65,7 +65,7 @@ front() ->
end.
any_type() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
1 ->
list;
2 ->
@@ -77,7 +77,7 @@ any_type() ->
end.
tail_type() ->
- case random:uniform(5) of
+ case rand:uniform(5) of
1 ->
list;
2 ->
@@ -90,9 +90,9 @@ random_length(N) ->
UpperLimit = 255,
case N of
M when M > UpperLimit ->
- random:uniform(UpperLimit+1) - 1;
+ rand:uniform(UpperLimit+1) - 1;
_ ->
- random:uniform(N+1) - 1
+ rand:uniform(N+1) - 1
end.
random_iolist(0,Acc) ->
@@ -139,7 +139,7 @@ random_iolist(N) ->
standard_seed() ->
- random:seed(1201,855653,380975).
+ rand:seed(exsplus, {1201,855653,380975}).
do_comp(List,F1,F2) ->
X = F1(List),
diff --git a/lib/stdlib/test/random_unicode_list.erl b/lib/stdlib/test/random_unicode_list.erl
index ecafe42318..3bc86a8430 100644
--- a/lib/stdlib/test/random_unicode_list.erl
+++ b/lib/stdlib/test/random_unicode_list.erl
@@ -85,7 +85,7 @@ int_to_utf32_little(I) ->
id(I) -> I.
random_char() ->
- case random:uniform(16#10FFFF+1) - 1 of
+ case rand:uniform(16#10FFFF+1) - 1 of
X when X >= 16#D800,
X =< 16#DFFF ->
random_char();
@@ -116,13 +116,13 @@ random_binary(N,Enc) ->
int_to(Enc,X)
end,
L)),
- case {random:uniform(3),size(B)} of
+ case {rand:uniform(3),size(B)} of
{2,M} when M > 1 ->
B2 = id(<<1:3,B/binary,1:5>>),
<<_:3,C:M/binary,_:5>> = B2,
C;
{3,M} when M > 1 ->
- X = random:uniform(M+1)-1,
+ X = rand:uniform(M+1)-1,
<<B1:X/binary,B2/binary>> = B,
[B1,B2];
_ ->
@@ -132,7 +132,7 @@ random_list(N) ->
random_list(N,[]).
front() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
10 ->
false;
_ ->
@@ -140,7 +140,7 @@ front() ->
end.
any_type() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
1 ->
list;
2 ->
@@ -152,7 +152,7 @@ any_type() ->
end.
tail_type() ->
- case random:uniform(5) of
+ case rand:uniform(5) of
1 ->
list;
2 ->
@@ -165,9 +165,9 @@ random_length(N) ->
UpperLimit = 255,
case N of
M when M > UpperLimit ->
- random:uniform(UpperLimit+1) - 1;
+ rand:uniform(UpperLimit+1) - 1;
_ ->
- random:uniform(N+1) - 1
+ rand:uniform(N+1) - 1
end.
random_unicode_list(0,Acc,_Enc) ->
@@ -214,7 +214,7 @@ random_unicode_list(N,Enc) ->
standard_seed() ->
- random:seed(1201,855653,380975).
+ rand:seed(exsplus, {1201,855653,380975}).
do_comp(List,F1,F2) ->
X = F1(List),
diff --git a/lib/stdlib/test/re_SUITE.erl b/lib/stdlib/test/re_SUITE.erl
index d78d6153da..a937e7b1cf 100644
--- a/lib/stdlib/test/re_SUITE.erl
+++ b/lib/stdlib/test/re_SUITE.erl
@@ -30,10 +30,12 @@
opt_no_start_optimize/1,opt_never_utf/1,opt_ucp/1,
match_limit/1,sub_binaries/1,copt/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,3}}].
all() ->
[pcre, compile_options, run_options, combined_options,
@@ -61,264 +63,247 @@ end_per_group(_GroupName, Config) ->
Config.
-pcre(doc) ->
- ["Run all applicable tests from the PCRE testsuites."];
+%% Run all applicable tests from the PCRE testsuites.
pcre(Config) when is_list(Config) ->
- Dog = ?t:timetrap(?t:minutes(3)),
- RootDir = ?config(data_dir, Config),
+ RootDir = proplists:get_value(data_dir, Config),
Res = run_pcre_tests:test(RootDir),
0 = lists:sum([ X || {X,_,_} <- Res ]),
- ?t:timetrap_cancel(Dog),
{comment,Res}.
-compile_options(doc) ->
- ["Test all documented compile options"];
+%% Test all documented compile options.
compile_options(Config) when is_list(Config) ->
- ?line ok = ctest("ABDabcdABCD","abcd",[],true,{match,[{3,4}]}),
- ?line ok = ctest("ABDabcdABCD","abcd",[anchored],true,nomatch),
- ?line ok = ctest("ABDabcdABCD",".*abcd",[anchored],true,{match,[{0,7}]}),
- ?line ok = ctest("ABCabcdABC","ABCD",[],true,nomatch),
- ?line ok = ctest("ABCabcdABC","ABCD",[caseless],true,{match,[{3,4}]}),
- ?line ok = ctest("abcdABC\n","ABC$",[],true,{match,[{4,3}]}),
- ?line ok = ctest("abcdABC\n","ABC$",[dollar_endonly],true,nomatch),
- ?line ok = ctest("abcdABC\n","ABC.",[],true,nomatch),
- ?line ok = ctest("abcdABC\n","ABC.",[dotall],true,{match,[{4,4}]}),
- ?line ok = ctest("abcdABCD","ABC .",[],true,nomatch),
- ?line ok = ctest("abcdABCD","ABC .",[extended],true,{match,[{4,4}]}),
- ?line ok = ctest("abcd\nABCD","ABC",[],true,{match,[{5,3}]}),
- ?line ok = ctest("abcd\nABCD","ABC",[firstline],true,nomatch),
- ?line ok = ctest("abcd\nABCD","^ABC",[],true,nomatch),
- ?line ok = ctest("abcd\nABCD","^ABC",[multiline],true,{match,[{5,3}]}),
- ?line ok = ctest("abcdABCD","(ABC)",[],true,{match,[{4,3},{4,3}]}),
- ?line ok = ctest("abcdABCD","(ABC)",[no_auto_capture],true,{match,[{4,3}]}),
- ?line ok = ctest(notused,"(?<FOO>ABC)|(?<FOO>DEF)",[],false,notused),
- ?line ok = ctest("abcdABCD","(?<FOO>ABC)|(?<FOO>DEF)",[dupnames],true,{match,[{4,3},{4,3}]}),
- ?line ok = ctest("abcdABCDabcABCD","abcd.*D",[],true,{match,[{0,15}]}),
- ?line ok = ctest("abcdABCDabcABCD","abcd.*D",[ungreedy],true,{match,[{0,8}]}),
- ?line ok = ctest("abcdABCabcABC\nD","abcd.*D",[],true,nomatch),
- ?line ok = ctest("abcdABCabcABC\nD","abcd.*D",[{newline,cr}],true,{match,[{0,15}]}),
- ?line ok = ctest("abcdABCabcABC\rD","abcd.*D",[],true,{match,[{0,15}]}),
- ?line ok = ctest("abcdABCabcABC\rD","abcd.*D",[{newline,lf}],true,{match,[{0,15}]}),
- ?line ok = ctest("abcdABCabcd\r\n","abcd$",[{newline,lf}],true,nomatch),
- ?line ok = ctest("abcdABCabcd\r\n","abcd$",[{newline,cr}],true,nomatch),
- ?line ok = ctest("abcdABCabcd\r\n","abcd$",[{newline,crlf}],true,{match,[{7,4}]}),
-
- ?line ok = ctest("abcdABCabcd\r","abcd$",[{newline,crlf}],true,nomatch),
- ?line ok = ctest("abcdABCabcd\n","abcd$",[{newline,crlf}],true,nomatch),
- ?line ok = ctest("abcdABCabcd\r\n","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}),
-
- ?line ok = ctest("abcdABCabcd\r","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}),
- ?line ok = ctest("abcdABCabcd\n","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}),
+ ok = ctest("ABDabcdABCD","abcd",[],true,{match,[{3,4}]}),
+ ok = ctest("ABDabcdABCD","abcd",[anchored],true,nomatch),
+ ok = ctest("ABDabcdABCD",".*abcd",[anchored],true,{match,[{0,7}]}),
+ ok = ctest("ABCabcdABC","ABCD",[],true,nomatch),
+ ok = ctest("ABCabcdABC","ABCD",[caseless],true,{match,[{3,4}]}),
+ ok = ctest("abcdABC\n","ABC$",[],true,{match,[{4,3}]}),
+ ok = ctest("abcdABC\n","ABC$",[dollar_endonly],true,nomatch),
+ ok = ctest("abcdABC\n","ABC.",[],true,nomatch),
+ ok = ctest("abcdABC\n","ABC.",[dotall],true,{match,[{4,4}]}),
+ ok = ctest("abcdABCD","ABC .",[],true,nomatch),
+ ok = ctest("abcdABCD","ABC .",[extended],true,{match,[{4,4}]}),
+ ok = ctest("abcd\nABCD","ABC",[],true,{match,[{5,3}]}),
+ ok = ctest("abcd\nABCD","ABC",[firstline],true,nomatch),
+ ok = ctest("abcd\nABCD","^ABC",[],true,nomatch),
+ ok = ctest("abcd\nABCD","^ABC",[multiline],true,{match,[{5,3}]}),
+ ok = ctest("abcdABCD","(ABC)",[],true,{match,[{4,3},{4,3}]}),
+ ok = ctest("abcdABCD","(ABC)",[no_auto_capture],true,{match,[{4,3}]}),
+ ok = ctest(notused,"(?<FOO>ABC)|(?<FOO>DEF)",[],false,notused),
+ ok = ctest("abcdABCD","(?<FOO>ABC)|(?<FOO>DEF)",[dupnames],true,{match,[{4,3},{4,3}]}),
+ ok = ctest("abcdABCDabcABCD","abcd.*D",[],true,{match,[{0,15}]}),
+ ok = ctest("abcdABCDabcABCD","abcd.*D",[ungreedy],true,{match,[{0,8}]}),
+ ok = ctest("abcdABCabcABC\nD","abcd.*D",[],true,nomatch),
+ ok = ctest("abcdABCabcABC\nD","abcd.*D",[{newline,cr}],true,{match,[{0,15}]}),
+ ok = ctest("abcdABCabcABC\rD","abcd.*D",[],true,{match,[{0,15}]}),
+ ok = ctest("abcdABCabcABC\rD","abcd.*D",[{newline,lf}],true,{match,[{0,15}]}),
+ ok = ctest("abcdABCabcd\r\n","abcd$",[{newline,lf}],true,nomatch),
+ ok = ctest("abcdABCabcd\r\n","abcd$",[{newline,cr}],true,nomatch),
+ ok = ctest("abcdABCabcd\r\n","abcd$",[{newline,crlf}],true,{match,[{7,4}]}),
+
+ ok = ctest("abcdABCabcd\r","abcd$",[{newline,crlf}],true,nomatch),
+ ok = ctest("abcdABCabcd\n","abcd$",[{newline,crlf}],true,nomatch),
+ ok = ctest("abcdABCabcd\r\n","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}),
+
+ ok = ctest("abcdABCabcd\r","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}),
+ ok = ctest("abcdABCabcd\n","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}),
ok.
-run_options(doc) ->
- ["Test all documented run specific options"];
+%% Test all documented run specific options.
run_options(Config) when is_list(Config) ->
- ?line rtest("ABCabcdABC","abc",[],[],true),
- ?line rtest("ABCabcdABC","abc",[anchored],[],false),
- % Anchored in run overrides unanchored in compilation
- ?line rtest("ABCabcdABC","abc",[],[anchored],false),
-
- ?line rtest("","a?b?",[],[],true),
- ?line rtest("","a?b?",[],[notempty],false),
-
- ?line rtest("abc","^a",[],[],true),
- ?line rtest("abc","^a",[],[notbol],false),
- ?line rtest("ab\nc","^a",[multiline],[],true),
- ?line rtest("ab\nc","^a",[multiline],[notbol],false),
- ?line rtest("ab\nc","^c",[multiline],[notbol],true),
-
- ?line rtest("abc","c$",[],[],true),
- ?line rtest("abc","c$",[],[noteol],false),
-
- ?line rtest("ab\nc","b$",[multiline],[],true),
- ?line rtest("ab\nc","c$",[multiline],[],true),
- ?line rtest("ab\nc","b$",[multiline],[noteol],true),
- ?line rtest("ab\nc","c$",[multiline],[noteol],false),
-
- ?line rtest("abc","ab",[],[{offset,0}],true),
- ?line rtest("abc","ab",[],[{offset,1}],false),
-
- ?line rtest("abcdABCabcABC\nD","abcd.*D",[],[],false),
- ?line rtest("abcdABCabcABC\nD","abcd.*D",[],[{newline,cr}],true),
- ?line rtest("abcdABCabcABC\rD","abcd.*D",[],[],true),
- ?line rtest("abcdABCabcABC\rD","abcd.*D",[{newline,cr}],[{newline,lf}],true),
- ?line rtest("abcdABCabcd\r\n","abcd$",[],[{newline,lf}],false),
- ?line rtest("abcdABCabcd\r\n","abcd$",[],[{newline,cr}],false),
- ?line rtest("abcdABCabcd\r\n","abcd$",[],[{newline,crlf}],true),
-
- ?line rtest("abcdABCabcd\r","abcd$",[],[{newline,crlf}],false),
- ?line rtest("abcdABCabcd\n","abcd$",[],[{newline,crlf}],false),
- ?line rtest("abcdABCabcd\r\n","abcd$",[],[{newline,anycrlf}],true),
-
- ?line rtest("abcdABCabcd\r","abcd$",[],[{newline,anycrlf}],true),
- ?line rtest("abcdABCabcd\n","abcd$",[],[{newline,anycrlf}],true),
-
- ?line {ok,MP} = re:compile(".*(abcd).*"),
- ?line {match,[{0,10},{3,4}]} = re:run("ABCabcdABC",MP,[]),
- ?line {match,[{0,10},{3,4}]} = re:run("ABCabcdABC",MP,[{capture,all}]),
- ?line {match,[{0,10},{3,4}]} = re:run("ABCabcdABC",MP,[{capture,all,index}]),
- ?line {match,["ABCabcdABC","abcd"]} = re:run("ABCabcdABC",MP,[{capture,all,list}]),
- ?line {match,[<<"ABCabcdABC">>,<<"abcd">>]} = re:run("ABCabcdABC",MP,[{capture,all,binary}]),
- ?line {match,[{0,10}]} = re:run("ABCabcdABC",MP,[{capture,first}]),
- ?line {match,[{0,10}]} = re:run("ABCabcdABC",MP,[{capture,first,index}]), ?line {match,["ABCabcdABC"]} = re:run("ABCabcdABC",MP,[{capture,first,list}]),
- ?line {match,[<<"ABCabcdABC">>]} = re:run("ABCabcdABC",MP,[{capture,first,binary}]),
-
- ?line {match,[{3,4}]} = re:run("ABCabcdABC",MP,[{capture,all_but_first}]),
- ?line {match,[{3,4}]} = re:run("ABCabcdABC",MP,[{capture,all_but_first,index}]),
- ?line {match,["abcd"]} = re:run("ABCabcdABC",MP,[{capture,all_but_first,list}]),
- ?line {match,[<<"abcd">>]} = re:run("ABCabcdABC",MP,[{capture,all_but_first,binary}]),
-
- ?line match = re:run("ABCabcdABC",MP,[{capture,none}]),
- ?line match = re:run("ABCabcdABC",MP,[{capture,none,index}]),
- ?line match = re:run("ABCabcdABC",MP,[{capture,none,list}]),
- ?line match = re:run("ABCabcdABC",MP,[{capture,none,binary}]),
-
- ?line {ok,MP2} = re:compile(".*(?<FOO>abcd).*"),
- ?line {match,[{3,4}]} = re:run("ABCabcdABC",MP2,[{capture,[1]}]),
- ?line {match,[{3,4}]} = re:run("ABCabcdABC",MP2,[{capture,['FOO']}]),
- ?line {match,[{3,4}]} = re:run("ABCabcdABC",MP2,[{capture,["FOO"]}]),
- ?line {match,["abcd"]} = re:run("ABCabcdABC",MP2,[{capture,["FOO"],list}]),
- ?line {match,[<<"abcd">>]} = re:run("ABCabcdABC",MP2,[{capture,["FOO"],binary}]),
-
- ?line {match,[{-1,0}]} = re:run("ABCabcdABC",MP2,[{capture,[200]}]),
- ?line {match,[{-1,0}]} = re:run("ABCabcdABC",MP2,[{capture,['BAR']}]),
- ?line {match,[""]} = re:run("ABCabcdABC",MP2,[{capture,[200],list}]),
- ?line {match,[""]} = re:run("ABCabcdABC",MP2,[{capture,['BAR'],list}]),
- ?line {match,[<<>>]} = re:run("ABCabcdABC",MP2,[{capture,[200],binary}]),
- ?line {match,[<<>>]} = re:run("ABCabcdABC",MP2,[{capture,['BAR'],binary}]),
-
- ?line {ok, MP3} = re:compile(".*((?<FOO>abdd)|a(..d)).*"),
- ?line {match,[{0,10},{3,4},{-1,0},{4,3}]} = re:run("ABCabcdABC",MP3,[]),
- ?line {match,[{0,10},{3,4},{-1,0},{4,3}]} = re:run("ABCabcdABC",MP3,[{capture,all,index}]),
- ?line {match,[<<"ABCabcdABC">>,<<"abcd">>,<<>>,<<"bcd">>]} = re:run("ABCabcdABC",MP3,[{capture,all,binary}]),
- ?line {match,["ABCabcdABC","abcd",[],"bcd"]} = re:run("ABCabcdABC",MP3,[{capture,all,list}]),
+ rtest("ABCabcdABC","abc",[],[],true),
+ rtest("ABCabcdABC","abc",[anchored],[],false),
+ %% Anchored in run overrides unanchored in compilation
+ rtest("ABCabcdABC","abc",[],[anchored],false),
+
+ rtest("","a?b?",[],[],true),
+ rtest("","a?b?",[],[notempty],false),
+
+ rtest("abc","^a",[],[],true),
+ rtest("abc","^a",[],[notbol],false),
+ rtest("ab\nc","^a",[multiline],[],true),
+ rtest("ab\nc","^a",[multiline],[notbol],false),
+ rtest("ab\nc","^c",[multiline],[notbol],true),
+
+ rtest("abc","c$",[],[],true),
+ rtest("abc","c$",[],[noteol],false),
+
+ rtest("ab\nc","b$",[multiline],[],true),
+ rtest("ab\nc","c$",[multiline],[],true),
+ rtest("ab\nc","b$",[multiline],[noteol],true),
+ rtest("ab\nc","c$",[multiline],[noteol],false),
+
+ rtest("abc","ab",[],[{offset,0}],true),
+ rtest("abc","ab",[],[{offset,1}],false),
+
+ rtest("abcdABCabcABC\nD","abcd.*D",[],[],false),
+ rtest("abcdABCabcABC\nD","abcd.*D",[],[{newline,cr}],true),
+ rtest("abcdABCabcABC\rD","abcd.*D",[],[],true),
+ rtest("abcdABCabcABC\rD","abcd.*D",[{newline,cr}],[{newline,lf}],true),
+ rtest("abcdABCabcd\r\n","abcd$",[],[{newline,lf}],false),
+ rtest("abcdABCabcd\r\n","abcd$",[],[{newline,cr}],false),
+ rtest("abcdABCabcd\r\n","abcd$",[],[{newline,crlf}],true),
+
+ rtest("abcdABCabcd\r","abcd$",[],[{newline,crlf}],false),
+ rtest("abcdABCabcd\n","abcd$",[],[{newline,crlf}],false),
+ rtest("abcdABCabcd\r\n","abcd$",[],[{newline,anycrlf}],true),
+
+ rtest("abcdABCabcd\r","abcd$",[],[{newline,anycrlf}],true),
+ rtest("abcdABCabcd\n","abcd$",[],[{newline,anycrlf}],true),
+
+ {ok,MP} = re:compile(".*(abcd).*"),
+ {match,[{0,10},{3,4}]} = re:run("ABCabcdABC",MP,[]),
+ {match,[{0,10},{3,4}]} = re:run("ABCabcdABC",MP,[{capture,all}]),
+ {match,[{0,10},{3,4}]} = re:run("ABCabcdABC",MP,[{capture,all,index}]),
+ {match,["ABCabcdABC","abcd"]} = re:run("ABCabcdABC",MP,[{capture,all,list}]),
+ {match,[<<"ABCabcdABC">>,<<"abcd">>]} = re:run("ABCabcdABC",MP,[{capture,all,binary}]),
+ {match,[{0,10}]} = re:run("ABCabcdABC",MP,[{capture,first}]),
+ {match,[{0,10}]} = re:run("ABCabcdABC",MP,[{capture,first,index}]), ?line {match,["ABCabcdABC"]} = re:run("ABCabcdABC",MP,[{capture,first,list}]),
+ {match,[<<"ABCabcdABC">>]} = re:run("ABCabcdABC",MP,[{capture,first,binary}]),
+
+ {match,[{3,4}]} = re:run("ABCabcdABC",MP,[{capture,all_but_first}]),
+ {match,[{3,4}]} = re:run("ABCabcdABC",MP,[{capture,all_but_first,index}]),
+ {match,["abcd"]} = re:run("ABCabcdABC",MP,[{capture,all_but_first,list}]),
+ {match,[<<"abcd">>]} = re:run("ABCabcdABC",MP,[{capture,all_but_first,binary}]),
+
+ match = re:run("ABCabcdABC",MP,[{capture,none}]),
+ match = re:run("ABCabcdABC",MP,[{capture,none,index}]),
+ match = re:run("ABCabcdABC",MP,[{capture,none,list}]),
+ match = re:run("ABCabcdABC",MP,[{capture,none,binary}]),
+
+ {ok,MP2} = re:compile(".*(?<FOO>abcd).*"),
+ {match,[{3,4}]} = re:run("ABCabcdABC",MP2,[{capture,[1]}]),
+ {match,[{3,4}]} = re:run("ABCabcdABC",MP2,[{capture,['FOO']}]),
+ {match,[{3,4}]} = re:run("ABCabcdABC",MP2,[{capture,["FOO"]}]),
+ {match,["abcd"]} = re:run("ABCabcdABC",MP2,[{capture,["FOO"],list}]),
+ {match,[<<"abcd">>]} = re:run("ABCabcdABC",MP2,[{capture,["FOO"],binary}]),
+
+ {match,[{-1,0}]} = re:run("ABCabcdABC",MP2,[{capture,[200]}]),
+ {match,[{-1,0}]} = re:run("ABCabcdABC",MP2,[{capture,['BAR']}]),
+ {match,[""]} = re:run("ABCabcdABC",MP2,[{capture,[200],list}]),
+ {match,[""]} = re:run("ABCabcdABC",MP2,[{capture,['BAR'],list}]),
+ {match,[<<>>]} = re:run("ABCabcdABC",MP2,[{capture,[200],binary}]),
+ {match,[<<>>]} = re:run("ABCabcdABC",MP2,[{capture,['BAR'],binary}]),
+
+ {ok, MP3} = re:compile(".*((?<FOO>abdd)|a(..d)).*"),
+ {match,[{0,10},{3,4},{-1,0},{4,3}]} = re:run("ABCabcdABC",MP3,[]),
+ {match,[{0,10},{3,4},{-1,0},{4,3}]} = re:run("ABCabcdABC",MP3,[{capture,all,index}]),
+ {match,[<<"ABCabcdABC">>,<<"abcd">>,<<>>,<<"bcd">>]} = re:run("ABCabcdABC",MP3,[{capture,all,binary}]),
+ {match,["ABCabcdABC","abcd",[],"bcd"]} = re:run("ABCabcdABC",MP3,[{capture,all,list}]),
ok.
-
-
-combined_options(doc) ->
- ["Test compile options given directly to run"];
+
+
+%% Test compile options given directly to run.
combined_options(Config) when is_list(Config) ->
- ?line ok = crtest("ABDabcdABCD","abcd",[],true,{match,[{3,4}]}),
- ?line ok = crtest("ABDabcdABCD","abcd",[anchored],true,nomatch),
- ?line ok = crtest("ABDabcdABCD",".*abcd",[anchored],true,{match,[{0,7}]}),
- ?line ok = crtest("ABCabcdABC","ABCD",[],true,nomatch),
- ?line ok = crtest("ABCabcdABC","ABCD",[caseless],true,{match,[{3,4}]}),
- ?line ok = crtest("abcdABC\n","ABC$",[],true,{match,[{4,3}]}),
- ?line ok = crtest("abcdABC\n","ABC$",[dollar_endonly],true,nomatch),
- ?line ok = crtest("abcdABC\n","ABC.",[],true,nomatch),
- ?line ok = crtest("abcdABC\n","ABC.",[dotall],true,{match,[{4,4}]}),
- ?line ok = crtest("abcdABCD","ABC .",[],true,nomatch),
- ?line ok = crtest("abcdABCD","ABC .",[extended],true,{match,[{4,4}]}),
- ?line ok = crtest("abcd\nABCD","ABC",[],true,{match,[{5,3}]}),
- ?line ok = crtest("abcd\nABCD","ABC",[firstline],true,nomatch),
- ?line ok = crtest("abcd\nABCD","^ABC",[],true,nomatch),
- ?line ok = crtest("abcd\nABCD","^ABC",[multiline],true,{match,[{5,3}]}),
- ?line ok = crtest("abcdABCD","(ABC)",[],true,{match,[{4,3},{4,3}]}),
- ?line ok = crtest("abcdABCD","(ABC)",[no_auto_capture],true,{match,[{4,3}]}),
- ?line ok = crtest(notused,"(?<FOO>ABC)|(?<FOO>DEF)",[],false,notused),
- ?line ok = crtest("abcdABCD","(?<FOO>ABC)|(?<FOO>DEF)",[dupnames],true,{match,[{4,3},{4,3}]}),
- ?line ok = crtest("abcdABCDabcABCD","abcd.*D",[],true,{match,[{0,15}]}),
- ?line ok = crtest("abcdABCDabcABCD","abcd.*D",[ungreedy],true,{match,[{0,8}]}),
- ?line ok = ctest("abcdABCabcABC\nD","abcd.*D",[],true,nomatch),
- ?line ok = crtest("abcdABCabcABC\nD","abcd.*D",[{newline,cr}],true,{match,[{0,15}]}),
- ?line ok = crtest("abcdABCabcABC\rD","abcd.*D",[],true,{match,[{0,15}]}),
- ?line ok = crtest("abcdABCabcABC\rD","abcd.*D",[{newline,lf}],true,{match,[{0,15}]}),
- ?line ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,lf}],true,nomatch),
- ?line ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,cr}],true,nomatch),
- ?line ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,crlf}],true,{match,[{7,4}]}),
-
- ?line ok = crtest("abcdABCabcd\r","abcd$",[{newline,crlf}],true,nomatch),
- ?line ok = crtest("abcdABCabcd\n","abcd$",[{newline,crlf}],true,nomatch),
- ?line ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}),
-
- ?line ok = crtest("abcdABCabcd\r","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}),
- ?line ok = crtest("abcdABCabcd\n","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}),
-
- ?line ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,anycrlf},{capture,all,list}],true,{match,["abcd"]}),
-
- ?line ok = crtest("abcdABCabcd\r","abcd$",[{newline,anycrlf},{capture,all,list}],true,{match,["abcd"]}),
-
- ?line ok = crtest("abcdABCabcd\n","abcd$",[{newline,anycrlf},{capture,all,list}],true,{match,["abcd"]}),
-
- ?line ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,anycrlf},{capture,all,binary}],true,{match,[<<"abcd">>]}),
-
- ?line ok = crtest("abcdABCabcd\r","abcd$",[{newline,anycrlf},{capture,all,binary}],true,{match,[<<"abcd">>]}),
- ?line ok = crtest("abcdABCabcd\n","abcd$",[{newline,anycrlf},{capture,all,binary}],true,{match,[<<"abcd">>]}),
-
- % Check that unique run-options fail in compile only case:
- ?line {'EXIT',{badarg,_}} = (catch re:compile("abcd$",[{newline,anycrlf},{capture,all,binary}])),
- ?line {'EXIT',{badarg,_}} = (catch re:compile("abcd$",[{newline,anycrlf},{offset,3}])),
- ?line {'EXIT',{badarg,_}} = (catch re:compile("abcd$",[{newline,anycrlf},notempty])),
- ?line {'EXIT',{badarg,_}} = (catch re:compile("abcd$",[{newline,anycrlf},notbol])),
- ?line {'EXIT',{badarg,_}} = (catch re:compile("abcd$",[{newline,anycrlf},noteol])),
-
-
- ?line {match,_} = re:run("abcdABCabcd\r\n","abcd$",[{newline,crlf}]),
- ?line nomatch = re:run("abcdABCabcd\r\nefgh","abcd$",[{newline,crlf}]),
- ?line {match,_} = re:run("abcdABCabcd\r\nefgh","abcd$",[{newline,crlf},multiline]),
- ?line nomatch = re:run("abcdABCabcd\r\nefgh","efgh$",[{newline,crlf},multiline,noteol]),
- ?line {match,_} = re:run("abcdABCabcd\r\nefgh","abcd$",[{newline,crlf},multiline,noteol]),
- ?line {match,_} = re:run("abcdABCabcd\r\nefgh","^abcd",[{newline,crlf},multiline,noteol]),
- ?line nomatch = re:run("abcdABCabcd\r\nefgh","^abcd",[{newline,crlf},multiline,notbol]),
- ?line {match,_} = re:run("abcdABCabcd\r\nefgh","^efgh",[{newline,crlf},multiline,notbol]),
- ?line {match,_} = re:run("ABC\nD","[a-z]*",[{newline,crlf}]),
- ?line nomatch = re:run("ABC\nD","[a-z]*",[{newline,crlf},notempty]),
+ ok = crtest("ABDabcdABCD","abcd",[],true,{match,[{3,4}]}),
+ ok = crtest("ABDabcdABCD","abcd",[anchored],true,nomatch),
+ ok = crtest("ABDabcdABCD",".*abcd",[anchored],true,{match,[{0,7}]}),
+ ok = crtest("ABCabcdABC","ABCD",[],true,nomatch),
+ ok = crtest("ABCabcdABC","ABCD",[caseless],true,{match,[{3,4}]}),
+ ok = crtest("abcdABC\n","ABC$",[],true,{match,[{4,3}]}),
+ ok = crtest("abcdABC\n","ABC$",[dollar_endonly],true,nomatch),
+ ok = crtest("abcdABC\n","ABC.",[],true,nomatch),
+ ok = crtest("abcdABC\n","ABC.",[dotall],true,{match,[{4,4}]}),
+ ok = crtest("abcdABCD","ABC .",[],true,nomatch),
+ ok = crtest("abcdABCD","ABC .",[extended],true,{match,[{4,4}]}),
+ ok = crtest("abcd\nABCD","ABC",[],true,{match,[{5,3}]}),
+ ok = crtest("abcd\nABCD","ABC",[firstline],true,nomatch),
+ ok = crtest("abcd\nABCD","^ABC",[],true,nomatch),
+ ok = crtest("abcd\nABCD","^ABC",[multiline],true,{match,[{5,3}]}),
+ ok = crtest("abcdABCD","(ABC)",[],true,{match,[{4,3},{4,3}]}),
+ ok = crtest("abcdABCD","(ABC)",[no_auto_capture],true,{match,[{4,3}]}),
+ ok = crtest(notused,"(?<FOO>ABC)|(?<FOO>DEF)",[],false,notused),
+ ok = crtest("abcdABCD","(?<FOO>ABC)|(?<FOO>DEF)",[dupnames],true,{match,[{4,3},{4,3}]}),
+ ok = crtest("abcdABCDabcABCD","abcd.*D",[],true,{match,[{0,15}]}),
+ ok = crtest("abcdABCDabcABCD","abcd.*D",[ungreedy],true,{match,[{0,8}]}),
+ ok = ctest("abcdABCabcABC\nD","abcd.*D",[],true,nomatch),
+ ok = crtest("abcdABCabcABC\nD","abcd.*D",[{newline,cr}],true,{match,[{0,15}]}),
+ ok = crtest("abcdABCabcABC\rD","abcd.*D",[],true,{match,[{0,15}]}),
+ ok = crtest("abcdABCabcABC\rD","abcd.*D",[{newline,lf}],true,{match,[{0,15}]}),
+ ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,lf}],true,nomatch),
+ ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,cr}],true,nomatch),
+ ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,crlf}],true,{match,[{7,4}]}),
+
+ ok = crtest("abcdABCabcd\r","abcd$",[{newline,crlf}],true,nomatch),
+ ok = crtest("abcdABCabcd\n","abcd$",[{newline,crlf}],true,nomatch),
+ ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}),
+
+ ok = crtest("abcdABCabcd\r","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}),
+ ok = crtest("abcdABCabcd\n","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}),
+
+ ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,anycrlf},{capture,all,list}],true,{match,["abcd"]}),
+
+ ok = crtest("abcdABCabcd\r","abcd$",[{newline,anycrlf},{capture,all,list}],true,{match,["abcd"]}),
+
+ ok = crtest("abcdABCabcd\n","abcd$",[{newline,anycrlf},{capture,all,list}],true,{match,["abcd"]}),
+
+ ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,anycrlf},{capture,all,binary}],true,{match,[<<"abcd">>]}),
+
+ ok = crtest("abcdABCabcd\r","abcd$",[{newline,anycrlf},{capture,all,binary}],true,{match,[<<"abcd">>]}),
+ ok = crtest("abcdABCabcd\n","abcd$",[{newline,anycrlf},{capture,all,binary}],true,{match,[<<"abcd">>]}),
+
+ %% Check that unique run-options fail in compile only case:
+ {'EXIT',{badarg,_}} = (catch re:compile("abcd$",[{newline,anycrlf},{capture,all,binary}])),
+ {'EXIT',{badarg,_}} = (catch re:compile("abcd$",[{newline,anycrlf},{offset,3}])),
+ {'EXIT',{badarg,_}} = (catch re:compile("abcd$",[{newline,anycrlf},notempty])),
+ {'EXIT',{badarg,_}} = (catch re:compile("abcd$",[{newline,anycrlf},notbol])),
+ {'EXIT',{badarg,_}} = (catch re:compile("abcd$",[{newline,anycrlf},noteol])),
+
+
+ {match,_} = re:run("abcdABCabcd\r\n","abcd$",[{newline,crlf}]),
+ nomatch = re:run("abcdABCabcd\r\nefgh","abcd$",[{newline,crlf}]),
+ {match,_} = re:run("abcdABCabcd\r\nefgh","abcd$",[{newline,crlf},multiline]),
+ nomatch = re:run("abcdABCabcd\r\nefgh","efgh$",[{newline,crlf},multiline,noteol]),
+ {match,_} = re:run("abcdABCabcd\r\nefgh","abcd$",[{newline,crlf},multiline,noteol]),
+ {match,_} = re:run("abcdABCabcd\r\nefgh","^abcd",[{newline,crlf},multiline,noteol]),
+ nomatch = re:run("abcdABCabcd\r\nefgh","^abcd",[{newline,crlf},multiline,notbol]),
+ {match,_} = re:run("abcdABCabcd\r\nefgh","^efgh",[{newline,crlf},multiline,notbol]),
+ {match,_} = re:run("ABC\nD","[a-z]*",[{newline,crlf}]),
+ nomatch = re:run("ABC\nD","[a-z]*",[{newline,crlf},notempty]),
ok.
-replace_autogen(doc) ->
- ["Test replace with autogenerated erlang module"];
+%% Test replace with autogenerated erlang module.
replace_autogen(Config) when is_list(Config) ->
- Dog = ?t:timetrap(?t:minutes(3)),
re_testoutput1_replacement_test:run(),
- ?t:timetrap_cancel(Dog),
ok.
-global_capture(doc) ->
- ["Tests capture options together with global searching"];
+%% Test capture options together with global searching.
global_capture(Config) when is_list(Config) ->
- Dog = ?t:timetrap(?t:minutes(3)),
- ?line {match,[{3,4}]} = re:run("ABCabcdABC",".*(?<FOO>abcd).*",[{capture,[1]}]),
- ?line {match,[{10,4}]} = re:run("ABCabcdABCabcdA",".*(?<FOO>abcd).*",[{capture,[1]}]),
- ?line {match,[[{10,4}]]} = re:run("ABCabcdABCabcdA",".*(?<FOO>abcd).*",[global,{capture,[1]}]),
- ?line {match,[{3,4}]} = re:run("ABCabcdABC",".*(?<FOO>abcd).*",[{capture,['FOO']}]),
- ?line {match,[{10,4}]} = re:run("ABCabcdABCabcdA",".*(?<FOO>abcd).*",[{capture,['FOO']}]),
- ?line {match,[[{10,4}]]} = re:run("ABCabcdABCabcdA",".*(?<FOO>abcd).*",[global,{capture,['FOO']}]),
- ?line {match,[[{3,4},{3,4}],[{10,4},{10,4}]]} = re:run("ABCabcdABCabcdA","(?<FOO>abcd)",[global]),
- ?line {match,[[{3,4},{3,4}],[{10,4},{10,4}]]} = re:run("ABCabcdABCabcdA","(?<FOO>abcd)",[global,{capture,all}]),
- ?line {match,[[{3,4},{3,4}],[{10,4},{10,4}]]} = re:run("ABCabcdABCabcdA","(?<FOO>abcd)",[global,{capture,all,index}]),
- ?line {match,[[{3,4}],[{10,4}]]} = re:run("ABCabcdABCabcdA","(?<FOO>abcd)",[global,{capture,first}]),
- ?line {match,[[{3,4}],[{10,4}]]} = re:run("ABCabcdABCabcdA","(?<FOO>abcd)",[global,{capture,all_but_first}]),
- ?line {match,[[<<"bcd">>],[<<"bcd">>]]} = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,all_but_first,binary}]),
- ?line {match,[["bcd"],["bcd"]]} = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,all_but_first,list}]),
- ?line {match,[["abcd","bcd"],["abcd","bcd"]]} = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,all,list}]),
- ?line {match,[[<<"abcd">>,<<"bcd">>],[<<"abcd">>,<<"bcd">>]]} = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,all,binary}]),
- ?line {match,[[{3,4},{4,3}],[{10,4},{11,3}]]} = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,all,index}]),
- ?line match = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,none,index}]),
- ?line match = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,none,binary}]),
- ?line match = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,none,list}]),
- ?line {match,[[<<195,133,98,99,100>>,<<"bcd">>],[<<"abcd">>,<<"bcd">>]]} = re:run("ABCÅbcdABCabcdA",".(?<FOO>bcd)",[global,{capture,all,binary},unicode]),
- ?line {match,[["Åbcd","bcd"],["abcd","bcd"]]} = re:run(<<"ABC",8#303,8#205,"bcdABCabcdA">>,".(?<FOO>bcd)",[global,{capture,all,list},unicode]),
- ?line {match,[["Åbcd","bcd"],["abcd","bcd"]]} = re:run("ABCÅbcdABCabcdA",".(?<FOO>bcd)",[global,{capture,all,list},unicode]),
- ?line {match,[[{3,5},{5,3}],[{11,4},{12,3}]]} = re:run("ABCÅbcdABCabcdA",".(?<FOO>bcd)",[global,{capture,all,index},unicode]),
- ?t:timetrap_cancel(Dog),
+ {match,[{3,4}]} = re:run("ABCabcdABC",".*(?<FOO>abcd).*",[{capture,[1]}]),
+ {match,[{10,4}]} = re:run("ABCabcdABCabcdA",".*(?<FOO>abcd).*",[{capture,[1]}]),
+ {match,[[{10,4}]]} = re:run("ABCabcdABCabcdA",".*(?<FOO>abcd).*",[global,{capture,[1]}]),
+ {match,[{3,4}]} = re:run("ABCabcdABC",".*(?<FOO>abcd).*",[{capture,['FOO']}]),
+ {match,[{10,4}]} = re:run("ABCabcdABCabcdA",".*(?<FOO>abcd).*",[{capture,['FOO']}]),
+ {match,[[{10,4}]]} = re:run("ABCabcdABCabcdA",".*(?<FOO>abcd).*",[global,{capture,['FOO']}]),
+ {match,[[{3,4},{3,4}],[{10,4},{10,4}]]} = re:run("ABCabcdABCabcdA","(?<FOO>abcd)",[global]),
+ {match,[[{3,4},{3,4}],[{10,4},{10,4}]]} = re:run("ABCabcdABCabcdA","(?<FOO>abcd)",[global,{capture,all}]),
+ {match,[[{3,4},{3,4}],[{10,4},{10,4}]]} = re:run("ABCabcdABCabcdA","(?<FOO>abcd)",[global,{capture,all,index}]),
+ {match,[[{3,4}],[{10,4}]]} = re:run("ABCabcdABCabcdA","(?<FOO>abcd)",[global,{capture,first}]),
+ {match,[[{3,4}],[{10,4}]]} = re:run("ABCabcdABCabcdA","(?<FOO>abcd)",[global,{capture,all_but_first}]),
+ {match,[[<<"bcd">>],[<<"bcd">>]]} = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,all_but_first,binary}]),
+ {match,[["bcd"],["bcd"]]} = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,all_but_first,list}]),
+ {match,[["abcd","bcd"],["abcd","bcd"]]} = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,all,list}]),
+ {match,[[<<"abcd">>,<<"bcd">>],[<<"abcd">>,<<"bcd">>]]} = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,all,binary}]),
+ {match,[[{3,4},{4,3}],[{10,4},{11,3}]]} = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,all,index}]),
+ match = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,none,index}]),
+ match = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,none,binary}]),
+ match = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,none,list}]),
+ {match,[[<<195,133,98,99,100>>,<<"bcd">>],[<<"abcd">>,<<"bcd">>]]} = re:run("ABCÅbcdABCabcdA",".(?<FOO>bcd)",[global,{capture,all,binary},unicode]),
+ {match,[["Åbcd","bcd"],["abcd","bcd"]]} = re:run(<<"ABC",8#303,8#205,"bcdABCabcdA">>,".(?<FOO>bcd)",[global,{capture,all,list},unicode]),
+ {match,[["Åbcd","bcd"],["abcd","bcd"]]} = re:run("ABCÅbcdABCabcdA",".(?<FOO>bcd)",[global,{capture,all,list},unicode]),
+ {match,[[{3,5},{5,3}],[{11,4},{12,3}]]} = re:run("ABCÅbcdABCabcdA",".(?<FOO>bcd)",[global,{capture,all,index},unicode]),
ok.
-replace_input_types(doc) ->
- ["Tests replace with different input types"];
+%% Test replace with different input types.
replace_input_types(Config) when is_list(Config) ->
- Dog = ?t:timetrap(?t:minutes(3)),
- ?line <<"abcd">> = re:replace("abcd","Z","X",[{return,binary},unicode]),
- ?line <<"abcd">> = re:replace("abcd","\x{400}","X",[{return,binary},unicode]),
- ?line <<"a",208,128,"cd">> = re:replace(<<"abcd">>,"b","\x{400}",[{return,binary},unicode]),
- ?t:timetrap_cancel(Dog),
+ <<"abcd">> = re:replace("abcd","Z","X",[{return,binary},unicode]),
+ <<"abcd">> = re:replace("abcd","\x{400}","X",[{return,binary},unicode]),
+ <<"a",208,128,"cd">> = re:replace(<<"abcd">>,"b","\x{400}",[{return,binary},unicode]),
ok.
-replace_return(doc) ->
- ["Tests return options of replace together with global searching"];
+%% Test return options of replace together with global searching.
replace_return(Config) when is_list(Config) ->
- Dog = ?t:timetrap(?t:minutes(3)),
{'EXIT',{badarg,_}} = (catch re:replace("na","(a","")),
ok = replacetest(<<"nisse">>,"i","a",[{return,binary}],<<"nasse">>),
ok = replacetest("ABC\305abcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,binary}],<<"ABCÅXABCXA">>),
@@ -339,7 +324,6 @@ replace_return(Config) when is_list(Config) ->
ok = replacetest("a\x{400}bcd","d","X",[global,{return,binary},unicode],<<"a",208,128,"bcX">>),
ok = replacetest("a\x{400}bcd","Z","X",[global,{return,list},unicode],"a\x{400}bcd"),
ok = replacetest("a\x{400}bcd","Z","X",[global,{return,binary},unicode],<<"a",208,128,"bcd">>),
- ?t:timetrap_cancel(Dog),
ok.
rtest(Subj, RE, Copt, Ropt, true) ->
@@ -412,18 +396,13 @@ copt(ungreedy) -> true;
copt(unicode) -> true;
copt(_) -> false.
-split_autogen(doc) ->
- ["Test split with autogenerated erlang module"];
+%% Test split with autogenerated erlang module.
split_autogen(Config) when is_list(Config) ->
- Dog = ?t:timetrap(?t:minutes(3)),
re_testoutput1_split_test:run(),
- ?t:timetrap_cancel(Dog),
ok.
-split_options(doc) ->
- ["Test special options to split."];
+%% Test special options to split.
split_options(Config) when is_list(Config) ->
- Dog = ?t:timetrap(?t:minutes(1)),
ok = splittest("a b c ","( )",[group,trim],[[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>]]),
ok = splittest("a b c ","( )",[group,{parts,0}],[[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>]]),
ok = splittest("a b c ","( )",[{parts,infinity},group],[[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<>>]]),
@@ -439,27 +418,23 @@ split_options(Config) when is_list(Config) ->
{'EXIT',{badarg,_}} = (catch re:split("a b c d","( +)",[{parts,banan}])),
{'EXIT',{badarg,_}} = (catch re:split("a b c d","( +)",[{capture,all}])),
{'EXIT',{badarg,_}} = (catch re:split("a b c d","( +)",[{capture,[],binary}])),
- % Parts 0 is equal to no parts specification (implicit strip)
+ %% Parts 0 is equal to no parts specification (implicit strip)
ok = splittest("a b c d","( *)",[{parts,0},{return,list}],["a"," ","b"," ","c"," ","d"]),
- ?t:timetrap_cancel(Dog),
ok.
-
+
join([]) -> [];
join([A]) -> [A];
join([H|T]) -> [H,<<":">>|join(T)].
-split_specials(doc) ->
- ["Some special cases of split that are easy to get wrong."];
+%% Some special cases of split that are easy to get wrong.
split_specials(Config) when is_list(Config) ->
%% More or less just to remember these icky cases
- Dog = ?t:timetrap(?t:minutes(1)),
- ?line <<"::abd:f">> =
+ <<"::abd:f">> =
iolist_to_binary(join(re:split("abdf","^(?!(ab)de|x)(abd)(f)",[trim]))),
- ?line <<":abc2xyzabc3">> =
+ <<":abc2xyzabc3">> =
iolist_to_binary(join(re:split("abc1abc2xyzabc3","\\Aabc.",[trim]))),
- ?t:timetrap_cancel(Dog),
ok.
-
+
%% Test that errors are handled correctly by the erlang code.
error_handling(_Config) ->
@@ -470,26 +445,26 @@ error_handling(_Config) ->
false ->
error_handling()
end.
-
+
error_handling() ->
- % This test checks the exception tuples manufactured in the erlang
- % code to hide the trapping from the user at least when it comes to errors
- Dog = ?t:timetrap(?t:minutes(1)),
- % The malformed precomiled RE is detected after
- % the trap to re:grun from grun, in the grun function clause
- % that handles precompiled expressions
+ %% This test checks the exception tuples manufactured in the erlang
+ %% code to hide the trapping from the user at least when it comes to errors
+
+ %% The malformed precomiled RE is detected after
+ %% the trap to re:grun from grun, in the grun function clause
+ %% that handles precompiled expressions
{'EXIT',{badarg,[{re,run,["apa",{1,2,3,4},[global]],_},
{?MODULE,error_handling,0,_} | _]}} =
(catch re:run("apa",{1,2,3,4},[global])),
- % An invalid capture list will also cause a badarg late,
- % but with a non pre compiled RE, the exception should be thrown by the
- % grun function clause that handles RE's compiled implicitly by
- % the run/3 BIF before trapping.
+ %% An invalid capture list will also cause a badarg late,
+ %% but with a non pre compiled RE, the exception should be thrown by the
+ %% grun function clause that handles RE's compiled implicitly by
+ %% the run/3 BIF before trapping.
{'EXIT',{badarg,[{re,run,["apa","p",[{capture,[1,{a}]},global]],_},
{?MODULE,error_handling,0,_} | _]}} =
(catch re:run("apa","p",[{capture,[1,{a}]},global])),
- % And so the case of a precompiled expression together with
- % a compile-option (binary and list subject):
+ %% And so the case of a precompiled expression together with
+ %% a compile-option (binary and list subject):
{ok,RE} = re:compile("(p)"),
{match,[[{1,1},{1,1}]]} = re:run(<<"apa">>,RE,[global]),
{match,[[{1,1},{1,1}]]} = re:run("apa",RE,[global]),
@@ -509,7 +484,7 @@ error_handling() ->
{error, {compile, {_,_}}} = re:run("apa","(p",[report_errors]),
{'EXIT',{badarg,_}} = (catch re:run("apa","(p",[global])),
{error, {compile, {_,_}}} = re:run("apa","(p",[report_errors,global]),
- % Badly formed options
+ %% Badly formed options
{'EXIT',{badarg,_}} = (catch re:run(<<"apa">>,RE,["global"])),
{'EXIT',{badarg,_}} = (catch re:run(<<"apa">>,RE,[{offset,-1}])),
{'EXIT',{badarg,_}} = (catch re:run(<<"apa">>,RE,[{offset,ett}])),
@@ -536,7 +511,7 @@ error_handling() ->
{'EXIT',{badarg,_}} = (catch re:run(<<"apa",2:2>>,<<"(p)">>,[{capture,[0,1],binary}])),
<<_:4,Temp:3/binary,_:4>> = <<38,23,6,18>>,
{match,[{1,1},{1,1}]} = re:run(Temp,<<"(p)">>,[]), % Unaligned works
- % The replace errors:
+ %% The replace errors:
{'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[]],_},
{?MODULE,error_handling,0,_} | _]}} =
(catch re:replace("apa",{1,2,3,4},"X",[])),
@@ -572,13 +547,13 @@ error_handling() ->
(catch iolist_to_binary(re:replace("apa","p","X",
[{return,banana}]))),
{'EXIT',{badarg,_}} = (catch re:replace("apa","(p","X",[])),
- % Badarg, not compile error.
+ %% Badarg, not compile error.
{'EXIT',{badarg,[{re,replace,
["apa","(p","X",[{return,banana}]],_},
{?MODULE,error_handling,0,_} | _]}} =
(catch iolist_to_binary(re:replace("apa","(p","X",
[{return,banana}]))),
- % And the split errors:
+ %% And the split errors:
[<<"a">>,<<"a">>] = (catch re:split("apa","p",[])),
[<<"a">>,<<"p">>,<<"a">>] = (catch re:split("apa",RE,[])),
{'EXIT',{badarg,[{re,split,["apa","p",[report_errors]],_},
@@ -618,34 +593,31 @@ error_handling() ->
{?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa",RE,[banana])),
{'EXIT',{badarg,_}} = (catch re:split("apa","(p")),
- %Exception on bad argument, not compilation error
+ %%Exception on bad argument, not compilation error
{'EXIT',{badarg,[{re,split,
["apa",
"(p",
[banana]],_},
{?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa","(p",[banana])),
- ?t:timetrap_cancel(Dog),
ok.
-
-pcre_cve_2008_2371(doc) ->
- "Fix as in http://vcs.pcre.org/viewvc?revision=360&view=revision";
+
+%% Fix as in http://vcs.pcre.org/viewvc?revision=360&view=revision
pcre_cve_2008_2371(Config) when is_list(Config) ->
%% Make sure it doesn't crash the emulator.
re:compile(<<"(?i)[\xc3\xa9\xc3\xbd]|[\xc3\xa9\xc3\xbdA]">>, [unicode]),
ok.
-pcre_compile_workspace_overflow(doc) ->
- "Patch from http://vcs.pcre.org/viewvc/code/trunk/pcre_compile.c?r1=504&r2=505&view=patch";
+%% Patch from
+%% http://vcs.pcre.org/viewvc/code/trunk/pcre_compile.c?r1=504&r2=505&view=patch
pcre_compile_workspace_overflow(Config) when is_list(Config) ->
N = 819,
- ?line {error,{"internal error: overran compiling workspace",799}} =
+ {error,{"internal error: overran compiling workspace",799}} =
re:compile([lists:duplicate(N, $(), lists:duplicate(N, $))]),
ok.
-re_infinite_loop(doc) ->
- "Make sure matches that really loop infinitely actually fail";
+
+%% Make sure matches that really loop infinitely actually fail.
re_infinite_loop(Config) when is_list(Config) ->
- Dog = ?t:timetrap(?t:minutes(1)),
Str =
"http:/www.flickr.com/slideShow/index.gne?group_id=&user_id=69845378@N0",
EMail_regex = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+"
@@ -657,20 +629,17 @@ re_infinite_loop(Config) when is_list(Config) ->
nomatch = re:run(Str, EMail_regex, [global]),
{error,match_limit} = re:run(Str, EMail_regex,[report_errors]),
{error,match_limit} = re:run(Str, EMail_regex,[report_errors,global]),
- ?t:timetrap_cancel(Dog),
ok.
-re_backwards_accented(doc) ->
- "Check for nasty bug where accented graphemes can make PCRE back past "
- "beginning of subject";
+
+%% Check for nasty bug where accented graphemes can make PCRE back
+%% past beginning of subject.
re_backwards_accented(Config) when is_list(Config) ->
- Dog = ?t:timetrap(?t:minutes(1)),
- ?line match = re:run(<<65,204,128,65,204,128,97,98,99>>,
- <<"\\X?abc">>,
- [unicode,{capture,none}]),
- ?t:timetrap_cancel(Dog),
+ match = re:run(<<65,204,128,65,204,128,97,98,99>>,
+ <<"\\X?abc">>,
+ [unicode,{capture,none}]),
ok.
-opt_dupnames(doc) ->
- "Check correct handling of dupnames option to re";
+
+%% Check correct handling of dupnames option to re.
opt_dupnames(Config) when is_list(Config) ->
Days = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],
_ = [ begin
@@ -704,9 +673,9 @@ opt_dupnames(Config) when is_list(Config) ->
"(?<DN>Sat)(?:urday)?",
[dupnames, {capture, ['Skrap','DN','Skrap2'],index}]),
{match,[{-1,0},{0,3},{-1,0}]} = re:run("Wednesday","(?<Skrap>.)(?<DN>Mon|Fri|Sun)(?:day)?(?<Skrap2>.)|"
- "(?<DN>Tue)(?:sday)?|(?<DN>Wed)nesday|(?<DN>Thu)(?:rsday)?|"
- "(?<DN>Sat)(?:urday)?",
- [dupnames, {capture, ['Skrap','DN','Skrap2'],index}]),
+ "(?<DN>Tue)(?:sday)?|(?<DN>Wed)nesday|(?<DN>Thu)(?:rsday)?|"
+ "(?<DN>Sat)(?:urday)?",
+ [dupnames, {capture, ['Skrap','DN','Skrap2'],index}]),
nomatch = re:run("Wednsday","(?<Skrap>.)(?<DN>Mon|Fri|Sun)(?:day)?(?<Skrap2>.)|"
"(?<DN>Tue)(?:sday)?|(?<DN>Wed)nesday|(?<DN>Thu)(?:rsday)?|"
"(?<DN>Sat)(?:urday)?",
@@ -758,8 +727,7 @@ opt_dupnames(Config) when is_list(Config) ->
"h","a","n","T","e","then"],binary}]),
ok.
-opt_all_names(doc) ->
- "Test capturing of all_names";
+%% Test capturing of all_names.
opt_all_names(Config) when is_list(Config) ->
Days = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],
{match,[{1,3},{0,1},{7,1}]} = re:run("SMondayX","(?<Skrap>.)(?<DN>Mon|Fri|Sun)(?:day)?(?<Skrap2>.)|"
@@ -767,10 +735,10 @@ opt_all_names(Config) when is_list(Config) ->
"(?<DN>Sat)(?:urday)?",
[dupnames, {capture, all_names,index}]),
{match,[{0,3},{-1,0},{-1,0}]} = re:run("Wednesday","(?<Skrap>.)(?<DN>Mon|Fri|Sun)(?:day)?(?<Skrap2>.)|"
- "(?<DN>Tue)(?:sday)?|(?<DN>Wed)nesday|(?<DN>Thu)(?:rsday)?|"
- "(?<DN>Sat)(?:urday)?",
- [dupnames, {capture, all_names,index}]),
-
+ "(?<DN>Tue)(?:sday)?|(?<DN>Wed)nesday|(?<DN>Thu)(?:rsday)?|"
+ "(?<DN>Sat)(?:urday)?",
+ [dupnames, {capture, all_names,index}]),
+
_ = [ begin
{match,[{0,3}]} =
re:run(Day,
@@ -809,7 +777,7 @@ opt_all_names(Config) when is_list(Config) ->
{match,[[<<>>,<<>>,<<"C">>],
[<<>>,<<>>,<<"C">>],
[<<>>,<<>>,<<"C">>]]} = re:run("CCC","(?<A>A)|(?<B>B)|(?<C>C)",
- [global,{capture, all_names, binary}]),
+ [global,{capture, all_names, binary}]),
{match,[[<<"C">>,<<>>],
[<<>>,<<"B">>],
[<<"C">>,<<>>]]} = re:run("CBC","(?<A>A)|(?<B>B)|(?<A>C)",
@@ -831,8 +799,7 @@ opt_all_names(Config) when is_list(Config) ->
[dupnames,{capture,all_names,binary}]),
ok.
-inspect(doc) ->
- "Test the minimal inspect function";
+%% Test the minimal inspect function.
inspect(Config) when is_list(Config)->
{ok,MP} = re:compile("(?<A>A)|(?<B>B)|(?<C>C)."),
{namelist,[<<"A">>,<<"B">>,<<"C">>]} = re:inspect(MP,namelist),
@@ -845,15 +812,13 @@ inspect(Config) when is_list(Config)->
{'EXIT',{badarg,_}} = (catch re:inspect({re_pattern,3,0,0,<<"kalle",2:2>>},namelist)),
ok.
-opt_no_start_optimize(doc) ->
- "Test that the no_start_optimize compilation flag works";
+%% Test that the no_start_optimize compilation flag works.
opt_no_start_optimize(Config) when is_list(Config) ->
{match, [{3,3}]} = re:run("DEFABC","(*COMMIT)ABC",[]), % Start optimization makes this result wrong!
nomatch = re:run("DEFABC","(*COMMIT)ABC",[no_start_optimize]), % This is the correct result...
ok.
-opt_never_utf(doc) ->
- "Check that the never_utf option works";
+%% Check that the never_utf option works.
opt_never_utf(Config) when is_list(Config) ->
{match,[{0,3}]} = re:run("ABC","ABC",[never_utf]),
{match,[{0,3}]} = re:run("ABC","(*UTF)ABC",[]),
@@ -867,29 +832,29 @@ opt_never_utf(Config) when is_list(Config) ->
{error,_} = (catch re:compile("(*UTF)ABC",[never_utf])),
{error,_} = (catch re:compile("(*UTF8)ABC",[never_utf])),
ok.
-opt_ucp(doc) ->
- "Check that the ucp option is passed to PCRE";
+
+%% Check that the ucp option is passed to PCRE.
opt_ucp(Config) when is_list(Config) ->
{match,[{0,1}]} = re:run([$a],"\\w",[unicode]),
{match,[{0,2}]} = re:run([229],"\\w",[unicode]), % Latin1 works without UCP, as we have a default
- % Latin1 table
+ %% Latin1 table
nomatch = re:run([1024],"\\w",[unicode]), % Latin1 word characters only, 1024 is not latin1
{match,[{0,2}]} = re:run([1024],"\\w",[unicode,ucp]), % Any Unicode word character works with 'ucp'
ok.
-match_limit(doc) ->
- "Check that the match_limit and match_limit_recursion options work";
+
+%% Check that the match_limit and match_limit_recursion options work.
match_limit(Config) when is_list(Config) ->
nomatch = re:run("aaaaaaaaaaaaaz","(a+)*zz",[]),
nomatch = re:run("aaaaaaaaaaaaaz","(a+)*zz",[{match_limit,3000}]),
nomatch = re:run("aaaaaaaaaaaaaz","(a+)*zz",[{match_limit_recursion,10}]),
nomatch = re:run("aaaaaaaaaaaaaz","(a+)*zz",[report_errors]),
{error,match_limit} = re:run("aaaaaaaaaaaaaz","(a+)*zz",[{match_limit,3000},
- report_errors]),
+ report_errors]),
{error,match_limit_recursion} =
re:run("aaaaaaaaaaaaaz","(a+)*zz",[{match_limit_recursion,10},
report_errors]),
{error,match_limit} = re:run("aaaaaaaaaaaaaz","(a+)*zz",[{match_limit,3000},
- report_errors,global]),
+ report_errors,global]),
{error,match_limit_recursion} =
re:run("aaaaaaaaaaaaaz","(a+)*zz",[{match_limit_recursion,10},
report_errors,global]),
@@ -902,9 +867,9 @@ match_limit(Config) when is_list(Config) ->
"aaaaaaaaaaaaaz" = re:replace("aaaaaaaaaaaaaz","(a+)*zz","!",
[{match_limit,3000},{return,list}]),
{'EXIT', {badarg,_}} = (catch re:replace("aaaaaaaaaaaaaz","(a+)*zz","!",
- [{match_limit_recursion,-1},{return,list}])),
+ [{match_limit_recursion,-1},{return,list}])),
{'EXIT', {badarg,_}} = (catch re:replace("aaaaaaaaaaaaaz","(a+)*zz","!",
- [{match_limit,-1},{return,list}])),
+ [{match_limit,-1},{return,list}])),
{'EXIT', {badarg,_}} = (catch re:run("aaaaaaaaaaaaaz","(a+)*zz",
[{match_limit_recursion,-1},
report_errors,global])),
@@ -912,9 +877,8 @@ match_limit(Config) when is_list(Config) ->
[{match_limit,-1},
report_errors,global])),
ok.
-sub_binaries(doc) ->
- "test that we get sub-binaries if subject is a binary and we "
- "capture binaries";
+%% Test that we get sub-binaries if subject is a binary and we capture
+%% binaries.
sub_binaries(Config) when is_list(Config) ->
Bin = list_to_binary(lists:seq(1,255)),
{match,[B,C]}=re:run(Bin,"(a)",[{capture,all,binary}]),
diff --git a/lib/stdlib/test/run_pcre_tests.erl b/lib/stdlib/test/run_pcre_tests.erl
index 1fdc777470..8b0373d062 100644
--- a/lib/stdlib/test/run_pcre_tests.erl
+++ b/lib/stdlib/test/run_pcre_tests.erl
@@ -69,8 +69,6 @@ pick_exec_options([]) ->
test([],_,_,_) ->
0;
test([{RE0,Line,Options0,Tests}|T],PreCompile,XMode,REAsList) ->
- %io:format("."),
- %case RE of <<>> -> io:format("Empty re:~w~n",[Line]); _ -> ok end,
Unicode = lists:member(unicode,Options0),
RE = case REAsList of
true ->
@@ -90,7 +88,6 @@ test([{RE0,Line,Options0,Tests}|T],PreCompile,XMode,REAsList) ->
end,
case Cres of
{ok,P} ->
- %erlang:display({testrun,RE,P,Tests,ExecOptions,Xopt,XMode}),
case (catch testrun(RE,P,Tests,ExecOptions,Xopt,XMode)) of
N when is_integer(N) ->
N + test(T,PreCompile,XMode,REAsList);
@@ -125,16 +122,10 @@ test([{RE0,Line,Options0,Tests}|T],PreCompile,XMode,REAsList) ->
loopexec(_,_,X,Y,_,_) when X > Y ->
{match,[]};
loopexec(P,Chal,X,Y,Unicode,Xopt) ->
- %io:format("~p~n",[X]),
case re:run(Chal,P,[{offset,X}]++Xopt) of
nomatch ->
- %io:format(" re:exec(~p,~p,[{offset,~p}]) -> ~p~n",
- % [P,Chal,X,no]),
{match,[]};
- %loopexec(P,Chal,X+1,Y);
{match,[{A,B}|More]} ->
- %io:format(" re:exec(~p,~p,[{offset,~p}]) -> ~p~n",
- % [P,Chal,X,{match,[{A,B}|More]}]),
{match,Rest} =
case B>0 of
true ->
@@ -169,7 +160,6 @@ forward(Chal,A,N,true) ->
_ ->
1
end,
- %io:format("Forward ~p~n",[Forw]),
forward(Chal,A+Forw,N-1,true).
contains_eightbit(<<>>) ->
@@ -334,8 +324,6 @@ testrun(RE,P,[{Chal,Line,ExecOpt,Responses}|T],EO,Xopt0,XMode) ->
nomatch ->
nomatch;
{match, Reslist} ->
- %io:format("re:run(~w,~w,~w) -> ~w~n",[Chal,P,ExecOpt++Xopt++
- % [{capture,all,list}],Reslist]),
UFix = lists:member(unicode,EO),
{match,bfix([if
UFix =:= true -> list_to_utf8(L);
@@ -425,7 +413,6 @@ pickline(Start,Stop,Bin) when Stop >= size(Bin) ->
{Res,Stop};
pickline(Start,Stop,Bin) ->
- %erlang:display({Start,Stop,size(Bin)}),
<<_:Stop/binary,Ch,_/binary>> = Bin,
case Ch of
$\n ->
@@ -465,15 +452,13 @@ stru([{_,<<>>}|T]) ->
stru(T);
stru([{Line,<<Ch,Re0/binary>>}|T0]) ->
{T,Re} = find_rest_re(Ch,[{Line,Re0}|T0]),
- %io:format("DBG: ~p~n",[Re]),
{NewRe,<< Ch, Options/binary >>} = end_of_re(Ch,Re),
case interpret_options_x(backstrip(frontstrip(Options)),NewRe) of
{Olist,<<>>} ->
U = lists:member(unicode,Olist),
case T of
[{_,<<$-,_/binary>>}|Con] ->
- %Debug output, we skip those
- %io:format("Skipping debug (~w)~n",[Line]),
+ %%Debug output, we skip those
TmpT = skip_debug(Con),
{NewT,Matches} = stru2(TmpT,U),
[{NewRe,Line,Olist,Matches}|stru(NewT)];
@@ -482,12 +467,10 @@ stru([{Line,<<Ch,Re0/binary>>}|T0]) ->
{NewT,Matches} = stru2(NewT0,U),
[{NewRe,Line,Olist,Matches}|stru(NewT)];
[{_,<<Bla,_/binary>>}|_] when Bla =/= $ ->
- %io:format("Skipping blabla (~w)~n",[Line]),
NewT = skip_until_empty(T),
stru(NewT);
_ ->
{NewT,Matches} = stru2(T,U),
- %erlang:display({NewRe,Line,Olist,Matches}),
Matches1 = case U of
true ->
Matches ++
@@ -496,7 +479,6 @@ stru([{Line,<<Ch,Re0/binary>>}|T0]) ->
false ->
Matches
end,
- %erlang:display({NewRe,Line,Olist,Matches1}),
[{NewRe,Line,Olist,Matches1}|stru(NewT)]
end;
{_,Rest} ->
@@ -605,7 +587,7 @@ backslash_end(<<_,R/binary>>) ->
backslash_end(R).
stru2([{Line,<<$ ,Rest/binary>>} | T],U) ->
- % A challenge
+ %% A challenge
case (catch responses(T,U)) of
{NewT,Rlist} ->
{NewNewT,StrList} = stru2(NewT,U),
@@ -765,17 +747,17 @@ pick_offset(Rest) ->
escape(<<>>,_) ->
{[],<<>>};
escape(<<$\\, Ch, Rest/binary>>,U) when Ch >= $A, Ch =< $Z; Ch =:= $? ->
- %Options in the string...
+ %%Options in the string...
NewOpts = eopt(Ch),
{MoreOpts,Tail} = escape(Rest,U),
{NewOpts ++ MoreOpts,Tail};
escape(<<$\\, $>, Rest/binary>>,U) ->
- %Offset Options in the string...
+ %%Offset Options in the string...
{NewOpt,NewRest} = pick_offset(Rest),
{MoreOpts,Tail} = escape(NewRest,U),
{[NewOpt|MoreOpts],Tail};
escape(<<$\\, $<, Rest/binary>>,U) ->
- %CR Options in the string...
+ %%CR Options in the string...
{NewOpt,NewRest} = pinch_cr(Rest),
{MoreOpts,Tail} = escape(NewRest,U),
{[NewOpt|MoreOpts],Tail};
@@ -789,7 +771,6 @@ escape(<<$\\, Ch, Rest/binary>>,U) ->
{<<$\\>>,<<Ch,Rest/binary>>}
end;
CCC ->
- %erlang:display({escape,CCC}),
{<<CCC>>,Rest}
end,
{MoreOpts,Tail} = escape(NR,U),
@@ -877,7 +858,6 @@ multi_esc(<<$x,${,N,O,$},Rest/binary>>,Unicode)
((N >= $a) and (N =< $f))) and
(((O >= $0) and (O =< $9)) or ((O >= $A) and (O =< $F)) or
((O >= $a) and (O =< $f)))) ->
- %io:format("~p(~p)~n",[<<$x,${,N,O,$}>>,get(unicode)]),
Cha = (trx(N) bsl 4) bor trx(O),
case Unicode of
false ->
@@ -974,8 +954,8 @@ single_esc($\\) ->
$\\;
single_esc($a) ->
7;
-%single_esc(Ch) when Ch >= $A, Ch =< $Z -> % eh?
-% Ch;
+%%single_esc(Ch) when Ch >= $A, Ch =< $Z -> % eh?
+%% Ch;
single_esc(_) ->
no.
@@ -1003,8 +983,6 @@ gen_split_test(OneFile) ->
io:format(F,"-module(~s).~n",[ErlModule]),
io:format(F,"-compile(export_all).~n",[]),
io:format(F,"-compile(no_native).~n",[]),
- %io:format(F,"-include(\"test_server.hrl\").~n",[]),
- %io:format(F,"-define(line,erlang:display(?LINE),).~n",[]),
io:format(F,"%% This file is generated by running ~w:gen_split_test(~p)~n",
[?MODULE,OneFile]),
io:format(F,"join([]) -> [];~n",[]),
@@ -1083,7 +1061,7 @@ dumponesplit(F,{RE,Line,O,TS}) ->
%% Generate replacement tests from indatafile,
%% you will need perl on the machine
gen_repl_test(OneFile) ->
- random:seed(1219,687731,62804),
+ rand:seed(exsplus, {1219,687731,62804}),
{ok,Bin} = file:read_file(OneFile),
Lines = splitfile(0,Bin,1),
Structured = stru(Lines),
@@ -1095,7 +1073,6 @@ gen_repl_test(OneFile) ->
io:format(F,"-module(~s).~n",[ErlModule]),
io:format(F,"-compile(export_all).~n",[]),
io:format(F,"-compile(no_native).~n",[]),
- %io:format(F,"-include(\"test_server.hrl\").~n",[]),
io:format(F,"%% This file is generated by running ~w:gen_repl_test(~p)~n",
[?MODULE,OneFile]),
io:format(F,"run() ->~n",[]),
@@ -1237,15 +1214,15 @@ btr(_) ->
ranchar() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
9 -> $&;
10 -> <<"\\1">>;
N when N < 5 ->
- random:uniform($Z-$A)+$A-1;
+ rand:uniform($Z-$A)+$A-1;
M when M < 9 ->
- random:uniform($z-$a)+$a-1
+ rand:uniform($z-$a)+$a-1
end.
ranstring() ->
- iolist_to_binary([ranchar() || _ <- lists:duplicate(random:uniform(20),0) ]).
+ iolist_to_binary([ranchar() || _ <- lists:duplicate(rand:uniform(20),0) ]).
diff --git a/lib/stdlib/test/select_SUITE.erl b/lib/stdlib/test/select_SUITE.erl
index ead64ffc75..b7e86377c4 100644
--- a/lib/stdlib/test/select_SUITE.erl
+++ b/lib/stdlib/test/select_SUITE.erl
@@ -27,21 +27,21 @@
%% Define to run outside of test server
%%
%%-define(STANDALONE,1).
-
+
%%
%% Define for debug output
%%
%%-define(debug,1).
-
+
-ifdef(STANDALONE).
-define(config(A,B),config(A,B)).
-export([config/2]).
--define(fmt(A,B),io:format(A,B)).
-else.
--include_lib("test_server/include/test_server.hrl").
--define(fmt(A,B),test_server:format(A,B)).
+-include_lib("common_test/include/ct.hrl").
-endif.
-
+
+-define(fmt(A,B), io:format(A, B)).
+
-ifdef(debug).
-ifdef(STANDALONE).
-define(line, erlang:display({?MODULE,?LINE}), ).
@@ -53,7 +53,7 @@
-endif.
-define(dbgformat(A,B),noop).
-endif.
-
+
-ifdef(STANDALONE).
config(priv_dir,_) ->
".".
@@ -64,16 +64,15 @@ config(priv_dir,_) ->
init_per_testcase/2, end_per_testcase/2,
return_values/1]).
-init_per_testcase(_Case, Config) when is_list(Config) ->
- ?line Dog=test_server:timetrap(test_server:seconds(1200)),
- [{watchdog, Dog}|Config].
+init_per_testcase(_Case, Config) ->
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,20}}].
all() ->
[return_values, select_test].
@@ -94,17 +93,11 @@ end_per_group(_GroupName, Config) ->
Config.
-select_test(suite) ->
- [];
-select_test(doc) ->
- ["Tests select in numerous ways"];
+%% Test select in numerous ways.
select_test(Config) when is_list(Config) ->
do_test(Config).
-return_values(suite) ->
- [];
-return_values(doc) ->
- ["Tests return values in specific situations for select/3 and select/1"];
+%% Test return values in specific situations for select/3 and select/1.
return_values(Config) when is_list(Config) ->
do_return_values().
@@ -117,7 +110,7 @@ table_factor({ets,_}) ->
100.
gen_dets_filename(Config,N) ->
- filename:join(?config(priv_dir,Config),
+ filename:join(proplists:get_value(priv_dir,Config),
"testdets_" ++ integer_to_list(N) ++ ".dets").
create_tables(Config) ->
@@ -128,15 +121,15 @@ create_tables(Config) ->
F1 = gen_dets_filename(Config,1),
(catch file:delete(F1)),
{ok,DetsPlain} = dets:open_file(testdets_1,
- [{file, F1}]),
+ [{file, F1}]),
F3 = gen_dets_filename(Config,3),
(catch file:delete(F3)),
{ok,DetsBag} = dets:open_file(testdets_3,
- [{file, F3},{type, bag}]),
+ [{file, F3},{type, bag}]),
F4 = gen_dets_filename(Config,4),
(catch file:delete(F4)),
{ok,DetsDBag} = dets:open_file(testdets_4,
- [{file, F4},{type, duplicate_bag}]),
+ [{file, F4},{type, duplicate_bag}]),
[{ets,Hash}, {ets,Tree}, {ets,Bag}, {ets,DBag},
{dets, DetsPlain}, {dets, DetsBag}, {dets, DetsDBag}].
@@ -189,7 +182,7 @@ build_tables(Config,Type) ->
L = create_tables(Config),
?dbgformat("Tables: ~p~n",[L]),
lists:foreach(fun(TD) ->
- fill_table(TD,table_size(TD),Type)
+ fill_table(TD,table_size(TD),Type)
end,
L),
L.
@@ -202,21 +195,20 @@ destroy_tables([{ets,Tab}|T]) ->
destroy_tables([{dets,Tab}|T]) ->
dets:close(Tab),
destroy_tables(T).
-
+
init_random(Config) ->
- WriteDir = ReadDir = ?config(priv_dir,Config),
+ WriteDir = ReadDir = proplists:get_value(priv_dir,Config),
(catch file:make_dir(WriteDir)),
Seed = case file:consult(filename:join([ReadDir,
"preset_random_seed2.txt"])) of
{ok,[X]} ->
X;
_ ->
- {A,B,C} = erlang:timestamp(),
- random:seed(A,B,C),
- get(random_seed)
+ rand:seed(exsplus),
+ rand:export_seed()
end,
- put(random_seed,Seed),
+ rand:seed(Seed),
{ok, F} = file:open(filename:join([WriteDir, "last_random_seed2.txt"]),
[write]),
io:format(F,"~p. ~n",[Seed]),
@@ -224,27 +216,27 @@ init_random(Config) ->
ok.
create_random_key(N,Type) ->
- gen_key(random:uniform(N),Type).
+ gen_key(rand:uniform(N),Type).
create_pb_key(N,list) ->
- X = random:uniform(N),
- case random:uniform(4) of
+ X = rand:uniform(N),
+ case rand:uniform(4) of
3 -> {[X, X+1, '_'], fun([Z,Z1,P1]) ->
- [Z,Z1,P1] =:= [X,X+1,P1] end};
+ [Z,Z1,P1] =:= [X,X+1,P1] end};
2 -> {[X, '_', '_'], fun([Z,P1,P2]) -> [Z,P1,P2] =:= [X,P1,P2] end};
1 -> {[X, X+1, '$1'], fun([Z,Z1,P1]) ->
[Z,Z1,P1] =:= [X,X+1,P1] end};
_ -> {[X, '$1', '$2'], fun([Z,P1,P2]) -> [Z,P1,P2] =:= [X,P1,P2] end}
end;
create_pb_key(N, tuple) ->
- X = random:uniform(N),
- case random:uniform(2) of
+ X = rand:uniform(N),
+ case rand:uniform(2) of
1 -> {{X, X+1, '$1'},fun({Z,Z1,P1}) -> {Z,Z1,P1} =:= {X,X+1,P1} end};
_ -> {{X, '$1', '$2'},fun({Z,P1,P2}) -> {Z,P1,P2} =:= {X,P1,P2} end}
end;
create_pb_key(N, complex) ->
- X = random:uniform(N),
- case random:uniform(2) of
+ X = rand:uniform(N),
+ case rand:uniform(2) of
1 -> {{[X, X+1], '$1'}, fun({[Z,Z1],P1}) ->
{[Z,Z1],P1} =:= {[X,X+1],P1} end};
_ -> {{[X, '$1'], '$2'},fun({[Z,P1],P2}) ->
@@ -310,7 +302,7 @@ cmp_ms_to_fun({Mod,Tab}, MS, Fun1, Fun2, ChunkSize) ->
false ->
?fmt("Match_spec result differs from fun result:~n",[]),
?fmt("Parameters: ~p,~p,~p,~p~n",
- [{Mod,Tab}, MS, Fun1, Fun2]),
+ [{Mod,Tab}, MS, Fun1, Fun2]),
?fmt("Match_spec Result: ~p~n", [MSRes]),
?fmt("Fun Result: ~p~n", [FunRes]),
Info = (catch Mod:info(Tab)),
@@ -352,18 +344,18 @@ do_test(Config) ->
?fmt("multi_key done for type ~w~n",[Type]),
multi_mixed_key(Tabs,Type),
?fmt("multi_mixed_key done for type ~w~n",
- [Type]),
+ [Type]),
destroy_tables(Tabs)
end,
[tuple, list, complex]),
ok.
-
+
basic_key(Tabs,Type) ->
Fun = fun() ->
lists:map(fun(Tab) ->
- ?line Key =
+ Key =
create_random_key(num_els(Tab),Type),
- ?line MS =
+ MS =
[{{Key,'_','_','_','_'},[],['$_']}],
MF = fun({Key0,A,B,F,Bi},Acc) ->
case Key =:= Key0 of
@@ -374,18 +366,18 @@ basic_key(Tabs,Type) ->
Acc
end
end,
- ?line cmp_ms_to_fun(Tab,MS,MF,[])
+ cmp_ms_to_fun(Tab,MS,MF,[])
end,
Tabs)
end,
- ?line do_n(50,Fun),
+ do_n(50,Fun),
ok.
-
+
basic_pb_key(Tabs,Type) ->
InnerFun = fun(Tab) ->
- ?line {Key,KeyFun} =
+ {Key,KeyFun} =
create_pb_key(num_els(Tab),Type),
- ?line MS = [{{Key,'_','_','_','_'},[],['$_']}],
+ MS = [{{Key,'_','_','_','_'},[],['$_']}],
MF = fun({Key0,A,B,F,Bi},Acc) ->
case KeyFun(Key0) of
true ->
@@ -395,27 +387,27 @@ basic_pb_key(Tabs,Type) ->
Acc
end
end,
- ?line cmp_ms_to_fun(Tab,MS,MF,[])
+ cmp_ms_to_fun(Tab,MS,MF,[])
end,
- ?line {Etses, Detses} = split_by_type(Tabs),
-
- ?line FunEts = fun() ->
- ?line lists:foreach(InnerFun,
- Etses)
- end,
- ?line FunDets = fun() ->
- ?line lists:foreach(InnerFun,
- Detses)
- end,
- ?line do_n(table_factor(hd(Etses)) div 2,FunEts),
- ?line do_n(10,FunDets),
+ {Etses, Detses} = split_by_type(Tabs),
+
+ FunEts = fun() ->
+ lists:foreach(InnerFun,
+ Etses)
+ end,
+ FunDets = fun() ->
+ lists:foreach(InnerFun,
+ Detses)
+ end,
+ do_n(table_factor(hd(Etses)) div 2,FunEts),
+ do_n(10,FunDets),
ok.
-
+
double_pb_key(Tabs,Type) ->
InnerFun = fun(Tab) ->
- ?line {KeyA,KeyFunA} =
+ {KeyA,KeyFunA} =
create_pb_key(num_els(Tab),Type),
- ?line {KeyB,KeyFunB} =
+ {KeyB,KeyFunB} =
create_pb_key(num_els(Tab),Type),
MS = [{{KeyA,'_','_','_','_'},[],['$_']},
{{KeyB,'_','_','_','_'},[],['$_']}],
@@ -449,51 +441,51 @@ double_pb_key(Tabs,Type) ->
end
end
end,
- ?line cmp_ms_to_fun(Tab,MS,MF,[])
+ cmp_ms_to_fun(Tab,MS,MF,[])
end,
- ?line {Etses, Detses} = split_by_type(Tabs),
-
- ?line FunEts = fun() ->
- ?line lists:foreach(InnerFun,
- Etses)
- end,
- ?line FunDets = fun() ->
- ?line lists:foreach(InnerFun,
- Detses)
- end,
- ?line do_n(table_factor(hd(Etses)) div 2,FunEts),
- ?line do_n(10,FunDets),
+ {Etses, Detses} = split_by_type(Tabs),
+
+ FunEts = fun() ->
+ lists:foreach(InnerFun,
+ Etses)
+ end,
+ FunDets = fun() ->
+ lists:foreach(InnerFun,
+ Detses)
+ end,
+ do_n(table_factor(hd(Etses)) div 2,FunEts),
+ do_n(10,FunDets),
ok.
-
-
+
+
multi_key(Tabs,Type) ->
Fun = fun() ->
lists:map(fun(Tab) ->
- ?line KeyA =
+ KeyA =
create_random_key(num_els(Tab),Type),
- ?line KeyB =
+ KeyB =
create_random_key(num_els(Tab),Type),
- ?line KeyC =
+ KeyC =
create_random_key(num_els(Tab),Type),
- ?line KeyD =
+ KeyD =
create_random_key(num_els(Tab),Type),
- ?line KeyE =
+ KeyE =
create_random_key(num_els(Tab),Type),
- ?line KeyF =
+ KeyF =
create_random_key(num_els(Tab),Type),
- ?line KeyG =
+ KeyG =
create_random_key(num_els(Tab),Type),
- ?line KeyH =
+ KeyH =
create_random_key(num_els(Tab),Type),
- ?line KeyI =
+ KeyI =
create_random_key(num_els(Tab),Type),
- ?line KeyJ =
+ KeyJ =
create_random_key(num_els(Tab),Type),
- ?line KeyK =
+ KeyK =
create_random_key(num_els(Tab),Type),
- ?line KeyL =
+ KeyL =
create_random_key(num_els(Tab),Type),
-
+
MS = [{{KeyA,'$1','_','$2','_'},[],
[{{'$1','$2'}}]},
{{KeyB,'$1','_','$2','_'},[],
@@ -520,7 +512,7 @@ multi_key(Tabs,Type) ->
[{{'$1','$2'}}]}
],
?dbgformat("Tab: ~p, MS: ~p~n",
- [Tab,MS]),
+ [Tab,MS]),
MF = fun({Key0,A,_B,F,_Bi},Acc) ->
case Key0 of
KeyA ->
@@ -563,40 +555,40 @@ multi_key(Tabs,Type) ->
Acc
end
end,
- ?line cmp_ms_to_fun(Tab,MS,MF,[])
+ cmp_ms_to_fun(Tab,MS,MF,[])
end,
Tabs)
end,
- ?line do_n(33,Fun),
+ do_n(33,Fun),
ok.
-
+
multi_mixed_key(Tabs,Type) ->
InnerFun = fun(Tab) ->
- ?line KeyA =
+ KeyA =
create_random_key(num_els(Tab),Type),
- ?line KeyB =
+ KeyB =
create_random_key(num_els(Tab),Type),
- ?line KeyC =
+ KeyC =
create_random_key(num_els(Tab),Type),
- ?line KeyD =
+ KeyD =
create_random_key(num_els(Tab),Type),
- ?line {KeyE, FunE} =
+ {KeyE, FunE} =
create_pb_key(num_els(Tab),Type),
- ?line KeyF =
+ KeyF =
create_random_key(num_els(Tab),Type),
- ?line {KeyG, FunG} =
+ {KeyG, FunG} =
create_pb_key(num_els(Tab),Type),
- ?line KeyH =
+ KeyH =
create_random_key(num_els(Tab),Type),
- ?line KeyI =
+ KeyI =
create_random_key(num_els(Tab),Type),
- ?line {KeyJ, FunJ} =
+ {KeyJ, FunJ} =
create_pb_key(num_els(Tab),Type),
- ?line KeyK =
+ KeyK =
create_random_key(num_els(Tab),Type),
- ?line KeyL =
+ KeyL =
create_random_key(num_els(Tab),Type),
-
+
MS = [{{KeyA,'$1','_','$2','_'},[],
[{{'$1','$2'}}]},
{{KeyB,'$1','_','$2','_'},[],
@@ -665,34 +657,34 @@ multi_mixed_key(Tabs,Type) ->
end
end
end,
- ?line cmp_ms_to_fun(Tab,MS,MF,[]),
- ?line case Tab of
- {ets,_} ->
- ?line cmp_ms_to_fun(Tab,MS,MF,[],1),
- ?line cmp_ms_to_fun(Tab,MS,MF,[],10),
- ?line cmp_ms_to_fun(Tab,MS,MF,[],1000000),
- ?line cmp_ms_to_fun(Tab,MS,MF,[],-1),
- ?line cmp_ms_to_fun(Tab,MS,MF,[],-10),
- ?line cmp_ms_to_fun(Tab,MS,MF,[],-1000000);
- _ ->
- ok
- end
+ cmp_ms_to_fun(Tab,MS,MF,[]),
+ case Tab of
+ {ets,_} ->
+ cmp_ms_to_fun(Tab,MS,MF,[],1),
+ cmp_ms_to_fun(Tab,MS,MF,[],10),
+ cmp_ms_to_fun(Tab,MS,MF,[],1000000),
+ cmp_ms_to_fun(Tab,MS,MF,[],-1),
+ cmp_ms_to_fun(Tab,MS,MF,[],-10),
+ cmp_ms_to_fun(Tab,MS,MF,[],-1000000);
+ _ ->
+ ok
+ end
end,
- ?line {Etses, Detses} = split_by_type(Tabs),
-
- ?line FunEts = fun() ->
- ?line lists:foreach(InnerFun,
- Etses)
- end,
- ?line FunDets = fun() ->
- ?line lists:foreach(InnerFun,
- Detses)
- end,
- ?line do_n(table_factor(hd(Etses)) div 2,FunEts),
- ?line do_n(table_factor(hd(Detses)) div 2,FunDets),
+ {Etses, Detses} = split_by_type(Tabs),
+
+ FunEts = fun() ->
+ lists:foreach(InnerFun,
+ Etses)
+ end,
+ FunDets = fun() ->
+ lists:foreach(InnerFun,
+ Detses)
+ end,
+ do_n(table_factor(hd(Etses)) div 2,FunEts),
+ do_n(table_factor(hd(Detses)) div 2,FunDets),
ok.
-
-
+
+
split_by_type(List) ->
split_by_type(List,[],[]).
split_by_type([],AccEts,AccDets) ->
@@ -703,121 +695,119 @@ split_by_type([{ets,Tab}|T],AccEts,AccDets) ->
split_by_type(T,[{ets,Tab}|AccEts],AccDets).
whitebox() ->
- ?line ets:new(xxx,[named_table, ordered_set]),
- ?line ets:new(yyy,[named_table]),
- ?line E = fun(0,_)->ok;
- (N,F) ->
- ?line ets:insert(xxx,{N,N rem 10}),
- ?line ets:insert(yyy,{N,N rem 10}),
- F(N-1,F)
- end,
- ?line E(10000,E),
-
- ?line G = fun(F,C,A) ->
- ?line case ets:select(C) of
- {L,C2} ->
- ?line F(F,C2,A+length(L));
- '$end_of_table' ->
- ?line A
- end
- end,
- ?line H=fun({L,C}) ->
- ?line G(G,C,length(L))
- end,
-
- ?line 1 = H(ets:select(xxx,[{{'$1','$2'},[{'<','$1',2}],['$_']}],7)),
- ?line 10000 = H(ets:select(xxx,[{{'$1','$2'},[],['$_']}],1)),
- ?line 1 = H(ets:select(yyy,[{{'$1','$2'},[{'<','$1',2}],['$_']}],7)),
- ?line 10000 = H(ets:select(yyy,[{{'$1','$2'},[],['$_']}],1)),
-
- ?line {[{5,5}],_} = ets:select(xxx,[{{5,'$2'},[],['$_']}],1),
- ?line {[{5,5}],_} = ets:select(yyy,[{{5,'$2'},[],['$_']}],1),
-
- ?line I = fun(_,0) ->
- ok;
- (I,N) ->
- ?line 10000 =
- H(ets:select(xxx,[{{'$1','$2'},[],['$_']}],N)),
- I(I,N-1)
- end,
- ?line I(I,2000),
- ?line J = fun(F,C,A) ->
- ?line case ets:select(C) of
- {L,C2} ->
- ?line F(F,C2,lists:reverse(L)++A);
- '$end_of_table' ->
- ?line lists:reverse(A)
- end
- end,
- ?line K = fun({L,C}) ->
- ?line J(J,C,lists:reverse(L))
- end,
- ?line M = fun(_, _, 0) ->
- ok;
- (F, What, N) ->
- ?line What =
- K(ets:select(xxx,[{{'$1','$2'},[],['$_']}],N)),
- F(F, What, N-1)
- end,
- ?line N = fun(HM) ->
- ?line What = ets:select(xxx,[{{'$1','$2'},[],['$_']}]),
- ?line What = lists:sort(What),
- M(M, What, HM)
- end,
- ?line N(2000),
- ?line ets:delete(xxx),
- ?line ets:delete(yyy).
+ ets:new(xxx,[named_table, ordered_set]),
+ ets:new(yyy,[named_table]),
+ E = fun(0,_)->ok;
+ (N,F) ->
+ ets:insert(xxx,{N,N rem 10}),
+ ets:insert(yyy,{N,N rem 10}),
+ F(N-1,F)
+ end,
+ E(10000,E),
+
+ G = fun(F,C,A) ->
+ case ets:select(C) of
+ {L,C2} ->
+ F(F,C2,A+length(L));
+ '$end_of_table' ->
+ A
+ end
+ end,
+ H=fun({L,C}) ->
+ G(G,C,length(L))
+ end,
+
+ 1 = H(ets:select(xxx,[{{'$1','$2'},[{'<','$1',2}],['$_']}],7)),
+ 10000 = H(ets:select(xxx,[{{'$1','$2'},[],['$_']}],1)),
+ 1 = H(ets:select(yyy,[{{'$1','$2'},[{'<','$1',2}],['$_']}],7)),
+ 10000 = H(ets:select(yyy,[{{'$1','$2'},[],['$_']}],1)),
+
+ {[{5,5}],_} = ets:select(xxx,[{{5,'$2'},[],['$_']}],1),
+ {[{5,5}],_} = ets:select(yyy,[{{5,'$2'},[],['$_']}],1),
+
+ I = fun(_,0) ->
+ ok;
+ (I,N) ->
+ 10000 =
+ H(ets:select(xxx,[{{'$1','$2'},[],['$_']}],N)),
+ I(I,N-1)
+ end,
+ I(I,2000),
+ J = fun(F,C,A) ->
+ case ets:select(C) of
+ {L,C2} ->
+ F(F,C2,lists:reverse(L)++A);
+ '$end_of_table' ->
+ lists:reverse(A)
+ end
+ end,
+ K = fun({L,C}) ->
+ J(J,C,lists:reverse(L))
+ end,
+ M = fun(_, _, 0) ->
+ ok;
+ (F, What, N) ->
+ What =
+ K(ets:select(xxx,[{{'$1','$2'},[],['$_']}],N)),
+ F(F, What, N-1)
+ end,
+ N = fun(HM) ->
+ What = ets:select(xxx,[{{'$1','$2'},[],['$_']}]),
+ What = lists:sort(What),
+ M(M, What, HM)
+ end,
+ N(2000),
+ ets:delete(xxx),
+ ets:delete(yyy).
do_return_values() ->
- ?line T = ets:new(xxx,[ordered_set]),
- ?line U = ets:new(xxx,[]),
- ?line '$end_of_table' = ets:select(T,[{'_',[],['$_']}],1),
- ?line '$end_of_table' = ets:select(U,[{'_',[],['$_']}],1),
- ?line ets:insert(T,{ett,1}),
- ?line ets:insert(U,{ett,1}),
- ?line {[{ett,1}],C1} = ets:select(T,[{'_',[],['$_']}],1),
- ?line '$end_of_table' = ets:select(C1),
- ?line {[{ett,1}],C2} = ets:select(U,[{'_',[],['$_']}],1),
- ?line '$end_of_table' = ets:select(C2),
- ?line {[{ett,1}],C3} = ets:select(T,[{'_',[],['$_']}],2),
- ?line '$end_of_table' = ets:select(C3),
- ?line {[{ett,1}],C4} = ets:select(U,[{'_',[],['$_']}],2),
- ?line '$end_of_table' = ets:select(C4),
- ?line E = fun(0,_)->ok;
- (N,F) ->
- ?line ets:insert(T,{N,N rem 10}),
- ?line ets:insert(U,{N,N rem 10}),
- F(N-1,F)
- end,
- ?line E(10000,E),
- ?line '$end_of_table' = ets:select(T,[{{hej, hopp},[],['$_']}],1),
- ?line '$end_of_table' = ets:select(U,[{{hej,hopp},[],['$_']}],1),
- ?line {[{ett,1}],CC1} = ets:select(T,[{{'$1','_'},[{is_atom, '$1'}],
- ['$_']}],1),
- ?line '$end_of_table' = ets:select(CC1),
- ?line {[{ett,1}],CC2} = ets:select(U,[{{'$1','_'},[{is_atom, '$1'}],
- ['$_']}],1),
- ?line '$end_of_table' = ets:select(CC2),
- ?line {[{ett,1}],CC3} = ets:select(T,[{{'$1','_'},[{is_atom, '$1'}],
- ['$_']}],2),
- ?line '$end_of_table' = ets:select(CC3),
- ?line {[{ett,1}],CC4} = ets:select(U,[{{'$1','_'},[{is_atom, '$1'}],
- ['$_']}],2),
- ?line '$end_of_table' = ets:select(CC4),
- ?line ets:delete(T),
- ?line ets:delete(U),
- ?line V = ets:new(xxx,[{keypos, 4}]),
- ?line X = ets:new(xxx,[ordered_set, {keypos, 4}]),
- ?line ets:insert(V,{1,1,1,ett}),
- ?line ets:insert(X,{1,1,1,ett}),
- ?line '$end_of_table' = ets:select(V,[{{1,1,1},[],['$_']}],1),
- ?line '$end_of_table' = ets:select(X,[{{1,1,1},[],['$_']}],1),
- ?line ets:delete(V),
- ?line ets:delete(X),
+ T = ets:new(xxx,[ordered_set]),
+ U = ets:new(xxx,[]),
+ '$end_of_table' = ets:select(T,[{'_',[],['$_']}],1),
+ '$end_of_table' = ets:select(U,[{'_',[],['$_']}],1),
+ ets:insert(T,{ett,1}),
+ ets:insert(U,{ett,1}),
+ {[{ett,1}],C1} = ets:select(T,[{'_',[],['$_']}],1),
+ '$end_of_table' = ets:select(C1),
+ {[{ett,1}],C2} = ets:select(U,[{'_',[],['$_']}],1),
+ '$end_of_table' = ets:select(C2),
+ {[{ett,1}],C3} = ets:select(T,[{'_',[],['$_']}],2),
+ '$end_of_table' = ets:select(C3),
+ {[{ett,1}],C4} = ets:select(U,[{'_',[],['$_']}],2),
+ '$end_of_table' = ets:select(C4),
+ E = fun(0,_)->ok;
+ (N,F) ->
+ ets:insert(T,{N,N rem 10}),
+ ets:insert(U,{N,N rem 10}),
+ F(N-1,F)
+ end,
+ E(10000,E),
+ '$end_of_table' = ets:select(T,[{{hej, hopp},[],['$_']}],1),
+ '$end_of_table' = ets:select(U,[{{hej,hopp},[],['$_']}],1),
+ {[{ett,1}],CC1} = ets:select(T,[{{'$1','_'},[{is_atom, '$1'}],
+ ['$_']}],1),
+ '$end_of_table' = ets:select(CC1),
+ {[{ett,1}],CC2} = ets:select(U,[{{'$1','_'},[{is_atom, '$1'}],
+ ['$_']}],1),
+ '$end_of_table' = ets:select(CC2),
+ {[{ett,1}],CC3} = ets:select(T,[{{'$1','_'},[{is_atom, '$1'}],
+ ['$_']}],2),
+ '$end_of_table' = ets:select(CC3),
+ {[{ett,1}],CC4} = ets:select(U,[{{'$1','_'},[{is_atom, '$1'}],
+ ['$_']}],2),
+ '$end_of_table' = ets:select(CC4),
+ ets:delete(T),
+ ets:delete(U),
+ V = ets:new(xxx,[{keypos, 4}]),
+ X = ets:new(xxx,[ordered_set, {keypos, 4}]),
+ ets:insert(V,{1,1,1,ett}),
+ ets:insert(X,{1,1,1,ett}),
+ '$end_of_table' = ets:select(V,[{{1,1,1},[],['$_']}],1),
+ '$end_of_table' = ets:select(X,[{{1,1,1},[],['$_']}],1),
+ ets:delete(V),
+ ets:delete(X),
ok.
-
-
diff --git a/lib/stdlib/test/sets_SUITE.erl b/lib/stdlib/test/sets_SUITE.erl
index 972a812072..b866cb62e0 100644
--- a/lib/stdlib/test/sets_SUITE.erl
+++ b/lib/stdlib/test/sets_SUITE.erl
@@ -31,20 +31,19 @@
is_set/1,fold/1,filter/1,
take_smallest/1,take_largest/1, iterate/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-import(lists, [foldl/3,reverse/1]).
init_per_testcase(_Case, Config) ->
- Dog = ?t:timetrap(?t:minutes(5)),
- [{watchdog,Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,5}}].
all() ->
[create, add_element, del_element, subtract,
@@ -107,9 +106,9 @@ add_element_del([H|T], M, S, Del, []) ->
add_element_del(T, M, M(add_element, {H,S}), Del, [H]);
add_element_del([H|T], M, S0, Del, Inserted) ->
S1 = M(add_element, {H,S0}),
- case random:uniform(3) of
+ case rand:uniform(3) of
1 ->
- OldEl = lists:nth(random:uniform(length(Inserted)), Inserted),
+ OldEl = lists:nth(rand:uniform(length(Inserted)), Inserted),
S = M(del_element, {OldEl,S1}),
add_element_del(T, M, S, [OldEl|Del], [H|Inserted]);
_ ->
@@ -438,7 +437,7 @@ iterate_1(M) ->
M(empty, []).
iterate_2(M) ->
- random:seed(1, 2, 42),
+ rand:seed(exsplus, {1,2,42}),
iter_set(M, 1000).
iter_set(_M, 0) ->
@@ -447,7 +446,7 @@ iter_set(M, N) ->
L = [I || I <- lists:seq(1, N)],
T = M(from_list, L),
L = lists:reverse(iterate_set(M, T)),
- R = random:uniform(N),
+ R = rand:uniform(N),
S = lists:reverse(iterate_set(M, R, T)),
S = [E || E <- L, E >= R],
iter_set(M, N-1).
@@ -481,7 +480,7 @@ sets_mods() ->
test_all(Tester) ->
Res = [begin
- random:seed(1, 2, 42),
+ rand:seed(exsplus, {1,2,42}),
S = Tester(M),
{M(size, S),lists:sort(M(to_list, S))}
end || M <- sets_mods()],
@@ -492,7 +491,7 @@ test_all([{Low,High}|T], Tester) ->
test_all([Sz|T], Tester) when is_integer(Sz) ->
List = rnd_list(Sz),
Res = [begin
- random:seed(19, 2, Sz),
+ rand:seed(exsplus, {19,2,Sz}),
S = Tester(List, M),
{M(size, S),lists:sort(M(to_list, S))}
end || M <- sets_mods()],
@@ -512,10 +511,10 @@ rnd_list(Sz) ->
rnd_list_1(Sz, []).
atomic_rnd_term() ->
- case random:uniform(3) of
- 1 -> list_to_atom(integer_to_list($\s+random:uniform(94))++"rnd");
- 2 -> random:uniform();
- 3 -> random:uniform(50)-37
+ case rand:uniform(3) of
+ 1 -> list_to_atom(integer_to_list($\s+rand:uniform(94))++"rnd");
+ 2 -> rand:uniform();
+ 3 -> rand:uniform(50)-37
end.
rnd_list_1(0, Acc) -> Acc;
@@ -543,7 +542,7 @@ remove_some(List0, P) ->
end.
remove_some([H|T], P, Acc) ->
- case random:uniform() of
+ case rand:uniform() of
F when F < P -> %Remove.
remove_some(T, P, Acc);
_ ->
diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl
index a9dd6b5817..af735218b9 100644
--- a/lib/stdlib/test/shell_SUITE.erl
+++ b/lib/stdlib/test/shell_SUITE.erl
@@ -52,28 +52,25 @@
config(priv_dir,_) ->
".".
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([init_per_testcase/2, end_per_testcase/2]).
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(10)).
init_per_testcase(_Case, Config) ->
- ?line Dog = ?t:timetrap(?default_timeout),
- ?line OrigPath = code:get_path(),
- ?line code:add_patha(?config(priv_dir,Config)),
- [{orig_path,OrigPath}, {watchdog, Dog} | Config].
+ OrigPath = code:get_path(),
+ code:add_patha(proplists:get_value(priv_dir,Config)),
+ [{orig_path,OrigPath} | Config].
end_per_testcase(_Case, Config) ->
- ?line Dog = ?config(watchdog, Config),
- ?line test_server:timetrap_cancel(Dog),
- ?line OrigPath = ?config(orig_path,Config),
- ?line code:set_path(OrigPath),
- ?line application:unset_env(stdlib, restricted_shell),
- ?line (catch code:purge(user_default)),
- ?line (catch code:delete(user_default)),
+ OrigPath = proplists:get_value(orig_path,Config),
+ code:set_path(OrigPath),
+ application:unset_env(stdlib, restricted_shell),
+ (catch code:purge(user_default)),
+ (catch code:delete(user_default)),
ok.
-endif.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,10}}].
all() ->
[forget, records, known_bugs, otp_5226, otp_5327,
@@ -112,101 +109,95 @@ end_per_group(_GroupName, Config) ->
-record(state, {bin, reply, leader, unic = latin1}).
-start_restricted_from_shell(doc) ->
- ["Test that a restricted shell can be started from the normal shell"];
-start_restricted_from_shell(suite) ->
- [];
+%% Test that a restricted shell can be started from the normal shell.
start_restricted_from_shell(Config) when is_list(Config) ->
- ?line [{error,nofile}] = scan(<<"begin shell:start_restricted("
- "nonexisting_module) end.">>),
- ?line Test = filename:join(?config(priv_dir, Config),
- "test_restricted.erl"),
+ [{error,nofile}] = scan(<<"begin shell:start_restricted("
+ "nonexisting_module) end.">>),
+ Test = filename:join(proplists:get_value(priv_dir, Config),
+ "test_restricted.erl"),
Contents = <<"-module(test_restricted).
-export([local_allowed/3, non_local_allowed/3]).
- local_allowed(m,[],State) ->
- {true,State};
- local_allowed(ugly,[],_State) ->
- non_conforming_reply;
- local_allowed(_,_,State) ->
- {false,State}.
-
- non_local_allowed({shell,stop_restricted},[],State) ->
- {true,State};
- non_local_allowed({erlang,'+'},[_],State) ->
- {true,State};
- non_local_allowed({erlang,'-'},[_,_],_State) ->
- non_conforming_reply;
- non_local_allowed({h, d}, [Arg], S) ->
- {{redirect, {erlang,hd}, [Arg]}, S};
- non_local_allowed(_,_,State) ->
- {false,State}.
- ">>,
- ?line ok = compile_file(Config, Test, Contents, []),
- ?line "exception exit: restricted shell starts now" =
- comm_err(<<"begin shell:start_restricted("
- "test_restricted) end.">>),
- ?line {ok, test_restricted} =
- application:get_env(stdlib, restricted_shell),
- ?line "Module" ++ _ = t({<<"begin m() end.">>, utf8}),
- ?line "exception exit: restricted shell does not allow c(foo)" =
- comm_err(<<"begin c(foo) end.">>),
- ?line "exception exit: restricted shell does not allow init:stop()" =
- comm_err(<<"begin init:stop() end.">>),
- ?line "exception exit: restricted shell does not allow init:stop()" =
- comm_err(<<"begin F = fun() -> init:stop() end, F() end.">>),
- ?line "exception error: an error occurred when evaluating an arithmetic expression" =
- comm_err(<<"begin +a end.">>),
- ?line "exception exit: restricted shell does not allow a + b" =
- comm_err(<<"begin a+b end.">>),
- ?line "exception exit: restricted shell does not allow - b" =
- comm_err(<<"begin -b end.">>),
- ?line "exception exit: restricted shell does not allow 1 + 2" =
- comm_err(<<"begin if atom(1 + 2> 0) -> 1; true -> 2 end end.">>),
- ?line "exception exit: restricted shell does not allow 1 + 2" =
- comm_err(<<"begin if is_atom(1 + 2> 0) -> 1; true -> 2 end end.">>),
- ?line "exception exit: restricted shell does not allow - 2" =
- comm_err(<<"begin if - 2 -> 1; true -> 2 end end.">>),
- ?line "exception exit: restricted shell does not allow - 2" =
- comm_err(<<"begin if (- 2 > 0) andalso true -> 1; true -> 2 end end.">>),
- ?line "exception exit: restricted shell does not allow - 2" =
- comm_err(<<"begin if (- 2 > 0) orelse true -> 1; true -> 2 end end.">>),
- ?line "exception exit: restricted shell does not allow 1 + 2" =
- comm_err(<<"begin if 1 + 2 > 0 -> 1; true -> 2 end end.">>),
- ?line "exception exit: restricted shell does not allow 1 + 2" =
- comm_err(<<"begin if erlang:is_atom(1 + 2> 0) -> 1; true -> 2 end end.">>),
- ?line "exception exit: restricted shell does not allow is_integer(1)" =
- comm_err(<<"begin if is_integer(1) -> 1; true -> 2 end end.">>),
- ?line "exception exit: restricted shell does not allow is_integer(1)" =
- comm_err(<<"begin if integer(1) -> 1; true -> 2 end end.">>),
- ?line "exception exit: "
- "restricted shell module returned bad value non_conforming_reply" =
- comm_err(<<"ugly().">>),
- ?line [one] = scan(<<"h:d([one,two]).">>),
- ?line "exception exit: "
- "restricted shell module returned bad value non_conforming_reply" =
- comm_err(<<"1 - 2.">>),
- ?line "exception exit: restricted shell stopped"=
- comm_err(<<"begin shell:stop_restricted() end.">>),
- ?line undefined =
- application:get_env(stdlib, restricted_shell),
- ok.
-
-start_restricted_on_command_line(doc) ->
- ["Check restricted shell when started from the command line"];
-start_restricted_on_command_line(suite) ->
- [];
+local_allowed(m,[],State) ->
+ {true,State};
+local_allowed(ugly,[],_State) ->
+ non_conforming_reply;
+local_allowed(_,_,State) ->
+ {false,State}.
+
+non_local_allowed({shell,stop_restricted},[],State) ->
+ {true,State};
+non_local_allowed({erlang,'+'},[_],State) ->
+ {true,State};
+non_local_allowed({erlang,'-'},[_,_],_State) ->
+ non_conforming_reply;
+non_local_allowed({h, d}, [Arg], S) ->
+ {{redirect, {erlang,hd}, [Arg]}, S};
+non_local_allowed(_,_,State) ->
+ {false,State}.
+">>,
+ ok = compile_file(Config, Test, Contents, []),
+"exception exit: restricted shell starts now" =
+comm_err(<<"begin shell:start_restricted("
+ "test_restricted) end.">>),
+{ok, test_restricted} =
+application:get_env(stdlib, restricted_shell),
+"Module" ++ _ = t({<<"begin m() end.">>, utf8}),
+"exception exit: restricted shell does not allow c(foo)" =
+comm_err(<<"begin c(foo) end.">>),
+"exception exit: restricted shell does not allow init:stop()" =
+comm_err(<<"begin init:stop() end.">>),
+"exception exit: restricted shell does not allow init:stop()" =
+comm_err(<<"begin F = fun() -> init:stop() end, F() end.">>),
+"exception error: an error occurred when evaluating an arithmetic expression" =
+comm_err(<<"begin +a end.">>),
+"exception exit: restricted shell does not allow a + b" =
+comm_err(<<"begin a+b end.">>),
+"exception exit: restricted shell does not allow - b" =
+comm_err(<<"begin -b end.">>),
+"exception exit: restricted shell does not allow 1 + 2" =
+comm_err(<<"begin if atom(1 + 2> 0) -> 1; true -> 2 end end.">>),
+"exception exit: restricted shell does not allow 1 + 2" =
+comm_err(<<"begin if is_atom(1 + 2> 0) -> 1; true -> 2 end end.">>),
+"exception exit: restricted shell does not allow - 2" =
+comm_err(<<"begin if - 2 -> 1; true -> 2 end end.">>),
+"exception exit: restricted shell does not allow - 2" =
+comm_err(<<"begin if (- 2 > 0) andalso true -> 1; true -> 2 end end.">>),
+"exception exit: restricted shell does not allow - 2" =
+comm_err(<<"begin if (- 2 > 0) orelse true -> 1; true -> 2 end end.">>),
+"exception exit: restricted shell does not allow 1 + 2" =
+comm_err(<<"begin if 1 + 2 > 0 -> 1; true -> 2 end end.">>),
+"exception exit: restricted shell does not allow 1 + 2" =
+comm_err(<<"begin if erlang:is_atom(1 + 2> 0) -> 1; true -> 2 end end.">>),
+"exception exit: restricted shell does not allow is_integer(1)" =
+comm_err(<<"begin if is_integer(1) -> 1; true -> 2 end end.">>),
+"exception exit: restricted shell does not allow is_integer(1)" =
+comm_err(<<"begin if integer(1) -> 1; true -> 2 end end.">>),
+"exception exit: "
+"restricted shell module returned bad value non_conforming_reply" =
+comm_err(<<"ugly().">>),
+[one] = scan(<<"h:d([one,two]).">>),
+"exception exit: "
+"restricted shell module returned bad value non_conforming_reply" =
+comm_err(<<"1 - 2.">>),
+"exception exit: restricted shell stopped"=
+comm_err(<<"begin shell:stop_restricted() end.">>),
+undefined =
+application:get_env(stdlib, restricted_shell),
+ok.
+
+%% Check restricted shell when started from the command line.
start_restricted_on_command_line(Config) when is_list(Config) ->
- ?line {ok,Node} = start_node(shell_suite_helper_1,
- "-pa "++?config(priv_dir,Config)++
- " -stdlib restricted_shell foo"),
- ?line "Warning! Restricted shell module foo not found: nofile"++_ =
+ {ok,Node} = start_node(shell_suite_helper_1,
+ "-pa "++proplists:get_value(priv_dir,Config)++
+ " -stdlib restricted_shell foo"),
+ "Warning! Restricted shell module foo not found: nofile"++_ =
t({Node, <<"begin m() end.">>}),
- ?line "exception exit: restricted shell does not allow m()" =
+ "exception exit: restricted shell does not allow m()" =
comm_err({Node, <<"begin m() end.">>}),
- ?line [ok] =
+ [ok] =
(catch scan({Node, <<"begin q() end.">>})),
- ?line test_server:stop_node(Node),
- ?line Test = filename:join(?config(priv_dir, Config),
+ test_server:stop_node(Node),
+ Test = filename:join(proplists:get_value(priv_dir, Config),
"test_restricted2.erl"),
Contents = <<"-module(test_restricted2).
-export([local_allowed/3, non_local_allowed/3]).
@@ -222,36 +213,34 @@ start_restricted_on_command_line(Config) when is_list(Config) ->
non_local_allowed(_,_,State) ->
{false,State}.
">>,
- ?line ok = compile_file(Config, Test, Contents, []),
- ?line {ok,Node2} = start_node(shell_suite_helper_2,
- "-pa "++?config(priv_dir,Config)++
+ ok = compile_file(Config, Test, Contents, []),
+ {ok,Node2} = start_node(shell_suite_helper_2,
+ "-pa "++proplists:get_value(priv_dir,Config)++
" -stdlib restricted_shell test_restricted2"),
- ?line "Module" ++ _ = t({Node2,<<"begin m() end.">>, utf8}),
- ?line "exception exit: restricted shell does not allow c(foo)" =
+ "Module" ++ _ = t({Node2,<<"begin m() end.">>, utf8}),
+ "exception exit: restricted shell does not allow c(foo)" =
comm_err({Node2,<<"begin c(foo) end.">>}),
- ?line "exception exit: restricted shell does not allow init:stop()" =
+ "exception exit: restricted shell does not allow init:stop()" =
comm_err({Node2,<<"begin init:stop() end.">>}),
- ?line "exception exit: restricted shell does not allow init:stop()" =
+ "exception exit: restricted shell does not allow init:stop()" =
comm_err({Node2,<<"begin F = fun() -> init:stop() end, F() end.">>}),
- ?line [Node2] =
+ [Node2] =
scan({Node2, <<"begin erlang:node() end.">>}),
- ?line [Node2] =
+ [Node2] =
scan({Node2, <<"begin node() end.">>}),
- ?line "exception exit: restricted shell stopped"=
+ "exception exit: restricted shell stopped"=
comm_err({Node2,<<"begin shell:stop_restricted() end.">>}),
- ?line [ok] =
+ [ok] =
scan({Node2, <<"begin q() end.">>}),
- ?line test_server:stop_node(Node2),
+ test_server:stop_node(Node2),
ok.
-restricted_local(suite) ->
- [];
-restricted_local(doc) ->
- ["Tests calling local shell functions with spectacular arguments in restricted shell"];
+%% Tests calling local shell functions with spectacular arguments in
+%% restricted shell.
restricted_local(Config) when is_list(Config) ->
- ?line [{error,nofile}] = scan(<<"begin shell:start_restricted("
+ [{error,nofile}] = scan(<<"begin shell:start_restricted("
"nonexisting_module) end.">>),
- ?line Test = filename:join(?config(priv_dir, Config),
+ Test = filename:join(proplists:get_value(priv_dir, Config),
"test_restricted_local.erl"),
Contents = <<"-module(test_restricted_local).
-export([local_allowed/3, non_local_allowed/3]).
@@ -271,8 +260,8 @@ restricted_local(Config) when is_list(Config) ->
non_local_allowed(_,_,State) ->
{false,State}.
">>,
- ?line ok = compile_file(Config, Test, Contents, []),
- ?line Test2 = filename:join(?config(priv_dir, Config),
+ ok = compile_file(Config, Test, Contents, []),
+ Test2 = filename:join(proplists:get_value(priv_dir, Config),
"user_default.erl"),
Contents2 = <<"-module(user_default).
-export([funkis/1,apple/1]).
@@ -283,117 +272,113 @@ restricted_local(Config) when is_list(Config) ->
apple(_) ->
apple.
">>,
- ?line ok = compile_file(Config, Test2, Contents2, []),
- ?line "exception exit: restricted shell starts now" =
+ ok = compile_file(Config, Test2, Contents2, []),
+ "exception exit: restricted shell starts now" =
comm_err(<<"begin shell:start_restricted("
"test_restricted_local) end.">>),
- ?line {ok, test_restricted_local} =
+ {ok, test_restricted_local} =
application:get_env(stdlib, restricted_shell),
- ?line "exception exit: restricted shell does not allow foo(" ++ _ =
+ "exception exit: restricted shell does not allow foo(" ++ _ =
comm_err(<<"begin F=fun() -> hello end, foo(F) end.">>),
- ?line "exception error: undefined shell command banan/1" =
+ "exception error: undefined shell command banan/1" =
comm_err(<<"begin F=fun() -> hello end, banan(F) end.">>),
- ?line "{error,"++_ = t(<<"begin F=fun() -> hello end, c(F) end.">>),
- ?line "exception exit: restricted shell does not allow l(" ++ _ =
+ "{error,"++_ = t(<<"begin F=fun() -> hello end, c(F) end.">>),
+ "exception exit: restricted shell does not allow l(" ++ _ =
comm_err(<<"begin F=fun() -> hello end, l(F) end.">>),
- ?line "exception error: variable 'F' is unbound" =
+ "exception error: variable 'F' is unbound" =
comm_err(<<"begin F=fun() -> hello end, f(F), F end.">>),
- ?line [funkis] =
+ [funkis] =
scan(<<"begin F=fun() -> hello end, funkis(F) end.">>),
- ?line "exception exit: restricted shell does not allow apple(" ++ _ =
+ "exception exit: restricted shell does not allow apple(" ++ _ =
comm_err(<<"begin F=fun() -> hello end, apple(F) end.">>),
- ?line "exception exit: restricted shell stopped"=
+ "exception exit: restricted shell stopped"=
comm_err(<<"begin shell:stop_restricted() end.">>),
- ?line undefined =
+ undefined =
application:get_env(stdlib, restricted_shell),
- ?line (catch code:purge(user_default)),
- ?line true = (catch code:delete(user_default)),
+ (catch code:purge(user_default)),
+ true = (catch code:delete(user_default)),
ok.
-forget(doc) ->
- ["f/0 and f/1"];
-forget(suite) ->
- [];
+%% f/0 and f/1.
forget(Config) when is_list(Config) ->
%% f/0
- ?line [ok] = scan(<<"begin f() end.">>),
- ?line "1: variable 'A' is unbound" =
+ [ok] = scan(<<"begin f() end.">>),
+ "1: variable 'A' is unbound" =
comm_err(<<"A = 3, f(), A.">>),
- ?line [ok] = scan(<<"A = 3, A = f(), A.">>),
+ [ok] = scan(<<"A = 3, A = f(), A.">>),
%% f/1
- ?line [ok] = scan(<<"begin f(A) end.">>),
- ?line "1: variable 'A' is unbound" =
+ [ok] = scan(<<"begin f(A) end.">>),
+ "1: variable 'A' is unbound" =
comm_err(<<"A = 3, f(A), A.">>),
- ?line [ok] = scan(<<"A = 3, A = f(A), A.">>),
- ?line "exception error: no function clause matching call to f/1" =
+ [ok] = scan(<<"A = 3, A = f(A), A.">>),
+ "exception error: no function clause matching call to f/1" =
comm_err(<<"f(a).">>),
ok.
-records(doc) ->
- ["Test of the record support. OTP-5063."];
-records(suite) ->
- [];
+%% Test of the record support. OTP-5063.
records(Config) when is_list(Config) ->
%% rd/2
- ?line [{attribute,_,record,{bar,_}},ok] =
+ [{attribute,_,record,{bar,_}},ok] =
scan(<<"rd(foo,{bar}),
rd(bar,{foo = (#foo{})#foo.bar}),
rl(bar).">>),
- ?line "variable 'R' is unbound" = % used to work (before OTP-5878, R11B)
+ "variable 'R' is unbound" = % used to work (before OTP-5878, R11B)
exit_string(<<"rd(foo,{bar}),
R = #foo{},
rd(bar,{foo = R#foo.bar}).">>),
- ?line "exception error: no function clause matching call to rd/2" =
+ "exception error: no function clause matching call to rd/2" =
comm_err(<<"rd({foo},{bar}).">>),
- ?line "bad record declaration" = exit_string(<<"A = bar, rd(foo,A).">>),
- ?line [foo] = scan(<<"begin rd(foo,{bar}) end.">>),
- ?line "1: record foo undefined" =
+ "bad record declaration" = exit_string(<<"A = bar, rd(foo,A).">>),
+ [foo] = scan(<<"begin rd(foo,{bar}) end.">>),
+ "1: record foo undefined" =
comm_err(<<"begin rd(foo,{bar}), #foo{} end.">>),
- ?line ['f o o'] = scan(<<"rd('f o o', {bar}).">>),
- ?line [foo] = scan(<<"rd(foo,{bar}), rd(foo,{foo = #foo{}}).">>),
+ ['f o o'] = scan(<<"rd('f o o', {bar}).">>),
+ [foo] = scan(<<"rd(foo,{bar}), rd(foo,{foo = #foo{}}).">>),
%% rf/0,1
- ?line [_, {attribute,_,record,{foo,_}},ok] =
+ [_, {attribute,_,record,{foo,_}},ok] =
scan(<<"rf('_'). rd(foo,{bar}),rl().">>),
- ?line "1: record foo undefined" =
+ "1: record foo undefined" =
comm_err(<<"rd(foo,{bar}), #foo{}, rf(foo), #foo{}.">>),
- ?line [ok,{foo,undefined}] =
+ [ok,{foo,undefined}] =
scan(<<"rd(foo,{bar}), A = #foo{}, rf(foo). A.">>),
- ?line [_] = scan(<<"begin rf() end.">>),
- ?line [ok] = scan(<<"begin rf(foo) end.">>),
+ [_] = scan(<<"begin rf() end.">>),
+ [ok] = scan(<<"begin rf(foo) end.">>),
%% rp/1
- ?line "#foo{bar = undefined}.\nok.\n" =
+ "#foo{bar = undefined}.\nok.\n" =
t(<<"rd(foo,{bar}), rp(#foo{}).">>),
- ?line [{foo,3,4,3},ok] = scan(<<"rd(foo,{a = 3, b}), rp({foo,3,4,3}).">>),
- ?line "#foo{a = 12}.\nok.\n" = t(<<"rd(foo,{a = 3}), rp({foo,12}).">>),
- ?line [{[{foo}],12},ok] = scan(<<"rd(foo,{a = 3}), rp({[{foo}],12}).">>),
+ [{foo,3,4,3},ok] = scan(<<"rd(foo,{a = 3, b}), rp({foo,3,4,3}).">>),
+ "#foo{a = 12}.\nok.\n" = t(<<"rd(foo,{a = 3}), rp({foo,12}).">>),
+ [{[{foo}],12},ok] = scan(<<"rd(foo,{a = 3}), rp({[{foo}],12}).">>),
%% rr/1,2,3
MS = ?MODULE_STRING,
RR1 = "rr(" ++ MS ++ "). #state{}.",
- ?line "[state]\n"
+ "[state]\n"
"#state{bin = undefined,reply = undefined,leader = undefined,\n"
" unic = latin1}.\n" =
t(RR1),
RR2 = "rr(" ++ MS ++ ",[state]). #state{}.",
- ?line "[state]\n"
+ "[state]\n"
"#state{bin = undefined,reply = undefined,leader = undefined,\n"
" unic = latin1}.\n" =
t(RR2),
RR3 = "rr(" ++ MS ++ ",'_'). #state{}.",
- ?line "[state]\n"
+ "[state]\n"
"#state{bin = undefined,reply = undefined,leader = undefined,\n"
" unic = latin1}.\n" =
t(RR3),
RR4 = "rr(" ++ MS ++ ", '_', {d,test1}).",
- ?line [[state]] = scan(RR4),
+ [[state]] = scan(RR4),
- Test = filename:join(?config(priv_dir, Config), "test.erl"),
+ Test = filename:join(proplists:get_value(priv_dir, Config), "test.erl"),
Contents = <<"-module(test).
- -record(state, {bin, reply, leader}).
+ -record(state, {bin :: binary(),
+ reply = no,
+ leader = some :: atom()}).
-ifdef(test1).
-record(test1, {f}).
@@ -402,7 +387,7 @@ records(Config) when is_list(Config) ->
-ifdef(test2).
-record(test2, {g}).
-endif.">>,
- ?line ok = file:write_file(Test, Contents),
+ ok = file:write_file(Test, Contents),
RR5 = "rr(\"" ++ Test ++ "\", '_', {d,test1}), rl([test1,test2]).",
A1 = erl_anno:new(1),
@@ -413,164 +398,155 @@ records(Config) when is_list(Config) ->
"\", '_', [{d,test1},{d,test2,17}]), rl([test1,test2]).",
[{attribute,A1,record,{test1,_}},{attribute,A1,record,{test2,_}},ok] =
scan(RR7),
- ?line PreReply = scan(<<"rr(prim_file).">>), % preloaded...
- ?line true = is_list(PreReply),
- ?line Dir = filename:join(?config(priv_dir, Config), "*.erl"),
- ?line RR8 = "rp(rr(\"" ++ Dir ++ "\")).",
- ?line [_,ok] = scan(RR8),
+ PreReply = scan(<<"rr(prim_file).">>), % preloaded...
+ true = is_list(PreReply),
+ Dir = filename:join(proplists:get_value(priv_dir, Config), "*.erl"),
+ RR8 = "rp(rr(\"" ++ Dir ++ "\")).",
+ [_,ok] = scan(RR8),
file:delete(Test),
RR1000 = "begin rr(" ++ MS ++ ") end.",
- ?line [_] = scan(RR1000),
+ [_] = scan(RR1000),
RR1001 = "begin rr(" ++ MS ++ ", state) end.",
- ?line [_] = scan(RR1001),
+ [_] = scan(RR1001),
RR1002 = "begin rr(" ++ MS ++ ", state,{i,'.'}) end.",
- ?line [_] = scan(RR1002),
+ [_] = scan(RR1002),
- ?line [{error,nofile}] = scan(<<"rr(not_a_module).">>),
- ?line [{error,invalid_filename}] = scan(<<"rr({foo}).">>),
- ?line [[]] = scan(<<"rr(\"not_a_file\").">>),
+ [{error,nofile}] = scan(<<"rr(not_a_module).">>),
+ [{error,invalid_filename}] = scan(<<"rr({foo}).">>),
+ [[]] = scan(<<"rr(\"not_a_file\").">>),
%% using records
- ?line [2] = scan(<<"rd(foo,{bar}), record_info(size, foo).">>),
- ?line [true] = scan(<<"rd(foo,{bar}), is_record(#foo{}, foo).">>),
- ?line [true] = scan(<<"rd(foo,{bar}), erlang:is_record(#foo{}, foo).">>),
- ?line [true] = scan(<<"rd(foo,{bar}),
+ [2] = scan(<<"rd(foo,{bar}), record_info(size, foo).">>),
+ [true] = scan(<<"rd(foo,{bar}), is_record(#foo{}, foo).">>),
+ [true] = scan(<<"rd(foo,{bar}), erlang:is_record(#foo{}, foo).">>),
+ [true] = scan(<<"rd(foo,{bar}),
fun() when record(#foo{},foo) -> true end().">>),
- ?line [2] = scan(<<"rd(foo,{bar}), #foo.bar.">>),
- ?line "#foo{bar = 17}.\n" =
+ [2] = scan(<<"rd(foo,{bar}), #foo.bar.">>),
+ "#foo{bar = 17}.\n" =
t(<<"rd(foo,{bar}), A = #foo{}, A#foo{bar = 17}.">>),
%% test of is_record/2 in lc
- ?line "[#foo{bar = 3}].\n" =
+ "[#foo{bar = 3}].\n" =
t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
"is_record(X, foo)].">>),
- ?line "[x,[],{a,b}].\n" =
+ "[x,[],{a,b}].\n" =
t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
"not is_record(X, foo)].">>),
- ?line "[#foo{bar = 3}].\n" =
+ "[#foo{bar = 3}].\n" =
t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
"begin is_record(X, foo) end].">>),
- ?line "[x,[],{a,b}].\n" =
+ "[x,[],{a,b}].\n" =
t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
"begin not is_record(X, foo) end].">>),
- ?line "[#foo{bar = 3},x,[],{a,b}].\n" =
+ "[#foo{bar = 3},x,[],{a,b}].\n" =
t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
"is_record(X, foo) or not is_binary(X)].">>),
- ?line "[#foo{bar = 3},x,[],{a,b}].\n" =
+ "[#foo{bar = 3},x,[],{a,b}].\n" =
t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
"not is_record(X, foo) or not is_binary(X)].">>),
- ?line "[#foo{bar = 3}].\n" =
+ "[#foo{bar = 3}].\n" =
t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
"is_record(X, foo) or is_reference(X)].">>),
- ?line "[x,[],{a,b}].\n" =
+ "[x,[],{a,b}].\n" =
t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
"not is_record(X, foo) or is_reference(X)].">>),
- ?line "[#foo{bar = 3},x,[],{a,b}].\n" =
+ "[#foo{bar = 3},x,[],{a,b}].\n" =
t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
"begin is_record(X, foo) or not is_binary(X) end].">>),
- ?line "[#foo{bar = 3},x,[],{a,b}].\n" =
+ "[#foo{bar = 3},x,[],{a,b}].\n" =
t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
"begin not is_record(X, foo) or not is_binary(X) end].">>),
- ?line "[#foo{bar = 3}].\n" =
+ "[#foo{bar = 3}].\n" =
t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
"begin is_record(X, foo) or is_reference(X) end].">>),
- ?line "[x,[],{a,b}].\n" =
+ "[x,[],{a,b}].\n" =
t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
"begin not is_record(X, foo) or is_reference(X) end].">>),
- ?line [ok] =
+ [ok] =
scan(<<"rd(a,{}), is_record({a},a) andalso true, b().">>),
%% nested record defs
- ?line "#b{a = #a{}}.\n" = t(<<"rd(a,{}), rd(b, {a = #a{}}), #b{}.">>),
+ "#b{a = #a{}}.\n" = t(<<"rd(a,{}), rd(b, {a = #a{}}), #b{}.">>),
- ?line [ok,ok,ok] = scan(<<"rf('_'), rp(rp(rl(rf(rf(rf(rl())))))).">>),
+ [ok,ok,ok] = scan(<<"rf('_'), rp(rp(rl(rf(rf(rf(rl())))))).">>),
ok.
-known_bugs(doc) ->
- ["Known bugs."];
-known_bugs(suite) ->
- [];
+%% Known bugs.
known_bugs(Config) when is_list(Config) ->
%% erl_eval:merge_bindings/2 cannot handle _removal_ of bindings.
- ?line [3] = scan(<<"A = 3, length(begin f(A), [3] end), A.">>),
+ [3] = scan(<<"A = 3, length(begin f(A), [3] end), A.">>),
ok.
-otp_5226(doc) ->
- ["OTP-5226. Wildcards accepted when reading BEAM files using rr/1,2,3."];
-otp_5226(suite) ->
- [];
+%% OTP-5226. Wildcards accepted when reading BEAM files using rr/1,2,3.
otp_5226(Config) when is_list(Config) ->
Test1 = <<"-module(test1).
-record('_test1', {a,b}).">>,
Test2 = <<"-module(test2).
-record('_test2', {c,d}).">>,
- ?line File1 = filename("test1.erl", Config),
- ?line File2 = filename("test2.erl", Config),
- ?line Beam = filename("*.beam", Config),
- ?line ok = compile_file(Config, File1, Test1, [no_debug_info]),
- ?line ok = compile_file(Config, File2, Test2, [no_debug_info]),
- RR = "rr(\"" ++ Beam ++ "\").",
- ?line [Recs] = scan(RR),
- ?line true = lists:member('_test1', Recs),
- ?line true = lists:member('_test2', Recs),
- file:delete(filename("test1.beam", Config)),
- file:delete(filename("test2.beam", Config)),
- file:delete(File1),
- file:delete(File2),
- ok.
-
-otp_5327(doc) ->
- ["OTP-5226. Test of eval_bits, mostly."];
-otp_5327(suite) ->
- [];
+ File1 = filename("test1.erl", Config),
+ File2 = filename("test2.erl", Config),
+ Beam = filename("*.beam", Config),
+ ok = compile_file(Config, File1, Test1, [no_debug_info]),
+ ok = compile_file(Config, File2, Test2, [no_debug_info]),
+ RR = "rr(\"" ++ Beam ++ "\").",
+ [Recs] = scan(RR),
+ true = lists:member('_test1', Recs),
+ true = lists:member('_test2', Recs),
+ file:delete(filename("test1.beam", Config)),
+ file:delete(filename("test2.beam", Config)),
+ file:delete(File1),
+ file:delete(File2),
+ ok.
+
+%% OTP-5226. Test of eval_bits, mostly.
otp_5327(Config) when is_list(Config) ->
- ?line "exception error: bad argument" =
+ "exception error: bad argument" =
comm_err(<<"<<\"hej\":default>>.">>),
- ?line <<"abc">> =
+ <<"abc">> =
erl_parse:normalise({bin,1,[{bin_element,1,{string,1,"abc"},
- default,default}]}),
- ?line [<<"abc">>] = scan(<<"<<(<<\"abc\">>):3/binary>>.">>),
- ?line [<<"abc">>] = scan(<<"<<(<<\"abc\">>)/binary>>.">>),
- ?line "exception error: bad argument" =
+ default,default}]}),
+ [<<"abc">>] = scan(<<"<<(<<\"abc\">>):3/binary>>.">>),
+ [<<"abc">>] = scan(<<"<<(<<\"abc\">>)/binary>>.">>),
+ "exception error: bad argument" =
comm_err(<<"<<(<<\"abc\">>):4/binary>>.">>),
- ?line true = byte_size(hd(scan("<<3.14:64/float>>."))) =:= 8,
- ?line true = byte_size(hd(scan("<<3.14:32/float>>."))) =:= 4,
- ?line "exception error: bad argument" =
+ true = byte_size(hd(scan("<<3.14:64/float>>."))) =:= 8,
+ true = byte_size(hd(scan("<<3.14:32/float>>."))) =:= 4,
+ "exception error: bad argument" =
comm_err(<<"<<3.14:128/float>>.">>),
- ?line "exception error: bad argument" =
+ "exception error: bad argument" =
comm_err(<<"<<10:default>>.">>),
- ?line [<<98,1:1>>] = scan(<<"<<3:3,5:6>>.">>),
- ?line {'EXIT',{badarg,_}} =
+ [<<98,1:1>>] = scan(<<"<<3:3,5:6>>.">>),
+ {'EXIT',{badarg,_}} =
(catch erl_parse:normalise({bin,1,[{bin_element,1,{integer,1,17},
{atom,1,all},
default}]})),
- ?line [<<-20/signed>>] = scan(<<"<<-20/signed>> = <<-20>>.">>),
- ?line [<<-300:16/signed>>] =
- scan(<<"<<-300:16/signed>> = <<-300:16>>.">>),
- ?line [<<-1000:24/signed>>] =
- scan(<<"<<-1000:24/signed>> = <<-1000:24>>.">>),
- ?line [<<-(1 bsl 29):32/signed>>] =
+ [<<-20/signed>>] = scan(<<"<<-20/signed>> = <<-20>>.">>),
+ [<<-300:16/signed>>] =
+ scan(<<"<<-300:16/signed>> = <<-300:16>>.">>),
+ [<<-1000:24/signed>>] =
+ scan(<<"<<-1000:24/signed>> = <<-1000:24>>.">>),
+ [<<-(1 bsl 29):32/signed>>] =
scan(<<"<<-(1 bsl 29):32/signed>> = <<-(1 bsl 29):32>>.">>),
- ?line "exception error: no match of right hand side value <<0,0,0>>" =
+ "exception error: no match of right hand side value <<0,0,0>>" =
comm_err(<<"<<B:3/unit:7-binary,_/binary>> = <<0:24>>.">>),
- ?line true = [<<103133:64/float>>] =:=
+ true = [<<103133:64/float>>] =:=
scan(<<"<<103133:64/float>> = <<103133:64/float>>.">>),
- ?line true = [<<103133.0:64/float>>] =:=
+ true = [<<103133.0:64/float>>] =:=
scan(<<"<<103133.0:64/float>> = <<103133:64/float>>.">>),
- ?line true = [<<103133:64/float>>] =:= scan(<<"<<103133:64/float>>.">>),
+ true = [<<103133:64/float>>] =:= scan(<<"<<103133:64/float>>.">>),
Int = 17,
- ?line true = [<<Int:64/float>>] =:= scan(<<"Int = 17, <<Int:64/float>>.">>),
- ?line "exception error: no match of right hand side value" ++ _ =
+ true = [<<Int:64/float>>] =:= scan(<<"Int = 17, <<Int:64/float>>.">>),
+ "exception error: no match of right hand side value" ++ _ =
comm_err(<<"<<103133:64/binary>> = <<103133:64/float>>.">>),
- ?line "exception error: interpreted function with arity 1 called with two arguments" =
+ "exception error: interpreted function with arity 1 called with two arguments" =
comm_err(<<"(fun(X) -> X end)(a,b).">>),
- ?line {'EXIT', {{illegal_pattern,_}, _}} =
+ {'EXIT', {{illegal_pattern,_}, _}} =
(catch evaluate("<<A:a>> = <<17:32>>.", [])),
C = <<"
<<A:4,B:4,C:4,D:4,E:4,F:4>> = <<\"hej\">>,
@@ -579,60 +555,54 @@ otp_5327(Config) when is_list(Config) ->
_ -> 2
end.
">>,
- ?line 1 = evaluate(C, []),
+ 1 = evaluate(C, []),
%% unbound_var would be nicer...
- ?line {'EXIT',{{illegal_pattern,_},_}} =
+ {'EXIT',{{illegal_pattern,_},_}} =
(catch evaluate(<<"<<A:B>> = <<17:32>>.">>, [])),
%% undefined_bittype is turned into badmatch:
- ?line {'EXIT',{{badmatch,<<17:32>>},_}} =
+ {'EXIT',{{badmatch,<<17:32>>},_}} =
(catch evaluate(<<"<<A/apa>> = <<17:32>>.">>, [])),
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch evaluate(<<"<<17/binary-unit:8-unit:16>>.">>, [])),
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch evaluate(<<"<<17:32/unsigned-signed>> = <<17:32>>.">>, [])),
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch evaluate(<<"<<17:32/unsigned-signed>>.">>, [])),
- ?line <<17:32>> = evaluate(<<"<<17:32/signed-signed>>.">>, []),
- ?line {'EXIT',_} =
+ <<17:32>> = evaluate(<<"<<17:32/signed-signed>>.">>, []),
+ {'EXIT',_} =
(catch evaluate(<<"<<32/unit:8>>.">>, [])),
ok.
-otp_5435(doc) ->
- ["OTP-5435. sys_pre_expand not in the path."];
-otp_5435(suite) ->
- [];
+%% OTP-5435. sys_pre_expand not in the path.
otp_5435(Config) when is_list(Config) ->
- ?line true = <<103133:64/float>> =:=
+ true = <<103133:64/float>> =:=
evaluate(<<"<<103133:64/float>> = <<103133:64/float>>.">>, []),
- ?line true = <<103133.0:64/float>> =:=
+ true = <<103133.0:64/float>> =:=
evaluate(<<"<<103133.0:64/float>> = <<103133:64/float>>.">>, []),
- ?line true = is_alive(),
- ?line {ok, Node} = start_node(shell_SUITE_otp_5435),
- ?line ok = rpc:call(Node, ?MODULE, otp_5435_2, []),
- ?line ?t:stop_node(Node),
+ true = is_alive(),
+ {ok, Node} = start_node(shell_SUITE_otp_5435),
+ ok = rpc:call(Node, ?MODULE, otp_5435_2, []),
+ test_server:stop_node(Node),
ok.
-
+
start_node(Name) ->
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?t:start_node(Name, slave, [{args, "-pa " ++ PA}]).
+ PA = filename:dirname(code:which(?MODULE)),
+ test_server:start_node(Name, slave, [{args, "-pa " ++ PA}]).
otp_5435_2() ->
- ?line true = code:del_path(compiler),
+ true = code:del_path(compiler),
%% sys_pre_expand can no longer be found
%% OTP-5876. But erl_expand_records can!
- ?line [{attribute,_,record,{bar,_}},ok] =
+ [{attribute,_,record,{bar,_}},ok] =
scan(<<"rd(foo,{bar}),
rd(bar,{foo = (#foo{})#foo.bar}),
- rl(bar).">>),
+ rl(bar).">>),
ok.
-otp_5195(doc) ->
- ["OTP-5195. QLC, mostly."];
-otp_5195(suite) ->
- [];
+%% OTP-5195. QLC, mostly.
otp_5195(Config) when is_list(Config) ->
%% QLC. It was easier to put these cases here than in qlc_SUITE.
- ?line "[#a{b = undefined}].\n" =
+ "[#a{b = undefined}].\n" =
t(<<"rd(a,{b}), qlc:e(qlc:q([X || X <- [#a{}],is_record(X, a)])).">>),
%% An experimental shell used to translate error tuples:
@@ -640,570 +610,556 @@ otp_5195(Config) when is_list(Config) ->
%% "list expression\".\n" =
%% t(<<"qlc:q([X || X <- [{a}], Y <- [X]]).">>),
%% Same as last one (if the shell does not translate error tuples):
- ?line [{error,qlc,{1,qlc,{used_generator_variable,'X'}}}] =
+ [{error,qlc,{1,qlc,{used_generator_variable,'X'}}}] =
scan(<<"qlc:q([X || X <- [{a}], Y <- [X]]).">>),
- ?line {error,qlc,{1,qlc,{used_generator_variable,'X'}}} =
+ {error,qlc,{1,qlc,{used_generator_variable,'X'}}} =
evaluate(<<"qlc:q([X || X <- [{a}], Y <- [X]]).">>, []),
Ugly = <<"qlc:e(qlc:q([X || X <- qlc:append([[1,2,3],ugly()])])).">>,
- ?line "undefined shell command ugly/0" = error_string(Ugly),
- ?line {'EXIT',{undef,_}} = (catch evaluate(Ugly, [])),
+ "undefined shell command ugly/0" = error_string(Ugly),
+ {'EXIT',{undef,_}} = (catch evaluate(Ugly, [])),
V_1 = <<"qlc:e(qlc:q([X || X <- qlc:append([[1,2,3],v(-1)])])).">>,
- ?line "- 1: command not found" = comm_err(V_1),
- ?line {'EXIT', {undef,_}} = (catch evaluate(V_1, [])),
+ "- 1: command not found" = comm_err(V_1),
+ {'EXIT', {undef,_}} = (catch evaluate(V_1, [])),
- ?line "1\n2\n3\n3.\n" =
+ "1\n2\n3\n3.\n" =
t(<<"1. 2. 3. 3 = fun(A) when A =:= 2 -> v(3) end(v(2)).">>),
- ?line List4 = t(<<"[a,list]. A = [1,2]. "
- "qlc:q([X || X <- qlc:append(A, v(1))]). "
- "[1,2,a,list] = qlc:e(v(-1)).">>),
- ?line "[1,2,a,list].\n" = string:substr(List4, string:len(List4)-13),
+ List4 = t(<<"[a,list]. A = [1,2]. "
+ "qlc:q([X || X <- qlc:append(A, v(1))]). "
+ "[1,2,a,list] = qlc:e(v(-1)).">>),
+ "[1,2,a,list].\n" = string:substr(List4, string:len(List4)-13),
ok.
-otp_5915(doc) ->
- ["OTP-5915. Strict record tests in guards."];
-otp_5915(suite) ->
- [];
+%% OTP-5915. Strict record tests in guards.
otp_5915(Config) when is_list(Config) ->
C = <<"
rd(r, {a = 4,b}),
- rd(r1, {a,b}),
- rd(r2, {a = #r1{},b,c=length([1,2,3])}),
- rd(r3, {a = fun(_) -> #r1{} end(1), b}),
-
- foo = fun(A) when A#r1.a > A#r1.b -> foo end(#r1{b = 2}),
- 0 = fun(A) when A#r2.a -> 0 end(#r2{a = true}),
- 1 = fun(A) when (#r1{a = A})#r1.a > 2 -> 1 end(3),
- 2 = fun(N) when ((#r2{a = #r{a = 4}, b = length([a,b,c])})#r2.a)#r.a > N ->
- 2 end(2),
- 3 = fun(A) when (A#r2.a)#r1.a =:= 3 -> 3 end(#r2{a = #r1{a = 3}}),
- ok = fun() ->
- F = fun(A) when record(A#r.a, r1) -> 4;
- (A) when record(A#r1.a, r1) -> 5
- end,
- 5 = F(#r1{a = #r1{}}),
- 4 = F(#r{a = #r1{}}),
- ok
- end(),
- 3 = fun(A) when record(A#r1.a, r),
- (A#r1.a)#r.a > 3 -> 3
- end(#r1{a = #r{a = 4}}),
- 7 = fun(A) when record(A#r3.a, r1) -> 7 end(#r3{}),
- [#r1{a = 2,b = 1}] =
- fun() ->
- [A || A <- [#r1{a = 1, b = 3},
- #r2{a = 2,b = 1},
- #r1{a = 2, b = 1}],
- A#r1.a >
- A#r1.b]
- end(),
- {[_],b} =
- fun(L) ->
+ rd(r1, {a,b}),
+ rd(r2, {a = #r1{},b,c=length([1,2,3])}),
+ rd(r3, {a = fun(_) -> #r1{} end(1), b}),
+
+ foo = fun(A) when A#r1.a > A#r1.b -> foo end(#r1{b = 2}),
+ 0 = fun(A) when A#r2.a -> 0 end(#r2{a = true}),
+ 1 = fun(A) when (#r1{a = A})#r1.a > 2 -> 1 end(3),
+ 2 = fun(N) when ((#r2{a = #r{a = 4}, b = length([a,b,c])})#r2.a)#r.a > N ->
+ 2 end(2),
+ 3 = fun(A) when (A#r2.a)#r1.a =:= 3 -> 3 end(#r2{a = #r1{a = 3}}),
+ ok = fun() ->
+ F = fun(A) when record(A#r.a, r1) -> 4;
+ (A) when record(A#r1.a, r1) -> 5
+ end,
+ 5 = F(#r1{a = #r1{}}),
+ 4 = F(#r{a = #r1{}}),
+ ok
+ end(),
+ 3 = fun(A) when record(A#r1.a, r),
+ (A#r1.a)#r.a > 3 -> 3
+ end(#r1{a = #r{a = 4}}),
+ 7 = fun(A) when record(A#r3.a, r1) -> 7 end(#r3{}),
+ [#r1{a = 2,b = 1}] =
+ fun() ->
+ [A || A <- [#r1{a = 1, b = 3},
+ #r2{a = 2,b = 1},
+ #r1{a = 2, b = 1}],
+ A#r1.a >
+ A#r1.b]
+ end(),
+ {[_],b} =
+ fun(L) ->
%% A is checked only once:
- R1 = [{A,B} || A <- L, A#r1.a, B <- L, A#r1.b],
- A = #r2{a = true},
+ R1 = [{A,B} || A <- L, A#r1.a, B <- L, A#r1.b],
+ A = #r2{a = true},
%% A is checked again:
- B = if A#r1.a -> a; true -> b end,
- {R1,B}
- end([#r1{a = true, b = true}]),
-
- p = fun(A) when (A#r1.a =:= 2) or (A#r2.a =:= 1) -> o;
- (_) -> p
- end(#r1{a = 2}),
-
- o = fun(A) when (A#r1.a =:= 2) orelse (A#r2.a =:= 1) -> o;
- (_) -> p
- end(#r1{a = 2}),
-
- 3 = fun(A) when A#r1.a > 3,
- record(A, r1) -> 3
- end(#r1{a = 5}),
-
- ok = fun() ->
- F = fun(A) when (A#r2.a =:= 1) orelse (A#r2.a) -> 2;
- (A) when (A#r1.a =:= 1) orelse (A#r1.a) -> 1;
- (A) when (A#r2.a =:= 2) andalso (A#r2.b) -> 3
- end,
- 1 = F(#r1{a = 1}),
- 2 = F(#r2{a = true}),
- 3 = F(#r2{a = 2, b = true}),
- ok
- end(),
-
- b = fun(A) when false or not (A#r.a =:= 1) -> a;
- (_) -> b
- end(#r1{a = 1}),
- b = fun(A) when not (A#r.a =:= 1) or false -> a;
- (_) -> b
- end(#r1{a = 1}),
-
- ok = fun() ->
- F = fun(A) when not (A#r.a =:= 1) -> yes;
- (_) -> no
- end,
- no = F(#r1{a = 2}),
- yes = F(#r{a = 2}),
- no = F(#r{a = 1}),
- ok
- end(),
-
- a = fun(A) when record(A, r),
- A#r.a =:= 1,
- A#r.b =:= 2 ->a
- end(#r{a = 1, b = 2}),
- a = fun(A) when erlang:is_record(A, r),
- A#r.a =:= 1,
- A#r.b =:= 2 -> a
- end(#r{a = 1, b = 2}),
- a = fun(A) when is_record(A, r),
- A#r.a =:= 1,
- A#r.b =:= 2 -> a
- end(#r{a = 1, b = 2}),
-
- nop = fun(A) when (is_record(A, r1) and (A#r1.a > 3)) or (A#r2.a < 1) ->
- japp;
- (_) ->
- nop
- end(#r2{a = 0}),
- nop = fun(A) when (A#r1.a > 3) or (A#r2.a < 1) -> japp;
- (_) ->
- nop
- end(#r2{a = 0}),
-
- ok = fun() ->
- F = fun(A) when (A#r1.a =:= 2) or (A#r2.a =:= 1) -> o;
- (_) -> p
- end,
- p = F(#r2{a = 1}),
- p = F(#r1{a = 2}),
- ok
- end(),
-
- ok = fun() ->
- F = fun(A) when fail, A#r1.a; A#r1.a -> ab;
- (_) -> bu
- end,
- ab = F(#r1{a = true}),
- bu = F(#r2{a = true}),
- ok
- end(),
-
- both = fun(A) when A#r.a, A#r.b -> both
- end(#r{a = true, b = true}),
-
- ok = fun() ->
- F = fun(A, B) when ((A#r1.a) orelse (B#r2.a))
- or (B#r2.b) or (A#r1.b) -> true;
- (_, _) -> false
- end,
- true = F(#r1{a = false, b = false}, #r2{a = false, b = true}),
- false = F(#r1{a = true, b = true}, #r1{a = false, b = true}),
- ok
- end(),
-
- ok.">>,
+ B = if A#r1.a -> a; true -> b end,
+ {R1,B}
+ end([#r1{a = true, b = true}]),
+
+ p = fun(A) when (A#r1.a =:= 2) or (A#r2.a =:= 1) -> o;
+ (_) -> p
+ end(#r1{a = 2}),
+
+ o = fun(A) when (A#r1.a =:= 2) orelse (A#r2.a =:= 1) -> o;
+ (_) -> p
+ end(#r1{a = 2}),
+
+ 3 = fun(A) when A#r1.a > 3,
+ record(A, r1) -> 3
+ end(#r1{a = 5}),
+
+ ok = fun() ->
+ F = fun(A) when (A#r2.a =:= 1) orelse (A#r2.a) -> 2;
+ (A) when (A#r1.a =:= 1) orelse (A#r1.a) -> 1;
+ (A) when (A#r2.a =:= 2) andalso (A#r2.b) -> 3
+ end,
+ 1 = F(#r1{a = 1}),
+ 2 = F(#r2{a = true}),
+ 3 = F(#r2{a = 2, b = true}),
+ ok
+ end(),
+
+ b = fun(A) when false or not (A#r.a =:= 1) -> a;
+ (_) -> b
+ end(#r1{a = 1}),
+ b = fun(A) when not (A#r.a =:= 1) or false -> a;
+ (_) -> b
+ end(#r1{a = 1}),
+
+ ok = fun() ->
+ F = fun(A) when not (A#r.a =:= 1) -> yes;
+ (_) -> no
+ end,
+ no = F(#r1{a = 2}),
+ yes = F(#r{a = 2}),
+ no = F(#r{a = 1}),
+ ok
+ end(),
+
+ a = fun(A) when record(A, r),
+ A#r.a =:= 1,
+ A#r.b =:= 2 ->a
+ end(#r{a = 1, b = 2}),
+ a = fun(A) when erlang:is_record(A, r),
+ A#r.a =:= 1,
+ A#r.b =:= 2 -> a
+ end(#r{a = 1, b = 2}),
+ a = fun(A) when is_record(A, r),
+ A#r.a =:= 1,
+ A#r.b =:= 2 -> a
+ end(#r{a = 1, b = 2}),
+
+ nop = fun(A) when (is_record(A, r1) and (A#r1.a > 3)) or (A#r2.a < 1) ->
+ japp;
+ (_) ->
+ nop
+ end(#r2{a = 0}),
+ nop = fun(A) when (A#r1.a > 3) or (A#r2.a < 1) -> japp;
+ (_) ->
+ nop
+ end(#r2{a = 0}),
+
+ ok = fun() ->
+ F = fun(A) when (A#r1.a =:= 2) or (A#r2.a =:= 1) -> o;
+ (_) -> p
+ end,
+ p = F(#r2{a = 1}),
+ p = F(#r1{a = 2}),
+ ok
+ end(),
+
+ ok = fun() ->
+ F = fun(A) when fail, A#r1.a; A#r1.a -> ab;
+ (_) -> bu
+ end,
+ ab = F(#r1{a = true}),
+ bu = F(#r2{a = true}),
+ ok
+ end(),
+
+ both = fun(A) when A#r.a, A#r.b -> both
+ end(#r{a = true, b = true}),
+
+ ok = fun() ->
+ F = fun(A, B) when ((A#r1.a) orelse (B#r2.a))
+ or (B#r2.b) or (A#r1.b) -> true;
+ (_, _) -> false
+ end,
+ true = F(#r1{a = false, b = false}, #r2{a = false, b = true}),
+ false = F(#r1{a = true, b = true}, #r1{a = false, b = true}),
+ ok
+ end(),
+
+ ok.">>,
[ok] = scan(C),
- ok.
+ ok.
-otp_5916(doc) ->
- ["OTP-5916. erlang:is_record/3 allowed in guards."];
-otp_5916(suite) ->
- [];
+%% OTP-5916. erlang:is_record/3 allowed in guards.
otp_5916(Config) when is_list(Config) ->
C = <<"
rd(r1, {a,b}),
- rd(r2, {a,b}),
+ rd(r2, {a,b}),
- true = if erlang:is_record(#r1{},r1,3) -> true; true -> false end,
- false = if erlang:is_record(#r2{},r1,3) -> true; true -> false end,
+ true = if erlang:is_record(#r1{},r1,3) -> true; true -> false end,
+ false = if erlang:is_record(#r2{},r1,3) -> true; true -> false end,
- true = if is_record(#r1{},r1,3) -> true; true -> false end,
- false = if is_record(#r2{},r1,3) -> true; true -> false end,
+ true = if is_record(#r1{},r1,3) -> true; true -> false end,
+ false = if is_record(#r2{},r1,3) -> true; true -> false end,
- ok.">>,
+ ok.">>,
[ok] = scan(C),
- ok.
+ ok.
-bs_match_misc_SUITE(doc) ->
- ["OTP-5327. Adopted from parts of emulator/test/bs_match_misc_SUITE.erl."];
-bs_match_misc_SUITE(suite) ->
- [];
+%% OTP-5327. Adopted from parts of emulator/test/bs_match_misc_SUITE.erl.
bs_match_misc_SUITE(Config) when is_list(Config) ->
C = <<"
F1 = fun() -> 3.1415 end,
- FOne = fun() -> 1.0 end,
-
- Fcmp = fun(F1, F2) when (F1 - F2) / F2 < 0.0000001 -> ok end,
-
- MakeSubBin = fun(Bin0) ->
- Sz = size(Bin0),
- Bin1 = <<37,Bin0/binary,38,39>>,
- <<_:8,Bin:Sz/binary,_:8,_:8>> = Bin1,
- Bin
- end,
-
- MatchFloat =
- fun(Bin0, Fsz, I) ->
- Bin = MakeSubBin(Bin0),
- Bsz = size(Bin) * 8,
- Tsz = Bsz - Fsz - I,
- <<_:I,F:Fsz/float,_:Tsz>> = Bin,
- F
- end,
-
- TFloat = fun() ->
- F = F1(),
- G = FOne(),
-
- G = MatchFloat(<<63,128,0,0>>, 32, 0),
- G = MatchFloat(<<63,240,0,0,0,0,0,0>>, 64, 0),
-
- Fcmp(F, MatchFloat(<<F:32/float>>, 32, 0)),
- Fcmp(F, MatchFloat(<<F:64/float>>, 64, 0)),
- Fcmp(F, MatchFloat(<<1:1,F:32/float,127:7>>, 32, 1)),
- Fcmp(F, MatchFloat(<<1:1,F:64/float,127:7>>, 64, 1)),
- Fcmp(F, MatchFloat(<<1:13,F:32/float,127:3>>, 32, 13)),
- Fcmp(F, MatchFloat(<<1:13,F:64/float,127:3>>, 64, 13))
- end,
- TFloat(),
-
- F2 = fun() -> 2.7133 end,
-
- MatchFloatLittle = fun(Bin0, Fsz, I) ->
- Bin = MakeSubBin(Bin0),
- Bsz = size(Bin) * 8,
- Tsz = Bsz - Fsz - I,
- <<_:I,F:Fsz/float-little,_:Tsz>> = Bin,
- F
- end,
-
- LittleFloat = fun() ->
- F = F2(),
- G = FOne(),
-
- G = MatchFloatLittle(<<0,0,0,0,0,0,240,63>>, 64, 0),
- G = MatchFloatLittle(<<0,0,128,63>>, 32, 0),
-
- Fcmp(F, MatchFloatLittle(<<F:32/float-little>>, 32, 0)),
- Fcmp(F, MatchFloatLittle(<<F:64/float-little>>, 64, 0)),
- Fcmp(F, MatchFloatLittle(<<1:1,F:32/float-little,127:7>>, 32, 1)),
- Fcmp(F, MatchFloatLittle(<<1:1,F:64/float-little,127:7>>, 64, 1)),
- Fcmp(F, MatchFloatLittle(<<1:13,F:32/float-little,127:3>>, 32, 13)),
- Fcmp(F, MatchFloatLittle(<<1:13,F:64/float-little,127:3>>, 64, 13))
- end,
- LittleFloat(),
-
- Sean1 = fun(<<B/binary>>) when size(B) < 4 -> small;
- (<<1, _B/binary>>) -> large
- end,
-
- Sean = fun() ->
- small = Sean1(<<>>),
- small = Sean1(<<1>>),
- small = Sean1(<<1,2>>),
- small = Sean1(<<1,2,3>>),
- large = Sean1(<<1,2,3,4>>),
-
- small = Sean1(<<4>>),
- small = Sean1(<<4,5>>),
- small = Sean1(<<4,5,6>>),
- {'EXIT',{function_clause,_}} = (catch Sean1(<<4,5,6,7>>))
- end,
- Sean(),
-
- NativeBig = fun() ->
- <<37.33:64/native-float>> = <<37.33:64/big-float>>,
- <<3974:16/native-integer>> = <<3974:16/big-integer>>
- end,
-
- NativeLittle = fun() ->
- <<37869.32343:64/native-float>> = <<37869.32343:64/little-float>>,
- <<7974:16/native-integer>> = <<7974:16/little-integer>>
- end,
-
- Native = fun() ->
- <<3.14:64/native-float>> = <<3.14:64/native-float>>,
- <<333:16/native>> = <<333:16/native>>,
- <<38658345:32/native>> = <<38658345:32/native>>,
- case <<1:16/native>> of
- <<0,1>> -> NativeBig();
- <<1,0>> -> NativeLittle()
- end
- end,
- Native(),
-
- Split = fun(<<N:16,B:N/binary,T/binary>>) -> {B,T} end,
-
- Split2 = fun(N, <<N:16,B:N/binary,T/binary>>) -> {B,T} end,
-
- Split_2 = fun(<<N0:8,N:N0,B:N/binary,T/binary>>) -> {B,T} end,
-
- Skip = fun(<<N:8,_:N/binary,T/binary>>) -> T end,
-
- SizeVar = fun() ->
- {<<45>>,<<>>} = Split(<<1:16,45>>),
- {<<45>>,<<46,47>>} = Split(<<1:16,45,46,47>>),
- {<<45,46>>,<<47>>} = Split(<<2:16,45,46,47>>),
-
- {<<45,46,47>>,<<48>>} = Split_2(<<16:8,3:16,45,46,47,48>>),
-
- {<<45,46>>,<<47>>} = Split2(2, <<2:16,45,46,47>>),
- {'EXIT',{function_clause,_}} =
- (catch Split2(42, <<2:16,45,46,47>>)),
-
- <<\"cdef\">> = Skip(<<2:8,\"abcdef\">>)
+ FOne = fun() -> 1.0 end,
+
+ Fcmp = fun(F1, F2) when (F1 - F2) / F2 < 0.0000001 -> ok end,
+
+ MakeSubBin = fun(Bin0) ->
+ Sz = size(Bin0),
+ Bin1 = <<37,Bin0/binary,38,39>>,
+ <<_:8,Bin:Sz/binary,_:8,_:8>> = Bin1,
+ Bin
+ end,
+
+ MatchFloat =
+ fun(Bin0, Fsz, I) ->
+ Bin = MakeSubBin(Bin0),
+ Bsz = size(Bin) * 8,
+ Tsz = Bsz - Fsz - I,
+ <<_:I,F:Fsz/float,_:Tsz>> = Bin,
+ F
+ end,
+
+ TFloat = fun() ->
+ F = F1(),
+ G = FOne(),
+
+ G = MatchFloat(<<63,128,0,0>>, 32, 0),
+ G = MatchFloat(<<63,240,0,0,0,0,0,0>>, 64, 0),
+
+ Fcmp(F, MatchFloat(<<F:32/float>>, 32, 0)),
+ Fcmp(F, MatchFloat(<<F:64/float>>, 64, 0)),
+ Fcmp(F, MatchFloat(<<1:1,F:32/float,127:7>>, 32, 1)),
+ Fcmp(F, MatchFloat(<<1:1,F:64/float,127:7>>, 64, 1)),
+ Fcmp(F, MatchFloat(<<1:13,F:32/float,127:3>>, 32, 13)),
+ Fcmp(F, MatchFloat(<<1:13,F:64/float,127:3>>, 64, 13))
+ end,
+ TFloat(),
+
+ F2 = fun() -> 2.7133 end,
+
+ MatchFloatLittle = fun(Bin0, Fsz, I) ->
+ Bin = MakeSubBin(Bin0),
+ Bsz = size(Bin) * 8,
+ Tsz = Bsz - Fsz - I,
+ <<_:I,F:Fsz/float-little,_:Tsz>> = Bin,
+ F
+ end,
+
+ LittleFloat = fun() ->
+ F = F2(),
+ G = FOne(),
+
+ G = MatchFloatLittle(<<0,0,0,0,0,0,240,63>>, 64, 0),
+ G = MatchFloatLittle(<<0,0,128,63>>, 32, 0),
+
+ Fcmp(F, MatchFloatLittle(<<F:32/float-little>>, 32, 0)),
+ Fcmp(F, MatchFloatLittle(<<F:64/float-little>>, 64, 0)),
+ Fcmp(F, MatchFloatLittle(<<1:1,F:32/float-little,127:7>>, 32, 1)),
+ Fcmp(F, MatchFloatLittle(<<1:1,F:64/float-little,127:7>>, 64, 1)),
+ Fcmp(F, MatchFloatLittle(<<1:13,F:32/float-little,127:3>>, 32, 13)),
+ Fcmp(F, MatchFloatLittle(<<1:13,F:64/float-little,127:3>>, 64, 13))
+ end,
+ LittleFloat(),
+
+ Sean1 = fun(<<B/binary>>) when size(B) < 4 -> small;
+ (<<1, _B/binary>>) -> large
+ end,
+
+ Sean = fun() ->
+ small = Sean1(<<>>),
+ small = Sean1(<<1>>),
+ small = Sean1(<<1,2>>),
+ small = Sean1(<<1,2,3>>),
+ large = Sean1(<<1,2,3,4>>),
+
+ small = Sean1(<<4>>),
+ small = Sean1(<<4,5>>),
+ small = Sean1(<<4,5,6>>),
+ {'EXIT',{function_clause,_}} = (catch Sean1(<<4,5,6,7>>))
+ end,
+ Sean(),
+
+ NativeBig = fun() ->
+ <<37.33:64/native-float>> = <<37.33:64/big-float>>,
+ <<3974:16/native-integer>> = <<3974:16/big-integer>>
+ end,
+
+ NativeLittle = fun() ->
+ <<37869.32343:64/native-float>> = <<37869.32343:64/little-float>>,
+ <<7974:16/native-integer>> = <<7974:16/little-integer>>
+ end,
+
+ Native = fun() ->
+ <<3.14:64/native-float>> = <<3.14:64/native-float>>,
+ <<333:16/native>> = <<333:16/native>>,
+ <<38658345:32/native>> = <<38658345:32/native>>,
+ case <<1:16/native>> of
+ <<0,1>> -> NativeBig();
+ <<1,0>> -> NativeLittle()
+ end
+ end,
+ Native(),
+
+ Split = fun(<<N:16,B:N/binary,T/binary>>) -> {B,T} end,
+
+ Split2 = fun(N, <<N:16,B:N/binary,T/binary>>) -> {B,T} end,
+
+ Split_2 = fun(<<N0:8,N:N0,B:N/binary,T/binary>>) -> {B,T} end,
+
+ Skip = fun(<<N:8,_:N/binary,T/binary>>) -> T end,
+
+ SizeVar = fun() ->
+ {<<45>>,<<>>} = Split(<<1:16,45>>),
+ {<<45>>,<<46,47>>} = Split(<<1:16,45,46,47>>),
+ {<<45,46>>,<<47>>} = Split(<<2:16,45,46,47>>),
+
+ {<<45,46,47>>,<<48>>} = Split_2(<<16:8,3:16,45,46,47,48>>),
+
+ {<<45,46>>,<<47>>} = Split2(2, <<2:16,45,46,47>>),
+ {'EXIT',{function_clause,_}} =
+ (catch Split2(42, <<2:16,45,46,47>>)),
+
+ <<\"cdef\">> = Skip(<<2:8,\"abcdef\">>)
end,
- SizeVar(),
-
- Wcheck = fun(<<A>>) when A==3-> ok1;
- (<<_,_:2/binary>>) -> ok2;
- (<<_>>) -> ok3;
- (Other) -> {error,Other}
- end,
-
- Wiger = fun() ->
- ok1 = Wcheck(<<3>>),
- ok2 = Wcheck(<<1,2,3>>),
- ok3 = Wcheck(<<4>>),
- {error,<<1,2,3,4>>} = Wcheck(<<1,2,3,4>>),
- {error,<<>>} = Wcheck(<<>>)
- end,
- Wiger(),
-
- ok.
- ">>,
+ SizeVar(),
+
+ Wcheck = fun(<<A>>) when A==3-> ok1;
+ (<<_,_:2/binary>>) -> ok2;
+ (<<_>>) -> ok3;
+ (Other) -> {error,Other}
+ end,
+
+ Wiger = fun() ->
+ ok1 = Wcheck(<<3>>),
+ ok2 = Wcheck(<<1,2,3>>),
+ ok3 = Wcheck(<<4>>),
+ {error,<<1,2,3,4>>} = Wcheck(<<1,2,3,4>>),
+ {error,<<>>} = Wcheck(<<>>)
+ end,
+ Wiger(),
+
+ ok.
+">>,
[ok] = scan(C),
- ok = evaluate(C, []).
+ok = evaluate(C, []).
%% This one is not run during night builds since it takes several minutes.
-bs_match_int_SUITE(doc) ->
- ["OTP-5327. Adopted from emulator/test/bs_match_int_SUITE.erl."];
-bs_match_int_SUITE(suite) ->
- [];
+
+%% OTP-5327. Adopted from emulator/test/bs_match_int_SUITE.erl.
bs_match_int_SUITE(Config) when is_list(Config) ->
C = <<"
FunClause = fun({'EXIT',{function_clause,_}}) -> ok end,
- Mkbin = fun(L) when list(L) -> list_to_binary(L) end,
-
- GetInt1 = fun(<<I:0>>) -> I;
- (<<I:8>>) -> I;
- (<<I:16>>) -> I;
- (<<I:24>>) -> I;
- (<<I:32>>) -> I
- end,
-
- GetInt2 = fun(Bin0, I, F) when size(Bin0) < 4 ->
- Bin = <<0,Bin0/binary>>,
- I = GetInt1(Bin),
- F(Bin, I, F);
- (_, I, _F) -> I
- end,
-
- GetInt = fun(Bin) ->
- I = GetInt1(Bin),
- GetInt2(Bin, I, GetInt2)
- end,
-
-
- Cmp128 = fun(<<I:128>>, I) -> equal;
- (_, _) -> not_equal
- end,
-
- Uint2 = fun([H|T], Acc, F) -> F(T, Acc bsl 8 bor H, F);
- ([], Acc, _F) -> Acc
- end,
-
- Uint = fun(L) -> Uint2(L, 0, Uint2) end,
-
- Integer = fun() ->
- 0 = GetInt(Mkbin([])),
- 0 = GetInt(Mkbin([0])),
- 42 = GetInt(Mkbin([42])),
- 255 = GetInt(Mkbin([255])),
- 256 = GetInt(Mkbin([1,0])),
- 257 = GetInt(Mkbin([1,1])),
- 258 = GetInt(Mkbin([1,2])),
- 258 = GetInt(Mkbin([1,2])),
- 65534 = GetInt(Mkbin([255,254])),
- 16776455 = GetInt(Mkbin([255,253,7])),
- 4245492555 = GetInt(Mkbin([253,13,19,75])),
- 4294967294 = GetInt(Mkbin([255,255,255,254])),
- 4294967295 = GetInt(Mkbin([255,255,255,255])),
- Eight = [200,1,19,128,222,42,97,111],
- Cmp128(Eight, Uint(Eight)),
- FunClause(catch GetInt(Mkbin(lists:seq(1,5))))
- end,
- Integer(),
-
- Sint = fun(Bin) ->
- case Bin of
- <<I:8/signed>> -> I;
- <<I:8/signed,_:3,_:5>> -> I;
- Other -> {no_match,Other}
- end
- end,
-
- SignedInteger = fun() ->
- {no_match,_} = Sint(Mkbin([])),
- {no_match,_} = Sint(Mkbin([1,2,3])),
- 127 = Sint(Mkbin([127])),
- -1 = Sint(Mkbin([255])),
- -128 = Sint(Mkbin([128])),
- 42 = Sint(Mkbin([42,255])),
- 127 = Sint(Mkbin([127,255]))
- end,
- SignedInteger(),
-
- Dynamic5 = fun(Bin, S1, S2, A, B) ->
- case Bin of
- <<A:S1,B:S2>> ->
- % io:format(\"~p ~p ~p ~p~n\", [S1,S2,A,B]),
- ok;
- _Other -> erlang:error(badmatch, [Bin,S1,S2,A,B])
- end
- end,
-
- Dynamic2 = fun(Bin, S1, F) when S1 >= 0 ->
- S2 = size(Bin) * 8 - S1,
- Dynamic5(Bin, S1, S2, (1 bsl S1) - 1, (1 bsl S2) - 1),
- F(Bin, S1-1, F);
- (_, _, _) -> ok
- end,
-
- Dynamic = fun(Bin, S1) ->
- Dynamic2(Bin, S1, Dynamic2)
- end,
-
- Dynamic(Mkbin([255]), 8),
- Dynamic(Mkbin([255,255]), 16),
- Dynamic(Mkbin([255,255,255]), 24),
- Dynamic(Mkbin([255,255,255,255]), 32),
-
- BigToLittle4 =
- fun([B0,B1,B2,B3,B4,B5,B6,B7|T], N, Acc, F) when N >= 8 ->
- F(T, N-8, [B0,B1,B2,B3,B4,B5,B6,B7|Acc], F);
- (List, N, Acc, _F) -> lists:sublist(List, 1, N) ++ Acc
- end,
-
- BigToLittle =
- fun(List, N) -> BigToLittle4(List, N, [], BigToLittle4) end,
-
- ReversedSublist =
- fun(_List, 0, Acc, _F) -> Acc;
- ([H|T], N, Acc, F) -> F(T, N-1, [H|Acc], F)
- end,
-
- TwoComplementAndReverse =
- fun([H|T], Carry, Acc, F) ->
- Sum = 1-H+Carry,
- F(T, Sum div 2, [Sum rem 2|Acc], F);
- ([], Carry, Acc, _F) -> [Carry|Acc]
- end,
-
- MakeInt = fun(_List, 0, Acc, _F) -> Acc;
- ([H|T], N, Acc, F) -> F(T, N-1, Acc bsl 1 bor H, F)
- end,
-
- MakeSignedInt =
- fun(_List, 0) -> 0;
- ([0|_]=List, N) -> MakeInt(List, N, 0, MakeInt);
- ([1|_]=List0, N) ->
- List1 = ReversedSublist(List0, N, [], ReversedSublist),
- List2 = TwoComplementAndReverse(List1, 1, [],
- TwoComplementAndReverse),
- -MakeInt(List2, length(List2), 0, MakeInt)
- end,
-
- BitsToList =
- fun([H|T], 0, F) -> F(T, 16#80, F);
- ([H|_]=List, Mask, F) ->
- [case H band Mask of
+ Mkbin = fun(L) when list(L) -> list_to_binary(L) end,
+
+ GetInt1 = fun(<<I:0>>) -> I;
+ (<<I:8>>) -> I;
+ (<<I:16>>) -> I;
+ (<<I:24>>) -> I;
+ (<<I:32>>) -> I
+ end,
+
+ GetInt2 = fun(Bin0, I, F) when size(Bin0) < 4 ->
+ Bin = <<0,Bin0/binary>>,
+ I = GetInt1(Bin),
+ F(Bin, I, F);
+ (_, I, _F) -> I
+ end,
+
+ GetInt = fun(Bin) ->
+ I = GetInt1(Bin),
+ GetInt2(Bin, I, GetInt2)
+ end,
+
+
+ Cmp128 = fun(<<I:128>>, I) -> equal;
+ (_, _) -> not_equal
+ end,
+
+ Uint2 = fun([H|T], Acc, F) -> F(T, Acc bsl 8 bor H, F);
+ ([], Acc, _F) -> Acc
+ end,
+
+ Uint = fun(L) -> Uint2(L, 0, Uint2) end,
+
+ Integer = fun() ->
+ 0 = GetInt(Mkbin([])),
+ 0 = GetInt(Mkbin([0])),
+ 42 = GetInt(Mkbin([42])),
+ 255 = GetInt(Mkbin([255])),
+ 256 = GetInt(Mkbin([1,0])),
+ 257 = GetInt(Mkbin([1,1])),
+ 258 = GetInt(Mkbin([1,2])),
+ 258 = GetInt(Mkbin([1,2])),
+ 65534 = GetInt(Mkbin([255,254])),
+ 16776455 = GetInt(Mkbin([255,253,7])),
+ 4245492555 = GetInt(Mkbin([253,13,19,75])),
+ 4294967294 = GetInt(Mkbin([255,255,255,254])),
+ 4294967295 = GetInt(Mkbin([255,255,255,255])),
+ Eight = [200,1,19,128,222,42,97,111],
+ Cmp128(Eight, Uint(Eight)),
+ FunClause(catch GetInt(Mkbin(lists:seq(1,5))))
+ end,
+ Integer(),
+
+ Sint = fun(Bin) ->
+ case Bin of
+ <<I:8/signed>> -> I;
+ <<I:8/signed,_:3,_:5>> -> I;
+ Other -> {no_match,Other}
+ end
+ end,
+
+ SignedInteger = fun() ->
+ {no_match,_} = Sint(Mkbin([])),
+ {no_match,_} = Sint(Mkbin([1,2,3])),
+ 127 = Sint(Mkbin([127])),
+ -1 = Sint(Mkbin([255])),
+ -128 = Sint(Mkbin([128])),
+ 42 = Sint(Mkbin([42,255])),
+ 127 = Sint(Mkbin([127,255]))
+ end,
+ SignedInteger(),
+
+ Dynamic5 = fun(Bin, S1, S2, A, B) ->
+ case Bin of
+ <<A:S1,B:S2>> ->
+ %% io:format(\"~p ~p ~p ~p~n\", [S1,S2,A,B]),
+ ok;
+ _Other -> erlang:error(badmatch, [Bin,S1,S2,A,B])
+ end
+ end,
+
+ Dynamic2 = fun(Bin, S1, F) when S1 >= 0 ->
+ S2 = size(Bin) * 8 - S1,
+ Dynamic5(Bin, S1, S2, (1 bsl S1) - 1, (1 bsl S2) - 1),
+ F(Bin, S1-1, F);
+ (_, _, _) -> ok
+ end,
+
+ Dynamic = fun(Bin, S1) ->
+ Dynamic2(Bin, S1, Dynamic2)
+ end,
+
+ Dynamic(Mkbin([255]), 8),
+ Dynamic(Mkbin([255,255]), 16),
+ Dynamic(Mkbin([255,255,255]), 24),
+ Dynamic(Mkbin([255,255,255,255]), 32),
+
+ BigToLittle4 =
+ fun([B0,B1,B2,B3,B4,B5,B6,B7|T], N, Acc, F) when N >= 8 ->
+ F(T, N-8, [B0,B1,B2,B3,B4,B5,B6,B7|Acc], F);
+ (List, N, Acc, _F) -> lists:sublist(List, 1, N) ++ Acc
+ end,
+
+ BigToLittle =
+ fun(List, N) -> BigToLittle4(List, N, [], BigToLittle4) end,
+
+ ReversedSublist =
+ fun(_List, 0, Acc, _F) -> Acc;
+ ([H|T], N, Acc, F) -> F(T, N-1, [H|Acc], F)
+ end,
+
+ TwoComplementAndReverse =
+ fun([H|T], Carry, Acc, F) ->
+ Sum = 1-H+Carry,
+ F(T, Sum div 2, [Sum rem 2|Acc], F);
+ ([], Carry, Acc, _F) -> [Carry|Acc]
+ end,
+
+ MakeInt = fun(_List, 0, Acc, _F) -> Acc;
+ ([H|T], N, Acc, F) -> F(T, N-1, Acc bsl 1 bor H, F)
+ end,
+
+ MakeSignedInt =
+ fun(_List, 0) -> 0;
+ ([0|_]=List, N) -> MakeInt(List, N, 0, MakeInt);
+ ([1|_]=List0, N) ->
+ List1 = ReversedSublist(List0, N, [], ReversedSublist),
+ List2 = TwoComplementAndReverse(List1, 1, [],
+ TwoComplementAndReverse),
+ -MakeInt(List2, length(List2), 0, MakeInt)
+ end,
+
+ BitsToList =
+ fun([H|T], 0, F) -> F(T, 16#80, F);
+ ([H|_]=List, Mask, F) ->
+ [case H band Mask of
0 -> 0;
_ -> 1
- end | F(List, Mask bsr 1, F)];
- ([], _, _F) -> []
- end,
-
- MoreDynamic3 =
- fun(Action, Bin, List, Bef, Aft, F) when Bef =< Aft ->
- Action(Bin, List, Bef, Aft-Bef),
- F(Action, Bin, List, Bef, Aft-1, F);
- (_, _, _, _, _, _) -> ok
- end,
-
- MoreDynamic2 =
- fun(Action, Bin, [_|T]=List, Bef, F) ->
- MoreDynamic3(Action, Bin, List, Bef, size(Bin)*8,
- MoreDynamic3),
- F(Action, Bin, T, Bef+1, F);
- (_, _, [], _, _F) -> ok
- end,
-
- MoreDynamic1 =
- fun(Action, Bin) ->
- BitList = BitsToList(binary_to_list(Bin),16#80,BitsToList),
- MoreDynamic2(Action, Bin, BitList, 0, MoreDynamic2)
- end,
-
- MoreDynamic = fun() ->
- % Unsigned big-endian numbers.
- Unsigned = fun(Bin, List, SkipBef, N) ->
- SkipAft = 8*size(Bin) - N - SkipBef,
- <<_:SkipBef,Int:N,_:SkipAft>> = Bin,
- Int = MakeInt(List, N, 0, MakeInt)
- end,
- MoreDynamic1(Unsigned, erlang:md5(Mkbin([42]))),
+ end | F(List, Mask bsr 1, F)];
+ ([], _, _F) -> []
+ end,
+
+ MoreDynamic3 =
+ fun(Action, Bin, List, Bef, Aft, F) when Bef =< Aft ->
+ Action(Bin, List, Bef, Aft-Bef),
+ F(Action, Bin, List, Bef, Aft-1, F);
+ (_, _, _, _, _, _) -> ok
+ end,
+
+ MoreDynamic2 =
+ fun(Action, Bin, [_|T]=List, Bef, F) ->
+ MoreDynamic3(Action, Bin, List, Bef, size(Bin)*8,
+ MoreDynamic3),
+ F(Action, Bin, T, Bef+1, F);
+ (_, _, [], _, _F) -> ok
+ end,
+
+ MoreDynamic1 =
+ fun(Action, Bin) ->
+ BitList = BitsToList(binary_to_list(Bin),16#80,BitsToList),
+ MoreDynamic2(Action, Bin, BitList, 0, MoreDynamic2)
+ end,
+
+ MoreDynamic = fun() ->
+ %% Unsigned big-endian numbers.
+ Unsigned = fun(Bin, List, SkipBef, N) ->
+ SkipAft = 8*size(Bin) - N - SkipBef,
+ <<_:SkipBef,Int:N,_:SkipAft>> = Bin,
+ Int = MakeInt(List, N, 0, MakeInt)
+ end,
+ MoreDynamic1(Unsigned, erlang:md5(Mkbin([42]))),
%% Signed big-endian numbers.
- Signed = fun(Bin, List, SkipBef, N) ->
- SkipAft = 8*size(Bin) - N - SkipBef,
- <<_:SkipBef,Int:N/signed,_:SkipAft>> = Bin,
- case MakeSignedInt(List, N) of
- Int -> ok;
- Other ->
- io:format(\"Bin = ~p,\", [Bin]),
+ Signed = fun(Bin, List, SkipBef, N) ->
+ SkipAft = 8*size(Bin) - N - SkipBef,
+ <<_:SkipBef,Int:N/signed,_:SkipAft>> = Bin,
+ case MakeSignedInt(List, N) of
+ Int -> ok;
+ Other ->
+ io:format(\"Bin = ~p,\", [Bin]),
io:format(\"SkipBef = ~p, N = ~p\",
[SkipBef,N]),
- io:format(\"Expected ~p, got ~p\",
+ io:format(\"Expected ~p, got ~p\",
[Int,Other])
- end
- end,
- MoreDynamic1(Signed, erlang:md5(Mkbin([43]))),
+ end
+ end,
+ MoreDynamic1(Signed, erlang:md5(Mkbin([43]))),
%% Unsigned little-endian numbers.
- UnsLittle = fun(Bin, List, SkipBef, N) ->
- SkipAft = 8*size(Bin) - N - SkipBef,
- <<_:SkipBef,Int:N/little,_:SkipAft>> = Bin,
- Int = MakeInt(BigToLittle(List, N), N, 0,
- MakeInt)
- end,
- MoreDynamic1(UnsLittle, erlang:md5(Mkbin([44]))),
+ UnsLittle = fun(Bin, List, SkipBef, N) ->
+ SkipAft = 8*size(Bin) - N - SkipBef,
+ <<_:SkipBef,Int:N/little,_:SkipAft>> = Bin,
+ Int = MakeInt(BigToLittle(List, N), N, 0,
+ MakeInt)
+ end,
+ MoreDynamic1(UnsLittle, erlang:md5(Mkbin([44]))),
%% Signed little-endian numbers.
- SignLittle = fun(Bin, List, SkipBef, N) ->
- SkipAft = 8*size(Bin) - N - SkipBef,
- <<_:SkipBef,Int:N/signed-little,_:SkipAft>> = Bin,
- Little = BigToLittle(List, N),
- Int = MakeSignedInt(Little, N)
- end,
- MoreDynamic1(SignLittle, erlang:md5(Mkbin([45])))
- end,
- MoreDynamic(),
-
- ok.
- ">>,
+ SignLittle = fun(Bin, List, SkipBef, N) ->
+ SkipAft = 8*size(Bin) - N - SkipBef,
+ <<_:SkipBef,Int:N/signed-little,_:SkipAft>> = Bin,
+ Little = BigToLittle(List, N),
+ Int = MakeSignedInt(Little, N)
+ end,
+ MoreDynamic1(SignLittle, erlang:md5(Mkbin([45])))
+ end,
+ MoreDynamic(),
+
+ ok.
+">>,
[ok] = scan(C),
- ok = evaluate(C, []).
+ok = evaluate(C, []).
-bs_match_tail_SUITE(doc) ->
- ["OTP-5327. Adopted from emulator/test/bs_match_tail_SUITE.erl."];
-bs_match_tail_SUITE(suite) ->
- [];
+%% OTP-5327. Adopted from emulator/test/bs_match_tail_SUITE.erl.
bs_match_tail_SUITE(Config) when is_list(Config) ->
C = <<"
GetTailUsed = fun(<<A:1,T/binary>>) -> {A,T} end,
@@ -1211,13 +1167,13 @@ bs_match_tail_SUITE(Config) when is_list(Config) ->
GetTailUnused = fun(<<A:15,_/binary>>) -> A end,
GetDynTailUsed = fun(Bin, Sz) ->
- <<A:Sz,T/binary>> = Bin,
- {A,T}
+ <<A:Sz,T/binary>> = Bin,
+ {A,T}
end,
GetDynTailUnused = fun(Bin, Sz) ->
- <<A:Sz,_/binary>> = Bin,
- A
+ <<A:Sz,_/binary>> = Bin,
+ A
end,
Mkbin = fun(L) when list(L) -> list_to_binary(L) end,
@@ -1227,12 +1183,12 @@ bs_match_tail_SUITE(Config) when is_list(Config) ->
TestZeroTail2 = fun(<<_A:4,_B:4>>) -> ok end,
ZeroTail = fun() ->
- 7 = (catch TestZeroTail(Mkbin([7]))),
- {'EXIT',{function_clause,_}} =
- (catch TestZeroTail(Mkbin([1,2]))),
- {'EXIT',{function_clause,_}} =
- (catch TestZeroTail2(Mkbin([1,2,3])))
- end,
+ 7 = (catch TestZeroTail(Mkbin([7]))),
+ {'EXIT',{function_clause,_}} =
+ (catch TestZeroTail(Mkbin([1,2]))),
+ {'EXIT',{function_clause,_}} =
+ (catch TestZeroTail2(Mkbin([1,2,3])))
+ end,
ZeroTail(),
AlGetTailUsed = fun(<<A:16,T/binary>>) -> {A,T} end,
@@ -1240,45 +1196,42 @@ bs_match_tail_SUITE(Config) when is_list(Config) ->
AlGetTailUnused = fun(<<A:16,_/binary>>) -> A end,
Aligned = fun() ->
- Tail1 = Mkbin([]),
- {258,Tail1} = AlGetTailUsed(Mkbin([1,2])),
- Tail2 = Mkbin(lists:seq(1, 127)),
- {35091,Tail2} = AlGetTailUsed(Mkbin([137,19|Tail2])),
-
- 64896 = AlGetTailUnused(Mkbin([253,128])),
- 64895 = AlGetTailUnused(Mkbin([253,127|lists:seq(42, 255)])),
-
- Tail3 = Mkbin(lists:seq(0, 19)),
- {0,Tail1} = GetDynTailUsed(Tail1, 0),
- {0,Tail3} = GetDynTailUsed(Mkbin([Tail3]), 0),
- {73,Tail3} = GetDynTailUsed(Mkbin([73|Tail3]), 8),
-
- 0 = GetDynTailUnused(Mkbin([]), 0),
- 233 = GetDynTailUnused(Mkbin([233]), 8),
- 23 = GetDynTailUnused(Mkbin([23,22,2]), 8)
- end,
+ Tail1 = Mkbin([]),
+ {258,Tail1} = AlGetTailUsed(Mkbin([1,2])),
+ Tail2 = Mkbin(lists:seq(1, 127)),
+ {35091,Tail2} = AlGetTailUsed(Mkbin([137,19|Tail2])),
+
+ 64896 = AlGetTailUnused(Mkbin([253,128])),
+ 64895 = AlGetTailUnused(Mkbin([253,127|lists:seq(42, 255)])),
+
+ Tail3 = Mkbin(lists:seq(0, 19)),
+ {0,Tail1} = GetDynTailUsed(Tail1, 0),
+ {0,Tail3} = GetDynTailUsed(Mkbin([Tail3]), 0),
+ {73,Tail3} = GetDynTailUsed(Mkbin([73|Tail3]), 8),
+
+ 0 = GetDynTailUnused(Mkbin([]), 0),
+ 233 = GetDynTailUnused(Mkbin([233]), 8),
+ 23 = GetDynTailUnused(Mkbin([23,22,2]), 8)
+ end,
Aligned(),
-
+
UnAligned = fun() ->
- {'EXIT',{function_clause,_}} =
- (catch GetTailUsed(Mkbin([42]))),
- {'EXIT',{{badmatch,_},_}} =
- (catch GetDynTailUsed(Mkbin([137]), 3)),
- {'EXIT',{function_clause,_}} =
- (catch GetTailUnused(Mkbin([42,33]))),
- {'EXIT',{{badmatch,_},_}} =
- (catch GetDynTailUnused(Mkbin([44]), 7))
- end,
+ {'EXIT',{function_clause,_}} =
+ (catch GetTailUsed(Mkbin([42]))),
+ {'EXIT',{{badmatch,_},_}} =
+ (catch GetDynTailUsed(Mkbin([137]), 3)),
+ {'EXIT',{function_clause,_}} =
+ (catch GetTailUnused(Mkbin([42,33]))),
+ {'EXIT',{{badmatch,_},_}} =
+ (catch GetDynTailUnused(Mkbin([44]), 7))
+ end,
UnAligned(),
ok.
- ">>,
+">>,
[ok] = scan(C),
- ok = evaluate(C, []).
+ok = evaluate(C, []).
-bs_match_bin_SUITE(doc) ->
- ["OTP-5327. Adopted from emulator/test/bs_match_bin_SUITE.erl."];
-bs_match_bin_SUITE(suite) ->
- [];
+%% OTP-5327. Adopted from emulator/test/bs_match_bin_SUITE.erl.
bs_match_bin_SUITE(Config) when is_list(Config) ->
ByteSplitBinary =
<<"ByteSplit =
@@ -1288,252 +1241,249 @@ bs_match_bin_SUITE(Config) when is_list(Config) ->
<<B1:Sz1/binary,B2:Sz2/binary>> = B,
B1 = list_to_binary(lists:sublist(L, 1, Pos)),
B2 = list_to_binary(lists:nthtail(Pos, L)),
- Fun(L, B, Pos-1, Fun);
- (L, B, _, _Fun) -> ok
- end,
- Mkbin = fun(L) when list(L) -> list_to_binary(L) end,
- L = lists:seq(0, 57),
- B = Mkbin(L),
- ByteSplit(L, B, size(B), ByteSplit),
- Id = fun(I) -> I end,
- MakeUnalignedSubBinary =
- fun(Bin0) ->
- Bin1 = <<0:3,Bin0/binary,31:5>>,
- Sz = size(Bin0),
- <<0:3,Bin:Sz/binary,31:5>> = Id(Bin1),
- Bin
+ Fun(L, B, Pos-1, Fun);
+ (L, B, _, _Fun) -> ok
end,
- Unaligned = MakeUnalignedSubBinary(B),
- ByteSplit(L, Unaligned, size(Unaligned), ByteSplit),
- ok.
- ">>,
+ Mkbin = fun(L) when list(L) -> list_to_binary(L) end,
+ L = lists:seq(0, 57),
+ B = Mkbin(L),
+ ByteSplit(L, B, size(B), ByteSplit),
+ Id = fun(I) -> I end,
+ MakeUnalignedSubBinary =
+ fun(Bin0) ->
+ Bin1 = <<0:3,Bin0/binary,31:5>>,
+ Sz = size(Bin0),
+ <<0:3,Bin:Sz/binary,31:5>> = Id(Bin1),
+ Bin
+ end,
+ Unaligned = MakeUnalignedSubBinary(B),
+ ByteSplit(L, Unaligned, size(Unaligned), ByteSplit),
+ ok.
+">>,
[ok] = scan(ByteSplitBinary),
- ok = evaluate(ByteSplitBinary, []),
- BitSplitBinary =
- <<"Mkbin = fun(L) when list(L) -> list_to_binary(L) end,
+ok = evaluate(ByteSplitBinary, []),
+BitSplitBinary =
+<<"Mkbin = fun(L) when list(L) -> list_to_binary(L) end,
MakeInt =
- fun(List, 0, Acc, _F) -> Acc;
- ([H|T], N, Acc, F) -> F(T, N-1, Acc bsl 1 bor H, F)
- end,
-
- MakeBinFromList =
- fun(List, 0, _F) -> Mkbin([]);
- (List, N, F) ->
- list_to_binary([MakeInt(List, 8, 0, MakeInt),
- F(lists:nthtail(8, List), N-8, F)])
- end,
-
- BitSplitBinary3 =
- fun(Action, Bin, List, Bef, Aft, F) when Bef =< Aft ->
- Action(Bin, List, Bef, (Aft-Bef) div 8 * 8),
- F(Action, Bin, List, Bef, Aft-8, F);
- (_, _, _, _, _, _) -> ok
- end,
-
- BitSplitBinary2 =
- fun(Action, Bin, [_|T]=List, Bef, F) ->
- BitSplitBinary3(Action, Bin, List, Bef, size(Bin)*8,
- BitSplitBinary3),
- F(Action, Bin, T, Bef+1, F);
- (Action, Bin, [], Bef, F) -> ok
- end,
-
- BitsToList =
- fun([H|T], 0, F) -> F(T, 16#80, F);
- ([H|_]=List, Mask, F) ->
- [case H band Mask of
- 0 -> 0;
- _ -> 1
- end | F(List, Mask bsr 1, F)];
- ([], _, _F) -> []
- end,
-
- BitSplitBinary1 =
- fun(Action, Bin) ->
- BitList = BitsToList(binary_to_list(Bin), 16#80,
- BitsToList),
- BitSplitBinary2(Action, Bin, BitList, 0, BitSplitBinary2)
- end,
-
- Fun = fun(Bin, List, SkipBef, N) ->
- SkipAft = 8*size(Bin) - N - SkipBef,
- <<I1:SkipBef,OutBin:N/binary-unit:1,I2:SkipAft>> = Bin,
- OutBin = MakeBinFromList(List, N, MakeBinFromList)
- end,
-
- BitSplitBinary1(Fun, erlang:md5(<<1,2,3>>)),
- Id = fun(I) -> I end,
- MakeUnalignedSubBinary =
- fun(Bin0) ->
- Bin1 = <<0:3,Bin0/binary,31:5>>,
- Sz = size(Bin0),
- <<0:3,Bin:Sz/binary,31:5>> = Id(Bin1),
- Bin
- end,
- BitSplitBinary1(Fun, MakeUnalignedSubBinary(erlang:md5(<<1,2,3>>))),
- ok.
- ">>,
+ fun(List, 0, Acc, _F) -> Acc;
+ ([H|T], N, Acc, F) -> F(T, N-1, Acc bsl 1 bor H, F)
+ end,
+
+ MakeBinFromList =
+ fun(List, 0, _F) -> Mkbin([]);
+ (List, N, F) ->
+ list_to_binary([MakeInt(List, 8, 0, MakeInt),
+ F(lists:nthtail(8, List), N-8, F)])
+ end,
+
+ BitSplitBinary3 =
+ fun(Action, Bin, List, Bef, Aft, F) when Bef =< Aft ->
+ Action(Bin, List, Bef, (Aft-Bef) div 8 * 8),
+ F(Action, Bin, List, Bef, Aft-8, F);
+ (_, _, _, _, _, _) -> ok
+ end,
+
+ BitSplitBinary2 =
+ fun(Action, Bin, [_|T]=List, Bef, F) ->
+ BitSplitBinary3(Action, Bin, List, Bef, size(Bin)*8,
+ BitSplitBinary3),
+ F(Action, Bin, T, Bef+1, F);
+ (Action, Bin, [], Bef, F) -> ok
+ end,
+
+ BitsToList =
+ fun([H|T], 0, F) -> F(T, 16#80, F);
+ ([H|_]=List, Mask, F) ->
+ [case H band Mask of
+ 0 -> 0;
+ _ -> 1
+ end | F(List, Mask bsr 1, F)];
+ ([], _, _F) -> []
+ end,
+
+ BitSplitBinary1 =
+ fun(Action, Bin) ->
+ BitList = BitsToList(binary_to_list(Bin), 16#80,
+ BitsToList),
+ BitSplitBinary2(Action, Bin, BitList, 0, BitSplitBinary2)
+ end,
+
+ Fun = fun(Bin, List, SkipBef, N) ->
+ SkipAft = 8*size(Bin) - N - SkipBef,
+ <<I1:SkipBef,OutBin:N/binary-unit:1,I2:SkipAft>> = Bin,
+ OutBin = MakeBinFromList(List, N, MakeBinFromList)
+ end,
+
+ BitSplitBinary1(Fun, erlang:md5(<<1,2,3>>)),
+ Id = fun(I) -> I end,
+ MakeUnalignedSubBinary =
+ fun(Bin0) ->
+ Bin1 = <<0:3,Bin0/binary,31:5>>,
+ Sz = size(Bin0),
+ <<0:3,Bin:Sz/binary,31:5>> = Id(Bin1),
+ Bin
+ end,
+ BitSplitBinary1(Fun, MakeUnalignedSubBinary(erlang:md5(<<1,2,3>>))),
+ ok.
+">>,
[ok] = scan(BitSplitBinary),
- ok = evaluate(BitSplitBinary, []).
+ok = evaluate(BitSplitBinary, []).
-define(FAIL(Expr), "{'EXIT',{badarg,_}} = (catch " ??Expr ")").
-define(COF(Int0),
"(fun(Int) ->
true = <<Int:32/float>> =:= <<(float(Int)):32/float>>,
- true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
- end)(Nonliteral(" ??Int0 ")),
- true = <<" ??Int0 ":32/float>> =:= <<(float("??Int0")):32/float>>,
- true = <<" ??Int0 ":64/float>> =:= <<(float("??Int0")):64/float>>").
+ true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
+ end)(Nonliteral(" ??Int0 ")),
+true = <<" ??Int0 ":32/float>> =:= <<(float("??Int0")):32/float>>,
+true = <<" ??Int0 ":64/float>> =:= <<(float("??Int0")):64/float>>").
-define(COF64(Int0),
"(fun(Int) ->
true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
- end)(Nonliteral(" ??Int0 ")),
- true = <<" ??Int0 ":64/float>> =:= <<(float("??Int0")):64/float>>").
+ end)(Nonliteral(" ??Int0 ")),
+true = <<" ??Int0 ":64/float>> =:= <<(float("??Int0")):64/float>>").
-bs_construct_SUITE(doc) ->
- ["OTP-5327. Adopted from parts of emulator/test/bs_construct_SUITE.erl."];
-bs_construct_SUITE(suite) ->
- [];
+%% OTP-5327. Adopted from parts of emulator/test/bs_construct_SUITE.erl.
bs_construct_SUITE(Config) when is_list(Config) ->
C1 = <<"
Testf_1 = fun(W, B) -> "
?FAIL(<<42:W>>) ","
- ?FAIL(<<3.14:W/float>>) ","
- ?FAIL(<<B:W/binary>>) "
+ ?FAIL(<<3.14:W/float>>) ","
+ ?FAIL(<<B:W/binary>>) "
end,
- TestF = fun() -> "
+ TestF = fun() -> "
?FAIL(<<3.14>>) ","
- ?FAIL(<<<<1,2>>>>) ","
+ ?FAIL(<<<<1,2>>>>) ","
- ?FAIL(<<2.71/binary>>) ","
- ?FAIL(<<24334/binary>>) ","
- ?FAIL(<<24334344294788947129487129487219847/binary>>) ","
+ ?FAIL(<<2.71/binary>>) ","
+ ?FAIL(<<24334/binary>>) ","
+ ?FAIL(<<24334344294788947129487129487219847/binary>>) ","
- ?FAIL(<<<<1,2,3>>/float>>) ",
+ ?FAIL(<<<<1,2,3>>/float>>) ",
%% Negative field widths.
Testf_1(-8, <<1,2,3,4,5>>),"
?FAIL(<<42:(-16)>>) ","
- ?FAIL(<<3.14:(-8)/float>>) ","
- ?FAIL(<<<<23,56,0,2>>:(-16)/binary>>) ","
- ?FAIL(<<<<23,56,0,2>>:(2.5)/binary>>) ","
- ?FAIL(<<<<23,56,0,2>>:(anka)>>) "
+ ?FAIL(<<3.14:(-8)/float>>) ","
+ ?FAIL(<<<<23,56,0,2>>:(-16)/binary>>) ","
+ ?FAIL(<<<<23,56,0,2>>:(2.5)/binary>>) ","
+ ?FAIL(<<<<23,56,0,2>>:(anka)>>) "
end,
- TestF(),
+ TestF(),
- NotUsed1 = fun(I, BinString) -> <<I:32,BinString/binary>>, ok end,
+ NotUsed1 = fun(I, BinString) -> <<I:32,BinString/binary>>, ok end,
- NotUsed2 = fun(I, Sz) -> <<I:Sz>>, ok end,
+ NotUsed2 = fun(I, Sz) -> <<I:Sz>>, ok end,
- NotUsed3 = fun(I) -><<I:(-8)>>, ok end,
+ NotUsed3 = fun(I) -><<I:(-8)>>, ok end,
- NotUsed = fun() ->
- ok = NotUsed1(3, <<\"dum\">>),
+ NotUsed = fun() ->
+ ok = NotUsed1(3, <<\"dum\">>),
{'EXIT',{badarg,_}} = (catch NotUsed1(3, \"dum\")), "
- ?FAIL(NotUsed2(444, -2)) ","
- ?FAIL(NotUsed2(444, anka)) ","
- ?FAIL(NotUsed3(444)) "
+ ?FAIL(NotUsed2(444, -2)) ","
+ ?FAIL(NotUsed2(444, anka)) ","
+ ?FAIL(NotUsed3(444)) "
end,
- NotUsed(),
-
- InGuard3 = fun(Bin, A, B) when <<A:13,B:3>> == Bin -> 1;
- (Bin, A, B) when <<A:16,B/binary>> == Bin -> 2;
- (Bin, A, B) when <<A:14,B/float,3:2>> == Bin -> 3;
- (Bin, A, B) when {a,b,<<A:14,B/float,3:2>>} == Bin ->
- cant_happen;
- (_, _, _) -> nope
- end,
-
- InGuard = fun() ->
- 1 = InGuard3(<<16#74ad:16>>, 16#e95, 5),
- 2 = InGuard3(<<16#3A,16#F7,\"hello\">>, 16#3AF7, <<\"hello\">>),
+ NotUsed(),
+
+ InGuard3 = fun(Bin, A, B) when <<A:13,B:3>> == Bin -> 1;
+ (Bin, A, B) when <<A:16,B/binary>> == Bin -> 2;
+ (Bin, A, B) when <<A:14,B/float,3:2>> == Bin -> 3;
+ (Bin, A, B) when {a,b,<<A:14,B/float,3:2>>} == Bin ->
+ cant_happen;
+ (_, _, _) -> nope
+ end,
+
+ InGuard = fun() ->
+ 1 = InGuard3(<<16#74ad:16>>, 16#e95, 5),
+ 2 = InGuard3(<<16#3A,16#F7,\"hello\">>, 16#3AF7, <<\"hello\">>),
3 = InGuard3(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415),
- nope = InGuard3(<<1>>, 42, b),
- nope = InGuard3(<<1>>, a, b),
- nope = InGuard3(<<1,2>>, 1, 1),
- nope = InGuard3(<<4,5>>, 1, 2.71),
- nope = InGuard3(<<4,5>>, 1, <<12,13>>)
- end,
- InGuard(),
+ nope = InGuard3(<<1>>, 42, b),
+ nope = InGuard3(<<1>>, a, b),
+ nope = InGuard3(<<1,2>>, 1, 1),
+ nope = InGuard3(<<4,5>>, 1, 2.71),
+ nope = InGuard3(<<4,5>>, 1, <<12,13>>)
+ end,
+ InGuard(),
- Nonliteral = fun(X) -> X end,
+ Nonliteral = fun(X) -> X end,
- CoerceToFloat = fun() -> "
+ CoerceToFloat = fun() -> "
?COF(0) ","
- ?COF(-1) ","
- ?COF(1) ","
- ?COF(42) ","
- ?COF(255) ","
- ?COF(-255) ","
- ?COF64(298748888888888888888888888883478264866528467367364766666666666666663) ","
- ?COF64(-367546729879999999999947826486652846736736476555566666663) "
+ ?COF(-1) ","
+ ?COF(1) ","
+ ?COF(42) ","
+ ?COF(255) ","
+ ?COF(-255) ","
+ ?COF64(298748888888888888888888888883478264866528467367364766666666666666663) ","
+ ?COF64(-367546729879999999999947826486652846736736476555566666663) "
end,
- CoerceToFloat(),
- ok.
- ">>,
+ CoerceToFloat(),
+ ok.
+">>,
[ok] = scan(C1),
- ok = evaluate(C1, []),
+ok = evaluate(C1, []),
- %% There is another one, lib/compiler/test/bs_construct_SUITE.erl...
- C2 = <<"
+%% There is another one, lib/compiler/test/bs_construct_SUITE.erl...
+C2 = <<"
I = fun(X) -> X end,
Fail = fun() ->
- I_minus_777 = I(-777),
- I_minus_2047 = I(-2047),
+ I_minus_777 = I(-777),
+ I_minus_2047 = I(-2047),
%% One negative field size, but the sum of field sizes will be 1 byte.
%% Make sure that we reject that properly.
- {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8,
- 57:I_minus_2047/unit:8>>),
+ {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8,
+ 57:I_minus_2047/unit:8>>),
%% Same thing, but use literals.
- {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8,
- 57:(-2047)/unit:8>>),
+ {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8,
+ 57:(-2047)/unit:8>>),
%% Bad alignment.
- I_one = I(1),
- <<1:1>> = <<2375:I_one>>,
- <<3:2>> = <<45:1,2375:I_one>>,
- <<14:4>> = <<45:1,2375:I_one,918:2>>,
- <<118:7>> = <<45:1,2375:I_one,918:5>>,
+ I_one = I(1),
+ <<1:1>> = <<2375:I_one>>,
+ <<3:2>> = <<45:1,2375:I_one>>,
+ <<14:4>> = <<45:1,2375:I_one,918:2>>,
+ <<118:7>> = <<45:1,2375:I_one,918:5>>,
%% Not numbers.
- {'EXIT',{badarg,_}} = (catch <<45:(I(not_a_number))>>),
- {'EXIT',{badarg,_}} = (catch <<13:8,45:(I(not_a_number))>>),
+ {'EXIT',{badarg,_}} = (catch <<45:(I(not_a_number))>>),
+ {'EXIT',{badarg,_}} = (catch <<13:8,45:(I(not_a_number))>>),
%% Unaligned sizes.
- BadSz = I(7),
- <<2:4>> = <<34:4>>,
- <<34:7>> = <<34:BadSz>>,
+ BadSz = I(7),
+ <<2:4>> = <<34:4>>,
+ <<34:7>> = <<34:BadSz>>,
- [] = [X || {X} <- [], X == <<3:BadSz>>],
- [] = [X || {X} <- [], X == <<3:4>>]
- end,
+ [] = [X || {X} <- [], X == <<3:BadSz>>],
+ [] = [X || {X} <- [], X == <<3:4>>]
+ end,
Fail(),
FloatBin1 = fun(F) ->
- {<<1,2,3>>,F+3.0}
- end,
+ {<<1,2,3>>,F+3.0}
+ end,
FloatBin = fun() ->
%% Some more coverage.
- {<<1,2,3>>,7.0} = FloatBin1(4)
- end,
+ {<<1,2,3>>,7.0} = FloatBin1(4)
+ end,
FloatBin(),
ok.
- ">>,
+">>,
[ok] = scan(C2),
- ok = evaluate(C2, []).
+ok = evaluate(C2, []).
evaluate(B, Vars) when is_binary(B) ->
evaluate(binary_to_list(B), Vars);
@@ -1547,60 +1497,55 @@ evaluate(Str, Vars) ->
end.
-refman_bit_syntax(doc) ->
- ["Bit syntax examples from the Reference Manual. OTP-5237."];
-refman_bit_syntax(suite) ->
- [];
+%% Bit syntax examples from the Reference Manual. OTP-5237.
refman_bit_syntax(Config) when is_list(Config) ->
%% Reference Manual "Bit Syntax Expressions"
- ?line Bin1 = <<1,17,42>>,
- ?line true = [1,17,42] =:= binary_to_list(Bin1),
- ?line Bin2 = <<"abc">>,
- ?line true = "abc" =:= binary_to_list(Bin2),
- ?line Bin3 = <<1,17,42:16>>,
- ?line true = [1,17,0,42] =:= binary_to_list(Bin3),
- ?line <<_A,_B,C:16>> = <<1,17,42:16>>,
- ?line true = C =:= 42,
- ?line <<D:16,_E,F>> = <<1,17,42:16>>,
- ?line true = D =:= 273,
- ?line true = F =:= 42,
+ Bin1 = <<1,17,42>>,
+ true = [1,17,42] =:= binary_to_list(Bin1),
+ Bin2 = <<"abc">>,
+ true = "abc" =:= binary_to_list(Bin2),
+ Bin3 = <<1,17,42:16>>,
+ true = [1,17,0,42] =:= binary_to_list(Bin3),
+ <<_A,_B,C:16>> = <<1,17,42:16>>,
+ true = C =:= 42,
+ <<D:16,_E,F>> = <<1,17,42:16>>,
+ true = D =:= 273,
+ true = F =:= 42,
<<_G,H/binary>> = <<1,17,42:16>>,
- ?line true = H =:= <<17,0,42>>,
+ true = H =:= <<17,0,42>>,
- ?line [ok] =
+ [ok] =
scan(<<"Bin1 = <<1,17,42>>,
true = [1,17,42] =:= binary_to_list(Bin1),
- Bin2 = <<\"abc\">>,
+ Bin2 = <<\"abc\">>,
true = \"abc\" =:= binary_to_list(Bin2),
Bin3 = <<1,17,42:16>>,
- true =
- [1,17,0,42] =:= binary_to_list(Bin3),
- <<A,B,C:16>> = <<1,17,42:16>>,
- true = C =:= 42,
- <<D:16,E,F>> = <<1,17,42:16>>,
- true = D =:= 273,
- true = F =:= 42,
- <<G,H/binary>> = <<1,17,42:16>>,
- true = H =:= <<17,0,42>>,
- ok.">>),
+ true =
+ [1,17,0,42] =:= binary_to_list(Bin3),
+ <<A,B,C:16>> = <<1,17,42:16>>,
+ true = C =:= 42,
+ <<D:16,E,F>> = <<1,17,42:16>>,
+ true = D =:= 273,
+ true = F =:= 42,
+ <<G,H/binary>> = <<1,17,42:16>>,
+ true = H =:= <<17,0,42>>,
+ ok.">>),
%% Binary comprehensions.
- ?line <<2,4,6>> = << << (X*2) >> || <<X>> <= << 1,2,3 >> >>,
- ok.
+ <<2,4,6>> = << << (X*2) >> || <<X>> <= << 1,2,3 >> >>,
+ ok.
-define(IP_VERSION, 4).
-define(IP_MIN_HDR_LEN, 5).
-progex_bit_syntax(doc) ->
- ["Bit syntax examples from Programming Examples. OTP-5237."];
-progex_bit_syntax(suite) ->
- [];
+
+%% Bit syntax examples from Programming Examples. OTP-5237.
progex_bit_syntax(Config) when is_list(Config) ->
Bin11 = <<1, 17, 42>>,
true = [1, 17, 42] =:= binary_to_list(Bin11),
Bin12 = <<"abc">>,
true = [97, 98, 99] =:= binary_to_list(Bin12),
-
+
A = 1, B = 17, C = 42,
Bin2 = <<A, B, C:16>>,
true = [1, 17, 00, 42] =:= binary_to_list(Bin2),
@@ -1613,10 +1558,10 @@ progex_bit_syntax(Config) when is_list(Config) ->
DgramSize = byte_size(Dgram),
case Dgram of
<<?IP_VERSION:4, HLen:4, SrvcType:8, TotLen:16,
- ID:16, Flgs:3, FragOff:13,
- TTL:8, Proto:8, HdrChkSum:16,
- SrcIP:32, DestIP:32,
- RestDgram/binary>> when HLen>=5, 4*HLen=<DgramSize ->
+ ID:16, Flgs:3, FragOff:13,
+ TTL:8, Proto:8, HdrChkSum:16,
+ SrcIP:32, DestIP:32,
+ RestDgram/binary>> when HLen>=5, 4*HLen=<DgramSize ->
OptsLen = 4*(HLen - ?IP_MIN_HDR_LEN),
<<Opts:OptsLen/binary,Data/binary>> = RestDgram,
{SrvcType, TotLen, Flgs, FragOff, ID, HdrChkSum,
@@ -1653,57 +1598,57 @@ progex_bit_syntax(Config) when is_list(Config) ->
B2 = triples_to_bin2(BL),
true = Lst =:= binary_to_list(B2),
- ?line [ok] = scan(
- <<"Bin11 = <<1, 17, 42>>,
+ [ok] = scan(
+ <<"Bin11 = <<1, 17, 42>>,
true = [1, 17, 42] =:= binary_to_list(Bin11),
- Bin12 = <<\"abc\">>,
+ Bin12 = <<\"abc\">>,
true = [97, 98, 99] =:= binary_to_list(Bin12),
- A = 1, B = 17, C = 42,
- Bin2 = <<A, B, C:16>>,
- true = [1, 17, 00, 42] =:= binary_to_list(Bin2),
- <<D:16, E, F/binary>> = Bin2,
- true = D =:= 273,
- true = E =:= 00,
- true = [42] =:= binary_to_list(F),
-
- Fun4 = fun(Dgram) ->
- DgramSize = byte_size(Dgram),
- case Dgram of
- <<4:4, HLen:4, SrvcType:8, TotLen:16,
- ID:16, Flgs:3, FragOff:13,
- TTL:8, Proto:8, HdrChkSum:16,
- SrcIP:32, DestIP:32,
- RestDgram/binary>> when HLen>=5,
- 4*HLen=<DgramSize ->
- OptsLen = 4*(HLen - 5),
- <<Opts:OptsLen/binary,Data/binary>> = RestDgram,
- {SrvcType, TotLen, Flgs, FragOff, ID, HdrChkSum,
- Proto, TTL, SrcIP, DestIP, Data, Opts};
- _ ->
- not_ok
- end
- end,
- true = Fun4(<<>>) =:= not_ok,
- true = is_tuple(Fun4(list_to_binary
- ([<<4:4,5:4>>,list_to_binary(lists:seq(1,255))]))),
-
- X = 23432324, Y = 24324234,
- <<10:7>> = <<X:1, Y:6>>,
- Z = 234324324,
- XYZ = <<X:1, Y:6, Z:1>>,
- true = [20] =:= binary_to_list(XYZ),
- Hello1 = <<\"hello\">>,
+ A = 1, B = 17, C = 42,
+ Bin2 = <<A, B, C:16>>,
+ true = [1, 17, 00, 42] =:= binary_to_list(Bin2),
+ <<D:16, E, F/binary>> = Bin2,
+ true = D =:= 273,
+ true = E =:= 00,
+ true = [42] =:= binary_to_list(F),
+
+ Fun4 = fun(Dgram) ->
+ DgramSize = byte_size(Dgram),
+ case Dgram of
+ <<4:4, HLen:4, SrvcType:8, TotLen:16,
+ ID:16, Flgs:3, FragOff:13,
+ TTL:8, Proto:8, HdrChkSum:16,
+ SrcIP:32, DestIP:32,
+ RestDgram/binary>> when HLen>=5,
+ 4*HLen=<DgramSize ->
+ OptsLen = 4*(HLen - 5),
+ <<Opts:OptsLen/binary,Data/binary>> = RestDgram,
+ {SrvcType, TotLen, Flgs, FragOff, ID, HdrChkSum,
+ Proto, TTL, SrcIP, DestIP, Data, Opts};
+ _ ->
+ not_ok
+ end
+ end,
+ true = Fun4(<<>>) =:= not_ok,
+ true = is_tuple(Fun4(list_to_binary
+ ([<<4:4,5:4>>,list_to_binary(lists:seq(1,255))]))),
+
+ X = 23432324, Y = 24324234,
+ <<10:7>> = <<X:1, Y:6>>,
+ Z = 234324324,
+ XYZ = <<X:1, Y:6, Z:1>>,
+ true = [20] =:= binary_to_list(XYZ),
+ Hello1 = <<\"hello\">>,
Hello2 = <<$h,$e,$l,$l,$o>>,
- true = \"hello\" =:= binary_to_list(Hello1),
+ true = \"hello\" =:= binary_to_list(Hello1),
true = \"hello\" =:= binary_to_list(Hello2),
FunM1 = fun(<<X1:7/binary, Y1:1/binary>>) -> {X1,Y1} end,
- true = {<<\"1234567\">>,<<\"8\">>} =:= FunM1(<<\"12345678\">>),
+ true = {<<\"1234567\">>,<<\"8\">>} =:= FunM1(<<\"12345678\">>),
FunM2 = fun(<<_X1:7/binary-unit:7, _Y1:1/binary-unit:1>>) -> ok;
(_) -> not_ok end,
- true = not_ok =:= FunM2(<<\"1\">>),
+ true = not_ok =:= FunM2(<<\"1\">>),
ok.">>),
ok.
@@ -1724,590 +1669,577 @@ triples_to_bin2([{X,Y,Z} | T], Acc) ->
triples_to_bin2([], Acc) ->
list_to_binary(lists:reverse(Acc)).
-progex_records(doc) ->
- ["Record examples from Programming Examples. OTP-5237."];
-progex_records(suite) ->
- [];
+%% Record examples from Programming Examples. OTP-5237.
progex_records(Config) when is_list(Config) ->
Test1 =
- <<"-module(recs).
+ <<"-module(recs).
-record(person, {name = \"\", phone = [], address}).
-record(name, {first = \"Robert\", last = \"Ericsson\"}).
-record(person2, {name = #name{}, phone}).
- -export([t/0]).
+-export([t/0]).
- t() ->
- _P1 = #person{phone=[0,8,2,3,4,3,1,2], name=\"Robert\"},
+t() ->
+ _P1 = #person{phone=[0,8,2,3,4,3,1,2], name=\"Robert\"},
\"Robert\" = _P1#person.name,
[0,8,2,3,4,3,1,2] = _P1#person.phone,
- undefined = _P1#person.address,
+ undefined = _P1#person.address,
- _P2 = #person{name = \"Jakob\", _ = '_'},
+ _P2 = #person{name = \"Jakob\", _ = '_'},
\"Jakob\" = _P2#person.name,
'_' = _P2#person.phone,
- '_' = _P2#person.address,
-
- P = #person{name = \"Joe\", phone = [0,8,2,3,4,3,1,2]},
+ '_' = _P2#person.address,
+
+ P = #person{name = \"Joe\", phone = [0,8,2,3,4,3,1,2]},
\"Joe\" = P#person.name,
[0,8,2,3,4,3,1,2] = P#person.phone,
- undefined = P#person.address,
+ undefined = P#person.address,
- P1 = #person{name=\"Joe\", phone=[1,2,3], address=\"A street\"},
+ P1 = #person{name=\"Joe\", phone=[1,2,3], address=\"A street\"},
P2 = P1#person{name=\"Robert\"},
\"Robert\" = P2#person.name,
[1,2,3] = P2#person.phone,
- \"A street\" = P2#person.address,
+ \"A street\" = P2#person.address,
a_person = foo(P1),
- {found, [1,2,3]} =
- find_phone([#person{name = a},
- #person{name = b, phone = [3,2,1]},
- #person{name = c, phone = [1,2,3]}],
- c),
+ {found, [1,2,3]} =
+ find_phone([#person{name = a},
+ #person{name = b, phone = [3,2,1]},
+ #person{name = c, phone = [1,2,3]}],
+ c),
- P3 = #person{name=\"Joe\", phone=[0,0,7], address=\"A street\"},
+ P3 = #person{name=\"Joe\", phone=[0,0,7], address=\"A street\"},
#person{name = Name} = P3,
- \"Joe\" = Name,
+ \"Joe\" = Name,
\"Robert\" = demo(),
ok.
- foo(P) when is_record(P, person) -> a_person;
- foo(_) -> not_a_person.
+foo(P) when is_record(P, person) -> a_person;
+foo(_) -> not_a_person.
- find_phone([#person{name=Name, phone=Phone} | _], Name) ->
- {found, Phone};
- find_phone([_| T], Name) ->
- find_phone(T, Name);
- find_phone([], _Name) ->
- not_found.
+find_phone([#person{name=Name, phone=Phone} | _], Name) ->
+ {found, Phone};
+find_phone([_| T], Name) ->
+ find_phone(T, Name);
+find_phone([], _Name) ->
+ not_found.
- demo() ->
- P = #person2{name= #name{first=\"Robert\",last=\"Virding\"},
+demo() ->
+ P = #person2{name= #name{first=\"Robert\",last=\"Virding\"},
phone=123},
- _First = (P#person2.name)#name.first.
- ">>,
- ?line ok = run_file(Config, recs, Test1),
+ _First = (P#person2.name)#name.first.
+">>,
+ ok = run_file(Config, recs, Test1),
- Test1_shell =
- <<"rd(person, {name = \"\", phone = [], address}),
+Test1_shell =
+<<"rd(person, {name = \"\", phone = [], address}),
rd(name, {first = \"Robert\", last = \"Ericsson\"}),
rd(person2, {name = #name{}, phone}),
- _P1 = #person{phone=[0,8,2,3,4,3,1,2], name=\"Robert\"},
+ _P1 = #person{phone=[0,8,2,3,4,3,1,2], name=\"Robert\"},
\"Robert\" = _P1#person.name,
[0,8,2,3,4,3,1,2] = _P1#person.phone,
- undefined = _P1#person.address,
+ undefined = _P1#person.address,
- _P2 = #person{name = \"Jakob\", _ = '_'},
+ _P2 = #person{name = \"Jakob\", _ = '_'},
\"Jakob\" = _P2#person.name,
'_' = _P2#person.phone,
- '_' = _P2#person.address,
+ '_' = _P2#person.address,
- P = #person{name = \"Joe\", phone = [0,8,2,3,4,3,1,2]},
+ P = #person{name = \"Joe\", phone = [0,8,2,3,4,3,1,2]},
\"Joe\" = P#person.name,
[0,8,2,3,4,3,1,2] = P#person.phone,
- undefined = P#person.address,
+ undefined = P#person.address,
- P1 = #person{name=\"Joe\", phone=[1,2,3], address=\"A street\"},
+ P1 = #person{name=\"Joe\", phone=[1,2,3], address=\"A street\"},
P2 = P1#person{name=\"Robert\"},
\"Robert\" = P2#person.name,
[1,2,3] = P2#person.phone,
- \"A street\" = P2#person.address,
+ \"A street\" = P2#person.address,
Foo = fun(P) when is_record(P, person) -> a_person;
(_) -> not_a_person
end,
- a_person = Foo(P1),
-
- Find = fun([#person{name=Name, phone=Phone} | _], Name, Fn) ->
- {found, Phone};
- ([_| T], Name, Fn) ->
- Fn(T, Name, Fn);
- ([], _Name, _Fn) ->
- not_found
- end,
-
- {found, [1,2,3]} = Find([#person{name = a},
- #person{name = b, phone = [3,2,1]},
- #person{name = c, phone = [1,2,3]}],
- c,
- Find),
-
- P3 = #person{name=\"Joe\", phone=[0,0,7], address=\"A street\"},
+ a_person = Foo(P1),
+
+ Find = fun([#person{name=Name, phone=Phone} | _], Name, Fn) ->
+ {found, Phone};
+ ([_| T], Name, Fn) ->
+ Fn(T, Name, Fn);
+ ([], _Name, _Fn) ->
+ not_found
+ end,
+
+ {found, [1,2,3]} = Find([#person{name = a},
+ #person{name = b, phone = [3,2,1]},
+ #person{name = c, phone = [1,2,3]}],
+ c,
+ Find),
+
+ P3 = #person{name=\"Joe\", phone=[0,0,7], address=\"A street\"},
#person{name = Name} = P3,
- \"Joe\" = Name,
+ \"Joe\" = Name,
Demo = fun() ->
- P17 = #person2{name= #name{first=\"Robert\",last=\"Virding\"},
+ P17 = #person2{name= #name{first=\"Robert\",last=\"Virding\"},
phone=123},
- _First = (P17#person2.name)#name.first
- end,
+ _First = (P17#person2.name)#name.first
+ end,
- \"Robert\" = Demo(),
+ \"Robert\" = Demo(),
ok.
- ">>,
- ?line [ok] = scan(Test1_shell),
+">>,
+ [ok] = scan(Test1_shell),
- Test2 =
- <<"-module(recs).
+Test2 =
+<<"-module(recs).
-record(person, {name, age, phone = [], dict = []}).
- -compile(export_all).
+-compile(export_all).
- t() -> ok.
+t() -> ok.
- make_hacker_without_phone(Name, Age) ->
- #person{name = Name, age = Age,
- dict = [{computer_knowledge, excellent},
- {drinks, coke}]}.
- print(#person{name = Name, age = Age,
- phone = Phone, dict = Dict}) ->
- io:format(\"Name: ~s, Age: ~w, Phone: ~w ~n\"
+make_hacker_without_phone(Name, Age) ->
+ #person{name = Name, age = Age,
+ dict = [{computer_knowledge, excellent},
+ {drinks, coke}]}.
+print(#person{name = Name, age = Age,
+ phone = Phone, dict = Dict}) ->
+ io:format(\"Name: ~s, Age: ~w, Phone: ~w ~n\"
\"Dictionary: ~w.~n\", [Name, Age, Phone, Dict]).
birthday(P) when record(P, person) ->
- P#person{age = P#person.age + 1}.
+ P#person{age = P#person.age + 1}.
- register_two_hackers() ->
- Hacker1 = make_hacker_without_phone(\"Joe\", 29),
+register_two_hackers() ->
+ Hacker1 = make_hacker_without_phone(\"Joe\", 29),
OldHacker = birthday(Hacker1),
- % The central_register_server should have
- % an interface function for this.
- central_register_server ! {register_person, Hacker1},
- central_register_server ! {register_person,
- OldHacker#person{name = \"Robert\",
+ %% The central_register_server should have
+ %% an interface function for this.
+ central_register_server ! {register_person, Hacker1},
+ central_register_server ! {register_person,
+ OldHacker#person{name = \"Robert\",
phone = [0,8,3,2,4,5,3,1]}}.
- ">>,
- ?line ok = run_file(Config, recs, Test2),
- ok.
+">>,
+ ok = run_file(Config, recs, Test2),
+ok.
-progex_lc(doc) ->
- ["List comprehension examples from Programming Examples. OTP-5237."];
-progex_lc(suite) ->
- [];
+%% List comprehension examples from Programming Examples. OTP-5237.
progex_lc(Config) when is_list(Config) ->
Test1 =
- <<"-module(lc).
+ <<"-module(lc).
-export([t/0]).
- t() ->
- [a,4,b,5,6] = [X || X <- [1,2,a,3,4,b,5,6], X > 3],
- [4,5,6] = [X || X <- [1,2,a,3,4,b,5,6], integer(X), X > 3],
- [{1,a},{1,b},{2,a},{2,b},{3,a},{3,b}] =
- [{X, Y} || X <- [1,2,3], Y <- [a,b]],
-
- [1,2,3,4,5,6,7,8] = sort([4,5,1,8,3,6,7,2]),
- [[b,u,g],[b,g,u],[u,b,g],[u,g,b],[g,b,u],[g,u,b]] =
- perms([b,u,g]),
- [] = pyth(11),
- [{3,4,5},{4,3,5}] = pyth(12),
- [{3,4,5},{4,3,5},{5,12,13},{6,8,10},{8,6,10},{8,15,17},
- {9,12,15},{12,5,13},{12,9,15},{12,16,20},{15,8,17},
- {16,12,20}] = pyth(50),
- [] = pyth1(11),
- [{3,4,5},{4,3,5}] = pyth1(12),
- [{3,4,5},{4,3,5},{5,12,13},{6,8,10},{8,6,10},{8,15,17},
- {9,12,15},{12,5,13},{12,9,15},{12,16,20},{15,8,17},
- {16,12,20}] = pyth1(50),
- [1,2,3,4,5] = append([[1,2,3],[4,5]]),
- [2,3,4] = map(fun(X) -> X + 1 end, [1,2,3]),
- [2,4] = filter(fun(X) -> X > 1 end, [0,2,4]),
- [1,2,3,7] = select(b,[{a,1},{b,2},{c,3},{b,7}]),
- [2,7] = select2(b,[{a,1},{b,2},{c,3},{b,7}]),
- ok.
-
- sort([Pivot|T]) ->
- sort([ X || X <- T, X < Pivot]) ++
- [Pivot] ++
- sort([ X || X <- T, X >= Pivot]);
- sort([]) -> [].
-
- perms([]) -> [[]];
- perms(L) -> [[H|T] || H <- L, T <- perms(L--[H])].
-
- pyth(N) ->
- [ {A,B,C} ||
- A <- lists:seq(1,N),
- B <- lists:seq(1,N),
- C <- lists:seq(1,N),
- A+B+C =< N,
- A*A+B*B == C*C
- ].
-
- pyth1(N) ->
- [{A,B,C} ||
- A <- lists:seq(1,N),
- B <- lists:seq(1,N-A+1),
- C <- lists:seq(1,N-A-B+2),
- A+B+C =< N,
- A*A+B*B == C*C ].
-
- append(L) -> [X || L1 <- L, X <- L1].
- map(Fun, L) -> [Fun(X) || X <- L].
- filter(Pred, L) -> [X || X <- L, Pred(X)].
-
- select(X, L) -> [Y || {X, Y} <- L].
- select2(X, L) -> [Y || {X1, Y} <- L, X == X1].
- ">>,
- ?line ok = run_file(Config, lc, Test1),
-
- Test1_shell =
- <<"[a,4,b,5,6] = [X || X <- [1,2,a,3,4,b,5,6], X > 3],
- [4,5,6] = [X || X <- [1,2,a,3,4,b,5,6], integer(X), X > 3],
- [{1,a},{1,b},{2,a},{2,b},{3,a},{3,b}] =
- [{X, Y} || X <- [1,2,3], Y <- [a,b]],
-
- Sort = fun([Pivot|T], Fn) ->
- Fn([ X || X <- T, X < Pivot], Fn) ++
- [Pivot] ++
- Fn([ X || X <- T, X >= Pivot], Fn);
- ([], _Fn) -> []
- end,
-
- [1,2,3,4,5,6,7,8] = Sort([4,5,1,8,3,6,7,2], Sort),
- Perms = fun([], _Fn) -> [[]];
- (L, Fn) -> [[H|T] || H <- L, T <- Fn(L--[H], Fn)]
- end,
- [[b,u,g],[b,g,u],[u,b,g],[u,g,b],[g,b,u],[g,u,b]] =
- Perms([b,u,g], Perms),
-
- Pyth = fun(N) ->
- [ {A,B,C} ||
- A <- lists:seq(1,N),
- B <- lists:seq(1,N),
- C <- lists:seq(1,N),
- A+B+C =< N,
- A*A+B*B == C*C
- ]
- end,
-
- [] = Pyth(11),
- [{3,4,5},{4,3,5}] = Pyth(12),
- %[{3,4,5},{4,3,5},{5,12,13},{6,8,10},{8,6,10},{8,15,17},
- % {9,12,15},{12,5,13},{12,9,15},{12,16,20},{15,8,17},
- % {16,12,20}] = Pyth(50),
-
- Pyth1 = fun(N) ->
- [{A,B,C} ||
- A <- lists:seq(1,N),
- B <- lists:seq(1,N-A+1),
- C <- lists:seq(1,N-A-B+2),
- A+B+C =< N,
- A*A+B*B == C*C ]
- end,
-
- [] = Pyth1(11),
- [{3,4,5},{4,3,5}] = Pyth1(12),
- [{3,4,5},{4,3,5},{5,12,13},{6,8,10},{8,6,10},{8,15,17},
- {9,12,15},{12,5,13},{12,9,15},{12,16,20},{15,8,17},
- {16,12,20}] = Pyth1(50),
-
- Append = fun(L) -> [X || L1 <- L, X <- L1] end,
- [1,2,3,4,5] = Append([[1,2,3],[4,5]]),
- Map = fun(Fun, L) -> [Fun(X) || X <- L] end,
- [2,3,4] = Map(fun(X) -> X + 1 end, [1,2,3]),
- Filter = fun(Pred, L) -> [X || X <- L, Pred(X)] end,
- [2,4] = Filter(fun(X) -> X > 1 end, [0,2,4]),
-
- Select = fun(X, L) -> [Y || {X, Y} <- L] end,
- [1,2,3,7] = Select(b,[{a,1},{b,2},{c,3},{b,7}]),
- Select2 = fun(X, L) -> [Y || {X1, Y} <- L, X == X1] end,
- [2,7] = Select2(b,[{a,1},{b,2},{c,3},{b,7}]),
- ok.
- ">>,
- ?line [ok] = scan(Test1_shell),
+t() ->
+ [a,4,b,5,6] = [X || X <- [1,2,a,3,4,b,5,6], X > 3],
+ [4,5,6] = [X || X <- [1,2,a,3,4,b,5,6], integer(X), X > 3],
+ [{1,a},{1,b},{2,a},{2,b},{3,a},{3,b}] =
+ [{X, Y} || X <- [1,2,3], Y <- [a,b]],
+
+ [1,2,3,4,5,6,7,8] = sort([4,5,1,8,3,6,7,2]),
+ [[b,u,g],[b,g,u],[u,b,g],[u,g,b],[g,b,u],[g,u,b]] =
+ perms([b,u,g]),
+ [] = pyth(11),
+ [{3,4,5},{4,3,5}] = pyth(12),
+ [{3,4,5},{4,3,5},{5,12,13},{6,8,10},{8,6,10},{8,15,17},
+ {9,12,15},{12,5,13},{12,9,15},{12,16,20},{15,8,17},
+ {16,12,20}] = pyth(50),
+ [] = pyth1(11),
+ [{3,4,5},{4,3,5}] = pyth1(12),
+ [{3,4,5},{4,3,5},{5,12,13},{6,8,10},{8,6,10},{8,15,17},
+ {9,12,15},{12,5,13},{12,9,15},{12,16,20},{15,8,17},
+ {16,12,20}] = pyth1(50),
+ [1,2,3,4,5] = append([[1,2,3],[4,5]]),
+ [2,3,4] = map(fun(X) -> X + 1 end, [1,2,3]),
+ [2,4] = filter(fun(X) -> X > 1 end, [0,2,4]),
+ [1,2,3,7] = select(b,[{a,1},{b,2},{c,3},{b,7}]),
+ [2,7] = select2(b,[{a,1},{b,2},{c,3},{b,7}]),
ok.
-progex_funs(doc) ->
- ["Funs examples from Programming Examples. OTP-5237."];
-progex_funs(suite) ->
- [];
+sort([Pivot|T]) ->
+ sort([ X || X <- T, X < Pivot]) ++
+ [Pivot] ++
+ sort([ X || X <- T, X >= Pivot]);
+sort([]) -> [].
+
+perms([]) -> [[]];
+perms(L) -> [[H|T] || H <- L, T <- perms(L--[H])].
+
+pyth(N) ->
+ [ {A,B,C} ||
+ A <- lists:seq(1,N),
+ B <- lists:seq(1,N),
+ C <- lists:seq(1,N),
+ A+B+C =< N,
+ A*A+B*B == C*C
+ ].
+
+pyth1(N) ->
+ [{A,B,C} ||
+ A <- lists:seq(1,N),
+ B <- lists:seq(1,N-A+1),
+ C <- lists:seq(1,N-A-B+2),
+ A+B+C =< N,
+ A*A+B*B == C*C ].
+
+append(L) -> [X || L1 <- L, X <- L1].
+map(Fun, L) -> [Fun(X) || X <- L].
+filter(Pred, L) -> [X || X <- L, Pred(X)].
+
+select(X, L) -> [Y || {X, Y} <- L].
+select2(X, L) -> [Y || {X1, Y} <- L, X == X1].
+">>,
+ ok = run_file(Config, lc, Test1),
+
+Test1_shell =
+<<"[a,4,b,5,6] = [X || X <- [1,2,a,3,4,b,5,6], X > 3],
+ [4,5,6] = [X || X <- [1,2,a,3,4,b,5,6], integer(X), X > 3],
+ [{1,a},{1,b},{2,a},{2,b},{3,a},{3,b}] =
+ [{X, Y} || X <- [1,2,3], Y <- [a,b]],
+
+ Sort = fun([Pivot|T], Fn) ->
+ Fn([ X || X <- T, X < Pivot], Fn) ++
+ [Pivot] ++
+ Fn([ X || X <- T, X >= Pivot], Fn);
+ ([], _Fn) -> []
+ end,
+
+ [1,2,3,4,5,6,7,8] = Sort([4,5,1,8,3,6,7,2], Sort),
+ Perms = fun([], _Fn) -> [[]];
+ (L, Fn) -> [[H|T] || H <- L, T <- Fn(L--[H], Fn)]
+ end,
+ [[b,u,g],[b,g,u],[u,b,g],[u,g,b],[g,b,u],[g,u,b]] =
+ Perms([b,u,g], Perms),
+
+ Pyth = fun(N) ->
+ [ {A,B,C} ||
+ A <- lists:seq(1,N),
+ B <- lists:seq(1,N),
+ C <- lists:seq(1,N),
+ A+B+C =< N,
+ A*A+B*B == C*C
+ ]
+ end,
+
+ [] = Pyth(11),
+ [{3,4,5},{4,3,5}] = Pyth(12),
+%%[{3,4,5},{4,3,5},{5,12,13},{6,8,10},{8,6,10},{8,15,17},
+%% {9,12,15},{12,5,13},{12,9,15},{12,16,20},{15,8,17},
+%% {16,12,20}] = Pyth(50),
+
+ Pyth1 = fun(N) ->
+ [{A,B,C} ||
+ A <- lists:seq(1,N),
+ B <- lists:seq(1,N-A+1),
+ C <- lists:seq(1,N-A-B+2),
+ A+B+C =< N,
+ A*A+B*B == C*C ]
+ end,
+
+ [] = Pyth1(11),
+ [{3,4,5},{4,3,5}] = Pyth1(12),
+ [{3,4,5},{4,3,5},{5,12,13},{6,8,10},{8,6,10},{8,15,17},
+ {9,12,15},{12,5,13},{12,9,15},{12,16,20},{15,8,17},
+ {16,12,20}] = Pyth1(50),
+
+ Append = fun(L) -> [X || L1 <- L, X <- L1] end,
+ [1,2,3,4,5] = Append([[1,2,3],[4,5]]),
+ Map = fun(Fun, L) -> [Fun(X) || X <- L] end,
+ [2,3,4] = Map(fun(X) -> X + 1 end, [1,2,3]),
+ Filter = fun(Pred, L) -> [X || X <- L, Pred(X)] end,
+ [2,4] = Filter(fun(X) -> X > 1 end, [0,2,4]),
+
+ Select = fun(X, L) -> [Y || {X, Y} <- L] end,
+ [1,2,3,7] = Select(b,[{a,1},{b,2},{c,3},{b,7}]),
+ Select2 = fun(X, L) -> [Y || {X1, Y} <- L, X == X1] end,
+ [2,7] = Select2(b,[{a,1},{b,2},{c,3},{b,7}]),
+ ok.
+">>,
+ [ok] = scan(Test1_shell),
+ok.
+
+%% Funs examples from Programming Examples. OTP-5237.
progex_funs(Config) when is_list(Config) ->
Test1 =
- <<"-module(funs).
+ <<"-module(funs).
-compile(export_all).
- double([H|T]) -> [2*H|double(T)];
- double([]) -> [].
+double([H|T]) -> [2*H|double(T)];
+double([]) -> [].
- add_one([H|T]) -> [H+1|add_one(T)];
- add_one([]) -> [].
+add_one([H|T]) -> [H+1|add_one(T)];
+add_one([]) -> [].
- map(F, [H|T]) -> [F(H)|map(F, T)];
- map(F, []) -> [].
+map(F, [H|T]) -> [F(H)|map(F, T)];
+map(F, []) -> [].
- double2(L) -> map(fun(X) -> 2*X end, L).
- add_one2(L) -> map(fun(X) -> 1 + X end, L).
+double2(L) -> map(fun(X) -> 2*X end, L).
+add_one2(L) -> map(fun(X) -> 1 + X end, L).
- print_list(Stream, [H|T]) ->
- io:format(Stream, \"~p~n\", [H]),
+print_list(Stream, [H|T]) ->
+ io:format(Stream, \"~p~n\", [H]),
print_list(Stream, T);
- print_list(Stream, []) ->
- true.
-
- broadcast(Msg, [Pid|Pids]) ->
- Pid ! Msg,
- broadcast(Msg, Pids);
- broadcast(_, []) ->
- true.
-
- foreach(F, [H|T]) ->
- F(H),
- foreach(F, T);
- foreach(F, []) ->
- ok.
+ print_list(Stream, []) ->
+ true.
+
+broadcast(Msg, [Pid|Pids]) ->
+ Pid ! Msg,
+ broadcast(Msg, Pids);
+broadcast(_, []) ->
+ true.
+
+foreach(F, [H|T]) ->
+ F(H),
+ foreach(F, T);
+foreach(F, []) ->
+ ok.
- print_list2(S, L) ->
- foreach(fun(H) -> io:format(S, \"~p~n\",[H]) end, L).
+print_list2(S, L) ->
+ foreach(fun(H) -> io:format(S, \"~p~n\",[H]) end, L).
broadcast2(M, L) -> foreach(fun(Pid) -> Pid ! M end, L).
- t1() -> map(fun(X) -> 2 * X end, [1,2,3,4,5]).
+t1() -> map(fun(X) -> 2 * X end, [1,2,3,4,5]).
- t2() -> map(fun double/1, [1,2,3,4,5]).
+t2() -> map(fun double/1, [1,2,3,4,5]).
- t3() -> map({?MODULE, double3}, [1,2,3,4,5]).
+t3() -> map({?MODULE, double3}, [1,2,3,4,5]).
- double3(X) -> X * 2.
+double3(X) -> X * 2.
- f(F, Args) when function(F) ->
- apply(F, Args);
- f(N, _) when integer(N) ->
- N.
+f(F, Args) when function(F) ->
+ apply(F, Args);
+f(N, _) when integer(N) ->
+ N.
- print_list3(File, List) ->
- {ok, Stream} = file:open(File, write),
- foreach(fun(X) -> io:format(Stream,\"~p~n\",[X]) end, List),
+print_list3(File, List) ->
+ {ok, Stream} = file:open(File, write),
+ foreach(fun(X) -> io:format(Stream,\"~p~n\",[X]) end, List),
file:close(Stream).
- print_list4(File, List) ->
- {ok, Stream} = file:open(File, write),
- foreach(fun(File) ->
- io:format(Stream,\"~p~n\",[File])
+print_list4(File, List) ->
+ {ok, Stream} = file:open(File, write),
+ foreach(fun(File) ->
+ io:format(Stream,\"~p~n\",[File])
end, List),
- file:close(Stream).
+ file:close(Stream).
+
+any(Pred, [H|T]) ->
+ case Pred(H) of
+ true -> true;
+ false -> any(Pred, T)
+ end;
+any(Pred, []) ->
+ false.
- any(Pred, [H|T]) ->
- case Pred(H) of
- true -> true;
- false -> any(Pred, T)
- end;
- any(Pred, []) ->
- false.
-
- all(Pred, [H|T]) ->
- case Pred(H) of
- true -> all(Pred, T);
- false -> false
- end;
- all(Pred, []) ->
- true.
-
- foldl(F, Accu, [Hd|Tail]) ->
- foldl(F, F(Hd, Accu), Tail);
- foldl(F, Accu, []) -> Accu.
-
- mapfoldl(F, Accu0, [Hd|Tail]) ->
- {R,Accu1} = F(Hd, Accu0),
- {Rs,Accu2} = mapfoldl(F, Accu1, Tail),
- {[R|Rs], Accu2};
- mapfoldl(F, Accu, []) -> {[], Accu}.
-
- filter(F, [H|T]) ->
- case F(H) of
- true -> [H|filter(F, T)];
- false -> filter(F, T)
- end;
- filter(F, []) -> [].
-
- diff(L1, L2) ->
- filter(fun(X) -> not lists:member(X, L2) end, L1).
-
- intersection(L1,L2) -> filter(fun(X) -> lists:member(X,L1) end, L2).
-
- takewhile(Pred, [H|T]) ->
- case Pred(H) of
- true -> [H|takewhile(Pred, T)];
- false -> []
- end;
- takewhile(Pred, []) ->
- [].
-
- dropwhile(Pred, [H|T]) ->
- case Pred(H) of
- true -> dropwhile(Pred, T);
- false -> [H|T]
- end;
- dropwhile(Pred, []) ->
- [].
-
- splitlist(Pred, L) ->
- splitlist(Pred, L, []).
-
- splitlist(Pred, [H|T], L) ->
- case Pred(H) of
- true -> splitlist(Pred, T, [H|L]);
- false -> {lists:reverse(L), [H|T]}
- end;
- splitlist(Pred, [], L) ->
- {lists:reverse(L), []}.
-
- first(Pred, [H|T]) ->
- case Pred(H) of
- true ->
- {true, H};
- false ->
- first(Pred, T)
- end;
- first(Pred, []) ->
- false.
-
- ints_from(N) ->
- fun() ->
- [N|ints_from(N+1)]
- end.
-
- pconst(X) ->
- fun (T) ->
- case T of
- [X|T1] -> {ok, {const, X}, T1};
- _ -> fail
- end
- end.
-
- pand(P1, P2) ->
- fun (T) ->
- case P1(T) of
- {ok, R1, T1} ->
- case P2(T1) of
- {ok, R2, T2} ->
- {ok, {'and', R1, R2}};
- fail ->
- fail
- end;
- fail ->
- fail
- end
- end.
-
- por(P1, P2) ->
- fun (T) ->
- case P1(T) of
- {ok, R, T1} ->
- {ok, {'or',1,R}, T1};
- fail ->
- case P2(T) of
- {ok, R1, T1} ->
- {ok, {'or',2,R1}, T1};
- fail ->
- fail
- end
- end
- end.
-
- grammar() ->
- pand(
- por(pconst(a), pconst(b)),
- por(pconst(c), pconst(d))).
-
- parse(List) ->
- (grammar())(List).
-
-
- t() ->
- [2,4,6,8] = double([1,2,3,4]),
- [2,3,4,5] = add_one([1,2,3,4]),
- [2,4,6,8] = double2([1,2,3,4]),
- [2,3,4,5] = add_one2([1,2,3,4]),
- XX = ints_from(1),
- [1 | _] = XX(),
- 1 = hd(XX()),
- Y = tl(XX()),
- 2 = hd(Y()),
-
- P1 = pconst(a),
- {ok,{const,a},[b,c]} = P1([a,b,c]),
- fail = P1([x,y,z]),
-
- {ok,{'and',{'or',1,{const,a}},{'or',1,{const,c}}}} =
- parse([a,c]),
- {ok,{'and',{'or',1,{const,a}},{'or',2,{const,d}}}} =
- parse([a,d]),
- {ok,{'and',{'or',2,{const,b}},{'or',1,{const,c}}}} =
- parse([b,c]),
- {ok,{'and',{'or',2,{const,b}},{'or',2,{const,d}}}} =
- parse([b,d]),
- fail = parse([a,b]),
- ok.
- ">>,
- ?line ok = run_file(Config, funs, Test1),
-
- Test2_shell =
- <<"Double = fun(X) -> 2 * X end,
+all(Pred, [H|T]) ->
+ case Pred(H) of
+ true -> all(Pred, T);
+ false -> false
+ end;
+all(Pred, []) ->
+ true.
+
+foldl(F, Accu, [Hd|Tail]) ->
+ foldl(F, F(Hd, Accu), Tail);
+foldl(F, Accu, []) -> Accu.
+
+mapfoldl(F, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = F(Hd, Accu0),
+ {Rs,Accu2} = mapfoldl(F, Accu1, Tail),
+ {[R|Rs], Accu2};
+mapfoldl(F, Accu, []) -> {[], Accu}.
+
+filter(F, [H|T]) ->
+ case F(H) of
+ true -> [H|filter(F, T)];
+ false -> filter(F, T)
+ end;
+filter(F, []) -> [].
+
+diff(L1, L2) ->
+ filter(fun(X) -> not lists:member(X, L2) end, L1).
+
+intersection(L1,L2) -> filter(fun(X) -> lists:member(X,L1) end, L2).
+
+takewhile(Pred, [H|T]) ->
+ case Pred(H) of
+ true -> [H|takewhile(Pred, T)];
+ false -> []
+ end;
+takewhile(Pred, []) ->
+ [].
+
+dropwhile(Pred, [H|T]) ->
+ case Pred(H) of
+ true -> dropwhile(Pred, T);
+ false -> [H|T]
+ end;
+dropwhile(Pred, []) ->
+ [].
+
+splitlist(Pred, L) ->
+ splitlist(Pred, L, []).
+
+splitlist(Pred, [H|T], L) ->
+ case Pred(H) of
+ true -> splitlist(Pred, T, [H|L]);
+ false -> {lists:reverse(L), [H|T]}
+ end;
+splitlist(Pred, [], L) ->
+ {lists:reverse(L), []}.
+
+first(Pred, [H|T]) ->
+ case Pred(H) of
+ true ->
+ {true, H};
+ false ->
+ first(Pred, T)
+ end;
+first(Pred, []) ->
+ false.
+
+ints_from(N) ->
+ fun() ->
+ [N|ints_from(N+1)]
+ end.
+
+pconst(X) ->
+ fun (T) ->
+ case T of
+ [X|T1] -> {ok, {const, X}, T1};
+ _ -> fail
+ end
+ end.
+
+pand(P1, P2) ->
+ fun (T) ->
+ case P1(T) of
+ {ok, R1, T1} ->
+ case P2(T1) of
+ {ok, R2, T2} ->
+ {ok, {'and', R1, R2}};
+ fail ->
+ fail
+ end;
+ fail ->
+ fail
+ end
+ end.
+
+por(P1, P2) ->
+ fun (T) ->
+ case P1(T) of
+ {ok, R, T1} ->
+ {ok, {'or',1,R}, T1};
+ fail ->
+ case P2(T) of
+ {ok, R1, T1} ->
+ {ok, {'or',2,R1}, T1};
+ fail ->
+ fail
+ end
+ end
+ end.
+
+grammar() ->
+ pand(
+ por(pconst(a), pconst(b)),
+ por(pconst(c), pconst(d))).
+
+parse(List) ->
+ (grammar())(List).
+
+
+t() ->
+ [2,4,6,8] = double([1,2,3,4]),
+ [2,3,4,5] = add_one([1,2,3,4]),
+ [2,4,6,8] = double2([1,2,3,4]),
+ [2,3,4,5] = add_one2([1,2,3,4]),
+ XX = ints_from(1),
+ [1 | _] = XX(),
+ 1 = hd(XX()),
+ Y = tl(XX()),
+ 2 = hd(Y()),
+
+ P1 = pconst(a),
+ {ok,{const,a},[b,c]} = P1([a,b,c]),
+ fail = P1([x,y,z]),
+
+ {ok,{'and',{'or',1,{const,a}},{'or',1,{const,c}}}} =
+ parse([a,c]),
+ {ok,{'and',{'or',1,{const,a}},{'or',2,{const,d}}}} =
+ parse([a,d]),
+ {ok,{'and',{'or',2,{const,b}},{'or',1,{const,c}}}} =
+ parse([b,c]),
+ {ok,{'and',{'or',2,{const,b}},{'or',2,{const,d}}}} =
+ parse([b,d]),
+ fail = parse([a,b]),
+ ok.
+">>,
+ ok = run_file(Config, funs, Test1),
+
+Test2_shell =
+<<"Double = fun(X) -> 2 * X end,
[2,4,6,8,10] = lists:map(Double, [1,2,3,4,5]),
-
- Big = fun(X) -> if X > 10 -> true; true -> false end end,
- false = lists:any(Big, [1,2,3,4]),
- true = lists:any(Big, [1,2,3,12,5]),
- false = lists:all(Big, [1,2,3,4,12,6]),
- true = lists:all(Big, [12,13,14,15]),
- L = [\"I\",\"like\",\"Erlang\"],
+
+ Big = fun(X) -> if X > 10 -> true; true -> false end end,
+ false = lists:any(Big, [1,2,3,4]),
+ true = lists:any(Big, [1,2,3,12,5]),
+ false = lists:all(Big, [1,2,3,4,12,6]),
+ true = lists:all(Big, [12,13,14,15]),
+ L = [\"I\",\"like\",\"Erlang\"],
11 = lists:foldl(fun(X, Sum) -> length(X) + Sum end, 0, L),
- Upcase = fun(X) when $a =< X, X =< $z -> X + $A - $a;
- (X) -> X
- end,
- Upcase_word = fun(X) -> lists:map(Upcase, X) end,
- \"ERLANG\" = Upcase_word(\"Erlang\"),
+ Upcase = fun(X) when $a =< X, X =< $z -> X + $A - $a;
+ (X) -> X
+ end,
+ Upcase_word = fun(X) -> lists:map(Upcase, X) end,
+ \"ERLANG\" = Upcase_word(\"Erlang\"),
[\"I\",\"LIKE\",\"ERLANG\"] = lists:map(Upcase_word, L),
{[\"I\",\"LIKE\",\"ERLANG\"],11} =
lists:mapfoldl(fun(Word, Sum) ->
- {Upcase_word(Word), Sum + length(Word)}
+ {Upcase_word(Word), Sum + length(Word)}
end, 0, L),
- [500,12,45] = lists:filter(Big, [500,12,2,45,6,7]),
- [200,500,45] = lists:takewhile(Big, [200,500,45,5,3,45,6]),
- [5,3,45,6] = lists:dropwhile(Big, [200,500,45,5,3,45,6]),
- {[200,500,45],[5,3,45,6]} =
- lists:splitwith(Big, [200,500,45,5,3,45,6]),
+ [500,12,45] = lists:filter(Big, [500,12,2,45,6,7]),
+ [200,500,45] = lists:takewhile(Big, [200,500,45,5,3,45,6]),
+ [5,3,45,6] = lists:dropwhile(Big, [200,500,45,5,3,45,6]),
+ {[200,500,45],[5,3,45,6]} =
+ lists:splitwith(Big, [200,500,45,5,3,45,6]),
%% {true,45} = lists:first(Big, [1,2,45,6,123]),
%% false = lists:first(Big, [1,2,4,5]),
-
- Adder = fun(X) -> fun(Y) -> X + Y end end,
- Add6 = Adder(6),
- 16 = Add6(10),
- ok.
- ">>,
- ?line [ok] = scan(Test2_shell),
- ok.
+
+ Adder = fun(X) -> fun(Y) -> X + Y end end,
+ Add6 = Adder(6),
+ 16 = Add6(10),
+ ok.
+">>,
+ [ok] = scan(Test2_shell),
+ok.
-otp_5990(doc) ->
- "OTP-5990. {erlang,is_record}.";
-otp_5990(suite) -> [];
+%% OTP-5990. {erlang,is_record}.
otp_5990(Config) when is_list(Config) ->
- ?line [true] =
+ [true] =
scan(<<"rd('OrdSet', {orddata = {},ordtype = type}), "
"S = #'OrdSet'{ordtype = {}}, "
"if tuple(S#'OrdSet'.ordtype) -> true; true -> false end.">>),
ok.
-otp_6166(doc) ->
- "OTP-6166. Order of record definitions.";
-otp_6166(suite) -> [];
+%% OTP-6166. Order of record definitions.
otp_6166(Config) when is_list(Config) ->
- Test1 = filename:join(?config(priv_dir, Config), "test1.hrl"),
+ Test1 = filename:join(proplists:get_value(priv_dir, Config), "test1.hrl"),
Contents1 = <<"-module(test1).
-record(r5, {f}). -record(r3, {f = #r5{}}). "
"-record(r1, {f = #r3{}}). -record(r4, {f = #r1{}}). "
- "-record(r2, {f = #r4{}}).">>,
- ?line ok = file:write_file(Test1, Contents1),
+"-record(r2, {f = #r4{}}).">>,
+ ok = file:write_file(Test1, Contents1),
- Test2 = filename:join(?config(priv_dir, Config), "test2.hrl"),
+ Test2 = filename:join(proplists:get_value(priv_dir, Config), "test2.hrl"),
Contents2 = <<"-module(test2).
-record(r5, {f}). -record(r3, {f = #r5{}}). "
"-record(r1, {f = #r3{}}). -record(r4, {f = #r1{}}). "
"-record(r2, {f = #r4{}}).
-record(r6, {f = #r5{}}). % r6 > r0
-record(r0, {f = #r5{}, g = #r5{}}). % r0 < r5">>,
- ?line ok = file:write_file(Test2, Contents2),
+ ok = file:write_file(Test2, Contents2),
RR12 = "[r1,r2,r3,r4,r5] = rr(\"" ++ Test1 ++ "\"),
[r0,r1,r2,r3,r4,r5,r6] = rr(\"" ++ Test2 ++ "\"),
@@ -2315,74 +2247,72 @@ otp_6166(Config) when is_list(Config) ->
true = is_record(R0, r0),
true = is_record(R6, r6),
ok. ",
- ?line [ok] = scan(RR12),
+ [ok] = scan(RR12),
file:delete(Test1),
file:delete(Test2),
ok.
-otp_6554(doc) ->
- "OTP-6554. Formatted exits and error messages.";
-otp_6554(suite) -> [];
+%% OTP-6554. Formatted exits and error messages.
otp_6554(Config) when is_list(Config) ->
%% Should check the stacktrace as well...
- ?line "exception error: bad argument" =
+ "exception error: bad argument" =
comm_err(<<"math:sqrt(a).">>),
- ?line "exception error: bad argument" =
+ "exception error: bad argument" =
comm_err(<<"fun(X, Y) -> X ++ Y end(a, b).">>),
- ?line "exception error: bad argument" =
+ "exception error: bad argument" =
comm_err(<<"math:sqrt(lists:seq(1,40)).">>),
- ?line "exception error: bad argument" =
+ "exception error: bad argument" =
comm_err(<<"math:sqrt(lists:seq(1,10)).">>),
- ?line "exception error: bad argument" =
+ "exception error: bad argument" =
comm_err(<<"a ++ b.">>),
- ?line "exception error: bad argument" =
+ "exception error: bad argument" =
comm_err(<<"I = {file_info,undefined,undefined,undefined,undefined,
undefined,undefined,undefined,undefined,undefined,
undefined,undefined,undefined,undefined},
aa ++ I.">>),
- ?line "exception error: bad argument" =
+ "exception error: bad argument" =
comm_err(<<"I = {file_info,undefined,undefined,undefined,undefined,
undefined,undefined,undefined,undefined,undefined,
undefined,undefined,undefined,undefined},
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ++ I.">>),
- ?line "exception error: bad argument" =
+ "exception error: bad argument" =
comm_err(<<"I = {file_info,undefined,undefined,undefined,undefined,
undefined,undefined,undefined,undefined,undefined,
undefined,undefined,undefined,undefined},
I ++ I.">>),
- ?line "exception error: bad argument" =
+ "exception error: bad argument" =
comm_err(<<"fun(X) -> not X end(a).">>),
- ?line "exception error: bad argument: a" =
+ "exception error: bad argument: a" =
comm_err(<<"fun(A, B) -> A orelse B end(a, b).">>),
- ?line "exception error: an error occurred when evaluating an arithmetic expression" =
+ "exception error: an error occurred when evaluating an arithmetic expression" =
comm_err(<<"math:sqrt(2)/round(math:sqrt(0)).">>),
- ?line "exception error: interpreted function with arity 1 called with no arguments" =
+ "exception error: interpreted function with arity 1 called with no arguments" =
comm_err(<<"fun(V) -> V end().">>),
- ?line "exception error: interpreted function with arity 1 called with two arguments" =
+ "exception error: interpreted function with arity 1 called with two arguments" =
comm_err(<<"fun(V) -> V end(1,2).">>),
- ?line "exception error: interpreted function with arity 0 called with one argument" =
+ "exception error: interpreted function with arity 0 called with one argument" =
comm_err(<<"fun() -> v end(1).">>),
- ?line "exception error: interpreted function with arity 0 called with 4 arguments" =
+ "exception error: interpreted function with arity 0 called with 4 arguments" =
comm_err(<<"fun() -> v end(1,2,3,4).">>),
- ?line "exception error: math:sqrt/1 called with two arguments" =
+ "exception error: math:sqrt/1 called with two arguments" =
comm_err(<<"fun math:sqrt/1(1,2).">>),
- ?line "exception error: bad function 1." ++ _ =
+ "exception error: bad function 1." ++ _ =
comm_err(<<"(math:sqrt(2))().">>),
- ?line "exception error: bad function [1," ++ _ =
+ "exception error: bad function [1," ++ _ =
comm_err(<<"(lists:seq(1, 100))().">>),
- ?line "exception error: no match of right hand side value 1" ++ _ =
+ "exception error: no match of right hand side value 1" ++ _ =
comm_err(<<"a = math:sqrt(2).">>),
- ?line "exception error: no match of right hand side value" ++ _ =
+ "exception error: no match of right hand side value" ++ _ =
comm_err(<<"I = {file_info,undefined,undefined,undefined,undefined,
undefined,undefined,undefined,undefined,undefined,
undefined,undefined,undefined,undefined},
a = I.">>),
- ?line "exception error: no case clause matching 1" ++ _ =
+ "exception error: no case clause matching 1" ++ _ =
comm_err(<<"case math:sqrt(2) of a -> ok end.">>),
- ?line "exception error: no case clause matching [1," ++ _ =
+ "exception error: no case clause matching [1," ++ _ =
comm_err(<<"V = lists:seq(1, 20), case V of a -> ok end.">>),
- ?line "exception error: no function clause matching" =
+ "exception error: no function clause matching" =
comm_err(<<"fun(P) when is_pid(P) -> true end(a).">>),
case test_server:is_native(erl_eval) of
true ->
@@ -2404,68 +2334,68 @@ otp_6554(Config) when is_list(Config) ->
"lists:reverse(34) (lists.erl, line " ++ _ =
comm_err(<<"lists:reverse(34).">>)
end,
- ?line "exception error: function_clause" =
+ "exception error: function_clause" =
comm_err(<<"erlang:error(function_clause, 4).">>),
- ?line "exception error: no function clause matching" ++ _ =
+ "exception error: no function clause matching" ++ _ =
comm_err(<<"fun(a, b, c, d) -> foo end"
" (lists:seq(1,17),"
" lists:seq(1, 18),"
" lists:seq(1, 40),"
" lists:seq(1, 5)).">>),
- ?line "exception error: no function clause matching" =
+ "exception error: no function clause matching" =
comm_err(<<"fun(P, q) when is_pid(P) -> true end(a, b).">>),
- ?line "exception error: no true branch found when evaluating an if expression" =
+ "exception error: no true branch found when evaluating an if expression" =
comm_err(<<"if length([a,b]) > 17 -> a end.">>),
- ?line "exception error: no such process or port" =
+ "exception error: no such process or port" =
comm_err(<<"Pid = spawn(fun() -> a end),"
"timer:sleep(1),"
"link(Pid).">>),
- ?line "exception error: a system limit has been reached" =
+ "exception error: a system limit has been reached" =
comm_err(<<"list_to_atom(lists:duplicate(300,$a)).">>),
- ?line "exception error: bad receive timeout value" =
+ "exception error: bad receive timeout value" =
comm_err(<<"receive after a -> foo end.">>),
- ?line "exception error: no try clause matching 1" ++ _ =
+ "exception error: no try clause matching 1" ++ _ =
comm_err(<<"try math:sqrt(2) of bar -> yes after 3 end.">>),
- ?line "exception error: no try clause matching [1" ++ _ =
+ "exception error: no try clause matching [1" ++ _ =
comm_err(<<"V = lists:seq(1, 20),"
"try V of bar -> yes after 3 end.">>),
- ?line "exception error: undefined function math:sqrt/2" =
+ "exception error: undefined function math:sqrt/2" =
comm_err(<<"math:sqrt(2, 2).">>),
- ?line "exception error: limit of number of arguments to interpreted function "
+ "exception error: limit of number of arguments to interpreted function "
"exceeded" =
comm_err(<<"fun(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U) ->"
" a end().">>),
- ?line "exception error: bad filter a" =
+ "exception error: bad filter a" =
comm_err(<<"[b || begin a end].">>),
- ?line "exception error: bad generator a" =
+ "exception error: bad generator a" =
comm_err(<<"[X || X <- a].">>),
- ?line "exception throw: undef" = comm_err(<<"throw(undef).">>),
- ?line "exception exit: undef" = comm_err(<<"exit(undef).">>),
+ "exception throw: undef" = comm_err(<<"throw(undef).">>),
+ "exception exit: undef" = comm_err(<<"exit(undef).">>),
- ?line "exception exit: foo" =
+ "exception exit: foo" =
comm_err(<<"catch spawn_link(fun() ->"
" timer:sleep(300), exit(foo) "
" end),"
"timer:sleep(500).">>),
- ?line [ok] = scan(
+ [ok] = scan(
<<"begin process_flag(trap_exit, true),"
" Pid = spawn_link(fun() ->"
" timer:sleep(300), exit(foo) "
" end),"
" timer:sleep(500),"
" receive {'EXIT', Pid, foo} -> ok end end.">>),
- ?line "exception exit: badarith" =
+ "exception exit: badarith" =
comm_err(<<"catch spawn_link(fun() ->"
" timer:sleep(300), 1/0 "
" end),"
"timer:sleep(500).">>),
- ?line "exception exit: {nocatch,foo}" =
+ "exception exit: {nocatch,foo}" =
comm_err(<<"catch spawn_link(fun() ->"
" timer:sleep(300), throw(foo) "
" end),"
"timer:sleep(500).">>),
- ?line [ok] = scan(
+ [ok] = scan(
<<"begin process_flag(trap_exit, true),"
" Pid = spawn_link(fun() ->"
" timer:sleep(300), throw(foo) "
@@ -2474,37 +2404,37 @@ otp_6554(Config) when is_list(Config) ->
" receive {'EXIT', Pid, {{nocatch,foo},_}} -> ok end "
"end.">>),
- ?line "exception error: an error occurred when evaluating an arithmetic expression" =
+ "exception error: an error occurred when evaluating an arithmetic expression" =
comm_err(<<"begin catch_exception(true), 1/0 end.">>),
- ?line "exception error: an error occurred when evaluating an arithmetic expression" =
+ "exception error: an error occurred when evaluating an arithmetic expression" =
comm_err(<<"begin catch_exception(false), 1/0 end.">>),
- ?line "exception error: no function clause matching call to catch_exception/1" =
+ "exception error: no function clause matching call to catch_exception/1" =
comm_err(<<"catch_exception(1).">>),
%% A bug was corrected (expansion of 'try'):
- ?line "2: command not found" =
+ "2: command not found" =
comm_err(<<"try 1 of 1 -> v(2) after 3 end.">>),
%% Cover a few lines:
- ?line "3: command not found" =
+ "3: command not found" =
comm_err(<<"receive foo -> foo after 0 -> v(3) end.">>),
- ?line "3: command not found" =
+ "3: command not found" =
comm_err(<<"receive foo -> foo after 0 -> e(3) end.">>),
- ?line "1 / 0: command not found" = comm_err(<<"v(1/0).">>),
- ?line "1\n1.\n" = t(<<"1. e(1).">>),
- ?line [ok] = scan(<<"h().">>),
- ?line "exception exit: normal" = comm_err(<<"exit(normal).">>),
- ?line [foo] = scan(<<"begin history(0), foo end.">>),
- ?line application:unset_env(stdlib, shell_history_length),
- ?line [true] = scan(<<"begin <<10:(1024*1024*10)>>,"
+ "1 / 0: command not found" = comm_err(<<"v(1/0).">>),
+ "1\n1.\n" = t(<<"1. e(1).">>),
+ [ok] = scan(<<"h().">>),
+ "exception exit: normal" = comm_err(<<"exit(normal).">>),
+ [foo] = scan(<<"begin history(0), foo end.">>),
+ application:unset_env(stdlib, shell_history_length),
+ [true] = scan(<<"begin <<10:(1024*1024*10)>>,"
"<<10:(1024*1024*10)>>, garbage_collect() end.">>),
- ?line "1: syntax error before: '.'" = comm_err("1-."),
- %% ?line comm_err(<<"exit().">>), % would hang
- ?line "exception error: no function clause matching call to history/1" =
+ "1: syntax error before: '.'" = comm_err("1-."),
+ %% comm_err(<<"exit().">>), % would hang
+ "exception error: no function clause matching call to history/1" =
comm_err(<<"history(foo).">>),
- ?line "exception error: no function clause matching call to results/1" =
+ "exception error: no function clause matching call to results/1" =
comm_err(<<"results(foo).">>),
- ?line Test = filename:join(?config(priv_dir, Config),
+ Test = filename:join(proplists:get_value(priv_dir, Config),
"otp_6554.erl"),
Contents = <<"-module(otp_6554).
-export([local_allowed/3, non_local_allowed/3]).
@@ -2514,31 +2444,31 @@ otp_6554(Config) when is_list(Config) ->
non_local_allowed(_,_,State) ->
{true,State}.
">>,
- ?line ok = compile_file(Config, Test, Contents, []),
- ?line "exception exit: restricted shell starts now" =
+ ok = compile_file(Config, Test, Contents, []),
+ "exception exit: restricted shell starts now" =
comm_err(<<"begin shell:start_restricted(otp_6554) end.">>),
- ?line "-record(r,{}).\n1.\nok.\n" =
+ "-record(r,{}).\n1.\nok.\n" =
t(<<"f(), f(B), h(), b(), history(20), results(20),"
"rd(r, {}), rl(r), rf('_'), rl(), rf(),"
"rp(1), _ = rr({foo}), _ = rr({foo}, []),"
"rr({foo}, [], []), ok.">>),
- ?line "false.\n" = t(<<"catch_exception(true).">>),
- ?line "exception exit: restricted shell stopped"=
+ "false.\n" = t(<<"catch_exception(true).">>),
+ "exception exit: restricted shell stopped"=
comm_err(<<"begin shell:stop_restricted() end.">>),
- ?line "true.\n" = t(<<"catch_exception(false).">>),
+ "true.\n" = t(<<"catch_exception(false).">>),
- ?line "20\n1\n1\n1: results(2)\n2: 1\n-> 1\n3: v(2)\n-> 1.\nok.\n" =
+ "20\n1\n1\n1: results(2)\n2: 1\n-> 1\n3: v(2)\n-> 1.\nok.\n" =
t(<<"results(2). 1. v(2). h().">>),
- ?line application:unset_env(stdlib, shell_saved_results),
- ?line "1\nfoo\n17\nB = foo\nC = 17\nF = fun() ->\n foo"
+ application:unset_env(stdlib, shell_saved_results),
+ "1\nfoo\n17\nB = foo\nC = 17\nF = fun() ->\n foo"
"\n end.\nok.\n" =
t(<<"begin F = fun() -> foo end, 1 end. B = F(). C = 17. b().">>),
- ?line "3: command not found" = comm_err(<<"#{v(3) => v}.">>),
- ?line "3: command not found" = comm_err(<<"#{k => v(3)}.">>),
- ?line "3: command not found" = comm_err(<<"#{v(3) := v}.">>),
- ?line "3: command not found" = comm_err(<<"#{k := v(3)}.">>),
- ?line "3: command not found" = comm_err(<<"(v(3))#{}.">>),
+ "3: command not found" = comm_err(<<"#{v(3) => v}.">>),
+ "3: command not found" = comm_err(<<"#{k => v(3)}.">>),
+ "3: command not found" = comm_err(<<"#{v(3) := v}.">>),
+ "3: command not found" = comm_err(<<"#{k := v(3)}.">>),
+ "3: command not found" = comm_err(<<"(v(3))#{}.">>),
%% Tests I'd like to do: (you should try them manually)
%% "catch spawn_link(fun() -> timer:sleep(1000), exit(foo) end)."
%% "** exception error: foo" should be output after 1 second
@@ -2550,12 +2480,10 @@ otp_6554(Config) when is_list(Config) ->
ok.
-otp_7184(doc) ->
- "OTP-7184. Propagate exit signals from dying evaluator process.";
-otp_7184(suite) -> [];
+%% OTP-7184. Propagate exit signals from dying evaluator process.
otp_7184(Config) when is_list(Config) ->
register(otp_7184, self()),
- ?line catch
+ catch
t(<<"P = self(),
spawn_link(fun() -> process_flag(trap_exit,true),
P ! up,
@@ -2567,7 +2495,7 @@ otp_7184(Config) when is_list(Config) ->
erlang:raise(throw, thrown, []).">>),
receive {otp_7184,{'EXIT',_,{{nocatch,thrown},[]}}} -> ok end,
- ?line catch
+ catch
t(<<"P = self(),
spawn_link(fun() -> process_flag(trap_exit,true),
P ! up,
@@ -2579,7 +2507,7 @@ otp_7184(Config) when is_list(Config) ->
erlang:raise(exit, fini, []).">>),
receive {otp_7184,{'EXIT',_,{fini,[]}}} -> ok end,
- ?line catch
+ catch
t(<<"P = self(),
spawn_link(fun() -> process_flag(trap_exit,true),
P ! up,
@@ -2594,18 +2522,16 @@ otp_7184(Config) when is_list(Config) ->
unregister(otp_7184),
%% v/1, a few missed cases
- ?line "17\n<<0,0,0,64>>.\nok.\n" =
+ "17\n<<0,0,0,64>>.\nok.\n" =
t(<<"17. "
"<<64:32>>. "
"<<64>> = << << X >> || << X >> <= v(2), X > v(1) >>, ok.">>),
- ?line "17\n<<0,17>>.\n" =t(<<"17. <<(v(1)):16>>.">>),
+ "17\n<<0,17>>.\n" =t(<<"17. <<(v(1)):16>>.">>),
ok.
-otp_7232(doc) ->
- "OTP-7232. qlc:info() bug.";
-otp_7232(suite) -> [];
+%% OTP-7232. qlc:info() bug.
otp_7232(Config) when is_list(Config) ->
Info = <<"qlc:info(qlc:sort(qlc:q([X || X <- [55296,56296]]), "
"{order, fun(A,B)-> A>B end})).">>,
@@ -2616,24 +2542,22 @@ otp_7232(Config) when is_list(Config) ->
" end}])" = evaluate(Info, []),
ok.
-otp_8393(doc) ->
- "OTP-8393. Prompt string.";
-otp_8393(suite) -> [];
+%% OTP-8393. Prompt string.
otp_8393(Config) when is_list(Config) ->
- ?line _ = shell:prompt_func(default),
- ?line "Bad prompt function: '> '" =
+ _ = shell:prompt_func(default),
+ "Bad prompt function: '> '" =
prompt_err(<<"shell:prompt_func('> ').">>),
- ?line _ = shell:prompt_func(default),
- ?line "exception error: an error occurred when evaluating an arithmetic expression"++_ =
+ _ = shell:prompt_func(default),
+ "exception error: an error occurred when evaluating an arithmetic expression"++_ =
prompt_err(<<"shell:prompt_func({shell_SUITE,prompt4}).">>),
- ?line _ = shell:prompt_func(default),
- ?line "default.\n" =
+ _ = shell:prompt_func(default),
+ "default.\n" =
t(<<"shell:prompt_func({shell_SUITE,prompt2}).">>),
- ?line _ = shell:prompt_func(default),
- ?line "default\nl.\n" =
+ _ = shell:prompt_func(default),
+ "default\nl.\n" =
t(<<"shell:prompt_func({shell_SUITE,prompt3}). l.">>),
%%
@@ -2642,8 +2566,8 @@ otp_8393(Config) when is_list(Config) ->
%% That is instead tested in the io_proto_SUITE, which has
%% the right infrastructure in place for such tests. /PaN
%%
- ?line _ = shell:prompt_func(default),
- ?line "default\nl.\n" =
+ _ = shell:prompt_func(default),
+ "default\nl.\n" =
t(<<"shell:prompt_func({shell_SUITE,prompt5}). l.">>),
%% Restricted shell.
@@ -2661,30 +2585,30 @@ otp_8393(Config) when is_list(Config) ->
non_local_allowed(_,_,State) ->
{false,State}.
">>,
- ?line Test = filename:join(?config(priv_dir, Config),
+ Test = filename:join(proplists:get_value(priv_dir, Config),
"test_restricted_shell.erl"),
- ?line ok = compile_file(Config, Test, Contents, []),
- ?line _ = shell:prompt_func(default),
- ?line "exception exit: restricted shell starts now" =
+ ok = compile_file(Config, Test, Contents, []),
+ _ = shell:prompt_func(default),
+ "exception exit: restricted shell starts now" =
comm_err(<<"begin shell:start_restricted("
"test_restricted_shell) end.">>),
- ?line "default.\n"++_ =
+ "default.\n"++_ =
t(<<"shell:prompt_func({shell_SUITE,prompt1}).">>),
- ?line "exception exit: restricted shell does not allow apple(" ++ _ =
+ "exception exit: restricted shell does not allow apple(" ++ _ =
comm_err(<<"apple(1).">>),
- ?line "{shell_SUITE,prompt1}.\n" =
+ "{shell_SUITE,prompt1}.\n" =
t(<<"shell:prompt_func(default).">>),
- ?line "exception exit: restricted shell stopped"=
+ "exception exit: restricted shell stopped"=
comm_err(<<"begin shell:stop_restricted() end.">>),
- ?line undefined =
+ undefined =
application:get_env(stdlib, restricted_shell),
- ?line NR = shell:results(20),
- ?line "default\n20.\n" =
+ NR = shell:results(20),
+ "default\n20.\n" =
t(<<"shell:prompt_func({shell_SUITE,prompt3}). results(0).">>),
- ?line _ = shell:prompt_func(default),
- ?line 0 = shell:results(NR),
+ _ = shell:prompt_func(default),
+ 0 = shell:results(NR),
ok.
prompt1(_L) ->
@@ -2745,12 +2669,10 @@ prompt_err(B) ->
S = string:strip(S2, both, $"),
string:strip(S, right, $.).
-otp_10302(doc) ->
- "OTP-10302. Unicode.";
-otp_10302(suite) -> [];
+%% OTP-10302. Unicode.
otp_10302(Config) when is_list(Config) ->
{ok,Node} = start_node(shell_suite_helper_2,
- "-pa "++?config(priv_dir,Config)++
+ "-pa "++proplists:get_value(priv_dir,Config)++
" +pc unicode"),
Test1 =
<<"begin
@@ -3095,9 +3017,9 @@ run_file(Config, Module, Test) ->
ok.
compile_file(Config, File, Test, Opts0) ->
- ?line Opts = [export_all,return,{outdir,?config(priv_dir, Config)}|Opts0],
- ?line ok = file:write_file(File, Test),
- ?line case compile:file(File, Opts) of
+ Opts = [export_all,return,{outdir,proplists:get_value(priv_dir, Config)}|Opts0],
+ ok = file:write_file(File, Test),
+ case compile:file(File, Opts) of
{ok, _M, _Ws} -> ok;
_ -> error
end.
@@ -3105,10 +3027,10 @@ compile_file(Config, File, Test, Opts0) ->
filename(Name, Config) when is_atom(Name) ->
filename(atom_to_list(Name), Config);
filename(Name, Config) ->
- filename:join(?config(priv_dir, Config), Name).
+ filename:join(proplists:get_value(priv_dir, Config), Name).
start_node(Name, Xargs) ->
- ?line N = test_server:start_node(Name, slave, [{args, " " ++ Xargs}]),
+ N = test_server:start_node(Name, slave, [{args, " " ++ Xargs}]),
global:sync(),
N.
diff --git a/lib/stdlib/test/slave_SUITE.erl b/lib/stdlib/test/slave_SUITE.erl
index 65627b3741..dc14e4735a 100644
--- a/lib/stdlib/test/slave_SUITE.erl
+++ b/lib/stdlib/test/slave_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(slave_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2, t_start/1, t_start_link/1,
@@ -29,7 +29,9 @@
-export([fun_init/1, test_errors/1]).
-export([timeout_test/1, auth_test/1, rsh_test/1, start_a_slave/3]).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[t_start_link, start_link_nodedown, t_start, errors].
@@ -50,30 +52,27 @@ end_per_group(_GroupName, Config) ->
Config.
-t_start_link(suite) -> [];
t_start_link(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(20)),
-
%% Define useful variables.
- ?line Host = host(),
- ?line Slave1 = node_name(Host, slave1),
- ?line Slave2 = node_name(Host, slave2),
+ Host = host(),
+ Slave1 = node_name(Host, slave1),
+ Slave2 = node_name(Host, slave2),
%% Test slave:start_link() with one, two, and three arguments.
- ?line ThisNode = node(),
- ?line {error, {already_running, ThisNode}} = slave:start_link(Host),
- ?line {ok, Slave1} = slave:start_link(Host, slave1),
- ?line {ok, Slave2} = slave:start_link(Host, slave2, "-my_option 42"),
- ?line {ok, [["42"]]} = rpc:call(Slave2, init, get_argument, [my_option]),
+ ThisNode = node(),
+ {error, {already_running, ThisNode}} = slave:start_link(Host),
+ {ok, Slave1} = slave:start_link(Host, slave1),
+ {ok, Slave2} = slave:start_link(Host, slave2, "-my_option 42"),
+ {ok, [["42"]]} = rpc:call(Slave2, init, get_argument, [my_option]),
%% Kill the two slave nodes and verify that they are dead.
- ?line rpc:cast(Slave1, erlang, halt, []),
- ?line rpc:cast(Slave2, erlang, halt, []),
- ?line is_dead(Slave1),
- ?line is_dead(Slave2),
+ rpc:cast(Slave1, erlang, halt, []),
+ rpc:cast(Slave2, erlang, halt, []),
+ is_dead(Slave1),
+ is_dead(Slave2),
%% Start two slave nodes from another process and verify that
%% the slaves die when that process terminates.
@@ -85,41 +84,36 @@ t_start_link(Config) when is_list(Config) ->
Parent ! slaves_started,
receive never -> ok end
end),
- ?line receive slaves_started -> ok end,
- ?line process_flag(trap_exit, true),
- ?line wait_alive(Slave1),
- ?line wait_alive(Slave2),
- ?line exit(Pid, kill),
- ?line receive {'EXIT', Pid, killed} -> ok end,
- ?line test_server:sleep(250),
- ?line is_dead(Slave1),
- ?line is_dead(Slave2),
-
- ?line test_server:timetrap_cancel(Dog),
+ receive slaves_started -> ok end,
+ process_flag(trap_exit, true),
+ wait_alive(Slave1),
+ wait_alive(Slave2),
+ exit(Pid, kill),
+ receive {'EXIT', Pid, killed} -> ok end,
+ ct:sleep(250),
+ is_dead(Slave1),
+ is_dead(Slave2),
+
ok.
%% Test that slave:start_link() works when the master exits.
-start_link_nodedown(suite) -> [];
start_link_nodedown(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(20)),
-
%% Define useful variables.
- ?line Host = host(),
- ?line Master = node_name(Host, my_master),
- ?line Slave = node_name(Host, my_slave),
+ Host = host(),
+ Master = node_name(Host, my_master),
+ Slave = node_name(Host, my_slave),
+
+ Pa = "-pa " ++ filename:dirname(code:which(?MODULE)),
+ {ok, Master} = slave:start_link(Host, my_master, Pa),
+ spawn(Master, ?MODULE, start_a_slave, [self(), Host, my_slave]),
+ {reply, {ok, _Node}} = receive Any -> Any end,
- ?line Pa = "-pa " ++ filename:dirname(code:which(?MODULE)),
- ?line {ok, Master} = slave:start_link(Host, my_master, Pa),
- ?line spawn(Master, ?MODULE, start_a_slave, [self(), Host, my_slave]),
- ?line {reply, {ok, _Node}} = receive Any -> Any end,
-
- ?line rpc:call(Master, erlang, halt, []),
- ?line receive after 200 -> ok end,
- ?line pang = net_adm:ping(Slave),
+ rpc:call(Master, erlang, halt, []),
+ receive after 200 -> ok end,
+ pang = net_adm:ping(Slave),
- ?line test_server:timetrap_cancel(Dog),
ok.
start_a_slave(ReplyTo, Host, Name) ->
@@ -128,82 +122,74 @@ start_a_slave(ReplyTo, Host, Name) ->
%% Test slave:start().
-t_start(suite) -> [];
t_start(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(20)),
-
%% Define useful variables.
- ?line Host = host(),
- ?line Slave1 = node_name(Host, slave1),
- ?line Slave2 = node_name(Host, slave2),
+ Host = host(),
+ Slave1 = node_name(Host, slave1),
+ Slave2 = node_name(Host, slave2),
%% By running all tests from this master node which is linked
%% to this test case, we ensure that all slaves are killed
%% if this test case fails. (If they are not, and therefore further
%% test cases fail, there is a bug in slave.)
- ?line {ok, Master} = slave:start_link(Host, master),
-
+ {ok, Master} = slave:start_link(Host, master),
+
%% Test slave:start() with one, two, and three arguments.
- ?line ThisNode = node(),
- ?line {error, {already_running, ThisNode}} = slave:start(Host),
- ?line {ok, Slave1} = rpc:call(Master, slave, start, [Host, slave1]),
- ?line {ok, Slave2} = rpc:call(Master, slave, start,
- [Host, slave2, "-my_option 42"]),
- ?line {ok, [["42"]]} = rpc:call(Slave2, init, get_argument, [my_option]),
+ ThisNode = node(),
+ {error, {already_running, ThisNode}} = slave:start(Host),
+ {ok, Slave1} = rpc:call(Master, slave, start, [Host, slave1]),
+ {ok, Slave2} = rpc:call(Master, slave, start,
+ [Host, slave2, "-my_option 42"]),
+ {ok, [["42"]]} = rpc:call(Slave2, init, get_argument, [my_option]),
%% Test that a slave terminates when its master node terminates.
- ?line ok = slave:stop(Slave2),
- ?line is_dead(Slave2),
- ?line {ok, Slave2} = rpc:call(Slave1, slave, start, [Host, slave2]),
- ?line is_alive(Slave2),
- ?line rpc:call(Slave1, erlang, halt, []), % Kill master.
+ ok = slave:stop(Slave2),
+ is_dead(Slave2),
+ {ok, Slave2} = rpc:call(Slave1, slave, start, [Host, slave2]),
+ is_alive(Slave2),
+ rpc:call(Slave1, erlang, halt, []), % Kill master.
receive after 1000 -> ok end, % Make sure slaves have noticed
% their dead master.
- ?line is_dead(Slave1),
- ?line is_dead(Slave2), % Slave should be dead, too.
+ is_dead(Slave1),
+ is_dead(Slave2), % Slave should be dead, too.
%% Kill all slaves and verify that they are dead.
- ?line ok = slave:stop(Slave1),
- ?line ok = slave:stop(Slave2),
- ?line is_dead(Slave1),
- ?line is_dead(Slave2),
+ ok = slave:stop(Slave1),
+ ok = slave:stop(Slave2),
+ is_dead(Slave1),
+ is_dead(Slave2),
- ?line test_server:timetrap_cancel(Dog),
ok.
%% Test the various error conditions in parallell (since the timeout
%% in slave is 32 seconds).
-errors(suite) -> [];
errors(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:seconds(50)),
-
- ?line process_flag(trap_exit, true),
- ?line Pa = filename:dirname(code:which(?MODULE)),
- ?line {ok, Master} = slave_start_link(host(), master,
- "-rsh no_rsh_program -pa "++Pa++
- " -env ERL_CRASH_DUMP erl_crash_dump.master"),
- ?line Pids = rpc:call(Master, ?MODULE, test_errors, [self()]),
- ?line wait_for_result(Pids),
+ process_flag(trap_exit, true),
+ Pa = filename:dirname(code:which(?MODULE)),
+ {ok, Master} = slave_start_link(host(), master,
+ "-rsh no_rsh_program -pa "++Pa++
+ " -env ERL_CRASH_DUMP erl_crash_dump.master"),
+ Pids = rpc:call(Master, ?MODULE, test_errors, [self()]),
+ wait_for_result(Pids),
- ?line test_server:timetrap_cancel(Dog),
ok.
wait_for_result([]) ->
ok;
wait_for_result(Pids) ->
- ?line receive
- {'EXIT', Pid, normal} ->
- io:format("Process ~p terminated", [Pid]),
- wait_for_result(lists:delete(Pid, Pids));
- {'EXIT', _, Reason} ->
- exit(Reason)
- end.
+ receive
+ {'EXIT', Pid, normal} ->
+ io:format("Process ~p terminated", [Pid]),
+ wait_for_result(lists:delete(Pid, Pids));
+ {'EXIT', _, Reason} ->
+ exit(Reason)
+ end.
show_process_info(Pid) ->
io:format("~p: ~p", [Pid, catch process_info(Pid, initial_call)]).
@@ -211,25 +197,25 @@ show_process_info(Pid) ->
test_errors(ResultTo) ->
%% Sigh! We use ordinary spawn instead of fun_spawn/1 to be able
%% identify the processes by their initial call.
- ?line P1 = spawn(?MODULE, timeout_test, [ResultTo]),
- ?line P2 = spawn(?MODULE, auth_test, [ResultTo]),
- ?line P3 = spawn(?MODULE, rsh_test, [ResultTo]),
+ P1 = spawn(?MODULE, timeout_test, [ResultTo]),
+ P2 = spawn(?MODULE, auth_test, [ResultTo]),
+ P3 = spawn(?MODULE, rsh_test, [ResultTo]),
Pids =[P1, P2, P3],
- ?line lists:foreach(fun show_process_info/1, Pids),
+ lists:foreach(fun show_process_info/1, Pids),
Pids.
timeout_test(ResultTo) ->
link(ResultTo),
- ?line {error, timeout} = slave:start(host(), slave1, "-boot no_boot_script").
+ {error, timeout} = slave:start(host(), slave1, "-boot no_boot_script").
auth_test(ResultTo) ->
link(ResultTo),
- ?line {error, timeout} = slave:start(host(), slave2,
- "-setcookie definitely_not_a_cookie").
+ {error, timeout} = slave:start(host(), slave2,
+ "-setcookie definitely_not_a_cookie").
rsh_test(ResultTo) ->
link(ResultTo),
- ?line {error, no_rsh} = slave:start(super, slave3).
+ {error, no_rsh} = slave:start(super, slave3).
%%% Utilities.
@@ -239,7 +225,7 @@ wait_alive(Node) ->
wait_alive_1(10, Node).
wait_alive_1(0, Node) ->
- ?t:fail({still_not_alive,Node});
+ ct:fail({still_not_alive,Node});
wait_alive_1(N, Node) ->
case rpc:call(Node, init, get_status, []) of
{started,_} ->
diff --git a/lib/stdlib/test/sofs_SUITE.erl b/lib/stdlib/test/sofs_SUITE.erl
index d23eb3abb9..2277b2d6fb 100644
--- a/lib/stdlib/test/sofs_SUITE.erl
+++ b/lib/stdlib/test/sofs_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(sofs_SUITE).
-%-define(debug, true).
+%%-define(debug, true).
-ifdef(debug).
-define(format(S, A), io:format(S, A)).
@@ -27,7 +27,7 @@
-define(config(X,Y), foo).
-define(t, test_server).
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(format(S, A), ok).
-endif.
@@ -35,28 +35,28 @@
init_per_group/2,end_per_group/2]).
-export([ from_term_1/1, set_1/1, from_sets_1/1, relation_1/1,
- a_function_1/1, family_1/1, projection/1,
- relation_to_family_1/1, domain_1/1, range_1/1, image/1,
- inverse_image/1, inverse_1/1, converse_1/1, no_elements_1/1,
- substitution/1, restriction/1, drestriction/1,
- strict_relation_1/1, extension/1, weak_relation_1/1,
- to_sets_1/1, specification/1, union_1/1, intersection_1/1,
- difference/1, symdiff/1, symmetric_partition/1,
- is_sofs_set_1/1, is_set_1/1, is_equal/1, is_subset/1,
- is_a_function_1/1, is_disjoint/1, join/1, canonical/1,
- composite_1/1, relative_product_1/1, relative_product_2/1,
- product_1/1, partition_1/1, partition_3/1,
- multiple_relative_product/1, digraph/1, constant_function/1,
- misc/1]).
+ a_function_1/1, family_1/1, projection/1,
+ relation_to_family_1/1, domain_1/1, range_1/1, image/1,
+ inverse_image/1, inverse_1/1, converse_1/1, no_elements_1/1,
+ substitution/1, restriction/1, drestriction/1,
+ strict_relation_1/1, extension/1, weak_relation_1/1,
+ to_sets_1/1, specification/1, union_1/1, intersection_1/1,
+ difference/1, symdiff/1, symmetric_partition/1,
+ is_sofs_set_1/1, is_set_1/1, is_equal/1, is_subset/1,
+ is_a_function_1/1, is_disjoint/1, join/1, canonical/1,
+ composite_1/1, relative_product_1/1, relative_product_2/1,
+ product_1/1, partition_1/1, partition_3/1,
+ multiple_relative_product/1, digraph/1, constant_function/1,
+ misc/1]).
-export([ family_specification/1,
- family_domain_1/1, family_range_1/1,
- family_to_relation_1/1,
- union_of_family_1/1, intersection_of_family_1/1,
- family_projection/1, family_difference/1,
- family_intersection_1/1, family_union_1/1,
- family_intersection_2/1, family_union_2/1,
- partition_family/1]).
+ family_domain_1/1, family_range_1/1,
+ family_to_relation_1/1,
+ union_of_family_1/1, intersection_of_family_1/1,
+ family_projection/1, family_difference/1,
+ family_intersection_1/1, family_union_1/1,
+ family_intersection_2/1, family_union_2/1,
+ partition_family/1]).
-import(sofs,
[a_function/1, a_function/2, constant_function/2,
@@ -87,7 +87,9 @@
-compile({inline,[{eval,2}]}).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,2}}].
all() ->
[{group, sofs}, {group, sofs_family}].
@@ -129,401 +131,384 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_Case, Config) ->
- Dog=?t:timetrap(?t:minutes(2)),
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
%% [{2,b},{1,a,b}] == lists:sort([{2,b},{1,a,b}])
%% [{1,a,b},{2,b}] == lists:keysort(1,[{2,b},{1,a,b}])
-from_term_1(suite) -> [];
-from_term_1(doc) -> [""];
from_term_1(Conf) when is_list(Conf) ->
%% would go wrong: projection(1,from_term([{2,b},{1,a,b}])),
- ?line {'EXIT', {badarg, _}} = (catch from_term([], {atom,'_',atom})),
- ?line {'EXIT', {badarg, _}} = (catch from_term([], [])),
- ?line {'EXIT', {badarg, _}} = (catch from_term([], [atom,atom])),
-
- ?line [] = to_external(from_term([])),
- ?line eval(from_term([]), empty_set()),
- ?line [] = to_external(from_term([], ['_'])),
- ?line eval(from_term([], ['_']), empty_set()),
- ?line [[]] = to_external(from_term([[]])),
- ?line [[['_']]] = type(from_term([[],[[]]])),
- ?line [[],[[]]] = to_external(from_term([[],[[]]])),
- ?line [[['_']]] = type(from_term([[],[[]]])),
- ?line eval(from_term([a],['_']), set([a])),
- ?line [[],[a]] = to_external(from_term([[],[a]])),
- ?line [[],[{a}]] = to_external(from_term([[{a}],[]])),
- ?line [{[],[{a,b,[d]}]},{[{a,b}],[]}] =
+ {'EXIT', {badarg, _}} = (catch from_term([], {atom,'_',atom})),
+ {'EXIT', {badarg, _}} = (catch from_term([], [])),
+ {'EXIT', {badarg, _}} = (catch from_term([], [atom,atom])),
+
+ [] = to_external(from_term([])),
+ eval(from_term([]), empty_set()),
+ [] = to_external(from_term([], ['_'])),
+ eval(from_term([], ['_']), empty_set()),
+ [[]] = to_external(from_term([[]])),
+ [[['_']]] = type(from_term([[],[[]]])),
+ [[],[[]]] = to_external(from_term([[],[[]]])),
+ [[['_']]] = type(from_term([[],[[]]])),
+ eval(from_term([a],['_']), set([a])),
+ [[],[a]] = to_external(from_term([[],[a]])),
+ [[],[{a}]] = to_external(from_term([[{a}],[]])),
+ [{[],[{a,b,[d]}]},{[{a,b}],[]}] =
to_external(from_term([{[],[{a,b,[d]}]},{[{a,b}],[]}])),
- ?line [{[a,b],[c,d]}] = to_external(from_term([{[a,b],[c,d]}])),
- ?line [{{a,b},[a,b],{{a},{b}}}] =
+ [{[a,b],[c,d]}] = to_external(from_term([{[a,b],[c,d]}])),
+ [{{a,b},[a,b],{{a},{b}}}] =
to_external(from_term([{{a,b},[a,b],{{a},{b}}}])),
- ?line [{{a,{[a,b]},a}},{{z,{[y,z]},z}}] =
+ [{{a,{[a,b]},a}},{{z,{[y,z]},z}}] =
to_external(from_term([{{a,{[a,b,a]},a}},{{z,{[y,y,z]},z}}])),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch from_term([{m1,[{m1,f1,1},{m1,f2,2}]},{m2,[]},{m3,[a]}])),
- ?line MS1 = [{m1,[{m1,f1,1},{m1,f2,2}]},{m2,[]},{m3,[{m3,f3,3}]}],
- ?line eval(to_external(from_term(MS1)), MS1),
-
- ?line eval(to_external(from_term(a)), a),
- ?line eval(to_external(from_term({a})), {a}),
-
- ?line eval(to_external(from_term([[a],[{b,c}]],[[atomic]])),
- [[a],[{b,c}]]),
- ?line eval(type(from_term([[a],[{b,c}]],[[atomic]])),
- [[atomic]]),
-
- ?line {'EXIT', {badarg, _}} = (catch from_term([[],[],a])),
- ?line {'EXIT', {badarg, _}} = (catch from_term([{[a,b],[c,{d}]}])),
- ?line {'EXIT', {badarg, _}} = (catch from_term([[],[a],[{a}]])),
- ?line {'EXIT', {badarg, _}} = (catch from_term([a,{a,b}])),
- ?line {'EXIT', {badarg, _}} = (catch from_term([[a],[{b,c}]],[['_']])),
- ?line {'EXIT', {badarg, _}} = (catch from_term([a | {a,b}])),
- ?line {'EXIT', {badarg, _}} =
+ MS1 = [{m1,[{m1,f1,1},{m1,f2,2}]},{m2,[]},{m3,[{m3,f3,3}]}],
+ eval(to_external(from_term(MS1)), MS1),
+
+ eval(to_external(from_term(a)), a),
+ eval(to_external(from_term({a})), {a}),
+
+ eval(to_external(from_term([[a],[{b,c}]],[[atomic]])),
+ [[a],[{b,c}]]),
+ eval(type(from_term([[a],[{b,c}]],[[atomic]])),
+ [[atomic]]),
+
+ {'EXIT', {badarg, _}} = (catch from_term([[],[],a])),
+ {'EXIT', {badarg, _}} = (catch from_term([{[a,b],[c,{d}]}])),
+ {'EXIT', {badarg, _}} = (catch from_term([[],[a],[{a}]])),
+ {'EXIT', {badarg, _}} = (catch from_term([a,{a,b}])),
+ {'EXIT', {badarg, _}} = (catch from_term([[a],[{b,c}]],[['_']])),
+ {'EXIT', {badarg, _}} = (catch from_term([a | {a,b}])),
+ {'EXIT', {badarg, _}} =
(catch from_term([{{a},b,c},{d,e,f}],[{{atom},atom,atom}])),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch from_term([{a,{b,c}} | tail], [{atom,{atom,atom}}])),
- ?line {'EXIT', {badarg, _}} = (catch from_term({})),
- ?line {'EXIT', {badarg, _}} = (catch from_term([{}])),
+ {'EXIT', {badarg, _}} = (catch from_term({})),
+ {'EXIT', {badarg, _}} = (catch from_term([{}])),
- ?line [{foo,bar},[b,a]] =
+ [{foo,bar},[b,a]] =
to_external(from_term([[b,a],{foo,bar},[b,a]], [atom])),
- ?line [{[atom],{atom,atom}}] =
+ [{[atom],{atom,atom}}] =
type(from_term([{[], {a,b}},{[a,b],{e,f}}])),
- ?line [{[atom],{atom,atom}}] =
+ [{[atom],{atom,atom}}] =
type(from_term([{[], {a,b}},{[a,b],{e,f}}], [{[atom],{atom,atom}}])),
- ?line [[atom]] = type(from_term([[a],[{b,c}]],[[atom]])),
+ [[atom]] = type(from_term([[a],[{b,c}]],[[atom]])),
- ?line {atom, atom} = type(from_term({a,b}, {atom, atom})),
- ?line atom = type(from_term(a, atom)),
- ?line {'EXIT', {badarg, _}} = (catch from_term({a,b},{atom})),
- ?line [{{a},b,c},{{d},e,f}] =
+ {atom, atom} = type(from_term({a,b}, {atom, atom})),
+ atom = type(from_term(a, atom)),
+ {'EXIT', {badarg, _}} = (catch from_term({a,b},{atom})),
+ [{{a},b,c},{{d},e,f}] =
to_external(from_term([{{a},b,c},{{a},b,c},{{d},e,f}],
[{{atom},atom,atom}])),
%% from_external too...
- ?line e = to_external(from_external(e, atom)),
- ?line {e} = to_external(from_external({e}, {atom})),
- ?line [e] = to_external(from_external([e], [atom])),
+ e = to_external(from_external(e, atom)),
+ {e} = to_external(from_external({e}, {atom})),
+ [e] = to_external(from_external([e], [atom])),
%% and is_type...
- ?line true = is_type(['_']),
- ?line false = is_type('_'),
- ?line true = is_type([['_']]),
- ?line false = is_type({atom,[],atom}),
- ?line false = is_type({atom,'_',atom}),
- ?line true = is_type({atom,atomic,atom}),
- ?line true = is_type({atom,atom}),
- ?line true = is_type(atom),
- ?line true = is_type([atom]),
- ?line true = is_type(type),
+ true = is_type(['_']),
+ false = is_type('_'),
+ true = is_type([['_']]),
+ false = is_type({atom,[],atom}),
+ false = is_type({atom,'_',atom}),
+ true = is_type({atom,atomic,atom}),
+ true = is_type({atom,atom}),
+ true = is_type(atom),
+ true = is_type([atom]),
+ true = is_type(type),
ok.
-set_1(suite) -> [];
-set_1(doc) -> [""];
set_1(Conf) when is_list(Conf) ->
%% set/1
- ?line {'EXIT', {badarg, _}} = (catch set(a)),
- ?line {'EXIT', {badarg, _}} = (catch set({a})),
- ?line eval(set([]), from_term([],[atom])),
- ?line eval(set([a,b,c]), from_term([a,b,c])),
- ?line eval(set([a,b,a,a,b]), from_term([a,b])),
- ?line eval(set([a,b,c,a,d,d,c,1]), from_term([1,a,b,c,d])),
- ?line eval(set([a,b,d,a,c]), from_term([a,b,c,d])),
- ?line eval(set([f,e,d,c,d]), from_term([c,d,e,f])),
- ?line eval(set([h,f,d,g,g,d,c]), from_term([c,d,f,g,h])),
- ?line eval(set([h,e,d,k,l]), from_term([d,e,h,k,l])),
- ?line eval(set([h,e,c,k,d]), from_term([c,d,e,h,k])),
+ {'EXIT', {badarg, _}} = (catch set(a)),
+ {'EXIT', {badarg, _}} = (catch set({a})),
+ eval(set([]), from_term([],[atom])),
+ eval(set([a,b,c]), from_term([a,b,c])),
+ eval(set([a,b,a,a,b]), from_term([a,b])),
+ eval(set([a,b,c,a,d,d,c,1]), from_term([1,a,b,c,d])),
+ eval(set([a,b,d,a,c]), from_term([a,b,c,d])),
+ eval(set([f,e,d,c,d]), from_term([c,d,e,f])),
+ eval(set([h,f,d,g,g,d,c]), from_term([c,d,f,g,h])),
+ eval(set([h,e,d,k,l]), from_term([d,e,h,k,l])),
+ eval(set([h,e,c,k,d]), from_term([c,d,e,h,k])),
%% set/2
- ?line {'EXIT', {badarg, _}} = (catch set(a, [a])),
- ?line {'EXIT', {badarg, _}} = (catch set({a}, [a])),
- ?line {'EXIT', {badarg, _}} = (catch set([a], {a})),
- ?line {'EXIT', {badarg, _}} = (catch set([a], a)),
- ?line {'EXIT', {badarg, _}} = (catch set([a], [a,b])),
- ?line {'EXIT', {badarg, _}} = (catch set([a | b],[foo])),
- ?line {'EXIT', {badarg, _}} = (catch set([a | b],['_'])),
- ?line {'EXIT', {badarg, _}} = (catch set([a | b],[[atom]])),
- ?line {'EXIT', {badarg, _}} = (catch set([{}],[{}])),
- ?line eval(set([a],['_']), from_term([a],['_'])),
- ?line eval(set([], ['_']), empty_set()),
- ?line eval(set([a,b,a,b],[foo]), from_term([a,b],[foo])),
+ {'EXIT', {badarg, _}} = (catch set(a, [a])),
+ {'EXIT', {badarg, _}} = (catch set({a}, [a])),
+ {'EXIT', {badarg, _}} = (catch set([a], {a})),
+ {'EXIT', {badarg, _}} = (catch set([a], a)),
+ {'EXIT', {badarg, _}} = (catch set([a], [a,b])),
+ {'EXIT', {badarg, _}} = (catch set([a | b],[foo])),
+ {'EXIT', {badarg, _}} = (catch set([a | b],['_'])),
+ {'EXIT', {badarg, _}} = (catch set([a | b],[[atom]])),
+ {'EXIT', {badarg, _}} = (catch set([{}],[{}])),
+ eval(set([a],['_']), from_term([a],['_'])),
+ eval(set([], ['_']), empty_set()),
+ eval(set([a,b,a,b],[foo]), from_term([a,b],[foo])),
ok.
-from_sets_1(suite) -> [];
-from_sets_1(doc) -> [""];
from_sets_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
+ E = empty_set(),
%% unordered
- ?line eval(from_sets([]), E),
- ?line {'EXIT', {type_mismatch, _}} =
+ eval(from_sets([]), E),
+ {'EXIT', {type_mismatch, _}} =
(catch from_sets([from_term([{a,b}]),
E,
from_term([{a,b,c}])])),
- ?line eval(from_sets([from_term([{a,b}]), E]),
- from_term([[],[{a,b}]])),
+ eval(from_sets([from_term([{a,b}]), E]),
+ from_term([[],[{a,b}]])),
- ?line eval(from_sets([from_term({a,b},{atom,atom}),
- from_term({b,c},{atom,atom})]),
- relation([{a,b}, {b,c}])),
- ?line {'EXIT', {type_mismatch, _}} =
+ eval(from_sets([from_term({a,b},{atom,atom}),
+ from_term({b,c},{atom,atom})]),
+ relation([{a,b}, {b,c}])),
+ {'EXIT', {type_mismatch, _}} =
(catch from_sets([from_term({a,b},{atom,atom}),
from_term({a,b,c},{atom,atom,atom})])),
- ?line {'EXIT', {badarg, _}} = (catch from_sets(foo)),
- ?line eval(from_sets([E]), from_term([[]])),
- ?line eval(from_sets([E,E]), from_term([[]])),
- ?line eval(from_sets([E,set([a])]), from_term([[],[a]])),
- ?line {'EXIT', {badarg, _}} = (catch from_sets([E,{a}])),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {badarg, _}} = (catch from_sets(foo)),
+ eval(from_sets([E]), from_term([[]])),
+ eval(from_sets([E,E]), from_term([[]])),
+ eval(from_sets([E,set([a])]), from_term([[],[a]])),
+ {'EXIT', {badarg, _}} = (catch from_sets([E,{a}])),
+ {'EXIT', {type_mismatch, _}} =
(catch from_sets([E,from_term({a}),E])),
- ?line {'EXIT', {type_mismatch, _}} = (catch from_sets([from_term({a}),E])),
+ {'EXIT', {type_mismatch, _}} = (catch from_sets([from_term({a}),E])),
%% ordered
- ?line O = {from_term(a,atom), from_term({b}, {atom}), set([c,d])},
- ?line eval(from_sets(O), from_term({a,{b},[c,d]}, {atom,{atom},[atom]})),
- ?line {'EXIT', {badarg, _}} = (catch from_sets([a,b])),
- ?line {'EXIT', {badarg, _}} = (catch from_sets({a,b})),
- ?line eval(from_sets({from_term({a}),E}), from_term({{a},[]})),
+ O = {from_term(a,atom), from_term({b}, {atom}), set([c,d])},
+ eval(from_sets(O), from_term({a,{b},[c,d]}, {atom,{atom},[atom]})),
+ {'EXIT', {badarg, _}} = (catch from_sets([a,b])),
+ {'EXIT', {badarg, _}} = (catch from_sets({a,b})),
+ eval(from_sets({from_term({a}),E}), from_term({{a},[]})),
ok.
-relation_1(suite) -> [];
-relation_1(doc) -> [""];
relation_1(Conf) when is_list(Conf) ->
%% relation/1
- ?line eval(relation([]), from_term([], [{atom,atom}])),
- ?line eval(from_term([{a}]), relation([{a}])),
- ?line {'EXIT', {badarg, _}} = (catch relation(a)),
- ?line {'EXIT', {badarg, _}} = (catch relation([{a} | a])),
- ?line {'EXIT', {badarg, _}} = (catch relation([{}])),
- ?line {'EXIT', {badarg, _}} = (catch relation([],0)),
- ?line {'EXIT', {badarg, _}} = (catch relation([{a}],a)),
+ eval(relation([]), from_term([], [{atom,atom}])),
+ eval(from_term([{a}]), relation([{a}])),
+ {'EXIT', {badarg, _}} = (catch relation(a)),
+ {'EXIT', {badarg, _}} = (catch relation([{a} | a])),
+ {'EXIT', {badarg, _}} = (catch relation([{}])),
+ {'EXIT', {badarg, _}} = (catch relation([],0)),
+ {'EXIT', {badarg, _}} = (catch relation([{a}],a)),
%% relation/2
- ?line eval(relation([{a},{b}], 1), from_term([{a},{b}])),
- ?line eval(relation([{1,a},{2,b},{1,a}], [{x,y}]),
- from_term([{1,a},{2,b}], [{x,y}])),
- ?line eval(relation([{[1,2],a},{[2,1],b},{[2,1],a}], [{[x],y}]),
- from_term([{[1,2],a},{[1,2],b}], [{[x],y}])),
- ?line {'EXIT', {badarg, _}} = (catch relation([{1,a},{2,b}], [{[x],y}])),
- ?line {'EXIT', {badarg, _}} = (catch relation([{1,a},{1,a,b}], [{x,y}])),
- ?line {'EXIT', {badarg, _}} = (catch relation([{a}], 2)),
- ?line {'EXIT', {badarg, _}} = (catch relation([{a},{b},{c,d}], 1)),
- ?line eval(relation([{{a},[{foo,bar}]}], ['_']),
- from_term([{{a},[{foo,bar}]}], ['_'])),
- ?line eval(relation([], ['_']), from_term([], ['_'])),
- ?line {'EXIT', {badarg, _}} = (catch relation([[a]],['_'])),
- ?line eval(relation([{[a,b,a]}], [{[atom]}]), from_term([{[a,b,a]}])),
- ?line eval(relation([{[a,b,a],[[d,e,d]]}], [{[atom],[[atom]]}]),
- from_term([{[a,b,a],[[d,e,d]]}])),
- ?line eval(relation([{[a,b,a],[[d,e,d]]}], [{atom,[[atom]]}]),
- from_term([{[a,b,a],[[d,e,d]]}], [{atom,[[atom]]}])),
+ eval(relation([{a},{b}], 1), from_term([{a},{b}])),
+ eval(relation([{1,a},{2,b},{1,a}], [{x,y}]),
+ from_term([{1,a},{2,b}], [{x,y}])),
+ eval(relation([{[1,2],a},{[2,1],b},{[2,1],a}], [{[x],y}]),
+ from_term([{[1,2],a},{[1,2],b}], [{[x],y}])),
+ {'EXIT', {badarg, _}} = (catch relation([{1,a},{2,b}], [{[x],y}])),
+ {'EXIT', {badarg, _}} = (catch relation([{1,a},{1,a,b}], [{x,y}])),
+ {'EXIT', {badarg, _}} = (catch relation([{a}], 2)),
+ {'EXIT', {badarg, _}} = (catch relation([{a},{b},{c,d}], 1)),
+ eval(relation([{{a},[{foo,bar}]}], ['_']),
+ from_term([{{a},[{foo,bar}]}], ['_'])),
+ eval(relation([], ['_']), from_term([], ['_'])),
+ {'EXIT', {badarg, _}} = (catch relation([[a]],['_'])),
+ eval(relation([{[a,b,a]}], [{[atom]}]), from_term([{[a,b,a]}])),
+ eval(relation([{[a,b,a],[[d,e,d]]}], [{[atom],[[atom]]}]),
+ from_term([{[a,b,a],[[d,e,d]]}])),
+ eval(relation([{[a,b,a],[[d,e,d]]}], [{atom,[[atom]]}]),
+ from_term([{[a,b,a],[[d,e,d]]}], [{atom,[[atom]]}])),
ok.
-a_function_1(suite) -> [];
-a_function_1(doc) -> [""];
a_function_1(Conf) when is_list(Conf) ->
%% a_function/1
- ?line eval(a_function([]), from_term([], [{atom,atom}])),
- ?line eval(a_function([{a,b},{a,b},{b,c}]), from_term([{a,b},{b,c}])),
- ?line {'EXIT', {badarg, _}} = (catch a_function([{a}])),
- ?line {'EXIT', {badarg, _}} = (catch a_function([{a},{b},{c,d}])),
- ?line {'EXIT', {badarg, _}} = (catch a_function(a)),
- ?line {'EXIT', {badarg, _}} = (catch a_function([{a,b} | a])),
- ?line {'EXIT', {bad_function, _}} =
+ eval(a_function([]), from_term([], [{atom,atom}])),
+ eval(a_function([{a,b},{a,b},{b,c}]), from_term([{a,b},{b,c}])),
+ {'EXIT', {badarg, _}} = (catch a_function([{a}])),
+ {'EXIT', {badarg, _}} = (catch a_function([{a},{b},{c,d}])),
+ {'EXIT', {badarg, _}} = (catch a_function(a)),
+ {'EXIT', {badarg, _}} = (catch a_function([{a,b} | a])),
+ {'EXIT', {bad_function, _}} =
(catch a_function([{a,b},{b,c},{a,c}])),
F = 0.0, I = round(F),
if
F == I -> % term ordering
- ?line {'EXIT', {bad_function, _}} =
+ {'EXIT', {bad_function, _}} =
(catch a_function([{I,a},{F,b}])),
- ?line {'EXIT', {bad_function, _}} =
- (catch a_function([{[I],a},{[F],b}],[{[a],b}]));
+ {'EXIT', {bad_function, _}} =
+ (catch a_function([{[I],a},{[F],b}],[{[a],b}]));
true ->
- ?line 2 = no_elements(a_function([{I,a},{F,b}])),
- ?line 2 = no_elements(a_function([{[I],a},{[F],b}],[{[a],b}]))
+ 2 = no_elements(a_function([{I,a},{F,b}])),
+ 2 = no_elements(a_function([{[I],a},{[F],b}],[{[a],b}]))
end,
%% a_function/2
FT = [{atom,atom}],
- ?line eval(a_function([], FT), from_term([], FT)),
- ?line eval(a_function([{a,b},{b,c},{b,c}], FT),
- from_term([{a,b},{b,c}], FT)),
- ?line {'EXIT', {badarg, _}} = (catch a_function([{a,b}], [{a}])),
- ?line {'EXIT', {badarg, _}} = (catch a_function([{a,b}], [{a,[b,c]}])),
- ?line {'EXIT', {badarg, _}} = (catch a_function([{a}], FT)),
- ?line {'EXIT', {badarg, _}} = (catch a_function([{a},{b},{c,d}], FT)),
- ?line {'EXIT', {badarg, _}} = (catch a_function(a, FT)),
- ?line {'EXIT', {badarg, _}} = (catch a_function([{a,b} | a], FT)),
- ?line eval(a_function([{{a},[{foo,bar}]}], ['_']),
- from_term([{{a},[{foo,bar}]}], ['_'])),
- ?line eval(a_function([], ['_']), from_term([], ['_'])),
- ?line {'EXIT', {badarg, _}} = (catch a_function([[a]],['_'])),
- ?line {'EXIT', {bad_function, _}} =
+ eval(a_function([], FT), from_term([], FT)),
+ eval(a_function([{a,b},{b,c},{b,c}], FT),
+ from_term([{a,b},{b,c}], FT)),
+ {'EXIT', {badarg, _}} = (catch a_function([{a,b}], [{a}])),
+ {'EXIT', {badarg, _}} = (catch a_function([{a,b}], [{a,[b,c]}])),
+ {'EXIT', {badarg, _}} = (catch a_function([{a}], FT)),
+ {'EXIT', {badarg, _}} = (catch a_function([{a},{b},{c,d}], FT)),
+ {'EXIT', {badarg, _}} = (catch a_function(a, FT)),
+ {'EXIT', {badarg, _}} = (catch a_function([{a,b} | a], FT)),
+ eval(a_function([{{a},[{foo,bar}]}], ['_']),
+ from_term([{{a},[{foo,bar}]}], ['_'])),
+ eval(a_function([], ['_']), from_term([], ['_'])),
+ {'EXIT', {badarg, _}} = (catch a_function([[a]],['_'])),
+ {'EXIT', {bad_function, _}} =
(catch a_function([{a,b},{b,c},{a,c}], FT)),
- ?line eval(a_function([{a,[a]},{a,[a,a]}], [{atom,[atom]}]),
- from_term([{a,[a]}])),
- ?line eval(a_function([{[b,a],c},{[a,b],c}], [{[atom],atom}]),
- from_term([{[a,b],c}])),
+ eval(a_function([{a,[a]},{a,[a,a]}], [{atom,[atom]}]),
+ from_term([{a,[a]}])),
+ eval(a_function([{[b,a],c},{[a,b],c}], [{[atom],atom}]),
+ from_term([{[a,b],c}])),
ok.
-family_1(suite) -> [];
-family_1(doc) -> [""];
family_1(Conf) when is_list(Conf) ->
%% family/1
- ?line eval(family([]), from_term([],[{atom,[atom]}])),
- ?line {'EXIT', {badarg, _}} = (catch family(a)),
- ?line {'EXIT', {badarg, _}} = (catch family([a])),
- ?line {'EXIT', {badarg, _}} = (catch family([{a,b}])),
- ?line {'EXIT', {badarg, _}} = (catch family([{a,[]} | a])),
- ?line {'EXIT', {badarg, _}} = (catch family([{a,[a|b]}])),
- ?line {'EXIT', {bad_function, _}} =
+ eval(family([]), from_term([],[{atom,[atom]}])),
+ {'EXIT', {badarg, _}} = (catch family(a)),
+ {'EXIT', {badarg, _}} = (catch family([a])),
+ {'EXIT', {badarg, _}} = (catch family([{a,b}])),
+ {'EXIT', {badarg, _}} = (catch family([{a,[]} | a])),
+ {'EXIT', {badarg, _}} = (catch family([{a,[a|b]}])),
+ {'EXIT', {bad_function, _}} =
(catch family([{a,[a]},{a,[]}])),
- ?line {'EXIT', {bad_function, _}} =
+ {'EXIT', {bad_function, _}} =
(catch family([{a,[]},{b,[]},{a,[a]}])),
F = 0.0, I = round(F),
if
F == I -> % term ordering
- ?line {'EXIT', {bad_function, _}} =
+ {'EXIT', {bad_function, _}} =
(catch family([{I,[a]},{F,[b]}])),
- ?line true = (1 =:= no_elements(family([{a,[I]},{a,[F]}])));
+ true = (1 =:= no_elements(family([{a,[I]},{a,[F]}])));
true ->
- ?line {'EXIT', {bad_function, _}} =
+ {'EXIT', {bad_function, _}} =
(catch family([{a,[I]},{a,[F]}]))
end,
- ?line eval(family([{a,[]},{b,[b]},{a,[]}]), from_term([{a,[]},{b,[b]}])),
- ?line eval(to_external(family([{b,[{hej,san},tjo]},{a,[]}])),
- [{a,[]},{b,[tjo,{hej,san}]}]),
- ?line eval(family([{a,[a]},{a,[a,a]}]), family([{a,[a]}])),
+ eval(family([{a,[]},{b,[b]},{a,[]}]), from_term([{a,[]},{b,[b]}])),
+ eval(to_external(family([{b,[{hej,san},tjo]},{a,[]}])),
+ [{a,[]},{b,[tjo,{hej,san}]}]),
+ eval(family([{a,[a]},{a,[a,a]}]), family([{a,[a]}])),
%% family/2
FT = [{a,[a]}],
- ?line eval(family([], FT), from_term([],FT)),
- ?line {'EXIT', {badarg, _}} = (catch family(a,FT)),
- ?line {'EXIT', {badarg, _}} = (catch family([a],FT)),
- ?line {'EXIT', {badarg, _}} = (catch family([{a,b}],FT)),
- ?line {'EXIT', {badarg, _}} = (catch family([{a,[]} | a],FT)),
- ?line {'EXIT', {badarg, _}} = (catch family([{a,[a|b]}], FT)),
- ?line {'EXIT', {bad_function, _}} =
+ eval(family([], FT), from_term([],FT)),
+ {'EXIT', {badarg, _}} = (catch family(a,FT)),
+ {'EXIT', {badarg, _}} = (catch family([a],FT)),
+ {'EXIT', {badarg, _}} = (catch family([{a,b}],FT)),
+ {'EXIT', {badarg, _}} = (catch family([{a,[]} | a],FT)),
+ {'EXIT', {badarg, _}} = (catch family([{a,[a|b]}], FT)),
+ {'EXIT', {bad_function, _}} =
(catch family([{a,[a]},{a,[]}], FT)),
- ?line {'EXIT', {bad_function, _}} =
+ {'EXIT', {bad_function, _}} =
(catch family([{a,[]},{b,[]},{a,[a]}], FT)),
- ?line eval(family([{a,[]},{b,[b,b]},{a,[]}], FT),
- from_term([{a,[]},{b,[b]}], FT)),
- ?line eval(to_external(family([{b,[{hej,san},tjo]},{a,[]}], FT)),
- [{a,[]},{b,[tjo,{hej,san}]}]),
-
- ?line eval(family([{{a},[{foo,bar}]}], ['_']),
- from_term([{{a},[{foo,bar}]}], ['_'])),
- ?line eval(family([], ['_']), from_term([], ['_'])),
- ?line {'EXIT', {badarg, _}} = (catch family([[a]],['_'])),
- ?line {'EXIT', {badarg, _}} = (catch family([{a,b}],['_'])),
- ?line {'EXIT', {badarg, _}} =
+ eval(family([{a,[]},{b,[b,b]},{a,[]}], FT),
+ from_term([{a,[]},{b,[b]}], FT)),
+ eval(to_external(family([{b,[{hej,san},tjo]},{a,[]}], FT)),
+ [{a,[]},{b,[tjo,{hej,san}]}]),
+
+ eval(family([{{a},[{foo,bar}]}], ['_']),
+ from_term([{{a},[{foo,bar}]}], ['_'])),
+ eval(family([], ['_']), from_term([], ['_'])),
+ {'EXIT', {badarg, _}} = (catch family([[a]],['_'])),
+ {'EXIT', {badarg, _}} = (catch family([{a,b}],['_'])),
+ {'EXIT', {badarg, _}} =
(catch family([{a,[foo]}], [{atom,atom}])),
- ?line eval(family([{{a},[{foo,bar}]}], [{{dt},[{r1,t2}]}]),
- from_term([{{a},[{foo,bar}]}], [{{dt},[{r1,t2}]}])),
- ?line eval(family([{a,[a]},{a,[a,a]}],[{atom,[atom]}]),
- family([{a,[a]}])),
- ?line eval(family([{[a,b],[a]},{[b,a],[a,a]}],[{[atom],[atom]}]),
- from_term([{[a,b],[a]},{[b,a],[a,a]}])),
+ eval(family([{{a},[{foo,bar}]}], [{{dt},[{r1,t2}]}]),
+ from_term([{{a},[{foo,bar}]}], [{{dt},[{r1,t2}]}])),
+ eval(family([{a,[a]},{a,[a,a]}],[{atom,[atom]}]),
+ family([{a,[a]}])),
+ eval(family([{[a,b],[a]},{[b,a],[a,a]}],[{[atom],[atom]}]),
+ from_term([{[a,b],[a]},{[b,a],[a,a]}])),
ok.
-projection(suite) -> [];
-projection(doc) -> [""];
projection(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([]),
+ E = empty_set(),
+ ER = relation([]),
%% set of ordered sets
- ?line S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
- ?line S2 = relation([{a,1},{a,2},{a,3},{b,4},{b,5},{b,6}]),
-
- ?line eval(projection(1, E), E),
- ?line eval(projection(1, ER), set([])),
- ?line eval(projection(1, relation([{a,1}])), set([a])),
- ?line eval(projection(1, S1), set([a,b,c])),
- ?line eval(projection(1, S2), set([a,b])),
- ?line eval(projection(2, S1), set([0,1,2,22])),
- ?line eval(projection(2, relation([{1,a},{2,a},{3,b}])), set([a,b])),
- ?line eval(projection(1, relation([{a},{b},{c}])), set([a,b,c])),
+ S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
+ S2 = relation([{a,1},{a,2},{a,3},{b,4},{b,5},{b,6}]),
+
+ eval(projection(1, E), E),
+ eval(projection(1, ER), set([])),
+ eval(projection(1, relation([{a,1}])), set([a])),
+ eval(projection(1, S1), set([a,b,c])),
+ eval(projection(1, S2), set([a,b])),
+ eval(projection(2, S1), set([0,1,2,22])),
+ eval(projection(2, relation([{1,a},{2,a},{3,b}])), set([a,b])),
+ eval(projection(1, relation([{a},{b},{c}])), set([a,b,c])),
Fun1 = {external, fun({A,B,C}) -> {A,{B,C}} end},
- ?line eval(projection(Fun1, E), E),
+ eval(projection(Fun1, E), E),
%% No check here:
- ?line eval(projection(3, projection(Fun1, empty_set())), E),
- ?line E2 = relation([], 3),
- ?line eval(projection(Fun1, E2), from_term([], [{atom,{atom,atom}}])),
+ eval(projection(3, projection(Fun1, empty_set())), E),
+ E2 = relation([], 3),
+ eval(projection(Fun1, E2), from_term([], [{atom,{atom,atom}}])),
Fun2 = {external, fun({A,_B}) -> {A} end},
- ?line eval(projection(Fun2, ER), from_term([], [{atom}])),
- ?line eval(projection(Fun2, relation([{a,1}])), relation([{a}])),
- ?line eval(projection(Fun2, relation([{a,1},{b,3},{a,2}])),
- relation([{a},{b}])),
+ eval(projection(Fun2, ER), from_term([], [{atom}])),
+ eval(projection(Fun2, relation([{a,1}])), relation([{a}])),
+ eval(projection(Fun2, relation([{a,1},{b,3},{a,2}])),
+ relation([{a},{b}])),
Fun3 = {external, fun({A,_B,C}) -> {C,{A},C} end},
- ?line eval(projection(Fun3, relation([{a,1,x},{b,3,y},{a,2,z}])),
- from_term([{x,{a},x},{y,{b},y},{z,{a},z}])),
+ eval(projection(Fun3, relation([{a,1,x},{b,3,y},{a,2,z}])),
+ from_term([{x,{a},x},{y,{b},y},{z,{a},z}])),
Fun4 = {external, fun(A={B,_C,_D}) -> {B, A} end},
- ?line eval(projection(Fun4, relation([{a,1,x},{b,3,y},{a,2,z}])),
- from_term([{a,{a,1,x}},{b,{b,3,y}},{a,{a,2,z}}])),
+ eval(projection(Fun4, relation([{a,1,x},{b,3,y},{a,2,z}])),
+ from_term([{a,{a,1,x}},{b,{b,3,y}},{a,{a,2,z}}])),
- ?line eval(projection({external, fun({A,B,_C,D}) -> {A,B,A,D} end},
- relation([{1,1,1,2}, {1,1,3,1}])),
- relation([{1,1,1,1}, {1,1,1,2}])),
+ eval(projection({external, fun({A,B,_C,D}) -> {A,B,A,D} end},
+ relation([{1,1,1,2}, {1,1,3,1}])),
+ relation([{1,1,1,1}, {1,1,1,2}])),
- ?line {'EXIT', {badarg, _}} = (catch projection(1, set([]))),
- ?line {'EXIT', {function_clause, _}} =
+ {'EXIT', {badarg, _}} = (catch projection(1, set([]))),
+ {'EXIT', {function_clause, _}} =
(catch projection({external, fun({A}) -> A end}, S1)),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch projection({external, fun({A,_}) -> {A,0} end},
from_term([{1,a}]))),
%% {} is not an ordered set
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch projection({external, fun(_) -> {} end}, ER)),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch projection({external, fun(_) -> {{}} end}, ER)),
- ?line eval(projection({external, fun({T,_}) -> T end},
- relation([{{},a},{{},b}])),
- set([{}])),
- ?line eval(projection({external, fun({T}) -> T end}, relation([{{}}])),
- set([{}])),
-
- ?line eval(projection({external, fun(A) -> {A} end},
- relation([{1,a},{2,b}])),
- from_term([{{1,a}},{{2,b}}])),
- ?line eval(projection({external, fun({A,B}) -> {B,A} end},
- relation([{1,a},{2,b}])),
- relation([{a,1},{b,2}])),
- ?line eval(projection({external, fun(X=Y=A) -> {X,Y,A} end}, set([a,b,c])),
- relation([{a,a,a},{b,b,b},{c,c,c}])),
-
- ?line eval(projection({external, fun({A,{_},B}) -> {A,B} end},
- from_term([{a,{a},b},{a,{b},c}])),
- relation([{a,b},{a,c}])),
- ?line eval(projection({external, fun({A,_,B}) -> {A,B} end},
- relation([{a,{},b},{a,{},c}])),
- relation([{a,b},{a,c}])),
+ eval(projection({external, fun({T,_}) -> T end},
+ relation([{{},a},{{},b}])),
+ set([{}])),
+ eval(projection({external, fun({T}) -> T end}, relation([{{}}])),
+ set([{}])),
+
+ eval(projection({external, fun(A) -> {A} end},
+ relation([{1,a},{2,b}])),
+ from_term([{{1,a}},{{2,b}}])),
+ eval(projection({external, fun({A,B}) -> {B,A} end},
+ relation([{1,a},{2,b}])),
+ relation([{a,1},{b,2}])),
+ eval(projection({external, fun(X=Y=A) -> {X,Y,A} end}, set([a,b,c])),
+ relation([{a,a,a},{b,b,b},{c,c,c}])),
+
+ eval(projection({external, fun({A,{_},B}) -> {A,B} end},
+ from_term([{a,{a},b},{a,{b},c}])),
+ relation([{a,b},{a,c}])),
+ eval(projection({external, fun({A,_,B}) -> {A,B} end},
+ relation([{a,{},b},{a,{},c}])),
+ relation([{a,b},{a,c}])),
Fun5 = fun(S) -> from_term({to_external(S),0}, {type(S),atom}) end,
- ?line eval(projection(Fun5, E), E),
- ?line eval(projection(Fun5, set([a,b])), from_term([{a,0},{b,0}])),
- ?line eval(projection(Fun5, relation([{a,1},{b,2}])),
- from_term([{{a,1},0},{{b,2},0}])),
- ?line eval(projection(Fun5, from_term([[a],[b]])),
- from_term([{[a],0},{[b],0}])),
+ eval(projection(Fun5, E), E),
+ eval(projection(Fun5, set([a,b])), from_term([{a,0},{b,0}])),
+ eval(projection(Fun5, relation([{a,1},{b,2}])),
+ from_term([{{a,1},0},{{b,2},0}])),
+ eval(projection(Fun5, from_term([[a],[b]])),
+ from_term([{[a],0},{[b],0}])),
F = 0.0, I = round(F),
- ?line FR = relation([{I},{F}]),
+ FR = relation([{I},{F}]),
if
F == I -> % term ordering
true = (no_elements(projection(1, FR)) =:= 1);
@@ -532,382 +517,374 @@ projection(Conf) when is_list(Conf) ->
end,
%% set of sets
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch projection({external, fun(X) -> X end},
from_term([], [[atom]]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch projection({external, fun(X) -> X end}, from_term([[a]]))),
- ?line eval(projection(fun sofs:union/1,
- from_term([[[1,2],[2,3]], [[a,b],[b,c]]])),
- from_term([[1,2,3], [a,b,c]])),
- ?line eval(projection(fun(_) -> from_term([a]) end,
- from_term([[b]], [[a]])),
- from_term([[a]])),
- ?line eval(projection(fun(_) -> from_term([a]) end,
- from_term([[1,2],[3,4]])),
- from_term([[a]])),
+ eval(projection(fun sofs:union/1,
+ from_term([[[1,2],[2,3]], [[a,b],[b,c]]])),
+ from_term([[1,2,3], [a,b,c]])),
+ eval(projection(fun(_) -> from_term([a]) end,
+ from_term([[b]], [[a]])),
+ from_term([[a]])),
+ eval(projection(fun(_) -> from_term([a]) end,
+ from_term([[1,2],[3,4]])),
+ from_term([[a]])),
Fun10 = fun(S) ->
- %% Cheating a lot...
- case to_external(S) of
- [1] -> from_term({1,1});
- _ -> S
- end
- end,
- ?line eval(projection(Fun10, from_term([[1]])), from_term([{1,1}])),
- ?line eval(projection(fun(_) -> from_term({a}) end, from_term([[a]])),
- from_term([{a}])),
- ?line {'EXIT', {badarg, _}} =
+ %% Cheating a lot...
+ case to_external(S) of
+ [1] -> from_term({1,1});
+ _ -> S
+ end
+ end,
+ eval(projection(Fun10, from_term([[1]])), from_term([{1,1}])),
+ eval(projection(fun(_) -> from_term({a}) end, from_term([[a]])),
+ from_term([{a}])),
+ {'EXIT', {badarg, _}} =
(catch projection(fun(_) -> {a} end, from_term([[a]]))),
ok.
-substitution(suite) -> [];
-substitution(doc) -> [""];
substitution(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([]),
+ E = empty_set(),
+ ER = relation([]),
%% set of ordered sets
- ?line S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
- ?line S2 = relation([{a,1},{a,2},{a,3},{b,4},{b,5},{b,6}]),
+ S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
+ S2 = relation([{a,1},{a,2},{a,3},{b,4},{b,5},{b,6}]),
- ?line eval(substitution(1, E), E),
+ eval(substitution(1, E), E),
%% No check here:
Fun0 = {external, fun({A,B,C}) -> {A,{B,C}} end},
- ?line eval(substitution(3, substitution(Fun0, empty_set())), E),
- ?line eval(substitution(1, ER), from_term([],[{{atom,atom},atom}])),
- ?line eval(substitution(1, relation([{a,1}])), from_term([{{a,1},a}])),
- ?line eval(substitution(1, S1),
- from_term([{{a,1},a},{{b,2},b},{{b,22},b},{{c,0},c}])),
- ?line eval(substitution(1, S2),
- from_term([{{a,1},a},{{a,2},a},{{a,3},a},{{b,4},b},
- {{b,5},b},{{b,6},b}])),
- ?line eval(substitution(2, S1),
- from_term([{{a,1},1},{{b,2},2},{{b,22},22},{{c,0},0}])),
-
+ eval(substitution(3, substitution(Fun0, empty_set())), E),
+ eval(substitution(1, ER), from_term([],[{{atom,atom},atom}])),
+ eval(substitution(1, relation([{a,1}])), from_term([{{a,1},a}])),
+ eval(substitution(1, S1),
+ from_term([{{a,1},a},{{b,2},b},{{b,22},b},{{c,0},c}])),
+ eval(substitution(1, S2),
+ from_term([{{a,1},a},{{a,2},a},{{a,3},a},{{b,4},b},
+ {{b,5},b},{{b,6},b}])),
+ eval(substitution(2, S1),
+ from_term([{{a,1},1},{{b,2},2},{{b,22},22},{{c,0},0}])),
+
Fun1 = fun({A,_B}) -> {A} end,
XFun1 = {external, Fun1},
- ?line eval(substitution(XFun1, E), E),
- ?line eval(substitution(Fun1, E), E),
- ?line eval(substitution(XFun1, ER), from_term([], [{{atom,atom},{atom}}])),
- ?line eval(substitution(XFun1, relation([{a,1}])),
- from_term([{{a,1},{a}}])),
- ?line eval(substitution(XFun1, relation([{a,1},{b,3},{a,2}])),
- from_term([{{a,1},{a}},{{a,2},{a}},{{b,3},{b}}])),
- ?line eval(substitution({external, fun({A,_B,C}) -> {C,A,C} end},
- relation([{a,1,x},{b,3,y},{a,2,z}])),
- from_term([{{a,1,x},{x,a,x}},{{a,2,z},{z,a,z}},
- {{b,3,y},{y,b,y}}])),
+ eval(substitution(XFun1, E), E),
+ eval(substitution(Fun1, E), E),
+ eval(substitution(XFun1, ER), from_term([], [{{atom,atom},{atom}}])),
+ eval(substitution(XFun1, relation([{a,1}])),
+ from_term([{{a,1},{a}}])),
+ eval(substitution(XFun1, relation([{a,1},{b,3},{a,2}])),
+ from_term([{{a,1},{a}},{{a,2},{a}},{{b,3},{b}}])),
+ eval(substitution({external, fun({A,_B,C}) -> {C,A,C} end},
+ relation([{a,1,x},{b,3,y},{a,2,z}])),
+ from_term([{{a,1,x},{x,a,x}},{{a,2,z},{z,a,z}},
+ {{b,3,y},{y,b,y}}])),
Fun2 = fun(S) -> {A,_B} = to_external(S), from_term({A}) end,
- ?line eval(substitution(Fun2, ER), E),
- ?line eval(substitution(Fun2, relation([{a,1}])),
- from_term([{{a,1},{a}}])),
+ eval(substitution(Fun2, ER), E),
+ eval(substitution(Fun2, relation([{a,1}])),
+ from_term([{{a,1},{a}}])),
Fun3 = fun(S) -> from_term({to_external(S),0}, {type(S),atom}) end,
- ?line eval(substitution(Fun3, E), E),
- ?line eval(substitution(Fun3, set([a,b])),
- from_term([{a,{a,0}},{b,{b,0}}])),
- ?line eval(substitution(Fun3, relation([{a,1},{b,2}])),
- from_term([{{a,1},{{a,1},0}},{{b,2},{{b,2},0}}])),
- ?line eval(substitution(Fun3, from_term([[a],[b]])),
- from_term([{[a],{[a],0}},{[b],{[b],0}}])),
-
- ?line eval(substitution(fun(_) -> E end, from_term([[a],[b]])),
- from_term([{[a],[]},{[b],[]}])),
-
- ?line {'EXIT', {badarg, _}} = (catch substitution(1, set([]))),
- ?line eval(substitution(1, ER), from_term([], [{{atom,atom},atom}])),
- ?line {'EXIT', {function_clause, _}} =
+ eval(substitution(Fun3, E), E),
+ eval(substitution(Fun3, set([a,b])),
+ from_term([{a,{a,0}},{b,{b,0}}])),
+ eval(substitution(Fun3, relation([{a,1},{b,2}])),
+ from_term([{{a,1},{{a,1},0}},{{b,2},{{b,2},0}}])),
+ eval(substitution(Fun3, from_term([[a],[b]])),
+ from_term([{[a],{[a],0}},{[b],{[b],0}}])),
+
+ eval(substitution(fun(_) -> E end, from_term([[a],[b]])),
+ from_term([{[a],[]},{[b],[]}])),
+
+ {'EXIT', {badarg, _}} = (catch substitution(1, set([]))),
+ eval(substitution(1, ER), from_term([], [{{atom,atom},atom}])),
+ {'EXIT', {function_clause, _}} =
(catch substitution({external, fun({A,_}) -> A end}, set([]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch substitution({external, fun({A,_}) -> {A,0} end},
from_term([{1,a}]))),
%% set of sets
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch substitution({external, fun(X) -> X end},
from_term([], [[atom]]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch substitution({external, fun(X) -> X end}, from_term([[a]]))),
- ?line eval(substitution(fun(X) -> X end, from_term([], [[atom]])), E),
- ?line eval(substitution(fun sofs:union/1,
- from_term([[[1,2],[2,3]], [[a,b],[b,c]]])),
- from_term([{[[1,2],[2,3]],[1,2,3]}, {[[a,b],[b,c]],[a,b,c]}])),
- ?line eval(substitution(fun(_) -> from_term([a]) end,
- from_term([[b]], [[a]])),
- from_term([{[b],[a]}], [{[a],[atom]}])),
- ?line eval(substitution(fun(_) -> from_term([a]) end,
- from_term([[1,2],[3,4]])),
- from_term([{[1,2],[a]},{[3,4],[a]}])),
+ eval(substitution(fun(X) -> X end, from_term([], [[atom]])), E),
+ eval(substitution(fun sofs:union/1,
+ from_term([[[1,2],[2,3]], [[a,b],[b,c]]])),
+ from_term([{[[1,2],[2,3]],[1,2,3]}, {[[a,b],[b,c]],[a,b,c]}])),
+ eval(substitution(fun(_) -> from_term([a]) end,
+ from_term([[b]], [[a]])),
+ from_term([{[b],[a]}], [{[a],[atom]}])),
+ eval(substitution(fun(_) -> from_term([a]) end,
+ from_term([[1,2],[3,4]])),
+ from_term([{[1,2],[a]},{[3,4],[a]}])),
Fun10 = fun(S) ->
- %% Cheating a lot...
- case to_external(S) of
- [1] -> from_term({1,1});
- _ -> S
- end
- end,
- ?line eval(substitution(Fun10, from_term([[1]])),
- from_term([{[1],{1,1}}])),
- ?line {'EXIT', {type_mismatch, _}} =
+ %% Cheating a lot...
+ case to_external(S) of
+ [1] -> from_term({1,1});
+ _ -> S
+ end
+ end,
+ eval(substitution(Fun10, from_term([[1]])),
+ from_term([{[1],{1,1}}])),
+ {'EXIT', {type_mismatch, _}} =
(catch substitution(Fun10, from_term([[1],[2]]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch substitution(Fun10, from_term([[1],[0]]))),
- ?line eval(substitution(fun(_) -> from_term({a}) end, from_term([[a]])),
- from_term([{[a],{a}}])),
- ?line {'EXIT', {badarg, _}} =
+ eval(substitution(fun(_) -> from_term({a}) end, from_term([[a]])),
+ from_term([{[a],{a}}])),
+ {'EXIT', {badarg, _}} =
(catch substitution(fun(_) -> {a} end, from_term([[a]]))),
ok.
-restriction(suite) -> [];
-restriction(doc) -> [""];
restriction(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([], 2),
+ E = empty_set(),
+ ER = relation([], 2),
%% set of ordered sets
- ?line S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
- ?line eval(restriction(S1, set([a,b])),
- relation([{a,1},{b,2},{b,22}])),
- ?line eval(restriction(2, S1, set([1,2])),
- relation([{a,1},{b,2}])),
- ?line eval(restriction(S1, set([a,b,c])), S1),
- ?line eval(restriction(1, S1, set([0,1,d,e])), ER),
- ?line eval(restriction(1, S1, E), ER),
- ?line eval(restriction({external, fun({_A,B,C}) -> {B,C} end},
- relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
- relation([{bb,2},{cc,3}])),
- relation([{b,bb,2},{c,cc,3}])),
+ S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
+ eval(restriction(S1, set([a,b])),
+ relation([{a,1},{b,2},{b,22}])),
+ eval(restriction(2, S1, set([1,2])),
+ relation([{a,1},{b,2}])),
+ eval(restriction(S1, set([a,b,c])), S1),
+ eval(restriction(1, S1, set([0,1,d,e])), ER),
+ eval(restriction(1, S1, E), ER),
+ eval(restriction({external, fun({_A,B,C}) -> {B,C} end},
+ relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
+ relation([{bb,2},{cc,3}])),
+ relation([{b,bb,2},{c,cc,3}])),
R1 = relation([],[{a,b}]),
- ?line eval(restriction(2, R1,sofs:set([],[b])), R1),
+ eval(restriction(2, R1,sofs:set([],[b])), R1),
Id = fun(X) -> X end,
XId = {external, Id},
- ?line eval(restriction(XId, relation([{a,b}]), E), ER),
- ?line eval(restriction(XId, E, relation([{b,d}])), E),
+ eval(restriction(XId, relation([{a,b}]), E), ER),
+ eval(restriction(XId, E, relation([{b,d}])), E),
Fun1 = fun(S) -> {_A,B,C} = to_external(S), from_term({B,C}) end,
- ?line eval(restriction(Fun1,
- relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
- relation([{bb,2},{cc,3}])),
- relation([{b,bb,2},{c,cc,3}])),
- ?line eval(restriction({external, fun({_,{A},B}) -> {A,B} end},
- from_term([{a,{aa},1},{b,{bb},2},{c,{cc},3}]),
- from_term([{bb,2},{cc,3}])),
- from_term([{b,{bb},2},{c,{cc},3}])),
+ eval(restriction(Fun1,
+ relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
+ relation([{bb,2},{cc,3}])),
+ relation([{b,bb,2},{c,cc,3}])),
+ eval(restriction({external, fun({_,{A},B}) -> {A,B} end},
+ from_term([{a,{aa},1},{b,{bb},2},{c,{cc},3}]),
+ from_term([{bb,2},{cc,3}])),
+ from_term([{b,{bb},2},{c,{cc},3}])),
S5 = relation([{1,a},{2,b},{3,c}]),
- ?line eval(restriction(2, S5, set([b,c])), relation([{2,b},{3,c}])),
+ eval(restriction(2, S5, set([b,c])), relation([{2,b},{3,c}])),
S4 = relation([{a,1},{b,2},{b,27},{c,0}]),
- ?line eval(restriction(2, S4, E), ER),
+ eval(restriction(2, S4, E), ER),
S6 = relation([{1,a},{2,c},{3,b}]),
- ?line eval(restriction(2, S6, set([d,e])), ER),
- ?line eval(restriction(2,
- relation([{1,d},{2,c},{3,b},{4,a},{5,e}]),
- set([c])),
- relation([{2,c}])),
- ?line eval(restriction(XId,
- relation([{1,a},{3,b},{4,c},{4,d}]),
- relation([{2,a},{2,c},{4,c}])),
- relation([{4,c}])),
- ?line eval(restriction(2, relation([{a,b}]), E), ER),
- ?line eval(restriction(2, E, relation([{b,d}])), E),
- ?line eval(restriction(2, relation([{b,d}]), E), ER),
- ?line eval(restriction(XId, E, set([a])), E),
- ?line eval(restriction(1, S1, E), ER),
- ?line {'EXIT', {badarg, _}} =
+ eval(restriction(2, S6, set([d,e])), ER),
+ eval(restriction(2,
+ relation([{1,d},{2,c},{3,b},{4,a},{5,e}]),
+ set([c])),
+ relation([{2,c}])),
+ eval(restriction(XId,
+ relation([{1,a},{3,b},{4,c},{4,d}]),
+ relation([{2,a},{2,c},{4,c}])),
+ relation([{4,c}])),
+ eval(restriction(2, relation([{a,b}]), E), ER),
+ eval(restriction(2, E, relation([{b,d}])), E),
+ eval(restriction(2, relation([{b,d}]), E), ER),
+ eval(restriction(XId, E, set([a])), E),
+ eval(restriction(1, S1, E), ER),
+ {'EXIT', {badarg, _}} =
(catch restriction(3, relation([{a,b}]), E)),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch restriction(3, relation([{a,b}]), relation([{b,d}]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch restriction(3, relation([{a,b}]), set([{b,d}]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch restriction(2, relation([{a,b}]), relation([{b,d}]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch restriction({external, fun({A,_B}) -> A end},
relation([{a,b}]), relation([{b,d}]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch restriction({external, fun({A,_}) -> {A,0} end},
from_term([{1,a}]),
from_term([{1,0}]))),
- ?line eval(restriction(2, relation([{a,d},{b,e},{c,b},{d,c}]), set([b,d])),
- relation([{a,d},{c,b}])),
- ?line {'EXIT', {function_clause, _}} =
+ eval(restriction(2, relation([{a,d},{b,e},{c,b},{d,c}]), set([b,d])),
+ relation([{a,d},{c,b}])),
+ {'EXIT', {function_clause, _}} =
(catch restriction({external, fun({A,_B}) -> A end}, set([]), E)),
Fun3 = fun(S) -> from_term({to_external(S),0}, {type(S),atom}) end,
- ?line eval(restriction(Fun3, set([1,2]), from_term([{1,0}])),
- from_term([1])),
+ eval(restriction(Fun3, set([1,2]), from_term([{1,0}])),
+ from_term([1])),
%% set of sets
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch restriction({external, fun(X) -> X end},
from_term([], [[atom]]), set([a]))),
S2 = from_term([], [[atom]]),
- ?line eval(restriction(Id, S2, E), E),
+ eval(restriction(Id, S2, E), E),
S3 = from_term([[a],[b]], [[atom]]),
- ?line eval(restriction(Id, S3, E), E),
- ?line eval(restriction(Id, from_term([], [[atom]]), set([a])),
- from_term([], [[atom]])),
- ?line eval(restriction(fun sofs:union/1,
- from_term([[[a],[b]], [[b],[c]],
- [[], [a,b]], [[1],[2]]]),
- from_term([[a,b],[1,2,3],[b,c]])),
- from_term([[[],[a,b]], [[a],[b]],[[b],[c]]])),
- ?line eval(restriction(fun(_) -> from_term([a]) end,
- from_term([], [[atom]]),
- from_term([], [[a]])),
- from_term([], [[atom]])),
- ?line {'EXIT', {type_mismatch, _}} =
+ eval(restriction(Id, S3, E), E),
+ eval(restriction(Id, from_term([], [[atom]]), set([a])),
+ from_term([], [[atom]])),
+ eval(restriction(fun sofs:union/1,
+ from_term([[[a],[b]], [[b],[c]],
+ [[], [a,b]], [[1],[2]]]),
+ from_term([[a,b],[1,2,3],[b,c]])),
+ from_term([[[],[a,b]], [[a],[b]],[[b],[c]]])),
+ eval(restriction(fun(_) -> from_term([a]) end,
+ from_term([], [[atom]]),
+ from_term([], [[a]])),
+ from_term([], [[atom]])),
+ {'EXIT', {type_mismatch, _}} =
(catch restriction(fun(_) -> from_term([a]) end,
from_term([[1,2],[3,4]]),
from_term([], [atom]))),
Fun10 = fun(S) ->
- %% Cheating a lot...
- case to_external(S) of
- [1] -> from_term({1,1});
- _ -> S
- end
- end,
- ?line {'EXIT', {type_mismatch, _}} =
+ %% Cheating a lot...
+ case to_external(S) of
+ [1] -> from_term({1,1});
+ _ -> S
+ end
+ end,
+ {'EXIT', {type_mismatch, _}} =
(catch restriction(Fun10, from_term([[1]]), from_term([], [[atom]]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch restriction(fun(_) -> from_term({a}) end,
from_term([[a]]),
from_term([], [atom]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch restriction(fun(_) -> {a} end,
from_term([[a]]),
from_term([], [atom]))),
ok.
-drestriction(suite) -> [];
-drestriction(doc) -> [""];
drestriction(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([], 2),
+ E = empty_set(),
+ ER = relation([], 2),
%% set of ordered sets
- ?line S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
- ?line eval(drestriction(S1, set([a,b])), relation([{c,0}])),
- ?line eval(drestriction(2, S1, set([1,2])),
- relation([{b,22},{c,0}])),
- ?line eval(drestriction(S1, set([a,b,c])), ER),
- ?line eval(drestriction(2, ER, set([a,b])), ER),
- ?line eval(drestriction(1, S1, set([0,1,d,e])), S1),
- ?line eval(drestriction(1, S1, E), S1),
- ?line eval(drestriction({external, fun({_A,B,C}) -> {B,C} end},
- relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
- relation([{bb,2},{cc,3}])),
- relation([{a,aa,1}])),
+ S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
+ eval(drestriction(S1, set([a,b])), relation([{c,0}])),
+ eval(drestriction(2, S1, set([1,2])),
+ relation([{b,22},{c,0}])),
+ eval(drestriction(S1, set([a,b,c])), ER),
+ eval(drestriction(2, ER, set([a,b])), ER),
+ eval(drestriction(1, S1, set([0,1,d,e])), S1),
+ eval(drestriction(1, S1, E), S1),
+ eval(drestriction({external, fun({_A,B,C}) -> {B,C} end},
+ relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
+ relation([{bb,2},{cc,3}])),
+ relation([{a,aa,1}])),
Id = fun(X) -> X end,
XId = {external, Id},
- ?line eval(drestriction(XId, relation([{a,b}]), E), relation([{a,b}])),
- ?line eval(drestriction(XId, E, relation([{b,d}])), E),
+ eval(drestriction(XId, relation([{a,b}]), E), relation([{a,b}])),
+ eval(drestriction(XId, E, relation([{b,d}])), E),
Fun1 = fun(S) -> {_A,B,C} = to_external(S), from_term({B,C}) end,
- ?line eval(drestriction(Fun1,
- relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
- relation([{bb,2},{cc,3}])),
- relation([{a,aa,1}])),
- ?line eval(drestriction({external, fun({_,{A},B}) -> {A,B} end},
- from_term([{a,{aa},1},{b,{bb},2},{c,{cc},3}]),
- from_term([{bb,2},{cc,3}])),
- from_term([{a,{aa},1}])),
+ eval(drestriction(Fun1,
+ relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
+ relation([{bb,2},{cc,3}])),
+ relation([{a,aa,1}])),
+ eval(drestriction({external, fun({_,{A},B}) -> {A,B} end},
+ from_term([{a,{aa},1},{b,{bb},2},{c,{cc},3}]),
+ from_term([{bb,2},{cc,3}])),
+ from_term([{a,{aa},1}])),
S5 = relation([{1,a},{2,b},{3,c}]),
- ?line eval(drestriction(2, S5, set([b,c])), relation([{1,a}])),
+ eval(drestriction(2, S5, set([b,c])), relation([{1,a}])),
S4 = relation([{a,1},{b,2},{b,27},{c,0}]),
- ?line eval(drestriction(2, S4, set([])), S4),
+ eval(drestriction(2, S4, set([])), S4),
S6 = relation([{1,a},{2,c},{3,b}]),
- ?line eval(drestriction(2, S6, set([d,e])), S6),
- ?line eval(drestriction(2,
- relation([{1,d},{2,c},{3,b},{4,a},{5,e}]),
- set([c])),
- relation([{1,d},{3,b},{4,a},{5,e}])),
- ?line eval(drestriction(XId,
- relation([{1,a},{3,b},{4,c},{4,d}]),
- relation([{2,a},{2,c},{4,c}])),
- relation([{1,a},{3,b},{4,d}])),
- ?line eval(drestriction(2, relation([{a,b}]), E), relation([{a,b}])),
- ?line eval(drestriction(2, E, relation([{b,d}])), E),
- ?line eval(drestriction(2, relation([{b,d}]), E), relation([{b,d}])),
- ?line eval(drestriction(XId, E, set([a])), E),
- ?line eval(drestriction(1, S1, E), S1),
- ?line {'EXIT', {badarg, _}} =
+ eval(drestriction(2, S6, set([d,e])), S6),
+ eval(drestriction(2,
+ relation([{1,d},{2,c},{3,b},{4,a},{5,e}]),
+ set([c])),
+ relation([{1,d},{3,b},{4,a},{5,e}])),
+ eval(drestriction(XId,
+ relation([{1,a},{3,b},{4,c},{4,d}]),
+ relation([{2,a},{2,c},{4,c}])),
+ relation([{1,a},{3,b},{4,d}])),
+ eval(drestriction(2, relation([{a,b}]), E), relation([{a,b}])),
+ eval(drestriction(2, E, relation([{b,d}])), E),
+ eval(drestriction(2, relation([{b,d}]), E), relation([{b,d}])),
+ eval(drestriction(XId, E, set([a])), E),
+ eval(drestriction(1, S1, E), S1),
+ {'EXIT', {badarg, _}} =
(catch drestriction(3, relation([{a,b}]), E)),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch drestriction(3, relation([{a,b}]), relation([{b,d}]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch drestriction(3, relation([{a,b}]), set([{b,d}]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch drestriction(2, relation([{a,b}]), relation([{b,d}]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch drestriction({external, fun({A,_B}) -> A end},
relation([{a,b}]), relation([{b,d}]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch drestriction({external, fun({A,_}) -> {A,0} end},
from_term([{1,a}]),
from_term([{1,0}]))),
- ?line eval(drestriction(2, relation([{a,d},{b,e},{c,b},{d,c}]), set([b,d])),
- relation([{b,e},{d,c}])),
- ?line {'EXIT', {function_clause, _}} =
+ eval(drestriction(2, relation([{a,d},{b,e},{c,b},{d,c}]), set([b,d])),
+ relation([{b,e},{d,c}])),
+ {'EXIT', {function_clause, _}} =
(catch drestriction({external, fun({A,_B}) -> A end}, set([]), E)),
Fun3 = fun(S) -> from_term({to_external(S),0}, {type(S),atom}) end,
- ?line eval(drestriction(Fun3, set([1,2]), from_term([{1,0}])),
- from_term([2])),
+ eval(drestriction(Fun3, set([1,2]), from_term([{1,0}])),
+ from_term([2])),
%% set of sets
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch drestriction({external, fun(X) -> X end},
from_term([], [[atom]]), set([a]))),
S2 = from_term([], [[atom]]),
- ?line eval(drestriction(Id, S2, E), S2),
+ eval(drestriction(Id, S2, E), S2),
S3 = from_term([[a],[b]], [[atom]]),
- ?line eval(drestriction(Id, S3, E), S3),
- ?line eval(drestriction(Id, from_term([], [[atom]]), set([a])),
- from_term([], [[atom]])),
- ?line eval(drestriction(fun sofs:union/1,
- from_term([[[a],[b]], [[b],[c]],
- [[], [a,b]], [[1],[2]]]),
- from_term([[a,b],[1,2,3],[b,c]])),
- from_term([[[1],[2]]])),
- ?line eval(drestriction(fun(_) -> from_term([a]) end,
- from_term([], [[atom]]),
- from_term([], [[a]])),
- from_term([], [[atom]])),
- ?line {'EXIT', {type_mismatch, _}} =
+ eval(drestriction(Id, S3, E), S3),
+ eval(drestriction(Id, from_term([], [[atom]]), set([a])),
+ from_term([], [[atom]])),
+ eval(drestriction(fun sofs:union/1,
+ from_term([[[a],[b]], [[b],[c]],
+ [[], [a,b]], [[1],[2]]]),
+ from_term([[a,b],[1,2,3],[b,c]])),
+ from_term([[[1],[2]]])),
+ eval(drestriction(fun(_) -> from_term([a]) end,
+ from_term([], [[atom]]),
+ from_term([], [[a]])),
+ from_term([], [[atom]])),
+ {'EXIT', {type_mismatch, _}} =
(catch drestriction(fun(_) -> from_term([a]) end,
from_term([[1,2],[3,4]]),
from_term([], [atom]))),
Fun10 = fun(S) ->
- %% Cheating a lot...
- case to_external(S) of
- [1] -> from_term({1,1});
- _ -> S
- end
- end,
- ?line {'EXIT', {type_mismatch, _}} =
+ %% Cheating a lot...
+ case to_external(S) of
+ [1] -> from_term({1,1});
+ _ -> S
+ end
+ end,
+ {'EXIT', {type_mismatch, _}} =
(catch drestriction(Fun10, from_term([[1]]), from_term([], [[atom]]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch drestriction(fun(_) -> from_term({a}) end,
from_term([[a]]),
from_term([], [atom]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch drestriction(fun(_) -> {a} end,
from_term([[a]]),
from_term([], [atom]))),
ok.
-strict_relation_1(suite) -> [];
-strict_relation_1(doc) -> [""];
strict_relation_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([], 2),
- ?line eval(strict_relation(E), E),
- ?line eval(strict_relation(ER), ER),
- ?line eval(strict_relation(relation([{1,a},{a,a},{2,b}])),
- relation([{1,a},{2,b}])),
- ?line {'EXIT', {badarg, _}} =
+ E = empty_set(),
+ ER = relation([], 2),
+ eval(strict_relation(E), E),
+ eval(strict_relation(ER), ER),
+ eval(strict_relation(relation([{1,a},{a,a},{2,b}])),
+ relation([{1,a},{2,b}])),
+ {'EXIT', {badarg, _}} =
(catch strict_relation(relation([{1,2,3}]))),
F = 0.0, I = round(F),
- ?line FR = relation([{F,I}]),
+ FR = relation([{F,I}]),
if
F == I -> % term ordering
eval(strict_relation(FR), ER);
@@ -916,362 +893,334 @@ strict_relation_1(Conf) when is_list(Conf) ->
end,
ok.
-extension(suite) -> [];
-extension(doc) -> [""];
extension(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([], 2),
- ?line EF = family([]),
- ?line C1 = from_term(3),
- ?line C2 = from_term([3]),
- ?line {'EXIT', {function_clause, _}} = (catch extension(foo, E, C1)),
- ?line {'EXIT', {function_clause, _}} = (catch extension(ER, foo, C1)),
- ?line {'EXIT', {{case_clause, _},_}} = (catch extension(ER, E, foo)),
- ?line {'EXIT', {type_mismatch, _}} = (catch extension(ER, E, E)),
- ?line {'EXIT', {badarg, _}} = (catch extension(C2, E, E)),
- ?line eval(E, extension(E, E, E)),
- ?line eval(EF, extension(EF, E, E)),
- ?line eval(family([{3,[]}]), extension(EF, set([3]), E)),
- ?line eval(ER, extension(ER, E, C1)),
- ?line eval(E, extension(E, ER, E)),
- ?line eval(from_term([],[{{atom,atom},type(ER)}]), extension(E, ER, ER)),
-
- ?line R1 = relation([{c,7},{c,9},{c,11},{d,17},{f,20}]),
- ?line S1 = set([a,c,d,e]),
- ?line eval(extension(R1, S1, C1), lextension(R1, S1, C1)),
-
- ?line S2 = set([1,2,3]),
- ?line eval(extension(ER, S2, C1), lextension(ER, S2, C1)),
-
- ?line R3 = relation([{4,a},{8,b}]),
- ?line S3 = set([1,2,3,4,5,6,7,8,9,10,11]),
- ?line eval(extension(R3, S3, C1), lextension(R3, S3, C1)),
-
- ?line R4 = relation([{2,b},{4,d},{6,f}]),
- ?line S4 = set([1,3,5,7]),
- ?line eval(extension(R4, S4, C1), lextension(R4, S4, C1)),
-
- ?line F1 = family([{a,[1]},{c,[2]}]),
- ?line S5 = set([a,b,c,d]),
- ?line eval(extension(F1, S5, C2), lextension(F1, S5, C2)),
+ E = empty_set(),
+ ER = relation([], 2),
+ EF = family([]),
+ C1 = from_term(3),
+ C2 = from_term([3]),
+ {'EXIT', {function_clause, _}} = (catch extension(foo, E, C1)),
+ {'EXIT', {function_clause, _}} = (catch extension(ER, foo, C1)),
+ {'EXIT', {{case_clause, _},_}} = (catch extension(ER, E, foo)),
+ {'EXIT', {type_mismatch, _}} = (catch extension(ER, E, E)),
+ {'EXIT', {badarg, _}} = (catch extension(C2, E, E)),
+ eval(E, extension(E, E, E)),
+ eval(EF, extension(EF, E, E)),
+ eval(family([{3,[]}]), extension(EF, set([3]), E)),
+ eval(ER, extension(ER, E, C1)),
+ eval(E, extension(E, ER, E)),
+ eval(from_term([],[{{atom,atom},type(ER)}]), extension(E, ER, ER)),
+
+ R1 = relation([{c,7},{c,9},{c,11},{d,17},{f,20}]),
+ S1 = set([a,c,d,e]),
+ eval(extension(R1, S1, C1), lextension(R1, S1, C1)),
+
+ S2 = set([1,2,3]),
+ eval(extension(ER, S2, C1), lextension(ER, S2, C1)),
+
+ R3 = relation([{4,a},{8,b}]),
+ S3 = set([1,2,3,4,5,6,7,8,9,10,11]),
+ eval(extension(R3, S3, C1), lextension(R3, S3, C1)),
+
+ R4 = relation([{2,b},{4,d},{6,f}]),
+ S4 = set([1,3,5,7]),
+ eval(extension(R4, S4, C1), lextension(R4, S4, C1)),
+
+ F1 = family([{a,[1]},{c,[2]}]),
+ S5 = set([a,b,c,d]),
+ eval(extension(F1, S5, C2), lextension(F1, S5, C2)),
ok.
lextension(R, S, C) ->
union(R, drestriction(1, constant_function(S, C), domain(R))).
-weak_relation_1(suite) -> [];
-weak_relation_1(doc) -> [""];
weak_relation_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([], 2),
- ?line eval(weak_relation(E), E),
- ?line eval(weak_relation(ER), ER),
- ?line eval(weak_relation(relation([{a,1},{a,2},{b,2},{c,c}])),
- relation([{1,1},{2,2},{a,1},{a,2},{a,a},{b,2},{b,b},{c,c}])),
- ?line eval(weak_relation(relation([{a,1},{a,a},{a,b}])),
- relation([{1,1},{a,1},{a,a},{a,b},{b,b}])),
- ?line eval(weak_relation(relation([{a,1},{a,b},{7,w}])),
- relation([{1,1},{7,7},{7,w},{a,1},{a,a},{a,b},{b,b},{w,w}])),
- ?line {'EXIT', {badarg, _}} =
+ E = empty_set(),
+ ER = relation([], 2),
+ eval(weak_relation(E), E),
+ eval(weak_relation(ER), ER),
+ eval(weak_relation(relation([{a,1},{a,2},{b,2},{c,c}])),
+ relation([{1,1},{2,2},{a,1},{a,2},{a,a},{b,2},{b,b},{c,c}])),
+ eval(weak_relation(relation([{a,1},{a,a},{a,b}])),
+ relation([{1,1},{a,1},{a,a},{a,b},{b,b}])),
+ eval(weak_relation(relation([{a,1},{a,b},{7,w}])),
+ relation([{1,1},{7,7},{7,w},{a,1},{a,a},{a,b},{b,b},{w,w}])),
+ {'EXIT', {badarg, _}} =
(catch weak_relation(from_term([{{a},a}]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch weak_relation(from_term([{a,a}],[{d,r}]))),
- ?line {'EXIT', {badarg, _}} = (catch weak_relation(relation([{1,2,3}]))),
+ {'EXIT', {badarg, _}} = (catch weak_relation(relation([{1,2,3}]))),
F = 0.0, I = round(F),
if
F == I -> % term ordering
- ?line FR1 = relation([{F,I}]),
+ FR1 = relation([{F,I}]),
eval(weak_relation(FR1), FR1),
- ?line FR2 = relation([{F,2},{I,1}]),
+ FR2 = relation([{F,2},{I,1}]),
true = no_elements(weak_relation(FR2)) =:= 5,
- ?line FR3 = relation([{1,0},{1.0,1}]),
+ FR3 = relation([{1,0},{1.0,1}]),
true = no_elements(weak_relation(FR3)) =:= 3;
true ->
ok
end,
ok.
-to_sets_1(suite) -> [];
-to_sets_1(doc) -> [""];
to_sets_1(Conf) when is_list(Conf) ->
- ?line {'EXIT', {badarg, _}} = (catch to_sets(from_term(a))),
- ?line {'EXIT', {function_clause, _}} = (catch to_sets(a)),
+ {'EXIT', {badarg, _}} = (catch to_sets(from_term(a))),
+ {'EXIT', {function_clause, _}} = (catch to_sets(a)),
%% unordered
- ?line [] = to_sets(empty_set()),
- ?line eval(to_sets(from_term([a])), [from_term(a)]),
- ?line eval(to_sets(from_term([[]],[[atom]])), [set([])]),
+ [] = to_sets(empty_set()),
+ eval(to_sets(from_term([a])), [from_term(a)]),
+ eval(to_sets(from_term([[]],[[atom]])), [set([])]),
- ?line L = [from_term([a,b]),from_term([c,d])],
- ?line eval(to_sets(from_sets(L)), L),
+ L = [from_term([a,b]),from_term([c,d])],
+ eval(to_sets(from_sets(L)), L),
- ?line eval(to_sets(relation([{a,1},{b,2}])),
- [from_term({a,1},{atom,atom}), from_term({b,2},{atom,atom})]),
+ eval(to_sets(relation([{a,1},{b,2}])),
+ [from_term({a,1},{atom,atom}), from_term({b,2},{atom,atom})]),
%% ordered
- ?line O = {from_term(a,atom), from_term({b}, {atom}), set([c,d])},
- ?line eval(to_sets(from_sets(O)), O),
+ O = {from_term(a,atom), from_term({b}, {atom}), set([c,d])},
+ eval(to_sets(from_sets(O)), O),
ok.
-specification(suite) -> [];
-specification(doc) -> [""];
specification(Conf) when is_list(Conf) ->
Fun = {external, fun(I) when is_integer(I) -> true; (_) -> false end},
- ?line [1,2,3] = to_external(specification(Fun, set([a,1,b,2,c,3]))),
+ [1,2,3] = to_external(specification(Fun, set([a,1,b,2,c,3]))),
Fun2 = fun(S) -> is_subset(S, set([1,3,5,7,9])) end,
S2 = from_term([[1],[2],[3],[4],[5],[6],[7]]),
- ?line eval(specification(Fun2, S2), from_term([[1],[3],[5],[7]])),
+ eval(specification(Fun2, S2), from_term([[1],[3],[5],[7]])),
Fun2x = fun([1]) -> true;
([3]) -> true;
(_) -> false
end,
- ?line eval(specification({external,Fun2x}, S2), from_term([[1],[3]])),
+ eval(specification({external,Fun2x}, S2), from_term([[1],[3]])),
Fun3 = fun(_) -> neither_true_nor_false end,
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch specification(Fun3, set([a]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch specification({external, Fun3}, set([a]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch specification(Fun3, from_term([[a]]))),
- ?line {'EXIT', {function_clause, _}} =
+ {'EXIT', {function_clause, _}} =
(catch specification(Fun, a)),
ok.
-union_1(suite) -> [];
-union_1(doc) -> [""];
union_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([], 2),
- ?line {'EXIT', {badarg, _}} = (catch union(ER)),
- ?line {'EXIT', {type_mismatch, _}} =
+ E = empty_set(),
+ ER = relation([], 2),
+ {'EXIT', {badarg, _}} = (catch union(ER)),
+ {'EXIT', {type_mismatch, _}} =
(catch union(relation([{a,b}]), relation([{a,b,c}]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch union(from_term([{a,b}]), from_term([{c,[x]}]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch union(from_term([{a,b}]), from_term([{c,d}], [{d,r}]))),
- ?line {'EXIT', {badarg, _}} = (catch union(set([a,b,c]))),
- ?line eval(union(E), E),
- ?line eval(union(from_term([[]],[[atom]])), set([])),
- ?line eval(union(from_term([[{a,b},{b,c}],[{b,c}]])),
- relation([{a,b},{b,c}])),
- ?line eval(union(from_term([[1,2,3],[2,3,4],[3,4,5]])),
- set([1,2,3,4,5])),
-
- ?line eval(union(from_term([{[a],[],c}]), from_term([{[],[],q}])),
- from_term([{[a],[],c},{[],[],q}])),
-
- ?line eval(union(E, E), E),
- ?line eval(union(set([a,b]), E), set([a,b])),
- ?line eval(union(E, set([a,b])), set([a,b])),
-
- ?line eval(union(from_term([[a,b]])), from_term([a,b])),
+ {'EXIT', {badarg, _}} = (catch union(set([a,b,c]))),
+ eval(union(E), E),
+ eval(union(from_term([[]],[[atom]])), set([])),
+ eval(union(from_term([[{a,b},{b,c}],[{b,c}]])),
+ relation([{a,b},{b,c}])),
+ eval(union(from_term([[1,2,3],[2,3,4],[3,4,5]])),
+ set([1,2,3,4,5])),
+
+ eval(union(from_term([{[a],[],c}]), from_term([{[],[],q}])),
+ from_term([{[a],[],c},{[],[],q}])),
+
+ eval(union(E, E), E),
+ eval(union(set([a,b]), E), set([a,b])),
+ eval(union(E, set([a,b])), set([a,b])),
+
+ eval(union(from_term([[a,b]])), from_term([a,b])),
ok.
-intersection_1(suite) -> [];
-intersection_1(doc) -> [""];
intersection_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line {'EXIT', {badarg, _}} = (catch intersection(from_term([a,b]))),
- ?line {'EXIT', {badarg, _}} = (catch intersection(E)),
- ?line {'EXIT', {type_mismatch, _}} =
+ E = empty_set(),
+ {'EXIT', {badarg, _}} = (catch intersection(from_term([a,b]))),
+ {'EXIT', {badarg, _}} = (catch intersection(E)),
+ {'EXIT', {type_mismatch, _}} =
(catch intersection(relation([{a,b}]), relation([{a,b,c}]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch intersection(relation([{a,b}]), from_term([{a,b}],[{d,r}]))),
- ?line eval(intersection(from_term([[a,b,c],[d,e,f],[g,h,i]])), set([])),
-
- ?line eval(intersection(E, E), E),
- ?line eval(intersection(set([a,b,c]),set([0,b,q])),
- set([b])),
- ?line eval(intersection(set([0,b,q]),set([a,b,c])),
- set([b])),
- ?line eval(intersection(set([a,b,c]),set([a,b,c])),
- set([a,b,c])),
- ?line eval(intersection(set([a,b,d]),set([c,d])),
- set([d])),
+ eval(intersection(from_term([[a,b,c],[d,e,f],[g,h,i]])), set([])),
+
+ eval(intersection(E, E), E),
+ eval(intersection(set([a,b,c]),set([0,b,q])),
+ set([b])),
+ eval(intersection(set([0,b,q]),set([a,b,c])),
+ set([b])),
+ eval(intersection(set([a,b,c]),set([a,b,c])),
+ set([a,b,c])),
+ eval(intersection(set([a,b,d]),set([c,d])),
+ set([d])),
ok.
-difference(suite) -> [];
-difference(doc) -> [""];
difference(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line {'EXIT', {type_mismatch, _}} =
+ E = empty_set(),
+ {'EXIT', {type_mismatch, _}} =
(catch difference(relation([{a,b}]), relation([{a,b,c}]))),
- ?line eval(difference(E, E), E),
- ?line {'EXIT', {type_mismatch, _}} =
+ eval(difference(E, E), E),
+ {'EXIT', {type_mismatch, _}} =
(catch difference(relation([{a,b}]), from_term([{a,c}],[{d,r}]))),
- ?line eval(difference(set([a,b,c,d,f]), set([a,d,e,g])),
- set([b,c,f])),
- ?line eval(difference(set([a,b,c]), set([d,e,f])),
- set([a,b,c])),
- ?line eval(difference(set([a,b,c]), set([a,b,c,d,e,f])),
- set([])),
- ?line eval(difference(set([e,f,g]), set([a,b,c,e])),
- set([f,g])),
- ?line eval(difference(set([a,b,d,e,f]), set([c])),
- set([a,b,d,e,f])),
+ eval(difference(set([a,b,c,d,f]), set([a,d,e,g])),
+ set([b,c,f])),
+ eval(difference(set([a,b,c]), set([d,e,f])),
+ set([a,b,c])),
+ eval(difference(set([a,b,c]), set([a,b,c,d,e,f])),
+ set([])),
+ eval(difference(set([e,f,g]), set([a,b,c,e])),
+ set([f,g])),
+ eval(difference(set([a,b,d,e,f]), set([c])),
+ set([a,b,d,e,f])),
ok.
-symdiff(suite) -> [];
-symdiff(doc) -> [""];
symdiff(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line {'EXIT', {type_mismatch, _}} =
+ E = empty_set(),
+ {'EXIT', {type_mismatch, _}} =
(catch symdiff(relation([{a,b}]), relation([{a,b,c}]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch symdiff(relation([{a,b}]), from_term([{a,b}], [{d,r}]))),
- ?line eval(symdiff(E, E), E),
- ?line eval(symdiff(set([a,b,c,d,e,f]), set([0,1,a,c])),
- union(set([b,d,e,f]), set([0,1]))),
- ?line eval(symdiff(set([a,b,c]), set([q,v,w,x,y])),
- union(set([a,b,c]), set([q,v,w,x,y]))),
- ?line eval(symdiff(set([a,b,c,d,e,f]), set([a,b,c])),
- set([d,e,f])),
- ?line eval(symdiff(set([c,e,g,h,i]), set([b,d,f])),
- union(set([c,e,g,h,i]), set([b,d,f]))),
- ?line eval(symdiff(set([c,d,g,h,k,l]),
- set([a,b,e,f,i,j,m,n])),
- union(set([c,d,g,h,k,l]), set([a,b,e,f,i,j,m,n]))),
- ?line eval(symdiff(set([c,d,g,h,k,l]),
- set([d,e,h,i,l,m,n,o,p])),
- union(set([c,g,k]), set([e,i,m,n,o,p]))),
+ eval(symdiff(E, E), E),
+ eval(symdiff(set([a,b,c,d,e,f]), set([0,1,a,c])),
+ union(set([b,d,e,f]), set([0,1]))),
+ eval(symdiff(set([a,b,c]), set([q,v,w,x,y])),
+ union(set([a,b,c]), set([q,v,w,x,y]))),
+ eval(symdiff(set([a,b,c,d,e,f]), set([a,b,c])),
+ set([d,e,f])),
+ eval(symdiff(set([c,e,g,h,i]), set([b,d,f])),
+ union(set([c,e,g,h,i]), set([b,d,f]))),
+ eval(symdiff(set([c,d,g,h,k,l]),
+ set([a,b,e,f,i,j,m,n])),
+ union(set([c,d,g,h,k,l]), set([a,b,e,f,i,j,m,n]))),
+ eval(symdiff(set([c,d,g,h,k,l]),
+ set([d,e,h,i,l,m,n,o,p])),
+ union(set([c,g,k]), set([e,i,m,n,o,p]))),
ok.
-symmetric_partition(suite) -> [];
-symmetric_partition(doc) -> [""];
symmetric_partition(Conf) when is_list(Conf) ->
- ?line E = set([]),
- ?line S1 = set([1,2,3,4]),
- ?line S2 = set([3,4,5,6]),
- ?line S3 = set([3,4]),
- ?line S4 = set([1,2,3,4,5,6]),
- ?line T1 = set([1,2]),
- ?line T2 = set([3,4]),
- ?line T3 = set([5,6]),
- ?line T4 = set([1,2,5,6]),
- ?line {'EXIT', {type_mismatch, _}} =
+ E = set([]),
+ S1 = set([1,2,3,4]),
+ S2 = set([3,4,5,6]),
+ S3 = set([3,4]),
+ S4 = set([1,2,3,4,5,6]),
+ T1 = set([1,2]),
+ T2 = set([3,4]),
+ T3 = set([5,6]),
+ T4 = set([1,2,5,6]),
+ {'EXIT', {type_mismatch, _}} =
(catch symmetric_partition(relation([{a,b}]), relation([{a,b,c}]))),
- ?line {E, E, E} = symmetric_partition(E, E),
- ?line {'EXIT', {type_mismatch, _}} =
+ {E, E, E} = symmetric_partition(E, E),
+ {'EXIT', {type_mismatch, _}} =
(catch symmetric_partition(relation([{a,b}]),
from_term([{a,c}],[{d,r}]))),
- ?line {E, E, S1} = symmetric_partition(E, S1),
- ?line {S1, E, E} = symmetric_partition(S1, E),
- ?line {T1, T2, T3} = symmetric_partition(S1, S2),
- ?line {T3, T2, T1} = symmetric_partition(S2, S1),
- ?line {E, T2, T4} = symmetric_partition(S3, S4),
- ?line {T4, T2, E} = symmetric_partition(S4, S3),
-
- ?line S5 = set([1,3,5]),
- ?line S6 = set([2,4,6,7,8]),
- ?line {S5, E, S6} = symmetric_partition(S5, S6),
- ?line {S6, E, S5} = symmetric_partition(S6, S5),
- ?line EE = empty_set(),
- ?line {EE, EE, EE} = symmetric_partition(EE, EE),
+ {E, E, S1} = symmetric_partition(E, S1),
+ {S1, E, E} = symmetric_partition(S1, E),
+ {T1, T2, T3} = symmetric_partition(S1, S2),
+ {T3, T2, T1} = symmetric_partition(S2, S1),
+ {E, T2, T4} = symmetric_partition(S3, S4),
+ {T4, T2, E} = symmetric_partition(S4, S3),
+
+ S5 = set([1,3,5]),
+ S6 = set([2,4,6,7,8]),
+ {S5, E, S6} = symmetric_partition(S5, S6),
+ {S6, E, S5} = symmetric_partition(S6, S5),
+ EE = empty_set(),
+ {EE, EE, EE} = symmetric_partition(EE, EE),
ok.
-is_sofs_set_1(suite) -> [];
-is_sofs_set_1(doc) -> [""];
is_sofs_set_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line true = is_sofs_set(E),
- ?line true = is_sofs_set(from_term([a])),
- ?line true = is_sofs_set(from_term({a})),
- ?line true = is_sofs_set(from_term(a)),
- ?line false = is_sofs_set(a),
+ E = empty_set(),
+ true = is_sofs_set(E),
+ true = is_sofs_set(from_term([a])),
+ true = is_sofs_set(from_term({a})),
+ true = is_sofs_set(from_term(a)),
+ false = is_sofs_set(a),
ok.
-is_set_1(suite) -> [];
-is_set_1(doc) -> [""];
is_set_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line true = is_set(E),
- ?line true = is_set(from_term([a])),
- ?line false = is_set(from_term({a})),
- ?line false = is_set(from_term(a)),
- ?line {'EXIT', _} = (catch is_set(a)),
-
- ?line true = is_empty_set(E),
- ?line false = is_empty_set(from_term([a])),
- ?line false = is_empty_set(from_term({a})),
- ?line false = is_empty_set(from_term(a)),
- ?line {'EXIT', _} = (catch is_empty_set(a)),
+ E = empty_set(),
+ true = is_set(E),
+ true = is_set(from_term([a])),
+ false = is_set(from_term({a})),
+ false = is_set(from_term(a)),
+ {'EXIT', _} = (catch is_set(a)),
+
+ true = is_empty_set(E),
+ false = is_empty_set(from_term([a])),
+ false = is_empty_set(from_term({a})),
+ false = is_empty_set(from_term(a)),
+ {'EXIT', _} = (catch is_empty_set(a)),
ok.
-is_equal(suite) -> [];
-is_equal(doc) -> [""];
is_equal(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line true = is_equal(E, E),
- ?line false = is_equal(from_term([a]), E),
- ?line {'EXIT', {type_mismatch, _}} =
+ E = empty_set(),
+ true = is_equal(E, E),
+ false = is_equal(from_term([a]), E),
+ {'EXIT', {type_mismatch, _}} =
(catch is_equal(intersection(set([a]), set([b])),
intersection(from_term([{a}]), from_term([{b}])))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch is_equal(from_term([],[{[atom],atom,[atom]}]),
from_term([],[{[atom],{atom},[atom]}]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch is_equal(set([a]), from_term([a],[type]))),
- ?line E2 = from_sets({from_term(a,atom)}),
- ?line true = is_equal(E2, E2),
- ?line true = is_equal(from_term({a}, {atom}), E2),
- ?line false = is_equal(from_term([{[a],[],c}]),
- from_term([{[],[],q}])),
+ E2 = from_sets({from_term(a,atom)}),
+ true = is_equal(E2, E2),
+ true = is_equal(from_term({a}, {atom}), E2),
+ false = is_equal(from_term([{[a],[],c}]),
+ from_term([{[],[],q}])),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch is_equal(E, E2)),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch is_equal(E2, E)),
- ?line true = is_equal(from_term({[],a,[]},{[atom],atom,[atom]}),
- from_term({[],a,[]},{[atom],atom,[atom]})),
- ?line {'EXIT', {type_mismatch, _}} =
+ true = is_equal(from_term({[],a,[]},{[atom],atom,[atom]}),
+ from_term({[],a,[]},{[atom],atom,[atom]})),
+ {'EXIT', {type_mismatch, _}} =
(catch is_equal(from_term({[],a,[]},{[atom],atom,[atom]}),
from_term({[],{a},[]},{[atom],{atom},[atom]}))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch is_equal(from_term({a}), from_term({a},{type}))),
ok.
-is_subset(suite) -> [];
-is_subset(doc) -> [""];
is_subset(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line true = is_subset(E, E),
- ?line true = is_subset(set([a,c,e]), set([a,b,c,d,e])),
- ?line false = is_subset(set([a,b]), E),
- ?line false = is_subset(set([d,e,f]), set([b,c,d,e])),
- ?line false = is_subset(set([a,b,c]), set([b,c])),
- ?line false = is_subset(set([b,c]), set([a,c])),
- ?line false = is_subset(set([d,e]), set([a,b])),
- ?line {'EXIT', {type_mismatch, _}} =
+ E = empty_set(),
+ true = is_subset(E, E),
+ true = is_subset(set([a,c,e]), set([a,b,c,d,e])),
+ false = is_subset(set([a,b]), E),
+ false = is_subset(set([d,e,f]), set([b,c,d,e])),
+ false = is_subset(set([a,b,c]), set([b,c])),
+ false = is_subset(set([b,c]), set([a,c])),
+ false = is_subset(set([d,e]), set([a,b])),
+ {'EXIT', {type_mismatch, _}} =
(catch is_subset(intersection(set([a]), set([b])),
intersection(from_term([{a}]), from_term([{b}])))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch is_subset(set([a]), from_term([a,b], [at]))),
ok.
-is_a_function_1(suite) -> [];
-is_a_function_1(doc) -> [""];
is_a_function_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([], 2),
- ?line {'EXIT', {badarg, _}} = (catch is_a_function(set([a,b]))),
- ?line true = is_a_function(E),
- ?line true = is_a_function(ER),
- ?line true = is_a_function(relation([])),
- ?line true = is_a_function(relation([],2)),
- ?line true = is_a_function(relation([{a,b},{b,c}])),
- ?line false = is_a_function(relation([{a,b},{b,c},{b,d},{e,f}])),
- ?line IS = relation([{{a,b},c},{{a,b},d}]),
- ?line false = is_a_function(IS),
+ E = empty_set(),
+ ER = relation([], 2),
+ {'EXIT', {badarg, _}} = (catch is_a_function(set([a,b]))),
+ true = is_a_function(E),
+ true = is_a_function(ER),
+ true = is_a_function(relation([])),
+ true = is_a_function(relation([],2)),
+ true = is_a_function(relation([{a,b},{b,c}])),
+ false = is_a_function(relation([{a,b},{b,c},{b,d},{e,f}])),
+ IS = relation([{{a,b},c},{{a,b},d}]),
+ false = is_a_function(IS),
F = 0.0, I = round(F),
- ?line FR = relation([{I,F},{F,1}]),
+ FR = relation([{I,F},{F,1}]),
if
F == I -> % term ordering
false = is_a_function(FR);
@@ -1280,343 +1229,315 @@ is_a_function_1(Conf) when is_list(Conf) ->
end,
ok.
-is_disjoint(suite) -> [];
-is_disjoint(doc) -> [""];
is_disjoint(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line {'EXIT', {type_mismatch, _}} =
+ E = empty_set(),
+ {'EXIT', {type_mismatch, _}} =
(catch is_disjoint(relation([{a,1}]), set([a,b]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch is_disjoint(set([a]), from_term([a],[mota]))),
- ?line true = is_disjoint(E, E),
- ?line false = is_disjoint(set([a,b,c]),set([b,c,d])),
- ?line false = is_disjoint(set([b,c,d]),set([a,b,c])),
- ?line true = is_disjoint(set([a,c,e]),set([b,d,f])),
+ true = is_disjoint(E, E),
+ false = is_disjoint(set([a,b,c]),set([b,c,d])),
+ false = is_disjoint(set([b,c,d]),set([a,b,c])),
+ true = is_disjoint(set([a,c,e]),set([b,d,f])),
ok.
-join(suite) -> [];
-join(doc) -> [""];
join(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
-
- ?line {'EXIT', {badarg, _}} = (catch join(relation([{a,1}]), 3, E, 5)),
- ?line {'EXIT', {badarg, _}} = (catch join(E, 1, relation([{a,1}]), 3)),
- ?line {'EXIT', {badarg, _}} = (catch join(E, 1, from_term([a]), 1)),
-
- ?line eval(join(E, 1, E, 2), E),
- ?line eval(join(E, 1, from_term([{{a},b}]), 2), E),
- ?line eval(join(from_term([{{a},b}]), 2, E, 1), E),
- ?line eval(join(from_term([{{a},b,e}]), 2, from_term([{c,{d}}]), 1),
- from_term([], [{{atom},atom,atom,{atom}}])),
- ?line eval(join(relation([{a}]), 1, relation([{1,a},{2,a}]), 2),
- relation([{a,1},{a,2}])),
- ?line eval(join(relation([{a,b,c},{b,c,d}]), 2,
- relation([{1,b},{2,a},{3,c}]), 2),
- relation([{a,b,c,1},{b,c,d,3}])),
- ?line eval(join(relation([{1,a,aa},{1,b,bb},{1,c,cc},{2,a,aa},{2,b,bb}]),
- 1,
- relation([{1,c,cc},{1,d,dd},{1,e,ee},{2,c,cc},{2,d,dd}]),
- 1),
- relation([{1,a,aa,c,cc},{1,a,aa,d,dd},{1,a,aa,e,ee},{1,b,bb,c,cc},
- {1,b,bb,d,dd},{1,b,bb,e,ee},{1,c,cc,c,cc},{1,c,cc,d,dd},
- {1,c,cc,e,ee},{2,a,aa,c,cc},{2,a,aa,d,dd},{2,b,bb,c,cc},
- {2,b,bb,d,dd}])),
+ E = empty_set(),
+
+ {'EXIT', {badarg, _}} = (catch join(relation([{a,1}]), 3, E, 5)),
+ {'EXIT', {badarg, _}} = (catch join(E, 1, relation([{a,1}]), 3)),
+ {'EXIT', {badarg, _}} = (catch join(E, 1, from_term([a]), 1)),
+
+ eval(join(E, 1, E, 2), E),
+ eval(join(E, 1, from_term([{{a},b}]), 2), E),
+ eval(join(from_term([{{a},b}]), 2, E, 1), E),
+ eval(join(from_term([{{a},b,e}]), 2, from_term([{c,{d}}]), 1),
+ from_term([], [{{atom},atom,atom,{atom}}])),
+ eval(join(relation([{a}]), 1, relation([{1,a},{2,a}]), 2),
+ relation([{a,1},{a,2}])),
+ eval(join(relation([{a,b,c},{b,c,d}]), 2,
+ relation([{1,b},{2,a},{3,c}]), 2),
+ relation([{a,b,c,1},{b,c,d,3}])),
+ eval(join(relation([{1,a,aa},{1,b,bb},{1,c,cc},{2,a,aa},{2,b,bb}]),
+ 1,
+ relation([{1,c,cc},{1,d,dd},{1,e,ee},{2,c,cc},{2,d,dd}]),
+ 1),
+ relation([{1,a,aa,c,cc},{1,a,aa,d,dd},{1,a,aa,e,ee},{1,b,bb,c,cc},
+ {1,b,bb,d,dd},{1,b,bb,e,ee},{1,c,cc,c,cc},{1,c,cc,d,dd},
+ {1,c,cc,e,ee},{2,a,aa,c,cc},{2,a,aa,d,dd},{2,b,bb,c,cc},
+ {2,b,bb,d,dd}])),
R1 = relation([{a,b},{b,c}]),
R2 = relation([{b,1},{a,2},{c,3},{c,4}]),
- ?line eval(join(R1, 1, R2, 1), from_term([{a,b,2},{b,c,1}])),
- ?line eval(join(R1, 2, R2, 1), from_term([{a,b,1},{b,c,3},{b,c,4}])),
- ?line eval(join(R1, 1, converse(R2), 2),
- from_term([{a,b,2},{b,c,1}])),
- ?line eval(join(R1, 2, converse(R2), 2),
- from_term([{a,b,1},{b,c,3},{b,c,4}])),
+ eval(join(R1, 1, R2, 1), from_term([{a,b,2},{b,c,1}])),
+ eval(join(R1, 2, R2, 1), from_term([{a,b,1},{b,c,3},{b,c,4}])),
+ eval(join(R1, 1, converse(R2), 2),
+ from_term([{a,b,2},{b,c,1}])),
+ eval(join(R1, 2, converse(R2), 2),
+ from_term([{a,b,1},{b,c,3},{b,c,4}])),
ok.
-canonical(suite) -> [];
-canonical(doc) -> [""];
canonical(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line {'EXIT', {badarg, _}} =
+ E = empty_set(),
+ {'EXIT', {badarg, _}} =
(catch canonical_relation(set([a,b]))),
- ?line eval(canonical_relation(E), E),
- ?line eval(canonical_relation(from_term([[]])), E),
- ?line eval(canonical_relation(from_term([[a,b,c]])),
- from_term([{a,[a,b,c]},{b,[a,b,c]},{c,[a,b,c]}])),
+ eval(canonical_relation(E), E),
+ eval(canonical_relation(from_term([[]])), E),
+ eval(canonical_relation(from_term([[a,b,c]])),
+ from_term([{a,[a,b,c]},{b,[a,b,c]},{c,[a,b,c]}])),
ok.
-relation_to_family_1(suite) -> [];
-relation_to_family_1(doc) -> [""];
relation_to_family_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line EF = family([]),
- ?line eval(relation_to_family(E), E),
- ?line eval(relation_to_family(relation([])), EF),
- ?line eval(relation_to_family(relation([], 2)), EF),
- ?line R = relation([{b,1},{c,7},{c,9},{c,11}]),
- ?line F = family([{b,[1]},{c,[7,9,11]}]),
- ?line eval(relation_to_family(R), F),
- ?line eval(sofs:rel2fam(R), F),
- ?line {'EXIT', {badarg, _}} = (catch relation_to_family(set([a]))),
+ E = empty_set(),
+ EF = family([]),
+ eval(relation_to_family(E), E),
+ eval(relation_to_family(relation([])), EF),
+ eval(relation_to_family(relation([], 2)), EF),
+ R = relation([{b,1},{c,7},{c,9},{c,11}]),
+ F = family([{b,[1]},{c,[7,9,11]}]),
+ eval(relation_to_family(R), F),
+ eval(sofs:rel2fam(R), F),
+ {'EXIT', {badarg, _}} = (catch relation_to_family(set([a]))),
ok.
-domain_1(suite) -> [];
-domain_1(doc) -> [""];
domain_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([]),
- ?line {'EXIT', {badarg, _}} = (catch domain(relation([],3))),
- ?line eval(domain(E), E),
- ?line eval(domain(ER), set([])),
- ?line eval(domain(relation([{1,a},{1,b},{2,a},{2,b}])), set([1,2])),
- ?line eval(domain(relation([{a,1},{b,2},{c,3}])), set([a,b,c])),
- ?line eval(field(relation([{a,1},{b,2},{c,3}])),
- set([a,b,c,1,2,3])),
+ E = empty_set(),
+ ER = relation([]),
+ {'EXIT', {badarg, _}} = (catch domain(relation([],3))),
+ eval(domain(E), E),
+ eval(domain(ER), set([])),
+ eval(domain(relation([{1,a},{1,b},{2,a},{2,b}])), set([1,2])),
+ eval(domain(relation([{a,1},{b,2},{c,3}])), set([a,b,c])),
+ eval(field(relation([{a,1},{b,2},{c,3}])),
+ set([a,b,c,1,2,3])),
F = 0.0, I = round(F),
- ?line FR = relation([{I,a},{F,b}]),
+ FR = relation([{I,a},{F,b}]),
if
F == I -> % term ordering
- ?line true = (1 =:= no_elements(domain(FR)));
+ true = (1 =:= no_elements(domain(FR)));
true ->
- ?line true = (2 =:= no_elements(domain(FR)))
+ true = (2 =:= no_elements(domain(FR)))
end,
ok.
-range_1(suite) -> [];
-range_1(doc) -> [""];
range_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([]),
- ?line {'EXIT', {badarg, _}} = (catch range(relation([],3))),
- ?line eval(range(E), E),
- ?line eval(range(ER), set([])),
- ?line eval(range(relation([{1,a},{1,b},{2,a},{2,b}])), set([a,b])),
- ?line eval(range(relation([{a,1},{b,2},{c,3}])), set([1,2,3])),
+ E = empty_set(),
+ ER = relation([]),
+ {'EXIT', {badarg, _}} = (catch range(relation([],3))),
+ eval(range(E), E),
+ eval(range(ER), set([])),
+ eval(range(relation([{1,a},{1,b},{2,a},{2,b}])), set([a,b])),
+ eval(range(relation([{a,1},{b,2},{c,3}])), set([1,2,3])),
ok.
-
-inverse_1(suite) -> [];
-inverse_1(doc) -> [""];
+
inverse_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([]),
- ?line {'EXIT', {badarg, _}} = (catch inverse(relation([],3))),
- ?line {'EXIT', {bad_function, _}} =
+ E = empty_set(),
+ ER = relation([]),
+ {'EXIT', {badarg, _}} = (catch inverse(relation([],3))),
+ {'EXIT', {bad_function, _}} =
(catch inverse(relation([{1,a},{1,b}]))),
- ?line {'EXIT', {bad_function, _}} =
+ {'EXIT', {bad_function, _}} =
(catch inverse(relation([{1,a},{2,a}]))),
- ?line eval(inverse(E), E),
- ?line eval(inverse(ER), ER),
- ?line eval(inverse(relation([{a,1},{b,2},{c,3}])),
- relation([{1,a},{2,b},{3,c}])),
+ eval(inverse(E), E),
+ eval(inverse(ER), ER),
+ eval(inverse(relation([{a,1},{b,2},{c,3}])),
+ relation([{1,a},{2,b},{3,c}])),
F = 0.0, I = round(F),
- ?line FR = relation([{I,a},{F,b}]),
+ FR = relation([{I,a},{F,b}]),
if
F == I -> % term ordering
- ?line {'EXIT', {bad_function, _}} = (catch inverse(FR));
+ {'EXIT', {bad_function, _}} = (catch inverse(FR));
true ->
- ?line eval(inverse(FR), relation([{a,I},{b,F}]))
+ eval(inverse(FR), relation([{a,I},{b,F}]))
end,
ok.
-
-converse_1(suite) -> [];
-converse_1(doc) -> [""];
+
converse_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([]),
- ?line {'EXIT', {badarg, _}} = (catch converse(relation([],3))),
- ?line eval(converse(ER), ER),
- ?line eval(converse(E), E),
- ?line eval(converse(relation([{a,1},{b,2},{c,3}])),
- relation([{1,a},{2,b},{3,c}])),
- ?line eval(converse(relation([{1,a},{1,b}])),
- relation([{a,1},{b,1}])),
- ?line eval(converse(relation([{1,a},{2,a}])),
- relation([{a,1},{a,2}])),
+ E = empty_set(),
+ ER = relation([]),
+ {'EXIT', {badarg, _}} = (catch converse(relation([],3))),
+ eval(converse(ER), ER),
+ eval(converse(E), E),
+ eval(converse(relation([{a,1},{b,2},{c,3}])),
+ relation([{1,a},{2,b},{3,c}])),
+ eval(converse(relation([{1,a},{1,b}])),
+ relation([{a,1},{b,1}])),
+ eval(converse(relation([{1,a},{2,a}])),
+ relation([{a,1},{a,2}])),
ok.
-
-no_elements_1(suite) -> [];
-no_elements_1(doc) -> [""];
+
no_elements_1(Conf) when is_list(Conf) ->
- ?line 0 = no_elements(empty_set()),
- ?line 0 = no_elements(set([])),
- ?line 1 = no_elements(from_term([a])),
- ?line 10 = no_elements(from_term(lists:seq(1,10))),
- ?line 3 = no_elements(from_term({a,b,c},{atom,atom,atom})),
- ?line {'EXIT', {badarg, _}} = (catch no_elements(from_term(a))),
- ?line {'EXIT', {function_clause, _}} = (catch no_elements(a)),
+ 0 = no_elements(empty_set()),
+ 0 = no_elements(set([])),
+ 1 = no_elements(from_term([a])),
+ 10 = no_elements(from_term(lists:seq(1,10))),
+ 3 = no_elements(from_term({a,b,c},{atom,atom,atom})),
+ {'EXIT', {badarg, _}} = (catch no_elements(from_term(a))),
+ {'EXIT', {function_clause, _}} = (catch no_elements(a)),
ok.
-image(suite) -> [];
-image(doc) -> [""];
image(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([]),
- ?line eval(image(E, E), E),
- ?line eval(image(ER, E), set([])),
- ?line eval(image(relation([{a,1},{b,2},{c,3},{f,6}]), set([a,b,c,d,f])),
- set([1,2,3,6])),
- ?line eval(image(relation([{a,1},{b,2},{c,3},{d,4},{r,17}]),
- set([b,c,q,r])),
- set([2,3,17])),
- ?line eval(image(from_term([{[a],{1}},{[b],{2}}]), from_term([[a]])),
- from_term([{1}])),
- ?line eval(image(relation([{1,a},{2,a},{3,a},{4,b},{2,b}]), set([1,2,4])),
- set([a,b])),
- ?line {'EXIT', {badarg, _}} =
+ E = empty_set(),
+ ER = relation([]),
+ eval(image(E, E), E),
+ eval(image(ER, E), set([])),
+ eval(image(relation([{a,1},{b,2},{c,3},{f,6}]), set([a,b,c,d,f])),
+ set([1,2,3,6])),
+ eval(image(relation([{a,1},{b,2},{c,3},{d,4},{r,17}]),
+ set([b,c,q,r])),
+ set([2,3,17])),
+ eval(image(from_term([{[a],{1}},{[b],{2}}]), from_term([[a]])),
+ from_term([{1}])),
+ eval(image(relation([{1,a},{2,a},{3,a},{4,b},{2,b}]), set([1,2,4])),
+ set([a,b])),
+ {'EXIT', {badarg, _}} =
(catch image(from_term([a,b]), E)),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch image(from_term([{[a],1}]), set([[a]]))),
ok.
-inverse_image(suite) -> [];
-inverse_image(doc) -> [""];
inverse_image(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([]),
- ?line eval(inverse_image(E, E), E),
- ?line eval(inverse_image(ER, E), set([])),
- ?line eval(inverse_image(converse(relation([{a,1},{b,2},{c,3},{f,6}])),
- set([a,b,c,d,f])),
- set([1,2,3,6])),
- ?line eval(inverse_image(converse(relation([{a,1},{b,2},{c,3},
- {d,4},{r,17}])),
- set([b,c,q,r])),
- set([2,3,17])),
- ?line eval(inverse_image(converse(from_term([{[a],{1}},{[b],{2}}])),
- from_term([[a]])),
- from_term([{1}])),
- ?line eval(inverse_image(converse(relation([{1,a},{2,a},
- {3,a},{4,b},{2,b}])),
- set([1,2,4])),
- set([a,b])),
- ?line {'EXIT', {badarg, _}} =
+ E = empty_set(),
+ ER = relation([]),
+ eval(inverse_image(E, E), E),
+ eval(inverse_image(ER, E), set([])),
+ eval(inverse_image(converse(relation([{a,1},{b,2},{c,3},{f,6}])),
+ set([a,b,c,d,f])),
+ set([1,2,3,6])),
+ eval(inverse_image(converse(relation([{a,1},{b,2},{c,3},
+ {d,4},{r,17}])),
+ set([b,c,q,r])),
+ set([2,3,17])),
+ eval(inverse_image(converse(from_term([{[a],{1}},{[b],{2}}])),
+ from_term([[a]])),
+ from_term([{1}])),
+ eval(inverse_image(converse(relation([{1,a},{2,a},
+ {3,a},{4,b},{2,b}])),
+ set([1,2,4])),
+ set([a,b])),
+ {'EXIT', {badarg, _}} =
(catch inverse_image(from_term([a,b]), E)),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch inverse_image(converse(from_term([{[a],1}])), set([[a]]))),
ok.
-composite_1(suite) -> [];
-composite_1(doc) -> [""];
composite_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line EF = a_function([]),
- ?line eval(composite(E, E), E),
- ?line eval(composite(E, a_function([{a,b}])), E),
- ?line eval(composite(relation([{a,b}]), E), E),
- ?line {'EXIT', {bad_function, _}} =
+ E = empty_set(),
+ EF = a_function([]),
+ eval(composite(E, E), E),
+ eval(composite(E, a_function([{a,b}])), E),
+ eval(composite(relation([{a,b}]), E), E),
+ {'EXIT', {bad_function, _}} =
(catch composite(EF, relation([{a,b},{a,c}]))),
- ?line {'EXIT', {bad_function, _}} =
+ {'EXIT', {bad_function, _}} =
(catch composite(a_function([{b,a}]), EF)),
- ?line {'EXIT', {bad_function, _}} =
+ {'EXIT', {bad_function, _}} =
(catch composite(relation([{1,a},{2,b},{2,a}]),
a_function([{a,1},{b,3}]))),
- ?line {'EXIT', {bad_function, _}} =
- (catch composite(a_function([{1,a},{2,b}]), a_function([{b,3}]))),
- ?line eval(composite(EF, EF), EF),
- ?line eval(composite(a_function([{b,a}]), from_term([{a,{b,c}}])),
- from_term([{b,{b,c}}])),
- ?line eval(composite(a_function([{q,1},{z,2}]),
- a_function([{1,a},{2,a}])),
- a_function([{q,a},{z,a}])),
- ?line eval(composite(a_function([{a,0},{b,0},{c,1},{d,1},{e,2},{f,3}]),
- a_function([{0,p},{1,q},{2,r},{3,w},{4,aa}])),
- a_function([{c,q},{d,q},{f,w},{e,r},{a,p},{b,p}])),
- ?line eval(composite(a_function([{1,c}]),
- a_function([{a,1},{b,3},{c,4}])),
- a_function([{1,4}])),
- ?line {'EXIT', {bad_function, _}} =
+ {'EXIT', {bad_function, _}} =
+ (catch composite(a_function([{1,a},{2,b}]), a_function([{b,3}]))),
+ eval(composite(EF, EF), EF),
+ eval(composite(a_function([{b,a}]), from_term([{a,{b,c}}])),
+ from_term([{b,{b,c}}])),
+ eval(composite(a_function([{q,1},{z,2}]),
+ a_function([{1,a},{2,a}])),
+ a_function([{q,a},{z,a}])),
+ eval(composite(a_function([{a,0},{b,0},{c,1},{d,1},{e,2},{f,3}]),
+ a_function([{0,p},{1,q},{2,r},{3,w},{4,aa}])),
+ a_function([{c,q},{d,q},{f,w},{e,r},{a,p},{b,p}])),
+ eval(composite(a_function([{1,c}]),
+ a_function([{a,1},{b,3},{c,4}])),
+ a_function([{1,4}])),
+ {'EXIT', {bad_function, _}} =
(catch composite(a_function([{1,a},{2,b}]),
a_function([{a,1},{c,3}]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch composite(from_term([a,b]), E)),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch composite(E, from_term([a,b]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch composite(from_term([{a,b}]), from_term([{{a},b}]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch composite(from_term([{a,b}]),
from_term([{b,c}], [{d,r}]))),
F = 0.0, I = round(F),
- ?line FR1 = relation([{1,c}]),
- ?line FR2 = relation([{I,1},{F,3},{c,4}]),
+ FR1 = relation([{1,c}]),
+ FR2 = relation([{I,1},{F,3},{c,4}]),
if
F == I -> % term ordering
- ?line {'EXIT', {bad_function, _}} = (catch composite(FR1, FR2));
+ {'EXIT', {bad_function, _}} = (catch composite(FR1, FR2));
true ->
- ?line eval(composite(FR1, FR2), a_function([{1,4}]))
+ eval(composite(FR1, FR2), a_function([{1,4}]))
end,
ok.
-relative_product_1(suite) -> [];
-relative_product_1(doc) -> [""];
relative_product_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([]),
- ?line eval(relative_product1(E, E), E),
- ?line eval(relative_product1(E, relation([{a,b}])), E),
- ?line eval(relative_product1(relation([{a,b}]), E), E),
- ?line eval(relative_product1(relation([{a,b}]), from_term([{a,{b,c}}])),
- from_term([{b,{b,c}}])),
- ?line eval(relative_product1(relation([{1,z},{1,q},{2,z}]),
- relation([{1,a},{1,b},{2,a}])),
- relation([{q,a},{q,b},{z,a},{z,b}])),
- ?line eval(relative_product1(relation([{0,a},{0,b},{1,c},
- {1,d},{2,e},{3,f}]),
- relation([{1,q},{3,w}])),
- relation([{c,q},{d,q},{f,w}])),
- ?line {'EXIT', {badarg, _}} =
+ E = empty_set(),
+ ER = relation([]),
+ eval(relative_product1(E, E), E),
+ eval(relative_product1(E, relation([{a,b}])), E),
+ eval(relative_product1(relation([{a,b}]), E), E),
+ eval(relative_product1(relation([{a,b}]), from_term([{a,{b,c}}])),
+ from_term([{b,{b,c}}])),
+ eval(relative_product1(relation([{1,z},{1,q},{2,z}]),
+ relation([{1,a},{1,b},{2,a}])),
+ relation([{q,a},{q,b},{z,a},{z,b}])),
+ eval(relative_product1(relation([{0,a},{0,b},{1,c},
+ {1,d},{2,e},{3,f}]),
+ relation([{1,q},{3,w}])),
+ relation([{c,q},{d,q},{f,w}])),
+ {'EXIT', {badarg, _}} =
(catch relative_product1(from_term([a,b]), ER)),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch relative_product1(ER, from_term([a,b]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch relative_product1(from_term([{a,b}]), from_term([{{a},b}]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch relative_product1(from_term([{a,b}]),
from_term([{b,c}], [{d,r}]))),
ok.
-relative_product_2(suite) -> [];
-relative_product_2(doc) -> [""];
relative_product_2(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([]),
+ E = empty_set(),
+ ER = relation([]),
- ?line {'EXIT', {badarg, _}} = (catch relative_product({from_term([a,b])})),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {badarg, _}} = (catch relative_product({from_term([a,b])})),
+ {'EXIT', {type_mismatch, _}} =
(catch relative_product({from_term([{a,b}]), from_term([{{a},b}])})),
- ?line {'EXIT', {badarg, _}} = (catch relative_product({})),
- ?line true = is_equal(relative_product({ER}),
- from_term([], [{atom,{atom}}])),
- ?line eval(relative_product({relation([{a,b},{c,a}]),
- relation([{a,1},{a,2}]),
- relation([{a,aa},{c,1}])}),
- from_term([{a,{b,1,aa}},{a,{b,2,aa}}])),
- ?line eval(relative_product({relation([{a,b}])}, E), E),
- ?line eval(relative_product({E}, relation([{a,b}])), E),
- ?line eval(relative_product({E,from_term([], [{{atom,atom,atom},atom}])}),
- E),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} = (catch relative_product({})),
+ true = is_equal(relative_product({ER}),
+ from_term([], [{atom,{atom}}])),
+ eval(relative_product({relation([{a,b},{c,a}]),
+ relation([{a,1},{a,2}]),
+ relation([{a,aa},{c,1}])}),
+ from_term([{a,{b,1,aa}},{a,{b,2,aa}}])),
+ eval(relative_product({relation([{a,b}])}, E), E),
+ eval(relative_product({E}, relation([{a,b}])), E),
+ eval(relative_product({E,from_term([], [{{atom,atom,atom},atom}])}),
+ E),
+ {'EXIT', {badarg, _}} =
(catch relative_product({from_term([a,b])}, E)),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch relative_product({relation([])}, set([]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch relative_product({from_term([{a,b}]),
from_term([{{a},b}])}, ER)),
- ?line {'EXIT', {badarg, _}} = (catch relative_product({}, ER)),
- ?line relprod2({relation([{a,b}])}, from_term([],[{{atom},atom}]), ER),
- ?line relprod2({relation([{a,b}]),relation([{a,1}])},
- from_term([{{b,1},{tjo,hej,sa}}]),
- from_term([{a,{tjo,hej,sa}}])),
- ?line relprod2({relation([{a,b}]), ER}, from_term([{{a,b},b}]), ER),
- ?line relprod2({relation([{a,b},{c,a}]),
- relation([{a,1},{a,2}])},
- from_term([{{b,1},b1},{{b,2},b2}]),
- relation([{a,b1},{a,b2}])),
- ?line eval(relative_product({relation([{a,b}]), ER}),
- from_term([],[{atom,{atom,atom}}])),
- ?line eval(relative_product({from_term([{{a,[a,b]},[a]}]),
- from_term([{{a,[a,b]},[[a,b]]}])}),
- from_term([{{a,[a,b]},{[a],[[a,b]]}}])),
+ {'EXIT', {badarg, _}} = (catch relative_product({}, ER)),
+ relprod2({relation([{a,b}])}, from_term([],[{{atom},atom}]), ER),
+ relprod2({relation([{a,b}]),relation([{a,1}])},
+ from_term([{{b,1},{tjo,hej,sa}}]),
+ from_term([{a,{tjo,hej,sa}}])),
+ relprod2({relation([{a,b}]), ER}, from_term([{{a,b},b}]), ER),
+ relprod2({relation([{a,b},{c,a}]),
+ relation([{a,1},{a,2}])},
+ from_term([{{b,1},b1},{{b,2},b2}]),
+ relation([{a,b1},{a,b2}])),
+ eval(relative_product({relation([{a,b}]), ER}),
+ from_term([],[{atom,{atom,atom}}])),
+ eval(relative_product({from_term([{{a,[a,b]},[a]}]),
+ from_term([{{a,[a,b]},[[a,b]]}])}),
+ from_term([{{a,[a,b]},{[a],[[a,b]]}}])),
ok.
relprod2(A1T, A2, R) ->
@@ -1624,219 +1545,213 @@ relprod2(A1T, A2, R) ->
eval(relative_product(A1T, A2), R),
eval(relative_product(tuple_to_list(A1T), A2), R).
-product_1(suite) -> [];
-product_1(doc) -> [""];
product_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line eval(product(E, E), E),
- ?line eval(product(relation([]), E), E),
- ?line eval(product(E, relation([])), E),
- ?line eval(product(relation([{a,b}]),relation([{c,d}])),
- from_term([{{a,b},{c,d}}],[{{atom,atom},{atom,atom}}])),
-
- ?line eval(product({E, set([a,b,c])}), E),
- ?line eval(product({set([a,b,c]), E}), E),
- ?line eval(product({set([a,b,c]), E, E}), E),
- ?line eval(product({E,E}), E),
- ?line eval(product({set([a,b]),set([1,2])}),
- relation([{a,1},{a,2},{b,1},{b,2}])),
- ?line eval(product({from_term([a,b]), from_term([{a,b},{c,d}]),
- from_term([1])}),
- from_term([{a,{a,b},1},{a,{c,d},1},{b,{a,b},1},{b,{c,d},1}])),
- ?line {'EXIT', {badarg, _}} = (catch product({})),
- ?line {'EXIT', {badarg, _}} = (catch product({foo})),
- ?line eval(product({E}), E),
- ?line eval(product({E, E}), E),
- ?line eval(product(set([a,b]), set([1,2])),
- relation([{a,1},{a,2},{b,1},{b,2}])),
- ?line eval(product({relation([]), E}), E),
+ E = empty_set(),
+ eval(product(E, E), E),
+ eval(product(relation([]), E), E),
+ eval(product(E, relation([])), E),
+ eval(product(relation([{a,b}]),relation([{c,d}])),
+ from_term([{{a,b},{c,d}}],[{{atom,atom},{atom,atom}}])),
+
+ eval(product({E, set([a,b,c])}), E),
+ eval(product({set([a,b,c]), E}), E),
+ eval(product({set([a,b,c]), E, E}), E),
+ eval(product({E,E}), E),
+ eval(product({set([a,b]),set([1,2])}),
+ relation([{a,1},{a,2},{b,1},{b,2}])),
+ eval(product({from_term([a,b]), from_term([{a,b},{c,d}]),
+ from_term([1])}),
+ from_term([{a,{a,b},1},{a,{c,d},1},{b,{a,b},1},{b,{c,d},1}])),
+ {'EXIT', {badarg, _}} = (catch product({})),
+ {'EXIT', {badarg, _}} = (catch product({foo})),
+ eval(product({E}), E),
+ eval(product({E, E}), E),
+ eval(product(set([a,b]), set([1,2])),
+ relation([{a,1},{a,2},{b,1},{b,2}])),
+ eval(product({relation([]), E}), E),
ok.
-partition_1(suite) -> [];
-partition_1(doc) -> [""];
partition_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([]),
- ?line Id = fun(A) -> A end,
- ?line S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
- ?line eval(partition(1, E), E),
- ?line eval(partition(2, E), E),
- ?line eval(partition(1, ER), from_term([], [type(ER)])),
- ?line eval(partition(2, ER), from_term([], [type(ER)])),
- ?line eval(partition(1, relation([{1,a},{1,b},{2,c},{2,d}])),
- from_term([[{1,a},{1,b}],[{2,c},{2,d}]])),
- ?line eval(partition(2, relation([{1,a},{1,b},{2,a},{2,b},{3,c}])),
- from_term([[{1,a},{2,a}],[{1,b},{2,b}],[{3,c}]])),
- ?line eval(partition(2, relation([{1,a}])), from_term([[{1,a}]])),
- ?line eval(partition(2, relation([{1,a},{2,b}])),
- from_term([[{1,a}],[{2,b}]])),
- ?line eval(partition(2, relation([{1,a},{2,a},{3,a}])),
- from_term([[{1,a},{2,a},{3,a}]])),
- ?line eval(partition(2, relation([{1,b},{2,a}])), % OTP-4516
- from_term([[{1,b}],[{2,a}]])),
- ?line eval(union(partition(Id, S1)), S1),
- ?line eval(partition({external, fun({A,{B,_}}) -> {A,B} end},
- from_term([{a,{b,c}},{b,{c,d}},{a,{b,f}}])),
- from_term([[{a,{b,c}},{a,{b,f}}],[{b,{c,d}}]])),
+ E = empty_set(),
+ ER = relation([]),
+ Id = fun(A) -> A end,
+ S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
+ eval(partition(1, E), E),
+ eval(partition(2, E), E),
+ eval(partition(1, ER), from_term([], [type(ER)])),
+ eval(partition(2, ER), from_term([], [type(ER)])),
+ eval(partition(1, relation([{1,a},{1,b},{2,c},{2,d}])),
+ from_term([[{1,a},{1,b}],[{2,c},{2,d}]])),
+ eval(partition(2, relation([{1,a},{1,b},{2,a},{2,b},{3,c}])),
+ from_term([[{1,a},{2,a}],[{1,b},{2,b}],[{3,c}]])),
+ eval(partition(2, relation([{1,a}])), from_term([[{1,a}]])),
+ eval(partition(2, relation([{1,a},{2,b}])),
+ from_term([[{1,a}],[{2,b}]])),
+ eval(partition(2, relation([{1,a},{2,a},{3,a}])),
+ from_term([[{1,a},{2,a},{3,a}]])),
+ eval(partition(2, relation([{1,b},{2,a}])), % OTP-4516
+ from_term([[{1,b}],[{2,a}]])),
+ eval(union(partition(Id, S1)), S1),
+ eval(partition({external, fun({A,{B,_}}) -> {A,B} end},
+ from_term([{a,{b,c}},{b,{c,d}},{a,{b,f}}])),
+ from_term([[{a,{b,c}},{a,{b,f}}],[{b,{c,d}}]])),
F = 0.0, I = round(F),
- ?line FR = relation([{I,a},{F,b}]),
+ FR = relation([{I,a},{F,b}]),
if
F == I -> % term ordering
- ?line eval(partition(1, FR), from_term([[{I,a},{F,b}]]));
+ eval(partition(1, FR), from_term([[{I,a},{F,b}]]));
true ->
- ?line eval(partition(1, FR), from_term([[{I,a}],[{F,b}]]))
+ eval(partition(1, FR), from_term([[{I,a}],[{F,b}]]))
end,
- ?line {'EXIT', {badarg, _}} = (catch partition(2, set([a]))),
- ?line {'EXIT', {badarg, _}} = (catch partition(1, set([a]))),
- ?line eval(partition(Id, set([a])), from_term([[a]])),
-
- ?line eval(partition(E), E),
- ?line P1 = from_term([[a,b,c],[d,e,f],[g,h]]),
- ?line P2 = from_term([[a,d],[b,c,e,f,q,v]]),
- ?line eval(partition(union(P1, P2)),
- from_term([[a],[b,c],[d],[e,f],[g,h],[q,v]])),
- ?line {'EXIT', {badarg, _}} = (catch partition(from_term([a]))),
+ {'EXIT', {badarg, _}} = (catch partition(2, set([a]))),
+ {'EXIT', {badarg, _}} = (catch partition(1, set([a]))),
+ eval(partition(Id, set([a])), from_term([[a]])),
+
+ eval(partition(E), E),
+ P1 = from_term([[a,b,c],[d,e,f],[g,h]]),
+ P2 = from_term([[a,d],[b,c,e,f,q,v]]),
+ eval(partition(union(P1, P2)),
+ from_term([[a],[b,c],[d],[e,f],[g,h],[q,v]])),
+ {'EXIT', {badarg, _}} = (catch partition(from_term([a]))),
ok.
-partition_3(suite) -> [];
-partition_3(doc) -> [""];
partition_3(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([]),
+ E = empty_set(),
+ ER = relation([]),
%% set of ordered sets
- ?line S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
- ?line eval(partition(1, S1, set([0,1,d,e])),
- lpartition(1, S1, set([0,1,d,e]))),
- ?line eval(partition(1, S1, E), lpartition(1, S1, E)),
- ?line eval(partition(2, ER, set([a,b])), lpartition(2, ER, set([a,b]))),
+ S1 = relation([{a,1},{b,2},{b,22},{c,0}]),
+ eval(partition(1, S1, set([0,1,d,e])),
+ lpartition(1, S1, set([0,1,d,e]))),
+ eval(partition(1, S1, E), lpartition(1, S1, E)),
+ eval(partition(2, ER, set([a,b])), lpartition(2, ER, set([a,b]))),
XFun1 = {external, fun({_A,B,C}) -> {B,C} end},
R1a = relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
R1b = relation([{bb,2},{cc,3}]),
- ?line eval(partition(XFun1, R1a, R1b), lpartition(XFun1, R1a, R1b)),
+ eval(partition(XFun1, R1a, R1b), lpartition(XFun1, R1a, R1b)),
Id = fun(X) -> X end,
XId = {external, Id},
R2 = relation([{a,b}]),
- ?line eval(partition(XId, R2, E), lpartition(XId, R2, E)),
+ eval(partition(XId, R2, E), lpartition(XId, R2, E)),
R3 = relation([{b,d}]),
- ?line eval(partition(XId, E, R3), lpartition(XId, E, R3)),
+ eval(partition(XId, E, R3), lpartition(XId, E, R3)),
Fun1 = fun(S) -> {_A,B,C} = to_external(S), from_term({B,C}) end,
R4a = relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
R4b = relation([{bb,2},{cc,3}]),
- ?line eval(partition(Fun1,R4a,R4b), lpartition(Fun1,R4a,R4b)),
+ eval(partition(Fun1,R4a,R4b), lpartition(Fun1,R4a,R4b)),
XFun2 = {external, fun({_,{A},B}) -> {A,B} end},
R5a = from_term([{a,{aa},1},{b,{bb},2},{c,{cc},3}]),
R5b = from_term([{bb,2},{cc,3}]),
- ?line eval(partition(XFun2,R5a, R5b), lpartition(XFun2,R5a, R5b)),
+ eval(partition(XFun2,R5a, R5b), lpartition(XFun2,R5a, R5b)),
R6 = relation([{a,b}]),
- ?line eval(partition(2, R6, E), lpartition(2, R6, E)),
+ eval(partition(2, R6, E), lpartition(2, R6, E)),
R7 = relation([{b,d}]),
- ?line eval(partition(2, E, R7), lpartition(2, E, R7)),
+ eval(partition(2, E, R7), lpartition(2, E, R7)),
S2 = set([a]),
- ?line eval(partition(XId, E, S2), lpartition(XId, E, S2)),
- ?line eval(partition(XId, S1, E), lpartition(XId, S1, E)),
- ?line {'EXIT', {badarg, _}} =
+ eval(partition(XId, E, S2), lpartition(XId, E, S2)),
+ eval(partition(XId, S1, E), lpartition(XId, S1, E)),
+ {'EXIT', {badarg, _}} =
(catch partition(3, relation([{a,b}]), E)),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch partition(3, relation([{a,b}]), relation([{b,d}]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch partition(3, relation([{a,b}]), set([{b,d}]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch partition(2, relation([{a,b}]), relation([{b,d}]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch partition({external, fun({A,_B}) -> A end},
relation([{a,b}]), relation([{b,d}]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch partition({external, fun({A,_}) -> {A,0} end},
from_term([{1,a}]),
from_term([{1,0}]))),
S18a = relation([{1,e},{2,b},{3,c},{4,b},{5,a},{6,0}]),
S18b = set([b,d,f]),
- ?line eval(partition({external,fun({_,X}) -> X end}, S18a, S18b),
- lpartition({external,fun({_,X}) -> X end}, S18a, S18b)),
+ eval(partition({external,fun({_,X}) -> X end}, S18a, S18b),
+ lpartition({external,fun({_,X}) -> X end}, S18a, S18b)),
S19a = sofs:relation([{3,a},{8,b}]),
S19b = set([2,6,7]),
- ?line eval(partition({external,fun({X,_}) -> X end}, S19a, S19b),
- lpartition({external,fun({X,_}) -> X end}, S19a, S19b)),
+ eval(partition({external,fun({X,_}) -> X end}, S19a, S19b),
+ lpartition({external,fun({X,_}) -> X end}, S19a, S19b)),
R8a = relation([{a,d},{b,e},{c,b},{d,c}]),
S8 = set([b,d]),
- ?line eval(partition(2, R8a, S8), lpartition(2, R8a, S8)),
+ eval(partition(2, R8a, S8), lpartition(2, R8a, S8)),
S16a = relation([{1,e},{2,b},{3,c},{4,b},{5,a},{6,0}]),
S16b = set([b,c,d]),
- ?line eval(partition(2, S16a, S16b), lpartition(2, S16a, S16b)),
+ eval(partition(2, S16a, S16b), lpartition(2, S16a, S16b)),
S17a = relation([{e,1},{b,2},{c,3},{b,4},{a,5},{0,6}]),
S17b = set([b,c,d]),
- ?line eval(partition(1, S17a, S17b), lpartition(1, S17a, S17b)),
+ eval(partition(1, S17a, S17b), lpartition(1, S17a, S17b)),
- ?line {'EXIT', {function_clause, _}} =
+ {'EXIT', {function_clause, _}} =
(catch partition({external, fun({A,_B}) -> A end}, set([]), E)),
Fun3 = fun(S) -> from_term({to_external(S),0}, {type(S),atom}) end,
S9a = set([1,2]),
S9b = from_term([{1,0}]),
- ?line eval(partition(Fun3, S9a, S9b), lpartition(Fun3, S9a, S9b)),
+ eval(partition(Fun3, S9a, S9b), lpartition(Fun3, S9a, S9b)),
S14a = relation([{1,a},{2,b},{3,c},{0,0}]),
S14b = set([b,c]),
- ?line eval(partition(2, S14a, S14b), lpartition(2, S14a, S14b)),
+ eval(partition(2, S14a, S14b), lpartition(2, S14a, S14b)),
S15a = relation([{a,1},{b,2},{c,3},{0,0}]),
S15b = set([b,c]),
- ?line eval(partition(1, S15a, S15b), lpartition(1, S15a, S15b)),
+ eval(partition(1, S15a, S15b), lpartition(1, S15a, S15b)),
%% set of sets
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch partition({external, fun(X) -> X end},
from_term([], [[atom]]), set([a]))),
S10 = from_term([], [[atom]]),
- ?line eval(partition(Id, S10, E), lpartition(Id, S10, E)),
+ eval(partition(Id, S10, E), lpartition(Id, S10, E)),
S10e = from_term([[a],[b]], [[atom]]),
- ?line eval(partition(Id, S10e, E), lpartition(Id, S10e, E)),
+ eval(partition(Id, S10e, E), lpartition(Id, S10e, E)),
S11a = from_term([], [[atom]]),
S11b = set([a]),
- ?line eval(partition(Id, S11a, S11b), lpartition(Id, S11a, S11b)),
+ eval(partition(Id, S11a, S11b), lpartition(Id, S11a, S11b)),
S12a = from_term([[[a],[b]], [[b],[c]], [[], [a,b]], [[1],[2]]]),
S12b = from_term([[a,b],[1,2,3],[b,c]]),
- ?line eval(partition(fun sofs:union/1, S12a, S12b),
- lpartition(fun sofs:union/1, S12a, S12b)),
+ eval(partition(fun sofs:union/1, S12a, S12b),
+ lpartition(fun sofs:union/1, S12a, S12b)),
Fun13 = fun(_) -> from_term([a]) end,
S13a = from_term([], [[atom]]),
S13b = from_term([], [[a]]),
- ?line eval(partition(Fun13, S13a, S13b), lpartition(Fun13, S13a, S13b)),
+ eval(partition(Fun13, S13a, S13b), lpartition(Fun13, S13a, S13b)),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch partition(fun(_) -> from_term([a]) end,
from_term([[1,2],[3,4]]),
from_term([], [atom]))),
Fun10 = fun(S) ->
- %% Cheating a lot...
- case to_external(S) of
- [1] -> from_term({1,1});
- _ -> S
- end
- end,
- ?line {'EXIT', {type_mismatch, _}} =
+ %% Cheating a lot...
+ case to_external(S) of
+ [1] -> from_term({1,1});
+ _ -> S
+ end
+ end,
+ {'EXIT', {type_mismatch, _}} =
(catch partition(Fun10, from_term([[1]]), from_term([], [[atom]]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch partition(fun(_) -> from_term({a}) end,
from_term([[a]]),
from_term([], [atom]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch partition(fun(_) -> {a} end,
from_term([[a]]),
from_term([], [atom]))),
@@ -1845,84 +1760,80 @@ partition_3(Conf) when is_list(Conf) ->
lpartition(F, S1, S2) ->
{restriction(F, S1, S2), drestriction(F, S1, S2)}.
-multiple_relative_product(suite) -> [];
-multiple_relative_product(doc) -> [""];
multiple_relative_product(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([]),
- ?line T = relation([{a,1},{a,11},{b,2},{c,3},{c,33},{d,4}]),
- ?line {'EXIT', {badarg, _}} =
+ E = empty_set(),
+ ER = relation([]),
+ T = relation([{a,1},{a,11},{b,2},{c,3},{c,33},{d,4}]),
+ {'EXIT', {badarg, _}} =
(catch multiple_relative_product({}, ER)),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch multiple_relative_product({}, relation([{a,b}]))),
- ?line eval(multiple_relative_product({E,T,T}, relation([], 3)), E),
- ?line eval(multiple_relative_product({T,T,T}, E), E),
- ?line eval(multiple_relative_product({T,T,T}, relation([],3)),
- from_term([],[{{atom,atom,atom},{atom,atom,atom}}])),
- ?line eval(multiple_relative_product({T,T,T},
+ eval(multiple_relative_product({E,T,T}, relation([], 3)), E),
+ eval(multiple_relative_product({T,T,T}, E), E),
+ eval(multiple_relative_product({T,T,T}, relation([],3)),
+ from_term([],[{{atom,atom,atom},{atom,atom,atom}}])),
+ eval(multiple_relative_product({T,T,T},
relation([{a,b,c},{c,d,a}])),
- from_term([{{a,b,c},{1,2,3}}, {{a,b,c},{1,2,33}},
- {{a,b,c},{11,2,3}}, {{a,b,c},{11,2,33}},
- {{c,d,a},{3,4,1}}, {{c,d,a},{3,4,11}},
- {{c,d,a},{33,4,1}}, {{c,d,a},{33,4,11}}])),
- ?line {'EXIT', {type_mismatch, _}} =
+ from_term([{{a,b,c},{1,2,3}}, {{a,b,c},{1,2,33}},
+ {{a,b,c},{11,2,3}}, {{a,b,c},{11,2,33}},
+ {{c,d,a},{3,4,1}}, {{c,d,a},{3,4,11}},
+ {{c,d,a},{33,4,1}}, {{c,d,a},{33,4,11}}])),
+ {'EXIT', {type_mismatch, _}} =
(catch multiple_relative_product({T}, from_term([{{a}}]))),
ok.
-digraph(suite) -> [];
-digraph(doc) -> [""];
digraph(Conf) when is_list(Conf) ->
- ?line T0 = ets:all(),
- ?line E = empty_set(),
- ?line R = relation([{a,b},{b,c},{c,d},{d,a}]),
- ?line F = relation_to_family(R),
+ T0 = ets:all(),
+ E = empty_set(),
+ R = relation([{a,b},{b,c},{c,d},{d,a}]),
+ F = relation_to_family(R),
Type = type(F),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch family_to_digraph(set([a]))),
digraph_fail(badarg, catch family_to_digraph(set([a]), [foo])),
digraph_fail(badarg, catch family_to_digraph(F, [foo])),
digraph_fail(cyclic, catch family_to_digraph(family([{a,[a]}]),[acyclic])),
- ?line G1 = family_to_digraph(E),
- ?line {'EXIT', {badarg, _}} = (catch digraph_to_family(G1, foo)),
- ?line {'EXIT', {badarg, _}} = (catch digraph_to_family(G1, atom)),
- ?line true = [] == to_external(digraph_to_family(G1)),
- ?line true = [] == to_external(digraph_to_family(G1, Type)),
- ?line true = digraph:delete(G1),
-
- ?line G1a = family_to_digraph(E, [protected]),
- ?line true = [] == to_external(digraph_to_family(G1a)),
- ?line true = [] == to_external(digraph_to_family(G1a, Type)),
- ?line true = digraph:delete(G1a),
-
- ?line G2 = family_to_digraph(F),
- ?line true = F == digraph_to_family(G2),
- ?line true = F == digraph_to_family(G2, type(F)),
- ?line true = digraph:delete(G2),
-
- ?line R2 = from_term([{{a},b},{{c},d}]),
- ?line F2 = relation_to_family(R2),
- ?line Type2 = type(F2),
- ?line G3 = family_to_digraph(F2, [protected]),
- ?line true = is_subset(F2, digraph_to_family(G3, Type2)),
- ?line true = digraph:delete(G3),
+ G1 = family_to_digraph(E),
+ {'EXIT', {badarg, _}} = (catch digraph_to_family(G1, foo)),
+ {'EXIT', {badarg, _}} = (catch digraph_to_family(G1, atom)),
+ true = [] == to_external(digraph_to_family(G1)),
+ true = [] == to_external(digraph_to_family(G1, Type)),
+ true = digraph:delete(G1),
+
+ G1a = family_to_digraph(E, [protected]),
+ true = [] == to_external(digraph_to_family(G1a)),
+ true = [] == to_external(digraph_to_family(G1a, Type)),
+ true = digraph:delete(G1a),
+
+ G2 = family_to_digraph(F),
+ true = F == digraph_to_family(G2),
+ true = F == digraph_to_family(G2, type(F)),
+ true = digraph:delete(G2),
+
+ R2 = from_term([{{a},b},{{c},d}]),
+ F2 = relation_to_family(R2),
+ Type2 = type(F2),
+ G3 = family_to_digraph(F2, [protected]),
+ true = is_subset(F2, digraph_to_family(G3, Type2)),
+ true = digraph:delete(G3),
Fl = 0.0, I = round(Fl),
if
Fl == I -> % term ordering
- ?line G4 = digraph:new(),
+ G4 = digraph:new(),
digraph:add_vertex(G4, Fl),
digraph:add_vertex(G4, I),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch digraph_to_family(G4, Type)),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch digraph_to_family(G4)),
- ?line true = digraph:delete(G4);
+ true = digraph:delete(G4);
true -> ok
end,
-
- ?line true = T0 == ets:all(),
+
+ true = T0 == ets:all(),
ok.
digraph_fail(ExitReason, Fail) ->
@@ -1932,32 +1843,28 @@ digraph_fail(ExitReason, Fail) ->
{true,2} -> ok
end.
-constant_function(suite) -> [];
-constant_function(doc) -> [""];
constant_function(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line C = from_term(3),
- ?line eval(constant_function(E, C), E),
- ?line eval(constant_function(set([a,b]), E), from_term([{a,[]},{b,[]}])),
- ?line eval(constant_function(set([a,b]), C), from_term([{a,3},{b,3}])),
- ?line {'EXIT', {badarg, _}} = (catch constant_function(C, C)),
- ?line {'EXIT', {badarg, _}} = (catch constant_function(set([]), foo)),
+ E = empty_set(),
+ C = from_term(3),
+ eval(constant_function(E, C), E),
+ eval(constant_function(set([a,b]), E), from_term([{a,[]},{b,[]}])),
+ eval(constant_function(set([a,b]), C), from_term([{a,3},{b,3}])),
+ {'EXIT', {badarg, _}} = (catch constant_function(C, C)),
+ {'EXIT', {badarg, _}} = (catch constant_function(set([]), foo)),
ok.
-misc(suite) -> [];
-misc(doc) -> [""];
misc(Conf) when is_list(Conf) ->
- % find "relational" part of relation:
- ?line S = relation([{a,b},{b,c},{b,d},{c,d}]),
+ %% find "relational" part of relation:
+ S = relation([{a,b},{b,c},{b,d},{c,d}]),
Id = fun(A) -> A end,
- ?line RR = relational_restriction(S),
- ?line eval(union(difference(partition(Id,S), partition(1,S))), RR),
- ?line eval(union(difference(partition(1,S), partition(Id,S))), RR),
-
- % the "functional" part:
- ?line eval(union(intersection(partition(1,S), partition(Id,S))),
- difference(S, RR)),
- ?line {'EXIT', {undef, _}} =
+ RR = relational_restriction(S),
+ eval(union(difference(partition(Id,S), partition(1,S))), RR),
+ eval(union(difference(partition(1,S), partition(Id,S))), RR),
+
+ %% the "functional" part:
+ eval(union(intersection(partition(1,S), partition(Id,S))),
+ difference(S, RR)),
+ {'EXIT', {undef, _}} =
(catch projection(fun external:foo/1, set([a,b,c]))),
ok.
@@ -1966,157 +1873,143 @@ relational_restriction(R) ->
family_to_relation(family_specification(Fun, relation_to_family(R))).
-family_specification(suite) -> [];
-family_specification(doc) -> [""];
family_specification(Conf) when is_list(Conf) ->
E = empty_set(),
%% internal
- ?line eval(family_specification(fun sofs:is_set/1, E), E),
- ?line {'EXIT', {badarg, _}} =
- (catch family_specification(fun sofs:is_set/1, set([]))),
- ?line F1 = from_term([{1,[1]}]),
- ?line eval(family_specification(fun sofs:is_set/1, F1), F1),
+ eval(family_specification(fun sofs:is_set/1, E), E),
+ {'EXIT', {badarg, _}} =
+ (catch family_specification(fun sofs:is_set/1, set([]))),
+ F1 = from_term([{1,[1]}]),
+ eval(family_specification(fun sofs:is_set/1, F1), F1),
Fun = fun(S) -> is_subset(S, set([0,1,2,3,4])) end,
- ?line F2 = family([{a,[1,2]},{b,[3,4,5]}]),
- ?line eval(family_specification(Fun, F2), family([{a,[1,2]}])),
- ?line F3 = from_term([{a,[]},{b,[]}]),
- ?line eval(family_specification(fun sofs:is_set/1, F3), F3),
+ F2 = family([{a,[1,2]},{b,[3,4,5]}]),
+ eval(family_specification(Fun, F2), family([{a,[1,2]}])),
+ F3 = from_term([{a,[]},{b,[]}]),
+ eval(family_specification(fun sofs:is_set/1, F3), F3),
Fun2 = fun(_) -> throw(fippla) end,
- ?line fippla = (catch family_specification(Fun2, family([{a,[1]}]))),
+ fippla = (catch family_specification(Fun2, family([{a,[1]}]))),
Fun3 = fun(_) -> neither_true_nor_false end,
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch family_specification(Fun3, F3)),
%% external
IsList = {external, fun(L) when is_list(L) -> true; (_) -> false end},
- ?line eval(family_specification(IsList, E), E),
- ?line eval(family_specification(IsList, F1), F1),
+ eval(family_specification(IsList, E), E),
+ eval(family_specification(IsList, F1), F1),
MF = {external, fun(L) -> lists:member(3, L) end},
- ?line eval(family_specification(MF, F2), family([{b,[3,4,5]}])),
- ?line fippla = (catch family_specification(Fun2, family([{a,[1]}]))),
- ?line {'EXIT', {badarg, _}} =
+ eval(family_specification(MF, F2), family([{b,[3,4,5]}])),
+ fippla = (catch family_specification(Fun2, family([{a,[1]}]))),
+ {'EXIT', {badarg, _}} =
(catch family_specification({external, Fun3}, F3)),
ok.
-family_domain_1(suite) -> [];
-family_domain_1(doc) -> [""];
family_domain_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = from_term([{a,[]},{b,[]}],[{atom,[{atom,atom}]}]),
- ?line EF = from_term([{a,[]},{b,[]}],[{atom,[atom]}]),
- ?line eval(family_domain(E), E),
- ?line eval(family_domain(ER), EF),
- ?line FR = from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),
- ?line eval(family_domain(FR), from_term([{a,[1,2,3]},{b,[]},{c,[4,5]}])),
- ?line eval(family_field(E), E),
- ?line eval(family_field(FR),
- from_term([{a,[a,b,c,1,2,3]},{b,[]},{c,[d,e,4,5]}])),
- ?line eval(family_domain(from_term([{{a},[{{1,[]},c}]}])),
- from_term([{{a},[{1,[]}]}])),
- ?line eval(family_domain(from_term([{{a},[{{1,[a]},c}]}])),
- from_term([{{a},[{1,[a]}]}])),
- ?line eval(family_domain(from_term([{{a},[]}])),
- from_term([{{a},[]}])),
- ?line eval(family_domain(from_term([], type(FR))),
- from_term([], [{atom,[atom]}])),
- ?line {'EXIT', {badarg, _}} = (catch family_domain(set([a]))),
- ?line {'EXIT', {badarg, _}} = (catch family_field(set([a]))),
- ?line {'EXIT', {badarg, _}} = (catch family_domain(set([{a,[b]}]))),
+ E = empty_set(),
+ ER = from_term([{a,[]},{b,[]}],[{atom,[{atom,atom}]}]),
+ EF = from_term([{a,[]},{b,[]}],[{atom,[atom]}]),
+ eval(family_domain(E), E),
+ eval(family_domain(ER), EF),
+ FR = from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),
+ eval(family_domain(FR), from_term([{a,[1,2,3]},{b,[]},{c,[4,5]}])),
+ eval(family_field(E), E),
+ eval(family_field(FR),
+ from_term([{a,[a,b,c,1,2,3]},{b,[]},{c,[d,e,4,5]}])),
+ eval(family_domain(from_term([{{a},[{{1,[]},c}]}])),
+ from_term([{{a},[{1,[]}]}])),
+ eval(family_domain(from_term([{{a},[{{1,[a]},c}]}])),
+ from_term([{{a},[{1,[a]}]}])),
+ eval(family_domain(from_term([{{a},[]}])),
+ from_term([{{a},[]}])),
+ eval(family_domain(from_term([], type(FR))),
+ from_term([], [{atom,[atom]}])),
+ {'EXIT', {badarg, _}} = (catch family_domain(set([a]))),
+ {'EXIT', {badarg, _}} = (catch family_field(set([a]))),
+ {'EXIT', {badarg, _}} = (catch family_domain(set([{a,[b]}]))),
ok.
-family_range_1(suite) -> [];
-family_range_1(doc) -> [""];
family_range_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = from_term([{a,[]},{b,[]}],[{atom,[{atom,atom}]}]),
- ?line EF = from_term([{a,[]},{b,[]}],[{atom,[atom]}]),
- ?line eval(family_range(E), E),
- ?line eval(family_range(ER), EF),
- ?line FR = from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),
- ?line eval(family_range(FR), from_term([{a,[a,b,c]},{b,[]},{c,[d,e]}])),
- ?line eval(family_range(from_term([{{a},[{c,{1,[a]}}]}])),
- from_term([{{a},[{1,[a]}]}])),
- ?line eval(family_range(from_term([{{a},[{c,{1,[]}}]}])),
- from_term([{{a},[{1,[]}]}])),
- ?line eval(family_range(from_term([{{a},[]}])),
- from_term([{{a},[]}])),
- ?line eval(family_range(from_term([], type(FR))),
- from_term([], [{atom,[atom]}])),
- ?line {'EXIT', {badarg, _}} = (catch family_range(set([a]))),
- ?line {'EXIT', {badarg, _}} = (catch family_range(set([{a,[b]}]))),
+ E = empty_set(),
+ ER = from_term([{a,[]},{b,[]}],[{atom,[{atom,atom}]}]),
+ EF = from_term([{a,[]},{b,[]}],[{atom,[atom]}]),
+ eval(family_range(E), E),
+ eval(family_range(ER), EF),
+ FR = from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),
+ eval(family_range(FR), from_term([{a,[a,b,c]},{b,[]},{c,[d,e]}])),
+ eval(family_range(from_term([{{a},[{c,{1,[a]}}]}])),
+ from_term([{{a},[{1,[a]}]}])),
+ eval(family_range(from_term([{{a},[{c,{1,[]}}]}])),
+ from_term([{{a},[{1,[]}]}])),
+ eval(family_range(from_term([{{a},[]}])),
+ from_term([{{a},[]}])),
+ eval(family_range(from_term([], type(FR))),
+ from_term([], [{atom,[atom]}])),
+ {'EXIT', {badarg, _}} = (catch family_range(set([a]))),
+ {'EXIT', {badarg, _}} = (catch family_range(set([{a,[b]}]))),
ok.
-family_to_relation_1(suite) -> [];
-family_to_relation_1(doc) -> [""];
family_to_relation_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line ER = relation([]),
- ?line EF = family([]),
- ?line eval(family_to_relation(E), E),
- ?line eval(family_to_relation(EF), ER),
- ?line eval(sofs:fam2rel(EF), ER),
- ?line F = family([{a,[]},{b,[1]},{c,[7,9,11]}]),
- ?line eval(family_to_relation(F), relation([{b,1},{c,7},{c,9},{c,11}])),
- ?line {'EXIT', {badarg, _}} = (catch family_to_relation(set([a]))),
+ E = empty_set(),
+ ER = relation([]),
+ EF = family([]),
+ eval(family_to_relation(E), E),
+ eval(family_to_relation(EF), ER),
+ eval(sofs:fam2rel(EF), ER),
+ F = family([{a,[]},{b,[1]},{c,[7,9,11]}]),
+ eval(family_to_relation(F), relation([{b,1},{c,7},{c,9},{c,11}])),
+ {'EXIT', {badarg, _}} = (catch family_to_relation(set([a]))),
ok.
-union_of_family_1(suite) -> [];
-union_of_family_1(doc) -> [""];
union_of_family_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line EF = from_term([{a,[]},{b,[]}],[{atom,[atom]}]),
- ?line eval(union_of_family(E), E),
- ?line eval(union_of_family(EF), set([])),
- ?line eval(union_of_family(family([])), set([])),
- ?line FR = from_term([{a,[1,2,3]},{b,[]},{c,[4,5]}]),
- ?line eval(union_of_family(FR), set([1,2,3,4,5])),
- ?line eval(union_of_family(sofs:family([{a,[1,2]},{b,[1,2]}])),
- set([1,2])),
- ?line {'EXIT', {badarg, _}} = (catch union_of_family(set([a]))),
+ E = empty_set(),
+ EF = from_term([{a,[]},{b,[]}],[{atom,[atom]}]),
+ eval(union_of_family(E), E),
+ eval(union_of_family(EF), set([])),
+ eval(union_of_family(family([])), set([])),
+ FR = from_term([{a,[1,2,3]},{b,[]},{c,[4,5]}]),
+ eval(union_of_family(FR), set([1,2,3,4,5])),
+ eval(union_of_family(sofs:family([{a,[1,2]},{b,[1,2]}])),
+ set([1,2])),
+ {'EXIT', {badarg, _}} = (catch union_of_family(set([a]))),
ok.
-intersection_of_family_1(suite) -> [];
-intersection_of_family_1(doc) -> [""];
intersection_of_family_1(Conf) when is_list(Conf) ->
- ?line EF = from_term([{a,[]},{b,[]}],[{atom,[atom]}]),
- ?line eval(intersection_of_family(EF), set([])),
- ?line FR = from_term([{a,[1,2,3]},{b,[2,3]},{c,[3,4,5]}]),
- ?line eval(intersection_of_family(FR), set([3])),
- ?line {'EXIT', {badarg, _}} =
+ EF = from_term([{a,[]},{b,[]}],[{atom,[atom]}]),
+ eval(intersection_of_family(EF), set([])),
+ FR = from_term([{a,[1,2,3]},{b,[2,3]},{c,[3,4,5]}]),
+ eval(intersection_of_family(FR), set([3])),
+ {'EXIT', {badarg, _}} =
(catch intersection_of_family(family([]))),
- ?line EE = from_term([], [[atom]]),
- ?line {'EXIT', {badarg, _}} = (catch intersection_of_family(EE)),
- ?line {'EXIT', {badarg, _}} = (catch intersection_of_family(set([a]))),
+ EE = from_term([], [[atom]]),
+ {'EXIT', {badarg, _}} = (catch intersection_of_family(EE)),
+ {'EXIT', {badarg, _}} = (catch intersection_of_family(set([a]))),
ok.
-family_projection(suite) -> [];
-family_projection(doc) -> [""];
family_projection(Conf) when is_list(Conf) ->
SSType = [{atom,[[atom]]}],
SRType = [{atom,[{atom,atom}]}],
- ?line E = empty_set(),
-
- ?line eval(family_projection(fun(X) -> X end, family([])), E),
- ?line L1 = [{a,[]}],
- ?line eval(family_projection(fun sofs:union/1, E), E),
- ?line eval(family_projection(fun sofs:union/1, from_term(L1, SSType)),
- family(L1)),
- ?line {'EXIT', {badarg, _}} =
+ E = empty_set(),
+
+ eval(family_projection(fun(X) -> X end, family([])), E),
+ L1 = [{a,[]}],
+ eval(family_projection(fun sofs:union/1, E), E),
+ eval(family_projection(fun sofs:union/1, from_term(L1, SSType)),
+ family(L1)),
+ {'EXIT', {badarg, _}} =
(catch family_projection(fun sofs:union/1, set([]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch family_projection(fun sofs:union/1, from_term([{1,[1]}]))),
- ?line F2 = from_term([{a,[[1],[2]]},{b,[[3,4],[5]]}], SSType),
- ?line eval(family_projection(fun sofs:union/1, F2),
- family_union(F2)),
+ F2 = from_term([{a,[[1],[2]]},{b,[[3,4],[5]]}], SSType),
+ eval(family_projection(fun sofs:union/1, F2),
+ family_union(F2)),
- ?line F3 = from_term([{1,[{a,b},{b,c},{c,d}]},{3,[]},{5,[{3,5}]}],
- SRType),
- ?line eval(family_projection(fun sofs:domain/1, F3), family_domain(F3)),
- ?line eval(family_projection(fun sofs:range/1, F3), family_range(F3)),
+ F3 = from_term([{1,[{a,b},{b,c},{c,d}]},{3,[]},{5,[{3,5}]}],
+ SRType),
+ eval(family_projection(fun sofs:domain/1, F3), family_domain(F3)),
+ eval(family_projection(fun sofs:range/1, F3), family_range(F3)),
- ?line eval(family_projection(fun(_) -> E end, family([{a,[b,c]}])),
- from_term([{a,[]}])),
+ eval(family_projection(fun(_) -> E end, family([{a,[b,c]}])),
+ from_term([{a,[]}])),
Fun1 = fun(S) ->
case to_external(S) of
@@ -2124,264 +2017,252 @@ family_projection(Conf) when is_list(Conf) ->
_ -> S
end
end,
- ?line eval(family_projection(Fun1, family([{a,[1]}])),
- from_term([{a,{1,1}}])),
+ eval(family_projection(Fun1, family([{a,[1]}])),
+ from_term([{a,{1,1}}])),
Fun2 = fun(_) -> throw(fippla) end,
- ?line fippla =
+ fippla =
(catch family_projection(Fun2, family([{a,[1]}]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch family_projection(Fun1, from_term([{1,[1]},{2,[2]}]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch family_projection(Fun1, from_term([{1,[1]},{0,[0]}]))),
- ?line eval(family_projection(fun(_) -> E end, from_term([{a,[]}])),
- from_term([{a,[]}])),
+ eval(family_projection(fun(_) -> E end, from_term([{a,[]}])),
+ from_term([{a,[]}])),
F4 = from_term([{a,[{1,2,3}]},{b,[{4,5,6}]},{c,[]},{m3,[]}]),
Z = from_term(0),
- ?line eval(family_projection(fun(S) -> local_adjoin(S, Z) end, F4),
- from_term([{a,[{{1,2,3},0}]},{b,[{{4,5,6},0}]},{c,[]},{m3,[]}])),
- ?line {'EXIT', {badarg, _}} =
+ eval(family_projection(fun(S) -> local_adjoin(S, Z) end, F4),
+ from_term([{a,[{{1,2,3},0}]},{b,[{{4,5,6},0}]},{c,[]},{m3,[]}])),
+ {'EXIT', {badarg, _}} =
(catch family_projection({external, fun(X) -> X end},
from_term([{1,[1]}]))),
%% ordered set element
- ?line eval(family_projection(fun(_) -> from_term(a, atom) end,
- from_term([{1,[a]}])),
- from_term([{1,a}])),
+ eval(family_projection(fun(_) -> from_term(a, atom) end,
+ from_term([{1,[a]}])),
+ from_term([{1,a}])),
ok.
-family_difference(suite) -> [];
-family_difference(doc) -> [""];
family_difference(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line EF = family([]),
- ?line F9 = from_term([{b,[b,c]}]),
- ?line F10 = from_term([{a,[b,c]}]),
- ?line eval(family_difference(E, E), E),
- ?line eval(family_difference(E, F10), from_term([], type(F10))),
- ?line eval(family_difference(F10, E), F10),
- ?line eval(family_difference(F9, F10), F9),
- ?line eval(family_difference(F10, F10), family([{a,[]}])),
- ?line F20 = from_term([{a,[1,2,3]},{b,[1,2,3]},{c,[1,2,3]}]),
- ?line F21 = from_term([{b,[1,2,3]},{c,[1,2,3]}]),
- ?line eval(family_difference(F20, from_term([{a,[2]}])),
- from_term([{a,[1,3]},{b,[1,2,3]},{c,[1,2,3]}])),
- ?line eval(family_difference(F20, from_term([{0,[2]},{q,[1,2]}])), F20),
- ?line eval(family_difference(F20, F21),
- from_term([{a,[1,2,3]},{b,[]},{c,[]}])),
-
- ?line eval(family_difference(from_term([{e,[f,g]}]), family([])),
- from_term([{e,[f,g]}])),
- ?line eval(family_difference(from_term([{e,[f,g]}]), EF),
- from_term([{e,[f,g]}])),
- ?line eval(family_difference(from_term([{a,[a,b,c,d]},{c,[b,c]}]),
- from_term([{a,[b,c]},{b,[d]},{d,[e,f]}])),
- from_term([{a,[a,d]},{c,[b,c]}])),
- ?line {'EXIT', {badarg, _}} =
+ E = empty_set(),
+ EF = family([]),
+ F9 = from_term([{b,[b,c]}]),
+ F10 = from_term([{a,[b,c]}]),
+ eval(family_difference(E, E), E),
+ eval(family_difference(E, F10), from_term([], type(F10))),
+ eval(family_difference(F10, E), F10),
+ eval(family_difference(F9, F10), F9),
+ eval(family_difference(F10, F10), family([{a,[]}])),
+ F20 = from_term([{a,[1,2,3]},{b,[1,2,3]},{c,[1,2,3]}]),
+ F21 = from_term([{b,[1,2,3]},{c,[1,2,3]}]),
+ eval(family_difference(F20, from_term([{a,[2]}])),
+ from_term([{a,[1,3]},{b,[1,2,3]},{c,[1,2,3]}])),
+ eval(family_difference(F20, from_term([{0,[2]},{q,[1,2]}])), F20),
+ eval(family_difference(F20, F21),
+ from_term([{a,[1,2,3]},{b,[]},{c,[]}])),
+
+ eval(family_difference(from_term([{e,[f,g]}]), family([])),
+ from_term([{e,[f,g]}])),
+ eval(family_difference(from_term([{e,[f,g]}]), EF),
+ from_term([{e,[f,g]}])),
+ eval(family_difference(from_term([{a,[a,b,c,d]},{c,[b,c]}]),
+ from_term([{a,[b,c]},{b,[d]},{d,[e,f]}])),
+ from_term([{a,[a,d]},{c,[b,c]}])),
+ {'EXIT', {badarg, _}} =
(catch family_difference(set([]), set([]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch family_difference(from_term([{a,[b,c]}]),
from_term([{e,[{f}]}]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch family_difference(from_term([{a,[b]}]),
from_term([{c,[d]}], [{i,[s]}]))),
ok.
-family_intersection_1(suite) -> [];
-family_intersection_1(doc) -> [""];
family_intersection_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line EF = family([]),
- ?line ES = from_term([], [{atom,[[atom]]}]),
- ?line eval(family_intersection(E), E),
- ?line {'EXIT', {badarg, _}} = (catch family_intersection(EF)),
- ?line eval(family_intersection(ES), EF),
- ?line {'EXIT', {badarg, _}} = (catch family_intersection(set([]))),
- ?line {'EXIT', {badarg, _}} =
+ E = empty_set(),
+ EF = family([]),
+ ES = from_term([], [{atom,[[atom]]}]),
+ eval(family_intersection(E), E),
+ {'EXIT', {badarg, _}} = (catch family_intersection(EF)),
+ eval(family_intersection(ES), EF),
+ {'EXIT', {badarg, _}} = (catch family_intersection(set([]))),
+ {'EXIT', {badarg, _}} =
(catch family_intersection(from_term([{a,[1,2]}]))),
- ?line F1 = from_term([{a,[[1],[2],[2,3]]},{b,[]},{c,[[4]]}]),
- ?line {'EXIT', {badarg, _}} = (catch family_intersection(F1)),
- ?line F2 = from_term([{b,[[1],[2],[2,3]]},{a,[]},{c,[[4]]}]),
- ?line {'EXIT', {badarg, _}} = (catch family_intersection(F2)),
- ?line F3 = from_term([{a,[[1,2,3],[2],[2,3]]},{c,[[4,5,6],[5,6,7]]}]),
- ?line eval(family_intersection(F3), family([{a,[2]},{c,[5,6]}])),
+ F1 = from_term([{a,[[1],[2],[2,3]]},{b,[]},{c,[[4]]}]),
+ {'EXIT', {badarg, _}} = (catch family_intersection(F1)),
+ F2 = from_term([{b,[[1],[2],[2,3]]},{a,[]},{c,[[4]]}]),
+ {'EXIT', {badarg, _}} = (catch family_intersection(F2)),
+ F3 = from_term([{a,[[1,2,3],[2],[2,3]]},{c,[[4,5,6],[5,6,7]]}]),
+ eval(family_intersection(F3), family([{a,[2]},{c,[5,6]}])),
ok.
-family_intersection_2(suite) -> [];
-family_intersection_2(doc) -> [""];
family_intersection_2(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line EF = family([]),
- ?line F1 = from_term([{a,[1,2]},{b,[4,5]},{c,[7,8]},{d,[10,11]}]),
- ?line F2 = from_term([{c,[6,7]},{d,[9,10,11]},{q,[1]}]),
- ?line F3 = from_term([{a,[1,2]},{b,[4,5]},{c,[6,7,8]},{d,[9,10,11]},
- {q,[1]}]),
-
- ?line eval(family_intersection(E, E), E),
- ?line eval(family_intersection(EF, EF), EF),
- ?line eval(family_intersection(F1, F2),
- from_term([{c,[7]},{d,[10,11]}])),
- ?line eval(family_intersection(F1, F3), F1),
- ?line eval(family_intersection(F2, F3), F2),
-
- ?line eval(family_intersection(EF, from_term([{e,[f,g]}])), EF),
- ?line eval(family_intersection(E, from_term([{e,[f,g]}])), EF),
- ?line eval(family_intersection(from_term([{e,[f,g]}]), EF), EF),
- ?line eval(family_intersection(from_term([{e,[f,g]}]), E), EF),
- ?line {'EXIT', {type_mismatch, _}} =
+ E = empty_set(),
+ EF = family([]),
+ F1 = from_term([{a,[1,2]},{b,[4,5]},{c,[7,8]},{d,[10,11]}]),
+ F2 = from_term([{c,[6,7]},{d,[9,10,11]},{q,[1]}]),
+ F3 = from_term([{a,[1,2]},{b,[4,5]},{c,[6,7,8]},{d,[9,10,11]},
+ {q,[1]}]),
+
+ eval(family_intersection(E, E), E),
+ eval(family_intersection(EF, EF), EF),
+ eval(family_intersection(F1, F2),
+ from_term([{c,[7]},{d,[10,11]}])),
+ eval(family_intersection(F1, F3), F1),
+ eval(family_intersection(F2, F3), F2),
+
+ eval(family_intersection(EF, from_term([{e,[f,g]}])), EF),
+ eval(family_intersection(E, from_term([{e,[f,g]}])), EF),
+ eval(family_intersection(from_term([{e,[f,g]}]), EF), EF),
+ eval(family_intersection(from_term([{e,[f,g]}]), E), EF),
+ {'EXIT', {type_mismatch, _}} =
(catch family_intersection(from_term([{a,[b,c]}]),
from_term([{e,[{f}]}]))),
- ?line F11 = family([{a,[1,2,3]},{b,[0,2,4]},{c,[0,3,6,9]}]),
- ?line eval(union_of_family(F11), set([0,1,2,3,4,6,9])),
- ?line F12 = from_term([{a,[1,2,3,4]},{b,[0,2,4]},{c,[2,3,4,5]}]),
- ?line eval(intersection_of_family(F12), set([2,4])),
+ F11 = family([{a,[1,2,3]},{b,[0,2,4]},{c,[0,3,6,9]}]),
+ eval(union_of_family(F11), set([0,1,2,3,4,6,9])),
+ F12 = from_term([{a,[1,2,3,4]},{b,[0,2,4]},{c,[2,3,4,5]}]),
+ eval(intersection_of_family(F12), set([2,4])),
ok.
-family_union_1(suite) -> [];
-family_union_1(doc) -> [""];
family_union_1(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line EF = family([]),
- ?line ES = from_term([], [{atom,[[atom]]}]),
- ?line eval(family_union(E), E),
- ?line eval(family_union(ES), EF),
- ?line {'EXIT', {badarg, _}} = (catch family_union(set([]))),
- ?line {'EXIT', {badarg, _}} =
+ E = empty_set(),
+ EF = family([]),
+ ES = from_term([], [{atom,[[atom]]}]),
+ eval(family_union(E), E),
+ eval(family_union(ES), EF),
+ {'EXIT', {badarg, _}} = (catch family_union(set([]))),
+ {'EXIT', {badarg, _}} =
(catch family_union(from_term([{a,[1,2]}]))),
- ?line eval(family_union(from_term([{a,[[1],[2],[2,3]]},{b,[]},{c,[[4]]}])),
- family([{a,[1,2,3]},{b,[]},{c,[4]}])),
+ eval(family_union(from_term([{a,[[1],[2],[2,3]]},{b,[]},{c,[[4]]}])),
+ family([{a,[1,2,3]},{b,[]},{c,[4]}])),
ok.
-family_union_2(suite) -> [];
-family_union_2(doc) -> [""];
family_union_2(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
- ?line EF = family([]),
- ?line F1 = from_term([{a,[1,2]},{b,[4,5]},{c,[7,8]},{d,[10,11]}]),
- ?line F2 = from_term([{c,[6,7]},{d,[9,10,11]},{q,[1]}]),
- ?line F3 = from_term([{a,[1,2]},{b,[4,5]},{c,[6,7,8]},{d,[9,10,11]},
- {q,[1]}]),
-
- ?line eval(family_union(E, E), E),
- ?line eval(family_union(F1, E), F1),
- ?line eval(family_union(E, F2), F2),
- ?line eval(family_union(F1, F2), F3),
- ?line eval(family_union(F2, F1), F3),
-
- ?line eval(family_union(E, from_term([{e,[f,g]}])),
- from_term([{e,[f,g]}])),
- ?line eval(family_union(EF, from_term([{e,[f,g]}])),
- from_term([{e,[f,g]}])),
- ?line eval(family_union(from_term([{e,[f,g]}]), E),
- from_term([{e,[f,g]}])),
- ?line {'EXIT', {badarg, _}} =
+ E = empty_set(),
+ EF = family([]),
+ F1 = from_term([{a,[1,2]},{b,[4,5]},{c,[7,8]},{d,[10,11]}]),
+ F2 = from_term([{c,[6,7]},{d,[9,10,11]},{q,[1]}]),
+ F3 = from_term([{a,[1,2]},{b,[4,5]},{c,[6,7,8]},{d,[9,10,11]},
+ {q,[1]}]),
+
+ eval(family_union(E, E), E),
+ eval(family_union(F1, E), F1),
+ eval(family_union(E, F2), F2),
+ eval(family_union(F1, F2), F3),
+ eval(family_union(F2, F1), F3),
+
+ eval(family_union(E, from_term([{e,[f,g]}])),
+ from_term([{e,[f,g]}])),
+ eval(family_union(EF, from_term([{e,[f,g]}])),
+ from_term([{e,[f,g]}])),
+ eval(family_union(from_term([{e,[f,g]}]), E),
+ from_term([{e,[f,g]}])),
+ {'EXIT', {badarg, _}} =
(catch family_union(set([]),set([]))),
- ?line {'EXIT', {type_mismatch, _}} =
+ {'EXIT', {type_mismatch, _}} =
(catch family_union(from_term([{a,[b,c]}]),
from_term([{e,[{f}]}]))),
ok.
-partition_family(suite) -> [];
-partition_family(doc) -> [""];
partition_family(Conf) when is_list(Conf) ->
- ?line E = empty_set(),
+ E = empty_set(),
%% set of ordered sets
- ?line ER = relation([]),
- ?line EF = from_term([], [{atom,[{atom,atom}]}]),
-
- ?line eval(partition_family(1, E), E),
- ?line eval(partition_family(2, E), E),
- ?line eval(partition_family(fun sofs:union/1, E), E),
- ?line eval(partition_family(1, ER), EF),
- ?line eval(partition_family(2, ER), EF),
- ?line {'EXIT', {badarg, _}} = (catch partition_family(1, set([]))),
- ?line {'EXIT', {badarg, _}} = (catch partition_family(2, set([]))),
- ?line {'EXIT', {function_clause, _}} =
+ ER = relation([]),
+ EF = from_term([], [{atom,[{atom,atom}]}]),
+
+ eval(partition_family(1, E), E),
+ eval(partition_family(2, E), E),
+ eval(partition_family(fun sofs:union/1, E), E),
+ eval(partition_family(1, ER), EF),
+ eval(partition_family(2, ER), EF),
+ {'EXIT', {badarg, _}} = (catch partition_family(1, set([]))),
+ {'EXIT', {badarg, _}} = (catch partition_family(2, set([]))),
+ {'EXIT', {function_clause, _}} =
(catch partition_family(fun({_A,B}) -> {B} end, from_term([{1}]))),
- ?line eval(partition_family(1, relation([{1,a},{1,b},{2,c},{2,d}])),
- from_term([{1,[{1,a},{1,b}]},{2,[{2,c},{2,d}]}])),
- ?line eval(partition_family(1, relation([{1,a},{2,b}])),
- from_term([{1,[{1,a}]},{2,[{2,b}]}])),
- ?line eval(partition_family(2, relation([{1,a},{1,b},{2,a},{2,b},{3,c}])),
- from_term([{a,[{1,a},{2,a}]},{b,[{1,b},{2,b}]},{c,[{3,c}]}])),
- ?line eval(partition_family(2, relation([{1,a}])),
- from_term([{a,[{1,a}]}])),
- ?line eval(partition_family(2, relation([{1,a},{2,a},{3,a}])),
- from_term([{a,[{1,a},{2,a},{3,a}]}])),
- ?line eval(partition_family(2, relation([{1,a},{2,b}])),
- from_term([{a,[{1,a}]},{b,[{2,b}]}])),
- ?line F13 = from_term([{a,b,c},{a,b,d},{b,b,c},{a,c,c},{a,c,d},{b,c,c}]),
- ?line eval(partition_family(2, F13),
- from_term([{b,[{a,b,c},{a,b,d},{b,b,c}]},
- {c,[{a,c,c},{a,c,d},{b,c,c}]}])),
+ eval(partition_family(1, relation([{1,a},{1,b},{2,c},{2,d}])),
+ from_term([{1,[{1,a},{1,b}]},{2,[{2,c},{2,d}]}])),
+ eval(partition_family(1, relation([{1,a},{2,b}])),
+ from_term([{1,[{1,a}]},{2,[{2,b}]}])),
+ eval(partition_family(2, relation([{1,a},{1,b},{2,a},{2,b},{3,c}])),
+ from_term([{a,[{1,a},{2,a}]},{b,[{1,b},{2,b}]},{c,[{3,c}]}])),
+ eval(partition_family(2, relation([{1,a}])),
+ from_term([{a,[{1,a}]}])),
+ eval(partition_family(2, relation([{1,a},{2,a},{3,a}])),
+ from_term([{a,[{1,a},{2,a},{3,a}]}])),
+ eval(partition_family(2, relation([{1,a},{2,b}])),
+ from_term([{a,[{1,a}]},{b,[{2,b}]}])),
+ F13 = from_term([{a,b,c},{a,b,d},{b,b,c},{a,c,c},{a,c,d},{b,c,c}]),
+ eval(partition_family(2, F13),
+ from_term([{b,[{a,b,c},{a,b,d},{b,b,c}]},
+ {c,[{a,c,c},{a,c,d},{b,c,c}]}])),
Fun1 = {external, fun({A,_B}) -> {A} end},
- ?line eval(partition_family(Fun1, relation([{a,1},{a,2},{b,3}])),
- from_term([{{a},[{a,1},{a,2}]},{{b},[{b,3}]}])),
+ eval(partition_family(Fun1, relation([{a,1},{a,2},{b,3}])),
+ from_term([{{a},[{a,1},{a,2}]},{{b},[{b,3}]}])),
Fun2 = fun(S) -> {A,_B} = to_external(S), from_term({A}) end,
- ?line eval(partition_family(Fun2, relation([{a,1},{a,2},{b,3}])),
- from_term([{{a},[{a,1},{a,2}]},{{b},[{b,3}]}])),
+ eval(partition_family(Fun2, relation([{a,1},{a,2},{b,3}])),
+ from_term([{{a},[{a,1},{a,2}]},{{b},[{b,3}]}])),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch partition_family({external, fun({A,_}) -> {A,0} end},
from_term([{1,a}]))),
- ?line [{{atom,atom},[{atom,atom,atom,atom}]}] =
+ [{{atom,atom},[{atom,atom,atom,atom}]}] =
type(partition_family({external, fun({A,_B,C,_D}) -> {C,A} end},
relation([],4))),
Fun3 = fun(S) -> from_term({to_external(S),0}, {type(S),atom}) end,
- ?line eval(partition_family(Fun3, E), E),
- ?line eval(partition_family(Fun3, set([a,b])),
- from_term([{{a,0},[a]}, {{b,0},[b]}])),
- ?line eval(partition_family(Fun3, relation([{a,1},{b,2}])),
- from_term([{{{a,1},0},[{a,1}]},{{{b,2},0},[{b,2}]}])),
- ?line eval(partition_family(Fun3, from_term([[a],[b]])),
- from_term([{{[a],0},[[a]]}, {{[b],0},[[b]]}])),
- ?line partition_family({external, fun(X) -> X end}, E),
+ eval(partition_family(Fun3, E), E),
+ eval(partition_family(Fun3, set([a,b])),
+ from_term([{{a,0},[a]}, {{b,0},[b]}])),
+ eval(partition_family(Fun3, relation([{a,1},{b,2}])),
+ from_term([{{{a,1},0},[{a,1}]},{{{b,2},0},[{b,2}]}])),
+ eval(partition_family(Fun3, from_term([[a],[b]])),
+ from_term([{{[a],0},[[a]]}, {{[b],0},[[b]]}])),
+ partition_family({external, fun(X) -> X end}, E),
F = 0.0, I = round(F),
- ?line FR = relation([{I,a},{F,b}]),
+ FR = relation([{I,a},{F,b}]),
if
F == I -> % term ordering
- ?line true = (1 =:= no_elements(partition_family(1, FR)));
+ true = (1 =:= no_elements(partition_family(1, FR)));
true ->
- ?line eval(partition_family(1, FR),
- from_term([{I,[{I,a}]},{F,[{F,b}]}]))
+ eval(partition_family(1, FR),
+ from_term([{I,[{I,a}]},{F,[{F,b}]}]))
end,
%% set of sets
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch partition_family({external, fun(X) -> X end},
from_term([], [[atom]]))),
- ?line {'EXIT', {badarg, _}} =
+ {'EXIT', {badarg, _}} =
(catch partition_family({external, fun(X) -> X end},
from_term([[a]]))),
- ?line eval(partition_family(fun sofs:union/1,
- from_term([[[1],[1,2]], [[1,2]]])),
- from_term([{[1,2], [[[1],[1,2]],[[1,2]]]}])),
- ?line eval(partition_family(fun(X) -> X end,
- from_term([[1],[1,2],[1,2,3]])),
- from_term([{[1],[[1]]},{[1,2],[[1,2]]},{[1,2,3],[[1,2,3]]}])),
-
- ?line eval(partition_family(fun(_) -> from_term([a]) end,
- from_term([], [[atom]])),
- E),
+ eval(partition_family(fun sofs:union/1,
+ from_term([[[1],[1,2]], [[1,2]]])),
+ from_term([{[1,2], [[[1],[1,2]],[[1,2]]]}])),
+ eval(partition_family(fun(X) -> X end,
+ from_term([[1],[1,2],[1,2,3]])),
+ from_term([{[1],[[1]]},{[1,2],[[1,2]]},{[1,2,3],[[1,2,3]]}])),
+
+ eval(partition_family(fun(_) -> from_term([a]) end,
+ from_term([], [[atom]])),
+ E),
Fun10 = fun(S) ->
- %% Cheating a lot...
- case to_external(S) of
- [1] -> from_term({1,1});
- _ -> S
- end
- end,
+ %% Cheating a lot...
+ case to_external(S) of
+ [1] -> from_term({1,1});
+ _ -> S
+ end
+ end,
- ?line eval(partition_family(Fun10, from_term([[1]])),
- from_term([{{1,1},[[1]]}])),
- ?line eval(partition_family(fun(_) -> from_term({a}) end,
- from_term([[a]])),
- from_term([{{a},[[a]]}])),
- ?line {'EXIT', {badarg, _}} =
- (catch partition_family(fun(_) -> {a} end, from_term([[a]]))),
+ eval(partition_family(Fun10, from_term([[1]])),
+ from_term([{{1,1},[[1]]}])),
+ eval(partition_family(fun(_) -> from_term({a}) end,
+ from_term([[a]])),
+ from_term([{{a},[[a]]}])),
+ {'EXIT', {badarg, _}} =
+ (catch partition_family(fun(_) -> {a} end, from_term([[a]]))),
ok.
%% Not meant to be efficient...
diff --git a/lib/stdlib/test/stdlib_SUITE.erl b/lib/stdlib/test/stdlib_SUITE.erl
index fa9d0f6b55..f7064c4169 100644
--- a/lib/stdlib/test/stdlib_SUITE.erl
+++ b/lib/stdlib/test/stdlib_SUITE.erl
@@ -21,7 +21,7 @@
%%% Purpose:Stdlib application test suite.
%%%-----------------------------------------------------------------
-module(stdlib_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-compile(export_all).
@@ -51,15 +51,12 @@ init_per_testcase(_Case, Config) ->
end_per_testcase(_Case, _Config) ->
ok.
-%
-% Test cases starts here.
-%
-app_test(suite) ->
- [];
-app_test(doc) ->
- ["Application consistency test."];
+%%
+%% Test cases starts here.
+%%
+%% Application consistency test.
app_test(Config) when is_list(Config) ->
- ?t:app_test(stdlib),
+ test_server:app_test(stdlib),
ok.
%% Test that appup allows upgrade from/downgrade to a maximum of one
@@ -160,10 +157,8 @@ check_appup([],_,_) ->
-include_lib("stdlib/include/assert.hrl").
-include_lib("stdlib/include/assert.hrl"). % test repeated inclusion
-assert_test(suite) ->
- [];
-assert_test(doc) ->
- ["Assert macros test."];
+
+%% Assert macros test.
assert_test(_Config) ->
ok = ?assert(true),
{'EXIT',{{assert, _},_}} = (catch ?assert(false)),
diff --git a/lib/stdlib/test/string_SUITE.erl b/lib/stdlib/test/string_SUITE.erl
index 53eea6f180..b5d221732e 100644
--- a/lib/stdlib/test/string_SUITE.erl
+++ b/lib/stdlib/test/string_SUITE.erl
@@ -21,28 +21,24 @@
%%% Purpose: string test suite.
%%%-----------------------------------------------------------------
-module(string_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
-
-% Test server specific exports
+%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
-export([init_per_testcase/2, end_per_testcase/2]).
-% Test cases must be exported.
+%% Test cases must be exported.
-export([len/1,equal/1,concat/1,chr_rchr/1,str_rstr/1]).
-export([span_cspan/1,substr/1,tokens/1,chars/1]).
-export([copies/1,words/1,strip/1,sub_word/1,left_right/1]).
-export([sub_string/1,centre/1, join/1]).
-export([to_integer/1,to_float/1]).
-export([to_upper_to_lower/1]).
-%%
-%% all/1
-%%
-suite() -> [{ct_hooks,[ts_install_cth]}].
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[len, equal, concat, chr_rchr, str_rstr, span_cspan,
@@ -67,155 +63,125 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_Case, Config) ->
- ?line Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+ Config.
+
+end_per_testcase(_Case, _Config) ->
ok.
-%
-% Test cases starts here.
-%
+%%
+%% Test cases starts here.
+%%
-len(suite) ->
- [];
-len(doc) ->
- [];
len(Config) when is_list(Config) ->
- ?line 0 = string:len(""),
- ?line L = tuple_size(list_to_tuple(atom_to_list(?MODULE))),
- ?line L = string:len(atom_to_list(?MODULE)),
+ 0 = string:len(""),
+ L = tuple_size(list_to_tuple(atom_to_list(?MODULE))),
+ L = string:len(atom_to_list(?MODULE)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:len({})),
+ {'EXIT',_} = (catch string:len({})),
ok.
-equal(suite) ->
- [];
-equal(doc) ->
- [];
equal(Config) when is_list(Config) ->
- ?line true = string:equal("", ""),
- ?line false = string:equal("", " "),
- ?line true = string:equal("laban", "laban"),
- ?line false = string:equal("skvimp", "skvump"),
+ true = string:equal("", ""),
+ false = string:equal("", " "),
+ true = string:equal("laban", "laban"),
+ false = string:equal("skvimp", "skvump"),
%% invalid arg type
- ?line true = string:equal(2, 2), % not good, should crash
+ true = string:equal(2, 2), % not good, should crash
ok.
-concat(suite) ->
- [];
-concat(doc) ->
- [];
concat(Config) when is_list(Config) ->
- ?line "erlang rules" = string:concat("erlang ", "rules"),
- ?line "" = string:concat("", ""),
- ?line "x" = string:concat("x", ""),
- ?line "y" = string:concat("", "y"),
+ "erlang rules" = string:concat("erlang ", "rules"),
+ "" = string:concat("", ""),
+ "x" = string:concat("x", ""),
+ "y" = string:concat("", "y"),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:concat(hello, please)),
+ {'EXIT',_} = (catch string:concat(hello, please)),
ok.
-chr_rchr(suite) ->
- [];
-chr_rchr(doc) ->
- [];
chr_rchr(Config) when is_list(Config) ->
{_,_,X} = erlang:timestamp(),
- ?line 0 = string:chr("", (X rem (255-32)) + 32),
- ?line 0 = string:rchr("", (X rem (255-32)) + 32),
- ?line 1 = string:chr("x", $x),
- ?line 1 = string:rchr("x", $x),
- ?line 1 = string:chr("xx", $x),
- ?line 2 = string:rchr("xx", $x),
- ?line 3 = string:chr("xyzyx", $z),
- ?line 3 = string:rchr("xyzyx", $z),
+ 0 = string:chr("", (X rem (255-32)) + 32),
+ 0 = string:rchr("", (X rem (255-32)) + 32),
+ 1 = string:chr("x", $x),
+ 1 = string:rchr("x", $x),
+ 1 = string:chr("xx", $x),
+ 2 = string:rchr("xx", $x),
+ 3 = string:chr("xyzyx", $z),
+ 3 = string:rchr("xyzyx", $z),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:chr(hello, $h)),
+ {'EXIT',_} = (catch string:chr(hello, $h)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:chr("hello", h)),
+ {'EXIT',_} = (catch string:chr("hello", h)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:rchr(hello, $h)),
+ {'EXIT',_} = (catch string:rchr(hello, $h)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:rchr("hello", h)),
+ {'EXIT',_} = (catch string:rchr("hello", h)),
ok.
-str_rstr(suite) ->
- [];
-str_rstr(doc) ->
- [];
str_rstr(Config) when is_list(Config) ->
{_,_,X} = erlang:timestamp(),
- ?line 0 = string:str("", [(X rem (255-32)) + 32]),
- ?line 0 = string:rstr("", [(X rem (255-32)) + 32]),
- ?line 1 = string:str("x", "x"),
- ?line 1 = string:rstr("x", "x"),
- ?line 0 = string:str("hello", ""),
- ?line 0 = string:rstr("hello", ""),
- ?line 1 = string:str("xxxx", "xx"),
- ?line 3 = string:rstr("xxxx", "xx"),
- ?line 3 = string:str("xy z yx", " z"),
- ?line 3 = string:rstr("xy z yx", " z"),
+ 0 = string:str("", [(X rem (255-32)) + 32]),
+ 0 = string:rstr("", [(X rem (255-32)) + 32]),
+ 1 = string:str("x", "x"),
+ 1 = string:rstr("x", "x"),
+ 0 = string:str("hello", ""),
+ 0 = string:rstr("hello", ""),
+ 1 = string:str("xxxx", "xx"),
+ 3 = string:rstr("xxxx", "xx"),
+ 3 = string:str("xy z yx", " z"),
+ 3 = string:rstr("xy z yx", " z"),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:str(hello, "he")),
+ {'EXIT',_} = (catch string:str(hello, "he")),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:str("hello", he)),
+ {'EXIT',_} = (catch string:str("hello", he)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:rstr(hello, "he")),
+ {'EXIT',_} = (catch string:rstr(hello, "he")),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:rstr("hello", he)),
+ {'EXIT',_} = (catch string:rstr("hello", he)),
ok.
-span_cspan(suite) ->
- [];
-span_cspan(doc) ->
- [];
span_cspan(Config) when is_list(Config) ->
- ?line 0 = string:span("", "1"),
- ?line 0 = string:span("1", ""),
- ?line 0 = string:cspan("", "1"),
- ?line 1 = string:cspan("1", ""),
- ?line 1 = string:span("1 ", "1"),
- ?line 5 = string:span(" 1 ", "12 "),
- ?line 6 = string:span("1231234", "123"),
- ?line 0 = string:cspan("1 ", "1"),
- ?line 1 = string:cspan("3 ", "12 "),
- ?line 6 = string:cspan("1231234", "4"),
+ 0 = string:span("", "1"),
+ 0 = string:span("1", ""),
+ 0 = string:cspan("", "1"),
+ 1 = string:cspan("1", ""),
+ 1 = string:span("1 ", "1"),
+ 5 = string:span(" 1 ", "12 "),
+ 6 = string:span("1231234", "123"),
+ 0 = string:cspan("1 ", "1"),
+ 1 = string:cspan("3 ", "12 "),
+ 6 = string:cspan("1231234", "4"),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:span(1234, "1")),
+ {'EXIT',_} = (catch string:span(1234, "1")),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:span(1234, "1")),
+ {'EXIT',_} = (catch string:span(1234, "1")),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:cspan("1234", 1)),
+ {'EXIT',_} = (catch string:cspan("1234", 1)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:cspan("1234", 4)),
+ {'EXIT',_} = (catch string:cspan("1234", 4)),
ok.
-substr(suite) ->
- [];
-substr(doc) ->
- [];
substr(Config) when is_list(Config) ->
- ?line {'EXIT',_} = (catch string:substr("", 0)),
- ?line [] = string:substr("", 1),
- ?line {'EXIT',_} = (catch string:substr("", 2)),
- ?line [] = string:substr("1", 2),
- ?line {'EXIT',_} = (catch string:substr("", 0, 1)),
- ?line [] = string:substr("", 1, 1),
- ?line [] = string:substr("", 1, 2),
- ?line {'EXIT',_} = (catch string:substr("", 2, 2)),
- ?line "1234" = string:substr("1234", 1),
- ?line "1234" = string:substr("1234", 1, 4),
- ?line "1234" = string:substr("1234", 1, 5),
- ?line "23" = string:substr("1234", 2, 2),
- ?line "4" = string:substr("1234", 4),
- ?line "" = string:substr("1234", 4, 0),
- ?line "4" = string:substr("1234", 4, 1),
- %% invalid arg type
- ?line {'EXIT',_} = (catch string:substr(1234, 1)),
- %% invalid arg type
- ?line {'EXIT',_} = (catch string:substr("1234", "1")),
+ {'EXIT',_} = (catch string:substr("", 0)),
+ [] = string:substr("", 1),
+ {'EXIT',_} = (catch string:substr("", 2)),
+ [] = string:substr("1", 2),
+ {'EXIT',_} = (catch string:substr("", 0, 1)),
+ [] = string:substr("", 1, 1),
+ [] = string:substr("", 1, 2),
+ {'EXIT',_} = (catch string:substr("", 2, 2)),
+ "1234" = string:substr("1234", 1),
+ "1234" = string:substr("1234", 1, 4),
+ "1234" = string:substr("1234", 1, 5),
+ "23" = string:substr("1234", 2, 2),
+ "4" = string:substr("1234", 4),
+ "" = string:substr("1234", 4, 0),
+ "4" = string:substr("1234", 4, 1),
+ %% invalid arg type
+ {'EXIT',_} = (catch string:substr(1234, 1)),
+ %% invalid arg type
+ {'EXIT',_} = (catch string:substr("1234", "1")),
ok.
tokens(Config) when is_list(Config) ->
@@ -252,261 +218,217 @@ replace_sep(C, Seps, New) ->
false -> C
end.
-chars(suite) ->
- [];
-chars(doc) ->
- [];
chars(Config) when is_list(Config) ->
- ?line [] = string:chars($., 0),
- ?line [] = string:chars($., 0, []),
- ?line 10 = length(string:chars(32, 10, [])),
- ?line "aaargh" = string:chars($a, 3, "rgh"),
+ [] = string:chars($., 0),
+ [] = string:chars($., 0, []),
+ 10 = length(string:chars(32, 10, [])),
+ "aaargh" = string:chars($a, 3, "rgh"),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:chars($x, [])),
+ {'EXIT',_} = (catch string:chars($x, [])),
ok.
-copies(suite) ->
- [];
-copies(doc) ->
- [];
copies(Config) when is_list(Config) ->
- ?line "" = string:copies("", 10),
- ?line "" = string:copies(".", 0),
- ?line "." = string:copies(".", 1),
- ?line 30 = length(string:copies("123", 10)),
+ "" = string:copies("", 10),
+ "" = string:copies(".", 0),
+ "." = string:copies(".", 1),
+ 30 = length(string:copies("123", 10)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:copies("hej", -1)),
- ?line {'EXIT',_} = (catch string:copies("hej", 2.0)),
+ {'EXIT',_} = (catch string:copies("hej", -1)),
+ {'EXIT',_} = (catch string:copies("hej", 2.0)),
ok.
-words(suite) ->
- [];
-words(doc) ->
- [];
words(Config) when is_list(Config) ->
- ?line 1 = string:words(""),
- ?line 1 = string:words("", $,),
- ?line 1 = string:words("hello"),
- ?line 1 = string:words("hello", $,),
- ?line 1 = string:words("...", $.),
- ?line 2 = string:words("2.35", $.),
- ?line 100 = string:words(string:copies(". ", 100)),
+ 1 = string:words(""),
+ 1 = string:words("", $,),
+ 1 = string:words("hello"),
+ 1 = string:words("hello", $,),
+ 1 = string:words("...", $.),
+ 2 = string:words("2.35", $.),
+ 100 = string:words(string:copies(". ", 100)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:chars(hej, 1)),
+ {'EXIT',_} = (catch string:chars(hej, 1)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:chars("hej", 1, " ")),
+ {'EXIT',_} = (catch string:chars("hej", 1, " ")),
ok.
-strip(suite) ->
- [];
-strip(doc) ->
- [];
strip(Config) when is_list(Config) ->
- ?line "" = string:strip(""),
- ?line "" = string:strip("", both),
- ?line "" = string:strip("", both, $.),
- ?line "hej" = string:strip(" hej "),
- ?line "hej " = string:strip(" hej ", left),
- ?line " hej" = string:strip(" hej ", right),
- ?line " hej " = string:strip(" hej ", right, $.),
- ?line "hej hopp" = string:strip(" hej hopp ", both),
+ "" = string:strip(""),
+ "" = string:strip("", both),
+ "" = string:strip("", both, $.),
+ "hej" = string:strip(" hej "),
+ "hej " = string:strip(" hej ", left),
+ " hej" = string:strip(" hej ", right),
+ " hej " = string:strip(" hej ", right, $.),
+ "hej hopp" = string:strip(" hej hopp ", both),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:strip(hej)),
+ {'EXIT',_} = (catch string:strip(hej)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:strip(" hej", up)),
+ {'EXIT',_} = (catch string:strip(" hej", up)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:strip(" hej", left, " ")), % not good
+ {'EXIT',_} = (catch string:strip(" hej", left, " ")), % not good
ok.
-sub_word(suite) ->
- [];
-sub_word(doc) ->
- [];
sub_word(Config) when is_list(Config) ->
- ?line "" = string:sub_word("", 1),
- ?line "" = string:sub_word("", 1, $,),
- ?line {'EXIT',_} = (catch string:sub_word("1 2 3", 0)),
- ?line "" = string:sub_word("1 2 3", 4),
- ?line "llo th" = string:sub_word("but hello there", 2, $e),
+ "" = string:sub_word("", 1),
+ "" = string:sub_word("", 1, $,),
+ {'EXIT',_} = (catch string:sub_word("1 2 3", 0)),
+ "" = string:sub_word("1 2 3", 4),
+ "llo th" = string:sub_word("but hello there", 2, $e),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:sub_word('hello there', 1)),
+ {'EXIT',_} = (catch string:sub_word('hello there', 1)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:sub_word("hello there", 1, "e")),
+ {'EXIT',_} = (catch string:sub_word("hello there", 1, "e")),
ok.
-left_right(suite) ->
- [];
-left_right(doc) ->
- [];
left_right(Config) when is_list(Config) ->
- ?line "" = string:left("", 0),
- ?line "" = string:left("hej", 0),
- ?line "" = string:left("hej", 0, $.),
- ?line "" = string:right("", 0),
- ?line "" = string:right("hej", 0),
- ?line "" = string:right("hej", 0, $.),
- ?line "123 " = string:left("123 ", 5),
- ?line " 123" = string:right(" 123", 5),
- ?line "123!!" = string:left("123!", 5, $!),
- ?line "==123" = string:right("=123", 5, $=),
- ?line "1" = string:left("123", 1, $.),
- ?line "3" = string:right("123", 1, $.),
- %% invalid arg type
- ?line {'EXIT',_} = (catch string:left(hello, 5)),
- %% invalid arg type
- ?line {'EXIT',_} = (catch string:right(hello, 5)),
- %% invalid arg type
- ?line {'EXIT',_} = (catch string:left("hello", 5, ".")),
- %% invalid arg type
- ?line {'EXIT',_} = (catch string:right("hello", 5, ".")),
+ "" = string:left("", 0),
+ "" = string:left("hej", 0),
+ "" = string:left("hej", 0, $.),
+ "" = string:right("", 0),
+ "" = string:right("hej", 0),
+ "" = string:right("hej", 0, $.),
+ "123 " = string:left("123 ", 5),
+ " 123" = string:right(" 123", 5),
+ "123!!" = string:left("123!", 5, $!),
+ "==123" = string:right("=123", 5, $=),
+ "1" = string:left("123", 1, $.),
+ "3" = string:right("123", 1, $.),
+ %% invalid arg type
+ {'EXIT',_} = (catch string:left(hello, 5)),
+ %% invalid arg type
+ {'EXIT',_} = (catch string:right(hello, 5)),
+ %% invalid arg type
+ {'EXIT',_} = (catch string:left("hello", 5, ".")),
+ %% invalid arg type
+ {'EXIT',_} = (catch string:right("hello", 5, ".")),
ok.
-sub_string(suite) ->
- [];
-sub_string(doc) ->
- [];
sub_string(Config) when is_list(Config) ->
- ?line {'EXIT',_} = (catch string:sub_string("", 0)),
- ?line [] = string:sub_string("", 1),
- ?line {'EXIT',_} = (catch string:sub_string("", 2)),
- ?line [] = string:sub_string("1", 2),
- ?line {'EXIT',_} = (catch string:sub_string("", 0, 1)),
- ?line [] = string:sub_string("", 1, 1),
- ?line [] = string:sub_string("", 1, 2),
- ?line {'EXIT',_} = (catch string:sub_string("", 2, 2)),
- ?line "1234" = string:sub_string("1234", 1),
- ?line "1234" = string:sub_string("1234", 1, 4),
- ?line "1234" = string:sub_string("1234", 1, 5),
- ?line "23" = string:sub_string("1234", 2, 3),
- ?line "4" = string:sub_string("1234", 4),
- ?line "4" = string:sub_string("1234", 4, 4),
- ?line "4" = string:sub_string("1234", 4, 5),
- %% invalid arg type
- ?line {'EXIT',_} = (catch string:sub_string(1234, 1)),
- %% invalid arg type
- ?line {'EXIT',_} = (catch string:sub_string("1234", "1")),
+ {'EXIT',_} = (catch string:sub_string("", 0)),
+ [] = string:sub_string("", 1),
+ {'EXIT',_} = (catch string:sub_string("", 2)),
+ [] = string:sub_string("1", 2),
+ {'EXIT',_} = (catch string:sub_string("", 0, 1)),
+ [] = string:sub_string("", 1, 1),
+ [] = string:sub_string("", 1, 2),
+ {'EXIT',_} = (catch string:sub_string("", 2, 2)),
+ "1234" = string:sub_string("1234", 1),
+ "1234" = string:sub_string("1234", 1, 4),
+ "1234" = string:sub_string("1234", 1, 5),
+ "23" = string:sub_string("1234", 2, 3),
+ "4" = string:sub_string("1234", 4),
+ "4" = string:sub_string("1234", 4, 4),
+ "4" = string:sub_string("1234", 4, 5),
+ %% invalid arg type
+ {'EXIT',_} = (catch string:sub_string(1234, 1)),
+ %% invalid arg type
+ {'EXIT',_} = (catch string:sub_string("1234", "1")),
ok.
-centre(suite) ->
- [];
-centre(doc) ->
- [];
centre(Config) when is_list(Config) ->
- ?line "" = string:centre("", 0),
- ?line "" = string:centre("1", 0),
- ?line "" = string:centre("", 0, $-),
- ?line "" = string:centre("1", 0, $-),
- ?line "gd" = string:centre("agda", 2),
- ?line "agda " = string:centre("agda", 5),
- ?line " agda " = string:centre("agda", 6),
- ?line "agda." = string:centre("agda", 5, $.),
- ?line "--agda--" = string:centre("agda", 8, $-),
- ?line "agda" = string:centre("agda", 4),
- %% invalid arg type
- ?line {'EXIT',_} = (catch string:centre(hello, 10)),
+ "" = string:centre("", 0),
+ "" = string:centre("1", 0),
+ "" = string:centre("", 0, $-),
+ "" = string:centre("1", 0, $-),
+ "gd" = string:centre("agda", 2),
+ "agda " = string:centre("agda", 5),
+ " agda " = string:centre("agda", 6),
+ "agda." = string:centre("agda", 5, $.),
+ "--agda--" = string:centre("agda", 8, $-),
+ "agda" = string:centre("agda", 4),
+ %% invalid arg type
+ {'EXIT',_} = (catch string:centre(hello, 10)),
ok.
-to_integer(suite) ->
- [];
-to_integer(doc) ->
- [];
to_integer(Config) when is_list(Config) ->
- ?line {1,""} = test_to_integer("1"),
- ?line {1,""} = test_to_integer("+1"),
- ?line {-1,""} = test_to_integer("-1"),
- ?line {1,"="} = test_to_integer("1="),
- ?line {7,"F"} = test_to_integer("7F"),
- ?line {709,""} = test_to_integer("709"),
- ?line {709,"*2"} = test_to_integer("709*2"),
- ?line {0,"xAB"} = test_to_integer("0xAB"),
- ?line {16,"#FF"} = test_to_integer("16#FF"),
- ?line {error,no_integer} = test_to_integer(""),
- ?line {error,no_integer} = test_to_integer("!1"),
- ?line {error,no_integer} = test_to_integer("F1"),
- ?line {error,not_a_list} = test_to_integer('23'),
- ?line {3,[[]]} = test_to_integer([$3,[]]),
- ?line {3,[hello]} = test_to_integer([$3,hello]),
+ {1,""} = test_to_integer("1"),
+ {1,""} = test_to_integer("+1"),
+ {-1,""} = test_to_integer("-1"),
+ {1,"="} = test_to_integer("1="),
+ {7,"F"} = test_to_integer("7F"),
+ {709,""} = test_to_integer("709"),
+ {709,"*2"} = test_to_integer("709*2"),
+ {0,"xAB"} = test_to_integer("0xAB"),
+ {16,"#FF"} = test_to_integer("16#FF"),
+ {error,no_integer} = test_to_integer(""),
+ {error,no_integer} = test_to_integer("!1"),
+ {error,no_integer} = test_to_integer("F1"),
+ {error,not_a_list} = test_to_integer('23'),
+ {3,[[]]} = test_to_integer([$3,[]]),
+ {3,[hello]} = test_to_integer([$3,hello]),
ok.
test_to_integer(Str) ->
io:format("Checking ~p~n", [Str]),
case string:to_integer(Str) of
{error,_Reason} = Bad ->
- ?line {'EXIT',_} = (catch list_to_integer(Str)),
+ {'EXIT',_} = (catch list_to_integer(Str)),
Bad;
{F,_Rest} = Res ->
- ?line _ = integer_to_list(F),
+ _ = integer_to_list(F),
Res
end.
-to_float(suite) ->
- [];
-to_float(doc) ->
- [];
to_float(Config) when is_list(Config) ->
- ?line {1.2,""} = test_to_float("1.2"),
- ?line {1.2,""} = test_to_float("1,2"),
- ?line {120.0,""} = test_to_float("1.2e2"),
- ?line {120.0,""} = test_to_float("+1,2e2"),
- ?line {-120.0,""} = test_to_float("-1.2e2"),
- ?line {-120.0,""} = test_to_float("-1,2e+2"),
- ?line {-1.2e-2,""} = test_to_float("-1.2e-2"),
- ?line {1.2,"="} = test_to_float("1.2="),
- ?line {7.9,"e"} = test_to_float("7.9e"),
- ?line {7.9,"ee"} = test_to_float("7.9ee"),
- ?line {7.9,"e+"} = test_to_float("7.9e+"),
- ?line {7.9,"e-"} = test_to_float("7.9e-"),
- ?line {7.9,"e++"} = test_to_float("7.9e++"),
- ?line {7.9,"e--"} = test_to_float("7.9e--"),
- ?line {7.9,"e+e"} = test_to_float("7.9e+e"),
- ?line {7.9,"e-e"} = test_to_float("7.9e-e"),
- ?line {7.9,"e+."} = test_to_float("7.9e+."),
- ?line {7.9,"e-."} = test_to_float("7.9e-."),
- ?line {7.9,"e+,"} = test_to_float("7.9e+,"),
- ?line {7.9,"e-,"} = test_to_float("7.9e-,"),
- ?line {error,no_float} = test_to_float(""),
- ?line {error,no_float} = test_to_float("e1,0"),
- ?line {error,no_float} = test_to_float("1;0"),
- ?line {error,no_float} = test_to_float("1"),
- ?line {error,no_float} = test_to_float("1e"),
- ?line {error,no_float} = test_to_float("2."),
- ?line {error,not_a_list} = test_to_float('2.3'),
- ?line {2.3,[[]]} = test_to_float([$2,$.,$3,[]]),
- ?line {2.3,[hello]} = test_to_float([$2,$.,$3,hello]),
+ {1.2,""} = test_to_float("1.2"),
+ {1.2,""} = test_to_float("1,2"),
+ {120.0,""} = test_to_float("1.2e2"),
+ {120.0,""} = test_to_float("+1,2e2"),
+ {-120.0,""} = test_to_float("-1.2e2"),
+ {-120.0,""} = test_to_float("-1,2e+2"),
+ {-1.2e-2,""} = test_to_float("-1.2e-2"),
+ {1.2,"="} = test_to_float("1.2="),
+ {7.9,"e"} = test_to_float("7.9e"),
+ {7.9,"ee"} = test_to_float("7.9ee"),
+ {7.9,"e+"} = test_to_float("7.9e+"),
+ {7.9,"e-"} = test_to_float("7.9e-"),
+ {7.9,"e++"} = test_to_float("7.9e++"),
+ {7.9,"e--"} = test_to_float("7.9e--"),
+ {7.9,"e+e"} = test_to_float("7.9e+e"),
+ {7.9,"e-e"} = test_to_float("7.9e-e"),
+ {7.9,"e+."} = test_to_float("7.9e+."),
+ {7.9,"e-."} = test_to_float("7.9e-."),
+ {7.9,"e+,"} = test_to_float("7.9e+,"),
+ {7.9,"e-,"} = test_to_float("7.9e-,"),
+ {error,no_float} = test_to_float(""),
+ {error,no_float} = test_to_float("e1,0"),
+ {error,no_float} = test_to_float("1;0"),
+ {error,no_float} = test_to_float("1"),
+ {error,no_float} = test_to_float("1e"),
+ {error,no_float} = test_to_float("2."),
+ {error,not_a_list} = test_to_float('2.3'),
+ {2.3,[[]]} = test_to_float([$2,$.,$3,[]]),
+ {2.3,[hello]} = test_to_float([$2,$.,$3,hello]),
ok.
test_to_float(Str) ->
io:format("Checking ~p~n", [Str]),
case string:to_float(Str) of
{error,_Reason} = Bad ->
- ?line {'EXIT',_} = (catch list_to_float(Str)),
+ {'EXIT',_} = (catch list_to_float(Str)),
Bad;
{F,_Rest} = Res ->
- ?line _ = float_to_list(F),
+ _ = float_to_list(F),
Res
end.
-
-to_upper_to_lower(suite) ->
- [];
-to_upper_to_lower(doc) ->
- [];
+
to_upper_to_lower(Config) when is_list(Config) ->
- ?line "1234ABCDEFÅÄÖ=" = string:to_upper("1234abcdefåäö="),
- ?line "éèíúùòóåäöabc()" = string:to_lower("ÉÈÍÚÙÒÓÅÄÖabc()"),
- ?line All = lists:seq(0, 255),
+ "1234ABCDEFÅÄÖ=" = string:to_upper("1234abcdefåäö="),
+ "éèíúùòóåäöabc()" = string:to_lower("ÉÈÍÚÙÒÓÅÄÖabc()"),
+ All = lists:seq(0, 255),
- ?line UC = string:to_upper(All),
- ?line 256 = length(UC),
- ?line all_upper_latin1(UC, 0),
+ UC = string:to_upper(All),
+ 256 = length(UC),
+ all_upper_latin1(UC, 0),
- ?line LC = string:to_lower(All),
- ?line all_lower_latin1(LC, 0),
+ LC = string:to_lower(All),
+ all_lower_latin1(LC, 0),
- ?line LC = string:to_lower(string:to_upper(LC)),
- ?line LC = string:to_lower(string:to_upper(UC)),
- ?line UC = string:to_upper(string:to_lower(LC)),
- ?line UC = string:to_upper(string:to_lower(UC)),
+ LC = string:to_lower(string:to_upper(LC)),
+ LC = string:to_lower(string:to_upper(UC)),
+ UC = string:to_upper(string:to_lower(LC)),
+ UC = string:to_upper(string:to_lower(UC)),
ok.
all_upper_latin1([C|T], C) when 0 =< C, C < $a;
@@ -533,15 +455,11 @@ all_lower_latin1([H|T], C) when $A =< C, C =< $Z;
all_lower_latin1(T, C+1);
all_lower_latin1([], 256) -> ok.
-join(suite) ->
- [];
-join(doc) ->
- [];
join(Config) when is_list(Config) ->
- ?line "erlang rules" = string:join(["erlang", "rules"], " "),
- ?line "a,-,b,-,c" = string:join(["a", "b", "c"], ",-,"),
- ?line "1234" = string:join(["1", "2", "3", "4"], ""),
- ?line [] = string:join([], ""), % OTP-7231
+ "erlang rules" = string:join(["erlang", "rules"], " "),
+ "a,-,b,-,c" = string:join(["a", "b", "c"], ",-,"),
+ "1234" = string:join(["1", "2", "3", "4"], ""),
+ [] = string:join([], ""), % OTP-7231
%% invalid arg type
- ?line {'EXIT',_} = (catch string:join([apa], "")),
+ {'EXIT',_} = (catch string:join([apa], "")),
ok.
diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl
index 903ca76575..9de5a57e7f 100644
--- a/lib/stdlib/test/supervisor_SUITE.erl
+++ b/lib/stdlib/test/supervisor_SUITE.erl
@@ -22,7 +22,6 @@
-module(supervisor_SUITE).
-include_lib("common_test/include/ct.hrl").
--define(TIMEOUT, ?t:minutes(1)).
%% Testserver specific export
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -78,7 +77,8 @@
%%-------------------------------------------------------------------------
suite() ->
- [{ct_hooks,[ts_install_cth]}].
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[{group, sup_start}, {group, sup_start_map}, {group, sup_stop}, child_adm,
@@ -144,11 +144,9 @@ end_per_group(_GroupName, Config) ->
Config.
init_per_testcase(_Case, Config) ->
- Dog = ?t:timetrap(?TIMEOUT),
- [{watchdog,Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- ?t:timetrap_cancel(?config(watchdog,Config)),
+end_per_testcase(_Case, _Config) ->
ok.
start_link(InitResult) ->
@@ -704,7 +702,7 @@ permanent_normal(Config) when is_list(Config) ->
true ->
ok;
false ->
- test_server:fail({permanent_child_not_restarted, Child1})
+ ct:fail({permanent_child_not_restarted, Child1})
end,
[1,1,0,1] = get_child_counts(sup_test).
@@ -753,7 +751,7 @@ permanent_shutdown(Config) when is_list(Config) ->
true ->
ok;
false ->
- test_server:fail({permanent_child_not_restarted, Child1})
+ ct:fail({permanent_child_not_restarted, Child1})
end,
[1,1,0,1] = get_child_counts(sup_test),
@@ -764,7 +762,7 @@ permanent_shutdown(Config) when is_list(Config) ->
true ->
ok;
false ->
- test_server:fail({permanent_child_not_restarted, Child1})
+ ct:fail({permanent_child_not_restarted, Child1})
end,
[1,1,0,1] = get_child_counts(sup_test).
@@ -817,7 +815,7 @@ temporary_shutdown(Config) when is_list(Config) ->
faulty_application_shutdown(Config) when is_list(Config) ->
%% Set some paths
- AppDir = filename:join(?config(data_dir, Config), "app_faulty"),
+ AppDir = filename:join(proplists:get_value(data_dir, Config), "app_faulty"),
EbinDir = filename:join(AppDir, "ebin"),
%% Start faulty app
@@ -860,7 +858,7 @@ permanent_abnormal(Config) when is_list(Config) ->
true ->
ok;
false ->
- test_server:fail({permanent_child_not_restarted, Child1})
+ ct:fail({permanent_child_not_restarted, Child1})
end,
[1,1,0,1] = get_child_counts(sup_test).
@@ -879,7 +877,7 @@ transient_abnormal(Config) when is_list(Config) ->
true ->
ok;
false ->
- test_server:fail({transient_child_not_restarted, Child1})
+ ct:fail({transient_child_not_restarted, Child1})
end,
[1,1,0,1] = get_child_counts(sup_test).
@@ -975,9 +973,9 @@ one_for_one(Config) when is_list(Config) ->
if length(Children) == 2 ->
case lists:keysearch(CPid2, 2, Children) of
{value, _} -> ok;
- _ -> test_server:fail(bad_child)
+ _ -> ct:fail(bad_child)
end;
- true -> test_server:fail({bad_child_list, Children})
+ true -> ct:fail({bad_child_list, Children})
end,
[2,2,0,2] = get_child_counts(sup_test),
@@ -1028,7 +1026,7 @@ one_for_all(Config) when is_list(Config) ->
Children = supervisor:which_children(sup_test),
if length(Children) == 2 -> ok;
true ->
- test_server:fail({bad_child_list, Children})
+ ct:fail({bad_child_list, Children})
end,
%% Test that no old children is still alive
@@ -1103,7 +1101,7 @@ one_for_all_other_child_fails_restart(Config) when is_list(Config) ->
{_childName, _Pid} ->
exit(SupPid, kill),
check_exit([StarterPid, SupPid]),
- test_server:fail({restarting_child_not_terminated, Child1Pid2})
+ ct:fail({restarting_child_not_terminated, Child1Pid2})
end,
%% Let the restart complete.
Child1Pid3 = receive {child1, Pid5} -> Pid5 end,
@@ -1130,9 +1128,9 @@ simple_one_for_one(Config) when is_list(Config) ->
if length(Children) == 2 ->
case lists:keysearch(CPid2, 2, Children) of
{value, _} -> ok;
- _ -> test_server:fail(bad_child)
+ _ -> ct:fail(bad_child)
end;
- true -> test_server:fail({bad_child_list, Children})
+ true -> ct:fail({bad_child_list, Children})
end,
[1,2,0,2] = get_child_counts(sup_test),
@@ -1166,9 +1164,9 @@ simple_one_for_one_shutdown(Config) when is_list(Config) ->
if T < 1000*ShutdownTime ->
%% Because supervisor's children wait before exiting, it can't
%% terminate quickly
- test_server:fail({shutdown_too_short, T});
+ ct:fail({shutdown_too_short, T});
T >= 1000*5*ShutdownTime ->
- test_server:fail({shutdown_too_long, T});
+ ct:fail({shutdown_too_long, T});
true ->
check_exit([SupPid])
end.
@@ -1190,9 +1188,9 @@ simple_one_for_one_extra(Config) when is_list(Config) ->
if length(Children) == 2 ->
case lists:keysearch(CPid2, 2, Children) of
{value, _} -> ok;
- _ -> test_server:fail(bad_child)
+ _ -> ct:fail(bad_child)
end;
- true -> test_server:fail({bad_child_list, Children})
+ true -> ct:fail({bad_child_list, Children})
end,
[1,2,0,2] = get_child_counts(sup_test),
terminate(SupPid, CPid2, child2, abnormal),
@@ -1244,7 +1242,7 @@ rest_for_one(Config) when is_list(Config) ->
if length(Children) == 3 ->
ok;
true ->
- test_server:fail({bad_child_list, Children})
+ ct:fail({bad_child_list, Children})
end,
[3,3,0,3] = get_child_counts(sup_test),
@@ -1320,7 +1318,7 @@ rest_for_one_other_child_fails_restart(Config) when is_list(Config) ->
{child1, _Child1Pid3} ->
exit(SupPid, kill),
check_exit([StarterPid, SupPid]),
- test_server:fail({restarting_started_child, Child1Pid2})
+ ct:fail({restarting_started_child, Child1Pid2})
end,
StarterPid ! {stop, Self},
check_exit([StarterPid, SupPid]).
@@ -1350,7 +1348,7 @@ child_unlink(Config) when is_list(Config) ->
ok;
_ ->
exit(Pid, kill),
- test_server:fail(supervisor_hangs)
+ ct:fail(supervisor_hangs)
end.
%%-------------------------------------------------------------------------
%% Test a basic supervison tree.
@@ -1486,18 +1484,18 @@ count_restarting_children(Config) when is_list(Config) ->
supervisor_deadlock:restart_child(Ch1_1),
supervisor_deadlock:restart_child(Ch1_2),
supervisor_deadlock:restart_child(Ch1_3),
- test_server:sleep(400),
+ ct:sleep(400),
[1,3,0,3] = get_child_counts(SupPid),
[Ch2_1, Ch2_2, Ch2_3] = [C || {_,C,_,_} <- supervisor:which_children(SupPid)],
ets:insert(supervisor_deadlock,{fail_start,true}),
supervisor_deadlock:restart_child(Ch2_1),
supervisor_deadlock:restart_child(Ch2_2),
- test_server:sleep(4000), % allow restart to happen before proceeding
+ ct:sleep(4000), % allow restart to happen before proceeding
[1,1,0,3] = get_child_counts(SupPid),
ets:insert(supervisor_deadlock,{fail_start,false}),
- test_server:sleep(4000), % allow restart to happen before proceeding
+ ct:sleep(4000), % allow restart to happen before proceeding
[1,3,0,3] = get_child_counts(SupPid),
ok = supervisor:terminate_child(SupPid, Ch2_3),
@@ -1689,7 +1687,7 @@ simple_one_for_one_scale_many_temporary_children(_Config) ->
%% The scaling shoul be linear (i.e.10, really), but we
%% give some extra here to avoid failing the test
%% unecessarily.
- ?t:fail({bad_scaling,Scaling});
+ ct:fail({bad_scaling,Scaling});
true ->
ok
end;
@@ -2118,14 +2116,14 @@ in_child_list([Pid | Rest], Pids) ->
true ->
in_child_list(Rest, Pids);
false ->
- test_server:fail(child_should_be_alive)
+ ct:fail(child_should_be_alive)
end.
not_in_child_list([], _) ->
true;
not_in_child_list([Pid | Rest], Pids) ->
case is_in_child_list(Pid, Pids) of
true ->
- test_server:fail(child_should_not_be_alive);
+ ct:fail(child_should_not_be_alive);
false ->
not_in_child_list(Rest, Pids)
end.
@@ -2146,7 +2144,7 @@ check_exit_reason(Reason) ->
{'EXIT', _, Reason} ->
ok;
{'EXIT', _, Else} ->
- test_server:fail({bad_exit_reason, Else})
+ ct:fail({bad_exit_reason, Else})
end.
check_exit_reason(Pid, Reason) ->
@@ -2154,5 +2152,5 @@ check_exit_reason(Pid, Reason) ->
{'EXIT', Pid, Reason} ->
ok;
{'EXIT', Pid, Else} ->
- test_server:fail({bad_exit_reason, Else})
+ ct:fail({bad_exit_reason, Else})
end.
diff --git a/lib/stdlib/test/supervisor_bridge_SUITE.erl b/lib/stdlib/test/supervisor_bridge_SUITE.erl
index b55fbfaf0d..029cb3fd7f 100644
--- a/lib/stdlib/test/supervisor_bridge_SUITE.erl
+++ b/lib/stdlib/test/supervisor_bridge_SUITE.erl
@@ -24,13 +24,15 @@
simple_global_supervisor/1]).
-export([client/1,init/1,internal_loop_init/1,terminate/2,server9212/0]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(bridge_name,supervisor_bridge_SUITE_server).
-define(work_bridge_name,work_supervisor_bridge_SUITE_server).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
all() ->
[starting, mini_terminate, mini_die, badstart, simple_global_supervisor].
@@ -53,33 +55,30 @@ end_per_group(_GroupName, Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-starting(suite) -> [];
starting(Config) when is_list(Config) ->
process_flag(trap_exit,true),
- ?line ignore = start(1),
- ?line {error,testing} = start(2),
+ ignore = start(1),
+ {error,testing} = start(2),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-mini_terminate(suite) -> [];
mini_terminate(Config) when is_list(Config) ->
miniappl(1),
ok.
-mini_die(suite) -> [];
mini_die(Config) when is_list(Config) ->
miniappl(2),
ok.
miniappl(N) ->
process_flag(trap_exit,true),
- ?line {ok,Server} = start(3),
- ?line Client = spawn_link(?MODULE,client,[N]),
- ?line Handle = test_server:timetrap(2000),
- ?line miniappl_loop(Client,Server),
- ?line test_server:timetrap_cancel(Handle).
+ {ok,Server} = start(3),
+ Client = spawn_link(?MODULE,client,[N]),
+ ct:timetrap({seconds,2}),
+ miniappl_loop(Client, Server).
+
miniappl_loop([],[]) ->
ok;
@@ -87,19 +86,19 @@ miniappl_loop(Client,Server) ->
io:format("Client ~p, Server ~p\n",[Client,Server]),
receive
{'EXIT',Client,_} ->
- ?line miniappl_loop([],Server);
+ miniappl_loop([],Server);
{'EXIT',Server,killed} -> %% terminate
- ?line miniappl_loop(Client,[]);
+ miniappl_loop(Client,[]);
{'EXIT',Server,died} -> %% die
- ?line miniappl_loop(Client,[]);
+ miniappl_loop(Client,[]);
{dying,_Reason} ->
- ?line miniappl_loop(Client, Server);
+ miniappl_loop(Client, Server);
Other ->
- ?line exit({failed,Other})
+ exit({failed,Other})
end.
%%%%%%%%%%%%%%%%%%%%
-% Client
+%% Client
client(N) ->
io:format("Client starting...\n"),
@@ -112,7 +111,7 @@ client(N) ->
exit(fine).
%%%%%%%%%%%%%%%%%%%%
-% Non compliant server
+%% Non compliant server
start(N) ->
supervisor_bridge:start_link({local,?bridge_name},?MODULE,N).
@@ -170,45 +169,44 @@ terminate(_Reason, _State) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-badstart(suite) -> [];
-badstart(doc) -> "Test various bad ways of starting a supervisor bridge.";
+%% Test various bad ways of starting a supervisor bridge.
badstart(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap(test_server:minutes(1)),
-
%% Various bad arguments.
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch supervisor_bridge:start_link({xxx,?bridge_name},?MODULE,1)),
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch supervisor_bridge:start_link({local,"foo"},?MODULE,1)),
- ?line {'EXIT',_} =
+ {'EXIT',_} =
(catch supervisor_bridge:start_link(?bridge_name,?MODULE,1)),
- ?line [] = test_server:messages_get(), % No messages waiting
+ receive
+ Msg ->
+ ct:fail({unexpected,Msg})
+ after 1 ->
+ ok
+ end,
%% Already started.
- ?line process_flag(trap_exit, true),
- ?line {ok,Pid} =
+ process_flag(trap_exit, true),
+ {ok,Pid} =
supervisor_bridge:start_link({local,?bridge_name},?MODULE,3),
- ?line {error,{already_started,Pid}} =
+ {error,{already_started,Pid}} =
supervisor_bridge:start_link({local,?bridge_name},?MODULE,3),
- ?line public_kill(),
+ public_kill(),
%% We used to wait 1 ms before retrieving the message queue,
%% but that might not always be enough if the machine is overloaded.
- ?line receive
- {'EXIT', Pid, killed} -> ok
- end,
- ?line test_server:timetrap_cancel(Dog),
+ receive
+ {'EXIT', Pid, killed} -> ok
+ end,
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% OTP-9212. Restart of global supervisor.
-simple_global_supervisor(suite) -> [];
-simple_global_supervisor(doc) -> "Globally registered supervisor.";
+%% Globally registered supervisor.
simple_global_supervisor(Config) when is_list(Config) ->
- ?line Dog = test_server:timetrap({seconds,10}),
Child = {child, {?MODULE,server9212,[]}, permanent, 2000, worker, []},
InitResult = {ok, {{one_for_all,3,60}, [Child]}},
@@ -216,16 +214,15 @@ simple_global_supervisor(Config) when is_list(Config) ->
supervisor:start_link({local,bridge9212}, ?MODULE, {4,InitResult}),
BN_1 = global:whereis_name(?bridge_name),
- ?line exit(BN_1, kill),
+ exit(BN_1, kill),
timer:sleep(200),
BN_2 = global:whereis_name(?bridge_name),
- ?line true = is_pid(BN_2),
- ?line true = BN_1 =/= BN_2,
+ true = is_pid(BN_2),
+ true = BN_1 =/= BN_2,
- ?line process_flag(trap_exit, true),
+ process_flag(trap_exit, true),
exit(Sup, kill),
- ?line receive {'EXIT', Sup, killed} -> ok end,
- ?line test_server:timetrap_cancel(Dog),
+ receive {'EXIT', Sup, killed} -> ok end,
ok.
server9212() ->
diff --git a/lib/stdlib/test/sys_SUITE.erl b/lib/stdlib/test/sys_SUITE.erl
index 573fa6f358..39bc835824 100644
--- a/lib/stdlib/test/sys_SUITE.erl
+++ b/lib/stdlib/test/sys_SUITE.erl
@@ -22,7 +22,7 @@
init_per_group/2,end_per_group/2,log/1,log_to_file/1,
stats/1,trace/1,suspend/1,install/1,special_process/1]).
-export([handle_call/3,terminate/2,init/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(server,sys_SUITE_server).
@@ -53,7 +53,6 @@ end_per_group(_GroupName, Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-log(suite) -> [];
log(Config) when is_list(Config) ->
{ok,_Server} = start(),
ok = sys:log(?server,true),
@@ -63,9 +62,8 @@ log(Config) when is_list(Config) ->
stop(),
ok.
-log_to_file(suite) -> [];
log_to_file(Config) when is_list(Config) ->
- TempName = test_server:temp_name(?config(priv_dir,Config) ++ "sys."),
+ TempName = test_server:temp_name(proplists:get_value(priv_dir,Config) ++ "sys."),
{ok,_Server} = start(),
ok = sys:log_to_file(?server,TempName),
{ok,-44} = public_call(44),
@@ -74,20 +72,19 @@ log_to_file(Config) when is_list(Config) ->
Msg1 = io:get_line(Fd,''),
Msg2 = io:get_line(Fd,''),
file:close(Fd),
- lists:prefix("*DBG* sys_SUITE_server got call {req,44} from ",Msg1),
- lists:prefix("*DBG* sys_SUITE_server sent {ok,-44} to ",Msg2),
+ "*DBG* sys_SUITE_server got call {req,44} from " ++ _ = Msg1,
+ "*DBG* sys_SUITE_server sent {ok,-44} to " ++ _ = Msg2,
stop(),
ok.
-stats(suite) -> [];
stats(Config) when is_list(Config) ->
Self = self(),
{ok,_Server} = start(),
ok = sys:statistics(?server,true),
{ok,-44} = public_call(44),
{ok,Stats} = sys:statistics(?server,get),
- lists:member({messages_in,1},Stats),
- lists:member({messages_out,1},Stats),
+ true = lists:member({messages_in,1}, Stats),
+ true = lists:member({messages_out,0}, Stats),
ok = sys:statistics(?server,false),
{status,_Pid,{module,_Mod},[_PDict,running,Self,_,_]} =
sys:get_status(?server),
@@ -95,43 +92,40 @@ stats(Config) when is_list(Config) ->
stop(),
ok.
-trace(suite) -> [];
trace(Config) when is_list(Config) ->
{ok,_Server} = start(),
- test_server:sleep(2000),
- test_server:capture_start(),
+ ct:sleep(2000),
+ ct:capture_start(),
sys:trace(?server,true),
{ok,-44} = public_call(44),
%% ho, hum, allow for the io to reach us..
- test_server:sleep(1000),
- test_server:capture_stop(),
- [Msg1,Msg2] = test_server:capture_get(),
- lists:prefix("*DBG* sys_SUITE_server got call {req,44} from ",Msg1),
- lists:prefix("*DBG* sys_SUITE_server sent {ok,-44} to ",Msg2),
+ ct:sleep(1000),
+ ct:capture_stop(),
+ [Msg1,Msg2] = ct:capture_get(),
+ "*DBG* sys_SUITE_server got call {req,44} from " ++ _ = Msg1,
+ "*DBG* sys_SUITE_server sent {ok,-44} to " ++ _ = Msg2,
stop(),
ok.
-suspend(suite) -> [];
suspend(Config) when is_list(Config) ->
- ?line {ok,_Server} = start(),
- ?line sys:suspend(?server,1000),
- ?line {'EXIT',_} = (catch public_call(48)),
- ?line {status,_,_,[_,suspended,_,_,_]} = sys:get_status(?server),
- ?line sys:suspend(?server,1000), %% doing it twice is no error
- ?line {'EXIT',_} = (catch public_call(48)),
- ?line sys:resume(?server),
- ?line {status,_,_,[_,running,_,_,_]} = sys:get_status(?server),
- ?line {ok,-48} = (catch public_call(48)),
- ?line sys:resume(?server), %% doing it twice is no error
- ?line {ok,-48} = (catch public_call(48)),
- ?line stop(),
+ {ok,_Server} = start(),
+ sys:suspend(?server,1000),
+ {'EXIT',_} = (catch public_call(48)),
+ {status,_,_,[_,suspended,_,_,_]} = sys:get_status(?server),
+ sys:suspend(?server,1000), %% doing it twice is no error
+ {'EXIT',_} = (catch public_call(48)),
+ sys:resume(?server),
+ {status,_,_,[_,running,_,_,_]} = sys:get_status(?server),
+ {ok,-48} = (catch public_call(48)),
+ sys:resume(?server), %% doing it twice is no error
+ {ok,-48} = (catch public_call(48)),
+ stop(),
ok.
-install(suite) -> [];
install(Config) when is_list(Config) ->
- ?line {ok,_Server} = start(),
- ?line Master = self(),
- ?line SpyFun =
+ {ok,_Server} = start(),
+ Master = self(),
+ SpyFun =
fun(func_state,Event,ProcState) ->
case Event of
{in,{'$gen_call',_From,{req,Arg}}} ->
@@ -141,22 +135,26 @@ install(Config) when is_list(Config) ->
io:format("Trigged other=~p\n",[Other])
end
end,
- ?line sys:install(?server,{SpyFun,func_state}),
- ?line {ok,-1} = (catch public_call(1)),
- ?line sys:no_debug(?server),
- ?line {ok,-2} = (catch public_call(2)),
- ?line sys:install(?server,{SpyFun,func_state}),
- ?line sys:install(?server,{SpyFun,func_state}),
- ?line {ok,-3} = (catch public_call(3)),
- ?line sys:remove(?server,SpyFun),
- ?line {ok,-4} = (catch public_call(4)),
- ?line Msgs = test_server:messages_get(),
- ?line [{spy_got,{request,1},sys_SUITE_server},
- {spy_got,{request,3},sys_SUITE_server}] = Msgs,
- ?line stop(),
+ sys:install(?server,{SpyFun,func_state}),
+ {ok,-1} = (catch public_call(1)),
+ sys:no_debug(?server),
+ {ok,-2} = (catch public_call(2)),
+ sys:install(?server,{SpyFun,func_state}),
+ sys:install(?server,{SpyFun,func_state}),
+ {ok,-3} = (catch public_call(3)),
+ sys:remove(?server,SpyFun),
+ {ok,-4} = (catch public_call(4)),
+ [{spy_got,{request,1},sys_SUITE_server},
+ {spy_got,{request,3},sys_SUITE_server}] = get_messages(),
+ stop(),
ok.
-special_process(suite) -> [];
+get_messages() ->
+ receive
+ Msg -> [Msg|get_messages()]
+ after 1 -> []
+ end.
+
special_process(Config) when is_list(Config) ->
ok = spec_proc(sys_sp1),
ok = spec_proc(sys_sp2).
diff --git a/lib/stdlib/test/tar_SUITE.erl b/lib/stdlib/test/tar_SUITE.erl
index 6da017f818..7f20851445 100644
--- a/lib/stdlib/test/tar_SUITE.erl
+++ b/lib/stdlib/test/tar_SUITE.erl
@@ -26,7 +26,7 @@
extract_from_open_file/1, symlinks/1, open_add_close/1, cooked_compressed/1,
memory/1,unicode/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -53,10 +53,9 @@ end_per_group(_GroupName, Config) ->
Config.
-borderline(doc) ->
- ["Test creating, listing and extracting one file from an archive",
- "multiple times with different file sizes. ",
- "Also check that the file attributes of the extracted file has survived."];
+%% Test creating, listing and extracting one file from an archive,
+%% multiple times with different file sizes. Also check that the file
+%% attributes of the extracted file has survived.
borderline(Config) when is_list(Config) ->
%% Note: We cannot use absolute paths, because the pathnames will be
@@ -64,47 +63,47 @@ borderline(Config) when is_list(Config) ->
%% Therefore, strip off the current working directory from the front
%% of the private directory path.
- ?line {ok, Cwd} = file:get_cwd(),
- ?line RootDir = ?config(priv_dir, Config),
- ?line TempDir = remove_prefix(Cwd++"/", filename:join(RootDir, "borderline")),
- ?line ok = file:make_dir(TempDir),
+ {ok, Cwd} = file:get_cwd(),
+ RootDir = proplists:get_value(priv_dir, Config),
+ TempDir = remove_prefix(Cwd++"/", filename:join(RootDir, "borderline")),
+ ok = file:make_dir(TempDir),
- ?line Record = 512,
- ?line Block = 20 * Record,
+ Record = 512,
+ Block = 20 * Record,
- ?line lists:foreach(fun(Size) -> borderline_test(Size, TempDir) end,
- [0, 1, 10, 13, 127, 333, Record-1, Record, Record+1,
- Block-2*Record-1, Block-2*Record, Block-2*Record+1,
- Block-Record-1, Block-Record, Block-Record+1,
- Block-1, Block, Block+1,
- Block+Record-1, Block+Record, Block+Record+1]),
+ lists:foreach(fun(Size) -> borderline_test(Size, TempDir) end,
+ [0, 1, 10, 13, 127, 333, Record-1, Record, Record+1,
+ Block-2*Record-1, Block-2*Record, Block-2*Record+1,
+ Block-Record-1, Block-Record, Block-Record+1,
+ Block-1, Block, Block+1,
+ Block+Record-1, Block+Record, Block+Record+1]),
%% Clean up.
- ?line delete_files([TempDir]),
+ delete_files([TempDir]),
ok.
borderline_test(Size, TempDir) ->
- ?line Archive = filename:join(TempDir, "ar_"++integer_to_list(Size)++".tar"),
- ?line Name = filename:join(TempDir, "file_"++integer_to_list(Size)),
- ?line io:format("Testing size ~p", [Size]),
+ Archive = filename:join(TempDir, "ar_"++integer_to_list(Size)++".tar"),
+ Name = filename:join(TempDir, "file_"++integer_to_list(Size)),
+ io:format("Testing size ~p", [Size]),
%% Create a file and archive it.
X0 = erlang:monotonic_time(),
- ?line file:write_file(Name, random_byte_list(X0, Size)),
- ?line ok = erl_tar:create(Archive, [Name]),
- ?line ok = file:delete(Name),
+ file:write_file(Name, random_byte_list(X0, Size)),
+ ok = erl_tar:create(Archive, [Name]),
+ ok = file:delete(Name),
%% Verify listing and extracting.
- ?line {ok, [Name]} = erl_tar:table(Archive),
- ?line ok = erl_tar:extract(Archive, [verbose]),
+ {ok, [Name]} = erl_tar:table(Archive),
+ ok = erl_tar:extract(Archive, [verbose]),
%% Verify contents of extracted file.
- ?line {ok, Bin} = file:read_file(Name),
- ?line true = match_byte_list(X0, binary_to_list(Bin)),
+ {ok, Bin} = file:read_file(Name),
+ true = match_byte_list(X0, binary_to_list(Bin)),
%% Verify that Unix tar can read it.
- ?line tar_tf(Archive, Name),
+ tar_tf(Archive, Name),
ok.
@@ -117,20 +116,20 @@ tar_tf(Archive, Name) ->
end.
tar_tf1(Archive, Name) ->
- ?line Expect = Name ++ "\n",
- ?line cmd_expect("tar tf " ++ Archive, Expect).
+ Expect = Name ++ "\n",
+ cmd_expect("tar tf " ++ Archive, Expect).
%% We can't use os:cmd/1, because Unix 'tar tf Name' on Solaris never
%% terminates when given an archive of a size it doesn't like.
cmd_expect(Cmd, Expect) ->
- ?line Port = open_port({spawn, make_cmd(Cmd)}, [stream, in, eof]),
- ?line get_data(Port, Expect).
+ Port = open_port({spawn, make_cmd(Cmd)}, [stream, in, eof]),
+ get_data(Port, Expect).
get_data(Port, Expect) ->
receive
{Port, {data, Bytes}} ->
- ?line get_data(Port, match_output(Bytes, Expect, Port));
+ get_data(Port, match_output(Bytes, Expect, Port));
{Port, eof} ->
Port ! {self(), close},
receive
@@ -143,26 +142,26 @@ get_data(Port, Expect) ->
after 1 -> % force context switch
ok
end,
- ?line match_output(eof, Expect, Port)
+ match_output(eof, Expect, Port)
end.
match_output([C|Output], [C|Expect], Port) ->
- ?line match_output(Output, Expect, Port);
+ match_output(Output, Expect, Port);
match_output([_|_], [_|_], Port) ->
- ?line kill_port_and_fail(Port, badmatch);
+ kill_port_and_fail(Port, badmatch);
match_output([X|Output], [], Port) ->
- ?line kill_port_and_fail(Port, {too_much_data, [X|Output]});
+ kill_port_and_fail(Port, {too_much_data, [X|Output]});
match_output([], Expect, _Port) ->
Expect;
match_output(eof, [], _Port) ->
[];
match_output(eof, _Expect, Port) ->
- ?line kill_port_and_fail(Port, unexpected_end_of_input).
+ kill_port_and_fail(Port, unexpected_end_of_input).
kill_port_and_fail(Port, Reason) ->
unlink(Port),
exit(Port, die),
- test_server:fail(Reason).
+ ct:fail(Reason).
make_cmd(Cmd) ->
case os:type() of
@@ -198,58 +197,56 @@ random_byte_list(_X, 0, Result) ->
next_random(X) ->
(X*17059465+1) band 16#fffffffff.
-atomic(doc) ->
- ["Test the 'atomic' operations: create/extract/table, on compressed "
- "and uncompressed archives."
- "Also test the 'cooked' option."];
-atomic(suite) -> [];
+%% Test the 'atomic' operations: create/extract/table, on compressed
+%% and uncompressed archives.
+%% Also test the 'cooked' option.
atomic(Config) when is_list(Config) ->
- ?line ok = file:set_cwd(?config(priv_dir, Config)),
- ?line DataFiles = data_files(),
- ?line Names = [Name || {Name,_,_} <- DataFiles],
+ ok = file:set_cwd(proplists:get_value(priv_dir, Config)),
+ DataFiles = data_files(),
+ Names = [Name || {Name,_,_} <- DataFiles],
io:format("Names: ~p", [Names]),
%% Create an uncompressed archive. The compressed flag should still be
%% allowed when listing contents or extracting.
- ?line Tar1 = "uncompressed.tar",
- ?line erl_tar:create(Tar1, Names, []),
- ?line {ok, Names} = erl_tar:table(Tar1, []),
- ?line {ok, Names} = erl_tar:table(Tar1, [compressed]),
- ?line {ok, Names} = erl_tar:table(Tar1, [cooked]),
- ?line {ok, Names} = erl_tar:table(Tar1, [compressed,cooked]),
-
+ Tar1 = "uncompressed.tar",
+ erl_tar:create(Tar1, Names, []),
+ {ok, Names} = erl_tar:table(Tar1, []),
+ {ok, Names} = erl_tar:table(Tar1, [compressed]),
+ {ok, Names} = erl_tar:table(Tar1, [cooked]),
+ {ok, Names} = erl_tar:table(Tar1, [compressed,cooked]),
+
%% Create a compressed archive.
- ?line Tar2 = "compressed.tar",
- ?line erl_tar:create(Tar2, Names, [compressed]),
- ?line {ok, Names} = erl_tar:table(Tar2, [compressed]),
- ?line {error, Reason} = erl_tar:table(Tar2, []),
- ?line {ok, Names} = erl_tar:table(Tar2, [compressed,cooked]),
- ?line {error, Reason} = erl_tar:table(Tar2, [cooked]),
- ?line ok = io:format("No compressed option: ~p, ~s",
- [Reason, erl_tar:format_error(Reason)]),
+ Tar2 = "compressed.tar",
+ erl_tar:create(Tar2, Names, [compressed]),
+ {ok, Names} = erl_tar:table(Tar2, [compressed]),
+ {error, Reason} = erl_tar:table(Tar2, []),
+ {ok, Names} = erl_tar:table(Tar2, [compressed,cooked]),
+ {error, Reason} = erl_tar:table(Tar2, [cooked]),
+ ok = io:format("No compressed option: ~p, ~s",
+ [Reason, erl_tar:format_error(Reason)]),
%% Same test again, but this time created with 'cooked'
- ?line Tar3 = "uncompressed_cooked.tar",
- ?line erl_tar:create(Tar3, Names, [cooked]),
- ?line {ok, Names} = erl_tar:table(Tar3, []),
- ?line {ok, Names} = erl_tar:table(Tar3, [compressed]),
- ?line {ok, Names} = erl_tar:table(Tar3, [cooked]),
- ?line {ok, Names} = erl_tar:table(Tar3, [compressed,cooked]),
-
- ?line Tar4 = "compressed_cooked.tar",
- ?line erl_tar:create(Tar4, Names, [compressed,cooked]),
- ?line {ok, Names} = erl_tar:table(Tar4, [compressed]),
- ?line {error, Reason} = erl_tar:table(Tar4, []),
- ?line {ok, Names} = erl_tar:table(Tar4, [compressed,cooked]),
- ?line {error, Reason} = erl_tar:table(Tar4, [cooked]),
- ?line ok = io:format("No compressed option: ~p, ~s",
- [Reason, erl_tar:format_error(Reason)]),
+ Tar3 = "uncompressed_cooked.tar",
+ erl_tar:create(Tar3, Names, [cooked]),
+ {ok, Names} = erl_tar:table(Tar3, []),
+ {ok, Names} = erl_tar:table(Tar3, [compressed]),
+ {ok, Names} = erl_tar:table(Tar3, [cooked]),
+ {ok, Names} = erl_tar:table(Tar3, [compressed,cooked]),
+
+ Tar4 = "compressed_cooked.tar",
+ erl_tar:create(Tar4, Names, [compressed,cooked]),
+ {ok, Names} = erl_tar:table(Tar4, [compressed]),
+ {error, Reason} = erl_tar:table(Tar4, []),
+ {ok, Names} = erl_tar:table(Tar4, [compressed,cooked]),
+ {error, Reason} = erl_tar:table(Tar4, [cooked]),
+ ok = io:format("No compressed option: ~p, ~s",
+ [Reason, erl_tar:format_error(Reason)]),
%% Clean up.
- ?line delete_files([Tar1,Tar2,Tar3,Tar4|Names]),
+ delete_files([Tar1,Tar2,Tar3,Tar4|Names]),
ok.
@@ -279,50 +276,48 @@ create_files([{Name, Size, First}|Rest]) ->
create_files([]) ->
ok.
-long_names(doc) ->
- ["Test to extract an Unix tar file containing filenames longer than 100 ",
- "characters and empty directories."];
+%% Test to extract an Unix tar file containing filenames longer than
+%% 100 characters and empty directories.
long_names(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line Long = filename:join(DataDir, "long_names.tar"),
+ DataDir = proplists:get_value(data_dir, Config),
+ Long = filename:join(DataDir, "long_names.tar"),
run_in_short_tempdir(Config,
fun() -> do_long_names(Long) end).
do_long_names(Long) ->
%% Try table/2 and extract/2.
- ?line case erl_tar:table(Long, [verbose]) of
- {ok,List} when is_list(List) ->
- ?line io:format("~p\n", [List])
- end,
+ case erl_tar:table(Long, [verbose]) of
+ {ok,List} when is_list(List) ->
+ io:format("~p\n", [List])
+ end,
- ?line {ok,Cwd} = file:get_cwd(),
- ?line ok = erl_tar:extract(Long),
- ?line Base = filename:join([Cwd, "original_software", "written_by",
- "a_bunch_of_hackers",
- "spending_all_their_nights",
- "still", "not_long_enough",
- "but_soon_it_will_be"]),
+ {ok,Cwd} = file:get_cwd(),
+ ok = erl_tar:extract(Long),
+ Base = filename:join([Cwd, "original_software", "written_by",
+ "a_bunch_of_hackers",
+ "spending_all_their_nights",
+ "still", "not_long_enough",
+ "but_soon_it_will_be"]),
%% Verify that the empty directory was created.
- ?line EmptyDir = filename:join(Base, "empty_directory"),
- ?line {ok, #file_info{type=directory}} = file:read_file_info(EmptyDir),
+ EmptyDir = filename:join(Base, "empty_directory"),
+ {ok, #file_info{type=directory}} = file:read_file_info(EmptyDir),
%% Verify that the files were created.
- ?line {ok,First} = file:read_file(filename:join(Base, "first_file")),
- ?line {ok,Second} = file:read_file(filename:join(Base, "second_file")),
- ?line "Here"++_ = binary_to_list(First),
- ?line "And"++_ = binary_to_list(Second),
+ {ok,First} = file:read_file(filename:join(Base, "first_file")),
+ {ok,Second} = file:read_file(filename:join(Base, "second_file")),
+ "Here"++_ = binary_to_list(First),
+ "And"++_ = binary_to_list(Second),
ok.
-create_long_names(doc) ->
- ["Creates a tar file from a deep directory structure (filenames are ",
- "longer than 100 characters)."];
+%% Creates a tar file from a deep directory structure (filenames are
+%% longer than 100 characters).
create_long_names(Config) when is_list(Config) ->
run_in_short_tempdir(Config, fun create_long_names/0).
-
+
create_long_names() ->
- ?line {ok,Dir} = file:get_cwd(),
+ {ok,Dir} = file:get_cwd(),
Dirs = ["aslfjkshjkhliuf",
"asdhjfehnbfsky",
"sahajfskdfhsz",
@@ -330,49 +325,48 @@ create_long_names() ->
"f7nafhjgffagkhsfkhsjk",
"dfjasldkfjsdkfjashbv"],
- ?line DeepDir = make_dirs(Dirs, []),
- ?line AFile = filename:join(DeepDir, "a_file"),
- ?line Hello = "hello, world\n",
- ?line ok = file:write_file(AFile, Hello),
- ?line TarName = filename:join(Dir, "my_tar_with_long_names.tar"),
- ?line ok = erl_tar:create(TarName, [AFile]),
+ DeepDir = make_dirs(Dirs, []),
+ AFile = filename:join(DeepDir, "a_file"),
+ Hello = "hello, world\n",
+ ok = file:write_file(AFile, Hello),
+ TarName = filename:join(Dir, "my_tar_with_long_names.tar"),
+ ok = erl_tar:create(TarName, [AFile]),
%% Print contents.
- ?line ok = erl_tar:tt(TarName),
+ ok = erl_tar:tt(TarName),
%% Extract and verify.
- ?line ExtractDir = "extract_dir",
- ?line ok = file:make_dir(ExtractDir),
- ?line ok = erl_tar:extract(TarName, [{cwd,ExtractDir}]),
- ?line {ok, Bin} = file:read_file(filename:join(ExtractDir, AFile)),
- ?line Hello = binary_to_list(Bin),
+ ExtractDir = "extract_dir",
+ ok = file:make_dir(ExtractDir),
+ ok = erl_tar:extract(TarName, [{cwd,ExtractDir}]),
+ {ok, Bin} = file:read_file(filename:join(ExtractDir, AFile)),
+ Hello = binary_to_list(Bin),
ok.
make_dirs([Dir|Rest], []) ->
- ?line ok = file:make_dir(Dir),
- ?line make_dirs(Rest, Dir);
+ ok = file:make_dir(Dir),
+ make_dirs(Rest, Dir);
make_dirs([Dir|Rest], Parent) ->
- ?line Name = filename:join(Parent, Dir),
- ?line ok = file:make_dir(Name),
- ?line make_dirs(Rest, Name);
+ Name = filename:join(Parent, Dir),
+ ok = file:make_dir(Name),
+ make_dirs(Rest, Name);
make_dirs([], Dir) ->
Dir.
-bad_tar(doc) ->
- ["Try erl_tar:table/2 and erl_tar:extract/2 on some corrupted tar files."];
+%% Try erl_tar:table/2 and erl_tar:extract/2 on some corrupted tar files.
bad_tar(Config) when is_list(Config) ->
- ?line try_bad("bad_checksum", bad_header, Config),
- ?line try_bad("bad_octal", bad_header, Config),
- ?line try_bad("bad_too_short", eof, Config),
- ?line try_bad("bad_even_shorter", eof, Config),
+ try_bad("bad_checksum", bad_header, Config),
+ try_bad("bad_octal", bad_header, Config),
+ try_bad("bad_too_short", eof, Config),
+ try_bad("bad_even_shorter", eof, Config),
ok.
try_bad(Name0, Reason, Config) ->
- %% Intentionally no ?line macros here.
+ %% Intentionally no macros here.
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Name = Name0 ++ ".tar",
io:format("~nTrying ~s", [Name]),
Full = filename:join(DataDir, Name),
@@ -383,38 +377,37 @@ try_bad(Name0, Reason, Config) ->
io:format("Result: ~p", [Expected]),
case catch erl_tar:format_error(Reason) of
{'EXIT', CrashReason} ->
- test_server:fail({format_error, crashed, CrashReason});
+ ct:fail({format_error, crashed, CrashReason});
String when is_list(String) ->
io:format("format_error(~p) -> ~s", [Reason, String]);
Other ->
- test_server:fail({format_error, returned, Other})
+ ct:fail({format_error, returned, Other})
end;
{Other1, Other2} ->
io:format("table/2 returned ~p", [Other1]),
io:format("extract/2 returned ~p", [Other2]),
- test_server:fail({bad_return_value, Other1, Other2})
+ ct:fail({bad_return_value, Other1, Other2})
end.
-errors(doc) ->
- ["Tests that some common errors return correct error codes ",
- "and that format_error/1 handles them correctly."];
+%% Tests that some common errors return correct error codes
+%% and that format_error/1 handles them correctly.
errors(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
%% Give the tar file the same name as a directory.
- ?line BadTar = filename:join(PrivDir, "bad_tarfile.tar"),
- ?line ok = file:make_dir(BadTar),
- ?line try_error(erl_tar, create, [BadTar, []], {BadTar, eisdir}),
+ BadTar = filename:join(PrivDir, "bad_tarfile.tar"),
+ ok = file:make_dir(BadTar),
+ try_error(erl_tar, create, [BadTar, []], {BadTar, eisdir}),
%% Try including non-existent files in the tar file.
- ?line NonExistent = "non_existent_file",
- ?line GoodTar = filename:join(PrivDir, "a_good_tarfile.tar"),
- ?line try_error(erl_tar, create, [GoodTar, [NonExistent]],
- {NonExistent, enoent}),
+ NonExistent = "non_existent_file",
+ GoodTar = filename:join(PrivDir, "a_good_tarfile.tar"),
+ try_error(erl_tar, create, [GoodTar, [NonExistent]],
+ {NonExistent, enoent}),
%% Clean up.
- ?line delete_files([GoodTar,BadTar]),
-
+ delete_files([GoodTar,BadTar]),
+
ok.
try_error(M, F, A, Error) ->
@@ -423,18 +416,18 @@ try_error(M, F, A, Error) ->
{'EXIT', Reason} ->
exit(Reason);
ok ->
- test_server:fail(unexpected_success);
+ ct:fail(unexpected_success);
{error, Error} ->
case catch erl_tar:format_error(Error) of
{'EXIT', FReason} ->
- test_server:fail({format_error, crashed, FReason});
+ ct:fail({format_error, crashed, FReason});
String when is_list(String) ->
io:format("format_error(~p) -> ~s", [Error, String]);
Other ->
- test_server:fail({format_error, returned, Other})
+ ct:fail({format_error, returned, Other})
end;
Other ->
- test_server:fail({expected, {error, Error}, actual, Other})
+ ct:fail({expected, {error, Error}, actual, Other})
end.
%% remove_prefix(Prefix, List) -> ListWithoutPrefix.
@@ -444,107 +437,104 @@ remove_prefix([C|Rest1], [C|Rest2]) ->
remove_prefix(_, Result) ->
Result.
-extract_from_binary(doc) ->
- "Test extracting a tar archive from a binary.";
+%% Test extracting a tar archive from a binary.
extract_from_binary(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Long = filename:join(DataDir, "no_fancy_stuff.tar"),
- ?line ExtractDir = filename:join(PrivDir, "extract_from_binary"),
- ?line ok = file:make_dir(ExtractDir),
-
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Long = filename:join(DataDir, "no_fancy_stuff.tar"),
+ ExtractDir = filename:join(PrivDir, "extract_from_binary"),
+ ok = file:make_dir(ExtractDir),
+
%% Read a tar file into a binary and extract from the binary.
- ?line {ok, Bin} = file:read_file(Long),
- ?line ok = erl_tar:extract({binary, Bin}, [{cwd,ExtractDir}]),
+ {ok, Bin} = file:read_file(Long),
+ ok = erl_tar:extract({binary, Bin}, [{cwd,ExtractDir}]),
%% Verify.
Dir = filename:join(ExtractDir, "no_fancy_stuff"),
- ?line true = filelib:is_dir(Dir),
- ?line true = filelib:is_file(filename:join(Dir, "a_dir_list")),
- ?line true = filelib:is_file(filename:join(Dir, "EPLICENCE")),
+ true = filelib:is_dir(Dir),
+ true = filelib:is_file(filename:join(Dir, "a_dir_list")),
+ true = filelib:is_file(filename:join(Dir, "EPLICENCE")),
%% Clean up.
- ?line delete_files([ExtractDir]),
+ delete_files([ExtractDir]),
ok.
extract_from_binary_compressed(Config) when is_list(Config) ->
%% Test extracting a compressed tar archive from a binary.
- ?line DataDir = ?config(data_dir, Config),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Name = filename:join(DataDir, "cooked_tar_problem.tar.gz"),
- ?line ExtractDir = filename:join(PrivDir, "extract_from_binary_compressed"),
- ?line ok = file:make_dir(ExtractDir),
- ?line {ok,Bin} = file:read_file(Name),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Name = filename:join(DataDir, "cooked_tar_problem.tar.gz"),
+ ExtractDir = filename:join(PrivDir, "extract_from_binary_compressed"),
+ ok = file:make_dir(ExtractDir),
+ {ok,Bin} = file:read_file(Name),
%% Try taking contents.
- ?line {ok,Files} = erl_tar:table({binary,Bin}, [compressed]),
- ?line io:format("~p\n", [Files]),
- ?line 19 = length(Files),
-
+ {ok,Files} = erl_tar:table({binary,Bin}, [compressed]),
+ io:format("~p\n", [Files]),
+ 19 = length(Files),
+
%% Trying extracting from a binary.
- ?line ok = erl_tar:extract({binary,Bin}, [compressed,{cwd,ExtractDir}]),
- ?line {ok,List} = file:list_dir(filename:join(ExtractDir, "ddll_SUITE_data")),
- ?line io:format("~p\n", [List]),
- ?line 19 = length(List),
+ ok = erl_tar:extract({binary,Bin}, [compressed,{cwd,ExtractDir}]),
+ {ok,List} = file:list_dir(filename:join(ExtractDir, "ddll_SUITE_data")),
+ io:format("~p\n", [List]),
+ 19 = length(List),
%% Clean up while at the same time testing that all file
%% were extracted as expected.
lists:foreach(fun(N) ->
File = filename:join(ExtractDir, N),
io:format("Deleting: ~p\n", [File]),
- ?line ok = file:delete(File)
+ ok = file:delete(File)
end, Files),
%% Clean up the rest.
- ?line delete_files([ExtractDir]),
+ delete_files([ExtractDir]),
ok.
-extract_from_open_file(doc) ->
- "Test extracting a tar archive from an open file.";
+%% Test extracting a tar archive from an open file.
extract_from_open_file(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Long = filename:join(DataDir, "no_fancy_stuff.tar"),
- ?line ExtractDir = filename:join(PrivDir, "extract_from_open_file"),
- ?line ok = file:make_dir(ExtractDir),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Long = filename:join(DataDir, "no_fancy_stuff.tar"),
+ ExtractDir = filename:join(PrivDir, "extract_from_open_file"),
+ ok = file:make_dir(ExtractDir),
- ?line {ok, File} = file:open(Long, [read]),
- ?line ok = erl_tar:extract({file, File}, [{cwd,ExtractDir}]),
+ {ok, File} = file:open(Long, [read]),
+ ok = erl_tar:extract({file, File}, [{cwd,ExtractDir}]),
%% Verify.
Dir = filename:join(ExtractDir, "no_fancy_stuff"),
- ?line true = filelib:is_dir(Dir),
- ?line true = filelib:is_file(filename:join(Dir, "a_dir_list")),
- ?line true = filelib:is_file(filename:join(Dir, "EPLICENCE")),
+ true = filelib:is_dir(Dir),
+ true = filelib:is_file(filename:join(Dir, "a_dir_list")),
+ true = filelib:is_file(filename:join(Dir, "EPLICENCE")),
%% Close open file.
- ?line ok = file:close(File),
+ ok = file:close(File),
%% Clean up.
- ?line delete_files([ExtractDir]),
+ delete_files([ExtractDir]),
ok.
-symlinks(doc) ->
- "Test that archives containing symlinks can be created and extracted.";
+%% Test that archives containing symlinks can be created and extracted.
symlinks(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Dir = filename:join(PrivDir, "symlinks"),
- ?line ok = file:make_dir(Dir),
- ?line ABadSymlink = filename:join(Dir, "bad_symlink"),
- ?line PointsTo = "/a/definitely/non_existing/path",
- ?line Res = case make_symlink("/a/definitely/non_existing/path", ABadSymlink) of
- {error, enotsup} ->
- {skip, "Symbolic links not supported on this platform"};
- ok ->
- symlinks(Dir, "bad_symlink", PointsTo),
- long_symlink(Dir)
- end,
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Dir = filename:join(PrivDir, "symlinks"),
+ ok = file:make_dir(Dir),
+ ABadSymlink = filename:join(Dir, "bad_symlink"),
+ PointsTo = "/a/definitely/non_existing/path",
+ Res = case make_symlink("/a/definitely/non_existing/path", ABadSymlink) of
+ {error, enotsup} ->
+ {skip, "Symbolic links not supported on this platform"};
+ ok ->
+ symlinks(Dir, "bad_symlink", PointsTo),
+ long_symlink(Dir)
+ end,
%% Clean up.
- ?line delete_files([Dir]),
+ delete_files([Dir]),
Res.
make_symlink(Path, Link) ->
@@ -569,103 +559,103 @@ make_symlink(Path, Link) ->
_ ->
file:make_symlink(Path, Link)
end.
-
+
symlinks(Dir, BadSymlink, PointsTo) ->
- ?line Tar = filename:join(Dir, "symlink.tar"),
- ?line DerefTar = filename:join(Dir, "dereference.tar"),
+ Tar = filename:join(Dir, "symlink.tar"),
+ DerefTar = filename:join(Dir, "dereference.tar"),
%% Create the archive.
- ?line ok = file:set_cwd(Dir),
- ?line GoodSymlink = "good_symlink",
- ?line AFile = "a_good_file",
- ?line ALine = "A line of text for a file.",
- ?line ok = file:write_file(AFile, ALine),
- ?line ok = file:make_symlink(AFile, GoodSymlink),
- ?line ok = erl_tar:create(Tar, [BadSymlink, GoodSymlink, AFile], [verbose]),
+ ok = file:set_cwd(Dir),
+ GoodSymlink = "good_symlink",
+ AFile = "a_good_file",
+ ALine = "A line of text for a file.",
+ ok = file:write_file(AFile, ALine),
+ ok = file:make_symlink(AFile, GoodSymlink),
+ ok = erl_tar:create(Tar, [BadSymlink, GoodSymlink, AFile], [verbose]),
%% List contents of tar file.
- ?line ok = erl_tar:tt(Tar),
+ ok = erl_tar:tt(Tar),
%% Also create another archive with the dereference flag.
- ?line ok = erl_tar:create(DerefTar, [AFile, GoodSymlink], [dereference, verbose]),
+ ok = erl_tar:create(DerefTar, [AFile, GoodSymlink], [dereference, verbose]),
%% Extract files to a new directory.
- ?line NewDir = filename:join(Dir, "extracted"),
- ?line ok = file:make_dir(NewDir),
- ?line ok = erl_tar:extract(Tar, [{cwd, NewDir}, verbose]),
+ NewDir = filename:join(Dir, "extracted"),
+ ok = file:make_dir(NewDir),
+ ok = erl_tar:extract(Tar, [{cwd, NewDir}, verbose]),
%% Verify that the files are there.
- ?line ok = file:set_cwd(NewDir),
- ?line {ok, #file_info{type=symlink}} = file:read_link_info(BadSymlink),
- ?line {ok, PointsTo} = file:read_link(BadSymlink),
- ?line {ok, #file_info{type=symlink}} = file:read_link_info(GoodSymlink),
- ?line {ok, AFile} = file:read_link(GoodSymlink),
- ?line Expected = list_to_binary(ALine),
- ?line {ok, Expected} = file:read_file(GoodSymlink),
+ ok = file:set_cwd(NewDir),
+ {ok, #file_info{type=symlink}} = file:read_link_info(BadSymlink),
+ {ok, PointsTo} = file:read_link(BadSymlink),
+ {ok, #file_info{type=symlink}} = file:read_link_info(GoodSymlink),
+ {ok, AFile} = file:read_link(GoodSymlink),
+ Expected = list_to_binary(ALine),
+ {ok, Expected} = file:read_file(GoodSymlink),
%% Extract the "dereferenced archive" to a new directory.
- ?line NewDirDeref = filename:join(Dir, "extracted_deref"),
- ?line ok = file:make_dir(NewDirDeref),
- ?line ok = erl_tar:extract(DerefTar, [{cwd, NewDirDeref}, verbose]),
+ NewDirDeref = filename:join(Dir, "extracted_deref"),
+ ok = file:make_dir(NewDirDeref),
+ ok = erl_tar:extract(DerefTar, [{cwd, NewDirDeref}, verbose]),
%% Verify that the files are there.
- ?line ok = file:set_cwd(NewDirDeref),
- ?line {ok, #file_info{type=regular}} = file:read_link_info(GoodSymlink),
- ?line {ok, #file_info{type=regular}} = file:read_link_info(AFile),
- ?line {ok, Expected} = file:read_file(GoodSymlink),
- ?line {ok, Expected} = file:read_file(AFile),
+ ok = file:set_cwd(NewDirDeref),
+ {ok, #file_info{type=regular}} = file:read_link_info(GoodSymlink),
+ {ok, #file_info{type=regular}} = file:read_link_info(AFile),
+ {ok, Expected} = file:read_file(GoodSymlink),
+ {ok, Expected} = file:read_file(AFile),
ok.
long_symlink(Dir) ->
- ?line Tar = filename:join(Dir, "long_symlink.tar"),
- ?line ok = file:set_cwd(Dir),
-
- ?line AFile = "long_symlink",
- ?line FarTooLong = "/tmp/aarrghh/this/path/is/far/longer/than/one/hundred/characters/which/is/the/maximum/number/of/characters/allowed",
- ?line ok = file:make_symlink(FarTooLong, AFile),
- ?line {error,Error} = erl_tar:create(Tar, [AFile], [verbose]),
- ?line io:format("Error: ~s\n", [erl_tar:format_error(Error)]),
- ?line {FarTooLong,symbolic_link_too_long} = Error,
+ Tar = filename:join(Dir, "long_symlink.tar"),
+ ok = file:set_cwd(Dir),
+
+ AFile = "long_symlink",
+ FarTooLong = "/tmp/aarrghh/this/path/is/far/longer/than/one/hundred/characters/which/is/the/maximum/number/of/characters/allowed",
+ ok = file:make_symlink(FarTooLong, AFile),
+ {error,Error} = erl_tar:create(Tar, [AFile], [verbose]),
+ io:format("Error: ~s\n", [erl_tar:format_error(Error)]),
+ {FarTooLong,symbolic_link_too_long} = Error,
ok.
open_add_close(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line ok = file:set_cwd(PrivDir),
- ?line Dir = filename:join(PrivDir, "open_add_close"),
- ?line ok = file:make_dir(Dir),
-
- ?line [{FileOne,_,_},{FileTwo,_,_},{FileThree,_,_}] = oac_files(),
- ?line ADir = "empty_dir",
- ?line AnotherDir = "another_dir",
- ?line SomeContent = filename:join(AnotherDir, "some_content"),
- ?line ok = file:make_dir(ADir),
- ?line ok = file:make_dir(AnotherDir),
- ?line ok = file:make_dir(SomeContent),
-
- ?line TarOne = filename:join(Dir, "archive1.tar"),
- ?line {ok,AD} = erl_tar:open(TarOne, [write]),
- ?line ok = erl_tar:add(AD, FileOne, []),
- ?line ok = erl_tar:add(AD, FileTwo, "second file", []),
- ?line ok = erl_tar:add(AD, FileThree, [verbose]),
- ?line ok = erl_tar:add(AD, FileThree, "chunked", [{chunks,11411},verbose]),
- ?line ok = erl_tar:add(AD, ADir, [verbose]),
- ?line ok = erl_tar:add(AD, AnotherDir, [verbose]),
- ?line ok = erl_tar:close(AD),
-
- ?line ok = erl_tar:t(TarOne),
- ?line ok = erl_tar:tt(TarOne),
-
- ?line {ok,[FileOne,"second file",FileThree,"chunked",ADir,SomeContent]} = erl_tar:table(TarOne),
-
- ?line delete_files(["oac_file","oac_small","oac_big",Dir,AnotherDir,ADir]),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ ok = file:set_cwd(PrivDir),
+ Dir = filename:join(PrivDir, "open_add_close"),
+ ok = file:make_dir(Dir),
+
+ [{FileOne,_,_},{FileTwo,_,_},{FileThree,_,_}] = oac_files(),
+ ADir = "empty_dir",
+ AnotherDir = "another_dir",
+ SomeContent = filename:join(AnotherDir, "some_content"),
+ ok = file:make_dir(ADir),
+ ok = file:make_dir(AnotherDir),
+ ok = file:make_dir(SomeContent),
+
+ TarOne = filename:join(Dir, "archive1.tar"),
+ {ok,AD} = erl_tar:open(TarOne, [write]),
+ ok = erl_tar:add(AD, FileOne, []),
+ ok = erl_tar:add(AD, FileTwo, "second file", []),
+ ok = erl_tar:add(AD, FileThree, [verbose]),
+ ok = erl_tar:add(AD, FileThree, "chunked", [{chunks,11411},verbose]),
+ ok = erl_tar:add(AD, ADir, [verbose]),
+ ok = erl_tar:add(AD, AnotherDir, [verbose]),
+ ok = erl_tar:close(AD),
+
+ ok = erl_tar:t(TarOne),
+ ok = erl_tar:tt(TarOne),
+
+ {ok,[FileOne,"second file",FileThree,"chunked",ADir,SomeContent]} = erl_tar:table(TarOne),
+
+ delete_files(["oac_file","oac_small","oac_big",Dir,AnotherDir,ADir]),
ok.
@@ -678,60 +668,59 @@ oac_files() ->
cooked_compressed(Config) when is_list(Config) ->
%% Test that a compressed archive can be read in cooked mode.
- ?line DataDir = ?config(data_dir, Config),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Name = filename:join(DataDir, "cooked_tar_problem.tar.gz"),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Name = filename:join(DataDir, "cooked_tar_problem.tar.gz"),
%% Try table/2 and extract/2.
- ?line {ok,List} = erl_tar:table(Name, [cooked,compressed]),
- ?line io:format("~p\n", [List]),
- ?line 19 = length(List),
- ?line ok = erl_tar:extract(Name, [cooked,compressed,{cwd,PrivDir}]),
+ {ok,List} = erl_tar:table(Name, [cooked,compressed]),
+ io:format("~p\n", [List]),
+ 19 = length(List),
+ ok = erl_tar:extract(Name, [cooked,compressed,{cwd,PrivDir}]),
%% Clean up while at the same time testing that all file
%% were extracted as expected.
lists:foreach(fun(N) ->
File = filename:join(PrivDir, N),
io:format("Deleting: ~p\n", [File]),
- ?line ok = file:delete(File)
+ ok = file:delete(File)
end, List),
%% Clean up.
- ?line delete_files([filename:join(PrivDir, "ddll_SUITE_data")]),
+ delete_files([filename:join(PrivDir, "ddll_SUITE_data")]),
ok.
-memory(doc) ->
- ["Test that an archive can be created directly from binaries and "
- "that an archive can be extracted into binaries."];
+%% Test that an archive can be created directly from binaries and
+%% that an archive can be extracted into binaries.
memory(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
-
- ?line FileBins = [{"bar/fum", <<"BARFUM">>},{"foo", <<"FOO">>}],
- ?line Name1 = filename:join(DataDir, "memory.tar"),
- ?line ok = erl_tar:create(Name1, FileBins, [write,verbose]),
- ?line {ok,Extracted1} = erl_tar:extract(Name1, [memory,verbose]),
- ?line FileBins1 = lists:sort(Extracted1),
-
- ?line io:format("FileBins: ~p\n", [FileBins]),
- ?line io:format("FileBins1: ~p\n", [FileBins1]),
- ?line FileBins = FileBins1,
-
- ?line Name2 = filename:join(DataDir, "memory2.tar"),
- ?line {ok,Fd} = erl_tar:open(Name2, [write]),
- ?line [ok,ok] = [erl_tar:add(Fd, B, N, [write,verbose]) || {N,B} <- FileBins],
- ?line ok = erl_tar:close(Fd),
- ?line {ok,Extracted2} = erl_tar:extract(Name2, [memory,verbose]),
- ?line FileBins2 = lists:sort(Extracted2),
- ?line io:format("FileBins2: ~p\n", [FileBins2]),
- ?line FileBins = FileBins2,
+ DataDir = proplists:get_value(data_dir, Config),
+
+ FileBins = [{"bar/fum", <<"BARFUM">>},{"foo", <<"FOO">>}],
+ Name1 = filename:join(DataDir, "memory.tar"),
+ ok = erl_tar:create(Name1, FileBins, [write,verbose]),
+ {ok,Extracted1} = erl_tar:extract(Name1, [memory,verbose]),
+ FileBins1 = lists:sort(Extracted1),
+
+ io:format("FileBins: ~p\n", [FileBins]),
+ io:format("FileBins1: ~p\n", [FileBins1]),
+ FileBins = FileBins1,
+
+ Name2 = filename:join(DataDir, "memory2.tar"),
+ {ok,Fd} = erl_tar:open(Name2, [write]),
+ [ok,ok] = [erl_tar:add(Fd, B, N, [write,verbose]) || {N,B} <- FileBins],
+ ok = erl_tar:close(Fd),
+ {ok,Extracted2} = erl_tar:extract(Name2, [memory,verbose]),
+ FileBins2 = lists:sort(Extracted2),
+ io:format("FileBins2: ~p\n", [FileBins2]),
+ FileBins = FileBins2,
%% Clean up.
- ?line ok = delete_files([Name1,Name2]),
+ ok = delete_files([Name1,Name2]),
ok.
%% Test filenames with characters outside the US ASCII range.
unicode(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
do_unicode(PrivDir),
case has_transparent_naming() of
true ->
@@ -811,7 +800,7 @@ delete_files([Item|Rest]) ->
%% 260 characters.
run_in_short_tempdir(Config, Fun) ->
{ok,Cwd} = file:get_cwd(),
- PrivDir0 = ?config(priv_dir, Config),
+ PrivDir0 = proplists:get_value(priv_dir, Config),
%% Normalize name to make sure that there is no slash at the end.
PrivDir = filename:absname(PrivDir0),
@@ -850,7 +839,7 @@ start_node(Name, Args) ->
ct:log("Trying to start ~w@~s~n", [Name,Host]),
case test_server:start_node(Name, peer, [{args,Args}]) of
{error,Reason} ->
- test_server:fail(Reason);
+ ct:fail(Reason);
{ok,Node} ->
ct:log("Node ~p started~n", [Node]),
Node
diff --git a/lib/stdlib/test/timer_SUITE.erl b/lib/stdlib/test/timer_SUITE.erl
index 057d82fb65..d4bbd39d50 100644
--- a/lib/stdlib/test/timer_SUITE.erl
+++ b/lib/stdlib/test/timer_SUITE.erl
@@ -24,7 +24,7 @@
-export([big_test/1, collect/3, i_t/3, a_t/2]).
-export([do_nrev/1, internal_watchdog/2]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Random test of the timer module. This is a really nasty test, as it
%% runs a lot of timeouts and then checks in the end if any of them
@@ -41,7 +41,9 @@
%% reasonable on different machines; therefore the test can sometimes
%% fail, even though the timer module is ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,20}}].
all() ->
[do_big_test].
@@ -65,23 +67,19 @@ end_per_group(_GroupName, Config) ->
%% ------------------------------------------------------- %%
do_big_test(TConfig) when is_list(TConfig) ->
- Dog = ?t:timetrap(?t:minutes(20)),
Save = process_flag(trap_exit, true),
Result = big_test(200),
process_flag(trap_exit, Save),
- ?t:timetrap_cancel(Dog),
report_result(Result).
report_result(ok) -> ok;
-report_result(Error) -> ?line test_server:fail(Error).
+report_result(Error) -> ct:fail(Error).
%% ------------------------------------------------------- %%
big_test(N) ->
C = start_collect(),
system_time(), system_time(), system_time(),
- random:seed(erlang:timestamp()),
- random:uniform(100),random:uniform(100),random:uniform(100),
big_loop(C, N, []),
@@ -100,7 +98,7 @@ big_test(N) ->
Result = analyze_report(Report),
%%io:format("big_test is done: ~w~n", [Result]),
Result.
-
+
big_loop(_C, 0, []) ->
%%io:format("All processes are done!~n", []),
ok;
@@ -111,8 +109,8 @@ big_loop(C, 0, Pids) ->
{'EXIT', Pid, done} ->
big_loop(C, 0, lists:delete(Pid, Pids));
{'EXIT', Pid, Error} ->
- ?line ok = io:format("XXX Pid ~w died with reason ~p~n",
- [Pid, Error]),
+ ok = io:format("XXX Pid ~w died with reason ~p~n",
+ [Pid, Error]),
big_loop(C, 0, lists:delete(Pid, Pids))
end;
big_loop(C, N, Pids) ->
@@ -121,24 +119,24 @@ big_loop(C, N, Pids) ->
{'EXIT', Pid, done} ->
big_loop(C, N, lists:delete(Pid, Pids));
{'EXIT', Pid, Error} ->
- ?line ok =io:format("XXX Internal error: Pid ~w died, reason ~p~n",
- [Pid, Error]),
+ ok =io:format("XXX Internal error: Pid ~w died, reason ~p~n",
+ [Pid, Error]),
big_loop(C, N, lists:delete(Pid, Pids))
after 0 ->
%% maybe start an interval timer test
- Pids1 = maybe_start_i_test(Pids, C, random:uniform(4)),
-
+ Pids1 = maybe_start_i_test(Pids, C, rand:uniform(4)),
+
%% start 1-4 "after" tests
- Pids2 = start_after_test(Pids1, C, random:uniform(4)),
+ Pids2 = start_after_test(Pids1, C, rand:uniform(4)),
%%Pids2=Pids1,
%% wait a little while
- timer:sleep(random:uniform(200)*3),
+ timer:sleep(rand:uniform(200)*3),
%% spawn zero, one or two nrev to get some load ;-/
- Pids3 = start_nrev(Pids2, random:uniform(100)),
-
+ Pids3 = start_nrev(Pids2, rand:uniform(100)),
+
big_loop(C, N-1, Pids3)
end.
@@ -148,20 +146,20 @@ start_nrev(Pids, N) when N < 25 ->
start_nrev(Pids, N) when N < 75 ->
[spawn_link(timer_SUITE, do_nrev, [1])|Pids];
start_nrev(Pids, _N) ->
- NrevPid1 = spawn_link(timer_SUITE, do_nrev, [random:uniform(1000)*10]),
+ NrevPid1 = spawn_link(timer_SUITE, do_nrev, [rand:uniform(1000)*10]),
NrevPid2 = spawn_link(timer_SUITE, do_nrev, [1]),
[NrevPid1,NrevPid2|Pids].
-
+
start_after_test(Pids, C, 1) ->
- TO1 = random:uniform(100)*47,
+ TO1 = rand:uniform(100)*47,
[s_a_t(C, TO1)|Pids];
start_after_test(Pids, C, 2) ->
- TO1 = random:uniform(100)*47,
- TO2 = TO1 div random:uniform(3) + 101,
+ TO1 = rand:uniform(100)*47,
+ TO2 = TO1 div rand:uniform(3) + 101,
[s_a_t(C, TO1),s_a_t(C, TO2)|Pids];
start_after_test(Pids, C, N) ->
- TO1 = random:uniform(100)*47,
+ TO1 = rand:uniform(100)*47,
start_after_test([s_a_t(C, TO1)|Pids], C, N-1).
s_a_t(C, TimeOut) ->
@@ -179,16 +177,16 @@ a_t(C, TimeOut) ->
watchdog ->
Stop = system_time(),
report(C, Start,Stop,TimeOut),
- ?line ok = io:format("Internal watchdog timeout (a), not good!!~n",
- []),
+ ok = io:format("Internal watchdog timeout (a), not good!!~n",
+ []),
exit(done)
end.
maybe_start_i_test(Pids, C, 1) ->
%% ok do it
- TOI = random:uniform(53)*49,
- CountI = random:uniform(10) + 3, % at least 4 times
+ TOI = rand:uniform(53)*49,
+ CountI = rand:uniform(10) + 3, % at least 4 times
[spawn_link(timer_SUITE, i_t, [C, TOI, CountI])|Pids];
maybe_start_i_test(Pids, _C, _) ->
Pids.
@@ -210,8 +208,8 @@ i_wait(Start, Prev, Times, TimeOut, Times, Ref, C) ->
Now = system_time(),
report_interval(C, {final,Times}, Start, Prev, Now, TimeOut),
timer:cancel(Ref),
- ?line ok = io:format("Internal watchdog timeout (i), not good!!~n",
- []),
+ ok = io:format("Internal watchdog timeout (i), not good!!~n",
+ []),
exit(done)
end;
i_wait(Start, Prev, Count, TimeOut, Times, Ref, C) ->
@@ -223,8 +221,8 @@ i_wait(Start, Prev, Count, TimeOut, Times, Ref, C) ->
watchdog ->
Now = system_time(),
report_interval(C, {final,Count}, Start, Prev, Now, TimeOut),
- ?line ok = io:format("Internal watchdog timeout (j), not good!!~n",
- []),
+ ok = io:format("Internal watchdog timeout (j), not good!!~n",
+ []),
exit(done)
end.
@@ -291,13 +289,6 @@ update(New, Stat) when New < Stat#stat.min ->
update(New, Stat) ->
Stat#stat{n=Stat#stat.n + 1, avg=(New+Stat#stat.avg) div 2}.
-%update(New, {N,Max,Min,Avg}) when New>Max ->
-% {N+1,New,Min,(New+Avg) div 2};
-%update(New, {N,Max,Min,Avg}) when New<Min ->
-% {N+1,Max,New,(New+Avg) div 2};
-%update(New, {N,Max,Min,Avg}) ->
-% {N+1,Max,Min,(New+Avg) div 2}.
-
print_report({E,LateS,EarlyS,I}) ->
Early = EarlyS#stat.n, Late = LateS#stat.n,
Total = E + Early + Late,
@@ -381,10 +372,10 @@ nrev([]) ->
[];
nrev([H|T]) ->
append(nrev(T), [H]).
-
+
append([H|T],Z) ->
- [H|append(T,Z)];
+ [H|append(T,Z)];
append([],X) ->
- X.
+ X.
%% ------------------------------------------------------- %%
diff --git a/lib/stdlib/test/timer_simple_SUITE.erl b/lib/stdlib/test/timer_simple_SUITE.erl
index 93fbc3a032..64fce2a4b2 100644
--- a/lib/stdlib/test/timer_simple_SUITE.erl
+++ b/lib/stdlib/test/timer_simple_SUITE.erl
@@ -51,12 +51,14 @@
timer/4,
timer/5]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(MAXREF, (1 bsl 18)).
-define(REFMARG, 30).
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,10}}].
all() ->
[apply_after, send_after1, send_after2, send_after3,
@@ -87,222 +89,198 @@ init_per_testcase(_, Config) when is_list(Config) ->
%% Testing timer interface!!
-apply_after(doc) -> "Test of apply_after, with sending of message.";
-apply_after(suite) -> [];
+%% Test of apply_after, with sending of message.
apply_after(Config) when is_list(Config) ->
- ?line timer:apply_after(500, ?MODULE, send, [self(), ok_apply]),
- ?line ok = get_mess(1000, ok_apply).
+ timer:apply_after(500, ?MODULE, send, [self(), ok_apply]),
+ ok = get_mess(1000, ok_apply).
-send_after1(doc) -> "Test of send_after with time = 0.";
-send_after1(suite) -> [];
+%% Test of send_after with time = 0.
send_after1(Config) when is_list(Config) ->
- ?line timer:send_after(0, ok_send1),
- ?line ok = get_mess(1000, ok_send1).
+ timer:send_after(0, ok_send1),
+ ok = get_mess(1000, ok_send1).
-send_after2(doc) -> "Test of send_after with time = 500.";
-send_after2(suite) -> [];
+%% Test of send_after with time = 500.
send_after2(Config) when is_list(Config) ->
- ?line timer:send_after(500, self(), ok_send2),
- ?line ok = get_mess(2000, ok_send2).
+ timer:send_after(500, self(), ok_send2),
+ ok = get_mess(2000, ok_send2).
-send_after3(doc) -> "Test of send_after with time = 500, with receiver "
- "a registered process. [OTP-2735]";
-send_after3(suite) -> [];
+%% Test of send_after with time = 500, with receiver a registered
+%% process. [OTP-2735]
send_after3(Config) when is_list(Config) ->
- ?line Name = list_to_atom(pid_to_list(self())),
- ?line register(Name, self()),
- ?line timer:send_after(500, Name, ok_send3),
- ?line ok = get_mess(2000, ok_send3),
- ?line unregister(Name).
-
-exit_after1(doc) -> "Test of exit_after with time = 1000.";
-exit_after1(suite) -> [];
+ Name = list_to_atom(pid_to_list(self())),
+ register(Name, self()),
+ timer:send_after(500, Name, ok_send3),
+ ok = get_mess(2000, ok_send3),
+ unregister(Name).
+
+%% Test of exit_after with time = 1000.
exit_after1(Config) when is_list(Config) ->
- ?line process_flag(trap_exit, true),
- ?line Pid = spawn_link(?MODULE, forever, []),
- ?line timer:exit_after(1000, Pid, exit_test1),
- ?line ok = get_mess(5000, {'EXIT', Pid, exit_test1}).
-
-exit_after2(doc) -> "Test of exit_after with time = 1000. The process to "
- "exit is the name of a registered process. "
- "[OTP-2735]";
-exit_after2(suite) -> [];
+ process_flag(trap_exit, true),
+ Pid = spawn_link(?MODULE, forever, []),
+ timer:exit_after(1000, Pid, exit_test1),
+ ok = get_mess(5000, {'EXIT', Pid, exit_test1}).
+
+%% Test of exit_after with time = 1000. The process to exit is the
+%% name of a registered process. [OTP-2735]
exit_after2(Config) when is_list(Config) ->
- ?line process_flag(trap_exit, true),
- ?line Pid = spawn_link(?MODULE, forever, []),
- ?line Name = list_to_atom(pid_to_list(Pid)),
- ?line register(Name, Pid),
- ?line timer:exit_after(1000, Name, exit_test2),
- ?line ok = get_mess(2000, {'EXIT', Pid, exit_test2}).
-
-kill_after1(doc) -> "Test of kill_after with time = 1000.";
-kill_after1(suite) -> [];
+ process_flag(trap_exit, true),
+ Pid = spawn_link(?MODULE, forever, []),
+ Name = list_to_atom(pid_to_list(Pid)),
+ register(Name, Pid),
+ timer:exit_after(1000, Name, exit_test2),
+ ok = get_mess(2000, {'EXIT', Pid, exit_test2}).
+
+%% Test of kill_after with time = 1000.
kill_after1(Config) when is_list(Config) ->
- ?line process_flag(trap_exit, true),
- ?line Pid = spawn_link(?MODULE, forever, []),
- ?line timer:kill_after(1000, Pid),
- ?line ok = get_mess(2000, {'EXIT', Pid, killed}).
-
-kill_after2(doc) -> "Test of kill_after with time = 1000. The process to "
- "exit is the name of a registered process. "
- "[OTP-2735]";
-kill_after2(suite) -> [];
+ process_flag(trap_exit, true),
+ Pid = spawn_link(?MODULE, forever, []),
+ timer:kill_after(1000, Pid),
+ ok = get_mess(2000, {'EXIT', Pid, killed}).
+
+%% Test of kill_after with time = 1000. The process to exit is the
+%% name of a registered process. [OTP-2735]
kill_after2(Config) when is_list(Config) ->
- ?line process_flag(trap_exit, true),
- ?line Pid = spawn_link(?MODULE, forever, []),
- ?line Name = list_to_atom(pid_to_list(Pid)),
- ?line register(Name, Pid),
- ?line timer:kill_after(1000, Name),
- ?line ok = get_mess(2000, {'EXIT', Pid, killed}).
-
-apply_interval(doc) -> "Test of apply_interval by sending messages. Receive "
- "3 messages, cancel the timer, and check that we do "
- "not get any more messages.";
-apply_interval(suite) -> [];
+ process_flag(trap_exit, true),
+ Pid = spawn_link(?MODULE, forever, []),
+ Name = list_to_atom(pid_to_list(Pid)),
+ register(Name, Pid),
+ timer:kill_after(1000, Name),
+ ok = get_mess(2000, {'EXIT', Pid, killed}).
+
+%% Test of apply_interval by sending messages. Receive
+%% 3 messages, cancel the timer, and check that we do
+%% not get any more messages.
apply_interval(Config) when is_list(Config) ->
- ?line {ok, Ref} = timer:apply_interval(1000, ?MODULE, send,
+ {ok, Ref} = timer:apply_interval(1000, ?MODULE, send,
[self(), apply_int]),
- ?line ok = get_mess(1500, apply_int, 3),
- ?line timer:cancel(Ref),
- ?line nor = get_mess(1000, apply_int).
-
-send_interval1(doc) -> "Test of send_interval/2. Receive 5 messages, cancel "
- "the timer, and check that we do not get any more "
- "messages.";
-send_interval1(suite) -> [];
+ ok = get_mess(1500, apply_int, 3),
+ timer:cancel(Ref),
+ nor = get_mess(1000, apply_int).
+
+%% Test of send_interval/2. Receive 5 messages, cancel the timer, and
+%% check that we do not get any more messages.
send_interval1(Config) when is_list(Config) ->
{ok, Ref} = timer:send_interval(1000, send_int),
- ?line ok = get_mess(1500, send_int, 5),
+ ok = get_mess(1500, send_int, 5),
timer:cancel(Ref),
- ?line nor = get_mess(1000, send_int). % We should receive only five
+ nor = get_mess(1000, send_int). % We should receive only five
-send_interval2(doc) -> "Test of send_interval/3. Receive 2 messages, cancel "
- "the timer, and check that we do not get any more "
- "messages.";
-send_interval2(suite) -> [];
+%% Test of send_interval/3. Receive 2 messages, cancel the timer, and
+%% check that we do not get any more messages.
send_interval2(Config) when is_list(Config) ->
{ok, Ref} = timer:send_interval(1000, self(), send_int2),
- ?line ok = get_mess(1500, send_int2, 2),
+ ok = get_mess(1500, send_int2, 2),
timer:cancel(Ref),
- ?line nor = get_mess(1000, send_int2). % We should receive only two
+ nor = get_mess(1000, send_int2). % We should receive only two
-send_interval3(doc) -> "Test of send_interval/3. Receive 2 messages, cancel "
- "the timer, and check that we do not get any more "
- "messages. The receiver is the name of a registered "
- "process. [OTP-2735]";
-send_interval3(suite) -> [];
+%% Test of send_interval/3. Receive 2 messages, cancel the timer, and
+%% check that we do not get any more messages. The receiver is the
+%% name of a registered process. [OTP-2735]
send_interval3(Config) when is_list(Config) ->
- ?line process_flag(trap_exit, true),
- ?line Name = list_to_atom(pid_to_list(self())),
- ?line register(Name, self()),
- ?line {ok, Ref} = timer:send_interval(1000, Name, send_int3),
- ?line ok = get_mess(1500, send_int3, 2),
+ process_flag(trap_exit, true),
+ Name = list_to_atom(pid_to_list(self())),
+ register(Name, self()),
+ {ok, Ref} = timer:send_interval(1000, Name, send_int3),
+ ok = get_mess(1500, send_int3, 2),
timer:cancel(Ref),
- ?line nor = get_mess(1000, send_int3), % We should receive only two
- ?line unregister(Name).
+ nor = get_mess(1000, send_int3), % We should receive only two
+ unregister(Name).
-send_interval4(doc) -> "Test that send interval stops sending msg when the "
- "receiving process terminates.";
-send_interval4(suite) -> [];
+%% Test that send interval stops sending msg when the receiving
+%% process terminates.
send_interval4(Config) when is_list(Config) ->
- ?line timer:send_interval(500, one_time_only),
+ timer:send_interval(500, one_time_only),
receive
one_time_only -> ok
end,
- ?line timer_server ! {'EXIT', self(), normal}, % Should remove the timer
- ?line timer:send_after(600, send_intv_ok),
- ?line send_intv_ok = receive
- Msg -> Msg
- end.
-
-cancel1(doc) -> "Test that we can cancel a timer.";
-cancel1(suite) -> [];
+ timer_server ! {'EXIT', self(), normal}, % Should remove the timer
+ timer:send_after(600, send_intv_ok),
+ send_intv_ok = receive
+ Msg -> Msg
+ end.
+
+%% Test that we can cancel a timer.
cancel1(Config) when is_list(Config) ->
- ?line {ok, Ref} = timer:send_after(1000, this_should_be_canceled),
- ?line timer:cancel(Ref),
- ?line nor = get_mess(2000, this_should_be_canceled). % We should rec 0 msgs
+ {ok, Ref} = timer:send_after(1000, this_should_be_canceled),
+ timer:cancel(Ref),
+ nor = get_mess(2000, this_should_be_canceled). % We should rec 0 msgs
-cancel2(doc) -> "Test cancel/1 with bad argument.";
-cancel2(suite) -> [];
+%% Test cancel/1 with bad argument.
cancel2(Config) when is_list(Config) ->
- ?line {error, badarg} = timer:cancel(no_reference).
+ {error, badarg} = timer:cancel(no_reference).
-tc(doc) -> "Test sleep/1 and tc/3.";
-tc(suite) -> [];
+%% Test sleep/1 and tc/3.
tc(Config) when is_list(Config) ->
%% This should test both sleep and tc/3
- ?line {Res1, ok} = timer:tc(timer, sleep, [500]),
- ?line ok = if
+ {Res1, ok} = timer:tc(timer, sleep, [500]),
+ ok = if
Res1 < 500*1000 -> {too_early, Res1}; % Too early
Res1 > 800*1000 -> {too_late, Res1}; % Too much time
true -> ok
end,
%% tc/2
- ?line {Res2, ok} = timer:tc(fun(T) -> timer:sleep(T) end, [500]),
- ?line ok = if
+ {Res2, ok} = timer:tc(fun(T) -> timer:sleep(T) end, [500]),
+ ok = if
Res2 < 500*1000 -> {too_early, Res2}; % Too early
Res2 > 800*1000 -> {too_late, Res2}; % Too much time
true -> ok
end,
-
+
%% tc/1
- ?line {Res3, ok} = timer:tc(fun() -> timer:sleep(500) end),
- ?line ok = if
+ {Res3, ok} = timer:tc(fun() -> timer:sleep(500) end),
+ ok = if
Res3 < 500*1000 -> {too_early, Res3}; % Too early
Res3 > 800*1000 -> {too_late, Res3}; % Too much time
true -> ok
end,
%% Check that timer:tc don't catch errors
- ?line ok = try timer:tc(erlang, exit, [foo])
- catch exit:foo -> ok
- end,
-
- ?line ok = try timer:tc(fun(Reason) -> 1 = Reason end, [foo])
- catch error:{badmatch,_} -> ok
- end,
-
- ?line ok = try timer:tc(fun() -> throw(foo) end)
- catch foo -> ok
- end,
-
+ ok = try timer:tc(erlang, exit, [foo])
+ catch exit:foo -> ok
+ end,
+
+ ok = try timer:tc(fun(Reason) -> 1 = Reason end, [foo])
+ catch error:{badmatch,_} -> ok
+ end,
+
+ ok = try timer:tc(fun() -> throw(foo) end)
+ catch foo -> ok
+ end,
+
%% Check that return values are propageted
Self = self(),
- ?line {_, Self} = timer:tc(erlang, self, []),
- ?line {_, Self} = timer:tc(fun(P) -> P end, [self()]),
- ?line {_, Self} = timer:tc(fun() -> self() end),
-
- ?line Sec = timer:seconds(4),
- ?line Min = timer:minutes(4),
- ?line Hour = timer:hours(4),
- ?line MyRes = 4*1000 + 4*60*1000 + 4*60*60*1000,
- ?line if MyRes == Sec + Min + Hour -> ok end,
- ?line TimerRes = timer:hms(4,4,4),
- ?line if MyRes == TimerRes -> ok end,
+ {_, Self} = timer:tc(erlang, self, []),
+ {_, Self} = timer:tc(fun(P) -> P end, [self()]),
+ {_, Self} = timer:tc(fun() -> self() end),
+
+ Sec = timer:seconds(4),
+ Min = timer:minutes(4),
+ Hour = timer:hours(4),
+ MyRes = 4*1000 + 4*60*1000 + 4*60*60*1000,
+ if MyRes == Sec + Min + Hour -> ok end,
+ TimerRes = timer:hms(4,4,4),
+ if MyRes == TimerRes -> ok end,
ok.
-unique_refs(doc) ->
- "Tests that cancellations of one-shot timers do not accidentally "
- "cancel interval timers [OTP-2771].";
-unique_refs(suite) ->
- [];
+%% Test that cancellations of one-shot timers do not accidentally
+%% cancel interval timers. [OTP-2771].
unique_refs(Config) when is_list(Config) ->
- ?line ITimers = repeat_send_interval(10), % 10 interval timers
- ?line eat_refs(?MAXREF - ?REFMARG),
- ?line set_and_cancel_one_shots(?REFMARG),
- ?line NumLeft = num_timers(),
- ?line io:format("~w timers left, should be 10\n", [NumLeft]),
- ?line cancel(ITimers),
- ?line receive_nisse(),
- ?line 10 = NumLeft.
+ ITimers = repeat_send_interval(10), % 10 interval timers
+ eat_refs(?MAXREF - ?REFMARG),
+ set_and_cancel_one_shots(?REFMARG),
+ NumLeft = num_timers(),
+ io:format("~w timers left, should be 10\n", [NumLeft]),
+ cancel(ITimers),
+ receive_nisse(),
+ 10 = NumLeft.
repeat_send_interval(0) ->
[];
repeat_send_interval(M) ->
- ?line {ok, Ref} = timer:send_interval(6000,self(), nisse),
- ?line [Ref| repeat_send_interval(M - 1)].
+ {ok, Ref} = timer:send_interval(6000,self(), nisse),
+ [Ref| repeat_send_interval(M - 1)].
eat_refs(0) ->
0;
@@ -320,8 +298,8 @@ set_and_cancel_one_shots(N) ->
set_and_cancel_one_shots(N-1).
cancel([T| Ts]) ->
- ?line timer:cancel(T),
- ?line cancel(Ts);
+ timer:cancel(T),
+ cancel(Ts);
cancel([]) ->
ok.
@@ -344,7 +322,7 @@ get_mess(Time, Mess, N) ->
receive
Mess -> get_mess(Time, Mess, N-1)
after Time
- -> nor % Not Received
+ -> nor % Not Received
end.
forever() ->
@@ -352,16 +330,13 @@ forever() ->
forever().
-%
-% Testing for performance (on different implementations) of timers
-%
+%%
+%% Testing for performance (on different implementations) of timers
+%%
+
-timer_perf(suite) -> [];
timer_perf(Config) when is_list(Config) ->
- Dog = ?t:timetrap(?t:minutes(10)),
- Res = performance(timer),
- ?t:timetrap_cancel(Dog),
- Res.
+ performance(timer).
performance(Mod) ->
process_flag(trap_exit, true),
@@ -374,7 +349,7 @@ performance(Mod) ->
big_test(M) ->
Load_Pids = start_nrev(20, M), % Increase if more load wanted :)
-
+
LPids = spawn_timers(5, M, 10000, 5),
apply(M, sleep, [4000]),
@@ -384,7 +359,7 @@ big_test(M) ->
SPids = spawn_timers(15, M, 100, 3),
Res = wait(SPids ++ MPids ++ LPids, [], 0, M),
-
+
lists:foreach(fun(Pid) -> exit(Pid, kill) end, Load_Pids),
Res.
@@ -395,12 +370,12 @@ wait(Pids, ResList, N, M) ->
{Pid, ok, Res, T} ->
wait(lists:delete(Pid, Pids), [{T, Res} | ResList], N, M);
{Pid, Error}->
- ?line test_server:fail(Error),
+ ct:fail(Error),
wait(lists:delete(Pid, Pids), ResList, N+1, M);
{'EXIT', Pid, normal} ->
wait(lists:delete(Pid, Pids), ResList, N, M);
{'EXIT', Pid, Reason} ->
- ?line test_server:fail({Pid,Reason})
+ ct:fail({Pid,Reason})
end.
spawn_timers(0, _, _, _) ->
@@ -440,7 +415,6 @@ timer_irec(Start, T, {N, Max}, Res, {Pid, Mod, Ref}) ->
done ->
Now = system_time(),
Elapsed = (Now - (Start + (N*T*1000))) div 1000,
-% io:format("~w Now ~w Started ~w Elap ~w~n", [T,Now,Start,Elapsed]),
timer_irec(Start, T,
{N+1, Max},
[Elapsed | Res],
@@ -476,11 +450,11 @@ nrev([]) ->
[];
nrev([H|T]) ->
append(nrev(T), [H]).
-
+
append([H|T],Z) ->
- [H|append(T,Z)];
+ [H|append(T,Z)];
append([],X) ->
- X.
+ X.
system_time() ->
erlang:monotonic_time(micro_seconds).
@@ -488,7 +462,6 @@ system_time() ->
%% ------------------------------------------------------- %%
report_result({Res, 0}) ->
-% io:format("DEBUG0 all ~p ~n", [Res]),
{A_List, I_List} = split_list(Res, [], []),
A_val = calc_a_val(A_List),
I_val = calc_i_val(I_List),
@@ -497,7 +470,7 @@ report_result({Res, 0}) ->
report_result({Head, N}) ->
io:format("Test Failed: Number of internal tmo ~w~n", [N]),
- ?line test_server:fail({Head, N}).
+ ct:fail({Head, N}).
split_list([], AL, IL) ->
{AL, IL};
@@ -547,11 +520,11 @@ get_ivals(List) ->
LTot = lists:map(fun(X) -> element(2, X) end, List),
LMin = lists:map(fun(X) -> element(4, X) end, List),
LMax = lists:map(fun(X) -> element(5, X) end, List),
-
+
MaxTot = lists:max(LTot),
MinTot = lists:min(LTot),
AverTot = lists:sum(LTot) div Len,
-
+
IterMax = lists:max(LMax),
IterMin = lists:min(LMin),
IterAver= AverTot div Num,
diff --git a/lib/stdlib/test/unicode_SUITE.erl b/lib/stdlib/test/unicode_SUITE.erl
index 8bb2555213..d2ee5d19a4 100644
--- a/lib/stdlib/test/unicode_SUITE.erl
+++ b/lib/stdlib/test/unicode_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(unicode_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
@@ -37,16 +37,16 @@
ex_binaries_errors_utf16_big/1,
ex_binaries_errors_utf32_little/1,
ex_binaries_errors_utf32_big/1]).
-
-init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog=?t:timetrap(?t:minutes(20)),
- [{watchdog, Dog}|Config].
-end_per_testcase(_Case, Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog).
+init_per_testcase(_Case, Config) ->
+ Config.
+
+end_per_testcase(_Case, _Config) ->
+ ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,20}}].
all() ->
[utf8_illegal_sequences_bif,
@@ -80,7 +80,7 @@ binaries_errors_limit(Config) when is_list(Config) ->
ex_binaries_errors_utf8(Config),
setlimit(default),
ok.
-
+
ex_binaries_errors_utf8(Config) when is_list(Config) ->
%% Original smoke test, we should not forget the original offset...
<<_:8,_:8,RR2/binary>> = <<$a,$b,164,165,$c>>,
@@ -151,10 +151,10 @@ utf16_inner_loop([_|List], BrokenPart, BrokenSz, PartlyBroken, PBSz, Endian) ->
utf16_inner_loop(List, BrokenPart, BrokenSz, PartlyBroken, PBSz, Endian);
utf16_inner_loop([], _, _, _, _, _) ->
ok.
-
+
ex_binaries_errors_utf32_big(Config) when is_list(Config) ->
ex_binaries_errors_utf32(big).
-
+
ex_binaries_errors_utf32_little(Config) when is_list(Config) ->
ex_binaries_errors_utf32(little).
@@ -180,7 +180,7 @@ ex_binaries_errors_utf32(Endian) ->
PartlyBroken, PBSz, Endian)
end || N <- lists:seq(1, 16, 3) ],
ok.
-
+
utf32_inner_loop([_|List], BrokenPart, BrokenSz, PartlyBroken, PBSz, Endian) ->
Sz = length(List)*4 + BrokenSz,
Chomped = binary:part(PartlyBroken, PBSz - Sz, Sz),
@@ -199,115 +199,115 @@ exceptions(Config) when is_list(Config) ->
ex_exceptions(Config).
ex_exceptions(Config) when is_list(Config) ->
- ?line L = lists:seq(0,255),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L++255,unicode)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary({1,2,3},unicode)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(1,unicode)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(1.0,unicode)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary('1',unicode)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary([1,2,3,apa],unicode)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary([1,2,3,4.0],unicode)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L++255,latin1)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary({1,2,3},latin1)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(1,latin1)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(1.0,latin1)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary('1',latin1)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary([1,2,3,apa],latin1)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary([1,2,3,4.0],latin1)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,gnarfl)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,L)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,{latin1})),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,[latin1])),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,1)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,1.0)),
+ L = lists:seq(0,255),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L++255,unicode)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary({1,2,3},unicode)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(1,unicode)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(1.0,unicode)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary('1',unicode)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary([1,2,3,apa],unicode)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary([1,2,3,4.0],unicode)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L++255,latin1)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary({1,2,3},latin1)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(1,latin1)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(1.0,latin1)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary('1',latin1)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary([1,2,3,apa],latin1)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary([1,2,3,4.0],latin1)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,gnarfl)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,L)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,{latin1})),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,[latin1])),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,1)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,1.0)),
Encodings = [unicode, utf8,utf16,utf32,{utf16,big},
{utf16,little},{utf32,big},{utf32,little}],
[ begin
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L++255,unicode,Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary({1,2,3},unicode,Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(1,unicode,Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(1.0,unicode,Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary('1',unicode,Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary([1,2,3,apa],unicode,
- Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary([1,2,3,4.0],unicode,
- Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L++255,latin1,Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary({1,2,3},latin1,Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(1,latin1,Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(1.0,latin1,Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary('1',latin1,Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary([1,2,3,apa],latin1,
- Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary([1,2,3,4.0],latin1,
- Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,gnarfl,Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,L,Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,{latin1},Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,[latin1],Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,1,Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,1.0,Enc))
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L++255,unicode,Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary({1,2,3},unicode,Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(1,unicode,Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(1.0,unicode,Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary('1',unicode,Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary([1,2,3,apa],unicode,
+ Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary([1,2,3,4.0],unicode,
+ Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L++255,latin1,Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary({1,2,3},latin1,Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(1,latin1,Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(1.0,latin1,Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary('1',latin1,Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary([1,2,3,apa],latin1,
+ Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary([1,2,3,4.0],latin1,
+ Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,gnarfl,Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,L,Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,{latin1},Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,[latin1],Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,1,Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_binary(L,1.0,Enc))
end || Enc <- Encodings ],
Encodings2 = [latin1, unicode, utf8,utf16,utf32,{utf16,big},
- {utf16,little},{utf32,big},{utf32,little}],
+ {utf16,little},{utf32,big},{utf32,little}],
[ begin
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(L++255,Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_list({1,2,3},Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(1,Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(1.0,Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_list('1',Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_list([1,2,3,apa],Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_list([1,2,3,4.0],Enc)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(L,{Enc})),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(L,[Enc]))
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(L++255,Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_list({1,2,3},Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(1,Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(1.0,Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_list('1',Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_list([1,2,3,apa],Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_list([1,2,3,4.0],Enc)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(L,{Enc})),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(L,[Enc]))
end || Enc <- Encodings2 ],
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(L,gnarfl)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(L,L)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(L,1)),
- ?line {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(L,1.0)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(L,gnarfl)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(L,L)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(L,1)),
+ {'EXIT',{badarg,_}} = (catch unicode:characters_to_list(L,1.0)),
[ begin
- ?line Bx = unicode:characters_to_binary(L,latin1, Enc),
- ?line L = unicode:characters_to_list(Bx,Enc)
+ Bx = unicode:characters_to_binary(L,latin1, Enc),
+ L = unicode:characters_to_list(Bx,Enc)
end || Enc <- Encodings ],
- ?line B = unicode:characters_to_binary(L,latin1),
- ?line L = unicode:characters_to_list(B,unicode),
- ?line L = unicode:characters_to_list(list_to_binary(L),latin1),
- ?line More = <<B/binary,0,1,2>>,
- ?line B2 = list_to_binary([254,255]),
- ?line B3 = list_to_binary([0,1,2,254,255]),
- ?line {error,B,Rest1} = unicode:characters_to_binary([L,B2],unicode),
- ?line B2 = iolist_to_binary(Rest1),
- ?line {error,More,Rest2} = unicode:characters_to_binary([L,B3],unicode),
- [ begin ?line {error,_,_} = unicode:characters_to_binary([L,B2],unicode,Enc) end
+ B = unicode:characters_to_binary(L,latin1),
+ L = unicode:characters_to_list(B,unicode),
+ L = unicode:characters_to_list(list_to_binary(L),latin1),
+ More = <<B/binary,0,1,2>>,
+ B2 = list_to_binary([254,255]),
+ B3 = list_to_binary([0,1,2,254,255]),
+ {error,B,Rest1} = unicode:characters_to_binary([L,B2],unicode),
+ B2 = iolist_to_binary(Rest1),
+ {error,More,Rest2} = unicode:characters_to_binary([L,B3],unicode),
+ [ begin {error,_,_} = unicode:characters_to_binary([L,B2],unicode,Enc) end
|| Enc <- Encodings ],
- ?line Valid0 = unicode:characters_to_binary([L,254,255],unicode),
- ?line Valid1 = unicode:characters_to_binary([L,254,255],latin1),
- ?line Valid2 = unicode:characters_to_binary([L,254,255,256,257],unicode),
- ?line Valid3 = unicode:characters_to_binary([L,B2],latin1),
- ?line true = is_binary(Valid0),
- ?line true = is_binary(Valid1),
- ?line true = is_binary(Valid2),
- ?line true = is_binary(Valid3),
- ?line Valid4 = unicode:characters_to_binary([L,B3],latin1),
- ?line true = is_binary(Valid4),
- ?line B2 = iolist_to_binary(Rest2),
- ?line true = (L ++ [254,255] =:= unicode:characters_to_list(Valid0,unicode)),
- ?line true = (L ++ [254,255,256,257] =:= unicode:characters_to_list(Valid2,unicode)),
+ Valid0 = unicode:characters_to_binary([L,254,255],unicode),
+ Valid1 = unicode:characters_to_binary([L,254,255],latin1),
+ Valid2 = unicode:characters_to_binary([L,254,255,256,257],unicode),
+ Valid3 = unicode:characters_to_binary([L,B2],latin1),
+ true = is_binary(Valid0),
+ true = is_binary(Valid1),
+ true = is_binary(Valid2),
+ true = is_binary(Valid3),
+ Valid4 = unicode:characters_to_binary([L,B3],latin1),
+ true = is_binary(Valid4),
+ B2 = iolist_to_binary(Rest2),
+ true = (L ++ [254,255] =:= unicode:characters_to_list(Valid0,unicode)),
+ true = (L ++ [254,255,256,257] =:= unicode:characters_to_list(Valid2,unicode)),
lists:foreach(fun(Enco) ->
- ?line Valid0x = unicode:characters_to_binary([L,254,255],unicode,Enco),
- ?line Valid1x = unicode:characters_to_binary([L,254,255],latin1,Enco),
- ?line Valid2x = unicode:characters_to_binary([L,254,255,256,257],unicode,Enco),
- ?line Valid3x = unicode:characters_to_binary([L,B2],latin1,Enco),
- ?line true = is_binary(Valid0x),
- ?line true = is_binary(Valid1x),
- ?line true = is_binary(Valid2x),
- ?line true = is_binary(Valid3x)
+ Valid0x = unicode:characters_to_binary([L,254,255],unicode,Enco),
+ Valid1x = unicode:characters_to_binary([L,254,255],latin1,Enco),
+ Valid2x = unicode:characters_to_binary([L,254,255,256,257],unicode,Enco),
+ Valid3x = unicode:characters_to_binary([L,B2],latin1,Enco),
+ true = is_binary(Valid0x),
+ true = is_binary(Valid1x),
+ true = is_binary(Valid2x),
+ true = is_binary(Valid3x)
end, Encodings),
ok.
-
+
latin1(Config) when is_list(Config) ->
setlimit(10),
@@ -316,132 +316,132 @@ latin1(Config) when is_list(Config) ->
ex_latin1(Config).
ex_latin1(Config) when is_list(Config) ->
- ?line All = lists:seq(0,255),
- ?line AllBin = list_to_binary(All),
- ?line AllUtf8 = unicode:characters_to_binary(All,latin1),
- ?line AllUtf8 = unicode:characters_to_binary(AllBin,latin1),
- ?line AllUtf8 = unicode:characters_to_binary([AllBin],latin1),
- ?line AllUtf8 = unicode:characters_to_binary(make_unaligned(AllBin),latin1),
- ?line AllUtf8 = unicode:characters_to_binary([make_unaligned(AllBin)],latin1),
- ?line AllUtf8 = list_to_utf8_bsyntax([AllBin],latin1),
- ?line AllUtf8 = list_to_utf8_bsyntax([make_unaligned(AllBin)],latin1),
- ?line AllUtf8 = unicode_mixed_to_utf8_1(All),
-
- ?line AllUtf16_Big = unicode:characters_to_binary(All,latin1,utf16),
- ?line AllUtf16_Big = unicode:characters_to_binary(AllBin,latin1,utf16),
- ?line AllUtf16_Big = unicode:characters_to_binary([AllBin],latin1,utf16),
- ?line AllUtf16_Big = unicode:characters_to_binary(make_unaligned(AllBin),latin1,utf16),
- ?line AllUtf16_Big = unicode:characters_to_binary([make_unaligned(AllBin)],latin1,utf16),
- ?line AllUtf16_Big = list_to_utf16_big_bsyntax([AllBin],latin1),
- ?line AllUtf16_Big = list_to_utf16_big_bsyntax([make_unaligned(AllBin)],latin1),
-
- ?line AllUtf16_Little = unicode:characters_to_binary(All,latin1,{utf16,little}),
- ?line AllUtf16_Little = unicode:characters_to_binary(AllBin,latin1,{utf16,little}),
- ?line AllUtf16_Little = unicode:characters_to_binary([AllBin],latin1,{utf16,little}),
- ?line AllUtf16_Little = unicode:characters_to_binary(make_unaligned(AllBin),latin1,
- {utf16,little}),
- ?line AllUtf16_Little = unicode:characters_to_binary([make_unaligned(AllBin)],latin1,
- {utf16,little}),
- ?line AllUtf16_Little = list_to_utf16_little_bsyntax([AllBin],latin1),
- ?line AllUtf16_Little = list_to_utf16_little_bsyntax([make_unaligned(AllBin)],latin1),
-
- ?line AllUtf32_Big = unicode:characters_to_binary(All,latin1,utf32),
- ?line AllUtf32_Big = unicode:characters_to_binary(AllBin,latin1,utf32),
- ?line AllUtf32_Big = unicode:characters_to_binary([AllBin],latin1,utf32),
- ?line AllUtf32_Big = unicode:characters_to_binary(make_unaligned(AllBin),latin1,utf32),
- ?line AllUtf32_Big = unicode:characters_to_binary([make_unaligned(AllBin)],latin1,utf32),
- ?line AllUtf32_Big = list_to_utf32_big_bsyntax([AllBin],latin1),
- ?line AllUtf32_Big = list_to_utf32_big_bsyntax([make_unaligned(AllBin)],latin1),
-
- ?line AllUtf32_Little = unicode:characters_to_binary(All,latin1,{utf32,little}),
- ?line AllUtf32_Little = unicode:characters_to_binary(AllBin,latin1,{utf32,little}),
- ?line AllUtf32_Little = unicode:characters_to_binary([AllBin],latin1,{utf32,little}),
- ?line AllUtf32_Little = unicode:characters_to_binary(make_unaligned(AllBin),latin1,
- {utf32,little}),
- ?line AllUtf32_Little = unicode:characters_to_binary([make_unaligned(AllBin)],latin1,
- {utf32,little}),
- ?line AllUtf32_Little = list_to_utf32_little_bsyntax([AllBin],latin1),
- ?line AllUtf32_Little = list_to_utf32_little_bsyntax([make_unaligned(AllBin)],latin1),
-
- ?line DoubleUtf8 = <<AllUtf8/binary,AllUtf8/binary>>,
- ?line DoubleUtf8 = unicode:characters_to_binary([All,AllBin],latin1),
- ?line DoubleUtf8 =
+ All = lists:seq(0,255),
+ AllBin = list_to_binary(All),
+ AllUtf8 = unicode:characters_to_binary(All,latin1),
+ AllUtf8 = unicode:characters_to_binary(AllBin,latin1),
+ AllUtf8 = unicode:characters_to_binary([AllBin],latin1),
+ AllUtf8 = unicode:characters_to_binary(make_unaligned(AllBin),latin1),
+ AllUtf8 = unicode:characters_to_binary([make_unaligned(AllBin)],latin1),
+ AllUtf8 = list_to_utf8_bsyntax([AllBin],latin1),
+ AllUtf8 = list_to_utf8_bsyntax([make_unaligned(AllBin)],latin1),
+ AllUtf8 = unicode_mixed_to_utf8_1(All),
+
+ AllUtf16_Big = unicode:characters_to_binary(All,latin1,utf16),
+ AllUtf16_Big = unicode:characters_to_binary(AllBin,latin1,utf16),
+ AllUtf16_Big = unicode:characters_to_binary([AllBin],latin1,utf16),
+ AllUtf16_Big = unicode:characters_to_binary(make_unaligned(AllBin),latin1,utf16),
+ AllUtf16_Big = unicode:characters_to_binary([make_unaligned(AllBin)],latin1,utf16),
+ AllUtf16_Big = list_to_utf16_big_bsyntax([AllBin],latin1),
+ AllUtf16_Big = list_to_utf16_big_bsyntax([make_unaligned(AllBin)],latin1),
+
+ AllUtf16_Little = unicode:characters_to_binary(All,latin1,{utf16,little}),
+ AllUtf16_Little = unicode:characters_to_binary(AllBin,latin1,{utf16,little}),
+ AllUtf16_Little = unicode:characters_to_binary([AllBin],latin1,{utf16,little}),
+ AllUtf16_Little = unicode:characters_to_binary(make_unaligned(AllBin),latin1,
+ {utf16,little}),
+ AllUtf16_Little = unicode:characters_to_binary([make_unaligned(AllBin)],latin1,
+ {utf16,little}),
+ AllUtf16_Little = list_to_utf16_little_bsyntax([AllBin],latin1),
+ AllUtf16_Little = list_to_utf16_little_bsyntax([make_unaligned(AllBin)],latin1),
+
+ AllUtf32_Big = unicode:characters_to_binary(All,latin1,utf32),
+ AllUtf32_Big = unicode:characters_to_binary(AllBin,latin1,utf32),
+ AllUtf32_Big = unicode:characters_to_binary([AllBin],latin1,utf32),
+ AllUtf32_Big = unicode:characters_to_binary(make_unaligned(AllBin),latin1,utf32),
+ AllUtf32_Big = unicode:characters_to_binary([make_unaligned(AllBin)],latin1,utf32),
+ AllUtf32_Big = list_to_utf32_big_bsyntax([AllBin],latin1),
+ AllUtf32_Big = list_to_utf32_big_bsyntax([make_unaligned(AllBin)],latin1),
+
+ AllUtf32_Little = unicode:characters_to_binary(All,latin1,{utf32,little}),
+ AllUtf32_Little = unicode:characters_to_binary(AllBin,latin1,{utf32,little}),
+ AllUtf32_Little = unicode:characters_to_binary([AllBin],latin1,{utf32,little}),
+ AllUtf32_Little = unicode:characters_to_binary(make_unaligned(AllBin),latin1,
+ {utf32,little}),
+ AllUtf32_Little = unicode:characters_to_binary([make_unaligned(AllBin)],latin1,
+ {utf32,little}),
+ AllUtf32_Little = list_to_utf32_little_bsyntax([AllBin],latin1),
+ AllUtf32_Little = list_to_utf32_little_bsyntax([make_unaligned(AllBin)],latin1),
+
+ DoubleUtf8 = <<AllUtf8/binary,AllUtf8/binary>>,
+ DoubleUtf8 = unicode:characters_to_binary([All,AllBin],latin1),
+ DoubleUtf8 =
unicode:characters_to_binary([All,make_unaligned(AllBin)],latin1),
- ?line DoubleUtf8 = unicode:characters_to_binary([All|AllBin],latin1),
- ?line DoubleUtf8 =
+ DoubleUtf8 = unicode:characters_to_binary([All|AllBin],latin1),
+ DoubleUtf8 =
unicode:characters_to_binary([All|make_unaligned(AllBin)],latin1),
- ?line DoubleUtf8 = unicode:characters_to_binary([AllBin,All],latin1),
- ?line DoubleUtf8 = unicode:characters_to_binary([AllBin|All],latin1),
- ?line DoubleUtf8 = list_to_utf8_bsyntax([AllBin|All],latin1),
+ DoubleUtf8 = unicode:characters_to_binary([AllBin,All],latin1),
+ DoubleUtf8 = unicode:characters_to_binary([AllBin|All],latin1),
+ DoubleUtf8 = list_to_utf8_bsyntax([AllBin|All],latin1),
- ?line DoubleUtf16 = <<AllUtf16_Big/binary,AllUtf16_Big/binary>>,
- ?line DoubleUtf16 = unicode:characters_to_binary([All,AllBin],latin1,{utf16,big}),
- ?line DoubleUtf16 =
+ DoubleUtf16 = <<AllUtf16_Big/binary,AllUtf16_Big/binary>>,
+ DoubleUtf16 = unicode:characters_to_binary([All,AllBin],latin1,{utf16,big}),
+ DoubleUtf16 =
unicode:characters_to_binary([All,make_unaligned(AllBin)],latin1,{utf16,big}),
- ?line DoubleUtf16 = unicode:characters_to_binary([All|AllBin],latin1,{utf16,big}),
- ?line DoubleUtf16 =
+ DoubleUtf16 = unicode:characters_to_binary([All|AllBin],latin1,{utf16,big}),
+ DoubleUtf16 =
unicode:characters_to_binary([All|make_unaligned(AllBin)],latin1,{utf16,big}),
- ?line DoubleUtf16 = unicode:characters_to_binary([AllBin,All],latin1,{utf16,big}),
- ?line DoubleUtf16 = unicode:characters_to_binary([AllBin|All],latin1,{utf16,big}),
- ?line DoubleUtf16 = list_to_utf16_big_bsyntax([AllBin|All],latin1),
-
- ?line All = unicode:characters_to_list(AllUtf8,unicode),
- ?line All = unicode:characters_to_list(make_unaligned(AllUtf8),unicode),
- ?line All = utf8_to_list_bsyntax(AllUtf8),
- ?line AllAll = All ++ All,
- ?line AllAll = unicode:characters_to_list(DoubleUtf8,unicode),
- ?line AllAll = unicode:characters_to_list(make_unaligned(DoubleUtf8),unicode),
- ?line AllAll = utf8_to_list_bsyntax(DoubleUtf8),
- ?line {error,AllUtf8,Rest1} = unicode:characters_to_binary(All++[16#FFF],latin1),
- ?line [16#FFF] = lists:flatten(Rest1),
- ?line {error,DoubleUtf8,Rest2} =
+ DoubleUtf16 = unicode:characters_to_binary([AllBin,All],latin1,{utf16,big}),
+ DoubleUtf16 = unicode:characters_to_binary([AllBin|All],latin1,{utf16,big}),
+ DoubleUtf16 = list_to_utf16_big_bsyntax([AllBin|All],latin1),
+
+ All = unicode:characters_to_list(AllUtf8,unicode),
+ All = unicode:characters_to_list(make_unaligned(AllUtf8),unicode),
+ All = utf8_to_list_bsyntax(AllUtf8),
+ AllAll = All ++ All,
+ AllAll = unicode:characters_to_list(DoubleUtf8,unicode),
+ AllAll = unicode:characters_to_list(make_unaligned(DoubleUtf8),unicode),
+ AllAll = utf8_to_list_bsyntax(DoubleUtf8),
+ {error,AllUtf8,Rest1} = unicode:characters_to_binary(All++[16#FFF],latin1),
+ [16#FFF] = lists:flatten(Rest1),
+ {error,DoubleUtf8,Rest2} =
unicode:characters_to_binary([All,AllBin,16#FFF],latin1),
- ?line {error,DoubleUtf16,Rest2x} =
+ {error,DoubleUtf16,Rest2x} =
unicode:characters_to_binary([All,AllBin,16#FFF],latin1,utf16),
- ?line [16#FFF] = lists:flatten(Rest2),
- ?line [16#FFF] = lists:flatten(Rest2x),
- ?line {error,AllUtf8,Rest3} =
+ [16#FFF] = lists:flatten(Rest2),
+ [16#FFF] = lists:flatten(Rest2x),
+ {error,AllUtf8,Rest3} =
unicode:characters_to_binary([All,16#FFF,AllBin,16#FFF],
- latin1),
- ?line {error,AllUtf8,Rest3} =
+ latin1),
+ {error,AllUtf8,Rest3} =
unicode:characters_to_binary([All,16#FFF,make_unaligned(AllBin),16#FFF],
- latin1),
- ?line {error,AllUtf16_Big,Rest3x} =
+ latin1),
+ {error,AllUtf16_Big,Rest3x} =
unicode:characters_to_binary([All,16#FFF,AllBin,16#FFF],
- latin1,{utf16,big}),
- ?line {error,AllUtf16_Big,Rest3x} =
+ latin1,{utf16,big}),
+ {error,AllUtf16_Big,Rest3x} =
unicode:characters_to_binary([All,16#FFF,make_unaligned(AllBin),16#FFF],
- latin1,{utf16,big}),
- ?line [16#FFF,AllBin,16#FFF] = lists:flatten(Rest3),
- ?line [16#FFF,AllBin,16#FFF] = lists:flatten(Rest3x),
- ?line DoubleSize = byte_size(DoubleUtf8),
- ?line AllBut1 = DoubleSize - 1,
- ?line AllBut2 = DoubleSize - 2,
- ?line <<MissingLastByte:AllBut1/binary,_>> = DoubleUtf8,
- ?line <<_:AllBut2/binary,MissingStart:1/binary,_>> = DoubleUtf8,
- ?line {ChompedList,_} = lists:split(length(AllAll) - 1,AllAll),
- ?line {incomplete,ChompedList,MissingStart} =
+ latin1,{utf16,big}),
+ [16#FFF,AllBin,16#FFF] = lists:flatten(Rest3),
+ [16#FFF,AllBin,16#FFF] = lists:flatten(Rest3x),
+ DoubleSize = byte_size(DoubleUtf8),
+ AllBut1 = DoubleSize - 1,
+ AllBut2 = DoubleSize - 2,
+ <<MissingLastByte:AllBut1/binary,_>> = DoubleUtf8,
+ <<_:AllBut2/binary,MissingStart:1/binary,_>> = DoubleUtf8,
+ {ChompedList,_} = lists:split(length(AllAll) - 1,AllAll),
+ {incomplete,ChompedList,MissingStart} =
unicode:characters_to_list(MissingLastByte,unicode),
- ?line {incomplete,ChompedList,MissingStart} =
+ {incomplete,ChompedList,MissingStart} =
unicode:characters_to_list(make_unaligned(MissingLastByte),unicode),
- ?line DoubleSize16 = byte_size(DoubleUtf16),
- ?line DoubleUtf16_2 = list_to_binary([DoubleUtf16,<<16#FFFFF/utf16-big>>]),
- ?line DoubleSize16_2 = byte_size(DoubleUtf16_2),
- ?line AllBut1_16 = DoubleSize16 - 1,
- ?line AllBut2_16_2 = DoubleSize16_2 - 2,
- ?line <<MissingLastBytes16:AllBut2_16_2/binary,_,_>> = DoubleUtf16_2,
- ?line <<MissingLastByte16:AllBut1_16/binary,_>> = DoubleUtf16,
- ?line {incomplete,AllAll,_} =
+ DoubleSize16 = byte_size(DoubleUtf16),
+ DoubleUtf16_2 = list_to_binary([DoubleUtf16,<<16#FFFFF/utf16-big>>]),
+ DoubleSize16_2 = byte_size(DoubleUtf16_2),
+ AllBut1_16 = DoubleSize16 - 1,
+ AllBut2_16_2 = DoubleSize16_2 - 2,
+ <<MissingLastBytes16:AllBut2_16_2/binary,_,_>> = DoubleUtf16_2,
+ <<MissingLastByte16:AllBut1_16/binary,_>> = DoubleUtf16,
+ {incomplete,AllAll,_} =
unicode:characters_to_list(MissingLastBytes16,utf16),
- ?line {incomplete,AllAll,_} =
+ {incomplete,AllAll,_} =
unicode:characters_to_list(make_unaligned(MissingLastBytes16),utf16),
- ?line {incomplete,ChompedList,_} =
+ {incomplete,ChompedList,_} =
unicode:characters_to_list(MissingLastByte16,utf16),
- ?line {incomplete,ChompedList,_} =
+ {incomplete,ChompedList,_} =
unicode:characters_to_list(make_unaligned(MissingLastByte16),utf16),
ok.
-
+
roundtrips(Config) when is_list(Config) ->
setlimit(10),
ex_roundtrips(Config),
@@ -449,23 +449,21 @@ roundtrips(Config) when is_list(Config) ->
ex_roundtrips(Config).
ex_roundtrips(Config) when is_list(Config) ->
- ?line L1 = ranges(0, 16#D800 - 1,
- erlang:system_info(context_reductions) * 11),
- ?line L2 = ranges(16#DFFF + 1, 16#10000 - 1,
- erlang:system_info(context_reductions) * 11),
- %?line L3 = ranges(16#FFFF + 1, 16#10FFFF,
- % erlang:system_info(context_reductions) * 11),
- ?line L3 = ranges(16#FFFFF, 16#10FFFF,
- erlang:system_info(context_reductions) * 11),
- ?line L = L1 ++ L2 ++ L3,
- ?line LLen = length(L),
- ?line Parts = erlang:system_info(schedulers),
- ?line Lists = splitup(L,LLen,Parts),
- ?line PidRefs = [spawn_monitor(fun() ->
- do_roundtrips(MyPart)
- end) || MyPart <- Lists],
- ?line [receive {'DOWN',Ref,process,Pid,Reason} -> normal=Reason end ||
- {Pid,Ref} <- PidRefs],
+ L1 = ranges(0, 16#D800 - 1,
+ erlang:system_info(context_reductions) * 11),
+ L2 = ranges(16#DFFF + 1, 16#10000 - 1,
+ erlang:system_info(context_reductions) * 11),
+ L3 = ranges(16#FFFFF, 16#10FFFF,
+ erlang:system_info(context_reductions) * 11),
+ L = L1 ++ L2 ++ L3,
+ LLen = length(L),
+ Parts = erlang:system_info(schedulers),
+ Lists = splitup(L,LLen,Parts),
+ PidRefs = [spawn_monitor(fun() ->
+ do_roundtrips(MyPart)
+ end) || MyPart <- Lists],
+ [receive {'DOWN',Ref,process,Pid,Reason} -> normal=Reason end ||
+ {Pid,Ref} <- PidRefs],
ok.
do_roundtrips([]) ->
@@ -529,10 +527,10 @@ ex_random_lists(Config) when is_list(Config) ->
PlainFlatten4 = fun(L) ->
iolist_to_binary([int_to_utf8(X) || X <- unicode:characters_to_list(flatb(L),latin1)])
end,
- ?line random_iolist:run(150, PlainFlatten1, PlainFlatten3),
- ?line random_iolist:run(150, PlainFlatten2, PlainFlatten3),
- ?line random_iolist:run(150, PlainFlatten1, PlainFlatten2),
- ?line random_iolist:run(150, PlainFlatten1, PlainFlatten4),
+ random_iolist:run(150, PlainFlatten1, PlainFlatten3),
+ random_iolist:run(150, PlainFlatten2, PlainFlatten3),
+ random_iolist:run(150, PlainFlatten1, PlainFlatten2),
+ random_iolist:run(150, PlainFlatten1, PlainFlatten4),
SelfMade = fun(L) ->
iolist_to_binary(lists:map(fun(X) ->
int_to_utf8(X)
@@ -548,52 +546,52 @@ ex_random_lists(Config) when is_list(Config) ->
Other
end
end,
- ?line random_iolist:run(150, PlainFlatten1, SelfMade),
- ?line random_iolist:run(150, PlainFlatten2, SelfMadeA),
+ random_iolist:run(150, PlainFlatten1, SelfMade),
+ random_iolist:run(150, PlainFlatten2, SelfMadeA),
RoundTrip11 = fun(L) ->
- unicode:characters_to_list(unicode:characters_to_binary(L,latin1),unicode)
- end,
+ unicode:characters_to_list(unicode:characters_to_binary(L,latin1),unicode)
+ end,
RoundTrip21 = fun(L) ->
- utf8_to_list_bsyntax(unicode:characters_to_binary(L,latin1))
- end,
+ utf8_to_list_bsyntax(unicode:characters_to_binary(L,latin1))
+ end,
RoundTrip31 = fun(L) ->
- unicode:characters_to_list(list_to_utf8_bsyntax(L,latin1),unicode)
- end,
+ unicode:characters_to_list(list_to_utf8_bsyntax(L,latin1),unicode)
+ end,
RoundTrip41 = fun(L) ->
- utf8_to_list_bsyntax(list_to_utf8_bsyntax(L,latin1))
- end,
+ utf8_to_list_bsyntax(list_to_utf8_bsyntax(L,latin1))
+ end,
RoundTrip51 = fun(L) ->
- unicode:characters_to_list(L,latin1)
- end,
- ?line random_iolist:run(150, RoundTrip11,RoundTrip21),
- ?line random_iolist:run(150, RoundTrip21,RoundTrip31),
- ?line random_iolist:run(150, RoundTrip31,RoundTrip41),
- ?line random_iolist:run(150, RoundTrip11,RoundTrip41),
- ?line random_iolist:run(150, RoundTrip21,RoundTrip41),
- ?line random_iolist:run(150, RoundTrip11,RoundTrip31),
- ?line random_iolist:run(150, RoundTrip11,RoundTrip51),
+ unicode:characters_to_list(L,latin1)
+ end,
+ random_iolist:run(150, RoundTrip11,RoundTrip21),
+ random_iolist:run(150, RoundTrip21,RoundTrip31),
+ random_iolist:run(150, RoundTrip31,RoundTrip41),
+ random_iolist:run(150, RoundTrip11,RoundTrip41),
+ random_iolist:run(150, RoundTrip21,RoundTrip41),
+ random_iolist:run(150, RoundTrip11,RoundTrip31),
+ random_iolist:run(150, RoundTrip11,RoundTrip51),
UniFlatten1 = fun(L) ->
unicode:characters_to_binary(flat(L),unicode)
end,
UniFlatten2 = fun(L) ->
- unicode:characters_to_binary(L,unicode)
+ unicode:characters_to_binary(L,unicode)
end,
UniFlatten3 = fun(L) ->
- unicode:characters_to_binary(flatx(L),unicode)
+ unicode:characters_to_binary(flatx(L),unicode)
end,
UniFlatten4 = fun(L) ->
- unicode:characters_to_binary(unicode:characters_to_list(L,unicode),unicode)
+ unicode:characters_to_binary(unicode:characters_to_list(L,unicode),unicode)
end,
- ?line random_unicode_list:run(150, UniFlatten1,UniFlatten2),
- ?line random_unicode_list:run(150, UniFlatten1,UniFlatten3),
- ?line random_unicode_list:run(150, UniFlatten2,UniFlatten4),
- ?line random_unicode_list:run(150, UniFlatten2,UniFlatten3),
+ random_unicode_list:run(150, UniFlatten1,UniFlatten2),
+ random_unicode_list:run(150, UniFlatten1,UniFlatten3),
+ random_unicode_list:run(150, UniFlatten2,UniFlatten4),
+ random_unicode_list:run(150, UniFlatten2,UniFlatten3),
- ?line Encodings = [utf8,{utf16,big},
- {utf16,little},{utf32,big},{utf32,little}],
+ Encodings = [utf8,{utf16,big},
+ {utf16,little},{utf32,big},{utf32,little}],
lists:foreach(fun(OutEnc1) ->
lists:foreach(fun(InEnc1) ->
Uni16BigFlatten1 = fun(L) ->
@@ -608,11 +606,10 @@ ex_random_lists(Config) when is_list(Config) ->
Uni16BigFlatten4 = fun(L) ->
unicode:characters_to_binary(unicode:characters_to_list(L,InEnc1),InEnc1,OutEnc1)
end,
- %erlang:display({InEnc1,OutEnc1}),
- ?line random_unicode_list:run(150, Uni16BigFlatten1,Uni16BigFlatten2,InEnc1),
- ?line random_unicode_list:run(150, Uni16BigFlatten1,Uni16BigFlatten3,InEnc1),
- ?line random_unicode_list:run(150, Uni16BigFlatten2,Uni16BigFlatten4,InEnc1),
- ?line random_unicode_list:run(150, Uni16BigFlatten2,Uni16BigFlatten3,InEnc1)
+ random_unicode_list:run(150, Uni16BigFlatten1,Uni16BigFlatten2,InEnc1),
+ random_unicode_list:run(150, Uni16BigFlatten1,Uni16BigFlatten3,InEnc1),
+ random_unicode_list:run(150, Uni16BigFlatten2,Uni16BigFlatten4,InEnc1),
+ random_unicode_list:run(150, Uni16BigFlatten2,Uni16BigFlatten3,InEnc1)
end, Encodings)
end, Encodings),
SelfMade1 = fun(L) ->
@@ -624,10 +621,10 @@ ex_random_lists(Config) when is_list(Config) ->
SelfMade3 = fun(L) ->
list_to_utf8_bsyntax(L,unicode)
end,
- ?line random_unicode_list:run(150, SelfMade1,SelfMade2),
- ?line random_unicode_list:run(150, UniFlatten2, SelfMade1),
- ?line random_unicode_list:run(150, UniFlatten2, SelfMade2),
- ?line random_unicode_list:run(150, UniFlatten2, SelfMade3),
+ random_unicode_list:run(150, SelfMade1,SelfMade2),
+ random_unicode_list:run(150, UniFlatten2, SelfMade1),
+ random_unicode_list:run(150, UniFlatten2, SelfMade2),
+ random_unicode_list:run(150, UniFlatten2, SelfMade3),
RoundTrip1 = fun(L) ->
unicode:characters_to_list(unicode:characters_to_binary(L,unicode),unicode)
end,
@@ -640,12 +637,12 @@ ex_random_lists(Config) when is_list(Config) ->
RoundTrip4 = fun(L) ->
utf8_to_list_bsyntax(list_to_utf8_bsyntax(L,unicode))
end,
- ?line random_unicode_list:run(150, RoundTrip1,RoundTrip2),
- ?line random_unicode_list:run(150, RoundTrip2,RoundTrip3),
- ?line random_unicode_list:run(150, RoundTrip3,RoundTrip4),
- ?line random_unicode_list:run(150, RoundTrip1,RoundTrip4),
- ?line random_unicode_list:run(150, RoundTrip2,RoundTrip4),
- ?line random_unicode_list:run(150, RoundTrip1,RoundTrip3),
+ random_unicode_list:run(150, RoundTrip1,RoundTrip2),
+ random_unicode_list:run(150, RoundTrip2,RoundTrip3),
+ random_unicode_list:run(150, RoundTrip3,RoundTrip4),
+ random_unicode_list:run(150, RoundTrip1,RoundTrip4),
+ random_unicode_list:run(150, RoundTrip2,RoundTrip4),
+ random_unicode_list:run(150, RoundTrip1,RoundTrip3),
lists:foreach(fun(OutEnc2) ->
lists:foreach(fun(InEnc2) ->
RoundTripUtf16_Big_1 = fun(L) ->
@@ -660,12 +657,12 @@ ex_random_lists(Config) when is_list(Config) ->
RoundTripUtf16_Big_4 = fun(L) ->
x_to_list_bsyntax(InEnc2,list_to_x_bsyntax(InEnc2,L,InEnc2))
end,
- ?line random_unicode_list:run(150, RoundTripUtf16_Big_1,RoundTripUtf16_Big_2,InEnc2),
- ?line random_unicode_list:run(150, RoundTripUtf16_Big_2,RoundTripUtf16_Big_3,InEnc2),
- ?line random_unicode_list:run(150, RoundTripUtf16_Big_3,RoundTripUtf16_Big_4,InEnc2),
- ?line random_unicode_list:run(150, RoundTripUtf16_Big_1,RoundTripUtf16_Big_4,InEnc2),
- ?line random_unicode_list:run(150, RoundTripUtf16_Big_2,RoundTripUtf16_Big_4,InEnc2),
- ?line random_unicode_list:run(150, RoundTripUtf16_Big_1,RoundTripUtf16_Big_3,InEnc2)
+ random_unicode_list:run(150, RoundTripUtf16_Big_1,RoundTripUtf16_Big_2,InEnc2),
+ random_unicode_list:run(150, RoundTripUtf16_Big_2,RoundTripUtf16_Big_3,InEnc2),
+ random_unicode_list:run(150, RoundTripUtf16_Big_3,RoundTripUtf16_Big_4,InEnc2),
+ random_unicode_list:run(150, RoundTripUtf16_Big_1,RoundTripUtf16_Big_4,InEnc2),
+ random_unicode_list:run(150, RoundTripUtf16_Big_2,RoundTripUtf16_Big_4,InEnc2),
+ random_unicode_list:run(150, RoundTripUtf16_Big_1,RoundTripUtf16_Big_3,InEnc2)
end, Encodings)
end, Encodings),
ToList1 = fun(L) ->
@@ -680,12 +677,12 @@ ex_random_lists(Config) when is_list(Config) ->
ToList4 = fun(L) ->
utf8_to_list(unicode_mixed_to_utf8_2(L))
end,
- ?line random_unicode_list:run(150, ToList1,ToList2),
- ?line random_unicode_list:run(150, ToList2,ToList3),
- ?line random_unicode_list:run(150, ToList3,ToList4),
- ?line random_unicode_list:run(150, ToList1,ToList4),
- ?line random_unicode_list:run(150, ToList2,ToList4),
- ?line random_unicode_list:run(150, ToList1,ToList3),
+ random_unicode_list:run(150, ToList1,ToList2),
+ random_unicode_list:run(150, ToList2,ToList3),
+ random_unicode_list:run(150, ToList3,ToList4),
+ random_unicode_list:run(150, ToList1,ToList4),
+ random_unicode_list:run(150, ToList2,ToList4),
+ random_unicode_list:run(150, ToList1,ToList3),
ok.
@@ -696,13 +693,13 @@ utf16_illegal_sequences_bif(Config) when is_list(Config) ->
ex_utf16_illegal_sequences_bif(Config).
ex_utf16_illegal_sequences_bif(Config) when is_list(Config) ->
- ?line utf16_fail_range_bif_simple(16#10FFFF+1, 16#10FFFF+512), %Too large.
- ?line utf16_fail_range_bif(16#D800, 16#DFFF), %Reserved for UTF-16.
+ utf16_fail_range_bif_simple(16#10FFFF+1, 16#10FFFF+512), %Too large.
+ utf16_fail_range_bif(16#D800, 16#DFFF), %Reserved for UTF-16.
+
+ lonely_hi_surrogate_bif(16#D800, 16#DBFF,incomplete),
+ lonely_hi_surrogate_bif(16#DC00, 16#DFFF,error),
+ leading_lo_surrogate_bif(16#DC00, 16#DFFF),
- ?line lonely_hi_surrogate_bif(16#D800, 16#DBFF,incomplete),
- ?line lonely_hi_surrogate_bif(16#DC00, 16#DFFF,error),
- ?line leading_lo_surrogate_bif(16#DC00, 16#DFFF),
-
ok.
utf16_fail_range_bif(Char, End) when Char =< End ->
@@ -770,20 +767,20 @@ utf8_illegal_sequences_bif(Config) when is_list(Config) ->
ex_utf8_illegal_sequences_bif(Config).
ex_utf8_illegal_sequences_bif(Config) when is_list(Config) ->
- ?line fail_range_bif(16#10FFFF+1, 16#10FFFF+512), %Too large.
- ?line fail_range_bif(16#D800, 16#DFFF), %Reserved for UTF-16.
+ fail_range_bif(16#10FFFF+1, 16#10FFFF+512), %Too large.
+ fail_range_bif(16#D800, 16#DFFF), %Reserved for UTF-16.
%% Illegal first character.
- ?line [fail_bif(<<I,16#8F,16#8F,16#8F>>,unicode) || I <- lists:seq(16#80, 16#BF)],
+ [fail_bif(<<I,16#8F,16#8F,16#8F>>,unicode) || I <- lists:seq(16#80, 16#BF)],
%% Short sequences.
- ?line short_sequences_bif(16#80, 16#10FFFF),
+ short_sequences_bif(16#80, 16#10FFFF),
%% Overlong sequences. (Using more bytes than necessary
%% is not allowed.)
- ?line overlong_bif(0, 127, 2),
- ?line overlong_bif(128, 16#7FF, 3),
- ?line overlong_bif(16#800, 16#FFFF, 4),
+ overlong_bif(0, 127, 2),
+ overlong_bif(128, 16#7FF, 3),
+ overlong_bif(16#800, 16#FFFF, 4),
ok.
fail_range_bif(Char, End) when Char =< End ->
@@ -797,7 +794,6 @@ fail_range_bif(_, _) -> ok.
short_sequences_bif(Char, End) ->
Step = (End - Char) div erlang:system_info(schedulers) + 1,
-% Step = (End - Char) + 1,
PidRefs = short_sequences_bif_1(Char, Step, End),
[receive {'DOWN',Ref,process,Pid,Reason} -> normal=Reason end ||
{Pid,Ref} <- PidRefs],
@@ -918,8 +914,8 @@ only_fail_bif_1(Bin,Coding) ->
Other ->
exit({faulty_encoding_accepted,[Bin],Coding,Other})
end.
-
-
+
+
fail_bif(Bin,Coding) ->
@@ -1021,9 +1017,9 @@ unicode_mixed_to_utf8_2(L) ->
int_to_utf8(E)
end || E <- Flist ],
iolist_to_binary([ExpList]).
-
-
-
+
+
+
utf8_to_list_bsyntax(<<>>) ->
[];
@@ -1042,8 +1038,8 @@ list_to_utf8_bsyntax(List,latin1) ->
FList = flatb(List),
list_to_binary([ <<E/utf8>> || E <- FList ]).
-
-
+
+
%%
@@ -1066,7 +1062,7 @@ int_to_utf16_little(U) when U >= 16#10000, U =< 16#10FFFF ->
LO = (16#DC00 bor (UPrim band 16#3FF)),
<<HI:16/little,LO:16/little>>.
-
+
%% This function intentionally allows construction of
%% UTF-8 sequence in illegal ranges.
int_to_utf8(I) when I =< 16#7F ->
@@ -1093,7 +1089,7 @@ int_to_utf8(I) when I =< 16#3FFFFFF ->
B2 = (I bsr 18),
B1 = (I bsr 24),
<<1:1,1:1,1:1,1:1,1:1,0:1,B1:2,1:1,0:1,B2:6,1:1,0:1,B3:6,1:1,0:1,B4:6,
- 1:1,0:1,B5:6>>.
+ 1:1,0:1,B5:6>>.
utf16_big_to_list_bsyntax(<<>>) ->
[];
@@ -1131,7 +1127,7 @@ list_to_utf16_little_bsyntax(List,latin1) ->
list_to_binary([ <<E/utf16-little>> || E <- FList ]).
-
+
utf32_big_to_list_bsyntax(<<>>) ->
[];
utf32_big_to_list_bsyntax(<<C/utf32-big,R/binary>>) ->
@@ -1162,12 +1158,12 @@ list_to_utf32_little_bsyntax(List,{utf32,little}) ->
E;
true ->
<<E/utf32-little>>
- end || E <- FList ]);
+ end || E <- FList ]);
list_to_utf32_little_bsyntax(List,latin1) ->
FList = flatb(List),
list_to_binary([ <<E/utf32-little>> || E <- FList ]).
-
+
%% int_to_utf8(I, NumberOfBytes) -> Binary.
%% This function can be used to construct overlong sequences.
@@ -1211,7 +1207,7 @@ utf8_to_int(<<1:1,1:1,0:1,B1:5,1:1,0:1,B2:6>>) ->
utf8_to_int(<<1:1,1:1,1:1,0:1,B1:4,1:1,0:1,B2:6,1:1,0:1,B3:6>>) ->
(B1 bsl 12) bor (B2 bsl 6) bor B3;
utf8_to_int(<<1:1,1:1,1:1,1:1,0:1,B1:3,1:1,0:1,
- B2:6,1:1,0:1,B3:6,1:1,0:1,B4:6>>) ->
+ B2:6,1:1,0:1,B3:6,1:1,0:1,B4:6>>) ->
Res = (B1 bsl 18) bor (B2 bsl 12) bor (B3 bsl 6) bor B4,
case Res of
X when X > 16#10FFFF ->
@@ -1295,10 +1291,9 @@ list_to_x_bsyntax({utf32,big},L,Enc) ->
list_to_utf32_big_bsyntax(L,Enc);
list_to_x_bsyntax({utf32,little},L,Enc) ->
list_to_utf32_little_bsyntax(L,Enc).
-
+
make_unaligned(Bin0) when is_binary(Bin0) ->
-% put(c_count,get(c_count)+1),
Bin1 = <<0:3,Bin0/binary,31:5>>,
Sz = byte_size(Bin0),
<<0:3,Bin:Sz/binary,31:5>> = id(Bin1),
@@ -1310,80 +1305,3 @@ setlimit(X) ->
erts_debug:set_internal_state(available_internal_state,true),
io:format("Setting loop limit, old: ~p, now set to ~p~n",
[erts_debug:set_internal_state(unicode_loop_limit,X),X]).
-
-
-%%
-%% Tracing utility
-%%
-
-%% tr_dump() ->
-%% erlang:display(lists:sort(ets:tab2list(values))).
-
-%% tr_off(Pid) ->
-%% receive after 10000 -> ok end,
-%% tr_dump(),
-%% Ref = erlang:monitor(process,Pid),
-%% exit(Pid,kill),
-%% receive
-%% {'DOWN',Ref,_,_,_} -> ok
-%% end,
-%% ok.
-
-%% tr_on() ->
-%% catch ets:delete(values),
-%% ets:new(values,[named_table,public]),
-%% ets:insert(values,{traps,0}),
-%% catch ets:delete(state),
-%% ets:new(state,[named_table,public]),
-%% Pid = spawn(?MODULE,trace_recv,[values,state]),
-%% erlang:trace(new,true,[garbage_collection,{tracer,Pid},timestamp,call]),
-%% erlang:trace_pattern({erlang,list_to_utf8,2},[{'_',[],[{return_trace}]}],[global]),
-%% Pid.
-
-%% ts_to_int({Mega,Sec,Micro}) ->
-%% ((Mega * 1000000) + Sec) * 1000000 + Micro.
-
-%% trace_recv(Values,State) ->
-%% receive
-%% {trace_ts,Pid,call,_,TS} ->
-%% case ets:lookup(State,{call,Pid}) of
-%% [{{call,Pid},_}] ->
-%% ets:update_counter(values,traps,1);
-%% _ ->
-%% ok
-%% end,
-%% ets:insert(State,{{call,Pid},ts_to_int(TS)});
-%% {trace_ts,Pid,return_from,_,_,TS} ->
-%% case ets:lookup(State,{call,Pid}) of
-%% [{{call,Pid},TS2}] ->
-%% ets:delete(State,{call,Pid}),
-%% Elapsed = ts_to_int(TS) - TS2,
-%% case ets:lookup(Values,Pid) of
-%% [{Pid,GCNum,CallNum,GCTime,CallTime}] ->
-%% ets:insert(Values,{Pid,GCNum,CallNum+1,GCTime,CallTime+Elapsed});
-%% [] ->
-%% ets:insert(Values,{Pid,0,1,0,Elapsed})
-%% end;
-%% _Other ->
-%% erlang:display({what2,Pid})
-%% end;
-%% {trace_ts,Pid,gc_start,_,TS} ->
-%% ets:insert(State,{{gc,Pid},ts_to_int(TS)});
-%% {trace_ts,Pid,gc_end,_,TS} ->
-%% case ets:lookup(State,{gc,Pid}) of
-%% [{{gc,Pid},TS2}] ->
-%% ets:delete(State,{gc,Pid}),
-%% Elapsed = ts_to_int(TS) - TS2,
-%% case ets:lookup(Values,Pid) of
-%% [{Pid,Num,CNum,Time,CTime}] ->
-%% ets:insert(Values,{Pid,Num+1,CNum,Time+Elapsed,CTime});
-%% [] ->
-%% ets:insert(Values,{Pid,1,0,Elapsed,0})
-%% end;
-%% _Other ->
-%% erlang:display({what,Pid})
-%% end;
-%% X ->
-%% erlang:display({trace_recv,X})
-%% end,
-%% trace_recv(Values,State).
diff --git a/lib/stdlib/test/win32reg_SUITE.erl b/lib/stdlib/test/win32reg_SUITE.erl
index 6d27ac6387..62619dff47 100644
--- a/lib/stdlib/test/win32reg_SUITE.erl
+++ b/lib/stdlib/test/win32reg_SUITE.erl
@@ -22,9 +22,11 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,long/1,evil_write/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{seconds,10}}].
all() ->
[long, evil_write].
@@ -49,11 +51,8 @@ init_per_suite(Config) when is_list(Config) ->
end_per_suite(Config) when is_list(Config) ->
Config.
-
-long(doc) -> "Test long keys and entries (OTP-3446).";
+%% Test long keys and entries (OTP-3446).
long(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
-
LongKey = "software\\" ++
lists:flatten(lists:duplicate(10, "..\\software\\")) ++
"Ericsson\\Erlang",
@@ -76,12 +75,9 @@ long(Config) when is_list(Config) ->
%% Done.
ok = win32reg:close(Reg),
- test_server:timetrap_cancel(Dog),
ok.
evil_write(Config) when is_list(Config) ->
- Dog = test_server:timetrap(test_server:seconds(10)),
-
Key = "Software\\Ericsson\\Erlang",
{ok,Reg} = win32reg:open([read,write]),
ok = win32reg:change_key(Reg, "\\hkcu"),
@@ -95,13 +91,12 @@ evil_write(Config) when is_list(Config) ->
%% Done.
ok = win32reg:close(Reg),
- test_server:timetrap_cancel(Dog),
ok.
evil_write_1(Reg, [_|[_|_]=Key]=Key0) ->
- ?line io:format("Key = ~p\n", [Key0]),
- ?line ok = win32reg:set_value(Reg, Key0, "A good value for me"),
- ?line {ok,_Val} = win32reg:value(Reg, Key0),
- ?line ok = win32reg:delete_value(Reg, Key0),
+ io:format("Key = ~p\n", [Key0]),
+ ok = win32reg:set_value(Reg, Key0, "A good value for me"),
+ {ok,_Val} = win32reg:value(Reg, Key0),
+ ok = win32reg:delete_value(Reg, Key0),
evil_write_1(Reg, Key);
evil_write_1(_, [_]) -> ok.
diff --git a/lib/stdlib/test/y2k_SUITE.erl b/lib/stdlib/test/y2k_SUITE.erl
index 9e766e80ab..7828eb26ed 100644
--- a/lib/stdlib/test/y2k_SUITE.erl
+++ b/lib/stdlib/test/y2k_SUITE.erl
@@ -22,7 +22,7 @@
-module(y2k_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
@@ -55,104 +55,80 @@ end_per_group(_GroupName, Config) ->
Config.
-date_1999_01_01(doc) ->
- "#1 : 1999-01-01: test roll-over from 1998-12-31 to 1999-01-01.";
-date_1999_01_01(suite) ->
- [];
+%% #1 : 1999-01-01: test roll-over from 1998-12-31 to 1999-01-01.
date_1999_01_01(Config) when is_list(Config) ->
- ?line Date = {1998, 12, 31}, NextDate = {1999, 1, 1},
- ?line match(next_date(Date), NextDate),
+ Date = {1998, 12, 31}, NextDate = {1999, 1, 1},
+ match(next_date(Date), NextDate),
TZD = tzd(Date),
if
TZD > 0 ->
- ?line Time = {24 - TZD, 0, 0},
- ?line {NDate, _NTime} =
+ Time = {24 - TZD, 0, 0},
+ {NDate, _NTime} =
erlang:localtime_to_universaltime({Date, Time}),
- ?line match(NDate, NextDate);
+ match(NDate, NextDate);
TZD < 0 ->
- ?line Time = {24 + TZD, 0, 0},
- ?line {NDate, _NTime} =
+ Time = {24 + TZD, 0, 0},
+ {NDate, _NTime} =
erlang:universaltime_to_localtime({Date, Time}),
- ?line match(NDate, NextDate);
+ match(NDate, NextDate);
true ->
ok
end.
-
-date_1999_02_28(doc) ->
- "#2 : 1999-02-28: test roll-over from 1999-02-28 to 1999-03-01.";
-date_1999_02_28(suite) ->
- [];
+
+%% #2 : 1999-02-28: test roll-over from 1999-02-28 to 1999-03-01.
date_1999_02_28(Config) when is_list(Config) ->
- ?line Date = {1999, 2, 28}, NextDate = {1999, 3, 1},
- ?line match(next_date(Date), NextDate),
- ?line match(tz_next_date(Date), NextDate).
-
-date_1999_09_09(doc) ->
- "#3 : 1999-09-09: test roll-over from 1999-09-08 to 1999-09-09.";
-date_1999_09_09(suite) ->
- [];
+ Date = {1999, 2, 28}, NextDate = {1999, 3, 1},
+ match(next_date(Date), NextDate),
+ match(tz_next_date(Date), NextDate).
+
+%% #3 : 1999-09-09: test roll-over from 1999-09-08 to 1999-09-09.
date_1999_09_09(Config) when is_list(Config) ->
- ?line Date = {1999, 9, 8}, NextDate = {1999, 9, 9},
- ?line match(next_date(Date), NextDate),
- ?line match(tz_next_date(Date), NextDate).
-
-date_2000_01_01(doc) ->
- "#4 : 2000-01-01: test roll-over from 1999-12-31 to 2000-01-01 to "
- "2000-01-02.";
-date_2000_01_01(suite) ->
- [];
+ Date = {1999, 9, 8}, NextDate = {1999, 9, 9},
+ match(next_date(Date), NextDate),
+ match(tz_next_date(Date), NextDate).
+
+%% #4 : 2000-01-01: test roll-over from 1999-12-31 to 2000-01-01 to
+%% 2000-01-02.;
date_2000_01_01(Config) when is_list(Config) ->
- ?line Date = {1999, 12, 31}, NextDate = {2000, 1, 1},
- ?line match(next_date(Date), NextDate),
- ?line match(tz_next_date(Date), NextDate),
- ?line NextDate1 = {2000, 1, 2},
- ?line match(next_date(NextDate), NextDate1),
- ?line match(tz_next_date(NextDate), NextDate1).
-
-date_2000_02_29(doc) ->
- "#5 : 2000-02-29: test roll-over from 2000-02-28 to 2000-02-29 to "
- "2000-03-01.";
-date_2000_02_29(suite) ->
- [];
+ Date = {1999, 12, 31}, NextDate = {2000, 1, 1},
+ match(next_date(Date), NextDate),
+ match(tz_next_date(Date), NextDate),
+ NextDate1 = {2000, 1, 2},
+ match(next_date(NextDate), NextDate1),
+ match(tz_next_date(NextDate), NextDate1).
+
+%% #5 : 2000-02-29: test roll-over from 2000-02-28 to 2000-02-29 to
+%% 2000-03-01.
date_2000_02_29(Config) when is_list(Config) ->
- ?line Date = {2000, 2, 28}, NextDate = {2000, 2, 29},
- ?line match(next_date(Date), NextDate),
- ?line match(tz_next_date(Date), NextDate),
- ?line NextDate1 = {2000, 3, 1},
- ?line match(next_date(NextDate), NextDate1),
- ?line match(tz_next_date(NextDate), NextDate1).
-
-date_2001_01_01(doc) ->
- "#6 : 2001-01-01: test roll-over from 2000-12-31 to 2001-01-01.";
-date_2001_01_01(suite) ->
- [];
+ Date = {2000, 2, 28}, NextDate = {2000, 2, 29},
+ match(next_date(Date), NextDate),
+ match(tz_next_date(Date), NextDate),
+ NextDate1 = {2000, 3, 1},
+ match(next_date(NextDate), NextDate1),
+ match(tz_next_date(NextDate), NextDate1).
+
+%% #6 : 2001-01-01: test roll-over from 2000-12-31 to 2001-01-01.
date_2001_01_01(Config) when is_list(Config) ->
- ?line Date = {2000, 12, 31}, NextDate = {2001, 1, 1},
- ?line match(next_date(Date), NextDate),
- ?line match(tz_next_date(Date), NextDate).
-
-date_2001_02_29(doc) ->
- "#7 : 2001-02-29: test roll-over from 2001-02-28 to 2001-03-01.";
-date_2001_02_29(suite) ->
- [];
+ Date = {2000, 12, 31}, NextDate = {2001, 1, 1},
+ match(next_date(Date), NextDate),
+ match(tz_next_date(Date), NextDate).
+
+%% #7 : 2001-02-29: test roll-over from 2001-02-28 to 2001-03-01.
date_2001_02_29(Config) when is_list(Config) ->
- ?line Date = {2001, 2, 28}, NextDate = {2001, 3, 1},
- ?line match(next_date(Date), NextDate),
- ?line match(tz_next_date(Date), NextDate).
-
-date_2004_02_29(doc) ->
- "#8 : 2004-02-29: test roll-over from 2004-02-28 to 2004-02-29 to "
- "2004-03-01.";
-date_2004_02_29(suite) ->
- [];
+ Date = {2001, 2, 28}, NextDate = {2001, 3, 1},
+ match(next_date(Date), NextDate),
+ match(tz_next_date(Date), NextDate).
+
+%% #8 : 2004-02-29: test roll-over from 2004-02-28 to 2004-02-29 to
+%% 2004-03-01.
date_2004_02_29(Config) when is_list(Config) ->
- ?line Date = {2004, 2, 28}, NextDate = {2004, 2, 29},
- ?line match(next_date(Date), NextDate),
- ?line match(tz_next_date(Date), NextDate),
- ?line NextDate1 = {2004, 3, 1},
- ?line match(next_date(NextDate), NextDate1),
- ?line match(tz_next_date(NextDate), NextDate1).
-
+ Date = {2004, 2, 28}, NextDate = {2004, 2, 29},
+ match(next_date(Date), NextDate),
+ match(tz_next_date(Date), NextDate),
+ NextDate1 = {2004, 3, 1},
+ match(next_date(NextDate), NextDate1),
+ match(tz_next_date(NextDate), NextDate1).
+
%%
%% Local functions
%%
@@ -162,7 +138,7 @@ next_date(Date) ->
%% timezonediff
%%
tzd(Date) ->
- ?line {_LDate, {LH, _LM, _LS}} =
+ {_LDate, {LH, _LM, _LS}} =
erlang:universaltime_to_localtime({Date, {12, 0, 0}}),
12 - LH.
@@ -170,15 +146,15 @@ tz_next_date(Date) ->
TZD = tzd(Date),
if
TZD > 0 ->
- ?line Time = {24 - TZD, 0, 0},
- ?line {NDate, _NTime} =
+ Time = {24 - TZD, 0, 0},
+ {NDate, _NTime} =
erlang:localtime_to_universaltime({Date, Time}),
- ?line NDate;
+ NDate;
TZD < 0 ->
- ?line Time = {24 + TZD, 0, 0},
- ?line {NDate, _NTime} =
+ Time = {24 + TZD, 0, 0},
+ {NDate, _NTime} =
erlang:universaltime_to_localtime({Date, Time}),
- ?line NDate;
+ NDate;
true ->
Date
end.
@@ -189,6 +165,3 @@ tz_next_date(Date) ->
match(X, X) ->
ok.
-
-
-
diff --git a/lib/stdlib/test/zip_SUITE.erl b/lib/stdlib/test/zip_SUITE.erl
index c275053691..57ad869f24 100644
--- a/lib/stdlib/test/zip_SUITE.erl
+++ b/lib/stdlib/test/zip_SUITE.erl
@@ -28,8 +28,7 @@
compress_control/1,
foldl/1]).
--include_lib("test_server/include/test_server.hrl").
--include("test_server_line.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
-include_lib("stdlib/include/zip.hrl").
@@ -57,12 +56,11 @@ end_per_group(_GroupName, Config) ->
Config.
-borderline(doc) ->
- ["Test creating, listing and extracting one file from an archive "
- "multiple times with different file sizes. Also check that the "
- "modification date of the extracted file has survived."];
+%% Test creating, listing and extracting one file from an archive
+%% multiple times with different file sizes. Also check that the
+%% modification date of the extracted file has survived.
borderline(Config) when is_list(Config) ->
- RootDir = ?config(priv_dir, Config),
+ RootDir = proplists:get_value(priv_dir, Config),
TempDir = filename:join(RootDir, "borderline"),
ok = file:make_dir(TempDir),
@@ -179,7 +177,7 @@ match_output(eof, Expect, Port) ->
kill_port_and_fail(Port, Reason) ->
unlink(Port),
exit(Port, die),
- test_server:fail(Reason).
+ ct:fail(Reason).
make_cmd(Cmd) ->
Cmd.
@@ -216,12 +214,10 @@ random_byte_list(_X, 0, Result) ->
next_random(X) ->
(X*17059465+1) band 16#fffffffff.
-atomic(doc) ->
- ["Test the 'atomic' operations: zip/unzip/list_dir, on archives."
- "Also test the 'cooked' option."];
-atomic(suite) -> [];
+%% Test the 'atomic' operations: zip/unzip/list_dir, on archives.
+%% Also test the 'cooked' option.
atomic(Config) when is_list(Config) ->
- ok = file:set_cwd(?config(priv_dir, Config)),
+ ok = file:set_cwd(proplists:get_value(priv_dir, Config)),
DataFiles = data_files(),
Names = [Name || {Name,_,_} <- DataFiles],
io:format("Names: ~p", [Names]),
@@ -244,12 +240,10 @@ atomic(Config) when is_list(Config) ->
ok.
-openzip_api(doc) ->
- ["Test the openzip_open/2, openzip_get/1, openzip_get/2, openzip_close/1 "
- "and openzip_list_dir/1 functions."];
-openzip_api(suite) -> [];
+%% Test the openzip_open/2, openzip_get/1, openzip_get/2, openzip_close/1
+%% and openzip_list_dir/1 functions.
openzip_api(Config) when is_list(Config) ->
- ok = file:set_cwd(?config(priv_dir, Config)),
+ ok = file:set_cwd(proplists:get_value(priv_dir, Config)),
DataFiles = data_files(),
Names = [Name || {Name, _, _} <- DataFiles],
io:format("Names: ~p", [Names]),
@@ -283,12 +277,10 @@ openzip_api(Config) when is_list(Config) ->
ok.
-zip_api(doc) ->
- ["Test the zip_open/2, zip_get/1, zip_get/2, zip_close/1 "
- "and zip_list_dir/1 functions."];
-zip_api(suite) -> [];
+%% Test the zip_open/2, zip_get/1, zip_get/2, zip_close/1,
+%% and zip_list_dir/1 functions.
zip_api(Config) when is_list(Config) ->
- ok = file:set_cwd(?config(priv_dir, Config)),
+ ok = file:set_cwd(proplists:get_value(priv_dir, Config)),
DataFiles = data_files(),
Names = [Name || {Name, _, _} <- DataFiles],
io:format("Names: ~p", [Names]),
@@ -319,13 +311,11 @@ zip_api(Config) when is_list(Config) ->
%% Clean up.
delete_files([Names]),
- ok.
+ ok.
-open_leak(doc) ->
- ["Test that zip doesn't leak processes and ports where the "
- "controlling process dies without closing an zip opened with "
- "zip:zip_open/1."];
-open_leak(suite) -> [];
+%% Test that zip doesn't leak processes and ports where the
+%% controlling process dies without closing an zip opened with
+%% zip:zip_open/1.
open_leak(Config) when is_list(Config) ->
%% Create a zip archive
Zip = "zip.zip",
@@ -359,13 +349,10 @@ spawned_zip_dead(ZipSrv) ->
false
end.
-unzip_options(doc) ->
- ["Test options for unzip, only cwd and file_list currently"];
-unzip_options(suite) ->
- [];
+%% Test options for unzip, only cwd and file_list currently.
unzip_options(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Long = filename:join(DataDir, "abc.zip"),
%% create a temp directory
@@ -375,28 +362,25 @@ unzip_options(Config) when is_list(Config) ->
FList = ["quotes/rain.txt","wikipedia.txt"],
%% Unzip a zip file in Subdir
- ?line {ok, RetList} = zip:unzip(Long, [{cwd, Subdir},
- {file_list, FList}]),
+ {ok, RetList} = zip:unzip(Long, [{cwd, Subdir},
+ {file_list, FList}]),
%% Verify.
- ?line true = (length(FList) =:= length(RetList)),
- ?line lists:foreach(fun(F)-> {ok,B} = file:read_file(filename:join(DataDir, F)),
- {ok,B} = file:read_file(filename:join(Subdir, F)) end,
- FList),
- ?line lists:foreach(fun(F)-> ok = file:delete(F) end,
- RetList),
+ true = (length(FList) =:= length(RetList)),
+ lists:foreach(fun(F)-> {ok,B} = file:read_file(filename:join(DataDir, F)),
+ {ok,B} = file:read_file(filename:join(Subdir, F)) end,
+ FList),
+ lists:foreach(fun(F)-> ok = file:delete(F) end,
+ RetList),
%% Clean up and verify no more files.
- ?line 0 = delete_files([Subdir]),
+ 0 = delete_files([Subdir]),
ok.
-unzip_jar(doc) ->
- ["Test unzip a jar file (OTP-7382)"];
-unzip_jar(suite) ->
- [];
+%% Test unzip a jar file (OTP-7382).
unzip_jar(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
JarFile = filename:join(DataDir, "test.jar"),
%% create a temp directory
@@ -409,28 +393,25 @@ unzip_jar(Config) when is_list(Config) ->
{ok, RetList} = zip:unzip(JarFile),
%% Verify.
- ?line lists:foreach(fun(F)-> {ok,B} = file:read_file(filename:join(DataDir, F)),
- {ok,B} = file:read_file(filename:join(Subdir, F)) end,
- FList),
- ?line lists:foreach(fun(F)-> ok = file:delete(F) end,
- RetList),
+ lists:foreach(fun(F)-> {ok,B} = file:read_file(filename:join(DataDir, F)),
+ {ok,B} = file:read_file(filename:join(Subdir, F)) end,
+ FList),
+ lists:foreach(fun(F)-> ok = file:delete(F) end,
+ RetList),
%% Clean up and verify no more files.
- ?line 0 = delete_files([Subdir]),
+ 0 = delete_files([Subdir]),
ok.
-zip_options(doc) ->
- ["Test the options for unzip, only cwd currently"];
-zip_options(suite) ->
- [];
+%% Test the options for unzip, only cwd currently.
zip_options(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ok = file:set_cwd(PrivDir),
DataFiles = data_files(),
Names = [Name || {Name, _, _} <- DataFiles],
%% Make sure cwd is not where we get the files
- ok = file:set_cwd(?config(data_dir, Config)),
+ ok = file:set_cwd(proplists:get_value(data_dir, Config)),
%% Create a zip archive
{ok, {_,Zip}} =
@@ -460,10 +441,7 @@ zip_options(Config) when is_list(Config) ->
ok.
-list_dir_options(doc) ->
- ["Test the options for list_dir... one day"];
-list_dir_options(suite) ->
- [];
+%% Test the options for list_dir... one day.
list_dir_options(Config) when is_list(Config) ->
ok.
@@ -515,10 +493,9 @@ create_files([]) ->
%% make_dirs([], Dir) ->
%% Dir.
-bad_zip(doc) ->
- ["Try zip:unzip/1 on some corrupted zip files."];
+%% Try zip:unzip/1 on some corrupted zip files.
bad_zip(Config) when is_list(Config) ->
- ok = file:set_cwd(?config(priv_dir, Config)),
+ ok = file:set_cwd(proplists:get_value(priv_dir, Config)),
try_bad("bad_crc", {bad_crc, "abc.txt"}, Config),
try_bad("bad_central_directory", bad_central_directory, Config),
try_bad("bad_file_header", bad_file_header, Config),
@@ -538,7 +515,7 @@ try_bad(N, R, Config) ->
try_bad(Name0, Reason, What, Config) ->
%% Intentionally no macros here.
- DataDir = ?config(data_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
Name = Name0 ++ ".zip",
io:format("~nTrying ~s", [Name]),
Full = filename:join(DataDir, Name),
@@ -548,14 +525,13 @@ try_bad(Name0, Reason, What, Config) ->
io:format("Result: ~p\n", [Expected]);
Other ->
io:format("unzip/2 returned ~p (expected ~p)\n", [Other, Expected]),
- test_server:fail({bad_return_value, Other})
+ ct:fail({bad_return_value, Other})
end.
-unzip_to_binary(doc) ->
- ["Test extracting to binary with memory option."];
+%% Test extracting to binary with memory option.
unzip_to_binary(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
WorkDir = filename:join(PrivDir, "unzip_to_binary"),
_ = file:make_dir(WorkDir),
@@ -574,11 +550,10 @@ unzip_to_binary(Config) when is_list(Config) ->
ok.
-zip_to_binary(doc) ->
- ["Test compressing to binary with memory option."];
+%% Test compressing to binary with memory option.
zip_to_binary(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
WorkDir = filename:join(PrivDir, "zip_to_binary"),
_ = file:make_dir(WorkDir),
@@ -607,8 +582,7 @@ zip_to_binary(Config) when is_list(Config) ->
ok.
-aliases(doc) ->
- ["Test using the aliases, extract/2, table/2 and create/3"];
+%% Test using the aliases, extract/2, table/2 and create/3.
aliases(Config) when is_list(Config) ->
{_, _, X0} = erlang:timestamp(),
Size = 100,
@@ -629,11 +603,10 @@ aliases(Config) when is_list(Config) ->
-unzip_from_binary(doc) ->
- ["Test extracting a zip archive from a binary."];
+%% Test extracting a zip archive from a binary.
unzip_from_binary(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
ExtractDir = filename:join(PrivDir, "extract_from_binary"),
ok = file:make_dir(ExtractDir),
Archive = filename:join(ExtractDir, "abc.zip"),
@@ -699,11 +672,9 @@ do_delete_files([Item|Rest], Cnt) ->
end,
do_delete_files(Rest, Cnt + DelCnt).
-compress_control(doc) ->
- ["Test control of which files that should be compressed"];
-compress_control(suite) -> [];
+%% Test control of which files that should be compressed.
compress_control(Config) when is_list(Config) ->
- ok = file:set_cwd(?config(priv_dir, Config)),
+ ok = file:set_cwd(proplists:get_value(priv_dir, Config)),
Dir = "compress_control",
Files = [
{Dir, dir, $d},
@@ -834,32 +805,32 @@ extensions([], Old) ->
Old.
foldl(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
File = filename:join([PrivDir, "foldl.zip"]),
FooBin = <<"FOO">>,
BarBin = <<"BAR">>,
Files = [{"foo", FooBin}, {"bar", BarBin}],
- ?line {ok, {File, Bin}} = zip:create(File, Files, [memory]),
+ {ok, {File, Bin}} = zip:create(File, Files, [memory]),
ZipFun = fun(N, I, B, Acc) -> [{N, B(), I()} | Acc] end,
- ?line {ok, FileSpec} = zip:foldl(ZipFun, [], {File, Bin}),
- ?line [{"bar", BarBin, #file_info{}}, {"foo", FooBin, #file_info{}}] = FileSpec,
- ?line {ok, {File, Bin}} = zip:create(File, lists:reverse(FileSpec), [memory]),
- ?line {foo_bin, FooBin} =
+ {ok, FileSpec} = zip:foldl(ZipFun, [], {File, Bin}),
+ [{"bar", BarBin, #file_info{}}, {"foo", FooBin, #file_info{}}] = FileSpec,
+ {ok, {File, Bin}} = zip:create(File, lists:reverse(FileSpec), [memory]),
+ {foo_bin, FooBin} =
try
zip:foldl(fun("foo", _, B, _) -> throw(B()); (_, _, _, Acc) -> Acc end, [], {File, Bin})
catch
throw:FooBin ->
{foo_bin, FooBin}
end,
- ?line ok = file:write_file(File, Bin),
- ?line {ok, FileSpec} = zip:foldl(ZipFun, [], File),
+ ok = file:write_file(File, Bin),
+ {ok, FileSpec} = zip:foldl(ZipFun, [], File),
- ?line {error, einval} = zip:foldl(fun() -> ok end, [], File),
- ?line {error, einval} = zip:foldl(ZipFun, [], 42),
- ?line {error, einval} = zip:foldl(ZipFun, [], {File, 42}),
+ {error, einval} = zip:foldl(fun() -> ok end, [], File),
+ {error, einval} = zip:foldl(ZipFun, [], 42),
+ {error, einval} = zip:foldl(ZipFun, [], {File, 42}),
- ?line ok = file:delete(File),
- ?line {error, enoent} = zip:foldl(ZipFun, [], File),
+ ok = file:delete(File),
+ {error, enoent} = zip:foldl(ZipFun, [], File),
ok.
diff --git a/lib/syntax_tools/src/erl_recomment.erl b/lib/syntax_tools/src/erl_recomment.erl
index 72e1e2d2f5..5ce533285d 100644
--- a/lib/syntax_tools/src/erl_recomment.erl
+++ b/lib/syntax_tools/src/erl_recomment.erl
@@ -611,12 +611,15 @@ expand_comment(C) ->
attrs :: erl_syntax:syntaxTreeAttributes(),
precomments = [] :: [erl_syntax:syntaxTree()],
postcomments = [] :: [erl_syntax:syntaxTree()],
- subtrees = [] :: [erl_syntax:syntaxTree()]}).
+ subtrees = [] :: [extendedSyntaxTree()]}).
+
-record(list, {min = 0 :: integer(),
max = 0 :: integer(),
subtrees = [] :: [erl_syntax:syntaxTree()]}).
+-type extendedSyntaxTree() :: #tree{} | #leaf{} | #list{}.
+
leaf_node(Min, Max, Value) ->
#leaf{min = Min,
max = Max,
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index 3f2a3e05dd..97b5797b06 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -355,7 +355,7 @@
%% where `Pos' `Ann' and `Comments' are the corresponding values of a
%% `tree' or `wrapper' record.
--record(attr, {pos = 0 :: term(),
+-record(attr, {pos = erl_anno:new(0) :: term(),
ann = [] :: [term()],
com = none :: 'none' | #com{}}).
-type syntaxTreeAttributes() :: #attr{}.
diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl
index 5b5b18d15b..58c4cc5244 100644
--- a/lib/syntax_tools/src/erl_syntax_lib.erl
+++ b/lib/syntax_tools/src/erl_syntax_lib.erl
@@ -359,9 +359,9 @@ new_variable_name(S) ->
%% within a reasonably small range relative to the number of elements in
%% the set.
%%
-%% This function uses the module `random' to generate new
+%% This function uses the module `rand' to generate new
%% keys. The seed it uses may be initialized by calling
-%% `random:seed/0' or `random:seed/3' before this
+%% `rand:seed/1' or `rand:seed/2' before this
%% function is first called.
%%
%% @see new_variable_name/1
@@ -404,7 +404,13 @@ start_range(S) ->
%% order, but (pseudo-)randomly distributed over the range.
generate(_Key, Range) ->
- random:uniform(Range). % works well
+ _ = case rand:export_seed() of
+ undefined ->
+ rand:seed(exsplus, {753,8,73});
+ _ ->
+ ok
+ end,
+ rand:uniform(Range). % works well
%% =====================================================================
diff --git a/lib/syntax_tools/src/erl_tidy.erl b/lib/syntax_tools/src/erl_tidy.erl
index db7f0939a3..f2de12b410 100644
--- a/lib/syntax_tools/src/erl_tidy.erl
+++ b/lib/syntax_tools/src/erl_tidy.erl
@@ -937,7 +937,7 @@ hidden_uses_2(Tree, Used) ->
-record(env, {file :: file:filename(),
module :: atom(),
- current :: fa(),
+ current :: fa() | 'undefined',
imports = dict:new() :: dict:dict(atom(), atom()),
context = normal :: context(),
verbosity = 1 :: 0 | 1 | 2,
@@ -949,10 +949,10 @@ hidden_uses_2(Tree, Used) ->
new_guard_tests = true :: boolean(),
old_guard_tests = false :: boolean()}).
--record(st, {varc :: non_neg_integer(),
+-record(st, {varc :: non_neg_integer() | 'undefined',
used = sets:new() :: sets:set({atom(), arity()}),
imported :: sets:set({atom(), arity()}),
- vars :: sets:set(atom()),
+ vars :: sets:set(atom()) | 'undefined',
functions :: sets:set({atom(), arity()}),
new_forms = [] :: [erl_syntax:syntaxTree()],
rename :: dict:dict(mfa(), {atom(), atom()})}).
@@ -1064,13 +1064,13 @@ visit_clause(Tree, Env, St0) ->
visit_infix_expr(Tree, #env{context = guard_test}, St0) ->
%% Detect transition from guard test to guard expression.
- visit_other(Tree, #env{context = guard_expr}, St0);
+ visit_other(Tree, #env{context = guard_expr, file = ""}, St0);
visit_infix_expr(Tree, Env, St0) ->
visit_other(Tree, Env, St0).
visit_prefix_expr(Tree, #env{context = guard_test}, St0) ->
%% Detect transition from guard test to guard expression.
- visit_other(Tree, #env{context = guard_expr}, St0);
+ visit_other(Tree, #env{context = guard_expr, file = ""}, St0);
visit_prefix_expr(Tree, Env, St0) ->
visit_other(Tree, Env, St0).
diff --git a/lib/syntax_tools/src/igor.erl b/lib/syntax_tools/src/igor.erl
index eac5af5540..4557678f9d 100644
--- a/lib/syntax_tools/src/igor.erl
+++ b/lib/syntax_tools/src/igor.erl
@@ -1594,10 +1594,11 @@ alias_expansions_2(Modules, Table) ->
preserved :: boolean(),
no_headers :: boolean(),
notes :: notes(),
- map :: map_fun(),
+ map :: map_fun() | 'undefined',
renaming :: fun((atom()) -> map_fun()),
expand :: dict:dict({atom(), integer()},
- {atom(), {atom(), integer()}}),
+ {atom(), {atom(), integer()}})
+ | 'undefined',
redirect :: dict:dict(atom(), atom())
}).
diff --git a/lib/syntax_tools/src/merl.erl b/lib/syntax_tools/src/merl.erl
index 690306c17b..163ce48bbc 100644
--- a/lib/syntax_tools/src/merl.erl
+++ b/lib/syntax_tools/src/merl.erl
@@ -514,15 +514,17 @@ parse_forms([]) ->
parse_2(Ts) ->
%% one or more comma-separated expressions?
%% (recall that Ts has no dot tokens if we get to this stage)
- case erl_parse:parse_exprs(Ts ++ [{dot,0}]) of
+ A = a0(),
+ case erl_parse:parse_exprs(Ts ++ [{dot,A}]) of
{ok, Exprs} -> Exprs;
{error, E} ->
- parse_3(Ts ++ [{'end',0}, {dot,0}], [E])
+ parse_3(Ts ++ [{'end',A}, {dot,A}], [E])
end.
parse_3(Ts, Es) ->
%% try-clause or clauses?
- case erl_parse:parse_exprs([{'try',0}, {atom,0,true}, {'catch',0} | Ts]) of
+ A = a0(),
+ case erl_parse:parse_exprs([{'try',A}, {atom,A,true}, {'catch',A} | Ts]) of
{ok, [{'try',_,_,_,_,_}=X]} ->
%% get the right kind of qualifiers in the clause patterns
erl_syntax:try_expr_handlers(X);
@@ -533,7 +535,8 @@ parse_3(Ts, Es) ->
parse_4(Ts, Es) ->
%% fun-clause or clauses? (`(a)' is also a pattern, but `(a,b)' isn't,
%% so fun-clauses must be tried before normal case-clauses
- case erl_parse:parse_exprs([{'fun',0} | Ts]) of
+ A = a0(),
+ case erl_parse:parse_exprs([{'fun',A} | Ts]) of
{ok, [{'fun',_,{clauses,Cs}}]} -> Cs;
{error, E} ->
parse_5(Ts, [E|Es])
@@ -541,7 +544,8 @@ parse_4(Ts, Es) ->
parse_5(Ts, Es) ->
%% case-clause or clauses?
- case erl_parse:parse_exprs([{'case',0}, {atom,0,true}, {'of',0} | Ts]) of
+ A = a0(),
+ case erl_parse:parse_exprs([{'case',A}, {atom,A,true}, {'of',A} | Ts]) of
{ok, [{'case',_,_,Cs}]} -> Cs;
{error, E} ->
%% select the best error to report
@@ -1210,7 +1214,7 @@ merge_comments(StartLine, Cs, [], Acc) ->
merge_comments(StartLine, [], [],
[erl_syntax:set_pos(
erl_syntax:comment(Indent, Text),
- StartLine + Line - 1)
+ anno(StartLine + Line - 1))
|| {Line, _, Indent, Text} <- Cs] ++ Acc);
merge_comments(StartLine, [C|Cs], [T|Ts], Acc) ->
{Line, _Col, Indent, Text} = C,
@@ -1228,3 +1232,9 @@ merge_comments(StartLine, [C|Cs], [T|Ts], Acc) ->
[erl_syntax:comment(Indent, Text)], T),
merge_comments(StartLine, Cs, [Tc|Ts], Acc)
end.
+
+a0() ->
+ anno(0).
+
+anno(Location) ->
+ erl_anno:new(Location).
diff --git a/lib/syntax_tools/src/merl_transform.erl b/lib/syntax_tools/src/merl_transform.erl
index 66b06c8137..fe58b6a122 100644
--- a/lib/syntax_tools/src/merl_transform.erl
+++ b/lib/syntax_tools/src/merl_transform.erl
@@ -68,8 +68,7 @@ case_guard([{expr,_}, {text,Text}]) ->
erl_syntax:is_literal(Text).
case_body([{expr,Expr}, {text,_Text}], T) ->
- pre_expand_case(Expr, erl_syntax:case_expr_clauses(T),
- erl_syntax:get_pos(T)).
+ pre_expand_case(Expr, erl_syntax:case_expr_clauses(T), get_location(T)).
post(T) ->
merl:switch(
@@ -79,7 +78,7 @@ post(T) ->
lists:all(fun erl_syntax:is_literal/1, [F|As])
end,
fun ([{args, As}, {function, F}]) ->
- Line = erl_syntax:get_pos(F),
+ Line = get_location(F),
[F1|As1] = lists:map(fun erl_syntax:concrete/1, [F|As]),
eval_call(Line, F1, As1, T)
end},
@@ -118,7 +117,7 @@ expand_qquote(_As, T, _StartPos) ->
expand_template(F, [Pattern | Args], T) ->
case erl_syntax:is_literal(Pattern) of
true ->
- Line = erl_syntax:get_pos(Pattern),
+ Line = get_location(Pattern),
As = [erl_syntax:concrete(Pattern)],
merl:qquote(Line, "merl:_@function(_@pattern, _@args)",
[{function, F},
@@ -260,3 +259,12 @@ is_erlang_var([C|_]) when C >= $A, C =< $Z ; C >= $À, C =< $Þ, C /= $× ->
true;
is_erlang_var(_) ->
false.
+
+get_location(T) ->
+ Pos = erl_syntax:get_pos(T),
+ case erl_anno:is_anno(Pos) of
+ true ->
+ erl_anno:location(Pos);
+ false ->
+ Pos
+ end.
diff --git a/lib/syntax_tools/test/Makefile b/lib/syntax_tools/test/Makefile
index 569c044b1a..4ace860223 100644
--- a/lib/syntax_tools/test/Makefile
+++ b/lib/syntax_tools/test/Makefile
@@ -26,7 +26,7 @@ RELSYSDIR = $(RELEASE_PATH)/syntax_tools_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_COMPILE_FLAGS +=
EBIN = .
diff --git a/lib/syntax_tools/test/merl_SUITE.erl b/lib/syntax_tools/test/merl_SUITE.erl
index 125250395a..945972d405 100644
--- a/lib/syntax_tools/test/merl_SUITE.erl
+++ b/lib/syntax_tools/test/merl_SUITE.erl
@@ -16,7 +16,7 @@
%%
-module(merl_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% include the Merl header file
-include_lib("syntax_tools/include/merl.hrl").
diff --git a/lib/syntax_tools/test/syntax_tools_SUITE.erl b/lib/syntax_tools/test/syntax_tools_SUITE.erl
index 40e00e0554..eb52cce6af 100644
--- a/lib/syntax_tools/test/syntax_tools_SUITE.erl
+++ b/lib/syntax_tools/test/syntax_tools_SUITE.erl
@@ -18,7 +18,7 @@
%%
-module(syntax_tools_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
diff --git a/lib/test_server/AUTHORS b/lib/test_server/AUTHORS
deleted file mode 100644
index 3212999174..0000000000
--- a/lib/test_server/AUTHORS
+++ /dev/null
@@ -1,12 +0,0 @@
-Original Authors and Contributors:
-
-Mattias Nilsson
-Bj�rn Gustavsson
-Janne Lindblad
-Patrik Winroth
-Claes Wikstr�m
-Siri Hansen
-Peter Andersson
-
-...and others.
-
diff --git a/lib/test_server/Makefile b/lib/test_server/Makefile
deleted file mode 100644
index 382749d1fc..0000000000
--- a/lib/test_server/Makefile
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-2009. 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
-
-#
-# Macros
-#
-
-SUB_DIRECTORIES = src doc/src
-
-include vsn.mk
-VSN = $(TEST_SERVER_VSN)
-
-SPECIAL_TARGETS =
-
-#
-# Default Subdir Targets
-#
-include $(ERL_TOP)/make/otp_subdir.mk
-
diff --git a/lib/test_server/README b/lib/test_server/README
deleted file mode 100644
index fc71c90ca8..0000000000
--- a/lib/test_server/README
+++ /dev/null
@@ -1,113 +0,0 @@
-===========================================================================
- OTP Test Server
-===========================================================================
-
-To compile the 'test_server' application you need to build and install
-a Erlang/OTP system from source. Get your open source Erlang/OTP from
-http://www.erlang.org/. The resulting "erlc" command must be in the
-search path for commands.
-
-The Erlang test_server application and the example tests are to be
-inserted into an existing source tree for Erlang/OTP.
-
-You don't run the Test Server or the tests from the source tree.
-Instead a test installation area $TESTROOT is used with the resulting
-directory structure
-
- $TESTROOT/test_server
- $TESTROOT/<app1>_test
- $TESTROOT/<app2>_test
- .
- .
-
-For more details see the test_server documentation can be found in the
-"$ERL_TOP/lib/test_server/doc/html" directory.
-
-
-Unpacking the sources
----------------------
-
-Enter your Erlang/OTP source tree and unpack the OTP Test Server and
-optionally the test examples
-
- % cd otp_src_RXX
- % gunzip -c test_server-<VSN>.tar.gz | tar xf -
- % gunzip -c emulator-YYYY-MM-DD.tar.gz | tar xf -
- % gunzip -c stdlib-YYYY-MM-DD.tar.gz | tar xf -
-
-
-How to build and install the OTP Test Server
---------------------------------------------
-
-Set the ERL_TOP variable to the top directory of the source tree
-
- % cd otp_src_RXX
-
- % setenv ERL_TOP `pwd`
- or
- % export ERL_TOP=`pwd`
-
-If not done before you need to run the configure script
-
- % ./configure
-
-Then build and install from the the base directory of the test_server
-application
-
- % cd lib/test_server
- % gmake release_tests TESTROOT=<some dir>
-
-
-How to build and install the example test suites
-------------------------------------------------
-
-If you want to build and install the example test suites
-you build and install from the the test directories
-
- % cd $ERL_TOP/lib/stdlib/test
- % gmake release_tests TESTROOT=<some dir>
-
- % cd $ERL_TOP/erts/emulator/test
- % gmake release_tests TESTROOT=<some dir>
-
-
-How to run OTP test suites
---------------------------
-
-First cd into $TESTROOT/test_server
-
- % cd $TESTROOT/test_server
-
-Install the OTP Test Server framework
-
- % erl
- 1> ts:install().
-
-Check which tests are available
-
- 2> ts:tests().
- [...]
-
-Run the collections of test suites one at the time
-
- 3> ts:run(emulator). (starts a xterm with an Erlang shell)
- 4> ts:run(stdlib). (starts a xterm with an Erlang shell)
-
-or all at once
-
- 5> ts:run(). (the node running the tests will be in the background)
-
-Note that it is normal to see lots of error messages in the Erlang
-shell. The tests will stress the system with lots of invalid input to
-find problems in the error handling.
-
-Also note that a failing test case does not always indicate a bug in
-Erlang/OTP. Differences in the network setup, machine configuration
-etc may cause a test case to fail or time out.
-
-The result of the tests are recorded in the file named "index.html" in
-the "$TESTROOT/test_server" directory. You can follow the progress of
-tests suites not yet completed from "last_test.html".
-
-For more details see the test_server documentation can be found in the
-"$ERL_TOP/lib/test_server/doc/html" directory.
diff --git a/lib/test_server/doc/html/.gitignore b/lib/test_server/doc/html/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/test_server/doc/html/.gitignore
+++ /dev/null
diff --git a/lib/test_server/doc/man3/.gitignore b/lib/test_server/doc/man3/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/test_server/doc/man3/.gitignore
+++ /dev/null
diff --git a/lib/test_server/doc/man6/.gitignore b/lib/test_server/doc/man6/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/test_server/doc/man6/.gitignore
+++ /dev/null
diff --git a/lib/test_server/doc/pdf/.gitignore b/lib/test_server/doc/pdf/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/test_server/doc/pdf/.gitignore
+++ /dev/null
diff --git a/lib/test_server/doc/src/Makefile b/lib/test_server/doc/src/Makefile
deleted file mode 100644
index 8c5418aee5..0000000000
--- a/lib/test_server/doc/src/Makefile
+++ /dev/null
@@ -1,140 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2002-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%
-#
-
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(TEST_SERVER_VSN)
-APPLICATION=test_server
-
-DOC_EXTRA_FRONT_PAGE_INFO=Important note: \
-The Test Server application is obsolete and will be removed \
-in the next major OTP release
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = \
- test_server_ctrl.xml \
- test_server.xml
-XML_REF3_INTERNAL = \
- ts.xml
-XML_REF6_FILES = test_server_app.xml
-
-XML_PART_FILES = \
- part.xml \
- part_notes.xml \
- part_notes_history.xml
-
-XML_CHAPTER_FILES = \
- basics_chapter.xml \
- run_test_chapter.xml \
- write_test_chapter.xml \
- test_spec_chapter.xml \
- example_chapter.xml \
- write_framework_chapter.xml \
- notes.xml \
- notes_history.xml
-
-BOOK_FILES = book.xml
-
-XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) $(XML_REF6_FILES) \
- $(XML_PART_FILES) $(XML_CHAPTER_FILES)
-
-GIF_FILES =
-
-# ----------------------------------------------------
-
-HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
-
-HTML_INTERNAL = $(XML_REF3_INTERNAL:%.xml=$(HTMLDIR)/%.html)
-
-INFO_FILE = ../../info
-
-MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-MAN3_INTERNAL = $(XML_REF3_INTERNAL:%.xml=$(MAN3DIR)/%.3)
-MAN6_FILES = $(XML_REF6_FILES:%_app.xml=$(MAN6DIR)/%.6)
-
-HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
-
-TOP_PDF_FILE = $(PDFDIR)/test_server-$(VSN).pdf
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-$(HTMLDIR)/%.gif: %.gif
- $(INSTALL_DATA) $< $@
-
-docs: pdf html man
-
-pdf: $(TOP_PDF_FILE)
-
-html: gifs $(HTML_REF_MAN_FILE)
-
-man: $(MAN3_FILES) $(MAN3_INTERNAL) $(MAN6_FILES)
-
-gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-
-debug opt:
-
-clean clean_docs:
- rm -rf $(HTMLDIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(MAN6DIR)/*
- rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_docs_spec: docs
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(HTMLDIR)/* \
- "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
- $(INSTALL_DATA) $(MAN3_FILES) "$(RELEASE_PATH)/man/man3"
- $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6"
- $(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6"
-
-release_spec:
-
-release_tests_spec:
diff --git a/lib/test_server/doc/src/basics_chapter.xml b/lib/test_server/doc/src/basics_chapter.xml
deleted file mode 100644
index 9e9f38aab4..0000000000
--- a/lib/test_server/doc/src/basics_chapter.xml
+++ /dev/null
@@ -1,215 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2002</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Test Server Basics</title>
- <prepared>Siri Hansen</prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>basics_chapter.xml</file>
- </header>
-
- <section>
- <title>Introduction</title>
- <p><em>Test Server</em> is a portable test tool for automated
- testing of Erlang programs and OTP applications. It provides an
- interface for running test programs directly with Test Server
- as well as an interface for integrating Test Server
- with a framework application. The latter makes it possible to use
- Test Server as the engine of a higher level test tool
- application.</p>
-
- <p>It is strongly recommended that Test Server be used from inside
- a framework application, rather than interfaced directly for
- running test programs. Test Server can be pretty difficult to use
- since it's a very general and quite extensive and complex
- application. Furthermore, the <c>test_server_ctrl</c> functions
- are not meant to be used from within the actual test programs. The
- framework should handle communication with Test Server and deal
- with the more complex aspects of this interaction automatically so
- that a higher level interface may be provided for the tester. For
- test tool usage to be productive, a simpler, more intuitive and
- (if required) more specific interface is required than what Test Server
- can provide.</p>
-
- <p>OTP delivers a general purpose framework for Test Server, called
- <em>Common Test</em>. This application is a tool well suited for
- automated black box testing of target systems of <em>any kind</em>
- (not necessarily implemented in Erlang). Common Test is also a very
- useful tool for white box testing of Erlang programs and OTP
- applications. Unless a more specific functionality and/or user
- interface is required (in which case you might need to implement
- your own framework), Common Test should do the job for
- you. Please read the Common Test User's Guide and reference manual
- for more information.</p>
-
- <p>Under normal circumstances, knowledge about the Test Server
- application is not required for using the Common Test framework.
- However, if you want to use Test Server without a framework,
- or learn how to integrate it with your own framework, please read on...
- </p>
- </section>
- <section>
- <title>Getting started</title>
- <p>Testing when using Test Server is done by running test
- suites. A test suite is a number of test cases, where each test
- case tests one or more things. The test case is the smallest unit
- that the test server deals with. One or more test cases are
- grouped together into one ordinary Erlang module, which is called
- a test suite. Several test suite modules can be grouped together
- in special test specification files representing whole application
- and/or system test "jobs".
- </p>
- <p>The test suite Erlang module must follow a certain interface,
- which is specified by Test Server. See the section on writing
- test suites for details about this.
- </p>
- <p>Each test case is considered a success if it returns to the
- caller, no matter what the returned value is. An exception to this
- is the return value <c>{skip, Reason}</c> which indicates that the
- test case is skipped. A failure is specified as a crash, no matter
- what the crash reason is.
- </p>
- <p>As a test suite runs, all information (including output to
- stdout) is recorded in several different log files. A minimum of
- information is displayed to the user console. This only include
- start and stop information, plus a note for each failed test case.
- </p>
- <p>The result from each test case is recorded in an HTML log file
- which is created for each test run. Every test case gets one row
- in a table presenting total time, whether the case was successful
- or not, if it was skipped, and possibly also a comment. The HTML
- file has links to each test case's logfile, which may be viewed
- from e.g. Netscape or any other HTML capable browser.
- </p>
- <p>The Test Server consists of three parts:
- </p>
- <list type="bulleted">
- <item>The part that executes the test suites and
- provides support for the test suite author is called
- <c>test_server</c>. This is described in the chapter about
- writing test cases in this user's guide, and in the reference
- manual for the <c>test_server</c> module.</item>
- <item>The controlling part, which provides the low level
- operator interface, starts and stops slave nodes and writes
- log files, is called
- <c>test_server_ctrl</c>. The Test Server Controller should not
- be used directly when running tests. Instead a framework built
- on top of it should be used. More information
- about how to write your own framework can be found
- in this user's guide and in the reference manual for the
- <c>test_server_ctrl</c> module.</item>
- </list>
- </section>
-
- <section>
- <title>Definition of terms</title>
- <taglist>
- <tag><em>conf(iguration) case</em></tag>
- <item>This is a group of test cases which need some specific
- configuration. A conf case contains an initiation function which
- sets up a specific configuration, one or more test cases using
- this configuration, and a cleanup function which restores the
- configuration. A conf case is specified in a test specification
- either like this:<c>{conf,InitFunc,ListOfCases,CleanupFunc}</c>,
- or this: <c>{conf,Properties,InitFunc,ListOfCases,CleanupFunc}</c>
- </item>
- <tag><em>datadir</em></tag>
- <item>Data directory for a test suite. This directory contains
- any files used by the test suite, e.g. additional erlang
- modules, c code or data files. If the data directory contains
- code which must be compiled before the test suite is run, it
- should also contain a makefile source called Makefile.src
- defining how to compile.
- </item>
- <tag><em>documentation clause</em></tag>
- <item>One of the function clauses in a test case. This clause
- shall return a list of strings describing what the test case
- tests.
- </item>
- <tag><em>execution clause</em></tag>
- <item>One of the function clauses in a test case. This clause
- implements the actual test case, i.e. calls the functions that
- shall be tested and checks results. The clause shall crash if it
- fails.
- </item>
- <tag><em>major log file</em></tag>
- <item>This is the test suites log file.
- </item>
- <tag><em>Makefile.src</em></tag>
- <item>This file is used by the test server framework to generate
- a makefile for a datadir. It contains some special characters
- which are replaced according to the platform currently tested.
- </item>
- <tag><em>minor log file</em></tag>
- <item>This is a separate log file for each test case.
- </item>
- <tag><em>privdir</em></tag>
- <item>Private directory for a test suite. This directory should
- be used when the test suite needs to write to files.
- </item>
- <tag><em>skip case</em></tag>
- <item>A test case which shall be skipped.
- </item>
- <tag><em>specification clause</em></tag>
- <item>One of the function clauses in a test case. This clause
- shall return an empty list, a test specification or
- <c>{skip,Reason}</c>. If an empty list is returned, it means
- that the test case shall be executed, and so it must also have
- an execution clause.
- </item>
- <tag><em>test case</em></tag>
- <item>A single test included in a test suite. Typically it tests
- one function in a module or application. A test case is
- implemented as a function in a test suite module. The function
- can have three clauses, the documentation-, specification- and
- execution clause.
- </item>
- <tag><em>test specification</em></tag>
- <item>A specification of which test suites and test cases to
- run. There can be test specifications on three different levels
- in a test. The top level is a test specification file which
- roughly specifies what to test for a whole application. Then
- there is a test specification for each test suite returned from
- the <c>all(suite)</c> function in the suite. And there can also
- be a test specification returned from the specification clause
- of a test case.
- </item>
- <tag><em>test specification file</em></tag>
- <item>This is a text file containing the test specification for
- an application. The file has the extension ".spec" or
- ".spec.Platform", where Platform is e.g. "vxworks".
- </item>
- <tag><em>test suite</em></tag>
- <item>An erlang module containing a collection of test cases for
- a specific application or module.
- </item>
- <tag><em>topcase</em></tag>
- <item>The first "command" in a test specification file. This
- command contains the test specification, like this:
- <c>{topcase,TestSpecification}</c></item>
- </taglist>
- </section>
-</chapter>
-
diff --git a/lib/test_server/doc/src/book.xml b/lib/test_server/doc/src/book.xml
deleted file mode 100644
index 6eb7daae1a..0000000000
--- a/lib/test_server/doc/src/book.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book xmlns:xi="http://www.w3.org/2001/XInclude">
- <header titlestyle="normal">
- <copyright>
- <year>2002</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Test Server</title>
- <prepared>Siri Hansen</prepared>
- <docno></docno>
- <date>2002-07-11</date>
- <rev></rev>
- <file>book.xml</file>
- </header>
- <insidecover>
- </insidecover>
- <pagetext>Test Server</pagetext>
- <preamble>
- <contents level="2"></contents>
- </preamble>
- <parts lift="no">
- <xi:include href="part.xml"/>
- </parts>
- <applications>
- <xi:include href="ref_man.xml"/>
- </applications>
- <releasenotes>
- <xi:include href="notes.xml"/>
- </releasenotes>
- <listofterms></listofterms>
- <index></index>
-</book>
-
diff --git a/lib/test_server/doc/src/example_chapter.xml b/lib/test_server/doc/src/example_chapter.xml
deleted file mode 100644
index ec152fdd6c..0000000000
--- a/lib/test_server/doc/src/example_chapter.xml
+++ /dev/null
@@ -1,151 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2002</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Examples</title>
- <prepared>Siri Hansen</prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>example_chapter.xml</file>
- </header>
-
- <section>
- <title>Test suite</title>
- <code type="none">
--module(my_SUITE).
-
--export([all/1,
- not_started/1, not_started_func1/1, not_started_func2/1,
- start/1, stop/1,
- func1/1, func2/1
- ]).
-
--export([init_per_testcase/2, end_per_testcase/2]).
-
--include("test_server.hrl").
-
--define(default_timeout, ?t:minutes(1)).
-
-init_per_testcase(_Case, Config) ->
- Dog=?t:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
- ok.
-
-all(suite) ->
- %% Test specification on test suite level
- [not_started,
- {conf, start, [func1, func2], stop}].
-
-not_started(suite) ->
- %% Test specification on test case level
- [not_started_func1, not_started_func2];
-not_started(doc) ->
- ["Testing all functions when application is not started"].
-%% No execution clause unless the specification clause returns [].
-
-
-not_started_func1(suite) ->
- [];
-not_started_func1(doc) ->
- ["Testing function 1 when application is not started"].
-not_started_func1(Config) when list(Config) ->
- {error, not_started} = myapp:func1(dummy_ref,1),
- {error, not_started} = myapp:func1(dummy_ref,2),
- ok.
-
-not_started_func2(suite) ->
- [];
-not_started_func2(doc) ->
- ["Testing function 2 when application is not started"].
-not_started_func2(Config) when list(Config) ->
- {error, not_started} = myapp:func2(dummy_ref,1),
- {error, not_started} = myapp:func2(dummy_ref,2),
- ok.
-
-
-%% No specification clause needed for an init function in a conf case!!!
-start(doc) ->
- ["Testing start of my application."];
-start(Config) when list(Config) ->
- Ref = myapp:start(),
- case erlang:whereis(my_main_process) of
- Pid when pid(Pid) ->
- [{myapp_ref,Ref}|Config];
- undefined ->
- %% Since this is the init function in a conf case, the rest of the
- %% cases in the conf case will be skipped if this case fails.
- ?t:fail("my_main_process did not start")
- end.
-
-func1(suite) ->
- [];
-func1(doc) ->
- ["Test that func1 returns ok when argument is 1 and error if argument is 2"];
-func1(Config) when list(Config) ->
- Ref = ?config(myapp_ref,Config),
- ok = myapp:func1(Ref,1),
- error = myapp:func1(Ref,2),
- ok.
-
-func2(suite) ->
- [];
-func2(doc) ->
- ["Test that func1 returns ok when argument is 3 and error if argument is 4"];
-func2(Config) when list(Config) ->
- Ref = ?config(myapp_ref,Config),
- ok = myapp:func2(Ref,3),
- error = myapp:func2(Ref,4),
- ok.
-
-%% No specification clause needed for a cleanup function in a conf case!!!
-stop(doc) ->
- ["Testing termination of my application"];
-stop(Config) when list(Config) ->
- Ref = ?config(myapp_ref,Config),
- ok = myapp:stop(Ref),
- case erlang:whereis(my_main_process) of
- undefined ->
- lists:keydelete(myapp_ref,1,Config);
- Pid when pid(Pid) ->
- ?t:fail("my_main_process did not stop")
- end.
- </code>
- </section>
-
- <section>
- <title>Test specification file</title>
- <p><em><c>myapp.spec:</c></em></p>
- <code type="none">
-{topcase, {dir, "../myapp_test"}}. % Test specification on top level </code>
- <p><em><c>myapp.spec.vxworks:</c></em></p>
- <code type="none">
-{topcase, {dir, "../myapp_test"}}. % Test specification on top level
-{skip,{my_SUITE,func2,"Not applicable on VxWorks"}}. </code>
- </section>
-</chapter>
-
-
diff --git a/lib/test_server/doc/src/fascicules.xml b/lib/test_server/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/test_server/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/test_server/doc/src/notes.xml b/lib/test_server/doc/src/notes.xml
deleted file mode 100644
index 9b5df6271a..0000000000
--- a/lib/test_server/doc/src/notes.xml
+++ /dev/null
@@ -1,1715 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2004</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>APPLICATION Release Notes</title>
- <prepared>Peter Andersson</prepared>
- <responsible>Peter Andersson</responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2007-11-30</date>
- <rev>A</rev>
- <file>notes.xml</file>
- </header>
-
-<section><title>Test_Server 3.10</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Two new CT hook functions have been added:
- <c>post_init_per_testcase/4</c> and
- <c>pre_end_per_testcase/3</c>. With these hook functions,
- it is possible to perform arbitrary actions (including
- modifications of test execution, test state and results)
- immediately before and after the execution of the test
- case.</p>
- <p>
- Own Id: OTP-13242 Aux Id: seq12991 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.9.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- When generating Makefile from Makefile.src,
- ts_lib:get_arg/4 earlier removed all spaces in the
- extracted argument. The code was probably meant for
- removing leading and trailing spaces only, and is now
- corrected to do so.</p>
- <p>
- Own Id: OTP-13015</p>
- </item>
- <item>
- <p>
- With the Common Test 'create_priv_dir' start option set
- to 'auto_per_tc', the name of the priv directory for a
- configuration function could clash with the name of the
- priv directory for a test case, which would cause Test
- Server failure. This error has been corrected.</p>
- <p>
- Own Id: OTP-13181</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.9</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- The status of an aborted test due to test suite
- compilation error has changed from 'auto_skipped' to
- 'failed'. This affects both the textual log file, event
- handling and CT hook callbacks. The logging of
- compilation failures has also been improved, especially
- in the case of multiple test suites failing compilation.</p>
- <p>
- Own Id: OTP-10816</p>
- </item>
- <item>
- <p>
- The Test Server source code parser (erl2html2) failed to
- handle the macro tuple in the syntax tree returned by
- epp_dodger. This error has been corrected.</p>
- <p>
- Own Id: OTP-12740</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- The Test Server application has been marked as obsolete
- and will be removed from OTP in the next major release
- (OTP 19.0).</p>
- <p>
- Own Id: OTP-10923 Aux Id: OTP-12705 </p>
- </item>
- <item>
- <p>
- When running OTP tests using the ts interface, it is now
- possible to specify so called test categories per OTP
- application. A test category is represented by a CT test
- specification and defines an arbitrary subset of existing
- test suites, groups and cases. Examples of test
- categories are 'smoke' (smoke tests) and 'bench'
- (benchmarks). (Call ts:help() for more info). Also,
- functions for reading terms from the current test
- specification during test, ct:get_testspec_terms/0 and
- ct:get_testspec_terms/1, have been implemented.</p>
- <p>
- Own Id: OTP-11962</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.8.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- If the last expression in a test case causes a timetrap
- timeout, the stack trace is ignored and not printed to
- the test case log file. This happens because the
- {Suite,TestCase,Line} info is not available in the stack
- trace in this scenario, due to tail call elimination.
- Common Test has been modified to handle this situation by
- inserting a {Suite,TestCase,last_expr} tuple in the
- correct place and printing the stack trace as expected.</p>
- <p>
- Own Id: OTP-12697 Aux Id: seq12848 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.8</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- When installing test suites in a cross compilation
- environment, ts_install was not able to read the values
- of the environment variables specified in the
- configuration file. This has been fixed.</p>
- <p>
- Own Id: OTP-11441</p>
- </item>
- <item>
- <p>
- Printouts by means of ct:log/2/3 or ct:pal/2/3 from the
- hook functions on_tc_fail/2 and on_tc_skip/2 would (quite
- unexpectedly) end up in the "unexpected i/o" log file
- instead of in the test case log file. This behaviour has
- been changed so that now, all printouts (including stdio
- printouts) from these hook functions will be routed to
- the test case log file.</p>
- <p>
- Own Id: OTP-12468</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- The format of the information printed on top of the test
- case (and configuration function) log file has been
- slightly modified, mainly in order to make the start
- configuration data easier to read and interpret.</p>
- <p>
- Own Id: OTP-12518 Aux Id: seq12808 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.7.2</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- The source code to html code generator in Test Server
- (and Common Test) would fail to generate anchors in the
- html code for functions with non-expandable macros,
- resulting in bad html links to such functions. This
- correction lets the code generator ignore macros that
- can't be expanded (i.e. not pre-process them), so that
- correct anchors will always be produced.</p>
- <p>
- Own Id: OTP-11766 Aux Id: seq12556 </p>
- </item>
- <item>
- <p>
- Make sure to install .hrl files when needed</p>
- <p>
- Own Id: OTP-12197</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Distribute <c>autoconf</c> helpers to applications at
- build time instead of having multiple identical copies
- committed in the repository.</p>
- <p>
- Own Id: OTP-12348</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.7.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- The mechanism for running code cover analysis with
- common_test has been improved. Earlier, if a test run
- consisted of multiple tests, cover would be started and
- stopped for each test. This would give "intermediate"
- cover logs available from the "Coverage log" link on the
- test suite result pages. To accumulate cover data over
- all tests, the 'export' option had to be used in the
- cover spec file. This was not well documented, and the
- functionality was quite confusing.</p>
- <p>
- Using the 'nodes' option in the cover spec file would
- fail when the test run consisted of multiple tests, since
- the specified nodes would only be included in the cover
- analysis of the first test.</p>
- <p>
- The repeated compilation and analysis of the same modules
- was also very time consuming.</p>
- <p>
- To overcome these problems, ct will now only cover
- compile and analyze modules once per test run, i.e. once
- for each cover spec file. The log file is available via a
- new button on the top level index page. The old "Coverage
- log" links on the test suite result pages still exist,
- but they all point to the same log containing the
- accumulated result.</p>
- <p>
- Own Id: OTP-11971</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.7</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Application upgrade (appup) files are corrected for the
- following applications: </p>
- <p>
- <c>asn1, common_test, compiler, crypto, debugger,
- dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe,
- inets, observer, odbc, os_mon, otp_mibs, parsetools,
- percept, public_key, reltool, runtime_tools, ssh,
- syntax_tools, test_server, tools, typer, webtool, wx,
- xmerl</c></p>
- <p>
- A new test utility for testing appup files is added to
- test_server. This is now used by most applications in
- OTP.</p>
- <p>
- (Thanks to Tobias Schlager)</p>
- <p>
- Own Id: OTP-11744</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Calls to erlang:open_port/2 with 'spawn' are updated to
- handle space in the command path.</p>
- <p>
- Own Id: OTP-10842</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.6.4</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>The way Common Test handles skipping of test cases has
- been updated. In previous versions, returning
- <c>{skip,Reason}</c> from a configuration function (such
- as init_per_suite or init_per_group), resulted in all
- affected test cases getting skipped with status
- <c>auto_skipped</c>. This was inappropriate, since this
- status is supposed to be used to inform that Common Test
- has taken the initiative to skip something (e.g. a test
- case group if init_per_group failed). Therefore, in this
- version of Common Test, whenever the user skips a suite,
- group, or individual test case (by means of a
- configuration function or test specification term), the
- affected test cases get the status <c>user_skipped</c>
- instead.</p> <p>This update has meant a few changes that
- may affect Common Test users in various ways:</p> <list>
- <item>The test results and statistics will be affected,
- which is important to know when running regression tests
- and comparing results to previous test runs.</item>
- <item>Users that read or parse the textual log file
- <c>suite.log</c> will notice that an auto skipped
- function is now reported as <c>auto_skipped</c> rather
- than <c>skipped</c> as before.</item> <item>When
- <c>require</c> fails in an info function (such as suite/0
- or group/1), all affected configuration functions and
- test cases are marked as <c>auto_skipped</c>.</item>
- <item>If Common Test detects an error in the test suite
- (such as e.g. an invalid all/0 function), all affected
- configuration functions and test cases are marked as
- <c>auto_skipped</c>.</item> <item>If a repeated test run
- session reaches a deadline with <c>force_stop</c>
- enabled, all remaining test cases are marked as
- <c>auto_skipped</c> rather than <c>user_skipped</c> as
- before.</item> <item>The event messages that Common Test
- generates during test runs have been affected by this
- update. For details see OTP-11524.</item> </list>
- <p>
- Own Id: OTP-11305 Aux Id: OTP-11524 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.6.3</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Test Server installed an error handler (test_server_h)
- only to be able to write the name of the current test
- case to stdout whenever it received an error- or progress
- report. This functionality was not useful and has been
- removed. The built-in Common Test hook, cth_log_redirect,
- has instead been improved to now also tag all error- and
- progress reports in the log with suite-, group-, and/or
- test case name.</p>
- <p>
- Own Id: OTP-11263 Aux Id: seq12251 </p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- A new log, the "Pre- and Post Test I/O Log", has been
- introduced, which makes it possible to capture error- and
- progress reports, as well as printouts made with ct:log/2
- and ct:pal/2, before and after a test run. (Some minor
- improvements of the logging system have been made at the
- same time). Links to the new log are found on the Common
- Test Framework Log page. The Common Test User's Guide has
- been updated with information about the new log and also
- with a new section on how to synchronize external
- applications with Common Test by means of the CT Hook
- init and terminate functions.</p>
- <p>
- Own Id: OTP-11272</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Known Bugs and Problems</title>
- <list>
- <item>
- <p>
- Test Server: Report auto_skipped in major log.</p>
- <p>
- Own Id: OTP-11297</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.6.2</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Some unused code related to remote targets is removed,
- and documentation is updated.</p>
- <p>
- Own Id: OTP-10607 Aux Id: kunagi-338 [249] </p>
- </item>
- <item>
- <p>
- A bug in test_server_gl caused io requests containing
- invalid data (i.e. not unicode:chardata()) to hang, since
- no io reply was sent. This has been corrected.</p>
- <p>
- Own Id: OTP-10991</p>
- </item>
- <item>
- <p>
- Common Test would, in case of timetrap error, print a
- warning in the log if end_per_testcase wasn't implemented
- in the suite, even though it's an optional function. This
- printout has been removed.</p>
- <p>
- Own Id: OTP-11052</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- The '-force_stop' flag to use with time-limited repeats
- of test runs can now be used with a new 'skip_rest'
- option which causes the rest of the test cases in the
- ongoing test job to be skipped when the time limit is
- reached. E.g. 'ct_run -spec xxx -duration 010000
- -force_stop skip_rest'</p>
- <p>
- Own Id: OTP-10856 Aux Id: OTP-10832 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.6.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- The unicode update of test_server for R16A introduced a
- few potential errors when logging to files. Sometimes ~tp
- or ~ts was used for formatting also when writing to files
- that were not opened with the {encoding,utf8} option. If
- then the argument contained unicode characters above 255,
- the file descriptor would crash. This has been corrected
- by the following modifications:</p> <list> <item> Since the
- 'unexpected_io' log file is used only when the test case
- HTML file is not available (e.g. between test cases),
- this file is now also a HTML file and as other
- test_server HTML logs it is always UTF-8 encoded </item>
- <item> Since it is possible to change which information
- is going to which log file (with
- test_server_ctrl:set_levels/3), we do not have full
- control over which information is written to which file.
- This means that any printout could be written to the
- 'major' log file (suite.log), which was earlier encoded
- as latin1. To avoid crashing this file descriptor due to
- unicode strings, the 'major' log file is now also encoded
- in UTF-8 (possible incopatibility). </item> <item> The
- cross_cover.info file is no longer a text file which can
- be read with file:consult/1, instead it is written as a
- pure binary file using term_to_binary when writing and
- binary_to_term when reading. </item> <item> The encoding
- of the file named 'last_name', which only content is the
- path to the last run.&lt;timestamp&gt; directory, is now
- dependent on the file name mode of the VM. If file names
- are expected to be unicode, then the 'last_name' file is
- UTF-8 encoded, else it is latin1 encoded. </item> </list>
- <p>
- Also, ~tp has been changed back to ~p unless it is
- somehow likely that the argument includes strings. It is
- not obvious that this is the correct thing to do, but
- some decission had to be taken...</p>
- <p>
- Own Id: OTP-10780</p>
- </item>
- <item>
- <p>
- Using the force_stop flag/option to interrupt a test run
- caused a crash in Common Test. This problem has been
- solved.</p>
- <p>
- Own Id: OTP-10832</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.6</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Line numbering of erlang files that were not correctly
- indented could be wrong after coverting to html with
- erl2html2:convert/[2,3] (the source code pointed to from
- the test case). This has been corrected.</p>
- <p>
- Also, there are now link targets for each line and not
- only for each 10th line, and link targets for functions
- now include the arity and not only the function name
- (e.g. func/1 has a link target "func-1").</p>
- <p>
- Own Id: OTP-9710 Aux Id: seq11945, kunagi-201 [112] </p>
- </item>
- <item>
- <p>
- Severe errors detected by <c>test_server</c> (e.g. if log
- files directories cannot be created) will now be reported
- to <c>common_test</c> and noted in the <c>common_test</c>
- logs.</p>
- <p>
- Own Id: OTP-9769 Aux Id: kunagi-202 [113] </p>
- </item>
- <item>
- <p>
- The earlier undocumented cross cover feature for
- accumulating cover data over multiple tests has now been
- fixed and documented.</p>
- <p>
- Own Id: OTP-9870 Aux Id: kunagi-206 [117] </p>
- </item>
- <item>
- <p>
- If the test suite itself was included in code coverage
- analysis, then the test_server would not manage to set
- data_dir correctly for the test. This has been corrected.</p>
- <p>
- Own Id: OTP-9956 Aux Id: kunagi-207 [118] </p>
- </item>
- <item>
- <p>
- Any call to test_server:break/1 should cancel all active
- timetramps. However, in some cases
- Suite:end_per_testcase/2 is executed on a different
- process than the test case itself, and if
- test_server:break/1 was called from there, the timetraps
- were not cancelled. This has been corrected.</p>
- <p>
- Own Id: OTP-10046 Aux Id: kunagi-174 [85] </p>
- </item>
- <item>
- <p>When a test case failed because of a timetrap time
- out, the <c>Config</c> data for the case was lost in the
- following call to <c>end_per_testcase/2</c>, and also in
- calls to the CT Hook function
- <c>post_end_per_testcase/4</c>. This problem has been
- solved and the <c>Config</c> data is now correctly passed
- to the above functions after a timetrap timeout
- failure.</p>
- <p>
- Own Id: OTP-10070 Aux Id: kunagi-175 [86] </p>
- </item>
- <item>
- <p>In test_server, the same process would supervise the
- currently running test case and be group leader (and IO
- server) for the test case. Furthermore, when running
- parallel test cases, new temporary supervisor/group
- leader processes were spawned and the process that was
- group leader for sequential test cases would not be
- active. That would lead to several problems:</p>
- <p>* Processes started by init_per_suite will inherit the
- group leader of the init_per_suite process (and that
- group leader would not process IO requests when parallel
- test cases was running). If later a parallel test case
- caused such a processto print using (for example)
- io:format/2, the calling would hang.</p>
- <p>* Similarly, if a process was spawned from a parallel
- test case, it would inherit the temporary group leader
- for that parallel test case. If that spawned process
- later - when the group of parallel tests have finished -
- attempted to print something, its group leader would be
- dead and there would be <c>badarg</c> exception.</p>
- <p>Those problems have been solved by having group
- leaders separate from the processes that supervises the
- test cases, and keeping temporary group leader process
- for parallel test cases alive until no more process in
- the system use them as group leaders.</p>
- <p>Also, a new <c>unexpected_io.log</c> log file
- (reachable from the summary page of each test suite) has
- been introduced. All unexpected IO will be printed into
- it(for example, IO to a group leader for a parallel test
- case that has finished).</p>
- <p>
- Own Id: OTP-10101 Aux Id: OTP-10125 </p>
- </item>
- <item>
- <p>
- The stability of <c>common_test</c> and
- <c>test_server</c> when running test cases in parallel
- has been improved.</p>
- <p>
- Own Id: OTP-10480 Aux Id: kunagi-318 [229] </p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Added a general framework for executing benchmarks of
- Erlang/OTP. Benchmarks for the Erlang VM and mnesia have
- been incorporated in the framework. </p>
- <p>
- For details about how to add more benchmarks see
- $ERL_TOP/HOWTO/BENCHMARKS.md in the source distribution.</p>
- <p>
- Own Id: OTP-10156</p>
- </item>
- <item>
- <p>
- Update common test modules to handle Unicode:</p> <list>
- <item> Use UTF-8 encoding for all HTML files, except the
- HTML version of the test suite generated with
- erl2html2:convert, which will have the same encoding as
- the original test suite (.erl) file. </item> <item>
- Encode link targets in HTML files with
- test_server_ctrl:uri_encode/1. </item> <item> Use unicode
- modifier 't' with ~s when appropriate. </item> <item> Use
- unicode:characters_to_list and
- unicode:characters_to_binary for conversion between
- binaries and strings instead of binary_to_list and
- list_to_binary. </item> </list>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.5.3</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- test_server_h will now recognize info_reports written by
- ct connection handlers (according to the description in
- cth_conn_log) and ignore them as they will be completely
- handled by by ct_conn_log_h.</p>
- <p>
- Earlier test_server_h would print a tag (testcase name)
- before forwarding the report to error_logger_tty_h. This
- would cause lots of tags in the log with no info report
- following (since error_logger_tty_h did not handle them).</p>
- <p>
- Own Id: OTP-10571</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Known Bugs and Problems</title>
- <list>
- <item>
- <p>
- Restore Config data if lost when test case fails.</p>
- <p>
- Own Id: OTP-10070 Aux Id: kunagi-175 [86] </p>
- </item>
- <item>
- <p>
- IO server error in test_server.</p>
- <p>
- Own Id: OTP-10125 Aux Id: OTP-10101, kunagi-177 [88] </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.5.2</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- The documentation has been updated with the latest
- changes for the test_server_ctrl:report/2 function.</p>
- <p>
- Own Id: OTP-10086 Aux Id: seq12066 </p>
- </item>
- <item>
- <p>
- The ct:get_status/0 function failed to report status if a
- parallel test case group was running at the time of the
- call. This has been fixed and the return value for the
- function has been updated. Please see the ct reference
- manual for details.</p>
- <p>
- Own Id: OTP-10172</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- It is now possible to sort the HTML tables by clicking on
- the header elements. In order to reset a sorted table,
- the browser window should simply be refreshed. This
- feature requires that the browser supports javascript,
- and has javascript execution enabled. If the 'ct_run
- -basic_html' flag is used, no javascript code is included
- in the generated HTML code.</p>
- <p>
- Own Id: OTP-9896 Aux Id: seq12034, OTP-9835 </p>
- </item>
- <item>
- <p>
- Verbosity levels for log printouts has been added. This
- makes it possible to specify preferred verbosity for
- different categories of log printouts, as well as general
- printouts (such as standard IO), to allow control over
- which strings get printed and which get ignored. New
- versions of the Common Test logging functions, ct:log,
- ct:pal and ct:print, have been introduced, with a new
- Importance argument added. The Importance value is
- compared to the verbosity level at runtime. More
- information can be found in the chapter about Logging in
- the Common Test User's Guide.</p>
- <p>
- Own Id: OTP-10067 Aux Id: seq12050 </p>
- </item>
- <item>
- <p>
- The Erlang/OTP test runner ts has been extended to allow
- cross compilation of test suites. To cross compile the
- test suites first follow the normal cross compilation
- procedures and release the tests on the build host. Then
- install ts using an xcomp specification file and compile
- test suites using ts:compile_testcases/0. For more
- details see $ERL_TOP/xcomp/README.md.</p>
- <p>
- Own Id: OTP-10074</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.5.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- After a test case timeout or abortion, the
- end_per_testcase function executes on a new dedicated
- process. The group leader for this process should be set
- to the IO server for the test case, which was not done
- properly. The result of this error was that no warnings
- about end_per_testcase failing or timing out were ever
- printed in the test case log. Also, help functions such
- as e.g. test_server:stop_node/1, attempting to
- synchronize with the IO server, would hang. The fault has
- been corrected.</p>
- <p>
- Own Id: OTP-9666</p>
- </item>
- <item>
- <p>
- A deadlock situation could occur if Common Test is
- forwarding error_handler printouts to Test Server at the
- same time a new test case is starting. This error has
- been fixed.</p>
- <p>
- Own Id: OTP-9894</p>
- </item>
- <item>
- <p>
- When a test case was killed because of a timetrap
- timeout, the current location (suite, case and line) was
- not printed correctly in the log files. This has been
- corrected.</p>
- <p>
- Own Id: OTP-9930 Aux Id: seq12002 </p>
- </item>
- <item>
- <p>
- Test Server and Common Test would add new error handlers
- with each test run and fail to remove previously added
- ones. In the case of Test Server, this would only happen
- if SASL was not running on the test node. This has been
- fixed.</p>
- <p>
- Own Id: OTP-9941 Aux Id: seq12009 </p>
- </item>
- <item>
- <p>
- If a test case process was terminated due to an exit
- signal from a linked process, Test Server failed to
- report the correct name of the suite and case to the
- framework. This has been corrected.</p>
- <p>
- Own Id: OTP-9958 Aux Id: OTP-9855 </p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- A new optional feature has been introduced that enables
- Common Test to generate priv_dir directory names that are
- unique for each test case or config function. The name of
- the option/flag is 'create_priv_dir' and it can be set to
- value 'auto_per_run' (which is the default, existing,
- behaviour), or 'auto_per_tc' or 'manual_per_tc'. If
- 'auto_per_tc' is used, Test Server creates a dedicated
- priv_dir automatically for each test case (which can be
- very expensive in case of many and/or repeated cases). If
- 'manual_per_tc' is used, the user needs to create the
- priv_dir explicitly by calling the new function
- ct:make_priv_dir/0.</p>
- <p>
- Own Id: OTP-9659 Aux Id: seq11930 </p>
- </item>
- <item>
- <p>
- A column for test case group name has been added to the
- suite overview HTML log file.</p>
- <p>
- Own Id: OTP-9730 Aux Id: seq11952 </p>
- </item>
- <item>
- <p>
- It is now possible to use the post_end_per_testcase CT
- hook function to print a comment for a test case in the
- overview log file, even if the test case gets killed by a
- timetrap or unknown exit signal, or if the
- end_per_testcase function times out.</p>
- <p>
- Own Id: OTP-9855 Aux Id: seq11979 </p>
- </item>
- <item>
- <p>
- Common Test will now print error information (with a time
- stamp) in the test case log file immediately when a test
- case fails. This makes it easier to see when, in time,
- the fault actually occured, and aid the job of locating
- relevant trace and debug printouts in the log.</p>
- <p>
- Own Id: OTP-9904 Aux Id: seq11985, OTP-9900 </p>
- </item>
- <item>
- <p>
- Test Server has been modified to check the SASL
- errlog_type parameter when receiving an error logger
- event, so that it doesn't print reports of type that the
- user has disabled.</p>
- <p>
- Own Id: OTP-9955 Aux Id: seq12013 </p>
- </item>
- <item>
- <p>
- If an application cannot be found by ts it is
- automatically skipped when testing.</p>
- <p>
- Own Id: OTP-9971</p>
- </item>
- <item>
- <p>
- By specifying a user defined function ({M,F,A} or fun) as
- timetrap value, either by means of an info function or by
- calling ct:timetrap/1, it is now possible to set a
- timetrap that will be triggered when the user function
- returns.</p>
- <p>
- Own Id: OTP-9988 Aux Id: OTP-9501, seq11894 </p>
- </item>
- <item>
- <p>
- If the optional configuration functions init_per_suite/1
- and end_per_suite/1 are not implemented in the test
- suite, local Common Test versions of these functions are
- called instead, and will be displayed in the overview log
- file. Any printouts made by the pre- or
- post_init_per_suite and pre- or post_end_per_suite hook
- functions are saved in the log files for these functions.</p>
- <p>
- Own Id: OTP-9992</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.5</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- The test case group info function has been implemented in
- Common Test. Before execution of a test case group, a
- call is now made to <c>TestSuite:group(GroupName)</c>.
- The function returns a list of test properties, e.g. to
- specify timetrap values, require configuration data, etc
- (analogue to the test suite- and test case info
- function). The scope of the properties set by
- <c>group(GroupName)</c> is all test cases and sub-groups
- of group <c>GroupName</c>.</p>
- <p>
- Own Id: OTP-9235</p>
- </item>
- <item>
- <p>
- The look of the HTML log files generated by Common Test
- and Test Server has been improved (and made easier to
- customize) by means of a CSS file.</p>
- <p>
- Own Id: OTP-9706</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Known Bugs and Problems</title>
- <list>
- <item>
- <p>
- Fix problems in CT/TS due to line numbers in exceptions.</p>
- <p>
- Own Id: OTP-9203</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.4.5</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- An error in how comments are colored in the test suite
- overview html log file has been corrected. As result, a
- new framework callback function, format_comment/1, has
- been introduced.</p>
- <p>
- Own Id: OTP-9237</p>
- </item>
- <item>
- <p>
- Test Server did not release SASL TTY handlers
- (sasl_report_tty_h and error_logger_tty_h) properly after
- each test run. This error has been fixed.</p>
- <p>
- Own Id: OTP-9311</p>
- </item>
- <item>
- <p>
- Automatically generated init- and end-configuration
- functions for test case groups caused incorrect execution
- order of test cases. This has been corrected.</p>
- <p>
- Own Id: OTP-9369</p>
- </item>
- <item>
- <p>
- If ct:log/2 was called with bad arguments, this could
- cause the Common Test IO handling process to crash. This
- fault has been corrected.</p>
- <p>
- Own Id: OTP-9371 Aux Id: OTP-8933 </p>
- </item>
- <item>
- <p>
- A bug has been fixed that made Test Server call the
- end_tc/3 framework function with an incorrect module name
- as first argument.</p>
- <p>
- Own Id: OTP-9379 Aux Id: seq11863 </p>
- </item>
- <item>
- <p>
- If end_per_testcase caused a timetrap timeout, the actual
- test case status was discarded and the test case logged
- as successful (even if the case had actually failed
- before the call to end_per_testcase). This fault has been
- fixed.</p>
- <p>
- Own Id: OTP-9397</p>
- </item>
- <item>
- <p>
- If a timetrap timeout occured during execution of of a
- function in a lib module (i.e. a function called directly
- or indirectly from a test case), the Suite argument in
- the end_tc/3 framework callback function would not
- correctly contain the name of the test suite, but the lib
- module. (This would only happen if the lib module was
- compiled with ct.hrl included). This error has been
- solved.</p>
- <p>
- Own Id: OTP-9398</p>
- </item>
- <item>
- <p>
- Add a proplist() type</p>
- <p>
- Recently I was adding specs to an API and found that
- there is no canonical proplist() type defined. (Thanks to
- Ryan Zezeski)</p>
- <p>
- Own Id: OTP-9499</p>
- </item>
- <item>
- <p> XML files have been corrected. </p>
- <p>
- Own Id: OTP-9550 Aux Id: OTP-9541 </p>
- </item>
- <item>
- <p>
- If a test suite would start with a test case group
- defined without the init_per_group/2 and end_per_group/2
- function, init_per_suite/1 would not execute initially
- and logging of the test run would fail. This error has
- been fixed.</p>
- <p>
- Own Id: OTP-9584</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- A new option, 'logopts', has been introduced, to make it
- possible to modify some aspects of the logging behaviour
- in Common Test (or Test Server). For example, whenever an
- io printout is made, test_server adds newline (\n) to the
- end of the output string. This may not always be a
- preferred action and can therefore be disabled by means
- of "ct_run ... -logopts no_nl" (or ct:run_test([...,
- {logopts,[no_nl]}])). A new framework callback function,
- get_logopts/0, has been introduced (see the ct_framework
- module for details).</p>
- <p>
- Own Id: OTP-9372 Aux Id: OTP-9396 </p>
- </item>
- <item>
- <p>
- A new option, 'logopts', has been introduced, to make it
- possible to modify some aspects of the logging behaviour
- in Common Test (or Test Server). For example, if the html
- version of the test suite source code should not be
- generated during the test run (and consequently be
- unavailable in the log file system), the feature may be
- disabled by means of "ct_run ... -logopts no_src" (or
- ct:run_test([..., {logopts,[no_src]}])). A new framework
- callback function, get_logopts/0, has been introduced
- (see the ct_framework module for details).</p>
- <p>
- Own Id: OTP-9396 Aux Id: seq11869, OTP-9372 </p>
- </item>
- <item>
- <p>
- It is now possible to use a tuple {M,F,A}, or a fun, as
- timetrap specification in the suite info function or test
- case info functions. The function must return a valid
- timeout value, as documented in the common_test man page
- and in the User's Guide.</p>
- <p>
- Own Id: OTP-9501 Aux Id: seq11894 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.4.4</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- It was previously not possible to use timetrap value
- 'infinity' with ct:timetrap/1. This has been fixed.</p>
- <p>
- Own Id: OTP-9159</p>
- </item>
- <item>
- <p>
- A bug that made it impossible to cancel the previous
- timetrap when calling ct:timetrap/1 has been corrected.</p>
- <p>
- Own Id: OTP-9233 Aux Id: OTP-9159 </p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- When running tests with auto-compilation disabled, Common
- Test could only display the test suite source code on
- html format in the test case log if the source file was
- located in the same directory as the pre-compiled suite.
- This has been modified so that Common Test now tries to
- locate the source file by means of the test suite module
- info (Suite:module_info/1). As a result, a suite may now
- be compiled to a different output directory (e.g.
- $MYTEST/bin) than the source code directory (e.g.
- $MYTEST/src), without the source-code-to-html generation
- being affected.</p>
- <p>
- Own Id: OTP-9138</p>
- </item>
- <item>
- <p>
- It is now possible to return a tuple {fail,Reason} from
- init_per_testcase/2. The result is that the associated
- test case gets logged as failed without ever executing.</p>
- <p>
- Own Id: OTP-9160 Aux Id: seq11502 </p>
- </item>
- <item>
- <p>
- Added DragonflyBSD check in test_server configure.</p>
- <p>
- Own Id: OTP-9249</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.4.3</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Updated the ts*.config files to contain information
- relevant to testing Erlang/OTP in an open source
- environment.</p>
- <p>
- Own Id: OTP-9017</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Alpha release of Common Test Hooks (CTH). CTHs allow the
- users of common test to abtract out common behaviours
- from test suites in a much more elegant and flexible way
- than was possible before. Note that the addition of this
- feature may introduce minor changes in the undocumented
- behaviour of the interface inbetween common_test and
- test_server.</p>
- <p>
- *** POTENTIAL INCOMPATIBILITY ***</p>
- <p>
- Own Id: OTP-8851</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.4.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>Miscellaneous updates</p>
- <p>
- Own Id: OTP-8976</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.4.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Returning {return_group_result,failed} from end_per_group
- in a group that is part of a sequence, did not cause the
- proceeding cases (or groups) to get skipped. This has
- been fixed.</p>
- <p>
- Own Id: OTP-8753 Aux Id: seq11644 </p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Common Test has been updated to handle start options and
- test specification terms for test case groups (and test
- cases in groups). Also, an option named 'label', has been
- added that associates the test run with a name that
- Common Test prints in the overview HTML logs.</p>
- <p>
- Own Id: OTP-8725 Aux Id: OTP-8727 </p>
- </item>
- <item>
- <p>
- It is now possible to skip all tests in a suite, or a
- group, by returning {fail,Reason} from the end_tc/5
- framework function for init_per_suite, or init_per_group.</p>
- <p>
- Own Id: OTP-8805 Aux Id: seq11664 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.4</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Returning {fail,Reason} from the framework end_tc
- function was not handled properly by Test Server for all
- test suite functions.</p>
- <p>
- Own Id: OTP-8492 Aux Id: seq11502 </p>
- </item>
- <item>
- <p>
- If the framework end_tc function would hang and get
- aborted by Test Server, there was no indication of
- failure in the logs. This has been fixed.</p>
- <p>
- Own Id: OTP-8682 Aux Id: seq11504 </p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- It is now possible for the Test Server framework end_tc
- function to change the status of the test case from ok or
- auto-skipped to failed by returning {fail,Reason}.</p>
- <p>
- Own Id: OTP-8495 Aux Id: seq11502 </p>
- </item>
- <item>
- <p>
- Test Server will now call the end_per_testcase/2 function
- even if the test case has been terminated explicitly
- (with abort_current_testcase/1), or after a timetrap
- timeout. Under these circumstances the return value of
- end_per_testcase is completely ignored. Therefore the
- function will not be able to change the reason for test
- case termination by returning {fail,Reason}, nor will it
- be able to save data with {save_config,Data}.</p>
- <p>
- Own Id: OTP-8500 Aux Id: seq11521 </p>
- </item>
- <item>
- <p>
- Previously, a repeat property of a test case group
- specified the number of times the group should be
- repeated after the main test run. I.e. {repeat,N} would
- case the group to execute 1+N times. To be consistent
- with the behaviour of the run_test repeat option, this
- has been changed. N now specifies the absolute number of
- executions instead.</p>
- <p>
- Own Id: OTP-8689 Aux Id: seq11502 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.3.6</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- The Test Server parse transform did not handle bit string
- comprehensions. This has been fixed.</p>
- <p>
- Own Id: OTP-8458 Aux Id: OTP-8311 </p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- The tc_status value in the Config list for a test case
- that has failed because of a timetrap timeout, has
- changed from {tc_status,timeout} to
- {tc_status,timetrap_timeout}.</p>
- <p>
- Own Id: OTP-8302</p>
- </item>
- <item>
- <p>The documentation is now possible to build in an open
- source environment after a number of bugs are fixed and
- some features are added in the documentation build
- process. </p>
- <p>- The arity calculation is updated.</p>
- <p>- The module prefix used in the function names for
- bif's are removed in the generated links so the links
- will look like
- "http://www.erlang.org/doc/man/erlang.html#append_element-2"
- instead of
- "http://www.erlang.org/doc/man/erlang.html#erlang:append_element-2".</p>
- <p>- Enhanced the menu positioning in the html
- documentation when a new page is loaded.</p>
- <p>- A number of corrections in the generation of man
- pages (thanks to Sergei Golovan)</p>
- <p>- The legal notice is taken from the xml book file so
- OTP's build process can be used for non OTP
- applications.</p>
- <p>
- Own Id: OTP-8343</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.3.5</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- If the init_per_testcase/2 function fails, the test case
- now gets marked and counted as auto skipped, not user
- skipped (which would previously happen).</p>
- <p>
- Own Id: OTP-8289</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- The documentation is now built with open source tools
- (xsltproc and fop) that exists on most platforms. One
- visible change is that the frames are removed.</p>
- <p>
- Own Id: OTP-8201</p>
- </item>
- <item>
- <p>
- It is now possible to fail a test case from the
- end_per_testcase/2 function, by returning {fail,Reason}.</p>
- <p>
- Own Id: OTP-8284</p>
- </item>
- <item>
- <p>
- It is now possible to fail a test case by having the
- end_tc/3 framework function return {fail,Reason} for the
- test case.</p>
- <p>
- Own Id: OTP-8285</p>
- </item>
- <item>
- <p>
- The test_server framework API (e.g. the end_tc/3
- function) has been modified. See the test_server_ctrl
- documentation for details.</p>
- <p>
- Own Id: OTP-8286 Aux Id: OTP-8285, OTP-8287 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.3.4</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- When running a suite starting with a test case group,
- Test Server crashed if init_per_suite/1 exited or
- returned skip. This has been fixed.</p>
- <p>
- Own Id: OTP-8105 Aux Id: OTP-8089 </p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Various updates and fixes in Common Test and Test Server.</p>
- <p>
- Own Id: OTP-8045 Aux Id: OTP-8089,OTP-8105,OTP-8163 </p>
- </item>
- <item>
- <p>
- Errors in coverage data collection and analysis were
- difficult to detect. The logging has been improved so
- that more information about e.g. imported and missing
- modules is printed to the html log files.</p>
- <p>
- Own Id: OTP-8163 Aux Id: seq11374 </p>
- </item>
- <item>
- <p>
- The Common Test HTML overview pages have been improved.
- It is now possible to see if a test case has been skipped
- explicitly or because a configuration function has
- failed. Also, the history page (all_runs.html) now has
- scrolling text displaying the test names. The old format
- (showing names as a truncated string) can still be
- generated by means of the flag/option 'basic_html'.</p>
- <p>
- Own Id: OTP-8177</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.3.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Various corrections and improvements of Common Test and
- Test Server.</p>
- <p>
- Own Id: OTP-7981</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.3.1</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Minor updates and corrections.</p>
- <p>
- Own Id: OTP-7897</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.3</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- The conf case in Test Server has been extended with
- properties that make it possible to execute test cases in
- parallel, in sequence and in shuffled order. It is now
- also possible to repeat test cases according to different
- criterias. The properties can be combined, making it
- possible to e.g. repeat a conf case a certain number of
- times and execute the test cases in different (random)
- order every time. The properties are specified in a list
- in the conf case definition: {conf, Properties, InitCase,
- TestCases, EndCase}. The available properties are:
- parallel, sequence, shuffle, repeat, repeat_until_all_ok,
- repeat_until_any_ok, repeat_until_any_fail,
- repeat_until_all_fail.</p>
- <p>
- Own Id: OTP-7511 Aux Id: OTP-7839 </p>
- </item>
- <item>
- <p>The test server starts Cover on nodes of the same
- version as the test server itself only.</p>
- <p>
- Own Id: OTP-7699</p>
- </item>
- <item>
- <p>
- The Erlang mode for Emacs has been updated with new and
- modified skeletons for Common Test and TS. Syntax for
- test case groups in Common Test (and conf cases with
- properties in TS) has been added and a new minimal Common
- Test suite skeleton has been introduced.</p>
- <p>
- Own Id: OTP-7856</p>
- </item>
- </list>
- </section>
-
-</section>
-<section><title>Test_Server 3.2.4.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- The step functionality in Common Test (based on
- interaction with Debugger) was broken. This has been
- fixed, and some new step features have also been added.
- Please see the Common Test User's Guide for details.</p>
- <p>
- Own Id: OTP-7800 Aux Id: seq11106 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.2.4</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Miscellaneous updates.</p>
- <p>
- Own Id: OTP-7527</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.2.3</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- When a testcase terminated due to a timetrap, io sent to
- the group leader from framework:end_tc/3 (using
- ct:pal/2/3 or ct:log/2/3) would cause deadlock. This has
- been fixed.</p>
- <p>
- Own Id: OTP-7447 Aux Id: seq11010 </p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Various updates and improvements, plus some minor bug
- fixes, have been implemented in Common Test and Test
- Server.</p>
- <p>
- Own Id: OTP-7112</p>
- </item>
- <item>
- <p>
- It is now possible, by means of the new function
- ct:abort_current_testcase/1 or
- test_server_ctrl:abort_current_testcase/1, to abort the
- currently executing test case.</p>
- <p>
- Own Id: OTP-7518 Aux Id: OTP-7112 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.2.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p><c>erlang:system_info/1</c> now accepts the
- <c>logical_processors</c>, and <c>debug_compiled</c>
- arguments. For more info see the, <c>erlang(3)</c>
- documentation.</p> <p>The scale factor returned by
- <c>test_server:timetrap_scale_factor/0</c> is now also
- effected if the emulator uses a larger amount of
- scheduler threads than the amount of logical processors
- on the system. </p>
- <p>
- Own Id: OTP-7175</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.2.1</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- When init_per_suite or end_per_suite terminated due to
- runtime failure, test_server failed to format the line
- number information properly and crashed. This error has
- now been fixed.</p>
- <p>
- Own Id: OTP-7091</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Test_Server 3.2.0</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Test Server is a portable test server for automated
- application testing. The server can run test suites on
- local or remote targets and log progress and results to
- HTML pages. The main purpose of Test Server is to act as
- engine inside customized test tools. A callback interface
- for such framework applications is provided.</p>
- <p>
- Own Id: OTP-6989</p>
- </item>
- </list>
- </section>
-
-</section>
-
-</chapter>
-
diff --git a/lib/test_server/doc/src/notes_history.xml b/lib/test_server/doc/src/notes_history.xml
deleted file mode 100644
index ca7880d74f..0000000000
--- a/lib/test_server/doc/src/notes_history.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2006</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Test Server Release Notes History</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
-
- <section>
- <title>Test Server 3.1.1</title>
-
- <section>
- <title>Improvements and new features</title>
- <list type="bulleted">
- <item>
- <p>Added functions <c>test_server:break/1</c> and
- <c>test_server:continue/0</c> for semiautomatic testing.</p>
- <p><c>test_server:timetrap/1</c> can now also take
- <c>{hours,H} | {minutes,M | {seconds,S}</c>.</p>
- <p>Added function
- <c>test_server_ctrl:multiply_timetraps/1</c>,
- <c>test_server_ctrl:add_case/3</c>,
- <c>test_server_ctrl:add_cases/2/3</c>.</p>
- <p>Added test suite functions <c>init_per_suite/1</c> and
- <c>end_per_suite/1</c>.</p>
- <p><c>fin_per_testcase/2</c> is changed to
- <c>end_per_testcase/2</c>. <c>fin_per_testcase</c> is kept
- for backwards compatibility.</p>
- <p>Added support for writing own test server frameworks.
- Callback functions <c>init_tc/1</c>, <c>end_tc/3</c>,
- <c>get_suite/2</c>, <c>report/2</c>, <c>warn/1</c>.</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Test Server 3.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Added the options <c>cover</c> and <c>cover_details</c>
- to <c>ts:run</c>. When one of these options is used,
- the tested application will be cover compiled
- before the test is run. The cover compiled code will also
- be loaded on all slave or peer nodes started with
- <c>test_server:start_node</c>. When the test is completed
- coverage data from all nodes is collected and merged, and
- presented in the coverage log to which there will be a link
- from the test suite result page (i.e. the one with the
- heading "Test suite ... results").</p>
- <p>The <c>cover_details</c> option will do
- <c>cover:analyse_to_file</c> for each cover compiled module,
- while the <c>cover</c> option only will produce a list of
- modules and the number of covered/uncovered lines in each
- module.</p>
- <p>To make it possible to run all test from a script (like in
- the OTP daily builds), the following is added:
- <c>ts:run([all_tests | Options])</c>.</p>
- <p>This means that e.g. the following is possible:
- <c>erl -s ts run all_tests batch cover</c>.</p>
- <p>Note that it is also possible to run tests with cover even
- if you don't use <c>ts</c>.
- See <c>test_server_ctrl:cover/2/3</c>.</p>
- <p>Own Id: OTP-4703</p>
- </item>
- <item>
- <p>Removed module <c>ts_save.erl</c> and function
- <c>ts:save/0/1</c><em>(incompatible)</em>.</p>
- <p>Added config variable <c>ipv6_hosts</c> to
- <c>ts:install/1</c> and test spec file.</p>
- <p>No longer removing duplicates of test cases from test spec
- <em>(incompatible)</em>.</p>
- <p>Added function <c>test_server:run_on_shielded_node/2</c>.</p>
- <p>Creation of html files for test suite source does no longer
- crash if suite contains more than 9999 lines of code.</p>
- <p>Added functionality for cross cover compilation,
- i.e. collection of cover data from all tests.</p>
- <p>Multiplying timetrap times with 10 when running with cover.</p>
- <p>Added <c>ts:r/3</c> for running tests with cover.</p>
- <p>*** POTENTIAL INCOMPATIBILITY ***</p>
- <p>Own Id: OTP-5040</p>
- </item>
- </list>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/test_server/doc/src/part.xml b/lib/test_server/doc/src/part.xml
deleted file mode 100644
index 685ed16a94..0000000000
--- a/lib/test_server/doc/src/part.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2002</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Test Server User's Guide</title>
- <prepared></prepared>
- <docno></docno>
- <date>2002-07-11</date>
- <rev></rev>
- </header>
- <description>
- <p><em>Test Server</em> is a portable test server for
- automated application testing. The server can run test suites
- and log progress and results to HTML
- pages. The main purpose of Test Server is to act as engine
- inside customized test tools. A callback interface for
- such framework applications is provided.</p>
- </description>
- <xi:include href="basics_chapter.xml"/>
- <xi:include href="test_spec_chapter.xml"/>
- <xi:include href="write_test_chapter.xml"/>
- <xi:include href="run_test_chapter.xml"/>
- <xi:include href="write_framework_chapter.xml"/>
- <xi:include href="example_chapter.xml"/>
-</part>
-
diff --git a/lib/test_server/doc/src/part_notes.xml b/lib/test_server/doc/src/part_notes.xml
deleted file mode 100644
index 8cb9b6c591..0000000000
--- a/lib/test_server/doc/src/part_notes.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2004</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Test Server Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The <em>Test Server</em> is a portable test server for
- application testing. The test server can run automatic test suites
- and log progress and results to HTML
- pages. It also provides some support for test suite authors.</p>
- <p>For information about older versions, see
- <url href="part_notes_history_frame.html">Release Notes History</url>.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/test_server/doc/src/part_notes_history.xml b/lib/test_server/doc/src/part_notes_history.xml
deleted file mode 100644
index 468b5aa8ba..0000000000
--- a/lib/test_server/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2006</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Test Server Release Notes History</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The <em>Test Server</em> is a portable test server for
- application testing. The test server can run automatic test suites
- and log progress and results to HTML
- pages. It also provides some support for test suite authors.</p>
- </description>
- <include file="notes_history"></include>
-</part>
-
diff --git a/lib/test_server/doc/src/ref_man.xml b/lib/test_server/doc/src/ref_man.xml
deleted file mode 100644
index 1b06d9750b..0000000000
--- a/lib/test_server/doc/src/ref_man.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE application SYSTEM "application.dtd">
-
-<application xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2002</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Test Server Reference Manual</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>ref_man.xml</file>
- </header>
- <description>
- <p><em>Test Server</em> is a portable test server for
- automated application testing. The server can run test suites
- and log progress and results to HTML
- pages. The main purpose of Test Server is to act as engine
- inside customized test tools. A callback interface for
- such framework applications is provided.</p>
- </description>
- <xi:include href="test_server_app.xml"/>
- <xi:include href="test_server_ctrl.xml"/>
- <xi:include href="test_server.xml"/>
-</application>
-
diff --git a/lib/test_server/doc/src/run_test_chapter.xml b/lib/test_server/doc/src/run_test_chapter.xml
deleted file mode 100644
index cb5b29c993..0000000000
--- a/lib/test_server/doc/src/run_test_chapter.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2002</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Running Test Suites</title>
- <prepared>Siri Hansen</prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>run_test_chapter.xml</file>
- </header>
-
- <section>
- <title>Using the test server controller</title>
- <p>The test server controller provides a low level interface to
- all the Test Server functionality. It is possible to use this
- interface directly, but it is recommended to use a framework
- such as <em>Common Test</em> instead. If no existing framework
- suits your needs, you could of course build your own
- on top of the test server controller. Some information about how
- to do this can be found in the section named "Writing you own
- test server framework" in the Test Server User's Guide.
- </p>
- <p>For information about using the controller directly, please see
- all available functions in the reference manual for
- <c>test_server_ctrl</c>.
- </p>
- </section>
-</chapter>
-
diff --git a/lib/test_server/doc/src/test_server.xml b/lib/test_server/doc/src/test_server.xml
deleted file mode 100644
index 96ff6de3ba..0000000000
--- a/lib/test_server/doc/src/test_server.xml
+++ /dev/null
@@ -1,853 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2007</year>
- <year>2013</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- 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.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>test_server</title>
- <prepared>Siri Hansen</prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date></date>
- <rev></rev>
- <file>test_server_ref.sgml</file>
- </header>
- <module>test_server</module>
- <modulesummary>This module provides support for test suite authors.</modulesummary>
- <description>
- <p>The <c>test_server</c> module aids the test suite author by providing
- various support functions. The supported functionality includes:
- </p>
- <list type="bulleted">
- <item>Logging and timestamping
- </item>
- <item>Capturing output to stdout
- </item>
- <item>Retrieving and flushing the message queue of a process
- </item>
- <item>Watchdog timers, process sleep, time measurement and unit
- conversion
- </item>
- <item>Private scratch directory for all test suites
- </item>
- <item>Start and stop of slave- or peer nodes</item>
- </list>
- <p>For more information on how to write test cases and for
- examples, please see the Test Server User's Guide.
- </p>
- </description>
-
- <section>
- <title>TEST SUITE SUPPORT FUNCTIONS</title>
- <p>The following functions are supposed to be used inside a test
- suite.
- </p>
- </section>
- <funcs>
- <func>
- <name>os_type() -> OSType</name>
- <fsummary>Returns the OS type of the target node</fsummary>
- <type>
- <v>OSType = term()</v>
- <d>This is the same as returned from <c>os:type/0</c></d>
- </type>
- <desc>
- <p>This function is equivalent to <c>os:type/0</c>. It is kept
- for backwards compatibility.</p>
- </desc>
- </func>
- <func>
- <name>fail()</name>
- <name>fail(Reason)</name>
- <fsummary>Makes the test case fail.</fsummary>
- <type>
- <v>Reason = term()</v>
- <d>The reason why the test case failed.</d>
- </type>
- <desc>
- <p>This will make the test suite fail with a given reason, or
- with <c>suite_failed</c> if no reason was given. Use this
- function if you want to terminate a test case, as this will
- make it easier to read the log- and HTML files. <c>Reason</c>
- will appear in the comment field in the HTML log.</p>
- </desc>
- </func>
- <func>
- <name>timetrap(Timout) -> Handle</name>
- <fsummary></fsummary>
- <type>
- <v>Timeout = integer() | {hours,H} | {minutes,M} | {seconds,S}</v>
- <v>H = M = S = integer()</v>
- <v>Pid = pid()</v>
- <d>The process that is to be timetrapped (<c>self()</c>by default)</d>
- </type>
- <desc>
- <p>Sets up a time trap for the current process. An expired
- timetrap kills the process with reason
- <c>timetrap_timeout</c>. The returned handle is to be given
- as argument to <c>timetrap_cancel</c> before the timetrap
- expires. If <c>Timeout</c> is an integer, it is expected to
- be milliseconds.</p>
- <note>
- <p>If the current process is trapping exits, it will not be killed
- by the exit signal with reason <c>timetrap_timeout</c>.
- If this happens, the process will be sent an exit signal
- with reason <c>kill</c> 10 seconds later which will kill the
- process. Information about the timetrap timeout will in
- this case not be found in the test logs. However, the
- error_logger will be sent a warning.</p>
- </note>
- </desc>
- </func>
- <func>
- <name>timetrap_cancel(Handle) -> ok</name>
- <fsummary>Cancels a timetrap.</fsummary>
- <type>
- <v>Handle = term()</v>
- <d>Handle returned from <c>timetrap</c></d>
- </type>
- <desc>
- <p>This function cancels a timetrap. This must be done before
- the timetrap expires.</p>
- </desc>
- </func>
- <func>
- <name>timetrap_scale_factor() -> ScaleFactor</name>
- <fsummary>Returns the scale factor for timeouts.</fsummary>
- <type>
- <v>ScaleFactor = integer()</v>
- </type>
- <desc>
- <p>This function returns the scale factor by which all timetraps
- are scaled. It is normally 1, but can be greater than 1 if
- the test_server is running <c>cover</c>, using a larger amount of
- scheduler threads than the amount of logical processors on the
- system, running under purify, valgrind or in a debug-compiled
- emulator. The scale factor can be used if you need to scale you
- own timeouts in test cases with same factor as the test_server
- uses.</p>
- </desc>
- </func>
- <func>
- <name>sleep(MSecs) -> ok</name>
- <fsummary>Suspens the calling task for a specified time.</fsummary>
- <type>
- <v>MSecs = integer() | float() | infinity</v>
- <d>The number of milliseconds to sleep</d>
- </type>
- <desc>
- <p>This function suspends the calling process for at least the
- supplied number of milliseconds. There are two major reasons
- why you should use this function instead of
- <c>timer:sleep</c>, the first being that the module
- <c>timer</c> may be unavailable at the time the test suite is
- run, and the second that it also accepts floating point
- numbers.</p>
- </desc>
- </func>
- <func>
- <name>adjusted_sleep(MSecs) -> ok</name>
- <fsummary>Suspens the calling task for a specified time.</fsummary>
- <type>
- <v>MSecs = integer() | float() | infinity</v>
- <d>The default number of milliseconds to sleep</d>
- </type>
- <desc>
- <p>This function suspends the calling process for at least the
- supplied number of milliseconds. The function behaves the same
- way as <c>test_server:sleep/1</c>, only <c>MSecs</c>
- will be multiplied by the 'multiply_timetraps' value, if set,
- and also automatically scaled up if 'scale_timetraps' is set
- to true (which it is by default).</p>
- </desc>
- </func>
- <func>
- <name>hours(N) -> MSecs</name>
- <name>minutes(N) -> MSecs</name>
- <name>seconds(N) -> MSecs</name>
- <fsummary></fsummary>
- <type>
- <v>N = integer()</v>
- <d>Value to convert to milliseconds.</d>
- </type>
- <desc>
- <p>Theese functions convert <c>N</c> number of hours, minutes
- or seconds into milliseconds.
- </p>
- <p>Use this function when you want to
- <c>test_server:sleep/1</c> for a number of seconds, minutes or
- hours(!).</p>
- </desc>
- </func>
- <func>
- <name>format(Format) -> ok</name>
- <name>format(Format, Args)</name>
- <name>format(Pri, Format)</name>
- <name>format(Pri, Format, Args)</name>
- <fsummary></fsummary>
- <type>
- <v>Format = string()</v>
- <d>Format as described for <c>io_:format</c>.</d>
- <v>Args = list()</v>
- <d>List of arguments to format.</d>
- </type>
- <desc>
- <p>Formats output just like <c>io:format</c> but sends the
- formatted string to a logfile. If the urgency value,
- <c>Pri</c>, is lower than some threshold value, it will also
- be written to the test person's console. Default urgency is
- 50, default threshold for display on the console is 1.
- </p>
- <p>Typically, the test person don't want to see everything a
- test suite outputs, but is merely interested in if the test
- cases succeeded or not, which the test server tells him. If he
- would like to see more, he could manually change the threshold
- values by using the <c>test_server_ctrl:set_levels/3</c>
- function.</p>
- </desc>
- </func>
- <func>
- <name>capture_start() -> ok</name>
- <name>capture_stop() -> ok</name>
- <name>capture_get() -> list()</name>
- <fsummary>Captures all output to stdout for a process.</fsummary>
- <desc>
- <p>These functions makes it possible to capture all output to
- stdout from a process started by the test suite. The list of
- characters captured can be purged by using <c>capture_get</c>.</p>
- </desc>
- </func>
- <func>
- <name>messages_get() -> list()</name>
- <fsummary>Empty the message queue.</fsummary>
- <desc>
- <p>This function will empty and return all the messages
- currently in the calling process' message queue.</p>
- </desc>
- </func>
- <func>
- <name>timecall(M, F, A) -> {Time, Value}</name>
- <fsummary>Measures the time needed to call a function.</fsummary>
- <type>
- <v>M = atom()</v>
- <d>The name of the module where the function resides.</d>
- <v>F = atom()</v>
- <d>The name of the function to call in the module.</d>
- <v>A = list()</v>
- <d>The arguments to supply the called function.</d>
- <v>Time = integer()</v>
- <d>The number of seconds it took to call the function.</d>
- <v>Value = term()</v>
- <d>Value returned from the called function.</d>
- </type>
- <desc>
- <p>This function measures the time (in seconds) it takes to
- call a certain function. The function call is <em>not</em>
- caught within a catch.</p>
- </desc>
- </func>
- <func>
- <name>do_times(N, M, F, A) -> ok</name>
- <name>do_times(N, Fun)</name>
- <fsummary>Calls MFA or Fun N times.</fsummary>
- <type>
- <v>N = integer()</v>
- <d>Number of times to call MFA.</d>
- <v>M = atom()</v>
- <d>Module name where the function resides.</d>
- <v>F = atom()</v>
- <d>Function name to call.</d>
- <v>A = list()</v>
- <d>Arguments to M:F.</d>
- </type>
- <desc>
- <p>Calls MFA or Fun N times. Useful for extensive testing of a
- sensitive function.</p>
- </desc>
- </func>
- <func>
- <name>m_out_of_n(M, N, Fun) -> ok | exit({m_out_of_n_failed, {R,left_to_do}}</name>
- <fsummary>Fault tolerant <c>do_times</c>.</fsummary>
- <type>
- <v>N = integer()</v>
- <d>Number of times to call the Fun.</d>
- <v>M = integer()</v>
- <d>Number of times to require a successful return.</d>
- </type>
- <desc>
- <p>Repeatedly evaluates the given function until it succeeds
- (doesn't crash) M times. If, after N times, M successful
- attempts have not been accomplished, the process crashes with
- reason {m_out_of_n_failed, {R,left_to_do}}, where R indicates
- how many cases that was still to be successfully completed.
- </p>
- <p>For example:
- </p>
- <p><c>m_out_of_n(1,4,fun() -> tricky_test_case() end)</c> <br></br>
-Tries to run tricky_test_case() up to 4 times, and is
- happy if it succeeds once.
- </p>
- <p><c>m_out_of_n(7,8,fun() -> clock_sanity_check() end)</c> <br></br>
-Tries running clock_sanity_check() up to 8 times,and
- allows the function to fail once. This might be useful if
- clock_sanity_check/0 is known to fail if the clock crosses an
- hour boundary during the test (and the up to 8 test runs could
- never cross 2 boundaries)</p>
- </desc>
- </func>
- <func>
- <name>call_crash(M, F, A) -> Result</name>
- <name>call_crash(Time, M, F, A) -> Result</name>
- <name>call_crash(Time, Crash, M, F, A) -> Result</name>
- <fsummary>Calls MFA and succeeds if it crashes.</fsummary>
- <type>
- <v>Result = ok | exit(call_crash_timeout) | exit({wrong_crash_reason, Reason})</v>
- <v>Crash = term()</v>
- <d>Crash return from the function.</d>
- <v>Time = integer()</v>
- <d>Timeout in milliseconds.</d>
- <v>M = atom()</v>
- <d>Module name where the function resides.</d>
- <v>F = atom()</v>
- <d>Function name to call.</d>
- <v>A = list()</v>
- <d>Arguments to M:F.</d>
- </type>
- <desc>
- <p>Spawns a new process that calls MFA. The call is considered
- successful if the call crashes with the gives reason
- (<c>Crash</c>) or any reason if not specified. The call must
- terminate within the given time (default <c>infinity</c>), or
- it is considered a failure.</p>
- </desc>
- </func>
- <func>
- <name>temp_name(Stem) -> Name</name>
- <fsummary>Returns a unique filename.</fsummary>
- <type>
- <v>Stem = string()</v>
- </type>
- <desc>
- <p>Returns a unique filename starting with <c>Stem</c> with
- enough extra characters appended to make up a unique
- filename. The filename returned is guaranteed not to exist in
- the filesystem at the time of the call.</p>
- </desc>
- </func>
- <func>
- <name>break(Comment) -> ok</name>
- <fsummary>Cancel all timetraps and wait for call to continue/0.</fsummary>
- <type>
- <v>Comment = string()</v>
- </type>
- <desc>
- <p><c>Comment</c> is a string which will be written in
- the shell, e.g. explaining what to do.</p>
- <p>This function will cancel all timetraps and pause the
- execution of the test case until the user executes the
- <c>continue/0</c> function. It gives the user the opportunity
- to interact with the erlang node running the tests, e.g. for
- debugging purposes or for manually executing a part of the
- test case.</p>
- <p>When the <c>break/1</c> function is called, the shell will
- look something like this:</p>
- <code type="none"><![CDATA[
- --- SEMIAUTOMATIC TESTING ---
- The test case executes on process <0.51.0>
-
-
- "Here is a comment, it could e.g. instruct to pull out a card"
-
-
- -----------------------------
-
- Continue with --> test_server:continue(). ]]></code>
- <p>The user can now interact with the erlang node, and when
- ready call <c>test_server:continue().</c></p>
- <p>Note that this function can not be used if the test is
- executed with <c>ts:run/0/1/2/3/4</c> in <c>batch</c> mode.</p>
- </desc>
- </func>
- <func>
- <name>continue() -> ok</name>
- <fsummary>Continue after break/1.</fsummary>
- <desc>
- <p>This function must be called in order to continue after a
- test case has called <c>break/1</c>.</p>
- </desc>
- </func>
- <func>
- <name>run_on_shielded_node(Fun, CArgs) -> term()</name>
- <fsummary>Execute a function a shielded node.</fsummary>
- <type>
- <v>Fun = function() (arity 0)</v>
- <d>Function to execute on the shielded node.</d>
- <v>CArg = string()</v>
- <d>Extra command line arguments to use when starting the shielded node.</d>
- </type>
- <desc>
- <p><c>Fun</c> is executed in a process on a temporarily created
- hidden node with a proxy for communication with the test server
- node. The node is called a shielded node (should have been called
- a shield node). If <c>Fun</c> is successfully executed, the result
- is returned. A peer node (see <c>start_node/3</c>) started from
- the shielded node will be shielded from test server node, i.e.
- they will not be aware of each other. This is useful when you want
- to start nodes from earlier OTP releases than the OTP release of
- the test server node.</p>
- <p>Nodes from an earlier OTP release can normally not be started
- if the test server hasn't been started in compatibility mode
- (see the <c>+R</c> flag in the <c>erl(1)</c> documentation) of
- an earlier release. If a shielded node is started in compatibility
- mode of an earlier OTP release than the OTP release of the test
- server node, the shielded node can start nodes of an earlier OTP
- release.</p>
- <note>
- <p>You <em>must</em> make sure that nodes started by the shielded
- node never communicate directly with the test server node.</p>
- </note>
- <note>
- <p>Slave nodes always communicate with the test server node;
- therefore, <em>never</em> start <em>slave nodes</em> from the
- shielded node, <em>always</em> start <em>peer nodes</em>.</p>
- </note>
- </desc>
- </func>
- <func>
- <name>start_node(Name, Type, Options) -> {ok, Node} | {error, Reason}</name>
- <fsummary>Start a node.</fsummary>
- <type>
- <v>Name = atom() | string()</v>
- <d>Name of the slavenode to start (as given to -sname or -name)</d>
- <v>Type = slave | peer</v>
- <d>The type of node to start.</d>
- <v>Options = [{atom(), term()]</v>
- <d>Tuplelist of options</d>
- </type>
- <desc>
- <p>This functions starts a node, possibly on a remote machine,
- and guarantees cross architecture transparency. Type is set to
- either <c>slave</c> or <c>peer</c>.
- </p>
- <p><c>slave</c> means that the new node will have a master,
- i.e. the slave node will terminate if the master terminates,
- TTY output produced on the slave will be sent back to the
- master node and file I/O is done via the master. The master is
- normally the target node unless the target is itself a slave.
- </p>
- <p><c>peer</c> means that the new node is an independent node
- with no master.
- </p>
- <p><c>Options</c> is a tuplelist which can contain one or more
- of
- </p>
- <taglist>
- <tag><c>{remote, true}</c></tag>
- <item>Start the node on a remote host. If not specified, the
- node will be started on the local host. Test cases that
- require a remote host will fail with a reasonable comment if
- no remote hosts are available at the time they are run.
- </item>
- <tag><c>{args, Arguments}</c></tag>
- <item>Arguments passed directly to the node. This is
- typically a string appended to the command line.
- </item>
- <tag><c>{wait, false}</c></tag>
- <item>Don't wait until the node is up. By default, this
- function does not return until the node is up and running,
- but this option makes it return as soon as the node start
- command is given..
- <br></br>
-Only valid for peer nodes
- </item>
- <tag><c>{fail_on_error, false}</c></tag>
- <item>Returns <c>{error, Reason}</c> rather than failing the
- test case.
- <br></br>
-Only valid for peer nodes. Note that slave nodes always
- act as if they had <c>fail_on_error=false</c></item>
- <tag><c>{erl, ReleaseList}</c></tag>
- <item>Use an Erlang emulator determined by ReleaseList when
- starting nodes, instead of the same emulator as the test
- server is running. ReleaseList is a list of specifiers,
- where a specifier is either {release, Rel}, {prog, Prog}, or
- 'this'. Rel is either the name of a release, e.g., "r12b_patched"
- or 'latest'. 'this' means using the same emulator as the test
- server. Prog is the name of an emulator executable. If the
- list has more than one element, one of them is picked
- randomly. (Only works on Solaris and Linux, and the test server
- gives warnings when it notices that nodes are not of the same
- version as itself.)
- <br></br>
- <br></br>
-
- When specifying this option to run a previous release, use
- <c>is_release_available/1</c> function to test if the given
- release is available and skip the test case if not.
- <br></br>
- <br></br>
-
- In order to avoid compatibility problems (may not appear right
- away), use a shielded node (see <c>run_on_shielded_node/2</c>)
- when starting nodes from different OTP releases than the test
- server.
- </item>
- <tag><c>{cleanup, false}</c></tag>
- <item>Tells the test server not to kill this node if it is
- still alive after the test case is completed. This is useful
- if the same node is to be used by a group of test cases.
- </item>
- <tag><c>{env, Env}</c></tag>
- <item><c>Env</c> should be a list of tuples <c>{Name, Val}</c>,
- where <c>Name</c> is the name of an environment variable, and
- <c>Val</c> is the value it is to have in the started node.
- Both <c>Name</c> and <c>Val</c> must be strings. The one
- exception is <c>Val</c> being the atom <c>false</c> (in
- analogy with <c>os:getenv/1</c>), which removes the
- environment variable. Only valid for peer nodes. Not
- available on VxWorks.</item>
- <tag><c>{start_cover, false}</c></tag>
- <item>By default the test server will start cover on all nodes
- when the test is run with code coverage analysis. To make
- sure cover is not started on a new node, set this option to
- <c>false</c>. This can be necessary if the connection to
- the node at some point will be broken but the node is
- expected to stay alive. The reason is that a remote cover
- node can not continue to run without its main node. Another
- solution would be to explicitly stop cover on the node
- before breaking the connection, but in some situations (if
- old code resides in one or more processes) this is not
- possible.</item>
- </taglist>
- </desc>
- </func>
- <func>
- <name>stop_node(NodeName) -> bool()</name>
- <fsummary>Stops a node</fsummary>
- <type>
- <v>NodeName = term()</v>
- <d>Name of the node to stop</d>
- </type>
- <desc>
- <p>This functions stops a node previously started with
- <c>start_node/3</c>. Use this function to stop any node you
- start, or the test server will produce a warning message in
- the test logs, and kill the nodes automatically unless it was
- started with the <c>{cleanup, false}</c> option.</p>
- </desc>
- </func>
- <func>
- <name>is_commercial() -> bool()</name>
- <fsummary>Tests whether the emulator is commercially supported</fsummary>
- <desc>
- <p>This function test whether the emulator is commercially supported
- emulator. The tests for a commercially supported emulator could be more
- stringent (for instance, a commercial release should always contain
- documentation for all applications).</p>
- </desc>
- </func>
-
- <func>
- <name>is_release_available(Release) -> bool()</name>
- <fsummary>Tests whether a release is available</fsummary>
- <type>
- <v>Release = string() | atom()</v>
- <d>Release to test for</d>
- </type>
- <desc>
- <p>This function test whether the release given by
- <c>Release</c> (for instance, "r12b_patched") is available
- on the computer that the test_server controller is running on.
- Typically, you should skip the test case if not.</p>
- <p>Caution: This function may not be called from the <c>suite</c>
- clause of a test case, as the test_server will deadlock.</p>
- </desc>
- </func>
- <func>
- <name>is_native(Mod) -> bool()</name>
- <fsummary>Checks whether the module is natively compiled or not</fsummary>
- <type>
- <v>Mod = atom()</v>
- <d>A module name</d>
- </type>
- <desc>
- <p>Checks whether the module is natively compiled or not</p>
- </desc>
- </func>
- <func>
- <name>app_test(App) -> ok | test_server:fail()</name>
- <name>app_test(App,Mode)</name>
- <fsummary>Checks an applications .app file for obvious errors</fsummary>
- <type>
- <v>App = term()</v>
- <d>The name of the application to test</d>
- <v>Mode = pedantic | tolerant</v>
- <d>Default is pedantic</d>
- </type>
- <desc>
- <p>Checks an applications .app file for obvious errors.
- The following is checked:
- </p>
- <list type="bulleted">
- <item>required fields
- </item>
- <item>that all modules specified actually exists
- </item>
- <item>that all requires applications exists
- </item>
- <item>that no module included in the application has export_all
- </item>
- <item>that all modules in the ebin/ dir is included (If
- <c>Mode==tolerant</c> this only produces a warning, as all
- modules does not have to be included)</item>
- </list>
- </desc>
- </func>
- <func>
- <name>appup_test(App) -> ok | test_server:fail()</name>
- <fsummary>Checks an applications .appup file for obvious errors</fsummary>
- <type>
- <v>App = term()</v>
- <d>The name of the application to test</d>
- </type>
- <desc>
- <p>Checks an applications .appup file for obvious errors.
- The following is checked:
- </p>
- <list type="bulleted">
- <item>syntax
- </item>
- <item>that .app file version and .appup file version match
- </item>
- <item>for non-library applications: validity of high-level upgrade
- instructions, specifying no instructions is explicitly allowed
- (in this case the application is not upgradeable)</item>
- <item>for library applications: that there is exactly one wildcard
- regexp clause restarting the application when upgrading or
- downgrading from any version</item>
- </list>
- </desc>
- </func>
- <func>
- <name>comment(Comment) -> ok</name>
- <fsummary>Print a comment on the HTML result page</fsummary>
- <type>
- <v>Comment = string()</v>
- </type>
- <desc>
- <p>The given String will occur in the comment field of the
- table on the HTML result page. If called several times, only
- the last comment is printed. comment/1 is also overwritten by
- the return value {comment,Comment} from a test case or by
- fail/1 (which prints Reason as a comment).</p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>TEST SUITE EXPORTS</title>
- <p>The following functions must be exported from a test suite
- module.
- </p>
- </section>
- <funcs>
- <func>
- <name>all(suite) -> TestSpec | {skip, Comment}</name>
- <fsummary>Returns the module's test specification</fsummary>
- <type>
- <v>TestSpec = list()</v>
- <v>Comment = string()</v>
- <d>This comment will be printed on the HTML result page</d>
- </type>
- <desc>
- <p>This function must return the test specification for the
- test suite module. The syntax of a test specification is
- described in the Test Server User's Guide.</p>
- </desc>
- </func>
- <func>
- <name>init_per_suite(Config0) -> Config1 | {skip, Comment}</name>
- <fsummary>Test suite initiation</fsummary>
- <type>
- <v>Config0 = Config1 = [tuple()]</v>
- <v>Comment = string()</v>
- <d>Describes why the suite is skipped</d>
- </type>
- <desc>
- <p>This function is called before all other test cases in the
- suite. <c>Config</c> is the configuration which can be modified
- here. Whatever is returned from this function is given as
- <c>Config</c> to the test cases.
- </p>
- <p>If this function fails, all test cases in the suite will be
- skipped.</p>
- </desc>
- </func>
- <func>
- <name>end_per_suite(Config) -> void()</name>
- <fsummary>Test suite finalization</fsummary>
- <type>
- <v>Config = [tuple()]</v>
- </type>
- <desc>
- <p>This function is called after the last test case in the
- suite, and can be used to clean up whatever the test cases
- have done. The return value is ignored.</p>
- </desc>
- </func>
- <func>
- <name>init_per_testcase(Case, Config0) -> Config1 | {skip, Comment}</name>
- <fsummary>Test case initiation</fsummary>
- <type>
- <v>Case = atom()</v>
- <v>Config0 = Config1 = [tuple()]</v>
- <v>Comment = string()</v>
- <d>Describes why the test case is skipped</d>
- </type>
- <desc>
- <p>This function is called before each test case. The
- <c>Case</c> argument is the name of the test case, and
- <c>Config</c> is the configuration which can be modified
- here. Whatever is returned from this function is given as
- <c>Config</c> to the test case.</p>
- </desc>
- </func>
- <func>
- <name>end_per_testcase(Case, Config) -> void()</name>
- <fsummary>Test case finalization</fsummary>
- <type>
- <v>Case = atom()</v>
- <v>Config = [tuple()]</v>
- </type>
- <desc>
- <p>This function is called after each test case, and can be
- used to clean up whatever the test case has done. The return
- value is ignored.</p>
- </desc>
- </func>
- <func>
- <name>Case(doc) -> [Decription]</name>
- <name>Case(suite) -> [] | TestSpec | {skip, Comment}</name>
- <name>Case(Config) -> {skip, Comment} | {comment, Comment} | Ok</name>
- <fsummary>A test case</fsummary>
- <type>
- <v>Description = string()</v>
- <d>Short description of the test case</d>
- <v>TestSpec = list()</v>
- <v>Comment = string()</v>
- <d>This comment will be printed on the HTML result page</d>
- <v>Ok = term()</v>
- <v>Config = [tuple()]</v>
- <d>Elements from the Config parameter can be read with the ?config macro, see section about test suite support macros</d>
- </type>
- <desc>
- <p>The <em>documentation clause</em> (argument <c>doc</c>) can
- be used for automatic generation of test documentation or test
- descriptions.
- </p>
- <p>The <em>specification clause</em> (argument <c>spec</c>)
- shall return an empty list, the test specification for the
- test case or <c>{skip,Comment}</c>. The syntax of a test
- specification is described in the Test Server User's Guide.
- </p>
- <p>The <em>execution clause</em> (argument <c>Config</c>) is
- only called if the specification clause returns an empty list.
- The execution clause is the real test case. Here you must call
- the functions you want to test, and do whatever you need to
- check the result. If something fails, make sure the process
- crashes or call <c>test_server:fail/0/1</c> (which also will
- cause the process to crash).
- </p>
- <p>You can return <c>{skip,Comment}</c> if you decide not to
- run the test case after all, e.g. if it is not applicable on
- this platform.
- </p>
- <p>You can return <c>{comment,Comment}</c> if you wish to
- print some information in the 'Comment' field on the HTML
- result page.
- </p>
- <p>If the execution clause returns anything else, it is
- considered a success, unless it is <c>{'EXIT',Reason}</c> or
- <c>{'EXIT',Pid,Reason}</c> which can't be distinguished from a
- crash, and thus will be considered a failure.
- </p>
- <p>A <em>conf test case</em> is a group of test cases with an
- init and a cleanup function. The init and cleanup functions
- are also test cases, but they have special rules:</p>
- <list type="bulleted">
- <item>They do not need a specification clause.</item>
- <item>They must always have the execution clause.</item>
- <item>They must return the <c>Config</c> parameter, a modified
- version of it or <c>{skip,Comment}</c> from the execution clause.</item>
- <item>The cleanup function may also return a tuple
- <c>{return_group_result,Status}</c>, which is used to return the
- status of the conf case to Test Server and/or to a conf case on a
- higher level. (<c>Status = ok | skipped | failed</c>).</item>
- <item><c>init_per_testcase</c> and <c>end_per_testcase</c> are
- not called before and after these functions.</item>
- </list>
- </desc>
- </func>
- </funcs>
-
-
- <section>
- <title>TEST SUITE SUPPORT MACROS</title>
- <p>There are some macros defined in the <c>test_server.hrl</c>
- that are quite useful for test suite programmers:
- </p>
- <p>The <em>config</em> macro, is used to
- retrieve information from the <c>Config</c> variable sent to all
- test cases. It is used with two arguments, where the first is the
- name of the configuration variable you wish to retrieve, and the
- second is the <c>Config</c> variable supplied to the test case
- from the test server.
- </p>
- <p>Possible configuration variables include:</p>
- <list type="bulleted">
- <item><c>data_dir</c> - Data file directory.</item>
- <item><c>priv_dir</c> - Scratch file directory.</item>
- <item><c>nodes</c> - Nodes specified in the spec file</item>
- <item><c>nodenames</c> - Generated nodenames.</item>
- <item>Whatever added by conf test cases or
- <c>init_per_testcase/2</c></item>
- </list>
- <p>Examples of the <c>config</c> macro can be seen in the Examples chapter
- in the user's guide.</p>
- <p>The <em>line</em> and <em>line_trace</em> macros are deprecated, see
- below.</p>
- </section>
-
- <section>
- <title>TEST SUITE LINE NUMBERS</title>
- <p>In the past, ERTS did not produce line numbers when generating
- stacktraces, test_server was thus unable to provide them when reporting
- test failures. It had instead two different mecanisms to do it: either by
- using the <c>line</c> macro or by using the <c>test_server_line</c> parse
- transform. Both are deprecated and should not be used in new tests
- anymore.</p>
- </section>
-</erlref>
-
diff --git a/lib/test_server/doc/src/test_server_app.xml b/lib/test_server/doc/src/test_server_app.xml
deleted file mode 100644
index 4830916561..0000000000
--- a/lib/test_server/doc/src/test_server_app.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE appref SYSTEM "appref.dtd">
-
-<appref>
- <header>
- <copyright>
- <year>2002</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Test Server Application</title>
- <prepared>Siri Hansen</prepared>
- <responsible>Peter Andersson</responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2002-07-12</date>
- <rev>PA1</rev>
- <file>test_server_app.xml</file>
- </header>
- <app>test_server</app>
- <appsummary>Test Server for manual or automatic testing of Erlang code</appsummary>
- <description>
- <p><em>Test Server</em> is a portable test server for
- automated application testing. The server can run test suites
- and log progress and results to HTML
- pages. The main purpose of Test Server is to act as engine
- inside customized test tools. A callback interface for
- such framework applications is provided.</p>
- <p>In brief the test server supports:</p>
- <list type="bulleted">
- <item>Running multiple, concurrent test suites</item>
- <item>Test suites may contain other test suites, in a tree fashion</item>
- <item>Logging of the events in a test suite, on both suite and case levels</item>
- <item>HTML presentation of test suite results</item>
- <item>HTML presentation of test suite code</item>
- <item>Support for test suite authors, e.g. start/stop slave nodes</item>
- <item>Call trace on target and slave nodes</item>
- </list>
- <p>For information about how to write test cases and test suites,
- please see the Test Server User's Guide and the reference
- manual for the <c>test_server</c> module.
- </p>
- <p><em>Common Test</em> is an existing test tool application based on the
- OTP Test Server. Please read the Common Test User's Guide for more information.
- </p>
- </description>
-
- <section>
- <title>Configuration</title>
- <p>There are currently no configuration parameters available for
- this application.
- </p>
- </section>
-
- <section>
- <title>SEE ALSO</title>
- <p></p>
- </section>
-</appref>
-
diff --git a/lib/test_server/doc/src/test_server_ctrl.xml b/lib/test_server/doc/src/test_server_ctrl.xml
deleted file mode 100644
index 2762997ece..0000000000
--- a/lib/test_server/doc/src/test_server_ctrl.xml
+++ /dev/null
@@ -1,844 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2007</year>
- <year>2013</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- 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.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>The Test Server Controller</title>
- <prepared>Siri Hansen, Peter Andersson</prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date></date>
- <rev></rev>
- <file>test_server_ctrl_ref.sgml</file>
- </header>
- <module>test_server_ctrl</module>
- <modulesummary>This module provides a low level interface to the Test Server.</modulesummary>
- <description>
- <p>The <c>test_server_ctrl</c> module provides a low level
- interface to the Test Server. This interface is normally
- not used directly by the tester, but through a framework built
- on top of <c>test_server_ctrl</c>.
- </p>
- <p>Common Test is such a framework, well suited for automated
- black box testing of target systems of any kind (not necessarily
- implemented in Erlang). Common Test is also a very useful tool for
- white box testing Erlang programs and OTP applications.
- Please see the Common Test User's Guide and reference manual for
- more information.
- </p>
- <p>If you want to write your own framework, some more information
- can be found in the chapter "Writing your own test server
- framework" in the Test Server User's Guide. Details about the
- interface provided by <c>test_server_ctrl</c> follows below.
- </p>
- </description>
- <funcs>
- <func>
- <name>start() -> Result</name>
- <fsummary>Starts the test server.</fsummary>
- <type>
- <v>Result = ok | {error, {already_started, pid()}</v>
- </type>
- <desc>
- <p>This function starts the test server.</p>
- </desc>
- </func>
- <func>
- <name>stop() -> ok</name>
- <fsummary>Stops the test server immediately.</fsummary>
- <desc>
- <p>This stops the test server and
- all its activity. The running test suite (if any) will be
- halted.</p>
- </desc>
- </func>
- <func>
- <name>add_dir(Name, Dir) -> ok</name>
- <name>add_dir(Name, Dir, Pattern) -> ok</name>
- <name>add_dir(Name, [Dir|Dirs]) -> ok</name>
- <name>add_dir(Name, [Dir|Dirs], Pattern) -> ok</name>
- <fsummary>Add a directory to the job queue.</fsummary>
- <type>
- <v>Name = term()</v>
- <d>The jobname for this directory.</d>
- <v>Dir = term()</v>
- <d>The directory to scan for test suites.</d>
- <v>Dirs = [term()]</v>
- <d>List of directories to scan for test suites.</d>
- <v>Pattern = term()</v>
- <d>Suite match pattern. Directories will be scanned for Pattern_SUITE.erl files.</d>
- </type>
- <desc>
- <p>Puts a collection of suites matching (*_SUITE) in given
- directories into the job queue. <c>Name</c> is an arbitrary
- name for the job, it can be any erlang term. If <c>Pattern</c>
- is given, only modules matching <c>Pattern*</c> will be added.</p>
- </desc>
- </func>
- <func>
- <name>add_module(Mod) -> ok</name>
- <name>add_module(Name, [Mod|Mods]) -> ok</name>
- <fsummary>Add a module to the job queue with or without a given name.</fsummary>
- <type>
- <v>Mod = atom()</v>
- <v>Mods = [atom()]</v>
- <d>The name(s) of the module(s) to add.</d>
- <v>Name = term()</v>
- <d>Name for the job.</d>
- </type>
- <desc>
- <p>This function adds a module or a list of modules, to the
- test servers job queue. <c>Name</c> may be any Erlang
- term. When <c>Name</c> is not given, the job gets the name of
- the module.</p>
- </desc>
- </func>
- <func>
- <name>add_case(Mod, Case) -> ok</name>
- <fsummary>Adds one test case to the job queue.</fsummary>
- <type>
- <v>Mod = atom()</v>
- <d>Name of the module the test case is in.</d>
- <v>Case = atom() </v>
- <d>Function name of the test case to add.</d>
- </type>
- <desc>
- <p>This function will add one test case to the job queue. The
- job will be given the module's name.</p>
- </desc>
- </func>
- <func>
- <name>add_case(Name, Mod, Case) -> ok</name>
- <fsummary>Equivalent to add_case/2, but with specified name.</fsummary>
- <type>
- <v>Name = string()</v>
- <d>Name to use for the test job.</d>
- </type>
- <desc>
- <p>Equivalent to <c>add_case/2</c>, but the test job will get
- the specified name.</p>
- </desc>
- </func>
- <func>
- <name>add_cases(Mod, Cases) -> ok</name>
- <fsummary>Adds a list of test cases to the job queue.</fsummary>
- <type>
- <v>Mod = atom()</v>
- <d>Name of the module the test case is in.</d>
- <v>Cases = [Case] </v>
- <v>Case = atom() </v>
- <d>Function names of the test cases to add.</d>
- </type>
- <desc>
- <p>This function will add one or more test cases to the job
- queue. The job will be given the module's name.</p>
- </desc>
- </func>
- <func>
- <name>add_cases(Name, Mod, Cases) -> ok</name>
- <fsummary>Equivalent to add_cases/2, but with specified name.</fsummary>
- <type>
- <v>Name = string()</v>
- <d>Name to use for the test job.</d>
- </type>
- <desc>
- <p>Equivalent to <c>add_cases/2</c>, but the test job will get
- the specified name.</p>
- </desc>
- </func>
- <func>
- <name>add_spec(TestSpecFile) -> ok | {error, nofile}</name>
- <fsummary>Adds a test specification file to the job queue.</fsummary>
- <type>
- <v>TestSpecFile = string()</v>
- <d>Name of the test specification file</d>
- </type>
- <desc>
- <p>This function will add the content of the given test
- specification file to the job queue. The job will be given the
- name of the test specification file, e.g. if the file is
- called <c>test.spec</c>, the job will be called <c>test</c>.
- </p>
- <p>See the reference manual for the test server application
- for details about the test specification file.</p>
- </desc>
- </func>
- <func>
- <name>add_dir_with_skip(Name, [Dir|Dirs], Skip) -> ok</name>
- <name>add_dir_with_skip(Name, [Dir|Dirs], Pattern, Skip) -> ok</name>
- <name>add_module_with_skip(Mod, Skip) -> ok</name>
- <name>add_module_with_skip(Name, [Mod|Mods], Skip) -> ok</name>
- <name>add_case_with_skip(Mod, Case, Skip) -> ok</name>
- <name>add_case_with_skip(Name, Mod, Case, Skip) -> ok</name>
- <name>add_cases_with_skip(Mod, Cases, Skip) -> ok</name>
- <name>add_cases_with_skip(Name, Mod, Cases, Skip) -> ok</name>
- <fsummary>Same purpose as functions listed above, but with extra Skip argument.</fsummary>
- <type>
- <v>Skip = [SkipItem]</v>
- <d>List of items to be skipped from the test.</d>
- <v>SkipItem = {Mod,Comment} | {Mod,Case,Comment} | {Mod,Cases,Comment}</v>
- <v>Mod = atom()</v>
- <d>Test suite name.</d>
- <v>Comment = string()</v>
- <d>Reason why suite or case is being skipped.</d>
- <v>Cases = [Case]</v>
- <v>Case = atom()</v>
- <d>Name of test case function.</d>
- </type>
- <desc>
- <p>These functions add test jobs just like the add_dir, add_module,
- add_case and add_cases functions above, but carry an additional
- argument, Skip. Skip is a list of items that should be skipped
- in the current test run. Test job items that occur in the Skip
- list will be logged as SKIPPED with the associated Comment.</p>
- </desc>
- </func>
- <func>
- <name>add_tests_with_skip(Name, Tests, Skip) -> ok</name>
- <fsummary>Adds different types of jobs to the run queue.</fsummary>
- <type>
- <v>Name = term()</v>
- <d>The jobname for this directory.</d>
- <v>Tests = [TestItem]</v>
- <d>List of jobs to add to the run queue.</d>
- <v>TestItem = {Dir,all,all} | {Dir,Mods,all} | {Dir,Mod,Cases}</v>
- <v>Dir = term()</v>
- <d>The directory to scan for test suites.</d>
- <v>Mods = [Mod]</v>
- <v>Mod = atom()</v>
- <d>Test suite name.</d>
- <v>Cases = [Case]</v>
- <v>Case = atom()</v>
- <d>Name of test case function.</d>
- <v>Skip = [SkipItem]</v>
- <d>List of items to be skipped from the test.</d>
- <v>SkipItem = {Mod,Comment} | {Mod,Case,Comment} | {Mod,Cases,Comment}</v>
- <v>Comment = string()</v>
- <d>Reason why suite or case is being skipped.</d>
- </type>
- <desc>
- <p>This function adds various test jobs to the test_server_ctrl
- job queue. These jobs can be of different type (all or specific suites
- in one directory, all or specific cases in one suite, etc). It is also
- possible to get particular items skipped by passing them along in the
- Skip list (see the add_*_with_skip functions above).</p>
- </desc>
- </func>
- <func>
- <name>abort_current_testcase(Reason) -> ok | {error,no_testcase_running}</name>
- <fsummary>Aborts the test case currently executing.</fsummary>
- <type>
- <v>Reason = term()</v>
- <d>The reason for stopping the test case, which will be printed in the log.</d>
- </type>
- <desc>
- <p>When calling this function, the currently executing test case will be aborted.
- It is the user's responsibility to know for sure which test case is currently
- executing. The function is therefore only safe to call from a function which
- has been called (or synchronously invoked) by the test case.</p>
- </desc>
- </func>
- <func>
- <name>set_levels(Console, Major, Minor) -> ok</name>
- <fsummary>Sets the levels of I/O.</fsummary>
- <type>
- <v>Console = integer()</v>
- <d>Level for I/O to be sent to console.</d>
- <v>Major = integer()</v>
- <d>Level for I/O to be sent to the major logfile.</d>
- <v>Minor = integer()</v>
- <d>Level for I/O to be sent to the minor logfile.</d>
- </type>
- <desc>
- <p>Determines where I/O from test suites/test server will
- go. All text output from test suites and the test server is
- tagged with a priority value which ranges from 0 to 100, 100
- being the most detailed. (see the section about log files in
- the user's guide). Output from the test cases (using
- <c>io:format/2</c>) has a detail level of 50. Depending on the
- levels set by this function, this I/O may be sent to the
- console, the major log file (for the whole test suite) or to
- the minor logfile (separate for each test case).
- </p>
- <p>All output with detail level:</p>
- <list type="bulleted">
- <item>Less than or equal to <c>Console</c> is displayed on
- the screen (default 1)
- </item>
- <item>Less than or equal to <c>Major</c> is logged in the
- major log file (default 19)
- </item>
- <item>Greater than or equal to <c>Minor</c> is logged in the
- minor log files (default 10)
- </item>
- </list>
- <p>To view the currently set thresholds, use the
- <c>get_levels/0</c> function.</p>
- </desc>
- </func>
- <func>
- <name>get_levels() -> {Console, Major, Minor}</name>
- <fsummary>Returns the current levels.</fsummary>
- <desc>
- <p>Returns the current levels. See <c>set_levels/3</c> for
- types.</p>
- </desc>
- </func>
- <func>
- <name>jobs() -> JobQueue</name>
- <fsummary>Returns the job queue.</fsummary>
- <type>
- <v>JobQueue = [{list(), pid()}]</v>
- </type>
- <desc>
- <p>This function will return all the jobs currently in the job
- queue.</p>
- </desc>
- </func>
- <func>
- <name>multiply_timetraps(N) -> ok</name>
- <fsummary>All timetraps started after this will be multiplied by N.</fsummary>
- <type>
- <v>N = integer() | infinity</v>
- </type>
- <desc>
- <p>This function should be called before a test is started
- which requires extended timetraps, e.g. if extensive tracing
- is used. All timetraps started after this call will be
- multiplied by <c>N</c>.</p>
- </desc>
- </func>
- <func>
- <name>scale_timetraps(Bool) -> ok</name>
- <fsummary>.</fsummary>
- <type>
- <v>Bool = true | false</v>
- </type>
- <desc>
- <p>This function should be called before a test is started.
- The parameter specifies if test_server should attempt
- to automatically scale the timetrap value in order to compensate
- for delays caused by e.g. the cover tool.</p>
- </desc>
- </func>
- <func>
- <name>get_timetrap_parameters() -> {N,Bool} </name>
- <fsummary>Read the parameter values that affect timetraps.</fsummary>
- <type>
- <v>N = integer() | infinity</v>
- <v>Bool = true | false</v>
- </type>
- <desc>
- <p>This function may be called to read the values set by
- <c>multiply_timetraps/1</c> and <c>scale_timetraps/1</c>.</p>
- </desc>
- </func>
- <func>
- <name>cover(Application,Analyse) -> ok</name>
- <name>cover(CoverFile,Analyse) -> ok</name>
- <name>cover(App,CoverFile,Analyse) -> ok</name>
- <fsummary>Informs the test_server controller that next test shall run with code coverage analysis.</fsummary>
- <type>
- <v>Application = atom()</v>
- <d>OTP application to cover compile</d>
- <v>CoverFile = string()</v>
- <d>Name of file listing modules to exclude from or include in cover compilation. The filename must include full path to the file.</d>
- <v>Analyse = details | overview</v>
- </type>
- <desc>
- <p>This function informs the test_server controller that next
- test shall run with code coverage analysis. All timetraps will
- automatically be multiplied by 10 when cover i run.
- </p>
- <p><c>Application</c> and <c>CoverFile</c> indicates what to
- cover compile. If <c>Application</c> is given, the default is
- that all modules in the <c>ebin</c> directory of the
- application will be cover compiled. The <c>ebin</c> directory
- is found by adding <c>ebin</c> to
- <c>code:lib_dir(Application)</c>.
- </p>
- <p>A <c>CoverFile</c> can have the following entries:</p>
- <code type="none">
-{exclude, all | ExcludeModuleList}.
-{include, IncludeModuleList}.
-{cross, CrossCoverInfo}.</code>
- <p>Note that each line must end with a full
- stop. <c>ExcludeModuleList</c> and <c>IncludeModuleList</c>
- are lists of atoms, where each atom is a module name.
- </p>
-
- <p><c>CrossCoverInfo</c> is used when collecting cover data
- over multiple tests. Modules listed here are compiled, but
- they will not be analysed when the test is finished. See
- <seealso
- marker="#cross_cover_analyse-2">cross_cover_analyse/2</seealso>
- for more information about the cross cover mechanism and the
- format of <c>CrossCoverInfo</c>.
- </p>
- <p>If both an <c>Application</c> and a <c>CoverFile</c> is
- given, all modules in the application are cover compiled,
- except for the modules listed in <c>ExcludeModuleList</c>. The
- modules in <c>IncludeModuleList</c> are also cover compiled.
- </p>
- <p>If a <c>CoverFile</c> is given, but no <c>Application</c>,
- only the modules in <c>IncludeModuleList</c> are cover
- compiled.
- </p>
- <p><c>Analyse</c> indicates the detail level of the cover
- analysis. If <c>Analyse = details</c>, each cover compiled
- module will be analysed with
- <c>cover:analyse_to_file/1</c>. If <c>Analyse = overview</c>
- an overview of all cover compiled modules is created, listing
- the number of covered and not covered lines for each module.
- </p>
- <p>If the test following this call starts any slave or peer
- nodes with <c>test_server:start_node/3</c>, the same cover
- compiled code will be loaded on all nodes. If the loading
- fails, e.g. if the node runs an old version of OTP, the node
- will simply not be a part of the coverage analysis. Note that
- slave or peer nodes must be stopped with
- <c>test_server:stop_node/1</c> for the node to be part of the
- coverage analysis, else the test server will not be able to
- fetch coverage data from the node.
- </p>
- <p>When the test is finished, the coverage analysis is
- automatically completed, logs are created and the cover
- compiled modules are unloaded. If another test is to be run
- with coverage analysis, <c>test_server_ctrl:cover/2/3</c> must
- be called again.
- </p>
- </desc>
- </func>
- <func>
- <name>cross_cover_analyse(Level, Tests) -> ok</name>
- <fsummary>Analyse cover data collected from multiple tests</fsummary>
- <type>
- <v>Level = details | overview</v>
- <v>Tests = [{Tag,LogDir}]</v>
- <v>Tag = atom()</v>
- <d>Test identifier.</d>
- <v>LogDir = string()</v>
- <d>Log directory for the test identified by <c>Tag</c>. This
- can either be the <c>run.&lt;timestamp&gt;</c> directory or
- the parent directory of this (in which case the latest
- <c>run.&lt;timestamp&gt;</c> directory is chosen.</d>
- </type>
- <desc>
- <p>Analyse cover data collected from multiple tests. The modules
- analysed are the ones listed in <c>cross</c> statements in
- the cover files. These are modules that are heavily used by
- other tests than the one where they belong or are explicitly
- tested. They should then be listed as cross modules in the
- cover file for the test where they are used but do not
- belong. Se example below.</p>
- <p>This function should be run after all tests are completed,
- and the result will be stored in a file called
- <c>cross_cover.html</c> in the <c>run.&lt;timestamp&gt;</c>
- directory of the test the modules belong to.</p>
- <p>Note that the function can be executed on any node, and it
- does not require <c>test_server_ctrl</c> to be started first.</p>
- <p>The <c>cross</c> statement in the cover file must be like this:</p>
- <code type="none">
-{cross,[{Tag,Modules}]}.</code>
- <p>where <c>Tag</c> is the same as <c>Tag</c> in the
- <c>Tests</c> parameter to this function and <c>Modules</c> is a
- list of module names (atoms).</p>
- <p><em>Example:</em></p>
- <p>If the module <c>m1</c> belongs to system <c>s1</c> but is
- heavily used also in the tests for another system <c>s2</c>,
- then the cover files for the two systems' tests could be like
- this:</p>
-<code type="none">
-s1.cover:
- {include,[m1]}.
-
-s2.cover:
- {include,[....]}. % modules belonging to system s2
- {cross,[{s1,[m1]}]}.</code>
- <p>When the tests for both <c>s1</c> and <c>s2</c> are completed, run</p>
-<code type="none">
-test_server_ctrl:cross_cover_analyse(Level,[{s1,S1LogDir},{s2,S2LogDir}])
-</code>
-
- <p>and the accumulated cover data for <c>m1</c> will be written to
- <c>S1LogDir/[run.&lt;timestamp&gt;/]cross_cover.html</c>.</p>
- <p>Note that the <c>m1</c> module will also be presented in the
- normal coverage log for <c>s1</c> (due to the include statement in
- <c>s1.cover</c>), but that only includes the coverage achieved by the
- <c>s1</c> test itself.</p>
- <p>The Tag in the <c>cross</c> statement in the cover file has
- no other purpose than mapping the list of modules
- (<c>[m1]</c> in the example above) to the correct log
- directory where it should be included in the
- <c>cross_cover.html</c> file (<c>S1LogDir</c> in the example
- above). I.e. the value of <c>Tag</c> has no meaning, it
- could be <c>foo</c> as well as <c>s1</c> above, as long as
- the same <c>Tag</c> is used in the cover file and in the
- call to this function.</p>
- </desc>
- </func>
- <func>
- <name>trc(TraceInfoFile) -> ok | {error, Reason}</name>
- <fsummary>Starts call trace on target and slave nodes</fsummary>
- <type>
- <v>TraceInfoFile = atom() | string()</v>
- <d>Name of a file defining which functions to trace and how</d>
- </type>
- <desc>
- <p>This function starts call trace on target and on slave or
- peer nodes that are started or will be started by the test
- suites.
- </p>
- <p>Timetraps are not extended automatically when tracing is
- used. Use <c>multiply_timetraps/1</c> if necessary.
- </p>
- <p>Note that the trace support in the test server is in a very
- early stage of the implementation, and thus not yet as
- powerful as one might wish for.
- </p>
- <p>The trace information file specified by the
- <c>TraceInfoFile</c> argument is a text file containing one or
- more of the following elements:
- </p>
- <list type="bulleted">
- <item><c>{SetTP,Module,Pattern}.</c></item>
- <item><c>{SetTP,Module,Function,Pattern}.</c></item>
- <item><c>{SetTP,Module,Function,Arity,Pattern}.</c></item>
- <item><c>ClearTP.</c></item>
- <item><c>{ClearTP,Module}.</c></item>
- <item><c>{ClearTP,Module,Function}.</c></item>
- <item><c>{ClearTP,Module,Function,Arity}.</c></item>
- </list>
- <taglist>
- <tag><c>SetTP = tp | tpl</c></tag>
- <item>This is maps to the corresponding functions in the
- <c>ttb</c> module in the <c>observer</c>
- application. <c>tp</c> means set trace pattern on global
- function calls. <c>tpl</c> means set trace pattern on local
- and global function calls.
- </item>
- <tag><c>ClearTP = ctp | ctpl | ctpg</c></tag>
- <item>This is maps to the corresponding functions in the
- <c>ttb</c> module in the <c>observer</c>
- application. <c>ctp</c> means clear trace pattern (i.e. turn
- off) on global and local function calls. <c>ctpl</c> means
- clear trace pattern on local function calls only and <c>ctpg</c>
- means clear trace pattern on global function calls only.
- </item>
- <tag><c>Module = atom()</c></tag>
- <item>The module to trace
- </item>
- <tag><c>Function = atom()</c></tag>
- <item>The name of the function to trace
- </item>
- <tag><c>Arity = integer()</c></tag>
- <item>The arity of the function to trace
- </item>
- <tag><c>Pattern = [] | match_spec()</c></tag>
- <item>The trace pattern to set for the module or
- function. For a description of the match_spec() syntax,
- please turn to the User's guide for the runtime system
- (erts). The chapter "Match Specification in Erlang" explains
- the general match specification language.
- </item>
- </taglist>
- <p>The trace result will be logged in a (binary) file called
- <c>NodeName-test_server</c> in the current directory of the
- test server controller node. The log must be formatted using
- <c>ttb:format/1/2</c>.
- </p>
- </desc>
- </func>
- <func>
- <name>stop_trace() -> ok | {error, not_tracing}</name>
- <fsummary>Stops tracing on target and slave nodes.</fsummary>
- <desc>
- <p>This function stops tracing on target, and on slave or peer
- nodes that are currently running. New slave or peer nodes will
- no longer be traced after this.</p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>FUNCTIONS INVOKED FROM COMMAND LINE</title>
- <p>The following functions are supposed to be invoked from the
- command line using the <c>-s</c> option when starting the erlang
- node.</p>
- </section>
- <funcs>
- <func>
- <name>run_test(CommandLine) -> ok</name>
- <fsummary>Runs the tests specified on the command line.</fsummary>
- <type>
- <v>CommandLine = FlagList</v>
- </type>
- <desc>
- <p>This function is supposed to be invoked from the
- commandline. It starts the test server, interprets the
- argument supplied from the commandline, runs the tests
- specified and when all tests are done, stops the test server
- and returns to the Erlang prompt.
- </p>
- <p>The <c>CommandLine</c> argument is a list of command line
- flags, typically <c>['KEY1', Value1, 'KEY2', Value2, ...]</c>.
- The valid command line flags are listed below.
- </p>
- <p>Under a UNIX command prompt, this function can be invoked like this:
- <br></br>
-<c>erl -noshell -s test_server_ctrl run_test KEY1 Value1 KEY2 Value2 ... -s erlang halt</c></p>
- <p>Or make an alias (this is for unix/tcsh) <br></br>
-<c>alias erl_test 'erl -noshell -s test_server_ctrl run_test \!* -s erlang halt'</c></p>
- <p>And then use it like this <br></br>
-<c>erl_test KEY1 Value1 KEY2 Value2 ...</c> <br></br>
-</p>
- <p>The valid command line flags are</p>
- <taglist>
- <tag><c>DIR dir</c></tag>
- <item>Adds all test modules in the directory <c>dir</c> to
- the job queue.
- </item>
- <tag><c>MODULE mod</c></tag>
- <item>Adds the module <c>mod</c> to the job queue.
- </item>
- <tag><c>CASE mod case</c></tag>
- <item>Adds the case <c>case</c> in module <c>mod</c> to the
- job queue.
- </item>
- <tag><c>SPEC spec</c></tag>
- <item>Runs the test specification file <c>spec</c>.
- </item>
- <tag><c>SKIPMOD mod</c></tag>
- <item>Skips all test cases in the module <c>mod</c></item>
- <tag><c>SKIPCASE mod case</c></tag>
- <item>Skips the test case <c>case</c> in module <c>mod</c>.
- </item>
- <tag><c>NAME name</c></tag>
- <item>Names the test suite to something else than the
- default name. This does not apply to <c>SPEC</c> which keeps
- its names.
- </item>
- <tag><c>COVER app cover_file analyse</c></tag>
- <item>Indicates that the test should be run with cover
- analysis. <c>app</c>, <c>cover_file</c> and <c>analyse</c>
- corresponds to the parameters to
- <c>test_server_ctrl:cover/3</c>. If no cover file is used,
- the atom <c>none</c> should be given.
- </item>
- <tag><c>TRACE traceinfofile</c></tag>
- <item>Specifies a trace information file. When this option
- is given, call tracing is started on the target node and all
- slave or peer nodes that are started. The trace information
- file specifies which modules and functions to trace. See the
- function <c>trc/1</c> above for more information about the
- syntax of this file.
- </item>
- </taglist>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>FRAMEWORK CALLBACK FUNCTIONS</title>
- <p>A test server framework can be defined by setting the
- environment variable <c>TEST_SERVER_FRAMEWORK</c> to a module
- name. This module will then be framework callback module, and it
- must export the following function:</p>
- </section>
- <funcs>
- <func>
- <name>get_suite(Mod,Func) -> TestCaseList</name>
- <fsummary>Get subcases.</fsummary>
- <type>
- <v>Mod = atom()</v>
- <d>Test suite name.</d>
- <v>Func = atom()</v>
- <d>Name of test case.</d>
- <v>TestCaseList = [SubCase]</v>
- <d>List of test cases.</d>
- <v>SubCase = atom()</v>
- <d>Name of a case.</d>
- </type>
- <desc>
- <p>This function is called before a test case is started. The
- purpose is to retrieve a list of subcases. The default
- behaviour of this function should be to call
- <c>Mod:Func(suite)</c> and return the result from this call.</p>
- </desc>
- </func>
- <func>
- <name>init_tc(Mod,Func,Args0) -> {ok,Args1} | {skip,ReasonToSkip} | {auto_skip,ReasonToSkip} | {fail,ReasonToFail}</name>
- <fsummary>Preparation for a test case or configuration function.</fsummary>
- <type>
- <v>Mod = atom()</v>
- <d>Test suite name.</d>
- <v>Func = atom()</v>
- <d>Name of test case or configuration function.</d>
- <v>Args0 = Args1 = [tuple()]</v>
- <d>Normally Args = [Config]</d>
- <v>ReasonToSkip = term()</v>
- <d>Reason to skip the test case or configuration function.</d>
- <v>ReasonToFail = term()</v>
- <d>Reason to fail the test case or configuration function.</d>
- </type>
- <desc>
- <p>This function is called before a test case or configuration
- function starts. It is called on the process executing the function
- <c>Mod:Func</c>. Typical use of this function can be to alter
- the input parameters to the test case function (<c>Args</c>) or
- to set properties for the executing process.</p>
- <p>By returning <c>{skip,Reason}</c>, <c>Func</c> gets skipped.
- <c>Func</c> also gets skipped if <c>{auto_skip,Reason}</c> is returned,
- but then gets an auto skipped status (rather than user skipped).</p>
- <p>To fail <c>Func</c> immediately instead of executing it, return
- <c>{fail,ReasonToFail}.</c></p>
- </desc>
- </func>
- <func>
- <name>end_tc(Mod,Func,Status) -> ok | {fail,ReasonToFail}</name>
- <fsummary>Cleanup after a test case or configuration function.</fsummary>
- <type>
- <v>Mod = atom()</v>
- <d>Test suite name.</d>
- <v>Func = atom()</v>
- <d>Name of test case or configuration function.</d>
- <v>Status = {Result,Args} | {TCPid,Result,Args}</v>
- <d>The status of the test case or configuration function.</d>
- <v>ReasonToFail = term()</v>
- <d>Reason to fail the test case or configuration function.</d>
- <v>Result = ok | Skip | Fail</v>
- <d>The final result of the test case or configuration function.</d>
- <v>TCPid = pid()</v>
- <d>Pid of the process executing Func</d>
- <v>Skip = {skip,SkipReason}</v>
- <v>SkipReason = term() | {failed,{Mod,init_per_testcase,term()}}</v>
- <d>Reason why the function was skipped.</d>
- <v>Fail = {error,term()} | {'EXIT',term()} | {timetrap_timeout,integer()} |
- {testcase_aborted,term()} | testcase_aborted_or_killed |
- {failed,term()} | {failed,{Mod,end_per_testcase,term()}}</v>
- <d>Reason why the function failed.</d>
- <v>Args = [tuple()]</v>
- <d>Normally Args = [Config]</d>
- </type>
- <desc>
- <p>This function is called when a test case, or a configuration function,
- is finished. It is normally called on the process where the function
- <c>Mod:Func</c> has been executing, but if not, the pid of the test
- case process is passed with the <c>Status</c> argument.</p>
- <p>Typical use of the <c>end_tc/3</c> function can be to clean up
- after <c>init_tc/3</c>.</p>
- <p>If <c>Func</c> is a test case, it is possible to analyse the value of
- <c>Result</c> to verify that <c>init_per_testcase/2</c> and
- <c>end_per_testcase/2</c> executed successfully.</p>
- <p>It is possible with <c>end_tc/3</c> to fail an otherwise successful
- test case, by returning <c>{fail,ReasonToFail}</c>. The test case <c>Func</c>
- will be logged as failed with the provided term as reason.</p>
- </desc>
- </func>
- <func>
- <name>report(What,Data) -> ok</name>
- <fsummary>Progress report for test.</fsummary>
- <type>
- <v>What = atom()</v>
- <v>Data = term()</v>
- </type>
- <desc>
- <p>This function is called in order to keep the framework up-to-date with
- the progress of the test. This is useful e.g. if the
- framework implements a GUI where the progress information is
- constantly updated. The following can be reported:
- </p>
- <p><c>What = tests_start, Data = {Name,NumCases}</c><br></br>
- <c>What = loginfo, Data = [{topdir,TestRootDir},{rundir,CurrLogDir}]</c><br></br>
- <c>What = tests_done, Data = {Ok,Failed,{UserSkipped,AutoSkipped}}</c><br></br>
- <c>What = tc_start, Data = {{Mod,{Func,GroupName}},TCLogFile}</c><br></br>
- <c>What = tc_done, Data = {Mod,{Func,GroupName},Result}</c><br></br>
- <c>What = tc_user_skip, Data = {Mod,{Func,GroupName},Comment}</c><br></br>
- <c>What = tc_auto_skip, Data = {Mod,{Func,GroupName},Comment}</c><br></br>
- <c>What = framework_error, Data = {{FWMod,FWFunc},Error}</c></p>
- <p>Note that for a test case function that doesn't belong to a group,
- <c>GroupName</c> has value <c>undefined</c>, otherwise the name of the test
- case group.</p>
- </desc>
- </func>
- <func>
- <name>error_notification(Mod, Func, Args, Error) -> ok</name>
- <fsummary>Inform framework of crashing testcase or configuration function.</fsummary>
- <type>
- <v>Mod = atom()</v>
- <d>Test suite name.</d>
- <v>Func = atom()</v>
- <d>Name of test case or configuration function.</d>
- <v>Args = [tuple()]</v>
- <d>Normally Args = [Config]</d>
- <v>Error = {Reason,Location}</v>
- <v>Reason = term()</v>
- <d>Reason for termination.</d>
- <v>Location = unknown | [{Mod,Func,Line}]</v>
- <d>Last known position in Mod before termination.</d>
- <v>Line = integer()</v>
- <d>Line number in file Mod.erl.</d>
- </type>
- <desc>
- <p>This function is called as the result of function <c>Mod:Func</c> failing
- with Reason at Location. The function is intended mainly to aid
- specific logging or error handling in the framework application. Note
- that for Location to have relevant values (i.e. other than unknown),
- the <c>line</c> macro or <c>test_server_line</c> parse transform must
- be used. For details, please see the section about test suite line numbers
- in the <c>test_server</c> reference manual page.</p>
- </desc>
- </func>
- <func>
- <name>warn(What) -> boolean()</name>
- <fsummary>Ask framework if test server should issue a warning for What.</fsummary>
- <type>
- <v>What = processes | nodes</v>
- </type>
- <desc>
- <p>The test server checks the number of processes and nodes
- before and after the test is executed. This function is a
- question to the framework if the test server should warn when
- the number of processes or nodes has changed during the test
- execution. If <c>true</c> is returned, a warning will be written
- in the test case minor log file.</p>
- </desc>
- </func>
- <func>
- <name>target_info() -> InfoStr</name>
- <fsummary>Print info about the target system to the test case log.</fsummary>
- <type>
- <v>InfoStr = string() | ""</v>
- </type>
- <desc>
- <p>The test server will ask the framework for information about
- the test target system and print InfoStr in the test case
- log file below the host information.</p>
- </desc>
- </func>
- </funcs>
-</erlref>
-
diff --git a/lib/test_server/doc/src/test_spec_chapter.xml b/lib/test_server/doc/src/test_spec_chapter.xml
deleted file mode 100644
index 0a62010364..0000000000
--- a/lib/test_server/doc/src/test_spec_chapter.xml
+++ /dev/null
@@ -1,375 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2002</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Test Structure and Test Specifications</title>
- <prepared>Siri Hansen</prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>test_spec_chapter.xml</file>
- </header>
-
- <section>
- <title>Test structure</title>
- <p>A test consists of a set of test cases. Each test case is
- implemented as an erlang function. An erlang module implementing
- one or more test cases is called a test suite.
- </p>
- </section>
-
- <section>
- <title>Test specifications</title>
- <p>A test specification is a specification of which test suites
- and test cases to run and which to skip. A test specification can
- also group several test cases into conf cases with init and
- cleanup functions (see section about configuration cases
- below). In a test there can be test specifications on three
- different levels:
- </p>
- <p>The top level is a test specification file which roughly
- specifies what to test for a whole application. The test
- specification in such a file is encapsulated in a topcase
- command.
- </p>
- <p>Then there is a test specification for each test suite,
- specifying which test cases to run within the suite. The test
- specification for a test suite is returned from the
- <c>all(suite)</c> function in the test suite module.
- </p>
- <p>And finally there can be a test specification per test case,
- specifying sub test cases to run. The test specification for a
- test case is returned from the specification clause of the test
- case.
- </p>
- <p>When a test starts, the total test specification is built in a
- tree fashion, starting from the top level test specification.
- </p>
- <p>The following are the valid elements of a test
- specification. The specification can be one of these elements or a
- list with any combination of the elements:
- </p>
- <taglist>
- <tag><c>{Mod, Case}</c></tag>
- <item>This specifies the test case Mod:Case/1
- </item>
- <tag><c>{dir, Dir}</c></tag>
- <item>This specifies all modules <c>*_SUITE</c> in the directory
- <c>Dir</c></item>
- <tag><c>{dir, Dir, Pattern}</c></tag>
- <item>This specifies all modules <c>Pattern*</c> in the
- directory <c>Dir</c></item>
- <tag><c>{conf, Init, TestSpec, Fin}</c></tag>
- <item>This is a configuration case. In a test specification
- file, <c>Init</c> and <c>Fin</c> must be
- <c>{Mod,Func}</c>. Inside a module they can also be just
- <c>Func</c>. See the section named Configuration Cases below for
- more information about this.
- </item>
- <tag><c>{conf, Properties, Init, TestSpec, Fin}</c></tag>
- <item>This is a configuration case as explained above, but
- which also takes a list of execution properties for its group
- of test cases and nested sub-groups.
- </item>
- <tag><c>{make, Init, TestSpec, Fin}</c></tag>
- <item>This is a special version of a conf case which is only
- used by the test server framework <c>ts</c>. <c>Init</c> and
- <c>Fin</c> are make and unmake functions for a data
- directory. <c>TestSpec</c> is the test specification for the
- test suite owning the data directory in question. If the make
- function fails, all tests in the test suite are skipped. The
- difference between this "make case" and a normal conf case is
- that for the make case, <c>Init</c> and <c>Fin</c> are given with
- arguments (<c>{Mod,Func,Args}</c>).
- </item>
- <tag><c>Case</c></tag>
- <item>This can only be used inside a module, i.e. not a test
- specification file. It specifies the test case
- <c>CurrentModule:Case</c>.
- </item>
- </taglist>
- </section>
-
- <section>
- <title>Test Specification Files</title>
- <p>A test specification file is a text file containing the top
- level test specification (a topcase command), and possibly one or
- more additional commands. A "command" in a test specification file
- means a key-value tuple ended by a dot-newline sequence.
- </p>
- <p>The following commands are valid:
- </p>
- <taglist>
- <tag><c>{topcase, TestSpec}</c></tag>
- <item>This command is mandatory in all test specification
- files. <c>TestSpec</c> is the top level test specification of a
- test.
- </item>
- <tag><c>{skip, {Mod, Comment}}</c></tag>
- <item>This specifies that all cases in the module <c>Mod</c>
- shall be skipped. <c>Comment</c> is a string.
- </item>
- <tag><c>{skip, {Mod, Case, Comment}}</c></tag>
- <item>This specifies that the case <c>Mod:Case</c> shall be
- skipped.
- </item>
- <tag><c>{skip, {Mod, CaseList, Comment}}</c></tag>
- <item>This specifies that all cases <c>Mod:Case</c>, where
- <c>Case</c> is in <c>CaseList</c>, shall be skipped.
- </item>
- <tag><c>{nodes, Nodes}</c></tag>
- <item><c>Nodes</c> is a list of nodenames available to the test
- suite. It will be added to the <c>Config</c> argument to all
- test cases. <c>Nodes</c> is a list of atoms.
- </item>
- <tag><c>{require_nodenames, Num}</c></tag>
- <item>Specifies how many nodenames the test suite will
- need. Theese will be automatically generated and inserted into the
- <c>Config</c> argument to all test cases. <c>Num</c> is an
- integer.
- </item>
- <tag><c>{hosts, Hosts}</c></tag>
- <item>This is a list of available hosts on which to start slave
- nodes. It is used when the <c>{remote, true}</c> option is given
- to the <c>test_server:start_node/3</c> function. Also, if
- <c>{require_nodenames, Num}</c> is contained in a test
- specification file, the generated nodenames will be spread over
- all hosts given in this <c>Hosts</c> list. The hostnames are
- atoms or strings.
- </item>
- <tag><c>{diskless, true}</c></tag>
- <item>Adds <c>{diskless, true}</c> to the <c>Config</c> argument
- to all test cases. This is kept for backwards compatibility and
- should not be used. Use a configuration case instead.
- </item>
- <tag><c>{ipv6_hosts, Hosts}</c></tag>
- <item>Adds <c>{ipv6_hosts, Hosts}</c> to the <c>Config</c>
- argument to all test cases.</item>
- </taglist>
- <p>All test specification files shall have the extension
- ".spec". If special test specification files are needed for
- Windows or VxWorks platforms, additional files with the
- extension ".spec.win" and ".spec.vxworks" shall be
- used. This is useful e.g. if some test cases shall be skipped on
- these platforms.
- </p>
- <p>Some examples for test specification files can be found in the
- Examples section of this user's guide.
- </p>
- </section>
-
- <section>
- <title>Configuration cases</title>
- <p>If a group of test cases need the same initialization, a so called
- <em>configuration</em> or <em>conf</em> case can be used. A conf
- case consists of an initialization function, the group of test cases
- needing this initialization and a cleanup or finalization function.
- </p>
- <p>If the init function in a conf case fails or returns
- <c>{skip,Comment}</c>, the rest of the test cases in the conf case
- (including the cleanup function) are skipped. If the init function
- succeeds, the cleanup function will always be called, even if some
- of the test cases in between failed.
- </p>
- <p>Both the init function and the cleanup function in a conf case
- get the <c>Config</c> parameter as only argument. This parameter
- can be modified or returned as is. Whatever is returned by the
- init function is given as <c>Config</c> parameter to the rest of
- the test cases in the conf case, including the cleanup function.
- </p>
- <p>If the <c>Config</c> parameter is changed by the init function,
- it must be restored by the cleanup function. Whatever is returned
- by the cleanup function will be given to the next test case called.
- </p>
- <p>The optional <c>Properties</c> list can be used to specify
- execution properties for the test cases and possibly nested
- sub-groups of the configuration case. The available properties are:</p>
- <pre>
- Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
- Shuffle = shuffle | {shuffle,Seed}
- Seed = {integer(),integer(),integer()}
- RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
- repeat_until_any_ok | repeat_until_any_fail
- N = integer() | forever</pre>
-
- <p>If the <c>parallel</c> property is specified, Test Server will execute
- all test cases in the group in parallel. If <c>sequence</c> is specified,
- the cases will be executed in a sequence, meaning if one case fails, all
- following cases will be skipped. If <c>shuffle</c> is specified, the cases
- in the group will be executed in random order. The <c>repeat</c> property
- orders Test Server to repeat execution of the cases in the group a given
- number of times, or until any, or all, cases fail or succeed.</p>
-
- <p>Properties may be combined so that e.g. if <c>shuffle</c>,
- <c>repeat_until_any_fail</c> and <c>sequence</c> are all specified, the test
- cases in the group will be executed repeatedly and in random order until
- a test case fails, when execution is immediately stopped and the rest of
- the cases skipped.</p>
-
- <p>The properties for a conf case is always printed on the top of the HTML log
- for the group's init function. Also, the total execution time for a conf case
- can be found at the bottom of the log for the group's end function.</p>
-
- <p>Configuration cases may be nested so that sets of grouped cases can be
- configured with the same init- and end functions.</p>
- </section>
-
- <section>
- <title>The parallel property and nested configuration cases</title>
- <p>If a conf case has a parallel property, its test cases will be spawned
- simultaneously and get executed in parallel. A test case is not allowed
- to execute in parallel with the end function however, which means
- that the time it takes to execute a set of parallel cases is equal to the
- execution time of the slowest test case in the group. A negative side
- effect of running test cases in parallel is that the HTML summary pages
- are not updated with links to the individual test case logs until the
- end function for the conf case has finished.</p>
-
- <p>A conf case nested under a parallel conf case will start executing in
- parallel with previous (parallel) test cases (no matter what properties the
- nested conf case has). Since, however, test cases are never executed in
- parallel with the init- or the end function of the same conf case, it's
- only after a nested group of cases has finished that any remaining parallel
- cases in the previous conf case get spawned.</p>
- </section>
-
- <section>
- <title>Repeated execution of test cases</title>
- <marker id="repeated_cases"></marker>
- <p>A conf case may be repeated a certain number of times
- (specified by an integer) or indefinitely (specified by <c>forever</c>).
- The repetition may also be stopped prematurely if any or all cases
- fail or succeed, i.e. if the property <c>repeat_until_any_fail</c>,
- <c>repeat_until_any_ok</c>, <c>repeat_until_all_fail</c>, or
- <c>repeat_until_all_ok</c> is used. If the basic <c>repeat</c>
- property is used, status of test cases is irrelevant for the repeat
- operation.</p>
-
- <p>It is possible to return the status of a conf case (ok or
- failed), to affect the execution of the conf case on the level above.
- This is accomplished by, in the end function, looking up the value
- of <c>tc_group_properties</c> in the <c>Config</c> list and checking the
- result of the finished test cases. If status <c>failed</c> should be
- returned from the conf case as a result, the end function should return
- the value <c>{return_group_result,failed}</c>. The status of a nested conf
- case is taken into account by Test Server when deciding if execution
- should be repeated or not (unless the basic <c>repeat</c> property is used).</p>
-
- <p>The <c>tc_group_properties</c> value is a list of status tuples,
- each with the key <c>ok</c>, <c>skipped</c> and <c>failed</c>. The
- value of a status tuple is a list containing names of test cases
- that have been executed with the corresponding status as result.</p>
-
- <p>Here's an example of how to return the status from a conf case:</p>
- <pre>
- conf_end_function(Config) ->
- Status = ?config(tc_group_result, Config),
- case proplists:get_value(failed, Status) of
- [] -> % no failed cases
- {return_group_result,ok};
- _Failed -> % one or more failed
- {return_group_result,failed}
- end.</pre>
-
- <p>It is also possible in the end function to check the status of
- a nested conf case (maybe to determine what status the current conf case should
- return). This is as simple as illustrated in the example above, only the
- name of the end function of the nested conf case is stored in a tuple
- <c>{group_result,EndFunc}</c>, which can be searched for in the status lists.
- Example:</p>
- <pre>
- conf_end_function_X(Config) ->
- Status = ?config(tc_group_result, Config),
- Failed = proplists:get_value(failed, Status),
- case lists:member({group_result,conf_end_function_Y}, Failed) of
- true ->
- {return_group_result,failed};
- false ->
- {return_group_result,ok}
- end;
- ...</pre>
-
- <note><p>When a conf case is repeated, the init- and end functions
- are also always called with each repetition.</p></note>
- </section>
-
- <section>
- <title>Shuffled test case order</title>
- <p>The order that test cases in a conf case are executed, is under normal
- circumstances the same as the order defined in the test specification.
- With the <c>shuffle</c> property set, however, Test Server will instead
- execute the test cases in random order.</p>
-
- <p>The user may provide a seed value (a tuple of three integers) with
- the shuffle property: <c>{shuffle,Seed}</c>. This way, the same shuffling
- order can be created every time the conf case is executed. If no seed value
- is given, Test Server creates a "random" seed for the shuffling operation
- (using the return value of <c>erlang:now()</c>). The seed value is always
- printed to the log file of the init function so that it can be used to
- recreate the same execution order in subsequent test runs.</p>
-
- <note><p>If execution of a conf case with shuffled test cases is repeated,
- the seed will not be reset in between turns.</p></note>
-
- <p>If a nested conf case is specified in a conf case with a <c>shuffle</c>
- property, the execution order of the nested cases in relation to the test cases
- (and other conf cases) is also random. The order of the test cases in the nested
- conf case is however not random (unless, of course, this one also has a
- <c>shuffle</c> property).</p>
- </section>
-
- <section>
- <title>Skipping test cases</title>
- <p>It is possible to skip certain test cases, for example if you
- know beforehand that a specific test case fails. This might be
- functionality which isn't yet implemented, a bug that is known but
- not yet fixed or some functionality which doesn't work or isn't
- applicable on a specific platform.
- </p>
- <p>There are several different ways to state that a test case
- should be skipped:</p>
- <list type="bulleted">
- <item>Using the <c>{skip,What}</c> command in a test
- specification file
- </item>
- <item>Returning <c>{skip,Reason}</c> from the
- <c>init_per_testcase/2</c> function
- </item>
- <item>Returning <c>{skip,Reason}</c> from the specification
- clause of the test case
- </item>
- <item>Returning <c>{skip,Reason}</c> from the execution clause
- of the test case
- </item>
- </list>
- <p>The latter of course means that the execution clause is
- actually called, so the author must make sure that the test case
- is not run. For more information about the different clauses in a
- test case, see the chapter about writing test cases.
- </p>
- <p>When a test case is skipped, it will be noted as <c>SKIPPED</c>
- in the HTML log.
- </p>
- </section>
-</chapter>
-
diff --git a/lib/test_server/doc/src/ts.xml b/lib/test_server/doc/src/ts.xml
deleted file mode 100644
index 60dfdbc545..0000000000
--- a/lib/test_server/doc/src/ts.xml
+++ /dev/null
@@ -1,568 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2007</year>
- <year>2013</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- 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.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>The OTP Test Server Framework</title>
- <prepared>Mattias Nilsson</prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date></date>
- <rev></rev>
- <file>ts.xml</file>
- </header>
- <module>ts</module>
- <modulesummary>Test Server Framework for testing OTP</modulesummary>
- <description>
- <p>This is a framework for testing OTP. The <c>ts</c> module
- implements the interface to all the functionality in the
- framework.
- </p>
- <p>The framework is built on top of the Test Server Controller,
- <c>test_server_ctrl</c>, and provides a high level operator
- interface. The main features added by the framework are:
- </p>
- <list type="bulleted">
- <item>Automatic compilation of test suites and data directories
- </item>
- <item>Collection of files in central directories and creation of
- additional HTML pages for better overview.
- </item>
- <item>Single command interface for running all available tests
- </item>
- <item>Spawns a new node with correct parameters before starting
- the test server
- </item>
- <item>Atomatically creates the parameter file needed when
- running tests on remote target
- </item>
- </list>
- <p>More information about the Test Server Framework and how to run
- test cases can be found in the Test Server User's Guide.
- </p>
- <p>For writing you own test server framework, please turn to the
- reference manual for the Test Server Controller and chapter named
- "Writing your own test server framework" in the Test Server User's
- Guide.
- </p>
- <p>SETUP</p>
- <p>To be able to run <c>ts</c>, you must first `install'
- <c>ts</c> for the current environment. This is done by calling
- <c>ts:install/0/1/2</c>. A file called `variables' is created
- and used by <c>ts</c> when running test suites. It is not
- recommended to edit this file, but it is possible to alter if
- <c>ts</c> gets the wrong idea about your environment.
- </p>
- <p><c>ts:install/0</c> is used if the target platform is the
- same as the controller host, i.e. if you run on "local target"
- and no options are needed. Then running <c>ts:install/0</c> <c>ts</c>
- will run an autoconf script for your current
- environment and set up the necessary variables needed by the
- test suites.
- </p>
- <p><c>ts:install/1</c> or <c>ts:install/2</c> is used if the
- target platform is different from the controller host, i.e. if
- you run on "remote target" or if special options are required
- for your system.
- </p>
- <p>See the reference manual for detailed information about
- <c>ts:install/0/1/2</c>.
- </p>
- <p>Some of the common variables in the 'variables' file are
- described below. Do not make any assumptions as of what is found
- in this file, as it may change at any time.
- </p>
- <list>
- <item><c>longnames</c><br></br>
- Set to true if the system is using fully qualified
- nodenames.
- </item>
- <item><c>platform_id</c><br></br>
- This is the currently installed platform identification
- string.
- </item>
- <item><c>platform_filename</c><br></br>
- This is the name used to create the final save directory
- for test runs.
- </item>
- <item><c>platform_label</c><br></br>
- This is the string presented in the generated test
- results index page.
- </item>
- <item><c>rsh_name</c><br></br>
- This is the rsh program to use when starting slave or
- peer nodes on a remote host.
- </item>
- <item><c>erl_flags</c><br></br>
- Compile time flags used when compiling test suites.
- </item>
- <item><c>erl_release</c><br></br>
- The Erlang/OTP release being tested.
- </item>
- <item><c>'EMULATOR'</c><br></br>
- The emulator being tested (e.g. beam)
- </item>
- <item><c>'CPU'</c><br></br>
- The CPU in the machine running the tests, e.g. sparc.
- </item>
- <item><c>target_host</c><br></br>
- The target host name
- </item>
- <item><c>os</c><br></br>
- The target operating system, e.g. solaris2.8
- </item>
- <item><c>target</c><br></br>
- The current target platform, e.g. sparc-sun-solaris2.8
- </item>
- </list>
- <p>RUNNING TESTS</p>
- <p>After installing <c>ts</c>, you can run your test with the
- <c>ts:run/0/1/2/3/4</c> functions. These functions, however,
- require a special directory structure to be able to find your
- test suites. Both the test server and all tests must be located
- under your $TESTROOT directory. The test server implementation
- shall be located in the directory <c>$TESTROOT/test_server</c>
- and for each application there must be a directory named
- <c><![CDATA[$TESTROOT/<application>_test]]></c> containing the .spec file
- and all test suites and data directories for the
- application. Note that there shall only be one .spec file for
- each application.
- </p>
- <p><c>$TESTROOT/test_server</c> must be the current directory
- when calling the <c>ts:run/*</c> function.
- </p>
- <p>All available tests can be found with <c>ts:tests()</c>. This
- will list all applications for which a test specification file
- <c><![CDATA[../<application>_test/<application>.spec]]></c> can be found.
- </p>
- <p>To run all these tests, use <c>ts:run()</c>.
- </p>
- <p>To run one or some of the tests, use <c>ts:run(Tests)</c>,
- where <c>Tests</c> is the name of the application you want to
- test, or a list of such names.
- </p>
- <p>To run one test suite within a test, use
- <c>ts:run(Test,Suite)</c>.
- </p>
- <p>To run one test case within a suite, use
- <c>ts:run(Test,Suite,Case)</c></p>
- <p>To all these functions, you can also add a list of
- options. Please turn to the reference manual for the <c>ts</c>
- module to see the valid options to use.
- </p>
- <p>The function <c>ts:help()</c> displays some simple help for
- the functions in <c>ts</c>. Use this for quick reference.
- </p>
- <p>LOG FILES</p>
- <p>As the execution of the test suites go on, events are logged in
- four different ways:
- </p>
- <list type="bulleted">
- <item>Text to the operator's console.</item>
- <item>Suite related information is sent to the major log file.</item>
- <item>Case related information is sent to the minor log file.</item>
- <item>The HTML log file gets updated with test results.</item>
- </list>
- <p>Typically the operator, who may run hundreds or thousands of
- test cases, doesn't want to fill the screen with details
- about/from the specific test cases. By default, the operator will
- only see:
- </p>
- <list type="bulleted">
- <item>A confirmation that the test has started.
- </item>
- <item>A small note about each failed test case.
- </item>
- <item>A summary of all the run test cases.
- </item>
- <item>A confirmation that the test run is complete
- </item>
- <item>Some special information like error reports and progress
- reports, printouts written with erlang:display/1 or io:format/3
- specifically addressed to somewhere other than
- <c>standard_io</c>.</item>
- </list>
- <p>This is enough for the operator to know, and if he wants to dig
- in deeper into a specific test case result, he can do so by
- following the links in the HTML presentation to take a look in the
- major or minor log files.
- </p>
- <p>A detailed report of the entire test suite is stored in the
- major logfile, the exact reason for failure, time spent etc.
- </p>
- <p>The HTML log file is a summary of the major log file, but gives
- a much better overview of the test run. It also has links to every
- test case's log file for quick viewing with a HTML browser.
- </p>
- <p>The minor log file contain full details of every single test
- case, each one in a separate file. This way the files should be
- easy to compare with previous test runs, even if the set of test
- cases change.
- </p>
- <p>Which information that goes where is user configurable via the
- test server controller. Three threshold values determine what
- comes out on screen, and in the major or minor log files. The
- contents that goes to the HTML log file is fixed, and cannot be
- altered.
- </p>
-
- </description>
- <funcs>
- <func>
- <name>install() -> ok | {error, Reason}</name>
- <name>install(TargetSystem) -> ok | {error, Reason}</name>
- <name>install(Opts) -> ok | {error, Reason}</name>
- <name>install(TargetSystem,Opts) -> ok | {error, Reason}</name>
- <fsummary>Installs the Test Server Framework</fsummary>
- <type>
- <v>TargetSystem = {Architecture, TargetHost}</v>
- <v>Architecture = atom() or string()</v>
- <d>e.g. "ose" or "vxworks_ppc603"</d>
- <v>TargetHost = atom() or string()</v>
- <d>The name of the target host</d>
- <v>Opts = list()</v>
- </type>
- <desc>
- <p>Installs and configures the Test Server Framework for
- running test suites. If a remote host is to be used, the
- <c>TargetSystem</c> argument must be given so that "cross
- installation" can be done. Installation is required for
- any of the functions in <c>ts</c> to work.
- </p>
- <p>Opts may be one or more of
- </p>
- <list>
- <item><c>{longnames, Bool}</c><br></br>
- Use fully qualified hostnames for test_server and
- slave nodes. Bool is <c>true</c> or <c>false</c> (default).
- </item>
- <item><c>{verbose, Level}</c><br></br>
- Verbosity level for test server output, set to 0, 1 or
- 2, where 0 is quiet(default).
- </item>
- <item><c>{hosts, Hosts}</c><br></br>
- This is a list of available hosts on which to start
- slave nodes. It is used when the <c>{remote, true}</c>
- option is given to the <c>test_server:start_node/3</c>
- function. Also, if <c>{require_nodenames, Num}</c> is
- contained in a test specification file, the generated
- nodenames will be spread over all hosts given in this
- <c>Hosts</c> list. The hostnames are given as atoms or
- strings.
- </item>
- <item><c>{slavetargets, SlaveTarges}</c><br></br>
- For VxWorks only. This is a list of
- available hosts where slave nodes can be started. This is
- necessary because only one node can run per host in the
- VxWorks environment. This is not the same as
- <c>{hosts, Hosts}</c> because it is used for all slave nodes
- - not only the ones started with <c>{remote, true}</c>. The
- hostnames are given as atoms or strings.
- </item>
- <item><c>{crossroot, TargetErlRoot}</c><br></br>
- Erlang root directory on target host
- <br></br>
-This option is mandatory for remote targets
- </item>
- <item><c>{master, {MasterHost, MasterCookie}}</c><br></br>
- If target is remote and the target node is started as
- a slave node, this option
- indicates which master and cookie to use. The given master
- will also be used as master for slave nodes started with
- <c>test_server:start_node/3</c>. It is expected that the
- <c>erl_boot_server</c> is started on the master node before
- the test is run. If this option is not given, the test
- server controller node is used as master and the
- <c>erl_boot_server</c> is automatically started.
- </item>
- <item><c>{erl_start_args, ArgString}</c><br></br>
- Additional arguments to be used when starting the test
- server controller node. <c>ArgString</c> will be appended to
- the command line when starting the erlang node. Note that
- this will only affect the startup of the <em>controller node</em>,
- i.e. not the target node or any slave nodes
- startet from a test case.
- </item>
- <item><c>{ipv6_hosts, HostList}</c><br></br>
- This option will be inserted in the
- <c>Config</c> parameter for each test case. <c>HostList</c>
- is a list of hosts supporting IPv6.
- </item>
- </list>
- </desc>
- </func>
- <func>
- <name>help() -> ok</name>
- <fsummary>Presents simple help on the functions in <c>ts</c></fsummary>
- <desc>
- <p>Presents simple help on the functions in <c>ts</c>. Useful
- for quick reference.</p>
- </desc>
- </func>
- <func>
- <name>tests() -> Tests</name>
- <fsummary>Returns the list of available tests</fsummary>
- <desc>
- <p>Returns the list of available tests. This is actually just
- a list of all test specification files found by looking up
- "../*_test/*.spec".
- </p>
- <p>In each ../Name_test/ directory there should be one test
- specification file named Name.spec.</p>
- </desc>
- </func>
- <func>
- <name>run() -> ok | {error, Reason}</name>
- <name>run([all_tests|Opts])</name>
- <name>run(Specs)</name>
- <name>run(Specs, Opts)</name>
- <name>run(Spec, Module)</name>
- <name>run(Spec, Module, Opts)</name>
- <name>run(Spec, Module, Case)</name>
- <name>run(Spec, Module, Case, Opts)</name>
- <fsummary>Runs (specified) test suite(s)</fsummary>
- <type>
- <v>Specs = Spec | [Spec]</v>
- <v>Spec = atom()</v>
- <v>Module = atom()</v>
- <v>Case = atom()</v>
- <v>Opts = [Opt]</v>
- <v>Opt = batch | verbose | {verbose, Level} | {vars, Vars} | keep_topcase | cover | cover_details |{cover,CoverFile} | {cover_details,CoverFile} | {trace, TraceSpec}</v>
- <v>Level = integer(); 0 means silent</v>
- <v>Vars = list() of key-value tuples</v>
- <v>CoverFile = string(); name of file listing modules to exclude from or include in cover compilation. The name must include full path to the file.</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>This function runs test suite(s)/case(s). To be able to run
- any tests, ts:install must first be called to create the
- <c>variables</c> file needed. To run a whole test specification,
- only specify the name of the test specification, and all test
- suite modules belonging to that test spec will be run. To run
- a single module in a test specification, use the Module
- argument to specify the name of the module to run and all test
- cases in that module will be run, and to run a specified test
- case, specify the name of the test case using the Case
- argument. If called with no argument, all test specifications
- available will be run. Use ts:tests/0 to see the available
- test specifications.
- </p>
- <p>If the <c>batch</c> option is not given, a new xterm is
- started (unix) when <c>ts:run</c> is called.
- </p>
- <p>The <c>verbose</c> option sets the verbosity level for test
- server output. This has the same effect as if given to
- <c>ts:install/1/2</c></p>
- <p>The <c>vars</c> option can be used for adding configuration
- variables that are not in the <c>variables</c> file generated
- during installation. Can be any of the <c>Opts</c> valid for
- <c>ts:install/1/2</c>.
- </p>
- <p>The <c>keep_topcase</c> option forces <c>ts</c> to keep the
- topcase in your test specification file as is. This option can
- only be used if you don't give the <c>Module</c> or
- <c>Case</c> parameters to <c>ts:run</c>. The
- <c>keep_topcase</c> option is necessary if your topcase
- contains anything other than <c><![CDATA[{dir,"../<Name>_test"}]]></c>. If
- the option is not used, <c>ts</c> will modify your topcase.
- </p>
- <p>The <c>cover</c> and <c>cover_details</c> options indicates
- that the test shall be run with code coverage
- analysis. <c>cover_details</c> means that analysis shall be
- done on the most detailed level. If the test is run with a
- remote target, this option creates a list of uncovered lines
- in each cover compiled module. If the test is run with a local
- target, each cover compiled module will be analysed with
- <c>cover:analyse_to_file/1</c>. The <c>cover</c> options will
- only create an overview of all cover compiled modules with the
- number of covered and not covered lines.
- </p>
- <p>The <c>CoverFile</c> which can be given with the
- <c>cover</c> and <c>cover_details</c> options must be the
- filename of a file listing modules to be excluded from or
- included in the cover compilation. By default, <c>ts</c>
- believes that <c>Spec</c> is the name of an OTP application
- and that all modules in this application shall be cover
- compiled. The <c>CoverFile</c> can exclude modules that belong
- to the application and add modules that don't belong to the
- application. The file can have the following entries:</p>
- <code type="none">
-{exclude, all | ExcludeModuleList}.
-{include, IncludeModuleList}. </code>
- <p>Note that each line must end with a full
- stop. <c>ExcludeModuleList</c> and <c>IncludeModuleList</c>
- are lists of atoms, where each atom is a module name.
- </p>
- <p>If the <c>cover</c> or <c>cover_details</c> options are
- given on their own, the directory <c><![CDATA[../<Spec>_test]]></c> is
- searched for a <c>CoverFile</c> named <c><![CDATA[<Spec>.cover]]></c>. If
- this file is not found, <c>Spec</c> is assumed to be the name
- of an OTP application, and all modules in the <c>ebin</c>
- directory for the application are cover compiled. The
- <c>ebin</c> directory is found by adding <c>ebin</c> to
- <c>code:lib_dir(Spec)</c>.
- </p>
- <p>The same cover compiled code will be loaded on all slave or
- peer nodes started with <c>test_server:start_node/3</c>. The
- exception is nodes that run an old version of OTP. If the loading
- fails, the node will simply not be a part of the coverage
- analysis. Note that slave and peer nodes must be stopped with
- <c>test_server:stop_node/1</c> for the node to be part of the
- coverage analysis, else the test server will not be able to
- fetch coverage data from the node.
- </p>
- <p>The <c>trace</c> option is used to turn on call trace on
- target and on slave or peer nodes started with
- <c>test_server:start_node/3</c>. <c>TraceSpec</c> can be the
- name of a trace information file, or a list of elements like
- the ones in a trace information file. Please turn to the
- reference manual for <c>test_server_ctrl:trc/1</c> for details
- about the trace information file.
- </p>
- </desc>
- </func>
- <func>
- <name>cross_cover_analyse(Level) -> ok</name>
- <name>cross_cover_analyse([Level]) -> ok</name>
- <fsummary>Analyse cover data collected from all tests</fsummary>
- <desc>
- <p>Analyse cover data collected from all tests.
- </p>
- <p>See test_server_ctrl:cross_cover_analyse/2
- </p>
- </desc>
- </func>
- <func>
- <name>r() -> ok</name>
- <name>r(Opts) -> ok</name>
- <name>r(SpecOrSuite) -> ok</name>
- <name>r(SpecOrSuite,Opts) -> ok</name>
- <name>r(Suite,Case) -> ok</name>
- <name>r(Suite,Case,Opts) -> ok</name>
- <fsummary>Run test suite or test case without <c>ts</c>installed</fsummary>
- <type>
- <v>SpecOrSuite = Spec | Suite</v>
- <v>Spec = string()</v>
- <d>"Name.spec" or "Name.spec.OsType", where OsType is vxworks</d>
- <v>Suite = atom()</v>
- <v>Case = atom()</v>
- <v>Opts = [Opt]</v>
- <v>Opt = {Cover,AppOrCoverFile} | {Cover,Application,CoverFile}</v>
- <v>Cover = cover | cover_details</v>
- <v>AppOrCoverFile = Application | CoverFile</v>
- <v>Application = atom()</v>
- <d>OTP application to cover compile</d>
- <v>CoverFile = string()</v>
- <d>Name of file listing modules to exclude from or include in cover compilation</d>
- </type>
- <desc>
- <p>This function can be used to run a test suites or test
- cases directly, without any of the additional features added
- by the test server framework. It is simply a wrapper function
- for the <c>add_dir</c>, <c>add_spec</c>, <c>add_module</c> and
- <c>add_case</c> functions in <c>test_server_ctrl</c>:
- </p>
- <p><c>r() -> add_dir(".")</c> <br></br>
-<c>r(Spec) -> add_spec(Spec)</c> <br></br>
-<c>r(Suite) -> add_module(Suite)</c> <br></br>
-<c>r(Suite,Case) -> add_case(Suite,Case)</c></p>
- <p>To use this function, it is required that the test suite is
- compiled and in the code path of the node where the function
- is called. The function can be used without having <c>ts</c>
- installed.
- </p>
- <p>For information about the <c>cover</c> and
- <c>cover_details</c> options, see <c>test_server_ctrl:cover/2/3</c>.</p>
- </desc>
- </func>
- <func>
- <name>estone() -> ok | {error, Reason}</name>
- <name>estone(Opts) -> ok</name>
- <fsummary>Runs the EStone test</fsummary>
- <desc>
- <p>This function runs the EStone test. It is a shortcut for
- running the test suite <c>estone_SUITE</c> in the
- <c>kernel</c> application.
- </p>
- <p><c>Opts</c> is the same as the <c>Opts</c> argument for the
- <c>ts:run</c> functions.</p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>Makfile.src in Data Directory</title>
- <p>If a data directory contains code which must be compiled before
- the test suite is run, a makefile source called
- <c>Makefile.src</c> can be placed in the data directory. This file
- will be converted to a valid makefile by <c>ts:run/0/1/2/3/4</c>.
- </p>
- <p>The reason for generating the makefile is that you can use
- variables from the <c>variables</c> file which was generated by
- <c>ts:install/0/1/2</c>. All occurrences of <c>@Key@</c> in
- <c>Makefile.src</c> is substituted by the <c>Value</c> from
- <c>{Key,Value}</c> found in the <c>variables</c> file. Example:
- </p>
- <p>Cut from <c>variables</c>:</p>
- <code type="none">
- ...
- {'EMULATOR',"beam"}.
- {'CFLAGS',"-g -O2"}.
- {'LD',"$(CC) $(CFLAGS)"}.
- {'CC',"gcc"}.
- ...
- </code>
- <p><c>Makefile.src</c> for compiling erlang code could look
- something like this:</p>
- <code type="none">
- EFLAGS=+debug_info
-
- all: ordsets1.@EMULATOR@
-
- ordsets1.@EMULATOR@: ordsets1.erl
- erlc $(EFLAGS) ordsets1.erl
- </code>
- <p><c>Makefile.src</c> for compiling c code could look
- something like this:</p>
- <code type="none">
- CC = @CC@
- LD = @LD@
- CFLAGS = @CFLAGS@ -I@erl_include@ @DEFS@
- CROSSLDFLAGS = @CROSSLDFLAGS@
-
- PROGS = nfs_check@exe@
-
- all: $(PROGS)
-
- nfs_check@exe@: nfs_check@obj@
- $(LD) $(CROSSLDFLAGS) -o nfs_check nfs_check@obj@ @LIBS@
-
- nfs_check@obj@: nfs_check.c
- $(CC) -c -o nfs_check@obj@ $(CFLAGS) nfs_check.c
- </code>
- </section>
-</erlref>
-
diff --git a/lib/test_server/doc/src/why_test_chapter.xml b/lib/test_server/doc/src/why_test_chapter.xml
deleted file mode 100644
index 3d0e8271b1..0000000000
--- a/lib/test_server/doc/src/why_test_chapter.xml
+++ /dev/null
@@ -1,141 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2002</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Why Test</title>
- <prepared>Siri Hansen</prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
-
- <section>
- <title>Goals</title>
- <p>It's not possible to prove that a program is correct by
- testing. On the contrary, it has been formally proven that it is
- impossible to prove programs in general by testing. Theoretical
- program proofs or plain examination of code may be viable options
- for those that wish to certify that a program is correct. The test
- server, as it is based on testing, cannot be used for
- certification. Its intended use is instead to (cost effectively)
- <em>find bugs</em>. A successful test suite is one that reveals a
- bug. If a test suite results in Ok, then we know very little that
- we didn't know before.
- </p>
- </section>
-
- <section>
- <title>What to test?</title>
- <p>There are many kinds of test suites. Some concentrate on
- calling every function in the interface to some module or
- server. Some other do the same, but uses all kinds of illegal
- parameters, and verifies that the server stays alive and rejects
- the requests with reasonable error codes. Some test suites
- simulate an application (typically consisting of a few modules of
- an application), some try to do tricky requests in general, some
- test suites even test internal functions.
- </p>
- <p>Another interesting category of test suites are the ones that
- check that fixed bugs don't reoccur. When a bugfix is introduced,
- a test case that checks for that specific bug should be written
- and submitted to the affected test suite(s).
- </p>
- <p>Aim for finding bugs. Write whatever test that has the highest
- probability of finding a bug, now or in the future. Concentrate
- more on the critical parts. Bugs in critical subsystems are a lot
- more expensive than others.
- </p>
- <p>Aim for functionality testing rather than implementation
- details. Implementation details change quite often, and the test
- suites should be long lived. Often implementation details differ
- on different platforms and versions. If implementation details
- have to be tested, try to factor them out into separate test
- cases. Later on these test cases may be rewritten, or just
- skipped.
- </p>
- <p>Also, aim for testing everything once, no less, no more. It's
- not effective having every test case fail just because one
- function in the interface changed.
- </p>
- </section>
-
- <section>
- <title>How much to test</title>
- <p>There is a unix shell script that counts the number of non
- commented words (lines and characters too) of source code in each
- application's test directory and divides with the number of such
- source words in the src directory. This is a measure of how much
- test code there is.
- </p>
- <p>There has been much debate over how much test code, compared to
- production code, should be written in a project. More test code
- finds more bugs, but test code needs to be maintained just like
- the production code, and it's expensive to write it in the first
- place. In several articles from relatively mature software
- organizations that I have read, the amount of test code has been
- about the same as the production code. </p>
- <p>In OTP, at the time of
- writing, few applications come even close to this, some have no
- test code at all.
- </p>
-
- <section>
- <title>Full coverage</title>
- <p>It is possible to cover compile the modules being tested
- before running the test suites. Doing so displays which branches
- of the code that are tested by the test suite, and which are
- not. Many use this as a measure of a good test suite. When every
- single line of source code is covered once by the test suite,
- the test suite is finished.
- </p>
- <p>A coverage of 100% still proves nothing, though. It doesn't
- mean that the code is error free, that everything is tested. For
- instance, if a function contains a division, it has to be
- executed at least twice. Once with parameters that cause
- division by zero, and once with other parameters.
- </p>
- <p>High degree of coverage is good of course, it means that no
- major parts of the code has been left untested. It's another
- question whether it's cost effective. You're only likely to find
- 50% more bugs when going from 67% to 100% coverage, but the work
- (cost) is maybe 200% as large, or more, because reaching all of
- those obscure branches is usually complicated.
- </p>
- <p>Again, the reason for testing with the test server is to find
- bugs, not to create certificates of valid code. Maximizing the
- number of found bugs per hour probably means not going for 100%
- coverage. For some module the optimum may be 70%, for some other
- maybe 250%. 100% shouldn't be a goal in itself.</p>
- </section>
-
- <section>
- <title>User interface testing</title>
- <p>It is very difficult to do sensible testing of user
- interfaces, especially the graphic ones. The test server has
- some support for capturing the text I/O that goes to the user,
- but none for graphics. There are several tools on the market
- that help with this.</p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/test_server/doc/src/write_framework_chapter.xml b/lib/test_server/doc/src/write_framework_chapter.xml
deleted file mode 100644
index d10b580c34..0000000000
--- a/lib/test_server/doc/src/write_framework_chapter.xml
+++ /dev/null
@@ -1,160 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2002</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Write you own test server framework</title>
- <prepared>Siri Hansen</prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>write_framework_chapter.xml</file>
- </header>
-
- <section>
- <title>Introduction</title>
- <p>The test server controller can be interfaced from the operating
- system or from within Erlang. The nature of your new framework
- will decide which interface to use. If you want your framework to
- start a new node for each test, the operating system interface is
- very convenient. If your node is already started, going from
- within Erlang might be a more flexible solution.
- </p>
- <p>The two methods are described below.
- </p>
- </section>
-
- <section>
- <title>Interfacing the test server controller from Erlang</title>
- <p>Using the test server from Erlang means that you have to start
- the test server and then add test jobs. Use
- <c>test_server_ctrl:start/0</c> to start the test server, and
- <c>test_server_ctrl:stop/0</c> to stop it.
- </p>
-
- <section>
- <title>Adding test jobs</title>
- <p>There are many commands available for adding test cases to
- the test server's job queue: <br></br>
-</p>
- <list type="bulleted">
- <item>Single test case <br></br>
-<c>test_server_ctrl:add_case/2/3</c></item>
- <item>Multiple test cases from same suite <br></br>
-<c>test_server_ctrl:add_cases/2/3</c></item>
- <item>Test suite module or modules <br></br>
-<c>test_server_ctrl:add_module/1/2</c></item>
- <item>Some or all test suite modules in a directory <br></br>
-<c>test_server_ctrl:add_dir/2/3</c></item>
- <item>Test cases specified in a test specification file <br></br>
-<c>test_server_ctrl:add_spec/1</c></item>
- </list>
- <p>All test suites are given a unique name, which is usually
- given when the test suite is added to the job queue. In some
- cases, a default name is used, as in the case when a module is
- added without a specified name. The test job name is used to
- store logfiles, which are stored in the `name.logs' directory
- under the current directory.
- </p>
- <p>See the reference manual for details about the functions for
- adding test jobs.
- </p>
- </section>
- </section>
-
- <section>
- <title>Interfacing the test server controller from the operating system.</title>
- <p>The function <c>run_test/1</c> is your interface in the test
- server controller if you wish to use it from the operating
- system. You simply start an erlang shell and invoke this function
- with the <c>-s</c> option. <c>run_test/1</c> starts the test
- server, runs the test specified by the command line and stops the
- test server. The argument to <c>run_test/1</c> is a list of
- command line flags, typically
- <c>['KEY1', Value1, 'KEY2', Value2, ...]</c>.
- The valid command line flags are listed in the reference manual
- for <c>test_server_ctrl</c>.
- </p>
- <p>A typical command line may look like this <br></br>
-<c>erl -noshell -s test_server_ctrl run_test KEY1 Value1 KEY2 Value2 ... -s erlang halt</c></p>
- <p>Or make an alias (this is for unix/tcsh) <br></br>
-<c>alias erl_test 'erl -noshell -s test_server_ctrl run_test \!* -s erlang halt'</c></p>
- <p>And then use it like this <br></br>
-<c>erl_test KEY1 Value1 KEY2 Value2 ...</c> <br></br>
-</p>
-
- <section>
- <title>An Example</title>
- <p>An example of starting a test run from the command line <br></br>
-</p>
- <p><c>erl -name test_srv -noshell -rsh /home/super/otp/bin/ctrsh </c> <br></br>
-<c>-pa /clearcase/otp/erts/lib/kernel/test </c> <br></br>
-<c>-boot start_sasl -sasl errlog_type error </c> <br></br>
-<c>-s test_server_ctrl run_test SPEC kernel.spec -s erlang halt</c> <br></br>
-</p>
- </section>
- </section>
-
- <section>
- <title>Framework callback functions</title>
- <p>By defining the environment variable
- <c>TEST_SERVER_FRAMEWORK</c> to a module name, the framework
- callback functions can be used. The framework callback functions
- are called by the test server in order let the framework interact
- with the execution of the tests and to keep the framework upto
- date with information about the test progress.
- </p>
- <p>The framework callback functions are described in the reference
- manual for <c>test_server_ctrl</c>.
- </p>
- <p>Note that this topic is in an early stage of development, and
- changes might occur.
- </p>
- </section>
-
- <section>
- <title>Other concerns</title>
- <p>Some things to think about when writing you own test server
- framework:
- </p>
- <list type="bulleted">
- <item><c>emulator version</c> - Make sure that the intended
- version of the emulator is started.
- </item>
- <item><c>operating system path</c> - If test cases use port
- programs, make sure the paths are correct.
- </item>
- <item><c>recompilation</c> - Make sure all test suites are fresh
- compiled.
- </item>
- <item><c>test_server.hrl</c> - Make sure the
- <c>test_server.hrl</c> file is in the include path when
- compiling test suites.
- </item>
- <item><c>running applications</c> - Some test suites require
- some applications to be running (e.g. sasl). Make sure they are
- started.
- </item>
- </list>
- </section>
-</chapter>
-
diff --git a/lib/test_server/doc/src/write_test_chapter.xml b/lib/test_server/doc/src/write_test_chapter.xml
deleted file mode 100644
index c3e1881b8a..0000000000
--- a/lib/test_server/doc/src/write_test_chapter.xml
+++ /dev/null
@@ -1,228 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2002</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Writing Test Suites</title>
- <prepared>Siri Hansen</prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>write_test_chapter.xml</file>
- </header>
-
- <section>
- <title>Support for test suite authors</title>
- <p>The <c>test_server</c> module provides some useful functions
- to support the test suite author. This includes:
- </p>
- <list type="bulleted">
- <item>Starting and stopping slave or peer nodes</item>
- <item>Capturing and checking stdout output</item>
- <item>Retrieving and flushing process message queue</item>
- <item>Watchdog timers</item>
- <item>Checking that a function crashes</item>
- <item>Checking that a function succeeds at least m out of n times</item>
- <item>Checking .app files</item>
- </list>
- <p>Please turn to the reference manual for the <c>test_server</c>
- module for details about these functions.
- </p>
- </section>
-
- <section>
- <title>Test suites</title>
- <p>A test suite is an ordinary Erlang module that contains test
- cases. It's recommended that the module has a name on the form
- *_SUITE.erl. Otherwise, the directory function will not find the
- modules (by default).
- </p>
- <p>For some of the test server support, the test server include
- file <c>test_server.hrl</c> must be included. Never include it
- with the full path, for portability reasons. Use the compiler
- include directive instead.
- </p>
- <p>The special function <c>all(suite)</c> in each module is called
- to get the test specification for that module. The function
- typically returns a list of test cases in that module, but any
- test specification could be returned. Please see the chapter
- about test specifications for details about this.
- </p>
- </section>
-
- <section>
- <title>Init per test case</title>
- <p>In each test suite module, the functions
- <c>init_per_testcase/2</c> and <c>end_per_testcase/2</c> must be
- implemented.
- </p>
- <p><c>init_per_testcase</c> is called before each test case in the
- test suite, giving a (limited) possibility for initialization.
- </p>
- <p><c>end_per_testcase/2</c> is called after each test case is
- completed, giving a possibility to clean up.
- </p>
- <p>The first argument to these functions is the name of the test
- case. This can be used to do individual initialization and cleanup for
- each test cases.
- </p>
- <p>The second argument is a list of tuples called
- <c>Config</c>. The first element in a <c>Config</c> tuple
- should be an atom - a key value to be used for searching.
- <c>init_per_testcase/2</c> may modify the <c>Config</c>
- parameter or just return it as is. Whatever is retuned by
- <c>init_per_testcase/2</c> is given as <c>Config</c> parameter to
- the test case itself.
- </p>
- <p>The return value of <c>end_per_testcase/2</c> is ignored by the
- test server.
- </p>
- </section>
-
- <section>
- <title>Test cases</title>
- <p>The smallest unit that the test server is concerned with is a
- test case. Each test case can in turn test many things, for
- example make several calls to the same interface function with
- different parameters.
- </p>
- <p>It is possible to put many or few tests into each test
- case. How many things each test case tests is up to the author,
- but here are some things to keep in mind.
- </p>
- <p>Very small test cases often leads to more code, since
- initialization has to be duplicated. Larger code, especially with
- a lot of duplication, increases maintenance and reduces
- readability.
- </p>
- <p>Larger test cases make it harder to tell what went wrong if it
- fails, and force us to skip larger portions of test code if a
- specific part fails. These effects are accentuated when running on
- multiple platforms because test cases often have to be skipped.
- </p>
- <p>A test case generally consists of three parts, the
- documentation part, the specification part and the execution
- part. These are implemented as three clauses of the same function.
- </p>
- <p>The documentation clause matches the argument '<c>doc</c>' and
- returns a list for strings describing what the test case tests.
- </p>
- <p>The specification clause matches the argument '<c>suite</c>'
- and returns the test specification for this particular test
- case. If the test specification is an empty list, this indicates
- that the test case is a leaf test case, i.e. one to be executed.
- </p>
- <p>The execution clause implements the actual test case. It takes
- one argument, <c>Config</c>, which contain configuration
- information like <c>data_dir</c> and <c>priv_dir</c>. See <seealso marker="#data_priv_dir">Data and Private Directories</seealso> for
- more information about these.
- </p>
- <p>The <c>Config</c> variable can also contain the
- <c>nodenames</c> key, if requested by the <c>require_nodenames</c>
- command in the test suite specification file. All <c>Config</c>
- items should be extracted using the <c>?config</c> macro. This is
- to ensure future compatibility if the <c>Config</c> format
- changes. See the reference manual for <c>test_server</c> for
- details about this macro.
- </p>
- <p>If the execution clause crashes or exits, it is considered a
- failure. If it returns <c>{skip,Reason}</c>, the test case is
- considered skipped. If it returns <c>{comment,String}</c>,
- the string will be added in the 'Comment' field on the HTML
- result page. If the execution clause returns anything else, it is
- considered a success, unless it is <c>{'EXIT',Reason}</c> or
- <c>{'EXIT',Pid,Reason}</c> which can't be distinguished from a
- crash, and thus will be considered a failure.
- </p>
- </section>
-
- <section>
- <marker id="data_priv_dir"></marker>
- <title>Data and Private Directories</title>
- <p>The data directory (<c>data_dir</c>) is the directory where the test
- module has its own files needed for the testing. A compiler test
- case may have source files to feed into the compiler, a release
- upgrade test case may have some old and new release of
- something. A graphics test case may have some icons and a test
- case doing a lot of math with bignums might store the correct
- answers there. The name of the <c>data_dir</c> is the the name of
- the test suite and then "_data". For example,
- <c>"some_path/foo_SUITE.beam"</c> has the data directory
- <c>"some_path/foo_SUITE_data/"</c>.
- </p>
- <p>The <c>priv_dir</c> is the test suite's private directory. This
- directory should be used when a test case needs to write to
- files. The name of the private directory is generated by the test
- server, which also creates the directory.
- </p>
- <p><em>Warning:</em> Do not depend on current directory to be
- writable, or to point to anything in particular. All scratch files
- are to be written in the <c>priv_dir</c>, and all data files found
- in <c>data_dir</c>. If the current directory has to be something
- specific, it must be set with <c>file:set_cwd/1</c>.
- </p>
- </section>
-
- <section>
- <title>Execution environment</title>
- <p>Each time a test case is about to be executed, a new process is
- created with <c>spawn_link</c>. This is so that the test case will
- have no dependencies to earlier tests, with respect to process flags,
- process links, messages in the queue, other processes having registered
- the process, etc. As little as possible is done to change the initial
- context of the process (what is created by plain spawn). Here is a
- list of differences:
- </p>
- <list type="bulleted">
- <item>It has a link to the test server. If this link is removed,
- the test server will not know when the test case is finished,
- just wait infinitely.
- </item>
- <item>It often holds a few items in the process dictionary, all
- with names starting with '<c>test_server_</c>'. This is to keep
- track of if/where a test case fails.
- </item>
- <item>There is a top-level catch. All of the test case code is
- catched, so that the location of a crash can be reported back to
- the test server. If the test case process is killed by another
- process (thus the catch code is never executed) the test server
- is not able to tell where the test case was executing.
- </item>
- <item>It has a special group leader implemented by the test
- server. This way the test server is able to capture the io that
- the test case provokes. This is also used by some of the test
- server support functions.
- </item>
- </list>
- <p>There is no time limit for a test case, unless the test case
- itself imposes such a limit, by calling
- <c>test_server:timetrap/1</c> for example. The call can be made
- in each test case, or in the <c>init_per_testcase/2</c>
- function. Make sure to call the corresponding
- <c>test_server:timetrap_cancel/1</c> function as well, e.g in the
- <c>end_per_testcase/2</c> function, or else the test cases will
- always fail.
- </p>
- </section>
-
-</chapter>
-
diff --git a/lib/test_server/ebin/.gitignore b/lib/test_server/ebin/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/test_server/ebin/.gitignore
+++ /dev/null
diff --git a/lib/test_server/include/test_server.hrl b/lib/test_server/include/test_server.hrl
deleted file mode 100644
index 77864ef3b5..0000000000
--- a/lib/test_server/include/test_server.hrl
+++ /dev/null
@@ -1,32 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2011. 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%
-%%
-
--ifdef(line_trace).
--line_trace(true).
--define(line,
- io:format(lists:concat([?MODULE,",",integer_to_list(?LINE),": ~p"]),
- [erlang:monotonic_time()-erlang:system_info(start_time)]),).
--else.
--define(line,).
--endif.
--define(t,test_server).
--define(config,test_server:lookup_config).
-
-
diff --git a/lib/test_server/include/test_server_line.hrl b/lib/test_server/include/test_server_line.hrl
deleted file mode 100644
index 37da956cd0..0000000000
--- a/lib/test_server/include/test_server_line.hrl
+++ /dev/null
@@ -1,20 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2011. 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%
-%%
-
diff --git a/lib/test_server/info b/lib/test_server/info
deleted file mode 100644
index 7a9ed6c700..0000000000
--- a/lib/test_server/info
+++ /dev/null
@@ -1,2 +0,0 @@
-group: test Test Applications
-short: The OTP Test Server
diff --git a/lib/test_server/prebuild.skip b/lib/test_server/prebuild.skip
deleted file mode 100644
index 8ee4101f6a..0000000000
--- a/lib/test_server/prebuild.skip
+++ /dev/null
@@ -1 +0,0 @@
-src/autom4te.cache
diff --git a/lib/test_server/src/Makefile b/lib/test_server/src/Makefile
deleted file mode 100644
index 6a26ee2933..0000000000
--- a/lib/test_server/src/Makefile
+++ /dev/null
@@ -1,144 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-2013. 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
-
-# ----------------------------------------------------
-# Configuration info.
-# ----------------------------------------------------
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(TEST_SERVER_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/test_server-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES= test_server_ctrl \
- test_server_gl \
- test_server_io \
- test_server_node \
- test_server \
- test_server_sup \
- erl2html2
-
-TS_MODULES= \
- ts \
- ts_run \
- ts_lib \
- ts_make \
- ts_erl_config \
- ts_autoconf_win32 \
- ts_install \
- ts_install_cth \
- ts_benchmark
-
-TARGET_MODULES= $(MODULES:%=$(EBIN)/%)
-TS_TARGET_MODULES= $(TS_MODULES:%=$(EBIN)/%)
-
-ERL_FILES= $(MODULES:=.erl)
-TS_ERL_FILES= $(TS_MODULES:=.erl)
-HRL_FILES = ../include/test_server.hrl ../include/test_server_line.hrl
-INTERNAL_HRL_FILES = test_server_internal.hrl
-TS_HRL_FILES= ts.hrl
-C_FILES =
-AUTOCONF_FILES = configure.in conf_vars.in
-PROGRAMS = configure config.sub config.guess install-sh
-CONFIG = ts.config ts.unix.config ts.win32.config
-
-TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR)) \
- $(APP_TARGET) $(APPUP_TARGET)
-TS_TARGET_FILES = $(TS_MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-TARGETS = $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(PROGRAMS) \
- $(APP_TARGET) $(APPUP_TARGET)
-TS_TARGETS = $(TS_MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-APP_FILE= test_server.app
-APP_SRC= $(APP_FILE).src
-APP_TARGET= $(EBIN)/$(APP_FILE)
-
-APPUP_FILE= test_server.appup
-APPUP_SRC= $(APPUP_FILE).src
-APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_COMPILE_FLAGS += -I../include -Werror
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-tests debug opt: $(TARGETS) $(TS_TARGETS)
-
-clean:
- rm -f $(TARGET_FILES) $(TS_TARGET_FILES)
- rm -f core
-
-docs:
-
-configure: configure.in
- autoconf configure.in > configure
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-$(APP_TARGET): $(APP_SRC) ../vsn.mk
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
-
-$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(TS_HRL_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/include"
- $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
-
-release_tests_spec: opt
- $(INSTALL_DIR) "$(RELEASE_PATH)/test_server"
- $(INSTALL_DATA) $(ERL_FILES) $(TS_ERL_FILES) \
- $(HRL_FILES) $(INTERNAL_HRL_FILES) $(TS_HRL_FILES) \
- $(TS_TARGET_FILES) \
- $(AUTOCONF_FILES) $(C_FILES) $(CONFIG) \
- "$(RELEASE_PATH)/test_server"
- $(INSTALL_SCRIPT) $(PROGRAMS) "$(RELEASE_PATH)/test_server"
-
-release_docs_spec:
-
diff --git a/lib/test_server/src/test_server.app.src b/lib/test_server/src/test_server.app.src
deleted file mode 100644
index 334be8109d..0000000000
--- a/lib/test_server/src/test_server.app.src
+++ /dev/null
@@ -1,39 +0,0 @@
-% This is an -*- erlang -*- file.
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2009-2013. 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%
-
-{application, test_server,
- [{description, "The OTP Test Server application"},
- {vsn, "%VSN%"},
- {modules, [
- erl2html2,
- test_server_ctrl,
- test_server,
- test_server_io,
- test_server_node,
- test_server_sup
- ]},
- {registered, [test_server_ctrl,
- test_server,
- test_server_break_process]},
- {applications, [kernel,stdlib]},
- {env, []},
- {runtime_dependencies, ["tools-2.8","stdlib-2.5","runtime_tools-1.8.16",
- "observer-2.1","kernel-4.0","inets-6.0",
- "syntax_tools-1.7","erts-7.0"]}]}.
-
diff --git a/lib/test_server/src/test_server.appup.src b/lib/test_server/src/test_server.appup.src
deleted file mode 100644
index 7c4aa630ae..0000000000
--- a/lib/test_server/src/test_server.appup.src
+++ /dev/null
@@ -1,22 +0,0 @@
-%% -*- erlang -*-
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2014. 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%
-{"%VSN%",
- [{<<".*">>,[{restart_application, test_server}]}],
- [{<<".*">>,[{restart_application, test_server}]}]
-}.
diff --git a/lib/test_server/src/things/distr_startup_SUITE.erl b/lib/test_server/src/things/distr_startup_SUITE.erl
deleted file mode 100644
index aa84ab007f..0000000000
--- a/lib/test_server/src/things/distr_startup_SUITE.erl
+++ /dev/null
@@ -1,239 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. 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(distr_startup_SUITE).
--compile([export_all]).
-%%-define(line_trace,1).
--include("test_server.hrl").
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all(suite) -> [reads,writes].
-
--define(iterations,10000).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-app1() ->
- {application, app1,
- [{description, "ERTS CXC 138 10"},
- {vsn, "2.0"},
- {applications, [kernel, stdlib]},
- {mod, {ch_sup, {app1, 1, 3}}}]}.
-
-app3() ->
- {application, app3,
- [{description, "ERTS CXC 138 10"},
- {vsn, "2.0"},
- {applications, [kernel, stdlib]},
- {mod, {ch_sup, {app3, 7, 9}}}]}.
-
-
-config(Fd,C1,C2,C3) ->
- io:format(Fd,
- "[{kernel, [{sync_nodes_optional, ['~s','~s','~s']},"
- "{sync_nodes_timeout, 1},"
- "{distributed, [{app1, ['~s', '~s', '~s']},"
- "{app2, 10000, ['~s', '~s', '~s']},"
- "{app3, 5000, [{'~s', '~s'}, '~s']}]}]}].~n",
- [C1,C2,C3, C1,C2,C3, C1,C2,C3, C1,C2,C3]).
-
-from(H, [H | T]) -> T;
-from(H, [_ | T]) -> from(H, T);
-from(H, []) -> [].
-
-%%-----------------------------------------------------------------
-%% Test suite for distributed applications, tests start, load
-%% etc indirectly.
-%% Should be started in a CC view with:
-%% erl -sname master -rsh ctrsh
-%%-----------------------------------------------------------------
-start_nodes(Conf) ->
- % Write a config file
- ?line Nodes = ?config(nodes,Conf),
- ?line [C1,C2,C3|_] = Nodes, %% Need at least 3 nodes
- ?line Dir = ?config(priv_dir,Conf),
- ?line {ok, Fd} = file:open(Dir ++ "sys.config", write),
- ?line config(Fd,C1,C2,C3),
- ?line file:close(Fd),
- ?line Config = Dir ++ "sys",
-
- % Test [cp1, cp2, cp3]
- ?line {ok, Cp1} = start_node(lists:nth(1,Nodes), Config),
- ?line {ok, Cp2} = start_node(lists:nth(2,Nodes), Config),
- ?line {ok, Cp3} = start_node(lists:nth(3,Nodes), Config),
- % Start app1 and make sure cp1 starts it
- %%?line rpc:multicall([Cp1, Cp2, Cp3], application, load, [app1()]),
- %%?line rpc:multicall([Cp1, Cp2, Cp3], application, start,[app1,permanent]),
- ?line test_server:sleep(1000),
- {Cp1,Cp2,Cp3}.
-
-stop_nodes({Cp1,Cp2,Cp3}) ->
- ?line stop_node(Cp1),
- ?line stop_node(Cp2),
- ?line stop_node(Cp3).
-
-start_node(NodeAtHost, Config) ->
- ?line NodeAtHostStr = atom_to_list(NodeAtHost),
- ?line HostStr = from($@,NodeAtHostStr),
- ?line NodeStr = lists:reverse(from($@,lists:reverse(NodeAtHostStr))),
- ?line Host = list_to_atom(HostStr),
- ?line Node = list_to_atom(NodeStr),
- ?line io:format("Launching slave node ~p@~p ~p",[Node,Host,Config]),
- ?line slave:start(Host, Node, lists:concat(["-config ", Config])).
-
-stop_node(Node) ->
- ?line rpc:cast(Node, erlang, halt, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-start_client_process(Cp,Mode,NodeNum) ->
- io:format("Starting client process at ~p in mode ~p",[Cp,Mode]),
- ?line case rpc:call(Cp, erlang, spawn,
- [?MODULE, client,
- [Mode,NodeNum,self(),random:uniform(1000)]]) of
- {badrpc,Reason} ->
- ?line exit({badrpc,{Cp,Reason}});
- Client ->
- ?line Client
- end.
-
-start_clients(Mode,Conf) ->
- ?line random:seed(4711,0,0),
- ?line {Cp1,Cp2,Cp3} = start_nodes(Conf),
- ?line Client1 = start_client_process(Cp1,Mode,1),
- ?line Client2 = start_client_process(Cp2,Mode,2),
- ?line Client3 = start_client_process(Cp3,Mode,3),
- test_server:format(1,"All 3 nodes started, "
- "power off client(s) any time...",[]),
- Client1 ! go,
- Client2 ! go,
- Client3 ! go,
- {{Cp1,Cp2,Cp3},{Client1,Client2,Client3}}.
-
-stop_clients(Cps) ->
- test_server:format(1,"Test completed.",[]),
- ?line stop_nodes(Cps).
-
-data() ->
- {{self(),foo,bar,[1,2,3,4,5,6,7],{{{{}}}},
- "We need pretty long packages, so that there is a big risk "
- "of cutting it in the middle when suddenly turning off "
- "the power or breaking the connection. "
- "We don't check the contents of the data very much, but "
- "at least there is a magic cookie at the end (123456)."
- "If that one arrives correctly, the link is ok as far "
- "as we are concerned."},
- 123456}.
-
-reads(suite) -> [];
-reads(Conf) ->
- ?line {Cps,_} = start_clients(w,Conf),
- ?line read_loop(?iterations,0),
- ?line stop_clients(Cps),
- ok.
-
-read_loop(0,M) ->
- ok;
-read_loop(N,M) ->
- ?line Dog = test_server:timetrap(test_server:seconds(0.5)),
- M2 =
- receive
- {Node,Count,{_,123456}} ->
- ?line setelement(Node,M,element(Node,M)+1);
- {Node,Count,Data} ->
- ?line exit({network_transmission_error,Data});
- {nodedown,Node} ->
- ?line test_server:format(1,"Node ~s went down",[Node]),
- ?line M;
- Other ->
- ?line M
- after test_server:seconds(0.1) ->
- ?line io:format("No message!"),
- ?line M
- end,
- ?line test_server:timetrap_cancel(Dog),
- ?line M3 =
- case N rem 100 of
- 0 -> io:format("~p reads to go (~w msgs)",[N,M2]),
- {0,0,0};
- _ -> M2
- end,
- ?line read_loop(N-1,M3).
-
-client(w,NodeNum,Pid,Seed) ->
- random:seed(Seed,0,0),
- receive
- go -> ok
- end,
- client_write_loop(Pid,0,NodeNum,data());
-client(r,NodeNum,Pid,Seed) ->
- random:seed(Seed,0,0),
- receive
- go -> ok
- end,
- client_read_loop(0).
-
-client_write_loop(Pid,N,NodeNum,Data) ->
- test_server:sleep(random:uniform(20)),
- Pid ! {NodeNum,N,Data},
- client_write_loop(Pid,N+1,NodeNum,Data).
-
-writes(suite) -> [];
-writes(Conf) ->
- ?line {Cps,{C1,C2,C3}} = start_clients(r,Conf),
- ?line write_loop(2*?iterations,{C1,C2,C3},data()),
- ?line stop_clients(Cps),
- ok.
-
-write_loop(0,_,_) ->
- ok;
-write_loop(N,Clients,Data) ->
- ?line Dog = test_server:timetrap(test_server:seconds(0.5)),
- ?line Client = element(random:uniform(size(Clients)),Clients),
- ?line Client ! {node(),N,Data},
- ?line test_server:timetrap_cancel(Dog),
- receive
- {nodedown,Node} ->
- ?line test_server:format(1,"Node ~s went down",[Node])
- after 0 ->
- ?line ok
- end,
- ?line case N rem 100 of
- 0 -> io:format("~p writes to go",[N]);
- _ -> ok
- end,
- ?line write_loop(N-1,Clients,Data).
-
-client_read_loop(N) ->
- receive
- {Node,Count,{_,123456}} ->
- ?line ok;
- {Node,Count,Data} ->
- ?line io:format("~p(~p): transmission error from node ~p(~p): ~p",
- [node(),N,Node,Count,Data]);
- Other ->
- ?line io:format("~p(~p): got a strange message: ~p",
- [node(),N,Other])
- end,
- client_read_loop(N+1).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
diff --git a/lib/test_server/src/things/mnesia_power_SUITE.erl b/lib/test_server/src/things/mnesia_power_SUITE.erl
deleted file mode 100644
index e9bc75e583..0000000000
--- a/lib/test_server/src/things/mnesia_power_SUITE.erl
+++ /dev/null
@@ -1,126 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. 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(mnesia_power_SUITE).
--compile([export_all]).
-%%-define(line_trace,1).
--include("test_server.hrl").
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all(suite) -> [run].
-
--define(iterations,3). %% nof power-off cycles to do before acceptance
--define(rows,8). %% nof database rows to use (not too big, please)
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
--record(sum_table_1,{row,a,b,c,s}).
-
-run(suite) -> [];
-run(Config) ->
- ?line mnesia:create_schema([node()]),
- ?line mnesia:start(),
- ?line mnesia:create_table([{name, sum_table_1}, {disc_copies,[node()]},
- {attributes,record_info(fields,sum_table_1)}]),
- ?line run_test(Config,?iterations).
-
-run(Config,N) ->
- ?line mnesia:start(),
- ?line check_consistency(sum_table_1),
- case N of
- 0 -> ?line ok;
- N -> ?line run_test(Config,N)
- end.
-
-run_test(Config,N) ->
- ?line Pid1a = start_manipulator(sum_table_1),
- ?line Pid1b = start_manipulator(sum_table_1),
- ?line Pid1c = start_manipulator(sum_table_1),
- ?line test_server:resume_point(?MODULE,run,[Config,N-1]),
- ?line test_server:format(1,"Manipulating data like crazy now, "
- "power off any time..."),
- ?line test_server:sleep(infinity).
-
-start_manipulator(Table) ->
- ?line spawn_link(?MODULE,manipulator_init,[Table]).
-
-manipulator_init(Table) ->
- random:seed(4711,0,0),
- manipulator(0,Table).
-
-manipulator(N,Table) ->
- ?line Fun =
- fun() ->
- ?line Row = random:uniform(?rows),
- ?line A = random:uniform(100000),
- ?line B = random:uniform(100000),
- ?line C = random:uniform(100000),
- ?line Sum = A+B+C,
- ?line case mnesia:write(#sum_table_1
- {row=Row,a=A,b=B,c=C,s=Sum}) of
- ok -> ok;
- Other ->
- ?line io:format("Trans failed: ~p\n",[Other])
- end
- end,
- ?line mnesia:transaction(Fun),
- case mnesia:table_info(sum_table_1,size) of
- 0 -> exit(still_empty);
- _ -> ok
- end,
- case N rem 2000 of
- 0 -> io:format("~p did ~p operations",[self(),N]),
- check_consistency(sum_table_1);
- _ -> ok
- end,
- ?line manipulator(N+1,Table).
-
-check_consistency(Table) ->
- io:format("Checking consistency of table ~p\n",[Table]),
- All = mnesia:table_info(Table,wild_pattern),
- ?line Fun =
- fun() ->
- mnesia:match_object(All)
- end,
- ?line case mnesia:transaction(Fun) of
- {atomic,Val} ->
- check_consistency_rows(Val,0);
- Other ->
- io:format("Trans failed: ~p\n",[Other]),
- exit(failed),
- check_consistency(Table)
- end.
-
-check_consistency_rows([#sum_table_1{a=A,b=B,c=C,s=Sum}|Rows],N) ->
- ?line Sum=A+B+C,
- ?line check_consistency_rows(Rows,N+1);
-check_consistency_rows([],N) ->
- io:format("All ~p rows were consistent\n",[N]),
- {ok,N};
-check_consistency_rows(Thing,N) ->
- io:format("Mnesia transaction returned:\n~p\n",[Thing]),
- exit({bad_format,Thing}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-
-
-
diff --git a/lib/test_server/src/things/random_kill_SUITE.erl b/lib/test_server/src/things/random_kill_SUITE.erl
deleted file mode 100644
index 917bc2b3d5..0000000000
--- a/lib/test_server/src/things/random_kill_SUITE.erl
+++ /dev/null
@@ -1,82 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. 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(random_kill_SUITE).
--compile([export_all]).
-%%-define(line_trace,1).
--include("test_server.hrl").
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-all(suite) -> [run].
-
--define(iterations,25). %% Kill this many processes,
- %% possibly with reboots in between
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-run(suite) -> [];
-run(Config) ->
- registered(?iterations).
-
-registered(0) ->
- ok;
-registered(N) ->
- random:seed(3461*N,1159*N,351*N),
- Pid = select_victim(registered),
- test_server:resume_point(?MODULE,registered,[N-1]),
- test_server:format("About to kill pid ~p (~p)\n~p",
- [Pid,process_info(Pid,registered_name),info(Pid)]),
- %%exit(Pid,kill),
- registered(N-1).
-
-info(Pid) ->
- Rest0 = tl(pid_to_list(Pid)),
- {P1,Rest1} = get_until($.,Rest0),
- {P2,Rest2} = get_until($.,Rest1),
- {P3,_} = get_until($>,Rest2),
- c:i(list_to_integer(P1),list_to_integer(P2),list_to_integer(P3)).
-
-get_until(Ch,L) ->
- get_until(Ch,L,[]).
-get_until(Ch,[],Acc) ->
- {lists:reverse(Acc),[]};
-get_until(Ch,[Ch|T],Acc) ->
- {lists:reverse(Acc),T};
-get_until(Ch,[H|T],Acc) ->
- get_until(Ch,T,[H|Acc]).
-
-select_victim(registered) ->
- Pids =
- lists:map(fun(Server)-> whereis(Server) end,registered()),
- ImmunePids =
- [self()|lists:map(fun(Job)-> element(2,Job) end,test_server:jobs())],
- SuitablePids =
- lists:filter(fun(Pid)-> case lists:member(Pid,ImmunePids) of
- true -> false;
- false -> true
- end
- end, Pids),
- Selected = random:uniform(length(SuitablePids)),
- io:format("Selected ~p if ~p",[Selected,length(SuitablePids)]),
- lists:nth(Selected,SuitablePids).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
diff --git a/lib/test_server/src/things/soft.gs.txt b/lib/test_server/src/things/soft.gs.txt
deleted file mode 100644
index ec57884997..0000000000
--- a/lib/test_server/src/things/soft.gs.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-6> gs:start().
-RealTimeViolation, 478ms (after 1164 good)
-{1,<0.65.0>}
-RealTimeViolation, 352ms (after 0 good)
-RealTimeViolation, 492ms (after 0 good)
-RealTimeViolation, 166ms (after 0 good)
-RealTimeInfo, 18ms (after 7 good)
-RealTimeViolation, 115ms (after 13 good)
-7> application-specific initialization failed: couldn't connect to display ":0.0"
-RealTimeViolation, 20340ms (after 0 good)
-gs error: user backend died reason {port_handler,#Port,normal}
-
-RealTimeInfo, 31ms (after 21 good)
-RealTimeInfo, 21ms (after 69 good)
-RealTimeInfo, 21ms (after 119 good)
-RealTimeInfo, 21ms (after 169 good)
diff --git a/lib/test_server/src/things/verify.erl b/lib/test_server/src/things/verify.erl
deleted file mode 100644
index b09d0fbda9..0000000000
--- a/lib/test_server/src/things/verify.erl
+++ /dev/null
@@ -1,200 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. 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(verify).
-
--export([dir/0, dir/1]).
-
-%% usage verify:dir()
-%% or verify:dir(Dir)
-%%
-%% runs tests on all files with the extension ".t1"
-%% creates an error log file verify.log in the directory where the
-%% tests were run
-
--import(lists, [reverse/1, foldl/3, map/2]).
-
-dir() ->
- dir(".").
-
-dir(Dir) ->
- case file:list_dir(Dir) of
- {ok, Files} ->
- VFiles = collect_vers(Files, []),
- VFiles1 = map(fun(F) -> Dir ++ "/" ++ F end, VFiles),
- Nerrs = foldl(fun(F, Sum) ->
- case file(F) of
- {file,_,had,N,errors} ->
- Sum + N;
- no_errors ->
- Sum;
- Other ->
- Sum + 1
- end
- end, 0, VFiles1),
- case Nerrs of
- 0 -> no_errors;
- _ -> {dir,Dir,had,Nerrs,errors}
- end;
- _ ->
- {error, cannot,list_dir, Dir}
- end.
-
-collect_vers([H|T], L) ->
- case reverse(H) of
- [$1,$t,$.|T1] -> collect_vers(T, [reverse(T1)|L]);
- _ -> collect_vers(T, L)
- end;
-collect_vers([], L) ->
- L.
-
-file(File) ->
- case file:open(File ++ ".t1", read) of
- {ok, S} ->
- io:format("Verifying: ~s\n", [File]),
- ErrFile = File ++ ".errs",
- {ok, E} = file:open(ErrFile, write),
- Bind0 = erl_eval:new_bindings(),
- NErrs = do(S, {E, File, Bind0, 0}, 1),
- file:close(S),
- file:close(E),
- case NErrs of
- 0 ->
- file:delete(ErrFile),
- no_errors;
- _ ->
- {file,File,had,NErrs,errors}
- end;
- _ ->
- error_in_opening_file
- end.
-
-do(S, Env, Line) ->
- R = io:scan_erl_exprs(S, '', Line),
- do1(R, S, Env).
-
-do1({eof,_}, _, {_,_,_,NErrs}) ->
- NErrs;
-do1({ok,Toks,Next}, S, Env0) ->
- E1 = handle_toks(Toks, Next, Env0),
- do(S, E1, Next);
-do1({error, {Line,Mod,Args}, Next}, S, E) ->
- io:format("*** ~w ~p~n", [Line,Mod:format_error(Args)]),
- E1 = add_error(E),
- do(S, E1, Next).
-
-add_error({Stream, File, Bindings, N}) -> {Stream, File, Bindings, N+1}.
-
-handle_toks(Toks, Line, Env0) ->
- %% io:format("Toks:~p\n", [Toks]).
- case erl_parse:parse_exprs(Toks) of
- {ok, Exprs} ->
- %% io:format("Got:~p\n", [Exprs]),
- eval(Exprs, Line, Env0);
- {error, {LineNo, Mod, What}} ->
- Str = apply(Mod, format_error, [What]),
- io:format("*** Line:~w ***~s\n", [LineNo, Str]),
- add_error(Env0);
- Parse_error ->
- io:format("Parse Error:~p\n",[Parse_error]),
- add_error(Env0)
- end.
-
-forget([{var,_,Name}], B0) -> erl_eval:del_binding(Name, B0);
-forget([], _) -> erl_eval:new_bindings().
-
-eval([{call,_,{atom,_,f}, Args}], _, {Stream, Bind0, Errs}) ->
- Bind1 = forget(Args, Bind0),
- {Stream, Bind1, Errs};
-eval(Exprs, Line, {Stream, File, Bind0, NErrs}) ->
- %% io:format("Bindings >> ~p\n", [Bind0]),
- %% io:format("Exprs >> ~p\n", [Exprs]),
- case catch erl_eval:exprs(Exprs, Bind0) of
- {'EXIT', Reason} ->
- out_both(Stream, "----------------------------------~n", []),
- out_both(Stream, "File:~s Error in:~s~n", [File, pp(Exprs)]),
- print_bindings(Stream, Exprs, Bind0),
- print_lhs(Stream, Exprs),
- out_both(Stream, '*** Rhs evaluated to:~p~n',[rhs(Exprs, Bind0)]),
- {Stream, File, Bind0, NErrs+1};
- {value, _, Bind1} ->
- {Stream, File, Bind1, NErrs}
- end.
-
-pp([H]) -> erl_pp:expr(H);
-pp([H|T]) -> [erl_pp:expr(H),$,|pp(T)];
-pp([]) -> [].
-
-print_bindings(E, Form, Bindings) ->
- case varsin(Form) of
- [] ->
- true;
- Vars ->
- print_vars(E, Vars, Bindings)
- end.
-
-print_vars(E, [Var|T], Bindings) ->
- case erl_eval:binding(Var, Bindings) of
- {value, Val} ->
- out_both(E, '~s = ~p\n',[Var, Val]);
- unbound ->
- out_both(E, '~s *is unbound*\n', [Var])
- end,
- print_vars(E, T, Bindings);
-print_vars(_, [], _) ->
- true.
-
-
-out_both(E, Format, Data) ->
- io:format(Format, Data),
- io:format(E, Format, Data).
-
-print_lhs(E, [{match, _, Lhs, Rhs}]) ->
- %% io:format(">>>> here:~w\n",[Lhs]),
- out_both(E, '*** Lhs was:~s\n',[erl_pp:expr(Lhs)]);
-print_lhs(E, _) ->
- out_both(E, '** UNDEFINED **', []).
-
-
-rhs([{match, _, Lhs, Rhs}], Bindings) ->
- case catch erl_eval:exprs([Rhs], Bindings) of
- {value, Val, _} -> Val;
- Other -> undefined()
- end;
-rhs(_, _) ->
- undefined().
-
-varsin(X) -> varsin(X, []).
-
-varsin({var,_,'_'}, L) ->
- L;
-varsin({var,_,V}, L) ->
- case lists:member(V, L) of
- true -> L;
- false -> [V|L]
- end;
-varsin([H|T], L) ->
- varsin(T, varsin(H, L));
-varsin(T, L) when tuple(T) ->
- varsin(tuple_to_list(T), L);
-varsin(_, L) ->
- L.
-
-undefined() ->
- '** UNDEFINED **'.
diff --git a/lib/test_server/test/Makefile b/lib/test_server/test/Makefile
deleted file mode 100644
index 8eec940505..0000000000
--- a/lib/test_server/test/Makefile
+++ /dev/null
@@ -1,92 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-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%
-#
-
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES= \
- test_server_SUITE \
- test_server_test_lib \
- erl2html2_SUITE
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-INSTALL_PROGS= $(TARGET_FILES)
-
-EMAKEFILE=Emakefile
-COVERFILE=test_server.cover
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/test_server_test
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-ERL_MAKE_FLAGS += -pa $(ERL_TOP)/lib/test_server/ebin
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/test
-
-EBIN = .
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-.PHONY: make_emakefile
-
-make_emakefile:
- $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) \
- '*_SUITE_make' > $(EMAKEFILE)
- $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES)\
- >> $(EMAKEFILE)
-
-tests debug opt: make_emakefile
- erl $(ERL_MAKE_FLAGS) -make
-
-clean:
- rm -f $(EMAKEFILE)
- rm -f $(TARGET_FILES) $(GEN_FILES)
- rm -f core
-
-docs:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
-
-release_tests_spec: make_emakefile
- $(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(COVERFILE) "$(RELSYSDIR)"
- $(INSTALL_DATA) test_server_test_lib.hrl test_server.spec test_server.cover "$(RELSYSDIR)"
- chmod -R u+w "$(RELSYSDIR)"
- @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
-
-release_docs_spec:
diff --git a/lib/test_server/test/test_server.cover b/lib/test_server/test/test_server.cover
deleted file mode 100644
index 052415377d..0000000000
--- a/lib/test_server/test/test_server.cover
+++ /dev/null
@@ -1 +0,0 @@
-{incl_app,test_server,details}.
diff --git a/lib/test_server/test/test_server.spec b/lib/test_server/test/test_server.spec
deleted file mode 100644
index a3b4d01d08..0000000000
--- a/lib/test_server/test/test_server.spec
+++ /dev/null
@@ -1 +0,0 @@
-{suites, "../test_server_test", all}.
diff --git a/lib/test_server/vsn.mk b/lib/test_server/vsn.mk
deleted file mode 100644
index 8c5fc97383..0000000000
--- a/lib/test_server/vsn.mk
+++ /dev/null
@@ -1 +0,0 @@
-TEST_SERVER_VSN = 3.10
diff --git a/lib/tools/Makefile b/lib/tools/Makefile
index 2699ffab51..fef33743c0 100644
--- a/lib/tools/Makefile
+++ b/lib/tools/Makefile
@@ -24,7 +24,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# Macros
# ----------------------------------------------------
-SUB_DIRECTORIES = c_src src doc/src examples priv emacs
+SUB_DIRECTORIES = c_src src doc/src examples emacs
include vsn.mk
VSN = $(TOOLS_VSN)
diff --git a/lib/tools/c_src/Makefile.in b/lib/tools/c_src/Makefile.in
index 66bba229f6..e8bce149b1 100644
--- a/lib/tools/c_src/Makefile.in
+++ b/lib/tools/c_src/Makefile.in
@@ -97,11 +97,8 @@ DRIVERS=
ifneq ($(strip $(ETHR_LIB_NAME)),)
# Need ethread package for emem
-ifneq ($(findstring ose,$(TARGET)),ose)
-# Do not build on OSE
PROGS += $(BIN_DIR)/emem$(TYPEMARKER)@EXEEXT@
endif
-endif
EMEM_OBJ_DIR=$(OBJ_DIR)/emem
CREATE_DIRS += $(EMEM_OBJ_DIR)
@@ -152,12 +149,7 @@ ERTS_LIB = $(ERL_TOP/erts/lib_src/obj/$(TARGET)/$(TYPE)/MADE
_create_dirs := $(shell mkdir -p $(CREATE_DIRS))
-ifneq ($(findstring ose,$(TARGET)),ose)
all: $(PROGS) $(DRIVERS)
-else
-# Do not build dynamic files on OSE
-all:
-endif
$(ERTS_LIB):
$(make_verbose)cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE)
diff --git a/lib/tools/doc/src/cover_chapter.xml b/lib/tools/doc/src/cover_chapter.xml
index 2f7f8d8083..c3f1570477 100644
--- a/lib/tools/doc/src/cover_chapter.xml
+++ b/lib/tools/doc/src/cover_chapter.xml
@@ -451,48 +451,5 @@ ok
<p>When Cover is stopped, all Cover compiled modules are unloaded.</p>
</section>
</section>
-
- <section>
- <title>Using the Web Based User Interface to Cover</title>
-
- <section>
- <title>Introduction</title>
- <p>To ease the use of Cover there is a web based user interface
- to Cover called WebCover. WebCover is designed to be started
- and used via WebTool. It is possible to Cover compile Erlang
- modules and to generate printable Cover and Call analyses via
- the web based user interface.</p>
- </section>
-
- <section>
- <title>Start the Web Based User Interface to Cover</title>
- <p>To start WebCover you can either start WebTool, point a
- browser to the start page of WebTool and start WebCover from
- there, or you can use the <c>start_webtool</c> script to start
- Webtool, WebCover and a browser. See WebTool documentation for
- further information.</p>
- <p>Currently WebCover is only compatible
- with Internet Explorer and Netscape Navigator 4.0 and higher.</p>
- </section>
-
- <section>
- <title>Navigating WebCover</title>
- <p>From the menu in the lefthand frame you can select the
- <c>Nodes</c>, <c>Compile</c>, <c>Import</c> or <c>Result</c>
- page.</p>
- <p>From the <c>Nodes</c> page you can add remote nodes to
- participate in the coverage analysis. Coverage data from all
- involved nodes will then be merged during analysis.</p>
- <p>From the <c>Compile</c> page you can Cover compile <c>.erl</c>
- or <c>.beam</c> files.</p>
- <p>From the <c>Import</c> page you can import coverage data from
- a previous analysis. Imported data will then be merged with
- the current coverage data. <em>Note</em> that it is only possible to
- import files with the extension <c>.coverdata</c>.</p>
- <p>From the <c>Result</c> page you can analyse, reset or export
- coverage data.</p>
- <p>Please follow the instructions on each page.</p>
- </section>
- </section>
</chapter>
diff --git a/lib/tools/emacs/erlang-skels-old.el b/lib/tools/emacs/erlang-skels-old.el
index c271cce3cb..d0b2bfd97f 100644
--- a/lib/tools/emacs/erlang-skels-old.el
+++ b/lib/tools/emacs/erlang-skels-old.el
@@ -816,7 +816,7 @@ Please see the function `tempo-define-template'.")
"%% Note: This directive should only be used in test suites." n
"-compile(export_all)." n n
- "-include_lib(\"test_server/include/test_server.hrl\")." n n
+ "-include_lib(\"common_test/include/ct.hrl\")." n n
(erlang-skel-separator 2)
"%% TEST SERVER CALLBACK FUNCTIONS" n
diff --git a/lib/tools/emacs/erlang-skels.el b/lib/tools/emacs/erlang-skels.el
index 6880ec733c..ac37ff2ee5 100644
--- a/lib/tools/emacs/erlang-skels.el
+++ b/lib/tools/emacs/erlang-skels.el
@@ -1070,7 +1070,7 @@ Please see the function `tempo-define-template'.")
"%% Note: This directive should only be used in test suites." n
"-compile(export_all)." n n
- "-include_lib(\"test_server/include/test_server.hrl\")." n n
+ "-include_lib(\"common_test/include/ct.hrl\")." n n
(erlang-skel-separator-start 2)
"%% TEST SERVER CALLBACK FUNCTIONS" n
diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el
index 466bf139b9..2ff14dea02 100644
--- a/lib/tools/emacs/erlang.el
+++ b/lib/tools/emacs/erlang.el
@@ -897,6 +897,7 @@ resulting regexp is surrounded by \\_< and \\_>."
"get_module_info"
"get_stacktrace"
"hash"
+ "has_prepared_code_on_load"
"hibernate"
"insert_element"
"is_builtin"
diff --git a/lib/gs/contribs/ebin/.gitignore b/lib/tools/priv/.gitignore
index e69de29bb2..e69de29bb2 100644
--- a/lib/gs/contribs/ebin/.gitignore
+++ b/lib/tools/priv/.gitignore
diff --git a/lib/tools/priv/Makefile b/lib/tools/priv/Makefile
deleted file mode 100644
index aa4aaa2fc8..0000000000
--- a/lib/tools/priv/Makefile
+++ /dev/null
@@ -1,69 +0,0 @@
-# ``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.
-#
-# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-# AB. All Rights Reserved.''
-#
-# $Id$
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN = $(TOOLS_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/tools-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-HTDOCS_FILES = index.html
-
-TOOL_FILES = cover.tool
-
-# ----------------------------------------------------
-# 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)/priv"
- $(INSTALL_DATA) $(HTDOCS_FILES) "$(RELSYSDIR)/priv"
- $(INSTALL_DATA) $(TOOL_FILES) "$(RELSYSDIR)/priv"
-
-release_docs_spec:
-
-
-
diff --git a/lib/tools/priv/cover.tool b/lib/tools/priv/cover.tool
deleted file mode 100644
index 9e72f89ff4..0000000000
--- a/lib/tools/priv/cover.tool
+++ /dev/null
@@ -1,2 +0,0 @@
-{version,"1.2"}.
-[{config_func,{cover_web,configData,[]}}].
diff --git a/lib/tools/priv/index.html b/lib/tools/priv/index.html
deleted file mode 100644
index 6b60ef5d0a..0000000000
--- a/lib/tools/priv/index.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>Erlang webb tools </TITLE>
-</HEAD>
-<FRAMESET COLS="250,*">
-<FRAME NAME="menu" SRC="/webcover/erl/cover_web/menu_frame">
-<FRAME NAME="main" SRC="/webcover/erl/cover_web/compile_frame">
-</FRAMESET>
-</HTML>
-
diff --git a/lib/tools/src/Makefile b/lib/tools/src/Makefile
index 9fcfb79628..7301ff856a 100644
--- a/lib/tools/src/Makefile
+++ b/lib/tools/src/Makefile
@@ -37,7 +37,6 @@ RELSYSDIR = $(RELEASE_PATH)/lib/tools-$(VSN)
MODULES= \
cover \
- cover_web \
eprof \
fprof \
cprof \
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index d16ca7f406..87de31919f 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -20,9 +20,7 @@
-module(cover).
%%
-%% This module implements the Erlang coverage tool. The module named
-%% cover_web implements a user interface for the coverage tool to run
-%% under webtool.
+%% This module implements the Erlang coverage tool.
%%
%% ARCHITECTURE
%% The coverage tool consists of one process on each node involved in
@@ -2004,9 +2002,7 @@ munge_expr({lc,Line,Expr,Qs}, Vars) ->
{MungedQs, Vars3} = munge_qualifiers(Qs, Vars2),
{{lc,Line,MungedExpr,MungedQs}, Vars3};
munge_expr({bc,Line,Expr,Qs}, Vars) ->
- {bin,BLine,[{bin_element,EL,Val,Sz,TSL}|Es]} = Expr,
- Expr2 = {bin,BLine,[{bin_element,EL,Val,Sz,TSL}|Es]},
- {MungedExpr,Vars2} = munge_expr(Expr2, Vars),
+ {MungedExpr,Vars2} = munge_expr(?BLOCK1(Expr), Vars),
{MungedQs, Vars3} = munge_qualifiers(Qs, Vars2),
{{bc,Line,MungedExpr,MungedQs}, Vars3};
munge_expr({block,Line,Body}, Vars) ->
diff --git a/lib/tools/src/cover_web.erl b/lib/tools/src/cover_web.erl
deleted file mode 100644
index ae8b3f25cf..0000000000
--- a/lib/tools/src/cover_web.erl
+++ /dev/null
@@ -1,1185 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2009. 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(cover_web).
--author('[email protected]').
--behaviour(gen_server).
-
-%%Export of configuration function
--export([configData/0]).
-%% External exports
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- terminate/2, code_change/3]).
-
--export([start_link/0,start/0,stop/0]).
--export([menu_frame/2,nodes_frame/2,import_frame/2,
- compile_frame/2,result_frame/2]).
--export([list_dir/2,compile/2,add_node/2,remove_node/2,result/2,
- calls/2,coverage/2,import/2]).
-
--record(state,{dir}).
-
--include_lib("kernel/include/file.hrl").
-
-%% Timeouts
--define(DEFAULT_TIME,10000).
--define(MAX_COMPILE_TIME,60000).
--define(MAX_ANALYSE_TIME,30000).
-
-%% Colors
--define(INFO_BG_COLOR,"#C0C0EA").
-
-%%%----------------------------------------------------------------------
-%%% API - called from erlang shell
-%%%----------------------------------------------------------------------
-%% Start webtool and webcover from erlang shell
-start() ->
- webtool:start(),
- webtool:start_tools([],"app=webcover"),
- ok.
-
-%% Stop webtool and webcover from erlang shell
-stop() ->
- webtool:stop_tools([],"app=webcover"),
- webtool:stop().
-
-
-
-%%%----------------------------------------------------------------------
-%%% API - called from webtool
-%%%----------------------------------------------------------------------
-start_link() ->
- gen_server:start_link({local, webcover_server},cover_web, [], []).
-
-
-nodes_frame(Env,Input)->
- call({nodes_frame,Env,Input}).
-
-add_node(Env,Input)->
- call({add_node,Env,Input}).
-
-remove_node(Env,Input)->
- call({remove_node,Env,Input}).
-
-compile_frame(Env,Input)->
- call({compile_frame,Env,Input}).
-
-list_dir(Env,Input) ->
- call({list_dir,Env,Input}).
-
-compile(Env,Input)->
- call({compile,Env,Input},?MAX_COMPILE_TIME).
-
-result_frame(Env,Input)->
- call({result_frame,Env,Input}).
-
-result(Env,Input) ->
- call({result,Env,Input},?MAX_ANALYSE_TIME).
-
-calls(Env,Input) ->
- call({calls,Env,Input}).
-
-coverage(Env,Input) ->
- call({coverage,Env,Input}).
-
-import_frame(Env,Input)->
- call({import_frame,Env,Input}).
-
-import(Env,Input)->
- call({import,Env,Input}).
-
-menu_frame(Env,Input)->
- call({menu_frame,Env,Input}).
-
-call(Msg) ->
- call(Msg,?DEFAULT_TIME).
-call(Msg,Time) ->
- gen_server:call(webcover_server,Msg,Time).
-
-
-
-configData()->
- {webcover,[{web_data,{"WebCover","/webcover"}},
- {alias,{"/webcover",code:priv_dir(tools)}},
- {alias,{erl_alias,"/webcover/erl",[cover_web]}},
- {start,{child,{{local,webcover_server},
- {cover_web,start_link,[]},
- permanent,100,worker,[cover_web]}}}
- ]}.
-
-
-%%%----------------------------------------------------------------------
-%%% Callback functions from gen_server
-%%%----------------------------------------------------------------------
-
-%%----------------------------------------------------------------------
-%% Func: init/1
-%% Returns: {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%%----------------------------------------------------------------------
-init([]) ->
- cover:start(),
- CS = whereis(cover_server),
- link(CS),
- GL = spawn_link(fun group_leader_proc/0),
- group_leader(GL,CS),
-
- %% Must trap exists in order to have terminate/2 executed when
- %% crashing because of a linked process crash.
- process_flag(trap_exit,true),
- {ok,Cwd} = file:get_cwd(),
- {ok, #state{dir=Cwd}}.
-
-group_leader_proc() ->
- register(cover_group_leader_proc,self()),
- group_leader_loop([]).
-group_leader_loop(Warnings) ->
- receive
- {io_request,From,ReplyAs,{put_chars,io_lib,Func,[Format,Args]}} ->
- Msg = (catch io_lib:Func(Format,Args)),
- From ! {io_reply,ReplyAs,ok},
- case lists:member(Msg,Warnings) of
- true -> group_leader_loop(Warnings);
- false -> group_leader_loop([Msg|Warnings])
- end;
- {io_request,From,ReplyAs,{put_chars,_Encoding,io_lib,Func,[Format,Args]}} ->
- Msg = (catch io_lib:Func(Format,Args)),
- From ! {io_reply,ReplyAs,ok},
- case lists:member(Msg,Warnings) of
- true -> group_leader_loop(Warnings);
- false -> group_leader_loop([Msg|Warnings])
- end;
- IoReq when element(1,IoReq)=:= io_request ->
- group_leader() ! IoReq,
- group_leader_loop(Warnings);
- {From,get_warnings} ->
- Warnings1 =
- receive
- {io_request,From,ReplyAs,
- {put_chars,io_lib,Func,[Format,Args]}} ->
- Msg = (catch io_lib:Func(Format,Args)),
- From ! {io_reply,ReplyAs,ok},
- case lists:member(Msg,Warnings) of
- true -> Warnings;
- false -> [Msg|Warnings]
- end
- after 0 ->
- Warnings
- end,
- From ! {warnings,Warnings1},
- group_leader_loop([])
- end.
-
-%%----------------------------------------------------------------------
-%% Func: handle_call/3
-%% Returns: {reply, Reply, State} |
-%% {reply, Reply, State, Timeout} |
-%% {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, Reply, State} | (terminate/2 is called)
-%% {stop, Reason, State} (terminate/2 is called)
-%%----------------------------------------------------------------------
-handle_call({nodes_frame,_Env,_Input},_From,State)->
- {reply,nodes_frame1(),State};
-
-handle_call({add_node,_Env,Input},_From,State)->
- {reply,do_add_node(Input),State};
-
-handle_call({remove_node,_Env,Input},_From,State)->
- {reply,do_remove_node(Input),State};
-
-handle_call({compile_frame,_Env,_Input},_From,State)->
- {reply,compile_frame1(State#state.dir),State};
-
-handle_call({list_dir,_Env,Input},_From,State)->
- Dir = get_input_data(Input,"path"),
- case filelib:is_dir(Dir) of
- true ->
- {reply,compile_frame1(Dir),State#state{dir=Dir}};
- false ->
- Err = Dir ++ " is not a directory",
- {reply,compile_frame1(State#state.dir,Err),State}
- end;
-handle_call({compile,_Env,Input},_From,State)->
- {reply,do_compile(Input,State#state.dir),State};
-
-handle_call({result_frame,_Env,_Input},_From,State)->
- {reply,result_frame1(),State};
-
-handle_call({result,_Env,Input},_From,State)->
- {reply,handle_result(Input),State};
-
-handle_call({calls,_Env,Input},_From,State)->
- {reply,call_page(Input),State};
-
-handle_call({coverage,_Env,Input},_From,State)->
- {reply,coverage_page(Input),State};
-
-handle_call({import_frame,_Env,_Input},_From,State)->
- {ok,Cwd} = file:get_cwd(),
- {reply,import_frame1(Cwd),State};
-
-handle_call({import,_Env,Input},_From,State)->
- {reply,do_import(Input),State};
-
-handle_call({menu_frame,_Env,_Input},_From,State)->
- {reply,menu_frame1(),State};
-
-handle_call(_Request, _From, State) ->
- Reply = bad_request,
- {reply, Reply, State}.
-
-
-%%----------------------------------------------------------------------
-%% Func: handle_cast/2
-%% Returns: {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State} (terminate/2 is called)
-%%----------------------------------------------------------------------
-handle_cast(_Msg, State) ->
- {noreply, State}.
-
-%%----------------------------------------------------------------------
-%% Func: handle_info/2
-%% Returns: {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State} (terminate/2 is called)
-%%----------------------------------------------------------------------
-handle_info({'EXIT',_Pid,Reason}, State) ->
- {stop, Reason, State}.
-
-%%----------------------------------------------------------------------
-%% Func: terminate/2
-%% Purpose: Shutdown the server
-%% Returns: any (ignored by gen_server)
-%%----------------------------------------------------------------------
-terminate(_Reason, _State) ->
- cover:stop(),
- ok.
-
-%%--------------------------------------------------------------------
-%% Func: code_change/3
-%% Purpose: Convert process state when code is changed
-%% Returns: {ok, NewState}
-%%--------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%%----------------------------------------------------------------------
-%%% Internal functions
-%%%----------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% The functions that creates the whole pages by collecting all the %%
-%% neccessary data for each page. These functions are the public %%
-%% interface. %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%----------------------------------------------------------------------
-%% Returns the page to the left frame
-%%----------------------------------------------------------------------
-menu_frame1()->
- [header(),html_header(""),menu_body(),html_end()].
-
-%%----------------------------------------------------------------------
-%% Creates the page where the user can add and remove nodes
-%%----------------------------------------------------------------------
-
-nodes_frame1()->
- nodes_frame1([]).
-nodes_frame1(Err)->
- [header(),html_header("Add/remove nodes"),nodes_body(Err),html_end()].
-
-%%----------------------------------------------------------------------
-%% Creates the page where the user can cover compile modules
-%%----------------------------------------------------------------------
-
-compile_frame1(Dir)->
- compile_frame1(Dir,[]).
-compile_frame1(Dir,Err) ->
- [header(),html_header("Cover compile"),compile_body(Dir,Err),html_end()].
-
-%%----------------------------------------------------------------------
-%% Creates the page where the user can handle results
-%%----------------------------------------------------------------------
-
-result_frame1()->
- result_frame1([]).
-result_frame1(Err) ->
- [header(),html_header("Show cover results"),result_body(Err),html_end()].
-
-%%----------------------------------------------------------------------
-%%The beginning of the page that clear the cover information on a cover
-%%compiled module
-%%----------------------------------------------------------------------
-call_page(Input)->
- [header(),html_header("Code coverage"),call_result(Input),html_end()].
-
-coverage_page(Input)->
- [header(),html_header("Code coverage"),coverage_result(Input),html_end()].
-
-%%----------------------------------------------------------------------
-%% Creates the page where the user an import files
-%%----------------------------------------------------------------------
-import_frame1(Dir) ->
- import_frame1(Dir,"").
-import_frame1(Dir,Err) ->
- [header(),html_header("Import coverdata"),import_body(Dir,Err),html_end()].
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% The functions that build the body of the menu frame %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-menu_body() ->
- Nodes = cover:which_nodes(),
- Modules = cover:modules(),
- Imported = cover:imported(),
- ["<A HREF=\"./nodes_frame\" TARGET=\"main\">Nodes</A><BR>\n",
- "<A HREF=\"./compile_frame\" TARGET=\"main\">Compile</A><BR>\n",
- "<A HREF=\"./import_frame\" TARGET=\"main\">Import</A><BR>\n",
- "<A HREF=\"./result_frame\" TARGET=\"main\">Result</A>\n",
- "<P><B>Nodes:</B>\n",
- "<UL>\n",
- lists:map(fun(N) -> "<LI>"++atom_to_list(N)++"</LI>\n" end,[node()|Nodes]),
- "</UL>\n",
- "<P><B>Compiled modules:</B>\n",
- "<UL>\n",
- lists:map(fun(M) -> "<LI>"++atom_to_list(M)++"</LI>\n" end,Modules),
- "</UL>\n",
- "<P><B>Imported files:</B>\n",
- "<UL>\n",
- "<FONT SIZE=-1>\n",
- lists:map(fun(F) ->
- Short = filename:basename(F),
- "<LI TITLE=\""++F++"\">"++Short++"</LI>\n" end,Imported),
- "</FONT>\n",
- "</UL>\n"].
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% The functions that build the body of the nodes frame %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-nodes_body(Err) ->
- CN = cover:which_nodes(),
- Fun = fun(N) ->
- NStr = atom_to_list(N),
- ["<OPTION VALUE=",NStr,
- " onClick=\"node.value=selected_node.value\">",NStr,
- "</OPTION>\n"]
- end,
- AllNodes = lists:append(lists:map(Fun,nodes()--CN)),
- CoverNodes = lists:append(lists:map(Fun,CN)),
-
- [reload_menu_script(Err),
- "<H1 ALIGN=center>Nodes</H1>\n",
- "<TABLE BORDER=0 WIDTH=600 ALIGN=center>\n",
- "<TR><TD BGCOLOR=",?INFO_BG_COLOR," COLSPAN=2>\n",
- "<P>You can run cover over several nodes simultaneously. Coverage data\n",
- "from all involved nodes will be merged during analysis.\n",
- "<P>Select or enter node names to add or remove here.\n",
- "</TD></TR>\n",
- "<TR><TD COLSPAN=2><BR><BR></TD></TR>\n",
- "<FORM ACTION=\"./add_node\" NAME=add_node>\n",
- "<TR><TD VALIGN=top>Add node:</TD>\n",
- "<TD><INPUT TYPE=text NAME=\"node\" SIZE=40 >",
- "<INPUT TYPE=submit\n",
- " onClick=\"if(!node.value){node.value=selected_node.value};\" VALUE=Add>"
- "<BR><SELECT NAME=selected_node TITLE=\"Select node\">\n",
- AllNodes ++
- "</SELECT>\n",
- "</TD></TR>\n"
- "</FORM>\n",
- "<TR><TD COLSPAN=2><BR><BR></TD></TR>\n",
- "<FORM ACTION=\"./remove_node\" NAME=remove_node>\n",
- "<TR><TD>Remove node:</TD>\n",
- "<TD><SELECT NAME=node TITLE=\"Select node\">\n",
- CoverNodes ++
- "</SELECT>\n",
- "<INPUT TYPE=submit VALUE=Remove>"
- "</TD></TR>\n",
- "</FORM>",
- "</TABLE>"].
-
-
-do_add_node(Input) ->
- NodeStr = get_input_data(Input, "node"),
- Node = list_to_atom(NodeStr),
- case net_adm:ping(Node) of
- pong ->
- cover:start(Node),
- nodes_frame1();
- pang ->
- nodes_frame1("Node \\\'" ++ NodeStr ++ "\\\' is not alive")
- end.
-
-do_remove_node(Input) ->
- Node = list_to_atom(get_input_data(Input, "node")),
- cover:stop(Node),
- nodes_frame1().
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% The functions that is used when the user wants to compile something %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-compile_body(Dir,Err) ->
- Erls = filelib:wildcard(filename:join(Dir,"*.erl")),
- Beams = filelib:wildcard(filename:join(Dir,"*.beam")),
-
- [reload_menu_script(Err),
- "<H1 ALIGN=center>Compile</H1>\n",
- "<TABLE WIDTH=600 ALIGN=center BORDER=0>\n",
- "<TR><TD COLSPAN=3 BGCOLOR=",?INFO_BG_COLOR,">\n",
- "Each module which shall be part of the cover analysis must be prepared\n",
- "or 'cover compiled'. On this page you can select .erl files and/or\n",
- ".beam files to include in the analysis. If you select a .erl file it\n",
- "will first be compiled with the Erlang compiler and then prepared for\n",
- "coverage analysis. If you select a .beam file it will be prepared for\n",
- "coverage analysis directly.\n",
- "</TD></TR>\n",
- "<FORM ACTION=\"./list_dir\" NAME=list_dir>\n",
- "<TR><TD WIDTH=30% BGCOLOR=",?INFO_BG_COLOR," ROWSPAN=2>\n",
- "To list a different directory, enter the directory name here.\n",
- "</TD>\n",
- "<TH COLSPAN=2><BR>List directory:<BR></TH>\n",
- "</TR>\n",
- "<TR><TD ALIGN=center COLSPAN=2>\n",
- "<INPUT TYPE=text NAME=\"path\" SIZE=40 VALUE=",Dir,">",
- "<INPUT TYPE=submit VALUE=Ok>",
- "<BR><BR></TD></TR>\n",
- "</FORM>\n",
- "<FORM ACTION=\"./compile\" NAME=compile_selection>\n",
- "<TR><TD BGCOLOR=",?INFO_BG_COLOR," ROWSPAN=2>\n",
- "<P>Select one or more .erl or .beam files to prepare for coverage\n"
- "analysis, and click the \"Compile\" button.\n",
- "<P>To reload the original file after coverage analysis is complete,\n"
- "select one or more files and click the \"Uncompile\" button, or\n",
- "simply click the \"Uncompile all\" button to reload all originals.\n"
- "</TD>\n",
- "<TH>.erl files</TH><TH>.beam files</TH></TR>\n",
- "<TR><TD ALIGN=center VALIGN=top>\n",
- "<SELECT NAME=erl TITLE=\"Select .erl files to compile\" MULTIPLE=true",
- " SIZE=15>\n",
- list_modules(Erls) ++
- "</SELECT></TD>\n",
- "<TD ALIGN=center VALIGN=top>\n",
- "<SELECT NAME=beam TITLE=\"Select .beam files to compile\"MULTIPLE=true",
- " SIZE=15>\n",
- list_modules(Beams) ++
- "</SELECT></TD></TR>\n"
- "<TR><TD BGCOLOR=",?INFO_BG_COLOR," ROWSPAN=2>\n",
- "Compile options are only needed for .erl files. The options must be\n"
- "given e.g. like this: \n"
- "<FONT SIZE=-1>[{i,\"/my/path/include\"},{i,\"/other/path/\"}]</FONT>\n"
- "</TD>\n",
- "<TH COLSPAN=2><BR>Compile options:<BR></TH>\n",
- "</TR>\n",
- "<TR><TD COLSPAN=2 ALIGN=center>\n",
- "<INPUT TYPE=text NAME=\"options\" SIZE=40>\n",
- "<INPUT TYPE=hidden NAME=\"action\"></TD></TR>\n",
- "<TR><TD></TD><TD ALIGN=center COLSPAN=2>\n",
- "<INPUT TYPE=submit onClick=\"action.value=\'compile\';\"VALUE=Compile>",
- "<INPUT TYPE=submit onClick=\"action.value=\'uncompile\';\" ",
- "VALUE=Uncompile>",
- "<INPUT TYPE=submit onClick=\"action.value=\'uncompile_all\';\" ",
- "VALUE=\"Uncompile all\">",
- "<BR><INPUT TYPE=reset VALUE=\"Reset form\"></TD></TR>\n",
- "</FORM>\n",
- "</TABLE>\n"].
-
-list_modules([File|Files]) ->
- Mod = filename:basename(File),
- ["<OPTION VALUE=",File," onDblClick=\"action.value=\'compile\';submit();\">",
- Mod,"</OPTION>\n" | list_modules(Files)];
-list_modules([]) ->
- [].
-
-do_compile(Input,Dir) ->
- {Erls,Beams,Opts,Action} = get_compile_input(parse(Input),[],[]),
- Errs =
- case Action of
- "compile" ->
- do_compile(Erls,Beams,Opts,[]);
- "uncompile" ->
- do_uncompile(Erls++Beams);
- "uncompile_all" ->
- do_uncompile(cover:modules())
- end,
- compile_frame1(Dir,Errs).
-
-get_compile_input([{"erl",File}|Input],Erl,Beam) ->
- get_compile_input(Input,[File|Erl],Beam);
-get_compile_input([{"beam",File}|Input],Erl,Beam) ->
- get_compile_input(Input,Erl,[File|Beam]);
-get_compile_input([{"options",Opts0},{"action",Action}],Erl,Beam) ->
- Opts = parse_options(Opts0),
- {Erl,Beam,Opts,Action}.
-
-do_compile([Erl|Erls],Beams,Opts,Errs) ->
- case cover:compile_module(Erl,Opts) of
- {ok,_} ->
- do_compile(Erls,Beams,Opts,Errs);
- {error,File} ->
- do_compile(Erls,Beams,Opts,["\\n"++File|Errs])
- end;
-do_compile([],[Beam|Beams],Opts,Errs) ->
- case cover:compile_beam(Beam) of
- {ok,_} ->
- do_compile([],Beams,Opts,Errs);
- {error,{no_abstract_code,File}} ->
- do_compile([],Beams,Opts,["\\n"++File++" (no_abstract_code)"|Errs])
- end;
-do_compile([],[],_,[]) ->
- [];
-do_compile([],[],_,Errs) ->
- "Compilation failed for the following files:" ++ Errs.
-
-parse_options(Options)->
- case erl_scan:string(Options ++".") of
- {ok,Tokens,_Line} ->
- case erl_parse:parse_exprs(Tokens) of
- {ok,X}->
- case lists:map(fun erl_parse:normalise/1, X) of
- [List] when is_list(List) -> List;
- List -> List
- end;
- _ ->
- []
- end;
- _ ->
- []
- end.
-
-
-do_uncompile(Files) ->
- lists:foreach(
- fun(File) ->
- Module =
- if is_atom(File) ->
- File;
- true ->
- ModStr = filename:basename(filename:rootname(File)),
- list_to_atom(ModStr)
- end,
- case code:which(Module) of
- cover_compiled ->
- code:purge(Module),
- case code:load_file(Module) of
- {module, Module} ->
- ok;
- {error, _Reason2} ->
- code:delete(Module)
- end;
- _ ->
- ok
- end
- end,
- Files),
- [].
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% The functions that builds the body of the page for coverage analysis%
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-result_body(Err) ->
- [reload_menu_script(Err),
- "<H1 ALIGN=center>Result</H1>\n",
- "<TABLE BORDER=0 WIDTH=600 ALIGN=center>\n",
- "<TR><TD BGCOLOR=",?INFO_BG_COLOR,">\n",
- "<P>After executing all your tests you can view the result of the\n",
- "coverage analysis here. For each module you can\n",
- "<DL>\n",
- "<DT><B>Analyse to file</B></DT>\n",
- "<DD>The source code of the module is shown with the number of calls\n",
- "to each line stated in the left margin. Lines which are never called\n",
- "are colored red.</DD>\n",
- "<DT><B>Analyse coverage</B></DT>\n",
- "<DD>Show the number of covered and uncovered lines in the module.</DD>\n",
- "<DT><B>Analyse calls</B></DT>\n",
- "<DD>Show the number of calls in the module.</DD>\n",
- "<DT><B>Reset module</B></DT>\n",
- "<DD>Delete all coverage data for the module.</DD>\n",
- "<DT><B>Export module</B></DT>\n",
- "<DD>Write all coverage data for the module to a file. The data can\n",
- "later be imported from the \"Import\" page.</DD>\n",
- "</DL>\n",
- "<P>You can also reset or export data for all modules with the\n",
- "<B>Reset all</B> and <B>Export all</B> actions respectively. For these\n",
- "two actions there is no need to select a module.\n",
- "<P>Select module and action from the drop down menus below, and click\n",
- "the \"Execute\" button.\n",
- "</TD></TR>\n",
- "<TR><TD><BR><BR>\n",
- result_selections(),
- "</TD></TR></TABLE>"].
-
-result_selections() ->
- ModList = filter_modlist(cover:modules()++cover:imported_modules(),[]),
-
- ["<FORM ACTION=\"./result\" NAME=result_selection>\n",
- "<TABLE WIDTH=\"300\" BORDER=0 ALIGN=center>\n",
- "<TR><TD ALIGN=left>\n",
- "Module:\n",
- "<BR><SELECT NAME=module TITLE=\"Select module\">\n",
- ModList ++
- "</SELECT>\n",
- "</TD>\n",
- "<TD ALIGN=left>\n",
- "Action:\n",
- "<BR><SELECT NAME=action TITLE=\"Select action\">\n",
- "<OPTION VALUE=\"analyse_to_file\">Analyse to file</OPTION>\n"
- "<OPTION VALUE=\"coverage\">Analyse coverage</OPTION>\n"
- "<OPTION VALUE=\"calls\">Analyse calls</OPTION>\n"
- "<OPTION VALUE=\"reset\">Reset module</OPTION>\n"
- "<OPTION VALUE=\"reset_all\">Reset all</OPTION>\n"
- "<OPTION VALUE=\"export\">Export module</OPTION>\n"
- "<OPTION VALUE=\"export_all\">Export all</OPTION>\n"
- "</SELECT>\n",
- "</TD>\n",
- "<TD ALIGN=center VALIGN=bottom><INPUT TYPE=submit VALUE=Execute>\n"
- "</TD></TR>\n"
- "</TABLE>\n",
- "</FORM>\n"].
-
-filter_modlist([M|Ms],Already) ->
- case lists:member(M,Already) of
- true ->
- filter_modlist(Ms,Already);
- false ->
- MStr = atom_to_list(M),
- ["<OPTION VALUE=",MStr,">",MStr,"</OPTION>\n" |
- filter_modlist(Ms,[M|Already])]
- end;
-filter_modlist([],_Already) ->
- [].
-
-
-
-handle_result(Input) ->
- case parse(Input) of
- [{"module",M},{"action",A}] ->
- case A of
- "analyse_to_file" ->
- case cover:analyse_to_file(list_to_atom(M),[html]) of
- {ok,File} ->
- case file:read_file(File) of
- {ok,HTML}->
- file:delete(File),
- [header(),
- reload_menu_script(""),
- binary_to_list(HTML)];
- _ ->
- result_frame1("Can not read file" ++ File)
- end;
- {error,no_source_code_found} ->
- result_frame1("No source code found for \\\'" ++
- M ++ "\\\'")
- end;
- "calls" ->
- call_page(Input);
- "coverage" ->
- coverage_page(Input);
- "reset" ->
- cover:reset(list_to_atom(M)),
- result_frame1("Coverage data for \\\'" ++ M ++
- "\\\' is now reset");
- "reset_all" ->
- cover:reset(),
- result_frame1("All coverage data is now reset");
- "export" ->
- ExportFile = generate_filename(M),
- cover:export(ExportFile,list_to_atom(M)),
- result_frame1("Coverage data for \\\'" ++ M ++
- "\\\' is now exported to file \\\"" ++
- ExportFile ++ "\\\"");
- "export_all" ->
- ExportFile = generate_filename("COVER"),
- cover:export(ExportFile),
- result_frame1(
- "All coverage data is now exported to file \\\"" ++
- ExportFile ++ "\\\"")
- end;
- [{"action",_A}] ->
- result_frame1("No module is selected")
- end.
-
-generate_filename(Prefix) ->
- {ok,Cwd} = file:get_cwd(),
- filename:join(Cwd,Prefix ++ "_" ++ ts() ++ ".coverdata").
-
-ts() ->
- {{Y,M,D},{H,Min,S}} = calendar:now_to_local_time(erlang:timestamp()),
- io_lib:format("~4.4.0w~2.2.0w~2.2.0w-~2.2.0w~2.2.0w~2.2.0w",
- [Y,M,D,H,Min,S]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% The functions that builds the body of the page that shows the calls %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-call_result(Input)->
- Mod = list_to_atom(get_input_data(Input, "module")),
- case cover:analyse(Mod,calls) of
- {error,_}->
- error_body();
- {ok,_} ->
- call_result2(Mod,Input)
- end.
-
-call_result2(Mod,Input)->
- Result =
- case get_input_data(Input,"what") of
- "mod" ->
- call_result(mod,Mod);
- "func" ->
- call_result(func,Mod);
- "clause" ->
- call_result(clause,Mod);
- _->
- call_result(all,Mod)
- end,
- result_choice("calls",Mod) ++ Result.
-
-result_choice(Level,Mod)->
- ModStr=atom_to_list(Mod),
- [reload_menu_script(""),
- "<TABLE WIDTH=100%><TR>\n",
- "<TD><A HREF=./",Level,"?module=",ModStr,"&what=all>All Data</A></TD>\n",
- "<TD><A HREF=./",Level,"?module=",ModStr,"&what=mod>Module</A></TD>\n",
- "<TD><A HREF=./",Level,"?module=",ModStr,"&what=func>Function</A></TD>\n",
- "<TD><A HREF=./",Level,"?module=",ModStr,"&what=clause>Clause</A></TD>\n",
- "</TR></TABLE><BR>\n"].
-
-call_result(Mode,Module)->
- Content =
- case Mode of
- mod->
- format_cover_call(cover:analyse(Module,calls,module),mod);
- func->
- format_cover_call(cover:analyse(Module,calls,function),func);
- clause->
- format_cover_call(cover:analyse(Module,calls,clause),clause);
- _->
- format_cover_call(cover:analyse(Module,calls,module),mod) ++
- format_cover_call(cover:analyse(Module,calls,function),func)++
- format_cover_call(cover:analyse(Module,calls,clause),clause)
- end,
- getModDate(Module,date())++"<BR>"++
- "<TABLE WIDTH=\"100%\" BORDER=1>"
- ++ Content ++"</TABLE>".
-
-
-format_cover_call({error,_},_)->
- ["<TR><TD>\n",
- "<BR><BR><BR><BR>\n",
- "<FONT SIZE=5>The selected module is not Cover Compiled</FONT>\n",
- "<BR>\n",
- "</TD></TR>\n"];
-
-format_cover_call({ok,{Mod,Calls}},mod)->
- ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=5><B>Module calls</B></TD></TR>\n",
- "<TR><TD COLSPAN=4><I>Module</I></TD>",
- "<TD ALIGN=\"right\"><I>Number of calls</I></TD></TR>\n",
- "<TR><TD COLSPAN=4>" ++ atom_to_list(Mod) ++"</TD>"
- "<TD ALIGN=\"right\">" ++ integer_to_list(Calls)++"</TD></TR>\n"];
-
-format_cover_call({ok,Calls},func)->
- ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=5><B>Function calls</B></TD></TR>\n",
- "<TR><TD><I>Module</I></TD><TD><I>Function</I></TD>",
- "<TD COLSPAN=2 ALIGN=\"right\"><I>Arity</I></TD>",
- "<TD ALIGN=\"right\"><I>Number of calls </I></TD></TR>\n",
- lists:append(
- lists:map(
- fun({{Mod,Func,Arity},Nr_of_calls})->
- ["<TR><TD WIDTH=\"20%\">"++ atom_to_list(Mod)++"</TD>\n",
- "<TD WIDTH=\"20%\" >" ++ atom_to_list(Func) ++" </TD>\n",
- "<TD COLSPAN=2 WIDTH=\"40%\" ALIGN=\"right\">",
- integer_to_list(Arity),
- "</TD>\n",
- "<TD WIDTH=\"20%\" ALIGN=\"right\">",
- integer_to_list(Nr_of_calls),
- "</TD></TR>\n"]
- end,
- Calls))];
-
-format_cover_call({ok,Calls},clause)->
- ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=5><B>Clause calls</B></TD></TR>\n",
- "<TR><TD><I>Module</I></TD><TD><I>Function</I></TD>",
- "<TD ALIGN=\"right\"><I>Arity</I></TD>",
- "<TD ALIGN=\"right\"><I>Ordinal</I></TD>",
- "<TD ALIGN=\"right\"><I>Number of calls</I></TD></TR>\n",
- lists:append(
- lists:map(
- fun({{Mod,Func,Arity,Ord},Nr_of_calls})->
- ["<TR><TD WIDTH=\"20%\" >", atom_to_list(Mod), "</TD>\n",
- "<TD WIDTH=\"20%\" >", atom_to_list(Func), "</TD>\n",
- "<TD WIDTH=\"20%\" ALIGN=\"right\">",
- integer_to_list(Arity),
- "</TD>\n",
- "<TD WIDTH=\"20%\" ALIGN=\"right\">",
- integer_to_list(Ord),
- "</TD>\n",
- "<TD WIDTH=\"20%\" ALIGN=\"right\">",
- integer_to_list(Nr_of_calls),
- "</TD></TR>\n"]
- end,
- Calls))].
-
-
-error_body()->
- ["<TABLE WIDTH=\"100%\" BORDER=1>\n",
- "<TR ALIGN=\"center\">\n",
- "<TD>\n",
- "<BR><BR><BR><BR><BR><BR>\n",
- "<FONT SIZE=5>The selected module is not Cover Compiled</FONT>\n",
- "<BR>\n",
- "</TD>\n",
- "</TR>\n",
- "</TABLE>\n"].
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% The functions that builds the body of the page that shows coverage %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-coverage_result(Input)->
- Mod = list_to_atom(get_input_data(Input, "module")),
- case cover:analyse(Mod,coverage) of
- {error,_}->
- error_body();
- {ok,_} ->
- coverage_result2(Mod,Input)
- end.
-
-coverage_result2(Mod,Input)->
- Result =
- case get_input_data(Input,"what") of
- "mod" ->
- coverage_result(mod,Mod);
- "func" ->
- coverage_result(func,Mod);
- "clause" ->
- coverage_result(clause,Mod);
- _->
- coverage_result(all,Mod)
- end,
- result_choice("coverage",Mod) ++ Result.
-
-coverage_result(Mode,Module)->
- Content =
- case Mode of
- mod->
- format_cover_coverage(cover:analyse(Module,coverage,module),
- mod);
- func->
- format_cover_coverage(cover:analyse(Module,coverage,function),
- func);
- clause->
- format_cover_coverage(cover:analyse(Module,coverage,clause),
- clause);
- _->
- format_cover_coverage(cover:analyse(Module,coverage,module),
- mod) ++
- format_cover_coverage(cover:analyse(Module,coverage,function),
- func)++
- format_cover_coverage(cover:analyse(Module,coverage,clause),
- clause)
- end,
- getModDate(Module,date())++"<BR>"++
- "<TABLE WIDTH=\"100%\" BORDER=1>"
- ++ Content ++"</TABLE>".
-
-getModDate(Module,{Year,Mon,Day})->
- "<TABLE>
- <TR>
- <TD>Module:</TD>
- <TD>" ++ atom_to_list(Module) ++ "</TD>
- </TR>
- <TR>
- <TD>Date:</TD>
- <TD>" ++ integer_to_list(Day) ++ "/" ++
- integer_to_list(Mon) ++"&nbsp;-&nbsp;"++
- integer_to_list(Year) ++
- "</TD>
- </TR>
- </TABLE>".
-
-
-format_cover_coverage({error,_},_)->
- "<TR><TD>
- <BR><BR><BR><BR>
- <FONT SIZE=5>The selected module is not Cover Compiled</FONT>
- <BR>
- </TD></TR>";
-
-
-format_cover_coverage({ok,{Mod,{Cov,Not_cov}}},mod)->
- ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=6><B>Module coverage</B></TD></TR>\n",
- "<TR><TD COLSPAN=4><I>Module</I></TD>\n",
- "<TD ALIGN=\"right\"><I>Covered</I></TD>\n"
- "<TD ALIGN=\"RIGHT\" NOWRAP=\"true\"><I>Not Covered</I></TD>\n",
- "</TR>\n",
- "<TR><TD COLSPAN=4>", atom_to_list(Mod), "</TD>\n"
- "<TD ALIGN=\"right\">", integer_to_list(Cov), "</TD>\n"
- "<TD ALIGN=\"right\" >", integer_to_list(Not_cov), "</TD></TR>\n"];
-
-format_cover_coverage({ok,Cov_res},func)->
- ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=6><B>Function coverage</B></TD>\n",
- "</TR>\n",
- "<TR><TD><I>Module</I></TD><TD><I>Function</I></TD>",
- "<TD ALIGN=\"right\"><I>Arity</I></TD>",
- "<TD COLSPAN=2 ALIGN=\"right\"><I>Covered</I></TD>",
- "<TD ALIGN=\"right\" STYLE=\"white-space:nowrap\"><I>Not Covered</I></TD>",
- "</TR>\n",
- lists:append(
- lists:map(
- fun({{Mod,Func,Arity},{Cov,Not_cov}})->
- ["<TR><TD WIDTH=\"20%\" >"++ atom_to_list(Mod) ++" </TD>\n",
- "<TD WIDTH=\"20%\" >" ++ atom_to_list(Func) ++"</TD>\n",
- "<TD WIDTH=\"40%\" ALIGN=\"right\">",
- integer_to_list(Arity),
- "</TD>\n",
- "<TD WIDTH=\"40%\" ALIGN=\"right\" COLSPAN=2>",
- integer_to_list(Cov),
- "</TD>\n"
- "<TD WIDTH=\"20%\" ALIGN=\"right\">",
- integer_to_list(Not_cov),
- "</TD></TR>\n"]
- end,
- Cov_res))];
-
-format_cover_coverage({ok,Cov_res},clause)->
- ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=6><B>Clause coverage</B></TD></TR>\n",
- "<TR><TD><I>Module</I></TD><TD><I>Function</I></TD>\n",
- "<TD ALIGN=\"right\"><I>Arity</I></TD>\n",
- "<TD ALIGN=\"right\"><I>Ordinal<I></TD>\n",
- "<TD ALIGN=\"right\">Covered</TD>\n",
- "<TD ALIGN=\"right\" STYLE=\"white-space:nowrap\">Not Covered</TD></TR>\n",
- lists:append(
- lists:map(
- fun({{Mod,Func,Arity,Ord},{Cov,Not_cov}})->
- ["<TR><TD WIDTH=\"20%\" >"++ atom_to_list(Mod) ++"</TD>\n",
- "<TD WIDTH=\"20%\" >" ++ atom_to_list(Func) ++" </TD>\n",
- "<TD WIDTH=\"20%\" ALIGN=\"right\">",
- integer_to_list(Arity),
- "</TD>\n"
- "<TD WIDTH=\"20%\" ALIGN=\"right\">",
- integer_to_list(Ord),
- "</TD>\n"
- "<TD WIDTH=\"20%\" ALIGN=\"right\">",
- integer_to_list(Cov),
- "</TD>\n"
- "<TD WIDTH=\"20%\" ALIGN=\"right\">",
- integer_to_list(Not_cov),
- "</TD></TR>\n"]
- end,
- Cov_res))].
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% The functions that builds the body of the import page %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-import_body(Dir,Err) ->
- [reload_menu_script(Err),
- "<H1 ALIGN=center>Import</H1>\n",
- "<TABLE BORDER=0 WIDTH=600 ALIGN=center>\n",
- "<TR><TD BGCOLOR=",?INFO_BG_COLOR,">\n",
- "<P>You can import coverage data from a previous analysis. If you do so\n",
- "the imported data will be merged with the current coverage data.\n",
- "<P>You can export data from the current analysis from the \"Result\"\n",
- "page.\n",
- "<P>Select the file to import here.\n",
- "</TD></TR>\n",
- "<TR><TD ALIGN=center><BR><BR>\n",
- "<FORM NAME=change_import_dir METHOD=post ACTION=\"./import\">\n",
- "<B>Change directory:</B><BR>\n",
- "<INPUT TYPE=text NAME=\"file\" SIZE=30 VALUE=",Dir,">",
- "<INPUT TYPE=hidden NAME=dir VALUE=",Dir,">\n",
- "<INPUT TYPE=submit VALUE=Ok><BR>\n",
- "</FORM>\n",
- browse_import(Dir),
- "</TABLE>"].
-
-browse_import(Dir) ->
- {ok,List} = file:list_dir(Dir),
- Sorted = lists:reverse(lists:sort(List)),
- {Dirs,Files} = filter_files(Dir,Sorted,[],[]),
- ["<FORM NAME=browse_import METHOD=post ACTION=\"./import\">\n"
- "<SELECT NAME=file TITLE=\"Select import file\" SIZE=10>\n",
- "<OPTION VALUE=\"..\" onDblClick=submit()>../</OPTION>\n",
- Dirs,
- Files,
- "</SELECT>\n",
- "<INPUT TYPE=hidden NAME=dir VALUE=",Dir,">\n",
- "<BR><INPUT TYPE=submit VALUE=Ok>\n"
- "</FORM>\n"].
-
-filter_files(Dir,[File|Files],Ds,Fs) ->
- case filename:extension(File) of
- ".coverdata" ->
- Fs1 = ["<OPTION VALUE=",File," onDblClick=submit()>",
- File,"</OPTION>\n" | Fs],
- filter_files(Dir,Files,Ds,Fs1);
- _ ->
- FullName = filename:join(Dir,File),
- case filelib:is_dir(FullName) of
- true ->
- Ds1 = ["<OPTION VALUE=",File," onDblClick=submit()>",
- File,"/</OPTION>\n" | Ds],
- filter_files(Dir,Files,Ds1,Fs);
- false ->
- filter_files(Dir,Files,Ds,Fs)
- end
- end;
-filter_files(_Dir,[],Ds,Fs) ->
- {Ds,Fs}.
-
-
-
-
-do_import(Input) ->
- case parse(Input) of
- [{"file",File0},{"dir",Dir}] ->
- File = filename:join(Dir,File0),
- case filelib:is_dir(File) of
- true ->
- import_frame1(File);
- false ->
- case filelib:is_file(File) of
- true ->
- case cover:import(File) of
- ok ->
- import_frame1(Dir);
- {error,{cant_open_file,ExportFile,_Reason}} ->
- import_frame1(Dir,
- "Error importing file\\n\\\""
- ++ ExportFile ++ "\\\"")
- end;
- false ->
- import_frame1(Dir,
- "Error importing file\\n\\\"" ++
- File ++ "\\\"")
- end
- end;
- [{"dir",Dir}] ->
- import_frame1(Dir,"No file is selected")
- end.
-
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% Different private helper functions %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%Create the Header for the page If we now the mimetype use that type %%
-%%otherwise use text %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-header() ->
- header("text/html").
-header(MimeType) ->
- "Pragma:no-cache\r\n" ++
- "Content-type: " ++ MimeType ++ "\r\n\r\n".
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%Create the Htmlheader set the title of the page %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-html_header(Title) ->
- "<HTML>\n" ++
- "<HEAD>\n" ++
- "<TITLE>" ++ Title ++ "</TITLE>\n" ++
- "</HEAD>\n"
- "<BODY BGCOLOR=\"#FFFFFF\">\n".
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Close the body- and Html tags %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-html_end()->
- "</BODY></HTML>".
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% A script which reloads the menu frame and possibly pops up an alert%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-reload_menu_script(Err) ->
- ["<SCRIPT>\n",
- "function reloadMenu()\n",
- " {\n",
- " parent.menu.document.location.href=\"./menu_frame\";\n",
- case Err of
- "" -> "";
- _ -> " alert(\""++Err++"\");\n"
- end,
- case get_warnings() of
- [] ->
- "";
- Warnings ->
- " alert(\""++fix_newline(lists:flatten(Warnings))++"\");\n"
- end,
- " }\n",
- "</SCRIPT>\n",
- "<BODY onLoad=reloadMenu() BGCOLOR=\"#FFFFFF\">"].
-
-fix_newline([$\n|Rest]) ->
- [$\\,$n|fix_newline(Rest)];
-fix_newline([$"|Rest]) ->
- [$\\,$"|fix_newline(Rest)];
-fix_newline([Char|Rest]) ->
- [Char|fix_newline(Rest)];
-fix_newline([]) ->
- [].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Control the input data and return the intresting values or error %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-get_input_data(Input,Key)->
- case lists:keysearch(Key,1,parse(Input)) of
- {value,{Key,Value}} ->
- Value;
- false ->
- undefined
- end.
-
-parse(Input) ->
- httpd:parse_query(Input).
-
-
-get_warnings() ->
- cover_group_leader_proc ! {self(), get_warnings},
- receive {warnings,Warnings} ->
- Warnings
- end.
diff --git a/lib/tools/src/lcnt.erl b/lib/tools/src/lcnt.erl
index 3a3cebf3ed..d552d5b46e 100644
--- a/lib/tools/src/lcnt.erl
+++ b/lib/tools/src/lcnt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2010-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.
@@ -94,12 +94,12 @@
-record(stats, {
file :: atom(),
- line :: non_neg_integer(),
+ line :: non_neg_integer() | 'undefined',
tries :: non_neg_integer(),
colls :: non_neg_integer(),
time :: non_neg_integer(), % us
nt :: non_neg_integer(), % #timings collected
- hist :: tuple() % histogram
+ hist :: tuple() | 'undefined' % histogram
}).
-record(lock, {
@@ -757,7 +757,7 @@ list2lock([F|Fs], Ls) ->
stats2stats([]) -> [];
stats2stats([Stat|Stats]) ->
- Sz = tuple_size(#stats{}),
+ Sz = record_info(size, stats),
[stat2stat(Stat,Sz)|stats2stats(Stats)].
stat2stat(Stat,Sz) when tuple_size(Stat) =:= Sz -> Stat;
diff --git a/lib/tools/src/make.erl b/lib/tools/src/make.erl
index 5d5a1ef2bd..26378f28a0 100644
--- a/lib/tools/src/make.erl
+++ b/lib/tools/src/make.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-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.
@@ -299,10 +299,11 @@ check_includes(File, IncludePath, ObjMTime) ->
end.
check_includes2(Epp, File, ObjMTime) ->
+ A1 = erl_anno:new(1),
case epp:parse_erl_form(Epp) of
- {ok, {attribute, 1, file, {File, 1}}} ->
+ {ok, {attribute, A1, file, {File, A1}}} ->
check_includes2(Epp, File, ObjMTime);
- {ok, {attribute, 1, file, {IncFile, 1}}} ->
+ {ok, {attribute, A1, file, {IncFile, A1}}} ->
case file:read_file_info(IncFile) of
{ok, #file_info{mtime=MTime}} when MTime>ObjMTime ->
epp:close(Epp),
diff --git a/lib/tools/src/tools.app.src b/lib/tools/src/tools.app.src
index 978b54719c..a00969eabe 100644
--- a/lib/tools/src/tools.app.src
+++ b/lib/tools/src/tools.app.src
@@ -21,7 +21,6 @@
[{description, "DEVTOOLS CXC 138 16"},
{vsn, "%VSN%"},
{modules, [cover,
- cover_web,
eprof,
fprof,
instrument,
@@ -36,12 +35,12 @@
xref_utils
]
},
- {registered,[webcover_server]},
+ {registered, []},
{applications, [kernel, stdlib]},
{env, [{file_util_search_methods,[{"", ""}, {"ebin", "esrc"}, {"ebin", "src"}]}
]
},
- {runtime_dependencies, ["webtool-0.8.10","stdlib-2.5","runtime_tools-1.8.14",
+ {runtime_dependencies, ["stdlib-2.5","runtime_tools-1.8.14",
"kernel-3.0","inets-5.10","erts-7.0",
"compiler-5.0"]}
]
diff --git a/lib/tools/test/Makefile b/lib/tools/test/Makefile
index 49b86628b7..8768413dc1 100644
--- a/lib/tools/test/Makefile
+++ b/lib/tools/test/Makefile
@@ -53,8 +53,7 @@ RELSYSDIR = $(RELEASE_PATH)/tools_test
# FLAGS
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \
- -I$(ERL_TOP)/lib/percept/include
+ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/percept/include
EBIN = .
diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl
index 71570a55fa..d4b346c407 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -21,7 +21,7 @@
-compile(export_all).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -29,7 +29,7 @@ all() ->
NoStartStop = [eif,otp_5305,otp_5418,otp_7095,otp_8273,
otp_8340,otp_8188,compile_beam_opts,eep37,
analyse_no_beam, line_0, compile_beam_no_file,
- otp_13277],
+ otp_13277, otp_13289],
StartStop = [start, compile, analyse, misc, stop,
distribution, reconnect, die_and_reconnect,
dont_reconnect_after_stop, stop_node_after_disconnect,
@@ -1253,7 +1253,7 @@ otp_8340(doc) ->
["OTP-8340. Bug."];
otp_8340(suite) -> [];
otp_8340(Config) when is_list(Config) ->
- ?line [{{t,1},1},{{t,4},1}] =
+ [{{t,1},1},{{t,2},1},{{t,4},1}] =
analyse_expr(<<"<< \n"
" <<3:2, \n"
" SeqId:62>> \n"
@@ -1547,10 +1547,8 @@ comprehension_8188(Cf) ->
" true]. \n" % 2
" two() -> 2">>, Cf), % 1
- %% The template cannot have a counter since it is not allowed to
- %% be a block.
?line [{{t,1},1},
- %% {{t,2},2},
+ {{t,2},2},
{{t,3},1},
{{t,4},1},
{{t,5},0},
@@ -1560,7 +1558,7 @@ comprehension_8188(Cf) ->
{{t,13},2},
{{t,14},2}] =
analyse_expr(<<"<< \n" % 1
- " << (X*2) >> || \n" % 2 (now: 0)
+ " << (X*2) >> || \n" % 2
" <<X>> <= << (case two() of\n"
" 2 -> 1;\n" % 1
" _ -> 2\n" % 0
@@ -1575,7 +1573,7 @@ comprehension_8188(Cf) ->
"two() -> 2">>, Cf),
?line [{{t,1},1},
- %% {{t,2},4},
+ {{t,2},4},
{{t,4},1},
{{t,6},1},
{{t,7},0},
@@ -1584,7 +1582,7 @@ comprehension_8188(Cf) ->
{{t,12},4},
{{t,13},1}] =
analyse_expr(<<"<< \n" % 1
- " << (2)\n" % 4 (now: 0)
+ " << (2)\n" % 4
" :(8) >> || \n"
" <<X>> <= << 1,\n" % 1
" (case two() of \n"
@@ -1766,6 +1764,21 @@ otp_13277(Config) ->
?line ok = file:delete(File),
ok.
+%% Test general expressions in a binary comprehension.
+otp_13289(Config) ->
+ Test = <<"-module(t).
+ -export([t/0]).
+
+ t() ->
+ << (id(<<I>>)) || I <- [1,2,3] >>.
+
+ id(I) -> I.
+ ">>,
+ File = cc_mod(t, Test, Config),
+ <<1,2,3>> = t:t(),
+ ok = file:delete(File),
+ ok.
+
%%--Auxiliary------------------------------------------------------------
analyse_expr(Expr, Config) ->
diff --git a/lib/tools/test/cover_SUITE_data/d.erl b/lib/tools/test/cover_SUITE_data/d.erl
index 696e27e49b..b1d8ebd62e 100644
--- a/lib/tools/test/cover_SUITE_data/d.erl
+++ b/lib/tools/test/cover_SUITE_data/d.erl
@@ -6,7 +6,7 @@
size/0]).
-export([init/0]). % spawn
--record(person, {name, age, location, moved=false}).
+-record(person, {name, age :: integer(), location, moved=false :: boolean()}).
%%%----------------------------------------------------------------------
%%% User interface functions
diff --git a/lib/tools/test/cprof_SUITE.erl b/lib/tools/test/cprof_SUITE.erl
index 7b22dea7ed..8beaf4f399 100644
--- a/lib/tools/test/cprof_SUITE.erl
+++ b/lib/tools/test/cprof_SUITE.erl
@@ -42,7 +42,7 @@
-define(config(A,B),config(A,B)).
-export([config/2]).
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-endif.
-ifdef(debug).
diff --git a/lib/tools/test/emem_SUITE.erl b/lib/tools/test/emem_SUITE.erl
index 95cda98558..93d21623ce 100644
--- a/lib/tools/test/emem_SUITE.erl
+++ b/lib/tools/test/emem_SUITE.erl
@@ -43,7 +43,7 @@
-include_lib("kernel/include/file.hrl").
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(DEFAULT_TIMEOUT, ?t:minutes(5)).
diff --git a/lib/tools/test/eprof_SUITE.erl b/lib/tools/test/eprof_SUITE.erl
index 5428643667..6274eabc37 100644
--- a/lib/tools/test/eprof_SUITE.erl
+++ b/lib/tools/test/eprof_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(eprof_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
diff --git a/lib/tools/test/fprof_SUITE.erl b/lib/tools/test/fprof_SUITE.erl
index e8f179c630..d1a673d6b7 100644
--- a/lib/tools/test/fprof_SUITE.erl
+++ b/lib/tools/test/fprof_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(fprof_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Test server framework exports
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
diff --git a/lib/tools/test/ignore_cores.erl b/lib/tools/test/ignore_cores.erl
index 13f34cd10f..e40b91392c 100644
--- a/lib/tools/test/ignore_cores.erl
+++ b/lib/tools/test/ignore_cores.erl
@@ -28,7 +28,7 @@
-module(ignore_cores).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([init/1, fini/1, setup/3, setup/4, restore/1, dir/1]).
diff --git a/lib/tools/test/instrument_SUITE.erl b/lib/tools/test/instrument_SUITE.erl
index 3b981a9303..773d805cd0 100644
--- a/lib/tools/test/instrument_SUITE.erl
+++ b/lib/tools/test/instrument_SUITE.erl
@@ -25,7 +25,7 @@
-export(['+Mim true'/1, '+Mis true'/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
init_per_testcase(_Case, Config) ->
?line Dog=?t:timetrap(10000),
diff --git a/lib/tools/test/lcnt_SUITE.erl b/lib/tools/test/lcnt_SUITE.erl
index f3789a4137..47b8031bee 100644
--- a/lib/tools/test/lcnt_SUITE.erl
+++ b/lib/tools/test/lcnt_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(lcnt_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
diff --git a/lib/tools/test/make_SUITE.erl b/lib/tools/test/make_SUITE.erl
index 70bc8502bf..fdcc310df1 100644
--- a/lib/tools/test/make_SUITE.erl
+++ b/lib/tools/test/make_SUITE.erl
@@ -25,7 +25,7 @@
otp_6057_a/1, otp_6057_b/1, otp_6057_c/1,
otp_6057_end/1]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
diff --git a/lib/tools/test/tools_SUITE.erl b/lib/tools/test/tools_SUITE.erl
index 9403124c96..ae2a69305b 100644
--- a/lib/tools/test/tools_SUITE.erl
+++ b/lib/tools/test/tools_SUITE.erl
@@ -19,7 +19,7 @@
%%
-module(tools_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%% Default timetrap timeout (set in init_per_testcase).
-define(default_timeout, ?t:minutes(1)).
diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl
index ad47b31443..53aa80d2a3 100644
--- a/lib/tools/test/xref_SUITE.erl
+++ b/lib/tools/test/xref_SUITE.erl
@@ -30,7 +30,7 @@
-define(privdir, "xref_SUITE_priv").
-define(copydir, "xref_SUITE_priv/datacopy").
-else.
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(format(S, A), ok).
-define(datadir, ?config(data_dir, Conf)).
-define(privdir, ?config(priv_dir, Conf)).
@@ -1151,17 +1151,13 @@ read_expected(Version) ->
{POS8+4,{FF,{a,b,1}}},
{POS8+4,{FF,{erlang,apply,2}}},
{POS8+5,{FF,{erlang,apply,2}}},
- {POS8+6,{FF,{erlang,apply,3}}},
{POS8+6,{FF,{m,f,1}}},
- {POS8+7,{FF,{erlang,apply,3}}},
- {POS9+1,{FF,{erlang,apply,3}}},
{POS9+1,{FF,{read,bi,0}}},
{POS9+2,{FF,{a,b,1}}},
{POS9+2,{FF,{erlang,apply,2}}},
{POS9+3,{FF,{erlang,apply,2}}},
{POS9+4,{FF,{erlang,apply,2}}},
{POS9+4,{FF,{erlang,not_a_function,1}}},
- {POS9+5,{FF,{erlang,apply,3}}},
{POS9+5,{FF,{mod,func,2}}},
{POS9+6,{FF,{erlang,apply,1}}},
{POS9+7,{FF,{erlang,apply,2}}},
@@ -1169,17 +1165,11 @@ read_expected(Version) ->
{POS9+8,{FF,{q,f,1}}},
{POS10+4,{FF,{erlang,apply,2}}},
{POS10+5,{FF,{mod1,fun1,1}}},
- {POS11+1,{FF,{erlang,apply,3}}},
- {POS11+2,{FF,{erlang,apply,3}}},
- {POS11+3,{FF,{erlang,apply,3}}},
- {POS11+4,{FF,{erlang,apply,3}}},
{POS11+6,{FF,{erlang,apply,2}}},
{POS12+1,{FF,{erlang,apply,2}}},
{POS12+4,{FF,{erlang,apply,2}}},
- {POS12+5,{FF,{erlang,apply,3}}},
{POS12+5,{FF,{m3,f3,2}}},
{POS12+7,{FF,{erlang,apply,2}}},
- {POS12+8,{FF,{erlang,apply,3}}},
{POS13+1,{FF,{dm,df,1}}},
{POS13+6,{{read,bi,0},{foo,module_info,0}}},
{POS13+7,{{read,bi,0},{read,module_info,0}}},
@@ -1189,10 +1179,6 @@ read_expected(Version) ->
OK = case Version of
abstract_v1 ->
- [{POS8+3, {FF,{erlang,apply,3}}},
- {POS10+1, {FF,{erlang,apply,3}}},
- {POS10+6, {FF,{erlang,apply,3}}}]
- ++
[{0,{FF,{read,'$F_EXPR',178}}},
{0,{FF,{modul,'$F_EXPR',179}}}]
++ O1;
@@ -1213,13 +1199,25 @@ read_expected(Version) ->
{POS3+3, {FF,{erlang,spawn_link,3}}},
{POS3+4, {FF,{erlang,spawn_link,3}}},
{POS6+4, {FF,{erlang,spawn,3}}},
+ {POS8+6,{FF,{erlang,apply,3}}},
+ {POS8+7,{FF,{erlang,apply,3}}},
+ {POS9+1,{FF,{erlang,apply,3}}},
+ {POS9+5,{FF,{erlang,apply,3}}},
+ {POS11+1,{FF,{erlang,apply,3}}},
+ {POS11+2,{FF,{erlang,apply,3}}},
+ {POS11+3,{FF,{erlang,apply,3}}},
+ {POS11+4,{FF,{erlang,apply,3}}},
+ {POS12+5,{FF,{erlang,apply,3}}},
+ {POS12+8,{FF,{erlang,apply,3}}},
{POS13+5, {{read,bi,0},{erlang,length,1}}},
{POS14+3, {{read,bi,0},{erlang,length,1}}}],
%% Operators (OTP-8647):
OKB = case Version of
abstract_v1 ->
- [];
+ [{POS8+3, {FF,{erlang,apply,3}}},
+ {POS10+1, {FF,{erlang,apply,3}}},
+ {POS10+6, {FF,{erlang,apply,3}}}];
_ ->
[{POS13+16, {{read,bi,0},{erlang,'!',2}}},
{POS13+16, {{read,bi,0},{erlang,'-',1}}},
diff --git a/lib/typer/src/typer.erl b/lib/typer/src/typer.erl
index 562530c868..5c82750a21 100644
--- a/lib/typer/src/typer.erl
+++ b/lib/typer/src/typer.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2006-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.
@@ -137,11 +137,14 @@ extract(#analysis{macros = Macros,
NewCodeServer =
try
NewRecords = dialyzer_codeserver:get_temp_records(CodeServer1),
+ NewExpTypes = dialyzer_codeserver:get_temp_exported_types(CodeServer1),
+ case sets:size(NewExpTypes) of 0 -> ok end,
OldRecords = dialyzer_plt:get_types(TrustPLT), % XXX change to the PLT?
MergedRecords = dialyzer_utils:merge_records(NewRecords, OldRecords),
CodeServer2 = dialyzer_codeserver:set_temp_records(MergedRecords, CodeServer1),
- CodeServer3 = dialyzer_utils:process_record_remote_types(CodeServer2),
- dialyzer_contracts:process_contract_remote_types(CodeServer3)
+ CodeServer3 = dialyzer_codeserver:finalize_exported_types(NewExpTypes, CodeServer2),
+ CodeServer4 = dialyzer_utils:process_record_remote_types(CodeServer3),
+ dialyzer_contracts:process_contract_remote_types(CodeServer4)
catch
throw:{error, ErrorMsg} ->
compile_error(ErrorMsg)
@@ -845,8 +848,7 @@ collect_info(Analysis) ->
%% io:format("Merged Records ~p",[MergedRecords]),
TmpCServer1 = dialyzer_codeserver:set_temp_records(MergedRecords, TmpCServer),
TmpCServer2 =
- dialyzer_codeserver:insert_temp_exported_types(MergedExpTypes,
- TmpCServer1),
+ dialyzer_codeserver:finalize_exported_types(MergedExpTypes, TmpCServer1),
TmpCServer3 = dialyzer_utils:process_record_remote_types(TmpCServer2),
dialyzer_contracts:process_contract_remote_types(TmpCServer3)
catch
diff --git a/lib/typer/test/Makefile b/lib/typer/test/Makefile
index d6dd22b6cf..fb5570d9f0 100644
--- a/lib/typer/test/Makefile
+++ b/lib/typer/test/Makefile
@@ -25,7 +25,7 @@ RELSYSDIR = $(RELEASE_PATH)/typer_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_COMPILE_FLAGS +=
EBIN = .
diff --git a/lib/webtool/AUTHORS b/lib/webtool/AUTHORS
deleted file mode 100644
index 5f173dd264..0000000000
--- a/lib/webtool/AUTHORS
+++ /dev/null
@@ -1,4 +0,0 @@
-Original Authors and Contributors:
-
-Siri Hansen
-Martin Gustafsson
diff --git a/lib/webtool/Makefile b/lib/webtool/Makefile
deleted file mode 100644
index 9afcb87af2..0000000000
--- a/lib/webtool/Makefile
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2001-2009. 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
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-
-SUB_DIRECTORIES = src priv doc/src
-
-include vsn.mk
-VSN = $(WEBTOOL_VSN)
-
-SPECIAL_TARGETS =
-
-# ----------------------------------------------------
-# Default Subdir Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_subdir.mk
-
-
diff --git a/lib/webtool/doc/html/.gitignore b/lib/webtool/doc/html/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/webtool/doc/html/.gitignore
+++ /dev/null
diff --git a/lib/webtool/doc/man1/.gitignore b/lib/webtool/doc/man1/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/webtool/doc/man1/.gitignore
+++ /dev/null
diff --git a/lib/webtool/doc/man3/.gitignore b/lib/webtool/doc/man3/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/webtool/doc/man3/.gitignore
+++ /dev/null
diff --git a/lib/webtool/doc/pdf/.gitignore b/lib/webtool/doc/pdf/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/webtool/doc/pdf/.gitignore
+++ /dev/null
diff --git a/lib/webtool/doc/src/Makefile b/lib/webtool/doc/src/Makefile
deleted file mode 100644
index 57de52a616..0000000000
--- a/lib/webtool/doc/src/Makefile
+++ /dev/null
@@ -1,132 +0,0 @@
-# ``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.
-#
-# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-# AB. All Rights Reserved.''
-#
-# $Id$
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(WEBTOOL_VSN)
-APPLICATION=webtool
-
-DOC_EXTRA_FRONT_PAGE_INFO=Important note: \
-The Webtool application is obsolete and will be removed \
-in the next major OTP release
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-XML_APPLICATION_FILES = ref_man.xml
-
-XML_REF1_FILES = start_webtool.xml
-
-XML_REF3_FILES = webtool.xml
-
-XML_PART_FILES = \
- part.xml \
- part_notes.xml \
- part_notes_history.xml
-
-XML_CHAPTER_FILES = \
- webtool_chapter.xml \
- notes.xml \
- notes_history.xml
-
-BOOK_FILES = book.xml
-
-XML_FILES = \
- $(BOOK_FILES) $(XML_CHAPTER_FILES) \
- $(XML_PART_FILES) $(XML_REF3_FILES) \
- $(XML_REF1_FILES) $(XML_APPLICATION_FILES)
-
-GIF_FILES =
-
-# ----------------------------------------------------
-
-HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
-
-INFO_FILE = ../../info
-
-MAN1_FILES = $(XML_REF1_FILES:%.xml=$(MAN1DIR)/%.1)
-MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-
-HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
-
-TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-$(HTMLDIR)/%.gif: %.gif
- $(INSTALL_DATA) $< $@
-
-docs: pdf html man
-
-$(TOP_PDF_FILE): $(XML_FILES)
-
-pdf: $(TOP_PDF_FILE)
-
-html: gifs $(HTML_REF_MAN_FILE)
-
-
-clean clean_docs:
- rm -rf $(HTMLDIR)/*
- rm -f $(MAN1DIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
-
-man: $(MAN1_FILES) $(MAN3_FILES)
-
-gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-
-debug opt:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_docs_spec: docs
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(HTMLDIR)/* \
- "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELEASE_PATH)/man/man1"
- $(INSTALL_DATA) $(MAN1_FILES) "$(RELEASE_PATH)/man/man1"
- $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
- $(INSTALL_DATA) $(MAN3_FILES) "$(RELEASE_PATH)/man/man3"
-
-release_spec:
-
diff --git a/lib/webtool/doc/src/book.xml b/lib/webtool/doc/src/book.xml
deleted file mode 100644
index feccee7c62..0000000000
--- a/lib/webtool/doc/src/book.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book xmlns:xi="http://www.w3.org/2001/XInclude">
- <header titlestyle="normal">
- <copyright>
- <year>2001</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>WebTool</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev>1.0</rev>
- </header>
- <insidecover>
- </insidecover>
- <pagetext>WebTool</pagetext>
- <preamble>
- </preamble>
- <parts lift="no">
- <xi:include href="part.xml"/>
- </parts>
- <applications>
- <xi:include href="ref_man.xml"/>
- </applications>
- <releasenotes>
- <xi:include href="notes.xml"/>
- </releasenotes>
- <listofterms></listofterms>
- <index></index>
-</book>
-
diff --git a/lib/webtool/doc/src/fascicules.xml b/lib/webtool/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/webtool/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/webtool/doc/src/notes.xml b/lib/webtool/doc/src/notes.xml
deleted file mode 100644
index 0ebb66ae3c..0000000000
--- a/lib/webtool/doc/src/notes.xml
+++ /dev/null
@@ -1,269 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2004</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>Webtool Release Notes</title>
- <prepared>otp_appnotes</prepared>
- <docno>nil</docno>
- <date>nil</date>
- <rev>nil</rev>
- <file>notes.xml</file>
- </header>
- <p>This document describes the changes made to the Webtool
- application.</p>
-
-<section><title>WebTool 0.9.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Remove dependency to inets <c>mod_include</c> in
- configuration.</p>
- <p>
- Own Id: OTP-13406</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>WebTool 0.9</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- The Webtool application has been marked as obsolete and
- will be removed from OTP in the next major release (OTP
- 19.0).</p>
- <p>
- Own Id: OTP-10922 Aux Id: OTP-12705 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>WebTool 0.8.10</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Application upgrade (appup) files are corrected for the
- following applications: </p>
- <p>
- <c>asn1, common_test, compiler, crypto, debugger,
- dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe,
- inets, observer, odbc, os_mon, otp_mibs, parsetools,
- percept, public_key, reltool, runtime_tools, ssh,
- syntax_tools, test_server, tools, typer, webtool, wx,
- xmerl</c></p>
- <p>
- A new test utility for testing appup files is added to
- test_server. This is now used by most applications in
- OTP.</p>
- <p>
- (Thanks to Tobias Schlager)</p>
- <p>
- Own Id: OTP-11744</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>WebTool 0.8.9.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Misc build updates</p>
- <p>
- Own Id: OTP-10784</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>WebTool 0.8.9.1</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Miscellaneous documentation build updates</p>
- <p>
- Own Id: OTP-9813</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>WebTool 0.8.9</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Do not install *.bat files on non-win32 machines (Thanks
- to Hans Ulrich Niedermann)</p>
- <p>
- Own Id: OTP-9515</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>WebTool 0.8.8</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Various small documentation fixes (Thanks to Bernard
- Duggan)</p>
- <p>
- Own Id: OTP-9172</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>WebTool 0.8.7</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Up until now Netscape has been the default web browser on
- Unix/Linux. Webtool has now been updated to start Firefox
- as default browser instead.</p>
- <p>
- Own Id: OTP-8651 Aux Id: OTP-8650 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>WebTool 0.8.6</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Misc updates</p>
- <p>
- Own Id: OTP-8456</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>WebTool 0.8.5</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- The documentation is now built with open source tools
- (xsltproc and fop) that exists on most platforms. One
- visible change is that the frames are removed.</p>
- <p>
- Own Id: OTP-8201</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>WebTool 0.8.4</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>The copyright notices have been updated.</p>
- <p>
- Own Id: OTP-7851</p>
- </item>
- </list>
- </section>
-
-</section>
-<section><title>WebTool 0.8.3.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Minor updates.</p>
- <p>
- Own Id: OTP-6998</p>
- </item>
- </list>
- </section>
-
-</section>
-
- <section>
- <title>WebTool 0.8.3.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Minor Makefile changes.</p>
- <p>Own Id: OTP-6689</p>
- </item>
- <item>
- <p>Obsolete guard tests (such as list()) have been replaced
- with the modern guard tests (such as is_list()).</p>
- <p>Own Id: OTP-6725</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>WebTool 0.8.3</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Removed some dead code discovered by Dialyzer.</p>
- <p>Own Id: OTP-6041</p>
- </item>
- </list>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/webtool/doc/src/notes_history.xml b/lib/webtool/doc/src/notes_history.xml
deleted file mode 100644
index 792475d948..0000000000
--- a/lib/webtool/doc/src/notes_history.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2006</year>
- <year>2013</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- 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.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Webtool Release Notes History</title>
- <prepared>otp_appnotes</prepared>
- <docno>nil</docno>
- <date>nil</date>
- <rev>nil</rev>
- </header>
-
- <section>
- <title>Webtool 0.8.2</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Bugfix: <c>webtool</c> crashed when trying to find a free
- port number if connection failed with other reason than
- <c>econnrefused</c>.</p>
- <p>Own Id: OTP-5166</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Misc improvements:</p>
- <list type="bulleted">
- <item>The function <c>debug_app/1</c> and some error
- printouts are added to simplify debugging of own
- application.</item>
- <item>Multiple webtool instances can now be started on
- the same host. If the default port (8888) is in use, port
- 8889 is tried. If 8889 is also used, 8890 is tried and so
- on. Max number of ports tried is 256.</item>
- <item><em>Incompatible:</em> If <c>Data</c> is set to
- <c>PortNumber</c> in <c>start(Path,Data)</c>, the default
- data will be used for ip-number (<c>127.0.0.1</c>) and
- server name (<c>localhost</c>).</item>
- </list>
- <p>*** POTENTIAL INCOMPATIBILITY ***</p>
- <p>Own Id: OTP-4724</p>
- </item>
- </list>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/webtool/doc/src/part.xml b/lib/webtool/doc/src/part.xml
deleted file mode 100644
index b0c4ee310d..0000000000
--- a/lib/webtool/doc/src/part.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2001</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>WebTool User's Guide</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p><em>WebTool</em> provides a easy way to use web based tools with
- Erlang/OTP. It configures and starts a webserver as well as all
- available tools.</p>
- </description>
- <xi:include href="webtool_chapter.xml"/>
-</part>
-
diff --git a/lib/webtool/doc/src/part_notes.xml b/lib/webtool/doc/src/part_notes.xml
deleted file mode 100644
index db2b790f3f..0000000000
--- a/lib/webtool/doc/src/part_notes.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2004</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>WebTool Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p><em>WebTool</em> provides an easy way to use web based tools with
- Erlang/OTP. It configures and starts a webserver as well as all
- available tools.</p>
- <p>For information about older versions, see
- <url href="part_notes_history_frame.html">Release Notes History</url>.</p>
- </description>
- <xi:include href="notes"/>
-</part>
-
diff --git a/lib/webtool/doc/src/part_notes_history.xml b/lib/webtool/doc/src/part_notes_history.xml
deleted file mode 100644
index 50ce62e58d..0000000000
--- a/lib/webtool/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2006</year>
- <year>2013</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- 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.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>WebTool Release Notes History</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p><em>WebTool</em> provides a easy way to use web based tools with
- Erlang/OTP. It configures and starts a webserver as well as all
- available tools.</p>
- </description>
- <include file="notes_history"></include>
-</part>
-
diff --git a/lib/webtool/doc/src/ref_man.xml b/lib/webtool/doc/src/ref_man.xml
deleted file mode 100644
index aa81392b11..0000000000
--- a/lib/webtool/doc/src/ref_man.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE application SYSTEM "application.dtd">
-
-<application xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2001</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>WebTool Reference Manual</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p><em>WebTool</em> provides an easy way to use web based tools with
- Erlang/OTP. It configures and starts a webserver as well as all
- available tools.</p>
- </description>
- <xi:include href="webtool.xml"/>
- <xi:include href="start_webtool.xml"/>
-</application>
-
diff --git a/lib/webtool/doc/src/start_webtool.xml b/lib/webtool/doc/src/start_webtool.xml
deleted file mode 100644
index e9c94c4271..0000000000
--- a/lib/webtool/doc/src/start_webtool.xml
+++ /dev/null
@@ -1,104 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE comref SYSTEM "comref.dtd">
-
-<comref>
- <header>
- <copyright>
- <year>2003</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>start_webtool</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno>1</docno>
- <approved></approved>
- <checked></checked>
- <date>2003-06-18</date>
- <rev></rev>
- <file>start_webtool.sgml</file>
- </header>
- <com>start_webtool</com>
- <comsummary>WebTool Start Script</comsummary>
- <description>
- <p>The <c>start_webtool</c> script starts WebTool, a WebTool
- application and a web browser pointing to this application.</p>
- </description>
- <funcs>
- <func>
- <name>start_webtool application [ browser ]</name>
- <fsummary>Start a WebTool Application</fsummary>
- <desc>
- <p>Starts WebTool, the given WebTool Application and a web
- browser pointing to this application.
- </p>
- <p>If no argument is given, a list of available applications
- is displayed, e.g.</p>
- <pre>
->start_webtool
-Starting webtool...
-WebTool is available at http://localhost:8888/
-Or http://127.0.0.1:8888/
-
-Usage: start_webtool application [ browser ]
-
-Available applications are: [orber,appmon,crashdump_viewer,webcover]
-Default browser is 'iexplore' (Internet Explorer) on Windows or else 'firefox' </pre>
- <p>To start any of the listed applications, give the
- application name as the first argument, e.g.</p>
- <pre>
->start_webtool webcover
-Starting webtool...
-WebTool is available at http://localhost:8888/
-Or http://127.0.0.1:8888/
-Starting webcover...
-Sending URL to netscape...done </pre>
- <p>The WebTool application WebCover is then started and the
- default browser is used. The default browser is Internet
- Explorer on Windows or else Firefox.
- </p>
- <p>To use another browser, give the browser's start command
- as the second argument, e.g.</p>
- <pre>
->start_webtool webcover mozilla
-Starting webtool...
-WebTool is available at http://localhost:8888/
-Or http://127.0.0.1:8888/
-Starting webcover...
-Sending URL to mozilla...done </pre>
- <p>If the given browser name is not known to WebTool, WebTool
- will run it as a command with the start URL as the only
- argument, e.g.</p>
- <pre>
->start_webtool webcover mybrowser
-Starting webtool...
-WebTool is available at http://localhost:8888/
-Or http://127.0.0.1:8888/
-Starting webcover...
-Starting mybrowser... </pre>
- <p>Here the command <c>"mybrowser http://localhost:8888/webcover"</c> is executed.
- </p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>See Also</title>
- <p><seealso marker="webtool">webtool(3)</seealso></p>
- </section>
-</comref>
-
diff --git a/lib/webtool/doc/src/webtool.xml b/lib/webtool/doc/src/webtool.xml
deleted file mode 100644
index 2647518dae..0000000000
--- a/lib/webtool/doc/src/webtool.xml
+++ /dev/null
@@ -1,157 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2001</year>
- <year>2013</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- 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.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>webtool</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <module>webtool</module>
- <modulesummary>WebTool is a tool used to simplify the implementation of web based tools with Erlang/OTP.</modulesummary>
- <description>
- <p>WebTool makes it easy to use web based tools with Erlang/OTP. WebTool
- configures and starts the webserver httpd.</p>
- </description>
- <funcs>
- <func>
- <name>start()-> {ok,Pid}| {stop,Reason}</name>
- <fsummary>Start WebTool.</fsummary>
- <desc>
- <p>Start WebTool with default data, i.e. port 8888, ip-number
- 127.0.0.1, and server-name <c>localhost</c>. If port 8888 is
- in use, port 8889 is tried instead. If 8889 is also in use,
- 8890 is tried and so on. Max number of ports tried is 256.
- </p>
- <p>The <c>mime.types</c> file and WebTool's own HTML files
- are assumed to be in the directory
- <c><![CDATA[webtool-<vsn>/priv/root/conf]]></c>.</p>
- </desc>
- </func>
- <func>
- <name>start(Path,Data)->{ok,Pid}|{stop,Reason}</name>
- <fsummary>Start WebTool with default configuration.</fsummary>
- <type>
- <v>Path = string() | standard_path</v>
- <v>Data = [Port,Address,Name] | PortNumber | standard_data</v>
- <v>Port = {port,PortNumber}</v>
- <v>Address = {bind_address,IpNumber}</v>
- <v>Name = {server_name,ServerName}</v>
- <v>PortNumber = integer()</v>
- <v>IpNumber = tuple(), e.g. {127,0,0,1}</v>
- <v>ServerName = string()</v>
- <v>Pid = pid()</v>
- </type>
- <desc>
- <p>Use this function to start WebTool if the default port,
- ip-number,servername or path can not be used.</p>
- <p><c>Path</c> is the directory where the <c>mime.types</c>
- file and WebTool's own HTML files are located. By default
- this is <c><![CDATA[webtool-<vsn>/priv]]></c>, and in most cases there
- is no need to change this. If <c>Path</c> is set to
- <c>standard_path</c> the default will be used.</p>
- <p>If <c>Data</c> is set to <c>PortNumber</c>, the default data
- will be used for ip-number (<c>127.0.0.1</c>) and server
- name (<c>localhost</c>).</p>
- </desc>
- </func>
- <func>
- <name>stop()->void</name>
- <fsummary>Stop WebTool.</fsummary>
- <desc>
- <p>Stop WebTool and the tools started by WebTool.</p>
- </desc>
- </func>
- <func>
- <name>debug_app(Module)->void</name>
- <fsummary>Debug a WebTool application.</fsummary>
- <type>
- <v>Module = atom()</v>
- </type>
- <desc>
- <p>Debug a WebTool application by tracing all functions in the
- given module which are called from WebTool.</p>
- </desc>
- </func>
- <func>
- <name>stop_debug()->void</name>
- <fsummary>Stop debugging an application and format the trace log.</fsummary>
- <desc>
- <p>Stop the tracing started by <c>debug_app/1</c>, and format
- the trace log.</p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>CALLBACK FUNCTIONS</title>
- <p>The following callback function must be implemented by each web
- based tool that will be used via WebTool. When started, WebTool
- searches the Erlang code path for *.tool files to locate all web
- based tools and their callback functions. See the <seealso marker="webtool_chapter">WebTool User's Guide</seealso> for more
- information about the *.tool files.</p>
- </section>
- <funcs>
- <func>
- <name>Module:Func(Data)-> {Name,WebData}|error</name>
- <fsummary>Returns configuration data needed by WebTool to configure and start a tool.</fsummary>
- <type>
- <v>Data = term()</v>
- <v>Name = atom()</v>
- <v>WebData = [WebOptions]</v>
- <v>WebOptions = LinkData | Alias | Start</v>
- <v>LinkData = {web_data,{ToolName,Url}}</v>
- <v>Alias = {alias,{VirtualPath,RealPath}} | {alias,{erl_alias,Path,[Modules]}</v>
- <v>Start = {start,StartData}</v>
- <v>ToolName = Url = VirtualPath = RealPath = Path = string()</v>
- <v>Modules = atom()</v>
- <v>StartData = AppData | ChildSpec | Func</v>
- <v>AppData = {app,AppName}</v>
- <v>ChildSpec = {child,child_spec()}</v>
- <d>See the Reference Manual for the module supervisor in the STDLIB application for details about child_spec().</d>
- <v>Func = {func,{StartMod,StartFunc,StartArg}, {StopMod,StopFunc,StopArg}}</v>
- <v>AppName = StartMod = StartFunc = StopMod = StopFunc =atom()</v>
- <v>StartArg = StopArg = [term()]</v>
- </type>
- <desc>
- <p>This is the configuration function (<c>config_func</c>)
- which must be stated in the <c>*.tool</c> file.</p>
- <p>The function is called by WebTool at startup to retrieve the
- data needed to start and configure the tool. <c>LinkData</c> is
- used by WebTool to create the link to the tool. <c>Alias</c> is
- used to create the aliases needed by the webserver. <c>Start</c>
- is used to start and stop the tool.</p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>See Also</title>
- <p><seealso marker="start_webtool">start_webtool(1)</seealso>,
- <seealso marker="webtool_chapter">WebTool User's Guide</seealso></p>
- </section>
-</erlref>
-
diff --git a/lib/webtool/doc/src/webtool_chapter.xml b/lib/webtool/doc/src/webtool_chapter.xml
deleted file mode 100644
index 160a42f855..0000000000
--- a/lib/webtool/doc/src/webtool_chapter.xml
+++ /dev/null
@@ -1,246 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2001</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- 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.
-
- </legalnotice>
-
- <title>WebTool User Guide</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>webtool_chapter.xml</file>
- </header>
-
- <section>
- <title>Introduction </title>
- <p>WebTool provides an easy and efficient way to implement web
- based tools with Erlang/OTP. WebTool configures and starts the
- webserver and the various web based tools.</p>
- <p>All tools that shall run under WebTool must have a *.tool
- file in the code path or in its priv directory. When WebTool
- starts it searches the code path for such files. For each
- <c>ebin</c> directory in the path, the <c>priv</c> directory is
- also searched. The *.tool files contain the configuration data
- for each web based tool.</p>
- </section>
-
- <section>
- <title>Starting WebTool</title>
- <p>Start WebTool by calling the function <c>webtool:start/0</c> or
- <c>webtool:start/2</c>. If <c>webtool:start/0</c> is used the
- start page of WebTool is available at
- <em>http://localhost:8888/</em> or
- <em>http://127.0.0.1:8888/</em>, and the directory containing
- the root directory for the webserver, is assumed to be
- <c><![CDATA[webtool-<vsn>/priv]]></c>.</p>
- <p>Use <c>webtool:start/2</c> if the default path for the root
- directory, port, ip-number or server name can not be used. See
- the Reference Manual for <seealso marker="webtool">webtool</seealso> for more information.</p>
- <p>WebTool, with the default configuration as in <c>start/0</c>,
- can also be started with the <c>start_webtool</c> script which
- is available in the <c>priv</c> directory of the WebTool
- application. See the Reference Manual for <seealso marker="start_webtool">start_webtool</seealso> for further
- information about this script. For Windows users, the batch file
- <c>start_webtool.bat</c> can be used for the same purpose.</p>
- </section>
-
- <section>
- <title>Using WebTool</title>
- <p>Start WebTool and point the browser to the corresponding URL.
- At the top of the page there is a frame with a link named
- <em>WebTool</em>. Click that link and a page where it is
- possible to start the available tools will appear in the main
- frame.</p>
- </section>
-
- <section>
- <title>Start a web based tool</title>
- <p>Click on the link labeled <em>WebTool</em> in the topmost frame,
- select the checkbox for each tool to start and
- click on the button labeled <em>Start</em>. A link to each tool
- that WebTool succeeded to start will appear in the topmost frame.</p>
- </section>
-
- <section>
- <title>Stop a web based tool</title>
- <p>Click on the link labeled <em>WebTool</em> in the topmost
- frame. Select <em>Stop Tools</em> in the left frame. Select the
- checkbox for each tool to stop and click on the button labeled
- <em>Stop</em>.</p>
- </section>
-
- <section>
- <title>Develop new web based tools</title>
- <p>WebTool can be used as a framework when developing new web based
- tools.</p>
- <p>A web based tool running under WebTool will typically consist of
- three parts.</p>
- <list type="bulleted">
- <item>A *.tool file which defines how WebTool can find the tool's
- configuration data</item>
- <item>The Erlang code generating the web interface to the tool (HTML
- code)</item>
- <item>The tool itself.</item>
- </list>
- <p>In most cases it is a good idea to separate the code for
- creation of the html-pages and the code for the logic. This
- increases the readability of the code and the logic might be
- possible to reuse.</p>
-
- <section>
- <title>The *.tool file</title>
- <p>When WebTool starts it searches the current path for
- <c>*.tool</c> files to find all available tools. The *.tool
- file contains a version identifier and a list of tuples which
- is the configuration data. The version identifier specifies
- the *.tool file version, i.e. not the version of
- webtool. Currently the only valid version is "1.2" and the
- only valid configuration tag is
- <c>config_func</c>. <c>config_func</c> specifies which
- function WebTool must call to get further configuration data
- for the tool. This means that a *.tool file generally must
- look like this:</p>
- <code type="none">
- {version,"1.2"}.
- [{config_func,{Module,Function,Arguments}}]. </code>
- <p><c>Module</c> is the name of the module where the callback
- function is defined. <c>Function</c> is the name of the
- callback function, and <c>Arguments</c> is the list of
- arguments to the callback function.</p>
- </section>
-
- <section>
- <title>The configuration function</title>
- <p>The *.tool file points out a configuration function. This
- function must return a list of configuration parameters (see
- the Reference Manual for <seealso marker="webtool">webtool</seealso>).</p>
- <p>The <c>web_data</c> parameter is mandatory and it specifies
- the name of the tool and the link to the tool's start
- page. All other parameters are optional.</p>
- <p>If the tool requires any processes to run, the <c>start</c>
- parameter specifies the function that WebTool must call in
- order to start the process(es).</p>
- <p>The <c>alias</c> parameters are passed directly on to the
- webserver (INETS). The webserver has three ways to create
- dynamic web pages CGI, Eval Scheme and Erl Scheme. All tools
- running under WebTool must use Erl Scheme.</p>
- <p>Erl Scheme tries to resemble plain CGI. The big difference is
- that Erl Scheme can only execute Erlang code. The code will
- furthermore be executed on the same instance as the webserver.</p>
- <p>An URL which calls an Erlang function with Erl Scheme can have
- the following syntax:</p>
- <code type="none"><![CDATA[
-http://Servername:Port/ErlScriptAlias/Mod/Func<?QueryString> ]]></code>
- <p>An <c>alias</c> parameter in the configuration function can be
- an ErlScriptAlias as used in the above URL. The definition of
- an ErlScriptAlias shall be like this:</p>
- <p><c>{alias,{erl_alias,Path,[Modules]}}</c>, e.g.</p>
- <p><c>{alias,{erl_alias,"/testtool",[helloworld]}}</c></p>
- <p>The following URL will then cause a call to the function
- helloworld:helloworld/2 (if WebTool is started with default
- settings i.e. servername "localhost" and port 8888):</p>
- <p><c>http://localhost:8888/testtool/helloworld/helloworld</c></p>
- <p>Note that the module <c>helloworld</c> must be in the code
- path of the node running WebTool.</p>
- <p>Functions that are called via the Erl Scheme must take two
- arguments, <c>Environment</c> and <c>Input</c>.
- </p>
- <list type="bulleted">
- <item><c>Environment</c> is a list of key/value tuples.</item>
- <item><c>Input</c> is the part of the URL after the "?", i.e. the
- part of the URL containing name-value pairs. If the page was
- called with the URL:
- <br></br>
-<c><![CDATA[http://localhost:8888/testtool/helloworld/helloworld?input1=one&amp;input2=two]]></c> <br></br>
-<c>Input</c> will be the string
- <c><![CDATA["input1=one&amp;input2=two"]]></c>. In the module
- <c>httpd</c> in the INETS application there is a function
- <c>parse_query</c> which will parse such a string and return
- a list of key-value tuples.</item>
- </list>
- <p>An <c>alias</c> parameter in the configuration function can
- also be a normal path alias. This can e.g. be used to point
- out a directory where HTML files are stored. The following
- definition states that the URL
- <c>http://localhost:8888/mytool_home/</c> really points to the
- directory <c>/usr/local/otp/lib/myapp-1.0/priv</c>:</p>
- <p><c>{alias,{"/mytool_home","/usr/local/otp/lib/myapp-1.0/priv"}}</c></p>
- <p>See the INETS documentation, especially the module
- <c>mod_esi</c>, for a more in depth coverage of the Erl Scheme.</p>
- </section>
-
- <section>
- <title>A small example</title>
- <p>A Hello World example that uses Erl Scheme would look like
- this. Note that this example does not have a process running
- and thus does not need a <c>start</c> parameter in the
- configuration function.
- </p>
- <p><em>helloworld.erl:</em></p>
- <pre>
- -module(helloworld).
- -export([config_data/0]).
- -export([helloworld/2]).
-
- config_data()->
- {testtool,
- [{web_data,{"TestTool","/testtool/helloworld/helloworld"}},
- {alias,{erl_alias,"/testtool",[helloworld]}}]}.
-
- helloworld(_Env,_Input)-&gt;
- [header(),html_header(),helloworld_body(),html_end()].
-
- header() -&gt;
- header("text/html").
-
- header(MimeType) -&gt;
- "Content-type: " ++ MimeType ++ "\r\n\r\n".
-
- html_header() -&gt;
- "&lt;HTML&gt;
- &lt;HEAD&gt;
- &lt;TITLE&gt;Hello world Example &lt;/TITLE&gt;
- &lt;/HEAD&gt;\n".
-
- helloworld_body()-&gt;
- "&lt;BODY&gt;Hello World&lt;/BODY&gt;".
-
- html_end()-&gt;
- "&lt;/HTML&gt;".
- </pre>
- <p>To use this example with WebTool a *.tool file must be created
- and added to a directory in the current path, e.g. the same
- directory as the compiled <c>helloworld.beam</c>.</p>
- <p><em>testtool.tool:</em></p>
- <code type="none">
- {version,"1.2"}.
- [{config_func, {helloworld,config_data,[]}}].
- </code>
- <p>When <c>helloworld.erl</c> is compiled, start WebTool by
- calling the function <c>webtool:start()</c> and point your
- browser to <em>http://localhost:8888/</em>. Select WebTool in
- the topmost frame and start TestTool from the web page. Click
- on the link labeled <em>TestTool</em> in the topmost frame.</p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/webtool/ebin/.gitignore b/lib/webtool/ebin/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/webtool/ebin/.gitignore
+++ /dev/null
diff --git a/lib/webtool/info b/lib/webtool/info
deleted file mode 100644
index 4d8dc6f2cb..0000000000
--- a/lib/webtool/info
+++ /dev/null
@@ -1,2 +0,0 @@
-group: tools
-short: A tool that simplifying the use of web based Erlang tools
diff --git a/lib/webtool/priv/Makefile b/lib/webtool/priv/Makefile
deleted file mode 100644
index 4963767a4d..0000000000
--- a/lib/webtool/priv/Makefile
+++ /dev/null
@@ -1,82 +0,0 @@
-# ``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.
-#
-# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-# AB. All Rights Reserved.''
-#
-# $Id$
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(WEBTOOL_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/webtool-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-WEBSERVER_CONFIG_FILES = root/conf/mime.types
-
-HTDOCS_FILES = root/doc/index.html \
- root/doc/tool_management.html \
- root/doc/start_info.html
-
-ifeq ($(findstring win32,$(TARGET)),win32)
-WIN32_SCRIPTS= bin/start_webtool.bat
-else
-WIN32_SCRIPTS=
-endif
-SCRIPTS = bin/start_webtool $(WIN32_SCRIPTS)
-
-# ----------------------------------------------------
-# 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)/priv"
- $(INSTALL_DIR) "$(RELSYSDIR)/priv/root"
- $(INSTALL_DIR) "$(RELSYSDIR)/priv/root/conf"
- $(INSTALL_DIR) "$(RELSYSDIR)/priv/root/doc"
- $(INSTALL_DATA) $(HTDOCS_FILES) "$(RELSYSDIR)/priv/root/doc"
- $(INSTALL_DATA) $(WEBSERVER_CONFIG_FILES) "$(RELSYSDIR)/priv/root/conf"
- $(INSTALL_DIR) "$(RELSYSDIR)/priv/bin"
- $(INSTALL_SCRIPT) $(SCRIPTS) "$(RELSYSDIR)/priv/bin"
-
-release_docs_spec:
-
-
diff --git a/lib/webtool/priv/bin/start_webtool b/lib/webtool/priv/bin/start_webtool
deleted file mode 100755
index e552fb5af0..0000000000
--- a/lib/webtool/priv/bin/start_webtool
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-erl -sname webtool -s webtool script_start $@
diff --git a/lib/webtool/priv/bin/start_webtool.bat b/lib/webtool/priv/bin/start_webtool.bat
deleted file mode 100644
index cd16aa6200..0000000000
--- a/lib/webtool/priv/bin/start_webtool.bat
+++ /dev/null
@@ -1,2 +0,0 @@
-@ECHO OFF
-CALL erl -sname webtool -s webtool script_start %* -s erlang halt \ No newline at end of file
diff --git a/lib/webtool/priv/root/conf/mime.types b/lib/webtool/priv/root/conf/mime.types
deleted file mode 100644
index 32f7cd853c..0000000000
--- a/lib/webtool/priv/root/conf/mime.types
+++ /dev/null
@@ -1,99 +0,0 @@
-# This is a comment. I love comments.
-
-application/activemessage
-application/andrew-inset
-application/applefile
-application/atomicmail
-application/dca-rft
-application/dec-dx
-application/mac-binhex40 hqx
-application/mac-compactpro cpt
-application/macwriteii
-application/msword doc
-application/news-message-id
-application/news-transmission
-application/octet-stream bin dms lha lzh exe class
-application/oda oda
-application/pdf pdf
-application/postscript ai eps ps
-application/powerpoint ppt
-application/remote-printing
-application/rtf rtf
-application/slate
-application/wita
-application/wordperfect5.1
-application/x-bcpio bcpio
-application/x-cdlink vcd
-application/x-compress Z
-application/x-cpio cpio
-application/x-csh csh
-application/x-director dcr dir dxr
-application/x-dvi dvi
-application/x-gtar gtar
-application/x-gzip gz
-application/x-hdf hdf
-application/x-httpd-cgi cgi
-application/x-koan skp skd skt skm
-application/x-latex latex
-application/x-mif mif
-application/x-netcdf nc cdf
-application/x-sh sh
-application/x-shar shar
-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/zip zip
-audio/basic au snd
-audio/mpeg mpga mp2
-audio/x-aiff aif aiff aifc
-audio/x-pn-realaudio ram
-audio/x-pn-realaudio-plugin rpm
-audio/x-realaudio ra
-audio/x-wav wav
-chemical/x-pdb pdb xyz
-image/gif gif
-image/ief ief
-image/jpeg jpeg jpg jpe
-image/png png
-image/tiff tiff tif
-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/external-body
-message/news
-message/partial
-message/rfc822
-multipart/alternative
-multipart/appledouble
-multipart/digest
-multipart/mixed
-multipart/parallel
-text/html html htm
-text/x-server-parsed-html shtml
-text/plain txt
-text/richtext rtx
-text/tab-separated-values tsv
-text/x-setext etx
-text/x-sgml sgml sgm
-video/mpeg mpeg mpg mpe
-video/quicktime qt mov
-video/x-msvideo avi
-video/x-sgi-movie movie
-x-conference/x-cooltalk ice
-x-world/x-vrml wrl vrml
diff --git a/lib/webtool/priv/root/doc/index.html b/lib/webtool/priv/root/doc/index.html
deleted file mode 100644
index 9fbb143cc7..0000000000
--- a/lib/webtool/priv/root/doc/index.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>Erlang WebTool</TITLE>
-</HEAD>
-<FRAMESET ROWS="60,*">
-<FRAME NAME="top1" SRC="webtool/webtool/started_tools">
-<FRAME NAME="app_frame" SRC="./start_info.html">
-</FRAMESET>
-</HTML>
-
-
diff --git a/lib/webtool/priv/root/doc/start_info.html b/lib/webtool/priv/root/doc/start_info.html
deleted file mode 100644
index fcf44433f1..0000000000
--- a/lib/webtool/priv/root/doc/start_info.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<HTML>
-<HEAD>
-</HEAD>
-<BODY BGCOLOR="#FFFFFF">
-<TABLE WIDTH=100% HEIGHT=100%>
-<TR VALIGN="middle">
-<TD ALIGN="center">
-
-<TABLE WIDTH="60%">
-<TR>
-<TD ALIGN="center"><FONT SIZE=6>Welcome <BR> to<BR> WebTool</FONT></TD>
-</TR>
-
-<TR>
-<TD><BR><BR><BR><BR>
-</TD>
-</TR>
-
-<TR>
-<TD ALIGN="center">Click on the link WebTool on the top of the page, or <A HREF=tool_management.html>here</a> to start the Web based tools.</TD>
-</TR>
-</TABLE>
-
-</TD>
-</TR>
-</TABLE>
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/lib/webtool/priv/root/doc/tool_management.html b/lib/webtool/priv/root/doc/tool_management.html
deleted file mode 100644
index 19d9dbcb9e..0000000000
--- a/lib/webtool/priv/root/doc/tool_management.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>Erlang WebTool </TITLE>
-</HEAD>
-<FRAMESET COLS="200,*">
-<FRAME NAME="left" SRC="/webtool/webtool/toolbar">
-<FRAME NAME="right" SRC="/webtool/webtool/start_tools">
-</FRAMESET>
-
diff --git a/lib/webtool/src/webtool.app.src b/lib/webtool/src/webtool.app.src
deleted file mode 100644
index 6b9750c2b4..0000000000
--- a/lib/webtool/src/webtool.app.src
+++ /dev/null
@@ -1,28 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2009. 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%
-%%
-{application,webtool,
- [{description,"Toolbar lookalike for the web"},
- {vsn,"%VSN%"},
- {modules,[webtool,webtool_sup]},
- {registered,[web_tool,websup]},
- {applications,[kernel,stdlib]},
- {runtime_dependencies, ["stdlib-2.0","observer-2.0","kernel-3.0",
- "inets-5.10","erts-6.0"]}]}.
-
diff --git a/lib/webtool/src/webtool.appup.src b/lib/webtool/src/webtool.appup.src
deleted file mode 100644
index 1394d0d6d5..0000000000
--- a/lib/webtool/src/webtool.appup.src
+++ /dev/null
@@ -1,22 +0,0 @@
-%% -*- erlang -*-
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2014. 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%
-{"%VSN%",
- [{<<".*">>,[{restart_application, webtool}]}],
- [{<<".*">>,[{restart_application, webtool}]}]
-}.
diff --git a/lib/webtool/src/webtool.erl b/lib/webtool/src/webtool.erl
deleted file mode 100644
index a0f2b5aab0..0000000000
--- a/lib/webtool/src/webtool.erl
+++ /dev/null
@@ -1,1207 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2010. 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(webtool).
--behaviour(gen_server).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% The general idea is: %%
-%% %%
-%% %%
-%% 1. Scan through the path for *.tool files and find all the web %%
-%% based tools. Query each tool for configuration data. %%
-%% 2. Add Alias for Erlscript and html for each tool to %%
-%% the webserver configuration data. %%
-%% 3. Start the webserver. %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% API functions
--export([start/0, start/2, stop/0]).
-
-%% Starting Webtool from a shell script
--export([script_start/0, script_start/1]).
-
-%% Web api
--export([started_tools/2, toolbar/2, start_tools/2, stop_tools/2]).
-
-%% API against other tools
--export([is_localhost/0]).
-
-%% Debug export s
--export([get_tools1/1]).
--export([debug/1, stop_debug/0, debug_app/1]).
-
-%% gen_server callbacks
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- terminate/2, code_change/3]).
-
--include_lib("kernel/include/file.hrl").
--include_lib("stdlib/include/ms_transform.hrl").
-
--record(state,{priv_dir,app_data,supvis,web_data,started=[]}).
-
--define(MAX_NUMBER_OF_WEBTOOLS,256).
--define(DEFAULT_PORT,8888).% must be >1024 or the user must be root on unix
--define(DEFAULT_ADDR,{127,0,0,1}).
-
--define(WEBTOOL_ALIAS,{webtool,[{alias,{erl_alias,"/webtool",[webtool]}}]}).
--define(HEADER,"Pragma:no-cache\r\n Content-type: text/html\r\n\r\n").
--define(HTML_HEADER,"<HTML>\r\n<HEAD>\r\n<TITLE>WebTool</TITLE>\r\n</HEAD>\r\n<BODY BGCOLOR=\"#FFFFFF\">\r\n").
--define(HTML_HEADER_RELOAD,"<HTML>\r\n<HEAD>\r\n<TITLE>WebTool
- </TITLE>\r\n</HEAD>\r\n
- <BODY BGCOLOR=\"#FFFFFF\" onLoad=reloadCompiledList()>\r\n").
-
--define(HTML_END,"</BODY></HTML>").
-
--define(SEND_URL_TIMEOUT,5000).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% For debugging only. %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Start tracing with
-%% debug(Functions).
-%% Functions = local | global | FunctionList
-%% FunctionList = [Function]
-%% Function = {FunctionName,Arity} | FunctionName |
-%% {Module, FunctionName, Arity} | {Module,FunctionName}
-debug(F) ->
- ttb:tracer(all,[{file,"webtool.trc"}]), % tracing all nodes
- ttb:p(all,[call,timestamp]),
- MS = [{'_',[],[{return_trace},{message,{caller}}]}],
- tp(F,MS),
- ttb:ctp(?MODULE,stop_debug), % don't want tracing of the stop_debug func
- ok.
-tp(local,MS) -> % all functions
- ttb:tpl(?MODULE,MS);
-tp(global,MS) -> % all exported functions
- ttb:tp(?MODULE,MS);
-tp([{M,F,A}|T],MS) -> % Other module
- ttb:tpl(M,F,A,MS),
- tp(T,MS);
-tp([{M,F}|T],MS) when is_atom(F) -> % Other module
- ttb:tpl(M,F,MS),
- tp(T,MS);
-tp([{F,A}|T],MS) -> % function/arity
- ttb:tpl(?MODULE,F,A,MS),
- tp(T,MS);
-tp([F|T],MS) -> % function
- ttb:tpl(?MODULE,F,MS),
- tp(T,MS);
-tp([],_MS) ->
- ok.
-stop_debug() ->
- ttb:stop([format]).
-
-debug_app(Mod) ->
- ttb:tracer(all,[{file,"webtool_app.trc"},{handler,{fun out/4,true}}]),
- ttb:p(all,[call,timestamp]),
- MS = [{'_',[],[{return_trace},{message,{caller}}]}],
- ttb:tp(Mod,MS),
- ok.
-
-out(_,{trace_ts,Pid,call,MFA={M,F,A},{W,_,_},TS},_,S)
- when W==webtool;W==mod_esi->
- io:format("~w: (~p)~ncall ~s~n", [TS,Pid,ffunc(MFA)]),
- [{M,F,length(A)}|S];
-out(_,{trace_ts,Pid,return_from,MFA,R,TS},_,[MFA|S]) ->
- io:format("~w: (~p)~nreturned from ~s -> ~p~n", [TS,Pid,ffunc(MFA),R]),
- S;
-out(_,_,_,_) ->
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Functions called via script. %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-script_start() ->
- usage(),
- halt().
-script_start([App]) ->
- DefaultBrowser =
- case os:type() of
- {win32,_} -> iexplore;
- _ -> firefox
- end,
- script_start([App,DefaultBrowser]);
-script_start([App,Browser]) ->
- io:format("Starting webtool...\n"),
- start(),
- AvailableApps = get_applications(),
- {OSType,_} = os:type(),
- case lists:keysearch(App,1,AvailableApps) of
- {value,{App,StartPage}} ->
- io:format("Starting ~w...\n",[App]),
- start_tools([],"app=" ++ atom_to_list(App)),
- PortStr = integer_to_list(get_port()),
- Url = case StartPage of
- "/" ++ Page ->
- "http://localhost:" ++ PortStr ++ "/" ++ Page;
- _ ->
- "http://localhost:" ++ PortStr ++ "/" ++ StartPage
- end,
- case Browser of
- none ->
- ok;
- iexplore when OSType == win32->
- io:format("Starting internet explorer...\n"),
- {ok,R} = win32reg:open(""),
- Key="\\local_machine\\SOFTWARE\\Microsoft\\IE Setup\\Setup",
- win32reg:change_key(R,Key),
- {ok,Val} = win32reg:value(R,"Path"),
- IExplore=filename:join(win32reg:expand(Val),"iexplore.exe"),
- os:cmd("\"" ++ IExplore ++ "\" " ++ Url);
- _ when OSType == win32 ->
- io:format("Starting ~w...\n",[Browser]),
- os:cmd("\"" ++ atom_to_list(Browser) ++ "\" " ++ Url);
- B when B==firefox; B==mozilla ->
- io:format("Sending URL to ~w...",[Browser]),
- BStr = atom_to_list(Browser),
- SendCmd = BStr ++ " -raise -remote \'openUrl(" ++
- Url ++ ")\'",
- Port = open_port({spawn,SendCmd},[exit_status]),
- receive
- {Port,{exit_status,0}} ->
- io:format("done\n"),
- ok;
- {Port,{exit_status,_Error}} ->
- io:format(" not running, starting ~w...\n",
- [Browser]),
- os:cmd(BStr ++ " " ++ Url),
- ok
- after ?SEND_URL_TIMEOUT ->
- io:format(" failed, starting ~w...\n",[Browser]),
- erlang:port_close(Port),
- os:cmd(BStr ++ " " ++ Url)
- end;
- _ ->
- io:format("Starting ~w...\n",[Browser]),
- os:cmd(atom_to_list(Browser) ++ " " ++ Url)
- end,
- ok;
- false ->
- stop(),
- io:format("\n{error,{unknown_app,~p}}\n",[App]),
- halt()
- end.
-
-usage() ->
- io:format("Starting webtool...\n"),
- start(),
- Apps = lists:map(fun({A,_}) -> A end,get_applications()),
- io:format(
- "\nUsage: start_webtool application [ browser ]\n"
- "\nAvailable applications are: ~p\n"
- "Default browser is \'iexplore\' (Internet Explorer) on Windows "
- "or else \'firefox\'\n",
- [Apps]),
- stop().
-
-
-get_applications() ->
- gen_server:call(web_tool,get_applications).
-
-get_port() ->
- gen_server:call(web_tool,get_port).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Api functions to the genserver. %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%----------------------------------------------------------------------
-%
-%----------------------------------------------------------------------
-
-start()->
- start(standard_path,standard_data).
-
-start(Path,standard_data)->
- case get_standard_data() of
- {error,Reason} ->
- {error,Reason};
- Data ->
- start(Path,Data)
- end;
-
-start(standard_path,Data)->
- Path=get_path(),
- start(Path,Data);
-
-start(Path,Port) when is_integer(Port)->
- Data = get_standard_data(Port),
- start(Path,Data);
-
-start(Path,Data0)->
- Data = Data0 ++ rest_of_standard_data(),
- gen_server:start({local,web_tool},webtool,{Path,Data},[]).
-
-stop()->
- gen_server:call(web_tool,stoppit).
-
-%----------------------------------------------------------------------
-%Web Api functions called by the web
-%----------------------------------------------------------------------
-started_tools(Env,Input)->
- gen_server:call(web_tool,{started_tools,Env,Input}).
-
-toolbar(Env,Input)->
- gen_server:call(web_tool,{toolbar,Env,Input}).
-
-start_tools(Env,Input)->
- gen_server:call(web_tool,{start_tools,Env,Input}).
-
-stop_tools(Env,Input)->
- gen_server:call(web_tool,{stop_tools,Env,Input}).
-%----------------------------------------------------------------------
-%Support API for other tools
-%----------------------------------------------------------------------
-
-is_localhost()->
- gen_server:call(web_tool,is_localhost).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%%The gen_server callback functions that builds the webbpages %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-handle_call(get_applications,_,State)->
- MS = ets:fun2ms(fun({Tool,{web_data,{_,Start}}}) -> {Tool,Start} end),
- Tools = ets:select(State#state.app_data,MS),
- {reply,Tools,State};
-
-handle_call(get_port,_,State)->
- {value,{port,Port}}=lists:keysearch(port,1,State#state.web_data),
- {reply,Port,State};
-
-handle_call({started_tools,_Env,_Input},_,State)->
- {reply,started_tools_page(State),State};
-
-handle_call({toolbar,_Env,_Input},_,State)->
- {reply,toolbar(),State};
-
-handle_call({start_tools,Env,Input},_,State)->
- {NewState,Page}=start_tools_page(Env,Input,State),
- {reply,Page,NewState};
-
-handle_call({stop_tools,Env,Input},_,State)->
- {NewState,Page}=stop_tools_page(Env,Input,State),
- {reply,Page,NewState};
-
-handle_call(stoppit,_From,Data)->
- {stop,normal,ok,Data};
-
-handle_call(is_localhost,_From,Data)->
- Result=case proplists:get_value(bind_address, Data#state.web_data) of
- ?DEFAULT_ADDR ->
- true;
- _IpNumber ->
- false
- end,
- {reply,Result,Data}.
-
-
-handle_info(_Message,State)->
- {noreply,State}.
-
-handle_cast(_Request,State)->
- {noreply,State}.
-
-code_change(_,State,_)->
- {ok,State}.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-% The other functions needed by the gen_server behaviour
-%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%----------------------------------------------------------------------
-% Start the gen_server
-%----------------------------------------------------------------------
-init({Path,Config})->
- case filelib:is_dir(Path) of
- true ->
- {ok, Table} = get_tool_files_data(),
- insert_app(?WEBTOOL_ALIAS, Table),
- case webtool_sup:start_link() of
- {ok, Pid} ->
- case start_webserver(Table, Path, Config) of
- {ok, _} ->
- print_url(Config),
- {ok,#state{priv_dir=Path,
- app_data=Table,
- supvis=Pid,
- web_data=Config}};
- {error, Error} ->
- {stop, {error, Error}}
- end;
- Error ->
- {stop,Error}
- end;
- false ->
- {stop, {error, error_dir}}
- end.
-
-terminate(_Reason,Data)->
- %%shut down the webbserver
- shutdown_server(Data),
- %%Shutdown the different tools that are started with application:start
- shutdown_apps(Data),
- %%Shutdown the supervisor and its children will die
- shutdown_supervisor(Data),
- ok.
-
-print_url(ConfigData)->
- Server=proplists:get_value(server_name,ConfigData,"undefined"),
- Port=proplists:get_value(port,ConfigData,"undefined"),
- {A,B,C,D}=proplists:get_value(bind_address,ConfigData,"undefined"),
- io:format("WebTool is available at http://~s:~w/~n",[Server,Port]),
- io:format("Or http://~w.~w.~w.~w:~w/~n",[A,B,C,D,Port]).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-% begin build the pages
-%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%----------------------------------------------------------------------
-%The page that shows the started tools
-%----------------------------------------------------------------------
-started_tools_page(State)->
- [?HEADER,?HTML_HEADER,started_tools(State),?HTML_END].
-
-toolbar()->
- [?HEADER,?HTML_HEADER,toolbar_page(),?HTML_END].
-
-
-start_tools_page(_Env,Input,State)->
- %%io:format("~n======= ~n ~p ~n============~n",[Input]),
- case get_tools(Input) of
- {tools,Tools}->
- %%io:format("~n======= ~n ~p ~n============~n",[Tools]),
- {ok,NewState}=handle_apps(Tools,State,start),
- {NewState,[?HEADER,?HTML_HEADER_RELOAD,reload_started_apps(),
- show_unstarted_apps(NewState),?HTML_END]};
- _ ->
- {State,[?HEADER,?HTML_HEADER,show_unstarted_apps(State),?HTML_END]}
- end.
-
-stop_tools_page(_Env,Input,State)->
- case get_tools(Input) of
- {tools,Tools}->
- {ok,NewState}=handle_apps(Tools,State,stop),
- {NewState,[?HEADER,?HTML_HEADER_RELOAD,reload_started_apps(),
- show_started_apps(NewState),?HTML_END]};
- _ ->
- {State,[?HEADER,?HTML_HEADER,show_started_apps(State),?HTML_END]}
- end.
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Functions that start and config the webserver
-%% 1. Collect the config data
-%% 2. Start webserver
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%----------------------------------------------------------------------
-% Start the webserver
-%----------------------------------------------------------------------
-start_webserver(Data,Path,Config)->
- case get_conf_data(Data,Path,Config) of
- {ok,Conf_data}->
- %%io:format("Conf_data: ~p~n",[Conf_data]),
- start_server(Conf_data);
- {error,Error} ->
- {error,{error_server_conf_file,Error}}
- end.
-
-start_server(Conf_data)->
- case inets:start(httpd, Conf_data, stand_alone) of
- {ok,Pid}->
- {ok,Pid};
- Error->
- {error,{server_error,Error}}
- end.
-
-%----------------------------------------------------------------------
-% Create config data for the webserver
-%----------------------------------------------------------------------
-get_conf_data(Data,Path,Config)->
- Aliases=get_aliases(Data),
- ServerRoot = filename:join([Path,"root"]),
- MimeTypesFile = filename:join([ServerRoot,"conf","mime.types"]),
- case httpd_conf:load_mime_types(MimeTypesFile) of
- {ok,MimeTypes} ->
- Config1 = Config ++ Aliases,
- Config2 = [{server_root,ServerRoot},
- {document_root,filename:join([Path,"root/doc"])},
- {mime_types,MimeTypes} |
- Config1],
- {ok,Config2};
- Error ->
- Error
- end.
-
-%----------------------------------------------------------------------
-% Control the path for *.tools files
-%----------------------------------------------------------------------
-get_tool_files_data()->
- Tools=get_tools1(code:get_path()),
- %%io:format("Data : ~p ~n",[Tools]),
- get_file_content(Tools).
-
-%----------------------------------------------------------------------
-%Control that the data in the file really is erlang terms
-%----------------------------------------------------------------------
-get_file_content(Tools)->
- Get_data=fun({tool,ToolData}) ->
- %%io:format("Data : ~p ~n",[ToolData]),
- case proplists:get_value(config_func,ToolData) of
- {M,F,A}->
- case catch apply(M,F,A) of
- {'EXIT',_} ->
- bad_data;
- Data when is_tuple(Data) ->
- Data;
- _->
- bad_data
- end;
- _ ->
- bad_data
- end
- end,
- insert_file_content([X ||X<-lists:map(Get_data,Tools),X/=bad_data]).
-
-%----------------------------------------------------------------------
-%Insert the data from the file in to the ets:table
-%----------------------------------------------------------------------
-insert_file_content(Content)->
- Table=ets:new(app_data,[bag]),
- lists:foreach(fun(X)->
- insert_app(X,Table)
- end,Content),
- {ok,Table}.
-
-%----------------------------------------------------------------------
-%Control that we got a a tuple of a atom and a list if so add the
-%elements in the list to the ets:table
-%----------------------------------------------------------------------
-insert_app({Name,Key_val_list},Table) when is_list(Key_val_list),is_atom(Name)->
- %%io:format("ToolData: ~p: ~p~n",[Name,Key_val_list]),
- lists:foreach(
- fun({alias,{erl_alias,Alias,Mods}}) ->
- Key_val = {erl_script_alias,{Alias,Mods}},
- %%io:format("Insert: ~p~n",[Key_val]),
- ets:insert(Table,{Name,Key_val});
- (Key_val_pair)->
- %%io:format("Insert: ~p~n",[Key_val_pair]),
- ets:insert(Table,{Name,Key_val_pair})
- end,
- Key_val_list);
-
-insert_app(_,_)->
- ok.
-
-%----------------------------------------------------------------------
-% Select all the alias in the database
-%----------------------------------------------------------------------
-get_aliases(Data)->
- MS = ets:fun2ms(fun({_,{erl_script_alias,Alias}}) ->
- {erl_script_alias,Alias};
- ({_,{alias,Alias}}) ->
- {alias,Alias}
- end),
- ets:select(Data,MS).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Helper functions %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-get_standard_data(Port)->
- [
- {port,Port},
- {bind_address,?DEFAULT_ADDR},
- {server_name,"localhost"}
- ].
-
-get_standard_data()->
- case get_free_port(?DEFAULT_PORT,?MAX_NUMBER_OF_WEBTOOLS) of
- {error,Reason} -> {error,Reason};
- Port ->
- [
- {port,Port},
- {bind_address,?DEFAULT_ADDR},
- {server_name,"localhost"}
- ]
- end.
-
-get_free_port(_Port,0) ->
- {error,no_free_port_found};
-get_free_port(Port,N) ->
- case gen_tcp:connect("localhost",Port,[]) of
- {error, _Reason} ->
- Port;
- {ok,Sock} ->
- gen_tcp:close(Sock),
- get_free_port(Port+1,N-1)
- end.
-
-rest_of_standard_data() ->
- [
- %% Do not allow the server to be crashed by malformed http-request
- {max_header_siz,1024},
- {max_header_action,reply414},
- %% Go on a straight ip-socket
- {com_type,ip_comm},
- %% Do not change the order of these module names!!
- {modules,[mod_alias,
- mod_auth,
- mod_esi,
- mod_actions,
- mod_cgi,
- mod_dir,
- mod_get,
- mod_head,
- mod_log,
- mod_disk_log]},
- {directory_index,["index.html"]},
- {default_type,"text/plain"}
- ].
-
-
-get_path()->
- code:priv_dir(webtool).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% These functions is used to shutdown the webserver
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%----------------------------------------------------------------------
-% Shut down the webbserver
-%----------------------------------------------------------------------
-shutdown_server(State)->
- {Addr,Port} = get_addr_and_port(State#state.web_data),
- inets:stop(httpd,{Addr,Port}).
-
-get_addr_and_port(Config) ->
- Addr = proplists:get_value(bind_address,Config,?DEFAULT_ADDR),
- Port = proplists:get_value(port,Config,?DEFAULT_PORT),
- {Addr,Port}.
-
-%----------------------------------------------------------------------
-% Select all apps in the table and close them
-%----------------------------------------------------------------------
-shutdown_apps(State)->
- Data=State#state.app_data,
- MS = ets:fun2ms(fun({_,{start,HowToStart}}) -> HowToStart end),
- lists:foreach(fun(Start_app)->
- stop_app(Start_app)
- end,
- ets:select(Data,MS)).
-
-%----------------------------------------------------------------------
-%Shuts down the supervisor that supervises tools that is not
-%Designed as applications
-%----------------------------------------------------------------------
-shutdown_supervisor(State)->
- %io:format("~n==================~n"),
- webtool_sup:stop(State#state.supvis).
- %io:format("~n==================~n").
-
-%----------------------------------------------------------------------
-%close the individual apps.
-%----------------------------------------------------------------------
-stop_app({child,_Real_name})->
- ok;
-
-stop_app({app,Real_name})->
- application:stop(Real_name);
-
-stop_app({func,_Start,Stop})->
- case Stop of
- {M,F,A} ->
- catch apply(M,F,A);
- _NoStop ->
- ok
- end.
-
-
-
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% These functions creates the webpage where the user can select if
-%% to start apps or to stop apps
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-toolbar_page()->
- "<TABLE>
- <TR>
- <TD>
- <B>Select Action</B>
- </TD>
- </TR>
- <TR>
- <TD>
- <A HREF=\"./start_tools\" TARGET=right> Start Tools</A>
- </TD>
- </TR>
- <TR>
- <TD>
- <A HREF=\"./stop_tools\" TARGET=right> Stop Tools</A>
- </TD>
- </TR>
- </TABLE>".
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% These functions creates the webbpage that shows the started apps
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%----------------------------------------------------------------------
-% started_tools(State)->String (html table)
-% State is a record of type state
-%----------------------------------------------------------------------
-started_tools(State)->
- Names=get_started_apps(State#state.app_data,State#state.started),
- "<TABLE BORDER=1 WIDTH=100%>
- "++ make_rows(Names,[],0) ++"
- </TABLE>".
-%----------------------------------------------------------------------
-%get_started_apps(Data,Started)-> [{web_name,link}]
-%selects the started apps from the ets table of apps.
-%----------------------------------------------------------------------
-
-get_started_apps(Data,Started)->
- SelectData=fun({Name,Link}) ->
- {Name,Link}
- end,
- MS = lists:map(fun(A) -> {{A,{web_data,'$1'}},[],['$1']} end,Started),
-
- [{"WebTool","/tool_management.html"} |
- [SelectData(X) || X <- ets:select(Data,MS)]].
-
-%----------------------------------------------------------------------
-% make_rows(List,Result,Fields)-> String (The rows of a htmltable
-% List a list of tupler discibed above
-% Result an accumulator for the result
-% Field, counter that counts the number of cols in each row.
-%----------------------------------------------------------------------
-make_rows([],Result,Fields)->
- Result ++ fill_out(Fields);
-make_rows([Data|Paths],Result,Field)when Field==0->
- make_rows(Paths,Result ++ "<TR>" ++ make_field(Data),Field+1);
-
-make_rows([Path|Paths],Result,Field)when Field==4->
- make_rows(Paths,Result ++ make_field(Path) ++ "</TR>",0);
-
-make_rows([Path|Paths],Result,Field)->
- make_rows(Paths,Result ++ make_field(Path),Field+1).
-
-%----------------------------------------------------------------------
-% make_fields(Path)-> String that is a field i a html table
-% Path is a name url tuple {Name,url}
-%----------------------------------------------------------------------
-make_field(Path)->
- "<TD WIDTH=20%>" ++ get_name(Path) ++ "</TD>".
-
-
-%----------------------------------------------------------------------
-%get_name({Nae,Url})->String that represents a <A> tag in html.
-%----------------------------------------------------------------------
-get_name({Name,Url})->
- "<A HREF=\"" ++ Url ++ "\" TARGET=app_frame>" ++ Name ++ "</A>".
-
-
-%----------------------------------------------------------------------
-% fill_out(Nr)-> String, that represent Nr fields in a html-table.
-%----------------------------------------------------------------------
-fill_out(Nr)when Nr==0->
- [];
-fill_out(Nr)when Nr==4->
- "<TD WIDTH=\"20%\" >&nbsp</TD></TR>";
-
-fill_out(Nr)->
- "<TD WIDTH=\"20%\">&nbsp</TD>" ++ fill_out(Nr+1).
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%%These functions starts applicatons and builds the page showing tools
-%%to start
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%----------------------------------------------------------------------
-%Controls whether the user selected a tool to start
-%----------------------------------------------------------------------
-get_tools(Input)->
- case httpd:parse_query(Input) of
- []->
- no_tools;
- Tools->
- FormatData=fun({_Name,Data}) -> list_to_atom(Data) end,
- SelectData=
- fun({Name,_Data}) -> string:equal(Name,"app") end,
- {tools,[FormatData(X)||X<-Tools,SelectData(X)]}
- end.
-
-%----------------------------------------------------------------------
-% Selects the data to start the applications the user has ordered
-% starting of
-%----------------------------------------------------------------------
-handle_apps([],State,_Cmd)->
- {ok,State};
-
-handle_apps([Tool|Tools],State,Cmd)->
- case ets:match_object(State#state.app_data,{Tool,{start,'_'}}) of
- []->
- Started = case Cmd of
- start ->
- [Tool|State#state.started];
- stop ->
- lists:delete(Tool,State#state.started)
- end,
- {ok,#state{priv_dir=State#state.priv_dir,
- app_data=State#state.app_data,
- supvis=State#state.supvis,
- web_data=State#state.web_data,
- started=Started}};
- ToStart ->
- case handle_apps2(ToStart,State,Cmd) of
- {ok,NewState}->
- handle_apps(Tools,NewState,Cmd);
- _->
- handle_apps(Tools,State,Cmd)
- end
- end.
-
-%----------------------------------------------------------------------
-%execute every start or stop data about a tool.
-%----------------------------------------------------------------------
-handle_apps2([{Name,Start_data}],State,Cmd)->
- case handle_app({Name,Start_data},State#state.app_data,State#state.supvis,Cmd) of
- ok->
- Started = case Cmd of
- start ->
- [Name|State#state.started];
- stop ->
-
- lists:delete(Name,State#state.started)
- end,
- {ok,#state{priv_dir=State#state.priv_dir,
- app_data=State#state.app_data,
- supvis=State#state.supvis,
- web_data=State#state.web_data,
- started=Started}};
- _->
- error
- end;
-
-handle_apps2([{Name,Start_data}|Rest],State,Cmd)->
- case handle_app({Name,Start_data},State#state.app_data,State#state.supvis,Cmd)of
- ok->
- handle_apps2(Rest,State,Cmd);
- _->
- error
- end.
-
-
-%----------------------------------------------------------------------
-% Handle start and stop of applications
-%----------------------------------------------------------------------
-
-handle_app({Name,{start,{func,Start,Stop}}},Data,_Pid,Cmd)->
- Action = case Cmd of
- start ->
- Start;
- _ ->
- Stop
- end,
- case Action of
- {M,F,A} ->
- case catch apply(M,F,A) of
- {'EXIT',_} = Exit->
- %%! Here the tool disappears from the webtool interface!!
- io:format("\n=======ERROR (webtool, line ~w) =======\n"
- "Could not start application \'~p\'\n\n"
- "~w:~w(~s) ->\n"
- "~p\n\n",
- [?LINE,Name,M,F,format_args(A),Exit]),
- ets:delete(Data,Name);
- _OK->
- ok
- end;
- _NoStart ->
- ok
- end;
-
-
-handle_app({Name,{start,{child,ChildSpec}}},Data,Pid,Cmd)->
- case Cmd of
- start ->
- case catch supervisor:start_child(Pid,ChildSpec) of
- {ok,_}->
- ok;
- {ok,_,_}->
- ok;
- {error,Reason}->
- %%! Here the tool disappears from the webtool interface!!
- io:format("\n=======ERROR (webtool, line ~w) =======\n"
- "Could not start application \'~p\'\n\n"
- "supervisor:start_child(~p,~p) ->\n"
- "~p\n\n",
- [?LINE,Name,Pid,ChildSpec,{error,Reason}]),
- ets:delete(Data,Name);
- Error ->
- %%! Here the tool disappears from the webtool interface!!
- io:format("\n=======ERROR (webtool, line ~w) =======\n"
- "Could not start application \'~p\'\n\n"
- "supervisor:start_child(~p,~p) ->\n"
- "~p\n\n",
- [?LINE,Name,Pid,ChildSpec,Error]),
- ets:delete(Data,Name)
- end;
- stop ->
- case catch supervisor:terminate_child(websup,element(1,ChildSpec)) of
- ok ->
- supervisor:delete_child(websup,element(1,ChildSpec));
- _ ->
- error
- end
- end;
-
-
-
-handle_app({Name,{start,{app,Real_name}}},Data,_Pid,Cmd)->
- case Cmd of
- start ->
- case application:start(Real_name,temporary) of
- ok->
- io:write(Name),
- ok;
- {error,{already_started,_}}->
- %% Remove it from the database so we dont start
- %% anything already started
- ets:match_delete(Data,{Name,{start,{app,Real_name}}}),
- ok;
- {error,_Reason}=Error->
- %%! Here the tool disappears from the webtool interface!!
- io:format("\n=======ERROR (webtool, line ~w) =======\n"
- "Could not start application \'~p\'\n\n"
- "application:start(~p,~p) ->\n"
- "~p\n\n",
- [?LINE,Name,Real_name,temporary,Error]),
- ets:delete(Data,Name)
- end;
-
- stop ->
- application:stop(Real_name)
- end;
-
-%----------------------------------------------------------------------
-% If the data is incorrect delete the app
-%----------------------------------------------------------------------
-handle_app({Name,Incorrect},Data,_Pid,Cmd)->
- %%! Here the tool disappears from the webtool interface!!
- io:format("\n=======ERROR (webtool, line ~w) =======\n"
- "Could not ~w application \'~p\'\n\n"
- "Incorrect data: ~p\n\n",
- [?LINE,Cmd,Name,Incorrect]),
- ets:delete(Data,Name).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% this functions creates the page that shows the unstarted tools %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-reload_started_apps()->
- "<script>
- function reloadCompiledList()
- {
- parent.parent.top1.document.location.href=\"/webtool/webtool/started_tools\";
- }
- </script>".
-
-show_unstarted_apps(State)->
- "<TABLE HEIGHT=100% WIDTH=100% BORDER=0>
- <TR HEIGHT=80%><TD ALIGN=\"center\" VALIGN=\"middle\">
- <FORM NAME=\"stop_apps\" ACTION=\"/webtool/webtool/start_tools\" >
- <TABLE BORDER=1 WIDTH=60%>
- <TR BGCOLOR=\"#8899AA\">
- <TD ALIGN=CENTER COLSPAN=2><FONT SIZE=4>Available Tools<FONT></TD>
- </TR>
- <TR>
- <TD WIDTH=50%>
- <TABLE BORDER=0>
- "++ list_available_apps(State)++"
- <TR><TD COLSPAN=2>&nbsp;</TD></TR>
- <TR>
- <TD COLSPAN=2 ALIGN=\"center\">
- <INPUT TYPE=submit VALUE=\"Start\">
- </TD>
- </TR>
- </TABLE>
- </TD>
- <TD>
- To Start a Tool:
- <UL>
- <LI>Select the
- checkbox for each tool to
- start.</LI>
- <LI>Click on the
- button marked <EM>Start</EM>.</LI></UL>
- </TD>
- </TR>
- </TABLE>
- </FORM>
- </TD></TR>
- <TR><TD>&nbsp;</TD></TR>
- </TABLE>".
-
-
-
-list_available_apps(State)->
- MS = ets:fun2ms(fun({Tool,{web_data,{Name,_}}}) -> {Tool,Name} end),
- Unstarted_apps=
- lists:filter(
- fun({Tool,_})->
- false==lists:member(Tool,State#state.started)
- end,
- ets:select(State#state.app_data,MS)),
- case Unstarted_apps of
- []->
- "<TR><TD>All tools are started</TD></TR>";
- _->
- list_apps(Unstarted_apps)
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% these functions creates the page that shows the started apps %%
-%% the user can select to shutdown %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-show_started_apps(State)->
- "<TABLE HEIGHT=100% WIDTH=100% BORDER=0>
- <TR HEIGHT=80%><TD ALIGN=\"center\" VALIGN=\"middle\">
- <FORM NAME=\"stop_apps\" ACTION=\"/webtool/webtool/stop_tools\" >
- <TABLE BORDER=1 WIDTH=60%>
- <TR BGCOLOR=\"#8899AA\">
- <TD ALIGN=CENTER COLSPAN=2><FONT SIZE=4>Started Tools<FONT></TD>
- </TR>
- <TR>
- <TD WIDTH=50%>
- <TABLE BORDER=0>
- "++ list_started_apps(State)++"
- <TR><TD COLSPAN=2>&nbsp;</TD></TR>
- <TR>
- <TD COLSPAN=2 ALIGN=\"center\">
- <INPUT TYPE=submit VALUE=\"Stop\">
- </TD>
- </TR>
- </TABLE>
- </TD>
- <TD>
- Stop a Tool:
- <UL>
- <LI>Select the
- checkbox for each tool to
- stop.</LI>
- <LI>Click on the
- button marked <EM>Stop</EM>.</LI></UL>
- </TD>
- </TR>
- </TABLE>
- </FORM>
- </TD></TR>
- <TR><TD>&nbsp;</TD></TR>
- </TABLE>".
-
-list_started_apps(State)->
- MS = lists:map(fun(A) -> {{A,{web_data,{'$1','_'}}},[],[{{A,'$1'}}]} end,
- State#state.started),
- Started_apps= ets:select(State#state.app_data,MS),
- case Started_apps of
- []->
- "<TR><TD>No tool is started yet.</TD></TR>";
- _->
- list_apps(Started_apps)
- end.
-
-
-list_apps(Apps) ->
- lists:map(fun({Tool,Name})->
- "<TR><TD>
- <INPUT TYPE=\"checkbox\" NAME=\"app\" VALUE=\""
- ++ atom_to_list(Tool) ++ "\">
- " ++ Name ++ "
- </TD></TR>"
- end,
- Apps).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Collecting the data from the *.tool files %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%----------------------------------------
-% get_tools(Dirs) => [{M,F,A},{M,F,A}...{M,F,A}]
-% Dirs - [string()] Directory names
-% Calls get_tools2/2 recursively for a number of directories
-% to retireve the configuration data for the web based tools.
-%----------------------------------------
-get_tools1(Dirs)->
- get_tools1(Dirs,[]).
-
-get_tools1([Dir|Rest],Data) when is_list(Dir) ->
- Tools=case filename:basename(Dir) of
- %% Dir is an 'ebin' directory, check in '../priv' as well
- "ebin" ->
- [get_tools2(filename:join(filename:dirname(Dir),"priv")) |
- get_tools2(Dir)];
- _ ->
- get_tools2(Dir)
- end,
- get_tools1(Rest,[Tools|Data]);
-
-get_tools1([],Data) ->
- lists:flatten(Data).
-
-%----------------------------------------
-% get_tools2(Directory) => DataList
-% DataList : [WebTuple]|[]
-% WebTuple: {tool,[{web,M,F,A}]}
-%
-%----------------------------------------
-get_tools2(Dir)->
- get_tools2(tool_files(Dir),[]).
-
-get_tools2([ToolFile|Rest],Data) ->
- case get_tools3(ToolFile) of
- {tool,WebData} ->
- get_tools2(Rest,[{tool,WebData}|Data]);
- {error,_Reason} ->
- get_tools2(Rest,Data);
- nodata ->
- get_tools2(Rest,Data)
- end;
-
-get_tools2([],Data) ->
- Data.
-
-%----------------------------------------
-% get_tools3(ToolFile) => {ok,Tool}|{error,Reason}|nodata
-% Tool: {tool,[KeyValTuple]}
-% ToolFile - string() A .tool file
-% Now we have the file get the data and sort it out
-%----------------------------------------
-get_tools3(ToolFile) ->
- case file:consult(ToolFile) of
- {error,open} ->
- {error,nofile};
- {error,read} ->
- {error,format};
- {ok,[{version,"1.2"},ToolInfo]} when is_list(ToolInfo)->
- webdata(ToolInfo);
- {ok,[{version,_Vsn},_Info]} ->
- {error,old_version};
- {ok,_Other} ->
- {error,format}
- end.
-
-
-%----------------------------------------------------------------------
-% webdata(TupleList)-> ToolTuple| nodata
-% ToolTuple: {tool,[{config_func,{M,F,A}}]}
-%
-% There are a little unneccesary work in this format but it is extendable
-%----------------------------------------------------------------------
-webdata(TupleList)->
- case proplists:get_value(config_func,TupleList,nodata) of
- {M,F,A} ->
- {tool,[{config_func,{M,F,A}}]};
- _ ->
- nodata
- end.
-
-
-%=============================================================================
-% Functions for getting *.tool configuration files
-%=============================================================================
-
-%----------------------------------------
-% tool_files(Dir) => ToolFiles
-% Dir - string() Directory name
-% ToolFiles - [string()]
-% Return the list of all files in Dir ending with .tool (appended to Dir)
-%----------------------------------------
-tool_files(Dir) ->
- case file:list_dir(Dir) of
- {ok,Files} ->
- filter_tool_files(Dir,Files);
- {error,_Reason} ->
- []
- end.
-
-%----------------------------------------
-% filter_tool_files(Dir,Files) => ToolFiles
-% Dir - string() Directory name
-% Files, ToolFiles - [string()] File names
-% Filters out the files in Files ending with .tool and append them to Dir
-%----------------------------------------
-filter_tool_files(_Dir,[]) ->
- [];
-filter_tool_files(Dir,[File|Rest]) ->
- case filename:extension(File) of
- ".tool" ->
- [filename:join(Dir,File)|filter_tool_files(Dir,Rest)];
- _ ->
- filter_tool_files(Dir,Rest)
- end.
-
-
-%%%-----------------------------------------------------------------
-%%% format functions
-ffunc({M,F,A}) when is_list(A) ->
- io_lib:format("~w:~w(~s)\n",[M,F,format_args(A)]);
-ffunc({M,F,A}) when is_integer(A) ->
- io_lib:format("~w:~w/~w\n",[M,F,A]).
-
-format_args([]) ->
- "";
-format_args(Args) ->
- Str = lists:append(["~p"|lists:duplicate(length(Args)-1,",~p")]),
- io_lib:format(Str,Args).
diff --git a/lib/webtool/src/webtool_sup.erl b/lib/webtool/src/webtool_sup.erl
deleted file mode 100644
index e4a05c53ae..0000000000
--- a/lib/webtool/src/webtool_sup.erl
+++ /dev/null
@@ -1,75 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2009. 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(webtool_sup).
-
--behaviour(supervisor).
-
-%% External exports
--export([start_link/0,stop/1]).
-
-%% supervisor callbacks
--export([init/1]).
-
-%%%----------------------------------------------------------------------
-%%% API
-%%%----------------------------------------------------------------------
-start_link() ->
- supervisor:start_link({local,websup},webtool_sup, []).
-
-stop(Pid)->
- exit(Pid,normal).
-%%%----------------------------------------------------------------------
-%%% Callback functions from supervisor
-%%%----------------------------------------------------------------------
-
-%%----------------------------------------------------------------------
-%% Func: init/1
-%% Returns: {ok, {SupFlags, [ChildSpec]}} |
-%% ignore |
-%% {error, Reason}
-%%----------------------------------------------------------------------
-init(_StartArgs) ->
- %%Child1 =
- %%Child2 ={webcover_backend,{webcover_backend,start_link,[]},permanent,2000,worker,[webcover_backend]},
- %%{ok,{{simple_one_for_one,5,10},[Child1]}}.
- {ok,{{one_for_one,100,10},[]}}.
-
-%%%----------------------------------------------------------------------
-%%% Internal functions
-%%%----------------------------------------------------------------------
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/webtool/test/Makefile b/lib/webtool/test/Makefile
deleted file mode 100644
index 93aa1c09eb..0000000000
--- a/lib/webtool/test/Makefile
+++ /dev/null
@@ -1,65 +0,0 @@
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES= \
- webtool_SUITE
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-INSTALL_PROGS= $(TARGET_FILES)
-
-EMAKEFILE=Emakefile
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/webtool_test
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
-
-EBIN = .
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-make_emakefile:
- $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \
- > $(EMAKEFILE)
- $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' \
- >> $(EMAKEFILE)
-
-tests debug opt: make_emakefile
- erl $(ERL_MAKE_FLAGS) -make
-
-clean:
- rm -f $(EMAKEFILE)
- rm -f $(TARGET_FILES) $(GEN_FILES)
- rm -f core
-
-docs:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
-
-release_tests_spec: make_emakefile
- $(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) "$(RELSYSDIR)"
- $(INSTALL_DATA) webtool.spec "$(RELSYSDIR)"
- chmod -R u+w "$(RELSYSDIR)"
-
-release_docs_spec:
diff --git a/lib/webtool/test/webtool.spec b/lib/webtool/test/webtool.spec
deleted file mode 100644
index 134e6ed40c..0000000000
--- a/lib/webtool/test/webtool.spec
+++ /dev/null
@@ -1 +0,0 @@
-{suites,"../webtool_test",all}.
diff --git a/lib/webtool/test/webtool_SUITE.erl b/lib/webtool/test/webtool_SUITE.erl
deleted file mode 100644
index 9e2d9a2e0f..0000000000
--- a/lib/webtool/test/webtool_SUITE.erl
+++ /dev/null
@@ -1,51 +0,0 @@
-%% ``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.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-%% AB. All Rights Reserved.''
-%%
--module(webtool_SUITE).
-
--compile([export_all]).
--include_lib("common_test/include/ct.hrl").
-
-suite() ->
- [{ct_hooks, [ts_install_cth]}].
-
-all() ->
- [app, appup].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-app() ->
- [{doc, "Test that the webtool app file is ok"}].
-app(Config) when is_list(Config) ->
- ok = ?t:app_test(webtool).
-
-appup() ->
- [{doc, "Test that the webtool appup file is ok"}].
-appup(Config) when is_list(Config) ->
- ok = ?t:appup_test(webtool).
diff --git a/lib/webtool/vsn.mk b/lib/webtool/vsn.mk
deleted file mode 100644
index 92201282c0..0000000000
--- a/lib/webtool/vsn.mk
+++ /dev/null
@@ -1 +0,0 @@
-WEBTOOL_VSN=0.9.1
diff --git a/lib/wx/examples/demo/ex_canvas.erl b/lib/wx/examples/demo/ex_canvas.erl
index cdc783055c..acc94743d6 100644
--- a/lib/wx/examples/demo/ex_canvas.erl
+++ b/lib/wx/examples/demo/ex_canvas.erl
@@ -219,4 +219,4 @@ redraw(DC, Bitmap) ->
wxMemoryDC:destroy(MemoryDC).
get_pos(W,H) ->
- {random:uniform(W), random:uniform(H)}.
+ {rand:uniform(W), rand:uniform(H)}.
diff --git a/lib/wx/examples/sudoku/sudoku_game.erl b/lib/wx/examples/sudoku/sudoku_game.erl
index e3c39b4ec9..8bb5fe4d38 100644
--- a/lib/wx/examples/sudoku/sudoku_game.erl
+++ b/lib/wx/examples/sudoku/sudoku_game.erl
@@ -151,8 +151,7 @@ test() -> %% Known to solvable
{{9,2},4}, {{9,4},5}, {{9,6},8}, {{9,8},7}].
new_game(S) ->
- {X,Y,Z} = erlang:now(),
- random:seed(Y,X,Z),
+ rand:seed(exsplus),
case new_game(1,1,gb_sets:empty(),empty_table(S#s{}),[], 0) of
stop -> new_game(S);
Game -> Game
@@ -171,7 +170,7 @@ new_game(R,C,BT,St,Acc,Cnt) when R < 10, C < 10 ->
[{{BR,BC},BVal,BBT,BST}|BAcc] = Acc,
new_game(BR,BC,gb_sets:add(BVal,BBT),BST,BAcc,Cnt+1);
Size ->
- Ind = random:uniform(Size),
+ Ind = rand:uniform(Size),
V = lists:nth(Ind,gb_sets:to_list(S)),
new_game(R,C+1,gb_sets:empty(),
add({R,C,M},V,St),
@@ -207,7 +206,7 @@ pick_shown(Given,Left,S0,Level,Gfx) ->
io:format("Below level ~p ~p~n", [GivenSz,Level]),
S0;
true ->
- Ran = random:uniform(LeftSz),
+ Ran = rand:uniform(LeftSz),
V = lists:nth(Ran,gb_sets:to_list(Left)),
S1 = rebuild_all(rcm(V),S0#s{v=setelement(V,S0#s.v,0)}),
case solve(S1, true) of
diff --git a/lib/xmerl/test/Makefile b/lib/xmerl/test/Makefile
index f9c03336c8..14e11d5fc4 100644
--- a/lib/xmerl/test/Makefile
+++ b/lib/xmerl/test/Makefile
@@ -84,7 +84,7 @@ RELSYSDIR = $(RELEASE_PATH)/xmerl_test
# FLAGS
# ----------------------------------------------------
-#ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include -I$(ERL_TOP)/lib/xmerl/include/ $(XMERL_PRESERV_TEST_DIRS)
+ERL_COMPILE_FLAGS +=
# ----------------------------------------------------
diff --git a/lib/xmerl/test/xmerl_SUITE.erl b/lib/xmerl/test/xmerl_SUITE.erl
index 7ddf1066de..672f8a43d1 100644
--- a/lib/xmerl/test/xmerl_SUITE.erl
+++ b/lib/xmerl/test/xmerl_SUITE.erl
@@ -27,7 +27,7 @@
%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%%-include("xmerl.hrl").
-include_lib("xmerl/include/xmerl.hrl").
-include_lib("kernel/include/file.hrl").
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl
index afd39b6598..2e026d7476 100644
--- a/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl
@@ -10,7 +10,7 @@
-export([test/0, check_node_set/2, ticket_6873/0, ticket_7496/0, functions/0]).
-export([namespaces/0]).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("xmerl/include/xmerl.hrl").
test() ->
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_lib.erl b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_lib.erl
index 4cde46826e..f5c65b0c63 100644
--- a/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_lib.erl
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_lib.erl
@@ -9,7 +9,7 @@
-export([test/0,check_node_set/2,ticket_6873/0]).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("xmerl/include/xmerl.hrl").
test() ->
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_text.erl b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_text.erl
index e39ad6bcb0..c3a1fb9c4d 100644
--- a/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_text.erl
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_text.erl
@@ -9,7 +9,7 @@
-compile(export_all).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("xmerl/include/xmerl.hrl").
-import(xmerl_xs,
diff --git a/lib/xmerl/test/xmerl_sax_SUITE.erl b/lib/xmerl/test/xmerl_sax_SUITE.erl
index a15d9bd57c..f0e80f81d3 100644
--- a/lib/xmerl/test/xmerl_sax_SUITE.erl
+++ b/lib/xmerl/test/xmerl_sax_SUITE.erl
@@ -27,7 +27,7 @@
%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
%%======================================================================
diff --git a/lib/xmerl/test/xmerl_sax_std_SUITE.erl b/lib/xmerl/test/xmerl_sax_std_SUITE.erl
index 70e768ff04..b820bd5bc2 100644
--- a/lib/xmerl/test/xmerl_sax_std_SUITE.erl
+++ b/lib/xmerl/test/xmerl_sax_std_SUITE.erl
@@ -27,7 +27,7 @@
%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
%%======================================================================
diff --git a/lib/xmerl/test/xmerl_std_SUITE.erl b/lib/xmerl/test/xmerl_std_SUITE.erl
index 0ef44bb04e..d3e28353e2 100644
--- a/lib/xmerl/test/xmerl_std_SUITE.erl
+++ b/lib/xmerl/test/xmerl_std_SUITE.erl
@@ -25,7 +25,7 @@
%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%%-include("xmerl.hrl").
-include_lib("xmerl/include/xmerl.hrl").
diff --git a/lib/xmerl/test/xmerl_test_lib.erl b/lib/xmerl/test/xmerl_test_lib.erl
index 62689353f2..aa8a86138a 100644
--- a/lib/xmerl/test/xmerl_test_lib.erl
+++ b/lib/xmerl/test/xmerl_test_lib.erl
@@ -28,7 +28,7 @@
-compile(export_all).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("xmerl/include/xmerl.hrl").
%% cmp_element/2
diff --git a/lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE.erl b/lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE.erl
index ee648dc455..7393a878e2 100644
--- a/lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE.erl
+++ b/lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE.erl
@@ -27,7 +27,7 @@
-compile(export_all).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("xmerl/include/xmerl.hrl").
-include_lib("xmerl/include/xmerl_xsd.hrl").
diff --git a/lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE.erl b/lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE.erl
index 634e47ba7b..6a645b255e 100644
--- a/lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE.erl
+++ b/lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE.erl
@@ -27,7 +27,7 @@
-compile(export_all).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("xmerl/include/xmerl.hrl").
-include_lib("xmerl/include/xmerl_xsd.hrl").
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE.erl b/lib/xmerl/test/xmerl_xsd_SUITE.erl
index 92c8287782..e1ce8525c7 100644
--- a/lib/xmerl/test/xmerl_xsd_SUITE.erl
+++ b/lib/xmerl/test/xmerl_xsd_SUITE.erl
@@ -25,7 +25,7 @@
-compile(export_all).
%%-export([Function/Arity, ...]).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
%%-include("xmerl.hrl").
-include_lib("xmerl/include/xmerl.hrl").
diff --git a/lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE.erl b/lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE.erl
index 5ad6bb94fb..5057e70956 100644
--- a/lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE.erl
+++ b/lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE.erl
@@ -27,7 +27,7 @@
-compile(export_all).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("xmerl/include/xmerl.hrl").
-include_lib("xmerl/include/xmerl_xsd.hrl").
diff --git a/lib/xmerl/test/xmerl_xsd_lib.erl b/lib/xmerl/test/xmerl_xsd_lib.erl
index 892706609f..58fb6a27cc 100644
--- a/lib/xmerl/test/xmerl_xsd_lib.erl
+++ b/lib/xmerl/test/xmerl_xsd_lib.erl
@@ -32,7 +32,7 @@
-compile(export_all).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("xmerl.hrl").
-include("xmerl_xsd.hrl").
-include_lib("kernel/include/file.hrl").
diff --git a/make/ose_lm.mk.in b/make/ose_lm.mk.in
deleted file mode 100644
index de8d351af3..0000000000
--- a/make/ose_lm.mk.in
+++ /dev/null
@@ -1,76 +0,0 @@
-#-*-makefile-*- ; force emacs to enter makefile-mode
-# ----------------------------------------------------
-# Template target for generating an OSE5 load module
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2013. 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%
-#
-# Author: Petre Pircalabu
-# ----------------------------------------------------
-
-# ----------------------------------------------------
-# build-ose-load-module
-# Creates an OSE5 load module
-# params:
-# $(1) - The output target
-# $(2) - Objects
-# $(3) - Libraries
-# $(4) - LM configuration file
-# ----------------------------------------------------
-
-ifeq ($(findstring ose,$(TARGET)),ose)
-LDR1FLAGS = @erl_xcomp_ose_ldflags_pass1@
-LDR2FLAGS = @erl_xcomp_ose_ldflags_pass2@
-OSEROOT = @erl_xcomp_ose_OSEROOT@
-LCF = @erl_xcomp_ose_LM_LCF@
-BEAM_LMCONF = @erl_xcomp_ose_BEAM_LM_CONF@
-EPMD_LMCONF = @erl_xcomp_ose_EPMD_LM_CONF@
-RUN_ERL_LMCONF = @erl_xcomp_ose_RUN_ERL_LM_CONF@
-STRIP = @erl_xcomp_ose_STRIP@
-LM_POST_LINK = @erl_xcomp_ose_LM_POST_LINK@
-LM_SET_CONF = @erl_xcomp_ose_LM_SET_CONF@
-LM_ELF_SIZE = @erl_xcomp_ose_LM_ELF_SIZE@
-OSE_CONFD = @erl_xcomp_ose_CONFD@
-CRT0_LM = @erl_xcomp_ose_CRT0_LM@
-endif
-
-define build-ose-load-module
- @echo " --- Linking $(1)"
-
- @echo " --- Linking $(1) (pass 1)"
- $(ld_verbose)$(PURIFY) $(LD) -o $(1)_unconfigured_ro -r \
- $(2) --start-group $(3) --end-group --cref --discard-none -M > $(1)_1.map
-
- @echo " --- Linking $(1) (pass 2)"
- $(ld_verbose)$(PURIFY) $(LD) -o $(1)_unconfigured \
- $(1)_unconfigured_ro -T $(LCF) -n --emit-relocs -e crt0_lm --cref \
- --discard-none -M > $(1)_2.map
-
- @echo " --- Inserting configuration"
- $(ld_verbose) $(LM_SET_CONF) $(1)_unconfigured < $(4)
-
- @echo " --- Striping $(1)"
-# $(ld_verbose) $(STRIP) $(1)_unconfigured
-
- @echo " --- Postlinking $(1)"
- $(ld_verbose) $(LM_POST_LINK) $(1)_unconfigured
-
- @echo " --- Sizing $(1)"
- $(ld_verbose) $(LM_ELF_SIZE) $(1)_unconfigured
- mv $(1)_unconfigured $(1)
-endef
diff --git a/make/otp.mk.in b/make/otp.mk.in
index 723f83cb45..c05c499d66 100644
--- a/make/otp.mk.in
+++ b/make/otp.mk.in
@@ -90,14 +90,10 @@ OTP_RELEASE = @OTP_RELEASE@
# Erlang language section
# ----------------------------------------------------
EMULATOR = beam
-ifeq ($(findstring ose_ppc750,$(TARGET)),ose_ppc750)
-ERL_COMPILE_FLAGS += +compressed
+ifdef BOOTSTRAP
+ ERL_COMPILE_FLAGS += +slim
else
- ifdef BOOTSTRAP
- ERL_COMPILE_FLAGS += +slim
- else
- ERL_COMPILE_FLAGS += +debug_info
- endif
+ ERL_COMPILE_FLAGS += +debug_info
endif
ERLC_WFLAGS = -W
ERLC = erlc $(ERLC_WFLAGS) $(ERLC_FLAGS)
diff --git a/otp_build b/otp_build
index ac99ced42a..57dc2e3a9c 100755
--- a/otp_build
+++ b/otp_build
@@ -26,7 +26,7 @@ EXPECTED_AUTOCONF_VERSION=2.59
#
# NOTE: lazy_configure depends on '.' always being last directory
if [ -z "$ONLY_ERTS" ]; then
- AUTOCONF_SUBDIRS="lib lib/* lib/test_server/src"
+ AUTOCONF_SUBDIRS="lib lib/* lib/common_test/test_server"
fi
AUTOCONF_SUBDIRS="$AUTOCONF_SUBDIRS erts ."
@@ -264,7 +264,7 @@ create_lib_configure_in()
distribute_config_helpers ()
{
aclocal_dirs=". ./lib/erl_interface ./lib/odbc ./lib/wx ./lib/megaco"
- autoconf_aux_dirs="./lib/common_test/priv/auxdir ./lib/erl_interface/src/auxdir ./lib/test_server/src ./lib/wx/autoconf"
+ autoconf_aux_dirs="./lib/common_test/priv/auxdir ./lib/erl_interface/src/auxdir ./lib/common_test/test_server ./lib/wx/autoconf"
aclocal_master="./erts/aclocal.m4"
install_sh_master="./erts/autoconf/install-sh"
diff --git a/system/doc/reference_manual/expressions.xml b/system/doc/reference_manual/expressions.xml
index 893398b71b..75486488e9 100644
--- a/system/doc/reference_manual/expressions.xml
+++ b/system/doc/reference_manual/expressions.xml
@@ -245,13 +245,13 @@ lists:keysearch(Name, 1, List)</code>
handle(Msg, State)
spawn(m, init, [])</code>
<p><em>Examples</em> where <c>ExprF</c> is a fun:</p>
- <code type="none">
-Fun1 = fun(X) -> X+1 end
-Fun1(3)
-=> 4
-
-fun lists:append/2([1,2], [3,4])
-=> [1,2,3,4]</code>
+ <pre>
+1> <input>Fun1 = fun(X) -> X+1 end,</input>
+<input>Fun1(3).</input>
+4
+2> <input>fun lists:append/2([1,2], [3,4]).</input>
+[1,2,3,4]
+3> </pre>
<p>Notice that when calling a local function, there is a difference
between using the implicitly or fully qualified function name.
@@ -1004,7 +1004,7 @@ M4 = M3#{a := 2, b := 3}. % 'a' and 'b' was added in `M1` and `M2`.</code>
</p>
<list>
<item><p>A <c>badmatch</c> exception.</p>
- <p>This is if it is used in the context of the matching operator
+ <p>This is if it is used in the context of the match operator
as in the example.</p>
</item>
<item><p>Or resulting in the next clause being tested in function heads and
@@ -1085,7 +1085,7 @@ Ei = Value |
<p>Used in a bit string construction, <c>Value</c> is an expression
that is to evaluate to an integer, float, or bit string. If the
expression is not a single literal or variable, it
- is to be enclosed in parenthesis.</p>
+ is to be enclosed in parentheses.</p>
<p>Used in a bit string matching, <c>Value</c> must be a variable,
or an integer, float, or string.</p>
@@ -1319,7 +1319,7 @@ catch Expr</code>
{'EXIT',{badarith,[...]}}</pre>
<p>Notice that <c>catch</c> has low precedence and catch
subexpressions often needs to be enclosed in a block
- expression or in parenthesis:</p>
+ expression or in parentheses:</p>
<pre>
3> <input>A = catch 1+2.</input>
** 1: syntax error before: 'catch' **
@@ -1556,9 +1556,11 @@ end</pre>
<p>Bit string comprehensions are written with
the following syntax:</p>
<pre>
-&lt;&lt; BitString || Qualifier1,...,QualifierN &gt;&gt;</pre>
- <p>Here, <c>BitString</c> is a bit string expression and each
- <c>Qualifier</c> is either a generator, a bit string generator or a filter.</p>
+&lt;&lt; BitStringExpr || Qualifier1,...,QualifierN &gt;&gt;</pre>
+ <p><c>BitStringExpr</c> is an expression that evalutes to a bit
+ string. If <c>BitStringExpr</c> is a function call, it must be
+ enclosed in parentheses. Each <c>Qualifier</c> is either a
+ generator, a bit string generator or a filter.</p>
<list type="bulleted">
<item>A <em>generator</em> is written as: <br></br>
&nbsp;&nbsp;<c><![CDATA[Pattern <- ListExpr]]></c>. <br></br>
diff --git a/system/doc/reference_manual/macros.xml b/system/doc/reference_manual/macros.xml
index 3b1f72e5d6..42ea639b54 100644
--- a/system/doc/reference_manual/macros.xml
+++ b/system/doc/reference_manual/macros.xml
@@ -146,6 +146,10 @@ bar(X) ->
<item>The current line number.</item>
<tag><c>?MACHINE</c>.</tag>
<item>The machine name, <c>'BEAM'</c>.</item>
+ <tag><c>?FUNCTION_NAME</c></tag>
+ <item>The name of the current function.</item>
+ <tag><c>?FUNCTION_ARITY</c></tag>
+ <item>The arity (number of arguments) for the current function.</item>
</taglist>
</section>
diff --git a/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml
index 22627058c1..c5d24a96b5 100644
--- a/system/doc/reference_manual/typespec.xml
+++ b/system/doc/reference_manual/typespec.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2015</year>
+ <year>2003</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -69,7 +69,7 @@
<p>
For integers and atoms, it is allowed for singleton types; for example,
the integers
- <c>-1</c> and <c>42</c>, or the atoms <c>'foo'</c> and <c>'bar'</c>).
+ <c>-1</c> and <c>42</c>, or the atoms <c>'foo'</c> and <c>'bar'</c>.
All other types are built using unions of either predefined
types or singleton types. In a type union between a type and one
@@ -148,9 +148,9 @@
Union :: Type1 | Type2
]]></pre>
<p>
- The general form of bitstrings is <c>&lt;&lt;_:M, _:_*N&gt;&gt;</c>,
+ The general form of bit strings is <c>&lt;&lt;_:M, _:_*N&gt;&gt;</c>,
where <c>M</c> and <c>N</c> are positive integers. It denotes a
- bitstring that is <c>M + (k*N)</c> bits long (that is, a bitstring that
+ bit string that is <c>M + (k*N)</c> bits long (that is, a bit string that
starts with <c>M</c> bits and continues with <c>k</c> segments of
<c>N</c> bits each, where <c>k</c> is also a positive integer).
The notations <c>&lt;&lt;_:_*N&gt;&gt;</c>, <c>&lt;&lt;_:M&gt;&gt;</c>,
@@ -495,7 +495,8 @@
</p>
<pre> -spec id(X) -> X when X :: tuple().</pre>
<p>
- Currently, the <c>::</c> constraint (read as <c>is_subtype</c>) is
+ Currently, the <c>::</c> constraint
+ (read as &laquo;is a subtype of&raquo;) is
the only guard constraint that can be used in the <c>'when'</c>
part of a <c>'-spec'</c> attribute.
</p>
@@ -513,7 +514,7 @@
<em>the same</em> tuple.
</p>
<p>
- However, it is up to the tools that process the specificationss
+ However, it is up to the tools that process the specifications
to choose whether to take this extra information into account
or not.
</p>
@@ -529,16 +530,6 @@
<pre>
-spec foo({X, integer()}) -> X when X :: atom()
; ([Y]) -> Y when Y :: number().</pre>
- <note>
- <p>
- For backwards compatibility the following form is also allowed:
- </p>
- <pre> -spec id(X) -> X when is_subtype(X, tuple()).</pre>
- <p>
- but its use is discouraged. It will be removed in a future
- Erlang/OTP release.
- </p>
- </note>
<p>
Some functions in Erlang are not meant to return;
either because they define servers or because they are used to
diff --git a/xcomp/erl-xcomp-powerpc-ose5.conf b/xcomp/erl-xcomp-powerpc-ose5.conf
deleted file mode 100644
index 88b2135593..0000000000
--- a/xcomp/erl-xcomp-powerpc-ose5.conf
+++ /dev/null
@@ -1,358 +0,0 @@
-## -*-shell-script-*-
-##
-## %CopyrightBegin%
-##
-## Copyright Ericsson AB 2009-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%
-##
-## File: erl-xcomp-sfk-linux-ose5.conf
-## Author: Petre Pircalabu
-##
-## -----------------------------------------------------------------------------
-## When cross compiling Erlang/OTP using `otp_build', copy this file and set
-## the variables needed below. Then pass the path to the copy of this file as
-## an argument to `otp_build' in the configure stage:
-## `otp_build configure --xcomp-conf=<FILE>'
-## -----------------------------------------------------------------------------
-
-## Note that you cannot define arbitrary variables in a cross compilation
-## configuration file. Only the ones listed below will be guaranteed to be
-## visible throughout the whole execution of all `configure' scripts. Other
-## variables needs to be defined as arguments to `configure' or exported in
-## the environment.
-
-## -- Variables needed for an OSE5 build ---------------------------------------
-OSEROOT="/vobs/ose5/system"
-HOST="linux"
-
-GCCVERSION="4.4.3"
-GCCROOT="${OSEROOT}/gcc_linux_powerpc_${GCCVERSION}"
-
-OSEDEBUG="no"
-OSESSL="no"
-
-case ${GCCVERSION} in
-4.4.3)
- GCCTARGET="powerpc-eabi"
- ;;
-4.6.3)
- GCCTARGET="powerpc-ose-eabi"
- ;;
-*)
- echo "Error: Unknown GCCVERSION: ${GCCVERSION}"
- exit 1
-esac
-
-if [ ${OSEDEBUG} != "yes" ];
-then
-OPT_LEVEL="-O2"
-else
-OPT_LEVEL=""
-fi
-
-if [ ${OSESSL} = "yes" ];
-then
-## If your crypto is not in OSEROOT then you have to use --with-ssl to
-## point to the correct place. Also CRYPTO_LIB_PATH has to be modified to
-## point there as well.
-CRYPTO_CONFIG_OPTION="--disable-dynamic-ssl-lib"
-CRYPTO_NIF_PATH=",$ERL_TOP/lib/crypto/priv/lib/powerpc-unknown-ose/crypto.a"
-CRYPTO_LIB_PATH="${OSEROOT}/lib/powerpc/libsslcrypto.a"
-else
-CRYPTO_CONFIG_OPTION="--without-ssl"
-CRYPTO_NIF_PATH=""
-CRYPTO_LIB_PATH=""
-fi
-
-
-## -- Variables for `otp_build' Only -------------------------------------------
-
-## Variables in this section are only used, when configuring Erlang/OTP for
-## cross compilation using `$ERL_TOP/otp_build configure'.
-
-## *NOTE*! These variables currently have *no* effect if you configure using
-## the `configure' script directly.
-
-# * `erl_xcomp_build' - The build system used. This value will be passed as
-# `--build=$erl_xcomp_build' argument to the `configure' script. It does
-# not have to be a full `CPU-VENDOR-OS' triplet, but can be. The full
-# `CPU-VENDOR-OS' triplet will be created by
-# `$ERL_TOP/erts/autoconf/config.sub $erl_xcomp_build'. If set to `guess',
-# the build system will be guessed using
-# `$ERL_TOP/erts/autoconf/config.guess'.
-erl_xcomp_build=guess
-
-# * `erl_xcomp_host' - Cross host/target system to build for. This value will
-# be passed as `--host=$erl_xcomp_host' argument to the `configure' script.
-# It does not have to be a full `CPU-VENDOR-OS' triplet, but can be. The
-# full `CPU-VENDOR-OS' triplet will be created by
-# `$ERL_TOP/erts/autoconf/config.sub $erl_xcomp_host'.
-erl_xcomp_host="powerpc-ose"
-
-disabled_apps="--without-erl_interface --without-os_mon --without-megaco --without-observer --without-wx --without-appmon --without-cosEvent --without-cosEventDomain --without-cosFileTransfer --without-cosNotification --without-cosProperty --without-cosTime --without-cosTransactions --without-debugger --without-dialyzer --without-edoc --without-erl_docgen --without-eunit --without-gs --without-hipe --without-ic --without-orber --without-pman --without-toolbar --without-tv --without-webtool --without-typer"
-
-# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
-# `configure' script.
-erl_xcomp_configure_flags="${CRYPTO_CONFIG_OPTION} --disable-kernel-poll --disable-hipe --without-termcap --without-javac ${disabled_apps} --enable-static-nifs=$ERL_TOP/lib/asn1/priv/lib/powerpc-unknown-ose/asn1rt_nif.a${CRYPTO_NIF_PATH}"
-
-## -- Cross Compiler and Other Tools -------------------------------------------
-
-## If the cross compilation tools are prefixed by `<HOST>-' you probably do
-## not need to set these variables (where `<HOST>' is what has been passed as
-## `--host=<HOST>' argument to `configure').
-
-## All variables in this section can also be used when native compiling.
-
-# * `CC' - C compiler.
-CC="$GCCROOT/bin/$GCCTARGET-gcc"
-
-# * `CFLAGS' - C compiler flags.
-CFLAGS="-msoft-float -g -fno-strict-aliasing -fno-builtin -fshort-wchar -Wall -Wno-unknown-pragmas -mpowerpc -nostdlib -I$GCCROOT/include/c++/$GCCVERSION -I$OSEROOT/include -I$OSEROOT/include/ose_spi -I$OSEROOT/include/gcc -MD -MP -D__OSE__ -DBIG_ENDIAN -DCF_CONF_SIZE=0x800 ${OPT_LEVEL}"
-
-
-# * `STATIC_CFLAGS' - Static C compiler flags.
-#STATIC_CFLAGS=
-
-# * `CFLAG_RUNTIME_LIBRARY_PATH' - This flag should set runtime library
-# search path for the shared libraries. Note that this actually is a
-# linker flag, but it needs to be passed via the compiler.
-#CFLAG_RUNTIME_LIBRARY_PATH=
-
-# * `CPP' - C pre-processor.
-CPP="$GCCROOT/bin/$GCCTARGET-cpp"
-
-# * `CPPFLAGS' - C pre-processor flags.
-CPPFLAGS="-msoft-float -g -fno-strict-aliasing -fno-builtin -fshort-wchar -Wall -Wno-unknown-pragmas -mpowerpc -nostdlib -I$GCCROOT/include/c++/$GCCVERSION -I$OSEROOT/include -I$OSEROOT/include/ose_spi -I$OSEROOT/include/gcc -MD -MP -D__OSE__ -DBIG_ENDIAN -DCF_CONF_SIZE=0x800 ${OPT_LEVEL}"
-
-
-# * `CXX' - C++ compiler.
-CXX="$GCCROOT/bin/$GCCTARGET-g++"
-
-# * `CXXFLAGS' - C++ compiler flags.
-CXXFLAGS="-msoft-float -g -fno-strict-aliasing -ansi -I$GCCROOT/include/c++/$GCCVERSION -I$OSEROOT/include -I$OSEROOT/include/gcc ${OPT_LEVEL}"
-
-# * `LD' - Linker.
-LD="${GCCROOT}/bin/${GCCTARGET}-ld"
-
-# * `LDFLAGS' - Linker flags.
-LDFLAGS="-Wl,-ecrt0_lm -Wl,-T,${ERL_TOP}/erts/emulator/sys/ose/gcc_${GCCVERSION}_lm_ppc.lcf"
-
-# * `LIBS' - Libraries.
-LIBS="${OSEROOT}/lib/powerpc/libcrt.a ${OSEROOT}/lib/powerpc/libm.a ${GCCROOT}/lib/gcc/${GCCTARGET}/${GCCVERSION}/nof/libgcc.a ${CRYPTO_LIB_PATH}"
-
-## -- *D*ynamic *E*rlang *D*river Linking --
-
-## *NOTE*! Either set all or none of the `DED_LD*' variables.
-
-# * `DED_LD' - Linker for Dynamically loaded Erlang Drivers.
-DED_LD=
-
-# * `DED_LDFLAGS' - Linker flags to use with `DED_LD'.
-DED_LDFLAGS=
-
-# * `DED_LD_FLAG_RUNTIME_LIBRARY_PATH' - This flag should set runtime library
-# search path for shared libraries when linking with `DED_LD'.
-DED_LD_FLAG_RUNTIME_LIBRARY_PATH=
-
-## -- Large File Support --
-
-## *NOTE*! Either set all or none of the `LFS_*' variables.
-
-# * `LFS_CFLAGS' - Large file support C compiler flags.
-#LFS_CFLAGS=
-
-# * `LFS_LDFLAGS' - Large file support linker flags.
-#LFS_LDFLAGS=
-
-# * `LFS_LIBS' - Large file support libraries.
-#LFS_LIBS=
-
-## -- Other Tools --
-
-# * `RANLIB' - `ranlib' archive index tool.
-RANLIB="$GCCROOT/bin/$GCCTARGET-ranlib"
-
-# * `AR' - `ar' archiving tool.
-AR="$GCCROOT/bin/$GCCTARGET-ar"
-
-# * `STRIP' - `strip
-STRIP="$GCCROOT/bin/$GCCTARGET-strip"
-
-# * `GETCONF' - `getconf' system configuration inspection tool. `getconf' is
-# currently used for finding out large file support flags to use, and
-# on Linux systems for finding out if we have an NPTL thread library or
-# not.
-#GETCONF=
-
-## -- Cross System Root Locations ----------------------------------------------
-
-# * `erl_xcomp_sysroot' - The absolute path to the system root of the cross
-# compilation environment. Currently, the `crypto', `odbc', `ssh' and
-# `ssl' applications need the system root. These applications will be
-# skipped if the system root has not been set. The system root might be
-# needed for other things too. If this is the case and the system root
-# has not been set, `configure' will fail and request you to set it.
-erl_xcomp_sysroot="$OSEROOT"
-
-# * `erl_xcomp_isysroot' - The absolute path to the system root for includes
-# of the cross compilation environment. If not set, this value defaults
-# to `$erl_xcomp_sysroot', i.e., only set this value if the include system
-# root path is not the same as the system root path.
-#erl_xcomp_isysroot="$OSEROOT"
-
-## -- Optional Feature, and Bug Tests ------------------------------------------
-
-## These tests cannot (always) be done automatically when cross compiling. You
-## usually do not need to set these variables. Only set these if you really
-## know what you are doing.
-
-## Note that some of these values will override results of tests performed
-## by `configure', and some will not be used until `configure' is sure that
-## it cannot figure the result out.
-
-## The `configure' script will issue a warning when a default value is used.
-## When a variable has been set, no warning will be issued.
-
-# * `erl_xcomp_after_morecore_hook' - `yes|no'. Defaults to `no'. If `yes',
-# the target system must have a working `__after_morecore_hook' that can be
-# used for tracking used `malloc()' implementations core memory usage.
-# This is currently only used by unsupported features.
-#erl_xcomp_after_morecore_hook=
-
-# * `erl_xcomp_bigendian' - `yes|no'. No default. If `yes', the target system
-# must be big endian. If `no', little endian. This can often be
-# automatically detected, but not always. If not automatically detected,
-# `configure' will fail unless this variable is set. Since no default
-# value is used, `configure' will try to figure this out automatically.
-#erl_xcomp_bigendian=
-
-# * `erl_xcomp_double_middle` - `yes|no`. No default. If `yes`, the
-# target system must have doubles in "middle-endian" format. If
-# `no`, it has "regular" endianness. This can often be automatically
-# detected, but not always. If not automatically detected,
-# `configure` will fail unless this variable is set. Since no
-# default value is used, `configure` will try to figure this out
-# automatically.
-#erl_xcomp_double_middle_endian
-
-# * `erl_xcomp_clock_gettime_cpu_time' - `yes|no'. Defaults to `no'. If `yes',
-# the target system must have a working `clock_gettime()' implementation
-# that can be used for retrieving process CPU time.
-#erl_xcomp_clock_gettime_cpu_time=
-
-# * `erl_xcomp_getaddrinfo' - `yes|no'. Defaults to `no'. If `yes', the target
-# system must have a working `getaddrinfo()' implementation that can
-# handle both IPv4 and IPv6.
-#erl_xcomp_getaddrinfo=
-
-# * `erl_xcomp_gethrvtime_procfs_ioctl' - `yes|no'. Defaults to `no'. If `yes',
-# the target system must have a working `gethrvtime()' implementation and
-# is used with procfs `ioctl()'.
-#erl_xcomp_gethrvtime_procfs_ioctl=
-
-# * `erl_xcomp_dlsym_brk_wrappers' - `yes|no'. Defaults to `no'. If `yes', the
-# target system must have a working `dlsym(RTLD_NEXT, <S>)' implementation
-# that can be used on `brk' and `sbrk' symbols used by the `malloc()'
-# implementation in use, and by this track the `malloc()' implementations
-# core memory usage. This is currently only used by unsupported features.
-#erl_xcomp_dlsym_brk_wrappers=
-
-# * `erl_xcomp_kqueue' - `yes|no'. Defaults to `no'. If `yes', the target
-# system must have a working `kqueue()' implementation that returns a file
-# descriptor which can be used by `poll()' and/or `select()'. If `no' and
-# the target system has not got `epoll()' or `/dev/poll', the kernel-poll
-# feature will be disabled.
-#erl_xcomp_kqueue=
-
-# * `erl_xcomp_linux_clock_gettime_correction' - `yes|no'. Defaults to `yes' on
-# Linux; otherwise, `no'. If `yes', `clock_gettime(CLOCK_MONOTONIC, _)' on
-# the target system must work. This variable is recommended to be set to
-# `no' on Linux systems with kernel versions less than 2.6.
-#erl_xcomp_linux_clock_gettime_correction=
-
-# * `erl_xcomp_linux_nptl' - `yes|no'. Defaults to `yes' on Linux; otherwise,
-# `no'. If `yes', the target system must have NPTL (Native POSIX Thread
-# Library). Older Linux systems have LinuxThreads instead of NPTL (Linux
-# kernel versions typically less than 2.6).
-#erl_xcomp_linux_nptl=
-
-# * `erl_xcomp_linux_usable_sigaltstack' - `yes|no'. Defaults to `yes' on Linux;
-# otherwise, `no'. If `yes', `sigaltstack()' must be usable on the target
-# system. `sigaltstack()' on Linux kernel versions less than 2.4 are
-# broken.
-#erl_xcomp_linux_usable_sigaltstack=
-
-# * `erl_xcomp_linux_usable_sigusrx' - `yes|no'. Defaults to `yes'. If `yes',
-# the `SIGUSR1' and `SIGUSR2' signals must be usable by the ERTS. Old
-# LinuxThreads thread libraries (Linux kernel versions typically less than
-# 2.2) used these signals and made them unusable by the ERTS.
-#erl_xcomp_linux_usable_sigusrx=
-
-# * `erl_xcomp_poll' - `yes|no'. Defaults to `no' on Darwin/MacOSX; otherwise,
-# `yes'. If `yes', the target system must have a working `poll()'
-# implementation that also can handle devices. If `no', `select()' will be
-# used instead of `poll()'.
-erl_xcomp_poll=no
-
-# * `erl_xcomp_putenv_copy' - `yes|no'. Defaults to `no'. If `yes', the target
-# system must have a `putenv()' implementation that stores a copy of the
-# key/value pair.
-#erl_xcomp_putenv_copy=
-
-# * `erl_xcomp_reliable_fpe' - `yes|no'. Defaults to `no'. If `yes', the target
-# system must have reliable floating point exceptions.
-#erl_xcomp_reliable_fpe=
-# * `erl_xcomp_ose_ldflags_pass1` - Linker flags for the OSE module (pass 1)
-erl_xcomp_ose_ldflags_pass1="-r --no-omagic"
-
-# * `erl_xcomp_ose_ldflags_pass2` - Linker flags for the OSE module (pass 2)
-erl_xcomp_ose_ldflags_pass2="-n --emit-relocs -ecrt0_lm --no-omagic"
-
-# * `erl_xcomp_ose_OSEROOT` - OSE installation root directory
-erl_xcomp_ose_OSEROOT="${OSEROOT}"
-
-# * `erl_xcomp_ose_STRIP` - Strip utility shipped with the OSE distribution
-erl_xcomp_ose_STRIP="${GCCROOT}/bin/${GCCTARGET}-strip"
-
-# * `erl_xcomp_ose_LM_POST_LINK` - OSE postlink tool
-erl_xcomp_ose_LM_POST_LINK="${OSEROOT}/bin/${HOST}/lm_post_link"
-
-# * `erl_xcomp_ose_LM_SET_CONF` - Sets the configuration for an OSE load module
-erl_xcomp_ose_LM_SET_CONF="${OSEROOT}/bin/${HOST}/lm_set_conf"
-
-# * `erl_xcomp_ose_LM_ELF_SIZE` - OSE load module elf size tool
-erl_xcomp_ose_LM_ELF_SIZE="${OSEROOT}/bin/${HOST}/lm_elf_size"
-
-# * `erl_xcomp_ose_LM_LCF` - OSE load module linker configuration file
-erl_xcomp_ose_LM_LCF="${ERL_TOP}/erts/emulator/sys/ose/gcc_${GCCVERSION}_lm_ppc.lcf"
-
-# * `erl_xcomp_ose_BEAM_LM_CONF` - beam OSE load module configuration file
-erl_xcomp_ose_BEAM_LM_CONF="${ERL_TOP}/erts/emulator/sys/ose/beam.lmconf"
-
-# * `erl_xcomp_ose_RUN_ERL_LM_CONF` - run_erl_lm OSE load module configuration file
-erl_xcomp_ose_RUN_ERL_LM_CONF="${ERL_TOP}/erts/etc/ose/etc.lmconf"
-
-# * `erl_xcomp_ose_EPMD_LM_CONF` - epmd OSE load module configuration file
-erl_xcomp_ose_EPMD_LM_CONF="${ERL_TOP}/erts/etc/ose/etc.lmconf"
-
-# * `erl_xcomp_ose_CONFD` - OSE confd source file
-erl_xcomp_ose_CONFD="${OSEROOT}/src/ose_confd.c"
-
-# * `erl_xcomp_ose_CRT0_LM` - OSE crt0 lm source file
-erl_xcomp_ose_CRT0_LM="${OSEROOT}/src/crt0_lm.c"
-
-
-## -----------------------------------------------------------------------------
diff --git a/xcomp/erl-xcomp-sfk-linux-ose5.conf b/xcomp/erl-xcomp-sfk-linux-ose5.conf
deleted file mode 100644
index a4d64e5636..0000000000
--- a/xcomp/erl-xcomp-sfk-linux-ose5.conf
+++ /dev/null
@@ -1,305 +0,0 @@
-## -*-shell-script-*-
-##
-## %CopyrightBegin%
-##
-## Copyright Ericsson AB 2009-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%
-##
-## File: erl-xcomp-sfk-linux-ose5.conf
-## Author: Petre Pircalabu
-##
-## -----------------------------------------------------------------------------
-## When cross compiling Erlang/OTP using `otp_build', copy this file and set
-## the variables needed below. Then pass the path to the copy of this file as
-## an argument to `otp_build' in the configure stage:
-## `otp_build configure --xcomp-conf=<FILE>'
-## -----------------------------------------------------------------------------
-
-## Note that you cannot define arbitrary variables in a cross compilation
-## configuration file. Only the ones listed below will be guaranteed to be
-## visible throughout the whole execution of all `configure' scripts. Other
-## variables needs to be defined as arguments to `configure' or exported in
-## the environment.
-
-## -- Variables needed for an OSE5 build ---------------------------------------
-OSEROOT="/vobs/ose5/system"
-HOST="linux"
-GCCVERSION="4.6.3"
-GCCROOT="${OSEROOT}/gcc_linux_x86_${GCCVERSION}"
-GCCTARGET="i386-elf"
-
-## -- Variables for `otp_build' Only -------------------------------------------
-
-## Variables in this section are only used, when configuring Erlang/OTP for
-## cross compilation using `$ERL_TOP/otp_build configure'.
-
-## *NOTE*! These variables currently have *no* effect if you configure using
-## the `configure' script directly.
-
-# * `erl_xcomp_build' - The build system used. This value will be passed as
-# `--build=$erl_xcomp_build' argument to the `configure' script. It does
-# not have to be a full `CPU-VENDOR-OS' triplet, but can be. The full
-# `CPU-VENDOR-OS' triplet will be created by
-# `$ERL_TOP/erts/autoconf/config.sub $erl_xcomp_build'. If set to `guess',
-# the build system will be guessed using
-# `$ERL_TOP/erts/autoconf/config.guess'.
-erl_xcomp_build=guess
-
-# * `erl_xcomp_host' - Cross host/target system to build for. This value will
-# be passed as `--host=$erl_xcomp_host' argument to the `configure' script.
-# It does not have to be a full `CPU-VENDOR-OS' triplet, but can be. The
-# full `CPU-VENDOR-OS' triplet will be created by
-# `$ERL_TOP/erts/autoconf/config.sub $erl_xcomp_host'.
-erl_xcomp_host="$GCCTARGET-ose"
-
-# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
-# `configure' script.
-erl_xcomp_configure_flags="--disable-threads --disable-smp-support --disable-kernel-poll --disable-hipe --without-termcap --without-javac --disable-dynamic-ssl-lib --disable-shared-zlib --without-ssl --enable-static-nifs --enable-static-nifs=$ERL_TOP/lib/asn1/priv/lib/powerpc-unknown-ose/asn1rt_nif.a"
-
-## -- Cross Compiler and Other Tools -------------------------------------------
-
-## If the cross compilation tools are prefixed by `<HOST>-' you probably do
-## not need to set these variables (where `<HOST>' is what has been passed as
-## `--host=<HOST>' argument to `configure').
-
-## All variables in this section can also be used when native compiling.
-
-# * `CC' - C compiler.
-CC="$GCCROOT/bin/$GCCTARGET-gcc"
-
-# * `CFLAGS' - C compiler flags.
-CFLAGS="-g -fno-strict-aliasing -fno-builtin -fshort-wchar -Wall -Wno-unknown-pragmas -I$GCCROOT/include/c++/$GCCVERSION -I$OSEROOT/include -I$OSEROOT/include/ose_spi -I$OSEROOT/include/gcc -MD -MP -D__OSE__ -DLITTLE_ENDIAN -DCF_CONF_SIZE=0x800"
-
-# * `STATIC_CFLAGS' - Static C compiler flags.
-#STATIC_CFLAGS=
-
-# * `CFLAG_RUNTIME_LIBRARY_PATH' - This flag should set runtime library
-# search path for the shared libraries. Note that this actually is a
-# linker flag, but it needs to be passed via the compiler.
-#CFLAG_RUNTIME_LIBRARY_PATH=
-
-# * `CPP' - C pre-processor.
-#CPP=
-
-# * `CPPFLAGS' - C pre-processor flags.
-CPPFLAGS="-g -fno-strict-aliasing -fno-builtin -fshort-wchar -Wall -Wno-unknown-pragmas -I$GCCROOT/include/c++/$GCCVERSION -I$OSEROOT/include -I$OSEROOT/include/ose_spi -I$OSEROOT/include/gcc -MD -MP -D__OSE__ -DLITTLE_ENDIAN -DCF_CONF_SIZE=0x800"
-
-# * `CXX' - C++ compiler.
-#CXX=
-
-# * `CXXFLAGS' - C++ compiler flags.
-CXXFLAGS="-g -fno-strict-aliasing -ansi -I$GCCROOT/include/c++/$GCCVERSION -I$OSEROOT/include -I$OSEROOT/include/gcc "
-
-# * `LD' - Linker.
-LD="$GCCROOT/bin/$GCCTARGET-ld"
-
-# * `LDFLAGS' - Linker flags.
-LDFLAGS="-Wl,-ecrt0_lm -Wl,-T,$ERL_TOP/erts/emulator/sys/ose/gcc_lm_x86_$GCCVERSION.lcf"
-
-# * `LIBS' - Libraries.
-LIBS="$OSEROOT/lib/x86/libcrt.a $OSEROOT/lib/x86/libm.a $GCCROOT/lib/gcc/$GCCTARGET/$GCCVERSION/libgcc.a"
-
-## -- *D*ynamic *E*rlang *D*river Linking --
-
-## *NOTE*! Either set all or none of the `DED_LD*' variables.
-
-# * `DED_LD' - Linker for Dynamically loaded Erlang Drivers.
-#DED_LD=
-
-# * `DED_LDFLAGS' - Linker flags to use with `DED_LD'.
-#DED_LDFLAGS=
-
-# * `DED_LD_FLAG_RUNTIME_LIBRARY_PATH' - This flag should set runtime library
-# search path for shared libraries when linking with `DED_LD'.
-#DED_LD_FLAG_RUNTIME_LIBRARY_PATH=
-
-## -- Large File Support --
-
-## *NOTE*! Either set all or none of the `LFS_*' variables.
-
-# * `LFS_CFLAGS' - Large file support C compiler flags.
-#LFS_CFLAGS=
-
-# * `LFS_LDFLAGS' - Large file support linker flags.
-#LFS_LDFLAGS=
-
-# * `LFS_LIBS' - Large file support libraries.
-#LFS_LIBS=
-
-## -- Other Tools --
-
-# * `RANLIB' - `ranlib' archive index tool.
-RANLIB="$GCCROOT/bin/$GCCTARGET-ranlib"
-
-# * `AR' - `ar' archiving tool.
-AR="$GCCROOT/bin/$GCCTARGET-ar"
-
-# * `STRIP' - `strip
-STRIP="$GCCROOT/bin/$GCCTARGET-strip"
-
-# * `GETCONF' - `getconf' system configuration inspection tool. `getconf' is
-# currently used for finding out large file support flags to use, and
-# on Linux systems for finding out if we have an NPTL thread library or
-# not.
-#GETCONF=
-
-## -- Cross System Root Locations ----------------------------------------------
-
-# * `erl_xcomp_sysroot' - The absolute path to the system root of the cross
-# compilation environment. Currently, the `crypto', `odbc', `ssh' and
-# `ssl' applications need the system root. These applications will be
-# skipped if the system root has not been set. The system root might be
-# needed for other things too. If this is the case and the system root
-# has not been set, `configure' will fail and request you to set it.
-erl_xcomp_sysroot="$OSEROOT"
-
-# * `erl_xcomp_isysroot' - The absolute path to the system root for includes
-# of the cross compilation environment. If not set, this value defaults
-# to `$erl_xcomp_sysroot', i.e., only set this value if the include system
-# root path is not the same as the system root path.
-erl_xcomp_isysroot="$OSEROOT/include"
-
-## -- Optional Feature, and Bug Tests ------------------------------------------
-
-## These tests cannot (always) be done automatically when cross compiling. You
-## usually do not need to set these variables. Only set these if you really
-## know what you are doing.
-
-## Note that some of these values will override results of tests performed
-## by `configure', and some will not be used until `configure' is sure that
-## it cannot figure the result out.
-
-## The `configure' script will issue a warning when a default value is used.
-## When a variable has been set, no warning will be issued.
-
-# * `erl_xcomp_after_morecore_hook' - `yes|no'. Defaults to `no'. If `yes',
-# the target system must have a working `__after_morecore_hook' that can be
-# used for tracking used `malloc()' implementations core memory usage.
-# This is currently only used by unsupported features.
-#erl_xcomp_after_morecore_hook=
-
-# * `erl_xcomp_bigendian' - `yes|no'. No default. If `yes', the target system
-# must be big endian. If `no', little endian. This can often be
-# automatically detected, but not always. If not automatically detected,
-# `configure' will fail unless this variable is set. Since no default
-# value is used, `configure' will try to figure this out automatically.
-#erl_xcomp_bigendian=
-
-# * `erl_xcomp_double_middle` - `yes|no`. No default. If `yes`, the
-# target system must have doubles in "middle-endian" format. If
-# `no`, it has "regular" endianness. This can often be automatically
-# detected, but not always. If not automatically detected,
-# `configure` will fail unless this variable is set. Since no
-# default value is used, `configure` will try to figure this out
-# automatically.
-#erl_xcomp_double_middle_endian
-
-# * `erl_xcomp_clock_gettime_cpu_time' - `yes|no'. Defaults to `no'. If `yes',
-# the target system must have a working `clock_gettime()' implementation
-# that can be used for retrieving process CPU time.
-#erl_xcomp_clock_gettime_cpu_time=
-
-# * `erl_xcomp_getaddrinfo' - `yes|no'. Defaults to `no'. If `yes', the target
-# system must have a working `getaddrinfo()' implementation that can
-# handle both IPv4 and IPv6.
-#erl_xcomp_getaddrinfo=
-
-# * `erl_xcomp_gethrvtime_procfs_ioctl' - `yes|no'. Defaults to `no'. If `yes',
-# the target system must have a working `gethrvtime()' implementation and
-# is used with procfs `ioctl()'.
-#erl_xcomp_gethrvtime_procfs_ioctl=
-
-# * `erl_xcomp_dlsym_brk_wrappers' - `yes|no'. Defaults to `no'. If `yes', the
-# target system must have a working `dlsym(RTLD_NEXT, <S>)' implementation
-# that can be used on `brk' and `sbrk' symbols used by the `malloc()'
-# implementation in use, and by this track the `malloc()' implementations
-# core memory usage. This is currently only used by unsupported features.
-#erl_xcomp_dlsym_brk_wrappers=
-
-# * `erl_xcomp_kqueue' - `yes|no'. Defaults to `no'. If `yes', the target
-# system must have a working `kqueue()' implementation that returns a file
-# descriptor which can be used by `poll()' and/or `select()'. If `no' and
-# the target system has not got `epoll()' or `/dev/poll', the kernel-poll
-# feature will be disabled.
-#erl_xcomp_kqueue=
-
-# * `erl_xcomp_linux_clock_gettime_correction' - `yes|no'. Defaults to `yes' on
-# Linux; otherwise, `no'. If `yes', `clock_gettime(CLOCK_MONOTONIC, _)' on
-# the target system must work. This variable is recommended to be set to
-# `no' on Linux systems with kernel versions less than 2.6.
-#erl_xcomp_linux_clock_gettime_correction=
-
-# * `erl_xcomp_linux_nptl' - `yes|no'. Defaults to `yes' on Linux; otherwise,
-# `no'. If `yes', the target system must have NPTL (Native POSIX Thread
-# Library). Older Linux systems have LinuxThreads instead of NPTL (Linux
-# kernel versions typically less than 2.6).
-#erl_xcomp_linux_nptl=
-
-# * `erl_xcomp_linux_usable_sigaltstack' - `yes|no'. Defaults to `yes' on Linux;
-# otherwise, `no'. If `yes', `sigaltstack()' must be usable on the target
-# system. `sigaltstack()' on Linux kernel versions less than 2.4 are
-# broken.
-#erl_xcomp_linux_usable_sigaltstack=
-
-# * `erl_xcomp_linux_usable_sigusrx' - `yes|no'. Defaults to `yes'. If `yes',
-# the `SIGUSR1' and `SIGUSR2' signals must be usable by the ERTS. Old
-# LinuxThreads thread libraries (Linux kernel versions typically less than
-# 2.2) used these signals and made them unusable by the ERTS.
-#erl_xcomp_linux_usable_sigusrx=
-
-# * `erl_xcomp_poll' - `yes|no'. Defaults to `no' on Darwin/MacOSX; otherwise,
-# `yes'. If `yes', the target system must have a working `poll()'
-# implementation that also can handle devices. If `no', `select()' will be
-# used instead of `poll()'.
-erl_xcomp_poll=no
-
-# * `erl_xcomp_putenv_copy' - `yes|no'. Defaults to `no'. If `yes', the target
-# system must have a `putenv()' implementation that stores a copy of the
-# key/value pair.
-#erl_xcomp_putenv_copy=
-
-# * `erl_xcomp_reliable_fpe' - `yes|no'. Defaults to `no'. If `yes', the target
-# system must have reliable floating point exceptions.
-#erl_xcomp_reliable_fpe=
-
-# * `erl_xcomp_ose_ldflags_pass1` - Linker flags for the OSE module (pass 1)
-erl_xcomp_ose_ldflags_pass1="-r --no-omagic"
-
-# * `erl_xcomp_ose_ldflags_pass2` - Linker flags for the OSE module (pass 2)
-erl_xcomp_ose_ldflags_pass2="-n --emit-relocs -ecrt0_lm --no-omagic"
-
-# * `erl_xcomp_ose_OSEROOT` - OSE installation root directory
-erl_xcomp_ose_OSEROOT="$OSEROOT"
-
-# * `erl_xcomp_ose_STRIP` - Strip utility shipped with the OSE distribution
-erl_xcomp_ose_STRIP="$GCCROOT/bin/$GCCTARGET-strip"
-
-# * `erl_xcomp_ose_LM_POST_LINK` - OSE postlink tool
-erl_xcomp_ose_LM_POST_LINK="$OSEROOT/bin/$HOST/lm_post_link"
-
-# * `erl_xcomp_ose_LM_SET_CONF` - OSE load module configuration tool
-erl_xcomp_ose_LM_SET_CONF="$OSEROOT/bin/$HOST/lm_set_conf"
-
-# * `erl_xcomp_ose_LM_GET_CONF` - OSE load module elf size tool
-erl_xcomp_ose_LM_ELF_SIZE="$OSEROOT/bin/$HOST/lm_elf_size"
-
-# * `erl_xcomp_ose_LM_LCF` - OSE load module linker configuration file
-erl_xcomp_ose_LM_LCF="${ERL_TOP}/erts/emulator/sys/ose/gcc_lm_x86_$GCCVERSION.lcf"
-
-# * `erl_xcomp_ose_LM_CONF` - OSE load module default configuration file
-erl_xcomp_ose_LM_CONF="${ERL_TOP}/erts/emulator/sys/ose/default.lmconf"
-
-## -----------------------------------------------------------------------------
diff --git a/xcomp/erl-xcomp-vars.sh b/xcomp/erl-xcomp-vars.sh
index 0443867341..e864f7b96b 100644
--- a/xcomp/erl-xcomp-vars.sh
+++ b/xcomp/erl-xcomp-vars.sh
@@ -27,4 +27,4 @@
# and precious variables in $ERL_TOP/erts/aclocal.m4.
#
-erl_xcomp_vars="erl_xcomp_sysroot erl_xcomp_isysroot erl_xcomp_bigendian erl_xcomp_double_middle_endian erl_xcomp_linux_clock_gettime_correction erl_xcomp_linux_nptl erl_xcomp_linux_usable_sigusrx erl_xcomp_linux_usable_sigaltstack erl_xcomp_poll erl_xcomp_kqueue erl_xcomp_putenv_copy erl_xcomp_reliable_fpe erl_xcomp_getaddrinfo erl_xcomp_gethrvtime_procfs_ioctl erl_xcomp_clock_gettime_cpu_time erl_xcomp_after_morecore_hook erl_xcomp_dlsym_brk_wrappers erl_xcomp_posix_memalign erl_xcomp_ose_ldflags_pass1 erl_xcomp_ose_ldflags_pass2 erl_xcomp_ose_OSEROOT erl_xcomp_ose_STRIP erl_xcomp_ose_LM_POST_LINK erl_xcomp_ose_LM_SET_CONF erl_xcomp_ose_LM_GET_CONF erl_xcomp_ose_LM_ELF_SIZE erl_xcomp_ose_LM_LCF erl_xcomp_ose_BEAM_LM_CONF erl_xcomp_ose_EPMD_LM_CONF erl_xcomp_ose_RUN_ERL_LM_CONF erl_xcomp_ose_CONFD erl_xcomp_ose_CRT0_LM"
+erl_xcomp_vars="erl_xcomp_sysroot erl_xcomp_isysroot erl_xcomp_bigendian erl_xcomp_double_middle_endian erl_xcomp_linux_clock_gettime_correction erl_xcomp_linux_nptl erl_xcomp_linux_usable_sigusrx erl_xcomp_linux_usable_sigaltstack erl_xcomp_poll erl_xcomp_kqueue erl_xcomp_putenv_copy erl_xcomp_reliable_fpe erl_xcomp_getaddrinfo erl_xcomp_gethrvtime_procfs_ioctl erl_xcomp_clock_gettime_cpu_time erl_xcomp_after_morecore_hook erl_xcomp_dlsym_brk_wrappers erl_xcomp_posix_memalign"